From d452d6f89dc46378336a389a60ea8d772927fb3f Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Thu, 6 Dec 2018 09:29:09 -0800 Subject: [PATCH 1/5] exo: Correct seal key source --- exosphere/src/sealedkeys.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exosphere/src/sealedkeys.c b/exosphere/src/sealedkeys.c index 03c417d4f..14142b274 100644 --- a/exosphere/src/sealedkeys.c +++ b/exosphere/src/sealedkeys.c @@ -33,7 +33,7 @@ static const uint8_t g_seal_key_sources[CRYPTOUSECASE_MAX_5X][0x10] = { {0x0E, 0xE0, 0xC4, 0x33, 0x82, 0x66, 0xE8, 0x08, 0x39, 0x13, 0x41, 0x7D, 0x04, 0x64, 0x2B, 0x6D}, {0xE1, 0xA8, 0xAA, 0x6A, 0x2D, 0x9C, 0xDE, 0x43, 0x0C, 0xDE, 0xC6, 0x17, 0xF6, 0xC7, 0xF1, 0xDE}, {0x74, 0x20, 0xF6, 0x46, 0x77, 0xB0, 0x59, 0x2C, 0xE8, 0x1B, 0x58, 0x64, 0x47, 0x41, 0x37, 0xD9}, - {0xAA, 0x19, 0x0F, 0xFA, 0x4C, 0x30, 0x3B, 0x2E, 0xE8, 0x1B, 0x58, 0x64, 0x47, 0x41, 0x37, 0xD9} + {0xAA, 0x19, 0x0F, 0xFA, 0x4C, 0x30, 0x3B, 0x2E, 0xE6, 0xD8, 0x9A, 0xCF, 0xE5, 0x3F, 0xB3, 0x4B} }; bool usecase_is_invalid(unsigned int usecase) { From ef373d954f6adac5b3ffae749294e9c14adf4c15 Mon Sep 17 00:00:00 2001 From: hexkyz Date: Fri, 7 Dec 2018 22:17:06 +0000 Subject: [PATCH 2/5] fusee: Fix KFUSE clock. --- fusee/fusee-primary/src/car.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/fusee/fusee-primary/src/car.c b/fusee/fusee-primary/src/car.c index 5bf8b4331..935dea922 100644 --- a/fusee/fusee-primary/src/car.c +++ b/fusee/fusee-primary/src/car.c @@ -15,6 +15,7 @@ */ #include "car.h" +#include "timers.h" #include "utils.h" static inline uint32_t get_clk_source_reg(CarDevice dev) { @@ -121,7 +122,15 @@ void clkrst_disable(CarDevice dev) { void clkrst_reboot(CarDevice dev) { clkrst_disable(dev); - clkrst_enable(dev); + if (dev == CARDEVICE_KFUSE) { + /* Workaround for KFUSE clock. */ + clk_enable(dev); + udelay(100); + rst_disable(dev); + udelay(200); + } else { + clkrst_enable(dev); + } } void clkrst_enable_fuse_regs(bool enable) { From 00aa283a54d7ace981fe9baebe8126b437d3d5ab Mon Sep 17 00:00:00 2001 From: hexkyz Date: Fri, 7 Dec 2018 22:18:01 +0000 Subject: [PATCH 3/5] fusee: Fix KFUSE clock. --- fusee/fusee-secondary/src/car.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/fusee/fusee-secondary/src/car.c b/fusee/fusee-secondary/src/car.c index 5bf8b4331..935dea922 100644 --- a/fusee/fusee-secondary/src/car.c +++ b/fusee/fusee-secondary/src/car.c @@ -15,6 +15,7 @@ */ #include "car.h" +#include "timers.h" #include "utils.h" static inline uint32_t get_clk_source_reg(CarDevice dev) { @@ -121,7 +122,15 @@ void clkrst_disable(CarDevice dev) { void clkrst_reboot(CarDevice dev) { clkrst_disable(dev); - clkrst_enable(dev); + if (dev == CARDEVICE_KFUSE) { + /* Workaround for KFUSE clock. */ + clk_enable(dev); + udelay(100); + rst_disable(dev); + udelay(200); + } else { + clkrst_enable(dev); + } } void clkrst_enable_fuse_regs(bool enable) { From 4827fd71b4fbaec9df9529a468d815eee306a12a Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Fri, 7 Dec 2018 14:27:46 -0800 Subject: [PATCH 4/5] fusee: Fix race condition involving volatile reads --- fusee/fusee-secondary/src/smmu.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/fusee/fusee-secondary/src/smmu.c b/fusee/fusee-secondary/src/smmu.c index 23bd3d37d..db54e5d9d 100644 --- a/fusee/fusee-secondary/src/smmu.c +++ b/fusee/fusee-secondary/src/smmu.c @@ -226,9 +226,10 @@ void smmu_emulate_tsec(void *tsec_keys, const void *package1, size_t package1_si uint32_t old_key_data = *key_data; uint32_t buf_counter = 0; while (!(tsec->FALCON_CPUCTL & 0x10)) { - if (*key_data != old_key_data) { - old_key_data = *key_data; - key_buf[buf_counter] = *key_data; + const uint32_t new_key_data = *key_data; + if (new_key_data != old_key_data) { + old_key_data = new_key_data; + key_buf[buf_counter] = new_key_data; buf_counter++; } } From 0ef336889388efaeab32f91528fde4dc1e318749 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Fri, 7 Dec 2018 14:54:06 -0800 Subject: [PATCH 5/5] fusee: retry tsec key generation on failure. --- fusee/fusee-secondary/src/smmu.c | 103 +++++++++++++++++++------------ 1 file changed, 64 insertions(+), 39 deletions(-) diff --git a/fusee/fusee-secondary/src/smmu.c b/fusee/fusee-secondary/src/smmu.c index db54e5d9d..23e394837 100644 --- a/fusee/fusee-secondary/src/smmu.c +++ b/fusee/fusee-secondary/src/smmu.c @@ -20,6 +20,8 @@ #include "timers.h" #include "tsec.h" +#define TSEC_KEYGEN_MAX_RETRIES 25 + void *smmu_heap = (void *)SMMU_HEAP_BASE_ADDR; static void safe_memcpy(void *dst, void *src, uint32_t sz) { @@ -168,14 +170,6 @@ void smmu_emulate_tsec(void *tsec_keys, const void *package1, size_t package1_si /* Copy package1 into IRAM. */ memcpy((void *)0x40010000, package1, package1_size); - /* Load the TSEC firmware from IRAM. */ - if (tsec_load_fw((void *)(0x40010000 + 0xE00), 0x2900) < 0) { - fatal_error("[SMMU]: Failed to load TSEC firmware!\n"); - } - - /* Disable the aperture since it has precedence over the SMMU. */ - mc_disable_ahb_redirect(); - /* Setup TSEC's address space. */ uint32_t *pdir = smmu_setup_tsec_as(1); @@ -189,21 +183,6 @@ void smmu_emulate_tsec(void *tsec_keys, const void *package1, size_t package1_si volatile uint32_t *iram_pages = smmu_alloc_page(48); volatile uint32_t *expv_page = smmu_alloc_page(1); - /* Copy CAR, MC and FUSE. */ - safe_memcpy((void *)car_page, (void *)0x60006000, 0x1000); - safe_memcpy((void *)mc_page, (void *)0x70019000, 0x1000); - safe_memcpy((void *)&fuse_page[0x800/4], (void *)0x7000F800, 0x400); - - /* Copy IRAM. */ - memcpy((void *)iram_pages, (void *)0x40010000, 0x30000); - - /* TSEC wants CLK_RST_CONTROLLER_CLK_SOURCE_TSEC_0 to be equal to 2. */ - car_page[0x1F4/4] = 2; - - /* TSEC wants the aperture fully open. */ - mc_page[0x65C/4] = 0; - mc_page[0x660/4] = 0x80000000; - /* Map all necessary pages. */ smmu_map(pdir, 0x60006000, (uint32_t)car_page, 1, _READABLE | _WRITABLE | _NONSECURE); smmu_map(pdir, 0x7000F000, (uint32_t)fuse_page, 1, _READABLE | _NONSECURE); @@ -217,20 +196,69 @@ void smmu_emulate_tsec(void *tsec_keys, const void *package1, size_t package1_si /* Enable the SMMU. */ smmu_enable(); - /* Run the TSEC firmware. */ - tsec_run_fw(); - - /* Extract the keys from SE. */ + /* Loop retrying TSEC firmware execution, in case we lose the SE keydata race. */ uint32_t key_buf[0x20/4] = {0}; - volatile uint32_t *key_data = (volatile uint32_t *)((void *)se_page + 0x320); - uint32_t old_key_data = *key_data; - uint32_t buf_counter = 0; - while (!(tsec->FALCON_CPUCTL & 0x10)) { - const uint32_t new_key_data = *key_data; - if (new_key_data != old_key_data) { - old_key_data = new_key_data; - key_buf[buf_counter] = new_key_data; - buf_counter++; + unsigned int retries = 0; + while (true) { + if (retries++ > TSEC_KEYGEN_MAX_RETRIES) { + fatal_error("[SMMU] TSEC key generation race was lost too many times!"); + } + + /* Load the TSEC firmware from IRAM. */ + if (tsec_load_fw((void *)(0x40010000 + 0xE00), 0x2900) < 0) { + fatal_error("[SMMU]: Failed to load TSEC firmware!\n"); + } + + /* Disable the aperture since it has precedence over the SMMU. */ + mc_disable_ahb_redirect(); + + /* Clear all pages. */ + memset((void *)car_page, 0, SMMU_PAGE_SIZE); + memset((void *)fuse_page, 0, SMMU_PAGE_SIZE); + memset((void *)pmc_page, 0, SMMU_PAGE_SIZE); + memset((void *)flow_page, 0, SMMU_PAGE_SIZE); + memset((void *)se_page, 0, SMMU_PAGE_SIZE); + memset((void *)mc_page, 0, SMMU_PAGE_SIZE); + memset((void *)iram_pages, 0, 48 * SMMU_PAGE_SIZE); + memset((void *)expv_page, 0, SMMU_PAGE_SIZE); + + /* Copy CAR, MC and FUSE. */ + safe_memcpy((void *)car_page, (void *)0x60006000, 0x1000); + safe_memcpy((void *)mc_page, (void *)0x70019000, 0x1000); + safe_memcpy((void *)&fuse_page[0x800/4], (void *)0x7000F800, 0x400); + + /* Copy IRAM. */ + memcpy((void *)iram_pages, (void *)0x40010000, 0x30000); + + /* TSEC wants CLK_RST_CONTROLLER_CLK_SOURCE_TSEC_0 to be equal to 2. */ + car_page[0x1F4/4] = 2; + + /* TSEC wants the aperture fully open. */ + mc_page[0x65C/4] = 0; + mc_page[0x660/4] = 0x80000000; + + + /* Run the TSEC firmware. */ + tsec_run_fw(); + + /* Extract the keys from SE. */ + volatile uint32_t *key_data = (volatile uint32_t *)((void *)se_page + 0x320); + uint32_t old_key_data = *key_data; + uint32_t buf_counter = 0; + while (!(tsec->FALCON_CPUCTL & 0x10)) { + const uint32_t new_key_data = *key_data; + if (new_key_data != old_key_data) { + old_key_data = new_key_data; + key_buf[buf_counter] = new_key_data; + buf_counter++; + } + } + + /* Enable back the aperture. */ + mc_enable_ahb_redirect(); + + if (buf_counter == 8) { + break; } } @@ -249,9 +277,6 @@ void smmu_emulate_tsec(void *tsec_keys, const void *package1, size_t package1_si /* Clear TSEC's address space. */ smmu_clear_tsec_as(1); - /* Enable back the aperture. */ - mc_enable_ahb_redirect(); - /* Return the decrypted package1 from emulated IRAM. */ memcpy(package1_dec, (void *)iram_pages, package1_size);