summaryrefslogtreecommitdiff
path: root/ta/pkcs11
diff options
context:
space:
mode:
authorRuchika Gupta <ruchika.gupta@linaro.org>2020-11-30 13:06:35 +0530
committerJérôme Forissier <jerome@forissier.org>2020-12-07 10:55:35 +0100
commit2158ea6c997a50729b2fd99d35f003d8d7877ba1 (patch)
treee2b0d5202488df6832ff65ccd5f3a216ac84cea3 /ta/pkcs11
parent460ba6215552b8b7fde6131e5fd9e2b3a81c641f (diff)
ta: pkcs11: Add support for big key sizes for HMAC hash Mechanisms
Currently the support for maximum key size supported in HMAC hash functions is limited by the underlying Global TEE implementation. The RFC 2202 and 4231 specify some HMAC test vectors where key size is greater than the sizes as supported in current TEE implementation. For such key sizes, greater than the maximum key size supported by TEE, first hash the key and then use the resultant as the actual key to HMAC. Signed-off-by: Ruchika Gupta <ruchika.gupta@linaro.org> Reviewed-by: Etienne Carriere <etienne.carriere@linaro.org>
Diffstat (limited to 'ta/pkcs11')
-rw-r--r--ta/pkcs11/src/pkcs11_helpers.c39
-rw-r--r--ta/pkcs11/src/pkcs11_helpers.h8
-rw-r--r--ta/pkcs11/src/processing.c2
-rw-r--r--ta/pkcs11/src/processing_symm.c128
4 files changed, 161 insertions, 16 deletions
diff --git a/ta/pkcs11/src/pkcs11_helpers.c b/ta/pkcs11/src/pkcs11_helpers.c
index d987c3ba..d5b0d4b1 100644
--- a/ta/pkcs11/src/pkcs11_helpers.c
+++ b/ta/pkcs11/src/pkcs11_helpers.c
@@ -479,6 +479,45 @@ bool pkcs2tee_load_attr(TEE_Attribute *tee_ref, uint32_t tee_id,
return true;
}
+/*
+ * Initialize a TEE attribute with hash of a target PKCS11 TA attribute
+ * in an object.
+ */
+enum pkcs11_rc pkcs2tee_load_hashed_attr(TEE_Attribute *tee_ref,
+ uint32_t tee_id,
+ struct pkcs11_object *obj,
+ enum pkcs11_attr_id pkcs11_id,
+ uint32_t tee_algo, void *hash_ptr,
+ uint32_t *hash_size)
+{
+ TEE_OperationHandle handle = TEE_HANDLE_NULL;
+ void *a_ptr = NULL;
+ uint32_t a_size = 0;
+ enum pkcs11_rc rc = PKCS11_CKR_OK;
+ TEE_Result res = TEE_ERROR_GENERIC;
+
+ rc = get_attribute_ptr(obj->attributes, pkcs11_id, &a_ptr, &a_size);
+ if (rc)
+ return rc;
+
+ res = TEE_AllocateOperation(&handle, tee_algo, TEE_MODE_DIGEST, 0);
+ if (res) {
+ EMSG("TEE_AllocateOperation() failed %#"PRIx32, tee_algo);
+ return tee2pkcs_error(res);
+ }
+
+ res = TEE_DigestDoFinal(handle, a_ptr, a_size, hash_ptr, hash_size);
+ TEE_FreeOperation(handle);
+ if (res) {
+ EMSG("TEE_DigestDoFinal() failed %#"PRIx32, tee_algo);
+ return PKCS11_CKR_FUNCTION_FAILED;
+ }
+
+ TEE_InitRefAttribute(tee_ref, tee_id, hash_ptr, *hash_size);
+
+ return PKCS11_CKR_OK;
+}
+
/* Easy conversion between PKCS11 TA function of TEE crypto mode */
void pkcs2tee_mode(uint32_t *tee_id, enum processing_func function)
{
diff --git a/ta/pkcs11/src/pkcs11_helpers.h b/ta/pkcs11/src/pkcs11_helpers.h
index 791eb2aa..94346fe4 100644
--- a/ta/pkcs11/src/pkcs11_helpers.h
+++ b/ta/pkcs11/src/pkcs11_helpers.h
@@ -61,6 +61,14 @@ bool pkcs2tee_load_attr(TEE_Attribute *tee_ref, uint32_t tee_id,
struct pkcs11_object *obj,
enum pkcs11_attr_id pkcs11_id);
+/* Hash and load TEE operation attributes from a PKCS11 object */
+enum pkcs11_rc pkcs2tee_load_hashed_attr(TEE_Attribute *tee_ref,
+ uint32_t tee_id,
+ struct pkcs11_object *obj,
+ enum pkcs11_attr_id pkcs11_id,
+ uint32_t tee_algo, void *hash_ptr,
+ uint32_t *hash_size);
+
/* Return true if attribute is a boolean, false otherwise */
static inline bool pkcs11_attr_is_boolean(enum pkcs11_attr_id id)
{
diff --git a/ta/pkcs11/src/processing.c b/ta/pkcs11/src/processing.c
index 69d0f334..4cf896cb 100644
--- a/ta/pkcs11/src/processing.c
+++ b/ta/pkcs11/src/processing.c
@@ -88,6 +88,8 @@ void release_active_processing(struct pkcs11_session *session)
session->processing->tee_op_handle = TEE_HANDLE_NULL;
}
+ TEE_Free(session->processing->extra_ctx);
+
TEE_Free(session->processing);
session->processing = NULL;
}
diff --git a/ta/pkcs11/src/processing_symm.c b/ta/pkcs11/src/processing_symm.c
index a32afab4..3f64b906 100644
--- a/ta/pkcs11/src/processing_symm.c
+++ b/ta/pkcs11/src/processing_symm.c
@@ -132,6 +132,32 @@ static enum pkcs11_rc pkcsmech2tee_key_type(uint32_t *tee_type,
return PKCS11_RV_NOT_FOUND;
}
+static enum pkcs11_rc hmac_to_tee_hash(uint32_t *algo,
+ enum pkcs11_mechanism_id mech_id)
+{
+ static const struct {
+ enum pkcs11_mechanism_id mech;
+ uint32_t tee_id;
+ } hmac_hash[] = {
+ { PKCS11_CKM_MD5_HMAC, TEE_ALG_MD5 },
+ { PKCS11_CKM_SHA_1_HMAC, TEE_ALG_SHA1 },
+ { PKCS11_CKM_SHA224_HMAC, TEE_ALG_SHA224 },
+ { PKCS11_CKM_SHA256_HMAC, TEE_ALG_SHA256 },
+ { PKCS11_CKM_SHA384_HMAC, TEE_ALG_SHA384 },
+ { PKCS11_CKM_SHA512_HMAC, TEE_ALG_SHA512 },
+ };
+ size_t n = 0;
+
+ for (n = 0; n < ARRAY_SIZE(hmac_hash); n++) {
+ if (hmac_hash[n].mech == mech_id) {
+ *algo = hmac_hash[n].tee_id;
+ return PKCS11_CKR_OK;
+ }
+ }
+
+ return PKCS11_RV_NOT_FOUND;
+}
+
static enum pkcs11_rc
allocate_tee_operation(struct pkcs11_session *session,
enum processing_func function,
@@ -164,6 +190,19 @@ allocate_tee_operation(struct pkcs11_session *session,
&max_key_size);
if (key_size < min_key_size)
return PKCS11_CKR_KEY_SIZE_RANGE;
+
+ /*
+ * If size of generic key is greater than the size
+ * supported by TEE API, this is not considered an
+ * error. When loading TEE key, we will hash the key
+ * to generate the appropriate key for HMAC operation.
+ * This key size will not be greater than the
+ * max_key_size. So we can use max_key_size for
+ * TEE_AllocateOperation().
+ */
+ if (key_size > max_key_size)
+ size = max_key_size * 8;
+
mode = TEE_MODE_MAC;
break;
default:
@@ -183,6 +222,42 @@ allocate_tee_operation(struct pkcs11_session *session,
return tee2pkcs_error(res);
}
+static enum pkcs11_rc hash_secret_helper(enum pkcs11_mechanism_id mech_id,
+ struct pkcs11_object *obj,
+ TEE_Attribute *tee_attr,
+ void **ctx,
+ size_t *object_size_bits)
+{
+ uint32_t algo = 0;
+ void *hash_ptr = NULL;
+ uint32_t hash_size = 0;
+ enum pkcs11_rc rc = PKCS11_CKR_OK;
+
+ rc = hmac_to_tee_hash(&algo, mech_id);
+ if (rc)
+ return rc;
+
+ hash_size = TEE_ALG_GET_DIGEST_SIZE(algo);
+ hash_ptr = TEE_Malloc(hash_size, 0);
+ if (!hash_ptr)
+ return PKCS11_CKR_DEVICE_MEMORY;
+
+ rc = pkcs2tee_load_hashed_attr(tee_attr, TEE_ATTR_SECRET_VALUE, obj,
+ PKCS11_CKA_VALUE, algo, hash_ptr,
+ &hash_size);
+ if (rc) {
+ EMSG("No secret/hash error");
+ TEE_Free(hash_ptr);
+ return rc;
+ }
+
+ *ctx = hash_ptr;
+
+ *object_size_bits = hash_size * 8;
+
+ return PKCS11_CKR_OK;
+}
+
static enum pkcs11_rc load_tee_key(struct pkcs11_session *session,
struct pkcs11_object *obj,
struct pkcs11_attribute_head *proc_params)
@@ -193,17 +268,17 @@ static enum pkcs11_rc load_tee_key(struct pkcs11_session *session,
enum pkcs11_key_type key_type = 0;
enum pkcs11_rc rc = PKCS11_CKR_OK;
TEE_Result res = TEE_ERROR_GENERIC;
+ uint32_t max_key_size = 0;
+ uint32_t min_key_size = 0;
if (obj->key_handle != TEE_HANDLE_NULL) {
/* Key was already loaded and fits current need */
goto key_ready;
}
- if (!pkcs2tee_load_attr(&tee_attr, TEE_ATTR_SECRET_VALUE,
- obj, PKCS11_CKA_VALUE)) {
- EMSG("No secret found");
- return PKCS11_CKR_FUNCTION_FAILED;
- }
+ object_size = get_object_key_bit_size(obj);
+ if (!object_size)
+ return PKCS11_CKR_GENERAL_ERROR;
switch (proc_params->id) {
case PKCS11_CKM_MD5_HMAC:
@@ -224,23 +299,43 @@ static enum pkcs11_rc load_tee_key(struct pkcs11_session *session,
else
rc = pkcs2tee_key_type(&tee_key_type, obj);
+ if (rc)
+ return rc;
+
+ mechanism_supported_key_sizes(proc_params->id,
+ &min_key_size,
+ &max_key_size);
+
+ if ((object_size / 8) > max_key_size) {
+ rc = hash_secret_helper(proc_params->id, obj, &tee_attr,
+ &session->processing->extra_ctx,
+ &object_size);
+ if (rc)
+ return rc;
+ } else {
+ if (!pkcs2tee_load_attr(&tee_attr,
+ TEE_ATTR_SECRET_VALUE,
+ obj,
+ PKCS11_CKA_VALUE)) {
+ EMSG("No secret found");
+ return PKCS11_CKR_FUNCTION_FAILED;
+ }
+ }
break;
+
default:
- /*
- * For all other mechanisms, use object key_type
- * to determine the corresponding tee_key_type
- */
rc = pkcs2tee_key_type(&tee_key_type, obj);
+ if (rc)
+ return rc;
+
+ if (!pkcs2tee_load_attr(&tee_attr, TEE_ATTR_SECRET_VALUE,
+ obj, PKCS11_CKA_VALUE)) {
+ EMSG("No secret found");
+ return PKCS11_CKR_FUNCTION_FAILED;
+ }
break;
}
- if (rc)
- return rc;
-
- object_size = get_object_key_bit_size(obj);
- if (!object_size)
- return PKCS11_CKR_GENERAL_ERROR;
-
res = TEE_AllocateTransientObject(tee_key_type, object_size,
&obj->key_handle);
if (res) {
@@ -570,6 +665,7 @@ enum pkcs11_rc step_symm_operation(struct pkcs11_session *session,
TEE_Panic(function);
break;
}
+
break;
case PKCS11_CKM_AES_ECB: