diff --git a/src/crypto/asn1.c b/src/crypto/asn1.c index 802553cab..4ee95415f 100644 --- a/src/crypto/asn1.c +++ b/src/crypto/asn1.c @@ -83,6 +83,19 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #define EINFO_ENOTTY_ALGORITHM \ __einfo_uniqify ( EINFO_ENOTTY, 0x01, "Inappropriate algorithm" ) +/** "ecPublicKey" object identifier */ +static uint8_t oid_ecpublickey[] = { ASN1_OID_ECPUBLICKEY }; + +/** Generic elliptic curve container algorithm + * + * The actual curve to be used is identified via the algorithm + * parameters, rather than the top-level OID. + */ +struct asn1_algorithm ecpubkey_algorithm __asn1_algorithm = { + .name = "ecPublicKey", + .oid = ASN1_CURSOR ( oid_ecpublickey ), +}; + /** * Start parsing ASN.1 object * @@ -624,20 +637,66 @@ int asn1_signature_algorithm ( const struct asn1_cursor *cursor, return 0; } +/** + * Parse ASN.1 OID-identified elliptic curve algorithm + * + * @v cursor ASN.1 object cursor + * @ret algorithm Algorithm + * @ret rc Return status code + */ +int asn1_curve_algorithm ( const struct asn1_cursor *cursor, + struct asn1_algorithm **algorithm ) { + struct asn1_cursor curve; + + /* Elliptic curves are identified as either: + * + * - the algorithm "id-ecPublicKey" with the actual curve + * specified in the algorithm parameters, or + * + * - a standalone object identifier for the curve + */ + if ( asn1_check_algorithm ( cursor, &ecpubkey_algorithm, + &curve ) != 0 ) { + memcpy ( &curve, cursor, sizeof ( curve ) ); + } + + /* Identify curve */ + asn1_enter ( &curve, ASN1_OID ); + *algorithm = asn1_find_algorithm ( &curve ); + if ( ! *algorithm ) { + DBGC ( cursor, "ASN1 %p unrecognised EC algorithm:\n", + cursor ); + DBGC_HDA ( cursor, 0, cursor->data, cursor->len ); + return -ENOTSUP_ALGORITHM; + } + + /* Check algorithm has an elliptic curve */ + if ( ! (*algorithm)->curve ) { + DBGC ( cursor, "ASN1 %p algorithm %s is not an elliptic curve " + "algorithm:\n", cursor, (*algorithm)->name ); + DBGC_HDA ( cursor, 0, cursor->data, cursor->len ); + return -ENOTTY_ALGORITHM; + } + + return 0; +} + /** * Check ASN.1 OID-identified algorithm * * @v cursor ASN.1 object cursor * @v expected Expected algorithm + * @ret params Algorithm parameters, or NULL * @ret rc Return status code */ int asn1_check_algorithm ( const struct asn1_cursor *cursor, - struct asn1_algorithm *expected ) { + struct asn1_algorithm *expected, + struct asn1_cursor *params ) { struct asn1_algorithm *actual; int rc; /* Parse algorithm */ - if ( ( rc = asn1_algorithm ( cursor, &actual, NULL ) ) != 0 ) + if ( ( rc = asn1_algorithm ( cursor, &actual, params ) ) != 0 ) return rc; /* Check algorithm matches */ diff --git a/src/crypto/rsa.c b/src/crypto/rsa.c index 051bbfa08..14456f755 100644 --- a/src/crypto/rsa.c +++ b/src/crypto/rsa.c @@ -194,8 +194,8 @@ static int rsa_parse_mod_exp ( struct asn1_cursor *modulus, asn1_skip_any ( &cursor ); /* Enter privateKey, if present */ - if ( asn1_check_algorithm ( &cursor, - &rsa_encryption_algorithm ) == 0 ) { + if ( asn1_check_algorithm ( &cursor, &rsa_encryption_algorithm, + NULL ) == 0 ) { /* Skip privateKeyAlgorithm */ asn1_skip_any ( &cursor ); diff --git a/src/include/ipxe/asn1.h b/src/include/ipxe/asn1.h index e3f48e8f7..641a1190d 100644 --- a/src/include/ipxe/asn1.h +++ b/src/include/ipxe/asn1.h @@ -127,9 +127,15 @@ struct asn1_builder_header { #define ASN1_OID_TRIPLE( value ) \ ( 0x80 | ( ( (value) >> 14 ) & 0x7f ) ), ASN1_OID_DOUBLE ( (value) ) +/** ASN.1 OID for ecPublicKey (1.2.840.10045.2.1) */ +#define ASN1_OID_ECPUBLICKEY \ + ASN1_OID_INITIAL ( 1, 2 ), ASN1_OID_DOUBLE ( 840 ), \ + ASN1_OID_DOUBLE ( 10045 ), ASN1_OID_SINGLE ( 2 ), \ + ASN1_OID_SINGLE ( 1 ) + /** ASN.1 OID for prime256v1 (1.2.840.10045.3.1.7) */ #define ASN1_OID_PRIME256V1 \ - ASN1_OID_INITIAL ( 1, 1 ), ASN1_OID_DOUBLE ( 840 ), \ + ASN1_OID_INITIAL ( 1, 2 ), ASN1_OID_DOUBLE ( 840 ), \ ASN1_OID_DOUBLE ( 10045 ), ASN1_OID_SINGLE ( 3 ), \ ASN1_OID_SINGLE ( 1 ), ASN1_OID_SINGLE ( 7 ) @@ -426,6 +432,7 @@ extern struct asn1_algorithm oid_sha512_algorithm __asn1_algorithm; extern struct asn1_algorithm oid_sha224_algorithm __asn1_algorithm; extern struct asn1_algorithm oid_sha512_224_algorithm __asn1_algorithm; extern struct asn1_algorithm oid_sha512_256_algorithm __asn1_algorithm; +extern struct asn1_algorithm ecpubkey_algorithm __asn1_algorithm; /** * Invalidate ASN.1 object cursor @@ -497,8 +504,11 @@ extern int asn1_cipher_algorithm ( const struct asn1_cursor *cursor, struct asn1_cursor *params ); extern int asn1_signature_algorithm ( const struct asn1_cursor *cursor, struct asn1_algorithm **algorithm ); +extern int asn1_curve_algorithm ( const struct asn1_cursor *cursor, + struct asn1_algorithm **algorithm ); extern int asn1_check_algorithm ( const struct asn1_cursor *cursor, - struct asn1_algorithm *expected ); + struct asn1_algorithm *expected, + struct asn1_cursor *params ); extern int asn1_parse_cbc ( struct asn1_algorithm *algorithm, struct asn1_cursor *params ); extern int asn1_parse_gcm ( struct asn1_algorithm *algorithm,