feat(core): introduce tamper detection on STM32U5

cepetr/u5/tamper-experiment
cepetr 8 months ago
parent 2b2a0f5646
commit d06e0fd382

@ -87,6 +87,9 @@
#ifdef USE_SECP256K1_ZKP
#include "zkp_context.h"
#endif
#if USE_TAMPERS
#include "tamper.h"
#endif
// from util.s
extern void shutdown_privileged(void);
@ -165,6 +168,10 @@ int main(void) {
touch_init();
#endif
#if USE_TAMPERS
tamper_init();
#endif
#ifdef USE_SD_CARD
sdcard_init();
#endif

@ -160,4 +160,7 @@ static inline void restore_irq_pri(uint32_t state) {
#define IRQ_PRI_PENDSV NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 15, 0)
#define IRQ_PRI_RTC_WKUP NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 15, 0)
// !@# TAMPER interrupt priority should be probably much higher
#define IRQ_PRI_TAMP NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 15, 0)
#endif // MICROPY_INCLUDED_STM32_IRQ_H

@ -69,7 +69,7 @@ extern "C" {
/*#define HAL_PKA_MODULE_ENABLED */
/*#define HAL_QSPI_MODULE_ENABLED */
/*#define HAL_RNG_MODULE_ENABLED */
/*#define HAL_RTC_MODULE_ENABLED */
#define HAL_RTC_MODULE_ENABLED
/*#define HAL_SAI_MODULE_ENABLED */
/*#define HAL_CRYP_MODULE_ENABLED */
/*#define HAL_SD_MODULE_ENABLED */

@ -0,0 +1,201 @@
/*
* 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 <irq.h>
#include <supervise.h>
#include <tamper.h>
#include STM32_HAL_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
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// Temporary solution for STM32U5A9 Discovery Board experiments
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
void tamper_init() {
RCC_PeriphCLKInitTypeDef clk_init_def = {0};
RCC_OscInitTypeDef osc_init_def = {0};
// Enable LSI clock
osc_init_def.OscillatorType = RCC_OSCILLATORTYPE_LSI;
osc_init_def.LSIState = RCC_LSI_ON;
HAL_RCC_OscConfig(&osc_init_def);
// Select RTC peripheral clock source
clk_init_def.PeriphClockSelection = RCC_PERIPHCLK_RTC;
clk_init_def.RTCClockSelection = RCC_RTCCLKSOURCE_LSI;
HAL_RCCEx_PeriphCLKConfig(&clk_init_def);
// 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 resides 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();
HAL_PWREx_EnableMonitoring();
// HAL_PWR_DisableBkUpAccess();
// Enable all internal tampers (4th and 10th are intentionally skipped)
// Enable TAMP_IN2 external input (PA0)
// We select all of them despite some of them are never triggered
TAMP->CR1 =
TAMP_CR1_TAMP2E | // external TAMP_IN2
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 periherals 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 internal tampers to the "confirmed" mode
// => all secrets all deleted when any tamper event is triggered
TAMP->CR3 = 0;
// Setup external tampers
// TAMP_IN2 active low, "confirmed" mode
TAMP->CR2 = 0;
// TAMP_CR2_TAMP2TRG;
// 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 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_TAMP);
NVIC_EnableIRQ(TAMP_IRQn);
// svc_setpriority(TAMP_IRQn, IRQ_PRI_TAMP);
// svc_enableIRQ(TAMP_IRQn);
}
// Interrupt handle for all tamper events
// It displays an error message
void TAMP_IRQHandler(void) {
const char* reason = "UNKNOWN";
uint32_t sr = TAMP->SR;
if (sr & TAMP_SR_TAMP1F) {
reason = "INPUT1";
} else if (sr & TAMP_SR_TAMP2F) {
reason = "INPUT2";
} else if (sr & TAMP_SR_ITAMP1F) {
reason = "VOLTAGE";
} else if (sr & TAMP_SR_ITAMP2F) {
reason = "TEMPERATURE";
} else if (sr & TAMP_SR_ITAMP3F) {
reason = "LSE CLOCK";
} else if (sr & TAMP_SR_ITAMP5F) {
reason = "RTC OVERFLOW";
} else if (sr & TAMP_SR_ITAMP6F) {
reason = "SWD ACCESS";
} else if (sr & TAMP_SR_ITAMP7F) {
reason = "ANALOG WDG1";
} else if (sr & TAMP_SR_ITAMP8F) {
reason = "MONO COUNTER";
} else if (sr & TAMP_SR_ITAMP9F) {
reason = "CRYPTO ERROR";
} else if (sr & TAMP_SR_ITAMP11F) {
reason = "IWDG";
} else if (sr & TAMP_SR_ITAMP12F) {
reason = "ANALOG WDG2";
} else if (sr & TAMP_SR_ITAMP13F) {
reason = "ANALOG WDG3";
}
error_shutdown("INTERNAL TAMPER", reason);
}
// Triggers ITAMP5 by overflowing RTC date/time
static void tamper_test_rtc_overflow(void) {
RTC_HandleTypeDef hrtc;
RTC_DateTypeDef date = {0};
RTC_TimeTypeDef time = {0};
// Initialize RTC and select BCD format for date & time
hrtc.Instance = RTC;
hrtc.Init.HourFormat = RTC_HOURFORMAT_24;
hrtc.Init.AsynchPrediv = 127;
hrtc.Init.SynchPrediv = 255;
hrtc.Init.OutPut = RTC_OUTPUT_DISABLE;
hrtc.Init.OutPutRemap = RTC_OUTPUT_REMAP_NONE;
hrtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
hrtc.Init.OutPutPullUp = RTC_OUTPUT_PULLUP_NONE;
hrtc.Init.BinMode = RTC_BINARY_NONE;
HAL_RTC_Init(&hrtc);
// set date 99/12/31
date.Year = 0x99;
date.Month = 0x12;
date.Date = 0x31;
date.WeekDay = 0x00;
HAL_RTC_SetDate(&hrtc, &date, RTC_FORMAT_BCD);
// set time 23:59:50
time.Hours = 0x23;
time.Minutes = 0x59;
time.Seconds = 0x50;
HAL_RTC_SetTime(&hrtc, &time, RTC_FORMAT_BCD);
}
// Triggers ITAMP8 by overflowing monotonic counter
static void tamper_test_counter_overflow(void) {
for (uint32_t i = 0; i < UINT32_MAX; i++) {
TAMP->COUNTR = 0;
}
TAMP->COUNTR = 0;
}
void tamper_test(uint32_t tamper_bit) {
if (tamper_bit & TAMP_CR1_ITAMP5E) {
tamper_test_rtc_overflow();
} else if (tamper_bit & TAMP_CR1_ITAMP8E) {
tamper_test_counter_overflow();
}
}

@ -0,0 +1,38 @@
/*
* 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/>.
*/
#ifndef TREZOR_HAL_TAMPER_H
#define TREZOR_HAL_TAMPER_H
#include <stdint.h>
// 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
void tamper_init(void);
// Triggers one of internal tampers.
// The function is intended for experimentation with internal tamper mechanism
// Use TAMP_CR1_xxx constants to as a parameter
// Only TAMP_CR1_ITAMP5E (RTC) and TAMP_CR1_ITAMP8E (monotonic counter)
// are supported
void tamper_test(uint32_t tamper_type);
#endif // TREZOR_HAL_TAMPER_H

@ -2,9 +2,7 @@ from __future__ import annotations
def stm32u5_common_files(env, defines, sources, paths):
defines += [
("STM32_HAL_H", '"<stm32u5xx.h>"'),
]
defines += [("STM32_HAL_H", '"<stm32u5xx.h>"'), "USE_TAMPERS"]
paths += [
"embed/trezorhal/stm32u5",
@ -34,6 +32,7 @@ def stm32u5_common_files(env, defines, sources, paths):
"vendor/stm32cube-u5/Drivers/STM32U5xx_HAL_Driver/Src/stm32u5xx_hal_pwr_ex.c",
"vendor/stm32cube-u5/Drivers/STM32U5xx_HAL_Driver/Src/stm32u5xx_hal_rcc.c",
"vendor/stm32cube-u5/Drivers/STM32U5xx_HAL_Driver/Src/stm32u5xx_hal_rcc_ex.c",
"vendor/stm32cube-u5/Drivers/STM32U5xx_HAL_Driver/Src/stm32u5xx_hal_rtc.c",
"vendor/stm32cube-u5/Drivers/STM32U5xx_HAL_Driver/Src/stm32u5xx_hal_sd.c",
"vendor/stm32cube-u5/Drivers/STM32U5xx_HAL_Driver/Src/stm32u5xx_hal_spi.c",
"vendor/stm32cube-u5/Drivers/STM32U5xx_HAL_Driver/Src/stm32u5xx_hal_sram.c",
@ -53,6 +52,7 @@ def stm32u5_common_files(env, defines, sources, paths):
"embed/trezorhal/stm32u5/systick.c",
"embed/trezorhal/stm32u5/random_delays.c",
"embed/trezorhal/stm32u5/rng.c",
"embed/trezorhal/stm32u5/tamper.c",
"embed/trezorhal/stm32u5/vectortable.s",
]

Loading…
Cancel
Save