]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[crypto] Generalise X.509 OID-identified algorithm to asn1.c
authorMichael Brown <mcb30@ipxe.org>
Wed, 21 Mar 2012 13:57:32 +0000 (13:57 +0000)
committerMichael Brown <mcb30@ipxe.org>
Thu, 22 Mar 2012 00:31:22 +0000 (00:31 +0000)
The concept of an OID-identified algorithm as defined in X.509 is used
in some other standards (e.g. PKCS#7).  Generalise this functionality
and provide it as part of the ASN.1 core.

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 f075b66ddd2019dd32018466c7ca929ce10fbc8e..cd502502d99b8d7cc387ec7a2c2b1fac3ca9bd05 100644 (file)
@@ -22,6 +22,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
 #include <stddef.h>
 #include <string.h>
 #include <errno.h>
+#include <ipxe/tables.h>
 #include <ipxe/asn1.h>
 
 /** @file
@@ -341,3 +342,56 @@ int asn1_compare ( const struct asn1_cursor *cursor1,
        return ( difference ? difference :
                 memcmp ( cursor1->data, cursor2->data, cursor1->len ) );
 }
+
+/**
+ * Identify ASN.1 algorithm by OID
+ *
+ * @v cursor           ASN.1 object cursor
+
+ * @ret algorithm      Algorithm, or NULL
+ */
+static struct asn1_algorithm *
+asn1_find_algorithm ( const struct asn1_cursor *cursor ) {
+       struct asn1_algorithm *algorithm;
+
+       for_each_table_entry ( algorithm, ASN1_ALGORITHMS ) {
+               if ( asn1_compare ( &algorithm->oid, cursor ) == 0 )
+                       return algorithm;
+       }
+
+       return NULL;
+}
+
+/**
+ * Parse ASN.1 OID-identified algorithm
+ *
+ * @v cursor           ASN.1 object cursor
+ * @ret algorithm      Algorithm, or NULL
+ */
+struct asn1_algorithm * asn1_algorithm ( const struct asn1_cursor *cursor ) {
+       struct asn1_cursor contents;
+       struct asn1_algorithm *algorithm;
+       int rc;
+
+       /* Enter signatureAlgorithm */
+       memcpy ( &contents, cursor, sizeof ( contents ) );
+       asn1_enter ( &contents, ASN1_SEQUENCE );
+
+       /* Enter algorithm */
+       if ( ( rc = asn1_enter ( &contents, ASN1_OID ) ) != 0 ) {
+               DBGC ( cursor, "ASN1 %p cannot locate algorithm OID:\n",
+                      cursor );
+               DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
+               return NULL;
+       }
+
+       /* Identify algorithm */
+       algorithm = asn1_find_algorithm ( &contents );
+       if ( ! algorithm ) {
+               DBGC ( cursor, "ASN1 %p unrecognised algorithm:\n", cursor );
+               DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
+               return NULL;
+       }
+
+       return algorithm;
+}
index 9b98b179046dd536f5cc58e146546ccb882e805a..62f52c95470aac02296a3ab9bf8b54f412a2198a 100644 (file)
@@ -39,6 +39,53 @@ FILE_LICENCE ( GPL2_OR_LATER );
  * RSA is documented in RFC 3447.
  */
 
+/** "rsaEncryption" object identifier */
+static uint8_t oid_rsa_encryption[] = { ASN1_OID_RSAENCRYPTION };
+
+/** "md5WithRSAEncryption" object identifier */
+static uint8_t oid_md5_with_rsa_encryption[] =
+       { ASN1_OID_MD5WITHRSAENCRYPTION };
+
+/** "sha1WithRSAEncryption" object identifier */
+static uint8_t oid_sha1_with_rsa_encryption[] =
+       { ASN1_OID_SHA1WITHRSAENCRYPTION };
+
+/** "sha256WithRSAEncryption" object identifier */
+static uint8_t oid_sha256_with_rsa_encryption[] =
+       { ASN1_OID_SHA256WITHRSAENCRYPTION };
+
+/** "rsaEncryption" OID-identified algorithm */
+struct asn1_algorithm rsa_encryption_algorithm __asn1_algorithm = {
+       .name = "rsaEncryption",
+       .pubkey = &rsa_algorithm,
+       .digest = NULL,
+       .oid = ASN1_OID_CURSOR ( oid_rsa_encryption ),
+};
+
+/** "md5WithRSAEncryption" OID-identified algorithm */
+struct asn1_algorithm md5_with_rsa_encryption_algorithm __asn1_algorithm = {
+       .name = "md5WithRSAEncryption",
+       .pubkey = &rsa_algorithm,
+       .digest = &md5_algorithm,
+       .oid = ASN1_OID_CURSOR ( oid_md5_with_rsa_encryption ),
+};
+
+/** "sha1WithRSAEncryption" OID-identified algorithm */
+struct asn1_algorithm sha1_with_rsa_encryption_algorithm __asn1_algorithm = {
+       .name = "sha1WithRSAEncryption",
+       .pubkey = &rsa_algorithm,
+       .digest = &sha1_algorithm,
+       .oid = ASN1_OID_CURSOR ( oid_sha1_with_rsa_encryption ),
+};
+
+/** "sha256WithRSAEncryption" OID-identified algorithm */
+struct asn1_algorithm sha256_with_rsa_encryption_algorithm __asn1_algorithm = {
+       .name = "sha256WithRSAEncryption",
+       .pubkey = &rsa_algorithm,
+       .digest = &sha256_algorithm,
+       .oid = ASN1_OID_CURSOR ( oid_sha256_with_rsa_encryption ),
+};
+
 /** MD5 digestInfo prefix */
 static const uint8_t rsa_md5_prefix_data[] =
        { RSA_DIGESTINFO_PREFIX ( MD5_DIGEST_SIZE, ASN1_OID_MD5 ) };
index 449d07e2e1097ade67de7791126b362223140108..5ce42f88b48ef11cea2e24bef93d46aa02093b64 100644 (file)
@@ -49,10 +49,10 @@ FILE_LICENCE ( GPL2_OR_LATER );
        __einfo_error ( EINFO_ENOTSUP_EXTENSION )
 #define EINFO_ENOTSUP_EXTENSION \
        __einfo_uniqify ( EINFO_ENOTSUP, 0x02, "Unsupported extension" )
-#define EINVAL_NON_SIGNATURE \
-       __einfo_error ( EINFO_EINVAL_NON_SIGNATURE )
-#define EINFO_EINVAL_NON_SIGNATURE \
-       __einfo_uniqify ( EINFO_EINVAL, 0x01, "Not a signature algorithm" )
+#define EINVAL_ALGORITHM \
+       __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 \
@@ -101,70 +101,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 );
 
