From 43b26806af1d0af50bdd4af16a10ae635a3bf3a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?King=20K=C3=A9vin?= Date: Mon, 15 Apr 2024 07:55:33 +0200 Subject: [PATCH] put manufacturer key to other page --- examples/device/hid_cdc_passkey/src/main.c | 97 +++++++++++++++++----- 1 file changed, 75 insertions(+), 22 deletions(-) diff --git a/examples/device/hid_cdc_passkey/src/main.c b/examples/device/hid_cdc_passkey/src/main.c index dd53552a3..3f5da50d1 100644 --- a/examples/device/hid_cdc_passkey/src/main.c +++ b/examples/device/hid_cdc_passkey/src/main.c @@ -50,12 +50,13 @@ #define BUTTON_DEBOUNCE (50U) // debounce time in ms -#define TIMEOUT_GLOBAL (24U * 60) // maximum time to hold the credentials, in minutes -#define TIMEOUT_REPEAT (6U * 60) // maximum time after last repeat to hold the credentials, in minutes +#define TIMEOUT_GLOBAL (12U * 60) // maximum time to hold the credentials, in minutes +#define TIMEOUT_REPEAT (3U * 60) // maximum time after last repeat to hold the credentials, in minutes + +char manuf_key[32 + 1]; // the key set by the manufacturer to authenticate the device static struct config_t { uint8_t layout; // keyboard layout - char manuf_key[32 + 1]; // the key set by the manufacturer to authenticate the device char user_key[32 + 1]; // the key set by the user to authenticate the device bool button_swap; // the order of the buttons (which is for username or password) uint16_t timeout_global; // time to hold the credentials, in minutes @@ -63,8 +64,8 @@ static struct config_t { uint8_t crc; // simple XOR CRC to check config validity } config; -// TODO move manuf key to seperate page, in write protected space - +// page to store manufacturer key (can't be corrupter by save config) +#define FLASH_MANUF_ADDR ((uint32_t)0x08000000 + 0x400 * 26) // last available page of last sector to store config #define FLASH_CONFIG_ADDR ((uint32_t)0x08000000 + 0x400 * 27) @@ -138,6 +139,18 @@ uint32_t board_button2_read(void) static void load_config(void) { + memcpy(manuf_key, (uint8_t*)FLASH_MANUF_ADDR, sizeof(manuf_key)); + bool manuf_ok = false; + for (uint8_t i = 0; i < sizeof(manuf_key); i++) { + if (0 == manuf_key[i]) { + manuf_ok = true; + break; + } + } + if (!manuf_ok) { + memset(manuf_key, 0, sizeof(manuf_key)); + } + memcpy(&config, (uint8_t*)FLASH_CONFIG_ADDR, sizeof(config)); uint8_t crc = 0x42; // start with non-zero value to have a checksum work with empty config for (uint16_t i = 0; i < sizeof(config); i++) { @@ -195,6 +208,33 @@ end: HAL_FLASH_Lock(); } +static void save_manuf(void) +{ + // save to flash + HAL_FLASH_Unlock(); + FLASH_EraseInitTypeDef EraseInitStruct; + EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES; + EraseInitStruct.PageAddress = FLASH_MANUF_ADDR; + EraseInitStruct.NbPages = 1; + uint32_t error; + if (HAL_FLASHEx_Erase(&EraseInitStruct, &error) != HAL_OK) { + printf("earsing page failed\r\n"); + goto end; + } + for (uint16_t i = 0; i < sizeof(manuf_key); i += 4) { + const uint32_t address = FLASH_CONFIG_ADDR + i; + uint32_t data; + memcpy(&data, (uint8_t*)&manuf_key[i], sizeof(data)); // works even if the data it not aligned + if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, address, data) != HAL_OK) { + printf("flash page failed\r\n"); + goto end; + } + } + printf("manufacturer key saved\r\n"); +end: + HAL_FLASH_Lock(); +} + // convert bytes to ASCII hex (does not add end zero) static void b2h(const uint8_t* b, char* h, uint8_t len) { @@ -238,13 +278,20 @@ int main(void) tud_init(BOARD_TUD_RHPORT); printf("\r\npasskey v2\r\n"); + load_config(); + + FLASH_OBProgramInitTypeDef ob; + HAL_FLASHEx_OBGetConfig(&ob); + if (OB_RDP_LEVEL_2 != ob.RDPLevel) { + printf("device not locked\r\n"); + } + if (0 == strlen(manuf_key)) { + printf("manufacturer key not set\r\n"); + } if (board_init_after_tusb) { board_init_after_tusb(); } - - load_config(); - while (true) { tud_task(); // tinyusb device task @@ -367,7 +414,7 @@ void cdc_task(void) str = "\r\nenter authentication key (up to 32 char): "; break; case 'a': // run authentication - if (0 == strlen(config.user_key) && 0 == strlen(config.manuf_key)) { + if (0 == strlen(config.user_key) && 0 == strlen(manuf_key)) { str = "\r\nno key set\r\n"; } else { i = 0; // reset index @@ -390,9 +437,17 @@ void cdc_task(void) break; // hidden menu case 'K': // set manufacturer key - i = 0; // reset index - menu = MENU_MANUF; - str = "\r\nenter manufacturer key (up to 32 char): "; + { + FLASH_OBProgramInitTypeDef ob; + HAL_FLASHEx_OBGetConfig(&ob); + if (OB_RDP_LEVEL_2 == ob.RDPLevel) { + str = "\r\ndevice locked\r\n"; + } else { + i = 0; // reset index + menu = MENU_MANUF; + str = "\r\nenter manufacturer key (up to 32 char): "; + } + } break; case 'L': // lock device { @@ -400,8 +455,6 @@ void cdc_task(void) HAL_FLASHEx_OBGetConfig(&ob); if (OB_RDP_LEVEL_2 == ob.RDPLevel) { str = "\r\ndevice locked\r\n"; - } else if (0 == strlen(config.manuf_key)) { - str = "\r\nset manufacturer key first\r\n"; } else { str = "\r\nlocking device\r\n"; ob.RDPLevel = OB_RDP_LEVEL_2; // level 2, disabling debug, and write protecting option byte @@ -475,9 +528,9 @@ void cdc_task(void) if ('\r' == buf[j] || '\n' == buf[j]) { // end received tmp[i] = 0; // end key if (strlen(tmp)) { - memset(config.manuf_key, 0, sizeof(config.manuf_key)); - memcpy(config.manuf_key, tmp, i); - save_config(); + memset(manuf_key, 0, sizeof(manuf_key)); + memcpy(manuf_key, tmp, i); + save_manuf(); str = "\r\nmanufacturer key saved\r\n"; } else { str = "\r\ninvalid input\r\n"; @@ -522,7 +575,7 @@ void cdc_task(void) tmp[i] = 0; // end string if (strlen(tmp)) { echo = false; // we need to write now - if (strlen(config.manuf_key)) { + if (strlen(manuf_key)) { char uid[4 * 3 * 2 + 1]; b2h((uint8_t*)UID_BASE, uid, 4 * 3); uid[sizeof(uid) - 1] = 0; // end string @@ -530,11 +583,11 @@ void cdc_task(void) tud_cdc_write_str_flush(uid); tud_cdc_write_str_flush(tmp); tud_cdc_write_str_flush("\r\n"); - uint8_t hash_in[sizeof(config.manuf_key) + sizeof(tmp)]; - memcpy(&hash_in[0], config.manuf_key, strlen(config.manuf_key)); - memcpy(&hash_in[strlen(config.user_key)], tmp, strlen(tmp)); + uint8_t hash_in[sizeof(manuf_key) + sizeof(tmp)]; + memcpy(&hash_in[0], manuf_key, strlen(manuf_key)); + memcpy(&hash_in[strlen(manuf_key)], tmp, strlen(tmp)); SHA256_HASH hash_out; - Sha256Calculate(hash_in, strlen(config.manuf_key) + strlen(tmp), &hash_out); + Sha256Calculate(hash_in, strlen(manuf_key) + strlen(tmp), &hash_out); char hash_str[SHA256_HASH_SIZE * 2 + 1]; b2h(hash_out.bytes, hash_str, SHA256_HASH_SIZE); hash_str[SHA256_HASH_SIZE * 2] = 0; // end string