CRYPTO
本文档是《Rockchip Crypto/HWRNG 开发指南》,旨在介绍Rockchip公司生产的RK系列芯片中Crypto(加密)和HWRNG(硬件随机数生成器)的开发流程。文档详细阐述了驱动开发、上层应用开发、硬件启用方法、性能数据等关键信息。文档适用于技术支持工程师和软件开发工程师,以确保他们能够有效地利用Rockchip提供的硬件加密和随机数生成功能。
1. 概述
Rockchip Crypto (加密引擎,Cryptography) 是 Rockchip 系列芯片集成的硬件加密引擎,支持 AES、RSA、SHA、ECC 等算法,提供硬件加速功能,降低 CPU 负载。
Rockchip HWRNG(硬件真随机数生成器,TRNG)基于物理噪声源生成不可预测的随机数,满足安全应用需求。
1.1 Crypto 版本演进
以下是 Crypto 版本演进的表格:
Crypto 版本 |
算法 |
描述 |
---|---|---|
crypto v1 |
DES/TDES |
支持 ECB/CBC 两种模式,其中 TDES 支持 EEE 和 EDE 两种密钥模式 |
AES |
支持 ECB/CBC/CTR/XTS 模式,支持 128/192/256 bit 三种密钥长度 |
|
HASH |
支持 SHA1/SHA256/MD5 |
|
RSA |
支持 512/1024/2048 三种密钥长度(RK3126、RK3128、RK3288 和 RK3368 不支持) |
|
TRNG |
支持 256bit 硬件随机数 |
|
crypto v2 |
DES/TDES |
支持 ECB/CBC/OFB/CFB 四种模式,其中 TDES 只支持 EDE 密钥模式 |
AES |
支持 ECB/CBC/OFB/CFB/CTR/CTS/XTS/CCM/GCM/CBC-MAC/CMAC |
|
SM4 |
支持 ECB/CBC/OFB/CFB/CTR/CTS/XTS/CCM/GCM/CBC-MAC/CMAC(可选) |
|
HASH |
支持 MD5/SHA1/SHA224/SHA256/SHA384/SHA512/SM3/SHA512-224/SHA512-256(SM3 可选) |
|
HMAC |
支持 MD5/SHA1/SHA256/SHA512/SM3 带硬件填充 |
|
RSA/ECC |
支持最大 4096bit 的常用大数运算操作,通过软件封装可实现 RSA/ECC 算法 |
|
TRNG |
支持 256bit 硬件随机数 |
|
crypto v3 |
特性说明 |
在 crypto v2 算法基础上,增加多线程支持;从 RV1106 开始的平台自动识别支持的算法, |
crypto v4 |
特性说明 |
在 crypto v3 算法基础上,优化 IP 芯片面积,使用同一个 CRYPTO CORE 硬件,例化出 NSCRYPTO/SCRYPTO/KEYLAD 三个硬件 IP;驱动使用兼容 crypto v3 代码, |
1.2 各平台版本支持情况
以下是 Rockchip 芯片平台与 Crypto IP 版本的对应关系表格:
Crypto 版本 | 芯片平台 | 说明 |
---|---|---|
v1 | RK3399、RK3288、RK3368、RK3328/RK3228H、RK322x、RK3128、RK1108、RK3126 | 基础加密引擎,支持 AES/RSA |
v2 | RK3326/PX30、RK3308、RK1808、RV1126/RV1109、RK2206、RK356x、RK3588 | 新增 SHA、国密算法支持 |
v3 | RV1106 | 支持 ECC 和 DMA 传输 |
v4 | RK3528、RK3562 | 优化性能,支持 SM2/SM3/SM4 国密算法 |
注:
RK356x 包含 RK3566、RK3568 等型号。
RV1106 为 v3 版本中唯一支持的芯片。
v4 版本芯片需搭配最新 SDK 实现完整国密功能。
2. 驱动开发
2.1 驱动代码说明
2.1.1 HWRNG 驱动
驱动代码路径:drivers/char/hw_random/rockchip-rng.c
因为HWRNG驱动比较简单,因此crypto v1/v2, trngv1, rkrng四种平台都集中到同一个.c 文件中。驱动中不区分具体的芯片型号,只按照 "rockchip,cryptov1-rng" 和 "rockchip,cryptov2-rng" , "rockchip,trngv1" , "rockchip,rkrng" 四种 compatible 进行划分。目前 "rockchip,trngv1" , "rockchip,rkrng" 为独立的 HWRNG 模块,其他两种 HWRNG 均内置在CYRPTO 模块中。
2.1.2 Crypto 驱动
路径:drivers/crypto/rockchip/
驱动相关文件如下:
drivers/crypto/rockchip
|-- procfs.c // 实现 proc 文件系统统计信息(如时钟速率、算法列表等功能)
|-- procfs.h // proc 文件系统相关头文件,定义相关数据结构与函数声明
|-- rk_crypto_bignum.c // 加密模块中 PKA(公钥算法)大整数运算相关 API 实现
|-- rk_crypto_bignum.h // 加密模块中 PKA 大整数运算相关头文件,声明数据结构与函数
|-- rk_crypto_core.c // Linux 加密驱动框架及公共接口的具体实现代码
|-- rk_crypto_core.h // Linux 加密驱动通用头文件,包含公共定义与宏
|-- rk_crypto_ahash_utils.c // 哈希算法(ahash,通用哈希)相关通用 API 实现
|-- rk_crypto_ahash_utils.h // 哈希算法(ahash)通用头文件,定义相关工具函数与结构
|-- rk_crypto_skcipher_utils.c // 对称密钥加密算法(skcipher)通用 API 实现
|-- rk_crypto_skcipher_utils.h // 对称密钥加密算法(skcipher)通用头文件
|-- rk_crypto_utils.c // 加密模块通用工具函数 API 实现,供多模块复用
|-- rk_crypto_utils.h // 加密模块通用工具头文件,声明公共函数与数据结构
|-- rk_crypto_v1.c // crypto v1 版本硬件相关接口的具体实现代码
|-- rk_crypto_v1.h // crypto v1 版本的结构定义与接口声明头文件
|-- rk_crypto_v1_skcipher.c // crypto v1 版本分组密码算法(如 AES 等)的实现
|-- rk_crypto_v1_ahash.c // crypto v1 版本哈希算法(如 SHA、MD5 等)的实现
|-- rk_crypto_v1_reg.h // crypto v1 版本硬件寄存器定义,描述寄存器地址与功能
|-- rk_crypto_v2.c // crypto v2 版本硬件相关接口的具体实现代码
|-- rk_crypto_v2.h // crypto v2 版本的结构定义与接口声明头文件
|-- rk_crypto_v2_skcipher.c // crypto v2 版本分组密码算法的实现
|-- rk_crypto_v2_ahash.c // crypto v2 版本哈希算法的实现
|-- rk_crypto_v2_akcipher.c // crypto v2 版本 RSA 等非对称加密算法的实现
|-- rk_crypto_v2_pka.c // crypto v2 版本 PKA 操作(如大整数运算)的实现
|-- rk_crypto_v2_reg.h // crypto v2 版本硬件寄存器定义
|-- rk_crypto_v3.c // crypto v3/v4 版本硬件相关接口的具体实现代码
|-- rk_crypto_v3.h // crypto v3/v4 版本的结构定义与接口声明头文件
|-- rk_crypto_v3_skcipher.c // crypto v3/v4 版本分组密码算法的实现
|-- rk_crypto_v3_ahash.c // crypto v3/v4 版本哈希算法的实现
|-- rk_crypto_v3_reg.h // crypto v3/v4 版本硬件寄存器定义
`-- cryptodev_linux // 向用户空间导出加密接口,供用户态程序调用内核加密功能
当前驱动实现的算法情况如下表:
Crypto 版本 |
算法 |
模式/描述 |
---|---|---|
crypto v1 |
AES |
ECB/CBC |
DES/TDES |
ECB/CBC |
|
HASH |
SHA1/SHA256/MD5 |
|
crypto v2/v3/v4(驱动实现) |
AES |
ECB/CBC/OFB/CFB/CTR/GCM |
DES/TDES |
ECB/CBC/CFB/OFB |
|
SM4 |
ECB/CBC/OFB/CFB/OFB/CTR/GCM |
|
HASH |
SHA1/SHA256/SHA384/SHA512/MD5/SM3 |
|
HMAC |
HMAC_SHA1/HMAC_SHA256/HMAC_SHA512/HMAC_MD5/HMAC_SM3 |
|
RSA |
最大 4096bit |
|
crypto v2/v3/v4硬件完整版 |
AES(128/192/256) |
ECB/CBC/OFB/CFB/CTR/XTS/CTS/CCM/GCM/CBC-MAC/CMAC(注:删除线部分驱动未实现) |
SM4 |
ECB/CBC/OFB/CFB/CTR/XTS/CTS/CCM/GCM/CBC-MAC/CMAC(注:删除线部分驱动未实现) |
|
DES/TDES |
ECB/CBC/OFB/CFB |
|
HASH |
MD5/SHA-1/SHA256/SHA512/SM3/SHA224/SHA384/SHA512-224/SHA512-384(注:删除线部分驱动未实现) |
|
HMAC |
SHA-1/SHA-256/SHA-512/MD5/SM3 |
|
RSA |
4096bit PKA 大数运算支持 |
crypto v2/v3/v4 硬件差异表
芯片平台 | AES | DES/TDES | SM3/SM4 | HASH | HMAC | RSA | 多线程 |
---|---|---|---|---|---|---|---|
RK3326/PX30/RK3308 | √ | √ | × | √ | √ | √ | × |
RK1808 | AES-128(内核驱动视为不支持) | × | × | SHA-1/SHA-224/SHA-256/MD5 | √ | √ | × |
RV1126/RV1109 | AES-128/AES-256 | √ | √ | √ | √ | √ | × |
RK2206 | √ | √ | × | √ | √ | √ | × |
RK3568/RK3588 | √ | √ | √ | √ | √ | √ | × |
RV1106 | √ | √ | × | SHA-1/SHA-224/SHA-256/MD5 | √ | √ | √ |
RK3562 | √ | √ | × | SHA-1/SHA-224/SHA-256/MD5 | √ | √ | √ |
RK3528 | √ | √ | √ | √ | √ | √ | √ |
备注:
RK1808:AES 仅支持 128bit,对于 kernel 驱动来说可认为不支持 AES。
RV1126/RV1109:因不支持 AES-192,AES-192 部分只能通过软算法实现,但软算法不支持硬算法的所有模式,建议不要改动代码里已配置好的算法列表。
2.2 启用硬件 HWRNG
2.2.1 内核配置
hwrng驱动会默认编译进内核,由dts文件决定是否使能。
方法一:Menuconfig中配置
在 Linux/arm64 4.4.194 内核配置中,与 Rockchip 随机数生成器相关的配置如下:
- **配置路径**:
**Device Drivers → Character devices → Hardware Random Number Generator Core support**
- **核心配置项**:
- **Rockchip Random Number Generator support**:
若该项标记为 `[*]`,表示启用 Rockchip 随机数生成器支持。此时,内核将驱动 Rockchip 硬件随机数生成器(HWRNG),为系统提供硬件级随机数生成功能,适用于加密密钥生成等安全场景。
方法二:内核config文件中配置 config中配置(一般情况下rockchip_defconfig 中已默认配置好): 只需要添加如下语句即可
CONFIG_HW_RANDOM=y
CONFIG_HW_RANDOM_ROCKCHIP=y
2.2.2 板级 DTS 文件配置
当前大部分芯片 dtsi 都已配置好 hwrng 节点,只需在板级 dts 中将 rng 模块使能即可,如下所示:
&rng {
status = "okay";
}
2.2.3 新增芯片 DTSI 文件配置
如果是新增芯片或者因为其他原因导致dtsi中未配置hwrng节点,那么可以参考以下方式进行配置。
在 arch/arm64/boot/dts/rockchip/rkxxx.dtsi
中添加 HWRNG 节点。
crypto v1:
rng: rng@ff060000 {
compatible = "rockchip,cryptov1-rng";
reg = <0x0 0xff060000 0x0 0x4000>;
clocks = <&cru SCLK_CRYPTO>, <&cru HCLK_CRYPTO_SLV>;
clock-names = "clk_crypto", "hclk_crypto";
assigned-clocks = <&cru SCLK_CRYPTO>, <&cru HCLK_CRYPTO_SLV>;
assigned-clock-rates = <150000000>, <100000000>;
status = "disabled";
};
crypto v2: 实际 TRNG 不需要依赖全部的 clock,只需依赖 hclk_crypto 一个即可。
rng: rng@ff500400 {
compatible = "rockchip,cryptov2-rng";
reg = <0xff500400 0x80>; # 需要加上0x400,如果rng在crypto内部
clocks = <&cru HCLK_CRYPTO>;
clock-names = "hclk_crypto";
power-domains = <&power RV1126_PD_CRYPTO>;
resets = <&cru SRST_CRYPTO_CORE>;
reset-names = "reset";
status = "disabled";
};
trng v1: 目前RK3588和RV1106使用的是trng v1的随机数模块,该模块与crypto v2中拆分出的trng模块设计完全不同,提升了随机性。
rng: rng@fe378000 {
compatible = "rockchip,trngv1";
reg = <0x0 0xfe378000 0x0 0x200>;
interrupts = <GIC_SPI 400 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&scmi_clk SCMI_HCLK_SECURE_NS>;
clock-names = "hclk_trng";
resets = <&scmi_reset SRST_H_TRNG_NS>;
reset-names = "reset";
status = "disabled";
};
2.2.4 确认 HWRNG 已启用
确认硬件驱动调用
执行命令:
cat /sys/devices/virtual/misc/hw_random/rng_current
若输出为 rockchip
,则表明当前调用的是 Rockchip 硬件随机数驱动。
Linux 系统随机数获取
在 Linux 系统中,执行以下命令获取随机数(每次执行随机数内容不同):
cat /dev/hwrng | od -x | head -n 1
Android 系统随机数获取
在 Android 系统中,通过以下命令获取随机数(每次执行随机数内容不同):
cat /dev/hw_random | od -x | head -n 1
2.3 启用硬件 Crypto
当前驱动代码 crypto v1 支持 rk3328,crypto v2 支持 px30/rv1126/rk3568/rk3588,crypto v3支持rv1106。 对于以上平台,只需开启 config 和 dts node 即可启用硬件 crypto。从rv1106开始,支持的feature均会在寄存器信息中体现,crypto v3可以自动适配后续新增芯片的新增功能。
2.3.1 内核配置
方法一:Menuconfig中配置 在 menuconfig 配置中使能 Rockchip 加解密驱动支持,在 dts 中会自动根据芯片平台 compatible id 进行自动适配 v1/v2/v3。(要先确保CONFIG_CRYPTO_HW开启,才能看到硬件crypto的相关配置项)
在 Linux 内核配置界面(以 Linux/arm64 5.10.66 为例),进入 **Cryptographic API -> Hardware crypto devices** 菜单后,与 Rockchip 加密引擎相关的配置项如下:
- **Rockchip's Cryptographic Engine driver**
该项标记为 `[*]` 时,表示启用 Rockchip 加密引擎驱动,使内核支持 Rockchip 芯片的硬件加密功能(如 AES、RSA 等算法的硬件加速)。
- **Export rockchip crypto device for user space**
该项标记为 `[*]` 时,意味着将 Rockchip 加密设备接口导出到用户空间,允许用户态程序调用硬件加密功能,便于上层应用开发调用硬件加密资源。
方法二:内核config文件中配置 在 config 文件中添加如下语句,其中的 CONFIG_CRYPTO_DEV_ROCKCHIP_V3 只是示例,要根据实际的芯片配置,建议使用menuconfig的形式进行修改,会自动选择平台:
CONFIG_CRYPTO_HW=y
CONFIG_CRYPTO_DEV_ROCKCHIP=y
CONFIG_CRYPTO_DEV_ROCKCHIP_V3=y
CONFIG_CRYPTO_DEV_ROCKCHIP_DEV=y
2.3.2 板级 DTS 文件配置
确认 crypto 的 dts 节点配置正常后,直接在板级 dts 文件中开启 crypto 模块即可,如下所示:
&crypto {
status = "okay";
};
2.3.3 新增芯片平台支持
如果芯片 dtsi 中没有配置 crypto 的 dts 节点,则需要按照以下步骤添加支持。
1. 确定crypto I版本
确定芯片 crypto IP 的版本 v1/ v2/v3,从RV1106开始的V3版本,compatible基本已确定为"rockchip,crypto-v3",算法的裁剪和feature均由软件自行适配,只需配置好dts即可。
2. 修改驱动代码drivers/crypto/rockchip/rk_crypto_core.c
主要在驱动代码中添加algs_name, soc_data,compatible等信息
/* 增加芯片支持的算法信息,px30属于crypto v2,支持的算法参见crypto_v2_algs */
/* 特别注意:crypto_v2_algs为crypto v2支持的所有算法。*/
/* 某些芯片在crypto v2上做了裁剪,如rk1808不支持SHA512算法,因此需要对比TRM确认支持的算法 */
static char *px30_algs_name[] = {
"ecb(aes)", "cbc(aes)", "xts(aes)",
"ecb(des)", "cbc(des)",
"ecb(des3_ede)", "cbc(des3_ede)",
"sha1", "sha256", "sha512", "md5",
};
/* 绑定px30_algs_name到px30_soc_data */
static const struct rk_crypto_soc_data px30_soc_data =
RK_CRYPTO_V2_SOC_DATA_INIT(px30_algs_name, false);
/* 绑定px30_soc_data到id_table */
static const struct of_device_id crypto_of_id_table[] = {
/* crypto v2 in belows */
{
.compatible = "rockchip,px30-crypto",
.data = (void *)&px30_soc_data,
},
{
.compatible = "rockchip,rv1126-crypto",
.data = (void *)&rv1126_soc_data,
},
/* crypto v1 in belows */
{
.compatible = "rockchip,rk3288-crypto",
.data = (void *)&rk3288_soc_data,
},
{ /* sentinel */ }
};
3. 新增芯片 DTSI 文件配置
在 arch/arm64/boot/dts/rockchip/rkxxx.dtsi
中添加 crypto 节点。
注解
根据芯片 TRM 进行修改确定 CRYPTO 基地址
clocks 的宏不同平台可能略有不同,如果 dts 出现报错,可以去 include/dtbindings/clock 目录下, grep -rn CRYPTO 查找对应的 clock 宏名称,如下所示: troy@inno:~/kernel/include/dt-bindings/clock$ grep -rn CRYPTO rk3328-cru.h:57:#define SCLK_CRYPTO 59 rk3328-cru.h:206:#define HCLK_CRYPTO_MST 336 rk3328-cru.h:207:#define HCLK_CRYPTO_SLV 337 rk3328-cru.h:284:#define SRST_CRYPTO 68
一、Crypto v1 DTS 配置
crypto: crypto-controller@ff8a0000 {
/* 根据实际配置 crypto 基地址 */
compatible = "rockchip,rk3288-crypto"; /* 修改为对应芯片平台,如 "rk3399-crypto" */
reg = <0x0 0xff8a0000 0x0 0x4000>; /* 根据实际配置 crypto 基地址 */
interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>; /* 根据实际配置 crypto 中断号 */
clocks = <&cru ACLK_CRYPTO>, <&cru HCLK_CRYPTO>,
<&cru SCLK_CRYPTO>, <&cru ACLK_DMAC1>;
clock-names = "aclk", "hclk", "sclk", "apb_pclk";
resets = <&cru SRST_CRYPTO>;
reset-names = "crypto-rst";
status = "disabled";
};
配置说明:
compatible
:匹配芯片平台的 crypto 驱动,需根据实际芯片修改。reg
:设置 crypto 硬件寄存器的基地址和地址范围。interrupts
:配置 crypto 模块使用的中断号及类型。clocks
与clock-names
:指定 crypto 所需时钟源及名称。resets
与reset-names
:定义 crypto 模块的复位源及名称。status
:当前设为disabled
,启用时需改为okay
。
二、Crypto v2 DTS 配置
对于大部分 Crypto v2 芯片,HWRNG 寄存器地址位于 crypto 地址空间内,配置 reg
时需拆分地址空间(CIPHER、RSA 等部分)。
crypto: crypto@ff500000 {
/* 根据实际配置 crypto 基地址 */
compatible = "rockchip,rv1126-crypto"; /* 修改为对应芯片平台 */
reg = <0xff500000 0x400>, <0xff500480 0x3B80>; /* 根据实际配置 crypto 基地址 */
interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cru CLK_CRYPTO_CORE>, <&cru CLK_CRYPTO_PKA>,
<&cru ACLK_CRYPTO>, <&cru HCLK_CRYPTO>;
clock-names = "aclk", "hclk", "sclk", "apb_pclk";
power-domains = <&power RV1126_PD_CRYPTO>;
resets = <&cru SRST_CRYPTO_CORE>;
reset-names = "crypto-rst";
status = "disabled";
};
配置说明:
compatible
:匹配 Crypto v2 芯片平台的驱动。reg
:拆分地址空间,第一部分为 CIPHER/HASH 使用寄存器,第二部分为 RSA(PKA)等使用寄存器。interrupts
:配置中断号及类型。clocks
与clock-names
:指定所需时钟源及名称。power-domains
:关联芯片电源域(按需配置)。resets
与reset-names
:定义复位源及名称。status
:当前设为disabled
,启用时需改为okay
。
4. 板级crypto开启
&crypto {
status = "okay";
};
2.3.4 确认 Crypto 已启用
通过命令 cat /proc/crypto | grep rk 可以查看系统注册的 RK 硬件 crypto 算法。(以 RV1126 为例)
driver : pkcs1pad(rsa-rk,sha256)
driver : rsa-rk
driver : hmac-sm3-rk
driver : hmac-md5-rk
driver : hmac-sha512-rk
driver : hmac-sha256-rk
driver : hmac-sha1-rk
driver : sm3-rk
driver : md5-rk
driver : sha512-rk
driver : sha256-rk
driver : sha1-rk
driver : ofb-des3_ede-rk
driver : cfb-des3_ede-rk
driver : cbc-des3_ede-rk
driver : ecb-des3_ede-rk
driver : ofb-des-rk
driver : cfb-des-rk
driver : cbc-des-rk
driver : ecb-des-rk
driver : xts-aes-rk
driver : ctr-aes-rk
driver : cfb-aes-rk
driver : cbc-aes-rk
driver : ecb-aes-rk
driver : xts-sm4-rk
driver : ctr-sm4-rk
driver : ofb-sm4-rk
driver : cfb-sm4-rk
driver : cbc-sm4-rk
driver : ecb-sm4-rk
通过命令cat /proc/rkcrypto(需要确保升级最新代码,旧的代码不支持该功能),可以查看rockchip crypto驱动的相关信息。包括crypto 版本,clock时钟频率,当前可用的算法,以及当前驱动运行的一些统计信息,后续会不断进行完善补充。(CRYPTO Version中"CRYPTO V3.0.0.0 multi"表示当前平台支持crypto支持多线程)。
Rockchip Crypto Version: CRYPTO V2.0.0.0
use_soft_aes192 : false
clock info:
aclk 350000000
hclk 150000000
sclk 350000000
pka 350000000
Valid algorithms:
CIPHER:
ecb(sm4)
cbc(sm4)
cfb(sm4)
ofb(sm4)
ctr(sm4)
ecb(aes)
cbc(aes)
cfb(aes)
ofb(aes)
ctr(aes)
ecb(des)
cbc(des)
cfb(des)
ofb(des)
ecb(des3_ede)
cbc(des3_ede)
cfb(des3_ede)
ofb(des3_ede)
AEAD:
gcm(sm4)
gcm(aes)
HASH:
sha1
sha224
sha256
sha384
sha512
md5
sm3
HMAC:
hmac(sha1)
hmac(sha256)
hmac(sha512)
hmac(md5)
hmac(sm3)
ASYM:
rsa
Statistic info:
busy_cnt : 1
equeue_cnt : 28764
dequeue_cnt : 28765
done_cnt : 310710
complete_cnt : 28765
fake_cnt : 0
irq_cnt : 310710
timeout_cnt : 0
error_cnt : 0
last_error : 0
Crypto queue usage [0/50], ever_max = 1, status: idle
3. 应用层开发
3.1 用户空间调用 HWRNG
user space 有两种方式可以获取到硬件 hwrng 输出的随机数:
读取 kernel 驱动节点
调用 librkcrypto 库中的接口
注解
hwrng 硬件驱动注册成功后可以为 kernel random 驱动增加熵,hwrng 产生的随机数会输入到 random 驱动的熵池中。kernel 的 random 驱动是 CSPRNG(Cryptography Secure Pseudo Random Number Generator),是符合密码学安全标准的。因此如果对随机数质量要求较高的话,可以读取 /dev/random 或者 /dev/urandom 节点获取随机数。
3.1.1 读取内核驱动节点
若 kernel 已开启 rng,在 user space 可通过读取节点获取随机数。Linux 平台读取节点为 /dev/hwrng
,Android 平台为 /dev/hw_random
。参考代码如下:
#ifdef ANDROID
#define HWRNG_NODE "/dev/hw_random"
#else
#define HWRNG_NODE "/dev/hwrng"
#endif
RK_RES rk_get_random(uint8_t *data, uint32_t len) {
RK_RES res = RK_CRYPTO_SUCCESS;
int hwrng_fd = -1;
int read_len = 0;
hwrng_fd = open(HWRNG_NODE, O_RDONLY, 0);
if (hwrng_fd < 0) {
E_TRACE("open %s error!", HWRNG_NODE);
return RK_CRYPTO_ERR_GENERIC;
}
read_len = read(hwrng_fd, data, len);
if (read_len != len) {
E_TRACE("read %s error!", HWRNG_NODE);
res = RK_CRYPTO_ERR_GENERIC;
}
close(hwrng_fd);
return res;
}
3.1.2 调用 librkcrypto API
参考下文 API 说明:rk_get_random。
3.2 用户空间调用 Crypto
user space 使用 librkcrypto api 接口进行调用。本节是对 librkcrypto 的使用说明。
注解
注意:使用前请确认 kernel 中硬件 crypto 是否已启用,启用方法与确认方法参考启用硬件 crypto和确认硬件 crypto 已启用的方法。
3.2.1 适用范围
API | RK3588 | RK356x | RV1109/1126 |
---|---|---|---|
rk_crypto_mem_alloc/free | √ | √ | √ |
rk_crypto_init/deinit | √ | √ | √ |
rk_get_random | √ | √ | √ |
rk_hash_init/update/update_virt/final | √ | √ | √ |
rk_cipher_init/crypt/crypt_virt/final | √ | √ | √ |
rk_ae_init/set_aad/set_aad_virt/crypt/crypt_virt/final | √ | √ | √ |
rk_rsa_pub_encrypt/priv_decrypt/priv_encrypt/pub_decrypt | √ | √ | √ |
rk_rsa_sign/verify | √ | √ | √ |
rk_write_oem_otp_key | √ | √ | √ |
rk_oem_otp_key_is_written | √ | √ | √ |
rk_set_oem_hr_otp_read_lock | √ | √ | √ |
rk_oem_otp_key_cipher | √ | √ | √ |
rk_oem_otp_key_cipher_virt | √ | √ | √ |
3.2.2 版本依赖
V1.2.0版本librkcrypto库功能依赖kernel以下提交点,若kernel crypto驱动没更新到以下提交点,可能会导致部分功能不可用。 kernel 4.19
commit c255a0aa097afbf7f28e3c0770c5ab778e5616b2
Author: Lin Jinhan <troy.lin@rock-chips.com>
Date: Tue Sep 13 17:20:46 2022 +0800
crypto: rockchip: rk3326/px30 add aes gcm support
Signed-off-by: Lin Jinhan <troy.lin@rock-chips.com>
Change-Id: I75949554d4f573c63092841eef76765a69cc6b24
kernel 5.10
commit 47e85085826daf6401265b803ac9ac7116ae6bb4
Author: Lin Jinhan <troy.lin@rock-chips.com>
Date: Tue Sep 13 17:20:46 2022 +0800
crypto: rockchip: rk3326/px30 add aes gcm support
Signed-off-by: Lin Jinhan <troy.lin@rock-chips.com>
Change-Id: I75949554d4f573c63092841eef76765a69cc6b24
3.2.3 注意事项
对称算法的输入数据长度,要求与所选算法和模式的数据长度要求一致。 比如 ECB/CBC 等要求 block 对齐,CTS/CTR 等则无数据长度对齐要求。API 中不做填充处理。
如果计算数据量较大,为了提高效率,建议选用通过 dma_fd 传递数据的算法接口。 由于 crypto 只支持 4G 以内连续物理地址,因此 dma fd 分配的 buffer 必须是 4G 以内物理连续地址(CMA)。可以使用 librkcrypto 提供的 rk_crypto_mem 相关接口分配,也可以自行用 DRM 等内存分配接口分配得到 dma fd。
CMA 配置: 由于 crypto 只支持 4G 以内的 CMA 地址访问,如果设备使用内存超过 4G,需要修改 dts 中 CMA 的配置,否则 rk_crypto_mem 虽然能分配成功,但是分配出的内存无法使用。以下以 rk3588-android.dtsi 平台为例。其中 0x10000000 为 CMA 的起始地址(256MB 处,尽量不要修改),0x00800000 为 CMA 的大小,可以根据实际需要进行修改。CMA 相关说明见文档<Rockchip_Developer_Guide_Linux_CMA_CN>。
--- a/arch/arm64/boot/dts/rockchip/rk3588-android.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3588-android.dtsi
@@ -70,7 +70,8 @@
cma {
compatible = "shared-dma-pool";
reusable;
- size = <0x0 (8 * 0x100000)>;
+ //size = <0x0 (8 * 0x100000)>;
+ reg = <0x0 0x10000000 0x0 0x00800000>;
linux,cma-default;
};
使用以下接口前,需确保 TEE 功能可用,TEE 相关说明见<Rockchip_Developer_Guide_TEE_SDK_CN>文档。
rk_set_oem_hr_otp_read_lock :当设置的 key_id 为 RK_OEM_OTP_KEY0/1/2 时,设置成功后,会影响其他 OTP 区域的属性。 例如部分 OTP 区域变为不可写,详见<Rockchip_Developer_Guide_OTP_CN>文档。因此,建议优先使用 RK_OEM_OTP_KEY3 。
rk_oem_otp_key_cipher_virt :支持的 len 最大值受 TEE 的共享内存影响,如果使用本接口前已占用 TEE 共享内存,那么 len 的最大值可能比预期的小。
3.2.4 关键数据结构
3.2.4.1 rk_crypto_mem
typedef struct {
void *vaddr;
int dma_fd;
size_t size;
} rk_crypto_mem;
vaddr:内存的虚拟地址。
dma_fd:内存对应的 DMA 文件描述符句柄。
size:内存区域的大小。
3.2.4.2 rk_cipher_config
typedef struct {
uint32_t algo;
uint32_t mode;
uint32_t operation;
uint8_t key[64];
uint32_t key_len;
uint8_t iv[16];
void *reserved;
} rk_cipher_config;
algo:算法类型,取值参考
RK_CRYPTO_ALGO
,具体范围以 API 描述为准。mode:算法模式,参考
RK_CIPHER_MODE
,支持 ECB/CBC/CTR/CFB/OFB 等模式。operation:加解密模式,参考
RK_CRYPTO_OPERATION
。key:密钥明文(使用 otp key 操作时无效)。
key_len:密钥长度(单位:字节)。
iv:初始向量(ECB 模式无效,其他模式下,执行
rk_cipher_crypt/crypt_virt
会自动更新,用于多次分段计算)。reserved:预留字段。
3.2.4.3 rk_ae_config
typedef struct {
uint32_t algo;
uint32_t mode;
uint32_t operation;
uint8_t key[32];
uint32_t key_len;
uint8_t iv[16];
uint32_t iv_len;
uint32_t tag_len;
uint32_t aad_len;
uint32_t payload_len;
void *reserved;
} rk_ae_config;
algo:算法类型,参考
RK_CRYPTO_ALGO
,支持 AES/SM4。mode:算法模式,参考
RK_CIPHER_MODE
,支持 GCM/CCM。operation:加解密模式,参考
RK_CRYPTO_OPERATION
。key:密钥明文(使用 keyladder 操作时无效)。
key_len:密钥长度(单位:字节)。
iv:初始向量。
iv_len:IV 的长度(单位:字节)。
tag_len:TAG 的长度(单位:字节)。
aad_len:AAD 的长度(单位:字节)。
payload_len:Payload 的长度(单位:字节)。
reserved:预留字段。
3.2.4.4 rk_hash_config
typedef struct {
uint32_t algo;
uint8_t *key;
uint32_t key_len;
} rk_hash_config;
algo:算法类型,参考
RK_CRYPTO_ALGO
,支持 HASH/HMAC 等多种算法。key:hash-mac 密钥(仅当
algo
为 HMAC 类型算法时有效)。key_len:key 的长度(单位:字节)。
3.2.4.5 rk_rsa_pub_key
typedef struct {
const uint8_t *n;
const uint8_t *e;
uint16_t n_len;
uint16_t e_len;
} rk_rsa_pub_key;
n:模长,与 OpenSSL 相同,大端模式。
e:指数,与 OpenSSL 相同,大端模式。
n_len:模长的长度。
e_len:指数的长度。
3.2.4.6 rk_rsa_pub_key_pack
typedef struct {
enum RK_RSA_KEY_TYPE key_type;
rk_rsa_pub_key key;
} rk_rsa_pub_key_pack;
key_type:密钥类型,参考
RK_RSA_KEY_TYPE
,支持明文密钥和 OTP_KEY 加密后的密文密钥,librkcrypto
会将传入的密钥,用对应的 otp key 密钥解密后再使用。key:公钥内容,结构定义见
rk_rsa_pub_key
。
3.2.4.7 rk_rsa_priv_key
typedef struct {
const uint8_t *n;
const uint8_t *e;
const uint8_t *d;
const uint8_t *p;
const uint8_t *q;
const uint8_t *dp;
const uint8_t *dq;
const uint8_t *qp;
uint16_t n_len;
uint16_t e_len;
uint16_t d_len;
uint16_t p_len;
uint16_t q_len;
uint16_t dp_len;
uint16_t dq_len;
uint16_t qp_len;
} rk_rsa_priv_key;
n:模长,与 OpenSSL 相同,采用大端模式。
e:指数,与 OpenSSL 相同,采用大端模式。
d:模反元素(即私钥),与 OpenSSL 相同,采用大端模式。
p:可选参数。
q:可选参数。
dp:可选参数。
dq:可选参数。
qp:可选参数。
n_len:模长
n
的长度。e_len:指数
e
的长度。d_len:私钥
d
的长度。p_len:参数
p
的长度。q_len:参数
q
的长度。dp_len:参数
dp
的长度。dq_len:参数
dq
的长度。qp_len:参数
qp
的长度。
3.2.4.8 rk_rsa_priv_key_pack
typedef struct {
enum RK_RSA_KEY_TYPE key_type;
rk_rsa_priv_key key;
} rk_rsa_priv_key_pack;
key_type:密钥类型,参考
RK_RSA_KEY_TYPE
,支持明文密钥和 OTP_KEY 加密后的密文密钥,librkcrypto
会将传入的密钥,通过对应的 otp key 密钥解密后使用。key:私钥内容,具体结构定义参考
rk_rsa_priv_key
。
3.2.5 常量定义
略 详见Rockchip_Developer_Guide_Crypto_HWRNG_CN.pdf
3.2.6 API 列表
略 详见Rockchip_Developer_Guide_Crypto_HWRNG_CN.pdf
3.2.7 Debug 日志
librkcrypto 的日志级别如下所示:
日志级别 | 值 |
---|---|
TRACE_TOP | 0 |
TRACE_ERROR | 1 |
TRACE_INFO | 2 |
TRACE_DEBUG | 3 |
TRACE_VERBOSE | 4 |
TRACE_BUTT | - |
默认日志级别为 TRACE_INFO
。
可以通过设置环境变量修改日志级别,需要在 librkcrypto 库加载之前设置环境变量才会生效。也可以在 rk_crypto_init
之前通过 rkcrypto_set_trace_level
接口进行设置。具体设置方法如下:
Android:
setprop vendor.rkcrypto.trace.level 1/2/3/4
Linux:
export rkcrypto_trace_level=1/2/3/4
4. 硬件 Crypto 性能数据
性能数据参考了典型的芯片在 uboot 下的性能,具体详细的性能见 librkcrypto 源码中的
perf_reports
目录。perf_reports
目录的性能为应用层调用 kernel crypto 内核驱动在最高 CPU/DDR 定频下的实测,由于系统调用的原因,性能会比uboot 测试的性能略低。
4.1 U-Boot 层性能
4.1.1 Crypto v1 性能数据
测试环境(uboot RK3399): 时钟:CRYPTO_CORE = 200M,不同芯片的最高频率略有不同 CIPHER/HASH 算法性能测试:
算法 |
实际 (MBps) |
理论 (MBps) |
---|---|---|
DES |
- |
<= 94 |
TDES |
- |
<= 31 |
AES-128 |
- |
<= 290 |
AES-192 |
- |
<= 246 |
AES-256 |
- |
< 213 |
MD5 |
125 |
< 196 |
SHA1 |
125 |
< 158 |
SHA256 |
125 |
- |
RSA 算法性能测试:
| RSA 算法长度(nbits) | 公钥加密/私钥解密 (ms) |
|---------------------|-----------------------|
| 2048 | 8 / 632 |
4.1.2 crypto v2 / v3 /v4 性能数据
这几个版本的CRYPTO IP计算核心没有发生大的变化,性能差异只体现在CRYPTO IP的工作主频上,CRYPTO V3的主频最高可以到350M,其理论性能可以在V2的基础上进行简单换算。 测试环境(uboot RV1126 V2): 时钟:CRYPTO_CORE = 200M,CRYPTO_PKA=300M, DDR=786M Hash/HMAC:总共测试 128M 的数据,每次计算 4M 的数据 DES/3DES/AES/SM4:总共测试 128M 数据,每次计算 4M 的明文和 4M 的 aad 数据
ALGO |
MODE |
Actual (Mbps) |
Theoretical (Mbps) |
---|---|---|---|
HASH/HMAC |
MD5 |
183 |
196 |
SHA1 |
148 |
158 |
|
SHA256/224 |
183 |
196 |
|
SHA512/384/512_224/512_256 |
288 |
316 |
|
SM3 |
183 |
-- |
|
DES |
ECB |
289 |
352 |
CBC/CFB/OFB |
79 |
88 |
|
3DES |
ECB |
107 |
116 |
CBC/CFB/OFB |
27 |
29 |
|
AES (128 | 192 | 256) |
ECB/CTR/XTS |
447 | 442 | 436 |
1066 | 914 | 800 |
CBC/CFB/OFB/CTS |
234 | 204 | 180 |
266 | 228 | 200 |
|
CMAC/CBC_MAC |
245 | 212 | 186 |
266 | 228 | 200 |
|
CCM(data+aad) |
180 | 162 | 146 |
-- |
|
GCM(data+aad) |
196 | 184 | 174 |
-- |
|
SM4 |
ECB/CTR/XTS |
320 |
-- |
CBC/CFB/OFB/CTS |
87 |
-- |
|
CMAC/CBC_MAC |
89 |
-- |
|
CCM(data+aad) |
156 |
-- |
|
GCM(data+aad) |
114 |
-- |
|
RSA 测试方法:生成 rsa key,包含 n, e, d,执行加密和解密测试。 |
|||
加密测试:密文 = d ^e % n |
|||
解密测试:明文 = d^d % n |
|||
RSA类型 |
ENC/DEC |
Time(ms) |
|
----------- |
--------- |
---------- |
|
RSA-1024 |
ENC |
< 1 |
|
DEC |
12 |
||
RSA-2048 |
ENC |
1 |
|
DEC |
93 |
||
RSA-3072 |
ENC |
1 |
|
DEC |
304 |
||
RSA-4096 |
ENC |
2 |
|
DEC |
710 |
5. References
Rockchip 官方文档:
Rockchip_Developer_Guide_Crypto_HWRNG_CN.pdf
Linux 内核源码:
drivers/crypto/rockchip/
NIST SP 800-90B:随机数生成安全标准
6. 附录
6.1 术语
TRNG:真随机数生成器(True Random Number Generator)。
DMA:直接内存访问(Direct Memory Access)。
OTP:一次性可编程存储器(One-Time Programmable)。
注:实际开发需结合具体芯片型号(如 RK3588)和官方 SDK 进行适配。