gnome-keyring r1401 - in trunk: . pkcs11 pkcs11/gck



Author: nnielsen
Date: Sun Dec 21 15:44:20 2008
New Revision: 1401
URL: http://svn.gnome.org/viewvc/gnome-keyring?rev=1401&view=rev

Log:
	* pkcs11/gck/*: (added)
	* pkcs11/Makefile.am:
	* configure.in: Added GCK base PKCS#11 module code 


Added:
   trunk/pkcs11/gck/   (props changed)
   trunk/pkcs11/gck/Makefile.am
   trunk/pkcs11/gck/gck-crypto.c
   trunk/pkcs11/gck/gck-crypto.h
   trunk/pkcs11/gck/gck-key.c
   trunk/pkcs11/gck/gck-key.h
   trunk/pkcs11/gck/gck-manager.c
   trunk/pkcs11/gck/gck-manager.h
   trunk/pkcs11/gck/gck-module-ep.h
   trunk/pkcs11/gck/gck-module.c
   trunk/pkcs11/gck/gck-module.h
   trunk/pkcs11/gck/gck-object.c
   trunk/pkcs11/gck/gck-object.h
   trunk/pkcs11/gck/gck-private-key.c
   trunk/pkcs11/gck/gck-private-key.h
   trunk/pkcs11/gck/gck-public-key.c
   trunk/pkcs11/gck/gck-public-key.h
   trunk/pkcs11/gck/gck-session.c
   trunk/pkcs11/gck/gck-session.h
   trunk/pkcs11/gck/gck-sexp.c
   trunk/pkcs11/gck/gck-sexp.h
   trunk/pkcs11/gck/gck-util.c
   trunk/pkcs11/gck/gck-util.h
   trunk/pkcs11/gck/temporary-test.c
Modified:
   trunk/ChangeLog
   trunk/configure.in
   trunk/pkcs11/Makefile.am

Modified: trunk/configure.in
==============================================================================
--- trunk/configure.in	(original)
+++ trunk/configure.in	Sun Dec 21 15:44:20 2008
@@ -381,6 +381,9 @@
 DAEMON_CFLAGS="$DAEMON_CFLAGS $LIBGCRYPT_CFLAGS"
 DAEMON_LIBS="$DAEMON_LIBS $LIBGCRYPT_LIBS"
 
+AC_SUBST([LIBGCRYPT_CFLAGS])
+AC_SUBST([LIBGCRYPT_LIBS])
+
 # -------------------------------------------------------------------
 # libtasn1
 # 
@@ -510,6 +513,7 @@
 pam/Makefile
 pam/tests/Makefile
 pkcs11/Makefile
+pkcs11/gck/Makefile
 pkcs11/rpc/Makefile
 pkcs11/tests/Makefile
 po/Makefile.in

Modified: trunk/pkcs11/Makefile.am
==============================================================================
--- trunk/pkcs11/Makefile.am	(original)
+++ trunk/pkcs11/Makefile.am	Sun Dec 21 15:44:20 2008
@@ -41,5 +41,5 @@
 TESTS_DIR = 
 endif
 
-SUBDIRS = . rpc $(TESTS_DIR)
+SUBDIRS = . rpc gck $(TESTS_DIR)
 

Added: trunk/pkcs11/gck/Makefile.am
==============================================================================
--- (empty file)
+++ trunk/pkcs11/gck/Makefile.am	Sun Dec 21 15:44:20 2008
@@ -0,0 +1,41 @@
+
+INCLUDES = \
+	-I$(top_builddir) \
+    	-I$(top_srcdir) \
+    	$(GOBJECT_CFLAGS) \
+	$(LIBGCRYPT_CFLAGS) \
+	$(GLIB_CFLAGS)
+	
+# ------------------------------------------------------------------------------
+# The dispatch code
+
+noinst_LTLIBRARIES = \
+	libgck.la	
+
+libgck_la_SOURCES = \
+	gck-crypto.c gck-crypto.h \
+	gck-key.c gck-key.h \
+	gck-manager.c gck-manager.h \
+	gck-module.c gck-module.h gck-module-ep.h \
+	gck-object.c gck-object.h \
+	gck-private-key.c gck-private-key.h \
+	gck-public-key.c gck-public-key.h \
+	gck-session.c gck-session.h \
+	gck-sexp.c gck-sexp.h \
+	gck-util.c gck-util.h 
+	
+# ------------------------------------------------------------------------------
+# TEMPORARY TEST BINARY
+
+noinst_PROGRAMS = \
+	temporary-test
+	
+temporary_test_SOURCES = \
+	temporary-test.c
+	
+temporary_test_LDADD = \
+	libgck.la \
+    	$(GOBJECT_LIBS) \
+    	$(LIBGCRYPT_LIBS) \
+	$(GLIB_LIBS)
+	
\ No newline at end of file

Added: trunk/pkcs11/gck/gck-crypto.c
==============================================================================
--- (empty file)
+++ trunk/pkcs11/gck/gck-crypto.c	Sun Dec 21 15:44:20 2008
@@ -0,0 +1,888 @@
+/* 
+ * gnome-keyring
+ * 
+ * Copyright (C) 2008 Stefan Walter
+ * 
+ * This program is free software; you can redistribute it and/or modify 
+ * it under the terms of the GNU Lesser General  License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *  
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General  License for more details.
+ *  
+ * You should have received a copy of the GNU Lesser General 
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.  
+ */
+
+#include "config.h"
+
+#include "gck-crypto.h"
+
+/* ----------------------------------------------------------------------------
+ * INTERNAL
+ */
+
+static gcry_sexp_t
+sexp_get_childv (gcry_sexp_t sexp, va_list va)
+{
+	gcry_sexp_t at = NULL;
+	gcry_sexp_t child;
+	const char *name;
+	
+	for(;;) {
+		name = va_arg (va, const char*);
+		if (!name)
+			break;
+
+		child = gcry_sexp_find_token (at ? at : sexp, name, 0);
+		gcry_sexp_release (at);
+		at = child;
+		if (at == NULL)
+			break;
+	}
+	
+	va_end (va);
+
+	return at;
+}
+
+static CK_RV
+data_to_sexp (const gchar *format, guint nbits, GckCryptoPadding padding, 
+              CK_BYTE_PTR data, CK_ULONG n_data, gcry_sexp_t *sexp)
+{
+	guchar *padded = NULL;
+	gcry_error_t gcry;
+	gcry_mpi_t mpi;
+	gsize n_padded;
+
+	g_assert (format);
+	g_assert (sexp);	
+	
+	g_return_val_if_fail (data, CKR_ARGUMENTS_BAD);
+
+	if (padding) {
+		padded = (padding) (nbits, data, n_data, &n_padded);
+		if (!padded)
+			return CKR_DATA_LEN_RANGE;
+	}
+		
+	/* Prepare the input s expression */
+	gcry = gcry_mpi_scan (&mpi, GCRYMPI_FMT_USG, 
+                              padded ? padded : data, 
+	                      padded ? n_padded : n_data, NULL);
+	g_free (padded);
+
+	g_return_val_if_fail (gcry == 0, CKR_GENERAL_ERROR);
+
+	gcry = gcry_sexp_build (sexp, NULL, format, mpi);
+	gcry_mpi_release (mpi);
+
+	g_return_val_if_fail (gcry == 0, CKR_GENERAL_ERROR);
+
+	g_assert (*sexp);
+	return CKR_OK;
+} 
+
+/* For the sake of checking arguments */
+static CK_RV
+sexp_to_data (gcry_sexp_t sexp, guint bits, CK_BYTE_PTR data, 
+              CK_ULONG *n_data, GckCryptoPadding padding, 
+              ...) G_GNUC_NULL_TERMINATED;
+
+static CK_RV
+sexp_to_data (gcry_sexp_t sexp, guint bits, CK_BYTE_PTR data, 
+              CK_ULONG *n_data, GckCryptoPadding padding, ...)
+{
+	gcry_sexp_t at = NULL;
+	gsize n_block, offset, len;
+	gcry_mpi_t mpi = NULL;
+	guchar *block;
+	va_list va;
+	gcry_error_t gcry;
+	
+	g_assert (sexp);
+	g_assert (data);
+	g_assert (n_data);
+	g_assert (*n_data);
+	g_assert (padding);
+	g_assert (bits);
+
+	/* First try and dig out sexp child based on arguments */
+	va_start (va, padding);
+	at = sexp_get_childv (sexp, va);
+	va_end (va);
+	
+	/* It's expected we would find it */
+	g_return_val_if_fail (at != NULL, CKR_GENERAL_ERROR);
+
+	/* Parse out the MPI */
+	mpi = gcry_sexp_nth_mpi (at, 1, GCRYMPI_FMT_USG);
+	g_return_val_if_fail (at != NULL, CKR_GENERAL_ERROR);
+	gcry_sexp_release (at);
+	
+	/* Print out the MPI into the end of a temporary buffer */
+	n_block = (bits + 7) / 8;
+	gcry = gcry_mpi_print (GCRYMPI_FMT_USG, NULL, 0, &len, mpi);
+	g_return_val_if_fail (gcry == 0, CKR_GENERAL_ERROR);
+	g_return_val_if_fail (len > n_block, CKR_GENERAL_ERROR);
+	offset = n_block - len;
+	block = g_malloc0 (n_block);
+	memset (block, 0, offset);
+	gcry = gcry_mpi_print (GCRYMPI_FMT_USG, block + offset, len, &len, mpi);
+	g_return_val_if_fail (gcry == 0, CKR_GENERAL_ERROR);
+	g_return_val_if_fail (len == n_block - offset, CKR_GENERAL_ERROR);
+	gcry_mpi_release (mpi);
+		
+	/* Pad it properly if necessary */
+	if (padding != NULL) {
+		guchar *padded = (padding) (bits, block, n_block, &n_block);
+		g_return_val_if_fail (padded, CKR_GENERAL_ERROR);
+		g_free (block);
+		block = padded;
+	}
+	
+	/* Now stuff it into the output buffer */
+	if (n_block > *n_data)
+		return CKR_BUFFER_TOO_SMALL;
+
+	memcpy (data, block, n_block);
+	*n_data = n_block;
+	g_free (block);
+	
+	return CKR_OK;
+}
+
+static void
+fill_random_nonzero (guchar *data, gsize n_data)
+{
+	guchar *rnd;
+	guint n_zero, i, j;
+	
+	gcry_randomize (data, n_data, GCRY_STRONG_RANDOM);
+
+	/* Find any zeros in random data */
+	n_zero = 0;
+	for (i = 0; i < n_data; ++i) {
+		if (data[i] == 0x00)
+			++n_zero;
+	}
+
+	while (n_zero > 0) {
+		rnd = gcry_random_bytes (n_zero, GCRY_STRONG_RANDOM);
+		n_zero = 0;
+		for (i = 0, j = 0; i < n_data; ++i) {
+			if (data[i] != 0x00)
+				continue;
+				
+			/* Use some of the replacement data */
+			data[i] = rnd[j];
+			++j;
+			
+			/* It's zero again :( */
+			if (data[i] == 0x00)
+				n_zero++;
+		}
+		
+		gcry_free (rnd);
+	}
+}
+
+static guchar*
+unpad_rsa_pkcs1 (guchar bt, guint n_modulus, const guchar* padded,
+                 gsize n_padded, gsize *n_raw)
+{ 
+	const guchar *at;
+	guchar *raw;
+	
+	/* The absolute minimum size including padding */
+	g_return_val_if_fail (n_modulus / 8 >= 3 + 8, NULL);
+	
+	if (n_padded != n_modulus / 8)
+		return NULL;
+		
+	/* Check the header */
+	if (padded[0] != 0x00 || padded[1] != bt)
+		return NULL;
+	
+	/* The first zero byte after the header */
+	at = memchr (padded + 2, 0x00, n_padded - 2);
+	if (!at)
+		return NULL;
+		
+	++at;
+	*n_raw = n_padded - (at - padded);
+	raw = g_new0 (guchar, *n_raw);
+	memcpy (raw, at, *n_raw);
+	return raw;
+}
+
+
+/* ----------------------------------------------------------------------------
+ * PUBLIC
+ */
+
+CK_RV
+gck_crypto_encrypt (gcry_sexp_t sexp, CK_MECHANISM_TYPE mech, CK_BYTE_PTR data, 
+                    CK_ULONG n_data, CK_BYTE_PTR encrypted, CK_ULONG_PTR n_encrypted)
+{
+	int algorithm;
+	CK_RV rv;
+	
+	g_return_val_if_fail (sexp, CKR_GENERAL_ERROR);
+	g_return_val_if_fail (n_encrypted, CKR_ARGUMENTS_BAD);
+	g_return_val_if_fail (data, CKR_ARGUMENTS_BAD);
+	
+	if (!gck_crypto_sexp_parse_key (sexp, &algorithm, NULL, NULL))
+		g_return_val_if_reached (CKR_GENERAL_ERROR);
+
+	/* 
+	 * The algorithm checks below are merely sanity checks.
+	 * Other code should have checed this at an earlier stage
+	 * and return the right error codes if invalid.
+	 */
+	
+	switch (mech) {
+	case CKM_RSA_PKCS:
+		g_return_val_if_fail (algorithm == GCRY_PK_RSA, CKR_GENERAL_ERROR); 
+		rv = gck_crypto_decrypt_rsa (sexp, gck_crypto_rsa_pad_two, data, n_data, encrypted, n_encrypted);
+		break;
+	case CKM_RSA_X_509:
+		g_return_val_if_fail (algorithm == GCRY_PK_RSA, CKR_GENERAL_ERROR);
+		rv = gck_crypto_decrypt_rsa (sexp, gck_crypto_rsa_pad_raw, data, n_data, encrypted, n_encrypted);
+		break;
+	default:
+		/* Again shouldn't be reached */
+		g_return_val_if_reached (CKR_GENERAL_ERROR);
+	};
+	
+	return rv;	
+}
+
+CK_RV
+gck_crypto_encrypt_rsa (gcry_sexp_t sexp, GckCryptoPadding padding, CK_BYTE_PTR data, 
+                        CK_ULONG n_data, CK_BYTE_PTR encrypted, CK_ULONG_PTR n_encrypted)
+{
+	gcry_sexp_t splain, sdata;
+	gcry_error_t gcry;
+	guint nbits;
+	CK_RV rv;
+	
+	g_return_val_if_fail (sexp, CKR_GENERAL_ERROR);
+	g_return_val_if_fail (n_encrypted, CKR_ARGUMENTS_BAD);
+	g_return_val_if_fail (data, CKR_ARGUMENTS_BAD);
+
+	nbits = gcry_pk_get_nbits (sexp);
+	g_return_val_if_fail (nbits > 0, CKR_GENERAL_ERROR);
+
+	/* Just want to know the length */
+	if (!encrypted) {
+		*n_encrypted = (nbits + 7) / 8;
+		return CKR_OK;
+	}
+
+	/* Prepare the input s expression */
+	rv = data_to_sexp ("(data (flags raw) (value %m))", 
+	                   nbits, padding, data, n_data, &splain);
+	if (rv != CKR_OK)
+		return rv;
+	
+	/* Do the magic */
+	gcry = gcry_pk_encrypt (&sdata, splain, sexp);
+	gcry_sexp_release (splain);
+	
+	/* TODO: Certain codes should be returned (data too big etc... ) */
+	if (gcry) {
+		g_message ("encrypting of the data failed: %s", gcry_strerror (gcry));
+		return CKR_FUNCTION_FAILED;
+	}
+
+	/* Now extract and send it back out */
+	rv = sexp_to_data (sexp, nbits, encrypted, n_encrypted, NULL, "enc-val", "rsa", "a", NULL);
+	gcry_sexp_release (sdata);
+	
+	return rv;
+}
+
+CK_RV
+gck_crypto_decrypt (gcry_sexp_t sexp, CK_MECHANISM_TYPE mech, CK_BYTE_PTR encrypted, 
+                    CK_ULONG n_encrypted, CK_BYTE_PTR data, CK_ULONG_PTR n_data)
+{
+	int algorithm;
+	CK_RV rv;
+	
+	g_return_val_if_fail (sexp, CKR_GENERAL_ERROR);
+	g_return_val_if_fail (n_data, CKR_ARGUMENTS_BAD);
+	g_return_val_if_fail (encrypted, CKR_ARGUMENTS_BAD);
+	
+	if (!gck_crypto_sexp_parse_key (sexp, &algorithm, NULL, NULL))
+		g_return_val_if_reached (CKR_GENERAL_ERROR);
+
+	/* 
+	 * The algorithm checks below are merely sanity checks.
+	 * Other code should have checed this at an earlier stage
+	 * and return the right error codes if invalid.
+	 */
+	
+	switch (mech) {
+	case CKM_RSA_PKCS:
+		g_return_val_if_fail (algorithm == GCRY_PK_RSA, CKR_GENERAL_ERROR); 
+		rv = gck_crypto_decrypt_rsa (sexp, gck_crypto_rsa_unpad_two, encrypted, n_encrypted, data, n_data);
+		break;
+	case CKM_RSA_X_509:
+		g_return_val_if_fail (algorithm == GCRY_PK_RSA, CKR_GENERAL_ERROR);
+		rv = gck_crypto_decrypt_rsa (sexp, NULL, encrypted, n_encrypted, data, n_data);
+		break;
+	default:
+		/* Again shouldn't be reached */
+		g_return_val_if_reached (CKR_GENERAL_ERROR);
+	};
+	
+	return rv;	
+}
+
+CK_RV
+gck_crypto_decrypt_rsa (gcry_sexp_t sexp, GckCryptoPadding padding, CK_BYTE_PTR encrypted, 
+                        CK_ULONG n_encrypted, CK_BYTE_PTR data, CK_ULONG_PTR n_data)
+{
+	gcry_sexp_t splain, sdata;
+	gcry_error_t gcry;
+	guint nbits;
+	CK_RV rv;
+
+	g_return_val_if_fail (sexp, CKR_GENERAL_ERROR);
+	g_return_val_if_fail (n_data, CKR_ARGUMENTS_BAD);
+	g_return_val_if_fail (data, CKR_ARGUMENTS_BAD);
+
+	nbits = gcry_pk_get_nbits (sexp);
+	g_return_val_if_fail (nbits > 0, CKR_GENERAL_ERROR);
+
+	/* Just want to know the length */
+	if (!data) {
+		*n_data = (nbits + 7) / 8;
+		return CKR_OK;
+	}
+	
+	/* Prepare the input s expression */
+	rv = data_to_sexp ("(enc-val (flags) (rsa (a %m)))", 
+	                   nbits, NULL, encrypted, n_encrypted, &sdata);
+	if (rv != CKR_OK)
+		return rv;
+
+	/* Do the magic */
+	gcry = gcry_pk_decrypt (&splain, sdata, sexp);
+	gcry_sexp_release (sdata);
+
+	/* TODO: Certain codes should be returned (data too big etc... ) */
+	if (gcry) {
+		g_message ("decrypting of the data failed: %s", gcry_strerror (gcry));
+		return CKR_FUNCTION_FAILED;
+	}
+
+	/* Now extract and send it back out */
+	rv = sexp_to_data (splain, nbits, data, n_data, padding, "value", NULL);
+	gcry_sexp_release (splain);
+	
+	return rv;
+}
+
+CK_RV
+gck_crypto_sign (gcry_sexp_t sexp, CK_MECHANISM_TYPE mech, CK_BYTE_PTR data, 
+                 CK_ULONG n_data, CK_BYTE_PTR signature, CK_ULONG_PTR n_signature)
+{
+	int algorithm;
+	CK_RV rv;
+	
+	g_return_val_if_fail (sexp, CKR_GENERAL_ERROR);
+	g_return_val_if_fail (n_signature, CKR_ARGUMENTS_BAD);
+	g_return_val_if_fail (data, CKR_ARGUMENTS_BAD);
+	
+	if (!gck_crypto_sexp_parse_key (sexp, &algorithm, NULL, NULL))
+		g_return_val_if_reached (CKR_GENERAL_ERROR);
+
+	/* 
+	 * The algorithm checks below are merely sanity checks.
+	 * Other code should have checed this at an earlier stage
+	 * and return the right error codes if invalid.
+	 */
+	
+	switch (mech) {
+	case CKM_RSA_PKCS:
+		g_return_val_if_fail (algorithm == GCRY_PK_RSA, CKR_GENERAL_ERROR); 
+		rv = gck_crypto_sign_rsa (sexp, gck_crypto_rsa_pad_one, data, n_data, signature, n_signature);
+		break;
+	case CKM_RSA_X_509:
+		g_return_val_if_fail (algorithm == GCRY_PK_RSA, CKR_GENERAL_ERROR);
+		rv = gck_crypto_sign_rsa (sexp, gck_crypto_rsa_pad_raw, data, n_data, signature, n_signature);
+		break;
+	case CKM_DSA:
+		g_return_val_if_fail (algorithm == GCRY_PK_DSA, CKR_GENERAL_ERROR);
+		rv = gck_crypto_sign_dsa (sexp, data, n_data, signature, n_signature);
+		break;
+	default:
+		/* Again shouldn't be reached */
+		g_return_val_if_reached (CKR_GENERAL_ERROR);
+	};
+	
+	return rv;
+}
+
+CK_RV
+gck_crypto_sign_rsa (gcry_sexp_t sexp, GckCryptoPadding padding, CK_BYTE_PTR data, 
+                     CK_ULONG n_data, CK_BYTE_PTR signature, CK_ULONG_PTR n_signature)
+{
+	gcry_sexp_t ssig, sdata;
+	guint nbits; 
+	gcry_error_t gcry;
+	CK_RV rv;
+	
+	g_return_val_if_fail (sexp, CKR_GENERAL_ERROR);
+	g_return_val_if_fail (n_signature, CKR_ARGUMENTS_BAD);
+	g_return_val_if_fail (data, CKR_ARGUMENTS_BAD);
+
+	nbits = gcry_pk_get_nbits (sexp);
+	g_return_val_if_fail (nbits > 0, CKR_GENERAL_ERROR);
+
+	/* Just want to know the length */
+	if (!signature) {
+		*n_signature = (nbits + 7) / 8;
+		return CKR_OK;
+	}
+	
+	/* Prepare the input sexp */
+	rv = data_to_sexp ("(data (flags raw) (value %m))", 
+	                    nbits, padding, data, n_data, &sdata);
+	if (rv != CKR_OK)
+		return rv;
+
+	/* Do the magic */
+	gcry = gcry_pk_sign (&ssig, sdata, sexp);
+	gcry_sexp_release (sdata);
+
+	/* TODO: Certain codes should be returned (data too big etc... ) */
+	if (gcry) {
+		g_message ("signing of the data failed: %s", gcry_strerror (gcry));
+		return CKR_FUNCTION_FAILED;
+	}
+
+	/* Now extract and send it back out */
+	rv = sexp_to_data (ssig, nbits, signature, n_signature, NULL, "rsa", "s", NULL);
+	gcry_sexp_release (ssig);
+	
+	return rv;
+}
+
+CK_RV
+gck_crypto_sign_dsa (gcry_sexp_t sexp, CK_BYTE_PTR data, CK_ULONG n_data, 
+                     CK_BYTE_PTR signature, CK_ULONG_PTR n_signature)
+{
+	gcry_sexp_t ssig, splain;
+	gcry_error_t gcry;
+	gcry_mpi_t mpi;
+	CK_ULONG size;
+	CK_RV rv;
+	
+	g_return_val_if_fail (sexp, CKR_GENERAL_ERROR);
+	g_return_val_if_fail (n_signature, CKR_ARGUMENTS_BAD);
+	g_return_val_if_fail (data, CKR_ARGUMENTS_BAD);
+
+	if (n_data != 20)
+		return CKR_DATA_LEN_RANGE;
+	
+	/* If no output, then don't process */
+	if (!signature) {
+		*n_signature = 40;
+		return CKR_OK;
+	} else if (*n_signature < 40) {
+		*n_signature = 40;
+		return CKR_BUFFER_TOO_SMALL;
+	}
+				
+	/* Prepare the input s-expression */
+	gcry = gcry_mpi_scan (&mpi, GCRYMPI_FMT_USG, data, n_data, NULL);
+	g_return_val_if_fail (gcry == 0, CKR_GENERAL_ERROR);
+	gcry = gcry_sexp_build (&splain, NULL, "(data (flags raw) (value %m))", mpi);
+	gcry_mpi_release (mpi);
+	g_return_val_if_fail (gcry == 0, CKR_GENERAL_ERROR);
+
+	/* Do the magic */
+	gcry = gcry_pk_sign (&ssig, splain, sexp);
+	gcry_sexp_release (splain);
+	
+	/* TODO: Certain codes should be returned (data too big etc... ) */
+	if (gcry) {
+		g_message ("signing of the data failed: %s", gcry_strerror (gcry));
+		return CKR_FUNCTION_FAILED;
+	}
+
+	g_assert (*n_signature >= 40);
+
+	size = 20;
+	rv = sexp_to_data (ssig, 20 * 8, signature, &size, NULL, "dsa", "r", NULL);
+	if (rv == CKR_OK) {
+		g_return_val_if_fail (size == 20, CKR_GENERAL_ERROR);
+		rv = sexp_to_data (ssig, 20 * 8, signature + 20, &size, NULL, "dsa", "s", NULL);
+		if (rv == CKR_OK) {
+			g_return_val_if_fail (size == 20, CKR_GENERAL_ERROR);
+			*n_signature = 40;
+		}
+	}
+	
+	gcry_sexp_release (ssig);
+	return CKR_OK;
+}
+
+CK_RV
+gck_crypto_verify (gcry_sexp_t sexp, CK_MECHANISM_TYPE mech, CK_BYTE_PTR data, 
+                   CK_ULONG n_data, CK_BYTE_PTR signature, CK_ULONG n_signature)
+{
+	int algorithm;
+	CK_RV rv;
+	
+	g_return_val_if_fail (sexp, CKR_GENERAL_ERROR);
+	g_return_val_if_fail (signature, CKR_ARGUMENTS_BAD);
+	g_return_val_if_fail (data, CKR_ARGUMENTS_BAD);
+	
+	if (!gck_crypto_sexp_parse_key (sexp, &algorithm, NULL, NULL))
+		g_return_val_if_reached (CKR_GENERAL_ERROR);
+
+	/* 
+	 * The algorithm checks below are merely sanity checks.
+	 * Other code should have checed this at an earlier stage
+	 * and return the right error codes if invalid.
+	 */
+	
+	switch (mech) {
+	case CKM_RSA_PKCS:
+		g_return_val_if_fail (algorithm == GCRY_PK_RSA, CKR_GENERAL_ERROR); 
+		rv = gck_crypto_verify_rsa (sexp, gck_crypto_rsa_pad_one, data, n_data, signature, n_signature);
+		break;
+	case CKM_RSA_X_509:
+		g_return_val_if_fail (algorithm == GCRY_PK_RSA, CKR_GENERAL_ERROR);
+		rv = gck_crypto_verify_rsa (sexp, gck_crypto_rsa_pad_raw, data, n_data, signature, n_signature);
+		break;
+	case CKM_DSA:
+		g_return_val_if_fail (algorithm == GCRY_PK_DSA, CKR_GENERAL_ERROR);
+		rv = gck_crypto_verify_dsa (sexp, data, n_data, signature, n_signature);
+		break;
+	default:
+		/* Again shouldn't be reached */
+		g_return_val_if_reached (CKR_GENERAL_ERROR);
+	};
+	
+	return rv;
+}
+
+CK_RV
+gck_crypto_verify_rsa (gcry_sexp_t sexp, GckCryptoPadding padding, CK_BYTE_PTR data, 
+                       CK_ULONG n_data, CK_BYTE_PTR signature, CK_ULONG n_signature)
+{
+	gcry_sexp_t ssig, sdata;
+	gcry_error_t gcry;
+	guint nbits;
+	CK_RV rv;
+	
+	g_return_val_if_fail (sexp, CKR_GENERAL_ERROR);
+	g_return_val_if_fail (signature, CKR_ARGUMENTS_BAD);
+	g_return_val_if_fail (data, CKR_ARGUMENTS_BAD);
+
+	/* The key size */
+	nbits = gcry_pk_get_nbits (sexp);
+	g_return_val_if_fail (nbits > 0, CKR_GENERAL_ERROR);
+	g_return_val_if_fail (nbits % 8 == 0, CKR_GENERAL_ERROR);
+
+	/* Prepare the input s expressions */
+	rv = data_to_sexp ("(data (flags raw) (value %m))", 
+	                   nbits, padding, data, n_data, &sdata);
+	if (rv != CKR_OK)
+		return rv;
+
+	rv = data_to_sexp ("(sig-val (rsa (s %m)))", 
+	                   nbits, NULL, signature, n_signature, &ssig);
+	if (rv != CKR_OK) {
+		gcry_sexp_release (sdata);
+		return rv;
+	}
+		
+	/* Do the magic */
+	gcry = gcry_pk_verify (ssig, sdata, sexp);
+	gcry_sexp_release (sdata);
+	gcry_sexp_release (ssig);
+	
+	/* TODO: See if any other codes should be mapped */
+	if (gcry_err_code (gcry) == GPG_ERR_BAD_SIGNATURE) {
+		return CKR_SIGNATURE_INVALID;
+	} else if (gcry) {
+		g_message ("signing of the data failed: %s", gcry_strerror (gcry));
+		return CKR_FUNCTION_FAILED;
+	}
+
+	return CKR_OK;
+}
+
+CK_RV
+gck_crypto_verify_dsa (gcry_sexp_t sexp, CK_BYTE_PTR data, CK_ULONG n_data, 
+                       CK_BYTE_PTR signature, CK_ULONG n_signature)
+{
+	gcry_sexp_t ssig, splain;
+	gcry_error_t gcry;
+	gcry_mpi_t mpi, mpi2;
+	
+	g_return_val_if_fail (sexp, CKR_GENERAL_ERROR);
+	g_return_val_if_fail (signature, CKR_ARGUMENTS_BAD);
+	g_return_val_if_fail (data, CKR_ARGUMENTS_BAD);
+
+	if (n_data != 20)
+		return CKR_DATA_LEN_RANGE;				
+	if (n_signature != 40)
+		return CKR_DATA_LEN_RANGE;
+
+	/* Prepare the input s-expressions */
+	gcry = gcry_mpi_scan (&mpi, GCRYMPI_FMT_USG, data, n_data, NULL);
+	g_return_val_if_fail (gcry == 0, CKR_GENERAL_ERROR);
+	gcry = gcry_sexp_build (&splain, NULL, "(data (flags raw) (value %m))", mpi);
+	gcry_mpi_release (mpi);
+	g_return_val_if_fail (gcry == 0, CKR_GENERAL_ERROR);
+
+	gcry = gcry_mpi_scan (&mpi, GCRYMPI_FMT_USG, signature, 20, NULL);
+	g_return_val_if_fail (gcry == 0, CKR_GENERAL_ERROR);
+	gcry = gcry_mpi_scan (&mpi2, GCRYMPI_FMT_USG, signature + 20, 20, NULL);
+	g_return_val_if_fail (gcry == 0, CKR_GENERAL_ERROR);
+	gcry = gcry_sexp_build (&ssig, NULL, "(sig-val (dsa (r %m) (s %m)))", mpi, mpi2);
+	gcry_mpi_release (mpi);
+	gcry_mpi_release (mpi2);
+	g_return_val_if_fail (gcry == 0, CKR_GENERAL_ERROR);
+	
+	/* Do the magic */
+	gcry = gcry_pk_verify (ssig, splain, sexp);
+	gcry_sexp_release (splain);
+	gcry_sexp_release (ssig);
+	
+	/* TODO: See if any other codes should be mapped */
+	if (gcry_err_code (gcry) == GPG_ERR_BAD_SIGNATURE) {
+		return CKR_SIGNATURE_INVALID;
+	} else if (gcry) {
+		g_message ("signing of the data failed: %s", gcry_strerror (gcry));
+		return CKR_FUNCTION_FAILED;
+	}
+
+	return CKR_OK;
+}
+
+CK_RV 
+gck_crypto_perform (gcry_sexp_t sexp, CK_MECHANISM_TYPE mech, CK_ATTRIBUTE_TYPE method, 
+                    CK_BYTE_PTR bufone, CK_ULONG n_bufone, CK_BYTE_PTR buftwo, CK_ULONG_PTR n_buftwo)
+{
+	g_return_val_if_fail (sexp, CKR_GENERAL_ERROR);
+	g_return_val_if_fail (method, CKR_GENERAL_ERROR);
+	g_return_val_if_fail (n_buftwo, CKR_GENERAL_ERROR);
+	
+	switch (method) {
+	case CKA_ENCRYPT:
+		return gck_crypto_encrypt (sexp, method, bufone, n_bufone, buftwo, n_buftwo);
+	case CKA_DECRYPT:
+		return gck_crypto_decrypt (sexp, method, bufone, n_bufone, buftwo, n_buftwo);
+	case CKA_SIGN:
+		return gck_crypto_sign (sexp, method, bufone, n_bufone, buftwo, n_buftwo);
+	case CKA_VERIFY:
+		return gck_crypto_verify (sexp, method, bufone, n_bufone, buftwo, *n_buftwo);
+	default:
+		g_return_val_if_reached (CKR_GENERAL_ERROR);
+	}
+}
+
+/* ----------------------------------------------------------------------------
+ * SEXP FUNCTIONS
+ */
+
+#define PUBLIC_KEY "public-key"
+#define PUBLIC_KEY_L 10
+#define PRIVATE_KEY "private-key"
+#define PRIVATE_KEY_L 11
+
+gboolean
+gck_crypto_sexp_parse_key (gcry_sexp_t s_key, int *algorithm, gboolean *is_private, 
+                           gcry_sexp_t *numbers)
+{
+	gboolean ret = FALSE;
+	gcry_sexp_t child = NULL;
+	gchar *str = NULL;
+  	const gchar *data;
+  	gsize n_data;
+  	gboolean priv;
+  	int algo;
+
+	data = gcry_sexp_nth_data (s_key, 0, &n_data);
+	if (!data) 
+		goto done;
+
+	if (n_data == PUBLIC_KEY_L && strncmp (data, PUBLIC_KEY, PUBLIC_KEY_L) == 0)
+		priv = FALSE;
+	else if (n_data == PRIVATE_KEY_L && strncmp (data, PRIVATE_KEY, PRIVATE_KEY_L) == 0)
+		priv = TRUE;
+	else
+		goto done;
+
+	child = gcry_sexp_nth (s_key, 1);
+	if (!child)
+		goto done;
+		
+	data = gcry_sexp_nth_data (child, 0, &n_data);
+	if (!data)
+		goto done;
+		
+	str = g_alloca (n_data + 1);
+	memcpy (str, data, n_data);
+	str[n_data] = 0;
+	
+	algo = gcry_pk_map_name (str);
+	if (!algo)
+		goto done;
+
+	/* Yay all done */
+	if (algorithm)
+		*algorithm = algo;
+	if (numbers) {
+		*numbers = child;
+		child = NULL;
+	}
+	if (is_private)
+		*is_private = priv;
+
+	ret = TRUE;
+	
+done:
+	gcry_sexp_release (child);
+	return ret;
+}
+
+gboolean
+gck_crypto_sexp_extract_mpi (gcry_sexp_t sexp, gcry_mpi_t *mpi, ...)
+{
+	gcry_sexp_t at = NULL;
+	va_list va;
+	
+	g_assert (sexp);
+	g_assert (mpi);
+	
+	va_start (va, mpi);
+	at = sexp_get_childv (sexp, va);
+	va_end (va);
+	
+	*mpi = NULL;
+	if (at)
+		*mpi = gcry_sexp_nth_mpi (at ? at : sexp, 1, GCRYMPI_FMT_USG);
+	if (at)
+		gcry_sexp_release (at);
+
+	return (*mpi) ? TRUE : FALSE;
+}
+
+/* ----------------------------------------------------------------------------
+ * PADDING FUNCTIONS
+ */
+
+
+guchar*
+gck_crypto_rsa_pad_raw (guint n_modulus, const guchar* raw,
+                        gsize n_raw, gsize *n_padded)
+{
+	gint total, n_pad;
+	guchar *padded;
+
+	/*
+	 * 0x00 0x00 0x00 ... 0x?? 0x?? 0x?? ...
+         *   padding               data
+         */
+
+	total = n_modulus / 8;
+	n_pad = total - n_raw;
+	if (n_pad < 0) /* minumum padding */
+		return NULL;
+
+	padded = g_new0 (guchar, total);
+	memset (padded, 0x00, n_pad);
+	memcpy (padded + n_pad, raw, n_raw);
+	
+	*n_padded = total;
+	return padded;
+}
+
+guchar*
+gck_crypto_rsa_pad_one (guint n_modulus, const guchar* raw, 
+                        gsize n_raw, gsize *n_padded)
+{
+	gint total, n_pad;
+	guchar *padded;
+
+	/*
+	 * 0x00 0x01 0xFF 0xFF ... 0x00 0x?? 0x?? 0x?? ...
+         *      type  padding              data
+         */
+
+	total = n_modulus / 8;
+	n_pad = total - 3 - n_raw;
+	if (n_pad < 8) /* minumum padding */
+		return NULL;
+
+	padded = g_new0 (guchar, total);
+	padded[1] = 1; /* Block type */
+	memset (padded + 2, 0xff, n_pad);
+	memcpy (padded + 3 + n_pad, raw, n_raw); 
+	
+	*n_padded = total;
+	return padded;
+}
+
+guchar*
+gck_crypto_rsa_pad_two (guint n_modulus, const guchar* raw, 
+                        gsize n_raw, gsize *n_padded)
+{
+	gint total, n_pad;
+	guchar *padded;
+
+	/*
+	 * 0x00 0x01 0x?? 0x?? ... 0x00 0x?? 0x?? 0x?? ...
+         *      type  padding              data
+         */
+
+	total = n_modulus / 8;
+	n_pad = total - 3 - n_raw;
+	if (n_pad < 8) /* minumum padding */
+		return NULL;
+
+	padded = g_new0 (guchar, total);
+	padded[1] = 2; /* Block type */
+	fill_random_nonzero (padded + 2, n_pad);
+	memcpy (padded + 3 + n_pad, raw, n_raw); 
+	
+	*n_padded = total;
+	return padded;
+}
+
+guchar*
+gck_crypto_rsa_unpad_pkcs1 (guint bits, const guchar *padded,
+                            gsize n_padded, gsize *n_raw)
+{
+	/* Further checks are done later */
+	g_return_val_if_fail (n_padded > 2, NULL);
+	return unpad_rsa_pkcs1 (padded[1], bits, padded, n_padded, n_raw);
+}
+
+guchar* 
+gck_crypto_rsa_unpad_one (guint bits, const guchar *padded, 
+                          gsize n_padded, gsize *n_raw)
+{
+	return unpad_rsa_pkcs1 (0x01, bits, padded, n_padded, n_raw);
+}
+
+guchar* 
+gck_crypto_rsa_unpad_two (guint bits, const guchar *padded, 
+                          gsize n_padded, gsize *n_raw)
+{
+	return unpad_rsa_pkcs1 (0x02, bits, padded, n_padded, n_raw);
+}

Added: trunk/pkcs11/gck/gck-crypto.h
==============================================================================
--- (empty file)
+++ trunk/pkcs11/gck/gck-crypto.h	Sun Dec 21 15:44:20 2008
@@ -0,0 +1,160 @@
+/* 
+ * gnome-keyring
+ * 
+ * Copyright (C) 2008 Stefan Walter
+ * 
+ * This program is free software; you can redistribute it and/or modify 
+ * it under the terms of the GNU Lesser General  License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *  
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General  License for more details.
+ *  
+ * You should have received a copy of the GNU Lesser General 
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.  
+ */
+
+#ifndef GCKCRYPTO_H_
+#define GCKCRYPTO_H_
+
+#include <glib.h>
+
+#include <gcrypt.h>
+
+#include "pkcs11/pkcs11.h"
+
+typedef guchar* (*GckCryptoPadding) (guint n_modulus, const guchar* raw, 
+                                     gsize n_raw, gsize *n_padded);
+
+static const CK_MECHANISM_TYPE GCK_CRYPTO_RSA_MECHANISMS[] = {
+	CKM_RSA_PKCS,
+	CKM_RSA_X_509
+};
+
+static const CK_MECHANISM_TYPE GCK_CRYPTO_DSA_MECHANISMS[] = {
+	CKM_DSA
+};
+
+CK_RV                    gck_crypto_perform                            (gcry_sexp_t sexp, 
+                                                                        CK_MECHANISM_TYPE mech, 
+                                                                        CK_ATTRIBUTE_TYPE method, 
+                                                                        CK_BYTE_PTR bufone, 
+                                                                        CK_ULONG n_bufone, 
+                                                                        CK_BYTE_PTR buftwo, 
+                                                                        CK_ULONG_PTR n_buftwo);
+
+CK_RV                    gck_crypto_encrypt                            (gcry_sexp_t sexp, 
+                                                                        CK_MECHANISM_TYPE mech, 
+                                                                        CK_BYTE_PTR data, 
+                                                                        CK_ULONG n_data, 
+                                                                        CK_BYTE_PTR encrypted, 
+                                                                        CK_ULONG_PTR n_encrypted);
+
+CK_RV                    gck_crypto_encrypt_rsa                        (gcry_sexp_t sexp, 
+                                                                        GckCryptoPadding padding, 
+                                                                        CK_BYTE_PTR data, 
+                                                                        CK_ULONG n_data, 
+                                                                        CK_BYTE_PTR encrypted, 
+                                                                        CK_ULONG_PTR n_encrypted);
+
+
+CK_RV                    gck_crypto_decrypt                            (gcry_sexp_t sexp, 
+                                                                        CK_MECHANISM_TYPE mech, 
+                                                                        CK_BYTE_PTR encrypted, 
+                                                                        CK_ULONG n_encrypted, 
+									CK_BYTE_PTR data, 
+									CK_ULONG_PTR n_data);
+
+CK_RV                    gck_crypto_decrypt_rsa                        (gcry_sexp_t sexp, 
+                                                                        GckCryptoPadding padding, 
+                                                                        CK_BYTE_PTR encrypted, 
+                                                                        CK_ULONG n_encrypted, 
+                                                                        CK_BYTE_PTR data, 
+                                                                        CK_ULONG_PTR n_data);
+
+CK_RV                    gck_crypto_sign                               (gcry_sexp_t sexp, 
+                                                                        CK_MECHANISM_TYPE mech, 
+                                                                        CK_BYTE_PTR data, 
+                                                                        CK_ULONG n_data, 
+                                                                        CK_BYTE_PTR signature, 
+                                                                        CK_ULONG_PTR n_signature);
+
+CK_RV                    gck_crypto_sign_rsa                           (gcry_sexp_t sexp, 
+                                                                        GckCryptoPadding padding, 
+                                                                        CK_BYTE_PTR data, 
+                                                                        CK_ULONG n_data, 
+                                                                        CK_BYTE_PTR signature, 
+                                                                        CK_ULONG_PTR n_signature);
+
+CK_RV                    gck_crypto_sign_dsa                           (gcry_sexp_t sexp, 
+                                                                        CK_BYTE_PTR data, 
+                                                                        CK_ULONG n_data, 
+                                                                        CK_BYTE_PTR signature, 
+                                                                        CK_ULONG_PTR n_signature);
+
+CK_RV                    gck_crypto_verify                             (gcry_sexp_t sexp, 
+                                                                        CK_MECHANISM_TYPE mech, 
+                                                                        CK_BYTE_PTR data, 
+                                                                        CK_ULONG n_data, 
+                                                                        CK_BYTE_PTR signature, 
+                                                                        CK_ULONG n_signature);
+
+CK_RV                    gck_crypto_verify_rsa                         (gcry_sexp_t sexp, 
+                                                                        GckCryptoPadding padding, 
+                                                                        CK_BYTE_PTR data, 
+                                                                        CK_ULONG n_data, 
+                                                                        CK_BYTE_PTR signature, 
+                                                                        CK_ULONG n_signature);
+
+
+CK_RV                    gck_crypto_verify_dsa                         (gcry_sexp_t sexp, 
+                                                                        CK_BYTE_PTR data, 
+                                                                        CK_ULONG n_data, 
+                                                                        CK_BYTE_PTR signature, 
+                                                                        CK_ULONG n_signature);
+
+gboolean                 gck_crypto_sexp_parse_key                     (gcry_sexp_t sexp,
+                                                                        int *algorithm, 
+                                                                        gboolean *is_private, 
+                                                                        gcry_sexp_t *numbers);
+
+gboolean                 gck_crypto_sexp_extract_mpi                   (gcry_sexp_t sexp, 
+                                                                        gcry_mpi_t *mpi, 
+                                                                        ...) G_GNUC_NULL_TERMINATED;
+
+guchar*	                 gck_crypto_rsa_pad_raw                        (guint bits, 
+       	                                                                const guchar* raw,
+       	                                                                gsize n_raw, 
+       	                                                                gsize *n_padded);
+
+guchar*                  gck_crypto_rsa_pad_one                        (guint bits, 
+                                                                        const guchar* raw, 
+                                                                        gsize n_raw, 
+                                                                        gsize *n_padded);
+
+guchar*                  gck_crypto_rsa_pad_two                        (guint bits, 
+                                                                        const guchar* raw, 
+                                                                        gsize n_raw, 
+                                                                        gsize *n_padded);
+
+guchar*                  gck_crypto_rsa_unpad_pkcs1                    (guint bits, 
+                                                                        const guchar *padded,
+                                                                        gsize n_padded, 
+                                                                        gsize *n_raw);
+
+guchar*                  gck_crypto_rsa_unpad_one                      (guint bits, 
+                                                                        const guchar *padded, 
+                                                                        gsize n_padded, 
+                                                                        gsize *n_raw);
+
+guchar*                  gck_crypto_rsa_unpad_two                      (guint bits, 
+                                                                        const guchar* padded, 
+                                                                        gsize n_padded, 
+                                                                        gsize *n_raw);
+
+#endif /* GCKCRYPTO_H_ */