-/** "rsaEncryption" object identifier */
-static uint8_t oid_rsa_encryption[] = { ASN1_OID_RSAENCRYPTION };
-
-/** "md5WithRSAEncryption" object identifier */
-static uint8_t oid_md5_with_rsa_encryption[] =
-       { ASN1_OID_MD5WITHRSAENCRYPTION };
-
-/** "sha1WithRSAEncryption" object identifier */
-static uint8_t oid_sha1_with_rsa_encryption[] =
-       { ASN1_OID_SHA1WITHRSAENCRYPTION };
-
-/** "sha256WithRSAEncryption" object identifier */
-static uint8_t oid_sha256_with_rsa_encryption[] =
-       { ASN1_OID_SHA256WITHRSAENCRYPTION };
-
-/** Supported algorithms */
-static struct x509_algorithm x509_algorithms[] = {
-       {
-               .name = "rsaEncryption",
-               .pubkey = &rsa_algorithm,
-               .digest = NULL,
-               .oid = ASN1_OID_CURSOR ( oid_rsa_encryption ),
-       },
-       {
-               .name = "md5WithRSAEncryption",
-               .pubkey = &rsa_algorithm,
-               .digest = &md5_algorithm,
-               .oid = ASN1_OID_CURSOR ( oid_md5_with_rsa_encryption ),
-       },
-       {
-               .name = "sha1WithRSAEncryption",
-               .pubkey = &rsa_algorithm,
-               .digest = &sha1_algorithm,
-               .oid = ASN1_OID_CURSOR ( oid_sha1_with_rsa_encryption ),
-       },
-       {
-               .name = "sha256WithRSAEncryption",
-               .pubkey = &rsa_algorithm,
-               .digest = &sha256_algorithm,
-               .oid = ASN1_OID_CURSOR ( oid_sha256_with_rsa_encryption ),
-       },
-};
-
-/**
- * Identify X.509 algorithm by OID
- *
- * @v oid              OID
- * @ret algorithm      Algorithm, or NULL
- */
-static struct x509_algorithm *
-x509_find_algorithm ( const struct asn1_cursor *oid ) {
-       struct x509_algorithm *algorithm;
-       unsigned int i;
-
-       for ( i = 0 ; i < ( sizeof ( x509_algorithms ) /
-                           sizeof ( x509_algorithms[0] ) ) ; i++ ) {
-               algorithm = &x509_algorithms[i];
-               if ( asn1_compare ( &algorithm->oid, oid ) == 0 )
-                       return algorithm;
-       }
-
-       return NULL;
-}
-
 /**
  * Parse X.509 certificate algorithm
  *
@@ -173,29 +109,24 @@ x509_find_algorithm ( const struct asn1_cursor *oid ) {
  * @v raw              ASN.1 cursor
  * @ret rc             Return status code
  */
