密钥管理与密钥派生开发指南
本文档以 security_demo_key.c 为例,介绍在 HiDiTing 开发板上实现 HKDF 密钥派生与 Keyslot 应用的开发流程,以及 Security Unified KM/KDF 接口的使用方法。
配套 Demo 使用公开的 RFC 5869 测试向量和内存 Keyslot,不读取、烧写或修改 eFuse。硬件密钥章节用于说明接口关系和安全约束;实际硬件密钥配置必须结合芯片安全方案、eFuse 状态和量产流程进行专项评审。
密钥管理与密钥派生背景知识
密钥安全不只取决于算法强度,还取决于密钥如何生成、派生、存储、加载、使用、轮换和销毁。将一个高强度算法与硬编码密钥结合,仍然可能形成严重安全风险。
密钥生命周期

各阶段的安全目标:
| 阶段 | 目标 |
|---|---|
| 生成/输入 | 使用足够熵或可信根密钥,不把默认密码当作密钥 |
| 派生 | 使用唯一 Salt 和明确的上下文 Info,隔离不同用途 |
| 加载 | 尽量缩短明文密钥在普通内存中的停留时间 |
| 使用 | 将 Keyslot 类型、算法引擎和目标算法正确匹配 |
| 轮换 | 支持密钥版本和回滚策略,避免永久使用单一业务密钥 |
| 销毁 | 先停止使用,再销毁 Keyslot,最后安全清理明文缓冲区 |
HKDF 与 PBKDF2
| 算法 | 输入特点 | 主要用途 | 不适合 |
|---|---|---|---|
| HKDF | 已具有一定熵的密钥材料 IKM | 从共享秘密、设备秘密派生一个或多个业务密钥 | 直接处理低熵用户口令 |
| PBKDF2 | 低熵口令 + Salt + 迭代次数 | 从口令派生密钥,提高穷举成本 | 代替随机密钥生成器 |
HKDF 分为两个逻辑阶段:
- Extract:使用 Salt 和 IKM 得到伪随机密钥 PRK。
- Expand:使用 PRK 和 Info 生成指定长度的输出密钥材料 OKM。
组合接口 uapi_drv_cipher_hkdf 在单次调用中完成 Extract 和 Expand。
| 参数 | 含义 | 设计建议 |
|---|---|---|
| IKM | Input Key Material,输入密钥材料 | 不应直接使用可预测文本 |
| Salt | 提取阶段的盐值 | 按协议或密钥域管理,不要求保密但应避免无依据复用 |
| Info | 派生上下文 | 放入产品、协议、方向、用途、版本等域分离信息 |
| PRK | Extract 输出 | 作为中间秘密处理 |
| OKM | 最终输出密钥材料 | 按具体算法截取正确长度并限制用途 |
明文密钥与硬件密钥
| 类型 | 加载接口 | 特点 | 使用建议 |
|---|---|---|---|
| 明文密钥 | uapi_drv_keyslot_set_clear_key |
应用需要在普通内存中持有密钥后再加载 | 用于示例、迁移或上层已安全提供密钥的场景 |
| 硬件密钥 | uapi_drv_keyslot_set_hard_key |
根据芯片硬件密钥和 Salt 形成工作密钥,应用不可直接读取根密钥 | 量产方案需结合 eFuse 和安全启动设计 |
警告: 未正确烧写或配置对应 eFuse 时,硬件密钥接口可能无法得到预期工作密钥。Demo 不得自动执行 eFuse 烧写,开发环境中的烧写流程也不得直接用于量产。
Keyslot 类型
| Keyslot 类型 | 用途 |
|---|---|
UAPI_DRV_KEYSLOT_TYPE_MCIPHER |
AES、SM4 等对称加解密 |
UAPI_DRV_KEYSLOT_TYPE_HMAC |
HMAC |
UAPI_DRV_KEYSLOT_TYPE_FLASH |
Flash 在线解密 |
KLAD Engine 决定密钥发送到哪个算法引擎:
| KLAD Engine | 对应能力 |
|---|---|
UAPI_DRV_KLAD_ENGINE_AES |
AES |
UAPI_DRV_KLAD_ENGINE_SM4 |
SM4 |
UAPI_DRV_KLAD_ENGINE_SHA2_HMAC |
SHA-2 HMAC |
UAPI_DRV_KLAD_ENGINE_SM3_HMAC |
SM3 HMAC |
Keyslot 类型、KLAD Engine、密钥长度和后续算法必须匹配。
安全目标与能力边界
KM/KDF 能降低密钥直接暴露和无依据复用的风险,但不能独立解决全部密钥管理问题。
| 安全目标 | KM/KDF 能力 | 仍需配套的机制 |
|---|---|---|
| 密钥域分离 | HKDF 的 Salt/Info 可派生不同用途密钥 | 统一的上下文编码和密钥用途策略 |
| 降低明文密钥暴露 | Keyslot 允许消费模块通过句柄使用密钥 | 安全输入、内存清理和最小权限 |
| 硬件根密钥使用 | 硬件密钥接口可形成工作密钥 | eFuse 规划、生命周期、烧写和保护策略 |
| 口令派生 | PBKDF2 增加离线穷举成本 | 强口令、合理迭代参数和限速 |
| 密钥轮换 | 可重新派生并加载新工作密钥 | 版本管理、双密钥过渡和回滚策略 |
| 密钥备份/恢复 | 不直接提供 | 受控备份、灾难恢复和设备返修流程 |
使用 KM/KDF 时,应明确以下能力边界:
- “软件不可读硬件根密钥”不代表整个系统不存在侧信道、错误配置或协议风险。
- Keyslot 句柄不是长期密钥标识,不应跨重启持久化。
- HKDF 输出只有在 IKM 具备足够熵时才适合作为高强度业务密钥。
- PBKDF2 增加口令猜测成本,但不能把弱口令变成不可破解密钥。
模块设计
KM 负责 Keyslot 生命周期和密钥加载;KDF 负责 PBKDF2/HKDF 派生;SYMC/HMAC 等消费模块通过 Keyslot 句柄使用密钥。应用不从 Keyslot 读回密钥。

