CC3XX: Extend HMAC to support arbitrary hash alg
Initial implementation of the HMAC in the refactored driver
supported only SHA256. Extend it to support arbitrary hash
algorithms as long as they're supported by the HW.
Signed-off-by: Antonio de Angelis <antonio.deangelis@arm.com>
Change-Id: I452f9cf3e05b2096a34d1f07985e3638628058b6
diff --git a/platform/ext/accelerator/cc312/cc312-rom/cc3xx_drbg_hmac.c b/platform/ext/accelerator/cc312/cc312-rom/cc3xx_drbg_hmac.c
index 83ae108..009875d 100644
--- a/platform/ext/accelerator/cc312/cc312-rom/cc3xx_drbg_hmac.c
+++ b/platform/ext/accelerator/cc312/cc312-rom/cc3xx_drbg_hmac.c
@@ -31,9 +31,10 @@
const uint8_t byte0 = 0x00; const uint8_t byte1 = 0x01;
cc3xx_err_t err;
size_t idx;
+ const cc3xx_hash_alg_t alg = CC3XX_HASH_ALG_SHA256;
/* 1. K = HMAC(K, V || 0x00 || provided_data) */
- err = cc3xx_hmac_set_key(&state->h, (const uint8_t *)state->key_k, sizeof(state->key_k));
+ err = cc3xx_hmac_set_key(&state->h, (const uint8_t *)state->key_k, sizeof(state->key_k), alg);
if (err != CC3XX_ERR_SUCCESS) {
return err;
}
@@ -59,7 +60,7 @@
}
/* 2. V = HMAC(K, V) */
- err = cc3xx_hmac_set_key(&state->h, (const uint8_t *)state->key_k, sizeof(state->key_k));
+ err = cc3xx_hmac_set_key(&state->h, (const uint8_t *)state->key_k, sizeof(state->key_k), alg);
if (err != CC3XX_ERR_SUCCESS) {
return err;
}
@@ -78,7 +79,7 @@
}
/* 4. K = HMAC(K, V || 0x01 || provided_data) */
- err = cc3xx_hmac_set_key(&state->h, (const uint8_t *)state->key_k, sizeof(state->key_k));
+ err = cc3xx_hmac_set_key(&state->h, (const uint8_t *)state->key_k, sizeof(state->key_k), alg);
if (err != CC3XX_ERR_SUCCESS) {
return err;
}
@@ -103,7 +104,7 @@
}
/* 5. V = HMAC(K, V) */
- err = cc3xx_hmac_set_key(&state->h, (const uint8_t *)state->key_k, sizeof(state->key_k));
+ err = cc3xx_hmac_set_key(&state->h, (const uint8_t *)state->key_k, sizeof(state->key_k), alg);
if (err != CC3XX_ERR_SUCCESS) {
return err;
}
@@ -151,6 +152,7 @@
size_t data_len[3] = {0};
size_t idx;
size_t last_hmac_update_num = 0;
+ const cc3xx_hash_alg_t alg = CC3XX_HASH_ALG_SHA256;
if (state->reseed_counter == UINT32_MAX) {
/* When we reach 2^32 invocations we must reseed */
@@ -171,7 +173,10 @@
uint32_t temp[CC3XX_DRBG_HMAC_OUTLEN/4];
size_t bytes_to_copy;
/* V = HMAC(K, V) */
- err = cc3xx_hmac_set_key(&state->h, (const uint8_t *)state->key_k, sizeof(state->key_k));
+ err = cc3xx_hmac_set_key(&state->h,
+ (const uint8_t *)state->key_k,
+ sizeof(state->key_k),
+ alg);
if (err != CC3XX_ERR_SUCCESS) {
return err;
}
diff --git a/platform/ext/accelerator/cc312/cc312-rom/cc3xx_hash.h b/platform/ext/accelerator/cc312/cc312-rom/cc3xx_hash.h
index 0e9709b..55c5fd5 100644
--- a/platform/ext/accelerator/cc312/cc312-rom/cc3xx_hash.h
+++ b/platform/ext/accelerator/cc312/cc312-rom/cc3xx_hash.h
@@ -14,9 +14,9 @@
#include <stdint.h>
#include <stddef.h>
-#define SHA1_OUTPUT_SIZE 20
-#define SHA224_OUTPUT_SIZE 28
-#define SHA256_OUTPUT_SIZE 32
+#define SHA1_OUTPUT_SIZE (20)
+#define SHA224_OUTPUT_SIZE (28)
+#define SHA256_OUTPUT_SIZE (32)
typedef enum {
CC3XX_HASH_ALG_SHA1 = 0b0001U,
@@ -24,6 +24,18 @@
CC3XX_HASH_ALG_SHA256 = 0b0010U,
} cc3xx_hash_alg_t;
+/**
+ * @brief Macro that returns the length of the hash associated to the
+ * algorithm value passed as input
+ */
+#define CC3XX_HASH_LENGTH(alg) \
+ ( \
+ alg == CC3XX_HASH_ALG_SHA1 ? SHA1_OUTPUT_SIZE : \
+ alg == CC3XX_HASH_ALG_SHA224 ? SHA224_OUTPUT_SIZE : \
+ alg == CC3XX_HASH_ALG_SHA256 ? SHA256_OUTPUT_SIZE : \
+ 0 \
+ )
+
struct cc3xx_hash_state_t {
cc3xx_hash_alg_t alg;
uint64_t curr_len;
diff --git a/platform/ext/accelerator/cc312/cc312-rom/cc3xx_hmac.c b/platform/ext/accelerator/cc312/cc312-rom/cc3xx_hmac.c
index 557a1c6..1b42fc5 100644
--- a/platform/ext/accelerator/cc312/cc312-rom/cc3xx_hmac.c
+++ b/platform/ext/accelerator/cc312/cc312-rom/cc3xx_hmac.c
@@ -10,15 +10,14 @@
#include "cc3xx_hash.h"
#include "cc3xx_hmac.h"
+/* SHA-1, SHA-224 and SHA-256 have all the same block size */
#define SHA256_BLOCK_SIZE (64)
-/* Hardcode support for SHA-256 based HMAC only */
-static const cc3xx_hash_alg_t alg = CC3XX_HASH_ALG_SHA256;
-
cc3xx_err_t cc3xx_hmac_set_key(
struct cc3xx_hmac_state_t *state,
const uint8_t *key,
- size_t key_size)
+ size_t key_size,
+ cc3xx_hash_alg_t alg)
{
const uint8_t ipad = 0x36;
cc3xx_err_t err;
@@ -40,7 +39,7 @@
goto out;
}
p_key = (const uint8_t *)hash_key_output;
- key_length = SHA256_OUTPUT_SIZE;
+ key_length = CC3XX_HASH_LENGTH(alg);
}
cc3xx_hash_finish(hash_key_output, sizeof(hash_key_output));
@@ -53,7 +52,8 @@
memset(&state->key[key_length], ipad, CC3XX_HMAC_BLOCK_SIZE - key_length);
/* H(K ^ ipad) */
- if ((err = cc3xx_hash_init(alg)) != CC3XX_ERR_SUCCESS) {
+ err = cc3xx_hash_init(alg);
+ if (err != CC3XX_ERR_SUCCESS) {
goto out;
}
@@ -62,6 +62,7 @@
out:
if (err == CC3XX_ERR_SUCCESS) {
cc3xx_hash_get_state(&state->hash);
+ state->alg = alg;
}
cc3xx_hash_uninit();
return err;
@@ -91,12 +92,12 @@
uint32_t *tag,
size_t tag_size)
{
- uint32_t scratch[SHA256_OUTPUT_SIZE / sizeof(uint32_t)];
+ uint32_t scratch[CC3XX_HASH_LENGTH(state->alg) / sizeof(uint32_t)];
const uint8_t ixopad = 0x36 ^ 0x5c; /* ipad ^ opad */
cc3xx_err_t err;
size_t idx;
- assert(tag_size >= SHA256_OUTPUT_SIZE);
+ assert(tag_size >= CC3XX_HASH_LENGTH(state->alg));
cc3xx_hash_set_state(&state->hash);
@@ -109,7 +110,7 @@
}
/* H( K ^ opad | H(K ^ ipad | data)) */
- err = cc3xx_hash_init(alg);
+ err = cc3xx_hash_init(state->alg);
if (err != CC3XX_ERR_SUCCESS) {
goto out;
}
diff --git a/platform/ext/accelerator/cc312/cc312-rom/cc3xx_hmac.h b/platform/ext/accelerator/cc312/cc312-rom/cc3xx_hmac.h
index 5866e8b..6651b1b 100644
--- a/platform/ext/accelerator/cc312/cc312-rom/cc3xx_hmac.h
+++ b/platform/ext/accelerator/cc312/cc312-rom/cc3xx_hmac.h
@@ -29,20 +29,23 @@
struct cc3xx_hmac_state_t {
uint8_t key[CC3XX_HMAC_BLOCK_SIZE];
struct cc3xx_hash_state_t hash; /* Allows to restart low-level hash */
+ cc3xx_hash_alg_t alg; /* Based on the hashing algorithm, sizes change */
} __attribute__((aligned(4)));
/**
* @brief Sets the key for the HMAC operation on the state
*
- * @param state A pointer to a state structure
- * @param key Buffer containing the key
- * @param key_size Size in bytes of the buffer \param key
+ * @param[out] state A pointer to a state structure
+ * @param[in] key Buffer containing the key
+ * @param[in] key_size Size in bytes of the buffer \param key
+ * @param[in] alg Underlying hashing algorithm
* @return cc3xx_err_t
*/
cc3xx_err_t cc3xx_hmac_set_key(
struct cc3xx_hmac_state_t *state,
const uint8_t *key,
- size_t key_size);
+ size_t key_size,
+ cc3xx_hash_alg_t alg);
/**
* @brief Update the HMAC operation with a new chunk of data to authenticate