mock-one.la \
mock-two.la \
mock-three.la \
- mock-four.la
+ mock-four.la \
+ mock-five.la
mock_one_la_SOURCES = p11-kit/mock-module-ep.c
mock_one_la_LIBADD = libp11-test.la libp11-common.la
mock_four_la_LDFLAGS = $(mock_one_la_LDFLAGS)
mock_four_la_LIBADD = $(mock_one_la_LIBADD)
+mock_five_la_SOURCES = p11-kit/mock-module-ep3.c
+mock_five_la_LDFLAGS = $(mock_one_la_LDFLAGS)
+mock_five_la_LIBADD = $(mock_one_la_LIBADD)
+
EXTRA_DIST += \
p11-kit/fixtures \
p11-kit/test-mock.c \
--- /dev/null
+/*
+ * Copyright (c) 2012 Stefan Walter
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the
+ * above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ * * The names of contributors to this software may not be
+ * used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * Author: Stef Walter <stef@thewalter.net>
+ */
+
+#include "config.h"
+
+#define CRYPTOKI_EXPORTS 1
+#include "pkcs11.h"
+
+#include "mock.h"
+#include "test.h"
+
+#include <stdio.h>
+
+static CK_RV
+override_initialize (CK_VOID_PTR init_args)
+{
+ CK_C_INITIALIZE_ARGS_PTR args = init_args;
+
+ assert_str_eq ("initialize-arg", args->pReserved);
+
+ return mock_C_Initialize (init_args);
+}
+
+#ifdef OS_WIN32
+__declspec(dllexport)
+#endif
+CK_RV
+C_GetFunctionList (CK_FUNCTION_LIST_PTR_PTR list)
+{
+ mock_module_init ();
+ mock_module.C_GetFunctionList = C_GetFunctionList;
+ if (list == NULL)
+ return CKR_ARGUMENTS_BAD;
+ mock_module.C_Initialize = override_initialize;
+ *list = &mock_module;
+ return CKR_OK;
+}
rv = load_module_from_file_inlock (*name, filename, &mod);
if (rv != CKR_OK)
goto out;
-
- /*
- * We support setting of CK_C_INITIALIZE_ARGS.pReserved from
- * 'x-init-reserved' setting in the config. This only works with specific
- * PKCS#11 modules, and is non-standard use of that field.
- */
- mod->init_args.pReserved = p11_dict_get (*config, "x-init-reserved");
}
+ /*
+ * We support setting of CK_C_INITIALIZE_ARGS.pReserved from
+ * 'x-init-reserved' setting in the config. This only works with specific
+ * PKCS#11 modules, and is non-standard use of that field.
+ */
+ mod->init_args.pReserved = p11_dict_get (*config, "x-init-reserved");
+
/* Take ownership of thes evariables */
p11_dict_free (mod->config);
mod->config = *config;
}
static CK_RV
-initialize_module_inlock_reentrant (Module *mod)
+initialize_module_inlock_reentrant (Module *mod, CK_C_INITIALIZE_ARGS *init_args)
{
CK_RV rv = CKR_OK;
p11_thread_id_t self;
if (mod->initialize_called != p11_forkid) {
p11_debug ("C_Initialize: calling");
+ /* The init_args argument takes precedence over mod->init_args */
+ if (init_args == NULL)
+ init_args = &mod->init_args;
+
rv = mod->virt.funcs.C_Initialize (&mod->virt.funcs,
- &mod->init_args);
+ init_args);
p11_debug ("C_Initialize: result: %lu", rv);
if (mod->name == NULL || !is_module_enabled_unlocked (mod->name, mod->config))
continue;
- rv = initialize_module_inlock_reentrant (mod);
+ rv = initialize_module_inlock_reentrant (mod, NULL);
if (rv != CKR_OK) {
if (mod->critical) {
p11_message ("initialization of critical module '%s' failed: %s",
if (!sessions)
rv = CKR_HOST_MEMORY;
else
- rv = initialize_module_inlock_reentrant (managed->mod);
+ rv = initialize_module_inlock_reentrant (managed->mod, init_args);
if (rv == CKR_OK) {
if (managed->sessions)
p11_dict_free (managed->sessions);
if (rv == CKR_OK) {
mod = p11_dict_get (gl.unmanaged_by_funcs, module);
assert (mod != NULL);
- rv = initialize_module_inlock_reentrant (mod);
+ rv = initialize_module_inlock_reentrant (mod, NULL);
if (rv != CKR_OK) {
p11_message ("module initialization failed: %s", p11_kit_strerror (rv));
p11_module_release_inlock_reentrant (module);
if (rv == CKR_OK) {
/* WARNING: Reentrancy can occur here */
- rv = initialize_module_inlock_reentrant (mod);
+ rv = initialize_module_inlock_reentrant (mod, NULL);
}
}
if (init_args != NULL) {
int supplied_ok;
- /* pReserved must be NULL */
+ /*
+ * pReserved is either a string or NULL. Other cases
+ * should be rejected by the caller of this function.
+ */
args = init_args;
/* ALL supplied function pointers need to have the value either NULL or non-NULL. */
if (ret == CKR_OK)
if (!p11_rpc_message_write_byte_array (&msg, P11_RPC_HANDSHAKE, P11_RPC_HANDSHAKE_LEN))
ret = CKR_HOST_MEMORY;
+ if (ret == CKR_OK) {
+ if (!p11_rpc_message_write_byte (&msg, reserved != NULL))
+ ret = CKR_HOST_MEMORY;
+ }
+ if (ret == CKR_OK) {
+ char *reserved_string = "";
+ if (reserved != NULL)
+ reserved_string = (char *) reserved;
+ if (!p11_rpc_message_write_byte_array (&msg, (CK_BYTE_PTR) reserved_string, strlen (reserved_string) + 1))
+ ret = CKR_HOST_MEMORY;
+ }
if (ret == CKR_OK)
ret = call_run (module, &msg);
call_done (module, &msg, ret);
static const p11_rpc_call p11_rpc_calls[] = {
{ P11_RPC_CALL_ERROR, "ERROR", NULL, "u" },
- { P11_RPC_CALL_C_Initialize, "C_Initialize", "ay", "" },
+ { P11_RPC_CALL_C_Initialize, "C_Initialize", "ayyay", "" },
{ P11_RPC_CALL_C_Finalize, "C_Finalize", "", "" },
{ P11_RPC_CALL_C_GetInfo, "C_GetInfo", "", "vsusv" },
{ P11_RPC_CALL_C_GetSlotList, "C_GetSlotList", "yfu", "au" },
CK_C_INITIALIZE_ARGS init_args;
CK_BYTE_PTR handshake;
CK_ULONG n_handshake;
+ CK_BYTE reserved_present = 0;
+ CK_BYTE_PTR reserved = NULL;
+ CK_ULONG n_reserved;
CK_RV ret = CKR_OK;
p11_debug ("C_Initialize: enter");
p11_message ("invalid handshake received from connecting module");
ret = CKR_GENERAL_ERROR;
}
+ }
+
+ if (ret == CKR_OK) {
+ if (!p11_rpc_message_read_byte (msg, &reserved_present))
+ ret = PARSE_ERROR;
+ }
+
+ if (ret == CKR_OK) {
+ ret = proto_read_byte_array (msg, &reserved, &n_reserved);
assert (p11_rpc_message_is_verified (msg));
}
if (ret == CKR_OK) {
memset (&init_args, 0, sizeof (init_args));
init_args.flags = CKF_OS_LOCKING_OK;
+ init_args.pReserved = reserved_present ? reserved : NULL;
func = self->C_Initialize;
assert (func != NULL);
setenv ("P11_KIT_PRIVATEDIR", BUILDDIR, 1);
data = "remote: |" BUILDDIR "/p11-kit/p11-kit remote " BUILDDIR "/.libs/mock-two.so\n";
p11_test_file_write (test.user_modules, "remote.module", data, strlen (data));
+ data = "remote: |" BUILDDIR "/p11-kit/p11-kit remote " BUILDDIR "/.libs/mock-five.so\nx-init-reserved: initialize-arg";
+ p11_test_file_write (test.user_modules, "init-arg.module", data, strlen (data));
p11_config_user_modules = test.user_modules;
p11_config_user_file = test.user_config;
p11_kit_modules_release (modules);
}
+static void
+test_basic_exec_with_init_arg (void)
+{
+ CK_FUNCTION_LIST **modules;
+ CK_FUNCTION_LIST *module;
+ CK_RV rv;
+
+ modules = p11_kit_modules_load (NULL, 0);
+
+ module = p11_kit_module_for_name (modules, "init-arg");
+ assert (module != NULL);
+
+ rv = p11_kit_module_initialize (module);
+ assert_num_eq (rv, CKR_OK);
+
+ rv = p11_kit_module_finalize (module);
+ assert_num_eq (rv, CKR_OK);
+
+ p11_kit_modules_release (modules);
+}
+
static void *
invoke_in_thread (void *arg)
{
p11_fixture (setup_remote, teardown_remote);
p11_test (test_basic_exec, "/transport/basic");
+ p11_test (test_basic_exec_with_init_arg, "/transport/init-arg");
p11_test (test_simultaneous_functions, "/transport/simultaneous-functions");
#ifdef OS_UNIX