]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[crypto] Parse X.509 extended key usage extension
authorMichael Brown <mcb30@ipxe.org>
Wed, 21 Mar 2012 16:16:37 +0000 (16:16 +0000)
committerMichael Brown <mcb30@ipxe.org>
Thu, 22 Mar 2012 11:41:22 +0000 (11:41 +0000)
Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/crypto/x509.c
src/include/ipxe/asn1.h
src/include/ipxe/x509.h

index cf82fc033c6ea86113e7cb302db18deac6c26b46..7c6aab5cea3570c8c23bc5bdeeb097bc1c79211e 100644 (file)
@@ -683,12 +683,92 @@ static int x509_parse_key_usage ( struct x509_certificate *cert,
        return 0;
 }
 
+/** "id-kp-codeSigning" object identifier */
+static uint8_t oid_code_signing[] = { ASN1_OID_CODESIGNING };
+
+/** Supported key purposes */
+static struct x509_key_purpose x509_key_purposes[] = {
+       {
+               .name = "codeSigning",
+               .bits = X509_CODE_SIGNING,
+               .oid = ASN1_OID_CURSOR ( oid_code_signing ),
+       },
+};
+
+/**
+ * Parse X.509 certificate key purpose identifier
+ *
+ * @v cert             X.509 certificate
+ * @v raw              ASN.1 cursor
+ * @ret rc             Return status code
+ */
+static int x509_parse_key_purpose ( struct x509_certificate *cert,
+                                   const struct asn1_cursor *raw ) {
+       struct x509_extended_key_usage *ext_usage = &cert->extensions.ext_usage;
+       struct x509_key_purpose *purpose;
+       struct asn1_cursor cursor;
+       unsigned int i;
+       int rc;
+
+       /* Enter keyPurposeId */
+       memcpy ( &cursor, raw, sizeof ( cursor ) );
+       if ( ( rc = asn1_enter ( &cursor, ASN1_OID ) ) != 0 ) {
+               DBGC ( cert, "X509 %p invalid keyPurposeId:\n", cert );
+               DBGC_HDA ( cert, 0, raw->data, raw->len );
+               return rc;
+       }
+
+       /* Identify key purpose */
+       for ( i = 0 ; i < ( sizeof ( x509_key_purposes ) /
+                           sizeof ( x509_key_purposes[0] ) ) ; i++ ) {
+               purpose = &x509_key_purposes[i];
+               if ( asn1_compare ( &cursor, &purpose->oid ) == 0 ) {
+                       DBGC ( cert, "X509 %p has key purpose %s\n",
+                              cert, purpose->name );
+                       ext_usage->bits |= purpose->bits;
+                       return 0;
+               }
+       }
+
+       /* Ignore unrecognised key purposes */
+       return 0;
+}
+
+/**
+ * Parse X.509 certificate extended key usage
+ *
+ * @v cert             X.509 certificate
+ * @v raw              ASN.1 cursor
+ * @ret rc             Return status code
+ */
+static int x509_parse_extended_key_usage ( struct x509_certificate *cert,
+                                          const struct asn1_cursor *raw ) {
+       struct asn1_cursor cursor;
+       int rc;
+
+       /* Enter extKeyUsage */
+       memcpy ( &cursor, raw, sizeof ( cursor ) );
+       asn1_enter ( &cursor, ASN1_SEQUENCE );
+
+       /* Parse each extension in turn */
+       while ( cursor.len ) {
+               if ( ( rc = x509_parse_key_purpose ( cert, &cursor ) ) != 0 )
+                       return rc;
+               asn1_skip_any ( &cursor );
+       }
+
+       return 0;
+}
+
 /** "id-ce-basicConstraints" object identifier */
 static uint8_t oid_ce_basic_constraints[] = { ASN1_OID_BASICCONSTRAINTS };
 
 /** "id-ce-keyUsage" object identifier */
 static uint8_t oid_ce_key_usage[] = { ASN1_OID_KEYUSAGE };
 
+/** "id-ce-extKeyUsage" object identifier */
+static uint8_t oid_ce_ext_key_usage[] = { ASN1_OID_EXTKEYUSAGE };
+
 /** Supported certificate extensions */
 static struct x509_extension x509_extensions[] = {
        {
@@ -701,6 +781,11 @@ static struct x509_extension x509_extensions[] = {
                .oid = ASN1_OID_CURSOR ( oid_ce_key_usage ),
                .parse = x509_parse_key_usage,
        },
+       {
+               .name = "extKeyUsage",
+               .oid = ASN1_OID_CURSOR ( oid_ce_ext_key_usage ),
+               .parse = x509_parse_extended_key_usage,
+       },
 };
 
 /**
index 553a8f3c32a01c5368c510d533ebb0325cbc03d5..393d5dc341dfbfd911925d5d30241e15dd67d557 100644 (file)
@@ -140,6 +140,18 @@ struct asn1_cursor {
        ASN1_OID_INITIAL ( 2, 5 ), ASN1_OID_SINGLE ( 29 ),      \
        ASN1_OID_SINGLE ( 19 )
 
+/** ASN.1 OID for id-ce-extKeyUsage (2.5.29.37) */
+#define ASN1_OID_EXTKEYUSAGE                                   \
+       ASN1_OID_INITIAL ( 2, 5 ), ASN1_OID_SINGLE ( 29 ),      \
+       ASN1_OID_SINGLE ( 37 )
+
+/** ASN.1 OID for id-kp-codeSigning (1.3.6.1.5.5.7.3.3) */
+#define ASN1_OID_CODESIGNING                                   \
+       ASN1_OID_INITIAL ( 1, 3 ), ASN1_OID_SINGLE ( 6 ),       \
+       ASN1_OID_SINGLE ( 1 ), ASN1_OID_SINGLE ( 5 ),           \
+       ASN1_OID_SINGLE ( 5 ), ASN1_OID_SINGLE ( 7 ),           \
+       ASN1_OID_SINGLE ( 3 ), ASN1_OID_SINGLE ( 3 )
+
 /** Define an ASN.1 cursor containing an OID */
 #define ASN1_OID_CURSOR( oid_value ) {                         \
                .data = oid_value,                              \
index 427f79557affa15355e0512dc71436217394fcd9..09e1800755de2061fd6c66ab21bc5bd84f9dae75 100644 (file)
@@ -113,12 +113,29 @@ enum x509_key_usage_bits {
        X509_DECIPHER_ONLY = 0x8000,
 };
 
+/** An X.509 certificate extended key usage */
+struct x509_extended_key_usage {
+       /** Usage bits */
+       unsigned int bits;
+};
+
+/** X.509 certificate extended key usage bits
+ *
+ * Extended key usages are identified by OID; these bits are purely an
+ * internal definition.
+ */
+enum x509_extended_key_usage_bits {
+       X509_CODE_SIGNING = 0x0001,
+};
+
 /** An X.509 certificate extensions set */
 struct x509_extensions {
        /** Basic constraints */
        struct x509_basic_constraints basic;
        /** Key usage */
        struct x509_key_usage usage;
+       /** Extended key usage */
+       struct x509_extended_key_usage ext_usage;
 };
 
 /** An X.509 certificate */
@@ -161,6 +178,16 @@ struct x509_extension {
                          const struct asn1_cursor *raw );
 };
 
+/** An X.509 key purpose */
+struct x509_key_purpose {
+       /** Name */
+       const char *name;
+       /** Object identifier */
+       struct asn1_cursor oid;
+       /** Extended key usage bits */
+       unsigned int bits;
+};
+
 /** An X.509 root certificate store */
 struct x509_root {
        /** Fingerprint digest algorithm */