fusee: support getting old tsec key from new tsec fw.

This commit is contained in:
Michael Scire 2018-11-25 16:22:47 -08:00
parent eab5e0df9b
commit c3569ec5e2
7 changed files with 50 additions and 26 deletions

View file

@ -20,7 +20,9 @@
/* This serves to set configuration for *exosphere itself*, separate from the SecMon Exosphere mimics. */ /* This serves to set configuration for *exosphere itself*, separate from the SecMon Exosphere mimics. */
/* "XBC0" */ /* "XBC0" */
#define MAGIC_EXOSPHERE_BOOTCONFIG (0x30434258) #define MAGIC_EXOSPHERE_BOOTCONFIG_0 (0x30434258)
/* "XBC1" */
#define MAGIC_EXOSPHERE_BOOTCONFIG (0x31434258)
#define EXOSPHERE_TARGET_FIRMWARE_100 1 #define EXOSPHERE_TARGET_FIRMWARE_100 1
#define EXOSPHERE_TARGET_FIRMWARE_200 2 #define EXOSPHERE_TARGET_FIRMWARE_200 2
@ -28,13 +30,18 @@
#define EXOSPHERE_TARGET_FIRMWARE_400 4 #define EXOSPHERE_TARGET_FIRMWARE_400 4
#define EXOSPHERE_TARGET_FIRMWARE_500 5 #define EXOSPHERE_TARGET_FIRMWARE_500 5
#define EXOSPHERE_TARGET_FIRMWARE_600 6 #define EXOSPHERE_TARGET_FIRMWARE_600 6
#define EXOSPHERE_TARGET_FIRMWARE_620 7
#define EXOSPHERE_TARGET_FIRMWARE_MIN EXOSPHERE_TARGET_FIRMWARE_100 #define EXOSPHERE_TARGET_FIRMWARE_MIN EXOSPHERE_TARGET_FIRMWARE_100
#define EXOSPHERE_TARGET_FIRMWARE_MAX EXOSPHERE_TARGET_FIRMWARE_600 #define EXOSPHERE_TARGET_FIRMWARE_MAX EXOSPHERE_TARGET_FIRMWARE_620
#define EXOSPHERE_FLAGS_DEFAULT 0x00000000
#define EXOSPHERE_FLAG_PERFORM_620_KEYGEN (1 << 0u)
typedef struct { typedef struct {
unsigned int magic; unsigned int magic;
unsigned int target_firmware; unsigned int target_firmware;
unsigned int flags;
} exosphere_config_t; } exosphere_config_t;
#define MAILBOX_EXOSPHERE_CONFIGURATION ((volatile exosphere_config_t *)(0x40002E40)) #define MAILBOX_EXOSPHERE_CONFIGURATION ((volatile exosphere_config_t *)(0x40002E40))

View file

