Message ID | 20231122064355.638946-1-LeoLiu-oc@zhaoxin.com |
---|---|
State | Superseded |
Headers | show |
Series | [v3] crypto: x86/sm2 -add Zhaoxin SM2 algorithm implementation | expand |
> +/* Zhaoxin sm2 verify function */ > +static inline size_t zhaoxin_gmi_sm2_verify(unsigned char *key, unsigned char *hash, > + unsigned char *sig, unsigned char *scratch) > +{ > + size_t result; > + > + asm volatile( > + ".byte 0xf2, 0x0f, 0xa6, 0xc0" > + :"=c"(result) > + :"a"(hash), "b"(key), "d"(SM2_CWORD_VERIFY), "S"(scratch), "D"(sig) > + :"memory"); > + > + return result; > +} What version of binutils supports this new instruction?
在 2023/11/22 22:26, Dave Hansen 写道: >> +/* Zhaoxin sm2 verify function */ >> +static inline size_t zhaoxin_gmi_sm2_verify(unsigned char *key, unsigned char *hash, >> + unsigned char *sig, unsigned char *scratch) >> +{ >> + size_t result; >> + >> + asm volatile( >> + ".byte 0xf2, 0x0f, 0xa6, 0xc0" >> + :"=c"(result) >> + :"a"(hash), "b"(key), "d"(SM2_CWORD_VERIFY), "S"(scratch), "D"(sig) >> + :"memory"); >> + >> + return result; >> +} > > What version of binutils supports this new instruction? > The instruction has not yet been submitted to binutils. It will only be used in the Zhaoxin-rng driver, and we are evaluating the necessity of submitting it to binutils. Yours sincerely, Leoliu-oc
在 2023/11/29 15:24, LeoLiu-oc 写道: > > > 在 2023/11/22 22:26, Dave Hansen 写道: >>> +/* Zhaoxin sm2 verify function */ >>> +static inline size_t zhaoxin_gmi_sm2_verify(unsigned char *key, >>> unsigned char *hash, >>> + unsigned char *sig, unsigned char *scratch) >>> +{ >>> + size_t result; >>> + >>> + asm volatile( >>> + ".byte 0xf2, 0x0f, 0xa6, 0xc0" >>> + :"=c"(result) >>> + :"a"(hash), "b"(key), "d"(SM2_CWORD_VERIFY), "S"(scratch), >>> "D"(sig) >>> + :"memory"); >>> + >>> + return result; >>> +} >> >> What version of binutils supports this new instruction? >> > > The instruction has not yet been submitted to binutils. It will only be > used in the Zhaoxin sm2 driver, and we are evaluating the necessity of > submitting it to binutils. > > Yours sincerely, > Leoliu-oc Sorry, Correct a clerical error. "Zhaoxin-rng" --> "Zhaoxin sm2". Yours sincerely, Leoliu-oc
On Wed, Nov 22, 2023 at 02:43:55PM +0800, LeoLiu-oc wrote: > From: LeoLiuoc <LeoLiu-oc@zhaoxin.com> > > Add support for SM2 (ShangMi 2) public key algorithm by Zhaoxin GMI > Instruction. The purpose of this driver is to ensure that the application > has both high performance and high security. > > --- > > v1 -> v2: > 1. The assembly code is modified to be embedded in the .c file. > 2. Optimize code style and details. > > v2 -> v3: > 1. Increase compatibility with i386 architecture. > 2. Optimize variable and return value types in some functions.. > > Signed-off-by: LeoLiuoc <LeoLiu-oc@zhaoxin.com> > --- > arch/x86/crypto/Kconfig | 11 ++ > arch/x86/crypto/Makefile | 2 + > arch/x86/crypto/sm2-zhaoxin-gmi_glue.c | 158 +++++++++++++++++++++++++ > arch/x86/include/asm/cpufeatures.h | 2 + > 4 files changed, 173 insertions(+) > create mode 100644 arch/x86/crypto/sm2-zhaoxin-gmi_glue.c > > diff --git a/arch/x86/crypto/Kconfig b/arch/x86/crypto/Kconfig > index 9bbfd01cfa2f..974d4c3806ff 100644 > --- a/arch/x86/crypto/Kconfig > +++ b/arch/x86/crypto/Kconfig > @@ -519,4 +519,15 @@ config CRYPTO_CRCT10DIF_PCLMUL > Architecture: x86_64 using: > - PCLMULQDQ (carry-less multiplication) > > +config CRYPTO_SM2_ZHAOXIN_GMI > + tristate "SM2 Cipher algorithm (Zhaoxin GMI Instruction)" > + depends on X86 && (CPU_SUP_CENTAUR || CPU_SUP_ZHAOXIN) > + select CRYPTO_AKCIPHER > + select CRYPTO_MANAGER Why does this depend on CRYPTO_MANAGER? > +static int zhaoxin_sm2_verify(struct akcipher_request *req) > +{ > + struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req); > + struct sm2_cipher_data *ec = akcipher_tfm_ctx(tfm); > + unsigned char *buffer; > + int ret, buf_len; > + > + buf_len = req->src_len + req->dst_len; What if this overflows? I know you copied this from the generic sm2 code, but that's still broken and both should be fixed up. Thanks,
在 2023/12/1 17:27, Herbert Xu 写道: > On Wed, Nov 22, 2023 at 02:43:55PM +0800, LeoLiu-oc wrote: >> From: LeoLiuoc <LeoLiu-oc@zhaoxin.com> >> >> Add support for SM2 (ShangMi 2) public key algorithm by Zhaoxin GMI >> Instruction. The purpose of this driver is to ensure that the application >> has both high performance and high security. >> >> --- >> >> v1 -> v2: >> 1. The assembly code is modified to be embedded in the .c file. >> 2. Optimize code style and details. >> >> v2 -> v3: >> 1. Increase compatibility with i386 architecture. >> 2. Optimize variable and return value types in some functions.. >> >> Signed-off-by: LeoLiuoc <LeoLiu-oc@zhaoxin.com> >> --- >> arch/x86/crypto/Kconfig | 11 ++ >> arch/x86/crypto/Makefile | 2 + >> arch/x86/crypto/sm2-zhaoxin-gmi_glue.c | 158 +++++++++++++++++++++++++ >> arch/x86/include/asm/cpufeatures.h | 2 + >> 4 files changed, 173 insertions(+) >> create mode 100644 arch/x86/crypto/sm2-zhaoxin-gmi_glue.c >> >> diff --git a/arch/x86/crypto/Kconfig b/arch/x86/crypto/Kconfig >> index 9bbfd01cfa2f..974d4c3806ff 100644 >> --- a/arch/x86/crypto/Kconfig >> +++ b/arch/x86/crypto/Kconfig >> @@ -519,4 +519,15 @@ config CRYPTO_CRCT10DIF_PCLMUL >> Architecture: x86_64 using: >> - PCLMULQDQ (carry-less multiplication) >> >> +config CRYPTO_SM2_ZHAOXIN_GMI >> + tristate "SM2 Cipher algorithm (Zhaoxin GMI Instruction)" >> + depends on X86 && (CPU_SUP_CENTAUR || CPU_SUP_ZHAOXIN) >> + select CRYPTO_AKCIPHER >> + select CRYPTO_MANAGER > > Why does this depend on CRYPTO_MANAGER? > Yes, this is redundant and will be removed in the next version. >> +static int zhaoxin_sm2_verify(struct akcipher_request *req) >> +{ >> + struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req); >> + struct sm2_cipher_data *ec = akcipher_tfm_ctx(tfm); >> + unsigned char *buffer; >> + int ret, buf_len; >> + >> + buf_len = req->src_len + req->dst_len; > > What if this overflows? I know you copied this from the generic sm2 > code, but that's still broken and both should be fixed up. > > Thanks, Yes, you are right. Thank you for your advice. The variable types will be adjusted according to the actual needs of the code in the next version. Sincerely, LeoLiu-oc
diff --git a/arch/x86/crypto/Kconfig b/arch/x86/crypto/Kconfig index 9bbfd01cfa2f..974d4c3806ff 100644 --- a/arch/x86/crypto/Kconfig +++ b/arch/x86/crypto/Kconfig @@ -519,4 +519,15 @@ config CRYPTO_CRCT10DIF_PCLMUL Architecture: x86_64 using: - PCLMULQDQ (carry-less multiplication) +config CRYPTO_SM2_ZHAOXIN_GMI + tristate "SM2 Cipher algorithm (Zhaoxin GMI Instruction)" + depends on X86 && (CPU_SUP_CENTAUR || CPU_SUP_ZHAOXIN) + select CRYPTO_AKCIPHER + select CRYPTO_MANAGER + help + SM2 (ShangMi 2) public key algorithm by Zhaoxin GMI Instruction + + Published by State Encryption Management Bureau, China, + as specified by OSCCA GM/T 0003.1-2012 -- 0003.5-2012. + endmenu diff --git a/arch/x86/crypto/Makefile b/arch/x86/crypto/Makefile index 9aa46093c91b..be37a4a7fc3f 100644 --- a/arch/x86/crypto/Makefile +++ b/arch/x86/crypto/Makefile @@ -109,6 +109,8 @@ aria-aesni-avx2-x86_64-y := aria-aesni-avx2-asm_64.o aria_aesni_avx2_glue.o obj-$(CONFIG_CRYPTO_ARIA_GFNI_AVX512_X86_64) += aria-gfni-avx512-x86_64.o aria-gfni-avx512-x86_64-y := aria-gfni-avx512-asm_64.o aria_gfni_avx512_glue.o +obj-$(CONFIG_CRYPTO_SM2_ZHAOXIN_GMI) += sm2-zhaoxin-gmi_glue.o + quiet_cmd_perlasm = PERLASM $@ cmd_perlasm = $(PERL) $< > $@ $(obj)/%.S: $(src)/%.pl FORCE diff --git a/arch/x86/crypto/sm2-zhaoxin-gmi_glue.c b/arch/x86/crypto/sm2-zhaoxin-gmi_glue.c new file mode 100644 index 000000000000..264c7948a49b --- /dev/null +++ b/arch/x86/crypto/sm2-zhaoxin-gmi_glue.c @@ -0,0 +1,158 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * SM2 asymmetric public-key algorithm + * as specified by OSCCA GM/T 0003.1-2012 -- 0003.5-2012 SM2 and + * described at https://tools.ietf.org/html/draft-shen-sm2-ecdsa-02 + * + * Copyright (c) 2023 Shanghai Zhaoxin Semiconductor LTD. + * Authors: YunShen <yunshen@zhaoxin.com> + */ + +#include <linux/module.h> +#include <linux/mpi.h> +#include <crypto/internal/akcipher.h> +#include <crypto/akcipher.h> +#include <crypto/sm2.h> +#include <asm/cpufeature.h> +#include <asm/processor.h> +#include <asm/cpu_device_id.h> + +#define SCRATCH_SIZE (4 * 2048) + +#define SM2_CWORD_VERIFY 0x8 +#define SM2_VERIFY_PASS 1 + +struct sm2_cipher_data { + u8 pub_key[65]; /* public key */ +}; + +/* Load supported features of the CPU to see if the SM2 is available. */ +static int zhaoxin_gmi_available(void) +{ + if (!boot_cpu_has(X86_FEATURE_SM2_EN)) { + pr_err("can't enable hardware SM2 if Zhaoxin GMI SM2 is not enabled\n"); + return -ENODEV; + } + return 0; +} + +/* Zhaoxin sm2 verify function */ +static inline size_t zhaoxin_gmi_sm2_verify(unsigned char *key, unsigned char *hash, + unsigned char *sig, unsigned char *scratch) +{ + size_t result; + + asm volatile( + ".byte 0xf2, 0x0f, 0xa6, 0xc0" + :"=c"(result) + :"a"(hash), "b"(key), "d"(SM2_CWORD_VERIFY), "S"(scratch), "D"(sig) + :"memory"); + + return result; +} + +/* Zhaoxin sm2 verify function */ +static int _zhaoxin_sm2_verify(struct sm2_cipher_data *ec, unsigned char *hash, unsigned char *sig) +{ + unsigned char *scratch = kzalloc(SCRATCH_SIZE, GFP_KERNEL); + int ret = -EKEYREJECTED; + size_t result; + + result = zhaoxin_gmi_sm2_verify(ec->pub_key, hash, sig, scratch); + if (result == SM2_VERIFY_PASS) + ret = 0; + + kfree(scratch); + + return ret; +} + +static int zhaoxin_sm2_verify(struct akcipher_request *req) +{ + struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req); + struct sm2_cipher_data *ec = akcipher_tfm_ctx(tfm); + unsigned char *buffer; + int ret, buf_len; + + buf_len = req->src_len + req->dst_len; + buffer = kmalloc(buf_len, GFP_KERNEL); + if (!buffer) + return -ENOMEM; + + sg_pcopy_to_buffer(req->src, sg_nents_for_len(req->src, buf_len), buffer, buf_len, 0); + ret = _zhaoxin_sm2_verify(ec, buffer + req->src_len, buffer); + + kfree(buffer); + + return ret; +} + +static int zhaoxin_sm2_set_pub_key(struct crypto_akcipher *tfm, const void *key, + unsigned int keylen) +{ + struct sm2_cipher_data *ec = akcipher_tfm_ctx(tfm); + + memcpy(ec->pub_key, key, keylen); + + return 0; +} + +static unsigned int zhaoxin_sm2_max_size(struct crypto_akcipher *tfm) +{ + /* Unlimited max size */ + return PAGE_SIZE; +} + +static int zhaoxin_sm2_init_tfm(struct crypto_akcipher *tfm) +{ + return zhaoxin_gmi_available(); +} + +static void zhaoxin_sm2_exit_tfm(struct crypto_akcipher *tfm) +{ + struct sm2_cipher_data *ec = akcipher_tfm_ctx(tfm); + + memset(ec, 0, sizeof(*ec)); +} + +static struct akcipher_alg zhaoxin_sm2 = { + .verify = zhaoxin_sm2_verify, + .set_pub_key = zhaoxin_sm2_set_pub_key, + .max_size = zhaoxin_sm2_max_size, + .init = zhaoxin_sm2_init_tfm, + .exit = zhaoxin_sm2_exit_tfm, + .base = { + .cra_name = "sm2", + .cra_driver_name = "zhaoxin-gmi-sm2", + .cra_priority = 150, + .cra_module = THIS_MODULE, + .cra_ctxsize = sizeof(struct sm2_cipher_data), + }, +}; + +static const struct x86_cpu_id zhaoxin_sm2_cpu_ids[] = { + X86_MATCH_FEATURE(X86_FEATURE_SM2, NULL), + {} +}; +MODULE_DEVICE_TABLE(x86cpu, zhaoxin_sm2_cpu_ids); + +static int __init zhaoxin_sm2_init(void) +{ + if (!x86_match_cpu(zhaoxin_sm2_cpu_ids)) + return -ENODEV; + + return crypto_register_akcipher(&zhaoxin_sm2); +} + +static void __exit zhaoxin_sm2_exit(void) +{ + crypto_unregister_akcipher(&zhaoxin_sm2); +} + +module_init(zhaoxin_sm2_init); +module_exit(zhaoxin_sm2_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("YunShen <yunshen@zhaoxin.com>"); +MODULE_DESCRIPTION("SM2 Zhaoxin GMI Algorithm"); +MODULE_ALIAS_CRYPTO("zhaoxin-gmi-sm2"); diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h index 4af140cf5719..07a78ec83bed 100644 --- a/arch/x86/include/asm/cpufeatures.h +++ b/arch/x86/include/asm/cpufeatures.h @@ -146,6 +146,8 @@ #define X86_FEATURE_HYPERVISOR ( 4*32+31) /* Running on a hypervisor */ /* VIA/Cyrix/Centaur-defined CPU features, CPUID level 0xC0000001, word 5 */ +#define X86_FEATURE_SM2 (5*32 + 0) /* SM2 ZhaoXin GMI present */ +#define X86_FEATURE_SM2_EN (5*32 + 1) /* SM2 ZhaoXin GMI enabled */ #define X86_FEATURE_XSTORE ( 5*32+ 2) /* "rng" RNG present (xstore) */ #define X86_FEATURE_XSTORE_EN ( 5*32+ 3) /* "rng_en" RNG enabled */ #define X86_FEATURE_XCRYPT ( 5*32+ 6) /* "ace" on-CPU crypto (xcrypt) */