psram restore, soon sdcard recovery
This commit is contained in:
parent
639409cd71
commit
7ec6093865
@ -26,15 +26,16 @@ TARGET_NAME = bootloader
|
||||
# Source files. Important: Add them also to link-script.ld to control placement.
|
||||
OBJS += startup.o assets/screens.o
|
||||
OBJS += firewall.o main.o dispatch.o verify.o oled.o clocks.o storage.o constant_time.o rng.o ae.o
|
||||
OBJS += delay.o gpio.o pins.o version.o sflash.o console.o psram.o
|
||||
OBJS += delay.o gpio.o pins.o version.o console.o psram.o sdcard.o
|
||||
OBJS += faster_sha256.o micro-ecc/uECC.o hal_glue.o
|
||||
|
||||
# Have to have copies of these because the DMA and interrupt stuff
|
||||
# needs to be commented-out.
|
||||
OBJS += stm32l4xx_hal_firewall.o stm32l4xx_hal_gpio.o stm32l4xx_hal_spi.o
|
||||
OBJS += stm32l4xx_hal_rcc.o stm32l4xx_hal_rcc_ex.o
|
||||
OBJS += stm32l4xx_hal_hash.o # stm32l4xx_hal_usart.o
|
||||
OBJS += stm32l4xx_hal_hash.o
|
||||
OBJS += stm32l4xx_hal_ospi.o
|
||||
OBJS += stm32l4xx_hal_sd.o stm32l4xx_ll_sdmmc.o
|
||||
|
||||
#OBJS = $(addsuffix .o, $(basename $(C_SRCS) $(ASM_SRCS)))
|
||||
|
||||
|
||||
1
stm32/mk4-bootloader/README.md
Symbolic link
1
stm32/mk4-bootloader/README.md
Symbolic link
@ -0,0 +1 @@
|
||||
../bootloader/README.md
|
||||
@ -2,6 +2,7 @@
|
||||
* (c) Copyright 2018 by Coinkite Inc. This file is covered by license found in COPYING-CC.
|
||||
*/
|
||||
#include "constant_time.h"
|
||||
#include "rng.h"
|
||||
|
||||
// check_all_ones()
|
||||
//
|
||||
@ -17,6 +18,7 @@ check_all_ones(const void *ptrV, int len)
|
||||
rv &= *ptr;
|
||||
}
|
||||
|
||||
rng_delay();
|
||||
return (rv == 0xff);
|
||||
}
|
||||
|
||||
@ -34,6 +36,7 @@ check_all_zeros(const void *ptrV, int len)
|
||||
rv |= *ptr;
|
||||
}
|
||||
|
||||
rng_delay();
|
||||
return (rv == 0x00);
|
||||
}
|
||||
|
||||
@ -53,6 +56,7 @@ check_equal(const void *aV, const void *bV, int len)
|
||||
diff |= (left[i] ^ right[i]);
|
||||
}
|
||||
|
||||
rng_delay();
|
||||
return (diff == 0);
|
||||
}
|
||||
|
||||
|
||||
@ -25,4 +25,14 @@ delay_ms(int ms)
|
||||
}
|
||||
}
|
||||
|
||||
// HAL_Delay()
|
||||
//
|
||||
// Replace HAL version which needs interrupts
|
||||
//
|
||||
void
|
||||
HAL_Delay(uint32_t Delay)
|
||||
{
|
||||
delay_ms(Delay);
|
||||
}
|
||||
|
||||
// EOF
|
||||
|
||||
@ -229,6 +229,7 @@ firewall_dispatch(int method_num, uint8_t *buf_io, int len_in,
|
||||
}
|
||||
|
||||
wipe_all_sram();
|
||||
psram_wipe();
|
||||
|
||||
if(arg2 == 2) {
|
||||
// need some time to show OLED contents
|
||||
@ -240,8 +241,6 @@ firewall_dispatch(int method_num, uint8_t *buf_io, int len_in,
|
||||
// NOT-REACHED (but ok if it does)
|
||||
}
|
||||
|
||||
psram_wipe();
|
||||
|
||||
// wait for an interrupt which will never happen (ie. sleep)
|
||||
LOCKUP_FOREVER()
|
||||
break;
|
||||
@ -266,7 +265,7 @@ firewall_dispatch(int method_num, uint8_t *buf_io, int len_in,
|
||||
uint8_t fw_digest[32], world_digest[32];
|
||||
|
||||
// takes time, shows progress bar
|
||||
checksum_flash(fw_digest, world_digest);
|
||||
checksum_flash(fw_digest, world_digest, 0);
|
||||
|
||||
rv = ae_set_gpio_secure(world_digest);
|
||||
|
||||
@ -371,6 +370,10 @@ firewall_dispatch(int method_num, uint8_t *buf_io, int len_in,
|
||||
rv = pin_long_secret(args);
|
||||
break;
|
||||
|
||||
case 7: // new for Mk4
|
||||
rv = pin_firmware_upgrade(args);
|
||||
break;
|
||||
|
||||
default:
|
||||
rv = ENOENT;
|
||||
break;
|
||||
|
||||
@ -78,6 +78,15 @@ gpio_setup(void)
|
||||
|
||||
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_7, 0); // turn LED off
|
||||
}
|
||||
// SD card detect switch: PC13
|
||||
{ GPIO_InitTypeDef setup = {
|
||||
.Pin = GPIO_PIN_13,
|
||||
.Mode = GPIO_MODE_INPUT,
|
||||
.Pull = GPIO_PULLUP,
|
||||
.Speed = GPIO_SPEED_FREQ_LOW,
|
||||
};
|
||||
HAL_GPIO_Init(GPIOC, &setup);
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
|
||||
@ -179,4 +179,9 @@ HAL_StatusTypeDef HAL_PWREx_ControlVoltageScaling(uint32_t VoltageScaling)
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
__weak void HAL_SDEx_DriveTransceiver_1_8V_Callback(FlagStatus status)
|
||||
{
|
||||
// unused?
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -24,8 +24,9 @@
|
||||
#include "pins.h"
|
||||
#include "verify.h"
|
||||
#include "storage.h"
|
||||
#include "sflash.h"
|
||||
//#include "sflash.h"
|
||||
#include "psram.h"
|
||||
#include "sdcard.h"
|
||||
#include "dispatch.h"
|
||||
#include "constant_time.h"
|
||||
#include "assets/screens.h"
|
||||
@ -46,7 +47,7 @@ reboot_seed_setup(void)
|
||||
extern uint8_t reboot_seed_base[1024]; // see link-script.ld
|
||||
|
||||
// lots of manual memory alloc here...
|
||||
uint8_t *reboot_seed = &reboot_seed_base[0]; // 32 bytes
|
||||
uint8_t *reboot_seed = &reboot_seed_base[0]; // 32 bytes
|
||||
|
||||
// populate seed w/ some noise
|
||||
ASSERT(((uint32_t)reboot_seed) == 0x20001c00);
|
||||
@ -147,10 +148,15 @@ system_startup(void)
|
||||
puts2("AE setup: ");
|
||||
// secure element setup
|
||||
ae_setup();
|
||||
ae_set_gpio(0); // not checking return on purpose
|
||||
ae_set_gpio(0); // not checking return on purpose XXX maybe move elsewhere/skip?
|
||||
|
||||
puts("done");
|
||||
|
||||
if(sdcard_is_inserted()) {
|
||||
puts2("SDCard: ");
|
||||
sdcard_setup();
|
||||
}
|
||||
|
||||
#if 0
|
||||
{ uint8_t config[128] = {0};
|
||||
int x = ae_config_read(config);
|
||||
@ -168,23 +174,30 @@ system_startup(void)
|
||||
// - may also do one-time setup of 508a
|
||||
// - note: ae_setup must already be called, since it can talk to that
|
||||
flash_setup();
|
||||
|
||||
puts("flash setup done");
|
||||
|
||||
// maybe upgrade to a firmware image found in sflash
|
||||
sf_firmware_upgrade();
|
||||
puts("Flash: setup done");
|
||||
|
||||
//puts("PSRAM setup");
|
||||
psram_setup();
|
||||
|
||||
// Check firmware is legit; else enter DFU
|
||||
// - may die due to downgrade attack or unsigned/badly signed image
|
||||
// - may die due to downgrade attack or badly signed image
|
||||
puts2("Verify: ");
|
||||
verify_firmware();
|
||||
bool main_ok = verify_firmware();
|
||||
|
||||
// load a blank screen, so that if the firmware crashes, we are showing
|
||||
// something reasonable and not misleading.
|
||||
oled_show(screen_blankish);
|
||||
if(main_ok) {
|
||||
// load a blank screen, so that if the firmware crashes, we are showing
|
||||
// something reasonable and not misleading.
|
||||
oled_show(screen_blankish);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// try to recover, from an image hanging around in PSRAM
|
||||
// .. will reboot if it works; only helps w/ reset pulses, not power downs.
|
||||
psram_recover_firmware();
|
||||
|
||||
// plan B?
|
||||
enter_dfu();
|
||||
}
|
||||
|
||||
// fatal_error(const char *msg)
|
||||
|
||||
@ -14,6 +14,7 @@
|
||||
#include "constant_time.h"
|
||||
#include "storage.h"
|
||||
#include "clocks.h"
|
||||
#include "psram.h"
|
||||
|
||||
// Number of iterations for KDF
|
||||
#define KDF_ITER_WORDS 12
|
||||
@ -1187,7 +1188,7 @@ pin_firmware_greenlight(pinAttempt_t *args)
|
||||
|
||||
// step 1: calc the value to use
|
||||
uint8_t fw_check[32], world_check[32];
|
||||
checksum_flash(fw_check, world_check);
|
||||
checksum_flash(fw_check, world_check, 0);
|
||||
|
||||
// step 2: write it out to chip.
|
||||
if(warmup_ae()) return EPIN_I_AM_BRICK;
|
||||
@ -1215,5 +1216,88 @@ pin_firmware_greenlight(pinAttempt_t *args)
|
||||
return 0;
|
||||
}
|
||||
|
||||
// pin_firmware_upgrade()
|
||||
//
|
||||
// Update the system firmware via file in PSRAM. Arrange for
|
||||
// light to stay green through out process.
|
||||
//
|
||||
int
|
||||
pin_firmware_upgrade(pinAttempt_t *args)
|
||||
{
|
||||
// Validate args and signature
|
||||
int rv = _validate_attempt(args, false);
|
||||
if(rv) return rv;
|
||||
|
||||
if((args->state_flags & PA_SUCCESSFUL) != PA_SUCCESSFUL) {
|
||||
// must come here with a successful PIN login
|
||||
return EPIN_WRONG_SUCCESS;
|
||||
}
|
||||
|
||||
if(args->change_flags != CHANGE_FIRMWARE) {
|
||||
return EPIN_BAD_REQUEST;
|
||||
}
|
||||
|
||||
// expecting start/length relative to psram start
|
||||
uint32_t *about = (uint32_t *)args->secret;
|
||||
uint32_t start = about[0];
|
||||
uint32_t len = about[1];
|
||||
|
||||
if(len < 32768) return EPIN_RANGE_ERR;
|
||||
if(len > 2<<20) return EPIN_RANGE_ERR;
|
||||
if(start+len > PSRAM_SIZE) return EPIN_RANGE_ERR;
|
||||
|
||||
const uint8_t *data = (const uint8_t *)PSRAM_BASE+start;
|
||||
|
||||
// verify a firmware image that's in RAM, and calc its digest
|
||||
// - also applies watermark policy, etc
|
||||
uint8_t world_check[32];
|
||||
bool ok = verify_firmware_in_ram(data, len, world_check);
|
||||
if(!ok) {
|
||||
return EPIN_AUTH_FAIL;
|
||||
}
|
||||
|
||||
// load existing PIN's hash
|
||||
uint8_t digest[32];
|
||||
pin_cache_restore(args, digest);
|
||||
|
||||
// step 1: calc the value to use, see above
|
||||
|
||||
// step 2: write it out to chip.
|
||||
if(warmup_ae()) return EPIN_I_AM_BRICK;
|
||||
|
||||
// under duress, we can't fake this, but we go through the motions,
|
||||
bool is_duress = get_is_duress(args);
|
||||
if(!is_duress) {
|
||||
rv = ae_encrypted_write(KEYNUM_firmware, KEYNUM_main_pin, digest, world_check, 32);
|
||||
|
||||
if(rv) {
|
||||
ae_reset_chip();
|
||||
|
||||
return EPIN_AE_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
// turn on light? maybe not idk
|
||||
rv = ae_set_gpio_secure(world_check);
|
||||
if(rv) {
|
||||
ae_reset_chip();
|
||||
|
||||
return EPIN_AE_FAIL;
|
||||
}
|
||||
|
||||
// -- point of no return --
|
||||
|
||||
// TODO backup to SPI flash??
|
||||
// TODO backup to SPI flash??
|
||||
// TODO backup to SPI flash??
|
||||
|
||||
// burn it, shows progress
|
||||
psram_do_upgrade(data, len);
|
||||
|
||||
// done
|
||||
NVIC_SystemReset();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// EOF
|
||||
|
||||
@ -28,8 +28,9 @@
|
||||
#define CHANGE_SECRET 0x008
|
||||
#define CHANGE_DURESS_SECRET 0x010
|
||||
#define CHANGE_SECONDARY_WALLET_PIN 0x020 // when used from main wallet only (obsolete)
|
||||
#define CHANGE_FIRMWARE 0x040 // when providing firmware via PSRAM
|
||||
#define CHANGE_LS_OFFSET 0xf00 // v2: which 32-byte part of long-secret to affect
|
||||
#define CHANGE__MASK 0xf3f
|
||||
#define CHANGE__MASK 0xf7f
|
||||
|
||||
// Magic value and/or version number.
|
||||
#define PA_MAGIC_V1 0x2eaf6311 // before v3.0.0 of main firmware (508a, mk1/2)
|
||||
@ -115,4 +116,7 @@ int pin_prefix_words(const char *pin_prefix, int prefix_len, uint32_t *result);
|
||||
// Read/write the long secret. 32 bytes at a time.
|
||||
int pin_long_secret(pinAttempt_t *args);
|
||||
|
||||
// Start firmware upgrade using data in PSRAM.
|
||||
int pin_firmware_upgrade(pinAttempt_t *args);
|
||||
|
||||
// EOF
|
||||
|
||||
@ -2,32 +2,45 @@
|
||||
* (c) Copyright 2021 by Coinkite Inc. This file is covered by license found in COPYING-CC.
|
||||
*
|
||||
* Setup and talk with the ESP-PSRAM64H chip, new on Mk4.
|
||||
* See stm32l4xx_hal_ospi.h
|
||||
*
|
||||
* CAUTION: All writes must be word aligned.
|
||||
*
|
||||
* CAUTION: All writes must be word aligned. Unaligned read okay.
|
||||
*
|
||||
*/
|
||||
#include "psram.h"
|
||||
#include "oled.h"
|
||||
#include "clocks.h"
|
||||
#include "sigheader.h"
|
||||
#include "ae.h"
|
||||
#include "ae_config.h"
|
||||
#include "assets/screens.h"
|
||||
#include <string.h>
|
||||
#include "delay.h"
|
||||
#include "rng.h"
|
||||
#include "storage.h"
|
||||
#include "sigheader.h"
|
||||
#include "stm32l4xx_hal.h"
|
||||
#include "verify.h"
|
||||
#include "console.h"
|
||||
#include "faster_sha256.h"
|
||||
#include "misc.h"
|
||||
|
||||
#undef INCL_SELFTEST
|
||||
|
||||
uint8_t psram_chip_eid[8];
|
||||
|
||||
#ifdef INCL_SELFTEST
|
||||
static void psram_memtest(bool simple);
|
||||
#endif
|
||||
|
||||
// Stash some data in PSRAM to survive brief power outages
|
||||
#define RECHDR_POS (recovery_header_t *)(PSRAM_BASE + PSRAM_SIZE - 2048)
|
||||
#define RECHDR_MAGIC1 0xdbcc8350
|
||||
#define RECHDR_MAGIC2 0xbafcfba3
|
||||
typedef struct {
|
||||
uint32_t magic1;
|
||||
const uint8_t *start;
|
||||
uint32_t size;
|
||||
uint32_t magic2;
|
||||
} recovery_header_t;
|
||||
|
||||
// psram_send_byte()
|
||||
//
|
||||
void
|
||||
@ -118,6 +131,7 @@ psram_setup(void)
|
||||
|
||||
// Read Electronic ID
|
||||
// - length not clear from datasheet, but repeats after 8 bytes
|
||||
uint8_t psram_chip_eid[8];
|
||||
|
||||
{ OSPI_RegularCmdTypeDef cmd = {
|
||||
.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG,
|
||||
@ -140,10 +154,11 @@ psram_setup(void)
|
||||
if(rv != HAL_OK) goto fail;
|
||||
}
|
||||
|
||||
puts2("PSRAM EID: ");
|
||||
hex_dump(psram_chip_eid, sizeof(psram_chip_eid));
|
||||
//puts2("PSRAM EID: ");
|
||||
//hex_dump(psram_chip_eid, sizeof(psram_chip_eid));
|
||||
ASSERT(psram_chip_eid[0] == 0x0d);
|
||||
ASSERT(psram_chip_eid[1] == 0x5d);
|
||||
// .. other bits seem pretty similar between devices, they don't claim they are UUID
|
||||
|
||||
// Put into Quad mode
|
||||
psram_send_byte(&qh, 0x35, false); // 0x35 = Enter Quad Mode
|
||||
@ -234,6 +249,106 @@ psram_wipe(void)
|
||||
puts("done");
|
||||
}
|
||||
|
||||
// recover_from_psram()
|
||||
//
|
||||
// Try to recover from interrupt PSRAM-based firmware upgrade.
|
||||
//
|
||||
bool
|
||||
psram_recover_firmware(void)
|
||||
{
|
||||
volatile recovery_header_t *h = RECHDR_POS;
|
||||
|
||||
// Check header is valid.
|
||||
if( (h->magic1 != RECHDR_MAGIC1)
|
||||
|| (h->magic2 != RECHDR_MAGIC2)
|
||||
|| ((uint32_t)h->start < PSRAM_BASE)
|
||||
|| ((uint32_t)h->start >= PSRAM_BASE+(PSRAM_SIZE/2))
|
||||
|| (h->size > FW_MAX_LENGTH_MK4)
|
||||
|| (h->size < FW_MIN_LENGTH)
|
||||
) {
|
||||
puts("PSR: nada");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Re-verify bytes and factory signature; will catch any bitrot in our
|
||||
// PSRAM copy of firmware
|
||||
uint8_t world_check[32];
|
||||
bool ok = verify_firmware_in_ram(h->start, h->size, world_check);
|
||||
|
||||
if(!ok) {
|
||||
puts("PSR: !check");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check we have the **right** firmware, based on the world check sum
|
||||
// but don't set the light at this point.
|
||||
// - this includes check over bootrom (ourselves)
|
||||
ae_setup();
|
||||
ae_pair_unlock();
|
||||
if(ae_checkmac_hard(KEYNUM_firmware, world_check) != 0) {
|
||||
puts("PSR: version");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Re-do the upgrade.
|
||||
psram_do_upgrade(h->start, h->size);
|
||||
|
||||
// done
|
||||
NVIC_SystemReset();
|
||||
|
||||
// not-reached
|
||||
return true;
|
||||
}
|
||||
|
||||
// psram_do_upgrade()
|
||||
//
|
||||
// Copy from PSRAM to real flash, at final executable location.
|
||||
//
|
||||
// NOTE: incoming start address is typically not aligned.
|
||||
//
|
||||
void
|
||||
psram_do_upgrade(const uint8_t *start, uint32_t size)
|
||||
{
|
||||
ASSERT(size >= FW_MIN_LENGTH);
|
||||
|
||||
// In case of reset/crash, we can recover, so save
|
||||
// what we need for that -- yes, we will re-verify signatures
|
||||
volatile recovery_header_t *h = RECHDR_POS;
|
||||
h->start = start;
|
||||
h->size = size;
|
||||
h->magic1 = RECHDR_MAGIC1;
|
||||
h->magic2 = RECHDR_MAGIC2;
|
||||
|
||||
flash_setup0();
|
||||
flash_unlock();
|
||||
|
||||
int rv;
|
||||
|
||||
// one uint64_t at a time = 8 bytes
|
||||
uint64_t tmp;
|
||||
for(uint32_t pos=0; pos < size; pos += 8) {
|
||||
uint32_t dest = FIRMWARE_START+pos;
|
||||
|
||||
if(dest % (4*FLASH_PAGE_SIZE) == 0) {
|
||||
// show some progress
|
||||
oled_show_progress(screen_upgrading, pos*100/size);
|
||||
}
|
||||
|
||||
if(dest % FLASH_PAGE_SIZE == 0) {
|
||||
// page erase as we go
|
||||
rv = flash_page_erase(dest);
|
||||
ASSERT(rv == 0);
|
||||
}
|
||||
|
||||
memcpy(&tmp, start+pos, 8);
|
||||
rv = flash_burn(dest, tmp);
|
||||
ASSERT(rv == 0);
|
||||
}
|
||||
|
||||
flash_lock();
|
||||
}
|
||||
|
||||
|
||||
#ifdef INCL_SELFTEST
|
||||
// psram_memtest()
|
||||
//
|
||||
@ -283,3 +398,4 @@ psram_memtest(bool simple)
|
||||
#endif
|
||||
|
||||
// EOF
|
||||
|
||||
|
||||
@ -8,11 +8,12 @@
|
||||
#define PSRAM_BASE 0x90000000
|
||||
#define PSRAM_SIZE 0x00800000
|
||||
|
||||
// 8 bytes of unique data from chip
|
||||
extern uint8_t psram_chip_eid[8];
|
||||
|
||||
extern void psram_setup(void);
|
||||
|
||||
extern void psram_wipe(void);
|
||||
|
||||
bool psram_recover_firmware(void);
|
||||
|
||||
void psram_do_upgrade(const uint8_t *start, uint32_t size);
|
||||
|
||||
// EOF
|
||||
|
||||
114
stm32/mk4-bootloader/sdcard.c
Normal file
114
stm32/mk4-bootloader/sdcard.c
Normal file
@ -0,0 +1,114 @@
|
||||
/*
|
||||
* (c) Copyright 2021 by Coinkite Inc. This file is covered by license found in COPYING-CC.
|
||||
*
|
||||
* Setup and read from the SD Card. Used in recovery mode only.
|
||||
*
|
||||
*/
|
||||
#include "oled.h"
|
||||
#include "clocks.h"
|
||||
#include "sigheader.h"
|
||||
#include "assets/screens.h"
|
||||
#include <string.h>
|
||||
#include "delay.h"
|
||||
#include "rng.h"
|
||||
#include "storage.h"
|
||||
#include "sigheader.h"
|
||||
#include "stm32l4xx_hal.h"
|
||||
#include "verify.h"
|
||||
#include "console.h"
|
||||
#include "misc.h"
|
||||
#include "sdcard.h"
|
||||
#include "psram.h"
|
||||
|
||||
SD_HandleTypeDef hsd;
|
||||
|
||||
// sdcard_setup()
|
||||
//
|
||||
void
|
||||
sdcard_setup(void)
|
||||
{
|
||||
// pinout setup
|
||||
|
||||
__HAL_RCC_SDMMC1_CLK_ENABLE();
|
||||
|
||||
// Configure pins: Port C: C8-C13, PD2=CMD
|
||||
// - C7 (light), and C13 (detect) setup in gpio_setup
|
||||
{ GPIO_InitTypeDef setup = {
|
||||
.Pin = GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12,
|
||||
.Mode = GPIO_MODE_AF_PP, // not sure
|
||||
.Pull = GPIO_PULLUP,
|
||||
.Speed = GPIO_SPEED_FREQ_VERY_HIGH,
|
||||
.Alternate = GPIO_AF12_SDMMC1,
|
||||
};
|
||||
HAL_GPIO_Init(GPIOC, &setup);
|
||||
}
|
||||
|
||||
// PD2 = CMD
|
||||
{ GPIO_InitTypeDef setup = {
|
||||
.Pin = GPIO_PIN_2,
|
||||
.Mode = GPIO_MODE_AF_PP, // not sure
|
||||
.Pull = GPIO_PULLUP,
|
||||
.Speed = GPIO_SPEED_FREQ_VERY_HIGH,
|
||||
.Alternate = GPIO_AF12_SDMMC1,
|
||||
};
|
||||
HAL_GPIO_Init(GPIOD, &setup);
|
||||
}
|
||||
|
||||
// reset module
|
||||
__HAL_RCC_SDMMC1_FORCE_RESET();
|
||||
__HAL_RCC_SDMMC1_RELEASE_RESET();
|
||||
|
||||
sdcard_probe();
|
||||
}
|
||||
|
||||
bool
|
||||
sdcard_probe(void)
|
||||
{
|
||||
memset(&hsd, 0, sizeof(SD_HandleTypeDef));
|
||||
|
||||
puts2("SDCard: ");
|
||||
|
||||
hsd.Instance = SDMMC1;
|
||||
hsd.Init.ClockEdge = SDMMC_CLOCK_EDGE_RISING;
|
||||
hsd.Init.ClockPowerSave = SDMMC_CLOCK_POWER_SAVE_ENABLE;
|
||||
hsd.Init.BusWide = SDMMC_BUS_WIDE_1B;
|
||||
hsd.Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;
|
||||
hsd.Init.ClockDiv = SDMMC_TRANSFER_CLK_DIV;
|
||||
|
||||
int rv = HAL_SD_Init(&hsd);
|
||||
if(rv != HAL_OK) {
|
||||
puts("init fail");
|
||||
return false;
|
||||
}
|
||||
|
||||
// configure the SD bus width for 4-bit wide operation
|
||||
rv = HAL_SD_ConfigWideBusOperation(&hsd, SDMMC_BUS_WIDE_4B);
|
||||
if(rv != HAL_OK) {
|
||||
puts("wide");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
uint8_t blk[512];
|
||||
rv = HAL_SD_ReadBlocks(&hsd, blk, 0, 1, 60000);
|
||||
if(rv != HAL_OK) {
|
||||
puts("read fail");
|
||||
return false;
|
||||
}
|
||||
|
||||
puts("ok");
|
||||
hex_dump(blk, 512);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// sdcard_is_inserted()
|
||||
//
|
||||
bool
|
||||
sdcard_is_inserted(void)
|
||||
{
|
||||
return !!HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13);
|
||||
}
|
||||
|
||||
// EOF
|
||||
|
||||
7
stm32/mk4-bootloader/sdcard.h
Normal file
7
stm32/mk4-bootloader/sdcard.h
Normal file
@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
void sdcard_setup(void);
|
||||
|
||||
bool sdcard_is_inserted(void);
|
||||
|
||||
bool sdcard_probe(void);
|
||||
@ -336,6 +336,7 @@ sf_calc_checksum(const coldcardFirmwareHeader_t *hdr, uint8_t fw_digest[32])
|
||||
sha256_final(&ctx, fw_digest);
|
||||
}
|
||||
|
||||
#if 0
|
||||
// sf_firmware_upgrade()
|
||||
//
|
||||
// maybe upgrade to a firmware image found in sflash
|
||||
@ -355,7 +356,6 @@ sf_firmware_upgrade(void)
|
||||
|
||||
if(!verify_header(&hdr)) {
|
||||
// something wrong with it. might be noise, blank or otherwise. Not an error.
|
||||
puts("SPI flash: nope");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -432,5 +432,6 @@ puts("SPI flash: nope");
|
||||
// Tell python, ultimately, that it worked.
|
||||
shared_bootflags |= RBF_FRESH_VERSION;
|
||||
}
|
||||
#endif
|
||||
|
||||
// EOF
|
||||
|
||||
@ -75,7 +75,7 @@
|
||||
#define HAL_RNG_MODULE_ENABLED
|
||||
//#define HAL_RTC_MODULE_ENABLED
|
||||
//#define HAL_SAI_MODULE_ENABLED
|
||||
//#define HAL_SD_MODULE_ENABLED
|
||||
#define HAL_SD_MODULE_ENABLED
|
||||
//#define HAL_SMARTCARD_MODULE_ENABLED
|
||||
//#define HAL_SMBUS_MODULE_ENABLED
|
||||
#define HAL_SPI_MODULE_ENABLED
|
||||
|
||||
@ -311,8 +311,10 @@ static uint32_t SD_WideBus_Enable (SD_HandleTypeDef *hsd);
|
||||
static uint32_t SD_WideBus_Disable(SD_HandleTypeDef *hsd);
|
||||
static uint32_t SD_FindSCR (SD_HandleTypeDef *hsd, uint32_t *pSCR);
|
||||
static void SD_PowerOFF (SD_HandleTypeDef *hsd);
|
||||
#if 0
|
||||
static void SD_Write_IT (SD_HandleTypeDef *hsd);
|
||||
static void SD_Read_IT (SD_HandleTypeDef *hsd);
|
||||
#endif
|
||||
#if !defined(STM32L4P5xx) && !defined(STM32L4Q5xx) && !defined(STM32L4R5xx) && !defined(STM32L4R7xx) && !defined(STM32L4R9xx) && !defined(STM32L4S5xx) && !defined(STM32L4S7xx) && !defined(STM32L4S9xx)
|
||||
static void SD_DMATransmitCplt(DMA_HandleTypeDef *hdma);
|
||||
static void SD_DMAReceiveCplt (DMA_HandleTypeDef *hdma);
|
||||
@ -1693,6 +1695,7 @@ HAL_StatusTypeDef HAL_SD_Erase(SD_HandleTypeDef *hsd, uint32_t BlockStartAdd, ui
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* @brief This function handles SD card interrupt request.
|
||||
* @param hsd Pointer to SD handle
|
||||
@ -2001,6 +2004,7 @@ void HAL_SD_IRQHandler(SD_HandleTypeDef *hsd)
|
||||
/* Nothing to do */
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief return the SD state
|
||||
@ -4018,6 +4022,7 @@ static uint32_t SD_FindSCR(SD_HandleTypeDef *hsd, uint32_t *pSCR)
|
||||
return HAL_SD_ERROR_NONE;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* @brief Wrap up reading in non-blocking mode.
|
||||
* @param hsd pointer to a SD_HandleTypeDef structure that contains
|
||||
@ -4056,7 +4061,9 @@ static void SD_Read_IT(SD_HandleTypeDef *hsd)
|
||||
hsd->RxXferSize = dataremaining;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* @brief Wrap up writing in non-blocking mode.
|
||||
* @param hsd pointer to a SD_HandleTypeDef structure that contains
|
||||
@ -4095,6 +4102,7 @@ static void SD_Write_IT(SD_HandleTypeDef *hsd)
|
||||
hsd->TxXferSize = dataremaining;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(STM32L4P5xx) || defined(STM32L4Q5xx) || defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx)
|
||||
/**
|
||||
|
||||
1665
stm32/mk4-bootloader/stm32l4xx_ll_sdmmc.c
Normal file
1665
stm32/mk4-bootloader/stm32l4xx_ll_sdmmc.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -21,7 +21,16 @@
|
||||
#include "stm32l4xx_hal.h"
|
||||
#include "constant_time.h"
|
||||
|
||||
const uint32_t num_pages_locked = ((BL_FLASH_SIZE + BL_NVROM_SIZE) / 0x800)-1; // == 15
|
||||
#if defined (STM32L4P5xx) || defined (STM32L4Q5xx) || defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx)
|
||||
#define FLASH_NB_DOUBLE_WORDS_IN_ROW 64
|
||||
#else
|
||||
#define FLASH_NB_DOUBLE_WORDS_IN_ROW 32
|
||||
#endif
|
||||
|
||||
// Number of flash pages to write-protect (ie. our size in flash pages)
|
||||
// - written into FLASH->WRP1AR
|
||||
// - once done, can't change bootrom via DFU (no error given, but doesn't change)
|
||||
const uint32_t num_pages_locked = ((BL_FLASH_SIZE + BL_NVROM_SIZE) / FLASH_PAGE_SIZE)-1; // == 15
|
||||
|
||||
// flash_setup0()
|
||||
//
|
||||
@ -190,6 +199,55 @@ flash_burn(uint32_t address, uint64_t val)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
// flash_burn_fast()
|
||||
//
|
||||
// My simplified version of FLASH_Program_Fast()
|
||||
//
|
||||
// NOTES:
|
||||
// - this function **AND** everything it calls, must be in RAM
|
||||
// - interrupts are already off here (entire bootloader)
|
||||
// - return non-zero on failure; don't try to handle anything
|
||||
// - needs 128 bytes
|
||||
// - PROBLEM: Requires bank erase, and we can't do that in any case.
|
||||
//
|
||||
__attribute__((section(".ramfunc")))
|
||||
__attribute__((noinline))
|
||||
int
|
||||
flash_burn_fast(uint32_t address, const uint32_t values[2*FLASH_NB_DOUBLE_WORDS_IN_ROW])
|
||||
{
|
||||
uint32_t rv;
|
||||
|
||||
// just in case?
|
||||
_flash_wait_done();
|
||||
|
||||
// clear any and all errors
|
||||
FLASH->SR = FLASH->SR & 0xffff;
|
||||
|
||||
// disable data cache
|
||||
__HAL_FLASH_DATA_CACHE_DISABLE();
|
||||
|
||||
// Set FSTPG bit
|
||||
SET_BIT(FLASH->CR, FLASH_CR_FSTPG);
|
||||
|
||||
for(int i=0; i<2*FLASH_NB_DOUBLE_WORDS_IN_ROW; i++, address++) {
|
||||
*(__IO uint32_t *)(address) = values[i];
|
||||
}
|
||||
|
||||
rv = _flash_wait_done();
|
||||
if(rv) return rv;
|
||||
|
||||
// If the program operation is completed, disable the FSTPG Bit
|
||||
CLEAR_BIT(FLASH->CR, FLASH_CR_FSTPG);
|
||||
|
||||
// Flush the caches to be sure of data consistency, and reenable.
|
||||
__HAL_FLASH_DATA_CACHE_RESET();
|
||||
__HAL_FLASH_DATA_CACHE_ENABLE();
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
// flash_page_erase()
|
||||
//
|
||||
// See HAL_FLASHEx_Erase(FLASH_EraseInitTypeDef *pEraseInit, uint32_t *PageError)
|
||||
@ -199,7 +257,7 @@ flash_burn(uint32_t address, uint64_t val)
|
||||
int
|
||||
flash_page_erase(uint32_t address)
|
||||
{
|
||||
uint32_t page_num = (address & 0x7ffffff) / FLASH_PAGE_SIZE; // 2k pages
|
||||
uint32_t page_num = (address & 0x7ffffff) / FLASH_PAGE_SIZE;
|
||||
|
||||
// protect ourselves!
|
||||
if(page_num < ((BL_FLASH_SIZE + BL_NVROM_SIZE) / FLASH_PAGE_SIZE)) {
|
||||
@ -407,9 +465,13 @@ flash_setup(void)
|
||||
STATIC_ASSERT(sizeof(rom_secrets_t) <= 2048);
|
||||
|
||||
// see if we have picked a pairing secret yet.
|
||||
// NOTE: critical section for glitching (at least in past versions)
|
||||
// - check_all.. functions have a rng_delay in them already
|
||||
rng_delay();
|
||||
bool blank_ps = check_all_ones(rom_secrets->pairing_secret, 32);
|
||||
bool blank_xor = check_all_ones(rom_secrets->pairing_secret_xor, 32);
|
||||
bool blank_ae = (~rom_secrets->ae_serial_number[0] == 0);
|
||||
rng_delay();
|
||||
|
||||
if(blank_ps) {
|
||||
// get some good entropy, save it.
|
||||
@ -423,6 +485,7 @@ flash_setup(void)
|
||||
// configure and lock-down the SE
|
||||
int rv = ae_setup_config();
|
||||
|
||||
rng_delay();
|
||||
if(rv) {
|
||||
// Hardware fail speaking to AE chip ... be careful not to brick here.
|
||||
// Do not continue!! We might fix the board, or add missing pullup, etc.
|
||||
@ -432,6 +495,7 @@ flash_setup(void)
|
||||
LOCKUP_FOREVER();
|
||||
}
|
||||
|
||||
rng_delay();
|
||||
if(blank_xor) {
|
||||
// write secret again, complemented, to indicate successful AE programming
|
||||
confirm_pairing_secret();
|
||||
@ -444,6 +508,7 @@ flash_setup(void)
|
||||
LOCKUP_FOREVER();
|
||||
}
|
||||
|
||||
rng_delay();
|
||||
if(!blank_ps && !blank_xor) {
|
||||
// check the XOR value also written: 2 phase commit
|
||||
uint8_t tmp[32];
|
||||
@ -492,7 +557,6 @@ flash_lockdown_hard(uint8_t rdp_level_code)
|
||||
FLASH->WRP2AR = 0xff; // unused.
|
||||
FLASH->WRP2BR = 0xff; // unused.
|
||||
|
||||
#if 0
|
||||
// PCRO = Proprietary Code Read-Out (protection)
|
||||
// - isn't useful to us (doesn't protect data, exec-only code)
|
||||
// - "In case the Level 1 is configured and no PCROP area is defined,
|
||||
@ -500,50 +564,14 @@ flash_lockdown_hard(uint8_t rdp_level_code)
|
||||
// the RDP level is decreased from Level 1 to Level 0)."
|
||||
// - D-bus access blocked, even for code running inside the PCROP area! (AN4758)
|
||||
// So literal values and constant tables and such would need special linking.
|
||||
//
|
||||
FLASH->PCROP1ER = (1<<31); // set PCROP_RDP bit, since maybe we need to?
|
||||
FLASH->PCROP1SR = 0xffff;
|
||||
FLASH->PCROP2ER = (1<<31); // set PCROP_RDP bit, since maybe we need to?
|
||||
FLASH->PCROP2SR = 0xffff;
|
||||
#endif
|
||||
|
||||
// set protection level
|
||||
FLASH->OPTR = 0xffeff800 | rdp_level_code; // select level X, other values as observed
|
||||
uint32_t was = FLASH->OPTR & ~0xff;
|
||||
FLASH->OPTR = was | rdp_level_code; // select level X, other values as observed
|
||||
|
||||
flash_ob_lock(true);
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
// backup_data_get()
|
||||
//
|
||||
uint32_t
|
||||
backup_data_get(int idx)
|
||||
{
|
||||
ASSERT(idx < 32);
|
||||
|
||||
return (&RTC->BKP0R)[idx];
|
||||
}
|
||||
|
||||
// backup_data_set()
|
||||
//
|
||||
void
|
||||
backup_data_set(int idx, uint32_t new_value)
|
||||
{
|
||||
ASSERT(idx < 32);
|
||||
|
||||
// unlock sequence.
|
||||
RTC->WPR = 0xCA;
|
||||
RTC->WPR = 0x53;
|
||||
|
||||
(&RTC->BKP0R)[idx] = new_value;
|
||||
|
||||
// relock (any value)
|
||||
// doesn't seem to work tho? stays unlocked
|
||||
RTC->WPR = 0xff;
|
||||
}
|
||||
#endif
|
||||
|
||||
// record_highwater_version()
|
||||
//
|
||||
int
|
||||
|
||||
@ -48,26 +48,12 @@ static inline bool flash_is_security_level2(void) {
|
||||
return ((FLASH->OPTR & FLASH_OPTR_RDP_Msk) == 0xCC);
|
||||
}
|
||||
|
||||
#if 0
|
||||
// We store some values in the RTC "backup" registers
|
||||
// - these are protected against accidental writes
|
||||
// - not cleared by system reset, full power cycle required
|
||||
// - mpy code could still change, so not secure.
|
||||
// - kinda pointless, but I have no SRAM that isn't wiped at boot
|
||||
// - XXX not working! no clock maybe? Reads as zero.
|
||||
#define IDX_WORD_LOOKUPS_USED 0x0
|
||||
#define IDX_DURESS_USED 0x1
|
||||
|
||||
uint32_t backup_data_get(int idx);
|
||||
void backup_data_set(int idx, uint32_t new_value);
|
||||
#endif
|
||||
|
||||
|
||||
// generial purpose flash functions
|
||||
void flash_setup0(void);
|
||||
void flash_lock(void);
|
||||
void flash_unlock(void);
|
||||
int flash_burn(uint32_t address, uint64_t val);
|
||||
int flash_burn_fast(uint32_t address, const uint32_t values[128]);
|
||||
int flash_page_erase(uint32_t address);
|
||||
|
||||
// write to OTP
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
*/
|
||||
#include "basics.h"
|
||||
#include "verify.h"
|
||||
#include "psram.h"
|
||||
#include "faster_sha256.h"
|
||||
#include "assets/screens.h"
|
||||
#include "oled.h"
|
||||
@ -21,13 +22,14 @@
|
||||
#include "firmware-keys.h"
|
||||
|
||||
// 2 megabyte on mk4
|
||||
#define MAIN_FLASH_SIZE (2<<20)
|
||||
// - less the LFS2 filesystem which contains settings and such that change at runtime normally.
|
||||
#define MAIN_FLASH_SIZE ((2<<20) - (512*1024))
|
||||
|
||||
// actual qty of bytes we check
|
||||
// - minus 64 because the firmware signature is skipped
|
||||
// - 0x400 of OTP area
|
||||
// - plus (0x28) twice for option bytes
|
||||
// - plus complete "system meory" area (boot rom with DFU)
|
||||
// - plus complete "system meory" area (STM boot rom containing DFU code)
|
||||
// - 12 bytes of device serial number
|
||||
#define TOTAL_CHECKSUM_LEN (MAIN_FLASH_SIZE - 64 + 0x400 + (0x28 *2) + 0x7000 + 12)
|
||||
|
||||
@ -56,7 +58,7 @@ checksum_more(SHA256_CTX *ctx, uint32_t *total, const uint8_t *addr, int len)
|
||||
// checksum_flash()
|
||||
//
|
||||
void
|
||||
checksum_flash(uint8_t fw_digest[32], uint8_t world_digest[32])
|
||||
checksum_flash(uint8_t fw_digest[32], uint8_t world_digest[32], uint32_t fw_length)
|
||||
{
|
||||
const uint8_t *start = (const uint8_t *)FIRMWARE_START;
|
||||
|
||||
@ -64,21 +66,29 @@ checksum_flash(uint8_t fw_digest[32], uint8_t world_digest[32])
|
||||
|
||||
SHA256_CTX ctx;
|
||||
uint32_t total_len = 0;
|
||||
uint8_t first[32];
|
||||
|
||||
sha256_init(&ctx);
|
||||
if(fw_length == 0) {
|
||||
uint8_t first[32];
|
||||
sha256_init(&ctx);
|
||||
|
||||
// start of firmware (just after we end) to header
|
||||
checksum_more(&ctx, &total_len, start, FW_HEADER_OFFSET + FW_HEADER_SIZE - 64);
|
||||
// use length from header in flash
|
||||
fw_length = FW_HDR->firmware_length;
|
||||
|
||||
// from after header to end
|
||||
checksum_more(&ctx, &total_len, start + FW_HEADER_OFFSET + FW_HEADER_SIZE,
|
||||
FW_HDR->firmware_length - (FW_HEADER_OFFSET + FW_HEADER_SIZE));
|
||||
// start of firmware (just after we end) to header
|
||||
checksum_more(&ctx, &total_len, start, FW_HEADER_OFFSET + FW_HEADER_SIZE - 64);
|
||||
|
||||
sha256_final(&ctx, first);
|
||||
// from after header to end
|
||||
checksum_more(&ctx, &total_len, start + FW_HEADER_OFFSET + FW_HEADER_SIZE,
|
||||
fw_length - (FW_HEADER_OFFSET + FW_HEADER_SIZE));
|
||||
|
||||
// double SHA256
|
||||
sha256_single(first, sizeof(first), fw_digest);
|
||||
sha256_final(&ctx, first);
|
||||
|
||||
// double SHA256
|
||||
sha256_single(first, sizeof(first), fw_digest);
|
||||
} else {
|
||||
// fw_digest should already be populated by caller
|
||||
total_len = fw_length - 64;
|
||||
}
|
||||
|
||||
// start over, and get the rest of flash. All of it.
|
||||
sha256_init(&ctx);
|
||||
@ -91,7 +101,7 @@ checksum_flash(uint8_t fw_digest[32], uint8_t world_digest[32])
|
||||
checksum_more(&ctx, &total_len, base, start-base);
|
||||
|
||||
// probably-blank area after firmware, and filesystem area
|
||||
const uint8_t *fs = start + FW_HDR->firmware_length;
|
||||
const uint8_t *fs = start + fw_length;
|
||||
const uint8_t *last = base + MAIN_FLASH_SIZE;
|
||||
checksum_more(&ctx, &total_len, fs, last-fs);
|
||||
|
||||
@ -168,19 +178,19 @@ check_is_downgrade(const uint8_t timestamp[8], const char *version)
|
||||
return (memcmp(timestamp, min, 8) < 0);
|
||||
}
|
||||
|
||||
// check_factory_key()
|
||||
// warn_bad_checksum()
|
||||
//
|
||||
void
|
||||
check_factory_key(uint32_t pubkey_num)
|
||||
warn_bad_checksum(void)
|
||||
{
|
||||
if(IS_FACTORY_KEY(pubkey_num)) return;
|
||||
|
||||
// warn the victim/altcoin user/developer
|
||||
// warn the victim about corrupted flash/ident info
|
||||
#if RELEASE
|
||||
const int wait = 100;
|
||||
#else
|
||||
const int wait = 1;
|
||||
const int wait = 10;
|
||||
#endif
|
||||
|
||||
puts("WARN: Bad firmware");
|
||||
|
||||
for(int i=0; i < wait; i++) {
|
||||
oled_show_progress(screen_devmode, (i*100)/wait);
|
||||
@ -220,13 +230,66 @@ verify_signature(const coldcardFirmwareHeader_t *hdr, const uint8_t fw_check[32]
|
||||
hdr->signature, uECC_secp256k1());
|
||||
|
||||
//puts(ok ? "Sig ok" : "Sig fail");
|
||||
rng_delay();
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
// verify_firmware_in_ram()
|
||||
//
|
||||
// Check hdr, and even signature of protential new firmware in PSRAM.
|
||||
// Returns checksum needed for 608
|
||||
//
|
||||
bool
|
||||
verify_firmware_in_ram(const uint8_t *start, uint32_t len, uint8_t world_check[32])
|
||||
{
|
||||
const coldcardFirmwareHeader_t *hdr = (const coldcardFirmwareHeader_t *)
|
||||
(start + FW_HEADER_OFFSET);
|
||||
uint8_t fw_digest[32];
|
||||
|
||||
// check basics like verison, hw compat, etc
|
||||
if(!verify_header(hdr)) goto fail;
|
||||
|
||||
if(check_is_downgrade(hdr->timestamp, (const char *)hdr->version_string)) {
|
||||
puts("downgrade");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rng_delay();
|
||||
|
||||
SHA256_CTX ctx;
|
||||
uint32_t total_len = 0;
|
||||
|
||||
sha256_init(&ctx);
|
||||
|
||||
// start of firmware up to header's signature
|
||||
checksum_more(&ctx, &total_len, start, FW_HEADER_OFFSET + FW_HEADER_SIZE - 64);
|
||||
|
||||
// from after header to end
|
||||
checksum_more(&ctx, &total_len, start + FW_HEADER_OFFSET + FW_HEADER_SIZE,
|
||||
hdr->firmware_length - (FW_HEADER_OFFSET + FW_HEADER_SIZE));
|
||||
|
||||
// double SHA256
|
||||
sha256_final(&ctx, fw_digest);
|
||||
sha256_single(fw_digest, 32, fw_digest);
|
||||
|
||||
rng_delay();
|
||||
|
||||
if(!verify_signature(hdr, fw_digest)) {
|
||||
puts("sig fail");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
checksum_flash(fw_digest, world_check, hdr->firmware_length);
|
||||
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
// verify_firmware()
|
||||
//
|
||||
void
|
||||
bool
|
||||
verify_firmware(void)
|
||||
{
|
||||
STATIC_ASSERT(sizeof(coldcardFirmwareHeader_t) == FW_HEADER_SIZE);
|
||||
@ -241,15 +304,13 @@ verify_firmware(void)
|
||||
|
||||
// measure checksum
|
||||
uint8_t fw_check[32], world_check[32];
|
||||
checksum_flash(fw_check, world_check);
|
||||
checksum_flash(fw_check, world_check, 0);
|
||||
|
||||
rng_delay();
|
||||
|
||||
// Verify the signature
|
||||
// - use pubkey_num to pick a specific key
|
||||
if(!verify_signature(FW_HDR, fw_check)) goto fail;
|
||||
|
||||
rng_delay();
|
||||
|
||||
// Push the hash to the SE which might make the Genuine light green,
|
||||
// but only if we arrived at same hash before. It decides.
|
||||
@ -257,30 +318,27 @@ verify_firmware(void)
|
||||
|
||||
rng_delay();
|
||||
|
||||
#if 0
|
||||
// XXX change this, no more dev key
|
||||
// maybe show big warning if not an "approved" key
|
||||
// show big/slow warning if light is not green
|
||||
if(not_green) {
|
||||
check_factory_key(FW_HDR->pubkey_num);
|
||||
warn_bad_checksum();
|
||||
}
|
||||
#endif
|
||||
|
||||
puts("good firmware");
|
||||
oled_show_progress(screen_verify, 100);
|
||||
|
||||
return;
|
||||
return true;
|
||||
|
||||
fail:
|
||||
puts("corrupt firmware");
|
||||
oled_show(screen_corrupt);
|
||||
enter_dfu();
|
||||
return;
|
||||
return false;
|
||||
|
||||
blank:
|
||||
puts("no firmware");
|
||||
oled_show(screen_dfu);
|
||||
enter_dfu();
|
||||
return;
|
||||
//enter_dfu();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// EOF
|
||||
|
||||
@ -11,11 +11,13 @@
|
||||
// The in-flash header.
|
||||
#define FW_HDR ((coldcardFirmwareHeader_t *)(FIRMWARE_START + FW_HEADER_OFFSET))
|
||||
|
||||
// check we have something valid, and signed, in memory
|
||||
extern void verify_firmware(void);
|
||||
// check we have something valid, and signed, in memory. T if okay
|
||||
bool verify_firmware(void);
|
||||
|
||||
// read and checksum over **all** of flash memory
|
||||
void checksum_flash(uint8_t fw_digest[32], uint8_t world_digest[32]);
|
||||
// - fw_length is length of firmware from it's header
|
||||
// - if fw_length is nonzero, then use incoming fw_digest
|
||||
void checksum_flash(uint8_t fw_digest[32], uint8_t world_digest[32], uint32_t fw_length);
|
||||
|
||||
// do some range/sanity checking on a signed header
|
||||
bool verify_header(const coldcardFirmwareHeader_t *hdr);
|
||||
@ -28,6 +30,9 @@ bool verify_signature(const coldcardFirmwareHeader_t *hdr, const uint8_t fw_chec
|
||||
// check if proposed version is new enough (based on OTP values)
|
||||
bool check_is_downgrade(const uint8_t timestamp[8], const char *version);
|
||||
|
||||
// verify a firmware image that's in RAM, and provide digest needed for 608
|
||||
bool verify_firmware_in_ram(const uint8_t *start, uint32_t len, uint8_t world_check[32]);
|
||||
|
||||
// read what the watermark is, might be all zeros
|
||||
void get_min_version(uint8_t min_version[8]);
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user