summaryrefslogtreecommitdiff
path: root/lib/x509
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@redhat.com>2014-01-02 12:50:13 +0100
committerNikos Mavrogiannopoulos <nmav@redhat.com>2014-01-02 13:53:52 +0100
commitf656e069183b51c72e458b6290c143f9c8d5704d (patch)
tree948a0d08d9080280cb3e7ea3c65837e42a4d7fa7 /lib/x509
parentf83c679f202b6c2c84c2dea2c79420e9bce54794 (diff)
downloadgnutls-f656e069183b51c72e458b6290c143f9c8d5704d.tar.gz
Updated PKCS #11 support for gnutls_x509_trust_list_add_trust_file().
It will now use the PKCS #11 trust URL while verifying instead of importing all CAs. That way it allows verification on the spot without requiring the gnutls to restart in case of a blacklisted CA. Conflicts: lib/x509/verify-high.c
Diffstat (limited to 'lib/x509')
-rw-r--r--lib/x509/verify-high.c52
-rw-r--r--lib/x509/verify-high.h15
-rw-r--r--lib/x509/verify-high2.c56
-rw-r--r--lib/x509/verify.c74
-rw-r--r--lib/x509/x509_int.h9
5 files changed, 130 insertions, 76 deletions
diff --git a/lib/x509/verify-high.c b/lib/x509/verify-high.c
index f3b42c94dd..5297f0c05c 100644
--- a/lib/x509/verify-high.c
+++ b/lib/x509/verify-high.c
@@ -53,14 +53,6 @@ struct node_st {
};
-struct gnutls_x509_trust_list_st {
- unsigned int size;
- struct node_st *node;
-
- gnutls_x509_crt_t *blacklisted;
- unsigned int blacklisted_size;
-};
-
#define DEFAULT_SIZE 127
/**
@@ -79,7 +71,9 @@ int
gnutls_x509_trust_list_init(gnutls_x509_trust_list_t * list,
unsigned int size)
{
- gnutls_x509_trust_list_t tmp =
+ gnutls_x509_trust_list_t tmp;
+
+ tmp =
gnutls_calloc(1, sizeof(struct gnutls_x509_trust_list_st));
if (!tmp)
@@ -150,6 +144,7 @@ gnutls_x509_trust_list_deinit(gnutls_x509_trust_list_t list,
}
gnutls_free(list->node);
+ gnutls_free(list->pkcs11_token);
gnutls_free(list);
}
@@ -211,13 +206,13 @@ int ret;
gnutls_assert();
return NULL;
}
-
+
ret = _gnutls_x509_crt_cpy(dst, src);
if (ret < 0) {
gnutls_assert();
return NULL;
}
-
+
return dst;
}
@@ -273,7 +268,7 @@ gnutls_x509_trust_list_remove_cas(gnutls_x509_trust_list_t list,
break;
}
}
-
+
/* Add the CA (or plain) certificate to the black list as well.
* This will prevent a subordinate CA from being valid, and
* ensure that a server certificate will also get rejected.
@@ -599,7 +594,7 @@ unsigned i, j;
if (blacklist_size == 0)
return 0;
-
+
for (i=0;i<cert_list_size;i++) {
for (j=0;j<blacklist_size;j++) {
if (_gnutls_check_if_same_cert(cert_list[i], blacklist[j]) != 0) {
@@ -667,12 +662,23 @@ gnutls_x509_trust_list_verify_crt(gnutls_x509_trust_list_t list,
return 0;
}
- *verify =
- _gnutls_x509_verify_certificate(cert_list, cert_list_size,
- list->node[hash].trusted_cas,
- list->
- node[hash].trusted_ca_size,
- flags, func);
+#ifdef ENABLE_PKCS11
+ if (list->pkcs11_token) {
+ /* use the token for verification */
+
+ *verify = _gnutls_pkcs11_verify_certificate(list->pkcs11_token,
+ cert_list, cert_list_size,
+ flags, func);
+ } else
+#endif
+ {
+ *verify =
+ _gnutls_x509_verify_certificate(cert_list, cert_list_size,
+ list->node[hash].trusted_cas,
+ list->
+ node[hash].trusted_ca_size,
+ flags, func);
+ }
if (*verify != 0 || (flags & GNUTLS_VERIFY_DISABLE_CRL_CHECKS))
return 0;
@@ -723,10 +729,10 @@ gnutls_x509_trust_list_verify_crt(gnutls_x509_trust_list_t list,
* @verify: will hold the certificate verification output.
* @func: If non-null will be called on each chain element verification with the output.
*
- * This function will try to find a certificate that is associated with the provided
- * name --see gnutls_x509_trust_list_add_named_crt(). If a match is found the certificate is considered valid. In addition to that
- * this function will also check CRLs. The @verify parameter will hold an OR'ed sequence of
- * %gnutls_certificate_status_t flags.
+ * This function will try to find a certificate that is associated with the provided
+ * name --see gnutls_x509_trust_list_add_named_crt(). If a match is found the certificate is considered valid.
+ * In addition to that this function will also check CRLs.
+ * The @verify parameter will hold an OR'ed sequence of %gnutls_certificate_status_t flags.
*
* Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
* negative error value.
diff --git a/lib/x509/verify-high.h b/lib/x509/verify-high.h
index ba45f6ee55..1b2303eb02 100644
--- a/lib/x509/verify-high.h
+++ b/lib/x509/verify-high.h
@@ -20,5 +20,20 @@
*
*/
+#ifndef VERIFY_HIGH_H
+# define VERIFY_HIGH_H
+
+struct gnutls_x509_trust_list_st {
+ unsigned int size;
+ struct node_st *node;
+
+ gnutls_x509_crt_t *blacklisted;
+ unsigned int blacklisted_size;
+
+ char* pkcs11_token;
+};
+
int _gnutls_trustlist_inlist(gnutls_x509_trust_list_t list,
gnutls_x509_crt_t cert);
+
+#endif
diff --git a/lib/x509/verify-high2.c b/lib/x509/verify-high2.c
index 1c3c365026..d810a59899 100644
--- a/lib/x509/verify-high2.c
+++ b/lib/x509/verify-high2.c
@@ -158,56 +158,6 @@ gnutls_x509_trust_list_remove_trust_mem(gnutls_x509_trust_list_t list,
#ifdef ENABLE_PKCS11
static
-int import_pkcs11_url(gnutls_x509_trust_list_t list, const char *ca_file,
- unsigned int flags)
-{
- gnutls_x509_crt_t *xcrt_list = NULL;
- gnutls_pkcs11_obj_t *pcrt_list = NULL;
- unsigned int pcrt_list_size = 0, i;
- int ret;
-
- ret =
- gnutls_pkcs11_obj_list_import_url2(&pcrt_list, &pcrt_list_size,
- ca_file,
- GNUTLS_PKCS11_OBJ_ATTR_CRT_TRUSTED_CA,
- 0);
- if (ret < 0)
- return gnutls_assert_val(ret);
-
- if (pcrt_list_size == 0) {
- ret = 0;
- goto cleanup;
- }
-
- xcrt_list =
- gnutls_malloc(sizeof(gnutls_x509_crt_t) * pcrt_list_size);
- if (xcrt_list == NULL) {
- ret = GNUTLS_E_MEMORY_ERROR;
- goto cleanup;
- }
-
- ret =
- gnutls_x509_crt_list_import_pkcs11(xcrt_list, pcrt_list_size,
- pcrt_list, 0);
- if (ret < 0) {
- gnutls_assert();
- goto cleanup;
- }
-
- ret =
- gnutls_x509_trust_list_add_cas(list, xcrt_list, pcrt_list_size,
- flags);
-
- cleanup:
- for (i = 0; i < pcrt_list_size; i++)
- gnutls_pkcs11_obj_deinit(pcrt_list[i]);
- gnutls_free(pcrt_list);
- gnutls_free(xcrt_list);
-
- return ret;
-}
-
-static
int remove_pkcs11_url(gnutls_x509_trust_list_t list, const char *ca_file)
{
gnutls_x509_crt_t *xcrt_list = NULL;
@@ -293,9 +243,9 @@ gnutls_x509_trust_list_add_trust_file(gnutls_x509_trust_list_t list,
#ifdef ENABLE_PKCS11
if (strncmp(ca_file, "pkcs11:", 7) == 0) {
- ret = import_pkcs11_url(list, ca_file, tl_flags);
- if (ret < 0)
- return gnutls_assert_val(ret);
+ list->pkcs11_token = strdup(ca_file);
+
+ return 0;
} else
#endif
{
diff --git a/lib/x509/verify.c b/lib/x509/verify.c
index f7390dcccc..b9facbe60e 100644
--- a/lib/x509/verify.c
+++ b/lib/x509/verify.c
@@ -682,6 +682,80 @@ _gnutls_x509_verify_certificate(const gnutls_x509_crt_t * certificate_list,
return 0;
}
+#ifdef ENABLE_PKCS11
+/* Verify X.509 certificate chain using a PKCS #11 token.
+ *
+ * Note that the return value is an OR of GNUTLS_CERT_* elements.
+ *
+ * This function verifies a X.509 certificate list. The certificate
+ * list should lead to a trusted certificate in order to be trusted.
+ */
+unsigned int
+_gnutls_pkcs11_verify_certificate(const char* url,
+ const gnutls_x509_crt_t * certificate_list,
+ int clist_size,
+ unsigned int flags,
+ gnutls_verify_output_function func)
+{
+ int ret;
+ unsigned int status = 0;
+ gnutls_x509_crt_t issuer = NULL;
+ gnutls_datum_t raw_issuer = {NULL, 0};
+
+ if (clist_size > 1) {
+ /* Check if the last certificate in the path is self signed.
+ * In that case ignore it (a certificate is trusted only if it
+ * leads to a trusted party by us, not the server's).
+ *
+ * This prevents from verifying self signed certificates against
+ * themselves. This (although not bad) caused verification
+ * failures on some root self signed certificates that use the
+ * MD2 algorithm.
+ */
+ if (gnutls_x509_crt_check_issuer
+ (certificate_list[clist_size - 1],
+ certificate_list[clist_size - 1]) != 0) {
+ clist_size--;
+ }
+ }
+
+ ret = gnutls_pkcs11_get_raw_issuer(url, certificate_list[clist_size - 1],
+ &raw_issuer, GNUTLS_X509_FMT_DER, 0);
+ if (ret < 0) {
+ gnutls_assert();
+ status |= GNUTLS_CERT_INVALID;
+ status |= GNUTLS_CERT_SIGNER_NOT_FOUND;
+ return status;
+ }
+
+ ret = gnutls_x509_crt_init(&issuer);
+ if (ret < 0) {
+ gnutls_assert();
+ status |= GNUTLS_CERT_INVALID;
+ status |= GNUTLS_CERT_SIGNER_NOT_FOUND;
+ goto cleanup;
+ }
+
+ ret = gnutls_x509_crt_import(issuer, &raw_issuer, GNUTLS_X509_FMT_DER);
+ if (ret < 0) {
+ gnutls_assert();
+ status |= GNUTLS_CERT_INVALID;
+ status |= GNUTLS_CERT_SIGNER_NOT_FOUND;
+ goto cleanup;
+ }
+
+ status = _gnutls_x509_verify_certificate(certificate_list, clist_size,
+ &issuer, 1, flags, func);
+
+cleanup:
+ gnutls_free(raw_issuer.data);
+ if (issuer != NULL)
+ gnutls_x509_crt_deinit(issuer);
+
+ return status;
+}
+#endif
+
/* This will return the appropriate hash to verify the given signature.
* If signature is NULL it will return an (or the) appropriate hash for
* the given parameters.
diff --git a/lib/x509/x509_int.h b/lib/x509/x509_int.h
index 8fa86e705c..b849f03a50 100644
--- a/lib/x509/x509_int.h
+++ b/lib/x509/x509_int.h
@@ -371,6 +371,15 @@ _gnutls_x509_verify_certificate(const gnutls_x509_crt_t * certificate_list,
unsigned int flags,
gnutls_verify_output_function func);
+#ifdef ENABLE_PKCS11
+unsigned int
+_gnutls_pkcs11_verify_certificate(const char* url,
+ const gnutls_x509_crt_t * certificate_list,
+ int clist_size,
+ unsigned int flags,
+ gnutls_verify_output_function func);
+#endif
+
int _gnutls_is_same_dn(gnutls_x509_crt_t cert1, gnutls_x509_crt_t cert2);
int