summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVadim Bendebury <vbendeb@chromium.org>2015-11-13 10:50:29 -0800
committerchrome-bot <chrome-bot@chromium.org>2015-11-18 20:39:57 -0800
commit2196df60704cf85f28683da89fcf35cdbbf8d720 (patch)
treef3ca2c42d729fc23648094a7b9d0d37b18d6f482
parent93760af711a283eb165158c4b9063465b96cb3ca (diff)
downloadchrome-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.h3
-rw-r--r--board/cr50/tpm2/aes.c149
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 */