主要代码位置:
| 层级 | 代码位置 | 作用 |
|---|---|---|
| KDF 接口 | src/include/driver/security_unified/security_kdf.h | PBKDF2、HKDF |
| KM 接口 | src/include/driver/security_unified/security_km.h | Keyslot 和密钥加载 |
| 服务层 | src/drivers/drivers/driver/security_unified/service_layer/hkdf_simple.c | HKDF 服务封装 |
| 服务层 | src/drivers/drivers/driver/security_unified/service_layer/km_simple.c | KM 服务封装 |
| 驱动层 | src/drivers/drivers/driver/security_unified/drv_code/km | Keyslot、PBKDF2 等 |
| 芯片适配 | src/drivers/chips/3322/porting/security_unified | Hi3322 密钥能力配置 |
参数与配置说明
HiDiTingV100 安全配置中与本示例相关的宏包括:
| 配置 | 作用 |
|---|---|
CONFIG_SECURITY_UNIFIED_SUPPORT_KM |
使能 KM;SELiteOS 配置中显式定义 |
CONFIG_HKM_SUPPORT |
使能硬件密钥管理基础能力 |
CONFIG_HASH_SUPPORT_HKDF |
使能 HKDF |
CONFIG_SECURITY_UNIFIED_SUPPORT_PBKDF2 |
使能 PBKDF2 |
CONFIG_SECURITY_UNIFIED_SUPPORT_SYMC |
使能消费 Keyslot 的对称加密模块 |
CONFIG_SYMC_SUPPORT_GCM |
使能 AES-GCM |
Demo 参数:
| 参数 | 示例值 | 说明 |
|---|---|---|
| KDF | HKDF-SHA256 | RFC 5869 Test Case 1 |
| OKM 长度 | 42 字节 | 全量匹配 RFC 5869 期望结果 |
| AES 密钥长度 | OKM 前 16 字节 | 用作 AES-128 测试密钥 |
| Keyslot 类型 | UAPI_DRV_KEYSLOT_TYPE_MCIPHER |
对称加解密 |
| KLAD Engine | UAPI_DRV_KLAD_ENGINE_AES |
AES |
| 硬件密钥 | 不使用 | 避免 eFuse 依赖和误操作 |
密钥长度约束:
- MCIPHER/FLASH 明文密钥长度必须为 16、24 或 32 字节。
- HMAC 明文密钥长度必须小于或等于 128 字节。
- 硬件工作密钥长度必须为 16、24 或 32 字节。
API 接口列表
KDF
| 接口函数 | 说明 |
|---|---|
| uapi_drv_cipher_pbkdf2 | 使用口令、Salt 和迭代次数派生密钥 |
| uapi_drv_cipher_hkdf_extract | HKDF Extract,输出 PRK |
| uapi_drv_cipher_hkdf_expand | HKDF Expand,输出 OKM |
| uapi_drv_cipher_hkdf | 一步完成 HKDF Extract 和 Expand |
KM
| 接口函数 | 说明 |
|---|---|
| uapi_drv_keyslot_setup | 创建指定类型的 Keyslot |
| uapi_drv_keyslot_set_clear_key | 向 Keyslot 加载明文密钥 |
| uapi_drv_keyslot_set_hard_key | 从硬件密钥派生并加载工作密钥 |
| uapi_drv_keyslot_teardown | 销毁 Keyslot |
Keyslot 消费接口
| 接口函数 | 说明 |
|---|---|
| uapi_drv_cipher_symc_gcm_encrypt | 使用 Keyslot 中的 AES 密钥执行 GCM 加密 |
| uapi_drv_cipher_symc_gcm_decrypt_verify | 使用 Keyslot 解密并校验 Tag |
快速跑通密钥管理 Demo
功能说明
AT+SECKEY 示例执行:
- 使用 RFC 5869 Test Case 1 派生并验证 42 字节 HKDF-SHA256 OKM。
- 取 OKM 的前 16 字节作为 AES-128 测试密钥,先用明文密钥路径执行一次 AES-GCM,得到基准密文和 Tag。
- 创建 MCIPHER 类型 Keyslot。
- 使用 AES KLAD Engine 将派生密钥加载到 Keyslot。
- 清理普通内存中的 OKM,再使用 Keyslot 句柄执行 AES-GCM 加密和解密。
- 验证 Keyslot 路径与明文密钥路径生成相同的密文和 Tag,并验证恢复明文。
- 销毁 Keyslot,并安全清理 IKM、PRK/OKM 和临时数据。
示例实现位于 /samples/native_samples/security/security_demo_key.c,命令注册位于 /samples/native_samples/security/security_demo.c。示例中的明文密钥路径仅用于建立可复现的测试基准,不适用于量产密钥方案。
操作流程
Keyslot 生命周期:
Keyslot 的有效期必须覆盖所有使用该句柄的密码运算:
禁止:
编译
Demo 已接入 diting-community 目标。完成一站式 CLI 环境配置后执行:
构建成功后,使用一站式 CLI 烧写固件并打开 UART2 串口监视器。以下为 Windows USB DFU 示例;将 COM3 替换为实际日志串口,其他平台和串口烧写参数参见一站式 CLI 开发环境使用指南。
fbb flash -f "$env:FBB_SDK_DIR\output\3322\fwpkg\diting-community.fwpkg" --chip 3322 -d --timeout 180
fbb monitor --port COM3 --baud 750000
说明:本文示例命令以一站式 CLI 为主。实际开发可从以下三种环境中选择,推荐使用一站式 CLI。
| 开发环境 | 适用场景 | 使用指南 |
|---|---|---|
| 一站式 CLI(推荐) | 快速完成目标选择、构建、烧录和串口监视 | 一站式 CLI 开发环境使用指南 |
| HiSpark Studio for VS Code | 图形化编辑、编译、烧录和调试 | HiSpark Studio for VS Code 开发环境使用指南 |
| WSL 与 Docker | 在 Windows 上使用一致的 Linux 容器构建环境 | WSL 与 Docker 环境使用指南 |
或使用一站式 CLI:
预期固件:
环境、烧录和串口监视参见一站式 CLI 开发环境使用指南。
使用方式
- 烧录并复位设备。
- 打开串口监视器。
- 执行
AT+SECKEY。 - 保存 HKDF、Keyslot、AES-GCM 各阶段的返回码。
命令返回 OK 且日志最后出现 [SEC][KEY] PASS 才表示示例通过。也可以执行 AT+SECDEMOALL 运行 AES-GCM、HASH、PKE、密钥管理和 mbed TLS 五项安全示例;五项汇总及 [SEC][ALL] 均为 PASS 才表示全部通过。
验证说明: Demo 已完成
diting-community目标的完整编译、最终 ELF 链接及固件 BIN 生成验证。
预期结果
[SEC][KEY] start
[SEC][PASS] HKDF-SHA256
[SEC][PASS] HKDF-SHA256 RFC5869 vector
[SEC][PASS] AES-GCM with direct HKDF key
[SEC][PASS] Keyslot setup
[SEC][PASS] Keyslot load AES key
[SEC][PASS] AES-GCM with Keyslot
[SEC][PASS] Keyslot ciphertext equals direct-key ciphertext
[SEC][PASS] Keyslot tag equals direct-key tag
[SEC][PASS] AES-GCM decrypt with Keyslot
[SEC][PASS] Keyslot restored plaintext
[SEC][PASS] Keyslot teardown
[SEC][KEY] PASS
OK
文件结构与代码走读
文件结构
配套 Demo 位于以下路径:
/samples/native_samples/security/
├── CMakeLists.txt # Security Demo 编译配置
├── security_demo.c # AT 命令注册与汇总入口
├── security_demo.h # 公共函数声明
├── security_demo_cipher_hash.c # AES-GCM 与 SHA-256 示例
├── security_demo_pke.c # ECDSA 签名验签示例
├── security_demo_key.c # HKDF 与 Keyslot 示例
├── security_demo_mbedtls.c # mbed TLS SHA-256 标准向量示例
├── security_demo_utils.c # 公共校验、日志与安全清理
├── security_demo_utils.h # 公共辅助函数声明
└── README.md # 安全示例运行说明
各文件职责
| 文件 | 职责 | 关键内容 |
|---|---|---|
security_demo_key.c |
实现 RFC 5869 HKDF 与 Keyslot 自检 | 标准向量、自检流程和错误处理 |
security_demo.c |
注册安全示例 AT 命令 | AT+SECAESGCM、AT+SECHASH、AT+SECPKE、AT+SECKEY、AT+SECMBEDTLS、AT+SECDEMOALL |
security_demo_mbedtls.c |
实现 mbed TLS SHA-256 自检 | abc 标准向量与公共 mbedtls_sha256() API |
security_demo_utils.c |
提供公共结果检查和清理能力 | PASS/FAIL 输出、字节比较、安全清零 |
CMakeLists.txt |
定义 security_sample 组件 |
源文件、头文件、编译宏和组件链接 |
代码走读
本节结合 /samples/native_samples/security/security_demo_key.c 说明实现顺序。
步骤 1:执行 HKDF
准备 uapi_drv_cipher_hkdf_t:
hmac_type选择 HMAC-SHA256。salt/salt_length指向测试 Salt。ikm/ikm_length指向输入密钥材料。info/info_length指向域分离信息。
接口成功后,将 OKM 与公开测试向量比较。
步骤 2:创建 Keyslot
uint32_t keyslot = UAPI_DRV_INVALID_KEY_SLOT;
ret = uapi_drv_keyslot_setup(
&keyslot, UAPI_DRV_KEYSLOT_TYPE_MCIPHER);
只有返回 ERRCODE_SUCC 后,Keyslot 句柄才有效。
步骤 3:加载派生密钥
加载成功后,应尽快安全清理普通内存中的 OKM 副本。清理操作不得被编译器优化掉。
步骤 4:使用 Keyslot
调用 AES-GCM 时:
key传NULL。key_len仍传实际密钥长度。keyslot_handle传已加载密钥的有效句柄。
ret = uapi_drv_cipher_symc_gcm_encrypt(
UAPI_DRV_CIPHER_SYMC_ALG_AES,
NULL, key_len, keyslot,
nonce, nonce_len,
aad, aad_len,
plain, cipher, plain_len,
tag, tag_len);
加解密的完整要求参见对称加解密与哈希开发指南。
步骤 5:统一退出和销毁
使用单一清理出口,确保任何失败阶段都能执行:
- 若 Keyslot 已成功创建,调用
uapi_drv_keyslot_teardown。 - 安全清理 IKM、PRK/OKM、测试密钥和临时缓冲区。
- 将句柄复位为
UAPI_DRV_INVALID_KEY_SLOT。 - 返回最先出现的有效错误码,避免清理错误覆盖根因。
基于密钥管理 Demo 开发应用
配套 Demo 可以通过 AT 命令触发板端回归,但自定义密钥管理应用应从业务任务或服务直接调用密钥管理接口或可复用的运行函数,并为新增算法补充标准向量、异常处理和敏感数据清理逻辑。
代码清单
- 新增或修改示例源文件
- 补充函数声明与编译配置
- 从业务任务或服务调用运行函数并处理结果
- 增加标准测试向量
- 增加负向测试与资源释放路径
- 如需串口回归,再注册独立 AT 命令(可选)
CMakeLists.txt 修改示例
在上层 samples/native_samples/CMakeLists.txt 中按功能宏加入示例目录:
在目标 config.py 中添加 CONFIG_ENABLE_SECURITY_SAMPLE,并将 security_sample 加入目标组件列表。
关键代码片段
以下代码展示业务入口直接复用现有自检函数的基本方式:
扩展建议:
不可逆安全配置应分为软件流程验证、工程样机验证和受控量产等阶段。Demo 不得作为量产烧写脚本使用。

