blob: f8b5bf9101651a94fc85e8140b6fa1a88bf334c4 [file] [log] [blame]
// SPDX-License-Identifier: BSD-2-Clause
/*
* Copyright (c) 2017-2020, Linaro Limited
*/
#include <ck_debug.h>
#include <inttypes.h>
#include <pkcs11.h>
#include <pkcs11_ta.h>
#include <stdlib.h>
#include <string.h>
#include "ck_helpers.h"
#include "local_utils.h"
#include "serializer.h"
#include "serialize_ck.h"
/*
* Serialization and de-serialization logic
*
* Cryptoki API works in a way that user application uses memory references
* in object attributes description. TA can be invoked with only a small set
* of possible references to caller memory. Thus a Cryptoki object, made of
* data and pointers to data, is reassembled into a byte array where each
* attribute info (ID, value size, value) is appended with byte alignment. This
* so-called serialized object can be passed through the TA API.
*
* Initial entry to PKCS11 TA uses serialize_ck_attributes(). When TA
* returns with updated serialized data to be passed back to caller, we call
* deserialize_ck_attributes().
*
* Special handling is performed for CK_ULONG passing which may be either 32
* bits or 64 bits depending on target device architecture. In TA interface
* this is handled as unsigned 32 bit data type.
*
* When user application is querying attributes in example with
* C_GetAttributeValue() user may allocate larger value buffers. During entry
* to TA shared buffer is allocated in serialize_ck_attributes() based on
* caller's arguments. For each attribute TA verifies if value fits in
* the buffer and if it does, value is returned. Value size in buffer is
* updated to indicate real size of the value. When call is returned back to
* REE deserialize_ck_attributes() is invoked and then both input arguments and
* serialization buffer are used to return values to caller. Provided input
* arguments from caller are used to determine serialization buffer structure
* and then actual values and value sizes are then decoded from serialization
* buffer and returned to caller in caller's allocated memory.
*/
/*
* Generic way of serializing CK keys, certificates, mechanism parameters, ...
* In cryptoki 2.40 parameters are almost all packaged as structure below:
*/
struct ck_ref {
CK_ULONG id;
CK_BYTE_PTR ptr;
CK_ULONG len;
};
/*
* This is for attributes that contains data memory indirections.
* In other words, an attributes that defines a list of attributes.
* They are identified from the attribute type CKA_...
*
* @obj - ref used to track the serial object being created
* @attribute - pointer to a structure aligned of the CK_ATTRIBUTE struct
*/
static CK_RV serialize_indirect_attribute(struct serializer *obj,
CK_ATTRIBUTE_PTR attribute)
{
CK_ATTRIBUTE_PTR attr = NULL;
CK_ULONG count = 0;
CK_RV rv = CKR_GENERAL_ERROR;
struct serializer obj2 = { 0 };
switch (attribute->type) {
/* These are serialized each separately */
case CKA_DERIVE_TEMPLATE:
case CKA_WRAP_TEMPLATE:
case CKA_UNWRAP_TEMPLATE:
count = attribute->ulValueLen / sizeof(CK_ATTRIBUTE);
attr = (CK_ATTRIBUTE_PTR)attribute->pValue;
break;
default:
return CKR_NO_EVENT;
}
/* Create a serialized object for the content */
rv = serialize_ck_attributes(&obj2, attr, count);
if (rv)
return rv;
/*
* Append the created serialized object into target object:
* [attrib-id][byte-size][attributes-data]
*/
rv = serialize_32b(obj, attribute->type);
if (rv)
goto out;
rv = serialize_32b(obj, obj2.size);
if (rv)
goto out;
rv = serialize_buffer(obj, obj2.buffer, obj2.size);
if (rv)
goto out;
obj->item_count++;
out:
release_serial_object(&obj2);
return rv;
}
static CK_RV deserialize_indirect_attribute(struct pkcs11_attribute_head *obj,
CK_ATTRIBUTE_PTR attribute)
{
CK_ULONG count = 0;
CK_ATTRIBUTE_PTR attr = NULL;
switch (attribute->type) {
/* These are serialized each separately */
case CKA_DERIVE_TEMPLATE:
case CKA_WRAP_TEMPLATE:
case CKA_UNWRAP_TEMPLATE:
count = attribute->ulValueLen / sizeof(CK_ATTRIBUTE);
attr = (CK_ATTRIBUTE_PTR)attribute->pValue;
break;
default:
return CKR_GENERAL_ERROR;
}
return deserialize_ck_attributes(obj->data, attr, count);
}
static int ck_attr_is_ulong(CK_ATTRIBUTE_TYPE attribute_id)
{
switch (attribute_id) {
case CKA_CLASS:
case CKA_CERTIFICATE_TYPE:
case CKA_CERTIFICATE_CATEGORY:
case CKA_NAME_HASH_ALGORITHM:
case CKA_KEY_TYPE:
case CKA_HW_FEATURE_TYPE:
case CKA_MECHANISM_TYPE:
case CKA_KEY_GEN_MECHANISM:
case CKA_VALUE_LEN:
case CKA_MODULUS_BITS:
return true;
default:
return false;
}
}
static CK_RV serialize_ck_attribute(struct serializer *obj, CK_ATTRIBUTE *attr)
{
CK_MECHANISM_TYPE *type = NULL;
uint32_t pkcs11_size = 0;
uint32_t pkcs11_data32 = 0;
void *pkcs11_pdata = NULL;
uint32_t *mech_buf = NULL;
CK_RV rv = CKR_GENERAL_ERROR;
unsigned int n = 0;
unsigned int m = 0;
if (attr->type == PKCS11_UNDEFINED_ID)
return CKR_ATTRIBUTE_TYPE_INVALID;
switch (attr->type) {
case CKA_DERIVE_TEMPLATE:
case CKA_WRAP_TEMPLATE:
case CKA_UNWRAP_TEMPLATE:
return serialize_indirect_attribute(obj, attr);
case CKA_ALLOWED_MECHANISMS:
n = attr->ulValueLen / sizeof(CK_ULONG);
pkcs11_size = n * sizeof(uint32_t);
mech_buf = malloc(pkcs11_size);
if (!mech_buf)
return CKR_HOST_MEMORY;
type = attr->pValue;
for (m = 0; m < n; m++) {
mech_buf[m] = type[m];
if (mech_buf[m] == PKCS11_UNDEFINED_ID) {
rv = CKR_MECHANISM_INVALID;
goto out;
}
}
pkcs11_pdata = mech_buf;
break;
/* Attributes which data value do not need conversion (aside ulong) */
default:
pkcs11_pdata = attr->pValue;
if (!attr->pValue) {
pkcs11_size = 0;
} else if (ck_attr_is_ulong(attr->type)) {
CK_ULONG ck_ulong = 0;
if (attr->ulValueLen < sizeof(CK_ULONG))
return CKR_ATTRIBUTE_VALUE_INVALID;
memcpy(&ck_ulong, attr->pValue, sizeof(ck_ulong));
pkcs11_data32 = ck_ulong;
pkcs11_pdata = &pkcs11_data32;
pkcs11_size = sizeof(uint32_t);
} else {
pkcs11_size = attr->ulValueLen;
}
break;
}
rv = serialize_32b(obj, attr->type);
if (rv)
goto out;
rv = serialize_32b(obj, pkcs11_size);
if (rv)
goto out;
rv = serialize_buffer(obj, pkcs11_pdata, pkcs11_size);
if (rv)
goto out;
obj->item_count++;
out:
free(mech_buf);
return rv;
}
/* CK attribute reference arguments are list of attribute item */
CK_RV serialize_ck_attributes(struct serializer *obj,
CK_ATTRIBUTE_PTR attributes, CK_ULONG count)
{
CK_ULONG n = 0;
CK_RV rv = CKR_OK;
rv = init_serial_object(obj);
if (rv)
return rv;
for (n = 0; n < count; n++) {
rv = serialize_ck_attribute(obj, attributes + n);
if (rv)
break;
}
if (rv)
release_serial_object(obj);
else
finalize_serial_object(obj);
return rv;
}
static CK_RV deserialize_mecha_list(CK_MECHANISM_TYPE *dst, void *src,
size_t count)
{
char *ta_src = src;
size_t n = 0;
uint32_t mecha_id = 0;
for (n = 0; n < count; n++) {
memcpy(&mecha_id, ta_src + n * sizeof(mecha_id),
sizeof(mecha_id));
dst[n] = mecha_id;
}
return CKR_OK;
}
static CK_RV deserialize_ck_attribute(struct pkcs11_attribute_head *in,
uint8_t *data, CK_ATTRIBUTE_PTR out)
{
CK_ULONG ck_ulong = 0;
uint32_t pkcs11_data32 = 0;
CK_RV rv = CKR_OK;
out->type = in->id;
if (in->size == PKCS11_CK_UNAVAILABLE_INFORMATION) {
out->ulValueLen = CK_UNAVAILABLE_INFORMATION;
return CKR_OK;
}
if (!out->pValue && ck_attr_is_ulong(out->type)) {
out->ulValueLen = sizeof(CK_ULONG);
return CKR_OK;
}
if (out->ulValueLen < in->size) {
out->ulValueLen = in->size;
return CKR_OK;
}
if (!out->pValue)
return CKR_OK;
/* Specific ulong encoded as 32bit in PKCS11 TA API */
if (ck_attr_is_ulong(out->type)) {
if (out->ulValueLen < sizeof(CK_ULONG))
return CKR_ATTRIBUTE_VALUE_INVALID;
memcpy(&pkcs11_data32, data, sizeof(uint32_t));
if (out->type == CKA_KEY_GEN_MECHANISM &&
pkcs11_data32 == PKCS11_CK_UNAVAILABLE_INFORMATION)
ck_ulong = CK_UNAVAILABLE_INFORMATION;
else
ck_ulong = pkcs11_data32;
memcpy(out->pValue, &ck_ulong, sizeof(CK_ULONG));
out->ulValueLen = sizeof(CK_ULONG);
return CKR_OK;
}
switch (out->type) {
case CKA_DERIVE_TEMPLATE:
case CKA_WRAP_TEMPLATE:
case CKA_UNWRAP_TEMPLATE:
rv = deserialize_indirect_attribute(in, out->pValue);
break;
case CKA_ALLOWED_MECHANISMS:
rv = deserialize_mecha_list(out->pValue, data,
in->size / sizeof(uint32_t));
out->ulValueLen = in->size / sizeof(uint32_t) *
sizeof(CK_ULONG);
break;
/* Attributes which data value do not need conversion (aside ulong) */
default:
memcpy(out->pValue, data, in->size);
out->ulValueLen = in->size;
break;
}
return rv;
}
CK_RV deserialize_ck_attributes(uint8_t *in, CK_ATTRIBUTE_PTR attributes,
CK_ULONG count)
{
CK_ATTRIBUTE_PTR cur_attr = attributes;
CK_ULONG n = 0;
CK_RV rv = CKR_OK;
uint8_t *curr_head = in;
size_t len = 0;
curr_head += sizeof(struct pkcs11_object_head);
for (n = count; n > 0; n--, cur_attr++, curr_head += len) {
struct pkcs11_attribute_head *cli_ref = (void *)curr_head;
struct pkcs11_attribute_head cli_head = { 0 };
void *data_ptr = NULL;
/* Make copy if header so that is aligned properly. */
memcpy(&cli_head, cli_ref, sizeof(cli_head));
/* Get real data pointer from template data */
data_ptr = cli_ref->data;
len = sizeof(cli_head);
/* Advance by size provisioned in input serialized buffer */
if (cur_attr->pValue) {
if (ck_attr_is_ulong(cur_attr->type))
len += sizeof(uint32_t);
else
len += cur_attr->ulValueLen;
}
rv = deserialize_ck_attribute(&cli_head, data_ptr, cur_attr);
if (rv)
return rv;
}
return rv;
}
/*
* Serialization of CK mechanism parameters
*
* Most mechanism have no parameters.
* Some mechanism have a single 32bit parameter.
* Some mechanism have a specific parameter structure which may contain
* indirected data (data referred by a buffer pointer).
*
* Below are each structure specific mechanisms parameters.
*/
static CK_RV serialize_mecha_aes_ctr(struct serializer *obj,
CK_MECHANISM_PTR mecha)
{
CK_AES_CTR_PARAMS_PTR param = mecha->pParameter;
CK_RV rv = CKR_GENERAL_ERROR;
uint32_t size = 0;
rv = serialize_32b(obj, obj->type);
if (rv)
return rv;
size = sizeof(uint32_t) + sizeof(param->cb);
rv = serialize_32b(obj, size);
if (rv)
return rv;
rv = serialize_ck_ulong(obj, param->ulCounterBits);
if (rv)
return rv;
rv = serialize_buffer(obj, param->cb, sizeof(param->cb));
if (rv)
return rv;
return rv;
}
static CK_RV serialize_mecha_aes_gcm(struct serializer *obj,
CK_MECHANISM_PTR mecha)
{
CK_GCM_PARAMS_PTR param = mecha->pParameter;
CK_RV rv = CKR_GENERAL_ERROR;
CK_ULONG aad_len = 0;
/* AAD is not manadatory */
if (param->pAAD)
aad_len = param->ulAADLen;
if (!param->pIv)
return CKR_MECHANISM_PARAM_INVALID;
rv = serialize_32b(obj, obj->type);
if (rv)
return rv;
rv = serialize_32b(obj, 3 * sizeof(uint32_t) +
param->ulIvLen + aad_len);
if (rv)
return rv;
rv = serialize_ck_ulong(obj, param->ulIvLen);
if (rv)
return rv;
rv = serialize_buffer(obj, param->pIv, param->ulIvLen);
if (rv)
return rv;
rv = serialize_ck_ulong(obj, aad_len);
if (rv)
return rv;
rv = serialize_buffer(obj, param->pAAD, aad_len);
if (rv)
return rv;
return serialize_ck_ulong(obj, param->ulTagBits);
}
static CK_RV serialize_mecha_aes_iv(struct serializer *obj,
CK_MECHANISM_PTR mecha)
{
uint32_t iv_size = mecha->ulParameterLen;
CK_RV rv = CKR_GENERAL_ERROR;
rv = serialize_32b(obj, obj->type);
if (rv)
return rv;
rv = serialize_32b(obj, iv_size);
if (rv)
return rv;
return serialize_buffer(obj, mecha->pParameter, mecha->ulParameterLen);
}
static CK_RV serialize_mecha_key_deriv_str(struct serializer *obj,
CK_MECHANISM_PTR mecha)
{
CK_KEY_DERIVATION_STRING_DATA_PTR param = mecha->pParameter;
CK_RV rv = CKR_GENERAL_ERROR;
uint32_t size = 0;
rv = serialize_32b(obj, obj->type);
if (rv)
return rv;
size = sizeof(uint32_t) + param->ulLen;
rv = serialize_32b(obj, size);
if (rv)
return rv;
rv = serialize_ck_ulong(obj, param->ulLen);
if (rv)
return rv;
return serialize_buffer(obj, param->pData, param->ulLen);
}
static CK_RV serialize_mecha_ecdh1_derive_param(struct serializer *obj,
CK_MECHANISM_PTR mecha)
{
CK_ECDH1_DERIVE_PARAMS *params = mecha->pParameter;
CK_RV rv = CKR_GENERAL_ERROR;
size_t params_size = 3 * sizeof(uint32_t) + params->ulSharedDataLen +
params->ulPublicDataLen;
rv = serialize_32b(obj, obj->type);
if (rv)
return rv;
rv = serialize_32b(obj, params_size);
if (rv)
return rv;
rv = serialize_32b(obj, params->kdf);
if (rv)
return rv;
rv = serialize_32b(obj, params->ulSharedDataLen);
if (rv)
return rv;
rv = serialize_buffer(obj, params->pSharedData,
params->ulSharedDataLen);
if (rv)
return rv;
rv = serialize_32b(obj, params->ulPublicDataLen);
if (rv)
return rv;
return serialize_buffer(obj, params->pPublicData,
params->ulPublicDataLen);
}
static CK_RV serialize_mecha_aes_cbc_encrypt_data(struct serializer *obj,
CK_MECHANISM_PTR mecha)
{
CK_AES_CBC_ENCRYPT_DATA_PARAMS_PTR param = mecha->pParameter;
CK_RV rv = CKR_GENERAL_ERROR;
uint32_t size = 0;
rv = serialize_32b(obj, obj->type);
if (rv)
return rv;
size = sizeof(param->iv) + sizeof(uint32_t) + param->length;
rv = serialize_32b(obj, size);
if (rv)
return rv;
rv = serialize_buffer(obj, param->iv, sizeof(param->iv));
if (rv)
return rv;
rv = serialize_ck_ulong(obj, param->length);
if (rv)
return rv;
return serialize_buffer(obj, param->pData, param->length);
}
static CK_RV serialize_mecha_rsa_pss_param(struct serializer *obj,
CK_MECHANISM_PTR mecha)
{
CK_RSA_PKCS_PSS_PARAMS *params = mecha->pParameter;
CK_RV rv = CKR_GENERAL_ERROR;
uint32_t params_size = 3 * sizeof(uint32_t);
if (mecha->ulParameterLen != sizeof(*params))
return CKR_ARGUMENTS_BAD;
rv = serialize_32b(obj, obj->type);
if (rv)
return rv;
rv = serialize_32b(obj, params_size);
if (rv)
return rv;
rv = serialize_ck_ulong(obj, params->hashAlg);
if (rv)
return rv;
rv = serialize_ck_ulong(obj, params->mgf);
if (rv)
return rv;
return serialize_ck_ulong(obj, params->sLen);
}
static CK_RV serialize_mecha_rsa_oaep_param(struct serializer *obj,
CK_MECHANISM_PTR mecha)
{
CK_RSA_PKCS_OAEP_PARAMS *params = mecha->pParameter;
CK_RV rv = CKR_GENERAL_ERROR;
size_t params_size = 4 * sizeof(uint32_t) + params->ulSourceDataLen;
if (mecha->ulParameterLen != sizeof(*params))
return CKR_ARGUMENTS_BAD;
rv = serialize_32b(obj, obj->type);
if (rv)
return rv;
rv = serialize_32b(obj, params_size);
if (rv)
return rv;
rv = serialize_ck_ulong(obj, params->hashAlg);
if (rv)
return rv;
rv = serialize_ck_ulong(obj, params->mgf);
if (rv)
return rv;
rv = serialize_ck_ulong(obj, params->source);
if (rv)
return rv;
rv = serialize_ck_ulong(obj, params->ulSourceDataLen);
if (rv)
return rv;
return serialize_buffer(obj, params->pSourceData,
params->ulSourceDataLen);
}
static CK_RV serialize_mecha_rsa_aes_key_wrap(struct serializer *obj,
CK_MECHANISM_PTR mecha)
{
CK_RSA_AES_KEY_WRAP_PARAMS *params = mecha->pParameter;
CK_RSA_PKCS_OAEP_PARAMS *aes_params = params->pOAEPParams;
CK_RV rv = CKR_GENERAL_ERROR;
size_t params_size = 5 * sizeof(uint32_t) + aes_params->ulSourceDataLen;
if (mecha->ulParameterLen != sizeof(*params))
return CKR_ARGUMENTS_BAD;
rv = serialize_32b(obj, obj->type);
if (rv)
return rv;
rv = serialize_32b(obj, params_size);
if (rv)
return rv;
rv = serialize_ck_ulong(obj, params->ulAESKeyBits);
if (rv)
return rv;
rv = serialize_ck_ulong(obj, aes_params->hashAlg);
if (rv)
return rv;
rv = serialize_ck_ulong(obj, aes_params->mgf);
if (rv)
return rv;
rv = serialize_ck_ulong(obj, aes_params->source);
if (rv)
return rv;
rv = serialize_ck_ulong(obj, aes_params->ulSourceDataLen);
if (rv)
return rv;
return serialize_buffer(obj, aes_params->pSourceData,
aes_params->ulSourceDataLen);
}
static CK_RV serialize_mecha_eddsa(struct serializer *obj,
CK_MECHANISM_PTR mecha)
{
CK_RV rv = CKR_GENERAL_ERROR;
CK_EDDSA_PARAMS *params = mecha->pParameter;
CK_ULONG params_len = mecha->ulParameterLen;
/*
* When no parameter is provided, the expected operation is
* no-prehash and no-context.
*/
CK_EDDSA_PARAMS default_params = {
.phFlag = 0,
.ulContextDataLen = 0,
};
if (params_len == 0) {
params = &default_params;
params_len = sizeof(*params);
}
if (params_len != sizeof(*params))
return CKR_ARGUMENTS_BAD;
rv = serialize_32b(obj, obj->type);
if (rv)
return rv;
rv = serialize_32b(obj, 2 * sizeof(uint32_t) + params->ulContextDataLen);
if (rv)
return rv;
rv = serialize_32b(obj, params->phFlag);
if (rv)
return rv;
rv = serialize_32b(obj, params->ulContextDataLen);
if (rv)
return rv;
return serialize_buffer(obj, params->pContextData, params->ulContextDataLen);
}
static CK_RV serialize_mecha_mac_general_param(struct serializer *obj,
CK_MECHANISM_PTR mecha)
{
CK_RV rv = CKR_GENERAL_ERROR;
CK_ULONG ck_data = 0;
if (mecha->ulParameterLen != sizeof(ck_data))
return CKR_ARGUMENTS_BAD;
memcpy(&ck_data, mecha->pParameter, mecha->ulParameterLen);
rv = serialize_32b(obj, obj->type);
if (rv)
return rv;
rv = serialize_32b(obj, sizeof(uint32_t));
if (rv)
return rv;
return serialize_ck_ulong(obj, ck_data);
}
/**
* serialize_ck_mecha_params - serialize a mechanism type & params
*
* @obj - serializer used to track the serialization
* @mechanism - pointer of the in structure aligned CK_MECHANISM.
*
* Serialized content:
* [mechanism-type][mechanism-param-blob]
*
* [mechanism-param-blob] depends on mechanism type ID, see
* serialize_mecha_XXX().
*/
CK_RV serialize_ck_mecha_params(struct serializer *obj,
CK_MECHANISM_PTR mechanism)
{
CK_MECHANISM mecha = { 0 };
CK_RV rv = CKR_GENERAL_ERROR;
memset(obj, 0, sizeof(*obj));
obj->object = PKCS11_CKO_MECHANISM;
mecha = *mechanism;
obj->type = mecha.mechanism;
if (obj->type == PKCS11_UNDEFINED_ID)
return CKR_MECHANISM_INVALID;
switch (mecha.mechanism) {
case CKM_GENERIC_SECRET_KEY_GEN:
case CKM_AES_KEY_GEN:
case CKM_AES_ECB:
case CKM_AES_CMAC:
case CKM_MD5:
case CKM_SHA_1:
case CKM_SHA224:
case CKM_SHA256:
case CKM_SHA384:
case CKM_SHA512:
case CKM_MD5_HMAC:
case CKM_SHA_1_HMAC:
case CKM_SHA224_HMAC:
case CKM_SHA256_HMAC:
case CKM_SHA384_HMAC:
case CKM_SHA512_HMAC:
case CKM_EC_KEY_PAIR_GEN:
case CKM_EC_EDWARDS_KEY_PAIR_GEN:
case CKM_ECDSA:
case CKM_ECDSA_SHA1:
case CKM_ECDSA_SHA224:
case CKM_ECDSA_SHA256:
case CKM_ECDSA_SHA384:
case CKM_ECDSA_SHA512:
case CKM_RSA_PKCS_KEY_PAIR_GEN:
case CKM_RSA_PKCS:
case CKM_RSA_X_509:
case CKM_MD5_RSA_PKCS:
case CKM_SHA1_RSA_PKCS:
case CKM_SHA224_RSA_PKCS:
case CKM_SHA256_RSA_PKCS:
case CKM_SHA384_RSA_PKCS:
case CKM_SHA512_RSA_PKCS:
/* No parameter expected, size shall be 0 */
if (mechanism->ulParameterLen)
return CKR_MECHANISM_PARAM_INVALID;
rv = serialize_32b(obj, obj->type);
if (rv)
return rv;
return serialize_32b(obj, 0);
case CKM_EDDSA:
return serialize_mecha_eddsa(obj, &mecha);
case CKM_AES_CBC:
case CKM_AES_CBC_PAD:
case CKM_AES_CTS:
return serialize_mecha_aes_iv(obj, &mecha);
case CKM_AES_CTR:
return serialize_mecha_aes_ctr(obj, &mecha);
case CKM_AES_GCM:
return serialize_mecha_aes_gcm(obj, &mecha);
case CKM_AES_ECB_ENCRYPT_DATA:
return serialize_mecha_key_deriv_str(obj, &mecha);
case CKM_AES_CBC_ENCRYPT_DATA:
return serialize_mecha_aes_cbc_encrypt_data(obj, &mecha);
case CKM_ECDH1_DERIVE:
case CKM_ECDH1_COFACTOR_DERIVE:
return serialize_mecha_ecdh1_derive_param(obj, &mecha);
case CKM_RSA_PKCS_PSS:
case CKM_SHA1_RSA_PKCS_PSS:
case CKM_SHA256_RSA_PKCS_PSS:
case CKM_SHA384_RSA_PKCS_PSS:
case CKM_SHA512_RSA_PKCS_PSS:
case CKM_SHA224_RSA_PKCS_PSS:
return serialize_mecha_rsa_pss_param(obj, &mecha);
case CKM_RSA_PKCS_OAEP:
return serialize_mecha_rsa_oaep_param(obj, &mecha);
case CKM_AES_CMAC_GENERAL:
case CKM_MD5_HMAC_GENERAL:
case CKM_SHA_1_HMAC_GENERAL:
case CKM_SHA224_HMAC_GENERAL:
case CKM_SHA256_HMAC_GENERAL:
case CKM_SHA384_HMAC_GENERAL:
case CKM_SHA512_HMAC_GENERAL:
return serialize_mecha_mac_general_param(obj, &mecha);
case CKM_RSA_AES_KEY_WRAP:
return serialize_mecha_rsa_aes_key_wrap(obj, &mecha);
default:
return CKR_MECHANISM_INVALID;
}
}