mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-12-22 20:31:14 +00:00
exo2: first pass at backwards-compat
This commit is contained in:
parent
42f1a3bf60
commit
da4107996a
9 changed files with 195 additions and 48 deletions
|
@ -17,6 +17,7 @@
|
||||||
#include "secmon_boot.hpp"
|
#include "secmon_boot.hpp"
|
||||||
#include "secmon_boot_functions.hpp"
|
#include "secmon_boot_functions.hpp"
|
||||||
#include "../smc/secmon_random_cache.hpp"
|
#include "../smc/secmon_random_cache.hpp"
|
||||||
|
#include "../smc/secmon_smc_handler.hpp"
|
||||||
#include "../secmon_cache.hpp"
|
#include "../secmon_cache.hpp"
|
||||||
#include "../secmon_cpu_context.hpp"
|
#include "../secmon_cpu_context.hpp"
|
||||||
#include "../secmon_misc.hpp"
|
#include "../secmon_misc.hpp"
|
||||||
|
@ -180,6 +181,9 @@ namespace ams::secmon {
|
||||||
/* Perform final initialization. */
|
/* Perform final initialization. */
|
||||||
secmon::SetupSocProtections();
|
secmon::SetupSocProtections();
|
||||||
secmon::SetupCpuSErrorDebug();
|
secmon::SetupCpuSErrorDebug();
|
||||||
|
|
||||||
|
/* Configure the smc handler tables to reflect the current target firmware. */
|
||||||
|
secmon::smc::ConfigureSmcHandlersForTargetFirmware();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -584,6 +584,11 @@ namespace ams::secmon {
|
||||||
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_LOCK_MODE, LOCKED),
|
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_LOCK_MODE, LOCKED),
|
||||||
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_PROTECT_MODE, LOCKBIT_SECURE));
|
MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_PROTECT_MODE, LOCKBIT_SECURE));
|
||||||
|
|
||||||
|
/* If we're cold-booting and on 1.0.0, alter the default carveout size. */
|
||||||
|
if (g_is_cold_boot && GetTargetFirmware() <= TargetFirmware_1_0_0) {
|
||||||
|
g_kernel_carveouts[0].size = 200 * 128_KB;
|
||||||
|
}
|
||||||
|
|
||||||
/* Configure the two kernel carveouts. */
|
/* Configure the two kernel carveouts. */
|
||||||
SetupKernelCarveouts();
|
SetupKernelCarveouts();
|
||||||
|
|
||||||
|
@ -599,10 +604,15 @@ namespace ams::secmon {
|
||||||
reg::Write(MC + MC_SMMU_TRANSLATION_ENABLE_3, ~0u);
|
reg::Write(MC + MC_SMMU_TRANSLATION_ENABLE_3, ~0u);
|
||||||
reg::Write(MC + MC_SMMU_TRANSLATION_ENABLE_4, ~0u);
|
reg::Write(MC + MC_SMMU_TRANSLATION_ENABLE_4, ~0u);
|
||||||
|
|
||||||
/* Configure ASIDs 1-3 as secure, and all others as non-secure. */
|
/* On modern firmware, configure ASIDs 1-3 as secure, and all others as non-secure. */
|
||||||
reg::Write(MC + MC_SMMU_ASID_SECURITY, MC_REG_BITS_ENUM(SMMU_ASID_SECURITY_SECURE_ASIDS_1, SECURE),
|
if (GetTargetFirmware() >= TargetFirmware_4_0_0) {
|
||||||
MC_REG_BITS_ENUM(SMMU_ASID_SECURITY_SECURE_ASIDS_2, SECURE),
|
reg::Write(MC + MC_SMMU_ASID_SECURITY, MC_REG_BITS_ENUM(SMMU_ASID_SECURITY_SECURE_ASIDS_1, SECURE),
|
||||||
MC_REG_BITS_ENUM(SMMU_ASID_SECURITY_SECURE_ASIDS_3, SECURE));
|
MC_REG_BITS_ENUM(SMMU_ASID_SECURITY_SECURE_ASIDS_2, SECURE),
|
||||||
|
MC_REG_BITS_ENUM(SMMU_ASID_SECURITY_SECURE_ASIDS_3, SECURE));
|
||||||
|
} else {
|
||||||
|
/* Legacy firmware accesses the MC directly, though, and so correspondingly we must allow ASIDs to be edited by non-secure world. */
|
||||||
|
reg::Write(MC + MC_SMMU_ASID_SECURITY, 0);
|
||||||
|
}
|
||||||
|
|
||||||
reg::Write(MC + MC_SMMU_ASID_SECURITY_1, 0);
|
reg::Write(MC + MC_SMMU_ASID_SECURITY_1, 0);
|
||||||
reg::Write(MC + MC_SMMU_ASID_SECURITY_2, 0);
|
reg::Write(MC + MC_SMMU_ASID_SECURITY_2, 0);
|
||||||
|
@ -1115,6 +1125,11 @@ namespace ams::secmon {
|
||||||
/* Disable the ARC. */
|
/* Disable the ARC. */
|
||||||
DisableArc();
|
DisableArc();
|
||||||
|
|
||||||
|
/* Further protections are applied only on 4.0.0+. */
|
||||||
|
if (GetTargetFirmware() < TargetFirmware_4_0_0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Finalize and lock the carveout scratch registers. */
|
/* Finalize and lock the carveout scratch registers. */
|
||||||
FinalizeCarveoutSecureScratchRegisters();
|
FinalizeCarveoutSecureScratchRegisters();
|
||||||
pmc::LockSecureRegister(pmc::SecureRegister_Carveout);
|
pmc::LockSecureRegister(pmc::SecureRegister_Carveout);
|
||||||
|
@ -1155,13 +1170,19 @@ namespace ams::secmon {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetupPmcAndMcSecure() {
|
void SetupPmcAndMcSecure() {
|
||||||
/* Set the PMC secure. */
|
const auto target_fw = GetTargetFirmware();
|
||||||
reg::ReadWrite(APB_MISC + APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG0_0, SLAVE_SECURITY_REG_BITS_ENUM(0, PMC, ENABLE));
|
|
||||||
|
|
||||||
/* Set the MC secure. */
|
if (target_fw >= TargetFirmware_2_0_0) {
|
||||||
reg::ReadWrite(APB_MISC + APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG1_0, SLAVE_SECURITY_REG_BITS_ENUM(1, MC0, ENABLE),
|
/* Set the PMC secure. */
|
||||||
SLAVE_SECURITY_REG_BITS_ENUM(1, MC1, ENABLE),
|
reg::ReadWrite(APB_MISC + APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG0_0, SLAVE_SECURITY_REG_BITS_ENUM(0, PMC, ENABLE));
|
||||||
SLAVE_SECURITY_REG_BITS_ENUM(1, MCB, ENABLE));
|
}
|
||||||
|
|
||||||
|
if (target_fw >= TargetFirmware_4_0_0) {
|
||||||
|
/* Set the MC secure. */
|
||||||
|
reg::ReadWrite(APB_MISC + APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG1_0, SLAVE_SECURITY_REG_BITS_ENUM(1, MC0, ENABLE),
|
||||||
|
SLAVE_SECURITY_REG_BITS_ENUM(1, MC1, ENABLE),
|
||||||
|
SLAVE_SECURITY_REG_BITS_ENUM(1, MCB, ENABLE));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetupCpuCoreContext() {
|
void SetupCpuCoreContext() {
|
||||||
|
|
|
@ -114,6 +114,9 @@ namespace ams::secmon::smc {
|
||||||
struct DecryptDeviceUniqueDataOption {
|
struct DecryptDeviceUniqueDataOption {
|
||||||
using DeviceUniqueDataIndex = util::BitPack32::Field<0, 3, DeviceUniqueData>;
|
using DeviceUniqueDataIndex = util::BitPack32::Field<0, 3, DeviceUniqueData>;
|
||||||
using Reserved = util::BitPack32::Field<3, 29, u32>;
|
using Reserved = util::BitPack32::Field<3, 29, u32>;
|
||||||
|
|
||||||
|
/* Legacy. */
|
||||||
|
using EnforceDeviceUnique = util::BitPack32::Field<0, 1, bool>;
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr const u8 SealKeySources[SealKey_Count][AesKeySize] = {
|
constexpr const u8 SealKeySources[SealKey_Count][AesKeySize] = {
|
||||||
|
@ -499,7 +502,7 @@ namespace ams::secmon::smc {
|
||||||
|
|
||||||
/* Decode arguments. */
|
/* Decode arguments. */
|
||||||
std::memcpy(key_source, std::addressof(args.r[1]), sizeof(key_source));
|
std::memcpy(key_source, std::addressof(args.r[1]), sizeof(key_source));
|
||||||
const int generation = GetTargetFirmware() >= TargetFirmware_3_0_0 ? std::max(0, static_cast<int>(args.r[3]) - 1) : 0;
|
const int generation = GetTargetFirmware() >= TargetFirmware_3_0_0 ? std::max<int>(pkg1::KeyGeneration_1_0_0, static_cast<int>(args.r[3]) - 1) : pkg1::KeyGeneration_1_0_0;
|
||||||
|
|
||||||
/* Validate arguments. */
|
/* Validate arguments. */
|
||||||
SMC_R_UNLESS(pkg1::IsValidKeyGeneration(generation), InvalidArgument);
|
SMC_R_UNLESS(pkg1::IsValidKeyGeneration(generation), InvalidArgument);
|
||||||
|
@ -517,11 +520,23 @@ namespace ams::secmon::smc {
|
||||||
return SmcResult::Success;
|
return SmcResult::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
SmcResult ValidateDeviceUniqueDataSize(DeviceUniqueData mode, size_t data_size) {
|
constexpr size_t GetDiscountedMinimumDeviceUniqueDataSize(bool enforce_device_unique) {
|
||||||
|
if (enforce_device_unique) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return DeviceUniqueDataTotalMetaSize - DeviceUniqueDataIvSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SmcResult ValidateDeviceUniqueDataSize(DeviceUniqueData mode, size_t data_size, bool enforce_device_unique) {
|
||||||
|
/* Determine the discounted size towards the minimum. */
|
||||||
|
const size_t discounted_size = GetDiscountedMinimumDeviceUniqueDataSize(enforce_device_unique);
|
||||||
|
SMC_R_UNLESS(enforce_device_unique || fuse::GetPatchVersion() < fuse::PatchVersion_Odnx02A2, InvalidArgument);
|
||||||
|
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case DeviceUniqueData_DecryptDeviceUniqueData:
|
case DeviceUniqueData_DecryptDeviceUniqueData:
|
||||||
{
|
{
|
||||||
SMC_R_UNLESS(data_size < DeviceUniqueDataSizeMax, InvalidArgument);
|
SMC_R_UNLESS(DeviceUniqueDataTotalMetaSize - discounted_size < data_size && data_size <= DeviceUniqueDataSizeMax, InvalidArgument);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DeviceUniqueData_ImportLotusKey:
|
case DeviceUniqueData_ImportLotusKey:
|
||||||
|
@ -529,7 +544,7 @@ namespace ams::secmon::smc {
|
||||||
case DeviceUniqueData_ImportSslKey:
|
case DeviceUniqueData_ImportSslKey:
|
||||||
case DeviceUniqueData_ImportEsClientCertKey:
|
case DeviceUniqueData_ImportEsClientCertKey:
|
||||||
{
|
{
|
||||||
SMC_R_UNLESS(DeviceUniqueDataSizeMin <= data_size && data_size <= DeviceUniqueDataSizeMax, InvalidArgument);
|
SMC_R_UNLESS(DeviceUniqueDataSizeMin - discounted_size <= data_size && data_size <= DeviceUniqueDataSizeMax, InvalidArgument);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -539,23 +554,9 @@ namespace ams::secmon::smc {
|
||||||
return SmcResult::Success;
|
return SmcResult::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
SmcResult DecryptDeviceUniqueDataImpl(SmcArguments &args) {
|
SmcResult DecryptDeviceUniqueDataImpl(const u8 *access_key, const u8 *key_source, const DeviceUniqueData mode, const uintptr_t data_address, const size_t data_size, bool enforce_device_unique) {
|
||||||
/* Decode arguments. */
|
|
||||||
u8 access_key[se::AesBlockSize];
|
|
||||||
u8 key_source[se::AesBlockSize];
|
|
||||||
|
|
||||||
std::memcpy(access_key, std::addressof(args.r[1]), sizeof(access_key));
|
|
||||||
const util::BitPack32 option = { static_cast<u32>(args.r[3]) };
|
|
||||||
const uintptr_t data_address = args.r[4];
|
|
||||||
const size_t data_size = args.r[5];
|
|
||||||
std::memcpy(key_source, std::addressof(args.r[6]), sizeof(key_source));
|
|
||||||
|
|
||||||
const auto mode = option.Get<DecryptDeviceUniqueDataOption::DeviceUniqueDataIndex>();
|
|
||||||
const auto reserved = option.Get<DecryptDeviceUniqueDataOption::Reserved>();
|
|
||||||
|
|
||||||
/* Validate arguments. */
|
/* Validate arguments. */
|
||||||
SMC_R_UNLESS(reserved == 0, InvalidArgument);
|
SMC_R_TRY(ValidateDeviceUniqueDataSize(mode, data_size, enforce_device_unique));
|
||||||
SMC_R_TRY(ValidateDeviceUniqueDataSize(mode, data_size));
|
|
||||||
|
|
||||||
/* Decrypt the device unique data. */
|
/* Decrypt the device unique data. */
|
||||||
alignas(8) u8 work_buffer[DeviceUniqueDataSizeMax];
|
alignas(8) u8 work_buffer[DeviceUniqueDataSizeMax];
|
||||||
|
@ -571,7 +572,7 @@ namespace ams::secmon::smc {
|
||||||
const u8 * const seal_key_source = SealKeySources[seal_key_type];
|
const u8 * const seal_key_source = SealKeySources[seal_key_type];
|
||||||
|
|
||||||
/* Decrypt the data. */
|
/* Decrypt the data. */
|
||||||
if (!DecryptDeviceUniqueData(work_buffer, data_size, nullptr, seal_key_source, se::AesBlockSize, access_key, sizeof(access_key), key_source, sizeof(key_source), work_buffer, data_size)) {
|
if (!DecryptDeviceUniqueData(work_buffer, data_size, nullptr, seal_key_source, se::AesBlockSize, access_key, sizeof(access_key), key_source, sizeof(key_source), work_buffer, data_size, enforce_device_unique)) {
|
||||||
return SmcResult::InvalidArgument;
|
return SmcResult::InvalidArgument;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -599,6 +600,89 @@ namespace ams::secmon::smc {
|
||||||
return SmcResult::Success;
|
return SmcResult::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SmcResult DecryptDeviceUniqueDataImpl(SmcArguments &args) {
|
||||||
|
/* Decode arguments. */
|
||||||
|
u8 access_key[se::AesBlockSize];
|
||||||
|
u8 key_source[se::AesBlockSize];
|
||||||
|
|
||||||
|
std::memcpy(access_key, std::addressof(args.r[1]), sizeof(access_key));
|
||||||
|
const util::BitPack32 option = { static_cast<u32>(args.r[3]) };
|
||||||
|
const uintptr_t data_address = args.r[4];
|
||||||
|
const size_t data_size = args.r[5];
|
||||||
|
std::memcpy(key_source, std::addressof(args.r[6]), sizeof(key_source));
|
||||||
|
|
||||||
|
const auto mode = GetTargetFirmware() >= TargetFirmware_5_0_0 ? option.Get<DecryptDeviceUniqueDataOption::DeviceUniqueDataIndex>() : DeviceUniqueData_DecryptDeviceUniqueData;
|
||||||
|
const auto reserved = option.Get<DecryptDeviceUniqueDataOption::Reserved>();
|
||||||
|
|
||||||
|
const bool enforce_device_unique = GetTargetFirmware() >= TargetFirmware_5_0_0 ? true : option.Get<DecryptDeviceUniqueDataOption::EnforceDeviceUnique>();
|
||||||
|
|
||||||
|
/* Validate arguments. */
|
||||||
|
SMC_R_UNLESS(reserved == 0, InvalidArgument);
|
||||||
|
|
||||||
|
/* Decrypt the device unique data. */
|
||||||
|
return DecryptDeviceUniqueDataImpl(access_key, key_source, mode, data_address, data_size, enforce_device_unique);
|
||||||
|
}
|
||||||
|
|
||||||
|
SmcResult DecryptAndImportEsDeviceKeyImpl(SmcArguments &args) {
|
||||||
|
/* Decode arguments. */
|
||||||
|
u8 access_key[se::AesBlockSize];
|
||||||
|
u8 key_source[se::AesBlockSize];
|
||||||
|
|
||||||
|
std::memcpy(access_key, std::addressof(args.r[1]), sizeof(access_key));
|
||||||
|
const util::BitPack32 option = { static_cast<u32>(args.r[3]) };
|
||||||
|
const uintptr_t data_address = args.r[4];
|
||||||
|
const size_t data_size = args.r[5];
|
||||||
|
std::memcpy(key_source, std::addressof(args.r[6]), sizeof(key_source));
|
||||||
|
|
||||||
|
const auto mode = DeviceUniqueData_ImportEsDeviceKey;
|
||||||
|
const auto reserved = option.Get<DecryptDeviceUniqueDataOption::Reserved>();
|
||||||
|
|
||||||
|
const bool enforce_device_unique = option.Get<DecryptDeviceUniqueDataOption::EnforceDeviceUnique>();
|
||||||
|
|
||||||
|
/* Validate arguments. */
|
||||||
|
SMC_R_UNLESS(reserved == 0, InvalidArgument);
|
||||||
|
|
||||||
|
/* Ensure that the key is exactly the correct size. */
|
||||||
|
if (enforce_device_unique) {
|
||||||
|
SMC_R_UNLESS(data_size == util::AlignUp(2 * se::RsaSize + sizeof(u32), se::AesBlockSize) + DeviceUniqueDataTotalMetaSize, InvalidArgument);
|
||||||
|
} else {
|
||||||
|
SMC_R_UNLESS(data_size == util::AlignUp(2 * se::RsaSize + sizeof(u32), se::AesBlockSize) + DeviceUniqueDataIvSize, InvalidArgument);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Decrypt the device unique data. */
|
||||||
|
return DecryptDeviceUniqueDataImpl(access_key, key_source, mode, data_address, data_size, enforce_device_unique);
|
||||||
|
}
|
||||||
|
|
||||||
|
SmcResult DecryptAndImportLotusKeyImpl(SmcArguments &args) {
|
||||||
|
/* Decode arguments. */
|
||||||
|
u8 access_key[se::AesBlockSize];
|
||||||
|
u8 key_source[se::AesBlockSize];
|
||||||
|
|
||||||
|
std::memcpy(access_key, std::addressof(args.r[1]), sizeof(access_key));
|
||||||
|
const util::BitPack32 option = { static_cast<u32>(args.r[3]) };
|
||||||
|
const uintptr_t data_address = args.r[4];
|
||||||
|
const size_t data_size = args.r[5];
|
||||||
|
std::memcpy(key_source, std::addressof(args.r[6]), sizeof(key_source));
|
||||||
|
|
||||||
|
const auto mode = DeviceUniqueData_ImportLotusKey;
|
||||||
|
const auto reserved = option.Get<DecryptDeviceUniqueDataOption::Reserved>();
|
||||||
|
|
||||||
|
const bool enforce_device_unique = option.Get<DecryptDeviceUniqueDataOption::EnforceDeviceUnique>();
|
||||||
|
|
||||||
|
/* Validate arguments. */
|
||||||
|
SMC_R_UNLESS(reserved == 0, InvalidArgument);
|
||||||
|
|
||||||
|
/* Ensure that the key is exactly the correct size. */
|
||||||
|
if (enforce_device_unique) {
|
||||||
|
SMC_R_UNLESS(data_size == se::RsaSize + DeviceUniqueDataTotalMetaSize, InvalidArgument);
|
||||||
|
} else {
|
||||||
|
SMC_R_UNLESS(data_size == se::RsaSize + DeviceUniqueDataIvSize, InvalidArgument);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Decrypt the device unique data. */
|
||||||
|
return DecryptDeviceUniqueDataImpl(access_key, key_source, mode, data_address, data_size, enforce_device_unique);
|
||||||
|
}
|
||||||
|
|
||||||
SmcResult ReencryptDeviceUniqueDataImpl(SmcArguments &args) {
|
SmcResult ReencryptDeviceUniqueDataImpl(SmcArguments &args) {
|
||||||
/* Decode arguments. */
|
/* Decode arguments. */
|
||||||
u8 access_key_dec[se::AesBlockSize];
|
u8 access_key_dec[se::AesBlockSize];
|
||||||
|
@ -617,9 +701,11 @@ namespace ams::secmon::smc {
|
||||||
const auto mode = option.Get<DecryptDeviceUniqueDataOption::DeviceUniqueDataIndex>();
|
const auto mode = option.Get<DecryptDeviceUniqueDataOption::DeviceUniqueDataIndex>();
|
||||||
const auto reserved = option.Get<DecryptDeviceUniqueDataOption::Reserved>();
|
const auto reserved = option.Get<DecryptDeviceUniqueDataOption::Reserved>();
|
||||||
|
|
||||||
|
const bool enforce_device_unique = true;
|
||||||
|
|
||||||
/* Validate arguments. */
|
/* Validate arguments. */
|
||||||
SMC_R_UNLESS(reserved == 0, InvalidArgument);
|
SMC_R_UNLESS(reserved == 0, InvalidArgument);
|
||||||
SMC_R_TRY(ValidateDeviceUniqueDataSize(mode, data_size));
|
SMC_R_TRY(ValidateDeviceUniqueDataSize(mode, data_size, enforce_device_unique));
|
||||||
|
|
||||||
/* Decrypt the device unique data. */
|
/* Decrypt the device unique data. */
|
||||||
alignas(8) u8 work_buffer[DeviceUniqueDataSizeMax];
|
alignas(8) u8 work_buffer[DeviceUniqueDataSizeMax];
|
||||||
|
@ -640,7 +726,7 @@ namespace ams::secmon::smc {
|
||||||
/* Determine the seal key to use. */
|
/* Determine the seal key to use. */
|
||||||
const u8 * const seal_key_source = SealKeySources[SealKey_ReencryptDeviceUniqueData];
|
const u8 * const seal_key_source = SealKeySources[SealKey_ReencryptDeviceUniqueData];
|
||||||
|
|
||||||
if (!DecryptDeviceUniqueData(work_buffer, data_size, std::addressof(device_id_high), seal_key_source, se::AesBlockSize, access_key_dec, sizeof(access_key_dec), key_source_dec, sizeof(key_source_dec), work_buffer, data_size)) {
|
if (!DecryptDeviceUniqueData(work_buffer, data_size, std::addressof(device_id_high), seal_key_source, se::AesBlockSize, access_key_dec, sizeof(access_key_dec), key_source_dec, sizeof(key_source_dec), work_buffer, data_size, enforce_device_unique)) {
|
||||||
return SmcResult::InvalidArgument;
|
return SmcResult::InvalidArgument;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -721,13 +807,11 @@ namespace ams::secmon::smc {
|
||||||
|
|
||||||
/* Legacy APIs. */
|
/* Legacy APIs. */
|
||||||
SmcResult SmcDecryptAndImportEsDeviceKey(SmcArguments &args) {
|
SmcResult SmcDecryptAndImportEsDeviceKey(SmcArguments &args) {
|
||||||
/* TODO */
|
return LockSecurityEngineAndInvoke(args, DecryptAndImportEsDeviceKeyImpl);
|
||||||
return SmcResult::NotImplemented;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SmcResult SmcDecryptAndImportLotusKey(SmcArguments &args) {
|
SmcResult SmcDecryptAndImportLotusKey(SmcArguments &args) {
|
||||||
/* TODO */
|
return LockSecurityEngineAndInvoke(args, DecryptAndImportLotusKeyImpl);
|
||||||
return SmcResult::NotImplemented;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Es encryption utilities. */
|
/* Es encryption utilities. */
|
||||||
|
|
|
@ -90,13 +90,13 @@ namespace ams::secmon::smc {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DecryptDeviceUniqueData(void *dst, size_t dst_size, u8 *out_device_id_high, const void *seal_key_source, size_t seal_key_source_size, const void *access_key, size_t access_key_size, const void *key_source, size_t key_source_size, const void *src, size_t src_size) {
|
bool DecryptDeviceUniqueData(void *dst, size_t dst_size, u8 *out_device_id_high, const void *seal_key_source, size_t seal_key_source_size, const void *access_key, size_t access_key_size, const void *key_source, size_t key_source_size, const void *src, size_t src_size, bool enforce_device_unique) {
|
||||||
/* Determine how much decrypted data there will be. */
|
/* Determine how much decrypted data there will be. */
|
||||||
const size_t enc_size = src_size - DeviceUniqueDataOuterMetaSize;
|
const size_t enc_size = src_size - (enforce_device_unique ? DeviceUniqueDataOuterMetaSize : DeviceUniqueDataIvSize);
|
||||||
const size_t dec_size = enc_size - DeviceUniqueDataInnerMetaSize;
|
const size_t dec_size = enc_size - DeviceUniqueDataInnerMetaSize;
|
||||||
|
|
||||||
/* Ensure that our sizes are allowed. */
|
/* Ensure that our sizes are allowed. */
|
||||||
AMS_ABORT_UNLESS(src_size > DeviceUniqueDataTotalMetaSize);
|
AMS_ABORT_UNLESS(src_size > (enforce_device_unique ? DeviceUniqueDataTotalMetaSize : DeviceUniqueDataIvSize));
|
||||||
AMS_ABORT_UNLESS(dst_size >= enc_size);
|
AMS_ABORT_UNLESS(dst_size >= enc_size);
|
||||||
|
|
||||||
/* Determine the extents of the data. */
|
/* Determine the extents of the data. */
|
||||||
|
@ -120,6 +120,11 @@ namespace ams::secmon::smc {
|
||||||
/* Decrypt the data. */
|
/* Decrypt the data. */
|
||||||
ComputeAes128Ctr(dst, dst_size, pkg1::AesKeySlot_Smc, enc, enc_size, temp_iv, DeviceUniqueDataIvSize);
|
ComputeAes128Ctr(dst, dst_size, pkg1::AesKeySlot_Smc, enc, enc_size, temp_iv, DeviceUniqueDataIvSize);
|
||||||
|
|
||||||
|
/* If we're not enforcing device unique, there's no mac/device id. */
|
||||||
|
if (!enforce_device_unique) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/* Compute the gmac. */
|
/* Compute the gmac. */
|
||||||
ComputeGmac(calc_mac, DeviceUniqueDataMacSize, dst, enc_size, temp_iv, DeviceUniqueDataIvSize);
|
ComputeGmac(calc_mac, DeviceUniqueDataMacSize, dst, enc_size, temp_iv, DeviceUniqueDataIvSize);
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ namespace ams::secmon::smc {
|
||||||
constexpr inline size_t DeviceUniqueDataInnerMetaSize = DeviceUniqueDataPaddingSize + DeviceUniqueDataDeviceIdSize;
|
constexpr inline size_t DeviceUniqueDataInnerMetaSize = DeviceUniqueDataPaddingSize + DeviceUniqueDataDeviceIdSize;
|
||||||
constexpr inline size_t DeviceUniqueDataTotalMetaSize = DeviceUniqueDataOuterMetaSize + DeviceUniqueDataInnerMetaSize;
|
constexpr inline size_t DeviceUniqueDataTotalMetaSize = DeviceUniqueDataOuterMetaSize + DeviceUniqueDataInnerMetaSize;
|
||||||
|
|
||||||
bool DecryptDeviceUniqueData(void *dst, size_t dst_size, u8 *out_device_id_high, const void *seal_key_source, size_t seal_key_source_size, const void *access_key, size_t access_key_size, const void *key_source, size_t key_source_size, const void *src, size_t src_size);
|
bool DecryptDeviceUniqueData(void *dst, size_t dst_size, u8 *out_device_id_high, const void *seal_key_source, size_t seal_key_source_size, const void *access_key, size_t access_key_size, const void *key_source, size_t key_source_size, const void *src, size_t src_size, bool enforce_device_unique);
|
||||||
void EncryptDeviceUniqueData(void *dst, size_t dst_size, const void *seal_key_source, size_t seal_key_source_size, const void *access_key, size_t access_key_size, const void *key_source, size_t key_source_size, const void *src, size_t src_size, u8 device_id_high);
|
void EncryptDeviceUniqueData(void *dst, size_t dst_size, const void *seal_key_source, size_t seal_key_source_size, const void *access_key, size_t access_key_size, const void *key_source, size_t key_source_size, const void *src, size_t src_size, u8 device_id_high);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -122,6 +122,15 @@ namespace ams::secmon::smc {
|
||||||
{ 0xC3000012, Restriction_SafeModeNotAllowed, SmcPrepareEsCommonTitleKey }
|
{ 0xC3000012, Restriction_SafeModeNotAllowed, SmcPrepareEsCommonTitleKey }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Deprecated handlerss. */
|
||||||
|
constexpr inline const HandlerInfo DecryptAndImportEsDeviceKeyHandlerInfo = {
|
||||||
|
0xC300100C, Restriction_DeviceUniqueDataNotAllowed, SmcDecryptAndImportEsDeviceKey
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr inline const HandlerInfo DecryptAndImportLotusKeyHandlerInfo = {
|
||||||
|
0xC300100E, Restriction_DeviceUniqueDataNotAllowed, SmcDecryptAndImportLotusKey
|
||||||
|
};
|
||||||
|
|
||||||
constinit HandlerInfo g_kern_handlers[] = {
|
constinit HandlerInfo g_kern_handlers[] = {
|
||||||
{ 0x00000000, Restriction_SafeModeNotAllowed, nullptr },
|
{ 0x00000000, Restriction_SafeModeNotAllowed, nullptr },
|
||||||
{ 0xC4000001, Restriction_SafeModeNotAllowed, SmcSuspendCpu },
|
{ 0xC4000001, Restriction_SafeModeNotAllowed, SmcSuspendCpu },
|
||||||
|
@ -266,6 +275,15 @@ namespace ams::secmon::smc {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ConfigureSmcHandlersForTargetFirmware() {
|
||||||
|
const auto target_fw = GetTargetFirmware();
|
||||||
|
|
||||||
|
if (target_fw < TargetFirmware_5_0_0) {
|
||||||
|
g_user_handlers[DecryptAndImportEsDeviceKeyHandlerInfo.function_id & 0xFF] = DecryptAndImportEsDeviceKeyHandlerInfo;
|
||||||
|
g_user_handlers[DecryptAndImportLotusKeyHandlerInfo.function_id & 0xFF] = DecryptAndImportLotusKeyHandlerInfo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void HandleSmc(int type, SmcArguments &args) {
|
void HandleSmc(int type, SmcArguments &args) {
|
||||||
/* Get the table. */
|
/* Get the table. */
|
||||||
const auto &table = GetHandlerTable(static_cast<HandlerType>(type), args.r[0]);
|
const auto &table = GetHandlerTable(static_cast<HandlerType>(type), args.r[0]);
|
||||||
|
|
|
@ -21,4 +21,6 @@ namespace ams::secmon::smc {
|
||||||
|
|
||||||
using SmcHandler = SmcResult (*)(SmcArguments &args);
|
using SmcHandler = SmcResult (*)(SmcArguments &args);
|
||||||
|
|
||||||
|
void ConfigureSmcHandlersForTargetFirmware();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -157,8 +157,9 @@ namespace ams::secmon::smc {
|
||||||
AMS_ABORT_UNLESS(reg::HasValue(PMC + APBDEV_PMC_PWRGATE_STATUS, PMC_REG_BITS_VALUE(PWRGATE_STATUS_CE123, 0)));
|
AMS_ABORT_UNLESS(reg::HasValue(PMC + APBDEV_PMC_PWRGATE_STATUS, PMC_REG_BITS_VALUE(PWRGATE_STATUS_CE123, 0)));
|
||||||
|
|
||||||
/* Validate that the bpmp is appropriately halted. */
|
/* Validate that the bpmp is appropriately halted. */
|
||||||
|
const bool jtag = IsJtagEnabled() || GetTargetFirmware() < TargetFirmware_4_0_0;
|
||||||
AMS_ABORT_UNLESS(reg::Read(FLOW_CTLR + FLOW_CTLR_HALT_COP_EVENTS) == reg::Encode(FLOW_REG_BITS_ENUM (HALT_COP_EVENTS_MODE, FLOW_MODE_STOP),
|
AMS_ABORT_UNLESS(reg::Read(FLOW_CTLR + FLOW_CTLR_HALT_COP_EVENTS) == reg::Encode(FLOW_REG_BITS_ENUM (HALT_COP_EVENTS_MODE, FLOW_MODE_STOP),
|
||||||
FLOW_REG_BITS_ENUM_SEL(HALT_COP_EVENTS_JTAG, IsJtagEnabled(), ENABLED, DISABLED)));
|
FLOW_REG_BITS_ENUM_SEL(HALT_COP_EVENTS_JTAG, jtag, ENABLED, DISABLED)));
|
||||||
|
|
||||||
/* TODO */
|
/* TODO */
|
||||||
}
|
}
|
||||||
|
@ -300,6 +301,9 @@ namespace ams::secmon::smc {
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoadAndStartSc7BpmpFirmware() {
|
void LoadAndStartSc7BpmpFirmware() {
|
||||||
|
/* Set BPMP reset. */
|
||||||
|
reg::Write(CLK_RST + CLK_RST_CONTROLLER_RST_DEV_L_SET, CLK_RST_REG_BITS_ENUM(RST_DEV_L_SET_SET_COP_RST, ENABLE));
|
||||||
|
|
||||||
/* Set the PMC as insecure, so that the BPMP firmware can access it. */
|
/* Set the PMC as insecure, so that the BPMP firmware can access it. */
|
||||||
reg::ReadWrite(APB_MISC + APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG0_0, SLAVE_SECURITY_REG_BITS_ENUM(0, PMC, DISABLE));
|
reg::ReadWrite(APB_MISC + APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG0_0, SLAVE_SECURITY_REG_BITS_ENUM(0, PMC, DISABLE));
|
||||||
|
|
||||||
|
@ -319,9 +323,6 @@ namespace ams::secmon::smc {
|
||||||
/* Disable activity monitor bpmp monitoring, so that we don't panic upon bpmp wake. */
|
/* Disable activity monitor bpmp monitoring, so that we don't panic upon bpmp wake. */
|
||||||
actmon::StopMonitoringBpmp();
|
actmon::StopMonitoringBpmp();
|
||||||
|
|
||||||
/* Set BPMP reset. */
|
|
||||||
reg::Write(CLK_RST + CLK_RST_CONTROLLER_RST_DEV_L_SET, CLK_RST_REG_BITS_ENUM(RST_DEV_L_SET_SET_COP_RST, ENABLE));
|
|
||||||
|
|
||||||
/* Load the bpmp firmware. */
|
/* Load the bpmp firmware. */
|
||||||
void * const sc7fw_load_address = MemoryRegionVirtualIramSc7Firmware.GetPointer<void>();
|
void * const sc7fw_load_address = MemoryRegionVirtualIramSc7Firmware.GetPointer<void>();
|
||||||
std::memcpy(sc7fw_load_address, sc7fw_bin, sc7fw_bin_size);
|
std::memcpy(sc7fw_load_address, sc7fw_bin, sc7fw_bin_size);
|
||||||
|
@ -417,7 +418,9 @@ namespace ams::secmon::smc {
|
||||||
pmic::EnableSleep();
|
pmic::EnableSleep();
|
||||||
|
|
||||||
/* Ensure that the soc is in a state valid for us to suspend. */
|
/* Ensure that the soc is in a state valid for us to suspend. */
|
||||||
ValidateSocStateForSuspend();
|
if (GetTargetFirmware() >= TargetFirmware_2_0_0) {
|
||||||
|
ValidateSocStateForSuspend();
|
||||||
|
}
|
||||||
|
|
||||||
/* Configure the pmc for sc7 entry. */
|
/* Configure the pmc for sc7 entry. */
|
||||||
pmc::ConfigureForSc7Entry();
|
pmc::ConfigureForSc7Entry();
|
||||||
|
|
|
@ -43,6 +43,16 @@ namespace ams::secmon::smc {
|
||||||
};
|
};
|
||||||
constexpr size_t ModularExponentiateByStorageKeyTableSize = util::size(ModularExponentiateByStorageKeyTable);
|
constexpr size_t ModularExponentiateByStorageKeyTableSize = util::size(ModularExponentiateByStorageKeyTable);
|
||||||
|
|
||||||
|
consteval u32 GetModeForImportRsaKey(ImportRsaKey import_key) {
|
||||||
|
for (size_t i = 0; i < ModularExponentiateByStorageKeyTableSize; ++i) {
|
||||||
|
if (static_cast<ImportRsaKey>(ModularExponentiateByStorageKeyTable[i]) == import_key) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AMS_ASSUME(false);
|
||||||
|
}
|
||||||
|
|
||||||
class PrepareEsDeviceUniqueKeyAsyncArguments {
|
class PrepareEsDeviceUniqueKeyAsyncArguments {
|
||||||
private:
|
private:
|
||||||
int generation;
|
int generation;
|
||||||
|
@ -200,7 +210,7 @@ namespace ams::secmon::smc {
|
||||||
const uintptr_t mod_address = args.r[2];
|
const uintptr_t mod_address = args.r[2];
|
||||||
const util::BitPack32 option = { static_cast<u32>(args.r[3]) };
|
const util::BitPack32 option = { static_cast<u32>(args.r[3]) };
|
||||||
|
|
||||||
const auto mode = option.Get<ModularExponentiateByStorageKeyOption::Mode>();
|
const auto mode = GetTargetFirmware() >= TargetFirmware_5_0_0 ? option.Get<ModularExponentiateByStorageKeyOption::Mode>() : GetModeForImportRsaKey(ImportRsaKey_Lotus);
|
||||||
const auto reserved = option.Get<PrepareEsDeviceUniqueKeyOption::Reserved>();
|
const auto reserved = option.Get<PrepareEsDeviceUniqueKeyOption::Reserved>();
|
||||||
|
|
||||||
/* Validate arguments. */
|
/* Validate arguments. */
|
||||||
|
@ -250,7 +260,7 @@ namespace ams::secmon::smc {
|
||||||
std::memcpy(label_digest, std::addressof(args.r[3]), sizeof(label_digest));
|
std::memcpy(label_digest, std::addressof(args.r[3]), sizeof(label_digest));
|
||||||
const util::BitPack32 option = { static_cast<u32>(args.r[7]) };
|
const util::BitPack32 option = { static_cast<u32>(args.r[7]) };
|
||||||
|
|
||||||
const auto generation = GetTargetFirmware() >= TargetFirmware_3_0_0 ? std::max(0, option.Get<PrepareEsDeviceUniqueKeyOption::KeyGeneration>() - 1) : 0;
|
const auto generation = GetTargetFirmware() >= TargetFirmware_3_0_0 ? std::max<int>(pkg1::KeyGeneration_1_0_0, option.Get<PrepareEsDeviceUniqueKeyOption::KeyGeneration>() - 1) : pkg1::KeyGeneration_1_0_0;
|
||||||
const auto type = option.Get<PrepareEsDeviceUniqueKeyOption::Type>();
|
const auto type = option.Get<PrepareEsDeviceUniqueKeyOption::Type>();
|
||||||
const auto reserved = option.Get<PrepareEsDeviceUniqueKeyOption::Reserved>();
|
const auto reserved = option.Get<PrepareEsDeviceUniqueKeyOption::Reserved>();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue