]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[crypto] Remove dynamically-allocated storage for certificate name
authorMichael Brown <mcb30@ipxe.org>
Tue, 25 Mar 2014 15:01:32 +0000 (15:01 +0000)
committerMichael Brown <mcb30@ipxe.org>
Tue, 25 Mar 2014 16:30:43 +0000 (16:30 +0000)
iPXE currently allocates a copy the certificate's common name as a
string.  This string is used by the TLS and CMS code to check
certificate names against an expected name, and also appears in
debugging messages.

Provide a function x509_check_name() to centralise certificate name
checking (in preparation for adding subjectAlternativeName support),
and a function x509_name() to provide a name to be used in debugging
messages, and remove the dynamically allocated string.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/crypto/cms.c
src/crypto/ocsp.c
src/crypto/x509.c
src/include/ipxe/x509.h
src/net/tls.c
src/net/validator.c

index c0c8d144f1070401530721d68dfab3abaffd090a..6191d1bbe179fa251db136c5914f35c351591522 100644 (file)
@@ -130,7 +130,7 @@ static int cms_parse_certificates ( struct cms_signature *sig,
                }
                cert = x509_last ( sig->certificates );
                DBGC ( sig, "CMS %p found certificate %s\n",
-                      sig, cert->subject.name );
+                      sig, x509_name ( cert ) );
 
                /* Move to next certificate */
                asn1_skip_any ( &cursor );
@@ -680,8 +680,7 @@ int cms_verify ( struct cms_signature *sig, userptr_t data, size_t len,
        /* Verify using all signerInfos */
        list_for_each_entry ( info, &sig->info, list ) {
                cert = x509_first ( info->chain );
-               if ( name && ( ( cert->subject.name == NULL ) ||
-                              ( strcmp ( cert->subject.name, name ) != 0 ) ) )
+               if ( name && ( x509_check_name ( cert, name ) != 0 ) )
                        continue;
                if ( ( rc = cms_verify_signer_info ( sig, info, data, len,
                                                     time, root ) ) != 0 )
index 27c0080cb11a371256fb4aac45506ee57190cb2c..1b39fd0d40455e02546a882fbb19a856109cf4f2 100644 (file)
@@ -177,11 +177,11 @@ static int ocsp_request ( struct ocsp_check *ocsp ) {
                      asn1_wrap ( builder, ASN1_SEQUENCE ),
                      asn1_wrap ( builder, ASN1_SEQUENCE ) ) ) != 0 ) {
                DBGC ( ocsp, "OCSP %p \"%s\" could not build request: %s\n",
-                      ocsp, ocsp->cert->subject.name, strerror ( rc ) );
+                      ocsp, x509_name ( ocsp->cert ), strerror ( rc ) );
                return rc;
        }
        DBGC2 ( ocsp, "OCSP %p \"%s\" request is:\n",
-               ocsp, ocsp->cert->subject.name );
+               ocsp, x509_name ( ocsp->cert ) );
        DBGC2_HDA ( ocsp, 0, builder->data, builder->len );
 
        /* Parse certificate ID for comparison with response */
@@ -192,7 +192,7 @@ static int ocsp_request ( struct ocsp_check *ocsp ) {
                      asn1_enter ( cert_id, ASN1_SEQUENCE ),
                      asn1_enter ( cert_id, ASN1_SEQUENCE ) ) ) != 0 ) {
                DBGC ( ocsp, "OCSP %p \"%s\" could not locate certID: %s\n",
-                      ocsp, ocsp->cert->subject.name, strerror ( rc ) );
+                      ocsp, x509_name ( ocsp->cert ), strerror ( rc ) );
                return rc;
        }
 
@@ -218,7 +218,7 @@ static int ocsp_uri_string ( struct ocsp_check *ocsp ) {
        base_uri_string = ocsp->cert->extensions.auth_info.ocsp.uri;
        if ( ! base_uri_string ) {
                DBGC ( ocsp, "OCSP %p \"%s\" has no OCSP URI\n",
-                      ocsp, ocsp->cert->subject.name );
+                      ocsp, x509_name ( ocsp->cert ) );
                rc = -ENOTTY;
                goto err_no_uri;
        }
@@ -250,7 +250,7 @@ static int ocsp_uri_string ( struct ocsp_check *ocsp ) {
                goto err_ocsp_uri;
        }
        DBGC2 ( ocsp, "OCSP %p \"%s\" URI is %s\n",
-               ocsp, ocsp->cert->subject.name, ocsp->uri_string );
+               ocsp, x509_name ( ocsp->cert ), ocsp->uri_string );
 
        /* Success */
        rc = 0;
