Skip to content

Commit

Permalink
Rework rpc_C_DeriveKey to allow size queries
Browse files Browse the repository at this point in the history
This adds support to the rpc_C_DeriveKey to send the mechanism parameter
back to the client after the actual call. This is necessary to allow
size queries for potential output fields in the parameter. In this case
the call itself will fail but instead of writing an error response the
client has to get the updated parameter. For this the server will send
the error code along with the parameter back to the client that then can
allocate space for the output fields in the parameter and do the call
again.
Since this will lead to a backwards compatability problem within the RPC
protocol the version is bumped.
  • Loading branch information
fcallies authored and ZoltanFridrich committed Feb 12, 2025
1 parent e2f514f commit 6449cfe
Show file tree
Hide file tree
Showing 6 changed files with 295 additions and 12 deletions.
2 changes: 1 addition & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ P11KIT_AGE=4
# ------------------------------------------------------------------------------
# p11-kit RPC protocol versions
P11KIT_RPC_MIN=0
P11KIT_RPC_MAX=1
P11KIT_RPC_MAX=2

# ------------------------------------------------------------------------------

Expand Down
2 changes: 1 addition & 1 deletion meson_options.txt
Original file line number Diff line number Diff line change
Expand Up @@ -83,5 +83,5 @@ option('rpc_min', type : 'integer',
description : 'Minimum RPC protocol version we support')

option('rpc_max', type : 'integer',
min : 0, max : 1, value : 1,
min : 0, max : 2, value : 2,
description : 'Maximum RPC protocol version we support')
124 changes: 117 additions & 7 deletions p11-kit/rpc-client.c
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,55 @@ proto_write_mechanism (p11_rpc_message *msg,
return p11_buffer_failed (msg->output) ? CKR_HOST_MEMORY : CKR_OK;
}

static CK_RV
proto_read_error (p11_rpc_message *msg, CK_RV *error)
{
if (!p11_rpc_message_read_ulong(msg, error))
return PARSE_ERROR;

return CKR_OK;
}

static CK_RV
proto_read_mech_param_update (p11_rpc_message *msg,
CK_MECHANISM_PTR *mech)
{
size_t offset;
CK_MECHANISM temp;

assert (msg != NULL);
assert (mech != NULL);
assert (msg->input != NULL);

/* Make sure this is in the right order */
assert (!msg->signature || p11_rpc_message_verify_part (msg, "P"));

/* Check the length needed to store the parameter */
memset (&temp, 0, sizeof (temp));
temp.mechanism = (*mech)->mechanism;
offset = msg->parsed;
if (!p11_rpc_buffer_get_mech_param_update (msg->input, &offset, &temp)) {
msg->parsed = offset;
return PARSE_ERROR;
}

/* The mechanism doesn't require parameter */
if (temp.ulParameterLen == 0) {
msg->parsed = offset;
return CKR_OK;
}

/* Actually retrieve the parameter */
if ((*mech)->ulParameterLen != temp.ulParameterLen)
return CKR_MECHANISM_PARAM_INVALID;
if (!p11_rpc_buffer_get_mech_param_update (msg->input, &msg->parsed, *mech))
return PARSE_ERROR;

assert (msg->parsed == offset);

return CKR_OK;
}

static CK_RV
proto_read_info (p11_rpc_message *msg,
CK_INFO_PTR info)
Expand Down Expand Up @@ -652,6 +701,16 @@ proto_read_sesssion_info (p11_rpc_message *msg,
if (_ret == CKR_OK && !p11_rpc_message_read_ulong (&_msg, val)) \
_ret = PARSE_ERROR;

#define OUT_MECH_PARAM_UPDATE(mech) \
if (_ret != CKR_OK) goto _cleanup; \
_ret = proto_read_mech_param_update (&_msg, &mech); \
if (_ret != CKR_OK) goto _cleanup;

#define OUT_ERROR(err) \
if (_ret != CKR_OK) goto _cleanup; \
_ret = proto_read_error (&_msg, &err);


#define OUT_BYTE_ARRAY(arr, len) \
if (len == NULL) \
_ret = CKR_ARGUMENTS_BAD; \
Expand Down Expand Up @@ -706,6 +765,17 @@ proto_read_sesssion_info (p11_rpc_message *msg,
if (_ret == CKR_OK) \
_ret = proto_read_mechanism_info (&_msg, info);

// EARLY_EXIT_ON_FAIL
#define PREP_EEOF \
CK_RV err;

#define PROCESS_CALL_NO_CHECK \
_ret = call_run (_mod, &_msg);

#define CHECK_EEOF \
if(err != CKR_OK) \
_ret = err;


/* -------------------------------------------------------------------
* INITIALIZATION and 'GLOBAL' CALLS
Expand Down Expand Up @@ -1874,13 +1944,13 @@ rpc_C_UnwrapKey (CK_X_FUNCTION_LIST *self,
}

static CK_RV
rpc_C_DeriveKey (CK_X_FUNCTION_LIST *self,
CK_SESSION_HANDLE session,
CK_MECHANISM_PTR mechanism,
CK_OBJECT_HANDLE base_key,
CK_ATTRIBUTE_PTR template,
CK_ULONG count,
CK_OBJECT_HANDLE_PTR key)
C_DeriveKey1 (CK_X_FUNCTION_LIST *self,
CK_SESSION_HANDLE session,
CK_MECHANISM_PTR mechanism,
CK_OBJECT_HANDLE base_key,
CK_ATTRIBUTE_PTR template,
CK_ULONG count,
CK_OBJECT_HANDLE_PTR key)
{
BEGIN_CALL_OR (C_DeriveKey, self, CKR_SESSION_HANDLE_INVALID);
IN_ULONG (session);
Expand All @@ -1892,6 +1962,46 @@ rpc_C_DeriveKey (CK_X_FUNCTION_LIST *self,
END_CALL;
}

static CK_RV
C_DeriveKey2 (CK_X_FUNCTION_LIST *self,
CK_SESSION_HANDLE session,
CK_MECHANISM_PTR mechanism,
CK_OBJECT_HANDLE base_key,
CK_ATTRIBUTE_PTR template,
CK_ULONG count,
CK_OBJECT_HANDLE_PTR key)
{
PREP_EEOF;
BEGIN_CALL_OR (C_DeriveKey2, self, CKR_SESSION_HANDLE_INVALID);
IN_ULONG (session);
IN_MECHANISM (mechanism);
IN_ULONG (base_key);
IN_ATTRIBUTE_ARRAY (template, count);
PROCESS_CALL_NO_CHECK;
OUT_ERROR (err);
OUT_MECH_PARAM_UPDATE (mechanism);
CHECK_EEOF;
OUT_ULONG (key);
END_CALL;
}

static CK_RV
rpc_C_DeriveKey (CK_X_FUNCTION_LIST *self,
CK_SESSION_HANDLE session,
CK_MECHANISM_PTR mechanism,
CK_OBJECT_HANDLE base_key,
CK_ATTRIBUTE_PTR template,
CK_ULONG count,
CK_OBJECT_HANDLE_PTR key)
{
uint8_t version = RPC_VERSION;

if (version <= 1)
return C_DeriveKey1 (self, session, mechanism, base_key, template, count, key);
else
return C_DeriveKey2 (self, session, mechanism, base_key, template, count, key);
}

static CK_RV
rpc_C_SeedRandom (CK_X_FUNCTION_LIST *self,
CK_SESSION_HANDLE session,
Expand Down
94 changes: 93 additions & 1 deletion p11-kit/rpc-message.c
Original file line number Diff line number Diff line change
Expand Up @@ -2007,6 +2007,9 @@ p11_rpc_buffer_get_dh_pkcs_derive_mechanism_value (p11_buffer *buffer,
return true;
}

static p11_rpc_mechanism_serializer p11_rpc_mech_param_update_serializers[] = {
};

static p11_rpc_mechanism_serializer p11_rpc_mechanism_serializers[] = {
{ CKM_IBM_ECDSA_OTHER, p11_rpc_buffer_add_ibm_ecdsa_other_mechanism_value, p11_rpc_buffer_get_ibm_ecdsa_other_mechanism_value },
{ CKM_RSA_PKCS_PSS, p11_rpc_buffer_add_rsa_pkcs_pss_mechanism_value, p11_rpc_buffer_get_rsa_pkcs_pss_mechanism_value },
Expand Down Expand Up @@ -2233,12 +2236,18 @@ p11_rpc_buffer_add_mechanism (p11_buffer *buffer, const CK_MECHANISM *mech)
p11_rpc_buffer_add_uint32 (buffer, mech->mechanism);

if (mechanism_has_no_parameters (mech->mechanism)) {
p11_rpc_buffer_add_byte_array (buffer, NULL, 0);
return;
}

assert (mechanism_has_sane_parameters (mech->mechanism));

if (mech->pParameter == NULL && mech->ulParameterLen == 0) {
p11_rpc_buffer_add_byte (buffer, 0);
return;
} else {
p11_rpc_buffer_add_byte (buffer, 1);
}

for (i = 0; i < ELEMS (p11_rpc_mechanism_serializers); i++) {
if (p11_rpc_mechanism_serializers[i].type == mech->mechanism) {
serializer = &p11_rpc_mechanism_serializers[i];
Expand All @@ -2260,6 +2269,7 @@ p11_rpc_buffer_get_mechanism (p11_buffer *buffer,
uint32_t mechanism;
p11_rpc_mechanism_serializer *serializer = NULL;
size_t i;
unsigned char has_param;

/* The mechanism type */
if (!p11_rpc_buffer_get_uint32 (buffer, offset, &mechanism))
Expand All @@ -2276,6 +2286,17 @@ p11_rpc_buffer_get_mechanism (p11_buffer *buffer,
mech->ulParameterLen = 0;
mech->pParameter = NULL;
return true;
} else if (mechanism_has_no_parameters (mech->mechanism)) {
return true;
}

if (!p11_rpc_buffer_get_byte(buffer, offset, &has_param))
return false;

if (has_param == 0) {
mech->ulParameterLen = 0;
mech->pParameter = NULL;
return true;
}

for (i = 0; i < ELEMS (p11_rpc_mechanism_serializers); i++) {
Expand All @@ -2294,3 +2315,74 @@ p11_rpc_buffer_get_mechanism (p11_buffer *buffer,

return true;
}

void
p11_rpc_buffer_add_mech_param_update (p11_buffer *buffer, const CK_MECHANISM *mech)
{
p11_rpc_mechanism_serializer *serializer = NULL;
size_t i;

if (mechanism_has_no_parameters (mech->mechanism)) {
return;
}

if (mech->pParameter == NULL && mech->ulParameterLen == 0) {
p11_rpc_buffer_add_byte (buffer, 0);
return;
} else {
p11_rpc_buffer_add_byte (buffer, 1);
}

for (i = 0; i < ELEMS (p11_rpc_mech_param_update_serializers); i++) {
if (p11_rpc_mech_param_update_serializers[i].type == mech->mechanism) {
serializer = &p11_rpc_mech_param_update_serializers[i];
break;
}
}

if (serializer == NULL)
return;

serializer->encode (buffer, mech->pParameter, mech->ulParameterLen);
}

bool
p11_rpc_buffer_get_mech_param_update (p11_buffer *buffer,
size_t *offset,
CK_MECHANISM *mech)
{
p11_rpc_mechanism_serializer *serializer = NULL;
size_t i;
unsigned char has_param;

if (mechanism_has_no_parameters (mech->mechanism)) {
mech->ulParameterLen = 0;
mech->pParameter = NULL;
return true;
}

if (!p11_rpc_buffer_get_byte(buffer, offset, &has_param))
return false;

if (has_param == 0) {
mech->ulParameterLen = 0;
mech->pParameter = NULL;
return true;
}

for (i = 0; i < ELEMS (p11_rpc_mech_param_update_serializers); i++) {
if (p11_rpc_mech_param_update_serializers[i].type == mech->mechanism) {
serializer = &p11_rpc_mech_param_update_serializers[i];
break;
}
}

if (serializer == NULL)
return true;

if (!serializer->decode (buffer, offset,
mech->pParameter, &mech->ulParameterLen))
return false;

return true;
}
10 changes: 10 additions & 0 deletions p11-kit/rpc-message.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ enum {
P11_RPC_CALL_C_MessageVerifyFinal,

P11_RPC_CALL_C_InitToken2,
P11_RPC_CALL_C_DeriveKey2,

P11_RPC_CALL_MAX
};
Expand All @@ -159,6 +160,7 @@ typedef struct {
* v = CK_VERSION
* y = CK_BYTE
* z = null terminated string
* P = mechanism parameter
*/

static const p11_rpc_call p11_rpc_calls[] = {
Expand Down Expand Up @@ -253,6 +255,7 @@ static const p11_rpc_call p11_rpc_calls[] = {
{ P11_RPC_CALL_C_MessageVerifyFinal, "C_MessageVerifyFinal", "u", "" },

{ P11_RPC_CALL_C_InitToken2, "C_InitToken2", "uays", "" },
{ P11_RPC_CALL_C_DeriveKey2, "C_DeriveKey2", "uMuaA", "uPu" },
};

#ifdef _DEBUG
Expand Down Expand Up @@ -514,6 +517,13 @@ bool p11_rpc_buffer_get_mechanism (p11_buffer *buffer,
size_t *offset,
CK_MECHANISM *mech);

void p11_rpc_buffer_add_mech_param_update (p11_buffer *buffer,
const CK_MECHANISM *mech);

bool p11_rpc_buffer_get_mech_param_update (p11_buffer *buffer,
size_t *offset,
CK_MECHANISM *mech);

void p11_rpc_buffer_add_rsa_pkcs_pss_mechanism_value
(p11_buffer *buffer,
const void *value,
Expand Down
Loading

0 comments on commit 6449cfe

Please sign in to comment.