diff --git a/fusee/fusee-secondary/src/key_derivation.c b/fusee/fusee-secondary/src/key_derivation.c index 60a65141a..92f64b42f 100644 --- a/fusee/fusee-secondary/src/key_derivation.c +++ b/fusee/fusee-secondary/src/key_derivation.c @@ -62,12 +62,12 @@ static const uint8_t AL16 new_master_kek_seeds[MASTERKEY_REVISION_700_800 - MAST }; static const uint8_t AL16 master_kek_seeds_mariko[MASTERKEY_REVISION_910_CURRENT - MASTERKEY_REVISION_500_510][0x10] = { - { 0x77, 0x60, 0x5A, 0xD2, 0xEE, 0x6E, 0xF8, 0x3C, 0x3F, 0x72, 0xE2, 0x59, 0x9D, 0xAC, 0x5E, 0x56 }, /* Mariko MasterKek seed 05. */ - { 0x1E, 0x80, 0xB8, 0x17, 0x3E, 0xC0, 0x60, 0xAA, 0x11, 0xBE, 0x1A, 0x4A, 0xA6, 0x6F, 0xE4, 0xAE }, /* Mariko MasterKek seed 06. */ - { 0x94, 0x08, 0x67, 0xBD, 0x0A, 0x00, 0x38, 0x84, 0x11, 0xD3, 0x1A, 0xDB, 0xDD, 0x8D, 0xF1, 0x8A }, /* Mariko MasterKek seed 07. */ - { 0x5C, 0x24, 0xE3, 0xB8, 0xB4, 0xF7, 0x00, 0xC2, 0x3C, 0xFD, 0x0A, 0xCE, 0x13, 0xC3, 0xDC, 0x23 }, /* Mariko MasterKek seed 08. */ - { 0x86, 0x69, 0xF0, 0x09, 0x87, 0xC8, 0x05, 0xAE, 0xB5, 0x7B, 0x48, 0x74, 0xDE, 0x62, 0xA6, 0x13 }, /* Mariko MasterKek seed 09. */ - { 0x0E, 0x44, 0x0C, 0xED, 0xB4, 0x36, 0xC0, 0x3F, 0xAA, 0x1D, 0xAE, 0xBF, 0x62, 0xB1, 0x09, 0x82 }, /* Mariko MasterKek seed 0A. */ + {0x77, 0x60, 0x5A, 0xD2, 0xEE, 0x6E, 0xF8, 0x3C, 0x3F, 0x72, 0xE2, 0x59, 0x9D, 0xAC, 0x5E, 0x56}, /* Mariko MasterKek seed 05. */ + {0x1E, 0x80, 0xB8, 0x17, 0x3E, 0xC0, 0x60, 0xAA, 0x11, 0xBE, 0x1A, 0x4A, 0xA6, 0x6F, 0xE4, 0xAE}, /* Mariko MasterKek seed 06. */ + {0x94, 0x08, 0x67, 0xBD, 0x0A, 0x00, 0x38, 0x84, 0x11, 0xD3, 0x1A, 0xDB, 0xDD, 0x8D, 0xF1, 0x8A}, /* Mariko MasterKek seed 07. */ + {0x5C, 0x24, 0xE3, 0xB8, 0xB4, 0xF7, 0x00, 0xC2, 0x3C, 0xFD, 0x0A, 0xCE, 0x13, 0xC3, 0xDC, 0x23}, /* Mariko MasterKek seed 08. */ + {0x86, 0x69, 0xF0, 0x09, 0x87, 0xC8, 0x05, 0xAE, 0xB5, 0x7B, 0x48, 0x74, 0xDE, 0x62, 0xA6, 0x13}, /* Mariko MasterKek seed 09. */ + {0x0E, 0x44, 0x0C, 0xED, 0xB4, 0x36, 0xC0, 0x3F, 0xAA, 0x1D, 0xAE, 0xBF, 0x62, 0xB1, 0x09, 0x82}, /* Mariko MasterKek seed 0A. */ }; static nx_dec_keyblob_t AL16 g_dec_keyblobs[32]; @@ -197,7 +197,6 @@ int derive_nx_keydata_erista(uint32_t target_firmware, const nx_keyblob_t *keybl } } - if (memcmp(g_dec_keyblobs[available_revision].master_kek, zeroes, 0x10) == 0) { fatal_error("Error: failed to derive master_kek_%02x!", available_revision); } @@ -225,11 +224,12 @@ int derive_nx_keydata_erista(uint32_t target_firmware, const nx_keyblob_t *keybl } int derive_nx_keydata_mariko(uint32_t target_firmware) { - /* Derive keys for Exosphere, lock critical keyslots. */ + /* Derive the device and master keys. */ + /* NOTE: Keyslots 7 and 10 are chosen here so we don't overwrite critical key material (KEK, BEK, SBK and SSK). */ decrypt_data_into_keyslot(0xA, 0xE, devicekey_4x_seed, 0x10); decrypt_data_into_keyslot(0x7, 0xC, &master_kek_seeds_mariko[target_firmware - MASTERKEY_REVISION_600_610], 0x10); decrypt_data_into_keyslot(0x7, 0x7, masterkey_seed, 0x10); - + /* Setup master key revision, derive older master keys for use. */ return mkey_detect_revision(fuse_get_hardware_state() != 0); } diff --git a/fusee/fusee-secondary/src/masterkey.c b/fusee/fusee-secondary/src/masterkey.c index 5d8397550..8040f8a07 100644 --- a/fusee/fusee-secondary/src/masterkey.c +++ b/fusee/fusee-secondary/src/masterkey.c @@ -32,8 +32,7 @@ static uint8_t g_old_devicekeys[MASTERKEY_NUM_NEW_DEVICE_KEYS - 1][0x10]; /* TODO: Extend with new vectors, as needed. */ /* Dev unit keys. */ -static const uint8_t mkey_vectors_dev[MASTERKEY_REVISION_MAX][0x10] = -{ +static const uint8_t mkey_vectors_dev[MASTERKEY_REVISION_MAX][0x10] = { {0x46, 0x22, 0xB4, 0x51, 0x9A, 0x7E, 0xA7, 0x7F, 0x62, 0xA1, 0x1F, 0x8F, 0xC5, 0x3A, 0xDB, 0xFE}, /* Zeroes encrypted with Master Key 00. */ {0x39, 0x33, 0xF9, 0x31, 0xBA, 0xE4, 0xA7, 0x21, 0x2C, 0xDD, 0xB7, 0xD8, 0xB4, 0x4E, 0x37, 0x23}, /* Master key 00 encrypted with Master key 01. */ {0x97, 0x29, 0xB0, 0x32, 0x43, 0x14, 0x8C, 0xA6, 0x85, 0xE9, 0x5A, 0x94, 0x99, 0x39, 0xAC, 0x5D}, /* Master key 01 encrypted with Master key 02. */ @@ -44,11 +43,11 @@ static const uint8_t mkey_vectors_dev[MASTERKEY_REVISION_MAX][0x10] = {0x37, 0xAF, 0xAB, 0x35, 0x79, 0x09, 0xD9, 0x48, 0x29, 0xD2, 0xDB, 0xA5, 0xA5, 0xF5, 0x30, 0x19}, /* Master key 06 encrypted with Master key 07. */ {0xEC, 0xE1, 0x46, 0x89, 0x37, 0xFD, 0xD2, 0x15, 0x8C, 0x3F, 0x24, 0x82, 0xEF, 0x49, 0x68, 0x04}, /* Master key 07 encrypted with Master key 08. */ {0x43, 0x3D, 0xC5, 0x3B, 0xEF, 0x91, 0x02, 0x21, 0x61, 0x54, 0x63, 0x8A, 0x35, 0xE7, 0xCA, 0xEE}, /* Master key 08 encrypted with Master key 09. */ - {0x6C, 0x2E, 0xCD, 0xB3, 0x34, 0x61, 0x77, 0xF5, 0xF9, 0xB1, 0xDD, 0x61, 0x98, 0x19, 0x3E, 0xD4}, /* Master key 09 encrypted with Master key 0A. */ }; + {0x6C, 0x2E, 0xCD, 0xB3, 0x34, 0x61, 0x77, 0xF5, 0xF9, 0xB1, 0xDD, 0x61, 0x98, 0x19, 0x3E, 0xD4}, /* Master key 09 encrypted with Master key 0A. */ +}; /* Retail unit keys. */ -static const uint8_t mkey_vectors[MASTERKEY_REVISION_MAX][0x10] = -{ +static const uint8_t mkey_vectors[MASTERKEY_REVISION_MAX][0x10] = { {0x0C, 0xF0, 0x59, 0xAC, 0x85, 0xF6, 0x26, 0x65, 0xE1, 0xE9, 0x19, 0x55, 0xE6, 0xF2, 0x67, 0x3D}, /* Zeroes encrypted with Master Key 00. */ {0x29, 0x4C, 0x04, 0xC8, 0xEB, 0x10, 0xED, 0x9D, 0x51, 0x64, 0x97, 0xFB, 0xF3, 0x4D, 0x50, 0xDD}, /* Master key 00 encrypted with Master key 01. */ {0xDE, 0xCF, 0xEB, 0xEB, 0x10, 0xAE, 0x74, 0xD8, 0xAD, 0x7C, 0xF4, 0x9E, 0x62, 0xE0, 0xE8, 0x72}, /* Master key 01 encrypted with Master key 02. */ @@ -103,7 +102,7 @@ static bool is_soc_mariko() { static bool check_mkey_revision(unsigned int revision, bool is_retail) { uint8_t final_vector[0x10]; - unsigned int check_keyslot = KEYSLOT_SWITCH_MASTERKEY; + unsigned int check_keyslot = is_soc_mariko() ? KEYSLOT_SWITCH_MASTERKEY_MARIKO : KEYSLOT_SWITCH_MASTERKEY; if (revision > 0) { /* Generate old master key array. */ for (unsigned int i = revision; i > 0; i--) { @@ -160,10 +159,8 @@ unsigned int mkey_get_keyslot(unsigned int revision) { generic_panic(); } - if (is_soc_mariko()) { - return KEYSLOT_SWITCH_MASTERKEY_MARIKO; - } else if (revision == g_mkey_revision) { - return KEYSLOT_SWITCH_MASTERKEY; + if (revision == g_mkey_revision) { + return (is_soc_mariko() ? KEYSLOT_SWITCH_MASTERKEY_MARIKO : KEYSLOT_SWITCH_MASTERKEY); } else { /* Load into a temp keyslot. */ set_aes_keyslot(KEYSLOT_SWITCH_TEMPKEY, g_old_masterkeys[revision], 0x10); diff --git a/fusee/fusee-secondary/src/masterkey.h b/fusee/fusee-secondary/src/masterkey.h index 45d213970..0003c189a 100644 --- a/fusee/fusee-secondary/src/masterkey.h +++ b/fusee/fusee-secondary/src/masterkey.h @@ -46,6 +46,4 @@ void derive_new_device_keys(bool is_retail, unsigned int keygen_keyslot, unsigne void set_old_devkey(unsigned int revision, const uint8_t *key); unsigned int devkey_get_keyslot(unsigned int revision); - - #endif \ No newline at end of file diff --git a/fusee/fusee-secondary/src/nxboot.c b/fusee/fusee-secondary/src/nxboot.c index 0a15f09f7..8c3b19ebb 100644 --- a/fusee/fusee-secondary/src/nxboot.c +++ b/fusee/fusee-secondary/src/nxboot.c @@ -647,9 +647,9 @@ static void nxboot_move_bootconfig() { fclose(bcfile); /* Select the actual BootConfig size and destination address. */ - /* NOTE: Mariko relies on BPMP's inability to data abort and tries to copy 0x1000 bytes instead. */ + /* NOTE: Nintendo relies on BPMP's inability to data abort and tries to copy 0x1000 bytes. */ bootconfig_addr = 0x4003F800; - bootconfig_size = 0x800; + bootconfig_size = 0x1000; /* Copy the BootConfig into IRAM. */ memset((void *)bootconfig_addr, 0, bootconfig_size); @@ -692,11 +692,6 @@ uint32_t nxboot_main(void) { void *exosphere_memaddr; exo_emummc_config_t exo_emummc_cfg; - /* Set the start time (Mariko only). */ - if (is_mariko) { - MAILBOX_NX_BOOTLOADER_START_TIME = get_time(); - } - /* Configure emummc or mount the real NAND. */ if (!nxboot_configure_emummc(&exo_emummc_cfg)) { emummc = NULL; @@ -772,8 +767,15 @@ uint32_t nxboot_main(void) { /* Read and parse boot0. */ print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT] Reading boot0...\n"); boot0 = fopen("boot0:/", "rb"); - if ((boot0 == NULL) || (package1_read_and_parse_boot0(&package1loader, &package1loader_size, g_keyblobs, &available_revision, boot0) == -1)) { - fatal_error("[NXBOOT] Couldn't parse boot0: %s!\n", strerror(errno)); + if (boot0 == NULL) { + fatal_error("[NXBOOT] Failed to open boot0: %s!\n", strerror(errno)); + } + if (is_mariko) { + /* TODO*/ + } else { + if (package1_read_and_parse_boot0(&package1loader, &package1loader_size, g_keyblobs, &available_revision, boot0) == -1) { + fatal_error("[NXBOOT] Couldn't parse boot0: %s!\n", strerror(errno)); + } } fclose(boot0); @@ -893,16 +895,16 @@ uint32_t nxboot_main(void) { unsigned int keygen_type = 0; if (is_mariko) { if (derive_nx_keydata_mariko(target_firmware) != 0) { - fatal_error("[NXBOOT] Key derivation failed!\n"); + fatal_error("[NXBOOT] Mariko key derivation failed!\n"); } } else if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_7_0_0) { /* If on 7.0.0+, sept has already derived keys for us (Erista only). */ if (derive_nx_keydata_erista(target_firmware, g_keyblobs, available_revision, tsec_key, tsec_root_keys, &keygen_type) != 0) { - fatal_error("[NXBOOT] Key derivation failed!\n"); + fatal_error("[NXBOOT] Erista key derivation failed!\n"); } } /* Derive new device keys. */ - { + if (!is_mariko) { derive_new_device_keys(fuse_get_hardware_state() != 0, KEYSLOT_SWITCH_5XNEWDEVICEKEYGENKEY, target_firmware); } @@ -937,7 +939,7 @@ uint32_t nxboot_main(void) { } } - /* Read the warmboot firmware from a file, otherwise from Atmosphere's implementation. */ + /* Read the warmboot firmware from a file, otherwise from Atmosphere's implementation (Erista only) or from cache (Mariko only). */ if (loader_ctx->warmboot_path[0] != '\0') { warmboot_fw_size = get_file_size(loader_ctx->warmboot_path); if (warmboot_fw_size == 0) { @@ -953,19 +955,23 @@ uint32_t nxboot_main(void) { if (read_from_file(warmboot_fw, warmboot_fw_size, loader_ctx->warmboot_path) != warmboot_fw_size) { fatal_error("[NXBOOT] Could not read the warmboot firmware from %s!\n", loader_ctx->warmboot_path); } - } else if (!is_mariko) { - /* Use Atmosphere's warmboot firmware implementation (Erista only). */ - warmboot_fw_size = warmboot_bin_size; - warmboot_fw = malloc(warmboot_fw_size); + } else { + if (is_mariko) { + /* TODO */ + } else { + /* Use Atmosphere's warmboot firmware implementation. */ + warmboot_fw_size = warmboot_bin_size; + warmboot_fw = malloc(warmboot_fw_size); - if (warmboot_fw == NULL) { - fatal_error("[NXBOOT] Out of memory!\n"); - } + if (warmboot_fw == NULL) { + fatal_error("[NXBOOT] Out of memory!\n"); + } - memcpy(warmboot_fw, warmboot_bin, warmboot_fw_size); + memcpy(warmboot_fw, warmboot_bin, warmboot_fw_size); - if (warmboot_fw_size == 0) { - fatal_error("[NXBOOT] Could not read the warmboot firmware from Package1!\n"); + if (warmboot_fw_size == 0) { + fatal_error("[NXBOOT] Could not read the warmboot firmware from Package1!\n"); + } } } diff --git a/fusee/fusee-secondary/src/nxboot.h b/fusee/fusee-secondary/src/nxboot.h index bf1f8922d..ebcc878b3 100644 --- a/fusee/fusee-secondary/src/nxboot.h +++ b/fusee/fusee-secondary/src/nxboot.h @@ -36,8 +36,6 @@ typedef struct { #define MAILBOX_NX_BOOTLOADER_BASE 0x40000000 #define MAKE_MAILBOX_NX_BOOTLOADER_REG(n) MAKE_REG32(MAILBOX_NX_BOOTLOADER_BASE + n) -#define MAILBOX_NX_BOOTLOADER_START_TIME MAKE_MAILBOX_NX_BOOTLOADER_REG(0x00) -#define MAILBOX_NX_BOOTLOADER_END_TIME MAKE_MAILBOX_NX_BOOTLOADER_REG(0x04) #define MAILBOX_NX_BOOTLOADER_BOOT_REASON_BASE MAKE_MAILBOX_NX_BOOTLOADER_REG(0x10) #define MAILBOX_NX_BOOTLOADER_SETUP_STATE MAKE_MAILBOX_NX_BOOTLOADER_REG(0xF8) #define MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE MAKE_MAILBOX_NX_BOOTLOADER_REG(0xFC) diff --git a/fusee/fusee-secondary/src/nxboot_iram.c b/fusee/fusee-secondary/src/nxboot_iram.c index 6c1da0f1e..efed59c1c 100644 --- a/fusee/fusee-secondary/src/nxboot_iram.c +++ b/fusee/fusee-secondary/src/nxboot_iram.c @@ -72,11 +72,6 @@ void nxboot_finish(uint32_t boot_memaddr) { /* Signal Exosphère. */ MAILBOX_NX_BOOTLOADER_SETUP_STATE = NX_BOOTLOADER_STATE_FINISHED_4X; - /* Set the end time (Mariko only).*/ - if (is_mariko) { - MAILBOX_NX_BOOTLOADER_END_TIME = get_time(); - } - /* Halt ourselves in waitevent state. */ while (1) { FLOW_CTLR_HALT_COP_EVENTS_0 = 0x50000000; diff --git a/fusee/fusee-secondary/src/package1.c b/fusee/fusee-secondary/src/package1.c index 0ceaa2239..6b890d50e 100644 --- a/fusee/fusee-secondary/src/package1.c +++ b/fusee/fusee-secondary/src/package1.c @@ -22,7 +22,7 @@ #include "bct.h" #include "se.h" -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_erista(void **package1loader, size_t *package1loader_size, nx_keyblob_t *keyblobs, uint32_t *revision, FILE *boot0) { nvboot_config_table *bct; /* Normal firmware BCT, primary. TODO: check? */ nv_bootloader_info *pk1l_info; /* TODO: check? */ size_t fpos, pk1l_offset; @@ -90,6 +90,11 @@ int package1_read_and_parse_boot0(void **package1loader, size_t *package1loader_ return 0; } +int package1_read_and_parse_boot0_mariko(void **package1loader, size_t *package1loader_size, FILE *boot0) { + /* TODO */ + return 0; +} + 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. */ /* We're looking for its 4 first bytes. */ diff --git a/fusee/fusee-secondary/src/package1.h b/fusee/fusee-secondary/src/package1.h index 56d900767..39da2f099 100644 --- a/fusee/fusee-secondary/src/package1.h +++ b/fusee/fusee-secondary/src/package1.h @@ -44,7 +44,8 @@ typedef struct { uint8_t data[]; } package1_header_t; -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_erista(void **package1loader, size_t *package1loader_size, nx_keyblob_t *keyblobs, uint32_t *revision, FILE *boot0); +int package1_read_and_parse_boot0_mariko(void **package1loader, size_t *package1loader_size, FILE *boot0); 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);