7533e7fb56
Newer version of pkcs11-tool set the CKA_PRIVATE attribute during generation making the operation fail. The attribute is now ignored.
552 lines
15 KiB
C
552 lines
15 KiB
C
/*
|
|
* Copyright (c) 2015-2016 Yubico AB
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are
|
|
* met:
|
|
*
|
|
* * Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
*
|
|
* * Redistributions in binary form must reproduce the above
|
|
* copyright notice, this list of conditions and the following
|
|
* disclaimer in the documentation and/or other materials provided
|
|
* with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*
|
|
*/
|
|
|
|
#include "mechanisms.h"
|
|
#include "openssl_utils.h"
|
|
#include "utils.h"
|
|
#include "debug.h"
|
|
#include <string.h>
|
|
|
|
#define F4 "\x01\x00\x01"
|
|
#define PRIME256V1 "\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07"
|
|
|
|
// Supported mechanisms for signature
|
|
static const CK_MECHANISM_TYPE sign_mechanisms[] = {
|
|
CKM_RSA_PKCS,
|
|
CKM_RSA_PKCS_PSS,
|
|
CKM_RSA_X_509,
|
|
CKM_SHA1_RSA_PKCS,
|
|
CKM_SHA256_RSA_PKCS,
|
|
CKM_SHA384_RSA_PKCS,
|
|
CKM_SHA512_RSA_PKCS,
|
|
CKM_SHA1_RSA_PKCS_PSS,
|
|
CKM_SHA256_RSA_PKCS_PSS,
|
|
CKM_SHA384_RSA_PKCS_PSS,
|
|
CKM_SHA512_RSA_PKCS_PSS,
|
|
CKM_ECDSA,
|
|
CKM_ECDSA_SHA1,
|
|
CKM_ECDSA_SHA256
|
|
};
|
|
|
|
// Supported mechanisms for key pair generation
|
|
static const CK_MECHANISM_TYPE generation_mechanisms[] = {
|
|
CKM_RSA_PKCS_KEY_PAIR_GEN,
|
|
//CKM_ECDSA_KEY_PAIR_GEN, Deperecated
|
|
CKM_EC_KEY_PAIR_GEN
|
|
};
|
|
|
|
// Supported mechanisms for hashing
|
|
static const CK_MECHANISM_TYPE hash_mechanisms[] = {
|
|
CKM_SHA_1,
|
|
CKM_SHA256,
|
|
CKM_SHA384,
|
|
CKM_SHA512
|
|
};
|
|
|
|
CK_RV check_sign_mechanism(const ykcs11_session_t *s, const CK_MECHANISM_PTR m) {
|
|
|
|
CK_ULONG i;
|
|
CK_BBOOL supported = CK_FALSE;
|
|
token_vendor_t token;
|
|
CK_MECHANISM_INFO info;
|
|
|
|
// Check if the mechanism is supported by the module
|
|
for (i = 0; i < sizeof(sign_mechanisms) / sizeof(CK_MECHANISM_TYPE); i++) {
|
|
if (m->mechanism == sign_mechanisms[i]) {
|
|
supported = CK_TRUE;
|
|
break;
|
|
}
|
|
}
|
|
if (supported == CK_FALSE)
|
|
return CKR_MECHANISM_INVALID;
|
|
|
|
// Check if the mechanism is supported by the token
|
|
token = get_token_vendor(s->slot->token->vid);
|
|
|
|
if (token.get_token_mechanism_info(m->mechanism, &info) != CKR_OK)
|
|
return CKR_MECHANISM_INVALID;
|
|
|
|
// TODO: also check that parametes make sense if any? And key size is in [min max]
|
|
|
|
return CKR_OK;
|
|
|
|
}
|
|
|
|
CK_BBOOL is_RSA_mechanism(CK_MECHANISM_TYPE m) {
|
|
|
|
switch (m) {
|
|
case CKM_RSA_PKCS_KEY_PAIR_GEN:
|
|
case CKM_RSA_PKCS:
|
|
case CKM_RSA_9796:
|
|
case CKM_RSA_X_509:
|
|
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:
|
|
// case CKM_RIPEMD128_RSA_PKCS:
|
|
// case CKM_RIPEMD160_RSA_PKCS:
|
|
// case CKM_RSA_PKCS_OAEP:
|
|
// case CKM_RSA_X9_31_KEY_PAIR_GEN:
|
|
// case CKM_RSA_X9_31:
|
|
// case CKM_SHA1_RSA_X9_31:
|
|
case CKM_RSA_PKCS_PSS:
|
|
case CKM_SHA1_RSA_PKCS_PSS:
|
|
// case CKM_SHA224_RSA_PKCS_PSS:
|
|
case CKM_SHA256_RSA_PKCS_PSS:
|
|
case CKM_SHA512_RSA_PKCS_PSS:
|
|
case CKM_SHA384_RSA_PKCS_PSS:
|
|
// case CKM_RSA_PKCS_TPM_1_1:
|
|
// case CKM_RSA_PKCS_OAEP_TPM_1_1:
|
|
// case CKM_RSA_AES_KEY_WRAP:
|
|
return CK_TRUE;
|
|
|
|
default:
|
|
return CK_FALSE;
|
|
}
|
|
|
|
// Not reached
|
|
return CK_FALSE;
|
|
}
|
|
|
|
CK_BBOOL is_PSS_mechanism(CK_MECHANISM_TYPE m) {
|
|
|
|
switch (m) {
|
|
case CKM_RSA_PKCS_PSS:
|
|
case CKM_SHA1_RSA_PKCS_PSS:
|
|
// case CKM_SHA224_RSA_PKCS_PSS:
|
|
case CKM_SHA256_RSA_PKCS_PSS:
|
|
case CKM_SHA512_RSA_PKCS_PSS:
|
|
case CKM_SHA384_RSA_PKCS_PSS:
|
|
return CK_TRUE;
|
|
|
|
default:
|
|
return CK_FALSE;
|
|
}
|
|
|
|
// Not reached
|
|
return CK_FALSE;
|
|
}
|
|
|
|
CK_BBOOL is_hashed_mechanism(CK_MECHANISM_TYPE m) {
|
|
|
|
switch (m) {
|
|
case CKM_SHA1_RSA_PKCS:
|
|
case CKM_SHA256_RSA_PKCS:
|
|
case CKM_SHA384_RSA_PKCS:
|
|
case CKM_SHA512_RSA_PKCS:
|
|
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_ECDSA_SHA1:
|
|
case CKM_ECDSA_SHA256:
|
|
case CKM_SHA_1:
|
|
case CKM_SHA256:
|
|
case CKM_SHA384:
|
|
case CKM_SHA512:
|
|
return CK_TRUE;
|
|
|
|
default:
|
|
return CK_FALSE;
|
|
}
|
|
|
|
// Not reached
|
|
return CK_FALSE;
|
|
}
|
|
|
|
CK_RV apply_sign_mechanism_init(op_info_t *op_info) {
|
|
|
|
if (op_info->type != YKCS11_SIGN)
|
|
return CKR_FUNCTION_FAILED;
|
|
|
|
switch (op_info->mechanism.mechanism) {
|
|
case CKM_RSA_PKCS:
|
|
case CKM_RSA_PKCS_PSS:
|
|
case CKM_RSA_X_509:
|
|
case CKM_ECDSA:
|
|
// No hash required for this mechanism
|
|
op_info->op.sign.md_ctx = NULL;
|
|
return CKR_OK;
|
|
|
|
case CKM_SHA1_RSA_PKCS:
|
|
case CKM_SHA1_RSA_PKCS_PSS:
|
|
case CKM_ECDSA_SHA1:
|
|
return do_md_init(YKCS11_SHA1, &op_info->op.sign.md_ctx);
|
|
|
|
case CKM_SHA256_RSA_PKCS:
|
|
case CKM_SHA256_RSA_PKCS_PSS:
|
|
case CKM_ECDSA_SHA256:
|
|
return do_md_init(YKCS11_SHA256, &op_info->op.sign.md_ctx);
|
|
|
|
case CKM_SHA384_RSA_PKCS:
|
|
case CKM_SHA384_RSA_PKCS_PSS:
|
|
return do_md_init(YKCS11_SHA384, &op_info->op.sign.md_ctx);
|
|
|
|
case CKM_SHA512_RSA_PKCS:
|
|
case CKM_SHA512_RSA_PKCS_PSS:
|
|
return do_md_init(YKCS11_SHA512, &op_info->op.sign.md_ctx);
|
|
|
|
default:
|
|
return CKR_FUNCTION_FAILED;
|
|
}
|
|
|
|
// Never reached
|
|
return CKR_FUNCTION_FAILED;
|
|
}
|
|
|
|
CK_RV apply_sign_mechanism_update(op_info_t *op_info, CK_BYTE_PTR in, CK_ULONG in_len) {
|
|
CK_RV rv;
|
|
|
|
if (op_info->type != YKCS11_SIGN)
|
|
return CKR_FUNCTION_FAILED;
|
|
|
|
switch (op_info->mechanism.mechanism) {
|
|
case CKM_RSA_PKCS:
|
|
case CKM_RSA_PKCS_PSS:
|
|
case CKM_ECDSA:
|
|
case CKM_RSA_X_509:
|
|
// Mechanism not suitable for multipart signatures
|
|
return CKR_FUNCTION_FAILED;
|
|
|
|
case CKM_SHA1_RSA_PKCS:
|
|
case CKM_SHA256_RSA_PKCS:
|
|
case CKM_SHA384_RSA_PKCS:
|
|
case CKM_SHA512_RSA_PKCS:
|
|
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_ECDSA_SHA1:
|
|
case CKM_ECDSA_SHA256:
|
|
rv = do_md_update(op_info->op.sign.md_ctx, in, in_len);
|
|
if (rv != CKR_OK)
|
|
return CKR_FUNCTION_FAILED;
|
|
|
|
return CKR_OK;
|
|
|
|
default:
|
|
return CKR_FUNCTION_FAILED;
|
|
}
|
|
|
|
}
|
|
|
|
CK_RV apply_sign_mechanism_finalize(op_info_t *op_info) {
|
|
|
|
CK_RV rv;
|
|
int nid = NID_undef;
|
|
CK_ULONG len;
|
|
|
|
if (op_info->type != YKCS11_SIGN)
|
|
return CKR_FUNCTION_FAILED;
|
|
|
|
switch (op_info->mechanism.mechanism) {
|
|
case CKM_SHA1_RSA_PKCS_PSS:
|
|
case CKM_SHA256_RSA_PKCS_PSS:
|
|
case CKM_SHA384_RSA_PKCS_PSS:
|
|
case CKM_SHA512_RSA_PKCS_PSS:
|
|
// Finalize the hash
|
|
rv = do_md_finalize(op_info->op.sign.md_ctx, op_info->buf, &op_info->buf_len, &nid);
|
|
op_info->op.sign.md_ctx = NULL;
|
|
if (rv != CKR_OK)
|
|
return CKR_FUNCTION_FAILED;
|
|
|
|
case CKM_RSA_PKCS_PSS:
|
|
// Compute padding for all PSS variants
|
|
// TODO: digestinfo/paraminfo ?
|
|
rv = do_pkcs_pss(op_info->op.sign.key, op_info->buf, op_info->buf_len, nid, op_info->buf, &op_info->buf_len);
|
|
do_free_rsa_public_key(op_info->op.sign.key);
|
|
|
|
return rv;
|
|
|
|
case CKM_RSA_X_509:
|
|
// Padding in this case consists of prepending zeroes
|
|
len = (op_info->op.sign.key_len / 8) - op_info->buf_len;
|
|
memmove(op_info->buf + len, op_info->buf, op_info->buf_len);
|
|
memset(op_info->buf, 0, len);
|
|
op_info->buf_len = op_info->op.sign.key_len / 8;
|
|
return CKR_OK;
|
|
|
|
case CKM_SHA1_RSA_PKCS:
|
|
case CKM_SHA256_RSA_PKCS:
|
|
case CKM_SHA384_RSA_PKCS:
|
|
case CKM_SHA512_RSA_PKCS:
|
|
// Finalize the hash add digest info
|
|
rv = do_md_finalize(op_info->op.sign.md_ctx, op_info->buf, &op_info->buf_len, &nid);
|
|
op_info->op.sign.md_ctx = NULL;
|
|
if (rv != CKR_OK)
|
|
return CKR_FUNCTION_FAILED;
|
|
|
|
case CKM_RSA_PKCS:
|
|
// Add digest info if needed
|
|
if (nid != NID_undef) {
|
|
rv = do_pkcs_1_digest_info(op_info->buf, op_info->buf_len, nid, op_info->buf, &op_info->buf_len);
|
|
if (rv != CKR_OK)
|
|
return CKR_FUNCTION_FAILED;
|
|
}
|
|
|
|
// Compute padding for all PKCS1 variants
|
|
len = op_info->buf_len;
|
|
op_info->buf_len = sizeof(op_info->buf);
|
|
return do_pkcs_1_t1(op_info->buf, len, op_info->buf, &op_info->buf_len, op_info->op.sign.key_len);
|
|
|
|
case CKM_ECDSA_SHA1:
|
|
case CKM_ECDSA_SHA256:
|
|
// Finalize the hash
|
|
rv = do_md_finalize(op_info->op.sign.md_ctx, op_info->buf, &op_info->buf_len, &nid);
|
|
op_info->op.sign.md_ctx = NULL;
|
|
if (rv != CKR_OK)
|
|
return CKR_FUNCTION_FAILED;
|
|
|
|
case CKM_ECDSA:
|
|
return CKR_OK;
|
|
|
|
default:
|
|
return CKR_FUNCTION_FAILED;
|
|
}
|
|
}
|
|
|
|
CK_RV sign_mechanism_cleanup(op_info_t *op_info) {
|
|
|
|
if (op_info->op.sign.md_ctx != NULL) {
|
|
do_md_cleanup(op_info->op.sign.md_ctx);
|
|
op_info->op.sign.md_ctx = NULL;
|
|
}
|
|
|
|
return CKR_OK;
|
|
}
|
|
|
|
CK_RV check_generation_mechanism(const ykcs11_session_t *s, CK_MECHANISM_PTR m) {
|
|
|
|
CK_ULONG i;
|
|
CK_BBOOL supported = CK_FALSE;
|
|
token_vendor_t token;
|
|
CK_MECHANISM_INFO info;
|
|
|
|
// Check if the mechanism is supported by the module
|
|
for (i = 0; i < sizeof(generation_mechanisms) / sizeof(CK_MECHANISM_TYPE); i++) {
|
|
if (m->mechanism == generation_mechanisms[i]) {
|
|
supported = CK_TRUE;
|
|
break;
|
|
}
|
|
}
|
|
if (supported == CK_FALSE)
|
|
return CKR_MECHANISM_INVALID;
|
|
|
|
// Check if the mechanism is supported by the token
|
|
token = get_token_vendor(s->slot->token->vid);
|
|
|
|
if (token.get_token_mechanism_info(m->mechanism, &info) != CKR_OK)
|
|
return CKR_MECHANISM_INVALID;
|
|
|
|
// TODO: also check that parametes make sense if any? And key size is in [min max]
|
|
|
|
return CKR_OK;
|
|
|
|
}
|
|
|
|
CK_RV check_pubkey_template(op_info_t *op_info, CK_ATTRIBUTE_PTR templ, CK_ULONG n) {
|
|
|
|
CK_ULONG i;
|
|
|
|
op_info->op.gen.rsa = is_RSA_mechanism(op_info->mechanism.mechanism);
|
|
|
|
for (i = 0; i < n; i++) {
|
|
switch (templ[i].type) {
|
|
case CKA_CLASS:
|
|
if (*((CK_ULONG_PTR) templ[i].pValue) != CKO_PUBLIC_KEY)
|
|
return CKR_TEMPLATE_INCONSISTENT;
|
|
|
|
break;
|
|
|
|
case CKA_KEY_TYPE:
|
|
if ((op_info->op.gen.rsa == CK_TRUE && (*((CK_KEY_TYPE *)templ[i].pValue)) != CKK_RSA) ||
|
|
(op_info->op.gen.rsa == CK_FALSE && (*((CK_KEY_TYPE *)templ[i].pValue)) != CKK_ECDSA))
|
|
return CKR_TEMPLATE_INCONSISTENT;
|
|
|
|
break;
|
|
|
|
case CKA_PUBLIC_EXPONENT:
|
|
if (op_info->op.gen.rsa == CK_FALSE)
|
|
return CKR_ATTRIBUTE_VALUE_INVALID;
|
|
|
|
// Only support F4
|
|
if (templ[i].ulValueLen != 3 || memcmp((CK_BYTE_PTR)templ[i].pValue, F4, 3) != 0) {
|
|
DBG("Unsupported public exponent");
|
|
return CKR_ATTRIBUTE_VALUE_INVALID;
|
|
}
|
|
|
|
break;
|
|
|
|
case CKA_MODULUS_BITS:
|
|
if (op_info->op.gen.rsa == CK_FALSE)
|
|
return CKR_ATTRIBUTE_VALUE_INVALID;
|
|
|
|
if (*((CK_ULONG_PTR) templ[i].pValue) != 1024 &&
|
|
*((CK_ULONG_PTR) templ[i].pValue) != 2048) { // TODO: make define?
|
|
DBG("Unsupported MODULUS_BITS (key length)");
|
|
return CKR_ATTRIBUTE_VALUE_INVALID;
|
|
}
|
|
|
|
op_info->op.gen.key_len = *((CK_ULONG_PTR) templ[i].pValue);
|
|
break;
|
|
|
|
case CKA_EC_PARAMS:
|
|
// Only support PRIME256V1
|
|
if (templ[i].ulValueLen != 10 || memcmp((CK_BYTE_PTR)templ[i].pValue, PRIME256V1, 10) != 0)
|
|
return CKR_FUNCTION_FAILED;
|
|
|
|
op_info->op.gen.key_len = 256;
|
|
break;
|
|
|
|
case CKA_ID:
|
|
if (is_valid_key_id(*((CK_BYTE_PTR)templ[i].pValue)) == CK_FALSE)
|
|
return CKR_ATTRIBUTE_VALUE_INVALID;
|
|
|
|
op_info->op.gen.key_id = PIV_PVTK_OBJ_PIV_AUTH + *((CK_BYTE_PTR)templ[i].pValue);
|
|
break;
|
|
|
|
case CKA_TOKEN:
|
|
case CKA_ENCRYPT:
|
|
case CKA_VERIFY:
|
|
case CKA_WRAP:
|
|
case CKA_DERIVE:
|
|
case CKA_PRIVATE:
|
|
// Ignore these attributes for now
|
|
break;
|
|
|
|
default:
|
|
DBG("Invalid attribute %lx in public key template", templ[i].type);
|
|
return CKR_ATTRIBUTE_TYPE_INVALID;
|
|
}
|
|
}
|
|
|
|
return CKR_OK;
|
|
|
|
}
|
|
|
|
CK_RV check_pvtkey_template(op_info_t *op_info, CK_ATTRIBUTE_PTR templ, CK_ULONG n) {
|
|
|
|
CK_ULONG i;
|
|
|
|
op_info->op.gen.rsa = is_RSA_mechanism(op_info->mechanism.mechanism);
|
|
op_info->op.gen.vendor_defined = 0;
|
|
|
|
for (i = 0; i < n; i++) {
|
|
switch (templ[i].type) {
|
|
case CKA_CLASS:
|
|
if (*((CK_ULONG_PTR)templ[i].pValue) != CKO_PRIVATE_KEY)
|
|
return CKR_TEMPLATE_INCONSISTENT;
|
|
|
|
break;
|
|
|
|
case CKA_KEY_TYPE:
|
|
if ((op_info->op.gen.rsa == CK_TRUE && (*((CK_KEY_TYPE *)templ[i].pValue)) != CKK_RSA) ||
|
|
(op_info->op.gen.rsa == CK_FALSE && (*((CK_KEY_TYPE *)templ[i].pValue)) != CKK_ECDSA))
|
|
return CKR_TEMPLATE_INCONSISTENT;
|
|
|
|
break;
|
|
|
|
/* case CKA_MODULUS_BITS:
|
|
if (op_info->op.gen.rsa == CK_FALSE)
|
|
return CKR_MECHANISM_PARAM_INVALID;
|
|
|
|
if (*((CK_ULONG_PTR)templ[i].pValue) != 1024 &&
|
|
*((CK_ULONG_PTR) templ[i].pValue) != 2048) // TODO: make define?
|
|
return CKR_MECHANISM_PARAM_INVALID;
|
|
|
|
op_info->op.gen.key_len = *((CK_ULONG_PTR) templ[i].pValue); // TODO: check length?
|
|
break;*/
|
|
|
|
case CKA_ID:
|
|
if (is_valid_key_id(*((CK_BYTE_PTR)templ[i].pValue)) == CK_FALSE)
|
|
return CKR_ATTRIBUTE_VALUE_INVALID;
|
|
|
|
// Check if ID was already specified in the public key template
|
|
// In that case it has to match
|
|
if (op_info->op.gen.key_id != 0 &&
|
|
op_info->op.gen.key_id != (*((CK_BYTE_PTR)templ[i].pValue) + PIV_PVTK_OBJ_PIV_AUTH))
|
|
return CKR_TEMPLATE_INCONSISTENT;
|
|
|
|
op_info->op.gen.key_id = PIV_PVTK_OBJ_PIV_AUTH + *((CK_BYTE_PTR)templ[i].pValue);
|
|
break;
|
|
|
|
case CKA_VENDOR_DEFINED:
|
|
op_info->op.gen.vendor_defined = (*((CK_ULONG_PTR)templ[i].pValue));
|
|
|
|
case CKA_SENSITIVE:
|
|
case CKA_DECRYPT:
|
|
case CKA_UNWRAP:
|
|
case CKA_SIGN:
|
|
case CKA_PRIVATE:
|
|
case CKA_TOKEN:
|
|
case CKA_DERIVE:
|
|
// Ignore these attributes for now
|
|
break;
|
|
|
|
default:
|
|
DBG("Invalid attribute %lx in private key template", templ[i].type);
|
|
return CKR_ATTRIBUTE_TYPE_INVALID;
|
|
}
|
|
}
|
|
|
|
return CKR_OK;
|
|
|
|
}
|
|
|
|
CK_RV check_hash_mechanism(const ykcs11_session_t *s, CK_MECHANISM_PTR m) {
|
|
|
|
CK_ULONG i;
|
|
CK_BBOOL supported = CK_FALSE;
|
|
token_vendor_t token;
|
|
CK_MECHANISM_INFO info;
|
|
|
|
// Check if the mechanism is supported by the module
|
|
for (i = 0; i < sizeof(hash_mechanisms) / sizeof(CK_MECHANISM_TYPE); i++) {
|
|
if (m->mechanism == hash_mechanisms[i]) {
|
|
supported = CK_TRUE;
|
|
break;
|
|
}
|
|
}
|
|
if (supported == CK_FALSE)
|
|
return CKR_MECHANISM_INVALID;
|
|
|
|
// Check if the mechanism is supported by the token
|
|
token = get_token_vendor(s->slot->token->vid);
|
|
|
|
if (token.get_token_mechanism_info(m->mechanism, &info) != CKR_OK)
|
|
return CKR_MECHANISM_INVALID;
|
|
|
|
// TODO: also check that parametes make sense if any? And key size is in [min max]
|
|
|
|
return CKR_OK;
|
|
|
|
}
|