乐趣区

关于linux内核模块:SCE-内核态接口使用手册

1. 介绍

SCE 部件作为飞腾平台的平安组件,提供了对称算法加速器 (SCA)、哈希算法加速器(HASH)、非对称算法加速器(ACA) 和真随机数生成器(TRNG)。

用户通过 Linux Kernel Crypto API 框架实现内核对各种算法驱动的反对,目前内核态已实现 SCA、HASH、TRNG 反对的算法驱动。通过装置 SCE 内核层驱动可查看已反对的算法驱动,利用开发者可通过相应的内核态接口实现对算法模块的调用。

2. 装置与测试

2.1 硬件及零碎要求

硬件要求如下表所示。

我的项目 阐明
CPU 飞腾平台 CPU
已支持系统 1、Ubuntu 22.04(kernel 4.19.0)
存储 无要求
内存 无要求

2.2 软件目录架构

软件目录架构如图所示:
1.src 文件夹:驱动模块源码。
2.include 文件夹:驱动模块头文件。
3.test 文件夹:内核层驱动测试代码。

2.3 内核驱动算法概述

目前反对的内核态驱动算法如下表所示。

加速器 算法 算法名 驱动名
对称引擎 SM4 ecb(sm4)
cbc(sm4)
ctr(sm4)
ofb(sm4)
ecb(sm4)-phytium
cbc(sm4)phytium
ctr(sm4)-phytium
ofb(sm4)-phytium
对称引擎 AES ecb(aes)
cbc(aes)
ctr(aes)
ofb(aes)
ecb(aes)-phytium
cbc(aes)phytium
ctr(aes)-phytium
ofb(aes)-phytium
对称引擎 DES ecb(des)
cbc(des)
ctr(des)
ofb(des)
ecb(des3_ede)
cbc(des3_ede)
ctr(des3_ede)
ofb(des3_ede)
ecb(aes)-phytium
cbc(aes)phytium
ctr(aes)-phytium
ofb(aes)-phytium
ecb(des3_ede)-phytium
cbc(des3_ede)-phytium
ctr(des3_ede)-phytium
ofb(des3_ede)-phytium
哈希引擎 DES ecb(des)
cbc(des)
ctr(des)
ofb(des)
ecb(des3_ede)
cbc(des3_ede)
ctr(des3_ede)
ofb(des3_ede)
ecb(des)-phytium
cbc(des)-phytium
ctr(des)-phytium
ofb(des)-phytium
ecb(des3_ede)-phytium
cbc(des3_ede)-phytium
ctr(des3_ede)-phytium
ofb(des3_ede)-phytium
哈希引擎 SHA sha1
sha224
sha256
sha384
sha512
md5
hmac(sha1)
hmac(sha224)
hmac(sha256)
hmac(sha384)
hmac(sha512)
hmac(md5)
sha1-phytium
sha224-phytium
sha256-phytium
sha384-phytium
sha512-phytium
md5-phytium
hmac(sha1)-phytium
hmac(sha224)-phytium
hmac(sha256)-phytium
hmac(sha384)-phytium
hmac(sha512)-phytium
hmac(md5)-phytium
哈希引擎 SM3 sm3
hmac(sm3)
sm3-phytium
hmac(sm3)-phytium
真随机数生成器 TRNG TRNG trng-phytium

2.4 内核层编译、装置与测试

1.SCE 内核层内核驱动编译装置步骤

进入驱动代码目录
cd driver
# 编译驱动模块
make
# 加载驱动模块
sudo insmod phytium_sce.ko
# 抉择应用内核层驱动模块
# 驱动模块反对用户态和内核态切换
# 通过操作 /proc/sce_dir/sce_work_state 管制
# 输出 1 启用内核态模块,输出 2 启用用户态模块,输出 0 敞开所有模块
sudo echo 1 > /proc/sce_dir/sce_work_state
# 查看驱动模块以后模式
cat /proc/sce_dir/sce_work_state
# 查看内核反对的 SCE 算法驱动
cat /proc/crypto | grep phytium

2.SCE 内核态接口编译装置

# 进入内核态测试代码目录
cd driver/test
# 编译测试模块
make

# 在执行 mtest.ko 前必须先加载好内核驱动模块
# 执行 mtest.ko 时通过传入参数可反对对不同算法进行功能性测试
# 倡议关上两个终端窗口 A 和 B,其中可在 A 终端输出测试命令,B 终端执行命令“sudo dmesg -w”sudo insmod mtest.ko #当在终端 A 执行该命令之后,可在终端 B 查到到内核打印信息,其中表明须要传入的参数信息

#示例命令,对 hash 进行功能测试
sudo insmod mtest.ko alg=sm3 mode=hash

3 SCE 内核态 API 阐明

该章节介绍 SCE 内核态 API 接口,接口的应用示例可浏览参考 kernel/test 目录下的测试用例。

3.1 哈希算法

3.1.1 调配哈希算法对象

函数原型 struct crypto_ahash *crypto_alloc_ahash(const char *alg_name, u32 type, u32 mask)
函数性能 调配一个新创建的异步哈希算法实例
输出阐明 alg_name – 算法名
type – 算法类型
mask – 算法类型屏蔽字
输入阐明
返回值阐明 新创建的异步哈希算法对象
应用阐明
注意事项 hash 算法能够是同步形式实现或异步形式实现,但算法利用不关注 hash 算法的实现形式,而是关注 hash 算法提供的算法接口。为实现对立治理,加密框架默认 hash 算法的实现形式为异步形式,将哈希算法的内部接口对立定义为异步哈希算法接口

3.1.2 调配哈希算法数据申请对象

函数原型 struct ahash_request *ahash_request_alloc(struct crypto_ahash *tfm, gfp_t gfp)
函数性能 调配申请数据结构
输出阐明 tfm – 算法实例
gfp – API 调用传递给 kmalloc 的内存调配标记
输入阐明
返回值阐明 胜利时返回调配的申请句柄,如果内存不足则返回 NULL
应用阐明
注意事项 若为同步调用的形式,则不须要调配创立 req 对象

3.1.3 设置异步回调

函数原型 void ahash_request_set_callback(struct ahash_request *req, u32 flags,crypto_completion_t compl, void *data)
函数性能 用于设置加解密实现后须要调用的回调函数
输出阐明 req – 申请句柄
flags - 标记位,指定为 0 或 ORing
compl - 注册到申请句柄的回调函数指针
data – 指向内核加密 API 不应用的内存
输入阐明
返回值阐明
应用阐明
注意事项

3.1.4 设置密钥

函数原型 int crypto_ahash_setkey(struct crypto_ahash *tfm, const u8 *key, unsigned int keylen)
函数性能 设置密钥
输出阐明 tfm – 算法实例
key – 密钥数据
keylen – 密钥数据长度
输入阐明
返回值阐明 胜利时返回调配的申请句柄,如果内存不足则返回 NULL
应用阐明
注意事项

3.1.5 设置数据

函数原型 void ahash_request_set_crypt(struct ahash_request *req, struct scatterlist *src, u8 *result, unsigned int nbytes)
函数性能 设置数据内存
输出阐明 req – 申请句柄
src – 源扩散 / 收集列表
result – 由音讯摘要填充的缓冲区
nbytes – 从 @src 解决的字节数
输入阐明
返回值阐明
应用阐明
注意事项

3.1.6 性能接口

函数原型 int crypto_ahash_init(struct ahash_request *req)
int crypto_ahash_digest(struct ahash_request *req)
int crypto_ahash_update(struct ahash_request *req)
int crypto_ahash_finup(struct ahash_request *req)
int crypto_ahash_final(struct ahash_request *req)
函数性能 init:初始化音讯摘要
digest:计算缓冲区的音讯摘要
update:向音讯摘要中增加数据以进行解决
finup:更新和实现音讯摘要
final:计算音讯摘要
输出阐明 req – ahash_request 句柄
输入阐明
返回值阐明 胜利计算音讯摘要返回 0,非 0 为 失败
应用阐明 hash 算法最终摘要值生成接口能够有多种调用形式,如 crypto_ahash_digest 示意在该接口中会实现生成摘要相干的所有流程。当然该操作也可拆分为 init、update、final 或 init、update、finup 类型的步骤,步骤拆分当前就能够反对在 init 之后执行屡次 update,以间断为 hash 操作提供数据,并在数据更新实现后调用 final 操作获取所有数据的最终 hash 值
注意事项

3.1.7 开释 req 资源

函数原型 void ahash_request_free(struct ahash_request *req)
函数性能 开释 req 资源
输出阐明 req – ahash_request 句柄
输入阐明
返回值阐明
应用阐明
注意事项

3.1.8 开释 tfm 资源

函数原型 void crypto_free_ahash(struct crypto_ahash *tfm)
函数性能 开释 tfm 资源
输出阐明 tfm - 算法实例
输入阐明
返回值阐明
应用阐明
注意事项

