summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/x509/verify-high.c17
-rw-r--r--lib/x509/verify.c48
-rw-r--r--lib/x509/x509_int.h1
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