diff --git a/burn_mac.py b/burn_mac.py new file mode 100644 index 0000000..70c8e4c --- /dev/null +++ b/burn_mac.py @@ -0,0 +1,64 @@ +#!/usr/bin/python + +import hashlib +import esptool, espefuse +import os, hmac, time + + +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"] + + # 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, 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 + 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) + + +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") + 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 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 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