diff --git a/common/attrs.c b/common/attrs.c index 21cf411b..1fcd8c88 100644 --- a/common/attrs.c +++ b/common/attrs.c @@ -141,12 +141,12 @@ attrs_build (CK_ATTRIBUTE *attrs, /* The attribute exists and we're not overriding */ } else if (!override) { if (take_values) - free (add->pValue); + p11_attr_clear (add); continue; /* The attribute exists but we're overriding */ } else { - free (attr->pValue); + p11_attr_clear (attr); } if (take_values) { @@ -432,7 +432,7 @@ p11_attrs_purge (CK_ATTRIBUTE *attrs) for (in = 0, out = 0; !p11_attrs_terminator (attrs + in); in++) { if (attrs[in].ulValueLen == (CK_ULONG)-1) { - free (attrs[in].pValue); + p11_attr_clear (attrs + in); attrs[in].pValue = NULL; attrs[in].ulValueLen = 0; } else { diff --git a/common/mock.c b/common/mock.c index 146f2abd..d2116367 100644 --- a/common/mock.c +++ b/common/mock.c @@ -286,10 +286,16 @@ module_reset_objects (CK_SLOT_ID slot_id) { CK_OBJECT_CLASS klass = CKO_PUBLIC_KEY; char *label = "Public prefix key"; + char *label2 = "Wrapped label"; char *value = "value"; CK_MECHANISM_TYPE type = CKM_MOCK_PREFIX; CK_BBOOL btrue = CK_TRUE; CK_BBOOL bfalse = CK_FALSE; + CK_ATTRIBUTE wrap_template[] = { + { CKA_LABEL, label2, strlen (label2) }, + { CKA_VERIFY, &btrue, sizeof (btrue) }, + { CKA_ENCRYPT, &btrue, sizeof (btrue) }, + }; CK_ATTRIBUTE attrs[] = { { CKA_CLASS, &klass, sizeof (klass) }, { CKA_LABEL, label, strlen (label) }, @@ -297,6 +303,7 @@ module_reset_objects (CK_SLOT_ID slot_id) { CKA_VERIFY, &btrue, sizeof (btrue) }, { CKA_PRIVATE, &bfalse, sizeof (bfalse) }, { CKA_ALWAYS_AUTHENTICATE, &btrue, sizeof (btrue) }, + { CKA_WRAP_TEMPLATE, &wrap_template, sizeof (wrap_template) }, { CKA_VALUE, value, strlen (value) }, { CKA_INVALID, NULL, 0 }, }; @@ -1618,6 +1625,51 @@ mock_X_GetObjectSize__invalid_handle (CK_X_FUNCTION_LIST *self, return CKR_SESSION_HANDLE_INVALID; } +static CK_RV +get_recursive_attribute_value (CK_ATTRIBUTE_PTR dest, + CK_ATTRIBUTE_PTR src, + CK_ULONG count) +{ + CK_RV rv, ret = CKR_OK; + CK_ULONG i; + CK_ATTRIBUTE *result, *attr; + + for (i = 0; i < count; ++i) { + result = dest + i; + attr = src + i; + + result->type = attr->type; + + if (result->pValue == NULL) { + result->ulValueLen = attr->ulValueLen; + continue; + } + + if (result->ulValueLen < attr->ulValueLen) { + result->ulValueLen = (CK_ULONG)-1; + ret = CKR_BUFFER_TOO_SMALL; + continue; + } + + if (IS_ATTRIBUTE_ARRAY (attr)) { + rv = get_recursive_attribute_value (result->pValue, + attr->pValue, attr->ulValueLen / sizeof (CK_ATTRIBUTE)); + if (rv != CKR_OK) { + result->ulValueLen = (CK_ULONG)-1; + ret = rv; + continue; + } + result->ulValueLen = attr->ulValueLen; + continue; + } + + memcpy (result->pValue, attr->pValue, attr->ulValueLen); + result->ulValueLen = attr->ulValueLen; + } + + return ret; +} + CK_RV mock_C_GetAttributeValue (CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object, @@ -1654,14 +1706,26 @@ mock_C_GetAttributeValue (CK_SESSION_HANDLE session, continue; } - if (result->ulValueLen >= attr->ulValueLen) { - memcpy (result->pValue, attr->pValue, attr->ulValueLen); + if (result->ulValueLen < attr->ulValueLen) { + result->ulValueLen = (CK_ULONG)-1; + ret = CKR_BUFFER_TOO_SMALL; + continue; + } + + if (IS_ATTRIBUTE_ARRAY (attr)) { + rv = get_recursive_attribute_value (result->pValue, + attr->pValue, attr->ulValueLen / sizeof (CK_ATTRIBUTE)); + if (rv != CKR_OK) { + result->ulValueLen = (CK_ULONG)-1; + ret = rv; + continue; + } result->ulValueLen = attr->ulValueLen; continue; } - result->ulValueLen = (CK_ULONG)-1; - ret = CKR_BUFFER_TOO_SMALL; + memcpy (result->pValue, attr->pValue, attr->ulValueLen); + result->ulValueLen = attr->ulValueLen; } return ret; diff --git a/common/persist.c b/common/persist.c index 5107a02f..a1202e0a 100644 --- a/common/persist.c +++ b/common/persist.c @@ -562,6 +562,13 @@ field_to_attribute (p11_persist *persist, return false; } + /* Ignore recursive attributes */ + if (IS_ATTRIBUTE_ARRAY (&attr)) { + free (attr.pValue); + attr.pValue = NULL; + attr.ulValueLen = 0; + } + *attrs = p11_attrs_take (*attrs, attr.type, attr.pValue, attr.ulValueLen); return true; diff --git a/p11-kit/iter.c b/p11-kit/iter.c index 48a0e80c..397e7e77 100644 --- a/p11-kit/iter.c +++ b/p11-kit/iter.c @@ -1012,6 +1012,50 @@ p11_kit_iter_get_attributes (P11KitIter *iter, templ, count); } +static CK_RV +prepare_recursive_attribute (P11KitIter *iter, + CK_ATTRIBUTE *templ) +{ + CK_RV rv; + CK_ULONG count, i; + CK_ATTRIBUTE *attr; + + return_val_if_fail (iter != NULL, CKR_GENERAL_ERROR); + return_val_if_fail (templ != NULL, CKR_GENERAL_ERROR); + return_val_if_fail (templ->pValue != NULL, CKR_GENERAL_ERROR); + return_val_if_fail (templ->ulValueLen != 0, CKR_GENERAL_ERROR); + return_val_if_fail (IS_ATTRIBUTE_ARRAY (templ), CKR_GENERAL_ERROR); + + memset (templ->pValue, 0, templ->ulValueLen); + rv = (iter->module->C_GetAttributeValue) (iter->session, iter->object, templ, 1); + + switch (rv) { + case CKR_OK: + case CKR_ATTRIBUTE_TYPE_INVALID: + case CKR_ATTRIBUTE_SENSITIVE: + break; + default: + return_val_if_fail (rv != CKR_BUFFER_TOO_SMALL, rv); + return rv; + } + + attr = templ->pValue; + count = templ->ulValueLen / sizeof (CK_ATTRIBUTE); + + for (i = 0; i < count; ++i, ++attr) { + /* Currently we don't support nested recursive attributes */ + return_val_if_fail (!IS_ATTRIBUTE_ARRAY (attr), CKR_FUNCTION_NOT_SUPPORTED); + return_val_if_fail (attr->type != CKA_INVALID, CKR_GENERAL_ERROR); + return_val_if_fail (attr->ulValueLen != 0, CKR_GENERAL_ERROR); + return_val_if_fail (attr->ulValueLen != (CK_ULONG)-1, CKR_GENERAL_ERROR); + + attr->pValue = malloc (attr->ulValueLen); + return_val_if_fail (attr->pValue != NULL, CKR_HOST_MEMORY); + } + + return CKR_OK; +} + /** * p11_kit_iter_load_attributes: * @iter: the iterator @@ -1081,7 +1125,7 @@ p11_kit_iter_load_attributes (P11KitIter *iter, for (i = 0; i < count; i++) { if (templ[i].ulValueLen == (CK_ULONG)-1 || templ[i].ulValueLen == 0) { - free (original[i].pValue); + p11_attr_clear (original + i); } else if (original[i].pValue != NULL && templ[i].ulValueLen == original[i].ulValueLen) { @@ -1090,6 +1134,14 @@ p11_kit_iter_load_attributes (P11KitIter *iter, } else { templ[i].pValue = realloc (original[i].pValue, templ[i].ulValueLen); return_val_if_fail (templ[i].pValue != NULL, CKR_HOST_MEMORY); + + if (IS_ATTRIBUTE_ARRAY (templ + i)) { + rv = prepare_recursive_attribute (iter, templ + i); + if (rv != CKR_OK) { + free (original); + return rv; + } + } } } diff --git a/p11-kit/rpc-client.c b/p11-kit/rpc-client.c index 19b628b1..df5a35db 100644 --- a/p11-kit/rpc-client.c +++ b/p11-kit/rpc-client.c @@ -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]); @@ -273,7 +268,7 @@ proto_read_attribute_array (p11_rpc_message *msg, /* Wants attribute data, enough space */ } else { size_t offset2 = msg->parsed; - if (!p11_rpc_buffer_get_attribute (msg->input, &offset2, attr)) { + if (!p11_rpc_message_get_attribute (NULL, msg->input, &offset2, attr)) { msg->parsed = offset2; return PARSE_ERROR; } @@ -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; } \ @@ -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; diff --git a/p11-kit/rpc-message.c b/p11-kit/rpc-message.c index 09d7f33d..4f44fac1 100644 --- a/p11-kit/rpc-message.c +++ b/p11-kit/rpc-message.c @@ -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, @@ -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)); @@ -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); @@ -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 @@ -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; @@ -1279,21 +1310,26 @@ p11_rpc_buffer_get_attribute (p11_buffer *buffer, if (!p11_rpc_buffer_get_uint32 (buffer, offset, &length)) return false; + if (length == 0) { + attr->pValue = NULL; + } else if (msg != NULL) { + /* Allocate memory for the attribute value */ + 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 && length != 0 && 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; } diff --git a/p11-kit/rpc-message.h b/p11-kit/rpc-message.h index f171fc4f..6272f6cc 100644 --- a/p11-kit/rpc-message.h +++ b/p11-kit/rpc-message.h @@ -186,7 +186,7 @@ static const p11_rpc_call p11_rpc_calls[] = { { P11_RPC_CALL_C_CopyObject, "C_CopyObject", "uuaA", "u" }, { P11_RPC_CALL_C_DestroyObject, "C_DestroyObject", "uu", "" }, { P11_RPC_CALL_C_GetObjectSize, "C_GetObjectSize", "uu", "u" }, - { P11_RPC_CALL_C_GetAttributeValue, "C_GetAttributeValue", "uufA", "aAu" }, + { P11_RPC_CALL_C_GetAttributeValue, "C_GetAttributeValue", "uuaA", "aAu" }, { P11_RPC_CALL_C_SetAttributeValue, "C_SetAttributeValue", "uuaA", "" }, { P11_RPC_CALL_C_FindObjectsInit, "C_FindObjectsInit", "uaA", "" }, { P11_RPC_CALL_C_FindObjects, "C_FindObjects", "ufu", "au" }, @@ -276,9 +276,6 @@ typedef enum _p11_rpc_value_type { P11_RPC_VALUE_BYTE_ARRAY } p11_rpc_value_type; -typedef void (*p11_rpc_value_encoder) (p11_buffer *, const void *, CK_ULONG); -typedef bool (*p11_rpc_value_decoder) (p11_buffer *, size_t *, void *, CK_ULONG *); - typedef enum _p11_rpc_message_type { P11_RPC_REQUEST = 1, P11_RPC_RESPONSE @@ -295,6 +292,10 @@ typedef struct { void *extra; } p11_rpc_message; +typedef void (*p11_rpc_value_encoder) (p11_buffer *, const void *, CK_ULONG); +typedef bool (*p11_rpc_value_decoder) (p11_buffer *, size_t *, void *, CK_ULONG *); +typedef bool (*p11_rpc_message_decoder) (p11_rpc_message *msg, p11_buffer *, size_t *, void *, CK_ULONG *); + void p11_rpc_message_init (p11_rpc_message *msg, p11_buffer *input, p11_buffer *output); @@ -347,10 +348,6 @@ bool p11_rpc_message_write_ulong_array (p11_rpc_message *msg, CK_ULONG_PTR arr, CK_ULONG num); -bool p11_rpc_message_write_attribute_buffer (p11_rpc_message *msg, - CK_ATTRIBUTE_PTR arr, - CK_ULONG num); - bool p11_rpc_message_write_attribute_array (p11_rpc_message *msg, CK_ATTRIBUTE_PTR arr, CK_ULONG num); @@ -371,6 +368,11 @@ bool p11_rpc_message_read_space_string (p11_rpc_message *msg, bool p11_rpc_message_read_version (p11_rpc_message *msg, CK_VERSION* version); +bool p11_rpc_message_get_attribute (p11_rpc_message *msg, + p11_buffer *buffer, + size_t *offset, + CK_ATTRIBUTE *attr); + p11_buffer * p11_rpc_buffer_new (size_t reserve); p11_buffer * p11_rpc_buffer_new_full (size_t reserve, @@ -437,10 +439,6 @@ bool p11_rpc_buffer_get_uint64 (p11_buffer *buf, void p11_rpc_buffer_add_attribute (p11_buffer *buffer, const CK_ATTRIBUTE *attr); -bool p11_rpc_buffer_get_attribute (p11_buffer *buffer, - size_t *offset, - CK_ATTRIBUTE *attr); - void p11_rpc_buffer_add_byte_value (p11_buffer *buffer, const void *value, CK_ULONG value_length); diff --git a/p11-kit/rpc-server.c b/p11-kit/rpc-server.c index b4cbcd09..3851e0d1 100644 --- a/p11-kit/rpc-server.c +++ b/p11-kit/rpc-server.c @@ -246,61 +246,6 @@ proto_write_ulong_array (p11_rpc_message *msg, return CKR_OK; } -static CK_RV -proto_read_attribute_buffer (p11_rpc_message *msg, - CK_ATTRIBUTE_PTR *result, - CK_ULONG *n_result) -{ - CK_ATTRIBUTE_PTR attrs; - uint32_t n_attrs, i; - uint32_t value; - - assert (msg != NULL); - assert (result != NULL); - assert (n_result != NULL); - assert (msg->input != NULL); - - /* Make sure this is in the right order */ - assert (!msg->signature || p11_rpc_message_verify_part (msg, "fA")); - - /* Read the number of attributes */ - if (!p11_rpc_buffer_get_uint32 (msg->input, &msg->parsed, &n_attrs)) - return PARSE_ERROR; - - /* Allocate memory for the attribute structures */ - attrs = p11_rpc_message_alloc_extra_array (msg, n_attrs, sizeof (CK_ATTRIBUTE)); - if (attrs == NULL) - return CKR_DEVICE_MEMORY; - - /* Now go through and fill in each one */ - for (i = 0; i < n_attrs; ++i) { - - /* The attribute type */ - if (!p11_rpc_buffer_get_uint32 (msg->input, &msg->parsed, &value)) - return PARSE_ERROR; - - attrs[i].type = value; - - /* The number of bytes to allocate */ - if (!p11_rpc_buffer_get_uint32 (msg->input, &msg->parsed, &value)) - return PARSE_ERROR; - - if (value == 0) { - attrs[i].pValue = NULL; - attrs[i].ulValueLen = 0; - } else { - attrs[i].pValue = p11_rpc_message_alloc_extra (msg, value); - if (!attrs[i].pValue) - return CKR_DEVICE_MEMORY; - attrs[i].ulValueLen = value; - } - } - - *result = attrs; - *n_result = n_attrs; - return CKR_OK; -} - static CK_RV proto_read_attribute_array (p11_rpc_message *msg, CK_ATTRIBUTE_PTR *result, @@ -327,39 +272,9 @@ proto_read_attribute_array (p11_rpc_message *msg, return CKR_DEVICE_MEMORY; /* Now go through and fill in each one */ - for (i = 0; i < n_attrs; ++i) { - size_t offset = msg->parsed; - CK_ATTRIBUTE temp; - - /* Check the length needed to store the value */ - memset (&temp, 0, sizeof (temp)); - if (!p11_rpc_buffer_get_attribute (msg->input, &offset, &temp)) { - msg->parsed = offset; + for (i = 0; i < n_attrs; ++i) + if (!p11_rpc_message_get_attribute (msg, msg->input, &msg->parsed, &attrs[i])) return PARSE_ERROR; - } - - if (IS_ATTRIBUTE_ARRAY (&temp)) { - p11_debug("recursive attribute array is not supported"); - return PARSE_ERROR; - } - - attrs[i].type = temp.type; - - /* Whether this one is valid or not */ - if (temp.ulValueLen != ((CK_ULONG)-1)) { - size_t offset2 = msg->parsed; - attrs[i].pValue = p11_rpc_message_alloc_extra (msg, temp.ulValueLen); - if (!p11_rpc_buffer_get_attribute (msg->input, &offset2, &attrs[i])) { - msg->parsed = offset2; - return PARSE_ERROR; - } - } else { - attrs[i].pValue = NULL; - attrs[i].ulValueLen = -1; - } - - msg->parsed = offset; - } *result = attrs; *n_result = n_attrs; @@ -686,10 +601,6 @@ call_ready (p11_rpc_message *msg) _ret = proto_read_ulong_buffer (msg, &buffer, &buffer_len); \ if (_ret != CKR_OK) goto _cleanup; -#define IN_ATTRIBUTE_BUFFER(buffer, buffer_len) \ - _ret = proto_read_attribute_buffer (msg, &buffer, &buffer_len); \ - if (_ret != CKR_OK) goto _cleanup; - #define IN_ATTRIBUTE_ARRAY(attrs, n_attrs) \ _ret = proto_read_attribute_array (msg, &attrs, &n_attrs); \ if (_ret != CKR_OK) goto _cleanup; @@ -1175,7 +1086,7 @@ rpc_C_GetAttributeValue (CK_X_FUNCTION_LIST *self, BEGIN_CALL (GetAttributeValue); IN_ULONG (session); IN_ULONG (object); - IN_ATTRIBUTE_BUFFER (template, count); + IN_ATTRIBUTE_ARRAY (template, count); PROCESS_CALL ((self, session, object, template, count)); OUT_ATTRIBUTE_ARRAY (template, count); END_CALL; diff --git a/p11-kit/test-mock.c b/p11-kit/test-mock.c index 374385fe..d3b0d2c8 100644 --- a/p11-kit/test-mock.c +++ b/p11-kit/test-mock.c @@ -606,6 +606,135 @@ test_set_attribute_value (void) teardown_mock_module (module); } +static void +test_get_wrap_template (void) +{ + CK_RV rv; + CK_FUNCTION_LIST_PTR module; + CK_SESSION_HANDLE session = 0; + char label[sizeof ("Wrapped label") - 1] = { 0 }; + CK_BBOOL verify = CK_FALSE; + CK_BBOOL encrypt = CK_FALSE; + CK_ATTRIBUTE temp[] = { + { 0 }, + { 0 }, + { 0 }, + }; + CK_ATTRIBUTE attrs[] = { + { CKA_WRAP_TEMPLATE, &temp, sizeof (temp) }, + }; + CK_ULONG n_attrs = sizeof (attrs) / sizeof (attrs[0]); + + module = setup_mock_module (&session); + + rv = (module->C_GetAttributeValue) (session, MOCK_PUBLIC_KEY_PREFIX, attrs, n_attrs); + assert (rv == CKR_OK); + assert_num_eq (attrs[0].type, CKA_WRAP_TEMPLATE); + assert_ptr_eq (attrs[0].pValue, &temp); + assert_num_eq (attrs[0].ulValueLen, sizeof (temp)); + assert_num_eq (temp[0].type, CKA_LABEL); + assert_ptr_eq (temp[0].pValue, NULL); + assert_num_eq (temp[0].ulValueLen, sizeof (label)); + assert_num_eq (temp[1].type, CKA_VERIFY); + assert_ptr_eq (temp[1].pValue, NULL); + assert_num_eq (temp[1].ulValueLen, sizeof (verify)); + assert_num_eq (temp[2].type, CKA_ENCRYPT); + assert_ptr_eq (temp[2].pValue, NULL); + assert_num_eq (temp[2].ulValueLen, sizeof (encrypt)); + + temp[0].pValue = label; + temp[1].pValue = &verify; + temp[2].pValue = &encrypt; + + rv = (module->C_GetAttributeValue) (session, MOCK_PUBLIC_KEY_PREFIX, attrs, n_attrs); + assert (rv == CKR_OK); + assert_num_eq (attrs[0].type, CKA_WRAP_TEMPLATE); + assert_ptr_eq (attrs[0].pValue, &temp); + assert_num_eq (attrs[0].ulValueLen, sizeof (temp)); + assert_num_eq (temp[0].type, CKA_LABEL); + assert_ptr_eq (temp[0].pValue, label); + assert_num_eq (temp[0].ulValueLen, sizeof (label)); + assert_num_eq (temp[1].type, CKA_VERIFY); + assert_ptr_eq (temp[1].pValue, &verify); + assert_num_eq (temp[1].ulValueLen, sizeof (verify)); + assert_num_eq (temp[2].type, CKA_ENCRYPT); + assert_ptr_eq (temp[2].pValue, &encrypt); + assert_num_eq (temp[2].ulValueLen, sizeof (encrypt)); + assert (strncmp (label, "Wrapped label", sizeof (label)) == 0); + assert (verify == CK_TRUE); + assert (encrypt == CK_TRUE); + + teardown_mock_module (module); +} + +static void +test_set_wrap_template (void) +{ + CK_RV rv; + CK_FUNCTION_LIST_PTR module; + CK_SESSION_HANDLE session = 0; + char label[] = { 'T', 'E', 'S', 'T' }; + CK_BBOOL local = CK_TRUE; + CK_ATTRIBUTE temp[] = { + { CKA_LABEL, label, sizeof (label) }, + { CKA_LOCAL, &local, sizeof (local) }, + }; + CK_ATTRIBUTE attrs[] = { + { CKA_WRAP_TEMPLATE, &temp, sizeof (temp) }, + }; + CK_ULONG n_attrs = sizeof (attrs) / sizeof (attrs[0]); + + module = setup_mock_module (&session); + + rv = (module->C_SetAttributeValue) (session, MOCK_PUBLIC_KEY_PREFIX, attrs, n_attrs); + assert (rv == CKR_OK); + + attrs[0].pValue = NULL; + attrs[0].ulValueLen = 0; + + rv = (module->C_GetAttributeValue) (session, MOCK_PUBLIC_KEY_PREFIX, attrs, n_attrs); + assert (rv == CKR_OK); + assert_num_eq (attrs[0].type, CKA_WRAP_TEMPLATE); + assert_ptr_eq (attrs[0].pValue, NULL); + assert_num_eq (attrs[0].ulValueLen, sizeof (temp)); + + memset (temp, 0, sizeof (temp)); + attrs[0].pValue = &temp; + + rv = (module->C_GetAttributeValue) (session, MOCK_PUBLIC_KEY_PREFIX, attrs, n_attrs); + assert (rv == CKR_OK); + assert_num_eq (attrs[0].type, CKA_WRAP_TEMPLATE); + assert_ptr_eq (attrs[0].pValue, &temp); + assert_num_eq (attrs[0].ulValueLen, sizeof (temp)); + assert_num_eq (temp[0].type, CKA_LABEL); + assert_ptr_eq (temp[0].pValue, NULL); + assert_num_eq (temp[0].ulValueLen, sizeof (label)); + assert_num_eq (temp[1].type, CKA_LOCAL); + assert_ptr_eq (temp[1].pValue, NULL); + assert_num_eq (temp[1].ulValueLen, sizeof (local)); + + memset (label, 0, sizeof (label)); + local = CK_FALSE; + temp[0].pValue = label; + temp[1].pValue = &local; + + rv = (module->C_GetAttributeValue) (session, MOCK_PUBLIC_KEY_PREFIX, attrs, n_attrs); + assert (rv == CKR_OK); + assert_num_eq (attrs[0].type, CKA_WRAP_TEMPLATE); + assert_ptr_eq (attrs[0].pValue, &temp); + assert_num_eq (attrs[0].ulValueLen, sizeof (temp)); + assert_num_eq (temp[0].type, CKA_LABEL); + assert_ptr_eq (temp[0].pValue, label); + assert_num_eq (temp[0].ulValueLen, sizeof (label)); + assert_num_eq (temp[1].type, CKA_LOCAL); + assert_ptr_eq (temp[1].pValue, &local); + assert_num_eq (temp[1].ulValueLen, sizeof (local)); + assert (strncmp (label, "TEST", sizeof (label)) == 0); + assert (local == CK_TRUE); + + teardown_mock_module (module); +} + static void test_create_object (void) { @@ -2581,6 +2710,8 @@ test_mock_add_tests (const char *prefix, const CK_VERSION *version) p11_test (test_login_logout, "%s/test_login_logout", prefix); p11_test (test_get_attribute_value, "%s/test_get_attribute_value", prefix); p11_test (test_set_attribute_value, "%s/test_set_attribute_value", prefix); + p11_test (test_get_wrap_template, "%s/test_get_wrap_template", prefix); + p11_test (test_set_wrap_template, "%s/test_set_wrap_template", prefix); p11_test (test_create_object, "%s/test_create_object", prefix); p11_test (test_create_object_private, "%s/test_create_object_private", prefix); p11_test (test_copy_object, "%s/test_copy_object", prefix);