gnutls-commit
[Top][All Lists]
Advanced

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

[SCM] GNU gnutls branch, master, updated. gnutls_2_11_6-71-g1750efb


From: Nikos Mavrogiannopoulos
Subject: [SCM] GNU gnutls branch, master, updated. gnutls_2_11_6-71-g1750efb
Date: Mon, 31 Jan 2011 22:15:37 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU gnutls".

http://git.savannah.gnu.org/cgit/gnutls.git/commit/?id=1750efbbd46e4141985cb4561df521591366e16f

The branch, master has been updated
       via  1750efbbd46e4141985cb4561df521591366e16f (commit)
       via  88d80080a07b719cec937374e52de6e2392b0205 (commit)
       via  96d232a164773ae89f782808f96f1243dcea4e7e (commit)
       via  115ea68a5986c63dab5524794b8e65c971d8380d (commit)
       via  441eccc7be861374b9b4ef4aeca15a25655ef5c4 (commit)
       via  c9a64eae05818161f2a92cc9e2e76de3045a1ce5 (commit)
       via  14406d26fa1119a20dc48dc54a739f65c35dea28 (commit)
       via  457d7b147fde9d78ae532afd4c4c9ce5e2352afc (commit)
       via  e43f90fea05d2578ab8398fafda644eb8977b4d9 (commit)
      from  c82982437256db0a95f2daa28a3cfa0575f84fef (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 1750efbbd46e4141985cb4561df521591366e16f
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Mon Jan 31 23:09:32 2011 +0100

    Modified output to not confuse earlier scripts.

commit 88d80080a07b719cec937374e52de6e2392b0205
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Mon Jan 31 23:07:05 2011 +0100

    Better output when removing certificates from list.

commit 96d232a164773ae89f782808f96f1243dcea4e7e
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Mon Jan 31 23:06:03 2011 +0100

    Modified to work on new certtool -e output.

commit 115ea68a5986c63dab5524794b8e65c971d8380d
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Mon Jan 31 22:19:02 2011 +0100

    The internal subsystem uses the new certificate verification functions.
    This has the side effect of deprecating gnutls_certificate_get_x509_crls()
    and gnutls_certificate_get_x509_cas() that can no longer operation since
    they relied on internal structures.

commit 441eccc7be861374b9b4ef4aeca15a25655ef5c4
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Mon Jan 31 20:43:14 2011 +0100

    Added a new API to verify certificates. It is more efficient and
    can be used to get details about the verification procedure.

commit c9a64eae05818161f2a92cc9e2e76de3045a1ce5
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Mon Jan 31 20:30:06 2011 +0100

    better output in chain output.

commit 14406d26fa1119a20dc48dc54a739f65c35dea28
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Sun Jan 30 22:34:00 2011 +0100

    exported gnutls_x509_crl_get_raw_issuer_dn()

commit 457d7b147fde9d78ae532afd4c4c9ce5e2352afc
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Sun Jan 30 11:46:42 2011 +0100

    corrected typos

commit e43f90fea05d2578ab8398fafda644eb8977b4d9
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Wed Jan 19 12:35:32 2011 +0100

    CKR_CRYPTOKI_ALREADY_INITIALIZED is not treated as an error, and Finalize 
is not called in that case.

-----------------------------------------------------------------------

Summary of changes:
 NEWS                             |   21 ++
 doc/cha-gtls-app.texi            |    4 +-
 doc/examples/ex-verify.c         |  184 +++++-----------
 lib/Makefile.am                  |    5 +-
 lib/auth_cert.h                  |   10 +-
 lib/gnutls_cert.c                |   38 ++--
 lib/gnutls_x509.c                |  462 +++++++++++++-------------------------
 lib/hash.c                       |  239 ++++++++++++++++++++
 lib/hash.h                       |    2 +
 lib/includes/gnutls/compat.h     |   13 +
 lib/includes/gnutls/gnutls.h.in  |    8 -
 lib/includes/gnutls/x509.h       |   56 +++++
 lib/libgnutls.map                |    8 +
 lib/pakchois/pakchois.c          |   14 +-
 lib/x509/Makefile.am             |    3 +-
 lib/x509/crl.c                   |  196 ++++++++++++++++-
 lib/x509/verify-high.c           |  325 +++++++++++++++++++++++++++
 lib/x509/verify.c                |  161 +++++++++----
 lib/x509/x509.c                  |  110 ++++++++--
 lib/x509/x509_int.h              |   17 ++
 src/certtool.c                   |  313 +++++++++-----------------
 tests/certificate_set_x509_crl.c |    2 +-
 tests/pkcs1-padding/pkcs1-pad    |    4 +-
 tests/sha2/sha2                  |    2 +-
 tests/x509paths/chain            |   16 +-
 25 files changed, 1444 insertions(+), 769 deletions(-)
 create mode 100644 lib/hash.c
 create mode 100644 lib/hash.h
 create mode 100644 lib/x509/verify-high.c

diff --git a/NEWS b/NEWS
index ca94e43..f300148 100644
--- a/NEWS
+++ b/NEWS
@@ -5,6 +5,13 @@ See the end for copying conditions.
 
 * Version 2.11.7 (unreleased)
 
+** libgnutls: Added new certificate verification functions, that
+can provide more details and are more efficient. Check 
+gnutls_x509_trust_list_*.
+
+** certtool: Uses the new certificate verification functions for
+--verify-chain.
+
 ** libgnutls: The deprecated  gnutls_x509_privkey_sign_hash() was
 replaced by gnutls_privkey_sign_hash2().
 
@@ -30,10 +37,22 @@ gnutls_pubkey_verify_data() respectively.
 ** libgnutls: gnutls_*_export_raw() functions now add leading zero in
 integers.
 
+** libgnutls: Added convenience functions gnutls_x509_crl_list_import2()
+and gnutls_x509_crt_list_import2().
+
 ** crypto.h: Fix use with C++.
 Reported by "Brendan Doherty" <address@hidden>.
 
 ** API and ABI modifications:
+gnutls_x509_crl_list_import: ADDED
+gnutls_x509_crl_list_import2: ADDED
+gnutls_x509_crt_list_import2: ADDED
+gnutls_x509_trust_list_verify_crt: ADDED
+gnutls_x509_trust_list_add_crls: ADDED
+gnutls_x509_trust_list_add_cas: ADDED
+gnutls_x509_trust_list_init: ADDED
+gnutls_x509_trust_list_deinit: ADDED
+gnutls_x509_crl_get_raw_issuer_dn: ADDED
 gnutls_pubkey_import_privkey: ADDED
 gnutls_pubkey_verify_data: ADDED
 gnutls_privkey_sign_hash2: ADDED
@@ -49,6 +68,8 @@ gnutls_x509_privkey_verify_data: DEPRECATED (use: 
gnutls_pubkey_verify_data)
 gnutls_psk_netconf_derive_key: DEPRECATED
 gnutls_session_set_finished_function: DEPRECATED
 gnutls_ext_register: DEPRECATED
+gnutls_certificate_get_x509_crls: DEPRECATED
+gnutls_certificate_get_x509_cas: DEPRECATED
 gnutls_x509_crt_verify_hash: DEPRECATED (use: gnutls_pubkey_verify_hash)
 gnutls_x509_crt_verify_data: DEPRECATED (use: gnutls_pubkey_verify_data)
 gnutls_x509_crt_get_verify_algorithm: DEPRECATED (use: 
gnutls_pubkey_get_verify_algorithm)
diff --git a/doc/cha-gtls-app.texi b/doc/cha-gtls-app.texi
index 2dfa871..6196473 100644
--- a/doc/cha-gtls-app.texi
+++ b/doc/cha-gtls-app.texi
@@ -234,8 +234,8 @@ treat the connection as being a secure one.
 
 @verbatiminclude examples/ex-rfc2818.c
 
-Another example is listed below which provides more detailed
-verification output, for applications that need it.
+Another example is listed below which uses the high level verification
+functions.
 
 @verbatiminclude examples/ex-verify.c
 
diff --git a/doc/examples/ex-verify.c b/doc/examples/ex-verify.c
index 5165e45..f71039a 100644
--- a/doc/examples/ex-verify.c
+++ b/doc/examples/ex-verify.c
@@ -21,17 +21,12 @@ int crl_list_size;
 gnutls_x509_crt_t *ca_list;
 int ca_list_size;
 
-static void verify_cert2 (gnutls_x509_crt_t crt,
-                          gnutls_x509_crt_t issuer,
-                          gnutls_x509_crl_t * crl_list, int crl_list_size);
-static void verify_last_cert (gnutls_x509_crt_t crt,
-                              gnutls_x509_crt_t * ca_list, int ca_list_size,
-                              gnutls_x509_crl_t * crl_list,
-                              int crl_list_size);
-
+static int print_details_func(gnutls_x509_crt_t cert,
+    gnutls_x509_crt_t issuer, gnutls_x509_crl_t crl, 
+    unsigned int verification_output);
 
 /* This function will try to verify the peer's certificate chain, and
- * also check if the hostname matches, and the activation, expiration dates.
+ * also check if the hostname matches.
  */
 void
 verify_certificate_chain (gnutls_session_t session,
@@ -40,7 +35,20 @@ verify_certificate_chain (gnutls_session_t session,
                           int cert_chain_length)
 {
   int i;
+  gnutls_x509_trust_list_t tlist;
   gnutls_x509_crt_t *cert;
+  
+  unsigned int output;
+
+  /* Initialize the trusted certificate list. This should be done
+   * once on initialization. gnutls_x509_crt_list_import2() and
+   * gnutls_x509_crl_list_import2() can be used to load them.
+   */
+  gnutls_x509_trust_list_init(&tlist);
+
+  gnutls_x509_trust_list_add_cas(tlist, ca_list, ca_list_size, 0);
+  gnutls_x509_trust_list_add_crls(tlist, crl_list, crl_list_size, 
+    GNUTLS_TL_VERIFY_CRL, 0);
 
   cert = malloc (sizeof (*cert) * cert_chain_length);
 
@@ -53,82 +61,8 @@ verify_certificate_chain (gnutls_session_t session,
       gnutls_x509_crt_import (cert[i], &cert_chain[i], GNUTLS_X509_FMT_DER);
     }
 
-  /* If the last certificate in the chain is self signed ignore it.
-   * That is because we want to check against our trusted certificate
-   * list.
-   */
-  if (gnutls_x509_crt_check_issuer (cert[cert_chain_length - 1],
-                                    cert[cert_chain_length - 1]) > 0
-      && cert_chain_length > 0)
-    {
-      cert_chain_length--;
-    }
-
-  /* Now verify the certificates against their issuers
-   * in the chain.
-   */
-  for (i = 1; i < cert_chain_length; i++)
-    {
-      verify_cert2 (cert[i - 1], cert[i], crl_list, crl_list_size);
-    }
-
-  /* Here we must verify the last certificate in the chain against
-   * our trusted CA list.
-   */
-  verify_last_cert (cert[cert_chain_length - 1],
-                    ca_list, ca_list_size, crl_list, crl_list_size);
-
-  /* Check if the name in the first certificate matches our destination!
-   */
-  if (!gnutls_x509_crt_check_hostname (cert[0], hostname))
-    {
-      printf ("The certificate's owner does not match hostname '%s'\n",
-              hostname);
-    }
-
-  for (i = 0; i < cert_chain_length; i++)
-    gnutls_x509_crt_deinit (cert[i]);
-
-  return;
-}
-
-
-/* Verifies a certificate against an other certificate
- * which is supposed to be it's issuer. Also checks the
- * crl_list if the certificate is revoked.
- */
-static void
-verify_cert2 (gnutls_x509_crt_t crt, gnutls_x509_crt_t issuer,
-              gnutls_x509_crl_t * crl_list, int crl_list_size)
-{
-  unsigned int output;
-  int ret;
-  size_t name_size;
-  char name[64];
-
-  /* Print information about the certificates to
-   * be checked.
-   */
-  name_size = sizeof (name);
-  gnutls_x509_crt_get_dn (crt, name, &name_size);
-
-  fprintf (stderr, "\nCertificate: %s\n", name);
-
-  name_size = sizeof (name);
-  gnutls_x509_crt_get_issuer_dn (crt, name, &name_size);
-
-  fprintf (stderr, "Issued by: %s\n", name);
-
-  /* Get the DN of the issuer cert.
-   */
-  name_size = sizeof (name);
-  gnutls_x509_crt_get_dn (issuer, name, &name_size);
-
-  fprintf (stderr, "Checking against: %s\n", name);
-
-  /* Do the actual verification.
-   */
-  gnutls_x509_crt_verify (crt, &issuer, 1, 0, &output);
+  gnutls_x509_trust_list_verify_crt(tlist, cert, cert_chain_length, 0, 
+    &output, print_details_func);
 
   if (output & GNUTLS_CERT_INVALID)
     {
@@ -148,68 +82,54 @@ verify_cert2 (gnutls_x509_crt_t crt, gnutls_x509_crt_t 
issuer,
   else
     fprintf (stderr, "Trusted\n");
 
-  /* Check if the certificate is revoked.
+  /* Check if the name in the first certificate matches our destination!
    */
-  ret = gnutls_x509_crt_check_revocation (crt, crl_list, crl_list_size);
-  if (ret == 1)
-    {                           /* revoked */
-      fprintf (stderr, "Revoked\n");
+  if (!gnutls_x509_crt_check_hostname (cert[0], hostname))
+    {
+      printf ("The certificate's owner does not match hostname '%s'\n",
+              hostname);
     }
-}
 
+  gnutls_x509_trust_list_deinit(tlist, 1);
 
-/* Verifies a certificate against our trusted CA list.
- * Also checks the crl_list if the certificate is revoked.
- */
-static void
-verify_last_cert (gnutls_x509_crt_t crt,
-                  gnutls_x509_crt_t * ca_list, int ca_list_size,
-                  gnutls_x509_crl_t * crl_list, int crl_list_size)
+  return;
+}
+
+static int print_details_func(gnutls_x509_crt_t cert,
+    gnutls_x509_crt_t issuer, gnutls_x509_crl_t crl, 
+    unsigned int verification_output)
 {
-  unsigned int output;
-  int ret;
+  char name[512];
+  char issuer_name[512];
   size_t name_size;
-  char name[64];
+  size_t issuer_name_size;
 
-  /* Print information about the certificates to
-   * be checked.
-   */
-  name_size = sizeof (name);
-  gnutls_x509_crt_get_dn (crt, name, &name_size);
-
-  fprintf (stderr, "\nCertificate: %s\n", name);
+  issuer_name_size = sizeof (issuer_name);
+  gnutls_x509_crt_get_issuer_dn (cert, issuer_name, &issuer_name_size);
 
   name_size = sizeof (name);
-  gnutls_x509_crt_get_issuer_dn (crt, name, &name_size);
+  gnutls_x509_crt_get_dn (cert, name, &name_size);
 
-  fprintf (stderr, "Issued by: %s\n", name);
+  fprintf (stdout, "\tSubject: %s\n", name);
+  fprintf (stdout, "\tIssuer: %s\n", issuer_name);
 
-  /* Do the actual verification.
-   */
-  gnutls_x509_crt_verify (crt, ca_list, ca_list_size,
-                          GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT, &output);
-
-  if (output & GNUTLS_CERT_INVALID)
+  if (issuer != NULL)
     {
-      fprintf (stderr, "Not trusted");
+      issuer_name_size = sizeof (issuer_name);
+      gnutls_x509_crt_get_dn (issuer, issuer_name, &issuer_name_size);
 
-      if (output & GNUTLS_CERT_SIGNER_NOT_CA)
-        fprintf (stderr, ": Issuer is not a CA\n");
-      if (output & GNUTLS_CERT_NOT_ACTIVATED)
-        fprintf (stderr, ": Not yet activated\n");
-      if (output & GNUTLS_CERT_EXPIRED)
-        fprintf (stderr, ": Expired\n");
-      fprintf (stderr, "\n");
+      fprintf (stdout, "\tVerified against: %s\n", issuer_name);
     }
-  else
-    fprintf (stderr, "Trusted\n");
 
+  if (crl != NULL)
+    {
+      issuer_name_size = sizeof (issuer_name);
+      gnutls_x509_crl_get_issuer_dn (crl, issuer_name, &issuer_name_size);
 
-  /* Check if the certificate is revoked.
-   */
-  ret = gnutls_x509_crt_check_revocation (crt, crl_list, crl_list_size);
-  if (ret == 1)
-    {                           /* revoked */
-      fprintf (stderr, "Revoked\n");
+      fprintf (stdout, "\tVerified against CRL of: %s\n", issuer_name);
     }
+
+  fprintf (stdout, "\tVerification output: %x\n\n", verification_output);
+
+  return 0;
 }
diff --git a/lib/Makefile.am b/lib/Makefile.am
index d177253..bdf0c26 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -81,7 +81,7 @@ COBJECTS = gnutls_record.c gnutls_compress.c debug.c 
gnutls_cipher.c  \
        crypto.c random.c  ext_signature.c cryptodev.c system.c \
        crypto-api.c ext_safe_renegotiation.c gnutls_privkey.c \
        pkcs11.c pkcs11_privkey.c gnutls_pubkey.c pkcs11_write.c locks.c \
-       pkcs11_secret.c
+       pkcs11_secret.c hash.c
 
 
 if ENABLE_NETTLE
@@ -105,7 +105,8 @@ HFILES = debug.h gnutls_compress.h gnutls_cipher.h 
gnutls_buffers.h \
        gnutls_helper.h auth_psk.h auth_psk_passwd.h                    \
        gnutls_supplemental.h crypto.h random.h system.h        \
        ext_session_ticket.h ext_signature.h gnutls_cryptodev.h         \
-       ext_safe_renegotiation.h locks.h gnutls_mbuffers.h pkcs11_int.h
+       ext_safe_renegotiation.h locks.h gnutls_mbuffers.h pkcs11_int.h \
+       hash.h
 
 if ENABLE_LOCAL_PAKCHOIS
 COBJECTS+=pakchois/pakchois.c pakchois/errors.c pakchois/dlopen.c
diff --git a/lib/auth_cert.h b/lib/auth_cert.h
index 95ca2e0..d447b71 100644
--- a/lib/auth_cert.h
+++ b/lib/auth_cert.h
@@ -71,15 +71,7 @@ typedef struct gnutls_certificate_credentials_st
 #endif
 
   /* X509 specific stuff */
-
-  gnutls_x509_crt_t *x509_ca_list;
-  unsigned x509_ncas;           /* number of CAs in the ca_list 
-                                 */
-
-  gnutls_x509_crl_t *x509_crl_list;
-  unsigned x509_ncrls;          /* number of CRLs in the crl_list 
-                                 */
-
+  gnutls_x509_trust_list_t tlist;
   unsigned int verify_flags;    /* flags to be used at 
                                  * certificate verification.
                                  */
diff --git a/lib/gnutls_cert.c b/lib/gnutls_cert.c
index ab6831f..27ba009 100644
--- a/lib/gnutls_cert.c
+++ b/lib/gnutls_cert.c
@@ -98,18 +98,8 @@ gnutls_certificate_free_keys 
(gnutls_certificate_credentials_t sc)
 void
 gnutls_certificate_free_cas (gnutls_certificate_credentials_t sc)
 {
-  unsigned j;
-
-  for (j = 0; j < sc->x509_ncas; j++)
-    {
-      gnutls_x509_crt_deinit (sc->x509_ca_list[j]);
-    }
-
-  sc->x509_ncas = 0;
-
-  gnutls_free (sc->x509_ca_list);
-  sc->x509_ca_list = NULL;
-
+  /* do nothing for now */
+  return;
 }
 
 /**
@@ -122,14 +112,15 @@ gnutls_certificate_free_cas 
(gnutls_certificate_credentials_t sc)
  * credentials.
  *
  * Since: 2.4.0
+ * Deprecated and defunctional since: 2.11.0
  **/
 void
 gnutls_certificate_get_x509_cas (gnutls_certificate_credentials_t sc,
                                  gnutls_x509_crt_t ** x509_ca_list,
                                  unsigned int *ncas)
 {
-  *x509_ca_list = sc->x509_ca_list;
-  *ncas = sc->x509_ncas;
+  *x509_ca_list = NULL;
+  *ncas = 0;
 }
 
 /**
@@ -142,14 +133,15 @@ gnutls_certificate_get_x509_cas 
(gnutls_certificate_credentials_t sc,
  * credentials.
  *
  * Since: 2.4.0
+ * Deprecated and defunctional since: 2.11.0
  **/
 void
 gnutls_certificate_get_x509_crls (gnutls_certificate_credentials_t sc,
                                   gnutls_x509_crl_t ** x509_crl_list,
                                   unsigned int *ncrls)
 {
-  *x509_crl_list = sc->x509_crl_list;
-  *ncrls = sc->x509_ncrls;
+  *x509_crl_list = NULL;
+  *ncrls = 0;
 }
 
 #ifdef ENABLE_OPENPGP
@@ -246,12 +238,9 @@ _gnutls_certificate_get_rsa_params (gnutls_rsa_params_t 
rsa_params,
 void
 gnutls_certificate_free_credentials (gnutls_certificate_credentials_t sc)
 {
+  gnutls_x509_trust_list_deinit(sc->tlist, 1);
   gnutls_certificate_free_keys (sc);
-  gnutls_certificate_free_cas (sc);
   gnutls_certificate_free_ca_names (sc);
-#ifdef ENABLE_PKI
-  gnutls_certificate_free_crls (sc);
-#endif
 
 #ifdef ENABLE_OPENPGP
   gnutls_openpgp_keyring_deinit (sc->keyring);
@@ -274,11 +263,20 @@ int
 gnutls_certificate_allocate_credentials (gnutls_certificate_credentials_t *
                                          res)
 {
+int ret;
+
   *res = gnutls_calloc (1, sizeof (certificate_credentials_st));
 
   if (*res == NULL)
     return GNUTLS_E_MEMORY_ERROR;
 
+  ret = gnutls_x509_trust_list_init( &(*res)->tlist);
+  if (ret < 0)
+    {
+      gnutls_assert();
+      gnutls_free(*res);
+      return GNUTLS_E_MEMORY_ERROR;
+    }
   (*res)->verify_bits = DEFAULT_VERIFY_BITS;
   (*res)->verify_depth = DEFAULT_VERIFY_DEPTH;
 
diff --git a/lib/gnutls_x509.c b/lib/gnutls_x509.c
index 36f304a..3cf9f1d 100644
--- a/lib/gnutls_x509.c
+++ b/lib/gnutls_x509.c
@@ -46,7 +46,6 @@
 #include "x509/x509_int.h"
 #include "read-file.h"
 
-
 /*
  * some x509 certificate parsing functions.
  */
@@ -173,13 +172,11 @@ _gnutls_x509_cert_verify_peers (gnutls_session_t session,
   /* Verify certificate 
    */
 
-  ret = gnutls_x509_crt_list_verify (peer_certificate_list,
+  ret = gnutls_x509_trust_list_verify_crt (cred->tlist, peer_certificate_list,
                                      peer_certificate_list_size,
-                                     cred->x509_ca_list, cred->x509_ncas,
-                                     cred->x509_crl_list, cred->x509_ncrls,
                                      cred->verify_flags | session->internals.
                                      priorities.additional_verify_flags,
-                                     status);
+                                     status, NULL);
 
   CLEAR_CERTS;
 
@@ -612,12 +609,12 @@ read_cas_url (gnutls_certificate_credentials_t res, const 
char *url)
       goto cleanup;
     }
 
-  res->x509_ca_list = xcrt_list;
-  res->x509_ncas = pcrt_list_size;
-
-  gnutls_free (pcrt_list);
-
-  return pcrt_list_size;
+  ret = gnutls_x509_trust_list_add_cas(res->tlist, xcrt_list, pcrt_list_size, 
0);
+  if (ret < 0)
+    {
+      gnutls_assert();
+      goto cleanup;
+    }
 
 cleanup:
   gnutls_free (xcrt_list);
@@ -996,7 +993,8 @@ gnutls_certificate_set_x509_key_file 
(gnutls_certificate_credentials_t res,
 }
 
 static int
-add_new_crt_to_rdn_seq (gnutls_certificate_credentials_t res, int new)
+add_new_crt_to_rdn_seq (gnutls_certificate_credentials_t res, 
gnutls_x509_crt_t* crts,
+  unsigned int crt_size)
 {
   gnutls_datum_t tmp;
   int ret;
@@ -1017,9 +1015,9 @@ add_new_crt_to_rdn_seq (gnutls_certificate_credentials_t 
res, int new)
    * so optimizing that is less important.
    */
 
-  for (i = res->x509_ncas - new; i < res->x509_ncas; i++)
+  for (i = 0; i < crt_size; i++)
     {
-      if ((ret = gnutls_x509_crt_get_raw_dn (res->x509_ca_list[i], &tmp)) < 0)
+      if ((ret = gnutls_x509_crt_get_raw_dn (crts[i], &tmp)) < 0)
         {
           gnutls_assert ();
           return ret;
@@ -1107,147 +1105,90 @@ _gnutls_check_key_usage (const gnutls_cert * cert, 
gnutls_kx_algorithm_t alg)
   return 0;
 }
 
-
-
 static int
-parse_pem_ca_mem (gnutls_x509_crt_t ** cert_list, unsigned *ncerts,
+parse_pem_ca_mem (gnutls_certificate_credentials_t res,
                   const opaque * input_cert, int input_cert_size)
 {
-  int i, size;
-  const opaque *ptr;
-  gnutls_datum_t tmp;
-  int ret, count;
+  gnutls_x509_crt_t *x509_cert_list;
+  unsigned int x509_ncerts;
+  gnutls_datum tmp;
+  int ret;
 
-  /* move to the certificate
-   */
-  ptr = memmem (input_cert, input_cert_size,
-                PEM_CERT_SEP, sizeof (PEM_CERT_SEP) - 1);
-  if (ptr == NULL)
-    ptr = memmem (input_cert, input_cert_size,
-                  PEM_CERT_SEP2, sizeof (PEM_CERT_SEP2) - 1);
+  tmp.data = (void*)input_cert;
+  tmp.size = input_cert_size;
 
-  if (ptr == NULL)
+  ret = gnutls_x509_crt_list_import2( &x509_cert_list, &x509_ncerts, &tmp, 
+    GNUTLS_X509_FMT_PEM, 0);
+  if (ret < 0)
     {
-      gnutls_assert ();
-      return GNUTLS_E_BASE64_DECODING_ERROR;
+      gnutls_assert();
+      return ret;
     }
-  size = input_cert_size - (ptr - input_cert);
-
-  i = *ncerts + 1;
-  count = 0;
 
-  do
+  if ((ret = add_new_crt_to_rdn_seq (res, x509_cert_list, x509_ncerts)) < 0)
     {
-
-      *cert_list =
-        (gnutls_x509_crt_t *) gnutls_realloc_fast (*cert_list,
-                                                   i *
-                                                   sizeof
-                                                   (gnutls_x509_crt_t));
-
-      if (*cert_list == NULL)
-        {
-          gnutls_assert ();
-          return GNUTLS_E_MEMORY_ERROR;
-        }
-
-      ret = gnutls_x509_crt_init (&cert_list[0][i - 1]);
-      if (ret < 0)
-        {
-          gnutls_assert ();
-          return ret;
-        }
-
-      tmp.data = (opaque *) ptr;
-      tmp.size = size;
-
-      ret =
-        gnutls_x509_crt_import (cert_list[0][i - 1],
-                                &tmp, GNUTLS_X509_FMT_PEM);
-      if (ret < 0)
-        {
-          gnutls_assert ();
-          return ret;
-        }
-
-      /* now we move ptr after the pem header 
-       */
-      ptr++;
-      size--;
-      /* find the next certificate (if any)
-       */
-
-      if (size > 0)
-        {
-          char *ptr3;
-
-          ptr3 = memmem (ptr, size, PEM_CERT_SEP, sizeof (PEM_CERT_SEP) - 1);
-          if (ptr3 == NULL)
-            ptr3 = memmem (ptr, size,
-                           PEM_CERT_SEP2, sizeof (PEM_CERT_SEP2) - 1);
-
-          ptr = ptr3;
-          size = input_cert_size - (ptr - input_cert);
-        }
-      else
-        ptr = NULL;
-
-      i++;
-      count++;
-
+      gnutls_assert();
+      goto cleanup;
     }
-  while (ptr != NULL);
 
-  *ncerts = i - 1;
+  ret = gnutls_x509_trust_list_add_cas(res->tlist, x509_cert_list, 
x509_ncerts, 0);
+  if (ret < 0)
+    {
+      gnutls_assert();
+      goto cleanup;
+    }
 
-  return count;
+cleanup:
+  gnutls_free(x509_cert_list);
+  return ret;
 }
 
 /* Reads a DER encoded certificate list from memory and stores it to a
  * gnutls_cert structure.  Returns the number of certificates parsed.
  */
 static int
-parse_der_ca_mem (gnutls_x509_crt_t ** cert_list, unsigned *ncerts,
+parse_der_ca_mem (gnutls_certificate_credentials_t res,
                   const void *input_cert, int input_cert_size)
 {
-  int i;
-  gnutls_datum_t tmp;
+  gnutls_x509_crt_t crt;
+  gnutls_datum tmp;
   int ret;
 
-  i = *ncerts + 1;
-
-  *cert_list =
-    (gnutls_x509_crt_t *) gnutls_realloc_fast (*cert_list,
-                                               i *
-                                               sizeof (gnutls_x509_crt_t));
+  tmp.data = (void*)input_cert;
+  tmp.size = input_cert_size;
 
-  if (*cert_list == NULL)
+  ret = gnutls_x509_crt_init( &crt);
+  if (ret < 0)
     {
-      gnutls_assert ();
-      return GNUTLS_E_MEMORY_ERROR;
+      gnutls_assert();
+      return ret;
     }
 
-  tmp.data = (opaque *) input_cert;
-  tmp.size = input_cert_size;
-
-  ret = gnutls_x509_crt_init (&cert_list[0][i - 1]);
+  ret = gnutls_x509_crt_import( crt, &tmp, GNUTLS_X509_FMT_DER);
   if (ret < 0)
     {
-      gnutls_assert ();
-      return ret;
+      gnutls_assert();
+      goto cleanup;
     }
 
-  ret =
-    gnutls_x509_crt_import (cert_list[0][i - 1], &tmp, GNUTLS_X509_FMT_DER);
+  if ((ret = add_new_crt_to_rdn_seq (res, &crt, 1)) < 0)
+    {
+      gnutls_assert();
+      goto cleanup;
+    }
+
+  ret = gnutls_x509_trust_list_add_cas(res->tlist, &crt, 1, 0);
   if (ret < 0)
     {
-      gnutls_assert ();
-      return ret;
+      gnutls_assert();
+      goto cleanup;
     }
 
-  *ncerts = i;
+  return ret;
 
-  return 1;                     /* one certificate parsed */
+cleanup:
+  gnutls_x509_crt_deinit(crt);
+  return ret;
 }
 
 /**
@@ -1274,18 +1215,15 @@ gnutls_certificate_set_x509_trust_mem 
(gnutls_certificate_credentials_t res,
                                        const gnutls_datum_t * ca,
                                        gnutls_x509_crt_fmt_t type)
 {
-  int ret, ret2;
+  int ret;
 
   if (type == GNUTLS_X509_FMT_DER)
-    ret = parse_der_ca_mem (&res->x509_ca_list, &res->x509_ncas,
+    ret = parse_der_ca_mem (res,
                             ca->data, ca->size);
   else
-    ret = parse_pem_ca_mem (&res->x509_ca_list, &res->x509_ncas,
+    ret = parse_pem_ca_mem (res,
                             ca->data, ca->size);
 
-  if ((ret2 = add_new_crt_to_rdn_seq (res, ret)) < 0)
-    return ret2;
-
   return ret;
 }
 
@@ -1314,44 +1252,49 @@ gnutls_certificate_set_x509_trust 
(gnutls_certificate_credentials_t res,
                                    gnutls_x509_crt_t * ca_list,
                                    int ca_list_size)
 {
-  int ret, i, ret2;
-
-  res->x509_ca_list = gnutls_realloc_fast (res->x509_ca_list,
-                                           (ca_list_size +
-                                            res->x509_ncas) *
-                                           sizeof (gnutls_x509_crt_t));
-  if (res->x509_ca_list == NULL)
-    {
-      gnutls_assert ();
-      return GNUTLS_E_MEMORY_ERROR;
-    }
+  int ret, i, j;
+  gnutls_x509_crt_t new_list[ca_list_size];
 
   for (i = 0; i < ca_list_size; i++)
     {
-      ret = gnutls_x509_crt_init (&res->x509_ca_list[res->x509_ncas]);
+      ret = gnutls_x509_crt_init (&new_list[i]);
       if (ret < 0)
         {
           gnutls_assert ();
-          return ret;
+          goto cleanup;
         }
 
-      ret = _gnutls_x509_crt_cpy (res->x509_ca_list[res->x509_ncas],
-                                  ca_list[i]);
+      ret = _gnutls_x509_crt_cpy (new_list[i], ca_list[i]);
       if (ret < 0)
         {
           gnutls_assert ();
-          gnutls_x509_crt_deinit (res->x509_ca_list[res->x509_ncas]);
-          return ret;
+          goto cleanup;
         }
-      res->x509_ncas++;
     }
 
-  if ((ret2 = add_new_crt_to_rdn_seq (res, ca_list_size)) < 0)
-    return ret2;
+  if ((ret = add_new_crt_to_rdn_seq (res, new_list, ca_list_size)) < 0)
+    {
+      gnutls_assert();
+      goto cleanup;
+    }
 
-  return 0;
+  ret = gnutls_x509_trust_list_add_cas(res->tlist, new_list, ca_list_size, 0);
+  if (ret < 0)
+    {
+      gnutls_assert ();
+      goto cleanup;
+    }
+
+  return ret;
+
+cleanup:
+  for (j=0;j<i;i++)
+    gnutls_x509_crt_deinit(new_list[j]);
+
+  return ret;
 }
 
+
 /**
  * gnutls_certificate_set_x509_trust_file:
  * @res: is a #gnutls_certificate_credentials_t structure.
@@ -1379,7 +1322,7 @@ gnutls_certificate_set_x509_trust_file 
(gnutls_certificate_credentials_t res,
                                         const char *cafile,
                                         gnutls_x509_crt_fmt_t type)
 {
-  int ret, ret2;
+  int ret;
   size_t size;
   char *data;
 
@@ -1396,9 +1339,9 @@ gnutls_certificate_set_x509_trust_file 
(gnutls_certificate_credentials_t res,
     }
 
   if (type == GNUTLS_X509_FMT_DER)
-    ret = parse_der_ca_mem (&res->x509_ca_list, &res->x509_ncas, data, size);
+    ret = parse_der_ca_mem (res, data, size);
   else
-    ret = parse_pem_ca_mem (&res->x509_ca_list, &res->x509_ncas, data, size);
+    ret = parse_pem_ca_mem (res, data, size);
 
   free (data);
 
@@ -1408,140 +1351,84 @@ gnutls_certificate_set_x509_trust_file 
(gnutls_certificate_credentials_t res,
       return ret;
     }
 
-  if ((ret2 = add_new_crt_to_rdn_seq (res, ret)) < 0)
-    return ret2;
-
   return ret;
 }
 
 #ifdef ENABLE_PKI
 
 static int
-parse_pem_crl_mem (gnutls_x509_crl_t ** crl_list, unsigned *ncrls,
+parse_pem_crl_mem (gnutls_x509_trust_list_t tlist, 
                    const opaque * input_crl, int input_crl_size)
 {
-  int size, i;
-  const opaque *ptr;
-  gnutls_datum_t tmp;
-  int ret, count;
+  gnutls_x509_crl_t *x509_crl_list;
+  unsigned int x509_ncrls;
+  gnutls_datum tmp;
+  int ret;
 
-  /* move to the certificate
-   */
-  ptr = memmem (input_crl, input_crl_size,
-                PEM_CRL_SEP, sizeof (PEM_CRL_SEP) - 1);
-  if (ptr == NULL)
+  tmp.data = (void*)input_crl;
+  tmp.size = input_crl_size;
+
+  ret = gnutls_x509_crl_list_import2( &x509_crl_list, &x509_ncrls, &tmp, 
+    GNUTLS_X509_FMT_PEM, 0);
+  if (ret < 0)
     {
-      gnutls_assert ();
-      return GNUTLS_E_BASE64_DECODING_ERROR;
+      gnutls_assert();
+      return ret;
     }
 
-  size = input_crl_size - (ptr - input_crl);
-
-  i = *ncrls + 1;
-  count = 0;
-
-  do
+  ret = gnutls_x509_trust_list_add_crls(tlist, x509_crl_list, x509_ncrls, 0, 
0);
+  if (ret < 0)
     {
-
-      *crl_list =
-        (gnutls_x509_crl_t *) gnutls_realloc_fast (*crl_list,
-                                                   i *
-                                                   sizeof
-                                                   (gnutls_x509_crl_t));
-
-      if (*crl_list == NULL)
-        {
-          gnutls_assert ();
-          return GNUTLS_E_MEMORY_ERROR;
-        }
-
-      ret = gnutls_x509_crl_init (&crl_list[0][i - 1]);
-      if (ret < 0)
-        {
-          gnutls_assert ();
-          return ret;
-        }
-
-      tmp.data = (char *) ptr;
-      tmp.size = size;
-
-      ret =
-        gnutls_x509_crl_import (crl_list[0][i - 1],
-                                &tmp, GNUTLS_X509_FMT_PEM);
-      if (ret < 0)
-        {
-          gnutls_assert ();
-          return ret;
-        }
-
-      /* now we move ptr after the pem header 
-       */
-      ptr++;
-      /* find the next certificate (if any)
-       */
-
-      size = input_crl_size - (ptr - input_crl);
-
-      if (size > 0)
-        ptr = memmem (ptr, size, PEM_CRL_SEP, sizeof (PEM_CRL_SEP) - 1);
-      else
-        ptr = NULL;
-      i++;
-      count++;
-
+      gnutls_assert();
+      goto cleanup;
     }
-  while (ptr != NULL);
-
-  *ncrls = i - 1;
 
-  return count;
+cleanup:
+  gnutls_free(x509_crl_list);
+  return ret;
 }
 
 /* Reads a DER encoded certificate list from memory and stores it to a
  * gnutls_cert structure. Returns the number of certificates parsed.
  */
 static int
-parse_der_crl_mem (gnutls_x509_crl_t ** crl_list, unsigned *ncrls,
+parse_der_crl_mem (gnutls_x509_trust_list_t tlist,
                    const void *input_crl, int input_crl_size)
 {
-  int i;
-  gnutls_datum_t tmp;
+  gnutls_x509_crl_t crl;
+  gnutls_datum tmp;
   int ret;
 
-  i = *ncrls + 1;
-
-  *crl_list =
-    (gnutls_x509_crl_t *) gnutls_realloc_fast (*crl_list,
-                                               i *
-                                               sizeof (gnutls_x509_crl_t));
+  tmp.data = (void*)input_crl;
+  tmp.size = input_crl_size;
 
-  if (*crl_list == NULL)
+  ret = gnutls_x509_crl_init( &crl);
+  if (ret < 0)
     {
-      gnutls_assert ();
-      return GNUTLS_E_MEMORY_ERROR;
+      gnutls_assert();
+      return ret;
     }
 
-  tmp.data = (opaque *) input_crl;
-  tmp.size = input_crl_size;
-
-  ret = gnutls_x509_crl_init (&crl_list[0][i - 1]);
+  ret = gnutls_x509_crl_import( crl, &tmp, GNUTLS_X509_FMT_DER);
   if (ret < 0)
     {
-      gnutls_assert ();
-      return ret;
+      gnutls_assert();
+      goto cleanup;
     }
 
-  ret =
-    gnutls_x509_crl_import (crl_list[0][i - 1], &tmp, GNUTLS_X509_FMT_DER);
+  ret = gnutls_x509_trust_list_add_crls(tlist, &crl, 1, 0, 0);
   if (ret < 0)
     {
-      gnutls_assert ();
-      return ret;
+      gnutls_assert();
+      goto cleanup;
     }
 
-  *ncrls = i;
+  return ret;
+
+cleanup:
+  gnutls_x509_crl_deinit(crl);
+  return ret;
 
-  return 1;                     /* one certificate parsed */
 }
 
 
@@ -1553,29 +1440,14 @@ read_crl_mem (gnutls_certificate_credentials_t res, 
const void *crl,
 {
   int ret;
 
-  /* allocate space for the certificate to add
-   */
-  res->x509_crl_list = gnutls_realloc_fast (res->x509_crl_list,
-                                            (1 +
-                                             res->x509_ncrls) *
-                                            sizeof (gnutls_x509_crl_t));
-  if (res->x509_crl_list == NULL)
-    {
-      gnutls_assert ();
-      return GNUTLS_E_MEMORY_ERROR;
-    }
-
   if (type == GNUTLS_X509_FMT_DER)
-    ret = parse_der_crl_mem (&res->x509_crl_list,
-                             &res->x509_ncrls, crl, crl_size);
+    ret = parse_der_crl_mem (res->tlist, crl, crl_size);
   else
-    ret = parse_pem_crl_mem (&res->x509_crl_list,
-                             &res->x509_ncrls, crl, crl_size);
+    ret = parse_pem_crl_mem (res->tlist, crl, crl_size);
 
   if (ret < 0)
     {
       gnutls_assert ();
-      return ret;
     }
 
   return ret;
@@ -1600,12 +1472,7 @@ gnutls_certificate_set_x509_crl_mem 
(gnutls_certificate_credentials_t res,
                                      const gnutls_datum_t * CRL,
                                      gnutls_x509_crt_fmt_t type)
 {
-  int ret;
-
-  if ((ret = read_crl_mem (res, CRL->data, CRL->size, type)) < 0)
-    return ret;
-
-  return ret;
+  return read_crl_mem (res, CRL->data, CRL->size, type);
 }
 
 /**
@@ -1629,38 +1496,40 @@ gnutls_certificate_set_x509_crl 
(gnutls_certificate_credentials_t res,
                                  gnutls_x509_crl_t * crl_list,
                                  int crl_list_size)
 {
-  int ret, i;
-
-  res->x509_crl_list = gnutls_realloc_fast (res->x509_crl_list,
-                                            (crl_list_size +
-                                             res->x509_ncrls) *
-                                            sizeof (gnutls_x509_crl_t));
-  if (res->x509_crl_list == NULL)
-    {
-      gnutls_assert ();
-      return GNUTLS_E_MEMORY_ERROR;
-    }
+  int ret, i, j;
+  gnutls_x509_crl_t new_crl[crl_list_size];
 
   for (i = 0; i < crl_list_size; i++)
     {
-      ret = gnutls_x509_crl_init (&res->x509_crl_list[res->x509_ncrls]);
+      ret = gnutls_x509_crl_init (&new_crl[i]);
       if (ret < 0)
         {
           gnutls_assert ();
-          return ret;
+          goto cleanup;
         }
 
-      ret = _gnutls_x509_crl_cpy (res->x509_crl_list[res->x509_ncrls],
-                                  crl_list[i]);
+      ret = _gnutls_x509_crl_cpy (new_crl[i], crl_list[i]);
       if (ret < 0)
         {
           gnutls_assert ();
-          return ret;
+          goto cleanup;
         }
-      res->x509_ncrls++;
     }
 
-  return 0;
+  ret = gnutls_x509_trust_list_add_crls(res->tlist, new_crl, crl_list_size, 0, 
0);
+  if (ret < 0)
+    {
+      gnutls_assert ();
+      goto cleanup;
+    }
+
+  return ret;
+
+cleanup:
+  for (j=0;j<i;j++)
+    gnutls_x509_crl_deinit(new_crl[j]);
+
+  return ret;
 }
 
 /**
@@ -1693,11 +1562,9 @@ gnutls_certificate_set_x509_crl_file 
(gnutls_certificate_credentials_t res,
     }
 
   if (type == GNUTLS_X509_FMT_DER)
-    ret = parse_der_crl_mem (&res->x509_crl_list, &res->x509_ncrls,
-                             data, size);
+    ret = parse_der_crl_mem (res->tlist, data, size);
   else
-    ret = parse_pem_crl_mem (&res->x509_crl_list, &res->x509_ncrls,
-                             data, size);
+    ret = parse_pem_crl_mem (res->tlist, data, size);
 
   free (data);
 
@@ -2194,17 +2061,8 @@ done:
 void
 gnutls_certificate_free_crls (gnutls_certificate_credentials_t sc)
 {
-  unsigned j;
-
-  for (j = 0; j < sc->x509_ncrls; j++)
-    {
-      gnutls_x509_crl_deinit (sc->x509_crl_list[j]);
-    }
-
-  sc->x509_ncrls = 0;
-
-  gnutls_free (sc->x509_crl_list);
-  sc->x509_crl_list = NULL;
+  /* do nothing for now */
+  return;
 }
 
 #endif
diff --git a/lib/hash.c b/lib/hash.c
new file mode 100644
index 0000000..197530a
--- /dev/null
+++ b/lib/hash.c
@@ -0,0 +1,239 @@
+/*
+ * Copyright (C) 2011 Free Software Foundation, Inc.
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GnuTLS.
+ *
+ * The GnuTLS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+#include <gnutls_int.h>
+#include <hash.h>
+/*
+-------------------------------------------------------------------------------
+lookup3.c, by Bob Jenkins, May 2006, Public Domain.
+
+These are functions for producing 32-bit hashes for hash table lookup.
+hashword(), hashlittle(), hashlittle2(), hashbig(), mix(), and final() 
+are externally useful functions.  Routines to test the hash are included 
+if SELF_TEST is defined.  You can use this free for any purpose.  It's in
+the public domain.  It has no warranty.
+
+You probably want to use hashlittle().  hashlittle() and hashbig()
+hash byte arrays.  hashlittle() is is faster than hashbig() on
+little-endian machines.  Intel and AMD are little-endian machines.
+On second thought, you probably want hashlittle2(), which is identical to
+hashlittle() except it returns two 32-bit hashes for the price of one.  
+You could implement hashbig2() if you wanted but I haven't bothered here.
+
+If you want to find a hash of, say, exactly 7 integers, do
+  a = i1;  b = i2;  c = i3;
+  mix(a,b,c);
+  a += i4; b += i5; c += i6;
+  mix(a,b,c);
+  a += i7;
+  final(a,b,c);
+then use c as the hash value.  If you have a variable length array of
+4-byte integers to hash, use hashword().  If you have a byte array (like
+a character string), use hashlittle().  If you have several byte arrays, or
+a mix of things, see the comments above hashlittle().  
+
+Why is this so big?  I read 12 bytes at a time into 3 4-byte integers, 
+then mix those integers.  This is fast (you can do a lot more thorough
+mixing with 12*3 instructions on 3 integers than you can with 3 instructions
+on 1 byte), but shoehorning those bytes into integers efficiently is messy.
+-------------------------------------------------------------------------------
+*/
+#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k))))
+
+/*
+-------------------------------------------------------------------------------
+mix -- mix 3 32-bit values reversibly.
+
+This is reversible, so any information in (a,b,c) before mix() is
+still in (a,b,c) after mix().
+
+If four pairs of (a,b,c) inputs are run through mix(), or through
+mix() in reverse, there are at least 32 bits of the output that
+are sometimes the same for one pair and different for another pair.
+This was tested for:
+* pairs that differed by one bit, by two bits, in any combination
+  of top bits of (a,b,c), or in any combination of bottom bits of
+  (a,b,c).
+* "differ" is defined as +, -, ^, or ~^.  For + and -, I transformed
+  the output delta to a Gray code (a^(a>>1)) so a string of 1's (as
+  is commonly produced by subtraction) look like a single 1-bit
+  difference.
+* the base values were pseudorandom, all zero but one bit set, or 
+  all zero plus a counter that starts at zero.
+
+Some k values for my "a-=c; a^=rot(c,k); c+=b;" arrangement that
+satisfy this are
+    4  6  8 16 19  4
+    9 15  3 18 27 15
+   14  9  3  7 17  3
+Well, "9 15 3 18 27 15" didn't quite get 32 bits diffing
+for "differ" defined as + with a one-bit base and a two-bit delta.  I
+used http://burtleburtle.net/bob/hash/avalanche.html to choose 
+the operations, constants, and arrangements of the variables.
+
+This does not achieve avalanche.  There are input bits of (a,b,c)
+that fail to affect some output bits of (a,b,c), especially of a.  The
+most thoroughly mixed value is c, but it doesn't really even achieve
+avalanche in c.
+
+This allows some parallelism.  Read-after-writes are good at doubling
+the number of bits affected, so the goal of mixing pulls in the opposite
+direction as the goal of parallelism.  I did what I could.  Rotates
+seem to cost as much as shifts on every machine I could lay my hands
+on, and rotates are much kinder to the top and bottom bits, so I used
+rotates.
+-------------------------------------------------------------------------------
+*/
+#define mix(a,b,c) \
+{ \
+  a -= c;  a ^= rot(c, 4);  c += b; \
+  b -= a;  b ^= rot(a, 6);  a += c; \
+  c -= b;  c ^= rot(b, 8);  b += a; \
+  a -= c;  a ^= rot(c,16);  c += b; \
+  b -= a;  b ^= rot(a,19);  a += c; \
+  c -= b;  c ^= rot(b, 4);  b += a; \
+}
+
+/*
+-------------------------------------------------------------------------------
+final -- final mixing of 3 32-bit values (a,b,c) into c
+
+Pairs of (a,b,c) values differing in only a few bits will usually
+produce values of c that look totally different.  This was tested for
+* pairs that differed by one bit, by two bits, in any combination
+  of top bits of (a,b,c), or in any combination of bottom bits of
+  (a,b,c).
+* "differ" is defined as +, -, ^, or ~^.  For + and -, I transformed
+  the output delta to a Gray code (a^(a>>1)) so a string of 1's (as
+  is commonly produced by subtraction) look like a single 1-bit
+  difference.
+* the base values were pseudorandom, all zero but one bit set, or 
+  all zero plus a counter that starts at zero.
+
+These constants passed:
+ 14 11 25 16 4 14 24
+ 12 14 25 16 4 14 24
+and these came close:
+  4  8 15 26 3 22 24
+ 10  8 15 26 3 22 24
+ 11  8 15 26 3 22 24
+-------------------------------------------------------------------------------
+*/
+#define final(a,b,c) \
+{ \
+  c ^= b; c -= rot(b,14); \
+  a ^= c; a -= rot(c,11); \
+  b ^= a; b -= rot(a,25); \
+  c ^= b; c -= rot(b,16); \
+  a ^= c; a -= rot(c,4);  \
+  b ^= a; b -= rot(a,14); \
+  c ^= b; c -= rot(b,24); \
+}
+
+
+/*
+-------------------------------------------------------------------------------
+hashlittle() -- hash a variable-length key into a 32-bit value
+  k       : the key (the unaligned variable-length array of bytes)
+  length  : the length of the key, counting by bytes
+  initval : can be any 4-byte value
+Returns a 32-bit value.  Every bit of the key affects every bit of
+the return value.  Two keys differing by one or two bits will have
+totally different hash values.
+
+The best hash table sizes are powers of 2.  There is no need to do
+mod a prime (mod is sooo slow!).  If you need less than 32 bits,
+use a bitmask.  For example, if you need only 10 bits, do
+  h = (h & hashmask(10));
+In which case, the hash table should have hashsize(10) elements.
+
+If you are hashing n strings (uint8_t **)k, do it like this:
+  for (i=0, h=0; i<n; ++i) h = hashlittle( k[i], len[i], h);
+
+By Bob Jenkins, 2006.  address@hidden  You may use this
+code any way you wish, private, educational, or commercial.  It's free.
+
+Use for hash table lookup, or anything where one collision in 2^^32 is
+acceptable.  Do NOT use for cryptographic purposes.
+-------------------------------------------------------------------------------
+*/
+
+uint32_t _gnutls_bhash( const void *key, size_t length, uint32_t initval)
+{
+  uint32_t a,b,c;                                          /* internal state */
+  const uint8_t *k;
+  union { const void *ptr; size_t i; } u;     /* needed for Mac Powerbook G4 */
+
+  /* Set up the internal state */
+  a = b = c = 0xdeadbeef + ((uint32_t)length) + initval;
+
+  u.ptr = key;
+
+  k = (const uint8_t *)key;
+
+  /*--------------- all but the last block: affect some 32 bits of (a,b,c) */
+  while (length > 12)
+  {
+    a += k[0];
+    a += ((uint32_t)k[1])<<8;
+    a += ((uint32_t)k[2])<<16;
+    a += ((uint32_t)k[3])<<24;
+    b += k[4];
+    b += ((uint32_t)k[5])<<8;
+    b += ((uint32_t)k[6])<<16;
+    b += ((uint32_t)k[7])<<24;
+    c += k[8];
+    c += ((uint32_t)k[9])<<8;
+    c += ((uint32_t)k[10])<<16;
+    c += ((uint32_t)k[11])<<24;
+    mix(a,b,c);
+    length -= 12;
+    k += 12;
+  }
+
+  /*-------------------------------- last block: affect all 32 bits of (c) */
+  switch(length)                   /* all the case statements fall through */
+  {
+    case 12: c+=((uint32_t)k[11])<<24;
+    case 11: c+=((uint32_t)k[10])<<16;
+    case 10: c+=((uint32_t)k[9])<<8;
+    case 9 : c+=k[8];
+    case 8 : b+=((uint32_t)k[7])<<24;
+    case 7 : b+=((uint32_t)k[6])<<16;
+    case 6 : b+=((uint32_t)k[5])<<8;
+    case 5 : b+=k[4];
+    case 4 : a+=((uint32_t)k[3])<<24;
+    case 3 : a+=((uint32_t)k[2])<<16;
+    case 2 : a+=((uint32_t)k[1])<<8;
+    case 1 : a+=k[0];
+             break;
+    case 0 : return c;
+  }
+
+  final(a,b,c);
+  return c;
+}
+
+
+
diff --git a/lib/hash.h b/lib/hash.h
new file mode 100644
index 0000000..faecfd2
--- /dev/null
+++ b/lib/hash.h
@@ -0,0 +1,2 @@
+uint32_t _gnutls_bhash( const void *key, size_t length, uint32_t initval);
+
diff --git a/lib/includes/gnutls/compat.h b/lib/includes/gnutls/compat.h
index f283f8f..a047dc8 100644
--- a/lib/includes/gnutls/compat.h
+++ b/lib/includes/gnutls/compat.h
@@ -308,5 +308,18 @@ gnutls_sign_callback_get (gnutls_session_t session, void 
**userdata)
                              unsigned int flags)
                              _GNUTLS_GCC_ATTR_DEPRECATED;
 
+/* These functions cannot be supported. They export internal
+ * structure.
+ */
+  void gnutls_certificate_get_x509_cas (gnutls_certificate_credentials_t sc,
+                                        gnutls_x509_crt_t ** x509_ca_list,
+                                        unsigned int *ncas)
+                                        _GNUTLS_GCC_ATTR_DEPRECATED;
+
+  void gnutls_certificate_get_x509_crls (gnutls_certificate_credentials_t sc,
+                                         gnutls_x509_crl_t ** x509_crl_list,
+                                         unsigned int *ncrls)
+                                         _GNUTLS_GCC_ATTR_DEPRECATED;
+
 
 #endif /* _GNUTLS_COMPAT_H */
diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in
index fe9909a..cd0b96b 100644
--- a/lib/includes/gnutls/gnutls.h.in
+++ b/lib/includes/gnutls/gnutls.h.in
@@ -1107,14 +1107,6 @@ extern "C"
                                        gnutls_x509_crl_t * crl_list,
                                        int crl_list_size);
 
-  void gnutls_certificate_get_x509_cas (gnutls_certificate_credentials_t sc,
-                                        gnutls_x509_crt_t ** x509_ca_list,
-                                        unsigned int *ncas);
-
-  void gnutls_certificate_get_x509_crls (gnutls_certificate_credentials_t sc,
-                                         gnutls_x509_crl_t ** x509_crl_list,
-                                         unsigned int *ncrls);
-
   void
     gnutls_certificate_get_openpgp_keyring (gnutls_certificate_credentials_t
                                             sc,
diff --git a/lib/includes/gnutls/x509.h b/lib/includes/gnutls/x509.h
index ffc0c50..7cbc810 100644
--- a/lib/includes/gnutls/x509.h
+++ b/lib/includes/gnutls/x509.h
@@ -105,6 +105,10 @@ extern "C"
   int gnutls_x509_crt_import (gnutls_x509_crt_t cert,
                               const gnutls_datum_t * data,
                               gnutls_x509_crt_fmt_t format);
+  int gnutls_x509_crt_list_import2 (gnutls_x509_crt_t ** certs,
+                             unsigned int * size,
+                             const gnutls_datum_t * data,
+                             gnutls_x509_crt_fmt_t format, unsigned int flags);
   int gnutls_x509_crt_list_import (gnutls_x509_crt_t * certs,
                                    unsigned int *cert_max,
                                    const gnutls_datum_t * data,
@@ -395,6 +399,10 @@ extern "C"
                               gnutls_x509_crt_fmt_t format,
                               void *output_data, size_t * output_data_size);
 
+  int
+  gnutls_x509_crl_get_raw_issuer_dn (gnutls_x509_crl_t crl,
+                                      gnutls_datum_t * dn);
+
   int gnutls_x509_crl_get_issuer_dn (const gnutls_x509_crl_t crl,
                                      char *buf, size_t * sizeof_buf);
   int gnutls_x509_crl_get_issuer_dn_by_oid (gnutls_x509_crl_t crl,
@@ -422,6 +430,16 @@ extern "C"
   int gnutls_x509_crl_check_issuer (gnutls_x509_crl_t crl,
                                     gnutls_x509_crt_t issuer);
 
+  int gnutls_x509_crl_list_import2 (gnutls_x509_crl_t ** crls,
+                             unsigned int * size,
+                             const gnutls_datum_t * data,
+                             gnutls_x509_crt_fmt_t format, unsigned int flags);
+
+  int gnutls_x509_crl_list_import (gnutls_x509_crl_t * crls,
+                                   unsigned int *crl_max,
+                                   const gnutls_datum_t * data,
+                                   gnutls_x509_crt_fmt_t format,
+                                   unsigned int flags);
 /* CRL writing.
  */
   int gnutls_x509_crl_set_version (gnutls_x509_crl_t crl,
@@ -810,6 +828,44 @@ extern "C"
                                             void *buf, size_t * sizeof_buf,
                                             unsigned int *critical);
 
+  typedef struct gnutls_x509_trust_list_st *gnutls_x509_trust_list_t;
+
+  int
+  gnutls_x509_trust_list_init (gnutls_x509_trust_list_t * list);
+
+  void
+  gnutls_x509_trust_list_deinit (gnutls_x509_trust_list_t list, unsigned int 
all);
+
+  int
+  gnutls_x509_trust_list_add_cas (gnutls_x509_trust_list_t list, 
+    const gnutls_x509_crt_t * clist, int clist_size, unsigned int flags);
+
+#define GNUTLS_TL_VERIFY_CRL 1
+  int
+  gnutls_x509_trust_list_add_crls (gnutls_x509_trust_list_t list, 
+    const gnutls_x509_crl_t * crl_list, int crl_size, unsigned int flags,
+    unsigned int verification_flags);
+
+  typedef int gnutls_verify_output_function (
+    gnutls_x509_crt_t cert,
+    gnutls_x509_crt_t issuer, /* The issuer if verification failed 
+     * because of him. might be null.
+     */
+    gnutls_x509_crl_t crl, /* The CRL that caused verification failure 
+     * if any. Might be null. 
+     */
+    unsigned int verification_output);
+
+  int
+  gnutls_x509_trust_list_verify_crt (
+    gnutls_x509_trust_list_t list,
+    gnutls_x509_crt_t *cert_list,
+    unsigned int cert_list_size,
+    unsigned int flags,
+    unsigned int *verify,
+    gnutls_verify_output_function func);
+
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/libgnutls.map b/lib/libgnutls.map
index 0937324..623c0fd 100644
--- a/lib/libgnutls.map
+++ b/lib/libgnutls.map
@@ -695,6 +695,14 @@ GNUTLS_2_12
        gnutls_openpgp_crt_verify_hash;
        gnutls_pubkey_import_privkey;
        gnutls_pubkey_verify_data;
+       gnutls_x509_trust_list_verify_crt;
+       gnutls_x509_trust_list_add_crls;
+       gnutls_x509_trust_list_add_cas;
+       gnutls_x509_trust_list_init;
+       gnutls_x509_trust_list_deinit;
+       gnutls_x509_crl_list_import;
+       gnutls_x509_crl_list_import2;
+       gnutls_x509_crt_list_import2;
 } GNUTLS_2_10;
 
 GNUTLS_PRIVATE {
diff --git a/lib/pakchois/pakchois.c b/lib/pakchois/pakchois.c
index d04b3ca..0c2a86a 100644
--- a/lib/pakchois/pakchois.c
+++ b/lib/pakchois/pakchois.c
@@ -63,6 +63,7 @@ struct provider
   void *mutex;
   const struct ck_function_list *fns;
   unsigned int refcount;
+  unsigned int finalize:1; /* whether to finalize this one */
   struct provider *next, **prevref;
   void *reserved;
 };
@@ -342,11 +343,19 @@ load_pkcs11_module (struct provider **provider,
   args.reserved = reserved;
 
   rv = fns->C_Initialize (&args);
-  if (rv != CKR_OK)
+  if (rv != CKR_OK && rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)
     {
       goto fail_ctx;
     }
 
+  /* no need to finalize if someone else has 
+   * initialized the library before us.
+   */
+  if (rv == CKR_CRYPTOKI_ALREADY_INITIALIZED)
+    prov->finalize = 0;
+  else
+    prov->finalize = 1;
+
   prov->next = provider_list;
   prov->prevref = &provider_list;
   if (prov->next)
@@ -542,7 +551,8 @@ provider_unref (struct provider *prov)
 
   if (--prov->refcount == 0)
     {
-      prov->fns->C_Finalize (NULL);
+      if (prov->finalize)
+        prov->fns->C_Finalize (NULL);
       dlclose (prov->handle);
       *prov->prevref = prov->next;
       if (prov->next)
diff --git a/lib/x509/Makefile.am b/lib/x509/Makefile.am
index 0081521..983f323 100644
--- a/lib/x509/Makefile.am
+++ b/lib/x509/Makefile.am
@@ -57,4 +57,5 @@ libgnutls_x509_la_SOURCES =   \
        verify.c                \
        x509.c                  \
        x509_int.h              \
-       x509_write.c
+       x509_write.c    \
+       verify-high.c
diff --git a/lib/x509/crl.c b/lib/x509/crl.c
index 5d996eb..fca657f 100644
--- a/lib/x509/crl.c
+++ b/lib/x509/crl.c
@@ -34,6 +34,7 @@
 #include <common.h>
 #include <x509_b64.h>
 #include <x509_int.h>
+#include <gnutls_x509.h>
 
 /**
  * gnutls_x509_crl_init:
@@ -532,8 +533,8 @@ gnutls_x509_crl_get_crt_serial (gnutls_x509_crl_t crl, int 
indx,
   return 0;
 }
 
-/*-
- * _gnutls_x509_crl_get_raw_issuer_dn - This function returns the issuer's DN 
DER encoded
+/**
+ * gnutls_x509_crl_get_raw_issuer_dn - This function returns the issuer's DN 
DER encoded
  * @crl: should contain a gnutls_x509_crl_t structure
  * @dn: will hold the starting point of the DN
  *
@@ -541,9 +542,9 @@ gnutls_x509_crl_get_crt_serial (gnutls_x509_crl_t crl, int 
indx,
  * the length.
  *
  * Returns a negative value on error, and zero on success.
- -*/
+ **/
 int
-_gnutls_x509_crl_get_raw_issuer_dn (gnutls_x509_crl_t crl,
+gnutls_x509_crl_get_raw_issuer_dn (gnutls_x509_crl_t crl,
                                     gnutls_datum_t * dn)
 {
   ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
@@ -1024,4 +1025,191 @@ gnutls_x509_crl_get_extension_data (gnutls_x509_crl_t 
crl, int indx,
   return 0;
 }
 
+/**
+ * gnutls_x509_crl_list_import2:
+ * @crls: The structures to store the parsed crl list. Must not be initialized.
+ * @size: It will contain the size of the list.
+ * @data: The PEM encoded CRL.
+ * @format: One of DER or PEM.
+ * @flags: must be zero or an OR'd sequence of gnutls_certificate_import_flags.
+ *
+ * This function will convert the given PEM encoded CRL list
+ * to the native gnutls_x509_crl_t format. The output will be stored
+ * in @crls.  They will be automatically initialized.
+ *
+ * If the Certificate is PEM encoded it should have a header of "X509
+ * CRL".
+ *
+ * Returns: the number of certificates read or a negative error value.
+ **/
+int
+gnutls_x509_crl_list_import2 (gnutls_x509_crl_t ** crls,
+                             unsigned int * size,
+                             const gnutls_datum_t * data,
+                             gnutls_x509_crt_fmt_t format, unsigned int flags)
+{
+unsigned int init = 1024;
+int ret;
+
+  *crls = gnutls_malloc(sizeof(gnutls_x509_crl_t*)*init);
+  if (*crls == NULL)
+    {
+      gnutls_assert();
+      return GNUTLS_E_MEMORY_ERROR;
+    }
+
+  ret = gnutls_x509_crl_list_import(*crls, &init, data, format, 
GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED);
+  if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER)
+    {
+      *crls = gnutls_realloc_fast(*crls, sizeof(gnutls_x509_crl_t*)*init);
+      if (*crls == NULL)
+        {
+          gnutls_assert();
+          return GNUTLS_E_MEMORY_ERROR;
+        }
+      
+      ret = gnutls_x509_crl_list_import(*crls, &init, data, format, flags);
+    }
+
+  if (ret < 0)
+    {
+      gnutls_free(*crls);
+      *crls = NULL;
+      return ret;
+    }
+
+  *size = init;
+  return 0;
+}
+
+/**
+ * gnutls_x509_crl_list_import:
+ * @crls: The structures to store the parsed CRLs. Must not be initialized.
+ * @crl_max: Initially must hold the maximum number of crls. It will be 
updated with the number of crls available.
+ * @data: The PEM encoded CRLs
+ * @format: One of DER or PEM.
+ * @flags: must be zero or an OR'd sequence of gnutls_certificate_import_flags.
+ *
+ * This function will convert the given PEM encoded CRL list
+ * to the native gnutls_x509_crl_t format. The output will be stored
+ * in @crls.  They will be automatically initialized.
+ *
+ * If the Certificate is PEM encoded it should have a header of "X509 CRL".
+ *
+ * Returns: the number of certificates read or a negative error value.
+ **/
+int
+gnutls_x509_crl_list_import (gnutls_x509_crl_t * crls,
+                             unsigned int *crl_max,
+                             const gnutls_datum_t * data,
+                             gnutls_x509_crt_fmt_t format, unsigned int flags)
+{
+  int size;
+  const char *ptr;
+  gnutls_datum_t tmp;
+  int ret, nocopy = 0;
+  unsigned int count = 0, j;
+
+  if (format == GNUTLS_X509_FMT_DER)
+    {
+      if (*crl_max < 1)
+        {
+          *crl_max = 1;
+          return GNUTLS_E_SHORT_MEMORY_BUFFER;
+        }
+
+      count = 1;                /* import only the first one */
+
+      ret = gnutls_x509_crl_init (&crls[0]);
+      if (ret < 0)
+        {
+          gnutls_assert ();
+          goto error;
+        }
+
+      ret = gnutls_x509_crl_import (crls[0], data, format);
+      if (ret < 0)
+        {
+          gnutls_assert ();
+          goto error;
+        }
+
+      *crl_max = 1;
+      return 1;
+    }
+
+  /* move to the certificate
+   */
+  ptr = memmem (data->data, data->size,
+                PEM_CRL_SEP, sizeof (PEM_CRL_SEP) - 1);
+  if (ptr == NULL)
+    {
+      gnutls_assert ();
+      return GNUTLS_E_BASE64_DECODING_ERROR;
+    }
+
+  count = 0;
+
+  do
+    {
+      if (count >= *crl_max)
+        {
+          if (!(flags & GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED))
+            break;
+          else
+            nocopy = 1;
+        }
+
+      if (!nocopy)
+        {
+          ret = gnutls_x509_crl_init (&crls[count]);
+          if (ret < 0)
+            {
+              gnutls_assert ();
+              goto error;
+            }
+
+          tmp.data = (void *) ptr;
+          tmp.size = data->size - (ptr - (char *) data->data);
+
+          ret =
+            gnutls_x509_crl_import (crls[count], &tmp, GNUTLS_X509_FMT_PEM);
+          if (ret < 0)
+            {
+              gnutls_assert ();
+              goto error;
+            }
+        }
+
+      /* now we move ptr after the pem header 
+       */
+      ptr++;
+      /* find the next certificate (if any)
+       */
+      size = data->size - (ptr - (char *) data->data);
+
+      if (size > 0)
+        {
+          ptr = memmem (ptr, size, PEM_CRL_SEP, sizeof (PEM_CRL_SEP) - 1);
+        }
+      else
+        ptr = NULL;
+
+      count++;
+    }
+  while (ptr != NULL);
+
+  *crl_max = count;
+
+  if (nocopy == 0)
+    return count;
+  else
+    return GNUTLS_E_SHORT_MEMORY_BUFFER;
+
+error:
+  for (j = 0; j < count; j++)
+    gnutls_x509_crl_deinit (crls[j]);
+  return ret;
+}
+
 #endif
diff --git a/lib/x509/verify-high.c b/lib/x509/verify-high.c
new file mode 100644
index 0000000..6260400
--- /dev/null
+++ b/lib/x509/verify-high.c
@@ -0,0 +1,325 @@
+/*
+ * Copyright (C) 2011 Free Software Foundation, Inc.
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GnuTLS.
+ *
+ * The GnuTLS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+
+#include <gnutls_int.h>
+#include <gnutls_errors.h>
+#include <gnutls_cert.h>
+#include <libtasn1.h>
+#include <gnutls_global.h>
+#include <gnutls_num.h>         /* MAX */
+#include <gnutls_sig.h>
+#include <gnutls_str.h>
+#include <gnutls_datum.h>
+#include <hash.h>
+#include "x509_int.h"
+#include <common.h>
+
+#define LIST_SIZE 457
+#define INIT_HASH 0x33a1
+struct node_st {
+  /* The trusted certificates */
+  gnutls_x509_crt_t * crts;
+  unsigned int crt_size;
+
+  /* The trusted CRLs */
+  gnutls_x509_crl_t * crls;
+  unsigned int crl_size;
+};
+
+struct gnutls_x509_trust_list_st {
+  struct node_st node[LIST_SIZE];
+};
+
+/**
+ * gnutls_x509_trust_list_init:
+ * @list: The structure to be initialized
+ *
+ * This function will initialize an X.509 trust list structure.
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
+ *   negative error value.
+ **/
+int
+gnutls_x509_trust_list_init (gnutls_x509_trust_list_t * list)
+{
+  gnutls_x509_trust_list_t tmp = gnutls_calloc (1, sizeof (struct 
gnutls_x509_trust_list_st));
+
+  if (!tmp)
+    return GNUTLS_E_MEMORY_ERROR;
+
+  *list = tmp;
+
+  return 0;                     /* success */
+}
+
+/**
+ * gnutls_x509_trust_list_deinit:
+ * @list: The structure to be deinitialized
+ * @all: if non-zero it will deinitialize all the certificates and CRLs 
contained in the structure.
+ *
+ * This function will deinitialize a trust list.
+ **/
+void
+gnutls_x509_trust_list_deinit (gnutls_x509_trust_list_t list, unsigned int all)
+{
+int i, j;
+
+  if (!list)
+    return;
+
+  if (all)
+    {
+      for (i=0;i<LIST_SIZE;i++)
+        {
+          for (j=0;j<list->node[i].crt_size;j++)
+            {
+              gnutls_x509_crt_deinit(list->node[i].crts[j]);
+            }
+          for (j=0;j<list->node[i].crl_size;j++)
+            {
+              gnutls_x509_crl_deinit(list->node[i].crls[j]);
+            }
+        }
+    }
+
+  gnutls_free (list);
+}
+
+/**
+ * gnutls_x509_trust_list_add_cas:
+ * @list: The structure of the list
+ * @clist: A list of CAs
+ * @clist_size: The length of the CA list
+ * @flags: should be 0.
+ *
+ * This function will add the given certificate authorities
+ * to the trusted list. The list of CAs must not be deinitialized
+ * during this structure's lifetime.
+ *
+ * Returns: The number of added elements is returned.
+ *
+ **/
+int
+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;
+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 = _gnutls_bhash(dn.data, dn.size, INIT_HASH);
+        hash %= LIST_SIZE;
+
+        list->node[hash].crts = gnutls_realloc_fast( list->node[hash].crts, 
(list->node[hash].crt_size+1)*sizeof(list->node[hash].crts[0]));
+        if (list->node[hash].crts == NULL)
+          {
+            gnutls_assert();
+            return i;
+          }
+
+        list->node[hash].crts[list->node[hash].crt_size] = clist[i];
+        list->node[hash].crt_size++;
+
+        _gnutls_free_datum(&dn);
+    }
+
+  return i;
+}
+
+/**
+ * gnutls_x509_trust_list_add_crls:
+ * @list: The structure of the list
+ * @crl_list: A list of CRLs
+ * @crl_size: The length of the CRL list
+ * @flags: if GNUTLS_TL_VERIFY_CRL is given the CRLs will be verified before 
being added.
+ * @verification_flags: gnutls_certificate_verify_flags if flags specifies 
GNUTLS_TL_VERIFY_CRL
+ *
+ * This function will add the given certificate revocation lists
+ * to the trusted list. The list of CRLs must not be deinitialized
+ * during this structure's lifetime.
+ *
+ * This function must be called after gnutls_x509_trust_list_add_cas()
+ * to allow verifying the CRLs for validity.
+ *
+ * Returns: The number of added elements is returned.
+ *
+ **/
+
+int
+gnutls_x509_trust_list_add_crls (gnutls_x509_trust_list_t list, 
+  const gnutls_x509_crl_t * crl_list, int crl_size, unsigned int flags,
+  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 = _gnutls_bhash(dn.data, dn.size, INIT_HASH);
+        hash %= LIST_SIZE;
+
+        _gnutls_free_datum(&dn);
+
+        if (flags & GNUTLS_TL_VERIFY_CRL)
+          {
+
+            ret = gnutls_x509_crl_verify(crl_list[i], list->node[hash].crts,
+              list->node[hash].crt_size, verification_flags, &vret);
+            if (ret < 0 || vret != 0)
+              continue;
+          }
+
+        list->node[hash].crls = gnutls_realloc_fast( list->node[hash].crls, 
(list->node[hash].crl_size+1)*sizeof(list->node[hash].crts[0]));
+        if (list->node[hash].crls == NULL)
+          {
+            gnutls_assert();
+            return i;
+          }
+
+        list->node[hash].crls[list->node[hash].crl_size] = crl_list[i];
+        list->node[hash].crl_size++;
+        j++;
+    }
+
+  return j;
+}
+
+
+/**
+ * gnutls_x509_trust_list_verify_crt:
+ * @list: The structure of the list
+ * @cert: is the certificate to be verified
+ * @flags: Flags that may be used to change the verification algorithm. Use OR 
of the gnutls_certificate_verify_flags enumerations.
+ * @verify: will hold the certificate verification output.
+ * @func: If non-null will be called on each chain element verification with 
the output.
+ *
+ * This function will try to verify the given certificate and return
+ * its status.
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
+ *   negative error value.
+ **/
+int
+gnutls_x509_trust_list_verify_crt (
+  gnutls_x509_trust_list_t list,
+  gnutls_x509_crt_t *cert_list,
+  unsigned int cert_list_size,
+  unsigned int flags,
+  unsigned int *verify,
+  gnutls_verify_output_function func)
+{
+gnutls_datum_t dn;
+int ret, i;
+uint32_t hash;
+
+  if (cert_list == NULL || cert_list_size < 1)
+    {
+      gnutls_assert();
+      return GNUTLS_E_INVALID_REQUEST;
+    }
+
+  ret = gnutls_x509_crt_get_raw_issuer_dn(cert_list[cert_list_size-1], &dn);
+  if (ret < 0)
+    {
+      gnutls_assert();
+      return ret;
+    }
+
+  hash = _gnutls_bhash(dn.data, dn.size, INIT_HASH);
+  hash %= LIST_SIZE;
+
+  _gnutls_free_datum(&dn);
+
+  *verify = _gnutls_x509_verify_certificate(cert_list, cert_list_size, 
+    list->node[hash].crts, list->node[hash].crt_size, 
+    flags, func);
+
+  if (*verify != 0) return 0;
+
+  /* Check revocation of individual certificates.
+   * start with the last one that we already have its hash
+   */
+  ret = _gnutls_x509_crt_check_revocation (cert_list[cert_list_size-1],
+                                        list->node[hash].crls, 
+                                        list->node[hash].crl_size, func);
+  if (ret == 1)
+    { /* revoked */
+      *verify |= GNUTLS_CERT_REVOKED;
+      *verify |= GNUTLS_CERT_INVALID;
+      return 0;
+    }
+
+  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 = _gnutls_bhash(dn.data, dn.size, INIT_HASH);
+      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, func);
+      if (ret == 1)
+        { /* revoked */
+          *verify |= GNUTLS_CERT_REVOKED;
+          *verify |= GNUTLS_CERT_INVALID;
+          return 0;
+        }
+    }
+
+  return 0;
+}
diff --git a/lib/x509/verify.c b/lib/x509/verify.c
index e830cec..ac0f5d0 100644
--- a/lib/x509/verify.c
+++ b/lib/x509/verify.c
@@ -39,12 +39,6 @@
 #include "x509_int.h"
 #include <common.h>
 
-static int _gnutls_verify_certificate2 (gnutls_x509_crt_t cert,
-                                        const gnutls_x509_crt_t * trusted_cas,
-                                        int tcas_size, unsigned int flags,
-                                        unsigned int *output,
-                                        gnutls_x509_crt_t * issuer);
-
 static int is_crl_issuer (gnutls_x509_crl_t crl,
                           gnutls_x509_crt_t issuer_cert);
 
@@ -255,12 +249,49 @@ cleanup:
 
 }
 
+/* Checks if the DN of two certificates is the same.
+ * Returns 1 if they match and zero if they don't match. Otherwise
+ * a negative value is returned to indicate error.
+ */
+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;
+}
+
+/* Finds an issuer of the certificate. If multiple issuers
+ * are present, returns one that is activated and not expired.
+ */
 static inline gnutls_x509_crt_t
 find_issuer (gnutls_x509_crt_t cert,
              const gnutls_x509_crt_t * trusted_cas, int tcas_size)
 {
-  int i;
+int i;
+gnutls_x509_crt_t issuer = NULL;
 
   /* this is serial search. 
    */
@@ -268,11 +299,25 @@ find_issuer (gnutls_x509_crt_t cert,
   for (i = 0; i < tcas_size; i++)
     {
       if (is_issuer (cert, trusted_cas[i]) == 1)
-        return trusted_cas[i];
+        {
+          if (issuer == NULL) 
+            {
+              issuer = trusted_cas[i];
+            }
+          else
+            {
+              time_t now = time(0);
+
+              if (now < gnutls_x509_crt_get_expiration_time(trusted_cas[i]) && 
+                now >= gnutls_x509_crt_get_activation_time(trusted_cas[i]))
+                {
+                  issuer = trusted_cas[i];
+                }
+            }
+        }
     }
 
-  gnutls_assert ();
-  return NULL;
+  return issuer;
 }
 
 
@@ -294,12 +339,14 @@ _gnutls_verify_certificate2 (gnutls_x509_crt_t cert,
                              const gnutls_x509_crt_t * trusted_cas,
                              int tcas_size, unsigned int flags,
                              unsigned int *output,
-                             gnutls_x509_crt_t * _issuer)
+                             gnutls_x509_crt_t * _issuer,
+                             gnutls_verify_output_function func)
 {
   gnutls_datum_t cert_signed_data = { NULL, 0 };
   gnutls_datum_t cert_signature = { NULL, 0 };
   gnutls_x509_crt_t issuer = NULL;
   int issuer_version, result;
+  unsigned int out = 0;
 
   if (output)
     *output = 0;
@@ -309,9 +356,11 @@ _gnutls_verify_certificate2 (gnutls_x509_crt_t cert,
   else
     {
       gnutls_assert ();
+      out = GNUTLS_CERT_SIGNER_NOT_FOUND | GNUTLS_CERT_INVALID;
       if (output)
-        *output |= GNUTLS_CERT_SIGNER_NOT_FOUND | GNUTLS_CERT_INVALID;
-      return 0;
+        *output |= out;
+      result = 0;
+      goto cleanup;
     }
 
   /* issuer is not in trusted certificate
@@ -319,10 +368,12 @@ _gnutls_verify_certificate2 (gnutls_x509_crt_t cert,
    */
   if (issuer == NULL)
     {
+      out = GNUTLS_CERT_SIGNER_NOT_FOUND | GNUTLS_CERT_INVALID;
       if (output)
-        *output |= GNUTLS_CERT_SIGNER_NOT_FOUND | GNUTLS_CERT_INVALID;
+        *output |= out;
       gnutls_assert ();
-      return 0;
+      result = 0;
+      goto cleanup;
     }
 
   if (_issuer != NULL)
@@ -342,9 +393,11 @@ _gnutls_verify_certificate2 (gnutls_x509_crt_t cert,
       if (check_if_ca (cert, issuer, flags) == 0)
         {
           gnutls_assert ();
+          out = GNUTLS_CERT_SIGNER_NOT_CA | GNUTLS_CERT_INVALID;
           if (output)
-            *output |= GNUTLS_CERT_SIGNER_NOT_CA | GNUTLS_CERT_INVALID;
-          return 0;
+            *output |= out;
+          result = 0;
+          goto cleanup;
         }
     }
 
@@ -371,9 +424,10 @@ _gnutls_verify_certificate2 (gnutls_x509_crt_t cert,
   if (result == GNUTLS_E_PK_SIG_VERIFY_FAILED)
     {
       gnutls_assert ();
+      out |= GNUTLS_CERT_INVALID;
       /* error. ignore it */
       if (output)
-        *output |= GNUTLS_CERT_INVALID;
+        *output |= out;
       result = 0;
     }
   else if (result < 0)
@@ -397,13 +451,16 @@ _gnutls_verify_certificate2 (gnutls_x509_crt_t cert,
           ((sigalg == GNUTLS_SIGN_RSA_MD5) &&
            !(flags & GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5)))
         {
+          out = GNUTLS_CERT_INSECURE_ALGORITHM | GNUTLS_CERT_INVALID;
           if (output)
-            *output |= GNUTLS_CERT_INSECURE_ALGORITHM | GNUTLS_CERT_INVALID;
+            *output |= out;
           result = 0;
         }
     }
 
 cleanup:
+  if (result >= 0 && func) func(cert, issuer, NULL, out);
+
   _gnutls_free_datum (&cert_signed_data);
   _gnutls_free_datum (&cert_signature);
 
@@ -461,13 +518,13 @@ check_time (gnutls_x509_crt_t crt, time_t now)
  * This function verifies a X.509 certificate list. The certificate
  * list should lead to a trusted certificate in order to be trusted.
  */
-static unsigned int
+unsigned int
 _gnutls_x509_verify_certificate (const gnutls_x509_crt_t * certificate_list,
                                  int clist_size,
                                  const gnutls_x509_crt_t * trusted_cas,
                                  int tcas_size,
-                                 const gnutls_x509_crl_t * CRLs,
-                                 int crls_size, unsigned int flags)
+                                 unsigned int flags, 
+                                 gnutls_verify_output_function func)
 {
   int i = 0, ret;
   unsigned int status = 0, output;
@@ -519,9 +576,12 @@ _gnutls_x509_verify_certificate (const gnutls_x509_crt_t * 
certificate_list,
                   status |= check_time (trusted_cas[j], now);
                   if (status != 0)
                     {
+                      if (func) func(certificate_list[i], trusted_cas[j], 
NULL, status);
                       return status;
                     }
                 }
+
+              if (func) func(certificate_list[i], trusted_cas[j], NULL, 
status);
               clist_size = i;
               break;
             }
@@ -530,9 +590,11 @@ _gnutls_x509_verify_certificate (const gnutls_x509_crt_t * 
certificate_list,
     }
 
   if (clist_size == 0)
-    /* The certificate is already present in the trusted certificate list.
-     * Nothing to verify. */
-    return status;
+    {
+      /* The certificate is already present in the trusted certificate list.
+       * Nothing to verify. */
+      return status;
+    }
 
   /* Verify the last certificate in the certificate path
    * against the trusted CA certificate list.
@@ -542,7 +604,7 @@ _gnutls_x509_verify_certificate (const gnutls_x509_crt_t * 
certificate_list,
    */
   ret = _gnutls_verify_certificate2 (certificate_list[clist_size - 1],
                                      trusted_cas, tcas_size, flags, &output,
-                                     &issuer);
+                                     &issuer, func);
   if (ret == 0)
     {
       /* if the last certificate in the certificate
@@ -555,23 +617,6 @@ _gnutls_x509_verify_certificate (const gnutls_x509_crt_t * 
certificate_list,
       return status;
     }
 
-  /* Check for revoked certificates in the chain
-   */
-#ifdef ENABLE_PKI
-  for (i = 0; i < clist_size; i++)
-    {
-      ret = gnutls_x509_crt_check_revocation (certificate_list[i],
-                                              CRLs, crls_size);
-      if (ret == 1)
-        {                       /* revoked */
-          status |= GNUTLS_CERT_REVOKED;
-          status |= GNUTLS_CERT_INVALID;
-          return status;
-        }
-    }
-#endif
-
-
   /* Check activation/expiration times
    */
   if (!(flags & GNUTLS_VERIFY_DISABLE_TIME_CHECKS))
@@ -588,6 +633,7 @@ _gnutls_x509_verify_certificate (const gnutls_x509_crt_t * 
certificate_list,
           status |= check_time (issuer, now);
           if (status != 0)
             {
+              if (func) func(certificate_list[clist_size - 1], issuer, NULL, 
status);
               return status;
             }
         }
@@ -597,6 +643,7 @@ _gnutls_x509_verify_certificate (const gnutls_x509_crt_t * 
certificate_list,
           status |= check_time (certificate_list[i], now);
           if (status != 0)
             {
+              if (func) func(certificate_list[i], NULL, NULL, status);
               return status;
             }
         }
@@ -617,7 +664,7 @@ _gnutls_x509_verify_certificate (const gnutls_x509_crt_t * 
certificate_list,
       if ((ret =
            _gnutls_verify_certificate2 (certificate_list[i - 1],
                                         &certificate_list[i], 1, flags,
-                                        NULL, NULL)) == 0)
+                                        NULL, NULL, func)) == 0)
         {
           status |= GNUTLS_CERT_INVALID;
           return status;
@@ -1074,6 +1121,8 @@ gnutls_x509_crt_list_verify (const gnutls_x509_crt_t * 
cert_list,
                              int CRL_list_length, unsigned int flags,
                              unsigned int *verify)
 {
+int i, ret;
+
   if (cert_list == NULL || cert_list_length == 0)
     return GNUTLS_E_NO_CERTIFICATE_FOUND;
 
@@ -1081,8 +1130,23 @@ gnutls_x509_crt_list_verify (const gnutls_x509_crt_t * 
cert_list,
    */
   *verify =
     _gnutls_x509_verify_certificate (cert_list, cert_list_length,
-                                     CA_list, CA_list_length, CRL_list,
-                                     CRL_list_length, flags);
+                                     CA_list, CA_list_length, 
+                                     flags, NULL);
+
+  /* Check for revoked certificates in the chain. 
+   */
+#ifdef ENABLE_PKI
+  for (i = 0; i < cert_list_length; i++)
+    {
+      ret = gnutls_x509_crt_check_revocation (cert_list[i],
+                                              CRL_list, CRL_list_length);
+      if (ret == 1)
+        {                       /* revoked */
+          *verify |= GNUTLS_CERT_REVOKED;
+          *verify |= GNUTLS_CERT_INVALID;
+        }
+    }
+#endif
 
   return 0;
 }
@@ -1111,7 +1175,8 @@ gnutls_x509_crt_verify (gnutls_x509_crt_t cert,
    */
   *verify =
     _gnutls_x509_verify_certificate (&cert, 1,
-                                     CA_list, CA_list_length, NULL, 0, flags);
+                                     CA_list, CA_list_length, 
+                                     flags, NULL);
   return 0;
 }
 
@@ -1183,7 +1248,7 @@ is_crl_issuer (gnutls_x509_crl_t crl, gnutls_x509_crt_t 
issuer_cert)
   NULL, 0};
   int ret;
 
-  ret = _gnutls_x509_crl_get_raw_issuer_dn (crl, &dn1);
+  ret = gnutls_x509_crl_get_raw_issuer_dn (crl, &dn1);
   if (ret < 0)
     {
       gnutls_assert ();
diff --git a/lib/x509/x509.c b/lib/x509/x509.c
index c34f544..300ee8e 100644
--- a/lib/x509/x509.c
+++ b/lib/x509/x509.c
@@ -128,9 +128,9 @@ _gnutls_x509_crt_cpy (gnutls_x509_crt_t dest, 
gnutls_x509_crt_t src)
 
 /**
  * gnutls_x509_crt_deinit:
- * @cert: The structure to be initialized
+ * @cert: The structure to be deinitialized
  *
- * This function will deinitialize a CRL structure.
+ * This function will deinitialize a certificate structure.
  **/
 void
 gnutls_x509_crt_deinit (gnutls_x509_crt_t cert)
@@ -2377,25 +2377,17 @@ gnutls_x509_crt_get_key_id (gnutls_x509_crt_t crt, 
unsigned int flags,
 
 #ifdef ENABLE_PKI
 
-/**
- * gnutls_x509_crt_check_revocation:
- * @cert: should contain a #gnutls_x509_crt_t structure
- * @crl_list: should contain a list of gnutls_x509_crl_t structures
- * @crl_list_length: the length of the crl_list
- *
- * This function will return check if the given certificate is
- * revoked.  It is assumed that the CRLs have been verified before.
- *
- * Returns: 0 if the certificate is NOT revoked, and 1 if it is.  A
- * negative value is returned on error.
- **/
+/* This is exactly as gnutls_x509_crt_check_revocation() except that
+ * it calls func.
+ */
 int
-gnutls_x509_crt_check_revocation (gnutls_x509_crt_t cert,
+_gnutls_x509_crt_check_revocation (gnutls_x509_crt_t cert,
                                   const gnutls_x509_crl_t * crl_list,
-                                  int crl_list_length)
+                                  int crl_list_length,
+                                  gnutls_verify_output_function func)
 {
-  opaque serial[64];
-  opaque cert_serial[64];
+  opaque serial[128];
+  opaque cert_serial[128];
   size_t serial_size, cert_serial_size;
   int ncerts, ret, i, j;
   gnutls_datum_t dn1, dn2;
@@ -2411,7 +2403,7 @@ 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);
+      ret = gnutls_x509_crl_get_raw_issuer_dn (crl_list[j], &dn1);
       if (ret < 0)
         {
           gnutls_assert ();
@@ -2475,15 +2467,38 @@ gnutls_x509_crt_check_revocation (gnutls_x509_crt_t 
cert,
               if (memcmp (serial, cert_serial, serial_size) == 0)
                 {
                   /* serials match */
+                  if (func) func(cert, NULL, crl_list[j], 
GNUTLS_CERT_REVOKED|GNUTLS_CERT_INVALID);
                   return 1;     /* revoked! */
                 }
             }
         }
+      if (func) func(cert, NULL, crl_list[j], 0);
 
     }
   return 0;                     /* not revoked. */
 }
 
+
+/**
+ * gnutls_x509_crt_check_revocation:
+ * @cert: should contain a #gnutls_x509_crt_t structure
+ * @crl_list: should contain a list of gnutls_x509_crl_t structures
+ * @crl_list_length: the length of the crl_list
+ *
+ * This function will return check if the given certificate is
+ * revoked.  It is assumed that the CRLs have been verified before.
+ *
+ * Returns: 0 if the certificate is NOT revoked, and 1 if it is.  A
+ * negative value is returned on error.
+ **/
+int
+gnutls_x509_crt_check_revocation (gnutls_x509_crt_t cert,
+                                  const gnutls_x509_crl_t * crl_list,
+                                  int crl_list_length)
+{
+  return _gnutls_x509_crt_check_revocation(cert, crl_list, crl_list_length, 
NULL);
+}
+
 /**
  * gnutls_x509_crt_get_verify_algorithm:
  * @crt: Holds the certificate
@@ -3063,6 +3078,63 @@ cleanup:
 }
 
 #endif
+/**
+ * gnutls_x509_crt_list_import2:
+ * @certs: The structures to store the parsed certificate. Must not be 
initialized.
+ * @size: It will contain the size of the list.
+ * @data: The PEM encoded certificate.
+ * @format: One of DER or PEM.
+ * @flags: must be zero or an OR'd sequence of gnutls_certificate_import_flags.
+ *
+ * This function will convert the given PEM encoded certificate list
+ * to the native gnutls_x509_crt_t format. The output will be stored
+ * in @certs.  They will be automatically initialized.
+ *
+ * If the Certificate is PEM encoded it should have a header of "X509
+ * CERTIFICATE", or "CERTIFICATE".
+ *
+ * Returns: the number of certificates read or a negative error value.
+ **/
+int
+gnutls_x509_crt_list_import2 (gnutls_x509_crt_t ** certs,
+                             unsigned int * size,
+                             const gnutls_datum_t * data,
+                             gnutls_x509_crt_fmt_t format, unsigned int flags)
+{
+unsigned int init = 1024;
+int ret;
+
+  *certs = gnutls_malloc(sizeof(gnutls_x509_crt_t*)*init);
+  if (*certs == NULL)
+    {
+      gnutls_assert();
+      return GNUTLS_E_MEMORY_ERROR;
+    }
+
+  ret = gnutls_x509_crt_list_import(*certs, &init, data, format, 
GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED);
+  if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER)
+    {
+      *certs = gnutls_realloc_fast(*certs, sizeof(gnutls_x509_crt_t*)*init);
+      if (*certs == NULL)
+        {
+          gnutls_assert();
+          return GNUTLS_E_MEMORY_ERROR;
+        }
+      
+      ret = gnutls_x509_crt_list_import(*certs, &init, data, format, flags);
+    }
+
+  if (ret < 0)
+    {
+      gnutls_free(*certs);
+      *certs = NULL;
+      return ret;
+    }
+
+  *size = init;
+  return 0;
+}
+
 
 /**
  * gnutls_x509_crt_list_import:
diff --git a/lib/x509/x509_int.h b/lib/x509/x509_int.h
index 61d2245..d5842bc 100644
--- a/lib/x509/x509_int.h
+++ b/lib/x509/x509_int.h
@@ -397,4 +397,21 @@ int _gnutls_x509_crq_set_extension (gnutls_x509_crq_t crq,
                                     const gnutls_datum_t * ext_data,
                                     unsigned int critical);
 
+unsigned int
+_gnutls_x509_verify_certificate (const gnutls_x509_crt_t * certificate_list,
+                                 int clist_size,
+                                 const gnutls_x509_crt_t * trusted_cas,
+                                 int tcas_size,
+                                 unsigned int flags,
+                                 gnutls_verify_output_function func);
+
+int
+_gnutls_is_same_dn (gnutls_x509_crt_t cert1, gnutls_x509_crt_t cert2);
+
+int
+_gnutls_x509_crt_check_revocation (gnutls_x509_crt_t cert,
+                                  const gnutls_x509_crl_t * crl_list,
+                                  int crl_list_length,
+                                  gnutls_verify_output_function func);
+
 #endif
diff --git a/src/certtool.c b/src/certtool.c
index c99ccf0..0dd60e5 100644
--- a/src/certtool.c
+++ b/src/certtool.c
@@ -1923,205 +1923,139 @@ generate_request (common_info_st * cinfo)
 
 }
 
-static void print_verification_res (gnutls_x509_crt_t crt,
-                                    gnutls_x509_crt_t issuer,
-                                    gnutls_x509_crl_t * crl_list,
-                                    int crl_list_size, unsigned int flags);
+static void print_verification_res (FILE* outfile, unsigned int output);
 
-#define CERT_SEP "-----BEGIN CERT"
-#define CRL_SEP "-----BEGIN X509 CRL"
-static int
-_verify_x509_mem (const void *cert, int cert_size)
+static int detailed_verification(gnutls_x509_crt_t cert,
+    gnutls_x509_crt_t issuer, gnutls_x509_crl_t crl, 
+    unsigned int verification_output)
 {
-  const char *ptr;
-  int ret, i;
   char name[512];
+  char tmp[255];
   char issuer_name[512];
   size_t name_size;
   size_t issuer_name_size;
-  gnutls_datum_t tmp;
-  gnutls_x509_crt_t *x509_cert_list = NULL;
-  gnutls_x509_crl_t *x509_crl_list = NULL;
-  int x509_ncerts, x509_ncrls;
-
-
-  /* Decode the CA certificate
-   */
-
-  /* Decode the CRL list
-   */
-  ptr = cert;
-
-  i = 1;
-
-  if (strstr (ptr, CRL_SEP) != NULL)    /* if CRLs exist */
-    do
-      {
-        x509_crl_list =
-          (gnutls_x509_crl_t *) realloc (x509_crl_list,
-                                         i * sizeof (gnutls_x509_crl_t));
-        if (x509_crl_list == NULL)
-          error (EXIT_FAILURE, 0, "memory error");
-
-        tmp.data = (char *) ptr;
-        tmp.size = cert_size;
-        tmp.size -=
-          (unsigned int) ((unsigned char *) ptr - (unsigned char *) cert);
-
-        ret = gnutls_x509_crl_init (&x509_crl_list[i - 1]);
-        if (ret < 0)
-          error (EXIT_FAILURE, 0, "error parsing CRL[%d]: %s", i,
-                 gnutls_strerror (ret));
-
-        ret = gnutls_x509_crl_import (x509_crl_list[i - 1], &tmp,
-                                      GNUTLS_X509_FMT_PEM);
-        if (ret < 0)
-          error (EXIT_FAILURE, 0, "error parsing CRL[%d]: %s", i,
-                 gnutls_strerror (ret));
-
-        /* now we move ptr after the pem header */
-        ptr = strstr (ptr, CRL_SEP);
-        if (ptr != NULL)
-          ptr++;
-
-        i++;
-      }
-    while ((ptr = strstr (ptr, CRL_SEP)) != NULL);
+  int ret;
 
-  x509_ncrls = i - 1;
 
+  issuer_name_size = sizeof (issuer_name);
+  ret =
+    gnutls_x509_crt_get_issuer_dn (cert, issuer_name, &issuer_name_size);
+  if (ret < 0)
+    error (EXIT_FAILURE, 0, "gnutls_x509_crt_get_issuer_dn: %s", 
gnutls_strerror (ret));
 
-  /* Decode the certificate chain. 
-   */
-  ptr = cert;
+  name_size = sizeof (name);
+  ret =
+    gnutls_x509_crt_get_dn (cert, name, &name_size);
+  if (ret < 0)
+    error (EXIT_FAILURE, 0, "gnutls_x509_crt_get_dn: %s", gnutls_strerror 
(ret));
 
-  i = 1;
+  fprintf (outfile, "\tSubject: %s\n", name);
+  fprintf (outfile, "\tIssuer: %s\n", issuer_name);
 
-  do
+  if (issuer != NULL)
     {
-      x509_cert_list =
-        (gnutls_x509_crt_t *) realloc (x509_cert_list,
-                                       i * sizeof (gnutls_x509_crt_t));
-      if (x509_cert_list == NULL)
-        error (EXIT_FAILURE, 0, "memory error");
-
+      issuer_name_size = sizeof (issuer_name);
+      ret =
+        gnutls_x509_crt_get_dn (issuer, issuer_name, &issuer_name_size);
+      if (ret < 0)
+        error (EXIT_FAILURE, 0, "gnutls_x509_crt_get_issuer_dn: %s", 
gnutls_strerror (ret));
 
-      tmp.data = (char *) ptr;
-      tmp.size = cert_size;
-      tmp.size -=
-        (unsigned int) ((unsigned char *) ptr - (unsigned char *) cert);
+      fprintf (outfile, "\tChecked against: %s\n", issuer_name);
+    }
 
-      ret = gnutls_x509_crt_init (&x509_cert_list[i - 1]);
-      if (ret < 0)
-        error (EXIT_FAILURE, 0, "error parsing certificate[%d]: %s", i,
-               gnutls_strerror (ret));
+  if (crl != NULL)
+    {
+      gnutls_datum data;
 
+      issuer_name_size = sizeof (issuer_name);
       ret =
-        gnutls_x509_crt_import (x509_cert_list[i - 1], &tmp,
-                                GNUTLS_X509_FMT_PEM);
+        gnutls_x509_crl_get_issuer_dn (crl, issuer_name, &issuer_name_size);
       if (ret < 0)
-        error (EXIT_FAILURE, 0, "error parsing certificate[%d]: %s", i,
-               gnutls_strerror (ret));
+        error (EXIT_FAILURE, 0, "gnutls_x509_crl_get_issuer_dn: %s", 
gnutls_strerror (ret));
 
-
-      if (i - 1 != 0)
+      name_size = sizeof(tmp);
+      ret = gnutls_x509_crl_get_number(crl, tmp, &name_size, NULL);
+      if (ret < 0)
+        strcpy(name, "unnumbered");
+      else
         {
-          /* verify the previous certificate using this one 
-           * as CA.
-           */
+          data.data = tmp;
+          data.size = name_size;
 
-          name_size = sizeof (name);
-          ret =
-            gnutls_x509_crt_get_dn (x509_cert_list[i - 2], name, &name_size);
+          name_size = sizeof(name);
+          ret = gnutls_hex_encode(&data, name, &name_size);
           if (ret < 0)
-            error (EXIT_FAILURE, 0, "get_dn: %s", gnutls_strerror (ret));
-
-          fprintf (outfile, "Certificate[%d]: %s\n", i - 2, name);
-
-          /* print issuer 
-           */
-          issuer_name_size = sizeof (issuer_name);
-          ret =
-            gnutls_x509_crt_get_issuer_dn (x509_cert_list[i - 2],
-                                           issuer_name, &issuer_name_size);
-          if (ret < 0)
-            error (EXIT_FAILURE, 0, "get_issuer_dn: %s",
-                   gnutls_strerror (ret));
-
-          fprintf (outfile, "\tIssued by: %s\n", issuer_name);
+            error (EXIT_FAILURE, 0, "gnutls_hex_encode: %s", gnutls_strerror 
(ret));
+        }
+      fprintf (outfile, "\tChecked against CRL[%s] of: %s\n", name, 
issuer_name);
+    }
 
-          /* Get the Issuer's name
-           */
-          name_size = sizeof (name);
-          ret =
-            gnutls_x509_crt_get_dn (x509_cert_list[i - 1], name, &name_size);
-          if (ret < 0)
-            error (EXIT_FAILURE, 0, "get_dn: %s", gnutls_strerror (ret));
+  fprintf (outfile, "\tOutput: ");
+  print_verification_res(outfile, verification_output);
 
-          fprintf (outfile, "\tVerifying against certificate[%d].\n", i - 1);
+  fputs(".\n\n", outfile);
 
-          if (strcmp (issuer_name, name) != 0)
-            {
-              fprintf (stderr, "Error: Issuer's name: %s\n", name);
-              error (EXIT_FAILURE, 0,
-                     "issuer name does not match the next certificate");
-            }
+  return 0;
+}
 
-          fprintf (outfile, "\tVerification output: ");
-          print_verification_res (x509_cert_list[i - 2],
-                                  x509_cert_list[i - 1], x509_crl_list,
-                                  x509_ncrls,
-                                  GNUTLS_VERIFY_DO_NOT_ALLOW_SAME);
-          fprintf (outfile, ".\n\n");
+static int
+_verify_x509_mem (const void *cert, int cert_size)
+{
+  int ret;
+  gnutls_datum_t tmp;
+  gnutls_x509_crt_t *x509_cert_list = NULL;
+  gnutls_x509_crl_t *x509_crl_list = NULL;
+  unsigned int x509_ncerts, x509_ncrls = 0;
+  gnutls_x509_trust_list_t list;
+  unsigned int output;
 
-        }
+  tmp.data = (void*)cert;
+  tmp.size = cert_size;
 
+  ret = gnutls_x509_crl_list_import2( &x509_crl_list, &x509_ncrls, &tmp, 
+    GNUTLS_X509_FMT_PEM, 0);
+  if (ret < 0)
+    {
+      x509_crl_list = NULL;
+      x509_ncrls = 0;
+    }
 
-      /* now we move ptr after the pem header 
-       */
-      ptr = strstr (ptr, CERT_SEP);
-      if (ptr != NULL)
-        ptr++;
+  /* ignore errors. CRL might not be given */
 
-      i++;
-    }
-  while ((ptr = strstr (ptr, CERT_SEP)) != NULL);
+  ret = gnutls_x509_crt_list_import2( &x509_cert_list, &x509_ncerts, &tmp, 
+    GNUTLS_X509_FMT_PEM, 0);
+  if (ret < 0 || x509_ncerts < 1)
+     error (EXIT_FAILURE, 0, "error parsing CRTs: %s", 
+                 gnutls_strerror (ret));
 
-  x509_ncerts = i - 1;
+  fprintf(stdout, "Loaded %d certificates and %d CRLs\n\n", x509_ncerts, 
x509_ncrls);
 
-  /* The last certificate in the list will be used as
-   * a CA (should be self signed).
-   */
-  name_size = sizeof (name);
-  ret = gnutls_x509_crt_get_dn (x509_cert_list[x509_ncerts - 1], name,
-                                &name_size);
+  ret = gnutls_x509_trust_list_init(&list);
   if (ret < 0)
-    error (EXIT_FAILURE, 0, "get_dn: %s", gnutls_strerror (ret));
+     error (EXIT_FAILURE, 0, "gnutls_x509_trust_list_init: %s", 
+                 gnutls_strerror (ret));
 
-  fprintf (outfile, "Certificate[%d]: %s\n", x509_ncerts - 1, name);
+  ret = gnutls_x509_trust_list_add_cas(list, &x509_cert_list[x509_ncerts - 1], 
1, 0);
+  if (ret < 0)
+     error (EXIT_FAILURE, 0, "gnutls_x509_trust_add_cas: %s", 
+                 gnutls_strerror (ret));
 
-  /* print issuer 
-   */
-  issuer_name_size = sizeof (issuer_name);
-  ret =
-    gnutls_x509_crt_get_issuer_dn (x509_cert_list[x509_ncerts - 1],
-                                   issuer_name, &issuer_name_size);
+  ret = gnutls_x509_trust_list_add_crls(list, x509_crl_list, x509_ncrls, 0, 0);
   if (ret < 0)
-    error (EXIT_FAILURE, 0, "get_issuer_dn: %s", gnutls_strerror (ret));
+     error (EXIT_FAILURE, 0, "gnutls_x509_trust_add_crls: %s", 
+                 gnutls_strerror (ret));
 
-  fprintf (outfile, "\tIssued by: %s\n", name);
+  gnutls_free(x509_crl_list);
 
-  if (strcmp (issuer_name, name) != 0)
-    error (EXIT_FAILURE, 0, "the last certificate is not self signed");
+  ret = gnutls_x509_trust_list_verify_crt (list, x509_cert_list, x509_ncerts,
+    GNUTLS_VERIFY_DO_NOT_ALLOW_SAME|GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT, 
&output,
+    detailed_verification);
+  if (ret < 0)
+     error (EXIT_FAILURE, 0, "gnutls_x509_trusted_list_verify_crt: %s", 
+                 gnutls_strerror (ret));
 
-  fprintf (outfile, "\tVerification output: ");
-  print_verification_res (x509_cert_list[x509_ncerts - 1],
-                          x509_cert_list[x509_ncerts - 1], x509_crl_list,
-                          /* we add GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT since 
it is
-                           * self signed. */
-                          x509_ncrls,
-                          GNUTLS_VERIFY_DO_NOT_ALLOW_SAME |
-                          GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
+  fprintf (outfile, "Chain verification output: ");
+  print_verification_res(outfile, output);
 
   fprintf (outfile, ".\n\n");
 
@@ -2140,40 +2074,16 @@ _verify_x509_mem (const void *cert, int cert_size)
       error (EXIT_FAILURE, 0, "gnutls_x509_crt_list_verify: %s",
              gnutls_strerror (ret));
 
-    fprintf (outfile, "Chain verification output: ");
-
-    if (verify_status & GNUTLS_CERT_INVALID)
-      {
-        fprintf (outfile, "Not verified");
-      }
-    else
+    if (output != verify_status)
       {
-        fprintf (outfile, "Verified");
+        fprintf (outfile, "Chain verification output[via internal]: ");
+        print_verification_res(outfile, verify_status);
+        fprintf (outfile, ".\n");
       }
-
-    if (verify_status & GNUTLS_CERT_SIGNER_NOT_CA)
-      {
-        fprintf (outfile, ", ");
-        fprintf (outfile, "Issuer is not a CA");
-      }
-
-    if (verify_status & GNUTLS_CERT_INSECURE_ALGORITHM)
-      {
-        fprintf (outfile, ", ");
-        fprintf (outfile, "Insecure algorithm");
-      }
-
-    fprintf (outfile, ".\n");
   }
 
-  for (i = 0; i < x509_ncerts; i++)
-    gnutls_x509_crt_deinit (x509_cert_list[i]);
-
-  for (i = 0; i < x509_ncrls; i++)
-    gnutls_x509_crl_deinit (x509_crl_list[i]);
-
-  free (x509_cert_list);
-  free (x509_crl_list);
+  gnutls_free(x509_cert_list);
+  gnutls_x509_trust_list_deinit(list, 1);
 
   if (ret < 0)
     error (EXIT_FAILURE, 0, "verification error: %s", gnutls_strerror (ret));
@@ -2182,18 +2092,9 @@ _verify_x509_mem (const void *cert, int cert_size)
 }
 
 static void
-print_verification_res (gnutls_x509_crt_t crt,
-                        gnutls_x509_crt_t issuer,
-                        gnutls_x509_crl_t * crl_list, int crl_list_size,
-                        unsigned int flags)
+print_verification_res (FILE* outfile, unsigned int output)
 {
-  unsigned int output;
   int comma = 0;
-  int ret;
-
-  ret = gnutls_x509_crt_verify (crt, &issuer, 1, flags, &output);
-  if (ret < 0)
-    error (EXIT_FAILURE, 0, "verification error: %s", gnutls_strerror (ret));
 
   if (output & GNUTLS_CERT_INVALID)
     {
@@ -2238,16 +2139,12 @@ print_verification_res (gnutls_x509_crt_t crt,
       comma = 1;
     }
 
-  ret = gnutls_x509_crt_check_revocation (crt, crl_list, crl_list_size);
-  if (ret < 0)
-    error (EXIT_FAILURE, 0, "revocation check: %s", gnutls_strerror (ret));
-
-  if (ret == 1)
-    {                           /* revoked */
+  if (output & GNUTLS_CERT_REVOKED)
+    {
       if (comma)
         fprintf (outfile, ", ");
-      comma = 1;
       fprintf (outfile, "Revoked");
+      comma = 1;
     }
 }
 
diff --git a/tests/certificate_set_x509_crl.c b/tests/certificate_set_x509_crl.c
index 20ebb30..8f39898 100644
--- a/tests/certificate_set_x509_crl.c
+++ b/tests/certificate_set_x509_crl.c
@@ -94,7 +94,7 @@ main (void)
     }
 
   rc = gnutls_certificate_set_x509_crl (crt, &crl, 1);
-  if (rc)
+  if (rc < 0)
     {
       printf ("gnutls_certificate_set_x509_crl rc %d: %s\n",
               rc, gnutls_strerror (rc));
diff --git a/tests/pkcs1-padding/pkcs1-pad b/tests/pkcs1-padding/pkcs1-pad
index d9bff4e..d10e080 100755
--- a/tests/pkcs1-padding/pkcs1-pad
+++ b/tests/pkcs1-padding/pkcs1-pad
@@ -33,7 +33,7 @@ fi
 
 # Test 1, PKCS#1 pad digestAlgorithm.parameters
 
-EXPECT1=3102
+EXPECT1=2002
 
 datefudge "2006-09-23" $CERTTOOL --verify-chain --infile 
$srcdir/pkcs1-pad-ok.pem | tee out1 >/dev/null 2>&1
 datefudge "2006-09-23" $CERTTOOL --verify-chain --infile 
$srcdir/pkcs1-pad-broken.pem | tee out2 >/dev/null 2>&1
@@ -81,7 +81,7 @@ echo "PKCS1-PAD2 OK"
 # by Andrei Pyshkin, Erik Tews and Ralf-Philipp Weinmann.
 
 
-EXPECT3=12
+EXPECT3=02
 
 datefudge "2006-09-23" $CERTTOOL --verify-chain --infile 
$srcdir/pkcs1-pad-broken3.pem | tee out1 >/dev/null 2>&1
 
diff --git a/tests/sha2/sha2 b/tests/sha2/sha2
index d094326..a2b810b 100755
--- a/tests/sha2/sha2
+++ b/tests/sha2/sha2
@@ -84,7 +84,7 @@ fi
 num=`cat new-user.pem new-subsubca.pem new-subca.pem new-ca.pem | $CERTTOOL 
--verify-chain | tee verify | grep -c Verified`
 #cat verify
 
-if test "$num" != "5"; then
+if test "$num" != "4"; then
     echo Verification failure
     exit 1
 fi
diff --git a/tests/x509paths/chain b/tests/x509paths/chain
index 060c30a..f581fec 100755
--- a/tests/x509paths/chain
+++ b/tests/x509paths/chain
@@ -30,25 +30,25 @@ test -d X509tests || tar xfz x509tests.tgz
 
 i=1
 while test -d X509tests/test$i; do
-    find X509tests/test$i -name *.crl -print0 |sort -r -z|xargs -n1 --null 
$CERTTOOL --crl-info --inder --infile > chain$i.pem
-    find X509tests/test$i -name E*.crt -print0 |sort -r -z|xargs -n1 --null 
$CERTTOOL --certificate-info --inder --infile >> chain$i.pem
+    find X509tests/test$i -name *.crl -print0 |sort -r -z|xargs -n1 --null 
$CERTTOOL --crl-info --inder --infile > chain$i.pem  2>/dev/null
+    find X509tests/test$i -name E*.crt -print0 |sort -r -z|xargs -n1 --null 
$CERTTOOL --certificate-info --inder --infile >> chain$i.pem 2>/dev/null
     if test "$i" -gt 1; then
-       find X509tests/test$i -name I*.crt -print0 |sort -r -z|xargs -n1 --null 
$CERTTOOL --certificate-info --inder --infile >> chain$i.pem
+       find X509tests/test$i -name I*.crt -print0 |sort -r -z|xargs -n1 --null 
$CERTTOOL --certificate-info --inder --infile >> chain$i.pem 2>/dev/null
     fi
-    find X509tests/test$i -name T*.crt -print0 |sort -r -z|xargs -n1 --null 
$CERTTOOL --certificate-info --inder --infile >> chain$i.pem
+    find X509tests/test$i -name T*.crt -print0 |sort -r -z|xargs -n1 --null 
$CERTTOOL --certificate-info --inder --infile >> chain$i.pem 2>/dev/null
     $CERTTOOL -e --infile chain$i.pem > out 2>&1
     rc=$?
     if test $rc != 0; then
        echo "Chain $i FATAL failure."
     else
-       if echo "$SUCCESS" | grep " $i " > /dev/null; then
-           if grep 'Verification output:' out | grep -v 'Verification output: 
Verified\.$' > /dev/null; then
+       if echo "$SUCCESS" | grep " $i " > /dev/null 2>&1; then
+           if grep 'Chain verification output:' out | grep -v 'Chain 
verification output: Verified\.$' > /dev/null 2>&1; then
                echo "Chain $i verification failure UNEXPECTED."
            else
                echo "Chain $i verification success as expected."
            fi
-       elif echo "$FAILURE" | grep " $i "; then
-           if grep 'Verification output:' out | grep -v 'Verification output: 
Verified\.$' > /dev/null; then
+       elif echo "$FAILURE" | grep " $i " >/dev/null 2>&1; then
+           if grep 'Chain verification output:' out | grep -v 'Chain 
verification output: Verified\.$' > /dev/null 2>&1; then
                echo "Chain $i verification failure as expected."
            else
                echo "Chain $i verification success UNEXPECTED. "


hooks/post-receive
-- 
GNU gnutls



reply via email to

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