From a593f14a9864945f028050935cb294fc7f7b531c Mon Sep 17 00:00:00 2001 From: AlanSong-oc Date: Fri, 5 Sep 2025 17:31:52 +0800 Subject: [PATCH] Add support for Zhaoxin GMI RNG/SM2/3/4 instruction Signed-off-by: AlanSong-oc --- Add-Zhaoxin-GMI-rng-instruction-support.patch | 722 ++++++++++++++++++ Add-Zhaoxin-GMI-sm2-instruction-support.patch | 716 +++++++++++++++++ Add-Zhaoxin-GMI-sm3-instruction-support.patch | 438 +++++++++++ Add-Zhaoxin-GMI-sm4-instruction-support.patch | 640 ++++++++++++++++ openssl.spec | 9 +- 5 files changed, 2524 insertions(+), 1 deletion(-) create mode 100755 Add-Zhaoxin-GMI-rng-instruction-support.patch create mode 100755 Add-Zhaoxin-GMI-sm2-instruction-support.patch create mode 100755 Add-Zhaoxin-GMI-sm3-instruction-support.patch create mode 100755 Add-Zhaoxin-GMI-sm4-instruction-support.patch diff --git a/Add-Zhaoxin-GMI-rng-instruction-support.patch b/Add-Zhaoxin-GMI-rng-instruction-support.patch new file mode 100755 index 0000000..0adbb1a --- /dev/null +++ b/Add-Zhaoxin-GMI-rng-instruction-support.patch @@ -0,0 +1,722 @@ +From eca62572224caf08dd983fbae222e929cf59103d Mon Sep 17 00:00:00 2001 +From: yunshen +Date: Thu, 4 Sep 2025 19:35:50 +0800 +Subject: [PATCH 1/4] Add-Zhaoxin-GMI-rng-instruction support + +--- + Configurations/00-base-templates.conf | 3 + + Configurations/10-main.conf | 2 + + Configure | 4 + + INSTALL | 5 + + README.ENGINE | 1 + + crypto/init.c | 17 +++ + engines/asm/e_gmi-x86.pl | 128 ++++++++++++++++++++ + engines/asm/e_gmi-x86_64.pl | 119 +++++++++++++++++++ + engines/build.info | 15 +++ + engines/e_gmi.c | 213 ++++++++++++++++++++++++++++++++++ + include/crypto/engine.h | 1 + + include/openssl/crypto.h | 3 +- + include/openssl/engine.h | 2 + + 13 files changed, 512 insertions(+), 1 deletion(-) + create mode 100644 engines/asm/e_gmi-x86.pl + create mode 100644 engines/asm/e_gmi-x86_64.pl + create mode 100644 engines/e_gmi.c + +diff --git a/Configurations/00-base-templates.conf b/Configurations/00-base-templates.conf +index a26d081..8eb19c1 100644 +--- a/Configurations/00-base-templates.conf ++++ b/Configurations/00-base-templates.conf +@@ -34,6 +34,7 @@ my %targets=( + padlock_asm_src => "", + chacha_asm_src => "chacha_enc.c", + poly1305_asm_src => "", ++ gmi_asm_src => "", + keccak1600_asm_src => "keccak1600.c", + + unistd => "", +@@ -212,6 +213,7 @@ my %targets=( + padlock_asm_src => "e_padlock-x86.s", + chacha_asm_src => "chacha-x86.s", + poly1305_asm_src=> "poly1305-x86.s", ++ gmi_asm_src => "e_gmi-x86.s", + }, + x86_elf_asm => { + template => 1, +@@ -233,6 +235,7 @@ my %targets=( + padlock_asm_src => "e_padlock-x86_64.s", + chacha_asm_src => "chacha-x86_64.s", + poly1305_asm_src=> "poly1305-x86_64.s", ++ gmi_asm_src => "e_gmi-x86_64.s", + keccak1600_asm_src => "keccak1600-x86_64.s", + }, + ia64_asm => { +diff --git a/Configurations/10-main.conf b/Configurations/10-main.conf +index 8939a50..a18ed86 100644 +--- a/Configurations/10-main.conf ++++ b/Configurations/10-main.conf +@@ -1690,6 +1690,7 @@ my %targets = ( + "-DL_ENDIAN -DCPU=SIMLINUX -DNO_STRINGS_H", + "-DTOOL_FAMILY=gnu -DTOOL=gnu", + "-DOPENSSL_NO_HW_PADLOCK", ++ "-DOPENSSL_NO_HW_GMI", + "-I\$(WIND_BASE)/target/h", + "-I\$(WIND_BASE)/target/h/wrn/coreip"), + sys_id => "VXWORKS", +@@ -1705,6 +1706,7 @@ my %targets = ( + "-DCPU=MIPS32 -DNO_STRINGS_H", + "-DTOOL_FAMILY=gnu -DTOOL=gnu", + "-DOPENSSL_NO_HW_PADLOCK", ++ "-DOPENSSL_NO_HW_GMI", + threads("-D_REENTRANT"), + "-I\$(WIND_BASE)/target/h", + "-I\$(WIND_BASE)/target/h/wrn/coreip"), +diff --git a/Configure b/Configure +index b537919..d2b2ef6 100644 +--- a/Configure ++++ b/Configure +@@ -1427,6 +1427,9 @@ unless ($disabled{asm}) { + if ($target{sm3_asm_src} ne "") { + push @{$config{lib_defines}}, "SM3_ASM"; + } ++ if ($target{gmi_asm_src} ne $table{DEFAULTS}->{gmi_asm_src}) { ++ push @{$config{dso_defines}}, "GMI_ASM"; ++ } + } + + my %predefined_C = compiler_predefined($config{CROSS_COMPILE}.$config{CC}); +@@ -3384,6 +3387,7 @@ sub print_table_entry + "build_scheme", + "sm4_asm_src", + "sm3_asm_src", ++ "gmi_asm_src", + ); + + if ($type eq "TABLE") { +diff --git a/INSTALL b/INSTALL +index f3ac727..7580bff 100644 +--- a/INSTALL ++++ b/INSTALL +@@ -416,6 +416,11 @@ + no-hw-padlock + Don't build the padlock engine. + ++ ++ no-hw-gmi ++ Don't build the gmi engine. ++ ++ + no-makedepend + Don't generate dependencies. + +diff --git a/README.ENGINE b/README.ENGINE +index 230dc82..0f81e1f 100644 +--- a/README.ENGINE ++++ b/README.ENGINE +@@ -16,6 +16,7 @@ + o Microsoft CryptoAPI + o VIA Padlock + o nCipher CHIL ++ o Zhaoxin GMI + + In addition, dynamic binding to external ENGINE implementations is now + provided by a special ENGINE called "dynamic". See the "DYNAMIC ENGINE" +diff --git a/crypto/init.c b/crypto/init.c +index b23af79..d6a500c 100644 +--- a/crypto/init.c ++++ b/crypto/init.c +@@ -388,6 +388,18 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_engine_capi) + return 1; + } + # endif ++# if !defined(OPENSSL_NO_HW) && !defined(OPENSSL_NO_HW_GMI) ++static CRYPTO_ONCE engine_gmi = CRYPTO_ONCE_STATIC_INIT; ++DEFINE_RUN_ONCE_STATIC(ossl_init_engine_gmi) ++{ ++# ifdef OPENSSL_INIT_DEBUG ++ fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_gmi: " ++ "engine_load_gmi_int()\n"); ++# endif ++ engine_load_gmi_int(); ++ return 1; ++} ++# endif + # if !defined(OPENSSL_NO_AFALGENG) + static CRYPTO_ONCE engine_afalg = CRYPTO_ONCE_STATIC_INIT; + DEFINE_RUN_ONCE_STATIC(ossl_init_engine_afalg) +@@ -728,6 +740,11 @@ int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings) + && !RUN_ONCE(&engine_capi, ossl_init_engine_capi)) + return 0; + # endif ++# if !defined(OPENSSL_NO_HW) && !defined(OPENSSL_NO_HW_GMI) ++ if ((opts & OPENSSL_INIT_ENGINE_GMI) ++ && !RUN_ONCE(&engine_gmi, ossl_init_engine_gmi)) ++ return 0; ++# endif + # if !defined(OPENSSL_NO_AFALGENG) + if ((opts & OPENSSL_INIT_ENGINE_AFALG) + && !RUN_ONCE(&engine_afalg, ossl_init_engine_afalg)) +diff --git a/engines/asm/e_gmi-x86.pl b/engines/asm/e_gmi-x86.pl +new file mode 100644 +index 0000000..8e60341 +--- /dev/null ++++ b/engines/asm/e_gmi-x86.pl +@@ -0,0 +1,128 @@ ++#!/usr/bin/env perl ++ ++# ==================================================================== ++# Written by Yun Shen and refer to the code ++# written by Andy Polyakov for the OpenSSL ++# project. The module is, however, dual licensed under OpenSSL and ++# CRYPTOGAMS licenses depending on where you obtain it. For further ++# details see http://www.openssl.org/~appro/cryptogams/. ++# ==================================================================== ++ ++# ==================================================================== ++# Copyright 2016 Shanghai Zhaoxin Semiconductor Co., Ltd. ALL RIGHTS RESERVED. ++# ==================================================================== ++ ++ ++$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; ++push(@INC,"${dir}","${dir}../../crypto/perlasm"); ++require "x86asm.pl"; ++ ++$output=pop; ++open STDOUT,">$output"; ++ ++&asm_init($ARGV[0]); ++ ++$ctx="edx"; ++$out="edi"; ++$inp="esi"; ++$len="ecx"; ++$chunk="ebx"; ++ ++&function_begin_B("zx_gmi_capability"); ++ &push ("ebx"); ++ &pushf (); ++ &pop ("eax"); ++ &mov ("ecx","eax"); ++ &xor ("eax",1<<21); ++ &push ("eax"); ++ &popf (); ++ &pushf (); ++ &pop ("eax"); ++ &xor ("ecx","eax"); ++ &xor ("eax","eax"); ++ &bt ("ecx",21); ++ &jnc (&label("noluck")); ++ &cpuid (); ++ &xor ("eax","eax"); ++ &cmp ("ebx","0x".unpack("H*",'tneC')); ++ &jne (&label("zhaoxin")); ++ &cmp ("edx","0x".unpack("H*",'Hrua')); ++ &jne (&label("noluck")); ++ &cmp ("ecx","0x".unpack("H*",'slua')); ++ &jne (&label("noluck")); ++ &jmp (&label("zhaoxinEnd")); ++&set_label("zhaoxin"); ++ &cmp ("ebx","0x".unpack("H*",'hS ')); ++ &jne (&label("noluck")); ++ &cmp ("edx","0x".unpack("H*",'hgna')); ++ &jne (&label("noluck")); ++ &cmp ("ecx","0x".unpack("H*",' ia')); ++ &jne (&label("noluck")); ++&set_label("zhaoxinEnd"); ++ &mov ("eax",0xC0000000); ++ &cpuid (); ++ &mov ("edx","eax"); ++ &xor ("eax","eax"); ++ &cmp ("edx",0xC0000001); ++ &jb (&label("noluck")); ++ &mov ("eax",0xC0000001); ++ &push ("ebx"); ++ &cpuid (); ++ &pop ("ebx"); ++ &mov ("eax","edx"); ++&set_label("noluck"); ++ &pop ("ebx"); ++ &ret (); ++&function_end_B("zx_gmi_capability") ++ ++&function_begin_B("get_cpu_fms"); ++ &push ("ebx"); ++ &pushf (); ++ &pop ("eax"); ++ &mov ("ecx","eax"); ++ &xor ("eax",1<<21); ++ &push ("eax"); ++ &popf (); ++ &pushf (); ++ &pop ("eax"); ++ &xor ("ecx","eax"); ++ &xor ("eax","eax"); ++ &bt ("ecx",21); ++ &jnc (&label("noluck")); ++ &mov ("eax",0x01); ++ &cpuid (); # FMS->EAX ++&set_label("noluck"); ++ &pop ("ebx"); ++ &ret (); ++&function_end_B("get_cpu_fms") ++ ++ ++&function_begin_B("gmi_repxstore"); ++ &push ("edi"); ++ &push ("ecx"); ++ &push ("edx"); ++ &mov ("edi",&wparam(0)); ++ &mov ("ecx",&wparam(1)); ++ &mov ("edx", 3); ++ &data_byte(0xf3,0x0f,0xa7,0xc0); # rep xstore ++ &pop ("edx"); ++ &pop ("ecx"); ++ &pop ("edi"); ++ &ret (); ++&function_end_B("gmi_repxstore"); ++ ++ ++&asciz ("ZhaoXin GMI x86 module, CRYPTOGAMS by "); ++&align (16); ++ ++&dataseg(); ++# Essentially this variable belongs in thread local storage. ++# Having this variable global on the other hand can only cause ++# few bogus key reloads [if any at all on signle-CPU system], ++# so we accept the penalty... ++&set_label("zx_gmi_saved_context",4); ++&data_word(0); ++ ++&asm_finish(); ++ ++close STDOUT; +diff --git a/engines/asm/e_gmi-x86_64.pl b/engines/asm/e_gmi-x86_64.pl +new file mode 100644 +index 0000000..55d0321 +--- /dev/null ++++ b/engines/asm/e_gmi-x86_64.pl +@@ -0,0 +1,119 @@ ++#!/usr/bin/env perl ++ ++# ==================================================================== ++# Written by Yun Shen , and refer to the code ++# written by Andy Polyakov for the OpenSSL ++# project. The module is, however, dual licensed under OpenSSL and ++# CRYPTOGAMS licenses depending on where you obtain it. For further ++# details see http://www.openssl.org/~appro/cryptogams/. ++# ==================================================================== ++ ++# ==================================================================== ++# Copyright 2016 Shanghai Zhaoxin Semiconductor Co., Ltd. ALL RIGHTS RESERVED. ++# ==================================================================== ++ ++ ++$flavour = shift; ++$output = shift; ++if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } ++ ++$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); ++ ++$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; ++( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or ++( $xlate="${dir}../../crypto/perlasm/x86_64-xlate.pl" and -f $xlate) or ++die "can't locate x86_64-xlate.pl"; ++ ++open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""; ++*STDOUT=*OUT; ++ ++$code=".text\n"; ++ ++$ctx="%rdx"; ++$out="%rdi"; ++$inp="%rsi"; ++$len="%rcx"; ++$chunk="%rbx"; ++ ++($arg1,$arg2,$arg3,$arg4)=$win64?("%rcx","%rdx","%r8", "%r9") : # Win64 order ++ ("%rdi","%rsi","%rdx","%rcx"); # Unix order ++ ++$code.=<<___; ++.globl zx_gmi_capability ++.type zx_gmi_capability,\@abi-omnipotent ++.align 16 ++zx_gmi_capability: ++ mov %rbx,%r8 ++ xor %eax,%eax ++ cpuid ++ xor %eax,%eax ++ cmp \$`"0x".unpack("H*",'tneC')`,%ebx ++ jne .Lzhaoxin ++ cmp \$`"0x".unpack("H*",'Hrua')`,%edx ++ jne .Lnoluck ++ cmp \$`"0x".unpack("H*",'slua')`,%ecx ++ jne .Lnoluck ++ jmp .LzhaoxinEnd ++.Lzhaoxin: ++ cmp \$`"0x".unpack("H*",'hS ')`,%ebx ++ jne .Lnoluck ++ cmp \$`"0x".unpack("H*",'hgna')`,%edx ++ jne .Lnoluck ++ cmp \$`"0x".unpack("H*",' ia')`,%ecx ++ jne .Lnoluck ++.LzhaoxinEnd: ++ mov \$0xC0000000,%eax ++ cpuid ++ mov %eax,%edx ++ xor %eax,%eax ++ cmp \$0xC0000001,%edx ++ jb .Lnoluck ++ mov \$0xC0000001,%eax ++ cpuid ++ mov %edx,%eax ++ and \$0xffffffef,%eax ++ or \$0x10,%eax # set Nano bit#4 ++.Lnoluck: ++ mov %r8,%rbx ++ ret ++.size zx_gmi_capability,.-zx_gmi_capability ++ ++.globl get_cpu_fms ++.type get_cpu_fms,\@abi-omnipotent ++.align 16 ++get_cpu_fms: ++ mov %rbx,%r8 ++ xor %eax,%eax ++ mov \$0x01,%eax ++ cpuid ++ mov %r8,%rbx ++ ret ++.size get_cpu_fms,.-get_cpu_fms ++ ++.globl gmi_repxstore ++.type gmi_repxstore,\@function,2 ++.align 16 ++gmi_repxstore: ++ mov %rsi,%rcx ++ mov \$3,%rdx ++ .byte 0xf3,0x0f,0xa7,0xc0 # rep xstore ++ ret ++.size gmi_repxstore,.-gmi_repxstore ++ ++ ++___ ++ ++ ++$code.=<<___; ++.asciz "ZhaoXin GMI x86_64 module, CRYPTOGAMS by " ++.align 16 ++.data ++.align 8 ++.Lzx_gmi_saved_context: ++ .quad 0 ++___ ++$code =~ s/\`([^\`]*)\`/eval($1)/gem; ++ ++print $code; ++ ++close STDOUT; +diff --git a/engines/build.info b/engines/build.info +index 1db7719..8346a73 100644 +--- a/engines/build.info ++++ b/engines/build.info +@@ -8,6 +8,10 @@ IF[{- !$disabled{"engine"} -}] + IF[{- !$disabled{capieng} -}] + SOURCE[../libcrypto]=e_capi.c + ENDIF ++ IF[{- !$disabled{hw} && !$disabled{'hw-gmi'} -}] ++ SOURCE[../libcrypto]= e_gmi.c {- $target{gmi_asm_src} -} ++ ENDIF ++ + IF[{- !$disabled{afalgeng} -}] + SOURCE[../libcrypto]=e_afalg.c + ENDIF +@@ -24,6 +28,12 @@ IF[{- !$disabled{"engine"} -}] + DEPEND[capi]=../libcrypto + INCLUDE[capi]=../include + ENDIF ++ IF[{- !$disabled{hw} && !$disabled{'hw-gmi'} -}] ++ ENGINES=gmi ++ SOURCE[gmi]=e_gmi.c {- $target{gmi_asm_src} -} ++ DEPEND[gmi]=../libcrypto ++ INCLUDE[gmi]=../include ++ ENDIF + IF[{- !$disabled{afalgeng} -}] + ENGINES=afalg + SOURCE[afalg]=e_afalg.c +@@ -43,4 +53,9 @@ IF[{- !$disabled{"engine"} -}] + GENERATE[e_padlock-x86.s]=asm/e_padlock-x86.pl \ + $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) $(PROCESSOR) + GENERATE[e_padlock-x86_64.s]=asm/e_padlock-x86_64.pl $(PERLASM_SCHEME) ++ ++ GENERATE[e_gmi-x86.s]=asm/e_gmi-x86.pl \ ++ $(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) $(PROCESSOR) ++ GENERATE[e_gmi-x86_64.s]=asm/e_gmi-x86_64.pl $(PERLASM_SCHEME) ++ + ENDIF +diff --git a/engines/e_gmi.c b/engines/e_gmi.c +new file mode 100644 +index 0000000..da092e3 +--- /dev/null ++++ b/engines/e_gmi.c +@@ -0,0 +1,213 @@ ++/* ++* Copyright 2004-2019 The OpenSSL Project Authors. All Rights Reserved. ++* ++* Licensed under the OpenSSL license (the "License"). You may not use ++* this file except in compliance with the License. You can obtain a copy ++* in the file LICENSE in the source distribution or at ++* https://www.openssl.org/source/license.html ++*/ ++/* ++# ==================================================================== ++# Copyright 2016 Shanghai Zhaoxin Semiconductor Co., Ltd. ALL RIGHTS RESERVED. ++# ==================================================================== ++*/ ++ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#ifndef OPENSSL_NO_HW ++# ifndef OPENSSL_NO_HW_GMI ++ ++/* Attempt to have a single source for both 0.9.7 and 0.9.8 :-) */ ++# if (OPENSSL_VERSION_NUMBER >= 0x00908000L) ++# ifndef OPENSSL_NO_DYNAMIC_ENGINE ++# define DYNAMIC_ENGINE ++# endif ++# elif (OPENSSL_VERSION_NUMBER >= 0x00907000L) ++# ifdef ENGINE_DYNAMIC_SUPPORT ++# define DYNAMIC_ENGINE ++# endif ++# else ++# error "Only OpenSSL >= 0.9.7 is supported" ++# endif ++ ++/* ++* ZHAOXIN GMI is available *ONLY* on some x86 CPUs. Not only that it ++* doesn't exist elsewhere, but it even can't be compiled on other platforms! ++*/ ++ ++# undef COMPILE_HW_GMI ++# if defined(GMI_ASM) ++# define COMPILE_HW_GMI ++# ifdef OPENSSL_NO_DYNAMIC_ENGINE ++static ENGINE *ENGINE_gmi(void); ++# endif ++# endif ++ ++# ifdef OPENSSL_NO_DYNAMIC_ENGINE ++void engine_load_gmi_int(void); ++void engine_load_gmi_int(void) ++{ ++/* On non-x86 CPUs it just returns. */ ++# ifdef COMPILE_HW_GMI ++ENGINE *toadd = ENGINE_gmi(); ++if (!toadd) ++return; ++ENGINE_add(toadd); ++ENGINE_free(toadd); ++ERR_clear_error(); ++# endif ++} ++# endif ++ ++# ifdef COMPILE_HW_GMI ++ ++/* Function for ENGINE detection and control */ ++unsigned int get_cpu_fms(void); ++static int gmi_available(void); ++static int gmi_init(ENGINE *e); ++ ++/* RNG Stuff */ ++static RAND_METHOD gmi_rand; ++/* Engine names */ ++static const char *gmi_id = "gmi"; ++static char gmi_name[100]; ++ ++/* Available features */ ++static int gmi_use_rng = 0; /* Random Number Generator */ ++ ++/* Prepare the ENGINE structure for registration */ ++static int gmi_bind_helper(ENGINE *e) ++{ ++ /* Check available features */ ++ gmi_available(); ++ ++ /* Generate a nice engine name with available features */ ++ BIO_snprintf(gmi_name, sizeof(gmi_name), ++ "ZhaoXin GMI (%s)", ++ gmi_use_rng ? "RNG" : "no-RNG"); ++ ++ /* Register everything or return with an error */ ++ if (!ENGINE_set_id(e, gmi_id) || ++ !ENGINE_set_name(e, gmi_name) || ++ !ENGINE_set_init_function(e, gmi_init) || ++ (gmi_use_rng && !ENGINE_set_RAND(e, &gmi_rand))) { ++ ++ return 0; ++ } ++ ++ /* Everything looks good */ ++ return 1; ++} ++ ++# ifdef OPENSSL_NO_DYNAMIC_ENGINE ++/* Constructor */ ++static ENGINE *ENGINE_gmi(void) ++{ ++ ENGINE *eng = ENGINE_new(); ++ ++ if (eng == NULL) { ++ return NULL; ++ } ++ ++ if (!gmi_bind_helper(eng)) { ++ ENGINE_free(eng); ++ return NULL; ++ } ++ ++ return eng; ++} ++# endif ++ ++/* Check availability of the engine */ ++static int gmi_init(ENGINE *e) ++{ ++ return (gmi_use_rng); ++} ++ ++/* ++* This stuff is needed if this ENGINE is being compiled into a ++* self-contained shared-library. ++*/ ++# ifndef OPENSSL_NO_DYNAMIC_ENGINE ++static int gmi_bind_fn(ENGINE *e, const char *id) ++{ ++ if (id && (strcmp(id, gmi_id) != 0)) { ++ printf("%s:%d",__func__,__LINE__); ++ return 0; ++ } ++ ++ if (!gmi_bind_helper(e)) { ++ printf("%s:%d",__func__,__LINE__); ++ return 0; ++ } ++ ++ return 1; ++} ++ ++IMPLEMENT_DYNAMIC_CHECK_FN() ++IMPLEMENT_DYNAMIC_BIND_FN(gmi_bind_fn) ++# endif /* !OPENSSL_NO_DYNAMIC_ENGINE */ ++ ++/* ===== Here comes the "real" engine ===== */ ++ ++/* Interface to assembler module */ ++unsigned int get_cpu_fms(void); ++unsigned int zx_gmi_capability(); ++int gmi_repxstore(void *buf, int num); ++ ++/* ++* Load supported features of the CPU to see if the PadLock is available. ++*/ ++static int gmi_available(void) ++{ ++ unsigned int edx = zx_gmi_capability(); ++ gmi_use_rng = ((edx & (0x3 << 2)) == (0x3 << 2)); ++ return gmi_use_rng; ++} ++ ++static int gmi_rand_bytes(unsigned char *output, int count) ++{ ++ gmi_repxstore(output, count); ++ return 1; ++} ++ ++static int gmi_rand_status(void) ++{ ++ return 1; ++} ++ ++static RAND_METHOD gmi_rand = { ++ NULL, /* seed */ ++ gmi_rand_bytes, /* bytes */ ++ NULL, /* cleanup */ ++ NULL, /* add */ ++ gmi_rand_bytes, /* pseudorand */ ++ gmi_rand_status, /* rand status */ ++}; ++ ++ ++ ++# endif /* COMPILE_HW_GMI */ ++# endif /* !OPENSSL_NO_HW_GMI */ ++#endif /* !OPENSSL_NO_HW */ ++ ++#if defined(OPENSSL_NO_HW) || defined(OPENSSL_NO_HW_GMI) \ ++|| !defined(COMPILE_HW_GMI) ++# ifndef OPENSSL_NO_DYNAMIC_ENGINE ++OPENSSL_EXPORT ++int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns); ++OPENSSL_EXPORT ++int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns) ++{ ++ return 0; ++} ++ ++IMPLEMENT_DYNAMIC_CHECK_FN() ++# endif ++#endif +diff --git a/include/crypto/engine.h b/include/crypto/engine.h +index f80ae3e..2f0f7e4 100644 +--- a/include/crypto/engine.h ++++ b/include/crypto/engine.h +@@ -15,6 +15,7 @@ void engine_load_rdrand_int(void); + void engine_load_dynamic_int(void); + void engine_load_padlock_int(void); + void engine_load_capi_int(void); ++void engine_load_gmi_int(void); + void engine_load_dasync_int(void); + void engine_load_afalg_int(void); + void engine_cleanup_int(void); +diff --git a/include/openssl/crypto.h b/include/openssl/crypto.h +index 132df5b..d896e10 100644 +--- a/include/openssl/crypto.h ++++ b/include/openssl/crypto.h +@@ -378,6 +378,7 @@ int CRYPTO_memcmp(const void * in_a, const void * in_b, size_t len); + # define OPENSSL_INIT_ATFORK 0x00020000L + /* OPENSSL_INIT_BASE_ONLY 0x00040000L */ + # define OPENSSL_INIT_NO_ATEXIT 0x00080000L ++# define OPENSSL_INIT_ENGINE_GMI 0x00100000L + /* OPENSSL_INIT flag range 0xfff00000 reserved for OPENSSL_init_ssl() */ + /* Max OPENSSL_INIT flag value is 0x80000000 */ + +@@ -385,7 +386,7 @@ int CRYPTO_memcmp(const void * in_a, const void * in_b, size_t len); + # define OPENSSL_INIT_ENGINE_ALL_BUILTIN \ + (OPENSSL_INIT_ENGINE_RDRAND | OPENSSL_INIT_ENGINE_DYNAMIC \ + | OPENSSL_INIT_ENGINE_CRYPTODEV | OPENSSL_INIT_ENGINE_CAPI | \ +- OPENSSL_INIT_ENGINE_PADLOCK) ++ OPENSSL_INIT_ENGINE_PADLOCK | OPENSSL_INIT_ENGINE_GMI) + + + /* Library initialisation functions */ +diff --git a/include/openssl/engine.h b/include/openssl/engine.h +index d707eae..c418a58 100644 +--- a/include/openssl/engine.h ++++ b/include/openssl/engine.h +@@ -330,6 +330,8 @@ ENGINE *ENGINE_by_id(const char *id); + OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_PADLOCK, NULL) + # define ENGINE_load_capi() \ + OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_CAPI, NULL) ++# define ENGINE_load_gmi() \ ++ OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_GMI, NULL) + # define ENGINE_load_afalg() \ + OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_AFALG, NULL) + # endif +-- +2.7.4 + diff --git a/Add-Zhaoxin-GMI-sm2-instruction-support.patch b/Add-Zhaoxin-GMI-sm2-instruction-support.patch new file mode 100755 index 0000000..82d3f0b --- /dev/null +++ b/Add-Zhaoxin-GMI-sm2-instruction-support.patch @@ -0,0 +1,716 @@ +From 9dc0a532a120d5e023c8607b05a8b844cb623e26 Mon Sep 17 00:00:00 2001 +From: yunshen +Date: Fri, 5 Sep 2025 16:37:42 +0800 +Subject: [PATCH 4/4] Add-Zhaoxin-GMI-sm2-instruction support + +--- + engines/e_gmi.c | 626 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- + engines/e_zx.h | 8 + + 2 files changed, 629 insertions(+), 5 deletions(-) + +diff --git a/engines/e_gmi.c b/engines/e_gmi.c +index a91075c..557e73c 100644 +--- a/engines/e_gmi.c ++++ b/engines/e_gmi.c +@@ -23,7 +23,10 @@ + #include + #include + #include ++#include ++#include + #include "crypto/evp.h" ++#include "crypto/sm2err.h" + #include "e_zx.h" + + #ifndef OPENSSL_NO_HW +@@ -93,6 +96,81 @@ static char gmi_name[100]; + /* Available features */ + static int gmi_use_ccs = 0; /* CCS */ + static int gmi_use_rng = 0; /* Random Number Generator */ ++static int gmi_use_sm2 = 0; /* SM2 */ ++ ++/* ===== GMI SM2 Cipher ===== */ ++static int gmi_sm2_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, ++ const unsigned char *tbs, size_t tbslen); ++static int gmi_sm2_verify(EVP_PKEY_CTX *ctx, ++ const unsigned char *sig, size_t siglen, ++ const unsigned char *tbs, size_t tbslen); ++static int gmi_sm2_encrypt(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, ++ const unsigned char *in, size_t inlen); ++static int gmi_sm2_decrypt(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, ++ const unsigned char *in, size_t inlen); ++static void gmi_sm2_cleanup(EVP_PKEY_CTX *ctx); ++static int gmi_sm2_init(EVP_PKEY_CTX *ctx); ++static int gmi_sm2_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src); ++static int gmi_sm2_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2); ++static int gmi_sm2_ctrl_str(EVP_PKEY_CTX *ctx, ++ const char *type, const char *value); ++static int gmi_sm2_digest_custom(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx); ++ ++EVP_PKEY_METHOD gmi_sm2_method = { ++ EVP_PKEY_SM2, ++ 0, ++ gmi_sm2_init, ++ gmi_sm2_copy, ++ gmi_sm2_cleanup, ++ ++ 0, ++ 0, ++ ++ 0, ++ 0, ++ ++ 0, ++ gmi_sm2_sign, ++ ++ 0, ++ gmi_sm2_verify, ++ ++ 0, 0, ++ ++ 0, 0, 0, 0, ++ ++ 0, ++ gmi_sm2_encrypt, ++ ++ 0, ++ gmi_sm2_decrypt, ++ ++ 0, ++ 0, ++ gmi_sm2_ctrl, ++ gmi_sm2_ctrl_str, ++ ++ 0, 0, ++ ++ 0, 0, 0, ++ ++ gmi_sm2_digest_custom ++}; ++ ++static int gmi_sm2_pkey_meths(ENGINE *e, EVP_PKEY_METHOD **pmeth, const int **pnids, int nid) ++{ ++ static const int rnid = EVP_PKEY_SM2; ++ if(pmeth == NULL){ ++ *pnids = &rnid; ++ return 1; ++ } ++ if(nid == EVP_PKEY_SM2){ ++ *pmeth = &gmi_sm2_method; ++ return 1; ++ } ++ *pmeth = NULL; ++ return 0; ++} + + /* Prepare the ENGINE structure for registration */ + static int gmi_bind_helper(ENGINE *e) +@@ -102,9 +180,10 @@ static int gmi_bind_helper(ENGINE *e) + + /* Generate a nice engine name with available features */ + BIO_snprintf(gmi_name, sizeof(gmi_name), +- "ZhaoXin GMI (%s, %s)", ++ "ZhaoXin GMI (%s, %s, %s)", + gmi_use_rng ? "RNG" : "no-RNG", +- gmi_use_ccs ? "CCS" : "no-CCS"); ++ gmi_use_ccs ? "CCS" : "no-CCS", ++ gmi_use_sm2 ? "SM2" : "no-SM2"); + + /* Register everything or return with an error */ + if (!ENGINE_set_id(e, gmi_id) || +@@ -112,7 +191,8 @@ static int gmi_bind_helper(ENGINE *e) + !ENGINE_set_init_function(e, gmi_init) || + (gmi_use_ccs && !ENGINE_set_ciphers(e, gmi_ciphers)) || + (gmi_use_ccs && !ENGINE_set_digests(e, gmi_digests)) || +- (gmi_use_rng && !ENGINE_set_RAND(e, &gmi_rand))) { ++ (gmi_use_rng && !ENGINE_set_RAND(e, &gmi_rand)) || ++ (gmi_use_sm2 && !ENGINE_set_pkey_meths(e, gmi_sm2_pkey_meths))) { + + return 0; + } +@@ -143,7 +223,7 @@ static ENGINE *ENGINE_gmi(void) + /* Check availability of the engine */ + static int gmi_init(ENGINE *e) + { +- return (gmi_use_ccs|gmi_use_rng); ++ return (gmi_use_ccs|gmi_use_rng|gmi_use_sm2); + } + + /* +@@ -230,10 +310,13 @@ static int gmi_available(void) + unsigned int edx = zx_gmi_capability(); + gmi_use_ccs = ((edx & (0x3 << 4)) == (0x3 << 4)); + gmi_use_rng = ((edx & (0x3 << 2)) == (0x3 << 2)); +- return gmi_use_ccs + gmi_use_rng; ++ gmi_use_sm2 = (edx & 0x3) == 0x3; ++ return gmi_use_ccs + gmi_use_rng + gmi_use_sm2; + } + + # define OSSL_NELEM(x) (sizeof(x)/sizeof((x)[0])) ++ ++/* ======== GX6 ===================== */ + /* List of supported ciphers. */ + static const int gmi_cipher_nids[] = { + NID_sm4_ecb, +@@ -752,6 +835,539 @@ static int gmi_digests(ENGINE *e, const EVP_MD **digest, + return ok; + } + ++// zx sm2 sign function ++// return 1: ok; 0:fail ++static int zx_sm2_sign(const unsigned char *hash, int dgstlen, ++ unsigned char *sig, unsigned int *siglen, EC_KEY *eckey ++ ) ++{ ++ unsigned char *scratch = (unsigned char *)malloc(SCRATCH_SIZE); ++ unsigned char *key = NULL; ++ int ret = 1; ++ size_t cword = 0x4, out_len = 0, f_ok; ++ ++ memset(scratch, 0, SCRATCH_SIZE); ++ EC_KEY_priv2buf(eckey, &key); ++ ++ __asm__ __volatile__( ++ ".byte 0xf2, 0x0f, 0xa6, 0xc0" ++ :"=c"(out_len),"=d"(f_ok) ++ :"a"(hash), "b"(key), "d"(cword), "S"(scratch), "D"(sig) ++ :"memory" ++ ); ++ ++ *siglen = out_len; ++ ++ if( f_ok & (0x1<<6)){ // check EDX BIT6 if 1. if 1, err occur! ++ printf("Err BIT is SET!!!!\n"); ++ ret = 0; ++ } ++ ++ if(key) free(key); ++ if(scratch) free(scratch); ++ return ret; ++} ++ ++// zx sm2 verify function ++// return 1: ok; 0:fail ++static int zx_sm2_verify(const unsigned char *hash, int dgstlen, ++ const unsigned char *sig, int sig_len, EC_KEY *eckey ++ ) ++{ ++ unsigned char *scratch = (unsigned char *)malloc(SCRATCH_SIZE); ++ size_t cword = 0x8, f_ok; ++ unsigned char *key = NULL; ++ ++ memset(scratch, 0, SCRATCH_SIZE); ++ EC_KEY_key2buf(eckey, POINT_CONVERSION_UNCOMPRESSED, &key, NULL); ++ __asm__ __volatile__( ++ ".byte 0xf2, 0x0f, 0xa6, 0xc0" ++ :"=c"(f_ok) ++ :"a"(hash), "b"(key), "d"(cword), "S"(scratch), "D"(sig) ++ :"memory"); ++ ++ if(key) free(key); ++ if(scratch) free(scratch); ++ return f_ok; ++} ++ ++// zx sm2 encrypt function ++// return 1: ok; 0:fail ++static int zx_sm2_encrypt( const EC_KEY *eckey, ++ const EVP_MD *digest, ++ const uint8_t *msg, size_t msg_len, ++ uint8_t *cipher, size_t *cipher_len ++ ) ++{ ++ unsigned char *scratch = (unsigned char *)malloc(SCRATCH_SIZE); ++ int ret = 1; ++ size_t cword = 0x1, out_len = 0, f_ok; ++ unsigned char *key = NULL; ++ ++ memset(scratch, 0, SCRATCH_SIZE); ++ EC_KEY_key2buf(eckey, POINT_CONVERSION_UNCOMPRESSED, &key, NULL); ++ __asm__ __volatile__( ++ ".byte 0xf2, 0x0f, 0xa6, 0xc0" ++ :"=c"(out_len),"=d"(f_ok) ++ :"a"(msg), "b"(key), "c"(msg_len),"d"(cword), "S"(scratch), "D"(cipher) ++ :"memory" ++ ); ++ *cipher_len = out_len; ++ ++ if( f_ok & (0x1<<6)){ // check EDX BIT6 if 1. if 1, err occur! ++ printf("Err BIT is SET!!!!\n"); ++ ret = 0; ++ } ++ if(key) free(key); ++ if(scratch) free(scratch); ++ return ret; ++} ++ ++// zx sm2 decrypt function ++// return 1: pass; return 0: fail ++static int zx_sm2_decrypt(const EC_KEY *eckey, ++ const EVP_MD *digest, ++ const uint8_t *cipher, size_t cipher_len, ++ unsigned char *plaintext, size_t *plaintext_len ++ ) ++{ ++ unsigned char *scratch = (unsigned char *)malloc(SCRATCH_SIZE); ++ int ret = 1; ++ size_t cword = 0x2, out_len = 0, f_ok; ++ unsigned char *key = NULL; ++ ++ memset(scratch, 0, SCRATCH_SIZE); ++ EC_KEY_priv2buf(eckey, &key); ++ __asm__ __volatile__( ++ ".byte 0xf2, 0x0f, 0xa6, 0xc0" ++ :"=c"(out_len),"=d"(f_ok) ++ :"a"(cipher), "b"(key), "c"(cipher_len),"d"(cword), "S"(scratch), "D"(plaintext) ++ :"memory" ++ ); ++ ++ if( f_ok & (0x1<<6)){ // check EDX BIT6 if 1. if 1, err occur! ++ printf("Err BIT is SET!!!!\n"); ++ ret = 0; ++ } ++ ++ *plaintext_len = out_len; ++ ++ if(key) free(key); ++ if(scratch) free(scratch); ++ return ret; ++} ++ ++static int zx_sm2_preprocess1(const uint8_t *id, const size_t id_len, const unsigned char *pubkey, uint8_t *result) ++{ ++ unsigned char *scratch = (unsigned char *)malloc(SCRATCH_SIZE); ++ size_t cword = 0x20, f_ok; ++ uint16_t id_bit_len = id_len << 3; ++ size_t in_buf_len = 2 + id_len; ++ uint8_t *in_buf = (unsigned char *)malloc(in_buf_len); ++ memset(scratch, 0, SCRATCH_SIZE); ++ memset(in_buf, 0, in_buf_len); ++ ++ memcpy(in_buf, &id_bit_len, 2); ++ memcpy(in_buf + 2, id, id_len); ++ ++ __asm__ __volatile__( ++ ".byte 0xf2, 0x0f, 0xa6, 0xc0" ++ :"=d"(f_ok) ++ :"a"(in_buf), "b"(pubkey), "d"(cword), "S"(scratch), "D"(result) ++ :"memory" ++ ); ++ ++ if( f_ok & (0x1<<6)){ // check EDX BIT6 if 1. if 1, err occur! ++ printf("Err BIT is SET!!!!\n"); ++ return 0; ++ } ++ ++ if(in_buf) free(in_buf); ++ if(scratch) free(scratch); ++ return 1; ++} ++ ++ ++/* EC pkey context structure */ ++typedef struct { ++ /* Key and paramgen group */ ++ EC_GROUP *gen_group; ++ /* message digest */ ++ const EVP_MD *md; ++ /* Distinguishing Identifier, ISO/IEC 15946-3 */ ++ uint8_t *id; ++ size_t id_len; ++ /* id_set indicates if the 'id' field is set (1) or not (0) */ ++ int id_set; ++} SM2_PKEY_CTX; ++ ++typedef struct SM2_Ciphertext_st ZX_SM2_Ciphertext; ++DECLARE_ASN1_FUNCTIONS(ZX_SM2_Ciphertext) ++ ++struct SM2_Ciphertext_st { ++ BIGNUM *C1x; ++ BIGNUM *C1y; ++ ASN1_OCTET_STRING *C3; ++ ASN1_OCTET_STRING *C2; ++}; ++ ++ASN1_SEQUENCE(ZX_SM2_Ciphertext) = { ++ ASN1_SIMPLE(ZX_SM2_Ciphertext, C1x, BIGNUM), ++ ASN1_SIMPLE(ZX_SM2_Ciphertext, C1y, BIGNUM), ++ ASN1_SIMPLE(ZX_SM2_Ciphertext, C3, ASN1_OCTET_STRING), ++ ASN1_SIMPLE(ZX_SM2_Ciphertext, C2, ASN1_OCTET_STRING), ++} ASN1_SEQUENCE_END(ZX_SM2_Ciphertext) ++ ++IMPLEMENT_ASN1_FUNCTIONS(ZX_SM2_Ciphertext) ++ ++static size_t ec_field_size(const EC_GROUP *group) ++{ ++ /* Is there some simpler way to do this? */ ++ BIGNUM *p = BN_new(); ++ BIGNUM *a = BN_new(); ++ BIGNUM *b = BN_new(); ++ size_t field_size = 0; ++ ++ if (p == NULL || a == NULL || b == NULL) ++ goto done; ++ ++ if (!EC_GROUP_get_curve(group, p, a, b, NULL)) ++ goto done; ++ field_size = (BN_num_bits(p) + 7) / 8; ++ ++ done: ++ BN_free(p); ++ BN_free(a); ++ BN_free(b); ++ ++ return field_size; ++} ++ ++ ++static int sm2_plaintext_size(const unsigned char *ct, size_t ct_size, size_t *pt_size) ++{ ++ struct SM2_Ciphertext_st *sm2_ctext = NULL; ++ ++ sm2_ctext = d2i_ZX_SM2_Ciphertext(NULL, &ct, ct_size); ++ ++ if (sm2_ctext == NULL) { ++ SM2err(SM2_F_SM2_PLAINTEXT_SIZE, SM2_R_INVALID_ENCODING); ++ return 0; ++ } ++ ++ *pt_size = sm2_ctext->C2->length; ++ ZX_SM2_Ciphertext_free(sm2_ctext); ++ ++ return 1; ++} ++ ++static int sm2_ciphertext_size(const EC_KEY *key, const EVP_MD *digest, size_t msg_len, ++ size_t *ct_size) ++{ ++ const size_t field_size = ec_field_size(EC_KEY_get0_group(key)); ++ const int md_size = EVP_MD_size(digest); ++ size_t sz; ++ ++ if (field_size == 0 || md_size < 0) ++ return 0; ++ ++ /* Integer and string are simple type; set constructed = 0, means primitive and definite length encoding. */ ++ sz = 2 * ASN1_object_size(0, field_size + 1, V_ASN1_INTEGER) ++ + ASN1_object_size(0, md_size, V_ASN1_OCTET_STRING) ++ + ASN1_object_size(0, msg_len, V_ASN1_OCTET_STRING); ++ /* Sequence is structured type; set constructed = 1, means constructed and definite length encoding. */ ++ *ct_size = ASN1_object_size(1, sz, V_ASN1_SEQUENCE); ++ ++ return 1; ++} ++ ++static int gmi_sm2_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, ++ const unsigned char *tbs, size_t tbslen) ++{ ++ int ret; ++ unsigned int sltmp; ++ EC_KEY *ec = ctx->pkey->pkey.ec; ++ const int sig_sz = ECDSA_size(ctx->pkey->pkey.ec); ++ ++ if (sig_sz <= 0) { ++ return 0; ++ } ++ ++ if (sig == NULL) { ++ *siglen = (size_t)sig_sz; ++ return 1; ++ } ++ ++ if (*siglen < (size_t)sig_sz) { ++ SM2err(SM2_F_PKEY_SM2_SIGN, SM2_R_BUFFER_TOO_SMALL); ++ return 0; ++ } ++ ++ ret = zx_sm2_sign(tbs, tbslen, sig, &sltmp, ec); ++ ++ if (ret <= 0) ++ return ret; ++ *siglen = (size_t)sltmp; ++ return 1; ++} ++ ++static int gmi_sm2_verify(EVP_PKEY_CTX *ctx, ++ const unsigned char *sig, size_t siglen, ++ const unsigned char *tbs, size_t tbslen) ++{ ++ EC_KEY *ec = ctx->pkey->pkey.ec; ++ return zx_sm2_verify(tbs, tbslen, sig, siglen, ec); ++} ++ ++static int gmi_sm2_encrypt(EVP_PKEY_CTX *ctx, ++ unsigned char *out, size_t *outlen, ++ const unsigned char *in, size_t inlen) ++{ ++ EC_KEY *ec = ctx->pkey->pkey.ec; ++ if (out == NULL) { ++ if (!sm2_ciphertext_size(ec, EVP_sm3(), inlen, outlen)) ++ return -1; ++ else ++ return 1; ++ } ++ ++ return zx_sm2_encrypt(ec, NULL, in, inlen, out, outlen); ++} ++ ++static int gmi_sm2_decrypt(EVP_PKEY_CTX *ctx, ++ unsigned char *out, size_t *outlen, ++ const unsigned char *in, size_t inlen) ++{ ++ EC_KEY *ec = ctx->pkey->pkey.ec; ++ if (out == NULL) { ++ if (!sm2_plaintext_size(in, inlen, outlen)) ++ return -1; ++ else ++ return 1; ++ } ++ ++ return zx_sm2_decrypt(ec, NULL, in, inlen, out, outlen); ++} ++ ++static int gmi_sm2_init(EVP_PKEY_CTX *ctx) ++{ ++ SM2_PKEY_CTX *smctx; ++ if ((smctx = OPENSSL_zalloc(sizeof(*smctx))) == NULL) { ++ printf("[YS]%s %d\n",__func__, __LINE__); ++ return 0; ++ } ++ ++ ctx->data = smctx; ++ return 1; ++} ++ ++static void gmi_sm2_cleanup(EVP_PKEY_CTX *ctx) ++{ ++ SM2_PKEY_CTX *smctx = ctx->data; ++ if (smctx != NULL) { ++ EC_GROUP_free(smctx->gen_group); ++ OPENSSL_free(smctx->id); ++ OPENSSL_free(smctx); ++ ctx->data = NULL; ++ } ++} ++ ++static int gmi_sm2_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) ++{ ++ SM2_PKEY_CTX *smctx = ctx->data; ++ EC_GROUP *group; ++ uint8_t *tmp_id; ++ ++ switch (type) { ++ case EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID: ++ group = EC_GROUP_new_by_curve_name(p1); ++ if (group == NULL) { ++ SM2err(SM2_F_PKEY_SM2_CTRL, SM2_R_INVALID_CURVE); ++ return 0; ++ } ++ EC_GROUP_free(smctx->gen_group); ++ smctx->gen_group = group; ++ return 1; ++ ++ case EVP_PKEY_CTRL_EC_PARAM_ENC: ++ if (smctx->gen_group == NULL) { ++ SM2err(SM2_F_PKEY_SM2_CTRL, SM2_R_NO_PARAMETERS_SET); ++ return 0; ++ } ++ EC_GROUP_set_asn1_flag(smctx->gen_group, p1); ++ return 1; ++ ++ case EVP_PKEY_CTRL_MD: ++ smctx->md = p2; ++ return 1; ++ ++ case EVP_PKEY_CTRL_GET_MD: ++ *(const EVP_MD **)p2 = smctx->md; ++ return 1; ++ ++ case EVP_PKEY_CTRL_SET1_ID: ++ if (p1 > 0) { ++ tmp_id = OPENSSL_malloc(p1); ++ if (tmp_id == NULL) { ++ SM2err(SM2_F_PKEY_SM2_CTRL, ERR_R_MALLOC_FAILURE); ++ return 0; ++ } ++ memcpy(tmp_id, p2, p1); ++ OPENSSL_free(smctx->id); ++ smctx->id = tmp_id; ++ } else { ++ /* set null-ID */ ++ OPENSSL_free(smctx->id); ++ smctx->id = NULL; ++ } ++ smctx->id_len = (size_t)p1; ++ smctx->id_set = 1; ++ return 1; ++ ++ case EVP_PKEY_CTRL_GET1_ID: ++ memcpy(p2, smctx->id, smctx->id_len); ++ return 1; ++ ++ case EVP_PKEY_CTRL_GET1_ID_LEN: ++ *(size_t *)p2 = smctx->id_len; ++ return 1; ++ ++ case EVP_PKEY_CTRL_DIGESTINIT: ++ case EVP_PKEY_CTRL_PKCS7_SIGN: ++ /* nothing to be inited, this is to suppress the error... */ ++ return 1; ++ ++ default: ++ return -2; ++ } ++} ++ ++static int gmi_sm2_ctrl_str(EVP_PKEY_CTX *ctx, ++ const char *type, const char *value) ++{ ++ uint8_t *hex_id; ++ long hex_len = 0; ++ int ret = 0; ++ ++ if (strcmp(type, "ec_paramgen_curve") == 0) { ++ int nid = NID_undef; ++ ++ if (((nid = EC_curve_nist2nid(value)) == NID_undef) ++ && ((nid = OBJ_sn2nid(value)) == NID_undef) ++ && ((nid = OBJ_ln2nid(value)) == NID_undef)) { ++ SM2err(SM2_F_PKEY_SM2_CTRL_STR, SM2_R_INVALID_CURVE); ++ return 0; ++ } ++ return EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid); ++ } else if (strcmp(type, "ec_param_enc") == 0) { ++ int param_enc; ++ ++ if (strcmp(value, "explicit") == 0) ++ param_enc = 0; ++ else if (strcmp(value, "named_curve") == 0) ++ param_enc = OPENSSL_EC_NAMED_CURVE; ++ else ++ return -2; ++ return EVP_PKEY_CTX_set_ec_param_enc(ctx, param_enc); ++ } else if (strcmp(type, "sm2_id") == 0) { ++ return gmi_sm2_ctrl(ctx, EVP_PKEY_CTRL_SET1_ID, ++ (int)strlen(value), (void *)value); ++ } else if (strcmp(type, "sm2_hex_id") == 0) { ++ /* ++ * TODO(3.0): reconsider the name "sm2_hex_id", OR change ++ * OSSL_PARAM_construct_from_text() / OSSL_PARAM_allocate_from_text() ++ * to handle infix "_hex_" ++ */ ++ hex_id = OPENSSL_hexstr2buf((const char *)value, &hex_len); ++ if (hex_id == NULL) { ++ SM2err(SM2_F_PKEY_SM2_CTRL_STR, ERR_R_PASSED_INVALID_ARGUMENT); ++ return 0; ++ } ++ ret = gmi_sm2_ctrl(ctx, EVP_PKEY_CTRL_SET1_ID, (int)hex_len, ++ (void *)hex_id); ++ OPENSSL_free(hex_id); ++ return ret; ++ } ++ ++ return -2; ++} ++ ++static int zx_sm2_compute_z_digest(uint8_t *out, ++ const EVP_MD *digest, ++ const uint8_t *id, ++ const size_t id_len, ++ const EC_KEY *eckey) ++{ ++ unsigned char *key= NULL; ++ ++ EC_KEY_key2buf(eckey, POINT_CONVERSION_UNCOMPRESSED, &key, NULL); ++ return zx_sm2_preprocess1(id, id_len, key, out); ++} ++ ++static int gmi_sm2_digest_custom(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx) ++{ ++ uint8_t z[EVP_MAX_MD_SIZE]; ++ SM2_PKEY_CTX *smctx = ctx->data; ++ EC_KEY *ec = ctx->pkey->pkey.ec; ++ const EVP_MD *md = EVP_MD_CTX_md(mctx); ++ int mdlen = EVP_MD_size(md); ++ ++ if (!smctx->id_set) ++ (void)gmi_sm2_ctrl(ctx, EVP_PKEY_CTRL_SET1_ID, SM2_DEFAULT_USERID_LEN ++ , (void *)SM2_DEFAULT_USERID); ++ ++ if (!smctx->id_set) { ++ /* ++ * An ID value must be set. The specifications are not clear whether a ++ * NULL is allowed. We only allow it if set explicitly for maximum ++ * flexibility. ++ */ ++ SM2err(SM2_F_PKEY_SM2_DIGEST_CUSTOM, SM2_R_ID_NOT_SET); ++ return 0; ++ } ++ ++ if (mdlen < 0) { ++ SM2err(SM2_F_PKEY_SM2_DIGEST_CUSTOM, SM2_R_INVALID_DIGEST); ++ return 0; ++ } ++ ++ /* get hashed prefix 'z' of tbs message */ ++ if (!zx_sm2_compute_z_digest(z, md, smctx->id, smctx->id_len, ec)) ++ return 0; ++ ++ int ret = EVP_DigestUpdate(mctx, z, (size_t)mdlen); ++ return ret; ++} ++ ++static int gmi_sm2_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) ++{ ++ SM2_PKEY_CTX *dctx, *sctx; ++ if (!gmi_sm2_init(dst)) ++ return 0; ++ sctx = src->data; ++ dctx = dst->data; ++ if (sctx->gen_group != NULL) { ++ dctx->gen_group = EC_GROUP_dup(sctx->gen_group); ++ if (dctx->gen_group == NULL) { ++ gmi_sm2_cleanup(dst); ++ return 0; ++ } ++ } ++ if (sctx->id != NULL) { ++ dctx->id = OPENSSL_malloc(sctx->id_len); ++ if (dctx->id == NULL) { ++ gmi_sm2_cleanup(dst); ++ return 0; ++ } ++ memcpy(dctx->id, sctx->id, sctx->id_len); ++ } ++ dctx->id_len = sctx->id_len; ++ dctx->id_set = sctx->id_set; ++ dctx->md = sctx->md; ++ ++ return 1; ++} ++ + static int gmi_rand_bytes(unsigned char *output, int count) + { + gmi_repxstore(output, count); +diff --git a/engines/e_zx.h b/engines/e_zx.h +index 6bffb48..9788398 100644 +--- a/engines/e_zx.h ++++ b/engines/e_zx.h +@@ -8,6 +8,14 @@ + #ifdef __cplusplus + extern "C" { + #endif ++ ++# define SCRATCH_SIZE (4*2048) ++# define SM2_PUBKEY_SIZE 65 ++# define SM2_PRIVKEY_SIZE 32 ++/* The default user id as specified in GM/T 0009-2012 */ ++# define SM2_DEFAULT_USERID "1234567812345678" ++# define SM2_DEFAULT_USERID_LEN 16 ++ + # define SM3_LONG unsigned int + # define SM3_WORD unsigned int + +-- +2.7.4 + diff --git a/Add-Zhaoxin-GMI-sm3-instruction-support.patch b/Add-Zhaoxin-GMI-sm3-instruction-support.patch new file mode 100755 index 0000000..9e862f0 --- /dev/null +++ b/Add-Zhaoxin-GMI-sm3-instruction-support.patch @@ -0,0 +1,438 @@ +From 8b4b8e1aad7026958cc1bf3f7cdb7581cfc63e94 Mon Sep 17 00:00:00 2001 +From: yunshen +Date: Thu, 4 Sep 2025 20:09:59 +0800 +Subject: [PATCH 2/4] Add-Zhaoxin-GMI-sm3-instruction support + +--- + engines/asm/e_gmi-x86.pl | 69 +++++++++++++++++ + engines/asm/e_gmi-x86_64.pl | 49 ++++++++++++ + engines/e_gmi.c | 184 +++++++++++++++++++++++++++++++++++++++++++- + engines/e_zx.h | 30 ++++++++ + 4 files changed, 328 insertions(+), 4 deletions(-) + create mode 100644 engines/e_zx.h + +diff --git a/engines/asm/e_gmi-x86.pl b/engines/asm/e_gmi-x86.pl +index 8e60341..63bd0f7 100644 +--- a/engines/asm/e_gmi-x86.pl ++++ b/engines/asm/e_gmi-x86.pl +@@ -111,6 +111,75 @@ $chunk="ebx"; + &ret (); + &function_end_B("gmi_repxstore"); + ++&function_begin_B("gmi_sm3_oneshot"); ++ &push ("ebx"); ++ &push ("edi"); ++ &push ("esi"); ++ &xor ("eax","eax"); ++ &mov ("edi",&wparam(0)); ++ &mov ("esi",&wparam(1)); ++ &mov ("ecx",&wparam(2)); ++ if ($::win32 or $::coff) { ++ &push (&::islabel("_win32_segv_handler")); ++ &data_byte(0x64,0xff,0x30); # push %fs:(%eax) ++ &data_byte(0x64,0x89,0x20); # mov %esp,%fs:(%eax) ++ } ++ &mov ("edx","esp"); # put aside %esp ++ &add ("esp",-128); ++ &movups ("xmm0",&QWP(0,"edi")); # copy-in context ++ &and ("esp",-16); ++ &movups ("xmm1",&QWP(16,"edi")); ++ &movaps (&QWP(0,"esp"),"xmm0"); ++ &mov ("edi","esp"); ++ &movaps (&QWP(16,"esp"),"xmm1"); ++ &mov ("ebx", 0x20); ++ &xor ("eax","eax"); ++ &data_byte(0xf3,0x0f,0xa6,0xe8); # gm5 ccs_hash ++ &movaps ("xmm0",&QWP(0,"esp")); ++ &movaps ("xmm1",&QWP(16,"esp")); ++ &mov ("esp","edx"); # restore %esp ++ if ($::win32 or $::coff) { ++ &data_byte(0x64,0x8f,0x05,0,0,0,0); # pop %fs:0 ++ &lea ("esp",&DWP(4,"esp")); ++ } ++ &mov ("edi",&wparam(0)); ++ &movups (&QWP(0,"edi"),"xmm0"); # copy-out context ++ &movups (&QWP(16,"edi"),"xmm1"); ++ &pop ("esi"); ++ &pop ("edi"); ++ &pop ("ebx"); ++ &ret (); ++&function_end_B("gmi_sm3_oneshot"); ++ ++&function_begin_B("gmi_sm3_blocks"); ++ &push ("ebx"); ++ &push ("edi"); ++ &push ("esi"); ++ &mov ("edi",&wparam(0)); ++ &mov ("esi",&wparam(1)); ++ &mov ("ecx",&wparam(2)); ++ &mov ("edx","esp"); # put aside %esp ++ &add ("esp",-128); ++ &movups ("xmm0",&QWP(0,"edi")); # copy-in context ++ &and ("esp",-16); ++ &movups ("xmm1",&QWP(16,"edi")); ++ &movaps (&QWP(0,"esp"),"xmm0"); ++ &mov ("edi","esp"); ++ &movaps (&QWP(16,"esp"),"xmm1"); ++ &mov ("ebx", 0x20); ++ &mov ("eax",-1); ++ &data_byte(0xf3,0x0f,0xa6,0xe8); # gm5 ccs_hash ++ &movaps ("xmm0",&QWP(0,"esp")); ++ &movaps ("xmm1",&QWP(16,"esp")); ++ &mov ("esp","edx"); # restore %esp ++ &mov ("edi",&wparam(0)); ++ &movups (&QWP(0,"edi"),"xmm0"); # copy-out context ++ &movups (&QWP(16,"edi"),"xmm1"); ++ &pop ("esi"); ++ &pop ("edi"); ++ &pop ("ebx"); ++ &ret (); ++&function_end_B("gmi_sm3_blocks"); + + &asciz ("ZhaoXin GMI x86 module, CRYPTOGAMS by "); + &align (16); +diff --git a/engines/asm/e_gmi-x86_64.pl b/engines/asm/e_gmi-x86_64.pl +index 55d0321..9e80d29 100644 +--- a/engines/asm/e_gmi-x86_64.pl ++++ b/engines/asm/e_gmi-x86_64.pl +@@ -100,6 +100,55 @@ gmi_repxstore: + ret + .size gmi_repxstore,.-gmi_repxstore + ++.globl gmi_sm3_oneshot ++.type gmi_sm3_oneshot,\@function,3 ++.align 16 ++gmi_sm3_oneshot: ++ mov %rbx, %r11 # save rbx ++ mov %rdx,%rcx ++ mov %rdi,%rdx # put aside %rdi ++ movups (%rdi),%xmm0 # copy-in context ++ sub \$128+8,%rsp ++ movups 16(%rdi),%xmm1 ++ movaps %xmm0,(%rsp) ++ mov %rsp,%rdi ++ movaps %xmm1,16(%rsp) ++ mov \$0x20, %rbx ++ xor %rax,%rax ++ .byte 0xf3,0x0f,0xa6,0xe8 # gm5 ccs_hash ++ movaps (%rsp),%xmm0 ++ movaps 16(%rsp),%xmm1 ++ add \$128+8,%rsp ++ movups %xmm0,(%rdx) # copy-out context ++ movups %xmm1,16(%rdx) ++ mov %r11, %rbx #restore rbx ++ ret ++.size gmi_sm3_oneshot,.-gmi_sm3_oneshot ++ ++.globl gmi_sm3_blocks ++.type gmi_sm3_blocks,\@function,3 ++.align 16 ++gmi_sm3_blocks: ++ mov %rbx, %r11 # save rbx ++ mov %rdx,%rcx ++ mov %rdi,%rdx # put aside %rdi ++ movups (%rdi),%xmm0 # copy-in context ++ sub \$128+8,%rsp ++ movups 16(%rdi),%xmm1 ++ movaps %xmm0,(%rsp) ++ mov %rsp,%rdi ++ movaps %xmm1,16(%rsp) ++ mov \$0x20, %rbx ++ mov \$-1,%rax ++ .byte 0xf3,0x0f,0xa6,0xe8 # gm5 ccs_hash ++ movaps (%rsp),%xmm0 ++ movaps 16(%rsp),%xmm1 ++ add \$128+8,%rsp ++ movups %xmm0,(%rdx) # copy-out context ++ movups %xmm1,16(%rdx) ++ mov %r11, %rbx #restore rbx ++ ret ++.size gmi_sm3_blocks,.-gmi_sm3_blocks + + ___ + +diff --git a/engines/e_gmi.c b/engines/e_gmi.c +index da092e3..a77434a 100644 +--- a/engines/e_gmi.c ++++ b/engines/e_gmi.c +@@ -16,9 +16,14 @@ + #include + #include + #include ++#include + #include ++#include + #include + #include ++#include ++#include "crypto/evp.h" ++#include "e_zx.h" + + #ifndef OPENSSL_NO_HW + # ifndef OPENSSL_NO_HW_GMI +@@ -72,6 +77,10 @@ unsigned int get_cpu_fms(void); + static int gmi_available(void); + static int gmi_init(ENGINE *e); + ++/* Cipher Stuff */ ++static int gmi_digests(ENGINE *e, const EVP_MD **digest, ++const int **nids, int nid); ++ + /* RNG Stuff */ + static RAND_METHOD gmi_rand; + /* Engine names */ +@@ -79,6 +88,7 @@ static const char *gmi_id = "gmi"; + static char gmi_name[100]; + + /* Available features */ ++static int gmi_use_ccs = 0; /* CCS */ + static int gmi_use_rng = 0; /* Random Number Generator */ + + /* Prepare the ENGINE structure for registration */ +@@ -89,13 +99,15 @@ static int gmi_bind_helper(ENGINE *e) + + /* Generate a nice engine name with available features */ + BIO_snprintf(gmi_name, sizeof(gmi_name), +- "ZhaoXin GMI (%s)", +- gmi_use_rng ? "RNG" : "no-RNG"); ++ "ZhaoXin GMI (%s, %s)", ++ gmi_use_rng ? "RNG" : "no-RNG", ++ gmi_use_ccs ? "CCS" : "no-CCS"); + + /* Register everything or return with an error */ + if (!ENGINE_set_id(e, gmi_id) || + !ENGINE_set_name(e, gmi_name) || + !ENGINE_set_init_function(e, gmi_init) || ++ (gmi_use_ccs && !ENGINE_set_digests(e, gmi_digests)) || + (gmi_use_rng && !ENGINE_set_RAND(e, &gmi_rand))) { + + return 0; +@@ -127,7 +139,7 @@ static ENGINE *ENGINE_gmi(void) + /* Check availability of the engine */ + static int gmi_init(ENGINE *e) + { +- return (gmi_use_rng); ++ return (gmi_use_ccs|gmi_use_rng); + } + + /* +@@ -159,6 +171,8 @@ IMPLEMENT_DYNAMIC_BIND_FN(gmi_bind_fn) + /* Interface to assembler module */ + unsigned int get_cpu_fms(void); + unsigned int zx_gmi_capability(); ++void gmi_sm3_oneshot(void *ctx, const void *inp, size_t len); ++void gmi_sm3_blocks(void *ctx, const void *inp, size_t len); + int gmi_repxstore(void *buf, int num); + + /* +@@ -167,8 +181,170 @@ int gmi_repxstore(void *buf, int num); + static int gmi_available(void) + { + unsigned int edx = zx_gmi_capability(); ++ gmi_use_ccs = ((edx & (0x3 << 4)) == (0x3 << 4)); + gmi_use_rng = ((edx & (0x3 << 2)) == (0x3 << 2)); +- return gmi_use_rng; ++ return gmi_use_ccs + gmi_use_rng; ++# define OSSL_NELEM(x) (sizeof(x)/sizeof((x)[0])) ++} ++ ++/* ===== GMI SM3 digest ===== */ ++#define HOST_l2c(l,c) ({ unsigned int r=(l); \ ++asm ("bswapl %0":"=r"(r):"0"(r)); \ ++*((unsigned int *)(c))=r; (c)+=4; r; }) ++ ++static int gmi_sm3_init(EVP_MD_CTX *ctx) ++{ ++ ZX_SM3_CTX *c = (ZX_SM3_CTX *)EVP_MD_CTX_md_data(ctx); ++ c->h[0]=0x6f168073UL; ++ c->h[1]=0xb9b21449UL; ++ c->h[2]=0xd7422417UL; ++ c->h[3]=0x00068adaUL; ++ c->h[4]=0xbc306fa9UL; ++ c->h[5]=0xaa383116UL; ++ c->h[6]=0x4dee8de3UL; ++ c->h[7]=0x4e0efbb0UL; ++ c->md_len = ZX_SM3_DIGEST_LENGTH; ++ c->num = 0; // ++ return 1; ++} ++ ++static int gmi_sm3_update(EVP_MD_CTX *ctx, const void *data_, size_t len) ++{ ++ const unsigned char *data = data_; ++ unsigned char *p; ++ SM3_WORD l; ++ size_t n; ++ ZX_SM3_CTX *c = (ZX_SM3_CTX *)EVP_MD_CTX_md_data(ctx); ++ ++ if (len == 0) ++ return 1; ++ ++ l = (c->Nl + (((SM3_WORD)len) << 3)) & 0xffffffffUL; ++ ++ if (l < c->Nl) /* overflow */ ++ c->Nh++; ++ c->Nh += (SM3_WORD)(len >> 29); /* might cause compiler warning on ++ * 16-bit */ ++ c->Nl = l; ++ ++ n = c->num; ++ if (n != 0) { ++ p = (unsigned char *)c->data; ++ ++ if (len >= ZX_SM3_CBLOCK || len + n >= ZX_SM3_CBLOCK) { ++ memcpy(p + n, data, ZX_SM3_CBLOCK - n); ++ gmi_sm3_blocks(c->h, p, 1); ++ n = ZX_SM3_CBLOCK - n; ++ data += n; ++ len -= n; ++ c->num = 0; ++ memset(p, 0, ZX_SM3_CBLOCK); /* keep it zeroed */ ++ } else { ++ memcpy(p + n, data, len); ++ c->num += (unsigned int)len; ++ return 1; ++ } ++ } ++ ++ n = len / ZX_SM3_CBLOCK; ++ if (n > 0) { ++ gmi_sm3_blocks(c->h, data, n); ++ n *= ZX_SM3_CBLOCK; ++ data += n; ++ len -= n; ++ } ++ ++ if (len != 0) { ++ p = (unsigned char *)c->data; ++ c->num = (unsigned int)len; ++ memcpy(p, data, len); ++ } ++ ++ return 1; ++} ++ ++static int gmi_sm3_final(EVP_MD_CTX *ctx, unsigned char *md) ++{ ++ ++ ZX_SM3_CTX *c = (ZX_SM3_CTX *)EVP_MD_CTX_md_data(ctx); ++ unsigned char *p = (unsigned char *)c->data; ++ size_t n = c->num; ++ ++ p[n] = 0x80; /* there is always room for one */ ++ n++; ++ ++ if (n > (ZX_SM3_CBLOCK - 8)) { ++ memset(p + n, 0, ZX_SM3_CBLOCK - n); ++ n = 0; ++ gmi_sm3_blocks(c->h, p, 1); ++ } ++ memset(p + n, 0, ZX_SM3_CBLOCK - 8 - n); ++ ++ p += ZX_SM3_CBLOCK - 8; ++ ++ (void)HOST_l2c(c->Nh, p); ++ (void)HOST_l2c(c->Nl, p); ++ ++ p -= ZX_SM3_CBLOCK; ++ gmi_sm3_blocks(c->h, p, 1); ++ ++ c->num = 0; ++ memset(p, 0, ZX_SM3_CBLOCK); ++ ++ memcpy(md, c->h, c->md_len); ++ ++ return 1; ++} ++ ++static const int gmi_digest_nids[] = { ++ NID_sm3 ++}; ++ ++static EVP_MD *_hidden_sm3_md = NULL; ++static const EVP_MD *zx_digest_sm3(void) ++{ ++ if (_hidden_sm3_md == NULL) { ++ EVP_MD *md; ++ ++ if ((md = EVP_MD_meth_new(NID_sm3, NID_sm3WithRSAEncryption)) == NULL ++ || !EVP_MD_meth_set_result_size(md, ZX_SM3_DIGEST_LENGTH) ++ || !EVP_MD_meth_set_input_blocksize(md, ZX_SM3_CBLOCK) ++ || !EVP_MD_meth_set_app_datasize(md, ++ sizeof(EVP_MD *) + sizeof(ZX_SM3_CTX)) ++ || !EVP_MD_meth_set_flags(md, EVP_MD_FLAG_DIGALGID_ABSENT) ++ || !EVP_MD_meth_set_init(md, gmi_sm3_init) ++ || !EVP_MD_meth_set_update(md, gmi_sm3_update) ++ || !EVP_MD_meth_set_final(md, gmi_sm3_final)) { ++ EVP_MD_meth_free(md); ++ md = NULL; ++ } ++ _hidden_sm3_md = md; ++ } ++ return _hidden_sm3_md; ++} ++ ++static int gmi_digests(ENGINE *e, const EVP_MD **digest, ++ const int **nids, int nid) ++{ ++ int ok = 1; ++ ++ if (digest == NULL) { ++ /* We are returning a list of supported nids */ ++ *nids = gmi_digest_nids; ++ return OSSL_NELEM(gmi_digest_nids); ++ } ++ ++ /* We are being asked for a specific digest */ ++ switch (nid) { ++ case NID_sm3: ++ *digest = zx_digest_sm3(); ++ break; ++ default: ++ ok = 0; ++ *digest = NULL; ++ break; ++ } ++ return ok; + } + + static int gmi_rand_bytes(unsigned char *output, int count) +diff --git a/engines/e_zx.h b/engines/e_zx.h +new file mode 100644 +index 0000000..b93fa97 +--- /dev/null ++++ b/engines/e_zx.h +@@ -0,0 +1,30 @@ ++#ifndef HEADER_E_ZX_H ++# define HEADER_E_ZX_H ++ ++# include ++# include ++# include ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++# define SM3_LONG unsigned int ++# define SM3_WORD unsigned int ++ ++# define ZX_SM3_LBLOCK 16 ++# define ZX_SM3_CBLOCK (ZX_SM3_LBLOCK*4) ++# define SM3_LAST_BLOCK (ZX_SM3_CBLOCK-8) ++# define ZX_SM3_DIGEST_LENGTH 32 ++ ++typedef struct SM3state_st { ++ SM3_LONG h[8]; ++ SM3_LONG Nl, Nh; ++ SM3_LONG data[ZX_SM3_LBLOCK]; ++ unsigned int num, md_len; ++} ZX_SM3_CTX; ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif +-- +2.7.4 + diff --git a/Add-Zhaoxin-GMI-sm4-instruction-support.patch b/Add-Zhaoxin-GMI-sm4-instruction-support.patch new file mode 100755 index 0000000..f58df75 --- /dev/null +++ b/Add-Zhaoxin-GMI-sm4-instruction-support.patch @@ -0,0 +1,640 @@ +From 91d5ff4cf902f7d9cd3cb8cc0776d760c7b8053f Mon Sep 17 00:00:00 2001 +From: yunshen +Date: Thu, 4 Sep 2025 20:40:49 +0800 +Subject: [PATCH 3/4] Add-Zhaoxin-GMI-sm4-instruction support + +--- + engines/asm/e_gmi-x86.pl | 50 ++++++ + engines/asm/e_gmi-x86_64.pl | 56 ++++++ + engines/e_gmi.c | 405 ++++++++++++++++++++++++++++++++++++++++++++ + engines/e_zx.h | 20 +++ + 4 files changed, 531 insertions(+) + +diff --git a/engines/asm/e_gmi-x86.pl b/engines/asm/e_gmi-x86.pl +index 63bd0f7..5a757e7 100644 +--- a/engines/asm/e_gmi-x86.pl ++++ b/engines/asm/e_gmi-x86.pl +@@ -97,6 +97,12 @@ $chunk="ebx"; + &function_end_B("get_cpu_fms") + + ++&function_begin_B("gmi_reload_key"); ++ &pushf (); ++ &popf (); ++ &ret (); ++&function_end_B("gmi_reload_key"); ++ + &function_begin_B("gmi_repxstore"); + &push ("edi"); + &push ("ecx"); +@@ -181,6 +187,50 @@ $chunk="ebx"; + &ret (); + &function_end_B("gmi_sm3_blocks"); + ++&function_begin_B("gmi_sm4_encrypt"); ++ ++ &push ("ebx"); ++ &push ("edi"); ++ &push ("esi"); ++ &mov ("edi",&wparam(0)); ++ &mov ("esi",&wparam(1)); ++ &mov ("edx",&wparam(2)); ++ &mov ("ecx",&wparam(3)); ++ ++ ++ &lea ("ebx",&DWP(32,"edx")); ++ &shr ("ecx", 4); ++ &mov ("eax",&DWP(16,"edx")); ++ ++ &data_byte(0xf3,0x0f,0xa7,0xf0); # gx6 ccs_encrypt ++ ++ &pop ("esi"); ++ &pop ("edi"); ++ &pop ("ebx"); ++ &ret (); ++&function_end_B("gmi_sm4_encrypt"); ++ ++&function_begin_B("gmi_sm4_ecb_enc"); ++ ++ &push ("ebx"); ++ &push ("edi"); ++ &push ("esi"); ++ &mov ("esi",&wparam(0)); ++ &mov ("edi",&wparam(1)); ++ &mov ("ebx",&wparam(2)); ++ ++ &mov ("ecx", 1); ++ &mov ("eax", 0x60); ++ ++ &data_byte(0xf3,0x0f,0xa7,0xf0); # gx6 ccs_encrypt ++ ++ &pop ("esi"); ++ &pop ("edi"); ++ &pop ("ebx"); ++ &ret (); ++&function_end_B("gmi_sm4_ecb_enc"); ++ ++ + &asciz ("ZhaoXin GMI x86 module, CRYPTOGAMS by "); + &align (16); + +diff --git a/engines/asm/e_gmi-x86_64.pl b/engines/asm/e_gmi-x86_64.pl +index 9e80d29..a285542 100644 +--- a/engines/asm/e_gmi-x86_64.pl ++++ b/engines/asm/e_gmi-x86_64.pl +@@ -100,6 +100,15 @@ gmi_repxstore: + ret + .size gmi_repxstore,.-gmi_repxstore + ++.globl gmi_reload_key ++.type gmi_reload_key,\@abi-omnipotent ++.align 16 ++gmi_reload_key: ++ pushf ++ popf ++ ret ++.size gmi_reload_key,.-gmi_reload_key ++ + .globl gmi_sm3_oneshot + .type gmi_sm3_oneshot,\@function,3 + .align 16 +@@ -150,6 +159,53 @@ gmi_sm3_blocks: + ret + .size gmi_sm3_blocks,.-gmi_sm3_blocks + ++.globl gmi_sm4_encrypt ++.type gmi_sm4_encrypt,\@function,4 ++.align 16 ++gmi_sm4_encrypt: ++ ++ push %rbp ++ push %rbx # save rbx ++ push %rdi ++ push %rsi ++ ++ ++ lea 32(%rdx), %rbx ++ shr \$0x04, %rcx ++ mov 16(%rdx), %rax ++ ++ .byte 0xf3,0x0f,0xa7,0xf0 # gx6 ccs_encrypt ++ ++ pop %rsi ++ pop %rdi ++ pop %rbx #restore rbx ++ pop %rbp ++ ret ++.size gmi_sm4_encrypt,.-gmi_sm4_encrypt ++ ++.globl gmi_sm4_ecb_enc ++.type gmi_sm4_ecb_enc,\@function,3 ++.align 16 ++gmi_sm4_ecb_enc: ++ push %rbp ++ push %rbx # save rbx ++ push %rdi ++ push %rsi ++ mov %rsi, %rax ++ mov %rdi, %rsi ++ mov %rax, %rdi ++ mov %rdx, %rbx ++ mov \$1, %rcx ++ mov \$0x60, %rax ++ .byte 0xf3,0x0f,0xa7,0xf0 # gx6 ccs_encrypt ++ pop %rsi ++ pop %rdi ++ pop %rbx #restore rbx ++ pop %rbp ++ ret ++.size gmi_sm4_ecb_enc,.-gmi_sm4_ecb_enc ++ ++ + ___ + + +diff --git a/engines/e_gmi.c b/engines/e_gmi.c +index a77434a..a91075c 100644 +--- a/engines/e_gmi.c ++++ b/engines/e_gmi.c +@@ -21,6 +21,7 @@ + #include + #include + #include ++#include + #include + #include "crypto/evp.h" + #include "e_zx.h" +@@ -78,6 +79,8 @@ static int gmi_available(void); + static int gmi_init(ENGINE *e); + + /* Cipher Stuff */ ++static int gmi_ciphers(ENGINE *e, const EVP_CIPHER **cipher, ++const int **nids, int nid); + static int gmi_digests(ENGINE *e, const EVP_MD **digest, + const int **nids, int nid); + +@@ -107,6 +110,7 @@ static int gmi_bind_helper(ENGINE *e) + if (!ENGINE_set_id(e, gmi_id) || + !ENGINE_set_name(e, gmi_name) || + !ENGINE_set_init_function(e, gmi_init) || ++ (gmi_use_ccs && !ENGINE_set_ciphers(e, gmi_ciphers)) || + (gmi_use_ccs && !ENGINE_set_digests(e, gmi_digests)) || + (gmi_use_rng && !ENGINE_set_RAND(e, &gmi_rand))) { + +@@ -168,13 +172,56 @@ IMPLEMENT_DYNAMIC_BIND_FN(gmi_bind_fn) + + /* ===== Here comes the "real" engine ===== */ + ++#define CCS_ENCRYPT_FUNC_SM4 0x10 ++ ++#define CCS_ENCRYPT_MODE_ECB 0x1 ++#define CCS_ENCRYPT_MODE_CBC 0x2 ++#define CCS_ENCRYPT_MODE_CFB 0x4 ++#define CCS_ENCRYPT_MODE_OFB 0x8 ++#define CCS_ENCRYPT_MODE_CTR 0x10 ++ ++struct gmi_cipher_data { ++ unsigned char iv[SM4_BLOCK_SIZE]; /* Initialization vector */ ++ union { ++ unsigned int pad[4]; ++ struct { ++ int encdec:1; ++ unsigned int func:5; ++ int mode:5; ++ int digest:1; ++ } b; ++ } cword; /* Control word */ ++ SM4_KEY ks; /* Encryption key */ ++}; + /* Interface to assembler module */ + unsigned int get_cpu_fms(void); + unsigned int zx_gmi_capability(); + void gmi_sm3_oneshot(void *ctx, const void *inp, size_t len); + void gmi_sm3_blocks(void *ctx, const void *inp, size_t len); ++void gmi_reload_key(void); ++void gmi_sm4_encrypt(unsigned char *out, const unsigned char *in,struct gmi_cipher_data *ctx, size_t len); ++void gmi_sm4_ecb_enc(unsigned char *in, unsigned char *out, unsigned char *key); + int gmi_repxstore(void *buf, int num); + ++static int gmi_zxc_check(void) ++{ ++ int eax = 0; ++ char family, model; ++ int f_zxc = 0; ++ ++ eax = get_cpu_fms(); ++ family = (eax & 0xf00) >> 8; /* bit 11-08 */ ++ model = (eax & 0xf0) >> 4; /* bit 7-4 */ ++ ++ if ((family == 7)&&(model == 0xb)) { ++ f_zxc = 0; ++ } else if (((family == 6)&&(model == 0xf)) || ++ ((family == 6)&&(model == 9))) { ++ f_zxc = 1; ++ } ++ return f_zxc; ++} ++ + /* + * Load supported features of the CPU to see if the PadLock is available. + */ +@@ -184,7 +231,365 @@ static int gmi_available(void) + gmi_use_ccs = ((edx & (0x3 << 4)) == (0x3 << 4)); + gmi_use_rng = ((edx & (0x3 << 2)) == (0x3 << 2)); + return gmi_use_ccs + gmi_use_rng; ++} ++ + # define OSSL_NELEM(x) (sizeof(x)/sizeof((x)[0])) ++/* List of supported ciphers. */ ++static const int gmi_cipher_nids[] = { ++ NID_sm4_ecb, ++ NID_sm4_cbc, ++ NID_sm4_cfb128, ++ NID_sm4_ofb128, ++ NID_sm4_ctr ++}; ++ ++static int gmi_cipher_nids_num = OSSL_NELEM(gmi_cipher_nids); ++ ++static int gmi_sm4_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, ++ const unsigned char *iv, int enc); ++ ++# define NEAREST_ALIGNED(ptr) ( (unsigned char *)(ptr) + \ ++( (0x10 - ((size_t)(ptr) & 0x0F)) & 0x0F ) ) ++# define ALIGNED_CIPHER_DATA_GMI(ctx) ((struct gmi_cipher_data *)\ ++NEAREST_ALIGNED(EVP_CIPHER_CTX_get_cipher_data(ctx))) ++ ++static int ++gmi_sm4_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg, ++ const unsigned char *in_arg, size_t nbytes) ++{ ++ struct gmi_cipher_data *cdata = ALIGNED_CIPHER_DATA_GMI(ctx); ++ gmi_sm4_encrypt(out_arg, in_arg, cdata, nbytes); ++ return 1; ++} ++ ++static int ++gmi_sm4_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg, ++ const unsigned char *in_arg, size_t nbytes) ++{ ++ struct gmi_cipher_data *cdata = ALIGNED_CIPHER_DATA_GMI(ctx); ++ memcpy(cdata->iv, EVP_CIPHER_CTX_iv(ctx), SM4_BLOCK_SIZE); ++ gmi_sm4_encrypt(out_arg, in_arg, cdata, nbytes); ++ memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), cdata->iv, SM4_BLOCK_SIZE); ++ return 1; ++} ++ ++typedef unsigned char u8; ++typedef unsigned short u16; ++typedef unsigned int u32; ++# define GETU16(p) ((u16)(p)[0]<<8 | (u16)(p)[1]) ++# define PUTU16(p,v) ((p)[0]=(u8)((v)>>8),(p)[1]=(u8)(v)) ++// increment upper 112 bits of 128-bit counter by 1 ++static void ctr112_inc(unsigned char *counter) ++{ ++ u32 n = 14, c = 1; ++ do { ++ --n; ++ c += counter[n]; ++ counter[n] = (u8)c; ++ c>>=8; ++ } while(n); ++} ++ ++static void ++gmi_ctr16_encrypt_blocks(const unsigned char *in, unsigned char *out, ++ size_t blocks, struct gmi_cipher_data *cdata, ++ const unsigned char ivec[16]) ++{ ++ memcpy(cdata->iv, ivec, SM4_BLOCK_SIZE); ++ gmi_sm4_encrypt(out, in, cdata, blocks*SM4_BLOCK_SIZE); ++} ++static void ++gmi_sm4_ctr32_encrypt_blocks(const unsigned char *in, ++ unsigned char *out, size_t len, ++ struct gmi_cipher_data *cdata, ++ const unsigned char ivec[16]) ++{ ++ u16 ctr16; ++ ctr16 = GETU16 (ivec + 14); ++ unsigned char iv[16] = {0}; ++ memcpy(iv, ivec, 16); ++ ++ while(len > 0){ ++ size_t blocks = len; ++ if (blocks > (1U << 15)) ++ blocks = 1U << 15; ++ ctr16 += (u16)blocks; ++ if (ctr16ks.rd_key, EVP_CIPHER_CTX_iv_noconst(ctx), buf, &num, ++ (block128_f) gmi_sm4_ecb_enc); ++ EVP_CIPHER_CTX_set_num(ctx, num); ++ } else { ++ unsigned int num = EVP_CIPHER_CTX_num(ctx); ++ CRYPTO_ctr128_encrypt_ctr32(in_arg, out_arg, nbytes, ++ cdata, EVP_CIPHER_CTX_iv_noconst(ctx), ++ EVP_CIPHER_CTX_buf_noconst(ctx), &num, ++ (ctr128_f) gmi_sm4_ctr32_encrypt_blocks); ++ EVP_CIPHER_CTX_set_num(ctx, num); ++ } ++ return 1; ++} ++ ++static int ++gmi_sm4_cfb128_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg, ++ const unsigned char *in_arg, size_t nbytes) ++{ ++ struct gmi_cipher_data *cdata = ALIGNED_CIPHER_DATA_GMI(ctx); ++ if (gmi_zxc_check()) { ++ int num = EVP_CIPHER_CTX_num(ctx); ++ CRYPTO_cfb128_encrypt(in_arg, out_arg, nbytes, cdata->ks.rd_key, ++ EVP_CIPHER_CTX_iv_noconst(ctx), &num, EVP_CIPHER_CTX_encrypting(ctx), ++ (block128_f)gmi_sm4_ecb_enc); ++ } else { ++ memcpy(cdata->iv, EVP_CIPHER_CTX_iv(ctx), SM4_BLOCK_SIZE); ++ ++ int n = EVP_CIPHER_CTX_num(ctx); ++ uint32_t number; ++ if (cdata->cword.b.encdec == 0) { ++ while (n && nbytes) { ++ *(out_arg++) = cdata->iv[n] ^= *(in_arg++); ++ --nbytes; ++ n = (n + 1) % 16; ++ } ++ ++ if (nbytes >= 16) { ++ number = nbytes / 16; ++ gmi_sm4_encrypt(out_arg, in_arg, cdata, number * 16); ++ nbytes -= number * 16; ++ out_arg += number * 16; ++ in_arg += number * 16; ++ n = 0; ++ } ++ ++ if (nbytes) { ++ gmi_sm4_ecb_enc(cdata->iv, cdata->iv, (unsigned char *)cdata->ks.rd_key); ++ while (nbytes--) { ++ out_arg[n] = cdata->iv[n] ^= in_arg[n]; ++ n++; ++ } ++ } ++ } else { ++ while (n && nbytes) { ++ unsigned char c; ++ *(out_arg++) = cdata->iv[n] ^ (c = *(in_arg++)); ++ cdata->iv[n] = c; ++ --nbytes; ++ n = (n + 1) % 16; ++ } ++ ++ if (nbytes >= 16) { ++ number = nbytes / 16; ++ gmi_sm4_encrypt(out_arg, in_arg, cdata, number * 16); ++ nbytes -= number * 16; ++ out_arg += number * 16; ++ in_arg += number * 16; ++ n = 0; ++ } ++ ++ if (nbytes) { ++ gmi_sm4_ecb_enc(cdata->iv, cdata->iv, (unsigned char *)cdata->ks.rd_key); ++ while (nbytes--) { ++ unsigned char c; ++ out_arg[n] = cdata->iv[n] ^ (c = in_arg[n]); ++ cdata->iv[n] = c; ++ ++n; ++ } ++ } ++ } ++ EVP_CIPHER_CTX_set_num(ctx, n); ++ ++ memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), cdata->iv, SM4_BLOCK_SIZE); ++ } ++ return 1; ++} ++ ++static int ++gmi_sm4_ofb128_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg, ++ const unsigned char *in_arg, size_t nbytes) ++{ ++ struct gmi_cipher_data *cdata = ALIGNED_CIPHER_DATA_GMI(ctx); ++ if (gmi_zxc_check()) { ++ int num = EVP_CIPHER_CTX_num(ctx); ++ CRYPTO_ofb128_encrypt(in_arg, out_arg, nbytes,cdata->ks.rd_key, ++ EVP_CIPHER_CTX_iv_noconst(ctx), &num, ++ (block128_f)gmi_sm4_ecb_enc); ++ } else { ++ memcpy(cdata->iv, EVP_CIPHER_CTX_iv(ctx), SM4_BLOCK_SIZE); ++ ++ int n = EVP_CIPHER_CTX_num(ctx); ++ uint32_t number; ++ while (n && nbytes) { ++ *(out_arg++) = *(in_arg++) ^ cdata->iv[n]; ++ --nbytes; ++ n = (n + 1) % 16; ++ } ++ ++ if (nbytes >= 16) { ++ number = nbytes / 16; ++ gmi_sm4_encrypt(out_arg, in_arg, cdata, number * 16); ++ nbytes -= number * 16; ++ out_arg += number * 16; ++ in_arg += number * 16; ++ n = 0; ++ } ++ ++ if (nbytes) { ++ gmi_sm4_ecb_enc(cdata->iv, cdata->iv, (unsigned char *)cdata->ks.rd_key); ++ while (nbytes--) { ++ out_arg[n] = in_arg[n] ^ cdata->iv[n]; ++ n++; ++ } ++ } ++ EVP_CIPHER_CTX_set_num(ctx, n); ++ ++ memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), cdata->iv, SM4_BLOCK_SIZE); ++ } ++ return 1; ++} ++ ++# define EVP_SM4_CIPHER_block_size_ECB SM4_BLOCK_SIZE ++# define EVP_SM4_CIPHER_block_size_CBC SM4_BLOCK_SIZE ++# define EVP_SM4_CIPHER_block_size_OFB 1 ++# define EVP_SM4_CIPHER_block_size_CFB 1 ++# define EVP_SM4_CIPHER_block_size_CTR 1 ++ ++/* ++* Declaring so many ciphers by hand would be a pain. Instead introduce a bit ++* of preprocessor magic :-) ++*/ ++ ++# define DECLARE_SM4_EVP(lmode,umode) \ ++static EVP_CIPHER *_hidden_sm4_##lmode = NULL; \ ++static const EVP_CIPHER *gmi_sm4_##lmode(void) \ ++{ \ ++ if (_hidden_sm4_##lmode == NULL \ ++ && ((_hidden_sm4_##lmode = \ ++ EVP_CIPHER_meth_new(NID_sm4_##lmode, \ ++ EVP_SM4_CIPHER_block_size_##umode, \ ++ SM4_KEY_SIZE)) == NULL \ ++ || !EVP_CIPHER_meth_set_iv_length(_hidden_sm4_##lmode, \ ++ SM4_BLOCK_SIZE) \ ++ || !EVP_CIPHER_meth_set_flags(_hidden_sm4_##lmode, \ ++ 0 | EVP_CIPH_##umode##_MODE) \ ++ || !EVP_CIPHER_meth_set_init(_hidden_sm4_##lmode, \ ++ gmi_sm4_init_key) \ ++ || !EVP_CIPHER_meth_set_do_cipher(_hidden_sm4_##lmode, \ ++ gmi_sm4_##lmode##_cipher) \ ++ || !EVP_CIPHER_meth_set_impl_ctx_size(_hidden_sm4_##lmode, \ ++ sizeof(struct gmi_cipher_data) + 16) \ ++ || !EVP_CIPHER_meth_set_set_asn1_params(_hidden_sm4_##lmode, \ ++ EVP_CIPHER_set_asn1_iv) \ ++ || !EVP_CIPHER_meth_set_get_asn1_params(_hidden_sm4_##lmode, \ ++ EVP_CIPHER_get_asn1_iv))) { \ ++ EVP_CIPHER_meth_free(_hidden_sm4_##lmode); \ ++ _hidden_sm4_##lmode = NULL; \ ++ } \ ++ return _hidden_sm4_##lmode; \ ++} ++ ++DECLARE_SM4_EVP(ecb, ECB) ++DECLARE_SM4_EVP(cbc, CBC) ++DECLARE_SM4_EVP(ctr, CTR) ++DECLARE_SM4_EVP(cfb128, CFB) ++DECLARE_SM4_EVP(ofb128, OFB) ++ ++ ++static int ++gmi_ciphers(ENGINE *e, const EVP_CIPHER **cipher, const int **nids, ++ int nid) ++{ ++ /* No specific cipher => return a list of supported nids ... */ ++ if (cipher == NULL) { ++ *nids = gmi_cipher_nids; ++ return gmi_cipher_nids_num; ++ } ++ ++ /* ... or the requested "cipher" otherwise */ ++ switch (nid) { ++ /* zx ciphers supports gmi's sm4 algorithm */ ++ case NID_sm4_ecb: ++ *cipher = gmi_sm4_ecb(); ++ break; ++ case NID_sm4_cbc: ++ *cipher = gmi_sm4_cbc(); ++ break; ++ case NID_sm4_cfb128: ++ *cipher = gmi_sm4_cfb128(); ++ break; ++ case NID_sm4_ofb128: ++ *cipher = gmi_sm4_ofb128(); ++ break; ++ case NID_sm4_ctr: ++ *cipher = gmi_sm4_ctr(); ++ break; ++ default: ++ /* Sorry, we don't support this NID */ ++ *cipher = NULL; ++ return 0; ++ } ++ ++ return 1; ++} ++ ++/* Prepare the encryption key for GMI sm4 usage */ ++static int ++gmi_sm4_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, ++ const unsigned char *iv, int enc) ++{ ++ struct gmi_cipher_data *cdata; ++ unsigned long mode = EVP_CIPHER_CTX_mode(ctx); ++ ++ if (key == NULL) ++ return 0; /* ERROR */ ++ ++ cdata = ALIGNED_CIPHER_DATA_GMI(ctx); ++ memset(cdata, 0, sizeof(*cdata)); ++ ++ /* Prepare Control word. */ ++ if (mode == EVP_CIPH_OFB_MODE || mode == EVP_CIPH_CTR_MODE) ++ cdata->cword.b.encdec = 0; ++ else ++ cdata->cword.b.encdec = (EVP_CIPHER_CTX_encrypting(ctx) == 0); ++ ++ cdata->cword.b.func = CCS_ENCRYPT_FUNC_SM4; ++ cdata->cword.b.mode = 1<<(mode-1); ++ cdata->cword.b.digest = 0; ++ ++ if (iv != NULL) ++ memcpy(cdata->iv, iv, SM4_BLOCK_SIZE); ++ ++ memcpy(cdata->ks.rd_key, key, SM4_KEY_SIZE); ++ ++ /* ++ * This is done to cover for cases when user reuses the ++ * context for new key. The catch is that if we don't do ++ * this, gmi_eas_cipher might proceed with old key... ++ */ ++ gmi_reload_key(); ++ ++ return 1; + } + + /* ===== GMI SM3 digest ===== */ +diff --git a/engines/e_zx.h b/engines/e_zx.h +index b93fa97..6bffb48 100644 +--- a/engines/e_zx.h ++++ b/engines/e_zx.h +@@ -23,6 +23,26 @@ typedef struct SM3state_st { + unsigned int num, md_len; + } ZX_SM3_CTX; + ++# define SM4_ENCRYPT 1 ++# define SM4_DECRYPT 0 ++ ++/* ++ * Because array size can't be a const in C, the following two are macros. ++ * Both sizes are in bytes. ++ */ ++#define SM4_BLOCK_SIZE 16 ++#define SM4_KEY_SIZE 16 ++ ++/* This should be a hidden type, but EVP requires that the size be known */ ++struct sm4_key_st { ++# ifdef SM4_LONG ++ unsigned long rd_key[32]; ++# else ++ unsigned int rd_key[32]; ++# endif ++}; ++typedef struct sm4_key_st SM4_KEY; ++ + #ifdef __cplusplus + } + #endif +-- +2.7.4 + diff --git a/openssl.spec b/openssl.spec index 1f29385..24f7f48 100644 --- a/openssl.spec +++ b/openssl.spec @@ -2,7 +2,7 @@ Name: openssl Epoch: 1 Version: 1.1.1wa -Release: 11 +Release: 12 Summary: Cryptography and SSL/TLS Toolkit License: OpenSSL and SSLeay URL: https://gitee.com/openeuler/openssl @@ -28,6 +28,10 @@ Patch17: backport-CVE-2024-5535-Add-a-test-for-ALPN-and-NPN.patch Patch18: backport-Pipeline-output-input-buf-arrays-must-live-until-the.patch Patch19: backport-CVE-2024-9143-Harden-BN_GF2m_poly2arr-against-misuse.patch Patch20: backport-CVE-2024-13176-Fix-timing-side-channel.patch +Patch21: Add-Zhaoxin-GMI-rng-instruction-support.patch +Patch22: Add-Zhaoxin-GMI-sm3-instruction-support.patch +Patch23: Add-Zhaoxin-GMI-sm4-instruction-support.patch +Patch24: Add-Zhaoxin-GMI-sm2-instruction-support.patch BuildRequires: gcc perl make lksctp-tools-devel coreutils util-linux zlib-devel Requires: coreutils %{name}-libs%{?_isa} = %{epoch}:%{version}-%{release} @@ -236,6 +240,9 @@ make test || : %ldconfig_scriptlets libs %changelog +* Fri Sep 5 2025 AlanSong-oc - 1:1.1.1wa-12 +- add support for Zhaoxin GMI RNG/SM2/3/4 instruction + * Wed Feb 5 2025 jinlun - 1:1.1.1wa-11 - fix CVE-2024-13176 -- Gitee