[gnome-keyring: 4/10] [gck] Add support for transient PKCS#11 objects.
- From: Stefan Walter <stefw src gnome org>
- To: svn-commits-list gnome org
- Subject: [gnome-keyring: 4/10] [gck] Add support for transient PKCS#11 objects.
- Date: Sun, 19 Jul 2009 19:33:28 +0000 (UTC)
commit 4508771f734590140051391b0a9222451f2aa453
Author: Stef Walter <stef memberwebs com>
Date: Sat Jul 18 22:42:48 2009 +0000
[gck] Add support for transient PKCS#11 objects.
Transient objects are not stored permanently. These may be token
objects with token 'scope' but dissappear automatically at some
point in the future.
Auto-destructed objects are always token objects.
pkcs11/gck/gck-module.c | 114 +++++++++++++++-
pkcs11/gck/gck-object.c | 132 +++++++++++-------
pkcs11/gck/gck-object.h | 13 +-
pkcs11/gck/gck-session.c | 17 ++-
pkcs11/gck/tests/Makefile.am | 1 +
pkcs11/gck/tests/unit-test-object.c | 262 +++++++++++++++++++++++++++++++++++
pkcs11/gck/tests/unit-test-timer.c | 2 +-
pkcs11/pkcs11g.h | 2 +
8 files changed, 478 insertions(+), 65 deletions(-)
---
diff --git a/pkcs11/gck/gck-module.c b/pkcs11/gck/gck-module.c
index 32cdcf3..f49fdac 100644
--- a/pkcs11/gck/gck-module.c
+++ b/pkcs11/gck/gck-module.c
@@ -29,10 +29,12 @@
#include "gck-certificate.h"
#include "gck-factory.h"
#include "gck-manager.h"
+#include "gck-memory-store.h"
#include "gck-module.h"
#include "gck-private-key.h"
#include "gck-public-key.h"
#include "gck-session.h"
+#include "gck-store.h"
#include "gck-timer.h"
#include "gck-transaction.h"
#include "gck-util.h"
@@ -46,13 +48,17 @@ enum {
};
struct _GckModulePrivate {
+ GMutex *mutex; /* The mutex controlling entry to this module */
+
GckManager *token_manager;
GHashTable *virtual_slots_by_id; /* Various slot partitions by their ID */
GHashTable *sessions_by_handle; /* Mapping of handle to all open sessions */
gint handle_counter; /* Constantly incrementing counter for handles and the like */
GArray *factories; /* Various registered object factories */
gboolean factories_sorted; /* Whether we need to sort the object factories */
- GMutex *mutex; /* The mutex controlling entry to this module */
+
+ GHashTable *transient_objects; /* Token objects that are not stored permanently. */
+ GckStore *transient_store; /* Store for trantsient objects. */
};
typedef struct _VirtualSlot {
@@ -134,6 +140,10 @@ static const MechanismAndInfo mechanism_list[] = {
/* Hidden function that you should not use */
GMutex* _gck_module_get_scary_mutex_that_you_should_not_touch (GckModule *self);
+static void remove_transient_object (GckModule *self, GckTransaction *transaction, GckObject *object);
+
+static void add_transient_object (GckModule *self, GckTransaction *transaction, GckObject *object);
+
/* -----------------------------------------------------------------------------
* INTERNAL
*/
@@ -340,6 +350,76 @@ done:
g_free (dup);
}
+
+static gboolean
+complete_transient_remove (GckTransaction *transaction, GckModule *self, GckObject *object)
+{
+ if (gck_transaction_get_failed (transaction))
+ add_transient_object (self, NULL, object);
+ g_object_unref (object);
+ return TRUE;
+}
+
+static void
+remove_transient_object (GckModule *self, GckTransaction *transaction, GckObject *object)
+{
+ g_assert (GCK_IS_MODULE (self));
+ g_assert (GCK_IS_OBJECT (object));
+
+ g_object_ref (object);
+
+ gck_manager_unregister_object (self->pv->token_manager, object);
+ if (!g_hash_table_remove (self->pv->transient_objects, object))
+ g_return_if_reached ();
+ g_object_set (object, "store", NULL, NULL);
+
+ if (transaction) {
+ gck_transaction_add (transaction, self,
+ (GckTransactionFunc)complete_transient_remove,
+ g_object_ref (object));
+ }
+
+ g_object_unref (object);
+}
+
+static gboolean
+complete_transient_add (GckTransaction *transaction, GckModule *self, GckObject *object)
+{
+ if (gck_transaction_get_failed (transaction))
+ remove_transient_object (self, NULL, object);
+ g_object_unref (object);
+ return TRUE;
+}
+
+static void
+add_transient_object (GckModule *self, GckTransaction *transaction, GckObject *object)
+{
+ g_assert (GCK_IS_MODULE (self));
+ g_assert (GCK_IS_OBJECT (object));
+
+ /* Must not already be associated with a session or manager */
+ g_return_if_fail (gck_object_get_manager (object) == NULL);
+ g_return_if_fail (g_hash_table_lookup (self->pv->transient_objects, object) == NULL);
+
+ g_hash_table_insert (self->pv->transient_objects, object, g_object_ref (object));
+ gck_manager_register_object (self->pv->token_manager, object);
+ g_object_set (object, "store", self->pv->transient_store, NULL);
+
+ if (transaction) {
+ gck_transaction_add (transaction, self,
+ (GckTransactionFunc)complete_transient_add,
+ g_object_ref (object));
+ }
+}
+
+static void
+dispose_unref_object (gpointer obj)
+{
+ g_assert (G_IS_OBJECT (obj));
+ g_object_run_dispose (obj);
+ g_object_unref (obj);
+}
+
/* -----------------------------------------------------------------------------
* OBJECT
*/
@@ -431,10 +511,16 @@ static GObject*
gck_module_constructor (GType type, guint n_props, GObjectConstructParam *props)
{
GckModule *self = GCK_MODULE (G_OBJECT_CLASS (gck_module_parent_class)->constructor(type, n_props, props));
+ CK_ATTRIBUTE attr;
+
g_return_val_if_fail (self, NULL);
+ /* Register store attributes */
+ attr.type = CKA_LABEL;
+ attr.pValue = "";
+ attr.ulValueLen = 0;
+ gck_store_register_schema (self->pv->transient_store, &attr, NULL, 0);
-
return G_OBJECT (self);
}
@@ -453,6 +539,10 @@ gck_module_init (GckModule *self)
g_atomic_int_set (&(self->pv->handle_counter), 1);
+ /* Create the store for transient objects */
+ self->pv->transient_store = GCK_STORE (gck_memory_store_new ());
+ self->pv->transient_objects = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, dispose_unref_object);
+
/* Register session object factories */
gck_module_register_factory (self, GCK_FACTORY_PRIVATE_KEY);
gck_module_register_factory (self, GCK_FACTORY_CERTIFICATE);
@@ -464,6 +554,8 @@ gck_module_dispose (GObject *obj)
{
GckModule *self = GCK_MODULE (obj);
+ g_hash_table_remove_all (self->pv->transient_objects);
+
if (self->pv->token_manager)
g_object_unref (self->pv->token_manager);
self->pv->token_manager = NULL;
@@ -480,7 +572,13 @@ static void
gck_module_finalize (GObject *obj)
{
GckModule *self = GCK_MODULE (obj);
+
+ g_hash_table_destroy (self->pv->transient_objects);
+ self->pv->transient_objects = NULL;
+ g_object_unref (self->pv->transient_store);
+ self->pv->transient_store = NULL;
+
g_assert (self->pv->token_manager == NULL);
g_assert (g_hash_table_size (self->pv->virtual_slots_by_id) == 0);
@@ -691,7 +789,11 @@ gck_module_store_token_object (GckModule *self, GckTransaction *transaction, Gck
g_return_if_fail (GCK_IS_MODULE (self));
g_return_if_fail (GCK_IS_OBJECT (object));
g_assert (GCK_MODULE_GET_CLASS (self)->store_token_object);
- GCK_MODULE_GET_CLASS (self)->store_token_object (self, transaction, object);
+
+ if (gck_object_get_transient (object))
+ add_transient_object (self, transaction, object);
+ else
+ GCK_MODULE_GET_CLASS (self)->store_token_object (self, transaction, object);
}
void
@@ -700,7 +802,11 @@ gck_module_remove_token_object (GckModule *self, GckTransaction *transaction, Gc
g_return_if_fail (GCK_IS_MODULE (self));
g_return_if_fail (GCK_IS_OBJECT (object));
g_assert (GCK_MODULE_GET_CLASS (self)->remove_token_object);
- GCK_MODULE_GET_CLASS (self)->remove_token_object (self, transaction, object);
+
+ if (gck_object_get_transient (object))
+ remove_transient_object (self, transaction, object);
+ else
+ GCK_MODULE_GET_CLASS (self)->remove_token_object (self, transaction, object);
}
void
diff --git a/pkcs11/gck/gck-object.c b/pkcs11/gck/gck-object.c
index 59e156f..a210b53 100644
--- a/pkcs11/gck/gck-object.c
+++ b/pkcs11/gck/gck-object.c
@@ -49,10 +49,10 @@ enum {
static guint signals[LAST_SIGNAL] = { 0 };
-typedef struct _GckObjectLifetime {
+typedef struct _GckObjectTransient {
GckTimer *timed_timer;
glong timed_when;
-} GckObjectLifetime;
+} GckObjectTransient;
struct _GckObjectPrivate {
CK_OBJECT_HANDLE handle;
@@ -60,7 +60,7 @@ struct _GckObjectPrivate {
GckManager *manager;
GckStore *store;
gchar *unique;
- GckObjectLifetime *lifetime;
+ GckObjectTransient *transient;
};
G_DEFINE_TYPE (GckObject, gck_object, G_TYPE_OBJECT);
@@ -74,16 +74,16 @@ kaboom_callback (GckTimer *timer, gpointer user_data)
{
GckObject *self = user_data;
GckTransaction *transaction;
- GckObjectLifetime *lifetime;
+ GckObjectTransient *transient;
GckSession *session;
CK_RV rv;
g_return_if_fail (GCK_IS_OBJECT (self));
- g_return_if_fail (self->pv->lifetime);
- lifetime = self->pv->lifetime;
+ g_return_if_fail (self->pv->transient);
+ transient = self->pv->transient;
- g_return_if_fail (timer == lifetime->timed_timer);
- lifetime->timed_timer = NULL;
+ g_return_if_fail (timer == transient->timed_timer);
+ transient->timed_timer = NULL;
g_object_ref (self);
@@ -108,17 +108,15 @@ static gboolean
start_callback (GckTransaction *transaction, GObject *obj, gpointer user_data)
{
GckObject *self = GCK_OBJECT (obj);
- GckObjectLifetime *lifetime;
- GckSession *session = user_data;
+ GckObjectTransient *transient;
g_return_val_if_fail (GCK_IS_OBJECT (self), FALSE);
- g_return_val_if_fail (GCK_IS_SESSION (session), FALSE);
- g_return_val_if_fail (self->pv->lifetime, FALSE);
- lifetime = self->pv->lifetime;
+ g_return_val_if_fail (self->pv->transient, FALSE);
+ transient = self->pv->transient;
- g_return_val_if_fail (!lifetime->timed_timer, FALSE);
- lifetime->timed_timer = gck_timer_start (gck_session_get_module (session),
- lifetime->timed_when, kaboom_callback, self);
+ g_return_val_if_fail (!transient->timed_timer, FALSE);
+ transient->timed_timer = gck_timer_start (self->pv->module, transient->timed_when,
+ kaboom_callback, self);
return TRUE;
}
@@ -158,9 +156,11 @@ gck_object_real_get_attribute (GckObject *self, CK_ATTRIBUTE* attr)
if (self->pv->unique)
return gck_attribute_set_string (attr, self->pv->unique);
return CKR_ATTRIBUTE_TYPE_INVALID;
+ case CKA_GNOME_TRANSIENT:
+ return gck_attribute_set_bool (attr, self->pv->transient ? TRUE : FALSE);
case CKA_GNOME_AUTO_DESTRUCT:
- return gck_attribute_set_time (attr, self->pv->lifetime ?
- self->pv->lifetime->timed_when : -1);
+ return gck_attribute_set_time (attr, self->pv->transient ?
+ self->pv->transient->timed_when : -1);
};
/* Give store a shot */
@@ -213,26 +213,54 @@ gck_object_real_set_attribute (GckObject *self, GckTransaction* transaction, CK_
}
static void
-gck_object_real_create_attribute (GckObject *self, GckTransaction *transaction,
- CK_ATTRIBUTE *attr, GckSession *session)
+gck_object_real_create_attributes (GckObject *self, GckTransaction *transaction,
+ GckSession *session, CK_ATTRIBUTE *attrs, CK_ULONG n_attrs)
{
+ CK_ATTRIBUTE_PTR transient_attr;
+ CK_ATTRIBUTE_PTR lifetime_attr;
+ gboolean transient = FALSE;
+ glong lifetime = -1;
CK_RV rv;
- switch (attr->type) {
- case CKA_GNOME_AUTO_DESTRUCT:
- if (!self->pv->lifetime)
- self->pv->lifetime = g_slice_new0 (GckObjectLifetime);
- rv = gck_attribute_get_time (attr, &self->pv->lifetime->timed_when);
- gck_attribute_consume (attr);
- if (rv == CKR_OK) {
- /* Must be a session object for an auto destruct */
- if (self->pv->lifetime->timed_when >= 0)
- gck_transaction_add (transaction, self, start_callback, session);
+ /* Parse the transient attribute */
+ transient_attr = gck_attributes_find (attrs, n_attrs, CKA_GNOME_TRANSIENT);
+ if (transient_attr) {
+ rv = gck_attribute_get_bool (transient_attr, &transient);
+ gck_attribute_consume (transient_attr);
+ if (rv != CKR_OK) {
+ gck_transaction_fail (transaction, rv);
+ return;
}
- if (rv != CKR_OK)
+ }
+
+ /* Parse the auto destruct attribute */
+ lifetime_attr = gck_attributes_find (attrs, n_attrs, CKA_GNOME_AUTO_DESTRUCT);
+ if (lifetime_attr) {
+ rv = gck_attribute_get_time (lifetime_attr, &lifetime);
+ gck_attribute_consume (lifetime_attr);
+ if (rv != CKR_OK) {
gck_transaction_fail (transaction, rv);
- return;
- };
+ return;
+ }
+
+ /* Default for the transient attribute */
+ if (!transient_attr)
+ transient = TRUE;
+ }
+
+ if (transient) {
+ self->pv->transient = g_slice_new0 (GckObjectTransient);
+ self->pv->transient->timed_when = lifetime;
+ }
+
+ if (lifetime >= 0) {
+ if (!self->pv->transient) {
+ gck_transaction_fail (transaction, CKR_TEMPLATE_INCONSISTENT);
+ return;
+ }
+
+ gck_transaction_add (transaction, self, start_callback, NULL);
+ }
}
static CK_RV
@@ -273,7 +301,7 @@ static void
gck_object_dispose (GObject *obj)
{
GckObject *self = GCK_OBJECT (obj);
- GckObjectLifetime *lifetime;
+ GckObjectTransient *transient;
if (self->pv->manager)
gck_manager_unregister_object (self->pv->manager, self);
@@ -282,14 +310,14 @@ gck_object_dispose (GObject *obj)
g_object_set (self, "store", NULL, NULL);
g_assert (self->pv->store == NULL);
- if (self->pv->lifetime) {
- lifetime = self->pv->lifetime;
- if (lifetime->timed_timer)
- gck_timer_cancel (lifetime->timed_timer);
- lifetime->timed_timer = NULL;
+ if (self->pv->transient) {
+ transient = self->pv->transient;
+ if (transient->timed_timer)
+ gck_timer_cancel (transient->timed_timer);
+ transient->timed_timer = NULL;
- g_slice_free (GckObjectLifetime, lifetime);
- self->pv->lifetime = NULL;
+ g_slice_free (GckObjectTransient, transient);
+ self->pv->transient = NULL;
}
G_OBJECT_CLASS (gck_object_parent_class)->dispose (obj);
@@ -307,7 +335,7 @@ gck_object_finalize (GObject *obj)
g_object_weak_unref (G_OBJECT (self->pv->module), module_went_away, self);
self->pv->module = NULL;
- g_assert (self->pv->lifetime == NULL);
+ g_assert (self->pv->transient == NULL);
G_OBJECT_CLASS (gck_object_parent_class)->finalize (obj);
}
@@ -414,7 +442,7 @@ gck_object_class_init (GckObjectClass *klass)
klass->unlock = gck_object_real_unlock;
klass->get_attribute = gck_object_real_get_attribute;
klass->set_attribute = gck_object_real_set_attribute;
- klass->create_attribute = gck_object_real_create_attribute;
+ klass->create_attributes = gck_object_real_create_attributes;
g_object_class_install_property (gobject_class, PROP_HANDLE,
g_param_spec_ulong ("handle", "Handle", "Object handle",
@@ -485,19 +513,19 @@ gck_object_set_attribute (GckObject *self, GckTransaction *transaction,
}
void
-gck_object_create_attribute (GckObject *self, GckTransaction *transaction,
- CK_ATTRIBUTE_PTR attr, GckSession *session)
+gck_object_create_attributes (GckObject *self, GckTransaction *transaction, GckSession *session,
+ CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs)
{
g_return_if_fail (GCK_IS_OBJECT (self));
g_return_if_fail (GCK_IS_TRANSACTION (transaction));
g_return_if_fail (!gck_transaction_get_failed (transaction));
g_return_if_fail (GCK_IS_SESSION (session));
- g_return_if_fail (attr);
+ g_return_if_fail (attrs);
- g_assert (GCK_OBJECT_GET_CLASS (self)->create_attribute);
+ g_assert (GCK_OBJECT_GET_CLASS (self)->create_attributes);
/* Check that the value will actually change */
- GCK_OBJECT_GET_CLASS (self)->create_attribute (self, transaction, attr, session);
+ GCK_OBJECT_GET_CLASS (self)->create_attributes (self, transaction, session, attrs, n_attrs);
}
void
@@ -589,6 +617,14 @@ gck_object_get_unique (GckObject *self)
return self->pv->unique;
}
+gboolean
+gck_object_get_transient (GckObject *self)
+{
+ g_return_val_if_fail (GCK_IS_OBJECT (self), FALSE);
+ return self->pv->transient ? TRUE : FALSE;
+}
+
+
CK_RV
gck_object_unlock (GckObject *self, CK_UTF8CHAR_PTR pin, CK_ULONG n_pin)
{
diff --git a/pkcs11/gck/gck-object.h b/pkcs11/gck/gck-object.h
index 0a3b065..44d79b8 100644
--- a/pkcs11/gck/gck-object.h
+++ b/pkcs11/gck/gck-object.h
@@ -56,8 +56,8 @@ struct _GckObjectClass {
void (*set_attribute) (GckObject *object, GckTransaction *transaction, CK_ATTRIBUTE *attr);
- void (*create_attribute) (GckObject *object, GckTransaction *transaction,
- CK_ATTRIBUTE *attr, GckSession *session);
+ void (*create_attributes) (GckObject *object, GckTransaction *transaction, GckSession *session,
+ CK_ATTRIBUTE *attrs, CK_ULONG n_attrs);
CK_RV (*unlock) (GckObject *self, CK_UTF8CHAR_PTR pin, CK_ULONG n_pin);
};
@@ -75,6 +75,8 @@ GckManager* gck_object_get_manager (GckObject *self);
const gchar* gck_object_get_unique (GckObject *self);
+gboolean gck_object_get_transient (GckObject *self);
+
CK_RV gck_object_unlock (GckObject *self,
CK_UTF8CHAR_PTR pin,
CK_ULONG n_pin);
@@ -93,10 +95,11 @@ void gck_object_set_attribute (GckObject *self,
GckTransaction *transaction,
CK_ATTRIBUTE_PTR attr);
-void gck_object_create_attribute (GckObject *self,
+void gck_object_create_attributes (GckObject *self,
GckTransaction *transaction,
- CK_ATTRIBUTE_PTR attr,
- GckSession *session);
+ GckSession *session,
+ CK_ATTRIBUTE_PTR attrs,
+ CK_ULONG n_attrs);
void gck_object_notify_attribute (GckObject *self,
CK_ATTRIBUTE_TYPE attr_type);
diff --git a/pkcs11/gck/gck-session.c b/pkcs11/gck/gck-session.c
index 334a770..dd4e70a 100644
--- a/pkcs11/gck/gck-session.c
+++ b/pkcs11/gck/gck-session.c
@@ -269,8 +269,9 @@ lookup_object_from_handle (GckSession *self, CK_OBJECT_HANDLE handle,
*/
if (writable) {
if (is_token) {
- if (gck_module_get_write_protected (self->pv->module))
- return CKR_TOKEN_WRITE_PROTECTED;
+ if (!gck_object_get_transient (object))
+ if (gck_module_get_write_protected (self->pv->module))
+ return CKR_TOKEN_WRITE_PROTECTED;
if (self->pv->read_only)
return CKR_SESSION_READ_ONLY;
}
@@ -740,6 +741,7 @@ gck_session_C_CreateObject (GckSession* self, CK_ATTRIBUTE_PTR template,
CK_ULONG n_attrs, i;
GckFactory factory;
gboolean is_token;
+ gboolean is_transient;
gboolean is_private;
CK_RV rv;
@@ -756,11 +758,13 @@ gck_session_C_CreateObject (GckSession* self, CK_ATTRIBUTE_PTR template,
/* Find out where we'll be creating this */
if (!gck_attributes_find_boolean (template, count, CKA_TOKEN, &is_token))
- is_token = CK_FALSE;
+ is_token = FALSE;
+ if (!gck_attributes_find_boolean (template, count, CKA_GNOME_TRANSIENT, &is_transient))
+ is_transient = FALSE;
/* See if we can create due to read-only */
if (is_token) {
- if (gck_module_get_write_protected (self->pv->module))
+ if (!is_transient && gck_module_get_write_protected (self->pv->module))
return CKR_TOKEN_WRITE_PROTECTED;
if (self->pv->read_only)
return CKR_SESSION_READ_ONLY;
@@ -792,9 +796,8 @@ gck_session_C_CreateObject (GckSession* self, CK_ATTRIBUTE_PTR template,
}
/* Give the object a chance to create additional attributes */
- for (i = 0; i < n_attrs && !gck_transaction_get_failed (transaction); ++i) {
- if (!gck_attribute_consumed (&attrs[i]))
- gck_object_create_attribute (object, transaction, &attrs[i], self);
+ if (!gck_transaction_get_failed (transaction)) {
+ gck_object_create_attributes (object, transaction, self, attrs, n_attrs);
}
/* Find somewhere to store the object */
diff --git a/pkcs11/gck/tests/Makefile.am b/pkcs11/gck/tests/Makefile.am
index e1b72e8..4bd2b10 100644
--- a/pkcs11/gck/tests/Makefile.am
+++ b/pkcs11/gck/tests/Makefile.am
@@ -11,6 +11,7 @@ UNIT_AUTO = \
unit-test-crypto.c \
unit-test-data-asn1.c \
unit-test-data-der.c \
+ unit-test-object.c \
unit-test-timer.c \
unit-test-transaction.c \
unit-test-store.c \
diff --git a/pkcs11/gck/tests/unit-test-object.c b/pkcs11/gck/tests/unit-test-object.c
new file mode 100644
index 0000000..d55f36d
--- /dev/null
+++ b/pkcs11/gck/tests/unit-test-object.c
@@ -0,0 +1,262 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* unit-test-timer.c: Test thread timer functionality
+
+ Copyright (C) 2009 Stefan Walter
+
+ 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 <stef memberwebs com>
+*/
+
+#include "run-auto-test.h"
+#include "test-module.h"
+
+#include "gck/gck-attributes.h"
+#include "gck/gck-object.h"
+#include "gck/gck-session.h"
+#include "gck/gck-module.h"
+
+#include "pkcs11g.h"
+
+static GckModule *module = NULL;
+static GckSession *session = NULL;
+static guchar *certificate_data = NULL;
+static gsize certificate_n_data = 0;
+
+DEFINE_SETUP(object_setup)
+{
+ CK_SESSION_HANDLE handle;
+ CK_RV rv;
+
+ module = test_module_initialize ();
+ test_module_enter ();
+
+ rv = gck_module_C_OpenSession (module, 1, CKF_SERIAL_SESSION | CKF_RW_SESSION,
+ NULL, NULL, &handle);
+ g_assert (rv == CKR_OK);
+
+ session = gck_module_lookup_session (module, handle);
+ g_assert (session);
+
+ certificate_data = test_read_testdata ("test-certificate-1.der", &certificate_n_data);
+}
+
+DEFINE_TEARDOWN(object_teardown)
+{
+ CK_RV rv;
+
+ g_free (certificate_data);
+ certificate_data = NULL;
+ certificate_n_data = 0;
+
+ rv = gck_module_C_CloseAllSessions (module, 1);
+ g_assert (rv == CKR_OK);
+
+ test_module_leave ();
+ test_module_finalize ();
+ module = NULL;
+ session = NULL;
+}
+
+static gboolean
+check_object_exists (CK_OBJECT_HANDLE handle)
+{
+ CK_BBOOL token;
+ CK_ATTRIBUTE attr = { CKA_TOKEN, &token, sizeof (token) };
+ CK_RV rv;
+
+ rv = gck_session_C_GetAttributeValue (session, handle, &attr, 1);
+ if (rv == CKR_OBJECT_HANDLE_INVALID)
+ return FALSE;
+
+ g_assert (rv == CKR_OK);
+ return TRUE;
+}
+
+DEFINE_TEST(object_create_destroy_transient)
+{
+ CK_BBOOL transient = CK_TRUE;
+ CK_BBOOL token = CK_TRUE;
+ CK_OBJECT_CLASS klass = CKO_CERTIFICATE;
+ CK_CERTIFICATE_TYPE type = CKC_X_509;
+
+ CK_ATTRIBUTE attrs[] = {
+ { CKA_TOKEN, &token, sizeof (token) },
+ { CKA_GNOME_TRANSIENT, &transient, sizeof (transient) },
+ { CKA_CLASS, &klass, sizeof (klass) },
+ { CKA_CERTIFICATE_TYPE, &type, sizeof (type) },
+ { CKA_VALUE, certificate_data, certificate_n_data },
+ };
+
+ CK_ATTRIBUTE lookup = { CKA_GNOME_TRANSIENT, &transient, sizeof (transient) };
+ CK_OBJECT_HANDLE handle;
+ CK_RV rv;
+
+ rv = gck_session_C_CreateObject (session, attrs, G_N_ELEMENTS (attrs), &handle);
+ g_assert (rv == CKR_OK);
+ g_assert (handle != 0);
+
+ g_assert (check_object_exists (handle));
+
+ transient = CK_FALSE;
+ rv = gck_session_C_GetAttributeValue (session, handle, &lookup, 1);
+ g_assert (rv == CKR_OK);
+ g_assert (transient == CK_TRUE);
+
+ rv = gck_session_C_DestroyObject (session, handle);
+ g_assert (rv == CKR_OK);
+
+ g_assert (!check_object_exists (handle));
+}
+
+DEFINE_TEST(object_transient_transacted_fail)
+{
+ CK_BBOOL transient = CK_TRUE;
+ CK_BBOOL token = CK_TRUE;
+ CK_OBJECT_CLASS klass = CKO_CERTIFICATE;
+ CK_CERTIFICATE_TYPE type = CKC_X_509;
+ CK_ULONG invalid = 4;
+
+ CK_ATTRIBUTE attrs[] = {
+ { CKA_TOKEN, &token, sizeof (token) },
+ { CKA_GNOME_TRANSIENT, &transient, sizeof (transient) },
+ { CKA_CLASS, &klass, sizeof (klass) },
+ { CKA_CERTIFICATE_TYPE, &type, sizeof (type) },
+ { CKA_VALUE, certificate_data, certificate_n_data },
+
+ /* An invalid attribute, should cause transaction to fail */
+ { CKA_BITS_PER_PIXEL, &invalid, sizeof (invalid) }
+ };
+
+ CK_OBJECT_HANDLE handle;
+ CK_RV rv;
+
+ rv = gck_session_C_CreateObject (session, attrs, G_N_ELEMENTS (attrs), &handle);
+ g_assert (rv == CKR_ATTRIBUTE_TYPE_INVALID);
+}
+
+DEFINE_TEST(object_create_transient_bad_value)
+{
+ CK_OBJECT_CLASS klass = CKO_CERTIFICATE;
+ CK_CERTIFICATE_TYPE type = CKC_X_509;
+
+ CK_ATTRIBUTE attrs[] = {
+ { CKA_GNOME_TRANSIENT, NULL, 0 },
+ { CKA_CLASS, &klass, sizeof (klass) },
+ { CKA_CERTIFICATE_TYPE, &type, sizeof (type) },
+ { CKA_VALUE, certificate_data, certificate_n_data },
+ };
+
+ CK_OBJECT_HANDLE handle;
+ CK_RV rv;
+
+ /* Can't have a non-transient object that auto-destructs */
+ rv = gck_session_C_CreateObject (session, attrs, G_N_ELEMENTS (attrs), &handle);
+ g_assert (rv == CKR_ATTRIBUTE_VALUE_INVALID);
+}
+
+DEFINE_TEST(object_create_auto_destruct)
+{
+ CK_BBOOL token = CK_FALSE;
+ CK_OBJECT_CLASS klass = CKO_CERTIFICATE;
+ CK_CERTIFICATE_TYPE type = CKC_X_509;
+ gchar lifetime[16];
+ gchar check[16];
+
+ CK_ATTRIBUTE attrs[] = {
+ { CKA_GNOME_AUTO_DESTRUCT, lifetime, sizeof (lifetime) },
+ { CKA_TOKEN, &token, sizeof (token) },
+ { CKA_CLASS, &klass, sizeof (klass) },
+ { CKA_CERTIFICATE_TYPE, &type, sizeof (type) },
+ { CKA_VALUE, certificate_data, certificate_n_data },
+ };
+
+ CK_BBOOL transient;
+
+ CK_ATTRIBUTE lookups[] = {
+ { CKA_GNOME_AUTO_DESTRUCT, check, sizeof (check) },
+ { CKA_GNOME_TRANSIENT, &transient, sizeof (transient) }
+ };
+
+ CK_OBJECT_HANDLE handle;
+ GTimeVal tv;
+ CK_RV rv;
+
+ /* Fill in the special attribute */
+ g_get_current_time (&tv);
+ rv = gck_attribute_set_time (&attrs[0], tv.tv_sec + 2);
+ g_assert (rv == CKR_OK);
+
+ rv = gck_session_C_CreateObject (session, attrs, G_N_ELEMENTS (attrs), &handle);
+ g_assert (rv == CKR_OK);
+ g_assert (handle != 0);
+
+ g_assert (check_object_exists (handle));
+
+ transient = CK_FALSE;
+ rv = gck_session_C_GetAttributeValue (session, handle, lookups, G_N_ELEMENTS (lookups));
+ g_assert (rv == CKR_OK);
+ g_assert (transient == TRUE);
+ g_assert (memcmp (lifetime, check, 16) == 0);
+
+ test_module_leave ();
+ test_mainloop_run (2200);
+ test_module_enter ();
+
+ g_assert (!check_object_exists (handle));
+}
+
+DEFINE_TEST(object_create_auto_destruct_not_transient)
+{
+ CK_OBJECT_CLASS klass = CKO_CERTIFICATE;
+ CK_CERTIFICATE_TYPE type = CKC_X_509;
+ CK_BBOOL transient = CK_FALSE;
+
+ CK_ATTRIBUTE attrs[] = {
+ { CKA_GNOME_AUTO_DESTRUCT, "1999010101010100", 16 },
+ { CKA_GNOME_TRANSIENT, &transient, sizeof (transient) },
+ { CKA_CLASS, &klass, sizeof (klass) },
+ { CKA_CERTIFICATE_TYPE, &type, sizeof (type) },
+ { CKA_VALUE, certificate_data, certificate_n_data },
+ };
+
+ CK_OBJECT_HANDLE handle;
+ CK_RV rv;
+
+ /* Can't have a non-transient object that auto-destructs */
+ rv = gck_session_C_CreateObject (session, attrs, G_N_ELEMENTS (attrs), &handle);
+ g_assert (rv == CKR_TEMPLATE_INCONSISTENT);
+}
+
+DEFINE_TEST(object_create_auto_destruct_bad_value)
+{
+ CK_OBJECT_CLASS klass = CKO_CERTIFICATE;
+ CK_CERTIFICATE_TYPE type = CKC_X_509;
+
+ CK_ATTRIBUTE attrs[] = {
+ { CKA_GNOME_AUTO_DESTRUCT, "1999", 4 },
+ { CKA_CLASS, &klass, sizeof (klass) },
+ { CKA_CERTIFICATE_TYPE, &type, sizeof (type) },
+ { CKA_VALUE, certificate_data, certificate_n_data },
+ };
+
+ CK_OBJECT_HANDLE handle;
+ CK_RV rv;
+
+ /* Can't have a non-transient object that auto-destructs */
+ rv = gck_session_C_CreateObject (session, attrs, G_N_ELEMENTS (attrs), &handle);
+ g_assert (rv == CKR_ATTRIBUTE_VALUE_INVALID);
+}
diff --git a/pkcs11/gck/tests/unit-test-timer.c b/pkcs11/gck/tests/unit-test-timer.c
index e826799..d463041 100644
--- a/pkcs11/gck/tests/unit-test-timer.c
+++ b/pkcs11/gck/tests/unit-test-timer.c
@@ -26,7 +26,7 @@
#include "gck/gck-timer.h"
-GckModule *module = NULL;
+static GckModule *module = NULL;
DEFINE_SETUP(timer_setup)
{
diff --git a/pkcs11/pkcs11g.h b/pkcs11/pkcs11g.h
index d2ac6d9..da84c40 100644
--- a/pkcs11/pkcs11g.h
+++ b/pkcs11/pkcs11g.h
@@ -103,4 +103,6 @@
#define CKA_GNOME_AUTO_DESTRUCT (CKO_GNOME + 200)
+#define CKA_GNOME_TRANSIENT (CKO_GNOME + 201)
+
#endif /* PKCS11G_H */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]