diff options
author | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2014-09-10 16:55:05 +0200 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2014-09-15 14:04:33 +0200 |
commit | eb040b8297510c27d644d1f6b961a0bc246751c2 (patch) | |
tree | bbe3ff1ee413c894988b14ef6200bde667947aa2 | |
parent | 65b9475e5d1165a0c9f5351663032989ffa1df9d (diff) | |
download | gnutls-eb040b8297510c27d644d1f6b961a0bc246751c2.tar.gz |
check the key purpose of the CA certificate when in pkcs11 cert validation
-rw-r--r-- | lib/x509/verify-high.c | 17 | ||||
-rw-r--r-- | lib/x509/verify.c | 48 | ||||
-rw-r--r-- | lib/x509/x509_int.h | 1 |
3 files changed, 57 insertions, 9 deletions
diff --git a/lib/x509/verify-high.c b/lib/x509/verify-high.c index b6ea887745..fc5d301dd8 100644 --- a/lib/x509/verify-high.c +++ b/lib/x509/verify-high.c @@ -862,6 +862,14 @@ gnutls_x509_trust_list_verify_crt2(gnutls_x509_trust_list_t list, if (cert_list == NULL || cert_list_size < 1) return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + for (i=0;i<elements;i++) { + if (data[i].type == GNUTLS_DT_DNS_HOSTNAME) { + hostname = (void*)data[i].data; + } else if (data[i].type == GNUTLS_DT_KEY_PURPOSE_OID) { + purpose = (void*)data[i].data; + } + } + if (!(flags & GNUTLS_VERIFY_DO_NOT_ALLOW_UNSORTED_CHAIN)) cert_list = sort_clist(sorted, cert_list, &cert_list_size); @@ -891,6 +899,7 @@ gnutls_x509_trust_list_verify_crt2(gnutls_x509_trust_list_t list, *voutput = _gnutls_pkcs11_verify_crt_status(list->pkcs11_token, cert_list, cert_list_size, + purpose!=NULL?purpose:GNUTLS_KP_TLS_WWW_SERVER, flags, func); } else #endif @@ -964,14 +973,6 @@ gnutls_x509_trust_list_verify_crt2(gnutls_x509_trust_list_t list, } } - for (i=0;i<elements;i++) { - if (data[i].type == GNUTLS_DT_DNS_HOSTNAME) { - hostname = (void*)data[i].data; - } else if (data[i].type == GNUTLS_DT_KEY_PURPOSE_OID) { - purpose = (void*)data[i].data; - } - } - /* check the purpose if given */ if (purpose) do { gnutls_datum_t ext_data = {NULL, 0}; diff --git a/lib/x509/verify.c b/lib/x509/verify.c index 74c62231b0..030297318a 100644 --- a/lib/x509/verify.c +++ b/lib/x509/verify.c @@ -989,10 +989,44 @@ cleanup: } #ifdef ENABLE_PKCS11 +static bool check_key_purpose(gnutls_x509_crt_t issuer, const char *purpose) +{ + char oid[MAX_OID_SIZE]; + size_t oid_size; + int ret; + unsigned i; + + for (i=0;;i++) { + oid_size = sizeof(oid); + ret = gnutls_x509_crt_get_key_purpose_oid(issuer, i, oid, &oid_size, NULL); + if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { + if (i==0) { + /* no key purpose in certificate, assume ANY */ + return 1; + } else { + gnutls_assert(); + break; + } + } else if (ret < 0) { + gnutls_assert(); + break; + } + + if (strcmp(oid, purpose) == 0 || strcmp(oid, GNUTLS_KP_ANY) == 0) { + return 1; + } + } + return 0; +} + /* Verify X.509 certificate chain using a PKCS #11 token. * * Note that the return value is an OR of GNUTLS_CERT_* elements. * + * Unlike the non-PKCS#11 version, this function accepts a key purpose + * (from GNUTLS_KP_...). That is because in the p11-kit trust modules + * anchors are mixed and get assigned a purpose. + * * This function verifies a X.509 certificate list. The certificate * list should lead to a trusted certificate in order to be trusted. */ @@ -1000,6 +1034,7 @@ unsigned int _gnutls_pkcs11_verify_crt_status(const char* url, const gnutls_x509_crt_t * certificate_list, unsigned clist_size, + const char *purpose, unsigned int flags, gnutls_verify_output_function func) { @@ -1089,7 +1124,8 @@ _gnutls_pkcs11_verify_crt_status(const char* url, /* check against issuer */ ret = gnutls_pkcs11_get_raw_issuer(url, certificate_list[clist_size - 1], - &raw_issuer, GNUTLS_X509_FMT_DER, GNUTLS_PKCS11_OBJ_FLAG_PRESENT_IN_TRUSTED_MODULE); + &raw_issuer, GNUTLS_X509_FMT_DER, + GNUTLS_PKCS11_OBJ_FLAG_OVERWRITE_TRUSTMOD_EXT|GNUTLS_PKCS11_OBJ_FLAG_PRESENT_IN_TRUSTED_MODULE); if (ret < 0) { gnutls_assert(); if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE && clist_size > 2) { @@ -1125,6 +1161,16 @@ _gnutls_pkcs11_verify_crt_status(const char* url, goto cleanup; } + if (purpose != NULL) { + ret = check_key_purpose(issuer, purpose); + if (ret != 1) { + gnutls_assert(); + status |= GNUTLS_CERT_INVALID; + status |= GNUTLS_CERT_SIGNER_NOT_FOUND; + goto cleanup; + } + } + status = _gnutls_verify_crt_status(certificate_list, clist_size, &issuer, 1, flags, func); diff --git a/lib/x509/x509_int.h b/lib/x509/x509_int.h index e64a88e8d0..91740c61ac 100644 --- a/lib/x509/x509_int.h +++ b/lib/x509/x509_int.h @@ -394,6 +394,7 @@ unsigned int _gnutls_pkcs11_verify_crt_status(const char* url, const gnutls_x509_crt_t * certificate_list, unsigned clist_size, + const char *purpose, unsigned int flags, gnutls_verify_output_function func); #endif |