diff options
author | Stef Walter <stefw@gnome.org> | 2012-04-19 13:56:49 +0800 |
---|---|---|
committer | Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> | 2012-04-19 22:43:19 +0800 |
commit | b0de75186e8e529e427aae231b334a3e40e5bffd (patch) | |
tree | 52897c323888ffd56eef648b10d26f7a92da9924 /tests | |
parent | 7c25066261498dd98fb6bd1260ffe12f2fb5b7ce (diff) | |
download | gsoc2013-empathy-b0de75186e8e529e427aae231b334a3e40e5bffd.tar gsoc2013-empathy-b0de75186e8e529e427aae231b334a3e40e5bffd.tar.gz gsoc2013-empathy-b0de75186e8e529e427aae231b334a3e40e5bffd.tar.bz2 gsoc2013-empathy-b0de75186e8e529e427aae231b334a3e40e5bffd.tar.lz gsoc2013-empathy-b0de75186e8e529e427aae231b334a3e40e5bffd.tar.xz gsoc2013-empathy-b0de75186e8e529e427aae231b334a3e40e5bffd.tar.zst gsoc2013-empathy-b0de75186e8e529e427aae231b334a3e40e5bffd.zip |
tls-test: Use a proper PKCS#11 mock module for testing
* In empathy-tls-test.c use a proper PKCS#11 mock module,
which we can place certificate anchors and pinned certificates in.
* Fix EmpathyTlsVerifier to check for server trust assertions
not client ones, this was a bug highlighted by fixing tests.
https://bugzilla.gnome.org/show_bug.cgi?id=668186
https://bugzilla.gnome.org/show_bug.cgi?id=668261
Diffstat (limited to 'tests')
-rw-r--r-- | tests/Makefile.am | 4 | ||||
-rw-r--r-- | tests/certificates/collabora-ca.cer (renamed from tests/certificates/collabora-ca/collabora-ca.cer) | bin | 1536 -> 1536 bytes | |||
-rw-r--r-- | tests/empathy-tls-test.c | 157 | ||||
-rw-r--r-- | tests/mock-pkcs11.c | 1351 | ||||
-rw-r--r-- | tests/mock-pkcs11.h | 352 |
5 files changed, 1821 insertions, 43 deletions
diff --git a/tests/Makefile.am b/tests/Makefile.am index b6c49509f..5b6d31f28 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -16,6 +16,7 @@ AM_CPPFLAGS = \ $(EMPATHY_CFLAGS) \ $(WARN_CFLAGS) \ $(DISABLE_DEPRECATED) \ + -DSRCDIR=\""$(abs_srcdir)"\" \ $(NULL) LDADD = \ @@ -38,7 +39,8 @@ noinst_PROGRAMS = $(tests_list) TESTS = $(tests_list) empathy_tls_test_SOURCES = empathy-tls-test.c \ - test-helper.c test-helper.h + test-helper.c test-helper.h \ + mock-pkcs11.c mock-pkcs11.h empathy_irc_server_test_SOURCES = empathy-irc-server-test.c \ test-helper.c test-helper.h \ diff --git a/tests/certificates/collabora-ca/collabora-ca.cer b/tests/certificates/collabora-ca.cer Binary files differindex 2842c696f..2842c696f 100644 --- a/tests/certificates/collabora-ca/collabora-ca.cer +++ b/tests/certificates/collabora-ca.cer diff --git a/tests/empathy-tls-test.c b/tests/empathy-tls-test.c index 58c53dc6b..e2ba5b4cc 100644 --- a/tests/empathy-tls-test.c +++ b/tests/empathy-tls-test.c @@ -5,6 +5,7 @@ #include <libempathy/empathy-tls-certificate.h> #include <libempathy/empathy-tls-verifier.h> #include "test-helper.h" +#include "mock-pkcs11.h" #include <gcr/gcr.h> @@ -289,6 +290,9 @@ static void setup (Test *test, gconstpointer data) { GError *error = NULL; + GckModule *module; + const gchar *trust_uris[2] = { MOCK_SLOT_ONE_URI, NULL }; + test->loop = g_main_loop_new (NULL, FALSE); test->dbus = tp_dbus_daemon_dup (&error); @@ -299,13 +303,20 @@ setup (Test *test, gconstpointer data) test->result = NULL; test->cert = NULL; - /* No PKCS#11 modules by default, tests add them */ + /* Add our mock module as the only PKCS#11 module */ + module = gck_module_new (&mock_default_functions); + mock_C_Initialize (NULL); + gcr_pkcs11_set_modules (NULL); + gcr_pkcs11_add_module (module); + gcr_pkcs11_set_trust_lookup_uris (trust_uris); } static void teardown (Test *test, gconstpointer data) { + mock_C_Finalize (NULL); + test->dbus_name = NULL; if (test->mock) @@ -331,42 +342,30 @@ teardown (Test *test, gconstpointer data) } static void -add_pkcs11_module_for_testing (Test *test, - const gchar *filename, - const gchar *subdir) +add_certificate_to_mock (Test *test, + const gchar *certificate, + const gchar *peer) { GError *error = NULL; - gchar *args, *path, *directory; - gchar *standalone, *error_output; - gint exit_status; + GcrCertificate *cert; + gchar *contents; + gsize length; + gchar *path; - directory = g_build_filename (g_getenv ("EMPATHY_SRCDIR"), - "tests", "certificates", subdir, NULL); + path = g_build_filename (g_getenv ("EMPATHY_SRCDIR"), + "tests", "certificates", certificate, NULL); - /* - * Lookup the directory for standalone pkcs11 modules installed by - * gnome-keyring. We use these for testing our implementation. - */ - g_spawn_command_line_sync ("pkg-config --variable=pkcs11standalonedir gcr-3", - &standalone, &error_output, &exit_status, &error); + g_file_get_contents (path, &contents, &length, &error); g_assert_no_error (error); - if (exit_status != 0) - { - g_warning ("couldn't determine standalone pkcs11 module directory: %d: %s", - exit_status, error_output); - g_assert_not_reached (); - } - g_strstrip (standalone); - args = g_strdup_printf ("directory=\"%s\"", directory); - path = g_build_filename (standalone, filename, NULL); - gcr_pkcs11_add_module_from_file (path, args, &error); - g_assert_no_error (error); + cert = gcr_simple_certificate_new ((const guchar *)contents, length); + mock_module_add_certificate (cert); + mock_module_add_assertion (cert, + peer ? CKT_X_PINNED_CERTIFICATE : CKT_X_ANCHORED_CERTIFICATE, + GCR_PURPOSE_SERVER_AUTH, peer); + g_object_unref (cert); - g_free (directory); - g_free (standalone); - g_free (error_output); - g_free (args); + g_free (contents); g_free (path); } @@ -445,8 +444,7 @@ test_certificate_verify_success_with_pkcs11_lookup (Test *test, "dhansak-collabora.cer", NULL); /* We add the collabora directory with the collabora root */ - add_pkcs11_module_for_testing (test, "gkm-roots-store-standalone.so", - "collabora-ca"); + add_certificate_to_mock (test, "collabora-ca.cer", NULL); ensure_certificate_proxy (test); @@ -483,11 +481,10 @@ test_certificate_verify_success_with_full_chain (Test *test, */ test->mock = mock_tls_certificate_new_and_register (test->dbus, - "dhansak-collabora.cer", "collabora-ca/collabora-ca.cer", NULL); + "dhansak-collabora.cer", "collabora-ca.cer", NULL); /* We add the collabora directory with the collabora root */ - add_pkcs11_module_for_testing (test, "gkm-roots-store-standalone.so", - "collabora-ca"); + add_certificate_to_mock (test, "collabora-ca.cer", NULL); ensure_certificate_proxy (test); @@ -553,7 +550,7 @@ test_certificate_verify_root_not_anchored (Test *test, }; test->mock = mock_tls_certificate_new_and_register (test->dbus, - "dhansak-collabora.cer", "collabora-ca/collabora-ca.cer", NULL); + "dhansak-collabora.cer", "collabora-ca.cer", NULL); /* Note that we're not adding any place to find root certs */ @@ -588,11 +585,10 @@ test_certificate_verify_identities_invalid (Test *test, }; test->mock = mock_tls_certificate_new_and_register (test->dbus, - "dhansak-collabora.cer", "collabora-ca/collabora-ca.cer", NULL); + "dhansak-collabora.cer", "collabora-ca.cer", NULL); /* We add the collabora directory with the collabora root */ - add_pkcs11_module_for_testing (test, "gkm-roots-store-standalone.so", - "collabora-ca"); + add_certificate_to_mock (test, "collabora-ca.cer", NULL); ensure_certificate_proxy (test); @@ -625,11 +621,10 @@ test_certificate_verify_uses_reference_identities (Test *test, }; test->mock = mock_tls_certificate_new_and_register (test->dbus, - "dhansak-collabora.cer", "collabora-ca/collabora-ca.cer", NULL); + "dhansak-collabora.cer", "collabora-ca.cer", NULL); /* We add the collabora directory with the collabora root */ - add_pkcs11_module_for_testing (test, "gkm-roots-store-standalone.so", - "collabora-ca"); + add_certificate_to_mock (test, "collabora-ca.cer", NULL); ensure_certificate_proxy (test); @@ -650,6 +645,80 @@ test_certificate_verify_uses_reference_identities (Test *test, g_object_unref (verifier); } +static void +test_certificate_verify_success_with_pinned (Test *test, + gconstpointer data G_GNUC_UNUSED) +{ + EmpTLSCertificateRejectReason reason = 0; + GError *error = NULL; + EmpathyTLSVerifier *verifier; + const gchar *reference_identities[] = { + "www.collabora.co.uk", + NULL + }; + + /* + * In this test the mock TLS connection has a full certificate + * chain. We look for an anchor certificate in the chain. + */ + + test->mock = mock_tls_certificate_new_and_register (test->dbus, + "dhansak-collabora.cer", NULL); + + /* We add the collabora directory with the collabora root */ + add_certificate_to_mock (test, "dhansak-collabora.cer", "www.collabora.co.uk"); + + ensure_certificate_proxy (test); + + verifier = empathy_tls_verifier_new (test->cert, "www.collabora.co.uk", + reference_identities); + empathy_tls_verifier_verify_async (verifier, fetch_callback_result, test); + g_main_loop_run (test->loop); + empathy_tls_verifier_verify_finish (verifier, test->result, &reason, + NULL, &error); + g_assert_no_error (error); + + /* Yay the verification was a success! */ + + g_clear_error (&error); + g_object_unref (verifier); +} + +static void +test_certificate_verify_pinned_wrong_host (Test *test, + gconstpointer data G_GNUC_UNUSED) +{ + EmpTLSCertificateRejectReason reason = 0; + GError *error = NULL; + EmpathyTLSVerifier *verifier; + const gchar *reference_identities[] = { + "www.collabora.co.uk", + NULL + }; + + test->mock = mock_tls_certificate_new_and_register (test->dbus, + "dhansak-collabora.cer", NULL); + + /* Note that we're not adding any place to find root certs */ + + ensure_certificate_proxy (test); + + verifier = empathy_tls_verifier_new (test->cert, "another.collabora.co.uk", + reference_identities); + empathy_tls_verifier_verify_async (verifier, fetch_callback_result, test); + g_main_loop_run (test->loop); + + empathy_tls_verifier_verify_finish (verifier, test->result, &reason, + NULL, &error); + + /* And it should say we're self-signed */ + g_assert_error (error, G_IO_ERROR, + EMP_TLS_CERTIFICATE_REJECT_REASON_SELF_SIGNED); + + g_clear_error (&error); + g_object_unref (verifier); +} + int main (int argc, char **argv) @@ -673,6 +742,10 @@ main (int argc, setup, test_certificate_verify_identities_invalid, teardown); g_test_add ("/tls/certificate_verify_uses_reference_identities", Test, NULL, setup, test_certificate_verify_uses_reference_identities, teardown); + g_test_add ("/tls/certificate_verify_success_with_pinned", Test, NULL, + setup, test_certificate_verify_success_with_pinned, teardown); + g_test_add ("/tls/certificate_verify_pinned_wrong_host", Test, NULL, + setup, test_certificate_verify_pinned_wrong_host, teardown); result = g_test_run (); test_deinit (); diff --git a/tests/mock-pkcs11.c b/tests/mock-pkcs11.c new file mode 100644 index 000000000..4b1219f2c --- /dev/null +++ b/tests/mock-pkcs11.c @@ -0,0 +1,1351 @@ +/* + * Copyright (C) 2010 Stefan Walter + * Copyright (C) 2011 Collabora Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General License for more details. + * + * You should have received a copy of the GNU Lesser General + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#include "config.h" + +#include "mock-pkcs11.h" + +#include <gcr/gcr.h> + +#include <glib.h> + +#include <string.h> + +/* + * This is *NOT* how you'd want to implement a PKCS#11 module. This + * fake module simply provides enough for gnutls-pkcs11 backend to test against. + * It doesn't pass any tests, or behave as expected from a PKCS#11 module. + */ + +static gboolean initialized = FALSE; + +typedef enum { + OP_FIND = 1, +} Operation; + +static CK_OBJECT_HANDLE unique_identifier = 100; +static GHashTable *the_sessions = NULL; +static GHashTable *the_certificates = NULL; +static GHashTable *the_assertions = NULL; + +typedef struct { + GcrCertificate *cert; + CK_ULONG assertion_type; + gchar *purpose; + gchar *peer; +} Assertion; + +static void +free_assertion (gpointer data) +{ + Assertion *assertion = data; + g_clear_object (&assertion->cert); + g_free (assertion->purpose); + g_free (assertion->peer); + g_free (assertion); +} + +typedef struct { + CK_SESSION_HANDLE handle; + CK_SESSION_INFO info; + + Operation operation; + + /* For find operations */ + GList *matches; +} Session; + +static void +free_session (gpointer data) +{ + Session *sess = (Session*)data; + g_list_free (sess->matches); + g_free (sess); +} + +CK_OBJECT_HANDLE +mock_module_add_certificate (GcrCertificate *cert) +{ + CK_OBJECT_HANDLE handle; + + g_return_val_if_fail (GCR_IS_CERTIFICATE (cert), 0); + + handle = unique_identifier++; + g_hash_table_insert (the_certificates, GUINT_TO_POINTER (handle), g_object_ref (cert)); + return handle; +} + +CK_OBJECT_HANDLE +mock_module_add_assertion (GcrCertificate *cert, + CK_X_ASSERTION_TYPE assertion_type, + const gchar *purpose, + const gchar *peer) +{ + Assertion *assertion; + CK_OBJECT_HANDLE handle; + + g_return_val_if_fail (GCR_IS_CERTIFICATE (cert), 0); + + assertion = g_new0 (Assertion, 1); + assertion->cert = g_object_ref (cert); + assertion->assertion_type = assertion_type; + assertion->purpose = g_strdup (purpose); + assertion->peer = g_strdup (peer); + + handle = unique_identifier++; + g_hash_table_insert (the_assertions, GUINT_TO_POINTER (handle), assertion); + return handle; +} + +CK_RV +mock_C_Initialize (CK_VOID_PTR init_args) +{ + CK_C_INITIALIZE_ARGS_PTR args; + + g_return_val_if_fail (initialized == FALSE, CKR_CRYPTOKI_ALREADY_INITIALIZED); + + args = (CK_C_INITIALIZE_ARGS_PTR)init_args; + if (args) + { + g_return_val_if_fail( + (args->CreateMutex == NULL && args->DestroyMutex == NULL && + args->LockMutex == NULL && args->UnlockMutex == NULL) || + (args->CreateMutex != NULL && args->DestroyMutex != NULL && + args->LockMutex != NULL && args->UnlockMutex != NULL), + CKR_ARGUMENTS_BAD); + + /* Flags should allow OS locking and os threads */ + g_return_val_if_fail ((args->flags & CKF_OS_LOCKING_OK), CKR_CANT_LOCK); + g_return_val_if_fail ((args->flags & CKF_LIBRARY_CANT_CREATE_OS_THREADS) == 0, CKR_NEED_TO_CREATE_THREADS); + } + + the_sessions = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, free_session); + the_certificates = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify)g_object_unref); + the_assertions = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, free_assertion); + + initialized = TRUE; + return CKR_OK; +} + +CK_RV +mock_C_Finalize (CK_VOID_PTR reserved) +{ + g_return_val_if_fail (reserved == NULL, CKR_ARGUMENTS_BAD); + g_return_val_if_fail (initialized == TRUE, CKR_CRYPTOKI_NOT_INITIALIZED); + + initialized = FALSE; + + g_hash_table_destroy (the_certificates); + the_certificates = NULL; + + g_hash_table_destroy (the_assertions); + the_assertions = NULL; + + g_hash_table_destroy (the_sessions); + the_sessions = NULL; + + return CKR_OK; +} + +static const CK_INFO TEST_INFO = { + { CRYPTOKI_VERSION_MAJOR, CRYPTOKI_VERSION_MINOR }, + "TEST MANUFACTURER ", + 0, + "TEST LIBRARY ", + { 45, 145 } +}; + +CK_RV +mock_C_GetInfo (CK_INFO_PTR info) +{ + g_return_val_if_fail (info, CKR_ARGUMENTS_BAD); + memcpy (info, &TEST_INFO, sizeof (*info)); + return CKR_OK; +} + +CK_RV +mock_C_GetFunctionList (CK_FUNCTION_LIST_PTR_PTR list) +{ + g_return_val_if_fail (list, CKR_ARGUMENTS_BAD); + *list = &mock_default_functions; + return CKR_OK; +} + +CK_RV +mock_C_GetSlotList (CK_BBOOL token_present, + CK_SLOT_ID_PTR slot_list, + CK_ULONG_PTR count) +{ + CK_ULONG num = 1; + + g_return_val_if_fail (count, CKR_ARGUMENTS_BAD); + + /* Application only wants to know the number of slots. */ + if (slot_list == NULL) + { + *count = num; + return CKR_OK; + } + + if (*count < num) + g_return_val_if_reached (CKR_BUFFER_TOO_SMALL); + + *count = num; + slot_list[0] = MOCK_SLOT_ONE_ID; + return CKR_OK; +} + +/* Update mock-pkcs11.h URIs when updating this */ + +static const CK_SLOT_INFO MOCK_INFO_ONE = { + "MOCK SLOT ", + "MOCK MANUFACTURER ", + CKF_TOKEN_PRESENT | CKF_REMOVABLE_DEVICE, + { 55, 155 }, + { 65, 165 }, +}; + +CK_RV +mock_C_GetSlotInfo (CK_SLOT_ID slot_id, + CK_SLOT_INFO_PTR info) +{ + g_return_val_if_fail (info, CKR_ARGUMENTS_BAD); + + if (slot_id == MOCK_SLOT_ONE_ID) + { + memcpy (info, &MOCK_INFO_ONE, sizeof (*info)); + return CKR_OK; + } + else + { + g_return_val_if_reached (CKR_SLOT_ID_INVALID); + } +} + +/* Update mock-pkcs11.h URIs when updating this */ + +static const CK_TOKEN_INFO MOCK_TOKEN_ONE = { + "MOCK LABEL ", + "MOCK MANUFACTURER ", + "MOCK MODEL ", + "MOCK SERIAL ", + CKF_TOKEN_INITIALIZED | CKF_WRITE_PROTECTED, + 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' } +}; + +CK_RV +mock_C_GetTokenInfo (CK_SLOT_ID slot_id, + CK_TOKEN_INFO_PTR info) +{ + g_return_val_if_fail (info != NULL, CKR_ARGUMENTS_BAD); + + if (slot_id == MOCK_SLOT_ONE_ID) + { + memcpy (info, &MOCK_TOKEN_ONE, sizeof (*info)); + return CKR_OK; + } + else + { + g_return_val_if_reached (CKR_SLOT_ID_INVALID); + } +} + +CK_RV +mock_C_GetMechanismList (CK_SLOT_ID slot_id, + CK_MECHANISM_TYPE_PTR mechanism_list, + CK_ULONG_PTR count) +{ + g_return_val_if_fail (slot_id == MOCK_SLOT_ONE_ID, CKR_SLOT_ID_INVALID); + g_return_val_if_fail (count, CKR_ARGUMENTS_BAD); + + /* Application only wants to know the number of slots. */ + if (mechanism_list == NULL) + { + *count = 0; + return CKR_OK; + } + + return CKR_OK; +} + +CK_RV +mock_C_GetMechanismInfo (CK_SLOT_ID slot_id, + CK_MECHANISM_TYPE type, + CK_MECHANISM_INFO_PTR info) +{ + g_return_val_if_fail (slot_id == MOCK_SLOT_ONE_ID, CKR_SLOT_ID_INVALID); + g_return_val_if_fail (info, CKR_ARGUMENTS_BAD); + + g_return_val_if_reached (CKR_MECHANISM_INVALID); +} + +CK_RV +mock_unsupported_C_InitToken (CK_SLOT_ID slot_id, + CK_UTF8CHAR_PTR pin, + CK_ULONG pin_len, + CK_UTF8CHAR_PTR label) +{ + g_return_val_if_fail (slot_id == MOCK_SLOT_ONE_ID, CKR_SLOT_ID_INVALID); + return CKR_FUNCTION_NOT_SUPPORTED; +} + +CK_RV +mock_unsupported_C_WaitForSlotEvent (CK_FLAGS flags, + CK_SLOT_ID_PTR slot_id, + CK_VOID_PTR reserved) +{ + return CKR_FUNCTION_NOT_SUPPORTED; +} + +CK_RV +mock_C_OpenSession (CK_SLOT_ID slot_id, + CK_FLAGS flags, + CK_VOID_PTR application, + CK_NOTIFY notify, + CK_SESSION_HANDLE_PTR session) +{ + Session *sess; + + g_return_val_if_fail (slot_id == MOCK_SLOT_ONE_ID, CKR_SLOT_ID_INVALID); + g_return_val_if_fail (session != NULL, CKR_ARGUMENTS_BAD); + g_return_val_if_fail ((flags & CKF_SERIAL_SESSION) == CKF_SERIAL_SESSION, CKR_SESSION_PARALLEL_NOT_SUPPORTED); + + if (flags & CKF_RW_SESSION) + return CKR_TOKEN_WRITE_PROTECTED; + + sess = g_new0 (Session, 1); + sess->handle = ++unique_identifier; + sess->info.flags = flags; + sess->info.slotID = slot_id; + sess->info.state = CKS_RO_PUBLIC_SESSION; + sess->info.ulDeviceError = 0; + *session = sess->handle; + + g_hash_table_replace (the_sessions, GUINT_TO_POINTER (sess->handle), sess); + return CKR_OK; +} + +CK_RV +mock_C_CloseSession (CK_SESSION_HANDLE session) +{ + Session *sess; + + sess = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (session)); + g_return_val_if_fail (sess != NULL, CKR_SESSION_HANDLE_INVALID); + + g_hash_table_remove (the_sessions, GUINT_TO_POINTER (sess)); + return CKR_OK; +} + +CK_RV +mock_C_CloseAllSessions (CK_SLOT_ID slot_id) +{ + g_return_val_if_fail (slot_id == MOCK_SLOT_ONE_ID, CKR_SLOT_ID_INVALID); + + g_hash_table_remove_all (the_sessions); + return CKR_OK; +} + +CK_RV +mock_C_GetFunctionStatus (CK_SESSION_HANDLE session) +{ + return CKR_FUNCTION_NOT_PARALLEL; +} + +CK_RV +mock_C_CancelFunction (CK_SESSION_HANDLE session) +{ + return CKR_FUNCTION_NOT_PARALLEL; +} + +CK_RV +mock_C_GetSessionInfo (CK_SESSION_HANDLE session, + CK_SESSION_INFO_PTR info) +{ + Session *sess; + + g_return_val_if_fail (info != NULL, CKR_ARGUMENTS_BAD); + + sess = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (session)); + g_return_val_if_fail (sess != NULL, CKR_SESSION_HANDLE_INVALID); + + memcpy (info, &sess->info, sizeof (*info)); + return CKR_OK; +} + +CK_RV +mock_unsupported_C_InitPIN (CK_SESSION_HANDLE session, + CK_UTF8CHAR_PTR pin, + CK_ULONG pin_len) +{ + return CKR_FUNCTION_NOT_SUPPORTED; +} + +CK_RV +mock_unsupported_C_SetPIN (CK_SESSION_HANDLE session, + CK_UTF8CHAR_PTR old_pin, + CK_ULONG old_len, + CK_UTF8CHAR_PTR new_pin, + CK_ULONG new_len) +{ + return CKR_FUNCTION_NOT_SUPPORTED; +} + +CK_RV +mock_unsupported_C_GetOperationState (CK_SESSION_HANDLE session, + CK_BYTE_PTR operation_state, + CK_ULONG_PTR operation_state_len) +{ + return CKR_FUNCTION_NOT_SUPPORTED; +} + +CK_RV +mock_unsupported_C_SetOperationState (CK_SESSION_HANDLE session, + CK_BYTE_PTR operation_state, + CK_ULONG operation_state_len, + CK_OBJECT_HANDLE encryption_key, + CK_OBJECT_HANDLE authentication_key) +{ + return CKR_FUNCTION_NOT_SUPPORTED; +} + +CK_RV +mock_unsupported_C_Login (CK_SESSION_HANDLE session, + CK_USER_TYPE user_type, + CK_UTF8CHAR_PTR pin, + CK_ULONG pin_len) +{ + return CKR_FUNCTION_NOT_SUPPORTED; +} + +CK_RV +mock_unsupported_C_Logout (CK_SESSION_HANDLE session) +{ + return CKR_FUNCTION_NOT_SUPPORTED; +} + +CK_RV +mock_readonly_C_CreateObject (CK_SESSION_HANDLE session, + CK_ATTRIBUTE_PTR template, + CK_ULONG count, + CK_OBJECT_HANDLE_PTR object) +{ + Session *sess; + + g_return_val_if_fail (object, CKR_ARGUMENTS_BAD); + + sess = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (session)); + g_return_val_if_fail (sess != NULL, CKR_SESSION_HANDLE_INVALID); + + return CKR_TOKEN_WRITE_PROTECTED; +} + +CK_RV +mock_unsupported_C_CopyObject (CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE object, + CK_ATTRIBUTE_PTR template, + CK_ULONG count, + CK_OBJECT_HANDLE_PTR new_object) +{ + return CKR_FUNCTION_NOT_SUPPORTED; +} + +CK_RV +mock_readonly_C_DestroyObject (CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE object) +{ + Session *sess; + + g_return_val_if_fail (object, CKR_ARGUMENTS_BAD); + + sess = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (session)); + g_return_val_if_fail (sess != NULL, CKR_SESSION_HANDLE_INVALID); + + return CKR_TOKEN_WRITE_PROTECTED; +} + +CK_RV +mock_unsupported_C_GetObjectSize (CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE object, + CK_ULONG_PTR pulSize) +{ + return CKR_FUNCTION_NOT_SUPPORTED; +} + +static CK_RV +fill_data_attribute (CK_ATTRIBUTE *attr, + gconstpointer data, + gsize length) +{ + if (!attr->pValue) { + attr->ulValueLen = length; + return CKR_OK; + } else if (attr->ulValueLen < length) { + attr->ulValueLen = length; + return CKR_BUFFER_TOO_SMALL; + } else { + memcpy (attr->pValue, data, length); + attr->ulValueLen = length; + return CKR_OK; + } +} + +static CK_RV +fill_check_value_attribute (CK_ATTRIBUTE *attr, + GcrCertificate *cert) +{ + guchar *data; + gsize length; + CK_RV rv; + + data = gcr_certificate_get_fingerprint (cert, G_CHECKSUM_SHA1, &length); + rv = fill_data_attribute (attr, data, 3); + g_free (data); + + return rv; +} + +static CK_RV +fill_subject_attribute (CK_ATTRIBUTE *attr, + GcrCertificate *cert) +{ + guchar *data; + gsize length; + CK_RV rv; + + data = gcr_certificate_get_subject_raw (cert, &length); + rv = fill_data_attribute (attr, data, length); + g_free (data); + + return rv; +} + +static CK_RV +fill_issuer_attribute (CK_ATTRIBUTE *attr, + GcrCertificate *cert) +{ + guchar *data; + gsize length; + CK_RV rv; + + data = gcr_certificate_get_issuer_raw (cert, &length); + rv = fill_data_attribute (attr, data, length); + g_free (data); + + return rv; +} + +static CK_RV +fill_serial_attribute (CK_ATTRIBUTE *attr, + GcrCertificate *cert) +{ + guchar *data; + gsize length; + CK_RV rv; + + data = gcr_certificate_get_serial_number (cert, &length); + rv = fill_data_attribute (attr, data, length); + g_free (data); + + return rv; +} + +static CK_RV +fill_string_attribute (CK_ATTRIBUTE *attr, + const gchar *data) +{ + return fill_data_attribute (attr, data, strlen (data)); +} + +static CK_RV +fill_id_attribute (CK_ATTRIBUTE *attr, + GcrCertificate *cert) +{ + gchar *data; + CK_RV rv; + + data = g_strdup_printf ("%p", cert); + rv = fill_string_attribute (attr, data); + g_free (data); + + return rv; +} + +static CK_RV +fill_value_attribute (CK_ATTRIBUTE *attr, + GcrCertificate *cert) +{ + const guchar *data; + gsize length; + + data = gcr_certificate_get_der_data (cert, &length); + return fill_data_attribute (attr, data, length); +} + +static CK_RV +fill_ulong_attribute (CK_ATTRIBUTE *attr, + CK_ULONG value) +{ + return fill_data_attribute (attr, &value, sizeof (value)); +} + +static CK_RV +fill_bool_attribute (CK_ATTRIBUTE *attr, + CK_BBOOL value) +{ + return fill_data_attribute (attr, &value, sizeof (value)); +} + +static CK_RV +fill_certificate_attribute (CK_ATTRIBUTE *attr, + GcrCertificate *cert) +{ + switch (attr->type) + { + case CKA_CLASS: + return fill_ulong_attribute (attr, CKO_CERTIFICATE); + case CKA_TOKEN: + return fill_bool_attribute (attr, CK_TRUE); + case CKA_PRIVATE: + case CKA_MODIFIABLE: + case CKA_TRUSTED: + return fill_bool_attribute (attr, CK_FALSE); + case CKA_LABEL: + return fill_string_attribute (attr, "Certificate"); + case CKA_CERTIFICATE_TYPE: + return fill_ulong_attribute (attr, CKC_X_509); + case CKA_CERTIFICATE_CATEGORY: + return fill_ulong_attribute (attr, 2); + case CKA_CHECK_VALUE: + return fill_check_value_attribute (attr, cert); + case CKA_START_DATE: + case CKA_END_DATE: + return fill_data_attribute (attr, "", 0); + case CKA_SUBJECT: + return fill_subject_attribute (attr, cert); + case CKA_ID: + return fill_id_attribute (attr, cert); + case CKA_ISSUER: + return fill_issuer_attribute (attr, cert); + case CKA_SERIAL_NUMBER: + return fill_serial_attribute (attr, cert); + case CKA_VALUE: + return fill_value_attribute (attr, cert); + case CKA_URL: + case CKA_HASH_OF_SUBJECT_PUBLIC_KEY: + case CKA_HASH_OF_ISSUER_PUBLIC_KEY: + case CKA_JAVA_MIDP_SECURITY_DOMAIN: + default: + return CKR_ATTRIBUTE_TYPE_INVALID; + } +} + +static CK_RV +fill_assertion_attribute (CK_ATTRIBUTE *attr, + Assertion *assertion) +{ + CK_RV rv; + + switch (attr->type) + { + case CKA_CLASS: + return fill_ulong_attribute (attr, CKO_X_TRUST_ASSERTION); + case CKA_TOKEN: + return fill_bool_attribute (attr, CK_TRUE); + case CKA_PRIVATE: + case CKA_MODIFIABLE: + case CKA_TRUSTED: + return fill_bool_attribute (attr, CK_FALSE); + case CKA_LABEL: + return fill_string_attribute (attr, "Assertion"); + case CKA_X_ASSERTION_TYPE: + return fill_ulong_attribute (attr, assertion->assertion_type); + case CKA_X_PURPOSE: + return fill_string_attribute (attr, assertion->purpose); + case CKA_X_PEER: + if (!assertion->peer) + return CKR_ATTRIBUTE_TYPE_INVALID; + return fill_string_attribute (attr, assertion->peer); + case CKA_SERIAL_NUMBER: + case CKA_ISSUER: + return fill_certificate_attribute (attr, assertion->cert); + case CKA_X_CERTIFICATE_VALUE: + attr->type = CKA_VALUE; + rv = fill_certificate_attribute (attr, assertion->cert); + attr->type = CKA_X_CERTIFICATE_VALUE; + return rv; + + default: + return CKR_ATTRIBUTE_TYPE_INVALID; + } +} + +CK_RV +mock_C_GetAttributeValue (CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE object, + CK_ATTRIBUTE_PTR template, + CK_ULONG count) +{ + CK_RV rv, ret = CKR_OK; + GcrCertificate *cert; + Assertion *assertion; + Session *sess; + CK_ULONG i; + + sess = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (session)); + g_return_val_if_fail (sess != NULL, CKR_SESSION_HANDLE_INVALID); + + cert = g_hash_table_lookup (the_certificates, GUINT_TO_POINTER (object)); + assertion = g_hash_table_lookup (the_assertions, GUINT_TO_POINTER (object)); + + if (cert != NULL) { + for (i = 0; i < count; i++) { + rv = fill_certificate_attribute (template + i, cert); + if (rv != CKR_OK) + template[i].ulValueLen = (CK_ULONG)-1; + if (ret != CKR_OK) + ret = rv; + } + } else if (assertion != NULL) { + for (i = 0; i < count; i++) { + rv = fill_assertion_attribute (template + i, assertion); + if (rv != CKR_OK) + template[i].ulValueLen = (CK_ULONG)-1; + if (ret != CKR_OK) + ret = rv; + } + } else { + ret = CKR_OBJECT_HANDLE_INVALID; + } + + return ret; +} + +CK_RV +mock_readonly_C_SetAttributeValue (CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE object, + CK_ATTRIBUTE_PTR template, + CK_ULONG count) +{ + Session *sess; + + sess = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (session)); + g_return_val_if_fail (sess, CKR_SESSION_HANDLE_INVALID); + + return CKR_TOKEN_WRITE_PROTECTED; +} + +static gboolean +match_object_attributes (CK_SESSION_HANDLE session, + CK_ULONG object, + CK_ATTRIBUTE_PTR template, + CK_ULONG count) +{ + CK_ATTRIBUTE_PTR values; + gboolean mismatch = FALSE; + CK_RV rv; + CK_ULONG i; + + values = g_new0 (CK_ATTRIBUTE, count); + for (i = 0; i < count; i++) { + values[i].type = template[i].type; + if (template[i].ulValueLen != 0 && + template[i].ulValueLen != (CK_ULONG)-1) + values[i].pValue = g_malloc (template[i].ulValueLen); + values[i].ulValueLen = template[i].ulValueLen; + } + + rv = mock_C_GetAttributeValue (session, object, values, count); + + if (rv == CKR_OK) { + for (i = 0; i < count; i++) { + if (gcr_comparable_memcmp (values[i].pValue, values[i].ulValueLen, + template[i].pValue, template[i].ulValueLen) != 0) { + mismatch = TRUE; + break; + } + } + } + + for (i = 0; i < count; i++) + g_free (values[i].pValue); + g_free (values); + + if (rv != CKR_OK) + return FALSE; + + return !mismatch; +} + +CK_RV +mock_C_FindObjectsInit (CK_SESSION_HANDLE session, + CK_ATTRIBUTE_PTR template, + CK_ULONG count) +{ + GList *objects = NULL, *l; + Session *sess; + + sess = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (session)); + g_return_val_if_fail (sess != NULL, CKR_SESSION_HANDLE_INVALID); + + /* Starting an operation, cancels any previous one */ + if (sess->operation != 0) + sess->operation = 0; + + sess->operation = OP_FIND; + g_list_free (sess->matches); + sess->matches = NULL; + + objects = g_list_concat (objects, g_hash_table_get_keys (the_certificates)); + objects = g_list_concat (objects, g_hash_table_get_keys (the_assertions)); + + for (l = objects; l != NULL; l = g_list_next (l)) { + if (match_object_attributes (session, GPOINTER_TO_UINT (l->data), template, count)) + sess->matches = g_list_prepend (sess->matches, l->data); + } + + g_list_free (objects); + return CKR_OK; +} + +CK_RV +mock_C_FindObjects (CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE_PTR object, + CK_ULONG max_object_count, + CK_ULONG_PTR object_count) +{ + Session *sess; + + g_return_val_if_fail (object, CKR_ARGUMENTS_BAD); + g_return_val_if_fail (object_count, CKR_ARGUMENTS_BAD); + g_return_val_if_fail (max_object_count != 0, CKR_ARGUMENTS_BAD); + + sess = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (session)); + g_return_val_if_fail (sess != NULL, CKR_SESSION_HANDLE_INVALID); + g_return_val_if_fail (sess->operation == OP_FIND, CKR_OPERATION_NOT_INITIALIZED); + + *object_count = 0; + while (max_object_count > 0 && sess->matches) + { + *object = GPOINTER_TO_UINT (sess->matches->data); + ++object; + --max_object_count; + ++(*object_count); + sess->matches = g_list_remove (sess->matches, sess->matches->data); + } + + return CKR_OK; +} + +CK_RV +mock_C_FindObjectsFinal (CK_SESSION_HANDLE session) +{ + Session *sess; + + sess = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (session)); + g_return_val_if_fail (sess != NULL, CKR_SESSION_HANDLE_INVALID); + g_return_val_if_fail (sess->operation == OP_FIND, CKR_OPERATION_NOT_INITIALIZED); + + sess->operation = 0; + g_list_free (sess->matches); + sess->matches = NULL; + + return CKR_OK; +} + +CK_RV +mock_no_mechanisms_C_EncryptInit (CK_SESSION_HANDLE session, + CK_MECHANISM_PTR mechanism, + CK_OBJECT_HANDLE key) +{ + Session *sess; + + sess = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (session)); + g_return_val_if_fail (sess != NULL, CKR_SESSION_HANDLE_INVALID); + + return CKR_MECHANISM_INVALID; +} + +CK_RV +mock_not_initialized_C_Encrypt (CK_SESSION_HANDLE session, + CK_BYTE_PTR data, + CK_ULONG data_len, + CK_BYTE_PTR encrypted_data, + CK_ULONG_PTR encrypted_data_len) +{ + return CKR_OPERATION_NOT_INITIALIZED; +} + +CK_RV +mock_unsupported_C_EncryptUpdate (CK_SESSION_HANDLE session, + CK_BYTE_PTR part, + CK_ULONG part_len, + CK_BYTE_PTR encrypted_part, + CK_ULONG_PTR encrypted_part_len) +{ + return CKR_FUNCTION_NOT_SUPPORTED; +} + +CK_RV +mock_unsupported_C_EncryptFinal (CK_SESSION_HANDLE session, + CK_BYTE_PTR last_encrypted_part, + CK_ULONG_PTR last_encrypted_part_len) +{ + return CKR_FUNCTION_NOT_SUPPORTED; +} + +CK_RV +mock_no_mechanisms_C_DecryptInit (CK_SESSION_HANDLE session, + CK_MECHANISM_PTR mechanism, + CK_OBJECT_HANDLE key) +{ + Session *sess; + + sess = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (session)); + g_return_val_if_fail (sess != NULL, CKR_SESSION_HANDLE_INVALID); + + return CKR_MECHANISM_INVALID; +} + +CK_RV +mock_not_initialized_C_Decrypt (CK_SESSION_HANDLE session, + CK_BYTE_PTR encrypted_data, + CK_ULONG encrypted_data_len, + CK_BYTE_PTR data, + CK_ULONG_PTR data_len) +{ + return CKR_OPERATION_NOT_INITIALIZED; +} + +CK_RV +mock_unsupported_C_DecryptUpdate (CK_SESSION_HANDLE session, + CK_BYTE_PTR encrypted_part, + CK_ULONG encrypted_key_len, + CK_BYTE_PTR part, + CK_ULONG_PTR part_len) +{ + return CKR_FUNCTION_NOT_SUPPORTED; +} + +CK_RV +mock_unsupported_C_DecryptFinal (CK_SESSION_HANDLE session, + CK_BYTE_PTR last_part, + CK_ULONG_PTR last_part_len) +{ + return CKR_FUNCTION_NOT_SUPPORTED; +} + +CK_RV +mock_unsupported_C_DigestInit (CK_SESSION_HANDLE session, + CK_MECHANISM_PTR mechanism) +{ + return CKR_FUNCTION_NOT_SUPPORTED; +} + +CK_RV +mock_unsupported_C_Digest (CK_SESSION_HANDLE session, + CK_BYTE_PTR data, + CK_ULONG data_len, + CK_BYTE_PTR digest, + CK_ULONG_PTR digest_len) +{ + return CKR_FUNCTION_NOT_SUPPORTED; +} + +CK_RV +mock_unsupported_C_DigestUpdate (CK_SESSION_HANDLE session, + CK_BYTE_PTR part, + CK_ULONG part_len) +{ + return CKR_FUNCTION_NOT_SUPPORTED; +} + +CK_RV +mock_unsupported_C_DigestKey (CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE key) +{ + return CKR_FUNCTION_NOT_SUPPORTED; +} + +CK_RV +mock_unsupported_C_DigestFinal (CK_SESSION_HANDLE session, + CK_BYTE_PTR digest, + CK_ULONG_PTR digest_len) +{ + return CKR_FUNCTION_NOT_SUPPORTED; +} + +CK_RV +mock_no_mechanisms_C_SignInit (CK_SESSION_HANDLE session, + CK_MECHANISM_PTR mechanism, + CK_OBJECT_HANDLE key) +{ + Session *sess; + + sess = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (session)); + g_return_val_if_fail (sess != NULL, CKR_SESSION_HANDLE_INVALID); + + return CKR_MECHANISM_INVALID; +} + +CK_RV +mock_not_initialized_C_Sign (CK_SESSION_HANDLE session, + CK_BYTE_PTR data, + CK_ULONG data_len, + CK_BYTE_PTR signature, + CK_ULONG_PTR signature_len) +{ + return CKR_OPERATION_NOT_INITIALIZED; +} + +CK_RV +mock_unsupported_C_SignUpdate (CK_SESSION_HANDLE session, + CK_BYTE_PTR part, + CK_ULONG part_len) +{ + return CKR_FUNCTION_NOT_SUPPORTED; +} + +CK_RV +mock_unsupported_C_SignFinal (CK_SESSION_HANDLE session, + CK_BYTE_PTR signature, + CK_ULONG_PTR signature_len) +{ + return CKR_FUNCTION_NOT_SUPPORTED; +} + +CK_RV +mock_unsupported_C_SignRecoverInit (CK_SESSION_HANDLE session, + CK_MECHANISM_PTR mechanism, + CK_OBJECT_HANDLE key) +{ + return CKR_FUNCTION_NOT_SUPPORTED; +} + +CK_RV +mock_unsupported_C_SignRecover (CK_SESSION_HANDLE session, + CK_BYTE_PTR data, + CK_ULONG data_len, + CK_BYTE_PTR signature, + CK_ULONG_PTR signature_len) +{ + return CKR_FUNCTION_NOT_SUPPORTED; +} + +CK_RV +mock_no_mechanisms_C_VerifyInit (CK_SESSION_HANDLE session, + CK_MECHANISM_PTR mechanism, + CK_OBJECT_HANDLE key) +{ + Session *sess; + + sess = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (session)); + g_return_val_if_fail (sess != NULL, CKR_SESSION_HANDLE_INVALID); + + return CKR_MECHANISM_INVALID; +} + +CK_RV +mock_not_initialized_C_Verify (CK_SESSION_HANDLE session, + CK_BYTE_PTR data, + CK_ULONG data_len, + CK_BYTE_PTR signature, + CK_ULONG signature_len) +{ + return CKR_OPERATION_NOT_INITIALIZED; +} + +CK_RV +mock_unsupported_C_VerifyUpdate (CK_SESSION_HANDLE session, + CK_BYTE_PTR part, + CK_ULONG part_len) +{ + return CKR_FUNCTION_NOT_SUPPORTED; +} + +CK_RV +mock_unsupported_C_VerifyFinal (CK_SESSION_HANDLE session, + CK_BYTE_PTR signature, + CK_ULONG signature_len) +{ + return CKR_FUNCTION_NOT_SUPPORTED; +} + +CK_RV +mock_unsupported_C_VerifyRecoverInit (CK_SESSION_HANDLE session, + CK_MECHANISM_PTR mechanism, + CK_OBJECT_HANDLE key) +{ + return CKR_FUNCTION_NOT_SUPPORTED; +} + +CK_RV +mock_unsupported_C_VerifyRecover (CK_SESSION_HANDLE session, + CK_BYTE_PTR signature, + CK_ULONG signature_len, + CK_BYTE_PTR data, + CK_ULONG_PTR data_len) +{ + return CKR_FUNCTION_NOT_SUPPORTED; +} + +CK_RV +mock_unsupported_C_DigestEncryptUpdate (CK_SESSION_HANDLE session, + CK_BYTE_PTR part, + CK_ULONG part_len, + CK_BYTE_PTR encrypted_part, + CK_ULONG_PTR encrypted_key_len) +{ + return CKR_FUNCTION_NOT_SUPPORTED; +} + +CK_RV +mock_unsupported_C_DecryptDigestUpdate (CK_SESSION_HANDLE session, + CK_BYTE_PTR encrypted_part, + CK_ULONG encrypted_key_len, + CK_BYTE_PTR part, + CK_ULONG_PTR part_len) +{ + return CKR_FUNCTION_NOT_SUPPORTED; +} + +CK_RV +mock_unsupported_C_SignEncryptUpdate (CK_SESSION_HANDLE session, + CK_BYTE_PTR part, + CK_ULONG part_len, + CK_BYTE_PTR encrypted_part, + CK_ULONG_PTR encrypted_key_len) +{ + return CKR_FUNCTION_NOT_SUPPORTED; +} + +CK_RV +mock_unsupported_C_DecryptVerifyUpdate (CK_SESSION_HANDLE session, + CK_BYTE_PTR encrypted_part, + CK_ULONG encrypted_key_len, + CK_BYTE_PTR part, + CK_ULONG_PTR part_len) +{ + return CKR_FUNCTION_NOT_SUPPORTED; +} + +CK_RV +mock_unsupported_C_GenerateKey (CK_SESSION_HANDLE session, + CK_MECHANISM_PTR mechanism, + CK_ATTRIBUTE_PTR template, + CK_ULONG count, + CK_OBJECT_HANDLE_PTR key) +{ + return CKR_FUNCTION_NOT_SUPPORTED; +} + +CK_RV +mock_no_mechanisms_C_GenerateKeyPair (CK_SESSION_HANDLE session, + CK_MECHANISM_PTR mechanism, + CK_ATTRIBUTE_PTR public_key_template, + CK_ULONG public_key_attribute_count, + CK_ATTRIBUTE_PTR private_key_template, + CK_ULONG private_key_attribute_count, + CK_OBJECT_HANDLE_PTR public_key, + CK_OBJECT_HANDLE_PTR private_key) +{ + Session *sess; + + g_return_val_if_fail (mechanism, CKR_MECHANISM_INVALID); + g_return_val_if_fail (public_key_template, CKR_TEMPLATE_INCOMPLETE); + g_return_val_if_fail (public_key_attribute_count, CKR_TEMPLATE_INCOMPLETE); + g_return_val_if_fail (private_key_template, CKR_TEMPLATE_INCOMPLETE); + g_return_val_if_fail (private_key_attribute_count, CKR_TEMPLATE_INCOMPLETE); + g_return_val_if_fail (public_key, CKR_ARGUMENTS_BAD); + g_return_val_if_fail (private_key, CKR_ARGUMENTS_BAD); + + sess = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (session)); + g_return_val_if_fail (sess != NULL, CKR_SESSION_HANDLE_INVALID); + + return CKR_MECHANISM_INVALID; +} + +CK_RV +mock_no_mechanisms_C_WrapKey (CK_SESSION_HANDLE session, + CK_MECHANISM_PTR mechanism, + CK_OBJECT_HANDLE wrapping_key, + CK_OBJECT_HANDLE key, + CK_BYTE_PTR wrapped_key, + CK_ULONG_PTR wrapped_key_len) +{ + Session *sess; + + g_return_val_if_fail (mechanism, CKR_MECHANISM_INVALID); + g_return_val_if_fail (wrapping_key, CKR_OBJECT_HANDLE_INVALID); + g_return_val_if_fail (key, CKR_OBJECT_HANDLE_INVALID); + g_return_val_if_fail (wrapped_key_len, CKR_WRAPPED_KEY_LEN_RANGE); + + sess = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (session)); + g_return_val_if_fail (sess != NULL, CKR_SESSION_HANDLE_INVALID); + + return CKR_MECHANISM_INVALID; +} + +CK_RV +mock_no_mechanisms_C_UnwrapKey (CK_SESSION_HANDLE session, + CK_MECHANISM_PTR mechanism, + CK_OBJECT_HANDLE unwrapping_key, + CK_BYTE_PTR wrapped_key, + CK_ULONG wrapped_key_len, + CK_ATTRIBUTE_PTR template, + CK_ULONG count, + CK_OBJECT_HANDLE_PTR key) +{ + Session *sess; + + g_return_val_if_fail (mechanism, CKR_MECHANISM_INVALID); + g_return_val_if_fail (unwrapping_key, CKR_WRAPPING_KEY_HANDLE_INVALID); + g_return_val_if_fail (wrapped_key, CKR_WRAPPED_KEY_INVALID); + g_return_val_if_fail (wrapped_key_len, CKR_WRAPPED_KEY_LEN_RANGE); + g_return_val_if_fail (key, CKR_ARGUMENTS_BAD); + g_return_val_if_fail (template, CKR_TEMPLATE_INCOMPLETE); + g_return_val_if_fail (count, CKR_TEMPLATE_INCONSISTENT); + + sess = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (session)); + g_return_val_if_fail (sess != NULL, CKR_SESSION_HANDLE_INVALID); + + return CKR_MECHANISM_INVALID; +} + +CK_RV +mock_no_mechanisms_C_DeriveKey (CK_SESSION_HANDLE session, + CK_MECHANISM_PTR mechanism, + CK_OBJECT_HANDLE base_key, + CK_ATTRIBUTE_PTR template, + CK_ULONG count, + CK_OBJECT_HANDLE_PTR key) +{ + Session *sess; + + g_return_val_if_fail (mechanism, CKR_MECHANISM_INVALID); + g_return_val_if_fail (count, CKR_TEMPLATE_INCOMPLETE); + g_return_val_if_fail (template, CKR_TEMPLATE_INCOMPLETE); + g_return_val_if_fail (key, CKR_ARGUMENTS_BAD); + + sess = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (session)); + g_return_val_if_fail (sess != NULL, CKR_SESSION_HANDLE_INVALID); + + return CKR_MECHANISM_INVALID; +} + +CK_RV +mock_unsupported_C_SeedRandom (CK_SESSION_HANDLE session, + CK_BYTE_PTR pSeed, + CK_ULONG seed_len) +{ + return CKR_FUNCTION_NOT_SUPPORTED; +} + +CK_RV +mock_unsupported_C_GenerateRandom (CK_SESSION_HANDLE session, + CK_BYTE_PTR random_data, + CK_ULONG random_len) +{ + return CKR_FUNCTION_NOT_SUPPORTED; +} + +CK_FUNCTION_LIST mock_default_functions = { + { 2, 11 }, /* version */ + mock_C_Initialize, + mock_C_Finalize, + mock_C_GetInfo, + mock_C_GetFunctionList, + mock_C_GetSlotList, + mock_C_GetSlotInfo, + mock_C_GetTokenInfo, + mock_C_GetMechanismList, + mock_C_GetMechanismInfo, + mock_unsupported_C_InitToken, + mock_unsupported_C_InitPIN, + mock_unsupported_C_SetPIN, + mock_C_OpenSession, + mock_C_CloseSession, + mock_C_CloseAllSessions, + mock_C_GetSessionInfo, + mock_unsupported_C_GetOperationState, + mock_unsupported_C_SetOperationState, + mock_unsupported_C_Login, + mock_unsupported_C_Logout, + mock_readonly_C_CreateObject, + mock_unsupported_C_CopyObject, + mock_readonly_C_DestroyObject, + mock_unsupported_C_GetObjectSize, + mock_C_GetAttributeValue, + mock_readonly_C_SetAttributeValue, + mock_C_FindObjectsInit, + mock_C_FindObjects, + mock_C_FindObjectsFinal, + mock_no_mechanisms_C_EncryptInit, + mock_not_initialized_C_Encrypt, + mock_unsupported_C_EncryptUpdate, + mock_unsupported_C_EncryptFinal, + mock_no_mechanisms_C_DecryptInit, + mock_not_initialized_C_Decrypt, + mock_unsupported_C_DecryptUpdate, + mock_unsupported_C_DecryptFinal, + mock_unsupported_C_DigestInit, + mock_unsupported_C_Digest, + mock_unsupported_C_DigestUpdate, + mock_unsupported_C_DigestKey, + mock_unsupported_C_DigestFinal, + mock_no_mechanisms_C_SignInit, + mock_not_initialized_C_Sign, + mock_unsupported_C_SignUpdate, + mock_unsupported_C_SignFinal, + mock_unsupported_C_SignRecoverInit, + mock_unsupported_C_SignRecover, + mock_no_mechanisms_C_VerifyInit, + mock_not_initialized_C_Verify, + mock_unsupported_C_VerifyUpdate, + mock_unsupported_C_VerifyFinal, + mock_unsupported_C_VerifyRecoverInit, + mock_unsupported_C_VerifyRecover, + mock_unsupported_C_DigestEncryptUpdate, + mock_unsupported_C_DecryptDigestUpdate, + mock_unsupported_C_SignEncryptUpdate, + mock_unsupported_C_DecryptVerifyUpdate, + mock_unsupported_C_GenerateKey, + mock_no_mechanisms_C_GenerateKeyPair, + mock_no_mechanisms_C_WrapKey, + mock_no_mechanisms_C_UnwrapKey, + mock_no_mechanisms_C_DeriveKey, + mock_unsupported_C_SeedRandom, + mock_unsupported_C_GenerateRandom, + mock_C_GetFunctionStatus, + mock_C_CancelFunction, + mock_unsupported_C_WaitForSlotEvent +}; diff --git a/tests/mock-pkcs11.h b/tests/mock-pkcs11.h new file mode 100644 index 000000000..40ef1f28a --- /dev/null +++ b/tests/mock-pkcs11.h @@ -0,0 +1,352 @@ +/* + * Copyright (C) 2010-2012 Stefan Walter + * Copyright (C) 2011 Collabora Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#include <glib.h> + +#include <gcr/gcr.h> + +#include <gck/pkcs11.h> +#include <gck/pkcs11x.h> + +#ifndef MOCK_MODULE_H +#define MOCK_MODULE_H + +extern CK_FUNCTION_LIST mock_default_functions; + +CK_RV mock_C_Initialize (CK_VOID_PTR pInitArgs); + +CK_RV mock_C_Finalize (CK_VOID_PTR pReserved); + +CK_RV mock_C_GetInfo (CK_INFO_PTR pInfo); + +CK_RV mock_C_GetFunctionList (CK_FUNCTION_LIST_PTR_PTR list); + +CK_RV mock_C_GetSlotList (CK_BBOOL tokenPresent, + CK_SLOT_ID_PTR pSlotList, + CK_ULONG_PTR pulCount); + +CK_RV mock_C_GetSlotInfo (CK_SLOT_ID slotID, + CK_SLOT_INFO_PTR pInfo); + +CK_RV mock_C_GetTokenInfo (CK_SLOT_ID slotID, + CK_TOKEN_INFO_PTR pInfo); + +CK_RV mock_C_GetMechanismList (CK_SLOT_ID slotID, + CK_MECHANISM_TYPE_PTR pMechanismList, + CK_ULONG_PTR pulCount); + +CK_RV mock_C_GetMechanismInfo (CK_SLOT_ID slotID, + CK_MECHANISM_TYPE type, + CK_MECHANISM_INFO_PTR pInfo); + +CK_RV mock_unsupported_C_InitToken (CK_SLOT_ID slotID, + CK_UTF8CHAR_PTR pPin, + CK_ULONG ulPinLen, + CK_UTF8CHAR_PTR pLabel); + +CK_RV mock_unsupported_C_WaitForSlotEvent (CK_FLAGS flags, + CK_SLOT_ID_PTR pSlot, + CK_VOID_PTR pReserved); + +CK_RV mock_C_OpenSession (CK_SLOT_ID slotID, + CK_FLAGS flags, + CK_VOID_PTR pApplication, + CK_NOTIFY Notify, + CK_SESSION_HANDLE_PTR phSession); + +CK_RV mock_C_CloseSession (CK_SESSION_HANDLE hSession); + +CK_RV mock_C_CloseAllSessions (CK_SLOT_ID slotID); + +CK_RV mock_C_GetFunctionStatus (CK_SESSION_HANDLE hSession); + +CK_RV mock_C_CancelFunction (CK_SESSION_HANDLE hSession); + +CK_RV mock_C_GetSessionInfo (CK_SESSION_HANDLE hSession, + CK_SESSION_INFO_PTR pInfo); + +CK_RV mock_unsupported_C_InitPIN (CK_SESSION_HANDLE hSession, + CK_UTF8CHAR_PTR pPin, + CK_ULONG ulPinLen); + +CK_RV mock_unsupported_C_SetPIN (CK_SESSION_HANDLE hSession, + CK_UTF8CHAR_PTR pOldPin, + CK_ULONG ulOldLen, + CK_UTF8CHAR_PTR pNewPin, + CK_ULONG ulNewLen); + +CK_RV mock_unsupported_C_GetOperationState (CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pOperationState, + CK_ULONG_PTR pulOperationStateLen); + +CK_RV mock_unsupported_C_SetOperationState (CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pOperationState, + CK_ULONG ulOperationStateLen, + CK_OBJECT_HANDLE hEncryptionKey, + CK_OBJECT_HANDLE hAuthenticationKey); + +CK_RV mock_unsupported_C_Login (CK_SESSION_HANDLE hSession, + CK_USER_TYPE userType, + CK_UTF8CHAR_PTR pPin, + CK_ULONG pPinLen); + +CK_RV mock_unsupported_C_Logout (CK_SESSION_HANDLE hSession); + +CK_RV mock_readonly_C_CreateObject (CK_SESSION_HANDLE hSession, + CK_ATTRIBUTE_PTR pTemplate, + CK_ULONG ulCount, + CK_OBJECT_HANDLE_PTR phObject); + +CK_RV mock_unsupported_C_CopyObject (CK_SESSION_HANDLE hSession, + CK_OBJECT_HANDLE hObject, + CK_ATTRIBUTE_PTR pTemplate, + CK_ULONG ulCount, + CK_OBJECT_HANDLE_PTR phNewObject); + +CK_RV mock_readonly_C_DestroyObject (CK_SESSION_HANDLE hSession, + CK_OBJECT_HANDLE hObject); + +CK_RV mock_unsupported_C_GetObjectSize (CK_SESSION_HANDLE hSession, + CK_OBJECT_HANDLE hObject, + CK_ULONG_PTR pulSize); + +CK_RV mock_C_GetAttributeValue (CK_SESSION_HANDLE hSession, + CK_OBJECT_HANDLE hObject, + CK_ATTRIBUTE_PTR pTemplate, + CK_ULONG ulCount); + +CK_RV mock_readonly_C_SetAttributeValue (CK_SESSION_HANDLE hSession, + CK_OBJECT_HANDLE hObject, + CK_ATTRIBUTE_PTR pTemplate, + CK_ULONG ulCount); + +CK_RV mock_C_FindObjectsInit (CK_SESSION_HANDLE hSession, + CK_ATTRIBUTE_PTR pTemplate, + CK_ULONG ulCount); + +CK_RV mock_C_FindObjects (CK_SESSION_HANDLE hSession, + CK_OBJECT_HANDLE_PTR phObject, + CK_ULONG ulMaxObjectCount, + CK_ULONG_PTR pulObjectCount); + +CK_RV mock_fail_C_FindObjects (CK_SESSION_HANDLE hSession, + CK_OBJECT_HANDLE_PTR phObject, + CK_ULONG ulMaxObjectCount, + CK_ULONG_PTR pulObjectCount); + +CK_RV mock_C_FindObjectsFinal (CK_SESSION_HANDLE hSession); + +CK_RV mock_no_mechanisms_C_EncryptInit (CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hKey); + +CK_RV mock_not_initialized_C_Encrypt (CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pData, + CK_ULONG ulDataLen, + CK_BYTE_PTR pEncryptedData, + CK_ULONG_PTR pulEncryptedDataLen); + +CK_RV mock_unsupported_C_EncryptUpdate (CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pPart, + CK_ULONG ulPartLen, + CK_BYTE_PTR pEncryptedPart, + CK_ULONG_PTR pulEncryptedPartLen); + +CK_RV mock_unsupported_C_EncryptFinal (CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pLastEncryptedPart, + CK_ULONG_PTR pulLastEncryptedPartLen); + +CK_RV mock_no_mechanisms_C_DecryptInit (CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hKey); + +CK_RV mock_not_initialized_C_Decrypt (CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pEncryptedData, + CK_ULONG ulEncryptedDataLen, + CK_BYTE_PTR pData, + CK_ULONG_PTR pulDataLen); + +CK_RV mock_unsupported_C_DecryptUpdate (CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pEncryptedPart, + CK_ULONG ulEncryptedPartLen, + CK_BYTE_PTR pPart, + CK_ULONG_PTR pulPartLen); + +CK_RV mock_unsupported_C_DecryptFinal (CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pLastPart, + CK_ULONG_PTR pulLastPartLen); + +CK_RV mock_unsupported_C_DigestInit (CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism); + +CK_RV mock_unsupported_C_Digest (CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pData, + CK_ULONG ulDataLen, + CK_BYTE_PTR pDigest, + CK_ULONG_PTR pulDigestLen); + +CK_RV mock_unsupported_C_DigestUpdate (CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pPart, + CK_ULONG ulPartLen); + +CK_RV mock_unsupported_C_DigestKey (CK_SESSION_HANDLE hSession, + CK_OBJECT_HANDLE hKey); + +CK_RV mock_unsupported_C_DigestFinal (CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pDigest, + CK_ULONG_PTR pulDigestLen); + +CK_RV mock_no_mechanisms_C_SignInit (CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hKey); + +CK_RV mock_not_initialized_C_Sign (CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pData, + CK_ULONG ulDataLen, + CK_BYTE_PTR pSignature, + CK_ULONG_PTR pulSignatureLen); + +CK_RV mock_unsupported_C_SignUpdate (CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pPart, + CK_ULONG ulPartLen); + +CK_RV mock_unsupported_C_SignFinal (CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pSignature, + CK_ULONG_PTR pulSignatureLen); + +CK_RV mock_unsupported_C_SignRecoverInit (CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hKey); + +CK_RV mock_unsupported_C_SignRecover (CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pData, + CK_ULONG ulDataLen, + CK_BYTE_PTR pSignature, + CK_ULONG_PTR pulSignatureLen); + +CK_RV mock_no_mechanisms_C_VerifyInit (CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hKey); + +CK_RV mock_not_initialized_C_Verify (CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pData, + CK_ULONG ulDataLen, + CK_BYTE_PTR pSignature, + CK_ULONG ulSignatureLen); + +CK_RV mock_unsupported_C_VerifyUpdate (CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pPart, + CK_ULONG ulPartLen); + +CK_RV mock_unsupported_C_VerifyFinal (CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pSignature, + CK_ULONG pulSignatureLen); + +CK_RV mock_unsupported_C_VerifyRecoverInit (CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hKey); + +CK_RV mock_unsupported_C_VerifyRecover (CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pSignature, + CK_ULONG pulSignatureLen, + CK_BYTE_PTR pData, + CK_ULONG_PTR pulDataLen); + +CK_RV mock_unsupported_C_DigestEncryptUpdate (CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pPart, + CK_ULONG ulPartLen, + CK_BYTE_PTR pEncryptedPart, + CK_ULONG_PTR ulEncryptedPartLen); + +CK_RV mock_unsupported_C_DecryptDigestUpdate (CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pEncryptedPart, + CK_ULONG ulEncryptedPartLen, + CK_BYTE_PTR pPart, + CK_ULONG_PTR pulPartLen); + +CK_RV mock_unsupported_C_SignEncryptUpdate (CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pPart, + CK_ULONG ulPartLen, + CK_BYTE_PTR pEncryptedPart, + CK_ULONG_PTR ulEncryptedPartLen); + +CK_RV mock_unsupported_C_DecryptVerifyUpdate (CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pEncryptedPart, + CK_ULONG ulEncryptedPartLen, + CK_BYTE_PTR pPart, + CK_ULONG_PTR pulPartLen); + +CK_RV mock_unsupported_C_GenerateKey (CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_ATTRIBUTE_PTR pTemplate, + CK_ULONG ulCount, + CK_OBJECT_HANDLE_PTR phKey); + +CK_RV mock_no_mechanisms_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); + +CK_RV mock_no_mechanisms_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); + +CK_RV mock_no_mechanisms_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); + +CK_RV mock_no_mechanisms_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); + +CK_RV mock_unsupported_C_SeedRandom (CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pSeed, + CK_ULONG ulSeedLen); + +CK_RV mock_unsupported_C_GenerateRandom (CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pRandomData, + CK_ULONG ulRandomLen); + +CK_OBJECT_HANDLE mock_module_add_certificate (GcrCertificate *cert); + +CK_OBJECT_HANDLE mock_module_add_assertion (GcrCertificate *cert, + CK_X_ASSERTION_TYPE assertion_type, + const gchar *purpose, + const gchar *peer); + +#define MOCK_SLOT_ONE_ID 1 +#define MOCK_SLOT_ONE_URI "pkcs11:manufacturer=MOCK%20MANUFACTURER;serial=MOCK%20SERIAL" + +#endif /* MOCK_MODULE_H */ |