#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];
}
}
- 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; }
}
}
#define HEADER_L 1
#define MIN_L 1
- #define CMD_L 10
+ #define CMD_L 64
// MCU dependent configuration parameters
uint8_t pbuf[MTU];
// KISS command buffer
- uint8_t cbuf[CMD_L];
+ uint8_t cmdbuf[CMD_L];
// LoRa transmit buffer
uint8_t tbuf[MTU];
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
--- /dev/null
+#include <Ed25519.h>
+#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<EEPROM_SIG_LEN; i++){dev_eeprom_signature[i]=EEPROM.read(eeprom_addr(ADDR_SIGNATURE+i));}
+ mbedtls_md_context_t ctx;
+ mbedtls_md_type_t md_type = MBEDTLS_MD_SHA256;
+ mbedtls_md_init(&ctx);
+ mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(md_type), 0);
+ mbedtls_md_starts(&ctx);
+ mbedtls_md_update(&ctx, dev_bt_mac, BT_DEV_ADDR_LEN);
+ mbedtls_md_update(&ctx, dev_eeprom_signature, EEPROM_SIG_LEN);
+ mbedtls_md_finish(&ctx, dev_hash);
+ mbedtls_md_free(&ctx);
+ device_load_signature();
+ device_validate_signature();
+ device_validate_partitions();
+ device_init_done = true;
+ return device_init_done && fw_signature_validated;
+ } else {
+ return false;
+ }
+}
\ No newline at end of file
#define CMD_FB_READ 0x42
#define CMD_FB_WRITE 0x43
#define CMD_FB_READL 0x44
+ #define CMD_DISP_INT 0x45
#define CMD_BT_CTRL 0x46
#define CMD_BOARD 0x47
#define CMD_ROM_WRITE 0x52
#define CMD_CONF_SAVE 0x53
#define CMD_CONF_DELETE 0x54
+ #define CMD_DEV_HASH 0x56
+ #define CMD_DEV_SIG 0x57
+ #define CMD_FW_HASH 0x58
#define CMD_UNLOCK_ROM 0x59
#define ROM_UNLOCK_BYTE 0xF8
#define CMD_RESET 0x55
void setup() {
#if MCU_VARIANT == MCU_ESP32
- delay(500);
+ // TODO: Reset?
+ // delay(500);
EEPROM.begin(EEPROM_SIZE);
Serial.setRxBufferSize(CONFIG_UART_BUFFER_SIZE);
#endif
// Initialise buffers
memset(pbuf, 0, sizeof(pbuf));
- memset(cbuf, 0, sizeof(cbuf));
+ memset(cmdbuf, 0, sizeof(cmdbuf));
memset(packet_queue, 0, sizeof(packet_queue));
#endif
// Validate board health, EEPROM and config
- validateStatus();
+ validate_status();
}
void lora_receive() {
if (sbyte == TFESC) sbyte = FESC;
ESCAPE = false;
}
- cbuf[frame_len++] = sbyte;
+ if (frame_len < CMD_L) cmdbuf[frame_len++] = sbyte;
}
if (frame_len == 4) {
- uint32_t freq = (uint32_t)cbuf[0] << 24 | (uint32_t)cbuf[1] << 16 | (uint32_t)cbuf[2] << 8 | (uint32_t)cbuf[3];
+ uint32_t freq = (uint32_t)cmdbuf[0] << 24 | (uint32_t)cmdbuf[1] << 16 | (uint32_t)cmdbuf[2] << 8 | (uint32_t)cmdbuf[3];
if (freq == 0) {
kiss_indicate_frequency();
if (sbyte == TFESC) sbyte = FESC;
ESCAPE = false;
}
- cbuf[frame_len++] = sbyte;
+ if (frame_len < CMD_L) cmdbuf[frame_len++] = sbyte;
}
if (frame_len == 4) {
- uint32_t bw = (uint32_t)cbuf[0] << 24 | (uint32_t)cbuf[1] << 16 | (uint32_t)cbuf[2] << 8 | (uint32_t)cbuf[3];
+ uint32_t bw = (uint32_t)cmdbuf[0] << 24 | (uint32_t)cmdbuf[1] << 16 | (uint32_t)cmdbuf[2] << 8 | (uint32_t)cmdbuf[3];
if (bw == 0) {
kiss_indicate_bandwidth();
if (sbyte == TFESC) sbyte = FESC;
ESCAPE = false;
}
- cbuf[frame_len++] = sbyte;
+ if (frame_len < CMD_L) cmdbuf[frame_len++] = sbyte;
}
if (frame_len == 2) {
- eeprom_write(cbuf[0], cbuf[1]);
+ eeprom_write(cmdbuf[0], cmdbuf[1]);
}
} else if (command == CMD_FW_VERSION) {
kiss_indicate_version();
if (sbyte == TFESC) sbyte = FESC;
ESCAPE = false;
}
- cbuf[frame_len++] = sbyte;
+ if (frame_len < CMD_L) cmdbuf[frame_len++] = sbyte;
}
#if HAS_DISPLAY
if (frame_len == 9) {
- uint8_t line = cbuf[0];
+ uint8_t line = cmdbuf[0];
if (line > 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) {
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
}
}
}
}
}
-void validateStatus() {
+void validate_status() {
#if MCU_VARIANT == MCU_1284P
uint8_t boot_flags = OPTIBOOT_MCUSR;
uint8_t F_POR = PORF;
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<<F_POR)) {
boot_vector = START_FROM_POWERON;
} else if (boot_flags & (1<<F_BOR)) {
if (eeprom_lock_set()) {
if (eeprom_product_valid() && eeprom_model_valid() && eeprom_hwrev_valid()) {
if (eeprom_checksum_valid()) {
- hw_ready = true;
+ #if PLATFORM == PLATFORM_ESP32
+ if (device_init()) {
+ hw_ready = true;
+ } else {
+ hw_ready = false;
+ }
+ #else
+ hw_ready = true;
+ #endif
- if (eeprom_have_conf()) {
+ if (hw_ready && eeprom_have_conf()) {
eeprom_conf_load();
op_mode = MODE_TNC;
startRadio();
#endif
#if MCU_VARIANT == MCU_ESP32
+ #include "Device.h"
#include "soc/rtc_wdt.h"
#define ISR_VECT IRAM_ATTR
#else
#elif MCU_VARIANT == MCU_ESP32
- #if BOARD_MODEL == BOARD_RNODE_NG_20
+ #if BOARD_MODEL == BOARD_RNODE_NG_20 || BOARD_MODEL == BOARD_RNODE_NG_21
uint8_t led_standby_lng = 32;
uint8_t led_standby_cut = 16;
uint8_t led_standby_min = 0;
int8_t led_notready_direction = 0;
unsigned long led_notready_ticks = 0;
unsigned long led_standby_wait = 1000;
- unsigned long led_notready_wait = 20000;
+ unsigned long led_notready_wait = 200;
#else
uint8_t led_standby_min = 200;
}
}
#elif MCU_VARIANT == MCU_ESP32
- #if BOARD_MODEL == BOARD_RNODE_NG_20
+ #if BOARD_MODEL == BOARD_RNODE_NG_20 || BOARD_MODEL == BOARD_RNODE_NG_21
void led_indicate_not_ready() {
- led_notready_ticks++;
- if (led_notready_ticks > 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
#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);
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);
}
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);
}
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);
}
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);
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);
}
}