From befd912a886d6389191546738dfe4a7a5ebdc015 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Tue, 18 Jun 2019 23:23:31 -0700 Subject: [PATCH] sept: update to support 8.1.0 --- common/include/atmosphere/target_fw.h | 7 +- exosphere/src/exocfg.c | 20 +-- exosphere/src/exocfg.h | 4 +- fusee/fusee-secondary/Makefile | 17 ++- fusee/fusee-secondary/linker.ld | 10 +- fusee/fusee-secondary/src/key_derivation.c | 33 +++-- fusee/fusee-secondary/src/masterkey.c | 8 +- fusee/fusee-secondary/src/masterkey.h | 9 +- fusee/fusee-secondary/src/nxboot.c | 122 +++++++++++------- fusee/fusee-secondary/src/package2.c | 12 +- fusee/fusee-secondary/src/package2.h | 10 +- fusee/fusee-secondary/src/start.s | 22 +++- sept/sept-secondary/KEYS_template.py | 26 +++- sept/sept-secondary/Makefile | 4 +- .../key_derivation/src/key_derivation.c | 8 +- sept/sept-secondary/sept_sign.py | 13 +- sept/sept-secondary/src/key_derivation.c | 4 +- sept/sept-secondary/src/key_derivation.h | 2 +- sept/sept-secondary/src/main.c | 8 +- sept/sept-secondary/src/start.s | 19 ++- 20 files changed, 218 insertions(+), 140 deletions(-) diff --git a/common/include/atmosphere/target_fw.h b/common/include/atmosphere/target_fw.h index 4f944b293..4e368c44f 100644 --- a/common/include/atmosphere/target_fw.h +++ b/common/include/atmosphere/target_fw.h @@ -13,7 +13,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + #ifndef ATMOSPHERE_TARGET_FIRMWARE_H #define ATMOSPHERE_TARGET_FIRMWARE_H @@ -26,11 +26,12 @@ #define ATMOSPHERE_TARGET_FIRMWARE_620 7 #define ATMOSPHERE_TARGET_FIRMWARE_700 8 #define ATMOSPHERE_TARGET_FIRMWARE_800 9 +#define ATMOSPHERE_TARGET_FIRMWARE_810 10 -#define ATMOSPHERE_TARGET_FIRMWARE_CURRENT ATMOSPHERE_TARGET_FIRMWARE_800 +#define ATMOSPHERE_TARGET_FIRMWARE_CURRENT ATMOSPHERE_TARGET_FIRMWARE_810 #define ATMOSPHERE_TARGET_FIRMWARE_MIN ATMOSPHERE_TARGET_FIRMWARE_100 -#define ATMOSPHERE_TARGET_FIRMWARE_MAX ATMOSPHERE_TARGET_FIRMWARE_800 +#define ATMOSPHERE_TARGET_FIRMWARE_MAX ATMOSPHERE_TARGET_FIRMWARE_810 /* TODO: What should this be, for release? */ #define ATMOSPHERE_TARGET_FIRMWARE_DEFAULT_FOR_DEBUG ATMOSPHERE_TARGET_FIRMWARE_CURRENT diff --git a/exosphere/src/exocfg.c b/exosphere/src/exocfg.c index 7cf9488bd..974766178 100644 --- a/exosphere/src/exocfg.c +++ b/exosphere/src/exocfg.c @@ -13,7 +13,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + #include #include @@ -34,13 +34,13 @@ unsigned int exosphere_load_config(void) { generic_panic(); } g_has_loaded_config = true; - + const unsigned int magic = MAILBOX_EXOSPHERE_CONFIG.magic; - + if (magic == MAGIC_EXOSPHERE_CONFIG) { g_exosphere_cfg = MAILBOX_EXOSPHERE_CONFIG; } - + return g_exosphere_cfg.target_firmware; } @@ -48,7 +48,7 @@ unsigned int exosphere_get_target_firmware(void) { if (!g_has_loaded_config) { generic_panic(); } - + return g_exosphere_cfg.target_firmware; } @@ -56,15 +56,15 @@ unsigned int exosphere_should_perform_620_keygen(void) { if (!g_has_loaded_config) { generic_panic(); } - - return g_exosphere_cfg.target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_620 && EXOSPHERE_CHECK_FLAG(EXOSPHERE_FLAG_PERFORM_620_KEYGEN); + + return false; } unsigned int exosphere_should_override_debugmode_priv(void) { if (!g_has_loaded_config) { generic_panic(); } - + return EXOSPHERE_CHECK_FLAG(EXOSPHERE_FLAG_IS_DEBUGMODE_PRIV); } @@ -72,7 +72,7 @@ unsigned int exosphere_should_override_debugmode_user(void) { if (!g_has_loaded_config) { generic_panic(); } - + return EXOSPHERE_CHECK_FLAG(EXOSPHERE_FLAG_IS_DEBUGMODE_USER); } @@ -80,7 +80,7 @@ unsigned int exosphere_should_disable_usermode_exception_handlers(void) { if (!g_has_loaded_config) { generic_panic(); } - + return EXOSPHERE_CHECK_FLAG(EXOSPHERE_FLAG_DISABLE_USERMODE_EXCEPTION_HANDLERS); } diff --git a/exosphere/src/exocfg.h b/exosphere/src/exocfg.h index 316aa5646..16f37ec19 100644 --- a/exosphere/src/exocfg.h +++ b/exosphere/src/exocfg.h @@ -13,7 +13,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + #ifndef EXOSPHERE_EXOSPHERE_CONFIG_H #define EXOSPHERE_EXOSPHERE_CONFIG_H @@ -36,7 +36,7 @@ /* Exosphere config in DRAM shares physical/virtual mapping. */ #define MAILBOX_EXOSPHERE_CONFIG_PHYS MAILBOX_EXOSPHERE_CONFIG -#define EXOSPHERE_FLAG_PERFORM_620_KEYGEN (1 << 0u) +#define EXOSPHERE_FLAG_PERFORM_620_KEYGEN_DEPRECATED (1 << 0u) #define EXOSPHERE_FLAG_IS_DEBUGMODE_PRIV (1 << 1u) #define EXOSPHERE_FLAG_IS_DEBUGMODE_USER (1 << 2u) #define EXOSPHERE_FLAG_DISABLE_USERMODE_EXCEPTION_HANDLERS (1 << 3u) diff --git a/fusee/fusee-secondary/Makefile b/fusee/fusee-secondary/Makefile index 844dc8cf0..64fa59ba3 100644 --- a/fusee/fusee-secondary/Makefile +++ b/fusee/fusee-secondary/Makefile @@ -99,7 +99,7 @@ SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) KIPFILES := loader.kip pm.kip sm.kip ams_mitm.kip spl.kip boot.kip BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) fusee-primary.bin \ exosphere.bin lp0fw.bin rebootstub.bin thermosphere.bin splash_screen.bmp \ - sept-primary.bin sept-secondary.enc emummc.kip \ + sept-primary.bin sept-secondary_00.enc sept-secondary_01.enc emummc.kip \ $(KIPFILES) #--------------------------------------------------------------------------------- @@ -198,22 +198,27 @@ fusee_primary.bin.o fusee_primary_bin.h: fusee-primary.bin #--------------------------------------------------------------------------------- @echo $(notdir $<) @$(_bin2o) - + sept_primary.bin.o sept_primary_bin.h: sept-primary.bin #--------------------------------------------------------------------------------- @echo $(notdir $<) @$(_bin2o) - -sept_secondary.enc.o sept_secondary_enc.h: sept-secondary.enc + +sept_secondary_00.enc.o sept_secondary_00.h: sept-secondary_00.enc #--------------------------------------------------------------------------------- @echo $(notdir $<) @$(_bin2o) - + +sept_secondary_01.enc.o sept_secondary_01_enc.h: sept-secondary_01.enc +#--------------------------------------------------------------------------------- + @echo $(notdir $<) + @$(_bin2o) + %.bin.o %_bin.h: %.bin #--------------------------------------------------------------------------------- @echo $(notdir $<) @$(bin2o) - + %.bmp.o %_bmp.h: %.bmp #--------------------------------------------------------------------------------- @echo $(notdir $<) diff --git a/fusee/fusee-secondary/linker.ld b/fusee/fusee-secondary/linker.ld index 26e8cc445..54a44b73d 100644 --- a/fusee/fusee-secondary/linker.ld +++ b/fusee/fusee-secondary/linker.ld @@ -55,7 +55,7 @@ SECTIONS . = ALIGN(32); PROVIDE (__chainloader_end__ = ABSOLUTE(.)); } >low_iram :NONE - + .nxboot_loadable : { . = ALIGN(32); @@ -157,7 +157,7 @@ SECTIONS CONSTRUCTORS . = ALIGN(32); } >main - + __data_end__ = ABSOLUTE(.); PROVIDE (__total_size__ = (__data_end__ - __start__)); @@ -236,8 +236,10 @@ SECTIONS PROVIDE(__rebootstub_bin_size__ = rebootstub_bin_end - rebootstub_bin); PROVIDE(__sept_primary_bin_start__ = sept_primary_bin - __start__); PROVIDE(__sept_primary_bin_size__ = sept_primary_bin_end - sept_primary_bin); - PROVIDE(__sept_secondary_enc_start__ = sept_secondary_enc - __start__); - PROVIDE(__sept_secondary_enc_size__ = sept_secondary_enc_end - sept_secondary_enc); + PROVIDE(__sept_secondary_00_enc_start__ = sept_secondary_00_enc - __start__); + PROVIDE(__sept_secondary_00_enc_size__ = sept_secondary_00_enc_end - sept_secondary_00_enc); + PROVIDE(__sept_secondary_01_enc_start__ = sept_secondary_01_enc - __start__); + PROVIDE(__sept_secondary_01_enc_size__ = sept_secondary_01_enc_end - sept_secondary_01_enc); PROVIDE(__sm_kip_start__ = sm_kip - __start__); PROVIDE(__sm_kip_size__ = sm_kip_end - sm_kip); PROVIDE(__spl_kip_start__ = spl_kip - __start__); diff --git a/fusee/fusee-secondary/src/key_derivation.c b/fusee/fusee-secondary/src/key_derivation.c index 2a13a7c2c..d4de912be 100644 --- a/fusee/fusee-secondary/src/key_derivation.c +++ b/fusee/fusee-secondary/src/key_derivation.c @@ -54,7 +54,8 @@ 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[MASTERKEY_REVISION_700_CURRENT - MASTERKEY_REVISION_600_610][0x10] = { +/* TODO: Bother adding 8.1.0 here? We'll never call into here... */ +static const uint8_t AL16 new_master_kek_seeds[MASTERKEY_REVISION_700_800 - 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. */ }; @@ -93,17 +94,17 @@ static int decrypt_keyblob(const nx_keyblob_t *keyblobs, uint32_t revision, uint if (get_keyblob(&keyblob, revision, keyblobs, available_revision) != 0) { return -1; } - + se_aes_ecb_decrypt_block(0xD, work_buffer, 0x10, keyblob_seeds[revision], 0x10); decrypt_data_into_keyslot(keyslot, 0xE, work_buffer, 0x10); decrypt_data_into_keyslot(0xB, keyslot, keyblob_mac_seed, 0x10); - + /* Validate keyblob. */ se_compute_aes_128_cmac(0xB, work_buffer, 0x10, keyblob.mac + sizeof(keyblob.mac), sizeof(keyblob) - sizeof(keyblob.mac)); if (safe_memcmp(keyblob.mac, work_buffer, 0x10)) { return -1; } - + /* Decrypt keyblob. */ se_aes_ctr_crypt(keyslot, &g_dec_keyblobs[revision], sizeof(g_dec_keyblobs[revision]), keyblob.data, sizeof(keyblob.data), keyblob.ctr, sizeof(keyblob.ctr)); return 0; @@ -113,7 +114,7 @@ int load_package1_key(uint32_t revision) { if (revision > MASTERKEY_REVISION_600_610) { return -1; } - + set_aes_keyslot(0xB, g_dec_keyblobs[revision].package1_key, 0x10); return 0; } @@ -122,17 +123,17 @@ int load_package1_key(uint32_t revision) { 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}; - + /* Initialize keygen type. */ *out_keygen_type = 0; /* TODO: Set keyslot flags properly in preparation of derivation. */ set_aes_keyslot_flags(0xE, 0x15); set_aes_keyslot_flags(0xD, 0x15); - + /* Set the TSEC key. */ set_aes_keyslot(0xD, tsec_key, 0x10); - + /* Decrypt all keyblobs, setting keyslot 0xF correctly. */ for (unsigned int rev = 0; rev <= MASTERKEY_REVISION_600_610; rev++) { int ret = decrypt_keyblob(keyblobs, rev, available_revision); @@ -150,13 +151,16 @@ int derive_nx_keydata(uint32_t target_firmware, const nx_keyblob_t *keyblobs, ui break; case ATMOSPHERE_TARGET_FIRMWARE_700: case ATMOSPHERE_TARGET_FIRMWARE_800: - desired_keyblob = MASTERKEY_REVISION_700_CURRENT; + desired_keyblob = MASTERKEY_REVISION_700_800; + break; + case ATMOSPHERE_TARGET_FIRMWARE_810: + desired_keyblob = MASTERKEY_REVISION_810_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)); @@ -167,7 +171,7 @@ int derive_nx_keydata(uint32_t target_firmware, const nx_keyblob_t *keyblobs, ui memcpy(g_dec_keyblobs[rev].master_kek, work_buffer, 0x10); } } - + 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"; @@ -188,13 +192,13 @@ int derive_nx_keydata(uint32_t target_firmware, const nx_keyblob_t *keyblobs, ui } } } - - + + if (memcmp(g_dec_keyblobs[available_revision].master_kek, zeroes, 0x10) == 0) { fatal_error("Error: failed to derive master_kek_%02x!", available_revision); } } - + /* Clear the SBK. */ clear_aes_keyslot(0xE); @@ -225,6 +229,7 @@ int derive_nx_keydata(uint32_t target_firmware, const nx_keyblob_t *keyblobs, ui case ATMOSPHERE_TARGET_FIRMWARE_620: case ATMOSPHERE_TARGET_FIRMWARE_700: case ATMOSPHERE_TARGET_FIRMWARE_800: + case ATMOSPHERE_TARGET_FIRMWARE_810: decrypt_data_into_keyslot(0xA, 0xF, devicekey_4x_seed, 0x10); decrypt_data_into_keyslot(0xF, 0xF, devicekey_seed, 0x10); decrypt_data_into_keyslot(0xE, 0xC, masterkey_4x_seed, 0x10); diff --git a/fusee/fusee-secondary/src/masterkey.c b/fusee/fusee-secondary/src/masterkey.c index 28b6e3ee4..d2c5a06e7 100644 --- a/fusee/fusee-secondary/src/masterkey.c +++ b/fusee/fusee-secondary/src/masterkey.c @@ -13,7 +13,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + #include #include #include @@ -39,6 +39,7 @@ static const uint8_t mkey_vectors_dev[MASTERKEY_REVISION_MAX][0x10] = {0x78, 0xD5, 0xF1, 0x20, 0x3D, 0x16, 0xE9, 0x30, 0x32, 0x27, 0x34, 0x6F, 0xCF, 0xE0, 0x27, 0xDC}, /* Master key 04 encrypted with Master key 05. */ {0x6F, 0xD2, 0x84, 0x1D, 0x05, 0xEC, 0x40, 0x94, 0x5F, 0x18, 0xB3, 0x81, 0x09, 0x98, 0x8D, 0x4E}, /* Master key 05 encrypted with Master key 06. */ {0x37, 0xAF, 0xAB, 0x35, 0x79, 0x09, 0xD9, 0x48, 0x29, 0xD2, 0xDB, 0xA5, 0xA5, 0xF5, 0x30, 0x19}, /* Master key 06 encrypted with Master key 07. */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* TODO: Master key 07 encrypted with Master key 08. */ }; /* Retail unit keys. */ @@ -52,6 +53,7 @@ static const uint8_t mkey_vectors[MASTERKEY_REVISION_MAX][0x10] = {0xEB, 0xF5, 0x6F, 0x83, 0x61, 0x9E, 0xF8, 0xFA, 0xE0, 0x87, 0xD7, 0xA1, 0x4E, 0x25, 0x36, 0xEE}, /* Master key 04 encrypted with Master key 05. */ {0x1E, 0x1E, 0x22, 0xC0, 0x5A, 0x33, 0x3C, 0xB9, 0x0B, 0xA9, 0x03, 0x04, 0xBA, 0xDB, 0x07, 0x57}, /* Master key 05 encrypted with Master key 06. */ {0xA4, 0xD4, 0x52, 0x6F, 0xD1, 0xE4, 0x36, 0xAA, 0x9F, 0xCB, 0x61, 0x27, 0x1C, 0x67, 0x65, 0x1F}, /* Master key 06 encrypted with Master key 07. */ + {0xEA, 0x60, 0xB3, 0xEA, 0xCE, 0x8F, 0x24, 0x46, 0x7D, 0x33, 0x9C, 0xD1, 0xBC, 0x24, 0x98, 0x29}, /* Master key 07 encrypted with Master key 08. */ }; static bool check_mkey_revision(unsigned int revision, bool is_retail) { @@ -80,7 +82,7 @@ int mkey_detect_revision(bool is_retail) { if (g_determined_mkey_revision) { generic_panic(); } - + for (unsigned int rev = 0; rev < MASTERKEY_REVISION_MAX; rev++) { if (check_mkey_revision(rev, is_retail)) { g_determined_mkey_revision = true; @@ -88,7 +90,7 @@ int mkey_detect_revision(bool is_retail) { break; } } - + /* We must have determined the master key, or we're not running on a Switch. */ if (!g_determined_mkey_revision) { return -1; diff --git a/fusee/fusee-secondary/src/masterkey.h b/fusee/fusee-secondary/src/masterkey.h index 332dbcec5..0ee44eca4 100644 --- a/fusee/fusee-secondary/src/masterkey.h +++ b/fusee/fusee-secondary/src/masterkey.h @@ -13,14 +13,14 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + #ifndef FUSEE_MASTERKEY_H #define FUSEE_MASTERKEY_H /* 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 0x8 +/* TODO: Update to 0xA on release of new master key. */ +#define MASTERKEY_REVISION_MAX 0x9 #define MASTERKEY_REVISION_100_230 0x00 #define MASTERKEY_REVISION_300 0x01 @@ -29,7 +29,8 @@ #define MASTERKEY_REVISION_500_510 0x04 #define MASTERKEY_REVISION_600_610 0x05 #define MASTERKEY_REVISION_620 0x06 -#define MASTERKEY_REVISION_700_CURRENT 0x07 +#define MASTERKEY_REVISION_700_800 0x07 +#define MASTERKEY_REVISION_810_CURRENT 0x08 #define MASTERKEY_NUM_NEW_DEVICE_KEYS (MASTERKEY_REVISION_MAX - MASTERKEY_REVISION_400_410) diff --git a/fusee/fusee-secondary/src/nxboot.c b/fusee/fusee-secondary/src/nxboot.c index cc7f1cacd..2146a7062 100644 --- a/fusee/fusee-secondary/src/nxboot.c +++ b/fusee/fusee-secondary/src/nxboot.c @@ -13,7 +13,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + #include #include #include @@ -53,7 +53,8 @@ #define u8 uint8_t #define u32 uint32_t #include "exosphere_bin.h" -#include "sept_secondary_enc.h" +#include "sept_secondary_00_enc.h" +#include "sept_secondary_01_enc.h" #include "lp0fw_bin.h" #include "emummc_kip.h" #include "lib/log.h" @@ -207,8 +208,15 @@ static uint32_t nxboot_get_target_firmware(const void *package1loader) { } case 0x0F: /* 7.0.0 - 7.0.1 */ return ATMOSPHERE_TARGET_FIRMWARE_700; - case 0x10: /* 8.0.0 */ - return ATMOSPHERE_TARGET_FIRMWARE_800; + case 0x10: { /* 8.0.0 - 8.1.0 */ + if (memcmp(package1loader_header->build_timestamp, "20190314", 8) == 0) { + return ATMOSPHERE_TARGET_FIRMWARE_800; + } else if (memcmp(package1loader_header->build_timestamp, "20190531", 8) == 0) { + return ATMOSPHERE_TARGET_FIRMWARE_810; + } else { + fatal_error("[NXBOOT] Unable to identify package1!\n"); + } + } default: fatal_error("[NXBOOT] Unable to identify package1!\n"); } @@ -216,7 +224,7 @@ static uint32_t nxboot_get_target_firmware(const void *package1loader) { static bool nxboot_configure_emummc(exo_emummc_config_t *exo_emummc_config) { emummc_config_t emummc_cfg = {.enabled = false, .id = 0, .sector = -1, .path = "", .nintendo_path = ""}; - + char *emummc_ini = calloc(1, 0x10000); if (!read_from_file(emummc_ini, 0xFFFF, "emummc/emummc.ini")) { free(emummc_ini); @@ -237,12 +245,12 @@ static bool nxboot_configure_emummc(exo_emummc_config_t *exo_emummc_config) { exo_emummc_config->base_cfg.fs_version = FS_VER_1_0_0; /* Will be filled out later. */ strncpy(exo_emummc_config->emu_dir_path, emummc_cfg.nintendo_path, sizeof(exo_emummc_config->emu_dir_path)); exo_emummc_config->emu_dir_path[sizeof(exo_emummc_config->emu_dir_path) - 1] = '\0'; - + if (emummc_cfg.enabled) { if (emummc_cfg.sector != -1) { exo_emummc_config->base_cfg.type = EMUMMC_TYPE_PARTITION; exo_emummc_config->partition_cfg.start_sector = emummc_cfg.sector; - + /* Mount emulated NAND from SD card partition. */ if (nxfs_mount_emummc_partition(emummc_cfg.sector) < 0) { fatal_error("[NXBOOT] Failed to mount EmuMMC from SD card partition!\n"); @@ -258,24 +266,24 @@ static bool nxboot_configure_emummc(exo_emummc_config_t *exo_emummc_config) { char emummc_boot0_path[0x300 + 1] = {0}; char emummc_boot1_path[0x300 + 1] = {0}; char emummc_rawnand_path[0x300 + 1] = {0}; - + /* Prepare base folder path. */ snprintf(emummc_path, sizeof(emummc_path) - 1, "%s/%s", emummc_cfg.path, "eMMC"); - + /* Check if eMMC folder is present. */ if (!is_valid_folder(emummc_path)) { fatal_error("[NXBOOT] Failed to find EmuMMC eMMC folder!\n"); } - + /* Prepare expected file paths. */ snprintf(emummc_boot0_path, sizeof(emummc_boot0_path) - 1, "%s/%s", emummc_path, "boot0"); snprintf(emummc_boot1_path, sizeof(emummc_boot1_path) - 1, "%s/%s", emummc_path, "boot1"); - + /* Check if boot0 and boot1 image files are present. */ if (!is_valid_file(emummc_boot0_path) || !is_valid_file(emummc_boot1_path)) { fatal_error("[NXBOOT] Failed to find EmuMMC boot0/boot1 image files!\n"); } - + /* Find raw image files (single or multi part). */ for (int i = 0; i < 64; i++) { snprintf(emummc_rawnand_path, sizeof(emummc_rawnand_path) - 1, "%s/%02d", emummc_path, i); @@ -295,7 +303,7 @@ static bool nxboot_configure_emummc(exo_emummc_config_t *exo_emummc_config) { if ((num_parts == 0) || (part_limit == 0)) { fatal_error("[NXBOOT] Failed to find EmuMMC raw image files!\n"); } - + /* Mount emulated NAND from files. */ if (nxfs_mount_emummc_file(emummc_path, num_parts, part_limit) < 0) { fatal_error("[NXBOOT] Failed to mount EmuMMC from files!\n"); @@ -304,7 +312,7 @@ static bool nxboot_configure_emummc(exo_emummc_config_t *exo_emummc_config) { fatal_error("[NXBOOT] Invalid EmuMMC setting!\n"); } } - + return emummc_cfg.enabled; } @@ -337,7 +345,7 @@ static void nxboot_configure_stratosphere(uint32_t target_firmware) { if (ini_parse_string(get_loader_ctx()->bct0, stratosphere_ini_handler, &strat_cfg) < 0) { fatal_error("[NXBOOT] Failed to parse BCT.ini!\n"); } - + /* Enable NOGC patches if the user requested it, or if the user is booting into 4.0.0+ with 3.0.2- fuses. */ if (strat_cfg.has_nogc_config) { if (strat_cfg.enable_nogc) { @@ -353,7 +361,7 @@ static void nxboot_configure_stratosphere(uint32_t target_firmware) { static void nxboot_set_bootreason(void *bootreason_base) { boot_reason_t boot_reason = {0}; - FILE *boot0; + FILE *boot0; nvboot_config_table *bct; nv_bootloader_info *bootloader_info; @@ -362,7 +370,7 @@ static void nxboot_set_bootreason(void *bootreason_base) { if (bct == NULL) { fatal_error("[NXBOOT] Out of memory!\n"); } - + /* Open boot0. */ boot0 = fopen("boot0:/", "rb"); if (boot0 == NULL) { @@ -373,25 +381,25 @@ static void nxboot_set_bootreason(void *bootreason_base) { if (fread(bct, sizeof(nvboot_config_table), 1, boot0) == 0) { fatal_error("[NXBOOT] Failed to read the BCT!\n"); } - + /* Close boot0. */ fclose(boot0); - + /* Populate bootloader parameters. */ bootloader_info = &bct->bootloader[0]; boot_reason.bootloader_version = bootloader_info->version; boot_reason.bootloader_start_block = bootloader_info->start_blk; boot_reason.bootloader_start_page = bootloader_info->start_page; boot_reason.bootloader_attribute = bootloader_info->attribute; - + uint8_t power_key_intr = 0; uint8_t rtc_intr = 0; i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_ONOFFIRQ, &power_key_intr, 1); i2c_query(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_REG_RTCINT, &rtc_intr, 1); - + /* Set PMIC value. */ boot_reason.boot_reason_value = ((rtc_intr << 0x08) | power_key_intr); - + /* TODO: Find out what these mean. */ if (power_key_intr & 0x80) boot_reason.boot_reason_state = 0x01; @@ -401,10 +409,10 @@ static void nxboot_set_bootreason(void *bootreason_base) { boot_reason.boot_reason_state = 0x03; else if (rtc_intr & 0x04) boot_reason.boot_reason_state = 0x04; - + /* Set in memory. */ memcpy(bootreason_base, &boot_reason, sizeof(boot_reason)); - + /* Clean up. */ free(bct); } @@ -414,13 +422,13 @@ static void nxboot_move_bootconfig() { void *bootconfig; uint32_t bootconfig_addr; uint32_t bootconfig_size; - + /* Allocate memory for reading BootConfig. */ bootconfig = memalign(0x1000, 0x4000); if (bootconfig == NULL) { fatal_error("[NXBOOT] Out of memory!\n"); } - + /* Get BootConfig from the Package2 partition. */ bcfile = fopen("bcpkg21:/", "rb"); if (bcfile == NULL) { @@ -431,15 +439,15 @@ static void nxboot_move_bootconfig() { fatal_error("[NXBOOT] Failed to read BootConfig!\n"); } fclose(bcfile); - + /* Select the actual BootConfig size and destination address. */ bootconfig_addr = (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < ATMOSPHERE_TARGET_FIRMWARE_600) ? 0x4003D000 : 0x4003F800; bootconfig_size = (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < ATMOSPHERE_TARGET_FIRMWARE_400) ? 0x3000 : 0x1000; - + /* Copy the BootConfig into IRAM. */ memset((void *)bootconfig_addr, 0, bootconfig_size); memcpy((void *)bootconfig_addr, bootconfig, bootconfig_size); - + /* Clean up. */ free(bootconfig); } @@ -459,6 +467,8 @@ uint32_t nxboot_main(void) { size_t package2_size; void *tsec_fw; size_t tsec_fw_size; + const void *sept_secondary_enc = NULL; + size_t sept_secondary_enc_size = 0; void *warmboot_fw; size_t warmboot_fw_size; void *warmboot_memaddr; @@ -470,7 +480,7 @@ uint32_t nxboot_main(void) { FILE *boot0, *pk2file; void *exosphere_memaddr; exo_emummc_config_t exo_emummc_cfg; - + /* Configure emummc or mount the real NAND. */ if (!nxboot_configure_emummc(&exo_emummc_cfg)) { emummc = NULL; @@ -542,7 +552,7 @@ uint32_t nxboot_main(void) { fatal_error("[NXBOOT] Failed to read Package2!\n"); } fclose(pk2file); - + /* Read and parse boot0. */ print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT] Reading boot0...\n"); boot0 = fopen("boot0:/", "rb"); @@ -550,7 +560,7 @@ uint32_t nxboot_main(void) { fatal_error("[NXBOOT] Couldn't parse boot0: %s!\n", strerror(errno)); } fclose(boot0); - + /* Find the system's target firmware. */ uint32_t target_firmware = nxboot_get_target_firmware(package1loader); if (!target_firmware) @@ -561,26 +571,42 @@ uint32_t nxboot_main(void) { /* Read the TSEC firmware from a file, otherwise from PK1L. */ if (loader_ctx->tsecfw_path[0] != '\0') { tsec_fw_size = get_file_size(loader_ctx->tsecfw_path); - if ((tsec_fw_size != 0) && (tsec_fw_size != 0xF00 && tsec_fw_size != 0x2900 && tsec_fw_size != 0x3000)) { + if ((tsec_fw_size != 0) && (tsec_fw_size != 0xF00 && tsec_fw_size != 0x2900 && tsec_fw_size != 0x3000 && tsec_fw_size != 0x3300)) { fatal_error("[NXBOOT] TSEC firmware from %s has a wrong size!\n", loader_ctx->tsecfw_path); } else if (tsec_fw_size == 0) { fatal_error("[NXBOOT] Could not read the TSEC firmware from %s!\n", loader_ctx->tsecfw_path); } - + /* Allocate memory for the TSEC firmware. */ tsec_fw = memalign(0x100, tsec_fw_size); - + if (tsec_fw == NULL) { fatal_error("[NXBOOT] Out of memory!\n"); } if (read_from_file(tsec_fw, tsec_fw_size, loader_ctx->tsecfw_path) != tsec_fw_size) { fatal_error("[NXBOOT] Could not read the TSEC firmware from %s!\n", loader_ctx->tsecfw_path); } + + if (tsec_fw_size == 0x3000) { + sept_secondary_enc = sept_secondary_00_enc; + sept_secondary_enc_size = sept_secondary_00_enc_size; + } else if (tsec_fw_size == 0x3300) { + sept_secondary_enc = sept_secondary_01_enc; + sept_secondary_enc_size = sept_secondary_01_enc_size; + } else { + fatal_error("[NXBOOT] Unable to identify sept revision to run."); + } } else { if (!package1_get_tsec_fw(&tsec_fw, package1loader, package1loader_size)) { fatal_error("[NXBOOT] Failed to read the TSEC firmware from Package1loader!\n"); } - if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_700) { + if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_810) { + sept_secondary_enc = sept_secondary_01_enc; + sept_secondary_enc_size = sept_secondary_01_enc_size; + tsec_fw_size = 0x3300; + } else if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_700) { + sept_secondary_enc = sept_secondary_00_enc; + sept_secondary_enc_size = sept_secondary_00_enc_size; tsec_fw_size = 0x3000; } else if (target_firmware == ATMOSPHERE_TARGET_FIRMWARE_620) { tsec_fw_size = 0x2900; @@ -606,10 +632,10 @@ uint32_t nxboot_main(void) { get_and_clear_has_run_sept(); } else if (target_firmware == ATMOSPHERE_TARGET_FIRMWARE_620) { uint8_t tsec_keys[0x20] = {0}; - + /* Emulate the TSEC payload on 6.2.0+. */ smmu_emulate_tsec((void *)tsec_keys, package1loader, package1loader_size, package1loader); - + /* Copy back the keys. */ memcpy((void *)tsec_key, (void *)tsec_keys, 0x10); memcpy((void *)tsec_root_keys, (void *)tsec_keys + 0x10, 0x10); @@ -619,11 +645,11 @@ uint32_t nxboot_main(void) { fatal_error("[NXBOOT] Failed to get TSEC key!\n"); } } - + //fatal_error("Ran sept!"); /* Display splash screen. */ display_splash_screen_bmp(loader_ctx->custom_splash_path, (void *)0xC0000000); - + /* Derive keydata. If on 7.0.0+, sept has already derived keys for us. */ unsigned int keygen_type = 0; if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_700) { @@ -665,27 +691,27 @@ uint32_t nxboot_main(void) { if (warmboot_fw == NULL) { fatal_error("[NXBOOT] Out of memory!\n"); } - + memcpy(warmboot_fw, lp0fw_bin, warmboot_fw_size); - + if (warmboot_fw_size == 0) { fatal_error("[NXBOOT] Could not read the warmboot firmware from Package1!\n"); } } - + /* Patch warmboot firmware for atmosphere. */ if (warmboot_fw != NULL && warmboot_fw_size >= sizeof(warmboot_ams_header_t)) { warmboot_ams_header_t *ams_header = (warmboot_ams_header_t *)warmboot_fw; if (ams_header->ams_metadata.magic == WARMBOOT_MAGIC) { /* Set target firmware */ ams_header->ams_metadata.target_firmware = target_firmware; - + /* Set RSA modulus */ const uint8_t *pkc_modulus = fuse_get_retail_type() != 0 ? retail_pkc_modulus : dev_pkc_modulus; memcpy(ams_header->rsa_modulus, pkc_modulus, sizeof(ams_header->rsa_modulus)); } } - + /* Select the right address for the warmboot firmware. */ if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < ATMOSPHERE_TARGET_FIRMWARE_400) { @@ -708,7 +734,7 @@ uint32_t nxboot_main(void) { } print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT] Rebuilding package2...\n"); - + /* Parse stratosphere config. */ nxboot_configure_stratosphere(MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware); @@ -770,10 +796,10 @@ uint32_t nxboot_main(void) { free(package2); print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT] Powering on the CCPLEX...\n"); - + /* Unmount everything. */ nxfs_end(); - + /* Return the memory address for booting CPU0. */ return (uint32_t)exosphere_memaddr; } diff --git a/fusee/fusee-secondary/src/package2.c b/fusee/fusee-secondary/src/package2.c index de7af5b70..d9bd92ddc 100644 --- a/fusee/fusee-secondary/src/package2.c +++ b/fusee/fusee-secondary/src/package2.c @@ -13,7 +13,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + #include #include #include @@ -66,7 +66,7 @@ void package2_rebuild_and_copy(package2_header_t *package2, uint32_t target_firm if (thermosphere_size != 0 && package2->metadata.section_sizes[PACKAGE2_SECTION_UNUSED] != 0) { fatal_error(u8"Error: Package2 has no unused section for Thermosphère!\n"); } - + /* Load Kernel from SD, if possible. */ { size_t sd_kernel_size = get_file_size("atmosphere/kernel.bin"); @@ -88,13 +88,13 @@ void package2_rebuild_and_copy(package2_header_t *package2, uint32_t target_firm /* Perform any patches we want to the NX kernel. */ package2_patch_kernel(kernel, kernel_size, is_sd_kernel, (void *)&orig_ini1); - + /* Ensure we know where embedded INI is if present, and we don't if not. */ - if ((target_firmware < ATMOSPHERE_TARGET_FIRMWARE_800 && orig_ini1 != NULL) || + if ((target_firmware < ATMOSPHERE_TARGET_FIRMWARE_800 && orig_ini1 != NULL) || (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_800 && orig_ini1 == NULL)) { fatal_error("Error: inappropriate kernel embedded ini context"); } - + print(SCREEN_LOG_LEVEL_DEBUG, "Rebuilding the INI1 section...\n"); if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_800) { package2_get_src_section((void *)&orig_ini1, package2, PACKAGE2_SECTION_INI1); @@ -232,7 +232,7 @@ static bool package2_validate_metadata(package2_meta_t *metadata, uint8_t data[] /* Perform version checks. */ /* We will be compatible with all package2s released before current, but not newer ones. */ - if (metadata->version_max >= PACKAGE2_MINVER_THEORETICAL && metadata->version_min < PACKAGE2_MAXVER_700_CURRENT) { + if (metadata->version_max >= PACKAGE2_MINVER_THEORETICAL && metadata->version_min < PACKAGE2_MAXVER_810_CURRENT) { return true; } diff --git a/fusee/fusee-secondary/src/package2.h b/fusee/fusee-secondary/src/package2.h index 1b3d6d492..7427ce85c 100644 --- a/fusee/fusee-secondary/src/package2.h +++ b/fusee/fusee-secondary/src/package2.h @@ -13,7 +13,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + #ifndef FUSEE_PACKAGE2_H #define FUSEE_PACKAGE2_H @@ -36,7 +36,8 @@ #define PACKAGE2_MAXVER_500_510 0x7 #define PACKAGE2_MAXVER_600_610 0x8 #define PACKAGE2_MAXVER_620 0x9 -#define PACKAGE2_MAXVER_700_CURRENT 0xA +#define PACKAGE2_MAXVER_700_800 0xA +#define PACKAGE2_MAXVER_810_CURRENT 0xB #define PACKAGE2_MINVER_100 0x3 #define PACKAGE2_MINVER_200 0x4 @@ -46,7 +47,8 @@ #define PACKAGE2_MINVER_500_510 0x8 #define PACKAGE2_MINVER_600_610 0x9 #define PACKAGE2_MINVER_620 0xA -#define PACKAGE2_MINVER_700_CURRENT 0xB +#define PACKAGE2_MINVER_700_800 0xB +#define PACKAGE2_MINVER_810_CURRENT 0xC #define NX_BOOTLOADER_PACKAGE2_LOAD_ADDRESS ((void *)(0xA9800000ull)) @@ -79,7 +81,7 @@ typedef struct { /* Package2 can be encrypted or unencrypted for these functions: */ static inline size_t package2_meta_get_size(const package2_meta_t *metadata) { - return metadata->ctr_dwords[0] ^ metadata->ctr_dwords[2] ^ metadata->ctr_dwords[3]; + return metadata->ctr_dwords[0] ^ metadata->ctr_dwords[2] ^ metadata->ctr_dwords[3]; } static inline uint8_t package2_meta_get_header_version(const package2_meta_t *metadata) { diff --git a/fusee/fusee-secondary/src/start.s b/fusee/fusee-secondary/src/start.s index f6da2a185..c93b588b1 100644 --- a/fusee/fusee-secondary/src/start.s +++ b/fusee/fusee-secondary/src/start.s @@ -14,7 +14,7 @@ * along with this program. If not, see . */ #include - + .macro CLEAR_GPR_REG_ITER mov r\@, #0 .endm @@ -27,7 +27,7 @@ .type _start, %function _start: b _crt0 - + .word (_metadata - _start) _crt0: @@ -67,7 +67,7 @@ _crt0: ldr r0, [r0] ldr r1, [r1] b main - + /* Fusee-secondary header. */ .align 5 _metadata: @@ -168,12 +168,20 @@ _content_headers: .asciz "sept_primary" .align 5 -/* sept_secondary content header */ -.word __sept_secondary_enc_start__ -.word __sept_secondary_enc_size__ +/* sept_secondary 00 content header */ +.word __sept_secondary_00_enc_start__ +.word __sept_secondary_00_enc_size__ .word CONTENT_TYPE_SP2 .word 0xCCCCCCCC -.asciz "sept_secondary" +.asciz "sept_secondary_00" +.align 5 + +/* sept_secondary 01 content header */ +.word __sept_secondary_01_enc_start__ +.word __sept_secondary_01_enc_size__ +.word CONTENT_TYPE_SP2 +.word 0xCCCCCCCC +.asciz "sept_secondary_01" .align 5 /* sm content header */ diff --git a/sept/sept-secondary/KEYS_template.py b/sept/sept-secondary/KEYS_template.py index 38cdcb0c4..a3ac39639 100644 --- a/sept/sept-secondary/KEYS_template.py +++ b/sept/sept-secondary/KEYS_template.py @@ -1,7 +1,19 @@ -HOVI_ENC_KEY_PRD = bytearray.fromhex('00000000000000000000000000000000') -HOVI_ENC_KEY_DEV = bytearray.fromhex('00000000000000000000000000000000') -HOVI_SIG_KEY_PRD = bytearray.fromhex('00000000000000000000000000000000') -HOVI_SIG_KEY_DEV = bytearray.fromhex('00000000000000000000000000000000') -HOVI_KEK_KEY_PRD = bytearray.fromhex('00000000000000000000000000000000') -HOVI_KEK_KEY_DEV = bytearray.fromhex('00000000000000000000000000000000') -IV = bytearray.fromhex('00000000000000000000000000000000') +NUM_KEYS = 2 + +HOVI_ENC_KEY_PRD = [ + bytearray.fromhex('00000000000000000000000000000000'), + bytearray.fromhex('00000000000000000000000000000000'), +] +HOVI_SIG_KEY_PRD = [ + bytearray.fromhex('00000000000000000000000000000000'), + bytearray.fromhex('00000000000000000000000000000000'), +] + +IV = [ + bytearray.fromhex('00000000000000000000000000000000'), + bytearray.fromhex('00000000000000000000000000000000'), +] + +assert len(HOVI_ENC_KEY_PRD) == NUM_KEYS +assert len(HOVI_SIG_KEY_PRD) == NUM_KEYS +assert len(IV) == NUM_KEYS \ No newline at end of file diff --git a/sept/sept-secondary/Makefile b/sept/sept-secondary/Makefile index 03a8a5f8c..b9721de5f 100644 --- a/sept/sept-secondary/Makefile +++ b/sept/sept-secondary/Makefile @@ -137,12 +137,12 @@ clean: @echo clean ... @$(MAKE) -C $(AMS)/exosphere/rebootstub clean @$(MAKE) -C key_derivation clean - @rm -fr $(BUILD) $(TARGET).bin $(TARGET).enc $(TARGET).elf + @rm -fr $(BUILD) $(TARGET).bin $(TARGET)_*.enc $(TARGET).elf #--------------------------------------------------------------------------------- else -.PHONY: all +.PHONY: all $(OUTPUT).bin DEPENDS := $(OFILES:.o=.d) diff --git a/sept/sept-secondary/key_derivation/src/key_derivation.c b/sept/sept-secondary/key_derivation/src/key_derivation.c index 65eb9290b..a94885f71 100644 --- a/sept/sept-secondary/key_derivation/src/key_derivation.c +++ b/sept/sept-secondary/key_derivation/src/key_derivation.c @@ -20,7 +20,7 @@ #define AL16 __attribute__((aligned(16))) -#define DERIVATION_ID_MAX 1 +#define DERIVATION_ID_MAX 2 static const uint8_t AL16 keyblob_seed_00[0x10] = { 0xDF, 0x20, 0x6F, 0x59, 0x44, 0x54, 0xEF, 0xDC, 0x70, 0x74, 0x48, 0x3B, 0x0D, 0xED, 0x9F, 0xD3 @@ -44,10 +44,12 @@ static const uint8_t AL16 masterkey_4x_seed[0x10] = { static const uint8_t AL16 master_kek_seeds[DERIVATION_ID_MAX][0x10] = { {0x9A, 0x3E, 0xA9, 0xAB, 0xFD, 0x56, 0x46, 0x1C, 0x9B, 0xF6, 0x48, 0x7F, 0x5C, 0xFA, 0x09, 0x5C}, + {0xDE, 0xDC, 0xE3, 0x39, 0x30, 0x88, 0x16, 0xF8, 0xAE, 0x97, 0xAD, 0xEC, 0x64, 0x2D, 0x41, 0x41}, }; static const uint8_t AL16 master_devkey_seeds[DERIVATION_ID_MAX][0x10] = { {0x8F, 0x77, 0x5A, 0x96, 0xB0, 0x94, 0xFD, 0x8D, 0x28, 0xE4, 0x19, 0xC8, 0x16, 0x1C, 0xDB, 0x3D}, + {0x67, 0x62, 0xD4, 0x8E, 0x55, 0xCF, 0xFF, 0x41, 0x31, 0x15, 0x3B, 0x24, 0x0C, 0x7C, 0x07, 0xAE}, }; void derive_keys(void) { @@ -101,7 +103,7 @@ void derive_keys(void) { } /* Derive master kek. */ - decrypt_data_into_keyslot(0xE, 0xE, master_kek_seeds[0], 0x10); + decrypt_data_into_keyslot(0xE, 0xE, master_kek_seeds[derivation_id], 0x10); /* Derive master key, device master key. */ decrypt_data_into_keyslot(0xC, 0xE, masterkey_seed, 0x10); @@ -123,7 +125,7 @@ void derive_keys(void) { decrypt_data_into_keyslot(0xF, 0xF, devicekey_seed, 0x10); /* Derive firmware specific device key. */ - se_aes_ecb_decrypt_block(0xA, work_buffer, 0x10, master_devkey_seeds[0], 0x10); + se_aes_ecb_decrypt_block(0xA, work_buffer, 0x10, master_devkey_seeds[derivation_id], 0x10); decrypt_data_into_keyslot(0xE, 0xE, work_buffer, 0x10); /* Clear work buffer. */ diff --git a/sept/sept-secondary/sept_sign.py b/sept/sept-secondary/sept_sign.py index ba108c1fc..a5ca66a36 100644 --- a/sept/sept-secondary/sept_sign.py +++ b/sept/sept-secondary/sept_sign.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -import sys +import sys, os from struct import pack as pk, unpack as up from Crypto.Cipher import AES from Crypto.Hash import CMAC @@ -41,7 +41,7 @@ def get_last_block_for_desired_mac(key, data, desired_mac): return last_block -def sign_encrypt_code(code, sig_key, enc_key, iv, desired_mac): +def sign_encrypt_code(code, sig_key, enc_key, iv, desired_mac, version): # Pad with 0x20 of zeroes. code = code + bytearray(0x20) code_len = len(code) @@ -49,6 +49,9 @@ def sign_encrypt_code(code, sig_key, enc_key, iv, desired_mac): code_len &= ~0xFFF code = code + bytearray(code_len - len(code)) + # Insert version + code = code[:8] + pk(' #include -void derive_keys(void); +void derive_keys(uint32_t version); void load_keys(const uint8_t *se_state); #endif diff --git a/sept/sept-secondary/src/main.c b/sept/sept-secondary/src/main.c index 50c4f7285..b1cb458a4 100644 --- a/sept/sept-secondary/src/main.c +++ b/sept/sept-secondary/src/main.c @@ -48,7 +48,7 @@ static void set_has_rebooted(bool rebooted) { } -static void exfiltrate_keys_and_reboot_if_needed(void) { +static void exfiltrate_keys_and_reboot_if_needed(uint32_t version) { volatile tegra_pmc_t *pmc = pmc_get_regs(); uint8_t *enc_se_state = (uint8_t *)0x4003E000; uint8_t *dec_se_state = (uint8_t *)0x4003F000; @@ -59,7 +59,7 @@ static void exfiltrate_keys_and_reboot_if_needed(void) { set_has_rebooted(true); /* Derive keys. */ - derive_keys(); + derive_keys(version); reboot_to_self(); } else { @@ -135,14 +135,14 @@ static void exit_callback(int rc) { relocate_and_chainload(); } -int main(void) { +int sept_main(uint32_t version) { const char *stage2_path; stage2_args_t *stage2_args; uint32_t stage2_version = 0; ScreenLogLevel log_level = SCREEN_LOG_LEVEL_NONE; /* Extract keys from the security engine, which TSEC FW locked down. */ - exfiltrate_keys_and_reboot_if_needed(); + exfiltrate_keys_and_reboot_if_needed(version); /* Override the global logging level. */ log_set_log_level(log_level); diff --git a/sept/sept-secondary/src/start.s b/sept/sept-secondary/src/start.s index b79cfce26..73cdf5b10 100644 --- a/sept/sept-secondary/src/start.s +++ b/sept/sept-secondary/src/start.s @@ -13,7 +13,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + .macro CLEAR_GPR_REG_ITER mov r\@, #0 .endm @@ -26,13 +26,18 @@ _start: /* Switch to system mode, mask all interrupts, clear all flags */ msr cpsr_cxsf, #0xDF + b begin_relocation_loop + _version: + .word 0x00000000 /* Version. */ + .word 0x00000000 /* Reserved. */ + begin_relocation_loop: /* Relocate ourselves if necessary */ ldr r2, =__start__ adr r3, _start cmp r2, r3 beq _relocation_loop_end - + /* If we are relocating, we are not rebooting to ourselves. Note that. */ ldr r0, =0x4003FFFC mov r1, #0x0 @@ -50,12 +55,12 @@ _start: ldr r12, =_second_relocation_start bx r12 - + _second_relocation_start: ldr r4, =__bss_start__ sub r4, r4, r2 mov r1, #0x0 - + _second_relocation_loop: ldmia r3!, {r5-r12} stmia r2!, {r5-r12} @@ -67,7 +72,7 @@ _start: bx r12 _relocation_loop_end: - + /* Set the stack pointer */ ldr sp, =__stack_top__ mov fp, #0 @@ -78,7 +83,9 @@ _start: CLEAR_GPR_REG_ITER .endr ldr lr, =__program_exit - b main + ldr r0, =_version + ldr r0, [r0] + b sept_main /* No need to include this in normal programs: */ .section .chainloader.text.start, "ax", %progbits