ESP32 Secure Boot V1 |
![]() |
Добавил(а) microsin |
Все ссылки в этом документе относятся к Secure Boot V1 (схема безопасной загрузки, основанная на AES). Для ESP32 Revision 3 и далее предпочтительнее использовать схему безопасной загрузки Secure Boot V2 (см. документацию [2] для ESP32 Revision 3 или ESP32-S2). Технология Secure Boot гарантирует, что на чипе можно будет запустить только Ваш код. Данные загружаются из flash и проверяются при каждом сбросе/включении питания. Secure Boot отделяется от функции шифрования памяти SPI flash (Flash Encryption), и можно использовать безопасную загрузку без шифрования содержимого flash. Однако для безопасного рабочего окружения Secure Boot и Flash Encryption должны использоваться одновременно (см. далее раздел "Secure Boot и Flash Encryption"). Важное замечание: разрешение техники Secure Boot ограничивает возможности для будущих обновлений используемого чипа ESP32. Внимательно прочитайте этот документ, чтобы разобраться в последствиях включения безопасной загрузки. Что происходит при безопасной загрузке: • Большинство данных сохраняются в памяти flash. Доступ к flash не нужно защищать от физического доступа, чтобы работала функция Secure Boot, поскольку критические данные сохраняются в битах Efuse внутри чипа, и эти данные программно недоступны [3, 4]. [Обзор процесса Secure Boot] Ниже показан процесс безопасной загрузки, как он работает на верхнем уровне. Пошаговые инструкции по запуску безопасной загрузки приведены далее в разделе "Как разрешить Secure Boot". Дополнительные подробности процесса объясняются в разделе "Технические подробности Secure Boot". 1. Опции для разрешения Secure Boot предоставляются в меню конфигурации проекта ESP-IDF, в разделе "Secure Boot Configuration" (описание меню конфигурации см. в [7]). 2. По умолчанию Secure Boot подписывается образы и данные таблицы разделов во время процесса сборки. Опция конфигурации "Secure boot private signing key" это путь до файла (в формате PEM) с парой ECDSA-ключей (public/private key). 3. Образ загрузчика второй стадии (software bootloader) собирается средой разработки ESP-IDF, когда разрешена поддержка безопасной загрузки, вместе с публичным ключом (сигнатура проверки) кода загрузчика. Этот образ программного загрузчика прошивается в SPI flash со смещением 0x1000. Примечание: под "программным загрузчиком" (software bootloader) имеется в виду загрузчик второго уровня, см. [5]. 4. При первой загрузке программный загрузчик следует следующей процедуре для разрешения Secure Boot: • Аппаратная поддержка безопасной загрузки генерирует защищенный ключ загрузки устройства (device secure bootloader key, он генерируется на основе аппаратного генератора случайных чисел RNG, и затем сохраняется в область efuse, защищенную от записи), и цифровую подпись (secure digest). Эта подпись вычисляется от ключа, IV, и от содержимого образа загрузчика. 5. При последующих загрузках ROM bootloader видит, что прошит Secure Boot efuse, считывает цифровую подпись с адреса 0x0, и использует процедуру аппаратной поддержки Secure Boot для проверки загруженной подписи с вычисленным значением. Если подпись не совпала, то процесс загрузки остановится. Подпись и её сравнение выполняется полностью аппаратно, и вычисленную подпись невозможно прочитать программно. Дополнительную информацию см. далее в секции "Аппаратная поддержка Secure Boot". 6. Когда запускается режим Secure Boot, программный загрузчик (software bootloader) использует ключ подписи (secure boot signing key, публичный ключ, который встроен в код самого программного загрузчика, и поэтому он был также проверен как часть образа загрузчика), чтобы проверить подпись, прикрепленную ко всем последующим таблицам разделов и образам приложения перед тем, как они будут загружены. [Ключи шифрования] Во время процесса Secure Boot испльзуются следующие ключи: • "secure bootloader key" это 256-разрядный ключ AES, который сохранен в Efuse block 2. Пользователю не надо предоставлять этот ключ, потому что загрузчик может генерировать этот ключ самостоятельно с помощью внутреннего аппаратного генератора случайных чисел RNG (опционально можно предоставить этот ключ, см. далее раздел "Перепрошиваемый программный загрузчик"). Хранение этого ключа в Efuse обеспечивает защиту от чтения и записи ключа (обеспечение защиты ПО) до момента разрешения Secure Boot. - По умолчанию применена "None" схема кодирования Efuse Block 2, и 256 бит ключа сохранены в этот блок. На некоторых устройствах ESP32 схема кодирования устанавливается на 3/4 Encoding (CODING_SCHEME efuse установлен в значение 1), и 192-битный ключ должен сохраняться в этот блок. Дополнительную информацию см. в ESP32 Technical Reference Manual -> eFuse Controller (eFuse) > System Parameter coding_scheme [PDF]. Алгоритм шифрования во всех случаях работает с ключом 256 бит, при этом 192-битные ключи расширяются путем повтора некоторых бит. • "secure boot signing key" это стандартная ECDSA пара ключей public/private (см. секцию "Алгоритм подписи образа") в формате PEM. - Публичный ключ из этой пары (предназначенный для проверки подписи, но не для её создания) компилируется в тело software bootloader, и используется для проверки загрузки второй стадии (таблица разделов, образ приложения) перед продолжением загрузки. Этот публичный ключ можно свободно распространять по открытым каналам, его не нужно сохранять в секрете. [Размер программного загрузчика] Разрешение secure boot и/или шифрования flash увеличивают размер загрузчика, что может потребовать обновления (увеличения) значения смещения таблицы разделов, см. раздел "Размер загрузчика" документации [5]. [Как разрешить Secure Boot] 1. Откройте меню конфигурации проекта [7], перейдите в раздел "Secure Boot Configuration" и выберите опцию "One-time Flash" (однократное программирование). Доступна альтернатива для перепрошиваемого загрузчика, см. далее раздел "Перепрошиваемый программный загрузчик". 2. Выберите имя файла для ключа подписи Secure Boot. Эта опция появится после того, как разрешена конфигурация Secure Boot. Файл может быть в любом месте в вашей системе. Относительный путь строится относительно корневого каталога проекта. Этот файл пока не существует. 3. Установите другие опции menuconfig (по мере необходимости). Уделите в частности внимание опциям "Bootloader Config", поскольку прошить загрузчик можно будет только однократно. После этого выйдите из menuconfig и сохраните свою конфигурацию. 4. При первом запуске make, если ключ подписи не найден, то отобразится сообщение об ошибке, что нужно выполнить команду espsecure.py generate_signing_key для генерации ключа подписи. Важные замечания: ключ подписи, сгенерированный таким способом, будет использовать самый лучший источник генерации случайных числе в операционной системе, и выделенную инсталляцию Python (/dev/urandom на OSX/Linux и CryptGenRandom() на Windows). Если этот источник случайных чисел нестойкий, то приватный ключ будет ненадежным. Для целей производства рекомендуется генерировать пару ключей с использованием openssl или другой программы, соответствующую индустриальным стандартам. Подробности см. далее в разделе "Генерация Secure Boot Signing Key". 5. Запустите команду idf.py bootloader, чтобы выполнить сборку для загрузчика с разрешенной конфигурацией secure boot. Вывод сборки будет содержать приглашения для команды прошивки, используется esptool.py write_flash. 6. Когда Вы готовы прошить загрузчик, запустите указанную команду (Вы должны будете ввести её самостоятельно, этот шаг make не выполняет), и затем подождите завершения прошивки. Помните, что это прошивка однократная, после этого загрузчик поменять будет невозможно! 7. Запустите idf.py flash для сборки и прошивки таблицы раздела и только что собранного образа приложения. Образ приложения будет подписан ключом, который был сгенерирован на шаге 4. Замечание: idf.py flash не прошивает загрузчик, если разрешена конфигурация Secure Boot. 8. Сбросьте устройство ESP32, и оно запустит программный загрузчик, который был прошит на шаге 6. Программный загрузчик разрешит Secure Boot на чипе, затем проверит сигнатуру образа приложения и после успешной проверки загрузит и запустит его. В последовательной консоли Вы должны наблюдать вывод ESP32 для проверки разрешения Secure Boot, и что не было ошибок из-за сборки конфигурации. Замечания: безопасная загрузка будет разрешена только после прошивки корректной таблицы разделов и образа приложения. Это необходимо для предотвращения аварийных ситуаций до полной настройки системы. Если устройство ESP32 было сброшено, или был сбой по питанию во время первой загрузки, то процесс запустится снова при следующей загрузке. 9. При последующих загрузках аппаратура Secure Boot будет проверять, что программный загрузчик не был изменен (с помощью secure bootloader key) и затем программный загрузчик будет проверять подписанную таблицу разделов и образ приложения (используя публичную часть secure boot signing key). [Перепрошиваемый программный загрузчик] Рекомендуется сконфигурировать однократную прошивку загрузчика (опция "Secure Boot: One-Time Flash") для устройств, находящихся в производстве. В режиме однократной прошивки загрузчика каждое устройство получит уникальный ключ, который будет храниться только внутри этого устройства, и больше нигде. Однако также существует альтернативный режим Secure Boot: Reflashable (CONFIG_SECURE_BOOTLOADER_MODE -> SECURE_BOOTLOADER_REFLASHABLE). Этот режим позволяет предоставить двоичный файл ключа, используемый в качестве secure bootloader key. Если Вы владеете этим файлом, то можете генерировать новые образы загрузчика и загрузочные подписи Secure Boot для него. В процессе сборки ESP-IDF этот файл 256-битного ключа получается из ECDSA app signing key, генерируемого пользователем (см. далее раздел "Генерация Secure Boot Signing Key"). Этот приватный ключ SHA-256 используется как секретный ключ secure bootloader key в efuse (он применяется как есть для схемы кодирования None, либо обрезается до 192 бит, когда используется схема кодирования 3/4). Это удобно, поскольку нужно только сгенерировать/защитить один приватный ключ. Замечание: несмотря на наличие возможности перепрошивки загрузчика, строго рекомендуется не генерировать один secure boot key и прошивать в процессе производства его копию в каждое устройство. Для производства лучше использовать опцию однократной прошивки (One-Time Flash). Чтобы разрешить использование пререпрошиваемого загрузчика: 1. В меню конфигурации проекта [7] выберите "Bootloader Config" -> CONFIG_SECURE_BOOT -> CONFIG_SECURE_BOOT_V1_ENABLED -> CONFIG_SECURE_BOOTLOADER_MODE -> Reflashable. 2. Если необходимо, установите CONFIG_SECURE_BOOTLOADER_KEY_ENCODING, основываясь на схеме кодирования, используемой в Вашем устройстве. Схема кодирования показывается в строке Features, когда esptool.py подключается к чипу, или в результатах вывода команды espefuse.py summary. 3. Выполните шаги, показанные ниже в разделе "Генерация Secure Boot Signing Key", чтобы сгенерировать ключ подписи. Путь для сгенерированного файла должен быть указан в меню "Secure Boot Configuration". 4. Запустите команду idf.py bootloader. Будет создан двоичный файл ключа, полученный из приватного ключа, используемого для подписи. Будут выведены результаты двух прошивок - первый набор шагов включает результат команды espefuse.py burn_key secure_boot_v1 path_to/secure-bootloader-key-xxx.bin, которая используется для записи в efuse ключа загрузчика (прошивка этого ключа однократная). Второй набор шагов может использоваться для перепрошивки загрузчика с предварительно сгенерированной подписью (она генерируется во время процесса сборки). 5. Далее продолжайте выполнять действия, начиная с шага 6 описанного выше процесса разрешения однократно прошиваемого загрузчика (раздел "Как разрешить Secure Boot"), чтобы прошить загрузчик и разрешить Secure Boot. Наблюдайте за логом консоли чтобы убедиться, что не было ошибок в конфигурации Secure Boot. [Генерация Secure Boot Signing Key] Система сборки выведет приглашение для ввода команды с целью генерации нового ключа подписи (signing key) через команду espsecure.py generate_signing_key. Эта генерация использует библиотеку python-ecdsa, которая в свою очередь использует в качестве источника случайных чисел os.urandom() из библиотек Python. Надежность ключа подписи пропорциональна (a) качеству генератора случайных чисел, и (b) корректности используемого алгоритма шифрования. Для устройств, находящихся в производстве, рекомендуется использовать генерацию ключей подписи на основе качественного генератора энтропии, применяя лучшие на сегодняшний день утилиты генерации ключей EC. Например, для генерации ключа подписи с помощью openssl, используйте команду: openssl ecparam -name prime256v1 -genkey -noout -out my_secure_boot_signing_key.pem Помните, что безопасность Secure Boot зависит от надежности хранения в секрете приватной части ключа подписи. [Дистанционная подпись образов] Для сборок процесса производства хорошей практикой будет использовать удаленный сервер подписи (remote signing server) вместо того, чтобы держать ключ подписи в компьютере, на котором выполняется сборка (которая является конфигурацией безопасной загрузки ESP-IDF по умолчанию). Утилита командной строки espsecure.py на удаленной системе может использоваться при подписи образов приложения и данных таблицы разделов для Secure Boot. Чтобы использовать удаленную подпись, запретите опцию "Sign binaries during build". Приватный signing key не обязательно должен присутствовать в системе сборки. Однако публичный ключ (сигнатура проверки) нужен, потому что он компилируется в тело загрузчика (и может использоваться для проверки сигнатур образа при обновлениях OTA [8]). Чтобы получить публичный ключ из приватного ключа, выполните команду: espsecure.py extract_public_key --keyfile PRIVATE_SIGNING_KEY PUBLIC_VERIFICATION_KEY Для сборки защищенного загрузчика в menuconfig (опция "Secure boot public signature verification key") необходимо указать путь к ключу проверки публичной подписи. После того, как была выполнена сборка образа приложения и таблицы разделов, система сборки напечатает шаги для выполнения подписи с помощью утилиты espsecure.py: espsecure.py sign_data --keyfile PRIVATE_SIGNING_KEY BINARY_FILE Эта команда присоединит подпись образа к существующему двоичному файлу. Вы можете использовать аргумент –output, чтобы записать пописанный двоичный код в отдельный файл: espsecure.py sign_data --keyfile PRIVATE_SIGNING_KEY --output SIGNED_BINARY_FILE BINARY_FILE [Рекомендуемая практика использования Secure Boot] • Генерируйте ключ подписи на системе, где присутствует качественный источник энтропии (надежный генератор случайных чисел). [Технические подробности Secure Boot] Следующие разделы содержат низкоуровневые справочные описания различных элементов безопасной загрузки. Аппаратная поддержка Secure Boot. Первая стадия проверки Secure Boot (проверка тела software bootloader) осуществляется аппаратно. Аппаратная поддержка Secure Boot чипа ESP32 может выполнять 3 базовые операции: 1. Генерация случайной последовательности байт с помощью аппаратного генератора случайных чисел RNG. Алгоритм цифровой подписи защищенного загрузчика. Начиная с "образа" двоичных данных на входе, этот алгоритм генерирует на выходе цифровую подпись. Эта подпись иногда в документации аппаратуры называется как "abstract". Для Python-версии этого алгоритма см. утилиту espsecure.py tool, которая находится в каталоге components/esptool_py (команда digest_secure_bootloader). Элементы, помеченные символам (^), должны соответствовать аппаратным, а не криптографическим ограничениям. 1. Считывается ключ AES из efuse block 2, в обратном порядке байт. Если для efuse установлена схема кодирования 3/4 Encoding, то 192 бита расширяются до 256 бит с использования алгоритма, описанного в [9]. Выходная подпись содержит 192 байта данных: 128 байт IV, за которым идет 64 байта подписи SHA-512. Алгоритм подписи образа. Применяется детерминированный алгоритм ECDSA, как указано стандартом RFC 6979. • Кривая NIST256p (openssl называет эту кривую "prime256v1", также она иногда называется secp256r1). Запуск команд вручную. Технология Secure Boot интегрирована в систему сборки ESP-IDF, которая автоматически подписывает образ приложения, если разрешена конфигурация Secure Boot. Команда idf.py bootloader будет формировать подпись загрузчика (bootloader digest), если для этого сконфигурирована конфигурация проекта (menuconfig). Однако есть возможность использовать утилиту espsecure.py для генерации отдельных сигнатур и подписей. Для подписи двоичного образа: espsecure.py sign_data --keyfile ./my_signing_key.pem --output ./image_signed.bin image-unsigned.bin Здесь keyfile это файл в формате PEM, содержащий приватный ключ подписи (ECDSA private signing key). Для генерации подписи загрузчика: espsecure.py digest_secure_bootloader --keyfile ./securebootkey.bin --output ./bootloader-digest.bin build/bootloader/bootloader.bin Здесь keyfile это 32 сырых байта ключа безопасной загрузки (secure boot key) для устройства. Вывод команды espsecure.py digest_secure_bootloader command это один файл, который содержит подпись, так и добавленный к ней загрузчик. Для прошивки этого файла в устройство: esptool.py write_flash 0x0 bootloader-digest.bin [Secure Boot и Flash Encryption] Если Secure Boot используется без Flash Encryption, то есть возможность запустить атаку взлома типа "time-of-check to time-of-use", где содержимое flash подменяется после того, как образ проверен и запущен. Таким образом, рекомендуется одновременно включить обе эти опции защиты. [Проверка подписи приложения без Hardware Secure Boot] Целостность приложений можно проверить без разрешения опции аппаратной проверки загрузки (hardware secure boot). Эта опция использует ту же самую схему подписи приложения, как и hardware secure boot, однако в отличие от hardware secure boot она не защищает загрузчик от физического обновления. Это означает, что устройство может быть защищено от доступа через удаленный доступ по сети, но не будет защищено от физического локального доступа. В сравнении с аппаратным Secure Boot эта опция намного проще для реализации. Пошаговые инструкции см. далее в секции выше в разделе "Как разрешить проверку подписанного приложения". Приложение может быть проверено при обновлении, и опционально при загрузке. • Проверка при обновлении (опция Verification on update): когда это разрешено, подпись автоматически проверяется всякий раз, когда для OTA-обновления [8] используется esp_ota_ops.h API. Если разрешена функция hardware secure boot, то эта опция всегда разрешена и не может быть запрещена. Если функция hardware secure boot не разрешена, то эта опция все еще добавит значимую защиту от атак по сети, предотвращая спуфинг обновлений OTA. Как разрешить проверку подписанного приложения: 1. Откройте меню конфигурации проекта -> Security features -> разрешите CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT. 2. Может быть разрешена опция "Bootloader verifies app signatures", которая обеспечивает проверку загрузчиком образа приложения. 3. По умолчанию при выборе опции "Require signed app images" будет разрешена опция "Sign binaries during build", что приведет к подписи двоичных файлов, которая будет выполняться как часть процесса сборки. Файл с именем "Secure boot private signing key" будет использоваться для подписи образа. 4. Если запретить опцию "Sign binaries during build", то в "Secure boot public signature verification key" понадобится ввести путь до файла публичного ключа, используемого для проверки подписанных образов. В этом случае приватный ключ подписи должен быть сгенерирован инструкциями, описанными выше в разделе "Генерация Secure Boot Signing Key". Проверочный публичный ключ и подписанный образ должен быть сгенерирован инструкциями, описанными выше в разделе "Дистанционная подпись образов". [Дополнительные возможности] Отладка JTAG. По умолчанию, когда разрешена конфигурация Secure Boot, отладка JTAG через eFuse запрещается. Загрузчик прошивает этот eFuse во время первой загрузки, одновременно с прошивкой eFuse, который разрешает Secure Boot. См. "JTAG with Flash Encryption or Secure Boot" в советах [10] для дополнительной информации по использованию отладки JTAG, когда разрешена конфигурация Secure Boot, или разрешена проверка подписанного приложения. [Словарик] OTA Over The Air, технология загрузки (обновления) по радиоканалу. PEM Privacy Enhanced Mail, текстовый файл, содержащий сертификат подписи или ключ шифрования в виде ASCII-текста. [Ссылки] 1. ESP32 Secure Boot site:docs.espressif.com. |