gnome-keyring r1413 - in trunk: . gp11 gp11/tests



Author: nnielsen
Date: Mon Dec 29 06:46:36 2008
New Revision: 1413
URL: http://svn.gnome.org/viewvc/gnome-keyring?rev=1413&view=rev

Log:
	* gp11/gp11.h:
	* gp11/gp11-call.c:
	* gp11/gp11-marshal.list:
	* gp11/gp11-object.c:
	* gp11/gp11-private.h:
	* gp11/gp11-session.c:
	* gp11/gp11-slot.c:
	* gp11/tests/gp11-test.h:
	* gp11/tests/gp11-test-module.c:
	* gp11/tests/Makefile.am:
	* gp11/unit-test-gp11-crypto.c:
	* gp11/unit-test-gp11-session.c: Add crypto support to GP11 library.
	Add support for auto-login of context specific unlock of keys. Rework
	how auto-login of a token works.


Added:
   trunk/gp11/tests/unit-test-gp11-crypto.c
Modified:
   trunk/ChangeLog
   trunk/gp11/gp11-call.c
   trunk/gp11/gp11-marshal.list
   trunk/gp11/gp11-object.c
   trunk/gp11/gp11-private.h
   trunk/gp11/gp11-session.c
   trunk/gp11/gp11-slot.c
   trunk/gp11/gp11.h
   trunk/gp11/tests/Makefile.am
   trunk/gp11/tests/gp11-test-module.c
   trunk/gp11/tests/gp11-test.h
   trunk/gp11/tests/unit-test-gp11-session.c

Modified: trunk/gp11/gp11-call.c
==============================================================================
--- trunk/gp11/gp11-call.c	(original)
+++ trunk/gp11/gp11-call.c	Mon Dec 29 06:46:36 2008
@@ -36,7 +36,8 @@
 	GP11Module *module;
 	
 	/* For making the call */
-	GP11CallFunc func;
+	GP11PerformFunc perform;
+	GP11CompleteFunc complete;
 	GP11Arguments *args;
 	GCancellable *cancellable;
 	GDestroyNotify destroy;
@@ -46,10 +47,6 @@
 	gpointer object;
 	GAsyncReadyCallback callback;
 	gpointer user_data;
-	
-	/* For authenticating */
-	gboolean do_login;
-	gchar *password;
 };
 
 struct _GP11CallClass {
@@ -69,7 +66,7 @@
  */
 
 static CK_RV
-perform_call (GP11CallFunc func, GCancellable *cancellable, GP11Arguments *args)
+perform_call (GP11PerformFunc func, GCancellable *cancellable, GP11Arguments *args)
 {
 	CK_RV rv;
 	
@@ -97,31 +94,28 @@
 	return rv;
 }
 
+static gboolean
+complete_call (GP11CompleteFunc func, GP11Arguments *args, CK_RV result)
+{
+	/* Double check a few things */
+	g_assert (args);
+	
+	/* If no complete function, then just ignore */
+	if (!func)
+		return TRUE;
+
+	return (func) (args, result);
+}
+
+
 static void
 process_async_call (gpointer data, GP11CallClass *klass)
 {
 	GP11Call *call = GP11_CALL (data);
-	CK_ULONG pin_len;
 	
 	g_assert (GP11_IS_CALL (call));
 	
-	/* Try to login to the token, with the provided password */
-	if (call->do_login) {
-		call->do_login = FALSE;
-
-		pin_len = call->password ? strlen (call->password) : 0;
-		call->rv = (call->args->pkcs11->C_Login) (call->args->handle, CKU_USER, 
-		                                          (CK_UTF8CHAR_PTR)call->password, 
-		                                          pin_len);
-		
-		/* Fix the result so that we'll try the login again */
-		if (call->rv == CKR_PIN_INCORRECT)
-			call->rv = CKR_USER_NOT_LOGGED_IN;
-		
-	/* An actual call */
-	} else {
-		call->rv = perform_call (call->func, call->cancellable, call->args);
-	}
+	call->rv = perform_call (call->perform, call->cancellable, call->args);
 	
 	g_async_queue_push (klass->completed_queue, call);
 	
@@ -132,39 +126,29 @@
 static void 
 process_result (GP11Call *call, gpointer unused)
 {
-	GP11Slot *slot;
+	gboolean stop = FALSE;
 	
 	/* Double check a few things */
 	g_assert (GP11_IS_CALL (call));
 	
 	if (call->cancellable) {
 		/* Don't call the callback when cancelled */
-		if (g_cancellable_is_cancelled (call->cancellable))
+		if (g_cancellable_is_cancelled (call->cancellable)) {
 			call->rv = CKR_FUNCTION_CANCELED;
+			stop = TRUE;
+		}
 	}
 	
 	/* 
-	 * Now if this is a session call, and the slot wants does 
-	 * auto-login, then we try to get a password and do auto login.
+	 * Hmmm, does the function want to actually be done?
+	 * If not, then queue this call again. 
 	 */
-	if (call->rv == CKR_USER_NOT_LOGGED_IN && GP11_IS_SESSION (call->object)) {
-		g_free (call->password);
-		call->password = NULL;
-		slot = gp11_session_get_slot (GP11_SESSION (call->object));
-		g_assert (GP11_IS_SLOT (slot));
-		call->do_login = _gp11_slot_token_authentication (slot, &call->password);
-		g_object_unref (slot);
-	}
-	
-	/* If we're supposed to do a login, then queue this call again */
-	if (call->do_login) {
+	if (!stop && !complete_call (call->complete, call->args, call->rv)) {
 		g_object_ref (call);
 		g_thread_pool_push (GP11_CALL_GET_CLASS (call)->thread_pool, call, NULL);
-		return;
-	}
 	
 	/* All done, finish processing */
-	if (call->callback) {
+	} else if (call->callback) {
 		g_assert (G_IS_OBJECT (call->object));
 		(call->callback) (G_OBJECT (call->object), G_ASYNC_RESULT (call), 
 				  call->user_data);
@@ -261,10 +245,6 @@
 	call->destroy = NULL;
 	call->args = NULL;
 	
-	if (call->password)
-		g_free (call->password);
-	call->password = NULL;
-	
 	G_OBJECT_CLASS (_gp11_call_parent_class)->finalize (obj);
 }
 
@@ -398,18 +378,15 @@
 }
 
 gboolean
-_gp11_call_sync (gpointer object, gpointer func, gpointer data, 
-                 GCancellable *cancellable, GError **err)
+_gp11_call_sync (gpointer object, gpointer perform, gpointer complete, 
+                 gpointer data, GCancellable *cancellable, GError **err)
 {
 	GP11Arguments *args = (GP11Arguments*)data;
-	gchar *password = NULL;
 	GP11Module *module = NULL;
-	GP11Slot *slot; 
-	CK_ULONG pin_len;
 	CK_RV rv;
 	
 	g_assert (G_IS_OBJECT (object));
-	g_assert (func);
+	g_assert (perform);
 	g_assert (args);
 	
 	g_object_get (object, "module", &module, "handle", &args->handle, NULL);
@@ -419,31 +396,13 @@
 	args->pkcs11 = gp11_module_get_function_list (module);
 	g_assert (args->pkcs11);
 	
-	rv = perform_call ((GP11CallFunc)func, cancellable, args);
+	do {
+		rv = perform_call (perform, cancellable, args);
+		if (rv == CKR_FUNCTION_CANCELED)
+			break;
 		
-	/* 
-	 * Now if this is a session call, and the slot wants does 
-	 * auto-login, then we try to get a password and do auto login.
-	 */
-	if (rv == CKR_USER_NOT_LOGGED_IN && GP11_IS_SESSION (object)) {
+	} while (!complete_call (complete, args, rv));
 		
-		do {
-			slot = gp11_session_get_slot (GP11_SESSION (object));
-			if (!_gp11_slot_token_authentication (slot, &password)) {
-				rv = CKR_USER_NOT_LOGGED_IN;
-			} else {
-				pin_len = password ? strlen (password) : 0; 
-				rv = (args->pkcs11->C_Login) (args->handle, CKU_USER, 
-				                              (CK_UTF8CHAR_PTR)password, pin_len);
-			}
-			g_object_unref (slot);
-		} while (rv == CKR_PIN_INCORRECT);
-
-		/* If we logged in successfully then try again */
-		if (rv == CKR_OK)
-			rv = perform_call ((GP11CallFunc)func, cancellable, args);
-	}
-	
 	g_object_unref (module);
 
 	if (rv == CKR_OK)
@@ -454,14 +413,14 @@
 }
 
 gpointer
-_gp11_call_async_prep (gpointer object, gpointer cb_object, gpointer func, 
-                       gsize args_size, gpointer destroy)
+_gp11_call_async_prep (gpointer object, gpointer cb_object, gpointer perform, 
+                       gpointer complete, gsize args_size, gpointer destroy)
 {
 	GP11Arguments *args;
 	GP11Call *call;
 
 	g_assert (!object || G_IS_OBJECT (object));
-	g_assert (func);
+	g_assert (perform);
 	
 	if (!destroy)
 		destroy = g_free;
@@ -473,7 +432,8 @@
 	args = g_malloc0 (args_size);
 	call = g_object_new (GP11_TYPE_CALL, NULL);
 	call->destroy = (GDestroyNotify)destroy;
-	call->func = (GP11CallFunc)func;
+	call->perform = (GP11PerformFunc)perform;
+	call->complete = (GP11CompleteFunc)complete;
 	call->object = cb_object;
 	g_object_ref (cb_object);
 

Modified: trunk/gp11/gp11-marshal.list
==============================================================================
--- trunk/gp11/gp11-marshal.list	(original)
+++ trunk/gp11/gp11-marshal.list	Mon Dec 29 06:46:36 2008
@@ -1,3 +1,3 @@
-BOOLEAN:POINTER
-BOOLEAN:OBJECT,POINTER
+BOOLEAN:STRING,POINTER
+BOOLEAN:OBJECT,STRING,POINTER
 BOOLEAN:ULONG

Modified: trunk/gp11/gp11-object.c
==============================================================================
--- trunk/gp11/gp11-object.c	(original)
+++ trunk/gp11/gp11-object.c	Mon Dec 29 06:46:36 2008
@@ -483,7 +483,7 @@
 
 	session = require_session_sync (self, CKF_RW_SESSION, err);
 	if (session)
-		ret = _gp11_call_sync (session, perform_destroy, &args, cancellable, err);
+		ret = _gp11_call_sync (session, perform_destroy, NULL, &args, cancellable, err);
 	g_object_unref (session);
 	return ret;
 }
@@ -509,7 +509,7 @@
 	g_return_if_fail (GP11_IS_OBJECT (self));
 	g_return_if_fail (GP11_IS_SLOT (data->slot));
 
-	args = _gp11_call_async_prep (data->slot, self, perform_destroy, sizeof (*args), NULL);
+	args = _gp11_call_async_prep (data->slot, self, perform_destroy, NULL, sizeof (*args), NULL);
 	args->object = data->handle;
 	
 	call = _gp11_call_async_ready (args, cancellable, callback, user_data);
@@ -539,13 +539,6 @@
 	CK_OBJECT_HANDLE object;
 } SetAttributes;
 
-static void
-free_set_attributes (SetAttributes *args)
-{
-	gp11_attributes_unref (args->attrs);
-	g_free (args);
-}
-
 static CK_RV
 perform_set_attributes (SetAttributes *args)
 {
@@ -554,6 +547,13 @@
 	                                                 gp11_attributes_count (args->attrs));
 }
 
+static void
+free_set_attributes (SetAttributes *args)
+{
+	gp11_attributes_unref (args->attrs);
+	g_free (args);
+}
+
 /**
  * gp11_object_set:
  * @self: The object to set attributes on.
@@ -631,7 +631,7 @@
 
 	session = require_session_sync (self, CKF_RW_SESSION, err);
 	if (session)
-		ret = _gp11_call_sync (session, perform_set_attributes, &args, cancellable, err);
+		ret = _gp11_call_sync (session, perform_set_attributes, NULL, &args, cancellable, err);
 	g_object_unref (session);
 	return ret;
 }
@@ -658,9 +658,8 @@
 	g_return_if_fail (GP11_IS_OBJECT (self));
 
 	args = _gp11_call_async_prep (data->slot, self, perform_set_attributes, 
-	                              sizeof (*args), free_set_attributes);
-	args->attrs = attrs;
-	gp11_attributes_ref (attrs);
+	                              NULL, sizeof (*args), free_set_attributes);
+	args->attrs = gp11_attributes_ref (attrs);
 	args->object = data->handle;
 	
 	call = _gp11_call_async_ready (args, cancellable, callback, user_data);
@@ -692,15 +691,6 @@
 	GP11Attributes *results;
 } GetAttributes;
 
-static void
-free_get_attributes (GetAttributes *args)
-{
-	g_free (args->attr_types);
-	if (args->results)
-		gp11_attributes_unref (args->results);
-	g_free (args);
-}
-
 /* 
  * Certain failure return values only apply to individual attributes
  * being retrieved. These are ignored, since the attribute should 
@@ -776,6 +766,15 @@
 	return rv;
 }
 
+static void
+free_get_attributes (GetAttributes *args)
+{
+	g_free (args->attr_types);
+	if (args->results)
+		gp11_attributes_unref (args->results);
+}
+
+
 /**
  * gp11_object_get:
  * @self: The object to get attributes from.
@@ -848,7 +847,7 @@
 	args.n_attr_types = n_attr_types;
 	args.object = data->handle;
 
-	if (!_gp11_call_sync (session, perform_get_attributes, &args, cancellable, err)) {
+	if (!_gp11_call_sync (session, perform_get_attributes, NULL, &args, cancellable, err)) {
 		gp11_attributes_unref (args.results);
 		g_object_unref (session);
 		return NULL;
@@ -881,7 +880,8 @@
 	g_return_if_fail (GP11_IS_OBJECT (self));
 
 	args = _gp11_call_async_prep (data->slot, self, perform_get_attributes, 
-	                              sizeof (*args), free_get_attributes);
+	                              NULL, sizeof (*args), free_get_attributes);
+	
 	args->n_attr_types = n_attr_types;
 	if (n_attr_types)
 		args->attr_types = g_memdup (attr_types, sizeof (gulong) * n_attr_types);

Modified: trunk/gp11/gp11-private.h
==============================================================================
--- trunk/gp11/gp11-private.h	(original)
+++ trunk/gp11/gp11-private.h	Mon Dec 29 06:46:36 2008
@@ -52,14 +52,23 @@
  * SLOT
  */
 
-gboolean            _gp11_slot_token_authentication       (GP11Slot *slot, 
-                                                           gchar **password);
+gboolean            _gp11_slot_fire_authenticate_token       (GP11Slot *slot,
+                                                              gchar *label,
+                                                              gchar **password);
+
+gboolean            _gp11_slot_fire_authenticate_object      (GP11Slot *slot,
+                                                              GP11Object *object,
+                                                              gchar *label,
+                                                              gchar **password);
+
+gboolean            _gp11_slot_is_protected_auth_path        (GP11Slot *slot);
 
 /* ----------------------------------------------------------------------------
  * CALL
  */
 
-typedef CK_RV (*GP11CallFunc) (gpointer call_data); 
+typedef CK_RV (*GP11PerformFunc) (gpointer call_data);
+typedef gboolean (*GP11CompleteFunc) (gpointer call_data, CK_RV result); 
 
 typedef struct _GP11Call GP11Call;
 
@@ -92,14 +101,16 @@
 void               _gp11_call_uninitialize                (void);
 
 gboolean           _gp11_call_sync                        (gpointer object, 
-                                                           gpointer func, 
+                                                           gpointer perform, 
+                                                           gpointer complete,
                                                            gpointer args, 
                                                            GCancellable *cancellable, 
                                                            GError **err);
 
 gpointer           _gp11_call_async_prep                  (gpointer object, 
                                                            gpointer cb_object,
-                                                           gpointer func, 
+                                                           gpointer perform,
+                                                           gpointer complete,
                                                            gsize args_size,
                                                            gpointer destroy_func);
 
@@ -115,7 +126,6 @@
                                                            GAsyncReadyCallback callback, 
                                                            gpointer user_data);
 
-
 void               _gp11_call_async_short                 (GP11Call *call, 
                                                            CK_RV rv);
 

Modified: trunk/gp11/gp11-session.c
==============================================================================
--- trunk/gp11/gp11-session.c	(original)
+++ trunk/gp11/gp11-session.c	Mon Dec 29 06:46:36 2008
@@ -29,6 +29,8 @@
 
 #include <string.h>
 
+#include <glib/gi18n.h>
+
 enum {
 	DISCARD_HANDLE,
 	LAST_SIGNAL
@@ -45,12 +47,17 @@
 	GP11Slot *slot;
 	GP11Module *module;
 	CK_SESSION_HANDLE handle;
-	gint discarded;
 } GP11SessionData;
 
 typedef struct _GP11SessionPrivate {
+
+	/* Remain same from init to finalize */
 	GP11SessionData data;
-	/* Add mutex and future MT-unsafe members here */
+
+	/* Modified atomically */
+	gint discarded;
+	gint auto_login;
+	
 } GP11SessionPrivate;
 
 #define GP11_SESSION_GET_DATA(o) \
@@ -61,6 +68,43 @@
 static guint signals[LAST_SIGNAL] = { 0 };
 
 /* ----------------------------------------------------------------------------
+ * HELPERS
+ */
+
+static GP11SessionPrivate*
+lock_private (gpointer obj)
+{
+	GP11SessionPrivate *pv;
+	GP11Session *self;
+	
+	g_return_val_if_fail (GP11_IS_SESSION (obj), NULL);
+	self = GP11_SESSION (obj);
+	
+	g_object_ref (self);
+	
+	pv = G_TYPE_INSTANCE_GET_PRIVATE (self, GP11_TYPE_SESSION, GP11SessionPrivate);
+	/* g_static_mutex_lock (&pv->mutex); */
+	
+	return pv;
+}
+
+static void
+unlock_private (gpointer obj, GP11SessionPrivate *pv)
+{
+	GP11Session *self;
+
+	g_assert (pv);
+	g_assert (GP11_IS_SESSION (obj));
+	
+	self = GP11_SESSION (obj);
+	
+	g_assert (G_TYPE_INSTANCE_GET_PRIVATE (self, GP11_TYPE_SESSION, GP11SessionPrivate) == pv);
+	
+	/* g_static_mutex_unlock (&pv->mutex); */
+	g_object_unref (self);
+}
+
+/* ----------------------------------------------------------------------------
  * OBJECT
  */
 
@@ -92,7 +136,7 @@
 static void
 gp11_session_init (GP11Session *self)
 {
-
+	
 }
 
 static void
@@ -143,25 +187,31 @@
 static void
 gp11_session_dispose (GObject *obj)
 {
-	GP11SessionData *data = GP11_SESSION_GET_DATA (obj);
+	GP11SessionPrivate *pv;
 	GP11Session *self = GP11_SESSION (obj);
 	gboolean handled;
 	gint discarded;
 
 	g_return_if_fail (GP11_IS_SESSION (self));
 	
-	discarded = g_atomic_int_get (&data->discarded);
-	if (!discarded && g_atomic_int_compare_and_exchange (&data->discarded, discarded, 1)) {
+	pv = lock_private (obj);
 	
-		/* 
-		 * Let the world know that we're discarding the session 
-		 * handle. This allows session reuse to work.
-		 */
+	{
+		discarded = g_atomic_int_get (&pv->discarded);
+		if (!discarded && g_atomic_int_compare_and_exchange (&pv->discarded, discarded, 1)) {
+	
+			/* 
+			 * Let the world know that we're discarding the session 
+			 * handle. This allows session reuse to work.
+			 */
 		
-		g_signal_emit_by_name (self, "discard-handle", data->handle, &handled);
-		g_return_if_fail (handled);
+			g_signal_emit_by_name (self, "discard-handle", pv->data.handle, &handled);
+			g_return_if_fail (handled);
+		}
 
 	}
+	
+	unlock_private (obj, pv);
 
 	G_OBJECT_CLASS (gp11_session_parent_class)->dispose (obj);
 }
@@ -169,9 +219,10 @@
 static void
 gp11_session_finalize (GObject *obj)
 {
+	GP11SessionPrivate *pv = G_TYPE_INSTANCE_GET_PRIVATE (obj, GP11_TYPE_SESSION, GP11SessionPrivate);
 	GP11SessionData *data = GP11_SESSION_GET_DATA (obj);
 
-	g_assert (data->discarded != 0);
+	g_assert (pv->discarded != 0);
 	
 	if (data->slot)
 		g_object_unref (data->slot);
@@ -421,7 +472,7 @@
                          gsize n_pin, GCancellable *cancellable, GError **err)
 {
 	Login args = { GP11_ARGUMENTS_INIT, user_type, (guchar*)pin, n_pin };
-	return _gp11_call_sync (self, perform_login, &args, cancellable, err);
+	return _gp11_call_sync (self, perform_login, NULL, &args, cancellable, err);
 	
 }
 
@@ -443,7 +494,7 @@
                           gsize n_pin, GCancellable *cancellable, GAsyncReadyCallback callback,
                           gpointer user_data)
 {
-	Login* args = _gp11_call_async_prep (self, self, perform_login, sizeof (*args), free_login);
+	Login* args = _gp11_call_async_prep (self, self, perform_login, NULL, sizeof (*args), free_login);
 	
 	args->user_type = user_type;
 	args->pin = pin && n_pin ? g_memdup (pin, n_pin) : NULL;
@@ -509,7 +560,7 @@
 gp11_session_logout_full (GP11Session *self, GCancellable *cancellable, GError **err)
 {
 	GP11Arguments args = GP11_ARGUMENTS_INIT;
-	return _gp11_call_sync (self, perform_logout, &args, cancellable, err);	
+	return _gp11_call_sync (self, perform_logout, NULL, &args, cancellable, err);	
 }
 
 /**
@@ -526,7 +577,7 @@
 gp11_session_logout_async (GP11Session *self, GCancellable *cancellable,
                            GAsyncReadyCallback callback, gpointer user_data)
 {
-	GP11Arguments *args = _gp11_call_async_prep (self, self, perform_logout, 0, NULL);
+	GP11Arguments *args = _gp11_call_async_prep (self, self, perform_logout, NULL, 0, NULL);
 	_gp11_call_async_ready_go (args, cancellable, callback, user_data);
 }
 
@@ -640,7 +691,7 @@
 {
 	GP11SessionData *data = GP11_SESSION_GET_DATA (self);
 	CreateObject args = { GP11_ARGUMENTS_INIT, attrs, 0 };
-	if (!_gp11_call_sync (self, perform_create_object, &args, cancellable, err))
+	if (!_gp11_call_sync (self, perform_create_object, NULL, &args, cancellable, err))
 		return NULL;
 	return gp11_object_from_handle (data->slot, args.object);
 }
@@ -662,7 +713,7 @@
                                   gpointer user_data)
 {
 	CreateObject *args = _gp11_call_async_prep (self, self, perform_create_object, 
-	                                            sizeof (*args), free_create_object);
+	                                            NULL, sizeof (*args), free_create_object);
 	args->attrs = attrs;
 	gp11_attributes_ref (attrs);
 	_gp11_call_async_ready_go (args, cancellable, callback, user_data);
@@ -844,7 +895,7 @@
 	FindObjects args = { GP11_ARGUMENTS_INIT, attrs, NULL, 0 };
 	GList *results = NULL;
 	
-	if (_gp11_call_sync (self, perform_find_objects, &args, cancellable, err)) 
+	if (_gp11_call_sync (self, perform_find_objects, NULL, &args, cancellable, err)) 
 		results = objlist_from_handles (self, args.objects, args.n_objects);
 	g_free (args.objects);
 	return results;
@@ -867,7 +918,7 @@
                                  gpointer user_data)
 {
 	FindObjects *args = _gp11_call_async_prep (self, self, perform_find_objects, 
-	                                           sizeof (*args), free_find_objects);
+	                                           NULL, sizeof (*args), free_find_objects);
 	args->attrs = attrs;
 	gp11_attributes_ref (attrs);
 	_gp11_call_async_ready_go (args, cancellable, callback, user_data);
@@ -894,15 +945,187 @@
 	return objlist_from_handles (self, args->objects, args->n_objects);
 }
 
+/* --------------------------------------------------------------------------------------------------
+ * AUTHENTICATE 
+ */
+
+typedef enum _AuthenticateState {
+	AUTHENTICATE_NONE,
+	AUTHENTICATE_CAN,
+	AUTHENTICATE_WANT,
+	AUTHENTICATE_PERFORM
+} AuthenticateState;
+
+typedef struct _Authenticate {
+	AuthenticateState state;
+	gboolean protected_auth;
+	GP11Slot *slot;
+	GP11Object *object;
+	gchar *label;
+	gchar *password;
+} Authenticate;
+
+static CK_RV
+authenticate_perform (Authenticate *args, GP11Arguments *base)
+{
+	CK_ATTRIBUTE attributes[2];
+	CK_OBJECT_HANDLE handle;
+	CK_ULONG pin_len;
+	CK_BBOOL bvalue;
+	CK_RV rv;
+	
+	g_assert (args);
+	g_assert (base);
+	
+	switch (args->state) {
+	
+	/* 
+	 * Cannot authenticate for whatever reason, perhaps not 
+	 * enabled, or failed incomprehensibly etc. 
+	 * 
+	 */
+	case AUTHENTICATE_NONE:
+		return CKR_OK;
+	
+	/* 
+	 * Can authenticate but haven't seen if we should, yet 
+	 * check out the object in question. 
+	 */
+	case AUTHENTICATE_CAN:
+		
+		handle = gp11_object_get_handle (args->object);
+		
+		attributes[0].type = CKA_LABEL;
+		attributes[0].pValue = NULL;
+		attributes[0].ulValueLen = 0;
+		attributes[1].type = CKA_ALWAYS_AUTHENTICATE;
+		attributes[1].pValue = &bvalue;
+		attributes[1].ulValueLen = sizeof (bvalue);
+		
+		rv = (base->pkcs11->C_GetAttributeValue) (base->handle, handle, attributes, 2);
+		if (rv == CKR_ATTRIBUTE_TYPE_INVALID)
+			bvalue = CK_FALSE;
+		else if (rv != CKR_OK)
+			return rv;
+		
+		/* No authentication needed, on this object */
+		if (bvalue != CK_TRUE) {
+			args->state = AUTHENTICATE_NONE;
+			return CKR_OK;
+		}
+		
+		/* Protected authentication path, just go to perform */
+		if (args->protected_auth) {
+			args->state = AUTHENTICATE_PERFORM;
+			do {
+				rv = authenticate_perform (args, base);
+			} while (rv == CKR_PIN_INCORRECT);
+			return rv;
+		}
+
+		/* Get the label for a prompt */
+		g_assert (!args->label);
+		if (attributes[0].ulValueLen) {
+			attributes[0].pValue = g_malloc0 (attributes[0].ulValueLen + 1);
+			rv = (base->pkcs11->C_GetAttributeValue) (base->handle, handle, attributes, 2);
+			if (rv == CKR_OK) {
+				g_assert (!args->label);
+				args->label = attributes[0].pValue;
+				args->label[attributes[0].ulValueLen] = 0;
+			} else {
+				g_free (attributes[0].pValue);
+			}
+		}
+		
+		/* Need a password */
+		args->state = AUTHENTICATE_WANT;
+		return CKR_USER_NOT_LOGGED_IN; 
+
+	/*
+	 * This state should be handled in verify_authenticate.
+	 */
+	case AUTHENTICATE_WANT:
+		g_assert (FALSE);
+		return CKR_GENERAL_ERROR;
+	
+	/* 
+	 * Do the actual login authentication. 
+	 */
+	case AUTHENTICATE_PERFORM:
+		pin_len = args->password ? strlen (args->password) : 0; 
+		rv = (base->pkcs11->C_Login) (base->handle, CKU_CONTEXT_SPECIFIC, 
+		                              (CK_UTF8CHAR_PTR)args->password, pin_len);
+		if (rv == CKR_PIN_INCORRECT) 
+			args->state = AUTHENTICATE_WANT;
+		else
+			args->state = AUTHENTICATE_NONE;
+		return rv;
+		
+	default:
+		g_assert_not_reached ();
+		return CKR_GENERAL_ERROR;
+	}
+}
+
+static gboolean
+authenticate_complete (Authenticate *auth, GP11Arguments *base, CK_RV result)
+{
+	g_assert (auth);
+	g_assert (base);
+	
+	/* We're done here if not in this state */
+	if (auth->state == AUTHENTICATE_WANT) {
+
+		g_assert (GP11_IS_SLOT (auth->slot));
+		g_assert (GP11_IS_OBJECT (auth->object));
+
+		g_free (auth->password);
+		auth->password = NULL;
+	
+		if (_gp11_slot_fire_authenticate_object (auth->slot, auth->object, auth->label, &auth->password)) {
+			auth->state = AUTHENTICATE_PERFORM;
+			return FALSE; /* Want to continue processing this call */
+		}
+	}
 
-#if UNTESTED 
+	/* Free up various memory */
+	if (auth->slot)
+		g_object_unref (auth->slot);
+	if (auth->object)
+		g_object_unref (auth->object);
+	g_free (auth->label);
+	g_free (auth->password);
+	
+	/* The call is complete */
+	return TRUE;
+}
 
-/* ENCRYPT */
+static void
+authenticate_init (Authenticate *auth, GP11Slot *slot, GP11Object *object)
+{
+	g_assert (GP11_IS_SLOT (slot));
+	g_assert (GP11_IS_OBJECT (object));
+	
+	if (gp11_slot_get_auto_login (slot)) {
+		auth->state = AUTHENTICATE_CAN;
+		auth->protected_auth = _gp11_slot_is_protected_auth_path (slot);
+		auth->slot = g_object_ref (slot);
+		auth->object = g_object_ref (object);
+	} else {
+		auth->state = AUTHENTICATE_NONE;
+	}
+}
 
+/* --------------------------------------------------------------------------------------------------
+ * COMMON CRYPTO ROUTINES 
+ */
 
 typedef struct _Crypt {
 	GP11Arguments base;
 	
+	/* Authenticator */
+	Authenticate auth;
+	
 	/* Functions to call */
 	CK_C_EncryptInit init_func;
 	CK_C_Encrypt complete_func;
@@ -916,16 +1139,9 @@
 	/* Output */
 	guchar *result;
 	CK_ULONG n_result;
+	
 } Crypt;
 
-static void
-free_crypt (Crypt *args)
-{
-	g_free (args->input);
-	g_free (args->mech.pParameter);
-	g_free (args->result);
-}
-
 static CK_RV
 perform_crypt (Crypt *args)
 {
@@ -942,6 +1158,10 @@
 	if (rv != CKR_OK)
 		return rv;
 	
+	rv = authenticate_perform (&args->auth, &args->base);
+	if (rv != CKR_OK)
+		return rv;
+	
 	/* Get the length of the result */
 	rv = (args->complete_func) (args->base.handle, args->input, args->n_input, NULL, &args->n_result);
 	if (rv != CKR_OK)
@@ -952,13 +1172,33 @@
 	return (args->complete_func) (args->base.handle, args->input, args->n_input, args->result, &args->n_result);
 }
 
+static gboolean
+complete_crypt (Crypt *args, CK_RV result)
+{
+	if (!authenticate_complete (&args->auth, &args->base, result))
+		return FALSE;
+	
+	/* Call is complete */
+	return TRUE;
+}
+
+static void
+free_crypt (Crypt *args)
+{
+	g_free (args->input);
+	g_free (args->mech.pParameter);
+	g_free (args->result);
+	g_free (args);
+}
+
 static guchar*
 crypt_sync (GP11Session *self, GP11Object *key, GP11Mechanism *mech_args, const guchar *input, 
             gsize n_input, gsize *n_result, GCancellable *cancellable, GError **err,
             CK_C_EncryptInit init_func, CK_C_Encrypt complete_func)
 {
 	Crypt args;
-	
+	GP11Slot *slot;
+
 	g_return_val_if_fail (GP11_IS_OBJECT (key), NULL);
 	g_return_val_if_fail (mech_args, NULL);
 	g_return_val_if_fail (init_func, NULL);
@@ -979,11 +1219,16 @@
 	args.init_func = init_func;
 	args.complete_func = complete_func;
 	
-	if (!_gp11_call_sync (self, perform_crypt, &args, cancellable, err)) {
+	slot = gp11_session_get_slot (self);
+	authenticate_init (&args.auth, slot, key);
+	g_object_unref (slot);
+	
+	if (!_gp11_call_sync (self, perform_crypt, complete_crypt, &args, cancellable, err)) {
 		g_free (args.result);
 		return NULL;
 	}
 	
+	*n_result = args.n_result;
 	return args.result;
 }
 
@@ -992,7 +1237,8 @@
              gsize n_input, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data,
              CK_C_EncryptInit init_func, CK_C_Encrypt complete_func)
 {
-	Crypt *args = _gp11_call_async_prep (self, self, perform_crypt, sizeof (*args), free_crypt);
+	Crypt *args = _gp11_call_async_prep (self, self, perform_crypt, complete_crypt, sizeof (*args), free_crypt);
+	GP11Slot *slot;
 
 	g_return_if_fail (GP11_IS_OBJECT (key));
 	g_return_if_fail (mech_args);
@@ -1013,7 +1259,11 @@
 	args->init_func = init_func;
 	args->complete_func = complete_func;
 	
-	_gp11_call_async_go (args, cancellable, callback, user_data);
+	slot = gp11_session_get_slot (self);
+	authenticate_init (&args->auth, slot, key);
+	g_object_unref (slot);
+	
+	_gp11_call_async_ready_go (args, cancellable, callback, user_data);
 }
 
 static guchar*
@@ -1022,7 +1272,7 @@
 	Crypt *args;
 	guchar *res;
 	
-	if (!_gp11_call_basic_finish (self, result, err))
+	if (!_gp11_call_basic_finish (result, err))
 		return NULL;
 	args = _gp11_call_arguments (result, Crypt);
 	
@@ -1035,6 +1285,10 @@
 	return res;
 }
 
+/* --------------------------------------------------------------------------------------------------
+ * ENCRYPT
+ */
+
 guchar*
 gp11_session_encrypt (GP11Session *self, GP11Object *key, gulong mech, const guchar *input, 
                       gsize n_input, gsize *n_result, GError **err)
@@ -1049,13 +1303,17 @@
                            GCancellable *cancellable, GError **err)
 {
 	GP11Module *module = NULL;
+	CK_FUNCTION_LIST_PTR funcs;
 	guchar *ret;
 	
 	g_object_get (self, "module", &module, NULL);
 	g_return_val_if_fail (module != NULL, NULL);
+	
+	funcs = gp11_module_get_function_list (module);
+	g_return_val_if_fail (module != NULL, NULL);
 
 	ret = crypt_sync (self, key, mech_args, input, n_input, n_result, cancellable, err, 
-	                  module->funcs->C_EncryptInit, module->funcs->C_Encrypt);
+	                  funcs->C_EncryptInit, funcs->C_Encrypt);
 	
 	g_object_unref (module);
 	return ret;
