From 2287acead46878041e0e37ba0bfdd12c8cef0115 Mon Sep 17 00:00:00 2001 From: Michele Balistreri Date: Wed, 16 May 2018 15:22:12 +0300 Subject: [PATCH] add code to protect the bootloader and the recovery firmware --- .cproject | 5 ++--- Inc/flash.h | 21 +++++++++++++++++++++ Inc/main.h | 11 ++++++++++- Src/flash.c | 15 +++++++++++++++ Src/main.c | 19 +++++++++++++++++++ 5 files changed, 67 insertions(+), 4 deletions(-) diff --git a/.cproject b/.cproject index 21bbd2f..cf723be 100644 --- a/.cproject +++ b/.cproject @@ -94,9 +94,6 @@ - - - @@ -145,6 +142,7 @@ @@ -232,4 +230,5 @@ + diff --git a/Inc/flash.h b/Inc/flash.h index f70bd32..f5d4d87 100644 --- a/Inc/flash.h +++ b/Inc/flash.h @@ -7,9 +7,19 @@ #define FLASH_KEYR1 0x45670123 #define FLASH_KEYR2 0xCDEF89AB +#define FLASH_OPTKEYR1 0x08192A3B +#define FLASH_OPTKEYR2 0x4C5D6E7F + #define FLASH_BANK1 0 #define FLASH_BANK2 1 +#define RDP2 0xcc + +#define FLASH_IS_RDP2() ((FLASH->OPTR & 0xff) == RDP2) +#define FLASH_SET_RDP2() FLASH->OPTR |= RDP2 +#define FLASH_WP(reg, start, end) reg = (0xFF00FF00 | end << 16 | start) + + /** * Unlocks the flash, allowing writing. */ @@ -31,4 +41,15 @@ int flash_copy(uint32_t* src, __IO uint32_t* dst, uint32_t size); */ int flash_lock(); +/** + * Unlock the option bytes + */ +int flash_optunlock(); + +/** + * Write and reload the option bytes + */ +void flash_optprogram(); + + #endif /* FLASH_H_ */ diff --git a/Inc/main.h b/Inc/main.h index 7ab06fc..908ebf2 100644 --- a/Inc/main.h +++ b/Inc/main.h @@ -8,9 +8,12 @@ // The constants below define the memory layout documented in the README.md file #define BOOTLOADER_SIZE 0x2000 +#define BOOTLOADER_FIRST_PAGE 0 +#define BOOTLOADER_LAST_PAGE ((BOOTLOADER_SIZE / FLASH_PAGE_SIZE) - 1) + #define FIRMWARE_SIZE ((FLASH_BANK_SIZE - BOOTLOADER_SIZE) / 2) #define FIRMWARE_HEADER_SIZE 0x200 -#define FIRMWARE_FIRST_PAGE (BOOTLOADER_SIZE / FLASH_PAGE_SIZE) +#define FIRMWARE_FIRST_PAGE (BOOTLOADER_LAST_PAGE + 1) #define FIRMWARE_PAGE_COUNT (FIRMWARE_SIZE / FLASH_PAGE_SIZE) #define FIRMWARE_START (FLASH_START_BANK1 + BOOTLOADER_SIZE) @@ -21,6 +24,8 @@ #define RECOVERY_FW_START (FIRMWARE_START + FIRMWARE_SIZE) #define RECOVERY_FW_FIRST_PAGE (FIRMWARE_FIRST_PAGE + FIRMWARE_PAGE_COUNT) +#define RECOVERY_FW_LAST_PAGE (RECOVERY_FW_FIRST_PAGE + FIRMWARE_PAGE_COUNT - 1) + #define SIGNATURE_HEADER_OFFSET 8 #define SIGNATURE_LENGTH 64 @@ -28,6 +33,10 @@ #define SIGNATURE_COUNT 1 +/** + * Checks if the bootloader and recovery are write protected, if not protect them. Also enables the Read Protection level 2. Since this is irreversible, the code is disabled during development + */ +void protect_flash(); /** * Checks the firmware a the given address. It checks the magic number, validates the size and checks the signature(s). diff --git a/Src/flash.c b/Src/flash.c index 568445c..d76a76d 100644 --- a/Src/flash.c +++ b/Src/flash.c @@ -18,6 +18,15 @@ int flash_unlock() { return READ_BIT(FLASH->CR, FLASH_CR_LOCK); } +int flash_optunlock() { + flash_unlock(); + + FLASH->OPTKEYR = FLASH_OPTKEYR1; + FLASH->OPTKEYR = FLASH_OPTKEYR2; + + return READ_BIT(FLASH->CR, FLASH_CR_OPTLOCK); +} + int _flash_erase_page(uint8_t bank, uint8_t pg) { if(bank == FLASH_BANK1) { CLEAR_BIT(FLASH->CR, FLASH_CR_BKER); @@ -77,3 +86,9 @@ int flash_lock() { SET_BIT(FLASH->CR, FLASH_CR_LOCK); return 0; } + +void flash_optprogram() { + SET_BIT(FLASH->CR, FLASH_CR_OPTSTRT); + _flash_wait(); + SET_BIT(FLASH->CR, FLASH_CR_OBL_LAUNCH); +} diff --git a/Src/main.c b/Src/main.c index c8c68d2..ecc66d9 100644 --- a/Src/main.c +++ b/Src/main.c @@ -6,6 +6,8 @@ uint8_t fw_public_key[] = { 0xfe, 0xcb, 0x28, 0xb9, 0x50, 0xdd, 0x8b, 0x2f, 0xc7, 0x34, 0xd3, 0x60, 0x5b, 0x1a, 0xc6, 0xed, 0x02, 0x50, 0xf2, 0x4a, 0xc4, 0x75, 0xd1, 0x28, 0x7f, 0x7c, 0xb5, 0xce, 0x61, 0xd6, 0x95, 0xb9, 0xb5, 0x27, 0x0b, 0x52, 0x77, 0x42, 0x4b, 0xf3, 0xb4, 0x3c, 0xef, 0xcb, 0x56, 0xd1, 0x98, 0x22, 0x11, 0xc2, 0xe5, 0xd3, 0xf0, 0x22, 0x87, 0xb9, 0xe8, 0x20, 0xdc, 0xee, 0x9f, 0xc2, 0xad, 0x22, }; int main(void) { + protect_flash(); + if (!check_firmware(UPGRADE_FW_START)) { upgrade_firmware(); } else if (check_firmware(FIRMWARE_START)) { @@ -43,6 +45,23 @@ int check_firmware(uintptr_t addr) { return 0; } +void protect_flash() { +#ifdef BOOTLOADER_RELEASE + if (FLASH_IS_RDP2()) { + return; + } + + flash_optunlock(); + + FLASH_SET_RDP2(); + FLASH_WP(FLASH->WRP1AR, BOOTLOADER_FIRST_PAGE, BOOTLOADER_LAST_PAGE); + FLASH_WP(FLASH->WRP1BR, RECOVERY_FW_FIRST_PAGE, RECOVERY_FW_LAST_PAGE); + + // This resets the MCU + flash_optprogram(); +#endif +} + void _load_firmware(uintptr_t newfw, uint8_t newfw_bank, uint8_t newfw_page, uint8_t remove_newfw) { flash_unlock();