New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Montgomery and (Edwards) Key Generation, Use, and Interoperability #2952
Comments
This is problematic from the beginning of the edwards/montgomery keys in pkcs11 3.0. When I was putting together the basic support for this in opensc for nitrokey/openpgp, i tried to get some comments from the pkcs11 committee, but as far as I remember, there was no great consensus. In the end, I ended up implementing parsing for both ways. I agree that when generating keys, we should try to go with the most standard and compatible way. On the side note, I also noticed that the pkcs11-tool prints the EC_PARAMS as an OID regardless of the content, resulting in some weird results (did not manage to write the patch yet). |
Most likely because https://github.com/OpenSC/OpenSC/blob/master/src/tools/pkcs11-tool.c#L5794 is reading In some of my tests I changed this in pkcs11-tool.c Note the
Maybe these tables need an extra field to indicate "favored" way to list or store OID or printable string in ecparams. While looking at adding Montgomery keys and all the Also have modified Not sure how far to go with all of this, as OpenPGP cards have a lot of other info stored which would not be easy to pass into pkcs11. |
Some additional comments about curves 25519, RFCs and PKCS11: RFC7748 and RFC8032 are "Request for Proposal" from: "Internet Research Task Force (IRTF)"
Where as RFC8410 is from the "Internet Engineering Task Force (IETF)" and says:
RFC8410 title: "Algorithm Identifiers for Ed25519, Ed448, X25519, and X448 for Use in the Internet X.509 Public Key Infrastructure" It is the only one that defines OIDs and provides a recommendation for curve names to be used for these OIDs how to used then in ASN.1 for public, private and certificates. These OIDs are used by OpenSSL. So basically RFC7748 or RFC8032 are obsolete and OpenSC will never add a driver that does not support RFC8410 for 25519 curves. So having support for the pkcs11 3.0 "ecparams" "PrintableString" in pkcs11-tool.c and can help pass in unknow curve or experimental names to any pkcs11 module. Currently the OpenSC pkcs11 module and libopensc appear to only support 25519 curves in card-openpgp.c. And it appears GnuPG, Yubico and GNUK defined their own OIDs and the tokens use the same algorithms as defined in RFC8410. So we should prefer to use the RFC8410 names and OIDs but for backwards compatibility support the old names and OIDs. Modified Proposed Resolution pkcs11-tool.c define the RFC8410 curves including the 448 curves and any names know to be in use with OpenPGP and map to the RFC8410 OIDs. If newer card drivers are added and the algorithms match RFC8410 we would only accept the RFC8410 OIDs |
Additional info on 25519 curves:
|
Hi @dengert, Can you elaborate on your plan to submit some of these changes in master so we build on them? At least this one: dengert@1b0d7c9#diff-fcf954433b996121efbb3028d15e969537c35c7fd4bcd8b2a31bba29c4af18f7R160 I noticed 3 typos in the Ed488 line, the first being the 488 -> 448 (name + size), and the OID should end in 70 -> 71 I did try the Ed ones with my own SoftHSM and they work correctly (I don't have the latest master OID print fix though). My plan would be to add ed25519 + ed448 object create support and then EDDSA support to pkcs11-tool.
|
Thanks for the fix, I have pushed two commits to X25519-improvements-2 that can be squashed at a later time. Most of the other changes are in pkcs15 and pkac11 routines in libopensc and the OpenSc module. These include treating EDDSA and XEDDSA ecparams the same, so most of the code is already there. I have been testing with Yubikey and GUNK both in openpgp. They have a further problem that part of the OID is written to the cards, and these cards are using the old OIDs, so there needs to be a mapping from the new OIDS to the old OIDs used on the cards and may change with newer OpenPGP cards as well. . Found today that this could be in done in card-openpgp.c which would not effect your SoftHSM. Only RFC 8410 defines official OIDs, so these should be the ones we use, but support the old names. My intent was to get the OpenPGP code working, then submit as a PR. The main difference between the X25519-improvements and X25519-improvements-2 was to cleanup and reorganize the code with more commits that make more sense. I hope to get the changes in next week. |
- add matching of ec_curve_info using ec_params value - distinguish between ed25519 and edd448 using curve size Related OpenSC#2952
@Jakuje @dlegaultbbry I am looking at https://github.com/OpenSC/OpenSC/blob/master/src/tools/pkcs11-tool.c#L149-L150 But it also looks like the two OIDs and the printable strings should be switched so the lines look like: {"edwards25519", "1.3.6.1.4.3029.1.5.1", "130a63757276653235353139", 255, CKM_EC_EDWARDS_KEY_PAIR_GEN}, See comment on how this was assigned: https://oid-rep.orange-labs.fr/get/1.3.6.1.4.1.3029.1.5.1 and note it is for Ed25519 |
Further evidence shows the OpenSC OIDs were correct and the comment from https://lapo.it/asn1js/ "OBJECT IDENTIFIER 1.3.6.1.4.1.11591.15.1 curve25519 (GNU encryption algorithm)" is misleading.
From OpenPGP specs version 3.4.1 says in blob 6E "Application Related Data"
From an opensc-debug.log The blog 6E can seen in the Incoming APDU (328 bytes)
Note the 3rd byte is the Algorithm: SC_OPENPGP_KEYALGO_EDDSA=16, SC_OPENPGP_KEYALGO_ECDH=12 and SC_OPENPGP_KEYALGO_RSA=01 RFC 4880 from 31 August 2020 also confirms the above. |
I agree that there seems to be wide confusion and misinformation from those early defined OID values. https://oidref.com/1.3.6.1.4.1.11591.15.1 = ed25519 I think what is already there is fine minus the OID typo to be fixed. Then adding the extra ones you've already planned would provide enough support. |
@dlegaultbbry I have pushed additional commits to https://github.com/dengert/OpenSC/tree/X25519-improvements-2 |
I'm not familiar with PKCS#15, but why do you refer to the keys as EDDSA and XEDDSA instead of [Ed|X][25519|448] in dengert@e31e306 In dengert@62df4cb the comments at lines 450 and 458 need a refresh since it's now 25519 + 448 which are defined. Rest looks ok to me. |
I will look at these. The common code in OpenSC, including pkcs11-tool, is designed to work with the [Ed|X][25519|448] curves using the RFC 8410 names or OIDs and the older names and OIDs. PKCS11 3.0 treats the older OIDs differently and passed a printable string rather then the OIDs. The new OpenSC will convert to the newer names and accept the older names. The only The existing OpenSC code used these from
The above names apply to both 25519 and 448 size keys. Internally OpenSC uses OIDs that imply the size. In RFC 8410 8 Human-Readable Algorithm Names names might be a better choice when the curve is not known. But Using ECDH could also be used for ordinary EC curves when uses for DH. I have Nitrokey Start (GUNK) , Yubikey 5 NFC cards and can use software software PGP as well as OpenSSL 3.x The RFC 8410 curves define ASN.1 for pubkeys, and ordinary EC public use uncompressed 04||x||y but not RFC 8410 keys. There still needs to be a lot of testing of these mods, as I was not expecting anyone else at this time to wanting these changes. |
- add matching of ec_curve_info using ec_params value - distinguish between ed25519 and edd448 using curve size Related OpenSC#2952
Some updates on better support for Montgomery curves, the "X..." ones, in https://datatracker.ietf.org/doc/html/rfc8410 which also relates to #3118 #3000 #3090 OpenSSL only supports RFC 8410, but with some tests I have been able to use OpenSSL with Yubikey and NitroStart tokens with OpenPGP 3.4 applets. But it does not always work. I think I know why, but it needs further testing. https://datatracker.ietf.org/doc/html/rfc8410#page-4 says: https://www.rfc-editor.org/errata_search.php?rfc=7748 says: The Montgomery form of the curve is generally used with a ladder, where the v coordinate is unused and unspecified. Thus I picked the smaller of the two possible values for v. However, the curve is birationally equivalent to edwards25519, where both coordinates of the base point are used and are already in widespread use. Sadly, picking the smaller of the values for v ends up mapping to the negative of the base point on edwards25519. This change replaces v with -v so that it matches up." I have seen OpenSSL and OpenSC derive work, but also fail. I have attributed code changes to the failures but the failures may indeed be the choice of the: "smaller of the two possible values for v" some times working and other times not. The choice is done on the token and since it a choice between which "v" is smaller it could be a 50-50 chance of using the correct "v". If I am correct, one way to verify that OpenSSL using RFC8410 vs the Tokens using RFC 7748 can work is to do something like:
I plain on trying the above in a script for a few times to see the choice of a key will work 50% of the time. If that is the case, OpenSC code during key generation could try a few times to generate a key that would work with OpenSSL. If that is not the case it might be that the older OpenPGP tokens using the experimental RFCs will never work with OpenSSL, and much of the effort in #3090 is not usable. There are many variables in all of this
|
Well it turns out my test script was using the OpenSSL private key rather then the public key as the peer pubkey. Here is revised script that works: So things are looking much better. |
Problem Description
These are comments while experimenting with OpenPGP on a Nitro Start (GUNK) and a Yubikey 5 NFC and OpenSSL 3.1.2 generated MONTGOMERY keys and OpenSC 0.24.0-rc2. The Nitro and Yubikey initialized using GnuPG 2.2.7 gpg-card command.
Running derive commands between any two of the above produce the same generic secret key as expected.
Example using Yubikey token and the Nitro public key with output to YK10-Nitro.der:
Example of OpenSSL private key and the Nitro public key:
The problem stems from curve "friendly" names and OIDs used by different programs, RFCs and other documents.
OpenSSL is following RFC 8410 using "OBJECT IDENTIFIER ::= { 1 3 101 110 }" I
gpg-card uses "cv25519" as algorithm and does not list the OID.
OpenPGP Card Specification 3.4.1 appears to be the latest, but it does says anything about Edwards or Montgomery curves.
Internally the Yubikey and Nitro store on card
C2 0B 12 2B 06 01 04 01 97 55 01 05 01
in the DO 6E. Labeled "Algorithm attributes decryption" which is: Blob 'C2', length '0B', algorithm '12' and OID (minus the tag and length) '2B 06 01 04 01 97 55 01 05 01'This problem of inconsistent names and OIDs is known. and pkcs11-curr-v3.0-os) says:
"Montgomery EC public keys only support the use of the curveName selection to specify a curve name as defined in [RFC7748] and the use of the oID selection to specify a curve through an ECDH algorithm as defined in [RFC 8410]. Note that keys defined by RFC 7748 and RFC 8410 are incompatible."
Proposed Resolution
Since OpenSSL uses RFC 8410 and the OID 1.3.101.110 OpenSC should go with this OID. The OID 1.3.6.1.4.1.3029.1.5.1 appears to be a vendor's invented OID which is really used within the Yubikey and GNUK applets. OpenSC could continue to support the vendor's OID, but should favor the use of OID 1.3.101.110 and map this internally as needed.
Edwards curves have similar issues. RFC 8410 defines "id-Ed25519 OBJECT IDENTIFIER ::= { 1 3 101 112 }"
where as OpenSC is using the vendor's OID of 1.3.6.1.4.1.11591.15.1
(But OpenSSH is following RFC 8731 which is referring to RFC 7748.)
OpenSC 0.24.0-rc2 has some changes in pkcs11-tool .c to allow passing in a "printable string" or an OID as defined in PKCS11 3.0 but it is not complete.
Comments
I have also been working on code changes to OpenSC PKCS11 to support C_GenerateKeyPair for CKK_EC_MONTGOMERY and CKK_EC_EDWARDS in the openpgp code. So far I have been able to generate a CKK_EC_MONTGOMERY on the card
but the card-openpgp.c does not handle the public key correctly as EC keys have a leading
04
where as these key do not.Also have some changes to pkcs11-tool.c
The text was updated successfully, but these errors were encountered: