2. 生成并存储根密钥
任务说明
本案例目标是在TC3xx HSM中生成RSA-2048根密钥对,并将公钥导出存储到安全存储区(如HSM NVM或外部安全Flash),私钥永久保存在HSM内部不可导出。该根密钥将用于后续固件签名验证或安全启动链的信任根。
环境依赖
- TC3xx MCU(如AURIX TC397)HSM模块
- HSM固件支持Crypto Driver(符合AUTOSAR规范)
- 使用英飞凌MCAL中的
Csm(Crypto Service Manager)或直接操作HSM寄存器
关键完整代码
/* 假设使用AUTOSAR Csm接口,密钥ID定义 */
#define HSM_ROOT_KEY_ID 0x0001
#define HSM_KEY_STORAGE_NVM 0x0002 /* 安全存储区标识 */
/* 生成RSA-2048密钥对并存储公钥 */
Std_ReturnType HSM_GenerateAndStoreRootKey(void)
{
Crypto_ResultType result;
Crypto_KeyType keyType;
Crypto_KeyElement keyElement;
uint8 publicKeyBuffer[270]; /* RSA-2048公钥:模数256 + 指数8 + 头部 */
uint32 publicKeyLen = sizeof(publicKeyBuffer);
/* 1. 配置密钥类型为RSA-2048 */
keyType.cryptoAlgo = CRYPTO_ALGO_RSA;
keyType.keyLength = 2048;
keyType.keyFlags = CRYPTO_KEYFLAG_EXPORTABLE_PUBLIC; /* 仅公钥可导出 */
/* 2. 在HSM内部生成密钥对 */
result = Crypto_KeyGenerate(HSM_ROOT_KEY_ID, &keyType);
if (result != CRYPTO_E_OK) {
return E_NOT_OK;
}
/* 3. 导出公钥(私钥不可导出,由HSM硬件保证) */
keyElement.elementType = CRYPTO_KEY_ELEMENT_PUBLIC;
result = Crypto_KeyElementGet(HSM_ROOT_KEY_ID, &keyElement,
publicKeyBuffer, &publicKeyLen);
if (result != CRYPTO_E_OK) {
return E_NOT_OK;
}
/* 4. 将公钥写入安全存储区(NVM) */
result = Crypto_KeyElementSet(HSM_KEY_STORAGE_NVM,
CRYPTO_KEY_ELEMENT_PUBLIC,
publicKeyBuffer, publicKeyLen);
if (result != CRYPTO_E_OK) {
return E_NOT_OK;
}
return E_OK;
}
运行与验证
- 集成方式:将上述函数在HSM初始化完成后调用一次,通常在系统启动早期执行。
- 编译配置:确保MCAL Crypto驱动已启用,并在配置工具中定义密钥ID
HSM_ROOT_KEY_ID与存储区域HSM_KEY_STORAGE_NVM。 - 验证步骤:
- 调用
HSM_GenerateAndStoreRootKey()后检查返回值是否为E_OK。 - 读取NVM中存储的公钥数据,确认长度约为270字节且首字节为0x30(DER编码起始),说明公钥格式正确。
- 尝试调用
Crypto_KeyElementGet导出私钥(CRYPTO_KEY_ELEMENT_PRIVATE),应返回错误码,证明私钥不可导出。
- 调用
通过判定标准
- 函数返回
E_OK,且NVM中能读到有效的RSA公钥数据。 - 私钥导出操作被HSM拒绝,返回错误码。
- 使用导出的公钥对已知数据进行RSA加密,再用HSM内部私钥解密,能还原原始数据(需额外测试代码,但可验证密钥对正确性)。
常见问题
- 密钥生成失败:检查HSM是否已完成初始化,以及密钥ID是否与配置一致。
- 公钥导出长度不符:确认缓冲区至少270字节,且HSM驱动版本支持的DER编码格式。
- NVM写入失败:确认存储区域已擦除且地址对齐,部分HSM要求4字节对齐写入。