Skip to content
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

Incorrect Encoding of EC and EDDSA public keys #3000

Open
dengert opened this issue Jan 27, 2024 · 2 comments
Open

Incorrect Encoding of EC and EDDSA public keys #3000

dengert opened this issue Jan 27, 2024 · 2 comments

Comments

@dengert
Copy link
Member

dengert commented Jan 27, 2024

Problem Description

OpenSC has two ways to encode EC, EDDSA and XEDDSA public keys:

  • The SPKI method used in PKCS15 and X.509 public keys in certificates which is a sequence with the curve OID and the public key encoded in a ASN.1 BIT STRING. (Which is correct.)
  • The other method is to just encode and decode the pubkey data in an ASN.1 OCTET STRING. Which is wrong and used mostly internally in OpenSC.)

ANSI X9.62 says: "The elliptic curve public key (an ECPoint which is an OCTET STRING) is mapped to
a subjectPublicKey (a BIT STRING)"

PKCS11 says: `CKA_EC_POINT | Byte array | DER-encoding of ANSI X9.62 ECPoint value Q".

EC keys where first added to OpenSC in c34caeb in 2010-11-30 as:

+static struct sc_asn1_entry c_asn1_ec_pointQ[2] = {
+       { "ecpointQ", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_OCTET_STRING, SC_ASN1_ALLOC, NULL, NULL },
+       { NULL, 0, 0, 0, NULL, NULL }
+};

The line above should have been:

{ "ecpointQ", SC_ASN1_BIT_STRING_NI, SC_ASN1_TAG_BIT_STRING, SC_ASN1_ALLOC, NULL, NULL },

RFC 8410 also uses a BIT STRING.

PKCS15-v1.1 defines:

ECPublicKeyChoice ::= CHOICE {
raw ECPoint,
spki SubjectPublicKeyInfo, -- See X.509. Must contain a public EC key
...
}

where: "The value shall, in the IC card case, be a path to a file
containing either a value of type ECPublicKey, of type SubjectPublicKeyInfo, or (in the
case of a card capable of performing on-chip EC public-key operations) some card
specific representation of a public EC key." The raw or ECPublicKey are not further defined. But either may be written to the card.

Proposed Resolution

Correct the encoding for EC, EDDSA and XEDDSA format keys to encode using BIT STRING.
Change the decoding to accept a choice of BIT STRING or OCTET STRING, so as to continue
to work with cards where the data was written using OCTET STRING.

All EC, EDDSA and XEDDSA will use the same correct encoding.

Unresolved Issues

The value retuned for CKA_EC_POINT will change from an OCTET STRING to a BIT STRING. This may cause problems with calling applications which wrongly expect OCTET STRING but should only accept BIT STRING. (pkcs11-tool is the only application known to request CKA_EC_POINT. Libp11 and pkcs11-provider need to be checked.)

CKO_PUBLIC_KEY does NOT have a CKA_VALUE but in V2.40 and 3.0 does have a CKA_PUBLIC_KEY_INFO:
"Byte array DER-encoding of the SubjectPublicKeyInfo for this public key. (MAY be empty, DEFAULT derived from the underlying public key data)."

OpenSC implements for CKO_PUBLIC_KEY a CKA_VALUE and a CKA_SPKI (listed as a vendor attribute)
So would be easy to add CKA_PUBLIC_KEY_INFO.

Steps to reproduce

Best example of current method using OCTET STRING with openpgp on Yubikey with brainpoolP256r1:

pkcs11-tool -O --slot 1

Public Key Object; EC  EC_POINT 256 bits
  EC_POINT:   0441042853adc20c3fb426b0b85483baa870a6f0bcdbb3e17ead4e18552614910ada25118d1ca82b0f44c15b90ee19950b182749a395a2940985ee6d3358a5ea43b434
  EC_PARAMS:  06092b2403030208010107 (OID 1.3.36.3.3.2.8.1.1.7)
  label:      Signature key
  ID:         01
  Usage:      verify, verifyRecover

Tag: '04' OCTET STRING Length: 0x41 EC key in uncompressed format of: "04||x||y"

New proposed BIT STRING:

/opt/ossl-3.1.2/bin/pkcs11-tool' 
Public Key Object; EC  EC_POINT 260 bits
  EC_POINT:   034200042853adc20c3fb426b0b85483baa870a6f0bcdbb3e17ead4e18552614910ada25118d1ca82b0f44c15b90ee19950b182749a395a2940985ee6d3358a5ea43b434
  EC_PARAMS:  06092b2403030208010107 (OID 1.3.36.3.3.2.8.1.1.7)
  label:      Signature key
  ID:         01
  Usage:      verify, verifyRecover
  Access:     none

Tag: '03' BIT STRING Length: 0x42 Unused bits in last byte: '00' EC key in uncompressed format of: "04||x||y"
(The "260 bits" calculation need to be fixed.)
Other places in code need to be identified to handle the "Unused bits in last byte" and EDDSA and XEDDSA keys do not have a "uncompressed format '04' byte.

@dengert
Copy link
Member Author

dengert commented Feb 3, 2024

Does anyone have access to an official version of ANSI X9.62?

I found a draft online from 1997. Can someone verify that the official version says: "The elliptic curve public key (an ECPoint which is an OCTET STRING) is mapped to a subjectPublicKey (a BIT STRING)"

This would also make more sense as RFC 8410 say EdDSA and ECDH:

SubjectPublicKeyInfo  ::=  SEQUENCE  {
       algorithm         AlgorithmIdentifier,
       subjectPublicKey  BIT STRING
   }

dengert added a commit to dengert/OpenSC that referenced this issue Feb 15, 2024
See opensc issue OpenSC#3000

 On branch X25519-improvements-2
 Changes to be committed:
	modified:   libopensc/card-openpgp.c
	modified:   libopensc/pkcs15-pubkey.c
	modified:   tools/pkcs11-tool.c
	modified:   tools/pkcs15-init.c
dengert added a commit to dengert/OpenSC that referenced this issue Feb 16, 2024
See opensc issue OpenSC#3000

 On branch X25519-improvements-2
 Changes to be committed:
	modified:   libopensc/card-openpgp.c
	modified:   libopensc/pkcs15-pubkey.c
	modified:   tools/pkcs11-tool.c
	modified:   tools/pkcs15-init.c
dengert added a commit that referenced this issue Feb 16, 2024
See opensc issue #3000

 On branch X25519-improvements-2
 Changes to be committed:
	modified:   libopensc/card-openpgp.c
	modified:   libopensc/pkcs15-pubkey.c
	modified:   tools/pkcs11-tool.c
	modified:   tools/pkcs15-init.c
dengert added a commit to dengert/OpenSC that referenced this issue Mar 20, 2024
See opensc issue OpenSC#3000

 On branch X25519-improvements-2
 Changes to be committed:
	modified:   libopensc/card-openpgp.c
	modified:   libopensc/pkcs15-pubkey.c
	modified:   tools/pkcs11-tool.c
	modified:   tools/pkcs15-init.c
dengert added a commit to dengert/OpenSC that referenced this issue Mar 23, 2024
See opensc issue OpenSC#3000

 On branch X25519-improvements-2
 Changes to be committed:
	modified:   libopensc/card-openpgp.c
	modified:   libopensc/pkcs15-pubkey.c
	modified:   tools/pkcs11-tool.c
	modified:   tools/pkcs15-init.c
dengert added a commit to dengert/OpenSC that referenced this issue Mar 28, 2024
See opensc issue OpenSC#3000

 On branch X25519-improvements-2
 Changes to be committed:
	modified:   libopensc/card-openpgp.c
	modified:   libopensc/pkcs15-pubkey.c
	modified:   tools/pkcs11-tool.c
	modified:   tools/pkcs15-init.c
@Jakuje
Copy link
Member

Jakuje commented Mar 28, 2024

I dont have ANSI X9.6.2, but for example in the EC standard, referes to the fields as you describe:

https://www.secg.org/sec1-v2.pdf

dengert added a commit to dengert/OpenSC that referenced this issue Apr 5, 2024
See opensc issue OpenSC#3000

 On branch X25519-improvements-2
 Changes to be committed:
	modified:   libopensc/card-openpgp.c
	modified:   libopensc/pkcs15-pubkey.c
	modified:   tools/pkcs11-tool.c
	modified:   tools/pkcs15-init.c
dengert added a commit to dengert/OpenSC that referenced this issue Apr 18, 2024
See opensc issue OpenSC#3000

 On branch X25519-improvements-2
 Changes to be committed:
	modified:   libopensc/card-openpgp.c
	modified:   libopensc/pkcs15-pubkey.c
	modified:   tools/pkcs11-tool.c
	modified:   tools/pkcs15-init.c
dengert added a commit to dengert/OpenSC that referenced this issue Apr 27, 2024
See opensc issue OpenSC#3000

 On branch X25519-improvements-2
 Changes to be committed:
	modified:   libopensc/card-openpgp.c
	modified:   libopensc/pkcs15-pubkey.c
	modified:   tools/pkcs11-tool.c
	modified:   tools/pkcs15-init.c
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants