cipher使用参考¶
REVISION HISTORY¶
| Revision No. | Description |
Date |
|---|---|---|
| 1.0 | 04/18/2024 | |
| 1.1 | 04/11/2025 |
1. 概述¶
cipher模块,可用于对数据进行aes加解密、sha计算、rsa加解密与签章验签。
2. 关键字说明¶
-
AESDMA
进行加解密计算的硬件模块。
3. 功能描述¶
-
aes
支持aes128/aes192/aes256加解密算法;模式包括ecb/cbc/ctr模式;支持使用硬件密钥以及软件密钥。
-
hash
支持sha1/sha256算法,输入数据长度无限制
-
rsa
支持rsa2048/rsa4096加解密,签章验签;支持使用硬件密钥以及软件密钥
-
sm2/sm3/sm4
支持国密sm2/sm3/sm4算法
-
ECC160/192/256/384/512/521
支持椭圆曲线算法ECC160/192/256/384/512/521
4. Uboot用法介绍¶
4.1 代码框架和config¶
4.1.1 代码框架¶

4.1.2 uboot config¶
uboot下打开以下配置
[*] Sgs SoC platform drivers --->
[*] Sgs Crypto driver
4.2 cipher API接口解析¶
uboot下cipher api接口使用方法与kernel下的api用法一致,api介绍请参考5.3章节。
demo请参考cmd/sgs/aes.c文件中 do_verifyaes 接口的测试用例。
5. Kernel用法介绍¶
5.1 代码框架和kernel config¶
5.1.1 代码框架¶