@@ -327,14 +327,14 @@ static int ocsp_parse_response_status ( struct ocsp_check *ocsp,
        memcpy ( &cursor, raw, sizeof ( cursor ) );
        if ( ( rc = asn1_enter ( &cursor, ASN1_ENUMERATED ) ) != 0 ) {
                DBGC ( ocsp, "OCSP %p \"%s\" could not locate responseStatus: "
-                      "%s\n", ocsp, ocsp->cert->subject.name, strerror ( rc ));
+                      "%s\n", ocsp, x509_name ( ocsp->cert ), strerror ( rc ));
                return rc;
        }
 
        /* Extract response status */
        if ( cursor.len != sizeof ( status ) ) {
                DBGC ( ocsp, "OCSP %p \"%s\" invalid status:\n",
-                      ocsp, ocsp->cert->subject.name );
+                      ocsp, x509_name ( ocsp->cert ) );
                DBGC_HDA ( ocsp, 0, cursor.data, cursor.len );
                return -EINVAL;
        }
@@ -343,7 +343,7 @@ static int ocsp_parse_response_status ( struct ocsp_check *ocsp,
        /* Check response status */
        if ( status != OCSP_STATUS_SUCCESSFUL ) {
                DBGC ( ocsp, "OCSP %p \"%s\" response status %d\n",
-                      ocsp, ocsp->cert->subject.name, status );
+                      ocsp, x509_name ( ocsp->cert ), status );
                return EPROTO_STATUS ( status );
        }
 
@@ -368,7 +368,7 @@ static int ocsp_parse_response_type ( struct ocsp_check *ocsp,
        /* Check responseType is "basic" */
        if ( asn1_compare ( &oid_basic_response_type_cursor, &cursor ) != 0 ) {
                DBGC ( ocsp, "OCSP %p \"%s\" response type not supported:\n",
-                      ocsp, ocsp->cert->subject.name );
+                      ocsp, x509_name ( ocsp->cert ) );
                DBGC_HDA ( ocsp, 0, cursor.data, cursor.len );
                return -ENOTSUP_RESPONSE_TYPE;
        }
@@ -443,17 +443,17 @@ static int ocsp_parse_responder_id ( struct ocsp_check *ocsp,
        switch ( type ) {
        case ASN1_EXPLICIT_TAG ( 1 ) :
                DBGC2 ( ocsp, "OCSP %p \"%s\" responder identified by name\n",
-                       ocsp, ocsp->cert->subject.name );
+                       ocsp, x509_name ( ocsp->cert ) );
                responder->compare = ocsp_compare_responder_name;
                return 0;
        case ASN1_EXPLICIT_TAG ( 2 ) :
                DBGC2 ( ocsp, "OCSP %p \"%s\" responder identified by key "
-                       "hash\n", ocsp, ocsp->cert->subject.name );
+                       "hash\n", ocsp, x509_name ( ocsp->cert ) );
                responder->compare = ocsp_compare_responder_key_hash;
                return 0;
        default:
                DBGC ( ocsp, "OCSP %p \"%s\" unsupported responder ID type "
-                      "%d\n", ocsp, ocsp->cert->subject.name, type );
+                      "%d\n", ocsp, x509_name ( ocsp->cert ), type );
                return -ENOTSUP_RESPONDER_ID;
        }
 }
@@ -474,7 +474,7 @@ static int ocsp_parse_cert_id ( struct ocsp_check *ocsp,
        asn1_shrink_any ( &cursor );
        if ( asn1_compare ( &cursor, &ocsp->request.cert_id ) != 0 ) {
                DBGC ( ocsp, "OCSP %p \"%s\" certID mismatch:\n",
-                      ocsp, ocsp->cert->subject.name );
+                      ocsp, x509_name ( ocsp->cert ) );
                DBGC_HDA ( ocsp, 0, ocsp->request.cert_id.data,
                           ocsp->request.cert_id.len );
                DBGC_HDA ( ocsp, 0, cursor.data, cursor.len );
@@ -512,7 +512,7 @@ static int ocsp_parse_responses ( struct ocsp_check *ocsp,
        /* Check certStatus */
        if ( asn1_type ( &cursor ) != ASN1_IMPLICIT_TAG ( 0 ) ) {
                DBGC ( ocsp, "OCSP %p \"%s\" non-good certStatus:\n",
-                      ocsp, ocsp->cert->subject.name );
+                      ocsp, x509_name ( ocsp->cert ) );
                DBGC_HDA ( ocsp, 0, cursor.data, cursor.len );
                return -EACCES_CERT_STATUS;
        }
@@ -522,11 +522,11 @@ static int ocsp_parse_responses ( struct ocsp_check *ocsp,
        if ( ( rc = asn1_generalized_time ( &cursor,
                                            &response->this_update ) ) != 0 ) {
                DBGC ( ocsp, "OCSP %p \"%s\" could not parse thisUpdate: %s\n",
-                      ocsp, ocsp->cert->subject.name, strerror ( rc ) );
+                      ocsp, x509_name ( ocsp->cert ), strerror ( rc ) );
                return rc;
        }
        DBGC2 ( ocsp, "OCSP %p \"%s\" this update was at time %lld\n",
-               ocsp, ocsp->cert->subject.name, response->this_update );
+               ocsp, x509_name ( ocsp->cert ), response->this_update );
        asn1_skip_any ( &cursor );
 
        /* Parse nextUpdate, if present */
