summaryrefslogtreecommitdiff
path: root/lib/x509
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2013-03-05 16:46:32 +0100
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2013-03-05 19:48:48 +0100
commitb71abe5d67d9812bc49d667cacb0e1f0267ccee5 (patch)
tree42696fd8613ecf5db242f27efb34bcea795aeb06 /lib/x509
parent291a467dbf4dd7576f899470c338bdd1bb483f02 (diff)
downloadgnutls-b71abe5d67d9812bc49d667cacb0e1f0267ccee5.tar.gz
Several optimizations on certificate comparisons including DN. This speeds up CA certificate loading, and certificate verification.
Diffstat (limited to 'lib/x509')
-rw-r--r--lib/x509/common.c32
-rw-r--r--lib/x509/common.h6
-rw-r--r--lib/x509/crl.c75
-rw-r--r--lib/x509/dn.c26
-rw-r--r--lib/x509/ocsp.c7
-rw-r--r--lib/x509/verify-high.c134
-rw-r--r--lib/x509/verify.c280
-rw-r--r--lib/x509/x509.c125
-rw-r--r--lib/x509/x509_int.h9
9 files changed, 203 insertions, 491 deletions
diff --git a/lib/x509/common.c b/lib/x509/common.c
index 7557976ad3..d120e3bb3a 100644
--- a/lib/x509/common.c
+++ b/lib/x509/common.c
@@ -1799,3 +1799,35 @@ cleanup:
return ret;
}
+
+int
+_gnutls_x509_get_raw_dn2 (ASN1_TYPE c2, gnutls_datum_t* raw,
+ const char *whom, gnutls_datum_t * dn)
+{
+ int result, len1;
+ int start1, end1;
+ result =
+ asn1_der_decoding_startEnd (c2, raw->data, raw->size,
+ whom, &start1, &end1);
+
+ if (result != ASN1_SUCCESS)
+ {
+ gnutls_assert ();
+ result = _gnutls_asn2err (result);
+ goto cleanup;
+ }
+
+ len1 = end1 - start1 + 1;
+
+ result = _gnutls_set_datum (dn, &raw->data[start1], len1);
+ if (result < 0)
+ {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ result = 0;
+
+cleanup:
+ return result;
+}
diff --git a/lib/x509/common.h b/lib/x509/common.h
index 5aa5c8fa1d..ebffe489d7 100644
--- a/lib/x509/common.h
+++ b/lib/x509/common.h
@@ -162,7 +162,11 @@ void _asnstr_append_name (char *name, size_t name_size, const char *part1,
const char *part2);
int
-check_if_same_cert (gnutls_x509_crt_t cert1, gnutls_x509_crt_t cert2);
+_gnutls_x509_get_raw_dn2 (ASN1_TYPE c2, gnutls_datum_t* raw,
+ const char *whom, gnutls_datum_t * dn);
+
+int
+_gnutls_check_if_same_cert (gnutls_x509_crt_t cert1, gnutls_x509_crt_t cert2);
time_t _gnutls_x509_generalTime2gtime (const char *ttime);
diff --git a/lib/x509/crl.c b/lib/x509/crl.c
index 392ef3140c..152ab33ba9 100644
--- a/lib/x509/crl.c
+++ b/lib/x509/crl.c
@@ -79,6 +79,7 @@ gnutls_x509_crl_deinit (gnutls_x509_crl_t crl)
if (crl->crl)
asn1_delete_structure (&crl->crl);
+ gnutls_free(crl->raw_issuer_dn.data);
gnutls_free (crl);
}
@@ -129,7 +130,6 @@ gnutls_x509_crl_import (gnutls_x509_crl_t crl,
need_free = 1;
}
-
result = asn1_der_decoding (&crl->crl, _data.data, _data.size, NULL);
if (result != ASN1_SUCCESS)
{
@@ -138,6 +138,15 @@ gnutls_x509_crl_import (gnutls_x509_crl_t crl,
goto cleanup;
}
+ result = _gnutls_x509_get_raw_dn2 (crl->crl, &_data,
+ "tbsCertList.issuer.rdnSequence",
+ &crl->raw_issuer_dn);
+ if (result < 0)
+ {
+ gnutls_assert ();
+ goto cleanup;
+ }
+
if (need_free)
_gnutls_free_datum (&_data);
@@ -146,6 +155,7 @@ gnutls_x509_crl_import (gnutls_x509_crl_t crl,
cleanup:
if (need_free)
_gnutls_free_datum (&_data);
+ _gnutls_free_datum (&crl->raw_issuer_dn);
return result;
}
@@ -574,68 +584,7 @@ int
gnutls_x509_crl_get_raw_issuer_dn (gnutls_x509_crl_t crl,
gnutls_datum_t * dn)
{
- ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
- int result, len1;
- int start1, end1;
- gnutls_datum_t crl_signed_data;
-
- if (crl == NULL)
- {
- gnutls_assert ();
- return GNUTLS_E_INVALID_REQUEST;
- }
-
- /* get the issuer of 'crl'
- */
- if ((result =
- asn1_create_element (_gnutls_get_pkix (), "PKIX1.TBSCertList",
- &c2)) != ASN1_SUCCESS)
- {
- gnutls_assert ();
- return _gnutls_asn2err (result);
- }
-
- result =
- _gnutls_x509_get_signed_data (crl->crl, "tbsCertList", &crl_signed_data);
- if (result < 0)
- {
- gnutls_assert ();
- goto cleanup;
- }
-
- result =
- asn1_der_decoding (&c2, crl_signed_data.data, crl_signed_data.size, NULL);
- if (result != ASN1_SUCCESS)
- {
- /* couldn't decode DER */
- gnutls_assert ();
- asn1_delete_structure (&c2);
- result = _gnutls_asn2err (result);
- goto cleanup;
- }
-
- result =
- asn1_der_decoding_startEnd (c2, crl_signed_data.data,
- crl_signed_data.size, "issuer",
- &start1, &end1);
-
- if (result != ASN1_SUCCESS)
- {
- gnutls_assert ();
- result = _gnutls_asn2err (result);
- goto cleanup;
- }
-
- len1 = end1 - start1 + 1;
-
- _gnutls_set_datum (dn, &crl_signed_data.data[start1], len1);
-
- result = 0;
-
-cleanup:
- asn1_delete_structure (&c2);
- _gnutls_free_datum (&crl_signed_data);
- return result;
+ return _gnutls_set_datum (dn, crl->raw_issuer_dn.data, crl->raw_issuer_dn.size);
}
/**
diff --git a/lib/x509/dn.c b/lib/x509/dn.c
index 99d41ffcc5..817f7b9678 100644
--- a/lib/x509/dn.c
+++ b/lib/x509/dn.c
@@ -1069,32 +1069,6 @@ gnutls_x509_rdn_get_oid (const gnutls_datum_t * idn,
}
-/*
- * Compares the DER encoded part of a DN.
- *
- * FIXME: use a real DN comparison algorithm.
- *
- * Returns 1 if the DN's match and (0) if they don't match. Otherwise
- * a negative error code is returned to indicate error.
- */
-int
-_gnutls_x509_compare_raw_dn (const gnutls_datum_t * dn1,
- const gnutls_datum_t * dn2)
-{
-
- if (dn1->size != dn2->size)
- {
- gnutls_assert ();
- return 0;
- }
- if (memcmp (dn1->data, dn2->data, dn2->size) != 0)
- {
- gnutls_assert ();
- return 0;
- }
- return 1; /* they match */
-}
-
/**
* gnutls_x509_dn_export:
* @dn: Holds the uint8_t DN object
diff --git a/lib/x509/ocsp.c b/lib/x509/ocsp.c
index 7dd0f85619..bec927a332 100644
--- a/lib/x509/ocsp.c
+++ b/lib/x509/ocsp.c
@@ -2241,12 +2241,7 @@ gnutls_ocsp_resp_verify (gnutls_ocsp_resp_t resp,
is directly signed by something in trustlist and has proper OCSP
extkeyusage. */
rc = _gnutls_trustlist_inlist (trustlist, signercert);
- if (rc < 0)
- {
- gnutls_assert ();
- goto done;
- }
- if (rc == 1)
+ if (rc == 0)
{
/* not in trustlist, need to verify signature and bits */
gnutls_x509_crt_t issuer;
diff --git a/lib/x509/verify-high.c b/lib/x509/verify-high.c
index fc59495198..ace0bf2672 100644
--- a/lib/x509/verify-high.c
+++ b/lib/x509/verify-high.c
@@ -159,21 +159,13 @@ gnutls_x509_trust_list_add_cas(gnutls_x509_trust_list_t list,
const gnutls_x509_crt_t * clist,
int clist_size, unsigned int flags)
{
- gnutls_datum_t dn;
- int ret, i;
+ int i;
uint32_t hash;
for (i = 0; i < clist_size; i++) {
- ret = gnutls_x509_crt_get_raw_dn(clist[i], &dn);
- if (ret < 0) {
- gnutls_assert();
- return i;
- }
-
- hash = hash_pjw_bare(dn.data, dn.size);
+ hash = hash_pjw_bare(clist[i]->raw_dn.data, clist[i]->raw_dn.size);
hash %= list->size;
- _gnutls_free_datum(&dn);
list->node[hash].trusted_cas =
gnutls_realloc_fast(list->node[hash].trusted_cas,
(list->node[hash].trusted_ca_size +
@@ -223,24 +215,14 @@ gnutls_x509_trust_list_add_named_crt(gnutls_x509_trust_list_t list,
const void *name, size_t name_size,
unsigned int flags)
{
- gnutls_datum_t dn;
- int ret;
uint32_t hash;
if (name_size >= MAX_SERVER_NAME_SIZE)
return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
- ret = gnutls_x509_crt_get_raw_issuer_dn(cert, &dn);
- if (ret < 0) {
- gnutls_assert();
- return ret;
- }
-
- hash = hash_pjw_bare(dn.data, dn.size);
+ hash = hash_pjw_bare(cert->raw_issuer_dn.data, cert->raw_issuer_dn.size);
hash %= list->size;
- _gnutls_free_datum(&dn);
-
list->node[hash].named_certs =
gnutls_realloc_fast(list->node[hash].named_certs,
(list->node[hash].named_cert_size +
@@ -286,29 +268,19 @@ gnutls_x509_trust_list_add_crls(gnutls_x509_trust_list_t list,
unsigned int verification_flags)
{
int ret, i, j = 0;
- gnutls_datum_t dn;
unsigned int vret = 0;
uint32_t hash;
/* Probably we can optimize things such as removing duplicates
* etc.
*/
-
if (crl_size == 0 || crl_list == NULL)
return 0;
for (i = 0; i < crl_size; i++) {
- ret = gnutls_x509_crl_get_raw_issuer_dn(crl_list[i], &dn);
- if (ret < 0) {
- gnutls_assert();
- return i;
- }
-
- hash = hash_pjw_bare(dn.data, dn.size);
+ hash = hash_pjw_bare(crl_list[i]->raw_issuer_dn.data, crl_list[i]->raw_issuer_dn.size);
hash %= list->size;
- _gnutls_free_datum(&dn);
-
if (flags & GNUTLS_TL_VERIFY_CRL) {
ret =
@@ -349,10 +321,8 @@ static int shorten_clist(gnutls_x509_trust_list_t list,
gnutls_x509_crt_t * certificate_list,
unsigned int clist_size)
{
- int ret;
unsigned int j, i;
uint32_t hash;
- gnutls_datum_t dn;
if (clist_size > 1) {
/* Check if the last certificate in the path is self signed.
@@ -366,7 +336,7 @@ static int shorten_clist(gnutls_x509_trust_list_t list,
*/
if (gnutls_x509_crt_check_issuer(certificate_list[clist_size - 1],
certificate_list[clist_size -
- 1]) > 0) {
+ 1]) != 0) {
clist_size--;
}
}
@@ -377,21 +347,13 @@ static int shorten_clist(gnutls_x509_trust_list_t list,
* self-signed E but already removed above), and we trust B, remove
* B, C and D. */
for (i = 1; i < clist_size; i++) {
- ret = gnutls_x509_crt_get_raw_issuer_dn(certificate_list[i], &dn);
- if (ret < 0) {
- gnutls_assert();
- return ret;
- }
-
- hash = hash_pjw_bare(dn.data, dn.size);
+ hash = hash_pjw_bare(certificate_list[i]->raw_issuer_dn.data, certificate_list[i]->raw_issuer_dn.size);
hash %= list->size;
- _gnutls_free_datum(&dn);
-
for (j = 0; j < list->node[hash].trusted_ca_size; j++) {
- if (check_if_same_cert
+ if (_gnutls_check_if_same_cert
(certificate_list[i],
- list->node[hash].trusted_cas[j]) == 0) {
+ list->node[hash].trusted_cas[j]) != 0) {
/* cut the list at the point of first the trusted certificate */
clist_size = i + 1;
break;
@@ -437,7 +399,7 @@ static gnutls_x509_crt_t* sort_clist(gnutls_x509_crt_t sorted[DEFAULT_MAX_VERIFY
if (i==j) continue;
if (gnutls_x509_crt_check_issuer(clist[i],
- clist[j]))
+ clist[j]) != 0)
{
issuer[i] = j;
break;
@@ -487,27 +449,18 @@ int gnutls_x509_trust_list_get_issuer(gnutls_x509_trust_list_t list,
gnutls_x509_crt_t * issuer,
unsigned int flags)
{
- gnutls_datum_t dn;
int ret;
unsigned int i;
uint32_t hash;
- ret = gnutls_x509_crt_get_raw_issuer_dn(cert, &dn);
- if (ret < 0) {
- gnutls_assert();
- return ret;
- }
-
- hash = hash_pjw_bare(dn.data, dn.size);
+ hash = hash_pjw_bare(cert->raw_issuer_dn.data, cert->raw_issuer_dn.size);
hash %= list->size;
- _gnutls_free_datum(&dn);
-
for (i = 0; i < list->node[hash].trusted_ca_size; i++) {
ret =
gnutls_x509_crt_check_issuer(cert,
list->node[hash].trusted_cas[i]);
- if (ret > 0) {
+ if (ret != 0) {
*issuer = list->node[hash].trusted_cas[i];
return 0;
}
@@ -544,7 +497,6 @@ gnutls_x509_trust_list_verify_crt(gnutls_x509_trust_list_t list,
unsigned int *verify,
gnutls_verify_output_function func)
{
- gnutls_datum_t dn;
int ret;
unsigned int i;
uint32_t hash;
@@ -560,19 +512,10 @@ gnutls_x509_trust_list_verify_crt(gnutls_x509_trust_list_t list,
if (cert_list_size <= 0)
return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
- ret =
- gnutls_x509_crt_get_raw_issuer_dn(cert_list[cert_list_size - 1],
- &dn);
- if (ret < 0) {
- gnutls_assert();
- return ret;
- }
-
- hash = hash_pjw_bare(dn.data, dn.size);
+ hash = hash_pjw_bare(cert_list[cert_list_size - 1]->raw_issuer_dn.data,
+ cert_list[cert_list_size - 1]->raw_issuer_dn.size);
hash %= list->size;
- _gnutls_free_datum(&dn);
-
*verify = _gnutls_x509_verify_certificate(cert_list, cert_list_size,
list->node[hash].trusted_cas,
list->node[hash].
@@ -596,17 +539,9 @@ gnutls_x509_trust_list_verify_crt(gnutls_x509_trust_list_t list,
}
for (i = 0; i < cert_list_size - 1; i++) {
- ret = gnutls_x509_crt_get_raw_issuer_dn(cert_list[i], &dn);
- if (ret < 0) {
- gnutls_assert();
- return ret;
- }
-
- hash = hash_pjw_bare(dn.data, dn.size);
+ hash = hash_pjw_bare(cert_list[i]->raw_issuer_dn.data, cert_list[i]->raw_issuer_dn.size);
hash %= list->size;
- _gnutls_free_datum(&dn);
-
ret = _gnutls_x509_crt_check_revocation(cert_list[i],
list->node[hash].crls,
list->node[hash].crl_size,
@@ -650,26 +585,17 @@ gnutls_x509_trust_list_verify_named_crt(gnutls_x509_trust_list_t list,
unsigned int *verify,
gnutls_verify_output_function func)
{
- gnutls_datum_t dn;
int ret;
unsigned int i;
uint32_t hash;
- ret = gnutls_x509_crt_get_raw_issuer_dn(cert, &dn);
- if (ret < 0) {
- gnutls_assert();
- return ret;
- }
-
- hash = hash_pjw_bare(dn.data, dn.size);
+ hash = hash_pjw_bare(cert->raw_issuer_dn.data, cert->raw_issuer_dn.size);
hash %= list->size;
- _gnutls_free_datum(&dn);
-
*verify = GNUTLS_CERT_INVALID | GNUTLS_CERT_SIGNER_NOT_FOUND;
for (i = 0; i < list->node[hash].named_cert_size; i++) {
- if (check_if_same_cert(cert, list->node[hash].named_certs[i].cert) == 0) { /* check if name matches */
+ if (_gnutls_check_if_same_cert(cert, list->node[hash].named_certs[i].cert) != 0) { /* check if name matches */
if (list->node[hash].named_certs[i].name_size == name_size &&
memcmp(list->node[hash].named_certs[i].name, name,
name_size) == 0) {
@@ -698,40 +624,24 @@ gnutls_x509_trust_list_verify_named_crt(gnutls_x509_trust_list_t list,
return 0;
}
-/* return 0 if @cert is in @list, 1 if not, or < 0 on error. */
+/* return 1 if @cert is in @list, 0 if not */
int
_gnutls_trustlist_inlist (gnutls_x509_trust_list_t list,
gnutls_x509_crt_t cert)
{
- gnutls_datum_t dn;
int ret;
unsigned int i;
uint32_t hash;
- ret = gnutls_x509_crt_get_raw_dn (cert, &dn);
- if (ret < 0)
- {
- gnutls_assert();
- return ret;
- }
-
- hash = hash_pjw_bare(dn.data, dn.size);
+ hash = hash_pjw_bare(cert->raw_dn.data, cert->raw_dn.size);
hash %= list->size;
- _gnutls_free_datum (&dn);
-
for (i = 0; i < list->node[hash].trusted_ca_size; i++)
{
- ret = check_if_same_cert (cert, list->node[hash].trusted_cas[i]);
- if (ret < 0)
- {
- gnutls_assert ();
- return ret;
- }
-
- if (ret == 0)
- return 0;
+ ret = _gnutls_check_if_same_cert (cert, list->node[hash].trusted_cas[i]);
+ if (ret != 0)
+ return 1;
}
- return 1;
+ return 0;
}
diff --git a/lib/x509/verify.c b/lib/x509/verify.c
index 0d55ec4714..6e25b07998 100644
--- a/lib/x509/verify.c
+++ b/lib/x509/verify.c
@@ -36,51 +36,22 @@
#include <common.h>
#include <gnutls_pk.h>
-static int is_crl_issuer (gnutls_x509_crl_t crl,
- gnutls_x509_crt_t issuer_cert);
-
-static int _gnutls_verify_crl2 (gnutls_x509_crl_t crl,
- const gnutls_x509_crt_t * trusted_cas,
- int tcas_size, unsigned int flags,
- unsigned int *output);
-
-/* Checks if two certs are identical. Return 0 on match. */
+/* Checks if two certs are identical. Return 1 on match. */
int
-check_if_same_cert (gnutls_x509_crt_t cert1, gnutls_x509_crt_t cert2)
+_gnutls_check_if_same_cert (gnutls_x509_crt_t cert1, gnutls_x509_crt_t cert2)
{
gnutls_datum_t cert1bin = { NULL, 0 }, cert2bin =
- {
- NULL, 0};
+ { NULL, 0};
int result;
- uint8_t serial1[128], serial2[128];
- size_t serial1_size, serial2_size;
- serial1_size = sizeof (serial1);
- result = gnutls_x509_crt_get_serial (cert1, serial1, &serial1_size);
- if (result < 0)
- {
- gnutls_assert ();
- goto cmp;
- }
+ result = _gnutls_is_same_dn (cert1, cert2);
+ if (result == 0)
+ return 0;
- serial2_size = sizeof (serial2);
- result = gnutls_x509_crt_get_serial (cert2, serial2, &serial2_size);
- if (result < 0)
- {
- gnutls_assert ();
- goto cmp;
- }
-
- if (serial2_size != serial1_size
- || memcmp (serial1, serial2, serial1_size) != 0)
- {
- return 1;
- }
-
-cmp:
result = _gnutls_x509_der_encode (cert1->cert, "", &cert1bin, 0);
if (result < 0)
{
+ result = 0;
gnutls_assert ();
goto cleanup;
}
@@ -88,15 +59,16 @@ cmp:
result = _gnutls_x509_der_encode (cert2->cert, "", &cert2bin, 0);
if (result < 0)
{
+ result = 0;
gnutls_assert ();
goto cleanup;
}
if ((cert1bin.size == cert2bin.size) &&
(memcmp (cert1bin.data, cert2bin.data, cert1bin.size) == 0))
- result = 0;
- else
result = 1;
+ else
+ result = 0;
cleanup:
_gnutls_free_datum (&cert1bin);
@@ -202,7 +174,7 @@ check_if_ca (gnutls_x509_crt_t cert, gnutls_x509_crt_t issuer,
else if ((result == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) &&
((flags & GNUTLS_VERIFY_ALLOW_ANY_X509_V1_CA_CRT) ||
(!(flags & GNUTLS_VERIFY_DO_NOT_ALLOW_X509_V1_CA_CRT) &&
- (gnutls_x509_crt_check_issuer (issuer, issuer) == 1))))
+ (gnutls_x509_crt_check_issuer (issuer, issuer) != 0))))
{
gnutls_assert ();
result = 1;
@@ -222,40 +194,27 @@ cleanup:
}
-/* This function checks if 'certs' issuer is 'issuer_cert'.
- * This does a straight (DER) compare of the issuer/subject fields in
- * the given certificates.
+/* This function checks if cert's issuer is issuer.
+ * This does a straight (DER) compare of the issuer/subject DN fields in
+ * the given certificates, as well as check the authority key ID.
*
- * Returns 1 if they match and (0) if they don't match. Otherwise
- * a negative error code is returned to indicate error.
+ * Returns 1 if they match and (0) if they don't match.
*/
static int
-is_issuer (gnutls_x509_crt_t cert, gnutls_x509_crt_t issuer_cert)
+is_issuer (gnutls_x509_crt_t cert, gnutls_x509_crt_t issuer)
{
- gnutls_datum_t dn1 = { NULL, 0 },
- dn2 = { NULL, 0};
uint8_t id1[512];
uint8_t id2[512];
size_t id1_size;
size_t id2_size;
int ret;
- ret = gnutls_x509_crt_get_raw_issuer_dn (cert, &dn1);
- if (ret < 0)
- {
- gnutls_assert ();
- goto cleanup;
- }
-
- ret = gnutls_x509_crt_get_raw_dn (issuer_cert, &dn2);
- if (ret < 0)
- {
- gnutls_assert ();
- goto cleanup;
- }
+ if (cert->raw_issuer_dn.size == issuer->raw_dn.size &&
+ memcmp(cert->raw_issuer_dn.data, issuer->raw_dn.data, issuer->raw_dn.size) == 0)
+ ret = 1;
+ else
+ ret = 0;
- ret = _gnutls_x509_compare_raw_dn (&dn1, &dn2);
-
if (ret != 0)
{
/* check if the authority key identifier matches the subject key identifier
@@ -270,7 +229,7 @@ is_issuer (gnutls_x509_crt_t cert, gnutls_x509_crt_t issuer_cert)
}
id2_size = sizeof(id2);
- ret = gnutls_x509_crt_get_subject_key_id(issuer_cert, id2, &id2_size, NULL);
+ ret = gnutls_x509_crt_get_subject_key_id(issuer, id2, &id2_size, NULL);
if (ret < 0)
{
ret = 1;
@@ -285,10 +244,20 @@ is_issuer (gnutls_x509_crt_t cert, gnutls_x509_crt_t issuer_cert)
}
cleanup:
- _gnutls_free_datum (&dn1);
- _gnutls_free_datum (&dn2);
return ret;
+}
+/* Check if the given certificate is the issuer of the CRL.
+ * Returns 1 on success and 0 otherwise.
+ */
+static int
+is_crl_issuer (gnutls_x509_crl_t crl, gnutls_x509_crt_t issuer)
+{
+ if (crl->raw_issuer_dn.size == issuer->raw_dn.size &&
+ memcmp(crl->raw_issuer_dn.data, issuer->raw_dn.data, issuer->raw_dn.size) == 0)
+ return 1;
+ else
+ return 0;
}
/* Checks if the DN of two certificates is the same.
@@ -298,31 +267,11 @@ cleanup:
int
_gnutls_is_same_dn (gnutls_x509_crt_t cert1, gnutls_x509_crt_t cert2)
{
- gnutls_datum_t dn1 = { NULL, 0 }, dn2 =
- {
- NULL, 0};
- int ret;
-
- ret = gnutls_x509_crt_get_raw_dn (cert1, &dn1);
- if (ret < 0)
- {
- gnutls_assert ();
- goto cleanup;
- }
-
- ret = gnutls_x509_crt_get_raw_dn (cert2, &dn2);
- if (ret < 0)
- {
- gnutls_assert ();
- goto cleanup;
- }
-
- ret = _gnutls_x509_compare_raw_dn (&dn1, &dn2);
-
-cleanup:
- _gnutls_free_datum (&dn1);
- _gnutls_free_datum (&dn2);
- return ret;
+ if (cert1->raw_dn.size == cert2->raw_dn.size &&
+ memcmp(cert1->raw_dn.data, cert2->raw_dn.data, cert2->raw_dn.size) == 0)
+ return 1;
+ else
+ return 0;
}
/* Finds an issuer of the certificate. If multiple issuers
@@ -340,7 +289,7 @@ gnutls_x509_crt_t issuer = NULL;
for (i = 0; i < tcas_size; i++)
{
- if (is_issuer (cert, trusted_cas[i]) == 1)
+ if (is_issuer (cert, trusted_cas[i]) != 0)
{
if (issuer == NULL)
{
@@ -598,8 +547,7 @@ cleanup:
* key identifier and subject key identifier fields match.
*
* Returns: It will return true (1) if the given certificate is issued
- * by the given issuer, and false (0) if not. A negative error code is
- * returned in case of an error.
+ * by the given issuer, and false (0) if not.
**/
int
gnutls_x509_crt_check_issuer (gnutls_x509_crt_t cert,
@@ -641,7 +589,7 @@ _gnutls_x509_verify_certificate (const gnutls_x509_crt_t * certificate_list,
* MD2 algorithm.
*/
if (gnutls_x509_crt_check_issuer (certificate_list[clist_size - 1],
- certificate_list[clist_size - 1]) > 0)
+ certificate_list[clist_size - 1]) != 0)
{
clist_size--;
}
@@ -663,7 +611,7 @@ _gnutls_x509_verify_certificate (const gnutls_x509_crt_t * certificate_list,
for (j = 0; j < tcas_size; j++)
{
- if (check_if_same_cert (certificate_list[i], trusted_cas[j]) == 0)
+ if (_gnutls_check_if_same_cert (certificate_list[i], trusted_cas[j]) != 0)
{
/* explicity time check for trusted CA that we remove from
* list. GNUTLS_VERIFY_DISABLE_TRUSTED_TIME_CHECKS
@@ -898,11 +846,10 @@ 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. It will return true (1) if the given CRL was
- * issued by the given issuer, and false (0) if not.
+ * issuer certificate.
*
- * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
- * negative error value.
+ * Returns: true (1) if the given CRL was issued by the given issuer,
+ * and false (0) if not.
**/
int
gnutls_x509_crl_check_issuer (gnutls_x509_crl_t crl,
@@ -911,75 +858,6 @@ gnutls_x509_crl_check_issuer (gnutls_x509_crl_t crl,
return is_crl_issuer (crl, issuer);
}
-/**
- * gnutls_x509_crl_verify:
- * @crl: is the crl to be verified
- * @CA_list: is a certificate list that is considered to be trusted one
- * @CA_list_length: holds the number of CA certificates in CA_list
- * @flags: Flags that may be used to change the verification algorithm. Use OR of the gnutls_certificate_verify_flags enumerations.
- * @verify: will hold the crl verification output.
- *
- * This function will try to verify the given crl and return its status.
- * See gnutls_x509_crt_list_verify() for a detailed description of
- * return values. Note that since GnuTLS 3.1.4 this function includes
- * the time checks.
- *
- * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
- * negative error value.
- **/
-int
-gnutls_x509_crl_verify (gnutls_x509_crl_t crl,
- const gnutls_x509_crt_t * CA_list,
- int CA_list_length, unsigned int flags,
- unsigned int *verify)
-{
- int ret;
- /* Verify crl
- */
- ret = _gnutls_verify_crl2 (crl, CA_list, CA_list_length, flags, verify);
- if (ret < 0)
- {
- gnutls_assert ();
- return ret;
- }
-
- return 0;
-}
-
-
-/* The same as above, but here we've got a CRL.
- */
-static int
-is_crl_issuer (gnutls_x509_crl_t crl, gnutls_x509_crt_t issuer_cert)
-{
- gnutls_datum_t dn1 = { NULL, 0 }, dn2 =
- {
- NULL, 0};
- int ret;
-
- ret = gnutls_x509_crl_get_raw_issuer_dn (crl, &dn1);
- if (ret < 0)
- {
- gnutls_assert ();
- goto cleanup;
- }
-
- ret = gnutls_x509_crt_get_raw_dn (issuer_cert, &dn2);
- if (ret < 0)
- {
- gnutls_assert ();
- return ret;
- }
-
- ret = _gnutls_x509_compare_raw_dn (&dn1, &dn2);
-
-cleanup:
- _gnutls_free_datum (&dn1);
- _gnutls_free_datum (&dn2);
-
- return ret;
-}
-
static inline gnutls_x509_crt_t
find_crl_issuer (gnutls_x509_crl_t crl,
const gnutls_x509_crt_t * trusted_cas, int tcas_size)
@@ -991,7 +869,7 @@ find_crl_issuer (gnutls_x509_crl_t crl,
for (i = 0; i < tcas_size; i++)
{
- if (is_crl_issuer (crl, trusted_cas[i]) == 1)
+ if (is_crl_issuer (crl, trusted_cas[i]) != 0)
return trusted_cas[i];
}
@@ -999,19 +877,30 @@ find_crl_issuer (gnutls_x509_crl_t crl,
return NULL;
}
-/*
- * Returns only 0 or 1. If 1 it means that the CRL
- * was successfuly verified.
+/**
+ * gnutls_x509_crl_verify:
+ * @crl: is the crl to be verified
+ * @trusted_cas: is a certificate list that is considered to be trusted one
+ * @tcas_size: holds the number of CA certificates in CA_list
+ * @flags: Flags that may be used to change the verification algorithm. Use OR of the gnutls_certificate_verify_flags enumerations.
+ * @verify: will hold the crl verification output.
*
- * 'flags': an OR of the gnutls_certificate_verify_flags enumeration.
+ * This function will try to verify the given crl and return its verification status.
+ * See gnutls_x509_crt_list_verify() for a detailed description of
+ * return values. Note that since GnuTLS 3.1.4 this function includes
+ * the time checks.
*
- * Output will hold information about the verification
- * procedure.
- */
-static int
-_gnutls_verify_crl2 (gnutls_x509_crl_t crl,
- const gnutls_x509_crt_t * trusted_cas,
- int tcas_size, unsigned int flags, unsigned int *output)
+ * Note that value in @verify is set only when the return value of this
+ * function is success (i.e, failure to trust a CRL a certificate does not imply
+ * a negative return value).
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
+ * negative error value.
+ **/
+int
+gnutls_x509_crl_verify (gnutls_x509_crl_t crl,
+ const gnutls_x509_crt_t * trusted_cas,
+ int tcas_size, unsigned int flags, unsigned int *verify)
{
/* CRL is ignored for now */
gnutls_datum_t crl_signed_data = { NULL, 0 };
@@ -1021,8 +910,8 @@ _gnutls_verify_crl2 (gnutls_x509_crl_t crl,
time_t now = gnutls_time(0);
unsigned int usage;
- if (output)
- *output = 0;
+ if (verify)
+ *verify = 0;
if (tcas_size >= 1)
issuer = find_crl_issuer (crl, trusted_cas, tcas_size);
@@ -1033,8 +922,8 @@ _gnutls_verify_crl2 (gnutls_x509_crl_t crl,
if (issuer == NULL)
{
gnutls_assert ();
- if (output)
- *output |= GNUTLS_CERT_SIGNER_NOT_FOUND | GNUTLS_CERT_INVALID;
+ if (verify)
+ *verify |= GNUTLS_CERT_SIGNER_NOT_FOUND | GNUTLS_CERT_INVALID;
return 0;
}
@@ -1043,8 +932,8 @@ _gnutls_verify_crl2 (gnutls_x509_crl_t crl,
if (gnutls_x509_crt_get_ca_status (issuer, NULL) != 1)
{
gnutls_assert ();
- if (output)
- *output |= GNUTLS_CERT_SIGNER_NOT_CA | GNUTLS_CERT_INVALID;
+ if (verify)
+ *verify |= GNUTLS_CERT_SIGNER_NOT_CA | GNUTLS_CERT_INVALID;
return 0;
}
@@ -1054,8 +943,8 @@ _gnutls_verify_crl2 (gnutls_x509_crl_t crl,
if (!(usage & GNUTLS_KEY_CRL_SIGN))
{
gnutls_assert();
- if (output)
- *output |= GNUTLS_CERT_SIGNER_CONSTRAINTS_FAILURE | GNUTLS_CERT_INVALID;
+ if (verify)
+ *verify |= GNUTLS_CERT_SIGNER_CONSTRAINTS_FAILURE | GNUTLS_CERT_INVALID;
return 0;
}
}
@@ -1092,8 +981,8 @@ _gnutls_verify_crl2 (gnutls_x509_crl_t crl,
{
gnutls_assert ();
/* error. ignore it */
- if (output)
- *output |= GNUTLS_CERT_SIGNATURE_FAILURE;
+ if (verify)
+ *verify |= GNUTLS_CERT_SIGNATURE_FAILURE;
result = 0;
}
else if (result < 0)
@@ -1112,25 +1001,24 @@ _gnutls_verify_crl2 (gnutls_x509_crl_t crl,
((sigalg == GNUTLS_SIGN_RSA_MD5) &&
!(flags & GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5)))
{
- if (output)
- *output |= GNUTLS_CERT_INSECURE_ALGORITHM;
+ if (verify)
+ *verify |= GNUTLS_CERT_INSECURE_ALGORITHM;
result = 0;
}
}
if (gnutls_x509_crl_get_this_update (crl) > now)
- *output |= GNUTLS_CERT_REVOCATION_DATA_ISSUED_IN_FUTURE;
+ *verify |= GNUTLS_CERT_REVOCATION_DATA_ISSUED_IN_FUTURE;
if (gnutls_x509_crl_get_next_update (crl) < now)
- *output |= GNUTLS_CERT_REVOCATION_DATA_SUPERSEDED;
+ *verify |= GNUTLS_CERT_REVOCATION_DATA_SUPERSEDED;
cleanup:
- if (*output) *output |= GNUTLS_CERT_INVALID;
+ if (*verify) *verify |= GNUTLS_CERT_INVALID;
_gnutls_free_datum (&crl_signed_data);
_gnutls_free_datum (&crl_signature);
return result;
}
-
diff --git a/lib/x509/x509.c b/lib/x509/x509.c
index 957328a851..01455f924c 100644
--- a/lib/x509/x509.c
+++ b/lib/x509/x509.c
@@ -137,7 +137,8 @@ gnutls_x509_crt_deinit (gnutls_x509_crt_t cert)
if (cert->cert)
asn1_delete_structure (&cert->cert);
-
+ gnutls_free(cert->raw_dn.data);
+ gnutls_free(cert->raw_issuer_dn.data);
gnutls_free (cert);
}
@@ -205,6 +206,8 @@ gnutls_x509_crt_import (gnutls_x509_crt_t cert,
structure, so we need to replace it with a fresh
structure. */
asn1_delete_structure (&cert->cert);
+ _gnutls_free_datum(&cert->raw_dn);
+ _gnutls_free_datum(&cert->raw_issuer_dn);
result = asn1_create_element (_gnutls_get_pkix (),
"PKIX1.Certificate", &cert->cert);
@@ -224,6 +227,24 @@ gnutls_x509_crt_import (gnutls_x509_crt_t cert,
goto cleanup;
}
+ result = _gnutls_x509_get_raw_dn2 (cert->cert, &_data,
+ "tbsCertificate.issuer.rdnSequence",
+ &cert->raw_issuer_dn);
+ if (result < 0)
+ {
+ gnutls_assert ();
+ goto cleanup;
+ }
+
+ result = _gnutls_x509_get_raw_dn2 (cert->cert, &_data,
+ "tbsCertificate.subject.rdnSequence",
+ &cert->raw_dn);
+ if (result < 0)
+ {
+ gnutls_assert ();
+ goto cleanup;
+ }
+
cert->expanded = 1;
/* Since we do not want to disable any extension
@@ -237,6 +258,8 @@ gnutls_x509_crt_import (gnutls_x509_crt_t cert,
cleanup:
if (need_free)
_gnutls_free_datum (&_data);
+ _gnutls_free_datum (&cert->raw_dn);
+ _gnutls_free_datum (&cert->raw_issuer_dn);
return result;
}
@@ -2313,69 +2336,10 @@ gnutls_x509_crt_get_extension_data (gnutls_x509_crt_t cert, int indx,
return 0;
}
-static int
-_gnutls_x509_crt_get_raw_dn2 (gnutls_x509_crt_t cert,
- const char *whom, gnutls_datum_t * start)
-{
- ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
- int result, len1;
- int start1, end1;
- gnutls_datum_t signed_data = { NULL, 0 };
-
- /* get the issuer of 'cert'
- */
- if ((result =
- asn1_create_element (_gnutls_get_pkix (), "PKIX1.TBSCertificate",
- &c2)) != ASN1_SUCCESS)
- {
- gnutls_assert ();
- return _gnutls_asn2err (result);
- }
-
- result =
- _gnutls_x509_get_signed_data (cert->cert, "tbsCertificate", &signed_data);
- if (result < 0)
- {
- gnutls_assert ();
- goto cleanup;
- }
-
- result = asn1_der_decoding (&c2, signed_data.data, signed_data.size, NULL);
- if (result != ASN1_SUCCESS)
- {
- gnutls_assert ();
- asn1_delete_structure (&c2);
- result = _gnutls_asn2err (result);
- goto cleanup;
- }
-
- result =
- asn1_der_decoding_startEnd (c2, signed_data.data, signed_data.size,
- whom, &start1, &end1);
-
- if (result != ASN1_SUCCESS)
- {
- gnutls_assert ();
- result = _gnutls_asn2err (result);
- goto cleanup;
- }
-
- len1 = end1 - start1 + 1;
-
- _gnutls_set_datum (start, &signed_data.data[start1], len1);
-
- result = 0;
-
-cleanup:
- asn1_delete_structure (&c2);
- _gnutls_free_datum (&signed_data);
- return result;
-}
-
/**
* gnutls_x509_crt_get_raw_issuer_dn:
* @cert: should contain a #gnutls_x509_crt_t structure
- * @start: will hold the starting point of the DN
+ * @dn: will hold the starting point of the DN
*
* This function will return a pointer to the DER encoded DN structure
* and the length. This points to allocated data that must be free'd using gnutls_free().
@@ -2386,15 +2350,15 @@ cleanup:
**/
int
gnutls_x509_crt_get_raw_issuer_dn (gnutls_x509_crt_t cert,
- gnutls_datum_t * start)
+ gnutls_datum_t * dn)
{
- return _gnutls_x509_crt_get_raw_dn2 (cert, "issuer", start);
+ return _gnutls_set_datum (dn, cert->raw_issuer_dn.data, cert->raw_issuer_dn.size);
}
/**
* gnutls_x509_crt_get_raw_dn:
* @cert: should contain a #gnutls_x509_crt_t structure
- * @start: will hold the starting point of the DN
+ * @dn: will hold the starting point of the DN
*
* This function will return a pointer to the DER encoded DN structure and
* the length. This points to allocated data that must be free'd using gnutls_free().
@@ -2404,9 +2368,9 @@ gnutls_x509_crt_get_raw_issuer_dn (gnutls_x509_crt_t cert,
*
**/
int
-gnutls_x509_crt_get_raw_dn (gnutls_x509_crt_t cert, gnutls_datum_t * start)
+gnutls_x509_crt_get_raw_dn (gnutls_x509_crt_t cert, gnutls_datum_t * dn)
{
- return _gnutls_x509_crt_get_raw_dn2 (cert, "subject", start);
+ return _gnutls_set_datum (dn, cert->raw_dn.data, cert->raw_dn.size);
}
static int
@@ -2798,6 +2762,15 @@ gnutls_x509_crt_get_key_id (gnutls_x509_crt_t crt, unsigned int flags,
return ret;
}
+static int
+crl_issuer_matches (gnutls_x509_crl_t crl, gnutls_x509_crt_t cert)
+{
+ if (crl->raw_issuer_dn.size == cert->raw_issuer_dn.size &&
+ memcmp(crl->raw_issuer_dn.data, cert->raw_issuer_dn.data, cert->raw_issuer_dn.size) == 0)
+ return 1;
+ else
+ return 0;
+}
/* This is exactly as gnutls_x509_crt_check_revocation() except that
* it calls func.
@@ -2812,7 +2785,6 @@ _gnutls_x509_crt_check_revocation (gnutls_x509_crt_t cert,
uint8_t cert_serial[128];
size_t serial_size, cert_serial_size;
int ncerts, ret, i, j;
- gnutls_datum_t dn1, dn2;
if (cert == NULL)
{
@@ -2825,28 +2797,13 @@ _gnutls_x509_crt_check_revocation (gnutls_x509_crt_t cert,
/* Step 1. check if issuer's DN match
*/
- ret = gnutls_x509_crl_get_raw_issuer_dn (crl_list[j], &dn1);
- if (ret < 0)
- {
- gnutls_assert ();
- return ret;
- }
-
- ret = gnutls_x509_crt_get_raw_issuer_dn (cert, &dn2);
- if (ret < 0)
- {
- gnutls_assert ();
- return ret;
- }
-
- ret = _gnutls_x509_compare_raw_dn (&dn1, &dn2);
- _gnutls_free_datum (&dn1);
- _gnutls_free_datum (&dn2);
+ ret = crl_issuer_matches(crl_list[j], cert);
if (ret == 0)
{
/* issuers do not match so don't even
* bother checking.
*/
+ gnutls_assert();
continue;
}
diff --git a/lib/x509/x509_int.h b/lib/x509/x509_int.h
index 26ad9c45dc..053f00c1ea 100644
--- a/lib/x509/x509_int.h
+++ b/lib/x509/x509_int.h
@@ -44,6 +44,7 @@ typedef struct gnutls_x509_crl_int
{
ASN1_TYPE crl;
int use_extensions;
+ gnutls_datum_t raw_issuer_dn;
} gnutls_x509_crl_int;
typedef struct gnutls_x509_crt_int
@@ -51,6 +52,11 @@ typedef struct gnutls_x509_crt_int
ASN1_TYPE cert;
int use_extensions;
int expanded; /* a certificate has been expanded */
+
+ /* These two cached values allow fast calls to
+ * get_raw_*_dn(). */
+ gnutls_datum_t raw_dn;
+ gnutls_datum_t raw_issuer_dn;
struct pin_info_st pin;
} gnutls_x509_crt_int;
@@ -80,9 +86,6 @@ typedef struct gnutls_x509_privkey_int
int _gnutls_x509_crt_cpy (gnutls_x509_crt_t dest, gnutls_x509_crt_t src);
-int _gnutls_x509_compare_raw_dn (const gnutls_datum_t * dn1,
- const gnutls_datum_t * dn2);
-
int _gnutls_x509_crl_cpy (gnutls_x509_crl_t dest, gnutls_x509_crl_t src);
int _gnutls_x509_crl_get_raw_issuer_dn (gnutls_x509_crl_t crl,