Added: trunk/pkcs11/gck/gck-key.c
==============================================================================
--- (empty file)
+++ trunk/pkcs11/gck/gck-key.c	Sun Dec 21 15:44:20 2008
@@ -0,0 +1,291 @@
+/* 
+ * gnome-keyring
+ * 
+ * Copyright (C) 2008 Stefan Walter
+ * 
+ * This program is free software; you can redistribute it and/or modify 
+ * it under the terms of the GNU Lesser General  License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *  
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General  License for more details.
+ *  
+ * You should have received a copy of the GNU Lesser General 
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.  
+ */
+
+#include "config.h"
+
+#include "pkcs11/pkcs11.h"
+
+#include "gck-crypto.h"
+#include "gck-key.h"
+#include "gck-util.h"
+
+enum {
+	PROP_0,
+	PROP_BASE_SEXP,
+	PROP_ALGORITHM
+};
+
+struct _GckKeyPrivate {
+	GckSexp *base_sexp;
+};
+
+G_DEFINE_TYPE (GckKey, gck_key, GCK_TYPE_OBJECT);
+
+/* -----------------------------------------------------------------------------
+ * INTERNAL 
+ */
+
+/* -----------------------------------------------------------------------------
+ * KEY 
+ */
+
+static CK_RV 
+gck_key_real_get_attribute (GckObject *base, CK_ATTRIBUTE* attr)
+{
+	GckKey *self = GCK_KEY (base);
+	
+	switch (attr->type) {
+	case CKA_KEY_TYPE:
+		{
+			switch (gck_key_get_algorithm (self)) {
+			case GCRY_PK_RSA:
+				return gck_util_set_ulong (attr, CKK_RSA);
+			case GCRY_PK_DSA:
+				return gck_util_set_ulong (attr, CKK_DSA);
+			default:
+				g_return_val_if_reached (CKR_GENERAL_ERROR);
+			};
+		}
+		break;
+		
+	case CKA_ID:
+		{
+			guchar hash[20];
+			g_return_val_if_fail (self->pv->base_sexp, CKR_GENERAL_ERROR);
+			if (!gcry_pk_get_keygrip (gck_sexp_get (self->pv->base_sexp), hash))
+				g_return_val_if_reached (CKR_GENERAL_ERROR);
+			return gck_util_set_data (attr, hash, sizeof (hash));
+		}
+		break;
+		
+	case CKA_START_DATE:
+	case CKA_END_DATE:
+		return gck_util_set_data (attr, "", 0);
+	
+	case CKA_DERIVE:
+		return gck_util_set_bool (attr, FALSE);
+		
+	case CKA_LOCAL:
+		return gck_util_set_bool (attr, FALSE);
+		
+	case CKA_KEY_GEN_MECHANISM:
+		return gck_util_set_ulong (attr, CK_UNAVAILABLE_INFORMATION);
+		
+	case CKA_ALLOWED_MECHANISMS:
+		switch (gck_key_get_algorithm (self)) {
+		case GCRY_PK_RSA:
+			return gck_util_set_data (attr, (CK_VOID_PTR)GCK_CRYPTO_RSA_MECHANISMS, 
+			                          sizeof (GCK_CRYPTO_RSA_MECHANISMS));
+		case GCRY_PK_DSA:
+			return gck_util_set_data (attr, (CK_VOID_PTR)GCK_CRYPTO_DSA_MECHANISMS, 
+			                          sizeof (GCK_CRYPTO_DSA_MECHANISMS));
+		default:
+			g_return_val_if_reached (CKR_GENERAL_ERROR);
+		};
+	
+	/* Lookup the certificate subject */
+	case CKA_SUBJECT:
+		/* TODO: When we have certificates, implement this */
+		return gck_util_set_data (attr, "", 0);
+	};
+
+	return GCK_OBJECT_CLASS (gck_key_parent_class)->get_attribute (base, attr);
+}
+
+static GObject* 
+gck_key_constructor (GType type, guint n_props, GObjectConstructParam *props) 
+{
+	GckKey *self = GCK_KEY (G_OBJECT_CLASS (gck_key_parent_class)->constructor(type, n_props, props));
+	g_return_val_if_fail (self, NULL);	
+
+
+	return G_OBJECT (self);
+}
+
+static void
+gck_key_init (GckKey *self)
+{
+	self->pv = G_TYPE_INSTANCE_GET_PRIVATE (self, GCK_TYPE_KEY, GckKeyPrivate);
+
+}
+
+static void
+gck_key_dispose (GObject *obj)
+{
+#if 0
+	GckKey *self = GCK_KEY (obj);
+#endif
+	
+	G_OBJECT_CLASS (gck_key_parent_class)->dispose (obj);
+}
+
+static void
+gck_key_finalize (GObject *obj)
+{
+	GckKey *self = GCK_KEY (obj);
+	
+	if (self->pv->base_sexp)
+		gck_sexp_unref (self->pv->base_sexp);
+	self->pv->base_sexp = NULL;
+
+	G_OBJECT_CLASS (gck_key_parent_class)->finalize (obj);
+}
+
+static void
+gck_key_set_property (GObject *obj, guint prop_id, const GValue *value, 
+                      GParamSpec *pspec)
+{
+	GckKey *self = GCK_KEY (obj);
+	
+	switch (prop_id) {
+	case PROP_BASE_SEXP:
+		gck_key_set_base_sexp (self, g_value_get_boxed (value));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+gck_key_get_property (GObject *obj, guint prop_id, GValue *value, 
+                      GParamSpec *pspec)
+{
+	GckKey *self = GCK_KEY (obj);
+	
+	switch (prop_id) {
+	case PROP_BASE_SEXP:
+		g_value_set_boxed (value, gck_key_get_base_sexp (self));
+		break;
+	case PROP_ALGORITHM:
+		g_value_set_int (value, gck_key_get_algorithm (self));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+gck_key_class_init (GckKeyClass *klass)
+{
+	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+	GckObjectClass *gck_class = GCK_OBJECT_CLASS (klass);
+	
+	gck_key_parent_class = g_type_class_peek_parent (klass);
+	g_type_class_add_private (klass, sizeof (GckKeyPrivate));
+
+	gobject_class->constructor = gck_key_constructor;
+	gobject_class->dispose = gck_key_dispose;
+	gobject_class->finalize = gck_key_finalize;
+	gobject_class->set_property = gck_key_set_property;
+	gobject_class->get_property = gck_key_get_property;
+	
+	gck_class->get_attribute = gck_key_real_get_attribute;
+    
+	g_object_class_install_property (gobject_class, PROP_BASE_SEXP,
+	           g_param_spec_boxed ("base-sexp", "Base S-Exp", "Base Key S-Expression", 
+	                               GCK_BOXED_SEXP, G_PARAM_READWRITE));
+	
+	g_object_class_install_property (gobject_class, PROP_ALGORITHM,
+	           g_param_spec_int ("algorithm", "Algorithm", "GCrypt Algorithm", 
+	                             0, G_MAXINT, 0, G_PARAM_READABLE));
+    
+#if 0
+	signals[SIGNAL] = g_signal_new ("signal", GCK_TYPE_KEY, 
+	                                G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GckKeyClass, signal),
+	                                NULL, NULL, g_cclosure_marshal_VOID__OBJECT, 
+	                                G_TYPE_NONE, 0);
+#endif
+}
+
+/* -----------------------------------------------------------------------------
+ * PRIVATE 
+ */
+
+GckSexp*
+gck_key_get_base_sexp (GckKey *self)
+{
+	g_return_val_if_fail (GCK_IS_KEY (self), NULL);
+	return self->pv->base_sexp;
+}
+
+void
+gck_key_set_base_sexp (GckKey *self, GckSexp *sexp)
+{
+	g_return_if_fail (GCK_IS_KEY (self));
+	if (sexp)
+		gck_sexp_ref (sexp);
+	if (self->pv->base_sexp)
+		gck_sexp_unref (self->pv->base_sexp);
+	self->pv->base_sexp = sexp;
+	g_object_notify (G_OBJECT (self), "base-sexp");
+	g_object_notify (G_OBJECT (self), "algorithm");
+}
+
+int
+gck_key_get_algorithm (GckKey *self) 
+{
+	int algorithm;
+	g_return_val_if_fail (self->pv->base_sexp, 0);
+	if (!gck_crypto_sexp_parse_key (gck_sexp_get (self->pv->base_sexp), &algorithm, NULL, NULL))
+		g_return_val_if_reached (0);
+	return algorithm;
+}
+
+CK_RV
+gck_key_set_key_part (GckKey *self, int algo, const char *part,
+                      CK_ATTRIBUTE_PTR attr)
+{
+	gcry_sexp_t numbers;
+	gcry_mpi_t mpi;
+	int algorithm;
+	CK_RV rv;
+	
+	g_return_val_if_fail (GCK_IS_KEY (self), CKR_GENERAL_ERROR);
+	g_return_val_if_fail (self->pv->base_sexp, CKR_GENERAL_ERROR);
+	
+	if (!gck_crypto_sexp_parse_key (gck_sexp_get (self->pv->base_sexp),
+	                                &algorithm, NULL, &numbers))
+		g_return_val_if_reached (CKR_GENERAL_ERROR);
+	
+	if (algorithm != algo) {
+		gcry_sexp_release (numbers);
+		return CKR_ATTRIBUTE_TYPE_INVALID;
+	}
+	
+	if (!gck_crypto_sexp_extract_mpi (numbers, &mpi, part, NULL))
+		g_return_val_if_reached (CKR_GENERAL_ERROR);
+	rv = gck_util_set_mpi (attr, mpi);
+	gcry_sexp_release (numbers);
+	gcry_mpi_release (mpi);
+	
+	return rv;
+}
+
+GckSexp*
+gck_key_acquire_crypto_sexp (GckKey *self)
+{
+	g_return_val_if_fail (GCK_IS_KEY (self), NULL);
+	g_return_val_if_fail (GCK_KEY_GET_CLASS (self)->acquire_crypto_sexp, NULL);
+	return GCK_KEY_GET_CLASS (self)->acquire_crypto_sexp (self);
+}
+

Added: trunk/pkcs11/gck/gck-key.h
==============================================================================
--- (empty file)
+++ trunk/pkcs11/gck/gck-key.h	Sun Dec 21 15:44:20 2008
@@ -0,0 +1,70 @@
+/* 
+ * gnome-keyring
+ * 
+ * Copyright (C) 2008 Stefan Walter
+ * 
+ * This program is free software; you can redistribute it and/or modify 
+ * it under the terms of the GNU Lesser General  License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *  
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General  License for more details.
+ *  
+ * You should have received a copy of the GNU Lesser General 
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.  
+ */
+
+#ifndef __GCK_KEY_H__
+#define __GCK_KEY_H__
+
+#include <glib-object.h>
+
+#include "gck-sexp.h"
+#include "gck-object.h"
+
+#define GCK_TYPE_KEY               (gck_key_get_type ())
+#define GCK_KEY(obj)               (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCK_TYPE_KEY, GckKey))
+#define GCK_KEY_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST ((klass), GCK_TYPE_KEY, GckKeyClass))
+#define GCK_IS_KEY(obj)            (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCK_TYPE_KEY))
+#define GCK_IS_KEY_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE ((klass), GCK_TYPE_KEY))
+#define GCK_KEY_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS ((obj), GCK_TYPE_KEY, GckKeyClass))
+
+typedef struct _GckKey GckKey;
+typedef struct _GckKeyClass GckKeyClass;
+typedef struct _GckKeyPrivate GckKeyPrivate;
+    
+struct _GckKey {
+	GckObject parent;
+	GckKeyPrivate *pv;
+};
+
+struct _GckKeyClass {
+	GckObjectClass parent_class;
+	
+	/* virtual methods */
+
+	GckSexp* (*acquire_crypto_sexp) (GckKey *self);
+};
+
+GType                      gck_key_get_type               (void);
+
+GckSexp*                   gck_key_get_base_sexp          (GckKey *self);
+
+void                       gck_key_set_base_sexp          (GckKey *self,
+                                                           GckSexp *sexp);
+
+int                        gck_key_get_algorithm          (GckKey *self); 
+
+CK_RV                      gck_key_set_key_part           (GckKey *self,
+                                                           int algorithm,
+                                                           const char *part,
+                                                           CK_ATTRIBUTE_PTR attr);
+
+GckSexp*                   gck_key_acquire_crypto_sexp    (GckKey *self);
+
+#endif /* __GCK_KEY_H__ */

Added: trunk/pkcs11/gck/gck-manager.c
==============================================================================
--- (empty file)
+++ trunk/pkcs11/gck/gck-manager.c	Sun Dec 21 15:44:20 2008
@@ -0,0 +1,411 @@
+/* 
+ * gnome-keyring
+ * 
+ * Copyright (C) 2008 Stefan Walter
+ * 
+ * This program is free software; you can redistribute it and/or modify 
+ * it under the terms of the GNU Lesser General  License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *  
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General  License for more details.
+ *  
+ * You should have received a copy of the GNU Lesser General 
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.  
+ */
+
+#include "config.h"
+
+#include "gck-manager.h"
+#include "gck-util.h"
+
+#include <glib.h>
+#include <glib/gi18n.h>
+
+#include <stdarg.h>
+
+enum {
+	PROP_0,
+	PROP_FOR_TOKEN
+};
+
+struct _GckManagerPrivate {
+	gboolean for_token;
+	GList *objects;
+	GHashTable *object_by_handle;
+};
+
+G_DEFINE_TYPE(GckManager, gck_manager, G_TYPE_OBJECT);
+
+/* -----------------------------------------------------------------------------
+ * HELPERS
+ */
+
+static void
+add_object (GckManager *self, GckObject *object)
+{
+	CK_OBJECT_HANDLE handle;
+	
+	g_assert (GCK_IS_MANAGER (self));
+	g_assert (GCK_IS_OBJECT (object));
+	g_assert (gck_object_get_manager (object) == NULL);
+	
+	handle = gck_object_get_handle (object);
+	if (!handle) {
+		/* Make a new handle */
+		handle = (gck_util_next_handle () & GCK_OBJECT_HANDLE_MASK);
+		if (self->pv->for_token)
+			handle |= GCK_OBJECT_IS_PERMANENT;
+		gck_object_set_handle (object, handle);
+	}
+	
+	/* 
+	 * Mapping of objects by PKCS#11 'handle', we don't ref the
+	 * objects or anything. They're expected to unregister 
+	 * upon finalizing.   
+	 */
+	g_assert (g_hash_table_lookup (self->pv->object_by_handle, &handle) == NULL); 
+	g_hash_table_replace (self->pv->object_by_handle, gck_util_ulong_alloc (handle), object);
+	
+	/* Note objects is being managed */
+	self->pv->objects = g_list_prepend (self->pv->objects, object);
+	gck_object_set_manager (object, self);
+}
+
+static void
+remove_object (GckManager *self, GckObject *object)
+{
+	CK_OBJECT_HANDLE handle;
+	
+	g_assert (GCK_IS_MANAGER (self));
+	g_assert (GCK_IS_OBJECT (object));
+	g_assert (gck_object_get_manager (object) == self);
+	
+	handle = gck_object_get_handle (object);
+	g_assert (handle);
+	
+	/* Mapping of objects by PKCS#11 'handle' */	
+	g_assert (g_hash_table_lookup (self->pv->object_by_handle, &handle) == object); 
+	g_hash_table_remove (self->pv->object_by_handle, &handle);
+	
+	/* Release object management */		
+	self->pv->objects = g_list_remove (self->pv->objects, object);
+	gck_object_set_manager (object, NULL);
+}
+
+/* -----------------------------------------------------------------------------
+ * OBJECT
+ */
+
+static void
+gck_manager_init (GckManager *self)
+{
+	self->pv = G_TYPE_INSTANCE_GET_PRIVATE(self, GCK_TYPE_MANAGER, GckManagerPrivate);
+	self->pv->object_by_handle = g_hash_table_new_full (gck_util_ulong_hash, gck_util_ulong_equal, 
+	                                                    gck_util_ulong_free, NULL);
+}
+
+static void
+gck_manager_set_property (GObject *obj, guint prop_id, const GValue *value, 
+                          GParamSpec *pspec)
+{
+	GckManager *self = GCK_MANAGER (obj);
+	
+	switch (prop_id) {
+	case PROP_FOR_TOKEN:
+		self->pv->for_token = g_value_get_boolean (value);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+gck_manager_get_property (GObject *obj, guint prop_id, GValue *value, 
+                          GParamSpec *pspec)
+{
+	GckManager *self = GCK_MANAGER (obj);
+	
+	switch (prop_id) {
+	case PROP_FOR_TOKEN:
+		g_value_set_boolean (value, gck_manager_get_for_token (self));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+		break;
+	}
+}
+
+
+static void
+gck_manager_dispose (GObject *obj)
+{
+	GckManager *self = GCK_MANAGER (obj);
+ 	GList *objects, *l;
+
+	/* Unregister all objects */
+	objects = g_list_copy (self->pv->objects);
+	for (l = objects; l; l = g_list_next (l)) 
+		gck_manager_unregister_object (self, GCK_OBJECT (l->data));
+	g_list_free (objects);
+	
+	g_return_if_fail (self->pv->objects == NULL);
+ 	g_return_if_fail (g_hash_table_size (self->pv->object_by_handle) == 0);
+
+	G_OBJECT_CLASS (gck_manager_parent_class)->dispose (obj);
+}
+
+static void
+gck_manager_finalize (GObject *obj)
+{
+	GckManager *self = GCK_MANAGER (obj);
+ 	
+	g_hash_table_destroy (self->pv->object_by_handle);
+	g_assert (!self->pv->objects);
+
+	G_OBJECT_CLASS (gck_manager_parent_class)->finalize (obj);
+}
+
+static void
+gck_manager_class_init (GckManagerClass *klass)
+{
+	GObjectClass *gobject_class;
+	gobject_class = (GObjectClass*)klass;
+
+	gck_manager_parent_class = g_type_class_peek_parent (klass);
+	gobject_class->dispose = gck_manager_dispose;
+	gobject_class->get_property = gck_manager_get_property;
+	gobject_class->set_property = gck_manager_set_property;
+	gobject_class->finalize = gck_manager_finalize;
+
+	g_type_class_add_private (gobject_class, sizeof (GckManagerPrivate));
+	
+	g_object_class_install_property (gobject_class, PROP_FOR_TOKEN,
+	         g_param_spec_boolean ("for-token", "For Token", "Whether this manager is for token objects or not", 
+	                               FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+	
+}
+
+/* ------------------------------------------------------------------------
+ * PUBLIC METHODS
+ */
+
+gboolean
+gck_manager_get_for_token (GckManager *self)
+{
+	g_return_val_if_fail (GCK_IS_MANAGER (self), FALSE);
+	return self->pv->for_token;
+}
+
+void
+gck_manager_register_object (GckManager *self, GckObject *object)
+{
+	g_return_if_fail (GCK_IS_MANAGER (self));
+	g_return_if_fail (GCK_IS_OBJECT (object));
+	g_return_if_fail (gck_object_get_manager (object) == NULL);
+
+	add_object (self, object);
+}
+
+void
+gck_manager_unregister_object (GckManager *self, GckObject *object)
+{
+	g_return_if_fail (GCK_IS_MANAGER (self));
+	g_return_if_fail (GCK_IS_OBJECT (object));
+	g_return_if_fail (gck_object_get_manager (object) == self);
+
+	remove_object (self, object);
+}
+
+GckObject*
+gck_manager_lookup_handle (GckManager *self, CK_OBJECT_HANDLE handle)
+{
+	g_return_val_if_fail (GCK_IS_MANAGER (self), NULL);
+	g_return_val_if_fail (handle != 0, NULL);
+	
+	return (GckObject*)g_hash_table_lookup (self->pv->object_by_handle, &handle);
+}
+
+CK_RV
+gck_manager_find_handles (GckManager *self, CK_ATTRIBUTE_PTR template,
+                          CK_ULONG count, GArray *found)
+{
+	CK_OBJECT_HANDLE handle;
+	GckObject *object;
+	GList *l;
+	
+	g_return_val_if_fail (GCK_IS_MANAGER (self), CKR_GENERAL_ERROR);
+	g_return_val_if_fail (template || !count, CKR_GENERAL_ERROR);
+	g_return_val_if_fail (found, CKR_GENERAL_ERROR);
+	
+	for (l = self->pv->objects; l; l = g_list_next (l)) {
+		object = GCK_OBJECT (l->data);
+		if (gck_object_match_all (object, template, count)) {
+			handle = gck_object_get_handle (object);
+			g_return_val_if_fail (handle != 0, CKR_GENERAL_ERROR);
+			g_array_append_val (found, handle);
+		}
+	}
+	
+	return CKR_OK;
+	
+}
+
+#if 0
+GList*
+gck_manager_findv (GckManager *self, GType gtype, ...)
+{
+	CK_ATTRIBUTE attr;
+	GArray *attrs = NULL;
+	va_list va;
+	CK_ULONG uval, spacer;
+	CK_BBOOL bval;
+	CK_VOID_PTR value;
+	GList *ret = NULL;
+	
+	va_start (va, gtype);
+	
+	for (;;) {
+		memset (&attr, 0, sizeof (attr));
+		
+		attr.type = va_arg (va, CK_ATTRIBUTE_TYPE);
+		if (!attr.type) {
+			
+			/* 
+			 * We keep this in a lower scope that our alloca 
+			 * allocations, just in case some compiler gets the 
+			 * bright idea (like GNU C in some cases) that it'll
+			 * cleanup at variable scope rather than function scope.
+			 */
+			 
+			ret = gck_manager_find (self, gtype, attrs);
+			break;
+		}	
+		
+		switch (gck_attribute_data_type (attr.type)) {
+		case GCK_DATA_ULONG:
+			uval = va_arg (va, CK_ULONG);
+			gck_attribute_set_ulong (&attr, uval);
+			spacer = va_arg (va, CK_ULONG);
+			break;
+		
+		case GCK_DATA_BOOL:
+			bval = va_arg (va, int) ? CK_TRUE : CK_FALSE;
+			gck_attribute_set_boolean (&attr, bval);
+			spacer = va_arg (va, CK_ULONG);
+			break;
+		
+		case GCK_DATA_BYTES:
+			value = va_arg (va, CK_VOID_PTR);
+			uval = va_arg (va, CK_ULONG);
+			gck_attribute_set_data (&attr, value, uval);
+			break;
+
+		default:
+			g_warning ("unsupported type of data for attribute type: %d", (int)attr.type);
+			return NULL;	
+		};
+		
+		if (!attrs)
+			attrs = gck_attributes_new ();
+		g_array_append_val (attrs, attr);
+	}
+
+	va_end (va);
+	
+	gck_attributes_free (attrs);
+	return ret;
+}
+
+GList*
+gck_manager_find (GckManager *self, GType gtype, GArray *attrs)
+{
+	CK_OBJECT_CLASS *ocls = NULL;
+	GckObject *object;
+	gboolean do_refresh = TRUE;
+	GList *l, *objects = NULL;
+	
+	g_return_val_if_fail (GCK_IS_MANAGER (self), NULL);
+
+	/* Figure out the class of objects we're loading */
+	if (attrs)
+		ocls = (CK_OBJECT_CLASS*)gck_attributes_find (attrs, CKA_CLASS);
+	if (ocls) {
+		switch (*ocls) {
+		/* TODO: Add here classes for which we don't want to refresh */
+		default:
+			break;
+		}
+	}
+	
+	if (gtype) {
+		switch (gtype) {
+		/* TODO: Add here classes for which we don't want to refresh */
+		default:
+			break;
+		}
+	}
+
+	if (do_refresh) 
+		gck_storage_refresh_all ();
+
+	/* TODO: We may want to only go through objects of CKA_CLASS */
+	for (l = self->objects; l; l = g_list_next (l)) {
+		object = GCK_OBJECT (l->data);
+		if (gtype && !G_TYPE_CHECK_INSTANCE_TYPE (l->data, gtype))
+			continue;
+		if (!attrs || gck_object_match (object, attrs))
+			objects = g_list_prepend (objects, object);
+	}
+	
+	return objects;
+}
+
+GckObject*
+gck_manager_find_by_id (GckManager *self, GType gtype, gkrconstid id)
+{
+	CK_ATTRIBUTE attr;
+	GckObject *object;
+	gsize len;
+	GList *l;
+	
+	g_return_val_if_fail (id, NULL);
+	g_return_val_if_fail (GCK_IS_MANAGER (self), NULL);
+
+	attr.pValue = (CK_VOID_PTR)gkr_id_get_raw (id, &len);
+	attr.ulValueLen = len;
+	attr.type = CKA_ID; 
+
+	/* TODO: This needs to be done more efficiently */
+	for (l = self->objects; l; l = g_list_next (l)) {
+		object = GCK_OBJECT (l->data);
+		if (gtype && !G_TYPE_CHECK_INSTANCE_TYPE (l->data, gtype))
+			continue;
+		if (gck_object_match_one (object, &attr))
+			return object;
+	}
+
+	return NULL;	
+}
+
+GckObject*
+gck_manager_find_by_digest (GckManager *self, gkrconstid digest)
+{
+	GckManagerPrivate *pv;
+	GckObject *object;
+	
+	g_return_val_if_fail (digest, NULL);
+	g_return_val_if_fail (GCK_IS_MANAGER (self), NULL);
+	pv = GCK_MANAGER_GET_PRIVATE (self);
+
+	object = GCK_OBJECT (g_hash_table_lookup (pv->object_by_digest, digest));
+	return object;
+}
+
+#endif 

Added: trunk/pkcs11/gck/gck-manager.h
==============================================================================
--- (empty file)
+++ trunk/pkcs11/gck/gck-manager.h	Sun Dec 21 15:44:20 2008
@@ -0,0 +1,113 @@
+/* 
+ * gnome-keyring
+ * 
+ * Copyright (C) 2008 Stefan Walter
+ * 
+ * This program is free software; you can redistribute it and/or modify 
+ * it under the terms of the GNU Lesser General  License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *  
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General  License for more details.
+ *  
+ * You should have received a copy of the GNU Lesser General 
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.  
+ */
+
+#ifndef __GCK_MANAGER_H__
+#define __GCK_MANAGER_H__
+
+#include <gcrypt.h>
+#include <glib-object.h>
+
+#include "gck-object.h"
+
+/* 
+ * GckManager
+ * 
+ * A GckManager tracks a set of GckObject objects. It does not own 
+ * those objects. Once an object is registered with the manager it gets 
+ * an identifier.  
+ * 
+ * An object will unregister itself from the manager when it is destroyed or 
+ * it can be done explicitely.  
+ * 
+ * A singleton GckManager exists for token objects, those stored in 
+ * persistent storage. This manager lasts for the lifetime of the daemon.
+ * 
+ * Other GckManager objects can exist per client for session or 
+ * temporary objects. Multiple requests for a manager for the same client
+ * will return the same manager. Once all references dissappear this 
+ * manager will go away.
+ */
+
+G_BEGIN_DECLS
+
+#include "gck-object.h"
+
+#include "pkcs11/pkcs11.h"
+
+#define GCK_TYPE_MANAGER             (gck_manager_get_type ())
+#define GCK_MANAGER(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCK_TYPE_MANAGER, GckManager))
+#define GCK_MANAGER_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), GCK_TYPE_MANAGER, GckManager))
+#define GCK_IS_MANAGER(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCK_TYPE_MANAGER))
+#define GCK_IS_MANAGER_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), GCK_TYPE_MANAGER))
+#define GCK_MANAGER_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), GCK_TYPE_MANAGER, GckManagerClass))
+
+typedef struct _GckManagerClass GckManagerClass;
+typedef struct _GckManagerPrivate GckManagerPrivate;
+
+struct _GckManager {
+	 GObject parent;
+	 GckManagerPrivate *pv;
+};
+
+struct _GckManagerClass {
+	GObjectClass parent_class;
+};
+
+GType                   gck_manager_get_type            (void) G_GNUC_CONST;
+
+gboolean                gck_manager_get_for_token       (GckManager *self);
+
+#if 0
+GType                   gck_manager_type_from_string    (const gchar *type);
+#endif
+
+void                    gck_manager_register_object     (GckManager *self, 
+                                                         GckObject *object);
+
+void                    gck_manager_unregister_object   (GckManager *self, 
+                                                         GckObject *object);
+
+GckObject*              gck_manager_lookup_handle       (GckManager *self,
+                                                         CK_OBJECT_HANDLE obj);
+
+CK_RV                   gck_manager_find_handles        (GckManager *self,
+                                                         CK_ATTRIBUTE_PTR template,
+                                                         CK_ULONG count,
+                                                         GArray *found);
+
+#if 0
+GList*                  gck_manager_find                (GckManager *self,
+                                                         GType type, GArray *attrs);
+                                                                  
+GList*                  gck_manager_findv               (GckManager *self,
+                                                           GType gtype, ...) G_GNUC_NULL_TERMINATED;
+
+GckObject*              gck_manager_find_by_id         (GckManager *self,
+                                                           GType gtype, gkrconstid id);
+
+GckObject*              gck_manager_find_by_digest     (GckManager *self,
+                                                           gkrconstid digest);
+#endif
+
+G_END_DECLS
+
+#endif /* __GCK_MANAGER_H__ */
+

Added: trunk/pkcs11/gck/gck-module-ep.h
==============================================================================
--- (empty file)
+++ trunk/pkcs11/gck/gck-module-ep.h	Sun Dec 21 15:44:20 2008
@@ -0,0 +1,1114 @@
+/* 
+ * gnome-keyring
+ * 
+ * Copyright (C) 2008 Stefan Walter
+ * 
+ * This program is free software; you can redistribute it and/or modify 
+ * it under the terms of the GNU Lesser General  License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *  
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General  License for more details.
+ *  
+ * You should have received a copy of the GNU Lesser General 
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.  
+ */
+
+#include "gck-module.h"
+
+#include "pkcs11/pkcs11.h"
+
+static GckModule *pkcs11_module = NULL;
+static pid_t pkcs11_module_pid = 0;
+static GStaticMutex pkcs11_module_mutex = G_STATIC_MUTEX_INIT;
+
+/* Forward declaration */
+CK_RV C_GetFunctionList (CK_FUNCTION_LIST_PTR_PTR list);
+
+static CK_RV
+gck_C_Initialize (CK_VOID_PTR init_args)
+{
+	CK_RV rv = CKR_OK;
+	pid_t pid = getpid ();
+	
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+		if (pkcs11_module != NULL) {
+			if (pkcs11_module_pid != pid) 
+				rv = CKR_CRYPTOKI_ALREADY_INITIALIZED;
+			else 
+				pkcs11_module_pid = pid;
+		} else {
+			pkcs11_module = g_object_new (GCK_MODULE_TYPE, NULL);
+			pkcs11_module_pid = pid;
+		}
+
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+
+	return CKR_OK;
+}
+
+static CK_RV
+gck_C_Finalize (CK_VOID_PTR reserved)
+{
+	CK_RV rv;
+	
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+		if (pkcs11_module == NULL) {
+			rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+		} else {
+			g_object_unref (pkcs11_module);
+			pkcs11_module = NULL;
+			pkcs11_module_pid = 0;
+		}
+
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+}
+
+static CK_RV
+gck_C_GetInfo (CK_INFO_PTR info)
+{
+	CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+	
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+		if (pkcs11_module != NULL)
+			rv = gck_module_C_GetInfo (pkcs11_module, info);
+			
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+}
+
+static CK_RV
+gck_C_GetFunctionList (CK_FUNCTION_LIST_PTR_PTR list)
+{
+	xxxxx;
+}
+
+static CK_RV
+gck_C_GetSlotList (CK_BBOOL token_present, CK_SLOT_ID_PTR slot_list, CK_ULONG_PTR count)
+{
+	CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+	
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+		if (pkcs11_module != NULL)
+			rv = gck_module_C_GetSlotList (pkcs11_module, token_present, slot_list, count);
+			
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+}
+
+static CK_RV
+gck_C_GetSlotInfo (CK_SLOT_ID id, CK_SLOT_INFO_PTR info)
+{
+	CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+	
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+		if (pkcs11_module != NULL)
+			rv = gck_module_C_GetSlotInfo (pkcs11_module, id, info);
+			
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+}
+
+static CK_RV
+gck_C_GetTokenInfo (CK_SLOT_ID id, CK_TOKEN_INFO_PTR info)
+{
+	CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+	
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+		if (pkcs11_module != NULL)
+			rv = gck_module_C_GetTokenInfo (pkcs11_module, id, info);
+			
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+}
+
+static CK_RV
+gck_C_GetMechanismList (CK_SLOT_ID id, CK_MECHANISM_TYPE_PTR mechanism_list, CK_ULONG_PTR count)
+{
+	CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+	
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+		if (pkcs11_module != NULL)
+			rv = gck_module_C_GetMechanismList (pkcs11_module, id, info);
+			
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+}
+
+static CK_RV
+gck_C_GetMechanismInfo (CK_SLOT_ID id, CK_MECHANISM_TYPE type, CK_MECHANISM_INFO_PTR info)
+{
+	CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+	
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+		if (pkcs11_module != NULL)
+			rv = gck_module_C_GetMechanismInfo (pkcs11_module, id, type, info);
+			
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+}
+
+static CK_RV
+gck_C_InitToken (CK_SLOT_ID id, CK_UTF8CHAR_PTR pin, CK_ULONG pin_len, CK_UTF8CHAR_PTR label)
+{
+	CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+	
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+		if (pkcs11_module != NULL)
+			rv = gck_module_C_InitToken (pkcs11_module, id, pin, pin_len, label);
+			
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+}
+
+static CK_RV
+gck_C_WaitForSlotEvent (CK_FLAGS flags, CK_SLOT_ID_PTR slot, CK_VOID_PTR reserved)
+{
+	xxxxxxx;
+}
+
+static CK_RV
+gck_C_OpenSession (CK_SLOT_ID id, CK_FLAGS flags, CK_VOID_PTR user_data, CK_NOTIFY callback, CK_SESSION_HANDLE_PTR session)
+{
+	CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+	
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+		if (pkcs11_module != NULL)
+			rv = gck_module_C_OpenSession (pkcs11_module, id, flags, user_data, callback, session);
+			
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+}
+
+static CK_RV
+gck_C_CloseSession (CK_SESSION_HANDLE session)
+{
+	CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+	
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+		if (pkcs11_module != NULL)
+			rv = gck_module_C_CloseSession (pkcs11_module, session);
+			
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+}
+
+static CK_RV
+gck_C_CloseAllSessions (CK_SLOT_ID id)
+{
+	CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+	
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+		if (pkcs11_module != NULL)
+			rv = gck_module_C_CloseAllSessions (pkcs11_module, id);
+			
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+}
+
+static CK_RV
+gck_C_GetFunctionStatus (CK_SESSION_HANDLE session)
+{
+	CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+	
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+		if (pkcs11_module != NULL)
+			rv = gck_session_C_GetFunctionStatus (gck_module_lookup_session (session));
+			
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+
+}
+
+static CK_RV
+gck_C_CancelFunction (CK_SESSION_HANDLE session)
+{
+	CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+	
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+		if (pkcs11_module != NULL)
+			rv = gck_session_C_CancelFunction (gck_module_lookup_session (session));
+			
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+}
+
+static CK_RV
+gck_C_GetSessionInfo (CK_SESSION_HANDLE session, CK_SESSION_INFO_PTR info)
+{
+	CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+	
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+		if (pkcs11_module != NULL)
+			rv = gck_session_C_GetSessionInfo (gck_module_lookup_session (session),
+			                                   info);
+			
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+}
+
+static CK_RV
+gck_C_InitPIN (CK_SESSION_HANDLE session, CK_UTF8CHAR_PTR pin, CK_ULONG pin_len)
+{
+	CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+	
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+		if (pkcs11_module != NULL)
+			rv = gck_session_C_InitPIN (gck_module_lookup_session (session),
+			                                   pin, pin_len);
+			
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+}
+
+static CK_RV
+gck_C_SetPIN (CK_SESSION_HANDLE session, CK_UTF8CHAR_PTR old_pin, CK_ULONG old_pin_len, CK_UTF8CHAR_PTR new_pin, CK_ULONG new_pin_len)
+{
+	CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+	
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+		if (pkcs11_module != NULL)
+			rv = gck_session_C_SetPIN (gck_module_lookup_session (session),
+			                           old_pin, old_pin_len, new_pin, new_pin_len);
+			
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+}
+
+static CK_RV
+gck_C_GetOperationState (CK_SESSION_HANDLE session, CK_BYTE_PTR operation_state, CK_ULONG_PTR operation_state_len)
+{
+	CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+	
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+		if (pkcs11_module != NULL)
+			rv = gck_session_C_GetOperationState (gck_module_lookup_session (session),
+			                                      operation_state, operation_state_len);
+			
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+}
+
+static CK_RV
+gck_C_SetOperationState (CK_SESSION_HANDLE session, CK_BYTE_PTR operation_state,
+                         CK_ULONG operation_state_len, CK_OBJECT_HANDLE encryption_key,
+                         CK_OBJECT_HANDLE authentication_key)
+{
+	CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+	
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+		if (pkcs11_module != NULL)
+			rv = gck_session_C_SetOperationState (gck_module_lookup_session (session),
+			                                      operation_state, operation_state_len, encryption_key, authentication_key);
+			
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+}
+
+static CK_RV
+gck_C_Login (CK_SESSION_HANDLE session, CK_USER_TYPE user_type,
+             CK_UTF8CHAR_PTR pin, CK_ULONG pin_len)
+{
+	CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+	
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+		if (pkcs11_module != NULL)
+			rv = gck_module_C_Login (session, user_type, pin, pin_len);
+			
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+
+}
+
+static CK_RV
+gck_C_Logout (CK_SESSION_HANDLE session)
+{
+	CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+	
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+		if (pkcs11_module != NULL)
+			rv = gck_module_C_Logout (session);
+			
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+}
+
+static CK_RV
+gck_C_CreateObject (CK_SESSION_HANDLE session, CK_ATTRIBUTE_PTR template,
+                    CK_ULONG count, CK_OBJECT_HANDLE_PTR new_object)
+{
+	CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+		
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+	if (pkcs11_module != NULL)
+		rv = gck_session_C_CreateObject (gck_module_lookup_session (session),
+		                                 template, count, new_object);
+				
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+}
+
+static CK_RV
+gck_C_CopyObject (CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object,
+                  CK_ATTRIBUTE_PTR template, CK_ULONG count,
+                  CK_OBJECT_HANDLE_PTR new_object)
+{
+	CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+		
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+	if (pkcs11_module != NULL)
+		rv = gck_session_C_CopyObject (gck_module_lookup_session (session),
+		                               object, template, count, new_object);
+				
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+}
+
+
+static CK_RV
+gck_C_DestroyObject (CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object)
+{
+	CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+		
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+	if (pkcs11_module != NULL)
+		rv = gck_session_C_DestroyObject (gck_module_lookup_session (session), object);
+				
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+}
+
+static CK_RV
+gck_C_GetObjectSize (CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object,
+                     CK_ULONG_PTR size)
+{
+	CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+		
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+	if (pkcs11_module != NULL)
+		rv = gck_object_C_GetObjectSize (gck_module_lookup_object (session, object), 
+		                                 size);
+				
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+}
+
+static CK_RV
+gck_C_GetAttributeValue (CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object,
+                         CK_ATTRIBUTE_PTR template, CK_ULONG count)
+{
+	CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+		
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+	if (pkcs11_module != NULL)
+		rv = gck_object_C_GetAttributeValue (gck_module_lookup_object (session, object), 
+		                                     template, count);
+				
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+}
+
+static CK_RV
+gck_C_SetAttributeValue (CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object,
+                         CK_ATTRIBUTE_PTR template, CK_ULONG count)
+{
+	CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+		
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+	if (pkcs11_module != NULL)
+		rv = gck_object_C_SetAttributeValue (gck_module_lookup_object (session, object), 
+		                                     template, count);
+				
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+}
+
+static CK_RV
+gck_C_FindObjectsInit (CK_SESSION_HANDLE session, CK_ATTRIBUTE_PTR template,
+                       CK_ULONG count)
+{
+	CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+		
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+	if (pkcs11_module != NULL)
+		rv = gck_session_C_FindObjectsInit (gck_module_lookup_session (session), 
+		                                    template, count);
+	
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+}
+
+static CK_RV
+gck_C_FindObjects (CK_SESSION_HANDLE session, CK_OBJECT_HANDLE_PTR objects,
+                   CK_ULONG max_count, CK_ULONG_PTR count)
+{
+	CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+		
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+	if (pkcs11_module != NULL)
+		rv = gck_session_C_FindObjects (gck_module_lookup_session (session), 
+		                                objects, max_count, count);
+				
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+}
+
+static CK_RV
+gck_C_FindObjectsFinal (CK_SESSION_HANDLE session)
+{
+	CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+		
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+	if (pkcs11_module != NULL)
+		rv = gck_session_C_FindObjectsFinal (gck_module_lookup_session (session));
+				
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+}
+
+static CK_RV
+gck_C_EncryptInit (CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism,
+                   CK_OBJECT_HANDLE key)
+{
+	CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+		
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+	if (pkcs11_module != NULL)
+		rv = gck_session_C_EncryptInit (gck_module_lookup_session (session),
+		                                mechanism, key);
+				
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+}
+
+static CK_RV
+gck_C_Encrypt (CK_SESSION_HANDLE session, CK_BYTE_PTR data, CK_ULONG data_len,
+               CK_BYTE_PTR encrypted_data, CK_ULONG_PTR encrypted_data_len)
+{
+	CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+		
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+	if (pkcs11_module != NULL)
+		rv = gck_session_C_Encrypt (gck_module_lookup_session (session),
+		                            data, data_len, encrypted_data, encrypted_data_len);
+				
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+}
+
+static CK_RV
+gck_C_EncryptUpdate (CK_SESSION_HANDLE session, CK_BYTE_PTR part,
+                     CK_ULONG part_len, CK_BYTE_PTR encrypted_part,
+                     CK_ULONG_PTR encrypted_part_len)
+{
+	CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+		
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+	if (pkcs11_module != NULL)
+		rv = gck_session_C_EncryptUpdate (gck_module_lookup_session (session),
+		                                  part, part_len, encrypted_part, encrypted_part_len);
+				
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+}
+
+static CK_RV
+gck_C_EncryptFinal (CK_SESSION_HANDLE session, CK_BYTE_PTR last_part,
+                    CK_ULONG_PTR last_part_len)
+{
+	CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+		
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+	if (pkcs11_module != NULL)
+		rv = gck_session_C_EncryptFinal (gck_module_lookup_session (session),
+		                                 last_part, last_part_len);
+				
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+}
+
+static CK_RV
+gck_C_DecryptInit (CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism,
+                   CK_OBJECT_HANDLE key)
+{
+	CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+		
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+	if (pkcs11_module != NULL)
+		rv = gck_session_C_DecryptInit (gck_module_lookup_session (session),
+		                                mechanism, key);
+				
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+}
+
+static CK_RV
+gck_C_Decrypt (CK_SESSION_HANDLE session, CK_BYTE_PTR enc_data,
+               CK_ULONG enc_data_len, CK_BYTE_PTR data, CK_ULONG_PTR data_len)
+{
+	CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+		
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+	if (pkcs11_module != NULL)
+		rv = gck_session_C_Decrypt (gck_module_lookup_session (session),
+		                            enc_data, enc_data_len, data, data_len);
+				
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+}
+
+static CK_RV
+gck_C_DecryptUpdate (CK_SESSION_HANDLE session, CK_BYTE_PTR enc_part,
+                     CK_ULONG enc_part_len, CK_BYTE_PTR part, CK_ULONG_PTR part_len)
+{
+	CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+		
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+	if (pkcs11_module != NULL)
+		rv = gck_session_C_DecryptUpdate (gck_module_lookup_session (session),
+		                                  enc_part, enc_part_len, part, part_len);
+				
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+}
+
+static CK_RV
+gck_C_DecryptFinal (CK_SESSION_HANDLE session, CK_BYTE_PTR last_part,
+                    CK_ULONG_PTR last_part_len)
+{
+	CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+		
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+	if (pkcs11_module != NULL)
+		rv = gck_session_C_DecryptFinal (gck_module_lookup_session (session),
+		                                 last_part, last_part_len);
+				
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+}
+
+static CK_RV
+gck_C_DigestInit (CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism)
+{
+	CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+		
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+	if (pkcs11_module != NULL)
+		rv = gck_session_C_DigestInit (gck_module_lookup_session (session),
+		                               mechanism);
+				
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+}
+
+static CK_RV
+gck_C_Digest (CK_SESSION_HANDLE session, CK_BYTE_PTR data, CK_ULONG data_len,
+              CK_BYTE_PTR digest, CK_ULONG_PTR digest_len)
+{
+	CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+		
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+	if (pkcs11_module != NULL)
+		rv = gck_session_C_Digest (gck_module_lookup_session (session),
+		                           data, data_len, digest, digest_len);
+				
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+}
+
+static CK_RV
+gck_C_DigestUpdate (CK_SESSION_HANDLE session, CK_BYTE_PTR part, CK_ULONG part_len)
+{
+	CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+		
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+	if (pkcs11_module != NULL)
+		rv = gck_session_C_DigestUpdate (gck_module_lookup_session (session),
+		                                  part, part_len);
+				
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+}
+
+static CK_RV
+gck_C_DigestKey (CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key)
+{
+	CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+		
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+	if (pkcs11_module != NULL)
+		rv = gck_session_C_DigestKey (gck_module_lookup_session (session),
+		                              key);
+				
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+}
+
+static CK_RV
+gck_C_DigestFinal (CK_SESSION_HANDLE session, CK_BYTE_PTR digest,
+                   CK_ULONG_PTR digest_len)
+{
+	CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+		
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+	if (pkcs11_module != NULL)
+		rv = gck_session_C_DigestFinal (gck_module_lookup_session (session),
+		                                digest, digest_len);
+				
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+}
+
+static CK_RV
+gck_C_SignInit (CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism,
+                CK_OBJECT_HANDLE key)
+{
+	CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+		
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+	if (pkcs11_module != NULL)
+		rv = gck_session_C_SignInit (gck_module_lookup_session (session),
+		                             mechanism, key);
+				
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+}
+
+static CK_RV
+gck_C_Sign (CK_SESSION_HANDLE session, CK_BYTE_PTR data, CK_ULONG data_len,
+            CK_BYTE_PTR signature, CK_ULONG_PTR signature_len)
+{
+	CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+		
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+	if (pkcs11_module != NULL)
+		rv = gck_session_C_Sign (gck_module_lookup_session (session),
+		                         data, data_len, signature, signature_len);
+				
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+}
+
+static CK_RV
+gck_C_SignUpdate (CK_SESSION_HANDLE session, CK_BYTE_PTR part, CK_ULONG part_len)
+{
+	CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+		
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+	if (pkcs11_module != NULL)
+		rv = gck_session_C_SignUpdate (gck_module_lookup_session (session),
+		                               part, part_len);
+				
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+}
+
+static CK_RV
+gck_C_SignFinal (CK_SESSION_HANDLE session, CK_BYTE_PTR signature,
+                 CK_ULONG_PTR signature_len)
+{
+	CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+		
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+	if (pkcs11_module != NULL)
+		rv = gck_session_C_SignFinal (gck_module_lookup_session (session),
+		                              signature, signature_len);
+				
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+}
+
+static CK_RV
+gck_C_SignRecoverInit (CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism,
+                       CK_OBJECT_HANDLE key)
+{
+	CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+		
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+	if (pkcs11_module != NULL)
+		rv = gck_session_C_SignRecoverInit (gck_module_lookup_session (session),
+		                                    mechanism, key);
+				
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+}
+
+static CK_RV
+gck_C_SignRecover (CK_SESSION_HANDLE session, CK_BYTE_PTR data, CK_ULONG data_len, 
+                   CK_BYTE_PTR signature, CK_ULONG_PTR signature_len)
+{
+	CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+		
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+	if (pkcs11_module != NULL)
+		rv = gck_session_C_SignRecover (gck_module_lookup_session (session),
+		                                data, data_len, signature, signature_len);
+				
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+}
+
+static CK_RV
+gck_C_VerifyInit (CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism,
+                  CK_OBJECT_HANDLE key)
+{
+	CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+		
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+	if (pkcs11_module != NULL)
+		rv = gck_session_C_VerifyInit (gck_module_lookup_session (session),
+		                               mechanism, key);
+				
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+}
+
+static CK_RV
+gck_C_Verify (CK_SESSION_HANDLE session, CK_BYTE_PTR data, CK_ULONG data_len,
+              CK_BYTE_PTR signature, CK_ULONG signature_len)
+{
+	CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+		
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+	if (pkcs11_module != NULL)
+		rv = gck_session_C_Verify (gck_module_lookup_session (session),
+		                           data, data_len, signature, signature_len);
+				
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+}
+
+static CK_RV
+gck_C_VerifyUpdate (CK_SESSION_HANDLE session, CK_BYTE_PTR part, CK_ULONG part_len)
+{
+	CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+		
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+	if (pkcs11_module != NULL)
+		rv = gck_session_C_VerifyUpdate (gck_module_lookup_session (session),
+		                                 part, part_len);
+				
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+}
+
+static CK_RV
+gck_C_VerifyFinal (CK_SESSION_HANDLE session, CK_BYTE_PTR signature,
+                   CK_ULONG signature_len)
+{
+	CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+		
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+	if (pkcs11_module != NULL)
+		rv = gck_session_C_VerifyFinal (gck_module_lookup_session (session),
+		                                signature, signature_len);
+				
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+}
+
+static CK_RV
+gck_C_VerifyRecoverInit (CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism,
+                         CK_OBJECT_HANDLE key)
+{
+	CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+		
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+	if (pkcs11_module != NULL)
+		rv = gck_session_C_VerifyRecoverInit (gck_module_lookup_session (session),
+		                                      mechanism, key);
+				
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+}
+
+static CK_RV
+gck_C_VerifyRecover (CK_SESSION_HANDLE session, CK_BYTE_PTR signature,
+                     CK_ULONG signature_len, CK_BYTE_PTR data, CK_ULONG_PTR data_len)
+{
+	CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+		
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+	if (pkcs11_module != NULL)
+		rv = gck_session_C_VerifyRecover (gck_module_lookup_session (session),
+		                                  signature, signature_len, data, data_len);
+				
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+}
+
+static CK_RV
+gck_C_DigestEncryptUpdate (CK_SESSION_HANDLE session, CK_BYTE_PTR part,
+                           CK_ULONG part_len, CK_BYTE_PTR enc_part,
+                           CK_ULONG_PTR enc_part_len)
+{
+	CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+		
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+	if (pkcs11_module != NULL)
+		rv = gck_session_C_DigestEncryptUpdate (gck_module_lookup_session (session),
+		                                        part, part_len, enc_part, enc_part_len);
+				
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+}
+
+static CK_RV
+gck_C_DecryptDigestUpdate (CK_SESSION_HANDLE session, CK_BYTE_PTR enc_part,
+                           CK_ULONG enc_part_len, CK_BYTE_PTR part, 
+                           CK_ULONG_PTR part_len)
+{
+	CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+		
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+	if (pkcs11_module != NULL)
+		rv = gck_session_C_DecryptDigestUpdate (gck_module_lookup_session (session),
+		                                        enc_part, enc_part_len, part, part_len);
+				
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+}
+
+static CK_RV
+gck_C_SignEncryptUpdate (CK_SESSION_HANDLE session, CK_BYTE_PTR part,
+                         CK_ULONG part_len, CK_BYTE_PTR enc_part,
+                         CK_ULONG_PTR enc_part_len)
+{
+	CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+		
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+	if (pkcs11_module != NULL)
+		rv = gck_session_C_SignEncryptUpdate (gck_module_lookup_session (session),
+		                                      part, part_len, enc_part, enc_part_len);
+				
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+}
+
+static CK_RV
+gck_C_DecryptVerifyUpdate (CK_SESSION_HANDLE session, CK_BYTE_PTR enc_part,
+                           CK_ULONG enc_part_len, CK_BYTE_PTR part, 
+                           CK_ULONG_PTR part_len)
+{
+	CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+		
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+	if (pkcs11_module != NULL)
+		rv = gck_session_C_DecryptVerifyUpdate (gck_module_lookup_session (session),
+		                                        enc_part, enc_part_len, part, part_len);
+				
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+}
+
+static CK_RV
+gck_C_GenerateKey (CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism,
+                   CK_ATTRIBUTE_PTR template, CK_ULONG count, 
+                   CK_OBJECT_HANDLE_PTR key)
+{
+	CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+		
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+	if (pkcs11_module != NULL)
+		rv = gck_session_C_GenerateKey (gck_module_lookup_session (session),
+		                                mechanism, template, count, key);
+				
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+}
+
+static CK_RV
+gck_C_GenerateKeyPair (CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism,
+                       CK_ATTRIBUTE_PTR pub_template, CK_ULONG pub_count,
+                       CK_ATTRIBUTE_PTR priv_template, CK_ULONG priv_count,
+                       CK_OBJECT_HANDLE_PTR pub_key, CK_OBJECT_HANDLE_PTR priv_key)
+{
+	CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+		
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+	if (pkcs11_module != NULL)
+		rv = gck_session_C_GenerateKeyPair (gck_module_lookup_session (session),
+		                                    mechanism, pub_template, pub_count, priv_template, priv_count, pub_key, priv_key);
+				
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+}
+
+static CK_RV
+gck_C_WrapKey (CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism,
+               CK_OBJECT_HANDLE wrapping_key, CK_OBJECT_HANDLE key,
+               CK_BYTE_PTR wrapped_key, CK_ULONG_PTR wrapped_key_len)
+{
+	CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+		
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+	if (pkcs11_module != NULL)
+		rv = gck_session_C_WrapKey (gck_module_lookup_session (session),
+		                            mechanism, wrapping_key, key, wrapped_key, wrapped_key_len);
+				
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+}
+
+static CK_RV
+gck_C_UnwrapKey (CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism,
+                 CK_OBJECT_HANDLE unwrapping_key, CK_BYTE_PTR wrapped_key,
+                 CK_ULONG wrapped_key_len, CK_ATTRIBUTE_PTR template,
+                 CK_ULONG count, CK_OBJECT_HANDLE_PTR key)
+{
+	CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+		
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+	if (pkcs11_module != NULL)
+		rv = gck_session_C_UnwrapKey (gck_module_lookup_session (session),
+		                              mechanism, unwrapping_key, wrapped_key, wrapped_key_len, template, count, key);
+				
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+}
+
+static CK_RV
+gck_C_DeriveKey (CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism,
+                 CK_OBJECT_HANDLE base_key, CK_ATTRIBUTE_PTR template,
+                 CK_ULONG count, CK_OBJECT_HANDLE_PTR key)
+{
+	CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+		
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+	if (pkcs11_module != NULL)
+		rv = gck_session_C_UnwrapKey (gck_module_lookup_session (session),
+		                              mechanism, base_key, template, count, key);
+				
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+}
+
+static CK_RV
+gck_C_SeedRandom (CK_SESSION_HANDLE session, CK_BYTE_PTR seed, CK_ULONG seed_len)
+{
+	CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+		
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+	if (pkcs11_module != NULL)
+		rv = gck_session_C_SeedRandom (gck_module_lookup_session (session),
+		                               seed, seed_len);
+				
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+}
+
+static CK_RV
+gck_C_GenerateRandom (CK_SESSION_HANDLE session, CK_BYTE_PTR random_data,
+                      CK_ULONG random_len)
+{
+	CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+		
+	g_static_mutex_lock (&pkcs11_module_mutex);
+	
+	if (pkcs11_module != NULL)
+		rv = gck_session_C_GenerateRandom (gck_module_lookup_session (session),
+		                                   random_data, random_len);
+				
+	g_static_mutex_unlock (&pkcs11_module_mutex);
+}
+
+/* --------------------------------------------------------------------
+ * MODULE ENTRY POINT
+ */
+
+/* 
+ * PKCS#11 is broken here. It states that Unix compilers automatically byte 
+ * pack structures. This is wrong. GCC on Linux aligns to 4 by default. 
+ * 
+ * This results in incompatibilities. Where this structure's first version
+ * members take up too much or too little space depending on how this module
+ * is compiled.
+ */
+
+static CK_FUNCTION_LIST gck_function_list = {
+	{ CRYPTOKI_VERSION_MAJOR, CRYPTOKI_VERSION_MINOR },  /* version */
+	gck_C_Initialize,
+	gck_C_Finalize,
+	gck_C_GetInfo,
+	C_GetFunctionList,
+	gck_C_GetSlotList,
+	gck_C_GetSlotInfo,
+	gck_C_GetTokenInfo,
+	gck_C_GetMechanismList,
+	gck_C_GetMechanismInfo,
+	gck_C_InitToken,
+	gck_C_InitPIN,
+	gck_C_SetPIN,
+	gck_C_OpenSession,
+	gck_C_CloseSession,
+	gck_C_CloseAllSessions,
+	gck_C_GetSessionInfo,
+	gck_C_GetOperationState,
+	gck_C_SetOperationState,
+	gck_C_Login,
+	gck_C_Logout,
+	gck_C_CreateObject,
+	gck_C_CopyObject,
+	gck_C_DestroyObject,
+	gck_C_GetObjectSize,
+	gck_C_GetAttributeValue,
+	gck_C_SetAttributeValue,
+	gck_C_FindObjectsInit,
+	gck_C_FindObjects,
+	gck_C_FindObjectsFinal,
+	gck_C_EncryptInit,
+	gck_C_Encrypt,
+	gck_C_EncryptUpdate,
+	gck_C_EncryptFinal,
+	gck_C_DecryptInit,
+	gck_C_Decrypt,
+	gck_C_DecryptUpdate,
+	gck_C_DecryptFinal,
+	gck_C_DigestInit,
+	gck_C_Digest,
+	gck_C_DigestUpdate,
+	gck_C_DigestKey,
+	gck_C_DigestFinal,
+	gck_C_SignInit,
+	gck_C_Sign,
+	gck_C_SignUpdate,
+	gck_C_SignFinal,
+	gck_C_SignRecoverInit,
+	gck_C_SignRecover,
+	gck_C_VerifyInit,
+	gck_C_Verify,
+	gck_C_VerifyUpdate,
+	gck_C_VerifyFinal,
+	gck_C_VerifyRecoverInit,
+	gck_C_VerifyRecover,
+	gck_C_DigestEncryptUpdate,
+	gck_C_DecryptDigestUpdate,
+	gck_C_SignEncryptUpdate,
+	gck_C_DecryptVerifyUpdate,
+	gck_C_GenerateKey,
+	gck_C_GenerateKeyPair,
+	gck_C_WrapKey,
+	gck_C_UnwrapKey,
+	gck_C_DeriveKey,
+	gck_C_SeedRandom,
+	gck_C_GenerateRandom,
+	gck_C_GetFunctionStatus,
+	gck_C_CancelFunction,
+	gck_C_WaitForSlotEvent
+};
+
+CK_RV
+C_GetFunctionList (CK_FUNCTION_LIST_PTR_PTR list)
+{
+	return_val_if_fail (list, CKR_ARGUMENTS_BAD);
+
+	*list = &gck_function_list;
+	return CKR_OK;
+}

Added: trunk/pkcs11/gck/gck-module.c
==============================================================================
--- (empty file)
+++ trunk/pkcs11/gck/gck-module.c	Sun Dec 21 15:44:20 2008
@@ -0,0 +1,739 @@
+/* 
+ * gnome-keyring
+ * 
+ * Copyright (C) 2008 Stefan Walter
+ * 
+ * This program is free software; you can redistribute it and/or modify 
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *  
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *  
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.  
+ */
+
+#include "config.h"
+
+#include "pkcs11/pkcs11.h"
+
+#include "gck-manager.h"
+#include "gck-module.h"
+#include "gck-session.h"
+#include "gck-util.h"
+
+
+enum {
+	PROP_0,
+	PROP_MANAGER,
+	PROP_WRITE_PROTECTED
+};
+
+#if 0
+enum {
+	SIGNAL,
+	LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+#endif
+
+struct _GckModulePrivate {
+	GckManager *token_manager; 
+	GHashTable *virtual_slots_by_id;        /* Various slot partitions by their ID */
+	GHashTable *sessions_by_handle;         /* Mapping of handle to all open sessions */
+	gint handle_counter;                    /* Constantly incrementing counter for handles and the like */
+};
+
+typedef struct _VirtualSlot {
+	CK_SLOT_ID slot_id;
+	GckManager *session_manager;
+	GList *sessions;
+	gboolean logged_in;
+} VirtualSlot;
+
+G_DEFINE_TYPE (GckModule, gck_module, G_TYPE_OBJECT);
+
+/* These info blocks are used unless derived class overrides */
+
+static const CK_INFO default_module_info = {
+	{ CRYPTOKI_VERSION_MAJOR, CRYPTOKI_VERSION_MINOR },
+	"Gnome Keyring",
+	0,
+	"Gnome Keyring Module",
+	{ 1, 1 },
+};
+
+static const CK_SLOT_INFO default_slot_info = {
+	"Unnamed Slot",
+	"Gnome Keyring",
+	CKF_TOKEN_PRESENT,
+	{ 0, 0 },
+	{ 0, 0 }
+};
+
+static const CK_TOKEN_INFO default_token_info = {
+	"Unnamed Token",
+	"Gnome Keyring",
+	"1.0",
+	"1",
+	CKF_TOKEN_INITIALIZED | CKF_WRITE_PROTECTED,
+	CK_EFFECTIVELY_INFINITE,
+	CK_EFFECTIVELY_INFINITE,
+	CK_EFFECTIVELY_INFINITE,
+	CK_EFFECTIVELY_INFINITE,
+	1024,
+	1,
+	CK_UNAVAILABLE_INFORMATION,
+	CK_UNAVAILABLE_INFORMATION,
+	CK_UNAVAILABLE_INFORMATION,
+	CK_UNAVAILABLE_INFORMATION,
+	{ 0, 0 },
+	{ 0, 0 },
+	""
+};
+
+typedef struct _MechanismAndInfo {
+	CK_MECHANISM_TYPE mechanism;
+	CK_MECHANISM_INFO info;
+} MechanismAndInfo;
+
+static const MechanismAndInfo mechanism_list[] = {
+	/*  
+	 * CKM_RSA_PKCS
+	 * For RSA, min and max are the minimum and maximum modulus in bits
+	 */
+	{ CKM_RSA_PKCS, { 256, 32768, CKF_ENCRYPT | CKF_DECRYPT | CKF_SIGN | CKF_VERIFY } },
+
+	/* 
+	 * CKM_RSA_X509
+	 * For RSA, min and max are the minimum and maximum modulus in bits
+	 */
+	{ CKM_RSA_X_509, { 256, 32768, CKF_ENCRYPT | CKF_DECRYPT | CKF_SIGN | CKF_VERIFY } },
+	
+	/*
+	 * CKM_DSA
+	 * For DSA, min and max are the minimum and maximum modulus in bits
+	 */
+	{ CKM_DSA, { 512, 1024, CKF_SIGN | CKF_VERIFY } }
+};
+
+/* -----------------------------------------------------------------------------
+ * INTERNAL 
+ */
+
+static void
+extend_space_string (CK_UTF8CHAR_PTR string, gsize length)
+{
+	CK_UTF8CHAR_PTR at;
+	
+	/* Find a null pointer in the string */
+	at = memchr (string, '0', length);
+	g_assert (at != NULL && at < string + length);
+	for (; at < string + length; ++at) 
+		*at = ' ';
+}
+
+static void
+virtual_slot_free (gpointer data)
+{
+	VirtualSlot *slot;
+	GList *l;
+	
+	g_assert (data != NULL);
+	slot = (VirtualSlot*)data;
+	
+	g_return_if_fail (GCK_IS_MANAGER (slot->session_manager));
+	
+	/* Unreference all the sessions */
+	for (l = slot->sessions; l; l = g_list_next (l)) {
+		
+		/* Some sanity checks to make sure things have remained as expected */
+		g_return_if_fail (GCK_IS_SESSION (l->data));
+		g_return_if_fail (gck_session_get_slot_id (l->data) == slot->slot_id);
+		g_return_if_fail (gck_session_get_manager (l->data) == slot->session_manager);
+		g_return_if_fail (gck_session_get_logged_in (l->data) == slot->logged_in);
+		
+		g_object_unref (l->data);
+	}
+	
+	g_list_free (slot->sessions);
+	g_object_unref (slot->session_manager);
+	
+	g_slice_free (VirtualSlot, slot);
+}
+
+static VirtualSlot*
+virtual_slot_new (CK_SLOT_ID slot_id)
+{
+	VirtualSlot *slot;
+
+	slot = g_slice_new0 (VirtualSlot);
+	slot->session_manager = g_object_new (GCK_TYPE_MANAGER, "is-token", FALSE, NULL);
+	slot->logged_in = FALSE;
+	slot->sessions = NULL;
+	slot->slot_id = slot_id;
+	
+	return slot;
+}
+
+static VirtualSlot*
+lookup_virtual_slot (GckModule *self, CK_SLOT_ID slot_id)
+{
+	g_assert (GCK_IS_MODULE (self));
+	return g_hash_table_lookup (self->pv->virtual_slots_by_id, &slot_id);
+}
+
+static void
+register_virtual_slot (GckModule *self, VirtualSlot *slot)
+{
+	g_assert (slot);
+	g_assert (GCK_IS_MODULE (self));
+	g_assert (!g_hash_table_lookup (self->pv->virtual_slots_by_id, &(slot->slot_id)));
+	
+	return g_hash_table_insert (self->pv->virtual_slots_by_id, 
+	                            gck_util_ulong_alloc (slot->slot_id), slot);
+}
+
+static void
+unregister_virtual_slot (GckModule *self, VirtualSlot *slot)
+{
+	g_assert (slot);
+	g_assert (GCK_IS_MODULE (self));
+	
+	if (!g_hash_table_remove (self->pv->virtual_slots_by_id, &(slot->slot_id)))
+		g_assert_not_reached ();
+}
+
+/* -----------------------------------------------------------------------------
+ * OBJECT 
+ */
+
+static CK_RV
+gck_module_real_login_user (GckModule *self, CK_SLOT_ID slot_id, CK_UTF8CHAR_PTR pin, CK_ULONG n_pin)
+{
+	VirtualSlot *slot;
+	GList *l;
+	
+	slot = lookup_virtual_slot (self, slot_id);
+	g_return_val_if_fail (slot, CKR_GENERAL_ERROR);
+
+	/* Mark all sessions in the partition as logged in */
+	for (l = slot->sessions; l; l = g_list_next (l)) 
+		gck_session_set_logged_in (l->data, TRUE);
+	slot->logged_in = TRUE;
+	
+	return CKR_OK;
+}
+
+static CK_RV
+gck_module_real_logout_user (GckModule *self, CK_SLOT_ID slot_id)
+{
+	VirtualSlot *slot;
+	GList *l;
+
+	/* Calculate the partition identifier */
+	slot = lookup_virtual_slot (self, slot_id);
+	g_return_val_if_fail (slot, CKR_GENERAL_ERROR);
+
+	/* Mark all sessions in the partition as logged out */
+	for (l = slot->sessions; l; l = g_list_next (l)) 
+		gck_session_set_logged_in (l->data, FALSE);
+	slot->logged_in = FALSE;
+	
+	/* Derived classes should override if they want actual login */
+	return CKR_OK;
+}
+
+static GObject* 
+gck_module_constructor (GType type, guint n_props, GObjectConstructParam *props) 
+{
+	GckModule *self = GCK_MODULE (G_OBJECT_CLASS (gck_module_parent_class)->constructor(type, n_props, props));
+	g_return_val_if_fail (self, NULL);	
+
+
+	
+	return G_OBJECT (self);
+}
+
+static void
+gck_module_init (GckModule *self)
+{
+	self->pv = G_TYPE_INSTANCE_GET_PRIVATE (self, GCK_TYPE_MODULE, GckModulePrivate);
+	self->pv->token_manager = g_object_new (GCK_TYPE_MANAGER, "is-token", TRUE, NULL);
+	self->pv->sessions_by_handle = g_hash_table_new_full (gck_util_ulong_hash, gck_util_ulong_equal, 
+	                                                      gck_util_ulong_free, g_object_unref);
+	self->pv->virtual_slots_by_id = g_hash_table_new_full (gck_util_ulong_hash, gck_util_ulong_equal, 
+	                                                       gck_util_ulong_free, virtual_slot_free);
+	
+	g_atomic_int_set (&(self->pv->handle_counter), 1);
+}
+
+static void
+gck_module_dispose (GObject *obj)
+{
+	GckModule *self = GCK_MODULE (obj);
+
+	if (self->pv->token_manager)
+		g_object_unref (self->pv->token_manager);
+	self->pv->token_manager = NULL;
+	
+	g_hash_table_remove_all (self->pv->virtual_slots_by_id);
+	g_hash_table_remove_all (self->pv->sessions_by_handle);
+    
+	G_OBJECT_CLASS (gck_module_parent_class)->dispose (obj);
+}
+
+static void
+gck_module_finalize (GObject *obj)
+{
+	GckModule *self = GCK_MODULE (obj);
+	
+	g_assert (self->pv->token_manager == NULL);
+
+	g_assert (g_hash_table_size (self->pv->virtual_slots_by_id) == 0);
+	g_hash_table_destroy (self->pv->virtual_slots_by_id);
+	self->pv->virtual_slots_by_id = NULL;
+	
+	g_assert (g_hash_table_size (self->pv->sessions_by_handle) == 0);
+	g_hash_table_destroy (self->pv->sessions_by_handle);
+	self->pv->sessions_by_handle = NULL;
+
+	G_OBJECT_CLASS (gck_module_parent_class)->finalize (obj);
+}
+
+static void
+gck_module_set_property (GObject *obj, guint prop_id, const GValue *value, 
+                           GParamSpec *pspec)
+{
+#if 0
+	GckModule *self = GCK_MODULE (obj);
+#endif 
+	
+	switch (prop_id) {
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+gck_module_get_property (GObject *obj, guint prop_id, GValue *value, 
+                         GParamSpec *pspec)
+{
+	GckModule *self = GCK_MODULE (obj);
+	
+	switch (prop_id) {
+	case PROP_MANAGER:
+		g_value_set_object (value, gck_module_get_manager (self));
+		break;
+	case PROP_WRITE_PROTECTED:
+		g_value_set_boolean (value, gck_module_get_write_protected (self));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+gck_module_class_init (GckModuleClass *klass)
+{
+	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+    
+	gck_module_parent_class = g_type_class_peek_parent (klass);
+	g_type_class_add_private (klass, sizeof (GckModulePrivate));
+
+	gobject_class->constructor = gck_module_constructor;
+	gobject_class->dispose = gck_module_dispose;
+	gobject_class->finalize = gck_module_finalize;
+	gobject_class->set_property = gck_module_set_property;
+	gobject_class->get_property = gck_module_get_property;
+    
+	klass->module_info = &default_module_info;
+	klass->slot_info = &default_slot_info;
+	klass->token_info = &default_token_info;
+	
+	klass->login_user = gck_module_real_login_user;
+	klass->logout_user = gck_module_real_logout_user;
+	
+	g_object_class_install_property (gobject_class, PROP_MANAGER,
+	           g_param_spec_object ("manager", "Manager", "Token object manager", 
+	                                GCK_TYPE_MANAGER, G_PARAM_READABLE));
+	
+	g_object_class_install_property (gobject_class, PROP_WRITE_PROTECTED,
+	           g_param_spec_boolean ("write-protected", "Write Protected", "Token is write protected", 
+	                                 TRUE, G_PARAM_READABLE));
+
+#if 0
+	signals[SIGNAL] = g_signal_new ("signal", GCK_TYPE_MODULE, 
+	                                G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GckModuleClass, signal),
+	                                NULL, NULL, g_cclosure_marshal_VOID__OBJECT, 
+	                                G_TYPE_NONE, 0);
+#endif
+}
+
+/* -----------------------------------------------------------------------------
+ * PUBLIC 
+ */
+
+GckModule*
+gck_module_new (void)
+{
+	return g_object_new (GCK_TYPE_MODULE, NULL);
+}
+
+GckManager*
+gck_module_get_manager (GckModule *self)
+{
+	g_return_val_if_fail (GCK_IS_MODULE (self), NULL);
+	g_return_val_if_fail (GCK_IS_MANAGER (self->pv->token_manager), NULL);
+	return self->pv->token_manager;
+}
+
+gboolean
+gck_module_get_write_protected (GckModule *self)
+{
+	g_return_val_if_fail (GCK_IS_MODULE (self), FALSE);
+	g_return_val_if_fail (GCK_MODULE_GET_CLASS (self)->token_info, FALSE);
+	return (GCK_MODULE_GET_CLASS (self)->token_info->flags & CKF_WRITE_PROTECTED) ? TRUE : FALSE;
+}
+
+
+GckSession*
+gck_module_lookup_session (GckModule *self, CK_SESSION_HANDLE handle)
+{
+	GckSession *session;
+	
+	g_return_val_if_fail (GCK_IS_MODULE (self), NULL);
+	
+	session = g_hash_table_lookup (self->pv->sessions_by_handle, &handle);
+	if (!session)
+		return NULL;
+	
+	g_return_val_if_fail (GCK_IS_SESSION (session), NULL);
+	return session;
+}
+
+CK_RV
+gck_module_login_user (GckModule *self, CK_SLOT_ID slot_id, CK_UTF8CHAR_PTR pin, CK_ULONG n_pin)
+{
+	g_return_val_if_fail (GCK_IS_MODULE (self), CKR_GENERAL_ERROR);
+	g_assert (GCK_MODULE_GET_CLASS (self)->login_user);
+	return GCK_MODULE_GET_CLASS (self)->login_user (self, slot_id, pin, n_pin);
+}
+
+CK_RV
+gck_module_logout_user (GckModule *self, CK_SLOT_ID slot_id)
+{
+	g_return_val_if_fail (GCK_IS_MODULE (self), CKR_GENERAL_ERROR);
+	g_assert (GCK_MODULE_GET_CLASS (self)->logout_user);
+	return GCK_MODULE_GET_CLASS (self)->logout_user (self, slot_id);	
+}
+
+CK_ULONG
+gck_module_next_handle (GckModule *self)
+{
+	g_return_val_if_fail (GCK_IS_MODULE (self), 0);
+	return (self->pv->handle_counter)++;
+}
+
+/* -----------------------------------------------------------------------------
+ * PKCS#11
+ */
+
+CK_RV
+gck_module_C_GetInfo (GckModule *self, CK_INFO_PTR info)
+{
+	GckModuleClass *klass;
+	
+	g_return_val_if_fail (GCK_IS_MODULE (self), CKR_CRYPTOKI_NOT_INITIALIZED);
+	g_return_val_if_fail (info, CKR_ARGUMENTS_BAD);
+	
+	klass = GCK_MODULE_GET_CLASS (self);
+	g_return_val_if_fail (klass, CKR_GENERAL_ERROR);
+	
+	memcpy (info, klass->module_info, sizeof (CK_INFO));
+	
+	/* Extend all the strings appropriately */
+	extend_space_string (info->libraryDescription, sizeof (info->libraryDescription));
+	extend_space_string (info->manufacturerID, sizeof (info->manufacturerID));
+	
+	return CKR_OK;
+}
+
+CK_RV
+gck_module_C_GetSlotList (GckModule *self, CK_BBOOL token_present, CK_SLOT_ID_PTR slot_list, CK_ULONG_PTR count)
+{
+	g_return_val_if_fail (GCK_IS_MODULE (self), CKR_CRYPTOKI_NOT_INITIALIZED);
+	g_return_val_if_fail (count, CKR_ARGUMENTS_BAD);
+	
+	/* Just want to get the count */
+	if (slot_list == NULL) {
+		*count = 1;
+		return CKR_OK;
+	}
+	
+	/* Buffer too small? */
+	if (*count == 0) {
+		*count = 1;
+		return CKR_BUFFER_TOO_SMALL;
+	}
+	
+	g_return_val_if_fail (slot_list, CKR_ARGUMENTS_BAD);
+	
+	slot_list[0] = 0;
+	*count = 1;
+	return CKR_OK;
+}
+
+CK_RV
+gck_module_C_GetSlotInfo (GckModule *self, CK_SLOT_ID id, CK_SLOT_INFO_PTR info)
+{
+	GckModuleClass *klass;
+	
+	g_return_val_if_fail (GCK_IS_MODULE (self), CKR_CRYPTOKI_NOT_INITIALIZED);
+	g_return_val_if_fail (info, CKR_ARGUMENTS_BAD);
+	
+	/* Any slot ID is valid for partitioned module */
+	
+	klass = GCK_MODULE_GET_CLASS (self);
+	g_return_val_if_fail (klass, CKR_GENERAL_ERROR);
+	
+	memcpy (info, klass->slot_info, sizeof (CK_SLOT_INFO));
+	
+	/* Extend all the strings appropriately */
+	extend_space_string (info->manufacturerID, sizeof (info->manufacturerID));
+	extend_space_string (info->slotDescription, sizeof (info->slotDescription));
+	
+	return CKR_OK;
+}
+
+CK_RV
+gck_module_C_GetTokenInfo (GckModule *self, CK_SLOT_ID id, CK_TOKEN_INFO_PTR info)
+{
+	GckModuleClass *klass;
+	
+	g_return_val_if_fail (GCK_IS_MODULE (self), CKR_CRYPTOKI_NOT_INITIALIZED);
+	g_return_val_if_fail (info, CKR_ARGUMENTS_BAD);
+	
+	/* Any slot ID is valid for partitioned module */
+	
+	klass = GCK_MODULE_GET_CLASS (self);
+	g_return_val_if_fail (klass, CKR_GENERAL_ERROR);
+	
+	memcpy (info, klass->token_info, sizeof (CK_TOKEN_INFO));
+	
+	/* Extend all the strings appropriately */
+	extend_space_string (info->label, sizeof (info->label));
+	extend_space_string (info->manufacturerID, sizeof (info->manufacturerID));
+	extend_space_string (info->model, sizeof (info->model));
+	extend_space_string (info->serialNumber, sizeof (info->serialNumber));
+	
+	/* We don't purport to have a clock */
+	memset (info->utcTime, 0, sizeof (info->utcTime));
+	
+	return CKR_OK;	
+}
+
+CK_RV
+gck_module_C_GetMechanismList (GckModule *self, CK_SLOT_ID id, 
+                               CK_MECHANISM_TYPE_PTR mech_list, CK_ULONG_PTR count)
+{
+	const guint n_mechanisms = G_N_ELEMENTS (mechanism_list); 
+	guint i;
+	
+	g_return_val_if_fail (GCK_IS_MODULE (self), CKR_CRYPTOKI_NOT_INITIALIZED);
+	g_return_val_if_fail (count, CKR_ARGUMENTS_BAD);
+	
+	/* Just want to get the count */
+	if (mech_list == NULL) {
+		*count = n_mechanisms;
+		return CKR_OK;
+	}
+	
+	/* Buffer too small? */
+	if (*count < n_mechanisms) {
+		*count = n_mechanisms;
+		return CKR_BUFFER_TOO_SMALL;
+	}
+	
+	g_return_val_if_fail (mech_list, CKR_ARGUMENTS_BAD);
+	
+	*count = n_mechanisms;
+	for (i = 0; i < n_mechanisms; ++i)
+		mech_list[i] = mechanism_list[i].mechanism;
+
+	return CKR_OK;
+}
+
+CK_RV
+gck_module_C_GetMechanismInfo (GckModule *self, CK_SLOT_ID id, 
+                               CK_MECHANISM_TYPE type, CK_MECHANISM_INFO_PTR info)
+{
+	const guint n_mechanisms = G_N_ELEMENTS (mechanism_list); 
+	guint index;
+	
+	g_return_val_if_fail (GCK_IS_MODULE (self), CKR_CRYPTOKI_NOT_INITIALIZED);
+	g_return_val_if_fail (info, CKR_ARGUMENTS_BAD);
+
+	for (index = 0; index < n_mechanisms; ++index) {
+		if (mechanism_list[index].mechanism == type)
+			break;
+	}
+	
+	if (index == n_mechanisms)
+		return CKR_MECHANISM_INVALID;
+
+	memcpy (info, &mechanism_list[index].info, sizeof (CK_MECHANISM_INFO));
+	return CKR_OK;
+}
+
+CK_RV
+gck_module_C_OpenSession (GckModule *self, CK_SLOT_ID slot_id, CK_FLAGS flags, CK_VOID_PTR user_data, 
+                          CK_NOTIFY callback, CK_SESSION_HANDLE_PTR result)
+{
+	CK_SESSION_HANDLE handle;
+	VirtualSlot *slot;
+	gboolean read_only;
+	GckSession *session;
+	
+	g_return_val_if_fail (GCK_IS_MODULE (self), CKR_CRYPTOKI_NOT_INITIALIZED);
+	g_return_val_if_fail (handle, CKR_ARGUMENTS_BAD);
+	
+	if (!(flags & CKF_SERIAL_SESSION))
+		return CKR_SESSION_PARALLEL_NOT_SUPPORTED;
+
+	/* Lookup or register the virtual slot */
+	slot = lookup_virtual_slot (self, slot_id);
+	if (slot == NULL) {
+		slot = virtual_slot_new (slot_id);
+		register_virtual_slot (self, slot);
+	}
+
+	/* Make and register a new session */
+	handle = gck_module_next_handle (self);
+	read_only = !(flags & CKF_RW_SESSION);
+	session = g_object_new (GCK_TYPE_SESSION, "slot-id", slot->slot_id, "read-only", read_only, 
+	                        "handle", handle, "module", self, "manager", slot->session_manager, 
+	                        "logged-in", slot->logged_in, NULL);
+	slot->sessions = g_list_prepend (slot->sessions, session);
+	
+	/* Track the session by handle */
+	g_hash_table_insert (self->pv->sessions_by_handle, 
+	                     gck_util_ulong_alloc (handle), 
+	                     g_object_ref (session));
+	
+	*result = handle;
+	return CKR_OK;
+}
+
+CK_RV
+gck_module_C_CloseSession (GckModule *self, CK_SESSION_HANDLE handle)
+{
+	GckSession *session;
+	CK_SLOT_ID slot_id;
+	VirtualSlot *slot;
+	GList *link;
+	
+	g_return_val_if_fail (GCK_IS_MODULE (self), CKR_CRYPTOKI_NOT_INITIALIZED);
+	
+	session = gck_module_lookup_session (self, handle);
+	if (session == NULL)
+		return CKR_SESSION_HANDLE_INVALID;
+
+	/* Calculate the virtual slot */
+	slot_id = gck_session_get_slot_id (session);
+	slot = lookup_virtual_slot (self, slot_id);
+	g_return_val_if_fail (slot, CKR_GENERAL_ERROR);
+
+	link = g_list_find (slot->sessions, session);
+	g_return_val_if_fail (link, CKR_GENERAL_ERROR);
+	slot->sessions = g_list_delete_link (slot->sessions, link);
+	g_object_unref (session);
+	if (!slot->sessions) 
+		unregister_virtual_slot (self, slot);
+
+	if (!g_hash_table_remove (self->pv->sessions_by_handle, &handle))
+		g_assert_not_reached ();
+	
+	return CKR_OK;
+}
+
+CK_RV
+gck_module_C_CloseAllSessions (GckModule *self, CK_SLOT_ID slot_id)
+{
+	VirtualSlot *slot;
+	
+	g_return_val_if_fail (GCK_IS_MODULE (self), CKR_CRYPTOKI_NOT_INITIALIZED);
+	
+	/* Calculate the virtual slot */
+	slot = lookup_virtual_slot (self, slot_id);
+	if (!slot)
+		return CKR_OK;
+
+	unregister_virtual_slot (self, slot);
+	return CKR_OK;	
+}
+
+CK_RV
+gck_module_C_Login (GckModule *self, CK_SESSION_HANDLE handle, CK_USER_TYPE user_type,
+                    CK_UTF8CHAR_PTR pin, CK_ULONG pin_len)
+{
+	CK_SLOT_ID slot_id;
+	GckSession *session;
+	VirtualSlot *slot;
+	
+	g_return_val_if_fail (GCK_IS_MODULE (self), CKR_CRYPTOKI_NOT_INITIALIZED);
+	
+	session = gck_module_lookup_session (self, handle);
+	if (session == NULL)
+		return CKR_SESSION_HANDLE_INVALID;
+
+	/* Pass off context specifc logins to appropriate place */
+	if (user_type == CKU_CONTEXT_SPECIFIC)
+		return gck_session_login_context_specific (session, pin, pin_len);
+
+	/* We don't have support for SO logins */
+	if (user_type == CKU_SO) 
+		return CKR_USER_TYPE_INVALID;
+
+	/* Calculate the virtual slot */
+	slot_id = gck_session_get_slot_id (session);
+	slot = lookup_virtual_slot (self, slot_id);
+	g_return_val_if_fail (slot, CKR_GENERAL_ERROR);
+
+	if (slot->logged_in)
+		return CKR_USER_ALREADY_LOGGED_IN;
+	
+	return gck_module_login_user (self, slot_id, pin, pin_len);
+}
+
+CK_RV
+gck_module_C_Logout (GckModule *self, CK_SESSION_HANDLE handle)
+{
+	CK_SLOT_ID slot_id;
+	VirtualSlot *slot;
+	GckSession *session;
+	
+	g_return_val_if_fail (GCK_IS_MODULE (self), CKR_CRYPTOKI_NOT_INITIALIZED);
+	
+	session = gck_module_lookup_session (self, handle);
+	if (session == NULL)
+		return CKR_SESSION_HANDLE_INVALID;
+
+	slot_id = gck_session_get_slot_id (session);
+	slot = lookup_virtual_slot (self, slot_id);
+	g_return_val_if_fail (slot, CKR_GENERAL_ERROR);
+
+	if (!slot->logged_in)
+		return CKR_USER_ALREADY_LOGGED_IN;
+
+	return gck_module_logout_user (self, slot_id);
+}

Added: trunk/pkcs11/gck/gck-module.h
==============================================================================
--- (empty file)
+++ trunk/pkcs11/gck/gck-module.h	Sun Dec 21 15:44:20 2008
@@ -0,0 +1,138 @@
+/* 
+ * gnome-keyring
+ * 
+ * Copyright (C) 2008 Stefan Walter
+ * 
+ * This program is free software; you can redistribute it and/or modify 
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *  
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *  
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.  
+ */
+
+#ifndef __GCK_MODULE_H__
+#define __GCK_MODULE_H__
+
+#include <glib-object.h>
+
+typedef struct _GckSession GckSession;
+
+#define GCK_TYPE_MODULE               (gck_module_get_type ())
+#define GCK_MODULE(obj)               (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCK_TYPE_MODULE, GckModule))
+#define GCK_MODULE_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST ((klass), GCK_TYPE_MODULE, GckModuleClass))
+#define GCK_IS_MODULE(obj)            (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCK_TYPE_MODULE))
+#define GCK_IS_MODULE_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE ((klass), GCK_TYPE_MODULE))
+#define GCK_MODULE_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS ((obj), GCK_TYPE_MODULE, GckModuleClass))
+
+typedef struct _GckModule GckModule;
+typedef struct _GckModuleClass GckModuleClass;
+typedef struct _GckModulePrivate GckModulePrivate;
+    
+struct _GckModule {
+	GObject parent;
+	CK_FUNCTION_LIST pkcs11_funcs;
+	GckModulePrivate *pv;
+};
+
+struct _GckModuleClass {
+	GObjectClass parent_class;
+	
+	/* Various  */
+	const CK_INFO *module_info;
+	const CK_SLOT_INFO *slot_info;
+	const CK_TOKEN_INFO *token_info;
+	
+	/* signals --------------------------------------------------------- */
+    
+	void (*signal) (GckModule *module);
+	
+	/* virtual methods */
+	
+	CK_RV (*login_user) (GckModule *self, CK_SLOT_ID slot_id, 
+	                     CK_UTF8CHAR_PTR pin, CK_ULONG n_pin);
+	
+	CK_RV (*logout_user) (GckModule *self, CK_SLOT_ID slot_id);
+};
+
+GType                  gck_module_get_type               (void);
+
+GckModule*             gck_module_new                    (void);
+
+GckManager*            gck_module_get_manager                     (GckModule *self);
+
+gboolean               gck_module_get_write_protected             (GckModule *self);
+
+CK_ULONG               gck_module_next_handle                     (GckModule *self);
+
+GckSession*            gck_module_lookup_session                  (GckModule *self,
+                                                                   CK_SESSION_HANDLE handle);
+
+CK_RV                  gck_module_login_user                      (GckModule *self,
+                                                                   CK_SLOT_ID slot_id,
+                                                                   CK_UTF8CHAR_PTR pin,
+                                                                   CK_ULONG n_pin);
+
+CK_RV                  gck_module_logout_user                     (GckModule *self,
+                                                                   CK_SLOT_ID slot_id);
+
+
+
+
+CK_RV                  gck_module_C_GetInfo                       (GckModule *self, 
+                                                                   CK_INFO_PTR info);
+
+CK_RV                  gck_module_C_GetSlotList                   (GckModule *self, 
+                                                                   CK_BBOOL token_present, 
+                                                                   CK_SLOT_ID_PTR slot_list, 
+                                                                   CK_ULONG_PTR count);
+
+CK_RV                  gck_module_C_GetSlotInfo                   (GckModule *self, 
+                                                                   CK_SLOT_ID id, 
+                                                                   CK_SLOT_INFO_PTR info);
+
+CK_RV                  gck_module_C_GetTokenInfo                  (GckModule *self, 
+                                                                   CK_SLOT_ID id, 
+                                                                   CK_TOKEN_INFO_PTR info);
+
+CK_RV                  gck_module_C_GetMechanismList              (GckModule *self, 
+                                                                   CK_SLOT_ID id, 
+                                                                   CK_MECHANISM_TYPE_PTR mech_list, 
+                                                                   CK_ULONG_PTR count);
+
+CK_RV                  gck_module_C_GetMechanismInfo              (GckModule *self, 
+                                                                   CK_SLOT_ID id, 
+                                                                   CK_MECHANISM_TYPE type, 
+                                                                   CK_MECHANISM_INFO_PTR info);
+
+CK_RV                  gck_module_C_OpenSession                   (GckModule *self, 
+                                                                   CK_SLOT_ID id, 
+                                                                   CK_FLAGS flags, 
+                                                                   CK_VOID_PTR user_data, 
+                                                                   CK_NOTIFY callback, 
+                                                                   CK_SESSION_HANDLE_PTR session);
+
+CK_RV                  gck_module_C_CloseSession                  (GckModule *self,
+                                                                   CK_SESSION_HANDLE session);
+
+CK_RV                  gck_module_C_CloseAllSessions              (GckModule *self, 
+                                                                   CK_SLOT_ID id);
+
+CK_RV                  gck_module_C_Login                         (GckModule *self, 
+                                                                   CK_SESSION_HANDLE session, 
+                                                                   CK_USER_TYPE user_type,
+                                                                   CK_UTF8CHAR_PTR pin, 
+                                                                   CK_ULONG pin_len);
+
+CK_RV                  gck_module_C_Logout                        (GckModule *self, 
+                                                                   CK_SESSION_HANDLE session);
+
+#endif /* __GCK_MODULE_H__ */

Added: trunk/pkcs11/gck/gck-object.c
==============================================================================
--- (empty file)
+++ trunk/pkcs11/gck/gck-object.c	Sun Dec 21 15:44:20 2008
@@ -0,0 +1,387 @@
+/* 
+ * gnome-keyring
+ * 
+ * Copyright (C) 2008 Stefan Walter
+ * 
+ * This program is free software; you can redistribute it and/or modify 
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *  
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *  
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.  
+ */
+
+#include "config.h"
+
+#include "pkcs11/pkcs11.h"
+
+#include "gck-manager.h"
+#include "gck-object.h"
+#include "gck-util.h"
+
+enum {
+	PROP_0,
+	PROP_HANDLE,
+	PROP_MANAGER
+};
+
+struct _GckObjectPrivate {
+	CK_OBJECT_HANDLE handle;
+	GckManager *manager;
+};
+
+G_DEFINE_TYPE (GckObject, gck_object, G_TYPE_OBJECT);
+
+/* -----------------------------------------------------------------------------
+ * INTERNAL 
+ */
+
+/* -----------------------------------------------------------------------------
+ * OBJECT 
+ */
+
+static CK_RV 
+gck_object_real_get_attribute (GckObject *self, CK_ATTRIBUTE* attr)
+{
+	switch (attr->type)
+	{
+	case CKA_CLASS:
+		g_warning ("Derived class should have overridden CKA_CLASS");
+		return CKR_GENERAL_ERROR;
+	case CKA_LABEL:
+		g_warning ("Derived class should have overridden CKA_LABEL");
+		return gck_util_set_data (attr, "", 0);
+	case CKA_MODIFIABLE:
+	case CKA_PRIVATE:
+		return gck_util_set_bool (attr, FALSE);
+	case CKA_TOKEN:
+		return gck_util_set_bool (attr, (self->pv->handle & GCK_OBJECT_IS_PERMANENT) ? TRUE : FALSE);
+	};
+	
+	return CKR_ATTRIBUTE_TYPE_INVALID;
+}
+
+#if 0
+static CK_RV 
+gck_object_real_set_attribute (GckObject *self, const CK_ATTRIBUTE* attr)
+{
+	switch (attr->type) {
+	case CKA_LABEL:
+		g_warning ("Derived class should have overridden CKA_LABEL");
+		return CKR_ATTRIBUTE_READ_ONLY;
+	case CKA_TOKEN:
+	case CKA_PRIVATE:
+	case CKA_MODIFIABLE:
+		return CKR_ATTRIBUTE_READ_ONLY;
+		
+	case CKA_CLASS:
+		return CKR_ATTRIBUTE_READ_ONLY;
+	};
+	
+	return CKR_ATTRIBUTE_TYPE_INVALID;
+}
+#endif
+
+static CK_RV
+gck_object_real_unlock (GckObject *self, CK_UTF8CHAR_PTR pin, CK_ULONG n_pin)
+{
+	gboolean always_auth;
+	
+	if (!gck_object_get_attribute_boolean (self, CKA_ALWAYS_AUTHENTICATE, &always_auth))
+		always_auth = FALSE;
+	
+	/* A strange error code, but according to spec */
+	if (!always_auth)
+		return CKR_OPERATION_NOT_INITIALIZED;
+
+	/* A derived class should have overridden this */
+	g_return_val_if_reached (CKR_GENERAL_ERROR);
+}
+
+static GObject* 
+gck_object_constructor (GType type, guint n_props, GObjectConstructParam *props) 
+{
+	GckObject *self = GCK_OBJECT (G_OBJECT_CLASS (gck_object_parent_class)->constructor(type, n_props, props));
+	g_return_val_if_fail (self, NULL);	
+
+
+	
+	return G_OBJECT (self);
+}
+
+static void
+gck_object_init (GckObject *self)
+{
+	self->pv = G_TYPE_INSTANCE_GET_PRIVATE (self, GCK_TYPE_OBJECT, GckObjectPrivate);
+
+}
+
+static void
+gck_object_dispose (GObject *obj)
+{
+	GckObject *self = GCK_OBJECT (obj);
+	
+	gck_object_set_manager (self, NULL);
+    
+	G_OBJECT_CLASS (gck_object_parent_class)->dispose (obj);
+}
+
+static void
+gck_object_finalize (GObject *obj)
+{
+	GckObject *self = GCK_OBJECT (obj);
+	
+	g_assert (self->pv->manager == NULL);
+
+	G_OBJECT_CLASS (gck_object_parent_class)->finalize (obj);
+}
+
+static void
+gck_object_set_property (GObject *obj, guint prop_id, const GValue *value, 
+                           GParamSpec *pspec)
+{
+	GckObject *self = GCK_OBJECT (obj);
+	
+	switch (prop_id) {
+	case PROP_HANDLE:
+		gck_object_set_handle (self, g_value_get_ulong (value));
+		break;
+	case PROP_MANAGER:
+		gck_object_set_manager (self, g_value_get_object (value));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+gck_object_get_property (GObject *obj, guint prop_id, GValue *value, 
+                           GParamSpec *pspec)
+{
+	GckObject *self = GCK_OBJECT (obj);
+	
+	switch (prop_id) {
+	case PROP_HANDLE:
+		g_value_set_ulong (value, gck_object_get_handle (self));
+		break;
+	case PROP_MANAGER:
+		g_value_set_object (value, gck_object_get_manager (self));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+gck_object_class_init (GckObjectClass *klass)
+{
+	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+    
+	gck_object_parent_class = g_type_class_peek_parent (klass);
+	g_type_class_add_private (klass, sizeof (GckObjectPrivate));
+
+	gobject_class->constructor = gck_object_constructor;
+	gobject_class->dispose = gck_object_dispose;
+	gobject_class->finalize = gck_object_finalize;
+	gobject_class->set_property = gck_object_set_property;
+	gobject_class->get_property = gck_object_get_property;
+	
+	klass->unlock = gck_object_real_unlock;
+	klass->get_attribute = gck_object_real_get_attribute;
+#if 0
+	klass->set_attribute = gck_object_real_set_attribute;
+#endif
+	
+	g_object_class_install_property (gobject_class, PROP_HANDLE,
+	           g_param_spec_ulong ("handle", "Handle", "Object handle",
+	                               0, G_MAXULONG, 0, G_PARAM_READWRITE));
+
+	g_object_class_install_property (gobject_class, PROP_MANAGER,
+	           g_param_spec_object ("manager", "Manager", "Object manager", 
+	                                GCK_TYPE_MANAGER, G_PARAM_READWRITE));
+	
+#if 0
+	signals[SIGNAL] = g_signal_new ("signal", GCK_TYPE_OBJECT, 
+	                                G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GckObjectClass, signal),
+	                                NULL, NULL, g_cclosure_marshal_VOID__OBJECT, 
+	                                G_TYPE_NONE, 0);
+#endif
+}
+
+/* -----------------------------------------------------------------------------
+ * PUBLIC 
+ */
+
+gboolean
+gck_object_match (GckObject *self, CK_ATTRIBUTE_PTR match)
+{
+	CK_ATTRIBUTE attr;
+	gboolean matched = FALSE;
+	CK_RV rv;
+	
+	g_return_val_if_fail (GCK_IS_OBJECT (self), FALSE);
+	
+	if (!match->pValue)
+		return FALSE;
+	
+	attr.type = match->type;
+	attr.pValue = g_malloc0 (match->ulValueLen > 4 ? match->ulValueLen : 4);
+	attr.ulValueLen = match->ulValueLen;
+	
+	matched = FALSE;
+	
+	rv = gck_object_get_attribute (self, &attr);
+	matched = (rv == CKR_OK) && 
+	          (match->ulValueLen == attr.ulValueLen) &&
+	          (memcmp (match->pValue, attr.pValue, attr.ulValueLen) == 0);
+	
+	g_free (attr.pValue);
+	return matched;
+}
+
+gboolean
+gck_object_match_all (GckObject *self, CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs)
+{
+	CK_ULONG i;
+	
+	g_return_val_if_fail (GCK_IS_OBJECT (self), FALSE);
+	
+	for (i = 0; i < n_attrs; ++i) {
+		if (!gck_object_match (self, &attrs[i]))
+			return FALSE;
+	}
+	
+	return TRUE;
+}
+
+CK_OBJECT_HANDLE
+gck_object_get_handle (GckObject *self)
+{
+	g_return_val_if_fail (GCK_IS_OBJECT (self), 0);
+	return self->pv->handle;	
+}
+
+void
+gck_object_set_handle (GckObject *self, CK_OBJECT_HANDLE handle)
+{
+	g_return_if_fail (GCK_IS_OBJECT (self));
+	g_return_if_fail (handle != 0);
+	g_return_if_fail (self->pv->handle == 0);
+
+	self->pv->handle = handle;
+	g_object_notify (G_OBJECT (self), "handle");	
+}
+
+GckManager*
+gck_object_get_manager (GckObject *self)
+{
+	g_return_val_if_fail (GCK_IS_OBJECT (self), NULL);
+	return self->pv->manager;
+}
+
+void
+gck_object_set_manager (GckObject *self, GckManager *manager)
+{
+	g_return_if_fail (GCK_IS_OBJECT (self));
+	g_return_if_fail (!manager || GCK_IS_MANAGER (manager));
+
+	if (self->pv->manager) {
+		g_return_if_fail (!manager);
+		g_object_remove_weak_pointer (G_OBJECT (self->pv->manager), 
+		                              (gpointer*)&(self->pv->manager));
+	}
+	
+	self->pv->manager = manager;
+	if (self->pv->manager)
+		g_object_add_weak_pointer (G_OBJECT (self->pv->manager), 
+		                           (gpointer*)&(self->pv->manager));
+	
+	g_object_notify (G_OBJECT (self), "manager");
+}
+
+CK_RV
+gck_object_unlock (GckObject *self, CK_UTF8CHAR_PTR pin, CK_ULONG n_pin)
+{
+	g_return_val_if_fail (GCK_IS_OBJECT (self), CKR_GENERAL_ERROR);
+	g_return_val_if_fail (GCK_OBJECT_GET_CLASS (self)->unlock, CKR_GENERAL_ERROR);
+	return GCK_OBJECT_GET_CLASS (self)->unlock (self, pin, n_pin);
+}
+
+
+gboolean
+gck_object_get_attribute_boolean (GckObject *self, CK_ATTRIBUTE_TYPE type, gboolean *value)
+{
+	CK_ATTRIBUTE attr;
+	CK_BBOOL bvalue;
+	
+	g_return_val_if_fail (GCK_IS_OBJECT (self), FALSE);
+	g_return_val_if_fail (value, FALSE);
+	
+	attr.type = type;
+	attr.ulValueLen = sizeof (CK_BBOOL);
+	attr.pValue = &bvalue;
+	
+	if (gck_object_get_attribute (self, &attr) != CKR_OK)
+		return FALSE;
+	
+	*value = (bvalue == CK_TRUE) ? TRUE : FALSE;
+	return TRUE;
+}
+
+gboolean
+gck_object_get_attribute_ulong (GckObject *self, CK_ATTRIBUTE_TYPE type, gulong *value)
+{
+	CK_ATTRIBUTE attr;
+	CK_ULONG uvalue;
+	
+	g_return_val_if_fail (GCK_IS_OBJECT (self), FALSE);
+	g_return_val_if_fail (value, FALSE);
+	
+	attr.type = type;
+	attr.ulValueLen = sizeof (CK_ULONG);
+	attr.pValue = &uvalue;
+	
+	if (gck_object_get_attribute (self, &attr) != CKR_OK)
+		return FALSE;
+	
+	*value = uvalue;
+	return TRUE;
+}
+
+void*
+gck_object_get_attribute_data (GckObject *self, CK_ATTRIBUTE_TYPE type, gsize *n_data)
+{
+	CK_ATTRIBUTE attr;
+	
+	g_return_val_if_fail (GCK_IS_OBJECT (self), NULL);
+	g_return_val_if_fail (n_data, NULL);
+	
+	attr.type = type;
+	attr.ulValueLen = 0;
+	attr.pValue = NULL;
+	
+	if (gck_object_get_attribute (self, &attr) != CKR_OK)
+		return NULL;
+
+	if (attr.ulValueLen == 0)
+		attr.ulValueLen = 1;
+	
+	attr.pValue = g_malloc0 (attr.ulValueLen);
+	
+	if (gck_object_get_attribute (self, &attr) != CKR_OK) {
+		g_free (attr.pValue);
+		return NULL;
+	}
+	
+	return attr.pValue;
+}

Added: trunk/pkcs11/gck/gck-object.h
==============================================================================
--- (empty file)
+++ trunk/pkcs11/gck/gck-object.h	Sun Dec 21 15:44:20 2008
@@ -0,0 +1,102 @@
+/* 
+ * gnome-keyring
+ * 
+ * Copyright (C) 2008 Stefan Walter
+ * 
+ * This program is free software; you can redistribute it and/or modify 
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *  
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *  
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.  
+ */
+
+#ifndef __GCK_OBJECT_H__
+#define __GCK_OBJECT_H__
+
+#include <glib-object.h>
+
+#include "pkcs11/pkcs11.h"
+
+#define GCK_OBJECT_HANDLE_MASK  0x0FFFFFFF
+#define GCK_OBJECT_IS_PERMANENT	0x10000000
+#define GCK_OBJECT_IS_TEMPORARY	0x00000000
+
+#define GCK_TYPE_OBJECT               (gck_object_get_type ())
+#define GCK_OBJECT(obj)               (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCK_TYPE_OBJECT, GckObject))
+#define GCK_OBJECT_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST ((klass), GCK_TYPE_OBJECT, GckObjectClass))
+#define GCK_IS_OBJECT(obj)            (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCK_TYPE_OBJECT))
+#define GCK_IS_OBJECT_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE ((klass), GCK_TYPE_OBJECT))
+#define GCK_OBJECT_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS ((obj), GCK_TYPE_OBJECT, GckObjectClass))
+
+typedef struct _GckObject GckObject;
+typedef struct _GckObjectClass GckObjectClass;
+typedef struct _GckObjectPrivate GckObjectPrivate;
+
+typedef struct _GckManager GckManager;
+
+struct _GckObject {
+	GObject parent;
+	GckObjectPrivate *pv;
+};
+
+struct _GckObjectClass {
+	GObjectClass parent_class;
+	
+	/* virtual methods  --------------------------------------------------------- */
+    
+	CK_RV (*get_attribute) (GckObject *object, CK_ATTRIBUTE* attr);
+	
+	CK_RV (*unlock) (GckObject *self, CK_UTF8CHAR_PTR pin, CK_ULONG n_pin);
+};
+
+GType                  gck_object_get_type               (void);
+
+CK_OBJECT_HANDLE       gck_object_get_handle             (GckObject *self);
+
+void                   gck_object_set_handle             (GckObject *self,
+                                                          CK_OBJECT_HANDLE handle);
+
+GckManager*            gck_object_get_manager            (GckObject *self);
+
+void                   gck_object_set_manager            (GckObject *self,
+                                                          GckManager *manager);
+
+CK_RV                  gck_object_unlock                 (GckObject *self, 
+                                                          CK_UTF8CHAR_PTR pin, 
+                                                          CK_ULONG n_pin);
+
+gboolean               gck_object_match                  (GckObject *self,
+                                                          CK_ATTRIBUTE_PTR attr);
+
+gboolean               gck_object_match_all              (GckObject *self,
+                                                          CK_ATTRIBUTE_PTR attrs,
+                                                          CK_ULONG n_attrs);
+
+CK_RV                  gck_object_get_attribute          (GckObject *self,
+                                                          CK_ATTRIBUTE_PTR attr);
+
+void                   gck_object_cache_attribute        (GckObject *self,
+                                                          CK_ATTRIBUTE_PTR attr);
+
+gboolean               gck_object_get_attribute_boolean  (GckObject *self,
+                                                          CK_ATTRIBUTE_TYPE type,
+                                                          gboolean *value);
+
+gboolean               gck_object_get_attribute_ulong    (GckObject *self,
+                                                          CK_ATTRIBUTE_TYPE type,
+                                                          gulong *value);
+
+void*                  gck_object_get_attribute_data     (GckObject *self,
+                                                          CK_ATTRIBUTE_TYPE type,
+                                                          gsize *n_data);
+
+#endif /* __GCK_OBJECT_H__ */

Added: trunk/pkcs11/gck/gck-private-key.c
==============================================================================
--- (empty file)
+++ trunk/pkcs11/gck/gck-private-key.c	Sun Dec 21 15:44:20 2008
@@ -0,0 +1,292 @@
+/* 
+ * gnome-keyring
+ * 
+ * Copyright (C) 2008 Stefan Walter
+ * 
+ * This program is free software; you can redistribute it and/or modify 
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *  
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *  
+ * You should have received a copy of the GNU Lesser General Private
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.  
+ */
+
+#include "config.h"
+
+#include "pkcs11/pkcs11.h"
+
+#include "gck-private-key.h"
+#include "gck-util.h"
+
+#if 0
+enum {
+	PROP_0
+};
+#endif
+
+struct _GckPrivateKeyPrivate {
+	guint sexp_uses;
+	GckSexp *sexp;
+};
+
+G_DEFINE_TYPE (GckPrivateKey, gck_private_key, GCK_TYPE_KEY);
+
+/* -----------------------------------------------------------------------------
+ * INTERNAL 
+ */
+
+/* -----------------------------------------------------------------------------
+ * PRIVATE_KEY 
+ */
+
+static CK_RV 
+gck_private_key_real_get_attribute (GckObject *base, CK_ATTRIBUTE* attr)
+{
+	GckPrivateKey *self = GCK_PRIVATE_KEY (base);
+	
+	switch (attr->type) {
+	case CKA_CLASS:
+		return gck_util_set_ulong (attr, CKO_PRIVATE_KEY);
+		
+	case CKA_PRIVATE:
+		return gck_util_set_bool (attr, TRUE);
+
+	case CKA_SENSITIVE:
+		return gck_util_set_bool (attr, TRUE);
+		
+	case CKA_DECRYPT:
+		return gck_util_set_bool (attr, gck_key_get_algorithm (GCK_KEY (self)) == GCRY_PK_RSA); 
+		
+	case CKA_SIGN:
+		return gck_util_set_bool (attr, TRUE);
+		
+	case CKA_SIGN_RECOVER:
+		return gck_util_set_bool (attr, FALSE);
+		
+	case CKA_UNWRAP:
+		return gck_util_set_bool (attr, FALSE);
+		
+	case CKA_EXTRACTABLE:
+		return gck_util_set_bool (attr, FALSE);
+		
+	case CKA_ALWAYS_SENSITIVE:
+		return gck_util_set_bool (attr, FALSE);
+		
+	case CKA_NEVER_EXTRACTABLE:
+		return gck_util_set_bool (attr, FALSE);
+		
+	case CKA_WRAP_WITH_TRUSTED:
+		return gck_util_set_bool (attr, FALSE);
+		
+	case CKA_UNWRAP_TEMPLATE:
+		return CKR_ATTRIBUTE_TYPE_INVALID;
+		
+	case CKA_ALWAYS_AUTHENTICATE:
+		return gck_util_set_bool (attr, self->pv->sexp_uses > 1);
+		
+	case CKA_MODULUS:
+		return gck_key_set_key_part (GCK_KEY (self), GCRY_PK_RSA, "n", attr);
+		
+	case CKA_PUBLIC_EXPONENT:
+		return gck_key_set_key_part (GCK_KEY (self), GCRY_PK_RSA, "e", attr);
+		
+	/* RSA private key parts */
+	case CKA_PRIVATE_EXPONENT:
+	case CKA_PRIME_1:
+	case CKA_PRIME_2:
+	case CKA_EXPONENT_1:
+	case CKA_EXPONENT_2:
+	case CKA_COEFFICIENT:
+		return CKR_ATTRIBUTE_SENSITIVE;
+	
+	case CKA_PRIME:
+		return gck_key_set_key_part (GCK_KEY (self), GCRY_PK_DSA, "p", attr);
+		
+	case CKA_SUBPRIME:
+		return gck_key_set_key_part (GCK_KEY (self), GCRY_PK_DSA, "q", attr);
+		
+	case CKA_BASE:
+		return gck_key_set_key_part (GCK_KEY (self), GCRY_PK_DSA, "g", attr);
+		
+	/* DSA private parts */
+	case CKA_VALUE:
+		return CKR_ATTRIBUTE_SENSITIVE;
+	};	
+	
+	return GCK_OBJECT_CLASS (gck_private_key_parent_class)->get_attribute (base, attr);
+}
+
+#if 0
+static CK_RV 
+gck_private_key_real_set_attribute (GckPrivateKey *private_key, const CK_ATTRIBUTE* attr)
+{
+	switch (attr->type) {
+	/* TODO: CKA_LABEL */
+
+	case CKA_TOKEN:
+	case CKA_PRIVATE:
+	case CKA_MODIFIABLE:
+		return CKR_ATTRIBUTE_READ_ONLY;
+		
+	case CKA_CLASS:
+		return CKR_ATTRIBUTE_READ_ONLY;
+	};
+	
+xxx
+}
+#endif
+
+static GckSexp*
+gck_private_key_real_acquire_crypto_sexp (GckKey *base)
+{
+	GckPrivateKey *self = GCK_PRIVATE_KEY (base);
+	GckSexp *sexp;
+	
+	if (self->pv->sexp_uses == 0) {
+		g_return_val_if_fail (!self->pv->sexp, NULL);
+		return NULL;
+	}
+	
+	g_return_val_if_fail (self->pv->sexp, NULL);
+		
+	sexp = gck_sexp_ref (self->pv->sexp);
+	--(self->pv->sexp_uses);
+		
+	if (self->pv->sexp_uses == 0) {
+		gck_sexp_unref (self->pv->sexp);
+		self->pv->sexp = NULL;
+	}
+		
+	return sexp;
+}
+
+static GObject* 
+gck_private_key_constructor (GType type, guint n_props, GObjectConstructParam *props) 
+{
+	GckPrivateKey *self = GCK_PRIVATE_KEY (G_OBJECT_CLASS (gck_private_key_parent_class)->constructor(type, n_props, props));
+	g_return_val_if_fail (self, NULL);	
+
+
+	
+	return G_OBJECT (self);
+}
+
+static void
+gck_private_key_init (GckPrivateKey *self)
+{
+	self->pv = G_TYPE_INSTANCE_GET_PRIVATE (self, GCK_TYPE_PRIVATE_KEY, GckPrivateKeyPrivate);
+
+}
+
+static void
+gck_private_key_dispose (GObject *obj)
+{
+	GckPrivateKey *self = GCK_PRIVATE_KEY (obj);
+
+	if (self->pv->sexp)
+		gck_sexp_unref (self->pv->sexp);
+	self->pv->sexp = NULL;
+
+	G_OBJECT_CLASS (gck_private_key_parent_class)->dispose (obj);
+}
+
+static void
+gck_private_key_finalize (GObject *obj)
+{
+	GckPrivateKey *self = GCK_PRIVATE_KEY (obj);
+
+	g_assert (self->pv->sexp == NULL);
+	
+	G_OBJECT_CLASS (gck_private_key_parent_class)->finalize (obj);
+}
+
+static void
+gck_private_key_set_property (GObject *obj, guint prop_id, const GValue *value, 
+                              GParamSpec *pspec)
+{
+#if 0
+	GckPrivateKey *self = GCK_PRIVATE_KEY (obj);
+#endif
+	
+	switch (prop_id) {
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+gck_private_key_get_property (GObject *obj, guint prop_id, GValue *value, 
+                              GParamSpec *pspec)
+{
+#if 0
+	GckPrivateKey *self = GCK_PRIVATE_KEY (obj);
+#endif
+	
+	switch (prop_id) {
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+gck_private_key_class_init (GckPrivateKeyClass *klass)
+{
+	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+	GckObjectClass *gck_class = GCK_OBJECT_CLASS (klass);
+	GckKeyClass *key_class = GCK_KEY_CLASS (klass);
+	
+	gck_private_key_parent_class = g_type_class_peek_parent (klass);
+	g_type_class_add_private (klass, sizeof (GckPrivateKeyPrivate));
+
+	gobject_class->constructor = gck_private_key_constructor;
+	gobject_class->dispose = gck_private_key_dispose;
+	gobject_class->finalize = gck_private_key_finalize;
+	gobject_class->set_property = gck_private_key_set_property;
+	gobject_class->get_property = gck_private_key_get_property;
+	
+	gck_class->get_attribute = gck_private_key_real_get_attribute;
+#if 0
+	gck_class->set_attribute = gck_private_key_real_set_attribute;
+#endif
+	
+	key_class->acquire_crypto_sexp = gck_private_key_real_acquire_crypto_sexp;
+    
+#if 0
+	g_private_key_class_install_property (gprivate_key_class, PROP_PRIVATE_KEY,
+	           g_param_spec_pointer ("private_key", "PrivateKey", "PrivateKey.", G_PARAM_READWRITE));
+    
+	signals[SIGNAL] = g_signal_new ("signal", GCK_TYPE_PRIVATE_KEY, 
+	                                G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GckPrivateKeyClass, signal),
+	                                NULL, NULL, g_cclosure_marshal_VOID__OBJECT, 
+	                                G_TYPE_NONE, 0);
+#endif
+}
+
+/* -----------------------------------------------------------------------------
+ * PRIVATE 
+ */
+
+void
+gck_private_key_store_private (GckPrivateKey *self, GckSexp *sexp, guint num_uses)
+{
+	g_return_if_fail (GCK_IS_PRIVATE_KEY (self));
+	g_return_if_fail (sexp);
+	g_return_if_fail (num_uses > 0);
+	
+	gck_sexp_ref (sexp);
+	if (self->pv->sexp) 
+		gck_sexp_unref (self->pv->sexp);
+	self->pv->sexp = sexp;
+	self->pv->sexp_uses = num_uses;
+}
+

Added: trunk/pkcs11/gck/gck-private-key.h
==============================================================================
--- (empty file)
+++ trunk/pkcs11/gck/gck-private-key.h	Sun Dec 21 15:44:20 2008
@@ -0,0 +1,58 @@
+/* 
+ * gnome-keyring
+ * 
+ * Copyright (C) 2008 Stefan Walter
+ * 
+ * This program is free software; you can redistribute it and/or modify 
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *  
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *  
+ * You should have received a copy of the GNU Lesser General Private
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.  
+ */
+
+#ifndef __GCK_PRIVATE_KEY_H__
+#define __GCK_PRIVATE_KEY_H__
+
+#include <glib-object.h>
+
+#include "gck-key.h"
+#include "gck-sexp.h"
+
+#define GCK_TYPE_PRIVATE_KEY               (gck_private_key_get_type ())
+#define GCK_PRIVATE_KEY(obj)               (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCK_TYPE_PRIVATE_KEY, GckPrivateKey))
+#define GCK_PRIVATE_KEY_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST ((klass), GCK_TYPE_PRIVATE_KEY, GckPrivateKeyClass))
+#define GCK_IS_PRIVATE_KEY(obj)            (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCK_TYPE_PRIVATE_KEY))
+#define GCK_IS_PRIVATE_KEY_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE ((klass), GCK_TYPE_PRIVATE_KEY))
+#define GCK_PRIVATE_KEY_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS ((obj), GCK_TYPE_PRIVATE_KEY, GckPrivateKeyClass))
+
+typedef struct _GckPrivateKey GckPrivateKey;
+typedef struct _GckPrivateKeyClass GckPrivateKeyClass;
+typedef struct _GckPrivateKeyPrivate GckPrivateKeyPrivate;
+    
+struct _GckPrivateKey {
+	GckKey parent;
+	GckPrivateKeyPrivate *pv;
+};
+
+struct _GckPrivateKeyClass {
+	GckKeyClass parent_class;
+};
+
+GType                      gck_private_key_get_type               (void);
+
+GckPrivateKey*             gck_private_key_new                    (void);
+
+void                       gck_private_key_store_private          (GckPrivateKey *self, 
+                                                                   GckSexp *sexp, 
+                                                                   guint num_uses);               
+
+#endif /* __GCK_PRIVATE_KEY_H__ */

Added: trunk/pkcs11/gck/gck-public-key.c
==============================================================================
--- (empty file)
+++ trunk/pkcs11/gck/gck-public-key.c	Sun Dec 21 15:44:20 2008
@@ -0,0 +1,218 @@
+/* 
+ * gnome-keyring
+ * 
+ * Copyright (C) 2008 Stefan Walter
+ * 
+ * This program is free software; you can redistribute it and/or modify 
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *  
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *  
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.  
+ */
+
+#include "config.h"
+
+#include "pkcs11/pkcs11.h"
+
+#include "gck-public-key.h"
+#include "gck-util.h"
+
+#if 0
+enum {
+	PROP_0,
+	PROP_PUBLIC_KEY
+};
+
+struct _GckPublicKeyPrivate {
+};
+#endif
+
+G_DEFINE_TYPE (GckPublicKey, gck_public_key, GCK_TYPE_KEY);
+
+/* -----------------------------------------------------------------------------
+ * INTERNAL 
+ */
+
+/* -----------------------------------------------------------------------------
+ * PUBLIC_KEY 
+ */
+
+static CK_RV 
+gck_public_key_real_get_attribute (GckObject *base, CK_ATTRIBUTE* attr)
+{
+	GckPublicKey *self = GCK_PUBLIC_KEY (base);
+	
+	switch (attr->type)
+	{
+	
+	case CKA_ENCRYPT:
+		return gck_util_set_bool (attr, gck_key_get_algorithm (GCK_KEY (self)) == GCRY_PK_RSA);
+		
+	case CKA_VERIFY:
+		return gck_util_set_bool (attr, TRUE);
+		
+	case CKA_VERIFY_RECOVER:
+		return gck_util_set_bool (attr, FALSE);
+		
+	case CKA_WRAP:
+		return gck_util_set_bool (attr, FALSE);
+		
+	case CKA_TRUSTED:
+		return gck_util_set_bool (attr, FALSE);
+		
+	case CKA_WRAP_TEMPLATE:
+		return CKR_ATTRIBUTE_TYPE_INVALID;
+		
+	case CKA_MODULUS:
+		return gck_key_set_key_part (GCK_KEY (self), GCRY_PK_RSA, "n", attr);
+		
+	case CKA_PUBLIC_EXPONENT:
+		return gck_key_set_key_part (GCK_KEY (self), GCRY_PK_RSA, "e", attr);
+		
+	case CKA_PRIME:
+		return gck_key_set_key_part (GCK_KEY (self), GCRY_PK_DSA, "p", attr);
+		
+	case CKA_SUBPRIME:
+		return gck_key_set_key_part (GCK_KEY (self), GCRY_PK_DSA, "q", attr);
+		
+	case CKA_BASE:
+		return gck_key_set_key_part (GCK_KEY (self), GCRY_PK_DSA, "g", attr);
+		
+	/* DSA public value */
+	case CKA_VALUE:
+		return gck_key_set_key_part (GCK_KEY (self), GCRY_PK_DSA, "y", attr);
+	};
+	
+	return GCK_OBJECT_CLASS (gck_public_key_parent_class)->get_attribute (base, attr);
+}
+
+#if 0
+static CK_RV 
+gck_public_key_real_set_attribute (GckPublicKey *public_key, const CK_ATTRIBUTE* attr)
+{
+	switch (attr->type) {
+	/* TODO: CKA_LABEL */
+
+	case CKA_TOKEN:
+	case CKA_PRIVATE:
+	case CKA_MODIFIABLE:
+		return CKR_ATTRIBUTE_READ_ONLY;
+		
+	case CKA_CLASS:
+		return CKR_ATTRIBUTE_READ_ONLY;
+	};
+	
+	return CKA_ATTRIBUTE_TYPE_INVALID;
+}
+#endif
+
+static GObject* 
+gck_public_key_constructor (GType type, guint n_props, GObjectConstructParam *props) 
+{
+	GckPublicKey *self = GCK_PUBLIC_KEY (G_OBJECT_CLASS (gck_public_key_parent_class)->constructor(type, n_props, props));
+	g_return_val_if_fail (self, NULL);	
+	
+	return G_OBJECT (self);
+}
+
+static void
+gck_public_key_init (GckPublicKey *self)
+{
+#if 0
+	self->pv = G_TYPE_INSTANCE_GET_PRIVATE (self, GCK_TYPE_PUBLIC_KEY, GckPublicKeyPrivate);
+#endif
+}
+
+static void
+gck_public_key_dispose (GObject *obj)
+{
+#if 0
+	GckPublicKey *self = GCK_PUBLIC_KEY (obj);
+#endif
+	G_OBJECT_CLASS (gck_public_key_parent_class)->dispose (obj);
+}
+
+static void
+gck_public_key_finalize (GObject *obj)
+{
+#if 0
+	GckPublicKey *self = GCK_PUBLIC_KEY (obj);
+#endif
+	G_OBJECT_CLASS (gck_public_key_parent_class)->finalize (obj);
+}
+
+static void
+gck_public_key_set_property (GObject *obj, guint prop_id, const GValue *value, 
+                           GParamSpec *pspec)
+{
+#if 0
+	GckPublicKey *self = GCK_PUBLIC_KEY (obj);
+#endif
+	
+	switch (prop_id) {
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+gck_public_key_get_property (GObject *obj, guint prop_id, GValue *value, 
+                           GParamSpec *pspec)
+{
+#if 0
+	GckPublicKey *self = GCK_PUBLIC_KEY (obj);
+#endif
+	
+	switch (prop_id) {
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+gck_public_key_class_init (GckPublicKeyClass *klass)
+{
+	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+	GckObjectClass *gck_class = GCK_OBJECT_CLASS (klass);
+	
+	gck_public_key_parent_class = g_type_class_peek_parent (klass);
+#if 0
+	g_type_class_add_private (klass, sizeof (GckPublicKeyPrivate));
+#endif
+	
+	gobject_class->constructor = gck_public_key_constructor;
+	gobject_class->dispose = gck_public_key_dispose;
+	gobject_class->finalize = gck_public_key_finalize;
+	gobject_class->set_property = gck_public_key_set_property;
+	gobject_class->get_property = gck_public_key_get_property;
+	
+	gck_class->get_attribute = gck_public_key_real_get_attribute;
+#if 0
+	gck_class->set_attribute = gck_public_key_real_set_attribute;
+#endif
+	
+#if 0
+	g_public_key_class_install_property (gobject_class, PROP_PUBLIC_KEY,
+	           g_param_spec_pointer ("public_key", "PublicKey", "PublicKey.", G_PARAM_READWRITE));
+    
+	signals[SIGNAL] = g_signal_new ("signal", GCK_TYPE_PUBLIC_KEY, 
+	                                G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GckPublicKeyClass, signal),
+	                                NULL, NULL, g_cclosure_marshal_VOID__OBJECT, 
+	                                G_TYPE_NONE, 0);
+#endif
+}
+
+/* -----------------------------------------------------------------------------
+ * PUBLIC 
+ */

Added: trunk/pkcs11/gck/gck-public-key.h
==============================================================================
--- (empty file)
+++ trunk/pkcs11/gck/gck-public-key.h	Sun Dec 21 15:44:20 2008
@@ -0,0 +1,51 @@
+/* 
+ * gnome-keyring
+ * 
+ * Copyright (C) 2008 Stefan Walter
+ * 
+ * This program is free software; you can redistribute it and/or modify 
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *  
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *  
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.  
+ */
+
+#ifndef __GCK_PUBLIC_KEY_H__
+#define __GCK_PUBLIC_KEY_H__
+
+#include <glib-object.h>
+
+#include "gck-key.h"
+
+#define GCK_TYPE_PUBLIC_KEY               (gck_public_key_get_type ())
+#define GCK_PUBLIC_KEY(obj)               (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCK_TYPE_PUBLIC_KEY, GckPublicKey))
+#define GCK_PUBLIC_KEY_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST ((klass), GCK_TYPE_PUBLIC_KEY, GckPublicKeyClass))
+#define GCK_IS_PUBLIC_KEY(obj)            (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCK_TYPE_PUBLIC_KEY))
+#define GCK_IS_PUBLIC_KEY_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE ((klass), GCK_TYPE_PUBLIC_KEY))
+#define GCK_PUBLIC_KEY_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS ((obj), GCK_TYPE_PUBLIC_KEY, GckPublicKeyClass))
+
+typedef struct _GckPublicKey GckPublicKey;
+typedef struct _GckPublicKeyClass GckPublicKeyClass;
+typedef struct _GckPublicKeyPrivate GckPublicKeyPrivate;
+    
+struct _GckPublicKey {
+	GckKey parent;
+	GckPublicKeyPrivate *pv;
+};
+
+struct _GckPublicKeyClass {
+	GckKeyClass parent_class;
+};
+
+GType                     gck_public_key_get_type               (void);
+
+#endif /* __GCK_PUBLIC_KEY_H__ */

Added: trunk/pkcs11/gck/gck-session.c
==============================================================================
--- (empty file)
+++ trunk/pkcs11/gck/gck-session.c	Sun Dec 21 15:44:20 2008
@@ -0,0 +1,1092 @@
+/* 
+ * gnome-keyring
+ * 
+ * Copyright (C) 2008 Stefan Walter
+ * 
+ * This program is free software; you can redistribute it and/or modify 
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *  
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *  
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.  
+ */
+
+#include "config.h"
+
+#include "pkcs11/pkcs11.h"
+
+#include "gck-crypto.h"
+#include "gck-key.h"
+#include "gck-manager.h"
+#include "gck-session.h"
+#include "gck-sexp.h"
+
+enum {
+	PROP_0,
+	PROP_MODULE,
+	PROP_SLOT_ID,
+	PROP_HANDLE,
+	PROP_READ_ONLY,
+	PROP_MANAGER,
+	PROP_LOGGED_IN
+};
+
+#if 0
+enum {
+	SIGNAL,
+	LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+#endif 
+
+
+struct _GckSessionPrivate {
+
+	CK_SESSION_HANDLE handle;
+	CK_SLOT_ID slot_id;
+	
+	GckModule *module;
+	GckManager *manager;
+
+	gboolean logged_in;
+	gboolean read_only;
+
+	CK_NOTIFY notify_callback;
+	CK_VOID_PTR application_ptr;
+
+	/* Used for context specific logins */
+	void (*current_operation) (GckSession *self);
+	GckObject *current_object;
+
+	/* Used for find operations */
+	GArray *found_objects;
+	
+	/* Used for crypto operations */
+	GckSexp *crypto_sexp;
+	CK_MECHANISM_TYPE crypto_mechanism;
+	CK_ATTRIBUTE_TYPE crypto_method;
+};
+
+G_DEFINE_TYPE (GckSession, gck_session, G_TYPE_OBJECT);
+
+/* -----------------------------------------------------------------------------
+ * INTERNAL 
+ */
+
+static void
+cleanup_crypto (GckSession *self)
+{
+	g_assert (self->pv->current_operation == cleanup_crypto);
+
+	g_assert (self->pv->crypto_sexp);
+	g_assert (GCK_IS_KEY (self->pv->current_object));
+	gck_sexp_unref (self->pv->crypto_sexp);
+	self->pv->crypto_sexp = NULL;
+
+	self->pv->crypto_mechanism = 0;
+	self->pv->crypto_method = 0;
+
+	if (self->pv->current_object)
+		g_object_remove_weak_pointer (G_OBJECT (self->pv->current_object), 
+		                              (gpointer*)&(self->pv->current_object));
+	self->pv->current_object = NULL;
+	self->pv->current_operation = NULL;
+}
+
+static CK_RV
+prepare_crypto (GckSession *self, CK_MECHANISM_PTR mech, 
+                CK_ATTRIBUTE_TYPE method, CK_OBJECT_HANDLE handle)
+{
+	GckObject *object;
+	CK_MECHANISM_TYPE_PTR mechanisms;
+	CK_ULONG n_mechanisms, i;
+	gsize n_data;
+	gboolean have;
+	CK_RV rv;
+	
+	g_assert (GCK_IS_SESSION (self));
+	
+	if (self->pv->current_operation)
+		return CKR_OPERATION_ACTIVE;
+	
+	g_assert (!self->pv->crypto_sexp);
+	
+	/* First find the object */
+	rv = gck_session_lookup_readable_object (self, handle, &object);
+	if (rv != CKR_OK)
+		return rv;
+	
+	if (!GCK_IS_KEY (object))
+		return CKR_KEY_HANDLE_INVALID;
+
+	/* Lookup the mechanisms this object can do */
+	mechanisms = gck_object_get_attribute_data (object, CKA_ALLOWED_MECHANISMS, &n_data);
+	g_return_val_if_fail (mechanisms, CKR_GENERAL_ERROR);
+	g_return_val_if_fail (n_data % sizeof (CK_MECHANISM_TYPE) == 0, CKR_GENERAL_ERROR);
+	n_mechanisms = n_data / sizeof (CK_MECHANISM_TYPE);
+	
+	/* See if ours is represented */
+	have = FALSE;
+	for (i = 0; !have && i < n_mechanisms; ++i) {
+		if (mechanisms[i] == mech->mechanism)
+			have = TRUE;
+	}
+	
+	if (have == FALSE)
+		return CKR_KEY_TYPE_INCONSISTENT;
+
+	/* Check that the object can do this method */
+	if (!gck_object_get_attribute_boolean (object, method, &have))
+		g_return_val_if_reached (CKR_GENERAL_ERROR);
+	if (have == CK_FALSE)
+		return CKR_KEY_FUNCTION_NOT_PERMITTED;
+	
+	/* Track the cyrpto object */
+	self->pv->current_object = object;
+	g_object_ref (object);
+	
+	/* And note what we're setup for */
+	self->pv->current_operation = cleanup_crypto;
+	self->pv->crypto_mechanism = mech->mechanism;
+	self->pv->crypto_method = method;
+
+	return CKR_OK;
+}
+
+static CK_RV
+process_crypto (GckSession *self, CK_ATTRIBUTE_TYPE method, CK_BYTE_PTR bufone, 
+                CK_ULONG n_bufone, CK_BYTE_PTR buftwo, CK_ULONG_PTR n_buftwo)
+{
+	CK_RV rv;
+	
+	g_assert (GCK_IS_SESSION (self));
+
+	if (self->pv->current_operation != cleanup_crypto)
+		return CKR_OPERATION_NOT_INITIALIZED;
+	if (method != self->pv->crypto_method)
+		return CKR_OPERATION_NOT_INITIALIZED;
+	
+	/* Load up the actual sexp we're going to use */
+	if (!self->pv->crypto_sexp) {
+		g_return_val_if_fail (GCK_IS_KEY (self->pv->current_object), CKR_GENERAL_ERROR);
+		self->pv->crypto_sexp = gck_key_acquire_crypto_sexp (GCK_KEY (self->pv->current_object));
+		if (!self->pv->crypto_sexp)
+			return CKR_USER_NOT_LOGGED_IN;
+	}
+
+	g_assert (self->pv->crypto_mechanism);
+	rv = gck_crypto_perform (gck_sexp_get (self->pv->crypto_sexp), self->pv->crypto_mechanism, 
+	                         method, bufone, n_bufone, buftwo, n_buftwo);
+	
+	/* Under these conditions the operation isn't complete */
+	if (rv == CKR_BUFFER_TOO_SMALL || (rv == CKR_OK && buftwo == NULL))
+		return rv;
+	
+	cleanup_crypto (self);
+	return rv;
+}
+
+static void
+cleanup_found (GckSession *self)
+{
+	g_assert (GCK_IS_SESSION (self));
+	
+	g_assert (self->pv->found_objects);
+	g_array_free (self->pv->found_objects, TRUE);
+	self->pv->found_objects = NULL;
+	
+	self->pv->current_operation = NULL;
+}
+
+static CK_RV
+lookup_object_from_handle (GckSession *self, CK_OBJECT_HANDLE handle,
+                           gboolean writable, GckObject **result)
+{
+	GckManager *manager;
+	GckObject *object;
+	gboolean is_private;
+	gboolean is_token;
+	gboolean is_modifiable;
+	
+	g_return_val_if_fail (result, CKR_GENERAL_ERROR);
+	g_return_val_if_fail (GCK_IS_SESSION (self), CKR_GENERAL_ERROR);
+	
+	if (handle == 0)
+		return CKR_OBJECT_HANDLE_INVALID;
+	
+	if (handle & GCK_OBJECT_IS_PERMANENT) {
+		manager = gck_module_get_manager (self->pv->module);
+		is_token = TRUE;
+	} else {
+		manager = gck_session_get_manager (self);
+		is_token = FALSE;
+	}
+	
+	g_return_val_if_fail (manager, CKR_GENERAL_ERROR);
+	
+	object = gck_manager_lookup_handle (manager, handle);
+	if (object == NULL)
+		return CKR_OBJECT_HANDLE_INVALID;
+	
+	/* 
+	 * Check that we're not accessing private objects on a 
+	 * non-logged in session 
+	 */
+	if (!self->pv->logged_in) {
+		if (!gck_object_get_attribute_boolean (object, CKA_PRIVATE, &is_private))
+			is_private = FALSE;
+		if (is_private)
+			return CKR_USER_NOT_LOGGED_IN;
+	}
+	
+	/* 
+	 * If we're going to write to this object check that we're in a 
+	 * writable session and object is modifiable.
+	 */
+	if (writable && !is_token) {
+		if (gck_module_get_write_protected (self->pv->module))
+			return CKR_TOKEN_WRITE_PROTECTED;
+		if (self->pv->read_only && !is_token)
+			return CKR_SESSION_READ_ONLY;
+		if (!gck_object_get_attribute_boolean (object, CKA_MODIFIABLE, &is_modifiable))
+			is_modifiable = FALSE;
+		if (!is_modifiable) /* What's a better return code in this case? */
+			return CKR_ATTRIBUTE_READ_ONLY;
+	}
+	
+	*result = object;
+	return CKR_OK;
+}
+
+static gboolean
+attributes_find_boolean (CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs, 
+                         CK_ATTRIBUTE_TYPE type, CK_BBOOL *value)
+{
+	CK_ULONG i;
+	
+	g_assert (attrs || !n_attrs);
+	g_assert (value);
+	
+	for (i = 0; i < n_attrs; ++i) {
+		if (attrs[i].type == type && 
+		    attrs[i].pValue != NULL && 
+		    attrs[i].ulValueLen == sizeof (CK_BBOOL)) {
+			*value = *((CK_BBOOL*)attrs[i].pValue);
+			return TRUE;
+		}
+	}
+	
+	return FALSE;
+}
+
+/* -----------------------------------------------------------------------------
+ * OBJECT 
+ */
+
+
+static GObject* 
+gck_session_constructor (GType type, guint n_props, GObjectConstructParam *props) 
+{
+	GckSession *self = GCK_SESSION (G_OBJECT_CLASS (gck_session_parent_class)->constructor(type, n_props, props));
+	g_return_val_if_fail (self, NULL);	
+
+
+	
+	return G_OBJECT (self);
+}
+
+static void
+gck_session_init (GckSession *self)
+{
+	self->pv = G_TYPE_INSTANCE_GET_PRIVATE (self, GCK_TYPE_SESSION, GckSessionPrivate);
+	self->pv->read_only = TRUE;
+}
+
+static void
+gck_session_dispose (GObject *obj)
+{
+	GckSession *self = GCK_SESSION (obj);
+
+	/* Cleanup any current operation */
+	if (self->pv->current_operation)
+		(self->pv->current_operation) (self);
+
+	g_return_if_fail (self->pv->module);
+	g_object_unref (self->pv->module);
+	self->pv->module = NULL;
+
+	g_return_if_fail (self->pv->manager);
+	g_object_unref (self->pv->manager);
+	self->pv->manager = NULL;
+	
+	G_OBJECT_CLASS (gck_session_parent_class)->dispose (obj);
+}
+
+static void
+gck_session_finalize (GObject *obj)
+{
+	GckSession *self = GCK_SESSION (obj);
+
+	g_assert (self->pv->module == NULL);
+	g_assert (self->pv->manager == NULL);
+	
+	G_OBJECT_CLASS (gck_session_parent_class)->finalize (obj);
+}
+
+static void
+gck_session_set_property (GObject *obj, guint prop_id, const GValue *value, 
+                           GParamSpec *pspec)
+{
+	GckSession *self = GCK_SESSION (obj);
+	
+	switch (prop_id) {
+	case PROP_MODULE:
+		g_return_if_fail (!self->pv->module);
+		self->pv->module = g_value_get_object (value);
+		g_return_if_fail (self->pv->module);
+		g_object_ref (self->pv->module);
+		break;
+	case PROP_MANAGER:
+		g_return_if_fail (!self->pv->manager);
+		self->pv->manager = g_value_get_object (value);
+		g_return_if_fail (self->pv->manager);
+		g_object_ref (self->pv->manager);
+		break;
+	case PROP_SLOT_ID:
+		self->pv->slot_id = g_value_get_ulong (value);
+		break;
+	case PROP_HANDLE:
+		self->pv->handle = g_value_get_ulong (value);
+		g_return_if_fail (self->pv->handle != 0);
+		break;
+	case PROP_READ_ONLY:
+		self->pv->read_only = g_value_get_boolean (value);
+		break;
+	case PROP_LOGGED_IN:
+		gck_session_set_logged_in (self, g_value_get_boolean (value));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+gck_session_get_property (GObject *obj, guint prop_id, GValue *value, 
+                           GParamSpec *pspec)
+{
+	GckSession *self = GCK_SESSION (obj);
+	
+	switch (prop_id) {
+	case PROP_MODULE:
+		g_value_set_object (value, gck_session_get_module (self));
+		break;
+	case PROP_MANAGER:
+		g_value_set_object (value, gck_session_get_manager (self));
+		break;
+	case PROP_SLOT_ID:
+		g_value_set_ulong (value, gck_session_get_slot_id (self));
+		break;
+	case PROP_HANDLE:
+		g_value_set_ulong (value, gck_session_get_handle (self));
+		break;
+	case PROP_READ_ONLY:
+		g_value_set_boolean (value, gck_session_get_read_only (self));
+		break;
+	case PROP_LOGGED_IN:
+		g_value_set_boolean (value, gck_session_get_logged_in (self));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+gck_session_class_init (GckSessionClass *klass)
+{
+	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+    
+	gck_session_parent_class = g_type_class_peek_parent (klass);
+	g_type_class_add_private (klass, sizeof (GckSessionPrivate));
+
+	gobject_class->constructor = gck_session_constructor;
+	gobject_class->dispose = gck_session_dispose;
+	gobject_class->finalize = gck_session_finalize;
+	gobject_class->set_property = gck_session_set_property;
+	gobject_class->get_property = gck_session_get_property;
+    
+	g_object_class_install_property (gobject_class, PROP_MODULE,
+	         g_param_spec_object ("module", "Module", "Module this session belongs to", 
+	                              GCK_TYPE_MODULE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+	
+	g_object_class_install_property (gobject_class, PROP_MANAGER,
+	         g_param_spec_object ("manager", "Manager", "Object manager for this session", 
+	                              GCK_TYPE_MODULE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+	g_object_class_install_property (gobject_class, PROP_HANDLE,
+	         g_param_spec_ulong ("handle", "Handle", "PKCS#11 session handle", 
+	                             0, G_MAXULONG, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+	g_object_class_install_property (gobject_class, PROP_HANDLE,
+	         g_param_spec_ulong ("slot-id", "Slot ID", "Slot ID this session is opened on", 
+	                             0, G_MAXULONG, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+	
+	g_object_class_install_property (gobject_class, PROP_READ_ONLY,
+	         g_param_spec_boolean ("read-only", "Read Only", "Whether a read-only session or not", 
+	                               TRUE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+	
+	g_object_class_install_property (gobject_class, PROP_LOGGED_IN,
+	         g_param_spec_boolean ("logged-in", "Logged in", "Whether this session is logged in or not", 
+	                               FALSE, G_PARAM_READWRITE));
+
+#if 0
+	signals[SIGNAL] = g_signal_new ("signal", GCK_TYPE_SESSION, 
+	                                G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GckSessionClass, signal),
+	                                NULL, NULL, g_cclosure_marshal_VOID__OBJECT, 
+	                                G_TYPE_NONE, 0);
+#endif
+}
+
+/* -----------------------------------------------------------------------------
+ * PUBLIC 
+ */
+
+CK_SESSION_HANDLE
+gck_session_get_handle (GckSession *self)
+{
+	g_return_val_if_fail (GCK_IS_SESSION (self), 0);
+	return self->pv->handle;
+}
+
+CK_SLOT_ID
+gck_session_get_slot_id (GckSession *self)
+{
+	g_return_val_if_fail (GCK_IS_SESSION (self), 0);
+	return self->pv->slot_id;	
+}
+
+GckModule*
+gck_session_get_module (GckSession *self)
+{
+	g_return_val_if_fail (GCK_IS_SESSION (self), NULL);
+	g_return_val_if_fail (GCK_IS_MODULE (self->pv->module), NULL);
+	return self->pv->module;	
+}
+
+GckManager*
+gck_session_get_manager (GckSession *self)
+{
+	g_return_val_if_fail (GCK_IS_SESSION (self), NULL);
+	g_return_val_if_fail (GCK_IS_MANAGER (self->pv->manager), NULL);
+	return self->pv->manager;	
+}
+
+gboolean
+gck_session_get_logged_in (GckSession *self)
+{
+	g_return_val_if_fail (GCK_IS_SESSION (self), FALSE);
+	return self->pv->logged_in;
+}
+
+void
+gck_session_set_logged_in (GckSession *self, gboolean logged_in)
+{
+	g_return_if_fail (GCK_IS_SESSION (self));
+	self->pv->logged_in = logged_in;
+	g_object_notify (G_OBJECT (self), "logged-in");
+}
+
+gboolean
+gck_session_get_read_only (GckSession *self)
+{
+	g_return_val_if_fail (GCK_IS_SESSION (self), TRUE);
+	return self->pv->read_only;
+}
+
+CK_RV
+gck_session_lookup_readable_object (GckSession *self, CK_OBJECT_HANDLE handle, 
+                                    GckObject **result)
+{
+	return lookup_object_from_handle (self, handle, FALSE, result);
+}
+
+CK_RV
+gck_session_lookup_writable_object (GckSession *self, CK_OBJECT_HANDLE handle, 
+                                    GckObject **result)
+{
+	return lookup_object_from_handle (self, handle, TRUE, result);
+}
+
+CK_RV
+gck_session_login_context_specific (GckSession *self, CK_UTF8CHAR_PTR pin, CK_ULONG n_pin)
+{
+	gboolean always_auth;
+	gboolean is_private;
+	GckObject *object;
+	
+	g_return_val_if_fail (GCK_IS_SESSION (self), CKR_GENERAL_ERROR);
+
+	if (!self->pv->current_object)
+		return CKR_OPERATION_NOT_INITIALIZED;
+
+	object = self->pv->current_object;
+	g_return_val_if_fail (GCK_IS_OBJECT (object), CKR_GENERAL_ERROR);
+	
+	if (!gck_object_get_attribute_boolean (object, CKA_ALWAYS_AUTHENTICATE, &always_auth))
+		always_auth = FALSE; 
+	if (!gck_object_get_attribute_boolean (object, CKA_PRIVATE, &is_private))
+		is_private = FALSE;
+	
+	/* A strange code, but that's what the spec says */
+	if (always_auth == FALSE) 
+		return CKR_OPERATION_NOT_INITIALIZED;
+	
+	/* Double check that the object has what it takes */
+	g_return_val_if_fail (is_private == TRUE, CKR_GENERAL_ERROR);
+	
+	return gck_object_unlock (object, pin, n_pin);
+}
+
+/* -----------------------------------------------------------------------------
+ * PKCS#11
+ */
+
+CK_RV 
+gck_session_C_GetFunctionStatus (GckSession *self)
+{
+	g_return_val_if_fail (GCK_IS_SESSION (self), CKR_SESSION_HANDLE_INVALID);
+	return CKR_FUNCTION_NOT_PARALLEL;
+}
+
+CK_RV 
+gck_session_C_CancelFunction (GckSession *self)
+{
+	g_return_val_if_fail (GCK_IS_SESSION (self), CKR_SESSION_HANDLE_INVALID);
+	return CKR_FUNCTION_NOT_PARALLEL;
+}
+
+CK_RV
+gck_session_C_GetSessionInfo(GckSession* self, CK_SESSION_INFO_PTR info)
+{
+	g_return_val_if_fail (GCK_IS_SESSION (self), CKR_SESSION_HANDLE_INVALID);
+	g_return_val_if_fail (info, CKR_ARGUMENTS_BAD);
+	
+	info->slotID = self->pv->slot_id;
+	if (self->pv->logged_in)
+		info->state = self->pv->read_only ? CKS_RO_USER_FUNCTIONS : CKS_RW_USER_FUNCTIONS;
+	else
+		info->state = self->pv->read_only ? CKS_RO_PUBLIC_SESSION : CKS_RW_PUBLIC_SESSION;
+	info->flags = CKF_SERIAL_SESSION;
+	if (self->pv->read_only)
+		info->flags |= CKF_RW_SESSION;
+	info->ulDeviceError = 0;
+	
+	return CKR_OK;
+}
+
+CK_RV
+gck_session_C_InitPIN (GckSession* self, CK_UTF8CHAR_PTR pin,
+                       CK_ULONG pin_len)
+{
+	/* We don't support this stuff. We don't support 'SO' logins. */
+	return CKR_USER_NOT_LOGGED_IN;	
+}
+
+CK_RV
+gck_session_C_SetPIN (GckSession* self, CK_UTF8CHAR_PTR old_pin,
+                      CK_ULONG old_pin_len, CK_UTF8CHAR_PTR new_pin, CK_ULONG new_pin_len)
+{
+	/* TODO: We may support this in the future. */
+	return CKR_FUNCTION_NOT_SUPPORTED;
+
+}
+
+CK_RV
+gck_session_C_GetOperationState (GckSession* self, CK_BYTE_PTR operation_state,
+                                 CK_ULONG_PTR operation_state_len)
+{
+	/* Nope, We don't bend that way */
+	return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+CK_RV
+gck_session_C_SetOperationState (GckSession* self, CK_BYTE_PTR operation_state,
+                                 CK_ULONG operation_state_len, CK_OBJECT_HANDLE encryption_key,
+                                 CK_OBJECT_HANDLE authentication_key)
+{
+	/* Nope. We don't bend that way */
+	return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+CK_RV
+gck_session_C_CreateObject (GckSession* self, CK_ATTRIBUTE_PTR template,
+                            CK_ULONG count, CK_OBJECT_HANDLE_PTR new_object)
+{
+	/* TODO: Need to implement this */
+ 	return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+CK_RV
+gck_session_C_CopyObject (GckSession* self, CK_OBJECT_HANDLE object,
+                          CK_ATTRIBUTE_PTR template, CK_ULONG count,
+                          CK_OBJECT_HANDLE_PTR new_object)
+{
+	/* 
+	 * TODO: We need to implement this, initially perhaps only 
+	 * only for session objects.
+	 */
+ 	return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+CK_RV
+gck_session_C_GetObjectSize (GckSession* self, CK_ULONG_PTR size)
+{
+	/* TODO: Do we need to implement this? */
+	return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+CK_RV
+gck_session_C_GetAttributeValue (GckSession* self, CK_OBJECT_HANDLE handle, 
+                                 CK_ATTRIBUTE_PTR template, CK_ULONG count)
+{
+	GckObject *object;
+	CK_ULONG i;
+	CK_RV code, rv;
+	
+	g_return_val_if_fail (GCK_IS_SESSION (self), CKR_SESSION_HANDLE_INVALID);
+	g_return_val_if_fail (!count || template, CKR_ARGUMENTS_BAD);
+	
+	rv = gck_session_lookup_readable_object (self, handle, &object);
+	if (rv != CKR_OK)
+		return rv;
+	
+	rv = CKR_OK;
+	
+	for (i = 0; i < count; ++i) {
+		code = gck_object_get_attribute (object, &template[i]);
+
+		/* Not a true error, keep going */
+		if (code == CKR_ATTRIBUTE_SENSITIVE ||
+		    code == CKR_ATTRIBUTE_TYPE_INVALID ||
+		    code == CKR_BUFFER_TOO_SMALL) {
+			rv = code;
+			
+		/* Any other error aborts */
+		} else if (code != CKR_OK) {
+			rv = code;
+			break;
+		}
+	}
+
+	return rv;
+}
+
+CK_RV
+gck_session_C_SetAttributeValue (GckSession* self, CK_OBJECT_HANDLE handle, 
+                                 CK_ATTRIBUTE_PTR template, CK_ULONG count)
+{
+	/* TODO: Need to implement this */
+	return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+CK_RV
+gck_session_C_DestroyObject (GckSession* self, CK_OBJECT_HANDLE object)
+{
+	/* TODO: Need to implement this */
+	return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+CK_RV
+gck_session_C_FindObjectsInit (GckSession* self, CK_ATTRIBUTE_PTR template,
+                               CK_ULONG count)
+{
+	CK_BBOOL token;
+	GArray *found;
+	gboolean all;
+	CK_RV rv;
+	
+	g_return_val_if_fail (GCK_IS_SESSION (self), CKR_SESSION_HANDLE_INVALID);
+	g_return_val_if_fail (template || !count, CKR_ARGUMENTS_BAD);
+	
+	if (self->pv->current_operation)
+		return CKR_OPERATION_ACTIVE;
+
+	/* See whether this is token or not */
+	all = !attributes_find_boolean (template, count, CKA_TOKEN, &token);
+	
+	/* An array of object handles */
+	found = g_array_new (FALSE, TRUE, sizeof (CK_OBJECT_HANDLE));
+	
+	if (all || token)
+		rv = gck_manager_find_handles (gck_module_get_manager (self->pv->module), 
+		                               template, count, found);
+	
+	if (rv == CKR_OK && (all || !token))
+		rv = gck_manager_find_handles (self->pv->manager, template, 
+		                               count, found);
+
+	if (rv != CKR_OK) {
+		g_array_free (found, TRUE);
+		return rv;
+	}
+		
+	g_assert (!self->pv->current_operation);
+	g_assert (!self->pv->found_objects);
+	
+	self->pv->found_objects = found;
+	self->pv->current_operation = cleanup_found;
+	
+	return CKR_OK;
+}
+
+CK_RV
+gck_session_C_FindObjects (GckSession* self, CK_OBJECT_HANDLE_PTR objects,
+                           CK_ULONG max_count, CK_ULONG_PTR count)
+{
+	CK_ULONG n_objects, i;
+	GArray *found;
+	
+	g_return_val_if_fail (GCK_IS_SESSION (self), CKR_SESSION_HANDLE_INVALID);
+	g_return_val_if_fail (objects || !max_count, CKR_ARGUMENTS_BAD);
+	g_return_val_if_fail (count, CKR_ARGUMENTS_BAD);
+
+	if (self->pv->current_operation != cleanup_found)
+		return CKR_OPERATION_NOT_INITIALIZED;
+	
+	g_assert (self->pv->found_objects);
+	found = self->pv->found_objects;
+	
+	n_objects = MIN (max_count, found->len);
+	
+	for (i = 0; i < n_objects; ++i)
+		objects[i] = g_array_index (found, CK_OBJECT_HANDLE, i);
+
+	g_array_remove_range (found, 0, n_objects);
+	return CKR_OK;
+	
+}
+
+CK_RV
+gck_session_C_FindObjectsFinal (GckSession* self)
+{
+	g_return_val_if_fail (GCK_IS_SESSION (self), CKR_SESSION_HANDLE_INVALID);
+
+	if (self->pv->current_operation != cleanup_found)
+		return CKR_OPERATION_NOT_INITIALIZED;
+
+	cleanup_found (self);
+	return CKR_OK;
+}
+
+CK_RV
+gck_session_C_EncryptInit (GckSession *self, CK_MECHANISM_PTR mechanism,
+                           CK_OBJECT_HANDLE key)
+{
+	g_return_val_if_fail (GCK_IS_SESSION (self), CKR_SESSION_HANDLE_INVALID);
+	g_return_val_if_fail (mechanism, CKR_ARGUMENTS_BAD);
+	return prepare_crypto (self, mechanism, CKA_ENCRYPT, key);
+}
+
+CK_RV
+gck_session_C_Encrypt (GckSession *self, CK_BYTE_PTR data, CK_ULONG data_len,
+                       CK_BYTE_PTR encrypted_data, CK_ULONG_PTR encrypted_data_len)
+{
+	g_return_val_if_fail (GCK_IS_SESSION (self), CKR_SESSION_HANDLE_INVALID);
+	g_return_val_if_fail (data, CKR_ARGUMENTS_BAD);
+	return process_crypto (self, CKA_ENCRYPT, data, data_len, encrypted_data, encrypted_data_len);
+}
+
+CK_RV
+gck_session_C_EncryptUpdate (GckSession *self, CK_BYTE_PTR part,
+                             CK_ULONG part_len, CK_BYTE_PTR encrypted_part,
+                             CK_ULONG_PTR encrypted_part_len)
+{
+	/* Our keys don't support this incremental encryption */
+ 	return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+CK_RV
+gck_session_C_EncryptFinal (GckSession *self, CK_BYTE_PTR last_part,
+                            CK_ULONG_PTR last_part_len)
+{
+	/* Our keys don't support this incremental encryption */
+ 	return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+CK_RV
+gck_session_C_DecryptInit (GckSession *self, CK_MECHANISM_PTR mechanism,
+                           CK_OBJECT_HANDLE key)
+{
+	g_return_val_if_fail (GCK_IS_SESSION (self), CKR_SESSION_HANDLE_INVALID);
+	g_return_val_if_fail (mechanism, CKR_ARGUMENTS_BAD);
+	return prepare_crypto (self, mechanism, CKA_DECRYPT, key);	
+}
+
+CK_RV
+gck_session_C_Decrypt (GckSession *self, CK_BYTE_PTR enc_data,
+                       CK_ULONG enc_data_len, CK_BYTE_PTR data, CK_ULONG_PTR data_len)
+{
+	g_return_val_if_fail (GCK_IS_SESSION (self), CKR_SESSION_HANDLE_INVALID);
+	g_return_val_if_fail (data, CKR_ARGUMENTS_BAD);
+	return process_crypto (self, CKA_DECRYPT, enc_data, enc_data_len, data, data_len);
+}
+
+CK_RV
+gck_session_C_DecryptUpdate (GckSession *self, CK_BYTE_PTR enc_part,
+                             CK_ULONG enc_part_len, CK_BYTE_PTR part, CK_ULONG_PTR part_len)
+{
+	/* Our keys don't support this incremental decryption */
+ 	return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+CK_RV
+gck_session_C_DecryptFinal (GckSession *self, CK_BYTE_PTR last_part,
+                            CK_ULONG_PTR last_part_len)
+{
+	/* Our keys don't support this incremental decryption */
+ 	return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+CK_RV
+gck_session_C_DigestInit (GckSession *self, CK_MECHANISM_PTR mechanism)
+{
+	/* We don't do digests */
+ 	return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+CK_RV
+gck_session_C_Digest (GckSession *self, CK_BYTE_PTR data, CK_ULONG data_len,
+                      CK_BYTE_PTR digest, CK_ULONG_PTR digest_len)
+{
+	/* We don't do digests */
+ 	return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+CK_RV
+gck_session_C_DigestUpdate (GckSession *self, CK_BYTE_PTR part, CK_ULONG part_len)
+{
+	/* We don't do digests */
+ 	return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+CK_RV
+gck_session_C_DigestKey (GckSession *self, CK_OBJECT_HANDLE key)
+{
+	/* We don't do digests */
+ 	return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+CK_RV
+gck_session_C_DigestFinal (GckSession *self, CK_BYTE_PTR digest,
+                           CK_ULONG_PTR digest_len)
+{
+	/* We don't do digests */
+ 	return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+CK_RV
+gck_session_C_SignInit (GckSession *self, CK_MECHANISM_PTR mechanism, 
+                        CK_OBJECT_HANDLE key)
+{
+	g_return_val_if_fail (GCK_IS_SESSION (self), CKR_SESSION_HANDLE_INVALID);
+	g_return_val_if_fail (mechanism, CKR_ARGUMENTS_BAD);
+	return prepare_crypto (self, mechanism, CKA_SIGN, key);
+}
+
+CK_RV
+gck_session_C_Sign (GckSession *self, CK_BYTE_PTR data, CK_ULONG data_len,
+                    CK_BYTE_PTR signature, CK_ULONG_PTR signature_len)
+{
+	g_return_val_if_fail (GCK_IS_SESSION (self), CKR_SESSION_HANDLE_INVALID);
+	g_return_val_if_fail (data, CKR_ARGUMENTS_BAD);
+	return process_crypto (self, CKA_SIGN, data, data_len, signature, signature_len);
+}
+
+CK_RV
+gck_session_C_SignUpdate (GckSession *self, CK_BYTE_PTR part, CK_ULONG part_len)
+{
+	/* Our keys don't support incremental operations */
+ 	return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+CK_RV
+gck_session_C_SignFinal (GckSession *self, CK_BYTE_PTR signature,
+                         CK_ULONG_PTR signature_len)
+{
+	/* Our keys don't support incremental operations */
+ 	return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+CK_RV
+gck_session_C_SignRecoverInit (GckSession *self, CK_MECHANISM_PTR mechanism,
+                               CK_OBJECT_HANDLE key)
+{
+	/* TODO: Need to implement */
+ 	return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+CK_RV
+gck_session_C_SignRecover (GckSession *self, CK_BYTE_PTR data, CK_ULONG data_len, 
+                           CK_BYTE_PTR signature, CK_ULONG_PTR signature_len)
+{
+	/* TODO: Need to implement */
+ 	return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+CK_RV
+gck_session_C_VerifyInit (GckSession *self, CK_MECHANISM_PTR mechanism,
+                          CK_OBJECT_HANDLE key)
+{
+	g_return_val_if_fail (GCK_IS_SESSION (self), CKR_SESSION_HANDLE_INVALID);
+	g_return_val_if_fail (mechanism, CKR_ARGUMENTS_BAD);
+	return prepare_crypto (self, mechanism, CKA_VERIFY, key);
+}
+
+CK_RV
+gck_session_C_Verify (GckSession *self, CK_BYTE_PTR data, CK_ULONG data_len,
+                      CK_BYTE_PTR signature, CK_ULONG signature_len)
+{
+	g_return_val_if_fail (GCK_IS_SESSION (self), CKR_SESSION_HANDLE_INVALID);
+	g_return_val_if_fail (data, CKR_ARGUMENTS_BAD);
+	return process_crypto (self, CKA_VERIFY, data, data_len, signature, &signature_len);
+}
+
+CK_RV
+gck_session_C_VerifyUpdate (GckSession *self, CK_BYTE_PTR part, CK_ULONG part_len)
+{
+	/* Our keys don't support incremental operations */
+ 	return CKR_FUNCTION_NOT_SUPPORTED;	
+}
+
+CK_RV
+gck_session_C_VerifyFinal (GckSession *self, CK_BYTE_PTR signature,
+                           CK_ULONG signature_len)
+{
+	/* Our keys don't support incremental operations */
+ 	return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+CK_RV
+gck_session_C_VerifyRecoverInit (GckSession *self, CK_MECHANISM_PTR mechanism,
+                                 CK_OBJECT_HANDLE key)
+{
+	/* TODO: Need to implement */
+ 	return CKR_FUNCTION_NOT_SUPPORTED;	
+}
+
+CK_RV
+gck_session_C_VerifyRecover (GckSession *self, CK_BYTE_PTR signature,
+                             CK_ULONG signature_len, CK_BYTE_PTR data, 
+                             CK_ULONG_PTR data_len)
+{
+	/* TODO: Need to implement */
+ 	return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+CK_RV
+gck_session_C_DigestEncryptUpdate (GckSession *self, CK_BYTE_PTR part,
+                                   CK_ULONG part_len, CK_BYTE_PTR enc_part,
+                                   CK_ULONG_PTR enc_part_len)
+{
+	/* We don't support double operations */
+ 	return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+CK_RV
+gck_session_C_DecryptDigestUpdate (GckSession *self, CK_BYTE_PTR enc_part,
+                                   CK_ULONG enc_part_len, CK_BYTE_PTR part, 
+                                   CK_ULONG_PTR part_len)
+{
+	/* We don't support double operations */
+ 	return CKR_FUNCTION_NOT_SUPPORTED;	
+}
+
+CK_RV
+gck_session_C_SignEncryptUpdate (GckSession *self, CK_BYTE_PTR part,
+                                 CK_ULONG part_len, CK_BYTE_PTR enc_part,
+				 CK_ULONG_PTR enc_part_len)
+{
+	/* We don't support double operations */
+ 	return CKR_FUNCTION_NOT_SUPPORTED;	
+}
+
+CK_RV
+gck_session_C_DecryptVerifyUpdate (GckSession *self, CK_BYTE_PTR enc_part,
+                                   CK_ULONG enc_part_len, CK_BYTE_PTR part, 
+                                   CK_ULONG_PTR part_len)
+{
+	/* We don't support double operations */
+ 	return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+CK_RV
+gck_session_C_GenerateKey (GckSession* self, CK_MECHANISM_PTR mechanism,
+                           CK_ATTRIBUTE_PTR template, CK_ULONG count, 
+                           CK_OBJECT_HANDLE_PTR key)
+{
+	/* TODO: We need to implement this */
+ 	return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+CK_RV
+gck_session_C_GenerateKeyPair (GckSession* self, CK_MECHANISM_PTR mechanism,
+                               CK_ATTRIBUTE_PTR pub_template, CK_ULONG pub_count,
+                               CK_ATTRIBUTE_PTR priv_template, CK_ULONG priv_count,
+                               CK_OBJECT_HANDLE_PTR pub_key, CK_OBJECT_HANDLE_PTR priv_key)
+{
+	/* TODO: We need to implement this */
+ 	return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+CK_RV
+gck_session_C_WrapKey (GckSession* self, CK_MECHANISM_PTR mechanism,
+                       CK_OBJECT_HANDLE wrapping_key, CK_OBJECT_HANDLE key,
+                       CK_BYTE_PTR wrapped_key, CK_ULONG_PTR wrapped_key_len)
+{
+	/* TODO: We need to implement this */
+ 	return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+CK_RV
+gck_session_C_UnwrapKey (GckSession* self, CK_MECHANISM_PTR mechanism,
+                         CK_OBJECT_HANDLE unwrapping_key, CK_BYTE_PTR wrapped_key,
+                         CK_ULONG wrapped_key_len, CK_ATTRIBUTE_PTR template,
+                         CK_ULONG count, CK_OBJECT_HANDLE_PTR key)
+{
+	/* TODO: We need to implement this */
+ 	return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+CK_RV
+gck_session_C_DeriveKey (GckSession* self, CK_MECHANISM_PTR mechanism,
+                         CK_OBJECT_HANDLE base_key, CK_ATTRIBUTE_PTR template,
+                         CK_ULONG count, CK_OBJECT_HANDLE_PTR key)
+{
+	/* Our keys don't support derivation */
+ 	return CKR_FUNCTION_NOT_SUPPORTED;	
+}
+
+CK_RV
+gck_session_C_SeedRandom (GckSession* self, CK_BYTE_PTR seed, CK_ULONG seed_len)
+{
+	/* We don't have a RNG */
+ 	return CKR_RANDOM_NO_RNG;
+}
+
+CK_RV
+gck_session_C_GenerateRandom (GckSession* self, CK_BYTE_PTR random_data,
+                              CK_ULONG random_len)
+{
+	/* We don't have a RNG */
+ 	return CKR_RANDOM_NO_RNG;	
+}

Added: trunk/pkcs11/gck/gck-session.h
==============================================================================
--- (empty file)
+++ trunk/pkcs11/gck/gck-session.h	Sun Dec 21 15:44:20 2008
@@ -0,0 +1,344 @@
+/* 
+ * gnome-keyring
+ * 
+ * Copyright (C) 2008 Stefan Walter
+ * 
+ * This program is free software; you can redistribute it and/or modify 
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *  
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *  
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.  
+ */
+
+#ifndef __GCK_SESSION_H__
+#define __GCK_SESSION_H__
+
+#include <glib-object.h>
+
+#include "gck-module.h"
+#include "gck-manager.h"
+
+#define GCK_TYPE_SESSION               (gck_session_get_type ())
+#define GCK_SESSION(obj)               (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCK_TYPE_SESSION, GckSession))
+#define GCK_SESSION_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST ((klass), GCK_TYPE_SESSION, GckSessionClass))
+#define GCK_IS_SESSION(obj)            (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCK_TYPE_SESSION))
+#define GCK_IS_SESSION_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE ((klass), GCK_TYPE_SESSION))
+#define GCK_SESSION_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS ((obj), GCK_TYPE_SESSION, GckSessionClass))
+
+typedef struct _GckSessionClass GckSessionClass;
+typedef struct _GckSessionPrivate GckSessionPrivate;
+    
+struct _GckSession {
+	GObject parent;
+	GckSessionPrivate *pv;
+};
+
+struct _GckSessionClass {
+	GObjectClass parent_class;
+    
+#if 0
+	/* signals --------------------------------------------------------- */
+    
+	void (*signal) (GckSession *session);
+#endif
+};
+
+GType                    gck_session_get_type                           (void);
+
+GckSession*              gck_session_new                                (GckModule *module, 
+                                                                         GckManager *manager,
+                                                                         CK_SLOT_ID slot_id,
+                                                                         CK_FLAGS flags);
+
+CK_SESSION_HANDLE        gck_session_get_handle                         (GckSession *self);
+
+CK_SLOT_ID               gck_session_get_slot_id                        (GckSession *self);
+
+GckModule*               gck_session_get_module                         (GckSession *self);
+
+GckManager*              gck_session_get_manager                        (GckSession *self);
+
+gboolean                 gck_session_get_read_only                      (GckSession *self);
+
+gboolean                 gck_session_get_logged_in                      (GckSession *self);
+
+void                     gck_session_set_logged_in                      (GckSession *self,
+                                                                         gboolean logged_in);
+
+CK_RV                    gck_session_lookup_readable_object             (GckSession *self, 
+                                                                         CK_OBJECT_HANDLE handle, 
+                                                                         GckObject **result);
+
+CK_RV                    gck_session_lookup_writable_object             (GckSession *self, 
+                                                                         CK_OBJECT_HANDLE handle, 
+                                                                         GckObject **result);
+
+CK_RV                    gck_session_login_context_specific             (GckSession *self,
+                                                                         CK_UTF8CHAR_PTR pin,
+                                                                         CK_ULONG n_pin);
+
+
+
+
+
+CK_RV                    gck_session_C_GetFunctionStatus                (GckSession *self);
+
+CK_RV                    gck_session_C_CancelFunction                   (GckSession *self);
+
+CK_RV                    gck_session_C_GetSessionInfo                   (GckSession* self, 
+                                                                         CK_SESSION_INFO_PTR info);
+
+CK_RV                    gck_session_C_InitPIN                          (GckSession* self, 
+                                                                         CK_UTF8CHAR_PTR pin,
+                                                                         CK_ULONG pin_len);
+
+CK_RV                    gck_session_C_SetPIN                           (GckSession* self, 
+                                                                         CK_UTF8CHAR_PTR old_pin,
+                                                                         CK_ULONG old_pin_len, 
+                                                                         CK_UTF8CHAR_PTR new_pin, 
+                                                                         CK_ULONG new_pin_len);
+
+CK_RV                    gck_session_C_GetOperationState                (GckSession* self, 
+                                                                         CK_BYTE_PTR operation_state,
+                                                                         CK_ULONG_PTR operation_state_len);
+
+CK_RV                    gck_session_C_SetOperationState                (GckSession* self, 
+                                                                         CK_BYTE_PTR operation_state,
+                                                                         CK_ULONG operation_state_len, 
+                                                                         CK_OBJECT_HANDLE encryption_key,
+                                                                         CK_OBJECT_HANDLE authentication_key);
+
+CK_RV                    gck_session_C_CreateObject                     (GckSession* self, 
+                                                                         CK_ATTRIBUTE_PTR template,
+                                                                         CK_ULONG count, 
+                                                                         CK_OBJECT_HANDLE_PTR new_object);
+
+CK_RV                    gck_session_C_CopyObject                       (GckSession* self, 
+                                                                         CK_OBJECT_HANDLE object,
+                                                                         CK_ATTRIBUTE_PTR template, 
+                                                                         CK_ULONG count,
+                                                                         CK_OBJECT_HANDLE_PTR new_object);
+
+CK_RV                    gck_session_C_DestroyObject                    (GckSession* self, 
+                                                                         CK_OBJECT_HANDLE object);
+
+CK_RV                    gck_session_C_GetObjectSize                    (GckSession* self, 
+                                                                         CK_ULONG_PTR size);
+
+CK_RV                    gck_session_C_GetAttributeValue                (GckSession* self, 
+                                                                         CK_OBJECT_HANDLE handle, 
+                                                                         CK_ATTRIBUTE_PTR template, 
+                                                                         CK_ULONG count);
+
+CK_RV                    gck_session_C_SetAttributeValue                (GckSession* self, 
+                                                                         CK_OBJECT_HANDLE handle, 
+                                                                         CK_ATTRIBUTE_PTR template, 
+                                                                         CK_ULONG count);
+
+CK_RV                    gck_session_C_FindObjectsInit                  (GckSession* self, 
+                                                                         CK_ATTRIBUTE_PTR template,
+                                                                         CK_ULONG count);
+
+CK_RV                    gck_session_C_FindObjects                      (GckSession* self, 
+                                                                         CK_OBJECT_HANDLE_PTR objects,
+                                                                         CK_ULONG max_count, 
+                                                                         CK_ULONG_PTR count);
+
+CK_RV                    gck_session_C_FindObjectsFinal                 (GckSession* self);
+
+CK_RV                    gck_session_C_EncryptInit                      (GckSession *self, 
+                                                                         CK_MECHANISM_PTR mechanism,
+                                                                         CK_OBJECT_HANDLE key);
+
+CK_RV                    gck_session_C_Encrypt                          (GckSession *self, 
+                                                                         CK_BYTE_PTR data, 
+                                                                         CK_ULONG data_len,
+                                                                         CK_BYTE_PTR encrypted_data, 
+                                                                         CK_ULONG_PTR encrypted_data_len);
+
+CK_RV                    gck_session_C_EncryptUpdate                    (GckSession *self, 
+                                                                         CK_BYTE_PTR part,
+                                                                         CK_ULONG part_len, 
+                                                                         CK_BYTE_PTR encrypted_part,
+                                                                         CK_ULONG_PTR encrypted_part_len);
+
+CK_RV                    gck_session_C_EncryptFinal                     (GckSession *self, 
+                                                                         CK_BYTE_PTR last_part,
+                                                                         CK_ULONG_PTR last_part_len);
+
+CK_RV                    gck_session_C_DecryptInit                      (GckSession *self, 
+                                                                         CK_MECHANISM_PTR mechanism,
+                                                                         CK_OBJECT_HANDLE key);
+
+CK_RV                    gck_session_C_Decrypt                          (GckSession *self, 
+                                                                         CK_BYTE_PTR enc_data,
+                                                                         CK_ULONG enc_data_len, 
+                                                                         CK_BYTE_PTR data, 
+                                                                         CK_ULONG_PTR data_len);
+
+CK_RV                    gck_session_C_DecryptUpdate                    (GckSession *self, 
+                                                                         CK_BYTE_PTR enc_part,
+                                                                         CK_ULONG enc_part_len, 
+                                                                         CK_BYTE_PTR part, 
+                                                                         CK_ULONG_PTR part_len);
+
+CK_RV                    gck_session_C_DecryptFinal                     (GckSession *self, 
+                                                                         CK_BYTE_PTR last_part,
+                                                                         CK_ULONG_PTR last_part_len);
+
+CK_RV                    gck_session_C_DigestInit                       (GckSession *self, 
+                                                                         CK_MECHANISM_PTR mechanism);
+
+CK_RV                    gck_session_C_Digest                           (GckSession *self, 
+                                                                         CK_BYTE_PTR data, 
+                                                                         CK_ULONG data_len,
+                                                                         CK_BYTE_PTR digest, 
+                                                                         CK_ULONG_PTR digest_len);
+
+CK_RV                    gck_session_C_DigestUpdate                     (GckSession *self, 
+                                                                         CK_BYTE_PTR part, 
+                                                                         CK_ULONG part_len);
+
+CK_RV                    gck_session_C_DigestKey                        (GckSession *self, 
+                                                                         CK_OBJECT_HANDLE key);
+
+CK_RV                    gck_session_C_DigestFinal                      (GckSession *self, 
+                                                                         CK_BYTE_PTR digest,
+                                                                         CK_ULONG_PTR digest_len);
+
+CK_RV                    gck_session_C_SignInit                         (GckSession *self, 
+                                                                         CK_MECHANISM_PTR mechanism, 
+                                                                         CK_OBJECT_HANDLE key);
+
+CK_RV                    gck_session_C_Sign                             (GckSession *self, 
+                                                                         CK_BYTE_PTR data, 
+                                                                         CK_ULONG data_len,
+                                                                         CK_BYTE_PTR signature, 
+                                                                         CK_ULONG_PTR signature_len);
+
+CK_RV                    gck_session_C_SignUpdate                       (GckSession *self, 
+                                                                         CK_BYTE_PTR part, 
+                                                                         CK_ULONG part_len);
+
+CK_RV                    gck_session_C_SignFinal                        (GckSession *self, 
+                                                                         CK_BYTE_PTR signature,
+                                                                         CK_ULONG_PTR signature_len);
+
+CK_RV                    gck_session_C_SignRecoverInit                  (GckSession *self, 
+                                                                         CK_MECHANISM_PTR mechanism,
+                                                                         CK_OBJECT_HANDLE key);
+
+CK_RV                    gck_session_C_SignRecover                      (GckSession *self, 
+                                                                         CK_BYTE_PTR data, 
+                                                                         CK_ULONG data_len, 
+                                                                         CK_BYTE_PTR signature, 
+                                                                         CK_ULONG_PTR signature_len);
+
+CK_RV                    gck_session_C_VerifyInit                       (GckSession *self, 
+                                                                         CK_MECHANISM_PTR mechanism,
+                                                                         CK_OBJECT_HANDLE key);
+
+CK_RV                    gck_session_C_Verify                           (GckSession *self, 
+                                                                         CK_BYTE_PTR data, 
+                                                                         CK_ULONG data_len,
+                                                                         CK_BYTE_PTR signature, 
+                                                                         CK_ULONG signature_len);
+
+CK_RV                    gck_session_C_VerifyUpdate                     (GckSession *self, 
+                                                                         CK_BYTE_PTR part, 
+                                                                         CK_ULONG part_len);
+
+CK_RV                    gck_session_C_VerifyFinal                      (GckSession *self, 
+                                                                         CK_BYTE_PTR signature,
+                                                                         CK_ULONG signature_len);
+
+CK_RV                    gck_session_C_VerifyRecoverInit                (GckSession *self, 
+                                                                         CK_MECHANISM_PTR mechanism,
+                                                                         CK_OBJECT_HANDLE key);
+
+CK_RV                    gck_session_C_VerifyRecover                    (GckSession *self, 
+                                                                         CK_BYTE_PTR signature,
+                                                                         CK_ULONG signature_len, 
+                                                                         CK_BYTE_PTR data, 
+                                                                         CK_ULONG_PTR data_len);
+
+CK_RV                    gck_session_C_DigestEncryptUpdate              (GckSession *self, 
+                                                                         CK_BYTE_PTR part,
+                                                                         CK_ULONG part_len, 
+                                                                         CK_BYTE_PTR enc_part,
+                                                                         CK_ULONG_PTR enc_part_len);
+
+CK_RV                    gck_session_C_DecryptDigestUpdate              (GckSession *self, 
+                                                                         CK_BYTE_PTR enc_part,
+                                                                         CK_ULONG enc_part_len, 
+                                                                         CK_BYTE_PTR part, 
+                                                                         CK_ULONG_PTR part_len);
+
+CK_RV                    gck_session_C_SignEncryptUpdate                (GckSession *self, 
+                                                                         CK_BYTE_PTR part,
+                                                                         CK_ULONG part_len, 
+                                                                         CK_BYTE_PTR enc_part,
+                                                                         CK_ULONG_PTR enc_part_len);
+
+CK_RV                    gck_session_C_DecryptVerifyUpdate              (GckSession *self, 
+                                                                         CK_BYTE_PTR enc_part,
+                                                                         CK_ULONG enc_part_len, 
+                                                                         CK_BYTE_PTR part, 
+                                                                         CK_ULONG_PTR part_len);
+
+CK_RV                    gck_session_C_GenerateKey                      (GckSession* self, 
+                                                                         CK_MECHANISM_PTR mechanism,
+                                                                         CK_ATTRIBUTE_PTR template, 
+                                                                         CK_ULONG count, 
+                                                                         CK_OBJECT_HANDLE_PTR key);
+
+CK_RV                    gck_session_C_GenerateKeyPair                  (GckSession* self, 
+                                                                         CK_MECHANISM_PTR mechanism,
+                                                                         CK_ATTRIBUTE_PTR pub_template, 
+                                                                         CK_ULONG pub_count,
+                                                                         CK_ATTRIBUTE_PTR priv_template, 
+                                                                         CK_ULONG priv_count,
+                                                                         CK_OBJECT_HANDLE_PTR pub_key, 
+                                                                         CK_OBJECT_HANDLE_PTR priv_key);
+
+CK_RV                    gck_session_C_WrapKey                          (GckSession* self, 
+                                                                         CK_MECHANISM_PTR mechanism,
+                                                                         CK_OBJECT_HANDLE wrapping_key, 
+                                                                         CK_OBJECT_HANDLE key,
+                                                                         CK_BYTE_PTR wrapped_key, 
+                                                                         CK_ULONG_PTR wrapped_key_len);
+
+CK_RV                    gck_session_C_UnwrapKey                        (GckSession* self, 
+                                                                         CK_MECHANISM_PTR mechanism,
+                                                                         CK_OBJECT_HANDLE unwrapping_key, 
+                                                                         CK_BYTE_PTR wrapped_key,
+                                                                         CK_ULONG wrapped_key_len, 
+                                                                         CK_ATTRIBUTE_PTR template,
+                                                                         CK_ULONG count, 
+                                                                         CK_OBJECT_HANDLE_PTR key);
+
+CK_RV                    gck_session_C_DeriveKey                        (GckSession* self, 
+                                                                         CK_MECHANISM_PTR mechanism,
+                                                                         CK_OBJECT_HANDLE base_key, 
+                                                                         CK_ATTRIBUTE_PTR template,
+                                                                         CK_ULONG count, 
+                                                                         CK_OBJECT_HANDLE_PTR key);
+
+CK_RV                    gck_session_C_SeedRandom                       (GckSession* self, 
+                                                                         CK_BYTE_PTR seed, 
+                                                                         CK_ULONG seed_len);
+
+CK_RV                    gck_session_C_GenerateRandom                   (GckSession* self, 
+                                                                         CK_BYTE_PTR random_data,
+                                                                         CK_ULONG random_len);
+
+#endif /* __GCK_SESSION_H__ */

Added: trunk/pkcs11/gck/gck-sexp.c
==============================================================================
--- (empty file)
+++ trunk/pkcs11/gck/gck-sexp.c	Sun Dec 21 15:44:20 2008
@@ -0,0 +1,78 @@
+/* 
+ * gnome-keyring
+ * 
+ * Copyright (C) 2008 Stefan Walter
+ * 
+ * This program is free software; you can redistribute it and/or modify 
+ * it under the terms of the GNU Lesser General  License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *  
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General  License for more details.
+ *  
+ * You should have received a copy of the GNU Lesser General 
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.  
+ */
+
+#include "config.h"
+
+#include "gck-sexp.h"
+
+struct _GckSexp {
+	gint refs;
+	gcry_sexp_t real;
+};
+
+GckSexp*
+gck_sexp_new (gcry_sexp_t real)
+{
+	GckSexp *sexp;
+	g_return_val_if_fail (real, NULL);
+	sexp = g_slice_new0 (GckSexp);
+	sexp->refs = 1;
+	sexp->real = real;
+	return sexp;
+}
+
+GckSexp*
+gck_sexp_ref (GckSexp *sexp)
+{
+	g_return_val_if_fail (sexp, NULL);
+	++(sexp->refs);
+	return sexp;
+}
+
+void
+gck_sexp_unref (GckSexp *sexp)
+{
+	g_return_if_fail (sexp);
+	if (--(sexp->refs) == 0) {
+		g_assert (sexp->real);
+		gcry_sexp_release (sexp->real);
+		g_slice_free (GckSexp, sexp); 
+	}
+}
+
+gcry_sexp_t
+gck_sexp_get (GckSexp *sexp)
+{
+	g_return_val_if_fail (sexp, NULL);
+	g_return_val_if_fail (sexp->real, NULL);
+	return sexp->real;
+}
+
+GType
+gck_sexp_boxed_type (void)
+{
+	static GType type = 0;
+	if (!type) 
+		type = g_boxed_type_register_static ("GckSexp", 
+		                                     (GBoxedCopyFunc)gck_sexp_ref,
+		                                     (GBoxedFreeFunc)gck_sexp_unref);
+	return type;
+}

Added: trunk/pkcs11/gck/gck-sexp.h
==============================================================================
--- (empty file)
+++ trunk/pkcs11/gck/gck-sexp.h	Sun Dec 21 15:44:20 2008
@@ -0,0 +1,44 @@
+/* 
+ * gnome-keyring
+ * 
+ * Copyright (C) 2008 Stefan Walter
+ * 
+ * This program is free software; you can redistribute it and/or modify 
+ * it under the terms of the GNU Lesser General  License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *  
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General  License for more details.
+ *  
+ * You should have received a copy of the GNU Lesser General 
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.  
+ */
+
+#ifndef GCKSEXP_H_
+#define GCKSEXP_H_
+
+#include <gcrypt.h>
+
+#include <glib-object.h>
+
+struct _GckSexp;
+typedef struct _GckSexp GckSexp;
+
+GckSexp*       gck_sexp_new           (gcry_sexp_t sexp);
+
+GckSexp*       gck_sexp_ref           (GckSexp *sexp);
+
+void           gck_sexp_unref         (GckSexp *sexp);
+
+gcry_sexp_t    gck_sexp_get           (GckSexp *sexp);
+
+#define        GCK_BOXED_SEXP         (gck_sexp_boxed_type ())
+
+GType          gck_sexp_boxed_type    (void);
+
+#endif /* GCKSEXPHANDLE_H_ */

Added: trunk/pkcs11/gck/gck-util.c
==============================================================================
--- (empty file)
+++ trunk/pkcs11/gck/gck-util.c	Sun Dec 21 15:44:20 2008
@@ -0,0 +1,133 @@
+/* 
+ * gnome-keyring
+ * 
+ * Copyright (C) 2008 Stefan Walter
+ * 
+ * This program is free software; you can redistribute it and/or modify 
+ * it under the terms of the GNU Lesser General  License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *  
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General  License for more details.
+ *  
+ * You should have received a copy of the GNU Lesser General 
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.  
+ */
+
+#include "config.h"
+
+#include "gck-util.h"
+
+/* Only access using atomic operations */
+static gint next_handle = 0x00000010;
+
+gulong*
+gck_util_ulong_alloc (gulong value)
+{
+	return g_slice_dup (gulong, &value);
+}
+
+void
+gck_util_ulong_free (gpointer ptr_to_ulong)
+{
+	g_slice_free (gulong, ptr_to_ulong);
+}
+
+guint
+gck_util_ulong_hash (gconstpointer v)
+{
+	const signed char *p = v;
+	guint32 i, h = *p;
+	for(i = 0; i < sizeof (gulong); ++i)
+		h = (h << 5) - h + *(p++);
+	return h;
+}
+
+gboolean
+gck_util_ulong_equal (gconstpointer v1, gconstpointer v2)
+{
+	return *((const gulong*)v1) == *((const gulong*)v2);
+}
+
+CK_RV
+gck_util_set_bool (CK_ATTRIBUTE_PTR attr, CK_BBOOL value)
+{
+	return gck_util_set_data (attr, &value, sizeof (CK_BBOOL));
+}
+
+CK_RV
+gck_util_set_ulong (CK_ATTRIBUTE_PTR attr, CK_ULONG value)
+{
+	return gck_util_set_data (attr, &value, sizeof (CK_ULONG));
+}
+
+CK_RV
+gck_util_set_data (CK_ATTRIBUTE_PTR attr, CK_VOID_PTR value, CK_ULONG n_value)
+{
+	return gck_util_return_data (attr->pValue, &(attr->ulValueLen), value, n_value);
+}
+
+CK_RV
+gck_util_return_data (CK_VOID_PTR output, CK_ULONG_PTR n_output,
+                      CK_VOID_PTR input, CK_ULONG n_input)
+{
+	g_return_val_if_fail (n_output, CKR_GENERAL_ERROR);
+	g_return_val_if_fail (input, CKR_GENERAL_ERROR);
+	
+	/* Just asking for the length */
+	if (!output) {
+		*n_output = n_input;
+		return CKR_OK;
+	}
+	
+	/* Buffer is too short */
+	if (n_input > *n_output) {
+		*n_output = n_input;
+		return CKR_BUFFER_TOO_SMALL;
+	}
+
+	*n_output = n_input;
+	memcpy (output, input, n_input);
+	return CKR_OK;
+}
+
+CK_RV
+gck_util_set_mpi (CK_ATTRIBUTE_PTR attr, gcry_mpi_t mpi)
+{
+	gsize len;
+  	gcry_error_t gcry;
+
+	g_assert (attr);
+	g_assert (mpi);
+	
+	/* Get the size */
+	gcry = gcry_mpi_print (GCRYMPI_FMT_USG, NULL, 0, &len, mpi);
+	g_return_val_if_fail (gcry == 0, CKR_GENERAL_ERROR);
+
+	if (!attr->pValue) {
+		attr->ulValueLen = len;
+		return CKR_OK;
+	}
+	
+	if (len > attr->ulValueLen) {
+		attr->ulValueLen = len;
+		return CKR_BUFFER_TOO_SMALL;
+	}
+
+	/* Write in directly to attribute */
+	gcry = gcry_mpi_print (GCRYMPI_FMT_USG, attr->pValue, len, &len, mpi);	
+	g_return_val_if_fail (gcry == 0, CKR_GENERAL_ERROR);
+	
+	return CKR_OK;
+}
+
+CK_ULONG
+gck_util_next_handle (void)
+{
+	return (CK_ULONG)g_atomic_int_exchange_and_add (&next_handle, 1);
+}

Added: trunk/pkcs11/gck/gck-util.h
==============================================================================
--- (empty file)
+++ trunk/pkcs11/gck/gck-util.h	Sun Dec 21 15:44:20 2008
@@ -0,0 +1,60 @@
+/* 
+ * gnome-keyring
+ * 
+ * Copyright (C) 2008 Stefan Walter
+ * 
+ * This program is free software; you can redistribute it and/or modify 
+ * it under the terms of the GNU Lesser General  License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *  
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General  License for more details.
+ *  
+ * You should have received a copy of the GNU Lesser General 
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.  
+ */
+
+#ifndef GCKUTIL_H_
+#define GCKUTIL_H_
+
+#include <glib.h>
+
+#include <gcrypt.h>
+
+#include "pkcs11/pkcs11.h"
+
+guint                 gck_util_ulong_hash                         (gconstpointer ptr_to_ulong);
+
+gboolean              gck_util_ulong_equal                        (gconstpointer ptr_to_ulong_1, 
+                                                                   gconstpointer ptr_to_ulong_2);
+
+gulong*               gck_util_ulong_alloc                        (gulong value);
+
+void                  gck_util_ulong_free                         (gpointer ptr_to_ulong);
+
+CK_RV                 gck_util_set_bool                           (CK_ATTRIBUTE_PTR attr,
+                                                                   CK_BBOOL value);
+
+CK_RV                 gck_util_set_ulong                          (CK_ATTRIBUTE_PTR attr, 
+                                                                   CK_ULONG value);
+
+CK_RV                 gck_util_set_data                           (CK_ATTRIBUTE_PTR attr,
+                                                                   CK_VOID_PTR value,
+                                                                   CK_ULONG n_value);
+
+CK_RV                 gck_util_return_data                        (CK_VOID_PTR output,
+                                                                   CK_ULONG_PTR n_output,
+                                                                   CK_VOID_PTR input,
+                                                                   CK_ULONG n_input);
+
+CK_RV                 gck_util_set_mpi                            (CK_ATTRIBUTE_PTR attr, 
+                                                                   gcry_mpi_t mpi);
+
+CK_ULONG              gck_util_next_handle                        (void);
+
+#endif /* GCKUTIL_H_ */

Added: trunk/pkcs11/gck/temporary-test.c
==============================================================================
--- (empty file)
+++ trunk/pkcs11/gck/temporary-test.c	Sun Dec 21 15:44:20 2008
@@ -0,0 +1,10 @@
+
+#include "gck-crypto.h"
+#include <stdlib.h>
+
+int 
+main(int argc, char* argv[])
+{
+	gck_crypto_perform (NULL, 0, 0, NULL, 0, NULL, NULL);
+	return 0;
+}



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