refactor(core): move tamper driver from sys to sec
What changed, and why it matters
This commit is a pure code reorganization: it moves the tamper-detection driver files from one directory (sys) to another (sec) and updates all include paths accordingly. The actual tamper-detection logic is unchanged, so this does not fix or introduce a security vulnerability on its own.
No security action required; treat as routine refactoring. If assessing overall tamper-protection posture, review the moved driver's logic separately in its current state, but this commit itself does not alter that logic.
Security signals we found
Tamper-detection code is touched, but only via path/include relocation
No changes to tamper register configuration, interrupt handler, or secret-erasure logic
No changelog entry and commit title explicitly labels this as a refactor
Evidence from the diff
The change relocates the STM32U5 tamper driver from core/embed/sys/tamper to core/embed/sec/tamper, renames the include path from
Changed components
core/embed/projects/boardloader/main.ccore/embed/projects/bootloader/main.ccore/embed/projects/kernel/main.ccore/embed/projects/prodtest/cmd/prodtest_tamper.ccore/embed/projects/prodtest/main.ccore/embed/projects/secmon/main.ccore/embed/sec/tamper/inc/sec/tamper.hcore/embed/sec/tamper/stm32u5/tamper.ccore/site_scons/models/stm32u5_common.pyInspect captured patch +327 / −327
diff --git a/core/embed/projects/boardloader/main.c b/core/embed/projects/boardloader/main.c
index 7292558e..c0e34f7c 100644
--- a/core/embed/projects/boardloader/main.c
+++ b/core/embed/projects/boardloader/main.c
@@ -52,7 +52,7 @@
#endif
#ifdef USE_TAMPER
-#include <sys/tamper.h>
+#include <sec/tamper.h>
#endif
#include "bld_version.h"
diff --git a/core/embed/projects/bootloader/main.c b/core/embed/projects/bootloader/main.c
index 90f97827..91d681bc 100644
--- a/core/embed/projects/bootloader/main.c
+++ b/core/embed/projects/bootloader/main.c
@@ -66,7 +66,7 @@
#include <sys/rtc.h>
#endif
#ifdef USE_TAMPER
-#include <sys/tamper.h>
+#include <sec/tamper.h>
#endif
#ifdef USE_BLE
#include <io/ble.h>
diff --git a/core/embed/projects/kernel/main.c b/core/embed/projects/kernel/main.c
index d219ba81..71b35c2c 100644
--- a/core/embed/projects/kernel/main.c
+++ b/core/embed/projects/kernel/main.c
@@ -91,7 +91,7 @@
#endif
#ifdef USE_TAMPER
-#include <sys/tamper.h>
+#include <sec/tamper.h>
#endif
#ifdef USE_TOUCH
diff --git a/core/embed/projects/prodtest/cmd/prodtest_tamper.c b/core/embed/projects/prodtest/cmd/prodtest_tamper.c
index 08a831ae..107e8bae 100644
--- a/core/embed/projects/prodtest/cmd/prodtest_tamper.c
+++ b/core/embed/projects/prodtest/cmd/prodtest_tamper.c
@@ -22,7 +22,7 @@
#include <trezor_rtl.h>
#include <rtl/cli.h>
-#include <sys/tamper.h>
+#include <sec/tamper.h>
static void prodtest_tamper_read(cli_t* cli) {
if (cli_arg_count(cli) > 0) {
diff --git a/core/embed/projects/prodtest/main.c b/core/embed/projects/prodtest/main.c
index 32031be5..438c8251 100644
--- a/core/embed/projects/prodtest/main.c
+++ b/core/embed/projects/prodtest/main.c
@@ -106,7 +106,7 @@
#endif
#ifdef USE_TAMPER
-#include <sys/tamper.h>
+#include <sec/tamper.h>
#endif
#ifdef TREZOR_MODEL_T2T1
diff --git a/core/embed/projects/secmon/main.c b/core/embed/projects/secmon/main.c
index b74df15d..ed53951e 100644
--- a/core/embed/projects/secmon/main.c
+++ b/core/embed/projects/secmon/main.c
@@ -41,7 +41,7 @@
#endif
#ifdef USE_TAMPER
-#include <sys/tamper.h>
+#include <sec/tamper.h>
#endif
#ifdef USE_TROPIC
diff --git a/core/embed/sec/tamper/inc/sec/tamper.h b/core/embed/sec/tamper/inc/sec/tamper.h
new file mode 100644
index 00000000..79d20a04
--- /dev/null
+++ b/core/embed/sec/tamper/inc/sec/tamper.h
@@ -0,0 +1,41 @@
+/*
+ * This file is part of the Trezor project, https://trezor.io/
+ *
+ * Copyright (c) SatoshiLabs
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <trezor_types.h>
+
+#ifdef SECURE_MODE
+
+// Tamper module enables the internal tamper detection on STM32 microcontroller
+// as well as external tamper input if it's available on the device
+
+// Initializes the tamper detection
+bool tamper_init(void);
+
+// Get status of external tamper inputs
+uint8_t tamper_external_read(void);
+
+// Enable external tamper inputs
+void tamper_external_enable(void);
+
+// Disable external tamper inputs
+void tamper_external_disable(void);
+
+#endif // SECURE_MODE
diff --git a/core/embed/sec/tamper/stm32u5/tamper.c b/core/embed/sec/tamper/stm32u5/tamper.c
new file mode 100644
index 00000000..7f35d815
--- /dev/null
+++ b/core/embed/sec/tamper/stm32u5/tamper.c
@@ -0,0 +1,278 @@
+/*
+ * This file is part of the Trezor project, https://trezor.io/
+ *
+ * Copyright (c) SatoshiLabs
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef SECURE_MODE
+
+#include <trezor_bsp.h>
+#include <trezor_rtl.h>
+
+#include <sec/tamper.h>
+#include <sys/bootutils.h>
+#include <sys/irq.h>
+#include <sys/mpu.h>
+#include <sys/systick.h>
+#include <util/rsod.h>
+
+// Fixes a typo in CMSIS Device library for STM32U5
+#undef TAMP_CR3_ITAMP7NOER_Msk
+#undef TAMP_CR3_ITAMP7NOER
+#define TAMP_CR3_ITAMP7NOER_Msk (0x1UL << TAMP_CR3_ITAMP7NOER_Pos)
+#define TAMP_CR3_ITAMP7NOER TAMP_CR3_ITAMP7NOER_Msk
+
+// This function replaces calls to universal, but flash-wasting
+// functions HAL_RCC_OscConfig and HAL_RCCEx_PeriphCLKConfig.
+//
+// This is the configuration before the optimization:
+// clk_init_def.PeriphClockSelection = RCC_PERIPHCLK_RTC;
+// clk_init_def.RTCClockSelection = RCC_RTCCLKSOURCE_LSI (or
+// RCC_RTCCLKSOURCE_LSE); HAL_RCCEx_PeriphCLKConfig(&clk_init_def);
+static HAL_StatusTypeDef clk_init(uint32_t source) {
+ bool pwrclkchanged = false;
+
+ // Enable Power Clock
+ if (__HAL_RCC_PWR_IS_CLK_DISABLED()) {
+ __HAL_RCC_PWR_CLK_ENABLE();
+ pwrclkchanged = true;
+ }
+ // Enable write access to Backup domain
+ SET_BIT(PWR->DBPR, PWR_DBPR_DBP);
+
+ // Wait for Backup domain Write protection disable
+ uint32_t deadline = ticks_timeout(RCC_DBP_TIMEOUT_VALUE);
+
+ while (HAL_IS_BIT_CLR(PWR->DBPR, PWR_DBPR_DBP)) {
+ if (ticks_expired(deadline)) {
+ return HAL_TIMEOUT;
+ }
+ }
+ // Reset the Backup domain only if the RTC Clock source selection is modified
+ // from default
+ uint32_t bdcr_temp = READ_BIT(RCC->BDCR, RCC_BDCR_RTCSEL);
+
+ if ((bdcr_temp != RCC_RTCCLKSOURCE_NO_CLK) && (bdcr_temp != source)) {
+ // Store the content of BDCR register before the reset of Backup Domain
+ bdcr_temp = READ_BIT(RCC->BDCR, ~(RCC_BDCR_RTCSEL));
+ // RTC Clock selection can be changed only if the Backup Domain is reset
+ __HAL_RCC_BACKUPRESET_FORCE();
+ __HAL_RCC_BACKUPRESET_RELEASE();
+ // Restore the Content of BDCR register
+ RCC->BDCR = bdcr_temp;
+ }
+
+ // Wait for LSE reactivation if LSE was enabled prior to Backup Domain reset
+ if (HAL_IS_BIT_SET(bdcr_temp, RCC_BDCR_LSEON)) {
+ deadline = ticks_timeout(RCC_LSE_TIMEOUT_VALUE);
+
+ // Wait till LSE is ready
+ while (READ_BIT(RCC->BDCR, RCC_BDCR_LSERDY) == 0U) {
+ if (ticks_expired(deadline)) {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ // Apply new RTC clock source selection
+ __HAL_RCC_RTC_CONFIG(source);
+
+ // Restore clock configuration if changed
+ if (pwrclkchanged) {
+ __HAL_RCC_PWR_CLK_DISABLE();
+ }
+ return HAL_OK;
+}
+
+bool tamper_init(void) {
+#ifdef USE_LSE
+ HAL_StatusTypeDef res = clk_init(RCC_RTCCLKSOURCE_LSE);
+#else
+ HAL_StatusTypeDef res = clk_init(RCC_RTCCLKSOURCE_LSI);
+#endif
+
+ if (res != HAL_OK) {
+ return false;
+ }
+
+ // Enable RTC peripheral (tampers are part of it)
+ __HAL_RCC_RTC_ENABLE();
+ __HAL_RCC_RTCAPB_CLK_ENABLE();
+
+ // Clear all pending interrupts
+ // They may be some as RTC/TAMP peripherals reside inside the
+ // backup voltage domain
+ TAMP->SCR = TAMP_SCR_CTAMP2F | TAMP_SCR_CITAMP1F | TAMP_SCR_CITAMP2F |
+ TAMP_SCR_CITAMP3F | TAMP_SCR_CITAMP5F | TAMP_SCR_CITAMP6F |
+ TAMP_SCR_CITAMP7F | TAMP_SCR_CITAMP8F | TAMP_SCR_CITAMP9F |
+ TAMP_SCR_CITAMP11F | TAMP_SCR_CITAMP12F | TAMP_SCR_CITAMP13F;
+
+ NVIC_ClearPendingIRQ(TAMP_IRQn);
+
+ // Enable battery and power monitoring (!@# rework it)
+ RCC->AHB3ENR |= RCC_AHB3ENR_PWREN;
+ // HAL_PWR_EnableBkUpAccess();
+ PWR->BDCR1 |= PWR_BDCR1_MONEN;
+ // HAL_PWR_DisableBkUpAccess();
+
+ // // Set external tamper input filter
+ TAMP->FLTCR =
+ // TAMP_FLTCR_TAMPPUDIS | // disable pre-charge of TAMP_INx pins
+ (3 << TAMP_FLTCR_TAMPPRCH_Pos) | // pre-charge 8 RTCCLK cycles
+ (2 << TAMP_FLTCR_TAMPFLT_Pos) | // activated after 4 same samples
+ (7 << TAMP_FLTCR_TAMPFREQ_Pos); // sampling period RTCCLK / 256 (128Hz)
+
+ // Enable all internal tampers (4th and 10th are intentionally skipped)
+ // We select all of them despite some of them are never triggered
+ TAMP->CR1 |=
+ (TAMP_CR1_ITAMP1E | // backup domain voltage monitoring
+ TAMP_CR1_ITAMP2E | // temperature monitoring
+ TAMP_CR1_ITAMP3E | // LSE monitoring (LSECSS)
+ TAMP_CR1_ITAMP5E | // RTC calendar overflow
+ TAMP_CR1_ITAMP6E | // JTAG/SWD access when RDP > 0
+ TAMP_CR1_ITAMP7E | // ADC4 analog watchdog monitoring 1
+ TAMP_CR1_ITAMP8E | // Monotonic counter 1 overflow
+ TAMP_CR1_ITAMP9E | // Crypto peripherals fault (SAES, AES, PKA, TRNG)
+ TAMP_CR1_ITAMP11E | // IWDG reset when tamper flag is set
+ TAMP_CR1_ITAMP12E | // ADC4 analog watchdog monitoring 2
+ TAMP_CR1_ITAMP13E); // ADC4 analog watchdog monitoring 3
+
+ // Switch all tampers to the "confirmed" mode
+ // => all secrets all deleted when any tamper event is triggered
+ TAMP->CR3 = 0;
+
+#ifdef TAMPER_INPUT_2
+ // TAMP_IN2 level high
+ TAMP->CR2 |= TAMP_CR2_TAMP2TRG;
+#endif
+
+ // Enable all interrupts for all internal tampers
+ TAMP->IER = TAMP_IER_TAMP2IE | TAMP_IER_ITAMP1IE | TAMP_IER_ITAMP2IE |
+ TAMP_IER_ITAMP3IE | TAMP_IER_ITAMP5IE | TAMP_IER_ITAMP6IE |
+ TAMP_IER_ITAMP7IE | TAMP_IER_ITAMP8IE | TAMP_IER_ITAMP9IE |
+ TAMP_IER_ITAMP11IE | TAMP_IER_ITAMP12IE | TAMP_IER_ITAMP13IE;
+
+ // Enable TAMP interrupt at NVIC controller
+ NVIC_SetPriority(TAMP_IRQn, IRQ_PRI_HIGHEST);
+ NVIC_EnableIRQ(TAMP_IRQn);
+
+ return true;
+}
+
+uint8_t tamper_external_read(void) {
+ uint8_t val = 0;
+
+#ifdef TAMPER_INPUT_2
+ GPIO_InitTypeDef gpio = {0};
+ gpio.Mode = GPIO_MODE_INPUT;
+ gpio.Pull = GPIO_PULLUP;
+ gpio.Pin = GPIO_PIN_0;
+ gpio.Speed = GPIO_SPEED_LOW;
+ HAL_GPIO_Init(GPIOA, &gpio);
+
+ systick_delay_us(1);
+
+ val |= GPIO_PIN_SET == HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) ? 2 : 0;
+
+ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_0);
+#endif
+
+ return val;
+}
+
+void tamper_external_enable(void) {
+ // Enable external tampers
+#ifdef TAMPER_INPUT_2
+ TAMP->CR1 |= TAMP_CR1_TAMP2E;
+#endif
+}
+
+void tamper_external_disable(void) {
+#ifdef TAMPER_INPUT_2
+ TAMP->CR1 &= ~TAMP_CR1_TAMP2E;
+#endif
+}
+
+void tamper_build_pminfo(systask_postmortem_t* pminfo, uint32_t tamper_sr) {
+ const char* title = "TAMPER";
+
+ memset(pminfo, 0, sizeof(*pminfo));
+ pminfo->reason = TASK_TERM_REASON_ERROR;
+ memcpy(pminfo->error.title, title, strlen(title));
+
+#ifndef BOARDLOADER
+
+ const char* reason = "UNKNOWN";
+ if (tamper_sr & TAMP_SR_TAMP1F) {
+ reason = "INPUT1";
+ } else if (tamper_sr & TAMP_SR_TAMP2F) {
+ reason = "INPUT2";
+ } else if (tamper_sr & TAMP_SR_ITAMP1F) {
+ reason = "VOLTAGE";
+ } else if (tamper_sr & TAMP_SR_ITAMP2F) {
+ reason = "TEMPERATURE";
+ } else if (tamper_sr & TAMP_SR_ITAMP3F) {
+ reason = "LSE CLOCK";
+ } else if (tamper_sr & TAMP_SR_ITAMP5F) {
+ reason = "RTC OVERFLOW";
+ } else if (tamper_sr & TAMP_SR_ITAMP6F) {
+ reason = "SWD ACCESS";
+ } else if (tamper_sr & TAMP_SR_ITAMP7F) {
+ reason = "ANALOG WDG1";
+ } else if (tamper_sr & TAMP_SR_ITAMP8F) {
+ reason = "MONO COUNTER";
+ } else if (tamper_sr & TAMP_SR_ITAMP9F) {
+ reason = "CRYPTO ERROR";
+ } else if (tamper_sr & TAMP_SR_ITAMP11F) {
+ reason = "IWDG";
+ } else if (tamper_sr & TAMP_SR_ITAMP12F) {
+ reason = "ANALOG WDG2";
+ } else if (tamper_sr & TAMP_SR_ITAMP13F) {
+ reason = "ANALOG WDG3";
+ }
+ memcpy(pminfo->error.message, reason, strlen(reason));
+#endif
+}
+
+// Interrupt handle for all tamper events
+// It displays an error message
+void TAMP_IRQHandler(void) {
+ // tamper erases part of RAM so we need to reconfigure whatever is to be used,
+ // such as re-initialize MPU as it is used in reboot_with_rsod
+ mpu_init();
+
+ mpu_reconfig(MPU_MODE_DEFAULT);
+
+ // Disable external tamper, as its level detected
+ // and it would trigger again. We don't need it until reset.
+#ifdef TAMPER_INPUT_2
+ TAMP->CR1 &= ~TAMP_CR1_TAMP2E;
+#endif
+
+ uint32_t tamper_sr = TAMP->SR;
+ TAMP->SCR = tamper_sr;
+
+ systask_postmortem_t pminfo;
+ tamper_build_pminfo(&pminfo, tamper_sr);
+
+#if defined(USE_BOOTARGS_RSOD) && !defined(BOARDLOADER)
+ reboot_with_rsod(&pminfo);
+#else
+ rsod_panic_handler(&pminfo);
+#endif
+}
+
+#endif // SECURE_MODE
diff --git a/core/embed/sys/tamper/inc/sys/tamper.h b/core/embed/sys/tamper/inc/sys/tamper.h
deleted file mode 100644
index 79d20a04..00000000
--- a/core/embed/sys/tamper/inc/sys/tamper.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * This file is part of the Trezor project, https://trezor.io/
- *
- * Copyright (c) SatoshiLabs
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#pragma once
-
-#include <trezor_types.h>
-
-#ifdef SECURE_MODE
-
-// Tamper module enables the internal tamper detection on STM32 microcontroller
-// as well as external tamper input if it's available on the device
-
-// Initializes the tamper detection
-bool tamper_init(void);
-
-// Get status of external tamper inputs
-uint8_t tamper_external_read(void);
-
-// Enable external tamper inputs
-void tamper_external_enable(void);
-
-// Disable external tamper inputs
-void tamper_external_disable(void);
-
-#endif // SECURE_MODE
diff --git a/core/embed/sys/tamper/stm32u5/tamper.c b/core/embed/sys/tamper/stm32u5/tamper.c
deleted file mode 100644
index 35753752..00000000
--- a/core/embed/sys/tamper/stm32u5/tamper.c
+++ /dev/null
@@ -1,278 +0,0 @@
-/*
- * This file is part of the Trezor project, https://trezor.io/
- *
- * Copyright (c) SatoshiLabs
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <trezor_bsp.h>
-#include <trezor_rtl.h>
-
-#include <sys/bootutils.h>
-#include <sys/irq.h>
-#include <sys/mpu.h>
-#include <sys/systick.h>
-#include <sys/tamper.h>
-#include <util/rsod.h>
-
-#ifdef SECURE_MODE
-
-// Fixes a typo in CMSIS Device library for STM32U5
-#undef TAMP_CR3_ITAMP7NOER_Msk
-#undef TAMP_CR3_ITAMP7NOER
-#define TAMP_CR3_ITAMP7NOER_Msk (0x1UL << TAMP_CR3_ITAMP7NOER_Pos)
-#define TAMP_CR3_ITAMP7NOER TAMP_CR3_ITAMP7NOER_Msk
-
-// This function replaces calls to universal, but flash-wasting
-// functions HAL_RCC_OscConfig and HAL_RCCEx_PeriphCLKConfig.
-//
-// This is the configuration before the optimization:
-// clk_init_def.PeriphClockSelection = RCC_PERIPHCLK_RTC;
-// clk_init_def.RTCClockSelection = RCC_RTCCLKSOURCE_LSI (or
-// RCC_RTCCLKSOURCE_LSE); HAL_RCCEx_PeriphCLKConfig(&clk_init_def);
-static HAL_StatusTypeDef clk_init(uint32_t source) {
- bool pwrclkchanged = false;
-
- // Enable Power Clock
- if (__HAL_RCC_PWR_IS_CLK_DISABLED()) {
- __HAL_RCC_PWR_CLK_ENABLE();
- pwrclkchanged = true;
- }
- // Enable write access to Backup domain
- SET_BIT(PWR->DBPR, PWR_DBPR_DBP);
-
- // Wait for Backup domain Write protection disable
- uint32_t deadline = ticks_timeout(RCC_DBP_TIMEOUT_VALUE);
-
- while (HAL_IS_BIT_CLR(PWR->DBPR, PWR_DBPR_DBP)) {
- if (ticks_expired(deadline)) {
- return HAL_TIMEOUT;
- }
- }
- // Reset the Backup domain only if the RTC Clock source selection is modified
- // from default
- uint32_t bdcr_temp = READ_BIT(RCC->BDCR, RCC_BDCR_RTCSEL);
-
- if ((bdcr_temp != RCC_RTCCLKSOURCE_NO_CLK) && (bdcr_temp != source)) {
- // Store the content of BDCR register before the reset of Backup Domain
- bdcr_temp = READ_BIT(RCC->BDCR, ~(RCC_BDCR_RTCSEL));
- // RTC Clock selection can be changed only if the Backup Domain is reset
- __HAL_RCC_BACKUPRESET_FORCE();
- __HAL_RCC_BACKUPRESET_RELEASE();
- // Restore the Content of BDCR register
- RCC->BDCR = bdcr_temp;
- }
-
- // Wait for LSE reactivation if LSE was enabled prior to Backup Domain reset
- if (HAL_IS_BIT_SET(bdcr_temp, RCC_BDCR_LSEON)) {
- deadline = ticks_timeout(RCC_LSE_TIMEOUT_VALUE);
-
- // Wait till LSE is ready
- while (READ_BIT(RCC->BDCR, RCC_BDCR_LSERDY) == 0U) {
- if (ticks_expired(deadline)) {
- return HAL_TIMEOUT;
- }
- }
- }
-
- // Apply new RTC clock source selection
- __HAL_RCC_RTC_CONFIG(source);
-
- // Restore clock configuration if changed
- if (pwrclkchanged) {
- __HAL_RCC_PWR_CLK_DISABLE();
- }
- return HAL_OK;
-}
-
-bool tamper_init(void) {
-#ifdef USE_LSE
- HAL_StatusTypeDef res = clk_init(RCC_RTCCLKSOURCE_LSE);
-#else
- HAL_StatusTypeDef res = clk_init(RCC_RTCCLKSOURCE_LSI);
-#endif
-
- if (res != HAL_OK) {
- return false;
- }
-
- // Enable RTC peripheral (tampers are part of it)
- __HAL_RCC_RTC_ENABLE();
- __HAL_RCC_RTCAPB_CLK_ENABLE();
-
- // Clear all pending interrupts
- // They may be some as RTC/TAMP peripherals reside inside the
- // backup voltage domain
- TAMP->SCR = TAMP_SCR_CTAMP2F | TAMP_SCR_CITAMP1F | TAMP_SCR_CITAMP2F |
- TAMP_SCR_CITAMP3F | TAMP_SCR_CITAMP5F | TAMP_SCR_CITAMP6F |
- TAMP_SCR_CITAMP7F | TAMP_SCR_CITAMP8F | TAMP_SCR_CITAMP9F |
- TAMP_SCR_CITAMP11F | TAMP_SCR_CITAMP12F | TAMP_SCR_CITAMP13F;
-
- NVIC_ClearPendingIRQ(TAMP_IRQn);
-
- // Enable battery and power monitoring (!@# rework it)
- RCC->AHB3ENR |= RCC_AHB3ENR_PWREN;
- // HAL_PWR_EnableBkUpAccess();
- PWR->BDCR1 |= PWR_BDCR1_MONEN;
- // HAL_PWR_DisableBkUpAccess();
-
- // // Set external tamper input filter
- TAMP->FLTCR =
- // TAMP_FLTCR_TAMPPUDIS | // disable pre-charge of TAMP_INx pins
- (3 << TAMP_FLTCR_TAMPPRCH_Pos) | // pre-charge 8 RTCCLK cycles
- (2 << TAMP_FLTCR_TAMPFLT_Pos) | // activated after 4 same samples
- (7 << TAMP_FLTCR_TAMPFREQ_Pos); // sampling period RTCCLK / 256 (128Hz)
-
- // Enable all internal tampers (4th and 10th are intentionally skipped)
- // We select all of them despite some of them are never triggered
- TAMP->CR1 |=
- (TAMP_CR1_ITAMP1E | // backup domain voltage monitoring
- TAMP_CR1_ITAMP2E | // temperature monitoring
- TAMP_CR1_ITAMP3E | // LSE monitoring (LSECSS)
- TAMP_CR1_ITAMP5E | // RTC calendar overflow
- TAMP_CR1_ITAMP6E | // JTAG/SWD access when RDP > 0
- TAMP_CR1_ITAMP7E | // ADC4 analog watchdog monitoring 1
- TAMP_CR1_ITAMP8E | // Monotonic counter 1 overflow
- TAMP_CR1_ITAMP9E | // Crypto peripherals fault (SAES, AES, PKA, TRNG)
- TAMP_CR1_ITAMP11E | // IWDG reset when tamper flag is set
- TAMP_CR1_ITAMP12E | // ADC4 analog watchdog monitoring 2
- TAMP_CR1_ITAMP13E); // ADC4 analog watchdog monitoring 3
-
- // Switch all tampers to the "confirmed" mode
- // => all secrets all deleted when any tamper event is triggered
- TAMP->CR3 = 0;
-
-#ifdef TAMPER_INPUT_2
- // TAMP_IN2 level high
- TAMP->CR2 |= TAMP_CR2_TAMP2TRG;
-#endif
-
- // Enable all interrupts for all internal tampers
- TAMP->IER = TAMP_IER_TAMP2IE | TAMP_IER_ITAMP1IE | TAMP_IER_ITAMP2IE |
- TAMP_IER_ITAMP3IE | TAMP_IER_ITAMP5IE | TAMP_IER_ITAMP6IE |
- TAMP_IER_ITAMP7IE | TAMP_IER_ITAMP8IE | TAMP_IER_ITAMP9IE |
- TAMP_IER_ITAMP11IE | TAMP_IER_ITAMP12IE | TAMP_IER_ITAMP13IE;
-
- // Enable TAMP interrupt at NVIC controller
- NVIC_SetPriority(TAMP_IRQn, IRQ_PRI_HIGHEST);
- NVIC_EnableIRQ(TAMP_IRQn);
-
- return true;
-}
-
-uint8_t tamper_external_read(void) {
- uint8_t val = 0;
-
-#ifdef TAMPER_INPUT_2
- GPIO_InitTypeDef gpio = {0};
- gpio.Mode = GPIO_MODE_INPUT;
- gpio.Pull = GPIO_PULLUP;
- gpio.Pin = GPIO_PIN_0;
- gpio.Speed = GPIO_SPEED_LOW;
- HAL_GPIO_Init(GPIOA, &gpio);
-
- systick_delay_us(1);
-
- val |= GPIO_PIN_SET == HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) ? 2 : 0;
-
- HAL_GPIO_DeInit(GPIOA, GPIO_PIN_0);
-#endif
-
- return val;
-}
-
-void tamper_external_enable(void) {
- // Enable external tampers
-#ifdef TAMPER_INPUT_2
- TAMP->CR1 |= TAMP_CR1_TAMP2E;
-#endif
-}
-
-void tamper_external_disable(void) {
-#ifdef TAMPER_INPUT_2
- TAMP->CR1 &= ~TAMP_CR1_TAMP2E;
-#endif
-}
-
-void tamper_build_pminfo(systask_postmortem_t* pminfo, uint32_t tamper_sr) {
- const char* title = "TAMPER";
-
- memset(pminfo, 0, sizeof(*pminfo));
- pminfo->reason = TASK_TERM_REASON_ERROR;
- memcpy(pminfo->error.title, title, strlen(title));
-
-#ifndef BOARDLOADER
-
- const char* reason = "UNKNOWN";
- if (tamper_sr & TAMP_SR_TAMP1F) {
- reason = "INPUT1";
- } else if (tamper_sr & TAMP_SR_TAMP2F) {
- reason = "INPUT2";
- } else if (tamper_sr & TAMP_SR_ITAMP1F) {
- reason = "VOLTAGE";
- } else if (tamper_sr & TAMP_SR_ITAMP2F) {
- reason = "TEMPERATURE";
- } else if (tamper_sr & TAMP_SR_ITAMP3F) {
- reason = "LSE CLOCK";
- } else if (tamper_sr & TAMP_SR_ITAMP5F) {
- reason = "RTC OVERFLOW";
- } else if (tamper_sr & TAMP_SR_ITAMP6F) {
- reason = "SWD ACCESS";
- } else if (tamper_sr & TAMP_SR_ITAMP7F) {
- reason = "ANALOG WDG1";
- } else if (tamper_sr & TAMP_SR_ITAMP8F) {
- reason = "MONO COUNTER";
- } else if (tamper_sr & TAMP_SR_ITAMP9F) {
- reason = "CRYPTO ERROR";
- } else if (tamper_sr & TAMP_SR_ITAMP11F) {
- reason = "IWDG";
- } else if (tamper_sr & TAMP_SR_ITAMP12F) {
- reason = "ANALOG WDG2";
- } else if (tamper_sr & TAMP_SR_ITAMP13F) {
- reason = "ANALOG WDG3";
- }
- memcpy(pminfo->error.message, reason, strlen(reason));
-#endif
-}
-
-// Interrupt handle for all tamper events
-// It displays an error message
-void TAMP_IRQHandler(void) {
- // tamper erases part of RAM so we need to reconfigure whatever is to be used,
- // such as re-initialize MPU as it is used in reboot_with_rsod
- mpu_init();
-
- mpu_reconfig(MPU_MODE_DEFAULT);
-
- // Disable external tamper, as its level detected
- // and it would trigger again. We don't need it until reset.
-#ifdef TAMPER_INPUT_2
- TAMP->CR1 &= ~TAMP_CR1_TAMP2E;
-#endif
-
- uint32_t tamper_sr = TAMP->SR;
- TAMP->SCR = tamper_sr;
-
- systask_postmortem_t pminfo;
- tamper_build_pminfo(&pminfo, tamper_sr);
-
-#if defined(USE_BOOTARGS_RSOD) && !defined(BOARDLOADER)
- reboot_with_rsod(&pminfo);
-#else
- rsod_panic_handler(&pminfo);
-#endif
-}
-
-#endif // SECURE_MODE
diff --git a/core/site_scons/models/stm32u5_common.py b/core/site_scons/models/stm32u5_common.py
index c8248274..7252879d 100644
--- a/core/site_scons/models/stm32u5_common.py
+++ b/core/site_scons/models/stm32u5_common.py
@@ -17,6 +17,7 @@ def stm32u5_common_files(env, features_wanted, defines, sources, paths):
"embed/sec/rng/inc",
"embed/sec/secret/inc",
"embed/sec/secure_aes/inc",
+ "embed/sec/tamper/inc",
"embed/sec/time_estimate/inc",
"embed/sys/bsp/stm32u5",
"embed/sys/inc",
@@ -28,7 +29,6 @@ def stm32u5_common_files(env, features_wanted, defines, sources, paths):
"embed/sys/stack/inc",
"embed/sys/startup/inc",
"embed/sys/syscall/inc",
- "embed/sys/tamper/inc",
"embed/sys/task/inc",
"embed/sys/time/inc",
"embed/sys/trustzone/inc",
@@ -98,6 +98,7 @@ def stm32u5_common_files(env, features_wanted, defines, sources, paths):
"embed/sec/secure_aes/stm32u5/secure_aes.c",
"embed/sec/secure_aes/stm32u5/secure_aes_unpriv.c",
"embed/sec/storage/stm32u5/storage_salt.c",
+ "embed/sec/tamper/stm32u5/tamper.c",
"embed/sec/time_estimate/stm32/time_estimate.c",
"embed/sys/irq/stm32/irq.c",
"embed/sys/linker/linker_utils.c",
@@ -120,7 +121,6 @@ def stm32u5_common_files(env, features_wanted, defines, sources, paths):
"embed/sys/syscall/stm32/syscall_probe.c",
"embed/sys/syscall/stm32/syscall_stubs.c",
"embed/sys/syscall/stm32/syscall_verifiers.c",
- "embed/sys/tamper/stm32u5/tamper.c",
"embed/sys/task/stm32/systask.c",
"embed/sys/task/stm32/system.c",
"embed/sys/time/stm32/systick.c",
Why this scored 15/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.