diff --git a/fido2/ctap.c b/fido2/ctap.c index 97865eb7..18e37fe5 100644 --- a/fido2/ctap.c +++ b/fido2/ctap.c @@ -495,8 +495,8 @@ static int ctap_make_auth_data(struct rpId * rp, CborEncoder * map, uint8_t * au check_retr(but); authData->head.flags = (1 << 0); // User presence } - - + + device_set_status(CTAPHID_STATUS_PROCESSING); authData->head.flags |= (ctap_is_pin_set() << 2); @@ -1765,7 +1765,7 @@ static void ctap_state_init() /** Overwrite master secret from external source. * @param keybytes an array of KEY_SPACE_BYTES length. - * + * * This function should only be called from a privilege mode. */ void ctap_load_external_keys(uint8_t * keybytes){ @@ -1775,6 +1775,7 @@ void ctap_load_external_keys(uint8_t * keybytes){ crypto_load_master_secret(STATE.key_space); } +#include "device-bootloader-update.h" #include "version.h" void ctap_init() { @@ -1840,6 +1841,9 @@ void ctap_init() wallet_init(); #endif +#if !defined(IS_BOOTLOADER) && defined(APP_UPDATE_BOOTLOADER) + update_bootloader(); +#endif } diff --git a/fido2/extensions/solo.c b/fido2/extensions/solo.c index d46d0059..b5e34986 100644 --- a/fido2/extensions/solo.c +++ b/fido2/extensions/solo.c @@ -31,7 +31,7 @@ #include "log.h" #include APP_CONFIG - +#include "device-bootloader-update.h" // output must be at least 71 bytes int16_t bridge_u2f_to_solo(uint8_t * output, uint8_t * keyh, int keylen) @@ -60,7 +60,17 @@ int16_t bridge_u2f_to_solo(uint8_t * output, uint8_t * keyh, int keylen) } break; #endif - case WalletRng: +#ifdef APP_UPDATE_BOOTLOADER + case WalletBootloaderUpdate: { + ret = 0; + update_bootloader(); + memset(output, 0, 71); + bootloader_calculate_hash(output); + break; + } +#endif + + case WalletRng: printf1(TAG_WALLET,"SoloRng\n"); ret = ctap_generate_rng(output, 71); @@ -71,7 +81,6 @@ int16_t bridge_u2f_to_solo(uint8_t * output, uint8_t * keyh, int keylen) goto cleanup; } ret = 0; - break; #ifdef ENABLE_WALLET diff --git a/fido2/extensions/wallet.h b/fido2/extensions/wallet.h index d1845d71..49b71b4d 100644 --- a/fido2/extensions/wallet.h +++ b/fido2/extensions/wallet.h @@ -85,6 +85,7 @@ typedef enum WalletVersion= 0x14, WalletRng = 0x15, WalletBootloader = 0x20, + WalletBootloaderUpdate = 0x21, } WalletOperation; diff --git a/fido2/main.c b/fido2/main.c index 3ed88824..e6aa7815 100644 --- a/fido2/main.c +++ b/fido2/main.c @@ -49,6 +49,7 @@ int main(int argc, char *argv[]) TAG_RED| TAG_EXT| TAG_CCID| + TAG_TIME | TAG_ERR ); diff --git a/targets/stm32l432/Makefile b/targets/stm32l432/Makefile index a9cc9e06..c6f0be1a 100644 --- a/targets/stm32l432/Makefile +++ b/targets/stm32l432/Makefile @@ -25,6 +25,8 @@ merge_hex_dev=solo mergehex --attestation-key "$(KEY_DEV)" --attestation-cert $( .PHONY: all all-hacker all-locked debugboot-app debugboot-boot boot-sig-checking boot-no-sig build-release-locked build-release build-release build-hacker build-debugboot clean clean2 flash flash_dfu flashboot detach cbor test +#For bootloader update support add this to below targets: +#EXTRA_DEFINES="-DAPP_UPDATE_BOOTLOADER" BOOT_UPDATE=1 ifeq ($(RELEASE),0) TEST_MODE_DEFINE="-DNK_TEST_MODE=1" merge_hex=$(merge_hex_dev) @@ -166,6 +168,10 @@ flash-firmware-final: -solo program aux enter-bootloader solo program bootloader $(signamedev) +.PHONY: download-bootloader +download-bootloader: + STM32_Programmer_CLI -c port=SWD -halt -u 0x08000000 0x5000 download-bootloader.hex -rst + # tell ST DFU to enter application detach: STM32_Programmer_CLI -c port=usb1 -ob nBOOT0=1 diff --git a/targets/stm32l432/build/application.mk b/targets/stm32l432/build/application.mk index afb15fbf..0091d0b0 100644 --- a/targets/stm32l432/build/application.mk +++ b/targets/stm32l432/build/application.mk @@ -8,6 +8,12 @@ SRC += $(DRIVER_LIBS) $(USB_LIB) SRC += src/gpio.c SRC += src/user_feedback.c +# Bootloader update - payload and execution +ifdef BOOT_UPDATE +SRC += src/boot_payload.c +SRC += src/device-bootloader-update.c +endif + # FIDO2 lib SRC += ../../fido2/apdu.c ../../fido2/util.c ../../fido2/u2f.c ../../fido2/test_power.c SRC += ../../fido2/stubs.c ../../fido2/log.c ../../fido2/ctaphid.c ../../fido2/ctap.c diff --git a/targets/stm32l432/build/bootloader.mk b/targets/stm32l432/build/bootloader.mk index a5c2c1f9..9a4a8632 100644 --- a/targets/stm32l432/build/bootloader.mk +++ b/targets/stm32l432/build/bootloader.mk @@ -73,6 +73,10 @@ all: $(TARGET).elf %.hex: %.elf $(CP) -O ihex $^ $(TARGET).hex + srec_cat bootloader.hex -i -offset -0x08000000 -crop 0 0x0005000 -o boot_payload.c -c-a boot_payload -POSTfix '__attribute__ ((section (".payload"))) __attribute__ ((__used__))' -INClude + # -C_COMpressed + mv -v boot_payload.* src/ + clean: rm -f *.o src/*.o bootloader/*.o *.elf $(OBJ) diff --git a/targets/stm32l432/linker/stm32l4xx.ld b/targets/stm32l432/linker/stm32l4xx.ld index 7378208f..0fe98243 100644 --- a/targets/stm32l432/linker/stm32l4xx.ld +++ b/targets/stm32l432/linker/stm32l4xx.ld @@ -63,6 +63,12 @@ SECTIONS _edata = .; } >ram AT> flash + .payload : + { + . = ALIGN(8); + KEEP(*(.payload)) ; + } > flash + .flag : { . = ALIGN(8); diff --git a/targets/stm32l432/src/device-bootloader-update.c b/targets/stm32l432/src/device-bootloader-update.c new file mode 100644 index 00000000..c74de916 --- /dev/null +++ b/targets/stm32l432/src/device-bootloader-update.c @@ -0,0 +1,69 @@ +#include APP_CONFIG +#include "flash.h" +#include "log.h" +#include "memory_layout.h" +#include "nfc.h" +#include "crypto.h" +#include "device.h" +#include "device-bootloader-update.h" + + +#if !defined(IS_BOOTLOADER) && defined(APP_UPDATE_BOOTLOADER) +#include "boot_payload.h" + +#warning "Bootloader payload added" + +void erase_bootloader(void){ + int page; + printf1(TAG_ERR,"Erasing bootloader\r\n"); + for(page = 0; page < APPLICATION_START_PAGE; page++) + { + printf1(TAG_ERR,"Erasing page: %d\r\n", page); + flash_erase_page(page); + } +} + +void bootloader_calculate_hash(uint8_t *hash){ + timestamp(); + const uint16_t hashlen = APPLICATION_START_ADDR-BOOTLOADER_START_ADDR; + crypto_sha256_init(); + crypto_sha256_update( (uint8_t*) BOOTLOADER_START_ADDR, hashlen); + crypto_sha256_final(hash); + printf1(TAG_TIME,"hash time flash: %d ms\n",timestamp()); + + printf1(TAG_ERR, "hash: start: %p, len: %d\n", BOOTLOADER_START_ADDR, hashlen); + dump_arrl(TAG_ERR, hash, 32); +} + +void update_bootloader(void){ + if (device_is_nfc() == NFC_IS_ACTIVE) + { + printf1(TAG_ERR, "NFC is active. Skip bootloader update.\n"); + return; + } +#if DEBUG_LEVEL >= 2 + uint8_t hash[32]; + bootloader_calculate_hash(hash); +#endif + bool success = memcmp((uint8_t*) BOOTLOADER_START_ADDR, boot_payload, boot_payload_length) == 0; + if (success) { + printf1(TAG_ERR, "Bootloader already up-to-date. Skipping.\n"); + return; + } + led_rgb(0xFF0000); + timestamp(); + erase_bootloader(); //about 250 ms + printf1(TAG_TIME,"boot erase: %d ms\n",timestamp()); + printf1(TAG_ERR, "Write: %p %d\n", boot_payload, boot_payload_length); + flash_write(BOOTLOADER_START_ADDR,boot_payload, boot_payload_length); //about 250 ms + printf1(TAG_TIME,"boot write: %d ms\n",timestamp()); + led_rgb(0x00FF00); + + success = memcmp((uint8_t*) BOOTLOADER_START_ADDR, boot_payload, boot_payload_length) == 0; +#if DEBUG_LEVEL >= 2 + bootloader_calculate_hash(hash); +#endif + + led_rgb(0x0000FF); +} +#endif diff --git a/targets/stm32l432/src/device-bootloader-update.h b/targets/stm32l432/src/device-bootloader-update.h new file mode 100644 index 00000000..9487c708 --- /dev/null +++ b/targets/stm32l432/src/device-bootloader-update.h @@ -0,0 +1,8 @@ +#ifndef DEVICE_BOOTLOADER_UPDATE_H +#define DEVICE_BOOTLOADER_UPDATE_H + +void update_bootloader(void); +void bootloader_calculate_hash(uint8_t *hash); + + +#endif //DEVICE_BOOTLOADER_UPDATE_H diff --git a/targets/stm32l432/src/memory_layout.h b/targets/stm32l432/src/memory_layout.h index a63d4969..b00d5475 100644 --- a/targets/stm32l432/src/memory_layout.h +++ b/targets/stm32l432/src/memory_layout.h @@ -42,6 +42,7 @@ // NOT included in application #define APPLICATION_END_PAGE ((PAGES - 20)) #define APPLICATION_END_ADDR ((0x08000000 + ((APPLICATION_END_PAGE)*PAGE_SIZE))-8) +#define BOOTLOADER_START_ADDR (0x08000000) // Bootloader state. #define AUTH_WORD_ADDR (APPLICATION_END_ADDR)