3.2 对称算法

3.2.1 调配对称算法对象

函数原型 struct crypto_skcipher *crypto_alloc_skcipher(const char *alg_name, u32 type, u32 mask)
函数性能 调配一个新创建的对称算法实例
输出阐明 alg_name – 算法名
type – 算法类型
mask – 算法类型屏蔽字
输入阐明
返回值阐明 新创建的算法实例
应用阐明
注意事项

3.2.2 调配对称算法数据申请对象

函数原型 struct skcipher_request *skcipher_request_alloc(struct crypto_skcipher *tfm, gfp_t gfp)
函数性能 调配 req
输出阐明 tfm – 算法实例
gfp – API 调用传递给 kmalloc 的内存调配标记
输入阐明
返回值阐明 胜利时返回调配的申请句柄,如果内存不足则返回 NULL
应用阐明
注意事项

3.2.3 设置异步回调

函数原型 void skcipher_request_set_callback(struct skcipher_request *req, u32 flags, crypto_completion_t compl, void *data)
函数性能 用于设置加解密实现后须要调用的回调函数
输出阐明 req – 申请句柄
flags - 标记位,指定为 0 或 ORing
compl - 注册到申请句柄的回调函数指针
data – 指向内核加密 API 不应用的内存
输入阐明
返回值阐明
应用阐明
注意事项

3.2.4 设置密钥

函数原型 int crypto_skcipher_setkey(struct crypto_skcipher *tfm, const u8 *key, unsigned int keylen)
函数性能 设置密钥
输出阐明 tfm – 算法实例
key – 密钥数据
keylen – 密钥数据长度
输入阐明
返回值阐明 胜利时返回调配的申请句柄,如果内存不足则返回 NULL
应用阐明
注意事项

3.2.5 设置数据

函数原型 void skcipher_request_set_crypt(struct skcipher_request *req, struct scatterlist *src, struct scatterlist *dst, unsigned int cryptlen, void *iv)
函数性能 设置数据内存
输出阐明 req – 申请句柄
src – 源扩散 / 收集列表
dst – 指标扩散 / 收集列表
cryptlen – 从 @src 解决的字节数
iv – IV 数据,必须合乎 crypto_skcipher_ivsize 定义的 IV 大小
输入阐明
返回值阐明
应用阐明
注意事项

3.2.6 加密

函数原型 int crypto_skcipher_encrypt(struct skcipher_request *req)
函数性能 加密流程
输出阐明 req – 申请句柄
输入阐明
返回值阐明 胜利加密返回 0,非 0 为失败
应用阐明
注意事项

3.2.7 解密

函数原型 int crypto_skcipher_decrypt(struct skcipher_request *req)
函数性能 解密流程
输出阐明 req – 申请句柄
输入阐明
返回值阐明 胜利解密返回 0,非 0 为失败
应用阐明
注意事项

3.2.8 开释 req 资源

函数原型 void skcipher_request_free(struct skcipher_request *req)
函数性能 开释 req 资源
输出阐明 req – 申请句柄
输入阐明
返回值阐明
应用阐明
注意事项

3.2.9 开释 tfm 资源

函数原型 void crypto_free_skcipher(struct crypto_skcipher *tfm)
函数性能 开释 tfm 资源
输出阐明 tfm - 算法实例
输入阐明
返回值阐明
应用阐明
注意事项

3.3 真随机数生成器

3.3.1 调配真随机数生成器对象

函数原型 struct crypto_rng *crypto_alloc_rng(const char *alg_name, u32 type, u32 mask)
函数性能 调配一个新创建的 TRNG 实例
输出阐明 alg_name – 算法名
type – 算法类型
mask – 算法类型屏蔽字
输入阐明
返回值阐明 新创建的算法实例
应用阐明
注意事项

3.3.2 获取随机数

函数原型 int crypto_rng_get_bytes(struct crypto_rng *tfm, u8 *rdata, unsigned int dlen)
函数性能 获取随机数
输出阐明 tfm – 算法实例
rdata – 保留随机数的输入缓冲区
dlen – 输入缓冲区的长度
输入阐明
返回值阐明 0 为胜利,非 0 为失败
应用阐明
注意事项

3.3.3 开释 tfm 资源

函数原型 void crypto_free_rng(struct crypto_rng *tfm)
函数性能 开释 tfm 资源
输出阐明 tfm - 算法实例
输入阐明
返回值阐明
应用阐明
注意事项

4 算法应用示例

4.1 哈希算法应用示例

4.1.1 定义构造

