From da4107996a2cd30db10f24296c62567066c9ad39 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Thu, 11 Jun 2020 19:17:20 -0700 Subject: [PATCH] exo2: first pass at backwards-compat --- exosphere/program/source/boot/secmon_main.cpp | 4 + exosphere/program/source/secmon_setup.cpp | 41 ++++-- .../program/source/smc/secmon_smc_aes.cpp | 138 ++++++++++++++---- .../smc/secmon_smc_device_unique_data.cpp | 11 +- .../smc/secmon_smc_device_unique_data.hpp | 2 +- .../program/source/smc/secmon_smc_handler.cpp | 18 +++ .../program/source/smc/secmon_smc_handler.hpp | 2 + .../smc/secmon_smc_power_management.cpp | 13 +- .../program/source/smc/secmon_smc_rsa.cpp | 14 +- 9 files changed, 195 insertions(+), 48 deletions(-) diff --git a/exosphere/program/source/boot/secmon_main.cpp b/exosphere/program/source/boot/secmon_main.cpp index 6769cd9e7..db1e1e090 100644 --- a/exosphere/program/source/boot/secmon_main.cpp +++ b/exosphere/program/source/boot/secmon_main.cpp @@ -17,6 +17,7 @@ #include "secmon_boot.hpp" #include "secmon_boot_functions.hpp" #include "../smc/secmon_random_cache.hpp" +#include "../smc/secmon_smc_handler.hpp" #include "../secmon_cache.hpp" #include "../secmon_cpu_context.hpp" #include "../secmon_misc.hpp" @@ -180,6 +181,9 @@ namespace ams::secmon { /* Perform final initialization. */ secmon::SetupSocProtections(); secmon::SetupCpuSErrorDebug(); + + /* Configure the smc handler tables to reflect the current target firmware. */ + secmon::smc::ConfigureSmcHandlersForTargetFirmware(); } } diff --git a/exosphere/program/source/secmon_setup.cpp b/exosphere/program/source/secmon_setup.cpp index 254b8e51f..f3daa86fc 100644 --- a/exosphere/program/source/secmon_setup.cpp +++ b/exosphere/program/source/secmon_setup.cpp @@ -584,6 +584,11 @@ namespace ams::secmon { MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_LOCK_MODE, LOCKED), 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. */ SetupKernelCarveouts(); @@ -599,10 +604,15 @@ namespace ams::secmon { reg::Write(MC + MC_SMMU_TRANSLATION_ENABLE_3, ~0u); reg::Write(MC + MC_SMMU_TRANSLATION_ENABLE_4, ~0u); - /* 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), - MC_REG_BITS_ENUM(SMMU_ASID_SECURITY_SECURE_ASIDS_2, SECURE), - MC_REG_BITS_ENUM(SMMU_ASID_SECURITY_SECURE_ASIDS_3, SECURE)); + /* On modern firmware, configure ASIDs 1-3 as secure, and all others as non-secure. */ + if (GetTargetFirmware() >= TargetFirmware_4_0_0) { + 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_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_2, 0); @@ -1115,6 +1125,11 @@ namespace ams::secmon { /* Disable the ARC. */ DisableArc(); + /* Further protections are applied only on 4.0.0+. */ + if (GetTargetFirmware() < TargetFirmware_4_0_0) { + return; + } + /* Finalize and lock the carveout scratch registers. */ FinalizeCarveoutSecureScratchRegisters(); pmc::LockSecureRegister(pmc::SecureRegister_Carveout); @@ -1155,13 +1170,19 @@ namespace ams::secmon { } void SetupPmcAndMcSecure() { - /* Set the PMC secure. */ - reg::ReadWrite(APB_MISC + APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG0_0, SLAVE_SECURITY_REG_BITS_ENUM(0, PMC, ENABLE)); + const auto target_fw = GetTargetFirmware(); - /* 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)); + if (target_fw >= TargetFirmware_2_0_0) { + /* Set the PMC secure. */ + reg::ReadWrite(APB_MISC + APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG0_0, SLAVE_SECURITY_REG_BITS_ENUM(0, PMC, 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() { diff --git a/exosphere/program/source/smc/secmon_smc_aes.cpp b/exosphere/program/source/smc/secmon_smc_aes.cpp index cfb992e33..7dabf7d43 100644 --- a/exosphere/program/source/smc/secmon_smc_aes.cpp +++ b/exosphere/program/source/smc/secmon_smc_aes.cpp @@ -114,6 +114,9 @@ namespace ams::secmon::smc { struct DecryptDeviceUniqueDataOption { using DeviceUniqueDataIndex = util::BitPack32::Field<0, 3, DeviceUniqueData>; using Reserved = util::BitPack32::Field<3, 29, u32>; + + /* Legacy. */ + using EnforceDeviceUnique = util::BitPack32::Field<0, 1, bool>; }; constexpr const u8 SealKeySources[SealKey_Count][AesKeySize] = { @@ -499,7 +502,7 @@ namespace ams::secmon::smc { /* Decode arguments. */ 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(args.r[3]) - 1) : 0; + const int generation = GetTargetFirmware() >= TargetFirmware_3_0_0 ? std::max(pkg1::KeyGeneration_1_0_0, static_cast(args.r[3]) - 1) : pkg1::KeyGeneration_1_0_0; /* Validate arguments. */ SMC_R_UNLESS(pkg1::IsValidKeyGeneration(generation), InvalidArgument); @@ -517,11 +520,23 @@ namespace ams::secmon::smc { 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) { case DeviceUniqueData_DecryptDeviceUniqueData: { - SMC_R_UNLESS(data_size < DeviceUniqueDataSizeMax, InvalidArgument); + SMC_R_UNLESS(DeviceUniqueDataTotalMetaSize - discounted_size < data_size && data_size <= DeviceUniqueDataSizeMax, InvalidArgument); } break; case DeviceUniqueData_ImportLotusKey: @@ -529,7 +544,7 @@ namespace ams::secmon::smc { case DeviceUniqueData_ImportSslKey: 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; default: @@ -539,23 +554,9 @@ namespace ams::secmon::smc { 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(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(); - const auto reserved = option.Get(); - + 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) { /* Validate arguments. */ - 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. */ alignas(8) u8 work_buffer[DeviceUniqueDataSizeMax]; @@ -571,7 +572,7 @@ namespace ams::secmon::smc { const u8 * const seal_key_source = SealKeySources[seal_key_type]; /* 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; } @@ -599,6 +600,89 @@ namespace ams::secmon::smc { 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(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() : DeviceUniqueData_DecryptDeviceUniqueData; + const auto reserved = option.Get(); + + const bool enforce_device_unique = GetTargetFirmware() >= TargetFirmware_5_0_0 ? true : option.Get(); + + /* 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(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(); + + const bool enforce_device_unique = option.Get(); + + /* 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(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(); + + const bool enforce_device_unique = option.Get(); + + /* 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) { /* Decode arguments. */ u8 access_key_dec[se::AesBlockSize]; @@ -617,9 +701,11 @@ namespace ams::secmon::smc { const auto mode = option.Get(); const auto reserved = option.Get(); + const bool enforce_device_unique = true; + /* Validate arguments. */ 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. */ alignas(8) u8 work_buffer[DeviceUniqueDataSizeMax]; @@ -640,7 +726,7 @@ namespace ams::secmon::smc { /* Determine the seal key to use. */ 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; } } @@ -721,13 +807,11 @@ namespace ams::secmon::smc { /* Legacy APIs. */ SmcResult SmcDecryptAndImportEsDeviceKey(SmcArguments &args) { - /* TODO */ - return SmcResult::NotImplemented; + return LockSecurityEngineAndInvoke(args, DecryptAndImportEsDeviceKeyImpl); } SmcResult SmcDecryptAndImportLotusKey(SmcArguments &args) { - /* TODO */ - return SmcResult::NotImplemented; + return LockSecurityEngineAndInvoke(args, DecryptAndImportLotusKeyImpl); } /* Es encryption utilities. */ diff --git a/exosphere/program/source/smc/secmon_smc_device_unique_data.cpp b/exosphere/program/source/smc/secmon_smc_device_unique_data.cpp index 6505daa52..b6f6b2d4d 100644 --- a/exosphere/program/source/smc/secmon_smc_device_unique_data.cpp +++ b/exosphere/program/source/smc/secmon_smc_device_unique_data.cpp @@ -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. */ - 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; /* 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); /* Determine the extents of the data. */ @@ -120,6 +120,11 @@ namespace ams::secmon::smc { /* Decrypt the data. */ 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. */ ComputeGmac(calc_mac, DeviceUniqueDataMacSize, dst, enc_size, temp_iv, DeviceUniqueDataIvSize); diff --git a/exosphere/program/source/smc/secmon_smc_device_unique_data.hpp b/exosphere/program/source/smc/secmon_smc_device_unique_data.hpp index a8e790151..10e5d2b84 100644 --- a/exosphere/program/source/smc/secmon_smc_device_unique_data.hpp +++ b/exosphere/program/source/smc/secmon_smc_device_unique_data.hpp @@ -28,7 +28,7 @@ namespace ams::secmon::smc { constexpr inline size_t DeviceUniqueDataInnerMetaSize = DeviceUniqueDataPaddingSize + DeviceUniqueDataDeviceIdSize; 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); } diff --git a/exosphere/program/source/smc/secmon_smc_handler.cpp b/exosphere/program/source/smc/secmon_smc_handler.cpp index 644139b3c..a3cc7929c 100644 --- a/exosphere/program/source/smc/secmon_smc_handler.cpp +++ b/exosphere/program/source/smc/secmon_smc_handler.cpp @@ -122,6 +122,15 @@ namespace ams::secmon::smc { { 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[] = { { 0x00000000, Restriction_SafeModeNotAllowed, nullptr }, { 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) { /* Get the table. */ const auto &table = GetHandlerTable(static_cast(type), args.r[0]); diff --git a/exosphere/program/source/smc/secmon_smc_handler.hpp b/exosphere/program/source/smc/secmon_smc_handler.hpp index f05120951..4f1fc682b 100644 --- a/exosphere/program/source/smc/secmon_smc_handler.hpp +++ b/exosphere/program/source/smc/secmon_smc_handler.hpp @@ -21,4 +21,6 @@ namespace ams::secmon::smc { using SmcHandler = SmcResult (*)(SmcArguments &args); + void ConfigureSmcHandlersForTargetFirmware(); + } diff --git a/exosphere/program/source/smc/secmon_smc_power_management.cpp b/exosphere/program/source/smc/secmon_smc_power_management.cpp index 93f053887..97bb80399 100644 --- a/exosphere/program/source/smc/secmon_smc_power_management.cpp +++ b/exosphere/program/source/smc/secmon_smc_power_management.cpp @@ -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))); /* 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), - 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 */ } @@ -300,6 +301,9 @@ namespace ams::secmon::smc { } 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. */ 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. */ 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. */ void * const sc7fw_load_address = MemoryRegionVirtualIramSc7Firmware.GetPointer(); std::memcpy(sc7fw_load_address, sc7fw_bin, sc7fw_bin_size); @@ -417,7 +418,9 @@ namespace ams::secmon::smc { pmic::EnableSleep(); /* 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. */ pmc::ConfigureForSc7Entry(); diff --git a/exosphere/program/source/smc/secmon_smc_rsa.cpp b/exosphere/program/source/smc/secmon_smc_rsa.cpp index d84ce9b14..01104a503 100644 --- a/exosphere/program/source/smc/secmon_smc_rsa.cpp +++ b/exosphere/program/source/smc/secmon_smc_rsa.cpp @@ -43,6 +43,16 @@ namespace ams::secmon::smc { }; constexpr size_t ModularExponentiateByStorageKeyTableSize = util::size(ModularExponentiateByStorageKeyTable); + consteval u32 GetModeForImportRsaKey(ImportRsaKey import_key) { + for (size_t i = 0; i < ModularExponentiateByStorageKeyTableSize; ++i) { + if (static_cast(ModularExponentiateByStorageKeyTable[i]) == import_key) { + return i; + } + } + + AMS_ASSUME(false); + } + class PrepareEsDeviceUniqueKeyAsyncArguments { private: int generation; @@ -200,7 +210,7 @@ namespace ams::secmon::smc { const uintptr_t mod_address = args.r[2]; const util::BitPack32 option = { static_cast(args.r[3]) }; - const auto mode = option.Get(); + const auto mode = GetTargetFirmware() >= TargetFirmware_5_0_0 ? option.Get() : GetModeForImportRsaKey(ImportRsaKey_Lotus); const auto reserved = option.Get(); /* Validate arguments. */ @@ -250,7 +260,7 @@ namespace ams::secmon::smc { std::memcpy(label_digest, std::addressof(args.r[3]), sizeof(label_digest)); const util::BitPack32 option = { static_cast(args.r[7]) }; - const auto generation = GetTargetFirmware() >= TargetFirmware_3_0_0 ? std::max(0, option.Get() - 1) : 0; + const auto generation = GetTargetFirmware() >= TargetFirmware_3_0_0 ? std::max(pkg1::KeyGeneration_1_0_0, option.Get() - 1) : pkg1::KeyGeneration_1_0_0; const auto type = option.Get(); const auto reserved = option.Get();