exo: implement remaining SE changes for mariko support

This commit is contained in:
Michael Scire 2020-06-28 21:11:29 -07:00
parent 1f252dfa43
commit 7de919f3df
7 changed files with 106 additions and 52 deletions

View File

@ -37,7 +37,8 @@ namespace ams::pkg1 {
AesKeySlot_Master = 13, AesKeySlot_Master = 13,
AesKeySlot_Device = 15, AesKeySlot_Device = 15,
AesKeySlot_SecmonEnd = 16, AesKeySlot_Count = 16,
AesKeySlot_SecmonEnd = AesKeySlot_Count,
/* Used only during boot. */ /* Used only during boot. */
AesKeySlot_Tsec = 12, AesKeySlot_Tsec = 12,
@ -48,6 +49,10 @@ namespace ams::pkg1 {
AesKeySlot_DeviceMasterKeySourceKekErista = 10, AesKeySlot_DeviceMasterKeySourceKekErista = 10,
AesKeySlot_MasterKek = 13, AesKeySlot_MasterKek = 13,
AesKeySlot_DeviceMasterKeySourceKekMariko = 14, AesKeySlot_DeviceMasterKeySourceKekMariko = 14,
/* Mariko only keyslots, used during boot. */
AesKeySlot_MarikoKek = 12,
AesKeySlot_MarikoBek = 13,
}; };
enum RsaKeySlot { enum RsaKeySlot {

View File

@ -26,6 +26,9 @@ namespace ams::se {
void ClearAesKeyIv(int slot); void ClearAesKeyIv(int slot);
void LockAesKeySlot(int slot, u32 flags); 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 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); void SetEncryptedAesKey128(int dst_slot, int kek_slot, const void *key, size_t key_size);

View File

@ -25,6 +25,7 @@ namespace ams::se {
void SetSecure(bool secure); void SetSecure(bool secure);
void SetTzramSecure(); void SetTzramSecure();
void SetPerKeySecure(); void SetPerKeySecure();
void SetContextSaveSecure();
void Lockout(); void Lockout();

View File

@ -362,15 +362,10 @@ namespace ams::se {
StartOperationRaw(SE, SE_OPERATION_OP_START, out_ll_address, in_ll_address); StartOperationRaw(SE, SE_OPERATION_OP_START, out_ll_address, in_ll_address);
} }
} void ClearAesKeySlot(volatile SecurityEngineRegisters *SE, int slot) {
void ClearAesKeySlot(int slot) {
/* Validate the key slot. */ /* Validate the key slot. */
AMS_ABORT_UNLESS(0 <= slot && slot < AesKeySlotCount); AMS_ABORT_UNLESS(0 <= slot && slot < AesKeySlotCount);
/* Get the engine. */
auto *SE = GetRegisters();
for (int i = 0; i < 16; ++i) { for (int i = 0; i < 16; ++i) {
/* Select the keyslot. */ /* 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)); 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));
@ -380,6 +375,18 @@ namespace ams::se {
} }
} }
}
void ClearAesKeySlot(int slot) {
/* Clear the slot in SE1. */
ClearAesKeySlot(GetRegisters(), slot);
}
void ClearAesKeySlot2(int slot) {
/* Clear the slot in SE2. */
ClearAesKeySlot(GetRegisters2(), slot);
}
void ClearAesKeyIv(int slot) { void ClearAesKeyIv(int slot) {
/* Validate the key slot. */ /* Validate the key slot. */
AMS_ABORT_UNLESS(0 <= slot && slot < AesKeySlotCount); AMS_ABORT_UNLESS(0 <= slot && slot < AesKeySlotCount);

View File

@ -24,6 +24,18 @@ namespace ams::se {
constinit uintptr_t g_register2_address = secmon::MemoryRegionPhysicalDeviceSecurityEngine2.GetAddress(); constinit uintptr_t g_register2_address = secmon::MemoryRegionPhysicalDeviceSecurityEngine2.GetAddress();
constinit DoneHandler g_done_handler = nullptr; 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() { volatile SecurityEngineRegisters *GetRegisters() {
@ -45,17 +57,13 @@ namespace ams::se {
} }
void SetSecure(bool secure) { void SetSecure(bool secure) {
auto *SE = GetRegisters(); /* Set security for SE1. */
SetSecure(GetRegisters(), secure);
/* Set the security software setting. */ /* If SE2 is present, set security for SE2. */
if (secure) { if (fuse::GetSocType() == fuse::SocType_Mariko) {
reg::ReadWrite(SE->SE_SE_SECURITY, SE_REG_BITS_ENUM(SECURITY_SOFT_SETTING, SECURE)); SetSecure(GetRegisters2(), 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);
} }
void SetTzramSecure() { void SetTzramSecure() {
@ -72,6 +80,18 @@ namespace ams::se {
reg::ReadWrite(SE->SE_SE_SECURITY, SE_REG_BITS_ENUM(SECURITY_PERKEY_SETTING, SECURE)); 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() { void Lockout() {
auto *SE = GetRegisters(); auto *SE = GetRegisters();

View File

@ -109,6 +109,8 @@ namespace ams::se {
DEFINE_SE_REG_BIT_ENUM(SECURITY_HARD_SETTING, 0, 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_ENG_DIS, 1, DISABLE, ENABLE);
DEFINE_SE_REG_BIT_ENUM(SECURITY_PERKEY_SETTING, 2, SECURE, NONSECURE); 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); DEFINE_SE_REG_BIT_ENUM(SECURITY_SOFT_SETTING, 16, SECURE, NONSECURE);
/* SE_TZRAM_SECURITY */ /* SE_TZRAM_SECURITY */

View File

@ -44,12 +44,7 @@ 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)); 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) {
void InitializeRandom() {
/* Get the engine. */
auto *SE = GetRegisters();
/* Lock the entropy source. */ /* Lock the entropy source. */
reg::Write(SE->SE_RNG_SRC_CONFIG, SE_REG_BITS_ENUM(RNG_SRC_CONFIG_RO_ENTROPY_SOURCE, ENABLE), 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)); SE_REG_BITS_ENUM(RNG_SRC_CONFIG_RO_ENTROPY_SOURCE_LOCK, ENABLE));
@ -72,6 +67,30 @@ namespace ams::se {
} }
} }
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, 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());
}
}
void GenerateRandomBytes(void *dst, size_t size) { void GenerateRandomBytes(void *dst, size_t size) {
/* If we're not generating any bytes, there's nothing to do. */ /* If we're not generating any bytes, there's nothing to do. */
if (size == 0) { if (size == 0) {
@ -130,17 +149,14 @@ namespace ams::se {
} }
void GenerateSrk() { void GenerateSrk() {
/* Get the engine. */ /* Generate SRK for SE1. */
auto *SE = GetRegisters(); GenerateSrk(GetRegisters());
/* Configure the RNG to output to SRK and force a reseed. */ /* If we have SE2, generate SRK for SE2. */
ConfigRng(SE, SE_CONFIG_DST_SRK, SE_RNG_CONFIG_MODE_FORCE_RESEED); /* NOTE: Nintendo's implementation of this is incorrect. */
if (fuse::GetSocType() == fuse::SocType_Mariko) {
/* Configure a single block operation. */ GenerateSrk(GetRegisters2());
SE->SE_CRYPTO_LAST_BLOCK = 0; }
/* Execute the operation. */
ExecuteOperation(SE, SE_OPERATION_OP_START, nullptr, 0, nullptr, 0);
} }
} }