diff --git a/docs/memory.md b/docs/memory.md index b05d3056c..35d7db907 100644 --- a/docs/memory.md +++ b/docs/memory.md @@ -35,7 +35,7 @@ |----------|-------------------------|------|-------------------------------- | block 0 | 0x1FFF7800 - 0x1FFF781F | 32 B | device manufacturing date | block 1 | 0x1FFF7820 - 0x1FFF783F | 32 B | bootloader downgrade protection -| block 2 | 0x1FFF7840 - 0x1FFF785F | 32 B | unused +| block 2 | 0x1FFF7840 - 0x1FFF785F | 32 B | vendor keys lock | block 3 | 0x1FFF7860 - 0x1FFF787F | 32 B | unused | block 4 | 0x1FFF7880 - 0x1FFF789F | 32 B | unused | block 5 | 0x1FFF78A0 - 0x1FFF78BF | 32 B | unused diff --git a/embed/bootloader/main.c b/embed/bootloader/main.c index b14add349..cec56702a 100644 --- a/embed/bootloader/main.c +++ b/embed/bootloader/main.c @@ -259,7 +259,7 @@ secbool bootloader_loop(secbool firmware_present) // protection against bootloader downgrade -#define BOOTLOADER_VERSION_OTP_BLOCK 1 +#define OTP_BLOCK_BOOTLOADER_VERSION 1 void check_bootloader_version(void) { @@ -271,10 +271,10 @@ void check_bootloader_version(void) bits[i / 8] |= (1 << (7 - (i % 8))); } } - ensure(flash_otp_write(BOOTLOADER_VERSION_OTP_BLOCK, 0, bits, FLASH_OTP_BLOCK_SIZE), NULL); + ensure(flash_otp_write(OTP_BLOCK_BOOTLOADER_VERSION, 0, bits, FLASH_OTP_BLOCK_SIZE), NULL); uint8_t bits2[FLASH_OTP_BLOCK_SIZE]; - ensure(flash_otp_read(BOOTLOADER_VERSION_OTP_BLOCK, 0, bits2, FLASH_OTP_BLOCK_SIZE), NULL); + ensure(flash_otp_read(OTP_BLOCK_BOOTLOADER_VERSION, 0, bits2, FLASH_OTP_BLOCK_SIZE), NULL); ensure(sectrue * (0 == memcmp(bits, bits2, FLASH_OTP_BLOCK_SIZE)), "Bootloader downgraded"); } @@ -284,6 +284,19 @@ secbool load_vendor_header_keys(const uint8_t * const data, vendor_header * cons return load_vendor_header(data, BOOTLOADER_KEY_M, BOOTLOADER_KEY_N, BOOTLOADER_KEYS, vhdr); } +#define OTP_BLOCK_VENDOR_KEYS_LOCK 2 + +secbool check_vendor_keys_lock(const vendor_header * const vhdr) { + uint8_t lock[FLASH_OTP_BLOCK_SIZE]; + ensure(flash_otp_read(OTP_BLOCK_VENDOR_KEYS_LOCK, 0, lock, FLASH_OTP_BLOCK_SIZE), NULL); + if (0 == memcmp(lock, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", FLASH_OTP_BLOCK_SIZE)) { + return sectrue; + } + uint8_t hash[32]; + vendor_keys_hash(vhdr, hash); + return sectrue * (0 == memcmp(lock, hash, 32)); +} + int main(void) { #if PRODUCTION @@ -316,6 +329,10 @@ int main(void) load_vendor_header_keys((const uint8_t *)FIRMWARE_START, &vhdr), "invalid vendor header"); + ensure( + check_vendor_keys_lock(&vhdr), + "unauthorized vendor keys"); + image_header hdr; ensure(