5.1.2 kernel config¶
kernel下打开以下配置,才可正常使用aesdma.
Device Drivers --->
[*] Sgs SoC platform drivers --->
<*> Sgs Crypto driver
[*] HW_RANDOM Random Number Generator support
[*] Enable aesdma debug node
[ ] crypto in optee
<*> Support cryptodev
5.2 userspace下访问接口¶
通过用户层ioctl访问kernel。
- aes, sha, sm3, sm4:借助模块cryptodev,它提供了一种通用的加密API,使应用程序能够利用硬件加速的加密功能。可以通过打开
/dev/crypto设备文件来访问加密功能。应用程序可以使用常见的加密算法(如AES、DES等)和模式(如CBC、ECB、CTR等)来执行加密和解密操作。
rsa, sm2, ecc
- rsa, sm2, ecc:Kernel原生接口中不支持RSA/SM2/ECC算法,故RSA/SM2/ECC使用Linux标准接口注册misc类设备,产生
/dev/rsa和/dev/sm2节点, User Space可通过节点使用Hardware RSA/SM2/ECC算法。
5.2.1 aes/sm4加解密接口¶
demo路径:drivers/sgs_common/cryptodev/examples/aes.c drivers/sgs_common/cryptodev/examples/sm4.c
使用otpkey的demo:drivers/sgs_common/cryptodev/examples/aes-sgs-unique.c
-
打开节点
int cfd = -1; /* Open the crypto device */ cfd = open("/dev/crypto", O_RDWR, 0); if (cfd < 0) { perror("open(/dev/crypto)"); return 1; } /* Set close-on-exec (not really needed here) */ if (fcntl(cfd, F_SETFD, 1) == -1) { perror("fcntl(F_SETFD)"); return 1; } -
创建session
int aes_ctx_init(struct cryptodev_ctx* ctx, int cfd, const uint8_t* key, unsigned int key_size) { #ifdef CIOCGSESSINFO struct session_info_op siop; #endif memset(ctx, 0, sizeof(*ctx)); ctx->cfd = cfd; ctx->sess.cipher = CRYPTO_AES_CBC; // use CRYPTO_SM4_CBC for SM4 CBC mode ctx->sess.keylen = key_size; ctx->sess.key = (void*)key; if (ioctl(ctx->cfd, CIOCGSESSION, &ctx->sess)) { perror("ioctl(CIOCGSESSION)"); return -1; } #ifdef CIOCGSESSINFO memset(&siop, 0, sizeof(siop)); siop.ses = ctx->sess.ses; if (ioctl(ctx->cfd, CIOCGSESSINFO, &siop)) { perror("ioctl(CIOCGSESSINFO)"); return -1; } printf("Got %s with driver %s\n", siop.cipher_info.cra_name, siop.cipher_info.cra_driver_name); if (!(siop.flags & SIOP_FLAG_KERNEL_DRIVER_ONLY)) { printf("Note: This is not an accelerated cipher\n"); } /*printf("Alignmask is %x\n", (unsigned int)siop.alignmask); */ ctx->alignmask = siop.alignmask; #endif return 0; }key参数说明:
1)如果使用软件密钥,直接传入密钥的数据即可
2)如果使用硬件密钥,参考如下规则:
具体otpkey的生成以及烧录方式请参考Secureboot使用文档:Security_Boot使用参考文档中的第2章 OTP Key读写操作说明,关于Security_Boot使用参考文档可以咨询FAE窗口。
OTP中AESKEY256实际上是由OTP中两把AES128组合而成,组合和设置方式举例如下。
欲设置:
KEY256_1:000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F需设置:
key128_1:000102030405060708090A0B0C0D0E0Fkey128_2:101112131415161718191A1B1C1D1E1F配置方法和对应关系如下表:
eKeyType keylen corresponding otpkey DRV_SKCIPHER_KEY_SEL_HW_1 16 key128_1 DRV_SKCIPHER_KEY_SEL_HW_2 16 key128_2 DRV_SKCIPHER_KEY_SEL_HW_3 16 key128_3 DRV_SKCIPHER_KEY_SEL_HW_4 16 key128_4 DRV_SKCIPHER_KEY_SEL_HW_1 32 key256_1(key128_1+key128_2) DRV_SKCIPHER_KEY_SEL_HW_2 32 key256_2(key128_3+key128_4) 由于kernel原生没有选择是否使用otpkey的接口,程序会根据key的头部是否是特殊的字符序列"SGSU*"判断是否使用otpkey。
配置方法和对应关系如下表:
key keylen otpkey "SGSKEYN\x01" 16 key128_1 "SGSKEYN\x02" 16 key128_2 "SGSKEYN\x03" 16 key128_3 "SGSKEYN\x04" 16 key128_4 "SGSKEYN\x01" 32 key256_1(key128_1+key128_2) "SGSKEYN\x02" 32 key256_2(key128_3+key128_4) 例如使用otp key128_1,则key设置
unsigned char key[16] = {'S', 'G', 'S', 'K', 'E', 'Y', 'N', 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};注意:key长度需要满足16byte/32byte,前8byte数据需要按如上格式进行设置,其余位置的数据没有要求。
-
进行加解密
结构体说明
struct crypt_op { __u32 ses; /* session identifier */ __u16 op; /* COP_ENCRYPT or COP_DECRYPT */ __u16 flags; /* see COP_FLAG_* */ __u32 len; /* length of source data */ __u8 __user *src; /* source data */ __u8 __user *dst; /* pointer to output data */ /* pointer to output data for hash/MAC operations */ __u8 __user *mac; /* initialization vector for encryption operations */ __u8 __user *iv; };加解密实例
int aes_encrypt(struct cryptodev_ctx* ctx, const void* iv, const void* plaintext, void* ciphertext, size_t size) { struct crypt_op cryp; void* p; /* check plaintext and ciphertext alignment */ if (ctx->alignmask) { p = (void*)(((unsigned long)plaintext + ctx->alignmask) & ~ctx->alignmask); if (plaintext != p) { fprintf(stderr, "plaintext is not aligned\n"); return -1; } p = (void*)(((unsigned long)ciphertext + ctx->alignmask) & ~ctx->alignmask); if (ciphertext != p) { fprintf(stderr, "ciphertext is not aligned\n"); return -1; } } memset(&cryp, 0, sizeof(cryp)); /* Encrypt data.in to data.encrypted */ cryp.ses = ctx->sess.ses; cryp.len = size; cryp.src = (void*)plaintext; cryp.dst = ciphertext; cryp.iv = (void*)iv; cryp.op = COP_ENCRYPT; if (ioctl(ctx->cfd, CIOCCRYPT, &cryp)) { perror("ioctl(CIOCCRYPT)"); return -1; } return 0; } -
关闭session
void aes_ctx_deinit(struct cryptodev_ctx* ctx) { if (ioctl(ctx->cfd, CIOCFSESSION, &ctx->sess.ses)) { perror("ioctl(CIOCFSESSION)"); } } -
关闭节点
/* Close the original descriptor */ if (close(cfd)) { perror("close(cfd)"); return 1; }注意目前硬件加速只支持aes(ecb/cbc/ctr)以及sm4(ecb/cbc/ctr),如果需要使用其他算法,将使用软件解密。其中,硬件加速的aes/sm4对输入数据大小的对齐要求如下:
mode size alignment ecb 16 bytes cbc 1 bytes ctr 1 bytes 对输入数据的内存地址没有对齐要求,但使用aes的时候建议为16bytes对齐,可使得cryptodev开启zero copy功能,减少用户层与内核层之间的内存拷贝。
硬件加速AES支持key size为128/256 bit,硬件加速SM4支持的key size为128 bit。
5.2.2 hash运算接口¶
demo路径:drivers/sgs_common/cryptodev/examples/sha.c drivers/sgs_common/cryptodev/examples/sm3.c
-
打开节点
int cfd = -1, i; /* Open the crypto device */ cfd = open("/dev/crypto", O_RDWR, 0); if (cfd < 0) { perror("open(/dev/crypto)"); return 1; } /* Set close-on-exec (not really needed here) */ if (fcntl(cfd, F_SETFD, 1) == -1) { perror("fcntl(F_SETFD)"); return 1; } -
创建session
int sha_ctx_init(struct cryptodev_ctx* ctx, int cfd, const uint8_t* key, unsigned int key_size) { #ifdef CIOCGSESSINFO struct session_info_op siop; #endif memset(ctx, 0, sizeof(*ctx)); ctx->cfd = cfd; if (key == NULL) ctx->sess.mac = CRYPTO_SHA2_256; // use CRYPTO_SM3 for sm3 else { ctx->sess.mac = CRYPTO_SHA2_256_HMAC; ctx->sess.mackeylen = key_size; ctx->sess.mackey = (void*)key; } if (ioctl(ctx->cfd, CIOCGSESSION, &ctx->sess)) { perror("ioctl(CIOCGSESSION)"); return -1; } #ifdef CIOCGSESSINFO siop.ses = ctx->sess.ses; if (ioctl(ctx->cfd, CIOCGSESSINFO, &siop)) { perror("ioctl(CIOCGSESSINFO)"); return -1; } printf("Got %s with driver %s\n", siop.hash_info.cra_name, siop.hash_info.cra_driver_name); if (!(siop.flags & SIOP_FLAG_KERNEL_DRIVER_ONLY)) { printf("Note: This is not an accelerated cipher\n"); } /*printf("Alignmask is %x\n", (unsigned int)siop.alignmask);*/ ctx->alignmask = siop.alignmask; #endif return 0; } -
进行运算
结构体说明
struct crypt_op { __u32 ses; /* session identifier */ __u16 op; /* COP_ENCRYPT or COP_DECRYPT */ __u16 flags; /* see COP_FLAG_* */ __u32 len; /* length of source data */ __u8 __user *src; /* source data */ __u8 __user *dst; /* pointer to output data */ /* pointer to output data for hash/MAC operations */ __u8 __user *mac; /* initialization vector for encryption operations */ __u8 __user *iv; };加解密实例
int sha_hash(struct cryptodev_ctx* ctx, const void* text, size_t size, void* digest) { struct crypt_op cryp; void* p; /* check text and ciphertext alignment */ if (ctx->alignmask) { p = (void*)(((unsigned long)text + ctx->alignmask) & ~ctx->alignmask); if (text != p) { fprintf(stderr, "text is not aligned\n"); return -1; } } memset(&cryp, 0, sizeof(cryp)); /* Encrypt data.in to data.encrypted */ cryp.ses = ctx->sess.ses; cryp.len = size; cryp.src = (void*)text; cryp.mac = digest; if (ioctl(ctx->cfd, CIOCCRYPT, &cryp)) { perror("ioctl(CIOCCRYPT)"); return -1; } return 0; } -
关闭session
void sha_ctx_deinit(struct cryptodev_ctx* ctx) { if (ioctl(ctx->cfd, CIOCFSESSION, &ctx->sess.ses)) { perror("ioctl(CIOCFSESSION)"); } } -
关闭节点
/* Close the original descriptor */ if (close(cfd)) { perror("close(cfd)"); return 1; }注意目前硬件加速只支持sha256/sm3算法,如果使用其他算法(如sha1,md5)会调用软件算法。
5.2.3 rsa加解密接口¶
RSA加解密接口支持RSA512/1024/2048/4096(由于RSA512/1024的安全性较低,建议使用RSA2048/4096)。
demo路径:drivers/sgs_common/cryptodev/examples/cipher/cipher_rsa_sync.c
-
打开节点
int fd = -1; /* Open the crypto device */ fd = open("/dev/rsa", O_RDWR, 0); if (fd < 0) { perror("open(/dev/rsa)"); return 1; } -
进行运算
结构体说明
struct rsa_config { unsigned int *pu32RSA_Sig; //the address of source data unsigned int *pu32RSA_KeyN; //the address of KeyN unsigned int *pu32RSA_KeyE; //the address of KeyE unsigned int *pu32RSA_Output; //the address of destination data unsigned int u32RSA_KeyNLen; //64->512,128->1024,256->2048,512->4096 unsigned int u32RSA_KeyELen; //64->512,128->1024,256->2048,512->4096 unsigned int u32RSA_SigLen; //64->512,128->1024,256->2048,512->4096 unsigned char u8RSA_pub_ekey; //0:pvivate key,1:public key };加解密实例
static int test_rsa(int fd, struct rsa_config *prsa_config) { int i = 0; #if 1 // RSA calculate if (ioctl(fd, MDrv_RSA_Calculate, prsa_config)) { perror("ioctl(MDrv_RSA_Calculate)"); return 1; } #endif return 0; } -
关闭节点
/* Close the original descriptor */ if (close(fd)) { perror("close(fd)"); return 1; }其中,RSA对输入数据(pu32RSA_Sig)、KeyN(pu32RSA_KeyN)、KeyE(pu32RSA_KeyE)的大小要求如下:
RSA input size KeyN size KeyE size 512 64 bytes 64 bytes 64 bytes 1024 128 bytes 128 bytes 128 bytes 2048 256 bytes 256 bytes 256 bytes 4096 512 bytes 512 bytes 512 bytes
5.2.4 sm2/ECC加解密接口¶
SM2/ECC加解密的demo路径:drivers/sgs_common/cryptodev/examples/cipher/cipher_sm2_sync.c
-
打开节点
int fd = -1; /* Open the crypto device */ fd = open("/dev/sm2", O_RDWR, 0); if (fd < 0) { perror("open(/dev/sm2)"); return 1; } -
进行运算
结构体说明
typedef struct drv_sm2_config_s { unsigned char * pu8PrivKey; // private key unsigned char * pu8PubKeyX; // public key in X coordinate unsigned char * pu8PubKeyY; // public key in Y coordinate unsigned int u32KeyLen; // key length (unit: byte) unsigned char u8Mode; // decryption flag (set 1 for decryption, 0 for encryption) unsigned char * pu8Input; // input data unsigned int u32InputLen; // input data length (unit: byte) unsigned char * pu8Output; // output data unsigned char * pu8Sign; // Signature data drv_sm2_curve_e ecurve; //Curve parameters } drv_sm2_config_t;加解密实例
int UtSm2Encrypt(int s32Fd, void *pInput, void *pOutput, unsigned int u32Len) { drv_sm2_config_t stCfg; stCfg.u8Mode = 0; stCfg.ecurve = E_DRV_SM2_CURVE_DEFAULT; stCfg.pu8PubKeyX = g_u8PubKeyX; stCfg.pu8PubKeyY = g_u8PubKeyY; stCfg.u32KeyLen = UT_SM2_PRECISION * 4; stCfg.pu8Input = pInput; stCfg.u32InputLen = u32Len; stCfg.pu8Output = pOutput; if (ioctl(s32Fd, SM2_IOCTL_CRYPT, &stCfg)) { fprintf(stderr, "ioctl(SM2_IOCTL_CRYPT) failed\n"); return -1; } return 0; } -
关闭节点
/* Close the original descriptor */ if (close(fd)) { perror("close(fd)"); return 1; }其中,SM2加解密要求密钥长度为32 byte,支持的输入数据长度最大为 1MB。
5.3. kernel space使用Crypto模块提供的API接口¶
| API名称 | 功能 |
|---|---|
| drv_skcipher_run | aes/sm4加解密接口 |
| drv_hash_run | hash计算接口 |
| drv_akcipher_run | rsa/sm2加解密接口 |
| drv_rng_read | rng值读取接口 |
| run_decrypt | 数据解密接口 |
| run_authenticate2 | 数据验签接口 |
| run_authenticate | 数据验签接口 |
5.3.1. drv_skcipher_run¶
-
目的
对数据进行aes/sm4加密或者解密
-
语法
u32 drv_skcipher_run(drv_skcipher_config *config)
-
参数
参数名称 描述 config aes加解密过程使用的配置信息,包括数据地址信息,加解密信息等 typedef struct { drv_skcipher_key_sel key_sel; // select key u8 swkey[DRV_SKCIPHER_KEY_LEN_256]; // software key,max 256 drv_skcipher_key_len key_len; // skcipher key len drv_skcipher_alg_type alg_type; // skcipher algtype drv_skcipher_op_mode op_mode; // skcipher alg mode drv_skcipher_op_dir op_dir; // decrypt or encrypt drv_skcipher_mround_num mround_num; // aesdma multiround num u64 src_phys; // src phys addr u64 dst_phys; // dst phys addr u8 * src_virt; // src virt addr u8 * dst_virt; // dst virt addr u32 len; // plaintext len u8 * iv; // (CBC/CTR need)iv value u8 async; // 0:sync,1:async } __attribute__((aligned(16))) drv_skcipher_config; -
返回值
返回值 描述 config->len 加密或解密后数据的长度 0 加解密失败 1 参数错误 -
注意
-
使用该接口可参考drivers/sgs_common/crypto/ut/lnx/ut_aes.c。
在测试aesdma之前,需要先执行以下内容来开启aesdma的时钟:
打开CONFIG_SGS_AESDMA_DEBUG echo aesdma_clk_state=1 > /sys/bus/platform/devices/soc:aesdma/debug echo rng_clk_state=1 > /sys/bus/platform/devices/soc:aesdma/debug -
skcipher 密钥类型:
key macro support SW KEY DRV_SKCIPHER_KEY_SEL_SW YES HW KEY 1 DRV_SKCIPHER_KEY_SEL_HW_1 YES HW KEY 2 DRV_SKCIPHER_KEY_SEL_HW_2 YES HW KEY 3 DRV_SKCIPHER_KEY_SEL_HW_3 YES HW KEY 4 DRV_SKCIPHER_KEY_SEL_HW_4 YES HW KEY 5 DRV_SKCIPHER_KEY_SEL_HW_5 YES HW KEY 6 DRV_SKCIPHER_KEY_SEL_HW_6 YES HW KEY 7 DRV_SKCIPHER_KEY_SEL_HW_7 YES HW KEY 8 DRV_SKCIPHER_KEY_SEL_HW_8 YES key sel key 0 SW KEY 1 key1:1st HW key for aes128;{key1+key2 for aes256} 2 key2:2nd HW key for aes128;{key2+key3 for aes256} 3 key3:3rd HW key for aes128;{key3+key4 for aes256} 4 key4:4th HW key for aes128;{key4+key5 for aes256} 5 key5:5th HW key for aes128;{key5+key6 for aes256} 6 key6:6th HW key for aes128;{key6+key7 for aes256} 7 key7:7th HW key for aes128;{key7+key8 for aes256} 8 key8:8th HW key for aes128;{key8+key1 for aes256} -
skcipher 算法类型:
alg type macro support AES DRV_SKCIPHER_ALG_TYPE_AES YES DES DRV_SKCIPHER_ALG_TYPE_DES YES TDES DRV_SKCIPHER_ALG_TYPE_TDES YES SM4 DRV_SKCIPHER_ALG_TYPE_SM4 YES -
skcipher 密钥长度:
key len macro support 64bit DRV_SKCIPHER_KEY_LEN_64 YES 128bit DRV_SKCIPHER_KEY_LEN_128 YES 192bit DRV_SKCIPHER_KEY_LEN_192 YES 256bit DRV_SKCIPHER_KEY_LEN_256 YES AES算法长度可以选择128bit,192bit,256bit
DES算法长度固定为64bit
TDES算法长度固定为192bit,且只能使用ABA模式,即最后密钥64bit要和前64bit一致。
SM4算法长度固定为128bit
-
skcipher 操作模式:
operate mode macro support ECB DRV_SKCIPHER_OP_MODE_ECB YES CBC DRV_SKCIPHER_OP_MODE_CBC YES CTR DRV_SKCIPHER_OP_MODE_CTR YES -
skcipher 加密or解密:
operate dir macro support COPY DRV_SKCIPHER_OP_DIR_COPY NO ENCRYPT DRV_SKCIPHER_OP_DIR_ENCRYPT YES DECRYPT DRV_SKCIPHER_OP_DIR_DECRYPT YES -
skcipher 重复计算次数:
operate dir macro support Multi Round 1 DRV_SKCIPHER_MROUND_NUM_1 YES Multi Round 2 DRV_SKCIPHER_MROUND_NUM_2 YES Multi Round 3 DRV_SKCIPHER_MROUND_NUM_3 YES Multi Round 4 DRV_SKCIPHER_MROUND_NUM_4 YES
-
5.3.2. drv_hash_run¶
-
目的
对数据进行哈希计算
-
语法
u32 drv_hash_run(drv_hash_config *config)
-
参数
参数名称 描述 config 数据进行hash计算的配置信息 typedef struct { drv_hash_alg_type alg_type; // hash alg type drv_hash_work_mode work_mode; // auto or manual mode drv_hash_state * ctx; // hash state u64 src_phys; // src phys addr u8 * src_virt; // src virt addr u8 * digest; // hash result addr u32 len; // plaintext len u8 async; // 0:sync,1:async } __attribute__((aligned(16))) drv_hash_config; -
返回值
返回值 描述 0 成功 1 失败 -
注意
-
使用该接口可参考drivers/sgs_common/crypto/ut/lnx/ut_aes.c。
在测试aesdma之前,需要先执行以下内容来开启aesdma的时钟:
打开CONFIG_SGS_AESDMA_DEBUG echo aesdma_clk_state=1 > /sys/bus/platform/devices/soc:aesdma/debug echo rng_clk_state=1 > /sys/bus/platform/devices/soc:aesdma/debug -
hash 算法类型:
alg type macro support SHA1 DRV_HASH_ALG_TYPE_SHA1 YES SHA256 DRV_HASH_ALG_TYPE_SHA256 YES SM3 DRV_HASH_ALG_TYPE_SM3 YES -
hash 计算模式:
mode macro support AUTO DRV_HASH_WORK_MODE_AUTO YES MANUAL DRV_HASH_WORK_MODE_MANUAL YES
-
5.3.3. drv_akcipher_run¶
-
目的
rsa/sm2加解密接口
-
语法
u32 drv_akcipher_run(drv_akcipher_config *config)
-
参数
参数名称 描述 config 数据进行rsa加解密的配置信息 typedef struct { drv_akcipher_key_sel key_sel; // select key drv_akcipher_alg_type alg_type; // akcipher alg type drv_akcipher_key_len key_n_len; // key_n_len or ecc precision u8 async; // 0:sync,1:async union { struct { DRV_AKCIPHER_KEY_TYPE key_type; // public key or private key u8 * key_n; // RSA N key addr u8 * dst_virt; // dst virt addr u8 * key_e; // RSA E key addr u32 key_e_len;// RSA E key len u8 * src_virt; // src virt addr u32 data_len; // plaintext len } rsa; struct { /* For the specific parameters of ECC, please refer to the formula below. */ drv_sm2_curve *curve; // ecc curve addr drv_sm2_point *point_out; // output poinit drv_sm2_point *point_g; // g point drv_sm2_point *point_p; // p point u32 * K; // K u32 * S; // S u32 * T; // T u32 * in_curve; // 0:not in curve,1:in curve } ecc; }; } __attribute__((aligned(16))) drv_akcipher_config; -
返回值
返回值 描述 0 成功 1 失败 -
注意
-
使用该接口可参考drivers/sgs_common/crypto/ut/lnx/ut_aes.c。
在测试aesdma之前,需要先执行以下内容来开启aesdma的时钟:
打开CONFIG_SGS_AESDMA_DEBUG echo aesdma_clk_state=1 > /sys/bus/platform/devices/soc:aesdma/debug echo rng_clk_state=1 > /sys/bus/platform/devices/soc:aesdma/debug -
akcipher 密钥类型(software key or hardware key):
key macro support SW KEY DRV_AKCIPHER_KEY_SEL_SW YES HW KEY DRV_AKCIPHER_KEY_SEL_HW NO -
akcipher 密钥类型(public key or private key):
key macro support PRIVATE KEY DRV_AKCIPHER_KEY_TYPE_PRI YES PUBLIC KEY DRV_AKCIPHER_KEY_TYPE_PUB YES -
akcipher 算法类型:
alg type macro support RSA DRV_AKCIPHER_ALG_TYPE_RSA YES ECC MULT DRV_AKCIPHER_ALG_TYPE_ECC_POINT_MULT YES ECC MULT AND ADD DRV_AKCIPHER_ALG_TYPE_ECC_POINT_MULT_AND_ADD YES ECC VERIFY DRV_AKCIPHER_ALG_TYPE_ECC_POINT_VERIFY YES -
akcipher N KEY长度:
N key len macro support 256byte DRV_AKCIPHER_KEY_LEN_RSA2048 YES 256byte DRV_AKCIPHER_KEY_LEN_RSA4096 YES 20byte DRV_AKCIPHER_KEY_LEN_ECC160 YES 24byte DRV_AKCIPHER_KEY_LEN_ECC192 YES 28byte DRV_AKCIPHER_KEY_LEN_ECC224 YES 32byte DRV_AKCIPHER_KEY_LEN_ECC255 YES 32byte DRV_AKCIPHER_KEY_LEN_ECC256 YES 40byte DRV_AKCIPHER_KEY_LEN_ECC320 YES 48byte DRV_AKCIPHER_KEY_LEN_ECC384 YES 64byte DRV_AKCIPHER_KEY_LEN_ECC512 YES 68byte DRV_AKCIPHER_KEY_LEN_ECC521 YES
-
5.3.4. drv_rng_read¶
-
目的
读取硬件随机数
-
语法
u16 drv_rng_read(void);
-
参数
参数名称 描述 无 -
返回值
返回值 描述 value 16位的硬件随机数 0 获取硬件随机数失败 -
注意·
-
使用该接口可参考drivers/sgs_common/crypto/ut/lnx/ut_aes.c。
在测试aesdma之前,需要先执行以下内容来开启aesdma的时钟:
打开CONFIG_SGS_AESDMA_DEBUG echo aesdma_clk_state=1 > /sys/bus/platform/devices/soc:aesdma/debug echo rng_clk_state=1 > /sys/bus/platform/devices/soc:aesdma/debug
-
5.3.5. run_decrypt¶
-
目的
对指定数据进行解密,结果保存在数据源地址中
-
语法
void run_decrypt(u64 u64ImageAddr, u32 u32ImageSize, u32 u32KeySel, u16 *pu16Key, u32 keylen)
-
参数
参数名称 描述 u64ImageAddr input data start address u32ImageSize input data size u32KeySel aes(ecb) key number pu16Key aes(ecb) sw key keylen key len -
返回值
返回值 描述 无 -
注意
-
使用该接口可参考drivers/sgs_common/crypto/os/rtk/drv_aesdma_test.c中的run_auth_test测试接口。
在测试aesdma之前,需要先执行以下内容来开启aesdma的时钟:
打开CONFIG_SGS_AESDMA_DEBUG echo aesdma_clk_state=1 > /sys/bus/platform/devices/soc:aesdma/debug echo rng_clk_state=1 > /sys/bus/platform/devices/soc:aesdma/debug -
在run_decrypt中,固定为 AES(ECB) 的解密模式,可以使用sw key和hw key
-
5.3.6. run_authenticate2¶
-
目的
数据验签接口
-
语法
u8 run_authenticate2(u64 u64ImageAddr, u32 u32ImageSize, u64 u32Key, u32 u32KeySize, u32 u32Sig, u32 u32SigSize)
-
参数
参数名称 描述 u64ImageAddr input data start address u32ImageSize input data size(no include signature data size) u32Key rsa2048 public n key u32KeySize n key size u32Sig sig data start addr u32SigSize sig data size -
返回值
返回值 描述 1 验签通过 0 验签失败 -
注意
固定使用rsa2048对数据进行验签,在run_authenticate2中,先计算输入数据的sha256结果,再对签章数据进行验签计算,然后比较验签计算结果和sha256计算结果是否一致来判断验签是否成功。
5.3.7. run_authenticate¶
-
目的
数据验签接口
-
语法
u8 run_authenticate(u64 u64ImageAddr, u32 u32ImageSize, u32 *pu32Key)
-
参数
参数名称 描述 u64ImageAddr input data start address u32ImageSize input data size(no include signature data size) pu32Key rsa2048 public n key -
返回值
返回值 描述 1 验签通过 0 验签失败 -
注意
-
run_authenticate是将run_authenticate2封装了一层,输入的数据应该为plaintext+signature的格式,并且输入的u32ImageSize应该不包含签章数据的size。
-
该接口使用可以参考drivers/sgs/crypto/ut/rtk/drv_aesdma_test.c中的run_auth_test测试接口
在测试aesdma之前,需要先执行以下内容来开启aesdma的时钟:
打开CONFIG_SGS_AESDMA_DEBUG echo aesdma_clk_state=1 > /sys/bus/platform/devices/soc:aesdma/debug echo rng_clk_state=1 > /sys/bus/platform/devices/soc:aesdma/debug
-
5.4 调试节点¶
节点地址:/sys/bus/platform/devices/soc:aesdma/debug
5.4.1 debug节点说明¶
| 名称 | 说明 |
|---|---|
| rng_init | 随机数初始化状态 |
| sca | 硬件防旁路攻击使能状态 |
| mcg | 硬件门控时钟使能状态 |
| pa | 增强power saving,注:该功能开启后,模块只保留最基础的供电,并失去计算能力 |
| wadr_irq | skcipher中断使能状态 |
| ps_irq | hash/akcipher中断使能状态 |
| aesdma_clk_state | aesdma时钟状态 |
| aesdma_clk_freq | aesdma时钟频率 |
| rng_clk_state | rng时钟状态 |
| rng_clk_freq | rng时钟频率 |
| log_level | 可以调整driver打印等级。EMERG:0,ERROR:1,INFO:2,DEBUG:3 |
5.4.2 使用示例¶
查看所有信息:
cat /sys/bus/platform/devices/soc:aesdma/debug
debug节点会汇总其他子节点的信息,读取该节点,打印信息如图:

开启/关闭随机数初始化:
echo rng_init=1 > /sys/bus/platform/devices/soc:aesdma/debug
echo rng_init=0 > /sys/bus/platform/devices/soc:aesdma/debug
开启/关闭mcg:
echo mcg=1 > /sys/bus/platform/devices/soc:aesdma/debug
echo mcg=0 > /sys/bus/platform/devices/soc:aesdma/debug
开启/关闭pa:
echo pa=1 > /sys/bus/platform/devices/soc:aesdma/debug
echo pa=0 > /sys/bus/platform/devices/soc:aesdma/debug
开启/关闭skcipher中断:
echo wadr_irq=1 > /sys/bus/platform/devices/soc:aesdma/debug
echo wadr_irq=0 > /sys/bus/platform/devices/soc:aesdma/debug
开启/关闭hash/akcipher中断:
echo ps_irq=1 > /sys/bus/platform/devices/soc:aesdma/debug
echo ps_irq=0 > /sys/bus/platform/devices/soc:aesdma/debug
开启/关闭aesdma时钟:
echo aesdma_clk_state=1 > /sys/bus/platform/devices/soc:aesdma/debug
echo aesdma_clk_state=0 > /sys/bus/platform/devices/soc:aesdma/debug
调整aesdma时钟频率:
可选值(172000000,216000000)
echo aesdma_clk_freq=216000000 > /sys/bus/platform/devices/soc:aesdma/debug
开启/关闭rng时钟:
echo rng_clk_state=1 > /sys/bus/platform/devices/soc:aesdma/debug
echo rng_clk_state=0 > /sys/bus/platform/devices/soc:aesdma/debug
调整rng时钟频率:
可选值(12000000,288000000)
echo rng_clk_freq=288000000 > /sys/bus/platform/devices/soc:aesdma/debug
调整打印等级:
DRV_AESDMA_LOG_LEVEL_EMERG = 0,
DRV_AESDMA_LOG_LEVEL_ERROR = 1,
DRV_AESDMA_LOG_LEVEL_INFO = 2,
DRV_AESDMA_LOG_LEVEL_DEBUG = 3
可选值(0,1,2,3)
e.g. 开启全部log
echo log_level=3 > /sys/bus/platform/devices/soc:aesdma/debug
注:敏感信息默认不会打印(如SKCIPHER,AKCIPHER的密钥),需要提前将drivers/sgs/crypto/drv/drv_aesdma_internal.h中的宏SECRET_MSG_PRINT置为1。
5.5 sysfs调试信息¶
使用该功能需要提前开启kernel下配置:
- CONFIG_HWIP_DEBUG=y
aesdma是一个比较典型的唯一系统资源,在sysfs下使用了一个漂亮的列表展示了aesdma的调试信息,该调试节点有如下特性:
- 所有调试信息一次性输出
- 可以通过写节点的方式控制输出的信息
示例:
echo 'help' > /sys/class/sgs/aesdma/debug # show this help
echo '[-]state' > /sys/class/sgs/aesdma/debug # disable|enable show all aesdma state
echo '[-]statistic' > /sys/class/sgs/aesdma/debug # disable|enable show all aesdma statistic
echo '[-]reg' > /sys/class/sgs/aesdma/debug # disable|enable show all aesdma raw register value
cat /sys/class/sgs/aesdma/debug # show aesdma state | statistic | raw register value
读取该节点,打印信息如图:
-
驱动状态

-
统计数据

-
寄存器信息
