What changed, and why it matters
This commit adds support for a new Trezor hardware model, the T3T2. It is a product enablement change that introduces board definitions, memory layouts, bootloader hashes, vendor headers, and Python tooling entries for the new device. There is no indication of a security vulnerability or a fix for one.
No security action required. Treat as routine hardware model enablement. Ensure production keys replace the development placeholders before manufacturing, as already noted by the vendor's TODO comments.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The commit is a feature addition (‘feat(core): add T3T2 model’) that brings up a new STM32U5-based Trezor model. It adds the standard per-model boilerplate: Cargo feature, board headers, memory maps (normal and secure-monitor variants), linker scripts, model.toml, model header, OTP/secret/unit-properties layouts, development vendor headers and signed binaries, bootloader hashes, build.rs and xtask model registration, and trezorlib Python model definitions. The code includes placeholder development keys marked with ‘todo replace with production keys’, which is normal for pre-production hardware bring-up and not a vulnerability in itself. No runtime logic changes to existing models are visible.
Changed components
core/embed/models/T3T2/*core/embed/models/build.rscore/embed/xtask/src/model.rspython/src/trezorlib/cli/firmware.pypython/src/trezorlib/debuglink.pypython/src/trezorlib/firmware/models.pypython/src/trezorlib/models.pyInspect captured patch +860 / −3
diff --git a/core/embed/models/Cargo.toml b/core/embed/models/Cargo.toml
index ff376b77..4be1d5b6 100644
--- a/core/embed/models/Cargo.toml
+++ b/core/embed/models/Cargo.toml
@@ -24,6 +24,7 @@ model_t2t1 = []
model_t2b1 = []
model_t3b1 = []
model_t3t1 = []
+model_t3t2 = []
model_t3w1 = []
# --------------------------------------------------------------------------
diff --git a/core/embed/models/T3T2/boards/devkit.h b/core/embed/models/T3T2/boards/devkit.h
new file mode 100644
index 00000000..56167f14
--- /dev/null
+++ b/core/embed/models/T3T2/boards/devkit.h
@@ -0,0 +1,126 @@
+#pragma once
+
+#define VDD_3V3 1
+
+// ST7789 (Display Elektronik DEM240320B1) over 16-bit i8080 FMC bus.
+// The module has no tearing-effect (TE) output, so no DISPLAY_TE_* defines.
+#define DISPLAY_I8080_16BIT_DW 1
+
+// Use a single framebuffer on this project (lower RAM use; there is no TE
+// signal to drive smooth double-buffered swaps anyway).
+#define FRAME_BUFFER_COUNT 1
+
+#define DISPLAY_IDENTIFY 1
+
+// Display reset (DISPL_NRST)
+#define DISPLAY_RST_PORT GPIOG
+#define DISPLAY_RST_PIN GPIO_PIN_14
+
+// Display data/command select (DISPL_DC) routed to FMC_A4
+#define DISPLAY_DC_PORT GPIOF
+#define DISPLAY_DC_PIN GPIO_PIN_4
+#define DISPLAY_MEMORY_PIN 4
+
+// Display power-supply enable (DISPL_PWR_EN, load switch)
+#define DISPLAY_PWR_PORT GPIOF
+#define DISPLAY_PWR_PIN GPIO_PIN_15
+
+// Backlight: four LED strings driven as synchronized active-low PWM by
+// TIM3 CH1-CH4 on PE3-PE6 (cathodes via 33R), with a common boost supply.
+#define BACKLIGHT_PWM_TIM TIM3
+#define BACKLIGHT_PWM_TIM_CLK_EN __HAL_RCC_TIM3_CLK_ENABLE
+#define BACKLIGHT_PWM_TIM_CLK_DIS __HAL_RCC_TIM3_CLK_DISABLE
+#define BACKLIGHT_PWM_TIM_FORCE_RESET __HAL_RCC_TIM3_FORCE_RESET
+#define BACKLIGHT_PWM_TIM_RELEASE_RESET __HAL_RCC_TIM3_RELEASE_RESET
+#define BACKLIGHT_PWM_TIM_AF GPIO_AF2_TIM3
+#define BACKLIGHT_PWM_CHANNELS \
+ {TIM_CHANNEL_1, TIM_CHANNEL_2, TIM_CHANNEL_3, TIM_CHANNEL_4}
+#define BACKLIGHT_PWM_PORT GPIOE
+#define BACKLIGHT_PWM_PORT_CLK_EN __HAL_RCC_GPIOE_CLK_ENABLE
+#define BACKLIGHT_PWM_PINS (GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6)
+
+#define I2C_COUNT 3
+#define I2C_INSTANCE_0 I2C1
+#define I2C_INSTANCE_0_CLK_EN __HAL_RCC_I2C1_CLK_ENABLE
+#define I2C_INSTANCE_0_CLK_DIS __HAL_RCC_I2C1_CLK_DISABLE
+#define I2C_INSTANCE_0_PIN_AF GPIO_AF4_I2C1
+#define I2C_INSTANCE_0_SDA_PORT GPIOB
+#define I2C_INSTANCE_0_SDA_PIN GPIO_PIN_9
+#define I2C_INSTANCE_0_SDA_CLK_EN __HAL_RCC_GPIOB_CLK_ENABLE
+#define I2C_INSTANCE_0_SCL_PORT GPIOB
+#define I2C_INSTANCE_0_SCL_PIN GPIO_PIN_8
+#define I2C_INSTANCE_0_SCL_CLK_EN __HAL_RCC_GPIOB_CLK_ENABLE
+#define I2C_INSTANCE_0_RESET_REG &RCC->APB1RSTR1
+#define I2C_INSTANCE_0_RESET_BIT RCC_APB1RSTR1_I2C1RST
+#define I2C_INSTANCE_0_EV_IRQHandler I2C1_EV_IRQHandler
+#define I2C_INSTANCE_0_ER_IRQHandler I2C1_ER_IRQHandler
+#define I2C_INSTANCE_0_EV_IRQn I2C1_EV_IRQn
+#define I2C_INSTANCE_0_ER_IRQn I2C1_ER_IRQn
+#define I2C_INSTANCE_0_GUARD_TIME 0
+
+#define I2C_INSTANCE_1 I2C2
+#define I2C_INSTANCE_1_CLK_EN __HAL_RCC_I2C2_CLK_ENABLE
+#define I2C_INSTANCE_1_CLK_DIS __HAL_RCC_I2C2_CLK_DISABLE
+#define I2C_INSTANCE_1_PIN_AF GPIO_AF4_I2C2
+#define I2C_INSTANCE_1_SDA_PORT GPIOB
+#define I2C_INSTANCE_1_SDA_PIN GPIO_PIN_14
+#define I2C_INSTANCE_1_SDA_CLK_EN __HAL_RCC_GPIOB_CLK_ENABLE
+#define I2C_INSTANCE_1_SCL_PORT GPIOB
+#define I2C_INSTANCE_1_SCL_PIN GPIO_PIN_13
+#define I2C_INSTANCE_1_SCL_CLK_EN __HAL_RCC_GPIOB_CLK_ENABLE
+#define I2C_INSTANCE_1_RESET_REG &RCC->APB1RSTR1
+#define I2C_INSTANCE_1_RESET_BIT RCC_APB1RSTR1_I2C2RST
+#define I2C_INSTANCE_1_EV_IRQHandler I2C2_EV_IRQHandler
+#define I2C_INSTANCE_1_ER_IRQHandler I2C2_ER_IRQHandler
+#define I2C_INSTANCE_1_EV_IRQn I2C2_EV_IRQn
+#define I2C_INSTANCE_1_ER_IRQn I2C2_ER_IRQn
+#define I2C_INSTANCE_1_GUARD_TIME 0
+
+#define I2C_INSTANCE_2 I2C3
+#define I2C_INSTANCE_2_CLK_EN __HAL_RCC_I2C3_CLK_ENABLE
+#define I2C_INSTANCE_2_CLK_DIS __HAL_RCC_I2C3_CLK_DISABLE
+#define I2C_INSTANCE_2_PIN_AF GPIO_AF4_I2C3
+#define I2C_INSTANCE_2_SDA_PORT GPIOG
+#define I2C_INSTANCE_2_SDA_PIN GPIO_PIN_8
+#define I2C_INSTANCE_2_SDA_CLK_EN __HAL_RCC_GPIOG_CLK_ENABLE
+#define I2C_INSTANCE_2_SCL_PORT GPIOG
+#define I2C_INSTANCE_2_SCL_PIN GPIO_PIN_7
+#define I2C_INSTANCE_2_SCL_CLK_EN __HAL_RCC_GPIOG_CLK_ENABLE
+#define I2C_INSTANCE_2_RESET_REG &RCC->APB3RSTR
+#define I2C_INSTANCE_2_RESET_BIT RCC_APB3RSTR_I2C3RST
+#define I2C_INSTANCE_2_EV_IRQHandler I2C3_EV_IRQHandler
+#define I2C_INSTANCE_2_ER_IRQHandler I2C3_ER_IRQHandler
+#define I2C_INSTANCE_2_EV_IRQn I2C3_EV_IRQn
+#define I2C_INSTANCE_2_ER_IRQn I2C3_ER_IRQn
+#define I2C_INSTANCE_2_GUARD_TIME 50 // Optiga requires 50us guard time
+#define I2C_INSTANCE_2_GTZC_PERIPH GTZC_PERIPH_I2C3
+
+#define TOUCH_SENSITIVITY 0x40
+#define TOUCH_I2C_INSTANCE 0
+#define TOUCH_INT_PORT GPIOB
+#define TOUCH_INT_PIN GPIO_PIN_11
+#define TOUCH_ON_PORT GPIOG
+#define TOUCH_ON_PIN GPIO_PIN_0
+
+#define OPTIGA_I2C_INSTANCE 2
+#define OPTIGA_RST_PORT GPIOF
+#define OPTIGA_RST_PIN GPIO_PIN_13
+#define OPTIGA_RST_CLK_EN __HAL_RCC_GPIOF_CLK_ENABLE
+#define OPTIGA_PWR_PORT GPIOF
+#define OPTIGA_PWR_PIN GPIO_PIN_12
+#define OPTIGA_PWR_CLK_EN __HAL_RCC_GPIOF_CLK_ENABLE
+
+// reserved, replace with real pins when available
+#define HW_REVISION_PUPD GPIO_PULLUP
+#define HW_REVISION_0_PIN GPIO_PIN_6
+#define HW_REVISION_0_PORT GPIOF
+#define HW_REVISION_0_CLOCK_ENABLE() __HAL_RCC_GPIOF_CLK_ENABLE()
+#define HW_REVISION_1_PIN GPIO_PIN_7
+#define HW_REVISION_1_PORT GPIOF
+#define HW_REVISION_1_CLOCK_ENABLE() __HAL_RCC_GPIOF_CLK_ENABLE()
+#define HW_REVISION_2_PIN GPIO_PIN_8
+#define HW_REVISION_2_PORT GPIOF
+#define HW_REVISION_2_CLOCK_ENABLE() __HAL_RCC_GPIOF_CLK_ENABLE()
+#define HW_REVISION_3_PIN GPIO_PIN_9
+#define HW_REVISION_3_PORT GPIOF
+#define HW_REVISION_3_CLOCK_ENABLE() __HAL_RCC_GPIOF_CLK_ENABLE()
diff --git a/core/embed/models/T3T2/boards/devkit.toml b/core/embed/models/T3T2/boards/devkit.toml
new file mode 100644
index 00000000..8d2fbce9
--- /dev/null
+++ b/core/embed/models/T3T2/boards/devkit.toml
@@ -0,0 +1,16 @@
+header = "T3T2/boards/devkit.h"
+emulator_header = "T3T2/boards/unix.h"
+
+[display]
+driver = "io/display_st7789"
+panel = "io/display_panel_dem240320b1"
+
+[backlight]
+driver = "io/backlight_pwm"
+
+[touch]
+driver = "io/touch_ft6x36"
+panel = "io/touch_panel_lx154a2422cpt23"
+
+[optiga]
+
diff --git a/core/embed/models/T3T2/boards/unix.h b/core/embed/models/T3T2/boards/unix.h
new file mode 100644
index 00000000..4dc6370c
--- /dev/null
+++ b/core/embed/models/T3T2/boards/unix.h
@@ -0,0 +1,11 @@
+#pragma once
+
+#define WINDOW_WIDTH 400
+#define WINDOW_HEIGHT 600
+#define TOUCH_OFFSET_X 80
+#define TOUCH_OFFSET_Y 102
+
+#define ORIENTATION_NSEW 1
+
+#define BACKGROUND_FILE "T3T1/background_T3T1.h"
+#define BACKGROUND_NAME background_T3T1_jpg
diff --git a/core/embed/models/T3T2/bootloaders/bootloader_T3T2_devel.bin b/core/embed/models/T3T2/bootloaders/bootloader_T3T2_devel.bin
new file mode 100755
index 00000000..729f1ff5
Binary files /dev/null and b/core/embed/models/T3T2/bootloaders/bootloader_T3T2_devel.bin differ
diff --git a/core/embed/models/T3T2/bootloaders/bootloader_hashes.h b/core/embed/models/T3T2/bootloaders/bootloader_hashes.h
new file mode 100644
index 00000000..09e765c3
--- /dev/null
+++ b/core/embed/models/T3T2/bootloaders/bootloader_hashes.h
@@ -0,0 +1,13 @@
+#ifndef BOOTLOADER_HASHES_H
+#define BOOTLOADER_HASHES_H
+
+// Auto-generated file, do not edit.
+
+// clang-format off
+// bootloader_T3T2_devel.bin version 2.1.18.0
+#define BOOTLOADER_T3T2_DEVEL_00 {0xde, 0xc1, 0x72, 0x97, 0x9a, 0x52, 0xb6, 0x80, 0x1d, 0x68, 0xae, 0xa7, 0x20, 0x50, 0x58, 0xa7, 0x65, 0x78, 0xa4, 0x79, 0x7c, 0x72, 0x93, 0x63, 0x2e, 0x91, 0x12, 0x78, 0x54, 0xc5, 0xde, 0xfb}
+#define BOOTLOADER_T3T2_DEVEL_FF {0xbd, 0x6c, 0x02, 0xc6, 0x54, 0x42, 0x50, 0xbb, 0x3d, 0x85, 0xc1, 0x38, 0x5e, 0xaf, 0x5e, 0x81, 0xf9, 0xd5, 0x18, 0x92, 0x6e, 0x3f, 0x5a, 0xea, 0xe2, 0x68, 0x1e, 0xda, 0xce, 0xfe, 0x79, 0xb2}
+
+// clang-format on
+
+#endif
diff --git a/core/embed/models/T3T2/memory.h b/core/embed/models/T3T2/memory.h
new file mode 100644
index 00000000..06d38100
--- /dev/null
+++ b/core/embed/models/T3T2/memory.h
@@ -0,0 +1,113 @@
+/*
+ * 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
+
+// SHARED WITH MAKEFILE, LINKER SCRIPT etc.
+// misc
+#define FLASH_START (0x0C004000)
+
+// FLASH layout
+#define SECRET_START (0x0C000000)
+#define SECRET_MAXSIZE (2 * 8 * 1024) // 16 kB
+#define SECRET_SECTOR_START 0x0
+#define SECRET_SECTOR_END 0x1
+
+// overlaps with secret
+#define BHK_START (0x0C002000)
+#define BHK_MAXSIZE (1 * 8 * 1024) // 8 kB
+#define BHK_SECTOR_START 0x1
+#define BHK_SECTOR_END 0x1
+
+#define BOARDLOADER_START (0x0C004000)
+#define BOARDLOADER_MAXSIZE (8 * 8 * 1024) // 64 kB
+#define BOARDLOADER_SECTOR_START 0x2
+#define BOARDLOADER_SECTOR_END 0x9
+
+#define BOARDCAPS_START (0x0C013F00)
+#define BOARDCAPS_MAXSIZE 0x100
+
+// Update control block
+#define BOOTUCB_START (0x0C014000)
+#define BOOTUCB_MAXSIZE (1 * 8 * 1024) // 8 kB
+#define BOOTUCB_SECTOR_START 0xA
+#define BOOTUCB_SECTOR_END 0xA
+
+// Non-boardloader area (includes bootloader, firmware, assets and storage)
+#define NONBOARDLOADER_START (0x0C016000)
+#define NONBOARDLOADER_MAXSIZE (245 * 8 * 1024) // 1960 kB
+#define NONBOARDLOADER_SECTOR_START 0xB
+#define NONBOARDLOADER_SECTOR_END 0xFF
+
+#define BOOTLOADER_START (0x0C016000)
+#define BOOTLOADER_MAXSIZE (24 * 8 * 1024) // 192 kB
+#define BOOTLOADER_SECTOR_START 0xB
+#define BOOTLOADER_SECTOR_END 0x22
+
+#define FIRMWARE_START (0x0C046000)
+#define FIRMWARE_MAXSIZE (205 * 8 * 1024) // 1640 kB
+#define FIRMWARE_SECTOR_START 0x23
+#define FIRMWARE_SECTOR_END 0xEF
+
+// overlaps with assets and storage; sized to hold a full bootloader image
+#define BOOTUPDATE_START (0x0C1E0000)
+#define BOOTUPDATE_MAXSIZE (16 * 8 * 1024) // 128 kB
+#define BOOTUPDATE_SECTOR_START 0xF0
+#define BOOTUPDATE_SECTOR_END 0xFF
+
+#define ASSETS_START (0x0C1E0000)
+#define ASSETS_MAXSIZE (8 * 8 * 1024) // 64 kB
+#define ASSETS_SECTOR_START 0xF0
+#define ASSETS_SECTOR_END 0xF7
+
+#define STORAGE_1_START (0x0C1F0000)
+#define STORAGE_1_MAXSIZE (4 * 8 * 1024) // 32 kB
+#define STORAGE_1_SECTOR_START 0xF8
+#define STORAGE_1_SECTOR_END 0xFB
+
+#define STORAGE_2_START (0x0C1F8000)
+#define STORAGE_2_MAXSIZE (4 * 8 * 1024) // 32 kB
+#define STORAGE_2_SECTOR_START 0xFC
+#define STORAGE_2_SECTOR_END 0xFF
+
+// RAM layout
+// BOOTARGS is placed at the very start of SRAM and kept at the same address
+// across all boot stages (see memory_secmon.h) so the boot handoff is stable.
+#define BOOTARGS_START 0x30000000
+#define BOOTARGS_SIZE 0x200
+
+#define FB1_RAM_START 0x30000200
+#define FB1_RAM_SIZE (153600) // 240 * 320 * 2
+
+// Single framebuffer configuration: FB2 is unused (FRAME_BUFFER_COUNT == 1)
+#define FB2_RAM_START 0x30025A00
+#define FB2_RAM_SIZE (0)
+
+#define MAIN_RAM_START 0x30025A00
+#define MAIN_RAM_SIZE (48 * 1024)
+
+#define AUX1_RAM_START 0x30031A00
+#define AUX1_RAM_SIZE (172 * 1024 - 512)
+
+#define AUX2_RAM_START 0x3005C800
+#define AUX2_RAM_SIZE (398 * 1024)
+
+// misc
+#define CODE_ALIGNMENT 0x200
+#define COREAPP_ALIGNMENT 0x2000
diff --git a/core/embed/models/T3T2/memory.ld b/core/embed/models/T3T2/memory.ld
new file mode 100644
index 00000000..8c2c887d
--- /dev/null
+++ b/core/embed/models/T3T2/memory.ld
@@ -0,0 +1,63 @@
+/* Auto-generated file, do not edit.*/
+
+FLASH_START = 0xc004000;
+SECRET_START = 0xc000000;
+SECRET_MAXSIZE = 0x4000;
+SECRET_SECTOR_START = 0x0;
+SECRET_SECTOR_END = 0x1;
+BHK_START = 0xc002000;
+BHK_MAXSIZE = 0x2000;
+BHK_SECTOR_START = 0x1;
+BHK_SECTOR_END = 0x1;
+BOARDLOADER_START = 0xc004000;
+BOARDLOADER_MAXSIZE = 0x10000;
+BOARDLOADER_SECTOR_START = 0x2;
+BOARDLOADER_SECTOR_END = 0x9;
+BOARDCAPS_START = 0xc013f00;
+BOARDCAPS_MAXSIZE = 0x100;
+BOOTUCB_START = 0xc014000;
+BOOTUCB_MAXSIZE = 0x2000;
+BOOTUCB_SECTOR_START = 0xa;
+BOOTUCB_SECTOR_END = 0xa;
+NONBOARDLOADER_START = 0xc016000;
+NONBOARDLOADER_MAXSIZE = 0x1ea000;
+NONBOARDLOADER_SECTOR_START = 0xb;
+NONBOARDLOADER_SECTOR_END = 0xff;
+BOOTLOADER_START = 0xc016000;
+BOOTLOADER_MAXSIZE = 0x30000;
+BOOTLOADER_SECTOR_START = 0xb;
+BOOTLOADER_SECTOR_END = 0x22;
+FIRMWARE_START = 0xc046000;
+FIRMWARE_MAXSIZE = 0x19a000;
+FIRMWARE_SECTOR_START = 0x23;
+FIRMWARE_SECTOR_END = 0xef;
+BOOTUPDATE_START = 0xc1e0000;
+BOOTUPDATE_MAXSIZE = 0x20000;
+BOOTUPDATE_SECTOR_START = 0xf0;
+BOOTUPDATE_SECTOR_END = 0xff;
+ASSETS_START = 0xc1e0000;
+ASSETS_MAXSIZE = 0x10000;
+ASSETS_SECTOR_START = 0xf0;
+ASSETS_SECTOR_END = 0xf7;
+STORAGE_1_START = 0xc1f0000;
+STORAGE_1_MAXSIZE = 0x8000;
+STORAGE_1_SECTOR_START = 0xf8;
+STORAGE_1_SECTOR_END = 0xfb;
+STORAGE_2_START = 0xc1f8000;
+STORAGE_2_MAXSIZE = 0x8000;
+STORAGE_2_SECTOR_START = 0xfc;
+STORAGE_2_SECTOR_END = 0xff;
+BOOTARGS_START = 0x30000000;
+BOOTARGS_SIZE = 0x200;
+FB1_RAM_START = 0x30000200;
+FB1_RAM_SIZE = 0x25800;
+FB2_RAM_START = 0x30025a00;
+FB2_RAM_SIZE = 0x0;
+MAIN_RAM_START = 0x30025a00;
+MAIN_RAM_SIZE = 0xc000;
+AUX1_RAM_START = 0x30031a00;
+AUX1_RAM_SIZE = 0x2ae00;
+AUX2_RAM_START = 0x3005c800;
+AUX2_RAM_SIZE = 0x63800;
+CODE_ALIGNMENT = 0x200;
+COREAPP_ALIGNMENT = 0x2000;
diff --git a/core/embed/models/T3T2/memory_secmon.h b/core/embed/models/T3T2/memory_secmon.h
new file mode 100644
index 00000000..5caf34e8
--- /dev/null
+++ b/core/embed/models/T3T2/memory_secmon.h
@@ -0,0 +1,126 @@
+/*
+ * 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
+
+// SHARED WITH MAKEFILE, LINKER SCRIPT etc.
+// misc
+#define FLASH_START (0x0C004000)
+
+// FLASH layout
+#define SECRET_START (0x0C000000)
+#define SECRET_MAXSIZE (2 * 8 * 1024) // 16 kB
+#define SECRET_SECTOR_START 0x0
+#define SECRET_SECTOR_END 0x1
+
+// overlaps with secret
+#define BHK_START (0x0C002000)
+#define BHK_MAXSIZE (1 * 8 * 1024) // 8 kB
+#define BHK_SECTOR_START 0x1
+#define BHK_SECTOR_END 0x1
+
+#define BOARDLOADER_START (0x0C004000)
+#define BOARDLOADER_MAXSIZE (8 * 8 * 1024) // 64 kB
+#define BOARDLOADER_SECTOR_START 0x2
+#define BOARDLOADER_SECTOR_END 0x9
+
+#define BOARDCAPS_START (0x0C013F00)
+#define BOARDCAPS_MAXSIZE 0x100
+
+// Update control block
+#define BOOTUCB_START (0x0C014000)
+#define BOOTUCB_MAXSIZE (1 * 8 * 1024) // 8 kB
+#define BOOTUCB_SECTOR_START 0xA
+#define BOOTUCB_SECTOR_END 0xA
+
+// Non-boardloader area (includes bootloader, firmware, assets and storage)
+#define NONBOARDLOADER_START (0x0C016000)
+#define NONBOARDLOADER_MAXSIZE (245 * 8 * 1024) // 1960 kB
+#define NONBOARDLOADER_SECTOR_START 0xB
+#define NONBOARDLOADER_SECTOR_END 0xFF
+
+#define BOOTLOADER_START (0x0C016000)
+#define BOOTLOADER_MAXSIZE (24 * 8 * 1024) // 192 kB
+#define BOOTLOADER_SECTOR_START 0xB
+#define BOOTLOADER_SECTOR_END 0x22
+
+#define FIRMWARE_START (0x08046000)
+#define FIRMWARE_START_S (0x0C046000)
+#define FIRMWARE_MAXSIZE (205 * 8 * 1024) // 1640 kB
+#define FIRMWARE_SECTOR_START 0x23
+#define FIRMWARE_SECTOR_END 0xEF
+
+#define ASSETS_START (0x081E0000)
+#define ASSETS_MAXSIZE (8 * 8 * 1024) // 64 kB
+#define ASSETS_SECTOR_START 0xF0
+#define ASSETS_SECTOR_END 0xF7
+
+// overlaps with assets and storage; sized to hold a full bootloader image
+#define BOOTUPDATE_START (0x0C1E0000)
+#define BOOTUPDATE_MAXSIZE (16 * 8 * 1024) // 128 kB
+#define BOOTUPDATE_SECTOR_START 0xF0
+#define BOOTUPDATE_SECTOR_END 0xFF
+
+#define STORAGE_1_START (0x0C1F0000)
+#define STORAGE_1_MAXSIZE (4 * 8 * 1024) // 32 kB
+#define STORAGE_1_SECTOR_START 0xF8
+#define STORAGE_1_SECTOR_END 0xFB
+
+#define STORAGE_2_START (0x0C1F8000)
+#define STORAGE_2_MAXSIZE (4 * 8 * 1024) // 32 kB
+#define STORAGE_2_SECTOR_START 0xFC
+#define STORAGE_2_SECTOR_END 0xFF
+
+// RAM layout
+// Total SRAM is 768 kB (0x...0000..0x...C0000). SECMON_RAM (secure, 96 kB) is
+// carved out at the top of SRAM; everything below it is non-secure and shared
+// by the kernel and firmware. The framebuffers, MAIN_RAM, AUX1 and AUX2 all
+// live in the non-secure region. BOOTARGS stays at the start of SRAM (secure
+// alias) and matches memory.h so the boot handoff is stable.
+#define BOOTARGS_START 0x30000000
+#define BOOTARGS_SIZE 0x200
+
+#define NONSECURE_RAM1_START 0x20000200
+#define NONSECURE_RAM1_SIZE (672 * 1024 - 512) // up to SECMON_RAM
+
+#define SECMON_RAM_START 0x300A8000
+#define SECMON_RAM_SIZE (96 * 1024)
+
+#define NONSECURE_RAM2_START 0x200C0000
+#define NONSECURE_RAM2_SIZE 0
+
+#define FB1_RAM_START 0x20000200
+#define FB1_RAM_SIZE (153600) // 240 * 320 * 2
+
+// Single framebuffer configuration: FB2 is unused (FRAME_BUFFER_COUNT == 1)
+#define FB2_RAM_START 0x20025A00
+#define FB2_RAM_SIZE (0)
+
+#define MAIN_RAM_START 0x20025A00
+#define MAIN_RAM_SIZE (48 * 1024)
+
+#define AUX1_RAM_START 0x20031A00
+#define AUX1_RAM_SIZE (172 * 1024 - 512)
+
+#define AUX2_RAM_START 0x2005C800
+#define AUX2_RAM_SIZE (302 * 1024)
+
+// misc
+#define CODE_ALIGNMENT 0x200
+#define COREAPP_ALIGNMENT 0x2000
diff --git a/core/embed/models/T3T2/memory_secmon.ld b/core/embed/models/T3T2/memory_secmon.ld
new file mode 100644
index 00000000..dca3d4c7
--- /dev/null
+++ b/core/embed/models/T3T2/memory_secmon.ld
@@ -0,0 +1,70 @@
+/* Auto-generated file, do not edit.*/
+
+FLASH_START = 0xc004000;
+SECRET_START = 0xc000000;
+SECRET_MAXSIZE = 0x4000;
+SECRET_SECTOR_START = 0x0;
+SECRET_SECTOR_END = 0x1;
+BHK_START = 0xc002000;
+BHK_MAXSIZE = 0x2000;
+BHK_SECTOR_START = 0x1;
+BHK_SECTOR_END = 0x1;
+BOARDLOADER_START = 0xc004000;
+BOARDLOADER_MAXSIZE = 0x10000;
+BOARDLOADER_SECTOR_START = 0x2;
+BOARDLOADER_SECTOR_END = 0x9;
+BOARDCAPS_START = 0xc013f00;
+BOARDCAPS_MAXSIZE = 0x100;
+BOOTUCB_START = 0xc014000;
+BOOTUCB_MAXSIZE = 0x2000;
+BOOTUCB_SECTOR_START = 0xa;
+BOOTUCB_SECTOR_END = 0xa;
+NONBOARDLOADER_START = 0xc016000;
+NONBOARDLOADER_MAXSIZE = 0x1ea000;
+NONBOARDLOADER_SECTOR_START = 0xb;
+NONBOARDLOADER_SECTOR_END = 0xff;
+BOOTLOADER_START = 0xc016000;
+BOOTLOADER_MAXSIZE = 0x30000;
+BOOTLOADER_SECTOR_START = 0xb;
+BOOTLOADER_SECTOR_END = 0x22;
+FIRMWARE_START = 0x8046000;
+FIRMWARE_START_S = 0xc046000;
+FIRMWARE_MAXSIZE = 0x19a000;
+FIRMWARE_SECTOR_START = 0x23;
+FIRMWARE_SECTOR_END = 0xef;
+ASSETS_START = 0x81e0000;
+ASSETS_MAXSIZE = 0x10000;
+ASSETS_SECTOR_START = 0xf0;
+ASSETS_SECTOR_END = 0xf7;
+BOOTUPDATE_START = 0xc1e0000;
+BOOTUPDATE_MAXSIZE = 0x20000;
+BOOTUPDATE_SECTOR_START = 0xf0;
+BOOTUPDATE_SECTOR_END = 0xff;
+STORAGE_1_START = 0xc1f0000;
+STORAGE_1_MAXSIZE = 0x8000;
+STORAGE_1_SECTOR_START = 0xf8;
+STORAGE_1_SECTOR_END = 0xfb;
+STORAGE_2_START = 0xc1f8000;
+STORAGE_2_MAXSIZE = 0x8000;
+STORAGE_2_SECTOR_START = 0xfc;
+STORAGE_2_SECTOR_END = 0xff;
+BOOTARGS_START = 0x30000000;
+BOOTARGS_SIZE = 0x200;
+NONSECURE_RAM1_START = 0x20000200;
+NONSECURE_RAM1_SIZE = 0xa7e00;
+SECMON_RAM_START = 0x300a8000;
+SECMON_RAM_SIZE = 0x18000;
+NONSECURE_RAM2_START = 0x200c0000;
+NONSECURE_RAM2_SIZE = 0x0;
+FB1_RAM_START = 0x20000200;
+FB1_RAM_SIZE = 0x25800;
+FB2_RAM_START = 0x20025a00;
+FB2_RAM_SIZE = 0x0;
+MAIN_RAM_START = 0x20025a00;
+MAIN_RAM_SIZE = 0xc000;
+AUX1_RAM_START = 0x20031a00;
+AUX1_RAM_SIZE = 0x2ae00;
+AUX2_RAM_START = 0x2005c800;
+AUX2_RAM_SIZE = 0x4b800;
+CODE_ALIGNMENT = 0x200;
+COREAPP_ALIGNMENT = 0x2000;
diff --git a/core/embed/models/T3T2/model.toml b/core/embed/models/T3T2/model.toml
new file mode 100644
index 00000000..d220dc18
--- /dev/null
+++ b/core/embed/models/T3T2/model.toml
@@ -0,0 +1,27 @@
+mcu = "stm32u58"
+default_board = "devkit"
+secmon = true
+bootloader_header_tool = "headertool_pq"
+
+features = [
+ "backup_ram",
+ "boot_ucb",
+ "dma2d",
+ "hash_processor",
+ "hw_revision",
+ "iwdg",
+ "lockable_bootloader",
+ "mcu_attestation",
+ "secmon_header",
+ "secmon_layout",
+ "secmon_verification",
+ "secret",
+ "secure_aes",
+ "serial_number",
+ "framebuffer",
+ "tamper",
+ "thp",
+ "layout_delizia",
+ "display_rgb565",
+]
+
diff --git a/core/embed/models/T3T2/model_T3T2.h b/core/embed/models/T3T2/model_T3T2.h
new file mode 100644
index 00000000..bf9cbb28
--- /dev/null
+++ b/core/embed/models/T3T2/model_T3T2.h
@@ -0,0 +1,61 @@
+/*
+ * 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 "bootloaders/bootloader_hashes.h"
+#include "secret_layout.h"
+
+#include <rtl/sizedefs.h>
+
+#define MODEL_NAME "T3T2"
+#define MODEL_FULL_NAME "Trezor T3T2"
+#define MODEL_INTERNAL_NAME "T3T2"
+#define MODEL_INTERNAL_NAME_TOKEN T3T2
+#define MODEL_INTERNAL_NAME_QSTR MP_QSTR_T3T2
+#define MODEL_USB_MANUFACTURER "Trezor Company"
+#define MODEL_USB_PRODUCT MODEL_FULL_NAME
+#define MODEL_HOMESCREEN_MAXSIZE 16384
+
+// todo replace with production keys
+#define MODEL_BOARDLOADER_KEYS \
+ (const uint8_t *)"\x76\xaf\x42\x6e\x61\x40\x6b\xad\x7c\x07\x7b\x40\x9c\x66\xfd\xe3\x9f\xb8\x17\x91\x93\x13\xae\x1e\x4c\x02\x53\x5c\x80\xbe\xed\x96", \
+ (const uint8_t *)"\x61\x97\x51\xdc\x8d\x2d\x09\xd7\xe5\xdf\xb9\x9e\x41\xf6\x06\xde\xbd\xf4\x19\xf8\x5a\x81\x43\xe8\xe5\x39\x9e\xa6\x7a\x39\x88\xc7", \
+ (const uint8_t *)"\xab\xf9\x4b\x66\x15\xa7\xdd\xe2\xa8\x71\xf7\xd6\x2c\x38\xef\xc7\xd9\xd8\xf6\x01\x0d\x88\x46\xbe\xe6\x36\xe4\xf3\xe6\x58\xa3\x8c",
+
+// todo replace with production keys
+#define MODEL_BOOTLOADER_KEYS \
+ (const uint8_t *)"\x33\x8b\x94\x9b\x7e\x3b\x26\x47\x0d\x4f\xe3\x69\x6f\xd6\xff\xf2\x87\x57\x26\x5d\x14\xcc\xa4\x8e\xbf\x2d\xb9\x7b\x4f\x5b\xc0\x39", \
+ (const uint8_t *)"\x28\x68\x20\x27\x73\x0b\x78\x32\x01\xb0\x5a\x8c\x9d\x11\x68\x54\x47\xc1\x72\x97\xdb\x71\xb8\xa6\x0d\xc6\x93\xa4\x46\x10\x75\x1d", \
+ (const uint8_t *)"\x9f\xbf\x31\xb4\xe3\x51\xa4\xcc\x81\xc7\x59\x95\xb2\x25\x7f\x0a\x71\x69\x26\x8d\xa5\xa4\x4e\x94\xb6\xa5\x59\x0d\x43\x4e\x32\xda",
+
+#define IMAGE_CHUNK_SIZE (128 * 1024)
+#define IMAGE_HASH_SHA256
+
+#define DISPLAY_JUMP_BEHAVIOR DISPLAY_RESET_CONTENT
+#define RSOD_INFINITE_LOOP 1
+
+#define NORCOW_SECTOR_SIZE (4 * 8 * 1024) // 32 kB
+#define NORCOW_MIN_VERSION 0x00000006
+
+#ifdef USE_SECMON_LAYOUT
+#include "memory_secmon.h"
+#else
+#include "memory.h"
+#endif
diff --git a/core/embed/models/T3T2/otp_layout.h b/core/embed/models/T3T2/otp_layout.h
new file mode 100644
index 00000000..97263c62
--- /dev/null
+++ b/core/embed/models/T3T2/otp_layout.h
@@ -0,0 +1,12 @@
+#pragma once
+
+// OTP blocks allocation
+#define FLASH_OTP_BLOCK_BATCH 0
+#define FLASH_OTP_BLOCK_BOOTLOADER_VERSION 1
+#define FLASH_OTP_BLOCK_VENDOR_HEADER_LOCK 2
+#define FLASH_OTP_BLOCK_RANDOMNESS 3
+#define FLASH_OTP_BLOCK_DEVICE_VARIANT 4
+#define FLASH_OTP_BLOCK_FIRMWARE_VERSION 5
+#define FLASH_OTP_BLOCK_DEVICE_SN 6
+#define FLASH_OTP_BLOCK_DEVICE_VARIANT_REWORK 7
+#define FLASH_OTP_BLOCK_MASTER_KEY 8
diff --git a/core/embed/models/T3T2/secret_layout.h b/core/embed/models/T3T2/secret_layout.h
new file mode 100644
index 00000000..bbd4ee7a
--- /dev/null
+++ b/core/embed/models/T3T2/secret_layout.h
@@ -0,0 +1,63 @@
+/*
+ * 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
+
+#define SECRET_NUM_KEY_SLOTS 3
+
+#define SECRET_MASTER_KEY_SLOT_SIZE 0x20
+
+// first page: static
+#define SECRET_HEADER_OFFSET 0x00
+#define SECRET_HEADER_LEN 0x10
+
+#define SECRET_KEY_SLOT_0_OFFSET 0x10
+#define SECRET_KEY_SLOT_0_LEN SECRET_MASTER_KEY_SLOT_SIZE
+
+#define SECRET_MONOTONIC_COUNTER_0_OFFSET 0x30
+#define SECRET_MONOTONIC_COUNTER_0_LEN 0x400
+
+#define SECRET_MONOTONIC_COUNTER_1_OFFSET 0x430
+#define SECRET_MONOTONIC_COUNTER_1_LEN 0x400
+
+#define SECRET_KEY_SLOT_1_OFFSET 0x830
+#define SECRET_KEY_SLOT_1_LEN SECRET_MASTER_KEY_SLOT_SIZE
+#define SECRET_KEY_SLOT_1_PUBLIC 1
+
+// Optiga pairing secret
+#define SECRET_KEY_SLOT_2_OFFSET 0x850
+#define SECRET_KEY_SLOT_2_LEN 0x20
+
+#define SECRET_MCU_DEVICE_CERT_OFFSET 0x870
+#define SECRET_MCU_DEVICE_CERT_SIZE 0x1000
+
+#define SECRET_MONOTONIC_COUNTER_2_OFFSET 0x1870
+#define SECRET_MONOTONIC_COUNTER_2_LEN 0x400
+
+#define SECRET_LOCK_SLOT_OFFSET 0x1FF0
+#define SECRET_LOCK_SLOT_LEN 0x10
+
+// second page: refreshed on wallet wipe
+#define SECRET_BHK_OFFSET 0x2000
+#define SECRET_BHK_LEN 0x20
+
+// slot assignments
+#define SECRET_PRIVILEGED_MASTER_KEY_SLOT 0
+#define SECRET_UNPRIVILEGED_MASTER_KEY_SLOT 1
+#define SECRET_OPTIGA_SLOT 2
diff --git a/core/embed/models/T3T2/unit_properties_content.h b/core/embed/models/T3T2/unit_properties_content.h
new file mode 100644
index 00000000..3eb18d68
--- /dev/null
+++ b/core/embed/models/T3T2/unit_properties_content.h
@@ -0,0 +1,8 @@
+#pragma once
+
+// OTP device variant block layout
+// byte 0: version (always 0x01)
+#define UNIT_PROPERTIES_BYTE_COLOR 1
+#define UNIT_PROPERTIES_BYTE_BTCONLY 2
+#define UNIT_PROPERTIES_BYTE_PACKAGING 3
+#define UNIT_PROPERTIES_BYTE_BATTERY_TYPE 4
diff --git a/core/embed/models/T3T2/vendorheader/vendor_dev_DO_NOT_SIGN.json b/core/embed/models/T3T2/vendorheader/vendor_dev_DO_NOT_SIGN.json
new file mode 100644
index 00000000..0e9b3c92
--- /dev/null
+++ b/core/embed/models/T3T2/vendorheader/vendor_dev_DO_NOT_SIGN.json
@@ -0,0 +1,21 @@
+{
+ "header_len": 1024,
+ "text": "DEV ONLY, DO NOT USE!",
+ "hw_model": "T3T2",
+ "expiry": 0,
+ "version": [0, 0],
+ "sig_m": 2,
+ "trust": {
+ "deny_provisioning_access": true,
+ "allow_run_with_secret": true,
+ "show_vendor_string": false,
+ "require_user_click": false,
+ "red_background": false,
+ "delay": 0
+ },
+ "pubkeys": [
+ "e28a8970753332bd72fef413e6b0b2ef1b4aadda7aa2c141f233712a6876b351",
+ "d4eec1869fb1b8a4e817516ad5a931557cb56805c3eb16e8f3a803d647df7869",
+ "772c8a442b7db06e166cfbc1ccbcbcde6f3eba76a4e98ef3ffc519502237d6ef"
+ ]
+}
diff --git a/core/embed/models/T3T2/vendorheader/vendor_dev_DO_NOT_SIGN.toif b/core/embed/models/T3T2/vendorheader/vendor_dev_DO_NOT_SIGN.toif
new file mode 120000
index 00000000..22ac5e84
--- /dev/null
+++ b/core/embed/models/T3T2/vendorheader/vendor_dev_DO_NOT_SIGN.toif
@@ -0,0 +1 @@
+vendor_unsafe.toif
\ No newline at end of file
diff --git a/core/embed/models/T3T2/vendorheader/vendor_prodtest_DO_NOT_SIGN.json b/core/embed/models/T3T2/vendorheader/vendor_prodtest_DO_NOT_SIGN.json
new file mode 100644
index 00000000..b735dd7c
--- /dev/null
+++ b/core/embed/models/T3T2/vendorheader/vendor_prodtest_DO_NOT_SIGN.json
@@ -0,0 +1,21 @@
+{
+ "header_len": 1024,
+ "text": "UNSAFE, FACTORY TEST ONLY",
+ "hw_model": "T3T2",
+ "expiry": 0,
+ "version": [0, 0],
+ "sig_m": 2,
+ "trust": {
+ "deny_provisioning_access": false,
+ "allow_run_with_secret": true,
+ "show_vendor_string": false,
+ "require_user_click": false,
+ "red_background": false,
+ "delay": 0
+ },
+ "pubkeys": [
+ "e28a8970753332bd72fef413e6b0b2ef1b4aadda7aa2c141f233712a6876b351",
+ "d4eec1869fb1b8a4e817516ad5a931557cb56805c3eb16e8f3a803d647df7869",
+ "772c8a442b7db06e166cfbc1ccbcbcde6f3eba76a4e98ef3ffc519502237d6ef"
+ ]
+}
diff --git a/core/embed/models/T3T2/vendorheader/vendor_prodtest_DO_NOT_SIGN.toif b/core/embed/models/T3T2/vendorheader/vendor_prodtest_DO_NOT_SIGN.toif
new file mode 120000
index 00000000..22ac5e84
--- /dev/null
+++ b/core/embed/models/T3T2/vendorheader/vendor_prodtest_DO_NOT_SIGN.toif
@@ -0,0 +1 @@
+vendor_unsafe.toif
\ No newline at end of file
diff --git a/core/embed/models/T3T2/vendorheader/vendor_unsafe.json b/core/embed/models/T3T2/vendorheader/vendor_unsafe.json
new file mode 100644
index 00000000..be44ee68
--- /dev/null
+++ b/core/embed/models/T3T2/vendorheader/vendor_unsafe.json
@@ -0,0 +1,21 @@
+{
+ "header_len": 1024,
+ "text": "UNSAFE, DO NOT USE!",
+ "hw_model": "T3T2",
+ "expiry": 0,
+ "version": [0, 0],
+ "sig_m": 2,
+ "trust": {
+ "deny_provisioning_access": true,
+ "allow_run_with_secret": false,
+ "show_vendor_string": true,
+ "require_user_click": true,
+ "red_background": true,
+ "delay": 1
+ },
+ "pubkeys": [
+ "e28a8970753332bd72fef413e6b0b2ef1b4aadda7aa2c141f233712a6876b351",
+ "d4eec1869fb1b8a4e817516ad5a931557cb56805c3eb16e8f3a803d647df7869",
+ "772c8a442b7db06e166cfbc1ccbcbcde6f3eba76a4e98ef3ffc519502237d6ef"
+ ]
+}
diff --git a/core/embed/models/T3T2/vendorheader/vendor_unsafe.toif b/core/embed/models/T3T2/vendorheader/vendor_unsafe.toif
new file mode 100644
index 00000000..24b655da
Binary files /dev/null and b/core/embed/models/T3T2/vendorheader/vendor_unsafe.toif differ
diff --git a/core/embed/models/T3T2/vendorheader/vendorheader_dev_DO_NOT_SIGN_signed_dev.bin b/core/embed/models/T3T2/vendorheader/vendorheader_dev_DO_NOT_SIGN_signed_dev.bin
new file mode 100644
index 00000000..3f02ee74
Binary files /dev/null and b/core/embed/models/T3T2/vendorheader/vendorheader_dev_DO_NOT_SIGN_signed_dev.bin differ
diff --git a/core/embed/models/T3T2/vendorheader/vendorheader_dev_DO_NOT_SIGN_unsigned.bin b/core/embed/models/T3T2/vendorheader/vendorheader_dev_DO_NOT_SIGN_unsigned.bin
new file mode 100644
index 00000000..5b74b804
Binary files /dev/null and b/core/embed/models/T3T2/vendorheader/vendorheader_dev_DO_NOT_SIGN_unsigned.bin differ
diff --git a/core/embed/models/T3T2/vendorheader/vendorheader_prodtest_DO_NOT_SIGN_signed_dev.bin b/core/embed/models/T3T2/vendorheader/vendorheader_prodtest_DO_NOT_SIGN_signed_dev.bin
new file mode 100644
index 00000000..c924cb98
Binary files /dev/null and b/core/embed/models/T3T2/vendorheader/vendorheader_prodtest_DO_NOT_SIGN_signed_dev.bin differ
diff --git a/core/embed/models/T3T2/vendorheader/vendorheader_prodtest_DO_NOT_SIGN_unsigned.bin b/core/embed/models/T3T2/vendorheader/vendorheader_prodtest_DO_NOT_SIGN_unsigned.bin
new file mode 100644
index 00000000..e1dd6019
Binary files /dev/null and b/core/embed/models/T3T2/vendorheader/vendorheader_prodtest_DO_NOT_SIGN_unsigned.bin differ
diff --git a/core/embed/models/T3T2/vendorheader/vendorheader_unsafe_signed_dev.bin b/core/embed/models/T3T2/vendorheader/vendorheader_unsafe_signed_dev.bin
new file mode 100644
index 00000000..71fe30c3
Binary files /dev/null and b/core/embed/models/T3T2/vendorheader/vendorheader_unsafe_signed_dev.bin differ
diff --git a/core/embed/models/T3T2/vendorheader/vendorheader_unsafe_unsigned.bin b/core/embed/models/T3T2/vendorheader/vendorheader_unsafe_unsigned.bin
new file mode 100644
index 00000000..7fe153bb
Binary files /dev/null and b/core/embed/models/T3T2/vendorheader/vendorheader_unsafe_unsigned.bin differ
diff --git a/core/embed/models/T3T2/versions.h b/core/embed/models/T3T2/versions.h
new file mode 100644
index 00000000..c2a24c8e
--- /dev/null
+++ b/core/embed/models/T3T2/versions.h
@@ -0,0 +1,4 @@
+
+#define BOOTLOADER_MONOTONIC_VERSION 2
+#define FIRMWARE_MONOTONIC_VERSION 2
+#define SECMON_MONOTONIC_VERSION 1
diff --git a/core/embed/models/build.rs b/core/embed/models/build.rs
index 85548456..9b6eb361 100644
--- a/core/embed/models/build.rs
+++ b/core/embed/models/build.rs
@@ -10,6 +10,8 @@ fn main() -> Result<()> {
"T3B1"
} else if cfg!(feature = "model_t3t1") {
"T3T1"
+ } else if cfg!(feature = "model_t3t2") {
+ "T3T2"
} else if cfg!(feature = "model_t3w1") {
"T3W1"
} else if cfg!(feature = "model_d001") {
@@ -166,6 +168,8 @@ fn main() -> Result<()> {
define_model_t3b1(lib, &board_header)?;
} else if cfg!(feature = "model_t3t1") {
define_model_t3t1(lib, &board_header)?;
+ } else if cfg!(feature = "model_t3t2") {
+ define_model_t3t2(lib, &board_header)?;
} else if cfg!(feature = "model_t3w1") {
define_model_t3w1(lib, &board_header)?;
} else if cfg!(feature = "model_d001") {
@@ -288,6 +292,28 @@ fn define_model_t3t1(lib: &mut CLibrary, board_header: &str) -> Result<()> {
Ok(())
}
+fn define_model_t3t2(lib: &mut CLibrary, board_header: &str) -> Result<()> {
+ lib.add_defines([
+ ("TREZOR_MODEL_T3T2", None),
+ ("TREZOR_BOARD", Some(board_header)),
+ ("MODEL_HEADER", Some("\"T3T2/model_T3T2.h\"")),
+ ("VERSIONS_HEADER", Some("\"T3T2/versions.h\"")),
+ ("OTP_LAYOUT_HEADER", Some("\"T3T2/otp_layout.h\"")),
+ (
+ "UNIT_PROPERTIES_CONTENT_HEADER",
+ Some("\"T3T2/unit_properties_content.h\""),
+ ),
+ ("HW_MODEL", Some(model_to_num("T3T2").to_string().as_str())),
+ ("HW_REVISION", Some("0")),
+ ("USE_BOOTARGS_RSOD", Some("1")),
+ ("LSI_VALUE", Some("250")),
+ ("USE_LSI", Some("1")),
+ ("USE_OEM_KEYS_CHECK", Some("1")),
+ ]);
+
+ Ok(())
+}
+
fn define_model_t3b1(lib: &mut CLibrary, board_header: &str) -> Result<()> {
lib.add_defines([
("TREZOR_MODEL_T3B1", None),
diff --git a/core/embed/xtask/src/model.rs b/core/embed/xtask/src/model.rs
index c4820023..2646be33 100644
--- a/core/embed/xtask/src/model.rs
+++ b/core/embed/xtask/src/model.rs
@@ -20,6 +20,8 @@ pub enum Model {
T3B1,
#[value(name = "t3t1")]
T3T1,
+ #[value(name = "t3t2")]
+ T3T2,
#[value(name = "t3w1")]
T3W1,
}
@@ -42,6 +44,7 @@ impl Model {
Model::T2B1 => "T2B1",
Model::T3B1 => "T3B1",
Model::T3T1 => "T3T1",
+ Model::T3T2 => "T3T2",
Model::T3W1 => "T3W1",
}
}
diff --git a/python/src/trezorlib/cli/firmware.py b/python/src/trezorlib/cli/firmware.py
index 34c0040d..f5fe1f6c 100644
--- a/python/src/trezorlib/cli/firmware.py
+++ b/python/src/trezorlib/cli/firmware.py
@@ -48,6 +48,7 @@ MODEL_CHOICE = ChoiceType(
"T2T1": models.T2T1,
"T2B1": models.T2B1,
"T3T1": models.T3T1,
+ "T3T2": models.T3T2,
"T3B1": models.T3B1,
"T3W1": models.T3W1,
# aliases
diff --git a/python/src/trezorlib/debuglink.py b/python/src/trezorlib/debuglink.py
index e270268f..310607e9 100644
--- a/python/src/trezorlib/debuglink.py
+++ b/python/src/trezorlib/debuglink.py
@@ -86,7 +86,7 @@ class LayoutType(Enum):
return cls.Bolt
if model in (models.T2B1, models.T3B1):
return cls.Caesar
- if model in (models.T3T1,):
+ if model in (models.T3T1, models.T3T2):
return cls.Delizia
if model in (models.T3W1,):
return cls.Eckhart
@@ -103,7 +103,7 @@ class LayoutType(Enum):
return cls.Bolt
if internal_name in (models.T2B1.internal_name, models.T3B1.internal_name):
return cls.Caesar
- if internal_name in (models.T3T1.internal_name,):
+ if internal_name in (models.T3T1.internal_name, models.T3T2.internal_name):
return cls.Delizia
if internal_name in (models.T3W1.internal_name,):
return cls.Eckhart
diff --git a/python/src/trezorlib/firmware/models.py b/python/src/trezorlib/firmware/models.py
index db79704a..744e11b0 100644
--- a/python/src/trezorlib/firmware/models.py
+++ b/python/src/trezorlib/firmware/models.py
@@ -35,6 +35,7 @@ class Model(Enum):
T2T1 = b"T2T1"
T3B1 = b"T3B1"
T3T1 = b"T3T1"
+ T3T2 = b"T3T2"
T3W1 = b"T3W1"
D001 = b"D001"
D002 = b"D002"
@@ -303,6 +304,35 @@ T3T1 = ModelKeys(
nrf_keys=(),
)
+T3T2 = ModelKeys(
+ production=True,
+ boardloader_keys=[
+ bytes.fromhex(key)
+ for key in (
+ # todo replace with production keys
+ "76af426e61406bad7c077b409c66fde39fb817919313ae1e4c02535c80beed96",
+ "619751dc8d2d09d7e5dfb99e41f606debdf419f85a8143e8e5399ea67a3988c7",
+ "abf94b6615a7dde2a871f7d62c38efc7d9d8f6010d8846bee636e4f3e658a38c",
+ )
+ ],
+ boardloader_sigs_needed=2,
+ bootloader_keys=[
+ bytes.fromhex(key)
+ for key in (
+ # todo replace with production keys
+ "338b949b7e3b26470d4fe3696fd6fff28757265d14cca48ebf2db97b4f5bc039",
+ "28682027730b783201b05a8c9d11685447c17297db71b8a60dc693a44610751d",
+ "9fbf31b4e351a4cc81c75995b2257f0a7169268da5a44e94b6a5590d434e32da",
+ )
+ ],
+ bootloader_sigs_needed=2,
+ firmware_keys=(),
+ firmware_sigs_needed=-1,
+ secmon_keys=(),
+ secmon_sigs_needed=-1,
+ nrf_keys=(),
+)
+
T3B1 = ModelKeys(
production=True,
boardloader_keys=[
@@ -430,6 +460,12 @@ T3T1_HASH_PARAMS = FirmwareHashParameters(
padding_byte=None,
)
+T3T2_HASH_PARAMS = FirmwareHashParameters(
+ hash_function=hashlib.sha256,
+ chunk_size=1024 * 128,
+ padding_byte=None,
+)
+
T3B1_HASH_PARAMS = FirmwareHashParameters(
hash_function=hashlib.sha256,
chunk_size=1024 * 128,
@@ -453,6 +489,7 @@ MODEL_MAP = {
Model.T2T1: T2T1,
Model.T2B1: T2B1,
Model.T3T1: T3T1,
+ Model.T3T2: T3T2,
Model.T3B1: T3B1,
Model.T3W1: T3W1,
Model.D001: TREZOR_CORE_DEV,
@@ -465,6 +502,7 @@ MODEL_MAP_DEV = {
Model.T2T1: TREZOR_CORE_DEV,
Model.T2B1: TREZOR_CORE_DEV,
Model.T3T1: TREZOR_CORE_DEV,
+ Model.T3T2: TREZOR_CORE_DEV,
Model.T3B1: TREZOR_CORE_DEV,
Model.T3W1: TREZOR_CORE_DEV,
Model.D001: TREZOR_CORE_DEV,
@@ -477,6 +515,7 @@ MODEL_HASH_PARAMS_MAP = {
Model.T2T1: T2T1_HASH_PARAMS,
Model.T2B1: T2T1_HASH_PARAMS,
Model.T3T1: T3T1_HASH_PARAMS,
+ Model.T3T2: T3T2_HASH_PARAMS,
Model.T3B1: T3B1_HASH_PARAMS,
Model.T3W1: T3W1_HASH_PARAMS,
Model.D001: T2T1_HASH_PARAMS,
diff --git a/python/src/trezorlib/models.py b/python/src/trezorlib/models.py
index 6479dc05..9fffb94d 100644
--- a/python/src/trezorlib/models.py
+++ b/python/src/trezorlib/models.py
@@ -81,6 +81,15 @@ T3T1 = TrezorModel(
default_mapping=mapping.DEFAULT_MAPPING,
)
+T3T2 = TrezorModel(
+ name="T3T2",
+ internal_name="T3T2",
+ minimum_version=(2, 3, 0),
+ vendors=VENDORS,
+ usb_ids=(USBID_TREZOR_CORE, USBID_TREZOR_CORE_BOOTLOADER),
+ default_mapping=mapping.DEFAULT_MAPPING,
+)
+
T3B1 = TrezorModel(
name="Safe 3",
internal_name="T3B1",
@@ -138,7 +147,7 @@ TREZOR_DISC2 = DISC2
TREZOR_DISC3 = DISC3
LEGACY_MODELS = frozenset({T1B1})
-CORE_MODELS = frozenset({T2T1, T2B1, T3T1, T3B1, T3W1, DISC1, DISC2, DISC3})
+CORE_MODELS = frozenset({T2T1, T2B1, T3T1, T3T2, T3B1, T3W1, DISC1, DISC2, DISC3})
ALL_MODELS = LEGACY_MODELS | CORE_MODELS
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.