Skip to content

Commit

Permalink
client: Support PKCS#11 3.0
Browse files Browse the repository at this point in the history
This exports C_GetInterfaceList and C_GetInterface from the client
module.

Signed-off-by: Daiki Ueno <[email protected]>
  • Loading branch information
ueno committed Apr 11, 2023
1 parent e3975ef commit 3e3c79b
Showing 1 changed file with 151 additions and 32 deletions.
183 changes: 151 additions & 32 deletions p11-kit/client.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
typedef struct _State {
p11_virtual virt;
p11_rpc_transport *rpc;
CK_FUNCTION_LIST_3_0 *wrapped;
CK_INTERFACE wrapped;
struct _State *next;
} State;

Expand Down Expand Up @@ -97,57 +97,176 @@ get_server_address (char **addressp)
return CKR_OK;
}

static const char p11_interface_name[] = "PKCS 11";

static const CK_VERSION version_two = {
CRYPTOKI_LEGACY_VERSION_MAJOR,
CRYPTOKI_LEGACY_VERSION_MINOR
};

static const CK_VERSION version_three = {
CRYPTOKI_VERSION_MAJOR,
CRYPTOKI_VERSION_MINOR
};

/* We are not going to support any special interfaces */
#define NUM_INTERFACES 2

static CK_RV
get_interface_inlock(CK_INTERFACE **interface, const CK_VERSION *version, CK_FLAGS flags)
{
char *address = NULL;
State *state = NULL;
CK_FUNCTION_LIST_PTR module = NULL;
CK_RV rv;

return_val_if_fail (interface, CKR_ARGUMENTS_BAD);
return_val_if_fail (version, CKR_ARGUMENTS_BAD);

if (memcmp (version, &version_three, sizeof(*version)) != 0 &&
memcmp (version, &version_two, sizeof(*version)) != 0)
return CKR_ARGUMENTS_BAD;

rv = get_server_address (&address);
if (rv != CKR_OK)
goto cleanup;

state = calloc (1, sizeof (State));
if (!state) {
rv = CKR_HOST_MEMORY;
goto cleanup;
}

state->rpc = p11_rpc_transport_new (&state->virt, address, "client");
if (!state->rpc) {
rv = CKR_GENERAL_ERROR;
goto cleanup;
}

module = p11_virtual_wrap (&state->virt,
(p11_destroyer)p11_virtual_uninit);
if (!module) {
rv = CKR_GENERAL_ERROR;
goto cleanup;
}

module->version = *version;

state->wrapped.pInterfaceName = (char *)p11_interface_name;

state->wrapped.pFunctionList = (CK_FUNCTION_LIST_3_0 *)module;
module = NULL;

state->wrapped.flags = flags;

*interface = &state->wrapped;

state->next = all_instances;
all_instances = state;
state = NULL;

cleanup:
if (module)
p11_virtual_unwrap (module);
if (state) {
p11_virtual_unwrap (state->wrapped.pFunctionList);
p11_rpc_transport_free (state->rpc);
free (state);
}
free (address);
return rv;
}

#ifdef OS_WIN32
__declspec(dllexport)
#endif
CK_RV
C_GetFunctionList (CK_FUNCTION_LIST_PTR_PTR list)
{
char *address = NULL;
State *state;
CK_FUNCTION_LIST_PTR module = NULL;
CK_RV rv = CKR_OK;
CK_INTERFACE *res = NULL;

p11_library_init_once ();
p11_lock ();

rv = get_server_address (&address);
rv = get_interface_inlock (&res, &version_two, 0);
if (rv == CKR_OK)
*list = res->pFunctionList;

p11_unlock ();

if (rv == CKR_OK) {
state = calloc (1, sizeof (State));
if (!state)
rv = CKR_HOST_MEMORY;
return rv;
}

#ifdef OS_WIN32
__declspec(dllexport)
#endif
CK_RV
C_GetInterfaceList (CK_INTERFACE_PTR pInterfacesList, CK_ULONG_PTR pulCount)
{
CK_RV rv = CKR_OK;
CK_INTERFACE *interfaces[NUM_INTERFACES];
CK_ULONG count = 0;
CK_ULONG i;

if (pulCount == NULL_PTR)
return CKR_ARGUMENTS_BAD;

if (pInterfacesList == NULL_PTR) {
*pulCount = NUM_INTERFACES;
return CKR_OK;
}

if (rv == CKR_OK) {
state->rpc = p11_rpc_transport_new (&state->virt,
address,
"client");
if (!state->rpc) {
free (state);
rv = CKR_GENERAL_ERROR;
}
if (*pulCount < NUM_INTERFACES) {
*pulCount = NUM_INTERFACES;
return CKR_BUFFER_TOO_SMALL;
}

if (rv == CKR_OK) {
module = p11_virtual_wrap (&state->virt, (p11_destroyer)p11_virtual_uninit);
if (!module) {
p11_rpc_transport_free (state->rpc);
free (state);
rv = CKR_GENERAL_ERROR;
}
p11_library_init_once ();
p11_lock ();

rv = get_interface_inlock (&interfaces[count++], &version_three, 0);
if (rv != CKR_OK)
goto cleanup;

rv = get_interface_inlock (&interfaces[count++], &version_two, 0);
if (rv != CKR_OK)
goto cleanup;

for (i = 0; i < count; i++)
pInterfacesList[i] = *interfaces[i];
*pulCount = count;

cleanup:
p11_unlock ();

return rv;
}

#ifdef OS_WIN32
__declspec(dllexport)
#endif
CK_RV
C_GetInterface (CK_UTF8CHAR_PTR pInterfaceName, CK_VERSION_PTR pVersion,
CK_INTERFACE_PTR_PTR ppInterface, CK_FLAGS flags)
{
int rv;

if (ppInterface == NULL) {
return CKR_ARGUMENTS_BAD;
}

if (rv == CKR_OK) {
*list = module;
state->wrapped = (CK_FUNCTION_LIST_3_0 *)module;
state->next = all_instances;
all_instances = state;
if (pInterfaceName &&
strcmp ((const char *)pInterfaceName, p11_interface_name) != 0) {
return CKR_ARGUMENTS_BAD;
}

p11_unlock ();
p11_library_init_once ();
p11_lock ();

free (address);
rv = get_interface_inlock (ppInterface, pVersion, flags);

p11_unlock ();

return rv;
}
Expand All @@ -163,7 +282,7 @@ p11_client_module_cleanup (void)
for (; state != NULL; state = next) {
next = state->next;
p11_rpc_transport_free (state->rpc);
p11_virtual_unwrap ((CK_FUNCTION_LIST *)state->wrapped);
p11_virtual_unwrap (state->wrapped.pFunctionList);
free (state);
}
}

0 comments on commit 3e3c79b

Please sign in to comment.