]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
Also iterate over the CA certificates in a PKCS11 token
authorArmin Burgmeier <armin@arbur.net>
Mon, 6 Oct 2014 21:24:11 +0000 (17:24 -0400)
committerNikos Mavrogiannopoulos <nmav@redhat.com>
Tue, 7 Oct 2014 13:18:18 +0000 (15:18 +0200)
Signed-off-by: Armin Burgmeier <armin@arbur.net>
lib/x509/verify-high.c

index 9b0ee121eb4bf0a8cdeb4c5c1c728ecf1a7a8ec1..dda958be3e59e39e8815eebdff50ff482c3539bf 100644 (file)
@@ -57,6 +57,12 @@ struct node_st {
 struct gnutls_x509_trust_list_iter {
        unsigned int node_index;
        unsigned int ca_index;
+
+#ifdef ENABLE_PKCS11
+       gnutls_pkcs11_obj_t* pkcs11_list;
+       unsigned int pkcs11_index;
+       unsigned int pkcs11_size;
+#endif
 };
 
 #define DEFAULT_SIZE 127
@@ -294,6 +300,47 @@ gnutls_x509_trust_list_add_cas(gnutls_x509_trust_list_t list,
        return i;
 }
 
+static int
+advance_iter(gnutls_x509_trust_list_t list,
+             gnutls_x509_trust_list_iter_t iter)
+{
+       int ret;
+
+       if (iter->node_index < list->size) {
+               ++iter->ca_index;
+
+               /* skip entries */
+               while (iter->node_index < list->size &&
+                      iter->ca_index >= list->node[iter->node_index].trusted_ca_size) {
+                       ++iter->node_index;
+                       iter->ca_index = 0;
+               }
+
+               if (iter->node_index < list->size)
+                       return 0;
+       }
+
+#ifdef ENABLE_PKCS11
+       if (list->pkcs11_token != NULL) {
+               if (iter->pkcs11_list == NULL) {
+                       ret = gnutls_pkcs11_obj_list_import_url2(&iter->pkcs11_list, &iter->pkcs11_size,
+                           list->pkcs11_token, GNUTLS_PKCS11_OBJ_ATTR_CRT_TRUSTED_CA, 0);
+                       if (ret < 0)
+                               return gnutls_assert_val(ret);
+
+                       if (iter->pkcs11_size > 0)
+                               return 0;
+               } else if (iter->pkcs11_index < iter->pkcs11_size) {
+                       ++iter->pkcs11_index;
+                       if (iter->pkcs11_index < iter->pkcs11_size)
+                               return 0;
+               }
+       }
+#endif
+
+       return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
+}
+
 /**
  * gnutls_x509_trust_list_iter_get_ca:
  * @list: The structure of the list
@@ -322,7 +369,7 @@ gnutls_x509_trust_list_iter_get_ca(gnutls_x509_trust_list_t list,
 {
        int ret;
 
-       /* advance to next entry */
+       /* initialize iterator */
        if (*iter == NULL) {
                *iter = gnutls_malloc(sizeof (struct gnutls_x509_trust_list_iter));
                if (*iter == NULL)
@@ -330,31 +377,71 @@ gnutls_x509_trust_list_iter_get_ca(gnutls_x509_trust_list_t list,
 
                (*iter)->node_index = 0;
                (*iter)->ca_index = 0;
-       } else {
-               ++(*iter)->ca_index;
+
+#ifdef ENABLE_PKCS11
+               (*iter)->pkcs11_list = NULL;
+               (*iter)->pkcs11_size = 0;
+               (*iter)->pkcs11_index = 0;
+#endif
+
+               /* Advance iterator to the first valid entry */
+               if (list->node[0].trusted_ca_size == 0) {
+                       ret = advance_iter(list, *iter);
+                       if (ret != 0) {
+                               gnutls_x509_trust_list_iter_deinit(*iter);
+                               *iter = NULL;
+
+                               *crt = NULL;
+                               return gnutls_assert_val(ret);
+                       }
+               }
        }
 
-       /* skip empty nodes */
-       while ((*iter)->ca_index >= list->node[(*iter)->node_index].trusted_ca_size) {
-               ++(*iter)->node_index;
-               (*iter)->ca_index = 0;
+       /* obtain the certificate at the current iterator position */
+       if ((*iter)->node_index < list->size) {
+               ret = gnutls_x509_crt_init(crt);
+               if (ret < 0)
+                       return gnutls_assert_val(ret);
 
-               if ((*iter)->node_index >= list->size) {
-                       gnutls_free(*iter);
-                       *iter = NULL;
+               ret = _gnutls_x509_crt_cpy(*crt, list->node[(*iter)->node_index].trusted_cas[(*iter)->ca_index]);
+               if (ret < 0) {
+                       gnutls_x509_crt_deinit(*crt);
+                       return gnutls_assert_val(ret);
+               }
+       }
+#ifdef ENABLE_PKCS11
+       else if ( (*iter)->pkcs11_index < (*iter)->pkcs11_size) {
+               ret = gnutls_x509_crt_init(crt);
+               if (ret < 0)
+                       return gnutls_assert_val(ret);
 
-                       *crt = NULL;
-                       return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
+               ret = gnutls_x509_crt_import_pkcs11(*crt, (*iter)->pkcs11_list[(*iter)->pkcs11_index]);
+               if (ret < 0) {
+                       gnutls_x509_crt_deinit(*crt);
+                       return gnutls_assert_val(ret);
                }
        }
+#endif
 
-       ret = gnutls_x509_crt_init(crt);
-       if (ret < 0)
-               return gnutls_assert_val(ret);
+       else {
+               /* iterator is at end */
+               gnutls_x509_trust_list_iter_deinit(*iter);
+               *iter = NULL;
 
-       ret = _gnutls_x509_crt_cpy(*crt, list->node[(*iter)->node_index].trusted_cas[(*iter)->ca_index]);
-       if (ret < 0) {
+               *crt = NULL;
+               return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
+       }
+
+       /* Move iterator to the next position.
+        * GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE is returned if the iterator
+        * has been moved to the end position. That is okay, we return the
+        * certificate that we read and when this function is called again we
+        * report GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE to our caller. */
+       ret = advance_iter(list, *iter);
+       if (ret < 0 && ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
                gnutls_x509_crt_deinit(*crt);
+               *crt = NULL;
+
                return gnutls_assert_val(ret);
        }
 
@@ -374,6 +461,15 @@ void gnutls_x509_trust_list_iter_deinit(gnutls_x509_trust_list_iter_t iter)
        if (!iter)
                return;
 
+#ifdef ENABLE_PKCS11
+       if (iter->pkcs11_size > 0) {
+               unsigned i;
+               for (i = 0; i < iter->pkcs11_size; ++i)
+                       gnutls_pkcs11_obj_deinit(iter->pkcs11_list[i]);
+               gnutls_free(iter->pkcs11_list);
+       }
+#endif
+
        gnutls_free(iter);
 }