96 lines
3.2 KiB
C
96 lines
3.2 KiB
C
//
|
|
// (c) Copyright 2018 by Coinkite Inc. This file is covered by license found in COPYING-CC.
|
|
//
|
|
//
|
|
// enable.c
|
|
//
|
|
// C-level code to enable the firewall feature. All **outside** the firewall.
|
|
//
|
|
#include <errno.h>
|
|
#include "basics.h"
|
|
#include "stm32l4xx_hal_firewall.h"
|
|
#include "stm32l4xx_hal_rcc.h"
|
|
#include "storage.h"
|
|
#include "constant_time.h"
|
|
|
|
|
|
// firewall_setup()
|
|
//
|
|
// It's best if this is outside the firewall. After we return, we'll
|
|
// jump into setup code contained inside the firewall.
|
|
//
|
|
void
|
|
firewall_setup(void)
|
|
{
|
|
// This is critical: without the clock enabled to "SYSCFG" we
|
|
// can't tell the FW is enabled or not! Enabling it would also not work
|
|
__HAL_RCC_SYSCFG_CLK_ENABLE();
|
|
|
|
if(__HAL_FIREWALL_IS_ENABLED()) {
|
|
// After the first (POR) reset, the firewall may already be enabled, and if so
|
|
// we can't change it anyway, so we're done.
|
|
return;
|
|
}
|
|
|
|
#if RELEASE
|
|
// REMINDERS:
|
|
// - cannot debug anything in boot loader w/ firewall enabled (no readback, no bkpt)
|
|
// - when RDP=2, this protection still important or else python can read pairing secret
|
|
// - in factory mode (RDP!=2), it's nice to have this disabled so we can debug still
|
|
// - could look at RDP level here, but it would be harder to completely reset the bag number!
|
|
if(check_all_ones(rom_secrets->bag_number, sizeof(rom_secrets->bag_number))) {
|
|
// ok. still virgin unit -- run w/o security
|
|
return;
|
|
}
|
|
#else
|
|
// for debug builds, never enable firewall
|
|
return;
|
|
#endif
|
|
|
|
extern int firewall_starts; // see startup.S ... aligned@256 (0x08000300)
|
|
uint32_t start = (uint32_t)&firewall_starts;
|
|
uint32_t len = BL_FLASH_SIZE - (start - BL_FLASH_BASE);
|
|
|
|
#if 0
|
|
ASSERT(start);
|
|
ASSERT(!(start & 0xff));
|
|
ASSERT(len>256);
|
|
ASSERT(!(len & 0xff));
|
|
#endif
|
|
|
|
// NOTE: the "Non volatile data segment" is not executable, and so cannot
|
|
// overlap the "Code Segment". Not clear why it's ever useful, but
|
|
// maybe so you can prevent execution on that section, or have it somewhere
|
|
// else I suppose.
|
|
//
|
|
// - many of the bits in these registers are not-implemented and are forced to zero
|
|
// - that prevents the firewall being used for things like protecting OTP area
|
|
// - volatile data is SRAM1 only, so doesn't help us, since we're using SRAM2
|
|
// - on-chip DFU will erase up to start (0x300), which borks the reset vector
|
|
// but sensitive stuff is still there (which would allow bypass)
|
|
// - so it's important to enable option bytes to set write-protect on entire bootloader
|
|
// - to disable debug and complete protection, must enable write-protect "level 2"
|
|
//
|
|
|
|
FIREWALL_InitTypeDef init = {
|
|
.CodeSegmentStartAddress = start,
|
|
.CodeSegmentLength = len,
|
|
.NonVDataSegmentStartAddress = BL_NVROM_BASE,
|
|
.NonVDataSegmentLength = BL_NVROM_SIZE,
|
|
.VDataSegmentStartAddress = 0,
|
|
.VDataSegmentLength = 0,
|
|
.VolatileDataExecution = 0,
|
|
.VolatileDataShared = 0,
|
|
};
|
|
|
|
int rv = HAL_FIREWALL_Config((FIREWALL_InitTypeDef *)&init);
|
|
if(rv) {
|
|
INCONSISTENT("fw");
|
|
}
|
|
|
|
__HAL_FIREWALL_PREARM_DISABLE();
|
|
HAL_FIREWALL_EnableFirewall();
|
|
}
|
|
|
|
// EOF
|