Merge branch 'change/secure_boot_config_description' into 'master'

Improve description of the config SECURE_BOOT_V2_ALLOW_EFUSE_RD_DIS

Closes IDF-9161

See merge request espressif/esp-idf!32651
This commit is contained in:
Harshal Patil 2024-08-21 22:08:23 +08:00
commit a00d22197c
3 changed files with 123 additions and 68 deletions

View File

@ -776,6 +776,33 @@ menu "Security features"
This can lead to permanent bricking of the device, in case all keys are revoked
because of signature verification failure.
config SECURE_BOOT_V2_ALLOW_EFUSE_RD_DIS
bool "Do not disable the ability to further read protect eFuses"
depends on SECURE_BOOT_V2_ENABLED
default n
help
If not set (default, recommended), on first boot the bootloader will burn the WR_DIS_RD_DIS
efuse when Secure Boot is enabled. This prevents any more efuses from being read protected.
If this option is set, it will remain possible to write the EFUSE_RD_DIS efuse field after Secure
Boot is enabled. This may allow an attacker to read-protect the BLK2 efuse (for ESP32) and
BLOCK4-BLOCK10 (i.e. BLOCK_KEY0-BLOCK_KEY5)(for other chips) holding the secure boot public key digest,
causing an immediate denial of service and possibly allowing an additional fault injection attack to
bypass the signature protection.
The option must be set when you need to program any read-protected key type into the efuses,
e.g., HMAC, ECDSA etc. after secure boot has already been enabled on the device.
Please refer to secure boot V2 documentation guide for more details.
NOTE: Once a BLOCK is read-protected, the application will read all zeros from that block
NOTE: If "UART ROM download mode (Permanently disabled (recommended))" or
"UART ROM download mode (Permanently switch to Secure mode (recommended))" is set,
then it is __NOT__ possible to read/write efuses using espefuse.py utility.
However, efuse can be read/written from the application
Please refer to the Secure Boot V2 documentation guide for more information.
config SECURE_BOOT_FLASH_BOOTLOADER_DEFAULT
bool "Flash bootloader along with other artifacts when using the default flash command"
depends on SECURE_BOOT_V2_ENABLED && SECURE_BOOT_BUILD_SIGNED_BINARIES
@ -956,26 +983,6 @@ menu "Security features"
image to this length. It is generally not recommended to set this option, unless you have a legacy
partitioning scheme which doesn't support 64KB aligned partition lengths.
config SECURE_BOOT_V2_ALLOW_EFUSE_RD_DIS
bool "Allow additional read protecting of efuses"
depends on SECURE_BOOT_INSECURE && SECURE_BOOT_V2_ENABLED
help
If not set (default, recommended), on first boot the bootloader will burn the WR_DIS_RD_DIS
efuse when Secure Boot is enabled. This prevents any more efuses from being read protected.
If this option is set, it will remain possible to write the EFUSE_RD_DIS efuse field after Secure
Boot is enabled. This may allow an attacker to read-protect the BLK2 efuse (for ESP32) and
BLOCK4-BLOCK10 (i.e. BLOCK_KEY0-BLOCK_KEY5)(for other chips) holding the public key digest, causing an
immediate denial of service and possibly allowing an additional fault injection attack to
bypass the signature protection.
NOTE: Once a BLOCK is read-protected, the application will read all zeros from that block
NOTE: If "UART ROM download mode (Permanently disabled (recommended))" or
"UART ROM download mode (Permanently switch to Secure mode (recommended))" is set,
then it is __NOT__ possible to read/write efuses using espefuse.py utility.
However, efuse can be read/written from the application
config SECURE_BOOT_ALLOW_UNUSED_DIGEST_SLOTS
bool "Leave unused digest slots available (not revoke)"
depends on SECURE_BOOT_INSECURE && SOC_EFUSE_REVOKE_BOOT_KEY_DIGESTS

View File

@ -21,6 +21,8 @@ Secure Boot v2
{IDF_TARGET_SBV2_DEFAULT_SCHEME:default="RSA", esp32c2="ECDSA (v2), esp32c5="ECDSA (v2)"}
{IDF_TARGET_EFUSE_WR_DIS_RD_DIS:default="ESP_EFUSE_WR_DIS_RD_DIS", esp32="ESP_EFUSE_WR_DIS_EFUSE_RD_DISABLE"}
.. important::
This document is about Secure Boot v2, supported on {IDF_TARGET_NAME} {IDF_TARGET_ECO_VERSION}.
@ -431,10 +433,32 @@ Restrictions After Secure Boot Is Enabled
- Any updated bootloader or app will need to be signed with a key matching the digest already stored in eFuse.
- After Secure Boot is enabled, no further eFuses can be read-protected. If :doc:`/security/flash-encryption` is enabled then the bootloader will ensure that any flash encryption key generated on the first boot will already be read-protected. If :ref:`CONFIG_SECURE_BOOT_INSECURE` is enabled, then this behavior can be disabled, but this is not recommended.
- Please note that enabling Secure Boot or flash encryption disables the USB-OTG USB stack in the ROM, disallowing updates via the serial emulation or Device Firmware Update (DFU) on that port.
Burning read-protected keys
~~~~~~~~~~~~~~~~~~~~~~~~~~~
After Secure Boot is enabled, no further eFuses can be read-protected, because this might allow an attacker to read-protect the efuse block holding the public key digest, causing an immediate denial of service and possibly allowing an additional fault injection attack to bypass the signature protection.
If :doc:`/security/flash-encryption` is enabled by the 2nd stage bootloader, it ensures that the flash encryption key generated on the first boot shall already be read-protected.
In case you need to read-protect a key after Secure Boot has been enabled on the device, for example,
.. list::
:SOC_FLASH_ENC_SUPPORTED:* the flash encryption key
:SOC_HMAC_SUPPORTED:* HMAC keys
:SOC_ECDSA_SUPPORTED:* ECDSA keys
:SOC_KEY_MANAGER_SUPPORTED:* Key Manager keys
you need to enable the config :ref:`CONFIG_SECURE_BOOT_V2_ALLOW_EFUSE_RD_DIS` at the same time when you enable Secure Boot to prevent disabling the ability to read-protect further efuses.
It is highly recommended that all such keys must been burned before enabling secure boot.
In case you need to enable :ref:`CONFIG_SECURE_BOOT_V2_ALLOW_EFUSE_RD_DIS`, make sure that you burn the efuse {IDF_TARGET_EFUSE_WR_DIS_RD_DIS}, using ``esp_efuse_write_field_bit()`` API from ``esp_efuse.h``, once all the read-protected efuse keys have been programmed.
.. _secure-boot-v2-generate-key:

View File

@ -21,6 +21,8 @@
{IDF_TARGET_SBV2_DEFAULT_SCHEME:default="RSA", esp32c2="ECDSA (v2)"}
{IDF_TARGET_EFUSE_WR_DIS_RD_DIS:default="ESP_EFUSE_WR_DIS_RD_DIS", esp32="ESP_EFUSE_WR_DIS_EFUSE_RD_DISABLE"}
.. important::
本文档介绍了安全启动 v2{IDF_TARGET_NAME} {IDF_TARGET_ECO_VERSION} 支持该启动模式。
@ -29,7 +31,7 @@
芯片版本低于 v3.0 的 ESP32 安全启动请参阅 :doc:`secure-boot-v1`。如果你的芯片版本支持安全启动 v2推荐使用此模式相比安全启动 v1 更安全且灵活。
安全启动 v2 使用基于 {IDF_TARGET_SBV2_SCHEME} 的应用程序和引导加载程序 :ref:`second-stage-bootloader` 验证。若需要使用 {IDF_TARGET_SBV2_SCHEME} 方案对应用程序签名,且无需对引导加载程序签名,同样可以参考本文档。
安全启动 v2 使用基于 {IDF_TARGET_SBV2_SCHEME} 的应用程序和引导加载程序 (bootloader) :ref:`second-stage-bootloader` 验证。若需要使用 {IDF_TARGET_SBV2_SCHEME} 方案对应用程序签名,且无需对 bootloader 签名,同样可以参考本文档。
.. only:: esp32
@ -47,7 +49,7 @@
背景
----------
安全启动通过检查每个启动的软件是否已签名来确保设备不会运行任何未经授权(即未签名)的代码。在 {IDF_TARGET_NAME} 上,这些软件包括第二阶段的引导加载程序和每个应用程序的二进制文件。注意,第一阶段的引导加载程序是无法更改的 ROM 代码,因此不需要签名。
安全启动通过检查每个启动的软件是否已签名来确保设备不会运行任何未经授权(即未签名)的代码。在 {IDF_TARGET_NAME} 上,这些软件包括第二阶段的 bootloader 和每个应用程序的二进制文件。注意,第一阶段的 bootloader 是无法更改的 ROM 代码,因此不需要签名。
.. only:: esp32 or (SOC_SECURE_BOOT_V2_RSA and not SOC_SECURE_BOOT_V2_ECC)
@ -63,9 +65,9 @@
{IDF_TARGET_NAME} 的安全启动包括以下步骤:
1. 第一阶段引导加载程序 (ROM boot) 仍处于 ROM 中,加载第二阶段引导加载程序 (bootloader),并验证第二阶段引导加载程序的 {IDF_TARGET_SBV2_SCHEME} 签名。验证通过后方可进入第二阶段。
1. 第一阶段 bootloader (ROM boot) 仍处于 ROM 中,加载第二阶段 bootloader并验证第二阶段 bootloader 的 {IDF_TARGET_SBV2_SCHEME} 签名。验证通过后方可进入第二阶段。
2. 二级引导程序加载特定应用程序镜像时,会验证应用程序的 {IDF_TARGET_SBV2_SCHEME} 签名。若验证通过,则执行应用程序镜像。
2. 第二阶段 bootloader 加载特定应用程序镜像时,会验证应用程序的 {IDF_TARGET_SBV2_SCHEME} 签名。若验证通过,则执行应用程序镜像。
优势
@ -83,10 +85,10 @@
- {IDF_TARGET_NAME} 支持永久注销个别公钥,对此可以选择保守或激进的配置。
- 保守配置:在此情况下,只有在引导加载程序和应用程序成功迁移到新密钥后才会注销旧密钥。
- 保守配置:在此情况下,只有在 bootloader 和应用程序成功迁移到新密钥后才会注销旧密钥。
- 激进配置:在此情况下,只要使用此密钥验证失败,就会立即注销该密钥。
- 应用程序和软件引导加载程序采用相同的镜像格式和签名验证方法。
- 应用程序和软件 bootloader 采用相同的镜像格式和签名验证方法。
- 设备不存储任何机密信息,因此可以免受被动侧通道攻击的影响,如时序分析或功耗分析。
@ -96,39 +98,39 @@
以下为使用安全启动 v2 流程的概述。有关如何启用安全启动,请参阅 :ref:`secure-boot-v2-howto`
安全启动 v2 使用专用的 *签名块* 验证引导加载程序镜像和应用程序二进制镜像,每个镜像末尾都附加了一个单独生成的签名块。
安全启动 v2 使用专用的 *签名块* 验证 bootloader 镜像和应用程序二进制镜像,每个镜像末尾都附加了一个单独生成的签名块。
.. only:: esp32
在 ESP32 芯片版本 v3.0 中,引导加载程序或应用程序镜像只能附加一个签名块。
在 ESP32 芯片版本 v3.0 中,bootloader 或应用程序镜像只能附加一个签名块。
.. only:: esp32c2
在 {IDF_TARGET_NAME} 中,引导加载程序或应用程序镜像只能附加一个签名块。
在 {IDF_TARGET_NAME} 中,bootloader 或应用程序镜像只能附加一个签名块。
.. only:: SOC_EFUSE_REVOKE_BOOT_KEY_DIGESTS
在 {IDF_TARGET_NAME} 中,引导加载程序或应用程序镜像至多可以附加三个签名块。
在 {IDF_TARGET_NAME} 中,bootloader 或应用程序镜像至多可以附加三个签名块。
每个签名块包含前一个镜像的签名和相应的 {IDF_TARGET_SBV2_KEY} 公钥。有关格式详情,请参阅 :ref:`signature-block-format`。{IDF_TARGET_SBV2_KEY} 公钥的摘要存储在 eFuse 中。
应用程序镜像不仅在每次启动时验证,也会在每次空中升级 (OTA) 时验证。如果当前所选 OTA 应用程序镜像无法验证,引导加载程序将回退,并寻找其他正确签名的应用程序镜像。
应用程序镜像不仅在每次启动时验证,也会在每次空中升级 (OTA) 时验证。如果当前所选 OTA 应用程序镜像无法验证,bootloader 将回退,并寻找其他正确签名的应用程序镜像。
安全启动 v2 流程遵循以下步骤:
1. 启动时ROM 代码检查 eFuse 中的安全启动 v2 位。如果禁用了安全启动,则执行普通启动;如果启用了安全启动,将继续以下步骤。
2. ROM 代码验证引导加载程序的签名块,请参阅 :ref:`verify_signature-block`。如果验证失败,启动过程将中止。
2. ROM 代码验证 bootloader 的签名块,请参阅 :ref:`verify_signature-block`。如果验证失败,启动过程将中止。
3. ROM 代码使用原始镜像数据、相应的签名块以及 eFuse 验证引导加载程序镜像,请参阅 :ref:`verify_image`。如果验证失败,启动过程将中止。
3. ROM 代码使用原始镜像数据、相应的签名块以及 eFuse 验证 bootloader 镜像,请参阅 :ref:`verify_image`。如果验证失败,启动过程将中止。
4. ROM 代码执行引导加载程序
4. ROM 代码执行 bootloader
5. 引导加载程序验证应用程序镜像的签名块,请参阅 :ref:`verify_signature-block`。如果验证失败,启动过程将中止。
5. bootloader 验证应用程序镜像的签名块,请参阅 :ref:`verify_signature-block`。如果验证失败,启动过程将中止。
6. 引导加载程序使用原始镜像数据、相应的签名块以及 eFuse 验证引导加载程序镜像,请参阅 :ref:`verify_image`。如果验证失败,启动过程将中止。如果验证失败,但发现了其他应用程序镜像,引导加载程序将使用步骤 5 到 7 验证另一个镜像。该过程将重复,直至找到有效镜像,或所有镜像验证完毕。
6. bootloader 使用原始镜像数据、相应的签名块以及 eFuse 验证 bootloader 镜像,请参阅 :ref:`verify_image`。如果验证失败,启动过程将中止。如果验证失败,但发现了其他应用程序镜像, bootloader 将使用步骤 5 到 7 验证另一个镜像。该过程将重复,直至找到有效镜像,或所有镜像验证完毕。
7. 引导加载程序执行经验证的应用程序镜像。
7. bootloader 执行经验证的应用程序镜像。
.. _signature-block-format:
@ -311,29 +313,29 @@
如果存储在某个签名块中的公钥是适用于当前设备的有效公钥,且该签名块中存储的签名与从 flash 中读取的镜像数据计算出的签名匹配,则该镜像通过验证。
1. 将嵌入在引导加载程序签名块中的公钥生成的 SHA-256 哈希摘要与存储在 eFuse 中的摘要进行比较,如果公钥的哈希摘要无法与 eFuse 中的任何哈希摘要匹配,则验证失败。
1. 将嵌入在 bootloader 签名块中的公钥生成的 SHA-256 哈希摘要与存储在 eFuse 中的摘要进行比较,如果公钥的哈希摘要无法与 eFuse 中的任何哈希摘要匹配,则验证失败。
2. 生成应用程序镜像摘要,将其与签名块中的镜像摘要进行匹配,如果无法匹配,则验证失败。
.. only:: esp32 or (SOC_SECURE_BOOT_V2_RSA and not SOC_SECURE_BOOT_V2_ECC)
3. 使用公钥,采用 RSA-PSSRFC8017 的第 8.1.2 节)算法,验证引导加载程序镜像的签名,并与步骤 (2) 中计算的镜像摘要比较。
3. 使用公钥,采用 RSA-PSSRFC8017 的第 8.1.2 节)算法,验证 bootloader 镜像的签名,并与步骤 (2) 中计算的镜像摘要比较。
.. only:: SOC_SECURE_BOOT_V2_ECC and not SOC_SECURE_BOOT_V2_RSA
3. 使用公钥,采用 ECDSARFC6090 的第 5.3.3 节)算法,验证引导加载程序镜像的签名,并与步骤 (2) 中计算的镜像摘要比较。
3. 使用公钥,采用 ECDSARFC6090 的第 5.3.3 节)算法,验证 bootloader 镜像的签名,并与步骤 (2) 中计算的镜像摘要比较。
.. only:: SOC_SECURE_BOOT_V2_ECC and SOC_SECURE_BOOT_V2_RSA
1. 使用公钥,采用 RSA-PSSRFC8017 的第 8.1.2 节)算法或 ECDSARFC6090 的第 5.3.3 节)算法,验证引导加载程序镜像的签名,并与步骤 (2) 中计算的镜像摘要比较。
1. 使用公钥,采用 RSA-PSSRFC8017 的第 8.1.2 节)算法或 ECDSARFC6090 的第 5.3.3 节)算法,验证 bootloader 镜像的签名,并与步骤 (2) 中计算的镜像摘要比较。
引导加载程序大小
bootloader 大小
------------------
启用安全启动和/或 flash 加密都会增加引导加载程序的大小,因此可能需要更新分区表偏移量,请参阅 :ref:`bootloader-size`
启用安全启动和/或 flash 加密都会增加 bootloader 的大小,因此可能需要更新分区表偏移量,请参阅 :ref:`bootloader-size`
禁用 :ref:`CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES` 时,引导加载程序将使用 ``esptool````elf2image`` 命令中的 ``--pad-to-size`` 选项进行扇区填充,每个扇区大小为 4 KB。
禁用 :ref:`CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES` 时,bootloader 将使用 ``esptool````elf2image`` 命令中的 ``--pad-to-size`` 选项进行扇区填充,每个扇区大小为 4 KB。
.. _efuse-usage:
@ -403,17 +405,17 @@
在生产环境下,建议使用 OpenSSL 或其他行业标准的加密程序生成密钥对,详情请参阅 :ref:`secure-boot-v2-generate-key`
7. 运行 ``idf.py bootloader`` 构建启用了安全启动的引导加载程序,构建输出中会包含一个烧录命令的提示,使用 ``esptool.py write_flash`` 烧录。
7. 运行 ``idf.py bootloader`` 构建启用了安全启动的 bootloader ,构建输出中会包含一个烧录命令的提示,使用 ``esptool.py write_flash`` 烧录。
8. 当你准备好烧录引导加载程序时,请运行指定命令并等待烧录完成。注意,此处的指定命令需要手动输入,构建系统不会执行此过程。
8. 当你准备好烧录 bootloader 时,请运行指定命令并等待烧录完成。注意,此处的指定命令需要手动输入,构建系统不会执行此过程。
9. 运行 ``idf.py flash`` 构建并烧录分区表以及刚刚构建的应用程序镜像,该镜像使用步骤 6 中生成的签名密钥进行签名。
.. note::
如果启用了安全启动,``idf.py flash`` 不会烧录引导加载程序
如果启用了安全启动,``idf.py flash`` 不会烧录 bootloader
10. 重置 {IDF_TARGET_NAME},它将启动你烧录的软件引导加载程序。该软件引导加载程序会在芯片上启用安全启动,然后验证应用程序镜像签名,并启动应用程序。请查看 {IDF_TARGET_NAME} 的串行控制器输出,确保已启用安全启动,且没有因构建配置发生错误。
10. 重置 {IDF_TARGET_NAME},它将启动你烧录的软件 bootloader 。该软件 bootloader 会在芯片上启用安全启动,然后验证应用程序镜像签名,并启动应用程序。请查看 {IDF_TARGET_NAME} 的串行控制器输出,确保已启用安全启动,且没有因构建配置发生错误。
.. note::
@ -423,18 +425,40 @@
如果在初次启动过程中重置或关闭了 {IDF_TARGET_NAME},它会在下次启动时重新开始上述步骤。
11. 在后续启动过程中,安全启动硬件会验证软件引导加载程序是否更改,软件引导加载程序会使用其附加的签名块中经验证的公钥部分,验证已签名的应用程序镜像。
11. 在后续启动过程中,安全启动硬件会验证软件 bootloader 是否更改,软件 bootloader 会使用其附加的签名块中经验证的公钥部分,验证已签名的应用程序镜像。
启用安全启动后的限制
-----------------------------------------
- 任何更新过的引导加载程序或应用程序都需要使用与已存储在 eFuse 中的摘要相匹配的密钥来签名。
- 启用安全启动后,将不再对任何 eFuse 进行读保护。如果启用了 :doc:`/security/flash-encryption`,引导加载程序将确保在初次启动时生成的任何 flash 加密密钥已进行读保护。如果启用了 :ref:`CONFIG_SECURE_BOOT_INSECURE`,则可以禁用对设置读保护的限制,但不建议这样做。
- 任何更新过的 bootloader 或应用程序都需要使用与已存储在 eFuse 中的摘要相匹配的密钥来签名。
- 注意,启用安全启动或 flash 加密会禁用 ROM 中的 USB-OTG USB 栈,阻止通过该端口进行串行仿真或设备固件更新 (DFU)。
烧录读保护密钥
~~~~~~~~~~~~~~~
一旦启用安全启动,就无法再对 eFuses 进行读保护,这可以避免攻击者对存储公共密钥摘要的 eFuse 块进行读保护,进而导致系统无法验证和处理签名,系统服务无法正常运行。
如果第二阶段 bootloader 启用了 :doc:`/security/flash-encryption`,它会确保在第一次启动时生成的 flash 加密密钥被读保护。
如需在设备启用安全启动后对密钥进行读保护,如:
.. list::
:SOC_FLASH_ENC_SUPPORTED:* flash 加密密钥
:SOC_HMAC_SUPPORTED:* HMAC 密钥
:SOC_ECDSA_SUPPORTED:* ECDSA 密钥
:SOC_KEY_MANAGER_SUPPORTED:* 密钥管理器密钥
请在启用安全启动的同时启用配置项 :ref:`CONFIG_SECURE_BOOT_V2_ALLOW_EFUSE_RD_DIS`,以防止禁用 eFuses 读保护功能。
建议在启用安全启动之前,完成全部密钥的烧录。
如需启用配置项 :ref:`CONFIG_SECURE_BOOT_V2_ALLOW_EFUSE_RD_DIS`,请在所有读保护 eFuses 密钥烧录后,使用 ``esp_efuse.h````esp_efuse_write_field_bit()`` API 烧录 eFuses {IDF_TARGET_EFUSE_WR_DIS_RD_DIS}。
.. _secure-boot-v2-generate-key:
@ -545,7 +569,7 @@
* 在具备高质量熵源的系统上生成签名密钥。
* 时刻对签名密钥保密,泄漏此密钥将危及安全启动系统。
* 不允许第三方使用 ``idf.py secure-`` 命令来观察密钥生成或签名过程的任何细节,这两个过程都容易受到定时攻击或其他侧信道攻击的威胁。
* 在安全启动配置中启用所有安全启动选项,包括 flash 加密、禁用 JTAG、禁用 BASIC ROM 解释器和禁用 UART 引导加载程序的加密 flash 访问。
* 在安全启动配置中启用所有安全启动选项,包括 flash 加密、禁用 JTAG、禁用 BASIC ROM 解释器和禁用 UART bootloader 的加密 flash 访问。
* 结合 :doc:`flash-encryption` 使用安全启动,防止本地读取 flash 内容。
.. only:: SOC_EFUSE_REVOKE_BOOT_KEY_DIGESTS
@ -556,18 +580,18 @@
* 应独立计算并分别存储 1 到 3 个 {IDF_TARGET_SBV2_KEY} 公钥对(密钥 #0, #1, #2
* 完成烧录后,应设置 KEY_DIGEST eFuse 为写保护位。
* 未使用的 KEY_DIGEST 槽必须烧录其相应的 KEY_REVOKE eFuse以永久禁用。请在设备离开工厂前完成此操作。
* 烧录 eFuse 可以由软件引导加载程序在首次从 menuconfig 启用 ``Secure Boot v2`` 后进行,也可以使用 ``espefuse.py``,后者与 ROM 中的串行引导加载程序通信。
* 烧录 eFuse 可以由软件 bootloader 在首次从 menuconfig 启用 ``Secure Boot v2`` 后进行,也可以使用 ``espefuse.py``,后者与 ROM 中的串行 bootloader 通信。
* KEY_DIGEST 应从密钥摘要 #0 开始,按顺序编号。如果使用了密钥摘要 #1则必须使用密钥摘要 #0。如果使用了密钥摘要 #2则必须使用密钥摘要 #0 和 #1。
* 软件引导加载程序不支持 OTA 升级,它将至少由一个私钥签名,也可能使用全部三个私钥,并在工厂内烧录。
* 软件 bootloader 不支持 OTA 升级,它将至少由一个私钥签名,也可能使用全部三个私钥,并在工厂内烧录。
* 应用程序应仅由单个私钥签名,其他私钥应妥善保管。但如果需要注销某些私钥,也可以使用多个签名私钥,请参阅下文的 :ref:`secure-boot-v2-key-revocation`
多个密钥管理
-------------
* 在烧录引导程序之前,应使用设备整个生命周期所需的所有私钥对引导程序签名。
* 在烧录 bootloader 之前,应使用设备整个生命周期所需的所有私钥对 bootloader 签名。
* 构建系统每次只能使用一个私钥签名,如果需要,你必须手动运行命令以附加更多签名。
* 你可以使用 ``idf.py secure-sign-data`` 的附加功能,此命令也将在启用安全启动 v2 的引导加载程序编译的末尾显示。
* 你可以使用 ``idf.py secure-sign-data`` 的附加功能,此命令也将在启用安全启动 v2 的 bootloader 编译的末尾显示。
.. code-block::
@ -587,13 +611,13 @@
* 密钥按线性顺序处理,即密钥 #0、密钥 #1、密钥 #2。
* 应用程序每次应只使用一个密钥签名,尽量避免暴露未使用的私钥。
* 引导加载程序可以使用来自工厂的多个函数签名。
* bootloader 可以使用来自工厂的多个函数签名。
.. note::
请注意,启用配置 :ref:`CONFIG_SECURE_BOOT_ALLOW_UNUSED_DIGEST_SLOTS` 只能确保 **应用程序** 不会撤销未使用的摘要槽。
若想在设备首次启动时启用安全启动,那么即使启用了上述配置,引导加载程序也会在启用安全启动时撤销未使用的摘要槽,因为保留未使用的密钥槽会构成安全隐患。
如果在开发流程中需要保留未使用摘要槽,则应从外部启用安全启动 (:ref:`enable-secure-boot-v2-externally`),而不是在启动设备时启用安全启动,这样引导加载程序就无需启用安全启动,从而避免安全隐患。
若想在设备首次启动时启用安全启动,那么即使启用了上述配置,bootloader 也会在启用安全启动时撤销未使用的摘要槽,因为保留未使用的密钥槽会构成安全隐患。
如果在开发流程中需要保留未使用摘要槽,则应从外部启用安全启动 (:ref:`enable-secure-boot-v2-externally`),而不是在启动设备时启用安全启动,这样 bootloader 就无需启用安全启动,从而避免安全隐患。
保守方法
~~~~~~~~~~~~
@ -604,11 +628,11 @@
2. 新的 OTA 更新写入未使用的 OTA 应用程序分区。
3. 验证新应用程序的签名块。对比公钥与 eFuse 中烧录的摘要,并使用已验证的公钥验证应用程序。
4. 将活动分区设置为新的 OTA 应用程序分区。
5. 设备重置并加载使用密钥 #N-1 验证的引导加载程序,随后启动使用密钥 #N 验证的新应用程序。
6. 新应用程序使用密钥 #N 验证引导程序,这是最后的检查,然后运行代码注销密钥 #N-1即设置 KEY_REVOKE eFuse 位。
5. 设备重置并加载使用密钥 #N-1 验证的 bootloader ,随后启动使用密钥 #N 验证的新应用程序。
6. 新应用程序使用密钥 #N 验证 bootloader ,这是最后的检查,然后运行代码注销密钥 #N-1即设置 KEY_REVOKE eFuse 位。
7. 可以使用 API `esp_ota_revoke_secure_boot_public_key()` 注销密钥 #N-1。
* 类似的方法也可以用于物理重新烧录,以使用新的密钥,还可以同时更改引导加载程序的内容。
* 类似的方法也可以用于物理重新烧录,以使用新的密钥,还可以同时更改 bootloader 的内容。
.. _secure-boot-v2-aggressive-key-revocation:
@ -636,7 +660,7 @@
手动命令
~~~~~~~~~~~~~~~
安全启动已集成到 ESP-IDF 构建系统中,因此 ``idf.py build`` 将进行应用程序镜像签名。启用 :ref:`CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES` 后,``idf.py bootloader`` 将生成一个已签名的引导加载程序
安全启动已集成到 ESP-IDF 构建系统中,因此 ``idf.py build`` 将进行应用程序镜像签名。启用 :ref:`CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES` 后,``idf.py bootloader`` 将生成一个已签名的 bootloader
然而,也可以使用 ``idf.py`` 工具生成独立的签名和摘要。
@ -670,7 +694,7 @@ Keyfile 是包含 {IDF_TARGET_SBV2_KEY} 签名私钥的 PEM 文件。
无需启用硬件安全启动选项,即可在 OTA 更新时验证应用程序的安全启动 v2 签名。这种方法采用了与安全启动 v2 相同的应用程序签名方案,但不同于硬件安全启动,软件安全启动无法阻止能够写入 flash 的攻击者绕过签名验证。
如果在启动时无法接受安全启动验证的延迟,和/或威胁模型不包括物理访问或攻击者在 flash 中写入引导加载程序或应用程序分区,则适合使用未启用硬件安全启动的验证。
如果在启动时无法接受安全启动验证的延迟,和/或威胁模型不包括物理访问或攻击者在 flash 中写入 bootloader 或应用程序分区,则适合使用未启用硬件安全启动的验证。
在此模式下,当前运行的应用程序签名块中的公钥将用于验证新更新的应用程序签名。更新时,不会验证运行中的应用程序签名,而是假定它有效。通过这种方式,系统建立了从当前运行的应用程序到新更新的应用程序之间的信任链。
@ -726,6 +750,6 @@ Keyfile 是包含 {IDF_TARGET_SBV2_KEY} 签名私钥的 PEM 文件。
JTAG 调试
~~~~~~~~~~~~~~
启用安全启动模式时eFuse 会默认禁用 JTAG。初次启动时引导加载程序即禁用 JTAG 调试功能,并启用安全启动模式。
启用安全启动模式时eFuse 会默认禁用 JTAG。初次启动时bootloader 即禁用 JTAG 调试功能,并启用安全启动模式。
有关在启用安全启动或已签名应用程序验证的情况下使用 JTAG 调试的更多信息,请参阅 :ref:`jtag-debugging-security-features`