]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[crypto] Parse OCSP responder URI from X.509 certificate
authorMichael Brown <mcb30@ipxe.org>
Mon, 30 Apr 2012 00:49:01 +0000 (01:49 +0100)
committerMichael Brown <mcb30@ipxe.org>
Fri, 4 May 2012 14:15:34 +0000 (15:15 +0100)
Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/crypto/x509.c
src/include/ipxe/asn1.h
src/include/ipxe/x509.h
src/net/tls.c

index 7c6aab5cea3570c8c23bc5bdeeb097bc1c79211e..a0ed816d770627b0c632ea73cbcbe88523925a9e 100644 (file)
@@ -487,7 +487,7 @@ static int x509_parse_validity ( struct x509_certificate *cert,
  * @ret rc             Return status code
  */
 static int x509_parse_common_name ( struct x509_certificate *cert,
-                                   struct x509_name *name,
+                                   struct x509_string *name,
                                    const struct asn1_cursor *raw ) {
        struct asn1_cursor cursor;
        struct asn1_cursor oid_cursor;
@@ -533,7 +533,7 @@ static int x509_parse_common_name ( struct x509_certificate *cert,
 static int x509_parse_subject ( struct x509_certificate *cert,
                                const struct asn1_cursor *raw ) {
        struct x509_subject *subject = &cert->subject;
-       struct x509_name *name = &subject->name;
+       struct x509_string *name = &subject->name;
        int rc;
 
        /* Record raw subject */
@@ -750,7 +750,7 @@ static int x509_parse_extended_key_usage ( struct x509_certificate *cert,
        memcpy ( &cursor, raw, sizeof ( cursor ) );
        asn1_enter ( &cursor, ASN1_SEQUENCE );
 
-       /* Parse each extension in turn */
+       /* Parse each extended key usage in turn */
        while ( cursor.len ) {
                if ( ( rc = x509_parse_key_purpose ( cert, &cursor ) ) != 0 )
                        return rc;
@@ -760,14 +760,145 @@ static int x509_parse_extended_key_usage ( struct x509_certificate *cert,
        return 0;
 }
 
+/**
+ * Parse X.509 certificate OCSP access method
+ *
+ * @v cert             X.509 certificate
+ * @v raw              ASN.1 cursor
+ * @ret rc             Return status code
+ */
+static int x509_parse_ocsp ( struct x509_certificate *cert,
+                            const struct asn1_cursor *raw ) {
+       struct x509_ocsp_responder *ocsp = &cert->extensions.auth_info.ocsp;
+       struct asn1_cursor cursor;
+       int rc;
+
+       /* Enter accessLocation */
+       memcpy ( &cursor, raw, sizeof ( cursor ) );
+       if ( ( rc = asn1_enter ( &cursor, ASN1_IMPLICIT_TAG ( 6 ) ) ) != 0 ) {
+               DBGC ( cert, "X509 %p OCSP does not contain "
+                      "uniformResourceIdentifier:\n", cert );
+               DBGC_HDA ( cert, 0, raw->data, raw->len );
+               return rc;
+       }
+
+       /* Record URI */
+       ocsp->uri.data = cursor.data;
+       ocsp->uri.len = cursor.len;
+       DBGC ( cert, "X509 %p OCSP URI is:\n", cert );
+       DBGC_HDA ( cert, 0, ocsp->uri.data, ocsp->uri.len );
+
+       return 0;
+}
+
+/** "id-ad-ocsp" object identifier */
+static uint8_t oid_ad_ocsp[] = { ASN1_OID_OCSP };
+
+/** Supported access methods */
+static struct x509_access_method x509_access_methods[] = {
+       {
+               .name = "OCSP",
+               .oid = ASN1_OID_CURSOR ( oid_ad_ocsp ),
+               .parse = x509_parse_ocsp,
+       },
+};
+
+/**
+ * Identify X.509 access method by OID
+ *
+ * @v oid              OID
+ * @ret method         Access method, or NULL
+ */
+static struct x509_access_method *
+x509_find_access_method ( const struct asn1_cursor *oid ) {
+       struct x509_access_method *method;
+       unsigned int i;
+
+       for ( i = 0 ; i < ( sizeof ( x509_access_methods ) /
+                           sizeof ( x509_access_methods[0] ) ) ; i++ ) {
+               method = &x509_access_methods[i];
+               if ( asn1_compare ( &method->oid, oid ) == 0 )
+                       return method;
+       }
+
+       return NULL;
+}
+
+/**
+ * Parse X.509 certificate access description
+ *
+ * @v cert             X.509 certificate
+ * @v raw              ASN.1 cursor
+ * @ret rc             Return status code
+ */
+static int x509_parse_access_description ( struct x509_certificate *cert,
+                                          const struct asn1_cursor *raw ) {
+       struct asn1_cursor cursor;
+       struct asn1_cursor subcursor;
+       struct x509_access_method *method;
+       int rc;
+
+       /* Enter keyPurposeId */
+       memcpy ( &cursor, raw, sizeof ( cursor ) );
+       asn1_enter ( &cursor, ASN1_SEQUENCE );
+
+       /* Try to identify access method */
+       memcpy ( &subcursor, &cursor, sizeof ( subcursor ) );
+       asn1_enter ( &subcursor, ASN1_OID );
+       method = x509_find_access_method ( &subcursor );
+       asn1_skip_any ( &cursor );
+       DBGC ( cert, "X509 %p found access method %s\n",
+              cert, ( method ? method->name : "<unknown>" ) );
+
+       /* Parse access location, if applicable */
+       if ( method && ( ( rc = method->parse ( cert, &cursor ) ) != 0 ) )
+               return rc;
+
+       return 0;
+}
+
+/**
+ * Parse X.509 certificate authority information access
+ *
+ * @v cert             X.509 certificate
+ * @v raw              ASN.1 cursor
+ * @ret rc             Return status code
+ */
+static int x509_parse_authority_info_access ( struct x509_certificate *cert,
+                                             const struct asn1_cursor *raw ) {
+       struct asn1_cursor cursor;
+       int rc;
+
+       /* Enter authorityInfoAccess */
+       memcpy ( &cursor, raw, sizeof ( cursor ) );
+       asn1_enter ( &cursor, ASN1_SEQUENCE );
+
+       /* Parse each access description in turn */
+       while ( cursor.len ) {
+               if ( ( rc = x509_parse_access_description ( 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 };
+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 };
+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 };
+static uint8_t oid_ce_ext_key_usage[] =
+       { ASN1_OID_EXTKEYUSAGE };
+
+/** "id-pe-authorityInfoAccess" object identifier */
+static uint8_t oid_pe_authority_info_access[] =
+       { ASN1_OID_AUTHORITYINFOACCESS };
 
 /** Supported certificate extensions */
 static struct x509_extension x509_extensions[] = {
@@ -786,6 +917,11 @@ static struct x509_extension x509_extensions[] = {
                .oid = ASN1_OID_CURSOR ( oid_ce_ext_key_usage ),
                .parse = x509_parse_extended_key_usage,
        },
+       {
+               .name = "authorityInfoAccess",
+               .oid = ASN1_OID_CURSOR ( oid_pe_authority_info_access ),
+               .parse = x509_parse_authority_info_access,
+       },
 };
 
 /**
index d83308a2e1809092e7a07a1761868f2154798af9..1c433c5e7321240e02d87555957f2e0bd5192504 100644 (file)
@@ -53,6 +53,9 @@ struct asn1_cursor {
 /** ASN.1 set */
 #define ASN1_SET 0x31
 
+/** ASN.1 implicit tag */
+#define ASN1_IMPLICIT_TAG( number) ( 0x80 | (number) )
+
 /** ASN.1 explicit tag */
 #define ASN1_EXPLICIT_TAG( number) ( 0xa0 | (number) )
 
@@ -158,6 +161,20 @@ struct asn1_cursor {
        ASN1_OID_TRIPLE ( 113549 ), ASN1_OID_SINGLE ( 1 ),      \
        ASN1_OID_SINGLE ( 7 ), ASN1_OID_SINGLE ( 2 )
 
+/** ASN.1 OID for id-pe-authorityInfoAccess (1.3.6.1.5.5.7.1.1) */
+#define ASN1_OID_AUTHORITYINFOACCESS                           \
+       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 ( 1 ), ASN1_OID_SINGLE ( 1 )
+
+/** ASN.1 OID for id-ad-ocsp (1.3.6.1.5.5.7.48.1) */
+#define ASN1_OID_OCSP                                          \
+       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 ( 48 ), ASN1_OID_SINGLE ( 1 )
+
 /** Define an ASN.1 cursor containing an OID */
 #define ASN1_OID_CURSOR( oid_value ) {                         \
                .data = oid_value,                              \
index 09e1800755de2061fd6c66ab21bc5bd84f9dae75..271ed2e4493a278b630954fbe1b007b180ba8a19 100644 (file)
@@ -50,9 +50,9 @@ struct x509_validity {
        struct x509_time not_after;
 };
 
-/** An X.509 name */
-struct x509_name {
-       /** Name (not NUL-terminated) */
+/** An X.509 string */
+struct x509_string {
+       /** String (not NUL-terminated) */
        const void *data;
        /** Length of name */
        size_t len;
@@ -71,7 +71,7 @@ struct x509_subject {
        /** Raw subject */
        struct asn1_cursor raw;
        /** Common name */
-       struct x509_name name;
+       struct x509_string name;
        /** Public key information */
        struct x509_public_key public_key;
 };
@@ -128,6 +128,18 @@ enum x509_extended_key_usage_bits {
        X509_CODE_SIGNING = 0x0001,
 };
 
+/** X.509 certificate OCSP responder */
+struct x509_ocsp_responder {
+       /** URI */
+       struct x509_string uri;
+};
+
+/** X.509 certificate authority information access */
+struct x509_authority_info_access {
+       /** OCSP responder */
+       struct x509_ocsp_responder ocsp;
+};
+
 /** An X.509 certificate extensions set */
 struct x509_extensions {
        /** Basic constraints */
@@ -136,6 +148,8 @@ struct x509_extensions {
        struct x509_key_usage usage;
        /** Extended key usage */
        struct x509_extended_key_usage ext_usage;
+       /** Authority information access */
+       struct x509_authority_info_access auth_info;
 };
 
 /** An X.509 certificate */
@@ -188,6 +202,22 @@ struct x509_key_purpose {
        unsigned int bits;
 };
 
+/** An X.509 access method */
+struct x509_access_method {
+       /** Name */
+       const char *name;
+       /** Object identifier */
+       struct asn1_cursor oid;
+       /** Parse access method
+        *
+        * @v cert              X.509 certificate
+        * @v raw               ASN.1 cursor
+        * @ret rc              Return status code
+        */
+       int ( * parse ) ( struct x509_certificate *cert,
+                         const struct asn1_cursor *raw );
+};
+
 /** An X.509 root certificate store */
 struct x509_root {
        /** Fingerprint digest algorithm */
index 0f11fbe2f4e31a482a4ee1874898c223c319e155..3d46a2c7a253e150549f79892a53c42cfa2b6781 100644 (file)
@@ -1347,7 +1347,7 @@ static int tls_new_certificate ( struct tls_session *tls,
        struct pubkey_algorithm *pubkey = cipherspec->suite->pubkey;
        struct tls_certificate_context context;
        struct x509_certificate cert;
-       struct x509_name *name = &cert.subject.name;
+       struct x509_string *name = &cert.subject.name;
        struct x509_public_key *key = &cert.subject.public_key;
        time_t now;
        int rc;