diff options
author | Ruchika Gupta <ruchika.gupta@linaro.org> | 2020-10-29 12:57:06 +0530 |
---|---|---|
committer | Jérôme Forissier <jerome@forissier.org> | 2020-11-24 08:52:11 +0100 |
commit | 689f4e5b067fea8c8c0566e968ef2bf5303b2082 (patch) | |
tree | 6e19dd31833d788d7b87e105050b71e6dea2f135 /ta/pkcs11 | |
parent | 58ab0c3d6c7294d3faa4e8270e9b6f74bb7671da (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.c | 39 | ||||
-rw-r--r-- | ta/pkcs11/src/pkcs11_attributes.c | 42 | ||||
-rw-r--r-- | ta/pkcs11/src/pkcs11_helpers.c | 13 | ||||
-rw-r--r-- | ta/pkcs11/src/processing.c | 9 | ||||
-rw-r--r-- | ta/pkcs11/src/processing_symm.c | 132 | ||||
-rw-r--r-- | ta/pkcs11/src/token_capabilities.c | 37 |
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: |