各阶段设置停止条件:
| 阶段 | 必须验证 | 出现以下情况不得继续 |
|---|---|---|
| Demo | HKDF 向量、Keyslot 生命周期、AES-GCM 正负向测试 | 接口失败、结果不稳定、资源未释放 |
| 方案设计 | 根密钥、工作密钥、用途、轮换、吊销和返修 | 密钥用途不清、缺少恢复路径 |
| 工程样机 | 硬件密钥类型、Salt、eFuse 状态、断电恢复 | 结果与方案不一致、根密钥未就绪 |
| 量产评审 | 烧写顺序、权限、日志、密钥备份和审计 | 无双人复核、无失败隔离、仍含测试密钥 |
| 量产 | 每设备状态记录和抽检 | 密钥或配置异常批量扩散 |
不可逆操作要求:
- 任何 eFuse 操作前确认供电稳定、芯片型号、生命周期和当前 eFuse 状态。
- 量产前应在可替换的工程样机上完成全流程验证。
- 将密钥生成、设备烧写、校验和入库拆成可审计步骤。
- 烧写前备份允许备份的生产材料,并验证恢复流程。
- 禁用调试或下载能力前,确认后续升级、返修和故障分析通道。
- Demo、文档命令和普通应用不得自动触发 eFuse 烧写。
测试验证
完成一站式 CLI 环境配置后执行:
# 编译固件,编译生成的固件从 output/3322/fwpkg 中获取 diting-community.fwpkg
fbb set-target pack_diting_community
fbb build
- 烧录固件并启动设备。
- 从业务任务或测试任务调用
security_demo_run_key()或自定义运行函数。 - 保存函数结果、错误码和必要的脱敏日志。
- 确认所有正向检查通过,并且篡改输入被拒绝。
- 需要板端串口回归时,可选用配套 AT 命令触发同一运行函数。
注意事项
- 不得将产品密钥、设备私钥或默认测试密钥硬编码到量产固件中。
- 不得将低熵口令直接用作 AES 密钥;需要从口令派生密钥时,应使用经过评审的 PBKDF2 参数。
- HKDF 的 Info 应包含用途和上下文,实现密钥域分离。
- 不同用途的密钥不得无依据复用,例如同一密钥同时用于 AES-GCM 和 HMAC。
- Keyslot 生命周期必须覆盖所有使用该句柄的运算。
- 加载成功后尽快清理普通内存中的明文密钥副本。
- 安全清零必须使用不会被编译器优化掉的实现。
- 硬件密钥依赖芯片安全配置和 eFuse,不能仅凭接口返回成功判断量产方案正确。
- eFuse 烧写通常不可逆,本 Demo 不包含任何自动烧写逻辑。
- KDF 输出长度、算法和安全强度应与后续密码算法匹配。
eFuse 烧写过程中断
eFuse 烧写过程中发生断电或复位时,可能出现部分字段已烧写、密钥用途与保护状态不一致、设备无法启动或升级等情况。处理时应遵循以下原则:
- 状态未确认前,不得重复执行整套烧写命令。
- 读取芯片允许读取的状态,并与工单和生产记录进行比对。
- 确认芯片型号、生命周期、目标执行环境和已完成步骤。
- 由安全方案负责人决定继续烧写、隔离分析或报废。
- 原因未确认前,不得向同批设备继续执行相同流程。
烧写后调试或下载接口不可用
该现象可能是安全策略的预期结果,也可能由配置顺序错误引起。应确认调试或下载能力是否按方案关闭、后续升级是否应使用受信 OTA 或预加密镜像、量产工具是否仍依赖已关闭接口,以及返修和故障分析通道是否已经建立。不得为恢复开发便利而在量产配置中重新开放非必要的调试接口。
安全功能启用前检查
- 使用稳定电源,并关闭可能引起自动休眠或复位的功能。
- 在工程样机上完成全流程演练和断电异常测试。
- 备份安全方案允许备份的密钥材料、配置和生产记录。
- 通过双人复核确认芯片、目标环境和烧写顺序。
- 明确失败设备的隔离、返修和报废规则。
- 确认普通 Demo 和应用启动流程无法触发不可逆操作。
常见编译错误
错误码解析
Security Unified 组合错误码定义位于 /src/drivers/drivers/hal/security_unified/include/common_include/crypto_errno.h,可按以下方式解析:
env = (error >> 28) & 0xF;
layer = (error >> 24) & 0xF;
module = (error >> 20) & 0xF;
error_code = error & 0xFF;
| 字段 | 值 | 含义 |
|---|---|---|
| ENV | 0x1/0x2/0x3 | Linux/iTrustee/OP-TEE |
| ENV | 0x4/0x5/0x6 | LiteOS/SELiteOS/无 OS |
| ENV | 0x7/0x8 | FreeRTOS/AliOS |
| LAYER | 0x1/0x2 | UAPI/Dispatch |
| LAYER | 0x3/0x4/0x5 | KAPI/Driver/HAL |
| MODULE | 0x2 | HASH、HMAC 和 KDF 模块 |
| MODULE | 0x5 | KM 密钥管理模块 |
| MODULE | 0x6 | OTP/eFuse 模块 |
密钥管理与派生相关的常用错误类型如下:
| 名称 | 低 8 位 | 含义 | 优先检查项 |
|---|---|---|---|
ERROR_INVALID_PARAM |
0x01 | 参数取值无效 | Keyslot 类型、KLAD Engine、密钥和 KDF 长度 |
ERROR_PARAM_IS_NULL |
0x02 | 必填指针为空 | IKM、Salt、Info、OKM 和密钥缓冲区 |
ERROR_NOT_INIT |
0x03 | 模块未初始化 | KM/KDF 能力和系统安全环境 |
ERROR_UNSUPPORT |
0x04 | 配置或能力不支持 | KM、HKDF、PBKDF2 和目标算法配置宏 |
ERROR_CHN_BUSY |
0x07 | 通道繁忙 | Keyslot 并发访问和资源释放 |
ERROR_INVALID_HANDLE |
0x0D | Keyslot 句柄无效 | 创建、加载、使用和销毁顺序 |
ERROR_MALLOC |
0x41 | 内存申请失败 | 堆余量和临时派生缓冲区 |
ERROR_KLAD_ROOTKEY_NOT_READY |
0xA9 | 硬件根密钥未准备好 | eFuse、生命周期和硬件密钥类型 |
ERROR_HASH_CALC_TIMEOUT |
0xB2 | KDF 依赖的 HASH 运算超时 | HASH 通道、时钟和硬件状态 |
ERROR_KEYSLOT_TIMEOUT |
0xBD | Keyslot 操作超时 | KM 状态、并发和硬件响应 |
说明: 硬件根密钥相关错误不能通过反复调用接口消除。错误的 eFuse 操作可能不可逆,必须先核对芯片生命周期、硬件密钥类型和受控生产记录。
常见运行问题
Keyslot 创建失败
- 检查 Keyslot 类型是否有效。
- 检查可用通道是否被其他任务占用。
- 检查 KM 模块是否参与目标固件构建。
- 检查安全硬件和锁状态是否正常。
明文密钥加载失败
- MCIPHER/FLASH 类型的明文密钥长度必须为 16、24 或 32 字节。
- HMAC 明文密钥长度不得超过 128 字节。
- AES Keyslot 应选择 AES KLAD Engine。
- SM4 Keyslot 应选择 SM4 KLAD Engine。
- Keyslot 类型、KLAD Engine 和消费算法必须匹配。
使用 Keyslot 加密失败
- 检查 Keyslot 是否已经销毁。
- 检查 Keyslot 类型与目标算法是否匹配。
- 使用 Keyslot 调用 SYMC 接口时,
key应为NULL。 key_len应与加载到 Keyslot 中的工作密钥长度一致。
HKDF 输出与预期不同
- 检查 HMAC 类型。
- 逐字节核对 IKM、Salt、Info 及对应长度。
- 确认没有将十六进制文本误作二进制字节输入。
- 检查期望向量是否使用相同的 HASH 算法和输出长度。
硬件密钥结果不符合预期
应停止使用该结果,并检查:
- 对应 eFuse 是否已按安全方案完成受控烧写。
- 硬件密钥类型是否与 REE、TEE 或启动环境匹配。
- Salt、KLAD Engine 和工作密钥长度是否正确。
- 设备是否处于预期生命周期和安全状态。
- 已知答案测试结果是否与受控生产记录一致。
常见编译与链接问题
| 错误现象 | 原因 | 解决方法 |
|---|---|---|
找不到 security_kdf.h 或 security_km.h |
安全头文件路径未加入组件 | 检查 PRIVATE_HEADER 是否包含 src/include/driver |
| HKDF 接口链接失败 | HASH/HKDF 能力未参与构建 | 检查安全配置头和目标组件 |
| Keyslot 创建或加载失败 | 类型、KLAD Engine 或密钥长度不匹配 | 核对 MCIPHER、AES Engine 和 16 字节密钥 |
AT+SECKEY 不存在 |
Demo 开关或 AT 注册未生效 | 检查 CONFIG_ENABLE_SECURITY_SAMPLE 和固件版本 |
| 增量编译结果异常 | 旧对象文件或缓存掩盖配置变化 | 清理构建缓存后执行完整构建 |
调试方法
- HKDF 结果错误时,逐项检查 HMAC 类型、IKM、Salt、Info 和长度。
- Keyslot 创建失败时,检查类型是否正确、通道是否被占用、KM 是否参与编译。
- 加载密钥失败时,检查 KLAD Engine、Keyslot 类型和密钥长度是否匹配。
- 使用 Keyslot 加密失败时,确认
key为NULL,句柄和key_len有效。 - 检查是否在密码运算结束前调用了
keyslot_teardown。 - 硬件密钥结果不符合预期时,应停止相关操作,并确认 eFuse、硬件密钥类型、Salt 和目标执行环境。
- 打印完整十六进制返回值,并按本节说明解析运行环境、软件层级、功能模块和具体错误类型。
问题反馈信息
提交 Issue 或请求技术支持时,应提供 SDK 版本、芯片与开发板、构建目标、失败接口、完整十六进制返回值、Keyslot 类型、KLAD Engine、KDF 参数长度、相关配置宏、最小复现步骤、预期结果和实际日志。不得提交产品密钥、设备私钥、eFuse 值、证书私钥或生产环境凭据。