@ -56,7 +56,7 @@ static const uint8_t AL16 masterkey_4x_seed[0x10] = {
static nx_dec_keyblob_t AL16 g_dec_keyblobs[32]; static nx_dec_keyblob_t AL16 g_dec_keyblobs[32];
static int get_tsec_key(void *dst, const void *tsec_fw, size_t tsec_fw_size, uint32_t tsec_key_id) { static int get_tsec_key(void *dst, const void *tsec_fw, size_t tsec_fw_size, uint32_t tsec_key_id) {
return tsec_get_key(dst, tsec_key_id, tsec_fw); return tsec_get_key(dst, tsec_key_id, tsec_fw, tsec_fw_size);
} }
static int get_keyblob(nx_keyblob_t *dst, uint32_t revision, const nx_keyblob_t *keyblobs, uint32_t available_revision) { static int get_keyblob(nx_keyblob_t *dst, uint32_t revision, const nx_keyblob_t *keyblobs, uint32_t available_revision) {
@ -125,9 +125,10 @@ int derive_nx_keydata(uint32_t target_firmware, const nx_keyblob_t *keyblobs, ui
set_aes_keyslot_flags(0xD, 0x15); set_aes_keyslot_flags(0xD, 0x15);
/* Set TSEC key. */ /* Set TSEC key. */
if (get_tsec_key(work_buffer, tsec_fw, tsec_fw_size, 1) != 0) { if (get_tsec_key(work_buffer, tsec_fw, tsec_fw_size, 1) != 0) {
return -1; return -1;
} }
set_aes_keyslot(0xD, work_buffer, 0x10); set_aes_keyslot(0xD, work_buffer, 0x10);
/* Decrypt all keyblobs, setting keyslot 0xF correctly. */ /* Decrypt all keyblobs, setting keyslot 0xF correctly. */

View file

@ -76,8 +76,15 @@ static uint32_t nxboot_get_target_firmware(const void *package1loader) {
return EXOSPHERE_TARGET_FIRMWARE_400; return EXOSPHERE_TARGET_FIRMWARE_400;
case 0x0B: /* 5.0.0 - 5.1.0 */ case 0x0B: /* 5.0.0 - 5.1.0 */
return EXOSPHERE_TARGET_FIRMWARE_500; return EXOSPHERE_TARGET_FIRMWARE_500;
case 0x0E: /* 6.0.0 */ case 0x0E: { /* 6.0.0 - 6.2.0 */
return EXOSPHERE_TARGET_FIRMWARE_600; if (memcmp(package1loader_header->build_timestamp, "20180802", 8) == 0) {
return EXOSPHERE_TARGET_FIRMWARE_600;
} else if (memcmp(package1loader_header->build_timestamp, "20181107", 8) == 0) {
return EXOSPHERE_TARGET_FIRMWARE_620;
} else {
fatal_error("[NXBOOT]: Unable to identify package1!\n");
}
}
default: default:
return 0; return 0;
} }
@ -88,6 +95,7 @@ static void nxboot_configure_exosphere(uint32_t target_firmware) {
exo_cfg.magic = MAGIC_EXOSPHERE_BOOTCONFIG; exo_cfg.magic = MAGIC_EXOSPHERE_BOOTCONFIG;
exo_cfg.target_firmware = target_firmware; exo_cfg.target_firmware = target_firmware;
exo_cfg.flags = EXOSPHERE_FLAGS_DEFAULT;
if (ini_parse_string(get_loader_ctx()->bct0, exosphere_ini_handler, &exo_cfg) < 0) { if (ini_parse_string(get_loader_ctx()->bct0, exosphere_ini_handler, &exo_cfg) < 0) {
fatal_error("[NXBOOT]: Failed to parse BCT.ini!\n"); fatal_error("[NXBOOT]: Failed to parse BCT.ini!\n");
@ -261,10 +269,17 @@ uint32_t nxboot_main(void) {
} }
fclose(boot0); fclose(boot0);
/* Find the system's target firmware. */
uint32_t target_firmware = nxboot_get_target_firmware(package1loader);
if (!target_firmware)
fatal_error("[NXBOOT]: Failed to detect target firmware!\n");
else
print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT]: Detected target firmware %ld!\n", target_firmware);
/* Read the TSEC firmware from a file, otherwise from PK1L. */ /* Read the TSEC firmware from a file, otherwise from PK1L. */
if (loader_ctx->tsecfw_path[0] != '\0') { if (loader_ctx->tsecfw_path[0] != '\0') {
tsec_fw_size = get_file_size(loader_ctx->tsecfw_path); tsec_fw_size = get_file_size(loader_ctx->tsecfw_path);
if ((tsec_fw_size != 0) && (tsec_fw_size != 0xF00)) { if ((tsec_fw_size != 0) && (tsec_fw_size != 0xF00 && tsec_fw_size != 0x2900)) {
fatal_error("[NXBOOT]: TSEC firmware from %s has a wrong size!\n", loader_ctx->tsecfw_path); fatal_error("[NXBOOT]: TSEC firmware from %s has a wrong size!\n", loader_ctx->tsecfw_path);
} else if (tsec_fw_size == 0) { } else if (tsec_fw_size == 0) {
fatal_error("[NXBOOT]: Could not read the TSEC firmware from %s!\n", loader_ctx->tsecfw_path); fatal_error("[NXBOOT]: Could not read the TSEC firmware from %s!\n", loader_ctx->tsecfw_path);
@ -280,19 +295,16 @@ uint32_t nxboot_main(void) {
fatal_error("[NXBOOT]: Could not read the TSEC firmware from %s!\n", loader_ctx->tsecfw_path); fatal_error("[NXBOOT]: Could not read the TSEC firmware from %s!\n", loader_ctx->tsecfw_path);
} }
} else { } else {
tsec_fw_size = package1_get_tsec_fw(&tsec_fw, package1loader, package1loader_size); if (!package1_get_tsec_fw(&tsec_fw, package1loader, package1loader_size)) {
if (tsec_fw_size == 0) {
fatal_error("[NXBOOT]: Failed to read the TSEC firmware from Package1loader!\n"); fatal_error("[NXBOOT]: Failed to read the TSEC firmware from Package1loader!\n");
} }
if (target_firmware >= EXOSPHERE_TARGET_FIRMWARE_620) {
tsec_fw_size = 0x2900;
} else {
tsec_fw_size = 0xF00;
}
} }
/* Find the system's target firmware. */
uint32_t target_firmware = nxboot_get_target_firmware(package1loader);
if (!target_firmware)
fatal_error("[NXBOOT]: Failed to detect target firmware!\n");
else
print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT]: Detected target firmware %ld!\n", target_firmware);
print(SCREEN_LOG_LEVEL_MANDATORY, "[NXBOOT]: Loaded firmware from eMMC...\n"); print(SCREEN_LOG_LEVEL_MANDATORY, "[NXBOOT]: Loaded firmware from eMMC...\n");
/* Setup boot configuration for Exosphère. */ /* Setup boot configuration for Exosphère. */

View file

@ -90,15 +90,19 @@ int package1_read_and_parse_boot0(void **package1loader, size_t *package1loader_
return 0; return 0;
} }
size_t package1_get_tsec_fw(void **tsec_fw, const void *package1loader, size_t package1loader_size) { bool package1_get_tsec_fw(void **tsec_fw, const void *package1loader, size_t package1loader_size) {
/* The TSEC firmware is always located at a 256-byte aligned address. */ /* The TSEC firmware is always located at a 256-byte aligned address. */
/* We're looking for its 4 first bytes. We assume its size is always 0xF00 bytes. */ /* We're looking for its 4 first bytes. */
const uint32_t *pos; const uint32_t *pos;
uintptr_t pk1l = (uintptr_t)package1loader; uintptr_t pk1l = (uintptr_t)package1loader;
for (pos = (const uint32_t *)pk1l; (uintptr_t)pos < pk1l + package1loader_size && *pos != 0xCF42004D; pos += 0x40); for (pos = (const uint32_t *)pk1l; (uintptr_t)pos < pk1l + package1loader_size; pos += 0x40) {
if (*pos == 0xCF42004D) {
(*tsec_fw) = (void *)pos;
return true;
}
}
(*tsec_fw) = (void *)pos; return false;
return 0xF00;
} }
size_t package1_get_encrypted_package1(package1_header_t **package1, uint8_t *ctr, const void *package1loader, size_t package1loader_size) { size_t package1_get_encrypted_package1(package1_header_t **package1, uint8_t *ctr, const void *package1loader, size_t package1loader_size) {

View file

@ -46,7 +46,7 @@ typedef struct {
int package1_read_and_parse_boot0(void **package1loader, size_t *package1loader_size, nx_keyblob_t *keyblobs, uint32_t *revision, FILE *boot0); int package1_read_and_parse_boot0(void **package1loader, size_t *package1loader_size, nx_keyblob_t *keyblobs, uint32_t *revision, FILE *boot0);
size_t package1_get_tsec_fw(void **tsec_fw, const void *package1loader, size_t package1loader_size); bool package1_get_tsec_fw(void **tsec_fw, const void *package1loader, size_t package1loader_size);
size_t package1_get_encrypted_package1(package1_header_t **package1, uint8_t *ctr, const void *package1loader, size_t package1loader_size); size_t package1_get_encrypted_package1(package1_header_t **package1, uint8_t *ctr, const void *package1loader, size_t package1loader_size);
/* Must be aligned to 16 bytes. */ /* Must be aligned to 16 bytes. */

View file

@ -49,7 +49,7 @@ static int tsec_dma_phys_to_flcn(bool is_imem, uint32_t flcn_offset, uint32_t ph
return tsec_dma_wait_idle(); return tsec_dma_wait_idle();
} }
int tsec_get_key(uint8_t *key, uint32_t rev, const void *tsec_fw) int tsec_get_key(uint8_t *key, uint32_t rev, const void *tsec_fw, size_t tsec_fw_size)
{ {
volatile tegra_tsec_t *tsec = tsec_get_regs(); volatile tegra_tsec_t *tsec = tsec_get_regs();
@ -82,7 +82,7 @@ int tsec_get_key(uint8_t *key, uint32_t rev, const void *tsec_fw)
/* Load firmware. */ /* Load firmware. */
tsec->FALCON_DMATRFBASE = (uint32_t)tsec_fw >> 8; tsec->FALCON_DMATRFBASE = (uint32_t)tsec_fw >> 8;
for (uint32_t addr = 0; addr < 0xF00; addr += 0x100) for (uint32_t addr = 0; addr < tsec_fw_size; addr += 0x100)
{ {
if (!tsec_dma_phys_to_flcn(true, addr, addr)) if (!tsec_dma_phys_to_flcn(true, addr, addr))
{ {

View file

@ -109,6 +109,6 @@ static inline volatile tegra_tsec_t *tsec_get_regs(void)
return (volatile tegra_tsec_t *)TSEC_BASE; return (volatile tegra_tsec_t *)TSEC_BASE;
} }
int tsec_get_key(uint8_t *key, uint32_t rev, const void *tsec_fw); int tsec_get_key(uint8_t *key, uint32_t rev, const void *tsec_fw, size_t tsec_fw_size);
#endif #endif