mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-12-22 12:21:18 +00:00
fusee: support getting old tsec key from new tsec fw.
This commit is contained in:
parent
eab5e0df9b
commit
c3569ec5e2
7 changed files with 50 additions and 26 deletions
|
@ -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))
|
||||||
|
|
|
@ -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. */
|
||||||
|
|
|
@ -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");
|
||||||
|
@ -260,11 +268,18 @@ uint32_t nxboot_main(void) {
|
||||||
fatal_error("[NXBOOT]: Couldn't parse boot0: %s!\n", strerror(errno));
|
fatal_error("[NXBOOT]: Couldn't parse boot0: %s!\n", strerror(errno));
|
||||||
}
|
}
|
||||||
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. */
|
||||||
|
|
|
@ -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;
|
(*tsec_fw) = (void *)pos;
|
||||||
return 0xF00;
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
||||||
|
|
|
@ -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. */
|
||||||
|
|
|
@ -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))
|
||||||
{
|
{
|
||||||
|
|
|
@ -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
|
Loading…
Reference in a new issue