fusee: fix mariko master key derivation

This commit is contained in:
hexkyz 2020-12-19 17:54:53 +00:00 committed by SciresM
parent a05e87f78a
commit f4e763ce40
8 changed files with 53 additions and 53 deletions

View file

@ -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);
}

View file

@ -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);

View file

@ -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

View file

@ -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");
}
}
}

View file

@ -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)

View file

@ -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;

View file

@ -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. */

View file

@ -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);