mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2025-05-31 14:58:22 -04:00
exo: implement remaining SE changes for mariko support
This commit is contained in:
parent
5cb9fa510e
commit
bf92daf055
9 changed files with 167 additions and 67 deletions
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -25,6 +25,7 @@ namespace ams::se {
|
|||
void SetSecure(bool secure);
|
||||
void SetTzramSecure();
|
||||
void SetPerKeySecure();
|
||||
void SetContextSaveSecure();
|
||||
|
||||
void Lockout();
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue