diff --git a/libexosphere/include/exosphere/pkg1/pkg1_se_key_slots.hpp b/libexosphere/include/exosphere/pkg1/pkg1_se_key_slots.hpp index 260722d8..65969139 100644 --- a/libexosphere/include/exosphere/pkg1/pkg1_se_key_slots.hpp +++ b/libexosphere/include/exosphere/pkg1/pkg1_se_key_slots.hpp @@ -37,7 +37,8 @@ namespace ams::pkg1 { AesKeySlot_Master = 13, AesKeySlot_Device = 15, - AesKeySlot_SecmonEnd = 16, + AesKeySlot_Count = 16, + AesKeySlot_SecmonEnd = AesKeySlot_Count, /* Used only during boot. */ AesKeySlot_Tsec = 12, @@ -48,6 +49,10 @@ namespace ams::pkg1 { AesKeySlot_DeviceMasterKeySourceKekErista = 10, AesKeySlot_MasterKek = 13, AesKeySlot_DeviceMasterKeySourceKekMariko = 14, + + /* Mariko only keyslots, used during boot. */ + AesKeySlot_MarikoKek = 12, + AesKeySlot_MarikoBek = 13, }; enum RsaKeySlot { diff --git a/libexosphere/include/exosphere/se/se_aes.hpp b/libexosphere/include/exosphere/se/se_aes.hpp index d3f18d20..b5a82864 100644 --- a/libexosphere/include/exosphere/se/se_aes.hpp +++ b/libexosphere/include/exosphere/se/se_aes.hpp @@ -26,6 +26,9 @@ namespace ams::se { void ClearAesKeyIv(int slot); void LockAesKeySlot(int slot, u32 flags); + /* NOTE: This is Nintendo's API, but if we actually want to use SE2 we should use a different one. */ + void ClearAesKeySlot2(int slot); + void SetAesKey(int slot, const void *key, size_t key_size); void SetEncryptedAesKey128(int dst_slot, int kek_slot, const void *key, size_t key_size); diff --git a/libexosphere/include/exosphere/se/se_management.hpp b/libexosphere/include/exosphere/se/se_management.hpp index 2c57646b..843de190 100644 --- a/libexosphere/include/exosphere/se/se_management.hpp +++ b/libexosphere/include/exosphere/se/se_management.hpp @@ -25,6 +25,7 @@ namespace ams::se { void SetSecure(bool secure); void SetTzramSecure(); void SetPerKeySecure(); + void SetContextSaveSecure(); void Lockout(); diff --git a/libexosphere/source/se/se_aes.cpp b/libexosphere/source/se/se_aes.cpp index 00105f71..f5950552 100644 --- a/libexosphere/source/se/se_aes.cpp +++ b/libexosphere/source/se/se_aes.cpp @@ -362,22 +362,29 @@ namespace ams::se { StartOperationRaw(SE, SE_OPERATION_OP_START, out_ll_address, in_ll_address); } + void ClearAesKeySlot(volatile SecurityEngineRegisters *SE, int slot) { + /* Validate the key slot. */ + AMS_ABORT_UNLESS(0 <= slot && slot < AesKeySlotCount); + + for (int i = 0; i < 16; ++i) { + /* Select the keyslot. */ + reg::Write(SE->SE_CRYPTO_KEYTABLE_ADDR, SE_REG_BITS_VALUE(CRYPTO_KEYTABLE_ADDR_KEYIV_KEY_SLOT, slot), SE_REG_BITS_VALUE(CRYPTO_KEYTABLE_ADDR_KEYIV_WORD, i)); + + /* Write the data. */ + SE->SE_CRYPTO_KEYTABLE_DATA = 0; + } + } + } void ClearAesKeySlot(int slot) { - /* Validate the key slot. */ - AMS_ABORT_UNLESS(0 <= slot && slot < AesKeySlotCount); + /* Clear the slot in SE1. */ + ClearAesKeySlot(GetRegisters(), slot); + } - /* Get the engine. */ - auto *SE = GetRegisters(); - - for (int i = 0; i < 16; ++i) { - /* Select the keyslot. */ - reg::Write(SE->SE_CRYPTO_KEYTABLE_ADDR, SE_REG_BITS_VALUE(CRYPTO_KEYTABLE_ADDR_KEYIV_KEY_SLOT, slot), SE_REG_BITS_VALUE(CRYPTO_KEYTABLE_ADDR_KEYIV_WORD, i)); - - /* Write the data. */ - SE->SE_CRYPTO_KEYTABLE_DATA = 0; - } + void ClearAesKeySlot2(int slot) { + /* Clear the slot in SE2. */ + ClearAesKeySlot(GetRegisters2(), slot); } void ClearAesKeyIv(int slot) { diff --git a/libexosphere/source/se/se_management.cpp b/libexosphere/source/se/se_management.cpp index 7b4bfe37..fe5c20de 100644 --- a/libexosphere/source/se/se_management.cpp +++ b/libexosphere/source/se/se_management.cpp @@ -24,6 +24,18 @@ namespace ams::se { constinit uintptr_t g_register2_address = secmon::MemoryRegionPhysicalDeviceSecurityEngine2.GetAddress(); constinit DoneHandler g_done_handler = nullptr; + void SetSecure(volatile SecurityEngineRegisters *SE, bool secure) { + /* Set the security software setting. */ + if (secure) { + reg::ReadWrite(SE->SE_SE_SECURITY, SE_REG_BITS_ENUM(SECURITY_SOFT_SETTING, SECURE)); + } else { + reg::ReadWrite(SE->SE_SE_SECURITY, SE_REG_BITS_ENUM(SECURITY_SOFT_SETTING, NONSECURE)); + } + + /* Read the status register to force an update. */ + reg::Read(SE->SE_SE_SECURITY); + } + } volatile SecurityEngineRegisters *GetRegisters() { @@ -45,17 +57,13 @@ namespace ams::se { } void SetSecure(bool secure) { - auto *SE = GetRegisters(); + /* Set security for SE1. */ + SetSecure(GetRegisters(), secure); - /* Set the security software setting. */ - if (secure) { - reg::ReadWrite(SE->SE_SE_SECURITY, SE_REG_BITS_ENUM(SECURITY_SOFT_SETTING, SECURE)); - } else { - reg::ReadWrite(SE->SE_SE_SECURITY, SE_REG_BITS_ENUM(SECURITY_SOFT_SETTING, NONSECURE)); + /* If SE2 is present, set security for SE2. */ + if (fuse::GetSocType() == fuse::SocType_Mariko) { + SetSecure(GetRegisters2(), secure); } - - /* Read the status register to force an update. */ - reg::Read(SE->SE_SE_SECURITY); } void SetTzramSecure() { @@ -72,6 +80,18 @@ namespace ams::se { reg::ReadWrite(SE->SE_SE_SECURITY, SE_REG_BITS_ENUM(SECURITY_PERKEY_SETTING, SECURE)); } + + void SetContextSaveSecure() { + /* Context save lock to trustzone secure is only available on mariko. */ + if (fuse::GetSocType() == fuse::SocType_Mariko) { + auto *SE = GetRegisters(); + auto *SE2 = GetRegisters2(); + + reg::ReadWrite(SE->SE_SE_SECURITY, SE_REG_BITS_ENUM(SECURITY_CTX_SAVE_TZ_LOCK, SECURE)); + reg::ReadWrite(SE2->SE_SE_SECURITY, SE_REG_BITS_ENUM(SECURITY_CTX_SAVE_TZ_LOCK, SECURE)); + } + } + void Lockout() { auto *SE = GetRegisters(); diff --git a/libexosphere/source/se/se_registers.hpp b/libexosphere/source/se/se_registers.hpp index 5cffa954..189767ae 100644 --- a/libexosphere/source/se/se_registers.hpp +++ b/libexosphere/source/se/se_registers.hpp @@ -106,10 +106,12 @@ namespace ams::se { DEFINE_SE_REG_BIT_ENUM(STATUS_MEM_INTERFACE, 2, IDLE, BUSY); /* SE_SECURITY */ - DEFINE_SE_REG_BIT_ENUM(SECURITY_HARD_SETTING, 0, SECURE, NONSECURE); - DEFINE_SE_REG_BIT_ENUM(SECURITY_ENG_DIS, 1, DISABLE, ENABLE); - DEFINE_SE_REG_BIT_ENUM(SECURITY_PERKEY_SETTING, 2, SECURE, NONSECURE); - DEFINE_SE_REG_BIT_ENUM(SECURITY_SOFT_SETTING, 16, SECURE, NONSECURE); + DEFINE_SE_REG_BIT_ENUM(SECURITY_HARD_SETTING, 0, SECURE, NONSECURE); + DEFINE_SE_REG_BIT_ENUM(SECURITY_ENG_DIS, 1, DISABLE, ENABLE); + DEFINE_SE_REG_BIT_ENUM(SECURITY_PERKEY_SETTING, 2, SECURE, NONSECURE); + DEFINE_SE_REG_BIT_ENUM(SECURITY_CTX_SAVE_TZ_LOCK, 4, SECURE, NONSECURE); + DEFINE_SE_REG_BIT_ENUM(SECURITY_CTX_TZ_LOCK_SOFT, 5, SECURE, NONSECURE); + DEFINE_SE_REG_BIT_ENUM(SECURITY_SOFT_SETTING, 16, SECURE, NONSECURE); /* SE_TZRAM_SECURITY */ DEFINE_SE_REG(TZRAM_SETTING, 0, BITSIZEOF(u32)); diff --git a/libexosphere/source/se/se_rng.cpp b/libexosphere/source/se/se_rng.cpp index 4cb099bd..70eea576 100644 --- a/libexosphere/source/se/se_rng.cpp +++ b/libexosphere/source/se/se_rng.cpp @@ -44,31 +44,50 @@ namespace ams::se { reg::Write(SE->SE_RNG_CONFIG, SE_REG_BITS_ENUM(RNG_CONFIG_SRC, ENTROPY), SE_REG_BITS_VALUE(RNG_CONFIG_MODE, mode)); } - } + void InitializeRandom(volatile SecurityEngineRegisters *SE) { + /* Lock the entropy source. */ + reg::Write(SE->SE_RNG_SRC_CONFIG, SE_REG_BITS_ENUM(RNG_SRC_CONFIG_RO_ENTROPY_SOURCE, ENABLE), + SE_REG_BITS_ENUM(RNG_SRC_CONFIG_RO_ENTROPY_SOURCE_LOCK, ENABLE)); - void InitializeRandom() { - /* Get the engine. */ - auto *SE = GetRegisters(); + /* Set the reseed interval to force a reseed every 70000 blocks. */ + SE->SE_RNG_RESEED_INTERVAL = RngReseedInterval; - /* Lock the entropy source. */ - reg::Write(SE->SE_RNG_SRC_CONFIG, SE_REG_BITS_ENUM(RNG_SRC_CONFIG_RO_ENTROPY_SOURCE, ENABLE), - SE_REG_BITS_ENUM(RNG_SRC_CONFIG_RO_ENTROPY_SOURCE_LOCK, ENABLE)); + /* Initialize the DRBG. */ + { + u8 dummy_buf[AesBlockSize]; - /* Set the reseed interval to force a reseed every 70000 blocks. */ - SE->SE_RNG_RESEED_INTERVAL = RngReseedInterval; + /* Configure the engine to force drbg instantiation by writing random to memory. */ + ConfigRng(SE, SE_CONFIG_DST_MEMORY, SE_RNG_CONFIG_MODE_FORCE_INSTANTIATION); - /* Initialize the DRBG. */ - { - u8 dummy_buf[AesBlockSize]; + /* Configure to do a single RNG block operation to trigger DRBG init. */ + SE->SE_CRYPTO_LAST_BLOCK = 0; - /* Configure the engine to force drbg instantiation by writing random to memory. */ - ConfigRng(SE, SE_CONFIG_DST_MEMORY, SE_RNG_CONFIG_MODE_FORCE_INSTANTIATION); + /* Execute the operation. */ + ExecuteOperation(SE, SE_OPERATION_OP_START, dummy_buf, sizeof(dummy_buf), nullptr, 0); + } + } - /* Configure to do a single RNG block operation to trigger DRBG init. */ + void GenerateSrk(volatile SecurityEngineRegisters *SE) { + /* Configure the RNG to output to SRK and force a reseed. */ + ConfigRng(SE, SE_CONFIG_DST_SRK, SE_RNG_CONFIG_MODE_FORCE_RESEED); + + /* Configure a single block operation. */ SE->SE_CRYPTO_LAST_BLOCK = 0; /* Execute the operation. */ - ExecuteOperation(SE, SE_OPERATION_OP_START, dummy_buf, sizeof(dummy_buf), nullptr, 0); + ExecuteOperation(SE, SE_OPERATION_OP_START, nullptr, 0, nullptr, 0); + } + + } + + void InitializeRandom() { + /* Initialize random for SE1. */ + InitializeRandom(GetRegisters()); + + /* If we have SE2, initialize random for SE2. */ + /* NOTE: Nintendo's implementation of this is incorrect. */ + if (fuse::GetSocType() == fuse::SocType_Mariko) { + InitializeRandom(GetRegisters2()); } } @@ -130,17 +149,14 @@ namespace ams::se { } void GenerateSrk() { - /* Get the engine. */ - auto *SE = GetRegisters(); + /* Generate SRK for SE1. */ + GenerateSrk(GetRegisters()); - /* Configure the RNG to output to SRK and force a reseed. */ - ConfigRng(SE, SE_CONFIG_DST_SRK, SE_RNG_CONFIG_MODE_FORCE_RESEED); - - /* Configure a single block operation. */ - SE->SE_CRYPTO_LAST_BLOCK = 0; - - /* Execute the operation. */ - ExecuteOperation(SE, SE_OPERATION_OP_START, nullptr, 0, nullptr, 0); + /* If we have SE2, generate SRK for SE2. */ + /* NOTE: Nintendo's implementation of this is incorrect. */ + if (fuse::GetSocType() == fuse::SocType_Mariko) { + GenerateSrk(GetRegisters2()); + } } }