sept: update to support 8.1.0

This commit is contained in:
Michael Scire 2019-06-18 23:23:31 -07:00
parent c96ae0148e
commit befd912a88
20 changed files with 218 additions and 140 deletions

View file

@ -13,7 +13,7 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef ATMOSPHERE_TARGET_FIRMWARE_H #ifndef ATMOSPHERE_TARGET_FIRMWARE_H
#define ATMOSPHERE_TARGET_FIRMWARE_H #define ATMOSPHERE_TARGET_FIRMWARE_H
@ -26,11 +26,12 @@
#define ATMOSPHERE_TARGET_FIRMWARE_620 7 #define ATMOSPHERE_TARGET_FIRMWARE_620 7
#define ATMOSPHERE_TARGET_FIRMWARE_700 8 #define ATMOSPHERE_TARGET_FIRMWARE_700 8
#define ATMOSPHERE_TARGET_FIRMWARE_800 9 #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_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? */ /* TODO: What should this be, for release? */
#define ATMOSPHERE_TARGET_FIRMWARE_DEFAULT_FOR_DEBUG ATMOSPHERE_TARGET_FIRMWARE_CURRENT #define ATMOSPHERE_TARGET_FIRMWARE_DEFAULT_FOR_DEBUG ATMOSPHERE_TARGET_FIRMWARE_CURRENT

View file

@ -13,7 +13,7 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
@ -34,13 +34,13 @@ unsigned int exosphere_load_config(void) {
generic_panic(); generic_panic();
} }
g_has_loaded_config = true; g_has_loaded_config = true;
const unsigned int magic = MAILBOX_EXOSPHERE_CONFIG.magic; const unsigned int magic = MAILBOX_EXOSPHERE_CONFIG.magic;
if (magic == MAGIC_EXOSPHERE_CONFIG) { if (magic == MAGIC_EXOSPHERE_CONFIG) {
g_exosphere_cfg = MAILBOX_EXOSPHERE_CONFIG; g_exosphere_cfg = MAILBOX_EXOSPHERE_CONFIG;
} }
return g_exosphere_cfg.target_firmware; return g_exosphere_cfg.target_firmware;
} }
@ -48,7 +48,7 @@ unsigned int exosphere_get_target_firmware(void) {
if (!g_has_loaded_config) { if (!g_has_loaded_config) {
generic_panic(); generic_panic();
} }
return g_exosphere_cfg.target_firmware; return g_exosphere_cfg.target_firmware;
} }
@ -56,15 +56,15 @@ unsigned int exosphere_should_perform_620_keygen(void) {
if (!g_has_loaded_config) { if (!g_has_loaded_config) {
generic_panic(); 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) { unsigned int exosphere_should_override_debugmode_priv(void) {
if (!g_has_loaded_config) { if (!g_has_loaded_config) {
generic_panic(); generic_panic();
} }
return EXOSPHERE_CHECK_FLAG(EXOSPHERE_FLAG_IS_DEBUGMODE_PRIV); 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) { if (!g_has_loaded_config) {
generic_panic(); generic_panic();
} }
return EXOSPHERE_CHECK_FLAG(EXOSPHERE_FLAG_IS_DEBUGMODE_USER); 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) { if (!g_has_loaded_config) {
generic_panic(); generic_panic();
} }
return EXOSPHERE_CHECK_FLAG(EXOSPHERE_FLAG_DISABLE_USERMODE_EXCEPTION_HANDLERS); return EXOSPHERE_CHECK_FLAG(EXOSPHERE_FLAG_DISABLE_USERMODE_EXCEPTION_HANDLERS);
} }

View file

@ -13,7 +13,7 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef EXOSPHERE_EXOSPHERE_CONFIG_H #ifndef EXOSPHERE_EXOSPHERE_CONFIG_H
#define EXOSPHERE_EXOSPHERE_CONFIG_H #define EXOSPHERE_EXOSPHERE_CONFIG_H
@ -36,7 +36,7 @@
/* Exosphere config in DRAM shares physical/virtual mapping. */ /* Exosphere config in DRAM shares physical/virtual mapping. */
#define MAILBOX_EXOSPHERE_CONFIG_PHYS MAILBOX_EXOSPHERE_CONFIG #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_PRIV (1 << 1u)
#define EXOSPHERE_FLAG_IS_DEBUGMODE_USER (1 << 2u) #define EXOSPHERE_FLAG_IS_DEBUGMODE_USER (1 << 2u)
#define EXOSPHERE_FLAG_DISABLE_USERMODE_EXCEPTION_HANDLERS (1 << 3u) #define EXOSPHERE_FLAG_DISABLE_USERMODE_EXCEPTION_HANDLERS (1 << 3u)

View file

@ -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 KIPFILES := loader.kip pm.kip sm.kip ams_mitm.kip spl.kip boot.kip
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) fusee-primary.bin \ BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) fusee-primary.bin \
exosphere.bin lp0fw.bin rebootstub.bin thermosphere.bin splash_screen.bmp \ 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) $(KIPFILES)
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
@ -198,22 +198,27 @@ fusee_primary.bin.o fusee_primary_bin.h: fusee-primary.bin
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
@echo $(notdir $<) @echo $(notdir $<)
@$(_bin2o) @$(_bin2o)
sept_primary.bin.o sept_primary_bin.h: sept-primary.bin sept_primary.bin.o sept_primary_bin.h: sept-primary.bin
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
@echo $(notdir $<) @echo $(notdir $<)
@$(_bin2o) @$(_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 $<) @echo $(notdir $<)
@$(_bin2o) @$(_bin2o)
sept_secondary_01.enc.o sept_secondary_01_enc.h: sept-secondary_01.enc
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(_bin2o)
%.bin.o %_bin.h: %.bin %.bin.o %_bin.h: %.bin
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
@echo $(notdir $<) @echo $(notdir $<)
@$(bin2o) @$(bin2o)
%.bmp.o %_bmp.h: %.bmp %.bmp.o %_bmp.h: %.bmp
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
@echo $(notdir $<) @echo $(notdir $<)

