You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

473 lines
13 KiB

// SPDX-FileCopyrightText: 2020 Foundation Devices, Inc. <hello@foundationdevices.com>
// SPDX-License-Identifier: GPL-3.0-or-later
//
// SPDX-FileCopyrightText: 2018 Coinkite, Inc. <coldcardwallet.com>
// SPDX-License-Identifier: GPL-3.0-only
//
// (c) Copyright 2018 by Coinkite Inc. This file is part of Coldcard <coldcardwallet.com>
// and is covered by GPLv3 license found in COPYING.
//
//
// flash.c -- manage flash and its sensitive contents.
//
#include <string.h>
#include <errno.h>
#include "utils.h"
#include "pprng.h"
#include "hash.h"
#include "fwheader.h"
#include "se.h"
#include "se-atecc608a.h"
#include "verify.h"
#include "flash.h"
const uint32_t num_pages_locked = ((BL_FLASH_SIZE + BL_NVROM_SIZE) / 0x800) - 1; // == 15
static inline bool is_pairing_secret_programmed(
uint8_t *secret,
size_t len
)
{
uint8_t *ptr = secret;
for(; len; len--, ptr++)
{
if (*ptr != 0xff)
return true;
}
return false;
}
static inline bool is_se_programmed(void)
{
int rc;
uint8_t config[128] = {0};
rc = se_config_read(config);
if (rc < 0)
LOCKUP_FOREVER(); /* Can't talk to the SE */
if ((config[86] != 0x55) && (config[87] != 0x55))
return true;
return false;
}
// See FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE)
// Absolutely MUST be in RAM.
//
__attribute__((section(".ramfunc")))
static inline uint32_t _flash_wait_done(uint32_t bank)
{
uint32_t bsyflag, errorflag;
if (bank == FLASH_BANK_1)
bsyflag = FLASH_FLAG_QW_BANK1;
else
bsyflag = FLASH_FLAG_QW_BANK2;
while(__HAL_FLASH_GET_FLAG(bsyflag)) {
// busy wait
}
/* Get Error Flags */
if (bank == FLASH_BANK_1)
errorflag = FLASH->SR1 & FLASH_FLAG_ALL_ERRORS_BANK1;
else
errorflag = (FLASH->SR2 & FLASH_FLAG_ALL_ERRORS_BANK2) | 0x80000000U;
/* In case of error reported in Flash SR1 or SR2 register */
if ((errorflag & 0x7FFFFFFFU) != 0U)
{
/* Clear error programming flags */
__HAL_FLASH_CLEAR_FLAG(errorflag);
return errorflag;
}
/* Check FLASH End of programming flag */
if (bank == FLASH_BANK_1)
{
if (__HAL_FLASH_GET_FLAG_BANK1(FLASH_FLAG_EOP_BANK1))
{
/* Clear FLASH End of programming flag */
__HAL_FLASH_CLEAR_FLAG_BANK1(FLASH_FLAG_EOP_BANK1);
}
}
else
{
if (__HAL_FLASH_GET_FLAG_BANK2(FLASH_FLAG_EOP_BANK2))
{
/* Clear FLASH End of programming flag */
__HAL_FLASH_CLEAR_FLAG_BANK2(FLASH_FLAG_EOP_BANK2);
}
}
return 0;
}
__attribute__((section(".ramfunc")))
void flash_lock(void)
{
// see HAL_FLASH_Lock();
SET_BIT(FLASH->CR1, FLASH_CR_LOCK);
if (READ_BIT(FLASH->CR1, FLASH_CR_LOCK)) {
return; //INCONSISTENT("failed to lock bank 1");
}
SET_BIT(FLASH->CR2, FLASH_CR_LOCK);
if (READ_BIT(FLASH->CR2, FLASH_CR_LOCK)) {
return; //INCONSISTENT("failed to lock bank 2");
}
}
__attribute__((section(".ramfunc")))
void flash_unlock(void)
{
// see HAL_FLASH_Unlock()
if (READ_BIT(FLASH->CR1, FLASH_CR_LOCK)) {
/* Authorize the FLASH Bank1 Registers access */
WRITE_REG(FLASH->KEYR1, FLASH_KEY1);
WRITE_REG(FLASH->KEYR1, FLASH_KEY2);
if(READ_BIT(FLASH->CR1, FLASH_CR_LOCK)) {
return; //INCONSISTENT("failed to unlock bank 1");
}
}
if (READ_BIT(FLASH->CR2, FLASH_CR_LOCK)) {
/* Authorize the FLASH Bank2 Registers access */
WRITE_REG(FLASH->KEYR2, FLASH_KEY1);
WRITE_REG(FLASH->KEYR2, FLASH_KEY2);
if(READ_BIT(FLASH->CR2, FLASH_CR_LOCK)) {
return; //INCONSISTENT("failed to unlock bank 2");
}
}
}
int flash_ob_lock(bool lock)
{
if (!lock)
{
/* see HAL_FLASH_OB_Unlock() */
if (READ_BIT(FLASH->OPTCR, FLASH_OPTCR_OPTLOCK) != 0U)
{
/* Authorizes the Option Byte registers programming */
WRITE_REG(FLASH->OPTKEYR, FLASH_OPT_KEY1);
WRITE_REG(FLASH->OPTKEYR, FLASH_OPT_KEY2);
/* Verify that the Option Bytes are unlocked */
if (READ_BIT(FLASH->OPTCR, FLASH_OPTCR_OPTLOCK) != 0U)
{
return -1;
}
}
}
else
{
/* see HAL_FLASH_OB_Lock() */
/* Set the OPTLOCK Bit to lock the FLASH Option Byte Registers access */
SET_BIT(FLASH->OPTCR, FLASH_OPTCR_OPTLOCK);
/* Verify that the Option Bytes are locked */
if (READ_BIT(FLASH->OPTCR, FLASH_OPTCR_OPTLOCK) == 0U)
{
return -1;
}
}
return 0;
}
// See HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, ...)
//
// 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
//
__attribute__((section(".ramfunc")))
int flash_burn(uint32_t flash_address, uint32_t data_address)
{
uint32_t bank;
uint32_t rv;
__IO uint32_t *dest_addr = (__IO uint32_t *)flash_address;
__IO uint32_t *src_addr = (__IO uint32_t*)data_address;
uint8_t row_index = FLASH_NB_32BITWORD_IN_FLASHWORD;
if (IS_FLASH_PROGRAM_ADDRESS_BANK1(flash_address))
bank = FLASH_BANK_1;
else if (IS_FLASH_PROGRAM_ADDRESS_BANK2(flash_address))
bank = FLASH_BANK_2;
else
return -1;
_flash_wait_done(bank);
/* Set PG bit */
if (bank == FLASH_BANK_1)
SET_BIT(FLASH->CR1, FLASH_CR_PG);
else
SET_BIT(FLASH->CR2, FLASH_CR_PG);
__ISB();
__DSB();
/* Program the 256 bits flash word */
do
{
*dest_addr = *src_addr;
dest_addr++;
src_addr++;
row_index--;
} while (row_index != 0U);
__ISB();
__DSB();
rv = _flash_wait_done(bank);
/* If the program operation is completed, disable the PG*/
if (bank == FLASH_BANK_1)
CLEAR_BIT(FLASH->CR1, FLASH_CR_PG);
else
CLEAR_BIT(FLASH->CR2, FLASH_CR_PG);
return rv;
}
// See HAL_FLASHEx_Erase(FLASH_EraseInitTypeDef *pEraseInit, uint32_t *PageError)
//
__attribute__((section(".ramfunc")))
int flash_sector_erase(uint32_t address)
{
uint32_t sector;
if (IS_FLASH_PROGRAM_ADDRESS_BANK1(address)) {
sector = (address - FLASH_BANK1_BASE) / FLASH_SECTOR_SIZE;
/* Protect against erasing sector 0 (contains the bootloader) */
if (sector == 0)
return -1;
_flash_wait_done(FLASH_BANK_1);
/* reset Program/erase VoltageRange for Bank1 */
FLASH->CR1 &= ~(FLASH_CR_PSIZE | FLASH_CR_SNB);
FLASH->CR1 |= (FLASH_CR_SER | FLASH_VOLTAGE_RANGE_3 | (sector << FLASH_CR_SNB_Pos));
FLASH->CR1 |= FLASH_CR_START;
_flash_wait_done(FLASH_BANK_1);
/* The erase operation is completed, disable the SER Bit */
FLASH->CR1 &= (~(FLASH_CR_SER | FLASH_CR_SNB));
} else if (IS_FLASH_PROGRAM_ADDRESS_BANK2(address)) {
sector = (address - FLASH_BANK2_BASE) / FLASH_SECTOR_SIZE;
_flash_wait_done(FLASH_BANK_2);
/* reset Program/erase VoltageRange for Bank2 */
FLASH->CR2 &= ~(FLASH_CR_PSIZE | FLASH_CR_SNB);
FLASH->CR2 |= (FLASH_CR_SER | FLASH_VOLTAGE_RANGE_3 | (sector << FLASH_CR_SNB_Pos));
FLASH->CR2 |= FLASH_CR_START;
_flash_wait_done(FLASH_BANK_2);
/* The erase operation is completed, disable the SER Bit */
FLASH->CR2 &= (~(FLASH_CR_SER | FLASH_CR_SNB));
}
else
return -1;
return 0;
}
#define JUST_PROGRAM_ROM_SECRETS
#ifdef JUST_PROGRAM_ROM_SECRETS
__attribute__((section(".ramfunc")))
static int flash_rom_secrets(rom_secrets_t *secrets)
{
__IO uint32_t *src_secrets = (__IO uint32_t *)secrets;
__IO uint32_t *flash_secrets = (__IO uint32_t *)(BL_NVROM_BASE);
uint32_t flash_word_len = sizeof(uint32_t) * FLASH_NB_32BITWORD_IN_FLASHWORD;
uint32_t pos = (uint32_t)src_secrets;
uint32_t dest = (uint32_t)flash_secrets;
int i;
flash_unlock();
for (i = 0; i < sizeof(rom_secrets_t); i += flash_word_len, pos += flash_word_len, dest += flash_word_len) {
if (flash_burn(dest, pos)) {
return -1;
}
}
flash_lock();
return 0;
}
#else
__attribute__((section(".ramfunc")))
static int flash_bootloader(rom_secrets_t *secrets)
{
__IO uint32_t *sector0 = (__IO uint32_t *)BL_FLASH_BASE;
__IO uint32_t *sector0_end = (__IO uint32_t *)(BL_FLASH_BASE + BL_FLASH_SIZE);
__IO uint32_t *sram = (__IO uint32_t *)D1_AXISRAM_BASE;
__IO uint32_t *src_secrets = (__IO uint32_t *)secrets;
__IO uint32_t *src_secrets_end = (__IO uint32_t *)((uint32_t)secrets + sizeof(rom_secrets_t));
__IO uint32_t *sram_secrets = (__IO uint32_t *)(D1_AXISRAM_BASE + BL_FLASH_SIZE - BL_NVROM_SIZE);
uint32_t flash_word_len = sizeof(uint32_t) * FLASH_NB_32BITWORD_IN_FLASHWORD;
uint32_t pos = (uint32_t)sram;
uint32_t dest = (uint32_t)sector0;
int i;
/* Copy sector 0 to SRAM */
while (sector0 < sector0_end)
{
*sram = *sector0;
++sram;
++sector0;
}
/* Copy the ROM secrets to SRAM */
while (src_secrets < src_secrets_end)
{
*sram_secrets = *src_secrets;
++sram_secrets;
++src_secrets;
}
flash_unlock();
for (i = 0; i < BL_FLASH_SIZE; i += flash_word_len, pos += flash_word_len, dest += flash_word_len) {
if (flash_burn(dest, pos)) {
return -1;
}
}
flash_lock();
return 0;
}
#endif /* JUST_PROGRAM_ROM_SECRETS */
static void pick_pairing_secret(rom_secrets_t *local)
{
uint32_t secret[8];
int i;
uint32_t *pos;
uint16_t len;
for (i = 0; i < 8; i++) {
secret[i] = rng_sample();
}
// enforce policy that first word is not all ones (so it never
// looks like unprogrammed flash).
while(secret[0] == 0xff) {
secret[0] = rng_sample();
}
memcpy(local->pairing_secret, secret, sizeof(secret));
pos = (uint32_t *)local->otp_key;
len = sizeof(local->otp_key);
for (i = 0; i < len; i += sizeof(uint32_t), ++pos) {
*pos = rng_sample();
}
pos = (uint32_t *)&local->otp_key_long;
len = sizeof(local->otp_key_long);
for (i = 0; i < len; i += sizeof(uint32_t), ++pos) {
*pos = rng_sample();
}
pos = (uint32_t *)&local->hash_cache_secret;
len = sizeof(local->hash_cache_secret);
for (i = 0; i < len; i += sizeof(uint32_t), ++pos) {
*pos = rng_sample();
}
}
void flash_first_boot(void)
{
int rc;
uint8_t fw_hash[HASH_LEN];
uint8_t board_hash[HASH_LEN];
passport_firmware_header_t *fwhdr = (passport_firmware_header_t *)FW_HDR;
uint8_t *fwptr = (uint8_t *)fwhdr + FW_HEADER_SIZE;
bool secrets_already_programmed;
rom_secrets_t local_secrets = {0};
if (sizeof(rom_secrets_t) > 2048)
LOCKUP_FOREVER();
if (!verify_header(fwhdr))
LOCKUP_FOREVER();
hash_fw(&fwhdr->info, fwptr, fwhdr->info.fwlength, fw_hash, sizeof(fw_hash));
if (!verify_signature(fwhdr, fw_hash, sizeof(fw_hash)))
LOCKUP_FOREVER();
secrets_already_programmed = is_pairing_secret_programmed(rom_secrets->pairing_secret,
sizeof(rom_secrets->pairing_secret));
if (secrets_already_programmed)
memcpy(&local_secrets, rom_secrets, sizeof(local_secrets));
else
pick_pairing_secret(&local_secrets);
rc = se_setup_config(&local_secrets);
if (rc != 0)
LOCKUP_FOREVER();
if (!secrets_already_programmed)
{
HAL_SuspendTick();
#ifdef JUST_PROGRAM_ROM_SECRETS
rc = flash_rom_secrets(&local_secrets);
#else
rc = flash_bootloader(&local_secrets);
#endif /* JUST_PROGRAM_ROM_SECRETS */
HAL_ResumeTick();
if (rc < 0)
LOCKUP_FOREVER();
}
#ifdef DEMO
memset(board_hash, 0, sizeof(board_hash));
#else
hash_board(fw_hash, sizeof(fw_hash), board_hash, sizeof(board_hash));
#endif /* DEMO */
rc = se_program_board_hash(board_hash, sizeof(board_hash));
if (rc < 0)
LOCKUP_FOREVER();
flash_lockdown_hard((uint32_t)OB_RDP_LEVEL_2);
}
void flash_lockdown_hard(uint32_t rdp_level)
{
#ifndef FIXME /* Enable once we're almost ready to release and don't
* forget to move the secrets back into 0
*/
return;
#else
flash_ob_lock(false);
MODIFY_REG(FLASH->OPTSR_PRG, FLASH_OPTSR_RDP, rdp_level);
flash_ob_lock(true);
#endif /* FIXME */
}
bool flash_is_programmed(void)
{
if (!is_pairing_secret_programmed(rom_secrets->pairing_secret, sizeof(rom_secrets->pairing_secret)))
return false;
return is_se_programmed();
}