diff options
author | Stef Walter <stefw@gnome.org> | 2012-08-23 15:34:04 +0200 |
---|---|---|
committer | Stef Walter <stef@thewalter.net> | 2014-07-08 08:57:30 +0200 |
commit | c785ab66890ad7b73c556d6afdf2bb8a32dd50e2 (patch) | |
tree | b871dc6edf5e0a094fa3736eccdb92ca2a7091a8 /p11-kit/tests | |
parent | 469e75bb8184392cb47b3cb4897589caabe56e70 (diff) |
rpc: Implement PKCS#11 messages/client/server code
* This enables passing around bytes which represent PKCS#11 RPC calls.
* Caller is responsible for connecting/disconnecting and so on.
* Client side caller gets a mixin from p11_rpc_client_init() to call
into, which generates callbacks with byte arrays to be transported.
* Server side calls p11_rpc_server_handle() with a CK_FUNCTION_LIST_PTR
on which relevant methods get called.
* Doesn't yet implement the actual daemon or clients etc...
https://bugs.freedesktop.org/show_bug.cgi?id=54105
Diffstat (limited to 'p11-kit/tests')
-rw-r--r-- | p11-kit/tests/Makefile.am | 1 | ||||
-rw-r--r-- | p11-kit/tests/test-mock.c | 10 | ||||
-rw-r--r-- | p11-kit/tests/test-rpc.c | 939 |
3 files changed, 948 insertions, 2 deletions
diff --git a/p11-kit/tests/Makefile.am b/p11-kit/tests/Makefile.am index d270c74..2192fed 100644 --- a/p11-kit/tests/Makefile.am +++ b/p11-kit/tests/Makefile.am @@ -26,6 +26,7 @@ CHECK_PROGS = \ test-deprecated \ test-proxy \ test-iter \ + test-rpc \ $(NULL) if WITH_FFI diff --git a/p11-kit/tests/test-mock.c b/p11-kit/tests/test-mock.c index 5fba7ec..079ff0d 100644 --- a/p11-kit/tests/test-mock.c +++ b/p11-kit/tests/test-mock.c @@ -55,8 +55,14 @@ test_get_info (void) module = setup_mock_module (NULL); rv = (module->C_GetInfo) (&info); - assert (rv == CKR_OK); - assert (memcmp (&info, &MOCK_INFO, sizeof (CK_INFO)) == 0); + assert_num_eq (rv, CKR_OK); + assert_num_eq (MOCK_INFO.cryptokiVersion.major, info.cryptokiVersion.major); + assert_num_eq (MOCK_INFO.cryptokiVersion.minor, info.cryptokiVersion.minor); + assert (memcmp (MOCK_INFO.manufacturerID, info.manufacturerID, sizeof (info.manufacturerID)) == 0); + assert_num_eq (MOCK_INFO.flags, info.flags); + assert (memcmp (MOCK_INFO.libraryDescription, info.libraryDescription, sizeof (info.libraryDescription)) == 0); + assert_num_eq (MOCK_INFO.libraryVersion.major, info.libraryVersion.major); + assert_num_eq (MOCK_INFO.libraryVersion.minor, info.libraryVersion.minor); teardown_mock_module (module); } diff --git a/p11-kit/tests/test-rpc.c b/p11-kit/tests/test-rpc.c new file mode 100644 index 0000000..d945efd --- /dev/null +++ b/p11-kit/tests/test-rpc.c @@ -0,0 +1,939 @@ +/* + * Copyright (c) 2012 Stefan Walter + * Copyright (c) 2012 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 <stef@thewalter.net> + */ + +#include "config.h" +#include "test.h" + +#include "debug.h" +#include "library.h" +#include "message.h" +#include "mock.h" +#include "p11-kit.h" +#include "private.h" +#include "rpc.h" +#include "rpc-message.h" +#include "virtual.h" + +#include <sys/types.h> +#include <assert.h> +#include <string.h> +#include <stdio.h> +#include <stdlib.h> + +static void +test_new_free (void) +{ + p11_buffer *buf; + + buf = p11_rpc_buffer_new (0); + + assert_ptr_not_null (buf->data); + assert_num_eq (0, buf->len); + assert_num_eq (0, buf->flags); + assert (buf->size == 0); + assert_ptr_not_null (buf->ffree); + assert_ptr_not_null (buf->frealloc); + + p11_rpc_buffer_free (buf); +} + +static void +test_uint16 (void) +{ + p11_buffer buffer; + uint16_t val = 0xFFFF; + size_t next; + bool ret; + + p11_buffer_init (&buffer, 0); + + next = 0; + ret = p11_rpc_buffer_get_uint16 (&buffer, &next, &val); + assert_num_eq (false, ret); + assert_num_eq (0, next); + assert_num_eq (0xFFFF, val); + + p11_buffer_reset (&buffer, 0); + + ret = p11_rpc_buffer_set_uint16 (&buffer, 0, 0x6789); + assert_num_eq (false, ret); + + p11_buffer_reset (&buffer, 0); + + p11_buffer_add (&buffer, (unsigned char *)"padding", 7); + + p11_rpc_buffer_add_uint16 (&buffer, 0x6789); + assert_num_eq (9, buffer.len); + assert (!p11_buffer_failed (&buffer)); + + next = 7; + ret = p11_rpc_buffer_get_uint16 (&buffer, &next, &val); + assert_num_eq (true, ret); + assert_num_eq (9, next); + assert_num_eq (0x6789, val); + + p11_buffer_uninit (&buffer); +} + +static void +test_uint16_static (void) +{ + p11_buffer buf = { (unsigned char *)"pad0\x67\x89", 6, }; + uint16_t val = 0xFFFF; + size_t next; + bool ret; + + next = 4; + ret = p11_rpc_buffer_get_uint16 (&buf, &next, &val); + assert_num_eq (true, ret); + assert_num_eq (6, next); + assert_num_eq (0x6789, val); +} + +static void +test_uint32 (void) +{ + p11_buffer buffer; + uint32_t val = 0xFFFFFFFF; + size_t next; + bool ret; + + p11_buffer_init (&buffer, 0); + + next = 0; + ret = p11_rpc_buffer_get_uint32 (&buffer, &next, &val); + assert_num_eq (false, ret); + assert_num_eq (0, next); + assert_num_eq (0xFFFFFFFF, val); + + p11_buffer_reset (&buffer, 0); + + ret = p11_rpc_buffer_set_uint32 (&buffer, 0, 0x12345678); + assert_num_eq (false, ret); + + p11_buffer_reset (&buffer, 0); + + p11_buffer_add (&buffer, (unsigned char *)"padding", 7); + + p11_rpc_buffer_add_uint32 (&buffer, 0x12345678); + assert_num_eq (11, buffer.len); + assert (!p11_buffer_failed (&buffer)); + + next = 7; + ret = p11_rpc_buffer_get_uint32 (&buffer, &next, &val); + assert_num_eq (true, ret); + assert_num_eq (11, next); + assert_num_eq (0x12345678, val); + + p11_buffer_uninit (&buffer); +} + +static void +test_uint32_static (void) +{ + p11_buffer buf = { (unsigned char *)"pad0\x23\x45\x67\x89", 8, }; + uint32_t val = 0xFFFFFFFF; + size_t next; + bool ret; + + next = 4; + ret = p11_rpc_buffer_get_uint32 (&buf, &next, &val); + assert_num_eq (true, ret); + assert_num_eq (8, next); + assert_num_eq (0x23456789, val); +} + +static void +test_uint64 (void) +{ + p11_buffer buffer; + uint64_t val = 0xFFFFFFFFFFFFFFFF; + size_t next; + bool ret; + + p11_buffer_init (&buffer, 0); + + next = 0; + ret = p11_rpc_buffer_get_uint64 (&buffer, &next, &val); + assert_num_eq (0, ret); + assert_num_eq (0, next); + assert (0xFFFFFFFFFFFFFFFF == val); + + p11_buffer_reset (&buffer, 0); + + p11_buffer_add (&buffer, (unsigned char *)"padding", 7); + + p11_rpc_buffer_add_uint64 (&buffer, 0x0123456708ABCDEF); + assert_num_eq (15, buffer.len); + assert (!p11_buffer_failed (&buffer)); + + next = 7; + ret = p11_rpc_buffer_get_uint64 (&buffer, &next, &val); + assert_num_eq (true, ret); + assert_num_eq (15, next); + assert (0x0123456708ABCDEF == val); + + p11_buffer_uninit (&buffer); +} + +static void +test_uint64_static (void) +{ + p11_buffer buf = { (unsigned char *)"pad0\x89\x67\x45\x23\x11\x22\x33\x44", 12, }; + uint64_t val = 0xFFFFFFFFFFFFFFFF; + size_t next; + bool ret; + + next = 4; + ret = p11_rpc_buffer_get_uint64 (&buf, &next, &val); + assert_num_eq (true, ret); + assert_num_eq (12, next); + assert (0x8967452311223344 == val); +} + +static void +test_byte_array (void) +{ + p11_buffer buffer; + unsigned char bytes[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F }; + + const unsigned char *val; + size_t length = ~0; + size_t next; + bool ret; + + p11_buffer_init (&buffer, 0); + + /* Invalid read */ + + next = 0; + ret = p11_rpc_buffer_get_byte_array (&buffer, &next, &val, &length); + assert_num_eq (false, ret); + assert_num_eq (0, next); + assert_num_eq (~0, length); + + /* Test full array */ + + p11_buffer_reset (&buffer, 0); + p11_buffer_add (&buffer, (unsigned char *)"padding", 7); + + p11_rpc_buffer_add_byte_array (&buffer, bytes, 32); + assert_num_eq (43, buffer.len); + assert (!p11_buffer_failed (&buffer)); + + next = 7; + ret = p11_rpc_buffer_get_byte_array (&buffer, &next, &val, &length); + assert_num_eq (true, ret); + assert_num_eq (43, next); + assert_num_eq (32, length); + assert (memcmp (val, bytes, 32) == 0); + + p11_buffer_uninit (&buffer); +} + +static void +test_byte_array_null (void) +{ + p11_buffer buffer; + const unsigned char *val; + size_t length = ~0; + size_t next; + bool ret; + + p11_buffer_init (&buffer, 0); + + p11_buffer_reset (&buffer, 0); + p11_buffer_add (&buffer, (unsigned char *)"padding", 7); + + p11_rpc_buffer_add_byte_array (&buffer, NULL, 0); + assert_num_eq (11, buffer.len); + assert (!p11_buffer_failed (&buffer)); + + next = 7; + ret = p11_rpc_buffer_get_byte_array (&buffer, &next, &val, &length); + assert_num_eq (true, ret); + assert_num_eq (11, next); + assert_num_eq (0, length); + assert_ptr_eq (NULL, (void*)val); + + p11_buffer_uninit (&buffer); +} + +static void +test_byte_array_too_long (void) +{ + p11_buffer buffer; + const unsigned char *val = NULL; + size_t length = ~0; + size_t next; + bool ret; + + p11_buffer_init (&buffer, 0); + + p11_buffer_reset (&buffer, 0); + p11_buffer_add (&buffer, (unsigned char *)"padding", 7); + assert (!p11_buffer_failed (&buffer)); + + /* Passing a too short buffer here shouldn't matter, as length is checked for sanity */ + p11_rpc_buffer_add_byte_array (&buffer, (unsigned char *)"", 0x9fffffff); + assert (p11_buffer_failed (&buffer)); + + /* Force write a too long byte arary to buffer */ + p11_buffer_reset (&buffer, 0); + p11_rpc_buffer_add_uint32 (&buffer, 0x9fffffff); + + next = 0; + ret = p11_rpc_buffer_get_byte_array (&buffer, &next, &val, &length); + assert_num_eq (false, ret); + assert_num_eq (0, next); + assert_num_eq (~0, length); + assert_ptr_eq (NULL, (void*)val); + + p11_buffer_uninit (&buffer); +} + +static void +test_byte_array_static (void) +{ + unsigned char data[] = { 'p', 'a', 'd', 0x00, 0x00, 0x00, 0x00, 0x20, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F }; + p11_buffer buf = { data, 0x40, }; + const unsigned char *val; + size_t length = ~0; + size_t next; + bool ret; + + next = 4; + ret = p11_rpc_buffer_get_byte_array (&buf, &next, &val, &length); + assert_num_eq (true, ret); + assert_num_eq (40, next); + assert_num_eq (32, length); + assert (memcmp (data + 8, val, 32) == 0); +} + +static p11_virtual base; +static bool rpc_initialized = false; + +static CK_RV +rpc_initialize (p11_rpc_client_vtable *vtable, + void *init_reserved) +{ + assert_str_eq (vtable->data, "vtable-data"); + assert_num_eq (false, rpc_initialized); + rpc_initialized = true; + + return CKR_OK; +} + +static CK_RV +rpc_initialize_fails (p11_rpc_client_vtable *vtable, + void *init_reserved) +{ + assert_str_eq (vtable->data, "vtable-data"); + assert_num_eq (false, rpc_initialized); + return CKR_FUNCTION_FAILED; +} + +static CK_RV +rpc_initialize_device_removed (p11_rpc_client_vtable *vtable, + void *init_reserved) +{ + assert_str_eq (vtable->data, "vtable-data"); + assert_num_eq (false, rpc_initialized); + return CKR_DEVICE_REMOVED; +} + +static CK_RV +rpc_transport (p11_rpc_client_vtable *vtable, + p11_buffer *request, + p11_buffer *response) +{ + bool ret; + + assert_str_eq (vtable->data, "vtable-data"); + + /* Just pass directly to the server code */ + ret = p11_rpc_server_handle (&base.funcs, request, response); + assert (ret == true); + + return CKR_OK; +} + +static void +rpc_finalize (p11_rpc_client_vtable *vtable, + void *fini_reserved) +{ + assert_str_eq (vtable->data, "vtable-data"); + assert_num_eq (true, rpc_initialized); + rpc_initialized = false; +} + +static void +test_initialize (void) +{ + p11_rpc_client_vtable vtable = { "vtable-data", rpc_initialize, rpc_transport, rpc_finalize }; + p11_virtual mixin; + bool ret; + CK_RV rv; + + /* Build up our own function list */ + rpc_initialized = false; + p11_virtual_init (&base, &p11_virtual_base, &mock_module_no_slots, NULL); + + ret = p11_rpc_client_init (&mixin, &vtable); + assert_num_eq (true, ret); + + rv = mixin.funcs.C_Initialize (&mixin.funcs, NULL); + assert (rv == CKR_OK); + assert_num_eq (true, rpc_initialized); + + rv = mixin.funcs.C_Finalize (&mixin.funcs, NULL); + assert (rv == CKR_OK); + assert_num_eq (false, rpc_initialized); + + p11_virtual_uninit (&mixin); +} + +static void +test_not_initialized (void) +{ + p11_rpc_client_vtable vtable = { "vtable-data", rpc_initialize, rpc_transport, rpc_finalize }; + p11_virtual mixin; + CK_INFO info; + bool ret; + CK_RV rv; + + /* Build up our own function list */ + rpc_initialized = false; + p11_virtual_init (&base, &p11_virtual_base, &mock_module_no_slots, NULL); + + ret = p11_rpc_client_init (&mixin, &vtable); + assert_num_eq (true, ret); + + rv = (mixin.funcs.C_GetInfo) (&mixin.funcs, &info); + assert (rv == CKR_CRYPTOKI_NOT_INITIALIZED); + + p11_virtual_uninit (&mixin); +} + +static void +test_initialize_fails_on_client (void) +{ + p11_rpc_client_vtable vtable = { "vtable-data", rpc_initialize_fails, rpc_transport, rpc_finalize }; + p11_virtual mixin; + bool ret; + CK_RV rv; + + /* Build up our own function list */ + rpc_initialized = false; + p11_virtual_init (&base, &p11_virtual_base, &mock_module_no_slots, NULL); + + ret = p11_rpc_client_init (&mixin, &vtable); + assert_num_eq (true, ret); + + rv = (mixin.funcs.C_Initialize) (&mixin.funcs, NULL); + assert (rv == CKR_FUNCTION_FAILED); + assert_num_eq (false, rpc_initialized); + + p11_virtual_uninit (&mixin); +} + +static CK_RV +rpc_transport_fails (p11_rpc_client_vtable *vtable, + p11_buffer *request, + p11_buffer *response) +{ + return CKR_FUNCTION_REJECTED; +} + +static void +test_transport_fails (void) +{ + p11_rpc_client_vtable vtable = { "vtable-data", rpc_initialize, rpc_transport_fails, rpc_finalize }; + p11_virtual mixin; + bool ret; + CK_RV rv; + + /* Build up our own function list */ + rpc_initialized = false; + p11_virtual_init (&base, &p11_virtual_base, &mock_module_no_slots, NULL); + + ret = p11_rpc_client_init (&mixin, &vtable); + assert_num_eq (true, ret); + + rv = (mixin.funcs.C_Initialize) (&mixin.funcs, NULL); + assert (rv == CKR_FUNCTION_REJECTED); + assert_num_eq (false, rpc_initialized); + + p11_virtual_uninit (&mixin); +} + +static void +test_initialize_fails_on_server (void) +{ + p11_rpc_client_vtable vtable = { "vtable-data", rpc_initialize, rpc_transport, rpc_finalize }; + p11_virtual mixin; + bool ret; + CK_RV rv; + + /* Build up our own function list */ + p11_virtual_init (&base, &p11_virtual_base, &mock_module_no_slots, NULL); + base.funcs.C_Initialize = mock_X_Initialize__fails; + + ret = p11_rpc_client_init (&mixin, &vtable); + assert_num_eq (true, ret); + + rv = (mixin.funcs.C_Initialize) (&mixin.funcs, NULL); + assert (rv == CKR_FUNCTION_FAILED); + assert_num_eq (false, rpc_initialized); + + p11_virtual_uninit (&mixin); +} + +static CK_RV +rpc_transport_bad_parse (p11_rpc_client_vtable *vtable, + p11_buffer *request, + p11_buffer *response) +{ + int rc; + + assert_str_eq (vtable->data, "vtable-data"); + + /* Just zero bytes is an invalid message */ + rc = p11_buffer_reset (response, 2); + assert (rc >= 0); + + memset (response->data, 0, 2); + response->len = 2; + return CKR_OK; +} + +static void +test_transport_bad_parse (void) +{ + p11_rpc_client_vtable vtable = { "vtable-data", rpc_initialize, rpc_transport_bad_parse, rpc_finalize }; + p11_virtual mixin; + bool ret; + CK_RV rv; + + /* Build up our own function list */ + rpc_initialized = false; + p11_virtual_init (&base, &p11_virtual_base, &mock_module_no_slots, NULL); + + ret = p11_rpc_client_init (&mixin, &vtable); + assert_num_eq (true, ret); + + p11_kit_be_quiet (); + + rv = (mixin.funcs.C_Initialize) (&mixin.funcs, NULL); + assert (rv == CKR_DEVICE_ERROR); + assert_num_eq (0, rpc_initialized); + + p11_message_loud (); + p11_virtual_uninit (&mixin); +} + +static CK_RV +rpc_transport_short_error (p11_rpc_client_vtable *vtable, + p11_buffer *request, + p11_buffer *response) +{ + int rc; + + unsigned char data[] = { + 0x00, 0x00, 0x00, 0x00, /* RPC_CALL_ERROR */ + 0x00, 0x00, 0x00, 0x01, 0x75, /* signature 'u' */ + 0x00, 0x01, /* short error */ + }; + + assert_str_eq (vtable->data, "vtable-data"); + + rc = p11_buffer_reset (response, sizeof (data)); + assert (rc >= 0); + + memcpy (response->data, data, sizeof (data)); + response->len = sizeof (data); + return CKR_OK; +} + +static void +test_transport_short_error (void) +{ + p11_rpc_client_vtable vtable = { "vtable-data", rpc_initialize, rpc_transport_short_error, rpc_finalize }; + p11_virtual mixin; + bool ret; + CK_RV rv; + + /* Build up our own function list */ + p11_virtual_init (&base, &p11_virtual_base, &mock_module_no_slots, NULL); + + ret = p11_rpc_client_init (&mixin, &vtable); + assert_num_eq (true, ret); + + p11_kit_be_quiet (); + + rv = (mixin.funcs.C_Initialize) (&mixin.funcs, NULL); + assert (rv == CKR_DEVICE_ERROR); + assert_num_eq (0, rpc_initialized); + + p11_message_loud (); + p11_virtual_uninit (&mixin); +} + +static CK_RV +rpc_transport_invalid_error (p11_rpc_client_vtable *vtable, + p11_buffer *request, + p11_buffer *response) +{ + int rc; + + unsigned char data[] = { + 0x00, 0x00, 0x00, 0x00, /* RPC_CALL_ERROR */ + 0x00, 0x00, 0x00, 0x01, 0x75, /* signature 'u' */ + 0x00, 0x00, 0x00, 0x00, /* a CKR_OK error*/ + 0x00, 0x00, 0x00, 0x00, + }; + + assert_str_eq (vtable->data, "vtable-data"); + + rc = p11_buffer_reset (response, sizeof (data)); + assert (rc >= 0); + memcpy (response->data, data, sizeof (data)); + response->len = sizeof (data); + return CKR_OK; +} + +static void +test_transport_invalid_error (void) +{ + p11_rpc_client_vtable vtable = { "vtable-data", rpc_initialize, rpc_transport_invalid_error, rpc_finalize }; + p11_virtual mixin; + bool ret; + CK_RV rv; + + /* Build up our own function list */ + p11_virtual_init (&base, &p11_virtual_base, &mock_module_no_slots, NULL); + + ret = p11_rpc_client_init (&mixin, &vtable); + assert_num_eq (true, ret); + + p11_kit_be_quiet (); + + rv = (mixin.funcs.C_Initialize) (&mixin.funcs, NULL); + assert (rv == CKR_DEVICE_ERROR); + assert_num_eq (0, rpc_initialized); + + p11_message_loud (); + p11_virtual_uninit (&mixin); +} + +static CK_RV +rpc_transport_wrong_response (p11_rpc_client_vtable *vtable, + p11_buffer *request, + p11_buffer *response) +{ + int rc; + + unsigned char data[] = { + 0x00, 0x00, 0x00, 0x02, /* RPC_CALL_C_Finalize */ + 0x00, 0x00, 0x00, 0x00, /* signature '' */ + }; + + assert_str_eq (vtable->data, "vtable-data"); + + rc = p11_buffer_reset (response, sizeof (data)); + assert (rc >= 0); + memcpy (response->data, data, sizeof (data)); + response->len = sizeof (data); + return CKR_OK; +} + +static void +test_transport_wrong_response (void) +{ + p11_rpc_client_vtable vtable = { "vtable-data", rpc_initialize, rpc_transport_wrong_response, rpc_finalize }; + p11_virtual mixin; + bool ret; + CK_RV rv; + + /* Build up our own function list */ + p11_virtual_init (&base, &p11_virtual_base, &mock_module_no_slots, NULL); + + ret = p11_rpc_client_init (&mixin, &vtable); + assert_num_eq (true, ret); + + p11_kit_be_quiet (); + + rv = (mixin.funcs.C_Initialize) (&mixin.funcs, NULL); + assert (rv == CKR_DEVICE_ERROR); + assert_num_eq (0, rpc_initialized); + + p11_message_loud (); + p11_virtual_uninit (&mixin); +} + +static CK_RV +rpc_transport_bad_contents (p11_rpc_client_vtable *vtable, + p11_buffer *request, + p11_buffer *response) +{ + int rc; + + unsigned char data[] = { + 0x00, 0x00, 0x00, 0x02, /* RPC_CALL_C_GetInfo */ + 0x00, 0x00, 0x00, 0x05, /* signature 'vsusv' */ + 'v', 's', 'u', 's', 'v', + 0x00, 0x00, 0x00, 0x00, /* invalid data */ + }; + + assert_str_eq (vtable->data, "vtable-data"); + + rc = p11_buffer_reset (response, sizeof (data)); + assert (rc >= 0); + memcpy (response->data, data, sizeof (data)); + response->len = sizeof (data); + return CKR_OK; +} + +static void +test_transport_bad_contents (void) +{ + p11_rpc_client_vtable vtable = { "vtable-data", rpc_initialize, rpc_transport_bad_contents, rpc_finalize }; + p11_virtual mixin; + bool ret; + CK_RV rv; + + /* Build up our own function list */ + p11_virtual_init (&base, &p11_virtual_base, &mock_module_no_slots, NULL); + + ret = p11_rpc_client_init (&mixin, &vtable); + assert_num_eq (true, ret); + + p11_kit_be_quiet (); + + rv = (mixin.funcs.C_Initialize) (&mixin.funcs, NULL); + assert (rv == CKR_DEVICE_ERROR); + assert_num_eq (0, rpc_initialized); + + p11_message_loud (); + p11_virtual_uninit (&mixin); +} + +static p11_rpc_client_vtable test_normal_vtable = { + NULL, + rpc_initialize, + rpc_transport, + rpc_finalize, +}; + +static p11_rpc_client_vtable test_device_removed_vtable = { + NULL, + rpc_initialize_device_removed, + rpc_transport, + rpc_finalize, +}; + +static void +mixin_free (void *data) +{ + p11_virtual *mixin = data; + p11_virtual_uninit (mixin); + free (mixin); +} + +static CK_FUNCTION_LIST_PTR +setup_test_rpc_module (p11_rpc_client_vtable *vtable, + CK_FUNCTION_LIST *module_template, + CK_SESSION_HANDLE *session) +{ + CK_FUNCTION_LIST *rpc_module; + p11_virtual *mixin; + CK_RV rv; + + /* Build up our own function list */ + p11_virtual_init (&base, &p11_virtual_base, module_template, NULL); + + mixin = calloc (1, sizeof (p11_virtual)); + assert (mixin != NULL); + + vtable->data = "vtable-data"; + if (!p11_rpc_client_init (mixin, vtable)) + assert_not_reached (); + + rpc_module = p11_virtual_wrap (mixin, mixin_free); + assert_ptr_not_null (rpc_module); + + rv = p11_kit_module_initialize (rpc_module); + assert (rv == CKR_OK); + + if (session) { + rv = (rpc_module->C_OpenSession) (MOCK_SLOT_ONE_ID, CKF_RW_SESSION | CKF_SERIAL_SESSION, + NULL, NULL, session); + assert (rv == CKR_OK); + } + + return rpc_module; +} + +static CK_FUNCTION_LIST * +setup_mock_module (CK_SESSION_HANDLE *session) +{ + return setup_test_rpc_module (&test_normal_vtable, &mock_module, session); +} + +static void +teardown_mock_module (CK_FUNCTION_LIST *rpc_module) +{ + p11_kit_module_finalize (rpc_module); + p11_virtual_unwrap (rpc_module); +} + +static void +test_get_info_stand_in (void) +{ + CK_FUNCTION_LIST_PTR rpc_module; + CK_INFO info; + CK_RV rv; + char *string; + + rpc_module = setup_test_rpc_module (&test_device_removed_vtable, + &mock_module_no_slots, NULL); + + rv = (rpc_module->C_GetInfo) (&info); + assert (rv == CKR_OK); + + assert_num_eq (CRYPTOKI_VERSION_MAJOR, info.cryptokiVersion.major); + assert_num_eq (CRYPTOKI_VERSION_MINOR, info.cryptokiVersion.minor); + string = p11_kit_space_strdup (info.manufacturerID, sizeof (info.manufacturerID)); + assert_str_eq ("p11-kit", string); + free (string); + string = p11_kit_space_strdup (info.libraryDescription, sizeof (info.libraryDescription)); + assert_str_eq ("p11-kit (no connection)", string); + free (string); + assert_num_eq (0, info.flags); + assert_num_eq (1, info.libraryVersion.major); + assert_num_eq (1, info.libraryVersion.minor); + + teardown_mock_module (rpc_module); +} + +static void +test_get_slot_list_no_device (void) +{ + CK_FUNCTION_LIST_PTR rpc_module; + CK_SLOT_ID slot_list[8]; + CK_ULONG count; + CK_RV rv; + + rpc_module = setup_test_rpc_module (&test_device_removed_vtable, + &mock_module_no_slots, NULL); + + rv = (rpc_module->C_GetSlotList) (CK_TRUE, NULL, &count); + assert (rv == CKR_OK); + assert_num_eq (0, count); + rv = (rpc_module->C_GetSlotList) (CK_FALSE, NULL, &count); + assert (rv == CKR_OK); + assert_num_eq (0, count); + + count = 8; + rv = (rpc_module->C_GetSlotList) (CK_TRUE, slot_list, &count); + assert (rv == CKR_OK); + assert_num_eq (0, count); + + count = 8; + rv = (rpc_module->C_GetSlotList) (CK_FALSE, slot_list, &count); + assert (rv == CKR_OK); + assert_num_eq (0, count); + + teardown_mock_module (rpc_module); +} + +#include "test-mock.c" + +int +main (int argc, + char *argv[]) +{ + CK_MECHANISM_TYPE mechanisms[] = { + CKM_MOCK_CAPITALIZE, + CKM_MOCK_PREFIX, + CKM_MOCK_GENERATE, + CKM_MOCK_WRAP, + CKM_MOCK_DERIVE, + CKM_MOCK_COUNT, + 0, + }; + + mock_module_init (); + p11_library_init (); + + /* Override the mechanisms that the RPC mechanism will handle */ + p11_rpc_mechanisms_override_supported = mechanisms; + + p11_test (test_new_free, "/rpc/new-free"); + p11_test (test_uint16, "/rpc/uint16"); + p11_test (test_uint16_static, "/rpc/uint16-static"); + p11_test (test_uint32, "/rpc/uint32"); + p11_test (test_uint32_static, "/rpc/uint32-static"); + p11_test (test_uint64, "/rpc/uint64"); + p11_test (test_uint64_static, "/rpc/uint64-static"); + p11_test (test_byte_array, "/rpc/byte-array"); + p11_test (test_byte_array_null, "/rpc/byte-array-null"); + p11_test (test_byte_array_too_long, "/rpc/byte-array-too-long"); + p11_test (test_byte_array_static, "/rpc/byte-array-static"); + + p11_test (test_initialize_fails_on_client, "/rpc/initialize-fails-on-client"); + p11_test (test_initialize_fails_on_server, "/rpc/initialize-fails-on-server"); + p11_test (test_initialize, "/rpc/initialize"); + p11_test (test_not_initialized, "/rpc/not-initialized"); + p11_test (test_transport_fails, "/rpc/transport-fails"); + p11_test (test_transport_bad_parse, "/rpc/transport-bad-parse"); + p11_test (test_transport_short_error, "/rpc/transport-short-error"); + p11_test (test_transport_invalid_error, "/rpc/transport-invalid-error"); + p11_test (test_transport_wrong_response, "/rpc/transport-wrong-response"); + p11_test (test_transport_bad_contents, "/rpc/transport-bad-contents"); + p11_test (test_get_info_stand_in, "/rpc/get-info-stand-in"); + p11_test (test_get_slot_list_no_device, "/rpc/get-slot-list-no-device"); + + test_mock_add_tests ("/rpc"); + + return p11_test_run (argc, argv); +} |