1. Тема дня
Сегодня разбираем механизмы безопасности:
Secure Boot — разрешает запуск только доверенного firmware
Flash Encryption — скрывает содержимое внешней Flash
TrustZone — изолирует код и данные во время выполнения
Secure Storage — защищает ключи и секретные параметры
Anti-rollback — запрещает запуск отозванных старых версийГлавная мысль: Secure Boot защищает цепочку загрузки, TrustZone — границу доступа во время работы, а шифрование Flash — данные в выключенном устройстве. Ни один механизм не заменяет остальные.
2. Зачем это нужно в твоих проектах
В прошивках появляются чувствительные активы:
MQTT client private key
пароли APN и серверов
ключи подписи команд
ключи шифрования конфигурации
сертификаты устройства
параметры безопасного OTA
anti-replay counters
заводская калибровка
критичные GPIO и силовые выходыОшибка в AT-парсере может привести к выполнению кода, который прочитает MQTT private key. MPU помогает ловить память, но не создаёт полноценную cryptographic boundary. TrustZone на STM32U5/H5/Cortex-M33 может отделить ключи и secure services от обычного приложения. Для классического ESP32-WROOM-32U TrustZone нет; там основа — Secure Boot, Flash Encryption, NVS Encryption, eFuse, уникальные device keys и архитектурное ограничение доступа.
3. Теория
6.3.1 3.1. Модель угроз
Перед включением security-флагов нужно определить:
что защищаем;
от кого защищаем;
в каком состоянии устройства;
что допустимо потерять.6.3.2 3.2. Secure Boot
Цепочка доверия:
ROM / immutable Root of Trust
→ проверка bootloader
→ проверка приложения
→ переход к выполнениюSecure Boot проверяет подлинность кода. Он не скрывает содержимое firmware.
6.3.3 3.3. Flash Encryption
Flash Encryption скрывает содержимое внешней Flash. Но без Secure Boot не гарантирует, что запускаемый код доверенный.
Secure Boot без Flash Encryption:
код проверяется, но может читаться с Flash.
Flash Encryption без Secure Boot:
код скрыт, но подлинность цепочки слабее.6.3.4 3.4. TrustZone
На Cortex-M33 систему можно разделить:
Secure world:
ключи;
crypto;
проверка OTA;
secure storage;
критичные счётчики;
часть peripherals.
NonSecure world:
FreeRTOS;
EC25 parser;
MQTT/TCP;
UI;
обычная логика.Secure API должен быть узким:
typedef enum {
SECURE_STATUS_OK = 0,
SECURE_STATUS_INVALID_ARG,
SECURE_STATUS_DENIED,
SECURE_STATUS_INTERNAL_ERROR,
} secure_status_t;
secure_status_t secure_sign_event(const uint8_t *message,
size_t message_size,
uint8_t *signature,
size_t signature_capacity,
size_t *signature_size);Private key никогда не возвращается наружу. 6.3.5 3.5. Secure Service проверяет аргументы
Secure-мир не доверяет NonSecure-вводу. Нужно проверять pointer, length, output capacity, состояние, role, rate limits, replay. Плохой API:
const uint8_t *secure_get_private_key(void);Хороший:
secure_status_t secure_hmac_calculate(secure_key_id_t key_id,
const void *message,
size_t message_size,
void *output,
size_t output_size);6.3.6 3.6. Что помещать в Secure-мир
Стоит помещать:
проверку подписи OTA
device identity key
HMAC/signing service
anti-replay counter
security version
factory provisioning state
secure storage
критичную операцию подтверждения firmwareНе стоит помещать:
весь MQTT client
JSON parser
AT-парсер EC25
весь FreeRTOS application
logger
веб-сервер
сложную бизнес-логику6.3.7 3.7. Anti-rollback
Разделяй:
firmware version:
меняется каждый релиз
build number:
монотонно растёт
security version:
меняется только при отзыве старой security generationНе увеличивай secure_version на каждом обычном релизе, иначе потеряешь функциональный rollback.
6.3.8 3.8. Provisioning
DEVELOPMENT
→ тестовые ключи, debug открыт
PILOT
→ production-like ключи, тест recovery
PRODUCTION
→ финальные ключи, eFuse/option bytes, provisioning reportPrivate signing key не должен храниться в Git, Docker image, HIL Raspberry Pi или PR-job CI.
4. Типичные ошибки
1. Считать Flash Encryption заменой Secure Boot.
2. Считать Secure Boot защитой секретов в RAM.
3. Поместить весь проект в Secure-мир.
4. Передать NonSecure-коду pointer на ключ.
5. Не проверять NonSecure pointer и length.
6. Хранить signing key в обычном CI secret.
7. Включить eFuse/option bytes на единственной отладочной плате.
8. Использовать один symmetric key на весь парк.
9. Помещать private key в логи или core dump.
10. Не проектировать ротацию ключей.5. Практическое задание на 30-60 минут
Создай SECURITY_ARCHITECTURE.md:
# Security architecture
## Assets
| Asset | Confidential? | Integrity critical? | Location |
|---|---:|---:|---|
| Firmware signing private key | yes | yes | offline signing environment |
| Firmware verification key | no | yes | eFuse/bootloader |
| MQTT device private key | yes | yes | secure storage/encrypted NVS |
| CA certificate | no | yes | firmware/read-only storage |
| APN password | yes | medium | encrypted NVS |
| Phase policy | no | yes | signed config/read-only runtime |
| Boot counter | no | yes | protected persistent storage |Для ESP32 нарисуй:
Untrusted/external:
EC25 bytes, MQTT, HTTP, CLI
Application:
parser, networking, phase logic
Security services:
OTA verification, encrypted storage
Hardware root:
eFuse, Secure Boot digest, flash encryption keyДля STM32 TrustZone:
NonSecure:
EC25, MQTT, Modbus, UI, phase logic
Secure:
key operations, OTA verification,
anti-replay counter, secure storage
Immutable Root:
STiRoT/OEMiRoT6. Что почитать дальше
- ESP-IDF Security Overview, Secure Boot v2, Flash Encryption.
- STM32H5/U5 TrustZone, STiRoT/OEMiRoT, OBKeys, secure storage.
Короткий итог
immutable root
→ verified bootloader
→ verified application
→ Secure/NonSecure boundary
→ narrow secure services
→ isolated device keys
→ signed OTA
→ anti-rollback
→ controlled provisioningЗадание
Application просит secure service подписать arbitrary input и вернуть pointer на private key. Перепроектируйте interface и validation boundary.
Критерии самопроверки: Объяснить проверку untrusted pointer и output capacity; одно название TrustZone не проверяет опасный API.
Показать ответ автора
Никогда не возвращать private key или pointer на него. Предоставить узкую operation, например signing bounded digest, проверять input/output ranges и lengths, authorization/state/rate limits и сохранять key operations внутри secure boundary.
Задание
Разделите firmware version, build number и security version в release policy, сохраняющей functional rollback и отзывающей compromised generation.
Критерии самопроверки: Описать revocation decision и recovery/provisioning evidence до изменения irreversible device settings.
Показать ответ автора
Firmware version определяет feature release; build number растёт монотонно; security version меняется при отзыве older security generation. Не повышать irreversible security threshold для каждого обычного feature release.