From 1a6e0f053add9107bb0c565c84654ed6ff2d8af9 Mon Sep 17 00:00:00 2001 From: Pavol Rusnak Date: Mon, 13 Aug 2018 21:47:57 +0200 Subject: [PATCH] embed/extmod/modtrezorcrypto: refactor AES API, use test from NIST SP 800-38A --- .../modtrezorcrypto/modtrezorcrypto-aes.h | 109 +++++---- .../extmod/modtrezorcrypto/modtrezorcrypto.c | 2 +- src/apps/wallet/cipher_key_value.py | 10 +- src/trezor/crypto/__init__.py | 1 + src/trezor/crypto/aes.py | 71 ------ tests/test_trezor.crypto.aes.py | 207 ++++++++++++++---- vendor/trezor-crypto | 2 +- 7 files changed, 226 insertions(+), 176 deletions(-) delete mode 100644 src/trezor/crypto/aes.py diff --git a/embed/extmod/modtrezorcrypto/modtrezorcrypto-aes.h b/embed/extmod/modtrezorcrypto/modtrezorcrypto-aes.h index d1e4bd0dcb..5671d3ab9d 100644 --- a/embed/extmod/modtrezorcrypto/modtrezorcrypto-aes.h +++ b/embed/extmod/modtrezorcrypto/modtrezorcrypto-aes.h @@ -22,34 +22,26 @@ #include "aes/aes.h" #include "memzero.h" +enum AESMode { + ECB = 0x00, + CBC = 0x01, + CFB = 0x02, + OFB = 0x03, + CTR = 0x04, +}; + /// class AES: /// ''' /// AES context. /// ''' typedef struct _mp_obj_AES_t { mp_obj_base_t base; - union { - aes_encrypt_ctx encrypt_ctx; - aes_decrypt_ctx decrypt_ctx; - } ctx; + aes_encrypt_ctx encrypt_ctx; + aes_decrypt_ctx decrypt_ctx; mp_int_t mode; uint8_t iv[AES_BLOCK_SIZE]; - uint8_t ctr[AES_BLOCK_SIZE]; } mp_obj_AES_t; -enum { - ECB = 0x00, - CBC = 0x01, - CFB = 0x02, - OFB = 0x03, - CTR = 0x04, - Encrypt = 0x40, - Decrypt = 0x80, -}; - -#define AESModeMask 0x3F -#define AESDirMask 0xC0 - /// def __init__(self, mode: int, key: bytes, iv: bytes = None) -> None: /// ''' /// Initialize AES context. @@ -59,7 +51,7 @@ STATIC mp_obj_t mod_trezorcrypto_AES_make_new(const mp_obj_type_t *type, size_t mp_obj_AES_t *o = m_new_obj(mp_obj_AES_t); o->base.type = type; o->mode = mp_obj_get_int(args[0]); - if ((o->mode & AESModeMask) > 0x04) { + if (o->mode < ECB || o->mode > CTR) { mp_raise_ValueError("Invalid AES mode"); } mp_buffer_info_t key; @@ -77,38 +69,24 @@ STATIC mp_obj_t mod_trezorcrypto_AES_make_new(const mp_obj_type_t *type, size_t } else { memset(o->iv, 0, AES_BLOCK_SIZE); } - memset(o->ctr, 0, AES_BLOCK_SIZE); switch (key.len) { case 16: - if (o->mode == (ECB | Decrypt) || o->mode == (CBC | Decrypt)) { - aes_decrypt_key128(key.buf, &(o->ctx.decrypt_ctx)); - } else { - aes_encrypt_key128(key.buf, &(o->ctx.encrypt_ctx)); - } + aes_decrypt_key128(key.buf, &(o->decrypt_ctx)); + aes_encrypt_key128(key.buf, &(o->encrypt_ctx)); break; case 24: - if (o->mode == (ECB | Decrypt) || o->mode == (CBC | Decrypt)) { - aes_decrypt_key192(key.buf, &(o->ctx.decrypt_ctx)); - } else { - aes_encrypt_key192(key.buf, &(o->ctx.encrypt_ctx)); - } + aes_decrypt_key192(key.buf, &(o->decrypt_ctx)); + aes_encrypt_key192(key.buf, &(o->encrypt_ctx)); break; case 32: - if (o->mode == (ECB | Decrypt) || o->mode == (CBC |Decrypt)) { - aes_decrypt_key256(key.buf, &(o->ctx.decrypt_ctx)); - } else { - aes_encrypt_key256(key.buf, &(o->ctx.encrypt_ctx)); - } + aes_decrypt_key256(key.buf, &(o->decrypt_ctx)); + aes_encrypt_key256(key.buf, &(o->encrypt_ctx)); break; } return MP_OBJ_FROM_PTR(o); } -/// def update(self, data: bytes) -> bytes: -/// ''' -/// Update AES context with data. -/// ''' -STATIC mp_obj_t mod_trezorcrypto_AES_update(mp_obj_t self, mp_obj_t data) { +static mp_obj_t aes_update(mp_obj_t self, mp_obj_t data, bool encrypt) { mp_buffer_info_t buf; mp_get_buffer_raise(data, &buf, MP_BUFFER_READ); if (buf.len == 0) { @@ -117,63 +95,80 @@ STATIC mp_obj_t mod_trezorcrypto_AES_update(mp_obj_t self, mp_obj_t data) { vstr_t vstr; vstr_init_len(&vstr, buf.len); mp_obj_AES_t *o = MP_OBJ_TO_PTR(self); - switch (o->mode & AESModeMask) { + switch (o->mode) { case ECB: if (buf.len & (AES_BLOCK_SIZE - 1)) { mp_raise_ValueError("Invalid data length"); } - if ((o->mode & AESDirMask) == Encrypt) { - aes_ecb_encrypt(buf.buf, (uint8_t *)vstr.buf, buf.len, &(o->ctx.encrypt_ctx)); + if (encrypt) { + aes_ecb_encrypt(buf.buf, (uint8_t *)vstr.buf, buf.len, &(o->encrypt_ctx)); } else { - aes_ecb_decrypt(buf.buf, (uint8_t *)vstr.buf, buf.len, &(o->ctx.decrypt_ctx)); + aes_ecb_decrypt(buf.buf, (uint8_t *)vstr.buf, buf.len, &(o->decrypt_ctx)); } break; case CBC: if (buf.len & (AES_BLOCK_SIZE - 1)) { mp_raise_ValueError("Invalid data length"); } - if ((o->mode & AESDirMask) == Encrypt) { - aes_cbc_encrypt(buf.buf, (uint8_t *)vstr.buf, buf.len, o->iv, &(o->ctx.encrypt_ctx)); + if (encrypt) { + aes_cbc_encrypt(buf.buf, (uint8_t *)vstr.buf, buf.len, o->iv, &(o->encrypt_ctx)); } else { - aes_cbc_decrypt(buf.buf, (uint8_t *)vstr.buf, buf.len, o->iv, &(o->ctx.decrypt_ctx)); + aes_cbc_decrypt(buf.buf, (uint8_t *)vstr.buf, buf.len, o->iv, &(o->decrypt_ctx)); } break; case CFB: - if ((o->mode & AESDirMask) == Encrypt) { - aes_cfb_encrypt(buf.buf, (uint8_t *)vstr.buf, buf.len, o->iv, &(o->ctx.encrypt_ctx)); + if (encrypt) { + aes_cfb_encrypt(buf.buf, (uint8_t *)vstr.buf, buf.len, o->iv, &(o->encrypt_ctx)); } else { - aes_cfb_decrypt(buf.buf, (uint8_t *)vstr.buf, buf.len, o->iv, &(o->ctx.encrypt_ctx)); + aes_cfb_decrypt(buf.buf, (uint8_t *)vstr.buf, buf.len, o->iv, &(o->encrypt_ctx)); // decrypt uses encrypt_ctx } break; case OFB: // (encrypt == decrypt) - aes_ofb_crypt(buf.buf, (uint8_t *)vstr.buf, buf.len, o->iv, &(o->ctx.encrypt_ctx)); + aes_ofb_crypt(buf.buf, (uint8_t *)vstr.buf, buf.len, o->iv, &(o->encrypt_ctx)); break; case CTR: // (encrypt == decrypt) - aes_ctr_crypt(buf.buf, (uint8_t *)vstr.buf, buf.len, o->ctr, aes_ctr_cbuf_inc, &(o->ctx.encrypt_ctx)); + aes_ctr_crypt(buf.buf, (uint8_t *)vstr.buf, buf.len, o->iv, aes_ctr_cbuf_inc, &(o->encrypt_ctx)); break; } return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_AES_update_obj, mod_trezorcrypto_AES_update); + +/// def encrypt(self, data: bytes) -> bytes: +/// ''' +/// Encrypt data and update AES context. +/// ''' +STATIC mp_obj_t mod_trezorcrypto_AES_encrypt(mp_obj_t self, mp_obj_t data) { + return aes_update(self, data, true); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_AES_encrypt_obj, mod_trezorcrypto_AES_encrypt); + +/// def decrypt(self, data: bytes) -> bytes: +/// ''' +/// Decrypt data and update AES context. +/// ''' +STATIC mp_obj_t mod_trezorcrypto_AES_decrypt(mp_obj_t self, mp_obj_t data) { + return aes_update(self, data, false); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_AES_decrypt_obj, mod_trezorcrypto_AES_decrypt); STATIC mp_obj_t mod_trezorcrypto_AES___del__(mp_obj_t self) { mp_obj_AES_t *o = MP_OBJ_TO_PTR(self); - memzero(&(o->ctx), sizeof(aes_encrypt_ctx)); + memzero(&(o->encrypt_ctx), sizeof(aes_encrypt_ctx)); + memzero(&(o->decrypt_ctx), sizeof(aes_decrypt_ctx)); memzero(o->iv, AES_BLOCK_SIZE); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_AES___del___obj, mod_trezorcrypto_AES___del__); STATIC const mp_rom_map_elem_t mod_trezorcrypto_AES_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&mod_trezorcrypto_AES_update_obj) }, + { MP_ROM_QSTR(MP_QSTR_encrypt), MP_ROM_PTR(&mod_trezorcrypto_AES_encrypt_obj) }, + { MP_ROM_QSTR(MP_QSTR_decrypt), MP_ROM_PTR(&mod_trezorcrypto_AES_decrypt_obj) }, { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mod_trezorcrypto_AES___del___obj) }, { MP_ROM_QSTR(MP_QSTR_ECB), MP_OBJ_NEW_SMALL_INT(ECB) }, { MP_ROM_QSTR(MP_QSTR_CBC), MP_OBJ_NEW_SMALL_INT(CBC) }, { MP_ROM_QSTR(MP_QSTR_CFB), MP_OBJ_NEW_SMALL_INT(CFB) }, { MP_ROM_QSTR(MP_QSTR_OFB), MP_OBJ_NEW_SMALL_INT(OFB) }, { MP_ROM_QSTR(MP_QSTR_CTR), MP_OBJ_NEW_SMALL_INT(CTR) }, - { MP_ROM_QSTR(MP_QSTR_Encrypt), MP_OBJ_NEW_SMALL_INT(Encrypt) }, - { MP_ROM_QSTR(MP_QSTR_Decrypt), MP_OBJ_NEW_SMALL_INT(Decrypt) }, }; STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_AES_locals_dict, mod_trezorcrypto_AES_locals_dict_table); diff --git a/embed/extmod/modtrezorcrypto/modtrezorcrypto.c b/embed/extmod/modtrezorcrypto/modtrezorcrypto.c index 2ecc86f89b..dd6b4a94c5 100644 --- a/embed/extmod/modtrezorcrypto/modtrezorcrypto.c +++ b/embed/extmod/modtrezorcrypto/modtrezorcrypto.c @@ -51,7 +51,7 @@ STATIC const mp_rom_map_elem_t mp_module_trezorcrypto_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_trezorcrypto) }, - { MP_ROM_QSTR(MP_QSTR_AES), MP_ROM_PTR(&mod_trezorcrypto_AES_type) }, + { MP_ROM_QSTR(MP_QSTR_aes), MP_ROM_PTR(&mod_trezorcrypto_AES_type) }, { MP_ROM_QSTR(MP_QSTR_bip32), MP_ROM_PTR(&mod_trezorcrypto_bip32_module) }, { MP_ROM_QSTR(MP_QSTR_bip39), MP_ROM_PTR(&mod_trezorcrypto_bip39_module) }, { MP_ROM_QSTR(MP_QSTR_blake256), MP_ROM_PTR(&mod_trezorcrypto_Blake256_type) }, diff --git a/src/apps/wallet/cipher_key_value.py b/src/apps/wallet/cipher_key_value.py index 3cde61f13c..44c04ad84e 100644 --- a/src/apps/wallet/cipher_key_value.py +++ b/src/apps/wallet/cipher_key_value.py @@ -1,6 +1,5 @@ from trezor import wire -from trezor.crypto import hmac -from trezor.crypto.aes import AES_CBC_Decrypt, AES_CBC_Encrypt +from trezor.crypto import aes, hmac from trezor.crypto.hashlib import sha512 from trezor.messages.CipheredKeyValue import CipheredKeyValue from trezor.ui.text import Text @@ -40,9 +39,8 @@ def compute_cipher_key_value(msg, seckey: bytes) -> bytes: else: iv = data[32:48] + ctx = aes(aes.CBC, key, iv) if msg.encrypt: - aes = AES_CBC_Encrypt(key=key, iv=iv) + return ctx.encrypt(msg.value) else: - aes = AES_CBC_Decrypt(key=key, iv=iv) - - return aes.update(msg.value) + return ctx.decrypt(msg.value) diff --git a/src/trezor/crypto/__init__.py b/src/trezor/crypto/__init__.py index 254bc3f3d9..c7b2f9bfa2 100644 --- a/src/trezor/crypto/__init__.py +++ b/src/trezor/crypto/__init__.py @@ -1,6 +1,7 @@ from gc import collect from trezorcrypto import ( # noqa: F401 + aes, bip32, bip39, chacha20poly1305, diff --git a/src/trezor/crypto/aes.py b/src/trezor/crypto/aes.py deleted file mode 100644 index 8b9cae1123..0000000000 --- a/src/trezor/crypto/aes.py +++ /dev/null @@ -1,71 +0,0 @@ -from trezorcrypto import AES - - -def AES_ECB_Encrypt(key: bytes) -> AES: - """ - Create AES encryption context in ECB mode - """ - return AES(AES.ECB | AES.Encrypt, key) - - -def AES_ECB_Decrypt(key: bytes) -> AES: - """ - Create AES decryption context in ECB mode - """ - return AES(AES.ECB | AES.Decrypt, key) - - -def AES_CBC_Encrypt(key: bytes, iv: bytes) -> AES: - """ - Create AES encryption context in CBC mode - """ - return AES(AES.CBC | AES.Encrypt, key, iv) - - -def AES_CBC_Decrypt(key: bytes, iv: bytes) -> AES: - """ - Create AES decryption context in CBC mode - """ - return AES(AES.CBC | AES.Decrypt, key, iv) - - -def AES_CFB_Encrypt(key: bytes, iv: bytes) -> AES: - """ - Create AES encryption context in CFB mode - """ - return AES(AES.CFB | AES.Encrypt, key, iv) - - -def AES_CFB_Decrypt(key: bytes, iv: bytes) -> AES: - """ - Create AES decryption context in CFB mode - """ - return AES(AES.CFB | AES.Decrypt, key, iv) - - -def AES_OFB_Encrypt(key: bytes, iv: bytes) -> AES: - """ - Create AES encryption context in OFB mode - """ - return AES(AES.OFB | AES.Encrypt, key, iv) - - -def AES_OFB_Decrypt(key: bytes, iv: bytes) -> AES: - """ - Create AES decryption context in OFB mode - """ - return AES(AES.OFB | AES.Decrypt, key, iv) - - -def AES_CTR_Encrypt(key: bytes) -> AES: - """ - Create AES encryption context in CTR mode - """ - return AES(AES.CTR | AES.Encrypt, key) - - -def AES_CTR_Decrypt(key: bytes) -> AES: - """ - Create AES decryption context in CTR mode - """ - return AES(AES.CTR | AES.Decrypt, key) diff --git a/tests/test_trezor.crypto.aes.py b/tests/test_trezor.crypto.aes.py index dc0cfe3b2f..6bf73866f3 100644 --- a/tests/test_trezor.crypto.aes.py +++ b/tests/test_trezor.crypto.aes.py @@ -1,59 +1,186 @@ from common import * -from trezor.crypto.aes import * +from trezor.crypto import aes class TestCryptoAes(unittest.TestCase): - # vectors from https://github.com/ricmoo/pyaes - key = b'This_key_for_demo_purposes_only!' - iv = b'InitializationVe' + # test vectors from NIST Special Publication 800-38A (Appendix F) + # https://nvlpubs.nist.gov/nistpubs/legacy/sp/nistspecialpublication800-38a.pdf + + iv = unhexlify("000102030405060708090a0b0c0d0e0f") + ctr = unhexlify("f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff") + key128 = unhexlify("2b7e151628aed2a6abf7158809cf4f3c") + key192 = unhexlify("8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b") + key256 = unhexlify( + "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4" + ) def test_ecb(self): - a = AES_ECB_Encrypt(key=self.key) - plain = b'TextMustBe16Byte' - e = a.update(plain) - self.assertEqual(e, b'L6\x95\x85\xe4\xd9\xf1\x8a\xfb\xe5\x94X\x80|\x19\xc3') - a = AES_ECB_Decrypt(key=self.key) - d = a.update(e) - self.assertEqual(d, plain) + vectors128 = [ + ("6bc1bee22e409f96e93d7e117393172a", "3ad77bb40d7a3660a89ecaf32466ef97"), + ("ae2d8a571e03ac9c9eb76fac45af8e51", "f5d3d58503b9699de785895a96fdbaaf"), + ("30c81c46a35ce411e5fbc1191a0a52ef", "43b1cd7f598ece23881b00e3ed030688"), + ("f69f2445df4f9b17ad2b417be66c3710", "7b0c785e27e8ad3f8223207104725dd4"), + ] + vectors192 = [ + ("6bc1bee22e409f96e93d7e117393172a", "bd334f1d6e45f25ff712a214571fa5cc"), + ("ae2d8a571e03ac9c9eb76fac45af8e51", "974104846d0ad3ad7734ecb3ecee4eef"), + ("30c81c46a35ce411e5fbc1191a0a52ef", "ef7afd2270e2e60adce0ba2face6444e"), + ("f69f2445df4f9b17ad2b417be66c3710", "9a4b41ba738d6c72fb16691603c18e0e"), + ] + vectors256 = [ + ("6bc1bee22e409f96e93d7e117393172a", "f3eed1bdb5d2a03c064b5a7e3db181f8"), + ("ae2d8a571e03ac9c9eb76fac45af8e51", "591ccb10d410ed26dc5ba74a31362870"), + ("30c81c46a35ce411e5fbc1191a0a52ef", "b6ed21b99ca6f4f9f153e7b1beafed1d"), + ("f69f2445df4f9b17ad2b417be66c3710", "23304b7a39f9f3ff067d8d8f9e24ecc7"), + ] + for key, vec in [ + (self.key128, vectors128), + (self.key192, vectors192), + (self.key256, vectors256), + ]: + ctx1 = aes(aes.ECB, key) + ctx2 = aes(aes.ECB, key) + for plain, cipher in vec: + plain, cipher = unhexlify(plain), unhexlify(cipher) + e = ctx1.encrypt(plain) + self.assertEqual(e, cipher) + d = ctx2.decrypt(cipher) + self.assertEqual(d, plain) def test_cbc(self): - a = AES_CBC_Encrypt(key=self.key, iv=self.iv) - plain = b'TextMustBe16Byte' - e = a.update(plain) - self.assertEqual(e, b'\xd6:\x18\xe6\xb1\xb3\xc3\xdc\x87\xdf\xa7|\x08{k\xb6') - a = AES_CBC_Decrypt(key=self.key, iv=self.iv) - d = a.update(e) - self.assertEqual(d, plain) + vectors128 = [ + ("6bc1bee22e409f96e93d7e117393172a", "7649abac8119b246cee98e9b12e9197d"), + ("ae2d8a571e03ac9c9eb76fac45af8e51", "5086cb9b507219ee95db113a917678b2"), + ("30c81c46a35ce411e5fbc1191a0a52ef", "73bed6b8e3c1743b7116e69e22229516"), + ("f69f2445df4f9b17ad2b417be66c3710", "3ff1caa1681fac09120eca307586e1a7"), + ] + vectors192 = [ + ("6bc1bee22e409f96e93d7e117393172a", "4f021db243bc633d7178183a9fa071e8"), + ("ae2d8a571e03ac9c9eb76fac45af8e51", "b4d9ada9ad7dedf4e5e738763f69145a"), + ("30c81c46a35ce411e5fbc1191a0a52ef", "571b242012fb7ae07fa9baac3df102e0"), + ("f69f2445df4f9b17ad2b417be66c3710", "08b0e27988598881d920a9e64f5615cd"), + ] + vectors256 = [ + ("6bc1bee22e409f96e93d7e117393172a", "f58c4c04d6e5f1ba779eabfb5f7bfbd6"), + ("ae2d8a571e03ac9c9eb76fac45af8e51", "9cfc4e967edb808d679f777bc6702c7d"), + ("30c81c46a35ce411e5fbc1191a0a52ef", "39f23369a9d9bacfa530e26304231461"), + ("f69f2445df4f9b17ad2b417be66c3710", "b2eb05e2c39be9fcda6c19078c6a9d1b"), + ] + for key, vec in [ + (self.key128, vectors128), + (self.key192, vectors192), + (self.key256, vectors256), + ]: + ctx1 = aes(aes.CBC, key, self.iv) + ctx2 = aes(aes.CBC, key, self.iv) + for plain, cipher in vec: + plain, cipher = unhexlify(plain), unhexlify(cipher) + e = ctx1.encrypt(plain) + self.assertEqual(e, cipher) + d = ctx2.decrypt(cipher) + self.assertEqual(d, plain) def test_cfb(self): - a = AES_CFB_Encrypt(key=self.key, iv=self.iv) - plain = b'TextMustBeAMultipleOfSegmentSize' - e = a.update(plain) - self.assertEqual(e, b'v\xa9\xc1w"\x8aL\x93oU:\x9a\xa5\xa0\x90k\x1a/\xb4\\U\xc3>\xffh\x08\xe5\xac\'\xc4\xcfv') - a = AES_CFB_Decrypt(key=self.key, iv=self.iv) - d = a.update(e) - self.assertEqual(d, plain) + vectors128 = [ + ("6bc1bee22e409f96e93d7e117393172a", "3b3fd92eb72dad20333449f8e83cfb4a"), + ("ae2d8a571e03ac9c9eb76fac45af8e51", "c8a64537a0b3a93fcde3cdad9f1ce58b"), + ("30c81c46a35ce411e5fbc1191a0a52ef", "26751f67a3cbb140b1808cf187a4f4df"), + ("f69f2445df4f9b17ad2b417be66c3710", "c04b05357c5d1c0eeac4c66f9ff7f2e6"), + ] + vectors192 = [ + ("6bc1bee22e409f96e93d7e117393172a", "cdc80d6fddf18cab34c25909c99a4174"), + ("ae2d8a571e03ac9c9eb76fac45af8e51", "67ce7f7f81173621961a2b70171d3d7a"), + ("30c81c46a35ce411e5fbc1191a0a52ef", "2e1e8a1dd59b88b1c8e60fed1efac4c9"), + ("f69f2445df4f9b17ad2b417be66c3710", "c05f9f9ca9834fa042ae8fba584b09ff"), + ] + vectors256 = [ + ("6bc1bee22e409f96e93d7e117393172a", "dc7e84bfda79164b7ecd8486985d3860"), + ("ae2d8a571e03ac9c9eb76fac45af8e51", "39ffed143b28b1c832113c6331e5407b"), + ("30c81c46a35ce411e5fbc1191a0a52ef", "df10132415e54b92a13ed0a8267ae2f9"), + ("f69f2445df4f9b17ad2b417be66c3710", "75a385741ab9cef82031623d55b1e471"), + ] + for key, vec in [ + (self.key128, vectors128), + (self.key192, vectors192), + (self.key256, vectors256), + ]: + ctx1 = aes(aes.CFB, key, self.iv) + ctx2 = aes(aes.CFB, key, self.iv) + for plain, cipher in vec: + plain, cipher = unhexlify(plain), unhexlify(cipher) + e = ctx1.encrypt(plain) + self.assertEqual(e, cipher) + d = ctx2.decrypt(cipher) + self.assertEqual(d, plain) def test_ofb(self): - a = AES_OFB_Encrypt(key=self.key, iv=self.iv) - plain = b'Text may be any length you wish, no padding is required' - e = a.update(plain) - self.assertEqual(e, b'v\xa9\xc1wO\x92^\x9e\rR\x1e\xf7\xb1\xa2\x9d"l1\xc7\xe7\x9d\x87(\xc26s\xdd8\xc8@\xb6\xd9!\xf5\x0cM\xaa\x9b\xc4\xedLD\xe4\xb9\xd8\xdf\x9e\xac\xa1\xb8\xea\x0f\x8ev\xb5') - a = AES_OFB_Decrypt(key=self.key, iv=self.iv) - d = a.update(e) - self.assertEqual(d, plain) + vectors128 = [ + ("6bc1bee22e409f96e93d7e117393172a", "3b3fd92eb72dad20333449f8e83cfb4a"), + ("ae2d8a571e03ac9c9eb76fac45af8e51", "7789508d16918f03f53c52dac54ed825"), + ("30c81c46a35ce411e5fbc1191a0a52ef", "9740051e9c5fecf64344f7a82260edcc"), + ("f69f2445df4f9b17ad2b417be66c3710", "304c6528f659c77866a510d9c1d6ae5e"), + ] + vectors192 = [ + ("6bc1bee22e409f96e93d7e117393172a", "cdc80d6fddf18cab34c25909c99a4174"), + ("ae2d8a571e03ac9c9eb76fac45af8e51", "fcc28b8d4c63837c09e81700c1100401"), + ("30c81c46a35ce411e5fbc1191a0a52ef", "8d9a9aeac0f6596f559c6d4daf59a5f2"), + ("f69f2445df4f9b17ad2b417be66c3710", "6d9f200857ca6c3e9cac524bd9acc92a"), + ] + vectors256 = [ + ("6bc1bee22e409f96e93d7e117393172a", "dc7e84bfda79164b7ecd8486985d3860"), + ("ae2d8a571e03ac9c9eb76fac45af8e51", "4febdc6740d20b3ac88f6ad82a4fb08d"), + ("30c81c46a35ce411e5fbc1191a0a52ef", "71ab47a086e86eedf39d1c5bba97c408"), + ("f69f2445df4f9b17ad2b417be66c3710", "0126141d67f37be8538f5a8be740e484"), + ] + for key, vec in [ + (self.key128, vectors128), + (self.key192, vectors192), + (self.key256, vectors256), + ]: + ctx1 = aes(aes.OFB, key, self.iv) + ctx2 = aes(aes.OFB, key, self.iv) + for plain, cipher in vec: + plain, cipher = unhexlify(plain), unhexlify(cipher) + e = ctx1.encrypt(plain) + self.assertEqual(e, cipher) + d = ctx2.decrypt(cipher) + self.assertEqual(d, plain) def test_ctr(self): - a = AES_CTR_Encrypt(key=self.key) - plain = b'Text may be any length you wish, no padding is required' - e = a.update(plain) - self.assertEqual(e, b'1\xac\xd9d\xbaM\x8b\xf3I\xac\xce]\x8e\xac\xd8B\x8e\x99\x06.\xf0\x93\xc9\xd1\xc6\x0b*\xb1\x15\xf2*\x1dO\xe8\xef\xeeR63D\xb9~\x8a\x18\xe3\xdf\xd5\x08\\\xfa\x97"\x9dl\xb8') - a = AES_CTR_Decrypt(key=self.key) - d = a.update(e) - self.assertEqual(d, plain) + vectors128 = [ + ("6bc1bee22e409f96e93d7e117393172a", "874d6191b620e3261bef6864990db6ce"), + ("ae2d8a571e03ac9c9eb76fac45af8e51", "9806f66b7970fdff8617187bb9fffdff"), + ("30c81c46a35ce411e5fbc1191a0a52ef", "5ae4df3edbd5d35e5b4f09020db03eab"), + ("f69f2445df4f9b17ad2b417be66c3710", "1e031dda2fbe03d1792170a0f3009cee"), + ] + vectors192 = [ + ("6bc1bee22e409f96e93d7e117393172a", "1abc932417521ca24f2b0459fe7e6e0b"), + ("ae2d8a571e03ac9c9eb76fac45af8e51", "090339ec0aa6faefd5ccc2c6f4ce8e94"), + ("30c81c46a35ce411e5fbc1191a0a52ef", "1e36b26bd1ebc670d1bd1d665620abf7"), + ("f69f2445df4f9b17ad2b417be66c3710", "4f78a7f6d29809585a97daec58c6b050"), + ] + vectors256 = [ + ("6bc1bee22e409f96e93d7e117393172a", "601ec313775789a5b7a7f504bbf3d228"), + ("ae2d8a571e03ac9c9eb76fac45af8e51", "f443e3ca4d62b59aca84e990cacaf5c5"), + ("30c81c46a35ce411e5fbc1191a0a52ef", "2b0930daa23de94ce87017ba2d84988d"), + ("f69f2445df4f9b17ad2b417be66c3710", "dfc9c58db67aada613c2dd08457941a6"), + ] + for key, vec in [ + (self.key128, vectors128), + (self.key192, vectors192), + (self.key256, vectors256), + ]: + ctx1 = aes(aes.CTR, key, self.ctr) + ctx2 = aes(aes.CTR, key, self.ctr) + for plain, cipher in vec: + plain, cipher = unhexlify(plain), unhexlify(cipher) + e = ctx1.encrypt(plain) + self.assertEqual(e, cipher) + d = ctx2.decrypt(cipher) + self.assertEqual(d, plain) -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/vendor/trezor-crypto b/vendor/trezor-crypto index ff001a0f12..d454a48b51 160000 --- a/vendor/trezor-crypto +++ b/vendor/trezor-crypto @@ -1 +1 @@ -Subproject commit ff001a0f12565a0d7d51ad3ce5e11e98db6afc25 +Subproject commit d454a48b5169fddacd169e6ca4124b69449501c9