summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVadim Sukhomlinov <sukhomlinov@google.com>2019-10-10 18:38:32 -0700
committerCommit Bot <commit-bot@chromium.org>2020-01-04 05:25:01 +0000
commit32c349afe72541570984a32bd85b8f1fcf2acb39 (patch)
tree052173a3d8d68ede26f0dcc68922dfc541bcc461
parenta25fd9ccb9b38b2d81cf2027c3f081330c5e9c29 (diff)
downloadchrome-ec-32c349afe72541570984a32bd85b8f1fcf2acb39.tar.gz
cr50: Add support for ACVP tests of HMAC implementations
In order to support NIST ACVP testing, new commands to provide access to HMAC implementations (software, and hardware accelerated HMAC SHA-256) with CRYPTO_TEST_SETUP added: - Software HMAC (_cpri_StartHMAC) TPM implementation - dcrypto HMAC (DCRYPTO_HMAC_SHA256_init) Updated hash_test.py to support different hash algorithms for hash and HMAC, added HMAC tests. BRANCH=cr50 TEST=make BOARD=cr50 CRYPTO_TEST=1 -j && test/tpm_test/tpmtest.py BUG=b:138578319 Change-Id: I57da2f27734fc7e5dbc896d75c5f8b2ed60e3b18 Signed-off-by: Vadim Sukhomlinov <sukhomlinov@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1854885 Reviewed-by: Gurleen Grewal <gurleengrewal@google.com> Reviewed-by: Vadim Bendebury <vbendeb@chromium.org> Commit-Queue: Gurleen Grewal <gurleengrewal@google.com>
-rw-r--r--board/cr50/tpm2/hash.c114
-rw-r--r--test/tpm_test/hash_test.py162
2 files changed, 184 insertions, 92 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;
}
diff --git a/test/tpm_test/hash_test.py b/test/tpm_test/hash_test.py
index 477fa245b7..9f10894d2e 100644
--- a/test/tpm_test/hash_test.py
+++ b/test/tpm_test/hash_test.py
@@ -8,74 +8,70 @@
from __future__ import print_function
import hashlib
+import hmac
import struct
import subcmd
import utils
# Hash command modes
-CMD_START = 0
-CMD_CONT = 1
-CMD_FINISH = 2
-CMD_SINGLE = 3
+CMD_HASH_START = 0
+CMD_HASH_CONT = 1
+CMD_HASH_FINISH = 2
+CMD_HASH = 3
+CMD_HMAC_SW = 4
+CMD_HMAC_HW = 5
-# Hash modes
-MODE_SHA1 = 0
-MODE_SHA256 = 1
-MODE_SHA384 = 2
-MODE_SHA512 = 3
+
+# Hash algorithm
+ALG_SHA1 = 0
+ALG_SHA256 = 1
+ALG_SHA384 = 2
+ALG_SHA512 = 3
# A standard empty response to HASH extended commands.
EMPTY_RESPONSE = ''.join('%c' % x for x in (0x80, 0x01, 0x00, 0x00, 0x00, 0x0c,
0x00, 0x00, 0x00, 0x00, 0x00, 0x01))
test_inputs = (
- # SHA mode cmd mode handle text
- (MODE_SHA1, 'single', 0, ''),
- (MODE_SHA256, 'single', 0, ''),
- (MODE_SHA384, 'single', 0, ''),
- (MODE_SHA512, 'single', 0, ''),
-
- (MODE_SHA1, 'single', 0, 'anything really will work here'),
- (MODE_SHA256, 'single', 0, 'some more text, this time for sha256'),
- (MODE_SHA384, 'single', 0, 'some more text, this time for sha384'),
- (MODE_SHA512, 'single', 0, 'some more text, this time for sha512'),
- (MODE_SHA256, 'start', 1, 'some more text, this time for sha256'),
- (MODE_SHA256, 'cont', 1, 'some more text, this time for sha256'),
- (MODE_SHA256, 'start', 2, 'this could be anything, we just need to'),
- (MODE_SHA1, 'single', 3, 'interleave a SHA1 single calculation'),
- (MODE_SHA256, 'single', 3, 'interleave a SHA256 single calculation'),
- (MODE_SHA1, 'start', 3, 'let\'s interleave a sha1 calculation'),
- (MODE_SHA256, 'cont', 2, 'fill up a second context with something'),
- (MODE_SHA256, 'cont', 1, 'let\'s feed some more into context 1'),
- (MODE_SHA256, 'finish', 1, 'some more text, this time for sha256'),
- (MODE_SHA1, 'cont', 3, 'with two active sha256 calculations'),
- (MODE_SHA1, 'finish', 3, 'this should be enough'),
- (MODE_SHA256, 'finish', 2, 'it does not really matter what'),
- (MODE_SHA384, 'start', 1, 'some more text, this time for sha384'),
- (MODE_SHA384, 'cont', 1, 'some more text, this time for sha384'),
- (MODE_SHA384, 'start', 2, 'this could be anything, we just need to'),
- (MODE_SHA512, 'single', 3, 'interleave a SHA512 single calculation'),
- (MODE_SHA384, 'single', 3, 'interleave a SHA384 single calculation'),
- (MODE_SHA512, 'start', 3, 'let\'s interleave a sha512 calculation'),
- (MODE_SHA384, 'cont', 2, 'fill up a second context with something'),
- (MODE_SHA384, 'cont', 1, 'let\'s feed some more into context 1'),
- (MODE_SHA384, 'finish', 1, 'some more text, this time for sha384'),
- (MODE_SHA512, 'cont', 3, 'with two active sha384 calculations'),
- (MODE_SHA512, 'finish', 3, 'this should be enough'),
- (MODE_SHA384, 'finish', 2, 'it does not really matter what'),
- (MODE_SHA512, 'start', 1, 'some more text, this time for sha512'),
- (MODE_SHA512, 'cont', 1, 'some more text, this time for sha512'),
- (MODE_SHA512, 'start', 2, 'this could be anything, we just need to'),
- (MODE_SHA256, 'single', 3, 'interleave a SHA256 single calculation'),
- (MODE_SHA512, 'single', 3, 'interleave a SHA512 single calculation'),
- (MODE_SHA256, 'start', 3, 'let\'s interleave a sha256 calculation'),
- (MODE_SHA512, 'cont', 2, 'fill up a second context with something'),
- (MODE_SHA512, 'cont', 1, 'let\'s feed some more into context 1'),
- (MODE_SHA512, 'finish', 1, 'some more text, this time for sha512'),
- (MODE_SHA256, 'cont', 3, 'with two active sha512 calculations'),
- (MODE_SHA256, 'finish', 3, 'this should be enough'),
- (MODE_SHA512, 'finish', 2, 'it does not really matter what'),
+ # Hash cmd alg handle hmac_key text
+ (CMD_HMAC_SW, ALG_SHA256, 0, 'hmac_key1', 'some text, this time for sw hmac'),
+ (CMD_HMAC_SW, ALG_SHA1, 0, 'hmac_key2', 'some text, this time for sw hmac'),
+ (CMD_HMAC_SW, ALG_SHA384, 0, 'hmac_key3', 'some text, this time for sw hmac'),
+ (CMD_HMAC_SW, ALG_SHA512, 0, 'hmac_key4', 'some text, this time for sw hmac'),
+ (CMD_HMAC_HW, ALG_SHA256, 0, 'hmac_key5', 'some text, this time for hw hmac'),
+ (CMD_HMAC_SW, ALG_SHA256, 0, 'very long hmac_key 456456789012345', ' text'),
+ (CMD_HMAC_HW, ALG_SHA256, 0, 'very long hmac_key 123456789012345', ' text'),
+ (CMD_HMAC_SW, ALG_SHA384, 0, 'very long hmac_key 456456789012345', ' text'),
+ (CMD_HMAC_SW, ALG_SHA512, 0, 'very long hmac_key 456456789012345', ' text'),
+ (CMD_HASH, ALG_SHA1, 0, '', ''),
+ (CMD_HASH, ALG_SHA256, 0, '', ''),
+ (CMD_HASH, ALG_SHA1, 0, '', 'anything really will work here'),
+ (CMD_HASH, ALG_SHA256, 0, '', 'some more text, this time for sha256'),
+ (CMD_HASH_START, ALG_SHA256, 1, '', 'some more text, this time for sha256'),
+ (CMD_HASH_CONT, ALG_SHA256, 1, '', 'some more text, this time for sha256'),
+ (CMD_HASH_START, ALG_SHA256, 2, '', 'this could be anything here'),
+ (CMD_HASH, ALG_SHA1, 3, '', 'interleave a SHA1 single shot'),
+ (CMD_HASH, ALG_SHA256, 3, '', 'interleave a SHA256 single shot'),
+ (CMD_HASH_START, ALG_SHA1, 3, '', 'let\'s interleave a sha1 calculation'),
+ (CMD_HASH_CONT, ALG_SHA256, 2, '', 'fill up a second context with data'),
+ (CMD_HASH_CONT, ALG_SHA256, 1, '', 'let\'s feed some more into context 1'),
+ (CMD_HASH_FINISH, ALG_SHA256, 1, '', 'some more text, this time for sha256'),
+ (CMD_HASH_CONT, ALG_SHA1, 3, '', 'with two active sha256 calculations'),
+ (CMD_HASH_FINISH, ALG_SHA1, 3, '', 'this should be enough'),
+ (CMD_HASH_FINISH, ALG_SHA256, 2, '', 'it does not really matter what'),
+ (CMD_HASH, ALG_SHA384, 0, '', 'some more text, this time for sha384'),
+ (CMD_HASH, ALG_SHA512, 0, '', 'some more text, this time for sha512'),
+ (CMD_HASH_START, ALG_SHA256, 0, '', 'some more text, this time for sha256'),
+ (CMD_HASH_START, ALG_SHA384, 1, '', 'some more text, this time for sha384'),
+ (CMD_HASH_CONT, ALG_SHA384, 1, '', 'some more text, this time for sha384'),
+ (CMD_HASH_CONT, ALG_SHA256, 0, '', 'some more text, this time for sha256'),
+ (CMD_HASH_START, ALG_SHA512, 2, '', 'some more text, this time for sha512'),
+ (CMD_HASH_CONT, ALG_SHA512, 2, '', 'some more text, this time for sha512'),
+ (CMD_HASH_FINISH, ALG_SHA512, 2, '', 'this should be enough'),
+ (CMD_HASH_FINISH, ALG_SHA256, 0, '', 'this should be enough'),
+ (CMD_HASH_FINISH, ALG_SHA384, 1, '', 'this should be enough'),
)
+
def hash_test(tpm):
"""Exercise multiple hash threads simultaneously.
@@ -83,12 +79,16 @@ def hash_test(tpm):
field | size | note
===================================================================
- hash_cmd | 1 | 0 - start, 1 - cont., 2 - finish, 4 - single
- hash_mode | 1 | 0 - sha1, 1 - sha256
+ 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
Args:
tpm: a tpm object used to communicate with the device
@@ -98,35 +98,42 @@ def hash_test(tpm):
contexts = {}
- function_map = {
- MODE_SHA1: ('sha1', hashlib.sha1),
- MODE_SHA256: ('sha256', hashlib.sha256),
- MODE_SHA384: ('sha384', hashlib.sha384),
- MODE_SHA512: ('sha512', hashlib.sha512)
+ alg_map = {
+ ALG_SHA1: ('sha1', hashlib.sha1),
+ ALG_SHA256: ('sha256', hashlib.sha256),
+ ALG_SHA384: ('sha384', hashlib.sha384),
+ ALG_SHA512: ('sha512', hashlib.sha512),
}
cmd_map = {
- 'start': CMD_START,
- 'cont': CMD_CONT,
- 'finish': CMD_FINISH,
- 'single': CMD_SINGLE
+ CMD_HASH_START: 'hash start',
+ CMD_HASH_CONT: 'hash cont',
+ CMD_HASH_FINISH: 'hash finish',
+ CMD_HASH: 'hash',
+ CMD_HMAC_SW: 'hmac sw',
+ CMD_HMAC_HW: 'hmac hw'
}
for test in test_inputs:
- hash_mode, cmd_name, handle, text = test
+ hash_cmd, hash_alg, handle, hmac_key, text = test
+ mode_name = cmd_map[hash_cmd]
+ alg_name, hash_func = alg_map[hash_alg]
- mode_name, hash_func = function_map[hash_mode]
- hash_cmd = cmd_map[cmd_name]
- test_name = '%s:%s:%d' % (mode_name, cmd_name, handle)
+ test_name = '%s:%s:%d' % (mode_name, alg_name, handle)
cmd = '%c' % hash_cmd
- cmd += '%c' % hash_mode
+ cmd += '%c' % hash_alg
cmd += '%c' % handle # Ignored for single shots
+
cmd += struct.pack('>H', len(text))
cmd += text
+ # for HMAC add key
+ if hash_cmd in (CMD_HMAC_SW, CMD_HMAC_HW):
+ cmd += struct.pack('>H', len(hmac_key))
+ cmd += hmac_key
wrapped_response = tpm.command(tpm.wrap_ext_command(subcmd.HASH, cmd))
- if hash_cmd in (CMD_START, CMD_CONT):
- if hash_cmd == CMD_START:
+ if hash_cmd in (CMD_HASH_START, CMD_HASH_CONT):
+ if hash_cmd == CMD_HASH_START:
contexts[handle] = hash_func()
h = contexts[handle]
h.update(text)
@@ -134,10 +141,12 @@ def hash_test(tpm):
raise subcmd.TpmTestError("Unexpected response to '%s': %s" %
(test_name, utils.hex_dump(wrapped_response)))
continue
- if hash_cmd == CMD_FINISH:
+ if hash_cmd == CMD_HASH_FINISH:
h = contexts[handle]
- elif hash_cmd == CMD_SINGLE:
+ elif hash_cmd == CMD_HASH:
h = hash_func()
+ elif hash_cmd in (CMD_HMAC_SW, CMD_HMAC_HW):
+ h = hmac.new(bytes(hmac_key), digestmod=hash_func)
else:
raise subcmd.TpmTestError('Unknown command %d' % hash_cmd)
h.update(text)
@@ -147,4 +156,5 @@ def hash_test(tpm):
raise subcmd.TpmTestError('%s error:%s%s' % (test_name,
utils.hex_dump(digest),
utils.hex_dump(result)))
+
print('%sSUCCESS: %s' % (utils.cursor_back(), test_name))