summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--p11-kit/rpc-client.c63
-rw-r--r--p11-kit/rpc-message.c509
-rw-r--r--p11-kit/rpc-message.h77
-rw-r--r--p11-kit/rpc-server.c35
-rw-r--r--p11-kit/test-rpc.c223
5 files changed, 827 insertions, 80 deletions
diff --git a/p11-kit/rpc-client.c b/p11-kit/rpc-client.c
index c69dcfd..3521ddd 100644
--- a/p11-kit/rpc-client.c
+++ b/p11-kit/rpc-client.c
@@ -196,11 +196,7 @@ proto_read_attribute_array (p11_rpc_message *msg,
CK_ATTRIBUTE_PTR arr,
CK_ULONG len)
{
- uint32_t i, num, value, type;
- CK_ATTRIBUTE_PTR attr;
- const unsigned char *attrval = NULL;
- size_t attrlen = 0;
- unsigned char validity;
+ uint32_t i, num;
CK_RV ret;
assert (len != 0);
@@ -229,62 +225,49 @@ proto_read_attribute_array (p11_rpc_message *msg,
/* We need to go ahead and read everything in all cases */
for (i = 0; i < num; ++i) {
+ size_t offset = msg->parsed;
+ CK_ATTRIBUTE temp;
- /* The attribute type */
- p11_rpc_buffer_get_uint32 (msg->input, &msg->parsed, &type);
-
- /* Attribute validity */
- p11_rpc_buffer_get_byte (msg->input, &msg->parsed, &validity);
-
- /* And the data itself */
- if (validity) {
- if (p11_rpc_buffer_get_uint32 (msg->input, &msg->parsed, &value) &&
- p11_rpc_buffer_get_byte_array (msg->input, &msg->parsed, &attrval, &attrlen)) {
- if (attrval && value != attrlen) {
- p11_message ("attribute length does not match attribute data");
- return PARSE_ERROR;
- }
- attrlen = value;
- }
+ memset (&temp, 0, sizeof (temp));
+ if (!p11_rpc_buffer_get_attribute (msg->input, &offset, &temp)) {
+ msg->parsed = offset;
+ return PARSE_ERROR;
}
- /* Don't act on this data unless no errors */
- if (p11_buffer_failed (msg->input))
- break;
-
/* Try and stuff it in the output data */
if (arr) {
- attr = &(arr[i]);
- if (attr->type != type) {
+ CK_ATTRIBUTE *attr = &(arr[i]);
+
+ if (temp.type != attr->type) {
p11_message ("returned attributes in invalid order");
+ msg->parsed = offset;
return PARSE_ERROR;
}
- if (validity) {
+ if (temp.ulValueLen != ((CK_ULONG)-1)) {
/* Just requesting the attribute size */
if (!attr->pValue) {
- attr->ulValueLen = attrlen;
+ attr->ulValueLen = temp.ulValueLen;
/* Wants attribute data, but too small */
- } else if (attr->ulValueLen < attrlen) {
- attr->ulValueLen = attrlen;
+ } else if (attr->ulValueLen < temp.ulValueLen) {
+ attr->ulValueLen = temp.ulValueLen;
ret = CKR_BUFFER_TOO_SMALL;
- /* Wants attribute data, value is null */
- } else if (attrval == NULL) {
- attr->ulValueLen = 0;
-
/* Wants attribute data, enough space */
} else {
- attr->ulValueLen = attrlen;
- memcpy (attr->pValue, attrval, attrlen);
+ size_t offset2 = msg->parsed;
+ if (!p11_rpc_buffer_get_attribute (msg->input, &offset2, attr)) {
+ msg->parsed = offset2;
+ return PARSE_ERROR;
+ }
}
-
- /* Not a valid attribute */
} else {
- attr->ulValueLen = ((CK_ULONG)-1);
+ attr->ulValueLen = temp.ulValueLen;
}
}
+
+ msg->parsed = offset;
}
if (p11_buffer_failed (msg->input))
diff --git a/p11-kit/rpc-message.c b/p11-kit/rpc-message.c
index d1b491d..25d8a7b 100644
--- a/p11-kit/rpc-message.c
+++ b/p11-kit/rpc-message.c
@@ -35,6 +35,7 @@
#include "config.h"
+#define P11_DEBUG_FLAG P11_DEBUG_RPC
#include "debug.h"
#include "library.h"
#include "message.h"
@@ -44,6 +45,8 @@
#include <assert.h>
#include <string.h>
+#define ELEMS(x) (sizeof (x) / sizeof (x[0]))
+
void
p11_rpc_message_init (p11_rpc_message *msg,
p11_buffer *input,
@@ -255,8 +258,6 @@ p11_rpc_message_write_attribute_array (p11_rpc_message *msg,
CK_ULONG num)
{
CK_ULONG i;
- CK_ATTRIBUTE_PTR attr;
- unsigned char validity;
assert (num == 0 || arr != NULL);
assert (msg != NULL);
@@ -268,22 +269,8 @@ p11_rpc_message_write_attribute_array (p11_rpc_message *msg,
/* 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);
-
- /* Write out the attribute validity */
- validity = (((CK_LONG)attr->ulValueLen) == -1) ? 0 : 1;
- p11_rpc_buffer_add_byte (msg->output, validity);
-
- /* The attribute length and value */
- if (validity) {
- p11_rpc_buffer_add_uint32 (msg->output, attr->ulValueLen);
- p11_rpc_buffer_add_byte_array (msg->output, attr->pValue, attr->ulValueLen);
- }
- }
+ for (i = 0; i < num; ++i)
+ p11_rpc_buffer_add_attribute (msg->output, &(arr[i]));
return !p11_buffer_failed (msg->output);
}
@@ -768,3 +755,489 @@ p11_rpc_buffer_get_byte_array (p11_buffer *buf,
return true;
}
+
+static p11_rpc_value_type
+map_attribute_to_value_type (CK_ATTRIBUTE_TYPE type)
+{
+ switch (type) {
+ case CKA_TOKEN:
+ case CKA_PRIVATE:
+ case CKA_TRUSTED:
+ case CKA_SENSITIVE:
+ case CKA_ENCRYPT:
+ case CKA_DECRYPT:
+ case CKA_WRAP:
+ case CKA_UNWRAP:
+ case CKA_SIGN:
+ case CKA_SIGN_RECOVER:
+ case CKA_VERIFY:
+ case CKA_VERIFY_RECOVER:
+ case CKA_DERIVE:
+ case CKA_EXTRACTABLE:
+ case CKA_LOCAL:
+ case CKA_NEVER_EXTRACTABLE:
+ case CKA_ALWAYS_SENSITIVE:
+ case CKA_MODIFIABLE:
+ case CKA_COPYABLE:
+ case CKA_SECONDARY_AUTH: /* Deprecated */
+ case CKA_ALWAYS_AUTHENTICATE:
+ case CKA_WRAP_WITH_TRUSTED:
+ case CKA_RESET_ON_INIT:
+ case CKA_HAS_RESET:
+ case CKA_COLOR:
+ return P11_RPC_VALUE_BYTE;
+ case CKA_CLASS:
+ case CKA_CERTIFICATE_TYPE:
+ case CKA_CERTIFICATE_CATEGORY:
+ case CKA_JAVA_MIDP_SECURITY_DOMAIN:
+ case CKA_KEY_TYPE:
+ case CKA_MODULUS_BITS:
+ case CKA_PRIME_BITS:
+ case CKA_SUB_PRIME_BITS:
+ case CKA_VALUE_BITS:
+ case CKA_VALUE_LEN:
+ case CKA_KEY_GEN_MECHANISM:
+ case CKA_AUTH_PIN_FLAGS: /* Deprecated */
+ case CKA_HW_FEATURE_TYPE:
+ case CKA_PIXEL_X:
+ case CKA_PIXEL_Y:
+ case CKA_RESOLUTION:
+ case CKA_CHAR_ROWS:
+ case CKA_CHAR_COLUMNS:
+ case CKA_BITS_PER_PIXEL:
+ case CKA_MECHANISM_TYPE:
+ return P11_RPC_VALUE_ULONG;
+ case CKA_WRAP_TEMPLATE:
+ case CKA_UNWRAP_TEMPLATE:
+ return P11_RPC_VALUE_ATTRIBUTE_ARRAY;
+ case CKA_ALLOWED_MECHANISMS:
+ return P11_RPC_VALUE_MECHANISM_TYPE_ARRAY;
+ case CKA_START_DATE:
+ case CKA_END_DATE:
+ return P11_RPC_VALUE_DATE;
+ default:
+ p11_debug ("cannot determine the type of attribute value for %lu; assuming byte array",
+ type);
+ /* fallthrough */
+ case CKA_LABEL:
+ case CKA_APPLICATION:
+ case CKA_VALUE:
+ case CKA_OBJECT_ID:
+ case CKA_ISSUER:
+ case CKA_SERIAL_NUMBER:
+ case CKA_AC_ISSUER:
+ case CKA_OWNER:
+ case CKA_ATTR_TYPES:
+ case CKA_URL:
+ case CKA_HASH_OF_SUBJECT_PUBLIC_KEY:
+ case CKA_HASH_OF_ISSUER_PUBLIC_KEY:
+ case CKA_CHECK_VALUE:
+ case CKA_SUBJECT:
+ case CKA_ID:
+ case CKA_MODULUS:
+ case CKA_PUBLIC_EXPONENT:
+ case CKA_PRIVATE_EXPONENT:
+ case CKA_PRIME_1:
+ case CKA_PRIME_2:
+ case CKA_EXPONENT_1:
+ case CKA_EXPONENT_2:
+ case CKA_COEFFICIENT:
+ case CKA_PRIME:
+ case CKA_SUBPRIME:
+ case CKA_BASE:
+ case CKA_EC_PARAMS:
+ /* same as CKA_ECDSA_PARAMS */
+ case CKA_EC_POINT:
+ case CKA_CHAR_SETS:
+ case CKA_ENCODING_METHODS:
+ case CKA_MIME_TYPES:
+ case CKA_REQUIRED_CMS_ATTRIBUTES:
+ case CKA_DEFAULT_CMS_ATTRIBUTES:
+ case CKA_SUPPORTED_CMS_ATTRIBUTES:
+ return P11_RPC_VALUE_BYTE_ARRAY;
+ }
+}
+
+void
+p11_rpc_buffer_add_byte_value (p11_buffer *buffer,
+ const void *value,
+ CK_ULONG value_length)
+{
+ CK_BYTE byte_value;
+
+ /* Check if value can be converted to CK_BYTE. */
+ if (value_length > sizeof (CK_BYTE)) {
+ p11_buffer_fail (buffer);
+ return;
+ }
+ memcpy (&byte_value, value, value_length);
+
+ /* Check if byte_value can be converted to uint8_t. */
+ if (byte_value > UINT8_MAX) {
+ p11_buffer_fail (buffer);
+ return;
+ }
+
+ p11_rpc_buffer_add_byte (buffer, byte_value);
+}
+
+void
+p11_rpc_buffer_add_ulong_value (p11_buffer *buffer,
+ const void *value,
+ CK_ULONG value_length)
+{
+ CK_ULONG ulong_value;
+
+ /* Check if value can be converted to CK_ULONG. */
+ if (value_length > sizeof (CK_ULONG)) {
+ p11_buffer_fail (buffer);
+ return;
+ }
+ memcpy (&ulong_value, value, value_length);
+
+ /* Check if ulong_value can be converted to uint64_t. */
+ if (ulong_value > UINT64_MAX) {
+ p11_buffer_fail (buffer);
+ return;
+ }
+
+ p11_rpc_buffer_add_uint64 (buffer, ulong_value);
+}
+
+void
+p11_rpc_buffer_add_attribute_array_value (p11_buffer *buffer,
+ const void *value,
+ CK_ULONG value_length)
+{
+ const CK_ATTRIBUTE *attrs = value;
+ size_t count = value_length / sizeof (CK_ATTRIBUTE);
+ size_t i;
+
+ /* Check if count can be converted to uint32_t. */
+ if (count > UINT32_MAX) {
+ p11_buffer_fail (buffer);
+ return;
+ }
+
+ /* Write the number of items */
+ p11_rpc_buffer_add_uint32 (buffer, count);
+
+ /* Actually write the attributes. */
+ for (i = 0; i < count; i++) {
+ const CK_ATTRIBUTE *attr = &(attrs[i]);
+ p11_rpc_buffer_add_attribute (buffer, attr);
+ }
+}
+
+void
+p11_rpc_buffer_add_mechanism_type_array_value (p11_buffer *buffer,
+ const void *value,
+ CK_ULONG value_length)
+{
+ const CK_MECHANISM_TYPE *mechs = value;
+ size_t count = value_length / sizeof (CK_MECHANISM_TYPE);
+ size_t i;
+
+ /* Check if count can be converted to uint32_t. */
+ if (count > UINT32_MAX) {
+ p11_buffer_fail (buffer);
+ return;
+ }
+
+ /* Write the number of items */
+ p11_rpc_buffer_add_uint32 (buffer, count);
+
+ for (i = 0; i < count; i++) {
+ if (mechs[i] > UINT64_MAX) {
+ p11_buffer_fail (buffer);
+ return;
+ }
+ p11_rpc_buffer_add_uint64 (buffer, mechs[i]);
+ }
+}
+
+void
+p11_rpc_buffer_add_date_value (p11_buffer *buffer,
+ const void *value,
+ CK_ULONG value_length)
+{
+ CK_DATE date_value;
+ unsigned char array[8];
+
+ /* Check if value can be converted to CK_DATE. */
+ if (value_length > sizeof (CK_DATE)) {
+ p11_buffer_fail (buffer);
+ return;
+ }
+
+ memcpy (&date_value, value, value_length);
+ memcpy (array, date_value.year, 4);
+ memcpy (array + 4, date_value.month, 2);
+ memcpy (array + 6, date_value.day, 2);
+
+ p11_rpc_buffer_add_byte_array (buffer, array, 8);
+}
+
+void
+p11_rpc_buffer_add_byte_array_value (p11_buffer *buffer,
+ const void *value,
+ CK_ULONG value_length)
+{
+ /* Check if value length can be converted to uint32_t, as
+ * p11_rpc_buffer_add_byte_array expects. */
+ if (value_length > UINT32_MAX) {
+ p11_buffer_fail (buffer);
+ return;
+ }
+
+ p11_rpc_buffer_add_byte_array (buffer, value, value_length);
+}
+
+void
+p11_rpc_buffer_add_attribute (p11_buffer *buffer, const CK_ATTRIBUTE *attr)
+{
+ unsigned char validity;
+ static const p11_rpc_value_encoder encoders[] = {
+ p11_rpc_buffer_add_byte_value,
+ p11_rpc_buffer_add_ulong_value,
+ p11_rpc_buffer_add_attribute_array_value,
+ p11_rpc_buffer_add_mechanism_type_array_value,
+ p11_rpc_buffer_add_date_value,
+ p11_rpc_buffer_add_byte_array_value
+ };
+ p11_rpc_value_encoder encoder;
+ p11_rpc_value_type value_type;
+
+ /* The attribute type */
+ if (attr->type > UINT32_MAX) {
+ p11_buffer_fail (buffer);
+ return;
+ }
+ p11_rpc_buffer_add_uint32 (buffer, attr->type);
+
+ /* Write out the attribute validity */
+ validity = (((CK_LONG)attr->ulValueLen) == -1) ? 0 : 1;
+ p11_rpc_buffer_add_byte (buffer, validity);
+
+ if (!validity)
+ return;
+
+ /* The attribute length */
+ if (attr->ulValueLen > UINT32_MAX) {
+ p11_buffer_fail (buffer);
+ return;
+ }
+ p11_rpc_buffer_add_uint32 (buffer, attr->ulValueLen);
+
+ /* The attribute value */
+ value_type = map_attribute_to_value_type (attr->type);
+ assert (value_type < ELEMS (encoders));
+ encoder = encoders[value_type];
+ assert (encoder != NULL);
+ encoder (buffer, attr->pValue, attr->ulValueLen);
+}
+
+bool
+p11_rpc_buffer_get_byte_value (p11_buffer *buffer,
+ size_t *offset,
+ void *value,
+ CK_ULONG *value_length)
+{
+ unsigned char val;
+
+ if (!p11_rpc_buffer_get_byte (buffer, offset, &val))
+ return false;
+
+ if (value) {
+ CK_BYTE byte_value = val;
+ memcpy (value, &byte_value, sizeof (CK_BYTE));
+ }
+
+ if (value_length)
+ *value_length = sizeof (CK_BYTE);
+
+ return true;
+}
+
+bool
+p11_rpc_buffer_get_ulong_value (p11_buffer *buffer,
+ size_t *offset,
+ void *value,
+ CK_ULONG *value_length)
+{
+ uint64_t val;
+
+ if (!p11_rpc_buffer_get_uint64 (buffer, offset, &val))
+ return false;
+
+ if (value) {
+ CK_ULONG ulong_value = val;
+ memcpy (value, &ulong_value, sizeof (CK_ULONG));
+ }
+
+ if (value_length)
+ *value_length = sizeof (CK_ULONG);
+
+ return true;
+}
+
+bool
+p11_rpc_buffer_get_attribute_array_value (p11_buffer *buffer,
+ size_t *offset,
+ 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;
+}
+
+bool
+p11_rpc_buffer_get_mechanism_type_array_value (p11_buffer *buffer,
+ size_t *offset,
+ void *value,
+ CK_ULONG *value_length)
+{
+ uint32_t count, i;
+ CK_MECHANISM_TYPE *mech, temp;
+
+ if (!p11_rpc_buffer_get_uint32 (buffer, offset, &count))
+ return false;
+
+ if (!value) {
+ memset (&temp, 0, sizeof (CK_MECHANISM_TYPE));
+ mech = &temp;
+ } else
+ mech = value;
+
+ for (i = 0; i < count; i++) {
+ CK_ULONG len;
+ if (!p11_rpc_buffer_get_ulong_value (buffer, offset, mech, &len))
+ return false;
+ if (value)
+ mech++;
+ }
+
+ if (value_length)
+ *value_length = count * sizeof (CK_MECHANISM_TYPE);
+
+ return true;
+}
+
+bool
+p11_rpc_buffer_get_date_value (p11_buffer *buffer,
+ size_t *offset,
+ void *value,
+ CK_ULONG *value_length)
+{
+ CK_DATE date_value;
+ const unsigned char *array;
+ size_t array_length;
+
+ if (!p11_rpc_buffer_get_byte_array (buffer, offset,
+ &array, &array_length) ||
+ array_length != 8)
+ return false;
+
+ if (value) {
+ memcpy (date_value.year, array, 4);
+ memcpy (date_value.month, array + 4, 2);
+ memcpy (date_value.day, array + 6, 2);
+ memcpy (value, &date_value, sizeof (CK_DATE));
+ }
+
+ if (value_length)
+ *value_length = sizeof (CK_DATE);
+
+ return true;
+}
+
+bool
+p11_rpc_buffer_get_byte_array_value (p11_buffer *buffer,
+ size_t *offset,
+ void *value,
+ CK_ULONG *value_length)
+{
+ const unsigned char *val;
+ size_t len;
+
+ if (!p11_rpc_buffer_get_byte_array (buffer, offset, &val, &len))
+ return false;
+
+ if (val && value)
+ memcpy (value, val, len);
+
+ if (value_length)
+ *value_length = len;
+
+ return true;
+}
+
+bool
+p11_rpc_buffer_get_attribute (p11_buffer *buffer,
+ size_t *offset,
+ CK_ATTRIBUTE *attr)
+{
+ uint32_t type, length;
+ unsigned char validity;
+ static const p11_rpc_value_decoder decoders[] = {
+ p11_rpc_buffer_get_byte_value,
+ p11_rpc_buffer_get_ulong_value,
+ p11_rpc_buffer_get_attribute_array_value,
+ p11_rpc_buffer_get_mechanism_type_array_value,
+ p11_rpc_buffer_get_date_value,
+ p11_rpc_buffer_get_byte_array_value
+ };
+ p11_rpc_value_decoder decoder;
+ p11_rpc_value_type value_type;
+
+ /* The attribute type */
+ if (!p11_rpc_buffer_get_uint32 (buffer, offset, &type))
+ return false;
+
+ /* Attribute validity */
+ if (!p11_rpc_buffer_get_byte (buffer, offset, &validity))
+ return false;
+
+ /* Not a valid attribute */
+ if (!validity) {
+ attr->ulValueLen = ((CK_ULONG)-1);
+ attr->type = type;
+ return true;
+ }
+
+ if (!p11_rpc_buffer_get_uint32 (buffer, offset, &length))
+ return false;
+
+ /* Decode the attribute value */
+ value_type = map_attribute_to_value_type (type);
+ assert (value_type < ELEMS (decoders));
+ decoder = decoders[value_type];
+ assert (decoder != NULL);
+ if (!decoder (buffer, offset, attr->pValue, &attr->ulValueLen))
+ return false;
+ if (!attr->pValue)
+ attr->ulValueLen = length;
+ attr->type = type;
+ return true;
+}
diff --git a/p11-kit/rpc-message.h b/p11-kit/rpc-message.h
index 9827097..5c81c1c 100644
--- a/p11-kit/rpc-message.h
+++ b/p11-kit/rpc-message.h
@@ -216,6 +216,18 @@ static const p11_rpc_call p11_rpc_calls[] = {
#define P11_RPC_HANDSHAKE_LEN \
(strlen ((char *)P11_RPC_HANDSHAKE))
+typedef enum _p11_rpc_value_type {
+ P11_RPC_VALUE_BYTE = 0,
+ P11_RPC_VALUE_ULONG,
+ P11_RPC_VALUE_ATTRIBUTE_ARRAY,
+ P11_RPC_VALUE_MECHANISM_TYPE_ARRAY,
+ P11_RPC_VALUE_DATE,
+ 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
@@ -367,4 +379,69 @@ bool p11_rpc_buffer_get_uint64 (p11_buffer *buf,
size_t *offset,
uint64_t *val);
+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);
+
+bool p11_rpc_buffer_get_byte_value (p11_buffer *buffer,
+ size_t *offset,
+ void *value,
+ CK_ULONG *value_length);
+
+void p11_rpc_buffer_add_ulong_value (p11_buffer *buffer,
+ const void *value,
+ CK_ULONG value_length);
+
+bool p11_rpc_buffer_get_ulong_value (p11_buffer *buffer,
+ size_t *offset,
+ void *value,
+ CK_ULONG *value_length);
+
+void p11_rpc_buffer_add_attribute_array_value
+ (p11_buffer *buffer,
+ const void *value,
+ CK_ULONG value_length);
+
+bool p11_rpc_buffer_get_attribute_array_value
+ (p11_buffer *buffer,
+ size_t *offset,
+ void *value,
+ CK_ULONG *value_length);
+
+void p11_rpc_buffer_add_mechanism_type_array_value
+ (p11_buffer *buffer,
+ const void *value,
+ CK_ULONG value_length);
+
+bool p11_rpc_buffer_get_mechanism_type_array_value
+ (p11_buffer *buffer,
+ size_t *offset,
+ void *value,
+ CK_ULONG *value_length);
+
+void p11_rpc_buffer_add_date_value (p11_buffer *buffer,
+ const void *value,
+ CK_ULONG value_length);
+
+bool p11_rpc_buffer_get_date_value (p11_buffer *buffer,
+ size_t *offset,
+ void *value,
+ CK_ULONG *value_length);
+
+void p11_rpc_buffer_add_byte_array_value (p11_buffer *buffer,
+ const void *value,
+ CK_ULONG value_length);
+
+bool p11_rpc_buffer_get_byte_array_value (p11_buffer *buffer,
+ size_t *offset,
+ void *value,
+ CK_ULONG *value_length);
+
#endif /* _RPC_MESSAGE_H */
diff --git a/p11-kit/rpc-server.c b/p11-kit/rpc-server.c
index 071064f..dec9b0b 100644
--- a/p11-kit/rpc-server.c
+++ b/p11-kit/rpc-server.c
@@ -281,11 +281,7 @@ proto_read_attribute_array (p11_rpc_message *msg,
CK_ULONG *n_result)
{
CK_ATTRIBUTE_PTR attrs;
- const unsigned char *data;
- unsigned char valid;
uint32_t n_attrs, i;
- uint32_t value;
- size_t n_data;
assert (msg != NULL);
assert (result != NULL);
@@ -306,34 +302,31 @@ proto_read_attribute_array (p11_rpc_message *msg,
/* Now go through and fill in each one */
for (i = 0; i < n_attrs; ++i) {
+ size_t offset = msg->parsed;
+ CK_ATTRIBUTE temp;
- /* The attribute type */
- if (!p11_rpc_buffer_get_uint32 (msg->input, &msg->parsed, &value))
+ memset (&temp, 0, sizeof (temp));
+ if (!p11_rpc_buffer_get_attribute (msg->input, &offset, &temp)) {
+ msg->parsed = offset;
return PARSE_ERROR;
+ }
- attrs[i].type = value;
+ attrs[i].type = temp.type;
/* Whether this one is valid or not */
- if (!p11_rpc_buffer_get_byte (msg->input, &msg->parsed, &valid))
- return PARSE_ERROR;
-
- if (valid) {
- if (!p11_rpc_buffer_get_uint32 (msg->input, &msg->parsed, &value))
- return PARSE_ERROR;
- if (!p11_rpc_buffer_get_byte_array (msg->input, &msg->parsed, &data, &n_data))
- return PARSE_ERROR;
-
- if (data != NULL && n_data != value) {
- p11_message ("attribute length and data do not match");
+ 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;
}
-
- attrs[i].pValue = (CK_VOID_PTR)data;
- attrs[i].ulValueLen = value;
} else {
attrs[i].pValue = NULL;
attrs[i].ulValueLen = -1;
}
+
+ msg->parsed = offset;
}
*result = attrs;
diff --git a/p11-kit/test-rpc.c b/p11-kit/test-rpc.c
index c9f8333..c6490bf 100644
--- a/p11-kit/test-rpc.c
+++ b/p11-kit/test-rpc.c
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2012 Stefan Walter
- * Copyright (c) 2012 Red Hat Inc.
+ * Copyright (C) 2012-2017 Red Hat Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -352,6 +352,221 @@ test_byte_array_static (void)
assert (memcmp (data + 8, val, 32) == 0);
}
+static void
+test_byte_value (void)
+{
+ p11_buffer buffer;
+ unsigned char bytes[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F };
+
+ char val[16];
+ size_t offset = 0;
+ CK_ULONG val_size;
+ bool ret;
+
+ p11_buffer_init (&buffer, 0);
+
+ p11_rpc_buffer_add_byte_value(&buffer, bytes, sizeof(bytes));
+ assert (p11_buffer_failed (&buffer));
+
+ p11_buffer_reset (&buffer, 0);
+
+ p11_rpc_buffer_add_byte_value(&buffer, bytes, 1);
+ assert (!p11_buffer_failed (&buffer));
+
+ ret = p11_rpc_buffer_get_byte_value(&buffer, &offset, val, &val_size);
+ assert_num_eq (true, ret);
+
+ assert_num_eq (bytes[0], val[0]);
+
+ /* Read out of bound */
+ ret = p11_rpc_buffer_get_byte_value(&buffer, &offset, val, &val_size);
+ assert_num_eq (false, ret);
+
+ p11_buffer_uninit (&buffer);
+}
+
+static void
+test_ulong_value (void)
+{
+ p11_buffer buffer;
+ p11_buffer buf = { (unsigned char *)"pad0\x00\x00\x00\x00\x23\x45\x67\x89", 12, };
+ CK_ULONG val = 0xFFFFFFFF;
+ uint64_t val64 = 0xFFFFFFFFFFFFFFFF;
+ size_t offset = 0;
+ CK_ULONG val_size;
+ bool ret;
+
+ offset = 4;
+ ret = p11_rpc_buffer_get_ulong_value(&buf, &offset, &val, &val_size);
+ assert_num_eq (true, ret);
+ assert_num_eq (12, offset);
+ assert_num_eq (sizeof(val), val_size);
+ assert_num_eq (0x23456789, val);
+
+ p11_buffer_init (&buffer, 0);
+
+ offset = 0;
+ val_size = 8;
+ ret = p11_rpc_buffer_get_ulong_value (&buffer, &offset, &val64, &val_size);
+ assert_num_eq (0, ret);
+ assert_num_eq (0, offset);
+ assert_num_eq (sizeof(val), val_size);
+ assert (0xFFFFFFFFFFFFFFFF == val64);
+
+ p11_buffer_reset (&buffer, 0);
+
+ p11_buffer_add (&buffer, (unsigned char *)"padding", 7);
+
+ val64 = 0x0123456708ABCDEF;
+ p11_rpc_buffer_add_ulong_value (&buffer, &val64, sizeof(val64));
+ assert (!p11_buffer_failed (&buffer));
+
+ assert_num_eq (15, buffer.len);
+
+ val64 = 0xFFFFFFFFFFFFFFFF;
+ offset = 7;
+ ret = p11_rpc_buffer_get_ulong_value (&buffer, &offset, &val64, &val_size);
+ assert_num_eq (true, ret);
+ assert_num_eq (15, offset);
+ assert (0x0123456708ABCDEF == val64);
+
+ /* Read out of bound */
+ val64 = 0xFFFFFFFFFFFFFFFF;
+ ret = p11_rpc_buffer_get_ulong_value (&buffer, &offset, &val64, &val_size);
+ assert_num_eq (false, ret);
+
+ p11_buffer_uninit (&buffer);
+}
+
+static void
+test_attribute_array_value (void)
+{
+ p11_buffer buffer;
+ CK_BBOOL truev = CK_TRUE;
+ char labelv[] = "label";
+ CK_ATTRIBUTE attrs[] = {
+ { CKA_MODIFIABLE, &truev, sizeof (truev) },
+ { CKA_LABEL, labelv, sizeof (labelv) }
+ };
+ CK_BBOOL boolv = CK_FALSE;
+ char strv[] = "\0\0\0\0\0";
+ CK_ATTRIBUTE val[] = {
+ { CKA_MODIFIABLE, &boolv, sizeof (boolv) },
+ { CKA_LABEL, strv, sizeof (strv) }
+ };
+ CK_ULONG val_size;
+ size_t offset = 0, offset2;
+ bool ret;
+
+ p11_buffer_init (&buffer, 0);
+
+ p11_rpc_buffer_add_attribute_array_value(&buffer, attrs, sizeof(attrs));
+ assert (!p11_buffer_failed (&buffer));
+
+ offset2 = offset;
+ ret = p11_rpc_buffer_get_attribute_array_value(&buffer, &offset, NULL, &val_size);
+ assert_num_eq (true, ret);
+
+ offset = offset2;
+ ret = p11_rpc_buffer_get_attribute_array_value(&buffer, &offset, val, &val_size);
+ assert_num_eq (true, ret);
+ assert_num_eq (val[0].type, CKA_MODIFIABLE);
+ assert_num_eq (*(CK_BBOOL *)val[0].pValue, CK_TRUE);
+ assert_num_eq (val[0].ulValueLen, sizeof (truev));
+ assert_num_eq (val[1].type, CKA_LABEL);
+ assert_str_eq (val[1].pValue, "label");
+ assert_num_eq (val[1].ulValueLen, sizeof (labelv));
+
+ p11_buffer_uninit (&buffer);
+}
+
+static void
+test_mechanism_type_array_value (void)
+{
+ p11_buffer buffer;
+ CK_MECHANISM_TYPE mechs[] = { CKM_RSA_PKCS, CKM_DSA, CKM_SHA256_RSA_PKCS };
+ CK_MECHANISM_TYPE val[3];
+ CK_ULONG val_size;
+ size_t offset = 0, offset2;
+ bool ret;
+
+ p11_buffer_init (&buffer, 0);
+
+ p11_rpc_buffer_add_mechanism_type_array_value(&buffer, mechs, sizeof(mechs));
+ assert (!p11_buffer_failed (&buffer));
+
+ offset2 = offset;
+ ret = p11_rpc_buffer_get_mechanism_type_array_value(&buffer, &offset, NULL, &val_size);
+ assert_num_eq (true, ret);
+
+ offset = offset2;
+ ret = p11_rpc_buffer_get_mechanism_type_array_value(&buffer, &offset, val, &val_size);
+ assert_num_eq (true, ret);
+ assert_num_eq (val[0], CKM_RSA_PKCS);
+ assert_num_eq (val[1], CKM_DSA);
+ assert_num_eq (val[2], CKM_SHA256_RSA_PKCS);
+
+ p11_buffer_uninit (&buffer);
+}
+
+static void
+test_date_value (void)
+{
+ p11_buffer buffer;
+ CK_DATE date, val;
+ size_t offset = 0;
+ CK_ULONG val_size;
+ bool ret;
+
+ memcpy (date.year, "2017", 4);
+ memcpy (date.month, "05", 2);
+ memcpy (date.day, "16", 2);
+
+ p11_buffer_init (&buffer, 0);
+
+ p11_rpc_buffer_add_date_value(&buffer, &date, sizeof(date));
+ assert (!p11_buffer_failed (&buffer));
+
+ ret = p11_rpc_buffer_get_date_value(&buffer, &offset, &val, &val_size);
+ assert_num_eq (true, ret);
+
+ assert (memcmp (val.year, date.year, 4) == 0);
+ assert (memcmp (val.month, date.month, 2) == 0);
+ assert (memcmp (val.day, date.day, 2) == 0);
+
+ p11_buffer_uninit (&buffer);
+}
+
+static void
+test_byte_array_value (void)
+{
+ p11_buffer buffer;
+ unsigned char bytes[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F };
+
+ unsigned char val[32];
+ size_t offset = 0;
+ CK_ULONG val_size;
+ bool ret;
+
+ p11_buffer_init (&buffer, 0);
+
+ p11_rpc_buffer_add_byte_array_value(&buffer, bytes, sizeof(bytes));
+ assert (!p11_buffer_failed (&buffer));
+
+ ret = p11_rpc_buffer_get_byte_array_value(&buffer, &offset, val, &val_size);
+ assert_num_eq (true, ret);
+
+ assert_num_eq (bytes[0], val[0]);
+
+ p11_buffer_uninit (&buffer);
+}
+
static p11_virtual base;
static unsigned int rpc_initialized = 0;
@@ -1036,6 +1251,12 @@ main (int argc,
p11_test (test_byte_array_null, "/rpc/byte-array-null");
p11_test (test_byte_array_too_long, "/rpc/byte-array-too-long");
p11_test (test_byte_array_static, "/rpc/byte-array-static");
+ p11_test (test_byte_value, "/rpc/byte-value");
+ p11_test (test_ulong_value, "/rpc/ulong-value");
+ p11_test (test_attribute_array_value, "/rpc/attribute-array-value");
+ p11_test (test_mechanism_type_array_value, "/rpc/mechanism-type-array-value");
+ p11_test (test_date_value, "/rpc/date-value");
+ p11_test (test_byte_array_value, "/rpc/byte-array-value");
p11_test (test_initialize_fails_on_client, "/rpc/initialize-fails-on-client");
p11_test (test_initialize_fails_on_server, "/rpc/initialize-fails-on-server");