@@ -1067,11 +1325,16 @@
                             GAsyncReadyCallback callback, gpointer user_data)
 {
 	GP11Module *module = NULL;
+	CK_FUNCTION_LIST_PTR funcs;
+	
 	g_object_get (self, "module", &module, NULL);
 	g_return_if_fail (module != NULL);
 
+	funcs = gp11_module_get_function_list (module);
+	g_return_if_fail (module != NULL);
+
 	crypt_async (self, key, mech_args, input, n_input, cancellable, callback, user_data,
-	             module->funcs->C_EncryptInit, module->funcs->C_Encrypt);
+	             funcs->C_EncryptInit, funcs->C_Encrypt);
 	
 	g_object_unref (module);
 }
@@ -1083,6 +1346,10 @@
 	return crypt_finish (self, result, n_result, err);
 }
 
+/* --------------------------------------------------------------------------------------------------
+ * DECRYPT
+ */
+
 guchar*
 gp11_session_decrypt (GP11Session *self, GP11Object *key, gulong mech_type, const guchar *input,
                       gsize n_input, gsize *n_result, GError **err)
@@ -1097,13 +1364,17 @@
                            GCancellable *cancellable, GError **err)
 {
 	GP11Module *module = NULL;
+	CK_FUNCTION_LIST_PTR funcs;
 	guchar *ret;
 	
 	g_object_get (self, "module", &module, NULL);
 	g_return_val_if_fail (module != NULL, NULL);
+	
+	funcs = gp11_module_get_function_list (module);
+	g_return_val_if_fail (module != NULL, NULL);
 
 	ret = crypt_sync (self, key, mech_args, input, n_input, n_result, cancellable, err,
-	                  module->funcs->C_DecryptInit, module->funcs->C_Decrypt);
+	                  funcs->C_DecryptInit, funcs->C_Decrypt);
 	g_object_unref (module);
 	return ret;
 }
@@ -1114,11 +1385,16 @@
                             GAsyncReadyCallback callback, gpointer user_data)
 {
 	GP11Module *module = NULL;
+	CK_FUNCTION_LIST_PTR funcs;
+	
 	g_object_get (self, "module", &module, NULL);
 	g_return_if_fail (module != NULL);
+	
+	funcs = gp11_module_get_function_list (module);
+	g_return_if_fail (module != NULL);
 
 	crypt_async (self, key, mech_args, input, n_input, cancellable, callback, user_data,
-	             module->funcs->C_DecryptInit, module->funcs->C_Decrypt);
+	             funcs->C_DecryptInit, funcs->C_Decrypt);
 	g_object_unref (module);
 }
 
@@ -1129,6 +1405,10 @@
 	return crypt_finish (self, result, n_result, err);
 }
 
+/* --------------------------------------------------------------------------------------------------
+ * SIGN
+ */
+
 guchar*
 gp11_session_sign (GP11Session *self, GP11Object *key, gulong mech_type, const guchar *input, 
                    gsize n_input, gsize *n_result, GError **err)
@@ -1143,13 +1423,17 @@
                         GCancellable *cancellable, GError **err)
 {
 	GP11Module *module = NULL;
+	CK_FUNCTION_LIST_PTR funcs;
 	guchar *ret;
 	
 	g_object_get (self, "module", &module, NULL);
 	g_return_val_if_fail (module != NULL, NULL);
+	
+	funcs = gp11_module_get_function_list (module);
+	g_return_val_if_fail (module != NULL, NULL);
 
-	return crypt_sync (self, key, mech_args, input, n_input, n_result, cancellable, err,
-	                   module->funcs->C_SignInit, module->funcs->C_Sign);
+	ret = crypt_sync (self, key, mech_args, input, n_input, n_result, cancellable, err,
+	                  funcs->C_SignInit, funcs->C_Sign);
 	g_object_unref (module);
 	return ret;
 }
@@ -1160,11 +1444,16 @@
                          GAsyncReadyCallback callback, gpointer user_data)
 {
 	GP11Module *module = NULL;
+	CK_FUNCTION_LIST_PTR funcs;
+	
 	g_object_get (self, "module", &module, NULL);
 	g_return_if_fail (module != NULL);
+	
+	funcs = gp11_module_get_function_list (module);
+	g_return_if_fail (module != NULL);
 
 	crypt_async (self, key, mech_args, input, n_input, cancellable, callback, user_data,
-	             module->funcs->C_SignInit, module->funcs->C_Sign);
+	             funcs->C_SignInit, funcs->C_Sign);
 	g_object_unref (module);
 }
 
@@ -1175,10 +1464,16 @@
 	return crypt_finish (self, result, n_result, err);	
 }
 
+/* --------------------------------------------------------------------------------------------------
+ * VERIFY
+ */
 
 typedef struct _Verify {
 	GP11Arguments base;
 	
+	/* Authenticator */
+	Authenticate auth;
+
 	/* Input */
 	CK_OBJECT_HANDLE key;
 	CK_MECHANISM mech;
@@ -1189,14 +1484,6 @@
 	
 } Verify;
 
-static void
-free_verify (Verify *args)
-{
-	g_free (args->input);
-	g_free (args->signature);
-	g_free (args->mech.pParameter);
-}
-
 static CK_RV
 perform_verify (Verify *args)
 {
@@ -1207,11 +1494,34 @@
 	if (rv != CKR_OK)
 		return rv;
 	
+	rv = authenticate_perform (&args->auth, &args->base);
+	if (rv != CKR_OK)
+		return rv;
+	
 	/* Do the actual verify */
 	return (args->base.pkcs11->C_Verify) (args->base.handle, args->input, args->n_input, 
 	                                      args->signature, args->n_signature);
 }
 
+static gboolean
+complete_verify (Verify *args, CK_RV result)
+{
+	if (!authenticate_complete (&args->auth, &args->base, result))
+		return FALSE;
+	
+	/* Call is complete */
+	return TRUE;
+}
+
+static void
+free_verify (Verify *args)
+{
+	g_free (args->input);
+	g_free (args->signature);
+	g_free (args->mech.pParameter);
+	g_free (args);
+}
+
 gboolean
 gp11_session_verify (GP11Session *self, GP11Object *key, gulong mech_type, const guchar *input,
                      gsize n_input, const guchar *signature, gsize n_signature, GError **err)
@@ -1227,6 +1537,7 @@
                           gsize n_signature, GCancellable *cancellable, GError **err)
 {
 	Verify args;
+	GP11Slot *slot;
 	
 	g_return_val_if_fail (GP11_IS_OBJECT (key), FALSE);
 	g_return_val_if_fail (mech_args, FALSE);
@@ -1244,8 +1555,12 @@
 	args.n_input = n_input;
 	args.signature = (guchar*)signature;
 	args.n_signature = n_signature;
+	
+	slot = gp11_session_get_slot (self);
+	authenticate_init (&args.auth, slot, key);
+	g_object_unref (slot);
 
-	return _gp11_call_sync (self, perform_verify, &args, cancellable, err);
+	return _gp11_call_sync (self, perform_verify, complete_verify, &args, cancellable, err);
 }
 
 void
@@ -1254,8 +1569,9 @@
                            gsize n_signature, GCancellable *cancellable,
                            GAsyncReadyCallback callback, gpointer user_data)
 {
-	Verify *args = _gp11_call_async_prep (self, self, perform_verify, sizeof (*args), free_verify);
-
+	Verify *args = _gp11_call_async_prep (self, self, perform_verify, complete_verify, sizeof (*args), free_verify);
+	GP11Slot *slot;
+	
 	g_return_if_fail (GP11_IS_OBJECT (key));
 	g_return_if_fail (mech_args);
 	
@@ -1270,15 +1586,18 @@
 	args->input = input && n_input ? g_memdup (input, n_input) : NULL;
 	args->n_input = n_input;
 	args->signature = signature && n_signature ? g_memdup (signature, n_signature) : NULL;
-	args->n_input = n_signature;
+	args->n_signature = n_signature;
+	
+	slot = gp11_session_get_slot (self);
+	authenticate_init (&args->auth, slot, key);
+	g_object_unref (slot);
 	
-	_gp11_call_async_go (args, cancellable, callback, user_data);
+	_gp11_call_async_ready_go (args, cancellable, callback, user_data);
 }
 
 gboolean
 gp11_session_verify_finish (GP11Session *self, GAsyncResult *result, GError **err)
 {
-	return _gp11_call_basic_finish (self, result, err);
+	return _gp11_call_basic_finish (result, err);
 }
 
-#endif /* UNTESTED */

Modified: trunk/gp11/gp11-slot.c
==============================================================================
--- trunk/gp11/gp11-slot.c	(original)
+++ trunk/gp11/gp11-slot.c	Mon Dec 29 06:46:36 2008
@@ -39,10 +39,7 @@
 
 enum {
 	AUTHENTICATE_TOKEN,
-#ifdef UNIMPLEMENTED
-	AUTHENTICATE_KEY,
-	SLOT_EVENT
-#endif
+	AUTHENTICATE_OBJECT,
 	LAST_SIGNAL
 };
 
@@ -324,6 +321,18 @@
  * OBJECT
  */
 
+static gboolean 
+gp11_slot_real_authenticate_token (GP11Slot *self, gchar *label, gchar **password)
+{
+	return FALSE;
+}
+
+static gboolean 
+gp11_slot_real_authenticate_object (GP11Slot *self, GP11Object *object, gchar *label, gchar **password)
+{
+	return FALSE;
+}
+
 static void
 gp11_slot_init (GP11Slot *self)
 {
@@ -432,6 +441,9 @@
 	gobject_class->dispose = gp11_slot_dispose;
 	gobject_class->finalize = gp11_slot_finalize;
 	
+	klass->authenticate_object = gp11_slot_real_authenticate_object;
+	klass->authenticate_token = gp11_slot_real_authenticate_token;
+	
 	g_object_class_install_property (gobject_class, PROP_MODULE,
 		g_param_spec_object ("module", "Module", "PKCS11 Module",
 		                     GP11_TYPE_MODULE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
@@ -450,52 +462,91 @@
 	
 	signals[AUTHENTICATE_TOKEN] = g_signal_new ("authenticate-token", GP11_TYPE_SLOT, 
 			G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GP11SlotClass, authenticate_token),
-			g_signal_accumulator_true_handled, NULL, _gp11_marshal_BOOLEAN__POINTER, 
-			G_TYPE_BOOLEAN, 1, G_TYPE_POINTER);
+			g_signal_accumulator_true_handled, NULL, _gp11_marshal_BOOLEAN__STRING_POINTER, 
+			G_TYPE_BOOLEAN, 2, G_TYPE_STRING, G_TYPE_POINTER);
+
+	signals[AUTHENTICATE_OBJECT] = g_signal_new ("authenticate-object", GP11_TYPE_SLOT, 
+			G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GP11SlotClass, authenticate_object),
+			g_signal_accumulator_true_handled, NULL, _gp11_marshal_BOOLEAN__OBJECT_STRING_POINTER, 
+			G_TYPE_BOOLEAN, 3, G_TYPE_OBJECT, G_TYPE_STRING, G_TYPE_POINTER);
+
 
 	g_type_class_add_private (gobject_class, sizeof (GP11SlotPrivate));
 }
 
 /* ----------------------------------------------------------------------------
- * INTERNAL
+ * INTERNAL AUTHENTICATION
  */
 
-gboolean 
-_gp11_slot_token_authentication (GP11Slot *self, gchar **password)
+
+gboolean
+_gp11_slot_fire_authenticate_token (GP11Slot *self, gchar *label, gchar **password)
 {
 	GP11SlotPrivate *pv = lock_private (self);
-	gboolean emit_signal = FALSE;
-	gboolean ret = FALSE;
-
-	g_return_val_if_fail (GP11_IS_SLOT (self), FALSE);
-	g_return_val_if_fail (password, FALSE);
+	gboolean protected_auth = FALSE;
+	gchar *allocated = NULL;
+	gboolean ret;
+	
+	g_assert (GP11_IS_SLOT (self));
+	g_assert (pv);
 
 	{
-		if (pv->auto_login) {
-			
-			/* 
-			 * If it's a protected authentication path style token, then 
-			 * we don't prompt here, the hardware/software is expected
-			 * to prompt the user in some other way.
-			 */
-			
-			if (!pv->token_info) 
-				pv->token_info = gp11_slot_get_token_info (self);
-
-			if (pv->token_info && (pv->token_info->flags & CKF_PROTECTED_AUTHENTICATION_PATH)) {
-				*password = NULL;
-				ret = TRUE;
-			} else {
-				emit_signal = TRUE;
-			}
+		if (!pv->token_info) 
+			pv->token_info = gp11_slot_get_token_info (self);
+		if (pv->token_info) {
+			protected_auth = (pv->token_info->flags & CKF_PROTECTED_AUTHENTICATION_PATH) ? TRUE : FALSE;
+			if (!label)
+				label = allocated = g_strdup (pv->token_info->label); 
 		}
 	}
 	
 	unlock_private (self, pv);
+	
+	if (protected_auth) {
+		*password = NULL;
+		return TRUE;
+	}
+	
+	g_signal_emit (self, signals[AUTHENTICATE_TOKEN], 0, label, password, &ret);
+	g_free (allocated);
+	return ret;
+}
+
+gboolean
+_gp11_slot_fire_authenticate_object (GP11Slot *self, GP11Object *object,
+                                     gchar *label, gchar **password)
+{
+	gboolean ret;
 
-	if (emit_signal)
-		g_signal_emit (self, signals[AUTHENTICATE_TOKEN], 0, password, &ret);
+	g_assert (GP11_IS_SLOT (self));
+	g_assert (password);
 
+	if (_gp11_slot_is_protected_auth_path (self)) {
+		*password = NULL;
+		return TRUE;
+	}
+	
+	g_signal_emit (self, signals[AUTHENTICATE_OBJECT], 0, object, label, password, &ret);
+	return ret;
+}
+
+gboolean
+_gp11_slot_is_protected_auth_path (GP11Slot *self)
+{
+	GP11SlotPrivate *pv = lock_private (self);
+	gboolean ret;
+
+	g_assert (GP11_IS_SLOT (self));
+	g_assert (pv);
+
+	{
+		if (!pv->token_info) 
+			pv->token_info = gp11_slot_get_token_info (self);
+		ret = (pv->token_info && pv->token_info->flags & CKF_PROTECTED_AUTHENTICATION_PATH);
+	}
+	
+	unlock_private (self, pv);
+	
 	return ret;
 }
 
@@ -941,7 +992,7 @@
                       GError **err)
 {
 	InitToken args = { GP11_ARGUMENTS_INIT, pin, length, label };
-	return _gp11_call_sync (self, perform_init_token, &args, err);
+	return _gp11_call_sync (self, perform_init_token, NULL, &args, err);
 }
 
 void
@@ -950,7 +1001,7 @@
                             GAsyncReadyCallback callback, gpointer user_data)
 {
 	InitToken* args = _gp11_call_async_prep (self, self, perform_init_token, 
-	                                         sizeof (*args));
+	                                         NULL, sizeof (*args));
 	
 	args->pin = pin;
 	args->length = length;
@@ -969,16 +1020,68 @@
 
 typedef struct OpenSession {
 	GP11Arguments base;
+	GP11Slot *slot;
 	gulong flags;
+	gchar *password;
 	CK_SESSION_HANDLE session;
 } OpenSession;
 
 static CK_RV
 perform_open_session (OpenSession *args)
 {
-	return (args->base.pkcs11->C_OpenSession) (args->base.handle, 
-	                                           args->flags | CKF_SERIAL_SESSION, 
-	                                           NULL, NULL, &args->session);
+	CK_SESSION_INFO info;
+	CK_RV rv = CKR_OK;
+	CK_ULONG pin_len;
+	
+	/* Can be called multiple times */
+	
+	/* First step, open session */
+	if (!args->session) {
+		rv = (args->base.pkcs11->C_OpenSession) (args->base.handle, args->flags, 
+		                                         NULL, NULL, &args->session);
+	}
+
+	if (rv != CKR_OK || !gp11_slot_get_auto_login (args->slot))
+		return rv;
+
+	/* Step two, check if session is logged in */
+	rv = (args->base.pkcs11->C_GetSessionInfo) (args->session, &info);
+	if (rv != CKR_OK)
+		return rv;
+	
+	/* Already logged in? */
+	if (info.state != CKS_RO_PUBLIC_SESSION && info.state != CKS_RW_PUBLIC_SESSION)
+		return CKR_OK;
+	
+	/* Try to login */
+	pin_len = args->password ? strlen (args->password) : 0;
+	return (args->base.pkcs11->C_Login) (args->session, CKU_USER, 
+	                                     (CK_UTF8CHAR_PTR)args->password, pin_len);
+}
+
+static gboolean
+complete_open_session (OpenSession *args, CK_RV result)
+{
+	g_free (args->password);
+	args->password = NULL;
+	
+	/* Ask the token for a password */
+	if (gp11_slot_get_auto_login (args->slot) && result == CKR_PIN_INCORRECT) {
+		if (_gp11_slot_fire_authenticate_token (args->slot, NULL, &args->password))
+			return FALSE; /* Call is not complete */
+	}
+	
+	/* Call is complete */
+	return TRUE;
+}
+
+static void
+free_open_session (OpenSession *args)
+{
+	g_assert (!args->password);
+	if (args->slot)
+		g_object_unref (args->slot);
+	g_free (args);
 }
 
 /**
@@ -1038,8 +1141,14 @@
 
 	/* Open a new session */
 	if (session == NULL) {
-		OpenSession args = { GP11_ARGUMENTS_INIT, flags, 0 };
-		if (_gp11_call_sync (self, perform_open_session, &args, cancellable, err))
+		OpenSession args = { GP11_ARGUMENTS_INIT, 0,  };
+		
+		args.slot = self;
+		args.flags = flags;
+		args.password = NULL;
+		args.session = 0;
+		
+		if (_gp11_call_sync (self, perform_open_session, complete_open_session, &args, cancellable, err))
 			session = make_session_object (self, flags, args.session);
 	}
 
