#include #include "crypto.h" #include "hardware/flash.h" #include "hardware/sync.h" #include "pico/rand.h" #include "pico/stdlib.h" #include "platform.h" // The storage region is the last 64 KB of flash, far past the firmware image. #define STORAGE_FLASH_OFFSET (PICO_FLASH_SIZE_BYTES - STORAGE_SIZE) _Static_assert(STORAGE_SECTOR_SIZE == FLASH_SECTOR_SIZE, "sector size mismatch"); _Static_assert(STORAGE_PAGE_SIZE == FLASH_PAGE_SIZE, "page size mismatch"); extern char __flash_binary_end; void platform_led(bool on) { #ifdef PICO_DEFAULT_LED_PIN gpio_put(PICO_DEFAULT_LED_PIN, on); #else (void)on; #endif } void platform_init(void) { if ((uintptr_t)&__flash_binary_end > XIP_BASE + STORAGE_FLASH_OFFSET) platform_panic("firmware overlaps the storage region"); #ifdef PICO_DEFAULT_LED_PIN gpio_init(PICO_DEFAULT_LED_PIN); gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT); #endif } uint32_t platform_millis(void) { return to_ms_since_boot(get_absolute_time()); } // pico_rand mixes fresh hardware entropy (ROSC jitter, timers, and the TRNG // on RP2350) into every call. Each output block hashes many of those calls. void platform_random(uint8_t *buf, size_t len) { uint64_t samples[32]; uint8_t block[32]; while (len > 0) { for (size_t i = 0; i < 32; i++) samples[i] = get_rand_64(); crypto_part_t part = {samples, sizeof(samples)}; crypto_sha256(&part, 1, block); size_t n = len < sizeof(block) ? len : sizeof(block); memcpy(buf, block, n); buf += n; len -= n; } crypto_wipe(samples, sizeof(samples)); crypto_wipe(block, sizeof(block)); } void platform_panic(const char *msg) { panic("%s", msg); } void platform_wink(void) { for (int i = 0; i < 3; i++) { platform_led(true); sleep_ms(100); platform_led(false); sleep_ms(100); } } void platform_flash_read(uint32_t offset, void *buf, size_t len) { memcpy(buf, (const void *)(XIP_BASE + STORAGE_FLASH_OFFSET + offset), len); } // Flash is unavailable for execution while it is being written, so interrupts // (whose handlers live in flash) stay off for the duration. void platform_flash_erase(uint32_t offset) { uint32_t irq = save_and_disable_interrupts(); flash_range_erase(STORAGE_FLASH_OFFSET + offset, FLASH_SECTOR_SIZE); restore_interrupts(irq); } void platform_flash_program(uint32_t offset, const void *buf, size_t len) { uint32_t irq = save_and_disable_interrupts(); flash_range_program(STORAGE_FLASH_OFFSET + offset, buf, len); restore_interrupts(irq); }