mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-11-15 01:26:34 +00:00
fusee: fix mariko master key derivation
This commit is contained in:
parent
8402ea7e93
commit
a35a30efcd
8 changed files with 53 additions and 53 deletions
|
@ -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,7 +224,8 @@ 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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
|
@ -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,9 +767,16 @@ 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)) {
|
||||
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);
|
||||
|
||||
/* Find the system's target firmware. */
|
||||
|
@ -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,8 +955,11 @@ 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). */
|
||||
} else {
|
||||
if (is_mariko) {
|
||||
/* TODO */
|
||||
} else {
|
||||
/* Use Atmosphere's warmboot firmware implementation. */
|
||||
warmboot_fw_size = warmboot_bin_size;
|
||||
warmboot_fw = malloc(warmboot_fw_size);
|
||||
|
||||
|
@ -968,6 +973,7 @@ uint32_t nxboot_main(void) {
|
|||
fatal_error("[NXBOOT] Could not read the warmboot firmware from Package1!\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Patch warmboot firmware for atmosphere (Erista only). */
|
||||
if (!is_mariko && (warmboot_fw != NULL) && (warmboot_fw_size >= sizeof(warmboot_ams_header_t))) {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue