diff options
author | Vadim Bendebury <vbendeb@chromium.org> | 2015-11-13 10:50:29 -0800 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2015-11-18 20:39:57 -0800 |
commit | 2196df60704cf85f28683da89fcf35cdbbf8d720 (patch) | |
tree | f3ca2c42d729fc23648094a7b9d0d37b18d6f482 | |
parent | 93760af711a283eb165158c4b9063465b96cb3ca (diff) | |
download | chrome-ec-2196df60704cf85f28683da89fcf35cdbbf8d720.tar.gz |
cr50: add extension command handler for AES testing
The format of the payload the handler expects is as follows:
field | size | note
================================================================
mode | 1 | 0 - decrypt, 1 - encrypt
cipher_mode | 1 | ECB = 0, CTR = 1, CBC = 2, GCM = 3
key_len | 1 | key size in bytes (16, 24 or 32)
key | key len | key to use
iv_len | 1 | either 0 or 16
iv | 0 or 16 | as defined by iv_len
text_len | 2 | size of the text to process, big endian
text | text_len | text to encrypt/decrypt
Current limitations are such that actual size of the payload should
not exceed 2036 bytes and only ECB and CTR cipher modes are supported.
If necessary, input data is padded to the closest size divisible by
16.
The response generated by the handler consists of the result of the
encrypt/decrypt operation, it is always an integer amount of 16 byte
blocks.
The test code is compiled in if CRYPTO_TEST_SETUP is defined, which it
presently is.
BRANCH=none
BUG=chrome-os-partner:47524
TEST=Using the python utility on the host, exercised several NIST test
vectors for ECB and CTR, with key sizes of 128, 192 and 256 bytes
for both AES types. Both cipher text and decryption result match
the vector values.
Change-Id: I148f286d614f0212192a95b5518cddd32935f43d
Signed-off-by: Vadim Bendebury <vbendeb@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/312720
Reviewed-by: Nagendra Modadugu <ngm@google.com>
-rw-r--r-- | board/cr50/dcrypto/dcrypto.h | 3 | ||||
-rw-r--r-- | board/cr50/tpm2/aes.c | 149 |
2 files changed, 151 insertions, 1 deletions
diff --git a/board/cr50/dcrypto/dcrypto.h b/board/cr50/dcrypto/dcrypto.h index 9add80cce0..1dab319392 100644 --- a/board/cr50/dcrypto/dcrypto.h +++ b/board/cr50/dcrypto/dcrypto.h @@ -9,6 +9,9 @@ #ifndef EC_BOARD_CR50_DCRYPTO_DCRYPTO_H_ #define EC_BOARD_CR50_DCRYPTO_DCRYPTO_H_ +/* TODO(vbendeb) don't forget to disable this for prod builds. */ +#define CRYPTO_TEST_SETUP + #include <inttypes.h> enum cipher_mode { diff --git a/board/cr50/tpm2/aes.c b/board/cr50/tpm2/aes.c index e8ef12bcf7..29348ad2ab 100644 --- a/board/cr50/tpm2/aes.c +++ b/board/cr50/tpm2/aes.c @@ -218,7 +218,7 @@ CRYPT_RESULT _cpri__AESEncryptECB( assert(key != NULL); /* Initialize AES hardware. */ if (!DCRYPTO_aes_init(key, num_bits, NULL, - CIPHER_MODE_ECB, ENCRYPT_MODE)) + CIPHER_MODE_ECB, ENCRYPT_MODE)) return CRYPT_PARAMETER; return _cpri__AESBlock(out, len, in); } @@ -250,3 +250,150 @@ CRYPT_RESULT _cpri__AESEncryptOFB( } return CRYPT_SUCCESS; } + +#ifdef CRYPTO_TEST_SETUP + +#include "console.h" +#include "extension.h" +#include "hooks.h" +#include "uart.h" + +#define CPRINTF(format, args...) cprintf(CC_EXTENSION, format, ## args) + +static void aes_command_handler(void *cmd_body, + size_t cmd_size, + size_t *response_size) +{ + uint8_t *key; + uint16_t key_len; + uint8_t iv_len; + uint8_t *iv; + enum cipher_mode c_mode; + enum encrypt_mode e_mode; + uint8_t *cmd = (uint8_t *)cmd_body; + int16_t data_len; + unsigned max_data_len = *response_size; + unsigned actual_cmd_size; + + *response_size = 0; + + /* + * Command structure, shared out of band with the test driver running + * on the host: + * + * field | size | note + * ================================================================ + * mode | 1 | 0 - decrypt, 1 - encrypt + * cipher_mode | 1 | ECB = 0, CTR = 1, CBC = 2, GCM = 3 + * key_len | 1 | key size in bytes (16, 24 or 32) + * key | key len | key to use + * iv_len | 1 | either 0 or 16 + * iv | 0 or 16 | as defined by iv_len + * text_len | 2 | size of the text to process, big endian + * text | text_len | text to encrypt/decrypt + */ + e_mode = *cmd++; + c_mode = *cmd++; + key_len = *cmd++; + + if ((key_len != 16) && (key_len != 24) && (key_len != 32)) { + CPRINTF("Invalid key len %d\n", key_len * 8); + return; + } + key = cmd; + cmd += key_len; + key_len *= 8; + iv_len = *cmd++; + if (iv_len && (iv_len != 16)) { + CPRINTF("Invalid vector len %d\n", iv_len); + return; + } + iv = cmd; + cmd += iv_len; + data_len = *cmd++; + data_len = data_len * 256 + *cmd++; + + /* + * We know that the receive buffer is at least this big, i.e. all the + * preceding fields are guaranteed to fit. + * + * Now is a good time to verify overall sanity of the received + * payload: does the actual size match the added up sizes of the + * pieces. + */ + actual_cmd_size = cmd - (const uint8_t *)cmd_body + data_len; + if (actual_cmd_size != cmd_size) { + CPRINTF("Command size mismatch: %d != %d (data len %d)\n", + actual_cmd_size, cmd_size, data_len); + return; + } + + if (((data_len + 15) & ~15) > max_data_len) { + CPRINTF("Response buffer too small\n"); + return; + } + + + switch (c_mode) { + case CIPHER_MODE_ECB: + if (e_mode == 0) { + if (_cpri__AESDecryptECB((uint8_t *)cmd_body, + key_len, + key, data_len, cmd) == + CRYPT_SUCCESS) { + *response_size = data_len; + } + CPRINTF("%s:%d response size %d\n", + __func__, __LINE__, *response_size); + return; + } + if (e_mode == 1) { + /* pad input data to integer block size. */ + while (data_len & 15) + cmd[data_len++] = 0; + if (_cpri__AESEncryptECB((uint8_t *)cmd_body, + key_len, + key, data_len, cmd) == + CRYPT_SUCCESS) { + *response_size = data_len; + } + CPRINTF("%s:%d response size %d\n", + __func__, __LINE__, *response_size); + return; + } + break; + case CIPHER_MODE_CTR: + if (e_mode == 0) { + if (_cpri__AESDecryptCTR((uint8_t *)cmd_body, + key_len, + key, iv, data_len, cmd) == + CRYPT_SUCCESS) { + *response_size = data_len; + } + CPRINTF("%s:%d response size %d\n", + __func__, __LINE__, *response_size); + return; + } + if (e_mode == 1) { + /* pad input data to integer block size. */ + while (data_len & 15) + cmd[data_len++] = 0; + if (_cpri__AESEncryptCTR((uint8_t *)cmd_body, + key_len, + key, iv, data_len, cmd) == + CRYPT_SUCCESS) { + *response_size = data_len; + } + CPRINTF("%s:%d response size %d\n", + __func__, __LINE__, *response_size); + return; + } + break; + default: + break; + } +} + +DECLARE_EXTENSION_COMMAND(EXTENSION_AES, aes_command_handler); + +#endif /* CRYPTO_TEST_SETUP */ |