diff options
author | Vadim Sukhomlinov <sukhomlinov@google.com> | 2019-10-10 18:38:32 -0700 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2020-01-04 05:25:01 +0000 |
commit | 32c349afe72541570984a32bd85b8f1fcf2acb39 (patch) | |
tree | 052173a3d8d68ede26f0dcc68922dfc541bcc461 | |
parent | a25fd9ccb9b38b2d81cf2027c3f081330c5e9c29 (diff) | |
download | chrome-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.c | 114 | ||||
-rw-r--r-- | test/tpm_test/hash_test.py | 162 |
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)) |