@@ -536,11 +536,11 @@ static int ocsp_parse_responses ( struct ocsp_check *ocsp,
                                             &response->next_update ) ) != 0 ) {
                        DBGC ( ocsp, "OCSP %p \"%s\" could not parse "
                               "nextUpdate: %s\n", ocsp,
-                              ocsp->cert->subject.name, strerror ( rc ) );
+                              x509_name ( ocsp->cert ), strerror ( rc ) );
                        return rc;
                }
                DBGC2 ( ocsp, "OCSP %p \"%s\" next update is at time %lld\n",
-                       ocsp, ocsp->cert->subject.name, response->next_update );
+                       ocsp, x509_name ( ocsp->cert ), response->next_update );
        } else {
                /* If no nextUpdate is present, this indicates that
                 * "newer revocation information is available all the
@@ -550,7 +550,7 @@ static int ocsp_parse_responses ( struct ocsp_check *ocsp,
                 * time and it would still be valid.
                 */
                DBGC ( ocsp, "OCSP %p \"%s\" responder is a moron\n",
-                      ocsp, ocsp->cert->subject.name );
+                      ocsp, x509_name ( ocsp->cert ) );
                response->next_update = time ( NULL );
        }
 
@@ -630,7 +630,7 @@ static int ocsp_parse_certs ( struct ocsp_check *ocsp,
                                               &cert ) ) != 0 ) {
                        DBGC ( ocsp, "OCSP %p \"%s\" could not parse "
                               "certificate: %s\n", ocsp,
-                              ocsp->cert->subject.name, strerror ( rc ) );
+                              x509_name ( ocsp->cert ), strerror ( rc ) );
                        DBGC_HDA ( ocsp, 0, cursor.data, cursor.len );
                        return rc;
                }
@@ -638,9 +638,10 @@ static int ocsp_parse_certs ( struct ocsp_check *ocsp,
                /* Use if this certificate matches the responder ID */
                if ( response->responder.compare ( ocsp, cert ) == 0 ) {
                        response->signer = cert;
-                       DBGC2 ( ocsp, "OCSP %p \"%s\" response is signed by "
-                               "\"%s\"\n", ocsp, ocsp->cert->subject.name,
-                               response->signer->subject.name );
+                       DBGC2 ( ocsp, "OCSP %p \"%s\" response is signed by ",
+                               ocsp, x509_name ( ocsp->cert ) );
+                       DBGC2 ( ocsp, "\"%s\"\n",
+                               x509_name ( response->signer ) );
                        return 0;
                }
 
@@ -650,7 +651,7 @@ static int ocsp_parse_certs ( struct ocsp_check *ocsp,
        }
 
        DBGC ( ocsp, "OCSP %p \"%s\" missing responder certificate\n",
-              ocsp, ocsp->cert->subject.name );
+              ocsp, x509_name ( ocsp->cert ) );
        return -EACCES_NO_RESPONDER;
 }
 
@@ -682,17 +683,17 @@ static int ocsp_parse_basic_response ( struct ocsp_check *ocsp,
        if ( ( rc = asn1_signature_algorithm ( &cursor, algorithm ) ) != 0 ) {
                DBGC ( ocsp, "OCSP %p \"%s\" cannot parse signature "
                       "algorithm: %s\n",
-                      ocsp, ocsp->cert->subject.name, strerror ( rc ) );
+                      ocsp, x509_name ( ocsp->cert ), strerror ( rc ) );
                return rc;
        }
        DBGC2 ( ocsp, "OCSP %p \"%s\" signature algorithm is %s\n",
-               ocsp, ocsp->cert->subject.name, (*algorithm)->name );
+               ocsp, x509_name ( ocsp->cert ), (*algorithm)->name );
        asn1_skip_any ( &cursor );
 
        /* Parse signature */
        if ( ( rc = asn1_integral_bit_string ( &cursor, signature ) ) != 0 ) {
                DBGC ( ocsp, "OCSP %p \"%s\" cannot parse signature: %s\n",
-                      ocsp, ocsp->cert->subject.name, strerror ( rc ) );
+                      ocsp, x509_name ( ocsp->cert ), strerror ( rc ) );
                return rc;
        }
        asn1_skip_any ( &cursor );