-static int x509_parse_algorithm ( struct x509_certificate *cert,
-                                 struct x509_algorithm **algorithm,
+int x509_parse_pubkey_algorithm ( struct x509_certificate *cert,
+                                 struct asn1_algorithm **algorithm,
                                  const struct asn1_cursor *raw ) {
-       struct asn1_cursor cursor;
-       int rc;
 
-       /* Enter signatureAlgorithm */
-       memcpy ( &cursor, raw, sizeof ( cursor ) );
-       asn1_enter ( &cursor, ASN1_SEQUENCE );
-
-       /* Enter algorithm */
-       if ( ( rc = asn1_enter ( &cursor, ASN1_OID ) ) != 0 ) {
-               DBGC ( cert, "X509 %p cannot locate algorithm:\n", cert );
+       /* Parse algorithm */
+       *algorithm = asn1_algorithm ( raw );
+       if ( ! (*algorithm) ) {
+               DBGC ( cert, "X509 %p unrecognised algorithm:\n", cert );
                DBGC_HDA ( cert, 0, raw->data, raw->len );
-               return rc;
+               return -ENOTSUP_ALGORITHM;
        }
 
-       /* Identify algorithm */
-       *algorithm = x509_find_algorithm ( &cursor );
-       if ( ! *algorithm ) {
-               DBGC ( cert, "X509 %p unsupported algorithm:\n", cert );
-               DBGC_HDA ( cert, 0, cursor.data, cursor.len );
-               return -ENOTSUP_ALGORITHM;
+       /* Check algorithm has a public key */
+       if ( ! (*algorithm)->pubkey ) {
+               DBGC ( cert, "X509 %p algorithm %s is not a public-key "
+                      "algorithm:\n", cert, (*algorithm)->name );
+               DBGC_HDA ( cert, 0, raw->data, raw->len );
+               return -EINVAL_ALGORITHM;
        }
 
        return 0;
@@ -210,20 +141,21 @@ static int x509_parse_algorithm ( struct x509_certificate *cert,
  * @ret rc             Return status code
  */
 static int x509_parse_signature_algorithm ( struct x509_certificate *cert,
-                                           struct x509_algorithm **algorithm,
+                                           struct asn1_algorithm **algorithm,
                                            const struct asn1_cursor *raw ) {
        int rc;
 
        /* Parse algorithm */
-       if ( ( rc = x509_parse_algorithm ( cert, algorithm, raw ) ) != 0 )
+       if ( ( rc = x509_parse_pubkey_algorithm ( cert, algorithm,
+                                                 raw ) ) != 0 )
                return rc;
 
        /* Check algorithm is a signature algorithm */
-       if ( ! x509_is_signature_algorithm ( *algorithm ) ) {
+       if ( ! (*algorithm)->digest ) {
                DBGC ( cert, "X509 %p algorithm %s is not a signature "
                       "algorithm:\n", cert, (*algorithm)->name );
                DBGC_HDA ( cert, 0, raw->data, raw->len );
-               return -EINVAL_NON_SIGNATURE;
+               return -EINVAL_ALGORITHM;
        }
 
        return 0;
@@ -600,7 +532,7 @@ static int x509_parse_subject ( struct x509_certificate *cert,
 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 x509_algorithm **algorithm = &public_key->algorithm;
+       struct asn1_algorithm **algorithm = &public_key->algorithm;
        struct asn1_cursor cursor;
        int rc;
 
@@ -613,7 +545,8 @@ static int x509_parse_public_key ( struct x509_certificate *cert,
        asn1_enter ( &cursor, ASN1_SEQUENCE );
 
        /* Parse algorithm */
-       if ( ( rc = x509_parse_algorithm ( cert, algorithm, &cursor ) ) != 0 )
+       if ( ( rc = x509_parse_pubkey_algorithm ( cert, algorithm,
+                                                 &cursor ) ) != 0 )
                return rc;
        DBGC ( cert, "X509 %p public key algorithm is %s\n",
               cert, (*algorithm)->name );
@@ -866,7 +799,7 @@ static int x509_parse_extensions ( struct x509_certificate *cert,
  */
 static int x509_parse_tbscertificate ( struct x509_certificate *cert,
                                       const struct asn1_cursor *raw ) {
-       struct x509_algorithm **algorithm = &cert->signature_algorithm;
+       struct asn1_algorithm **algorithm = &cert->signature_algorithm;
        struct asn1_cursor cursor;
        int rc;
 
@@ -933,7 +866,7 @@ static int x509_parse_tbscertificate ( struct x509_certificate *cert,
  */
 int x509_parse ( struct x509_certificate *cert, const void *data, size_t len ) {
        struct x509_signature *signature = &cert->signature;
-       struct x509_algorithm **signature_algorithm = &signature->algorithm;
+       struct asn1_algorithm **signature_algorithm = &signature->algorithm;
        struct x509_bit_string *signature_value = &signature->value;
        struct asn1_cursor cursor;
        int rc;
@@ -991,7 +924,7 @@ int x509_parse ( struct x509_certificate *cert, const void *data, size_t len ) {
 static int x509_check_signature ( struct x509_certificate *cert,
                                  struct x509_public_key *public_key ) {
        struct x509_signature *signature = &cert->signature;
-       struct x509_algorithm *algorithm = signature->algorithm;
+       struct asn1_algorithm *algorithm = signature->algorithm;
        struct digest_algorithm *digest = algorithm->digest;
        struct pubkey_algorithm *pubkey = algorithm->pubkey;
        uint8_t digest_ctx[ digest->ctxsize ];
index f912f5f57707446d55f0d79e48a029dca848ea34..553a8f3c32a01c5368c510d533ebb0325cbc03d5 100644 (file)
@@ -9,6 +9,9 @@
 
 FILE_LICENCE ( GPL2_OR_LATER );
 
+#include <stdint.h>
+#include <ipxe/tables.h>
+
 /** An ASN.1 object cursor */
 struct asn1_cursor {
        /** Start of data */
@@ -143,6 +146,24 @@ struct asn1_cursor {
                .len = sizeof ( oid_value ),                    \
        }
 
+/** An ASN.1 OID-identified algorithm */
+struct asn1_algorithm {
+       /** Name */
+       const char *name;
+       /** Object identifier */
+       struct asn1_cursor oid;
+       /** Public-key algorithm (if applicable) */
+       struct pubkey_algorithm *pubkey;
+       /** Digest algorithm (if applicable) */
+       struct digest_algorithm *digest;
+};
+
+/** ASN.1 OID-identified algorithms */
+#define ASN1_ALGORITHMS __table ( struct asn1_algorithm, "asn1_algorithms" )
+
+/** Declare an ASN.1 OID-identified algorithm */
+#define __asn1_algorithm __table_entry ( ASN1_ALGORITHMS, 01 )
+
 /** An ASN.1 boolean */
 struct asn1_boolean {
        /** Value */
@@ -181,5 +202,7 @@ 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,
                          const struct asn1_cursor *cursor2 );
+extern struct asn1_algorithm *
+asn1_algorithm ( const struct asn1_cursor *cursor );
 
 #endif /* _IPXE_ASN1_H */
index 89f90b844d92c3d8a72bde0a81b01a9dde386479..45f738cd71a8fc4360e599398559423a6c2dd1b8 100644 (file)
@@ -14,29 +14,6 @@ FILE_LICENCE ( GPL2_OR_LATER );
 #include <time.h>
 #include <ipxe/asn1.h>
 
-/** An X.509 algorithm */
-struct x509_algorithm {
-       /** Name */
-       const char *name;
-       /** Object identifier */
-       struct asn1_cursor oid;
-       /** Public-key algorithm */
-       struct pubkey_algorithm *pubkey;
-       /** Digest algorithm (if applicable) */
-       struct digest_algorithm *digest;
-};
-
-/**
- * Test if X.509 algorithm is a signature algorithm
- *
- * @v algorithm                Algorithm
- * @ret is_signature   Algorithm is a signature algorithm
- */
-static inline __attribute__ (( always_inline )) int
-x509_is_signature_algorithm ( struct x509_algorithm *algorithm ) {
-       return ( algorithm->digest != NULL );
-}
-
 /** An X.509 bit string */
 struct x509_bit_string {
        /** Data */
@@ -80,7 +57,7 @@ struct x509_public_key {
        /** Raw public key */
        struct asn1_cursor raw;
        /** Public key algorithm */
-       struct x509_algorithm *algorithm;
+       struct asn1_algorithm *algorithm;
 };
 
 /** An X.509 certificate subject */
@@ -96,7 +73,7 @@ struct x509_subject {
 /** An X.509 certificate signature */
 struct x509_signature {
        /** Signature algorithm */
-       struct x509_algorithm *algorithm;
+       struct asn1_algorithm *algorithm;
        /** Signature value */
        struct x509_bit_string value;
 };
@@ -147,7 +124,7 @@ struct x509_certificate {
        /** Raw tbsCertificate */
        struct asn1_cursor tbs;
        /** Signature algorithm */
-       struct x509_algorithm *signature_algorithm;
+       struct asn1_algorithm *signature_algorithm;
        /** Issuer */
        struct x509_issuer issuer;
        /** Validity */