From b0a478641611b8bf98359443bc9f751f8547f6a2 Mon Sep 17 00:00:00 2001 From: Skyler Mansfield Date: Thu, 30 May 2024 16:40:56 +0100 Subject: [PATCH 1/8] HMAC: Add tildagon HMAC module --- drivers/micropython.cmake | 6 +++ drivers/tildagon/micropython.cmake | 16 ++++++++ .../{tildagon_py.c => tildagon/tildagon.c} | 13 ++---- drivers/tildagon_hmac/micropython.cmake | 15 +++++++ drivers/tildagon_hmac/tildagon_hmac.c | 40 +++++++++++++++++++ drivers/tildagon_hmac/tildagon_hmac.h | 8 ++++ 6 files changed, 89 insertions(+), 9 deletions(-) create mode 100644 drivers/tildagon/micropython.cmake rename drivers/{tildagon_py.c => tildagon/tildagon.c} (64%) create mode 100644 drivers/tildagon_hmac/micropython.cmake create mode 100644 drivers/tildagon_hmac/tildagon_hmac.c create mode 100644 drivers/tildagon_hmac/tildagon_hmac.h diff --git a/drivers/micropython.cmake b/drivers/micropython.cmake index ea024dd..6cd164a 100644 --- a/drivers/micropython.cmake +++ b/drivers/micropython.cmake @@ -18,3 +18,9 @@ include(${CMAKE_CURRENT_LIST_DIR}/tildagon_power/tildagon_power.cmake) # Add OTA helpers include(${CMAKE_CURRENT_LIST_DIR}/ota/micropython.cmake) + +# Add Tildagon module +include(${CMAKE_CURRENT_LIST_DIR}/tildagon/micropython.cmake) + +# Add HMAC driver +include(${CMAKE_CURRENT_LIST_DIR}/tildagon_hmac/micropython.cmake) diff --git a/drivers/tildagon/micropython.cmake b/drivers/tildagon/micropython.cmake new file mode 100644 index 0000000..0943825 --- /dev/null +++ b/drivers/tildagon/micropython.cmake @@ -0,0 +1,16 @@ +# Create an INTERFACE library for our C module. +add_library(usermod_tildagon INTERFACE) + +# Add our source files to the lib +target_sources(usermod_tildagon INTERFACE + ${CMAKE_CURRENT_LIST_DIR}/tildagon.c +) + +# Add the current directory as an include directory. +target_include_directories(usermod_tildagon INTERFACE + ${CMAKE_CURRENT_LIST_DIR} +) + +# Link our INTERFACE library to the usermod target. +target_link_libraries(usermod_tildagon INTERFACE usermod_tildagon_hmac) +target_link_libraries(usermod INTERFACE usermod_tildagon) diff --git a/drivers/tildagon_py.c b/drivers/tildagon/tildagon.c similarity index 64% rename from drivers/tildagon_py.c rename to drivers/tildagon/tildagon.c index 45f2536..1950962 100644 --- a/drivers/tildagon_py.c +++ b/drivers/tildagon/tildagon.c @@ -1,17 +1,14 @@ #include "py/builtin.h" #include "py/runtime.h" -#if MICROPY_PY_TILDAGON +// #include "tildagon_hmac/tildagon_hmac.h" + +extern const mp_obj_module_t tildagon_hmac_module; -// info() -static mp_obj_t py_tildagon_info(void) { - return MP_OBJ_NEW_SMALL_INT(42); -} -MP_DEFINE_CONST_FUN_OBJ_0(tildagon_info_obj, py_tildagon_info); static const mp_rom_map_elem_t mp_module_tildagon_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_tildagon) }, - { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&tildagon_info_obj) }, + { MP_ROM_QSTR(MP_QSTR_HMAC), MP_ROM_PTR(&tildagon_hmac_module) }, }; static MP_DEFINE_CONST_DICT(mp_module_tildagon_globals, mp_module_tildagon_globals_table); @@ -21,5 +18,3 @@ const mp_obj_module_t mp_module_tildagon = { }; MP_REGISTER_MODULE(MP_QSTR_tildagon, mp_module_tildagon); - -#endif \ No newline at end of file diff --git a/drivers/tildagon_hmac/micropython.cmake b/drivers/tildagon_hmac/micropython.cmake new file mode 100644 index 0000000..99a05de --- /dev/null +++ b/drivers/tildagon_hmac/micropython.cmake @@ -0,0 +1,15 @@ +# Create an INTERFACE library for our C module. +add_library(usermod_tildagon_hmac INTERFACE) + +# Add our source files to the lib +target_sources(usermod_tildagon_hmac INTERFACE + ${CMAKE_CURRENT_LIST_DIR}/tildagon_hmac.c +) + +# Add the current directory as an include directory. +target_include_directories(usermod_tildagon_hmac INTERFACE + ${CMAKE_CURRENT_LIST_DIR} +) + +# Link our INTERFACE library to the usermod target. +target_link_libraries(usermod INTERFACE usermod_tildagon_hmac) diff --git a/drivers/tildagon_hmac/tildagon_hmac.c b/drivers/tildagon_hmac/tildagon_hmac.c new file mode 100644 index 0000000..85956bf --- /dev/null +++ b/drivers/tildagon_hmac/tildagon_hmac.c @@ -0,0 +1,40 @@ +#include "tildagon_hmac.h" +#include "esp_hmac.h" + +#include "py/runtime.h" + +static mp_obj_t tildagon_hmac_digest(mp_obj_t key_slot, mp_obj_t msg) { + uint8_t hmac[32]; + hmac_key_id_t key_id = mp_obj_get_int(key_slot); + + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(msg, &bufinfo, MP_BUFFER_READ); + + esp_err_t err = esp_hmac_calculate(key_id, bufinfo.buf, bufinfo.len, hmac); + + if (err == ESP_FAIL) { + mp_raise_msg(&mp_type_Exception, "HMAC key not provisioned!"); + } + + return mp_obj_new_bytes(hmac, 32); +} + +static MP_DEFINE_CONST_FUN_OBJ_2(tildagon_hmac_digest_obj, tildagon_hmac_digest); + +static const mp_rom_map_elem_t tildagon_hmac_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_HMAC)}, + { MP_ROM_QSTR(MP_QSTR_digest), MP_ROM_PTR(&tildagon_hmac_digest_obj) }, + { MP_ROM_QSTR(MP_QSTR_HMAC_KEY0), MP_ROM_INT(HMAC_KEY0)}, + { MP_ROM_QSTR(MP_QSTR_HMAC_KEY1), MP_ROM_INT(HMAC_KEY1)}, + { MP_ROM_QSTR(MP_QSTR_HMAC_KEY2), MP_ROM_INT(HMAC_KEY2)}, + { MP_ROM_QSTR(MP_QSTR_HMAC_KEY3), MP_ROM_INT(HMAC_KEY3)}, + { MP_ROM_QSTR(MP_QSTR_HMAC_KEY4), MP_ROM_INT(HMAC_KEY4)}, + { MP_ROM_QSTR(MP_QSTR_HMAC_KEY5), MP_ROM_INT(HMAC_KEY5)}, +}; + +static MP_DEFINE_CONST_DICT(tildagon_hmac_globals, tildagon_hmac_globals_table); + +const mp_obj_module_t tildagon_hmac_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&tildagon_hmac_globals, +}; \ No newline at end of file diff --git a/drivers/tildagon_hmac/tildagon_hmac.h b/drivers/tildagon_hmac/tildagon_hmac.h new file mode 100644 index 0000000..7ded71a --- /dev/null +++ b/drivers/tildagon_hmac/tildagon_hmac.h @@ -0,0 +1,8 @@ +#ifndef _TILDAGON_HMAC_H_ +#define _TILDAGON_HMAC_H_ + +#include "py/runtime.h" + +extern const mp_obj_module_t tildagon_hmac_module; + +#endif // _TILDAGON_HMAC_H_ \ No newline at end of file From 1d6ef720e62ac49d7db632f0bd1c33a2f05cd967 Mon Sep 17 00:00:00 2001 From: Skyler Mansfield Date: Thu, 30 May 2024 16:43:05 +0100 Subject: [PATCH 2/8] HMAC: Add key burning script --- burn_mac.py | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 burn_mac.py diff --git a/burn_mac.py b/burn_mac.py new file mode 100644 index 0000000..f395c23 --- /dev/null +++ b/burn_mac.py @@ -0,0 +1,46 @@ +#!/usr/bin/python + +import hashlib +import esptool, espefuse +import os, hmac + + +def burn_hmac_key(key_to_use=1, port=None): + # This is the master secret and should be kept secret + # Initialise it from the environment variable + MASTER_SECRET = os.environ["MASTER_SECRET"] + + # Fix this in the code to the sha256sum of the master secret + MASTER_HASH='59a61bdad01d1074a37bc6ee2ae4bac0a424fc2fcfcbdfd0c386d1fdac0d5c7e' + + # PLEASE PLEASE PLEASE DO NOT REMOVE THIS CHECK + # IF YOU FLASH THE WRONG SECRET TO THE DEVICE IT CAN NEVER BE UNDONE + if hashlib.sha256(MASTER_SECRET.encode()).hexdigest() != MASTER_HASH: + print("Master secret does not match") + raise Exception("Master secret does not match") + + esp=esptool.get_default_connected_device(esptool.get_port_list(), port=port, connect_attempts=1, initial_baud=115200) + mac_address = esp.read_mac("BASE_MAC") + mac_str = '-'.join([f"{b:02X}" for b in mac_address]) + + print("MAC Address:", mac_str) + + COMBINED_SECRET = MASTER_SECRET + mac_str + + HMAC_KEY = hashlib.sha256(COMBINED_SECRET.encode()).digest() + + test_mac = hmac.digest(HMAC_KEY, b"test", "sha256") + print(test_mac.hex()) + + efuses, operations = espefuse.get_efuses(esp) + class Args: + name_value_pairs = {} + args = Args() + args.name_value_pairs[f"KEY_PURPOSE_{key_to_use}"] = 8 + args.name_value_pairs[f"BLOCK_KEY{key_to_use}"] = HMAC_KEY + print(operations.burn_efuse) + operations.burn_efuse(esp, efuses, args) + + +if __name__ == "__main__": + burn_hmac_key() From b41bd922232457d839c46149a93e3dd0faa8083b Mon Sep 17 00:00:00 2001 From: Skyler Mansfield Date: Thu, 30 May 2024 16:57:19 +0100 Subject: [PATCH 3/8] HMAC: Add sim fake --- sim/fakes/tildagon/HMAC.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 sim/fakes/tildagon/HMAC.py diff --git a/sim/fakes/tildagon/HMAC.py b/sim/fakes/tildagon/HMAC.py new file mode 100644 index 0000000..f473cdb --- /dev/null +++ b/sim/fakes/tildagon/HMAC.py @@ -0,0 +1,15 @@ +import hmac + +def digest(key_slot, msg): + key = bytes(32) + if key_slot == HMAC_KEY0: + key = b'\x96\xd6I\x0c\x8f\x81\x0f\xc1\x95a\xe2K\xef\xa5xT~\x8d\xcd\xa7~\xd9H\x0b\xdc\xf2\x9dD\xd3\xd3>Y' + return hmac.digest(key, msg, "sha256") + + +HMAC_KEY0 = 0 +HMAC_KEY1 = 1 +HMAC_KEY2 = 2 +HMAC_KEY3 = 3 +HMAC_KEY4 = 4 +HMAC_KEY5 = 5 \ No newline at end of file From d50e13242066d32671633f6b5ca90a62cd0aeaa0 Mon Sep 17 00:00:00 2001 From: Skyler Mansfield Date: Thu, 30 May 2024 17:53:40 +0100 Subject: [PATCH 4/8] HMAC: provisioning script now supports burning in a loop. --- burn_mac.py | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/burn_mac.py b/burn_mac.py index f395c23..8d67374 100644 --- a/burn_mac.py +++ b/burn_mac.py @@ -2,10 +2,10 @@ import hashlib import esptool, espefuse -import os, hmac +import os, hmac, time -def burn_hmac_key(key_to_use=1, port=None): +def burn_hmac_key(key_to_use=1, port=None, do_not_confirm=False): # This is the master secret and should be kept secret # Initialise it from the environment variable MASTER_SECRET = os.environ["MASTER_SECRET"] @@ -32,15 +32,30 @@ def burn_hmac_key(key_to_use=1, port=None): test_mac = hmac.digest(HMAC_KEY, b"test", "sha256") print(test_mac.hex()) - efuses, operations = espefuse.get_efuses(esp) + efuses, operations = espefuse.get_efuses(esp, do_not_confirm=do_not_confirm) class Args: name_value_pairs = {} args = Args() args.name_value_pairs[f"KEY_PURPOSE_{key_to_use}"] = 8 args.name_value_pairs[f"BLOCK_KEY{key_to_use}"] = HMAC_KEY print(operations.burn_efuse) - operations.burn_efuse(esp, efuses, args) + # operations.burn_efuse(esp, efuses, args) if __name__ == "__main__": - burn_hmac_key() + _in = input("Burn in a loop? (y/N): ") + if _in.lower() == "y": + loop = True + print("Burning fuses on loop. Press Ctrl+C to stop") + else: + print("Burning single fuse, waiting for device.") + while(True): + ports = esptool.get_port_list() + if not ports: + time.sleep(1) + continue + burn_hmac_key(do_not_confirm=loop) + while esptool.get_port_list(): + time.sleep(1) + if not loop: + break From 7b73933419b4d72f99413c47e9c3d934326cba5f Mon Sep 17 00:00:00 2001 From: Skyler Mansfield Date: Thu, 30 May 2024 20:00:39 +0100 Subject: [PATCH 5/8] HMAC: oops i left a line commented --- burn_mac.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/burn_mac.py b/burn_mac.py index 8d67374..9dafd81 100644 --- a/burn_mac.py +++ b/burn_mac.py @@ -39,7 +39,7 @@ class Args: args.name_value_pairs[f"KEY_PURPOSE_{key_to_use}"] = 8 args.name_value_pairs[f"BLOCK_KEY{key_to_use}"] = HMAC_KEY print(operations.burn_efuse) - # operations.burn_efuse(esp, efuses, args) + operations.burn_efuse(esp, efuses, args) if __name__ == "__main__": From 2a0151c11c7c8f9029ef451a93641c1e82bb8fe3 Mon Sep 17 00:00:00 2001 From: Skyler Mansfield Date: Thu, 30 May 2024 21:39:51 +0100 Subject: [PATCH 6/8] HMAC: rd/wr protect keys --- burn_mac.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/burn_mac.py b/burn_mac.py index 9dafd81..27c7855 100644 --- a/burn_mac.py +++ b/burn_mac.py @@ -38,12 +38,15 @@ class Args: args = Args() args.name_value_pairs[f"KEY_PURPOSE_{key_to_use}"] = 8 args.name_value_pairs[f"BLOCK_KEY{key_to_use}"] = HMAC_KEY + args.name_value_pairs[f"RD_DIS"] = (1<<(6-key_to_use)) + args.name_value_pairs[f"WR_DIS"] = (1<<(6-key_to_use)) print(operations.burn_efuse) operations.burn_efuse(esp, efuses, args) if __name__ == "__main__": _in = input("Burn in a loop? (y/N): ") + loop=False if _in.lower() == "y": loop = True print("Burning fuses on loop. Press Ctrl+C to stop") From de23a578dd20c4a253a209f62c6bed7f0ce5a2b1 Mon Sep 17 00:00:00 2001 From: Skyler Mansfield Date: Thu, 30 May 2024 21:43:32 +0100 Subject: [PATCH 7/8] HMAC: fix wr/rd protect offsets --- burn_mac.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/burn_mac.py b/burn_mac.py index 27c7855..57166f8 100644 --- a/burn_mac.py +++ b/burn_mac.py @@ -38,8 +38,8 @@ class Args: args = Args() args.name_value_pairs[f"KEY_PURPOSE_{key_to_use}"] = 8 args.name_value_pairs[f"BLOCK_KEY{key_to_use}"] = HMAC_KEY - args.name_value_pairs[f"RD_DIS"] = (1<<(6-key_to_use)) - args.name_value_pairs[f"WR_DIS"] = (1<<(6-key_to_use)) + args.name_value_pairs[f"RD_DIS"] = (1<<(key_to_use)) + args.name_value_pairs[f"WR_DIS"] = (1<<(23+key_to_use)) print(operations.burn_efuse) operations.burn_efuse(esp, efuses, args) From 08e6e2fefada16179cb1cba6f19b9dd44ee92e0f Mon Sep 17 00:00:00 2001 From: Skyler Mansfield Date: Thu, 30 May 2024 21:48:42 +0100 Subject: [PATCH 8/8] HMAC: don't write protect, i don't want to break more stuff --- burn_mac.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/burn_mac.py b/burn_mac.py index 57166f8..70c8e4c 100644 --- a/burn_mac.py +++ b/burn_mac.py @@ -39,7 +39,7 @@ class Args: args.name_value_pairs[f"KEY_PURPOSE_{key_to_use}"] = 8 args.name_value_pairs[f"BLOCK_KEY{key_to_use}"] = HMAC_KEY args.name_value_pairs[f"RD_DIS"] = (1<<(key_to_use)) - args.name_value_pairs[f"WR_DIS"] = (1<<(23+key_to_use)) + # args.name_value_pairs[f"WR_DIS"] = (1<<(23+key_to_use)) print(operations.burn_efuse) operations.burn_efuse(esp, efuses, args)