diff --git a/sept/sept-secondary/key_derivation/src/se.c b/sept/sept-secondary/key_derivation/src/se.c index e7db66ab0..59ac47242 100644 --- a/sept/sept-secondary/key_derivation/src/se.c +++ b/sept/sept-secondary/key_derivation/src/se.c @@ -203,12 +203,37 @@ void decrypt_data_into_keyslot(unsigned int keyslot_dst, unsigned int keyslot_sr generic_panic(); } + /* Write config, validate. */ se->CONFIG_REG = (ALG_AES_DEC | DST_KEYTAB); + if (se->CONFIG_REG != (ALG_AES_DEC | DST_KEYTAB)) { + generic_panic(); + } se->CRYPTO_REG = keyslot_src << 24; + if (se->CRYPTO_REG != (keyslot_src << 24)) { + generic_panic(); + } se->BLOCK_COUNT_REG = 0; + if (se->BLOCK_COUNT_REG != 0) { + generic_panic(); + } se->CRYPTO_KEYTABLE_DST_REG = keyslot_dst << 8; + if (se->CRYPTO_KEYTABLE_DST_REG != (keyslot_dst << 8)) { + generic_panic(); + } + + /* Clear address context. */ + se->IN_LL_ADDR_REG = 0; + se->OUT_LL_ADDR_REG = 0; + if (se->IN_LL_ADDR_REG != 0 || se->OUT_LL_ADDR_REG != 0) { + generic_panic(); + } trigger_se_blocking_op(OP_START, NULL, 0, wrapped_key, wrapped_key_size); + + /* Validate address context. */ + if (se->IN_LL_ADDR_REG == 0 || se->OUT_LL_ADDR_REG == 0) { + generic_panic(); + } } void se_synchronous_exp_mod(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size) { @@ -320,6 +345,11 @@ void trigger_se_blocking_op(unsigned int op, void *dst, size_t dst_size, const v /* Set registers for operation. */ se->ERR_STATUS_REG = se->ERR_STATUS_REG; se->INT_STATUS_REG = se->INT_STATUS_REG; + + if (se->IN_LL_ADDR_REG != (uint32_t) get_physical_address(&in_ll) || se->OUT_LL_ADDR_REG != (uint32_t) get_physical_address(&out_ll) || (se->INT_STATUS_REG & 0x10)) { + generic_panic(); + } + se->OPERATION_REG = op; while (!(se->INT_STATUS_REG & 0x10)) { /* Wait a while */ } @@ -725,39 +755,3 @@ void se_save_context(unsigned int srkgen_keyslot, unsigned int rng_keyslot, void se->CONFIG_REG = 0; se_encrypt_with_srk(work_buf, 0, NULL, 0); } - -void se_save_partial_context(unsigned int srkgen_keyslot, unsigned int rng_keyslot, void *dst) { - volatile tegra_se_t *se = se_get_regs(); - uint8_t _work_buf[0x80]; - uint8_t *work_buf = (uint8_t *)(((uintptr_t)_work_buf + 0x7F) & ~0x3F); - - /* Generate the SRK (context save encryption key). */ - se_generate_random_key(srkgen_keyslot, rng_keyslot); - se_generate_srk(srkgen_keyslot); - - se_generate_random(rng_keyslot, work_buf, 0x10); - - /* Save known pattern. */ - static const uint8_t context_save_known_pattern[0x10] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}; - se->CONTEXT_SAVE_CONFIG_REG = (CTX_SAVE_SRC_MEM); - se->BLOCK_COUNT_REG = 0; - se_encrypt_with_srk(dst + 0x00, 0x10, context_save_known_pattern, 0x10); - - /* Save specific keyslots 0xC, 0xD, 0xE. */ - se->CONTEXT_SAVE_CONFIG_REG = (CTX_SAVE_SRC_KEYTABLE_AES) | (0xE << CTX_SAVE_KEY_INDEX_SHIFT) | (CTX_SAVE_KEY_LOW_BITS); - se->BLOCK_COUNT_REG = 0; - se_encrypt_with_srk(dst + 0x10, 0x10, NULL, 0); - se->CONTEXT_SAVE_CONFIG_REG = (CTX_SAVE_SRC_KEYTABLE_AES) | (0xC << CTX_SAVE_KEY_INDEX_SHIFT) | (CTX_SAVE_KEY_LOW_BITS); - se->BLOCK_COUNT_REG = 0; - se_encrypt_with_srk(dst + 0x20, 0x10, NULL, 0); - se->CONTEXT_SAVE_CONFIG_REG = (CTX_SAVE_SRC_KEYTABLE_AES) | (0xD << CTX_SAVE_KEY_INDEX_SHIFT) | (CTX_SAVE_KEY_LOW_BITS); - se->BLOCK_COUNT_REG = 0; - se_encrypt_with_srk(dst + 0x30, 0x10, NULL, 0); - - /* Save SRK into PMC registers. */ - se->CONTEXT_SAVE_CONFIG_REG = (CTX_SAVE_SRC_SRK); - se->BLOCK_COUNT_REG = 0; - se_encrypt_with_srk(work_buf, 0, NULL, 0); - se->CONFIG_REG = 0; - se_encrypt_with_srk(work_buf, 0, NULL, 0); -} diff --git a/sept/sept-secondary/key_derivation/src/se.h b/sept/sept-secondary/key_derivation/src/se.h index d3b3c7ca1..98a6a170f 100644 --- a/sept/sept-secondary/key_derivation/src/se.h +++ b/sept/sept-secondary/key_derivation/src/se.h @@ -222,6 +222,4 @@ void se_set_in_context_save_mode(bool is_context_save_mode); void se_generate_random_key(unsigned int dst_keyslot, unsigned int rng_keyslot); void se_save_context(unsigned int srk_keyslot, unsigned int rng_keyslot, void *dst); -void se_save_partial_context(unsigned int srk_keyslot, unsigned int rng_keyslot, void *dst); - #endif diff --git a/sept/sept-secondary/key_derivation/src/utils.c b/sept/sept-secondary/key_derivation/src/utils.c index cc6cec4b7..a515fb57a 100644 --- a/sept/sept-secondary/key_derivation/src/utils.c +++ b/sept/sept-secondary/key_derivation/src/utils.c @@ -17,8 +17,15 @@ #include #include #include "utils.h" +#include "se.h" #include __attribute__ ((noreturn)) void generic_panic(void) { + /* Clear keyslots. */ + clear_aes_keyslot(0xD); + for (size_t i = 0; i < 0x10; i++) { + clear_aes_keyslot(i); + } + clear_aes_keyslot(0xD); while(1) { /* ... */ } } diff --git a/stratosphere/libstratosphere b/stratosphere/libstratosphere index 281534d9f..7e0ed3b38 160000 --- a/stratosphere/libstratosphere +++ b/stratosphere/libstratosphere @@ -1 +1 @@ -Subproject commit 281534d9f805af7dccbdd4e0e8883d4d055581ff +Subproject commit 7e0ed3b38f437791fdd398c7058c376c9d2a6853 diff --git a/stratosphere/loader/source/ldr_npdm.hpp b/stratosphere/loader/source/ldr_npdm.hpp index b0aae5731..c8c18f76a 100644 --- a/stratosphere/loader/source/ldr_npdm.hpp +++ b/stratosphere/loader/source/ldr_npdm.hpp @@ -37,7 +37,7 @@ class NpdmUtils { u8 default_cpuid; u32 _0x10; u32 system_resource_size; - u32 process_category; + u32 version; u32 main_stack_size; char title_name[0x50]; u32 aci0_offset; diff --git a/stratosphere/loader/source/ldr_process_creation.cpp b/stratosphere/loader/source/ldr_process_creation.cpp index 9a1449d4e..e76cdf20f 100644 --- a/stratosphere/loader/source/ldr_process_creation.cpp +++ b/stratosphere/loader/source/ldr_process_creation.cpp @@ -25,6 +25,35 @@ #include "ldr_npdm.hpp" #include "ldr_nso.hpp" +static inline bool IsDisallowedVersion810(const u64 title_id, const u32 version) { + return version == 0 && + (title_id == TitleId_Settings || + title_id == TitleId_Bus || + title_id == TitleId_Audio || + title_id == TitleId_NvServices || + title_id == TitleId_Ns || + title_id == TitleId_Ssl || + title_id == TitleId_Es || + title_id == TitleId_Creport || + title_id == TitleId_Ro); +} + +Result ProcessCreation::ValidateProcessVersion(u64 title_id, u32 version) { + if (GetRuntimeFirmwareVersion() < FirmwareVersion_810) { + return ResultSuccess; + } else { +#ifdef LDR_VALIDATE_PROCESS_VERSION + if (IsDisallowedVersion810(title_id, version)) { + return ResultLoaderInvalidVersion; + } else { + return ResultSuccess; + } +#else + return ResultSuccess; +#endif + } +} + Result ProcessCreation::InitializeProcessInfo(NpdmUtils::NpdmInfo *npdm, Handle reslimit_h, u64 arg_flags, ProcessInfo *out_proc_info) { /* Initialize a ProcessInfo using an npdm. */ *out_proc_info = {}; @@ -36,8 +65,8 @@ Result ProcessCreation::InitializeProcessInfo(NpdmUtils::NpdmInfo *npdm, Handle /* Set title id. */ out_proc_info->title_id = npdm->aci0->title_id; - /* Set process category. */ - out_proc_info->process_category = npdm->header->process_category; + /* Set version. */ + out_proc_info->version = npdm->header->version; /* Copy reslimit handle raw. */ out_proc_info->reslimit_h = reslimit_h; @@ -145,6 +174,9 @@ Result ProcessCreation::CreateProcess(Handle *out_process_h, u64 index, char *nc /* Load the process's NPDM. */ R_TRY(NpdmUtils::LoadNpdmFromCache(target_process->tid_sid.title_id, &npdm_info)); + /* Validate version. */ + R_TRY(ValidateProcessVersion(target_process->tid_sid.title_id, npdm_info.header->version)); + /* Validate the title we're loading is what we expect. */ if (npdm_info.aci0->title_id < npdm_info.acid->title_id_range_min || npdm_info.aci0->title_id > npdm_info.acid->title_id_range_max) { return ResultLoaderInvalidProgramId; diff --git a/stratosphere/loader/source/ldr_process_creation.hpp b/stratosphere/loader/source/ldr_process_creation.hpp index 1914122d1..df975d063 100644 --- a/stratosphere/loader/source/ldr_process_creation.hpp +++ b/stratosphere/loader/source/ldr_process_creation.hpp @@ -27,7 +27,7 @@ class ProcessCreation { public: struct ProcessInfo { u8 name[12]; - u32 process_category; + u32 version; u64 title_id; u64 code_addr; u32 code_num_pages; @@ -35,6 +35,7 @@ class ProcessCreation { Handle reslimit_h; u32 system_resource_num_pages; }; + static Result ValidateProcessVersion(u64 title_id, u32 version); static Result InitializeProcessInfo(NpdmUtils::NpdmInfo *npdm, Handle reslimit_h, u64 arg_flags, ProcessInfo *out_proc_info); static Result CreateProcess(Handle *out_process_h, u64 index, char *nca_path, LaunchQueue::LaunchItem *launch_item, u64 arg_flags, Handle reslimit_h); }; \ No newline at end of file