exosphere: Add support for 6.0.0.

This commit is contained in:
Michael Scire 2018-09-08 23:51:52 -07:00
parent 488fc0f119
commit fa0e906129
15 changed files with 186 additions and 59 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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;
@ -449,7 +480,17 @@ void load_package2(coldboot_crt0_reloc_list_t *reloc_list) {
MAKE_REG32(PMC_BASE + 0x0A0) &= 0xFFF3FFFF;
MAKE_REG32(PMC_BASE + 0x818) &= 0xFFFFFFFE;
MAKE_REG32(PMC_BASE + 0x334) |= 0x10;
MAKE_REG32(PMC_BASE + 0x360) = 6;
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);

View file

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

View file

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

View file

@ -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;
}
@ -279,6 +293,10 @@ 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];
iv_ctr[1] = args->X[3];
@ -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);

View file

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

View file

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

View file

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