summaryrefslogtreecommitdiff
path: root/board/cr50/tpm2/hash.c
diff options
context:
space:
mode:
Diffstat (limited to 'board/cr50/tpm2/hash.c')
-rw-r--r--board/cr50/tpm2/hash.c114
1 files changed, 98 insertions, 16 deletions
diff --git a/board/cr50/tpm2/hash.c b/board/cr50/tpm2/hash.c
index aba5d84a6f..7774a6f819 100644
--- a/board/cr50/tpm2/hash.c
+++ b/board/cr50/tpm2/hash.c
@@ -271,12 +271,68 @@ static void process_finish(int handle, void *response_body,
sizeof(*context));
}
+static uint16_t do_software_hmac(TPM_ALG_ID alg, uint32_t in_len, uint8_t *in,
+ uint32_t out_len, uint8_t *out)
+{
+ CPRI_HASH_STATE hstate;
+ TPM2B_MAX_HASH_BLOCK hmacKey;
+ uint8_t *key;
+ uint32_t key_len;
+ const uint16_t digest_len = _cpri__GetDigestSize(alg);
+
+ if (digest_len == 0)
+ return 0;
+ key = in + in_len;
+ key_len = *key++;
+ key_len = key_len * 256 + *key++;
+ _cpri__StartHMAC(alg, 0, &hstate, key_len, key, &hmacKey.b);
+ _cpri__UpdateHash(&hstate, in_len, in);
+ out_len = _cpri__CompleteHMAC(&hstate, &hmacKey.b, out_len, out);
+ return out_len;
+}
+
+static uint16_t do_dcrypto_hmac(TPM_ALG_ID alg, uint32_t in_len,
+ uint8_t *in, int32_t out_len, uint8_t *out)
+{
+ LITE_HMAC_CTX ctx;
+ uint8_t *key;
+ uint32_t key_len;
+
+ /* Dcrypto only support SHA-256 */
+ if (alg != TPM_ALG_SHA256)
+ return 0;
+ key = in + in_len;
+ key_len = *key++;
+ key_len = key_len * 256 + *key++;
+ DCRYPTO_HMAC_SHA256_init(&ctx, key, key_len);
+ HASH_update(&ctx.hash, in, in_len);
+ out_len = MIN(out_len, SHA256_DIGEST_SIZE);
+ memcpy(out, DCRYPTO_HMAC_final(&ctx), out_len);
+ return out_len;
+}
+
+enum hash_cmd {
+ CMD_HASH_START = 0,
+ CMD_HASH_CONTINUE = 1,
+ CMD_HASH_FINISH = 2,
+ CMD_HASH = 3,
+ CMD_SW_HMAC = 4,
+ CMD_HW_HMAC = 5
+};
+
+enum hash_alg {
+ HASH_ALG_SHA1 = 0,
+ HASH_ALG_SHA256 = 1,
+ HASH_ALG_SHA384 = 2,
+ HASH_ALG_SHA512 = 3
+};
+
static void hash_command_handler(void *cmd_body,
size_t cmd_size,
size_t *response_size)
{
- int mode;
- int hash_mode;
+ enum hash_cmd hash_cmd;
+ enum hash_alg hash_alg;
int handle;
uint16_t text_len;
uint8_t *cmd;
@@ -301,31 +357,36 @@ static void hash_command_handler(void *cmd_body,
*
* field | size | note
* ===================================================================
- * mode | 1 | 0 - start, 1 - cont., 2 - finish, 3 - single
- * hash_mode | 1 | 0 - sha1, 1 - sha256, 2 - sha384, 3 - sha512
+ * hash_cmd | 1 | 0 - start, 1 - cont., 2 - finish, 3 - single
+ * | | 4 - SW HMAC single shot (TPM code)
+ * | | 5 - HW HMAC SHA256 single shot (dcrypto code)
+ * hash_alg | 1 | 0 - sha1, 1 - sha256, 2 - sha384, 3 - sha512
* handle | 1 | session handle, ignored in 'single' mode
* text_len | 2 | size of the text to process, big endian
* text | text_len | text to hash
+ * for HMAC single shot only:
+ * key_len | 2 | size of the key for HMAC, big endian
+ * key | key_len | key for HMAC single shot
*/
- mode = *cmd++;
- hash_mode = *cmd++;
+ hash_cmd = *cmd++;
+ hash_alg = *cmd++;
handle = *cmd++;
text_len = *cmd++;
text_len = text_len * 256 + *cmd++;
- switch (hash_mode) {
- case 0:
+ switch (hash_alg) {
+ case HASH_ALG_SHA1:
alg = TPM_ALG_SHA1;
break;
- case 1:
+ case HASH_ALG_SHA256:
alg = TPM_ALG_SHA256;
break;
#ifdef SHA512_SUPPORT
- case 2:
+ case HASH_ALG_SHA384:
alg = TPM_ALG_SHA384;
break;
- case 3:
+ case HASH_ALG_SHA512:
alg = TPM_ALG_SHA512;
break;
#endif
@@ -333,8 +394,8 @@ static void hash_command_handler(void *cmd_body,
return;
}
- switch (mode) {
- case 0: /* Start a new hash context. */
+ switch (hash_cmd) {
+ case CMD_HASH_START: /* Start a new hash context. */
process_start(alg, handle, cmd_body, response_size);
if (*response_size)
break; /* Something went wrong. */
@@ -342,12 +403,12 @@ static void hash_command_handler(void *cmd_body,
cmd_body, response_size);
break;
- case 1:
+ case CMD_HASH_CONTINUE:
process_continue(handle, cmd, text_len,
cmd_body, response_size);
break;
- case 2:
+ case CMD_HASH_FINISH:
process_continue(handle, cmd, text_len,
cmd_body, response_size);
if (*response_size)
@@ -358,7 +419,7 @@ static void hash_command_handler(void *cmd_body,
*response_size);
break;
- case 3: /* Process a buffer in a single shot. */
+ case CMD_HASH: /* Process a buffer in a single shot. */
/*
* Error responses are just 1 byte in size, valid responses
* are of various hash sizes.
@@ -368,6 +429,27 @@ static void hash_command_handler(void *cmd_body,
CPRINTF("%s:%d response size %d\n", __func__,
__LINE__, *response_size);
break;
+ case CMD_SW_HMAC: /* SW HMAC SHA-256 (key, value) in a single shot. */
+ /*
+ * Error responses are just 1 byte in size, valid responses
+ * are of various hash sizes.
+ */
+ *response_size = do_software_hmac(alg, text_len, cmd,
+ response_room, cmd_body);
+ CPRINTF("%s:%d hmac response size %d\n", __func__, __LINE__,
+ *response_size);
+ break;
+ case CMD_HW_HMAC: /* HW HMAC SHA-256 (key, value) in a single shot */
+ /*
+ * Error responses are just 1 byte in size, valid responses
+ * are of various hash sizes.
+ */
+ *response_size = do_dcrypto_hmac(alg, text_len, cmd,
+ response_room, cmd_body);
+ CPRINTF("%s:%d hmac response size %d\n", __func__, __LINE__,
+ *response_size);
+ break;
+
default:
break;
}