一种基于OpenSSL的国密算法硬件加速方法转让专利

申请号 : CN202210828864.7

文献号 : CN114915405B

文献日 :

基本信息:

PDF:

法律信息:

相似专利:

发明人 : 李帅张志成杨沙洲赵峰

申请人 : 麒麟软件有限公司

摘要 :

本发明涉及一种基于OpenSSL的国密算法硬件加速方法,获取CPU型号,判断是否为兆芯相关的CPU型号,判断其是否支持用于硬件加速的GMI指令,如果不支持GMI指令,正常调用OpenSSL的evp接口进行软加解密;如果支持GMI指令,初始化支持硬件加速加解密的相关参数,调用相关接口进行数据传输的硬件加速加解密;本方法可以使OpenSSL实现硬件加速加解密,处理速度提高明显。

权利要求 :

1.一种基于OpenSSL的国密算法硬件加速方法,其特征在于,包括如下步骤:步骤S1、初始化OpenSSL,输入加解密类型;

步骤S2、获取CPU型号,判断是否为兆芯相关的CPU型号;

步骤S3、如果不属于兆芯相关的CPU型号,执行步骤S5;

步骤S4、如果属于兆芯相关的CPU型号,判断其是否支持用于硬件加速的GMI指令,如果不支持GMI指令,执行步骤S5;如果支持GMI指令,执行步骤S6;

步骤S5、正常调用OpenSSL的evp接口进行软加解密;

步骤S6、初始化支持硬件加速加解密的相关参数,调用相关接口进行数据传输的硬件加速加解密;

步骤S7、步骤S5或步骤S6执行后,释放空间;

步骤S6中,硬件加速加解密适用的算法为SM3算法和SM4算法,SM4算法包括五种模式,分别是ecb、cbc、cfb、ofb、ctr,针对上述五种模式对应执行ecb接口调用、cbc接口调用、cfb接口调用、ofb接口调用、ctr接口调用;

步骤S1中,加解密类型是软加解密类型,软加解密类型为OpenSSL中的SM3,以及SM4的ecb、cbc、cfb、ofb、ctr五种模式加解密类型;

步骤S2中,通过调用汇编语言获取CPU型号,与兆芯相关的CPU型号包括ZX‑C、ZX‑D和ZX‑E。

说明书 :

一种基于OpenSSL的国密算法硬件加速方法

技术领域

[0001] 本专利申请属于硬件加解密技术领域,更具体地说,是涉及一种基于OpenSSL的国密算法硬件加速方法。

背景技术

[0002] 随着互联网、物联网的快速发展,网络和信息安全事件不断出现,因此信息安全越来越受到各个行业的广泛重视,而密码学算法是信息安全的核心技术和基础支撑,可以说是整个信息安全的灵魂所在。
[0003] 国密算法是指由国家密码管理局颁布的一系列密码学算法标准,包括SM1、SM2、SM3、SM4、SM7、SM9以及祖冲之密码算法(ZUC)等一系列的密码算法。其中,SM1、SM4、SM7以及ZUC属于对称加密算法,SM2、 SM9属于非对称密码算法,而SM3是密码杂凑算法,也即常见的哈希算法。
[0004] OpenSSL是一套应用广泛的、开源的支持传输层安全协议的密码学基础库和全功能软件包,也已经支持国密SM2、SM3、SM4等加密算法。
[0005] 硬件加速则需要兆芯硬件支持,由兆芯设计实现的GMI是一组硬件加速指令集,目前已经实现了两条CPU指令,分别用于加速国密算法SM3和SM4。
[0006] 目前的OpenSSL高版本虽然已经支持国密算法,但仅仅只能做到软加解密,计算速度慢,性能相对较低。无法做到硬件加速加解密。
[0007] 软加解密,完全由软件实现的方式,不需要其他的硬件设备进行的加解密,往往被称作软加解密。
[0008] 硬件加速加解密,是指在软加解密的基础上使用硬件设备的高性能等特点,把原本比较复杂的编码算法,进行硬件指令化,简化操作复杂度,提高计算速度和性能。

发明内容

[0009] 本发明需要解决的技术问题是提供一种基于OpenSSL的国密算法硬件加速方法,以使OpenSSL实现硬件加速加解密。
[0010] 为了解决上述问题,本发明所采用的技术方案是:
[0011] 一种基于OpenSSL的国密算法硬件加速方法,包括如下步骤:
[0012] 步骤S1、初始化OpenSSL,输入加解密类型;
[0013] 步骤S2、获取CPU型号,判断是否为兆芯相关的CPU型号;
[0014] 步骤S3、如果不属于兆芯相关的CPU型号,执行步骤S5;
[0015] 步骤S4、如果属于兆芯相关的CPU型号,判断其是否支持用于硬件加速的GMI指令,如果不支持GMI指令,执行步骤S5;如果支持GMI指令,执行步骤S6;
[0016] 步骤S5、正常调用OpenSSL的evp接口进行软加解密;
[0017] 步骤S6、初始化支持硬件加速加解密的相关参数,调用相关接口进行数据传输的硬件加速加解密;
[0018] 步骤S7、步骤S5或步骤S6执行后(硬件加速加解密或软加解密执行后),释放空间。
[0019] 本发明技术方案的进一步改进在于:步骤S1中,加解密类型是软加解密类型,即OpenSSL中的SM3,以及SM4的ecb、cbc、cfb、ofb、ctr五种模式加解密类型。
[0020] 本发明技术方案的进一步改进在于:步骤S2中,通过调用汇编语言获取CPU型号,与兆芯相关的CPU型号包括ZX‑C、ZX‑D和ZX‑E。
[0021] 本发明技术方案的进一步改进在于:步骤S6中,硬件加速加解密适用的算法为SM3算法和SM4算法。
[0022] 本发明技术方案的进一步改进在于:SM4算法包括五种模式,分别是ecb、cbc、cfb、ofb、ctr,针对上述五种模式对应执行ecb接口调用、cbc接口调用、cfb接口调用、ofb接口调用、ctr接口调用。
[0023] 由于采用了上述技术方案,本发明取得的有益效果是:在使用硬件加速后,处理速度明显可以提高很大的性能。

附图说明

[0024] 图1为本发明的流程示意图。

具体实施方式

[0025] 下面结合实施例对本发明做进一步详细说明。
[0026] 本发明公开了一种基于OpenSSL的国密算法硬件加速方法,参见图1,包括如下步骤:
[0027] 步骤一、首先经过开始,初始化OpenSSL,输入加解密类型;
[0028] 步骤二、获取CPU型号,判断是否为兆芯相关的CPU型号;
[0029] 步骤三、如果不属于兆芯相关的CPU型号,执行步骤五;
[0030] 步骤四、如果属于兆芯相关的CPU型号,判断其是否支持用于硬件加速的GMI指令,如果不支持GMI指令,执行步骤五;如果支持GMI指令,执行步骤六;
[0031] 步骤五、正常调用OpenSSL的evp接口进行软加解密;
[0032] 步骤六、初始化支持硬件加速加解密的相关参数,调用相关接口进行数据传输的硬件加速加解密;
[0033] 步骤七、步骤五或步骤六执行后(硬件加速加解密或软加解密执行后),释放空间,至此结束。
[0034] 步骤一中,加解密类型用来选择国密的指令代码,具体的,加解密类型是软加解密类型,即OpenSSL中的SM3,以及SM4的ecb、cbc、cfb、ofb、ctr五种模式加解密类型。
[0035] 步骤二中,通过调用汇编语言获取CPU型号,与兆芯相关的CPU型号包括ZX‑C、ZX‑D和ZX‑E。
[0036] 步骤六中,硬件加速加解密适用的算法为SM3算法和SM4算法。
[0037] SM4算法包括五种模式,分别是ecb、cbc、cfb、ofb、ctr,针对上述五种模式对应执行ecb接口调用、cbc接口调用、cfb接口调用、ofb接口调用、ctr接口调用。
[0038] 本发明在设计时,主要是使用OpenSSL的原生EVP接口,而由于硬件加速是由兆芯设计实现,只针对兆芯相关的CPU才可以使用,所以首先需要判断是否为可支持此功能的CPU型号,对于不支持硬件加速的则进行原有的加解密流程进行。
[0039] 总体思路是:
[0040] 1.通过对CPU型号的判断确认是否支持硬件加速, 若支持则进行硬件加速流程加解密,若不支持则进行原有的流程调用。
[0041] 2.使用OpenSSL的原生EVP接口,针对SM3和SM4算法,对其原生EVP接口进行改造,即增加支持硬件加速的相关参数初始化工作,以及调用硬件加速加解密的接口。在不影响原生EVP接口调用原有功能的情况下,智能地选择是使用软加解密还是硬件加速加解密。
[0042] 本发明已成功应用于麒麟V10系统中,已使用此版本的OpenSSL密码库。
[0043] 相关代码如下:
[0044] 1.判断是否支持硬件加速,相关接口调用:
[0045] int is_zx = 0;
[0046] int cpu_is_support_gmi()
[0047] {
[0048]         unsigned int eax = 0;
[0049]         unsigned int edx = 0;
[0050]         unsigned char family,model,stepping;
[0051]         int is_support_gmi = 0;
[0052]         // to check zx's FMS
[0053]         unsigned int leaf = 0x1;
[0054]         asm volatile("cpuid":"=a"(eax):"0"(leaf):"ebx","ecx");
[0055]         family = (eax & 0xf00) >> 8;  // bit 11‑08
[0056]         model = (eax & 0xf0) >> 4; // bit 7‑4
[0057]         stepping = eax & 0xf; // bit 3‑0
[0058]         //for zx‑d/zx‑e
[0059]         if((family == 7)&(model == 0xb))
[0060]         {
[0061]                 is_support_gmi = 1;
[0062]         }
[0063]         // for zx‑c
[0064]         else if(((family == 6)&(model==0xf)&(stepping>=0xe))||((family==6)&(model==9)&(stepping>=0)))
[0065]         {
[0066]                 is_support_gmi = 1;
[0067]         }
[0068]         //It doesn't support SM3/SM4 instructions
[0069]         else
[0070]         {
[0071]                 is_support_gmi = 0;
[0072]         }
[0073]         return is_support_gmi;
[0074] }
[0075] 此部分代码通过调用汇编语言获取CPU信息并记录在eax变量中,进而判断出CPU型号,在支持硬件加速的CPU型号判断中使用参数is_support_gmi记录,如支持硬件加速则赋值为1,否则赋值为0。
[0076] 2.对算法SM3,定义支持硬件加速的算法标记,通过判断是否支持硬件加速以及初始化后进行后续兆芯GMI指令加速,相关代码:
[0077] #define SM3_A_ZX 0x6f168073UL
[0078] #define SM3_B_ZX 0xb9b21449UL
[0079] #define SM3_C_ZX 0xd7422417UL
[0080] #define SM3_D_ZX 0x00068adaUL
[0081] #define SM3_E_ZX 0xbc306fa9UL
[0082] #define SM3_F_ZX 0xaa383116UL
[0083] #define SM3_G_ZX 0x4dee8de3UL
[0084] #define SM3_H_ZX 0x4e0efbb0UL
[0085] is_zx= cpu_is_support_gmi();
[0086] int sm3_init(SM3_CTX *c)
[0087] {
[0088]     memset(c, 0, sizeof(*c));
[0089]     if (is_zx)
[0090]     {
[0091]         c‑>A = SM3_A_ZX;
[0092]         c‑>B = SM3_B_ZX;
[0093]         c‑>C = SM3_C_ZX;
[0094]         c‑>D = SM3_D_ZX;
[0095]         c‑>E = SM3_E_ZX;
[0096]         c‑>F = SM3_F_ZX;
[0097]         c‑>G = SM3_G_ZX;
[0098]         c‑>H = SM3_H_ZX;
[0099]     }
[0100]     else
[0101]     {
[0102]         c‑>A = SM3_A;
[0103]         c‑>B = SM3_B;
[0104]         c‑>C = SM3_C;
[0105]         c‑>D = SM3_D;
[0106]         c‑>E = SM3_E;
[0107]         c‑>F = SM3_F;
[0108]         c‑>G = SM3_G;
[0109]         c‑>H = SM3_H;
[0110]     }
[0111]     return 1;
[0112] }
[0113] void sm3_block_data_order(SM3_CTX *ctx, const void *p, size_t num)[0114] {
[0115]     if (is_zx)//支持硬件加速发送硬件指令
[0116]     {
[0117]             uint64_t in, out;
[0118]             in = (uint64_t)p;
[0119]             out = (uint64_t)(&(ctx‑>A));
[0120]            //利用汇编向CPU发送GMI指令,进行硬件加速
[0121]             __asm__ __volatile__(
[0122]                 "movq %2, %%rdi \n"
[0123]                 "movq %0, %%rsi \n"
[0124]                 "movq %1, %%rcx \n"
[0125]                 "movq $‑1, %%rax \n"
[0126]                 "movq $0x20, %%rbx \n"
[0127]                 ".byte 0xf3,0x0f,0xa6,0xe8"
[0128]                 :
[0129]                 :"r"(in),"r"(num),"r"(out)
[0130]                 :"%rax","memory"
[0131]         );
[0132]     }
[0133]     else {
[0134]            ……//此处为原有不支持硬件加速的软件算法流程
[0135] }
[0136] }
[0137] 此部分代码对SM3算法进行初始化通过is_zx获取是否支持硬件加速,对于支持硬件加速的使用新定义的SM3_A_ZX等值进行初始化,不支持硬件加速的话按原有定义初始化,最后点用函数sm3_block_data_order进行最终的算法计算。
[0138] 3.对于SM4算法同样需要判断是否支持硬件加速,SM4算法包含了五种不同模式,分别是ecb、cbc、cfb、ofb、ctr,所以针对不同模式都需要判断是否支持硬件加速并且初始化相关支持硬件加速参数,最后调用兆芯GMI指令进行硬件加速加解密。相关调用:
[0139] SM4算法使用GMI指令加速函数
[0140] void gmi_sm4_encrypt_full(unsigned char *out, const unsigned char *in,const SM4_KEY *key, uint64_t len,union ctrl c_w, unsigned char *iv)[0141] {
[0142]     uint64_t InTemp, OutTemp, KeyTemp, cword, cnt;
[0143]     /* What the gmi needs is original key, not round key */
[0144]     key = orig_key;
[0145]     //参数赋值
[0146]     InTemp = (uint64_t)in;
[0147]     OutTemp = (uint64_t)out;
[0148]     KeyTemp = (uint64_t)key;
[0149]     cword = (uint64_t)c_w.pad[0];
[0150]     cnt = ((len ‑ 1)/16)+1;
[0151]     //利用汇编向CPU发送指令进行加速加解密
[0152]     __asm__ __volatile__(
[0153]        "movq %0, %%rdi \n"
[0154]        "movq %1, %%rsi \n"
[0155]        "movq %2, %%rbx \n"
[0156]        "movq %3, %%rdx \n"
[0157]        "movq %4, %%rcx \n"
[0158]        "movq %5, %%rax \n"
[0159]        ".byte 0xf3,0x0f,0xa7,0xf0 \n"
[0160]        :
[0161]        :"r"(OutTemp),"r"(InTemp), "r"(KeyTemp),"r"(iv), "r"(cnt),"r"(cword)
[0162]        :"%rcx","rdi","rsi","rbx","rdx","rax","memory"
[0163]     );
[0164]     return;
[0165] }
[0166] 此部门代码主要是利用汇编语言的方法向CPU发送GMI指令,进行硬件加速加解密方法。
[0167] 3.1 判断是否支持硬件加速:
[0168] static int gmi_available(void)
[0169] {
[0170]     unsigned int eax = 0;
[0171]     unsigned int edx = 0;
[0172]     unsigned char family, model;
[0173]     /* Diff ZXC with ZXD */
[0174]     unsigned int leaf = 0x1;
[0175]     get_cpu_fms(eax, leaf);
[0176]     family = (eax & 0xf00) >> 8;
[0177] model = (eax & 0xf0) >> 4;
[0178] //is ZX‑D or ZX_E
[0179]     if ((family == 7)&&(model == 0xb)) {
[0180]         f_zxc = 0;
[0181]         edx = padlock_capability();
[0182]         padlock_use_ccs = ((edx & (0x3 << 4)) == (0x3 << 4));
[0183] }
[0184] //is ZX‑C
[0185] else if (((family == 6)&&(model == 0xf)) ||
[0186]         ((family == 6)&&(model == 9))) {
[0187]         f_zxc = 1;
[0188]         edx = padlock_capability();
[0189]         padlock_use_ccs = ((edx & (0x3 << 4)) == (0x3 << 4));
[0190] }
[0191] //不支持硬件加速
[0192] else {
[0193]       padlock_use_ccs = 0;
[0194]     }
[0195]     return padlock_use_ccs;
[0196] }
[0197] 此部分代码通过调用汇编语言获取CPU信息并记录在eax变量中,进而判断出CPU型号,使用参数f_zxc判断是否为ZX‑C型号,如是此型号赋值为1,否则为0.在支持硬件加速的CPU型号判断中使用参数padlock_use_ccs记录,如支持硬件加速赋值为不为0的值,否则赋值为0。
[0198] 3.2 ecb接口调用:
[0199] static void sm4_ecb_encrypt(const unsigned char *in, unsigned char *out, const SM4_KEY *key, const int enc)
[0200] {
[0201]     if (padlock_use_ccs) //是否支持硬件加速
[0202]     {
[0203]         union ctrl ctrl_word = {0};
[0204]         ctrl_word.b.encdec = !enc;//加解密类型
[0205]         ctrl_word.b.func = CCS_ENCRYPT_FUNC_SM4;//使用的算法[0206]         ctrl_word.b.mode = 1<<(SM4_ECB_MODE‑1);//算法类型
[0207]         ctrl_word.b.digest = 0;
[0208]         gmi_sm4_encrypt_full(out, in, key, 16, ctrl_word, NULL);
[0209] }
[0210] //原有的加解密流程
[0211]     else {
[0212]     if (enc)
[0213]         SM4_encrypt(in, out, key);
[0214]     else
[0215]         SM4_decrypt(in, out, key);
[0216]     }
[0217] }
[0218] 此部分代码为SM4的ecb模式接口,通过padlock_use_ccs值判断后续流程,若支持硬件加速进行参数初始化,之后传输数据进行硬件加速,否则使用原来软件加解密流程。
[0219] 3.3 cfb接口调用:
[0220] static void sm4_cfb128_encrypt(const unsigned char *in, unsigned char *out, size_t length, const SM4_KEY *key, unsigned char *ivec, int *num, const int enc)
[0221] {
[0222]     if (padlock_use_ccs)//是否支持硬件加速
[0223]     {
[0224]            union ctrl ctrl_word = {0};
[0225]            ctrl_word.b.encdec = !enc; //加解密类型
[0226]            ctrl_word.b.func = CCS_ENCRYPT_FUNC_SM4; //使用的算法[0227]            ctrl_word.b.mode = 1<<(SM4_CFB_MODE‑1); //算法类型[0228]            ctrl_word.b.digest = 0;
[0229]           gmi_sm4_encrypt_full(out, in, key, length, ctrl_word, ivec);
[0230]     }
[0231]     else //原有的加解密流程
[0232]         CRYPTO_cfb128_encrypt(in, out, length, key, ivec, num, enc, (block128_f)SM4_encrypt);
[0233] }
[0234] 3.4 cbc接口调用:
[0235] static void sm4_cbc_encrypt(const unsigned char *in, unsigned char *out, size_t len, const SM4_KEY *key, unsigned char *ivec, const int enc)[0236] {
[0237]     if (padlock_use_ccs) //是否支持硬件加速
[0238]     {
[0239]         union ctrl ctrl_word = {0};
[0240]         ctrl_word.b.encdec = !enc; //加解密类型
[0241]         ctrl_word.b.func = CCS_ENCRYPT_FUNC_SM4; //使用的算法[0242]         ctrl_word.b.mode = 1<<(SM4_CBC_MODE‑1); //算法类型
[0243]         ctrl_word.b.digest = 0;
[0244]         gmi_sm4_encrypt_full(out, in, key, len, ctrl_word, ivec);
[0245] }
[0246] //原有的加解密流程
[0247]     else {
[0248]     if (enc)
[0249]         CRYPTO_cbc128_encrypt(in, out, len, key, ivec,
[0250]                               (block128_f)SM4_encrypt);
[0251]     else
[0252]         CRYPTO_cbc128_decrypt(in, out, len, key, ivec,
[0253]                               (block128_f)SM4_decrypt);
[0254]     }
[0255] }
[0256] 3.5 ofb接口调用:
[0257] static void sm4_ofb128_encrypt(const unsigned char *in, unsigned char *out, size_t length, const SM4_KEY *key, unsigned char *ivec, int *num)[0258] {
[0259]     if (padlock_use_ccs) //是否支持硬件加速
[0260]     {
[0261]            union ctrl ctrl_word = {0};
[0262]            ctrl_word.b.encdec = 0; //加解密类型
[0263]            ctrl_word.b.func = CCS_ENCRYPT_FUNC_SM4; //使用的算法[0264]            ctrl_word.b.mode = 1<<(SM4_OFB_MODE‑1); //算法类型[0265]            ctrl_word.b.digest = 0;
[0266]           gmi_sm4_encrypt_full(out, in, key, length, ctrl_word, ivec);
[0267] }
[0268] //原有的加解密流程
[0269]     else
[0270]         CRYPTO_ofb128_encrypt(in, out, length, key, ivec, num,(block128_f)SM4_encrypt);
[0271] }
[0272] 3.6 ctr接口调用:
[0273] static int sm4_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,[0274]                           const unsigned char *in, size_t len)[0275] {
[0276]     unsigned int num = EVP_CIPHER_CTX_num(ctx);
[0277]     EVP_SM4_KEY *dat = EVP_C_DATA(EVP_SM4_KEY, ctx);
[0278]     if (padlock_use_ccs) //是否支持硬件加速
[0279]     {
[0280]            union ctrl ctrl_word = {0};
[0281]            ctrl_word.b.encdec = 0; //加解密类型
[0282]            ctrl_word.b.func = CCS_ENCRYPT_FUNC_SM4; //使用的算法[0283]            ctrl_word.b.mode = 1<<(SM4_CTR_MODE‑1); //算法类型[0284]            ctrl_word.b.digest = 0;
[0285]            gmi_sm4_encrypt_full(out, in, &dat‑>ks, len, ctrl_word, EVP_CIPHER_CTX_iv_noconst(ctx));
[0286] }
[0287] //原有的加解密流程
[0288]     else {
[0289]     CRYPTO_ctr128_encrypt(in, out, len, &dat‑>ks,
[0290]                           EVP_CIPHER_CTX_iv_noconst(ctx),
[0291]                           EVP_CIPHER_CTX_buf_noconst(ctx), &num,[0292]                           (block128_f)SM4_encrypt);
[0293]     }
[0294]     EVP_CIPHER_CTX_set_num(ctx, num);
[0295]     return 1;
[0296] }
[0297] 使用本发明的方法后,处理速度有了很大的提升,如表1‑表4的比对,分别针对16 bytes、64 bytes、256 bytes、1024 bytes、8192 bytes、16384 bytes这六种情形,以SM3和SM4‑ecb这两种算法为例,进行了针对的测算对比,可以看出本发明在速度提升方面有很大的优势。
[0298] 表1为使用命令openssl speed ‑evp sm3得到的未使用硬件加速的SM3算法性能;
[0299]
[0300] 表2是使用命令openssl speed ‑evp sm4‑ecb得到的未使用硬件加速的;SM4‑ECB模式性能;
[0301]
[0302] 表3是使用命令openssl speed ‑evp sm3得到的使用硬件加速后的SM3算法性能;
[0303]
[0304] 表4是使用命令openssl speed ‑evp sm4‑ecb得到的使用硬件加速的SM4‑ECB模式性能;
[0305]
[0306] 通过表1‑表4的对比,以每秒处理1000个字节为例,可以看到数据处理量飙升很多,处理数据加密速度亦增加很多,看出本发明在速度提升方面有巨大的优势。