当前文档版本为 v1.2.2,您可以访问当前页面的 开发中 版本以获取最近可能的更新。

Firmware Encryption 开发指南

1 概述

PAN108x SoC 提供了一个名为 Firmware Encryption 的固件加密机制,用于通过固件加密、硬件解密的付出保护 SoC Flash 中的关键代码。

2 在 App 工程中使能固件加密

任意 App 工程均可通过如下的简单配置使能固件加密功能,并编译生成加密固件,本文以 fw_encryption 例程为例进行说明。

2.1 在 prj.conf 文件中开启加密相关配置

在 App 工程的 prj.conf 中配置以下宏开关以使能固件加密机制:

# Enable Firmware Encryption Feature
CONFIG_FIRMWARE_ENCRYPTION=y
# Set the Encrypt Information File Name for Search
CONFIG_ENCRYPT_INFO_FILE_NAME="encrypt_info.yaml"
# Set the spetial flash area for encrypted code in
CONFIG_ENCRYPT_FLASH_OFFSET=0x303

其中:

  • CONFIG_FIRMWARE_ENCRYPTION:使能加密模块

  • CONFIG_ENCRYPT_INFO_FILE_NAME:指定加密配置文件的名称,默认为 encrypt_info.yaml

  • CONFIG_ENCRYPT_FLASH_OFFSET:指定加密代码位于 Flash 的位置,以 Flash Page(256B)为单位;例如上述例程中此项配置为 0x303,即对应 Flash 地址为 0x30300

    注意

    1. 此配置需要与加密配置文件 encrypt_info.yaml 中的 encrypt_flash_offset 项保持一致!

    2. 若无特殊需要,(在使能 Bootloader 的情况下)建议在实际项目中将加密 Flash 地址配置为与本例程中保持一致(即 CONFIG_ENCRYPT_FLASH_OFFSET=0x303),这样对 Flash 的利用率最高。

2.2 在 encrypt_info.yaml 文件中指定加密相关参数

在前述 App 工程的 prj.conf 文件中,通过 CONFIG_ENCRYPT_INFO_FILE_NAME="encrypt_info.yaml" 指定了一个名为 encrypt_info.yaml 的加密配置文件,其内容如下:

encrypt_info:
  secure_enable: true
  anti_injection_enable: true
  encrypt_flash_offset: 0x303 # The 303rd page of flash (or say absolute flash address 0x30300)
  encrypt_key: '4c68384139f574d836bcf34e9dfb01bf' # AES-128 key in hexadecimal string format
image_info:
  expected_start_addr: 0x30000 # For encrypt tool to validate input hex image file

其中各个 item 解释如下:

  • secure_enable: true:使能固件加密功能

  • anti_injection_enable: true:使能防注入保护功能,与固件加密功能结合使用,作用是防止通过 SWD Debug 的方式获取到加密 Flash 区域的明文信息

  • encrypt_flash_offset: 0x303:配置加密 Flash 的第几个 Page(大小 256 字节),如 0x303 表示加密 Flash 的第 303 个 Page,对应 Flash 绝对地址为 0x30300;注意此处配置的值一定要与 App 功能 prj.conf 中的配置 CONFIG_ENCRYPT_FLASH_OFFSET 值相同!

  • encrypt_key: '4c68384139f574d836bcf34e9dfb01bf':配置加密秘钥(AES-128)

  • expected_start_addr: 0x30000:配置当前 Image 固件的起始地址为 0x30000,用于编译过程中 Encrypt Tool 交叉验证输入 Image 的地址是否有效

警告

  1. 本文件中包含明文的加密秘钥(encrypt_key),一定要妥善保管,不可随意外传,以防密钥泄露!

  2. 在编译过程中,Post Build 流程会基于本文件生成一个二次加密后的 encrypt_info_enc.bin 文件,此文件中会对秘钥添加扰码,因此在后续 PanLink 载入加密信息的过程中建议使用此文件,而不是明文的 yaml 文件。

2.3 在 App 程序中编写待保护的加密函数

PAN108x SoC 加密区域大小为 256 字节,因此项目中应选取一个重要且简短的函数作为加密函数段。

代码中只需在期望加密的函数前,添加一个指示加密的特殊语法标记 __in_section_unique(encrypted_section) 即可:

#ifdef CONFIG_FIRMWARE_ENCRYPTION
__in_section_unique(encrypted_section)
#endif
void encrypted_test_function(uint32_t *calculation)
{
	/* Do some secret operations/calculations here */
	*calculation = *(uint32_t *)((uint32_t)(&encrypted_test_function) & 0xFFFFFFFE);
	printk("Hello from %s!\n", __func__);
}

上述代码即实现了将 encrypted_test_function() 函数编译到 Flash 加密区域的效果。

2.4 编译生成加密固件

App 工程经过上述修改后,编译即可生成加密后的固件:

  • zephyr_enc.bin:编译输出的加密后的二进制格式 App Image

  • zephyr_enc.hex:编译输出的加密后的十六进制文本格式 App Image

  • zephyr_enc.signed.bin加密并签名后的二进制格式的 App Image,可用于 DFU/OTA

  • zephyr_enc.signed.hex加密并签名后的十六进制文本格式的 App Image

  • zImageMerged.bin:合并了 Bootloader 和 加密签名后 App Image 的二进制格式 Image

  • zImageMerged.hex:合并了 Bootloader 和 加密签名后 App Image 的十六进制文本格式 Image