[gnome-keyring/trust-store: 26/26] [gcr] Implement GcrPkcs11Certificate which loads certs from PKCS#11



commit be5e83c8d4ea50cd569d4fe7e5095ad1806c3e6b
Author: Stef Walter <stefw collabora co uk>
Date:   Mon Dec 6 22:43:01 2010 +0000

    [gcr] Implement GcrPkcs11Certificate which loads certs from PKCS#11
    
    In particular we can lookup certs by issuer from the PKCS#11 store.

 gck/gck-mock.c                      |    7 +
 gck/gck-mock.h                      |    5 +
 gcr/gcr-pkcs11-certificate.c        |  334 +++++++++++++++++++++++++++++++++++
 gcr/gcr-pkcs11-certificate.h        |   76 ++++++++
 gcr/tests/Makefile.am               |    1 +
 gcr/tests/test-pkcs11-certificate.c |  255 ++++++++++++++++++++++++++
 6 files changed, 678 insertions(+), 0 deletions(-)
---
diff --git a/gck/gck-mock.c b/gck/gck-mock.c
index 4a64590..58c9b99 100644
--- a/gck/gck-mock.c
+++ b/gck/gck-mock.c
@@ -943,6 +943,13 @@ gck_mock_C_GetAttributeValue (CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObje
 }
 
 CK_RV
+gck_mock_fail_C_GetAttributeValue (CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
+                                   CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
+{
+	return CKR_FUNCTION_FAILED;
+}
+
+CK_RV
 gck_mock_C_SetAttributeValue (CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
                               CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
 {
diff --git a/gck/gck-mock.h b/gck/gck-mock.h
index fcdf2fb..db14f36 100644
--- a/gck/gck-mock.h
+++ b/gck/gck-mock.h
@@ -152,6 +152,11 @@ CK_RV               gck_mock_C_GetAttributeValue                   (CK_SESSION_H
                                                                     CK_ATTRIBUTE_PTR pTemplate,
                                                                     CK_ULONG ulCount);
 
+CK_RV               gck_mock_fail_C_GetAttributeValue              (CK_SESSION_HANDLE hSession,
+                                                                    CK_OBJECT_HANDLE hObject,
+                                                                    CK_ATTRIBUTE_PTR pTemplate,
+                                                                    CK_ULONG ulCount);
+
 CK_RV               gck_mock_C_SetAttributeValue                   (CK_SESSION_HANDLE hSession,
                                                                     CK_OBJECT_HANDLE hObject,
                                                                     CK_ATTRIBUTE_PTR pTemplate,
diff --git a/gcr/gcr-pkcs11-certificate.c b/gcr/gcr-pkcs11-certificate.c
new file mode 100644
index 0000000..0a613a1
--- /dev/null
+++ b/gcr/gcr-pkcs11-certificate.c
@@ -0,0 +1,334 @@
+/*
+ * gnome-keyring
+ *
+ * Copyright (C) 2010 Collabora Ltd
+ *
+ * This program 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 program 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 program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Author: Stef Walter <stefw collabora co uk>
+ */
+
+#include "config.h"
+
+#include "gcr-pkcs11-certificate.h"
+
+#include <gck/gck.h>
+#include <string.h>
+
+#include "gcr-certificate.h"
+#include "gcr-internal.h"
+
+#include "pkcs11/pkcs11.h"
+
+enum {
+	PROP_0,
+	PROP_ATTRIBUTES
+};
+
+struct _GcrPkcs11CertificatePrivate {
+	GckAttributes *attrs;
+};
+
+static void gcr_certificate_iface (GcrCertificateIface *iface);
+G_DEFINE_TYPE_WITH_CODE (GcrPkcs11Certificate, gcr_pkcs11_certificate, GCK_TYPE_OBJECT,
+                         G_IMPLEMENT_INTERFACE (GCR_TYPE_CERTIFICATE, gcr_certificate_iface));
+
+/* ----------------------------------------------------------------------------
+ * INTERAL
+ */
+
+static GckEnumerator*
+prepare_lookup_certificate_issuer (GcrCertificate *cert)
+{
+	GckAttributes *search;
+	GckEnumerator *en;
+	gpointer data;
+	gsize n_data;
+	GList *modules;
+
+	search = gck_attributes_new ();
+	gck_attributes_add_ulong (search, CKA_CLASS, CKO_CERTIFICATE);
+	gck_attributes_add_ulong (search, CKA_CERTIFICATE_TYPE, CKC_X_509);
+
+	data = gcr_certificate_get_issuer_raw (cert, &n_data);
+	gck_attributes_add_data (search, CKA_SUBJECT, data, n_data);
+	g_free (data);
+
+	modules = _gcr_get_pkcs11_modules ();
+	en = gck_modules_enumerate_objects (modules, search, 0);
+	gck_attributes_unref (search);
+
+	return en;
+}
+
+static GcrCertificate*
+perform_lookup_certificate (GckEnumerator *en, GCancellable *cancel, GError **error)
+{
+	GcrCertificate *cert;
+	GckObject *object;
+	GckAttributes *attrs;
+
+	object = gck_enumerator_next (en, cancel, error);
+
+	if (object == NULL)
+		return NULL;
+
+	/*
+	 * Only the CKA_VALUE, CKA_CLASS and CKA_CERTIFICATE_TYPE
+	 * is strictly necessary here, but we get more attrs.
+	 */
+	attrs = gck_object_get (object, cancel, error,
+	                        CKA_VALUE, CKA_LABEL,
+	                        CKA_ID, CKA_CLASS,
+	                        CKA_CERTIFICATE_TYPE,
+	                        CKA_ISSUER,
+	                        CKA_SERIAL_NUMBER,
+	                        GCK_INVALID);
+
+	if (attrs == NULL) {
+		g_object_unref (object);
+		return NULL;
+	}
+
+	cert = g_object_new (GCR_TYPE_PKCS11_CERTIFICATE,
+	                     "module", gck_object_get_module (object),
+	                     "handle", gck_object_get_handle (object),
+	                     "session", gck_object_get_session (object),
+	                     "attributes", attrs,
+	                     NULL);
+
+	g_object_unref (object);
+	gck_attributes_unref (attrs);
+
+	return cert;
+}
+
+static void
+thread_lookup_certificate (GSimpleAsyncResult *res, GObject *object, GCancellable *cancel)
+{
+	GError *error = NULL;
+	GcrCertificate *cert;
+
+	cert = perform_lookup_certificate (GCK_ENUMERATOR (object), cancel, &error);
+
+	if (error != NULL) {
+		g_assert (!cert);
+		g_simple_async_result_set_from_error (res, error);
+		g_clear_error (&error);
+
+	} else if (cert != NULL) {
+		g_simple_async_result_set_op_res_gpointer (res, cert, g_object_unref);
+
+	} else {
+		g_simple_async_result_set_op_res_gpointer (res, NULL, NULL);
+	}
+}
+
+/* ----------------------------------------------------------------------------
+ * OBJECT
+ */
+
+static GObject*
+gcr_pkcs11_certificate_constructor (GType type, guint n_props, GObjectConstructParam *props)
+{
+	gpointer obj = G_OBJECT_CLASS (gcr_pkcs11_certificate_parent_class)->constructor (type, n_props, props);
+	GckAttributes *attrs;
+	GckAttribute *attr;
+	gulong value;
+
+	attrs = gcr_pkcs11_certificate_get_attributes (obj);
+	g_return_val_if_fail (attrs, NULL);
+
+	if (!gck_attributes_find_ulong (attrs, CKA_CLASS, &value) ||
+	    value != CKO_CERTIFICATE) {
+		g_warning ("attributes don't contain a certificate with: %s",
+		           "CKA_CLASS == CKO_CERTIFICATE");
+		return NULL;
+	}
+
+	if (!gck_attributes_find_ulong (attrs, CKA_CERTIFICATE_TYPE, &value) ||
+	    value != CKC_X_509) {
+		g_warning ("attributes don't contain a certificate with: %s",
+		           "CKA_CERTIFICATE_TYPE == CKC_X_509");
+		return NULL;
+	}
+
+	attr = gck_attributes_find (attrs, CKA_VALUE);
+	if (!attr || !attr->value || attr->length == 0 || attr->length == G_MAXULONG) {
+		g_warning ("attributes don't contain a valid: CKA_VALUE");
+		return NULL;
+	}
+
+	return obj;
+}
+
+static void
+gcr_pkcs11_certificate_init (GcrPkcs11Certificate *self)
+{
+	self->pv = G_TYPE_INSTANCE_GET_PRIVATE (self, GCR_TYPE_PKCS11_CERTIFICATE, GcrPkcs11CertificatePrivate);
+}
+
+static void
+gcr_pkcs11_certificate_set_property (GObject *obj, guint prop_id, const GValue *value,
+                                     GParamSpec *pspec)
+{
+	GcrPkcs11Certificate *self = GCR_PKCS11_CERTIFICATE (obj);
+
+	switch (prop_id) {
+	case PROP_ATTRIBUTES:
+		g_return_if_fail (self->pv->attrs == NULL);
+		self->pv->attrs = g_value_dup_boxed (value);
+		g_return_if_fail (self->pv->attrs != NULL);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+gcr_pkcs11_certificate_get_property (GObject *obj, guint prop_id, GValue *value,
+                                     GParamSpec *pspec)
+{
+	GcrPkcs11Certificate *self = GCR_PKCS11_CERTIFICATE (obj);
+
+	switch (prop_id) {
+	case PROP_ATTRIBUTES:
+		g_value_set_boxed (value, gcr_pkcs11_certificate_get_attributes (self));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+gcr_pkcs11_certificate_finalize (GObject *obj)
+{
+	GcrPkcs11Certificate *self = GCR_PKCS11_CERTIFICATE (obj);
+
+	gck_attributes_unref (self->pv->attrs);
+
+	G_OBJECT_CLASS (gcr_pkcs11_certificate_parent_class)->finalize (obj);
+}
+
+static void
+gcr_pkcs11_certificate_class_init (GcrPkcs11CertificateClass *klass)
+{
+	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+	gobject_class->constructor = gcr_pkcs11_certificate_constructor;
+	gobject_class->get_property = gcr_pkcs11_certificate_get_property;
+	gobject_class->set_property = gcr_pkcs11_certificate_set_property;
+	gobject_class->finalize = gcr_pkcs11_certificate_finalize;
+
+	g_object_class_install_property (gobject_class, PROP_ATTRIBUTES,
+	         g_param_spec_boxed ("attributes", "Attributes", "The data displayed in the renderer",
+	                             GCK_TYPE_ATTRIBUTES, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+	g_type_class_add_private (gobject_class, sizeof (GcrPkcs11CertificatePrivate));
+
+	_gcr_initialize ();
+}
+
+static gconstpointer
+gcr_pkcs11_certificate_real_get_der_data (GcrCertificate *base, gsize *n_data)
+{
+	GcrPkcs11Certificate *self = GCR_PKCS11_CERTIFICATE (base);
+	GckAttribute *attr;
+
+	g_return_val_if_fail (GCR_IS_CERTIFICATE (self), NULL);
+	g_return_val_if_fail (n_data, NULL);
+	g_return_val_if_fail (self->pv->attrs, NULL);
+
+	attr = gck_attributes_find (self->pv->attrs, CKA_VALUE);
+	g_return_val_if_fail (attr && attr->length != 0 && attr->length != G_MAXULONG, NULL);
+	*n_data = attr->length;
+	return attr->value;
+}
+
+static void
+gcr_certificate_iface (GcrCertificateIface *iface)
+{
+	iface->get_der_data = (gpointer)gcr_pkcs11_certificate_real_get_der_data;
+}
+
+/* -----------------------------------------------------------------------------
+ * PUBLIC
+ */
+
+
+GckAttributes*
+gcr_pkcs11_certificate_get_attributes (GcrPkcs11Certificate *self)
+{
+	g_return_val_if_fail (GCR_IS_PKCS11_CERTIFICATE (self), NULL);
+	return self->pv->attrs;
+}
+
+GcrCertificate*
+gcr_pkcs11_certificate_lookup_issuer (GcrCertificate *cert, GCancellable *cancel,
+                                      GError **error)
+{
+	GckEnumerator *en;
+	GcrCertificate *issuer;
+
+	en = prepare_lookup_certificate_issuer (cert);
+	g_return_val_if_fail (en, FALSE);
+
+	issuer = perform_lookup_certificate (en, cancel, error);
+	g_object_unref (en);
+
+	return issuer;
+}
+
+void
+gcr_pkcs11_certificate_lookup_issuer_async (GcrCertificate *cert, GCancellable *cancel,
+                                            GAsyncReadyCallback callback, gpointer user_data)
+{
+	GSimpleAsyncResult *async;
+	GckEnumerator *en;
+
+	en = prepare_lookup_certificate_issuer (cert);
+	g_return_if_fail (en);
+
+	async = g_simple_async_result_new (G_OBJECT (en), callback, user_data,
+	                                   gcr_pkcs11_certificate_lookup_issuer_async);
+
+	g_simple_async_result_run_in_thread (async, thread_lookup_certificate,
+	                                     G_PRIORITY_DEFAULT, cancel);
+
+	g_object_unref (async);
+	g_object_unref (en);
+}
+
+GcrCertificate*
+gcr_pkcs11_certificate_lookup_issuer_finish (GAsyncResult *res, GError **error)
+{
+	GcrCertificate *cert;
+
+	g_return_val_if_fail (g_simple_async_result_is_valid (res,
+	                      g_async_result_get_source_object (res),
+	                      gcr_pkcs11_certificate_lookup_issuer_async), NULL);
+
+	if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error))
+		return NULL;
+
+	cert = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res));
+	if (cert != NULL)
+		g_object_ref (cert);
+
+	return cert;
+}
diff --git a/gcr/gcr-pkcs11-certificate.h b/gcr/gcr-pkcs11-certificate.h
new file mode 100644
index 0000000..a90c860
--- /dev/null
+++ b/gcr/gcr-pkcs11-certificate.h
@@ -0,0 +1,76 @@
+/*
+ * gnome-keyring
+ *
+ * Copyright (C) 2010 Collabora Ltd
+ *
+ * This program 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 program 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 program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Author: Stef Walter <stefw collabora co uk>
+ */
+
+#if !defined (__GCR_H_INSIDE__) && !defined (GCR_COMPILATION)
+#error "Only <gcr/gcr.h> can be included directly."
+#endif
+
+#ifndef __GCR_PKCS11_CERTIFICATE_H__
+#define __GCR_PKCS11_CERTIFICATE_H__
+
+#include "gcr-types.h"
+#include "gcr-certificate.h"
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define GCR_TYPE_PKCS11_CERTIFICATE               (gcr_pkcs11_certificate_get_type ())
+#define GCR_PKCS11_CERTIFICATE(obj)               (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCR_TYPE_CERTIFICATE, GcrPkcs11Certificate))
+#define GCR_PKCS11_CERTIFICATE_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST ((klass), GCR_TYPE_CERTIFICATE, GcrPkcs11CertificateClass))
+#define GCR_IS_PKCS11_CERTIFICATE(obj)            (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCR_TYPE_CERTIFICATE))
+#define GCR_IS_PKCS11_CERTIFICATE_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE ((klass), GCR_TYPE_CERTIFICATE))
+#define GCR_PKCS11_CERTIFICATE_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS ((obj), GCR_TYPE_CERTIFICATE, GcrPkcs11CertificateClass))
+
+typedef struct _GcrPkcs11Certificate GcrPkcs11Certificate;
+typedef struct _GcrPkcs11CertificateClass GcrPkcs11CertificateClass;
+typedef struct _GcrPkcs11CertificatePrivate GcrPkcs11CertificatePrivate;
+
+struct _GcrPkcs11Certificate {
+	GckObject parent;
+	GcrPkcs11CertificatePrivate *pv;
+};
+
+struct _GcrPkcs11CertificateClass {
+	GckObjectClass parent_class;
+};
+
+GType                   gcr_pkcs11_certificate_get_type               (void);
+
+GckAttributes*          gcr_pkcs11_certificate_get_attributes         (GcrPkcs11Certificate *self);
+
+GcrCertificate*         gcr_pkcs11_certificate_lookup_issuer          (GcrCertificate *cert,
+                                                                       GCancellable *cancel,
+                                                                       GError **error);
+
+void                    gcr_pkcs11_certificate_lookup_issuer_async    (GcrCertificate *cert,
+                                                                       GCancellable *cancel,
+                                                                       GAsyncReadyCallback callback,
+                                                                       gpointer user_data);
+
+GcrCertificate*         gcr_pkcs11_certificate_lookup_issuer_finish   (GAsyncResult *res,
+                                                                       GError **error);
+
+G_END_DECLS
+
+#endif /* __GCR_PKCS11_CERTIFICATE_H__ */
diff --git a/gcr/tests/Makefile.am b/gcr/tests/Makefile.am
index daee53f..ba06b60 100644
--- a/gcr/tests/Makefile.am
+++ b/gcr/tests/Makefile.am
@@ -3,6 +3,7 @@
 TESTING_FILES = \
 	test-certificate.c \
 	test-simple-certificate.c \
+	test-pkcs11-certificate.c \
 	test-trust.c \
 	unit-test-parser.c
 
diff --git a/gcr/tests/test-pkcs11-certificate.c b/gcr/tests/test-pkcs11-certificate.c
new file mode 100644
index 0000000..64866d2
--- /dev/null
+++ b/gcr/tests/test-pkcs11-certificate.c
@@ -0,0 +1,255 @@
+/* -*- 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,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.
+
+   Author: Stef Walter <stefw collabora co uk>
+*/
+
+#include "config.h"
+
+#include "test-suite.h"
+
+#include "egg/egg-asn1x.h"
+#include "egg/egg-asn1-defs.h"
+
+#include "gcr.h"
+#include "gcr/gcr-internal.h"
+
+#include "gck/gck-mock.h"
+#include "gck/gck-test.h"
+
+#include "pkcs11/pkcs11n.h"
+
+#include <glib.h>
+
+static gpointer cert_data = NULL;
+static gsize n_cert_data = 0;
+static gpointer cert2_data = NULL;
+static gsize n_cert2_data = 0;
+static CK_FUNCTION_LIST funcs;
+static GList *modules = NULL;
+
+TESTING_SETUP (pkcs11_certificate)
+{
+	GckAttributes *attrs;
+	CK_FUNCTION_LIST_PTR f;
+	GckModule *module;
+	gconstpointer subject;
+	gsize n_subject;
+	GNode *asn, *node;
+	CK_RV rv;
+
+	cert_data = testing_data_read ("der-certificate.crt", &n_cert_data);
+	g_assert (cert_data);
+
+	cert2_data = testing_data_read ("der-certificate-dsa.cer", &n_cert2_data);
+	g_assert (cert2_data);
+
+	rv = gck_mock_C_GetFunctionList (&f);
+	gck_assert_cmprv (rv, ==, CKR_OK);
+	memcpy (&funcs, f, sizeof (funcs));
+
+	/* Open a session */
+	rv = (funcs.C_Initialize) (NULL);
+	gck_assert_cmprv (rv, ==, CKR_OK);
+
+	g_assert (!modules);
+	module = gck_module_new (&funcs, 0);
+	modules = g_list_prepend (modules, module);
+
+	_gcr_set_test_pkcs11_modules (modules);
+
+	asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "Certificate", cert_data, n_cert_data);
+	g_assert (asn);
+	node = egg_asn1x_node (asn, "tbsCertificate", "subject", NULL);
+	subject = egg_asn1x_get_raw_element (node, &n_subject);
+
+	/* Add a certificate to the module */
+	attrs = gck_attributes_new ();
+	gck_attributes_add_data (attrs, CKA_VALUE, cert_data, n_cert_data);
+	gck_attributes_add_ulong (attrs, CKA_CLASS, CKO_CERTIFICATE);
+	gck_attributes_add_ulong (attrs, CKA_CERTIFICATE_TYPE, CKC_X_509);
+	gck_attributes_add_data (attrs, CKA_SUBJECT, subject, n_subject);
+	gck_mock_module_take_object (attrs);
+
+	egg_asn1x_destroy (asn);
+}
+
+TESTING_TEARDOWN (pkcs11_certificate)
+{
+	CK_RV rv;
+
+	g_free (cert_data);
+	cert_data = NULL;
+	n_cert_data = 0;
+
+	g_free (cert2_data);
+	cert2_data = NULL;
+	n_cert2_data = 0;
+
+	rv = (funcs.C_Finalize) (NULL);
+	gck_assert_cmprv (rv, ==, CKR_OK);
+
+	gck_list_unref_free (modules);
+	modules = NULL;
+}
+
+TESTING_TEST (pkcs11_lookup_certificate_issuer)
+{
+	GcrCertificate *cert, *issuer;
+	GError *error = NULL;
+	GckAttributes *attrs;
+	GckAttribute *attr;
+	gconstpointer der;
+	gsize n_der;
+
+	cert = gcr_simple_certificate_new_static (cert_data, n_cert_data);
+	g_assert (cert);
+
+	/* Should be self-signed, so should find itself (added in setup) */
+	issuer = gcr_pkcs11_certificate_lookup_issuer (cert, NULL, &error);
+	g_assert (GCR_IS_PKCS11_CERTIFICATE (issuer));
+	g_assert (error == NULL);
+
+	/* Should be the same certificate */
+	der = gcr_certificate_get_der_data (issuer, &n_der);
+	g_assert_cmpsize (n_der, ==, n_cert_data);
+	g_assert (memcmp (der, cert_data, n_cert_data) == 0);
+
+	/* Should return the same certificate here too */
+	attrs = gcr_pkcs11_certificate_get_attributes (GCR_PKCS11_CERTIFICATE (issuer));
+	g_assert (attrs);
+	attr = gck_attributes_find (attrs, CKA_VALUE);
+	g_assert (attr);
+	g_assert_cmpsize (attr->length, ==, n_cert_data);
+	g_assert (memcmp (attr->value, cert_data, n_cert_data) == 0);
+
+	/* Should return the same certificate here too */
+	attrs = NULL;
+	g_object_get (issuer, "attributes", &attrs, NULL);
+	g_assert (attrs);
+	attr = gck_attributes_find (attrs, CKA_VALUE);
+	g_assert (attr);
+	g_assert_cmpsize (attr->length, ==, n_cert_data);
+	g_assert (memcmp (attr->value, cert_data, n_cert_data) == 0);
+	gck_attributes_unref (attrs);
+
+	g_object_unref (cert);
+	g_object_unref (issuer);
+}
+
+TESTING_TEST (pkcs11_lookup_certificate_issuer_not_found)
+{
+	GcrCertificate *cert, *issuer;
+	GError *error = NULL;
+
+	cert = gcr_simple_certificate_new_static (cert2_data, n_cert2_data);
+	g_assert (cert);
+
+	/* Issuer shouldn't be found */
+	issuer = gcr_pkcs11_certificate_lookup_issuer (cert, NULL, &error);
+	g_assert (issuer == NULL);
+	g_assert (error == NULL);
+
+	g_object_unref (cert);
+}
+
+static void
+fetch_async_result (GObject *source, GAsyncResult *result, gpointer user_data)
+{
+	*((GAsyncResult**)user_data) = result;
+	g_object_ref (result);
+	testing_wait_stop ();
+}
+
+TESTING_TEST (pkcs11_lookup_certificate_issuer_async)
+{
+	GAsyncResult *result = NULL;
+	GcrCertificate *cert, *issuer;
+	GError *error = NULL;
+	gconstpointer der;
+	gsize n_der;
+
+	cert = gcr_simple_certificate_new_static (cert_data, n_cert_data);
+	g_assert (cert);
+
+	/* Should be self-signed, so should find itself (added in setup) */
+	gcr_pkcs11_certificate_lookup_issuer_async (cert, NULL, fetch_async_result, &result);
+	testing_wait_until (500);
+	g_assert (result);
+	issuer = gcr_pkcs11_certificate_lookup_issuer_finish (result, &error);
+	g_assert (GCR_IS_PKCS11_CERTIFICATE (issuer));
+	g_assert (error == NULL);
+	g_object_unref (result);
+	result = NULL;
+
+	/* Should be the same certificate */
+	der = gcr_certificate_get_der_data (issuer, &n_der);
+	g_assert_cmpsize (n_der, ==, n_cert_data);
+	g_assert (memcmp (der, cert_data, n_cert_data) == 0);
+
+	g_object_unref (cert);
+	g_object_unref (issuer);
+}
+
+TESTING_TEST (pkcs11_lookup_certificate_issuer_failure)
+{
+	GcrCertificate *cert, *issuer;
+	GError *error = NULL;
+
+	cert = gcr_simple_certificate_new_static (cert_data, n_cert_data);
+	g_assert (cert);
+
+	/* Make the lookup fail */
+	funcs.C_GetAttributeValue = gck_mock_fail_C_GetAttributeValue;
+
+	issuer = gcr_pkcs11_certificate_lookup_issuer (cert, NULL, &error);
+	g_assert (issuer == NULL);
+	g_assert_error (error, GCK_ERROR, CKR_FUNCTION_FAILED);
+	g_assert (error->message);
+	g_clear_error (&error);
+
+	g_object_unref (cert);
+}
+
+TESTING_TEST (pkcs11_lookup_certificate_issuer_fail_async)
+{
+	GAsyncResult *result = NULL;
+	GcrCertificate *cert, *issuer;
+	GError *error = NULL;
+
+	cert = gcr_simple_certificate_new_static (cert_data, n_cert_data);
+	g_assert (cert);
+
+	/* Make the lookup fail */
+	funcs.C_GetAttributeValue = gck_mock_fail_C_GetAttributeValue;
+
+	/* Should be self-signed, so should find itself (added in setup) */
+	gcr_pkcs11_certificate_lookup_issuer_async (cert, NULL, fetch_async_result, &result);
+	testing_wait_until (500);
+	g_assert (result);
+	issuer = gcr_pkcs11_certificate_lookup_issuer_finish (result, &error);
+	g_assert (issuer == NULL);
+	g_assert_error (error, GCK_ERROR, CKR_FUNCTION_FAILED);
+	g_assert (error->message);
+	g_clear_error (&error);
+	g_object_unref (result);
+	result = NULL;
+
+	g_object_unref (cert);
+}



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