Skip to content

Instantly share code, notes, and snippets.

@SciresM
Last active August 31, 2018 06:00
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SciresM/d1a1e00e95dae2d23f5a224b15fae769 to your computer and use it in GitHub Desktop.
Save SciresM/d1a1e00e95dae2d23f5a224b15fae769 to your computer and use it in GitHub Desktop.
diff --git a/exosphere/src/bootup.c b/exosphere/src/bootup.c
index a1fd252..e81ff1a 100644
--- a/exosphere/src/bootup.c
+++ b/exosphere/src/bootup.c
@@ -30,6 +30,23 @@
static bool g_has_booted_up = false;
+
+void setup_dram_magic_numbers(void) {
+ /* TODO: Why does these DRAM write occur? */
+ unsigned int target_fw = exosphere_get_target_firmware();
+ if (EXOSPHERE_TARGET_FIRMWARE_400 <= target_fw) {
+ (*(volatile uint32_t *)(0x8005FFFC)) = 0xC0EDBBCC;
+ flush_dcache_range((void *)0x8005FFFC, (void *)0x80060000);
+ if (EXOSPHERE_TARGET_FIRMWARE_600 <= target_fw) {
+ (*(volatile uint32_t *)(0x8005FF00)) = 0x00000083;
+ (*(volatile uint32_t *)(0x8005FF04)) = 0x00000002;
+ (*(volatile uint32_t *)(0x8005FF08)) = 0x00000210;
+ flush_dcache_range((void *)0x8005FF00, (void *)0x8005FF0C);
+ }
+ }
+ __dsb_sy();
+}
+
void bootup_misc_mmio(void) {
/* Initialize Fuse registers. */
fuse_init();
@@ -50,10 +67,8 @@ void bootup_misc_mmio(void) {
se_generate_random_key(KEYSLOT_SWITCH_SRKGENKEY, KEYSLOT_SWITCH_RNGKEY);
se_generate_srk(KEYSLOT_SWITCH_SRKGENKEY);
- /* TODO: Why does this DRAM write occur? */
- if (!g_has_booted_up && exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_400) {
- /* 4.x writes this magic number into DRAM. Why? */
- (*(volatile uint32_t *)(0x8005FFFC)) = 0xC0EDBBCC;
+ if (!g_has_booted_up && EXOSPHERE_TARGET_FIRMWARE_600 > exosphere_get_target_firmware() && exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_400) {
+ setup_dram_magic_numbers();
}
/* Todo: What? */
@@ -201,6 +216,9 @@ void bootup_misc_mmio(void) {
}
void setup_4x_mmio(void) {
+ if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_600) {
+ configure_gpu_ucode_carveout();
+ }
/* TODO: What are these MC reg writes? */
MAKE_MC_REG(0x65C) = 0xFFFFF000;
MAKE_MC_REG(0x660) = 0;
diff --git a/exosphere/src/bootup.h b/exosphere/src/bootup.h
index 2f5f0d1..ccbed95 100644
--- a/exosphere/src/bootup.h
+++ b/exosphere/src/bootup.h
@@ -86,6 +86,8 @@ void bootup_misc_mmio(void);
void setup_4x_mmio(void);
+void setup_dram_magic_numbers(void);
+
void setup_current_core_state(void);
void identity_unmap_iram_cd_tzram(void);
diff --git a/exosphere/src/exocfg.h b/exosphere/src/exocfg.h
index f02aa24..45413a9 100644
--- a/exosphere/src/exocfg.h
+++ b/exosphere/src/exocfg.h
@@ -16,9 +16,10 @@
#define EXOSPHERE_TARGET_FIRMWARE_300 3
#define EXOSPHERE_TARGET_FIRMWARE_400 4
#define EXOSPHERE_TARGET_FIRMWARE_500 5
+#define EXOSPHERE_TARGET_FIRMWARE_600 6
/* TODO: What should this be, for release? */
-#define EXOSPHERE_TARGET_FIRMWARE_DEFAULT_FOR_DEBUG EXOSPHERE_TARGET_FIRMWARE_500
+#define EXOSPHERE_TARGET_FIRMWARE_DEFAULT_FOR_DEBUG EXOSPHERE_TARGET_FIRMWARE_600
#define EXOSPHERE_LOOSEN_PACKAGE2_RESTRICTIONS_FOR_DEBUG 1
#define MAILBOX_BASE_PHYS (MMIO_GET_DEVICE_PA(MMIO_DEVID_NXBOOTLOADER_MAILBOX))
diff --git a/exosphere/src/lp0.c b/exosphere/src/lp0.c
index 1dc0f9c..f0ee55e 100644
--- a/exosphere/src/lp0.c
+++ b/exosphere/src/lp0.c
@@ -228,12 +228,13 @@ void save_se_and_power_down_cpu(void) {
/* TODO: uart_log("OYASUMI"); */
}
- __dsb_sy();
-
finalize_powerdown();
}
uint32_t cpu_suspend(uint64_t power_state, uint64_t entrypoint, uint64_t argument) {
+ /* TODO: 6.0.0 introduces heavy deja vu mitigations. */
+ /* Exosphere may want to implement these. */
+
/* Ensure SMC call is to enter deep sleep. */
if ((power_state & 0x17FFF) != 0x1001B) {
return 0xFFFFFFFD;
diff --git a/exosphere/src/masterkey.c b/exosphere/src/masterkey.c
index 4b83da8..6926c99 100644
--- a/exosphere/src/masterkey.c
+++ b/exosphere/src/masterkey.c
@@ -23,6 +23,7 @@ static const uint8_t mkey_vectors_dev[MASTERKEY_REVISION_MAX][0x10] =
{0x97, 0x29, 0xB0, 0x32, 0x43, 0x14, 0x8C, 0xA6, 0x85, 0xE9, 0x5A, 0x94, 0x99, 0x39, 0xAC, 0x5D}, /* Master key 01 encrypted with Master key 02. */
{0x2C, 0xCA, 0x9C, 0x31, 0x1E, 0x07, 0xB0, 0x02, 0x97, 0x0A, 0xD8, 0x03, 0xA2, 0x76, 0x3F, 0xA3}, /* Master key 02 encrypted with Master key 03. */
{0x9B, 0x84, 0x76, 0x14, 0x72, 0x94, 0x52, 0xCB, 0x54, 0x92, 0x9B, 0xC4, 0x8C, 0x5B, 0x0F, 0xBA}, /* Master key 03 encrypted with Master key 04. */
+ {0x78, 0xD5, 0xF1, 0x20, 0x3D, 0x16, 0xE9, 0x30, 0x32, 0x27, 0x34, 0x6F, 0xCF, 0xE0, 0x27, 0xDC}, /* Master key 04 encrypted with Master key 05. */
};
/* Retail unit keys. */
@@ -33,6 +34,7 @@ static const uint8_t mkey_vectors[MASTERKEY_REVISION_MAX][0x10] =
{0xDE, 0xCF, 0xEB, 0xEB, 0x10, 0xAE, 0x74, 0xD8, 0xAD, 0x7C, 0xF4, 0x9E, 0x62, 0xE0, 0xE8, 0x72}, /* Master key 01 encrypted with Master key 02. */
{0x0A, 0x0D, 0xDF, 0x34, 0x22, 0x06, 0x6C, 0xA4, 0xE6, 0xB1, 0xEC, 0x71, 0x85, 0xCA, 0x4E, 0x07}, /* Master key 02 encrypted with Master key 03. */
{0x6E, 0x7D, 0x2D, 0xC3, 0x0F, 0x59, 0xC8, 0xFA, 0x87, 0xA8, 0x2E, 0xD5, 0x89, 0x5E, 0xF3, 0xE9}, /* Master key 03 encrypted with Master key 04. */
+ {0xEB, 0xF5, 0x6F, 0x83, 0x61, 0x9E, 0xF8, 0xFA, 0xE0, 0x87, 0xD7, 0xA1, 0x4E, 0x25, 0x36, 0xEE}, /* Master key 04 encrypted with Master key 05. */
};
bool check_mkey_revision(unsigned int revision, bool is_retail) {
@@ -105,7 +107,7 @@ unsigned int mkey_get_keyslot(unsigned int revision) {
void set_old_devkey(unsigned int revision, const uint8_t *key) {
- if (revision < MASTERKEY_REVISION_400_410 || MASTERKEY_REVISION_500_CURRENT <= revision) {
+ if (revision < MASTERKEY_REVISION_400_410 || MASTERKEY_REVISION_600_CURRENT <= revision) {
generic_panic();
}
@@ -122,7 +124,7 @@ unsigned int devkey_get_keyslot(unsigned int revision) {
}
if (revision >= 1) {
- if (revision == MASTERKEY_REVISION_500_CURRENT) {
+ if (revision == MASTERKEY_REVISION_600_CURRENT) {
return KEYSLOT_SWITCH_DEVICEKEY;
} else {
/* Load into a temp keyslot. */
diff --git a/exosphere/src/masterkey.h b/exosphere/src/masterkey.h
index 5a6a523..9a43454 100644
--- a/exosphere/src/masterkey.h
+++ b/exosphere/src/masterkey.h
@@ -3,14 +3,15 @@
/* This is glue code to enable master key support across versions. */
-/* TODO: Update to 0x6 on release of new master key. */
-#define MASTERKEY_REVISION_MAX 0x5
+/* TODO: Update to 0x7 on release of new master key. */
+#define MASTERKEY_REVISION_MAX 0x6
#define MASTERKEY_REVISION_100_230 0x00
#define MASTERKEY_REVISION_300 0x01
#define MASTERKEY_REVISION_301_302 0x02
#define MASTERKEY_REVISION_400_410 0x03
-#define MASTERKEY_REVISION_500_CURRENT 0x04
+#define MASTERKEY_REVISION_500_510 0x04
+#define MASTERKEY_REVISION_600_CURRENT 0x05
#define MASTERKEY_NUM_NEW_DEVICE_KEYS (MASTERKEY_REVISION_MAX - MASTERKEY_REVISION_400_410)
diff --git a/exosphere/src/mc.c b/exosphere/src/mc.c
index 4a4aed9..080e6d7 100644
--- a/exosphere/src/mc.c
+++ b/exosphere/src/mc.c
@@ -22,40 +22,48 @@ volatile security_carveout_t *get_carveout_by_id(unsigned int carveout) {
return NULL;
}
-void configure_default_carveouts(void) {
- /* Configure Carveout 1 (UNUSED) */
- volatile security_carveout_t *carveout = get_carveout_by_id(1);
- carveout->paddr_low = 0;
+void configure_gpu_ucode_carveout(void) {
+ /* Starting in 6.0.0, Carveout 2 is configured later on. */
+ /* This is a helper function to make this easier... */
+ volatile security_carveout_t *carveout = get_carveout_by_id(2);
+ carveout->paddr_low = 0x80020000;
carveout->paddr_high = 0;
- carveout->size_big_pages = 0;
+ carveout->size_big_pages = 2; /* 0x40000 */
carveout->flags_0 = 0;
carveout->flags_1 = 0;
- carveout->flags_2 = 0;
+ carveout->flags_2 = 0x3000000;
carveout->flags_3 = 0;
- carveout->flags_4 = 0;
+ carveout->flags_4 = 0x300;
carveout->flags_5 = 0;
carveout->flags_6 = 0;
carveout->flags_7 = 0;
carveout->flags_8 = 0;
carveout->flags_9 = 0;
- carveout->allowed_clients = 0x04000006;
+ carveout->allowed_clients = 0x440167E;
+}
- /* Configure Carveout 2 (GPU UCODE) */
- carveout = get_carveout_by_id(2);
- carveout->paddr_low = 0x80020000;
+void configure_default_carveouts(void) {
+ /* Configure Carveout 1 (UNUSED) */
+ volatile security_carveout_t *carveout = get_carveout_by_id(1);
+ carveout->paddr_low = 0;
carveout->paddr_high = 0;
- carveout->size_big_pages = 2; /* 0x40000 */
+ carveout->size_big_pages = 0;
carveout->flags_0 = 0;
carveout->flags_1 = 0;
- carveout->flags_2 = 0x3000000;
+ carveout->flags_2 = 0;
carveout->flags_3 = 0;
- carveout->flags_4 = 0x300;
+ carveout->flags_4 = 0;
carveout->flags_5 = 0;
carveout->flags_6 = 0;
carveout->flags_7 = 0;
carveout->flags_8 = 0;
carveout->flags_9 = 0;
- carveout->allowed_clients = 0x440167E;
+ carveout->allowed_clients = 0x04000006;
+
+ /* Configure Carveout 2 (GPU UCODE) */
+ if (exosphere_get_target_firmware() < EXOSPHERE_TARGET_FIRMWARE_600) {
+ configure_gpu_ucode_carveout();
+ }
/* Configure Carveout 3 (UNUSED GPU) */
carveout = get_carveout_by_id(3);
diff --git a/exosphere/src/mc.h b/exosphere/src/mc.h
index de51417..3e735e3 100644
--- a/exosphere/src/mc.h
+++ b/exosphere/src/mc.h
@@ -50,6 +50,7 @@ typedef struct {
volatile security_carveout_t *get_carveout_by_id(unsigned int carveout);
void configure_default_carveouts(void);
+void configure_gpu_ucode_carveout(void);
void configure_kernel_carveout(unsigned int carveout_id, uint64_t address, uint64_t size);
diff --git a/exosphere/src/package2.c b/exosphere/src/package2.c
index 26db125..78d953c 100644
--- a/exosphere/src/package2.c
+++ b/exosphere/src/package2.c
@@ -22,20 +22,31 @@
extern void *__start_cold_addr;
extern size_t __bin_size;
+
+static const uint8_t new_device_key_sources[MASTERKEY_NUM_NEW_DEVICE_KEYS][0x10] = {
+ {0x8B, 0x4E, 0x1C, 0x22, 0x42, 0x07, 0xC8, 0x73, 0x56, 0x94, 0x08, 0x8B, 0xCC, 0x47, 0x0F, 0x5D}, /* 4.x New Device Key Source. */
+ {0x6C, 0xEF, 0xC6, 0x27, 0x8B, 0xEC, 0x8A, 0x91, 0x99, 0xAB, 0x24, 0xAC, 0x4F, 0x1C, 0x8F, 0x1C}, /* 5.x New Device Key Source. */
+ {0x70, 0x08, 0x1B, 0x97, 0x44, 0x64, 0xF8, 0x91, 0x54, 0x9D, 0xC6, 0x84, 0x8F, 0x1A, 0xB2, 0xE4} /* 6.x New Device Key Source. */
+};
+
+static const uint8_t new_device_keygen_sources[MASTERKEY_NUM_NEW_DEVICE_KEYS][0x10] = {
+ {0x88, 0x62, 0x34, 0x6E, 0xFA, 0xF7, 0xD8, 0x3F, 0xE1, 0x30, 0x39, 0x50, 0xF0, 0xB7, 0x5D, 0x5D}, /* 4.x New Device Keygen Source. */
+ {0x06, 0x1E, 0x7B, 0xE9, 0x6D, 0x47, 0x8C, 0x77, 0xC5, 0xC8, 0xE7, 0x94, 0x9A, 0xA8, 0x5F, 0x2E}, /* 5.x New Device Keygen Source. */
+ {0x99, 0xFA, 0x98, 0xBD, 0x15, 0x1C, 0x72, 0xFD, 0x7D, 0x9A, 0xD5, 0x41, 0x00, 0xFD, 0xB2, 0xEF} /* 6.x New Device Keygen Source. */
+};
+
+static const uint8_t new_device_keygen_sources_dev[MASTERKEY_NUM_NEW_DEVICE_KEYS][0x10] = {
+ {0xD6, 0xBD, 0x9F, 0xC6, 0x18, 0x09, 0xE1, 0x96, 0x20, 0x39, 0x60, 0xD2, 0x89, 0x83, 0x31, 0x34}, /* 4.x New Device Keygen Source. */
+ {0x59, 0x2D, 0x20, 0x69, 0x33, 0xB5, 0x17, 0xBA, 0xCF, 0xB1, 0x4E, 0xFD, 0xE4, 0xC2, 0x7B, 0xA8}, /* 5.x New Device Keygen Source. */
+ {0xF6, 0xD8, 0x59, 0x63, 0x8F, 0x47, 0xCB, 0x4A, 0xD8, 0x74, 0x05, 0x7F, 0x88, 0x92, 0x33, 0xA5} /* 6.x New Device Keygen Source. */
+};
+
static void derive_new_device_keys(unsigned int keygen_keyslot) {
uint8_t work_buffer[0x10];
- static const uint8_t new_device_key_sources[MASTERKEY_NUM_NEW_DEVICE_KEYS][0x10] = {
- {0x8B, 0x4E, 0x1C, 0x22, 0x42, 0x07, 0xC8, 0x73, 0x56, 0x94, 0x08, 0x8B, 0xCC, 0x47, 0x0F, 0x5D}, /* 4.x New Device Key Source. */
- {0x6C, 0xEF, 0xC6, 0x27, 0x8B, 0xEC, 0x8A, 0x91, 0x99, 0xAB, 0x24, 0xAC, 0x4F, 0x1C, 0x8F, 0x1C} /* 5.x New Device Key Source. */
- };
-
- static const uint8_t new_device_keygen_sources[MASTERKEY_NUM_NEW_DEVICE_KEYS][0x10] = {
- {0x88, 0x62, 0x34, 0x6E, 0xFA, 0xF7, 0xD8, 0x3F, 0xE1, 0x30, 0x39, 0x50, 0xF0, 0xB7, 0x5D, 0x5D}, /* 4.x New Device Keygen Source. */
- {0x06, 0x1E, 0x7B, 0xE9, 0x6D, 0x47, 0x8C, 0x77, 0xC5, 0xC8, 0xE7, 0x94, 0x9A, 0xA8, 0x5F, 0x2E} /* 5.x New Device Keygen Source. */
- };
+ bool is_retail = configitem_is_retail();
for (unsigned int revision = 0; revision < MASTERKEY_NUM_NEW_DEVICE_KEYS; revision++) {
se_aes_ecb_decrypt_block(keygen_keyslot, work_buffer, 0x10, new_device_key_sources[revision], 0x10);
- decrypt_data_into_keyslot(KEYSLOT_SWITCH_TEMPKEY, mkey_get_keyslot(0), new_device_keygen_sources[revision], 0x10);
+ decrypt_data_into_keyslot(KEYSLOT_SWITCH_TEMPKEY, mkey_get_keyslot(0), is_retail ? new_device_keygen_sources[revision] : new_device_keygen_sources_dev[revision], 0x10);
if (revision < MASTERKEY_NUM_NEW_DEVICE_KEYS - 1) {
se_aes_ecb_decrypt_block(KEYSLOT_SWITCH_TEMPKEY, work_buffer, 0x10, work_buffer, 0x10);
set_old_devkey(revision + MASTERKEY_REVISION_400_410, work_buffer);
@@ -94,6 +105,7 @@ static void setup_se(void) {
derive_new_device_keys(KEYSLOT_SWITCH_4XNEWDEVICEKEYGENKEY);
break;
case EXOSPHERE_TARGET_FIRMWARE_500:
+ case EXOSPHERE_TARGET_FIRMWARE_600:
derive_new_device_keys(KEYSLOT_SWITCH_5XNEWDEVICEKEYGENKEY);
break;
}
@@ -120,14 +132,18 @@ static void setup_boot_config(void) {
if (configitem_is_retail()) {
bootconfig_clear();
} else {
- flush_dcache_range((uint8_t *)NX_BOOTLOADER_BOOTCONFIG_POINTER, (uint8_t *)NX_BOOTLOADER_BOOTCONFIG_POINTER + sizeof(bootconfig_t));
- bootconfig_load_and_verify((bootconfig_t *)NX_BOOTLOADER_BOOTCONFIG_POINTER);
+ void *bootconfig_ptr = NX_BOOTLOADER_BOOTCONFIG_POINTER;
+ if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_600) {
+ bootconfig_ptr = NX_BOOTLOADER_BOOTCONFIG_POINTER_6X;
+ }
+ flush_dcache_range((uint8_t *)bootconfig_ptr, (uint8_t *)bootconfig_ptr + sizeof(bootconfig_t));
+ bootconfig_load_and_verify((bootconfig_t *)bootconfig_ptr);
}
}
static void package2_crypt_ctr(unsigned int master_key_rev, void *dst, size_t dst_size, const void *src, size_t src_size, const void *ctr, size_t ctr_size) {
/* Derive package2 key. */
- const uint8_t package2_key_source[0x10] = {0xFB, 0x8B, 0x6A, 0x9C, 0x79, 0x00, 0xC8, 0x49, 0xEF, 0xD2, 0x4D, 0x85, 0x4D, 0x30, 0xA0, 0xC7};
+ static const uint8_t package2_key_source[0x10] = {0xFB, 0x8B, 0x6A, 0x9C, 0x79, 0x00, 0xC8, 0x49, 0xEF, 0xD2, 0x4D, 0x85, 0x4D, 0x30, 0xA0, 0xC7};
flush_dcache_range((uint8_t *)dst, (uint8_t *)dst + dst_size);
flush_dcache_range((uint8_t *)src, (uint8_t *)src + src_size);
unsigned int keyslot = mkey_get_keyslot(master_key_rev);
@@ -383,7 +399,22 @@ static void load_package2_sections(package2_meta_t *metadata, uint32_t master_ke
}
static void copy_warmboot_bin_to_dram() {
- uint8_t *warmboot_src = (uint8_t *)0x4003B000;
+ uint8_t *warmboot_src;
+ switch (exosphere_get_target_firmware()) {
+ case EXOSPHERE_TARGET_FIRMWARE_100:
+ case EXOSPHERE_TARGET_FIRMWARE_200:
+ case EXOSPHERE_TARGET_FIRMWARE_300:
+ default:
+ generic_panic();
+ break;
+ case EXOSPHERE_TARGET_FIRMWARE_400:
+ case EXOSPHERE_TARGET_FIRMWARE_500:
+ warmboot_src = (uint8_t *)0x4003B000;
+ break;
+ case EXOSPHERE_TARGET_FIRMWARE_600:
+ warmboot_src = (uint8_t *)0x4003D800;
+ break;
+ }
uint8_t *warmboot_dst = (uint8_t *)0x8000D000;
const size_t warmboot_size = 0x2000;
@@ -432,8 +463,18 @@ void load_package2(coldboot_crt0_reloc_list_t *reloc_list) {
MAKE_REG32(PMC_BASE + 0x054) = 0x8000D000;
MAKE_REG32(PMC_BASE + 0x0A0) &= 0xFFF3FFFF;
MAKE_REG32(PMC_BASE + 0x818) &= 0xFFFFFFFE;
- MAKE_REG32(PMC_BASE + 0x334) |= 0x10;
- MAKE_REG32(PMC_BASE + 0x360) = 6;
+ MAKE_REG32(PMC_BASE + 0x334) |= 0x10;
+ switch (exosphere_get_target_firmware()) {
+ case EXOSPHERE_TARGET_FIRMWARE_400:
+ MAKE_REG32(PMC_BASE + 0x360) = 5;
+ break;
+ case EXOSPHERE_TARGET_FIRMWARE_500:
+ MAKE_REG32(PMC_BASE + 0x360) = 6;
+ break;
+ case EXOSPHERE_TARGET_FIRMWARE_600:
+ MAKE_REG32(PMC_BASE + 0x360) = 0x87;
+ break;
+ }
}
wait(1000);
@@ -449,7 +490,7 @@ void load_package2(coldboot_crt0_reloc_list_t *reloc_list) {
randomcache_init();
/* memclear the initial copy of Exosphere running in IRAM (relocated to TZRAM by earlier code). */
- memset((void *)reloc_list->reloc_base, 0, reloc_list->loaded_bin_size);
+ //memset((void *)reloc_list->reloc_base, 0, reloc_list->loaded_bin_size);
/* Let NX Bootloader know that we're running. */
MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE = 1;
@@ -474,6 +515,9 @@ void load_package2(coldboot_crt0_reloc_list_t *reloc_list) {
if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_400) {
sync_with_nx_bootloader(NX_BOOTLOADER_STATE_DRAM_INITIALIZED_4X);
copy_warmboot_bin_to_dram();
+ if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_600) {
+ setup_dram_magic_numbers();
+ }
sync_with_nx_bootloader(NX_BOOTLOADER_STATE_LOADED_PACKAGE2_4X);
} else {
sync_with_nx_bootloader(NX_BOOTLOADER_STATE_LOADED_PACKAGE2);
diff --git a/exosphere/src/package2.h b/exosphere/src/package2.h
index 156ab52..94ddd46 100644
--- a/exosphere/src/package2.h
+++ b/exosphere/src/package2.h
@@ -34,6 +34,7 @@ static inline uintptr_t get_nx_bootloader_mailbox_base(void) {
#define MAILBOX_NX_BOOTLOADER_BOOT_REASON (MAILBOX_NX_BOOTLOADER_BASE + 0xE10ULL)
#define NX_BOOTLOADER_BOOTCONFIG_POINTER ((void *)(0x4003D000ull))
+#define NX_BOOTLOADER_BOOTCONFIG_POINTER_6X ((void *)(0x4003F800ull))
#define NX_BOOTLOADER_PACKAGE2_LOAD_ADDRESS ((void *)(0xA9800000ull))
diff --git a/exosphere/src/smc_api.c b/exosphere/src/smc_api.c
index a0f9607..6d33fd0 100644
--- a/exosphere/src/smc_api.c
+++ b/exosphere/src/smc_api.c
@@ -142,6 +142,7 @@ void set_version_specific_smcs(void) {
/* Do nothing. */
break;
case EXOSPHERE_TARGET_FIRMWARE_500:
+ case EXOSPHERE_TARGET_FIRMWARE_600:
/* No more LoadSecureExpModKey. */
g_smc_user_table[0xE].handler = NULL;
g_smc_user_table[0xC].id = 0xC300D60C;
diff --git a/exosphere/src/smc_user.c b/exosphere/src/smc_user.c
index 4f88365..ee440bb 100644
--- a/exosphere/src/smc_user.c
+++ b/exosphere/src/smc_user.c
@@ -24,6 +24,20 @@ static uint8_t g_imported_exponents[4][0x100];
static uint8_t g_rsausecase_to_cryptousecase[5] = {1, 2, 3, 5, 6};
+static bool is_user_keyslot_valid(unsigned int keyslot) {
+ switch (exosphere_get_target_firmware()) {
+ case EXOSPHERE_TARGET_FIRMWARE_100:
+ case EXOSPHERE_TARGET_FIRMWARE_200:
+ case EXOSPHERE_TARGET_FIRMWARE_300:
+ case EXOSPHERE_TARGET_FIRMWARE_400:
+ case EXOSPHERE_TARGET_FIRMWARE_500:
+ return keyslot <= 3;
+ case EXOSPHERE_TARGET_FIRMWARE_600:
+ default:
+ return keyslot <= 5;
+ }
+}
+
void set_exp_mod_done(bool done) {
g_exp_mod_done = done;
}
@@ -136,7 +150,7 @@ uint32_t user_generate_aes_kek(smc_args_t *args) {
/* 5.0.0+ Bounds checking. */
if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_500) {
if (is_personalized) {
- if (master_key_rev > MASTERKEY_REVISION_500_CURRENT || ((1 << (master_key_rev + 1)) & 0x33) == 0) {
+ if (master_key_rev > MASTERKEY_REVISION_600_CURRENT || ((1 << (master_key_rev + 1)) & 0x73) == 0) {
return 2;
}
if (mask_id > 3 || usecase >= CRYPTOUSECASE_MAX_5X) {
@@ -222,7 +236,7 @@ uint32_t user_load_aes_key(smc_args_t *args) {
uint64_t wrapped_key[2];
uint32_t keyslot = (uint32_t)args->X[1];
- if (keyslot > 3) {
+ if (!is_user_keyslot_valid(keyslot)) {
return 2;
}
@@ -262,6 +276,10 @@ uint32_t crypt_aes_done_handler(void) {
uint32_t user_crypt_aes(smc_args_t *args) {
uint32_t keyslot = args->X[1] & 3;
uint32_t mode = (args->X[1] >> 4) & 3;
+
+ if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_600) {
+ keyslot = args->X[1] & 7;
+ }
uint64_t iv_ctr[2];
iv_ctr[0] = args->X[2];
@@ -271,7 +289,7 @@ uint32_t user_crypt_aes(smc_args_t *args) {
uint32_t out_ll_paddr = (uint32_t)(args->X[5]);
size_t size = args->X[6];
- if (size & 0xF) {
+ if (!is_user_keyslot_valid(keyslot) || size & 0xF) {
return 2;
}
@@ -390,7 +408,7 @@ uint32_t user_compute_cmac(smc_args_t *args) {
upage_ref_t page_ref;
/* Validate keyslot and size. */
- if (keyslot > 3 || args->X[3] > 0x400) {
+ if (!is_user_keyslot_valid(keyslot) || args->X[3] > 0x400) {
return 2;
}
@@ -626,7 +644,16 @@ uint32_t user_unwrap_rsa_oaep_wrapped_titlekey(smc_args_t *args) {
void *user_wrapped_key = (void *)args->X[1];
void *user_modulus = (void *)args->X[2];
- unsigned int master_key_rev = (unsigned int)args->X[7];
+ unsigned int option = (unsigned int)args->X[7];
+ unsigned int master_key_rev;
+ unsigned int titlekey_type;
+ if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_600) {
+ master_key_rev = option & 0x3F;
+ titlekey_type = (option >> 6) & 1;
+ } else {
+ master_key_rev = option;
+ titlekey_type = 0;
+ }
if(master_key_rev > 0) {
master_key_rev -= 1;
@@ -657,6 +684,7 @@ uint32_t user_unwrap_rsa_oaep_wrapped_titlekey(smc_args_t *args) {
tkey_set_expected_label_hash(&args->X[3]);
tkey_set_master_key_rev(master_key_rev);
+ tkey_set_type(titlekey_type);
/* Hardcode RSA keyslot 0. */
set_rsa_keyslot(0, modulus, 0x100, g_imported_exponents[0], 0x100);
@@ -670,7 +698,7 @@ uint32_t user_load_titlekey(smc_args_t *args) {
uint64_t sealed_titlekey[2];
uint32_t keyslot = (uint32_t)args->X[1];
- if (keyslot > 3) {
+ if (!is_user_keyslot_valid(keyslot)) {
return 2;
}
@@ -705,6 +733,7 @@ uint32_t user_unwrap_aes_wrapped_titlekey(smc_args_t *args) {
}
tkey_set_master_key_rev(master_key_rev);
+ tkey_set_type(0);
tkey_aes_unwrap(titlekey, 0x10, aes_wrapped_titlekey, 0x10);
seal_titlekey(sealed_titlekey, 0x10, titlekey, 0x10);
diff --git a/exosphere/src/titlekey.c b/exosphere/src/titlekey.c
index 4c46ed2..7e2d4ea 100644
--- a/exosphere/src/titlekey.c
+++ b/exosphere/src/titlekey.c
@@ -3,6 +3,7 @@
#include "utils.h"
#include "arm.h"
+#include "exocfg.h"
#include "titlekey.h"
#include "masterkey.h"
@@ -10,6 +11,7 @@
static uint64_t g_tkey_expected_label_hash[4];
static unsigned int g_tkey_master_key_rev = MASTERKEY_REVISION_MAX;
+static unsigned int g_tkey_type = 0;
/* Set the expected db prefix. */
void tkey_set_expected_label_hash(uint64_t *label_hash) {
@@ -25,6 +27,17 @@ void tkey_set_master_key_rev(unsigned int master_key_rev) {
g_tkey_master_key_rev = master_key_rev;
}
+static void tkey_validate_type(unsigned int type) {
+ if (type > TITLEKEY_TYPE_MAX || (type > 0 && exosphere_get_target_firmware() < EXOSPHERE_TARGET_FIRMWARE_600)) {
+ generic_panic();
+ }
+}
+
+void tkey_set_type(unsigned int type) {
+ tkey_validate_type(type);
+ g_tkey_type = type;
+}
+
/* Reference for MGF1 can be found here: https://en.wikipedia.org/wiki/Mask_generation_function#MGF1 */
void calculate_mgf1_and_xor(void *masked, size_t masked_size, const void *seed, size_t seed_size) {
uint8_t cur_hash[0x20];
@@ -136,18 +149,19 @@ size_t tkey_rsa_oaep_unwrap(void *dst, size_t dst_size, void *src, size_t src_si
return wrapped_titlekey_size;
}
+static const uint8_t titlekek_sources[TITLEKEY_TYPE_MAX+1][0x10] = {
+ {0x1E, 0xDC, 0x7B, 0x3B, 0x60, 0xE6, 0xB4, 0xD8, 0x78, 0xB8, 0x17, 0x15, 0x98, 0x5E, 0x62, 0x9B},
+ {0x3B, 0x78, 0xF2, 0x61, 0x0F, 0x9D, 0x5A, 0xE2, 0x7B, 0x4E, 0x45, 0xAF, 0xCB, 0x0B, 0x67, 0x4D}
+};
+
void tkey_aes_unwrap(void *dst, size_t dst_size, const void *src, size_t src_size) {
if (g_tkey_master_key_rev >= MASTERKEY_REVISION_MAX || dst_size != 0x10 || src_size != 0x10) {
generic_panic();
}
-
- const uint8_t titlekek_source[0x10] = {
- 0x1E, 0xDC, 0x7B, 0x3B, 0x60, 0xE6, 0xB4, 0xD8, 0x78, 0xB8, 0x17, 0x15, 0x98, 0x5E, 0x62, 0x9B
- };
-
+
/* Generate the appropriate titlekek into keyslot 9. */
unsigned int master_keyslot = mkey_get_keyslot(g_tkey_master_key_rev);
- decrypt_data_into_keyslot(KEYSLOT_SWITCH_TEMPKEY, master_keyslot, titlekek_source, 0x10);
+ decrypt_data_into_keyslot(KEYSLOT_SWITCH_TEMPKEY, master_keyslot, titlekek_sources[g_tkey_type], 0x10);
/* Unwrap the titlekey using the titlekek. */
se_aes_ecb_decrypt_block(KEYSLOT_SWITCH_TEMPKEY, dst, 0x10, src, 0x10);
diff --git a/exosphere/src/titlekey.h b/exosphere/src/titlekey.h
index a74949b..6d19a2d 100644
--- a/exosphere/src/titlekey.h
+++ b/exosphere/src/titlekey.h
@@ -3,8 +3,11 @@
#include <stdint.h>
+#define TITLEKEY_TYPE_MAX 0x1
+
void tkey_set_expected_label_hash(uint64_t *label_hash);
void tkey_set_master_key_rev(unsigned int master_key_rev);
+void tkey_set_type(unsigned int type);
size_t tkey_rsa_oaep_unwrap(void *dst, size_t dst_size, void *src, size_t src_size);
diff --git a/exosphere/src/utils.c b/exosphere/src/utils.c
index 2f60fbf..09d3938 100644
--- a/exosphere/src/utils.c
+++ b/exosphere/src/utils.c
@@ -14,14 +14,15 @@ __attribute__ ((noreturn)) void panic(uint32_t code) {
APBDEV_PMC_SCRATCH200_0 = code;
}
- /* Uncomment for Debugging.
+ /* // Uncomment for Debugging.
uint64_t temp_reg;
MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_DEBUG_IRAM)) = APBDEV_PMC_SCRATCH200_0;
SAVE_SYSREG64(ESR_EL3, 0x10);
SAVE_SYSREG64(ELR_EL3, 0x18);
SAVE_SYSREG64(FAR_EL3, 0x20);
MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x450ull) = 0x2;
- MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x400ull) = 0x10; */
+ MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x400ull) = 0x10;
+ */
/* TODO: Custom Panic Driver, which displays to screen without rebooting. */
/* For now, just use NX BOOTLOADER's panic. */
@@ -32,7 +33,7 @@ __attribute__ ((noreturn)) void panic(uint32_t code) {
}
__attribute__ ((noreturn)) void generic_panic(void) {
- /* Uncomment for Debugging.
+ /* //Uncomment for Debugging.
uint64_t temp_reg;
do { __asm__ __volatile__ ("mov %0, LR" : "=r"(temp_reg) :: "memory"); } while (false);
MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_DEBUG_IRAM) + 0x28) = (uint32_t)((temp_reg >> 0) & 0xFFFFFFFFULL);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment