CE 使用指南
1. 模块介绍
1.1. 术语定义
术语 | 定义 | 注释说明 |
---|---|---|
CE | Crypto Engine | 硬件加解密算法引擎 |
DES | Data Encryption Standard | 一种对称分组密码算法 |
AES | Advanced Encryption Standard | 一种对称分组密钥算法 |
ECB | Electronic Code Book | 电子密码本模式 |
CBC | Cipher Block Chaining | 密码分组链模式 |
CTR | Counter | 计数 器模式 |
XTS | XEX Tweakable Block Cipher with Ciphertext Stealing | 一种对称分组密码算法模式 |
CTS | Ciphertext Stealing | 一种对称分组密码算法模式 |
RSA | Rivest-Shamir-Adleman | 一种非对称密钥算法 |
MD5 | Message Digest Algorithm | 消息摘要算法 |
SHA | Secure Hash Algorithm | 安全散列算法 |
TRNG | True Random Number Generator | 真随机数生成器 |
SSK | Symmetric Secret Key | 对称密钥 |
HUK | Hardware Unique Key | 硬件唯一密钥 |
PNK | Part Number Key | 芯片型号密钥 |
PSK | Partner Secret Key | 合作伙伴密钥 |
1.2. 模块简介
CE 是一个独立的硬件加解密算法引擎,支持下列算法模式:
算法类型 | 算法列表 | 密钥位宽 |
---|---|---|
对称密钥算法 | AES ECB | 128/256 |
AES CBC | 128/256 | |
AES CTR | 128/256 | |
AES CTS | 128/256 | |
AES XTS | 256/512 | |
DES ECB | 64 | |
DES CBC | 64 | |
TDES ECB | 192 | |
TDES CBC | 192 | |
非对称密钥算法 | RSA | 512/1024/2048 |
消息摘要算法 | MD5 | |
SHA-1 | ||
SHA-224 | ||
SHA-256 | ||
SHA-384 | ||
SHA-512 |
同时具备下列功能:
- 真随机数产生器(TRNG)
- 安全访问 eFuse 密钥: eFuse 密钥仅 CE 可访问
- 安全 SRAM: 保护密钥安全
- 本地数据安全:加密的数据仅当前设备可解密,其他设备无法解密
- 硬件设备身份认证:软件可识别当前设备是否合法
- 可支持实现加密启动
- 可支持实现安全启动
- 可支持实现文件系统加密
1.3. 原理框图
图 8.10 CE 原理框图
2. 参数配置
2.1. 内核配置
使能 CE 相关的内核驱动,可在通过下列命令进行配置(在 SDK 顶层目录执行):
make linux-menuconfig
或者使用快捷命令:
make km
在内核的配置界面中,进行下列的选择:
Cryptographic API --->
<*> User-space interface for asymmetric key cipher algorithms
[*] Hardware crypto devices --->
[*] Support for artinchip cryptographic accelerator
<*> Artinchip's crypto engine driver
此处特别选择了 User-space interface for asymmetric key cipher algorithms
是因为默认的 Linux 内核仅对用户空间开放了下列四种类型的算法。
算法类型 | 内核开放接口 | 说明 |
---|---|---|
SKCIPHER | 是 | 对称密钥类算法,如 AES、DES 等 |
AEAD | 是 | 关联数据的认证加密类算法,如 GCM-AES,CCM-AES 等 |
HASH | 是 | 消息摘要类算法,如 MD5,SHA-256 等 |
RNG | 是 | 随机数类算法 |
AKCIPHER | 否 | 非对称密钥类算法,如 RSA |
内核中 非对称密钥类算法
默认并没有对用户空间开放。Artinchip 对内核打了补丁,使得内核支持用户空间程序 使用内核所提供的非对称密钥算法,在配置内核时使能上述配置即可。
2.2. DTS 配置
crypto: crypto-engine@10020000 {
compatible = "artinchip,aic-crypto-v1.0";
reg = <0x0 0x10020000 0x0 0x1000>;
interrupts-extended = <&plic0 33 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cmu CLK_CE>;
resets = <&rst RESET_CE>;
status = "okay";
};
3. 调试指南
3.1. 调试开关
可通过内核配置使能 CE 模块的 DEBUG 选项。在 SDK 根目录下执行:
make linux-menuconfig (or make km)
进入内核的配置界面:
Linux
Kernel hacking
Artinchip Debug
[*] CE driver debug
勾选使能该 DEBUG 选项后:
- CE 的驱动源码将以
-O0
编译- CE 驱动中的 pr_dbg() 和 dev_dbg() 调试信息会被编译
如果需要看到 pr_dbg() 和 dev_dbg() 的打印信息,还需要设置 loglevel=8
。
若需要在启动过程中即可看到打印,需要在 env.txt
中修改 bootargs,增加 loglevel=8
。 若仅需要在板子启动到 Linux shell 后使能相关打印,可以通过下列命令调整 loglevel:
echo 8 > /proc/sys/kernel/printk
4. 测试指南
CE 的测试主要覆盖以下几个要点:
- 驱动所实现的所有算法
- 不同数据长度的处理
- 输入输出 buffer 是否 4KB 对齐(需要支持不对齐的情况)
- 多进程/线程并发访问
测试的方式主要是通过对算法处理后的数据进行“比数”的方式进行,结果与参考结果一致,则表明测试通过。
4.1. 测试工具
主机端工具:
- OpenSSL (主机需要安装)
平台端工具:
- crypto_kcapi (编译 source/artinchip/test-ce)
编译 crypto_kcapi 需要在 SDK 顶层目录执行:
make menuconfig
选择配置:
Artinchip packages
Sample code
[*] test-ce
4.2. 测试对象
需要测试的算法有:
对称密钥算法 | 非对称密钥算法 | 消息摘要算法 |
---|---|---|
cbc(des3_ede)ecb(des3_ede)cbc(des)ecb(des)xts(aes)cts(aes)ctr(aes)cbc(aes)ecb(aes)huk-protected(xts(aes))huk-protected(cts(aes))huk-protected(cbc(aes))huk-protected(ecb(aes))ssk-protected(cbc(aes))ssk-protected(ecb(aes)) | rsapsk3-protected(rsa)psk2-protected(rsa)psk1-protected(rsa)psk0-protected(rsa)pnk-protected(rsa) | sha512sha384sha256sha224sha1md5hmac(sha256)hmac(sha1) |
4.3. 测试方法
4.3.1. 创建测试用例的脚本
HOST 端,通过 gen_xxx_test_data.sh
脚本,生成对应算法的测试脚本。 gen_xxx_test_data.sh
脚本所做的事情包括:
- 生成测试数据:指定长度的
0x00 ~ 0xFF
循环数据- 使用 OpenSSL 工具,根据指定的密钥,生成对应算法加解密后的数据
- 使用 OpenSSL 工具, 对生成的结果计算 MD5 值
- 将对应的 MD5 值写入生成的
test_xxx_script_kcapi.sh
中,作为比较依据- 生成的
test_xxx_script_kcapi.sh
使用 DEVICE 端的crypto_kcapi
工具进行测试
相关的脚本和数据在 source/artinchip/test-ce/test
目录下。目前有下列用于生成测试用例的脚本:
gen_hash_test_data.sh
gen_rsa_test_data.sh
gen_skcipher_ssram_test_data.sh
gen_skcipher_test_data.sh
图 8.11 生成测试脚本
4.3.2. 测试用例脚本
DEVICE 端在系统运行起来之后,可以在 /usr/local/bin/test
目录下,运行测试用例脚本。
测试脚本所做的事情包括:
- 生成测试数据:与 HOST 端一样,指定长度的
0x00 ~ 0xFF
循环数据- 使用 crypto_kcapi 工具,根据指定的密钥,生成对应算法加解密后的数据
- 使用 crypto_kcapi 工具,对生成的结果计算 MD5 值
- 对比测试脚本中的 MD5 值,如果一样,则测试通过,否则失败
图 8.12 运行测试脚本
目前有下列用于测试的脚本:
test_aes_cbc_huk_script_kcapi.sh
test_aes_cbc_script_kcapi.sh
test_aes_cbc_ssk_script_kcapi.sh
test_aes_ctr_huk_script_kcapi.sh
test_aes_ctr_script_kcapi.sh
test_aes_ctr_ssk_script_kcapi.sh
test_aes_ecb_huk_script_kcapi.sh
test_aes_ecb_script_kcapi.sh
test_aes_ecb_ssk_script_kcapi.sh
test_des_cbc_script_kcapi.sh
test_des_ecb_script_kcapi.sh
test_hash_all_script_kcapi.sh
test_md5_script_kcapi.sh
test_rsa_1024_script_kcapi.sh
test_rsa_2048_script_kcapi.sh
test_rsa_512_script_kcapi.sh
test_sha1_script_kcapi.sh
test_sha224_script_kcapi.sh
test_sha256_script_kcapi.sh
test_sha384_script_kcapi.sh
test_sha512_script_kcapi.sh
test_skciper_all_script_kcapi.sh
5. 设计说明
5.1. 源码说明
相关模块 | 源码路径 |
---|---|
1. Crypto subsystem2. AF_ALG | source/linux-5.10/crypto/ |
Driver | source/linux-5.10/drivers/crypto/artinchip/ce/ |
5.2. 模块架构
CE 模块对接内核加密子系统。 CE <—> Crypto subsystem <—> User space
之间的层次关系如下图所示。
图 8.13 CE 与内核加密子系统
Linux 内核加密子系统由几个部分组成
-
核心部分:
该部分实现了加密子系统的主要核心功能,包括主要的数据结构和管理所支持的算法类型以及不同算法之间进行组合的模板等对下对接各种算法的具体软硬件实现,对上提供对应的 API,为内核其他模块提供服务。
-
算法实现部分:
分为软件的基本算法实现硬件算法加速器的驱动。
-
用户空间接口部分:
内核加密子系统通过 Socket 接口向用户空间程序提供服务AF_NETLINK 接口,提供关于加密学子系统的信息,用户态程序可以通过该接口查询当前加密子系统向用户态提供了哪些服务,以及相关算法的详细信息;AF_ALG 接口,提供与具体算法进行交互的接口,用户态程序可以使用该接口对数据进行加解密等处理。
5.3. 设计要点
5.3.1. CE 算法的分类注册
CE 硬件实现了多组不同类型的加密算法加速单元,分别对应内核加密子系统中的几种类型加密算法。在驱动实现时,根据不同的算法类型,将 CE 硬件抽象出三个不同的算法加速器:
- 对称密钥算法加速器
- 非对称密钥算法加速器
- 消息摘要算法加速器
驱动按照不同的算法加速器进行资源分配和实现,每个算法加速器支持多种不同的具体算法,并且将具体算法注册到加密子系统 。
图 8.14 CE 算法分类
驱动为 每一个 CE 算法实现一个实例,然后注册到内核加密子系统。 内核加密子系统使用链表的方式管理所有注册的算法,后续的使用者通过两个名字( cra_name
, cra_driver_name
)可以查找到对应的算法。 例如:
struct skcipher_alg alg = {
.base.cra_name = "ecb(aes)",
.base.cra_driver_name = "ecb-aes-aic",
.base.cra_priority = 400,
.base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY,
.base.cra_blocksize = AES_BLOCK_SIZE,
.base.cra_ctxsize = sizeof(struct aic_skcipher_tfm_ctx),
.base.cra_alignmask = 0,
.base.cra_module = THIS_MODULE,
.init = aic_skcipher_alg_init,
.exit = aic_skcipher_alg_exit,
.setkey = aic_skcipher_alg_setkey,
.decrypt = aic_skcipher_aes_ecb_decrypt,
.encrypt = aic_skcipher_aes_ecb_encrypt,
.min_keysize = AES_MIN_KEY_SIZE,
.max_keysize = AES_MAX_KEY_SIZE,
.ivsize = 0,
};
各驱动和算法实现模块,通过下列接口向加密子系统注册算法。
int crypto_register_skcipher(struct skcipher_alg *alg);
void crypto_unregister_skcipher(struct skcipher_alg *alg);
int crypto_register_akcipher(struct akcipher_alg *alg);
void crypto_unregister_akcipher(struct akcipher_alg *alg);
int crypto_register_ahash(struct ahash_alg *alg);
void crypto_unregister_ahash(struct ahash_alg *alg);
int crypto_register_aead(struct aead_alg *alg);
void crypto_unregister_aead(struct aead_alg *alg);
int crypto_register_kpp(struct kpp_alg *alg);
void crypto_unregister_kpp(struct kpp_alg *alg);
int crypto_register_rng(struct rng_alg *alg);
void crypto_unregister_rng(struct rng_alg *alg);
图 8.15 加密子系统的算法列表
使用时,使用者需要使用对应的 API,创建对应算法的数据处理实例,然后使用对应类型算法的接口,进行数据的处理。如对称密钥算法使用下列的接口。
struct crypto_skcipher *
crypto_alloc_skcipher(const char *alg_name, u32 type, u32 mask);
struct skcipher_request *
skcipher_request_alloc(struct crypto_skcipher *tfm, gfp_t gfp);
int crypto_skcipher_encrypt(struct skcipher_request *req);
int crypto_skcipher_decrypt(struct skcipher_request *req);
注解
可以留意,以对对称密钥算法为例,向加密子系统注册算法实例时,使用的结构体为 struct skciper_alg
, 用户 API 使用时,使用的结构体为 struct crypto_skcipher
。这里的区别是,前者是对内, 是具体算法的实现;后者是对外,代表一个对称密钥算法。
5.3.2. 异步调用和处理
为了支持更广泛的应用场景,CE 的算法驱动需要实现异步调用,即每一个请求调用,都会立刻返回, 然后通过注册的回调函数来获取请求处理完成的通知。
要实现异步调用需要为每一个加速器实现对应的任务队列,以及相应的执行线程。内核加密子系统提供的公共模块 crypto_engine
已经实现了对应的功能,只需为每个加速器创建 crypto_engine
即可。
图 8.16 Crypto Engine 的异步工作流程
如上图所示,当算法驱动接收到一个数据处理请求时,只需做一些基本的标记工作,然后将该请求转发给对应的 crypto_engine
进行管理。crypto_engine
包含一个任务队列,以及一个工作线程。
工作线程总是检查当前队列是否有待处理的任务,如果有任务需要处理,则对当前任务按顺序调用对应的回调函数:
回调函数 | 说明 |
---|---|
prepare(…) | 准备硬件以及对将要送给硬件的数据进行预处理 |
do_one_request(…) | 启动硬件,处理数据 |
硬件完成处理之后,在对一个的 IRQ 处理线程中处理输出数据,并且调用该请求的回调函数,以及释放本次数据处理请求所申请的资源。
注解
CE 的每一个算法处理单元对应一个 crypto_engine
, 即有:skcipher engine,akcipher engine,hash engine