Cleaner flash handling using FLASH_PTR

Use `FLASH_PTR` macro to convert a flash address to a const pointer.
For real hardware it is just a cast, for emulator we subtract the
`FLASH_ORIGIN` and use it as index into the memory mapped flash file.

Make write access to flash with volatile pointers

Also use FLASH_PTR in DebugMemory* for now.  This allows for reading and
writing the flash in the emulator or just crash it by reading outside
the flash...
pull/25/head
Jochen Hoenicke 6 years ago committed by Pavol Rusnak
parent 1fcd512b7f
commit c09590b54d

@ -13,7 +13,7 @@ AS := as
OPTFLAGS ?= -O3
DBGFLAGS ?= -g3 -ggdb3
CPUFLAGS ?= -m32
CPUFLAGS ?=
FPUFLAGS ?=
else
PREFIX ?= arm-none-eabi-

@ -81,19 +81,19 @@ void __attribute__((noreturn)) load_app(int signed_firmware)
// zero out SRAM
memset_reg(_ram_start, _ram_end, 0);
jump_to_firmware((const vector_table_t *) FLASH_APP_START, signed_firmware);
jump_to_firmware((const vector_table_t *) FLASH_PTR(FLASH_APP_START), signed_firmware);
}
bool firmware_present(void)
{
#ifndef APPVER
if (memcmp((const void *)FLASH_META_MAGIC, "TRZR", 4)) { // magic does not match
if (memcmp(FLASH_PTR(FLASH_META_MAGIC), "TRZR", 4)) { // magic does not match
return false;
}
if (*((const uint32_t *)FLASH_META_CODELEN) < 4096) { // firmware reports smaller size than 4kB
if (*((const uint32_t *)FLASH_PTR(FLASH_META_CODELEN)) < 4096) { // firmware reports smaller size than 4kB
return false;
}
if (*((const uint32_t *)FLASH_META_CODELEN) > FLASH_TOTAL_SIZE - (FLASH_APP_START - FLASH_ORIGIN)) { // firmware reports bigger size than flash size
if (*((const uint32_t *)FLASH_PTR(FLASH_META_CODELEN)) > FLASH_TOTAL_SIZE - (FLASH_APP_START - FLASH_ORIGIN)) { // firmware reports bigger size than flash size
return false;
}
#endif

@ -302,7 +302,7 @@ static void erase_metadata_sectors(void)
static void backup_metadata(uint8_t *backup)
{
memcpy(backup, (void *)FLASH_META_START, FLASH_META_LEN);
memcpy(backup, FLASH_PTR(FLASH_META_START), FLASH_META_LEN);
}
static void restore_metadata(const uint8_t *backup)
@ -434,7 +434,7 @@ static void hid_rx_callback(usbd_device *dev, uint8_t ep)
// compute hash of written test pattern
uint8_t hash[32];
sha256_Raw((unsigned char *)FLASH_META_START, FLASH_META_LEN, hash);
sha256_Raw(FLASH_PTR(FLASH_META_START), FLASH_META_LEN, hash);
// restore metadata from backup
erase_metadata_sectors();
@ -504,7 +504,7 @@ static void hid_rx_callback(usbd_device *dev, uint8_t ep)
// flash status register should show now error and
// the config block should contain only \xff.
uint8_t hash[32];
sha256_Raw((unsigned char *)FLASH_META_START, FLASH_META_LEN, hash);
sha256_Raw(FLASH_PTR(FLASH_META_START), FLASH_META_LEN, hash);
if ((FLASH_SR & (FLASH_SR_PGAERR | FLASH_SR_PGPERR | FLASH_SR_PGSERR | FLASH_SR_WRPERR)) != 0
|| memcmp(hash, "\x2d\x86\x4c\x0b\x78\x9a\x43\x21\x4e\xee\x85\x24\xd3\x18\x20\x75\x12\x5e\x5c\xa2\xcd\x52\x7f\x35\x82\xec\x87\xff\xd9\x40\x76\xbc", 32) != 0) {
send_msg_failure(dev);
@ -619,7 +619,7 @@ static void hid_rx_callback(usbd_device *dev, uint8_t ep)
return;
}
uint8_t hash[32];
sha256_Raw((unsigned char *)FLASH_APP_START, flash_len - FLASH_META_DESC_LEN, hash);
sha256_Raw(FLASH_PTR(FLASH_APP_START), flash_len - FLASH_META_DESC_LEN, hash);
layoutFirmwareHash(hash);
do {
delay(100000);
@ -630,7 +630,7 @@ static void hid_rx_callback(usbd_device *dev, uint8_t ep)
bool hash_check_ok = brand_new_firmware || button.YesUp;
layoutProgress("INSTALLING ... Please wait", 1000);
uint8_t flags = *((uint8_t *)FLASH_META_FLAGS);
uint8_t flags = *FLASH_PTR(FLASH_META_FLAGS);
// wipe storage if:
// 0) there was no firmware
// 1) old firmware was unsigned

@ -26,8 +26,6 @@
#include <stddef.h>
extern void *emulator_flash_base;
void emulatorPoll(void);
void emulatorRandom(void *buffer, size_t size);

@ -17,8 +17,6 @@
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/stm32/flash.h>
#include <string.h>
#include "memory.h"
@ -66,7 +64,7 @@ static void *sector_to_address(uint8_t sector) {
return NULL;
}
return (void *) (FLASH_ORIGIN + offset);
return (void *) FLASH_PTR(FLASH_ORIGIN + offset);
}
static ssize_t sector_to_size(uint8_t sector) {
@ -106,9 +104,9 @@ void flash_erase_all_sectors(uint32_t program_size) {
}
void flash_program_word(uint32_t address, uint32_t data) {
MMIO32(address) = data;
*(volatile uint32_t *)FLASH_PTR(address) = data;
}
void flash_program_byte(uint32_t address, uint8_t data) {
MMIO8(address) = data;
*(volatile uint8_t *)FLASH_PTR(address) = data;
}

@ -34,7 +34,7 @@
#define EMULATOR_FLASH_FILE "emulator.img"
void *emulator_flash_base = NULL;
uint8_t *emulator_flash_base = NULL;
uint32_t __stack_chk_guard;

@ -1678,7 +1678,7 @@ void fsm_msgDebugLinkMemoryRead(DebugLinkMemoryRead *msg)
if (msg->has_length && msg->length < length)
length = msg->length;
resp->has_memory = true;
memcpy(resp->memory.bytes, (void*) msg->address, length);
memcpy(resp->memory.bytes, FLASH_PTR(msg->address), length);
resp->memory.size = length;
msg_debug_write(MessageType_MessageType_DebugLinkMemory, resp);
}
@ -1696,7 +1696,9 @@ void fsm_msgDebugLinkMemoryWrite(DebugLinkMemoryWrite *msg)
}
flash_lock();
} else {
#if !EMULATOR
memcpy((void *) msg->address, msg->memory.bytes, length);
#endif
}
}

@ -19,6 +19,7 @@
#include "protect.h"
#include "storage.h"
#include "memory.h"
#include "messages.h"
#include "usb.h"
#include "oled.h"
@ -159,8 +160,8 @@ bool protectPin(bool use_cached)
if (!storage_hasPin() || (use_cached && session_isPinCached())) {
return true;
}
uint32_t *fails = storage_getPinFailsPtr();
uint32_t wait = ~*fails;
uint32_t fails = storage_getPinFailsOffset();
uint32_t wait = ~*(const uint32_t*)FLASH_PTR(fails);
protectCheckMaxTry(wait);
usbTiny(1);
while (wait > 0) {
@ -205,7 +206,7 @@ bool protectPin(bool use_cached)
storage_resetPinFails(fails);
return true;
} else {
protectCheckMaxTry(~*fails);
protectCheckMaxTry(~*(const uint32_t*)FLASH_PTR(fails));
fsm_sendFailure(FailureType_Failure_PinInvalid, NULL);
return false;
}

@ -48,27 +48,13 @@
static const uint32_t storage_magic = 0x726f7473; // 'stor' as uint32_t
static uint32_t storage_uuid[12 / sizeof(uint32_t)];
#ifndef __clang__
// TODO: Fix this for Clang
_Static_assert(((uint32_t)storage_uuid & 3) == 0, "uuid unaligned");
_Static_assert((sizeof(storage_uuid) & 3) == 0, "uuid unaligned");
#endif
_Static_assert(sizeof(storage_uuid) == 12, "storage_uuid has wrong size");
Storage CONFIDENTIAL storageUpdate;
#ifndef __clang__
// TODO: Fix this for Clang
_Static_assert(((uint32_t)&storageUpdate & 3) == 0, "storage unaligned");
Storage CONFIDENTIAL storageUpdate __attribute__((aligned(4)));
_Static_assert((sizeof(storageUpdate) & 3) == 0, "storage unaligned");
#endif
#define STORAGE_ROM ((const Storage *)(FLASH_STORAGE_START + sizeof(storage_magic) + sizeof(storage_uuid)))
#if EMULATOR
// TODO: Fix this for emulator
#define storageRom STORAGE_ROM
#else
const Storage *storageRom = STORAGE_ROM;
#endif
#define FLASH_STORAGE (FLASH_STORAGE_START + sizeof(storage_magic) + sizeof(storage_uuid))
#define storageRom ((const Storage *) FLASH_PTR(FLASH_STORAGE))
char storage_uuid_str[25];
@ -146,7 +132,7 @@ void storage_check_flash_errors(void)
bool storage_from_flash(void)
{
storage_clear_update();
if (memcmp((void *)FLASH_STORAGE_START, &storage_magic, sizeof(storage_magic)) != 0) {
if (memcmp(FLASH_PTR(FLASH_STORAGE_START), &storage_magic, sizeof(storage_magic)) != 0) {
// wrong magic
return false;
}
@ -167,7 +153,7 @@ bool storage_from_flash(void)
}
// load uuid
memcpy(storage_uuid, (void *)(FLASH_STORAGE_START + sizeof(storage_magic)), sizeof(storage_uuid));
memcpy(storage_uuid, FLASH_PTR(FLASH_STORAGE_START + sizeof(storage_magic)), sizeof(storage_uuid));
data2hex(storage_uuid, sizeof(storage_uuid), storage_uuid_str);
#define OLD_STORAGE_SIZE(last_member) (((offsetof(Storage, last_member) + pb_membersize(Storage, last_member)) + 3) & ~3)
@ -215,20 +201,17 @@ bool storage_from_flash(void)
flash_erase_sector(FLASH_META_SECTOR_LAST, FLASH_CR_PROGRAM_X32);
flash_program_word(FLASH_STORAGE_PINAREA, 0xffffffff << pinctr);
// erase storageRom.has_pin_failed_attempts and storageRom.pin_failed_attempts
#if !EMULATOR
// TODO: Fix this for emulator
_Static_assert(((uint32_t)&STORAGE_ROM->pin_failed_attempts & 3) == 0, "storage.pin_failed_attempts unaligned");
#endif
flash_program_byte((uint32_t)&storageRom->has_pin_failed_attempts, 0);
flash_program_word((uint32_t)&storageRom->pin_failed_attempts, 0);
_Static_assert(((FLASH_STORAGE + offsetof(Storage, pin_failed_attempts)) & 3) == 0, "storage.pin_failed_attempts unaligned");
flash_program_byte(FLASH_STORAGE + offsetof(Storage, has_pin_failed_attempts), 0);
flash_program_word(FLASH_STORAGE + offsetof(Storage, pin_failed_attempts), 0);
flash_lock();
storage_check_flash_errors();
}
uint32_t *u2fptr = (uint32_t*) FLASH_STORAGE_U2FAREA;
const uint32_t *u2fptr = (const uint32_t*) FLASH_PTR(FLASH_STORAGE_U2FAREA);
while (*u2fptr == 0) {
u2fptr++;
}
storage_u2f_offset = 32 * (u2fptr - (uint32_t*) FLASH_STORAGE_U2FAREA);
storage_u2f_offset = 32 * (u2fptr - (const uint32_t*) FLASH_PTR(FLASH_STORAGE_U2FAREA));
uint32_t u2fword = *u2fptr;
while ((u2fword & 1) == 0) {
storage_u2f_offset++;
@ -374,7 +357,7 @@ static void storage_commit_locked(bool update)
// backup meta
uint32_t meta_backup[FLASH_META_DESC_LEN / sizeof(uint32_t)];
memcpy(meta_backup, (uint8_t*)FLASH_META_START, FLASH_META_DESC_LEN);
memcpy(meta_backup, FLASH_PTR(FLASH_META_START), FLASH_META_DESC_LEN);
// erase storage
flash_erase_sector(FLASH_META_SECTOR_FIRST, FLASH_CR_PROGRAM_X32);
@ -763,14 +746,14 @@ static void storage_area_recycle(uint32_t new_pinfails)
// first clear storage marker. In case of a failure below it is better
// to clear the storage than to allow restarting with zero PIN failures
flash_program_word(FLASH_STORAGE_START, 0);
if (*(uint32_t *)FLASH_STORAGE_START != 0) {
if (*(const uint32_t *)FLASH_PTR(FLASH_STORAGE_START) != 0) {
storage_show_error();
}
// erase storage sector
flash_erase_sector(FLASH_META_SECTOR_LAST, FLASH_CR_PROGRAM_X32);
flash_program_word(FLASH_STORAGE_PINAREA, new_pinfails);
if (*(uint32_t *)FLASH_STORAGE_PINAREA != new_pinfails) {
if (*(const uint32_t *)FLASH_PTR(FLASH_STORAGE_PINAREA) != new_pinfails) {
storage_show_error();
}
@ -782,24 +765,24 @@ static void storage_area_recycle(uint32_t new_pinfails)
}
}
void storage_resetPinFails(uint32_t *pinfailsptr)
void storage_resetPinFails(uint32_t flash_pinfails)
{
flash_clear_status_flags();
flash_unlock();
if ((uint32_t) (pinfailsptr + 1)
if (flash_pinfails + sizeof(uint32_t)
>= FLASH_STORAGE_PINAREA + FLASH_STORAGE_PINAREA_LEN) {
// recycle extra storage sector
storage_area_recycle(0xffffffff);
} else {
flash_program_word((uint32_t) pinfailsptr, 0);
flash_program_word(flash_pinfails, 0);
}
flash_lock();
storage_check_flash_errors();
}
bool storage_increasePinFails(uint32_t *pinfailsptr)
bool storage_increasePinFails(uint32_t flash_pinfails)
{
uint32_t newctr = *pinfailsptr << 1;
uint32_t newctr = *(const uint32_t*)FLASH_PTR(flash_pinfails) << 1;
// counter already at maximum, we do not increase it any more
// return success so that a good pin is accepted
if (!newctr)
@ -807,19 +790,19 @@ bool storage_increasePinFails(uint32_t *pinfailsptr)
flash_clear_status_flags();
flash_unlock();
flash_program_word((uint32_t) pinfailsptr, newctr);
flash_program_word(flash_pinfails, newctr);
flash_lock();
storage_check_flash_errors();
return *pinfailsptr == newctr;
return *(const uint32_t*)FLASH_PTR(flash_pinfails) == newctr;
}
uint32_t *storage_getPinFailsPtr(void)
uint32_t storage_getPinFailsOffset(void)
{
uint32_t *pinfailsptr = (uint32_t *) FLASH_STORAGE_PINAREA;
while (*pinfailsptr == 0)
pinfailsptr++;
return pinfailsptr;
uint32_t flash_pinfails = FLASH_STORAGE_PINAREA;
while (*(const uint32_t*)FLASH_PTR(flash_pinfails) == 0)
flash_pinfails += sizeof(uint32_t);
return flash_pinfails;
}
bool storage_isInitialized(void)
@ -866,15 +849,17 @@ uint32_t storage_getFlags(void)
uint32_t storage_nextU2FCounter(void)
{
uint32_t *ptr = ((uint32_t *) FLASH_STORAGE_U2FAREA) + (storage_u2f_offset / 32);
uint32_t flash_u2f_offset = FLASH_STORAGE_U2FAREA +
sizeof(uint32_t) * (storage_u2f_offset / 32);
uint32_t newval = 0xfffffffe << (storage_u2f_offset & 31);
flash_clear_status_flags();
flash_unlock();
flash_program_word((uint32_t) ptr, newval);
flash_program_word(flash_u2f_offset, newval);
storage_u2f_offset++;
if (storage_u2f_offset >= 8 * FLASH_STORAGE_U2FAREA_LEN) {
storage_area_recycle(*storage_getPinFailsPtr());
storage_area_recycle(*(const uint32_t*)
FLASH_PTR(storage_getPinFailsOffset()));
}
flash_lock();
storage_check_flash_errors();

@ -122,9 +122,9 @@ void storage_setPin(const char *pin);
void session_cachePin(void);
bool session_isPinCached(void);
void storage_clearPinArea(void);
void storage_resetPinFails(uint32_t *pinfailptr);
bool storage_increasePinFails(uint32_t *pinfailptr);
uint32_t *storage_getPinFailsPtr(void);
void storage_resetPinFails(uint32_t flash_pinfails);
bool storage_increasePinFails(uint32_t flash_pinfails);
uint32_t storage_getPinFailsOffset(void);
uint32_t storage_nextU2FCounter(void);
void storage_setU2FCounter(uint32_t u2fcounter);

@ -69,7 +69,7 @@ void memory_write_unlock(void)
int memory_bootloader_hash(uint8_t *hash)
{
sha256_Raw((const uint8_t *)FLASH_BOOT_START, FLASH_BOOT_LEN, hash);
sha256_Raw(FLASH_PTR(FLASH_BOOT_START), FLASH_BOOT_LEN, hash);
sha256_Raw(hash, 32, hash);
return 32;
}

@ -20,6 +20,8 @@
#ifndef __MEMORY_H__
#define __MEMORY_H__
#include <stdint.h>
/*
flash memory layout:
@ -62,10 +64,13 @@
*/
#define FLASH_ORIGIN (0x08000000)
#if EMULATOR
#define FLASH_ORIGIN ((uint32_t) emulator_flash_base)
extern uint8_t *emulator_flash_base;
#define FLASH_PTR(x) (emulator_flash_base + (x - FLASH_ORIGIN))
#else
#define FLASH_ORIGIN (0x08000000)
#define FLASH_PTR(x) (const uint8_t*) (x)
#endif
#define FLASH_TOTAL_SIZE (512 * 1024)

Loading…
Cancel
Save