]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[crypto] Generalise rsa_parse_integer() to asn1_enter_unsigned()
authorMichael Brown <mcb30@ipxe.org>
Thu, 11 Dec 2025 15:02:28 +0000 (15:02 +0000)
committerMichael Brown <mcb30@ipxe.org>
Thu, 11 Dec 2025 15:09:58 +0000 (15:09 +0000)
ECDSA signature values and private keys are fixed-length unsigned
integers modulo N (the group order of the elliptic curve) and are
therefore most naturally represented in ASN.1 using ASN1_OCTET_STRING.

Private key representations do use ASN1_OCTET_STRING, but signature
values tend to use ASN1_INTEGER, which adds no value but does ensure
that the encoding becomes variable-length and requires handling a
pointless extra zero byte if the MSB of the unsigned value happens to
be set.

RSA also makes use of ASN1_INTEGER for modulus and exponent values.
Generalise the existing rsa_parse_integer() to asn1_enter_unsigned()
to allow this code to be reused for ECDSA.

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

index 4ee95415f23b53b005d9bfebdfa3049a125c4fa2..819a8aadbfd5e9b2d3997c768f37353128ae0267 100644 (file)
@@ -372,6 +372,29 @@ int asn1_enter_bits ( struct asn1_cursor *cursor, unsigned int *unused ) {
        return 0;
 }
 
+/**
+ * Enter ASN.1 unsigned integer
+ *
+ * @v cursor           ASN.1 object cursor
+ * @ret rc             Return status code
+ */
+int asn1_enter_unsigned ( struct asn1_cursor *cursor ) {
+       int rc;
+
+       /* Enter integer */
+       if ( ( rc = asn1_enter ( cursor, ASN1_INTEGER ) ) != 0 )
+               return rc;
+
+       /* Skip initial positive sign byte if applicable */
+       if ( ( cursor->len > 1 ) &&
+            ( *( ( uint8_t * ) cursor->data ) == 0x00 ) ) {
+               cursor->data++;
+               cursor->len--;
+       }
+
+       return 0;
+}
+
 /**
  * Parse value of ASN.1 boolean
  *
index 14456f755613ee5568b5e1db6ca86b77df28c668..9c0982cf6b618ac9707d2b58a8ec36e0146f7334 100644 (file)
@@ -137,34 +137,6 @@ static int rsa_alloc ( struct rsa_context *context, size_t modulus_len,
        return 0;
 }
 
-/**
- * Parse RSA integer
- *
- * @v integer          Integer to fill in
- * @v raw              ASN.1 cursor
- * @ret rc             Return status code
- */
-static int rsa_parse_integer ( struct asn1_cursor *integer,
-                              const struct asn1_cursor *raw ) {
-
-       /* Enter integer */
-       memcpy ( integer, raw, sizeof ( *integer ) );
-       asn1_enter ( integer, ASN1_INTEGER );
-
-       /* Skip initial sign byte if applicable */
-       if ( ( integer->len > 1 ) &&
-            ( *( ( uint8_t * ) integer->data ) == 0x00 ) ) {
-               integer->data++;
-               integer->len--;
-       }
-
-       /* Fail if cursor or integer are invalid */
-       if ( ! integer->len )
-               return -EINVAL;
-
-       return 0;
-}
-
 /**
  * Parse RSA modulus and exponent
  *
@@ -226,7 +198,8 @@ static int rsa_parse_mod_exp ( struct asn1_cursor *modulus,
        }
 
        /* Extract modulus */
-       if ( ( rc = rsa_parse_integer ( modulus, &cursor ) ) != 0 )
+       memcpy ( modulus, &cursor, sizeof ( *modulus ) );
+       if ( ( rc = asn1_enter_unsigned ( modulus ) ) != 0 )
                return rc;
        asn1_skip_any ( &cursor );
 
@@ -235,7 +208,8 @@ static int rsa_parse_mod_exp ( struct asn1_cursor *modulus,
                asn1_skip ( &cursor, ASN1_INTEGER );
 
        /* Extract publicExponent/privateExponent */
-       if ( ( rc = rsa_parse_integer ( exponent, &cursor ) ) != 0 )
+       memcpy ( exponent, &cursor, sizeof ( *exponent ) );
+       if ( ( rc = asn1_enter_unsigned ( exponent ) ) != 0 )
                return rc;
 
        return 0;
index 641a1190dbc40bda76c6fa73918e893de82c51cc..914d42f57cf00e4da67e30214b061637de2df33b 100644 (file)
@@ -488,6 +488,7 @@ extern int asn1_skip_any ( struct asn1_cursor *cursor );
 extern int asn1_shrink_any ( struct asn1_cursor *cursor );
 extern int asn1_enter_bits ( struct asn1_cursor *cursor,
                             unsigned int *unused );
+extern int asn1_enter_unsigned ( struct asn1_cursor *cursor );
 extern int asn1_boolean ( const struct asn1_cursor *cursor );
 extern int asn1_integer ( const struct asn1_cursor *cursor, int *value );
 extern int asn1_compare ( const struct asn1_cursor *cursor1,