summaryrefslogtreecommitdiff
path: root/lib/x509/verify.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/x509/verify.c')
-rw-r--r--lib/x509/verify.c48
1 files changed, 47 insertions, 1 deletions
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);