]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[crypto] Generalise x509_parse_bit_string() to asn1_bit_string()
authorMichael Brown <mcb30@ipxe.org>
Mon, 14 May 2012 08:54:19 +0000 (09:54 +0100)
committerMichael Brown <mcb30@ipxe.org>
Mon, 14 May 2012 10:02:38 +0000 (11:02 +0100)
Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/crypto/asn1.c
src/crypto/rsa.c
src/crypto/x509.c
src/include/ipxe/asn1.h
src/include/ipxe/x509.h

index 47c735c56273d20330ee088eb62cbbd683014a85..9b3864ed27106cf006716ac60f8f4c91295f65ac 100644 (file)
@@ -62,6 +62,10 @@ FILE_LICENCE ( GPL2_OR_LATER );
        __einfo_error ( EINFO_EINVAL_ASN1_ALGORITHM )
 #define EINFO_EINVAL_ASN1_ALGORITHM \
        __einfo_uniqify ( EINFO_EINVAL, 0x06, "Invalid algorithm" )
+#define EINVAL_BIT_STRING \
+       __einfo_error ( EINFO_EINVAL_BIT_STRING )
+#define EINFO_EINVAL_BIT_STRING \
+       __einfo_uniqify ( EINFO_EINVAL, 0x07, "Invalid bit string" )
 #define ENOTSUP_ALGORITHM \
        __einfo_error ( EINFO_ENOTSUP_ALGORITHM )
 #define EINFO_ENOTSUP_ALGORITHM \
