diff options
-rw-r--r-- | p11-kit/rpc-client.c | 63 | ||||
-rw-r--r-- | p11-kit/rpc-message.c | 509 | ||||
-rw-r--r-- | p11-kit/rpc-message.h | 77 | ||||
-rw-r--r-- | p11-kit/rpc-server.c | 35 | ||||
-rw-r--r-- | p11-kit/test-rpc.c | 223 |
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"); |