From e107a9aa860273d96591e9c940f8b6b08cf0b5e3 Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Mon, 3 Dec 2018 20:06:44 -0500 Subject: [PATCH] refactor --- fido2/device.h | 11 +- fido2/extensions/extensions.h | 2 + targets/stm32l442/bootloader.mk | 3 +- targets/stm32l442/bootloader/bootloader.c | 162 +++++++++++++++++++ targets/stm32l442/bootloader/bootloader.h | 14 +- targets/stm32l442/src/device.c | 180 +--------------------- targets/stm32l442/src/memory_layout.h | 33 ++++ 7 files changed, 213 insertions(+), 192 deletions(-) create mode 100644 targets/stm32l442/bootloader/bootloader.c create mode 100644 targets/stm32l442/src/memory_layout.h diff --git a/fido2/device.h b/fido2/device.h index 536ab85..8d78df9 100644 --- a/fido2/device.h +++ b/fido2/device.h @@ -44,7 +44,7 @@ void usbhid_close(); void main_loop_delay(); void heartbeat(); -void bootloader_heartbeat(); + void authenticator_read_state(AuthenticatorState * ); @@ -94,13 +94,10 @@ void ctap_store_rk(int index,CTAP_residentKey * rk); void ctap_load_rk(int index,CTAP_residentKey * rk); void ctap_overwrite_rk(int index,CTAP_residentKey * rk); -// Boot laoder application -int bootloader_bridge(uint8_t klen, uint8_t * keyh); -// Trigger software reset -void device_reboot(); -// for bootloader -int is_authorized_to_boot(); + + + #endif diff --git a/fido2/extensions/extensions.h b/fido2/extensions/extensions.h index aed2c3f..9ee4cc3 100644 --- a/fido2/extensions/extensions.h +++ b/fido2/extensions/extensions.h @@ -25,4 +25,6 @@ int16_t extend_u2f(struct u2f_request_apdu* req, uint32_t len); +int bootloader_bridge(uint8_t klen, uint8_t * keyh); + #endif /* EXTENSIONS_H_ */ diff --git a/targets/stm32l442/bootloader.mk b/targets/stm32l442/bootloader.mk index 9aad2b1..3611940 100644 --- a/targets/stm32l442/bootloader.mk +++ b/targets/stm32l442/bootloader.mk @@ -4,7 +4,8 @@ SZ=arm-none-eabi-size AR=arm-none-eabi-ar # ST related -SRC = bootloader/main.c src/init.c src/redirect.c src/flash.c src/rng.c src/led.c src/device.c +SRC = bootloader/main.c bootloader/bootloader.c +SRC += src/init.c src/redirect.c src/flash.c src/rng.c src/led.c src/device.c SRC += src/fifo.c src/crypto.c src/attestation.c SRC += src/startup_stm32l432xx.s src/system_stm32l4xx.c SRC += $(wildcard lib/*.c) $(wildcard lib/usbd/*.c) diff --git a/targets/stm32l442/bootloader/bootloader.c b/targets/stm32l442/bootloader/bootloader.c new file mode 100644 index 0000000..10ec7c1 --- /dev/null +++ b/targets/stm32l442/bootloader/bootloader.c @@ -0,0 +1,162 @@ +#include +#include + +#include APP_CONFIG +#include "uECC.h" +#include "u2f.h" +#include "device.h" +#include "flash.h" +#include "crypto.h" +#include "led.h" +#include "memory_layout.h" +#include "ctap_errors.h" +#include "log.h" + +extern uint8_t REBOOT_FLAG; + +typedef enum +{ + BootWrite = 0x40, + BootDone = 0x41, + BootCheck = 0x42, + BootErase = 0x43, + BootVersion = 0x44, +} BootOperation; + + +typedef struct { + uint8_t op; + uint8_t addr[3]; + uint8_t tag[4]; + uint8_t len; + uint8_t payload[255 - 9]; +} __attribute__((packed)) BootloaderReq; + + +static void erase_application() +{ + int page; + for(page = APPLICATION_START_PAGE; page < APPLICATION_END_PAGE; page++) + { + flash_erase_page(page); + } +} + +static void authorize_application() +{ + uint32_t zero = 0; + uint32_t * ptr; + ptr = (uint32_t *)AUTH_WORD_ADDR; + flash_write((uint32_t)ptr, (uint8_t *)&zero, 4); +} +int is_authorized_to_boot() +{ + uint32_t * auth = (uint32_t *)AUTH_WORD_ADDR; + return *auth == 0; +} + +int bootloader_bridge(uint8_t klen, uint8_t * keyh) +{ + static int has_erased = 0; + BootloaderReq * req = (BootloaderReq * )keyh; + uint8_t payload[256]; + uint8_t hash[32]; + uint8_t version = 1; + + uint8_t * pubkey = (uint8_t*)"\x85\xaa\xce\xda\xd4\xb4\xd8\x0d\xf7\x0e\xe8\x91\x6d\x69\x8e\x00\x7a\x27\x40\x76\x93\x7a\x1d\x63\xb1\xcf\xe8\x22\xdd\x9f\xbc\x43\x3e\x34\x0a\x05\x9d\x8a\x9d\x72\xdc\xc2\x4b\x56\x9c\x64\x3d\xc1\x0d\x14\x64\x69\x52\x31\xd7\x54\xa3\xb6\x69\xa7\x6f\x6b\x81\x8d"; + const struct uECC_Curve_t * curve = NULL; + + if (req->len > 255-9) + { + return CTAP1_ERR_INVALID_LENGTH; + } + + memset(payload, 0xff, sizeof(payload)); + memmove(payload, req->payload, req->len); + + uint32_t addr = ((*((uint32_t*)req->addr)) & 0xffffff) | 0x8000000; + + uint32_t * ptr = (uint32_t *)addr; + + switch(req->op){ + case BootWrite: + printf1(TAG_BOOT, "BootWrite: %08lx\r\n",(uint32_t)ptr); + if ((uint32_t)ptr < APPLICATION_START_ADDR || (uint32_t)ptr >= APPLICATION_END_ADDR + || ((uint32_t)ptr+req->len) > APPLICATION_END_ADDR) + { + printf1(TAG_BOOT,"Bound exceeded [%08lx, %08lx]\r\n",APPLICATION_START_ADDR,APPLICATION_END_ADDR); + return CTAP2_ERR_NOT_ALLOWED; + } + + if (!has_erased || is_authorized_to_boot()) + { + erase_application(); + has_erased = 1; + } + if (is_authorized_to_boot()) + { + printf2(TAG_ERR, "Error, boot check bypassed\n"); + exit(1); + } + + flash_write((uint32_t)ptr,payload, req->len); + break; + case BootDone: + printf1(TAG_BOOT, "BootDone: "); + dump_hex1(TAG_BOOT, payload, 32); + ptr = (uint32_t *)APPLICATION_START_ADDR; + crypto_sha256_init(); + crypto_sha256_update((uint8_t*)ptr, APPLICATION_END_ADDR-APPLICATION_START_ADDR); + crypto_sha256_final(hash); + curve = uECC_secp256r1(); + + if (! uECC_verify(pubkey, + hash, + 32, + payload, + curve)) + { + return CTAP2_ERR_OPERATION_DENIED; + } + authorize_application(); + REBOOT_FLAG = 1; + break; + case BootCheck: + return 0; + break; + case BootErase: + printf1(TAG_BOOT, "BootErase.\r\n"); + erase_application(); + return 0; + break; + case BootVersion: + printf1(TAG_BOOT, "BootVersion.\r\n"); + u2f_response_writeback(&version,1); + return 0; + break; + default: + return CTAP1_ERR_INVALID_COMMAND; + } + return 0; +} + +void bootloader_heartbeat() +{ + static int state = 0; + static uint32_t val = 0x10; + + if (state) + { + val--; + } + else + { + val++; + } + + if (val > 30 || val < 1) + { + state = !state; + } + led_rgb((val * 3)<<8 | (val*10) << 16); +} diff --git a/targets/stm32l442/bootloader/bootloader.h b/targets/stm32l442/bootloader/bootloader.h index 8715bc4..576d981 100644 --- a/targets/stm32l442/bootloader/bootloader.h +++ b/targets/stm32l442/bootloader/bootloader.h @@ -22,11 +22,6 @@ #define DISABLE_CTAPHID_WINK #define DISABLE_CTAPHID_CBOR -void printing_init(); -void hw_init(void); - -//#define TEST -//#define TEST_POWER #define LED_INIT_VALUE 0x101000 @@ -37,4 +32,13 @@ void hw_init(void); #define SKIP_BUTTON_CHECK_WITH_DELAY 0 #define SKIP_BUTTON_CHECK_FAST 1 +void printing_init(); +void hw_init(void); + +// Trigger software reset +void device_reboot(); + +int is_authorized_to_boot(); +void bootloader_heartbeat(); + #endif diff --git a/targets/stm32l442/src/device.c b/targets/stm32l442/src/device.c index 01417c5..c5c6ead 100644 --- a/targets/stm32l442/src/device.c +++ b/targets/stm32l442/src/device.c @@ -18,30 +18,11 @@ #include "ctaphid.h" #include "ctap.h" #include "crypto.h" -#include "uECC.h" -#include "u2f.h" +#include "memory_layout.h" -#define PAGE_SIZE 2048 -#define PAGES 128 -// Pages 119-127 are data -#define COUNTER2_PAGE (PAGES - 4) -#define COUNTER1_PAGE (PAGES - 3) -#define STATE2_PAGE (PAGES - 2) -#define STATE1_PAGE (PAGES - 1) - -#define RK_NUM_PAGES 10 -#define RK_START_PAGE (PAGES - 14) -#define RK_END_PAGE (PAGES - 14 + RK_NUM_PAGES) -#define APPLICATION_START_PAGE (16) -#define APPLICATION_START_ADDR flash_addr(APPLICATION_START_PAGE) - -#define APPLICATION_END_PAGE ((PAGES - 19)) // 119 is NOT included in application -#define APPLICATION_END_ADDR (flash_addr(APPLICATION_END_PAGE)-8) // NOT included in application - -#define AUTH_WORD_ADDR (flash_addr(APPLICATION_END_PAGE)-8) uint32_t __90_ms = 0; uint32_t __device_status = 0; @@ -509,162 +490,3 @@ void _Error_Handler(char *file, int line) { } } - - -#ifdef IS_BOOTLOADER - -extern uint8_t REBOOT_FLAG; - -typedef enum -{ - BootWrite = 0x40, - BootDone = 0x41, - BootCheck = 0x42, - BootErase = 0x43, - BootVersion = 0x44, -} BootOperation; - - -typedef struct { - uint8_t op; - uint8_t addr[3]; - uint8_t tag[4]; - uint8_t len; - uint8_t payload[255 - 9]; -} __attribute__((packed)) BootloaderReq; - -//#define APPLICATION_START_ADDR 0x8000 -//#define APPLICATION_START_PAGE (0x8000/PAGE_SIZE) - -//#define APPLICATION_END_ADDR (PAGE_SIZE*125-4) // NOT included in application - -static void erase_application() -{ - int page; - for(page = APPLICATION_START_PAGE; page < APPLICATION_END_PAGE; page++) - { - flash_erase_page(page); - } -} - -static void authorize_application() -{ - uint32_t zero = 0; - uint32_t * ptr; - ptr = (uint32_t *)AUTH_WORD_ADDR; - flash_write((uint32_t)ptr, (uint8_t *)&zero, 4); -} -int is_authorized_to_boot() -{ - uint32_t * auth = (uint32_t *)AUTH_WORD_ADDR; - return *auth == 0; -} - -int bootloader_bridge(uint8_t klen, uint8_t * keyh) -{ - static int has_erased = 0; - BootloaderReq * req = (BootloaderReq * )keyh; - uint8_t payload[256]; - uint8_t hash[32]; - uint8_t version = 1; - - uint8_t * pubkey = (uint8_t*)"\x85\xaa\xce\xda\xd4\xb4\xd8\x0d\xf7\x0e\xe8\x91\x6d\x69\x8e\x00\x7a\x27\x40\x76\x93\x7a\x1d\x63\xb1\xcf\xe8\x22\xdd\x9f\xbc\x43\x3e\x34\x0a\x05\x9d\x8a\x9d\x72\xdc\xc2\x4b\x56\x9c\x64\x3d\xc1\x0d\x14\x64\x69\x52\x31\xd7\x54\xa3\xb6\x69\xa7\x6f\x6b\x81\x8d"; - const struct uECC_Curve_t * curve = NULL; - - if (req->len > 255-9) - { - return CTAP1_ERR_INVALID_LENGTH; - } - - memset(payload, 0xff, sizeof(payload)); - memmove(payload, req->payload, req->len); - - uint32_t addr = ((*((uint32_t*)req->addr)) & 0xffffff) | 0x8000000; - - uint32_t * ptr = (uint32_t *)addr; - - switch(req->op){ - case BootWrite: - printf1(TAG_BOOT, "BootWrite: %08lx\r\n",(uint32_t)ptr); - if ((uint32_t)ptr < APPLICATION_START_ADDR || (uint32_t)ptr >= APPLICATION_END_ADDR - || ((uint32_t)ptr+req->len) > APPLICATION_END_ADDR) - { - printf1(TAG_BOOT,"Bound exceeded [%08lx, %08lx]\r\n",APPLICATION_START_ADDR,APPLICATION_END_ADDR); - return CTAP2_ERR_NOT_ALLOWED; - } - - if (!has_erased || is_authorized_to_boot()) - { - erase_application(); - has_erased = 1; - } - if (is_authorized_to_boot()) - { - printf2(TAG_ERR, "Error, boot check bypassed\n"); - exit(1); - } - - flash_write((uint32_t)ptr,payload, req->len); - break; - case BootDone: - printf1(TAG_BOOT, "BootDone: "); - dump_hex1(TAG_BOOT, payload, 32); - ptr = (uint32_t *)APPLICATION_START_ADDR; - crypto_sha256_init(); - crypto_sha256_update((uint8_t*)ptr, APPLICATION_END_ADDR-APPLICATION_START_ADDR); - crypto_sha256_final(hash); - curve = uECC_secp256r1(); - - if (! uECC_verify(pubkey, - hash, - 32, - payload, - curve)) - { - return CTAP2_ERR_OPERATION_DENIED; - } - authorize_application(); - REBOOT_FLAG = 1; - break; - case BootCheck: - return 0; - break; - case BootErase: - printf1(TAG_BOOT, "BootErase.\r\n"); - erase_application(); - return 0; - break; - case BootVersion: - printf1(TAG_BOOT, "BootVersion.\r\n"); - u2f_response_writeback(&version,1); - return 0; - break; - default: - return CTAP1_ERR_INVALID_COMMAND; - } - return 0; -} - -void bootloader_heartbeat() -{ - static int state = 0; - static uint32_t val = 0x10; - int but = IS_BUTTON_PRESSED(); - - if (state) - { - val--; - } - else - { - val++; - } - - if (val > 30 || val < 1) - { - state = !state; - } - led_rgb((val * 3)<<8 | (val*10) << 16); -} - -#endif diff --git a/targets/stm32l442/src/memory_layout.h b/targets/stm32l442/src/memory_layout.h new file mode 100644 index 0000000..92ecd35 --- /dev/null +++ b/targets/stm32l442/src/memory_layout.h @@ -0,0 +1,33 @@ +#ifndef _MEMORY_LAYOUT_H_ +#define _MEMORY_LAYOUT_H_ + +#define PAGE_SIZE 2048 +#define PAGES 128 + +// Pages 119-127 are data +// Location of counter page and it's backup page +// The flash is wear leveled and counter should be fault tolerant +#define COUNTER2_PAGE (PAGES - 4) +#define COUNTER1_PAGE (PAGES - 3) + +// State of FIDO2 application +#define STATE2_PAGE (PAGES - 2) +#define STATE1_PAGE (PAGES - 1) + +// Storage of FIDO2 resident keys +#define RK_NUM_PAGES 10 +#define RK_START_PAGE (PAGES - 14) +#define RK_END_PAGE (PAGES - 14 + RK_NUM_PAGES) + +// Start of application code +#define APPLICATION_START_PAGE (16) +#define APPLICATION_START_ADDR flash_addr(APPLICATION_START_PAGE) + +// End of application code. Leave some extra room for future data storage. +#define APPLICATION_END_PAGE ((PAGES - 19)) // 119 is NOT included in application +#define APPLICATION_END_ADDR (flash_addr(APPLICATION_END_PAGE)-8) // NOT included in application + +// Bootloader state. +#define AUTH_WORD_ADDR (flash_addr(APPLICATION_END_PAGE)-8) + +#endif