From 79e4c0ef6e0dbd3cfcf3890ed98ac62fa8e0c37e Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Fri, 12 Jun 2020 02:21:08 -0700 Subject: [PATCH] exo2: add security checks, full 2.0.0 support --- exosphere/program/source/secmon_setup.cpp | 14 ++++---- .../program/source/secmon_setup_warm.cpp | 20 +++++------ .../smc/secmon_smc_power_management.cpp | 36 +++++++++++++++++-- .../exosphere/tegra/tegra_ahb_arbc.hpp | 5 ++- .../include/exosphere/tegra/tegra_clkrst.hpp | 10 +++++- 5 files changed, 62 insertions(+), 23 deletions(-) diff --git a/exosphere/program/source/secmon_setup.cpp b/exosphere/program/source/secmon_setup.cpp index 5c49db908..7c9ce28e8 100644 --- a/exosphere/program/source/secmon_setup.cpp +++ b/exosphere/program/source/secmon_setup.cpp @@ -1125,8 +1125,8 @@ namespace ams::secmon { /* Disable the ARC. */ DisableArc(); - /* Further protections are applied only on 4.0.0+. */ - if (GetTargetFirmware() < TargetFirmware_4_0_0) { + /* Further protections aren't applied on <= 1.0.0. */ + if (GetTargetFirmware() <= TargetFirmware_1_0_0) { return; } @@ -1156,16 +1156,16 @@ namespace ams::secmon { util::WaitMicroSeconds(1); } + /* Enable clock to the activity monitor. */ + clkrst::EnableActmonClock(); + /* If JTAG is disabled, disable JTAG. */ if (!secmon::IsJtagEnabled()) { reg::Write(FLOW_CTLR + FLOW_CTLR_HALT_COP_EVENTS, FLOW_REG_BITS_ENUM(HALT_COP_EVENTS_MODE, FLOW_MODE_STOP), FLOW_REG_BITS_ENUM(HALT_COP_EVENTS_JTAG, DISABLED)); - /* If version is above 4.0.0, turn on the activity monitor to prevent booting up the bpmp. */ - if (GetTargetFirmware() >= TargetFirmware_4_0_0) { - clkrst::EnableActmonClock(); - actmon::StartMonitoringBpmp(ActmonInterruptHandler); - } + /* Turn on the activity monitor to prevent booting up the bpmp. */ + actmon::StartMonitoringBpmp(ActmonInterruptHandler); } } diff --git a/exosphere/program/source/secmon_setup_warm.cpp b/exosphere/program/source/secmon_setup_warm.cpp index 560359339..331502e02 100644 --- a/exosphere/program/source/secmon_setup_warm.cpp +++ b/exosphere/program/source/secmon_setup_warm.cpp @@ -238,22 +238,18 @@ namespace ams::secmon { /* Set MSELECT config to set WRAP_TO_INCR_SLAVE0(APC) | WRAP_TO_INCR_SLAVE1(PCIe) | WRAP_TO_INCR_SLAVE2(GPU) */ /* and clear ERR_RESP_EN_SLAVE1(PCIe) | ERR_RESP_EN_SLAVE2(GPU) */ { - auto mselect_cfg = reg::Read(MSELECT(MSELECT_CONFIG)); - mselect_cfg &= ~(1u << 24); /* Clear ERR_RESP_EN_SLAVE1(PCIe) */ - mselect_cfg &= ~(1u << 25); /* Clear ERR_RESP_EN_SLAVE2(GPU) */ - mselect_cfg |= (1u << 27); /* Set WRAP_TO_INCR_SLAVE0(APC) */ - mselect_cfg |= (1u << 28); /* Set WRAP_TO_INCR_SLAVE1(PCIe) */ - mselect_cfg |= (1u << 29); /* Set WRAP_TO_INCR_SLAVE2(GPU) */ - reg::Write(MSELECT(MSELECT_CONFIG), mselect_cfg); + reg::ReadWrite(MSELECT(MSELECT_CONFIG), MSELECT_REG_BITS_ENUM(CONFIG_ERR_RESP_EN_SLAVE1, DISABLE), + MSELECT_REG_BITS_ENUM(CONFIG_ERR_RESP_EN_SLAVE2, DISABLE), + MSELECT_REG_BITS_ENUM(CONFIG_WRAP_TO_INCR_SLAVE0, ENABLE), + MSELECT_REG_BITS_ENUM(CONFIG_WRAP_TO_INCR_SLAVE1, ENABLE), + MSELECT_REG_BITS_ENUM(CONFIG_WRAP_TO_INCR_SLAVE2, ENABLE)); } /* Disable USB, USB2, AHB-DMA from arbitration. */ { - auto arb_dis = reg::Read(AHB_ARBC(AHB_ARBITRATION_DISABLE)); - arb_dis |= (1u << 5); /* Disable AHB-DMA */ - arb_dis |= (1u << 6); /* Disable USB */ - arb_dis |= (1u << 18); /* Disable USB2 */ - reg::Write(AHB_ARBC(AHB_ARBITRATION_DISABLE), arb_dis); + reg::ReadWrite(AHB_ARBC(AHB_ARBITRATION_DISABLE), AHB_REG_BITS_ENUM(ARBITRATION_DISABLE_AHBDMA, DISABLE), + AHB_REG_BITS_ENUM(ARBITRATION_DISABLE_USB, DISABLE), + AHB_REG_BITS_ENUM(ARBITRATION_DISABLE_USB2, DISABLE)); } /* Select high priority group with priority 7. */ diff --git a/exosphere/program/source/smc/secmon_smc_power_management.cpp b/exosphere/program/source/smc/secmon_smc_power_management.cpp index 66251b42e..eb65e7243 100644 --- a/exosphere/program/source/smc/secmon_smc_power_management.cpp +++ b/exosphere/program/source/smc/secmon_smc_power_management.cpp @@ -44,6 +44,7 @@ namespace ams::secmon::smc { constexpr inline const uintptr_t CLK_RST = MemoryRegionVirtualDeviceClkRst.GetAddress(); constexpr inline const uintptr_t EVP = secmon::MemoryRegionVirtualDeviceExceptionVectors.GetAddress(); constexpr inline const uintptr_t FLOW_CTLR = MemoryRegionVirtualDeviceFlowController.GetAddress(); + constexpr inline const uintptr_t AHB_ARBC = MemoryRegionVirtualDeviceSystem.GetAddress(); constexpr inline uintptr_t CommonSmcStackTop = MemoryRegionVirtualTzramVolatileData.GetEndAddress() - (0x80 * (NumCores - 1)); @@ -157,11 +158,42 @@ 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; + const bool jtag = IsJtagEnabled(); 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, jtag, ENABLED, DISABLED))); - /* TODO */ + /* Validate that USB2, APB-DMA, AHB-DMA are held in reset. */ + AMS_ABORT_UNLESS(reg::HasValue(CLK_RST + CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_REG_BITS_ENUM(RST_DEVICES_H_SWR_USB2_RST, ENABLE), + CLK_RST_REG_BITS_ENUM(RST_DEVICES_H_SWR_APBDMA_RST, ENABLE), + CLK_RST_REG_BITS_ENUM(RST_DEVICES_H_SWR_AHBDMA_RST, ENABLE))); + + /* Validate that USBD is held in reset. */ + AMS_ABORT_UNLESS(reg::HasValue(CLK_RST + CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_REG_BITS_ENUM(RST_DEVICES_L_SWR_USBD_RST, ENABLE))); + + /* Validate that AHB-DMA, USB, USB2, COP are not allowed to arbitrate on the AHB. */ + AMS_ABORT_UNLESS(reg::HasValue(AHB_ARBC + AHB_ARBITRATION_DISABLE, AHB_REG_BITS_ENUM(ARBITRATION_DISABLE_COP, DISABLE), + AHB_REG_BITS_ENUM(ARBITRATION_DISABLE_AHBDMA, DISABLE), + AHB_REG_BITS_ENUM(ARBITRATION_DISABLE_USB, DISABLE), + AHB_REG_BITS_ENUM(ARBITRATION_DISABLE_USB2, DISABLE))); + + /* Validate that the GPIO controller has clock enabled. */ + AMS_ABORT_UNLESS(reg::HasValue(CLK_RST + CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_REG_BITS_ENUM(CLK_OUT_ENB_L_CLK_ENB_GPIO, ENABLE))); + + /* Validate that both FUSE and KFUSE have clock enabled. */ + AMS_ABORT_UNLESS(reg::HasValue(CLK_RST + CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_RST_REG_BITS_ENUM(CLK_OUT_ENB_H_CLK_ENB_FUSE, ENABLE), + CLK_RST_REG_BITS_ENUM(CLK_OUT_ENB_H_CLK_ENB_KFUSE, ENABLE))); + + /* Validate that all of IRAM has clock enabled. */ + AMS_ABORT_UNLESS(reg::HasValue(CLK_RST + CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_REG_BITS_ENUM(CLK_OUT_ENB_U_CLK_ENB_IRAMA, ENABLE), + CLK_RST_REG_BITS_ENUM(CLK_OUT_ENB_U_CLK_ENB_IRAMB, ENABLE), + CLK_RST_REG_BITS_ENUM(CLK_OUT_ENB_U_CLK_ENB_IRAMC, ENABLE), + CLK_RST_REG_BITS_ENUM(CLK_OUT_ENB_U_CLK_ENB_IRAMD, ENABLE))); + + /* Validate that ACTMON has clock enabled. */ + AMS_ABORT_UNLESS(reg::HasValue(CLK_RST + CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_REG_BITS_ENUM(CLK_OUT_ENB_V_CLK_ENB_ACTMON, ENABLE))); + + /* Validate that ENTROPY has clock enabled. */ + AMS_ABORT_UNLESS(reg::HasValue(CLK_RST + CLK_RST_CONTROLLER_CLK_OUT_ENB_W, CLK_RST_REG_BITS_ENUM(CLK_OUT_ENB_W_CLK_ENB_ENTROPY, ENABLE))); } void GenerateCryptographicallyRandomBytes(void * const dst, int size) { diff --git a/libraries/libexosphere/include/exosphere/tegra/tegra_ahb_arbc.hpp b/libraries/libexosphere/include/exosphere/tegra/tegra_ahb_arbc.hpp index 74bf76ee6..d8a5d4321 100644 --- a/libraries/libexosphere/include/exosphere/tegra/tegra_ahb_arbc.hpp +++ b/libraries/libexosphere/include/exosphere/tegra/tegra_ahb_arbc.hpp @@ -35,4 +35,7 @@ #define DEFINE_AHB_REG_THREE_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN) REG_DEFINE_NAMED_THREE_BIT_ENUM(AHB_, NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN) #define DEFINE_AHB_REG_FOUR_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN) REG_DEFINE_NAMED_FOUR_BIT_ENUM (AHB_, NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN) -DEFINE_AHB_REG_BIT_ENUM(ARBITRATION_DISABLE_COP, 1, ENABLE, DISABLE); +DEFINE_AHB_REG_BIT_ENUM(ARBITRATION_DISABLE_COP, 1, ENABLE, DISABLE); +DEFINE_AHB_REG_BIT_ENUM(ARBITRATION_DISABLE_AHBDMA, 5, ENABLE, DISABLE); +DEFINE_AHB_REG_BIT_ENUM(ARBITRATION_DISABLE_USB, 6, ENABLE, DISABLE); +DEFINE_AHB_REG_BIT_ENUM(ARBITRATION_DISABLE_USB2, 18, ENABLE, DISABLE); diff --git a/libraries/libexosphere/include/exosphere/tegra/tegra_clkrst.hpp b/libraries/libexosphere/include/exosphere/tegra/tegra_clkrst.hpp index 649ed3f04..ae22a0f70 100644 --- a/libraries/libexosphere/include/exosphere/tegra/tegra_clkrst.hpp +++ b/libraries/libexosphere/include/exosphere/tegra/tegra_clkrst.hpp @@ -198,10 +198,15 @@ DEFINE_CLK_RST_REG_BIT_ENUM(RST_CPUG_CMPLX_CLR_CLR_NONCPURESET, 29, DISABLE, ENA HANDLER(L, RTC, 0, 4) \ HANDLER(L, TMR, 0, 5) \ HANDLER(L, GPIO, 0, 8) \ + HANDLER(L, USBD, 0, 22) \ HANDLER(L, CACHE2, 0, 31) \ HANDLER(H, MEM, 1, 0) \ + HANDLER(H, AHBDMA, 1, 1) \ + HANDLER(H, APBDMA, 1, 2) \ + HANDLER(H, USB2, 1, 26) \ HANDLER(H, PMC, 1, 6) \ HANDLER(H, FUSE, 1, 7) \ + HANDLER(H, KFUSE, 1, 8) \ HANDLER(H, I2C5, 1, 15) \ HANDLER(H, EMC, 1, 25) \ HANDLER(U, CSITE, 2, 9) \ @@ -213,6 +218,7 @@ DEFINE_CLK_RST_REG_BIT_ENUM(RST_CPUG_CMPLX_CLR_CLR_NONCPURESET, 29, DISABLE, ENA HANDLER(V, CPUG, 3, 0) \ HANDLER(V, MSELECT, 3, 3) \ HANDLER(V, SPDIF_DOUBLER, 3, 22) \ + HANDLER(V, ACTMON, 3, 23) \ HANDLER(V, TZRAM, 3, 30) \ HANDLER(V, SE, 3, 31) \ HANDLER(W, PCIERX0, 4, 2) \ @@ -239,10 +245,12 @@ DEFINE_CLK_RST_REG_BIT_ENUM(RST_CPUG_CMPLX_CLR_CLR_NONCPURESET, 29, DISABLE, ENA #define CLK_RST_DEFINE_SET_CLR_REG(REGISTER, DEVICE, REGISTER_INDEX, DEVICE_INDEX) \ DEFINE_CLK_RST_REG_BIT_ENUM(CLK_ENB_##REGISTER##_SET_SET_CLK_ENB_##DEVICE, DEVICE_INDEX, DISABLE, ENABLE); \ DEFINE_CLK_RST_REG_BIT_ENUM(CLK_ENB_##REGISTER##_CLR_CLR_CLK_ENB_##DEVICE, DEVICE_INDEX, DISABLE, ENABLE); \ + DEFINE_CLK_RST_REG_BIT_ENUM(CLK_OUT_ENB_##REGISTER##_CLK_ENB_##DEVICE, DEVICE_INDEX, DISABLE, ENABLE); \ DEFINE_CLK_RST_REG_BIT_ENUM(CLK_ENB_##REGISTER##_CLK_ENB_##DEVICE, DEVICE_INDEX, DISABLE, ENABLE); \ DEFINE_CLK_RST_REG_BIT_ENUM(RST_DEV_##REGISTER##_SET_SET_##DEVICE##_RST, DEVICE_INDEX, DISABLE, ENABLE); \ DEFINE_CLK_RST_REG_BIT_ENUM(RST_DEV_##REGISTER##_CLR_CLR_##DEVICE##_RST, DEVICE_INDEX, DISABLE, ENABLE); \ - DEFINE_CLK_RST_REG_BIT_ENUM(RST_DEV_##REGISTER##_##DEVICE##_RST, DEVICE_INDEX, DISABLE, ENABLE); + DEFINE_CLK_RST_REG_BIT_ENUM(RST_DEV_##REGISTER##_##DEVICE##_RST, DEVICE_INDEX, DISABLE, ENABLE); \ + DEFINE_CLK_RST_REG_BIT_ENUM(RST_DEVICES_##REGISTER##_SWR_##DEVICE##_RST, DEVICE_INDEX, DISABLE, ENABLE); CLK_RST_FOREACH_DEVICE(CLK_RST_DEFINE_SET_CLR_REG)