summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornagendra modadugu <ngm@google.com>2016-08-23 16:42:24 -0700
committerchrome-bot <chrome-bot@chromium.org>2016-08-25 01:46:12 -0700
commit9c693370505a83b76014f7f2b357a3a93afd57c2 (patch)
tree30f46b0808d0eb3bbe43edd06aedd05873378a9f
parent7e4564a87e2687aa958e4eb92d758359b6a66eee (diff)
downloadchrome-ec-9c693370505a83b76014f7f2b357a3a93afd57c2.tar.gz
CR50: add tests for AES CBC, CFB and OFB
Add tests for CBC, CFB and OFB AES modes. Also convert tests to use word unligned input parameters, to ensure that the api's are unalignment agnostic. Also add the program used for generating test vectors. BRANCH=none BUG=chrome-os-partner:56413 TEST=tpmtest.py passes Change-Id: I92c9ffece797aa7134d9cdad6ea32e6fe50feef1 Signed-off-by: nagendra modadugu <ngm@google.com> Reviewed-on: https://chromium-review.googlesource.com/374663 Commit-Ready: Nagendra Modadugu <ngm@google.com> Tested-by: Nagendra Modadugu <ngm@google.com> Reviewed-by: Vadim Bendebury <vbendeb@chromium.org> Reviewed-by: Andrey Pronin <apronin@chromium.org>
-rw-r--r--board/cr50/tpm2/aes.c159
-rw-r--r--test/tpm_test/crypto_test.py20
-rw-r--r--test/tpm_test/crypto_test.xml451
-rw-r--r--test/tpm_test/genvectors.py77
4 files changed, 674 insertions, 33 deletions
diff --git a/board/cr50/tpm2/aes.c b/board/cr50/tpm2/aes.c
index 0882e776f0..164f08aeb5 100644
--- a/board/cr50/tpm2/aes.c
+++ b/board/cr50/tpm2/aes.c
@@ -209,6 +209,15 @@ CRYPT_RESULT _cpri__AESEncryptOFB(
#include "hooks.h"
#include "uart.h"
+enum aes_test_cipher_mode {
+ TEST_MODE_ECB = 0,
+ TEST_MODE_CTR = 1,
+ TEST_MODE_CBC = 2,
+ TEST_MODE_GCM = 3,
+ TEST_MODE_OFB = 4,
+ TEST_MODE_CFB = 5,
+};
+
#define CPRINTF(format, args...) cprintf(CC_EXTENSION, format, ## args)
static void aes_command_handler(void *cmd_body,
@@ -219,13 +228,26 @@ static void aes_command_handler(void *cmd_body,
uint16_t key_len;
uint8_t iv_len;
uint8_t *iv;
- enum cipher_mode c_mode;
+ enum aes_test_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;
+ /* Copy inputs into a local unaligned buffer, so as to ensure
+ * that api's are memory-alignment agnostic.
+ */
+ struct unaligned_buf {
+ uint8_t unused;
+ uint8_t b[128];
+ } __packed;
+
+ struct unaligned_buf out_local;
+ struct unaligned_buf iv_local;
+ struct unaligned_buf key_local;
+ struct unaligned_buf data_local;
+
*response_size = 0;
/*
@@ -235,7 +257,7 @@ static void aes_command_handler(void *cmd_body,
* field | size | note
* ================================================================
* mode | 1 | 0 - decrypt, 1 - encrypt
- * cipher_mode | 1 | ECB = 0, CTR = 1, CBC = 2, GCM = 3
+ * cipher_mode | 1 | as per aes_test_cipher_mode
* key_len | 1 | key size in bytes (16, 24 or 32)
* key | key len | key to use
* iv_len | 1 | either 0 or 16
@@ -284,65 +306,150 @@ static void aes_command_handler(void *cmd_body,
return;
}
+ if (data_len > sizeof(out_local.b)) {
+ CPRINTF("Response buffer too small\n");
+ return;
+ }
+
+ memset(out_local.b, 'A', sizeof(out_local.b));
+ memcpy(iv_local.b, iv, iv_len);
+ memcpy(key_local.b, key, key_len / 8);
+ memcpy(data_local.b, cmd, data_len);
switch (c_mode) {
- case CIPHER_MODE_ECB:
+ case TEST_MODE_ECB:
if (e_mode == 0) {
- if (_cpri__AESDecryptECB((uint8_t *)cmd_body,
- key_len,
- key, data_len, cmd) ==
+ if (_cpri__AESDecryptECB(
+ out_local.b, key_len, key_local.b,
+ data_len, data_local.b) ==
CRYPT_SUCCESS) {
*response_size = data_len;
}
CPRINTF("%s:%d response size %d\n",
__func__, __LINE__, *response_size);
- return;
- }
- if (e_mode == 1) {
+ } else 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) ==
+ data_local.b[data_len++] = 0;
+ if (_cpri__AESEncryptECB(
+ out_local.b, key_len, key_local.b,
+ data_len, data_local.b) ==
CRYPT_SUCCESS) {
*response_size = data_len;
}
CPRINTF("%s:%d response size %d\n",
__func__, __LINE__, *response_size);
- return;
}
break;
- case CIPHER_MODE_CTR:
+ case TEST_MODE_CTR:
if (e_mode == 0) {
- if (_cpri__AESDecryptCTR((uint8_t *)cmd_body,
- key_len,
- key, iv, data_len, cmd) ==
+ if (_cpri__AESDecryptCTR(
+ out_local.b, key_len, key_local.b,
+ iv_local.b, data_len, data_local.b) ==
CRYPT_SUCCESS) {
*response_size = data_len;
}
CPRINTF("%s:%d response size %d\n",
__func__, __LINE__, *response_size);
- return;
- }
- if (e_mode == 1) {
+ } else 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) ==
+ data_local.b[data_len++] = 0;
+ if (_cpri__AESEncryptCTR(
+ out_local.b, key_len, key_local.b,
+ iv_local.b, data_len, data_local.b) ==
CRYPT_SUCCESS) {
*response_size = data_len;
}
CPRINTF("%s:%d response size %d\n",
__func__, __LINE__, *response_size);
- return;
}
break;
+ case TEST_MODE_CBC:
+ {
+ if (e_mode == 0) {
+ if (_cpri__AESDecryptCBC(
+ out_local.b, key_len, key_local.b,
+ iv_local.b, data_len, data_local.b) ==
+ CRYPT_SUCCESS) {
+ *response_size = data_len;
+ }
+ CPRINTF("%s:%d response size %d\n",
+ __func__, __LINE__, *response_size);
+ } else if (e_mode == 1) {
+ if (_cpri__AESEncryptCBC(
+ out_local.b, key_len, key_local.b,
+ iv_local.b, data_len, data_local.b) ==
+ CRYPT_SUCCESS) {
+ *response_size = data_len;
+ }
+ CPRINTF("%s:%d response size %d\n",
+ __func__, __LINE__, *response_size);
+ }
+ break;
+ }
+ case TEST_MODE_OFB:
+ if (e_mode == 0) {
+ if (_cpri__AESDecryptOFB(
+ out_local.b, key_len, key_local.b,
+ iv_local.b, data_len, data_local.b) ==
+ CRYPT_SUCCESS) {
+ *response_size = data_len;
+ }
+ CPRINTF("%s:%d response size %d\n",
+ __func__, __LINE__, *response_size);
+ } else if (e_mode == 1) {
+ if (_cpri__AESEncryptOFB(
+ out_local.b, key_len, key_local.b,
+ iv_local.b, data_len, data_local.b) ==
+ CRYPT_SUCCESS) {
+ *response_size = data_len;
+ }
+ CPRINTF("%s:%d response size %d\n",
+ __func__, __LINE__, *response_size);
+ }
+ break;
+ case TEST_MODE_CFB:
+ {
+ if (e_mode == 0) {
+ if (_cpri__AESDecryptCFB(
+ out_local.b, key_len, key_local.b,
+ iv_local.b, data_len, data_local.b) ==
+ CRYPT_SUCCESS) {
+ *response_size = data_len;
+ }
+ CPRINTF("%s:%d response size %d\n",
+ __func__, __LINE__, *response_size);
+ } else if (e_mode == 1) {
+ if (_cpri__AESEncryptCFB(
+ out_local.b, key_len, key_local.b,
+ iv_local.b, data_len, data_local.b) ==
+ CRYPT_SUCCESS) {
+ *response_size = data_len;
+ }
+ CPRINTF("%s:%d response size %d\n",
+ __func__, __LINE__, *response_size);
+ }
+ break;
+ }
default:
break;
}
+
+ if (*response_size > 0) {
+ int i;
+
+ for (i = *response_size; i < sizeof(out_local.b); i++) {
+ if (out_local.b[i] != 'A') {
+ CPRINTF(
+ "%s:%d output overwrite at offset %d\n",
+ __func__, __LINE__, i);
+ *response_size = 0;
+ }
+ }
+
+ memcpy(cmd_body, out_local.b, *response_size);
+ }
}
DECLARE_EXTENSION_COMMAND(EXTENSION_AES, aes_command_handler);
diff --git a/test/tpm_test/crypto_test.py b/test/tpm_test/crypto_test.py
index 929df7c48c..1c292dcdbc 100644
--- a/test/tpm_test/crypto_test.py
+++ b/test/tpm_test/crypto_test.py
@@ -7,6 +7,7 @@
from __future__ import print_function
+import binascii
import struct
import xml.etree.ElementTree as ET
@@ -61,10 +62,8 @@ def get_attribute(tdesc, attr_name, required=True):
# Drop spaces from hex representation.
text = text.replace(' ', '')
- if len(text) & 3:
- raise subcmd.TpmTestError('%s:%s %swrong hex number size' %
- (tdesc.get('name'), attr_name, utils.hex_dump(text)))
- # Convert text to binary
+
+ # Convert hex-text to little-endian binary (in 4-byte word chunks)
value = ''
for x in range(len(text)/8):
try:
@@ -72,6 +71,11 @@ def get_attribute(tdesc, attr_name, required=True):
except ValueError:
raise subcmd.TpmTestError('%s:%s %swrong hex value' %
(tdesc.get('name'), attr_name, utils.hex_dump(text)))
+
+ # Unpack remaining hex text, without introducing a zero pad.
+ for x in range(-1, -(len(text) % 8), -1):
+ value += chr(int(text[2*x:len(text) + (2*x)+2], 16))
+
return value
@@ -98,7 +102,9 @@ SUPPORTED_MODES = {
'ECB': 0,
'CTR': 1,
'CBC': 2,
- 'GCM': 3
+ 'GCM': 3,
+ 'OFB': 4,
+ 'CFB': 5
}),
}
@@ -165,9 +171,9 @@ def crypto_run(node_name, op_type, key, iv, in_text, out_text, tpm):
print('Out text mismatch in node %s:\n' % node_name)
else:
raise subcmd.TpmTestError(
- 'Out text mismatch in node %s, operation %d:\n'
+ 'Out text mismatch in node %s, operation %s:\n'
'In text:%sExpected out text:%sReal out text:%s' % (
- node_name, op_type,
+ node_name, 'ENCRYPT' if op_type == ENCRYPT else 'DECRYPT',
utils.hex_dump(in_text),
utils.hex_dump(out_text),
utils.hex_dump(real_out_text)))
diff --git a/test/tpm_test/crypto_test.xml b/test/tpm_test/crypto_test.xml
index 6de62d8bbb..7cf0758749 100644
--- a/test/tpm_test/crypto_test.xml
+++ b/test/tpm_test/crypto_test.xml
@@ -109,4 +109,455 @@ Many of the crypto_test elements were borrowed from NIST test vectors.
</cipher_text>
<iv>f3f2f1f0 f7f6f5f4 fbfaf9f8 fffefdfc</iv>
</crypto_test>
+
+ <crypto_test name="AES:CBC128 1">
+ <clear_text format="hex">
+ a636839ed2b0ad1abf458f93adb6d5eb
+ </clear_text>
+ <key>
+ 1f5b102067bf5ed28c24733abceb8b17
+ </key>
+ <cipher_text>
+ d955527cf393f7a6a2cdec0f1692104c
+ </cipher_text>
+ <iv>
+ f67c127e03e4f4de49f690f3b953b6db
+ </iv>
+ </crypto_test>
+
+ <crypto_test name="AES:CBC128 2">
+ <clear_text format="hex">
+ da092d3ab24b2a6b585ea1cc7cd2f9f000d06d5c5169d20d02d883eda07224f5
+ </clear_text>
+ <key>
+ 8587d0474afdd5fb265928fea02bce8b
+ </key>
+ <cipher_text>
+ 2f039d2e6324fde3778a77f011b975d6e0ac68ad12edee19308536028e7d6e0e
+ </cipher_text>
+ <iv>
+ fd450534ab529f92567ab5c05f221ce2
+ </iv>
+ </crypto_test>
+
+ <crypto_test name="AES:CBC192 1">
+ <clear_text format="hex">
+ 9b4d5e71fed8bf8650ac1f4165a24dbf
+ </clear_text>
+ <key>
+ 1ccc3bc8256027789502909f6633488906d18472dc5668de
+ </key>
+ <cipher_text>
+ cb0d808aecbf13aadbf9445ef31b211b
+ </cipher_text>
+ <iv>
+ b0aa195cfdb8128cd37006f7be857d2a
+ </iv>
+ </crypto_test>
+
+ <crypto_test name="AES:CBC192 2">
+ <clear_text format="hex">
+ 796a503d47ce4f508c781b05cabdf090b10bbd35eb8f266d6aefdf9c2557d1dd
+ </clear_text>
+ <key>
+ f24f6e0e8de446d81be04e8535cba109af54814946a58281
+ </key>
+ <cipher_text>
+ 2da16ace5b1928f892816c4564a2156110eb6427068a8b84b91d3f7e2e8ba509
+ </cipher_text>
+ <iv>
+ 72cc0e1acd9c45d80ed3aa24748a2d8b
+ </iv>
+ </crypto_test>
+
+ <crypto_test name="AES:CBC256 1">
+ <clear_text format="hex">
+ aac63e7086300c38038512e8897c22d2
+ </clear_text>
+ <key>
+ a0af53a1b0d721ab33888afab77c4629332dd3a6c8e6025da3a5227289dec227
+ </key>
+ <cipher_text>
+ 4b8dd68ed2ddac5a738c0ed8e881574d
+ </cipher_text>
+ <iv>
+ 187a3ea27c383d45b864036adaa27a26
+ </iv>
+ </crypto_test>
+
+ <crypto_test name="AES:CBC256 2">
+ <clear_text format="hex">
+ 02c6dc282c745fe663457d93d3dc6b8259ab14bf7c56ef1ec1ac59c9a650804d
+ </clear_text>
+ <key>
+ 5c01c80bc7206471558c157b5f0c053d9d77a0f3ea81059a1384dc9963e7fa67
+ </key>
+ <cipher_text>
+ de4838d472a8bf060378659f073a640d4978a9602e110eb02f70dade4d49e82b
+ </cipher_text>
+ <iv>
+ 2dbb1d53de16d52185af3828884a61b3
+ </iv>
+ </crypto_test>
+
+ <crypto_test name="AES:CFB128 1">
+ <clear_text format="hex">
+ c27e8ebe08
+ </clear_text>
+ <key>
+ 21df77a9938963824ad4fb63699b9e10
+ </key>
+ <cipher_text>
+ 93541291b3
+ </cipher_text>
+ <iv>
+ 5b906ff8038ecdf186461cde68ceb87d
+ </iv>
+ </crypto_test>
+
+ <crypto_test name="AES:CFB128 2">
+ <clear_text format="hex">
+ 1ba5fec5c8ca5f28a79ee5f531d708c2
+ </clear_text>
+ <key>
+ db5331b06fae350196419746be3c8a99
+ </key>
+ <cipher_text>
+ a44756b5f721ee427f2a46e53ff4d1f5
+ </cipher_text>
+ <iv>
+ f43f8a8fe7db8f22f3627d7d594ead2f
+ </iv>
+ </crypto_test>
+
+ <crypto_test name="AES:CFB128 3">
+ <clear_text format="hex">
+ 8395cf5fa9dc4693d0489ed99ed3d79e4117441110
+ </clear_text>
+ <key>
+ c51e8b5aaac64563fdd3edf3756f4bae
+ </key>
+ <cipher_text>
+ 229f61813f1d51524a11c17075a7999745055b3011
+ </cipher_text>
+ <iv>
+ d4e2873e252d374f3ab8bee783e33056
+ </iv>
+ </crypto_test>
+
+ <crypto_test name="AES:CFB128 4">
+ <clear_text format="hex">
+ a35814e166659c2fd82894bdccde6f6371025b213bde35920423a7223a09eca3
+ </clear_text>
+ <key>
+ 549ab2663df248cd6a971ea07bc4d7b1
+ </key>
+ <cipher_text>
+ 40cf3a37ca6db39340f1004a57dda9ed3d0629cc93e4facf143c62e02246d0e4
+ </cipher_text>
+ <iv>
+ 8a69c1cf5f9611c00b54478e8a27558b
+ </iv>
+ </crypto_test>
+
+ <crypto_test name="AES:CFB192 1">
+ <clear_text format="hex">
+ 86c4803c42
+ </clear_text>
+ <key>
+ 746831e7e595aa3fddcbedc1ae26f94bfce4ee40f3e1e980
+ </key>
+ <cipher_text>
+ 1856d5a500
+ </cipher_text>
+ <iv>
+ 01039108067aaa1d4a5047e15f52a9a3
+ </iv>
+ </crypto_test>
+
+ <crypto_test name="AES:CFB192 2">
+ <clear_text format="hex">
+ 369a7f259cec0ee6cff199b5098dc0ac
+ </clear_text>
+ <key>
+ 6a924856035968f0a1f99e098573085530af14165eb41c01
+ </key>
+ <cipher_text>
+ 49d28326ac3ecabe84b8658ed267beb7
+ </cipher_text>
+ <iv>
+ 944506624e812e1abd7eb0ab7fa08b05
+ </iv>
+ </crypto_test>
+
+ <crypto_test name="AES:CFB192 3">
+ <clear_text format="hex">
+ 7677dda1638143702f960d314c8b42e9ba012528d9
+ </clear_text>
+ <key>
+ a5f67cbae2b8fdd4ade986274787e74b0c943c4bb3f8ebec
+ </key>
+ <cipher_text>
+ 4729f94311972a541de3a0c6a3808e582059db884f
+ </cipher_text>
+ <iv>
+ 511d4661e60516891d167322417d565b
+ </iv>
+ </crypto_test>
+
+ <crypto_test name="AES:CFB192 4">
+ <clear_text format="hex">
+ 2ddc71dd68cd0b01a350180216d1d4de32b620e83c77a96decc5c45b571338ab
+ </clear_text>
+ <key>
+ f929b89472bdffa025a3a060e068734cd018e6a28071e48b
+ </key>
+ <cipher_text>
+ 21e716bd4ebc84627786d1380df8499502dc1c028361442ffbe912fd7052d197
+ </cipher_text>
+ <iv>
+ 23975ea307cc5204f29c235b61687ec1
+ </iv>
+ </crypto_test>
+
+ <crypto_test name="AES:CFB256 1">
+ <clear_text format="hex">
+ d1657ed2b3
+ </clear_text>
+ <key>
+ cc0e6b12df0610b91f6d33ee1f712d87ffc798c157cd11e2f52c9a50bf093371
+ </key>
+ <cipher_text>
+ 3319824a4f
+ </cipher_text>
+ <iv>
+ b123401360708c4aa6f11f5f04e191e1
+ </iv>
+ </crypto_test>
+
+ <crypto_test name="AES:CFB256 2">
+ <clear_text format="hex">
+ 7933ff6df6c98722419edcd3011a0b6b
+ </clear_text>
+ <key>
+ f42a206acd1c7064017cc869eed6a2807ac57e5f25edc220832e1c13daf113e1
+ </key>
+ <cipher_text>
+ ba6b4bd81d0e6926ed83ae684c2dd829
+ </cipher_text>
+ <iv>
+ 79d679c00af714f943a1f649217d34b4
+ </iv>
+ </crypto_test>
+
+ <crypto_test name="AES:CFB256 3">
+ <clear_text format="hex">
+ 913091426fa791d9f7b822e5a5e360ca7d575943ea
+ </clear_text>
+ <key>
+ 3c65a7d551d48c9ee6e37cb3f8d1f31cee6c1369e2068843905249346bbca0fa
+ </key>
+ <cipher_text>
+ fff98201e5fa0b08d818da9a614775c4b1e9d399a8
+ </cipher_text>
+ <iv>
+ 70998e67f207486e575b640cfd8ae59f
+ </iv>
+ </crypto_test>
+
+ <crypto_test name="AES:CFB256 4">
+ <clear_text format="hex">
+ 59ee972cefa6d30c2c3c0c6c73c189066ced4cc0d59afd0728087223d3724943
+ </clear_text>
+ <key>
+ 2826c55b27fdf41c6890a03d4113bb57ae0abb75c5b460e276edc148d3f96dc7
+ </key>
+ <cipher_text>
+ e17c9f488be47bcc54ea366704b9a0941e6e681d8f8445bec6c358038b5169b2
+ </cipher_text>
+ <iv>
+ c3f2173953f34012e82a3f1a6adf9b48
+ </iv>
+ </crypto_test>
+
+ <crypto_test name="AES:OFB128 1">
+ <clear_text format="hex">
+ c69758215b
+ </clear_text>
+ <key>
+ 30499479a11899b1b6c5293528809bd3
+ </key>
+ <cipher_text>
+ 32fab4a0ac
+ </cipher_text>
+ <iv>
+ 36d1827861331652397de67d24b9f6fa
+ </iv>
+ </crypto_test>
+
+ <crypto_test name="AES:OFB128 2">
+ <clear_text format="hex">
+ 41efde8ba6e71b9b034234cb7a99b47c
+ </clear_text>
+ <key>
+ 5b966ff25d38416a701a27f686a915cf
+ </key>
+ <cipher_text>
+ b752d8e79190e4b8491268f1456a9511
+ </cipher_text>
+ <iv>
+ 38acff7be2fdffc9314dfe410b24b3a2
+ </iv>
+ </crypto_test>
+
+ <crypto_test name="AES:OFB128 3">
+ <clear_text format="hex">
+ 49c74e50fb982a979eaf39ac2a558be1a9e5488e4b
+ </clear_text>
+ <key>
+ 49385d8eb6ea0e63cb32c9383d5c3cb6
+ </key>
+ <cipher_text>
+ 6b4f54782fae0cc337b9f806d459df35191fad0b80
+ </cipher_text>
+ <iv>
+ b417edffedd3fc706b5b0fea19ba409b
+ </iv>
+ </crypto_test>
+
+ <crypto_test name="AES:OFB128 4">
+ <clear_text format="hex">
+ 557c59c190a96492e7e3ce9a7c06a8e33931b1ed02002cb8727c4cc93ee7fcc0
+ </clear_text>
+ <key>
+ f458f61d05a9fff961c38cc2edbf02dc
+ </key>
+ <cipher_text>
+ 778ed8ee5ecb0d41bafea9fbfa8ab5f1f4ab34eb176e9aabab0bc86f33370233
+ </cipher_text>
+ <iv>
+ 90dfffe4e188f48eced3b2c39490530f
+ </iv>
+ </crypto_test>
+
+ <crypto_test name="AES:OFB192 1">
+ <clear_text format="hex">
+ bb45f365fd
+ </clear_text>
+ <key>
+ 37fa0d1f182f35cb59a11df8737a0c9d0b56801372d2f7ec
+ </key>
+ <cipher_text>
+ 3e84a0d15c
+ </cipher_text>
+ <iv>
+ b3343ff1fdef4f95944b088e218e1b72
+ </iv>
+ </crypto_test>
+
+ <crypto_test name="AES:OFB192 2">
+ <clear_text format="hex">
+ 44bd7e4e005bc3c01f3f053c7e0589d7
+ </clear_text>
+ <key>
+ 529b351bbe630dbf2d8f0c70331d57848cb773a7b70fe6cb
+ </key>
+ <cipher_text>
+ ac3dc2b0692da4604ac51a7136111bba
+ </cipher_text>
+ <iv>
+ 9fa0ccfcd6368e9fa3ff25137c1a8112
+ </iv>
+ </crypto_test>
+
+ <crypto_test name="AES:OFB192 3">
+ <clear_text format="hex">
+ 0ff5e3ec8a978b623d72cdaf0ef94154b184161d74
+ </clear_text>
+ <key>
+ 165a62acbf5ec4a01405b4a2f90fa50575327ceb8f70eb78
+ </key>
+ <cipher_text>
+ 2e70ae41889b5d3074221fd830fc1c4774a3c53233
+ </cipher_text>
+ <iv>
+ aa4a6b2c9682c261651836c9205efabe
+ </iv>
+ </crypto_test>
+
+ <crypto_test name="AES:OFB192 4">
+ <clear_text format="hex">
+ 4d67b3b279c79349f4ca2cea233a2c982739ee38f40ffd1a2c65c0a15b23b0a0
+ </clear_text>
+ <key>
+ fe9a1fb428ac71ad58a5d701701db9cb385c3f366e0dc4cd
+ </key>
+ <cipher_text>
+ c082c1156c2aaab98094c4a097f1e2d1c986062ce89e86c79420512ad313121d
+ </cipher_text>
+ <iv>
+ db72feeeda791cfcb96b6ee6b724f986
+ </iv>
+ </crypto_test>
+
+ <crypto_test name="AES:OFB256 1">
+ <clear_text format="hex">
+ 732b346426
+ </clear_text>
+ <key>
+ 2d6f926b2954d80e58e00145a74583dcce46efc6167d7d00b7c01ab73ffa83da
+ </key>
+ <cipher_text>
+ 9626f27f3d
+ </cipher_text>
+ <iv>
+ d987a6c6956a951218959da30e2a2169
+ </iv>
+ </crypto_test>
+
+ <crypto_test name="AES:OFB256 2">
+ <clear_text format="hex">
+ 71fd48054f6db38d33c7314c62b362c2
+ </clear_text>
+ <key>
+ b8eee3cd1a391b59d2894dd47faa4a8266c814e95a460184b2361efd8b386a7a
+ </key>
+ <cipher_text>
+ d221511b5691c96a03c8b0729f8fc944
+ </cipher_text>
+ <iv>
+ e9404d883cb1fbfe4a1ed33193f9bbcf
+ </iv>
+ </crypto_test>
+
+ <crypto_test name="AES:OFB256 3">
+ <clear_text format="hex">
+ 4990a1bf14a3c56b62c32c670dbdb0d1bc2ce052d8
+ </clear_text>
+ <key>
+ 8b04f99cf4a659490673fce9e81938895210ff98eb74235c22d5fdcc70f61d96
+ </key>
+ <cipher_text>
+ 1246ec884679c1ddad53052a2daeb05f952e54a2d2
+ </cipher_text>
+ <iv>
+ e401e83a2cf2ece54d4b15ed2805d71d
+ </iv>
+ </crypto_test>
+
+ <crypto_test name="AES:OFB256 4">
+ <clear_text format="hex">
+ f9e4439e4eb67cce27f46417d74bcbb4d38040ac87e9ccbcfa2ad9f6ca612686
+ </clear_text>
+ <key>
+ 5f6bc2dd955f56882c890b619769114796969b7162e1bbcb1260d25f78aae0bb
+ </key>
+ <cipher_text>
+ af05d2d2be7aeea3208e56741144f41369c98691c6e60f3ad2160bcc238d9099
+ </cipher_text>
+ <iv>
+ b11bf6f21675a8799172a8f52ee927a1
+ </iv>
+ </crypto_test>
+
</crypto_tests>
diff --git a/test/tpm_test/genvectors.py b/test/tpm_test/genvectors.py
new file mode 100644
index 0000000000..abab788efc
--- /dev/null
+++ b/test/tpm_test/genvectors.py
@@ -0,0 +1,77 @@
+#!/usr/bin/python
+# Copyright 2016 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Module for generating AES test vectors."""
+
+from binascii import b2a_hex as b2a
+from Crypto.Cipher import AES
+from itertools import izip_longest
+import os
+
+modes = {
+ AES.MODE_CBC: 'CBC',
+ AES.MODE_CFB: 'CFB',
+ AES.MODE_OFB: 'OFB',
+}
+
+template = \
+'''
+ <crypto_test name="AES:{mode}{key_bits} {test_num}">
+ <clear_text format="hex">
+ {pt}
+ </clear_text>
+ <key>
+ {key}
+ </key>
+ <cipher_text>
+ {ct}
+ </cipher_text>
+ <iv>
+ {iv}
+ </iv>
+ </crypto_test>
+'''
+
+def h2be(v):
+ # Convert input big-endian byte-string to 4-byte segmented
+ # little-endian words. Pad-bytes (if necessary) are the empty string.
+ word = [iter(v)] * 4
+ return ''.join([
+ ''.join(b[::-1]) for b in izip_longest(*word, fillvalue='')
+ ])
+
+
+for mode in [AES.MODE_CBC, AES.MODE_CFB, AES.MODE_OFB]:
+ for key_bytes in [16, 24, 32]:
+ test_num = 0
+ for pt_len in [5, 16, 21, 32]:
+ # CBC mode requires block sized inputs.
+ if mode == AES.MODE_CBC and pt_len % 16:
+ continue
+ test_num += 1
+
+ actual_pt_len = pt_len
+ if pt_len % 16:
+ pt_len = 16 * ((pt_len / 16) + 1)
+
+ key = os.urandom(key_bytes)
+ iv = os.urandom(16)
+ pt = os.urandom(pt_len)
+
+ obj = AES.new(key, mode=mode, IV=iv, segment_size=128)
+ ct = obj.encrypt(pt)
+ obj = AES.new(key, mode=mode, IV=iv, segment_size=128)
+
+ assert obj.decrypt(ct)[:pt_len] == pt
+
+ print template.format(mode=modes[mode],
+ key_bits=str(key_bytes * 8),
+ test_num=str(test_num),
+ pt=b2a(h2be(pt[:actual_pt_len])),
+ key=b2a(h2be(key)),
+ ct=b2a(h2be(ct[:actual_pt_len])),
+ iv=b2a(h2be(iv))),
+
+