[glib-networking/tls-database: 5/7] pkcs11: Initial implementation of PKCS#11 GTlsDatabase functionality.
- From: Stefan Walter <stefw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib-networking/tls-database: 5/7] pkcs11: Initial implementation of PKCS#11 GTlsDatabase functionality.
- Date: Tue, 28 Dec 2010 02:54:44 +0000 (UTC)
commit def9df9da064736cd1443e5ebc57d8e3e58c8707
Author: Stef Walter <stefw collabora co uk>
Date: Mon Dec 27 17:24:46 2010 -0600
pkcs11: Initial implementation of PKCS#11 GTlsDatabase functionality.
* PKCS#11 URI parser.
* GPkcs11Slot object for each slot.
* Code for loading pkcs11 modules and searching for objects.
tls/gnutls/Makefile.am | 8 +-
tls/gnutls/gtlspkcs11database-gnutls.c | 506 ++++++++++++++++++++++++++++++++
tls/gnutls/gtlspkcs11database-gnutls.h | 52 ++++
tls/pkcs11/Makefile.am | 4 +
tls/pkcs11/gpkcs11array.c | 5 +-
tls/pkcs11/gpkcs11array.h | 5 +-
tls/pkcs11/gpkcs11slot.c | 402 +++++++++++++++++++++++++
tls/pkcs11/gpkcs11slot.h | 76 +++++
tls/pkcs11/gpkcs11uri.c | 189 ++++++++++++
tls/pkcs11/gpkcs11uri.h | 36 +++
tls/pkcs11/gpkcs11util.h | 41 +++
tls/pkcs11/pkcs11-trust-assertions.h | 56 ++++
12 files changed, 1377 insertions(+), 3 deletions(-)
---
diff --git a/tls/gnutls/Makefile.am b/tls/gnutls/Makefile.am
index f9f1965..268fc0b 100644
--- a/tls/gnutls/Makefile.am
+++ b/tls/gnutls/Makefile.am
@@ -36,6 +36,8 @@ libgiognutls_la_SOURCES = \
gtlsinputstream-gnutls.h \
gtlsoutputstream-gnutls.c \
gtlsoutputstream-gnutls.h \
+ gtlspkcs11database-gnutls.c \
+ gtlspkcs11database-gnutls.h \
gtlsserverconnection-gnutls.c \
gtlsserverconnection-gnutls.h \
$(NULL)
@@ -48,10 +50,14 @@ libgiognutls_la_CFLAGS = \
$(LIBGNUTLS_CFLAGS) \
$(LIBGCRYPT_CFLAGS) \
-DGIO_MODULE_DIR=\"$(GIO_MODULE_DIR)\" \
- -DG_DISABLE_DEPRECATED
+ -DG_DISABLE_DEPRECATED \
+ -I$(top_srcdir)/tls/ \
+ -DPKCS11_REGISTRY_DIR=\"$(libdir)/pkcs11\" \
+ $(NULL)
libgiognutls_la_LDFLAGS = $(module_flags)
libgiognutls_la_LIBADD = \
+ $(top_srcdir)/tls/pkcs11/libgiopkcs11.la \
$(GLIB_LIBS) \
$(GNUTLS_LIBS) \
$(LIBGCRYPT_LIBS) \
diff --git a/tls/gnutls/gtlspkcs11database-gnutls.c b/tls/gnutls/gtlspkcs11database-gnutls.c
new file mode 100644
index 0000000..b60a9a2
--- /dev/null
+++ b/tls/gnutls/gtlspkcs11database-gnutls.c
@@ -0,0 +1,506 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright © 2010 Collabora, Ltd
+ *
+ * This library 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 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., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Stef Walter <stefw collabora co uk>
+ */
+
+#include "config.h"
+
+#include "gtlspkcs11database-gnutls.h"
+
+#include <gio/gio.h>
+#include <glib/gi18n-lib.h>
+#include <gnutls/x509.h>
+
+#include "pkcs11/gpkcs11slot.h"
+#include "pkcs11/gpkcs11util.h"
+#include "pkcs11/pkcs11.h"
+#include "pkcs11/pkcs11-trust-assertions.h"
+
+static void g_tls_pkcs11_database_gnutls_initable_iface_init (GInitableIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GTlsPkcs11DatabaseGnutls, g_tls_pkcs11_database_gnutls,
+ G_TYPE_TLS_DATABASE_GNUTLS,
+ G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
+ g_tls_pkcs11_database_gnutls_initable_iface_init));
+
+struct _GTlsPkcs11DatabaseGnutlsPrivate
+{
+ /* no changes after construction */
+ GList *pkcs11_slots;
+ GList *modules;
+ GList *initialized;
+};
+
+static CK_RV
+create_mutex (void **mutex)
+{
+ if (!mutex)
+ return CKR_ARGUMENTS_BAD;
+
+ if (!g_thread_supported ())
+ {
+ g_warning ("cannot create pkcs11 mutex, threading has not been initialized");
+ return CKR_GENERAL_ERROR;
+ }
+
+ *mutex = g_mutex_new ();
+ return CKR_OK;
+}
+
+static CK_RV
+destroy_mutex (void *mutex)
+{
+ if (!mutex)
+ return CKR_MUTEX_BAD;
+ g_mutex_free ((GMutex*)mutex);
+ return CKR_OK;
+}
+
+static CK_RV
+lock_mutex (void *mutex)
+{
+ if (!mutex)
+ return CKR_MUTEX_BAD;
+ g_mutex_lock ((GMutex*)mutex);
+ return CKR_OK;
+}
+
+static CK_RV
+unlock_mutex (void *mutex)
+{
+ if (!mutex)
+ return CKR_MUTEX_BAD;
+ g_mutex_unlock ((GMutex*)mutex);
+ return CKR_OK;
+}
+
+static gchar**
+list_registered_pkcs11_module_paths (const gchar *directory, GError **error)
+{
+ const gchar *name;
+ GError *err = NULL;
+ GArray *paths;
+ GDir *dir;
+ gchar *path;
+
+ paths = g_array_new (TRUE, TRUE, sizeof (gchar*));
+ dir = g_dir_open (directory, 0, &err);
+
+ if (dir == NULL)
+ {
+ if (g_error_matches (err, G_FILE_ERROR, G_FILE_ERROR_NOENT) ||
+ g_error_matches (err, G_FILE_ERROR, G_FILE_ERROR_NOTDIR))
+ {
+ g_clear_error (&err);
+ return (gchar**)g_array_free (paths, FALSE);
+ }
+ else
+ {
+ g_array_free (paths, TRUE);
+ g_propagate_error (error, err);
+ return NULL;
+ }
+ }
+
+ for (;;)
+ {
+ name = g_dir_read_name (dir);
+ if (!name)
+ break;
+
+ /* libtool can bite my shiny metal ass */
+ if (g_str_has_suffix (name, ".la"))
+ continue;
+
+ path = g_build_filename (directory, name, NULL);
+ if (g_file_test (path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))
+ g_array_append_val (paths, path);
+ else
+ g_free (path);
+ }
+
+ g_dir_close (dir);
+
+ return (gchar**)g_array_free (paths, FALSE);
+}
+
+static CK_FUNCTION_LIST_PTR
+load_and_initialize_module (GTlsPkcs11DatabaseGnutls *self,
+ const gchar *path,
+ GError **error)
+{
+ CK_C_GetFunctionList get_function_list;
+ CK_C_INITIALIZE_ARGS init_args;
+ CK_FUNCTION_LIST_PTR funcs;
+ GModule *module;
+ CK_RV rv;
+
+ /* Load the actual module */
+ module = g_module_open (path, 0);
+ if (!module)
+ {
+ g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
+ "Error loading PKCS#11 module: %s", g_module_error ());
+ return NULL;
+ }
+
+ /* Get the entry point */
+ if (!g_module_symbol (module, "C_GetFunctionList", (void**)&get_function_list))
+ {
+ g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
+ "Invalid PKCS#11 module: %s", g_module_error ());
+ g_module_close (module);
+ return NULL;
+ }
+
+ /* Get the function list */
+ rv = (get_function_list) (&funcs);
+ if (rv != CKR_OK)
+ {
+ g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
+ "Couldn't get PKCS#11 function list: %s",
+ g_pkcs11_rv_to_message (rv));
+ g_module_close (module);
+ return NULL;
+ }
+
+ memset (&init_args, 0, sizeof (init_args));
+ init_args.flags = CKF_OS_LOCKING_OK;
+ init_args.CreateMutex = create_mutex;
+ init_args.DestroyMutex = destroy_mutex;
+ init_args.LockMutex = lock_mutex;
+ init_args.UnlockMutex = unlock_mutex;
+ init_args.pReserved = NULL;
+
+ /* Now initialize the module */
+ rv = (funcs->C_Initialize) (&init_args);
+ if (rv == CKR_OK)
+ self->priv->initialized = g_list_append (self->priv->initialized, funcs);
+ if (rv == CKR_CRYPTOKI_ALREADY_INITIALIZED)
+ rv = CKR_OK;
+
+ if (rv == CKR_OK)
+ {
+ self->priv->modules = g_list_append (self->priv->modules, module);
+ return funcs;
+ }
+ else
+ {
+ g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
+ "Couldn't initialize PKCS#11 module: %s",
+ g_pkcs11_rv_to_message (rv));
+ g_module_close (module);
+ return NULL;
+ }
+}
+
+static gboolean
+enumerate_and_setup_slots (GTlsPkcs11DatabaseGnutls *self,
+ CK_FUNCTION_LIST_PTR funcs,
+ GError **error)
+{
+ CK_ULONG i, count = 0;
+ CK_SLOT_ID *list;
+ GPkcs11Slot *slot;
+ CK_RV rv;
+
+ rv = (funcs->C_GetSlotList) (CK_FALSE, NULL, &count);
+ if (rv != CKR_OK)
+ {
+ g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
+ "Couldn't load list of slots in PKCS#11 module: %s",
+ g_pkcs11_rv_to_message (rv));
+ return FALSE;
+ }
+
+ if (count == 0)
+ return TRUE;
+
+ list = g_new0 (CK_SLOT_ID, count);
+ rv = (funcs->C_GetSlotList) (CK_FALSE, list, &count);
+ if (rv != CKR_OK)
+ {
+ g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
+ "Couldn't load list of slots in PKCS#11 module: %s",
+ g_pkcs11_rv_to_message (rv));
+ g_free (list);
+ return FALSE;
+ }
+
+ for (i = 0; i < count; ++i)
+ {
+ slot = g_object_new (G_TYPE_PKCS11_SLOT,
+ "slot-id", list[i],
+ "module", funcs,
+ NULL);
+ self->priv->pkcs11_slots = g_list_append (self->priv->pkcs11_slots, slot);
+ }
+
+ return TRUE;
+}
+
+static gboolean
+find_objects_on_all_slots (GTlsPkcs11DatabaseGnutls *self,
+ GPkcs11Array *match,
+ CK_ATTRIBUTE_TYPE *attr_types,
+ guint attr_types_length,
+ GPkcs11SlotFindFunc callback,
+ gpointer user_data,
+ GError **error)
+{
+ GList *l;
+ GPkcs11SlotFindStatus status;
+
+ for (l = self->priv->pkcs11_slots; l; l = g_list_next (l))
+ {
+ status = g_pkcs11_slot_find_objects (l->data, match, attr_types,
+ attr_types_length, callback,
+ user_data, error);
+ if (status != G_PKCS11_SLOT_FIND_COMPLETED)
+ break;
+ }
+
+ return status != G_PKCS11_SLOT_FIND_FAILED;
+}
+
+static gboolean
+find_if_any_exist (GPkcs11Slot *slot,
+ CK_OBJECT_HANDLE object,
+ GPkcs11Array *attributes,
+ gpointer user_data)
+{
+ gboolean *found = (gboolean*)user_data;
+ *found = TRUE;
+ return TRUE; /* stop iteration */
+}
+
+static gboolean
+find_first_certificate (GPkcs11Slot *slot,
+ CK_OBJECT_HANDLE object,
+ GPkcs11Array *attributes,
+ gpointer user_data)
+{
+ GTlsCertificate **issuer = (GTlsCertificate**)user_data;
+ const CK_ATTRIBUTE *attr;
+ gnutls_datum_t datum;
+
+ attr = g_pkcs11_array_find_valid (attributes, CKA_VALUE);
+ if (attr == NULL)
+ return FALSE; /* continue */
+
+ datum.data = attr->pValue;
+ datum.size = attr->ulValueLen;
+
+ *issuer = g_tls_certificate_gnutls_new (&datum, NULL);
+ return TRUE; /* stop iteration */
+}
+
+static const gchar*
+calculate_peer_for_identity (GSocketConnectable *identity)
+{
+ const char *peer;
+
+ if (G_IS_NETWORK_ADDRESS (identity))
+ peer = g_network_address_get_hostname (G_NETWORK_ADDRESS (identity));
+ else if (G_IS_NETWORK_SERVICE (identity))
+ peer = g_network_service_get_domain (G_NETWORK_SERVICE (identity));
+ else
+ peer = NULL;
+
+ return peer;
+}
+
+static void
+g_tls_pkcs11_database_gnutls_finalize (GObject *object)
+{
+ GTlsPkcs11DatabaseGnutls *self = G_TLS_PKCS11_DATABASE_GNUTLS (object);
+ GList *l;
+
+ for (l = self->priv->pkcs11_slots; l; l = g_list_next (l))
+ g_object_unref (l->data);
+ g_list_free (self->priv->pkcs11_slots);
+ self->priv->pkcs11_slots = NULL;
+
+ G_OBJECT_CLASS (g_tls_pkcs11_database_gnutls_parent_class)->finalize (object);
+}
+
+static void
+g_tls_pkcs11_database_gnutls_init (GTlsPkcs11DatabaseGnutls *self)
+{
+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
+ G_TYPE_TLS_PKCS11_DATABASE_GNUTLS,
+ GTlsPkcs11DatabaseGnutlsPrivate);
+}
+
+static gboolean
+g_tls_pkcs11_database_gnutls_lookup_assertion (GTlsDatabaseGnutls *database,
+ GTlsCertificateGnutls *certificate,
+ GTlsDatabaseGnutlsAssertion assertion,
+ GSocketConnectable *identity,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GTlsPkcs11DatabaseGnutls *self = G_TLS_PKCS11_DATABASE_GNUTLS (database);
+ GByteArray *der = NULL;
+ gboolean found, ready;
+ GPkcs11Array *match;
+ const gchar *peer;
+
+ g_return_val_if_fail (G_IS_TLS_CERTIFICATE_GNUTLS (certificate), FALSE);
+ g_return_val_if_fail (!identity || G_IS_SOCKET_CONNECTABLE (identity), FALSE);
+ g_return_val_if_fail (!error || !*error, FALSE);
+
+ ready = FALSE;
+ found = FALSE;
+ match = g_pkcs11_array_new ();
+
+ if (assertion == G_TLS_DATABASE_GNUTLS_ANCHORED_CERTIFICATE ||
+ assertion == G_TLS_DATABASE_GNUTLS_PINNED_CERTIFICATE)
+ {
+ g_object_get (certificate, "certificate", &der, NULL);
+ g_return_val_if_fail (der, FALSE);
+ g_pkcs11_array_add_value (match, CKA_X_CERTIFICATE_VALUE, der->data, der->len);
+ g_byte_array_unref (der);
+
+ /* TLS Server Authentication */
+ g_pkcs11_array_add_value (match, CKA_X_PURPOSE, "1.3.6.1.5.5.7.3.1", -1);
+
+ if (assertion == G_TLS_DATABASE_GNUTLS_ANCHORED_CERTIFICATE)
+ {
+ g_pkcs11_array_add_ulong (match, CKA_X_ASSERTION_TYPE, CKT_X_ANCHORED_CERTIFICATE);
+ ready = TRUE;
+ }
+ else if (assertion == G_TLS_DATABASE_GNUTLS_PINNED_CERTIFICATE)
+ {
+ g_pkcs11_array_add_ulong (match, CKA_X_ASSERTION_TYPE, CKT_X_PINNED_CERTIFICATE);
+ peer = calculate_peer_for_identity (identity);
+ if (peer)
+ {
+ g_pkcs11_array_add_value (match, CKA_X_PEER, peer, -1);
+ ready = TRUE;
+ }
+ }
+ }
+
+ if (ready)
+ find_objects_on_all_slots (self, match, NULL, 0, find_if_any_exist,
+ &found, error);
+
+ g_pkcs11_array_unref (match);
+ return found;
+}
+
+static GTlsCertificate*
+g_tls_pkcs11_database_gnutls_lookup_issuer (GTlsDatabase *database,
+ GTlsCertificate *certificate,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GTlsPkcs11DatabaseGnutls *self = G_TLS_PKCS11_DATABASE_GNUTLS (database);
+ GTlsCertificate *issuer = NULL;
+ GPkcs11Array *match = NULL;
+ CK_ATTRIBUTE_TYPE attr_type = CKA_VALUE;
+ gnutls_x509_crt_t cert;
+ gnutls_datum_t dn;
+ int gerr;
+
+ g_return_val_if_fail (!error || !*error, NULL);
+ g_return_val_if_fail (G_IS_TLS_CERTIFICATE_GNUTLS (certificate), NULL);
+
+ /* Dig out the issuer of this certificate */
+ cert = g_tls_certificate_gnutls_get_cert (G_TLS_CERTIFICATE_GNUTLS (certificate));
+ gerr = gnutls_x509_crt_get_raw_issuer_dn (cert, &dn);
+ if (gerr < 0)
+ {
+ g_warning ("failed to get issuer of certificate: %s", gnutls_strerror (gerr));
+ return NULL;
+ }
+
+ match = g_pkcs11_array_new ();
+ g_pkcs11_array_add_value (match, CKA_SUBJECT, dn.data, dn.size);
+ gnutls_free (dn.data);
+
+ find_objects_on_all_slots (self, match, &attr_type, 1,
+ find_first_certificate, &issuer, error);
+
+ g_pkcs11_array_unref (match);
+ return issuer;
+}
+
+static void
+g_tls_pkcs11_database_gnutls_class_init (GTlsPkcs11DatabaseGnutlsClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GTlsDatabaseClass *database_class = G_TLS_DATABASE_CLASS (klass);
+ GTlsDatabaseGnutlsClass *gnutls_class = G_TLS_DATABASE_GNUTLS_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (GTlsPkcs11DatabaseGnutlsPrivate));
+
+ gobject_class->finalize = g_tls_pkcs11_database_gnutls_finalize;
+
+ database_class->lookup_issuer = g_tls_pkcs11_database_gnutls_lookup_issuer;
+ gnutls_class->lookup_assertion = g_tls_pkcs11_database_gnutls_lookup_assertion;
+}
+
+static gboolean
+g_tls_pkcs11_database_gnutls_initable_init (GInitable *initable,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GTlsPkcs11DatabaseGnutls *self = G_TLS_PKCS11_DATABASE_GNUTLS (initable);
+ CK_FUNCTION_LIST_PTR funcs;
+ gchar **paths, **path;
+ GError *err = NULL;
+ gboolean ret = FALSE;
+
+ g_return_val_if_fail (!error || !*error, FALSE);
+
+ paths = list_registered_pkcs11_module_paths (PKCS11_REGISTRY_DIR, &err);
+ if (!paths)
+ {
+ if (err)
+ {
+ g_propagate_error (error, err);
+ return FALSE;
+ }
+ return TRUE;
+ }
+
+ /* TODO: Partial success or failure? */
+
+ for (path = paths; *path; ++path)
+ {
+ funcs = load_and_initialize_module (self, *path, error);
+ if (funcs != NULL)
+ {
+ if (enumerate_and_setup_slots (self, funcs, error))
+ ret = TRUE;
+ }
+ }
+
+ g_strfreev (paths);
+ return ret;
+}
+
+static void
+g_tls_pkcs11_database_gnutls_initable_iface_init (GInitableIface *iface)
+{
+ iface->init = g_tls_pkcs11_database_gnutls_initable_init;
+}
diff --git a/tls/gnutls/gtlspkcs11database-gnutls.h b/tls/gnutls/gtlspkcs11database-gnutls.h
new file mode 100644
index 0000000..bc3771c
--- /dev/null
+++ b/tls/gnutls/gtlspkcs11database-gnutls.h
@@ -0,0 +1,52 @@
+/* GIO - GLib Certificate, Output and Gnutlsing Library
+ *
+ * Copyright © 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 of the licence or (at
+ * your option) any later version.
+ *
+ * See the included COPYING file for more information.
+ *
+ * Author: Stef Walter <stefw collabora co uk>
+ */
+
+#ifndef __G_TLS_PKCS11_DATABASE_GNUTLS_H__
+#define __G_TLS_PKCS11_DATABASE_GNUTLS_H__
+
+#include <gio/gio.h>
+
+#include "gtlsdatabase-gnutls.h"
+
+G_BEGIN_DECLS
+
+#define G_TYPE_TLS_PKCS11_DATABASE_GNUTLS (g_tls_pkcs11_database_gnutls_get_type ())
+#define G_TLS_PKCS11_DATABASE_GNUTLS(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), G_TYPE_TLS_PKCS11_DATABASE_GNUTLS, GTlsPkcs11DatabaseGnutls))
+#define G_TLS_PKCS11_DATABASE_GNUTLS_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), G_TYPE_TLS_PKCS11_DATABASE_GNUTLS, GTlsPkcs11DatabaseGnutlsClass))
+#define G_IS_TLS_PKCS11_DATABASE_GNUTLS(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), G_TYPE_TLS_PKCS11_DATABASE_GNUTLS))
+#define G_IS_TLS_PKCS11_DATABASE_GNUTLS_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), G_TYPE_TLS_PKCS11_DATABASE_GNUTLS))
+#define G_TLS_PKCS11_DATABASE_GNUTLS_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), G_TYPE_TLS_PKCS11_DATABASE_GNUTLS, GTlsPkcs11DatabaseGnutlsClass))
+
+typedef struct _GTlsPkcs11DatabaseGnutlsPrivate GTlsPkcs11DatabaseGnutlsPrivate;
+typedef struct _GTlsPkcs11DatabaseGnutlsClass GTlsPkcs11DatabaseGnutlsClass;
+typedef struct _GTlsPkcs11DatabaseGnutls GTlsPkcs11DatabaseGnutls;
+
+struct _GTlsPkcs11DatabaseGnutlsClass
+{
+ GTlsDatabaseGnutlsClass parent_class;
+};
+
+struct _GTlsPkcs11DatabaseGnutls
+{
+ GTlsDatabaseGnutls parent_instance;
+ GTlsPkcs11DatabaseGnutlsPrivate *priv;
+};
+
+GType g_tls_pkcs11_database_gnutls_get_type (void) G_GNUC_CONST;
+
+GTlsDatabase* g_tls_pkcs11_database_gnutls_new (void);
+
+G_END_DECLS
+
+#endif /* __G_TLS_PKCS11_DATABASE_GNUTLS_H___ */
diff --git a/tls/pkcs11/Makefile.am b/tls/pkcs11/Makefile.am
index 802fc15..be8a479 100644
--- a/tls/pkcs11/Makefile.am
+++ b/tls/pkcs11/Makefile.am
@@ -8,6 +8,10 @@ noinst_LTLIBRARIES = \
libgiopkcs11_la_SOURCES = \
gpkcs11array.c \
gpkcs11array.h \
+ gpkcs11slot.c \
+ gpkcs11slot.h \
+ gpkcs11uri.c \
+ gpkcs11uri.h \
pkcs11.h \
$(NULL)
diff --git a/tls/pkcs11/gpkcs11array.c b/tls/pkcs11/gpkcs11array.c
index 2b84e4c..0ad2e0e 100644
--- a/tls/pkcs11/gpkcs11array.c
+++ b/tls/pkcs11/gpkcs11array.c
@@ -70,12 +70,15 @@ void
g_pkcs11_array_add_value (GPkcs11Array *array,
CK_ATTRIBUTE_TYPE type,
gconstpointer value,
- gsize length)
+ gssize length)
{
CK_ATTRIBUTE attr;
g_return_if_fail (array);
+ if (length < 0)
+ length = strlen (value);
+
attr.type = type;
attr.pValue = (gpointer)value;
attr.ulValueLen = length;
diff --git a/tls/pkcs11/gpkcs11array.h b/tls/pkcs11/gpkcs11array.h
index ef6141c..8ff6a9e 100644
--- a/tls/pkcs11/gpkcs11array.h
+++ b/tls/pkcs11/gpkcs11array.h
@@ -44,7 +44,7 @@ void g_pkcs11_array_add (GPkcs11Array
void g_pkcs11_array_add_value (GPkcs11Array *array,
CK_ATTRIBUTE_TYPE type,
gconstpointer value,
- gsize length);
+ gssize length);
void g_pkcs11_array_add_boolean (GPkcs11Array *array,
CK_ATTRIBUTE_TYPE type,
@@ -57,6 +57,9 @@ void g_pkcs11_array_add_ulong (GPkcs11Array
const CK_ATTRIBUTE* g_pkcs11_array_find (GPkcs11Array *array,
CK_ATTRIBUTE_TYPE type);
+const CK_ATTRIBUTE* g_pkcs11_array_find_valid (GPkcs11Array *array,
+ CK_ATTRIBUTE_TYPE type);
+
gboolean g_pkcs11_array_find_boolean (GPkcs11Array *array,
CK_ATTRIBUTE_TYPE type,
gboolean *value);
diff --git a/tls/pkcs11/gpkcs11slot.c b/tls/pkcs11/gpkcs11slot.c
new file mode 100644
index 0000000..43e7cc1
--- /dev/null
+++ b/tls/pkcs11/gpkcs11slot.c
@@ -0,0 +1,402 @@
+/* GIO - Small GLib wrapper of PKCS#11 for use in GTls
+ *
+ * Copyright © 2010 Collabora, Ltd
+ *
+ * This library 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 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., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Stef Walter <stefw collabora co uk>
+ */
+
+#include "config.h"
+
+#include "gpkcs11slot.h"
+
+#include "gpkcs11array.h"
+#include "gpkcs11util.h"
+
+#include <glib/gi18n.h>
+
+enum {
+ PROP_0,
+ PROP_MODULE,
+ PROP_SLOT_ID
+};
+
+struct _GPkcs11SlotPrivate
+{
+ /* read-only after construct */
+ CK_FUNCTION_LIST_PTR module;
+ CK_SLOT_ID slot_id;
+
+ /* protected by mutex */
+ GMutex *mutex;
+ CK_SESSION_HANDLE last_session;
+};
+
+G_DEFINE_TYPE (GPkcs11Slot, g_pkcs11_slot, G_TYPE_OBJECT);
+
+static CK_SESSION_HANDLE
+session_checkout_or_open (GPkcs11Slot *self,
+ GError **error)
+{
+ CK_SESSION_HANDLE session = 0;
+ CK_RV rv;
+
+ g_mutex_lock (self->priv->mutex);
+
+ if (self->priv->last_session)
+ {
+ session = self->priv->last_session;
+ self->priv->last_session = 0;
+ }
+
+ g_mutex_lock (self->priv->mutex);
+
+ if (session)
+ return session;
+
+ rv = (self->priv->module->C_OpenSession) (self->priv->slot_id, CKF_SERIAL_SESSION,
+ NULL, NULL, &session);
+ if (rv != CKR_OK)
+ {
+ g_pkcs11_util_propagate_error (error, rv);
+ return 0;
+ }
+
+ return session;
+}
+
+static void
+session_close (GPkcs11Slot *self,
+ CK_SESSION_HANDLE session)
+{
+ CK_RV rv;
+
+ g_assert (session != 0);
+
+ rv = (self->priv->module->C_CloseSession) (session);
+ if (rv != CKR_OK)
+ g_warning ("couldn't close pkcs11 session: %s",
+ g_pkcs11_util_rv_to_message (rv));
+}
+
+static void
+session_checkin_or_close (GPkcs11Slot *self,
+ CK_SESSION_HANDLE session)
+{
+ g_assert (session != 0);
+
+ g_mutex_lock (self->priv->mutex);
+
+ if (self->priv->last_session == 0)
+ {
+ self->priv->last_session = session;
+ session = 0;
+ }
+
+ g_mutex_lock (self->priv->mutex);
+
+ if (session != 0)
+ session_close (self, session);
+}
+
+static GPkcs11Array*
+retrieve_object_attributes (GPkcs11Slot *self,
+ CK_SESSION_HANDLE session,
+ CK_OBJECT_HANDLE object,
+ CK_ATTRIBUTE_TYPE *attr_types,
+ guint attr_types_length)
+{
+ GPkcs11Array *result;
+ CK_ATTRIBUTE_PTR attr;
+ CK_ATTRIBUTE blank;
+ CK_RV rv;
+ guint i;
+
+ result = g_pkcs11_array_new ();
+ memset (&blank, 0, sizeof (blank));
+ for (i = 0; i < attr_types_length; ++i)
+ {
+ blank.type = attr_types[i];
+ g_pkcs11_array_add (result, &blank);
+ }
+
+ /* Get all the required buffer sizes */
+ rv = (self->priv->module->C_GetAttributeValue) (session, object,
+ result->attrs, result->len);
+ if (rv != CKR_OK &&
+ rv != CKR_ATTRIBUTE_SENSITIVE &&
+ rv != CKR_ATTRIBUTE_TYPE_INVALID)
+ {
+ g_message ("couldn't read pkcs11 object attributes: %s",
+ g_pkcs11_util_rv_to_message (rv));
+ g_pkcs11_array_unref (result);
+ return NULL;
+ }
+
+ /* Now allocate memory for them all */
+ for (i = 0; i < attr_types_length; ++i)
+ {
+ attr = &g_pkcs11_array_index (result, i);
+ if (attr->ulValueLen != (CK_ULONG)-1 && attr->ulValueLen)
+ attr->pValue = g_malloc0 (attr->ulValueLen);
+ }
+
+ /* And finally get all the values */
+ rv = (self->priv->module->C_GetAttributeValue) (session, object,
+ result->attrs, result->len);
+ if (rv != CKR_OK &&
+ rv != CKR_ATTRIBUTE_SENSITIVE &&
+ rv != CKR_ATTRIBUTE_TYPE_INVALID &&
+ rv != CKR_BUFFER_TOO_SMALL)
+ {
+ g_message ("couldn't retrieve pkcs11 object attributes: %s",
+ g_pkcs11_util_rv_to_message (rv));
+ g_pkcs11_array_unref (result);
+ return NULL;
+ }
+
+ return result;
+}
+
+static void
+g_pkcs11_slot_init (GPkcs11Slot *self)
+{
+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
+ G_TYPE_PKCS11_SLOT,
+ GPkcs11SlotPrivate);
+ self->priv->mutex = g_mutex_new ();
+}
+
+static void
+g_pkcs11_slot_dispose (GObject *object)
+{
+ GPkcs11Slot *self = G_PKCS11_SLOT (object);
+ CK_SESSION_HANDLE session = 0;
+
+ g_mutex_lock (self->priv->mutex);
+
+ session = self->priv->last_session;
+ self->priv->last_session = 0;
+
+ g_mutex_unlock (self->priv->mutex);
+
+ if (session)
+ session_close (self, session);
+
+ G_OBJECT_CLASS (g_pkcs11_slot_parent_class)->dispose (object);
+}
+
+static void
+g_pkcs11_slot_finalize (GObject *object)
+{
+ GPkcs11Slot *self = G_PKCS11_SLOT (object);
+
+ g_assert (self->priv->last_session == 0);
+ g_mutex_free (self->priv->mutex);
+ self->priv->mutex = NULL;
+
+ G_OBJECT_CLASS (g_pkcs11_slot_parent_class)->finalize (object);
+}
+
+static void
+g_pkcs11_slot_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GPkcs11Slot *self = G_PKCS11_SLOT (object);
+
+ switch (prop_id)
+ {
+ case PROP_MODULE:
+ g_value_set_pointer (value, self->priv->module);
+ break;
+
+ case PROP_SLOT_ID:
+ g_value_set_ulong (value, self->priv->slot_id);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+g_pkcs11_slot_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GPkcs11Slot *self = G_PKCS11_SLOT (object);
+
+ switch (prop_id)
+ {
+ case PROP_MODULE:
+ self->priv->module = g_value_get_pointer (value);
+ g_assert (self->priv->module);
+ break;
+
+ case PROP_SLOT_ID:
+ self->priv->slot_id = g_value_get_ulong (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+g_pkcs11_slot_class_init (GPkcs11SlotClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (GPkcs11SlotPrivate));
+
+ gobject_class->get_property = g_pkcs11_slot_get_property;
+ gobject_class->set_property = g_pkcs11_slot_set_property;
+ gobject_class->dispose = g_pkcs11_slot_dispose;
+ gobject_class->finalize = g_pkcs11_slot_finalize;
+
+ g_type_class_add_private (klass, sizeof (GPkcs11SlotPrivate));
+
+ g_object_class_install_property (gobject_class, PROP_MODULE,
+ g_param_spec_pointer ("module",
+ N_("Module"),
+ N_("PKCS#11 Module Pointer"),
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (gobject_class, PROP_SLOT_ID,
+ g_param_spec_ulong ("slot-id",
+ N_("Slot ID"),
+ N_("PKCS#11 Slot Identifier"),
+ 0,
+ G_MAXULONG,
+ G_MAXULONG,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS));
+}
+
+gboolean
+g_pkcs11_slot_login (GPkcs11Slot *self,
+ const guchar *pin,
+ gsize pin_length,
+ GError **error)
+{
+ CK_SESSION_HANDLE session;
+ GError *err = NULL;
+ CK_RV rv;
+
+ g_return_val_if_fail (G_IS_PKCS11_SLOT (self), FALSE);
+ g_return_val_if_fail (!error || !*error, FALSE);
+
+ session = session_checkout_or_open (self, &err);
+ if (err != NULL)
+ {
+ g_propagate_error (error, err);
+ return FALSE;
+ }
+
+ rv = (self->priv->module->C_Login) (session, CKU_USER,
+ (CK_BYTE_PTR)pin, pin_length);
+
+ session_checkin_or_close (self, session);
+
+ if (rv != CKR_OK)
+ {
+ g_pkcs11_util_propagate_error (error, rv);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+GPkcs11SlotFindStatus
+g_pkcs11_slot_find_objects (GPkcs11Slot *self,
+ GPkcs11Array *match,
+ CK_ATTRIBUTE_TYPE *attr_types,
+ guint attr_types_length,
+ GPkcs11SlotFindFunc callback,
+ gpointer user_data,
+ GError **error)
+{
+ GPkcs11SlotFindStatus status = G_PKCS11_SLOT_FIND_COMPLETED;
+ CK_OBJECT_HANDLE objects[256];
+ CK_SESSION_HANDLE session;
+ GPkcs11Array *attrs;
+ GError *err = NULL;
+ gboolean stop = FALSE;
+ CK_ULONG count, i;
+ CK_RV rv;
+
+ g_return_val_if_fail (G_IS_PKCS11_SLOT (self), FALSE);
+ g_return_val_if_fail (match, FALSE);
+ g_return_val_if_fail (callback, FALSE);
+ g_return_val_if_fail (!error || !*error, FALSE);
+
+ session = session_checkout_or_open (self, &err);
+ if (err != NULL)
+ {
+ g_propagate_error (error, err);
+ return G_PKCS11_SLOT_FIND_FAILED;
+ }
+
+ rv = (self->priv->module->C_FindObjectsInit) (session, match->attrs, match->len);
+
+ while (!stop && rv == CKR_OK)
+ {
+ count = 0;
+ rv = (self->priv->module->C_FindObjects) (session, objects,
+ G_N_ELEMENTS (objects), &count);
+ if (rv == CKR_OK)
+ {
+ if (count == 0)
+ break;
+
+ for (i = 0; !stop && i < count; ++i)
+ {
+ if (attr_types_length)
+ attrs = retrieve_object_attributes (self, session, objects[i],
+ attr_types, attr_types_length);
+ else
+ attrs = NULL;
+ stop = (callback) (self, objects[i], attrs, user_data);
+ if (attrs)
+ g_pkcs11_array_unref (attrs);
+ }
+ }
+ }
+
+ if (stop)
+ status = G_PKCS11_SLOT_FIND_STOPPED;
+
+ if (rv != CKR_OK && rv != CKR_TOKEN_NOT_PRESENT)
+ {
+ g_pkcs11_util_propagate_error (error, rv);
+ status = G_PKCS11_SLOT_FIND_FAILED;
+ }
+
+ rv = (self->priv->module->C_FindObjectsFinal) (session);
+ if (rv == CKR_OK)
+ session_close (self, session);
+ else
+ session_checkin_or_close (self, session);
+
+ return status;
+}
diff --git a/tls/pkcs11/gpkcs11slot.h b/tls/pkcs11/gpkcs11slot.h
new file mode 100644
index 0000000..fcc017b
--- /dev/null
+++ b/tls/pkcs11/gpkcs11slot.h
@@ -0,0 +1,76 @@
+/* GIO - Small GLib wrapper of PKCS#11 for use in GTls
+ *
+ * Copyright © 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 of the licence or (at
+ * your option) any later version.
+ *
+ * See the included COPYING file for more information.
+ *
+ * Author: Stef Walter <stefw collabora co uk>
+ */
+
+#ifndef __G_PKCS11_SLOT_H__
+#define __G_PKCS11_SLOT_H__
+
+#include <gio/gio.h>
+
+#include "gpkcs11array.h"
+
+#include "pkcs11.h"
+
+G_BEGIN_DECLS
+
+typedef enum {
+ G_PKCS11_SLOT_FIND_FAILED,
+ G_PKCS11_SLOT_FIND_STOPPED,
+ G_PKCS11_SLOT_FIND_COMPLETED
+} GPkcs11SlotFindStatus;
+
+#define G_TYPE_PKCS11_SLOT (g_pkcs11_slot_get_type ())
+#define G_PKCS11_SLOT(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), G_TYPE_PKCS11_SLOT, GPkcs11Slot))
+#define G_PKCS11_SLOT_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), G_TYPE_PKCS11_SLOT, GPkcs11SlotClass))
+#define G_IS_PKCS11_SLOT(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), G_TYPE_PKCS11_SLOT))
+#define G_IS_PKCS11_SLOT_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), G_TYPE_PKCS11_SLOT))
+#define G_PKCS11_SLOT_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), G_TYPE_PKCS11_SLOT, GPkcs11SlotClass))
+
+typedef struct _GPkcs11SlotPrivate GPkcs11SlotPrivate;
+typedef struct _GPkcs11SlotClass GPkcs11SlotClass;
+typedef struct _GPkcs11Slot GPkcs11Slot;
+
+struct _GPkcs11SlotClass
+{
+ GObjectClass parent_class;
+};
+
+struct _GPkcs11Slot
+{
+ GObject parent_instance;
+ GPkcs11SlotPrivate *priv;
+};
+
+typedef gboolean (*GPkcs11SlotFindFunc) (GPkcs11Slot *slot,
+ CK_OBJECT_HANDLE object,
+ GPkcs11Array *attributes,
+ gpointer user_data);
+
+GType g_pkcs11_slot_get_type (void) G_GNUC_CONST;
+
+gboolean g_pkcs11_slot_login (GPkcs11Slot *self,
+ const guchar* pin,
+ gsize pin_length,
+ GError **error);
+
+GPkcs11SlotFindStatus g_pkcs11_slot_find_objects (GPkcs11Slot *self,
+ GPkcs11Array *match,
+ CK_ATTRIBUTE_TYPE *attr_types,
+ guint attr_types_length,
+ GPkcs11SlotFindFunc callback,
+ gpointer user_data,
+ GError **error);
+
+G_END_DECLS
+
+#endif /* __G_TLS_CERTIFICATE_GNUTLS_H___ */
diff --git a/tls/pkcs11/gpkcs11uri.c b/tls/pkcs11/gpkcs11uri.c
new file mode 100644
index 0000000..2ad8ff5
--- /dev/null
+++ b/tls/pkcs11/gpkcs11uri.c
@@ -0,0 +1,189 @@
+/* GIO - Small GLib wrapper of PKCS#11 for use in GTls
+ *
+ * Copyright © 2010 Collabora, Ltd
+ *
+ * This library 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 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., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Stef Walter <stefw collabora co uk>
+ */
+
+#include "config.h"
+
+#include "gpkcs11uri.h"
+#include "gpkcs11util.h"
+
+#include <glib/gi18n-lib.h>
+
+#include <string.h>
+
+#define URI_PREFIX "pkcs11:"
+#define URI_PREFIX_LENGTH 7
+
+enum {
+ FAILED = -1,
+ NO_MATCH = 0,
+ SUCCESS = 1
+};
+
+static gint
+parse_string_field (const gchar *name,
+ const gchar *start,
+ const gchar *end,
+ CK_INFO *info,
+ CK_TOKEN_INFO *token,
+ GError **error)
+{
+ unsigned char *value;
+ gsize value_length;
+ gchar *string;
+ gsize string_length;
+
+ g_assert (name);
+ g_assert (start);
+ g_assert (end);
+ g_assert (token);
+ g_assert (info);
+
+ if (g_str_equal (name, "model"))
+ {
+ value = token->model;
+ value_length = sizeof (token->model);
+ }
+ else if (g_str_equal (name, "manufacturer"))
+ {
+ value = token->manufacturerID;
+ value_length = sizeof (token->manufacturerID);
+ }
+ else if (g_str_equal (name, "serial"))
+ {
+ value = token->serialNumber;
+ value_length = sizeof (token->serialNumber);
+ }
+ else if (g_str_equal (name, "token"))
+ {
+ value = token->label;
+ value_length = sizeof (token->label);
+ }
+ else if (g_str_equal (name, "library-description"))
+ {
+ value = info->libraryDescription;
+ value_length = sizeof (info->libraryDescription);
+ }
+ else if (g_str_equal (name, "library-manufacturer"))
+ {
+ value = info->manufacturerID;
+ value_length = sizeof (info->manufacturerID);
+ }
+ else
+ {
+ return NO_MATCH;
+ }
+
+ string = g_uri_unescape_segment (start, end, "");
+ if (string == NULL)
+ {
+ g_set_error (error, G_PKCS11_ERROR, G_PKCS11_ERROR_BAD_URI,
+ _("The URI has invalid syntax. The '%s' field encoding is invalid."), name);
+ return FAILED;
+ }
+
+ string_length = strlen (string);
+ if (string_length > value_length)
+ {
+ g_set_error (error, G_PKCS11_ERROR, G_PKCS11_ERROR_BAD_URI,
+ _("The URI has invalid syntax. The '%s' field is too long."), name);
+ g_free (string);
+ return FAILED;
+ }
+
+ /* All the fields are space (!) padded */
+ memset (value, ' ', value_length);
+ memcpy (value, string, string_length);
+ g_free (string);
+ return SUCCESS;
+}
+
+gboolean
+g_pkcs11_uri_parse (const gchar *uri,
+ CK_INFO *library,
+ CK_TOKEN_INFO *token,
+ GError **error)
+{
+ const gchar *spos, *epos;
+ gchar *key = NULL;
+ gboolean ret;
+ gint res;
+
+ g_return_val_if_fail (uri, FALSE);
+ g_return_val_if_fail (library, FALSE);
+ g_return_val_if_fail (token, FALSE);
+ g_return_val_if_fail (!error || !*error, FALSE);
+
+ if (!g_str_has_prefix (uri, URI_PREFIX))
+ {
+ g_set_error_literal (error, G_PKCS11_ERROR, G_PKCS11_ERROR_BAD_URI,
+ _("The URI has does not have the 'pkcs11' scheme."));
+ return FALSE;
+ }
+
+ /* All fields set to zero, including string fields */
+ memset (token, 0, sizeof (CK_TOKEN_INFO));
+ memset (library, 0, sizeof (CK_INFO));
+
+ ret = TRUE;
+ for (;;)
+ {
+ spos = strchr (uri, ';');
+ if (spos == NULL)
+ {
+ spos = uri + strlen (uri);
+ g_assert (*spos == '\0');
+ if (spos == uri)
+ break;
+ }
+
+ epos = strchr (uri, '=');
+ if (epos == NULL || spos == uri || epos == uri || epos >= spos)
+ {
+ g_set_error_literal (error, G_PKCS11_ERROR, G_PKCS11_ERROR_BAD_URI,
+ _("The URI has invalid syntax. It must consist of key=value pairs."));
+ ret = FALSE;
+ break;
+ }
+
+ g_free (key);
+ key = g_strndup (uri, epos - uri);
+ epos++;
+
+ res = parse_string_field (key, epos, spos, library, token, error);
+ if (res == NO_MATCH)
+ {
+ g_message ("Ignoring unsupported field '%s'", key);
+ }
+ else if (res != SUCCESS)
+ {
+ ret = FALSE;
+ break;
+ }
+
+ if (*spos == '\0')
+ break;
+ uri = spos + 1;
+ }
+
+ g_free (key);
+ return ret;
+}
diff --git a/tls/pkcs11/gpkcs11uri.h b/tls/pkcs11/gpkcs11uri.h
new file mode 100644
index 0000000..95f96d0
--- /dev/null
+++ b/tls/pkcs11/gpkcs11uri.h
@@ -0,0 +1,36 @@
+/* GIO - Small GLib wrapper of PKCS#11 for use in GTls
+ *
+ * Copyright © 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 of the licence or (at
+ * your option) any later version.
+ *
+ * See the included COPYING file for more information.
+ *
+ * Author: Stef Walter <stefw collabora co uk>
+ */
+
+#ifndef __G_PKCS11_URI_H__
+#define __G_PKCS11_URI_H__
+
+#include <glib.h>
+
+#include "pkcs11.h"
+
+G_BEGIN_DECLS
+
+gboolean g_pkcs11_uri_parse (const gchar *uri,
+ CK_INFO *library,
+ CK_TOKEN_INFO *token,
+ GError **error);
+
+gboolean g_pkcs11_uri_info_match (CK_INFO *match_library,
+ CK_INFO *library,
+ CK_TOKEN_INFO *match_token,
+ CK_TOKEN_INFO *token);
+
+G_END_DECLS
+
+#endif /* __G_PKCS11_URI_H___ */
diff --git a/tls/pkcs11/gpkcs11util.h b/tls/pkcs11/gpkcs11util.h
new file mode 100644
index 0000000..a7af5f7
--- /dev/null
+++ b/tls/pkcs11/gpkcs11util.h
@@ -0,0 +1,41 @@
+/* GIO - Small GLib wrapper of PKCS#11 for use in GTls
+ *
+ * Copyright © 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 of the licence or (at
+ * your option) any later version.
+ *
+ * See the included COPYING file for more information.
+ *
+ * Author: Stef Walter <stefw collabora co uk>
+ */
+
+#ifndef __G_PKCS11_UTIL_H__
+#define __G_PKCS11_UTIL_H__
+
+#include <glib.h>
+
+#include "pkcs11.h"
+
+G_BEGIN_DECLS
+
+#define G_PKCS11_VENDOR_CODE 0x47000000 /* G000 */
+
+enum {
+ G_PKCS11_ERROR_BAD_URI = (CKR_VENDOR_DEFINED | (G_PKCS11_VENDOR_CODE + 1)),
+};
+
+#define G_PKCS11_ERROR (g_pkcs11_get_error_domain ())
+
+GQuark g_pkcs11_get_error_domain (void) G_GNUC_CONST;
+
+const gchar* g_pkcs11_rv_to_message (CK_RV rv);
+
+void g_pkcs11_propagate_error (GError **error,
+ CK_RV rv);
+
+G_END_DECLS
+
+#endif /* __G_PKCS11_UTIL_H___ */
diff --git a/tls/pkcs11/pkcs11-trust-assertions.h b/tls/pkcs11/pkcs11-trust-assertions.h
new file mode 100644
index 0000000..decfd32
--- /dev/null
+++ b/tls/pkcs11/pkcs11-trust-assertions.h
@@ -0,0 +1,56 @@
+/*
+ * pkcs11x.h
+ * Copyright 2010 Collabora, Ltd
+ *
+ * This file is free software; as a special exception the author gives
+ * unlimited permission to copy and/or distribute it, with or without
+ * modifications, as long as this notice is preserved.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY, to the extent permitted by law; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.
+ */
+
+/*
+ * The latest version of this file is at:
+ *
+ * git://thewalter.net/git/pkcs11-trust-assertions
+ *
+ * or viewable on the web at:
+ *
+ * http://thewalter.net/git/cgit.cgi/pkcs11-trust-assertions/tree/pkcs11-trust-assertions.h
+ *
+ */
+
+#ifndef PKCS11_TRUST_ASSERTIONS_H
+#define PKCS11_TRUST_ASSERTIONS_H
+
+#include "pkcs11.h"
+
+#define CKA_XDG (CKA_VENDOR_DEFINED | 0x58444700UL /* XDG0 */ )
+#define CKO_XDG (CKA_VENDOR_DEFINED | 0x58444700UL /* XDG0 */ )
+
+/* -------------------------------------------------------------------
+ * TRUST ASSERTIONS
+ */
+
+#define CKO_X_TRUST_ASSERTION (CKO_XDG + 100)
+
+#define CKA_X_ASSERTION_TYPE (CKA_XDG + 1)
+
+#define CKA_X_CERTIFICATE_VALUE (CKA_XDG + 2)
+
+#define CKA_X_PURPOSE (CKA_XDG + 3)
+
+#define CKA_X_PEER (CKA_XDG + 4)
+
+typedef CK_ULONG CK_X_ASSERTION_TYPE;
+
+#define CKT_X_UNTRUSTED_CERTIFICATE 1UL
+
+#define CKT_X_PINNED_CERTIFICATE 2UL
+
+#define CKT_X_ANCHORED_CERTIFICATE 3UL
+
+#endif /* PKCS11_TRUST_ASSERTIONS_H */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]