@@ -1073,7 +1182,8 @@
 	
 	g_object_ref (self);
 	
-	args =  _gp11_call_async_prep (self, self, perform_open_session, sizeof (*args), NULL);
+	args =  _gp11_call_async_prep (self, self, perform_open_session, complete_open_session, 
+	                               sizeof (*args), free_open_session);
 	
 	pv = lock_private (self);
 
@@ -1081,6 +1191,7 @@
 		/* Try to use a cached session */
 		args->session = pop_session_table (pv, flags);
 		args->flags = flags;
+		args->slot = g_object_ref (self);
 	}
 	
 	unlock_private (self, pv);

Modified: trunk/gp11/gp11.h
==============================================================================
--- trunk/gp11/gp11.h	(original)
+++ trunk/gp11/gp11.h	Mon Dec 29 06:46:36 2008
@@ -257,13 +257,13 @@
                                                                gpointer reserved,
                                                                GError **err);
 
-const gchar*          gp11_module_get_path                    (GP11Module *module);
+const gchar*          gp11_module_get_path                    (GP11Module *self);
 
-CK_FUNCTION_LIST_PTR  gp11_module_get_function_list           (GP11Module *module);
+CK_FUNCTION_LIST_PTR  gp11_module_get_function_list           (GP11Module *self);
 
-GP11ModuleInfo*       gp11_module_get_info                    (GP11Module *module);
+GP11ModuleInfo*       gp11_module_get_info                    (GP11Module *self);
 
