diff options
author | Stefan Walter <stefw@src.gnome.org> | 2008-07-14 19:54:11 +0000 |
---|---|---|
committer | Stefan Walter <stefw@src.gnome.org> | 2008-07-14 19:54:11 +0000 |
commit | 59199cf372b2d871e7a5f4d6efa57cc2d46d6dc4 (patch) | |
tree | 287038a76286a0e98572535d1f0016e1df18f6e1 | |
parent | 2800c08ecc82c00223b667242fc5f0a2896261b0 (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
36 files changed, 9012 insertions, 76 deletions
@@ -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. @@ -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 (©, &attr); + gp11_attribute_clear (&attr); + fail_unless (gp11_attribute_get_ulong (©) == 88); + fail_unless (copy.type == ATTR_TYPE); + gp11_attribute_clear (©); +} + +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 |