]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
Several optimizations on certificate comparisons including DN. This speeds up CA...
authorNikos Mavrogiannopoulos <nmav@gnutls.org>
Tue, 5 Mar 2013 15:46:32 +0000 (16:46 +0100)
committerNikos Mavrogiannopoulos <nmav@gnutls.org>
Tue, 5 Mar 2013 18:48:48 +0000 (19:48 +0100)
lib/x509/common.c
lib/x509/common.h
lib/x509/crl.c
lib/x509/dn.c
lib/x509/ocsp.c
lib/x509/verify-high.c
lib/x509/verify.c
lib/x509/x509.c
lib/x509/x509_int.h

index 7557976ad312fa58b80e1802f4c486e6f026a2f2..d120e3bb3a977f1a4d0f99e47854184c9aece74d 100644 (file)
@@ -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;
+}
index 5aa5c8fa1d30361c5b20188808f406906bfcb385..ebffe489d7782608fe1811e5ab729364054c1a45 100644 (file)
@@ -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);
 
index 392ef3140c8fba70bff9b086d0e4965d025f7bca..152ab33ba9cb2d787a150cecd2551f9d717f1a86 100644 (file)
@@ -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);
 }
 
 /**
index 99d41ffcc5bc654978b39f807046cc29944fff0b..817f7b967886ba962975f01eec3d64bf2f4cb892 100644 (file)
@@ -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
index 7dd0f85619e208672e317498e891409088fe53dc..bec927a33276f8c97512944e60e16f099ce7492a 100644 (file)
@@ -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;
index fc594951988e8da45b76cd462c2abdef3100bcc9..ace0bf2672c2110573cd6eae111a3e83e7d3b1d4 100644 (file)
@@ -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;
 }
index 0d55ec471426687e31b84b799af05d69da71cd0a..6e25b079988199f2562d7c032cd0d2949400115e 100644 (file)
 #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;
 }
-
index 957328a8513128acea18b3bb78f1691253e12f3c..01455f924c65fb6fa5d00a7fdf410d37695874b1 100644 (file)
@@ -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;
         }
 
index 26ad9c45dcc306183b5193cb54c7f8300cded452..053f00c1ea0eb5fb8aa16504e8f6a138c9f28656 100644 (file)
@@ -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,