refactor
This commit is contained in:
parent
aece05b2e8
commit
e107a9aa86
@ -44,7 +44,7 @@ void usbhid_close();
|
|||||||
void main_loop_delay();
|
void main_loop_delay();
|
||||||
|
|
||||||
void heartbeat();
|
void heartbeat();
|
||||||
void bootloader_heartbeat();
|
|
||||||
|
|
||||||
void authenticator_read_state(AuthenticatorState * );
|
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_load_rk(int index,CTAP_residentKey * rk);
|
||||||
void ctap_overwrite_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
|
#endif
|
||||||
|
@ -25,4 +25,6 @@
|
|||||||
|
|
||||||
int16_t extend_u2f(struct u2f_request_apdu* req, uint32_t len);
|
int16_t extend_u2f(struct u2f_request_apdu* req, uint32_t len);
|
||||||
|
|
||||||
|
int bootloader_bridge(uint8_t klen, uint8_t * keyh);
|
||||||
|
|
||||||
#endif /* EXTENSIONS_H_ */
|
#endif /* EXTENSIONS_H_ */
|
||||||
|
@ -4,7 +4,8 @@ SZ=arm-none-eabi-size
|
|||||||
AR=arm-none-eabi-ar
|
AR=arm-none-eabi-ar
|
||||||
|
|
||||||
# ST related
|
# 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/fifo.c src/crypto.c src/attestation.c
|
||||||
SRC += src/startup_stm32l432xx.s src/system_stm32l4xx.c
|
SRC += src/startup_stm32l432xx.s src/system_stm32l4xx.c
|
||||||
SRC += $(wildcard lib/*.c) $(wildcard lib/usbd/*.c)
|
SRC += $(wildcard lib/*.c) $(wildcard lib/usbd/*.c)
|
||||||
|
162
targets/stm32l442/bootloader/bootloader.c
Normal file
162
targets/stm32l442/bootloader/bootloader.c
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#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);
|
||||||
|
}
|
@ -22,11 +22,6 @@
|
|||||||
#define DISABLE_CTAPHID_WINK
|
#define DISABLE_CTAPHID_WINK
|
||||||
#define DISABLE_CTAPHID_CBOR
|
#define DISABLE_CTAPHID_CBOR
|
||||||
|
|
||||||
void printing_init();
|
|
||||||
void hw_init(void);
|
|
||||||
|
|
||||||
//#define TEST
|
|
||||||
//#define TEST_POWER
|
|
||||||
|
|
||||||
#define LED_INIT_VALUE 0x101000
|
#define LED_INIT_VALUE 0x101000
|
||||||
|
|
||||||
@ -37,4 +32,13 @@ void hw_init(void);
|
|||||||
#define SKIP_BUTTON_CHECK_WITH_DELAY 0
|
#define SKIP_BUTTON_CHECK_WITH_DELAY 0
|
||||||
#define SKIP_BUTTON_CHECK_FAST 1
|
#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
|
#endif
|
||||||
|
@ -18,30 +18,11 @@
|
|||||||
#include "ctaphid.h"
|
#include "ctaphid.h"
|
||||||
#include "ctap.h"
|
#include "ctap.h"
|
||||||
#include "crypto.h"
|
#include "crypto.h"
|
||||||
#include "uECC.h"
|
#include "memory_layout.h"
|
||||||
#include "u2f.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 __90_ms = 0;
|
||||||
uint32_t __device_status = 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
|
|
||||||
|
33
targets/stm32l442/src/memory_layout.h
Normal file
33
targets/stm32l442/src/memory_layout.h
Normal file
@ -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
|
Loading…
x
Reference in New Issue
Block a user