]> granicus.if.org Git - p11-kit/commitdiff
rpc: Convert mechanism parameters for portability
authorDaiki Ueno <dueno@redhat.com>
Tue, 23 May 2017 09:51:33 +0000 (11:51 +0200)
committerDaiki Ueno <ueno@gnu.org>
Wed, 24 May 2017 09:27:28 +0000 (11:27 +0200)
This is similar to commit ba49b85e, but for mechanism parameters.

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 3521dddee46ae093f5ca7787a624fc0138252294..0dd45255b1aa4315c146445d4201b5ed590eda30 100644 (file)
@@ -379,143 +379,6 @@ proto_read_ulong_array (p11_rpc_message *msg, CK_ULONG_PTR arr,
        return p11_buffer_failed (msg->input) ? PARSE_ERROR : CKR_OK;
 }
 
-/* Used to override the supported mechanisms in tests */
-CK_MECHANISM_TYPE *p11_rpc_mechanisms_override_supported = NULL;
-
-static bool
-mechanism_has_sane_parameters (CK_MECHANISM_TYPE type)
-{
-       int i;
-
-       /* This can be set from tests, to override default set of supported */
-       if (p11_rpc_mechanisms_override_supported) {
-               for (i = 0; p11_rpc_mechanisms_override_supported[i] != 0; i++) {
-                       if (p11_rpc_mechanisms_override_supported[i] == type)
-                               return true;
-               }
-
-               return false;
-       }
-
-       /* This list is incomplete */
-       switch (type) {
-       case CKM_RSA_PKCS_OAEP:
-       case CKM_RSA_PKCS_PSS:
-               return true;
-       default:
-               return false;
-       }
-}
-
-static bool
-mechanism_has_no_parameters (CK_MECHANISM_TYPE mech)
-{
-       /* This list is incomplete */
-
-       switch (mech) {
-       case CKM_RSA_PKCS_KEY_PAIR_GEN:
-       case CKM_RSA_X9_31_KEY_PAIR_GEN:
-       case CKM_RSA_PKCS:
-       case CKM_RSA_9796:
-       case CKM_RSA_X_509:
-       case CKM_RSA_X9_31:
-       case CKM_MD2_RSA_PKCS:
-       case CKM_MD5_RSA_PKCS:
-       case CKM_SHA1_RSA_PKCS:
-       case CKM_SHA256_RSA_PKCS:
-       case CKM_SHA384_RSA_PKCS:
-       case CKM_SHA512_RSA_PKCS:
-       case CKM_RIPEMD128_RSA_PKCS:
-       case CKM_RIPEMD160_RSA_PKCS:
-       case CKM_SHA1_RSA_X9_31:
-       case CKM_DSA_KEY_PAIR_GEN:
-       case CKM_DSA_PARAMETER_GEN:
-       case CKM_DSA:
-       case CKM_DSA_SHA1:
-       case CKM_FORTEZZA_TIMESTAMP:
-       case CKM_EC_KEY_PAIR_GEN:
-       case CKM_ECDSA:
-       case CKM_ECDSA_SHA1:
-       case CKM_DH_PKCS_KEY_PAIR_GEN:
-       case CKM_DH_PKCS_PARAMETER_GEN:
-       case CKM_X9_42_DH_KEY_PAIR_GEN:
-       case CKM_X9_42_DH_PARAMETER_GEN:
-       case CKM_KEA_KEY_PAIR_GEN:
-       case CKM_GENERIC_SECRET_KEY_GEN:
-       case CKM_RC2_KEY_GEN:
-       case CKM_RC4_KEY_GEN:
-       case CKM_RC4:
-       case CKM_RC5_KEY_GEN:
-       case CKM_AES_KEY_GEN:
-       case CKM_AES_ECB:
-       case CKM_AES_MAC:
-       case CKM_DES_KEY_GEN:
-       case CKM_DES2_KEY_GEN:
-       case CKM_DES3_KEY_GEN:
-       case CKM_CDMF_KEY_GEN:
-       case CKM_CAST_KEY_GEN:
-       case CKM_CAST3_KEY_GEN:
-       case CKM_CAST128_KEY_GEN:
-       case CKM_IDEA_KEY_GEN:
-       case CKM_SSL3_PRE_MASTER_KEY_GEN:
-       case CKM_TLS_PRE_MASTER_KEY_GEN:
-       case CKM_SKIPJACK_KEY_GEN:
-       case CKM_BATON_KEY_GEN:
-       case CKM_JUNIPER_KEY_GEN:
-       case CKM_RC2_ECB:
-       case CKM_DES_ECB:
-       case CKM_DES3_ECB:
-       case CKM_CDMF_ECB:
-       case CKM_CAST_ECB:
-       case CKM_CAST3_ECB:
-       case CKM_CAST128_ECB:
-       case CKM_RC5_ECB:
-       case CKM_IDEA_ECB:
-       case CKM_RC2_MAC:
-       case CKM_DES_MAC:
-       case CKM_DES3_MAC:
-       case CKM_CDMF_MAC:
-       case CKM_CAST_MAC:
-       case CKM_CAST3_MAC:
-       case CKM_RC5_MAC:
-       case CKM_IDEA_MAC:
-       case CKM_SSL3_MD5_MAC:
-       case CKM_SSL3_SHA1_MAC:
-       case CKM_SKIPJACK_WRAP:
-       case CKM_BATON_WRAP:
-       case CKM_JUNIPER_WRAP:
-       case CKM_MD2:
-       case CKM_MD2_HMAC:
-       case CKM_MD5:
-       case CKM_MD5_HMAC:
-       case CKM_SHA_1:
-       case CKM_SHA_1_HMAC:
-       case CKM_SHA256:
-       case CKM_SHA256_HMAC:
-       case CKM_SHA384:
-       case CKM_SHA384_HMAC:
-       case CKM_SHA512:
-       case CKM_SHA512_HMAC:
-       case CKM_FASTHASH:
-       case CKM_RIPEMD128:
-       case CKM_RIPEMD128_HMAC:
-       case CKM_RIPEMD160:
-       case CKM_RIPEMD160_HMAC:
-       case CKM_KEY_WRAP_LYNKS:
-               return true;
-       default:
-               return false;
-       };
-}
-
-static bool
-mechanism_is_supported (CK_MECHANISM_TYPE mech)
-{
-       if (mechanism_has_no_parameters (mech) ||
-           mechanism_has_sane_parameters (mech))
-               return true;
-       return false;
-}
 static void
 mechanism_list_purge (CK_MECHANISM_TYPE_PTR mechs,
                       CK_ULONG *n_mechs)
@@ -526,7 +389,7 @@ mechanism_list_purge (CK_MECHANISM_TYPE_PTR mechs,
        assert (n_mechs != NULL);
 
        for (i = 0; i < (int)(*n_mechs); ++i) {
-               if (!mechanism_is_supported (mechs[i])) {
+               if (!p11_rpc_mechanism_is_supported (mechs[i])) {
 
                        /* Remove the mechanism from the list */
                        memmove (&mechs[i], &mechs[i + 1],
@@ -549,8 +412,8 @@ proto_write_mechanism (p11_rpc_message *msg,
        /* Make sure this is in the right order */
        assert (!msg->signature || p11_rpc_message_verify_part (msg, "M"));
 
-       /* The mechanism type */
-       p11_rpc_buffer_add_uint32 (msg->output, mech->mechanism);
+       if (!p11_rpc_mechanism_is_supported (mech->mechanism))
+               return CKR_MECHANISM_INVALID;
 
        /*
         * PKCS#11 mechanism parameters are not easy to serialize. They're
@@ -564,13 +427,7 @@ proto_write_mechanism (p11_rpc_message *msg,
         * pointing to garbage if they don't think it's going to be used.
         */
 
-       if (mechanism_has_no_parameters (mech->mechanism))
-               p11_rpc_buffer_add_byte_array (msg->output, NULL, 0);
-       else if (mechanism_has_sane_parameters (mech->mechanism))
-               p11_rpc_buffer_add_byte_array (msg->output, mech->pParameter,
-                                              mech->ulParameterLen);
-       else
-               return CKR_MECHANISM_INVALID;
+       p11_rpc_buffer_add_mechanism (msg->output, mech);
 
        return p11_buffer_failed (msg->output) ? CKR_HOST_MEMORY : CKR_OK;
 }
@@ -746,7 +603,7 @@ proto_read_sesssion_info (p11_rpc_message *msg,
                { _ret = CKR_HOST_MEMORY; goto _cleanup; }
 
 #define IN_MECHANISM_TYPE(val) \
-       if(!mechanism_is_supported (val)) \
+       if(!p11_rpc_mechanism_is_supported (val)) \
                { _ret = CKR_MECHANISM_INVALID; goto _cleanup; } \
        if (!p11_rpc_message_write_ulong (&_msg, val)) \
                { _ret = CKR_HOST_MEMORY; goto _cleanup; }
index ae6af2f06d52a0f1d8343641d2acc14199ea5e67..32f5a458cacdfcf2f2b08ee7d546ad45ec5a7421 100644 (file)
@@ -1240,3 +1240,345 @@ p11_rpc_buffer_get_attribute (p11_buffer *buffer,
        attr->type = type;
        return true;
 }
+
+/* Used to override the supported mechanisms in tests */
+CK_MECHANISM_TYPE *p11_rpc_mechanisms_override_supported = NULL;
+
+typedef struct {
+       CK_MECHANISM_TYPE type;
+       p11_rpc_value_encoder encode;
+       p11_rpc_value_decoder decode;
+} p11_rpc_mechanism_serializer;
+
+void
+p11_rpc_buffer_add_rsa_pkcs_pss_mechanism_value (p11_buffer *buffer,
+                                                const void *value,
+                                                CK_ULONG value_length)
+{
+       CK_RSA_PKCS_PSS_PARAMS params;
+
+       /* Check if value can be converted to CK_RSA_PKCS_PSS_PARAMS. */
+       if (value_length != sizeof (CK_RSA_PKCS_PSS_PARAMS)) {
+               p11_buffer_fail (buffer);
+               return;
+       }
+
+       memcpy (&params, value, value_length);
+
+       /* Check if params.hashAlg, params.mgf, and params.sLen can be
+        * converted to uint64_t. */
+       if (params.hashAlg > UINT64_MAX || params.mgf > UINT64_MAX ||
+           params.sLen > UINT64_MAX) {
+               p11_buffer_fail (buffer);
+               return;
+       }
+
+       p11_rpc_buffer_add_uint64 (buffer, params.hashAlg);
+       p11_rpc_buffer_add_uint64 (buffer, params.mgf);
+       p11_rpc_buffer_add_uint64 (buffer, params.sLen);
+}
+
+bool
+p11_rpc_buffer_get_rsa_pkcs_pss_mechanism_value (p11_buffer *buffer,
+                                                size_t *offset,
+                                                void *value,
+                                                CK_ULONG *value_length)
+{
+       uint64_t val[3];
+
+       if (!p11_rpc_buffer_get_uint64 (buffer, offset, &val[0]))
+               return false;
+       if (!p11_rpc_buffer_get_uint64 (buffer, offset, &val[1]))
+               return false;
+       if (!p11_rpc_buffer_get_uint64 (buffer, offset, &val[2]))
+               return false;
+
+       if (value) {
+               CK_RSA_PKCS_PSS_PARAMS params;
+
+               params.hashAlg = val[0];
+               params.mgf = val[1];
+               params.sLen = val[2];
+
+               memcpy (value, &params, sizeof (CK_RSA_PKCS_PSS_PARAMS));
+       }
+
+       if (value_length)
+               *value_length = sizeof (CK_RSA_PKCS_PSS_PARAMS);
+
+       return true;
+}
+
+void
+p11_rpc_buffer_add_rsa_pkcs_oaep_mechanism_value (p11_buffer *buffer,
+                                                 const void *value,
+                                                 CK_ULONG value_length)
+{
+       CK_RSA_PKCS_OAEP_PARAMS params;
+
+       /* Check if value can be converted to CK_RSA_PKCS_OAEP_PARAMS. */
+       if (value_length != sizeof (CK_RSA_PKCS_OAEP_PARAMS)) {
+               p11_buffer_fail (buffer);
+               return;
+       }
+
+       memcpy (&params, value, value_length);
+
+       /* Check if params.hashAlg, params.mgf, and params.source can be
+        * converted to uint64_t. */
+       if (params.hashAlg > UINT64_MAX || params.mgf > UINT64_MAX ||
+           params.source > UINT64_MAX) {
+               p11_buffer_fail (buffer);
+               return;
+       }
+
+       p11_rpc_buffer_add_uint64 (buffer, params.hashAlg);
+       p11_rpc_buffer_add_uint64 (buffer, params.mgf);
+       p11_rpc_buffer_add_uint64 (buffer, params.source);
+
+       /* parmas.pSourceData can only be an array of CK_BYTE or
+        * NULL */
+       p11_rpc_buffer_add_byte_array (buffer,
+                                      (unsigned char *)params.pSourceData,
+                                      params.ulSourceDataLen);
+}
+
+bool
+p11_rpc_buffer_get_rsa_pkcs_oaep_mechanism_value (p11_buffer *buffer,
+                                                 size_t *offset,
+                                                 void *value,
+                                                 CK_ULONG *value_length)
+{
+       uint64_t val[3];
+       const unsigned char *data;
+       size_t len;
+
+       if (!p11_rpc_buffer_get_uint64 (buffer, offset, &val[0]))
+               return false;
+       if (!p11_rpc_buffer_get_uint64 (buffer, offset, &val[1]))
+               return false;
+       if (!p11_rpc_buffer_get_uint64 (buffer, offset, &val[2]))
+               return false;
+       if (!p11_rpc_buffer_get_byte_array (buffer, offset, &data, &len))
+               return false;
+
+       if (value) {
+               CK_RSA_PKCS_OAEP_PARAMS params;
+
+               params.hashAlg = val[0];
+               params.mgf = val[1];
+               params.source = val[2];
+               params.pSourceData = (void *) data;
+               params.ulSourceDataLen = len;
+
+               memcpy (value, &params, sizeof (CK_RSA_PKCS_OAEP_PARAMS));
+       }
+
+       if (value_length)
+               *value_length = sizeof (CK_RSA_PKCS_OAEP_PARAMS);
+
+       return true;
+}
+
+static p11_rpc_mechanism_serializer p11_rpc_mechanism_serializers[] = {
+       { CKM_RSA_PKCS_PSS, p11_rpc_buffer_add_rsa_pkcs_pss_mechanism_value, p11_rpc_buffer_get_rsa_pkcs_pss_mechanism_value },
+       { CKM_RSA_PKCS_OAEP, p11_rpc_buffer_add_rsa_pkcs_oaep_mechanism_value, p11_rpc_buffer_get_rsa_pkcs_oaep_mechanism_value }
+};
+
+static p11_rpc_mechanism_serializer p11_rpc_byte_array_mechanism_serializer = {
+       0, p11_rpc_buffer_add_byte_array_value, p11_rpc_buffer_get_byte_array_value
+};
+
+static bool
+mechanism_has_sane_parameters (CK_MECHANISM_TYPE type)
+{
+       int i;
+
+       /* This can be set from tests, to override default set of supported */
+       if (p11_rpc_mechanisms_override_supported) {
+               for (i = 0; p11_rpc_mechanisms_override_supported[i] != 0; i++) {
+                       if (p11_rpc_mechanisms_override_supported[i] == type)
+                               return true;
+               }
+
+               return false;
+       }
+
+       for (i = 0; i < ELEMS(p11_rpc_mechanism_serializers); i++) {
+               if (p11_rpc_mechanism_serializers[i].type == type)
+                       return true;
+       }
+
+       return false;
+}
+
+static bool
+mechanism_has_no_parameters (CK_MECHANISM_TYPE mech)
+{
+       /* This list is incomplete */
+
+       switch (mech) {
+       case CKM_RSA_PKCS_KEY_PAIR_GEN:
+       case CKM_RSA_X9_31_KEY_PAIR_GEN:
+       case CKM_RSA_PKCS:
+       case CKM_RSA_9796:
+       case CKM_RSA_X_509:
+       case CKM_RSA_X9_31:
+       case CKM_MD2_RSA_PKCS:
+       case CKM_MD5_RSA_PKCS:
+       case CKM_SHA1_RSA_PKCS:
+       case CKM_SHA256_RSA_PKCS:
+       case CKM_SHA384_RSA_PKCS:
+       case CKM_SHA512_RSA_PKCS:
+       case CKM_RIPEMD128_RSA_PKCS:
+       case CKM_RIPEMD160_RSA_PKCS:
+       case CKM_SHA1_RSA_X9_31:
+       case CKM_DSA_KEY_PAIR_GEN:
+       case CKM_DSA_PARAMETER_GEN:
+       case CKM_DSA:
+       case CKM_DSA_SHA1:
+       case CKM_FORTEZZA_TIMESTAMP:
+       case CKM_EC_KEY_PAIR_GEN:
+       case CKM_ECDSA:
+       case CKM_ECDSA_SHA1:
+       case CKM_DH_PKCS_KEY_PAIR_GEN:
+       case CKM_DH_PKCS_PARAMETER_GEN:
+       case CKM_X9_42_DH_KEY_PAIR_GEN:
+       case CKM_X9_42_DH_PARAMETER_GEN:
+       case CKM_KEA_KEY_PAIR_GEN:
+       case CKM_GENERIC_SECRET_KEY_GEN:
+       case CKM_RC2_KEY_GEN:
+       case CKM_RC4_KEY_GEN:
+       case CKM_RC4:
+       case CKM_RC5_KEY_GEN:
+       case CKM_AES_KEY_GEN:
+       case CKM_AES_ECB:
+       case CKM_AES_MAC:
+       case CKM_DES_KEY_GEN:
+       case CKM_DES2_KEY_GEN:
+       case CKM_DES3_KEY_GEN:
+       case CKM_CDMF_KEY_GEN:
+       case CKM_CAST_KEY_GEN:
+       case CKM_CAST3_KEY_GEN:
+       case CKM_CAST128_KEY_GEN:
+       case CKM_IDEA_KEY_GEN:
+       case CKM_SSL3_PRE_MASTER_KEY_GEN:
+       case CKM_TLS_PRE_MASTER_KEY_GEN:
+       case CKM_SKIPJACK_KEY_GEN:
+       case CKM_BATON_KEY_GEN:
+       case CKM_JUNIPER_KEY_GEN:
+       case CKM_RC2_ECB:
+       case CKM_DES_ECB:
+       case CKM_DES3_ECB:
+       case CKM_CDMF_ECB:
+       case CKM_CAST_ECB:
+       case CKM_CAST3_ECB:
+       case CKM_CAST128_ECB:
+       case CKM_RC5_ECB:
+       case CKM_IDEA_ECB:
+       case CKM_RC2_MAC:
+       case CKM_DES_MAC:
+       case CKM_DES3_MAC:
+       case CKM_CDMF_MAC:
+       case CKM_CAST_MAC:
+       case CKM_CAST3_MAC:
+       case CKM_RC5_MAC:
+       case CKM_IDEA_MAC:
+       case CKM_SSL3_MD5_MAC:
+       case CKM_SSL3_SHA1_MAC:
+       case CKM_SKIPJACK_WRAP:
+       case CKM_BATON_WRAP:
+       case CKM_JUNIPER_WRAP:
+       case CKM_MD2:
+       case CKM_MD2_HMAC:
+       case CKM_MD5:
+       case CKM_MD5_HMAC:
+       case CKM_SHA_1:
+       case CKM_SHA_1_HMAC:
+       case CKM_SHA256:
+       case CKM_SHA256_HMAC:
+       case CKM_SHA384:
+       case CKM_SHA384_HMAC:
+       case CKM_SHA512:
+       case CKM_SHA512_HMAC:
+       case CKM_FASTHASH:
+       case CKM_RIPEMD128:
+       case CKM_RIPEMD128_HMAC:
+       case CKM_RIPEMD160:
+       case CKM_RIPEMD160_HMAC:
+       case CKM_KEY_WRAP_LYNKS:
+               return true;
+       default:
+               return false;
+       };
+}
+
+bool
+p11_rpc_mechanism_is_supported (CK_MECHANISM_TYPE mech)
+{
+       if (mechanism_has_no_parameters (mech) ||
+           mechanism_has_sane_parameters (mech))
+               return true;
+       return false;
+}
+
+void
+p11_rpc_buffer_add_mechanism (p11_buffer *buffer, const CK_MECHANISM *mech)
+{
+       p11_rpc_mechanism_serializer *serializer = NULL;
+       size_t i;
+
+       /* The mechanism type */
+       p11_rpc_buffer_add_uint32 (buffer, mech->mechanism);
+
+       if (mechanism_has_no_parameters (mech->mechanism)) {
+               p11_rpc_buffer_add_byte_array (buffer, NULL, 0);
+               return;
+       }
+
+       assert (mechanism_has_sane_parameters (mech->mechanism));
+
+       for (i = 0; i < ELEMS (p11_rpc_mechanism_serializers); i++) {
+               if (p11_rpc_mechanism_serializers[i].type == mech->mechanism) {
+                       serializer = &p11_rpc_mechanism_serializers[i];
+                       break;
+               }
+       }
+
+       if (serializer == NULL)
+               serializer = &p11_rpc_byte_array_mechanism_serializer;
+
+       serializer->encode (buffer, mech->pParameter, mech->ulParameterLen);
+}
+
+bool
+p11_rpc_buffer_get_mechanism (p11_buffer *buffer,
+                             size_t *offset,
+                             CK_MECHANISM *mech)
+{
+       uint32_t mechanism;
+       p11_rpc_mechanism_serializer *serializer = NULL;
+       size_t i;
+
+       /* The mechanism type */
+       if (!p11_rpc_buffer_get_uint32 (buffer, offset, &mechanism))
+               return false;
+
+       mech->mechanism = mechanism;
+
+       for (i = 0; i < ELEMS (p11_rpc_mechanism_serializers); i++) {
+               if (p11_rpc_mechanism_serializers[i].type == mech->mechanism) {
+                       serializer = &p11_rpc_mechanism_serializers[i];
+                       break;
+               }
+       }
+
+       if (serializer == NULL)
+               serializer = &p11_rpc_byte_array_mechanism_serializer;
+
+       if (!serializer->decode (buffer, offset,
+                                mech->pParameter, &mech->ulParameterLen))
+               return false;
+
+       return true;
+}
index 5c81c1c4b6a2a802ab957dc45abb2b20a29b385c..989bbc0cda665cd5fe2ada04e101c74331694f99 100644 (file)
@@ -444,4 +444,35 @@ bool             p11_rpc_buffer_get_byte_array_value     (p11_buffer *buffer,
                                                          void *value,
                                                          CK_ULONG *value_length);
 
+bool             p11_rpc_mechanism_is_supported          (CK_MECHANISM_TYPE mech);
+
+void             p11_rpc_buffer_add_mechanism            (p11_buffer *buffer,
+                                                         const CK_MECHANISM *mech);
+
+bool             p11_rpc_buffer_get_mechanism            (p11_buffer *buffer,
+                                                         size_t *offset,
+                                                         CK_MECHANISM *mech);
+
+void             p11_rpc_buffer_add_rsa_pkcs_pss_mechanism_value
+                                                         (p11_buffer *buffer,
+                                                         const void *value,
+                                                         CK_ULONG value_length);
+
+bool             p11_rpc_buffer_get_rsa_pkcs_pss_mechanism_value
+                                                         (p11_buffer *buffer,
+                                                         size_t *offset,
+                                                         void *value,
+                                                         CK_ULONG *value_length);
+
+void             p11_rpc_buffer_add_rsa_pkcs_oaep_mechanism_value
+                                                          (p11_buffer *buffer,
+                                                          const void *value,
+                                                          CK_ULONG value_length);
+
+bool             p11_rpc_buffer_get_rsa_pkcs_oaep_mechanism_value
+                                                          (p11_buffer *buffer,
+                                                          size_t *offset,
+                                                          void *value,
+                                                          CK_ULONG *value_length);
+
 #endif /* _RPC_MESSAGE_H */
index 1eebf1bf02d713580acfd059c02ff9ee938435f9..47beed0d1ac2e576b7ca9b69fb3b6730a127c114 100644 (file)
@@ -400,9 +400,8 @@ static CK_RV
 proto_read_mechanism (p11_rpc_message *msg,
                       CK_MECHANISM_PTR mech)
 {
-       const unsigned char *data;
-       uint32_t value;
-       size_t n_data;
+       size_t offset;
+       CK_MECHANISM temp;
 
        assert (msg != NULL);
        assert (mech != NULL);
@@ -411,17 +410,31 @@ proto_read_mechanism (p11_rpc_message *msg,
        /* Make sure this is in the right order */
        assert (!msg->signature || p11_rpc_message_verify_part (msg, "M"));
 
-       /* The mechanism type */
-       if (!p11_rpc_buffer_get_uint32 (msg->input, &msg->parsed, &value))
+       /* Check the length needed to store the parameter */
+       memset (&temp, 0, sizeof (temp));
+       offset = msg->parsed;
+       if (!p11_rpc_buffer_get_mechanism (msg->input, &offset, &temp)) {
+               msg->parsed = offset;
                return PARSE_ERROR;
+       }
 
-       /* The mechanism data */
-       if (!p11_rpc_buffer_get_byte_array (msg->input, &msg->parsed, &data, &n_data))
+       mech->mechanism = temp.mechanism;
+
+       /* The mechanism doesn't require parameter */
+       if (temp.ulParameterLen == 0) {
+               mech->pParameter = NULL;
+               mech->ulParameterLen = 0;
+               msg->parsed = offset;
+               return CKR_OK;
+       }
+
+       /* Actually retrieve the parameter */
+       mech->pParameter = p11_rpc_message_alloc_extra (msg, temp.ulParameterLen);
+       if (!p11_rpc_buffer_get_mechanism (msg->input, &msg->parsed, mech))
                return PARSE_ERROR;
 
-       mech->mechanism = value;
-       mech->pParameter = (CK_VOID_PTR)data;
-       mech->ulParameterLen = n_data;
+       assert (msg->parsed == offset);
+
        return CKR_OK;
 }
 
index c6490bf510d5fc6bb1e47c48a4c706c94eacb1d4..a20e939ee4590fb9f8875c8dc7fb85adeced0d91 100644 (file)
@@ -55,6 +55,8 @@
 #include <stdio.h>
 #include <stdlib.h>
 
+#define ELEMS(x) (sizeof (x) / sizeof (x[0]))
+
 static void
 test_new_free (void)
 {
@@ -567,6 +569,69 @@ test_byte_array_value (void)
        p11_buffer_uninit (&buffer);
 }
 
+static void
+test_mechanism_value (void)
+{
+       p11_buffer buffer;
+       CK_MECHANISM_TYPE *mechanisms;
+       CK_RSA_PKCS_PSS_PARAMS pss_params = {
+               CKM_SHA256,
+               CKG_MGF1_SHA256,
+               32
+       };
+       CK_RSA_PKCS_OAEP_PARAMS oaep_params = {
+               CKM_SHA384,
+               CKG_MGF1_SHA384,
+               0,
+               NULL,
+               0
+       };
+       CK_MECHANISM mechs[] = {
+               { CKM_RSA_PKCS_PSS, &pss_params, sizeof (pss_params) },
+               { CKM_RSA_PKCS_OAEP, &oaep_params, sizeof (oaep_params) }
+       };
+
+       CK_MECHANISM val;
+       size_t offset = 0;
+       bool ret;
+       size_t i;
+
+       mechanisms = p11_rpc_mechanisms_override_supported;
+       p11_rpc_mechanisms_override_supported = NULL;
+
+       p11_buffer_init (&buffer, 0);
+
+       for (i = 0; i < ELEMS (mechs); i++) {
+               size_t offset2 = offset;
+
+               p11_rpc_buffer_add_mechanism (&buffer, &mechs[i]);
+               assert (!p11_buffer_failed (&buffer));
+
+               memset (&val, 0, sizeof (val));
+               ret = p11_rpc_buffer_get_mechanism (&buffer, &offset, &val);
+               assert_num_eq (true, ret);
+               assert_num_eq (mechs[i].mechanism, val.mechanism);
+               assert_ptr_eq (NULL, val.pParameter);
+               assert_num_eq (mechs[i].ulParameterLen, val.ulParameterLen);
+
+               val.pParameter = malloc (val.ulParameterLen);
+               assert_ptr_not_null (val.pParameter);
+
+               offset = offset2;
+               ret = p11_rpc_buffer_get_mechanism (&buffer, &offset, &val);
+               assert_num_eq (true, ret);
+               assert_num_eq (mechs[i].mechanism, val.mechanism);
+               assert_num_eq (mechs[i].ulParameterLen, val.ulParameterLen);
+               assert (memcmp (val.pParameter, mechs[i].pParameter, val.ulParameterLen) == 0);
+
+               free (val.pParameter);
+       }
+
+       p11_buffer_uninit (&buffer);
+
+       p11_rpc_mechanisms_override_supported = mechanisms;
+}
+
 static p11_virtual base;
 static unsigned int rpc_initialized = 0;
 
@@ -1257,6 +1322,7 @@ main (int argc,
        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_mechanism_value, "/rpc/mechanism-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");