Этот документ (перевод документации [1]) относится к версии безопасной загрузки Secure Boot V2, которая поддерживается следующими чипами: ESP32 (начиная с ECO3), ESP32-S2, ESP32-S3, ESP32-C3 (начиная с ECO3) и ESP32-C2. Исключение составляет ESP32 он поддерживает только Secure Boot версии 1 (для ESP32 до ECO3 обращайтесь к [2]). Рекомендуется использовать версию V2, если есть в наличии поддерживающий эту версию чип. Secure Boot V2 безопаснее и более гибкая, чем Secure Boot V1.
Secure Boot V2 использует верификацию приложения и загрузчика на основе RSA-PSS. Этот документ также может использоваться как руководство для подписывания приложений с использованием схемы RSA-PSS без подписи загрузчика.
Опции Secure Boot V2 и схемы подписи RSA (App Signing Scheme) доступны для ESP32 начиная с ECO3. Для использования этих опций в menuconfig установите CONFIG_ESP32_REV_MIN в значение, большее или равное Rev 3.
Secure Boot защищает устройство от запуска любого не авторизованного (т. е. не подписанного) кода путем проверки подписи каждой части загружаемого программного обеспечения. Для ESP32 эти части включают загрузчик второй стадии [3] и каждый двоичный образ приложения. Обратите внимание, что загрузчик первой стадии не требует подписи, поскольку он находится в ROM, и поэтому его код не может быть изменен.
Новая схема верификации Secure Boot, основанная на RSA (Secure Boot V2), была введена на чипах ESP32 (начиная с ECO3), ESP32-S2, ESP32-S3 и ESP32-C3 (начиная с ECO3).
Процесс Secure Boot на ESP32 включает следующие шаги:
1. Когда загрузчик первой стадии загружает загрузчик второй стадии, то для загрузчика второй стадии проверяется подпись RSA-PSS. Если проверка была успешной, то производится запуск загрузчика второй стадии. 2. Когда загрузчик второй стадии загружает определенный образ приложения, также проверяется образ RSA-PSS этого приложения. Если проверка была успешной, то производится запуск загруженного приложения.
Достоинства Secure Boot V2:
• Публичный ключ RSA-PSS сохраняется в устройстве. Соответствующий ему приватный ключ RSA-PSS находится в секретном месте, и к нему нет никакого доступа со стороны устройства. • Во время производства только публичный ключ может быть сгенерирован и сохранен в чипе. • Для приложений и программного загрузчика используется один и тот же формат образа и один и тот же метод проверки сигнатуры. • На устройстве не сохраняется секретных данных. Таким образом, оно защищено от пассивных атак со стороны побочных каналов (анализ таймингов или потребления тока, и т. д.).
Примечание: под программным загрузчиком подразумевается загрузчик второй стадии [2].
[Процесс Secure Boot V2]
Здесь дается обзор процесса Secure Boot V2. Инструкции по разрешению Secure Boot предоставлены в разделе "Как разрешить Secure Boot V2".
Secure Boot V2 проверяет образ программного загрузчика и двоичные образы приложений, используя выделенный блок сигнатуры. Каждый образ имеет отдельно сгенерированный блок сигнатуры, который прикрепляется в конец образа.
В ESP32 ECO3 может быть прикреплен только один блок сигнатуры к загрузчику или к образу приложения.
Каждому блоку сигнатуры предшествует образ кода, а также соответствующий публичный ключ RSA-3072. Более подробно про формат см. далее раздел "Формат блока сигнатуры". Цифровая подпись публичного ключа RSA-3072 сохраняется в eFuse [4, 5].
Образ приложения проверяется не только при каждой загрузке, но также и при каждом обновлении по радиоканалу (OTA, см. [6]). Если текущий выбранный образ OTA app не может быть проверен, то загрузчик выполнит откат назад в поиске другого корректно подписанного образа приложения.
Процесс Secure Boot V2 выполняет следующие шаги:
1. В момент запуска (startup) код ROM проверяет бит Secure Boot V2, находящийся в eFuse. Если конфигурация Secure Boot запрещена, то выполняется нормальный процесс загрузки. Если конфигурация Secure Boot разрешена, то будет выполняться защищенная загрузка из следующих шагов. 2. Код ROM проверяет блок сигнатуры загрузчика (см. далее раздел "Проверка Signature Block"). Если эта проверка не прошла, то процесс загрузки обрывается. 3. Код ROM проверяет двоичные данные образа загрузчика, его соответствующий блок (блоки) сигнатуры, и eFuse (см. "Проверка образа"). Если эта проверка не прошла, то процесс загрузки обрывается. 4. Код ROM выполняет загрузчик второй стадии. 5. Загрузчик второй стадии проверяет блок сигнатуры приложения (см. далее раздел "Проверка Signature Block"). Если эта проверка не прошла, то процесс загрузки обрывается. 6. Загрузчик второй стадии проверяет двоичные данные образа приложения, его соответствующий блок сигнатуры и eFuse (см. "Проверка образа"). Если эта проверка не прошла, то процесс загрузки обрывается. Если проверка не прошла, но найден другой образ приложения, то загрузчик попытается проверить этот другой образ, выполняя шаги 5 .. 7. Это повторяется, пока не будет найден допустимый образ, либо пока не закончатся проверяемые образы. 7. Загрузчик запустит проверенный образ приложения.
[Формат блока сигнатуры]
Образы загрузчика и приложения дополняются до следующей границы блока из 4096 байт, так что сигнатура занимает отдельный сектор SPI flash. Сигнатура вычисляется от всех байт образа, включая дополняющие байты. Содержимое каждого блока сигнатуры показано в таблице 1.
Таблица 1. Содержимое Signature Block.
Смещение |
Размер (в байтах) |
Описание |
0 |
1 |
Magic-байт. |
1 |
1 |
Байт, содержащий номер версии (в настоящий момент 0x02). Для Secure Boot V1 здесь будет 0x01. |
2 |
2 |
Байты дополнения до размера слова. Это место зарезервировано, здесь будут нули. |
4 |
32 |
Хэш SHA-256 только для содержимого образа, не включая блок сигнатуры. |
36 |
384 |
RSA Public Modulus, используется для верификации сигнатуры (значение n в RFC8017). |
420 |
4 |
RSA Public Exponent, используется для верификации сигнатуры (значение e в RFC8017). |
424 |
384 |
Предварительно рассчитанное R, вычисленное от n. |
808 |
4 |
Предварительно рассчитанное M', вычисленное от n. |
812 |
384 |
Результат RSA-PSS Signature (секция 8.1.1 стандарта RFC8017) от содержимого образа, вычисленный со следующими параметрами PSS: хэш SHA256, функция MFG1, длина salt 32 байта, поле завершения по умолчанию (0xBC). |
1196 |
4 |
CRC32 от предшествующих 1095 байт. |
1200 |
16 |
Нулевое дополнение до длины 1216 байт. |
Примечание: R и M’ используются для аппаратно поддерживаемого алгоритма Монтгомери (hardware-assisted Montgomery Multiplication).
Хвост сектора сигнатуры оставляется чистым (заполненным байтами 0xFF), что позволяет записать другие блоки сигнатуры за предыдущим блоком.
[Проверка Signature Block]
Блок сигнатуры считается допустимым (valid), если первый байт равен 0xe7, и его корректная CRC32 сохранена со смещением 1196. Иначе блок сигнатуры считается ошибочным.
Проверка образа. Образ считается проверенным (verified), если публичный ключ, сохраненный в любом блоке сигнатуры, является допустимым для этого устройства, и если сохраненная сигнатура подходит для данных образа, считанных из flash.
1. Сравнивается хэш подписи SHA-256 публичного ключа, строенный в блок сигнатуры загрузчика, с подписью (подписями), сохраненными в битах eFuse. Если хеш публичного ключа не соответствует ни одному из хэшей из eFuse, то проверка завершается неудачей. 2. Генерируется подпись образа приложения, и сравнивается с подписью образа в блоке сигнатуры. Если подписи не совпали, то проверка завершается неудачей. 3. Используется публичный ключ для проверки сигнатуры образа загрузчика, с использованием RSA-PSS (см. секцию 8.1.2 стандарта RFC8017). Для сравнения используется подпись образа, вычисленная на шаге 2.
Размер загрузчика. Разрешение безопасной загрузки (secure boot) и/или шифрования SPI flash (flash encryption) увеличит размер кода загрузчика, что может потребовать обновления для смещения таблицы разделов (см. раздел "Размер загрузчика" в документации [3]).
Использование eFuse. ESP32-ECO3:
ABS_DONE_1 - разрешает защиту Secure Boot при загрузке. BLK2 - сохраняет подпись SHA-256 публичного ключа. Хэш SHA-256 модуля публичного ключа, экспонента, предварительно вычисленные значения R и M’ (представленные 776 байтами – смещения от 36 до 812 - как описано в формате Signature Block выше) записаны в eFuse key block. Должен быть установлен бит защиты от записи, но бит защиты от чтения не должен быть установлен.
Ключ (ключи) должен иметь возможность чтения, чтобы программа могла получить к нему доступ. Защита от чтения для ключа (ключей) активна, что программа прочитает ключ как нули, в результате процесс верификации потерпит неудачу, и процесс загрузки будет оборван.
[Как разрешить Secure Boot V2]
1. Откройте меню конфигурации проекта [7], в "Security features" установите "Enable hardware Secure Boot in bootloader", чтобы разрешить Secure Boot.
2. Для ESP32, конфигурация Secure Boot V2 доступна только начиная с ESP32 ECO3. Чтобы просмотреть опцию "Secure Boot V2", ревизия чипа должна быть изменена на revision 3 (ESP32- ECO3). Чтобы поменять ревизию чипа, установите "Minimum Supported ESP32 Revision" на Rev 3 в "Component Config" -> "ESP32- Specific".
3. Укажите путь до ключа подписи (Secure Boot signing key) относительно корневой директории проекта.
4. Выберите желаемый режим загрузки UART ROM в "UART ROM download mode". По умолчанию UART ROM download mode остается разрешенным для целей отладки, и следует иметь в виду, что это потенциально небезопасно. Рекомендуется запретить UART download mode для устройств, находящихся в производстве, что улучшит защиту кода.
5. Установите другие опции menuconfig (по мере необходимости). В особенности уделите внимание опциям "Bootloader Config", потому что прошить загрузчик Вы сможете только один раз. После этого выйдите из menuconfig и сохраните конфигурацию.
6. При первом запуске idf.py build, если ключ подписи не был найден, то будет выведено сообщение об ошибке с предложением создать ключ подписи (signing key) командой espsecure.py generate_signing_key.
Важные замечания: ключ подписи, генерируемый таким способом, будет использовать самый лучший доступный источник случайных чисел для операционной системы и её инсталляции Python (/dev/urandom на OSX/Linux и CryptGenRandom() на Windows). Если этот источник случайных чисел нестойкий, то приватный ключ будет ненадежным. Для целей производства рекомендуется генерировать пару ключей с использованием openssl или другой программы, соответствующую индустриальным стандартам. Подробности см. далее в разделе "Генерация Secure Boot Signing Key".
7. Запустите команду idf.py bootloader для сборки загрузчика с разрешенной функцией Secure Boot. Вывод сборки будет включать приглашение для команды прошивки с использованием esptool.py write_flash.
8. Когда Вы будете готовы прошить загрузчик, запустите эту указанную команду (Вам будет нужно ввести её самостоятельно, система сборки не будет выполнять этот шаг) и подождите завершения прошивки.
9. Запустите idf.py flash для сборки и прошивки таблицы разделов и только что собранного образа приложения (app image). Образ приложения будет подписан с помощью signing key, который был сгенерирован на шаге 4.
Замечание: idf.py flash не прошивает загрузчик, если разрешена конфигурация Secure Boot.
10. Сбросьте устройство ESP32, и оно запустит прошитый Вами загрузчик. Программный загрузчик разрешит Secure Boot на чипе, и затем проверит сигнатуру образа приложения и запустит это приложение. Вы должны наблюдать сообщения в выводе консоли ESP32, чтобы проверить, что конфигурация Secure Boot разрешена, и при сборке этой конфигурации не было никаких ошибок.
Замечания: безопасная загрузка (secure boot) будет разрешена только после того, как будет прошита правильная таблица разделов и корректный образ приложения. Это необходимо для предотвращения аварий до момента полной настройки системы. Если устройство ESP32 было сброшено, или был сбой по питанию во время первой загрузки, то процесс запустится снова при следующей загрузке.
11. При последующих загрузках аппаратура Secure Boot будет проверять, что программный загрузчик не был изменен, и программный загрузчик будет проверять подписанный образ приложения (используя проверенную часть публичного ключа добавленного signature block).
[Ограничения после разрешения Secure Boot]
• Любой обновленный загрузчик или приложение должны быть подписаны ключом, который подходит к цифровой подписи, которая была сохранена в eFuse. • После того, как конфигурация Secure Boot разрешена, никакие дополнительные eFuse не могут быть защищены от чтения (если разрешена конфигурация Flash Encryption, то загрузчик гарантирует, что любой ключ шифрования flash, сгенерированный при первой загрузке, уже будет защищен от чтения). Если разрешена опция CONFIG_SECURE_BOOT_INSECURE, то такое поведение запрещено, однако это не рекомендуется.
[Генерация Secure Boot Signing Key]
Система сборки выдаст приглашение ввести команду для генерации нового signing key с помощью espsecure.py generate_signing_key.
Параметр --version 2 будет генерировать приватный ключ RSA 3072 для конфигурации Secure Boot V2.
Надежность ключа подписи пропорциональна (a) качеству генератора случайных чисел, и (b) корректности используемого алгоритма шифрования. Для устройств, находящихся в производстве, рекомендуется использовать генерацию ключей подписи на основе качественного генератора энтропии, применяя лучшие на сегодняшний день утилиты генерации ключей RSA-PSS.
Например, для генерации ключа подписи с помощью openssl, используйте команду:
openssl genrsa -out my_secure_boot_signing_key.pem 3072
Помните, что безопасность системы Secure Boot зависит от надежности хранения в секрете приватной части ключа подписи.
[Дистанционная подпись образов]
Для сборок процесса производства хорошей практикой будет использовать удаленный сервер подписи (remote signing server) вместо того, чтобы держать ключ подписи в компьютере, на котором выполняется сборка (которая является конфигурацией безопасной загрузки ESP-IDF по умолчанию). Утилита командной строки espsecure.py на удаленной системе может использоваться при подписи образов приложения и данных таблицы разделов для Secure Boot.
Чтобы использовать дистанционное подписывание, запретите опцию "Sign binaries during build". Приватный ключ подписи не должен находиться на системе сборки.
После того, как были собраны образ приложения и таблица разделов, система сборки выведет шаги для их подписи с использованием espsecure.py:
espsecure.py sign_data --version 2 --keyfile PRIVATE_SIGNING_KEY BINARY_FILE
Показанная выше команда добавит образ сигнатуры к существующему двоичному бинарнику. Вы можете использовать аргумент –output, чтобы записать подписанный бинарник в отдельный файл:
espsecure.py sign_data --version 2 --keyfile PRIVATE_SIGNING_KEY
--output SIGNED_BINARY_FILE BINARY_FILE
[Рекомендуемая практика использования Secure Boot]
• Генерируйте ключ подписи на системе, где присутствует качественный источник энтропии (надежный генератор случайных чисел). • Сохраняйте ключ подписи приватным в течение всего времени жизни устройств. Утечка этого ключа скомпрометирует систему Secure Boot. • Не позволяйте сторонним лицам вмешиваться в любые аспекты генерации ключа или процесса подписи с использованием espsecure.py. Оба этих процесса уязвимы по времени или для сторонних атак. • Разрешите все опции безопасности в конфигурации Secure Boot. Это включает шифрование flash, запрет JTAG, запрет интерпретатора BASIC ROM, и запрет доступа к зашифрованной flash-памяти загрузчика UART. • Используйте Secure Boot в комбинации с flash encryption, чтобы предотвратить локальное чтение содержимого памяти flash.
[Технические подробности Secure Boot]
Следующие разделы содержат низкоуровневые справочные описания различных элементов безопасной загрузки.
Команды, вводимые вручную. Технология Secure Boot интегрирована в систему сборки ESP-IDF, так что запуск idf.py build выполнит подпись образа приложения, и запуск idf.py bootloader сгенерирует подписанный загрузчик, если при сборке была включена защита подписью двоичных файлов.
Однако можно использовать утилиту espsecure.py для создания отдельных сигнатур и цифровых подписей.
Для подписи двоичного образа:
espsecure.py sign_data --version 2 --keyfile ./my_signing_key.pem
--output ./image_signed.bin image-unsigned.bin
Здесь keyfile это файл в формате PEM, содержащий приватный ключ RSA-3072.
[Secure Boot и Flash Encryption]
Если Secure Boot используется без Flash Encryption, то есть возможность запустить атаку взлома типа "time-of-check to time-of-use", где содержимое flash подменяется после того, как образ проверен и запущен. Таким образом, рекомендуется одновременно включить обе эти опции защиты.
[Проверка подписи приложения без Hardware Secure Boot]
Сигнатура Secure Boot V2 может быть проверена в процессе обновления OTA, без разрешения опции аппаратной безопасной загрузки (hardware Secure Boot). Эта опция использует такую же схему подписи приложения, какая применяется для Secure Boot V2, однако в отличие от hardware Secure Boot отключение безопасной загрузки не дает защиты от возможности для атакующего что-либо записать код в память flash и обойти защиту сигнатурой.
Отключение безопасной загрузки может понадобиться в случаях, когда неприемлема задержка по времени, которая уходит на процесс верификации Secure Boot, и/или когда модель угрозы не включает возможность физического доступа для атакующего, чтобы он мог подменить загрузчик или образ приложения в памяти SPI flash.
В этом режиме публичный ключ, который присутствует в signature block работающего в настоящий момент приложения, будет использован для проверки сигнатуры нового кода для обновляемого приложения (сигнатура работающего приложения в процессе обновления не проверяется, поскольку подразумевается, что она корректна). Таким образом, система создает цепочку доверия от запущенного приложения к новому обновляемому приложению.
По этой причине важно, чтобы первоначальное приложение, прошитое в устройство, также было подписано. Проверка подписи выполняется при запуске приложения (app startup), и запуск приложения будет оборван, если подпись не была найдена. Это делается для предотвращения ситуации, когда обновление невозможно. Приложение должно иметь только один корректный блок сигнатуры в первой позиции. Обратите внимание, что в отличие от hardware Secure Boot V2, сигнатура работающего приложения при загрузке не проверяется. Система проверяет только блок сигнатуры в первой позиции, и игнорирует любые другие добавленные сигнатуры.
Замечание: как правило, рекомендуется использовать полную конфигурацию hardware Secure Boot за исключением случаев, когда отключение Secure Boot достаточно для обеспечения безопасности приложения.
Как разрешить верификацию подписи приложения (Enable Signed App Verification):
1. Откройте меню конфигурации проекта -> Security features. 2. Убедитесь, что установлен вариант RSA для схемы подписи приложения (Ensure App Signing Scheme). Для чипа ESP32 ECO3 выберите Rev 3 для CONFIG_ESP32_REV_MIN, чтобы опция RSA стала доступна. 3. Разрешите CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT. 4. По умолчанию опция "Sign binaries during build" будет разрешена при выборе опции "Require signed app images", в результате подпись двоичных файлов будет выполняться автоматически как часть процесса сборки. Файл с именем "Secure boot private signing key" будет использоваться для подписи образа. 5. Если Вы запретили опцию "Sign binaries during build", то все бинарники приложений должны быть подписаны в ручную инструкциями, показанными выше в разделе "Дистанционная подпись образов".
Предупреждение: очень важно, чтобы все прошиваемые приложения были подписаны либо вручную после сборки, либо автоматически во время сборки.
[Дополнительные возможности]
Отладка JTAG. По умолчанию, когда разрешена конфигурация Secure Boot, отладка JTAG через eFuse запрещается. Загрузчик прошивает этот eFuse во время первой загрузки, одновременно с прошивкой eFuse, который разрешает Secure Boot.
См. "JTAG with Flash Encryption or Secure Boot" в советах [8] для дополнительной информации по использованию отладки JTAG, когда разрешена конфигурация Secure Boot, или разрешена проверка подписанного приложения.
[Словарик]
OTA Over The Air, технология загрузки (обновления) по радиоканалу.
PEM Privacy Enhanced Mail, текстовый файл, содержащий сертификат подписи или ключ шифрования в виде ASCII-текста.
RSA аббревиатура от фамилий Rivest, Shamir и Adleman, криптографический алгоритм с открытым ключом, основывающийся на вычислительной сложности задачи факторизации больших целых чисел (из Википедии).
RSA-PSS RSA Signature Scheme with Probabilistic Signature Scheme, асимметричный алгоритм цифровой подписи (см. Википедию).
[Ссылки]
1. ESP32 Secure Boot V2 site:docs.espressif.com. 2. ESP32 Secure Boot V1. 3. ESP32 Bootloader. 4. ESP32: контроллер eFuse. 5. ESP32 eFuse Manager. 6. ESP32: обновление по радиоканалу (OTA). 7. Конфигурация проекта ESP-IDF. 8. ESP32 Tips and Quirks site:docs.espressif.com. |