]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
Updated PKCS #11 support for gnutls_x509_trust_list_add_trust_file().
authorNikos Mavrogiannopoulos <nmav@redhat.com>
Thu, 2 Jan 2014 11:50:13 +0000 (12:50 +0100)
committerNikos Mavrogiannopoulos <nmav@redhat.com>
Thu, 2 Jan 2014 12:31:10 +0000 (13:31 +0100)
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.

configure.ac
lib/x509/verify-high.c
lib/x509/verify-high.h
lib/x509/verify-high2.c
lib/x509/verify.c
lib/x509/x509_int.h

index 225349f95b8087ee9bbd18a6fb93c474594b84a8..bd17821de359297e0895eb26b009b62185ecb73c 100644 (file)
@@ -479,7 +479,7 @@ dnl auto detect http://lists.gnu.org/archive/html/help-gnutls/2012-05/msg00004.h
 AC_ARG_WITH([default-trust-store-file],
   [AS_HELP_STRING([--with-default-trust-store-file=FILE],
     [use the given file default trust store])], with_default_trust_store_file="$withval",
-  [if test "$build" = "$host";then
+  [if test "$build" = "$host" && test x$with_default_trust_store_pkcs11 = x;then
   for i in \
     /etc/ssl/ca-bundle.pem \
     /etc/ssl/certs/ca-certificates.crt \
@@ -487,7 +487,7 @@ AC_ARG_WITH([default-trust-store-file],
     /usr/local/share/certs/ca-root-nss.crt \
     /etc/ssl/cert.pem
     do
-    if test -e $i; then
+    if test -e "$i"; then
       with_default_trust_store_file="$i"
       break
     fi
@@ -803,7 +803,7 @@ AC_MSG_NOTICE([Optional libraries:
 
 AC_MSG_NOTICE([System files:
 
-  Trust store pkcs:     $with_default_trust_store_pkcs11
+  Trust store pkcs11:   $with_default_trust_store_pkcs11
   Trust store file:     $with_default_trust_store_file
   Blacklist file:       $with_default_blacklist_file
   CRL file:             $with_default_crl_file
index d8f8b667fa87e9176aa29842f9251acfd9364832..646e8a59e95f11539967afe9e79824c9ca30f1ff 100644 (file)
@@ -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
 
 /**
@@ -80,9 +72,9 @@ gnutls_x509_trust_list_init(gnutls_x509_trust_list_t * list,
                            unsigned int size)
 {
        gnutls_x509_trust_list_t tmp;
-       
+
        FAIL_IF_LIB_ERROR;
-       
+
        tmp =
            gnutls_calloc(1, sizeof(struct gnutls_x509_trust_list_st));
 
@@ -154,6 +146,7 @@ gnutls_x509_trust_list_deinit(gnutls_x509_trust_list_t list,
        }
 
        gnutls_free(list->node);
+       gnutls_free(list->pkcs11_token);
        gnutls_free(list);
 }
 
@@ -215,13 +208,13 @@ int ret;
                gnutls_assert();
                return NULL;
        }
-       
+
        ret = _gnutls_x509_crt_cpy(dst, src);
        if (ret < 0) {
                gnutls_assert();
                return NULL;
        }
-       
+
        return dst;
 }
 
@@ -277,7 +270,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.
@@ -603,7 +596,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) {
@@ -671,12 +664,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;
@@ -727,10 +731,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.
index ba45f6ee558bc43a8da057e70ddac4217236baaa..1b2303eb028505bb52757f8cf067a62d6ab7af84 100644 (file)
  *
  */
 
+#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
index 1c3c3650267fa825a5c836114f37d47497f7d3d6..d810a598997273ff94a42683c44994615528a6e8 100644 (file)
@@ -157,56 +157,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)
 {
@@ -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
        {
index 39bd1f432e7d59d398ccea079d815151d064e148..d6c2884a127811d4c55fcf15e50aa85c2c41cf2a 100644 (file)
@@ -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.
index 9863e0b7fa0e990162bfc2c8644cda70b43ae443..5615934ae605e68467007b07dcbc538ae43d1bf8 100644 (file)
@@ -378,6 +378,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