/* * (c) Copyright 2018 by Coinkite Inc. This file is covered by license found in COPYING-CC. * * dispatch.c * * This code runs in an area of flash protected from viewing. It has limited entry * point (via a special callgate) and checks state carefully before running other stuff. * */ #include #include #include #include "basics.h" #include "misc.h" #include "sha256.h" #include "version.h" #include "clocks.h" #include "oled.h" #include "delay.h" #include "rng.h" #include "gpio.h" #include "ae.h" #include "pins.h" #include "verify.h" #include "storage.h" #include "sflash.h" #include "dispatch.h" #include "constant_time.h" #include "assets/screens.h" #include "stm32l4xx_hal.h" // This magic value indicates we should go direct into DFU on this reboot. // Arbitrary SRAM1 location, random magic values. Also what screen to show. static const char *REBOOT_TO_DFU = "Boot2DFU"; typedef struct { char magic[8]; const uint8_t *screen; } dfu_flag_t; #define dfu_flag ((dfu_flag_t *)0x20008000) // reboot_seed_setup() // // We need to know when we are rebooted, so write some noise // into SRAM and lock its value. Not secrets. One page = 1k bytes here. // void 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 coldcardFirmwareHeader_t *hdr_copy = (void *)&reboot_seed_base[32]; uint32_t *boot_flags = (uint32_t *)RAM_BOOT_FLAGS; // can only do this once, and might be done already if(SYSCFG->SWPR != (1<<31)) { ASSERT(((uint32_t)reboot_seed) == 0x10007c00); ASSERT(((uint32_t)hdr_copy) == RAM_HEADER_BASE); // populate seed w/ noise memset(reboot_seed, 0x55, 1024); rng_buffer(reboot_seed, 32); // preserve a copy of the verified FW header memcpy(hdr_copy, FW_HDR, sizeof(coldcardFirmwareHeader_t)); // document how we booted. uint32_t fl = 0; if(!flash_is_security_level2()) { fl |= RBF_FACTORY_MODE; } if(sf_completed_upgrade == SF_COMPLETED_UPGRADE) { fl |= RBF_FRESH_VERSION; } *boot_flags = fl; // lock it (top most page = 1k bytes) SYSCFG->SWPR = (1<<31); } } // memset4() // static inline void memset4(uint32_t *dest, uint32_t value, uint32_t byte_len) { for(; byte_len; byte_len-=4, dest++) { *dest = value; } } // wipe_all_sram() // static void wipe_all_sram(void) { const uint32_t noise = 0xdeadbeef; // wipe all of SRAM (except our own memory, which was already wiped) memset4((void *)SRAM1_BASE, noise, SRAM1_SIZE_MAX); memset4((void *)SRAM2_BASE, noise, SRAM2_SIZE - BL_SRAM_SIZE); } // system_startup() // // Called only on system boot. // void system_startup(void) { // configure clocks first clocks_setup(); #if RELEASE // security check: should we be in protected mode? Was there some UV-C bitrot perhaps? if(!check_all_ones(rom_secrets->bag_number, sizeof(rom_secrets->bag_number)) && !flash_is_security_level2() ) { // yikes. recovery: do lockdown... we should be/(thought we were) locked already flash_lockdown_hard(OB_RDP_LEVEL_2); } #endif // workaround to get into DFU from micropython // LATER: none of this is useful with RDP=2 if(memcmp(dfu_flag->magic, REBOOT_TO_DFU, sizeof(dfu_flag->magic)) == 0) { dfu_flag->magic[0] = 0; // still see a flash here, but that's proof it works. oled_setup(); oled_show(dfu_flag->screen); enter_dfu(); // NOT-REACHED } // clear and setup OLED display oled_setup(); oled_show_progress(screen_verify, 0); // won't always need it, but enable RNG anyway rng_setup(); // wipe all of SRAM (except our own memory, which was already wiped) wipe_all_sram(); // config pins gpio_setup(); ae_setup(); ae_set_gpio(0); // not checking return on purpose // protect our flash, and/or check it's protected // - and pick pairing secret if we don't already have one // - may also do one-time setup of 508a // - note: ae_setup must already be called, since it can talk to that flash_setup(); // escape into DFU if(dfu_button_pressed()) dfu_by_request(); // maybe upgrade to a firmware image found in sflash sf_firmware_upgrade(); // SLOW part: check firmware is legit; else enter DFU // - may die due to downgrade attack or unsigned/badly signed image verify_firmware(); // .. for slow people, check again; last chance if(dfu_button_pressed()) dfu_by_request(); // track reboots, capture firmware hdr used // - must be near end of boot process, ie: here. reboot_seed_setup(); // load a blank screen, so that if the firmware crashes, we are showing // something reasonable and not misleading. oled_show(screen_blankish); } // fatal_error(const char *msg) // void fatal_error(const char *msgvoid) { oled_setup(); oled_show(screen_fatal); // Maybe should do a reset after a delay, like with // the watchdog timer or something. LOCKUP_FOREVER(); } // fatal_mitm() // void fatal_mitm(void) { oled_setup(); oled_show(screen_mitm); #ifdef RELEASE wipe_all_sram(); #endif LOCKUP_FOREVER(); } // dfu_by_request() // void dfu_by_request(void) { if(flash_is_security_level2()) { // cannot get into DFU when secure // so do nothing return; } oled_show(screen_dfu); enter_dfu(); } // enter_dfu() // void __attribute__((noreturn)) enter_dfu(void) { const uint32_t noise = 0xDeadBeef; // clear the green light, if set ae_setup(); ae_set_gpio(0); // Reset huge parts of the chip __HAL_RCC_APB1_FORCE_RESET(); __HAL_RCC_APB1_RELEASE_RESET(); __HAL_RCC_APB2_FORCE_RESET(); __HAL_RCC_APB2_RELEASE_RESET(); __HAL_RCC_AHB1_FORCE_RESET(); __HAL_RCC_AHB1_RELEASE_RESET(); #if 0 // But not this; it borks things. __HAL_RCC_AHB2_FORCE_RESET(); __HAL_RCC_AHB2_RELEASE_RESET(); #endif __HAL_RCC_AHB3_FORCE_RESET(); __HAL_RCC_AHB3_RELEASE_RESET(); __HAL_FIREWALL_PREARM_ENABLE(); // Wipe all of memory SRAM, just in case // there is some way to trick us into DFU // after sensitive content in place. memset4((void *)SRAM1_BASE, noise, SRAM1_SIZE_MAX); memset4((void *)SRAM2_BASE, noise, SRAM2_SIZE - 1024); // avoid seed area if(flash_is_security_level2()) { // cannot do DFU in RDP=2, so just die. Helps to preserve screen LOCKUP_FOREVER(); } // Reset clocks. HAL_RCC_DeInit(); // move system ROM into 0x0 __HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH(); // simulate a reset vector __ASM volatile ("movs r0, #0\n" "ldr r3, [r0, #0]\n" "msr msp, r3\n" "ldr r3, [r0, #4]\n" "blx r3" : : : "r0", "r3", "sp"); // NOT-REACHED. __builtin_unreachable(); } // good_addr() // static int good_addr(const uint8_t *b, int minlen, int len, bool readonly) { uint32_t x = (uint32_t)b; if(minlen) { if(!b) return EFAULT; // gave no buffer if(len < minlen) return ERANGE; // too small } if((x >= SRAM1_BASE) && ((x-SRAM1_BASE) < SRAM1_SIZE_MAX)) { // inside SRAM1, okay return 0; } if(!readonly) { return EPERM; } if((x >= FIRMWARE_START) && (x - FIRMWARE_START) < FW_MAX_LENGTH) { // inside flash of main firmware (happens for QSTR's) return 0; } return EACCES; } /* The callgate into the firewall... From the reference manual: The “call gate” is composed of 3 words located on the first three 32-bit addresses of the base address of the code segment and of the Volatile data segment if it is declared as not shared (VDS = 0) and executable (VDE = 1). – 1st word: Dummy 32-bit words always closed in order to protect the “call gate” opening from an access due to a prefetch buffer. – 2nd and 3rd words: 2 specific 32-bit words called “call gate” and always opened. We are assuming the caller gives us a working C runtime: stack, arguments in registers and so on. */ // firewall_dispatch() // // A C-runtime compatible env. is running, so do some work. // __attribute__ ((used)) int firewall_dispatch(int method_num, uint8_t *buf_io, int len_in, uint32_t arg2, uint32_t incoming_sp, uint32_t incoming_lr) { // from linker, offset of firewall entry extern uint32_t firewall_starts; int rv = 0; #if 0 // TODO: re-enable this; causing crash now. // in case the caller didn't already, but would just lead to a crash anyway __disable_irq(); #endif // "1=any code executed outside the protected segment will close the Firewall" // "0=.. will reset the processor" __HAL_FIREWALL_PREARM_DISABLE(); // Important: // - range check pointers so we aren't tricked into revealing our secrets // - check buf_io points to main SRAM, and not into us! // - range check len_in tightly // - calling convention only gives me enough for 4 args to this function, so // using read/write in place. // - use arg2 use when a simple number is needed; never a pointer! // - mpy may provide a pointer to flash if we give it a qstr or small value, and if // we're reading only, that's fine. if(len_in > 1024) { // arbitrary max, increase as needed rv = ERANGE; goto fail; } // Use these macros #define REQUIRE_IN_ONLY(x) if((rv = good_addr(buf_io, (x), len_in, true))) { goto fail; } #define REQUIRE_OUT(x) if((rv = good_addr(buf_io, (x), len_in, false))) { goto fail; } switch(method_num) { case 0: { REQUIRE_OUT(64); // Return my version string memset(buf_io, 0, len_in); strlcpy((char *)buf_io, version_string, len_in); rv = strlen(version_string); break; } case 1: { // Perform SHA256 over ourselves, with 32-bits of salt, to imply we // haven't stored valid responses. REQUIRE_OUT(32); SHA256_CTX ctx; sha256_init(&ctx); sha256_update(&ctx, (void *)&arg2, 4); sha256_update(&ctx, (void *)BL_FLASH_BASE, BL_FLASH_SIZE); sha256_final(&ctx, buf_io); break; } case 2: { const uint8_t *scr; bool secure = flash_is_security_level2(); // Go into DFU mode. It's a one-way trip. // Also used to show some "fatal" screens w/ memory wipe. switch(arg2) { default: case 0: // enter DFU for firmware upgrades if(secure) { // we cannot support DFU in secure mode anymore rv = EPERM; goto fail; } scr = screen_dfu; break; case 1: // in case some way for Micropython to detect it. scr = screen_downgrade; break; case 2: scr = screen_blankish; break; case 3: scr = screen_brick; secure = true; // no point going into DFU, if even possible break; } oled_setup(); oled_show(scr); wipe_all_sram(); if(secure) { // just die with that message shown; can't start DFU LOCKUP_FOREVER(); } else { // Cannot just call enter_dfu() because it doesn't work well // once Micropython has configured so much stuff in the chip. // Leave a reminder to ourselves memcpy(dfu_flag->magic, REBOOT_TO_DFU, sizeof(dfu_flag->magic)); dfu_flag->screen = scr; // reset system NVIC_SystemReset(); // NOT-REACHED } break; } case 3: // logout: wipe all of memory and lock up. Must powercycle to recover. switch(arg2) { case 0: case 2: oled_show(screen_logout); break; case 1: // leave screen untouched break; } wipe_all_sram(); if(arg2 == 2) { // need some time to show OLED contents delay_ms(100); // reboot so we can "login" again NVIC_SystemReset(); // NOT-REACHED (but ok if it does) } // wait for an interrupt which will never happen (ie. sleep) LOCKUP_FOREVER() break; case 4: // attempt to control the GPIO (won't work for 1) ae_setup(); ae_keep_alive(); switch(arg2) { default: case 0: // read state rv = ae_get_gpio(); break; case 1: // clear it (can work anytime) rv = ae_set_gpio(0); break; case 2: // set it (will always fail) rv = ae_set_gpio(1); break; case 3: { // do a verify and see if it maybe goes green uint8_t fw_digest[32], world_digest[32]; // takes time, shows progress bar checksum_flash(fw_digest, world_digest); rv = ae_set_gpio_secure(world_digest); oled_show(screen_blankish); break; } } break; case 5: // Are we a brick? // if the pairing secret doesn't work anymore, that // means we've been bricked. // TODO: also report hardware issue, and non-configured states ae_setup(); rv = (ae_pair_unlock() != 0); break; case 6: // Do we have a ATECC608a and all that implies? // NOTE: this number was unused in V1 bootroms, so return ENOENT #if FOR_608 rv = 0; #else rv = ENOENT; #endif break; case 12: // read the DFU button (used for selftest at least) REQUIRE_OUT(1); gpio_setup(); buf_io[0] = dfu_button_pressed(); break; case 15: { // Read a dataslot directly. Will fail on // encrypted slots. if(len_in != 4 && len_in != 32 && len_in != 72) { rv = ERANGE; } else { REQUIRE_OUT(4); ae_setup(); if(ae_read_data_slot(arg2 & 0xf, buf_io, len_in)) { rv = EIO; } } break; } case 16: { // Provide the 2 words for anti-phishing. REQUIRE_OUT(MAX_PIN_LEN); // arg2: length of pin. if((arg2 < 1) || (arg2 > MAX_PIN_LEN)) { rv = ERANGE; } else { if(pin_prefix_words((char *)buf_io, arg2, (uint32_t *)buf_io)) { rv = EIO; } } break; } case 17: // test rng REQUIRE_OUT(32); memset(buf_io, 0x55, 32); // to help show errors rng_buffer(buf_io, 32); break; case 18: { // Try login w/ PIN. REQUIRE_OUT(PIN_ATTEMPT_SIZE_V2); pinAttempt_t *args = (pinAttempt_t *)buf_io; switch(arg2) { case 0: rv = pin_setup_attempt(args); break; case 1: rv = pin_delay(args); break; case 2: rv = pin_login_attempt(args); break; case 3: rv = pin_change(args); break; case 4: rv = pin_fetch_secret(args); break; case 5: rv = pin_firmware_greenlight(args); break; case 6: // new for v2 rv = pin_long_secret(args); break; default: rv = ENOENT; break; } break; } case 19: { // bag number stuff switch(arg2) { case 0: // read out number REQUIRE_OUT(32); memcpy(buf_io, rom_secrets->bag_number, 32); break; case 1: // set the bag number, and (should) do lock down REQUIRE_IN_ONLY(32); flash_save_bag_number(buf_io); break; case 100: flash_lockdown_hard(OB_RDP_LEVEL_0); // wipes contents of flash (1->0) break; case 101: flash_lockdown_hard(OB_RDP_LEVEL_1); // Can only do 0->1 (experiments) break; case 102: // production units will be: flash_lockdown_hard(OB_RDP_LEVEL_2); // No change possible after this. break; default: rv = ENOENT; break; } break; } case 20: // Read out entire config dataspace REQUIRE_OUT(128); ae_setup(); rv = ae_config_read(buf_io); if(rv) { rv = EIO; } break; case 21: // read OTP / downgrade protection switch(arg2) { case 0: REQUIRE_OUT(8); get_min_version(buf_io); break; case 1: REQUIRE_IN_ONLY(8); rv = check_is_downgrade(buf_io, NULL); break; case 2: REQUIRE_IN_ONLY(8); if(buf_io[0] < 0x10 || buf_io[0] >= 0x40) { // bad data rv = ERANGE; } if(check_is_downgrade(buf_io, NULL)) { // already at a higher version? rv = EAGAIN; } else { uint8_t min[8]; get_min_version(min); if(memcmp(min, buf_io, 8) == 0) { // dupe rv = EAGAIN; } else { // save it, but might be "full" already if(record_highwater_version(buf_io)) { rv = ENOMEM; } } } break; case 3: // read raw counter0 value (max is 0x1fffff) REQUIRE_OUT(4); ae_setup(); rv = ae_get_counter((uint32_t *)buf_io, 0) ? EIO: 0; break; default: rv = ENOENT; break; } break; case -1: // System startup code. Cannot be reached by any code (that hopes to run // again) except our reset stub. if(incoming_lr <= BL_FLASH_BASE || incoming_lr >= (uint32_t)&firewall_starts) { fatal_error("LR"); } else { system_startup(); } break; default: rv = ENOENT; break; } #undef REQUIRE_IN_ONLY #undef REQUIRE_OUT fail: // Precaution: we don't want to leave ATECC508A authorized for any specific keys, // perhaps due to an error path we didn't see. Always reset the chip. ae_reset_chip(); // Unlikely it matters, but clear flash memory cache. __HAL_FLASH_DATA_CACHE_DISABLE(); __HAL_FLASH_DATA_CACHE_RESET(); __HAL_FLASH_DATA_CACHE_ENABLE(); // .. and instruction memory (flash cache too?) __HAL_FLASH_INSTRUCTION_CACHE_DISABLE(); __HAL_FLASH_INSTRUCTION_CACHE_RESET(); __HAL_FLASH_INSTRUCTION_CACHE_ENABLE(); // authorize return from firewall into user's code __HAL_FIREWALL_PREARM_ENABLE(); return rv; } // HAL support garbage const uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; const uint8_t APBPrescTable[8] = {0, 0, 0, 0, 1, 2, 3, 4}; const uint32_t MSIRangeTable[12] = {100000, 200000, 400000, 800000, 1000000, 2000000, \ 4000000, 8000000, 16000000, 24000000, 32000000, 48000000}; uint32_t SystemCoreClock; // TODO: cleanup HAL stuff to not use this uint32_t HAL_GetTick(void) { return 53; } // EOF