]> granicus.if.org Git - p11-kit/commitdiff
rpc: Convert attribute value for portability
authorDaiki Ueno <dueno@redhat.com>
Thu, 11 May 2017 13:26:36 +0000 (15:26 +0200)
committerDaiki Ueno <ueno@gnu.org>
Mon, 22 May 2017 15:19:20 +0000 (17:19 +0200)
When using the RPC across multiple architectures, where data models
are different, say LP64 vs ILP32, there can be unwanted truncation of
attribute values.

This patch converts the values into portable format for the known
attributes.

Co-authored-by: Nikos Mavrogiannopoulos <nmav@redhat.com>
p11-kit/rpc-client.c
p11-kit/rpc-message.c
p11-kit/rpc-message.h
p11-kit/rpc-server.c
p11-kit/test-rpc.c

index c69dcfdb4098a0ece4e3205ff37047c7f9fc61da..3521dddee46ae093f5ca7787a624fc0138252294 100644 (file)
@@ -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))
index d1b491d910ecec2721ecc27574e03336180572e5..25d8a7beceec142e73285d4cf1d66898eda01a11 100644 (file)
@@ -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;
+}
index 982709720faa179511992420599e90ad68ccf660..5c81c1c4b6a2a802ab957dc45abb2b20a29b385c 100644 (file)
@@ -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 */
index 071064f2b6847c36bf8c1a93f989cc4652aa26c4..dec9b0bf9eb3b30f105a9a637c496eb5098bb21b 100644 (file)
@@ -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;
index c9f8333f50223e5810632d39ca05c22f304ade8e..c6490bf510d5fc6bb1e47c48a4c706c94eacb1d4 100644 (file)
@@ -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");