View file

@ -55,7 +55,7 @@ SECTIONS
. = ALIGN(32); . = ALIGN(32);
PROVIDE (__chainloader_end__ = ABSOLUTE(.)); PROVIDE (__chainloader_end__ = ABSOLUTE(.));
} >low_iram :NONE } >low_iram :NONE
.nxboot_loadable : .nxboot_loadable :
{ {
. = ALIGN(32); . = ALIGN(32);
@ -157,7 +157,7 @@ SECTIONS
CONSTRUCTORS CONSTRUCTORS
. = ALIGN(32); . = ALIGN(32);
} >main } >main
__data_end__ = ABSOLUTE(.); __data_end__ = ABSOLUTE(.);
PROVIDE (__total_size__ = (__data_end__ - __start__)); PROVIDE (__total_size__ = (__data_end__ - __start__));
@ -236,8 +236,10 @@ SECTIONS
PROVIDE(__rebootstub_bin_size__ = rebootstub_bin_end - rebootstub_bin); PROVIDE(__rebootstub_bin_size__ = rebootstub_bin_end - rebootstub_bin);
PROVIDE(__sept_primary_bin_start__ = sept_primary_bin - __start__); PROVIDE(__sept_primary_bin_start__ = sept_primary_bin - __start__);
PROVIDE(__sept_primary_bin_size__ = sept_primary_bin_end - sept_primary_bin); PROVIDE(__sept_primary_bin_size__ = sept_primary_bin_end - sept_primary_bin);
PROVIDE(__sept_secondary_enc_start__ = sept_secondary_enc - __start__); PROVIDE(__sept_secondary_00_enc_start__ = sept_secondary_00_enc - __start__);
PROVIDE(__sept_secondary_enc_size__ = sept_secondary_enc_end - sept_secondary_enc); 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_start__ = sm_kip - __start__);
PROVIDE(__sm_kip_size__ = sm_kip_end - sm_kip); PROVIDE(__sm_kip_size__ = sm_kip_end - sm_kip);
PROVIDE(__spl_kip_start__ = spl_kip - __start__); PROVIDE(__spl_kip_start__ = spl_kip - __start__);

View file

@ -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 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. */ {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. */ {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) { if (get_keyblob(&keyblob, revision, keyblobs, available_revision) != 0) {
return -1; return -1;
} }
se_aes_ecb_decrypt_block(0xD, work_buffer, 0x10, keyblob_seeds[revision], 0x10); 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(keyslot, 0xE, work_buffer, 0x10);
decrypt_data_into_keyslot(0xB, keyslot, keyblob_mac_seed, 0x10); decrypt_data_into_keyslot(0xB, keyslot, keyblob_mac_seed, 0x10);
/* Validate keyblob. */ /* Validate keyblob. */
se_compute_aes_128_cmac(0xB, work_buffer, 0x10, keyblob.mac + sizeof(keyblob.mac), sizeof(keyblob) - sizeof(keyblob.mac)); 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)) { if (safe_memcmp(keyblob.mac, work_buffer, 0x10)) {
return -1; return -1;
} }
/* Decrypt keyblob. */ /* 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)); 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; return 0;
@ -113,7 +114,7 @@ int load_package1_key(uint32_t revision) {
if (revision > MASTERKEY_REVISION_600_610) { if (revision > MASTERKEY_REVISION_600_610) {
return -1; return -1;
} }
set_aes_keyslot(0xB, g_dec_keyblobs[revision].package1_key, 0x10); set_aes_keyslot(0xB, g_dec_keyblobs[revision].package1_key, 0x10);
return 0; 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) { 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 work_buffer[0x10];
uint8_t AL16 zeroes[0x10] = {0}; uint8_t AL16 zeroes[0x10] = {0};
/* Initialize keygen type. */ /* Initialize keygen type. */
*out_keygen_type = 0; *out_keygen_type = 0;
/* TODO: Set keyslot flags properly in preparation of derivation. */ /* TODO: Set keyslot flags properly in preparation of derivation. */
set_aes_keyslot_flags(0xE, 0x15); set_aes_keyslot_flags(0xE, 0x15);
set_aes_keyslot_flags(0xD, 0x15); set_aes_keyslot_flags(0xD, 0x15);
/* Set the TSEC key. */ /* Set the TSEC key. */
set_aes_keyslot(0xD, tsec_key, 0x10); set_aes_keyslot(0xD, tsec_key, 0x10);
/* Decrypt all keyblobs, setting keyslot 0xF correctly. */ /* Decrypt all keyblobs, setting keyslot 0xF correctly. */
for (unsigned int rev = 0; rev <= MASTERKEY_REVISION_600_610; rev++) { for (unsigned int rev = 0; rev <= MASTERKEY_REVISION_600_610; rev++) {
int ret = decrypt_keyblob(keyblobs, rev, available_revision); 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; break;
case ATMOSPHERE_TARGET_FIRMWARE_700: case ATMOSPHERE_TARGET_FIRMWARE_700:
case ATMOSPHERE_TARGET_FIRMWARE_800: 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; break;
default: default:
fatal_error("Unknown target firmware: %02x!", target_firmware); fatal_error("Unknown target firmware: %02x!", target_firmware);
break; break;
} }
/* Try emulation result. */ /* Try emulation result. */
for (unsigned int rev = MASTERKEY_REVISION_620; rev < MASTERKEY_REVISION_MAX; rev++) { 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)); 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); memcpy(g_dec_keyblobs[rev].master_kek, work_buffer, 0x10);
} }
} }
if (memcmp(g_dec_keyblobs[desired_keyblob].master_kek, zeroes, 0x10) == 0) { if (memcmp(g_dec_keyblobs[desired_keyblob].master_kek, zeroes, 0x10) == 0) {
/* Try reading the keys from a file. */ /* Try reading the keys from a file. */
const char *keyfile = fuse_get_retail_type() != 0 ? "atmosphere/prod.keys" : "atmosphere/dev.keys"; 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) { if (memcmp(g_dec_keyblobs[available_revision].master_kek, zeroes, 0x10) == 0) {
fatal_error("Error: failed to derive master_kek_%02x!", available_revision); fatal_error("Error: failed to derive master_kek_%02x!", available_revision);
} }
} }
/* Clear the SBK. */ /* Clear the SBK. */
clear_aes_keyslot(0xE); 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_620:
case ATMOSPHERE_TARGET_FIRMWARE_700: case ATMOSPHERE_TARGET_FIRMWARE_700:
case ATMOSPHERE_TARGET_FIRMWARE_800: case ATMOSPHERE_TARGET_FIRMWARE_800:
case ATMOSPHERE_TARGET_FIRMWARE_810:
decrypt_data_into_keyslot(0xA, 0xF, devicekey_4x_seed, 0x10); decrypt_data_into_keyslot(0xA, 0xF, devicekey_4x_seed, 0x10);
decrypt_data_into_keyslot(0xF, 0xF, devicekey_seed, 0x10); decrypt_data_into_keyslot(0xF, 0xF, devicekey_seed, 0x10);
decrypt_data_into_keyslot(0xE, 0xC, masterkey_4x_seed, 0x10); decrypt_data_into_keyslot(0xE, 0xC, masterkey_4x_seed, 0x10);

