From 381d16e651d5bcace316fbab4095c8dea8c43a92 Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Thu, 16 May 2019 16:52:37 +0200 Subject: [PATCH] proxy: Support C_WaitForSlotEvent() if CKF_DONT_BLOCK is specified While fully implementing C_WaitForSlotEvent() would require a separate thread to monitor events, it is straightforward to implement the function if the CKF_DONT_BLOCK flag is given. Suggested by David Ward. --- p11-kit/Makefile.am | 7 +++- p11-kit/mock-module-ep7.c | 70 +++++++++++++++++++++++++++++++++++++++ p11-kit/proxy.c | 64 +++++++++++++++++++++++++++-------- p11-kit/test-proxy.c | 40 ++++++++++++++++++++++ 4 files changed, 166 insertions(+), 15 deletions(-) create mode 100644 p11-kit/mock-module-ep7.c diff --git a/p11-kit/Makefile.am b/p11-kit/Makefile.am index 0155f7c58..09a068ef4 100644 --- a/p11-kit/Makefile.am +++ b/p11-kit/Makefile.am @@ -409,7 +409,8 @@ check_LTLIBRARIES += \ mock-four.la \ mock-five.la \ mock-seven.la \ - mock-eight.la + mock-eight.la \ + mock-nine.la mock_one_la_SOURCES = p11-kit/mock-module-ep.c mock_one_la_LIBADD = libp11-test.la libp11-common.la @@ -448,6 +449,10 @@ mock_eight_la_SOURCES = p11-kit/mock-module-ep6.c mock_eight_la_LDFLAGS = $(mock_one_la_LDFLAGS) mock_eight_la_LIBADD = $(mock_one_la_LIBADD) +mock_nine_la_SOURCES = p11-kit/mock-module-ep7.c +mock_nine_la_LDFLAGS = $(mock_one_la_LDFLAGS) +mock_nine_la_LIBADD = $(mock_one_la_LIBADD) + EXTRA_DIST += \ p11-kit/fixtures \ p11-kit/test-mock.c \ diff --git a/p11-kit/mock-module-ep7.c b/p11-kit/mock-module-ep7.c new file mode 100644 index 000000000..51fad06d4 --- /dev/null +++ b/p11-kit/mock-module-ep7.c @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2012 Stefan Walter + * Copyright (c) 2019 Red Hat, Inc. + * + * 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 , Daiki Ueno + */ + +#include "config.h" + +#define CRYPTOKI_EXPORTS 1 +#include "pkcs11.h" + +#include "mock.h" +#include "test.h" + +static CK_RV +override_wait_for_slot_event (CK_FLAGS flags, + CK_SLOT_ID_PTR slot, + CK_VOID_PTR reserved) +{ + if (flags & CKF_DONT_BLOCK) { + *slot = MOCK_SLOT_ONE_ID; + return CKR_OK; + } + + return mock_C_WaitForSlotEvent(flags, slot, reserved); +} + +#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_WaitForSlotEvent = override_wait_for_slot_event; + *list = &mock_module; + return CKR_OK; +} diff --git a/p11-kit/proxy.c b/p11-kit/proxy.c index ae8831863..a9c7055d7 100644 --- a/p11-kit/proxy.c +++ b/p11-kit/proxy.c @@ -604,7 +604,40 @@ proxy_C_WaitForSlotEvent (CK_X_FUNCTION_LIST *self, CK_SLOT_ID_PTR slot, CK_VOID_PTR reserved) { - return CKR_FUNCTION_NOT_SUPPORTED; + State *state = (State *)self; + Proxy *py = state->px; + CK_FUNCTION_LIST_PTR *f; + CK_FUNCTION_LIST_PTR funcs; + CK_SLOT_ID real_slot; + unsigned int i; + CK_RV rv = CKR_NO_EVENT; + + /* Only the non-blocking case is supported. */ + if ((flags & CKF_DONT_BLOCK) == 0) + return CKR_FUNCTION_NOT_SUPPORTED; + + p11_lock (); + + for (f = py->inited; *f; ++f) { + funcs = *f; + assert (funcs != NULL); + + rv = (funcs->C_WaitForSlotEvent) (flags, &real_slot, reserved); + if (rv == CKR_NO_EVENT) + continue; + if (rv != CKR_OK) + break; + for (i = 0; i < py->n_mappings; i++) + if (py->mappings[i].funcs == funcs && + py->mappings[i].real_slot == real_slot) { + *slot = py->mappings[i].wrap_slot; + break; + } + } + + p11_unlock (); + + return rv; } static CK_RV @@ -1617,14 +1650,6 @@ proxy_C_GenerateRandom (CK_X_FUNCTION_LIST *self, return (map.funcs->C_GenerateRandom) (handle, random_data, random_len); } -static CK_RV -module_C_WaitForSlotEvent (CK_FLAGS flags, - CK_SLOT_ID_PTR slot, - CK_VOID_PTR reserved) -{ - return proxy_C_WaitForSlotEvent (&global.virt.funcs, flags, slot, reserved); -} - /* -------------------------------------------------------------------- * MODULE ENTRY POINT */ @@ -1737,11 +1762,8 @@ C_GetFunctionList (CK_FUNCTION_LIST_PTR_PTR list) } } - if (rv == CKR_OK) { - /* We use this as a check below */ - module->C_WaitForSlotEvent = module_C_WaitForSlotEvent; + if (rv == CKR_OK) *list = module; - } if (loaded) p11_kit_modules_release (loaded); @@ -1769,7 +1791,21 @@ p11_proxy_module_cleanup (void) bool p11_proxy_module_check (CK_FUNCTION_LIST_PTR module) { - return (module->C_WaitForSlotEvent == module_C_WaitForSlotEvent); + State *state; + bool ret = false; + + if (!p11_virtual_is_wrapper (module)) + return false; + + p11_lock (); + for (state = all_instances; state != NULL; state = state->next) + if (state->wrapped == module) { + ret = true; + break; + } + p11_unlock (); + + return ret; } CK_RV diff --git a/p11-kit/test-proxy.c b/p11-kit/test-proxy.c index f61f37e18..9a8f71dec 100644 --- a/p11-kit/test-proxy.c +++ b/p11-kit/test-proxy.c @@ -234,6 +234,7 @@ teardown (void *unused) #define ENABLED "enable-in: test-proxy, p11-kit-proxy\n" #define DISABLED "disable-in: p11-kit-proxy\n" #define EIGHT_MODULE "module: mock-eight" SHLEXT "\n" +#define NINE_MODULE "module: mock-nine" SHLEXT "\n" static CK_ULONG load_modules_and_count_slots (void) @@ -343,6 +344,44 @@ test_slot_appear (void) p11_proxy_module_cleanup (); } +static void +test_slot_event (void) +{ + CK_FUNCTION_LIST_PTR proxy; + CK_SLOT_ID slot; + CK_SLOT_ID slots[32]; + CK_ULONG count; + CK_RV rv; + + p11_test_file_write (test.directory, "nine.module", NINE_MODULE, strlen (NINE_MODULE)); + + rv = C_GetFunctionList (&proxy); + assert (rv == CKR_OK); + + assert (p11_proxy_module_check (proxy)); + + rv = proxy->C_Initialize (NULL); + assert (rv == CKR_OK); + + rv = proxy->C_GetSlotList (CK_FALSE, slots, &count); + assert (rv == CKR_OK); + assert (count == 2); + + slot = 0; + rv = proxy->C_WaitForSlotEvent (0, &slot, NULL); + assert_num_eq (rv, CKR_FUNCTION_NOT_SUPPORTED); + assert_num_eq (slot, 0); + + rv = proxy->C_WaitForSlotEvent (CKF_DONT_BLOCK, &slot, NULL); + assert_num_eq (rv, CKR_OK); + assert_num_eq (slot, slots[0]); + + rv = proxy->C_Finalize (NULL); + assert_num_eq (rv, CKR_OK); + + p11_proxy_module_cleanup (); +} + static CK_FUNCTION_LIST_PTR setup_mock_module (CK_SESSION_HANDLE *session) { @@ -430,6 +469,7 @@ main (int argc, p11_test (test_disable, "/proxy/disable"); p11_test (test_no_slot, "/proxy/no-slot"); p11_test (test_slot_appear, "/proxy/slot-appear"); + p11_test (test_slot_event, "/proxy/slot-event"); test_mock_add_tests ("/proxy");