@@ -836,7 +837,7 @@ static int ocsp_check_signature ( struct ocsp_check *ocsp,
        if ( ( rc = pubkey_init ( pubkey, pubkey_ctx, public_key->raw.data,
                                  public_key->raw.len ) ) != 0 ) {
                DBGC ( ocsp, "OCSP %p \"%s\" could not initialise public key: "
-                      "%s\n", ocsp, ocsp->cert->subject.name, strerror ( rc ));
+                      "%s\n", ocsp, x509_name ( ocsp->cert ), strerror ( rc ));
                goto err_init;
        }
 
@@ -845,12 +846,12 @@ static int ocsp_check_signature ( struct ocsp_check *ocsp,
                                    response->signature.data,
                                    response->signature.len ) ) != 0 ) {
                DBGC ( ocsp, "OCSP %p \"%s\" signature verification failed: "
-                      "%s\n", ocsp, ocsp->cert->subject.name, strerror ( rc ));
+                      "%s\n", ocsp, x509_name ( ocsp->cert ), strerror ( rc ));
                goto err_verify;
        }
 
        DBGC2 ( ocsp, "OCSP %p \"%s\" signature is correct\n",
-               ocsp, ocsp->cert->subject.name );
+               ocsp, x509_name ( ocsp->cert ) );
 
  err_verify:
        pubkey_final ( pubkey, pubkey_ctx );
@@ -892,10 +893,10 @@ int ocsp_validate ( struct ocsp_check *ocsp, time_t time ) {
                x509_invalidate ( signer );
                if ( ( rc = x509_validate ( signer, ocsp->issuer, time,
                                            &ocsp_root ) ) != 0 ) {
-                       DBGC ( ocsp, "OCSP %p \"%s\" could not validate "
-                              "signer \"%s\": %s\n", ocsp,
-                              ocsp->cert->subject.name, signer->subject.name,
-                              strerror ( rc ) );
+                       DBGC ( ocsp, "OCSP %p \"%s\" could not validate ",
+                              ocsp, x509_name ( ocsp->cert ) );
+                       DBGC ( ocsp, "signer \"%s\": %s\n",
+                              x509_name ( signer ), strerror ( rc ) );
                        return rc;
                }
 
@@ -904,9 +905,10 @@ int ocsp_validate ( struct ocsp_check *ocsp, time_t time ) {
                 */
                if ( ! ( signer->extensions.ext_usage.bits &
                         X509_OCSP_SIGNING ) ) {
-                       DBGC ( ocsp, "OCSP %p \"%s\" signer \"%s\" is "
-                              "not an OCSP-signing certificate\n", ocsp,
-                              ocsp->cert->subject.name, signer->subject.name );
+                       DBGC ( ocsp, "OCSP %p \"%s\" ",
+                              ocsp, x509_name ( ocsp->cert ) );
+                       DBGC ( ocsp, "signer \"%s\" is not an OCSP-signing "
+                              "certificate\n", x509_name ( signer ) );
                        return -EACCES_NON_OCSP_SIGNING;
                }
        }
@@ -920,16 +922,16 @@ int ocsp_validate ( struct ocsp_check *ocsp, time_t time ) {
         */
        if ( response->this_update > ( time + X509_ERROR_MARGIN_TIME ) ) {
                DBGC ( ocsp, "OCSP %p \"%s\" response is not yet valid (at "
-                      "time %lld)\n", ocsp, ocsp->cert->subject.name, time );
+                      "time %lld)\n", ocsp, x509_name ( ocsp->cert ), time );
                return -EACCES_STALE;
        }
        if ( response->next_update < ( time - X509_ERROR_MARGIN_TIME ) ) {
                DBGC ( ocsp, "OCSP %p \"%s\" response is stale (at time "
-                      "%lld)\n", ocsp, ocsp->cert->subject.name, time );
+                      "%lld)\n", ocsp, x509_name ( ocsp->cert ), time );
                return -EACCES_STALE;
        }
        DBGC2 ( ocsp, "OCSP %p \"%s\" response is valid (at time %lld)\n",
-               ocsp, ocsp->cert->subject.name, time );
+               ocsp, x509_name ( ocsp->cert ), time );
 
        /* Mark certificate as passing OCSP verification */
        ocsp->cert->extensions.auth_info.ocsp.good = 1;
@@ -938,11 +940,12 @@ int ocsp_validate ( struct ocsp_check *ocsp, time_t time ) {
        if ( ( rc = x509_validate ( ocsp->cert, ocsp->issuer, time,
                                    &ocsp_root ) ) != 0 ) {
                DBGC ( ocsp, "OCSP %p \"%s\" could not validate certificate: "
-                      "%s\n", ocsp, ocsp->cert->subject.name, strerror ( rc ));
+                      "%s\n", ocsp, x509_name ( ocsp->cert ), strerror ( rc ));
                return rc;
        }
-       DBGC ( ocsp, "OCSP %p \"%s\" successfully validated using \"%s\"\n",
-              ocsp, ocsp->cert->subject.name, signer->subject.name );
+       DBGC ( ocsp, "OCSP %p \"%s\" successfully validated ",
+              ocsp, x509_name ( ocsp->cert ) );
+       DBGC ( ocsp, "using \"%s\"\n", x509_name ( signer ) );
 
        return 0;
 }
index d54124c531a9a4db1574b29badda3d7019bc2980..eb7d50290225bd46306ba29e7852d7e61870468a 100644 (file)
@@ -103,10 +103,33 @@ FILE_LICENCE ( GPL2_OR_LATER );
        __einfo_error ( EINFO_EACCES_OCSP_REQUIRED )
 #define EINFO_EACCES_OCSP_REQUIRED \
        __einfo_uniqify ( EINFO_EACCES, 0x09, "OCSP check required" )
+#define EACCES_WRONG_NAME \
+       __einfo_error ( EINFO_EACCES_WRONG_NAME )
+#define EINFO_EACCES_WRONG_NAME \
+       __einfo_uniqify ( EINFO_EACCES, 0x0a, "Incorrect certificate name" )
 
 /** Certificate cache */
 static LIST_HEAD ( x509_cache );
 
+/**
+ * Get X.509 certificate name (for debugging)
+ *
+ * @v cert             X.509 certificate
+ * @ret name           Name (for debugging)
+ */
+const char * x509_name ( struct x509_certificate *cert ) {
+       struct asn1_cursor *common_name = &cert->subject.common_name;
+       static char buf[64];
+       size_t len;
+
+       len = common_name->len;
+       if ( len > ( sizeof ( buf ) - 1 /* NUL */ ) )
+               len = ( sizeof ( buf ) - 1 /* NUL */ );
+       memcpy ( buf, common_name->data, len );
+       buf[len] = '\0';
+       return buf;
+}
+
 /**
  * Free X.509 certificate
  *
@@ -117,7 +140,6 @@ static void x509_free ( struct refcnt *refcnt ) {
                container_of ( refcnt, struct x509_certificate, refcnt );
 
        DBGC2 ( cert, "X509 %p freed\n", cert );
-       free ( cert->subject.name );
        free ( cert->extensions.auth_info.ocsp.uri );
        free ( cert );
 }
@@ -292,11 +314,10 @@ static int x509_parse_validity ( struct x509_certificate *cert,
  * Parse X.509 certificate common name
  *
  * @v cert             X.509 certificate
- * @v name             Common name to fill in
  * @v raw              ASN.1 cursor
  * @ret rc             Return status code
  */
