/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
/*
Copyright (C) 2010 Collabora Ltd
The Gnome Keyring Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The Gnome Keyring 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the Gnome Library; see the file COPYING.LIB. If not,
see <http://www.gnu.org/licenses/>.
Author: Stef Walter <stefw@collabora.co.uk>
*/
#include "config.h"
#include "gcr/gcr-base.h"
#include "gcr/gcr-internal.h"
#include "egg/egg-asn1x.h"
#include "egg/egg-asn1-defs.h"
#include "egg/egg-testing.h"
#include "gck/gck-mock.h"
#include "gck/gck-test.h"
#include <p11-kit/pkcs11.h>
#include "gck/pkcs11x.h"
#include <glib.h>
#include <errno.h>
#include <string.h>
/* ---------------------------------------------------------------------------
* A Mock certificate that checks that it's always called on the
* same thread. A GcrCertificate implemented on top of a non-thread-safe
* crypto library would require this behavior.
*/
GType mock_certificate_get_type (void);
#define MOCK_CERTIFICATE(obj) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), mock_certificate_get_type (), MockCertificate))
typedef struct _MockCertificate {
GObject parent;
GThread *created_on;
gpointer data;
gsize n_data;
} MockCertificate;
typedef struct _MockCertificateClass {
GObjectClass parent_class;
} MockCertificateClass;
static void mock_certificate_iface (GcrCertificateIface *iface);
G_DEFINE_TYPE_WITH_CODE (MockCertificate, mock_certificate, G_TYPE_OBJECT,
GCR_CERTIFICATE_MIXIN_IMPLEMENT_COMPARABLE ();
G_IMPLEMENT_INTERFACE (GCR_TYPE_CERTIFICATE, mock_certificate_iface);
);
static void
mock_certificate_init (MockCertificate *self)
{
self->created_on = g_thread_self ();
}
static void
mock_certificate_finalize (GObject *obj)
{
MockCertificate *self = MOCK_CERTIFICATE (obj);
g_assert (self->created_on == g_thread_self ());
g_free (self->data);
G_OBJECT_CLASS (mock_certificate_parent_class)->finalize (obj);
}
static void
mock_certificate_class_init (MockCertificateClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->finalize = mock_certificate_finalize;
gobject_class->get_property = gcr_certificate_mixin_get_property;
gcr_certificate_mixin_class_init (gobject_class);
}
static gconstpointer
mock_certificate_real_get_der_data (GcrCertificate *base, gsize *n_data)
{
MockCertificate *self = MOCK_CERTIFICATE (base);
g_assert (self->created_on == g_thread_self ());
*n_data = self->n_data;
return self->data;
}
static void
mock_certificate_iface (GcrCertificateIface *iface)
{
iface->get_der_data = (gpointer)mock_certificate_real_get_der_data;
}
static GcrCertificate*
mock_certificate_new (gconstpointer data, gsize n_data)
{
MockCertificate *self = g_object_new (mock_certificate_get_type (), NULL);
self->data = g_memdup (data, n_data);
self->n_data = n_data;
g_assert (self->created_on == g_thread_self ());
return GCR_CERTIFICATE (self);
}
/* ----------------------------------------------------------------------------
* TESTS
*/
typedef struct {
/* A self signed certificate */
GcrCertificate *cert_self;
/* Simple CA + issued */
GcrCertificate *cert_ca;
GcrCertificate *cert_signed;
/* Root + intermediate + issued */
GcrCertificate *cert_root;
GcrCertificate *cert_inter;
GcrCertificate *cert_host;
CK_FUNCTION_LIST funcs;
} Test;
static void
setup (Test *test, gconstpointer unused)
{
GList *modules = NULL;
CK_FUNCTION_LIST_PTR f;
gchar *contents;
gsize n_contents;
const gchar *uris[2];
CK_RV rv;
GckModule *module;
rv = gck_mock_C_GetFunctionList (&f);
gck_assert_cmprv (rv, ==, CKR_OK);
memcpy (&test->funcs, f, sizeof (test->funcs));
/* Open a session */
rv = (test->funcs.C_Initialize) (NULL);
gck_assert_cmprv (rv, ==, CKR_OK);
g_assert (!modules);
module = gck_module_new (&test->funcs);
modules = g_list_prepend (modules, module);
gcr_pkcs11_set_modules (modules);
uris[0] = GCK_MOCK_SLOT_ONE_URI;
uris[1] = NULL;
gcr_pkcs11_set_trust_lookup_uris (uris);
gcr_pkcs11_set_trust_store_uri (GCK_MOCK_SLOT_ONE_URI);
gck_list_unref_free (modules);
/* A self-signed certificate */
if (!g_file_get_contents (SRCDIR "/gcr/fixtures/der-certificate.crt", &contents, &n_contents, NULL))
g_assert_not_reached ();
test->cert_self = gcr_simple_certificate_new ((const guchar *)contents, n_contents);
g_free (contents);
/* A signed certificate */
if (!g_file_get_contents (SRCDIR "/gcr/fixtures/dhansak-collabora.cer", &contents, &n_contents, NULL))
g_assert_not_reached ();
test->cert_signed = mock_certificate_new (contents, n_contents);
g_free (contents);
/* The signer for the above certificate */
if (!g_file_get_contents (SRCDIR "/gcr/fixtures/collabora-ca.cer", &contents, &n_contents, NULL))
g_assert_not_reached ();
test->cert_ca = mock_certificate_new (contents, n_contents);
g_free (contents);
/* A root CA */
if (!g_file_get_contents (SRCDIR "/gcr/fixtures/startcom-ca.cer", &contents, &n_contents, NULL))
g_assert_not_reached ();
test->cert_root = mock_certificate_new (contents, n_contents);
g_free (contents);
/* An intermediate */
if (!g_file_get_contents (SRCDIR "/gcr/fixtures/startcom-intermediate.cer", &contents, &n_contents, NULL))
g_assert_not_reached ();
test->cert_inter = mock_certificate_new (contents, n_contents);
g_free (contents);
/* Signed by above intermediate */
if (!g_file_get_contents (SRCDIR "/gcr/fixtures/jabber-server.cer", &contents, &n_contents, NULL))
g_assert_not_reached ();
test->cert_host = mock_certificate_new (contents, n_contents);
g_free (contents);
}
static void
add_certificate_to_module (GcrCertificate *certificate)
{
GckBuilder builder = GCK_BUILDER_INIT;
gconstpointer data;
gsize n_data, n_subject;
gpointer subject;
data = gcr_certificate_get_der_data (certificate, &n_data);
g_assert (data);
subject = gcr_certificate_get_subject_raw (certificate, &n_subject);
g_assert (subject);
/* Add a certificate to the module */
gck_builder_add_data (&builder, CKA_VALUE, data, n_data);
gck_builder_add_ulong (&builder, CKA_CLASS, CKO_CERTIFICATE);
gck_builder_add_ulong (&builder, CKA_CERTIFICATE_TYPE, CKC_X_509);
gck_builder_add_data (&builder, CKA_SUBJECT, subject, n_subject);
gck_mock_module_add_object (gck_builder_end (&builder));
g_free (subject);
}
static void
add_anchor_to_module (GcrCertificate *certificate, const gchar *purpose)
{
GckBuilder builder = GCK_BUILDER_INIT;
gconstpointer data;
gsize n_data;
data = gcr_certificate_get_der_data (certificate, &n_data);
g_assert (data);
/* And add a pinned certificate for the signed certificate */
gck_builder_add_data (&builder, CKA_X_CERTIFICATE_VALUE, data, n_data);
gck_builder_add_ulong (&builder, CKA_CLASS, CKO_X_TRUST_ASSERTION);
gck_builder_add_ulong (&builder, CKA_X_ASSERTION_TYPE, CKT_X_ANCHORED_CERTIFICATE);
gck_builder_add_string (&builder, CKA_X_PURPOSE, purpose);
gck_mock_module_add_object (gck_builder_end (&builder));
}
static void
add_pinned_to_module (GcrCertificate *certificate, const gchar *purpose, const gchar *host)
{
GckBuilder builder = GCK_BUILDER_INIT;
gconstpointer data;
gsize n_data;
data = gcr_certificate_get_der_data (certificate, &n_data);
g_assert (data);
/* And add a pinned certificate for the signed certificate */
gck_builder_add_data (&builder, CKA_X_CERTIFICATE_VALUE, data, n_data);
gck_builder_add_ulong (&builder, CKA_CLASS, CKO_X_TRUST_ASSERTION);
gck_builder_add_ulong (&builder, CKA_X_ASSERTION_TYPE, CKT_X_PINNED_CERTIFICATE);
gck_builder_add_string (&builder, CKA_X_PURPOSE, purpose);
gck_builder_add_string (&builder, CKA_X_PEER, host);
gck_mock_module_add_object (gck_builder_end (&builder));
}
static void
teardown (Test *test, gconstpointer unused)
{
CK_RV rv;
g_object_unref (test->cert_self);
g_object_unref (test->cert_signed);
g_object_unref (test->cert_ca);
g_object_unref (test->cert_host);
g_object_unref (test->cert_inter);
g_object_unref (test->cert_root);
rv = (test->funcs.C_Finalize) (NULL);
gck_assert_cmprv (rv, ==, CKR_OK);
_gcr_uninitialize_library ();
}
static void
test_new (Test *test, gconstpointer unused)
{
GcrCertificateChain *chain;
chain = gcr_certificate_chain_new ();
g_assert_cmpuint (gcr_certificate_chain_get_status (chain), ==,
GCR_CERTIFICATE_CHAIN_UNKNOWN);
g_assert_cmpuint (gcr_certificate_chain_get_length (chain), ==, 0);
g_assert (gcr_certificate_chain_get_endpoint (chain) == NULL);
g_object_unref (chain);
}
static void
test_new_with_cert (Test *test, gconstpointer unused)
{
GcrCertificateChain *chain;
GcrCertificate *check;
guint status, length;
chain = gcr_certificate_chain_new ();
gcr_certificate_chain_add (chain, test->cert_signed);
gcr_certificate_chain_add (chain, test->cert_ca);
g_assert_cmpuint (gcr_certificate_chain_get_status (chain), ==,
GCR_CERTIFICATE_CHAIN_UNKNOWN);
g_assert_cmpuint (gcr_certificate_chain_get_length (chain), ==, 2);
status = G_MAXUINT;
length = 0;
g_object_get (chain, "status", &status, "length", &length, NULL);
g_assert_cmpuint (status, ==, GCR_CERTIFICATE_CHAIN_UNKNOWN);
g_assert_cmpuint (length, ==, 2);
check = gcr_certificate_chain_get_certificate (chain, 1);
g_assert (check == test->cert_ca);
/* Not yet completed */
check = gcr_certificate_chain_get_anchor (chain);
g_assert (check == NULL);
check = gcr_certificate_chain_get_endpoint (chain);
g_assert (check == test->cert_signed);
g_object_unref (chain);
}
static void
test_selfsigned (Test *test, gconstpointer unused)
{
GcrCertificateChain *chain;
GError *error = NULL;
chain = gcr_certificate_chain_new ();
/* Add a self-signed certificate */
gcr_certificate_chain_add (chain, test->cert_self);
if (!gcr_certificate_chain_build (chain, GCR_PURPOSE_CLIENT_AUTH,
NULL, 0, NULL, &error))
g_assert_not_reached ();
g_assert_no_error (error);
g_assert_cmpuint (gcr_certificate_chain_get_status (chain), ==,
GCR_CERTIFICATE_CHAIN_SELFSIGNED);
g_object_unref (chain);
}
static void
test_incomplete (Test *test, gconstpointer unused)
{
GcrCertificateChain *chain;
GError *error = NULL;
chain = gcr_certificate_chain_new ();
/* Add a signed certificate */
gcr_certificate_chain_add (chain, test->cert_signed);
if (!gcr_certificate_chain_build (chain, GCR_PURPOSE_CLIENT_AUTH,
NULL, 0, NULL, &error))
g_assert_not_reached ();
g_assert_no_error (error);
g_assert_cmpuint (gcr_certificate_chain_get_status (chain), ==,
GCR_CERTIFICATE_CHAIN_INCOMPLETE);
g_object_unref (chain);
}
static void
test_empty (Test *test, gconstpointer unused)
{
GcrCertificateChain *chain;
GError *error = NULL;
chain = gcr_certificate_chain_new ();
/* Add no certificate */
if (!gcr_certificate_chain_build (chain, GCR_PURPOSE_CLIENT_AUTH,
NULL, 0, NULL, &error))
g_assert_not_reached ();
g_assert_no_error (error);
g_assert_cmpuint (gcr_certificate_chain_get_status (chain), ==,
GCR_CERTIFICATE_CHAIN_UNKNOWN);
g_object_unref (chain);
}
static void
test_trim_extras (Test *test, gconstpointer unused)
{
GcrCertificateChain *chain;
GError *error = NULL;
chain = gcr_certificate_chain_new ();
/* Add two unrelated certificates */
gcr_certificate_chain_add (chain, test->cert_self);
gcr_certificate_chain_add (chain, test->cert_signed);
g_assert_cmpuint (gcr_certificate_chain_get_length (chain), ==, 2);
if (!gcr_certificate_chain_build (chain, GCR_PURPOSE_CLIENT_AUTH,
NULL, 0, NULL, &error))
g_assert_not_reached ();
g_assert_no_error (error);
g_assert_cmpuint (gcr_certificate_chain_get_status (chain), ==,
GCR_CERTIFICATE_CHAIN_SELFSIGNED);
g_assert_cmpuint (gcr_certificate_chain_get_length (chain), ==, 1);
g_object_unref (chain);
}
static void
fetch_async_result (GObject *source, GAsyncResult *result, gpointer user_data)
{
*((GAsyncResult**)user_data) = result;
g_object_ref (result);
egg_test_wait_stop ();
}
static void
test_complete_async (Test *test, gconstpointer unused)
{
GcrCertificateChain *chain;
GError *error = NULL;
GAsyncResult *result = NULL;
chain = gcr_certificate_chain_new ();
/* Add a whole bunch of certificates */
gcr_certificate_chain_add (chain, test->cert_signed);
gcr_certificate_chain_add (chain, test->cert_ca);
gcr_certificate_chain_add (chain, test->cert_self);
gcr_certificate_chain_build_async (chain, GCR_PURPOSE_CLIENT_AUTH,
NULL, 0, NULL, fetch_async_result, &result);
egg_test_wait_until (500);
if (!gcr_certificate_chain_build_finish (chain, result, &error))
g_assert_not_reached ();
g_assert_no_error (error);
g_object_unref (result);
g_assert_cmpuint (gcr_certificate_chain_get_status (chain), ==,
GCR_CERTIFICATE_CHAIN_SELFSIGNED);
g_assert_cmpuint (gcr_certificate_chain_get_length (chain), ==, 2);
g_object_unref (chain);
}
static void
test_with_anchor (Test *test, gconstpointer unused)
{
GcrCertificateChain *chain;
GError *error = NULL;
chain = gcr_certificate_chain_new ();
/* Two certificates in chain with ca trust anchor */
gcr_certificate_chain_add (chain, test->cert_signed);
gcr_certificate_chain_add (chain, test->cert_ca);
add_anchor_to_module (test->cert_ca, GCR_PURPOSE_CLIENT_AUTH);
g_assert_cmpuint (gcr_certificate_chain_get_length (chain), ==, 2);
if (!gcr_certificate_chain_build (chain, GCR_PURPOSE_CLIENT_AUTH,
NULL, 0, NULL, &error))
g_assert_not_reached ();
g_assert_no_error (error);
g_assert_cmpuint (gcr_certificate_chain_get_status (chain), ==,
GCR_CERTIFICATE_CHAIN_ANCHORED);
g_assert_cmpuint (gcr_certificate_chain_get_length (chain), ==, 2);
g_assert (gcr_certificate_chain_get_anchor (chain) == test->cert_ca);
g_object_unref (chain);
}
static void
test_with_anchor_and_lookup_ca (Test *test, gconstpointer unused)
{
GcrCertificateChain *chain;
GError *error = NULL;
chain = gcr_certificate_chain_new ();
/* One signed certificate, with CA in pkcs11, and trust anchor */
gcr_certificate_chain_add (chain, test->cert_signed);
add_certificate_to_module (test->cert_ca);
add_anchor_to_module (test->cert_ca, GCR_PURPOSE_CLIENT_AUTH);
g_assert_cmpuint (gcr_certificate_chain_get_length (chain), ==, 1);
if (!gcr_certificate_chain_build (chain, GCR_PURPOSE_CLIENT_AUTH,
NULL, 0, NULL, &error))
g_assert_not_reached ();
g_assert_no_error (error);
g_assert_cmpuint (gcr_certificate_chain_get_status (chain), ==,
GCR_CERTIFICATE_CHAIN_ANCHORED);
g_assert_cmpuint (gcr_certificate_chain_get_length (chain), ==, 2);
g_assert (gcr_certificate_chain_get_anchor (chain) != NULL);
g_object_unref (chain);
}
static void
test_with_pinned (Test *test, gconstpointer unused)
{
GcrCertificateChain *chain;
GError *error = NULL;
chain = gcr_certificate_chain_new ();
/* One certificate, and add CA to pkcs11 */
gcr_certificate_chain_add (chain, test->cert_signed);
gcr_certificate_chain_add (chain, test->cert_ca);
add_pinned_to_module (test->cert_signed, GCR_PURPOSE_CLIENT_AUTH, "pinned.example.com");
g_assert_cmpuint (gcr_certificate_chain_get_length (chain), ==, 2);
/* But we don't allow the lookup to happen */
if (!gcr_certificate_chain_build (chain, GCR_PURPOSE_CLIENT_AUTH,
"pinned.example.com", 0, NULL, &error))
g_assert_not_reached ();
g_assert_no_error (error);
g_assert_cmpuint (gcr_certificate_chain_get_status (chain), ==,
GCR_CERTIFICATE_CHAIN_PINNED);
g_assert_cmpuint (gcr_certificate_chain_get_length (chain), ==, 1);
g_assert (gcr_certificate_chain_get_anchor (chain) == NULL);
g_object_unref (chain);
}
static void
test_without_lookups (Test *test, gconstpointer unused)
{
GcrCertificateChain *chain;
GError *error = NULL;
chain = gcr_certificate_chain_new ();
/* One certificate, and add CA to pkcs11 */
gcr_certificate_chain_add (chain, test->cert_signed);
add_certificate_to_module (test->cert_ca);
g_assert_cmpuint (gcr_certificate_chain_get_length (chain), ==, 1);
/* But we don't allow the lookup to happen */
if (!gcr_certificate_chain_build (chain, GCR_PURPOSE_CLIENT_AUTH,
NULL, GCR_CERTIFICATE_CHAIN_NO_LOOKUPS,
NULL, &error))
g_assert_not_reached ();
g_assert_no_error (error);
g_assert_cmpuint (gcr_certificate_chain_get_status (chain), ==,
GCR_CERTIFICATE_CHAIN_INCOMPLETE);
g_assert_cmpuint (gcr_certificate_chain_get_length (chain), ==, 1);
g_assert (gcr_certificate_chain_get_anchor (chain) == NULL);
g_object_unref (chain);
}
static void
test_with_lookup_error (Test *test, gconstpointer unused)
{
GcrCertificateChain *chain;
GError *error = NULL;
/* Make the lookup fail */
test->funcs.C_GetAttributeValue = gck_mock_fail_C_GetAttributeValue;
chain = gcr_certificate_chain_new ();
/* Two certificates in chain with ca trust anchor */
gcr_certificate_chain_add (chain, test->cert_signed);
add_certificate_to_module (test->cert_ca);
g_assert_cmpuint (gcr_certificate_chain_get_length (chain), ==, 1);
if (gcr_certificate_chain_build (chain, GCR_PURPOSE_CLIENT_AUTH,
NULL, 0, NULL, &error))
g_assert_not_reached ();
g_assert_error (error, GCK_ERROR, CKR_FUNCTION_FAILED);
g_clear_error (&error);
g_assert_cmpuint (gcr_certificate_chain_get_status (chain), ==,
GCR_CERTIFICATE_CHAIN_UNKNOWN);
g_object_unref (chain);
}
static void
test_wrong_order_anchor (Test *test, gconstpointer unused)
{
GcrCertificateChain *chain;
GError *error = NULL;
chain = gcr_certificate_chain_new ();
/* Two certificates in chain with ca trust anchor */
gcr_certificate_chain_add (chain, test->cert_host);
gcr_certificate_chain_add (chain, test->cert_root);
gcr_certificate_chain_add (chain, test->cert_inter);
add_anchor_to_module (test->cert_root, GCR_PURPOSE_CLIENT_AUTH);
g_assert_cmpuint (gcr_certificate_chain_get_length (chain), ==, 3);
if (!gcr_certificate_chain_build (chain, GCR_PURPOSE_CLIENT_AUTH,
NULL, 0, NULL, &error))
g_assert_not_reached ();
g_assert_no_error (error);
g_assert_cmpuint (gcr_certificate_chain_get_status (chain), ==,
GCR_CERTIFICATE_CHAIN_ANCHORED);
g_assert_cmpuint (gcr_certificate_chain_get_length (chain), ==, 3);
g_assert (gcr_certificate_chain_get_anchor (chain) == test->cert_root);
g_object_unref (chain);
}
static void
test_with_anchor_error (Test *test, gconstpointer unused)
{
GcrCertificateChain *chain;
GError *error = NULL;
/* Make the lookup fail */
test->funcs.C_GetAttributeValue = gck_mock_fail_C_GetAttributeValue;
chain = gcr_certificate_chain_new ();
/* Two certificates in chain with ca trust anchor */
gcr_certificate_chain_add (chain, test->cert_signed);
add_certificate_to_module (test->cert_ca);
if (gcr_certificate_chain_build (chain, GCR_PURPOSE_CLIENT_AUTH,
NULL, 0, NULL, &error))
g_assert_not_reached ();
g_assert_error (error, GCK_ERROR, CKR_FUNCTION_FAILED);
g_clear_error (&error);
g_assert_cmpuint (gcr_certificate_chain_get_status (chain), ==,
GCR_CERTIFICATE_CHAIN_UNKNOWN);
g_object_unref (chain);
}
static void
test_with_anchor_error_async (Test *test, gconstpointer unused)
{
GcrCertificateChain *chain;
GError *error = NULL;
GAsyncResult *result;
/* Make the lookup fail */
test->funcs.C_GetAttributeValue = gck_mock_fail_C_GetAttributeValue;
chain = gcr_certificate_chain_new ();
/* Two certificates in chain with ca trust anchor */
gcr_certificate_chain_add (chain, test->cert_signed);
add_certificate_to_module (test->cert_ca);
gcr_certificate_chain_build_async (chain, GCR_PURPOSE_CLIENT_AUTH,
NULL, 0, NULL, fetch_async_result, &result);
egg_test_wait_until (500);
if (gcr_certificate_chain_build_finish (chain, result, &error))
g_assert_not_reached ();
g_assert_error (error, GCK_ERROR, CKR_FUNCTION_FAILED);
g_clear_error (&error);
g_object_unref (result);
g_assert_cmpuint (gcr_certificate_chain_get_status (chain), ==,
GCR_CERTIFICATE_CHAIN_UNKNOWN);
g_object_unref (chain);
}
int
main (int argc, char **argv)
{
g_test_init (&argc, &argv, NULL);
g_set_prgname ("test-certificate-chain");
g_test_add ("/gcr/certificate-chain/new", Test, NULL, setup, test_new, teardown);
g_test_add ("/gcr/certificate-chain/new_with_cert", Test, NULL, setup, test_new_with_cert, teardown);
g_test_add ("/gcr/certificate-chain/selfsigned", Test, NULL, setup, test_selfsigned, teardown);
g_test_add ("/gcr/certificate-chain/incomplete", Test, NULL, setup, test_incomplete, teardown);
g_test_add ("/gcr/certificate-chain/empty", Test, NULL, setup, test_empty, teardown);
g_test_add ("/gcr/certificate-chain/trim_extras", Test, NULL, setup, test_trim_extras, teardown);
g_test_add ("/gcr/certificate-chain/complete_async", Test, NULL, setup, test_complete_async, teardown);
g_test_add ("/gcr/certificate-chain/with_anchor", Test, NULL, setup, test_with_anchor, teardown);
g_test_add ("/gcr/certificate-chain/with_anchor_and_lookup_ca", Test, NULL, setup, test_with_anchor_and_lookup_ca, teardown);
g_test_add ("/gcr/certificate-chain/with_pinned", Test, NULL, setup, test_with_pinned, teardown);
g_test_add ("/gcr/certificate-chain/without_lookups", Test, NULL, setup, test_without_lookups, teardown);
g_test_add ("/gcr/certificate-chain/wrong_order_anchor", Test, NULL, setup, test_wrong_order_anchor, teardown);
g_test_add ("/gcr/certificate-chain/with_lookup_error", Test, NULL, setup, test_with_lookup_error, teardown);
g_test_add ("/gcr/certificate-chain/with_anchor_error", Test, NULL, setup, test_with_anchor_error, teardown);
g_test_add ("/gcr/certificate-chain/with_anchor_error_async", Test, NULL, setup, test_with_anchor_error_async, teardown);
return egg_tests_run_with_loop ();
}