From bfab1e974d733734d71f7351122faa0f01e43d29 Mon Sep 17 00:00:00 2001 From: Mark Qvist Date: Tue, 1 Nov 2022 21:11:41 +0100 Subject: [PATCH] Implemented ESP32 device init and firmware hash checks --- Bluetooth.h | 62 ++++++++++++++------- Config.h | 7 ++- Device.h | 136 +++++++++++++++++++++++++++++++++++++++++++++ Framing.h | 4 ++ RNode_Firmware.ino | 104 +++++++++++++++++++++++++++++----- Utilities.h | 96 +++++++++++++++++++------------- 6 files changed, 331 insertions(+), 78 deletions(-) create mode 100644 Device.h diff --git a/Bluetooth.h b/Bluetooth.h index 2e9f2a9..01c3576 100644 --- a/Bluetooth.h +++ b/Bluetooth.h @@ -8,6 +8,7 @@ uint32_t bt_pairing_started = 0; #define BT_DEV_ADDR_LEN 6 #define BT_DEV_HASH_LEN 16 +uint8_t dev_bt_mac[BT_DEV_ADDR_LEN]; char bt_da[BT_DEV_ADDR_LEN]; char bt_dh[BT_DEV_HASH_LEN]; char bt_devname[11]; @@ -70,33 +71,52 @@ char bt_devname[11]; } } - bool bt_setup_hw() { - if (!bt_ready) { - if (EEPROM.read(eeprom_addr(ADDR_CONF_BT)) == BT_ENABLE_BYTE) { bt_enabled = true; } else { bt_enabled = false; } + bool bt_early_init_done = false; + bool bt_early_init() { + if (!bt_early_init_done) { if (btStart()) { if (esp_bluedroid_init() == ESP_OK) { if (esp_bluedroid_enable() == ESP_OK) { const uint8_t* bda_ptr = esp_bt_dev_get_address(); - char *data = (char*)malloc(BT_DEV_ADDR_LEN+1); - for (int i = 0; i < BT_DEV_ADDR_LEN; i++) { - data[i] = bda_ptr[i]; - } - data[BT_DEV_ADDR_LEN] = EEPROM.read(eeprom_addr(ADDR_SIGNATURE)); - unsigned char *hash = MD5::make_hash(data, BT_DEV_ADDR_LEN); - memcpy(bt_dh, hash, BT_DEV_HASH_LEN); - sprintf(bt_devname, "RNode %02X%02X", bt_dh[14], bt_dh[15]); - free(data); - - SerialBT.enableSSP(); - SerialBT.onConfirmRequest(bt_confirm_pairing); - SerialBT.onAuthComplete(bt_pairing_complete); - SerialBT.register_callback(bt_connection_callback); - - bt_ready = true; + memcpy(dev_bt_mac, bda_ptr, BT_DEV_HASH_LEN); return true; + } else { + return false; + } + } else { + return false; + } + } else { + return false; + } + } else { + return true; + } + } + + bool bt_setup_hw() { + if (!bt_ready) { + if (EEPROM.read(eeprom_addr(ADDR_CONF_BT)) == BT_ENABLE_BYTE) { bt_enabled = true; } else { bt_enabled = false; } + if (bt_early_init()) { + const uint8_t* bda_ptr = esp_bt_dev_get_address(); + char *data = (char*)malloc(BT_DEV_ADDR_LEN+1); + for (int i = 0; i < BT_DEV_ADDR_LEN; i++) { + data[i] = bda_ptr[i]; + } + data[BT_DEV_ADDR_LEN] = EEPROM.read(eeprom_addr(ADDR_SIGNATURE)); + unsigned char *hash = MD5::make_hash(data, BT_DEV_ADDR_LEN); + memcpy(bt_dh, hash, BT_DEV_HASH_LEN); + sprintf(bt_devname, "RNode %02X%02X", bt_dh[14], bt_dh[15]); + free(data); + + SerialBT.enableSSP(); + SerialBT.onConfirmRequest(bt_confirm_pairing); + SerialBT.onAuthComplete(bt_pairing_complete); + SerialBT.register_callback(bt_connection_callback); + + bt_ready = true; + return true; - } else { return false; } - } else { return false; } } else { return false; } } } diff --git a/Config.h b/Config.h index 5939d2c..a9e8b02 100644 --- a/Config.h +++ b/Config.h @@ -60,7 +60,7 @@ #define HEADER_L 1 #define MIN_L 1 - #define CMD_L 10 + #define CMD_L 64 // MCU dependent configuration parameters @@ -267,7 +267,7 @@ uint8_t pbuf[MTU]; // KISS command buffer - uint8_t cbuf[CMD_L]; + uint8_t cmdbuf[CMD_L]; // LoRa transmit buffer uint8_t tbuf[MTU]; @@ -300,8 +300,9 @@ bool external_power = false; float battery_voltage = 0.0; float battery_percent = 0.0; - // float auxillary_temperature = 0.0; uint8_t battery_state = 0x00; + uint8_t display_intensity = 0xFF; + bool device_init_done = false; // Boot flags #define START_FROM_BOOTLOADER 0x01 diff --git a/Device.h b/Device.h new file mode 100644 index 0000000..612e964 --- /dev/null +++ b/Device.h @@ -0,0 +1,136 @@ +#include +#include "mbedtls/md.h" +#include "esp_ota_ops.h" +#include "esp_flash_partitions.h" +#include "esp_partition.h" + +// Forward declaration from Utilities.h +void eeprom_update(int mapped_addr, uint8_t byte); +void hard_reset(void); + +const uint8_t dev_keys [] PROGMEM = { + 0x0f, 0x15, 0x86, 0x74, 0xa0, 0x7d, 0xf2, 0xde, 0x32, 0x11, 0x29, 0xc1, 0x0d, 0xda, 0xcc, 0xc3, + 0xe1, 0x9b, 0xac, 0xf2, 0x27, 0x06, 0xee, 0x89, 0x1f, 0x7a, 0xfc, 0xc3, 0x6a, 0xf5, 0x38, 0x08 +}; + +#define DEV_SIG_LEN 64 +uint8_t dev_sig[DEV_SIG_LEN]; + +#define DEV_KEY_LEN 32 +uint8_t dev_k_prv[DEV_KEY_LEN]; +uint8_t dev_k_pub[DEV_KEY_LEN]; + +#define DEV_HASH_LEN 32 +uint8_t dev_hash[DEV_HASH_LEN]; +uint8_t dev_partition_table_hash[DEV_HASH_LEN]; +uint8_t dev_bootloader_hash[DEV_HASH_LEN]; +uint8_t dev_firmware_hash[DEV_HASH_LEN]; +uint8_t dev_firmware_hash_target[DEV_HASH_LEN]; + +#define EEPROM_SIG_LEN 128 +uint8_t dev_eeprom_signature[EEPROM_SIG_LEN]; + +bool dev_signature_validated = false; +bool fw_signature_validated = true; + +#define DEV_SIG_OFFSET EEPROM_SIZE-EEPROM_RESERVED-DEV_SIG_LEN +#define dev_sig_addr(a) (a+DEV_SIG_OFFSET) + +#define DEV_FWHASH_OFFSET EEPROM_SIZE-EEPROM_RESERVED-DEV_SIG_LEN-DEV_HASH_LEN +#define dev_fwhash_addr(a) (a+DEV_FWHASH_OFFSET) + +bool device_signatures_ok() { + return dev_signature_validated && fw_signature_validated; +} + +void device_validate_signature() { + int n_keys = sizeof(dev_keys)/DEV_KEY_LEN; + bool valid_signature_found = false; + for (int i = 0; i < n_keys; i++) { + memcpy(dev_k_pub, dev_keys+DEV_KEY_LEN*i, DEV_KEY_LEN); + if (Ed25519::verify(dev_sig, dev_k_pub, dev_hash, DEV_HASH_LEN)) { + valid_signature_found = true; + } + } + + if (valid_signature_found) { + dev_signature_validated = true; + } else { + dev_signature_validated = false; + } +} + +void device_save_signature() { + device_validate_signature(); + if (dev_signature_validated) { + for (uint8_t i = 0; i < DEV_SIG_LEN; i++) { + eeprom_update(dev_sig_addr(i), dev_sig[i]); + } + } +} + +void device_load_signature() { + for (uint8_t i = 0; i < DEV_SIG_LEN; i++) { + dev_sig[i] = EEPROM.read(dev_sig_addr(i)); + } +} + +void device_load_firmware_hash() { + Serial.println("Loading hash from EEPROM"); + for (uint8_t i = 0; i < DEV_HASH_LEN; i++) { + dev_firmware_hash_target[i] = EEPROM.read(dev_fwhash_addr(i)); + } +} + +void device_save_firmware_hash() { + for (uint8_t i = 0; i < DEV_HASH_LEN; i++) { + eeprom_update(dev_fwhash_addr(i), dev_firmware_hash_target[i]); + } + if (!fw_signature_validated) hard_reset(); +} + +void device_validate_partitions() { + device_load_firmware_hash(); + esp_partition_t partition; + partition.address = ESP_PARTITION_TABLE_OFFSET; + partition.size = ESP_PARTITION_TABLE_MAX_LEN; + partition.type = ESP_PARTITION_TYPE_DATA; + esp_partition_get_sha256(&partition, dev_partition_table_hash); + partition.address = ESP_BOOTLOADER_OFFSET; + partition.size = ESP_PARTITION_TABLE_OFFSET; + partition.type = ESP_PARTITION_TYPE_APP; + esp_partition_get_sha256(&partition, dev_bootloader_hash); + esp_partition_get_sha256(esp_ota_get_running_partition(), dev_firmware_hash); + for (uint8_t i = 0; i < DEV_HASH_LEN; i++) { + if (dev_firmware_hash_target[i] != dev_firmware_hash[i]) { + fw_signature_validated = false; + break; + } + } +} + +bool device_firmware_ok() { + return fw_signature_validated; +} + +bool device_init() { + if (bt_early_init()) { + for (uint8_t i=0; i 63) line = 63; int fb_o = line*8; - memcpy(fb+fb_o, cbuf+1, 8); + memcpy(fb+fb_o, cmdbuf+1, 8); } #endif } else if (command == CMD_FB_READ) { if (sbyte != 0x00) { kiss_indicate_fb(); } + } else if (command == CMD_DEV_HASH) { + #if MCU_VARIANT == MCU_ESP32 + if (sbyte != 0x00) { + kiss_indicate_device_hash(); + } + #endif + } else if (command == CMD_DEV_SIG) { + #if MCU_VARIANT == MCU_ESP32 + if (sbyte == FESC) { + ESCAPE = true; + } else { + if (ESCAPE) { + if (sbyte == TFEND) sbyte = FEND; + if (sbyte == TFESC) sbyte = FESC; + ESCAPE = false; + } + if (frame_len < CMD_L) cmdbuf[frame_len++] = sbyte; + } + + if (frame_len == DEV_SIG_LEN) { + memcpy(dev_sig, cmdbuf, DEV_SIG_LEN); + device_save_signature(); + } + #endif + } else if (command == CMD_FW_HASH) { + #if MCU_VARIANT == MCU_ESP32 + if (sbyte == FESC) { + ESCAPE = true; + } else { + if (ESCAPE) { + if (sbyte == TFEND) sbyte = FEND; + if (sbyte == TFESC) sbyte = FESC; + ESCAPE = false; + } + if (frame_len < CMD_L) cmdbuf[frame_len++] = sbyte; + } + + if (frame_len == DEV_HASH_LEN) { + memcpy(dev_firmware_hash_target, cmdbuf, DEV_SIG_LEN); + device_save_firmware_hash(); + } + #endif } else if (command == CMD_BT_CTRL) { #if HAS_BLUETOOTH if (sbyte == 0x00) { @@ -684,6 +727,20 @@ void serialCallback(uint8_t sbyte) { bt_enable_pairing(); } #endif + } else if (command == CMD_DISP_INT) { + #if HAS_DISPLAY + if (sbyte == FESC) { + ESCAPE = true; + } else { + if (ESCAPE) { + if (sbyte == TFEND) sbyte = FEND; + if (sbyte == TFESC) sbyte = FESC; + ESCAPE = false; + } + display_intensity = sbyte; + } + + #endif } } } @@ -739,7 +796,7 @@ void checkModemStatus() { } } -void validateStatus() { +void validate_status() { #if MCU_VARIANT == MCU_1284P uint8_t boot_flags = OPTIBOOT_MCUSR; uint8_t F_POR = PORF; @@ -759,6 +816,15 @@ void validateStatus() { uint8_t F_WDR = 0x01; #endif + if (hw_ready || device_init_done) { + hw_ready = false; + Serial.write("Error, invalid hardware check state\r\n"); + #if HAS_DISPLAY + if (disp_ready) update_display(); + #endif + led_indicate_boot_error(); + } + if (boot_flags & (1< led_notready_wait) { - led_notready_ticks = 0; - if (led_notready_value <= led_notready_min) { - led_notready_direction = 1; - } else if (led_notready_value >= led_notready_max) { - led_notready_direction = -1; + led_standby_ticks++; + + if (led_standby_ticks > led_notready_wait) { + led_standby_ticks = 0; + + if (led_standby_value <= led_standby_min) { + led_standby_direction = 1; + } else if (led_standby_value >= led_standby_max) { + led_standby_direction = -1; } - led_notready_value += led_notready_direction; - if (led_notready_value > 252) { - npset(0xFF, 0x00, 0x00); + + led_standby_value += led_standby_direction; + int offset = led_standby_value - led_standby_lng; + uint8_t led_standby_intensity; + if (offset < 0) { + led_standby_intensity = 0; } else { - npset(0x00, 0x00, 0x00); + led_standby_intensity = offset; } + if (offset > led_standby_cut) offset = led_standby_cut; + npset(led_standby_intensity, 0x00, 0x00); } } #else @@ -478,7 +486,7 @@ void serial_write(uint8_t byte) { #endif } -void escapedSerialWrite(uint8_t byte) { +void escaped_serial_write(uint8_t byte) { if (byte == FEND) { serial_write(FESC); byte = TFEND; } if (byte == FESC) { serial_write(FESC); byte = TFESC; } serial_write(byte); @@ -508,20 +516,20 @@ void kiss_indicate_radiostate() { void kiss_indicate_stat_rx() { serial_write(FEND); serial_write(CMD_STAT_RX); - escapedSerialWrite(stat_rx>>24); - escapedSerialWrite(stat_rx>>16); - escapedSerialWrite(stat_rx>>8); - escapedSerialWrite(stat_rx); + escaped_serial_write(stat_rx>>24); + escaped_serial_write(stat_rx>>16); + escaped_serial_write(stat_rx>>8); + escaped_serial_write(stat_rx); serial_write(FEND); } void kiss_indicate_stat_tx() { serial_write(FEND); serial_write(CMD_STAT_TX); - escapedSerialWrite(stat_tx>>24); - escapedSerialWrite(stat_tx>>16); - escapedSerialWrite(stat_tx>>8); - escapedSerialWrite(stat_tx); + escaped_serial_write(stat_tx>>24); + escaped_serial_write(stat_tx>>16); + escaped_serial_write(stat_tx>>8); + escaped_serial_write(stat_tx); serial_write(FEND); } @@ -529,14 +537,14 @@ void kiss_indicate_stat_rssi() { uint8_t packet_rssi_val = (uint8_t)(last_rssi+rssi_offset); serial_write(FEND); serial_write(CMD_STAT_RSSI); - escapedSerialWrite(packet_rssi_val); + escaped_serial_write(packet_rssi_val); serial_write(FEND); } void kiss_indicate_stat_snr() { serial_write(FEND); serial_write(CMD_STAT_SNR); - escapedSerialWrite(last_snr_raw); + escaped_serial_write(last_snr_raw); serial_write(FEND); } @@ -578,20 +586,20 @@ void kiss_indicate_txpower() { void kiss_indicate_bandwidth() { serial_write(FEND); serial_write(CMD_BANDWIDTH); - escapedSerialWrite(lora_bw>>24); - escapedSerialWrite(lora_bw>>16); - escapedSerialWrite(lora_bw>>8); - escapedSerialWrite(lora_bw); + escaped_serial_write(lora_bw>>24); + escaped_serial_write(lora_bw>>16); + escaped_serial_write(lora_bw>>8); + escaped_serial_write(lora_bw); serial_write(FEND); } void kiss_indicate_frequency() { serial_write(FEND); serial_write(CMD_FREQUENCY); - escapedSerialWrite(lora_freq>>24); - escapedSerialWrite(lora_freq>>16); - escapedSerialWrite(lora_freq>>8); - escapedSerialWrite(lora_freq); + escaped_serial_write(lora_freq>>24); + escaped_serial_write(lora_freq>>16); + escaped_serial_write(lora_freq>>8); + escaped_serial_write(lora_freq); serial_write(FEND); } @@ -617,15 +625,25 @@ void kiss_indicate_fbstate() { serial_write(FEND); } +#if MCU_VARIANT == MCU_ESP32 + void kiss_indicate_device_hash() { + serial_write(FEND); + serial_write(CMD_DEV_HASH); + for (int i = 0; i < DEV_HASH_LEN; i++) { + uint8_t byte = dev_hash[i]; + escaped_serial_write(byte); + } + serial_write(FEND); + } +#endif + void kiss_indicate_fb() { serial_write(FEND); serial_write(CMD_FB_READ); #if HAS_DISPLAY for (int i = 0; i < 512; i++) { uint8_t byte = fb[i]; - if (byte == FEND) { serial_write(FESC); byte = TFEND; } - if (byte == FESC) { serial_write(FESC); byte = TFESC; } - serial_write(byte); + escaped_serial_write(byte); } #else serial_write(0xFF); @@ -799,21 +817,21 @@ bool eeprom_info_locked() { void eeprom_dump_info() { for (int addr = ADDR_PRODUCT; addr <= ADDR_INFO_LOCK; addr++) { uint8_t byte = EEPROM.read(eeprom_addr(addr)); - escapedSerialWrite(byte); + escaped_serial_write(byte); } } void eeprom_dump_config() { for (int addr = ADDR_CONF_SF; addr <= ADDR_CONF_OK; addr++) { uint8_t byte = EEPROM.read(eeprom_addr(addr)); - escapedSerialWrite(byte); + escaped_serial_write(byte); } } void eeprom_dump_all() { for (int addr = 0; addr < EEPROM_RESERVED; addr++) { uint8_t byte = EEPROM.read(eeprom_addr(addr)); - escapedSerialWrite(byte); + escaped_serial_write(byte); } }