summaryrefslogtreecommitdiff
path: root/ta/pkcs11
diff options
context:
space:
mode:
authorRuchika Gupta <ruchika.gupta@linaro.org>2020-10-29 12:57:06 +0530
committerJérôme Forissier <jerome@forissier.org>2020-11-24 08:52:11 +0100
commit689f4e5b067fea8c8c0566e968ef2bf5303b2082 (patch)
tree6e19dd31833d788d7b87e105050b71e6dea2f135 /ta/pkcs11
parent58ab0c3d6c7294d3faa4e8270e9b6f74bb7671da (diff)
ta: pkcs11 : add support for HMAC modes for Sign/Verify
Add support for HMAC modes for hash functions - MD5, SHA1, SHA256, SHA224, SHA284 and SHA512 in Sign/Verify operations. PKCS#11 offers 2 HMAC methods for each hash function <h>, CKM_<h>_HMAC and CKM_<h>_HMAC_GENERAL. Fixed tag length of the output size of hash function i.e CKM_h_HMAC is currently supported. Co-developed-by: Etienne Carriere <etienne.carriere@linaro.org> Signed-off-by: Etienne Carriere <etienne.carriere@linaro.org> Signed-off-by: Ruchika Gupta <ruchika.gupta@linaro.org> Reviewed-by: Ricardo Salveti <ricardo@foundries.io>
Diffstat (limited to 'ta/pkcs11')
-rw-r--r--ta/pkcs11/src/entry.c39
-rw-r--r--ta/pkcs11/src/pkcs11_attributes.c42
-rw-r--r--ta/pkcs11/src/pkcs11_helpers.c13
-rw-r--r--ta/pkcs11/src/processing.c9
-rw-r--r--ta/pkcs11/src/processing_symm.c132
-rw-r--r--ta/pkcs11/src/token_capabilities.c37
6 files changed, 268 insertions, 4 deletions
diff --git a/ta/pkcs11/src/entry.c b/ta/pkcs11/src/entry.c
index ffd55c25..1f66f7a2 100644
--- a/ta/pkcs11/src/entry.c
+++ b/ta/pkcs11/src/entry.c
@@ -247,7 +247,44 @@ TEE_Result TA_InvokeCommandEntryPoint(void *tee_session, uint32_t cmd,
PKCS11_FUNCTION_DECRYPT,
PKCS11_FUNC_STEP_FINAL);
break;
-
+ case PKCS11_CMD_SIGN_INIT:
+ rc = entry_processing_init(client, ptypes, params,
+ PKCS11_FUNCTION_SIGN);
+ break;
+ case PKCS11_CMD_VERIFY_INIT:
+ rc = entry_processing_init(client, ptypes, params,
+ PKCS11_FUNCTION_VERIFY);
+ break;
+ case PKCS11_CMD_SIGN_ONESHOT:
+ rc = entry_processing_step(client, ptypes, params,
+ PKCS11_FUNCTION_SIGN,
+ PKCS11_FUNC_STEP_ONESHOT);
+ break;
+ case PKCS11_CMD_VERIFY_ONESHOT:
+ rc = entry_processing_step(client, ptypes, params,
+ PKCS11_FUNCTION_VERIFY,
+ PKCS11_FUNC_STEP_ONESHOT);
+ break;
+ case PKCS11_CMD_SIGN_UPDATE:
+ rc = entry_processing_step(client, ptypes, params,
+ PKCS11_FUNCTION_SIGN,
+ PKCS11_FUNC_STEP_UPDATE);
+ break;
+ case PKCS11_CMD_VERIFY_UPDATE:
+ rc = entry_processing_step(client, ptypes, params,
+ PKCS11_FUNCTION_VERIFY,
+ PKCS11_FUNC_STEP_UPDATE);
+ break;
+ case PKCS11_CMD_SIGN_FINAL:
+ rc = entry_processing_step(client, ptypes, params,
+ PKCS11_FUNCTION_SIGN,
+ PKCS11_FUNC_STEP_FINAL);
+ break;
+ case PKCS11_CMD_VERIFY_FINAL:
+ rc = entry_processing_step(client, ptypes, params,
+ PKCS11_FUNCTION_VERIFY,
+ PKCS11_FUNC_STEP_FINAL);
+ break;
default:
EMSG("Command %#"PRIx32" is not supported", cmd);
return TEE_ERROR_NOT_SUPPORTED;
diff --git a/ta/pkcs11/src/pkcs11_attributes.c b/ta/pkcs11/src/pkcs11_attributes.c
index 923f4db2..31eb358b 100644
--- a/ta/pkcs11/src/pkcs11_attributes.c
+++ b/ta/pkcs11/src/pkcs11_attributes.c
@@ -1095,6 +1095,48 @@ check_parent_attrs_against_processing(enum pkcs11_mechanism_id proc_id,
return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
+ case PKCS11_CKM_MD5_HMAC:
+ case PKCS11_CKM_SHA_1_HMAC:
+ case PKCS11_CKM_SHA224_HMAC:
+ case PKCS11_CKM_SHA256_HMAC:
+ case PKCS11_CKM_SHA384_HMAC:
+ case PKCS11_CKM_SHA512_HMAC:
+ if (key_class != PKCS11_CKO_SECRET_KEY)
+ return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
+
+ if (key_type == PKCS11_CKK_GENERIC_SECRET)
+ break;
+
+ switch (proc_id) {
+ case PKCS11_CKM_MD5_HMAC:
+ if (key_type == PKCS11_CKK_MD5_HMAC)
+ break;
+ return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
+ case PKCS11_CKM_SHA_1_HMAC:
+ if (key_type == PKCS11_CKK_SHA_1_HMAC)
+ break;
+ return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
+ case PKCS11_CKM_SHA224_HMAC:
+ if (key_type == PKCS11_CKK_SHA224_HMAC)
+ break;
+ return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
+ case PKCS11_CKM_SHA256_HMAC:
+ if (key_type == PKCS11_CKK_SHA256_HMAC)
+ break;
+ return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
+ case PKCS11_CKM_SHA384_HMAC:
+ if (key_type == PKCS11_CKK_SHA384_HMAC)
+ break;
+ return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
+ case PKCS11_CKM_SHA512_HMAC:
+ if (key_type == PKCS11_CKK_SHA512_HMAC)
+ break;
+ return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
+ default:
+ return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
+ }
+ break;
+
default:
DMSG("Invalid processing %#"PRIx32"/%s", proc_id,
id2str_proc(proc_id));
diff --git a/ta/pkcs11/src/pkcs11_helpers.c b/ta/pkcs11/src/pkcs11_helpers.c
index 47bbec05..d987c3ba 100644
--- a/ta/pkcs11/src/pkcs11_helpers.c
+++ b/ta/pkcs11/src/pkcs11_helpers.c
@@ -161,6 +161,14 @@ static const struct any_id __maybe_unused string_ta_cmd[] = {
PKCS11_ID(PKCS11_CMD_DECRYPT_FINAL),
PKCS11_ID(PKCS11_CMD_ENCRYPT_ONESHOT),
PKCS11_ID(PKCS11_CMD_DECRYPT_ONESHOT),
+ PKCS11_ID(PKCS11_CMD_SIGN_INIT),
+ PKCS11_ID(PKCS11_CMD_VERIFY_INIT),
+ PKCS11_ID(PKCS11_CMD_SIGN_UPDATE),
+ PKCS11_ID(PKCS11_CMD_VERIFY_UPDATE),
+ PKCS11_ID(PKCS11_CMD_SIGN_FINAL),
+ PKCS11_ID(PKCS11_CMD_VERIFY_FINAL),
+ PKCS11_ID(PKCS11_CMD_SIGN_ONESHOT),
+ PKCS11_ID(PKCS11_CMD_VERIFY_ONESHOT),
};
static const struct any_id __maybe_unused string_slot_flags[] = {
@@ -248,6 +256,7 @@ static const struct any_id __maybe_unused string_rc[] = {
PKCS11_ID(PKCS11_CKR_USER_TYPE_INVALID),
PKCS11_ID(PKCS11_CKR_KEY_SIZE_RANGE),
PKCS11_ID(PKCS11_CKR_SESSION_READ_ONLY_EXISTS),
+ PKCS11_ID(PKCS11_CKR_SIGNATURE_LEN_RANGE),
PKCS11_ID(PKCS11_RV_NOT_FOUND),
PKCS11_ID(PKCS11_RV_NOT_IMPLEMENTED),
};
@@ -289,6 +298,10 @@ static const struct any_id __maybe_unused string_internal_processing[] = {
static const struct any_id __maybe_unused string_functions[] = {
PKCS11_ID(PKCS11_FUNCTION_IMPORT),
+ PKCS11_ID(PKCS11_FUNCTION_ENCRYPT),
+ PKCS11_ID(PKCS11_FUNCTION_DECRYPT),
+ PKCS11_ID(PKCS11_FUNCTION_SIGN),
+ PKCS11_ID(PKCS11_FUNCTION_VERIFY),
};
/*
diff --git a/ta/pkcs11/src/processing.c b/ta/pkcs11/src/processing.c
index 761e62f5..91220e51 100644
--- a/ta/pkcs11/src/processing.c
+++ b/ta/pkcs11/src/processing.c
@@ -99,6 +99,13 @@ size_t get_object_key_bit_size(struct pkcs11_object *obj)
switch (get_key_type(attrs)) {
case PKCS11_CKK_AES:
+ case PKCS11_CKK_GENERIC_SECRET:
+ case PKCS11_CKK_MD5_HMAC:
+ case PKCS11_CKK_SHA_1_HMAC:
+ case PKCS11_CKK_SHA224_HMAC:
+ case PKCS11_CKK_SHA256_HMAC:
+ case PKCS11_CKK_SHA384_HMAC:
+ case PKCS11_CKK_SHA512_HMAC:
if (get_attribute_ptr(attrs, PKCS11_CKA_VALUE, NULL, &a_size))
return 0;
@@ -254,7 +261,7 @@ enum pkcs11_rc entry_processing_step(struct pkcs11_client *client,
else
rc = PKCS11_CKR_MECHANISM_INVALID;
- if (rc == PKCS11_CKR_OK) {
+ if (rc == PKCS11_CKR_OK && step == PKCS11_FUNC_STEP_UPDATE) {
session->processing->updated = true;
DMSG("PKCS11 session%"PRIu32": processing %s %s",
session->handle, id2str_proc(mecha_type),
diff --git a/ta/pkcs11/src/processing_symm.c b/ta/pkcs11/src/processing_symm.c
index 4f044938..5e9db0b4 100644
--- a/ta/pkcs11/src/processing_symm.c
+++ b/ta/pkcs11/src/processing_symm.c
@@ -23,6 +23,13 @@
bool processing_is_tee_symm(enum pkcs11_mechanism_id proc_id)
{
switch (proc_id) {
+ /* Authentication */
+ case PKCS11_CKM_MD5_HMAC:
+ case PKCS11_CKM_SHA_1_HMAC:
+ case PKCS11_CKM_SHA224_HMAC:
+ case PKCS11_CKM_SHA256_HMAC:
+ case PKCS11_CKM_SHA384_HMAC:
+ case PKCS11_CKM_SHA512_HMAC:
/* Cipherering */
case PKCS11_CKM_AES_ECB:
case PKCS11_CKM_AES_CBC:
@@ -48,6 +55,13 @@ pkcs2tee_algorithm(uint32_t *tee_id, struct pkcs11_attribute_head *proc_params)
{ PKCS11_CKM_AES_CBC_PAD, TEE_ALG_AES_CBC_NOPAD },
{ PKCS11_CKM_AES_CTR, TEE_ALG_AES_CTR },
{ PKCS11_CKM_AES_CTS, TEE_ALG_AES_CTS },
+ /* HMAC flavors */
+ { PKCS11_CKM_MD5_HMAC, TEE_ALG_HMAC_MD5 },
+ { PKCS11_CKM_SHA_1_HMAC, TEE_ALG_HMAC_SHA1 },
+ { PKCS11_CKM_SHA224_HMAC, TEE_ALG_HMAC_SHA224 },
+ { PKCS11_CKM_SHA256_HMAC, TEE_ALG_HMAC_SHA256 },
+ { PKCS11_CKM_SHA384_HMAC, TEE_ALG_HMAC_SHA384 },
+ { PKCS11_CKM_SHA512_HMAC, TEE_ALG_HMAC_SHA512 },
};
size_t n = 0;
@@ -109,7 +123,19 @@ allocate_tee_operation(struct pkcs11_session *session,
return PKCS11_CKR_FUNCTION_FAILED;
/* Sign/Verify with AES or generic key relate to TEE MAC operation */
- pkcs2tee_mode(&mode, function);
+ switch (params->id) {
+ case PKCS11_CKM_MD5_HMAC:
+ case PKCS11_CKM_SHA_1_HMAC:
+ case PKCS11_CKM_SHA224_HMAC:
+ case PKCS11_CKM_SHA256_HMAC:
+ case PKCS11_CKM_SHA384_HMAC:
+ case PKCS11_CKM_SHA512_HMAC:
+ mode = TEE_MODE_MAC;
+ break;
+ default:
+ pkcs2tee_mode(&mode, function);
+ break;
+ }
res = TEE_AllocateOperation(&session->processing->tee_op_handle,
algo, mode, size);
@@ -188,6 +214,18 @@ init_tee_operation(struct pkcs11_session *session,
enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
switch (proc_params->id) {
+ case PKCS11_CKM_MD5_HMAC:
+ case PKCS11_CKM_SHA_1_HMAC:
+ case PKCS11_CKM_SHA224_HMAC:
+ case PKCS11_CKM_SHA256_HMAC:
+ case PKCS11_CKM_SHA384_HMAC:
+ case PKCS11_CKM_SHA512_HMAC:
+ if (proc_params->size)
+ return PKCS11_CKR_MECHANISM_PARAM_INVALID;
+
+ TEE_MACInit(session->processing->tee_op_handle, NULL, 0);
+ rc = PKCS11_CKR_OK;
+ break;
case PKCS11_CKM_AES_ECB:
if (proc_params->size)
return PKCS11_CKR_MECHANISM_PARAM_INVALID;
@@ -273,6 +311,41 @@ static enum pkcs11_rc input_data_size_is_valid(struct active_processing *proc,
return PKCS11_CKR_OK;
}
+/* Validate input buffer size as per PKCS#11 constraints */
+static enum pkcs11_rc input_sign_size_is_valid(struct active_processing *proc,
+ size_t in_size)
+{
+ size_t sign_sz = 0;
+
+ switch (proc->mecha_type) {
+ case PKCS11_CKM_MD5_HMAC:
+ sign_sz = TEE_MD5_HASH_SIZE;
+ break;
+ case PKCS11_CKM_SHA_1_HMAC:
+ sign_sz = TEE_SHA1_HASH_SIZE;
+ break;
+ case PKCS11_CKM_SHA224_HMAC:
+ sign_sz = TEE_SHA224_HASH_SIZE;
+ break;
+ case PKCS11_CKM_SHA256_HMAC:
+ sign_sz = TEE_SHA256_HASH_SIZE;
+ break;
+ case PKCS11_CKM_SHA384_HMAC:
+ sign_sz = TEE_SHA384_HASH_SIZE;
+ break;
+ case PKCS11_CKM_SHA512_HMAC:
+ sign_sz = TEE_SHA512_HASH_SIZE;
+ break;
+ default:
+ return PKCS11_CKR_GENERAL_ERROR;
+ }
+
+ if (in_size < sign_sz)
+ return PKCS11_CKR_SIGNATURE_LEN_RANGE;
+
+ return PKCS11_CKR_OK;
+}
+
/*
* step_sym_cipher - processing symmetric (and related) cipher operation step
*
@@ -336,9 +409,35 @@ enum pkcs11_rc step_symm_operation(struct pkcs11_session *session,
/*
* Feed active operation with data
- * (PKCS11_FUNC_STEP_UPDATE/_ONESHOT)
*/
switch (proc->mecha_type) {
+ case PKCS11_CKM_MD5_HMAC:
+ case PKCS11_CKM_SHA_1_HMAC:
+ case PKCS11_CKM_SHA224_HMAC:
+ case PKCS11_CKM_SHA256_HMAC:
+ case PKCS11_CKM_SHA384_HMAC:
+ case PKCS11_CKM_SHA512_HMAC:
+ if (step == PKCS11_FUNC_STEP_FINAL ||
+ step == PKCS11_FUNC_STEP_ONESHOT)
+ break;
+
+ if (!in_buf) {
+ DMSG("No input data");
+ return PKCS11_CKR_ARGUMENTS_BAD;
+ }
+
+ switch (function) {
+ case PKCS11_FUNCTION_SIGN:
+ case PKCS11_FUNCTION_VERIFY:
+ TEE_MACUpdate(proc->tee_op_handle, in_buf, in_size);
+ rc = PKCS11_CKR_OK;
+ break;
+ default:
+ TEE_Panic(function);
+ break;
+ }
+ break;
+
case PKCS11_CKM_AES_ECB:
case PKCS11_CKM_AES_CBC:
case PKCS11_CKM_AES_CBC_PAD:
@@ -380,6 +479,35 @@ enum pkcs11_rc step_symm_operation(struct pkcs11_session *session,
* Finalize (PKCS11_FUNC_STEP_ONESHOT/_FINAL) operation
*/
switch (session->processing->mecha_type) {
+ case PKCS11_CKM_MD5_HMAC:
+ case PKCS11_CKM_SHA_1_HMAC:
+ case PKCS11_CKM_SHA224_HMAC:
+ case PKCS11_CKM_SHA256_HMAC:
+ case PKCS11_CKM_SHA384_HMAC:
+ case PKCS11_CKM_SHA512_HMAC:
+ switch (function) {
+ case PKCS11_FUNCTION_SIGN:
+ res = TEE_MACComputeFinal(proc->tee_op_handle,
+ in_buf, in_size, out_buf,
+ &out_size);
+ output_data = true;
+ rc = tee2pkcs_error(res);
+ break;
+ case PKCS11_FUNCTION_VERIFY:
+ rc = input_sign_size_is_valid(proc, in2_size);
+ if (rc)
+ return rc;
+ res = TEE_MACCompareFinal(proc->tee_op_handle,
+ in_buf, in_size, in2_buf,
+ in2_size);
+ rc = tee2pkcs_error(res);
+ break;
+ default:
+ TEE_Panic(function);
+ break;
+ }
+ break;
+
case PKCS11_CKM_AES_ECB:
case PKCS11_CKM_AES_CBC:
case PKCS11_CKM_AES_CBC_PAD:
diff --git a/ta/pkcs11/src/token_capabilities.c b/ta/pkcs11/src/token_capabilities.c
index dc1005bf..85e2119c 100644
--- a/ta/pkcs11/src/token_capabilities.c
+++ b/ta/pkcs11/src/token_capabilities.c
@@ -78,6 +78,13 @@ static const struct pkcs11_mechachism_modes pkcs11_modes[] = {
MECHANISM(PKCS11_CKM_AES_CBC_ENCRYPT_DATA, PKCS11_CKFM_DERIVE,
ANY_PART),
MECHANISM(PKCS11_CKM_AES_KEY_GEN, PKCS11_CKFM_GENERATE, ANY_PART),
+ /* HMAC */
+ MECHANISM(PKCS11_CKM_MD5_HMAC, CKFM_AUTH_NO_RECOVER, ANY_PART),
+ MECHANISM(PKCS11_CKM_SHA_1_HMAC, CKFM_AUTH_NO_RECOVER, ANY_PART),
+ MECHANISM(PKCS11_CKM_SHA224_HMAC, CKFM_AUTH_NO_RECOVER, ANY_PART),
+ MECHANISM(PKCS11_CKM_SHA256_HMAC, CKFM_AUTH_NO_RECOVER, ANY_PART),
+ MECHANISM(PKCS11_CKM_SHA384_HMAC, CKFM_AUTH_NO_RECOVER, ANY_PART),
+ MECHANISM(PKCS11_CKM_SHA512_HMAC, CKFM_AUTH_NO_RECOVER, ANY_PART),
};
#if CFG_TEE_TA_LOG_LEVEL > 0
@@ -165,6 +172,12 @@ const struct pkcs11_mechachism_modes token_mechanism[] = {
TA_MECHANISM(PKCS11_CKM_AES_CTS, CKFM_CIPHER),
TA_MECHANISM(PKCS11_CKM_AES_ECB_ENCRYPT_DATA, PKCS11_CKFM_DERIVE),
TA_MECHANISM(PKCS11_CKM_AES_CBC_ENCRYPT_DATA, PKCS11_CKFM_DERIVE),
+ TA_MECHANISM(PKCS11_CKM_MD5_HMAC, CKFM_AUTH_NO_RECOVER),
+ TA_MECHANISM(PKCS11_CKM_SHA_1_HMAC, CKFM_AUTH_NO_RECOVER),
+ TA_MECHANISM(PKCS11_CKM_SHA224_HMAC, CKFM_AUTH_NO_RECOVER),
+ TA_MECHANISM(PKCS11_CKM_SHA256_HMAC, CKFM_AUTH_NO_RECOVER),
+ TA_MECHANISM(PKCS11_CKM_SHA384_HMAC, CKFM_AUTH_NO_RECOVER),
+ TA_MECHANISM(PKCS11_CKM_SHA512_HMAC, CKFM_AUTH_NO_RECOVER),
};
/*
@@ -225,6 +238,30 @@ void mechanism_supported_key_sizes(uint32_t proc_id, uint32_t *min_key_size,
uint32_t *max_key_size)
{
switch (proc_id) {
+ case PKCS11_CKM_MD5_HMAC:
+ *min_key_size = 16;
+ *max_key_size = 16;
+ break;
+ case PKCS11_CKM_SHA_1_HMAC:
+ *min_key_size = 20;
+ *max_key_size = 20;
+ break;
+ case PKCS11_CKM_SHA224_HMAC:
+ *min_key_size = 28;
+ *max_key_size = 28;
+ break;
+ case PKCS11_CKM_SHA256_HMAC:
+ *min_key_size = 32;
+ *max_key_size = 32;
+ break;
+ case PKCS11_CKM_SHA384_HMAC:
+ *min_key_size = 48;
+ *max_key_size = 48;
+ break;
+ case PKCS11_CKM_SHA512_HMAC:
+ *min_key_size = 64;
+ *max_key_size = 64;
+ break;
case PKCS11_CKM_AES_KEY_GEN:
case PKCS11_CKM_AES_ECB:
case PKCS11_CKM_AES_CBC: