mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-12-22 12:21:18 +00:00
exosphere: Add support for 6.0.0.
This commit is contained in:
parent
488fc0f119
commit
fa0e906129
15 changed files with 186 additions and 59 deletions
|
@ -46,6 +46,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();
|
||||
|
@ -66,10 +83,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? */
|
||||
|
@ -219,6 +234,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;
|
||||
|
|
|
@ -102,6 +102,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);
|
||||
|
|
|
@ -32,9 +32,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))
|
||||
|
|
|
@ -244,12 +244,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;
|
||||
|
|
|
@ -39,6 +39,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. */
|
||||
|
@ -49,6 +50,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) {
|
||||
|
@ -121,7 +123,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();
|
||||
}
|
||||
|
||||
|
@ -138,7 +140,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. */
|
||||
|
|
|
@ -19,14 +19,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)
|
||||
|
||||
|
|
|
@ -38,6 +38,26 @@ volatile security_carveout_t *get_carveout_by_id(unsigned int carveout) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
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 = 2; /* 0x40000 */
|
||||
carveout->flags_0 = 0;
|
||||
carveout->flags_1 = 0;
|
||||
carveout->flags_2 = 0x3000000;
|
||||
carveout->flags_3 = 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 = 0x440167E;
|
||||
}
|
||||
|
||||
void configure_default_carveouts(void) {
|
||||
/* Configure Carveout 1 (UNUSED) */
|
||||
volatile security_carveout_t *carveout = get_carveout_by_id(1);
|
||||
|
@ -57,21 +77,9 @@ void configure_default_carveouts(void) {
|
|||
carveout->allowed_clients = 0x04000006;
|
||||
|
||||
/* Configure Carveout 2 (GPU UCODE) */
|
||||
carveout = get_carveout_by_id(2);
|
||||
carveout->paddr_low = 0x80020000;
|
||||
carveout->paddr_high = 0;
|
||||
carveout->size_big_pages = 2; /* 0x40000 */
|
||||
carveout->flags_0 = 0;
|
||||
carveout->flags_1 = 0;
|
||||
carveout->flags_2 = 0x3000000;
|
||||
carveout->flags_3 = 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 = 0x440167E;
|
||||
if (exosphere_get_target_firmware() < EXOSPHERE_TARGET_FIRMWARE_600) {
|
||||
configure_gpu_ucode_carveout();
|
||||
}
|
||||
|
||||
/* Configure Carveout 3 (UNUSED GPU) */
|
||||
carveout = get_carveout_by_id(3);
|
||||
|
|
|
@ -79,6 +79,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);
|
||||
|
||||
|
||||
|
|
|
@ -38,20 +38,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);
|
||||
|
@ -110,6 +121,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;
|
||||
}
|
||||
|
@ -136,14 +148,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);
|
||||
|
@ -399,7 +415,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;
|
||||
|
||||
|
@ -448,8 +479,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);
|
||||
|
@ -465,7 +506,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;
|
||||
|
||||
|
@ -490,6 +531,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);
|
||||
|
|
|
@ -50,6 +50,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))
|
||||
|
||||
|
|
|
@ -158,6 +158,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;
|
||||
|
|
|
@ -40,6 +40,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;
|
||||
}
|
||||
|
@ -152,7 +166,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) {
|
||||
|
@ -238,7 +252,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;
|
||||
}
|
||||
|
||||
|
@ -278,6 +292,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];
|
||||
|
@ -287,7 +305,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;
|
||||
}
|
||||
|
||||
|
@ -406,7 +424,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;
|
||||
}
|
||||
|
||||
|
@ -642,7 +660,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;
|
||||
|
@ -673,6 +700,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);
|
||||
|
@ -686,7 +714,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;
|
||||
}
|
||||
|
||||
|
@ -721,6 +749,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);
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include "utils.h"
|
||||
#include "arm.h"
|
||||
#include "exocfg.h"
|
||||
|
||||
#include "titlekey.h"
|
||||
#include "masterkey.h"
|
||||
|
@ -26,6 +27,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) {
|
||||
|
@ -41,6 +43,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];
|
||||
|
@ -152,18 +165,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);
|
||||
|
|
|
@ -19,8 +19,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);
|
||||
|
||||
|
|
|
@ -30,14 +30,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. */
|
||||
|
@ -48,7 +49,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);
|
||||
|
|
Loading…
Reference in a new issue