gnutls-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: gnutls fails to use Verisign CA cert without a Basic Constraint


From: Douglas E. Engert
Subject: Re: gnutls fails to use Verisign CA cert without a Basic Constraint
Date: Mon, 12 Jan 2009 14:09:49 -0600
User-agent: Thunderbird 2.0.0.19 (Windows/20081209)



Simon Josefsson wrote:
"Douglas E. Engert" <address@hidden> writes:

OK, see form below.

You need to send it to address@hidden, I could forward it but I think
they want it directly from the submitter.

OK, sent the form, first time was wrong address.

If you were to create a check_if_same_cert routine the actual code
to shorten the cert chain is only 7 lines, not counting
comments, "{" or "}" lines.

Here is a verify.c patch (Against Ubuntu version) that does the following:

added routine check_if_same_cert() to test if two certs are identical,
using the method used in check_if_ca.
(Note: check_if_ca could call check_if_same_cert too, but it made
the patch file hard to read.)

Adds this code:

+    /* We want to shorten the chain by removing the cert that matches
+     * one of the certs we trust and all the certs after that
+     * i.e. if cert chain is A, B, C, and we trust B, remove B and C
+     * we must leave the first cert on chain. */
+    if (clist_size > 1)
+    {
+      for (i = 1; i < clist_size; i++)
+      {
+        int j;
+           for (j = 0; j < tcas_size; j++)
+        {
+          if (check_if_same_cert ( certificate_list[i], trusted_cas[j], flags) 
== 1)
+          {
+              clist_size = i;
+              break;
+          }
+        }
+        /* clist_size may have been changed which gets out of loop */
+      }
+    }
+


Add the recent patches to get the if corrected, and added the patch
for  flags &= ~GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT;

--

 Douglas E. Engert  <address@hidden>
 Argonne National Laboratory
 9700 South Cass Avenue
 Argonne, Illinois  60439
 (630) 252-5444
--- ,verify.c   2009-01-06 14:02:41.000000000 -0600
+++ verify.c    2009-01-12 13:12:34.000000000 -0600
@@ -56,6 +56,79 @@
                                int tcas_size, unsigned int flags,
                                unsigned int *output);
 
+/* Checks if two certs are identical */
+
+static int
+check_if_same_cert (gnutls_x509_crt_t cert1, gnutls_x509_crt_t cert2,
+            unsigned int flags)
+{
+  gnutls_datum_t cert1_signed_data = { NULL, 0 };
+  gnutls_datum_t cert2_signed_data = { NULL, 0 };
+  gnutls_datum_t cert1_signature = { NULL, 0 };
+  gnutls_datum_t cert2_signature = { NULL, 0 };
+  int result;
+
+  result =
+    _gnutls_x509_get_signed_data (cert2->cert, "tbsCertificate",
+                                 &cert2_signed_data);
+  if (result < 0)
+    {
+      gnutls_assert ();
+      goto cleanup;
+    }
+
+  result =
+    _gnutls_x509_get_signed_data (cert1->cert, "tbsCertificate",
+                                 &cert1_signed_data);
+  if (result < 0)
+    {
+      gnutls_assert ();
+      goto cleanup;
+    }
+
+  result =
+    _gnutls_x509_get_signature (cert2->cert, "signature", &cert2_signature);
+  if (result < 0)
+    {
+      gnutls_assert ();
+      goto cleanup;
+    }
+
+  result =
+    _gnutls_x509_get_signature (cert1->cert, "signature", &cert1_signature);
+  if (result < 0)
+    {
+      gnutls_assert ();
+      goto cleanup;
+    }
+
+  /* If the  cert1 is the same as the cert2
+   * return true.
+   */
+  if (!(flags & GNUTLS_VERIFY_DO_NOT_ALLOW_SAME))
+    if (cert1_signed_data.size == cert2_signed_data.size)
+      {
+       if ((memcmp (cert1_signed_data.data, cert2_signed_data.data,
+                    cert1_signed_data.size) == 0) &&
+           (cert1_signature.size == cert2_signature.size) &&
+           (memcmp (cert1_signature.data, cert2_signature.data,
+                    cert1_signature.size) == 0))
+         {
+           result = 1;
+           goto cleanup;
+         }
+      }
+
+  result = 0;
+
+cleanup:
+  _gnutls_free_datum (&cert1_signed_data);
+  _gnutls_free_datum (&cert2_signed_data);
+  _gnutls_free_datum (&cert1_signature);
+  _gnutls_free_datum (&cert2_signature);
+  return result;
+}
+
 
 /* Checks if the issuer of a certificate is a
  * Certificate Authority, or if the certificate is the same
@@ -130,11 +203,23 @@
          }
       }
 
-  if (gnutls_x509_crt_get_ca_status (issuer, NULL) == 1)
+  result=gnutls_x509_crt_get_ca_status (issuer, NULL);
+  if (result == 1)
     {
       result = 1;
       goto cleanup;
     }
+  /* Handle V1 CAs that do not have a basicConstraint, but accept
+     these certs only if the appropriate flags are set. */
+  else if ((result == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) &&
+          ((flags & GNUTLS_VERIFY_ALLOW_ANY_X509_V1_CA_CRT) ||
+          ((flags & GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT) &&
+            (gnutls_x509_crt_check_issuer (issuer, issuer) == 1))))
+  {
+    gnutls_assert ();
+    result = 1;
+    goto cleanup;
+  }
   else
     gnutls_assert ();
 
@@ -397,6 +482,28 @@
         }
     }
 
+    /* We want to shorten the chain by removing the cert that matches
+     * one of the certs we trust and all the certs after that 
+     * i.e. if cert chain is A, B, C, and we trust B, remove B and C 
+     * we must leave the first cert on chain. */
+    if (clist_size > 1)
+    {
+      for (i = 1; i < clist_size; i++)
+      {
+        int j;
+           for (j = 0; j < tcas_size; j++)
+        {
+          if (check_if_same_cert ( certificate_list[i], trusted_cas[j], flags) 
== 1)
+          {
+              clist_size = i;
+              break;
+          }
+        }
+        /* clist_size may have been changed which gets out of loop */
+      }
+    }
+   
+
   /* Verify the last certificate in the certificate path
    * against the trusted CA certificate list.
    *
@@ -446,7 +553,7 @@
        * certificates can exist in a supplied chain.
        */
       if (!(flags & GNUTLS_VERIFY_ALLOW_ANY_X509_V1_CA_CRT))
-       flags ^= GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT;
+       flags &= ~GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT;
       if ((ret =
           _gnutls_verify_certificate2 (certificate_list[i - 1],
                                        &certificate_list[i], 1, flags,

reply via email to

[Prev in Thread] Current Thread [Next in Thread]