mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-11-09 22:56:35 +00:00
Add basic support to fusee for multiple tsec_root_keys.
This commit is contained in:
parent
3d6405be85
commit
f78fd29e38
9 changed files with 81 additions and 52 deletions
|
@ -24,11 +24,12 @@
|
|||
#define ATMOSPHERE_TARGET_FIRMWARE_500 5
|
||||
#define ATMOSPHERE_TARGET_FIRMWARE_600 6
|
||||
#define ATMOSPHERE_TARGET_FIRMWARE_620 7
|
||||
#define ATMOSPHERE_TARGET_FIRMWARE_700 8
|
||||
|
||||
#define ATMOSPHERE_TARGET_FIRMWARE_CURRENT ATMOSPHERE_TARGET_FIRMWARE_620
|
||||
#define ATMOSPHERE_TARGET_FIRMWARE_CURRENT ATMOSPHERE_TARGET_FIRMWARE_700
|
||||
|
||||
#define ATMOSPHERE_TARGET_FIRMWARE_MIN ATMOSPHERE_TARGET_FIRMWARE_100
|
||||
#define ATMOSPHERE_TARGET_FIRMWARE_MAX ATMOSPHERE_TARGET_FIRMWARE_620
|
||||
#define ATMOSPHERE_TARGET_FIRMWARE_MAX ATMOSPHERE_TARGET_FIRMWARE_700
|
||||
|
||||
/* TODO: What should this be, for release? */
|
||||
#define ATMOSPHERE_TARGET_FIRMWARE_DEFAULT_FOR_DEBUG ATMOSPHERE_TARGET_FIRMWARE_CURRENT
|
||||
|
|
|
@ -197,18 +197,19 @@ void extkeys_initialize_keyset(fusee_extkeys_t *keyset, FILE *f) {
|
|||
continue;
|
||||
}
|
||||
int matched_key = 0;
|
||||
if (strcmp(key, "tsec_root_key") == 0 || strcmp(key, "tsec_root_key_00") == 0) {
|
||||
parse_hex_key(keyset->tsec_root_key, value, sizeof(keyset->tsec_root_key));
|
||||
matched_key = 1;
|
||||
} else {
|
||||
char test_name[0x100] = {0};
|
||||
for (unsigned int i = 0; i < 0x20 && !matched_key; i++) {
|
||||
snprintf(test_name, sizeof(test_name), "master_kek_%02x", i);
|
||||
if (strcmp(key, test_name) == 0) {
|
||||
parse_hex_key(keyset->master_keks[i], value, sizeof(keyset->master_keks[i]));
|
||||
matched_key = 1;
|
||||
break;
|
||||
}
|
||||
char test_name[0x100] = {0};
|
||||
for (unsigned int i = 0; i < 0x20 && !matched_key; i++) {
|
||||
snprintf(test_name, sizeof(test_name), "tsec_root_key_%02x", i);
|
||||
if (strcmp(key, test_name) == 0) {
|
||||
parse_hex_key(keyset->tsec_root_keys[i], value, sizeof(keyset->tsec_root_keys[i]));
|
||||
matched_key = 1;
|
||||
break;
|
||||
}
|
||||
snprintf(test_name, sizeof(test_name), "master_kek_%02x", i);
|
||||
if (strcmp(key, test_name) == 0) {
|
||||
parse_hex_key(keyset->master_keks[i], value, sizeof(keyset->master_keks[i]));
|
||||
matched_key = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#include "masterkey.h"
|
||||
|
||||
typedef struct {
|
||||
unsigned char tsec_root_key[0x10];
|
||||
unsigned char tsec_root_keys[0x20][0x10];
|
||||
unsigned char master_keks[0x20][0x10];
|
||||
} fusee_extkeys_t;
|
||||
|
||||
|
|
|
@ -54,8 +54,9 @@ static const uint8_t AL16 masterkey_4x_seed[0x10] = {
|
|||
0x2D, 0xC1, 0xF4, 0x8D, 0xF3, 0x5B, 0x69, 0x33, 0x42, 0x10, 0xAC, 0x65, 0xDA, 0x90, 0x46, 0x66
|
||||
};
|
||||
|
||||
static const uint8_t AL16 new_master_kek_seeds[1][0x10] = {
|
||||
static const uint8_t AL16 new_master_kek_seeds[MASTERKEY_REVISION_700_CURRENT - MASTERKEY_REVISION_600_610][0x10] = {
|
||||
{0x37, 0x4B, 0x77, 0x29, 0x59, 0xB4, 0x04, 0x30, 0x81, 0xF6, 0xE5, 0x8C, 0x6D, 0x36, 0x17, 0x9A}, /* MasterKek seed 06. */
|
||||
{0x9A, 0x3E, 0xA9, 0xAB, 0xFD, 0x56, 0x46, 0x1C, 0x9B, 0xF6, 0x48, 0x7F, 0x5C, 0xFA, 0x09, 0x5C}, /* MasterKek seed 07. */
|
||||
};
|
||||
|
||||
static nx_dec_keyblob_t AL16 g_dec_keyblobs[32];
|
||||
|
@ -118,7 +119,7 @@ int load_package1_key(uint32_t revision) {
|
|||
}
|
||||
|
||||
/* Derive all Switch keys. */
|
||||
int derive_nx_keydata(uint32_t target_firmware, const nx_keyblob_t *keyblobs, uint32_t available_revision, const void *tsec_key, void *tsec_root_key, unsigned int *out_keygen_type) {
|
||||
int derive_nx_keydata(uint32_t target_firmware, const nx_keyblob_t *keyblobs, uint32_t available_revision, const void *tsec_key, void *tsec_root_keys, unsigned int *out_keygen_type) {
|
||||
uint8_t AL16 work_buffer[0x10];
|
||||
uint8_t AL16 zeroes[0x10] = {0};
|
||||
|
||||
|
@ -142,14 +143,31 @@ int derive_nx_keydata(uint32_t target_firmware, const nx_keyblob_t *keyblobs, ui
|
|||
|
||||
/* Do 6.2.0+ keygen. */
|
||||
if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_620) {
|
||||
if (memcmp(tsec_root_key, zeroes, 0x10) != 0) {
|
||||
/* We got a valid key from emulation. */
|
||||
set_aes_keyslot(0xC, tsec_root_key, 0x10);
|
||||
for (unsigned int rev = MASTERKEY_REVISION_620_CURRENT; rev < MASTERKEY_REVISION_MAX; rev++) {
|
||||
se_aes_ecb_decrypt_block(0xC, work_buffer, 0x10, new_master_kek_seeds[rev - MASTERKEY_REVISION_620_CURRENT], 0x10);
|
||||
uint32_t desired_keyblob;
|
||||
switch (target_firmware) {
|
||||
case ATMOSPHERE_TARGET_FIRMWARE_620:
|
||||
desired_keyblob = MASTERKEY_REVISION_620;
|
||||
break;
|
||||
case ATMOSPHERE_TARGET_FIRMWARE_700:
|
||||
desired_keyblob = MASTERKEY_REVISION_700_CURRENT;
|
||||
break;
|
||||
default:
|
||||
fatal_error("Unknown target firmware: %02x!", target_firmware);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Try emulation result. */
|
||||
for (unsigned int rev = MASTERKEY_REVISION_620; rev < MASTERKEY_REVISION_MAX; rev++) {
|
||||
void *tsec_root_key = (void *)((uintptr_t)tsec_root_keys + 0x10 * (rev - MASTERKEY_REVISION_620));
|
||||
if (memcmp(tsec_root_key, zeroes, 0x10) != 0) {
|
||||
/* We got a valid key from emulation. */
|
||||
set_aes_keyslot(0xC, tsec_root_key, 0x10);
|
||||
se_aes_ecb_decrypt_block(0xC, work_buffer, 0x10, new_master_kek_seeds[rev - MASTERKEY_REVISION_620], 0x10);
|
||||
memcpy(g_dec_keyblobs[rev].master_kek, work_buffer, 0x10);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
|
||||
if (memcmp(g_dec_keyblobs[desired_keyblob].master_kek, zeroes, 0x10) == 0) {
|
||||
/* Try reading the keys from a file. */
|
||||
const char *keyfile = fuse_get_retail_type() != 0 ? "atmosphere/prod.keys" : "atmosphere/dev.keys";
|
||||
FILE *extkey_file = fopen(keyfile, "r");
|
||||
|
@ -159,20 +177,18 @@ int derive_nx_keydata(uint32_t target_firmware, const nx_keyblob_t *keyblobs, ui
|
|||
}
|
||||
extkeys_initialize_keyset(&extkeys, extkey_file);
|
||||
fclose(extkey_file);
|
||||
|
||||
if (memcmp(extkeys.tsec_root_key, zeroes, 0x10) != 0) {
|
||||
set_aes_keyslot(0xC, extkeys.tsec_root_key, 0x10);
|
||||
for (unsigned int rev = MASTERKEY_REVISION_620_CURRENT; rev < MASTERKEY_REVISION_MAX; rev++) {
|
||||
se_aes_ecb_decrypt_block(0xC, work_buffer, 0x10, new_master_kek_seeds[rev - MASTERKEY_REVISION_620_CURRENT], 0x10);
|
||||
for (unsigned int rev = MASTERKEY_REVISION_620; rev < MASTERKEY_REVISION_MAX; rev++) {
|
||||
if (memcmp(extkeys.tsec_root_keys[rev - MASTERKEY_REVISION_620], zeroes, 0x10) != 0) {
|
||||
set_aes_keyslot(0xC, extkeys.tsec_root_keys[rev - MASTERKEY_REVISION_620], 0x10);
|
||||
se_aes_ecb_decrypt_block(0xC, work_buffer, 0x10, new_master_kek_seeds[rev - MASTERKEY_REVISION_620], 0x10);
|
||||
memcpy(g_dec_keyblobs[rev].master_kek, work_buffer, 0x10);
|
||||
}
|
||||
} else {
|
||||
for (unsigned int rev = MASTERKEY_REVISION_620_CURRENT; rev < MASTERKEY_REVISION_MAX; rev++) {
|
||||
} else {
|
||||
memcpy(g_dec_keyblobs[rev].master_kek, extkeys.master_keks[rev], 0x10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (memcmp(g_dec_keyblobs[available_revision].master_kek, zeroes, 0x10) == 0) {
|
||||
fatal_error("Error: failed to derive master_kek_%02x!", available_revision);
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
/* This is glue code to enable master key support across versions. */
|
||||
|
||||
/* TODO: Update to 0x8 on release of new master key. */
|
||||
#define MASTERKEY_REVISION_MAX 0x7
|
||||
#define MASTERKEY_REVISION_MAX 0x8
|
||||
|
||||
#define MASTERKEY_REVISION_100_230 0x00
|
||||
#define MASTERKEY_REVISION_300 0x01
|
||||
|
@ -28,7 +28,8 @@
|
|||
#define MASTERKEY_REVISION_400_410 0x03
|
||||
#define MASTERKEY_REVISION_500_510 0x04
|
||||
#define MASTERKEY_REVISION_600_610 0x05
|
||||
#define MASTERKEY_REVISION_620_CURRENT 0x06
|
||||
#define MASTERKEY_REVISION_620 0x06
|
||||
#define MASTERKEY_REVISION_700_CURRENT 0x07
|
||||
|
||||
#define MASTERKEY_NUM_NEW_DEVICE_KEYS (MASTERKEY_REVISION_MAX - MASTERKEY_REVISION_400_410)
|
||||
|
||||
|
|
|
@ -212,7 +212,7 @@ static void nxboot_configure_stratosphere(uint32_t target_firmware) {
|
|||
}
|
||||
}
|
||||
|
||||
static void nxboot_set_bootreason() {
|
||||
static void nxboot_set_bootreason(void *bootreason_base) {
|
||||
boot_reason_t boot_reason = {0};
|
||||
FILE *boot0;
|
||||
nvboot_config_table *bct;
|
||||
|
@ -264,7 +264,7 @@ static void nxboot_set_bootreason() {
|
|||
boot_reason.boot_reason_state = 0x04;
|
||||
|
||||
/* Set in memory. */
|
||||
memcpy((void *)MAILBOX_NX_BOOTLOADER_BOOT_REASON_BASE, &boot_reason, sizeof(boot_reason));
|
||||
memcpy(bootreason_base, &boot_reason, sizeof(boot_reason));
|
||||
|
||||
/* Clean up. */
|
||||
free(bct);
|
||||
|
@ -412,7 +412,12 @@ uint32_t nxboot_main(void) {
|
|||
/* Get the TSEC keys. */
|
||||
uint8_t tsec_key[0x10] = {0};
|
||||
uint8_t tsec_root_key[0x10] = {0};
|
||||
if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_620) {
|
||||
if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_700) {
|
||||
/* TODO: what to do here? */
|
||||
if (tsec_get_key(tsec_key, 1, tsec_fw, tsec_fw_size) != 0) {
|
||||
fatal_error("[NXBOOT]: Failed to get TSEC key!\n");
|
||||
}
|
||||
} else if (target_firmware == ATMOSPHERE_TARGET_FIRMWARE_620) {
|
||||
uint8_t tsec_keys[0x20] = {0};
|
||||
|
||||
/* Emulate the TSEC payload on 6.2.0+. */
|
||||
|
@ -438,9 +443,9 @@ uint32_t nxboot_main(void) {
|
|||
nxboot_configure_exosphere(target_firmware, keygen_type);
|
||||
|
||||
/* Initialize Boot Reason on older firmware versions. */
|
||||
if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < ATMOSPHERE_TARGET_FIRMWARE_400) {
|
||||
if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_400) {
|
||||
print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT]: Initializing Boot Reason...\n");
|
||||
nxboot_set_bootreason();
|
||||
nxboot_set_bootreason((void *)MAILBOX_NX_BOOTLOADER_BOOT_REASON_BASE(target_firmware));
|
||||
}
|
||||
|
||||
/* Read the warmboot firmware from a file, otherwise from Atmosphere's implementation. */
|
||||
|
|
|
@ -19,12 +19,14 @@
|
|||
|
||||
#include "utils.h"
|
||||
|
||||
#define MAILBOX_NX_BOOTLOADER_BASE 0x40002000
|
||||
#define MAILBOX_NX_BOOTLOADER_BOOT_REASON_BASE (MAILBOX_NX_BOOTLOADER_BASE + 0xE10)
|
||||
#define MAKE_MAILBOX_NX_BOOTLOADER_REG(n) MAKE_REG32(MAILBOX_NX_BOOTLOADER_BASE + n)
|
||||
#define MAILBOX_NX_BOOTLOADER_BASE_100_620 0x40002E00
|
||||
#define MAILBOX_NX_BOOTLOADER_BASE_700 0x40000000
|
||||
#define MAILBOX_NX_BOOTLOADER_BASE(targetfw) ((targetfw >= ATMOSPHERE_TARGET_FIRMWARE_700) ? (MAILBOX_NX_BOOTLOADER_BASE_700) : (MAILBOX_NX_BOOTLOADER_BASE_100_620))
|
||||
#define MAKE_MAILBOX_NX_BOOTLOADER_REG(targetfw, n) MAKE_REG32(MAILBOX_NX_BOOTLOADER_BASE(targetfw) + n)
|
||||
|
||||
#define MAILBOX_NX_BOOTLOADER_SETUP_STATE MAKE_MAILBOX_NX_BOOTLOADER_REG(0xEF8)
|
||||
#define MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE MAKE_MAILBOX_NX_BOOTLOADER_REG(0xEFC)
|
||||
#define MAILBOX_NX_BOOTLOADER_BOOT_REASON_BASE(targetfw) (MAILBOX_NX_BOOTLOADER_BASE(targetfw) + 0x10)
|
||||
#define MAILBOX_NX_BOOTLOADER_SETUP_STATE(targetfw) MAKE_MAILBOX_NX_BOOTLOADER_REG(targetfw, 0xF8)
|
||||
#define MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE(targetfw) MAKE_MAILBOX_NX_BOOTLOADER_REG(targetfw, 0xFC)
|
||||
|
||||
#define NX_BOOTLOADER_STATE_INIT 0
|
||||
#define NX_BOOTLOADER_STATE_MOVED_BOOTCONFIG 1
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "sysreg.h"
|
||||
|
||||
void nxboot_finish(uint32_t boot_memaddr) {
|
||||
uint32_t target_firmware = MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware;
|
||||
volatile tegra_se_t *se = se_get_regs();
|
||||
|
||||
/* Clear used keyslots. */
|
||||
|
@ -36,7 +37,7 @@ void nxboot_finish(uint32_t boot_memaddr) {
|
|||
|
||||
/* Lock keyslots. */
|
||||
set_aes_keyslot_flags(KEYSLOT_SWITCH_MASTERKEY, 0xFF);
|
||||
if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < ATMOSPHERE_TARGET_FIRMWARE_400) {
|
||||
if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_400) {
|
||||
set_aes_keyslot_flags(KEYSLOT_SWITCH_DEVICEKEY, 0xFF);
|
||||
} else {
|
||||
set_aes_keyslot_flags(KEYSLOT_SWITCH_4XOLDDEVICEKEY, 0xFF);
|
||||
|
@ -61,11 +62,11 @@ void nxboot_finish(uint32_t boot_memaddr) {
|
|||
se->_0x0 &= 0xFFFFFFFB;
|
||||
|
||||
/* Boot up Exosphère. */
|
||||
MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE = 0;
|
||||
if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < ATMOSPHERE_TARGET_FIRMWARE_400) {
|
||||
MAILBOX_NX_BOOTLOADER_SETUP_STATE = NX_BOOTLOADER_STATE_LOADED_PACKAGE2;
|
||||
MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE(target_firmware) = 0;
|
||||
if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_400) {
|
||||
MAILBOX_NX_BOOTLOADER_SETUP_STATE(target_firmware) = NX_BOOTLOADER_STATE_LOADED_PACKAGE2;
|
||||
} else {
|
||||
MAILBOX_NX_BOOTLOADER_SETUP_STATE = NX_BOOTLOADER_STATE_DRAM_INITIALIZED_4X;
|
||||
MAILBOX_NX_BOOTLOADER_SETUP_STATE(target_firmware) = NX_BOOTLOADER_STATE_DRAM_INITIALIZED_4X;
|
||||
}
|
||||
|
||||
/* Terminate the display. */
|
||||
|
@ -88,15 +89,15 @@ void nxboot_finish(uint32_t boot_memaddr) {
|
|||
}
|
||||
|
||||
/* Wait for Exosphère to wake up. */
|
||||
while (MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE == 0) {
|
||||
while (MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE(target_firmware) == 0) {
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
/* Signal Exosphère. */
|
||||
if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < ATMOSPHERE_TARGET_FIRMWARE_400) {
|
||||
MAILBOX_NX_BOOTLOADER_SETUP_STATE = NX_BOOTLOADER_STATE_FINISHED;
|
||||
if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_400) {
|
||||
MAILBOX_NX_BOOTLOADER_SETUP_STATE(target_firmware) = NX_BOOTLOADER_STATE_FINISHED;
|
||||
} else {
|
||||
MAILBOX_NX_BOOTLOADER_SETUP_STATE = NX_BOOTLOADER_STATE_FINISHED_4X;
|
||||
MAILBOX_NX_BOOTLOADER_SETUP_STATE(target_firmware) = NX_BOOTLOADER_STATE_FINISHED_4X;
|
||||
}
|
||||
|
||||
/* Halt ourselves in waitevent state. */
|
||||
|
|
|
@ -26,6 +26,7 @@ enum RoServiceCmd {
|
|||
Ro_Cmd_LoadNrr = 2,
|
||||
Ro_Cmd_UnloadNrr = 3,
|
||||
Ro_Cmd_Initialize = 4,
|
||||
Ro_Cmd_LoadNrrEx = 10,
|
||||
};
|
||||
|
||||
class RelocatableObjectsService final : public IServiceObject {
|
||||
|
@ -47,6 +48,7 @@ class RelocatableObjectsService final : public IServiceObject {
|
|||
Result LoadNrr(PidDescriptor pid_desc, u64 nrr_address, u64 nrr_size);
|
||||
Result UnloadNrr(PidDescriptor pid_desc, u64 nrr_address);
|
||||
Result Initialize(PidDescriptor pid_desc, CopiedHandle process_h);
|
||||
Result LoadNrrEx(PidDescriptor pid_desc, u64 nrr_address, u64 nrr_size);
|
||||
public:
|
||||
DEFINE_SERVICE_DISPATCH_TABLE {
|
||||
MakeServiceCommandMeta<Ro_Cmd_LoadNro, &RelocatableObjectsService::LoadNro>(),
|
||||
|
|
Loading…
Reference in a new issue