From fb1188936ca29af61709afd8b866ea55d4a05a67 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Thu, 11 Dec 2025 15:02:28 +0000 Subject: [PATCH] [crypto] Generalise rsa_parse_integer() to asn1_enter_unsigned() 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 --- src/crypto/asn1.c | 23 +++++++++++++++++++++++ src/crypto/rsa.c | 34 ++++------------------------------ src/include/ipxe/asn1.h | 1 + 3 files changed, 28 insertions(+), 30 deletions(-) diff --git a/src/crypto/asn1.c b/src/crypto/asn1.c index 4ee95415f..819a8aadb 100644 --- a/src/crypto/asn1.c +++ b/src/crypto/asn1.c @@ -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 * diff --git a/src/crypto/rsa.c b/src/crypto/rsa.c index 14456f755..9c0982cf6 100644 --- a/src/crypto/rsa.c +++ b/src/crypto/rsa.c @@ -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; diff --git a/src/include/ipxe/asn1.h b/src/include/ipxe/asn1.h index 641a1190d..914d42f57 100644 --- a/src/include/ipxe/asn1.h +++ b/src/include/ipxe/asn1.h @@ -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,