Complete x509parse_public_key_ec()
Warning: due to a bug in oid_descriptor_from_buf(), keys associated to some
curves (secp224r1, secp384r1, secp521r1) are incorrectly rejected,
since their namedCurve OID contains a nul byte.
diff --git a/library/x509parse.c b/library/x509parse.c
index 840319f..e04d56b 100644
--- a/library/x509parse.c
+++ b/library/x509parse.c
@@ -234,6 +234,40 @@
}
/*
+ * subjectPublicKey BIT STRING
+ * -- which, in our case, contains
+ * ECPoint ::= octet string (not ASN.1)
+ */
+static int x509_get_subpubkey_ec( unsigned char **p, const unsigned char *end,
+ const ecp_group *grp, ecp_point *pt )
+{
+ int ret;
+ size_t len;
+
+ if( ( ret = asn1_get_tag( p, end, &len, ASN1_BIT_STRING ) ) != 0 )
+ return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
+
+ if( *p + len != end )
+ return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT +
+ POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+ /*
+ * First byte in the content of BIT STRING is the nummber of padding bit.
+ * Here it is always 0 since ECPoint is an octet string, so skip it.
+ */
+ ++*p;
+ --len;
+
+ if( ( ret = ecp_point_read_binary( grp, pt,
+ (const unsigned char *) *p, len ) ) != 0 )
+ {
+ return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
+ }
+
+ return( 0 );
+}
+
+/*
* AttributeTypeAndValue ::= SEQUENCE {
* type AttributeType,
* value AttributeValue }
@@ -2634,20 +2668,71 @@
}
/*
+ * Parse a public EC key in RFC 5480 format, der-encoded
+ */
+static int x509parse_public_key_ec_der( ecp_keypair *key,
+ const unsigned char *buf, size_t len )
+{
+ int ret;
+ ecp_group_id grp_id;
+ x509_buf alg_oid;
+ pk_type_t alg = POLARSSL_PK_NONE;
+ unsigned char *p = (unsigned char *) buf;
+ unsigned char *end = p + len;
+ const unsigned char *params_end;
+ /*
+ * SubjectPublicKeyInfo ::= SEQUENCE {
+ * algorithm AlgorithmIdentifier,
+ * subjectPublicKey BIT STRING
+ * }
+ * -- algorithm parameters are ECParameters
+ * -- subjectPublicKey is an ECPoint
+ */
+ if( ( ret = asn1_get_tag( &p, end, &len,
+ ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+ {
+ return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + ret );
+ }
+
+ if( ( ret = x509_get_alg( &p, end, &alg_oid, ¶ms_end ) ) != 0 )
+ return( ret );
+
+ if( oid_get_pk_alg( &alg_oid, &alg ) != 0 )
+ return( POLARSSL_ERR_X509_UNKNOWN_PK_ALG );
+
+ if( alg != POLARSSL_PK_ECKEY && alg != POLARSSL_PK_ECKEY_DH )
+ return( POLARSSL_ERR_X509_UNKNOWN_PK_ALG );
+
+ if ( alg == POLARSSL_PK_ECKEY_DH )
+ key->alg = POLARSSL_ECP_KEY_ALG_ECDH;
+
+ if( ( ret = x509_get_ecparams( &p, params_end, &grp_id ) ) != 0 )
+ return( ret );
+
+ if( ( ret = ecp_use_known_dp( &key->grp, grp_id ) ) != 0 )
+ return( ret );
+
+ if( ( ret = x509_get_subpubkey_ec( &p, end, &key->grp, &key->Q ) ) != 0 )
+ {
+ return( ret );
+ }
+
+ return( 0 );
+}
+
+/*
* Parse a public EC key
*/
int x509parse_public_key_ec( ecp_keypair *eckey,
const unsigned char *key, size_t keylen )
{
int ret;
- size_t len;
- unsigned char *p, *end;
- x509_buf alg_oid;
#if defined(POLARSSL_PEM_C)
+ size_t len;
pem_context pem;
pem_init( &pem );
- ret = pem_read_buffer( &pem, /* TODO: check header */
+ ret = pem_read_buffer( &pem,
"-----BEGIN PUBLIC KEY-----",
"-----END PUBLIC KEY-----",
key, NULL, 0, &len );
@@ -2657,6 +2742,7 @@
/*
* Was PEM encoded
*/
+ key = pem.buf;
keylen = pem.buflen;
}
else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
@@ -2664,32 +2750,19 @@
pem_free( &pem );
return( ret );
}
-
- p = ( ret == 0 ) ? pem.buf : (unsigned char *) key;
-#else
- p = (unsigned char *) key;
#endif
- end = p + keylen;
- /* TODO: parse key */
- (void) alg_oid;
- (void) end;
- (void) eckey;
-
- if( ( ret = ecp_check_pubkey( &eckey->grp, &eckey->Q ) ) != 0 )
+ if( ( ret = x509parse_public_key_ec_der ( eckey, key, keylen ) ) != 0 ||
+ ( ret = ecp_check_pubkey( &eckey->grp, &eckey->Q ) ) != 0 )
{
-#if defined(POLARSSL_PEM_C)
- pem_free( &pem );
-#endif
ecp_keypair_free( eckey );
- return( ret );
}
#if defined(POLARSSL_PEM_C)
pem_free( &pem );
#endif
- return( 0 );
+ return( ret );
}
#endif /* defined(POLARSSL_ECP_C) */
diff --git a/tests/data_files/ec_pub.der b/tests/data_files/ec_pub.der
index 954bf3b..74c5951 100644
--- a/tests/data_files/ec_pub.der
+++ b/tests/data_files/ec_pub.der
Binary files differ
diff --git a/tests/data_files/ec_pub.pem b/tests/data_files/ec_pub.pem
index dbbc2e6..d677d27 100644
--- a/tests/data_files/ec_pub.pem
+++ b/tests/data_files/ec_pub.pem
@@ -1,4 +1,4 @@
-----BEGIN PUBLIC KEY-----
-ME4wEAYHKoZIzj0CAQYFK4EEACEDOgAEb3GKqedAJ2/1CRdhjIRhQO+4erL49GlI
-QrBg7frKWrc6ZrnjgXgdHt68Tux/2IyRuff+lvGn32s=
+MEkwEwYHKoZIzj0CAQYIKoZIzj0DAQEDMgAEvHl9s65/COw9SWtPtBGz9iClWKUB
+4CItCM/g3Irsixp78kvpKVHMW6G+uyR0kJrg
-----END PUBLIC KEY-----