diff --git a/p11-kit/rpc-client.c b/p11-kit/rpc-client.c index 93e8c7ad..fb39103e 100644 --- a/p11-kit/rpc-client.c +++ b/p11-kit/rpc-client.c @@ -430,9 +430,13 @@ proto_write_mechanism (p11_rpc_message *msg, /* Make sure this is in the right order */ assert (!msg->signature || p11_rpc_message_verify_part (msg, "M")); - /* This case is valid for C_*Init () functions to cancel operation */ + /* + * The NULL mechanism is used for C_*Init () functions to + * cancel operation. We use a special value 0xffffffff as a + * marker to indicate that. + */ if (mech == NULL) { - p11_rpc_buffer_add_uint32 (msg->output, 0); + p11_rpc_buffer_add_uint32 (msg->output, 0xffffffff); return p11_buffer_failed (msg->output) ? CKR_HOST_MEMORY : CKR_OK; } diff --git a/p11-kit/rpc-message.c b/p11-kit/rpc-message.c index cf6095ca..09d7f33d 100644 --- a/p11-kit/rpc-message.c +++ b/p11-kit/rpc-message.c @@ -2114,8 +2114,14 @@ p11_rpc_buffer_get_mechanism (p11_buffer *buffer, mech->mechanism = mechanism; - /* special NULL case */ - if (mechanism == 0) { + /* + * The NULL mechanism is used for C_*Init () functions to + * cancel operation. We use a special value 0xffffffff as a + * marker to indicate that. + */ + if (mechanism == 0xffffffff) { + mech->ulParameterLen = 0; + mech->pParameter = NULL; return true; } diff --git a/p11-kit/rpc-server.c b/p11-kit/rpc-server.c index 87bd5744..b4cbcd09 100644 --- a/p11-kit/rpc-server.c +++ b/p11-kit/rpc-server.c @@ -480,8 +480,14 @@ proto_read_mechanism (p11_rpc_message *msg, return PARSE_ERROR; } - if (temp.mechanism == 0) { + /* + * The NULL mechanism is used for C_*Init () functions to + * cancel operation. We use a special value 0xffffffff as a + * marker to indicate that. + */ + if (temp.mechanism == 0xffffffff) { *mech = NULL; + msg->parsed = offset; return CKR_OK; } diff --git a/p11-kit/test-rpc.c b/p11-kit/test-rpc.c index 130d50ee..f2145092 100644 --- a/p11-kit/test-rpc.c +++ b/p11-kit/test-rpc.c @@ -675,6 +675,31 @@ test_simultaneous_functions (void *module) p11_mutex_uninit (&delay_mutex); } +static void +test_mechanism_unsupported (void *module) +{ + CK_FUNCTION_LIST_PTR rpc_module; + CK_SESSION_HANDLE session; + CK_MECHANISM mech; + CK_RV rv; + + rpc_module = setup_test_rpc_module (&test_normal_vtable, + module, &session); + + memset (&mech, 0, sizeof(mech)); + + /* + * This mechanism is not supported by the remote mock module, + * but it should be able to return an error through RPC. + */ + mech.mechanism = CKM_RSA_PKCS_KEY_PAIR_GEN; + + rv = (rpc_module->C_DigestInit) (session, &mech); + assert_num_eq (rv, CKR_MECHANISM_INVALID); + + teardown_mock_module (rpc_module); +} + #ifdef OS_UNIX static void @@ -759,6 +784,7 @@ main (int argc, p11_testx (test_get_info_stand_in, &mock_module_no_slots, "/rpc/get-info-stand-in"); p11_testx (test_get_slot_list_no_device, &mock_module_no_slots, "/rpc/get-slot-list-no-device"); p11_testx (test_simultaneous_functions, &mock_module_no_slots, "/rpc/simultaneous-functions"); + p11_testx (test_mechanism_unsupported, &mock_module, "/rpc/mechanism-unsupported"); #ifdef OS_UNIX p11_testx (test_fork_and_reinitialize, &mock_module_no_slots, "/rpc/fork-and-reinitialize"); @@ -778,6 +804,7 @@ main (int argc, p11_testx (test_get_info_stand_in, &mock_module_v3_no_slots, "/rpc3/get-info-stand-in"); p11_testx (test_get_slot_list_no_device, &mock_module_v3_no_slots, "/rpc3/get-slot-list-no-device"); p11_testx (test_simultaneous_functions, &mock_module_v3_no_slots, "/rpc3/simultaneous-functions"); + p11_testx (test_mechanism_unsupported, &mock_module_v3, "/rpc3/mechanism-unsupported"); #ifdef OS_UNIX p11_testx (test_fork_and_reinitialize, &mock_module_v3_no_slots, "/rpc3/fork-and-reinitialize");