[gnutls-devel] [PATCH 2/3] Also iterate over the CA certificates in a PKCS11 token
Armin Burgmeier
armin at arbur.net
Mon Oct 6 23:24:11 CEST 2014
Signed-off-by: Armin Burgmeier <armin at arbur.net>
---
lib/x509/verify-high.c | 130 ++++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 113 insertions(+), 17 deletions(-)
diff --git a/lib/x509/verify-high.c b/lib/x509/verify-high.c
index 9b0ee12..dda958b 100644
--- a/lib/x509/verify-high.c
+++ b/lib/x509/verify-high.c
@@ -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);
}
--
2.1.1
More information about the Gnutls-devel
mailing list