-static int x509_parse_common_name ( struct x509_certificate *cert, char **name,
+static int x509_parse_common_name ( struct x509_certificate *cert,
                                    const struct asn1_cursor *raw ) {
        struct asn1_cursor cursor;
        struct asn1_cursor oid_cursor;
@@ -325,19 +346,9 @@ static int x509_parse_common_name ( struct x509_certificate *cert, char **name,
                        return rc;
                }
 
-               /* Allocate and copy name */
-               *name = zalloc ( name_cursor.len + 1 /* NUL */ );
-               if ( ! *name )
-                       return -ENOMEM;
-               memcpy ( *name, name_cursor.data, name_cursor.len );
-
-               /* Check that name contains no NULs */
-               if ( strlen ( *name ) != name_cursor.len ) {
-                       DBGC ( cert, "X509 %p contains malicious commonName:\n",
-                              cert );
-                       DBGC_HDA ( cert, 0, raw->data, raw->len );
-                       return rc;
-               }
+               /* Record common name */
+               memcpy ( &cert->subject.common_name, &name_cursor,
+                        sizeof ( cert->subject.common_name ) );
 
                return 0;
        }
@@ -357,7 +368,6 @@ static int x509_parse_common_name ( struct x509_certificate *cert, char **name,
 static int x509_parse_subject ( struct x509_certificate *cert,
                                const struct asn1_cursor *raw ) {
        struct x509_subject *subject = &cert->subject;
-       char **name = &subject->name;
        int rc;
 
        /* Record raw subject */
@@ -367,9 +377,10 @@ static int x509_parse_subject ( struct x509_certificate *cert,
        DBGC2_HDA ( cert, 0, subject->raw.data, subject->raw.len );
 
        /* Parse common name */
-       if ( ( rc = x509_parse_common_name ( cert, name, raw ) ) != 0 )
+       if ( ( rc = x509_parse_common_name ( cert, raw ) ) != 0 )
                return rc;
-       DBGC2 ( cert, "X509 %p common name is \"%s\":\n", cert, *name );
+       DBGC2 ( cert, "X509 %p common name is \"%s\":\n", cert,
+               x509_name ( cert ) );
 
        return 0;
 }
@@ -1045,7 +1056,7 @@ int x509_certificate ( const void *data, size_t len,
                if ( asn1_compare ( &cursor, &(*cert)->raw ) == 0 ) {
 
                        DBGC2 ( *cert, "X509 %p \"%s\" cache hit\n",
-                               *cert, (*cert)->subject.name );
+                               *cert, x509_name ( *cert ) );
 
                        /* Mark as most recently used */
                        list_del ( &(*cert)->list );
@@ -1109,14 +1120,14 @@ static int x509_check_signature ( struct x509_certificate *cert,
        digest_init ( digest, digest_ctx );
        digest_update ( digest, digest_ctx, cert->tbs.data, cert->tbs.len );
        digest_final ( digest, digest_ctx, digest_out );
-       DBGC2 ( cert, "X509 %p \"%s\" digest:\n", cert, cert->subject.name );
+       DBGC2 ( cert, "X509 %p \"%s\" digest:\n", cert, x509_name ( cert ) );
        DBGC2_HDA ( cert, 0, digest_out, sizeof ( digest_out ) );
 
        /* Check that signature public key algorithm matches signer */
        if ( public_key->algorithm->pubkey != pubkey ) {
                DBGC ( cert, "X509 %p \"%s\" signature algorithm %s does not "
                       "match signer's algorithm %s\n",
-                      cert, cert->subject.name, algorithm->name,
+                      cert, x509_name ( cert ), algorithm->name,
                       public_key->algorithm->name );
                rc = -EINVAL_ALGORITHM_MISMATCH;
                goto err_mismatch;
@@ -1126,14 +1137,14 @@ static int x509_check_signature ( struct x509_certificate *cert,
        if ( ( rc = pubkey_init ( pubkey, pubkey_ctx, public_key->raw.data,
                                  public_key->raw.len ) ) != 0 ) {
                DBGC ( cert, "X509 %p \"%s\" cannot initialise public key: "
-                      "%s\n", cert, cert->subject.name, strerror ( rc ) );
+                      "%s\n", cert, x509_name ( cert ), strerror ( rc ) );
                goto err_pubkey_init;
        }
        if ( ( rc = pubkey_verify ( pubkey, pubkey_ctx, digest, digest_out,
                                    signature->value.data,
                                    signature->value.len ) ) != 0 ) {
                DBGC ( cert, "X509 %p \"%s\" signature verification failed: "
-                      "%s\n", cert, cert->subject.name, strerror ( rc ) );
+                      "%s\n", cert, x509_name ( cert ), strerror ( rc ) );
                goto err_pubkey_verify;
        }
 
@@ -1172,9 +1183,10 @@ int x509_check_issuer ( struct x509_certificate *cert,
         * for some enjoyable ranting on this subject.
         */
        if ( asn1_compare ( &cert->issuer.raw, &issuer->subject.raw ) != 0 ) {
-               DBGC ( cert, "X509 %p \"%s\" issuer does not match X509 %p "
-                      "\"%s\" subject\n", cert, cert->subject.name,
-                      issuer, issuer->subject.name );
+               DBGC ( cert, "X509 %p \"%s\" issuer does not match ",
+                      cert, x509_name ( cert ) );
+               DBGC ( cert, "X509 %p \"%s\" subject\n",
+                      issuer, x509_name ( issuer ) );
                DBGC_HDA ( cert, 0, cert->issuer.raw.data,
                           cert->issuer.raw.len );
                DBGC_HDA ( issuer, 0, issuer->subject.raw.data,
@@ -1184,16 +1196,18 @@ int x509_check_issuer ( struct x509_certificate *cert,
 
        /* Check that issuer is allowed to sign certificates */
        if ( ! issuer->extensions.basic.ca ) {
-               DBGC ( issuer, "X509 %p \"%s\" cannot sign X509 %p \"%s\": "
-                      "not a CA certificate\n", issuer, issuer->subject.name,
-                      cert, cert->subject.name );
+               DBGC ( issuer, "X509 %p \"%s\" cannot sign ",
+                      issuer, x509_name ( issuer ) );
+               DBGC ( issuer, "X509 %p \"%s\": not a CA certificate\n",
+                      cert, x509_name ( cert ) );
                return -EACCES_NOT_CA;
        }
        if ( issuer->extensions.usage.present &&
             ( ! ( issuer->extensions.usage.bits & X509_KEY_CERT_SIGN ) ) ) {
-               DBGC ( issuer, "X509 %p \"%s\" cannot sign X509 %p \"%s\": "
-                      "no keyCertSign usage\n", issuer, issuer->subject.name,
-                      cert, cert->subject.name );
+               DBGC ( issuer, "X509 %p \"%s\" cannot sign ",
+                      issuer, x509_name ( issuer ) );
+               DBGC ( issuer, "X509 %p \"%s\": no keyCertSign usage\n",
+                      cert, x509_name ( cert ) );
                return -EACCES_KEY_USAGE;
        }
 
@@ -1243,14 +1257,14 @@ int x509_check_root ( struct x509_certificate *cert, struct x509_root *root ) {
                if ( memcmp ( fingerprint, root_fingerprint,
                              sizeof ( fingerprint ) ) == 0 ) {
                        DBGC ( cert, "X509 %p \"%s\" is a root certificate\n",
-                              cert, cert->subject.name );
+                              cert, x509_name ( cert ) );
                        return 0;
                }
                root_fingerprint += sizeof ( fingerprint );
        }
 
        DBGC2 ( cert, "X509 %p \"%s\" is not a root certificate\n",
-               cert, cert->subject.name );
+               cert, x509_name ( cert ) );
        return -ENOENT;
 }
 
@@ -1267,17 +1281,17 @@ int x509_check_time ( struct x509_certificate *cert, time_t time ) {
        /* Check validity period */
        if ( validity->not_before.time > ( time + X509_ERROR_MARGIN_TIME ) ) {
                DBGC ( cert, "X509 %p \"%s\" is not yet valid (at time %lld)\n",
-                      cert, cert->subject.name, time );
+                      cert, x509_name ( cert ), time );
                return -EACCES_EXPIRED;
        }
        if ( validity->not_after.time < ( time - X509_ERROR_MARGIN_TIME ) ) {
                DBGC ( cert, "X509 %p \"%s\" has expired (at time %lld)\n",
-                      cert, cert->subject.name, time );
+                      cert, x509_name ( cert ), time );
                return -EACCES_EXPIRED;
        }
 
        DBGC2 ( cert, "X509 %p \"%s\" is valid (at time %lld)\n",
-               cert, cert->subject.name, time );
+               cert, x509_name ( cert ), time );
        return 0;
 }
 
@@ -1324,15 +1338,15 @@ int x509_validate ( struct x509_certificate *cert,
        /* Fail unless we have an issuer */
        if ( ! issuer ) {
                DBGC2 ( cert, "X509 %p \"%s\" has no issuer\n",
-                       cert, cert->subject.name );
+                       cert, x509_name ( cert ) );
                return -EACCES_UNTRUSTED;
        }
 
        /* Fail unless issuer has already been validated */
        if ( ! issuer->valid ) {
-               DBGC ( cert, "X509 %p \"%s\" issuer %p \"%s\" has not yet "
-                      "been validated\n", cert, cert->subject.name,
-                      issuer, issuer->subject.name );
+               DBGC ( cert, "X509 %p \"%s\" ", cert, x509_name ( cert ) );
+               DBGC ( cert, "issuer %p \"%s\" has not yet been validated\n",
+                      issuer, x509_name ( issuer ) );
                return -EACCES_OUT_OF_ORDER;
        }
 
@@ -1342,9 +1356,9 @@ int x509_validate ( struct x509_certificate *cert,
 
        /* Fail if path length constraint is violated */
        if ( issuer->path_remaining == 0 ) {
-               DBGC ( cert, "X509 %p \"%s\" issuer %p \"%s\" path length "
-                      "exceeded\n", cert, cert->subject.name,
-                      issuer, issuer->subject.name );
+               DBGC ( cert, "X509 %p \"%s\" ", cert, x509_name ( cert ) );
+               DBGC ( cert, "issuer %p \"%s\" path length exceeded\n",
+                      issuer, x509_name ( issuer ) );
                return -EACCES_PATH_LEN;
        }
 
@@ -1352,7 +1366,7 @@ int x509_validate ( struct x509_certificate *cert,
        if ( cert->extensions.auth_info.ocsp.uri &&
             ( ! cert->extensions.auth_info.ocsp.good ) ) {
                DBGC ( cert, "X509 %p \"%s\" requires an OCSP check\n",
-                      cert, cert->subject.name );
+                      cert, x509_name ( cert ) );
                return -EACCES_OCSP_REQUIRED;
        }
 
@@ -1365,9 +1379,31 @@ int x509_validate ( struct x509_certificate *cert,
        /* Mark certificate as valid */
        cert->valid = 1;
 
-       DBGC ( cert, "X509 %p \"%s\" successfully validated using issuer %p "
-              "\"%s\"\n", cert, cert->subject.name,
-              issuer, issuer->subject.name );
+       DBGC ( cert, "X509 %p \"%s\" successfully validated using ",
+              cert, x509_name ( cert ) );
+       DBGC ( cert, "issuer %p \"%s\"\n", issuer, x509_name ( issuer ) );
+       return 0;
+}
+
+/**
+ * Check X.509 certificate name
+ *
+ * @v cert             X.509 certificate
+ * @v name             Name
+ * @ret rc             Return status code
+ */
+int x509_check_name ( struct x509_certificate *cert, const char *name ) {
+       struct asn1_cursor *common_name = &cert->subject.common_name;
+       size_t len = strlen ( name );
+
+       /* Check commonName */
+       if ( ! ( ( len == common_name->len ) &&
+                ( memcmp ( name, common_name->data, len ) == 0 ) ) ) {
+               DBGC ( cert, "X509 %p \"%s\" does not match name \"%s\"\n",
+                      cert, x509_name ( cert ), name );
+               return -EACCES_WRONG_NAME;
+       }
+
        return 0;
 }
 
@@ -1435,7 +1471,7 @@ int x509_append ( struct x509_chain *chain, struct x509_certificate *cert ) {
        link->cert = x509_get ( cert );
        list_add_tail ( &link->list, &chain->links );
        DBGC ( chain, "X509 chain %p added X509 %p \"%s\"\n",
-              chain, cert, cert->subject.name );
+              chain, cert, x509_name ( cert ) );
 
        return 0;
 }
index a47942a75e992ad7f0b71ed5b01d09f7a16aa489..3e4bcd2059f8d258ae629fac1b8e28538aef8df3 100644 (file)
@@ -65,7 +65,7 @@ struct x509_subject {
        /** Raw subject */
        struct asn1_cursor raw;
        /** Common name */
-       char *name;
+       struct asn1_cursor common_name;
        /** Public key information */
        struct x509_public_key public_key;
 };
@@ -330,11 +330,14 @@ struct x509_root {
        const void *fingerprints;
 };
 
+extern const char * x509_name ( struct x509_certificate *cert );
+
 extern int x509_certificate ( const void *data, size_t len,
                              struct x509_certificate **cert );
 extern int x509_validate ( struct x509_certificate *cert,
                           struct x509_certificate *issuer,
                           time_t time, struct x509_root *root );
+extern int x509_check_name ( struct x509_certificate *cert, const char *name );
 
 extern struct x509_chain * x509_alloc_chain ( void );
 extern int x509_append ( struct x509_chain *chain,
index 5e18f72665cdd5fd56bc272ac64bb6aaa1e29357..742a7c0b787e8b301d5fc19eb0deed430021332f 100644 (file)
@@ -49,10 +49,6 @@ FILE_LICENCE ( GPL2_OR_LATER );
 #include <ipxe/tls.h>
 
 /* Disambiguate the various error causes */
-#define EACCES_WRONG_NAME __einfo_error ( EINFO_EACCES_WRONG_NAME )
-#define EINFO_EACCES_WRONG_NAME                                                \
-       __einfo_uniqify ( EINFO_EACCES, 0x02,                           \
-                         "Incorrect server name" )
 #define EINVAL_CHANGE_CIPHER __einfo_error ( EINFO_EINVAL_CHANGE_CIPHER )
 #define EINFO_EINVAL_CHANGE_CIPHER                                     \
        __einfo_uniqify ( EINFO_EINVAL, 0x01,                           \
@@ -1479,7 +1475,7 @@ static int tls_parse_chain ( struct tls_session *tls,
                }
                cert = x509_last ( tls->chain );
                DBGC ( tls, "TLS %p found certificate %s\n",
-                      tls, cert->subject.name );
+                      tls, x509_name ( cert ) );
 
                /* Move to next certificate in list */
                data = next;
@@ -2454,11 +2450,9 @@ static void tls_validator_done ( struct tls_session *tls, int rc ) {
        assert ( cert != NULL );
 
        /* Verify server name */
-       if ( ( cert->subject.name == NULL ) ||
-            ( strcmp ( cert->subject.name, tls->name ) != 0 ) ) {
-               DBGC ( tls, "TLS %p server name incorrect (expected %s, got "
-                      "%s)\n", tls, tls->name, cert->subject.name );
-               rc = -EACCES_WRONG_NAME;
+       if ( ( rc = x509_check_name ( cert, tls->name ) ) != 0 ) {
+               DBGC ( tls, "TLS %p server certificate does not match %s: %s\n",
+                      tls, tls->name, strerror ( rc ) );
                goto err;
        }
 
index 1de3bb9d1f653f3629235bc120b2979bff97c9eb..7913ed64f2ba1a0b669ca1678b0c884d37e2498a 100644 (file)
@@ -179,7 +179,7 @@ static int validator_append ( struct validator *validator,
                }
                cert = x509_last ( certs );
                DBGC ( validator, "VALIDATOR %p found certificate %s\n",
-                      validator, cert->subject.name );
+                      validator, x509_name ( cert ) );
 
                /* Move to next certificate */
                asn1_skip_any ( &cursor );