openHiTLS SDF Provider
| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
| 28 天前 | ||
| 1 个月前 | ||
| 28 天前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 10 个月前 | ||
| 28 天前 |
SDFProv (sdf_provider)
新增能力(SM3/SM4/SM4-GCM)
- 哈希:SM3(HASH OP),通过 SDF HashInit/Update/Final 实现。
- 对称加解密:SM4 支持 ECB、CBC、GCM 三种模式:
- 原始密钥:Init 直接传入 16 字节密钥,内部调用
SDF_ImportKey+ Encrypt/DecryptInit。 - KEK 路径(仅限 ECB/CBC):通过
CRYPT_CTRL_SET_KEK_ID设置非 0 KEK 索引并使用SDF_ImportKeyWithKEK导入会话句柄。 - CBC 需 16 字节 IV;ECB 无 IV;GCM 需 12 字节 Nonce。
CRYPT_CTRL_REINIT_STATUS可在持有句柄时重置链路状态(可携带新 IV)。
- 原始密钥:Init 直接传入 16 字节密钥,内部调用
- SM4-GCM(AEAD):
- 底层调用
SDF_AuthEncInit/Update/Final和SDF_AuthDecInit/Update/Final。 - 加密调用顺序:
InitCtx→CRYPT_CTRL_SET_TAGLEN→CRYPT_CTRL_SET_AAD→Update→Final→CRYPT_CTRL_GET_TAG - 解密调用要求:
InitCtx后、首次Update/Final前完成CRYPT_CTRL_SET_AAD(如有 AAD)和CRYPT_CTRL_SET_TAG(缓存期望 Tag 及其长度),两者顺序不限;随后Update→Final(SDF 设备内部验 Tag) - Tag 长度默认是 0,表示未设置,开始 GCM 加解密时会报错;SDFP 本地仅允许 32 bit、64 bit,以及 96 到 128 bit 间 8 的倍数长度 Tag(对应 4/8/12/13/14/15/16 字节)。
- 底层调用
新增 demo
sm3_hash: 计算 "abc" 的 SM3 摘要并校验标准向量。sm4_ecb: SM4-ECB 以固定向量加解密回环并对比标准密文。sm4_cbc: RAW 密钥 CBC 交叉验证(CBC 无填充)。sm4_kek_cmd_cross: external provider 下通过CRYPT_CTRL_SET_KEK_ID设置 KEK index,执行 SM4 ECB/CBC KEK 交叉验证,并校验 KEK index 0 会被拒绝。sm4_internal_kek_cross: internal provider load 参数带入 SM4 KEK index,执行 SM4 ECB/CBC KEK 交叉验证。sm4_gcm: SM4-GCM 加密取 Tag,再带 Tag 解密验证,输出明文与原文对比。 (均依赖环境变量SDF_LIB_PATH;SM2 internal 用例需显式设置SDF_ECC_KEY_INDEX和SDF_ECC_KEY_PASS;SM4 KEK 用例需显式设置非 0SDF_SM4_KEY_INDEX;从当前目录加载libSDFProv.so)
基于 openHiTLS Provider 接口的 SDF 适配实现。
当前仓库输出的 Provider 名称为 SDFProv(对应 provider=SDFProv)。
能力范围
根据 src/ 下当前实现,已注册能力如下:
- SM2: 密钥管理(KeyMgmt)、签名/验签(Sign)、非对称加解密(AsymCipher)、密钥交换(KeyExch)
- RSA: 密钥管理(KeyMgmt)、签名/验签(Sign)、非对称加解密(AsymCipher)
- SM3: 哈希摘要(Hash)
- SM4: ECB、CBC、GCM(AEAD)对称加解密(SymmCipher)
注:非对称算法支持外部明文密钥、当次生成的运行时密钥,以及通过索引访问的 SDF 内部密钥;内部私钥访问必须显式配置口令。
目录结构
include/: Provider 对外公共头文件(sdfp.h,sdfp_errno.h)src/: Provider 源码,包含 common、sm2、sm3、sm4、rsa 模块demo/: 示例程序(sm2_sign、sm2_encrypt、rsa_sign、rsa_encrypt、sm3_hash、sm4_test、sm4_gcm)CMakeLists.txt: 构建脚本
依赖
- CMake
>= 3.10 - openHiTLS 头文件与依赖库(
libhitls_bsl.so、libhitls_crypto.so) - SDF 标准接口头文件:仓库内已在
src/common/维护一份内部标准头文件,无需额外传入 SDF SDK 头目录 - Linux
dlopen运行时(链接dl)
构建参数
CMakeLists.txt 目前支持以下参数:
HITLS_DIR: openHiTLS 安装目录(内部使用include、lib或build下的动态库)SDF_INCLUDE_DIR: 可选,厂商 SDF 头文件目录;设置后优先于仓库内标准头SDF_DIR: 可选,若设置且未设置SDF_INCLUDE_DIR,则使用${SDF_DIR}/includeBUILD_DEMOS: 是否构建 demo,默认ONSDFP_DEBUG: 是否开启 provider 调试日志,默认OFF;开启后SDFP_LOG会向 stderr 输出函数名、行号和错误码
说明:本项目编译期不链接 SDF 动态库,而是在 Provider 初始化时通过显式 SDFP_PARAM_SDF_LIB_PATH 参数使用 dlopen 加载真实设备库。demo 会从 SDF_LIB_PATH 读取路径并作为该参数传入 Provider。因此 SDF_LIB_DIR 和 SDF_NAME 不再是构建必需参数。
构建
mkdir -p build
cd build
cmake .. \
-DHITLS_DIR=/path/to/hitls \
-DSDFP_DEBUG=ON \
-DBUILD_DEMOS=ON
make -j
如果真实设备 SDK 的类型定义或算法 ID 与仓库维护的标准头不同,可显式覆盖:
cmake .. \
-DSDF_INCLUDE_DIR=/path/to/vendor/sdf/include \
-DHITLS_DIR=/path/to/hitls \
-DBUILD_DEMOS=ON
make -j
测试与示例运行
构建完成后可在 build/ 目录执行:
ctest --output-on-failure
或手动运行:
export SDF_LIB_PATH=/path/to/libsdf.so
export SDF_ECC_KEY_INDEX=your-ecc-key-index
export SDF_ECC_KEY_PASS=your-ecc-private-key-password
export SDF_SM4_KEY_INDEX=your-sm4-kek-index
./sdfp_demo
预期成功输出:
===== External Provider Tests =====
===== SM3 Hash =====
PASS: sm3_hash
===== SM4 ECB =====
PASS: sm4_ecb
===== SM4 CBC =====
PASS: sm4_cbc
===== SM4 GCM =====
PASS: sm4_gcm
===== SM2 Encrypt =====
PASS: sm2_encrypt
===== SM2 Sign =====
PASS: sm2_sign
........
===== Result: 14/14 passed =====
运行前提与注意事项
-
demo 会分两次加载 Provider:external 用例只传
SDF_LIB_PATH,不传 ECC/SM4 index/password;external 分组中的 cmd 用例会在 ctx 上显式设置 SM2 index/password 和 SM4 KEK index。internal 用例卸载后重新加载,并按环境变量传SDF_ECC_KEY_INDEX/SDF_ECC_KEY_PASS/SDF_SM4_KEY_INDEX/SDF_SM4_KEY_PASS。internal 分组也会跑普通 SM2 external key 用例,确认显式设置/生成的外部密钥不会被 provider 默认 internal index 覆盖。 完整 demo 需要显式传入SDF_ECC_KEY_INDEX、SDF_ECC_KEY_PASS和非 0SDF_SM4_KEY_INDEX;demo 不提供默认索引或默认私钥访问口令。 -
demo 首次加载时通过
CRYPT_EAL_ProviderSetLoadPath(NULL, "./")从当前目录加载 Provider,因此应在build/目录运行,保证能找到libSDFProv.so。 -
SDF 动态库路径是通过
SDFP_PARAM_SDF_LIB_PATH(ID=102)参数传递给CRYPT_EAL_ProviderLoad的;未传会返回SDFP_ERR_NULL_INPUT。 -
SM2/RSA:
keyIndex == 0表示没有内部密钥索引,走 external 明文密钥路径;keyIndex != 0表示走 SDF internal key 路径。internal 私钥操作必须配置 password,否则返回缺口令错误;单独设置 password 不会让keyIndex == 0的 ctx 切到 internal。 -
SM4 ECB/CBC:
CRYPT_CTRL_SET_KEK_ID是 KEK/internal 模式选择命令,参数必须是非 0 KEK index;传 0 会返回CRYPT_INVALID_ARG。raw key external 路径不要调用该命令。SM4 不使用CRYPT_CTRL_KEY_PASS;KEK 访问口令仅来自 provider load 参数SDFP_PARAM_SM4_KEY_PASS。
Provider 参数(当前实现)
对外加载参数定义在 include/sdfp.h:
SDFP_PARAM_SDF_LIB_PATH(102): SDF 动态库路径(Provider 初始化必需)SDFP_PARAM_ECC_KEY_INDEX(200): ECC 内部密钥索引默认值,0 表示未设置SDFP_PARAM_ECC_KEY_PASS(201): ECC 内部私钥访问口令SDFP_PARAM_SM4_KEY_INDEX(202): SM4 KEK 索引默认值,0 表示未设置SDFP_PARAM_SM4_KEY_PASS(203): SM4 密钥口令(预留给需要口令保护 SM4 密钥的 SDF 实现)
未设置 ECC 口令时,ECC 内部私钥访问操作会失败,不再回退到内置默认口令。设置 SDFP_PARAM_SM4_KEY_PASS 时,会在支持 SDF_GetKEKAccessRight / SDF_ReleaseKEKAccessRight 的 SDF 实现上执行 KEK 访问授权。
Provider-specific 控制参数定义在 include/sdfp.h:
CRYPT_CTRL_KEY_INDEX(101): 内部密钥索引CRYPT_CTRL_KEY_USAGE(103): 密钥用途CRYPT_CTRL_GET_KEY_INDEX(104): 获取密钥索引CRYPT_CTRL_GET_KEY_USAGE(105): 获取密钥用途CRYPT_CTRL_KEY_PASS(106): 设置私钥口令CRYPT_CTRL_SET_KEK_ID(110): 设置 KEK 索引(SM4 KEK 模式)CRYPT_CTRL_GEN_DEK_WITH_KEK(111): 通过 KEK 生成会话密钥,可取回密文KEY_USAGE_SIGN/KEY_USAGE_ENC/KEY_USAGE_EXCH: 内部密钥用途CRYPT_CTRL_REINIT_STATUS: openHiTLS 重置对称密码上下文状态命令(可带新 IV)
License
见 LICENSE。