summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@redhat.com>2014-11-14 09:32:40 +0100
committerNikos Mavrogiannopoulos <nmav@redhat.com>2014-11-14 09:32:40 +0100
commit410ca3898993a479cb9c365372fa627e94125014 (patch)
tree2f07bd0b56f61184ca27a8e9eaebd77f802e3a51
parentb17978315a662434fbcf1bec67ee33cf9c34caa9 (diff)
downloadgnutls-410ca3898993a479cb9c365372fa627e94125014.tar.gz
added gnutls_pkcs11_get_raw_issuer_by_dn and gnutls_x509_trust_list_get_issuer_by_dn
-rw-r--r--lib/includes/gnutls/pkcs11.h5
-rw-r--r--lib/includes/gnutls/x509.h5
-rw-r--r--lib/pkcs11.c84
-rw-r--r--lib/x509/verify-high.c85
4 files changed, 179 insertions, 0 deletions
diff --git a/lib/includes/gnutls/pkcs11.h b/lib/includes/gnutls/pkcs11.h
index 3a7fdfb84d..5a97f573e8 100644
--- a/lib/includes/gnutls/pkcs11.h
+++ b/lib/includes/gnutls/pkcs11.h
@@ -171,6 +171,11 @@ int gnutls_pkcs11_get_raw_issuer(const char *url, gnutls_x509_crt_t cert,
gnutls_x509_crt_fmt_t fmt,
unsigned int flags);
+int gnutls_pkcs11_get_raw_issuer_by_dn (const char *url, const gnutls_datum_t *dn,
+ gnutls_datum_t *issuer,
+ gnutls_x509_crt_fmt_t fmt,
+ unsigned int flags);
+
int gnutls_pkcs11_crt_is_known(const char *url, gnutls_x509_crt_t cert,
unsigned int flags);
diff --git a/lib/includes/gnutls/x509.h b/lib/includes/gnutls/x509.h
index 2ee2a5b556..491160b3c9 100644
--- a/lib/includes/gnutls/x509.h
+++ b/lib/includes/gnutls/x509.h
@@ -1257,6 +1257,11 @@ int gnutls_x509_trust_list_get_issuer(gnutls_x509_trust_list_t
gnutls_x509_crt_t * issuer,
unsigned int flags);
+int gnutls_x509_trust_list_get_issuer_by_dn(gnutls_x509_trust_list_t list,
+ const gnutls_datum_t *dn,
+ gnutls_x509_crt_t *issuer,
+ unsigned int flags);
+
#define GNUTLS_TL_VERIFY_CRL 1
#define GNUTLS_TL_USE_IN_TLS (1<<1)
#define GNUTLS_TL_NO_DUPLICATES (1<<2)
diff --git a/lib/pkcs11.c b/lib/pkcs11.c
index eebdc46764..cd46963098 100644
--- a/lib/pkcs11.c
+++ b/lib/pkcs11.c
@@ -3508,6 +3508,90 @@ int gnutls_pkcs11_get_raw_issuer(const char *url, gnutls_x509_crt_t cert,
}
/**
+ * gnutls_pkcs11_get_raw_issuer_by_dn:
+ * @url: A PKCS 11 url identifying a token
+ * @dn: is the DN to search for
+ * @issuer: Will hold the issuer if any in an allocated buffer.
+ * @fmt: The format of the exported issuer.
+ * @flags: Use zero or flags from %GNUTLS_PKCS11_OBJ_FLAG.
+ *
+ * This function will return the certificate with the given DN, if it
+ * is stored in the token. By default only marked as trusted issuers
+ * are retuned. If any issuer should be returned specify
+ * %GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_ANY in @flags.
+ *
+ * The name of the function includes issuer because it can
+ * be used to discover issuers of certificates.
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
+ * negative error value.
+ *
+ * Since: 3.4.0
+ **/
+int gnutls_pkcs11_get_raw_issuer_by_dn (const char *url, const gnutls_datum_t *dn,
+ gnutls_datum_t *issuer,
+ gnutls_x509_crt_fmt_t fmt,
+ unsigned int flags)
+{
+ int ret;
+ struct find_cert_st priv;
+ struct p11_kit_uri *info = NULL;
+
+ PKCS11_CHECK_INIT;
+
+ memset(&priv, 0, sizeof(priv));
+
+ if (url == NULL || url[0] == 0) {
+ url = "pkcs11:";
+ }
+
+ ret = pkcs11_url_to_info(url, &info);
+ if (ret < 0) {
+ gnutls_assert();
+ return ret;
+ }
+
+ priv.dn.data = dn->data;
+ priv.dn.size = dn->size;
+
+ if (!(flags & GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_ANY))
+ flags |= GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_TRUSTED;
+
+ priv.flags = flags;
+
+ ret = gnutls_pkcs11_obj_init(&priv.obj);
+ if (ret < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+ priv.need_import = 1;
+
+ ret =
+ _pkcs11_traverse_tokens(find_cert_cb, &priv, info,
+ NULL, pkcs11_obj_flags_to_int(flags));
+ if (ret < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ ret = gnutls_pkcs11_obj_export3(priv.obj, fmt, issuer);
+ if (ret < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ ret = 0;
+
+ cleanup:
+ if (priv.obj)
+ gnutls_pkcs11_obj_deinit(priv.obj);
+ if (info)
+ p11_kit_uri_free(info);
+
+ return ret;
+}
+
+/**
* gnutls_pkcs11_crt_is_known:
* @url: A PKCS 11 url identifying a token
* @cert: is the certificate to find issuer for
diff --git a/lib/x509/verify-high.c b/lib/x509/verify-high.c
index f3a65d97f6..98d5af18f5 100644
--- a/lib/x509/verify-high.c
+++ b/lib/x509/verify-high.c
@@ -883,6 +883,32 @@ int trust_list_get_issuer(gnutls_x509_trust_list_t list,
return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
}
+static
+int trust_list_get_issuer_by_dn(gnutls_x509_trust_list_t list,
+ const gnutls_datum_t *dn,
+ gnutls_x509_crt_t * issuer,
+ unsigned int flags)
+{
+ int ret;
+ unsigned int i;
+ uint32_t hash;
+
+ hash =
+ hash_pjw_bare(dn->data,
+ dn->size);
+ hash %= list->size;
+
+ for (i = 0; i < list->node[hash].trusted_ca_size; i++) {
+ ret = _gnutls_x509_compare_raw_dn(dn, &list->node[hash].trusted_cas[i]->raw_dn);
+ if (ret != 0) {
+ *issuer = crt_cpy(list->node[hash].trusted_cas[i]);
+ return 0;
+ }
+ }
+
+ return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
+}
+
/**
* gnutls_x509_trust_list_get_issuer:
* @list: The structure of the list
@@ -958,6 +984,65 @@ int gnutls_x509_trust_list_get_issuer(gnutls_x509_trust_list_t list,
return ret;
}
+/**
+ * gnutls_x509_trust_list_get_issuer_by_dn:
+ * @list: The structure of the list
+ * @dn: is the issuer's DN
+ * @issuer: Will hold the issuer if any. Should be treated as constant.
+ * @flags: Use zero
+ *
+ * This function will find the issuer of the given certificate, and
+ * return a copy of the issuer, which must be freed using gnutls_x509_crt_deinit().
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
+ * negative error value.
+ *
+ * Since: 3.4.0
+ **/
+int gnutls_x509_trust_list_get_issuer_by_dn(gnutls_x509_trust_list_t list,
+ const gnutls_datum_t *dn,
+ gnutls_x509_crt_t *issuer,
+ unsigned int flags)
+{
+ int ret;
+
+ ret = trust_list_get_issuer_by_dn(list, dn, issuer, flags);
+ if (ret == 0) {
+ return 0;
+ }
+
+#ifdef ENABLE_PKCS11
+ if (ret < 0 && list->pkcs11_token) {
+ gnutls_x509_crt_t crt;
+ gnutls_datum_t der = {NULL, 0};
+ /* use the token for verification */
+ ret = gnutls_pkcs11_get_raw_issuer_by_dn(list->pkcs11_token, dn, &der,
+ GNUTLS_X509_FMT_DER, 0);
+ if (ret < 0) {
+ gnutls_assert();
+ return ret;
+ }
+
+ ret = gnutls_x509_crt_init(&crt);
+ if (ret < 0) {
+ gnutls_free(der.data);
+ return gnutls_assert_val(ret);
+ }
+
+ ret = gnutls_x509_crt_import(crt, &der, GNUTLS_X509_FMT_DER);
+ gnutls_free(der.data);
+ if (ret < 0) {
+ gnutls_x509_crt_deinit(crt);
+ return gnutls_assert_val(ret);
+ }
+
+ *issuer = crt;
+ return 0;
+ }
+#endif
+ return ret;
+}
+
static
int check_if_in_blacklist(gnutls_x509_crt_t * cert_list, unsigned int cert_list_size,
gnutls_x509_crt_t * blacklist, unsigned int blacklist_size)