1
0
Fork 0
mirror of https://github.com/Atmosphere-NX/Atmosphere.git synced 2024-11-23 04:12:02 +00:00

fusee: retry tsec key generation on failure.

This commit is contained in:
Michael Scire 2018-12-07 14:54:06 -08:00
parent 4827fd71b4
commit 0ef3368893

View file

@ -20,6 +20,8 @@
#include "timers.h" #include "timers.h"
#include "tsec.h" #include "tsec.h"
#define TSEC_KEYGEN_MAX_RETRIES 25
void *smmu_heap = (void *)SMMU_HEAP_BASE_ADDR; void *smmu_heap = (void *)SMMU_HEAP_BASE_ADDR;
static void safe_memcpy(void *dst, void *src, uint32_t sz) { 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. */ /* Copy package1 into IRAM. */
memcpy((void *)0x40010000, package1, package1_size); 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. */ /* Setup TSEC's address space. */
uint32_t *pdir = smmu_setup_tsec_as(1); uint32_t *pdir = smmu_setup_tsec_as(1);
@ -189,6 +183,45 @@ 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 *iram_pages = smmu_alloc_page(48);
volatile uint32_t *expv_page = smmu_alloc_page(1); volatile uint32_t *expv_page = smmu_alloc_page(1);
/* 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);
smmu_map(pdir, 0x7000E000, (uint32_t)pmc_page, 1, _READABLE | _NONSECURE);
smmu_map(pdir, 0x60007000, (uint32_t)flow_page, 1, _WRITABLE | _NONSECURE);
smmu_map(pdir, 0x70012000, (uint32_t)se_page, 1, _READABLE | _WRITABLE | _NONSECURE);
smmu_map(pdir, 0x70019000, (uint32_t)mc_page, 1, _READABLE | _NONSECURE);
smmu_map(pdir, 0x40010000, (uint32_t)iram_pages, 48, _READABLE | _WRITABLE | _NONSECURE);
smmu_map(pdir, 0x6000F000, (uint32_t)expv_page, 1, _READABLE | _WRITABLE | _NONSECURE);
/* Enable the SMMU. */
smmu_enable();
/* Loop retrying TSEC firmware execution, in case we lose the SE keydata race. */
uint32_t key_buf[0x20/4] = {0};
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. */ /* Copy CAR, MC and FUSE. */
safe_memcpy((void *)car_page, (void *)0x60006000, 0x1000); safe_memcpy((void *)car_page, (void *)0x60006000, 0x1000);
safe_memcpy((void *)mc_page, (void *)0x70019000, 0x1000); safe_memcpy((void *)mc_page, (void *)0x70019000, 0x1000);
@ -204,24 +237,11 @@ void smmu_emulate_tsec(void *tsec_keys, const void *package1, size_t package1_si
mc_page[0x65C/4] = 0; mc_page[0x65C/4] = 0;
mc_page[0x660/4] = 0x80000000; 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);
smmu_map(pdir, 0x7000E000, (uint32_t)pmc_page, 1, _READABLE | _NONSECURE);
smmu_map(pdir, 0x60007000, (uint32_t)flow_page, 1, _WRITABLE | _NONSECURE);
smmu_map(pdir, 0x70012000, (uint32_t)se_page, 1, _READABLE | _WRITABLE | _NONSECURE);
smmu_map(pdir, 0x70019000, (uint32_t)mc_page, 1, _READABLE | _NONSECURE);
smmu_map(pdir, 0x40010000, (uint32_t)iram_pages, 48, _READABLE | _WRITABLE | _NONSECURE);
smmu_map(pdir, 0x6000F000, (uint32_t)expv_page, 1, _READABLE | _WRITABLE | _NONSECURE);
/* Enable the SMMU. */
smmu_enable();
/* Run the TSEC firmware. */ /* Run the TSEC firmware. */
tsec_run_fw(); tsec_run_fw();
/* Extract the keys from SE. */ /* Extract the keys from SE. */
uint32_t key_buf[0x20/4] = {0};
volatile uint32_t *key_data = (volatile uint32_t *)((void *)se_page + 0x320); volatile uint32_t *key_data = (volatile uint32_t *)((void *)se_page + 0x320);
uint32_t old_key_data = *key_data; uint32_t old_key_data = *key_data;
uint32_t buf_counter = 0; uint32_t buf_counter = 0;
@ -234,6 +254,14 @@ void smmu_emulate_tsec(void *tsec_keys, const void *package1, size_t package1_si
} }
} }
/* Enable back the aperture. */
mc_enable_ahb_redirect();
if (buf_counter == 8) {
break;
}
}
/* Check if the TSEC firmware wrote over the exception vectors. */ /* Check if the TSEC firmware wrote over the exception vectors. */
volatile uint32_t *tsec_done_check = (volatile uint32_t *)((void *)expv_page + 0x200); volatile uint32_t *tsec_done_check = (volatile uint32_t *)((void *)expv_page + 0x200);
if (!(*tsec_done_check)) { if (!(*tsec_done_check)) {
@ -249,9 +277,6 @@ void smmu_emulate_tsec(void *tsec_keys, const void *package1, size_t package1_si
/* Clear TSEC's address space. */ /* Clear TSEC's address space. */
smmu_clear_tsec_as(1); smmu_clear_tsec_as(1);
/* Enable back the aperture. */
mc_enable_ahb_redirect();
/* Return the decrypted package1 from emulated IRAM. */ /* Return the decrypted package1 from emulated IRAM. */
memcpy(package1_dec, (void *)iram_pages, package1_size); memcpy(package1_dec, (void *)iram_pages, package1_size);