fix(core): remove rcc module from non-secure kernel
What changed, and why it matters
This commit removes low-level clock-control code from the non-secure part of Trezor's STM32U5 firmware and replaces it with small, safe stubs. The stated reason is that the full clock-control peripheral (RCC) is not safely accessible when the kernel runs in non-secure mode, so using the vendor's standard routines there could cause problems. The change is defensive hardening rather than a clear, exploitable bug fix.
Treat as a hardening improvement. Review whether any remaining non-secure code still calls RCC registers directly, and verify that SystemCoreClock is reliably initialized before the non-secure kernel uses these stubs. No urgent user action is indicated by the diff alone.
Security signals we found
TrustZone/secure-monitor privilege boundary involved
Removal of peripheral access from less-privileged execution mode
Replacement of vendor HAL with constrained, mode-aware stubs
Defensive comment notes RCC is 'not fully accessible' in non-secure mode
Evidence from the diff
The patch drops stm32u5xx_hal_rcc.c and stm32u5xx_hal_rcc_ex.c from the non-secure build and adds minimal replacements in startup_init.c: HAL_RCC_GetHCLKFreq, HAL_RCC_GetSysClockFreq, and HAL_RCCEx_GetPeriphCLKFreq (limited to USART3). These stubs return SystemCoreClock, which is initialized by the secure monitor. The full RCC HAL sources are now only compiled when the ‘secure_mode’ feature is requested. The commit message frames this as removing unsafe RCC access from the non-secure kernel.
Changed components
core/embed/sys/startup/stm32u5/startup_init.ccore/site_scons/models/stm32u5_common.pySTM32U5 HAL RCC drivers (non-secure build exclusion)Inspect captured patch +28 / −2
diff --git a/core/embed/sys/startup/stm32u5/startup_init.c b/core/embed/sys/startup/stm32u5/startup_init.c
index 6e94a2c93..6f1030bae 100644
--- a/core/embed/sys/startup/stm32u5/startup_init.c
+++ b/core/embed/sys/startup/stm32u5/startup_init.c
@@ -69,6 +69,28 @@ uint32_t SystemCoreClock = DEFAULT_FREQ * 1000000U;
#pragma GCC optimize( \
"no-stack-protector") // applies to all functions in this file
+#ifndef SECURE_MODE
+
+// The following functions replace ST HAL routines from
+// stm32u5xx_hal_rcc.c and stm32u5xx_hal_rcc_ex.c that are not safe to call in
+// non-secure mode (e.g. the kernel running in non-secure mode),
+// because the RCC peripheral is not fully accessible.
+
+// Clocks are fully configured by secure monitor and the kernel can
+// rely on SystemCoreClock variable being set correctly.
+
+uint32_t HAL_RCC_GetHCLKFreq(void) { return SystemCoreClock; }
+
+uint32_t HAL_RCC_GetSysClockFreq(void) { return SystemCoreClock; }
+
+uint32_t HAL_RCCEx_GetPeriphCLKFreq(uint64_t PeriphClk) {
+ ensure(sectrue * (PeriphClk == RCC_PERIPHCLK_USART3),
+ "Only USART3 supported");
+ return SystemCoreClock;
+}
+
+#endif // SECURE_MODE
+
// This function replaces calls to universal, but flash-wasting
// function HAL_RCC_OscConfig.
//
diff --git a/core/site_scons/models/stm32u5_common.py b/core/site_scons/models/stm32u5_common.py
index e5ba1da0d..d54a3965d 100644
--- a/core/site_scons/models/stm32u5_common.py
+++ b/core/site_scons/models/stm32u5_common.py
@@ -70,8 +70,6 @@ def stm32u5_common_files(env, features_wanted, defines, sources, paths):
"vendor/stm32u5xx_hal_driver/Src/stm32u5xx_hal_pwr.c",
"vendor/stm32u5xx_hal_driver/Src/stm32u5xx_hal_pwr_ex.c",
"vendor/stm32u5xx_hal_driver/Src/stm32u5xx_hal_ramcfg.c",
- "vendor/stm32u5xx_hal_driver/Src/stm32u5xx_hal_rcc.c",
- "vendor/stm32u5xx_hal_driver/Src/stm32u5xx_hal_rcc_ex.c",
"vendor/stm32u5xx_hal_driver/Src/stm32u5xx_hal_rtc.c",
"vendor/stm32u5xx_hal_driver/Src/stm32u5xx_hal_rtc_ex.c",
"vendor/stm32u5xx_hal_driver/Src/stm32u5xx_hal_spi.c",
@@ -81,6 +79,12 @@ def stm32u5_common_files(env, features_wanted, defines, sources, paths):
"vendor/stm32u5xx_hal_driver/Src/stm32u5xx_ll_fmc.c",
]
+ if "secure_mode" in features_wanted:
+ sources += [
+ "vendor/stm32u5xx_hal_driver/Src/stm32u5xx_hal_rcc.c",
+ "vendor/stm32u5xx_hal_driver/Src/stm32u5xx_hal_rcc_ex.c",
+ ]
+
sources += [
"embed/sec/hash_processor/stm32u5/hash_processor.c",
"embed/sec/monoctr/stm32u5/monoctr.c",
Why this scored 42/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.