Skip to content

Commit

Permalink
rpc: add support for recursive attributes
Browse files Browse the repository at this point in the history
Signed-off-by: Zoltan Fridrich <[email protected]>
  • Loading branch information
ZoltanFridrich committed Feb 29, 2024
1 parent 7756404 commit b538c17
Show file tree
Hide file tree
Showing 8 changed files with 275 additions and 216 deletions.
61 changes: 60 additions & 1 deletion common/mock.c
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,24 @@ module_reset_objects (CK_SLOT_ID slot_id)
p11_dict_set (the_objects, handle_to_pointer (MOCK_PUBLIC_KEY_PREFIX), p11_attrs_dup (attrs));

}

{
CK_OBJECT_CLASS klass = CKO_PUBLIC_KEY;
char *label = "Public prefix key 2";
char *value = "value";
CK_BBOOL bfalse = CK_FALSE;
CK_ATTRIBUTE wrap_template[] = {
{ CKA_LOCAL, &bfalse, sizeof (bfalse) },
};
CK_ATTRIBUTE attrs[] = {
{ CKA_CLASS, &klass, sizeof (klass) },
{ CKA_LABEL, label, strlen (label) },
{ CKA_WRAP_TEMPLATE, &wrap_template, sizeof (wrap_template) },
{ CKA_VALUE, value, strlen (value) },
{ CKA_INVALID, NULL, 0 },
};
p11_dict_set (the_objects, handle_to_pointer (MOCK_PUBLIC_KEY_PREFIX_2), p11_attrs_dup (attrs));
}
}

void
Expand Down Expand Up @@ -1618,6 +1636,42 @@ mock_X_GetObjectSize__invalid_handle (CK_X_FUNCTION_LIST *self,
return CKR_SESSION_HANDLE_INVALID;
}

static CK_RV
mock_get_array_value (CK_ATTRIBUTE_PTR dest,
CK_ATTRIBUTE_PTR src,
CK_ULONG count)
{
CK_RV ret = CKR_OK;
CK_ULONG i;
CK_ATTRIBUTE *result, *attr;

for (i = 0; i < count; ++i) {
result = dest + i;
attr = src + i;

if (result->pValue == NULL) {
result->ulValueLen = attr->ulValueLen;
continue;
}

if (result->ulValueLen >= attr->ulValueLen) {
if (IS_ATTRIBUTE_ARRAY (attr)) {
mock_get_array_value (result->pValue, attr->pValue,
attr->ulValueLen / sizeof (CK_ATTRIBUTE));
} else {
memcpy (result->pValue, attr->pValue, attr->ulValueLen);
}
result->ulValueLen = attr->ulValueLen;
continue;
}

result->ulValueLen = (CK_ULONG)-1;
ret = CKR_BUFFER_TOO_SMALL;
}

return ret;
}

CK_RV
mock_C_GetAttributeValue (CK_SESSION_HANDLE session,
CK_OBJECT_HANDLE object,
Expand Down Expand Up @@ -1655,7 +1709,12 @@ mock_C_GetAttributeValue (CK_SESSION_HANDLE session,
}

if (result->ulValueLen >= attr->ulValueLen) {
memcpy (result->pValue, attr->pValue, attr->ulValueLen);
if (IS_ATTRIBUTE_ARRAY (attr)) {
mock_get_array_value (result->pValue, attr->pValue,
attr->ulValueLen / sizeof (CK_ATTRIBUTE));
} else {
memcpy (result->pValue, attr->pValue, attr->ulValueLen);
}
result->ulValueLen = attr->ulValueLen;
continue;
}
Expand Down
1 change: 1 addition & 0 deletions common/mock.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ enum {
MOCK_PUBLIC_KEY_PREFIX = 6,
MOCK_PROFILE_OBJECT = 7,
MOCK_CERTIFICATE_OBJECT = 8,
MOCK_PUBLIC_KEY_PREFIX_2 = 9,

/*
* CKM_MOCK_CAPITALIZE (encrypt/decrypt)
Expand Down
15 changes: 2 additions & 13 deletions p11-kit/rpc-client.c
Original file line number Diff line number Diff line change
Expand Up @@ -240,16 +240,11 @@ proto_read_attribute_array (p11_rpc_message *msg,
CK_ATTRIBUTE temp;

memset (&temp, 0, sizeof (temp));
if (!p11_rpc_buffer_get_attribute (msg->input, &offset, &temp)) {
if (!p11_rpc_message_get_attribute (msg, msg->input, &offset, &temp)) {
msg->parsed = offset;
return PARSE_ERROR;
}

if (IS_ATTRIBUTE_ARRAY (&temp)) {
p11_debug("recursive attribute array is not supported");
return PARSE_ERROR;
}

/* Try and stuff it in the output data */
if (arr) {
CK_ATTRIBUTE *attr = &(arr[i]);
Expand Down Expand Up @@ -627,12 +622,6 @@ proto_read_sesssion_info (p11_rpc_message *msg,
if (!p11_rpc_message_write_ulong_array (&_msg, arr, len)) \
{ _ret = CKR_HOST_MEMORY; goto _cleanup; }

#define IN_ATTRIBUTE_BUFFER(arr, num) \
if (num != 0 && arr == NULL) \
{ _ret = CKR_ARGUMENTS_BAD; goto _cleanup; } \
if (!p11_rpc_message_write_attribute_buffer (&_msg, (arr), (num))) \
{ _ret = CKR_HOST_MEMORY; goto _cleanup; }

#define IN_ATTRIBUTE_ARRAY(arr, num) \
if (num != 0 && arr == NULL) \
{ _ret = CKR_ARGUMENTS_BAD; goto _cleanup; } \
Expand Down Expand Up @@ -1262,7 +1251,7 @@ rpc_C_GetAttributeValue (CK_X_FUNCTION_LIST *self,
BEGIN_CALL_OR (C_GetAttributeValue, self, CKR_SESSION_HANDLE_INVALID);
IN_ULONG (session);
IN_ULONG (object);
IN_ATTRIBUTE_BUFFER (template, count);
IN_ATTRIBUTE_ARRAY (template, count);
PROCESS_CALL;
OUT_ATTRIBUTE_ARRAY (template, count);
END_CALL;
Expand Down
195 changes: 122 additions & 73 deletions p11-kit/rpc-message.c
Original file line number Diff line number Diff line change
Expand Up @@ -243,37 +243,6 @@ p11_rpc_message_verify_part (p11_rpc_message *msg,
return ok;
}

bool
p11_rpc_message_write_attribute_buffer (p11_rpc_message *msg,
CK_ATTRIBUTE_PTR arr,
CK_ULONG num)
{
CK_ATTRIBUTE_PTR attr;
CK_ULONG i;

assert (num == 0 || arr != NULL);
assert (msg != NULL);
assert (msg->output != NULL);

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

/* Write the number of items */
p11_rpc_buffer_add_uint32 (msg->output, num);

for (i = 0; i < num; ++i) {
attr = &(arr[i]);

/* The attribute type */
p11_rpc_buffer_add_uint32 (msg->output, attr->type);

/* And the attribute buffer length */
p11_rpc_buffer_add_uint32 (msg->output, attr->pValue ? attr->ulValueLen : 0);
}

return !p11_buffer_failed (msg->output);
}

bool
p11_rpc_message_write_attribute_array (p11_rpc_message *msg,
CK_ATTRIBUTE_PTR arr,
Expand Down Expand Up @@ -903,19 +872,95 @@ map_attribute_to_value_type (CK_ATTRIBUTE_TYPE type)
}
}

static bool
p11_rpc_message_get_byte_value (p11_rpc_message *msg,
p11_buffer *buffer,
size_t *offset,
void *value,
CK_ULONG *value_length)
{
return p11_rpc_buffer_get_byte_value (buffer, offset, value, value_length);
}

static bool
p11_rpc_message_get_ulong_value (p11_rpc_message *msg,
p11_buffer *buffer,
size_t *offset,
void *value,
CK_ULONG *value_length)
{
return p11_rpc_buffer_get_ulong_value (buffer, offset, value, value_length);
}

static bool
p11_rpc_message_get_attribute_array_value (p11_rpc_message *msg,
p11_buffer *buffer,
size_t *offset,
void *value,
CK_ULONG *value_length)
{
uint32_t count, i;
CK_ATTRIBUTE *attr = value;

if (!p11_rpc_buffer_get_uint32 (buffer, offset, &count))
return false;

if (value_length != NULL)
*value_length = count * sizeof (CK_ATTRIBUTE);

if (value == NULL)
return true;

for (i = 0; i < count; ++i)
if (!p11_rpc_message_get_attribute (msg, buffer, offset, attr + i))
return false;

return true;
}

static bool
p11_rpc_message_get_mechanism_type_array_value (p11_rpc_message *msg,
p11_buffer *buffer,
size_t *offset,
void *value,
CK_ULONG *value_length)
{
return p11_rpc_buffer_get_mechanism_type_array_value (buffer, offset, value, value_length);
}

static bool
p11_rpc_message_get_date_value (p11_rpc_message *msg,
p11_buffer *buffer,
size_t *offset,
void *value,
CK_ULONG *value_length)
{
return p11_rpc_buffer_get_date_value (buffer, offset, value, value_length);
}

static bool
p11_rpc_message_get_byte_array_value (p11_rpc_message *msg,
p11_buffer *buffer,
size_t *offset,
void *value,
CK_ULONG *value_length)
{
return p11_rpc_buffer_get_byte_array_value (buffer, offset, value, value_length);
}

typedef struct {
p11_rpc_value_type type;
p11_rpc_value_encoder encode;
p11_rpc_value_decoder decode;
p11_rpc_message_decoder decode;
} p11_rpc_attribute_serializer;

static p11_rpc_attribute_serializer p11_rpc_attribute_serializers[] = {
{ P11_RPC_VALUE_BYTE, p11_rpc_buffer_add_byte_value, p11_rpc_buffer_get_byte_value },
{ P11_RPC_VALUE_ULONG, p11_rpc_buffer_add_ulong_value, p11_rpc_buffer_get_ulong_value },
{ P11_RPC_VALUE_ATTRIBUTE_ARRAY, p11_rpc_buffer_add_attribute_array_value, p11_rpc_buffer_get_attribute_array_value },
{ P11_RPC_VALUE_MECHANISM_TYPE_ARRAY, p11_rpc_buffer_add_mechanism_type_array_value, p11_rpc_buffer_get_mechanism_type_array_value },
{ P11_RPC_VALUE_DATE, p11_rpc_buffer_add_date_value, p11_rpc_buffer_get_date_value },
{ P11_RPC_VALUE_BYTE_ARRAY, p11_rpc_buffer_add_byte_array_value, p11_rpc_buffer_get_byte_array_value }
{ P11_RPC_VALUE_BYTE, p11_rpc_buffer_add_byte_value, p11_rpc_message_get_byte_value },
{ P11_RPC_VALUE_ULONG, p11_rpc_buffer_add_ulong_value, p11_rpc_message_get_ulong_value },
{ P11_RPC_VALUE_ATTRIBUTE_ARRAY, p11_rpc_buffer_add_attribute_array_value, p11_rpc_message_get_attribute_array_value },
{ P11_RPC_VALUE_MECHANISM_TYPE_ARRAY, p11_rpc_buffer_add_mechanism_type_array_value, p11_rpc_message_get_mechanism_type_array_value },
{ P11_RPC_VALUE_DATE, p11_rpc_buffer_add_date_value, p11_rpc_message_get_date_value },
{ P11_RPC_VALUE_BYTE_ARRAY, p11_rpc_buffer_add_byte_array_value, p11_rpc_message_get_byte_array_value }
};

P11_STATIC_ASSERT(sizeof(CK_BYTE) <= sizeof(uint8_t));
Expand Down Expand Up @@ -977,6 +1022,12 @@ p11_rpc_buffer_add_attribute_array_value (p11_buffer *buffer,
return;
}

/* When value is NULL, write an empty attribute array */
if (attrs == NULL) {
p11_rpc_buffer_add_uint32 (buffer, 0);
return;
}

/* Write the number of items */
p11_rpc_buffer_add_uint32 (buffer, count);

Expand Down Expand Up @@ -1144,29 +1195,7 @@ p11_rpc_buffer_get_attribute_array_value (p11_buffer *buffer,
void *value,
CK_ULONG *value_length)
{
uint32_t count, i;
CK_ATTRIBUTE *attr, temp;

if (!p11_rpc_buffer_get_uint32 (buffer, offset, &count))
return false;

if (!value) {
memset (&temp, 0, sizeof (CK_ATTRIBUTE));
attr = &temp;
} else
attr = value;

for (i = 0; i < count; i++) {
if (!p11_rpc_buffer_get_attribute (buffer, offset, attr))
return false;
if (value)
attr++;
}

if (value_length)
*value_length = count * sizeof (CK_ATTRIBUTE);

return true;
return p11_rpc_message_get_attribute_array_value (NULL, buffer, offset, value, value_length);
}

bool
Expand Down Expand Up @@ -1252,11 +1281,13 @@ p11_rpc_buffer_get_byte_array_value (p11_buffer *buffer,
}

bool
p11_rpc_buffer_get_attribute (p11_buffer *buffer,
size_t *offset,
CK_ATTRIBUTE *attr)
p11_rpc_message_get_attribute (p11_rpc_message *msg,
p11_buffer *buffer,
size_t *offset,
CK_ATTRIBUTE *attr)
{
uint32_t type, length, decode_length;
uint32_t type, length;
CK_ULONG decode_length;
unsigned char validity;
p11_rpc_attribute_serializer *serializer;
p11_rpc_value_type value_type;
Expand All @@ -1279,24 +1310,42 @@ p11_rpc_buffer_get_attribute (p11_buffer *buffer,
if (!p11_rpc_buffer_get_uint32 (buffer, offset, &length))
return false;

if (length == 0) {
attr->type = type;
attr->pValue = NULL;
attr->ulValueLen = 0;
return true;
}

/* Allocate memory for the attribute value */
if (msg != NULL) {
attr->pValue = p11_rpc_message_alloc_extra (msg, length);
if (attr->pValue == NULL)
return false;
}

/* Decode the attribute value */
value_type = map_attribute_to_value_type (type);
assert (value_type < ELEMS (p11_rpc_attribute_serializers));
serializer = &p11_rpc_attribute_serializers[value_type];
assert (serializer != NULL);
if (!serializer->decode (buffer, offset, attr->pValue, &attr->ulValueLen))
if (!serializer->decode (msg, buffer, offset, attr->pValue, &decode_length))
return false;
if (attr->pValue == NULL && decode_length > length)
return false;
if (!attr->pValue) {
decode_length = attr->ulValueLen;
attr->ulValueLen = length;
if (decode_length > length) {
return false;
}
}
attr->type = type;
attr->ulValueLen = length;
return true;
}

bool
p11_rpc_buffer_get_attribute (p11_buffer *buffer,
size_t *offset,
CK_ATTRIBUTE *attr)
{
return p11_rpc_message_get_attribute (NULL, buffer, offset, attr);
}

/* Used to override the supported mechanisms in tests */
CK_MECHANISM_TYPE *p11_rpc_mechanisms_override_supported = NULL;

Expand Down
Loading

0 comments on commit b538c17

Please sign in to comment.