gnome-keyring r1401 - in trunk: . pkcs11 pkcs11/gck
- From: nnielsen svn gnome org
- To: svn-commits-list gnome org
- Subject: gnome-keyring r1401 - in trunk: . pkcs11 pkcs11/gck
- Date: Sun, 21 Dec 2008 15:44:20 +0000 (UTC)
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]