@@ -295,7 +299,9 @@ int asn1_shrink_any ( struct asn1_cursor *cursor ) {
  */
 int asn1_boolean ( const struct asn1_cursor *cursor ) {
        struct asn1_cursor contents;
-       const struct asn1_boolean *boolean;
+       const struct {
+               uint8_t value;
+       } __attribute__ (( packed )) *boolean;
 
        /* Enter boolean */
        memcpy ( &contents, cursor, sizeof ( contents ) );
@@ -347,6 +353,87 @@ int asn1_integer ( const struct asn1_cursor *cursor, int *value ) {
        return 0;
 }
 
+/**
+ * Parse ASN.1 bit string
+ *
+ * @v cursor           ASN.1 cursor
+ * @v bits             Bit string to fill in
+ * @ret rc             Return status code
+ */
+int asn1_bit_string ( const struct asn1_cursor *cursor,
+                     struct asn1_bit_string *bits ) {
+       struct asn1_cursor contents;
+       const struct {
+               uint8_t unused;
+               uint8_t data[0];
+       } __attribute__ (( packed )) *bit_string;
+       size_t len;
+       unsigned int unused;
+       uint8_t unused_mask;
+       const uint8_t *last;
+       int rc;
+
+       /* Enter bit string */
+       memcpy ( &contents, cursor, sizeof ( contents ) );
+       if ( ( rc = asn1_enter ( &contents, ASN1_BIT_STRING ) ) != 0 ) {
+               DBGC ( cursor, "ASN1 %p cannot locate bit string:\n", cursor );
+               DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
+               return rc;
+       }
+
+       /* Validity checks */
+       if ( contents.len < sizeof ( *bit_string ) ) {
+               DBGC ( cursor, "ASN1 %p invalid bit string:\n", cursor );
+               DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
+               return -EINVAL_BIT_STRING;
+       }
+       bit_string = contents.data;
+       len = ( contents.len - offsetof ( typeof ( *bit_string ), data ) );
+       unused = bit_string->unused;
+       unused_mask = ( 0xff >> ( 8 - unused ) );
+       last = ( bit_string->data + len - 1 );
+       if ( ( unused >= 8 ) ||
+            ( ( unused > 0 ) && ( len == 0 ) ) ||
+            ( ( *last & unused_mask ) != 0 ) ) {
+               DBGC ( cursor, "ASN1 %p invalid bit string:\n", cursor );
+               DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
+               return -EINVAL_BIT_STRING;
+       }
+
+       /* Populate bit string */
+       bits->data = &bit_string->data;
+       bits->len = len;
+       bits->unused = unused;
+
+       return 0;
+}
+
+/**
+ * Parse ASN.1 bit string that must be an integral number of bytes
+ *
+ * @v cursor           ASN.1 cursor
+ * @v bits             Bit string to fill in
+ * @ret rc             Return status code
+ */
+int asn1_integral_bit_string ( const struct asn1_cursor *cursor,
+                              struct asn1_bit_string *bits ) {
+       int rc;
+
+       /* Parse bit string */
+       if ( ( rc = asn1_bit_string ( cursor, bits ) ) != 0 )
+               return rc;
+
+       /* Check that there are no unused bits at end of string */
+       if ( bits->unused ) {
+               DBGC ( cursor, "ASN1 %p invalid integral bit string:\n",
+                      cursor );
+               DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
+               return -EINVAL_BIT_STRING;
+       }
+
+       return 0;
+}
+
 /**
  * Compare two ASN.1 objects
  *
index be2696ba87902f59fa7304785a4ba9dc14f5b713..563d6b9b9a72724fe02a8734ccdd453edcd8674f 100644 (file)
@@ -241,7 +241,7 @@ static int rsa_parse_integer ( struct rsa_context *context,
  */
 static int rsa_init ( void *ctx, const void *key, size_t key_len ) {
        struct rsa_context *context = ctx;
-       const struct asn1_bit_string *bit_string;
+       struct asn1_bit_string bits;
        struct asn1_cursor modulus;
        struct asn1_cursor exponent;
        struct asn1_cursor cursor;
@@ -274,17 +274,10 @@ static int rsa_init ( void *ctx, const void *key, size_t key_len ) {
                asn1_skip ( &cursor, ASN1_SEQUENCE );
 
                /* Enter subjectPublicKey */
-               asn1_enter ( &cursor, ASN1_BIT_STRING );
-
-               /* Check and skip unused-bits byte of bit string */
-               bit_string = cursor.data;
-               if ( ( cursor.len < sizeof ( *bit_string ) ) ||
-                    ( bit_string->unused != 0 ) ) {
-                       rc = -EINVAL;
+               if ( ( rc = asn1_integral_bit_string ( &cursor, &bits ) ) != 0 )
                        goto err_parse;
-               }
-               cursor.data = &bit_string->data;
-               cursor.len -= offsetof ( typeof ( *bit_string ), data );
+               cursor.data = bits.data;
+               cursor.len = bits.len;
 
                /* Enter RSAPublicKey */
                asn1_enter ( &cursor, ASN1_SEQUENCE );
index f25424a11cc26f0449923ffb6b4a7d4b49f938c7..dc8745dce7e807e4b7af4cbfdaa33d5f83d68d55 100644 (file)
@@ -54,10 +54,6 @@ FILE_LICENCE ( GPL2_OR_LATER );
        __einfo_error ( EINFO_EINVAL_ALGORITHM )
 #define EINFO_EINVAL_ALGORITHM \
        __einfo_uniqify ( EINFO_EINVAL, 0x01, "Invalid algorithm type" )
-#define EINVAL_BIT_STRING \
-       __einfo_error ( EINFO_EINVAL_BIT_STRING )
-#define EINFO_EINVAL_BIT_STRING \
-       __einfo_uniqify ( EINFO_EINVAL, 0x02, "Invalid bit string" )
 #define EINVAL_ALGORITHM_MISMATCH \
        __einfo_error ( EINFO_EINVAL_ALGORITHM_MISMATCH )
 #define EINFO_EINVAL_ALGORITHM_MISMATCH \
@@ -154,88 +150,6 @@ static uint8_t oid_common_name[] = { ASN1_OID_COMMON_NAME };
 static struct asn1_cursor oid_common_name_cursor =
        ASN1_OID_CURSOR ( oid_common_name );
 
-/**
- * Parse X.509 certificate bit string
- *
- * @v cert             X.509 certificate
- * @v bits             Bit string to fill in
- * @v raw              ASN.1 cursor
- * @ret rc             Return status code
- */
-static int x509_parse_bit_string ( struct x509_certificate *cert,
-                                  struct x509_bit_string *bits,
-                                  const struct asn1_cursor *raw ) {
-       struct asn1_cursor cursor;
-       const struct asn1_bit_string *bit_string;
-       size_t len;
-       unsigned int unused;
-       uint8_t unused_mask;
-       const uint8_t *last;
-       int rc;
-
-       /* Enter bit string */
-       memcpy ( &cursor, raw, sizeof ( cursor ) );
-       if ( ( rc = asn1_enter ( &cursor, ASN1_BIT_STRING ) ) != 0 ) {
-               DBGC ( cert, "X509 %p cannot locate bit string:\n", cert );
-               DBGC_HDA ( cert, 0, raw->data, raw->len );
-               return rc;
-       }
-
-       /* Validity checks */
-       if ( cursor.len < sizeof ( *bit_string ) ) {
-               DBGC ( cert, "X509 %p invalid bit string:\n", cert );
-               DBGC_HDA ( cert, 0, raw->data, raw->len );
-               return -EINVAL_BIT_STRING;
-       }
-       bit_string = cursor.data;
-       len = ( cursor.len - offsetof ( typeof ( *bit_string ), data ) );
-       unused = bit_string->unused;
-       unused_mask = ( 0xff >> ( 8 - unused ) );
-       last = ( bit_string->data + len - 1 );
-       if ( ( unused >= 8 ) ||
-            ( ( unused > 0 ) && ( len == 0 ) ) ||
-            ( ( *last & unused_mask ) != 0 ) ) {
-               DBGC ( cert, "X509 %p invalid bit string:\n", cert );
-               DBGC_HDA ( cert, 0, raw->data, raw->len );
-               return -EINVAL_BIT_STRING;
-       }
-
-       /* Populate bit string */
-       bits->data = &bit_string->data;
-       bits->len = len;
-       bits->unused = unused;
-
-       return 0;
-}
-
-/**
- * Parse X.509 certificate bit string that must be an integral number of bytes
- *
- * @v cert             X.509 certificate
- * @v bits             Bit string to fill in
- * @v raw              ASN.1 cursor
- * @ret rc             Return status code
- */
-static int x509_parse_integral_bit_string ( struct x509_certificate *cert,
-                                           struct x509_bit_string *bits,
-                                           const struct asn1_cursor *raw ) {
-       int rc;
-
-       /* Parse bit string */
-       if ( ( rc = x509_parse_bit_string ( cert, bits, raw ) ) != 0 )
-               return rc;
-
-       /* Check that there are no unused bits at end of string */
-       if ( bits->unused ) {
-               DBGC ( cert, "X509 %p invalid integral bit string:\n", cert );
-               DBGC_HDA ( cert, 0, raw->data, raw->len );
-               return -EINVAL_BIT_STRING;
-       }
-
-       return 0;
-}
-
-
 /**
  * Parse X.509 certificate version
  *
@@ -466,7 +380,7 @@ static int x509_parse_public_key ( struct x509_certificate *cert,
                                   const struct asn1_cursor *raw ) {
        struct x509_public_key *public_key = &cert->subject.public_key;
        struct asn1_algorithm **algorithm = &public_key->algorithm;
-       struct x509_bit_string *raw_bits = &public_key->raw_bits;
+       struct asn1_bit_string *raw_bits = &public_key->raw_bits;
        struct asn1_cursor cursor;
        int rc;
 
@@ -491,8 +405,11 @@ static int x509_parse_public_key ( struct x509_certificate *cert,
        asn1_skip_any ( &cursor );
 
        /* Parse bit string */
-       if ( ( rc = x509_parse_bit_string ( cert, raw_bits, &cursor ) ) != 0 )
+       if ( ( rc = asn1_bit_string ( &cursor, raw_bits ) ) != 0 ) {
+               DBGC ( cert, "X509 %p could not parse public key bits: %s\n",
+                      cert, strerror ( rc ) );
                return rc;
+       }
 
        return 0;
 }
@@ -569,7 +486,7 @@ static int x509_parse_basic_constraints ( struct x509_certificate *cert,
 static int x509_parse_key_usage ( struct x509_certificate *cert,
                                  const struct asn1_cursor *raw ) {
        struct x509_key_usage *usage = &cert->extensions.usage;
-       struct x509_bit_string bit_string;
+       struct asn1_bit_string bit_string;
        const uint8_t *bytes;
        size_t len;
        unsigned int i;
@@ -579,8 +496,11 @@ static int x509_parse_key_usage ( struct x509_certificate *cert,
        usage->present = 1;
 
        /* Parse bit string */
-       if ( ( rc = x509_parse_bit_string ( cert, &bit_string, raw ) ) != 0 )
+       if ( ( rc = asn1_bit_string ( raw, &bit_string ) ) != 0 ) {
+               DBGC ( cert, "X509 %p could not parse key usage: %s\n",
+                      cert, strerror ( rc ) );
                return rc;
+       }
 
        /* Parse key usage bits */
        bytes = bit_string.data;
@@ -1034,7 +954,7 @@ static int x509_parse ( struct x509_certificate *cert,
                        const struct asn1_cursor *raw ) {
        struct x509_signature *signature = &cert->signature;
        struct asn1_algorithm **signature_algorithm = &signature->algorithm;
-       struct x509_bit_string *signature_value = &signature->value;
+       struct asn1_bit_string *signature_value = &signature->value;
        struct asn1_cursor cursor;
        int rc;
 
@@ -1062,9 +982,12 @@ static int x509_parse ( struct x509_certificate *cert,
        asn1_skip_any ( &cursor );
 
        /* Parse signatureValue */
-       if ( ( rc = x509_parse_integral_bit_string ( cert, signature_value,
-                                                    &cursor ) ) != 0 )
+       if ( ( rc = asn1_integral_bit_string ( &cursor,
+                                              signature_value ) ) != 0 ) {
+               DBGC ( cert, "X509 %p could not parse signature value: %s\n",
+                      cert, strerror ( rc ) );
                return rc;
+       }
        DBGC2 ( cert, "X509 %p signatureValue is:\n", cert );
        DBGC2_HDA ( cert, 0, signature_value->data, signature_value->len );
 
index cd0d5342370bf9f28bd4b003d929bd0da4d95a4e..222e32ecee1a012df1a6b5ee3fbaff33420ea166 100644 (file)
@@ -200,18 +200,14 @@ struct asn1_algorithm {
 /** Declare an ASN.1 OID-identified algorithm */
 #define __asn1_algorithm __table_entry ( ASN1_ALGORITHMS, 01 )
 
-/** An ASN.1 boolean */
-struct asn1_boolean {
-       /** Value */
-       uint8_t value;
-} __attribute__ (( packed ));
-
 /** An ASN.1 bit string */
 struct asn1_bit_string {
-       /** Number of unused bits */
-       uint8_t unused;
        /** Data */
-       uint8_t data[0];
+       const void *data;
+       /** Length */
+       size_t len;
+       /** Unused bits at end of data */
+       unsigned int unused;
 } __attribute__ (( packed ));
 
 /**
@@ -236,6 +232,10 @@ extern int asn1_skip_any ( struct asn1_cursor *cursor );
 extern int asn1_shrink_any ( 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_bit_string ( const struct asn1_cursor *cursor,
+                            struct asn1_bit_string *bits );
+extern int asn1_integral_bit_string ( const struct asn1_cursor *cursor,
+                                     struct asn1_bit_string *bits );
 extern int asn1_compare ( const struct asn1_cursor *cursor1,
                          const struct asn1_cursor *cursor2 );
 extern int asn1_algorithm ( const struct asn1_cursor *cursor,
index a55511b81087ac503714149a3522861c16117bbd..8b1dda25f4a81e5c07cf04d4069f83c33bda3fc5 100644 (file)
@@ -16,16 +16,6 @@ FILE_LICENCE ( GPL2_OR_LATER );
 #include <ipxe/refcnt.h>
 #include <ipxe/list.h>
 
-/** An X.509 bit string */
-struct x509_bit_string {
-       /** Data */
-       const void *data;
-       /** Length */
-       size_t len;
-       /** Unused bits at end of data */
-       unsigned int unused;
-};
-
 /** An X.509 serial number */
 struct x509_serial {
        /** Raw serial number */
@@ -59,7 +49,7 @@ struct x509_public_key {
        /** Public key algorithm */
        struct asn1_algorithm *algorithm;
        /** Raw public key bit string */
-       struct x509_bit_string raw_bits;
+       struct asn1_bit_string raw_bits;
 };
 
 /** An X.509 certificate subject */
@@ -77,7 +67,7 @@ struct x509_signature {
        /** Signature algorithm */
        struct asn1_algorithm *algorithm;
        /** Signature value */
-       struct x509_bit_string value;
+       struct asn1_bit_string value;
 };
 
 /** An X.509 certificate basic constraints set */