View file

@ -13,7 +13,7 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
@ -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. */ {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. */ {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. */ {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. */ /* 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. */ {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. */ {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. */ {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) { 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) { if (g_determined_mkey_revision) {
generic_panic(); generic_panic();
} }
for (unsigned int rev = 0; rev < MASTERKEY_REVISION_MAX; rev++) { for (unsigned int rev = 0; rev < MASTERKEY_REVISION_MAX; rev++) {
if (check_mkey_revision(rev, is_retail)) { if (check_mkey_revision(rev, is_retail)) {
g_determined_mkey_revision = true; g_determined_mkey_revision = true;
@ -88,7 +90,7 @@ int mkey_detect_revision(bool is_retail) {
break; break;
} }
} }
/* We must have determined the master key, or we're not running on a Switch. */ /* We must have determined the master key, or we're not running on a Switch. */
if (!g_determined_mkey_revision) { if (!g_determined_mkey_revision) {
return -1; return -1;

View file

@ -13,14 +13,14 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef FUSEE_MASTERKEY_H #ifndef FUSEE_MASTERKEY_H
#define FUSEE_MASTERKEY_H #define FUSEE_MASTERKEY_H
/* This is glue code to enable master key support across versions. */ /* This is glue code to enable master key support across versions. */
/* TODO: Update to 0x8 on release of new master key. */ /* TODO: Update to 0xA on release of new master key. */
#define MASTERKEY_REVISION_MAX 0x8 #define MASTERKEY_REVISION_MAX 0x9
#define MASTERKEY_REVISION_100_230 0x00 #define MASTERKEY_REVISION_100_230 0x00
#define MASTERKEY_REVISION_300 0x01 #define MASTERKEY_REVISION_300 0x01
@ -29,7 +29,8 @@
#define MASTERKEY_REVISION_500_510 0x04 #define MASTERKEY_REVISION_500_510 0x04
#define MASTERKEY_REVISION_600_610 0x05 #define MASTERKEY_REVISION_600_610 0x05
#define MASTERKEY_REVISION_620 0x06 #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) #define MASTERKEY_NUM_NEW_DEVICE_KEYS (MASTERKEY_REVISION_MAX - MASTERKEY_REVISION_400_410)

View file

@ -13,7 +13,7 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
@ -53,7 +53,8 @@
#define u8 uint8_t #define u8 uint8_t
#define u32 uint32_t #define u32 uint32_t
#include "exosphere_bin.h" #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 "lp0fw_bin.h"
#include "emummc_kip.h" #include "emummc_kip.h"
#include "lib/log.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 */ case 0x0F: /* 7.0.0 - 7.0.1 */
return ATMOSPHERE_TARGET_FIRMWARE_700; return ATMOSPHERE_TARGET_FIRMWARE_700;
case 0x10: /* 8.0.0 */ case 0x10: { /* 8.0.0 - 8.1.0 */
return ATMOSPHERE_TARGET_FIRMWARE_800; 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: default:
fatal_error("[NXBOOT] Unable to identify package1!\n"); 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) { 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 = ""}; emummc_config_t emummc_cfg = {.enabled = false, .id = 0, .sector = -1, .path = "", .nintendo_path = ""};
char *emummc_ini = calloc(1, 0x10000); char *emummc_ini = calloc(1, 0x10000);
if (!read_from_file(emummc_ini, 0xFFFF, "emummc/emummc.ini")) { if (!read_from_file(emummc_ini, 0xFFFF, "emummc/emummc.ini")) {
free(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. */ 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)); 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'; exo_emummc_config->emu_dir_path[sizeof(exo_emummc_config->emu_dir_path) - 1] = '\0';
if (emummc_cfg.enabled) { if (emummc_cfg.enabled) {
if (emummc_cfg.sector != -1) { if (emummc_cfg.sector != -1) {
exo_emummc_config->base_cfg.type = EMUMMC_TYPE_PARTITION; exo_emummc_config->base_cfg.type = EMUMMC_TYPE_PARTITION;
exo_emummc_config->partition_cfg.start_sector = emummc_cfg.sector; exo_emummc_config->partition_cfg.start_sector = emummc_cfg.sector;
/* Mount emulated NAND from SD card partition. */ /* Mount emulated NAND from SD card partition. */
if (nxfs_mount_emummc_partition(emummc_cfg.sector) < 0) { if (nxfs_mount_emummc_partition(emummc_cfg.sector) < 0) {
fatal_error("[NXBOOT] Failed to mount EmuMMC from SD card partition!\n"); 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_boot0_path[0x300 + 1] = {0};
char emummc_boot1_path[0x300 + 1] = {0}; char emummc_boot1_path[0x300 + 1] = {0};
char emummc_rawnand_path[0x300 + 1] = {0}; char emummc_rawnand_path[0x300 + 1] = {0};
/* Prepare base folder path. */ /* Prepare base folder path. */
snprintf(emummc_path, sizeof(emummc_path) - 1, "%s/%s", emummc_cfg.path, "eMMC"); snprintf(emummc_path, sizeof(emummc_path) - 1, "%s/%s", emummc_cfg.path, "eMMC");
/* Check if eMMC folder is present. */ /* Check if eMMC folder is present. */
if (!is_valid_folder(emummc_path)) { if (!is_valid_folder(emummc_path)) {
fatal_error("[NXBOOT] Failed to find EmuMMC eMMC folder!\n"); fatal_error("[NXBOOT] Failed to find EmuMMC eMMC folder!\n");
} }
/* Prepare expected file paths. */ /* Prepare expected file paths. */
snprintf(emummc_boot0_path, sizeof(emummc_boot0_path) - 1, "%s/%s", emummc_path, "boot0"); 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"); snprintf(emummc_boot1_path, sizeof(emummc_boot1_path) - 1, "%s/%s", emummc_path, "boot1");
/* Check if boot0 and boot1 image files are present. */ /* Check if boot0 and boot1 image files are present. */
if (!is_valid_file(emummc_boot0_path) || !is_valid_file(emummc_boot1_path)) { 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"); fatal_error("[NXBOOT] Failed to find EmuMMC boot0/boot1 image files!\n");
} }
/* Find raw image files (single or multi part). */ /* Find raw image files (single or multi part). */
for (int i = 0; i < 64; i++) { for (int i = 0; i < 64; i++) {
snprintf(emummc_rawnand_path, sizeof(emummc_rawnand_path) - 1, "%s/%02d", emummc_path, 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)) { if ((num_parts == 0) || (part_limit == 0)) {
fatal_error("[NXBOOT] Failed to find EmuMMC raw image files!\n"); fatal_error("[NXBOOT] Failed to find EmuMMC raw image files!\n");
} }
/* Mount emulated NAND from files. */ /* Mount emulated NAND from files. */
if (nxfs_mount_emummc_file(emummc_path, num_parts, part_limit) < 0) { if (nxfs_mount_emummc_file(emummc_path, num_parts, part_limit) < 0) {
fatal_error("[NXBOOT] Failed to mount EmuMMC from files!\n"); 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"); fatal_error("[NXBOOT] Invalid EmuMMC setting!\n");
} }
} }
return emummc_cfg.enabled; 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) { if (ini_parse_string(get_loader_ctx()->bct0, stratosphere_ini_handler, &strat_cfg) < 0) {
fatal_error("[NXBOOT] Failed to parse BCT.ini!\n"); 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. */ /* 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.has_nogc_config) {
if (strat_cfg.enable_nogc) { 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) { static void nxboot_set_bootreason(void *bootreason_base) {
boot_reason_t boot_reason = {0}; boot_reason_t boot_reason = {0};
FILE *boot0; FILE *boot0;
nvboot_config_table *bct; nvboot_config_table *bct;
nv_bootloader_info *bootloader_info; nv_bootloader_info *bootloader_info;
@ -362,7 +370,7 @@ static void nxboot_set_bootreason(void *bootreason_base) {
if (bct == NULL) { if (bct == NULL) {
fatal_error("[NXBOOT] Out of memory!\n"); fatal_error("[NXBOOT] Out of memory!\n");
} }
/* Open boot0. */ /* Open boot0. */
boot0 = fopen("boot0:/", "rb"); boot0 = fopen("boot0:/", "rb");
if (boot0 == NULL) { 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) { if (fread(bct, sizeof(nvboot_config_table), 1, boot0) == 0) {
fatal_error("[NXBOOT] Failed to read the BCT!\n"); fatal_error("[NXBOOT] Failed to read the BCT!\n");
} }
/* Close boot0. */ /* Close boot0. */
fclose(boot0); fclose(boot0);
/* Populate bootloader parameters. */ /* Populate bootloader parameters. */
bootloader_info = &bct->bootloader[0]; bootloader_info = &bct->bootloader[0];
boot_reason.bootloader_version = bootloader_info->version; boot_reason.bootloader_version = bootloader_info->version;
boot_reason.bootloader_start_block = bootloader_info->start_blk; boot_reason.bootloader_start_block = bootloader_info->start_blk;
boot_reason.bootloader_start_page = bootloader_info->start_page; boot_reason.bootloader_start_page = bootloader_info->start_page;
boot_reason.bootloader_attribute = bootloader_info->attribute; boot_reason.bootloader_attribute = bootloader_info->attribute;
uint8_t power_key_intr = 0; uint8_t power_key_intr = 0;
uint8_t rtc_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_PWR_I2C_ADDR, MAX77620_REG_ONOFFIRQ, &power_key_intr, 1);
i2c_query(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_REG_RTCINT, &rtc_intr, 1); i2c_query(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_REG_RTCINT, &rtc_intr, 1);
/* Set PMIC value. */ /* Set PMIC value. */
boot_reason.boot_reason_value = ((rtc_intr << 0x08) | power_key_intr); boot_reason.boot_reason_value = ((rtc_intr << 0x08) | power_key_intr);
/* TODO: Find out what these mean. */ /* TODO: Find out what these mean. */
if (power_key_intr & 0x80) if (power_key_intr & 0x80)
boot_reason.boot_reason_state = 0x01; boot_reason.boot_reason_state = 0x01;
@ -401,10 +409,10 @@ static void nxboot_set_bootreason(void *bootreason_base) {
boot_reason.boot_reason_state = 0x03; boot_reason.boot_reason_state = 0x03;
else if (rtc_intr & 0x04) else if (rtc_intr & 0x04)
boot_reason.boot_reason_state = 0x04; boot_reason.boot_reason_state = 0x04;
/* Set in memory. */ /* Set in memory. */
memcpy(bootreason_base, &boot_reason, sizeof(boot_reason)); memcpy(bootreason_base, &boot_reason, sizeof(boot_reason));
/* Clean up. */ /* Clean up. */
free(bct); free(bct);
} }
@ -414,13 +422,13 @@ static void nxboot_move_bootconfig() {
void *bootconfig; void *bootconfig;
uint32_t bootconfig_addr; uint32_t bootconfig_addr;
uint32_t bootconfig_size; uint32_t bootconfig_size;
/* Allocate memory for reading BootConfig. */ /* Allocate memory for reading BootConfig. */
bootconfig = memalign(0x1000, 0x4000); bootconfig = memalign(0x1000, 0x4000);
if (bootconfig == NULL) { if (bootconfig == NULL) {
fatal_error("[NXBOOT] Out of memory!\n"); fatal_error("[NXBOOT] Out of memory!\n");
} }
/* Get BootConfig from the Package2 partition. */ /* Get BootConfig from the Package2 partition. */
bcfile = fopen("bcpkg21:/", "rb"); bcfile = fopen("bcpkg21:/", "rb");
if (bcfile == NULL) { if (bcfile == NULL) {
@ -431,15 +439,15 @@ static void nxboot_move_bootconfig() {
fatal_error("[NXBOOT] Failed to read BootConfig!\n"); fatal_error("[NXBOOT] Failed to read BootConfig!\n");
} }
fclose(bcfile); fclose(bcfile);
/* Select the actual BootConfig size and destination address. */ /* Select the actual BootConfig size and destination address. */
bootconfig_addr = (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < ATMOSPHERE_TARGET_FIRMWARE_600) ? 0x4003D000 : 0x4003F800; 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; bootconfig_size = (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < ATMOSPHERE_TARGET_FIRMWARE_400) ? 0x3000 : 0x1000;
/* Copy the BootConfig into IRAM. */ /* Copy the BootConfig into IRAM. */
memset((void *)bootconfig_addr, 0, bootconfig_size); memset((void *)bootconfig_addr, 0, bootconfig_size);
memcpy((void *)bootconfig_addr, bootconfig, bootconfig_size); memcpy((void *)bootconfig_addr, bootconfig, bootconfig_size);
/* Clean up. */ /* Clean up. */
free(bootconfig); free(bootconfig);
} }
@ -459,6 +467,8 @@ uint32_t nxboot_main(void) {
size_t package2_size; size_t package2_size;
void *tsec_fw; void *tsec_fw;
size_t tsec_fw_size; size_t tsec_fw_size;
const void *sept_secondary_enc = NULL;
size_t sept_secondary_enc_size = 0;
void *warmboot_fw; void *warmboot_fw;
size_t warmboot_fw_size; size_t warmboot_fw_size;
void *warmboot_memaddr; void *warmboot_memaddr;
@ -470,7 +480,7 @@ uint32_t nxboot_main(void) {
FILE *boot0, *pk2file; FILE *boot0, *pk2file;
void *exosphere_memaddr; void *exosphere_memaddr;
exo_emummc_config_t exo_emummc_cfg; exo_emummc_config_t exo_emummc_cfg;
/* Configure emummc or mount the real NAND. */ /* Configure emummc or mount the real NAND. */
if (!nxboot_configure_emummc(&exo_emummc_cfg)) { if (!nxboot_configure_emummc(&exo_emummc_cfg)) {
emummc = NULL; emummc = NULL;
@ -542,7 +552,7 @@ uint32_t nxboot_main(void) {
fatal_error("[NXBOOT] Failed to read Package2!\n"); fatal_error("[NXBOOT] Failed to read Package2!\n");
} }
fclose(pk2file); fclose(pk2file);
/* Read and parse boot0. */ /* Read and parse boot0. */
print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT] Reading boot0...\n"); print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT] Reading boot0...\n");
boot0 = fopen("boot0:/", "rb"); boot0 = fopen("boot0:/", "rb");
@ -550,7 +560,7 @@ uint32_t nxboot_main(void) {
fatal_error("[NXBOOT] Couldn't parse boot0: %s!\n", strerror(errno)); fatal_error("[NXBOOT] Couldn't parse boot0: %s!\n", strerror(errno));
} }
fclose(boot0); fclose(boot0);
/* Find the system's target firmware. */ /* Find the system's target firmware. */
uint32_t target_firmware = nxboot_get_target_firmware(package1loader); uint32_t target_firmware = nxboot_get_target_firmware(package1loader);
if (!target_firmware) if (!target_firmware)
@ -561,26 +571,42 @@ uint32_t nxboot_main(void) {
/* Read the TSEC firmware from a file, otherwise from PK1L. */ /* Read the TSEC firmware from a file, otherwise from PK1L. */
if (loader_ctx->tsecfw_path[0] != '\0') { if (loader_ctx->tsecfw_path[0] != '\0') {
tsec_fw_size = get_file_size(loader_ctx->tsecfw_path); 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); fatal_error("[NXBOOT] TSEC firmware from %s has a wrong size!\n", loader_ctx->tsecfw_path);
} else if (tsec_fw_size == 0) { } else if (tsec_fw_size == 0) {
fatal_error("[NXBOOT] Could not read the TSEC firmware from %s!\n", loader_ctx->tsecfw_path); fatal_error("[NXBOOT] Could not read the TSEC firmware from %s!\n", loader_ctx->tsecfw_path);
} }
/* Allocate memory for the TSEC firmware. */ /* Allocate memory for the TSEC firmware. */
tsec_fw = memalign(0x100, tsec_fw_size); tsec_fw = memalign(0x100, tsec_fw_size);
if (tsec_fw == NULL) { if (tsec_fw == NULL) {
fatal_error("[NXBOOT] Out of memory!\n"); fatal_error("[NXBOOT] Out of memory!\n");
} }
if (read_from_file(tsec_fw, tsec_fw_size, loader_ctx->tsecfw_path) != tsec_fw_size) { 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); 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 { } else {
if (!package1_get_tsec_fw(&tsec_fw, package1loader, package1loader_size)) { if (!package1_get_tsec_fw(&tsec_fw, package1loader, package1loader_size)) {
fatal_error("[NXBOOT] Failed to read the TSEC firmware from Package1loader!\n"); 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; tsec_fw_size = 0x3000;
} else if (target_firmware == ATMOSPHERE_TARGET_FIRMWARE_620) { } else if (target_firmware == ATMOSPHERE_TARGET_FIRMWARE_620) {
tsec_fw_size = 0x2900; tsec_fw_size = 0x2900;
@ -606,10 +632,10 @@ uint32_t nxboot_main(void) {
get_and_clear_has_run_sept(); get_and_clear_has_run_sept();
} else if (target_firmware == ATMOSPHERE_TARGET_FIRMWARE_620) { } else if (target_firmware == ATMOSPHERE_TARGET_FIRMWARE_620) {
uint8_t tsec_keys[0x20] = {0}; uint8_t tsec_keys[0x20] = {0};
/* Emulate the TSEC payload on 6.2.0+. */ /* Emulate the TSEC payload on 6.2.0+. */
smmu_emulate_tsec((void *)tsec_keys, package1loader, package1loader_size, package1loader); smmu_emulate_tsec((void *)tsec_keys, package1loader, package1loader_size, package1loader);
/* Copy back the keys. */ /* Copy back the keys. */
memcpy((void *)tsec_key, (void *)tsec_keys, 0x10); memcpy((void *)tsec_key, (void *)tsec_keys, 0x10);
memcpy((void *)tsec_root_keys, (void *)tsec_keys + 0x10, 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("[NXBOOT] Failed to get TSEC key!\n");
} }
} }
//fatal_error("Ran sept!"); //fatal_error("Ran sept!");
/* Display splash screen. */ /* Display splash screen. */
display_splash_screen_bmp(loader_ctx->custom_splash_path, (void *)0xC0000000); 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. */ /* Derive keydata. If on 7.0.0+, sept has already derived keys for us. */
unsigned int keygen_type = 0; unsigned int keygen_type = 0;
if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_700) { if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_700) {
@ -665,27 +691,27 @@ uint32_t nxboot_main(void) {
if (warmboot_fw == NULL) { if (warmboot_fw == NULL) {
fatal_error("[NXBOOT] Out of memory!\n"); fatal_error("[NXBOOT] Out of memory!\n");
} }
memcpy(warmboot_fw, lp0fw_bin, warmboot_fw_size); memcpy(warmboot_fw, lp0fw_bin, warmboot_fw_size);
if (warmboot_fw_size == 0) { if (warmboot_fw_size == 0) {
fatal_error("[NXBOOT] Could not read the warmboot firmware from Package1!\n"); fatal_error("[NXBOOT] Could not read the warmboot firmware from Package1!\n");
} }
} }
/* Patch warmboot firmware for atmosphere. */ /* Patch warmboot firmware for atmosphere. */
if (warmboot_fw != NULL && warmboot_fw_size >= sizeof(warmboot_ams_header_t)) { if (warmboot_fw != NULL && warmboot_fw_size >= sizeof(warmboot_ams_header_t)) {
warmboot_ams_header_t *ams_header = (warmboot_ams_header_t *)warmboot_fw; warmboot_ams_header_t *ams_header = (warmboot_ams_header_t *)warmboot_fw;
if (ams_header->ams_metadata.magic == WARMBOOT_MAGIC) { if (ams_header->ams_metadata.magic == WARMBOOT_MAGIC) {
/* Set target firmware */ /* Set target firmware */
ams_header->ams_metadata.target_firmware = target_firmware; ams_header->ams_metadata.target_firmware = target_firmware;
/* Set RSA modulus */ /* Set RSA modulus */
const uint8_t *pkc_modulus = fuse_get_retail_type() != 0 ? retail_pkc_modulus : dev_pkc_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)); memcpy(ams_header->rsa_modulus, pkc_modulus, sizeof(ams_header->rsa_modulus));
} }
} }
/* Select the right address for the warmboot firmware. */ /* Select the right address for the warmboot firmware. */
if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < ATMOSPHERE_TARGET_FIRMWARE_400) { 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"); print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT] Rebuilding package2...\n");
/* Parse stratosphere config. */ /* Parse stratosphere config. */
nxboot_configure_stratosphere(MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware); nxboot_configure_stratosphere(MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware);
@ -770,10 +796,10 @@ uint32_t nxboot_main(void) {
free(package2); free(package2);
print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT] Powering on the CCPLEX...\n"); print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT] Powering on the CCPLEX...\n");
/* Unmount everything. */ /* Unmount everything. */
nxfs_end(); nxfs_end();
/* Return the memory address for booting CPU0. */ /* Return the memory address for booting CPU0. */
return (uint32_t)exosphere_memaddr; return (uint32_t)exosphere_memaddr;
} }

View file

@ -13,7 +13,7 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <atmosphere.h> #include <atmosphere.h>
@ -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) { 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"); fatal_error(u8"Error: Package2 has no unused section for Thermosphère!\n");
} }
/* Load Kernel from SD, if possible. */ /* Load Kernel from SD, if possible. */
{ {
size_t sd_kernel_size = get_file_size("atmosphere/kernel.bin"); 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. */ /* Perform any patches we want to the NX kernel. */
package2_patch_kernel(kernel, kernel_size, is_sd_kernel, (void *)&orig_ini1); 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. */ /* 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)) { (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_800 && orig_ini1 == NULL)) {
fatal_error("Error: inappropriate kernel embedded ini context"); fatal_error("Error: inappropriate kernel embedded ini context");
} }
print(SCREEN_LOG_LEVEL_DEBUG, "Rebuilding the INI1 section...\n"); print(SCREEN_LOG_LEVEL_DEBUG, "Rebuilding the INI1 section...\n");
if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_800) { if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_800) {
package2_get_src_section((void *)&orig_ini1, package2, PACKAGE2_SECTION_INI1); 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. */ /* Perform version checks. */
/* We will be compatible with all package2s released before current, but not newer ones. */ /* 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; return true;
} }

View file

@ -13,7 +13,7 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef FUSEE_PACKAGE2_H #ifndef FUSEE_PACKAGE2_H
#define FUSEE_PACKAGE2_H #define FUSEE_PACKAGE2_H
@ -36,7 +36,8 @@
#define PACKAGE2_MAXVER_500_510 0x7 #define PACKAGE2_MAXVER_500_510 0x7
#define PACKAGE2_MAXVER_600_610 0x8 #define PACKAGE2_MAXVER_600_610 0x8
#define PACKAGE2_MAXVER_620 0x9 #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_100 0x3
#define PACKAGE2_MINVER_200 0x4 #define PACKAGE2_MINVER_200 0x4
@ -46,7 +47,8 @@
#define PACKAGE2_MINVER_500_510 0x8 #define PACKAGE2_MINVER_500_510 0x8
#define PACKAGE2_MINVER_600_610 0x9 #define PACKAGE2_MINVER_600_610 0x9
#define PACKAGE2_MINVER_620 0xA #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)) #define NX_BOOTLOADER_PACKAGE2_LOAD_ADDRESS ((void *)(0xA9800000ull))
@ -79,7 +81,7 @@ typedef struct {
/* Package2 can be encrypted or unencrypted for these functions: */ /* Package2 can be encrypted or unencrypted for these functions: */
static inline size_t package2_meta_get_size(const package2_meta_t *metadata) { 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) { static inline uint8_t package2_meta_get_header_version(const package2_meta_t *metadata) {

View file

@ -14,7 +14,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <atmosphere/version.h> #include <atmosphere/version.h>
.macro CLEAR_GPR_REG_ITER .macro CLEAR_GPR_REG_ITER
mov r\@, #0 mov r\@, #0
.endm .endm
@ -27,7 +27,7 @@
.type _start, %function .type _start, %function
_start: _start:
b _crt0 b _crt0
.word (_metadata - _start) .word (_metadata - _start)
_crt0: _crt0:
@ -67,7 +67,7 @@ _crt0:
ldr r0, [r0] ldr r0, [r0]
ldr r1, [r1] ldr r1, [r1]
b main b main
/* Fusee-secondary header. */ /* Fusee-secondary header. */
.align 5 .align 5
_metadata: _metadata:
@ -168,12 +168,20 @@ _content_headers:
.asciz "sept_primary" .asciz "sept_primary"
.align 5 .align 5
/* sept_secondary content header */ /* sept_secondary 00 content header */
.word __sept_secondary_enc_start__ .word __sept_secondary_00_enc_start__
.word __sept_secondary_enc_size__ .word __sept_secondary_00_enc_size__
.word CONTENT_TYPE_SP2 .word CONTENT_TYPE_SP2
.word 0xCCCCCCCC .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 .align 5
/* sm content header */ /* sm content header */

View file

@ -1,7 +1,19 @@
HOVI_ENC_KEY_PRD = bytearray.fromhex('00000000000000000000000000000000') NUM_KEYS = 2
HOVI_ENC_KEY_DEV = bytearray.fromhex('00000000000000000000000000000000')
HOVI_SIG_KEY_PRD = bytearray.fromhex('00000000000000000000000000000000') HOVI_ENC_KEY_PRD = [
HOVI_SIG_KEY_DEV = bytearray.fromhex('00000000000000000000000000000000') bytearray.fromhex('00000000000000000000000000000000'),
HOVI_KEK_KEY_PRD = bytearray.fromhex('00000000000000000000000000000000') bytearray.fromhex('00000000000000000000000000000000'),
HOVI_KEK_KEY_DEV = bytearray.fromhex('00000000000000000000000000000000') ]
IV = 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

View file

@ -137,12 +137,12 @@ clean:
@echo clean ... @echo clean ...
@$(MAKE) -C $(AMS)/exosphere/rebootstub clean @$(MAKE) -C $(AMS)/exosphere/rebootstub clean
@$(MAKE) -C key_derivation 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 else
.PHONY: all .PHONY: all $(OUTPUT).bin
DEPENDS := $(OFILES:.o=.d) DEPENDS := $(OFILES:.o=.d)

View file

@ -20,7 +20,7 @@
#define AL16 __attribute__((aligned(16))) #define AL16 __attribute__((aligned(16)))
#define DERIVATION_ID_MAX 1 #define DERIVATION_ID_MAX 2
static const uint8_t AL16 keyblob_seed_00[0x10] = { 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 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] = { 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}, {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] = { 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}, {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) { void derive_keys(void) {
@ -101,7 +103,7 @@ void derive_keys(void) {
} }
/* Derive master kek. */ /* 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. */ /* Derive master key, device master key. */
decrypt_data_into_keyslot(0xC, 0xE, masterkey_seed, 0x10); 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); decrypt_data_into_keyslot(0xF, 0xF, devicekey_seed, 0x10);
/* Derive firmware specific device key. */ /* 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); decrypt_data_into_keyslot(0xE, 0xE, work_buffer, 0x10);
/* Clear work buffer. */ /* Clear work buffer. */

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python #!/usr/bin/env python
import sys import sys, os
from struct import pack as pk, unpack as up from struct import pack as pk, unpack as up
from Crypto.Cipher import AES from Crypto.Cipher import AES
from Crypto.Hash import CMAC from Crypto.Hash import CMAC
@ -41,7 +41,7 @@ def get_last_block_for_desired_mac(key, data, desired_mac):
return last_block 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. # Pad with 0x20 of zeroes.
code = code + bytearray(0x20) code = code + bytearray(0x20)
code_len = len(code) code_len = len(code)
@ -49,6 +49,9 @@ def sign_encrypt_code(code, sig_key, enc_key, iv, desired_mac):
code_len &= ~0xFFF code_len &= ~0xFFF
code = code + bytearray(code_len - len(code)) code = code + bytearray(code_len - len(code))
# Insert version
code = code[:8] + pk('<I', version) + code[12:]
# Add empty trustzone, warmboot segments. # Add empty trustzone, warmboot segments.
code = code + bytearray(0x1FE0 - 0x10) code = code + bytearray(0x1FE0 - 0x10)
pk11_hdr = b'PK11' + pk('<IIIIIII', 0x1000, 0, 0, code_len - 0x20, 0, 0x1000, 0) pk11_hdr = b'PK11' + pk('<IIIIIII', 0x1000, 0, 0, code_len - 0x20, 0, 0x1000, 0)
@ -69,8 +72,10 @@ def main(argc, argv):
if len(code) & 0xF: if len(code) & 0xF:
code = code + bytearray(0x10 - (len(code) & 0xF)) code = code + bytearray(0x10 - (len(code) & 0xF))
# TODO: Support dev unit crypto # TODO: Support dev unit crypto
with open(argv[2], 'wb') as f: fn, fext = os.path.splitext(argv[2])
f.write(sign_encrypt_code(code, KEYS.HOVI_SIG_KEY_PRD, KEYS.HOVI_ENC_KEY_PRD, KEYS.IV, b'THANKS_NVIDIA_<3')) for key in range(KEYS.NUM_KEYS):
with open(fn + ('_%02X' % key) + fext, 'wb') as f:
f.write(sign_encrypt_code(code, KEYS.HOVI_SIG_KEY_PRD[key], KEYS.HOVI_ENC_KEY_PRD[key], KEYS.IV[key], b'THANKS_NVIDIA_<3', key))
return 0 return 0

View file

@ -29,7 +29,7 @@
#undef u32 #undef u32
void derive_keys(void) { void derive_keys(uint32_t version) {
/* Clear mailbox. */ /* Clear mailbox. */
volatile uint32_t *mailbox = (volatile uint32_t *)0x4003FF00; volatile uint32_t *mailbox = (volatile uint32_t *)0x4003FF00;
while (*mailbox != 0) { while (*mailbox != 0) {
@ -37,7 +37,7 @@ void derive_keys(void) {
} }
/* Set derivation id. */ /* Set derivation id. */
*((volatile uint32_t *)0x4003E800) = 0x0; *((volatile uint32_t *)0x4003E800) = version;
/* Copy key derivation stub into IRAM high. */ /* Copy key derivation stub into IRAM high. */
for (size_t i = 0; i < key_derivation_bin_size; i += sizeof(uint32_t)) { for (size_t i = 0; i < key_derivation_bin_size; i += sizeof(uint32_t)) {

View file

@ -21,7 +21,7 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
void derive_keys(void); void derive_keys(uint32_t version);
void load_keys(const uint8_t *se_state); void load_keys(const uint8_t *se_state);
#endif #endif

View file

@ -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(); volatile tegra_pmc_t *pmc = pmc_get_regs();
uint8_t *enc_se_state = (uint8_t *)0x4003E000; uint8_t *enc_se_state = (uint8_t *)0x4003E000;
uint8_t *dec_se_state = (uint8_t *)0x4003F000; 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); set_has_rebooted(true);
/* Derive keys. */ /* Derive keys. */
derive_keys(); derive_keys(version);
reboot_to_self(); reboot_to_self();
} else { } else {
@ -135,14 +135,14 @@ static void exit_callback(int rc) {
relocate_and_chainload(); relocate_and_chainload();
} }
int main(void) { int sept_main(uint32_t version) {
const char *stage2_path; const char *stage2_path;
stage2_args_t *stage2_args; stage2_args_t *stage2_args;
uint32_t stage2_version = 0; uint32_t stage2_version = 0;
ScreenLogLevel log_level = SCREEN_LOG_LEVEL_NONE; ScreenLogLevel log_level = SCREEN_LOG_LEVEL_NONE;
/* Extract keys from the security engine, which TSEC FW locked down. */ /* 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. */ /* Override the global logging level. */
log_set_log_level(log_level); log_set_log_level(log_level);

View file

@ -13,7 +13,7 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
.macro CLEAR_GPR_REG_ITER .macro CLEAR_GPR_REG_ITER
mov r\@, #0 mov r\@, #0
.endm .endm
@ -26,13 +26,18 @@
_start: _start:
/* Switch to system mode, mask all interrupts, clear all flags */ /* Switch to system mode, mask all interrupts, clear all flags */
msr cpsr_cxsf, #0xDF msr cpsr_cxsf, #0xDF
b begin_relocation_loop
_version:
.word 0x00000000 /* Version. */
.word 0x00000000 /* Reserved. */
begin_relocation_loop:
/* Relocate ourselves if necessary */ /* Relocate ourselves if necessary */
ldr r2, =__start__ ldr r2, =__start__
adr r3, _start adr r3, _start
cmp r2, r3 cmp r2, r3
beq _relocation_loop_end beq _relocation_loop_end
/* If we are relocating, we are not rebooting to ourselves. Note that. */ /* If we are relocating, we are not rebooting to ourselves. Note that. */
ldr r0, =0x4003FFFC ldr r0, =0x4003FFFC
mov r1, #0x0 mov r1, #0x0
@ -50,12 +55,12 @@ _start:
ldr r12, =_second_relocation_start ldr r12, =_second_relocation_start
bx r12 bx r12
_second_relocation_start: _second_relocation_start:
ldr r4, =__bss_start__ ldr r4, =__bss_start__
sub r4, r4, r2 sub r4, r4, r2
mov r1, #0x0 mov r1, #0x0
_second_relocation_loop: _second_relocation_loop:
ldmia r3!, {r5-r12} ldmia r3!, {r5-r12}
stmia r2!, {r5-r12} stmia r2!, {r5-r12}
@ -67,7 +72,7 @@ _start:
bx r12 bx r12
_relocation_loop_end: _relocation_loop_end:
/* Set the stack pointer */ /* Set the stack pointer */
ldr sp, =__stack_top__ ldr sp, =__stack_top__
mov fp, #0 mov fp, #0
@ -78,7 +83,9 @@ _start:
CLEAR_GPR_REG_ITER CLEAR_GPR_REG_ITER
.endr .endr
ldr lr, =__program_exit ldr lr, =__program_exit
b main ldr r0, =_version
ldr r0, [r0]
b sept_main
/* No need to include this in normal programs: */ /* No need to include this in normal programs: */
.section .chainloader.text.start, "ax", %progbits .section .chainloader.text.start, "ax", %progbits