summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Walter <stefw@src.gnome.org>2008-07-14 19:54:11 +0000
committerStefan Walter <stefw@src.gnome.org>2008-07-14 19:54:11 +0000
commit59199cf372b2d871e7a5f4d6efa57cc2d46d6dc4 (patch)
tree287038a76286a0e98572535d1f0016e1df18f6e1
parent2800c08ecc82c00223b667242fc5f0a2896261b0 (diff)
Only use CKR_GENERAL_ERROR when it's really quite dire.
* daemon/pk/gkr-pk-cert.c: * daemon/pk/gkr-pk-import.c: * daemon/pk/gkr-pk-object.c: * daemon/pk/gkr-pk-privkey.c: * daemon/pk/gkr-pk-pubkey.c: * daemon/pkcs11/gkr-pkcs11-daemon-session.c: * daemon/pkcs11/gkr-pkcs11-dsa.c: * daemon/pkcs11/gkr-pkcs11-rsa.c: Only use CKR_GENERAL_ERROR when it's really quite dire. * gp11/gp11.h: (added) * gp11/gp11.pc.in: (added) * gp11/gp11-attributes.c: (added) * gp11/gp11-call.c: (added) * gp11/gp11-misc.c: (added) * gp11/gp11-module.c: (added) * gp11/gp11-object.c: (added) * gp11/gp11-private.h: (added) * gp11/gp11-session.c: (added) * gp11/gp11-slot.c: (added) * gp11/Makefile.am: (added) * gp11/pkcs11.h: (added) * gp11/tests/gp11-test.h: (added) * gp11/tests/gp11-test-module.c: (added) * gp11/tests/Makefile.am: (added) * gp11/tests/unit-test-gp11-attributes.c: (added) * gp11/tests/unit-test-gp11-module.c: (added) * gp11/tests/unit-test-gp11-object.c: (added) * gp11/tests/unit-test-gp11-session.c: (added) * gp11/tests/unit-test-gp11-slot.c: (added) * tests/check.make: (added) * tests/check-helpers.c: (added) * tests/check-helpers.h: (added) * tests/prep-check.sh: (added) * configure.in: * Makefile.am: Added new GP11 library svn path=/trunk/; revision=1175
-rw-r--r--ChangeLog39
-rw-r--r--HACKING23
-rw-r--r--Makefile.am1
-rw-r--r--configure.in78
-rw-r--r--daemon/pk/gkr-pk-cert.c14
-rw-r--r--daemon/pk/gkr-pk-import.c2
-rw-r--r--daemon/pk/gkr-pk-object.c4
-rw-r--r--daemon/pk/gkr-pk-privkey.c12
-rw-r--r--daemon/pk/gkr-pk-pubkey.c18
-rw-r--r--daemon/pkcs11/gkr-pkcs11-daemon-session.c6
-rw-r--r--daemon/pkcs11/gkr-pkcs11-dsa.c16
-rw-r--r--daemon/pkcs11/gkr-pkcs11-rsa.c24
-rw-r--r--gp11/Makefile.am52
-rw-r--r--gp11/gp11-attributes.c508
-rw-r--r--gp11/gp11-call.c341
-rw-r--r--gp11/gp11-misc.c218
-rw-r--r--gp11/gp11-module.c319
-rw-r--r--gp11/gp11-object.c458
-rw-r--r--gp11/gp11-private.h99
-rw-r--r--gp11/gp11-session.c864
-rw-r--r--gp11/gp11-slot.c436
-rw-r--r--gp11/gp11.h1294
-rw-r--r--gp11/gp11.pc.in14
-rw-r--r--gp11/pkcs11.h1357
-rw-r--r--gp11/tests/Makefile.am39
-rw-r--r--gp11/tests/gp11-test-module.c1297
-rw-r--r--gp11/tests/gp11-test.h22
-rw-r--r--gp11/tests/unit-test-gp11-attributes.c440
-rw-r--r--gp11/tests/unit-test-gp11-module.c67
-rw-r--r--gp11/tests/unit-test-gp11-object.c369
-rw-r--r--gp11/tests/unit-test-gp11-session.c142
-rw-r--r--gp11/tests/unit-test-gp11-slot.c122
-rw-r--r--tests/check-helpers.c161
-rw-r--r--tests/check-helpers.h36
-rw-r--r--tests/check.make62
-rwxr-xr-xtests/prep-check.sh134
36 files changed, 9012 insertions, 76 deletions
diff --git a/ChangeLog b/ChangeLog
index 5bb79de5..ad9234ca 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,42 @@
+2008-07-14 Stef Walter <stef@memberwebs.com>
+
+ * daemon/pk/gkr-pk-cert.c:
+ * daemon/pk/gkr-pk-import.c:
+ * daemon/pk/gkr-pk-object.c:
+ * daemon/pk/gkr-pk-privkey.c:
+ * daemon/pk/gkr-pk-pubkey.c:
+ * daemon/pkcs11/gkr-pkcs11-daemon-session.c:
+ * daemon/pkcs11/gkr-pkcs11-dsa.c:
+ * daemon/pkcs11/gkr-pkcs11-rsa.c: Only use CKR_GENERAL_ERROR
+ when it's really quite dire.
+
+ * gp11/gp11.h: (added)
+ * gp11/gp11.pc.in: (added)
+ * gp11/gp11-attributes.c: (added)
+ * gp11/gp11-call.c: (added)
+ * gp11/gp11-misc.c: (added)
+ * gp11/gp11-module.c: (added)
+ * gp11/gp11-object.c: (added)
+ * gp11/gp11-private.h: (added)
+ * gp11/gp11-session.c: (added)
+ * gp11/gp11-slot.c: (added)
+ * gp11/Makefile.am: (added)
+ * gp11/pkcs11.h: (added)
+ * gp11/tests/gp11-test.h: (added)
+ * gp11/tests/gp11-test-module.c: (added)
+ * gp11/tests/Makefile.am: (added)
+ * gp11/tests/unit-test-gp11-attributes.c: (added)
+ * gp11/tests/unit-test-gp11-module.c: (added)
+ * gp11/tests/unit-test-gp11-object.c: (added)
+ * gp11/tests/unit-test-gp11-session.c: (added)
+ * gp11/tests/unit-test-gp11-slot.c: (added)
+ * tests/check.make: (added)
+ * tests/check-helpers.c: (added)
+ * tests/check-helpers.h: (added)
+ * tests/prep-check.sh: (added)
+ * configure.in:
+ * Makefile.am: Added new GP11 library
+
2008-07-09 Stef Walter <stef@memberwebs.com>
Move all daemon code and sub-modules into daemon/ directory.
diff --git a/HACKING b/HACKING
index 8076c5ad..ab31f11e 100644
--- a/HACKING
+++ b/HACKING
@@ -10,27 +10,30 @@ each other. These parts generally live in different directories:
daemon
The main daemon startup code and gnome-keyring password protocol operations.
-keyrings
+daemon/keyrings
Code that manages the user's password keyrings
+
+daemon/pk
+ General public key / certificate code, management of objects.
+
+daemon/pkcs11
+ The PKCS#11 part of the daemon.
+
+daemon/pkix
+ Nitty gritty handling of various PKCS#?? standards, parsing, ASN.1 stuff.
+
+daemon/ui
+ Prompting the user, asking for passwords.
library
The gnome-keyring library for accessing passwords and secrets.
-pk
- General public key / certificate code, management of objects.
-
pkcs11
The PKCS#11 module, provider and headers.
-
-pkix
- Nitty gritty handling of various PKCS#?? standards, parsing, ASN.1 stuff.
tests
Test tools and unit tests.
-ui
- Prompting the user, asking for passwords.
-
--------------------------------------------------------------------------------
USING 'LOCATIONS' INSTEAD OF FILE PATHS
diff --git a/Makefile.am b/Makefile.am
index 8c1dfd92..38e3c50a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -12,6 +12,7 @@ endif
SUBDIRS = \
. \
+ gp11 \
common \
library \
pkcs11 \
diff --git a/configure.in b/configure.in
index 039875eb..7300d5f9 100644
--- a/configure.in
+++ b/configure.in
@@ -3,6 +3,15 @@ AC_INIT(library/gnome-keyring.h)
AM_INIT_AUTOMAKE(gnome-keyring, 2.22.3)
AM_CONFIG_HEADER(config.h)
+dnl ****************************************************************************
+dnl GP11 library libtool versioning
+
+GP11_MAJOR=0 # Increment for major version number, breaks old apps.
+GP11_REVISION=0 # Increment for internal changes, nothing affected.
+GP11_AGE=0 # Increment for interface that doesn't break anything
+
+dnl ****************************************************************************
+
AM_SANITY_CHECK
AM_MAINTAINER_MODE
@@ -44,6 +53,10 @@ PKG_CHECK_MODULES(GOBJECT, glib-2.0 >= 2.8.0 gobject-2.0 >= 2.8.0)
AC_SUBST(GOBJECT_CFLAGS)
AC_SUBST(GOBJECT_LIBS)
+PKG_CHECK_MODULES(GIO, glib-2.0 >= 2.8.0 gio-2.0)
+AC_SUBST(GIO_CFLAGS)
+AC_SUBST(GIO_LIBS)
+
PKG_CHECK_MODULES(GTK, gtk+-2.0 >= 2.6.0)
AC_SUBST(GTK_CFLAGS)
AC_SUBST(GTK_LIBS)
@@ -80,24 +93,6 @@ else
fi
# --------------------------------------------------------------------
-# Tests and Unit Tests
-
-AC_ARG_ENABLE(tests,
- AC_HELP_STRING([--enable-tests],
- [Build test tools and unit tests]))
-
-if test "$enable_tests" = "yes"; then
- echo "building tests and unit tests"
- AC_DEFINE_UNQUOTED(WITH_TESTS, 1, [Build with unit test support])
- tests_status="yes"
-else
- echo "not building tests and unit tests"
- tests_status="no"
-fi
-
-AM_CONDITIONAL(WITH_TESTS, test "$enable_tests" == "yes")
-
-# --------------------------------------------------------------------
# Check for socklen_t
#
@@ -452,6 +447,47 @@ else
AC_MSG_RESULT(no)
fi
+# --------------------------------------------------------------------
+# Tests and Unit Tests
+
+AC_ARG_ENABLE(tests,
+ AC_HELP_STRING([--enable-tests],
+ [Build test tools and unit tests]))
+
+if test "$enable_tests" == "yes"; then
+ PKG_CHECK_MODULES(CHECK, check >= 0.9, [have_check=yes], [have_check=no])
+ if test "$have_check" == "yes"; then
+ echo "building tests and unit tests"
+ AC_DEFINE_UNQUOTED(WITH_TESTS, 1, [Build with unit test support])
+ tests_status="yes"
+ enable_tests="yes"
+ else
+ echo "The 'check' libraries are missing, cannot build tests"
+ tests_status="missing"
+ enable_tests="no"
+ fi
+else
+ echo "not building tests and unit tests"
+ tests_status="no"
+fi
+
+AM_CONDITIONAL(WITH_TESTS, test "$enable_tests" == "yes")
+
+AC_ARG_ENABLE(coverage,
+ AC_HELP_STRING([--enable-coverage],
+ [Build coverage testing into gnome-keyring]))
+
+if test "$enable_coverage" == "yes"; then
+ CFLAGS="$CFLAGS -fprofile-arcs -ftest-coverage"
+ LDFLAGS="$LDFLAGS -fprofile-arcs -ftest-coverage"
+fi
+
+# ----------------------------------------------------------------------
+
+GP11_LT_RELEASE=$GP11_MAJOR:$GP11_REVISION:$GP11_AGE
+AC_SUBST(GP11_LT_RELEASE)
+AC_SUBST(GP11_MAJOR)
+
AC_SUBST(DAEMON_CFLAGS)
AC_SUBST(DAEMON_LIBS)
@@ -474,6 +510,9 @@ daemon/pkix/tests/Makefile
daemon/ssh/Makefile
daemon/ssh/tests/Makefile
daemon/ui/Makefile
+gp11/gp11.pc
+gp11/Makefile
+gp11/tests/Makefile
library/Makefile
library/tests/Makefile
pam/Makefile
@@ -486,6 +525,9 @@ library/gnome-keyring-1.pc
library/gnome-keyring-1-uninstalled.pc
])
+#
+# gp11/tests/module/Makefile
+
# ------------------------------------------------------------------------------
# Summary
#
diff --git a/daemon/pk/gkr-pk-cert.c b/daemon/pk/gkr-pk-cert.c
index 5e068345..979bf79d 100644
--- a/daemon/pk/gkr-pk-cert.c
+++ b/daemon/pk/gkr-pk-cert.c
@@ -130,7 +130,7 @@ load_certificate (GkrPkCert *cert)
g_quark_to_string (obj->location),
err && err->message ? err->message : "");
g_error_free (err);
- return CKR_GENERAL_ERROR;
+ return CKR_FUNCTION_FAILED;
}
/* This can happen if the user cancels out of a dialog */
@@ -474,7 +474,7 @@ gkr_pk_cert_get_attribute (GkrPkObject* obj, CK_ATTRIBUTE_PTR attr)
res = gkr_pkix_der_read_basic_constraints (data, n_data, &is_ca, NULL);
g_free (data);
if (res != GKR_PKIX_SUCCESS)
- return CKR_GENERAL_ERROR;
+ return CKR_FUNCTION_FAILED;
if (is_ca)
value = 2; /* authority */
}
@@ -505,7 +505,7 @@ gkr_pk_cert_get_attribute (GkrPkObject* obj, CK_ATTRIBUTE_PTR attr)
return ret;
keyid = gkr_pk_cert_get_keyid (cert);
if (!keyid)
- return CKR_GENERAL_ERROR;
+ return CKR_FUNCTION_FAILED;
data = (CK_VOID_PTR)gkr_id_get_raw (keyid, &n_data);
gkr_pk_attribute_set_data (attr, data, n_data);
return CKR_OK;
@@ -517,7 +517,7 @@ gkr_pk_cert_get_attribute (GkrPkObject* obj, CK_ATTRIBUTE_PTR attr)
cdata = gkr_pkix_asn1_read_element (cert->data->asn1, cert->data->raw, cert->data->n_raw,
"tbsCertificate.subject", &n_data);
if (!cdata)
- return CKR_GENERAL_ERROR;
+ return CKR_FUNCTION_FAILED;
gkr_pk_attribute_set_data (attr, cdata, n_data);
return CKR_OK;
@@ -527,7 +527,7 @@ gkr_pk_cert_get_attribute (GkrPkObject* obj, CK_ATTRIBUTE_PTR attr)
cdata = gkr_pkix_asn1_read_element (cert->data->asn1, cert->data->raw, cert->data->n_raw,
"tbsCertificate.issuer", &n_data);
if (!cdata)
- return CKR_GENERAL_ERROR;
+ return CKR_FUNCTION_FAILED;
gkr_pk_attribute_set_data (attr, cdata, n_data);
return CKR_OK;
@@ -536,7 +536,7 @@ gkr_pk_cert_get_attribute (GkrPkObject* obj, CK_ATTRIBUTE_PTR attr)
return ret;
data = gkr_pkix_asn1_read_value (cert->data->asn1, "tbsCertificate.serialNumber", &n_data, NULL);
if (!data)
- return CKR_GENERAL_ERROR;
+ return CKR_FUNCTION_FAILED;
gkr_pk_attribute_set_data (attr, data, n_data);
g_free (data);
return CKR_OK;
@@ -569,7 +569,7 @@ gkr_pk_cert_get_attribute (GkrPkObject* obj, CK_ATTRIBUTE_PTR attr)
"tbsCertificate.validity.notBefore" :
"tbsCertificate.validity.notAfter",
&time))
- return CKR_GENERAL_ERROR;
+ return CKR_FUNCTION_FAILED;
gkr_pk_attribute_set_date (attr, time);
return CKR_OK;
diff --git a/daemon/pk/gkr-pk-import.c b/daemon/pk/gkr-pk-import.c
index 36b0984e..bd6fa9bd 100644
--- a/daemon/pk/gkr-pk-import.c
+++ b/daemon/pk/gkr-pk-import.c
@@ -532,7 +532,7 @@ gkr_pk_import_create (GkrPkManager* manager, GkrPkSession *session,
if (err->domain == GKR_PKIX_PARSE_ERROR)
ret = CKR_DATA_INVALID;
else
- ret = CKR_GENERAL_ERROR;
+ ret = CKR_FUNCTION_FAILED;
g_message ("couldn't import data: %s", err && err->message ? err->message : "");
g_clear_error (&err);
diff --git a/daemon/pk/gkr-pk-object.c b/daemon/pk/gkr-pk-object.c
index 83e38aac..6dfebbf9 100644
--- a/daemon/pk/gkr-pk-object.c
+++ b/daemon/pk/gkr-pk-object.c
@@ -558,12 +558,12 @@ gkr_pk_object_create (GkrPkSession *session,
res = gkr_pk_storage_store (the_storage, *object, &err);
if (!res) {
- g_warning ("couldn't store created object: %s",
+ g_message ("couldn't store created object: %s",
err && err->message ? err->message : "");
g_clear_error (&err);
g_object_unref (*object);
*object = NULL;
- return CKR_GENERAL_ERROR;
+ return CKR_FUNCTION_FAILED;
}
/* Register it with the object manager if necessary */
diff --git a/daemon/pk/gkr-pk-privkey.c b/daemon/pk/gkr-pk-privkey.c
index 62c53bf6..6592253b 100644
--- a/daemon/pk/gkr-pk-privkey.c
+++ b/daemon/pk/gkr-pk-privkey.c
@@ -194,7 +194,7 @@ create_rsa_private (GArray *attrs, gcry_sexp_t *skey)
/* TODO: We should be mapping better return codes */
if (gcry != 0) {
g_message ("couldn't create RSA key from passed attributes");
- ret = CKR_GENERAL_ERROR;
+ ret = CKR_FUNCTION_FAILED;
goto done;
}
@@ -244,7 +244,7 @@ create_dsa_private (GArray *attrs, gcry_sexp_t *skey)
/* TODO: We should be mapping better return codes */
if (gcry != 0) {
g_message ("couldn't create DSA key from passed attributes");
- ret = CKR_GENERAL_ERROR;
+ ret = CKR_FUNCTION_FAILED;
goto done;
}
@@ -300,7 +300,7 @@ attribute_from_public (GkrPkPrivkey *key, CK_ATTRIBUTE_PTR attr)
{
GkrPkPubkey *pub = get_public_key (key, TRUE);
if (pub == NULL)
- return CKR_GENERAL_ERROR;
+ return CKR_FUNCTION_FAILED;
return gkr_pk_object_get_attribute (GKR_PK_OBJECT (pub), attr);
}
@@ -312,7 +312,7 @@ attribute_from_certificate (GkrPkPrivkey *key, CK_ATTRIBUTE_PTR attr)
keyid = gkr_pk_privkey_get_keyid (key);
if (!keyid)
- return CKR_GENERAL_ERROR;
+ return CKR_FUNCTION_FAILED;
obj = GKR_PK_OBJECT (key);
crt = gkr_pk_manager_find_by_id (obj->manager, GKR_TYPE_PK_CERT, keyid);
@@ -334,7 +334,7 @@ extract_key_mpi (GkrPkPrivkey *key, int algorithm, const char *part, CK_ATTRIBUT
/* Load our key */
if (!load_private_key (key))
- return CKR_GENERAL_ERROR;
+ return CKR_FUNCTION_FAILED;
if (key->priv->algorithm != algorithm)
return CKR_ATTRIBUTE_TYPE_INVALID;
@@ -449,7 +449,7 @@ gkr_pk_privkey_get_attribute (GkrPkObject* obj, CK_ATTRIBUTE_PTR attr)
case CKA_ID:
keyid = gkr_pk_privkey_get_keyid (key);
if (!keyid)
- return CKR_GENERAL_ERROR;
+ return CKR_FUNCTION_FAILED;
value = (CK_VOID_PTR)gkr_id_get_raw (keyid, &len);
gkr_pk_attribute_set_data (attr, value, len);
return CKR_OK;
diff --git a/daemon/pk/gkr-pk-pubkey.c b/daemon/pk/gkr-pk-pubkey.c
index 9e6f3edb..f3dc2d56 100644
--- a/daemon/pk/gkr-pk-pubkey.c
+++ b/daemon/pk/gkr-pk-pubkey.c
@@ -148,7 +148,7 @@ create_rsa_public (GArray *attrs, gcry_sexp_t *skey)
/* TODO: We should be mapping better return codes */
if (gcry != 0) {
g_message ("couldn't create RSA key from passed attributes");
- ret = CKR_GENERAL_ERROR;
+ ret = CKR_FUNCTION_FAILED;
goto done;
}
@@ -186,7 +186,7 @@ create_dsa_public (GArray *attrs, gcry_sexp_t *skey)
/* TODO: We should be mapping better return codes */
if (gcry != 0) {
g_message ("couldn't create DSA key from passed attributes");
- ret = CKR_GENERAL_ERROR;
+ ret = CKR_FUNCTION_FAILED;
goto done;
}
@@ -208,13 +208,13 @@ attribute_from_related (GkrPkPubkey *key, GType type, CK_ATTRIBUTE_PTR attr)
GkrPkObject *crt, *obj;
if (!load_public_key (key))
- return CKR_GENERAL_ERROR;
+ return CKR_FUNCTION_FAILED;
obj = GKR_PK_OBJECT (key);
crt = gkr_pk_manager_find_by_id (obj->manager, type, key->pub->keyid);
if (crt == NULL)
- return CKR_GENERAL_ERROR;
+ return CKR_FUNCTION_FAILED;
return gkr_pk_object_get_attribute (crt, attr);
}
@@ -226,7 +226,7 @@ extract_key_mpi (GkrPkPubkey *key, int algorithm, const char *part, CK_ATTRIBUTE
gboolean ret;
if (!load_public_key (key))
- return CKR_GENERAL_ERROR;
+ return CKR_FUNCTION_FAILED;
if (key->pub->algorithm != algorithm)
return CKR_ATTRIBUTE_TYPE_INVALID;
@@ -246,7 +246,7 @@ extract_key_value (GkrPkPubkey *key, CK_ATTRIBUTE_PTR attr)
gsize n_data;
if (!load_public_key (key))
- return CKR_GENERAL_ERROR;
+ return CKR_FUNCTION_FAILED;
switch (gkr_pk_pubkey_get_algorithm (key)) {
case GCRY_PK_RSA:
@@ -346,7 +346,7 @@ gkr_pk_pubkey_get_attribute (GkrPkObject* obj, CK_ATTRIBUTE_PTR attr)
case CKA_KEY_TYPE:
if (!load_public_key (key))
- return CKR_GENERAL_ERROR;
+ return CKR_FUNCTION_FAILED;
switch (key->pub->algorithm) {
case GCRY_PK_RSA:
gkr_pk_attribute_set_ulong (attr, CKK_RSA);
@@ -362,7 +362,7 @@ gkr_pk_pubkey_get_attribute (GkrPkObject* obj, CK_ATTRIBUTE_PTR attr)
case CKA_MODULUS_BITS:
if (!load_public_key (key))
- return CKR_GENERAL_ERROR;
+ return CKR_FUNCTION_FAILED;
if (key->pub->algorithm != GCRY_PK_RSA)
return CKR_ATTRIBUTE_TYPE_INVALID;
g_assert (key->pub->numbers);
@@ -379,7 +379,7 @@ gkr_pk_pubkey_get_attribute (GkrPkObject* obj, CK_ATTRIBUTE_PTR attr)
case CKA_ID:
/* Always a SHA-1 hash output buffer */
if (!load_public_key (key) || !key->pub->keyid)
- return CKR_GENERAL_ERROR;
+ return CKR_FUNCTION_FAILED;
gkr_pk_attribute_set_id (attr, key->pub->keyid);
return CKR_OK;
diff --git a/daemon/pkcs11/gkr-pkcs11-daemon-session.c b/daemon/pkcs11/gkr-pkcs11-daemon-session.c
index 33a44d48..8ec4ee2b 100644
--- a/daemon/pkcs11/gkr-pkcs11-daemon-session.c
+++ b/daemon/pkcs11/gkr-pkcs11-daemon-session.c
@@ -391,7 +391,7 @@ session_C_Login (SessionInfo *sinfo, GkrPkcs11Message *req,
* not accept a PIN, but instead prompt for it.
*/
if (!gkr_keyring_login_unlock (NULL))
- return CKR_GENERAL_ERROR;
+ return CKR_FUNCTION_FAILED;
return CKR_OK;
}
@@ -522,10 +522,10 @@ session_C_DestroyObject (SessionInfo *sinfo, GkrPkcs11Message *req,
g_return_val_if_fail (object->storage, CKR_GENERAL_ERROR);
res = gkr_pk_storage_remove (object->storage, object, &err);
if (!res) {
- g_warning ("couldn't remove object from disk: %s",
+ g_message ("couldn't remove object from disk: %s",
err && err->message ? err->message : "");
g_clear_error (&err);
- ret = CKR_GENERAL_ERROR;
+ ret = CKR_FUNCTION_FAILED;
}
return ret;
diff --git a/daemon/pkcs11/gkr-pkcs11-dsa.c b/daemon/pkcs11/gkr-pkcs11-dsa.c
index c01e5201..a53ebab1 100644
--- a/daemon/pkcs11/gkr-pkcs11-dsa.c
+++ b/daemon/pkcs11/gkr-pkcs11-dsa.c
@@ -47,8 +47,8 @@ object_to_public_key (GkrPkObject *object, gcry_sexp_t *s_key)
*s_key = gkr_pk_pubkey_get_key (key);
if (!*s_key) {
/* TODO: This happens when the user doesn't unlock key, proper code */
- g_warning ("couldn't get public key");
- return CKR_GENERAL_ERROR;
+ g_message ("couldn't get public key");
+ return CKR_FUNCTION_FAILED;
}
return CKR_OK;
@@ -70,8 +70,8 @@ object_to_private_key (GkrPkObject *object, gcry_sexp_t *s_key)
*s_key = gkr_pk_privkey_get_key (key);
if (!*s_key) {
/* TODO: This happens when the user doesn't unlock key, proper code */
- g_warning ("couldn't get private key");
- return CKR_GENERAL_ERROR;
+ g_message ("couldn't get private key");
+ return CKR_FUNCTION_FAILED;
}
return CKR_OK;
@@ -116,8 +116,8 @@ gkr_pkcs11_dsa_sign (GkrPkObject *object, const guchar *plain, gsize n_plain,
/* TODO: Certain codes should be returned (data too big etc... ) */
if (gcry) {
- g_warning ("signing of the data failed: %s", gcry_strerror (gcry));
- return CKR_GENERAL_ERROR;
+ g_message ("signing of the data failed: %s", gcry_strerror (gcry));
+ return CKR_FUNCTION_FAILED;
}
*signature = g_new0 (guchar, 40);
@@ -182,8 +182,8 @@ gkr_pkcs11_dsa_verify (GkrPkObject *object, const guchar *plain, gsize n_plain,
if (gcry_err_code (gcry) == GPG_ERR_BAD_SIGNATURE) {
return CKR_SIGNATURE_INVALID;
} else if (gcry) {
- g_warning ("signing of the data failed: %s", gcry_strerror (gcry));
- return CKR_GENERAL_ERROR;
+ g_message ("signing of the data failed: %s", gcry_strerror (gcry));
+ return CKR_FUNCTION_FAILED;
}
return CKR_OK;
diff --git a/daemon/pkcs11/gkr-pkcs11-rsa.c b/daemon/pkcs11/gkr-pkcs11-rsa.c
index dea8923e..c3d100db 100644
--- a/daemon/pkcs11/gkr-pkcs11-rsa.c
+++ b/daemon/pkcs11/gkr-pkcs11-rsa.c
@@ -46,8 +46,8 @@ object_to_public_key (GkrPkObject *object, gcry_sexp_t *s_key)
*s_key = gkr_pk_pubkey_get_key (key);
if (!*s_key) {
/* TODO: This happens when the user doesn't unlock key, proper code */
- g_warning ("couldn't get public key");
- return CKR_GENERAL_ERROR;
+ g_message ("couldn't get public key");
+ return CKR_FUNCTION_FAILED;
}
return CKR_OK;
@@ -69,8 +69,8 @@ object_to_private_key (GkrPkObject *object, gcry_sexp_t *s_key)
*s_key = gkr_pk_privkey_get_key (key);
if (!*s_key) {
/* TODO: This happens when the user doesn't unlock key, proper code */
- g_warning ("couldn't get private key");
- return CKR_GENERAL_ERROR;
+ g_message ("couldn't get private key");
+ return CKR_FUNCTION_FAILED;
}
return CKR_OK;
@@ -167,8 +167,8 @@ gkr_pkcs11_rsa_encrypt (GkrPkObject *key, GkrCryptoPadding padfunc,
/* TODO: Certain codes should be returned (data too big etc... ) */
if (gcry) {
- g_warning ("encrypting of the data failed: %s", gcry_strerror (gcry));
- return CKR_GENERAL_ERROR;
+ g_message ("encrypting of the data failed: %s", gcry_strerror (gcry));
+ return CKR_FUNCTION_FAILED;
}
/* Now extract and send it back out */
@@ -218,8 +218,8 @@ gkr_crypto_sexp_dump (sdata);
/* TODO: Certain codes should be returned (data too big etc... ) */
if (gcry) {
- g_warning ("decrypting of the data failed: %s", gcry_strerror (gcry));
- return CKR_GENERAL_ERROR;
+ g_message ("decrypting of the data failed: %s", gcry_strerror (gcry));
+ return CKR_FUNCTION_FAILED;
}
gkr_crypto_sexp_dump (splain);
@@ -266,8 +266,8 @@ gkr_pkcs11_rsa_sign (GkrPkObject *object, GkrCryptoPadding padfunc,
/* TODO: Certain codes should be returned (data too big etc... ) */
if (gcry) {
- g_warning ("signing of the data failed: %s", gcry_strerror (gcry));
- return CKR_GENERAL_ERROR;
+ g_message ("signing of the data failed: %s", gcry_strerror (gcry));
+ return CKR_FUNCTION_FAILED;
}
/* Now extract and send it back out */
@@ -326,8 +326,8 @@ gkr_pkcs11_rsa_verify (GkrPkObject *object, GkrCryptoPadding padfunc,
if (gcry_err_code (gcry) == GPG_ERR_BAD_SIGNATURE) {
return CKR_SIGNATURE_INVALID;
} else if (gcry) {
- g_warning ("signing of the data failed: %s", gcry_strerror (gcry));
- return CKR_GENERAL_ERROR;
+ g_message ("signing of the data failed: %s", gcry_strerror (gcry));
+ return CKR_FUNCTION_FAILED;
}
return CKR_OK;
diff --git a/gp11/Makefile.am b/gp11/Makefile.am
new file mode 100644
index 00000000..1dd8ec66
--- /dev/null
+++ b/gp11/Makefile.am
@@ -0,0 +1,52 @@
+incdir = $(includedir)/gp11
+
+inc_HEADERS = \
+ gp11.h \
+ pkcs11.h
+
+INCLUDES = \
+ -I$(top_builddir) \
+ -I$(top_srcdir) \
+ $(GOBJECT_CFLAGS) \
+ $(GTHREAD_CFLAGS) \
+ $(GLIB_CFLAGS)
+
+lib_LTLIBRARIES = libgp11.la
+
+libgp11_la_SOURCES = \
+ gp11.h gp11-private.h \
+ gp11-attributes.c \
+ gp11-call.c \
+ gp11-misc.c \
+ gp11-module.c \
+ gp11-object.c \
+ gp11-session.c \
+ gp11-slot.c
+
+libgp11_la_LDFLAGS = \
+ -version-info $(GP11_LT_RELEASE) \
+ -no-undefined -export-symbols-regex 'gp11_*'
+
+libgp11_la_LIBADD = \
+ $(GOBJECT_LIBS) \
+ $(GTHREAD_LIBS) \
+ $(GIO_LIBS) \
+ $(GLIB_LIBS)
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = gp11-$(GP11_MAJOR).pc
+
+EXTRA_DIST = \
+ gp11.pc.in
+
+gp11-$(GP11_MAJOR).pc: gp11.pc
+ cp gp11.pc gp11-$(GP11_MAJOR).pc
+
+if WITH_TESTS
+TESTS_DIR = tests
+else
+TESTS_DIR =
+endif
+
+SUBDIRS = . $(TESTS_DIR)
+ \ No newline at end of file
diff --git a/gp11/gp11-attributes.c b/gp11/gp11-attributes.c
new file mode 100644
index 00000000..bdda1b4a
--- /dev/null
+++ b/gp11/gp11-attributes.c
@@ -0,0 +1,508 @@
+
+#include "config.h"
+
+#include "gp11.h"
+#include "gp11-private.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+void
+gp11_attribute_init (GP11Attribute *attr, guint attr_type,
+ gconstpointer value, gsize length)
+{
+ g_assert (sizeof (GP11Attribute) == sizeof (CK_ATTRIBUTE));
+ memset (attr, 0, sizeof (GP11Attribute));
+ attr->type = attr_type;
+ attr->length = length;
+ attr->value = value && length ? g_memdup (value, length) : NULL;
+}
+
+void
+_gp11_attribute_init_take (GP11Attribute *attr, guint attr_type,
+ gpointer value, gsize length)
+{
+ g_assert (sizeof (GP11Attribute) == sizeof (CK_ATTRIBUTE));
+ memset (attr, 0, sizeof (GP11Attribute));
+ attr->type = attr_type;
+ attr->length = length;
+ attr->value = value && length ? value : NULL;
+}
+
+void
+gp11_attribute_init_boolean (GP11Attribute *attr, guint attr_type,
+ gboolean value)
+{
+ CK_BBOOL bvalue = value ? CK_TRUE : CK_FALSE;
+ gp11_attribute_init (attr, attr_type, &bvalue, sizeof (bvalue));
+}
+
+void
+gp11_attribute_init_date (GP11Attribute *attr, guint attr_type,
+ const GDate *value)
+{
+ gchar buffer[9];
+ CK_DATE date;
+ g_return_if_fail (value);
+ g_snprintf (buffer, sizeof (buffer), "%04d%02d%02d",
+ (int)g_date_get_year (value),
+ (int)g_date_get_month (value),
+ (int)g_date_get_day (value));
+ memcpy (&date.year, buffer + 0, 4);
+ memcpy (&date.month, buffer + 4, 2);
+ memcpy (&date.day, buffer + 6, 2);
+ gp11_attribute_init (attr, attr_type, &date, sizeof (CK_DATE));
+}
+
+void
+gp11_attribute_init_ulong (GP11Attribute *attr, guint attr_type,
+ gulong value)
+{
+ CK_ULONG uvalue = value;
+ gp11_attribute_init (attr, attr_type, &uvalue, sizeof (uvalue));
+}
+
+void
+gp11_attribute_init_string (GP11Attribute *attr, guint attr_type,
+ const gchar *value)
+{
+ gsize len = value ? strlen (value) : 0;
+ gp11_attribute_init (attr, attr_type, (gpointer)value, len);
+}
+
+
+GP11Attribute*
+gp11_attribute_new (guint attr_type, gpointer value, gsize length)
+{
+ GP11Attribute *attr = g_slice_new0 (GP11Attribute);
+ gp11_attribute_init (attr, attr_type, value, length);
+ return attr;
+}
+
+GP11Attribute*
+gp11_attribute_new_boolean (guint attr_type, gboolean value)
+{
+ GP11Attribute *attr = g_slice_new0 (GP11Attribute);
+ gp11_attribute_init_boolean (attr, attr_type, value);
+ return attr;
+}
+
+GP11Attribute*
+gp11_attribute_new_date (guint attr_type, const GDate *value)
+{
+ GP11Attribute *attr = g_slice_new0 (GP11Attribute);
+ gp11_attribute_init_date (attr, attr_type, value);
+ return attr;
+}
+
+GP11Attribute*
+gp11_attribute_new_ulong (guint attr_type, gulong value)
+{
+ GP11Attribute *attr = g_slice_new0 (GP11Attribute);
+ gp11_attribute_init_ulong (attr, attr_type, value);
+ return attr;
+}
+
+GP11Attribute*
+gp11_attribute_new_string (guint attr_type, const gchar *value)
+{
+ GP11Attribute *attr = g_slice_new0 (GP11Attribute);
+ gp11_attribute_init_string (attr, attr_type, value);
+ return attr;
+}
+
+gboolean
+gp11_attribute_get_boolean (GP11Attribute *attr)
+{
+ g_return_val_if_fail (attr, FALSE);
+ g_return_val_if_fail (attr->length == sizeof (CK_BBOOL), FALSE);
+ g_return_val_if_fail (attr->value, FALSE);
+ return *((CK_BBOOL*)attr->value) == CK_TRUE ? TRUE : FALSE;
+}
+
+gulong
+gp11_attribute_get_ulong (GP11Attribute *attr)
+{
+ g_return_val_if_fail (attr, FALSE);
+ g_return_val_if_fail (attr->length == sizeof (CK_ULONG), (gulong)-1);
+ g_return_val_if_fail (attr->value, (gulong)-1);
+ return *((CK_ULONG*)attr->value);
+}
+
+gchar*
+gp11_attribute_get_string (GP11Attribute *attr)
+{
+ g_return_val_if_fail (attr, NULL);
+
+ if (!attr->value)
+ return NULL;
+
+ return g_strndup (attr->value, attr->length);
+}
+
+GDate*
+gp11_attribute_get_date (GP11Attribute *attr)
+{
+ guint year, month, day;
+ gchar buffer[5];
+ CK_DATE *date;
+ gchar *end;
+
+ g_return_val_if_fail (attr, NULL);
+ g_return_val_if_fail (attr->length == sizeof (CK_DATE), NULL);
+ g_return_val_if_fail (attr->value, NULL);
+ date = (CK_DATE*)attr->value;
+
+ memset (&buffer, 0, sizeof (buffer));
+ memcpy (buffer, date->year, 4);
+ year = strtol (buffer, &end, 10);
+ g_return_val_if_fail (end != buffer && !*end, NULL);
+
+ memset (&buffer, 0, sizeof (buffer));
+ memcpy (buffer, date->month, 2);
+ month = strtol (buffer, &end, 10);
+ g_return_val_if_fail (end != buffer && !*end, NULL);
+
+ memset (&buffer, 0, sizeof (buffer));
+ memcpy (buffer, date->day, 2);
+ day = strtol (buffer, &end, 10);
+ g_return_val_if_fail (end != buffer && !*end, NULL);
+
+ return g_date_new_dmy (day, month, year);
+}
+
+GP11Attribute*
+gp11_attribute_dup (GP11Attribute *attr)
+{
+ GP11Attribute *copy;
+
+ if (!attr)
+ return NULL;
+
+ copy = g_slice_new0 (GP11Attribute);
+ gp11_attribute_init_copy (copy, attr);
+ return copy;
+}
+
+void
+gp11_attribute_init_copy (GP11Attribute *dest, GP11Attribute *src)
+{
+ g_return_if_fail (dest);
+ g_return_if_fail (src);
+
+ /*
+ * TODO: Handle stupid, dumb, broken, special cases like
+ * CKA_WRAP_TEMPLATE and CKA_UNWRAP_TEMPLATE.
+ */
+
+ memcpy (dest, src, sizeof (GP11Attribute));
+ dest->value = src->value && src->length ? g_memdup (src->value, src->length) : NULL;
+}
+
+void
+gp11_attribute_clear (GP11Attribute *attr)
+{
+ g_return_if_fail (attr);
+ g_free (attr->value);
+ memset (attr, 0, sizeof (GP11Attribute));
+}
+
+void
+gp11_attribute_free (GP11Attribute *attr)
+{
+ if (attr) {
+ gp11_attribute_clear (attr);
+ g_slice_free (GP11Attribute, attr);
+ }
+}
+
+struct _GP11Attributes {
+ GArray *array;
+ gint immutable;
+ gint refs;
+};
+
+GP11Attributes*
+gp11_attributes_new (void)
+{
+ GP11Attributes *attrs;
+
+ g_assert (sizeof (GP11Attribute) == sizeof (CK_ATTRIBUTE));
+ attrs = g_slice_new0 (GP11Attributes);
+ attrs->array = g_array_new (0, 1, sizeof (GP11Attribute));
+ attrs->refs = 1;
+ attrs->immutable = 0;
+ return attrs;
+}
+
+static GP11Attributes*
+initialize_from_valist (guint type, va_list va)
+{
+ GP11Attributes *attrs;
+ gssize length;
+ gpointer value;
+
+ attrs = gp11_attributes_new ();
+
+ /* No attributes */
+ if (type == (guint)-1)
+ return attrs;
+
+ do {
+ length = va_arg (va, gssize);
+
+ /* All the different set types */
+ switch (length) {
+ case GP11_BOOLEAN:
+ gp11_attributes_add_boolean (attrs, type, va_arg (va, gboolean));
+ break;
+ case GP11_ULONG:
+ gp11_attributes_add_ulong (attrs, type, va_arg (va, gulong));
+ break;
+ case GP11_STRING:
+ gp11_attributes_add_string (attrs, type, va_arg (va, const gchar*));
+ break;
+ case GP11_DATE:
+ gp11_attributes_add_date (attrs, type, va_arg (va, const GDate*));
+ break;
+
+ /* Otherwise it should be data */
+ default:
+ value = va_arg (va, gpointer);
+
+ /* But not this long */
+ if (length < 0 || length >= G_MAXSSIZE)
+ g_warning ("length passed to attributes varargs is invalid or too large: %d", length);
+ else
+ gp11_attributes_add_data (attrs, type, value, length);
+ break;
+ };
+
+ type = va_arg (va, guint);
+
+ } while (type != (guint)-1);
+
+ return attrs;
+}
+
+GP11Attributes*
+gp11_attributes_newv (guint first_type, ...)
+{
+ GP11Attributes *attrs;
+ va_list va;
+
+ va_start (va, first_type);
+ attrs = initialize_from_valist (first_type, va);
+ va_end (va);
+
+ return attrs;
+}
+
+GP11Attributes*
+gp11_attributes_new_valist (va_list va)
+{
+ guint type = va_arg (va, guint);
+ return initialize_from_valist (type, va);
+}
+
+GP11Attribute*
+gp11_attributes_at (GP11Attributes *attrs, guint index)
+{
+ g_return_val_if_fail (attrs && attrs->array, NULL);
+ g_return_val_if_fail (index < attrs->array->len, NULL);
+ g_return_val_if_fail (g_atomic_int_get (&attrs->immutable) == 0, NULL);
+ return &g_array_index (attrs->array, GP11Attribute, index);
+}
+
+CK_ATTRIBUTE_PTR
+_gp11_attributes_raw (GP11Attributes *attrs)
+{
+ g_return_val_if_fail (attrs && attrs->array, NULL);
+ return (CK_ATTRIBUTE_PTR)attrs->array->data;
+}
+
+static GP11Attribute*
+attributes_push (GP11Attributes *attrs)
+{
+ GP11Attribute attr;
+ g_assert (g_atomic_int_get (&attrs->immutable) == 0);
+
+ memset (&attr, 0, sizeof (attr));
+ g_array_append_val (attrs->array, attr);
+ return &g_array_index (attrs->array, GP11Attribute, attrs->array->len - 1);
+}
+
+void
+gp11_attributes_add (GP11Attributes *attrs, GP11Attribute *attr)
+{
+ GP11Attribute *added;
+ g_return_if_fail (attrs && attrs->array);
+ g_return_if_fail (g_atomic_int_get (&attrs->immutable) == 0);
+ g_return_if_fail (attr);
+ added = attributes_push (attrs);
+ gp11_attribute_init_copy (added, attr);
+}
+
+void
+_gp11_attributes_add_take (GP11Attributes *attrs, guint attr_type,
+ gpointer value, gsize length)
+{
+ GP11Attribute *added;
+ g_return_if_fail (attrs);
+ g_return_if_fail (g_atomic_int_get (&attrs->immutable) == 0);
+ added = attributes_push (attrs);
+ _gp11_attribute_init_take (added, attr_type, (gpointer)value, length);
+}
+
+void
+gp11_attributes_add_data (GP11Attributes *attrs, guint attr_type,
+ gconstpointer value, gsize length)
+{
+ GP11Attribute *added;
+ g_return_if_fail (attrs);
+ g_return_if_fail (g_atomic_int_get (&attrs->immutable) == 0);
+ added = attributes_push (attrs);
+ gp11_attribute_init (added, attr_type, value, length);
+}
+
+void
+gp11_attributes_add_boolean (GP11Attributes *attrs, guint attr_type, gboolean value)
+{
+ GP11Attribute *added;
+ g_return_if_fail (attrs);
+ g_return_if_fail (g_atomic_int_get (&attrs->immutable) == 0);
+ added = attributes_push (attrs);
+ gp11_attribute_init_boolean (added, attr_type, value);
+}
+
+void
+gp11_attributes_add_string (GP11Attributes *attrs, guint attr_type, const gchar *value)
+{
+ GP11Attribute *added;
+ g_return_if_fail (attrs);
+ g_return_if_fail (g_atomic_int_get (&attrs->immutable) == 0);
+ added = attributes_push (attrs);
+ gp11_attribute_init_string (added, attr_type, value);
+}
+
+void
+gp11_attributes_add_date (GP11Attributes *attrs, guint attr_type, const GDate *value)
+{
+ GP11Attribute *added;
+ g_return_if_fail (attrs);
+ g_return_if_fail (g_atomic_int_get (&attrs->immutable) == 0);
+ added = attributes_push (attrs);
+ gp11_attribute_init_date (added, attr_type, value);
+}
+
+void
+gp11_attributes_add_ulong (GP11Attributes *attrs, guint attr_type, gulong value)
+{
+ GP11Attribute *added;
+ g_return_if_fail (attrs);
+ g_return_if_fail (g_atomic_int_get (&attrs->immutable) == 0);
+ added = attributes_push (attrs);
+ gp11_attribute_init_ulong (added, attr_type, value);
+}
+
+gulong
+gp11_attributes_count (GP11Attributes *attrs)
+{
+ g_return_val_if_fail (attrs, 0);
+ return attrs->array->len;
+}
+
+
+GP11Attribute*
+gp11_attributes_find (GP11Attributes *attrs, guint attr_type)
+{
+ GP11Attribute *attr;
+ guint i;
+
+ g_return_val_if_fail (attrs && attrs->array, NULL);
+
+ for (i = 0; i < attrs->array->len; ++i) {
+ attr = gp11_attributes_at (attrs, i);
+ if (attr->type == attr_type)
+ return attr;
+ }
+
+ return NULL;
+}
+
+gboolean
+gp11_attributes_find_boolean (GP11Attributes *attrs, guint attr_type, gboolean *value)
+{
+ GP11Attribute *attr;
+ g_return_val_if_fail (value, FALSE);
+
+ attr = gp11_attributes_find (attrs, attr_type);
+ if (!attr)
+ return FALSE;
+ *value = gp11_attribute_get_boolean (attr);
+ return TRUE;
+}
+
+gboolean
+gp11_attributes_find_ulong (GP11Attributes *attrs, guint attr_type, gulong *value)
+{
+ GP11Attribute *attr;
+ g_return_val_if_fail (value, FALSE);
+
+ attr = gp11_attributes_find (attrs, attr_type);
+ if (!attr)
+ return FALSE;
+ *value = gp11_attribute_get_ulong (attr);
+ return TRUE;
+}
+
+gboolean
+gp11_attributes_find_string (GP11Attributes *attrs, guint attr_type, gchar **value)
+{
+ GP11Attribute *attr;
+ g_return_val_if_fail (value, FALSE);
+
+ attr = gp11_attributes_find (attrs, attr_type);
+ if (!attr)
+ return FALSE;
+ *value = gp11_attribute_get_string (attr);
+ return TRUE;
+}
+
+gboolean
+gp11_attributes_find_date (GP11Attributes *attrs, guint attr_type, GDate **value)
+{
+ GP11Attribute *attr;
+ g_return_val_if_fail (value, FALSE);
+
+ attr = gp11_attributes_find (attrs, attr_type);
+ if (!attr)
+ return FALSE;
+ *value = gp11_attribute_get_date (attr);
+ return TRUE;
+}
+
+void
+gp11_attributes_ref (GP11Attributes *attrs)
+{
+ g_return_if_fail (attrs);
+ g_atomic_int_inc (&attrs->refs);
+}
+
+void
+gp11_attributes_unref (GP11Attributes *attrs)
+{
+ guint i;
+
+ if (!attrs)
+ return;
+
+ if (g_atomic_int_dec_and_test (&attrs->refs)) {
+ g_return_if_fail (attrs->array);
+ for (i = 0; i < attrs->array->len; ++i)
+ gp11_attribute_clear (gp11_attributes_at (attrs, i));
+ g_array_free (attrs->array, TRUE);
+ attrs->array = NULL;
+ g_slice_free (GP11Attributes, attrs);
+ }
+}
diff --git a/gp11/gp11-call.c b/gp11/gp11-call.c
new file mode 100644
index 00000000..8ab55095
--- /dev/null
+++ b/gp11/gp11-call.c
@@ -0,0 +1,341 @@
+
+#include "gp11-private.h"
+
+
+static GThreadPool *thread_pool = NULL;
+static GAsyncQueue *completed_queue = NULL;
+static guint completed_id = 0;
+
+static void _gp11_call_implement_async_result (GAsyncResultIface *iface);
+
+G_DEFINE_TYPE_EXTENDED (GP11Call, _gp11_call, G_TYPE_OBJECT, 0,
+ G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_RESULT, _gp11_call_implement_async_result));
+
+/* ----------------------------------------------------------------------------
+ * HELPER FUNCTIONS
+ */
+
+static CK_RV
+perform_call (GP11CallFunc func, GCancellable *cancellable, GP11Arguments *args)
+{
+ CK_RV rv;
+
+ /* Double check a few things */
+ g_assert (func);
+ g_assert (args);
+
+ if (cancellable) {
+ if (g_cancellable_is_cancelled (cancellable)) {
+ return CKR_FUNCTION_CANCELED;
+ }
+
+ /* Push for the notify callback */
+ g_object_ref (cancellable);
+ g_cancellable_push_current (cancellable);
+ }
+
+ rv = (func) (args);
+
+ if (cancellable) {
+ g_cancellable_pop_current (cancellable);
+ g_object_unref (cancellable);
+ }
+
+ return rv;
+}
+
+static void
+process_async_call (gpointer data, gpointer unused)
+{
+ GP11Call *call = GP11_CALL (data);
+ g_assert (GP11_IS_CALL (call));
+
+ g_assert (call->rv == CKR_OK);
+
+ call->rv = perform_call (call->func, call->cancellable,
+ call->args);
+
+ g_async_queue_push (completed_queue, call);
+
+ /* Wakeup main thread if on a separate thread */
+ g_main_context_wakeup (NULL);
+}
+static void
+process_result (GP11Call *call, gpointer unused)
+{
+ /* Double check a few things */
+ g_assert (GP11_IS_CALL (call));
+
+ if (call->cancellable) {
+ /* Don't call the callback when cancelled */
+ if (g_cancellable_is_cancelled (call->cancellable))
+ return;
+ }
+
+ if (call->callback) {
+ g_assert (G_IS_OBJECT (call->object));
+ (call->callback) (G_OBJECT (call->object), G_ASYNC_RESULT (call),
+ call->user_data);
+ }
+}
+
+static gboolean
+completed_prepare(GSource* source, gint *timeout)
+{
+ gboolean have;
+ g_assert (completed_queue);
+ have = g_async_queue_length (completed_queue) > 0;
+ *timeout = have ? 0 : -1;
+ return have;
+}
+
+static gboolean
+completed_check(GSource* source)
+{
+ g_assert (completed_queue);
+ return g_async_queue_length (completed_queue) > 0;
+}
+
+static gboolean
+completed_dispatch(GSource* source, GSourceFunc callback, gpointer user_data)
+{
+ gpointer *call;
+
+ g_assert (completed_queue);
+ g_assert (callback);
+
+ call = g_async_queue_try_pop (completed_queue);
+ if (call) {
+ ((GFunc)callback) (call, user_data);
+ g_object_unref (call);
+ }
+
+ return TRUE;
+}
+
+static void
+completed_finalize(GSource* source)
+{
+
+}
+
+static GSourceFuncs completed_functions = {
+ completed_prepare,
+ completed_check,
+ completed_dispatch,
+ completed_finalize
+};
+
+/* ----------------------------------------------------------------------------
+ * OBJECT
+ */
+
+static void
+_gp11_call_init (GP11Call *call)
+{
+ call->rv = CKR_OK;
+}
+
+static void
+_gp11_call_finalize (GObject *obj)
+{
+ GP11Call *call = GP11_CALL (obj);
+
+ if (call->object)
+ g_object_unref (call->object);
+ call->object = NULL;
+
+ if (call->cancellable)
+ g_object_unref (call->cancellable);
+ call->cancellable = NULL;
+
+ if (call->destroy)
+ (call->destroy) (call->args);
+ call->destroy = NULL;
+ call->args = NULL;
+
+ G_OBJECT_CLASS (_gp11_call_parent_class)->finalize (obj);
+}
+
+static gpointer
+_gp11_call_get_user_data (GAsyncResult *async_result)
+{
+ g_return_val_if_fail (GP11_IS_CALL (async_result), NULL);
+ return GP11_CALL (async_result)->user_data;
+}
+
+static GObject*
+_gp11_call_get_source_object (GAsyncResult *async_result)
+{
+ g_return_val_if_fail (GP11_IS_CALL (async_result), NULL);
+ return GP11_CALL (async_result)->object;
+}
+
+static void
+_gp11_call_implement_async_result (GAsyncResultIface *iface)
+{
+ iface->get_user_data = _gp11_call_get_user_data;
+ iface->get_source_object = _gp11_call_get_source_object;
+}
+
+static void
+_gp11_call_class_init (GP11CallClass *klass)
+{
+ GObjectClass *gobject_class = (GObjectClass*)klass;
+ GMainContext *context;
+ GError *err = NULL;
+ GSource *src;
+
+ _gp11_call_parent_class = g_type_class_peek_parent (klass);
+ gobject_class->finalize = _gp11_call_finalize;
+
+ g_assert (!thread_pool);
+ thread_pool = g_thread_pool_new ((GFunc)process_async_call, NULL, -1, FALSE, &err);
+ if (!thread_pool) {
+ g_critical ("couldn't create thread pool: %s",
+ err && err->message ? err->message : "");
+ return;
+ }
+
+ g_assert (!completed_queue);
+ completed_queue = g_async_queue_new_full (g_object_unref);
+ g_assert (completed_queue);
+
+ context = g_main_context_default ();
+ g_assert (context);
+
+ /* Add our idle handler which processes other tasks */
+ g_assert (!completed_id);
+ src = g_source_new (&completed_functions, sizeof (GSource));
+ completed_id = g_source_attach (src, context);
+ g_source_set_callback (src, (GSourceFunc)process_result, NULL, NULL);
+ g_source_unref (src);
+}
+
+/* ----------------------------------------------------------------------------
+ * PUBLIC
+ */
+
+void
+_gp11_call_uninitialize (void)
+{
+ GMainContext *context;
+ GSource *src;
+
+ if (thread_pool) {
+ g_thread_pool_free (thread_pool, FALSE, TRUE);
+ thread_pool = NULL;
+ }
+
+ if (completed_id) {
+ context = g_main_context_default ();
+ g_return_if_fail (context);
+
+ src = g_main_context_find_source_by_id (context, completed_id);
+ g_assert (src);
+ g_source_destroy (src);
+ completed_id = 0;
+ }
+ if (completed_queue) {
+ g_async_queue_unref (completed_queue);
+ completed_queue = NULL;
+ }
+}
+
+gboolean
+_gp11_call_sync (gpointer object, gpointer func, gpointer data,
+ GCancellable *cancellable, GError **err)
+{
+ GP11Arguments *args = (GP11Arguments*)data;
+ GP11Module *module;
+ CK_RV rv;
+
+ g_assert (G_IS_OBJECT (object));
+ g_assert (func);
+ g_assert (args);
+
+ g_object_get (object, "module", &module, "handle", &args->handle, NULL);
+ g_assert (GP11_IS_MODULE (module));
+
+ args->pkcs11 = module->funcs;
+ g_object_unref (module);
+
+ rv = perform_call ((GP11CallFunc)func, cancellable, args);
+ if (rv == CKR_OK)
+ return TRUE;
+
+ g_set_error (err, GP11_ERROR, rv, gp11_message_from_rv (rv));
+ return FALSE;
+}
+
+gpointer
+_gp11_call_async_prep (gpointer object, gpointer func, gsize args_size, gpointer destroy)
+{
+ GP11Arguments *args;
+ GP11Module *module;
+ GP11Call *call;
+
+ g_assert (G_IS_OBJECT (object));
+ g_assert (func);
+
+ if (!destroy)
+ destroy = g_free;
+
+ if (args_size == 0)
+ args_size = sizeof (GP11Arguments);
+ g_assert (args_size >= sizeof (GP11Arguments));
+
+ args = g_malloc0 (args_size);
+ g_object_get (object, "module", &module, "handle", &args->handle, NULL);
+ g_assert (GP11_IS_MODULE (module));
+ args->pkcs11 = module->funcs;
+ g_object_unref (module);
+
+ call = g_object_new (GP11_TYPE_CALL, NULL);
+ call->destroy = (GDestroyNotify)destroy;
+ call->func = (GP11CallFunc)func;
+ call->object = object;
+ g_object_ref (object);
+
+ /* Hook the two together */
+ call->args = args;
+ call->args->call = call;
+
+ return args;
+}
+
+void
+_gp11_call_async_go (gpointer data, GCancellable *cancellable,
+ GAsyncReadyCallback callback, gpointer user_data)
+{
+ GP11Arguments *args = (GP11Arguments*)data;
+
+ g_assert (GP11_IS_CALL (args->call));
+
+ args->call->cancellable = cancellable;
+ if (cancellable) {
+ g_assert (G_IS_CANCELLABLE (cancellable));
+ g_object_ref (cancellable);
+ }
+
+ args->call->callback = callback;
+ args->call->user_data = user_data;
+
+ g_assert (thread_pool);
+ g_thread_pool_push (thread_pool, args->call, NULL);
+}
+
+gboolean
+_gp11_call_basic_finish (gpointer object, GAsyncResult *result, GError **err)
+{
+ CK_RV rv;
+
+ g_return_val_if_fail (GP11_IS_CALL (result), FALSE);
+
+ rv = GP11_CALL (result)->rv;
+ if (rv == CKR_OK)
+ return TRUE;
+
+ g_set_error (err, GP11_ERROR, rv, gp11_message_from_rv (rv));
+ return FALSE;
+}
diff --git a/gp11/gp11-misc.c b/gp11/gp11-misc.c
new file mode 100644
index 00000000..4f0a243f
--- /dev/null
+++ b/gp11/gp11-misc.c
@@ -0,0 +1,218 @@
+
+#include "gp11.h"
+
+#include <glib/gi18n.h>
+
+GQuark
+gp11_get_error_quark (void)
+{
+ static GQuark domain = 0;
+ if (domain == 0)
+ domain = g_quark_from_static_string ("gp11-error");
+ return domain;
+}
+
+void
+gp11_list_unref_free (GList *reflist)
+{
+ GList *l;
+ for (l = reflist; l; l = g_list_next (l)) {
+ g_return_if_fail (G_IS_OBJECT (l->data));
+ g_object_unref (l->data);
+ }
+ g_list_free (reflist);
+}
+
+const gchar*
+gp11_message_from_rv (CK_RV rv)
+{
+ switch (rv) {
+
+ /* These are not really errors, or not current */
+ case CKR_OK:
+ case CKR_NO_EVENT:
+ case CKR_FUNCTION_NOT_PARALLEL:
+ case CKR_SESSION_PARALLEL_NOT_SUPPORTED:
+ g_return_val_if_reached ("");
+
+ case CKR_CANCEL:
+ case CKR_FUNCTION_CANCELED:
+ return _("The operation was cancelled");
+
+ case CKR_HOST_MEMORY:
+ return _("Insufficient memory available");
+ case CKR_SLOT_ID_INVALID:
+ return _("The specified slot ID is not valid");
+ case CKR_GENERAL_ERROR:
+ return _("Internal error");
+ case CKR_FUNCTION_FAILED:
+ return _("The operation failed");
+ case CKR_ARGUMENTS_BAD:
+ return _("Invalid arguments");
+ case CKR_NEED_TO_CREATE_THREADS:
+ return _("The module cannot created needed threads");
+ case CKR_CANT_LOCK:
+ return _("The module cannot lock data properly");
+ case CKR_ATTRIBUTE_READ_ONLY:
+ return _("The field is read-only");
+ case CKR_ATTRIBUTE_SENSITIVE:
+ return _("The field is sensitive and cannot be revealed");
+ case CKR_ATTRIBUTE_TYPE_INVALID:
+ return _("The field is invalid or does not exist");
+ case CKR_ATTRIBUTE_VALUE_INVALID:
+ return _("Invalid value for field");
+ case CKR_DATA_INVALID:
+ return _("The data is not valid or unrecognized");
+ case CKR_DATA_LEN_RANGE:
+ return _("The data is too long");
+ case CKR_DEVICE_ERROR:
+ return _("An error occurred on the device");
+ case CKR_DEVICE_MEMORY:
+ return _("Insufficient memory available on device");
+ case CKR_DEVICE_REMOVED:
+ return _("The device was removed or unplugged");
+ case CKR_ENCRYPTED_DATA_INVALID:
+ return _("The encrypted data is not valid or unrecognized");
+ case CKR_ENCRYPTED_DATA_LEN_RANGE:
+ return _("The encrypted data is too long");
+ case CKR_FUNCTION_NOT_SUPPORTED:
+ return _("This operation is not supported");
+ case CKR_KEY_HANDLE_INVALID:
+ return _("The key is missing or invalid");
+ case CKR_KEY_SIZE_RANGE:
+ return _("The key is the wrong size");
+ case CKR_KEY_TYPE_INCONSISTENT:
+ return _("The key is of the wrong type");
+ case CKR_KEY_NOT_NEEDED:
+ return _("No key is needed");
+ case CKR_KEY_CHANGED:
+ return _("The key is different than before");
+ case CKR_KEY_NEEDED:
+ return _("A key is needed");
+ case CKR_KEY_INDIGESTIBLE:
+ return _("Cannot include the key in digest");
+ case CKR_KEY_FUNCTION_NOT_PERMITTED:
+ return _("This operation cannot be done with this key");
+ case CKR_KEY_NOT_WRAPPABLE:
+ return _("The key cannot be wrapped");
+ case CKR_KEY_UNEXTRACTABLE:
+ return _("Cannot export this key");
+ case CKR_MECHANISM_INVALID:
+ return _("The crypto mechanism is invalid or unrecognized");
+ case CKR_MECHANISM_PARAM_INVALID:
+ return _("The crypto mechanism has an invalid argument");
+ case CKR_OBJECT_HANDLE_INVALID:
+ return _("The object is missing or invalid");
+ case CKR_OPERATION_ACTIVE:
+ return _("Another operation is already taking place");
+ case CKR_OPERATION_NOT_INITIALIZED:
+ return _("No operation is taking place");
+ case CKR_PIN_INCORRECT:
+ return _("The password or PIN is incorrect");
+ case CKR_PIN_INVALID:
+ return _("The password or PIN is invalid");
+ case CKR_PIN_LEN_RANGE:
+ return _("The password or PIN is of an invalid length");
+ case CKR_PIN_EXPIRED:
+ return _("The password or PIN has expired");
+ case CKR_PIN_LOCKED:
+ return _("The password or PIN is locked");
+ case CKR_SESSION_CLOSED:
+ return _("The session is closed");
+ case CKR_SESSION_COUNT:
+ return _("Too many sessions are active");
+ case CKR_SESSION_HANDLE_INVALID:
+ return _("The session is invalid");
+ case CKR_SESSION_READ_ONLY:
+ return _("The session is read-only");
+ case CKR_SESSION_EXISTS:
+ return _("An open session exists");
+ case CKR_SESSION_READ_ONLY_EXISTS:
+ return _("A read-only session exists");
+ case CKR_SESSION_READ_WRITE_SO_EXISTS:
+ return _("An administrator session exists");
+ case CKR_SIGNATURE_INVALID:
+ return _("The signature is bad or corrupted");
+ case CKR_SIGNATURE_LEN_RANGE:
+ return _("The signature is unrecognized or corrupted");
+ case CKR_TEMPLATE_INCOMPLETE:
+ return _("Certain required fields are missing");
+ case CKR_TEMPLATE_INCONSISTENT:
+ return _("Certain fields have invalid values");
+ case CKR_TOKEN_NOT_PRESENT:
+ return _("The device is not present or unplugged");
+ case CKR_TOKEN_NOT_RECOGNIZED:
+ return _("The device is invalid or unregocnizable");
+ case CKR_TOKEN_WRITE_PROTECTED:
+ return _("The device is write protected");
+ case CKR_UNWRAPPING_KEY_HANDLE_INVALID:
+ return _("Cannot import because the key is invalid");
+ case CKR_UNWRAPPING_KEY_SIZE_RANGE:
+ return _("Cannot import because the key is of the wrong size");
+ case CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT:
+ return _("Cannot import because the key is of the wrong type");
+ case CKR_USER_ALREADY_LOGGED_IN:
+ return _("You are already logged in");
+ case CKR_USER_NOT_LOGGED_IN:
+ return _("No user has logged in");
+ case CKR_USER_PIN_NOT_INITIALIZED:
+ return _("The user's password or PIN is not set");
+ case CKR_USER_TYPE_INVALID:
+ return _("The user is of an invalid type");
+ case CKR_USER_ANOTHER_ALREADY_LOGGED_IN:
+ return _("Another user is already logged in");
+ case CKR_USER_TOO_MANY_TYPES:
+ return _("Too many users of different types logged in");
+ case CKR_WRAPPED_KEY_INVALID:
+ return _("Cannot import an invalid key");
+ case CKR_WRAPPED_KEY_LEN_RANGE:
+ return _("Cannot import a key of the wrong size");
+ case CKR_WRAPPING_KEY_HANDLE_INVALID:
+ return _("Cannot export because the key is invalid");
+ case CKR_WRAPPING_KEY_SIZE_RANGE:
+ return _("Cannot export because the key is of the wrong size");
+ case CKR_WRAPPING_KEY_TYPE_INCONSISTENT:
+ return _("Cannot export because the key is of the wrong type");
+ case CKR_RANDOM_SEED_NOT_SUPPORTED:
+ return _("Cannot set a random seed");
+ case CKR_RANDOM_NO_RNG:
+ return _("No random number generator available");
+ case CKR_DOMAIN_PARAMS_INVALID:
+ return _("The crypto mechanism has an invalid parameter");
+ case CKR_BUFFER_TOO_SMALL:
+ return _("Not enough space to store the result");
+ case CKR_SAVED_STATE_INVALID:
+ return _("The saved state is invalid");
+ case CKR_INFORMATION_SENSITIVE:
+ return _("The information is sensitive and cannot be revealed");
+ case CKR_STATE_UNSAVEABLE:
+ return _("The state cannot be saved");
+ case CKR_CRYPTOKI_NOT_INITIALIZED:
+ return _("The module has not been initialized");
+ case CKR_CRYPTOKI_ALREADY_INITIALIZED:
+ return _("The module has already been initialized");
+ case CKR_MUTEX_BAD:
+ return _("Cannot lock data");
+ case CKR_MUTEX_NOT_LOCKED:
+ return _("The data cannot be locked");
+ case CKR_FUNCTION_REJECTED:
+ return _("The signature request was rejected by the user");
+
+ default:
+ g_message ("unknown error: %u", (guint)rv);
+ return _("Unknown error");
+ }
+}
+
+gchar*
+gp11_string_from_chars (const guchar *data, gsize max)
+{
+ gchar *string;
+
+ g_return_val_if_fail (data, NULL);
+ g_return_val_if_fail (max, NULL);
+
+ string = g_strndup ((gchar*)data, max);
+ g_strstrip (string);
+ return string;
+}
diff --git a/gp11/gp11-module.c b/gp11/gp11-module.c
new file mode 100644
index 00000000..d3082363
--- /dev/null
+++ b/gp11/gp11-module.c
@@ -0,0 +1,319 @@
+
+#include "config.h"
+
+#include "gp11.h"
+
+#include <string.h>
+
+enum {
+ PROP_0,
+ PROP_MODULE_PATH
+};
+
+typedef struct _GP11ModulePrivate {
+ GModule *module;
+} GP11ModulePrivate;
+
+#define GP11_MODULE_GET_PRIVATE(o) \
+ (G_TYPE_INSTANCE_GET_PRIVATE((o), GP11_TYPE_MODULE, GP11ModulePrivate))
+
+G_DEFINE_TYPE (GP11Module, gp11_module, G_TYPE_OBJECT);
+
+/* ----------------------------------------------------------------------------
+ * HELPERS
+ */
+
+static CK_RV
+create_mutex (void **mutex)
+{
+ if (!mutex)
+ return CKR_ARGUMENTS_BAD;
+
+ if (!g_thread_supported ()) {
+ g_warning ("cannot create pkcs11 mutex, threading has not been initialized");
+ return CKR_GENERAL_ERROR;
+ }
+
+ *mutex = g_mutex_new ();
+ g_return_val_if_fail (*mutex, CKR_GENERAL_ERROR);
+ return CKR_OK;
+}
+
+static CK_RV
+destroy_mutex (void *mutex)
+{
+ if (!mutex)
+ return CKR_MUTEX_BAD;
+ g_mutex_free ((GMutex*)mutex);
+ return CKR_OK;
+}
+
+static CK_RV
+lock_mutex (void *mutex)
+{
+ if (!mutex)
+ return CKR_MUTEX_BAD;
+ g_mutex_lock ((GMutex*)mutex);
+ return CKR_OK;
+}
+
+static CK_RV
+unlock_mutex (void *mutex)
+{
+ if (!mutex)
+ return CKR_MUTEX_BAD;
+ g_mutex_unlock ((GMutex*)mutex);
+ return CKR_OK;
+}
+
+/* ----------------------------------------------------------------------------
+ * OBJECT
+ */
+
+static void
+gp11_module_init (GP11Module *module)
+{
+
+}
+
+static void
+gp11_module_get_property (GObject *obj, guint prop_id, GValue *value,
+ GParamSpec *pspec)
+{
+ GP11Module *module = GP11_MODULE (obj);
+
+ switch (prop_id) {
+ case PROP_MODULE_PATH:
+ g_value_set_string (value, module->path);
+ break;
+ }
+}
+
+static void
+gp11_module_set_property (GObject *obj, guint prop_id, const GValue *value,
+ GParamSpec *pspec)
+{
+ GP11ModulePrivate *pv = GP11_MODULE_GET_PRIVATE (obj);
+ GP11Module *module = GP11_MODULE (obj);
+
+ switch (prop_id) {
+ case PROP_MODULE_PATH:
+ g_return_if_fail (!pv->module);
+ module->path = g_value_dup_string (value);
+ g_return_if_fail (module->path);
+ break;
+ }
+}
+
+static void
+gp11_module_dispose (GObject *obj)
+{
+ GP11Module *module = GP11_MODULE (obj);
+ CK_RV rv;
+
+ if (module->funcs) {
+ rv = (module->funcs->C_Finalize) (NULL);
+ if (rv != CKR_OK) {
+ g_warning ("C_Finalize on module '%s' failed: %s",
+ module->path, gp11_message_from_rv (rv));
+ }
+ module->funcs = NULL;
+ }
+}
+
+static void
+gp11_module_finalize (GObject *obj)
+{
+ GP11ModulePrivate *pv = GP11_MODULE_GET_PRIVATE (obj);
+ GP11Module *module = GP11_MODULE (obj);
+
+ g_assert (module->funcs == NULL);
+
+ if (pv->module) {
+ if (!g_module_close (pv->module))
+ g_warning ("failed to close the pkcs11 module: %s",
+ g_module_error ());
+ pv->module = NULL;
+ }
+
+ g_free (module->path);
+ module->path = NULL;
+
+ G_OBJECT_CLASS (gp11_module_parent_class)->finalize (obj);
+}
+
+
+static void
+gp11_module_class_init (GP11ModuleClass *klass)
+{
+ GObjectClass *gobject_class = (GObjectClass*)klass;
+ gp11_module_parent_class = g_type_class_peek_parent (klass);
+
+ gobject_class->get_property = gp11_module_get_property;
+ gobject_class->set_property = gp11_module_set_property;
+ gobject_class->dispose = gp11_module_dispose;
+ gobject_class->finalize = gp11_module_finalize;
+
+ g_object_class_install_property (gobject_class, PROP_MODULE_PATH,
+ g_param_spec_string ("module-path", "Module Path", "Path to the PKCS11 Module",
+ NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_type_class_add_private (gobject_class, sizeof (GP11ModulePrivate));
+}
+
+/* ----------------------------------------------------------------------------
+ * PUBLIC
+ */
+
+void
+gp11_module_info_free (GP11ModuleInfo *module_info)
+{
+ if (!module_info)
+ return;
+ g_free (module_info->library_description);
+ g_free (module_info->manufacturer_id);
+ g_free (module_info);
+}
+
+GP11Module*
+gp11_module_initialize (const gchar *path, GError **err)
+{
+ CK_C_INITIALIZE_ARGS init_args;
+ CK_C_GetFunctionList get_function_list;
+ GP11ModulePrivate *pv;
+ GP11Module *mod;
+ CK_RV rv;
+
+ g_return_val_if_fail (path != NULL, NULL);
+ g_return_val_if_fail (!err || !*err, NULL);
+
+ mod = g_object_new (GP11_TYPE_MODULE, "module-path", path, NULL);
+ pv = GP11_MODULE_GET_PRIVATE (mod);
+
+ /* Load the actual module */
+ pv->module = g_module_open (path, 0);
+ if (!pv->module) {
+ g_set_error (err, GP11_ERROR, CKR_GP11_MODULE_PROBLEM,
+ "Error loading pkcs11 module: %s", g_module_error ());
+ g_object_unref (mod);
+ return NULL;
+ }
+
+ /* Get the entry point */
+ if (!g_module_symbol (pv->module, "C_GetFunctionList", (void**)&get_function_list)) {
+ g_set_error (err, GP11_ERROR, CKR_GP11_MODULE_PROBLEM,
+ "Invalid pkcs11 module: %s", g_module_error ());
+ g_object_unref (mod);
+ return NULL;
+ }
+
+ /* Get the function list */
+ rv = (get_function_list) (&mod->funcs);
+ if (rv != CKR_OK) {
+ g_set_error (err, GP11_ERROR, rv, "Couldn't get pkcs11 function list: %s",
+ gp11_message_from_rv (rv));
+ g_object_unref (mod);
+ return NULL;
+ }
+
+ /* Make sure we have a compatible version */
+ if (mod->funcs->version.major != CRYPTOKI_VERSION_MAJOR) {
+ g_set_error (err, GP11_ERROR, CKR_GP11_MODULE_PROBLEM,
+ "Incompatible version of pkcs11 module: %d.%d",
+ (int)mod->funcs->version.major,
+ (int)mod->funcs->version.minor);
+ g_object_unref (mod);
+ return NULL;
+ }
+
+ memset (&init_args, 0, sizeof (init_args));
+ init_args.flags = CKF_OS_LOCKING_OK;
+ init_args.CreateMutex = create_mutex;
+ init_args.DestroyMutex = destroy_mutex;
+ init_args.LockMutex = lock_mutex;
+ init_args.UnlockMutex = unlock_mutex;
+ init_args.pReserved = NULL;
+
+ /* Now initialize the module */
+ rv = (mod->funcs->C_Initialize) (&init_args);
+ if (rv != CKR_OK) {
+ g_set_error (err, GP11_ERROR, rv, "Couldn't initialize module: %s",
+ gp11_message_from_rv (rv));
+ g_object_unref (mod);
+ return NULL;
+ }
+
+ return mod;
+}
+
+GP11ModuleInfo*
+gp11_module_get_info (GP11Module *module)
+{
+ GP11ModuleInfo *modinfo;
+ CK_INFO info;
+ CK_RV rv;
+
+ g_return_val_if_fail (GP11_IS_MODULE (module), NULL);
+ g_return_val_if_fail (module->funcs, NULL);
+
+ memset (&info, 0, sizeof (info));
+ rv = (module->funcs->C_GetInfo (&info));
+ if (rv != CKR_OK) {
+ g_warning ("couldn't get module info: %s", gp11_message_from_rv (rv));
+ return NULL;
+ }
+
+ modinfo = g_new0 (GP11ModuleInfo, 1);
+ modinfo->flags = info.flags;
+ modinfo->library_description = gp11_string_from_chars (info.libraryDescription,
+ sizeof (info.libraryDescription));
+ modinfo->manufacturer_id = gp11_string_from_chars (info.manufacturerID,
+ sizeof (info.manufacturerID));
+ modinfo->library_version_major = info.libraryVersion.major;
+ modinfo->library_version_minor = info.libraryVersion.minor;
+ modinfo->pkcs11_version_major = info.cryptokiVersion.major;
+ modinfo->pkcs11_version_minor = info.cryptokiVersion.minor;
+
+ return modinfo;
+}
+
+GList*
+gp11_module_get_slots (GP11Module *module, gboolean token_present)
+{
+ CK_SLOT_ID_PTR slot_list;
+ CK_ULONG count, i;
+ GList *result;
+ CK_RV rv;
+
+ g_return_val_if_fail (GP11_IS_MODULE (module), NULL);
+ g_return_val_if_fail (module->funcs, NULL);
+
+ rv = (module->funcs->C_GetSlotList) (token_present ? CK_TRUE : CK_FALSE, NULL, &count);
+ if (rv != CKR_OK) {
+ g_warning ("couldn't get slot count: %s", gp11_message_from_rv (rv));
+ return NULL;
+ }
+
+ if (!count)
+ return NULL;
+
+ slot_list = g_new (CK_SLOT_ID, count);
+ rv = (module->funcs->C_GetSlotList) (token_present ? CK_TRUE : CK_FALSE, slot_list, &count);
+ if (rv != CKR_OK) {
+ g_warning ("couldn't get slot list: %s", gp11_message_from_rv (rv));
+ g_free (slot_list);
+ return NULL;
+ }
+
+ result = NULL;
+ for (i = 0; i < count; ++i) {
+ /* TODO: Should we be looking these up somewhere? */
+ result = g_list_prepend (result, g_object_new (GP11_TYPE_SLOT,
+ "handle", slot_list[i],
+ "module", module, NULL));
+ }
+
+ g_free (slot_list);
+ return g_list_reverse (result);
+}
+
diff --git a/gp11/gp11-object.c b/gp11/gp11-object.c
new file mode 100644
index 00000000..81bb84ca
--- /dev/null
+++ b/gp11/gp11-object.c
@@ -0,0 +1,458 @@
+
+#include "config.h"
+
+#include "gp11.h"
+#include "gp11-private.h"
+
+#include <string.h>
+
+enum {
+ PROP_0,
+ PROP_MODULE,
+ PROP_SESSION,
+ PROP_HANDLE
+};
+
+G_DEFINE_TYPE (GP11Object, gp11_object, G_TYPE_OBJECT);
+
+/* ----------------------------------------------------------------------------
+ * OBJECT
+ */
+
+static void
+gp11_object_init (GP11Object *object)
+{
+
+}
+
+static void
+gp11_object_get_property (GObject *obj, guint prop_id, GValue *value,
+ GParamSpec *pspec)
+{
+ GP11Object *object = GP11_OBJECT (obj);
+
+ switch (prop_id) {
+ case PROP_MODULE:
+ g_value_set_object (value, object->module);
+ break;
+ case PROP_SESSION:
+ g_value_set_object (value, object->session);
+ break;
+ case PROP_HANDLE:
+ g_value_set_uint (value, object->handle);
+ break;
+ }
+}
+
+static void
+gp11_object_set_property (GObject *obj, guint prop_id, const GValue *value,
+ GParamSpec *pspec)
+{
+ GP11Object *object = GP11_OBJECT (obj);
+
+ switch (prop_id) {
+ case PROP_MODULE:
+ g_return_if_fail (!object->module);
+ object->module = g_value_get_object (value);
+ g_return_if_fail (object->module);
+ g_object_ref (object->module);
+ break;
+ case PROP_SESSION:
+ g_return_if_fail (!object->session);
+ object->session = g_value_get_object (value);
+ g_return_if_fail (object->session);
+ g_object_ref (object->session);
+ break;
+ case PROP_HANDLE:
+ g_return_if_fail (!object->handle);
+ object->handle = g_value_get_uint (value);
+ break;
+ }
+}
+
+static void
+gp11_object_dispose (GObject *obj)
+{
+ GP11Object *object = GP11_OBJECT (obj);
+
+ if (object->session)
+ g_object_unref (object->session);
+ object->session = NULL;
+
+ if (object->module)
+ g_object_unref (object->module);
+ object->module = NULL;
+
+ G_OBJECT_CLASS (gp11_object_parent_class)->dispose (obj);
+}
+
+static void
+gp11_object_finalize (GObject *obj)
+{
+ GP11Object *object = GP11_OBJECT (obj);
+
+ g_assert (object->session == NULL);
+ g_assert (object->module == NULL);
+ object->handle = 0;
+
+ G_OBJECT_CLASS (gp11_object_parent_class)->finalize (obj);
+}
+
+
+static void
+gp11_object_class_init (GP11ObjectClass *klass)
+{
+ GObjectClass *gobject_class = (GObjectClass*)klass;
+ gp11_object_parent_class = g_type_class_peek_parent (klass);
+
+ gobject_class->get_property = gp11_object_get_property;
+ gobject_class->set_property = gp11_object_set_property;
+ gobject_class->dispose = gp11_object_dispose;
+ gobject_class->finalize = gp11_object_finalize;
+
+ g_object_class_install_property (gobject_class, PROP_MODULE,
+ g_param_spec_object ("module", "Module", "PKCS11 Module",
+ GP11_TYPE_MODULE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property (gobject_class, PROP_SESSION,
+ g_param_spec_object ("session", "Session", "PKCS11 Session",
+ GP11_TYPE_SESSION, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property (gobject_class, PROP_HANDLE,
+ g_param_spec_uint ("handle", "Object Handle", "PKCS11 Object Handle",
+ 0, G_MAXUINT, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+}
+
+/* ----------------------------------------------------------------------------
+ * PUBLIC
+ */
+
+GP11Object*
+gp11_object_from_handle (GP11Session *session, CK_OBJECT_HANDLE handle)
+{
+ g_return_val_if_fail (GP11_IS_SESSION (session), NULL);
+ return g_object_new (GP11_TYPE_OBJECT, "module", session->module, "handle", handle, "session", session, NULL);
+}
+
+/* DESTROY */
+
+typedef struct _Destroy {
+ GP11Arguments base;
+ CK_OBJECT_HANDLE object;
+} Destroy;
+
+static CK_RV
+perform_destroy (Destroy *args)
+{
+ return (args->base.pkcs11->C_DestroyObject) (args->base.handle, args->object);
+}
+
+gboolean
+gp11_object_destroy (GP11Object *object, GError **err)
+{
+ return gp11_object_destroy_full (object, NULL, err);
+}
+
+gboolean
+gp11_object_destroy_full (GP11Object *object, GCancellable *cancellable, GError **err)
+{
+ Destroy args = { GP11_ARGUMENTS_INIT, 0 };
+ g_return_val_if_fail (GP11_IS_OBJECT (object), FALSE);
+ g_return_val_if_fail (GP11_IS_SESSION (object->session), FALSE);
+ args.object = object->handle;
+ return _gp11_call_sync (object->session, perform_destroy, &args, cancellable, err);
+}
+
+void
+gp11_object_destroy_async (GP11Object *object, GCancellable *cancellable,
+ GAsyncReadyCallback callback, gpointer user_data)
+{
+ Destroy* args;
+
+ g_return_if_fail (GP11_IS_OBJECT (object));
+ g_return_if_fail (GP11_IS_SESSION (object->session));
+
+ args = _gp11_call_async_prep (object->session, perform_destroy, sizeof (*args), NULL);
+ args->object = object->handle;
+
+ _gp11_call_async_go (args, cancellable, callback, user_data);
+}
+
+gboolean
+gp11_object_destroy_finish (GP11Object *object, GAsyncResult *result, GError **err)
+{
+ return _gp11_call_basic_finish (object, result, err);
+}
+
+typedef struct _SetAttributes {
+ GP11Arguments base;
+ GP11Attributes *attrs;
+ CK_OBJECT_HANDLE object;
+} SetAttributes;
+
+static void
+free_set_attributes (SetAttributes *args)
+{
+ gp11_attributes_unref (args->attrs);
+ g_free (args);
+}
+
+static CK_RV
+perform_set_attributes (SetAttributes *args)
+{
+ return (args->base.pkcs11->C_SetAttributeValue) (args->base.handle, args->object,
+ _gp11_attributes_raw (args->attrs),
+ gp11_attributes_count (args->attrs));
+}
+
+gboolean
+gp11_object_set (GP11Object *object, GError **err, ...)
+{
+ GP11Attributes *attrs;
+ va_list va;
+ CK_RV rv;
+
+ va_start (va, err);
+ attrs = gp11_attributes_new_valist (va);
+ va_end (va);
+
+ rv = gp11_object_set_full (object, attrs, NULL, err);
+
+ gp11_attributes_unref (attrs);
+ return rv;
+}
+
+gboolean
+gp11_object_set_full (GP11Object *object, GP11Attributes *attrs,
+ GCancellable *cancellable, GError **err)
+{
+ SetAttributes args;
+
+ g_return_val_if_fail (GP11_IS_OBJECT (object), FALSE);
+
+ memset (&args, 0, sizeof (args));
+ args.attrs = attrs;
+ args.object = object->handle;
+
+ return _gp11_call_sync (object->session, perform_set_attributes, &args, cancellable, err);
+}
+
+void
+gp11_object_set_async (GP11Object *object, GP11Attributes *attrs, GCancellable *cancellable,
+ GAsyncReadyCallback callback, gpointer user_data)
+{
+ SetAttributes *args;
+
+ g_return_if_fail (GP11_IS_OBJECT (object));
+
+ args = _gp11_call_async_prep (object->session, perform_set_attributes,
+ sizeof (*args), free_set_attributes);
+ args->attrs = attrs;
+ gp11_attributes_ref (attrs);
+ args->object = object->handle;
+
+ _gp11_call_async_go (args, cancellable, callback, user_data);
+}
+
+gboolean
+gp11_object_set_finish (GP11Object *object, GAsyncResult *result, GError **err)
+{
+ return _gp11_call_basic_finish (object, result, err);
+}
+
+typedef struct _GetAttributes {
+ GP11Arguments base;
+ guint *attr_types;
+ gsize n_attr_types;
+ CK_OBJECT_HANDLE object;
+ GP11Attributes *results;
+} GetAttributes;
+
+static void
+free_get_attributes (GetAttributes *args)
+{
+ g_free (args->attr_types);
+ if (args->results)
+ gp11_attributes_unref (args->results);
+ g_free (args);
+}
+
+static CK_RV
+perform_get_attributes (GetAttributes *args)
+{
+ CK_ATTRIBUTE_PTR attrs;
+ CK_ULONG i, n_attrs;
+ CK_RV rv;
+
+ /* Allocate the CK_ATTRIBUTE's */
+ n_attrs = args->n_attr_types;
+ if (n_attrs) {
+ attrs = g_new0 (CK_ATTRIBUTE, n_attrs);
+ for (i = 0; i < n_attrs; ++i)
+ attrs[i].type = args->attr_types[i];
+ } else {
+ attrs = NULL;
+ }
+
+ /* Get the size of each value */
+ rv = (args->base.pkcs11->C_GetAttributeValue) (args->base.handle, args->object,
+ attrs, n_attrs);
+ if (rv != CKR_OK) {
+ g_free (attrs);
+ return rv;
+ }
+
+ /* Allocate memory for each value */
+ for (i = 0; i < n_attrs; ++i) {
+ if (attrs[i].ulValueLen > 0 && attrs[i].ulValueLen != (CK_ULONG)-1)
+ attrs[i].pValue = g_malloc0 (attrs[i].ulValueLen);
+ }
+
+ /* Now get the actual values */
+ rv = (args->base.pkcs11->C_GetAttributeValue) (args->base.handle, args->object,
+ attrs, n_attrs);
+
+ /* Transfer over the memory to the results */
+ if (rv == CKR_OK) {
+ g_assert (!args->results);
+ args->results = gp11_attributes_new ();
+ for (i = 0; i < n_attrs; ++i) {
+ _gp11_attributes_add_take (args->results, attrs[i].type,
+ attrs[i].pValue, attrs[i].ulValueLen);
+ memset (&attrs[i], 0, sizeof (attrs[0]));
+ }
+ }
+
+ /* Free any memory we didn't use */
+ for (i = 0; i < n_attrs; ++i)
+ g_free (attrs[i].pValue);
+ g_free (attrs);
+ return rv;
+}
+
+GP11Attributes*
+gp11_object_get (GP11Object *object, GError **err, ...)
+{
+ GP11Attributes *result;
+ GArray *array;
+ va_list va;
+ guint type;
+
+ array = g_array_new (0, 1, sizeof (guint));
+ va_start (va, err);
+ for (;;) {
+ type = va_arg (va, guint);
+ if (type == (guint)-1)
+ break;
+ g_array_append_val (array, type);
+ }
+ va_end (va);
+
+ result = gp11_object_get_full (object, (guint*)array->data, array->len, NULL, err);
+ g_array_free (array, TRUE);
+ return result;
+}
+
+GP11Attributes*
+gp11_object_get_full (GP11Object *object, guint *attr_types, gsize n_attr_types,
+ GCancellable *cancellable, GError **err)
+{
+ GetAttributes args;
+
+ g_return_val_if_fail (GP11_IS_OBJECT (object), FALSE);
+
+ memset (&args, 0, sizeof (args));
+ args.attr_types = attr_types;
+ args.n_attr_types = n_attr_types;
+ args.object = object->handle;
+
+ if (!_gp11_call_sync (object->session, perform_get_attributes, &args, cancellable, err)) {
+ gp11_attributes_unref (args.results);
+ return NULL;
+ }
+
+ return args.results;
+}
+
+void
+gp11_object_get_async (GP11Object *object, guint *attr_types, gsize n_attr_types,
+ GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+ GetAttributes *args;
+
+ g_return_if_fail (GP11_IS_OBJECT (object));
+
+ args = _gp11_call_async_prep (object->session, perform_get_attributes,
+ sizeof (*args), free_get_attributes);
+ args->n_attr_types = n_attr_types;
+ if (n_attr_types)
+ args->attr_types = g_memdup (attr_types, sizeof (guint) * n_attr_types);
+ args->object = object->handle;
+
+ _gp11_call_async_go (args, cancellable, callback, user_data);
+}
+
+GP11Attributes*
+gp11_object_get_finish (GP11Object *object, GAsyncResult *result, GError **err)
+{
+ GP11Attributes *results;
+ GetAttributes *args;
+
+ if (!_gp11_call_basic_finish (object, result, err))
+ return NULL;
+
+ args = _gp11_call_arguments (result, GetAttributes);
+
+ results = args->results;
+ args->results = NULL;
+
+ return results;
+}
+
+GP11Attribute*
+gp11_object_get_one (GP11Object *object, guint attr_type, GError **err)
+{
+ return gp11_object_get_one_full (object, attr_type, NULL, err);
+}
+
+GP11Attribute*
+gp11_object_get_one_full (GP11Object *object, guint attr_type,
+ GCancellable *cancellable, GError **err)
+{
+ GP11Attributes *attrs;
+ GP11Attribute *attr;
+
+ attrs = gp11_object_get_full (object, &attr_type, 1, cancellable, err);
+ if (!attrs || !gp11_attributes_count (attrs))
+ return NULL;
+
+ attr = gp11_attributes_at (attrs, 0);
+ g_return_val_if_fail (attr, NULL);
+ attr = gp11_attribute_dup (attr);
+ gp11_attributes_unref (attrs);
+ return attr;
+}
+
+void
+gp11_object_get_one_async (GP11Object *object, guint attr_type, GCancellable *cancellable,
+ GAsyncReadyCallback callback, gpointer user_data)
+{
+ gp11_object_get_async (object, &attr_type, 1, cancellable, callback, user_data);
+}
+
+GP11Attribute*
+gp11_object_get_one_finish (GP11Object *object, GAsyncResult *result, GError **err)
+{
+ GP11Attributes *attrs;
+ GP11Attribute *attr;
+
+ attrs = gp11_object_get_finish (object, result, err);
+ if (!attrs)
+ return NULL;
+
+ attr = gp11_attributes_at (attrs, 0);
+ g_return_val_if_fail (attr, NULL);
+ attr = gp11_attribute_dup (attr);
+ gp11_attributes_unref (attrs);
+ return attr;
+}
diff --git a/gp11/gp11-private.h b/gp11/gp11-private.h
new file mode 100644
index 00000000..8a7a0531
--- /dev/null
+++ b/gp11/gp11-private.h
@@ -0,0 +1,99 @@
+#ifndef GP11_PRIVATE_H_
+#define GP11_PRIVATE_H_
+
+#include "gp11.h"
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+void _gp11_attribute_init_take (GP11Attribute *attr,
+ guint attr_type,
+ gpointer value,
+ gsize length);
+
+void _gp11_attributes_add_take (GP11Attributes *attr,
+ guint attr_type,
+ gpointer value,
+ gsize length);
+
+CK_ATTRIBUTE_PTR _gp11_attributes_raw (GP11Attributes *attrs);
+
+/* ----------------------------------------------------------------------------
+ * CALL
+ */
+
+typedef CK_RV (*GP11CallFunc) (gpointer call_data);
+
+typedef struct _GP11Call GP11Call;
+
+typedef struct _GP11Arguments {
+ GP11Call *call;
+
+ /* For the call function to use */
+ CK_FUNCTION_LIST_PTR pkcs11;
+ CK_ULONG handle;
+
+} GP11Arguments;
+
+#define GP11_ARGUMENTS_INIT { NULL, NULL, 0 }
+
+#define GP11_TYPE_CALL (_gp11_call_get_type())
+#define GP11_CALL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GP11_TYPE_CALL, GP11Call))
+#define GP11_CALL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GP11_TYPE_CALL, GP11Call))
+#define GP11_IS_CALL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GP11_TYPE_CALL))
+#define GP11_IS_CALL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GP11_TYPE_CALL))
+#define GP11_CALL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GP11_TYPE_CALL, GP11CallClass))
+
+typedef struct _GP11CallClass GP11CallClass;
+
+struct _GP11Call {
+ GObject parent;
+
+ /* For making the call */
+ GP11CallFunc func;
+ GP11Arguments *args;
+ GCancellable *cancellable;
+ GDestroyNotify destroy;
+ CK_RV rv;
+
+ /* For result callback only */
+ gpointer object;
+ GAsyncReadyCallback callback;
+ gpointer user_data;
+};
+
+struct _GP11CallClass {
+ GObjectClass parent;
+};
+
+GType _gp11_call_get_type (void) G_GNUC_CONST;
+
+#define _gp11_call_arguments(call, type) \
+ (type*)(GP11_CALL (call)->args)
+
+void _gp11_call_uninitialize (void);
+
+gboolean _gp11_call_sync (gpointer object,
+ gpointer func,
+ gpointer args,
+ GCancellable *cancellable,
+ GError **err);
+
+gpointer _gp11_call_async_prep (gpointer object,
+ gpointer func,
+ gsize args_size,
+ gpointer destroy_func);
+
+void _gp11_call_async_go (gpointer args,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean _gp11_call_basic_finish (gpointer object,
+ GAsyncResult *result,
+ GError **err);
+
+#endif /* GP11_PRIVATE_H_ */
diff --git a/gp11/gp11-session.c b/gp11/gp11-session.c
new file mode 100644
index 00000000..403cac43
--- /dev/null
+++ b/gp11/gp11-session.c
@@ -0,0 +1,864 @@
+
+#include "config.h"
+
+#include "gp11.h"
+#include "gp11-private.h"
+
+#include <string.h>
+
+enum {
+ PROP_0,
+ PROP_MODULE,
+ PROP_HANDLE
+};
+
+G_DEFINE_TYPE (GP11Session, gp11_session, G_TYPE_OBJECT);
+
+/* ----------------------------------------------------------------------------
+ * OBJECT
+ */
+
+static void
+gp11_session_init (GP11Session *session)
+{
+
+}
+
+static void
+gp11_session_get_property (GObject *obj, guint prop_id, GValue *value,
+ GParamSpec *pspec)
+{
+ GP11Session *session = GP11_SESSION (obj);
+
+ switch (prop_id) {
+ case PROP_MODULE:
+ g_value_set_object (value, session->module);
+ break;
+ case PROP_HANDLE:
+ g_value_set_uint (value, session->handle);
+ break;
+ }
+}
+
+static void
+gp11_session_set_property (GObject *obj, guint prop_id, const GValue *value,
+ GParamSpec *pspec)
+{
+ GP11Session *session = GP11_SESSION (obj);
+
+ switch (prop_id) {
+ case PROP_MODULE:
+ g_return_if_fail (!session->module);
+ session->module = g_value_dup_object (value);
+ g_return_if_fail (session->module);
+ break;
+ case PROP_HANDLE:
+ g_return_if_fail (!session->handle);
+ session->handle = g_value_get_uint (value);
+ break;
+ }
+}
+
+static void
+gp11_session_dispose (GObject *obj)
+{
+ GP11Session *session = GP11_SESSION (obj);
+ CK_RV rv;
+
+ if (session->handle) {
+ g_return_if_fail (session->module && session->module->funcs);
+ rv = (session->module->funcs->C_CloseSession) (session->handle);
+ if (rv != CKR_OK) {
+ g_warning ("couldn't close session properly: %s",
+ gp11_message_from_rv (rv));
+ }
+ session->handle = 0;
+ }
+
+ if (session->module)
+ g_object_unref (session->module);
+ session->module = NULL;
+
+ G_OBJECT_CLASS (gp11_session_parent_class)->dispose (obj);
+}
+
+static void
+gp11_session_finalize (GObject *obj)
+{
+ GP11Session *session = GP11_SESSION (obj);
+
+ g_assert (session->module == NULL);
+ g_assert (session->handle == 0);
+
+ G_OBJECT_CLASS (gp11_session_parent_class)->finalize (obj);
+}
+
+
+static void
+gp11_session_class_init (GP11SessionClass *klass)
+{
+ GObjectClass *gobject_class = (GObjectClass*)klass;
+ gp11_session_parent_class = g_type_class_peek_parent (klass);
+
+ gobject_class->get_property = gp11_session_get_property;
+ gobject_class->set_property = gp11_session_set_property;
+ gobject_class->dispose = gp11_session_dispose;
+ gobject_class->finalize = gp11_session_finalize;
+
+ g_object_class_install_property (gobject_class, PROP_MODULE,
+ g_param_spec_object ("module", "Module", "PKCS11 Module",
+ GP11_TYPE_MODULE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property (gobject_class, PROP_HANDLE,
+ g_param_spec_uint ("handle", "Session Handle", "PKCS11 Session Handle",
+ 0, G_MAXUINT, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+}
+
+/* ----------------------------------------------------------------------------
+ * PUBLIC
+ */
+
+void
+gp11_session_info_free (GP11SessionInfo *session_info)
+{
+ if (!session_info)
+ return;
+ g_free (session_info);
+}
+
+GP11Session*
+gp11_session_from_handle (GP11Slot *slot, CK_SESSION_HANDLE handle)
+{
+ g_return_val_if_fail (GP11_IS_SLOT (slot), NULL);
+ return g_object_new (GP11_TYPE_SESSION, "module", slot->module, "handle", handle, NULL);
+}
+
+GP11SessionInfo*
+gp11_session_get_info (GP11Session *session)
+{
+ GP11SessionInfo *sessioninfo;
+ CK_SESSION_INFO info;
+ CK_RV rv;
+
+ g_return_val_if_fail (GP11_IS_SESSION (session), NULL);
+ g_return_val_if_fail (GP11_IS_MODULE (session->module), NULL);
+ g_return_val_if_fail (session->module->funcs, NULL);
+
+ memset (&info, 0, sizeof (info));
+ rv = (session->module->funcs->C_GetSessionInfo) (session->handle, &info);
+ if (rv != CKR_OK) {
+ g_warning ("couldn't get session info: %s", gp11_message_from_rv (rv));
+ return NULL;
+ }
+
+ sessioninfo = g_new0 (GP11SessionInfo, 1);
+ sessioninfo->flags = info.flags;
+ sessioninfo->slot_id = info.slotID;
+ sessioninfo->state = info.state;
+ sessioninfo->device_error = info.ulDeviceError;
+
+ return sessioninfo;
+}
+
+
+
+/* LOGIN */
+
+typedef struct _Login {
+ GP11Arguments base;
+ guint32 user_type;
+ guchar *pin;
+ gsize n_pin;
+} Login;
+
+static void
+free_login (Login *args)
+{
+ g_free (args->pin);
+ g_free (args);
+}
+
+static CK_RV
+perform_login (Login *args)
+{
+ return (args->base.pkcs11->C_Login) (args->base.handle, args->user_type,
+ (CK_BYTE_PTR)args->pin, args->n_pin);
+}
+
+gboolean
+gp11_session_login (GP11Session *session, guint32 user_type, const guchar *pin,
+ gsize n_pin, GError **err)
+{
+ return gp11_session_login_full (session, user_type, pin, n_pin, NULL, err);
+}
+
+gboolean
+gp11_session_login_full (GP11Session *session, guint32 user_type, const guchar *pin,
+ gsize n_pin, GCancellable *cancellable, GError **err)
+{
+ Login args = { GP11_ARGUMENTS_INIT, user_type, (guchar*)pin, n_pin };
+ return _gp11_call_sync (session, perform_login, &args, cancellable, err);
+
+}
+
+void
+gp11_session_login_async (GP11Session *session, guint32 user_type, const guchar *pin,
+ gsize n_pin, GCancellable *cancellable, GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ Login* args = _gp11_call_async_prep (session, perform_login, sizeof (*args), free_login);
+
+ args->user_type = user_type;
+ args->pin = pin && n_pin ? g_memdup (pin, n_pin) : NULL;
+ args->n_pin = n_pin;
+
+ _gp11_call_async_go (args, cancellable, callback, user_data);
+
+}
+
+gboolean
+gp11_session_login_finish (GP11Session *session, GAsyncResult *result, GError **err)
+{
+ return _gp11_call_basic_finish (session, result, err);
+}
+
+
+
+
+/* LOGOUT */
+
+static CK_RV
+perform_logout (GP11Arguments *args)
+{
+ return (args->pkcs11->C_Logout) (args->handle);
+}
+
+gboolean
+gp11_session_logout (GP11Session *session, GError **err)
+{
+ return gp11_session_logout_full (session, NULL, err);
+}
+
+gboolean
+gp11_session_logout_full (GP11Session *session, GCancellable *cancellable, GError **err)
+{
+ GP11Arguments args = GP11_ARGUMENTS_INIT;
+ return _gp11_call_sync (session, perform_logout, &args, cancellable, err);
+}
+
+void
+gp11_session_logout_async (GP11Session *session, GCancellable *cancellable,
+ GAsyncReadyCallback callback, gpointer user_data)
+{
+ GP11Arguments *args = _gp11_call_async_prep (session, perform_logout, 0, NULL);
+ _gp11_call_async_go (args, cancellable, callback, user_data);
+}
+
+gboolean
+gp11_session_logout_finish (GP11Session *session, GAsyncResult *result, GError **err)
+{
+ return _gp11_call_basic_finish (session, result, err);
+}
+
+
+
+
+/* CREATE OBJECT */
+
+typedef struct _CreateObject {
+ GP11Arguments base;
+ GP11Attributes *attrs;
+ CK_OBJECT_HANDLE object;
+} CreateObject;
+
+static void
+free_create_object (CreateObject *args)
+{
+ gp11_attributes_unref (args->attrs);
+ g_free (args);
+}
+
+static CK_RV
+perform_create_object (CreateObject *args)
+{
+ return (args->base.pkcs11->C_CreateObject) (args->base.handle,
+ _gp11_attributes_raw (args->attrs),
+ gp11_attributes_count (args->attrs),
+ &args->object);
+}
+
+GP11Object*
+gp11_session_create_object (GP11Session *session, GError **err, ...)
+{
+ GP11Attributes *attrs;
+ GP11Object *object;
+ va_list va;
+
+ va_start (va, err);
+ attrs = gp11_attributes_new_valist (va);
+ va_end (va);
+
+ object = gp11_session_create_object_full (session, attrs, NULL, err);
+ gp11_attributes_unref (attrs);
+ return object;
+}
+
+GP11Object*
+gp11_session_create_object_full (GP11Session *session, GP11Attributes *attrs,
+ GCancellable *cancellable, GError **err)
+{
+ CreateObject args = { GP11_ARGUMENTS_INIT, attrs, 0 };
+ if (!_gp11_call_sync (session, perform_create_object, &args, cancellable, err))
+ return NULL;
+ return gp11_object_from_handle (session, args.object);
+}
+
+void
+gp11_session_create_object_async (GP11Session *session, GP11Attributes *attrs,
+ GCancellable *cancellable, GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ CreateObject *args = _gp11_call_async_prep (session, perform_create_object,
+ sizeof (*args), free_create_object);
+ args->attrs = attrs;
+ gp11_attributes_ref (attrs);
+ _gp11_call_async_go (args, cancellable, callback, user_data);
+}
+
+GP11Object*
+gp11_session_create_object_finish (GP11Session *session, GAsyncResult *result, GError **err)
+{
+ CreateObject *args;
+
+ if (!_gp11_call_basic_finish (session, result, err))
+ return NULL;
+ args = _gp11_call_arguments (result, CreateObject);
+ return gp11_object_from_handle (session, args->object);
+}
+
+
+
+/* FIND OBJECTS */
+
+typedef struct _FindObjects {
+ GP11Arguments base;
+ GP11Attributes *attrs;
+ CK_OBJECT_HANDLE_PTR objects;
+ CK_ULONG n_objects;
+} FindObjects;
+
+static void
+free_find_objects (FindObjects *args)
+{
+ gp11_attributes_unref (args->attrs);
+ g_free (args->objects);
+}
+
+static CK_RV
+perform_find_objects (FindObjects *args)
+{
+ CK_OBJECT_HANDLE_PTR batch;
+ CK_ULONG n_batch, n_found;
+ GArray *array;
+ CK_RV rv;
+
+ rv = (args->base.pkcs11->C_FindObjectsInit) (args->base.handle,
+ _gp11_attributes_raw (args->attrs),
+ gp11_attributes_count (args->attrs));
+ if (rv != CKR_OK)
+ return rv;
+
+ batch = NULL;
+ n_found = n_batch = 4;
+ array = g_array_new (0, 1, sizeof (CK_OBJECT_HANDLE));
+
+ do {
+ /*
+ * Reallocate and double in size:
+ * - First time.
+ * - Each time we found as many as batch
+ */
+
+ if (n_found == n_batch) {
+ n_batch *= 2;
+ batch = g_realloc (batch, sizeof (CK_OBJECT_HANDLE) * n_batch);
+ }
+
+ rv = (args->base.pkcs11->C_FindObjects) (args->base.handle,
+ batch, n_batch, &n_found);
+ if (rv != CKR_OK)
+ break;
+
+ g_array_append_vals (array, batch, n_found);
+
+ } while (n_found > 0);
+
+ g_free (batch);
+
+ if (rv == CKR_OK) {
+ args->n_objects = array->len;
+ args->objects = (CK_OBJECT_HANDLE_PTR)g_array_free (array, FALSE);
+ rv = (args->base.pkcs11->C_FindObjectsFinal) (args->base.handle);
+ } else {
+ args->objects = NULL;
+ args->n_objects = 0;
+ g_array_free (array, TRUE);
+ }
+
+ return rv;
+}
+
+static GList*
+objlist_from_handles (GP11Session *session, CK_OBJECT_HANDLE_PTR objects,
+ CK_ULONG n_objects)
+{
+ GList *results = NULL;
+
+ while (n_objects > 0) {
+ results = g_list_prepend (results,
+ gp11_object_from_handle (session, objects[--n_objects]));
+ }
+
+ return g_list_reverse (results);
+}
+
+GList*
+gp11_session_find_objects (GP11Session *session, GError **err, ...)
+{
+ GP11Attributes *attrs;
+ GList *results;
+ va_list va;
+
+ va_start (va, err);
+ attrs = gp11_attributes_new_valist (va);
+ va_end (va);
+
+ results = gp11_session_find_objects_full (session, attrs, NULL, err);
+ gp11_attributes_unref (attrs);
+ return results;
+}
+
+GList*
+gp11_session_find_objects_full (GP11Session *session, GP11Attributes *attrs,
+ GCancellable *cancellable, GError **err)
+{
+ FindObjects args = { GP11_ARGUMENTS_INIT, attrs, NULL, 0 };
+ GList *results = NULL;
+
+ if (_gp11_call_sync (session, perform_find_objects, &args, cancellable, err))
+ results = objlist_from_handles (session, args.objects, args.n_objects);
+ g_free (args.objects);
+ return results;
+}
+
+void
+gp11_session_find_objects_async (GP11Session *session, GP11Attributes *attrs,
+ GCancellable *cancellable, GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ FindObjects *args = _gp11_call_async_prep (session, perform_find_objects,
+ sizeof (*args), free_find_objects);
+ args->attrs = attrs;
+ gp11_attributes_ref (attrs);
+ _gp11_call_async_go (args, cancellable, callback, user_data);
+}
+
+GList*
+gp11_session_find_objects_finish (GP11Session *session, GAsyncResult *result, GError **err)
+{
+ FindObjects *args;
+
+ if (!_gp11_call_basic_finish (session, result, err))
+ return NULL;
+ args = _gp11_call_arguments (result, FindObjects);
+ return objlist_from_handles (session, args->objects, args->n_objects);
+}
+
+
+#if UNTESTED
+
+/* ENCRYPT */
+
+
+typedef struct _Crypt {
+ GP11Arguments base;
+
+ /* Functions to call */
+ CK_C_EncryptInit init_func;
+ CK_C_Encrypt complete_func;
+
+ /* Input */
+ CK_OBJECT_HANDLE key;
+ CK_MECHANISM mech;
+ guchar *input;
+ CK_ULONG n_input;
+
+ /* Output */
+ guchar *result;
+ CK_ULONG n_result;
+} Crypt;
+
+static void
+free_crypt (Crypt *args)
+{
+ g_free (args->input);
+ g_free (args->mech.pParameter);
+ g_free (args->result);
+}
+
+static CK_RV
+perform_crypt (Crypt *args)
+{
+ CK_RV rv;
+
+ g_assert (args);
+ g_assert (args->init_func);
+ g_assert (args->complete_func);
+ g_assert (!args->result);
+ g_assert (!args->n_result);
+
+ /* Initialize the crypt operation */
+ rv = (args->init_func) (args->base.handle, &args->mech, args->key);
+ if (rv != CKR_OK)
+ return rv;
+
+ /* Get the length of the result */
+ rv = (args->complete_func) (args->base.handle, args->input, args->n_input, NULL, &args->n_result);
+ if (rv != CKR_OK)
+ return rv;
+
+ /* And try again with a real buffer */
+ args->result = g_malloc0 (args->n_result);
+ return (args->complete_func) (args->base.handle, args->input, args->n_input, args->result, &args->n_result);
+}
+
+static guchar*
+crypt_sync (GP11Session *session, GP11Object *key, GP11Mechanism *mech_args, const guchar *input,
+ gsize n_input, gsize *n_result, GCancellable *cancellable, GError **err,
+ CK_C_EncryptInit init_func, CK_C_Encrypt complete_func)
+{
+ Crypt args;
+
+ g_return_val_if_fail (GP11_IS_OBJECT (key), NULL);
+ g_return_val_if_fail (mech_args, NULL);
+ g_return_val_if_fail (init_func, NULL);
+ g_return_val_if_fail (complete_func, NULL);
+
+ memset (&args, 0, sizeof (args));
+ g_object_get (key, "handle", &args.key, NULL);
+ g_return_val_if_fail (args.key != 0, NULL);
+
+ args.mech.mechanism = mech_args->type;
+ args.mech.pParameter = mech_args->parameter;
+ args.mech.ulParameterLen = mech_args->n_parameter;
+
+ /* No need to copy in this case */
+ args.input = (guchar*)input;
+ args.n_input = n_input;
+
+ args.init_func = init_func;
+ args.complete_func = complete_func;
+
+ if (!_gp11_call_sync (session, perform_crypt, &args, cancellable, err)) {
+ g_free (args.result);
+ return NULL;
+ }
+
+ return args.result;
+}
+
+static void
+crypt_async (GP11Session *session, GP11Object *key, GP11Mechanism *mech_args, const guchar *input,
+ gsize n_input, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data,
+ CK_C_EncryptInit init_func, CK_C_Encrypt complete_func)
+{
+ Crypt *args = _gp11_call_async_prep (session, perform_crypt, sizeof (*args), free_crypt);
+
+ g_return_if_fail (GP11_IS_OBJECT (key));
+ g_return_if_fail (mech_args);
+ g_return_if_fail (init_func);
+ g_return_if_fail (complete_func);
+
+ g_object_get (key, "handle", &args->key, NULL);
+ g_return_if_fail (args->key != 0);
+
+ args->mech.mechanism = mech_args->type;
+ args->mech.pParameter = mech_args->parameter && mech_args->n_parameter ?
+ g_memdup (mech_args->parameter, mech_args->n_parameter) : NULL;
+ args->mech.ulParameterLen = mech_args->n_parameter;
+
+ args->input = input && n_input ? g_memdup (input, n_input) : NULL;
+ args->n_input = n_input;
+
+ args->init_func = init_func;
+ args->complete_func = complete_func;
+
+ _gp11_call_async_go (args, cancellable, callback, user_data);
+}
+
+static guchar*
+crypt_finish (GP11Session *session, GAsyncResult *result, gsize *n_result, GError **err)
+{
+ Crypt *args;
+ guchar *res;
+
+ if (!_gp11_call_basic_finish (session, result, err))
+ return NULL;
+ args = _gp11_call_arguments (result, Crypt);
+
+ /* Steal the values from the results */
+ res = args->result;
+ args->result = NULL;
+ *n_result = args->n_result;
+ args->n_result = 0;
+
+ return res;
+}
+
+guchar*
+gp11_session_encrypt (GP11Session *session, GP11Object *key, guint mech, const guchar *input,
+ gsize n_input, gsize *n_result, GError **err)
+{
+ GP11Mechanism mech_args = { mech, NULL, 0 };
+ return gp11_session_encrypt_full (session, key, &mech_args, input, n_input, n_result, NULL, err);
+}
+
+guchar*
+gp11_session_encrypt_full (GP11Session *session, GP11Object *key, GP11Mechanism *mech_args,
+ const guchar *input, gsize n_input, gsize *n_result,
+ GCancellable *cancellable, GError **err)
+{
+ GP11Module *module = NULL;
+ guchar *ret;
+
+ g_object_get (session, "module", &module, NULL);
+ g_return_val_if_fail (module != NULL, NULL);
+
+ ret = crypt_sync (session, key, mech_args, input, n_input, n_result, cancellable, err,
+ module->funcs->C_EncryptInit, module->funcs->C_Encrypt);
+
+ g_object_unref (module);
+ return ret;
+}
+
+void
+gp11_session_encrypt_async (GP11Session *session, GP11Object *key, GP11Mechanism *mech_args,
+ const guchar *input, gsize n_input, GCancellable *cancellable,
+ GAsyncReadyCallback callback, gpointer user_data)
+{
+ GP11Module *module = NULL;
+ g_object_get (session, "module", &module, NULL);
+ g_return_if_fail (module != NULL);
+
+ crypt_async (session, key, mech_args, input, n_input, cancellable, callback, user_data,
+ module->funcs->C_EncryptInit, module->funcs->C_Encrypt);
+
+ g_object_unref (module);
+}
+
+guchar*
+gp11_session_encrypt_finish (GP11Session *session, GAsyncResult *result, gsize *n_result,
+ GError **err)
+{
+ return crypt_finish (session, result, n_result, err);
+}
+
+guchar*
+gp11_session_decrypt (GP11Session *session, GP11Object *key, guint mech_type, const guchar *input,
+ gsize n_input, gsize *n_result, GError **err)
+{
+ GP11Mechanism mech_args = { mech_type, NULL, 0 };
+ return gp11_session_decrypt_full (session, key, &mech_args, input, n_input, n_result, NULL, err);
+}
+
+guchar*
+gp11_session_decrypt_full (GP11Session *session, GP11Object *key, GP11Mechanism *mech_args,
+ const guchar *input, gsize n_input, gsize *n_result,
+ GCancellable *cancellable, GError **err)
+{
+ GP11Module *module = NULL;
+ guchar *ret;
+
+ g_object_get (session, "module", &module, NULL);
+ g_return_val_if_fail (module != NULL, NULL);
+
+ ret = crypt_sync (session, key, mech_args, input, n_input, n_result, cancellable, err,
+ module->funcs->C_DecryptInit, module->funcs->C_Decrypt);
+ g_object_unref (module);
+ return ret;
+}
+
+void
+gp11_session_decrypt_async (GP11Session *session, GP11Object *key, GP11Mechanism *mech_args,
+ const guchar *input, gsize n_input, GCancellable *cancellable,
+ GAsyncReadyCallback callback, gpointer user_data)
+{
+ GP11Module *module = NULL;
+ g_object_get (session, "module", &module, NULL);
+ g_return_if_fail (module != NULL);
+
+ crypt_async (session, key, mech_args, input, n_input, cancellable, callback, user_data,
+ module->funcs->C_DecryptInit, module->funcs->C_Decrypt);
+ g_object_unref (module);
+}
+
+guchar*
+gp11_session_decrypt_finish (GP11Session *session, GAsyncResult *result,
+ gsize *n_result, GError **err)
+{
+ return crypt_finish (session, result, n_result, err);
+}
+
+guchar*
+gp11_session_sign (GP11Session *session, GP11Object *key, guint mech_type, const guchar *input,
+ gsize n_input, gsize *n_result, GError **err)
+{
+ GP11Mechanism mech_args = { mech_type, NULL, 0 };
+ return gp11_session_sign_full (session, key, &mech_args, input, n_input, n_result, NULL, err);
+}
+
+guchar*
+gp11_session_sign_full (GP11Session *session, GP11Object *key, GP11Mechanism *mech_args,
+ const guchar *input, gsize n_input, gsize *n_result,
+ GCancellable *cancellable, GError **err)
+{
+ GP11Module *module = NULL;
+ guchar *ret;
+
+ g_object_get (session, "module", &module, NULL);
+ g_return_val_if_fail (module != NULL, NULL);
+
+ return crypt_sync (session, key, mech_args, input, n_input, n_result, cancellable, err,
+ module->funcs->C_SignInit, module->funcs->C_Sign);
+ g_object_unref (module);
+ return ret;
+}
+
+void
+gp11_session_sign_async (GP11Session *session, GP11Object *key, GP11Mechanism *mech_args,
+ const guchar *input, gsize n_input, GCancellable *cancellable,
+ GAsyncReadyCallback callback, gpointer user_data)
+{
+ GP11Module *module = NULL;
+ g_object_get (session, "module", &module, NULL);
+ g_return_if_fail (module != NULL);
+
+ crypt_async (session, key, mech_args, input, n_input, cancellable, callback, user_data,
+ module->funcs->C_SignInit, module->funcs->C_Sign);
+ g_object_unref (module);
+}
+
+guchar*
+gp11_session_sign_finish (GP11Session *session, GAsyncResult *result,
+ gsize *n_result, GError **err)
+{
+ return crypt_finish (session, result, n_result, err);
+}
+
+
+typedef struct _Verify {
+ GP11Arguments base;
+
+ /* Input */
+ CK_OBJECT_HANDLE key;
+ CK_MECHANISM mech;
+ guchar *input;
+ CK_ULONG n_input;
+ guchar *signature;
+ CK_ULONG n_signature;
+
+} Verify;
+
+static void
+free_verify (Verify *args)
+{
+ g_free (args->input);
+ g_free (args->signature);
+ g_free (args->mech.pParameter);
+}
+
+static CK_RV
+perform_verify (Verify *args)
+{
+ CK_RV rv;
+
+ /* Initialize the crypt operation */
+ rv = (args->base.pkcs11->C_VerifyInit) (args->base.handle, &args->mech, args->key);
+ if (rv != CKR_OK)
+ return rv;
+
+ /* Do the actual verify */
+ return (args->base.pkcs11->C_Verify) (args->base.handle, args->input, args->n_input,
+ args->signature, args->n_signature);
+}
+
+gboolean
+gp11_session_verify (GP11Session *session, GP11Object *key, guint mech_type, const guchar *input,
+ gsize n_input, const guchar *signature, gsize n_signature, GError **err)
+{
+ GP11Mechanism mech_args = { mech_type, NULL, 0 };
+ return gp11_session_verify_full (session, key, &mech_args, input, n_input,
+ signature, n_signature, NULL, err);
+}
+
+gboolean
+gp11_session_verify_full (GP11Session *session, GP11Object *key, GP11Mechanism *mech_args,
+ const guchar *input, gsize n_input, const guchar *signature,
+ gsize n_signature, GCancellable *cancellable, GError **err)
+{
+ Verify args;
+
+ g_return_val_if_fail (GP11_IS_OBJECT (key), FALSE);
+ g_return_val_if_fail (mech_args, FALSE);
+
+ memset (&args, 0, sizeof (args));
+ g_object_get (key, "handle", &args.key, NULL);
+ g_return_val_if_fail (args.key != 0, FALSE);
+
+ args.mech.mechanism = mech_args->type;
+ args.mech.pParameter = mech_args->parameter;
+ args.mech.ulParameterLen = mech_args->n_parameter;
+
+ /* No need to copy in this case */
+ args.input = (guchar*)input;
+ args.n_input = n_input;
+ args.signature = (guchar*)signature;
+ args.n_signature = n_signature;
+
+ return _gp11_call_sync (session, perform_verify, &args, cancellable, err);
+}
+
+void
+gp11_session_verify_async (GP11Session *session, GP11Object *key, GP11Mechanism *mech_args,
+ const guchar *input, gsize n_input, const guchar *signature,
+ gsize n_signature, GCancellable *cancellable,
+ GAsyncReadyCallback callback, gpointer user_data)
+{
+ Verify *args = _gp11_call_async_prep (session, perform_verify, sizeof (*args), free_verify);
+
+ g_return_if_fail (GP11_IS_OBJECT (key));
+ g_return_if_fail (mech_args);
+
+ g_object_get (key, "handle", &args->key, NULL);
+ g_return_if_fail (args->key != 0);
+
+ args->mech.mechanism = mech_args->type;
+ args->mech.pParameter = mech_args->parameter && mech_args->n_parameter ?
+ g_memdup (mech_args->parameter, mech_args->n_parameter) : NULL;
+ args->mech.ulParameterLen = mech_args->n_parameter;
+
+ args->input = input && n_input ? g_memdup (input, n_input) : NULL;
+ args->n_input = n_input;
+ args->signature = signature && n_signature ? g_memdup (signature, n_signature) : NULL;
+ args->n_input = n_signature;
+
+ _gp11_call_async_go (args, cancellable, callback, user_data);
+}
+
+gboolean
+gp11_session_verify_finish (GP11Session *session, GAsyncResult *result, GError **err)
+{
+ return _gp11_call_basic_finish (session, result, err);
+}
+
+#endif /* UNTESTED */
diff --git a/gp11/gp11-slot.c b/gp11/gp11-slot.c
new file mode 100644
index 00000000..04e6d32a
--- /dev/null
+++ b/gp11/gp11-slot.c
@@ -0,0 +1,436 @@
+
+#include "config.h"
+
+#include "gp11.h"
+#include "gp11-private.h"
+
+#include <string.h>
+
+enum {
+ PROP_0,
+ PROP_MODULE,
+ PROP_HANDLE
+};
+
+G_DEFINE_TYPE (GP11Slot, gp11_slot, G_TYPE_OBJECT);
+
+/* ----------------------------------------------------------------------------
+ * OBJECT
+ */
+
+static void
+gp11_slot_init (GP11Slot *slot)
+{
+
+}
+
+static void
+gp11_slot_get_property (GObject *obj, guint prop_id, GValue *value,
+ GParamSpec *pspec)
+{
+ GP11Slot *slot = GP11_SLOT (obj);
+
+ switch (prop_id) {
+ case PROP_MODULE:
+ g_value_set_object (value, slot->module);
+ break;
+ case PROP_HANDLE:
+ g_value_set_uint (value, slot->handle);
+ break;
+ }
+}
+
+static void
+gp11_slot_set_property (GObject *obj, guint prop_id, const GValue *value,
+ GParamSpec *pspec)
+{
+ GP11Slot *slot = GP11_SLOT (obj);
+
+ switch (prop_id) {
+ case PROP_MODULE:
+ g_return_if_fail (!slot->module);
+ slot->module = g_value_get_object (value);
+ g_return_if_fail (slot->module);
+ g_object_ref (slot->module);
+ break;
+ case PROP_HANDLE:
+ g_return_if_fail (!slot->handle);
+ slot->handle = g_value_get_uint (value);
+ break;
+ }
+}
+
+static void
+gp11_slot_dispose (GObject *obj)
+{
+ GP11Slot *slot = GP11_SLOT (obj);
+
+ if (slot->module)
+ g_object_unref (slot->module);
+ slot->module = NULL;
+
+ G_OBJECT_CLASS (gp11_slot_parent_class)->dispose (obj);
+}
+
+static void
+gp11_slot_finalize (GObject *obj)
+{
+ GP11Slot *slot = GP11_SLOT (obj);
+
+ g_assert (slot->module == NULL);
+ slot->handle = 0;
+
+ G_OBJECT_CLASS (gp11_slot_parent_class)->finalize (obj);
+}
+
+
+static void
+gp11_slot_class_init (GP11SlotClass *klass)
+{
+ GObjectClass *gobject_class = (GObjectClass*)klass;
+ gp11_slot_parent_class = g_type_class_peek_parent (klass);
+
+ gobject_class->get_property = gp11_slot_get_property;
+ gobject_class->set_property = gp11_slot_set_property;
+ gobject_class->dispose = gp11_slot_dispose;
+ gobject_class->finalize = gp11_slot_finalize;
+
+ g_object_class_install_property (gobject_class, PROP_MODULE,
+ g_param_spec_object ("module", "Module", "PKCS11 Module",
+ GP11_TYPE_MODULE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property (gobject_class, PROP_HANDLE,
+ g_param_spec_uint ("handle", "Handle", "PKCS11 Slot ID",
+ 0, G_MAXUINT, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+}
+
+/* ----------------------------------------------------------------------------
+ * PUBLIC
+ */
+
+void
+gp11_slot_info_free (GP11SlotInfo *slot_info)
+{
+ if (!slot_info)
+ return;
+ g_free (slot_info->slot_description);
+ g_free (slot_info->manufacturer_id);
+ g_free (slot_info);
+}
+
+void
+gp11_token_info_free (GP11TokenInfo *token_info)
+{
+ if (!token_info)
+ return;
+ g_free (token_info->label);
+ g_free (token_info->manufacturer_id);
+ g_free (token_info->model);
+ g_free (token_info->serial_number);
+ g_free (token_info);
+}
+
+void
+gp11_mechanism_info_free (GP11MechanismInfo *mech_info)
+{
+ if (!mech_info)
+ return;
+ g_free (mech_info);
+}
+
+GP11SlotInfo*
+gp11_slot_get_info (GP11Slot *slot)
+{
+ GP11SlotInfo *slotinfo;
+ CK_SLOT_INFO info;
+ CK_RV rv;
+
+ g_return_val_if_fail (GP11_IS_SLOT (slot), NULL);
+ g_return_val_if_fail (GP11_IS_MODULE (slot->module), NULL);
+ g_return_val_if_fail (slot->module->funcs, NULL);
+
+ memset (&info, 0, sizeof (info));
+ rv = (slot->module->funcs->C_GetSlotInfo) (slot->handle, &info);
+ if (rv != CKR_OK) {
+ g_warning ("couldn't get slot info: %s", gp11_message_from_rv (rv));
+ return NULL;
+ }
+
+ slotinfo = g_new0 (GP11SlotInfo, 1);
+ slotinfo->slot_description = gp11_string_from_chars (info.slotDescription,
+ sizeof (info.slotDescription));
+ slotinfo->manufacturer_id = gp11_string_from_chars (info.manufacturerID,
+ sizeof (info.manufacturerID));
+ slotinfo->flags = info.flags;
+ slotinfo->hardware_version_major = info.hardwareVersion.major;
+ slotinfo->hardware_version_minor = info.hardwareVersion.minor;
+ slotinfo->firmware_version_major = info.firmwareVersion.major;
+ slotinfo->firmware_version_minor = info.firmwareVersion.minor;
+
+ return slotinfo;
+}
+
+GP11TokenInfo*
+gp11_slot_get_token_info (GP11Slot *slot)
+{
+ GP11TokenInfo *tokeninfo;
+ CK_TOKEN_INFO info;
+ gchar *string;
+ struct tm tm;
+ CK_RV rv;
+
+ g_return_val_if_fail (GP11_IS_SLOT (slot), NULL);
+ g_return_val_if_fail (GP11_IS_MODULE (slot->module), NULL);
+ g_return_val_if_fail (slot->module->funcs, NULL);
+
+ memset (&info, 0, sizeof (info));
+ rv = (slot->module->funcs->C_GetTokenInfo) (slot->handle, &info);
+ if (rv != CKR_OK) {
+ g_warning ("couldn't get slot info: %s", gp11_message_from_rv (rv));
+ return NULL;
+ }
+
+ tokeninfo = g_new0 (GP11TokenInfo, 1);
+ tokeninfo->label = gp11_string_from_chars (info.label, sizeof (info.label));
+ tokeninfo->model = gp11_string_from_chars (info.model, sizeof (info.model));
+ tokeninfo->manufacturer_id = gp11_string_from_chars (info.manufacturerID,
+ sizeof (info.manufacturerID));
+ tokeninfo->serial_number = gp11_string_from_chars (info.serialNumber,
+ sizeof (info.serialNumber));
+ tokeninfo->flags = info.flags;
+ tokeninfo->max_session_count = info.ulMaxSessionCount;
+ tokeninfo->session_count = info.ulSessionCount;
+ tokeninfo->max_rw_session_count = info.ulMaxRwSessionCount;
+ tokeninfo->rw_session_count = info.ulRwSessionCount;
+ tokeninfo->max_pin_len = info.ulMaxPinLen;
+ tokeninfo->min_pin_len = info.ulMinPinLen;
+ tokeninfo->total_public_memory = info.ulTotalPublicMemory;
+ tokeninfo->total_private_memory = info.ulTotalPrivateMemory;
+ tokeninfo->free_private_memory = info.ulFreePrivateMemory;
+ tokeninfo->free_public_memory = info.ulFreePublicMemory;
+ tokeninfo->hardware_version_major = info.hardwareVersion.major;
+ tokeninfo->hardware_version_minor = info.hardwareVersion.minor;
+ tokeninfo->firmware_version_major = info.firmwareVersion.major;
+ tokeninfo->firmware_version_minor = info.firmwareVersion.minor;
+
+ /* Parse the time into seconds since epoch */
+ if (info.flags & CKF_CLOCK_ON_TOKEN) {
+ string = g_strndup ((gchar*)info.utcTime, MIN (14, sizeof (info.utcTime)));
+ if (!strptime (string, "%Y%m%d%H%M%S", &tm))
+ tokeninfo->utc_time = -1;
+ else
+ tokeninfo->utc_time = mktime (&tm);
+ } else {
+ tokeninfo->utc_time = -1;
+ }
+
+ return tokeninfo;
+}
+
+GSList*
+gp11_slot_get_mechanisms (GP11Slot *slot)
+{
+ CK_MECHANISM_TYPE_PTR mech_list;
+ CK_ULONG count, i;
+ GSList *result;
+ CK_RV rv;
+
+ g_return_val_if_fail (GP11_IS_SLOT (slot), NULL);
+ g_return_val_if_fail (GP11_IS_MODULE (slot->module), NULL);
+ g_return_val_if_fail (slot->module->funcs, NULL);
+
+ rv = (slot->module->funcs->C_GetMechanismList) (slot->handle, NULL, &count);
+ if (rv != CKR_OK) {
+ g_warning ("couldn't get mechanism count: %s", gp11_message_from_rv (rv));
+ return NULL;
+ }
+
+ if (!count)
+ return NULL;
+
+ mech_list = g_new (CK_MECHANISM_TYPE, count);
+ rv = (slot->module->funcs->C_GetMechanismList) (slot->handle, mech_list, &count);
+ if (rv != CKR_OK) {
+ g_warning ("couldn't get mechanism list: %s", gp11_message_from_rv (rv));
+ g_free (mech_list);
+ return NULL;
+ }
+
+ result = NULL;
+ for (i = 0; i < count; ++i)
+ result = g_slist_prepend (result, GUINT_TO_POINTER (mech_list[i]));
+
+ g_free (mech_list);
+ return g_slist_reverse (result);
+
+}
+
+GP11MechanismInfo*
+gp11_slot_get_mechanism_info (GP11Slot *slot, guint mech_type)
+{
+ GP11MechanismInfo *mechinfo;
+ CK_MECHANISM_INFO info;
+ struct tm;
+ CK_RV rv;
+
+ g_return_val_if_fail (GP11_IS_SLOT (slot), NULL);
+ g_return_val_if_fail (GP11_IS_MODULE (slot->module), NULL);
+ g_return_val_if_fail (slot->module->funcs, NULL);
+
+ memset (&info, 0, sizeof (info));
+ rv = (slot->module->funcs->C_GetMechanismInfo) (slot->handle, mech_type, &info);
+ if (rv != CKR_OK) {
+ g_warning ("couldn't get mechanism info: %s", gp11_message_from_rv (rv));
+ return NULL;
+ }
+
+ mechinfo = g_new0 (GP11MechanismInfo, 1);
+ mechinfo->flags = info.flags;
+ mechinfo->max_key_size = info.ulMaxKeySize;
+ mechinfo->min_key_size = info.ulMinKeySize;
+
+ return mechinfo;
+}
+
+#if UNIMPLEMENTED
+
+typedef struct InitToken {
+ GP11Arguments base;
+ const guchar *pin;
+ gsize length;
+ const gchar *label;
+} InitToken;
+
+static CK_RV
+perform_init_token (InitToken *args)
+{
+ return (args->base.pkcs11->C_InitToken) (args->base.handle,
+ args->pin, args->length,
+ args->label);
+}
+
+gboolean
+gp11_slot_init_token (GP11Slot *slot, const guchar *pin, gsize length,
+ const gchar *label, GCancellable *cancellable,
+ GError **err)
+{
+ InitToken args = { GP11_ARGUMENTS_INIT, pin, length, label };
+ return _gp11_call_sync (slot, perform_init_token, &args, err);
+}
+
+void
+gp11_slot_init_token_async (GP11Slot *slot, const guchar *pin, gsize length,
+ const gchar *label, GCancellable *cancellable,
+ GAsyncReadyCallback callback, gpointer user_data)
+{
+ InitToken* args = _gp11_call_async_prep (slot, perform_init_token,
+ sizeof (*args));
+
+ args->pin = pin;
+ args->length = length;
+ args->label = label;
+
+ _gp11_call_async_go (args, cancellable, callback, user_data);
+}
+
+gboolean
+gp11_slot_init_token_finish (GP11Slot *slot, GAsyncResult *result, GError **err)
+{
+ return _gp11_call_basic_finish (slot, result, err);
+}
+
+#endif /* UNIMPLEMENTED */
+
+typedef struct OpenSession {
+ GP11Arguments base;
+ guint flags;
+ CK_SESSION_HANDLE session;
+} OpenSession;
+
+static CK_RV
+perform_open_session (OpenSession *args)
+{
+ return (args->base.pkcs11->C_OpenSession) (args->base.handle,
+ args->flags | CKF_SERIAL_SESSION,
+ NULL, NULL, &args->session);
+}
+
+GP11Session*
+gp11_slot_open_session (GP11Slot *slot, guint flags, GError **err)
+{
+ return gp11_slot_open_session_full (slot, flags, NULL, err);
+}
+
+GP11Session*
+gp11_slot_open_session_full (GP11Slot *slot, guint flags, GCancellable *cancellable, GError **err)
+{
+ OpenSession args = { GP11_ARGUMENTS_INIT, flags, 0 };
+
+ if (!_gp11_call_sync (slot, perform_open_session, &args, cancellable, err))
+ return FALSE;
+
+ return gp11_session_from_handle (slot, args.session);
+}
+
+void
+gp11_slot_open_session_async (GP11Slot *slot, guint flags, GCancellable *cancellable,
+ GAsyncReadyCallback callback, gpointer user_data)
+{
+ OpenSession *args = _gp11_call_async_prep (slot, perform_open_session,
+ sizeof (*args), NULL);
+
+ args->flags = flags;
+ args->session = 0;
+
+ _gp11_call_async_go (args, cancellable, callback, user_data);
+}
+
+GP11Session*
+gp11_slot_open_session_finish (GP11Slot *slot, GAsyncResult *result, GError **err)
+{
+ OpenSession *args;
+
+ if (!_gp11_call_basic_finish (slot, result, err))
+ return NULL;
+
+ args = _gp11_call_arguments (result, OpenSession);
+ return gp11_session_from_handle (slot, args->session);
+}
+
+#if UNIMPLEMENTED
+
+static CK_RV
+perform_close_all_sessions (GP11Arguments *args)
+{
+ return (args->pkcs11->C_CloseAllSessions) (args->handle);
+}
+
+gboolean
+gp11_slot_close_all_sessions (GP11Slot *slot, GError **err)
+{
+ return gp11_slot_close_all_sessions_full (slot, NULL, err);
+}
+
+gboolean
+gp11_slot_close_all_sessions_full (GP11Slot *slot, GCancellable *cancellable, GError **err)
+{
+ GP11Arguments args = GP11_ARGUMENTS_INIT;
+ return _gp11_call_sync (slot, perform_close_all_sessions, &args, cancellable, err);
+}
+
+void
+gp11_slot_close_all_sessions_async (GP11Slot *slot, GCancellable *cancellable,
+ GAsyncReadyCallback callback, gpointer user_data)
+{
+ GP11Arguments *args = _gp11_call_async_prep (slot, perform_close_all_sessions, 0, NULL);
+ _gp11_call_async_go (args, cancellable, callback, user_data);
+}
+
+gboolean
+gp11_slot_close_all_sessions_finish (GP11Slot *slot, GAsyncResult *result,
+ GError **err)
+{
+ return _gp11_call_basic_finish (slot, result, err);
+}
+
+#endif
diff --git a/gp11/gp11.h b/gp11/gp11.h
new file mode 100644
index 00000000..03c99b74
--- /dev/null
+++ b/gp11/gp11.h
@@ -0,0 +1,1294 @@
+#ifndef GP11_H_
+#define GP11_H_
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gio/gio.h>
+
+#include "pkcs11.h"
+
+G_BEGIN_DECLS
+
+#define GP11_VENDOR_CODE 0x47503131 /* GP11 */
+
+/* An error code which results from a failure to load the PKCS11 module */
+#define CKR_GP11_MODULE_PROBLEM (CKR_VENDOR_DEFINED | (GP11_VENDOR_CODE + 1))
+
+#define GP11_ERROR (gp11_get_error_quark ())
+
+GQuark gp11_get_error_quark (void);
+
+void gp11_list_unref_free (GList *reflist);
+
+const gchar* gp11_message_from_rv (CK_RV rv);
+
+gchar* gp11_string_from_chars (const guchar *data, gsize max);
+
+typedef struct GP11Mechanism {
+ guint type;
+ gpointer parameter;
+ gulong n_parameter;
+} GP11Mechanism;
+
+typedef struct GP11Attribute {
+ gulong type;
+ gpointer value;
+ gulong length;
+} GP11Attribute;
+
+/*
+ * Used with var args in place of a length to denote that this type
+ * of value follows.
+ */
+enum {
+ GP11_BOOLEAN = -1,
+ GP11_ULONG = -2,
+ GP11_STRING = -3,
+ GP11_DATE = -4
+};
+
+void gp11_attribute_init (GP11Attribute *attr,
+ guint attr_type,
+ gconstpointer value,
+ gsize length);
+
+void gp11_attribute_init_boolean (GP11Attribute *attr,
+ guint attr_type,
+ gboolean value);
+
+void gp11_attribute_init_date (GP11Attribute *attr,
+ guint attr_type,
+ const GDate *value);
+
+void gp11_attribute_init_ulong (GP11Attribute *attr,
+ guint attr_type,
+ gulong value);
+
+void gp11_attribute_init_string (GP11Attribute *attr,
+ guint attr_type,
+ const gchar *value);
+
+void gp11_attribute_init_copy (GP11Attribute *dest,
+ GP11Attribute *src);
+
+GP11Attribute* gp11_attribute_new (guint attr_type,
+ gpointer value,
+ gsize length);
+
+GP11Attribute* gp11_attribute_new_boolean (guint attr_type,
+ gboolean value);
+
+GP11Attribute* gp11_attribute_new_date (guint attr_type,
+ const GDate *value);
+
+GP11Attribute* gp11_attribute_new_ulong (guint attr_type,
+ gulong value);
+
+GP11Attribute* gp11_attribute_new_string (guint attr_type,
+ const gchar *value);
+
+gboolean gp11_attribute_get_boolean (GP11Attribute *attr);
+
+gulong gp11_attribute_get_ulong (GP11Attribute *attr);
+
+gchar* gp11_attribute_get_string (GP11Attribute *attr);
+
+GDate* gp11_attribute_get_date (GP11Attribute *attr);
+
+GP11Attribute* gp11_attribute_dup (GP11Attribute *attr);
+
+void gp11_attribute_clear (GP11Attribute *attr);
+
+void gp11_attribute_free (GP11Attribute *attr);
+
+typedef struct _GP11Attributes GP11Attributes;
+
+GP11Attributes* gp11_attributes_new (void);
+
+GP11Attributes* gp11_attributes_newv (guint attr_type, ...);
+
+GP11Attributes* gp11_attributes_new_valist (va_list va);
+
+void gp11_attributes_set_immutable (GP11Attributes *attrs);
+
+gboolean gp11_attributes_is_immutable (GP11Attributes *attrs);
+
+GP11Attribute* gp11_attributes_at (GP11Attributes *attrs,
+ guint index);
+
+void gp11_attributes_add (GP11Attributes *attrs,
+ GP11Attribute *attr);
+
+void gp11_attributes_add_data (GP11Attributes *attrs,
+ guint attr_type,
+ gconstpointer value,
+ gsize length);
+
+void gp11_attributes_add_boolean (GP11Attributes *attrs,
+ guint attr_type,
+ gboolean value);
+
+void gp11_attributes_add_string (GP11Attributes *attrs,
+ guint attr_type,
+ const gchar *string);
+
+void gp11_attributes_add_date (GP11Attributes *attrs,
+ guint attr_type,
+ const GDate *date);
+
+void gp11_attributes_add_ulong (GP11Attributes *attrs,
+ guint attr_type,
+ gulong value);
+
+GP11Attribute* gp11_attributes_find (GP11Attributes *attrs,
+ guint attr_type);
+
+gboolean gp11_attributes_find_boolean (GP11Attributes *attrs,
+ guint attr_type,
+ gboolean *value);
+
+gboolean gp11_attributes_find_ulong (GP11Attributes *attrs,
+ guint attr_type,
+ gulong *value);
+
+gboolean gp11_attributes_find_string (GP11Attributes *attrs,
+ guint attr_type,
+ gchar **value);
+
+gboolean gp11_attributes_find_date (GP11Attributes *attrs,
+ guint attr_type,
+ GDate **value);
+
+gulong gp11_attributes_count (GP11Attributes *attrs);
+
+void gp11_attributes_ref (GP11Attributes *attrs);
+
+void gp11_attributes_unref (GP11Attributes *attrs);
+
+/* -------------------------------------------------------------------------
+ * FORWARDS
+ */
+
+typedef struct _GP11Slot GP11Slot;
+typedef struct _GP11Module GP11Module;
+typedef struct _GP11Session GP11Session;
+typedef struct _GP11Object GP11Object;
+
+/* -------------------------------------------------------------------------
+ * MODULE
+ */
+
+typedef struct _GP11ModuleInfo {
+ guint pkcs11_version_major;
+ guint pkcs11_version_minor;
+
+ gchar *manufacturer_id;
+ guint32 flags;
+
+ gchar *library_description;
+ guint library_version_major;
+ guint library_version_minor;
+} GP11ModuleInfo;
+
+void gp11_module_info_free (GP11ModuleInfo *module_info);
+
+#define GP11_TYPE_MODULE (gp11_module_get_type())
+#define GP11_MODULE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GP11_TYPE_MODULE, GP11Module))
+#define GP11_MODULE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GP11_TYPE_MODULE, GP11Module))
+#define GP11_IS_MODULE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GP11_TYPE_MODULE))
+#define GP11_IS_MODULE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GP11_TYPE_MODULE))
+#define GP11_MODULE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GP11_TYPE_MODULE, GP11ModuleClass))
+
+typedef struct _GP11ModuleClass GP11ModuleClass;
+
+struct _GP11Module {
+ GObject parent;
+
+ gchar *path;
+ CK_FUNCTION_LIST_PTR funcs;
+};
+
+struct _GP11ModuleClass {
+ GObjectClass parent;
+};
+
+GType gp11_module_get_type (void) G_GNUC_CONST;
+
+GP11Module* gp11_module_initialize (const gchar *path,
+ GError **err);
+
+GP11ModuleInfo* gp11_module_get_info (GP11Module *module);
+
+GList* gp11_module_get_slots (GP11Module *module,
+ gboolean token_present);
+
+enum {
+ GP11_IS_STRING = -1,
+ GP11_IS_BOOLEAN = -2,
+ GP11_IS_DATE = -3,
+ GP11_IS_ULONG = -4
+};
+
+/* ------------------------------------------------------------------------
+ * SLOT
+ */
+
+typedef struct _GP11SlotInfo {
+ gchar *slot_description;
+ gchar *manufacturer_id;
+ guint32 flags;
+ guint hardware_version_major;
+ guint hardware_version_minor;
+ guint firmware_version_major;
+ guint firmware_version_minor;
+} GP11SlotInfo;
+
+void gp11_slot_info_free (GP11SlotInfo *slot_info);
+
+typedef struct _GP11TokenInfo {
+ gchar *label;
+ gchar *manufacturer_id;
+ gchar *model;
+ gchar *serial_number;
+ guint32 flags;
+ glong max_session_count;
+ glong session_count;
+ glong max_rw_session_count;
+ glong rw_session_count;
+ glong max_pin_len;
+ glong min_pin_len;
+ glong total_public_memory;
+ glong free_public_memory;
+ glong total_private_memory;
+ glong free_private_memory;
+ guint hardware_version_major;
+ guint hardware_version_minor;
+ guint firmware_version_major;
+ guint firmware_version_minor;
+ gint64 utc_time;
+} GP11TokenInfo;
+
+void gp11_token_info_free (GP11TokenInfo *token_info);
+
+typedef struct _GP11MechanismInfo {
+ gulong min_key_size;
+ gulong max_key_size;
+ guint32 flags;
+} GP11MechanismInfo;
+
+void gp11_mechanism_info_free (GP11MechanismInfo *mech_info);
+
+#define GP11_TYPE_SLOT (gp11_slot_get_type())
+#define GP11_SLOT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GP11_TYPE_SLOT, GP11Slot))
+#define GP11_SLOT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GP11_TYPE_SLOT, GP11Slot))
+#define GP11_IS_SLOT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GP11_TYPE_SLOT))
+#define GP11_IS_SLOT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GP11_TYPE_SLOT))
+#define GP11_SLOT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GP11_TYPE_SLOT, GP11SlotClass))
+
+typedef struct _GP11SlotClass GP11SlotClass;
+
+struct _GP11Slot {
+ GObject parent;
+
+ GP11Module *module;
+ CK_SLOT_ID handle;
+};
+
+struct _GP11SlotClass {
+ GObjectClass parent;
+
+ void (*slot_event) (GP11Slot *slot);
+};
+
+GType gp11_slot_get_type (void) G_GNUC_CONST;
+
+GP11SlotInfo* gp11_slot_get_info (GP11Slot *slot);
+
+GP11TokenInfo* gp11_slot_get_token_info (GP11Slot *slot);
+
+GSList* gp11_slot_get_mechanisms (GP11Slot *slot);
+
+GP11MechanismInfo* gp11_slot_get_mechanism_info (GP11Slot *slot,
+ guint32 mech_type);
+
+#if UNIMPLEMENTED
+
+gboolean gp11_slot_init_token (GP11Slot *slot,
+ const guchar *pin,
+ gsize length,
+ const gchar *label,
+ GError **err);
+
+
+void gp11_slot_init_token_async (GP11Slot *slot,
+ const guchar *pin,
+ gsize length,
+ const gchar *label,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean gp11_slot_init_token_finish (GP11Slot *slot,
+ GAsyncResult *result,
+ GError **err);
+
+#endif /* UNIMPLEMENTED */
+
+GP11Session* gp11_slot_open_session (GP11Slot *slot,
+ guint flags,
+ GError **err);
+
+GP11Session* gp11_slot_open_session_full (GP11Slot *slot,
+ guint flags,
+ GCancellable *cancellable,
+ GError **err);
+
+void gp11_slot_open_session_async (GP11Slot *slot,
+ guint flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+GP11Session* gp11_slot_open_session_finish (GP11Slot *slot,
+ GAsyncResult *result,
+ GError **err);
+
+/* ------------------------------------------------------------------------
+ * SESSION
+ */
+
+typedef struct _GP11SessionInfo {
+ guint32 slot_id;
+ guint32 state;
+ guint32 flags;
+ gulong device_error;
+} GP11SessionInfo;
+
+void gp11_session_info_free (GP11SessionInfo *session_info);
+
+#define GP11_TYPE_SESSION (gp11_session_get_type())
+#define GP11_SESSION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GP11_TYPE_SESSION, GP11Session))
+#define GP11_SESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GP11_TYPE_SESSION, GP11Session))
+#define GP11_IS_SESSION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GP11_TYPE_SESSION))
+#define GP11_IS_SESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GP11_TYPE_SESSION))
+#define GP11_SESSION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GP11_TYPE_SESSION, GP11SessionClass))
+
+typedef struct _GP11SessionClass GP11SessionClass;
+
+struct _GP11Session {
+ GObject parent;
+
+ GP11Module *module;
+ CK_SLOT_ID handle;
+};
+
+struct _GP11SessionClass {
+ GObjectClass parent;
+};
+
+GType gp11_session_get_type (void) G_GNUC_CONST;
+
+GP11Session* gp11_session_from_handle (GP11Slot *slot, CK_SESSION_HANDLE handle);
+
+GP11SessionInfo* gp11_session_get_info (GP11Session *session);
+
+#if UNIMPLEMENTED
+
+gboolean gp11_session_init_pin (GP11Session *session,
+ const guchar *pin,
+ gsize n_pin,
+ GError **err);
+
+void gp11_session_init_pin_async (GP11Session *session,
+ const guchar *pin,
+ gsize n_pin,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean gp11_session_init_pin_finish (GP11Session *session,
+ GAsyncResult *result,
+ GError **err);
+
+gboolean gp11_session_set_pin (GP11Session *session,
+ const guchar *old_pin,
+ gsize n_old_pin,
+ const guchar *new_pin,
+ gsize n_new_pin,
+ GError **err);
+
+void gp11_session_set_pin_async (GP11Session *session,
+ const guchar *old_pin,
+ gsize n_old_pin,
+ const guchar *new_pin,
+ gsize n_new_pin,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean gp11_session_set_pin_finish (GP11Session *session,
+ GAsyncResult *result,
+ GError **err);
+
+guchar* gp11_session_get_operation_state (GP11Session *session,
+ gsize *n_result,
+ GError **err);
+
+void gp11_session_get_operation_state_async (GP11Session *session,
+ gsize *n_result,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+guchar* gp11_session_get_operation_state_finish (GP11Session *session,
+ GAsyncResult *result,
+ gsize *n_result,
+ GError **err);
+
+gboolean gp11_session_set_operation_state (GP11Session *session,
+ const guchar *state,
+ gsize n_state,
+ GError **err);
+
+void gp11_session_set_operation_state_async (GP11Session *session,
+ const guchar *state,
+ gsize n_state,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean gp11_session_set_operation_state_finish (GP11Session *session,
+ GAsyncResult *result,
+ GError **err);
+
+#endif /* UNIMPLEMENTED */
+
+gboolean gp11_session_login (GP11Session *session,
+ guint32 user_type,
+ const guchar *pin,
+ gsize n_pin,
+ GError **err);
+
+gboolean gp11_session_login_full (GP11Session *session,
+ guint32 user_type,
+ const guchar *pin,
+ gsize n_pin,
+ GCancellable *cancellable,
+ GError **err);
+
+void gp11_session_login_async (GP11Session *session,
+ guint32 user_type,
+ const guchar *pin,
+ gsize n_pin,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean gp11_session_login_finish (GP11Session *session,
+ GAsyncResult *result,
+ GError **err);
+
+gboolean gp11_session_logout (GP11Session *session,
+ GError **err);
+
+gboolean gp11_session_logout_full (GP11Session *session,
+ GCancellable *cancellable,
+ GError **err);
+
+void gp11_session_logout_async (GP11Session *session,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean gp11_session_logout_finish (GP11Session *session,
+ GAsyncResult *result,
+ GError **err);
+
+GP11Object* gp11_session_create_object (GP11Session *session,
+ GError **err,
+ ...);
+
+GP11Object* gp11_session_create_object_full (GP11Session *session,
+ GP11Attributes *attrs,
+ GCancellable *cancellable,
+ GError **err);
+
+void gp11_session_create_object_async (GP11Session *session,
+ GP11Attributes *attrs,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+GP11Object* gp11_session_create_object_finish (GP11Session *session,
+ GAsyncResult *result,
+ GError **err);
+
+GList* gp11_session_find_objects (GP11Session *session,
+ GError **err,
+ ...);
+
+GList* gp11_session_find_objects_full (GP11Session *session,
+ GP11Attributes *attrs,
+ GCancellable *cancellable,
+ GError **err);
+
+void gp11_session_find_objects_async (GP11Session *session,
+ GP11Attributes *attrs,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+GList* gp11_session_find_objects_finish (GP11Session *session,
+ GAsyncResult *result,
+ GError **err);
+
+#if UNIMPLEMENTED
+
+GP11Object* gp11_session_generate_key (GP11Session *session,
+ GP11Mechanism *mechanism,
+ GError **err,
+ ...);
+
+void gp11_session_generate_key_async (GP11Session *session,
+ GP11Mechanism *mechanism,
+ GAsyncReadyCallback callback,
+ gpointer user_data,
+ ...);
+
+GP11Object* gp11_session_generate_key_finish (GP11Session *session,
+ GAsyncResult *result,
+ GError **err,
+ ...);
+
+gboolean gp11_session_generate_key_pair (GP11Session *session,
+ GP11Mechanism *mechanism,
+ GP11Object **public_key,
+ GP11Object **private_key,
+ GError **err,
+ ...);
+
+void gp11_session_generate_key_pair_async (GP11Session *session,
+ GP11Mechanism *mechanism,
+ GAsyncReadyCallback callback,
+ gpointer user_data,
+ ...);
+
+gboolean gp11_session_generate_key_pair_finish (GP11Session *session,
+ GAsyncResult *result,
+ GP11Object **public_key,
+ GP11Object **private_key,
+ GError **err,
+ ...);
+
+gboolean gp11_session_seed_random (GP11Session *session,
+ const guchar *seed,
+ gsize n_seed,
+ GError **err);
+
+void gp11_session_seed_random_async (GP11Session *session,
+ const guchar *seed,
+ gsize n_seed,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean gp11_session_seed_random_finish (GP11Session *session,
+ GAsyncResult *result,
+ GError **err);
+
+guchar* gp11_session_generate_random (GP11Session *session,
+ gsize n_random,
+ GError **err);
+
+void gp11_session_generate_random_async (GP11Session *session,
+ gsize n_random,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+guchar* gp11_session_generate_random_finish (GP11Session *session,
+ GAsyncResult *result,
+ GError **err);
+
+
+#endif /* UNIMPLEMENTED */
+
+#if UNTESTED
+
+guchar* gp11_session_encrypt (GP11Session *session,
+ GP11Object *key,
+ guint mech,
+ const guchar *input,
+ gsize n_input,
+ gsize *n_result,
+ GError **err);
+
+guchar* gp11_session_encrypt_full (GP11Session *session,
+ GP11Object *key,
+ GP11Mechanism *mech_args,
+ const guchar *input,
+ gsize n_input,
+ gsize *n_result,
+ GCancellable *cancellable,
+ GError **err);
+
+void gp11_session_encrypt_async (GP11Session *session,
+ GP11Object *key,
+ GP11Mechanism *mech_args,
+ const guchar *input,
+ gsize n_input,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+guchar* gp11_session_encrypt_finish (GP11Session *session,
+ GAsyncResult *result,
+ gsize *n_result,
+ GError **err);
+
+#endif /* UNTESTED */
+
+#if UNIMPLEMENTED
+
+GP11Processor* gp11_session_batch_encrypt (GP11Session *session,
+ GP11Object *key,
+ GP11Mechanism *mech_args,
+ GCancellable *cancellable,
+ GError **err);
+
+void gp11_session_batch_encrypt_async (GP11Session *session,
+ GP11Object *key,
+ GP11Mechanism *mech_args,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+GP11Processor* gp11_session_batch_encrypt_finish (GP11Session *session,
+ GP11Object *key,
+ GAsyncResult *result,
+ GError **err);
+
+#endif /* UNIMPLEMENTED */
+
+#if UNTESTED
+guchar* gp11_session_decrypt (GP11Session *session,
+ GP11Object *key,
+ guint mech_type,
+ const guchar *input,
+ gsize n_input,
+ gsize *n_result,
+ GError **err);
+
+guchar* gp11_session_decrypt_full (GP11Session *session,
+ GP11Object *key,
+ GP11Mechanism *mech_args,
+ const guchar *input,
+ gsize n_input,
+ gsize *n_result,
+ GCancellable *cancellable,
+ GError **err);
+
+void gp11_session_decrypt_async (GP11Session *session,
+ GP11Object *key,
+ GP11Mechanism *mech_args,
+ const guchar *input,
+ gsize n_input,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+guchar* gp11_session_decrypt_finish (GP11Session *session,
+ GAsyncResult *result,
+ gsize *n_result,
+ GError **err);
+
+#endif /* UNTESTED */
+
+#if UNIMPLEMENTED
+
+GP11Processor* gp11_session_batch_decrypt (GP11Session *session,
+ GP11Object *key,
+ GP11Mechanism *mech_args,
+ GCancellable *cancellable,
+ GError **err);
+
+void gp11_session_batch_decrypt_async (GP11Session *session,
+ GP11Object *key,
+ GP11Mechanism *mech_args,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+GP11Processor* gp11_session_batch_decrypt_finish (GP11Session *session,
+ GAsyncResult *result,
+ GError **err);
+
+guchar* gp11_session_digest (GP11Session *session,
+ guint mech_type,
+ const guchar *input,
+ gsize n_input,
+ gsize *n_result,
+ GError **err);
+
+guchar* gp11_session_digest_full (GP11Session *session,
+ GP11Mechanism *mech_args,
+ const guchar *input,
+ gsize n_input,
+ gsize *n_result,
+ GCancellable *cancellable,
+ GError **err);
+
+void gp11_session_digest_async (GP11Session *session,
+ GP11Mechanism *mech_args,
+ const guchar *input,
+ gsize n_input,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+guchar* gp11_session_digest_finish (GP11Session *session,
+ GAsyncResult *result,
+ gsize *n_result,
+ GError **err);
+
+GP11Processor* gp11_session_batch_digest (GP11Session *session,
+ GP11Mechanism *mech_args,
+ GCancellable *cancellable,
+ GError **err);
+
+void gp11_session_batch_digest_async (GP11Session *session,
+ GP11Mechanism *mech_args,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+GP11Processor* gp11_session_batch_digest_finish (GP11Session *session,
+ GAsyncResult *result,
+ GError **err);
+
+GP11Processor* gp11_session_batch_digest_encrypt (GP11Session *session,
+ GP11Object *key,
+ GP11Mechanism *digest_mech,
+ GP11Mechanism *encrypt_mech,
+ GCancellable *cancellable,
+ GError **err);
+
+void gp11_session_batch_digest_encrypt_async (GP11Session *session,
+ GP11Object *key,
+ GP11Mechanism *digest_mech,
+ GP11Mechanism *encrypt_mech,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+GP11Processor* gp11_session_batch_digest_encrypt_finish (GP11Session *session,
+ GAsyncResult *result,
+ GError **err);
+
+GP11Processor* gp11_session_batch_digest_decrypt (GP11Session *session,
+ GP11Object *key,
+ GP11Mechanism *digest_mech,
+ GP11Mechanism *decrypt_mech,
+ GCancellable *cancellable,
+ GError **err);
+
+void gp11_session_batch_digest_decrypt_async (GP11Session *session,
+ GP11Object *key,
+ GP11Mechanism *digest_mech,
+ GP11Mechanism *decrypt_mech,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+GP11Processor* gp11_session_batch_digest_decrypt_finish (GP11Session *session,
+ GAsyncResult *result,
+ GError **err);
+
+GP11Processor* gp11_session_batch_decrypt_verify (GP11Session *session,
+ GP11Object *key,
+ GP11Mechanism *decrypt_mech,
+ GP11Mechanism *verify_mech,
+ GCancellable *cancellable,
+ GError **err);
+
+void gp11_session_batch_decrypt_verify_async (GP11Session *session,
+ GP11Object *key,
+ GP11Mechanism *decrypt_mech,
+ GP11Mechanism *verify_mech,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+GP11Processor* gp11_session_batch_decrypt_verify_finish (GP11Session *session,
+ GAsyncResult *result,
+ GError **err);
+
+#endif /* UNIMPLEMENTED */
+
+#if UNTESTED
+
+guchar* gp11_session_sign (GP11Session *session,
+ GP11Object *key,
+ guint mech_type,
+ const guchar *input,
+ gsize n_input,
+ gsize *n_result,
+ GError **err);
+
+guchar* gp11_session_sign_full (GP11Session *session,
+ GP11Object *key,
+ GP11Mechanism *mech_args,
+ const guchar *input,
+ gsize n_input,
+ gsize *n_result,
+ GCancellable *cancellable,
+ GError **err);
+
+void gp11_session_sign_async (GP11Session *session,
+ GP11Object *key,
+ GP11Mechanism *mech_args,
+ const guchar *input,
+ gsize n_input,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+guchar* gp11_session_sign_finish (GP11Session *session,
+ GAsyncResult *result,
+ gsize *n_result,
+ GError **err);
+
+#endif /* UNTESTED */
+
+#if UNIMPLEMENTED
+
+GP11Processor* gp11_session_batch_sign (GP11Session *session,
+ GP11Object *key,
+ GP11Mechanism *mech_args,
+ GCancellable *cancellable,
+ GError **err);
+
+void gp11_session_batch_sign_async (GP11Session *session,
+ GP11Object *key,
+ GP11Mechanism *mech_args,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+GP11Processor* gp11_session_batch_sign_finish (GP11Session *session,
+ GAsyncResult *result,
+ GError **err);
+
+GP11Processor* gp11_session_batch_sign_encrypt (GP11Session *session,
+ GP11Object *key,
+ GP11Mechanism *sign_mech,
+ GP11Mechanism *encrypt_mech,
+ GCancellable *cancellable,
+ GError **err);
+
+void gp11_session_batch_sign_encrypt_async (GP11Session *session,
+ GP11Object *key,
+ GP11Mechanism *sign_mechanism,
+ GP11Mechanism *encrypt_mech,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+GP11Processor* gp11_session_batch_sign_encrypt_finish (GP11Session *session,
+ GAsyncResult *result,
+ GError **err);
+
+guchar* gp11_session_sign_recover (GP11Session *session,
+ GP11Object *key,
+ guint mech_type,
+ const guchar *input,
+ gsize n_input,
+ gsize *n_result,
+ GError **err);
+
+guchar* gp11_session_sign_recover_full (GP11Session *session,
+ GP11Object *key,
+ GP11Mechanism *mech_args,
+ const guchar *input,
+ gsize n_input,
+ gsize *n_result,
+ GCancellable *cancellable,
+ GError **err);
+
+void gp11_session_sign_recover_async (GP11Session *session,
+ GP11Object *key,
+ GP11Mechanism *mech_args,
+ const guchar *input,
+ gsize n_input,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+guchar* gp11_session_sign_recover_finish (GP11Session *session,
+ GAsyncResult *result,
+ gsize *n_result,
+ GError **err);
+
+#endif /* UNIMPLEMENTED */
+
+#if UNTESTED
+
+gboolean gp11_session_verify (GP11Session *session,
+ GP11Object *key,
+ guint mech_type,
+ const guchar *input,
+ gsize n_input,
+ const guchar *signature,
+ gsize n_signature,
+ GError **err);
+
+gboolean gp11_session_verify_full (GP11Session *session,
+ GP11Object *key,
+ GP11Mechanism *mech_args,
+ const guchar *input,
+ gsize n_input,
+ const guchar *signature,
+ gsize n_signature,
+ GCancellable *cancellable,
+ GError **err);
+
+void gp11_session_verify_async (GP11Session *session,
+ GP11Object *key,
+ GP11Mechanism *mechanism,
+ const guchar *input,
+ gsize n_input,
+ const guchar *signature,
+ gsize n_signature,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean gp11_session_verify_finish (GP11Session *session,
+ GAsyncResult *result,
+ GError **err);
+
+#endif /* UNTESTED */
+
+#if UNIMPLEMENTED
+
+GkrProcessor* gp11_session_batch_verify (GP11Session *session,
+ GP11Object *key,
+ GP11Mechanism *mech_type,
+ const guchar *input,
+ gsize n_input,
+ gsize *n_result,
+ GCancellable *cancellable,
+ GError **err);
+
+void gp11_session_batch_verify_async (GP11Session *session,
+ GP11Object *key,
+ GP11Mechanism *mech_args,
+ const guchar *input,
+ gsize n_input,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+GkrProcessor* gp11_session_batch_verify_finish (GP11Session *session,
+ GAsyncResult *result,
+ GError **err);
+
+guchar* gp11_session_verify_recover (GP11Session *session,
+ GP11Object *key,
+ guint mech_type,
+ const guchar *input,
+ gsize n_input,
+ gsize *n_result,
+ GError **err);
+
+guchar* gp11_session_verify_recover_full (GP11Session *session,
+ GP11Object *key,
+ GP11Mechanism *mech_args,
+ const guchar *input,
+ gsize n_input,
+ gsize *n_result,
+ GCancellable *cancellable,
+ GError **err);
+
+void gp11_session_verify_recover_async (GP11Session *session,
+ GP11Object *key,
+ GP11Mechanism *mech_args,
+ const guchar *input,
+ gsize n_input,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+guchar* gp11_session_verify_recover_finish (GP11Session *session,
+ GAsyncResult *result,
+ gsize *n_result,
+ GError **err);
+
+guchar* gp11_session_wrap (GP11Session *session,
+ GP11Object *key,
+ guint mech_type,
+ GP11Object *wrapped_key,
+ gsize *n_result,
+ GError **err);
+
+guchar* gp11_session_wrap (GP11Session *session,
+ GP11Object *key,
+ GP11Mechanism *mech_args,
+ GP11Object *wrapped_key,
+ gsize *n_result,
+ GCancellable *cancellable,
+ GError **err);
+
+void gp11_session_wrap_async (GP11Session *session,
+ GP11Object *key,
+ GP11Mechanism *mech_args,
+ GP11Object *wrapped_key,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+guchar* gp11_session_wrap_finish (GP11Session *session,
+ GAsyncResult *result,
+ gsize *n_result,
+ GError **err);
+
+GP11Object* gp11_session_unwrap (GP11Session *session,
+ GP11Object *key,
+ guint mech_type,
+ const guchar *input,
+ gsize n_input,
+ GError **err,
+ ...);
+
+GP11Object* gp11_session_unwrap (GP11Session *session,
+ GP11Object *key,
+ GP11Mechanism *mech_args,
+ const guchar *input,
+ gsize n_input,
+ GCancellable *cancellable,
+ GError **err,
+ ...);
+
+void gp11_session_unwrap_async (GP11Session *session,
+ GP11Object *key,
+ GP11Mechanism *mech_args,
+ const guchar *input,
+ gsize n_input,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+ ...);
+
+GP11Object* gp11_session_unwrap_finish (GP11Session *session,
+ GAsyncResult *result,
+ GError **err);
+
+GP11Object* gp11_session_derive (GP11Session *session,
+ GP11Object *key,
+ guint mech_type,
+ GError **err,
+ ...);
+
+GP11Object* gp11_session_derive_full (GP11Session *session,
+ GP11Object *key,
+ GP11Mechanism *mech_args,
+ GCancellable *cancellable,
+ GError **err,
+ ...);
+
+void gp11_session_derive_async (GP11Session *session,
+ GP11Object *key,
+ GP11Mechanism *mech_args,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+ ...);
+
+GP11Object* gp11_session_derive_finish (GP11Session *session,
+ GAsyncResult *result,
+ GError **err);
+
+#endif /* UNIMPLEMENTED */
+
+
+/* ------------------------------------------------------------------------
+ * OBJECT
+ */
+
+#define GP11_TYPE_OBJECT (gp11_object_get_type())
+#define GP11_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GP11_TYPE_OBJECT, GP11Object))
+#define GP11_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GP11_TYPE_OBJECT, GP11Object))
+#define GP11_IS_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GP11_TYPE_OBJECT))
+#define GP11_IS_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GP11_TYPE_OBJECT))
+#define GP11_OBJECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GP11_TYPE_OBJECT, GP11ObjectClass))
+
+typedef struct _GP11ObjectClass GP11ObjectClass;
+
+struct _GP11Object {
+ GObject parent;
+
+ GP11Module *module;
+ GP11Session *session;
+ CK_OBJECT_HANDLE handle;
+};
+
+struct _GP11ObjectClass {
+ GObjectClass parent;
+};
+
+GType gp11_object_get_type (void) G_GNUC_CONST;
+
+GP11Object* gp11_object_from_handle (GP11Session *session,
+ CK_OBJECT_HANDLE handle);
+
+#ifdef UNIMPLEMENTED
+
+GP11Object* gp11_object_copy (GP11Object *object,
+ GError **err);
+
+GP11Object* gp11_object_copy_full (GP11Object *object,
+ GP11Attributes *additional,
+ GCancellable *cancellable,
+ GError **err);
+
+void gp11_object_copy_async (GP11Object *object,
+ GP11Attributes *additional,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+GP11Object* gp11_object_copy_finish (GP11Object *object,
+ GAsyncResult *result,
+ GError **err);
+
+#endif /* UNIMPLEMENTED */
+
+gboolean gp11_object_destroy (GP11Object *object,
+ GError **err);
+
+gboolean gp11_object_destroy_full (GP11Object *object,
+ GCancellable *cancellable,
+ GError **err);
+
+void gp11_object_destroy_async (GP11Object *object,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean gp11_object_destroy_finish (GP11Object *object,
+ GAsyncResult *result,
+ GError **err);
+
+#if UNIMPLEMENTED
+
+gssize gp11_object_get_size (GP11Object *object,
+ GError **err);
+
+gssize gp11_object_get_size_full (GP11Object *object,
+ GCancellable *cancellable,
+ GError **err);
+
+void gp11_object_get_size_async (GP11Object *object,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gssize gp11_object_get_size_finish (GP11Object *object,
+ GAsyncResult *result,
+ GError **err);
+
+#endif /* UNIMPLEMENTED */
+
+gboolean gp11_object_set (GP11Object *object,
+ GError **err,
+ ...);
+
+gboolean gp11_object_set_full (GP11Object *object,
+ GP11Attributes *attrs,
+ GCancellable *cancellable,
+ GError **err);
+
+void gp11_object_set_async (GP11Object *object,
+ GP11Attributes *attrs,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean gp11_object_set_finish (GP11Object *object,
+ GAsyncResult *result,
+ GError **err);
+
+GP11Attributes* gp11_object_get (GP11Object *object,
+ GError **err,
+ ...);
+
+GP11Attributes* gp11_object_get_full (GP11Object *object,
+ guint *attr_types,
+ gsize n_attr_types,
+ GCancellable *cancellable,
+ GError **err);
+
+void gp11_object_get_async (GP11Object *object,
+ guint *attr_types,
+ gsize n_attr_types,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+GP11Attributes* gp11_object_get_finish (GP11Object *object,
+ GAsyncResult *result,
+ GError **err);
+
+GP11Attribute* gp11_object_get_one (GP11Object *object,
+ guint attr_type,
+ GError **err);
+
+GP11Attribute* gp11_object_get_one_full (GP11Object *object,
+ guint attr_type,
+ GCancellable *cancellable,
+ GError **err);
+
+void gp11_object_get_one_async (GP11Object *object,
+ guint attr_type,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+GP11Attribute* gp11_object_get_one_finish (GP11Object *object,
+ GAsyncResult *result,
+ GError **err);
+
+
+/* ----------------------------------------------------------------------
+ * PROCESSOR
+ */
+
+#if UNIMPLEMENTED
+
+guchar* gp11_processor_step (GP11Processor *processor,
+ const guchar *input,
+ gsize n_input,
+ gsize *n_result,
+ GError **err);
+
+void gp11_processor_step_async (GP11Processor *processor,
+ const guchar *input,
+ gsize n_input,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+guchar* gp11_processor_step_finish (GP11Processor *processor,
+ GAsyncResult *result,
+ gsize *n_result,
+ GError **err);
+
+guchar* gp11_processor_close (GP11Processor *processor,
+ gsize *n_result,
+ GError **err);
+
+guchar* gp11_processor_close_async (GP11Processor *processor,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+guchar* gp11_processor_close_finish (GP11Processor *processor,
+ GAsyncResult *result,
+ gsize *n_result,
+ GError **err);
+
+#endif /* UNIMPLEMENTED */
+
+G_END_DECLS
+
+#endif /*GP11_H_*/
diff --git a/gp11/gp11.pc.in b/gp11/gp11.pc.in
new file mode 100644
index 00000000..c285f06e
--- /dev/null
+++ b/gp11/gp11.pc.in
@@ -0,0 +1,14 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+datarootdir=@datarootdir@
+datadir=@datadir@
+sysconfdir=@sysconfdir@
+
+Name: gp11
+Description: GObject bindings for PKCS#11
+Version: @GP11_MAJOR@
+Requires: gconf-2.0
+Libs: -L${libdir} -lgp11
+Cflags: -I${includedir}/gp11
diff --git a/gp11/pkcs11.h b/gp11/pkcs11.h
new file mode 100644
index 00000000..2e6a1e3e
--- /dev/null
+++ b/gp11/pkcs11.h
@@ -0,0 +1,1357 @@
+/* pkcs11.h
+ Copyright 2006, 2007 g10 Code GmbH
+ Copyright 2006 Andreas Jellinghaus
+
+ This file is free software; as a special exception the author gives
+ unlimited permission to copy and/or distribute it, with or without
+ modifications, as long as this notice is preserved.
+
+ This file is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY, to the extent permitted by law; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE. */
+
+/* Please submit changes back to the Scute project at
+ http://www.scute.org/ (or send them to marcus@g10code.com), so that
+ they can be picked up by other projects from there as well. */
+
+/* This file is a modified implementation of the PKCS #11 standard by
+ RSA Security Inc. It is mostly a drop-in replacement, with the
+ following change:
+
+ This header file does not require any macro definitions by the user
+ (like CK_DEFINE_FUNCTION etc). In fact, it defines those macros
+ for you (if useful, some are missing, let me know if you need
+ more).
+
+ There is an additional API available that does comply better to the
+ GNU coding standard. It can be switched on by defining
+ CRYPTOKI_GNU before including this header file. For this, the
+ following changes are made to the specification:
+
+ All structure types are changed to a "struct ck_foo" where CK_FOO
+ is the type name in PKCS #11.
+
+ All non-structure types are changed to ck_foo_t where CK_FOO is the
+ lowercase version of the type name in PKCS #11. The basic types
+ (CK_ULONG et al.) are removed without substitute.
+
+ All members of structures are modified in the following way: Type
+ indication prefixes are removed, and underscore characters are
+ inserted before words. Then the result is lowercased.
+
+ Note that function names are still in the original case, as they
+ need for ABI compatibility.
+
+ CK_FALSE, CK_TRUE and NULL_PTR are removed without substitute. Use
+ <stdbool.h>.
+
+ If CRYPTOKI_COMPAT is defined before including this header file,
+ then none of the API changes above take place, and the API is the
+ one defined by the PKCS #11 standard. */
+
+#ifndef PKCS11_H
+#define PKCS11_H 1
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* The version of cryptoki we implement. The revision is changed with
+ each modification of this file. If you do not use the "official"
+ version of this file, please consider deleting the revision macro
+ (you may use a macro with a different name to keep track of your
+ versions). */
+#define CRYPTOKI_VERSION_MAJOR 2
+#define CRYPTOKI_VERSION_MINOR 20
+#define CRYPTOKI_VERSION_REVISION 6
+
+
+/* Compatibility interface is default, unless CRYPTOKI_GNU is
+ given. */
+#ifndef CRYPTOKI_GNU
+#ifndef CRYPTOKI_COMPAT
+#define CRYPTOKI_COMPAT 1
+#endif
+#endif
+
+/* System dependencies. */
+
+#if defined(_WIN32) || defined(CRYPTOKI_FORCE_WIN32)
+
+/* There is a matching pop below. */
+#pragma pack(push, cryptoki, 1)
+
+#ifdef CRYPTOKI_EXPORTS
+#define CK_SPEC __declspec(dllexport)
+#else
+#define CK_SPEC __declspec(dllimport)
+#endif
+
+#else
+
+#define CK_SPEC
+
+#endif
+
+
+#ifdef CRYPTOKI_COMPAT
+ /* If we are in compatibility mode, switch all exposed names to the
+ PKCS #11 variant. There are corresponding #undefs below. */
+
+#define ck_flags_t CK_FLAGS
+#define ck_version _CK_VERSION
+
+#define ck_info _CK_INFO
+#define cryptoki_version cryptokiVersion
+#define manufacturer_id manufacturerID
+#define library_description libraryDescription
+#define library_version libraryVersion
+
+#define ck_notification_t CK_NOTIFICATION
+#define ck_slot_id_t CK_SLOT_ID
+
+#define ck_slot_info _CK_SLOT_INFO
+#define slot_description slotDescription
+#define hardware_version hardwareVersion
+#define firmware_version firmwareVersion
+
+#define ck_token_info _CK_TOKEN_INFO
+#define serial_number serialNumber
+#define max_session_count ulMaxSessionCount
+#define session_count ulSessionCount
+#define max_rw_session_count ulMaxRwSessionCount
+#define rw_session_count ulRwSessionCount
+#define max_pin_len ulMaxPinLen
+#define min_pin_len ulMinPinLen
+#define total_public_memory ulTotalPublicMemory
+#define free_public_memory ulFreePublicMemory
+#define total_private_memory ulTotalPrivateMemory
+#define free_private_memory ulFreePrivateMemory
+#define utc_time utcTime
+
+#define ck_session_handle_t CK_SESSION_HANDLE
+#define ck_user_type_t CK_USER_TYPE
+#define ck_state_t CK_STATE
+
+#define ck_session_info _CK_SESSION_INFO
+#define slot_id slotID
+#define device_error ulDeviceError
+
+#define ck_object_handle_t CK_OBJECT_HANDLE
+#define ck_object_class_t CK_OBJECT_CLASS
+#define ck_hw_feature_type_t CK_HW_FEATURE_TYPE
+#define ck_key_type_t CK_KEY_TYPE
+#define ck_certificate_type_t CK_CERTIFICATE_TYPE
+#define ck_attribute_type_t CK_ATTRIBUTE_TYPE
+
+#define ck_attribute _CK_ATTRIBUTE
+#define value pValue
+#define value_len ulValueLen
+
+#define ck_date _CK_DATE
+
+#define ck_mechanism_type_t CK_MECHANISM_TYPE
+
+#define ck_mechanism _CK_MECHANISM
+#define parameter pParameter
+#define parameter_len ulParameterLen
+
+#define ck_mechanism_info _CK_MECHANISM_INFO
+#define min_key_size ulMinKeySize
+#define max_key_size ulMaxKeySize
+
+#define ck_rv_t CK_RV
+#define ck_notify_t CK_NOTIFY
+
+#define ck_function_list _CK_FUNCTION_LIST
+
+#define ck_createmutex_t CK_CREATEMUTEX
+#define ck_destroymutex_t CK_DESTROYMUTEX
+#define ck_lockmutex_t CK_LOCKMUTEX
+#define ck_unlockmutex_t CK_UNLOCKMUTEX
+
+#define ck_c_initialize_args _CK_C_INITIALIZE_ARGS
+#define create_mutex CreateMutex
+#define destroy_mutex DestroyMutex
+#define lock_mutex LockMutex
+#define unlock_mutex UnlockMutex
+#define reserved pReserved
+
+#endif /* CRYPTOKI_COMPAT */
+
+
+
+typedef unsigned long ck_flags_t;
+
+struct ck_version
+{
+ unsigned char major;
+ unsigned char minor;
+};
+
+
+struct ck_info
+{
+ struct ck_version cryptoki_version;
+ unsigned char manufacturer_id[32];
+ ck_flags_t flags;
+ unsigned char library_description[32];
+ struct ck_version library_version;
+};
+
+
+typedef unsigned long ck_notification_t;
+
+#define CKN_SURRENDER (0)
+
+
+typedef unsigned long ck_slot_id_t;
+
+
+struct ck_slot_info
+{
+ unsigned char slot_description[64];
+ unsigned char manufacturer_id[32];
+ ck_flags_t flags;
+ struct ck_version hardware_version;
+ struct ck_version firmware_version;
+};
+
+
+#define CKF_TOKEN_PRESENT (1 << 0)
+#define CKF_REMOVABLE_DEVICE (1 << 1)
+#define CKF_HW_SLOT (1 << 2)
+#define CKF_ARRAY_ATTRIBUTE (1 << 30)
+
+
+struct ck_token_info
+{
+ unsigned char label[32];
+ unsigned char manufacturer_id[32];
+ unsigned char model[16];
+ unsigned char serial_number[16];
+ ck_flags_t flags;
+ unsigned long max_session_count;
+ unsigned long session_count;
+ unsigned long max_rw_session_count;
+ unsigned long rw_session_count;
+ unsigned long max_pin_len;
+ unsigned long min_pin_len;
+ unsigned long total_public_memory;
+ unsigned long free_public_memory;
+ unsigned long total_private_memory;
+ unsigned long free_private_memory;
+ struct ck_version hardware_version;
+ struct ck_version firmware_version;
+ unsigned char utc_time[16];
+};
+
+
+#define CKF_RNG (1 << 0)
+#define CKF_WRITE_PROTECTED (1 << 1)
+#define CKF_LOGIN_REQUIRED (1 << 2)
+#define CKF_USER_PIN_INITIALIZED (1 << 3)
+#define CKF_RESTORE_KEY_NOT_NEEDED (1 << 5)
+#define CKF_CLOCK_ON_TOKEN (1 << 6)
+#define CKF_PROTECTED_AUTHENTICATION_PATH (1 << 8)
+#define CKF_DUAL_CRYPTO_OPERATIONS (1 << 9)
+#define CKF_TOKEN_INITIALIZED (1 << 10)
+#define CKF_SECONDARY_AUTHENTICATION (1 << 11)
+#define CKF_USER_PIN_COUNT_LOW (1 << 16)
+#define CKF_USER_PIN_FINAL_TRY (1 << 17)
+#define CKF_USER_PIN_LOCKED (1 << 18)
+#define CKF_USER_PIN_TO_BE_CHANGED (1 << 19)
+#define CKF_SO_PIN_COUNT_LOW (1 << 20)
+#define CKF_SO_PIN_FINAL_TRY (1 << 21)
+#define CKF_SO_PIN_LOCKED (1 << 22)
+#define CKF_SO_PIN_TO_BE_CHANGED (1 << 23)
+
+#define CK_UNAVAILABLE_INFORMATION ((unsigned long) -1)
+#define CK_EFFECTIVELY_INFINITE (0)
+
+
+typedef unsigned long ck_session_handle_t;
+
+#define CK_INVALID_HANDLE (0)
+
+
+typedef unsigned long ck_user_type_t;
+
+#define CKU_SO (0)
+#define CKU_USER (1)
+#define CKU_CONTEXT_SPECIFIC (2)
+
+
+typedef unsigned long ck_state_t;
+
+#define CKS_RO_PUBLIC_SESSION (0)
+#define CKS_RO_USER_FUNCTIONS (1)
+#define CKS_RW_PUBLIC_SESSION (2)
+#define CKS_RW_USER_FUNCTIONS (3)
+#define CKS_RW_SO_FUNCTIONS (4)
+
+
+struct ck_session_info
+{
+ ck_slot_id_t slot_id;
+ ck_state_t state;
+ ck_flags_t flags;
+ unsigned long device_error;
+};
+
+#define CKF_RW_SESSION (1 << 1)
+#define CKF_SERIAL_SESSION (1 << 2)
+
+
+typedef unsigned long ck_object_handle_t;
+
+
+typedef unsigned long ck_object_class_t;
+
+#define CKO_DATA (0)
+#define CKO_CERTIFICATE (1)
+#define CKO_PUBLIC_KEY (2)
+#define CKO_PRIVATE_KEY (3)
+#define CKO_SECRET_KEY (4)
+#define CKO_HW_FEATURE (5)
+#define CKO_DOMAIN_PARAMETERS (6)
+#define CKO_MECHANISM (7)
+#define CKO_VENDOR_DEFINED ((unsigned long) (1 << 31))
+
+
+typedef unsigned long ck_hw_feature_type_t;
+
+#define CKH_MONOTONIC_COUNTER (1)
+#define CKH_CLOCK (2)
+#define CKH_USER_INTERFACE (3)
+#define CKH_VENDOR_DEFINED ((unsigned long) (1 << 31))
+
+
+typedef unsigned long ck_key_type_t;
+
+#define CKK_RSA (0)
+#define CKK_DSA (1)
+#define CKK_DH (2)
+#define CKK_ECDSA (3)
+#define CKK_EC (3)
+#define CKK_X9_42_DH (4)
+#define CKK_KEA (5)
+#define CKK_GENERIC_SECRET (0x10)
+#define CKK_RC2 (0x11)
+#define CKK_RC4 (0x12)
+#define CKK_DES (0x13)
+#define CKK_DES2 (0x14)
+#define CKK_DES3 (0x15)
+#define CKK_CAST (0x16)
+#define CKK_CAST3 (0x17)
+#define CKK_CAST128 (0x18)
+#define CKK_RC5 (0x19)
+#define CKK_IDEA (0x1a)
+#define CKK_SKIPJACK (0x1b)
+#define CKK_BATON (0x1c)
+#define CKK_JUNIPER (0x1d)
+#define CKK_CDMF (0x1e)
+#define CKK_AES (0x1f)
+#define CKK_BLOWFISH (0x20)
+#define CKK_TWOFISH (0x21)
+#define CKK_VENDOR_DEFINED ((unsigned long) (1 << 31))
+
+
+typedef unsigned long ck_certificate_type_t;
+
+#define CKC_X_509 (0)
+#define CKC_X_509_ATTR_CERT (1)
+#define CKC_WTLS (2)
+#define CKC_VENDOR_DEFINED ((unsigned long) (1 << 31))
+
+
+typedef unsigned long ck_attribute_type_t;
+
+#define CKA_CLASS (0)
+#define CKA_TOKEN (1)
+#define CKA_PRIVATE (2)
+#define CKA_LABEL (3)
+#define CKA_APPLICATION (0x10)
+#define CKA_VALUE (0x11)
+#define CKA_OBJECT_ID (0x12)
+#define CKA_CERTIFICATE_TYPE (0x80)
+#define CKA_ISSUER (0x81)
+#define CKA_SERIAL_NUMBER (0x82)
+#define CKA_AC_ISSUER (0x83)
+#define CKA_OWNER (0x84)
+#define CKA_ATTR_TYPES (0x85)
+#define CKA_TRUSTED (0x86)
+#define CKA_CERTIFICATE_CATEGORY (0x87)
+#define CKA_JAVA_MIDP_SECURITY_DOMAIN (0x88)
+#define CKA_URL (0x89)
+#define CKA_HASH_OF_SUBJECT_PUBLIC_KEY (0x8a)
+#define CKA_HASH_OF_ISSUER_PUBLIC_KEY (0x8b)
+#define CKA_CHECK_VALUE (0x90)
+#define CKA_KEY_TYPE (0x100)
+#define CKA_SUBJECT (0x101)
+#define CKA_ID (0x102)
+#define CKA_SENSITIVE (0x103)
+#define CKA_ENCRYPT (0x104)
+#define CKA_DECRYPT (0x105)
+#define CKA_WRAP (0x106)
+#define CKA_UNWRAP (0x107)
+#define CKA_SIGN (0x108)
+#define CKA_SIGN_RECOVER (0x109)
+#define CKA_VERIFY (0x10a)
+#define CKA_VERIFY_RECOVER (0x10b)
+#define CKA_DERIVE (0x10c)
+#define CKA_START_DATE (0x110)
+#define CKA_END_DATE (0x111)
+#define CKA_MODULUS (0x120)
+#define CKA_MODULUS_BITS (0x121)
+#define CKA_PUBLIC_EXPONENT (0x122)
+#define CKA_PRIVATE_EXPONENT (0x123)
+#define CKA_PRIME_1 (0x124)
+#define CKA_PRIME_2 (0x125)
+#define CKA_EXPONENT_1 (0x126)
+#define CKA_EXPONENT_2 (0x127)
+#define CKA_COEFFICIENT (0x128)
+#define CKA_PRIME (0x130)
+#define CKA_SUBPRIME (0x131)
+#define CKA_BASE (0x132)
+#define CKA_PRIME_BITS (0x133)
+#define CKA_SUB_PRIME_BITS (0x134)
+#define CKA_VALUE_BITS (0x160)
+#define CKA_VALUE_LEN (0x161)
+#define CKA_EXTRACTABLE (0x162)
+#define CKA_LOCAL (0x163)
+#define CKA_NEVER_EXTRACTABLE (0x164)
+#define CKA_ALWAYS_SENSITIVE (0x165)
+#define CKA_KEY_GEN_MECHANISM (0x166)
+#define CKA_MODIFIABLE (0x170)
+#define CKA_ECDSA_PARAMS (0x180)
+#define CKA_EC_PARAMS (0x180)
+#define CKA_EC_POINT (0x181)
+#define CKA_SECONDARY_AUTH (0x200)
+#define CKA_AUTH_PIN_FLAGS (0x201)
+#define CKA_ALWAYS_AUTHENTICATE (0x202)
+#define CKA_WRAP_WITH_TRUSTED (0x210)
+#define CKA_HW_FEATURE_TYPE (0x300)
+#define CKA_RESET_ON_INIT (0x301)
+#define CKA_HAS_RESET (0x302)
+#define CKA_PIXEL_X (0x400)
+#define CKA_PIXEL_Y (0x401)
+#define CKA_RESOLUTION (0x402)
+#define CKA_CHAR_ROWS (0x403)
+#define CKA_CHAR_COLUMNS (0x404)
+#define CKA_COLOR (0x405)
+#define CKA_BITS_PER_PIXEL (0x406)
+#define CKA_CHAR_SETS (0x480)
+#define CKA_ENCODING_METHODS (0x481)
+#define CKA_MIME_TYPES (0x482)
+#define CKA_MECHANISM_TYPE (0x500)
+#define CKA_REQUIRED_CMS_ATTRIBUTES (0x501)
+#define CKA_DEFAULT_CMS_ATTRIBUTES (0x502)
+#define CKA_SUPPORTED_CMS_ATTRIBUTES (0x503)
+#define CKA_WRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE | 0x211)
+#define CKA_UNWRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE | 0x212)
+#define CKA_ALLOWED_MECHANISMS (CKF_ARRAY_ATTRIBUTE | 0x600)
+#define CKA_VENDOR_DEFINED ((unsigned long) (1 << 31))
+
+
+struct ck_attribute
+{
+ ck_attribute_type_t type;
+ void *value;
+ unsigned long value_len;
+};
+
+
+struct ck_date
+{
+ unsigned char year[4];
+ unsigned char month[2];
+ unsigned char day[2];
+};
+
+
+typedef unsigned long ck_mechanism_type_t;
+
+#define CKM_RSA_PKCS_KEY_PAIR_GEN (0)
+#define CKM_RSA_PKCS (1)
+#define CKM_RSA_9796 (2)
+#define CKM_RSA_X_509 (3)
+#define CKM_MD2_RSA_PKCS (4)
+#define CKM_MD5_RSA_PKCS (5)
+#define CKM_SHA1_RSA_PKCS (6)
+#define CKM_RIPEMD128_RSA_PKCS (7)
+#define CKM_RIPEMD160_RSA_PKCS (8)
+#define CKM_RSA_PKCS_OAEP (9)
+#define CKM_RSA_X9_31_KEY_PAIR_GEN (0xa)
+#define CKM_RSA_X9_31 (0xb)
+#define CKM_SHA1_RSA_X9_31 (0xc)
+#define CKM_RSA_PKCS_PSS (0xd)
+#define CKM_SHA1_RSA_PKCS_PSS (0xe)
+#define CKM_DSA_KEY_PAIR_GEN (0x10)
+#define CKM_DSA (0x11)
+#define CKM_DSA_SHA1 (0x12)
+#define CKM_DH_PKCS_KEY_PAIR_GEN (0x20)
+#define CKM_DH_PKCS_DERIVE (0x21)
+#define CKM_X9_42_DH_KEY_PAIR_GEN (0x30)
+#define CKM_X9_42_DH_DERIVE (0x31)
+#define CKM_X9_42_DH_HYBRID_DERIVE (0x32)
+#define CKM_X9_42_MQV_DERIVE (0x33)
+#define CKM_SHA256_RSA_PKCS (0x40)
+#define CKM_SHA384_RSA_PKCS (0x41)
+#define CKM_SHA512_RSA_PKCS (0x42)
+#define CKM_SHA256_RSA_PKCS_PSS (0x43)
+#define CKM_SHA384_RSA_PKCS_PSS (0x44)
+#define CKM_SHA512_RSA_PKCS_PSS (0x45)
+#define CKM_RC2_KEY_GEN (0x100)
+#define CKM_RC2_ECB (0x101)
+#define CKM_RC2_CBC (0x102)
+#define CKM_RC2_MAC (0x103)
+#define CKM_RC2_MAC_GENERAL (0x104)
+#define CKM_RC2_CBC_PAD (0x105)
+#define CKM_RC4_KEY_GEN (0x110)
+#define CKM_RC4 (0x111)
+#define CKM_DES_KEY_GEN (0x120)
+#define CKM_DES_ECB (0x121)
+#define CKM_DES_CBC (0x122)
+#define CKM_DES_MAC (0x123)
+#define CKM_DES_MAC_GENERAL (0x124)
+#define CKM_DES_CBC_PAD (0x125)
+#define CKM_DES2_KEY_GEN (0x130)
+#define CKM_DES3_KEY_GEN (0x131)
+#define CKM_DES3_ECB (0x132)
+#define CKM_DES3_CBC (0x133)
+#define CKM_DES3_MAC (0x134)
+#define CKM_DES3_MAC_GENERAL (0x135)
+#define CKM_DES3_CBC_PAD (0x136)
+#define CKM_CDMF_KEY_GEN (0x140)
+#define CKM_CDMF_ECB (0x141)
+#define CKM_CDMF_CBC (0x142)
+#define CKM_CDMF_MAC (0x143)
+#define CKM_CDMF_MAC_GENERAL (0x144)
+#define CKM_CDMF_CBC_PAD (0x145)
+#define CKM_MD2 (0x200)
+#define CKM_MD2_HMAC (0x201)
+#define CKM_MD2_HMAC_GENERAL (0x202)
+#define CKM_MD5 (0x210)
+#define CKM_MD5_HMAC (0x211)
+#define CKM_MD5_HMAC_GENERAL (0x212)
+#define CKM_SHA_1 (0x220)
+#define CKM_SHA_1_HMAC (0x221)
+#define CKM_SHA_1_HMAC_GENERAL (0x222)
+#define CKM_RIPEMD128 (0x230)
+#define CKM_RIPEMD128_HMAC (0x231)
+#define CKM_RIPEMD128_HMAC_GENERAL (0x232)
+#define CKM_RIPEMD160 (0x240)
+#define CKM_RIPEMD160_HMAC (0x241)
+#define CKM_RIPEMD160_HMAC_GENERAL (0x242)
+#define CKM_SHA256 (0x250)
+#define CKM_SHA256_HMAC (0x251)
+#define CKM_SHA256_HMAC_GENERAL (0x252)
+#define CKM_SHA384 (0x260)
+#define CKM_SHA384_HMAC (0x261)
+#define CKM_SHA384_HMAC_GENERAL (0x262)
+#define CKM_SHA512 (0x270)
+#define CKM_SHA512_HMAC (0x271)
+#define CKM_SHA512_HMAC_GENERAL (0x272)
+#define CKM_CAST_KEY_GEN (0x300)
+#define CKM_CAST_ECB (0x301)
+#define CKM_CAST_CBC (0x302)
+#define CKM_CAST_MAC (0x303)
+#define CKM_CAST_MAC_GENERAL (0x304)
+#define CKM_CAST_CBC_PAD (0x305)
+#define CKM_CAST3_KEY_GEN (0x310)
+#define CKM_CAST3_ECB (0x311)
+#define CKM_CAST3_CBC (0x312)
+#define CKM_CAST3_MAC (0x313)
+#define CKM_CAST3_MAC_GENERAL (0x314)
+#define CKM_CAST3_CBC_PAD (0x315)
+#define CKM_CAST5_KEY_GEN (0x320)
+#define CKM_CAST128_KEY_GEN (0x320)
+#define CKM_CAST5_ECB (0x321)
+#define CKM_CAST128_ECB (0x321)
+#define CKM_CAST5_CBC (0x322)
+#define CKM_CAST128_CBC (0x322)
+#define CKM_CAST5_MAC (0x323)
+#define CKM_CAST128_MAC (0x323)
+#define CKM_CAST5_MAC_GENERAL (0x324)
+#define CKM_CAST128_MAC_GENERAL (0x324)
+#define CKM_CAST5_CBC_PAD (0x325)
+#define CKM_CAST128_CBC_PAD (0x325)
+#define CKM_RC5_KEY_GEN (0x330)
+#define CKM_RC5_ECB (0x331)
+#define CKM_RC5_CBC (0x332)
+#define CKM_RC5_MAC (0x333)
+#define CKM_RC5_MAC_GENERAL (0x334)
+#define CKM_RC5_CBC_PAD (0x335)
+#define CKM_IDEA_KEY_GEN (0x340)
+#define CKM_IDEA_ECB (0x341)
+#define CKM_IDEA_CBC (0x342)
+#define CKM_IDEA_MAC (0x343)
+#define CKM_IDEA_MAC_GENERAL (0x344)
+#define CKM_IDEA_CBC_PAD (0x345)
+#define CKM_GENERIC_SECRET_KEY_GEN (0x350)
+#define CKM_CONCATENATE_BASE_AND_KEY (0x360)
+#define CKM_CONCATENATE_BASE_AND_DATA (0x362)
+#define CKM_CONCATENATE_DATA_AND_BASE (0x363)
+#define CKM_XOR_BASE_AND_DATA (0x364)
+#define CKM_EXTRACT_KEY_FROM_KEY (0x365)
+#define CKM_SSL3_PRE_MASTER_KEY_GEN (0x370)
+#define CKM_SSL3_MASTER_KEY_DERIVE (0x371)
+#define CKM_SSL3_KEY_AND_MAC_DERIVE (0x372)
+#define CKM_SSL3_MASTER_KEY_DERIVE_DH (0x373)
+#define CKM_TLS_PRE_MASTER_KEY_GEN (0x374)
+#define CKM_TLS_MASTER_KEY_DERIVE (0x375)
+#define CKM_TLS_KEY_AND_MAC_DERIVE (0x376)
+#define CKM_TLS_MASTER_KEY_DERIVE_DH (0x377)
+#define CKM_SSL3_MD5_MAC (0x380)
+#define CKM_SSL3_SHA1_MAC (0x381)
+#define CKM_MD5_KEY_DERIVATION (0x390)
+#define CKM_MD2_KEY_DERIVATION (0x391)
+#define CKM_SHA1_KEY_DERIVATION (0x392)
+#define CKM_PBE_MD2_DES_CBC (0x3a0)
+#define CKM_PBE_MD5_DES_CBC (0x3a1)
+#define CKM_PBE_MD5_CAST_CBC (0x3a2)
+#define CKM_PBE_MD5_CAST3_CBC (0x3a3)
+#define CKM_PBE_MD5_CAST5_CBC (0x3a4)
+#define CKM_PBE_MD5_CAST128_CBC (0x3a4)
+#define CKM_PBE_SHA1_CAST5_CBC (0x3a5)
+#define CKM_PBE_SHA1_CAST128_CBC (0x3a5)
+#define CKM_PBE_SHA1_RC4_128 (0x3a6)
+#define CKM_PBE_SHA1_RC4_40 (0x3a7)
+#define CKM_PBE_SHA1_DES3_EDE_CBC (0x3a8)
+#define CKM_PBE_SHA1_DES2_EDE_CBC (0x3a9)
+#define CKM_PBE_SHA1_RC2_128_CBC (0x3aa)
+#define CKM_PBE_SHA1_RC2_40_CBC (0x3ab)
+#define CKM_PKCS5_PBKD2 (0x3b0)
+#define CKM_PBA_SHA1_WITH_SHA1_HMAC (0x3c0)
+#define CKM_KEY_WRAP_LYNKS (0x400)
+#define CKM_KEY_WRAP_SET_OAEP (0x401)
+#define CKM_SKIPJACK_KEY_GEN (0x1000)
+#define CKM_SKIPJACK_ECB64 (0x1001)
+#define CKM_SKIPJACK_CBC64 (0x1002)
+#define CKM_SKIPJACK_OFB64 (0x1003)
+#define CKM_SKIPJACK_CFB64 (0x1004)
+#define CKM_SKIPJACK_CFB32 (0x1005)
+#define CKM_SKIPJACK_CFB16 (0x1006)
+#define CKM_SKIPJACK_CFB8 (0x1007)
+#define CKM_SKIPJACK_WRAP (0x1008)
+#define CKM_SKIPJACK_PRIVATE_WRAP (0x1009)
+#define CKM_SKIPJACK_RELAYX (0x100a)
+#define CKM_KEA_KEY_PAIR_GEN (0x1010)
+#define CKM_KEA_KEY_DERIVE (0x1011)
+#define CKM_FORTEZZA_TIMESTAMP (0x1020)
+#define CKM_BATON_KEY_GEN (0x1030)
+#define CKM_BATON_ECB128 (0x1031)
+#define CKM_BATON_ECB96 (0x1032)
+#define CKM_BATON_CBC128 (0x1033)
+#define CKM_BATON_COUNTER (0x1034)
+#define CKM_BATON_SHUFFLE (0x1035)
+#define CKM_BATON_WRAP (0x1036)
+#define CKM_ECDSA_KEY_PAIR_GEN (0x1040)
+#define CKM_EC_KEY_PAIR_GEN (0x1040)
+#define CKM_ECDSA (0x1041)
+#define CKM_ECDSA_SHA1 (0x1042)
+#define CKM_ECDH1_DERIVE (0x1050)
+#define CKM_ECDH1_COFACTOR_DERIVE (0x1051)
+#define CKM_ECMQV_DERIVE (0x1052)
+#define CKM_JUNIPER_KEY_GEN (0x1060)
+#define CKM_JUNIPER_ECB128 (0x1061)
+#define CKM_JUNIPER_CBC128 (0x1062)
+#define CKM_JUNIPER_COUNTER (0x1063)
+#define CKM_JUNIPER_SHUFFLE (0x1064)
+#define CKM_JUNIPER_WRAP (0x1065)
+#define CKM_FASTHASH (0x1070)
+#define CKM_AES_KEY_GEN (0x1080)
+#define CKM_AES_ECB (0x1081)
+#define CKM_AES_CBC (0x1082)
+#define CKM_AES_MAC (0x1083)
+#define CKM_AES_MAC_GENERAL (0x1084)
+#define CKM_AES_CBC_PAD (0x1085)
+#define CKM_DSA_PARAMETER_GEN (0x2000)
+#define CKM_DH_PKCS_PARAMETER_GEN (0x2001)
+#define CKM_X9_42_DH_PARAMETER_GEN (0x2002)
+#define CKM_VENDOR_DEFINED ((unsigned long) (1 << 31))
+
+
+struct ck_mechanism
+{
+ ck_mechanism_type_t mechanism;
+ void *parameter;
+ unsigned long parameter_len;
+};
+
+
+struct ck_mechanism_info
+{
+ unsigned long min_key_size;
+ unsigned long max_key_size;
+ ck_flags_t flags;
+};
+
+#define CKF_HW (1 << 0)
+#define CKF_ENCRYPT (1 << 8)
+#define CKF_DECRYPT (1 << 9)
+#define CKF_DIGEST (1 << 10)
+#define CKF_SIGN (1 << 11)
+#define CKF_SIGN_RECOVER (1 << 12)
+#define CKF_VERIFY (1 << 13)
+#define CKF_VERIFY_RECOVER (1 << 14)
+#define CKF_GENERATE (1 << 15)
+#define CKF_GENERATE_KEY_PAIR (1 << 16)
+#define CKF_WRAP (1 << 17)
+#define CKF_UNWRAP (1 << 18)
+#define CKF_DERIVE (1 << 19)
+#define CKF_EXTENSION ((unsigned long) (1 << 31))
+
+
+/* Flags for C_WaitForSlotEvent. */
+#define CKF_DONT_BLOCK (1)
+
+
+typedef unsigned long ck_rv_t;
+
+
+typedef ck_rv_t (*ck_notify_t) (ck_session_handle_t session,
+ ck_notification_t event, void *application);
+
+/* Forward reference. */
+struct ck_function_list;
+
+#define _CK_DECLARE_FUNCTION(name, args) \
+typedef ck_rv_t (*CK_ ## name) args; \
+ck_rv_t CK_SPEC name args
+
+_CK_DECLARE_FUNCTION (C_Initialize, (void *init_args));
+_CK_DECLARE_FUNCTION (C_Finalize, (void *reserved));
+_CK_DECLARE_FUNCTION (C_GetInfo, (struct ck_info *info));
+_CK_DECLARE_FUNCTION (C_GetFunctionList,
+ (struct ck_function_list **function_list));
+
+_CK_DECLARE_FUNCTION (C_GetSlotList,
+ (unsigned char token_present, ck_slot_id_t *slot_list,
+ unsigned long *count));
+_CK_DECLARE_FUNCTION (C_GetSlotInfo,
+ (ck_slot_id_t slot_id, struct ck_slot_info *info));
+_CK_DECLARE_FUNCTION (C_GetTokenInfo,
+ (ck_slot_id_t slot_id, struct ck_token_info *info));
+_CK_DECLARE_FUNCTION (C_WaitForSlotEvent,
+ (ck_flags_t flags, ck_slot_id_t *slot, void *reserved));
+_CK_DECLARE_FUNCTION (C_GetMechanismList,
+ (ck_slot_id_t slot_id,
+ ck_mechanism_type_t *mechanism_list,
+ unsigned long *count));
+_CK_DECLARE_FUNCTION (C_GetMechanismInfo,
+ (ck_slot_id_t slot_id, ck_mechanism_type_t type,
+ struct ck_mechanism_info *info));
+_CK_DECLARE_FUNCTION (C_InitToken,
+ (ck_slot_id_t slot_id, unsigned char *pin,
+ unsigned long pin_len, unsigned char *label));
+_CK_DECLARE_FUNCTION (C_InitPIN,
+ (ck_session_handle_t session, unsigned char *pin,
+ unsigned long pin_len));
+_CK_DECLARE_FUNCTION (C_SetPIN,
+ (ck_session_handle_t session, unsigned char *old_pin,
+ unsigned long old_len, unsigned char *new_pin,
+ unsigned long new_len));
+
+_CK_DECLARE_FUNCTION (C_OpenSession,
+ (ck_slot_id_t slot_id, ck_flags_t flags,
+ void *application, ck_notify_t notify,
+ ck_session_handle_t *session));
+_CK_DECLARE_FUNCTION (C_CloseSession, (ck_session_handle_t session));
+_CK_DECLARE_FUNCTION (C_CloseAllSessions, (ck_slot_id_t slot_id));
+_CK_DECLARE_FUNCTION (C_GetSessionInfo,
+ (ck_session_handle_t session,
+ struct ck_session_info *info));
+_CK_DECLARE_FUNCTION (C_GetOperationState,
+ (ck_session_handle_t session,
+ unsigned char *operation_state,
+ unsigned long *operation_state_len));
+_CK_DECLARE_FUNCTION (C_SetOperationState,
+ (ck_session_handle_t session,
+ unsigned char *operation_state,
+ unsigned long operation_state_len,
+ ck_object_handle_t encryption_key,
+ ck_object_handle_t authentiation_key));
+_CK_DECLARE_FUNCTION (C_Login,
+ (ck_session_handle_t session, ck_user_type_t user_type,
+ unsigned char *pin, unsigned long pin_len));
+_CK_DECLARE_FUNCTION (C_Logout, (ck_session_handle_t session));
+
+_CK_DECLARE_FUNCTION (C_CreateObject,
+ (ck_session_handle_t session,
+ struct ck_attribute *templ,
+ unsigned long count, ck_object_handle_t *object));
+_CK_DECLARE_FUNCTION (C_CopyObject,
+ (ck_session_handle_t session, ck_object_handle_t object,
+ struct ck_attribute *templ, unsigned long count,
+ ck_object_handle_t *new_object));
+_CK_DECLARE_FUNCTION (C_DestroyObject,
+ (ck_session_handle_t session,
+ ck_object_handle_t object));
+_CK_DECLARE_FUNCTION (C_GetObjectSize,
+ (ck_session_handle_t session,
+ ck_object_handle_t object,
+ unsigned long *size));
+_CK_DECLARE_FUNCTION (C_GetAttributeValue,
+ (ck_session_handle_t session,
+ ck_object_handle_t object,
+ struct ck_attribute *templ,
+ unsigned long count));
+_CK_DECLARE_FUNCTION (C_SetAttributeValue,
+ (ck_session_handle_t session,
+ ck_object_handle_t object,
+ struct ck_attribute *templ,
+ unsigned long count));
+_CK_DECLARE_FUNCTION (C_FindObjectsInit,
+ (ck_session_handle_t session,
+ struct ck_attribute *templ,
+ unsigned long count));
+_CK_DECLARE_FUNCTION (C_FindObjects,
+ (ck_session_handle_t session,
+ ck_object_handle_t *object,
+ unsigned long max_object_count,
+ unsigned long *object_count));
+_CK_DECLARE_FUNCTION (C_FindObjectsFinal,
+ (ck_session_handle_t session));
+
+_CK_DECLARE_FUNCTION (C_EncryptInit,
+ (ck_session_handle_t session,
+ struct ck_mechanism *mechanism,
+ ck_object_handle_t key));
+_CK_DECLARE_FUNCTION (C_Encrypt,
+ (ck_session_handle_t session,
+ unsigned char *data, unsigned long data_len,
+ unsigned char *encrypted_data,
+ unsigned long *encrypted_data_len));
+_CK_DECLARE_FUNCTION (C_EncryptUpdate,
+ (ck_session_handle_t session,
+ unsigned char *part, unsigned long part_len,
+ unsigned char *encrypted_part,
+ unsigned long *encrypted_part_len));
+_CK_DECLARE_FUNCTION (C_EncryptFinal,
+ (ck_session_handle_t session,
+ unsigned char *last_encrypted_part,
+ unsigned long *last_encrypted_part_len));
+
+_CK_DECLARE_FUNCTION (C_DecryptInit,
+ (ck_session_handle_t session,
+ struct ck_mechanism *mechanism,
+ ck_object_handle_t key));
+_CK_DECLARE_FUNCTION (C_Decrypt,
+ (ck_session_handle_t session,
+ unsigned char *encrypted_data,
+ unsigned long encrypted_data_len,
+ unsigned char *data, unsigned long *data_len));
+_CK_DECLARE_FUNCTION (C_DecryptUpdate,
+ (ck_session_handle_t session,
+ unsigned char *encrypted_part,
+ unsigned long encrypted_part_len,
+ unsigned char *part, unsigned long *part_len));
+_CK_DECLARE_FUNCTION (C_DecryptFinal,
+ (ck_session_handle_t session,
+ unsigned char *last_part,
+ unsigned long *last_part_len));
+
+_CK_DECLARE_FUNCTION (C_DigestInit,
+ (ck_session_handle_t session,
+ struct ck_mechanism *mechanism));
+_CK_DECLARE_FUNCTION (C_Digest,
+ (ck_session_handle_t session,
+ unsigned char *data, unsigned long data_len,
+ unsigned char *digest,
+ unsigned long *digest_len));
+_CK_DECLARE_FUNCTION (C_DigestUpdate,
+ (ck_session_handle_t session,
+ unsigned char *part, unsigned long part_len));
+_CK_DECLARE_FUNCTION (C_DigestKey,
+ (ck_session_handle_t session, ck_object_handle_t key));
+_CK_DECLARE_FUNCTION (C_DigestFinal,
+ (ck_session_handle_t session,
+ unsigned char *digest,
+ unsigned long *digest_len));
+
+_CK_DECLARE_FUNCTION (C_SignInit,
+ (ck_session_handle_t session,
+ struct ck_mechanism *mechanism,
+ ck_object_handle_t key));
+_CK_DECLARE_FUNCTION (C_Sign,
+ (ck_session_handle_t session,
+ unsigned char *data, unsigned long data_len,
+ unsigned char *signature,
+ unsigned long *signature_len));
+_CK_DECLARE_FUNCTION (C_SignUpdate,
+ (ck_session_handle_t session,
+ unsigned char *part, unsigned long part_len));
+_CK_DECLARE_FUNCTION (C_SignFinal,
+ (ck_session_handle_t session,
+ unsigned char *signature,
+ unsigned long *signature_len));
+_CK_DECLARE_FUNCTION (C_SignRecoverInit,
+ (ck_session_handle_t session,
+ struct ck_mechanism *mechanism,
+ ck_object_handle_t key));
+_CK_DECLARE_FUNCTION (C_SignRecover,
+ (ck_session_handle_t session,
+ unsigned char *data, unsigned long data_len,
+ unsigned char *signature,
+ unsigned long *signature_len));
+
+_CK_DECLARE_FUNCTION (C_VerifyInit,
+ (ck_session_handle_t session,
+ struct ck_mechanism *mechanism,
+ ck_object_handle_t key));
+_CK_DECLARE_FUNCTION (C_Verify,
+ (ck_session_handle_t session,
+ unsigned char *data, unsigned long data_len,
+ unsigned char *signature,
+ unsigned long signature_len));
+_CK_DECLARE_FUNCTION (C_VerifyUpdate,
+ (ck_session_handle_t session,
+ unsigned char *part, unsigned long part_len));
+_CK_DECLARE_FUNCTION (C_VerifyFinal,
+ (ck_session_handle_t session,
+ unsigned char *signature,
+ unsigned long signature_len));
+_CK_DECLARE_FUNCTION (C_VerifyRecoverInit,
+ (ck_session_handle_t session,
+ struct ck_mechanism *mechanism,
+ ck_object_handle_t key));
+_CK_DECLARE_FUNCTION (C_VerifyRecover,
+ (ck_session_handle_t session,
+ unsigned char *signature,
+ unsigned long signature_len,
+ unsigned char *data,
+ unsigned long *data_len));
+
+_CK_DECLARE_FUNCTION (C_DigestEncryptUpdate,
+ (ck_session_handle_t session,
+ unsigned char *part, unsigned long part_len,
+ unsigned char *encrypted_part,
+ unsigned long *encrypted_part_len));
+_CK_DECLARE_FUNCTION (C_DecryptDigestUpdate,
+ (ck_session_handle_t session,
+ unsigned char *encrypted_part,
+ unsigned long encrypted_part_len,
+ unsigned char *part,
+ unsigned long *part_len));
+_CK_DECLARE_FUNCTION (C_SignEncryptUpdate,
+ (ck_session_handle_t session,
+ unsigned char *part, unsigned long part_len,
+ unsigned char *encrypted_part,
+ unsigned long *encrypted_part_len));
+_CK_DECLARE_FUNCTION (C_DecryptVerifyUpdate,
+ (ck_session_handle_t session,
+ unsigned char *encrypted_part,
+ unsigned long encrypted_part_len,
+ unsigned char *part,
+ unsigned long *part_len));
+
+_CK_DECLARE_FUNCTION (C_GenerateKey,
+ (ck_session_handle_t session,
+ struct ck_mechanism *mechanism,
+ struct ck_attribute *templ,
+ unsigned long count,
+ ck_object_handle_t *key));
+_CK_DECLARE_FUNCTION (C_GenerateKeyPair,
+ (ck_session_handle_t session,
+ struct ck_mechanism *mechanism,
+ struct ck_attribute *public_key_template,
+ unsigned long public_key_attribute_count,
+ struct ck_attribute *private_key_template,
+ unsigned long private_key_attribute_count,
+ ck_object_handle_t *public_key,
+ ck_object_handle_t *private_key));
+_CK_DECLARE_FUNCTION (C_WrapKey,
+ (ck_session_handle_t session,
+ struct ck_mechanism *mechanism,
+ ck_object_handle_t wrapping_key,
+ ck_object_handle_t key,
+ unsigned char *wrapped_key,
+ unsigned long *wrapped_key_len));
+_CK_DECLARE_FUNCTION (C_UnwrapKey,
+ (ck_session_handle_t session,
+ struct ck_mechanism *mechanism,
+ ck_object_handle_t unwrapping_key,
+ unsigned char *wrapped_key,
+ unsigned long wrapped_key_len,
+ struct ck_attribute *templ,
+ unsigned long attribute_count,
+ ck_object_handle_t *key));
+_CK_DECLARE_FUNCTION (C_DeriveKey,
+ (ck_session_handle_t session,
+ struct ck_mechanism *mechanism,
+ ck_object_handle_t base_key,
+ struct ck_attribute *templ,
+ unsigned long attribute_count,
+ ck_object_handle_t *key));
+
+_CK_DECLARE_FUNCTION (C_SeedRandom,
+ (ck_session_handle_t session, unsigned char *seed,
+ unsigned long seed_len));
+_CK_DECLARE_FUNCTION (C_GenerateRandom,
+ (ck_session_handle_t session,
+ unsigned char *random_data,
+ unsigned long random_len));
+
+_CK_DECLARE_FUNCTION (C_GetFunctionStatus, (ck_session_handle_t session));
+_CK_DECLARE_FUNCTION (C_CancelFunction, (ck_session_handle_t session));
+
+
+struct ck_function_list
+{
+ struct ck_version version;
+ CK_C_Initialize C_Initialize;
+ CK_C_Finalize C_Finalize;
+ CK_C_GetInfo C_GetInfo;
+ CK_C_GetFunctionList C_GetFunctionList;
+ CK_C_GetSlotList C_GetSlotList;
+ CK_C_GetSlotInfo C_GetSlotInfo;
+ CK_C_GetTokenInfo C_GetTokenInfo;
+ CK_C_GetMechanismList C_GetMechanismList;
+ CK_C_GetMechanismInfo C_GetMechanismInfo;
+ CK_C_InitToken C_InitToken;
+ CK_C_InitPIN C_InitPIN;
+ CK_C_SetPIN C_SetPIN;
+ CK_C_OpenSession C_OpenSession;
+ CK_C_CloseSession C_CloseSession;
+ CK_C_CloseAllSessions C_CloseAllSessions;
+ CK_C_GetSessionInfo C_GetSessionInfo;
+ CK_C_GetOperationState C_GetOperationState;
+ CK_C_SetOperationState C_SetOperationState;
+ CK_C_Login C_Login;
+ CK_C_Logout C_Logout;
+ CK_C_CreateObject C_CreateObject;
+ CK_C_CopyObject C_CopyObject;
+ CK_C_DestroyObject C_DestroyObject;
+ CK_C_GetObjectSize C_GetObjectSize;
+ CK_C_GetAttributeValue C_GetAttributeValue;
+ CK_C_SetAttributeValue C_SetAttributeValue;
+ CK_C_FindObjectsInit C_FindObjectsInit;
+ CK_C_FindObjects C_FindObjects;
+ CK_C_FindObjectsFinal C_FindObjectsFinal;
+ CK_C_EncryptInit C_EncryptInit;
+ CK_C_Encrypt C_Encrypt;
+ CK_C_EncryptUpdate C_EncryptUpdate;
+ CK_C_EncryptFinal C_EncryptFinal;
+ CK_C_DecryptInit C_DecryptInit;
+ CK_C_Decrypt C_Decrypt;
+ CK_C_DecryptUpdate C_DecryptUpdate;
+ CK_C_DecryptFinal C_DecryptFinal;
+ CK_C_DigestInit C_DigestInit;
+ CK_C_Digest C_Digest;
+ CK_C_DigestUpdate C_DigestUpdate;
+ CK_C_DigestKey C_DigestKey;
+ CK_C_DigestFinal C_DigestFinal;
+ CK_C_SignInit C_SignInit;
+ CK_C_Sign C_Sign;
+ CK_C_SignUpdate C_SignUpdate;
+ CK_C_SignFinal C_SignFinal;
+ CK_C_SignRecoverInit C_SignRecoverInit;
+ CK_C_SignRecover C_SignRecover;
+ CK_C_VerifyInit C_VerifyInit;
+ CK_C_Verify C_Verify;
+ CK_C_VerifyUpdate C_VerifyUpdate;
+ CK_C_VerifyFinal C_VerifyFinal;
+ CK_C_VerifyRecoverInit C_VerifyRecoverInit;
+ CK_C_VerifyRecover C_VerifyRecover;
+ CK_C_DigestEncryptUpdate C_DigestEncryptUpdate;
+ CK_C_DecryptDigestUpdate C_DecryptDigestUpdate;
+ CK_C_SignEncryptUpdate C_SignEncryptUpdate;
+ CK_C_DecryptVerifyUpdate C_DecryptVerifyUpdate;
+ CK_C_GenerateKey C_GenerateKey;
+ CK_C_GenerateKeyPair C_GenerateKeyPair;
+ CK_C_WrapKey C_WrapKey;
+ CK_C_UnwrapKey C_UnwrapKey;
+ CK_C_DeriveKey C_DeriveKey;
+ CK_C_SeedRandom C_SeedRandom;
+ CK_C_GenerateRandom C_GenerateRandom;
+ CK_C_GetFunctionStatus C_GetFunctionStatus;
+ CK_C_CancelFunction C_CancelFunction;
+ CK_C_WaitForSlotEvent C_WaitForSlotEvent;
+};
+
+
+typedef ck_rv_t (*ck_createmutex_t) (void **mutex);
+typedef ck_rv_t (*ck_destroymutex_t) (void *mutex);
+typedef ck_rv_t (*ck_lockmutex_t) (void *mutex);
+typedef ck_rv_t (*ck_unlockmutex_t) (void *mutex);
+
+
+struct ck_c_initialize_args
+{
+ ck_createmutex_t create_mutex;
+ ck_destroymutex_t destroy_mutex;
+ ck_lockmutex_t lock_mutex;
+ ck_unlockmutex_t unlock_mutex;
+ ck_flags_t flags;
+ void *reserved;
+};
+
+
+#define CKF_LIBRARY_CANT_CREATE_OS_THREADS (1 << 0)
+#define CKF_OS_LOCKING_OK (1 << 1)
+
+#define CKR_OK (0)
+#define CKR_CANCEL (1)
+#define CKR_HOST_MEMORY (2)
+#define CKR_SLOT_ID_INVALID (3)
+#define CKR_GENERAL_ERROR (5)
+#define CKR_FUNCTION_FAILED (6)
+#define CKR_ARGUMENTS_BAD (7)
+#define CKR_NO_EVENT (8)
+#define CKR_NEED_TO_CREATE_THREADS (9)
+#define CKR_CANT_LOCK (0xa)
+#define CKR_ATTRIBUTE_READ_ONLY (0x10)
+#define CKR_ATTRIBUTE_SENSITIVE (0x11)
+#define CKR_ATTRIBUTE_TYPE_INVALID (0x12)
+#define CKR_ATTRIBUTE_VALUE_INVALID (0x13)
+#define CKR_DATA_INVALID (0x20)
+#define CKR_DATA_LEN_RANGE (0x21)
+#define CKR_DEVICE_ERROR (0x30)
+#define CKR_DEVICE_MEMORY (0x31)
+#define CKR_DEVICE_REMOVED (0x32)
+#define CKR_ENCRYPTED_DATA_INVALID (0x40)
+#define CKR_ENCRYPTED_DATA_LEN_RANGE (0x41)
+#define CKR_FUNCTION_CANCELED (0x50)
+#define CKR_FUNCTION_NOT_PARALLEL (0x51)
+#define CKR_FUNCTION_NOT_SUPPORTED (0x54)
+#define CKR_KEY_HANDLE_INVALID (0x60)
+#define CKR_KEY_SIZE_RANGE (0x62)
+#define CKR_KEY_TYPE_INCONSISTENT (0x63)
+#define CKR_KEY_NOT_NEEDED (0x64)
+#define CKR_KEY_CHANGED (0x65)
+#define CKR_KEY_NEEDED (0x66)
+#define CKR_KEY_INDIGESTIBLE (0x67)
+#define CKR_KEY_FUNCTION_NOT_PERMITTED (0x68)
+#define CKR_KEY_NOT_WRAPPABLE (0x69)
+#define CKR_KEY_UNEXTRACTABLE (0x6a)
+#define CKR_MECHANISM_INVALID (0x70)
+#define CKR_MECHANISM_PARAM_INVALID (0x71)
+#define CKR_OBJECT_HANDLE_INVALID (0x82)
+#define CKR_OPERATION_ACTIVE (0x90)
+#define CKR_OPERATION_NOT_INITIALIZED (0x91)
+#define CKR_PIN_INCORRECT (0xa0)
+#define CKR_PIN_INVALID (0xa1)
+#define CKR_PIN_LEN_RANGE (0xa2)
+#define CKR_PIN_EXPIRED (0xa3)
+#define CKR_PIN_LOCKED (0xa4)
+#define CKR_SESSION_CLOSED (0xb0)
+#define CKR_SESSION_COUNT (0xb1)
+#define CKR_SESSION_HANDLE_INVALID (0xb3)
+#define CKR_SESSION_PARALLEL_NOT_SUPPORTED (0xb4)
+#define CKR_SESSION_READ_ONLY (0xb5)
+#define CKR_SESSION_EXISTS (0xb6)
+#define CKR_SESSION_READ_ONLY_EXISTS (0xb7)
+#define CKR_SESSION_READ_WRITE_SO_EXISTS (0xb8)
+#define CKR_SIGNATURE_INVALID (0xc0)
+#define CKR_SIGNATURE_LEN_RANGE (0xc1)
+#define CKR_TEMPLATE_INCOMPLETE (0xd0)
+#define CKR_TEMPLATE_INCONSISTENT (0xd1)
+#define CKR_TOKEN_NOT_PRESENT (0xe0)
+#define CKR_TOKEN_NOT_RECOGNIZED (0xe1)
+#define CKR_TOKEN_WRITE_PROTECTED (0xe2)
+#define CKR_UNWRAPPING_KEY_HANDLE_INVALID (0xf0)
+#define CKR_UNWRAPPING_KEY_SIZE_RANGE (0xf1)
+#define CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT (0xf2)
+#define CKR_USER_ALREADY_LOGGED_IN (0x100)
+#define CKR_USER_NOT_LOGGED_IN (0x101)
+#define CKR_USER_PIN_NOT_INITIALIZED (0x102)
+#define CKR_USER_TYPE_INVALID (0x103)
+#define CKR_USER_ANOTHER_ALREADY_LOGGED_IN (0x104)
+#define CKR_USER_TOO_MANY_TYPES (0x105)
+#define CKR_WRAPPED_KEY_INVALID (0x110)
+#define CKR_WRAPPED_KEY_LEN_RANGE (0x112)
+#define CKR_WRAPPING_KEY_HANDLE_INVALID (0x113)
+#define CKR_WRAPPING_KEY_SIZE_RANGE (0x114)
+#define CKR_WRAPPING_KEY_TYPE_INCONSISTENT (0x115)
+#define CKR_RANDOM_SEED_NOT_SUPPORTED (0x120)
+#define CKR_RANDOM_NO_RNG (0x121)
+#define CKR_DOMAIN_PARAMS_INVALID (0x130)
+#define CKR_BUFFER_TOO_SMALL (0x150)
+#define CKR_SAVED_STATE_INVALID (0x160)
+#define CKR_INFORMATION_SENSITIVE (0x170)
+#define CKR_STATE_UNSAVEABLE (0x180)
+#define CKR_CRYPTOKI_NOT_INITIALIZED (0x190)
+#define CKR_CRYPTOKI_ALREADY_INITIALIZED (0x191)
+#define CKR_MUTEX_BAD (0x1a0)
+#define CKR_MUTEX_NOT_LOCKED (0x1a1)
+#define CKR_FUNCTION_REJECTED (0x200)
+#define CKR_VENDOR_DEFINED ((unsigned long) (1 << 31))
+
+
+
+/* Compatibility layer. */
+
+#ifdef CRYPTOKI_COMPAT
+
+#undef CK_DEFINE_FUNCTION
+#define CK_DEFINE_FUNCTION(retval, name) retval CK_SPEC name
+
+/* For NULL. */
+#include <stddef.h>
+
+typedef unsigned char CK_BYTE;
+typedef unsigned char CK_CHAR;
+typedef unsigned char CK_UTF8CHAR;
+typedef unsigned char CK_BBOOL;
+typedef unsigned long int CK_ULONG;
+typedef long int CK_LONG;
+typedef CK_BYTE *CK_BYTE_PTR;
+typedef CK_CHAR *CK_CHAR_PTR;
+typedef CK_UTF8CHAR *CK_UTF8CHAR_PTR;
+typedef CK_ULONG *CK_ULONG_PTR;
+typedef void *CK_VOID_PTR;
+typedef void **CK_VOID_PTR_PTR;
+#define CK_FALSE 0
+#define CK_TRUE 1
+#ifndef CK_DISABLE_TRUE_FALSE
+#ifndef FALSE
+#define FALSE 0
+#endif
+#ifndef TRUE
+#define TRUE 1
+#endif
+#endif
+
+typedef struct ck_version CK_VERSION;
+typedef struct ck_version *CK_VERSION_PTR;
+
+typedef struct ck_info CK_INFO;
+typedef struct ck_info *CK_INFO_PTR;
+
+typedef ck_slot_id_t *CK_SLOT_ID_PTR;
+
+typedef struct ck_slot_info CK_SLOT_INFO;
+typedef struct ck_slot_info *CK_SLOT_INFO_PTR;
+
+typedef struct ck_token_info CK_TOKEN_INFO;
+typedef struct ck_token_info *CK_TOKEN_INFO_PTR;
+
+typedef ck_session_handle_t *CK_SESSION_HANDLE_PTR;
+
+typedef struct ck_session_info CK_SESSION_INFO;
+typedef struct ck_session_info *CK_SESSION_INFO_PTR;
+
+typedef ck_object_handle_t *CK_OBJECT_HANDLE_PTR;
+
+typedef ck_object_class_t *CK_OBJECT_CLASS_PTR;
+
+typedef struct ck_attribute CK_ATTRIBUTE;
+typedef struct ck_attribute *CK_ATTRIBUTE_PTR;
+
+typedef struct ck_date CK_DATE;
+typedef struct ck_date *CK_DATE_PTR;
+
+typedef ck_mechanism_type_t *CK_MECHANISM_TYPE_PTR;
+
+typedef struct ck_mechanism CK_MECHANISM;
+typedef struct ck_mechanism *CK_MECHANISM_PTR;
+
+typedef struct ck_mechanism_info CK_MECHANISM_INFO;
+typedef struct ck_mechanism_info *CK_MECHANISM_INFO_PTR;
+
+typedef struct ck_function_list CK_FUNCTION_LIST;
+typedef struct ck_function_list *CK_FUNCTION_LIST_PTR;
+typedef struct ck_function_list **CK_FUNCTION_LIST_PTR_PTR;
+
+typedef struct ck_c_initialize_args CK_C_INITIALIZE_ARGS;
+typedef struct ck_c_initialize_args *CK_C_INITIALIZE_ARGS_PTR;
+
+#define NULL_PTR NULL
+
+/* Delete the helper macros defined at the top of the file. */
+#undef ck_flags_t
+#undef ck_version
+
+#undef ck_info
+#undef cryptoki_version
+#undef manufacturer_id
+#undef library_description
+#undef library_version
+
+#undef ck_notification_t
+#undef ck_slot_id_t
+
+#undef ck_slot_info
+#undef slot_description
+#undef hardware_version
+#undef firmware_version
+
+#undef ck_token_info
+#undef serial_number
+#undef max_session_count
+#undef session_count
+#undef max_rw_session_count
+#undef rw_session_count
+#undef max_pin_len
+#undef min_pin_len
+#undef total_public_memory
+#undef free_public_memory
+#undef total_private_memory
+#undef free_private_memory
+#undef utc_time
+
+#undef ck_session_handle_t
+#undef ck_user_type_t
+#undef ck_state_t
+
+#undef ck_session_info
+#undef slot_id
+#undef device_error
+
+#undef ck_object_handle_t
+#undef ck_object_class_t
+#undef ck_hw_feature_type_t
+#undef ck_key_type_t
+#undef ck_certificate_type_t
+#undef ck_attribute_type_t
+
+#undef ck_attribute
+#undef value
+#undef value_len
+
+#undef ck_date
+
+#undef ck_mechanism_type_t
+
+#undef ck_mechanism
+#undef parameter
+#undef parameter_len
+
+#undef ck_mechanism_info
+#undef min_key_size
+#undef max_key_size
+
+#undef ck_rv_t
+#undef ck_notify_t
+
+#undef ck_function_list
+
+#undef ck_createmutex_t
+#undef ck_destroymutex_t
+#undef ck_lockmutex_t
+#undef ck_unlockmutex_t
+
+#undef ck_c_initialize_args
+#undef create_mutex
+#undef destroy_mutex
+#undef lock_mutex
+#undef unlock_mutex
+#undef reserved
+
+#endif /* CRYPTOKI_COMPAT */
+
+
+/* System dependencies. */
+#if defined(_WIN32) || defined(CRYPTOKI_FORCE_WIN32)
+#pragma pack(pop, cryptoki)
+#endif
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* PKCS11_H */
diff --git a/gp11/tests/Makefile.am b/gp11/tests/Makefile.am
new file mode 100644
index 00000000..22aef2d4
--- /dev/null
+++ b/gp11/tests/Makefile.am
@@ -0,0 +1,39 @@
+UNIT_AUTO = \
+ unit-test-gp11-attributes.c \
+ unit-test-gp11-module.c \
+ unit-test-gp11-object.c \
+ unit-test-gp11-session.c \
+ unit-test-gp11-slot.c
+
+
+UNIT_FLAGS = \
+ -I.. \
+ -DEXTERNAL_TEST
+
+UNIT_PROMPT =
+
+UNIT_LIBS = \
+ $(GIO_LIBS) \
+ $(top_builddir)/gp11/libgp11.la \
+ libgp11-test-module.la
+
+include $(top_srcdir)/tests/check.make
+
+# ------------------------------------------------------------------------
+
+lib_LTLIBRARIES = libgp11-test-module.la
+
+libgp11_test_module_la_LDFLAGS = \
+ -avoid-version
+
+libgp11_test_module_la_CFLAGS = \
+ -I. -I../ \
+ -I$(top_srcdir) \
+ $(GLIB_CFLAGS)
+
+libgp11_test_module_la_SOURCES = \
+ gp11-test-module.c
+
+libgp11_test_module_la_LIBADD = \
+ $(top_builddir)/gp11/libgp11.la
+
diff --git a/gp11/tests/gp11-test-module.c b/gp11/tests/gp11-test-module.c
new file mode 100644
index 00000000..dbc2abe6
--- /dev/null
+++ b/gp11/tests/gp11-test-module.c
@@ -0,0 +1,1297 @@
+#include "config.h"
+
+#include "gp11.h"
+#include "pkcs11.h"
+
+#include <glib.h>
+
+#include <check.h>
+#include <string.h>
+
+static gboolean initialized = FALSE;
+static gchar *the_pin = NULL;
+
+typedef enum _Operation {
+ OP_FIND = 1,
+} Operation;
+
+typedef struct _Session {
+ CK_SESSION_HANDLE handle;
+ CK_SESSION_INFO info;
+ gboolean logged_in;
+ CK_USER_TYPE user_type;
+ GHashTable *objects;
+
+ Operation operation;
+ GList *matches;
+
+} Session;
+
+static guint unique_identifier = 100;
+static GHashTable *the_sessions = NULL;
+static GHashTable *the_objects = NULL;
+
+/*
+ * This is not a generic test module, it works in concert with the
+ * unit-test-gp11-module.c
+ */
+
+static void
+free_session (gpointer data)
+{
+ Session *sess = (Session*)data;
+ if (sess)
+ g_hash_table_destroy (sess->objects);
+ g_free (sess);
+}
+
+static CK_RV
+test_C_Initialize (CK_VOID_PTR pInitArgs)
+{
+ GP11Attributes *attrs;
+ CK_C_INITIALIZE_ARGS_PTR args;
+ void *mutex;
+ CK_RV rv;
+
+ fail_unless (initialized == FALSE, "Initialized same module twice, maybe module was not finalized, outstanding refs?");
+ fail_unless (pInitArgs != NULL, "Missing arguments");
+
+ args = (CK_C_INITIALIZE_ARGS_PTR)pInitArgs;
+ fail_unless (args->CreateMutex != NULL, "Missing CreateMutex");
+ fail_unless (args->DestroyMutex != NULL, "Missing DestroyMutex");
+ fail_unless (args->LockMutex != NULL, "Missing LockMutex");
+ fail_unless (args->UnlockMutex != NULL, "Missing UnlockMutex");
+
+ fail_unless ((args->CreateMutex) (NULL) == CKR_ARGUMENTS_BAD, "CreateMutex succeeded wrong");
+ fail_unless ((args->DestroyMutex) (NULL) == CKR_MUTEX_BAD, "DestroyMutex succeeded wrong");
+ fail_unless ((args->LockMutex) (NULL) == CKR_MUTEX_BAD, "LockMutex succeeded wrong");
+ fail_unless ((args->UnlockMutex) (NULL) == CKR_MUTEX_BAD, "UnlockMutex succeeded wrong");
+
+ /* Try to create an actual mutex */
+ rv = (args->CreateMutex) (&mutex);
+ fail_unless (rv == CKR_OK, "CreateMutex failed");
+ fail_unless (mutex != NULL, "CreateMutex created null mutex");
+
+ /* Try and lock the mutex */
+ rv = (args->LockMutex) (mutex);
+ fail_unless (rv == CKR_OK, "LockMutex failed");
+
+ /* Try and unlock the mutex */
+ rv = (args->UnlockMutex) (mutex);
+ fail_unless (rv == CKR_OK, "UnlockMutex failed");
+
+ /* Try and destroy the mutex */
+ rv = (args->DestroyMutex) (mutex);
+ fail_unless (rv == CKR_OK, "DestroyMutex failed");
+
+ /* Flags should allow OS locking and os threads */
+ fail_unless ((args->flags & CKF_OS_LOCKING_OK) == CKF_OS_LOCKING_OK, "Invalid CKF_OS_LOCKING_OK flag");
+ fail_unless ((args->flags & CKF_LIBRARY_CANT_CREATE_OS_THREADS) == 0, "Invalid CKF_LIBRARY_CANT_CREATE_OS_THREADS flag");
+
+ the_pin = g_strdup ("booo");
+ the_sessions = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, free_session);
+ the_objects = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify)gp11_attributes_unref);
+
+ /* Our token object */
+ attrs = gp11_attributes_newv (CKA_CLASS, GP11_ULONG, CKO_DATA,
+ CKA_LABEL, GP11_STRING, "TEST LABEL",
+ -1);
+ g_hash_table_insert (the_objects, GUINT_TO_POINTER (2), attrs);
+
+ initialized = TRUE;
+ return CKR_OK;
+}
+
+static CK_RV
+test_C_Finalize (CK_VOID_PTR pReserved)
+{
+
+
+ fail_unless (pReserved == NULL, "Invalid reserved pointer");
+ fail_unless (initialized == TRUE, "Finalize without being initialized");
+
+ initialized = FALSE;
+ g_hash_table_destroy (the_objects);
+ the_objects = NULL;
+
+ g_hash_table_destroy (the_sessions);
+ the_sessions = NULL;
+
+ g_free (the_pin);
+ return CKR_OK;
+}
+
+const static CK_INFO TEST_INFO = {
+ { CRYPTOKI_VERSION_MAJOR, CRYPTOKI_VERSION_MINOR },
+ "TEST MANUFACTURER ",
+ 0,
+ "TEST LIBRARY ",
+ { 45, 145 }
+};
+
+static CK_RV
+test_C_GetInfo (CK_INFO_PTR pInfo)
+{
+
+
+ fail_unless (pInfo != NULL, "Invalid pointer to GetInfo");
+ memcpy (pInfo, &TEST_INFO, sizeof (*pInfo));
+ return CKR_OK;
+}
+
+static CK_RV
+test_C_GetFunctionList (CK_FUNCTION_LIST_PTR_PTR list)
+{
+
+
+ fail_unless (list != NULL, "Invalid pointer passed to GetFunctionList");
+ return C_GetFunctionList (list);
+}
+
+#define TEST_SLOT_ONE 52
+#define TEST_SLOT_TWO 134
+
+/*
+ * Two slots
+ * ONE: token present
+ * TWO: token not present
+ */
+
+static CK_RV
+test_C_GetSlotList (CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount)
+{
+ CK_ULONG count;
+
+
+
+ fail_unless (pulCount != NULL, "Invalid pulCount");
+
+ count = tokenPresent ? 1 : 2;
+
+ /* Application only wants to know the number of slots. */
+ if (pSlotList == NULL) {
+ *pulCount = count;
+ return CKR_OK;
+ }
+
+ if (*pulCount < count) {
+ fail_unless (*pulCount, "Passed in a bad count");
+ return CKR_BUFFER_TOO_SMALL;
+ }
+
+ *pulCount = count;
+ pSlotList[0] = TEST_SLOT_ONE;
+ if (!tokenPresent)
+ pSlotList[1] = TEST_SLOT_TWO;
+
+ return CKR_OK;
+}
+
+const static CK_SLOT_INFO TEST_INFO_ONE = {
+ "TEST SLOT ",
+ "TEST MANUFACTURER ",
+ CKF_TOKEN_PRESENT | CKF_REMOVABLE_DEVICE,
+ { 55, 155 },
+ { 65, 165 },
+};
+
+const static CK_SLOT_INFO TEST_INFO_TWO = {
+ "TEST SLOT ",
+ "TEST MANUFACTURER ",
+ CKF_REMOVABLE_DEVICE,
+ { 55, 155 },
+ { 65, 165 },
+};
+
+static CK_RV
+test_C_GetSlotInfo (CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo)
+{
+
+
+ fail_unless (pInfo != NULL, "Invalid pInfo");
+
+ if (slotID == TEST_SLOT_ONE) {
+ memcpy (pInfo, &TEST_INFO_ONE, sizeof (*pInfo));
+ return CKR_OK;
+ } else if (slotID == TEST_SLOT_TWO) {
+ memcpy (pInfo, &TEST_INFO_TWO, sizeof (*pInfo));
+ return CKR_OK;
+ } else {
+ fail ("Invalid slot id");
+ return CKR_SLOT_ID_INVALID;
+ }
+}
+
+const static CK_TOKEN_INFO TEST_TOKEN_ONE = {
+ "TEST LABEL ",
+ "TEST MANUFACTURER ",
+ "TEST MODEL ",
+ "TEST SERIAL ",
+ CKF_LOGIN_REQUIRED | CKF_USER_PIN_INITIALIZED | CKF_CLOCK_ON_TOKEN | CKF_PROTECTED_AUTHENTICATION_PATH | CKF_TOKEN_INITIALIZED,
+ 1,
+ 2,
+ 3,
+ 4,
+ 5,
+ 6,
+ 7,
+ 8,
+ 9,
+ 10,
+ { 75, 175 },
+ { 85, 185 },
+ { '1', '9', '9', '9', '0', '5', '2', '5', '0', '9', '1', '9', '5', '9', '0', '0' }
+};
+
+static CK_RV
+test_C_GetTokenInfo (CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo)
+{
+
+
+ fail_unless (pInfo != NULL, "Invalid pInfo");
+
+ if (slotID == TEST_SLOT_ONE) {
+ memcpy (pInfo, &TEST_TOKEN_ONE, sizeof (*pInfo));
+ return CKR_OK;
+ } else if (slotID == TEST_SLOT_TWO) {
+ return CKR_TOKEN_NOT_PRESENT;
+ } else {
+ fail ("Invalid slot id");
+ return CKR_SLOT_ID_INVALID;
+ }
+}
+
+/*
+ * TWO mechanisms:
+ * RSA
+ * DSA
+ */
+
+static CK_RV
+test_C_GetMechanismList (CK_SLOT_ID slotID, CK_MECHANISM_TYPE_PTR pMechanismList,
+ CK_ULONG_PTR pulCount)
+{
+
+
+ fail_unless (slotID == TEST_SLOT_ONE, "Invalid slotID");
+ fail_unless (pulCount != NULL, "Invalid pulCount");
+
+ /* Application only wants to know the number of slots. */
+ if (pMechanismList == NULL) {
+ *pulCount = 2;
+ return CKR_OK;
+ }
+
+ if (*pulCount != 2) {
+ fail_unless (*pulCount, "Passed in a bad count");
+ return CKR_BUFFER_TOO_SMALL;
+ }
+
+ pMechanismList[0] = CKM_RSA_PKCS;
+ pMechanismList[1] = CKM_DSA;
+ return CKR_OK;
+}
+
+static const CK_MECHANISM_INFO TEST_MECH_RSA = {
+ 512, 4096, 0
+};
+
+static const CK_MECHANISM_INFO TEST_MECH_DSA = {
+ 2048, 2048, 0
+};
+
+static CK_RV
+test_C_GetMechanismInfo (CK_SLOT_ID slotID, CK_MECHANISM_TYPE type,
+ CK_MECHANISM_INFO_PTR pInfo)
+{
+
+
+ fail_unless (slotID == TEST_SLOT_ONE, "Invalid slotID");
+ fail_unless (pInfo != NULL, "Invalid pInfo");
+
+ if (type == CKM_RSA_PKCS) {
+ memcpy (pInfo, &TEST_MECH_RSA, sizeof (*pInfo));
+ return CKR_OK;
+ } else if (type == CKM_DSA) {
+ memcpy (pInfo, &TEST_MECH_DSA, sizeof (*pInfo));
+ return CKR_OK;
+ } else {
+ fail ("Invalid type");
+ return CKR_MECHANISM_INVALID;
+ }
+}
+
+static CK_RV
+test_C_InitToken (CK_SLOT_ID slotID, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen,
+ CK_UTF8CHAR_PTR pLabel)
+{
+ fail_unless (slotID == TEST_SLOT_ONE, "Invalid slotID");
+ fail_unless (pPin != NULL, "Invalid pPin");
+ fail_unless (strlen ("TEST PIN"), "Invalid ulPinLen");
+ fail_unless (strncmp ((gchar*)pPin, "TEST PIN", ulPinLen) == 0, "Invalid pPin string");
+ fail_unless (pLabel != NULL, "Invalid pLabel");
+ fail_unless (strcmp ((gchar*)pPin, "TEST LABEL") == 0, "Invalid pLabel string");
+
+ g_free (the_pin);
+ the_pin = g_strndup ((gchar*)pPin, ulPinLen);
+ return CKR_OK;
+}
+
+static CK_RV
+test_C_WaitForSlotEvent (CK_FLAGS flags, CK_SLOT_ID_PTR pSlot, CK_VOID_PTR pReserved)
+{
+ fail ("Not yet used by library");
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+#define TEST_RSA_KEY 257
+#define TEST_DSA_KEY 357
+
+#ifdef INCOMPLETE
+
+#define TEST_KEY \
+"(private-key (rsa " \
+"(n #00B78758D55EBFFAB61D07D0DC49B5309A6F1DA2AE51C275DFC2370959BB81AC0C39093B1C618E396161A0DECEB8768D0FFB14F197B96C3DA14190EE0F20D51315#)" \
+"(e #010001#)" \
+"(d #108BCAC5FDD35812981E6EC5957D98E2AB76E4064C47B861D27C2CC322C50792313C852B4164A035B42D261F1A09F9FFE8F477F9F78FF2EABBDA6BA875C671D7#)" \
+"(p #00C357F11B19A18C66573D25D1E466D9AB8BCDDCDFE0B2E80BD46712C4BEC18EB7#)" \
+"(q #00F0843B90A60EF7034CA4BE80414ED9497CABCC685143B388013FF989CBB0E093#)" \
+"(u #12F2555F52EB56329A991CF0404B51C68AC921AD370A797860F550415FF987BD#)" \
+"))"
+#endif
+
+static CK_RV
+test_C_OpenSession (CK_SLOT_ID slotID, CK_FLAGS flags, CK_VOID_PTR pApplication,
+ CK_NOTIFY Notify, CK_SESSION_HANDLE_PTR phSession)
+{
+ Session *sess;
+
+ fail_unless (slotID == TEST_SLOT_ONE, "Invalid slotID");
+ fail_unless (pApplication == NULL, "pApplication should be null");
+ fail_unless (Notify == NULL, "Notify should be null");
+ fail_unless (phSession != NULL, "Invalid phSession");
+ fail_unless ((flags & CKF_SERIAL_SESSION) == CKF_SERIAL_SESSION);
+
+ sess = g_new0 (Session, 1);
+ sess->handle = ++unique_identifier;
+ sess->info.flags = flags;
+ sess->info.slotID = slotID;
+ sess->info.state = 0;
+ sess->info.ulDeviceError = 1414;
+ sess->objects = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify)gp11_attributes_unref);
+ *phSession = sess->handle;
+
+ g_hash_table_replace (the_sessions, GUINT_TO_POINTER (sess->handle), sess);
+ return CKR_OK;
+}
+
+static CK_RV
+test_C_CloseSession (CK_SESSION_HANDLE hSession)
+{
+ Session *session;
+
+
+
+ session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
+ fail_unless (session != NULL, "No such session found");
+ if (!session)
+ return CKR_SESSION_HANDLE_INVALID;
+
+ g_hash_table_remove (the_sessions, GUINT_TO_POINTER (hSession));
+ return CKR_OK;
+}
+
+static CK_RV
+test_C_CloseAllSessions (CK_SLOT_ID slotID)
+{
+ fail_unless (slotID == TEST_SLOT_ONE, "Invalid slotID");
+
+
+
+ g_hash_table_remove_all (the_sessions);
+ return CKR_OK;
+}
+
+static CK_RV
+test_C_GetFunctionStatus (CK_SESSION_HANDLE hSession)
+{
+ fail ("Not yet used by library");
+ return CKR_FUNCTION_NOT_PARALLEL;
+}
+
+static CK_RV
+test_C_CancelFunction (CK_SESSION_HANDLE hSession)
+{
+ fail ("Not yet used by library");
+ return CKR_FUNCTION_NOT_PARALLEL;
+}
+
+static CK_RV
+test_C_GetSessionInfo (CK_SESSION_HANDLE hSession, CK_SESSION_INFO_PTR pInfo)
+{
+ Session *session;
+
+ fail_unless (pInfo != NULL, "Invalid pInfo");
+
+ session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
+ fail_unless (session != NULL, "No such session found");
+ if (!session)
+ return CKR_SESSION_HANDLE_INVALID;
+
+ memcpy (pInfo, &session->info, sizeof (*pInfo));
+ return CKR_OK;
+}
+
+static CK_RV
+test_C_InitPIN (CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pPin,
+ CK_ULONG ulPinLen)
+{
+ fail ("Not yet used by library");
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+test_C_SetPIN (CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pOldPin,
+ CK_ULONG ulOldLen, CK_UTF8CHAR_PTR pNewPin, CK_ULONG ulNewLen)
+{
+ fail ("Not yet used by library");
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+test_C_GetOperationState (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pOperationState,
+ CK_ULONG_PTR pulOperationStateLen)
+{
+ fail ("Not yet used by library");
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+test_C_SetOperationState (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pOperationState,
+ CK_ULONG ulOperationStateLen, CK_OBJECT_HANDLE hEncryptionKey,
+ CK_OBJECT_HANDLE hAuthenticationKey)
+{
+ fail ("Not yet used by library");
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+test_C_Login (CK_SESSION_HANDLE hSession, CK_USER_TYPE userType,
+ CK_UTF8CHAR_PTR pPin, CK_ULONG pPinLen)
+{
+ Session *session;
+
+ session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
+ fail_if (session == NULL, "No such session found");
+ if (!session)
+ return CKR_SESSION_HANDLE_INVALID;
+
+ fail_unless (pPinLen == strlen (the_pin), "Wrong PIN length");
+ fail_unless (strncmp ((gchar*)pPin, the_pin, pPinLen) == 0, "Wrong PIN");
+ fail_unless (userType == CKU_SO || userType == CKU_USER || userType == CKU_CONTEXT_SPECIFIC, "Bad user type");
+ fail_unless (session->logged_in == FALSE, "Already logged in");
+
+ session->logged_in = TRUE;
+ session->user_type = userType;
+ return CKR_OK;
+}
+
+static CK_RV
+test_C_Logout (CK_SESSION_HANDLE hSession)
+{
+ Session *session;
+
+ session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
+ fail_unless (session != NULL, "No such session found");
+ if (!session)
+ return CKR_SESSION_HANDLE_INVALID;
+
+ fail_unless (session->logged_in, "Not logged in");
+ session->logged_in = FALSE;
+ session->user_type = 0;
+ return CKR_OK;
+}
+
+static CK_RV
+test_C_CreateObject (CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate,
+ CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phObject)
+{
+ GP11Attributes *attrs;
+ Session *session;
+ gboolean token;
+ CK_ULONG i;
+
+ fail_if (phObject == NULL);
+
+ session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
+ fail_if (session == NULL, "No such session found");
+ if (!session)
+ return CKR_SESSION_HANDLE_INVALID;
+
+ attrs = gp11_attributes_new ();
+ for (i = 0; i < ulCount; ++i)
+ gp11_attributes_add_data (attrs, pTemplate[i].type, pTemplate[i].pValue, pTemplate[i].ulValueLen);
+
+ *phObject = ++unique_identifier;
+ if (gp11_attributes_find_boolean (attrs, CKA_TOKEN, &token) && token)
+ g_hash_table_insert (the_objects, GUINT_TO_POINTER (*phObject), attrs);
+ else
+ g_hash_table_insert (session->objects, GUINT_TO_POINTER (*phObject), attrs);
+
+ return CKR_OK;
+}
+
+static CK_RV
+test_C_CopyObject (CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
+ CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
+ CK_OBJECT_HANDLE_PTR phNewObject)
+{
+ fail ("Not yet used by library");
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+
+static CK_RV
+test_C_DestroyObject (CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject)
+{
+ Session *session;
+
+ session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
+ fail_if (session == NULL, "No such session found");
+ if (!session)
+ return CKR_SESSION_HANDLE_INVALID;
+
+ if (!g_hash_table_remove (the_objects, GUINT_TO_POINTER (hObject)) &&
+ !g_hash_table_remove (session->objects, GUINT_TO_POINTER (hObject))) {
+ fail ("no such object found");
+ return CKR_OBJECT_HANDLE_INVALID;
+ }
+
+ return CKR_OK;
+}
+
+static CK_RV
+test_C_GetObjectSize (CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
+ CK_ULONG_PTR pulSize)
+{
+ fail ("Not yet used by library");
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+test_C_GetAttributeValue (CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
+ CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
+{
+ CK_ATTRIBUTE_PTR result;
+ CK_RV ret = CKR_OK;
+ GP11Attributes *attrs;
+ GP11Attribute *attr;
+ Session *session;
+ CK_ULONG i;
+
+ session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
+ fail_if (session == NULL, "No such session found");
+ if (!session)
+ return CKR_SESSION_HANDLE_INVALID;
+
+ attrs = g_hash_table_lookup (the_objects, GUINT_TO_POINTER (hObject));
+ if (!attrs)
+ attrs = g_hash_table_lookup (session->objects, GUINT_TO_POINTER (hObject));
+ if (!attrs) {
+ fail ("invalid object handle passed");
+ return CKR_OBJECT_HANDLE_INVALID;
+ }
+
+ for (i = 0; i < ulCount; ++i) {
+ result = pTemplate + i;
+ attr = gp11_attributes_find (attrs, result->type);
+ if (!attr) {
+ result->ulValueLen = (CK_ULONG)-1;
+ ret = CKR_ATTRIBUTE_TYPE_INVALID;
+ continue;
+ }
+
+ if (!result->pValue) {
+ result->ulValueLen = attr->length;
+ continue;
+ }
+
+ if (result->ulValueLen >= attr->length) {
+ memcpy (result->pValue, attr->value, attr->length);
+ continue;
+ }
+
+ result->ulValueLen = (CK_ULONG)-1;
+ ret = CKR_BUFFER_TOO_SMALL;
+ }
+
+ return ret;
+}
+
+static CK_RV
+test_C_SetAttributeValue (CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
+ CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
+{
+ Session *session;
+ CK_ATTRIBUTE_PTR set;
+ GP11Attributes *attrs;
+ GP11Attribute *attr;
+ CK_ULONG i;
+
+ session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
+ fail_if (session == NULL, "No such session found");
+ if (!session)
+ return CKR_SESSION_HANDLE_INVALID;
+
+ attrs = g_hash_table_lookup (the_objects, GUINT_TO_POINTER (hObject));
+ if (!attrs)
+ attrs = g_hash_table_lookup (session->objects, GUINT_TO_POINTER (hObject));
+ if (!attrs) {
+ fail ("invalid object handle passed");
+ return CKR_OBJECT_HANDLE_INVALID;
+ }
+
+ for (i = 0; i < ulCount; ++i) {
+ set = pTemplate + i;
+ attr = gp11_attributes_find (attrs, set->type);
+ if (!attr) {
+ gp11_attributes_add_data (attrs, set->type, set->pValue, set->ulValueLen);
+ } else {
+ gp11_attribute_clear (attr);
+ gp11_attribute_init (attr, set->type, set->pValue, set->ulValueLen);
+ }
+ }
+
+ return CKR_OK;
+}
+
+static CK_RV
+test_C_FindObjectsInit (CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate,
+ CK_ULONG ulCount)
+{
+ GHashTableIter iter;
+ GP11Attributes *attrs;
+ GP11Attribute *attr;
+ CK_ATTRIBUTE_PTR match;
+ Session *session;
+ gpointer key, value;
+ gboolean matched = TRUE;
+ CK_ULONG i;
+
+ session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
+ fail_if (session == NULL, "No such session found");
+ if (!session)
+ return CKR_SESSION_HANDLE_INVALID;
+
+ if (session->operation != 0) {
+ fail ("invalid call to FindObjectsInit");
+ return CKR_OPERATION_ACTIVE;
+ }
+
+ session->operation = OP_FIND;
+
+ /* Token objects */
+ g_hash_table_iter_init (&iter, the_objects);
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ attrs = (GP11Attributes*)value;
+ matched = TRUE;
+ for (i = 0; i < ulCount; ++i) {
+ match = pTemplate + i;
+ attr = gp11_attributes_find (attrs, match->type);
+ if (!attr) {
+ matched = FALSE;
+ break;
+ }
+
+ if (attr->length != match->ulValueLen ||
+ memcmp (attr->value, match->pValue, attr->length) != 0) {
+ matched = FALSE;
+ break;
+ }
+ }
+
+ if (matched)
+ session->matches = g_list_prepend (session->matches, key);
+ }
+
+ /* session objects */
+ g_hash_table_iter_init (&iter, session->objects);
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ attrs = (GP11Attributes*)value;
+ matched = TRUE;
+ for (i = 0; i < ulCount; ++i) {
+ match = pTemplate + i;
+ attr = gp11_attributes_find (attrs, match->type);
+ if (!attr) {
+ matched = FALSE;
+ break;
+ }
+
+ if (attr->length != match->ulValueLen ||
+ memcmp (attr->value, match->pValue, attr->length) != 0) {
+ matched = FALSE;
+ break;
+ }
+ }
+
+ if (matched)
+ session->matches = g_list_prepend (session->matches, key);
+ }
+
+ return CKR_OK;
+}
+
+static CK_RV
+test_C_FindObjects (CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE_PTR phObject,
+ CK_ULONG ulMaxObjectCount, CK_ULONG_PTR pulObjectCount)
+{
+ Session *session;
+
+ fail_if (phObject == NULL);
+ fail_if (pulObjectCount == NULL);
+ fail_if (ulMaxObjectCount == 0);
+
+ session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
+ fail_if (session == NULL, "No such session found");
+ if (!session)
+ return CKR_SESSION_HANDLE_INVALID;
+
+ if (session->operation != OP_FIND) {
+ fail ("invalid call to FindObjects");
+ return CKR_OPERATION_NOT_INITIALIZED;
+ }
+
+ *pulObjectCount = 0;
+ while (ulMaxObjectCount > 0 && session->matches) {
+ *phObject = GPOINTER_TO_UINT (session->matches->data);
+ ++phObject;
+ --ulMaxObjectCount;
+ ++(*pulObjectCount);
+ session->matches = g_list_remove (session->matches, session->matches->data);
+ }
+
+ return CKR_OK;
+}
+
+static CK_RV
+test_C_FindObjectsFinal (CK_SESSION_HANDLE hSession)
+{
+
+ Session *session;
+
+ session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
+ fail_if (session == NULL, "No such session found");
+ if (!session)
+ return CKR_SESSION_HANDLE_INVALID;
+
+ if (session->operation != OP_FIND) {
+ fail ("invalid call to FindObjectsFinal");
+ return CKR_OPERATION_NOT_INITIALIZED;
+ }
+
+ session->operation = 0;
+ g_list_free (session->matches);
+ session->matches = NULL;
+
+ return CKR_OK;
+}
+
+static CK_RV
+test_C_EncryptInit (CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hKey)
+{
+#ifdef INCOMPLETE
+ Session *session;
+
+ session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
+ fail_if (session == NULL, "No such session found");
+ if (!session)
+ return CKR_SESSION_HANDLE_INVALID;
+
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ BEGIN_CALL (C_EncryptInit)
+ IN_SESSION (hSession)
+ IN_MECHANISM (pMechanism)
+ IN_HANDLE (hKey)
+ PROCESS_CALL ((hSession, pMechanism, hKey))
+ DONE_CALL
+#else
+ fail ("Not yet implemented");
+ return CKR_FUNCTION_NOT_SUPPORTED;
+#endif
+}
+
+static CK_RV
+test_C_Encrypt (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen,
+ CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen)
+{
+#ifdef INCOMPLETE
+ Session *session;
+
+ session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
+ fail_if (session == NULL, "No such session found");
+ if (!session)
+ return CKR_SESSION_HANDLE_INVALID;
+
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ BEGIN_CALL (C_Encrypt)
+ IN_SESSION (hSession)
+ IN_BYTE_ARRAY (pData, ulDataLen)
+ PROCESS_CALL ((hSession, pData, ulDataLen, pEncryptedData, pulEncryptedDataLen))
+ OUT_BYTE_ARRAY (pEncryptedData, pulEncryptedDataLen)
+ DONE_CALL
+#else
+ fail ("Not yet implemented");
+ return CKR_FUNCTION_NOT_SUPPORTED;
+#endif
+}
+
+static CK_RV
+test_C_EncryptUpdate (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
+ CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart,
+ CK_ULONG_PTR pulEncryptedPartLen)
+{
+ fail ("Not yet used by library");
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+test_C_EncryptFinal (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pLastEncryptedPart,
+ CK_ULONG_PTR pulLastEncryptedPartLen)
+{
+ fail ("Not yet used by library");
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+test_C_DecryptInit (CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hKey)
+{
+#ifdef INCOMPLETE
+ Session *session;
+
+ session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
+ fail_if (session == NULL, "No such session found");
+ if (!session)
+ return CKR_SESSION_HANDLE_INVALID;
+
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ BEGIN_CALL (C_DecryptInit)
+ IN_SESSION (hSession)
+ IN_MECHANISM (pMechanism)
+ IN_HANDLE (hKey)
+ PROCESS_CALL ((hSession, pMechanism, hKey))
+ DONE_CALL
+#else
+ fail ("Not yet implemented");
+ return CKR_FUNCTION_NOT_SUPPORTED;
+#endif
+}
+
+static CK_RV
+test_C_Decrypt (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData,
+ CK_ULONG pulEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
+{
+#ifdef INCOMPLETE
+ Session *session;
+
+ session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
+ fail_if (session == NULL, "No such session found");
+ if (!session)
+ return CKR_SESSION_HANDLE_INVALID;
+
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ BEGIN_CALL (C_Decrypt)
+ IN_SESSION (hSession)
+ IN_BYTE_ARRAY (pEncryptedData, pulEncryptedDataLen)
+ PROCESS_CALL ((hSession, pEncryptedData, pulEncryptedDataLen, pData, pulDataLen))
+ OUT_BYTE_ARRAY (pData, pulDataLen)
+ DONE_CALL
+#else
+ fail ("Not yet implemented");
+ return CKR_FUNCTION_NOT_SUPPORTED;
+#endif
+}
+
+static CK_RV
+test_C_DecryptUpdate (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedPart,
+ CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen)
+{
+ fail ("Not yet used by library");
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+test_C_DecryptFinal (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pLastPart,
+ CK_ULONG_PTR pulLastPartLen)
+{
+ fail ("Not yet used by library");
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+test_C_DigestInit (CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism)
+{
+ fail ("Not yet used by library");
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+test_C_Digest (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen,
+ CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen)
+{
+ fail ("Not yet used by library");
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+test_C_DigestUpdate (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
+{
+ fail ("Not yet used by library");
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+test_C_DigestKey (CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey)
+{
+ fail ("Not yet used by library");
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+test_C_DigestFinal (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pDigest,
+ CK_ULONG_PTR pulDigestLen)
+{
+ fail ("Not yet used by library");
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+test_C_SignInit (CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hKey)
+{
+#ifdef INCOMPLETE
+ Session *session;
+
+ session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
+ fail_if (session == NULL, "No such session found");
+ if (!session)
+ return CKR_SESSION_HANDLE_INVALID;
+
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+#else
+ fail ("Not yet implemented");
+ return CKR_FUNCTION_NOT_SUPPORTED;
+#endif
+}
+
+static CK_RV
+test_C_Sign (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen,
+ CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
+{
+#ifdef INCOMPLETE
+ Session *session;
+
+ session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
+ fail_if (session == NULL, "No such session found");
+ if (!session)
+ return CKR_SESSION_HANDLE_INVALID;
+
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+#else
+ fail ("Not yet implemented");
+ return CKR_FUNCTION_NOT_SUPPORTED;
+#endif
+}
+
+static CK_RV
+test_C_SignUpdate (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
+{
+ fail ("Not yet used by library");
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+test_C_SignFinal (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature,
+ CK_ULONG_PTR pulSignatureLen)
+{
+ fail ("Not yet used by library");
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+test_C_SignRecoverInit (CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hKey)
+{
+ fail ("Not yet used by library");
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+test_C_SignRecover (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen,
+ CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
+{
+ fail ("Not yet used by library");
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+test_C_VerifyInit (CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hKey)
+{
+#ifdef INCOMPLETE
+ Session *session;
+
+ session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
+ fail_if (session == NULL, "No such session found");
+ if (!session)
+ return CKR_SESSION_HANDLE_INVALID;
+
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ BEGIN_CALL (C_VerifyInit);
+ IN_SESSION (hSession)
+ IN_MECHANISM (pMechanism)
+ IN_HANDLE (hKey)
+ PROCESS_CALL ((hSession, pMechanism, hKey))
+ DONE_CALL
+#else
+ fail ("Not yet implemented");
+ return CKR_FUNCTION_NOT_SUPPORTED;
+#endif
+}
+
+static CK_RV
+test_C_Verify (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen,
+ CK_BYTE_PTR pSignature, CK_ULONG pulSignatureLen)
+{
+#ifdef INCOMPLETE
+ Session *session;
+
+ session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
+ fail_if (session == NULL, "No such session found");
+ if (!session)
+ return CKR_SESSION_HANDLE_INVALID;
+
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ BEGIN_CALL (C_Verify)
+ IN_SESSION (hSession)
+ IN_BYTE_ARRAY (pData, ulDataLen)
+ IN_BYTE_ARRAY (pSignature, pulSignatureLen)
+ PROCESS_CALL ((hSession, pData, ulDataLen, pSignature, pulSignatureLen))
+ DONE_CALL
+#else
+ fail ("Not yet implemented");
+ return CKR_FUNCTION_NOT_SUPPORTED;
+#endif
+}
+
+static CK_RV
+test_C_VerifyUpdate (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
+{
+ fail ("Not yet used by library");
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+test_C_VerifyFinal (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature,
+ CK_ULONG pulSignatureLen)
+{
+ fail ("Not yet used by library");
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+test_C_VerifyRecoverInit (CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hKey)
+{
+ fail ("Not yet used by library");
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+test_C_VerifyRecover (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature,
+ CK_ULONG pulSignatureLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
+{
+ fail ("Not yet used by library");
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+test_C_DigestEncryptUpdate (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
+ CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart,
+ CK_ULONG_PTR ulEncryptedPartLen)
+{
+ fail ("Not yet used by library");
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+test_C_DecryptDigestUpdate (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedPart,
+ CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart,
+ CK_ULONG_PTR pulPartLen)
+{
+ fail ("Not yet used by library");
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+test_C_SignEncryptUpdate (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
+ CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart,
+ CK_ULONG_PTR ulEncryptedPartLen)
+{
+ fail ("Not yet used by library");
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+test_C_DecryptVerifyUpdate (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedPart,
+ CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart,
+ CK_ULONG_PTR pulPartLen)
+{
+ fail ("Not yet used by library");
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+test_C_GenerateKey (CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
+ CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
+ CK_OBJECT_HANDLE_PTR phKey)
+{
+ fail ("Not yet used by library");
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+test_C_GenerateKeyPair (CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
+ CK_ATTRIBUTE_PTR pPublicKeyTemplate, CK_ULONG ulPublicKeyAttributeCount,
+ CK_ATTRIBUTE_PTR pPrivateKeyTemplate, CK_ULONG ulPrivateKeyAttributeCount,
+ CK_OBJECT_HANDLE_PTR phPublicKey, CK_OBJECT_HANDLE_PTR phPrivateKey)
+{
+ fail ("Not yet used by library");
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+test_C_WrapKey (CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hWrappingKey, CK_OBJECT_HANDLE hKey,
+ CK_BYTE_PTR pWrappedKey, CK_ULONG_PTR pulWrappedKeyLen)
+{
+ fail ("Not yet used by library");
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+test_C_UnwrapKey (CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE pUnwrappingKey, CK_BYTE_PTR pWrappedKey,
+ CK_ULONG pulWrappedKeyLen, CK_ATTRIBUTE_PTR pTemplate,
+ CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phKey)
+{
+ fail ("Not yet used by library");
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+test_C_DeriveKey (CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hBaseKey, CK_ATTRIBUTE_PTR pTemplate,
+ CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phKey)
+{
+ fail ("Not yet used by library");
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+test_C_SeedRandom (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSeed, CK_ULONG ulSeedLen)
+{
+ fail ("Not yet used by library");
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+test_C_GenerateRandom (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pRandomData,
+ CK_ULONG ulRandomLen)
+{
+ fail ("Not yet used by library");
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_FUNCTION_LIST functionList = {
+ { 2, 11 }, /* version */
+ test_C_Initialize,
+ test_C_Finalize,
+ test_C_GetInfo,
+ test_C_GetFunctionList,
+ test_C_GetSlotList,
+ test_C_GetSlotInfo,
+ test_C_GetTokenInfo,
+ test_C_GetMechanismList,
+ test_C_GetMechanismInfo,
+ test_C_InitToken,
+ test_C_InitPIN,
+ test_C_SetPIN,
+ test_C_OpenSession,
+ test_C_CloseSession,
+ test_C_CloseAllSessions,
+ test_C_GetSessionInfo,
+ test_C_GetOperationState,
+ test_C_SetOperationState,
+ test_C_Login,
+ test_C_Logout,
+ test_C_CreateObject,
+ test_C_CopyObject,
+ test_C_DestroyObject,
+ test_C_GetObjectSize,
+ test_C_GetAttributeValue,
+ test_C_SetAttributeValue,
+ test_C_FindObjectsInit,
+ test_C_FindObjects,
+ test_C_FindObjectsFinal,
+ test_C_EncryptInit,
+ test_C_Encrypt,
+ test_C_EncryptUpdate,
+ test_C_EncryptFinal,
+ test_C_DecryptInit,
+ test_C_Decrypt,
+ test_C_DecryptUpdate,
+ test_C_DecryptFinal,
+ test_C_DigestInit,
+ test_C_Digest,
+ test_C_DigestUpdate,
+ test_C_DigestKey,
+ test_C_DigestFinal,
+ test_C_SignInit,
+ test_C_Sign,
+ test_C_SignUpdate,
+ test_C_SignFinal,
+ test_C_SignRecoverInit,
+ test_C_SignRecover,
+ test_C_VerifyInit,
+ test_C_Verify,
+ test_C_VerifyUpdate,
+ test_C_VerifyFinal,
+ test_C_VerifyRecoverInit,
+ test_C_VerifyRecover,
+ test_C_DigestEncryptUpdate,
+ test_C_DecryptDigestUpdate,
+ test_C_SignEncryptUpdate,
+ test_C_DecryptVerifyUpdate,
+ test_C_GenerateKey,
+ test_C_GenerateKeyPair,
+ test_C_WrapKey,
+ test_C_UnwrapKey,
+ test_C_DeriveKey,
+ test_C_SeedRandom,
+ test_C_GenerateRandom,
+ test_C_GetFunctionStatus,
+ test_C_CancelFunction,
+ test_C_WaitForSlotEvent
+};
+
+CK_RV
+C_GetFunctionList (CK_FUNCTION_LIST_PTR_PTR list)
+{
+ if (!list)
+ return CKR_ARGUMENTS_BAD;
+
+ *list = &functionList;
+ return CKR_OK;
+}
diff --git a/gp11/tests/gp11-test.h b/gp11/tests/gp11-test.h
new file mode 100644
index 00000000..cf092260
--- /dev/null
+++ b/gp11/tests/gp11-test.h
@@ -0,0 +1,22 @@
+#ifndef TESTGP11HELPERS_H_
+#define TESTGP11HELPERS_H_
+
+#include "gp11.h"
+
+#define FAIL_RES(res, e) do { \
+ fail_if (res ? TRUE : FALSE, "should have failed"); \
+ fail_unless ((e) && (e)->message, "error should be set"); \
+ g_clear_error (&e); \
+ } while (0)
+
+#define SUCCESS_RES(res, err) do { \
+ if (!res) g_printerr ("error: %s\n", err && err->message ? err->message : ""); \
+ fail_unless (res ? TRUE : FALSE, "should have succeeded"); \
+ g_clear_error (&err); \
+ } while(0)
+
+
+#define WAIT_UNTIL(cond) \
+ while(!cond) g_main_iteration (TRUE);
+
+#endif /*TESTGP11HELPERS_H_*/
diff --git a/gp11/tests/unit-test-gp11-attributes.c b/gp11/tests/unit-test-gp11-attributes.c
new file mode 100644
index 00000000..d814ebf6
--- /dev/null
+++ b/gp11/tests/unit-test-gp11-attributes.c
@@ -0,0 +1,440 @@
+
+#include <check.h>
+
+#include <glib.h>
+#include <string.h>
+
+#include "run-auto-test.h"
+#include "gp11-test.h"
+
+#define ATTR_TYPE 55
+#define ATTR_DATA "TEST DATA"
+#define N_ATTR_DATA 9
+
+DEFINE_TEST(init_memory)
+{
+ GP11Attribute attr;
+
+ fail_if (sizeof (attr) != sizeof (CK_ATTRIBUTE));
+
+ gp11_attribute_init (&attr, ATTR_TYPE, ATTR_DATA, N_ATTR_DATA);
+ fail_unless (attr.type == ATTR_TYPE);
+ fail_unless (attr.length == N_ATTR_DATA);
+ fail_unless (memcmp (attr.value, ATTR_DATA, attr.length) == 0);
+
+ gp11_attribute_clear (&attr);
+}
+
+DEFINE_TEST(init_boolean)
+{
+ GP11Attribute attr;
+
+ gp11_attribute_init_boolean (&attr, ATTR_TYPE, TRUE);
+ fail_unless (attr.type == ATTR_TYPE);
+ fail_unless (attr.length == sizeof (CK_BBOOL));
+ fail_unless (*((CK_BBOOL*)attr.value) == CK_TRUE);
+
+ gp11_attribute_clear (&attr);
+}
+
+DEFINE_TEST(init_date)
+{
+ GP11Attribute attr;
+ CK_DATE ck_date;
+ GDate *date;
+
+ date = g_date_new_dmy(05, 06, 1960);
+ memcpy (ck_date.year, "1960", 4);
+ memcpy (ck_date.month, "06", 2);
+ memcpy (ck_date.day, "05", 2);
+ gp11_attribute_init_date (&attr, ATTR_TYPE, date);
+ g_date_free (date);
+ fail_unless (attr.type == ATTR_TYPE);
+ fail_unless (attr.length == sizeof (CK_DATE));
+ fail_unless (memcmp (attr.value, &ck_date, attr.length) == 0);
+
+ gp11_attribute_clear (&attr);
+}
+
+DEFINE_TEST(init_ulong)
+{
+ GP11Attribute attr;
+
+ gp11_attribute_init_ulong (&attr, ATTR_TYPE, 88);
+ fail_unless (attr.type == ATTR_TYPE);
+ fail_unless (attr.length == sizeof (CK_ULONG));
+ fail_unless (*((CK_ULONG*)attr.value) == 88);
+
+ gp11_attribute_clear (&attr);
+}
+
+DEFINE_TEST(init_string)
+{
+ GP11Attribute attr;
+
+ gp11_attribute_init_string (&attr, ATTR_TYPE, "a test string");
+ fail_unless (attr.type == ATTR_TYPE);
+ fail_unless (attr.length == strlen ("a test string"));
+ fail_unless (memcmp (attr.value, "a test string", attr.length) == 0);
+
+ gp11_attribute_clear (&attr);
+}
+
+DEFINE_TEST(new_memory)
+{
+ GP11Attribute *attr;
+
+ attr = gp11_attribute_new (ATTR_TYPE, ATTR_DATA, N_ATTR_DATA);
+ fail_unless (attr->type == ATTR_TYPE);
+ fail_unless (attr->length == N_ATTR_DATA);
+ fail_unless (memcmp (attr->value, ATTR_DATA, attr->length) == 0);
+
+ gp11_attribute_free (attr);
+}
+
+DEFINE_TEST(new_boolean)
+{
+ GP11Attribute *attr;
+
+ attr = gp11_attribute_new_boolean (ATTR_TYPE, TRUE);
+ fail_unless (attr->type == ATTR_TYPE);
+ fail_unless (attr->length == sizeof (CK_BBOOL));
+ fail_unless (*((CK_BBOOL*)attr->value) == CK_TRUE);
+
+ gp11_attribute_free (attr);
+}
+
+DEFINE_TEST(new_date)
+{
+ GP11Attribute *attr;
+ CK_DATE ck_date;
+ GDate *date;
+
+ date = g_date_new_dmy(05, 06, 1800);
+ memcpy (ck_date.year, "1800", 4);
+ memcpy (ck_date.month, "06", 2);
+ memcpy (ck_date.day, "05", 2);
+ attr = gp11_attribute_new_date (ATTR_TYPE, date);
+ g_date_free (date);
+ fail_unless (attr->type == ATTR_TYPE);
+ fail_unless (attr->length == sizeof (CK_DATE));
+ fail_unless (memcmp (attr->value, &ck_date, attr->length) == 0);
+
+ gp11_attribute_free (attr);
+}
+
+DEFINE_TEST(new_ulong)
+{
+ GP11Attribute *attr;
+
+ attr = gp11_attribute_new_ulong (ATTR_TYPE, 88);
+ fail_unless (attr->type == ATTR_TYPE);
+ fail_unless (attr->length == sizeof (CK_ULONG));
+ fail_unless (*((CK_ULONG*)attr->value) == 88);
+
+ gp11_attribute_free (attr);
+}
+
+DEFINE_TEST(new_string)
+{
+ GP11Attribute *attr;
+
+ attr = gp11_attribute_new_string (ATTR_TYPE, "a test string");
+ fail_unless (attr->type == ATTR_TYPE);
+ fail_unless (attr->length == strlen ("a test string"));
+ fail_unless (memcmp (attr->value, "a test string", attr->length) == 0);
+
+ gp11_attribute_free (attr);
+}
+
+DEFINE_TEST(get_boolean)
+{
+ GP11Attribute *attr;
+
+ attr = gp11_attribute_new_boolean (ATTR_TYPE, TRUE);
+ fail_unless (gp11_attribute_get_boolean (attr) == TRUE);
+ gp11_attribute_free (attr);
+}
+
+DEFINE_TEST(get_date)
+{
+ GP11Attribute *attr;
+ CK_DATE ck_date;
+ GDate *date, *date2;
+
+ date = g_date_new_dmy(05, 06, 1800);
+ memcpy (ck_date.year, "1800", 4);
+ memcpy (ck_date.month, "06", 2);
+ memcpy (ck_date.day, "05", 2);
+ attr = gp11_attribute_new_date (ATTR_TYPE, date);
+ date2 = gp11_attribute_get_date (attr);
+ fail_unless (g_date_compare (date, date2) == 0);
+ g_date_free (date);
+ g_date_free (date2);
+ gp11_attribute_free (attr);
+}
+
+DEFINE_TEST(get_ulong)
+{
+ GP11Attribute *attr;
+
+ attr = gp11_attribute_new_ulong (ATTR_TYPE, 88);
+ fail_unless (gp11_attribute_get_ulong (attr) == 88);
+ gp11_attribute_free (attr);
+}
+
+DEFINE_TEST(get_string)
+{
+ GP11Attribute *attr;
+ gchar *value;
+
+ attr = gp11_attribute_new_string (ATTR_TYPE, "a test string");
+ value = gp11_attribute_get_string (attr);
+ fail_unless (strcmp ("a test string", value) == 0);
+ g_free (value);
+ gp11_attribute_free (attr);
+
+ /* Should be able to store null strings */
+ attr = gp11_attribute_new_string (ATTR_TYPE, NULL);
+ value = gp11_attribute_get_string (attr);
+ fail_unless (value == NULL);
+ gp11_attribute_free (attr);
+}
+
+DEFINE_TEST(dup_attribute)
+{
+ GP11Attribute attr, *dup;
+
+ gp11_attribute_init_ulong (&attr, ATTR_TYPE, 88);
+ dup = gp11_attribute_dup (&attr);
+ gp11_attribute_clear (&attr);
+ fail_unless (gp11_attribute_get_ulong (dup) == 88);
+ fail_unless (dup->type == ATTR_TYPE);
+ gp11_attribute_free (dup);
+
+ /* Should be able to dup null */
+ dup = gp11_attribute_dup (NULL);
+ fail_if (dup != NULL);
+}
+
+DEFINE_TEST(copy_attribute)
+{
+ GP11Attribute attr, copy;
+
+ gp11_attribute_init_ulong (&attr, ATTR_TYPE, 88);
+ gp11_attribute_init_copy (&copy, &attr);
+ gp11_attribute_clear (&attr);
+ fail_unless (gp11_attribute_get_ulong (&copy) == 88);
+ fail_unless (copy.type == ATTR_TYPE);
+ gp11_attribute_clear (&copy);
+}
+
+DEFINE_TEST(new_attributes)
+{
+ GP11Attributes *attrs;
+
+ attrs = gp11_attributes_new ();
+ fail_if (attrs == NULL);
+ fail_unless (gp11_attributes_count (attrs) == 0);
+
+ gp11_attributes_ref (attrs);
+ gp11_attributes_unref (attrs);
+
+ gp11_attributes_unref (attrs);
+
+ /* Can unref NULL */
+ gp11_attributes_unref (NULL);
+}
+
+static void
+test_attributes_contents (GP11Attributes *attrs)
+{
+ GP11Attribute *attr;
+ gchar *value;
+ GDate *date, *check;
+
+ fail_if (attrs == NULL);
+ fail_unless (gp11_attributes_count (attrs) == 5);
+
+ attr = gp11_attributes_at (attrs, 0);
+ fail_unless (attr->type == 0);
+ fail_unless (gp11_attribute_get_boolean (attr) == TRUE);
+
+ attr = gp11_attributes_at (attrs, 1);
+ fail_unless (attr->type == 101);
+ fail_unless (gp11_attribute_get_ulong (attr) == 888);
+
+ attr = gp11_attributes_at (attrs, 2);
+ fail_unless (attr->type == 202);
+ value = gp11_attribute_get_string (attr);
+ fail_unless (strcmp (value, "string") == 0);
+ g_free (value);
+
+ attr = gp11_attributes_at (attrs, 3);
+ fail_unless (attr->type == 303);
+ check = g_date_new_dmy (11, 12, 2008);
+ date = gp11_attribute_get_date (attr);
+ fail_unless (g_date_compare (date, check) == 0);
+ g_date_free (date);
+ g_date_free (check);
+
+ attr = gp11_attributes_at (attrs, 4);
+ fail_unless (attr->type == 404);
+ fail_unless (attr->length == N_ATTR_DATA);
+ fail_unless (memcmp (attr->value, ATTR_DATA, N_ATTR_DATA) == 0);
+}
+
+DEFINE_TEST(newv_attributes)
+{
+ GDate *date = g_date_new_dmy (11, 12, 2008);
+ GP11Attributes *attrs;
+ attrs = gp11_attributes_newv (0, GP11_BOOLEAN, TRUE,
+ 101, GP11_ULONG, 888,
+ 202, GP11_STRING, "string",
+ 303, GP11_DATE, date,
+ 404, N_ATTR_DATA, ATTR_DATA,
+ -1);
+ g_date_free (date);
+
+ test_attributes_contents (attrs);
+ gp11_attributes_unref (attrs);
+
+ /* An empty one */
+ attrs = gp11_attributes_newv (-1);
+ gp11_attributes_unref (attrs);
+}
+
+static GP11Attributes*
+help_attributes_valist (int dummy, ...)
+{
+ GP11Attributes *attrs;
+ va_list va;
+
+ va_start (va, dummy);
+ attrs = gp11_attributes_new_valist (va);
+ va_end (va);
+
+ return attrs;
+}
+
+DEFINE_TEST(new_valist_attributes)
+{
+ GP11Attributes *attrs;
+ GDate *date = g_date_new_dmy (11, 12, 2008);
+
+ attrs = help_attributes_valist (232434243, /* Not used */
+ 0, GP11_BOOLEAN, TRUE,
+ 101, GP11_ULONG, 888,
+ 202, GP11_STRING, "string",
+ 303, GP11_DATE, date,
+ 404, N_ATTR_DATA, ATTR_DATA,
+ -1);
+
+ g_date_free (date);
+ test_attributes_contents (attrs);
+ gp11_attributes_unref (attrs);
+}
+
+DEFINE_ABORT(bad_length)
+{
+ GP11Attributes *attrs;
+
+ /* We should catch this with a warning */
+ attrs = gp11_attributes_newv (1, G_MAXSSIZE + 500U, GP11_ULONG, "invalid data",
+ -1);
+
+ gp11_attributes_unref (attrs);
+}
+
+DEFINE_TEST(add_data_attributes)
+{
+ GP11Attributes *attrs;
+ GDate *date = g_date_new_dmy (11, 12, 2008);
+ attrs = gp11_attributes_new ();
+ gp11_attributes_add_boolean (attrs, 0, TRUE);
+ gp11_attributes_add_ulong (attrs, 101, 888);
+ gp11_attributes_add_string (attrs, 202, "string");
+ gp11_attributes_add_date (attrs, 303, date);
+ g_date_free (date);
+ gp11_attributes_add_data (attrs, 404, ATTR_DATA, N_ATTR_DATA);
+ test_attributes_contents (attrs);
+ gp11_attributes_unref (attrs);
+}
+
+DEFINE_TEST(add_attributes)
+{
+ GP11Attributes *attrs;
+ GP11Attribute attr;
+
+ GDate *date = g_date_new_dmy (11, 12, 2008);
+ attrs = gp11_attributes_new ();
+
+ gp11_attribute_init_boolean (&attr, 0, TRUE);
+ gp11_attributes_add (attrs, &attr);
+ gp11_attribute_clear (&attr);
+
+ gp11_attribute_init_ulong (&attr, 101, 888);
+ gp11_attributes_add (attrs, &attr);
+ gp11_attribute_clear (&attr);
+
+ gp11_attribute_init_string (&attr, 202, "string");
+ gp11_attributes_add (attrs, &attr);
+ gp11_attribute_clear (&attr);
+
+ gp11_attribute_init_date (&attr, 303, date);
+ gp11_attributes_add (attrs, &attr);
+ gp11_attribute_clear (&attr);
+ g_date_free (date);
+
+ gp11_attribute_init (&attr, 404, ATTR_DATA, N_ATTR_DATA);
+ gp11_attributes_add (attrs, &attr);
+ gp11_attribute_clear (&attr);
+
+ test_attributes_contents (attrs);
+ gp11_attributes_unref (attrs);
+}
+
+
+DEFINE_TEST(find_attributes)
+{
+ GP11Attribute *attr;
+ GDate *check, *date = g_date_new_dmy (13, 12, 2008);
+ gboolean bvalue, ret;
+ gulong uvalue;
+ gchar *svalue;
+
+ GP11Attributes *attrs;
+ attrs = gp11_attributes_newv (0, GP11_BOOLEAN, TRUE,
+ 101, GP11_ULONG, 888,
+ 202, GP11_STRING, "string",
+ 303, GP11_DATE, date,
+ 404, N_ATTR_DATA, ATTR_DATA,
+ -1);
+
+ attr = gp11_attributes_find (attrs, 404);
+ fail_if (attr == NULL);
+ fail_unless (attr->length == N_ATTR_DATA);
+ fail_unless (memcmp (attr->value, ATTR_DATA, N_ATTR_DATA) == 0);
+
+ ret = gp11_attributes_find_boolean (attrs, 0, &bvalue);
+ fail_unless (ret == TRUE);
+ fail_unless (bvalue == TRUE);
+
+ ret = gp11_attributes_find_ulong (attrs, 101, &uvalue);
+ fail_unless (ret == TRUE);
+ fail_unless (uvalue == 888);
+
+ ret = gp11_attributes_find_string (attrs, 202, &svalue);
+ fail_unless (ret == TRUE);
+ fail_if (svalue == NULL);
+ fail_unless (strcmp (svalue, "string") == 0);
+ g_free (svalue);
+
+ ret = gp11_attributes_find_date (attrs, 303, &check);
+ fail_unless (ret == TRUE);
+ fail_if (check == NULL);
+ fail_unless (g_date_compare (date, check) == 0);
+ g_date_free (check);
+
+ gp11_attributes_unref (attrs);
+}
diff --git a/gp11/tests/unit-test-gp11-module.c b/gp11/tests/unit-test-gp11-module.c
new file mode 100644
index 00000000..2f0599dc
--- /dev/null
+++ b/gp11/tests/unit-test-gp11-module.c
@@ -0,0 +1,67 @@
+
+#include <check.h>
+
+#include <glib.h>
+#include <string.h>
+
+#include "run-auto-test.h"
+#include "gp11-test.h"
+
+static GP11Module *module = NULL;
+
+DEFINE_SETUP(load_module)
+{
+ GError *err = NULL;
+
+ /* Successful load */
+ module = gp11_module_initialize (".libs/libgp11-test-module.so", &err);
+ SUCCESS_RES (module, err);
+}
+
+DEFINE_TEARDOWN(load_module)
+{
+ g_object_unref (module);
+}
+
+DEFINE_TEST(invalid_modules)
+{
+ GP11Module *invalid;
+ GError *err = NULL;
+
+ /* Shouldn't be able to load modules */
+ invalid = gp11_module_initialize ("blah-blah-non-existant", &err);
+ FAIL_RES (invalid, err);
+
+ /* Shouldn't be able to load any file successfully */
+ invalid = gp11_module_initialize ("/usr/lib/libm.so", &err);
+ FAIL_RES (invalid, err);
+
+}
+
+DEFINE_TEST(module_props)
+{
+ gchar *path;
+
+ g_object_get (module, "module-path", &path, NULL);
+ fail_unless (path != NULL, "no module-path");
+ fail_unless (strcmp (".libs/libgp11-test-module.so", path) == 0, "module path wrong");
+ g_free (path);
+}
+
+DEFINE_TEST(module_info)
+{
+ GP11ModuleInfo *info;
+
+ info = gp11_module_get_info (module);
+ fail_unless (info != NULL, "no module info");
+
+ fail_unless (info->pkcs11_version_major == CRYPTOKI_VERSION_MAJOR, "wrong major version");
+ fail_unless (info->pkcs11_version_minor == CRYPTOKI_VERSION_MINOR, "wrong minor version");
+ fail_unless (strcmp ("TEST MANUFACTURER", info->manufacturer_id) == 0);
+ fail_unless (strcmp ("TEST LIBRARY", info->library_description) == 0);
+ fail_unless (0 == info->flags);
+ fail_unless (45 == info->library_version_major);
+ fail_unless (145 == info->library_version_minor);
+
+ gp11_module_info_free (info);
+}
diff --git a/gp11/tests/unit-test-gp11-object.c b/gp11/tests/unit-test-gp11-object.c
new file mode 100644
index 00000000..50784a39
--- /dev/null
+++ b/gp11/tests/unit-test-gp11-object.c
@@ -0,0 +1,369 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "run-auto-test.h"
+
+#include <glib.h>
+
+#include "gp11-test.h"
+
+static GP11Module *module = NULL;
+static GP11Slot *slot = NULL;
+static GP11Session *session = NULL;
+static GP11Object *object = NULL;
+
+DEFINE_SETUP(prep_object)
+{
+ GError *err = NULL;
+ GList *slots;
+
+ /* Successful load */
+ module = gp11_module_initialize (".libs/libgp11-test-module.so", &err);
+ SUCCESS_RES (module, err);
+
+ slots = gp11_module_get_slots (module, TRUE);
+ fail_if (slots == NULL);
+
+ slot = GP11_SLOT (slots->data);
+ g_object_ref (slot);
+ gp11_list_unref_free (slots);
+
+ session = gp11_slot_open_session (slot, 0, &err);
+ SUCCESS_RES(session, err);
+
+ /* Our module always exports a token object with this */
+ object = gp11_object_from_handle (session, 2);
+ fail_if (object == NULL);
+}
+
+DEFINE_TEARDOWN(prep_object)
+{
+ g_object_unref (object);
+ g_object_unref (session);
+ g_object_unref (slot);
+ g_object_unref (module);
+}
+
+DEFINE_TEST(object_props)
+{
+ GP11Session *sess;
+ GP11Module *mod;
+ CK_OBJECT_HANDLE handle;
+ g_object_get (object, "session", &sess, "module", &mod, "handle", &handle, NULL);
+ fail_unless (sess == session);
+ g_object_unref (session);
+ fail_unless (module == mod);
+ g_object_unref (mod);
+ fail_unless (handle == 2);
+}
+
+static void
+fetch_async_result (GObject *source, GAsyncResult *result, gpointer user_data)
+{
+ *((GAsyncResult**)user_data) = result;
+ g_object_ref (result);
+}
+
+DEFINE_TEST(create_object)
+{
+ GAsyncResult *result = NULL;
+ GP11Attributes *attrs;
+ GP11Object *object;
+ CK_OBJECT_HANDLE last_handle;
+ GError *err = NULL;
+
+ /* Using simple */
+ object = gp11_session_create_object (session, &err,
+ CKA_CLASS, GP11_ULONG, CKO_DATA,
+ CKA_LABEL, GP11_STRING, "TEST LABEL",
+ CKA_TOKEN, GP11_BOOLEAN, CK_FALSE,
+ CKA_VALUE, 4, "BLAH",
+ -1);
+ SUCCESS_RES (object, err);
+ fail_unless (GP11_IS_OBJECT (object));
+
+ if (object) {
+ last_handle = object->handle;
+ g_object_unref (object);
+ }
+
+ /* Using full */
+ attrs = gp11_attributes_newv (CKA_CLASS, GP11_ULONG, CKO_DATA,
+ CKA_LABEL, GP11_STRING, "TEST LABEL",
+ CKA_TOKEN, GP11_BOOLEAN, CK_FALSE,
+ CKA_VALUE, 4, "BLAH",
+ -1);
+
+ object = gp11_session_create_object_full (session, attrs, NULL, &err);
+ fail_unless (GP11_IS_OBJECT (object));
+ SUCCESS_RES (object, err);
+
+ if (object) {
+ fail_if (last_handle == object->handle);
+ last_handle = object->handle;
+ g_object_unref (object);
+ }
+
+ /* Using async */
+ gp11_session_create_object_async (session, attrs, NULL, fetch_async_result, &result);
+ WAIT_UNTIL (result);
+ fail_if (result == NULL);
+
+ object = gp11_session_create_object_finish (session, result, &err);
+ g_object_unref (result);
+ SUCCESS_RES (object, err);
+ fail_unless (GP11_IS_OBJECT (object));
+
+ if (object)
+ g_object_unref (object);
+ gp11_attributes_unref (attrs);
+}
+
+DEFINE_TEST(destroy_object)
+{
+ GAsyncResult *result = NULL;
+ GP11Object *object;
+ GError *err = NULL;
+ gboolean ret;
+
+ /* Using simple */
+ object = gp11_session_create_object (session, &err,
+ CKA_CLASS, GP11_ULONG, CKO_DATA,
+ CKA_LABEL, GP11_STRING, "TEST OBJECT",
+ CKA_TOKEN, GP11_BOOLEAN, CK_TRUE,
+ -1);
+ SUCCESS_RES (object, err);
+ fail_unless (GP11_IS_OBJECT (object));
+
+ if (!object)
+ return;
+
+ ret = gp11_object_destroy (object, &err);
+ SUCCESS_RES (ret, err);
+ g_object_unref (object);
+
+ /* Using full */
+ object = gp11_session_create_object (session, &err,
+ CKA_CLASS, GP11_ULONG, CKO_DATA,
+ CKA_LABEL, GP11_STRING, "TEST OBJECT",
+ CKA_TOKEN, GP11_BOOLEAN, CK_TRUE,
+ -1);
+ SUCCESS_RES (object, err);
+ fail_unless (GP11_IS_OBJECT (object));
+
+ if (!object)
+ return;
+
+ ret = gp11_object_destroy_full (object, NULL, &err);
+ SUCCESS_RES (ret, err);
+ g_object_unref (object);
+
+ /* Using async */
+ object = gp11_session_create_object (session, &err,
+ CKA_CLASS, GP11_ULONG, CKO_DATA,
+ CKA_LABEL, GP11_STRING, "TEST OBJECT",
+ CKA_TOKEN, GP11_BOOLEAN, CK_TRUE,
+ -1);
+ SUCCESS_RES (object, err);
+ fail_unless (GP11_IS_OBJECT (object));
+
+ if (!object)
+ return;
+
+ /* Using async */
+ gp11_object_destroy_async (object, NULL, fetch_async_result, &result);
+ WAIT_UNTIL (result);
+ fail_if (result == NULL);
+
+ ret = gp11_object_destroy_finish (object, result, &err);
+ g_object_unref (result);
+ SUCCESS_RES (object, err);
+ g_object_unref (object);
+}
+
+DEFINE_TEST(get_attributes)
+{
+ GAsyncResult *result = NULL;
+ GP11Attributes *attrs;
+ GError *err = NULL;
+ gulong klass;
+ gchar *value = NULL;
+ guint types[2] = { CKA_CLASS, CKA_LABEL };
+
+ /* Simple */
+ attrs = gp11_object_get (object, &err, CKA_CLASS, CKA_LABEL, -1);
+ SUCCESS_RES (attrs, err);
+ if (attrs != NULL) {
+ fail_unless (gp11_attributes_find_ulong (attrs, CKA_CLASS, &klass) && klass == CKO_DATA);
+ fail_unless (gp11_attributes_find_string (attrs, CKA_LABEL, &value) && strcmp (value, "TEST LABEL") == 0);
+ g_free (value); value = NULL;
+ gp11_attributes_unref (attrs);
+ }
+
+ /* Full */
+ attrs = gp11_object_get_full (object, types, 2, NULL, &err);
+ SUCCESS_RES (attrs, err);
+ if (attrs != NULL) {
+ fail_unless (gp11_attributes_find_ulong (attrs, CKA_CLASS, &klass) && klass == CKO_DATA);
+ fail_unless (gp11_attributes_find_string (attrs, CKA_LABEL, &value) && strcmp (value, "TEST LABEL") == 0);
+ g_free (value); value = NULL;
+ gp11_attributes_unref (attrs);
+ }
+
+ /* Async */
+ gp11_object_get_async (object, types, 2, NULL, fetch_async_result, &result);
+ WAIT_UNTIL (result);
+ fail_if (result == NULL);
+
+ attrs = gp11_object_get_finish (object, result, &err);
+ g_object_unref (result);
+ SUCCESS_RES (attrs, err);
+ if (attrs != NULL) {
+ fail_unless (gp11_attributes_find_ulong (attrs, CKA_CLASS, &klass) && klass == CKO_DATA);
+ fail_unless (gp11_attributes_find_string (attrs, CKA_LABEL, &value) && strcmp (value, "TEST LABEL") == 0);
+ g_free (value); value = NULL;
+ gp11_attributes_unref (attrs);
+ }
+}
+
+DEFINE_TEST(get_one_attribute)
+{
+ GAsyncResult *result = NULL;
+ GP11Attribute *attr;
+ GError *err = NULL;
+
+ /* Simple */
+ attr = gp11_object_get_one (object, CKA_CLASS, &err);
+ SUCCESS_RES (attr, err);
+ if (attr != NULL) {
+ fail_unless (attr->type == CKA_CLASS && gp11_attribute_get_ulong (attr) == CKO_DATA);
+ gp11_attribute_free (attr);
+ }
+
+ /* Full */
+ attr = gp11_object_get_one_full (object, CKA_CLASS, NULL, &err);
+ SUCCESS_RES (attr, err);
+ if (attr != NULL) {
+ fail_unless (attr->type == CKA_CLASS && gp11_attribute_get_ulong (attr) == CKO_DATA);
+ gp11_attribute_free (attr);
+ }
+
+ /* Async */
+ gp11_object_get_one_async (object, CKA_CLASS, NULL, fetch_async_result, &result);
+ WAIT_UNTIL (result);
+ fail_if (result == NULL);
+
+ attr = gp11_object_get_one_finish (object, result, &err);
+ g_object_unref (result);
+ SUCCESS_RES (attr, err);
+ if (attr != NULL) {
+ fail_unless (attr->type == CKA_CLASS && gp11_attribute_get_ulong (attr) == CKO_DATA);
+ gp11_attribute_free (attr);
+ }
+}
+
+DEFINE_TEST(set_attributes)
+{
+ GAsyncResult *result = NULL;
+ GP11Attributes *attrs, *templ;
+ GError *err = NULL;
+ gulong klass;
+ gchar *value = NULL;
+ gboolean ret;
+
+ /* Simple */
+ ret = gp11_object_set (object, &err,
+ CKA_CLASS, GP11_ULONG, 5,
+ CKA_LABEL, GP11_STRING, "CHANGE ONE",
+ -1);
+ SUCCESS_RES (ret, err);
+ if (ret) {
+ attrs = gp11_object_get (object, &err, CKA_CLASS, CKA_LABEL, -1);
+ fail_unless (gp11_attributes_find_ulong (attrs, CKA_CLASS, &klass) && klass == 5);
+ fail_unless (gp11_attributes_find_string (attrs, CKA_LABEL, &value) && strcmp (value, "CHANGE ONE") == 0);
+ g_free (value); value = NULL;
+ gp11_attributes_unref (attrs);
+ }
+
+ templ = gp11_attributes_newv (CKA_CLASS, GP11_ULONG, 6,
+ CKA_LABEL, GP11_STRING, "CHANGE TWO",
+ -1);
+
+ /* Full */
+ ret = gp11_object_set_full (object, templ, NULL, &err);
+ gp11_attributes_unref (templ);
+ SUCCESS_RES (ret, err);
+ if (ret) {
+ attrs = gp11_object_get (object, &err, CKA_CLASS, CKA_LABEL, -1);
+ fail_unless (gp11_attributes_find_ulong (attrs, CKA_CLASS, &klass) && klass == 6);
+ fail_unless (gp11_attributes_find_string (attrs, CKA_LABEL, &value) && strcmp (value, "CHANGE TWO") == 0);
+ g_free (value); value = NULL;
+ gp11_attributes_unref (attrs);
+ }
+
+ templ = gp11_attributes_newv (CKA_CLASS, GP11_ULONG, 7,
+ CKA_LABEL, GP11_STRING, "CHANGE THREE",
+ -1);
+
+ /* Async */
+ gp11_object_set_async (object, templ, NULL, fetch_async_result, &result);
+ WAIT_UNTIL (result);
+ fail_if (result == NULL);
+
+ ret = gp11_object_set_finish (object, result, &err);
+ g_object_unref (result);
+ SUCCESS_RES (ret, err);
+ if (ret) {
+ attrs = gp11_object_get (object, &err, CKA_CLASS, CKA_LABEL, -1);
+ fail_unless (gp11_attributes_find_ulong (attrs, CKA_CLASS, &klass) && klass == 7);
+ fail_unless (gp11_attributes_find_string (attrs, CKA_LABEL, &value) && strcmp (value, "CHANGE THREE") == 0);
+ g_free (value); value = NULL;
+ gp11_attributes_unref (attrs);
+ }
+}
+
+DEFINE_TEST(find_objects)
+{
+ GAsyncResult *result = NULL;
+ GP11Attributes *templ;
+ GList *objects;
+ GP11Object *testobj;
+ GError *err = NULL;
+
+ testobj = gp11_session_create_object (session, &err,
+ CKA_CLASS, GP11_ULONG, CKO_DATA,
+ CKA_LABEL, GP11_STRING, "UNIQUE LABEL",
+ -1);
+ g_object_unref (testobj);
+
+ testobj = gp11_session_create_object (session, &err,
+ CKA_CLASS, GP11_ULONG, CKO_DATA,
+ CKA_LABEL, GP11_STRING, "OTHER LABEL",
+ -1);
+ g_object_unref (testobj);
+
+ /* Simple, "TEST LABEL" */
+ objects = gp11_session_find_objects (session, &err, CKA_LABEL, GP11_STRING, "UNIQUE LABEL", -1);
+ SUCCESS_RES (objects, err);
+ fail_unless (g_list_length (objects) == 1);
+ gp11_list_unref_free (objects);
+
+ /* Full, All */
+ templ = gp11_attributes_new ();
+ objects = gp11_session_find_objects_full (session, templ, NULL, &err);
+ SUCCESS_RES (objects, err);
+ fail_unless (g_list_length (objects) > 1);
+ gp11_list_unref_free (objects);
+
+ /* Async, None */
+ gp11_attributes_add_string (templ, CKA_LABEL, "blah blah");
+ gp11_session_find_objects_async (session, templ, NULL, fetch_async_result, &result);
+ WAIT_UNTIL (result);
+ fail_if (result == NULL);
+
+ objects = gp11_session_find_objects_finish (session, result, &err);
+ g_object_unref (result);
+ fail_unless (objects == NULL);
+ gp11_list_unref_free (objects);
+}
diff --git a/gp11/tests/unit-test-gp11-session.c b/gp11/tests/unit-test-gp11-session.c
new file mode 100644
index 00000000..7b6ffbe7
--- /dev/null
+++ b/gp11/tests/unit-test-gp11-session.c
@@ -0,0 +1,142 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "run-auto-test.h"
+
+#include <glib.h>
+
+#include "gp11-test.h"
+
+static GP11Module *module = NULL;
+static GP11Slot *slot = NULL;
+static GP11Session *session = NULL;
+
+DEFINE_SETUP(load_session)
+{
+ GError *err = NULL;
+ GList *slots;
+
+ /* Successful load */
+ module = gp11_module_initialize (".libs/libgp11-test-module.so", &err);
+ SUCCESS_RES (module, err);
+
+ slots = gp11_module_get_slots (module, TRUE);
+ fail_if (slots == NULL);
+
+ slot = GP11_SLOT (slots->data);
+ g_object_ref (slot);
+ gp11_list_unref_free (slots);
+
+ session = gp11_slot_open_session (slot, 0, &err);
+ SUCCESS_RES(session, err);
+}
+
+DEFINE_TEARDOWN(load_session)
+{
+ g_object_unref (session);
+ g_object_unref (slot);
+ g_object_unref (module);
+}
+
+DEFINE_TEST(session_props)
+{
+ GP11Module *mod;
+ guint handle;
+
+ g_object_get (session, "module", &mod, "handle", &handle, NULL);
+ fail_unless (mod == module);
+ g_object_unref (mod);
+
+ fail_unless (handle != 0);
+ fail_unless (session->handle == handle);
+}
+
+DEFINE_TEST(session_info)
+{
+ GP11SessionInfo *info;
+
+ g_printerr ("session_info");
+ info = gp11_session_get_info (session);
+ fail_unless (info != NULL, "no session info");
+
+ fail_unless (info->slot_id == slot->handle);
+ fail_unless ((info->flags & CKF_SERIAL_SESSION) == CKF_SERIAL_SESSION);
+ fail_unless (info->device_error == 1414);
+ gp11_session_info_free (info);
+}
+
+static void
+fetch_async_result (GObject *source, GAsyncResult *result, gpointer user_data)
+{
+ *((GAsyncResult**)user_data) = result;
+ g_object_ref (result);
+}
+
+DEFINE_TEST(open_close_session)
+{
+ GP11Session *sess;
+ GAsyncResult *result = NULL;
+ GError *err = NULL;
+
+ sess = gp11_slot_open_session_full (slot, 0, NULL, &err);
+ SUCCESS_RES (sess, err);
+
+ g_object_unref (sess);
+
+ /* Test opening async */
+ gp11_slot_open_session_async (slot, 0, NULL, fetch_async_result, &result);
+
+ WAIT_UNTIL (result);
+ fail_if (result == NULL);
+
+ /* Get the result */
+ sess = gp11_slot_open_session_finish (slot, result, &err);
+ SUCCESS_RES (sess, err);
+
+ g_object_unref (result);
+ g_object_unref (sess);
+}
+DEFINE_TEST(login_logout)
+{
+ GAsyncResult *result = NULL;
+ GError *err = NULL;
+ gboolean ret;
+
+ /* login/logout */
+ ret = gp11_session_login (session, CKU_USER, (guchar*)"booo", 4, &err);
+ SUCCESS_RES (ret, err);
+
+ ret = gp11_session_logout (session, &err);
+ SUCCESS_RES (ret, err);
+
+ /* login/logout full */
+ ret = gp11_session_login_full (session, CKU_USER, (guchar*)"booo", 4, NULL, &err);
+ SUCCESS_RES (ret, err);
+
+ ret = gp11_session_logout_full (session, NULL, &err);
+ SUCCESS_RES (ret, err);
+
+ /* login async */
+ gp11_session_login_async (session, CKU_USER, (guchar*)"booo", 4, NULL, fetch_async_result, &result);
+ WAIT_UNTIL (result);
+ fail_if (result == NULL);
+
+ ret = gp11_session_login_finish (session, result, &err);
+ SUCCESS_RES (ret, err);
+
+ g_object_unref (result);
+ result = NULL;
+
+ /* logout async */
+ gp11_session_logout_async (session, NULL, fetch_async_result, &result);
+ WAIT_UNTIL (result);
+ fail_if (result == NULL);
+
+ ret = gp11_session_logout_finish (session, result, &err);
+ SUCCESS_RES (ret, err);
+
+ g_object_unref (result);
+ result = NULL;
+
+}
diff --git a/gp11/tests/unit-test-gp11-slot.c b/gp11/tests/unit-test-gp11-slot.c
new file mode 100644
index 00000000..fdc0f7ef
--- /dev/null
+++ b/gp11/tests/unit-test-gp11-slot.c
@@ -0,0 +1,122 @@
+
+#include <check.h>
+
+#include <glib.h>
+#include <string.h>
+
+#include "run-auto-test.h"
+#include "gp11-test.h"
+
+static GP11Module *module = NULL;
+static GP11Slot *slot = NULL;
+
+DEFINE_SETUP(load_slots)
+{
+ GError *err = NULL;
+ GList *slots;
+
+ /* Successful load */
+ module = gp11_module_initialize (".libs/libgp11-test-module.so", &err);
+ SUCCESS_RES (module, err);
+
+ slots = gp11_module_get_slots (module, TRUE);
+ fail_if (slots == NULL);
+
+ slot = GP11_SLOT (slots->data);
+ g_object_ref (slot);
+ gp11_list_unref_free (slots);
+
+}
+
+DEFINE_TEARDOWN(load_slots)
+{
+ g_object_unref (slot);
+ g_object_unref (module);
+}
+
+DEFINE_TEST(slot_info)
+{
+ GP11SlotInfo *info;
+ GP11TokenInfo *token;
+ GList *slots, *l;
+
+ slots = gp11_module_get_slots (module, FALSE);
+ fail_unless (2 == g_list_length (slots), "wrong number of slots returned");
+ fail_unless (GP11_IS_SLOT (slots->data), "missing slot one");
+ fail_unless (GP11_IS_SLOT (slots->next->data), "missing slot two");
+
+ for (l = slots; l; l = g_list_next (l)) {
+ info = gp11_slot_get_info (GP11_SLOT (l->data));
+ fail_unless (info != NULL, "no slot info");
+
+ fail_unless (strcmp("TEST MANUFACTURER", info->manufacturer_id) == 0);
+ fail_unless (strcmp("TEST SLOT", info->slot_description) == 0);
+ fail_unless (55 == info->hardware_version_major);
+ fail_unless (155 == info->hardware_version_minor);
+ fail_unless (65 == info->firmware_version_major);
+ fail_unless (165 == info->firmware_version_minor);
+
+ gp11_slot_info_free (info);
+
+ if (info->flags & CKF_TOKEN_PRESENT) {
+ token = gp11_slot_get_token_info (slot);
+ fail_if (token == NULL, "no token info");
+
+ fail_unless (strcmp ("TEST MANUFACTURER", token->manufacturer_id) == 0);
+ fail_unless (strcmp ("TEST LABEL", token->label) == 0);
+ fail_unless (strcmp ("TEST MODEL", token->model) == 0);
+ fail_unless (strcmp ("TEST SERIAL", token->serial_number) == 0);
+ fail_unless (1 == token->max_session_count);
+ fail_unless (2 == token->session_count);
+ fail_unless (3 == token->max_rw_session_count);
+ fail_unless (4 == token->rw_session_count);
+ fail_unless (5 == token->max_pin_len);
+ fail_unless (6 == token->min_pin_len);
+ fail_unless (7 == token->total_public_memory);
+ fail_unless (8 == token->free_public_memory);
+ fail_unless (9 == token->total_private_memory);
+ fail_unless (10 == token->free_private_memory);
+ fail_unless (75 == token->hardware_version_major);
+ fail_unless (175 == token->hardware_version_minor);
+ fail_unless (85 == token->firmware_version_major);
+ fail_unless (185 == token->firmware_version_minor);
+ fail_unless (927645599 == token->utc_time);
+
+ gp11_token_info_free (token);
+ }
+ }
+
+ gp11_list_unref_free (slots);
+}
+
+DEFINE_TEST(slot_props)
+{
+ GP11Module *mod;
+ CK_SLOT_ID slot_id;
+
+ g_object_get (slot, "module", &mod, "handle", &slot_id, NULL);
+ fail_unless (mod == module);
+ fail_unless (slot_id == 52);
+
+ g_object_unref (mod);
+}
+
+DEFINE_TEST(slot_mechanisms)
+{
+ GSList *mechs, *l;
+ GP11MechanismInfo *info;
+
+ mechs = gp11_slot_get_mechanisms (slot);
+ fail_unless (2 == g_slist_length (mechs), "wrong number of mech types returned");
+
+ for (l = mechs; l; l = g_slist_next (l)) {
+
+ info = gp11_slot_get_mechanism_info (slot, GPOINTER_TO_UINT (l->data));
+ fail_unless (info != NULL, "no mech info returned");
+
+ gp11_mechanism_info_free (info);
+ }
+
+ g_slist_free (mechs);
+}
+
diff --git a/tests/check-helpers.c b/tests/check-helpers.c
new file mode 100644
index 00000000..d87d46d8
--- /dev/null
+++ b/tests/check-helpers.c
@@ -0,0 +1,161 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* test-helpers.c: Common functions called from check unit tests
+
+ Copyright (C) 2008 Stefan Walter
+
+ The Gnome Keyring Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The Gnome Keyring Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the Gnome Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Author: Stef Walter <stef@memberwebs.com>
+*/
+
+/* This file is included into the main .c file for each check unit-test program */
+
+#include <glib.h>
+#include <gtk/gtk.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <check.h>
+
+#include "check-helpers.h"
+
+#include "common/gkr-secure-memory.h"
+
+static GStaticMutex memory_mutex = G_STATIC_MUTEX_INIT;
+
+/* Used from the tests sometimes */
+SRunner *srunner = NULL;
+
+void gkr_memory_lock (void)
+{
+ g_static_mutex_lock (&memory_mutex);
+}
+
+void gkr_memory_unlock (void)
+{
+ g_static_mutex_unlock (&memory_mutex);
+}
+
+void* gkr_memory_fallback (void *p, unsigned long sz)
+{
+ return g_realloc (p, sz);
+}
+
+#ifndef EXTERNAL_TEST
+#include "common/gkr-async.h"
+#endif
+
+static GMainLoop *mainloop = NULL;
+
+static gboolean
+quit_loop (gpointer unused)
+{
+ g_main_loop_quit (mainloop);
+ return TRUE;
+}
+
+void
+test_mainloop_quit (void)
+{
+ g_main_loop_quit (mainloop);
+}
+
+void
+test_mainloop_run (int timeout)
+{
+ guint id = 0;
+
+ if (timeout)
+ id = g_timeout_add (timeout, quit_loop, NULL);
+ g_main_loop_run (mainloop);
+ if (timeout)
+ g_source_remove (id);
+}
+
+GMainLoop*
+test_mainloop_get (void)
+{
+ if (!mainloop)
+ mainloop = g_main_loop_new (NULL, FALSE);
+ return mainloop;
+}
+
+void
+test_quiet_abort_log_handler (const gchar *log_domain, GLogLevelFlags log_level,
+ const gchar *message, gpointer user_data)
+{
+ abort();
+}
+
+static void
+chdir_base_dir (char* argv0)
+{
+ gchar *dir, *base;
+
+ dir = g_path_get_dirname (argv0);
+ chdir (dir);
+
+ base = g_path_get_basename (dir);
+ if (strcmp (base, ".libs") == 0)
+ chdir ("..");
+
+ g_free (base);
+ g_free (dir);
+}
+
+int
+main (int argc, char* argv[])
+{
+ GLogLevelFlags fatal_mask;
+ const gchar* envi;
+ int number_failed;
+ Suite *suite;
+
+ g_thread_init (NULL);
+
+ envi = getenv ("GNOME_KEYRING_TEST_PATH");
+ if (envi) {
+ setenv ("GNOME_KEYRING_OUTSIDE_TEST", "TRUE", 1);
+ } else {
+ setenv ("GNOME_KEYRING_TEST_PATH", "/tmp/test-gnome-keyring", 1);
+ g_mkdir_with_parents ("/tmp/test-gnome-keyring", 0777);
+ }
+
+ chdir_base_dir (argv[0]);
+ gtk_init(&argc, &argv);
+ mainloop = g_main_loop_new (NULL, FALSE);
+
+#ifndef EXTERNAL_TEST
+
+ gkr_async_workers_init (mainloop);
+
+#endif
+
+ fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
+ fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
+ g_log_set_always_fatal (fatal_mask);
+
+ suite = test_suite_create ();
+ srunner = srunner_create (suite);
+ srunner_run_all (srunner, CK_NORMAL);
+ number_failed = srunner_ntests_failed (srunner);
+ srunner_free (srunner);
+ srunner = NULL;
+
+ return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
+}
diff --git a/tests/check-helpers.h b/tests/check-helpers.h
new file mode 100644
index 00000000..c918fc5b
--- /dev/null
+++ b/tests/check-helpers.h
@@ -0,0 +1,36 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* check-helpers.h: Declarations for common functions called from check unit tests
+
+ Copyright (C) 2008 Stefan Walter
+
+ The Gnome Keyring Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The Gnome Keyring Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the Gnome Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Author: Stef Walter <stef@memberwebs.com>
+*/
+
+#ifndef CHECK_HELPERS_H_
+#define CHECK_HELPERS_H_
+
+#include <glib.h>
+
+void test_mainloop_quit (void);
+void test_mainloop_run (int timeout);
+GMainLoop* test_mainloop_get (void);
+
+void test_quiet_abort_log_handler (const gchar *log_domain, GLogLevelFlags log_level,
+ const gchar *message, gpointer user_data);
+
+#endif /*CHECK_HELPERS_H_*/
diff --git a/tests/check.make b/tests/check.make
new file mode 100644
index 00000000..11a261be
--- /dev/null
+++ b/tests/check.make
@@ -0,0 +1,62 @@
+
+# The following need to be declared before this file is included:
+# UNIT_AUTO A list of C files with tests
+# UNIT_PROMPT A list of C files with prompting tests
+# UNIT_LIBS Libraries to link the tests to
+
+# ------------------------------------------------------------------------------
+
+INCLUDES= \
+ -I$(top_srcdir) \
+ -I$(top_srcdir)/daemon \
+ -I$(top_builddir) \
+ $(GTK_CFLAGS) \
+ $(GLIB_CFLAGS) \
+ $(CHECK_CFLAGS)
+
+LIBS = \
+ $(GTK_LIBS) \
+ $(GLIB_LIBS) \
+ $(GTHREAD_LIBS) \
+ $(CHECK_LIBS)
+
+noinst_PROGRAMS= \
+ run-auto-test \
+ run-prompt-test
+
+run-auto-test.c: $(UNIT_AUTO) Makefile.am $(top_srcdir)/tests/prep-check.sh
+ sh $(top_srcdir)/tests/prep-check.sh -b run-auto-test $(UNIT_AUTO)
+
+run_auto_test_SOURCES = \
+ run-auto-test.c run-auto-test.h \
+ $(UNIT_AUTO)
+
+run_auto_test_LDADD = \
+ $(UNIT_LIBS) \
+ $(DAEMON_LIBS)
+
+run_auto_test_CFLAGS = \
+ $(UNIT_FLAGS)
+
+run-prompt-test.c: $(UNIT_PROMPT) Makefile.am $(top_srcdir)/tests/prep-check.sh
+ sh $(top_srcdir)/tests/prep-check.sh -b run-prompt-test $(UNIT_PROMPT)
+
+run_prompt_test_SOURCES = \
+ run-prompt-test.c run-prompt-test.h \
+ $(UNIT_PROMPT)
+
+run_prompt_test_LDADD = \
+ $(UNIT_LIBS) \
+ $(DAEMON_LIBS)
+
+run_prompt_test_CFLAGS = \
+ $(UNIT_FLAGS)
+
+# ------------------------------------------------------------------------------
+# Run the tests
+
+test-auto: $(noinst_PROGRAMS)
+ ./run-auto-test
+
+test-prompt: $(noinst_PROGRAMS)
+ ./run-prompt-test
diff --git a/tests/prep-check.sh b/tests/prep-check.sh
new file mode 100755
index 00000000..7f805980
--- /dev/null
+++ b/tests/prep-check.sh
@@ -0,0 +1,134 @@
+#!/bin/sh -eu
+
+set -eu
+
+# --------------------------------------------------------------------
+# FUNCTIONS
+
+usage()
+{
+ echo "usage: prep-check.sh -b base-name files.c ..." >&2
+ exit 2
+}
+
+# --------------------------------------------------------------------
+# SOURCE FILE
+
+build_header()
+{
+ local _file
+
+ echo '/* This is auto-generated code. Edit at your own peril. */'
+ # echo "#ifndef _${BASE}_H_"
+ # echo "#define _${BASE}_H_"
+ echo
+ echo '#include <check.h>'
+ echo
+ echo 'extern SRunner *srunner;'
+ echo
+ echo '#define DEFINE_SETUP(x) void setup_##x(void)'
+ echo '#define DEFINE_TEARDOWN(x) void teardown_##x(void)'
+ echo '#define DEFINE_TEST(x) void x(void)'
+ echo '#define DEFINE_ABORT(x) void x(void)'
+ echo
+ for _file in $@; do
+ sed -ne 's/.*DEFINE_SETUP(\([^)]\+\))/ void setup_\1(void);/p' $_file
+ sed -ne 's/.*DEFINE_TEARDOWN(\([^)]\+\))/ void teardown_\1(void);/p' $_file
+ sed -ne 's/.*DEFINE_TEST(\([^)]\+\))/ void \1(void);/p' $_file
+ sed -ne 's/.*DEFINE_ABORT(\([^)]\+\))/ void \1(void);/p' $_file
+ done
+ echo
+ # echo "#endif"
+}
+
+build_source()
+{
+ local _tcases _file _name
+
+ echo '/* This is auto-generated code. Edit at your own peril. */'
+ echo '#include <check.h>'
+ echo "#include \"tests/check-helpers.h\""
+ echo "#include \"$BASE.h\""
+ echo
+
+ # A test macro
+ echo '#define WRAP_TEST(name) \'
+ echo ' START_TEST(test_##name) { \'
+ echo ' name (); \'
+ echo ' } END_TEST'
+
+ # Note that we can't run abort tests without CK_FORK
+ echo '#define WRAP_ABORT(name) \'
+ echo ' START_TEST(test_##name) { \'
+ echo ' if (srunner_fork_status (srunner) == CK_NOFORK) return; \'
+ echo ' GLogFunc old = g_log_set_default_handler (test_quiet_abort_log_handler, NULL); \'
+ echo ' name (); \'
+ echo ' g_log_set_default_handler (old, NULL); \'
+ echo ' } END_TEST'
+
+ # Include each file, and build a test case for it
+ _tcases=""
+ for _file in $@; do
+ _name=`echo $_file | tr -c 'a-zA-Z0-9' '_'`
+
+ # Include the test file
+ # echo "#include \"$_file\""
+ # echo
+
+ # Wrap each and every test
+ sed -ne 's/.*DEFINE_TEST(\([^)]\+\)).*/WRAP_TEST (\1);/p' $_file
+ sed -ne 's/.*DEFINE_ABORT(\([^)]\+\)).*/WRAP_ABORT (\1);/p' $_file
+ echo
+
+ # Add all tests to the test case
+ echo "static TCase* tcase_$_name(void) {"
+ _tcases="$_tcases $_name"
+ echo " TCase *tc = tcase_create (\"X\");"
+ sed -ne 's/.*DEFINE_SETUP(\([^)]\+\)).*/ tcase_add_checked_fixture (tc, setup_\1, teardown_\1);/p' $_file
+ sed -ne 's/.*DEFINE_TEST(\([^)]\+\)).*/ tcase_add_test (tc, test_\1);/p' $_file
+ sed -ne 's/.*DEFINE_ABORT(\([^)]\+\)).*/ tcase_add_test_raise_signal (tc, test_\1, 6);/p' $_file
+ echo " return tc;"
+ echo "}"
+ echo
+
+ done
+
+ echo "static Suite* test_suite_create (void) {"
+ echo " Suite *s = suite_create (\"$BASE\");"
+ for _name in $_tcases; do
+ echo " suite_add_tcase (s, tcase_$_name());"
+ done
+ echo " return s;"
+ echo "}"
+ echo
+
+ echo "#include \"tests/check-helpers.c\""
+}
+
+# --------------------------------------------------------------------
+# ARGUMENT PARSING
+
+BASE=unit
+
+while [ $# -gt 0 ]; do
+ case "$1" in
+ -b)
+ BASE="$2"
+ shift
+ ;;
+ --)
+ shift
+ break
+ ;;
+ -*)
+ usage
+ ;;
+ *)
+ break
+ ;;
+ esac
+ shift
+done
+
+build_header $* > $BASE.h
+build_source $* > $BASE.c