定义多个构造体变量,其中:
struct crypto_wait:异步操作期待对象
struct ahash_request:异步操作申请对象
struct crypto_ahash:哈希算法对象(上下文)
struct scatterlist:用来保留加 / 解密缓冲区的构造

     struct crypto_wait wait;
     struct ahash_request *req;
     struct crypto_ahash *tfm;
     struct scatterlist *sg = NULL;

4.1.2 申请内存

申请明文(src)和哈希值(dst)的数据内存空间。

     src = kmalloc(1024 + 512, GFP_KERNEL);
     if (src == NULL) {printk(KERN_ERR"%s:kmalloc failed!\n", __func__);
          return; 
     }
     dst = src+1024;

4.1.3 调配算法对象

通过传入的算法名 alg 和内核接口 crypto_alloc_ahash 调配算法名对应的算法对象,反对的算法对象能够通过在 /proc/crypto 文件中查看。

     tfm = crypto_alloc_ahash(alg, 0, 0);
         if (IS_ERR(tfm)) {printk(KERN_ERR"failed to load transform for %s: %ld\n", alg, PTR_ERR(tfm));
             return;
         }

4.1.4 调配算法数据申请对象

调配 request 异步操作期待对象。

     req = ahash_request_alloc(tfm, GFP_KERNEL);
         if (!req) {printk(KERN_INFO"ahash: Failed to allocate request for %s\n", alg);
                  goto fail;
     }

4.1.5 设置上下文

设置上下文,通过 ahash_request_set_callback 接口给异步申请对象设置回调函数,负责唤醒实现量相干的的回调传给加解密函数,以使其能在实现后唤醒对应线程。通过 crypto_ahash_setkey 接口为 hash 算法设置密钥。通过 ahash_request_set_crypt 接口设置生成哈希值操作相干参数,如源数据 sg 指针、填充音讯哈希值的缓冲区以及数据长度信息。

         crypto_init_wait(&wait);
         ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, crypto_req_done, &wait);
         if (key && klen)
              crypto_ahash_setkey(tfm, key, klen);

         if (len) {sg = kmalloc(sizeof(struct scatterlist) * len, GFP_KERNEL);
                  if (sg == NULL) {printk(KERN_ERR"%s:kmalloc sg failed!\n", __func__);
                       goto fail1;
                  }
                  sg_init_table(sg, len);
                  for (i = 0; i < len; i ++) {sg_set_buf(sg + i, data + i, 1);
                  }
         }
         ahash_request_set_crypt(req, sg, out, len);

4.1.6 进行 digest 摘要操作

     ret = crypto_wait_req(crypto_ahash_digest(req), &wait);
     if (ret) {printk(KERN_ERR"hashing failed ret=%d\n", ret);
     }

4.1.7 开释对象

     ahash_request_free(req);
     crypto_free_ahash(tfm);

4.2 对称算法应用示例

定义多个构造体变量,其中:
struct crypto_wait:异步操作期待对象
struct skcipher_request:对称密钥异步操作申请对象
struct crypto_skcipher:加密算法对象(上下文)
struct scatterlist:用来保留加 / 解密缓冲区的构造

struct crypto_wait wait;
struct skcipher_request *req;
struct crypto_skcipher *tfm;
struct scatterlist *ssg = NULL, *dsg = NULL;

4.2.2 申请内存

申请明文(src)、密文(dst)、密钥(key)和 IV(iv)等数据内存空间。

     src = kmalloc(1024 * 3, GFP_KERNEL);
     if (src == NULL) {printk(KERN_ERR"%s:kmalloc failed!\n", __func__);
        return;
     }
     memset(src, 0, 1024*3);
     dst = src + 1024;
     key = dst + 1024;
     iv = key + 512;

4.2.3 调配算法对象

通过传入的算法名 alg 和内核接口 crypto_alloc_skcipher 调配算法名对应的算法对象,反对的算法对象能够通过在 /proc/crypto 文件中查看。

    tfm = crypto_alloc_skcipher(alg, 0, 0);
    if (IS_ERR(tfm)) {printk(KERN_ERR"failed to load transform for %s: %ld\n", alg, PTR_ERR(tfm));
        return;
    }

4.2.4 调配算法数据申请对象

调配 request 异步操作期待对象。

     req = skcipher_request_alloc(tfm, GFP_KERNEL);
     if (!req) {printk(KERN_INFO"skcipher: Failed to allocate request for %s\n", alg);
         goto fail;
     }

4.2.5 设置上下文

