summaryrefslogtreecommitdiff
path: root/lib/x509
diff options
context:
space:
mode:
authorSahana Prasad <sahana@redhat.com>2020-05-22 09:42:47 +0200
committerSahana Prasad <sahana@redhat.com>2020-06-03 15:41:26 +0200
commite476e4b7e0de11820123da06ca9fcd0cbb94b8ff (patch)
tree40e9c5feae982c00c5f9fe0e35e4af5082bb2160 /lib/x509
parent86012fd64e248c31554d42e6d6b38bfcd4357f92 (diff)
downloadgnutls-e476e4b7e0de11820123da06ca9fcd0cbb94b8ff.tar.gz
Implements a callback function gnutls_x509_trust_list_set_getissuer_function()
Signed-off-by: Sahana Prasad <sahana@redhat.com>
Diffstat (limited to 'lib/x509')
-rw-r--r--lib/x509/verify-high.c37
-rw-r--r--lib/x509/verify-high.h6
-rw-r--r--lib/x509/verify.c129
-rw-r--r--lib/x509/x509_int.h33
4 files changed, 123 insertions, 82 deletions
diff --git a/lib/x509/verify-high.c b/lib/x509/verify-high.c
index 40638ad3aa..763c527a59 100644
--- a/lib/x509/verify-high.c
+++ b/lib/x509/verify-high.c
@@ -851,11 +851,10 @@ static int shorten_clist(gnutls_x509_trust_list_t list,
return clist_size;
}
-static
-int trust_list_get_issuer(gnutls_x509_trust_list_t list,
- gnutls_x509_crt_t cert,
- gnutls_x509_crt_t * issuer,
- unsigned int flags)
+int _gnutls_trust_list_get_issuer(gnutls_x509_trust_list_t list,
+ gnutls_x509_crt_t cert,
+ gnutls_x509_crt_t * issuer,
+ unsigned int flags)
{
int ret;
unsigned int i;
@@ -968,7 +967,7 @@ int gnutls_x509_trust_list_get_issuer(gnutls_x509_trust_list_t list,
{
int ret;
- ret = trust_list_get_issuer(list, cert, issuer, flags);
+ ret = _gnutls_trust_list_get_issuer(list, cert, issuer, flags);
if (ret == 0) {
return 0;
}
@@ -1335,11 +1334,10 @@ gnutls_x509_trust_list_verify_crt2(gnutls_x509_trust_list_t list,
}
*voutput =
- _gnutls_verify_crt_status(cert_list, cert_list_size,
- list->node[hash].trusted_cas,
- list->
- node[hash].trusted_ca_size,
- flags, purpose, func);
+ _gnutls_verify_crt_status(list, cert_list, cert_list_size,
+ list->node[hash].trusted_cas,
+ list->node[hash].trusted_ca_size,
+ flags, purpose, func);
saved_output = *voutput;
if (SIGNER_OLD_OR_UNKNOWN(*voutput) &&
@@ -1357,11 +1355,10 @@ gnutls_x509_trust_list_verify_crt2(gnutls_x509_trust_list_t list,
_gnutls_debug_log("issuer in verification was not found or insecure; trying against trust list\n");
*voutput =
- _gnutls_verify_crt_status(cert_list, cert_list_size,
- list->node[hash].trusted_cas,
- list->
- node[hash].trusted_ca_size,
- flags, purpose, func);
+ _gnutls_verify_crt_status(list, cert_list, cert_list_size,
+ list->node[hash].trusted_cas,
+ list->node[hash].trusted_ca_size,
+ flags, purpose, func);
if (*voutput != 0) {
if (SIGNER_WAS_KNOWN(saved_output))
*voutput = saved_output;
@@ -1375,10 +1372,10 @@ gnutls_x509_trust_list_verify_crt2(gnutls_x509_trust_list_t list,
if (SIGNER_OLD_OR_UNKNOWN(*voutput) && list->pkcs11_token) {
/* use the token for verification */
- *voutput = _gnutls_pkcs11_verify_crt_status(list->pkcs11_token,
- cert_list, cert_list_size,
- purpose,
- flags, func);
+ *voutput = _gnutls_pkcs11_verify_crt_status(list, list->pkcs11_token,
+ cert_list, cert_list_size,
+ purpose,
+ flags, func);
if (*voutput != 0) {
if (SIGNER_WAS_KNOWN(saved_output))
*voutput = saved_output;
diff --git a/lib/x509/verify-high.h b/lib/x509/verify-high.h
index ca1f98b831..6ce5f958ae 100644
--- a/lib/x509/verify-high.h
+++ b/lib/x509/verify-high.h
@@ -39,8 +39,12 @@ struct gnutls_x509_trust_list_st {
* will be deinitialized */
gnutls_x509_crt_t *keep_certs;
unsigned int keep_certs_size;
-
+
char* pkcs11_token;
+
+ /* set this callback if the issuer in the certificate
+ * chain is missing. */
+ gnutls_x509_trust_list_getissuer_function *issuer_callback;
};
int _gnutls_trustlist_inlist(gnutls_x509_trust_list_t list,
diff --git a/lib/x509/verify.c b/lib/x509/verify.c
index fd7c6a1642..4363e818b1 100644
--- a/lib/x509/verify.c
+++ b/lib/x509/verify.c
@@ -38,6 +38,7 @@
#include <x509_int.h>
#include <common.h>
#include <pk.h>
+#include <x509/verify-high.h>
#include "supported_exts.h"
#include "profiles.h"
@@ -604,11 +605,11 @@ static int _gnutls_x509_verify_data(gnutls_sign_algorithm_t sign,
gnutls_x509_crt_t issuer,
unsigned vflags);
-/*
+/*
* Verifies the given certificate against a certificate list of
* trusted CAs.
*
- * Returns only 0 or 1. If 1 it means that the certificate
+ * Returns only 0 or 1. If 1 it means that the certificate
* was successfully verified.
*
* 'flags': an OR of the gnutls_certificate_verify_flags enumeration.
@@ -616,13 +617,13 @@ static int _gnutls_x509_verify_data(gnutls_sign_algorithm_t sign,
* Output will hold some extra information about the verification
* procedure.
*/
-static unsigned
-verify_crt(gnutls_x509_crt_t cert,
- const gnutls_x509_crt_t * trusted_cas,
- int tcas_size, unsigned int flags,
- unsigned int *output,
- verify_state_st *vparams,
- unsigned end_cert)
+static unsigned verify_crt(gnutls_x509_trust_list_t tlist,
+ gnutls_x509_crt_t cert,
+ const gnutls_x509_crt_t * trusted_cas,
+ int tcas_size, unsigned int flags,
+ unsigned int *output,
+ verify_state_st *vparams,
+ unsigned end_cert)
{
gnutls_datum_t cert_signed_data = { NULL, 0 };
gnutls_datum_t cert_signature = { NULL, 0 };
@@ -646,6 +647,25 @@ verify_crt(gnutls_x509_crt_t cert,
if (tcas_size >= 1)
issuer = find_issuer(cert, trusted_cas, tcas_size);
+ if (issuer == NULL && tlist != NULL && tlist->issuer_callback != NULL) {
+ _gnutls_debug_log("Missing issuer callback set.\n");
+
+ /* missing issuer is populated by the callback */
+ ret = tlist->issuer_callback(tlist, cert);
+ if (ret < 0) {
+ /* if the callback fails, continue as though the callback
+ * wasn't invoked i.e issuer remains NULL */
+ gnutls_assert();
+ issuer = NULL;
+ }
+
+ ret = _gnutls_trust_list_get_issuer(tlist, cert, &issuer, 0);
+ if (ret < 0) {
+ gnutls_assert();
+ issuer = NULL;
+ }
+ }
+
ret =
_gnutls_x509_get_signed_data(cert->cert, &cert->der, "tbsCertificate",
&cert_signed_data);
@@ -680,7 +700,7 @@ verify_crt(gnutls_x509_crt_t cert,
} else {
if (vparams->nc != NULL) {
/* append the issuer's constraints */
- ret = gnutls_x509_crt_get_name_constraints(issuer, vparams->nc,
+ ret = gnutls_x509_crt_get_name_constraints(issuer, vparams->nc,
GNUTLS_NAME_CONSTRAINTS_FLAG_APPEND, NULL);
if (ret < 0 && ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
MARK_INVALID(GNUTLS_CERT_SIGNER_CONSTRAINTS_FAILURE);
@@ -909,13 +929,14 @@ unsigned check_ca_sanity(const gnutls_x509_crt_t issuer,
* list should lead to a trusted certificate in order to be trusted.
*/
unsigned int
-_gnutls_verify_crt_status(const gnutls_x509_crt_t * certificate_list,
- int clist_size,
- const gnutls_x509_crt_t * trusted_cas,
- int tcas_size,
- unsigned int flags,
- const char *purpose,
- gnutls_verify_output_function func)
+_gnutls_verify_crt_status(gnutls_x509_trust_list_t tlist,
+ const gnutls_x509_crt_t * certificate_list,
+ int clist_size,
+ const gnutls_x509_crt_t * trusted_cas,
+ int tcas_size,
+ unsigned int flags,
+ const char *purpose,
+ gnutls_verify_output_function func)
{
int i = 0, ret;
unsigned int status = 0, output;
@@ -1010,11 +1031,12 @@ _gnutls_verify_crt_status(const gnutls_x509_crt_t * certificate_list,
*/
output = 0;
- ret = verify_crt(certificate_list[clist_size - 1],
- trusted_cas, tcas_size, flags,
- &output,
- &vparams,
- clist_size==1?1:0);
+ ret = verify_crt(tlist,
+ certificate_list[clist_size - 1],
+ trusted_cas, tcas_size, flags,
+ &output,
+ &vparams,
+ clist_size==1?1:0);
if (ret != 1) {
/* if the last certificate in the certificate
* list is invalid, then the certificate is not
@@ -1053,11 +1075,12 @@ _gnutls_verify_crt_status(const gnutls_x509_crt_t * certificate_list,
}
if ((ret =
- verify_crt(certificate_list[i - 1],
- &certificate_list[i], 1,
- flags, &output,
- &vparams,
- i==1?1:0)) != 1) {
+ verify_crt(tlist,
+ certificate_list[i - 1],
+ &certificate_list[i], 1,
+ flags, &output,
+ &vparams,
+ i==1?1:0)) != 1) {
gnutls_assert();
status |= output;
status |= GNUTLS_CERT_INVALID;
@@ -1147,12 +1170,13 @@ unsigned _gnutls_check_key_purpose(gnutls_x509_crt_t cert, const char *purpose,
* list should lead to a trusted certificate in order to be trusted.
*/
unsigned int
-_gnutls_pkcs11_verify_crt_status(const char* url,
- const gnutls_x509_crt_t * certificate_list,
- unsigned clist_size,
- const char *purpose,
- unsigned int flags,
- gnutls_verify_output_function func)
+_gnutls_pkcs11_verify_crt_status(gnutls_x509_trust_list_t tlist,
+ const char* url,
+ const gnutls_x509_crt_t * certificate_list,
+ unsigned clist_size,
+ const char *purpose,
+ unsigned int flags,
+ gnutls_verify_output_function func)
{
int ret;
unsigned int status = 0, i;
@@ -1249,9 +1273,10 @@ _gnutls_pkcs11_verify_crt_status(const char* url,
ret = gnutls_pkcs11_crt_is_known(url, certificate_list[clist_size - 1],
GNUTLS_PKCS11_OBJ_FLAG_RETRIEVE_TRUSTED|GNUTLS_PKCS11_OBJ_FLAG_COMPARE);
if (ret != 0) {
- return _gnutls_verify_crt_status(certificate_list, clist_size,
- &certificate_list[clist_size - 1], 1, flags,
- purpose, func);
+ return _gnutls_verify_crt_status(tlist,
+ certificate_list, clist_size,
+ &certificate_list[clist_size - 1],
+ 1, flags, purpose, func);
}
}
@@ -1260,7 +1285,7 @@ _gnutls_pkcs11_verify_crt_status(const char* url,
/* verify the certificate list against 0 trusted CAs in order
* to get, any additional flags from the certificate list (e.g.,
* insecure algorithms or expired */
- status |= _gnutls_verify_crt_status(certificate_list, clist_size,
+ status |= _gnutls_verify_crt_status(tlist, certificate_list, clist_size,
NULL, 0, flags, purpose, func);
goto cleanup;
}
@@ -1303,8 +1328,8 @@ _gnutls_pkcs11_verify_crt_status(const char* url,
goto cleanup;
}
- status = _gnutls_verify_crt_status(certificate_list, clist_size,
- &issuer, 1, flags, purpose, func);
+ status = _gnutls_verify_crt_status(tlist, certificate_list, clist_size,
+ &issuer, 1, flags, purpose, func);
cleanup:
gnutls_free(raw_issuer.data);
@@ -1468,18 +1493,20 @@ gnutls_x509_crt_list_verify(const gnutls_x509_crt_t * cert_list,
{
unsigned i;
int ret;
+ gnutls_x509_trust_list_t tlist;
if (cert_list == NULL || cert_list_length == 0)
return GNUTLS_E_NO_CERTIFICATE_FOUND;
- /* Verify certificate
+ gnutls_x509_trust_list_init(&tlist, 0);
+
+ /* Verify certificate
*/
- *verify =
- _gnutls_verify_crt_status(cert_list, cert_list_length,
+ *verify = _gnutls_verify_crt_status(tlist, cert_list, cert_list_length,
CA_list, CA_list_length,
flags, NULL, NULL);
- /* Check for revoked certificates in the chain.
+ /* Check for revoked certificates in the chain.
*/
for (i = 0; i < cert_list_length; i++) {
ret = gnutls_x509_crt_check_revocation(cert_list[i],
@@ -1491,6 +1518,7 @@ gnutls_x509_crt_list_verify(const gnutls_x509_crt_t * cert_list,
}
}
+ gnutls_x509_trust_list_deinit(tlist, 0);
return 0;
}
@@ -1518,12 +1546,17 @@ gnutls_x509_crt_verify(gnutls_x509_crt_t cert,
unsigned CA_list_length, unsigned int flags,
unsigned int *verify)
{
- /* Verify certificate
+ gnutls_x509_trust_list_t tlist;
+
+ gnutls_x509_trust_list_init(&tlist, 0);
+
+ /* Verify certificate
*/
- *verify =
- _gnutls_verify_crt_status(&cert, 1,
+ *verify = _gnutls_verify_crt_status(tlist, &cert, 1,
CA_list, CA_list_length,
flags, NULL, NULL);
+
+ gnutls_x509_trust_list_deinit(tlist, 0);
return 0;
}
@@ -1533,9 +1566,9 @@ gnutls_x509_crt_verify(gnutls_x509_crt_t cert,
* @issuer: is the certificate of a possible issuer
*
* This function will check if the given CRL was issued by the given
- * issuer certificate.
+ * issuer certificate.
*
- * Returns: true (1) if the given CRL was issued by the given issuer,
+ * Returns: true (1) if the given CRL was issued by the given issuer,
* and false (0) if not.
**/
unsigned
diff --git a/lib/x509/x509_int.h b/lib/x509/x509_int.h
index 050e95059e..a41cc5827a 100644
--- a/lib/x509/x509_int.h
+++ b/lib/x509/x509_int.h
@@ -495,23 +495,30 @@ gnutls_x509_crt_verify_data3(gnutls_x509_crt_t crt,
const gnutls_datum_t *signature,
unsigned int flags);
+int _gnutls_trust_list_get_issuer(gnutls_x509_trust_list_t list,
+ gnutls_x509_crt_t cert,
+ gnutls_x509_crt_t * issuer,
+ unsigned int flags);
+
unsigned int
-_gnutls_verify_crt_status(const gnutls_x509_crt_t * certificate_list,
- int clist_size,
- const gnutls_x509_crt_t * trusted_cas,
- int tcas_size,
- unsigned int flags,
- const char *purpose,
- gnutls_verify_output_function func);
+_gnutls_verify_crt_status(gnutls_x509_trust_list_t tlist,
+ const gnutls_x509_crt_t * certificate_list,
+ int clist_size,
+ const gnutls_x509_crt_t * trusted_cas,
+ int tcas_size,
+ unsigned int flags,
+ const char *purpose,
+ gnutls_verify_output_function func);
#ifdef ENABLE_PKCS11
unsigned int
-_gnutls_pkcs11_verify_crt_status(const char* url,
- const gnutls_x509_crt_t * certificate_list,
- unsigned clist_size,
- const char *purpose,
- unsigned int flags,
- gnutls_verify_output_function func);
+_gnutls_pkcs11_verify_crt_status(gnutls_x509_trust_list_t tlist,
+ const char* url,
+ const gnutls_x509_crt_t * certificate_list,
+ unsigned clist_size,
+ const char *purpose,
+ unsigned int flags,
+ gnutls_verify_output_function func);
#endif
int _gnutls_check_cert_sanity(gnutls_x509_crt_t cert);