From 1f1def54b76a1c103abd117d73f9af2edfb68985 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Sun, 28 Nov 2021 15:14:47 -0600 Subject: [PATCH 1/3] add aesio to unix coverage build --- .../unix/variants/coverage/mpconfigvariant.mk | 6 +++++- shared-bindings/aesio/aes.c | 8 +++---- tests/unix/extra_coverage.py.exp | 21 ++++++++++--------- 3 files changed, 20 insertions(+), 15 deletions(-) diff --git a/ports/unix/variants/coverage/mpconfigvariant.mk b/ports/unix/variants/coverage/mpconfigvariant.mk index 563b5ad860..d924fc7146 100644 --- a/ports/unix/variants/coverage/mpconfigvariant.mk +++ b/ports/unix/variants/coverage/mpconfigvariant.mk @@ -31,10 +31,14 @@ SRC_BITMAP := \ $(patsubst ../../%,%,$(wildcard ../../shared-bindings/gifio/*.c ../../shared-module/gifio/*.c)) \ shared/runtime/context_manager_helpers.c \ displayio_min.c \ + shared-bindings/aesio/aes.c \ + shared-bindings/aesio/__init__.c \ shared-bindings/bitmaptools/__init__.c \ shared-bindings/displayio/Bitmap.c \ shared-bindings/rainbowio/__init__.c \ shared-bindings/util.c \ + shared-module/aesio/aes.c \ + shared-module/aesio/__init__.c \ shared-module/bitmaptools/__init__.c \ shared-module/displayio/area.c \ shared-module/displayio/Bitmap.c \ @@ -45,7 +49,7 @@ SRC_BITMAP := \ $(info $(SRC_BITMAP)) SRC_C += $(SRC_BITMAP) -CFLAGS += -DCIRCUITPY_GIFIO=1 -DCIRCUITPY_DISPLAYIO_UNIX=1 -DCIRCUITPY_BITMAPTOOLS=1 -DCIRCUITPY_RAINBOWIO=1 +CFLAGS += -DCIRCUITPY_GIFIO=1 -DCIRCUITPY_DISPLAYIO_UNIX=1 -DCIRCUITPY_BITMAPTOOLS=1 -DCIRCUITPY_RAINBOWIO=1 -DCIRCUITPY_AESIO=1 SRC_C += coverage.c SRC_CXX += coveragecpp.cpp diff --git a/shared-bindings/aesio/aes.c b/shared-bindings/aesio/aes.c index 152785c584..5737161c32 100644 --- a/shared-bindings/aesio/aes.c +++ b/shared-bindings/aesio/aes.c @@ -41,10 +41,10 @@ STATIC mp_obj_t aesio_aes_make_new(const mp_obj_type_t *type, size_t n_args, (void)type; enum { ARG_key, ARG_mode, ARG_IV, ARG_counter, ARG_segment_size }; static const mp_arg_t allowed_args[] = { - {MP_QSTR_key, MP_ARG_OBJ | MP_ARG_REQUIRED}, - {MP_QSTR_mode, MP_ARG_INT, {.u_int = AES_MODE_ECB}}, - {MP_QSTR_IV, MP_ARG_OBJ}, - {MP_QSTR_counter, MP_ARG_OBJ}, + {MP_QSTR_key, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_obj = MP_OBJ_NULL} }, + {MP_QSTR_mode, MP_ARG_INT, {.u_int = AES_MODE_ECB} }, + {MP_QSTR_IV, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + {MP_QSTR_counter, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, {MP_QSTR_segment_size, MP_ARG_INT, {.u_int = 8}}, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; diff --git a/tests/unix/extra_coverage.py.exp b/tests/unix/extra_coverage.py.exp index 278c6601a3..54efc744cb 100644 --- a/tests/unix/extra_coverage.py.exp +++ b/tests/unix/extra_coverage.py.exp @@ -29,16 +29,17 @@ RuntimeError: ame__ mport -builtins micropython _thread array -binascii bitmaptools btree cexample -cmath collections cppexample displayio -errno ffi framebuf gc -gifio hashlib json math -qrio rainbowio re sys -termios ubinascii uctypes uerrno -uheapq uio ujson ulab -uos urandom ure uselect -ustruct utime utimeq uzlib +builtins micropython _thread aesio +array binascii bitmaptools btree +cexample cmath collections cppexample +displayio errno ffi framebuf +gc gifio hashlib json +math qrio rainbowio re +sys termios ubinascii uctypes +uerrno uheapq uio ujson +ulab uos urandom ure +uselect ustruct utime utimeq +uzlib ime utime utimeq From 62895b26369d581d29127a6a2f204ff928eac437 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 30 Nov 2021 15:21:20 -0600 Subject: [PATCH 2/3] aesio: fix docs --- shared-bindings/aesio/aes.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/shared-bindings/aesio/aes.c b/shared-bindings/aesio/aes.c index 5737161c32..232f4bede8 100644 --- a/shared-bindings/aesio/aes.c +++ b/shared-bindings/aesio/aes.c @@ -9,6 +9,10 @@ // Defined at the end of this file +//| MODE_ECB: int +//| MODE_CBC: int +//| MODE_CTR: int +//| //| class AES: //| """Encrypt and decrypt AES streams""" //| @@ -16,8 +20,8 @@ //| """Create a new AES state with the given key. //| //| :param ~_typing.ReadableBuffer key: A 16-, 24-, or 32-byte key -//| :param int mode: AES mode to use. One of: AES.MODE_ECB, AES.MODE_CBC, or -//| AES.MODE_CTR +//| :param int mode: AES mode to use. One of: `MODE_ECB`, `MODE_CBC`, or +//| `MODE_CTR` //| :param ~_typing.ReadableBuffer iv: Initialization vector to use for CBC or CTR mode //| //| Additional arguments are supported for legacy reasons. @@ -30,7 +34,7 @@ //| key = b'Sixteen byte key' //| inp = b'CircuitPython!!!' # Note: 16-bytes long //| outp = bytearray(len(inp)) -//| cipher = aesio.AES(key, aesio.mode.MODE_ECB) +//| cipher = aesio.AES(key, aesio.MODE_ECB) //| cipher.encrypt_into(inp, outp) //| hexlify(outp)""" //| ... From 1654f5fb581eb6410870cfc417e187349fc82e91 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Sun, 28 Nov 2021 15:09:03 -0600 Subject: [PATCH 3/3] add an aes test This combines some test vectors from the implementation & a NIST standards document, plus the code from the docstring. The test vectors were eyeball-verified. --- tests/circuitpython/aes.py | 99 ++++++++++++++++++++++++++++++++++ tests/circuitpython/aes.py.exp | 36 +++++++++++++ 2 files changed, 135 insertions(+) create mode 100644 tests/circuitpython/aes.py create mode 100644 tests/circuitpython/aes.py.exp diff --git a/tests/circuitpython/aes.py b/tests/circuitpython/aes.py new file mode 100644 index 0000000000..40adc020c6 --- /dev/null +++ b/tests/circuitpython/aes.py @@ -0,0 +1,99 @@ +import aesio +from binascii import hexlify, unhexlify + +# doc example +key = b"Sixteen byte key" +inp = b"CircuitPython!!!" # Note: 16-bytes long +outp = bytearray(len(inp)) +cipher = aesio.AES(key, aesio.MODE_ECB) +cipher.encrypt_into(inp, outp) +print(str(hexlify(outp), "")) + +cipher = aesio.AES(key, aesio.MODE_ECB) +cipher.decrypt_into(outp, outp) +print(str(outp, "")) +print() + +print("ECB") +# ECB mode test vector, from the aes.c source +plaintext = unhexlify( + "6bc1bee22e409f96e93d7e117393172a" + "ae2d8a571e03ac9c9eb76fac45af8e51" + "30c81c46a35ce411e5fbc1191a0a52ef" + "f69f2445df4f9b17ad2b417be66c3710" +) + +key = unhexlify("2b7e151628aed2a6abf7158809cf4f3c") + +cyphertext = bytearray(len(plaintext)) +cipher = aesio.AES(key, aesio.MODE_ECB) +for i in range(0, len(plaintext), 16): + output = memoryview(cyphertext)[i : i + 16] + cipher.encrypt_into(plaintext[i : i + 16], output) + print(str(hexlify(output), "")) +print() + +plaintext = bytearray(len(plaintext)) +cipher = aesio.AES(key, aesio.MODE_ECB) +for i in range(0, len(plaintext), 16): + output = memoryview(plaintext)[i : i + 16] + cipher.decrypt_into(cyphertext[i : i + 16], output) + print(str(hexlify(output), "")) +print() + +print("CBC") +# CBC128-AES128 test vector from NIST Special Publication 800-38A, 2001 edition, p50 + +plaintext = unhexlify( + "6bc1bee22e409f96e93d7e117393172a" + "ae2d8a571e03ac9c9eb76fac45af8e51" + "30c81c46a35ce411e5fbc1191a0a52ef" + "f69f2445df4f9b17ad2b417be66c3710" +) + +key = unhexlify("2b7e151628aed2a6abf7158809cf4f3c") +iv = unhexlify("000102030405060708090a0b0c0d0e0f") +cyphertext = bytearray(len(plaintext)) +cipher = aesio.AES(key, aesio.MODE_CBC, IV=iv) +for i in range(0, len(plaintext), 16): + output = memoryview(cyphertext)[i : i + 16] + cipher.encrypt_into(plaintext[i : i + 16], output) + print(str(hexlify(output), "")) +print() + +plaintext = bytearray(len(plaintext)) +cipher = aesio.AES(key, aesio.MODE_CBC, IV=iv) +for i in range(0, len(plaintext), 16): + output = memoryview(plaintext)[i : i + 16] + cipher.decrypt_into(cyphertext[i : i + 16], output) + print(str(hexlify(output), "")) +print() + + +print("CTR") +# CTR128-AES128 test vector from NIST Special Publication 800-38A, 2001 edition, p55 + +plaintext = unhexlify( + "6bc1bee22e409f96e93d7e117393172a" + "ae2d8a571e03ac9c9eb76fac45af8e51" + "30c81c46a35ce411e5fbc1191a0a52ef" + "f69f2445df4f9b17ad2b417be66c3710" +) + +key = unhexlify("2b7e151628aed2a6abf7158809cf4f3c") +counter = unhexlify("f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff") +cyphertext = bytearray(len(plaintext)) +cipher = aesio.AES(key, aesio.MODE_CTR, IV=counter) +for i in range(0, len(plaintext), 16): + output = memoryview(cyphertext)[i : i + 16] + cipher.encrypt_into(plaintext[i : i + 16], output) + print(str(hexlify(output), "")) +print() + +plaintext = bytearray(len(plaintext)) +cipher = aesio.AES(key, aesio.MODE_CTR, IV=counter) +for i in range(0, len(plaintext), 16): + output = memoryview(plaintext)[i : i + 16] + cipher.decrypt_into(cyphertext[i : i + 16], output) + print(str(hexlify(output), "")) +print() diff --git a/tests/circuitpython/aes.py.exp b/tests/circuitpython/aes.py.exp new file mode 100644 index 0000000000..da0f8c29b1 --- /dev/null +++ b/tests/circuitpython/aes.py.exp @@ -0,0 +1,36 @@ +abb1a1f98f57409e455ac06e71535ffe +CircuitPython!!! + +ECB +3ad77bb40d7a3660a89ecaf32466ef97 +f5d3d58503b9699de785895a96fdbaaf +43b1cd7f598ece23881b00e3ed030688 +7b0c785e27e8ad3f8223207104725dd4 + +6bc1bee22e409f96e93d7e117393172a +ae2d8a571e03ac9c9eb76fac45af8e51 +30c81c46a35ce411e5fbc1191a0a52ef +f69f2445df4f9b17ad2b417be66c3710 + +CBC +7649abac8119b246cee98e9b12e9197d +5086cb9b507219ee95db113a917678b2 +73bed6b8e3c1743b7116e69e22229516 +3ff1caa1681fac09120eca307586e1a7 + +6bc1bee22e409f96e93d7e117393172a +ae2d8a571e03ac9c9eb76fac45af8e51 +30c81c46a35ce411e5fbc1191a0a52ef +f69f2445df4f9b17ad2b417be66c3710 + +CTR +874d6191b620e3261bef6864990db6ce +9806f66b7970fdff8617187bb9fffdff +5ae4df3edbd5d35e5b4f09020db03eab +1e031dda2fbe03d1792170a0f3009cee + +6bc1bee22e409f96e93d7e117393172a +ae2d8a571e03ac9c9eb76fac45af8e51 +30c81c46a35ce411e5fbc1191a0a52ef +f69f2445df4f9b17ad2b417be66c3710 +