diff options
author | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2014-11-14 09:32:40 +0100 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2014-11-14 09:32:40 +0100 |
commit | 410ca3898993a479cb9c365372fa627e94125014 (patch) | |
tree | 2f07bd0b56f61184ca27a8e9eaebd77f802e3a51 | |
parent | b17978315a662434fbcf1bec67ee33cf9c34caa9 (diff) | |
download | gnutls-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.h | 5 | ||||
-rw-r--r-- | lib/includes/gnutls/x509.h | 5 | ||||
-rw-r--r-- | lib/pkcs11.c | 84 | ||||
-rw-r--r-- | lib/x509/verify-high.c | 85 |
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) |