diff --git a/arch/x86/configs/openeuler_defconfig b/arch/x86/configs/openeuler_defconfig index 59baeb2973afbf98959585910ee3a476544e15a0..c9038f20123620bde31c3a33fe13b424e980687f 100644 --- a/arch/x86/configs/openeuler_defconfig +++ b/arch/x86/configs/openeuler_defconfig @@ -7020,6 +7020,7 @@ CONFIG_CRYPTO_CRYPTD=y CONFIG_CRYPTO_AUTHENC=m CONFIG_CRYPTO_TEST=m CONFIG_CRYPTO_SIMD=y +CONFIG_CRYPTO_ZHAOXIN_GMI_SM2=m CONFIG_CRYPTO_GLUE_HELPER_X86=y # diff --git a/arch/x86/crypto/Makefile b/arch/x86/crypto/Makefile index 9edfa5469f9f7538f0eba2ab538b37bca86b90c2..b31fe0670e6b2bf3baf9486305bb2ae023c8687c 100644 --- a/arch/x86/crypto/Makefile +++ b/arch/x86/crypto/Makefile @@ -46,6 +46,8 @@ obj-$(CONFIG_CRYPTO_MORUS1280_GLUE) += morus1280_glue.o obj-$(CONFIG_CRYPTO_MORUS640_SSE2) += morus640-sse2.o obj-$(CONFIG_CRYPTO_MORUS1280_SSE2) += morus1280-sse2.o +obj-$(CONFIG_CRYPTO_ZHAOXIN_GMI_SM2) += zhaoxin-gmi-sm2.o + # These modules require assembler to support AVX. ifeq ($(avx_supported),yes) obj-$(CONFIG_CRYPTO_CAMELLIA_AESNI_AVX_X86_64) += \ @@ -84,6 +86,8 @@ aegis256-aesni-y := aegis256-aesni-asm.o aegis256-aesni-glue.o morus640-sse2-y := morus640-sse2-asm.o morus640-sse2-glue.o morus1280-sse2-y := morus1280-sse2-asm.o morus1280-sse2-glue.o +zhaoxin-gmi-sm2-y := zhaoxin-gmi-sm2_asm.o zhaoxin-gmi-sm2_glue.o + ifeq ($(avx_supported),yes) camellia-aesni-avx-x86_64-y := camellia-aesni-avx-asm_64.o \ camellia_aesni_avx_glue.o diff --git a/arch/x86/crypto/zhaoxin-gmi-sm2_asm.S b/arch/x86/crypto/zhaoxin-gmi-sm2_asm.S new file mode 100644 index 0000000000000000000000000000000000000000..a8a7ea448bd36b825243c247b7a8cfc707c73abf --- /dev/null +++ b/arch/x86/crypto/zhaoxin-gmi-sm2_asm.S @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: GPL-2.0 +/* + * Zhaoxin GMI implementation of a SM2 function + * + * + * Copyright(c) 2023 Zhaoxin Semiconductor LTD. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Contact Information: + * YunShen + */ +#include + +#define KEY_PTR %rdi /* 1st arg */ +#define HASH_PTR %rsi /* 2nd arg */ +#define SIG_PTR %rdx /* 3rd arg */ +#define SCRATCH_PTR %rcx /* 4rd arg */ +#define VER_RESULT %rax /* ret */ + + +.text +.align 32 +############################################################################### +# int zx_gmi_sm2_verify( +# unsigned char *key, /*key*/ +# unsigned char *hash, /*hash*/ +# unsigned char *sig, /*signature*/ +# unsigned char *scratch /*8 kbytes scratch space*/ +# ); +############################################################################### +ENTRY(zx_gmi_sm2_verify) + + #push %r13 + push %r12 + push %rbx + + mov HASH_PTR, %rax + mov KEY_PTR, %rbx + mov SIG_PTR, %r12 + mov $8, %rdx + mov SCRATCH_PTR, %rsi + mov %r12, %rdi + + .byte 0XF2 + .byte 0X0F + .byte 0XA6 + .byte 0XC0 + + mov %rcx, %rax + + pop %rbx + pop %r12 + #pop %r13 + + RET + +ENDPROC(zx_gmi_sm2_verify) diff --git a/arch/x86/crypto/zhaoxin-gmi-sm2_glue.c b/arch/x86/crypto/zhaoxin-gmi-sm2_glue.c new file mode 100644 index 0000000000000000000000000000000000000000..972f82a924f01b8a1df8f55c3b963705bd162ecd --- /dev/null +++ b/arch/x86/crypto/zhaoxin-gmi-sm2_glue.c @@ -0,0 +1,152 @@ +// 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 + */ + +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_VERSION "1.0.0" + +#define SCRATCH_SIZE (4 * 2048) + +asmlinkage int zx_gmi_sm2_verify(unsigned char *key, unsigned char *hash, unsigned char *sig, + unsigned char *scratch); + +struct sm4_cipher_data { + u8 pub_key[65]; /* public key */ +}; + +/* Load supported features of the CPU to see if the SM2 is available. */ +static int zx_gmi_available(void) +{ + struct cpuinfo_x86 *c = &cpu_data(0); + + if (((c->x86 == 6) && (c->x86_model >= 0x0f)) || (c->x86 > 6)) { + if (!boot_cpu_has(X86_FEATURE_SM2) || !boot_cpu_has(X86_FEATURE_SM2_EN)) { + pr_err("can't enable hardware SM2 if ZX-GMI-SM2 is not enabled\n"); + return -ENODEV; + } + pr_info("This cpu support ZX-GMI-SM2\n"); + return 0; + } + return -ENODEV; +} +static int zx_sm2_ec_ctx_init(void) +{ + return zx_gmi_available(); +} + +/* Zhaoxin sm2 verify function */ +static int _zx_sm2_verify(struct sm4_cipher_data *ec, unsigned char *hash, unsigned char *sig) +{ + int ret = -EINVAL; + uint64_t f_ok = 0; + unsigned char *scratch = kmalloc(SCRATCH_SIZE, GFP_KERNEL); + + memset(scratch, 0, SCRATCH_SIZE); + f_ok = zx_gmi_sm2_verify(ec->pub_key, hash, sig, scratch); + if (f_ok == 1) + ret = 0; + else + ret = -EKEYREJECTED; + + kfree(scratch); + return ret; +} + +static void zx_sm2_ec_ctx_deinit(struct sm4_cipher_data *ec) +{ + memset(ec, 0, sizeof(*ec)); +} + +static int zx_sm2_verify(struct akcipher_request *req) +{ + struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req); + struct sm4_cipher_data *ec = akcipher_tfm_ctx(tfm); + unsigned char *buffer; + int ret; + + buffer = kmalloc(req->src_len + req->dst_len, GFP_KERNEL); + if (!buffer) + return -ENOMEM; + + sg_pcopy_to_buffer(req->src, + sg_nents_for_len(req->src, req->src_len + req->dst_len), + buffer, req->src_len + req->dst_len, 0); + + ret = _zx_sm2_verify(ec, buffer + req->src_len, buffer); + kfree(buffer); + return ret; +} + +static int zx_sm2_set_pub_key(struct crypto_akcipher *tfm, const void *key, unsigned int keylen) +{ + int rc = 0; + struct sm4_cipher_data *ec = akcipher_tfm_ctx(tfm); + + memcpy(ec->pub_key, key, keylen); + return rc; +} + +static unsigned int zx_sm2_max_size(struct crypto_akcipher *tfm) +{ + /* Unlimited max size */ + return PAGE_SIZE; +} + +static int zx_sm2_init_tfm(struct crypto_akcipher *tfm) +{ + return zx_sm2_ec_ctx_init(); +} + +static void zx_sm2_exit_tfm(struct crypto_akcipher *tfm) +{ + struct sm4_cipher_data *ec = akcipher_tfm_ctx(tfm); + + zx_sm2_ec_ctx_deinit(ec); +} + +static struct akcipher_alg zx_sm2 = { + .verify = zx_sm2_verify, + .set_pub_key = zx_sm2_set_pub_key, + .max_size = zx_sm2_max_size, + .init = zx_sm2_init_tfm, + .exit = zx_sm2_exit_tfm, + .base = { + .cra_name = "sm2", + .cra_driver_name = "zhaoxin-gmi-sm2", + .cra_priority = 150, + .cra_module = THIS_MODULE, + .cra_ctxsize = sizeof(struct sm4_cipher_data), + }, +}; + +static int __init zx_sm2_init(void) +{ + return crypto_register_akcipher(&zx_sm2); +} + +static void __exit zx_sm2_exit(void) +{ + crypto_unregister_akcipher(&zx_sm2); +} + +module_init(zx_sm2_init); +module_exit(zx_sm2_exit); + +MODULE_LICENSE("GPL"); +MODULE_VERSION(DRIVER_VERSION); +MODULE_AUTHOR("YunShen "); +MODULE_DESCRIPTION("Zhaoxin GMI SM2 Algorithm"); +MODULE_ALIAS_CRYPTO("zx-gmi-sm2"); diff --git a/crypto/Kconfig b/crypto/Kconfig index 0ec4767a8856b2931f80dea87c178b4cf6a0858f..e7f38a54af63843309915db4314694d356a638e6 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -136,6 +136,13 @@ config CRYPTO_ECDH help Generic implementation of the ECDH algorithm +config CRYPTO_ZHAOXIN_GMI_SM2 + tristate "SM2 algorithm (Zhaoxin GMI instruction)" + select CRYPTO_AKCIPHER + select CRYPTO_MANAGER + help + SM2 (ShangMi 2) public key algorithm by Zhaoxin GMI Instruction. + config CRYPTO_MANAGER tristate "Cryptographic algorithm manager" select CRYPTO_MANAGER2