feat(core): add support for D003 nucleo board
What changed, and why it matters
This commit adds support for a new Trezor development board called D003 (based on an STM32U5 Nucleo evaluation kit). It is purely an enablement change for internal hardware bring-up: new configuration files, memory layout, bootloader hash, vendor headers, and build-system entries. There is no indication it fixes a security bug or introduces a vulnerability in shipping products.
No security action required. Treat as normal hardware-support commit. If reviewing further, verify the D003 memory layout and bootloader hash match the intended STM32U5A5 reference design, and ensure the new vendor headers remain marked DO_NOT_SIGN in production tooling.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The change introduces the D003 model target for the NUCLEO-U5A5ZJ-Q development board. It adds model-specific headers, TOML/JSON vendor headers, a prebuilt bootloader binary with recorded hashes, memory map, linker script, OTP/secret layouts, and registration in Rust/Python model enums. Two small C preprocessor fixes change bitwise OR (|) to logical OR (||) in STM32U5 option-byte and TrustZone conditionals so the D003’s STM32U5A5 variant is handled correctly. These are correctness fixes for a new target, not patches for an exploitable flaw.
Changed components
core/embed/models (D003 model support)core/embed/sec/option_bytes/stm32u5/option_bytes.ccore/embed/sys/trustzone/stm32u5/trustzone.ccore/embed/xtask/src/model.rspython/src/trezorlib/firmware/models.pypython/src/trezorlib/models.pyInspect captured patch +490 / −3
diff --git a/core/embed/models/Cargo.toml b/core/embed/models/Cargo.toml
index c15b5195..ff376b77 100644
--- a/core/embed/models/Cargo.toml
+++ b/core/embed/models/Cargo.toml
@@ -19,6 +19,7 @@ xbuild.workspace = true
model_d001 = []
model_d002 = []
+model_d003 = []
model_t2t1 = []
model_t2b1 = []
model_t3b1 = []
diff --git a/core/embed/models/D003/boards/nucleo.toml b/core/embed/models/D003/boards/nucleo.toml
new file mode 100644
index 00000000..74f66655
--- /dev/null
+++ b/core/embed/models/D003/boards/nucleo.toml
@@ -0,0 +1,10 @@
+header = "D003/boards/nucleo_u5a5zj_q.h"
+
+# Headless development board: no display, touch or SD-card hardware.
+# The "none" drivers satisfy the display/touch APIs with no-ops. (The touch UI
+# stack is still compiled because the bolt layout depends on it.)
+[display]
+driver = "io/display_none"
+
+[touch]
+driver = "io/touch_none"
diff --git a/core/embed/models/D003/boards/nucleo_u5a5zj_q.h b/core/embed/models/D003/boards/nucleo_u5a5zj_q.h
new file mode 100644
index 00000000..5dc7e2d6
--- /dev/null
+++ b/core/embed/models/D003/boards/nucleo_u5a5zj_q.h
@@ -0,0 +1,34 @@
+/*
+ * 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/>.
+ */
+
+// Board definition for the NUCLEO-U5A5ZJ-Q development board (STM32U5A5ZJ).
+//
+// This is a headless development target: the board has no display, touch
+// panel or SD-card hardware. Only the bare essentials needed to bring up the
+// boot chain (boardloader -> bootloader) and communicate over USB are defined
+// here. Peripheral pin mappings (LEDs, button, UART) can be added as the
+// bring-up progresses.
+
+#ifndef NUCLEO_U5A5ZJ_Q_H_
+#define NUCLEO_U5A5ZJ_Q_H_
+
+// The Nucleo board is powered from the ST-LINK USB at 3.3 V.
+#define VDD_3V3 1
+
+#endif // NUCLEO_U5A5ZJ_Q_H_
diff --git a/core/embed/models/D003/bootloaders/bootloader_D003_devel.bin b/core/embed/models/D003/bootloaders/bootloader_D003_devel.bin
new file mode 100755
index 00000000..f4ef507a
Binary files /dev/null and b/core/embed/models/D003/bootloaders/bootloader_D003_devel.bin differ
diff --git a/core/embed/models/D003/bootloaders/bootloader_hashes.h b/core/embed/models/D003/bootloaders/bootloader_hashes.h
new file mode 100644
index 00000000..839d610a
--- /dev/null
+++ b/core/embed/models/D003/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_D003_devel.bin version 2.1.18.0
+#define BOOTLOADER_D003_DEVEL_00 {0x52, 0xdf, 0x47, 0x25, 0x57, 0xf1, 0x98, 0xb0, 0x1f, 0x3e, 0x6c, 0xf3, 0xac, 0xb9, 0x01, 0x57, 0xf3, 0x1d, 0xde, 0x02, 0x6a, 0xc6, 0x6b, 0x92, 0xc2, 0x32, 0xbf, 0xc2, 0x9e, 0xc0, 0xf2, 0xbe}
+#define BOOTLOADER_D003_DEVEL_FF {0xdf, 0x22, 0x26, 0x2b, 0x0d, 0xe1, 0x6d, 0x3d, 0xfd, 0x9b, 0xad, 0x0f, 0x84, 0x25, 0x27, 0x37, 0x8c, 0xd7, 0x27, 0x00, 0x45, 0x27, 0xa6, 0x1e, 0x36, 0xf0, 0xe8, 0x3b, 0xd8, 0x6f, 0x0a, 0xbf}
+
+// clang-format on
+
+#endif
diff --git a/core/embed/models/D003/config.mk b/core/embed/models/D003/config.mk
new file mode 100644
index 00000000..61898195
--- /dev/null
+++ b/core/embed/models/D003/config.mk
@@ -0,0 +1,3 @@
+MCU = STM32U5
+OPENOCD_TARGET = target/stm32u5x.cfg
+LAYOUT_FEATURE = layout_bolt
diff --git a/core/embed/models/D003/memory.h b/core/embed/models/D003/memory.h
new file mode 100644
index 00000000..4d525bec
--- /dev/null
+++ b/core/embed/models/D003/memory.h
@@ -0,0 +1,107 @@
+/*
+ * 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 (12 * 8 * 1024) // 96 kB
+#define BOARDLOADER_SECTOR_START 0x2
+#define BOARDLOADER_SECTOR_END 0xD
+
+#define BOARDCAPS_START (0x0C01BF00)
+#define BOARDCAPS_MAXSIZE 0x100
+
+// Update control block
+#define BOOTUCB_START (0x0C01C000)
+#define BOOTUCB_MAXSIZE (1 * 8 * 1024) // 8 kB
+#define BOOTUCB_SECTOR_START 0xE
+#define BOOTUCB_SECTOR_END 0xE
+
+// Non-boardloader area (includes bootloader, firmware, assets and storage)
+#define NONBOARDLOADER_START (0x0C01E000)
+#define NONBOARDLOADER_MAXSIZE (497 * 8 * 1024) // 3976 kB
+#define NONBOARDLOADER_SECTOR_START 0xF
+#define NONBOARDLOADER_SECTOR_END 0x1FF
+
+#define BOOTLOADER_START (0x0C01E000)
+#define BOOTLOADER_MAXSIZE (32 * 8 * 1024) // 256 kB
+#define BOOTLOADER_SECTOR_START 0xF
+#define BOOTLOADER_SECTOR_END 0x2E
+
+#define FIRMWARE_START (0x0C05E000)
+#define FIRMWARE_MAXSIZE (417 * 8 * 1024) // 3336 kB
+#define FIRMWARE_SECTOR_START 0x2F
+#define FIRMWARE_SECTOR_END 0x1CF
+
+// overlaps with assets and storage
+#define BOOTUPDATE_START (0x0C3A0000)
+#define BOOTUPDATE_MAXSIZE (48 * 8 * 1024) // 384 kB
+#define BOOTUPDATE_SECTOR_START 0x1D0
+#define BOOTUPDATE_SECTOR_END 0x1FF
+
+#define ASSETS_START (0x0C3A0000)
+#define ASSETS_MAXSIZE (16 * 8 * 1024) // 128 kB
+#define ASSETS_SECTOR_START 0x1D0
+#define ASSETS_SECTOR_END 0x1DF
+
+#define STORAGE_1_START (0x0C3C0000)
+#define STORAGE_1_MAXSIZE (16 * 8 * 1024) // 128 kB
+#define STORAGE_1_SECTOR_START 0x1E0
+#define STORAGE_1_SECTOR_END 0x1EF
+
+#define STORAGE_2_START (0x0C3E0000)
+#define STORAGE_2_MAXSIZE (16 * 8 * 1024) // 128 kB
+#define STORAGE_2_SECTOR_START 0x1F0
+#define STORAGE_2_SECTOR_END 0x1FF
+
+// RAM layout
+#define BOOTARGS_START (0x30000000)
+#define BOOTARGS_SIZE 0x200
+
+#define FB1_RAM_START (0x30000200)
+#define FB1_RAM_SIZE (768 * 1024 - 512)
+
+#define MAIN_RAM_START (0x300C0000)
+#define MAIN_RAM_SIZE (64 * 1024)
+
+#define FB2_RAM_START (0x300D0000)
+#define FB2_RAM_SIZE (768 * 1024)
+
+#define AUX1_RAM_START (0x30190000)
+#define AUX1_RAM_SIZE (896 * 1024)
+
+// misc
+#define CODE_ALIGNMENT 0x400
+#define COREAPP_ALIGNMENT 0x2000
diff --git a/core/embed/models/D003/memory.ld b/core/embed/models/D003/memory.ld
new file mode 100644
index 00000000..ff4e3aae
--- /dev/null
+++ b/core/embed/models/D003/memory.ld
@@ -0,0 +1,61 @@
+/* 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 = 0x18000;
+BOARDLOADER_SECTOR_START = 0x2;
+BOARDLOADER_SECTOR_END = 0xd;
+BOARDCAPS_START = 0xc01bf00;
+BOARDCAPS_MAXSIZE = 0x100;
+BOOTUCB_START = 0xc01c000;
+BOOTUCB_MAXSIZE = 0x2000;
+BOOTUCB_SECTOR_START = 0xe;
+BOOTUCB_SECTOR_END = 0xe;
+NONBOARDLOADER_START = 0xc01e000;
+NONBOARDLOADER_MAXSIZE = 0x3e2000;
+NONBOARDLOADER_SECTOR_START = 0xf;
+NONBOARDLOADER_SECTOR_END = 0x1ff;
+BOOTLOADER_START = 0xc01e000;
+BOOTLOADER_MAXSIZE = 0x40000;
+BOOTLOADER_SECTOR_START = 0xf;
+BOOTLOADER_SECTOR_END = 0x2e;
+FIRMWARE_START = 0xc05e000;
+FIRMWARE_MAXSIZE = 0x342000;
+FIRMWARE_SECTOR_START = 0x2f;
+FIRMWARE_SECTOR_END = 0x1cf;
+BOOTUPDATE_START = 0xc3a0000;
+BOOTUPDATE_MAXSIZE = 0x60000;
+BOOTUPDATE_SECTOR_START = 0x1d0;
+BOOTUPDATE_SECTOR_END = 0x1ff;
+ASSETS_START = 0xc3a0000;
+ASSETS_MAXSIZE = 0x20000;
+ASSETS_SECTOR_START = 0x1d0;
+ASSETS_SECTOR_END = 0x1df;
+STORAGE_1_START = 0xc3c0000;
+STORAGE_1_MAXSIZE = 0x20000;
+STORAGE_1_SECTOR_START = 0x1e0;
+STORAGE_1_SECTOR_END = 0x1ef;
+STORAGE_2_START = 0xc3e0000;
+STORAGE_2_MAXSIZE = 0x20000;
+STORAGE_2_SECTOR_START = 0x1f0;
+STORAGE_2_SECTOR_END = 0x1ff;
+BOOTARGS_START = 0x30000000;
+BOOTARGS_SIZE = 0x200;
+FB1_RAM_START = 0x30000200;
+FB1_RAM_SIZE = 0xbfe00;
+MAIN_RAM_START = 0x300c0000;
+MAIN_RAM_SIZE = 0x10000;
+FB2_RAM_START = 0x300d0000;
+FB2_RAM_SIZE = 0xc0000;
+AUX1_RAM_START = 0x30190000;
+AUX1_RAM_SIZE = 0xe0000;
+CODE_ALIGNMENT = 0x400;
+COREAPP_ALIGNMENT = 0x2000;
diff --git a/core/embed/models/D003/model.toml b/core/embed/models/D003/model.toml
new file mode 100644
index 00000000..183fce69
--- /dev/null
+++ b/core/embed/models/D003/model.toml
@@ -0,0 +1,13 @@
+mcu = "stm32u5a"
+default_board = "nucleo"
+secmon = false
+
+features = [
+ "hash_processor",
+ "lockable_bootloader",
+ "secret",
+ "secure_aes",
+ "secure_mode",
+ "tamper",
+ "layout_bolt",
+]
diff --git a/core/embed/models/D003/model_D003.h b/core/embed/models/D003/model_D003.h
new file mode 100644
index 00000000..d6e8a983
--- /dev/null
+++ b/core/embed/models/D003/model_D003.h
@@ -0,0 +1,55 @@
+/*
+ * 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 <rtl/sizedefs.h>
+#include "bootloaders/bootloader_hashes.h"
+#include "secret_layout.h"
+
+#define MODEL_NAME "D003"
+#define MODEL_FULL_NAME "Trezor DIY 3"
+#define MODEL_INTERNAL_NAME "D003"
+#define MODEL_INTERNAL_NAME_TOKEN D003
+#define MODEL_NAME_QSTR MP_QSTR_D003
+#define MODEL_INTERNAL_NAME_QSTR MP_QSTR_D003
+#define MODEL_USB_MANUFACTURER "Trezor DIY"
+#define MODEL_USB_PRODUCT MODEL_FULL_NAME
+#define MODEL_HOMESCREEN_MAXSIZE 65536
+
+/*** Development board uses DEV keys in any build variant ***/
+#define MODEL_BOARDLOADER_KEYS \
+ (const uint8_t *)"\xdb\x99\x5f\xe2\x51\x69\xd1\x41\xca\xb9\xbb\xba\x92\xba\xa0\x1f\x9f\x2e\x1e\xce\x7d\xf4\xcb\x2a\xc0\x51\x90\xf3\x7f\xcc\x1f\x9d", \
+ (const uint8_t *)"\x21\x52\xf8\xd1\x9b\x79\x1d\x24\x45\x32\x42\xe1\x5f\x2e\xab\x6c\xb7\xcf\xfa\x7b\x6a\x5e\xd3\x00\x97\x96\x0e\x06\x98\x81\xdb\x12", \
+ (const uint8_t *)"\x22\xfc\x29\x77\x92\xf0\xb6\xff\xc0\xbf\xcf\xdb\x7e\xdb\x0c\x0a\xa1\x4e\x02\x5a\x36\x5e\xc0\xe3\x42\xe8\x6e\x38\x29\xcb\x74\xb6",
+
+#define MODEL_BOOTLOADER_KEYS \
+ (const uint8_t *)"\xd7\x59\x79\x3b\xbc\x13\xa2\x81\x9a\x82\x7c\x76\xad\xb6\xfb\xa8\xa4\x9a\xee\x00\x7f\x49\xf2\xd0\x99\x2d\x99\xb8\x25\xad\x2c\x48", \
+ (const uint8_t *)"\x63\x55\x69\x1c\x17\x8a\x8f\xf9\x10\x07\xa7\x47\x8a\xfb\x95\x5e\xf7\x35\x2c\x63\xe7\xb2\x57\x03\x98\x4c\xf7\x8b\x26\xe2\x1a\x56", \
+ (const uint8_t *)"\xee\x93\xa4\xf6\x6f\x8d\x16\xb8\x19\xbb\x9b\xeb\x9f\xfc\xcd\xfc\xdc\x14\x12\xe8\x7f\xee\x6a\x32\x4c\x2a\x99\xa1\xe0\xe6\x71\x48",
+
+#define IMAGE_CHUNK_SIZE SIZE_256K
+#define IMAGE_HASH_SHA256
+
+#define DISPLAY_JUMP_BEHAVIOR DISPLAY_RESET_CONTENT
+
+#define NORCOW_SECTOR_SIZE (16 * 8 * 1024) // 128 kB
+#define NORCOW_MIN_VERSION 0x00000006
+
+#include "memory.h"
diff --git a/core/embed/models/D003/otp_layout.h b/core/embed/models/D003/otp_layout.h
new file mode 100644
index 00000000..139c63de
--- /dev/null
+++ b/core/embed/models/D003/otp_layout.h
@@ -0,0 +1,13 @@
+#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
+#define FLASH_OTP_BLOCK_MANUFACTURING_LOCK 9
diff --git a/core/embed/models/D003/secret_layout.h b/core/embed/models/D003/secret_layout.h
new file mode 100644
index 00000000..2e776a39
--- /dev/null
+++ b/core/embed/models/D003/secret_layout.h
@@ -0,0 +1,39 @@
+/*
+ * 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 0
+
+// first page: static
+#define SECRET_HEADER_OFFSET 0x00
+#define SECRET_HEADER_LEN 0x10
+
+#define SECRET_MONOTONIC_COUNTER_0_OFFSET 0x10
+#define SECRET_MONOTONIC_COUNTER_0_LEN 0x400
+
+#define SECRET_MONOTONIC_COUNTER_1_OFFSET (0x410)
+#define SECRET_MONOTONIC_COUNTER_1_LEN 0x400
+
+#define SECRET_MONOTONIC_COUNTER_2_OFFSET 0x810
+#define SECRET_MONOTONIC_COUNTER_2_LEN 0x400
+
+// second page: refreshed on wallet wipe
+#define SECRET_BHK_OFFSET 0x2000
+#define SECRET_BHK_LEN 0x20
diff --git a/core/embed/models/D003/test_bindgen_macros.txt b/core/embed/models/D003/test_bindgen_macros.txt
new file mode 100644
index 00000000..498931ce
--- /dev/null
+++ b/core/embed/models/D003/test_bindgen_macros.txt
@@ -0,0 +1,10 @@
+-DSTM32U5,
+-DTREZOR_MODEL_D003,
+-DFLASH_BIT_ACCESS=0,
+-DFLASH_BLOCK_WORDS=4,
+-DDISPLAY_RESX=240,
+-DDISPLAY_RESY=240,
+-DTREZOR_BOARD="D003/boards/nucleo_u5a5zj_q.h",
+-DMODEL_HEADER="D003/model_D003.h",
+-DOTP_LAYOUT_HEADER="D003/otp_layout.h",
+-DUNIT_PROPERTIES_CONTENT_HEADER="D003/unit_properties_content.h",
diff --git a/core/embed/models/D003/unit_properties_content.h b/core/embed/models/D003/unit_properties_content.h
new file mode 100644
index 00000000..3eb18d68
--- /dev/null
+++ b/core/embed/models/D003/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/D003/vendorheader/vendor_dev_DO_NOT_SIGN.json b/core/embed/models/D003/vendorheader/vendor_dev_DO_NOT_SIGN.json
new file mode 100644
index 00000000..4adad262
--- /dev/null
+++ b/core/embed/models/D003/vendorheader/vendor_dev_DO_NOT_SIGN.json
@@ -0,0 +1,23 @@
+{
+ "header_len": 5120,
+ "text": "DEV ONLY, DO NOT USE!",
+ "hw_model": "D003",
+ "fw_type": 2,
+ "expiry": 0,
+ "version": [0, 0],
+ "sig_m": 2,
+ "trust": {
+ "limit_runtime": false,
+ "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/D003/vendorheader/vendor_dev_DO_NOT_SIGN.toif b/core/embed/models/D003/vendorheader/vendor_dev_DO_NOT_SIGN.toif
new file mode 100644
index 00000000..3b187a70
Binary files /dev/null and b/core/embed/models/D003/vendorheader/vendor_dev_DO_NOT_SIGN.toif differ
diff --git a/core/embed/models/D003/vendorheader/vendor_prodtest_DO_NOT_SIGN.json b/core/embed/models/D003/vendorheader/vendor_prodtest_DO_NOT_SIGN.json
new file mode 100644
index 00000000..68f14c5d
--- /dev/null
+++ b/core/embed/models/D003/vendorheader/vendor_prodtest_DO_NOT_SIGN.json
@@ -0,0 +1,23 @@
+{
+ "header_len": 5120,
+ "text": "UNSAFE, DO NOT USE!",
+ "hw_model": "D003",
+ "fw_type": 4,
+ "expiry": 0,
+ "version": [0, 1],
+ "sig_m": 2,
+ "trust": {
+ "limit_runtime": false,
+ "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/D003/vendorheader/vendor_prodtest_DO_NOT_SIGN.toif b/core/embed/models/D003/vendorheader/vendor_prodtest_DO_NOT_SIGN.toif
new file mode 100644
index 00000000..8c25f0dd
Binary files /dev/null and b/core/embed/models/D003/vendorheader/vendor_prodtest_DO_NOT_SIGN.toif differ
diff --git a/core/embed/models/D003/vendorheader/vendor_unsafe.json b/core/embed/models/D003/vendorheader/vendor_unsafe.json
new file mode 100644
index 00000000..906c0f60
--- /dev/null
+++ b/core/embed/models/D003/vendorheader/vendor_unsafe.json
@@ -0,0 +1,23 @@
+{
+ "header_len": 5120,
+ "text": "UNSAFE, DO NOT USE!",
+ "hw_model": "D003",
+ "fw_type": 1,
+ "expiry": 0,
+ "version": [0, 1],
+ "sig_m": 2,
+ "trust": {
+ "limit_runtime": true,
+ "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/D003/vendorheader/vendor_unsafe.toif b/core/embed/models/D003/vendorheader/vendor_unsafe.toif
new file mode 100644
index 00000000..8c25f0dd
Binary files /dev/null and b/core/embed/models/D003/vendorheader/vendor_unsafe.toif differ
diff --git a/core/embed/models/D003/vendorheader/vendorheader_dev_DO_NOT_SIGN_signed_dev.bin b/core/embed/models/D003/vendorheader/vendorheader_dev_DO_NOT_SIGN_signed_dev.bin
new file mode 100644
index 00000000..c6642e17
Binary files /dev/null and b/core/embed/models/D003/vendorheader/vendorheader_dev_DO_NOT_SIGN_signed_dev.bin differ
diff --git a/core/embed/models/D003/vendorheader/vendorheader_dev_DO_NOT_SIGN_unsigned.bin b/core/embed/models/D003/vendorheader/vendorheader_dev_DO_NOT_SIGN_unsigned.bin
new file mode 100644
index 00000000..40b1c728
Binary files /dev/null and b/core/embed/models/D003/vendorheader/vendorheader_dev_DO_NOT_SIGN_unsigned.bin differ
diff --git a/core/embed/models/D003/vendorheader/vendorheader_prodtest_DO_NOT_SIGN_signed_dev.bin b/core/embed/models/D003/vendorheader/vendorheader_prodtest_DO_NOT_SIGN_signed_dev.bin
new file mode 100644
index 00000000..0aec76b9
Binary files /dev/null and b/core/embed/models/D003/vendorheader/vendorheader_prodtest_DO_NOT_SIGN_signed_dev.bin differ
diff --git a/core/embed/models/D003/vendorheader/vendorheader_prodtest_DO_NOT_SIGN_unsigned.bin b/core/embed/models/D003/vendorheader/vendorheader_prodtest_DO_NOT_SIGN_unsigned.bin
new file mode 100644
index 00000000..508a65ee
Binary files /dev/null and b/core/embed/models/D003/vendorheader/vendorheader_prodtest_DO_NOT_SIGN_unsigned.bin differ
diff --git a/core/embed/models/D003/vendorheader/vendorheader_unsafe_signed_dev.bin b/core/embed/models/D003/vendorheader/vendorheader_unsafe_signed_dev.bin
new file mode 100644
index 00000000..5bba4b2c
Binary files /dev/null and b/core/embed/models/D003/vendorheader/vendorheader_unsafe_signed_dev.bin differ
diff --git a/core/embed/models/D003/vendorheader/vendorheader_unsafe_signed_prod.bin b/core/embed/models/D003/vendorheader/vendorheader_unsafe_signed_prod.bin
new file mode 100644
index 00000000..c9c20ecc
Binary files /dev/null and b/core/embed/models/D003/vendorheader/vendorheader_unsafe_signed_prod.bin differ
diff --git a/core/embed/models/D003/vendorheader/vendorheader_unsafe_unsigned.bin b/core/embed/models/D003/vendorheader/vendorheader_unsafe_unsigned.bin
new file mode 100644
index 00000000..30b59bcf
Binary files /dev/null and b/core/embed/models/D003/vendorheader/vendorheader_unsafe_unsigned.bin differ
diff --git a/core/embed/models/D003/versions.h b/core/embed/models/D003/versions.h
new file mode 100644
index 00000000..8b93f26c
--- /dev/null
+++ b/core/embed/models/D003/versions.h
@@ -0,0 +1,4 @@
+
+#define BOOTLOADER_MONOTONIC_VERSION 1
+#define FIRMWARE_MONOTONIC_VERSION 1
+#define SECMON_MONOTONIC_VERSION 1
diff --git a/core/embed/models/build.rs b/core/embed/models/build.rs
index 0c990d23..85548456 100644
--- a/core/embed/models/build.rs
+++ b/core/embed/models/build.rs
@@ -16,6 +16,8 @@ fn main() -> Result<()> {
"D001"
} else if cfg!(feature = "model_d002") {
"D002"
+ } else if cfg!(feature = "model_d003") {
+ "D003"
} else {
""
};
@@ -170,6 +172,8 @@ fn main() -> Result<()> {
define_model_d001(lib, &board_header)?;
} else if cfg!(feature = "model_d002") {
define_model_d002(lib, &board_header)?;
+ } else if cfg!(feature = "model_d003") {
+ define_model_d003(lib, &board_header)?;
} else {
bail_unsupported!();
}
@@ -383,3 +387,26 @@ fn define_model_d002(lib: &mut CLibrary, board_header: &str) -> Result<()> {
Ok(())
}
+
+fn define_model_d003(lib: &mut CLibrary, board_header: &str) -> Result<()> {
+ lib.add_defines([
+ ("TREZOR_MODEL_D003", None),
+ ("TREZOR_BOARD", Some(board_header)),
+ ("MODEL_HEADER", Some("\"D003/model_D003.h\"")),
+ ("VERSIONS_HEADER", Some("\"D003/versions.h\"")),
+ ("OTP_LAYOUT_HEADER", Some("\"D003/otp_layout.h\"")),
+ (
+ "UNIT_PROPERTIES_CONTENT_HEADER",
+ Some("\"D003/unit_properties_content.h\""),
+ ),
+ ("HW_MODEL", Some(model_to_num("D003").to_string().as_str())),
+ ("HW_REVISION", Some("0")),
+ // 16 MHz HSE crystal, same as the U5G9J-DK, matching the board's
+ // CubeMX clock configuration (160 MHz SYSCLK).
+ ("HSE_VALUE", Some("16000000")),
+ ("USE_HSE", Some("1")),
+ ("USE_BOOTARGS_RSOD", Some("1")),
+ ]);
+
+ Ok(())
+}
diff --git a/core/embed/sec/option_bytes/stm32u5/option_bytes.c b/core/embed/sec/option_bytes/stm32u5/option_bytes.c
index 4215ffe9..2edfa98e 100644
--- a/core/embed/sec/option_bytes/stm32u5/option_bytes.c
+++ b/core/embed/sec/option_bytes/stm32u5/option_bytes.c
@@ -47,7 +47,7 @@
#error "VDD_3V3 or VDD_1V8 must be defined"
#endif
-#if defined STM32U5A9xx | defined STM32U5G9xx | defined STM32U5A5xx
+#if defined STM32U5A9xx || defined STM32U5G9xx || defined STM32U5A5xx
#define WRP_DEFAULT_VALUE 0xFF00FFFF
#define SEC_WM1R1_DEFAULT_VALUE 0xFF00FF00
#define SEC_WM1R2_DEFAULT_VALUE 0x7F007F00
diff --git a/core/embed/sys/trustzone/stm32u5/trustzone.c b/core/embed/sys/trustzone/stm32u5/trustzone.c
index 8964d3ba..05981fd4 100644
--- a/core/embed/sys/trustzone/stm32u5/trustzone.c
+++ b/core/embed/sys/trustzone/stm32u5/trustzone.c
@@ -79,7 +79,7 @@ sram_region_t g_sram_regions[] = {
{SRAM1_BASE, SRAM1_BASE + SRAM1_SIZE, GTZC_MPCBB1},
{SRAM2_BASE, SRAM2_BASE + SRAM2_SIZE, GTZC_MPCBB2},
{SRAM3_BASE, SRAM3_BASE + SRAM3_SIZE, GTZC_MPCBB3},
-#if defined STM32U5A9xx | defined STM32U5G9xx | defined STM32U5A5xx
+#if defined STM32U5A9xx || defined STM32U5G9xx || defined STM32U5A5xx
{SRAM5_BASE, SRAM5_BASE + SRAM5_SIZE, GTZC_MPCBB5},
#endif
#if defined STM32U5G9xx
diff --git a/core/embed/xtask/src/model.rs b/core/embed/xtask/src/model.rs
index 9bcf262b..c4820023 100644
--- a/core/embed/xtask/src/model.rs
+++ b/core/embed/xtask/src/model.rs
@@ -10,6 +10,8 @@ pub enum Model {
D001,
#[value(name = "d002")]
D002,
+ #[value(name = "d003")]
+ D003,
#[value(name = "t2t1")]
T2T1,
#[value(name = "t2b1")]
@@ -35,6 +37,7 @@ impl Model {
match self {
Model::D001 => "D001",
Model::D002 => "D002",
+ Model::D003 => "D003",
Model::T2T1 => "T2T1",
Model::T2B1 => "T2B1",
Model::T3B1 => "T3B1",
diff --git a/python/src/trezorlib/firmware/models.py b/python/src/trezorlib/firmware/models.py
index 712d7afa..db79704a 100644
--- a/python/src/trezorlib/firmware/models.py
+++ b/python/src/trezorlib/firmware/models.py
@@ -38,6 +38,7 @@ class Model(Enum):
T3W1 = b"T3W1"
D001 = b"D001"
D002 = b"D002"
+ D003 = b"D003"
# legacy aliases
ONE = b"T1B1"
@@ -45,6 +46,7 @@ class Model(Enum):
R = b"T2B1"
DISC1 = b"D001"
DISC2 = b"D002"
+ DISC3 = b"D003"
@classmethod
def from_hw_model(cls, hw_model: Self | bytes) -> Model:
@@ -455,6 +457,7 @@ MODEL_MAP = {
Model.T3W1: T3W1,
Model.D001: TREZOR_CORE_DEV,
Model.D002: TREZOR_CORE_DEV,
+ Model.D003: TREZOR_CORE_DEV,
}
MODEL_MAP_DEV = {
@@ -466,6 +469,7 @@ MODEL_MAP_DEV = {
Model.T3W1: TREZOR_CORE_DEV,
Model.D001: TREZOR_CORE_DEV,
Model.D002: TREZOR_CORE_DEV,
+ Model.D003: TREZOR_CORE_DEV,
}
MODEL_HASH_PARAMS_MAP = {
@@ -477,6 +481,7 @@ MODEL_HASH_PARAMS_MAP = {
Model.T3W1: T3W1_HASH_PARAMS,
Model.D001: T2T1_HASH_PARAMS,
Model.D002: D002_HASH_PARAMS,
+ Model.D003: D002_HASH_PARAMS,
}
# deprecated aliases -- don't add more
@@ -499,3 +504,5 @@ D001 = TREZOR_CORE_DEV
D001_DEV = TREZOR_CORE_DEV
D002 = TREZOR_CORE_DEV
D002_DEV = TREZOR_CORE_DEV
+D003 = TREZOR_CORE_DEV
+D003_DEV = TREZOR_CORE_DEV
diff --git a/python/src/trezorlib/models.py b/python/src/trezorlib/models.py
index a6022437..6479dc05 100644
--- a/python/src/trezorlib/models.py
+++ b/python/src/trezorlib/models.py
@@ -117,6 +117,15 @@ DISC2 = TrezorModel(
default_mapping=mapping.DEFAULT_MAPPING,
)
+DISC3 = TrezorModel(
+ name="DISC3",
+ internal_name="D003",
+ minimum_version=(2, 3, 0),
+ vendors=VENDORS,
+ usb_ids=(USBID_TREZOR_CORE, USBID_TREZOR_CORE_BOOTLOADER),
+ default_mapping=mapping.DEFAULT_MAPPING,
+)
+
# ==== model based names ====
TREZOR_ONE = T1B1
@@ -126,9 +135,10 @@ TREZOR_SAFE3 = T2B1
TREZOR_SAFE5 = T3T1
TREZOR_DISC1 = DISC1
TREZOR_DISC2 = DISC2
+TREZOR_DISC3 = DISC3
LEGACY_MODELS = frozenset({T1B1})
-CORE_MODELS = frozenset({T2T1, T2B1, T3T1, T3B1, T3W1, DISC1, DISC2})
+CORE_MODELS = frozenset({T2T1, T2B1, T3T1, 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.