设置上下文,通过 skcipher_request_set_callback 接口给异步申请对象设置回调函数,负责唤醒实现量相干的的回调传给加解密函数,以使其能在实现后唤醒对应线程。通过 crypto_skcipher_setkey 接口为 skcipher 算法设置密钥。通过 skcipher_request_set_crypt 接口设置加解密操作相干参数,如源数据、目标数据 sg 指针、iv 指针以及数据长度信息。

    crypto_init_wait(&wait);
    skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, crypto_req_done, &wait);
    crypto_skcipher_clear_flags(tfm, ~0);
    crypto_skcipher_setkey(tfm, key, klen);

    ssg = kmalloc(sizeof(struct scatterlist) * len, GFP_KERNEL);
    if (ssg == NULL) {printk(KERN_ERR"%s:kmalloc ssg failed!\n", __func__);
        goto fail1;
    }
    sg_init_table(ssg, len);
    for (i = 0; i < len; i ++) {sg_set_buf(ssg + i, data + i, 1);
    }

     dsg = kmalloc(sizeof(struct scatterlist) * len, GFP_KERNEL);
     if (dsg == NULL) {printk(KERN_ERR"%s:kmalloc dsg failed!\n", __func__);
         goto fail2;
     }
     sg_init_table(dsg, len);
     for (i = 0; i < len; i ++) {sg_set_buf(dsg + i, out + i, 1);
     }
    skcipher_request_set_crypt(req, ssg, dsg, len, iv);

4.2.6 实现加 / 解密

通过 crypto_skcipher_encrypt 接口执行理论的加密流程。
通过 crypto_skcipher_decrypt 接口执行理论的解密流程。

    if (enc)
        ret = crypto_wait_req(crypto_skcipher_encrypt(req), &wait);
    else
        ret = crypto_wait_req(crypto_skcipher_decrypt(req), &wait);
    if (ret) {printk(KERN_ERR"failed ret=%d\n", ret);
    }

4.2.7 开释对象

     skcipher_request_free(req);
     crypto_free_skcipher(tfm);

4.3 真随机数生成器应用示例

4.3.1 定义构造

定义多个构造体变量,其中:
struct crypto_rng:随机数算法对象(上下文)

    struct crypto_rng *tfm;

4.3.2 调配算法对象

通过传入的算法名 alg 和内核接口 crypto_alloc_rng 调配算法名对应的算法对象,反对的算法对象能够通过在 /proc/crypto 文件中查看。

     tfm = crypto_alloc_rng("trng", 0, 0);
     if (IS_ERR(tfm)) {printk(KERN_ERR "alg: cprng: Failed to load transform for %s:""%ld\n","trng", PTR_ERR(tfm));
         return;
     }

4.3.3 获取随机数

     err = crypto_rng_get_bytes(tfm, buf, len);
     if(err) {printk(KERN_ERR"generate len %d error", len);
        break;
     }

4.3.4 开释对象

     crypto_free_rng(tfm);

5 术语和缩略语

术语 全称 解释
ACA Asymmetric Cryptography Accelerator 非对称明码加速器
SCA Symmetric Cryptography Accelerator 对称明码加速器
TRNG True Random Number Generator 真随机数发生器

6 常见问题


版权所有。飞腾信息技术有限公司 2023。保留所有权力。
未经本公司批准,任何单位、公司或集体不得擅自复制,翻译,摘抄本文档内容的局部或全副,不得以任何形式或路径进行流传和宣传。

商标申明
Phytium 和其余飞腾商标均为飞腾信息技术有限公司的商标。
本文档提及的其余所有商标或注册商标,由各自的所有人领有。

留神
本文档的内容视为飞腾的窃密信息,您该当严格遵守窃密工作;未经飞腾当时书面批准,您不得向任何第三方披露本文档内容或提供给任何第三方应用。

因为产品版本升级或其余起因,本文档内容会不定期进行更新。除非另有约定,本文档仅作为应用领导,飞腾在现有技术的根底上尽最大致力提供相应的介绍及操作指引,但飞腾在此明确申明对本文档内容的准确性、完整性、适用性、可靠性的等不作任何明示或暗示的保障。

本文档中所有内容,包含但不限于图片、架构设计、页面布局、文字描述,均由飞腾和 / 或其关联公司依法领有其知识产权,包含但不限于商标权、专利权、著作权等。非经飞腾和 / 或其关联公司书面批准,任何人不得擅自应用、批改,复制上述内容。
如有技术问题,可分割 support@phytium.com.cn 获取反对。

退出移动版