]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[crypto] Allow for OID-identified elliptic curve algorithms
authorMichael Brown <mcb30@ipxe.org>
Thu, 27 Nov 2025 16:39:52 +0000 (16:39 +0000)
committerMichael Brown <mcb30@ipxe.org>
Wed, 3 Dec 2025 15:45:14 +0000 (15:45 +0000)
Elliptic curves in X.509 certificates are identified via the
id-ecPublicKey object identifier (1.2.840.10045.2.1), with the
specific elliptic curve identified via a second OID in the algorithm
parameters.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/crypto/asn1.c
src/crypto/rsa.c
src/include/ipxe/asn1.h

index 802553cab96ad8d045d6b688efdd02a66f37cc55..4ee95415f23b53b005d9bfebdfa3049a125c4fa2 100644 (file)
@@ -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 */
index 051bbfa087fa58e039148e4689616c95e2aca425..14456f755613ee5568b5e1db6ca86b77df28c668 100644 (file)
@@ -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 );
index e3f48e8f7b1e6a1b9338f8cdee0e32dee3f39a57..641a1190dbc40bda76c6fa73918e893de82c51cc 100644 (file)
@@ -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,