-GList*                gp11_module_get_slots                   (GP11Module *module,
+GList*                gp11_module_get_slots                   (GP11Module *self,
                                                                gboolean token_present);
 
 enum {
@@ -347,83 +347,82 @@
 struct _GP11SlotClass {
 	GObjectClass parent;
 
-	gboolean (*authenticate_token) (GP11Slot *slot, gchar **password);
+	gboolean (*authenticate_token) (GP11Slot *self, gchar *label, gchar **password);
 
-#ifdef UNIMPLEMENTED
-	gboolean (*authenticate_key) (GP11Slot *slot, GP11Object *object, 
-	                              gchar **password);
+	gboolean (*authenticate_object) (GP11Slot *self, GP11Object *object, gchar *label, gchar **password);
 
-	void (*slot_event) (GP11Slot *slot);
+#ifdef UNIMPLEMENTED
+	void (*slot_event) (GP11Slot *self);
 #endif
 	
-	gpointer reserved[10];	
+	gpointer reserved[9];	
 };
 
 GType               gp11_slot_get_type                      (void) G_GNUC_CONST;
 
-GP11Module*         gp11_slot_get_module                    (GP11Slot *slot);
+GP11Module*         gp11_slot_get_module                    (GP11Slot *self);
 
-CK_SLOT_ID          gp11_slot_get_handle                    (GP11Slot *slot);
+CK_SLOT_ID          gp11_slot_get_handle                    (GP11Slot *self);
 
-gboolean            gp11_slot_get_reuse_sessions            (GP11Slot *slot);
+gboolean            gp11_slot_get_reuse_sessions            (GP11Slot *self);
 
-void                gp11_slot_set_reuse_sessions            (GP11Slot *slot, 
+void                gp11_slot_set_reuse_sessions            (GP11Slot *self, 
                                                              gboolean reuse);
 
-gboolean            gp11_slot_get_auto_login                (GP11Slot *slot);
+gboolean            gp11_slot_get_auto_login                (GP11Slot *self);
 
-void                gp11_slot_set_auto_login                (GP11Slot *slot, 
+void                gp11_slot_set_auto_login                (GP11Slot *self, 
                                                              gboolean auto_login);
 
-gint                gp11_slot_get_max_pin_length            (GP11Slot *slot);
+gint                gp11_slot_get_max_pin_length            (GP11Slot *self);
 
-GP11SlotInfo*       gp11_slot_get_info                      (GP11Slot *slot);
+GP11SlotInfo*       gp11_slot_get_info                      (GP11Slot *self);
 
-GP11TokenInfo*      gp11_slot_get_token_info                (GP11Slot *slot);
+GP11TokenInfo*      gp11_slot_get_token_info                (GP11Slot *self);
 
-GP11Mechanisms*     gp11_slot_get_mechanisms                (GP11Slot *slot);
+GP11Mechanisms*     gp11_slot_get_mechanisms                (GP11Slot *self);
 
-GP11MechanismInfo*  gp11_slot_get_mechanism_info            (GP11Slot *slot,
+GP11MechanismInfo*  gp11_slot_get_mechanism_info            (GP11Slot *self,
                                                              gulong mech_type);
 
 #if UNIMPLEMENTED
 
-gboolean            gp11_slot_init_token                    (GP11Slot *slot, 
+gboolean            gp11_slot_init_token                    (GP11Slot *self, 
                                                              const guchar *pin,
                                                              gsize length, 
                                                              const gchar *label,
                                                              GError **err);
 
 
-void                gp11_slot_init_token_async              (GP11Slot *slot, 
+void                gp11_slot_init_token_async              (GP11Slot *self, 
                                                              const guchar *pin,
                                                              gsize length, 
                                                              const gchar *label,
                                                              GAsyncReadyCallback callback, 
                                                              gpointer user_data);
 
-gboolean            gp11_slot_init_token_finish             (GP11Slot *slot, 
+gboolean            gp11_slot_init_token_finish             (GP11Slot *self, 
                                                              GAsyncResult *result,
                                                              GError **err);
 
 #endif /* UNIMPLEMENTED */
 
-GP11Session*        gp11_slot_open_session                  (GP11Slot *slot,
+GP11Session*        gp11_slot_open_session                  (GP11Slot *self,
                                                              gulong flags,
                                                              GError **err);
 
-GP11Session*        gp11_slot_open_session_full             (GP11Slot *slot,
+GP11Session*        gp11_slot_open_session_full             (GP11Slot *self,
                                                              gulong flags,
                                                              GCancellable *cancellable,
                                                              GError **err);
 
-void                gp11_slot_open_session_async            (GP11Slot *slot,
+void                gp11_slot_open_session_async            (GP11Slot *self,
                                                              gulong flags,
                                                              GCancellable *cancellable,
                                                              GAsyncReadyCallback callback,
                                                              gpointer user_data);
 
-GP11Session*        gp11_slot_open_session_finish           (GP11Slot *slot,
+GP11Session*        gp11_slot_open_session_finish           (GP11Slot *self,
                                                     	     GAsyncResult *result,
                                                     	     GError **err);
 
@@ -451,12 +450,15 @@
 
 struct _GP11Session {
 	GObject parent;
+	gpointer reserved[4];
 };
 
 struct _GP11SessionClass {
 	GObjectClass parent;
 
 	gboolean (*discard_handle) (GP11Session *session, CK_SESSION_HANDLE handle);
+	
+	gpointer reserved[8];
 };
 
 GType               gp11_session_get_type                   (void) G_GNUC_CONST;
@@ -467,37 +469,37 @@
 
 GP11Slot*           gp11_session_get_slot                   (GP11Session *self);
 
-CK_SESSION_HANDLE   gp11_session_get_handle                 (GP11Session *session);
+CK_SESSION_HANDLE   gp11_session_get_handle                 (GP11Session *self);
 
-CK_SESSION_HANDLE   gp11_session_steal_handle               (GP11Session *session);
+CK_SESSION_HANDLE   gp11_session_steal_handle               (GP11Session *self);
 
-GP11SessionInfo*    gp11_session_get_info                   (GP11Session *session);
+GP11SessionInfo*    gp11_session_get_info                   (GP11Session *self);
 
 #if UNIMPLEMENTED
 
-gboolean            gp11_session_init_pin                   (GP11Session *session, 
+gboolean            gp11_session_init_pin                   (GP11Session *self, 
                                                              const guchar *pin,
                                                              gsize n_pin,
                                                              GError **err);
 
-void                gp11_session_init_pin_async             (GP11Session *session, 
+void                gp11_session_init_pin_async             (GP11Session *self, 
                                                              const guchar *pin,
                                                              gsize n_pin,
                                                              GAsyncReadyCallback callback,
                                                              gpointer user_data);
 
-gboolean            gp11_session_init_pin_finish            (GP11Session *session, 
+gboolean            gp11_session_init_pin_finish            (GP11Session *self, 
                                                              GAsyncResult *result,
                                                              GError **err);
 
-gboolean            gp11_session_set_pin                    (GP11Session *session,
+gboolean            gp11_session_set_pin                    (GP11Session *self,
                                                              const guchar *old_pin,
                                                              gsize n_old_pin,
                                                              const guchar *new_pin,
                                                              gsize n_new_pin,
                                                              GError **err);
 
-void                gp11_session_set_pin_async              (GP11Session *session,
+void                gp11_session_set_pin_async              (GP11Session *self,
                                                              const guchar *old_pin,
                                                              gsize n_old_pin,
                                                              const guchar *new_pin,
@@ -505,55 +507,55 @@
                                                              GAsyncReadyCallback callback,
                                                              gpointer user_data);
 
-gboolean            gp11_session_set_pin_finish             (GP11Session *session,
+gboolean            gp11_session_set_pin_finish             (GP11Session *self,
                                                              GAsyncResult *result,
                                                              GError **err);
 
-guchar*             gp11_session_get_operation_state        (GP11Session *session,
+guchar*             gp11_session_get_operation_state        (GP11Session *self,
                                                              gsize *n_result,
                                                              GError **err);
 
-void                gp11_session_get_operation_state_async  (GP11Session *session,
+void                gp11_session_get_operation_state_async  (GP11Session *self,
                                                              gsize *n_result,
                                                              GAsyncReadyCallback callback,
                                                              gpointer user_data);
 
-guchar*             gp11_session_get_operation_state_finish (GP11Session *session,
+guchar*             gp11_session_get_operation_state_finish (GP11Session *self,
                                                              GAsyncResult *result,
                                                              gsize *n_result,
                                                              GError **err);
 
-gboolean            gp11_session_set_operation_state        (GP11Session *session, 
+gboolean            gp11_session_set_operation_state        (GP11Session *self, 
                                                              const guchar *state,
                                                              gsize n_state,
                                                              GError **err);
 
-void                gp11_session_set_operation_state_async  (GP11Session *session, 
+void                gp11_session_set_operation_state_async  (GP11Session *self, 
                                                              const guchar *state,
                                                              gsize n_state,
                                                              GAsyncReadyCallback callback,
                                                              gpointer user_data);
 
-gboolean            gp11_session_set_operation_state_finish (GP11Session *session, 
+gboolean            gp11_session_set_operation_state_finish (GP11Session *self, 
                                                              GAsyncResult *result,
                                                              GError **err);
 
 #endif /* UNIMPLEMENTED */
 
-gboolean            gp11_session_login                      (GP11Session *session, 
+gboolean            gp11_session_login                      (GP11Session *self, 
                                                              gulong user_type,
                                                              const guchar *pin,
                                                              gsize n_pin,
                                                              GError **err);
 
-gboolean            gp11_session_login_full                 (GP11Session *session, 
+gboolean            gp11_session_login_full                 (GP11Session *self, 
                                                              gulong user_type,
                                                              const guchar *pin,
                                                              gsize n_pin,
                                                              GCancellable *cancellable,
                                                              GError **err);
 
-void                gp11_session_login_async                (GP11Session *session, 
+void                gp11_session_login_async                (GP11Session *self, 
                                                              gulong user_type,
                                                              const guchar *pin,
                                                              gsize n_pin,
@@ -561,136 +563,133 @@
                                                              GAsyncReadyCallback callback,
                                                              gpointer user_data);
 
-gboolean            gp11_session_login_finish               (GP11Session *session, 
+gboolean            gp11_session_login_finish               (GP11Session *self, 
                                                              GAsyncResult *result,
                                                              GError **err);
 
-gboolean            gp11_session_logout                     (GP11Session *session,
+gboolean            gp11_session_logout                     (GP11Session *self,
                                                              GError **err);
 
-gboolean            gp11_session_logout_full                (GP11Session *session,
+gboolean            gp11_session_logout_full                (GP11Session *self,
                                                              GCancellable *cancellable,
                                                              GError **err);
 
-void                gp11_session_logout_async               (GP11Session *session,
+void                gp11_session_logout_async               (GP11Session *self,
                                                              GCancellable *cancellable,
                                                              GAsyncReadyCallback callback,
                                                              gpointer user_data);
 
-gboolean            gp11_session_logout_finish              (GP11Session *session,
+gboolean            gp11_session_logout_finish              (GP11Session *self,
                                                              GAsyncResult *result,
                                                              GError **err);
 
-GP11Object*         gp11_session_create_object              (GP11Session *session, 
+GP11Object*         gp11_session_create_object              (GP11Session *self, 
                                                              GError **err, 
                                                              ...); 
 
-GP11Object*         gp11_session_create_object_full         (GP11Session *session,
+GP11Object*         gp11_session_create_object_full         (GP11Session *self,
                                                              GP11Attributes *attrs,
                                                              GCancellable *cancellable,
                                                              GError **err); 
 
-void                gp11_session_create_object_async        (GP11Session *session,
+void                gp11_session_create_object_async        (GP11Session *self,
                                                              GP11Attributes *attrs,
                                                              GCancellable *cancellable,
                                                              GAsyncReadyCallback callback,
                                                              gpointer user_data);
 
-GP11Object*         gp11_session_create_object_finish       (GP11Session *session, 
+GP11Object*         gp11_session_create_object_finish       (GP11Session *self, 
                                                              GAsyncResult *result,
                                                              GError **err); 
 
-GList*              gp11_session_find_objects               (GP11Session *session,
+GList*              gp11_session_find_objects               (GP11Session *self,
                                                              GError **err,
                                                              ...); 
 
-GList*              gp11_session_find_objects_full          (GP11Session *session,
+GList*              gp11_session_find_objects_full          (GP11Session *self,
                                                              GP11Attributes *attrs,
                                                              GCancellable *cancellable,
                                                              GError **err); 
 
-void                gp11_session_find_objects_async         (GP11Session *session,
+void                gp11_session_find_objects_async         (GP11Session *self,
                                                              GP11Attributes *attrs,
                                                              GCancellable *cancellable,
                                                              GAsyncReadyCallback callback,
                                                              gpointer user_data); 
 
-GList*              gp11_session_find_objects_finish        (GP11Session *session,
+GList*              gp11_session_find_objects_finish        (GP11Session *self,
                                                              GAsyncResult *result,
                                                              GError **err); 
 
 #if UNIMPLEMENTED
 
-GP11Object*         gp11_session_generate_key               (GP11Session *session,
+GP11Object*         gp11_session_generate_key               (GP11Session *self,
                                                              GP11Mechanism *mechanism,
                                                              GError **err,
                                                              ...);
 
-void                gp11_session_generate_key_async         (GP11Session *session,
+void                gp11_session_generate_key_async         (GP11Session *self,
                                                              GP11Mechanism *mechanism,
                                                              GAsyncReadyCallback callback,
                                                              gpointer user_data,
                                                              ...);
 
-GP11Object*         gp11_session_generate_key_finish        (GP11Session *session,
+GP11Object*         gp11_session_generate_key_finish        (GP11Session *self,
                                                              GAsyncResult *result,
                                                              GError **err,
                                                              ...);
 
-gboolean            gp11_session_generate_key_pair          (GP11Session *session,
+gboolean            gp11_session_generate_key_pair          (GP11Session *self,
                                                              GP11Mechanism *mechanism,
                                                              GP11Object **public_key,
                                                              GP11Object **private_key,
                                                              GError **err,
                                                              ...);
 
-void                gp11_session_generate_key_pair_async    (GP11Session *session,
+void                gp11_session_generate_key_pair_async    (GP11Session *self,
                                                              GP11Mechanism *mechanism,
                                                              GAsyncReadyCallback callback,
                                                              gpointer user_data,
                                                              ...);
 
-gboolean            gp11_session_generate_key_pair_finish   (GP11Session *session,
+gboolean            gp11_session_generate_key_pair_finish   (GP11Session *self,
                                                              GAsyncResult *result,
                                                              GP11Object **public_key,
                                                              GP11Object **private_key,
                                                              GError **err,
                                                              ...);
 
-gboolean            gp11_session_seed_random                (GP11Session *session,
+gboolean            gp11_session_seed_random                (GP11Session *self,
                                                              const guchar *seed,
                                                              gsize n_seed,
                                                              GError **err);
 
-void                gp11_session_seed_random_async          (GP11Session *session,
+void                gp11_session_seed_random_async          (GP11Session *self,
                                                              const guchar *seed,
                                                              gsize n_seed,
                                                              GAsyncReadyCallback callback,
                                                              gpointer user_data);
 
-gboolean            gp11_session_seed_random_finish         (GP11Session *session,
+gboolean            gp11_session_seed_random_finish         (GP11Session *self,
                                                              GAsyncResult *result,
                                                              GError **err);
 
-guchar*             gp11_session_generate_random            (GP11Session *session,
+guchar*             gp11_session_generate_random            (GP11Session *self,
                                                              gsize n_random,
                                                              GError **err);
 
-void                gp11_session_generate_random_async      (GP11Session *session,
+void                gp11_session_generate_random_async      (GP11Session *self,
                                                              gsize n_random,
                                                              GAsyncReadyCallback callback,
                                                              gpointer user_data);
 
-guchar*             gp11_session_generate_random_finish     (GP11Session *session,
+guchar*             gp11_session_generate_random_finish     (GP11Session *self,
                                                              GAsyncResult *result,
                                                              GError **err);
 
-
 #endif /* UNIMPLEMENTED */
 
-#if UNTESTED 
-
-guchar*             gp11_session_encrypt                     (GP11Session *session,
+guchar*             gp11_session_encrypt                     (GP11Session *self,
                                                               GP11Object *key,
                                                               gulong mech,
                                                               const guchar *input,
@@ -698,7 +697,7 @@
                                                               gsize *n_result,
                                                               GError **err);
 
-guchar*             gp11_session_encrypt_full                (GP11Session *session,
+guchar*             gp11_session_encrypt_full                (GP11Session *self,
                                                               GP11Object *key,
                                                               GP11Mechanism *mech_args,
                                                               const guchar *input,
@@ -707,7 +706,7 @@
                                                               GCancellable *cancellable,
                                                               GError **err);
 
-void                gp11_session_encrypt_async               (GP11Session *session,
+void                gp11_session_encrypt_async               (GP11Session *self,
                                                               GP11Object *key,
                                                               GP11Mechanism *mech_args,
                                                               const guchar *input,
@@ -716,37 +715,34 @@
                                                               GAsyncReadyCallback callback,
                                                               gpointer user_data);
 
-guchar*             gp11_session_encrypt_finish              (GP11Session *session,
+guchar*             gp11_session_encrypt_finish              (GP11Session *self,
                                                               GAsyncResult *result,
                                                               gsize *n_result,
                                                               GError **err);
 
-#endif /* UNTESTED */
-
 #if UNIMPLEMENTED
 
-GP11Processor*      gp11_session_batch_encrypt               (GP11Session *session,
+GP11Processor*      gp11_session_batch_encrypt               (GP11Session *self,
                                                               GP11Object *key,
                                                               GP11Mechanism *mech_args,
                                                               GCancellable *cancellable,
                                                               GError **err);
 
-void                gp11_session_batch_encrypt_async         (GP11Session *session,
+void                gp11_session_batch_encrypt_async         (GP11Session *self,
                                                               GP11Object *key,
                                                               GP11Mechanism *mech_args,
                                                               GCancellable *cancellable,
                                                               GAsyncReadyCallback callback,
                                                               gpointer user_data);
 
-GP11Processor*      gp11_session_batch_encrypt_finish        (GP11Session *session,
+GP11Processor*      gp11_session_batch_encrypt_finish        (GP11Session *self,
                                                               GP11Object *key,
                                                               GAsyncResult *result,
                                                               GError **err);
 
 #endif /* UNIMPLEMENTED */
 
-#if UNTESTED
-guchar*             gp11_session_decrypt                     (GP11Session *session,
+guchar*             gp11_session_decrypt                     (GP11Session *self,
                                                               GP11Object *key,
                                                               gulong mech_type,
                                                               const guchar *input,
@@ -754,7 +750,7 @@
                                                               gsize *n_result,
                                                               GError **err);
 
-guchar*             gp11_session_decrypt_full                (GP11Session *session,
+guchar*             gp11_session_decrypt_full                (GP11Session *self,
                                                               GP11Object *key,
                                                               GP11Mechanism *mech_args,
                                                               const guchar *input,
@@ -763,7 +759,7 @@
                                                               GCancellable *cancellable,
                                                               GError **err);
 
-void                gp11_session_decrypt_async               (GP11Session *session,
+void                gp11_session_decrypt_async               (GP11Session *self,
                                                               GP11Object *key,
                                                               GP11Mechanism *mech_args,
                                                               const guchar *input,
@@ -772,40 +768,38 @@
                                                               GAsyncReadyCallback callback,
                                                               gpointer user_data);
 
-guchar*             gp11_session_decrypt_finish              (GP11Session *session,
+guchar*             gp11_session_decrypt_finish              (GP11Session *self,
                                                               GAsyncResult *result,
                                                               gsize *n_result,
                                                               GError **err);
 
-#endif /* UNTESTED */
-
 #if UNIMPLEMENTED
 
-GP11Processor*      gp11_session_batch_decrypt               (GP11Session *session,
+GP11Processor*      gp11_session_batch_decrypt               (GP11Session *self,
                                                               GP11Object *key,
                                                               GP11Mechanism *mech_args,
                                                               GCancellable *cancellable,
                                                               GError **err);
 
-void                gp11_session_batch_decrypt_async         (GP11Session *session,
+void                gp11_session_batch_decrypt_async         (GP11Session *self,
                                                               GP11Object *key,
                                                               GP11Mechanism *mech_args,
                                                               GCancellable *cancellable,
                                                               GAsyncReadyCallback callback,
                                                               gpointer user_data);
 
-GP11Processor*      gp11_session_batch_decrypt_finish        (GP11Session *session,
+GP11Processor*      gp11_session_batch_decrypt_finish        (GP11Session *self,
                                                               GAsyncResult *result,
                                                               GError **err);
 
-guchar*             gp11_session_digest                      (GP11Session *session,
+guchar*             gp11_session_digest                      (GP11Session *self,
                                                               gulong mech_type,
                                                               const guchar *input,
                                                               gsize n_input,
                                                               gsize *n_result,
                                                               GError **err);
 
-guchar*             gp11_session_digest_full                 (GP11Session *session,
+guchar*             gp11_session_digest_full                 (GP11Session *self,
                                                               GP11Mechanism *mech_args,
                                                               const guchar *input,
                                                               gsize n_input,
@@ -813,7 +807,7 @@
                                                               GCancellable *cancellable,
                                                               GError **err);
 
-void                gp11_session_digest_async                (GP11Session *session,
+void                gp11_session_digest_async                (GP11Session *self,
                                                               GP11Mechanism *mech_args,
                                                               const guchar *input,
                                                               gsize n_input,
@@ -821,34 +815,34 @@
                                                               GAsyncReadyCallback callback,
                                                               gpointer user_data);
 
-guchar*             gp11_session_digest_finish               (GP11Session *session,
+guchar*             gp11_session_digest_finish               (GP11Session *self,
                                                               GAsyncResult *result,
                                                               gsize *n_result,
                                                               GError **err);
 
-GP11Processor*      gp11_session_batch_digest	             (GP11Session *session,
+GP11Processor*      gp11_session_batch_digest	             (GP11Session *self,
                                                               GP11Mechanism *mech_args,
                                                               GCancellable *cancellable,
                                                               GError **err);
 
-void                gp11_session_batch_digest_async          (GP11Session *session,
+void                gp11_session_batch_digest_async          (GP11Session *self,
                                                               GP11Mechanism *mech_args,
                                                               GCancellable *cancellable,
                                                               GAsyncReadyCallback callback,
                                                               gpointer user_data);
 
-GP11Processor*      gp11_session_batch_digest_finish         (GP11Session *session,
+GP11Processor*      gp11_session_batch_digest_finish         (GP11Session *self,
                                                               GAsyncResult *result,
                                                               GError **err);
 
-GP11Processor*      gp11_session_batch_digest_encrypt        (GP11Session *session,
+GP11Processor*      gp11_session_batch_digest_encrypt        (GP11Session *self,
                                                               GP11Object *key,
                                                               GP11Mechanism *digest_mech,
                                                               GP11Mechanism *encrypt_mech,
                                                               GCancellable *cancellable,
                                                               GError **err);
 
-void                gp11_session_batch_digest_encrypt_async  (GP11Session *session,
+void                gp11_session_batch_digest_encrypt_async  (GP11Session *self,
                                                               GP11Object *key,
                                                               GP11Mechanism *digest_mech,
                                                               GP11Mechanism *encrypt_mech,
@@ -856,18 +850,18 @@
                                                               GAsyncReadyCallback callback,
                                                               gpointer user_data);
 
-GP11Processor*      gp11_session_batch_digest_encrypt_finish (GP11Session *session,
+GP11Processor*      gp11_session_batch_digest_encrypt_finish (GP11Session *self,
                                                               GAsyncResult *result,
                                                               GError **err);
 
-GP11Processor*      gp11_session_batch_digest_decrypt        (GP11Session *session,
+GP11Processor*      gp11_session_batch_digest_decrypt        (GP11Session *self,
                                                               GP11Object *key,
                                                               GP11Mechanism *digest_mech,
                                                               GP11Mechanism *decrypt_mech,
                                                               GCancellable *cancellable,
                                                               GError **err);
 
-void                gp11_session_batch_digest_decrypt_async  (GP11Session *session,
+void                gp11_session_batch_digest_decrypt_async  (GP11Session *self,
                                                               GP11Object *key,
                                                               GP11Mechanism *digest_mech,
                                                               GP11Mechanism *decrypt_mech,
@@ -875,18 +869,18 @@
                                                               GAsyncReadyCallback callback,
                                                               gpointer user_data);
 
-GP11Processor*      gp11_session_batch_digest_decrypt_finish (GP11Session *session,
+GP11Processor*      gp11_session_batch_digest_decrypt_finish (GP11Session *self,
                                                               GAsyncResult *result,
                                                               GError **err);
 
-GP11Processor*      gp11_session_batch_decrypt_verify        (GP11Session *session,
+GP11Processor*      gp11_session_batch_decrypt_verify        (GP11Session *self,
                                                               GP11Object *key,
                                                               GP11Mechanism *decrypt_mech,
                                                               GP11Mechanism *verify_mech,
                                                               GCancellable *cancellable,
                                                               GError **err);
 
-void                gp11_session_batch_decrypt_verify_async  (GP11Session *session,
+void                gp11_session_batch_decrypt_verify_async  (GP11Session *self,
                                                               GP11Object *key,
                                                               GP11Mechanism *decrypt_mech,
                                                               GP11Mechanism *verify_mech,
@@ -894,15 +888,13 @@
                                                               GAsyncReadyCallback callback,
                                                               gpointer user_data);
 
-GP11Processor*      gp11_session_batch_decrypt_verify_finish (GP11Session *session,
+GP11Processor*      gp11_session_batch_decrypt_verify_finish (GP11Session *self,
                                                               GAsyncResult *result,
                                                               GError **err);
 
 #endif /* UNIMPLEMENTED */
 
-#if UNTESTED 
-
-guchar*             gp11_session_sign                        (GP11Session *session,
+guchar*             gp11_session_sign                        (GP11Session *self,
                                                               GP11Object *key,
                                                               gulong mech_type,
                                                               const guchar *input,
@@ -910,7 +902,7 @@
                                                               gsize *n_result,
                                                               GError **err);
 
-guchar*             gp11_session_sign_full                   (GP11Session *session,
+guchar*             gp11_session_sign_full                   (GP11Session *self,
                                                               GP11Object *key,
                                                               GP11Mechanism *mech_args,
                                                               const guchar *input,
@@ -919,7 +911,7 @@
                                                               GCancellable *cancellable,
                                                               GError **err);
 
-void                gp11_session_sign_async                  (GP11Session *session,
+void                gp11_session_sign_async                  (GP11Session *self,
                                                               GP11Object *key,
                                                               GP11Mechanism *mech_args,
                                                               const guchar *input,
@@ -928,40 +920,38 @@
                                                               GAsyncReadyCallback callback,
                                                               gpointer user_data);
 
-guchar*             gp11_session_sign_finish                 (GP11Session *session,
+guchar*             gp11_session_sign_finish                 (GP11Session *self,
                                                               GAsyncResult *result,
                                                               gsize *n_result,
                                                               GError **err);
 
-#endif /* UNTESTED */
-
 #if UNIMPLEMENTED
 
-GP11Processor*      gp11_session_batch_sign                  (GP11Session *session,
+GP11Processor*      gp11_session_batch_sign                  (GP11Session *self,
                                                               GP11Object *key,
                                                               GP11Mechanism *mech_args,
                                                               GCancellable *cancellable,
                                                               GError **err);
 
-void                gp11_session_batch_sign_async            (GP11Session *session,
+void                gp11_session_batch_sign_async            (GP11Session *self,
                                                               GP11Object *key,
                                                               GP11Mechanism *mech_args,
                                                               GCancellable *cancellable,
                                                               GAsyncReadyCallback callback,
                                                               gpointer user_data);
 
-GP11Processor*      gp11_session_batch_sign_finish           (GP11Session *session,
+GP11Processor*      gp11_session_batch_sign_finish           (GP11Session *self,
                                                               GAsyncResult *result,
                                                               GError **err);
 
-GP11Processor*      gp11_session_batch_sign_encrypt          (GP11Session *session,
+GP11Processor*      gp11_session_batch_sign_encrypt          (GP11Session *self,
                                                               GP11Object *key,
                                                               GP11Mechanism *sign_mech,
                                                               GP11Mechanism *encrypt_mech,
                                                               GCancellable *cancellable,
                                                               GError **err);
 
-void                gp11_session_batch_sign_encrypt_async    (GP11Session *session,
+void                gp11_session_batch_sign_encrypt_async    (GP11Session *self,
                                                               GP11Object *key,
                                                               GP11Mechanism *sign_mechanism,
                                                               GP11Mechanism *encrypt_mech,
@@ -969,11 +959,11 @@
                                                               GAsyncReadyCallback callback,
                                                               gpointer user_data);
 
-GP11Processor*      gp11_session_batch_sign_encrypt_finish   (GP11Session *session,
+GP11Processor*      gp11_session_batch_sign_encrypt_finish   (GP11Session *self,
                                                               GAsyncResult *result,
                                                               GError **err);
 
-guchar*             gp11_session_sign_recover                (GP11Session *session,
+guchar*             gp11_session_sign_recover                (GP11Session *self,
                                                               GP11Object *key,
                                                               gulong mech_type,
                                                               const guchar *input,
@@ -981,7 +971,7 @@
                                                               gsize *n_result,
                                                               GError **err);
 
-guchar*             gp11_session_sign_recover_full           (GP11Session *session,
+guchar*             gp11_session_sign_recover_full           (GP11Session *self,
                                                               GP11Object *key,
                                                               GP11Mechanism *mech_args,
                                                               const guchar *input,
@@ -990,7 +980,7 @@
                                                               GCancellable *cancellable,
                                                               GError **err);
 
-void                gp11_session_sign_recover_async          (GP11Session *session,
+void                gp11_session_sign_recover_async          (GP11Session *self,
                                                               GP11Object *key,
                                                               GP11Mechanism *mech_args,
                                                               const guchar *input,
@@ -999,16 +989,14 @@
                                                               GAsyncReadyCallback callback,
                                                               gpointer user_data);
 
-guchar*             gp11_session_sign_recover_finish         (GP11Session *session,
+guchar*             gp11_session_sign_recover_finish         (GP11Session *self,
                                                               GAsyncResult *result,
                                                               gsize *n_result,
                                                               GError **err);
 
 #endif /* UNIMPLEMENTED */
 
-#if UNTESTED 
-
-gboolean            gp11_session_verify                      (GP11Session *session,
+gboolean            gp11_session_verify                      (GP11Session *self,
                                                               GP11Object *key,
                                                               gulong mech_type,
                                                               const guchar *input,
@@ -1017,7 +1005,7 @@
                                                               gsize n_signature,
                                                               GError **err);
 
-gboolean            gp11_session_verify_full                 (GP11Session *session,
+gboolean            gp11_session_verify_full                 (GP11Session *self,
                                                               GP11Object *key,
                                                               GP11Mechanism *mech_args,
                                                               const guchar *input,
@@ -1027,7 +1015,7 @@
                                                               GCancellable *cancellable,
                                                               GError **err);
 
-void                gp11_session_verify_async                (GP11Session *session,
+void                gp11_session_verify_async                (GP11Session *self,
                                                               GP11Object *key,
                                                               GP11Mechanism *mechanism,
                                                               const guchar *input,
@@ -1038,15 +1026,13 @@
                                                               GAsyncReadyCallback callback,
                                                               gpointer user_data);
 
-gboolean            gp11_session_verify_finish               (GP11Session *session,
+gboolean            gp11_session_verify_finish               (GP11Session *self,
                                                               GAsyncResult *result,
                                                               GError **err);
 
-#endif /* UNTESTED */
-
 #if UNIMPLEMENTED
 
-GkrProcessor*       gp11_session_batch_verify                (GP11Session *session,
+GkrProcessor*       gp11_session_batch_verify                (GP11Session *self,
                                                               GP11Object *key,
                                                               GP11Mechanism *mech_type,
                                                               const guchar *input,
@@ -1055,7 +1041,7 @@
                                                               GCancellable *cancellable,
                                                               GError **err);
 
-void                gp11_session_batch_verify_async          (GP11Session *session,
+void                gp11_session_batch_verify_async          (GP11Session *self,
                                                               GP11Object *key,
                                                               GP11Mechanism *mech_args,
                                                               const guchar *input,
@@ -1064,11 +1050,11 @@
                                                               GAsyncReadyCallback callback,
                                                               gpointer user_data);
 
-GkrProcessor*       gp11_session_batch_verify_finish         (GP11Session *session,
+GkrProcessor*       gp11_session_batch_verify_finish         (GP11Session *self,
                                                               GAsyncResult *result,
                                                               GError **err);
 
-guchar*             gp11_session_verify_recover              (GP11Session *session,
+guchar*             gp11_session_verify_recover              (GP11Session *self,
                                                               GP11Object *key,
                                                               gulong mech_type,
                                                               const guchar *input,
@@ -1076,7 +1062,7 @@
                                                               gsize *n_result,
                                                               GError **err);
 
-guchar*             gp11_session_verify_recover_full         (GP11Session *session,
+guchar*             gp11_session_verify_recover_full         (GP11Session *self,
                                                               GP11Object *key,
                                                               GP11Mechanism *mech_args,
                                                               const guchar *input,
@@ -1085,7 +1071,7 @@
                                                               GCancellable *cancellable,
                                                               GError **err);
 
-void                gp11_session_verify_recover_async        (GP11Session *session,
+void                gp11_session_verify_recover_async        (GP11Session *self,
                                                               GP11Object *key,
                                                               GP11Mechanism *mech_args,
                                                               const guchar *input,
@@ -1094,19 +1080,19 @@
                                                               GAsyncReadyCallback callback,
                                                               gpointer user_data);
 
-guchar*             gp11_session_verify_recover_finish       (GP11Session *session,
+guchar*             gp11_session_verify_recover_finish       (GP11Session *self,
                                                               GAsyncResult *result,
                                                               gsize *n_result,
                                                               GError **err);
 
-guchar*             gp11_session_wrap                        (GP11Session *session,
+guchar*             gp11_session_wrap                        (GP11Session *self,
                                                               GP11Object *key,
                                                               gulong mech_type,
                                                               GP11Object *wrapped_key,
                                                               gsize *n_result,
                                                               GError **err);
 
-guchar*             gp11_session_wrap                        (GP11Session *session,
+guchar*             gp11_session_wrap                        (GP11Session *self,
                                                               GP11Object *key,
                                                               GP11Mechanism *mech_args,
                                                               GP11Object *wrapped_key,
@@ -1114,7 +1100,7 @@
                                                               GCancellable *cancellable,
                                                               GError **err);
 
-void                gp11_session_wrap_async                  (GP11Session *session,
+void                gp11_session_wrap_async                  (GP11Session *self,
                                                               GP11Object *key,
                                                               GP11Mechanism *mech_args,
                                                               GP11Object *wrapped_key,
@@ -1122,12 +1108,12 @@
                                                               GAsyncReadyCallback callback,
                                                               gpointer user_data);
 
-guchar*             gp11_session_wrap_finish                 (GP11Session *session,
+guchar*             gp11_session_wrap_finish                 (GP11Session *self,
                                                               GAsyncResult *result,
                                                               gsize *n_result,
                                                               GError **err);
 
-GP11Object*         gp11_session_unwrap                      (GP11Session *session,
+GP11Object*         gp11_session_unwrap                      (GP11Session *self,
                                                               GP11Object *key,
                                                               gulong mech_type,
                                                               const guchar *input,
@@ -1135,7 +1121,7 @@
                                                               GError **err,
                                                               ...);
 
-GP11Object*         gp11_session_unwrap                      (GP11Session *session,
+GP11Object*         gp11_session_unwrap                      (GP11Session *self,
                                                               GP11Object *key,
                                                               GP11Mechanism *mech_args,
                                                               const guchar *input,
@@ -1144,7 +1130,7 @@
                                                               GError **err,
                                                               ...);
 
-void                gp11_session_unwrap_async                (GP11Session *session,
+void                gp11_session_unwrap_async                (GP11Session *self,
                                                               GP11Object *key,
                                                               GP11Mechanism *mech_args,
                                                               const guchar *input,
@@ -1154,24 +1140,24 @@
                                                               gpointer user_data);
                                                               ...);
 
-GP11Object*         gp11_session_unwrap_finish               (GP11Session *session,
+GP11Object*         gp11_session_unwrap_finish               (GP11Session *self,
                                                               GAsyncResult *result,
                                                               GError **err);
 
-GP11Object*         gp11_session_derive                      (GP11Session *session,
+GP11Object*         gp11_session_derive                      (GP11Session *self,
                                                               GP11Object *key,
                                                               gulong mech_type,
                                                               GError **err,
                                                               ...);
 
-GP11Object*         gp11_session_derive_full                 (GP11Session *session,
+GP11Object*         gp11_session_derive_full                 (GP11Session *self,
                                                               GP11Object *key,
                                                               GP11Mechanism *mech_args,
                                                               GCancellable *cancellable,
                                                               GError **err,
                                                               ...);
 
-void                gp11_session_derive_async                (GP11Session *session,
+void                gp11_session_derive_async                (GP11Session *self,
                                                               GP11Object *key,
                                                               GP11Mechanism *mech_args,
                                                               GCancellable *cancellable,
@@ -1179,7 +1165,7 @@
                                                               gpointer user_data);
                                                               ...);
 
-GP11Object*         gp11_session_derive_finish               (GP11Session *session,
+GP11Object*         gp11_session_derive_finish               (GP11Session *self,
                                                               GAsyncResult *result,
                                                               GError **err);
 
@@ -1201,10 +1187,12 @@
 
 struct _GP11Object {
 	GObject parent;
+	gpointer reserved[4];
 };
 
 struct _GP11ObjectClass {
 	GObjectClass parent;
+	gpointer reserved[8];
 };
 
 GType               gp11_object_get_type                    (void) G_GNUC_CONST;
@@ -1217,128 +1205,128 @@
 
 GP11Module*         gp11_object_get_module                  (GP11Object *self);
 
-GP11Slot*           gp11_object_get_slot                    (GP11Object *object);
+GP11Slot*           gp11_object_get_slot                    (GP11Object *self);
 
-CK_OBJECT_HANDLE    gp11_object_get_handle                  (GP11Object *object);
+CK_OBJECT_HANDLE    gp11_object_get_handle                  (GP11Object *self);
 
-GP11Session*        gp11_object_get_session                 (GP11Object *object);
+GP11Session*        gp11_object_get_session                 (GP11Object *self);
 
-void                gp11_object_set_session                 (GP11Object *object,
+void                gp11_object_set_session                 (GP11Object *self,
                                                              GP11Session *session);
 
 #ifdef UNIMPLEMENTED
 
-GP11Object*         gp11_object_copy                        (GP11Object *object,
+GP11Object*         gp11_object_copy                        (GP11Object *self,
                                                              GError **err);
 
-GP11Object*         gp11_object_copy_full                   (GP11Object *object,
+GP11Object*         gp11_object_copy_full                   (GP11Object *self,
                                                              GP11Attributes *additional,
                                                              GCancellable *cancellable,
                                                              GError **err);
 
-void                gp11_object_copy_async                  (GP11Object *object,
+void                gp11_object_copy_async                  (GP11Object *self,
                                                              GP11Attributes *additional,
                                                              GCancellable *cancellable,
                                                              GAsyncReadyCallback callback,
                                                              gpointer user_data);
 
-GP11Object*         gp11_object_copy_finish                 (GP11Object *object,
+GP11Object*         gp11_object_copy_finish                 (GP11Object *self,
                                                              GAsyncResult *result,
                                                              GError **err);
 
 #endif /* UNIMPLEMENTED */
 
-gboolean            gp11_object_destroy                     (GP11Object *object,
+gboolean            gp11_object_destroy                     (GP11Object *self,
                                                              GError **err);
 
-gboolean            gp11_object_destroy_full                (GP11Object *object,
+gboolean            gp11_object_destroy_full                (GP11Object *self,
                                                              GCancellable *cancellable,
                                                              GError **err);
 
-void                gp11_object_destroy_async               (GP11Object *object,
+void                gp11_object_destroy_async               (GP11Object *self,
                                                              GCancellable *cancellable,
                                                              GAsyncReadyCallback callback,
                                                              gpointer user_data);
 
-gboolean            gp11_object_destroy_finish              (GP11Object *object,
+gboolean            gp11_object_destroy_finish              (GP11Object *self,
                                                              GAsyncResult *result,
                                                              GError **err);
 
 #if UNIMPLEMENTED
 
-gssize              gp11_object_get_size                    (GP11Object *object,
+gssize              gp11_object_get_size                    (GP11Object *self,
                                                              GError **err);
 
-gssize              gp11_object_get_size_full               (GP11Object *object,
+gssize              gp11_object_get_size_full               (GP11Object *self,
                                                              GCancellable *cancellable,
                                                              GError **err);
 
-void                gp11_object_get_size_async              (GP11Object *object,
+void                gp11_object_get_size_async              (GP11Object *self,
                                                              GAsyncReadyCallback callback,
                                                              gpointer user_data);
 
-gssize              gp11_object_get_size_finish             (GP11Object *object,
+gssize              gp11_object_get_size_finish             (GP11Object *self,
                                                              GAsyncResult *result,
                                                              GError **err);
 
 #endif /* UNIMPLEMENTED */
 
-gboolean            gp11_object_set                         (GP11Object *object,
+gboolean            gp11_object_set                         (GP11Object *self,
                                                              GError **err,
                                                              ...);
 
-gboolean            gp11_object_set_full                    (GP11Object *object,
+gboolean            gp11_object_set_full                    (GP11Object *self,
                                                              GP11Attributes *attrs,
                                                              GCancellable *cancellable,
                                                              GError **err);
 
-void                gp11_object_set_async                   (GP11Object *object,
+void                gp11_object_set_async                   (GP11Object *self,
                                                              GP11Attributes *attrs,
                                                              GCancellable *cancellable,
                                                              GAsyncReadyCallback callback,
                                                              gpointer user_data);
 
-gboolean            gp11_object_set_finish                  (GP11Object *object,
+gboolean            gp11_object_set_finish                  (GP11Object *self,
                                                              GAsyncResult *result,
                                                              GError **err);
 
-GP11Attributes*     gp11_object_get                         (GP11Object *object,
+GP11Attributes*     gp11_object_get                         (GP11Object *self,
                                                              GError **err,
                                                              ...);
 
-GP11Attributes*     gp11_object_get_full                    (GP11Object *object,
+GP11Attributes*     gp11_object_get_full                    (GP11Object *self,
                                                              const gulong *attr_types,
                                                              gsize n_attr_types,
                                                              GCancellable *cancellable,
                                                              GError **err);
 
-void                gp11_object_get_async                   (GP11Object *object,
+void                gp11_object_get_async                   (GP11Object *self,
                                                              const gulong *attr_types,
                                                              gsize n_attr_types,
                                                              GCancellable *cancellable,
                                                              GAsyncReadyCallback callback,
                                                              gpointer user_data);
 
-GP11Attributes*     gp11_object_get_finish                  (GP11Object *object,
+GP11Attributes*     gp11_object_get_finish                  (GP11Object *self,
                                                              GAsyncResult *result,
                                                              GError **err);
 
-GP11Attribute*      gp11_object_get_one                     (GP11Object *object,
+GP11Attribute*      gp11_object_get_one                     (GP11Object *self,
                                                              gulong attr_type,
                                                              GError **err);
 
-GP11Attribute*      gp11_object_get_one_full                (GP11Object *object,
+GP11Attribute*      gp11_object_get_one_full                (GP11Object *self,
                                                              gulong attr_type,
                                                              GCancellable *cancellable,
                                                              GError **err);
 
-void                gp11_object_get_one_async               (GP11Object *object,
+void                gp11_object_get_one_async               (GP11Object *self,
                                                              gulong attr_type,
                                                              GCancellable *cancellable,
                                                              GAsyncReadyCallback callback,
                                                              gpointer user_data);
 
-GP11Attribute*      gp11_object_get_one_finish              (GP11Object *object,
+GP11Attribute*      gp11_object_get_one_finish              (GP11Object *self,
                                                              GAsyncResult *result,
                                                              GError **err);
 

Modified: trunk/gp11/tests/Makefile.am
==============================================================================
--- trunk/gp11/tests/Makefile.am	(original)
+++ trunk/gp11/tests/Makefile.am	Mon Dec 29 06:46:36 2008
@@ -1,5 +1,6 @@
 UNIT_AUTO = \
 	unit-test-gp11-attributes.c \
+	unit-test-gp11-crypto.c \
 	unit-test-gp11-module.c \
 	unit-test-gp11-object.c \
 	unit-test-gp11-session.c \

Modified: trunk/gp11/tests/gp11-test-module.c
==============================================================================
--- trunk/gp11/tests/gp11-test-module.c	(original)
+++ trunk/gp11/tests/gp11-test-module.c	Mon Dec 29 06:46:36 2008
@@ -1,35 +1,66 @@
 #include "config.h"
 
 #include "gp11.h"
+#include "gp11-test.h"
+
 #include "pkcs11.h"
 
 #include <glib.h>
 
 #include <string.h>
 
+/* 
+ * This is *NOT* how you'd want to implement a PKCS#11 module. This 
+ * fake module simply provides enough for GP11 library to test against.
+ * It doesn't pass any tests, or behave as expected from a PKCS#11 module.
+ */ 
+
 static gboolean initialized = FALSE;
 static gchar *the_pin = NULL;
 
+static gboolean logged_in = FALSE;
+static CK_USER_TYPE user_type = 0;
+
 typedef enum _Operation {
 	OP_FIND = 1,
+	OP_CRYPTO
 } Operation;
 
 typedef struct _Session {
 	CK_SESSION_HANDLE handle;
 	CK_SESSION_INFO info;
-	gboolean logged_in;
-	CK_USER_TYPE user_type;
 	GHashTable *objects;
 
 	Operation operation;
+	
+	/* For find operations */
 	GList *matches;
 	
+	/* For crypto operations */
+	CK_OBJECT_HANDLE crypto_key;
+	CK_ATTRIBUTE_TYPE crypto_method;
+	CK_MECHANISM_TYPE crypto_mechanism;
+	CK_BBOOL want_context_login;
+	
+	/* For 'signing' with CKM_PREFIX */
+	CK_BYTE sign_prefix[128];
+	CK_ULONG n_sign_prefix;	
+	
 } Session;
 
 static guint unique_identifier = 100;
 static GHashTable *the_sessions = NULL;
 static GHashTable *the_objects = NULL;
 
+enum {
+	PRIVATE_KEY_CAPITALIZE = 3,
+	PUBLIC_KEY_CAPITALIZE = 4,
+	PRIVATE_KEY_PREFIX = 5,
+	PUBLIC_KEY_PREFIX = 6
+};
+
+#define SIGNED_PREFIX "signed-prefix:"
+
 /* 
  * This is not a generic test module, it works in concert with the 
  * unit-test-gp11-module.c
@@ -49,6 +80,7 @@
 {
 	GP11Attributes *attrs;
 	CK_C_INITIALIZE_ARGS_PTR args;
+	CK_ULONG value;
 	void *mutex;
 	CK_RV rv;
 	
@@ -97,6 +129,47 @@
 	                              -1);
 	g_hash_table_insert (the_objects, GUINT_TO_POINTER (2), attrs);
 	
+	/* Private capitalize key */
+	value = CKM_CAPITALIZE;
+	attrs = gp11_attributes_newv (CKA_CLASS, GP11_ULONG, CKO_PRIVATE_KEY,
+	                              CKA_LABEL, GP11_STRING, "Private Capitalize Key",
+	                              CKA_ALLOWED_MECHANISMS, sizeof (value), &value,
+	                              CKA_DECRYPT, GP11_BOOLEAN, TRUE,
+	                              CKA_PRIVATE, GP11_BOOLEAN, TRUE,
+	                              -1);
+	g_hash_table_insert (the_objects, GUINT_TO_POINTER (PRIVATE_KEY_CAPITALIZE), attrs);
+
+	/* Public capitalize key */
+	value = CKM_CAPITALIZE;
+	attrs = gp11_attributes_newv (CKA_CLASS, GP11_ULONG, CKO_PUBLIC_KEY,
+	                              CKA_LABEL, GP11_STRING, "Public Capitalize Key",
+	                              CKA_ALLOWED_MECHANISMS, sizeof (value), &value,
+	                              CKA_ENCRYPT, GP11_BOOLEAN, TRUE,
+	                              CKA_PRIVATE, GP11_BOOLEAN, FALSE,
+	                              -1);
+	g_hash_table_insert (the_objects, GUINT_TO_POINTER (PUBLIC_KEY_CAPITALIZE), attrs);
+
+	/* Private prefix key */
+	value = CKM_PREFIX;
+	attrs = gp11_attributes_newv (CKA_CLASS, GP11_ULONG, CKO_PRIVATE_KEY,
+	                              CKA_LABEL, GP11_STRING, "Private prefix key",
+	                              CKA_ALLOWED_MECHANISMS, sizeof (value), &value,
+	                              CKA_SIGN, GP11_BOOLEAN, TRUE,
+	                              CKA_PRIVATE, GP11_BOOLEAN, TRUE,
+	                              CKA_ALWAYS_AUTHENTICATE, GP11_BOOLEAN, TRUE,
+	                              -1);
+	g_hash_table_insert (the_objects, GUINT_TO_POINTER (PRIVATE_KEY_PREFIX), attrs);
+
+	/* Private prefix key */
+	value = CKM_PREFIX;
+	attrs = gp11_attributes_newv (CKA_CLASS, GP11_ULONG, CKO_PUBLIC_KEY,
+	                              CKA_LABEL, GP11_STRING, "Public prefix key",
+	                              CKA_ALLOWED_MECHANISMS, sizeof (value), &value,
+	                              CKA_VERIFY, GP11_BOOLEAN, TRUE,
+	                              CKA_PRIVATE, GP11_BOOLEAN, FALSE,
+	                              -1);
+	g_hash_table_insert (the_objects, GUINT_TO_POINTER (PUBLIC_KEY_PREFIX), attrs);
+	
 	initialized = TRUE;
 	return CKR_OK;
 }
@@ -250,16 +323,14 @@
 
 /* 
  * TWO mechanisms: 
- *  RSA 
- *  DSA
+ *  CKM_CAPITALIZE 
+ *  CKM_PREFIX
  */
 
 static CK_RV
 test_C_GetMechanismList (CK_SLOT_ID slotID, CK_MECHANISM_TYPE_PTR pMechanismList,
                          CK_ULONG_PTR pulCount)
 {
-	
-	
 	g_assert (slotID == TEST_SLOT_ONE && "Invalid slotID");
 	g_assert (pulCount != NULL && "Invalid pulCount");
 	
@@ -274,31 +345,31 @@
 		return CKR_BUFFER_TOO_SMALL;
 	}
 
-	pMechanismList[0] = CKM_RSA_PKCS;
-	pMechanismList[1] = CKM_DSA;
+	pMechanismList[0] = CKM_CAPITALIZE;
+	pMechanismList[1] = CKM_PREFIX;
 	return CKR_OK;
 }
 
-static const CK_MECHANISM_INFO TEST_MECH_RSA = {
+static const CK_MECHANISM_INFO TEST_MECH_CAPITALIZE = {
 	512, 4096, 0
 };
 
-static const CK_MECHANISM_INFO TEST_MECH_DSA = {
+static const CK_MECHANISM_INFO TEST_MECH_PREFIX = {
 	2048, 2048, 0
 };
 
 static CK_RV
 test_C_GetMechanismInfo (CK_SLOT_ID slotID, CK_MECHANISM_TYPE type, 
-                       CK_MECHANISM_INFO_PTR pInfo)
+                         CK_MECHANISM_INFO_PTR pInfo)
 {
 	g_assert (slotID == TEST_SLOT_ONE && "Invalid slotID");
 	g_assert (pInfo != NULL && "Invalid pInfo");
 
-	if (type == CKM_RSA_PKCS) {
-		memcpy (pInfo, &TEST_MECH_RSA, sizeof (*pInfo));
+	if (type == CKM_CAPITALIZE) {
+		memcpy (pInfo, &TEST_MECH_CAPITALIZE, sizeof (*pInfo));
 		return CKR_OK;
-	} else if (type == CKM_DSA) {
-		memcpy (pInfo, &TEST_MECH_DSA, sizeof (*pInfo));
+	} else if (type == CKM_PREFIX) {
+		memcpy (pInfo, &TEST_MECH_PREFIX, sizeof (*pInfo));
 		return CKR_OK;
 	} else {
 		g_assert_not_reached (); /* "Invalid type" */
@@ -329,22 +400,6 @@
 	return CKR_FUNCTION_NOT_SUPPORTED;
 }
 
-#define TEST_RSA_KEY   257
-#define TEST_DSA_KEY   357
-
-#ifdef INCOMPLETE
-
-#define TEST_KEY \
-"(private-key (rsa " \
-"(n  #00B78758D55EBFFAB61D07D0DC49B5309A6F1DA2AE51C275DFC2370959BB81AC0C39093B1C618E396161A0DECEB8768D0FFB14F197B96C3DA14190EE0F20D51315#)" \
-"(e #010001#)" \
-"(d #108BCAC5FDD35812981E6EC5957D98E2AB76E4064C47B861D27C2CC322C50792313C852B4164A035B42D261F1A09F9FFE8F477F9F78FF2EABBDA6BA875C671D7#)" \
-"(p #00C357F11B19A18C66573D25D1E466D9AB8BCDDCDFE0B2E80BD46712C4BEC18EB7#)" \
-"(q #00F0843B90A60EF7034CA4BE80414ED9497CABCC685143B388013FF989CBB0E093#)" \
-"(u #12F2555F52EB56329A991CF0404B51C68AC921AD370A797860F550415FF987BD#)" \
-"))"
-#endif
-
 static CK_RV
 test_C_OpenSession (CK_SLOT_ID slotID, CK_FLAGS flags, CK_VOID_PTR pApplication,
                     CK_NOTIFY Notify, CK_SESSION_HANDLE_PTR phSession)
@@ -467,13 +522,21 @@
 	if (!session)
 		return CKR_SESSION_HANDLE_INVALID;
 	
+	if (!pPin)
+		return CKR_PIN_INCORRECT;
+	
 	g_assert (pPinLen == strlen (the_pin) && "Wrong PIN length");
 	g_assert (strncmp ((gchar*)pPin, the_pin, pPinLen) == 0 && "Wrong PIN");
 	g_assert ((userType == CKU_SO || userType == CKU_USER || userType == CKU_CONTEXT_SPECIFIC) && "Bad user type");
-	g_assert (session->logged_in == FALSE && "Already logged in");
+	g_assert (logged_in == FALSE && "Already logged in");
+	
+	if (userType == CKU_CONTEXT_SPECIFIC) {
+		session->want_context_login = CK_FALSE;
+	} else {
+		logged_in = TRUE;
+		user_type = userType;
+	}
 	
-	session->logged_in = TRUE;
-	session->user_type = userType;
 	return CKR_OK;
 }
 
@@ -487,9 +550,9 @@
 	if (!session)
 		return CKR_SESSION_HANDLE_INVALID;
 
-	g_assert (session->logged_in && "Not logged in");
-	session->logged_in = FALSE;
-	session->user_type = 0;
+	g_assert (logged_in && "Not logged in");
+	logged_in = FALSE;
+	user_type = 0;
 	return CKR_OK;
 }
 
@@ -514,7 +577,7 @@
 		gp11_attributes_add_data (attrs, pTemplate[i].type, pTemplate[i].pValue, pTemplate[i].ulValueLen);
 	
 	if (gp11_attributes_find_boolean (attrs, CKA_PRIVATE, &priv) && priv) {
-		if (!session->logged_in) {
+		if (!logged_in) {
 			gp11_attributes_unref (attrs);
 			return CKR_USER_NOT_LOGGED_IN;
 		}
@@ -560,7 +623,7 @@
 	}
 	
 	if (gp11_attributes_find_boolean (attrs, CKA_PRIVATE, &priv) && priv) {
-		if (!session->logged_in)
+		if (!logged_in)
 			return CKR_USER_NOT_LOGGED_IN;
 	}
 
@@ -577,7 +640,7 @@
 
 static CK_RV
 test_C_GetAttributeValue (CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
-                        CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
+                          CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
 {
 	CK_ATTRIBUTE_PTR result;
 	CK_RV ret = CKR_OK;
@@ -680,10 +743,9 @@
 	if (!session)
 		return CKR_SESSION_HANDLE_INVALID;
 
-	if (session->operation != 0) {
-		g_assert_not_reached (); /* "invalid call to FindObjectsInit" */
-		return CKR_OPERATION_ACTIVE;
-	}
+	/* Starting an operation, cancels any previous one */
+	if (session->operation != 0) 
+		session->operation = 0;
 	
 	session->operation = OP_FIND;
 	
@@ -797,50 +859,71 @@
 test_C_EncryptInit (CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
                     CK_OBJECT_HANDLE hKey)
 {
-#ifdef INCOMPLETE
 	Session *session;
 
 	session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
 	g_assert (session != NULL && "No such session found");
 	if (!session)
 		return CKR_SESSION_HANDLE_INVALID;
-
-	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-	BEGIN_CALL (C_EncryptInit)
-		IN_SESSION (hSession)
-		IN_MECHANISM (pMechanism)
-		IN_HANDLE (hKey)
-	PROCESS_CALL ((hSession, pMechanism, hKey))
-	DONE_CALL
-#else 
-	g_assert_not_reached (); /* "Not yet implemented" */
-	return CKR_FUNCTION_NOT_SUPPORTED;
-#endif
+	
+	/* Starting an operation, cancels any previous one */
+	if (session->operation != 0) 
+		session->operation = 0;
+	
+	g_assert (pMechanism);
+	g_assert (pMechanism->mechanism == CKM_CAPITALIZE);
+	g_assert (hKey == PUBLIC_KEY_CAPITALIZE);
+
+	session->operation = OP_CRYPTO;
+	session->crypto_method = CKA_ENCRYPT;
+	session->crypto_mechanism = CKM_CAPITALIZE;
+	session->crypto_key = hKey;
+	return CKR_OK;
 }
 
 static CK_RV
 test_C_Encrypt (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen,
-              CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen)
+                CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen)
 {
-#ifdef INCOMPLETE
 	Session *session;
+	CK_ULONG i;
 
 	session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
 	g_assert (session != NULL && "No such session found");
 	if (!session)
 		return CKR_SESSION_HANDLE_INVALID;
-
-	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-	BEGIN_CALL (C_Encrypt)
-		IN_SESSION (hSession)
-		IN_BYTE_ARRAY (pData, ulDataLen)
-	PROCESS_CALL ((hSession, pData, ulDataLen, pEncryptedData, pulEncryptedDataLen))
-		OUT_BYTE_ARRAY (pEncryptedData, pulEncryptedDataLen)
-	DONE_CALL
-#else 
-	g_assert_not_reached (); /* "Not yet implemented" */
-	return CKR_FUNCTION_NOT_SUPPORTED;
-#endif
+	
+	if (session->operation != OP_CRYPTO) {
+		g_assert_not_reached (); /* "invalid call to Encrypt" */
+		return CKR_OPERATION_NOT_INITIALIZED;
+	}
+	
+	g_assert (pData);
+	g_assert (pulEncryptedDataLen);
+	g_assert (session->crypto_method == CKA_ENCRYPT);
+	g_assert (session->crypto_mechanism == CKM_CAPITALIZE);
+	g_assert (session->crypto_key == PUBLIC_KEY_CAPITALIZE);
+	
+	if (!pEncryptedData) {
+		*pulEncryptedDataLen = ulDataLen;
+		return CKR_OK;
+	}
+	
+	if (*pulEncryptedDataLen < ulDataLen) {
+		*pulEncryptedDataLen = ulDataLen;
+		return CKR_BUFFER_TOO_SMALL;
+	}
+	
+	for (i = 0; i < ulDataLen; ++i) 
+		pEncryptedData[i] = g_ascii_toupper (pData[i]);
+	*pulEncryptedDataLen = ulDataLen;
+	
+	session->operation = 0;
+	session->crypto_method = 0;
+	session->crypto_mechanism = 0;
+	session->crypto_key = 0;
+	
+	return CKR_OK;
 }
 
 static CK_RV
@@ -864,50 +947,71 @@
 test_C_DecryptInit (CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
                   CK_OBJECT_HANDLE hKey)
 {
-#ifdef INCOMPLETE
 	Session *session;
 
 	session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
 	g_assert (session != NULL && "No such session found");
 	if (!session)
 		return CKR_SESSION_HANDLE_INVALID;
-
-	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-	BEGIN_CALL (C_DecryptInit)
-		IN_SESSION (hSession)
-		IN_MECHANISM (pMechanism)
-		IN_HANDLE (hKey)
-	PROCESS_CALL ((hSession, pMechanism, hKey))
-	DONE_CALL
-#else 
-	g_assert_not_reached (); /* "Not yet implemented" */
-	return CKR_FUNCTION_NOT_SUPPORTED;
-#endif
+	
+	/* Starting an operation, cancels any previous one */
+	if (session->operation != 0) 
+		session->operation = 0;
+	
+	g_assert (pMechanism);
+	g_assert (pMechanism->mechanism == CKM_CAPITALIZE);
+	g_assert (hKey == PRIVATE_KEY_CAPITALIZE);
+
+	session->operation = OP_CRYPTO;
+	session->crypto_method = CKA_DECRYPT;
+	session->crypto_mechanism = CKM_CAPITALIZE;
+	session->crypto_key = hKey;
+	return CKR_OK;
 }
 
 static CK_RV
 test_C_Decrypt (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData,
-              CK_ULONG pulEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
+                CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
 {
-#ifdef INCOMPLETE
 	Session *session;
+	CK_ULONG i;
 
 	session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
 	g_assert (session != NULL && "No such session found");
 	if (!session)
 		return CKR_SESSION_HANDLE_INVALID;
-
-	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-	BEGIN_CALL (C_Decrypt)
-		IN_SESSION (hSession)
-		IN_BYTE_ARRAY (pEncryptedData, pulEncryptedDataLen)
-	PROCESS_CALL ((hSession, pEncryptedData, pulEncryptedDataLen, pData, pulDataLen))
-		OUT_BYTE_ARRAY (pData, pulDataLen)
-	DONE_CALL
-#else 
-	g_assert_not_reached (); /* "Not yet implemented" */
-	return CKR_FUNCTION_NOT_SUPPORTED;
-#endif
+	
+	if (session->operation != OP_CRYPTO) {
+		g_assert_not_reached (); /* "invalid call to Encrypt" */
+		return CKR_OPERATION_NOT_INITIALIZED;
+	}
+	
+	g_assert (pEncryptedData);
+	g_assert (pulDataLen);
+	g_assert (session->crypto_method == CKA_DECRYPT);
+	g_assert (session->crypto_mechanism == CKM_CAPITALIZE);
+	g_assert (session->crypto_key == PRIVATE_KEY_CAPITALIZE);
+	
+	if (!pData) {
+		*pulDataLen = ulEncryptedDataLen;
+		return CKR_OK;
+	}
+	
+	if (*pulDataLen < ulEncryptedDataLen) {
+		*pulDataLen = ulEncryptedDataLen;
+		return CKR_BUFFER_TOO_SMALL;
+	}
+	
+	for (i = 0; i < ulEncryptedDataLen; ++i) 
+		pData[i] = g_ascii_tolower (pEncryptedData[i]);
+	*pulDataLen = ulEncryptedDataLen;
+	
+	session->operation = 0;
+	session->crypto_method = 0;
+	session->crypto_mechanism = 0;
+	session->crypto_key = 0;
+	
+	return CKR_OK;
 }
 
 static CK_RV
@@ -965,40 +1069,92 @@
 
 static CK_RV
 test_C_SignInit (CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
-               CK_OBJECT_HANDLE hKey)
+                 CK_OBJECT_HANDLE hKey)
 {
-#ifdef INCOMPLETE
 	Session *session;
 
 	session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
 	g_assert (session != NULL && "No such session found");
 	if (!session)
 		return CKR_SESSION_HANDLE_INVALID;
-
-	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-#else 
-	g_assert_not_reached (); /* "Not yet implemented" */
-	return CKR_FUNCTION_NOT_SUPPORTED;
-#endif
+	
+	/* Starting an operation, cancels any previous one */
+	if (session->operation != 0) 
+		session->operation = 0;
+	
+	g_assert (pMechanism);
+	g_assert (pMechanism->mechanism == CKM_PREFIX);
+	g_assert (hKey == PRIVATE_KEY_PREFIX);
+
+	session->operation = OP_CRYPTO;
+	session->crypto_method = CKA_SIGN;
+	session->crypto_mechanism = CKM_PREFIX;
+	session->crypto_key = hKey;
+	
+	if (pMechanism->pParameter) {
+		g_assert (pMechanism->ulParameterLen < sizeof (session->sign_prefix));
+		memcpy (session->sign_prefix, pMechanism->pParameter, pMechanism->ulParameterLen);
+		session->n_sign_prefix = pMechanism->ulParameterLen;
+	} else {
+		g_assert (strlen (SIGNED_PREFIX) + 1 < sizeof (session->sign_prefix));
+		strcpy ((gchar*)session->sign_prefix, SIGNED_PREFIX);
+		session->n_sign_prefix = strlen (SIGNED_PREFIX);
+	}
+	
+	/* The private key has CKA_ALWAYS_AUTHENTICATE above */
+	session->want_context_login = CK_TRUE;
+	
+	return CKR_OK;
 }
 
 static CK_RV
 test_C_Sign (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen,
             CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
 {
-#ifdef INCOMPLETE
 	Session *session;
+	CK_ULONG length;
 
 	session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
 	g_assert (session != NULL && "No such session found");
 	if (!session)
 		return CKR_SESSION_HANDLE_INVALID;
-
-	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-#else 
-	g_assert_not_reached (); /* "Not yet implemented" */
-	return CKR_FUNCTION_NOT_SUPPORTED;
-#endif
+	
+	if (session->operation != OP_CRYPTO) {
+		g_assert_not_reached (); /* "invalid call to Encrypt" */
+		return CKR_OPERATION_NOT_INITIALIZED;
+	}
+	
+	if (session->want_context_login)
+		return CKR_USER_NOT_LOGGED_IN;
+	
+	g_assert (pData);
+	g_assert (pulSignatureLen);
+	g_assert (session->crypto_method == CKA_SIGN);
+	g_assert (session->crypto_mechanism == CKM_PREFIX);
+	g_assert (session->crypto_key == PRIVATE_KEY_PREFIX);
+	
+	length = session->n_sign_prefix + ulDataLen;
+	
+	if (!pSignature) {
+		*pulSignatureLen = length;
+		return CKR_OK;
+	}
+	
+	if (*pulSignatureLen < length) {
+		*pulSignatureLen = length;
+		return CKR_BUFFER_TOO_SMALL;
+	}
+	
+	memcpy (pSignature, session->sign_prefix, session->n_sign_prefix);
+	memcpy (pSignature + session->n_sign_prefix, pData, ulDataLen);
+	*pulSignatureLen = length;
+	
+	session->operation = 0;
+	session->crypto_method = 0;
+	session->crypto_mechanism = 0;
+	session->crypto_key = 0;
+	
+	return CKR_OK;
 }
 
 static CK_RV
@@ -1034,52 +1190,76 @@
 
 static CK_RV
 test_C_VerifyInit (CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
-                 CK_OBJECT_HANDLE hKey)
+                   CK_OBJECT_HANDLE hKey)
 {
-#ifdef INCOMPLETE
 	Session *session;
 
 	session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
 	g_assert (session != NULL && "No such session found");
 	if (!session)
 		return CKR_SESSION_HANDLE_INVALID;
-
-	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-	BEGIN_CALL (C_VerifyInit);
-		IN_SESSION (hSession)
-		IN_MECHANISM (pMechanism)
-		IN_HANDLE (hKey)
-	PROCESS_CALL ((hSession, pMechanism, hKey))
-	DONE_CALL
-#else 
-	g_assert_not_reached (); /* "Not yet implemented" */
-	return CKR_FUNCTION_NOT_SUPPORTED;
-#endif
+	
+	/* Starting an operation, cancels any previous one */
+	if (session->operation != 0) 
+		session->operation = 0;
+	
+	g_assert (pMechanism);
+	g_assert (pMechanism->mechanism == CKM_PREFIX);
+	g_assert (hKey == PUBLIC_KEY_PREFIX);
+
+	session->operation = OP_CRYPTO;
+	session->crypto_method = CKA_VERIFY;
+	session->crypto_mechanism = CKM_PREFIX;
+	session->crypto_key = hKey;
+	
+	if (pMechanism->pParameter) {
+		g_assert (pMechanism->ulParameterLen < sizeof (session->sign_prefix));
+		memcpy (session->sign_prefix, pMechanism->pParameter, pMechanism->ulParameterLen);
+		session->n_sign_prefix = pMechanism->ulParameterLen;
+	} else {
+		g_assert (strlen (SIGNED_PREFIX) + 1 < sizeof (session->sign_prefix));
+		strcpy ((gchar*)session->sign_prefix, SIGNED_PREFIX);
+		session->n_sign_prefix = strlen (SIGNED_PREFIX);
+	}
+	
+	return CKR_OK;
 }
 
 static CK_RV
 test_C_Verify (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen,
-             CK_BYTE_PTR pSignature, CK_ULONG pulSignatureLen)
+               CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
 {
-#ifdef INCOMPLETE
 	Session *session;
+	CK_ULONG length;
 
 	session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
 	g_assert (session != NULL && "No such session found");
 	if (!session)
 		return CKR_SESSION_HANDLE_INVALID;
+	
+	if (session->operation != OP_CRYPTO) {
+		g_assert_not_reached (); /* "invalid call to Encrypt" */
+		return CKR_OPERATION_NOT_INITIALIZED;
+	}
+	
+	g_assert (pData);
+	g_assert (pSignature);
+	g_assert (session->crypto_method == CKA_VERIFY);
+	g_assert (session->crypto_mechanism == CKM_PREFIX);
+	g_assert (session->crypto_key == PUBLIC_KEY_PREFIX);
+	
+	length = session->n_sign_prefix + ulDataLen;
+
+	if (ulSignatureLen < length) {
+		g_assert (FALSE);
+		return CKR_SIGNATURE_LEN_RANGE;
+	}
 
-	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-	BEGIN_CALL (C_Verify)
-		IN_SESSION (hSession)
-		IN_BYTE_ARRAY (pData, ulDataLen)
-		IN_BYTE_ARRAY (pSignature, pulSignatureLen)
-	PROCESS_CALL ((hSession, pData, ulDataLen, pSignature, pulSignatureLen))
-	DONE_CALL
-#else 
-	g_assert_not_reached (); /* "Not yet implemented" */
-	return CKR_FUNCTION_NOT_SUPPORTED;
-#endif
+	if (memcmp (pSignature, session->sign_prefix, session->n_sign_prefix) == 0 && 
+	    memcmp (pSignature + session->n_sign_prefix, pData, ulDataLen) == 0)
+		return CKR_OK;
+	
+	return CKR_SIGNATURE_INVALID;
 }
 
 static CK_RV

Modified: trunk/gp11/tests/gp11-test.h
==============================================================================
--- trunk/gp11/tests/gp11-test.h	(original)
+++ trunk/gp11/tests/gp11-test.h	Mon Dec 29 06:46:36 2008
@@ -19,4 +19,19 @@
 #define WAIT_UNTIL(cond) \
 	while(!cond) g_main_context_iteration (NULL, TRUE);
 
+/* 
+ * Some dumb crypto mechanisms for simple testing.
+ * 
+ * CKM_CAPITALIZE (encrypt/decrypt)
+ *     capitalizes to encrypt
+ *     lowercase to decrypt 
+ *
+ * CKM_PREFIX (sign/verify)
+ *     sign prefixes data with key label
+ *     verify unprefixes data with key label. 
+ */
+
+#define CKM_CAPITALIZE    (CKM_VENDOR_DEFINED | 1)
+#define CKM_PREFIX        (CKM_VENDOR_DEFINED | 2)
+
 #endif /*TESTGP11HELPERS_H_*/

Added: trunk/gp11/tests/unit-test-gp11-crypto.c
==============================================================================
--- (empty file)
+++ trunk/gp11/tests/unit-test-gp11-crypto.c	Mon Dec 29 06:46:36 2008
@@ -0,0 +1,313 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "run-auto-test.h"
+
+#include <glib.h>
+
+#include "gp11-test.h"
+
+static GP11Module *module = NULL;
+static GP11Slot *slot = NULL;
+static GP11Session *session = NULL;
+
+DEFINE_SETUP(crypto_session)
+{
+	GError *err = NULL;
+	GList *slots;
+	
+	/* Successful load */
+	module = gp11_module_initialize (".libs/libgp11-test-module.so", NULL, &err);
+	SUCCESS_RES (module, err);
+	
+	slots = gp11_module_get_slots (module, TRUE);
+	g_assert (slots != NULL);
+	
+	slot = GP11_SLOT (slots->data);
+	g_object_ref (slot);
+	gp11_list_unref_free (slots);
+
+	session = gp11_slot_open_session (slot, 0, &err);
+	SUCCESS_RES(session, err); 
+}
+
+DEFINE_TEARDOWN(crypto_session)
+{
+	g_object_unref (session); 
+	g_object_unref (slot);
+	g_object_unref (module);
+}
+
+static void 
+fetch_async_result (GObject *source, GAsyncResult *result, gpointer user_data)
+{
+	*((GAsyncResult**)user_data) = result;
+	g_object_ref (result);
+}
+
+static GP11Object*
+find_key (GP11Session *session, CK_ATTRIBUTE_TYPE method, CK_MECHANISM_TYPE mech)
+{
+	GList *objects, *l;
+	GP11Object *object = NULL;
+	GP11Attribute *attr;
+	
+	objects = gp11_session_find_objects (session, NULL, method, GP11_BOOLEAN, TRUE, GP11_INVALID);
+	g_assert (objects);
+	
+	for (l = objects; l; l = g_list_next (l)) {
+		gp11_object_set_session (l->data, session);
+		attr = gp11_object_get_one (l->data, CKA_ALLOWED_MECHANISMS, NULL);
+		g_assert (attr);
+		
+		/* We know all of them only have one allowed mech */
+		if (gp11_attribute_get_ulong (attr) == mech) {
+			object = l->data;
+			g_object_ref (object);
+			break;
+		}
+	}
+	
+	gp11_list_unref_free (objects);
+	return object;
+}
+
+static gboolean
+authenticate_object (GP11Slot *slot, GP11Object *object, gchar *label, gchar **password)
+{
+	g_assert (GP11_IS_SLOT (slot));
+	g_assert (GP11_IS_OBJECT (object));
+	g_assert (password);
+	g_assert (!*password);
+	
+	*password = g_strdup ("booo");
+	return TRUE;
+}
+
+DEFINE_TEST(encrypt)
+{
+	GP11Mechanism mech;
+	GError *error = NULL;
+	GAsyncResult *result = NULL;
+	GP11Object *key;
+	guchar *output;
+	gsize n_output;
+
+	mech.type = CKM_CAPITALIZE;
+	mech.n_parameter = 0;
+	mech.parameter = NULL;
+
+	/* Find the right key */
+	key = find_key (session, CKA_ENCRYPT, CKM_CAPITALIZE);
+	g_assert (key);
+	
+	/* Simple one */
+	output = gp11_session_encrypt (session, key, CKM_CAPITALIZE, (const guchar*)"blah blah", 10, &n_output, &error);
+	SUCCESS_RES (output, error);
+	g_assert (n_output == 10);
+	g_assert_cmpstr ((gchar*)output, ==, "BLAH BLAH");
+	g_free (output);
+	
+	/* Full one */
+	output = gp11_session_encrypt_full (session, key, &mech, (const guchar*)"blah blah", 10, &n_output, NULL, &error);
+	SUCCESS_RES (output, error);
+	g_assert (n_output == 10);
+	g_assert_cmpstr ((gchar*)output, ==, "BLAH BLAH");
+	g_free (output);
+	
+	/* Asynchronous one */
+	gp11_session_encrypt_async (session, key, &mech, (const guchar*)"second chance", 14, NULL, fetch_async_result, &result);
+
+	WAIT_UNTIL (result);
+	g_assert (result != NULL);
+	
+	/* Get the result */
+	output = gp11_session_encrypt_finish (session, result, &n_output, &error);
+	SUCCESS_RES (output, error);
+	g_assert (n_output == 14);
+	g_assert_cmpstr ((gchar*)output, ==, "SECOND CHANCE");
+	g_free (output);
+
+	g_object_unref (result);
+	g_object_unref (key);
+}
+
+DEFINE_TEST(decrypt)
+{
+	GP11Mechanism mech;
+	GError *error = NULL;
+	GAsyncResult *result = NULL;
+	GP11Object *key;
+	guchar *output;
+	gsize n_output;
+
+	mech.type = CKM_CAPITALIZE;
+	mech.n_parameter = 0;
+	mech.parameter = NULL;
+
+	/* Find the right key */
+	key = find_key (session, CKA_DECRYPT, CKM_CAPITALIZE);
+	g_assert (key);
+	
+	/* Simple one */
+	output = gp11_session_decrypt (session, key, CKM_CAPITALIZE, (const guchar*)"FRY???", 7, &n_output, &error);
+	SUCCESS_RES (output, error);
+	g_assert (n_output == 7);
+	g_assert_cmpstr ((gchar*)output, ==, "fry???");
+	g_free (output);
+	
+	/* Full one */
+	output = gp11_session_decrypt_full (session, key, &mech, (const guchar*)"TENNIS instructor", 18, &n_output, NULL, &error);
+	SUCCESS_RES (output, error);
+	g_assert (n_output == 18);
+	g_assert_cmpstr ((gchar*)output, ==, "tennis instructor");
+	g_free (output);
+	
+	/* Asynchronous one */
+	gp11_session_decrypt_async (session, key, &mech, (const guchar*)"FAT CHANCE", 11, NULL, fetch_async_result, &result);
+
+	WAIT_UNTIL (result);
+	g_assert (result != NULL);
+	
+	/* Get the result */
+	output = gp11_session_decrypt_finish (session, result, &n_output, &error);
+	SUCCESS_RES (output, error);
+	g_assert (n_output == 11);
+	g_assert_cmpstr ((gchar*)output, ==, "fat chance");
+	g_free (output);
+
+	g_object_unref (result);
+	g_object_unref (key);
+}
+
+DEFINE_TEST(login_context_specific)
+{
+	/* The test module won't let us sign without doing a login, check that */
+	
+	GError *error = NULL;
+	GP11Object *key;
+	guchar *output;
+	gsize n_output;
+
+	/* Find the right key */
+	key = find_key (session, CKA_SIGN, CKM_PREFIX);
+	g_assert (key);
+	
+	/* Simple one */
+	output = gp11_session_sign (session, key, CKM_PREFIX, (const guchar*)"TV Monster", 11, &n_output, &error);
+	g_assert (error && error->code == CKR_USER_NOT_LOGGED_IN);
+	FAIL_RES (output, error);
+	g_assert (output == NULL);
+	
+	g_object_unref (key);
+}
+
+DEFINE_TEST(sign)
+{
+	GP11Mechanism mech;
+	GError *error = NULL;
+	GAsyncResult *result = NULL;
+	GP11Object *key;
+	guchar *output;
+	gsize n_output;
+
+	mech.type = CKM_PREFIX;
+	mech.n_parameter = 10;
+	mech.parameter = "my-prefix:";
+	
+	/* Enable auto-login on this session, see previous test */
+	gp11_slot_set_auto_login (slot, TRUE);
+	g_signal_connect (slot, "authenticate-object", G_CALLBACK (authenticate_object), NULL);
+
+	/* Find the right key */
+	key = find_key (session, CKA_SIGN, CKM_PREFIX);
+	g_assert (key);
+	
+	/* Simple one */
+	output = gp11_session_sign (session, key, CKM_PREFIX, (const guchar*)"Labarbara", 10, &n_output, &error);
+	SUCCESS_RES (output, error);
+	g_assert_cmpuint (n_output, ==, 24);
+	g_assert_cmpstr ((gchar*)output, ==, "signed-prefix:Labarbara");
+	g_free (output);
+	
+	/* Full one */
+	output = gp11_session_sign_full (session, key, &mech, (const guchar*)"Labarbara", 10, &n_output, NULL, &error);
+	SUCCESS_RES (output, error);
+	g_assert_cmpuint (n_output, ==, 20);
+	g_assert_cmpstr ((gchar*)output, ==, "my-prefix:Labarbara");
+	g_free (output);
+	
+	/* Asynchronous one */
+	gp11_session_sign_async (session, key, &mech, (const guchar*)"Conrad", 7, NULL, fetch_async_result, &result);
+
+	WAIT_UNTIL (result);
+	g_assert (result != NULL);
+	
+	/* Get the result */
+	output = gp11_session_sign_finish (session, result, &n_output, &error);
+	SUCCESS_RES (output, error);
+	g_assert_cmpuint (n_output, ==, 17);
+	g_assert_cmpstr ((gchar*)output, ==, "my-prefix:Conrad");
+	g_free (output);
+
+	g_object_unref (result);
+	g_object_unref (key);
+}
+
+DEFINE_TEST(verify)
+{
+	GP11Mechanism mech;
+	GError *error = NULL;
+	GAsyncResult *result = NULL;
+	GP11Object *key;
+	gboolean ret;
+
+	mech.type = CKM_PREFIX;
+	mech.n_parameter = 10;
+	mech.parameter = "my-prefix:";
+	
+	/* Enable auto-login on this session, shouldn't be needed */
+	gp11_slot_set_auto_login (slot, TRUE);
+	g_signal_connect (slot, "authenticate-object", G_CALLBACK (authenticate_object), NULL);
+
+	/* Find the right key */
+	key = find_key (session, CKA_VERIFY, CKM_PREFIX);
+	g_assert (key);
+	
+	/* Simple one */
+	ret = gp11_session_verify (session, key, CKM_PREFIX, (const guchar*)"Labarbara", 10, 
+	                           (const guchar*)"signed-prefix:Labarbara", 24, &error);
+	SUCCESS_RES (ret, error);
+	
+	/* Full one */
+	ret = gp11_session_verify_full (session, key, &mech, (const guchar*)"Labarbara", 10, 
+	                                (const guchar*)"my-prefix:Labarbara", 20, NULL, &error);
+	SUCCESS_RES (ret, error);
+
+	/* Failure one */
+	ret = gp11_session_verify_full (session, key, &mech, (const guchar*)"Labarbara", 10, 
+	                                (const guchar*)"my-prefix:Loborboro", 20, NULL, &error);
+	FAIL_RES (ret, error);
+
+	/* Asynchronous one */
+	gp11_session_verify_async (session, key, &mech, (const guchar*)"Labarbara", 10, 
+	                           (const guchar*)"my-prefix:Labarbara", 20, NULL, fetch_async_result, &result);
+	WAIT_UNTIL (result);
+	g_assert (result != NULL);
+	ret = gp11_session_verify_finish (session, result, &error);
+	SUCCESS_RES (ret, error);
+	g_object_unref (result);
+	
+	/* Asynchronous failure */
+	result = NULL;
+	gp11_session_verify_async (session, key, &mech, (const guchar*)"Labarbara", 10, 
+	                           (const guchar*)"my-prefix:Labarxoro", 20, NULL, fetch_async_result, &result);
+	WAIT_UNTIL (result);
+	g_assert (result != NULL);
+	ret = gp11_session_verify_finish (session, result, &error);
+	FAIL_RES (ret, error);
+	g_object_unref (result);
+
+	g_object_unref (key);
+}

Modified: trunk/gp11/tests/unit-test-gp11-session.c
==============================================================================
--- trunk/gp11/tests/unit-test-gp11-session.c	(original)
+++ trunk/gp11/tests/unit-test-gp11-session.c	Mon Dec 29 06:46:36 2008
@@ -205,7 +205,7 @@
 }
 
 static gboolean
-authenticate_token (GP11Slot *slot, gchar **password, gpointer unused)
+authenticate_token (GP11Slot *slot, gchar *label, gchar **password, gpointer unused)
 {
 	g_assert (unused == GUINT_TO_POINTER (35));
 	g_assert (password != NULL);
@@ -219,6 +219,7 @@
 DEFINE_TEST(auto_login)
 {
 	GP11Object *object;
+	GP11Session *new_session;
 	GAsyncResult *result = NULL;
 	GError *err = NULL;
 	GP11Attributes *attrs;
@@ -244,6 +245,11 @@
 	g_assert (value == TRUE);
 	
 	g_signal_connect (slot, "authenticate-token", G_CALLBACK (authenticate_token), GUINT_TO_POINTER (35));
+	
+	/* Create a new session */
+	new_session = gp11_slot_open_session (slot, CKF_RW_SESSION, &err);
+	SUCCESS_RES (new_session, err);
+	g_object_unref (new_session);
 
 	/* Try again to do something that requires a login */
 	object = gp11_session_create_object_full (session, attrs, NULL, &err); 
@@ -255,6 +261,15 @@
 	SUCCESS_RES (ret, err);
 	
 	/* Now try the same thing, but asyncronously */
+	gp11_slot_open_session_async (slot, CKF_RW_SESSION, NULL, fetch_async_result, &result);
+	WAIT_UNTIL (result);
+	g_assert (result != NULL);
+	new_session = gp11_slot_open_session_finish (slot, result, &err);
+	SUCCESS_RES (new_session, err);
+	g_object_unref (result);
+	g_object_unref (new_session);
+	
+	result = NULL;
 	gp11_session_create_object_async (session, attrs, NULL, fetch_async_result, &result); 
 	WAIT_UNTIL (result);
 	g_assert (result != NULL);



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