ecc8879f创建于 2025年5月10日历史提交
Date: Thu, 13 Mar 2025 10:25:51 +0800
Subject: Add KAE Provider

---
 make/ZipSecurity.gmk                          |   1 +
 make/autoconf/configure.ac                    |   1 +
 make/autoconf/jdk-options.m4                  |  21 +
 make/autoconf/spec.gmk.in                     |   1 +
 make/common/Modules.gmk                       |  13 +
 make/conf/module-loader-map.conf              |   1 +
 .../hotspot/nbproject/configurations.xml      | 104 +++
 make/modules/jdk.crypto.kaeprovider/Copy.gmk  |  46 +
 make/modules/jdk.crypto.kaeprovider/Lib.gmk   |  46 +
 src/java.base/share/classes/module-info.java  |   8 +-
 .../share/lib/security/default.policy         |   5 +
 .../share/classes/module-info.java            |   6 +
 .../linux/classes/module-info.java            |  39 +
 .../security/openssl/KAEAESCipher.java        | 365 ++++++++
 .../openeuler/security/openssl/KAEConfig.java | 393 +++++++++
 .../security/openssl/KAEDHKeyAgreement.java   | 289 +++++++
 .../openssl/KAEDHKeyPairGenerator.java        | 183 ++++
 .../openeuler/security/openssl/KAEDigest.java | 264 ++++++
 .../security/openssl/KAEECDHKeyAgreement.java | 146 ++++
 .../openssl/KAEECKeyPairGenerator.java        | 151 ++++
 .../openeuler/security/openssl/KAEHMac.java   | 227 +++++
 .../openeuler/security/openssl/KAELog.java    | 188 +++++
 .../openeuler/security/openssl/KAEMGF1.java   |  94 +++
 .../security/openssl/KAEProvider.java         | 326 +++++++
 .../security/openssl/KAERSACipher.java        | 796 ++++++++++++++++++
 .../openssl/KAERSAKeyPairGenerator.java       | 164 ++++
 .../security/openssl/KAERSAPSSSignature.java  | 683 +++++++++++++++
 .../security/openssl/KAERSAPaddingType.java   |  83 ++
 .../security/openssl/KAERSASignature.java     | 365 ++++++++
 .../openssl/KAERSASignatureNative.java        |  46 +
 .../security/openssl/KAESM4Cipher.java        | 370 ++++++++
 .../security/openssl/KAESM4KeyGenerator.java  |  74 ++
 .../openssl/KAESymmetricCipherBase.java       | 791 +++++++++++++++++
 .../openeuler/security/openssl/KAEUtils.java  | 220 +++++
 .../linux/conf/security/kaeprovider.conf      |  75 ++
 .../security/openssl/kae_cipher_rsa.c         | 471 +++++++++++
 .../openeuler/security/openssl/kae_digest.c   | 232 +++++
 .../security/openssl/kae_exception.c          | 135 +++
 .../security/openssl/kae_exception.h          |  57 ++
 .../org/openeuler/security/openssl/kae_hmac.c | 208 +++++
 .../security/openssl/kae_keyagreement_dh.c    | 141 ++++
 .../security/openssl/kae_keyagreement_ecdh.c  | 121 +++
 .../openssl/kae_keypairgenerator_dh.c         | 132 +++
 .../openssl/kae_keypairgenerator_ec.c         | 505 +++++++++++
 .../openssl/kae_keypairgenerator_rsa.c        | 173 ++++
 .../org/openeuler/security/openssl/kae_log.h  |  33 +
 .../openeuler/security/openssl/kae_provider.c | 103 +++
 .../security/openssl/kae_signature_rsa.c      | 366 ++++++++
 .../security/openssl/kae_symmetric_cipher.c   | 415 +++++++++
 .../org/openeuler/security/openssl/kae_util.c | 246 ++++++
 .../org/openeuler/security/openssl/kae_util.h |  94 +++
 .../openeuler/security/openssl/openssl_ad.h   |  10 +
 test/jdk/TEST.groups                          |   3 +
 .../KeyAgreement/KeyAgreementTest.java        |  11 +-
 .../Signature/SignatureGetInstance.java       |   6 +-
 .../openeuler/security/openssl/AESTest.java   | 115 +++
 .../openeuler/security/openssl/DHTest.java    | 122 +++
 .../security/openssl/DigestTest.java          |  61 ++
 .../openeuler/security/openssl/ECDHTest.java  | 114 +++
 .../openeuler/security/openssl/HmacTest.java  |  89 ++
 .../security/openssl/KAEConfTest.java         | 122 +++
 .../openssl/KAEDisabledAlgorithmsTest.java    | 165 ++++
 .../security/openssl/KAEEngineIdTest.java     |  77 ++
 .../security/openssl/KAELogTest.java          | 127 +++
 .../security/openssl/KAETestHelper.java       | 209 +++++
 .../security/openssl/KAEUseEngineTest.java    | 263 ++++++
 .../security/openssl/KaeDebugLogTest.java     |  89 ++
 .../security/openssl/KaeProviderTest.java     | 171 ++++
 .../openeuler/security/openssl/RSATest.java   | 115 +++
 .../openeuler/security/openssl/SM3Test.java   |  55 ++
 .../openeuler/security/openssl/SM4Test.java   | 153 ++++
 .../jca/PreferredProviderNegativeTest.java    |   7 +-
 .../jdk/sun/security/krb5/auto/BasicProc.java |   4 +-
 test/jdk/sun/security/pkcs11/Secmod/policy    |   1 +
 test/jdk/sun/security/pkcs11/policy           |   1 +
 .../ssl/CipherSuite/DisabledCurve.java        |   4 +
 .../SSLSocketImpl/NotifyHandshakeTest.policy  |   2 +
 .../bench/security/openssl/AESBenchmark.java  | 108 +++
 .../security/openssl/AESGCMBenchmark.java     | 133 +++
 .../bench/security/openssl/BenchmarkBase.java | 106 +++
 .../openssl/DHKeyAgreementBenchMark.java      | 139 +++
 .../openssl/DHKeyPairGeneratorBenchmark.java  |  64 ++
 .../security/openssl/DigestBenchmark.java     |  69 ++
 .../openssl/ECKeyAgreementBenchmark.java      |  88 ++
 .../openssl/ECKeyPairGeneratorBenchmark.java  |  63 ++
 .../bench/security/openssl/HMacBenchmark.java |  73 ++
 .../security/openssl/RSACipherBenchmark.java  | 107 +++
 .../openssl/RSAKeyPairGeneratorBenchmark.java |  64 ++
 .../openssl/RSAPSSSignatureBenchmark.java     | 118 +++
 .../openssl/RSASignatureBenchmark.java        |  90 ++
 .../bench/security/openssl/SM3Benchmark.java  |  98 +++
 .../bench/security/openssl/SM4Benchmark.java  | 157 ++++
 92 files changed, 13584 insertions(+), 5 deletions(-)
 create mode 100644 make/modules/jdk.crypto.kaeprovider/Copy.gmk
 create mode 100644 make/modules/jdk.crypto.kaeprovider/Lib.gmk
 create mode 100644 src/jdk.crypto.kaeprovider/linux/classes/module-info.java
 create mode 100644 src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEAESCipher.java
 create mode 100644 src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEConfig.java
 create mode 100644 src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEDHKeyAgreement.java
 create mode 100644 src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEDHKeyPairGenerator.java
 create mode 100644 src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEDigest.java
 create mode 100644 src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEECDHKeyAgreement.java
 create mode 100644 src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEECKeyPairGenerator.java
 create mode 100644 src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEHMac.java
 create mode 100644 src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAELog.java
 create mode 100644 src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEMGF1.java
 create mode 100644 src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEProvider.java
 create mode 100644 src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAERSACipher.java
 create mode 100644 src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAERSAKeyPairGenerator.java
 create mode 100644 src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAERSAPSSSignature.java
 create mode 100644 src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAERSAPaddingType.java
 create mode 100644 src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAERSASignature.java
 create mode 100644 src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAERSASignatureNative.java
 create mode 100644 src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAESM4Cipher.java
 create mode 100644 src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAESM4KeyGenerator.java
 create mode 100644 src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAESymmetricCipherBase.java
 create mode 100644 src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEUtils.java
 create mode 100644 src/jdk.crypto.kaeprovider/linux/conf/security/kaeprovider.conf
 create mode 100644 src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_cipher_rsa.c
 create mode 100644 src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_digest.c
 create mode 100644 src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_exception.c
 create mode 100644 src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_exception.h
 create mode 100644 src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_hmac.c
 create mode 100644 src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_keyagreement_dh.c
 create mode 100644 src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_keyagreement_ecdh.c
 create mode 100644 src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_keypairgenerator_dh.c
 create mode 100644 src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_keypairgenerator_ec.c
 create mode 100644 src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_keypairgenerator_rsa.c
 create mode 100644 src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_log.h
 create mode 100644 src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_provider.c
 create mode 100644 src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_signature_rsa.c
 create mode 100644 src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_symmetric_cipher.c
 create mode 100644 src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_util.c
 create mode 100644 src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_util.h
 create mode 100644 src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/openssl_ad.h
 create mode 100644 test/jdk/org/openeuler/security/openssl/AESTest.java
 create mode 100644 test/jdk/org/openeuler/security/openssl/DHTest.java
 create mode 100644 test/jdk/org/openeuler/security/openssl/DigestTest.java
 create mode 100644 test/jdk/org/openeuler/security/openssl/ECDHTest.java
 create mode 100644 test/jdk/org/openeuler/security/openssl/HmacTest.java
 create mode 100644 test/jdk/org/openeuler/security/openssl/KAEConfTest.java
 create mode 100644 test/jdk/org/openeuler/security/openssl/KAEDisabledAlgorithmsTest.java
 create mode 100644 test/jdk/org/openeuler/security/openssl/KAEEngineIdTest.java
 create mode 100644 test/jdk/org/openeuler/security/openssl/KAELogTest.java
 create mode 100644 test/jdk/org/openeuler/security/openssl/KAETestHelper.java
 create mode 100644 test/jdk/org/openeuler/security/openssl/KAEUseEngineTest.java
 create mode 100644 test/jdk/org/openeuler/security/openssl/KaeDebugLogTest.java
 create mode 100644 test/jdk/org/openeuler/security/openssl/KaeProviderTest.java
 create mode 100644 test/jdk/org/openeuler/security/openssl/RSATest.java
 create mode 100644 test/jdk/org/openeuler/security/openssl/SM3Test.java
 create mode 100644 test/jdk/org/openeuler/security/openssl/SM4Test.java
 create mode 100644 test/micro/org/openeuler/bench/security/openssl/AESBenchmark.java
 create mode 100644 test/micro/org/openeuler/bench/security/openssl/AESGCMBenchmark.java
 create mode 100644 test/micro/org/openeuler/bench/security/openssl/BenchmarkBase.java
 create mode 100644 test/micro/org/openeuler/bench/security/openssl/DHKeyAgreementBenchMark.java
 create mode 100644 test/micro/org/openeuler/bench/security/openssl/DHKeyPairGeneratorBenchmark.java
 create mode 100644 test/micro/org/openeuler/bench/security/openssl/DigestBenchmark.java
 create mode 100644 test/micro/org/openeuler/bench/security/openssl/ECKeyAgreementBenchmark.java
 create mode 100644 test/micro/org/openeuler/bench/security/openssl/ECKeyPairGeneratorBenchmark.java
 create mode 100644 test/micro/org/openeuler/bench/security/openssl/HMacBenchmark.java
 create mode 100644 test/micro/org/openeuler/bench/security/openssl/RSACipherBenchmark.java
 create mode 100644 test/micro/org/openeuler/bench/security/openssl/RSAKeyPairGeneratorBenchmark.java
 create mode 100644 test/micro/org/openeuler/bench/security/openssl/RSAPSSSignatureBenchmark.java
 create mode 100644 test/micro/org/openeuler/bench/security/openssl/RSASignatureBenchmark.java
 create mode 100644 test/micro/org/openeuler/bench/security/openssl/SM3Benchmark.java
 create mode 100644 test/micro/org/openeuler/bench/security/openssl/SM4Benchmark.java

diff --git a/make/ZipSecurity.gmk b/make/ZipSecurity.gmk
index 489bbef49..170b54df6 100644
--- a/make/ZipSecurity.gmk
+++ b/make/ZipSecurity.gmk
@@ -42,6 +42,7 @@ $(eval $(call SetupZipArchive,BUILD_SEC_BIN_ZIP, \
         modules/java.base/sun/security/internal/spec \
         modules/java.base/com/sun/crypto/provider \
         modules/jdk.crypto.ec/sun/security/ec \
+        modules/jdk.crypto.kaeprovider/org/openeuler/security/openssl \
         modules/jdk.crypto.mscapi/sun/security/mscapi \
         modules/jdk.crypto.cryptoki/sun/security/pkcs11 \
         modules/jdk.crypto.cryptoki/sun/security/pkcs11/wrapper \
diff --git a/make/autoconf/configure.ac b/make/autoconf/configure.ac
index f7e9844a6..55201277c 100644
--- a/make/autoconf/configure.ac
+++ b/make/autoconf/configure.ac
@@ -256,6 +256,7 @@ HOTSPOT_SETUP_MISC
 LIB_TESTS_ENABLE_DISABLE_FAILURE_HANDLER
 LIB_TESTS_ENABLE_DISABLE_JTREG_TEST_THREAD_FACTORY
 
+JDKOPT_DETECT_KAE
 JDKOPT_ENABLE_DISABLE_GENERATE_CLASSLIST
 JDKOPT_EXCLUDE_TRANSLATIONS
 JDKOPT_ENABLE_DISABLE_MANPAGES
diff --git a/make/autoconf/jdk-options.m4 b/make/autoconf/jdk-options.m4
index 2cbdf74ae..a858c5e7e 100644
--- a/make/autoconf/jdk-options.m4
+++ b/make/autoconf/jdk-options.m4
@@ -345,6 +345,27 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_DEBUG_SYMBOLS],
   AC_SUBST(SHIP_DEBUG_SYMBOLS)
 ])
 
+###############################################################################
+#
+# Enable or disable the kae crypto implementation
+#
+AC_DEFUN_ONCE([JDKOPT_DETECT_KAE],
+[
+  AC_ARG_ENABLE(kae, [AS_HELP_STRING([--enable-kae],
+      [enable KAE support on aarch64 @<:@disabled@:>@])],
+      [ENABLE_KAE="true"], [ENABLE_KAE="false"])
+  AC_MSG_CHECKING([if kae has been enabled])
+  if test "x$enable_kae" = "xyes"; then
+      AC_MSG_RESULT([yes])
+  elif test "x$enable_kae" = "x" || test "x$enable_kae" = "xno"; then
+      AC_MSG_RESULT([no])
+  else
+      AC_MSG_ERROR([Invalid value for --enable-kae: $enable_kae])
+  fi
+
+  AC_SUBST(ENABLE_KAE)
+])
+
 ################################################################################
 #
 # Native and Java code coverage
diff --git a/make/autoconf/spec.gmk.in b/make/autoconf/spec.gmk.in
index f6def153c..8336b287a 100644
--- a/make/autoconf/spec.gmk.in
+++ b/make/autoconf/spec.gmk.in
@@ -804,6 +804,7 @@ TAR_INCLUDE_PARAM:=@TAR_INCLUDE_PARAM@
 TAR_SUPPORTS_TRANSFORM:=@TAR_SUPPORTS_TRANSFORM@
 
 # Build setup
+ENABLE_KAE:=@ENABLE_KAE@
 USE_EXTERNAL_LIBJPEG:=@USE_EXTERNAL_LIBJPEG@
 USE_EXTERNAL_LIBGIF:=@USE_EXTERNAL_LIBGIF@
 USE_EXTERNAL_LIBZ:=@USE_EXTERNAL_LIBZ@
diff --git a/make/common/Modules.gmk b/make/common/Modules.gmk
index 0eb0fb2dd..c3c6a1bf4 100644
--- a/make/common/Modules.gmk
+++ b/make/common/Modules.gmk
@@ -312,6 +312,19 @@ define ReadImportMetaData
       $$(eval $$(call ReadSingleImportMetaData, $$m)))
 endef
 
+ifeq ($(ENABLE_KAE), true)
+  ifeq ($(OPENJDK_TARGET_CPU_ARCH), aarch64)
+    PLATFORM_MODULES += jdk.crypto.kaeprovider
+  endif
+endif
+
+################################################################################
+# Filter out kae specific modules if kae is disabled or cpu is not aarch64
+
+ifneq ($(ENABLE_KAE)-$(OPENJDK_TARGET_CPU_ARCH), true-aarch64)
+  MODULES_FILTER += jdk.crypto.kaeprovider
+endif
+
 ################################################################################
 
 endif # _MODULES_GMK
diff --git a/make/conf/module-loader-map.conf b/make/conf/module-loader-map.conf
index 2c95b8570..881a68d5a 100644
--- a/make/conf/module-loader-map.conf
+++ b/make/conf/module-loader-map.conf
@@ -77,6 +77,7 @@ PLATFORM_MODULES= \
     jdk.accessibility \
     jdk.charsets \
     jdk.crypto.cryptoki \
+    jdk.crypto.kaeprovide \
     jdk.crypto.ec \
     jdk.dynalink \
     jdk.httpserver \
diff --git a/make/ide/netbeans/hotspot/nbproject/configurations.xml b/make/ide/netbeans/hotspot/nbproject/configurations.xml
index 4f64db4ec..29c5e668b 100644
--- a/make/ide/netbeans/hotspot/nbproject/configurations.xml
+++ b/make/ide/netbeans/hotspot/nbproject/configurations.xml
@@ -3,6 +3,110 @@
   <logicalFolder name="root" displayName="root" projectFiles="true" kind="ROOT">
     <df root="../.." name="0">
     </df>
+    <df name="jdk.crypto.kaeprovider">
+      <df name="linux">
+        <df name="native">
+          <df name="libj2kae">
+            <in>kae_cipher_rsa.c</in>
+            <in>kae_digest.c</in>
+            <in>kae_exception.c</in>
+            <in>kae_exception.h</in>
+            <in>kae_hmac.c</in>
+            <in>kae_keyagreement_dh.c</in>
+            <in>kae_keyagreement_ecdh.c</in>
+            <in>kae_keypairgenerator_dh.c</in>
+            <in>kae_keypairgenerator_ec.c</in>
+            <in>kae_keypairgenerator_rsa.c</in>
+            <in>kae_provider.c</in>
+            <in>kae_signature_rsa.c</in>
+            <in>kae_symmetric_cipher.c</in>
+            <in>kae_util.c</in>
+            <in>kae_util.h</in>
+            <in>kae_log.h</in>
+          </df>
+        </df>
+      </df>
+    </df>
+    <item path="../../../../src/jdk.crypto.kaeprovider/linux/native/org/openeuler/security/openssl/kae_cipher_rsa.c"
+          ex="false"
+          tool="0"
+          flavor2="0">
+    </item>
+    <item path="../../../../src/jdk.crypto.kaeprovider/linux/native/org/openeuler/security/openssl/kae_digest.c"
+          ex="false"
+          tool="0"
+          flavor2="0">
+    </item>
+    <item path="../../../../src/jdk.crypto.kaeprovider/linux/native/org/openeuler/security/openssl/kae_exception.c"
+          ex="false"
+          tool="0"
+          flavor2="0">
+    </item>
+    <item path="../../../../src/jdk.crypto.kaeprovider/linux/native/org/openeuler/security/openssl/kae_exception.h"
+          ex="false"
+          tool="3"
+          flavor2="0">
+    </item>
+    <item path="../../../../src/jdk.crypto.kaeprovider/linux/native/org/openeuler/security/openssl/kae_hmac.c"
+          ex="false"
+          tool="0"
+          flavor2="0">
+    </item>
+    <item path="../../../../src/jdk.crypto.kaeprovider/linux/native/org/openeuler/security/openssl/kae_keyagreement_dh.c"
+          ex="false"
+          tool="0"
+          flavor2="0">
+    </item>
+    <item path="../../../../src/jdk.crypto.kaeprovider/linux/native/org/openeuler/security/openssl/kae_keyagreement_ecdh.c"
+          ex="false"
+          tool="0"
+          flavor2="0">
+    </item>
+    <item path="../../../../src/jdk.crypto.kaeprovider/linux/native/org/openeuler/security/openssl/kae_keypairgenerator_dh.c"
+          ex="false"
+          tool="0"
+          flavor2="0">
+    </item>
+    <item path="../../../../src/jdk.crypto.kaeprovider/linux/native/org/openeuler/security/openssl/kae_keypairgenerator_ec.c"
+          ex="false"
+          tool="0"
+          flavor2="0">
+    </item>
+    <item path="../../../../src/jdk.crypto.kaeprovider/linux/native/org/openeuler/security/openssl/kae_keypairgenerator_rsa.c"
+          ex="false"
+          tool="0"
+          flavor2="0">
+    </item>
+    <item path="../../../../src/jdk.crypto.kaeprovider/linux/native/org/openeuler/security/openssl/kae_provider.c"
+          ex="false"
+          tool="0"
+          flavor2="0">
+    </item>
+    <item path="../../../../src/jdk.crypto.kaeprovider/linux/native/org/openeuler/security/openssl/kae_signature_rsa.c"
+          ex="false"
+          tool="0"
+          flavor2="0">
+    </item>
+    <item path="../../../../src/jdk.crypto.kaeprovider/linux/native/org/openeuler/security/openssl/kae_symmetric_cipher.c"
+          ex="false"
+          tool="0"
+          flavor2="0">
+    </item>
+    <item path="../../../../src/jdk.crypto.kaeprovider/linux/native/org/openeuler/security/openssl/kae_util.c"
+          ex="false"
+          tool="0"
+          flavor2="0">
+    </item>
+    <item path="../../../../src/jdk.crypto.kaeprovider/linux/native/org/openeuler/security/openssl/kae_util.h"
+          ex="false"
+          tool="3"
+          flavor2="0">
+    </item>
+    <item path="../../../../src/jdk.crypto.kaeprovider/linux/native/org/openeuler/security/openssl/kae_log.h"
+          ex="false"
+          tool="3"
+          flavor2="0">
+    </item>
     <logicalFolder name="ExternalFiles"
                    displayName="Important Files"
                    projectFiles="false"
diff --git a/make/modules/jdk.crypto.kaeprovider/Copy.gmk b/make/modules/jdk.crypto.kaeprovider/Copy.gmk
new file mode 100644
index 000000000..7b072952a
--- /dev/null
+++ b/make/modules/jdk.crypto.kaeprovider/Copy.gmk
@@ -0,0 +1,46 @@
+#
+# Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code 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
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+include CopyCommon.gmk
+
+################################################################################
+
+ifeq ($(ENABLE_KAE), true)
+  ifeq ($(OPENJDK_TARGET_CPU_ARCH), aarch64)
+
+    KAEPROVIDER_CONF_SRC := $(TOPDIR)/src/jdk.crypto.kaeprovider/linux/conf/security/kaeprovider.conf
+    KAEPROVIDER_CONF_DST := $(CONF_DST_DIR)/kaeprovider.conf
+  
+    $(KAEPROVIDER_CONF_DST): $(KAEPROVIDER_CONF_SRC)
+	$(call install-file)
+  
+    TARGETS += $(KAEPROVIDER_CONF_DST)
+
+  endif
+endif
+
+
+################################################################################
diff --git a/make/modules/jdk.crypto.kaeprovider/Lib.gmk b/make/modules/jdk.crypto.kaeprovider/Lib.gmk
new file mode 100644
index 000000000..2b01e3ed4
--- /dev/null
+++ b/make/modules/jdk.crypto.kaeprovider/Lib.gmk
@@ -0,0 +1,46 @@
+#
+# Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code 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
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+include LibCommon.gmk
+
+################################################################################
+
+ifeq ($(ENABLE_KAE), true)
+  ifeq ($(OPENJDK_TARGET_CPU_ARCH), aarch64)
+    $(eval $(call SetupJdkLibrary, BUILD_LIBJ2KAE, \
+        NAME := j2kae, \
+        OPTIMIZATION := LOW, \
+        CFLAGS := $(CFLAGS_JDKLIB), \
+        CXXFLAGS := $(CXXFLAGS_JDKLIB), \
+        LDFLAGS := $(LDFLAGS_JDKLIB) \
+            $(call SET_SHARED_LIBRARY_ORIGIN), \
+        LIBS_unix := $(LIBDL) -lssl -lcrypto, \
+    ))
+
+    TARGETS += $(BUILD_LIBJ2KAE)
+  endif
+endif
+
+################################################################################
diff --git a/src/java.base/share/classes/module-info.java b/src/java.base/share/classes/module-info.java
index 06b141dcf..8d7441a2e 100644
--- a/src/java.base/share/classes/module-info.java
+++ b/src/java.base/share/classes/module-info.java
@@ -326,11 +326,13 @@ module java.base {
     exports sun.security.internal.interfaces to
         jdk.crypto.cryptoki;
     exports sun.security.internal.spec to
+        jdk.crypto.kaeprovider,
         jdk.crypto.cryptoki;
     exports sun.security.jca to
         java.smartcardio,
         jdk.crypto.ec,
         jdk.crypto.cryptoki,
+        jdk.crypto.kaeprovider,
         jdk.naming.dns;
     exports sun.security.pkcs to
         jdk.crypto.ec,
@@ -340,12 +342,14 @@ module java.base {
         java.security.jgss,
         jdk.crypto.cryptoki,
         jdk.crypto.ec,
+        jdk.crypto.kaeprovider,
         jdk.security.auth;
     exports sun.security.provider.certpath to
         java.naming,
         jdk.jartool;
     exports sun.security.rsa to
-        jdk.crypto.cryptoki;
+        jdk.crypto.cryptoki,
+        jdk.crypto.kaeprovider;
     exports sun.security.timestamp to
         jdk.jartool;
     exports sun.security.tools to
@@ -360,6 +364,7 @@ module java.base {
         java.xml.crypto,
         jdk.crypto.ec,
         jdk.crypto.cryptoki,
+        jdk.crypto.kaeprovider,
         jdk.jartool,
         jdk.security.auth,
         jdk.security.jgss;
@@ -370,6 +375,7 @@ module java.base {
     exports sun.security.x509 to
         jdk.crypto.ec,
         jdk.crypto.cryptoki,
+        jdk.crypto.kaeprovider,
         jdk.jartool;
     exports sun.security.validator to
         jdk.jartool;
diff --git a/src/java.base/share/lib/security/default.policy b/src/java.base/share/lib/security/default.policy
index 86d451477..0243a4497 100644
--- a/src/java.base/share/lib/security/default.policy
+++ b/src/java.base/share/lib/security/default.policy
@@ -136,6 +136,11 @@ grant codeBase "jrt:/jdk.crypto.ec" {
     permission java.security.SecurityPermission "removeProviderProperty.SunEC";
 };
 
+grant codeBase "jrt:/jdk.crypto.kaeprovider" {
+    permission java.lang.RuntimePermission
+                   "accessClassInPackage.sun.security.*";
+};
+
 grant codeBase "jrt:/jdk.crypto.cryptoki" {
     permission java.lang.RuntimePermission
                    "accessClassInPackage.com.sun.crypto.provider";
diff --git a/src/jdk.crypto.ec/share/classes/module-info.java b/src/jdk.crypto.ec/share/classes/module-info.java
index 9ba6e6195..67bb6e00e 100644
--- a/src/jdk.crypto.ec/share/classes/module-info.java
+++ b/src/jdk.crypto.ec/share/classes/module-info.java
@@ -32,5 +32,11 @@
  * @since 9
  */
 module jdk.crypto.ec {
+    exports sun.security.ec to
+        jdk.crypto.kaeprovider;
+
+    opens sun.security.ec to
+        jdk.crypto.kaeprovider;
+
     provides java.security.Provider with sun.security.ec.SunEC;
 }
diff --git a/src/jdk.crypto.kaeprovider/linux/classes/module-info.java b/src/jdk.crypto.kaeprovider/linux/classes/module-info.java
new file mode 100644
index 000000000..802ac8960
--- /dev/null
+++ b/src/jdk.crypto.kaeprovider/linux/classes/module-info.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+* Provides the implementation of KAEProvider.
+*
+* @provides java.security.Provider
+* @moduleGraph
+* @since 11
+*/
+module jdk.crypto.kaeprovider {
+    // Depends on SunEC provider for EC related functionality
+    requires jdk.crypto.ec;
+
+    exports org.openeuler.security.openssl to java.base;
+    provides java.security.Provider with org.openeuler.security.openssl.KAEProvider;
+}
diff --git a/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEAESCipher.java b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEAESCipher.java
new file mode 100644
index 000000000..b61861c94
--- /dev/null
+++ b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEAESCipher.java
@@ -0,0 +1,365 @@
+/*
+ * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.openeuler.security.openssl;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.Key;
+import java.util.Locale;
+
+import javax.crypto.NoSuchPaddingException;
+
+/*
+ * This class currently supports:
+ * - AES/ECB/NOPADDING
+ * - AES/ECB/PKCS5PADDING
+ * - AES/CBC/NOPADDING
+ * - AES/CBC/PKCS5PADDING
+ * - AES/CTR/NOPADDING
+ * - AES/GCM/NOPADDING
+ */
+abstract class KAEAESCipher extends KAESymmetricCipherBase {
+
+    public static class Aes extends KAEAESCipher {
+        public Aes(Mode mode, Padding padding) {
+            super(mode, padding, -1);
+        }
+
+        public static class Cbc extends Aes {
+            public Cbc(Padding padding) {
+                super(Mode.CBC, padding);
+            }
+            public static class NoPadding extends Cbc {
+                public NoPadding() {
+                    super(Padding.NOPADDING);
+                }
+            }
+            public static class PKCS5Padding extends Cbc {
+                public PKCS5Padding() {
+                    super(Padding.PKCS5PADDING);
+                }
+            }
+        }
+
+        public static class Ecb extends Aes {
+            public Ecb(Padding padding) {
+                super(Mode.ECB, padding);
+            }
+            public static class NoPadding extends Ecb {
+                public NoPadding() {
+                    super(Padding.NOPADDING);
+                }
+            }
+            public static class PKCS5Padding extends Ecb {
+                public PKCS5Padding() {
+                    super(Padding.PKCS5PADDING);
+                }
+            }
+        }
+
+        public static class Ctr extends Aes {
+            public Ctr(Padding padding) {
+                super(Mode.CTR, padding);
+            }
+            public static class NoPadding extends Ctr {
+                public NoPadding() {
+                    super(Padding.NOPADDING);
+                }
+            }
+        }
+
+        public static class Gcm extends Aes {
+            public Gcm(Padding padding) {
+                super(Mode.GCM, padding);
+            }
+            public static class NoPadding extends Gcm {
+                public NoPadding() {
+                    super(Padding.NOPADDING);
+                }
+            }
+        }
+    }
+
+    public static class Aes_128 extends KAEAESCipher {
+        public Aes_128(Mode mode, Padding padding) {
+            super(mode, padding, 16);
+        }
+
+        public static class Cbc extends Aes_128 {
+            public Cbc(Padding padding) {
+                super(Mode.CBC, padding);
+            }
+            public static class NoPadding extends Cbc {
+                public NoPadding() {
+                    super(Padding.NOPADDING);
+                }
+            }
+            public static class PKCS5Padding extends Cbc {
+                public PKCS5Padding() {
+                    super(Padding.PKCS5PADDING);
+                }
+            }
+        }
+
+        public static class Ecb extends Aes_128 {
+            public Ecb(Padding padding) {
+                super(Mode.ECB, padding);
+            }
+            public static class NoPadding extends Ecb {
+                public NoPadding() {
+                    super(Padding.NOPADDING);
+                }
+            }
+            public static class PKCS5Padding extends Ecb {
+                public PKCS5Padding() {
+                    super(Padding.PKCS5PADDING);
+                }
+            }
+        }
+
+        public static class Ctr extends Aes_128 {
+            public Ctr(Padding padding) {
+                super(Mode.CTR, padding);
+            }
+            public static class NoPadding extends Ctr {
+                public NoPadding() {
+                    super(Padding.NOPADDING);
+                }
+            }
+        }
+
+        public static class Gcm extends Aes_128 {
+            public Gcm(Padding padding) {
+                super(Mode.GCM, padding);
+            }
+            public static class NoPadding extends Gcm {
+                public NoPadding() {
+                    super(Padding.NOPADDING);
+                }
+            }
+        }
+    }
+
+    public static class Aes_192 extends KAEAESCipher {
+        public Aes_192(Mode mode, Padding padding) {
+            super(mode, padding, 24);
+        }
+
+        public static class Cbc extends Aes_192 {
+            public Cbc(Padding padding) {
+                super(Mode.CBC, padding);
+            }
+            public static class NoPadding extends Cbc {
+                public NoPadding() {
+                    super(Padding.NOPADDING);
+                }
+            }
+            public static class PKCS5Padding extends Cbc {
+                public PKCS5Padding() {
+                    super(Padding.PKCS5PADDING);
+                }
+            }
+        }
+
+        public static class Ecb extends Aes_192 {
+            public Ecb(Padding padding) {
+                super(Mode.ECB, padding);
+            }
+            public static class NoPadding extends Ecb {
+                public NoPadding() {
+                    super(Padding.NOPADDING);
+                }
+            }
+            public static class PKCS5Padding extends Ecb {
+                public PKCS5Padding() {
+                    super(Padding.PKCS5PADDING);
+                }
+            }
+        }
+
+        public static class Ctr extends Aes_192 {
+            public Ctr(Padding padding) {
+                super(Mode.CTR, padding);
+            }
+            public static class NoPadding extends Ctr {
+                public NoPadding() {
+                    super(Padding.NOPADDING);
+                }
+            }
+        }
+
+        public static class Gcm extends Aes_192 {
+            public Gcm(Padding padding) {
+                super(Mode.GCM, padding);
+            }
+            public static class NoPadding extends Gcm {
+                public NoPadding() {
+                    super(Padding.NOPADDING);
+                }
+            }
+        }
+    }
+
+    public static class Aes_256 extends KAEAESCipher {
+        public Aes_256(Mode mode, Padding padding) {
+            super(mode, padding, 32);
+        }
+
+        public static class Cbc extends Aes_256 {
+            public Cbc(Padding padding) {
+                super(Mode.CBC, padding);
+            }
+            public static class NoPadding extends Cbc {
+                public NoPadding() {
+                    super(Padding.NOPADDING);
+                }
+            }
+            public static class PKCS5Padding extends Cbc {
+                public PKCS5Padding() {
+                    super(Padding.PKCS5PADDING);
+                }
+            }
+        }
+
+        public static class Ecb extends Aes_256 {
+            public Ecb(Padding padding) {
+                super(Mode.ECB, padding);
+            }
+            public static class NoPadding extends Ecb {
+                public NoPadding() {
+                    super(Padding.NOPADDING);
+                }
+            }
+            public static class PKCS5Padding extends Ecb {
+                public PKCS5Padding() {
+                    super(Padding.PKCS5PADDING);
+                }
+            }
+        }
+
+        public static class Ctr extends Aes_256 {
+            public Ctr(Padding padding) {
+                super(Mode.CTR, padding);
+            }
+            public static class NoPadding extends Ctr {
+                public NoPadding() {
+                    super(Padding.NOPADDING);
+                }
+            }
+        }
+
+        public static class Gcm extends Aes_256 {
+            public Gcm(Padding padding) {
+                super(Mode.GCM, padding);
+            }
+            public static class NoPadding extends Gcm {
+                public NoPadding() {
+                    super(Padding.NOPADDING);
+                }
+            }
+        }
+    }
+
+    KAEAESCipher(Mode mode, Padding padding, int fixedKeySize) {
+        super(mode, padding, fixedKeySize, "AES");
+    }
+
+    protected void checkKey(Key key) throws InvalidKeyException {
+        if (key == null || key.getEncoded() == null) {
+            throw new InvalidKeyException("Key cannot be null");
+        } else {
+            if (!keyAlgo.equalsIgnoreCase(key.getAlgorithm())) {
+                throw new InvalidKeyException("Key algorithm must be " + keyAlgo);
+            }
+            int keyLen = key.getEncoded().length;
+            if (fixedKeySize == -1) {
+                if (keyLen != 16 && keyLen != 24 & keyLen != 32) {
+                    throw new InvalidKeyException("Key size is not valid. Got key length of: " + keyLen);
+                }
+            } else {
+                if (keyLen != fixedKeySize) {
+                    throw new InvalidKeyException("Only " + fixedKeySize + "-byte keys are accepted. Got: " + keyLen);
+                }
+            }
+        }
+    }
+
+    protected String getCipherName(int keyLength, Mode mode) {
+        return "aes-" + keyLength + "-" + mode.toString().toLowerCase(Locale.US);
+    }
+
+    @Override
+    protected void engineSetMode(String modeStr) throws NoSuchAlgorithmException {
+        if (modeStr == null) {
+            throw new NoSuchAlgorithmException("null mode");
+        }
+
+        if (modeStr.equalsIgnoreCase("ECB")) {
+            mode = Mode.ECB;
+        } else if (modeStr.equalsIgnoreCase("CBC")) {
+            mode = Mode.CBC;
+        } else if (modeStr.equalsIgnoreCase("CTR")) {
+            mode = Mode.CTR;
+        } else if (modeStr.equalsIgnoreCase("GCM")) {
+            mode = Mode.GCM;
+        } else {
+            throw new NoSuchAlgorithmException("Unsupported mode " + mode);
+        }
+    }
+
+    @Override
+    protected void engineSetPadding(String paddingStr) throws NoSuchPaddingException {
+        if (paddingStr == null) {
+            throw new NoSuchPaddingException("null padding");
+        }
+        if (paddingStr.equalsIgnoreCase("PKCS7PADDING")) {
+            paddingStr = "PKCS5Padding";
+        }
+
+        // GCM has no Padding, pkcs5-> nopadding in sunjce
+        if (mode == Mode.GCM) {
+            this.padding = Padding.NOPADDING;
+        } else if (paddingStr.equalsIgnoreCase("NOPADDING")) {
+            this.padding = Padding.NOPADDING;
+        } else if(paddingStr.equalsIgnoreCase("PKCS5PADDING")) {
+            if (mode == Mode.CTR) {
+                throw new NoSuchPaddingException("PKCS#5 padding not supported with CTR mode");
+            }
+            this.padding = Padding.PKCS5PADDING;
+        } else {
+           throw new NoSuchPaddingException("Unsupported padding " + paddingStr);
+        }
+    }
+
+    protected void checkIvBytes(byte[] ivBytes) throws InvalidAlgorithmParameterException {
+        if ((ivBytes == null) || (ivBytes.length != blockSize)) {
+            throw new InvalidAlgorithmParameterException("Wrong IV length: must be " + blockSize + " bytes long.");
+        }
+    }
+}
+
diff --git a/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEConfig.java b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEConfig.java
new file mode 100644
index 000000000..a4eb57770
--- /dev/null
+++ b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEConfig.java
@@ -0,0 +1,393 @@
+/*
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.openeuler.security.openssl;
+
+import sun.security.util.Debug;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+public class KAEConfig {
+  private static final Debug kaeDebug = Debug.getInstance("kae");
+
+  // these property names indicates whether each algorithm uses KAEProvider
+  private static final String[] useKaeProviderPropertyNames = new String[]{
+          "kae.md5",
+          "kae.sha256",
+          "kae.sha384",
+          "kae.sm3",
+          "kae.aes",
+          "kae.sm4",
+          "kae.hmac",
+          "kae.rsa",
+          "kae.dh",
+          "kae.ec"
+  };
+
+  // these property names indicate whether KAE hardware acceleration is enabled for each algorithm
+  private static final String[] useKaeEnginePropertyNames = new String[]{
+          "kae.digest.useKaeEngine",
+          "kae.aes.useKaeEngine",
+          "kae.sm4.useKaeEngine",
+          "kae.hmac.useKaeEngine",
+          "kae.rsa.useKaeEngine",
+          "kae.dh.useKaeEngine",
+          "kae.ec.useKaeEngine"
+  };
+
+  // algorithm names
+  private static final String[] algorithmNames = new String[]{
+          "md5",
+          "sha256",
+          "sha384",
+          "sm3",
+          "aes-128-ecb",
+          "aes-128-cbc",
+          "aes-128-ctr",
+          "aes-128-gcm",
+          "aes-192-ecb",
+          "aes-192-cbc",
+          "aes-192-ctr",
+          "aes-192-gcm",
+          "aes-256-ecb",
+          "aes-256-cbc",
+          "aes-256-ctr",
+          "aes-256-gcm",
+          "sm4-ecb",
+          "sm4-cbc",
+          "sm4-ctr",
+          "sm4-ofb",
+          "hmac-md5",
+          "hmac-sha1",
+          "hmac-sha224",
+          "hmac-sha256",
+          "hmac-sha384",
+          "hmac-sha512",
+          "rsa",
+          "dh",
+          "ec"
+  };
+
+  // algorithm name and algorithm index mapping
+  private static final Map<String, Integer> algorithmNameIndexMap = new HashMap<>();
+
+  // algorithm name and algorithm category index mapping
+  private static final Map<String, Integer> algorithmNameCategoryMap = new HashMap<>();
+
+  // whether use KAEProvider for each algorithm
+  private static final boolean[] useKaeProviderFlags = new boolean[algorithmNames.length];
+
+  // whether use KAEProvider for each category algorithm
+  private static final Map<String, Boolean> useKaeProviderCategoryMap = new HashMap<>();
+
+  // whether enable the Kunpeng acceleration engine for each algorithm
+  private static final boolean[] useKaeEngineFlags = new boolean[algorithmNames.length];
+
+  // The kaeprovider.cnf properties
+  private static Properties props;
+
+  private KAEConfig() {
+
+  }
+
+  static {
+    kaeConfigInit();
+  }
+
+  @SuppressWarnings("removal")
+  private static void kaeConfigInit() {
+    AccessController.doPrivileged(new PrivilegedAction<Void>() {
+      public Void run() {
+        initialize();
+        return null;
+      }
+    });
+  }
+
+  private static File kaePropFile(String filename) {
+    String sep = File.separator;
+    String defaultKaeConf = System.getProperty("java.home") + sep + "conf" + sep + filename;
+    String kaeConf = System.getProperty("kae.conf", defaultKaeConf);
+    return new File(kaeConf);
+  }
+
+  private static void initialize() {
+    initProperties();
+    initAlgorithmNameMap();
+    initUseKaeProviderFlags();
+    initUseKaeEngineFlags();
+  }
+
+  private static void initProperties() {
+    props = new Properties();
+    File propFile = kaePropFile("kaeprovider.conf");
+    if (propFile.exists()) {
+      InputStream is = null;
+      try {
+        FileInputStream fis = new FileInputStream(propFile);
+        is = new BufferedInputStream(fis);
+        props.load(is);
+
+        if (kaeDebug != null) {
+          kaeDebug.println("reading kae properties file: " +
+                  propFile);
+        }
+      } catch (IOException e) {
+        if (kaeDebug != null) {
+          kaeDebug.println("unable to load kae properties from " +
+                  propFile);
+          e.printStackTrace();
+        }
+      } finally {
+        if (is != null) {
+          try {
+            is.close();
+          } catch (IOException ioe) {
+            if (kaeDebug != null) {
+              kaeDebug.println("unable to close input stream");
+            }
+          }
+        }
+      }
+    } else {
+      if (kaeDebug != null) {
+        kaeDebug.println("not found kae properties file: " +
+                propFile);
+      }
+    }
+  }
+
+  public static Boolean useKaeProvider(String key) {
+    return useKaeProviderCategoryMap.getOrDefault(key, Boolean.TRUE);
+  }
+
+  private static void initUseKaeProviderFlags() {
+    boolean[] categoryFlagsForProvider = new boolean[useKaeProviderPropertyNames.length];
+    Arrays.fill(categoryFlagsForProvider, true);
+    for (int i = 0; i < useKaeProviderPropertyNames.length; i++) {
+      String configValue = privilegedGetOverridable(useKaeProviderPropertyNames[i]);
+      if (configValue != null) {
+        categoryFlagsForProvider[i] = Boolean.parseBoolean(configValue);
+      }
+      useKaeProviderCategoryMap.put(useKaeProviderPropertyNames[i], categoryFlagsForProvider[i]);
+    }
+    int offset = useKaeProviderPropertyNames.length - useKaeEnginePropertyNames.length;
+    int digestAlgorithmLen = offset + 1;
+    // digest
+    System.arraycopy(categoryFlagsForProvider, 0, useKaeProviderFlags, 0, digestAlgorithmLen);
+
+    // non-digest
+    for (int i = digestAlgorithmLen; i < useKaeProviderFlags.length; i++) {
+      Integer algorithmCategoryIndex = algorithmNameCategoryMap.get(algorithmNames[i]);
+      if (categoryFlagsForProvider[algorithmCategoryIndex + offset]) {
+        useKaeProviderFlags[i] = true;
+      }
+    }
+
+    if (kaeDebug != null) {
+      kaeDebug.println("useKaeProviderPropertyNames: ");
+      for (int i = 0; i < categoryFlagsForProvider.length; i++) {
+        kaeDebug.println(useKaeProviderPropertyNames[i] + "=" + categoryFlagsForProvider[i]);
+      }
+
+      kaeDebug.println("useKaeProviderFlags: ");
+      for (int i = 0; i < useKaeProviderFlags.length; i++) {
+        kaeDebug.println(algorithmNames[i] + "=" + useKaeProviderFlags[i]);
+      }
+    }
+  }
+
+  public static boolean[] getUseKaeProviderFlags() {
+    return useKaeProviderFlags;
+  }
+
+  private static void initUseKaeEngineFlags() {
+    boolean[] categoryFlagsForEngine = new boolean[]{
+            true,  // digest
+            false, // aes
+            true,  // sm4
+            false, // hmac
+            true,  // rsa
+            true,  // dh
+            false  // ec
+    };
+    for (int i = 0; i < useKaeEnginePropertyNames.length; i++) {
+      String configValue = privilegedGetOverridable(useKaeEnginePropertyNames[i]);
+      if (configValue != null) {
+        categoryFlagsForEngine[i] = Boolean.parseBoolean(configValue);
+      }
+    }
+
+    // EC algorithm currently does not support KAE hardware acceleration, temporarily use openssl soft calculation.
+    categoryFlagsForEngine[useKaeEnginePropertyNames.length - 1] = false;
+
+    for (int i = 0; i < useKaeEngineFlags.length; i++) {
+      Integer algorithmCategoryIndex = algorithmNameCategoryMap.get(algorithmNames[i]);
+      if (categoryFlagsForEngine[algorithmCategoryIndex]) {
+        useKaeEngineFlags[i] = true;
+      }
+    }
+
+    String[] disabledAlgorithms = getDisabledAlgorithms();
+    for (String disabledAlgorithm : disabledAlgorithms) {
+      Integer algorithmIndex = algorithmNameIndexMap.get(disabledAlgorithm);
+      if (algorithmIndex != null) {
+        useKaeEngineFlags[algorithmIndex] = false;
+      }
+    }
+    if (kaeDebug != null) {
+      kaeDebug.println("useKaeEnginePropertyNames: ");
+      for (int i = 0; i < categoryFlagsForEngine.length; i++) {
+        kaeDebug.println(useKaeEnginePropertyNames[i] + "=" + categoryFlagsForEngine[i]);
+      }
+
+      kaeDebug.println("disabledAlgorithms: ");
+      for (int i = 0; i < disabledAlgorithms.length; i++) {
+        kaeDebug.println(disabledAlgorithms[i]);
+      }
+
+      kaeDebug.println("useKaeEngineFlags: ");
+      for (int i = 0; i < useKaeEngineFlags.length; i++) {
+        kaeDebug.println(algorithmNames[i] + "=" + useKaeEngineFlags[i]);
+      }
+    }
+  }
+
+  public static boolean[] getUseKaeEngineFlags() {
+    return useKaeEngineFlags;
+  }
+
+  private static void initAlgorithmNameIndexMap() {
+    for (int i = 0; i < algorithmNames.length; i++) {
+      algorithmNameIndexMap.put(algorithmNames[i], i);
+    }
+  }
+
+  /*
+   * 0 : digest
+   * 1 : aes
+   * 2 : sm4
+   * 3 : hmac
+   * 4 : rsa
+   * 5 : dh
+   * 6 : ec
+   */
+  private static void initAlgorithmNameCategoryMap() {
+    algorithmNameCategoryMap.put("md5", 0);
+    algorithmNameCategoryMap.put("sha256", 0);
+    algorithmNameCategoryMap.put("sha384", 0);
+    algorithmNameCategoryMap.put("sm3", 0);
+    algorithmNameCategoryMap.put("aes-128-ecb", 1);
+    algorithmNameCategoryMap.put("aes-128-cbc", 1);
+    algorithmNameCategoryMap.put("aes-128-ctr", 1);
+    algorithmNameCategoryMap.put("aes-128-gcm", 1);
+    algorithmNameCategoryMap.put("aes-192-ecb", 1);
+    algorithmNameCategoryMap.put("aes-192-cbc", 1);
+    algorithmNameCategoryMap.put("aes-192-ctr", 1);
+    algorithmNameCategoryMap.put("aes-192-gcm", 1);
+    algorithmNameCategoryMap.put("aes-256-ecb", 1);
+    algorithmNameCategoryMap.put("aes-256-cbc", 1);
+    algorithmNameCategoryMap.put("aes-256-ctr", 1);
+    algorithmNameCategoryMap.put("aes-256-gcm", 1);
+    algorithmNameCategoryMap.put("sm4-ecb", 2);
+    algorithmNameCategoryMap.put("sm4-cbc", 2);
+    algorithmNameCategoryMap.put("sm4-ctr", 2);
+    algorithmNameCategoryMap.put("sm4-ofb", 2);
+    algorithmNameCategoryMap.put("hmac-md5", 3);
+    algorithmNameCategoryMap.put("hmac-sha1", 3);
+    algorithmNameCategoryMap.put("hmac-sha224", 3);
+    algorithmNameCategoryMap.put("hmac-sha256", 3);
+    algorithmNameCategoryMap.put("hmac-sha384", 3);
+    algorithmNameCategoryMap.put("hmac-sha512", 3);
+    algorithmNameCategoryMap.put("rsa", 4);
+    algorithmNameCategoryMap.put("dh", 5);
+    algorithmNameCategoryMap.put("ec", 6);
+  }
+
+  private static void initAlgorithmNameMap() {
+    initAlgorithmNameIndexMap();
+    initAlgorithmNameCategoryMap();
+  }
+
+  private static String[] getDisabledAlgorithms() {
+    String disabledAlgorithms = privilegedGetOverridable("kae.engine.disabledAlgorithms",
+            "sha256,sha384");
+    return disabledAlgorithms.replaceAll(" ", "").split("\\,");
+  }
+
+  @SuppressWarnings("removal")
+  public static String privilegedGetProperty(String key) {
+    if (System.getSecurityManager() == null) {
+      return getProperty(key);
+    } else {
+      return AccessController.doPrivileged((PrivilegedAction<String>) () -> getOverridableProperty(key));
+    }
+  }
+
+  @SuppressWarnings("removal")
+  public static String privilegedGetOverridable(String key) {
+    if (System.getSecurityManager() == null) {
+      return getOverridableProperty(key);
+    } else {
+      return AccessController.doPrivileged((PrivilegedAction<String>) () -> getOverridableProperty(key));
+    }
+  }
+
+  public static String privilegedGetOverridable(String key, String defaultValue) {
+    String val = privilegedGetOverridable(key);
+    return (val == null) ? defaultValue : val;
+  }
+
+  private static String getProperty(String key) {
+    String val = props.getProperty(key);
+    if (val != null)
+      val = val.trim();
+    return val;
+  }
+
+  private static String getOverridableProperty(String key) {
+    String val = System.getProperty(key);
+    if (val == null) {
+      return getProperty(key);
+    } else {
+      return val;
+    }
+  }
+
+  public static String getAlgorithmName(int index) {
+    if (index < 0 || index >= algorithmNames.length) {
+      throw new IndexOutOfBoundsException();
+    }
+    return algorithmNames[index];
+  }
+}
diff --git a/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEDHKeyAgreement.java b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEDHKeyAgreement.java
new file mode 100644
index 000000000..541df07d6
--- /dev/null
+++ b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEDHKeyAgreement.java
@@ -0,0 +1,289 @@
+/*
+ * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.openeuler.security.openssl;
+
+import sun.security.util.KeyUtil;
+import java.math.BigInteger;
+import java.security.KeyFactory;
+import java.security.InvalidKeyException;
+import java.security.SecureRandom;
+import java.security.Key;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.NoSuchAlgorithmException;
+import java.security.AccessController;
+import java.security.ProviderException;
+import java.security.PrivilegedAction;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.AlgorithmParameterSpec;
+import javax.crypto.KeyAgreementSpi;
+import javax.crypto.SecretKey;
+import javax.crypto.ShortBufferException;
+import javax.crypto.interfaces.DHPrivateKey;
+import javax.crypto.interfaces.DHPublicKey;
+import javax.crypto.spec.DHParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+import javax.crypto.spec.DHPublicKeySpec;
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.DESedeKeySpec;
+import javax.crypto.spec.DESKeySpec;
+
+public class KAEDHKeyAgreement extends KeyAgreementSpi {
+    private boolean generateSecret = false;
+    private BigInteger p;
+    private BigInteger g;
+    private BigInteger x;
+    private BigInteger y;
+    static final int[] AES_KEYSIZES = {16, 24, 32};
+    static final int BLOWFISH_MAX_KEYSIZE = 56;
+
+    private static class AllowKDF {
+        private static final boolean VALUE = getValue();
+
+	@SuppressWarnings("removal")
+        private static boolean getValue() {
+		return AccessController.doPrivileged(
+                    (PrivilegedAction<Boolean>)
+                            () -> Boolean.getBoolean("jdk.crypto.KeyAgreement.legacyKDF"));
+        }
+    }
+
+    public KAEDHKeyAgreement() {
+    }
+
+    @Override
+    protected void engineInit(Key key, SecureRandom random) throws InvalidKeyException {
+        try {
+            engineInit(key, null, random);
+        } catch (InvalidAlgorithmParameterException e) {
+            // never happens, because we did not pass any parameters
+        }
+    }
+
+    @Override
+    protected void engineInit(Key key, AlgorithmParameterSpec params,
+                              SecureRandom random)
+            throws InvalidKeyException, InvalidAlgorithmParameterException {
+
+        // ignore "random" parameter, because our implementation does not
+        // require any source of randomness
+        generateSecret = false;
+        p = null;
+        g = null;
+
+        if ((params != null) && !(params instanceof DHParameterSpec)) {
+            throw new InvalidAlgorithmParameterException("Diffie-Hellman parameters expected");
+        }
+
+        if (!(key instanceof DHPrivateKey)) {
+            throw new InvalidKeyException("Diffie-Hellman private key expected");
+        }
+
+        DHPrivateKey privateKey = (DHPrivateKey) key;
+
+        // check if private key parameters are compatible with
+        // initialized ones
+        if (params != null) {
+            p = ((DHParameterSpec) params).getP();
+            g = ((DHParameterSpec) params).getG();
+        }
+
+        BigInteger priv_p = privateKey.getParams().getP();
+        BigInteger priv_g = privateKey.getParams().getG();
+        if (p != null && priv_p != null && !(p.equals(priv_p))) {
+            throw new InvalidKeyException("Incompatible parameters");
+        }
+        if (g != null && priv_g != null && !(g.equals(priv_g))) {
+            throw new InvalidKeyException("Incompatible parameters");
+        }
+        if ((p == null && priv_p == null) ||
+                (g == null) && priv_g == null) {
+            throw new InvalidKeyException("Missing parameters");
+        }
+        p = priv_p;
+        g = priv_g;
+
+        // store the x value
+        x = privateKey.getX();
+    }
+
+    @Override
+    protected Key engineDoPhase(Key key, boolean lastPhase)
+            throws InvalidKeyException, IllegalStateException {
+        if (!(key instanceof DHPublicKey)) {
+            throw new InvalidKeyException("Diffie-Hellman public "
+                    + "expected");
+        }
+        DHPublicKey publicKey = (DHPublicKey) key;
+        if (p == null || g == null) {
+            throw new IllegalStateException("Not initialized");
+        }
+        BigInteger pub_p = publicKey.getParams().getP();
+        BigInteger pub_g = publicKey.getParams().getG();
+        if (pub_p != null && !(p.equals(pub_p))) {
+            throw new InvalidKeyException("Incompatible parameters");
+        }
+        if (pub_g != null && !(g.equals(pub_g))) {
+            throw new InvalidKeyException("Incompatible parameters");
+        }
+        KeyUtil.validate(publicKey);
+        y = publicKey.getY();
+        generateSecret = true;
+        if (lastPhase == false) {
+            byte[] intermediate = engineGenerateSecret();
+            try {
+                KeyFactory fk = KeyFactory.getInstance("DH");
+                DHPublicKey newPublicKey = (DHPublicKey) fk.generatePublic(
+                        new DHPublicKeySpec(new BigInteger(1, intermediate), p, g));
+                return newPublicKey;
+            } catch (NoSuchAlgorithmException noalg) {
+                throw new ProviderException(noalg);
+            } catch (InvalidKeySpecException ikse) {
+                throw new ProviderException(ikse);
+            }
+        } else {
+            return null;
+        }
+    }
+
+    @Override
+    protected byte[] engineGenerateSecret()
+            throws IllegalStateException {
+        int expectedLen = (p.bitLength() + 7) >>> 3;
+        byte[] result = new byte[expectedLen];
+        try {
+            engineGenerateSecret(result, 0);
+        } catch (ShortBufferException shortBufferException) {
+            // should never happen since length are identical
+        }
+        return result;
+    }
+
+    @Override
+    protected int engineGenerateSecret(byte[] sharedSecret, int offset)
+            throws IllegalStateException, ShortBufferException {
+        if (!generateSecret) {
+            throw new IllegalStateException("Key agreement has not bee complated yet");
+        }
+        if (sharedSecret == null) {
+            throw new ShortBufferException("No buffer provided for shared secret");
+        }
+        BigInteger modulus = p;
+        int expectedLen = (modulus.bitLength() + 7) >>> 3;
+        if ((sharedSecret.length - offset) < expectedLen) {
+            throw new ShortBufferException("Buffer too short for shared secret");
+        }
+        generateSecret = false;
+        byte[] secret = nativeComputeKey(y.toByteArray(), x.toByteArray(),
+                p.toByteArray(), g.toByteArray(), modulus.bitLength());
+
+        if (secret.length == expectedLen) {
+            System.arraycopy(secret, 0, sharedSecret, offset,
+                    secret.length);
+        } else {
+            // Array too short, pad it w/ leading 0s
+            if (secret.length < expectedLen) {
+                System.arraycopy(secret, 0, sharedSecret,
+                        offset + (expectedLen - secret.length),
+                        secret.length);
+            } else {
+                // Array too long, check and trim off the excess
+                if ((secret.length == (expectedLen + 1)) && secret[0] == 0) {
+                    // ignore the leading sign byte
+                    System.arraycopy(secret, 1, sharedSecret, offset, expectedLen);
+                } else {
+                    throw new ProviderException("Generated secret is out-of-range");
+                }
+            }
+        }
+
+        return expectedLen;
+    }
+
+    @Override
+    protected SecretKey engineGenerateSecret(String algorithm)
+            throws IllegalStateException, NoSuchAlgorithmException, InvalidKeyException {
+        if (algorithm == null) {
+            throw new NoSuchAlgorithmException("null algorithm");
+        }
+
+        if (!algorithm.equalsIgnoreCase("TlsPremasterSecret") &&
+                !AllowKDF.VALUE) {
+
+            throw new NoSuchAlgorithmException("Unsupported secret key "
+                    + "algorithm: " + algorithm);
+        }
+
+        byte[] secret = engineGenerateSecret();
+        if (algorithm.equalsIgnoreCase("DES")) {
+            // DES
+            try {
+                SecretKeyFactory factory = SecretKeyFactory.getInstance("DES");
+                return factory.generateSecret(new DESKeySpec(secret));
+            } catch (InvalidKeySpecException e) {
+                throw new ProviderException("Generate DES Secret failed.", e);
+            }
+        } else if (algorithm.equalsIgnoreCase("DESede")
+                || algorithm.equalsIgnoreCase("TripleDES")) {
+            // Triple DES
+            try {
+                SecretKeyFactory factory = SecretKeyFactory.getInstance("DESede");
+                return factory.generateSecret(new DESedeKeySpec(secret));
+            } catch (InvalidKeySpecException e) {
+                throw new ProviderException("Generate DESede Secret failed.", e);
+            }
+        } else if (algorithm.equalsIgnoreCase("Blowfish")) {
+            // Blowfish
+            int keysize = secret.length;
+            if (keysize >= BLOWFISH_MAX_KEYSIZE)
+                keysize = BLOWFISH_MAX_KEYSIZE;
+            return new SecretKeySpec(secret, 0, keysize, "Blowfish");
+        } else if (algorithm.equalsIgnoreCase("AES")) {
+            int idx = AES_KEYSIZES.length - 1;
+            int keysize = secret.length;
+            SecretKeySpec secretKey = null;
+            while (secretKey == null && idx >= 0) {
+                if (keysize >= AES_KEYSIZES[idx]) {
+                    keysize = AES_KEYSIZES[idx];
+                    secretKey = new SecretKeySpec(secret, 0, keysize, "AES");
+                }
+                idx--;
+            }
+            if (secretKey == null) {
+                throw new InvalidKeyException("Key material is too short");
+            }
+            return secretKey;
+        } else if (algorithm.equals("TlsPremasterSecret")) {
+            // remove leading zero bytes per RFC 5246 Section 8.1.2
+            return new SecretKeySpec(
+                    KeyUtil.trimZeroes(secret), "TlsPremasterSecret");
+        } else {
+            throw new NoSuchAlgorithmException("Unsupported secret key "
+                    + "algorithm: " + algorithm);
+        }
+    }
+    protected native byte[] nativeComputeKey(byte[] y, byte[] x, byte[] p, byte[] g, int pSize);
+}
diff --git a/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEDHKeyPairGenerator.java b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEDHKeyPairGenerator.java
new file mode 100644
index 000000000..74134eef5
--- /dev/null
+++ b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEDHKeyPairGenerator.java
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.openeuler.security.openssl;
+
+import java.math.BigInteger;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.KeyPairGeneratorSpi;
+import java.security.SecureRandom;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.KeyPair;
+import java.security.NoSuchAlgorithmException;
+import java.security.InvalidParameterException;
+import java.security.GeneralSecurityException;
+import java.security.ProviderException;
+import java.security.KeyFactory;
+import java.security.spec.InvalidKeySpecException;
+import sun.security.jca.JCAUtil;
+import sun.security.provider.ParameterCache;
+import javax.crypto.spec.DHPublicKeySpec;
+import javax.crypto.spec.DHPrivateKeySpec;
+import javax.crypto.spec.DHParameterSpec;
+import javax.crypto.interfaces.DHPublicKey;
+import javax.crypto.interfaces.DHPrivateKey;
+
+import static sun.security.util.SecurityProviderConstants.DEF_DH_KEY_SIZE;
+
+public class KAEDHKeyPairGenerator
+        extends KeyPairGeneratorSpi {
+    private DHParameterSpec parameterSpec;
+    // The size in bits of the random exponent (private value)
+    private int pSize;
+    // The size in bits of the random exponent (private value)
+    private int lSize;
+    private SecureRandom random;
+
+    @SuppressWarnings("this-escape")
+    public KAEDHKeyPairGenerator() {
+        super();
+        initialize(DEF_DH_KEY_SIZE, null);
+    }
+
+    private static void checkKeySize(int keySize) {
+        if ((keySize < 512) || (keySize > 8192) || ((keySize & 0x3F) != 0)) {
+            throw new InvalidParameterException(
+                    "DH key size must be multiple of 64, and can only range " +
+                            "from 512 to 8192(inclusize).  " +
+                            "The specific key size " + keySize + " is not supported");
+        }
+    }
+    @Override
+    public void initialize(AlgorithmParameterSpec params, SecureRandom random)
+            throws InvalidAlgorithmParameterException {
+
+        if (!(params instanceof DHParameterSpec)){
+            throw new InvalidAlgorithmParameterException
+                    ("Inappropriate parameter type");
+        }
+
+        parameterSpec = (DHParameterSpec) params;
+        pSize = parameterSpec.getP().bitLength();
+
+        try {
+            checkKeySize(pSize);
+        } catch (InvalidParameterException e) {
+            throw new InvalidAlgorithmParameterException(e.getMessage());
+        }
+
+        // exponent size is optional, could be 0
+        lSize = parameterSpec.getL();
+
+        // Require exponentSize < primeSize
+        if ((lSize != 0) && (lSize > pSize)) {
+            throw new InvalidAlgorithmParameterException
+                    ("Exponent size must not be larger than modulus size");
+        }
+
+        this.random = random;
+    }
+
+    @Override
+    public void initialize(int keysize, SecureRandom random) {
+        checkKeySize(keysize);
+        this.parameterSpec = ParameterCache.getCachedDHParameterSpec(keysize);
+        if ((this.parameterSpec == null) && (keysize > 1024)) {
+            throw new InvalidParameterException("Unsupported " + keysize + "-bit DH parameter generation.");
+        }
+        this.pSize = keysize;
+        this.lSize = 0;
+        this.random = random;
+    }
+
+    @Override
+    public KeyPair generateKeyPair() {
+
+        if (random == null) {
+            random = JCAUtil.getSecureRandom();
+        }
+
+        if (parameterSpec == null) {
+            try {
+                parameterSpec = ParameterCache.getDHParameterSpec(pSize, random);
+            } catch (GeneralSecurityException e) {
+                // should never happen
+                throw new ProviderException(e);
+            }
+        }
+
+        BigInteger p = parameterSpec.getP();
+        BigInteger g = parameterSpec.getG();
+
+        if (lSize <= 0) {
+            lSize = pSize >> 1;
+            // use an exponent size of (pSize / 2) but at least 384 bits
+            if (lSize < 384) {
+                lSize = 384;
+            }
+        }
+        byte[][] keys;
+        try {
+            keys = nativeGenerateKeyPair(p.toByteArray(), g.toByteArray(), lSize);
+        } catch (Exception e){
+            throw new ProviderException("Invoke nativeGenerateKeyPair failed.", e);
+        }
+
+        // check keys
+        checkKeys(keys);
+
+        BigInteger pubKey = new BigInteger(keys[0]);
+        BigInteger priKey = new BigInteger(keys[1]);
+
+        try{
+            KeyFactory fk = KeyFactory.getInstance("DH");
+            DHPublicKey publicKey = (DHPublicKey)fk.generatePublic(new DHPublicKeySpec(pubKey, p , g));
+            DHPrivateKey privateKey = (DHPrivateKey)fk.generatePrivate(new DHPrivateKeySpec(priKey, p, g));
+            return new KeyPair(publicKey, privateKey);
+        } catch (NoSuchAlgorithmException noalg) {
+            throw new ProviderException(noalg);
+        } catch (InvalidKeySpecException ikse) {
+            throw new ProviderException(ikse);
+        }
+    }
+
+    private void checkKeys(byte[][] keys) {
+        if (keys == null) {
+            throw new ProviderException("Invalid keys, keys is null.");
+        }
+        // The keys needs to contain at least 2 byte arrays, which are public and private keys.
+        if (keys.length < 2) {
+            throw new ProviderException("Invalid keys, keys length is less than 2.");
+        }
+        for (int i = 0; i < keys.length; i++) {
+            if (keys[i] == null) {
+                throw new ProviderException("Invalid keys, keys[" + i + "]" + "is null.");
+            }
+        }
+    }
+
+    protected native static byte[][] nativeGenerateKeyPair(byte[] p, byte[] g, int lSize);
+}
diff --git a/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEDigest.java b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEDigest.java
new file mode 100644
index 000000000..aca5f4b29
--- /dev/null
+++ b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEDigest.java
@@ -0,0 +1,264 @@
+/*
+ * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.openeuler.security.openssl;
+
+import java.lang.ref.PhantomReference;
+import java.lang.ref.ReferenceQueue;
+import java.security.DigestException;
+import java.security.MessageDigestSpi;
+import java.security.ProviderException;
+import java.util.Set;
+import java.util.concurrent.ConcurrentSkipListSet;
+
+/**
+ * KAE Digest
+ */
+abstract class KAEDigest extends MessageDigestSpi implements Cloneable {
+
+    public static final class MD5 extends KAEDigest {
+        private static final long initContext = nativeInit("md5");
+
+        public MD5() {
+            super("md5", 16, initContext);
+        }
+    }
+
+    public static final class SM3 extends KAEDigest {
+        private static final long initContext = nativeInit("sm3");
+
+        public SM3() {
+            super("sm3", 32, initContext);
+        }
+    }
+
+    public static final class SHA256 extends KAEDigest {
+        private static final long initContext = nativeInit("sha256");
+
+        public SHA256() {
+            super("sha256", 32, initContext);
+        }
+    }
+
+    public static final class SHA384 extends KAEDigest {
+        private static final long initContext = nativeInit("sha384");
+
+        public SHA384() {
+            super("sha384", 48, initContext);
+        }
+    }
+
+    private final int digestLength;
+
+    private final String algorithm;
+    private final long initContext;
+
+    // field for ensuring native memory is freed
+    private DigestContextRef contextRef = null;
+
+    KAEDigest(String algorithm, int digestLength, long initContext) {
+        this.algorithm = algorithm;
+        this.digestLength = digestLength;
+        this.initContext = initContext;
+    }
+
+    private static class DigestContextRef extends PhantomReference<KAEDigest>
+        implements Comparable<DigestContextRef> {
+
+        private static ReferenceQueue<KAEDigest> referenceQueue = new ReferenceQueue<>();
+        private static Set<DigestContextRef> referenceList = new ConcurrentSkipListSet<>();
+        private static boolean disableKaeDispose = Boolean.getBoolean("kae.disableKaeDispose");
+
+        private final long ctxAddress;
+
+        DigestContextRef(KAEDigest kaeDigest, long ctxAddress) {
+            super(kaeDigest, referenceQueue);
+            this.ctxAddress = ctxAddress;
+            if (!disableKaeDispose) {
+                referenceList.add(this);
+                drainRefQueueBounded();
+            }
+        }
+
+        @Override
+        public int compareTo(DigestContextRef other) {
+            if (this.ctxAddress == other.ctxAddress) {
+                return 0;
+            } else {
+                return (this.ctxAddress < other.ctxAddress) ? -1 : 1;
+            }
+        }
+
+        private static void drainRefQueueBounded() {
+            while (true) {
+                DigestContextRef next = (DigestContextRef) referenceQueue.poll();
+                if (next == null) {
+                    break;
+                }
+                next.dispose();
+            }
+        }
+
+        void dispose() {
+            if (!disableKaeDispose) {
+                referenceList.remove(this);
+                try {
+                    nativeFree(ctxAddress);
+                } finally {
+                    this.clear();
+                }
+            } else {
+                nativeFree(ctxAddress);
+            }
+        }
+    }
+
+    // single byte update. See JCA doc.
+    @Override
+    protected synchronized void engineUpdate(byte input) {
+        byte[] oneByte = new byte[]{input};
+        engineUpdate(oneByte, 0, 1);
+    }
+
+
+    // array update. See JCA doc.
+    @Override
+    protected synchronized void engineUpdate(byte[] input, int offset, int len) {
+        if (len == 0 || input == null) {
+            return;
+        }
+        if ((offset < 0) || (len < 0) || (offset > input.length - len)) {
+            throw new ArrayIndexOutOfBoundsException();
+        }
+        if (contextRef == null) {
+            contextRef = createDigestContext(this);
+        }
+
+        try {
+            nativeUpdate(contextRef.ctxAddress, input, offset, len);
+        } catch (Exception e) {
+            engineReset();
+            throw new ProviderException("nativeUpdate failed for " + algorithm, e);
+        }
+    }
+
+
+    // return the digest. See JCA doc.
+    @Override
+    protected synchronized byte[] engineDigest() {
+        final byte[] output = new byte[digestLength];
+        try {
+            engineDigest(output, 0, digestLength);
+        } catch (Exception e) {
+            throw new ProviderException("Internal error", e);
+        }
+        return output;
+    }
+
+    // return the digest in the specified array. See JCA doc.
+    @Override
+    protected int engineDigest(byte[] output, int offset, int len) throws DigestException {
+        if (output == null) {
+            return 0;
+        }
+        if (len < digestLength) {
+            throw new DigestException("Length must be at least "
+                    + digestLength + " for " + algorithm + " digests");
+        }
+        if ((offset < 0) || (len < 0) || (offset > output.length - len)) {
+            throw new DigestException("Buffer too short to store digest");
+        }
+        if (contextRef == null) {
+            contextRef = createDigestContext(this);
+        }
+        try {
+            nativeDigest(contextRef.ctxAddress, output, offset, digestLength);
+        } catch (Exception e) {
+            throw new ProviderException("Invoke nativeDigest failed for " + algorithm, e);
+        } finally {
+            engineReset();
+        }
+        return digestLength;
+    }
+
+    // reset this object. See JCA doc.
+    @Override
+    protected synchronized void engineReset() {
+        if (contextRef != null) {
+            contextRef.dispose();
+            contextRef = null;
+        }
+    }
+
+    // return digest length. See JCA doc.
+    @Override
+    protected int engineGetDigestLength() {
+        return digestLength;
+    }
+
+    @Override
+    public synchronized Object clone() throws CloneNotSupportedException {
+        KAEDigest kaeDigest = (KAEDigest) super.clone();
+        if (kaeDigest.contextRef != null && kaeDigest.contextRef.ctxAddress != 0) {
+            long addr;
+            try {
+                addr = nativeClone(kaeDigest.contextRef.ctxAddress);
+            } catch (Exception e) {
+                throw new ProviderException("Invoke nativeClone failed for " + algorithm, e);
+            }
+            kaeDigest.contextRef = new DigestContextRef(kaeDigest, addr);
+        }
+        return kaeDigest;
+    }
+
+    private DigestContextRef createDigestContext(KAEDigest kaeDigest) {
+        long addr;
+        try {
+            addr = nativeClone(initContext);
+        } catch (Exception e) {
+            throw new ProviderException("Invoke nativeInit failed for " + algorithm, e);
+        }
+        if (addr == 0) {
+            throw new RuntimeException("Cannot initialize EVP_MD_CTX for " + algorithm);
+        }
+        return new DigestContextRef(kaeDigest, addr);
+    }
+
+    // return pointer to the context
+    protected native static long nativeInit(String algorithmName);
+
+    // update the input byte
+    protected native static void nativeUpdate(long ctxAddress, byte[] input, int offset, int inLen);
+
+    // digest and store the digest message to output
+    protected native static int nativeDigest(long ctxAddress, byte[] output, int offset, int len);
+
+    // digest clone
+    protected static native long nativeClone(long ctxAddress);
+
+    // free the specified context
+    protected native static void nativeFree(long ctxAddress);
+}
diff --git a/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEECDHKeyAgreement.java b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEECDHKeyAgreement.java
new file mode 100644
index 000000000..29dc09889
--- /dev/null
+++ b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEECDHKeyAgreement.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.openeuler.security.openssl;
+
+import sun.security.ec.ECKeyFactory;
+
+import java.math.BigInteger;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidParameterException;
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.SecureRandom;
+import java.security.interfaces.ECPrivateKey;
+import java.security.interfaces.ECPublicKey;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.ECParameterSpec;
+import java.security.spec.ECPoint;
+import javax.crypto.KeyAgreementSpi;
+import javax.crypto.SecretKey;
+import javax.crypto.ShortBufferException;
+import javax.crypto.spec.SecretKeySpec;
+
+public class KAEECDHKeyAgreement extends KeyAgreementSpi {
+    private ECPrivateKey privateKey;
+    private ECPublicKey publicKey;
+
+    // Length of the secret to be derived.
+    private int expectedSecretLen;
+    private String curveName;
+
+    @Override
+    protected void engineInit(Key key, SecureRandom random) throws InvalidKeyException {
+        if (!(key instanceof PrivateKey)) {
+            throw new InvalidKeyException("Key must be instance of PrivateKey");
+        }
+        privateKey = (ECPrivateKey) ECKeyFactory.toECKey(key);
+        publicKey = null;
+    }
+
+    @Override
+    protected void engineInit(Key key, AlgorithmParameterSpec params, SecureRandom random)
+            throws InvalidKeyException, InvalidAlgorithmParameterException {
+        if (params != null) {
+            throw new InvalidAlgorithmParameterException("Parameters not supported");
+        }
+        engineInit(key, random);
+    }
+
+    @Override
+    protected Key engineDoPhase(Key key, boolean lastPhase) throws InvalidKeyException, IllegalStateException {
+        if (privateKey == null) {
+            throw new IllegalStateException("Not initialized");
+        }
+        if (publicKey != null) {
+            throw new IllegalStateException("Phase already executed");
+        }
+        if (!lastPhase) {
+            throw new IllegalStateException
+                ("Only two party agreement supported, lastPhase must be true");
+        }
+        if (!(key instanceof ECPublicKey)) {
+            throw new InvalidKeyException
+                ("Key must be a PublicKey with algorithm EC");
+        }
+
+        publicKey = (ECPublicKey) key;
+        ECParameterSpec params = publicKey.getParams();
+        int keyLenBits = params.getCurve().getField().getFieldSize();
+        // Bits to bytes.
+        expectedSecretLen = (keyLenBits + 7) >> 3;
+
+        curveName = KAEUtils.getCurveBySize(keyLenBits);
+        if (curveName == null) {
+            throw new InvalidParameterException("unknown keyLenBits " + keyLenBits);
+        }
+        if (KAEUtils.getCurveByAlias(curveName) != null) {
+            curveName = KAEUtils.getCurveByAlias(curveName);
+        }
+        return null;
+    }
+
+    @Override
+    protected byte[] engineGenerateSecret() throws IllegalStateException {
+        if ((privateKey == null) || (publicKey == null)) {
+            throw new IllegalStateException("Not initialized correctly");
+        }
+        ECPoint w = publicKey.getW();
+        BigInteger wX = w.getAffineX();
+        BigInteger wY = w.getAffineY();
+
+        BigInteger s = privateKey.getS();
+        byte[] secret = nativeGenerateSecret(curveName, wX.toByteArray(), wY.toByteArray(), s.toByteArray());
+        if (secret == null || secret.length != expectedSecretLen) {
+            throw new RuntimeException("nativeGenerateSecret error. Expected: " + expectedSecretLen + ", actual: " + (secret == null ? "null" : secret.length));
+        }
+        return secret;
+    }
+
+    @Override
+    protected int engineGenerateSecret(byte[] sharedSecret, int offset) throws IllegalStateException, ShortBufferException {
+        if (offset + expectedSecretLen > sharedSecret.length) {
+            throw new ShortBufferException("Need " + expectedSecretLen +
+                    " bytes, only " + (sharedSecret.length - offset) + "available");
+        }
+        byte[] secret = engineGenerateSecret();
+        System.arraycopy(secret, 0, sharedSecret, offset, secret.length);
+        return secret.length;
+    }
+
+    @Override
+    protected SecretKey engineGenerateSecret(String algorithm) throws IllegalStateException,
+            NoSuchAlgorithmException, InvalidKeyException {
+        if (algorithm == null) {
+            throw new NoSuchAlgorithmException("Algorithm must not be null");
+        }
+        return new SecretKeySpec(engineGenerateSecret(), algorithm);
+    }
+
+    protected static native byte[] nativeGenerateSecret(String curveName, byte[] wX, byte[] wY, byte[] s);
+}
diff --git a/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEECKeyPairGenerator.java b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEECKeyPairGenerator.java
new file mode 100644
index 000000000..73d8551b1
--- /dev/null
+++ b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEECKeyPairGenerator.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.openeuler.security.openssl;
+
+import sun.security.ec.ECPrivateKeyImpl;
+import sun.security.ec.ECPublicKeyImpl;
+
+import java.math.BigInteger;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidParameterException;
+import java.security.KeyPair;
+import java.security.KeyPairGeneratorSpi;
+import java.security.ProviderException;
+import java.security.SecureRandom;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.ECFieldFp;
+import java.security.spec.ECField;
+import java.security.spec.ECGenParameterSpec;
+import java.security.spec.ECParameterSpec;
+import java.security.spec.ECPoint;
+import java.security.spec.EllipticCurve;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+
+public class KAEECKeyPairGenerator extends KeyPairGeneratorSpi {
+    private ECParameterSpec param = null;
+    private final int defaultKeySize = 256;
+
+    @Override
+    public void initialize(int keysize, SecureRandom random) {
+        String curveName = KAEUtils.getCurveBySize(keysize);
+        if (curveName == null) {
+            throw new InvalidParameterException("unknown key size " + keysize);
+        }
+        if (KAEUtils.getCurveByAlias(curveName) != null) {
+            curveName = KAEUtils.getCurveByAlias(curveName);
+        }
+        this.param = getParamsByCurve(curveName);
+    }
+
+    private ECParameterSpec getParamsByCurve(String curveName) {
+        byte[][] params = nativeGenerateParam(curveName);
+        if (params == null) {
+            throw new InvalidParameterException("unknown curve " + curveName);
+        }
+        BigInteger p = new BigInteger(params[0]);
+        BigInteger a = new BigInteger(params[1]);
+        BigInteger b = new BigInteger(params[2]);
+        BigInteger x = new BigInteger(params[3]);
+        BigInteger y = new BigInteger(params[4]);
+        BigInteger order = new BigInteger(params[5]);
+        BigInteger cofactor = new BigInteger(params[6]);
+        ECField field = new ECFieldFp(p);
+        EllipticCurve curve = new EllipticCurve(field, a, b);
+        ECPoint g = new ECPoint(x, y);
+        ECParameterSpec spec = new ECParameterSpec(curve, g, order, cofactor.intValue());
+        return spec;
+    }
+
+    @Override
+    public void initialize(AlgorithmParameterSpec param, SecureRandom random) throws InvalidAlgorithmParameterException {
+        if (param instanceof ECParameterSpec) {
+            this.param = (ECParameterSpec) param;
+        } else if (param instanceof ECGenParameterSpec) {
+            ECGenParameterSpec ecParam = (ECGenParameterSpec)param;
+            String curveName = ecParam.getName();
+            if (KAEUtils.getCurveByAlias(curveName) != null) {
+                curveName = KAEUtils.getCurveByAlias(curveName);
+            }
+            this.param = getParamsByCurve(curveName);
+        } else {
+            throw new InvalidAlgorithmParameterException("ECParameterSpec or ECGenParameterSpec for EC");
+        }
+    }
+
+    @Override
+    public KeyPair generateKeyPair() {
+        if (param == null) {
+            String curveName = KAEUtils.getCurveBySize(defaultKeySize);
+            param = getParamsByCurve(curveName);
+        }
+        EllipticCurve curve = param.getCurve();
+        ECFieldFp field = (ECFieldFp) curve.getField();
+        BigInteger p = field.getP();
+        BigInteger a = curve.getA();
+        BigInteger b = curve.getB();
+        ECPoint generator = param.getGenerator();
+        BigInteger x = generator.getAffineX();
+        BigInteger y = generator.getAffineY();
+        BigInteger order = param.getOrder();
+        int cofactor = param.getCofactor();
+
+        byte[][] keys = nativeGenerateKeyPair(p.toByteArray(), a.toByteArray(),
+                b.toByteArray(), x.toByteArray(), y.toByteArray(), order.toByteArray(), cofactor);
+        if (keys == null) {
+            throw new RuntimeException("nativeGenerateKeyPair failed");
+        }
+        BigInteger wX = new BigInteger(keys[0]);
+        BigInteger wY = new BigInteger(keys[1]);
+        BigInteger s = new BigInteger(keys[2]);
+        ECPoint w = new ECPoint(wX, wY);
+
+        ECPrivateKeyImpl privateKey = null;
+        ECPublicKeyImpl publicKey = null;
+        try {
+            Class<?> pubKeyImpl = Class.forName("sun.security.ec.ECPublicKeyImpl");
+            Constructor<?> conPubKeyImpl = pubKeyImpl.getDeclaredConstructor(ECPoint.class, ECParameterSpec.class);
+            conPubKeyImpl.setAccessible(true);
+            publicKey = (ECPublicKeyImpl) conPubKeyImpl.newInstance(w, param);
+    
+            Class<?> priKeyImpl = Class.forName("sun.security.ec.ECPrivateKeyImpl");
+            Constructor<?> conPriKeyImpl = priKeyImpl.getDeclaredConstructor(BigInteger.class, ECParameterSpec.class);
+            conPriKeyImpl.setAccessible(true);
+            privateKey = (ECPrivateKeyImpl) conPriKeyImpl.newInstance(s, param);
+        } catch (ClassNotFoundException | NoSuchMethodException | InstantiationException |
+                IllegalAccessException | InvocationTargetException e) {
+            throw new ProviderException(e);
+        }
+        return new KeyPair(publicKey, privateKey);
+    }
+
+    protected static native byte[][] nativeGenerateParam(String curveName);
+
+    protected static native byte[][] nativeGenerateKeyPair(byte[] p, byte[] a, byte[] b, byte[] x, byte[] y,
+            byte[] order, int cofactor);
+}
diff --git a/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEHMac.java b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEHMac.java
new file mode 100644
index 000000000..3ca909aa1
--- /dev/null
+++ b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEHMac.java
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.openeuler.security.openssl;
+
+import javax.crypto.MacSpi;
+import javax.crypto.SecretKey;
+import java.lang.ref.PhantomReference;
+import java.lang.ref.ReferenceQueue;
+import java.security.*;
+import java.security.spec.AlgorithmParameterSpec;
+import java.util.Set;
+import java.util.concurrent.ConcurrentSkipListSet;
+
+public abstract class KAEHMac extends MacSpi {
+
+    private final String algorithm;
+
+    /**
+     * The secret key used in this keyed HMAC.
+     */
+    private byte[] keyBytes;
+
+    /**
+     * Holds the output size of the message digest.
+     */
+    private final int digestSize;
+
+    /**
+     * Holds a dummy buffer for writing single bytes to the digest.
+     */
+    private final byte[] singleByte = new byte[1];
+
+    private HmacContextRef contextRef = null;
+
+    private KAEHMac(String algo, int size) {
+        this.algorithm = algo;
+        this.digestSize = size;
+    }
+
+    private static class HmacContextRef extends PhantomReference<KAEHMac>
+            implements Comparable<HmacContextRef> {
+
+        private static ReferenceQueue<KAEHMac> referenceQueue = new ReferenceQueue<>();
+        private static Set<HmacContextRef> referenceList = new ConcurrentSkipListSet<>();
+        private static boolean disableKaeDispose = Boolean.getBoolean("kae.disableKaeDispose");
+
+        private final long address;
+
+        HmacContextRef(KAEHMac kaeHMac, long address) {
+            super(kaeHMac, referenceQueue);
+            this.address = address;
+            if (!disableKaeDispose) {
+                referenceList.add(this);
+                drainRefQueueBounded();
+            }
+        }
+
+        @Override
+        public int compareTo(HmacContextRef other) {
+            if (this.address == other.address) {
+                return 0;
+            } else {
+                return (this.address < other.address) ? -1 : 1;
+            }
+        }
+
+        private static void drainRefQueueBounded() {
+            while (true) {
+                HmacContextRef next = (HmacContextRef) referenceQueue.poll();
+                if (next == null) break;
+                next.dispose(true);
+            }
+        }
+
+        void dispose(boolean needFree) {
+            if (!disableKaeDispose) {
+                referenceList.remove(this);
+                try {
+                    if (needFree) {
+                        nativeFree(address);
+                    }
+                } finally {
+                    this.clear();
+                }
+            } else {
+                nativeFree(address);
+            }
+        }
+    }
+
+    private void checkAndInitHmacContext () {
+        try {
+            if (contextRef == null) {
+                long ctxAddr = nativeInit(keyBytes, keyBytes.length, algorithm);
+                contextRef = new HmacContextRef(this, ctxAddr);
+            }
+        }
+        catch (Exception e) {
+            throw new ProviderException(e.getMessage()) ;
+        }
+    }
+
+    @Override
+    protected int engineGetMacLength() {
+        return digestSize;
+    }
+
+    @Override
+    protected void engineInit(Key key, AlgorithmParameterSpec params)
+            throws InvalidKeyException, InvalidAlgorithmParameterException {
+        if (!(key instanceof SecretKey)) {
+            throw new InvalidKeyException("key must be a SecretKey");
+        }
+        if (params != null) {
+            throw new InvalidAlgorithmParameterException("unknown parameter type");
+        }
+        keyBytes = key.getEncoded();
+        if (keyBytes == null) {
+            throw new InvalidKeyException("key cannot be encoded");
+        }
+    }
+
+    @Override
+    protected void engineUpdate(byte input) {
+        singleByte[0] = input;
+        engineUpdate(singleByte, 0, 1);
+    }
+
+    @Override
+    protected void engineUpdate(byte[] input, int offset, int len) {
+        checkAndInitHmacContext();
+        try {
+            nativeUpdate(contextRef.address, input, offset, len);
+        }
+        catch (Exception e) {
+            engineReset();
+            throw new ProviderException(e.getMessage());
+        }
+    }
+
+
+    @Override
+    protected byte[] engineDoFinal() {
+        final byte[] output = new byte[digestSize];
+        checkAndInitHmacContext();
+        final byte[] res;
+        try {
+            int bytesWritten = nativeFinal(contextRef.address, output, 0, digestSize);
+            res = new byte[bytesWritten];
+            System.arraycopy(output, 0, res, 0, bytesWritten);
+        }
+        catch (Exception e) {
+            engineReset();
+            throw new ProviderException(e.getMessage());
+        }
+        return res;
+    }
+
+    @Override
+    protected void engineReset() {
+        if (contextRef != null) {
+            contextRef.dispose(true);
+            contextRef = null;
+        }
+    }
+
+    public static final class HmacMD5 extends KAEHMac {
+        public HmacMD5() {
+            super("MD5", 16);
+        }
+    }
+    public static final class HmacSHA1 extends KAEHMac {
+        public HmacSHA1() {
+            super("SHA1", 20);
+        }
+    }
+    public static final class HmacSHA224 extends KAEHMac {
+        public HmacSHA224() throws NoSuchAlgorithmException {
+            super("SHA224", 28);
+        }
+    }
+    public static final class HmacSHA256 extends KAEHMac {
+        public HmacSHA256() throws NoSuchAlgorithmException {
+            super("SHA256", 32);
+        }
+    }
+    public static final class HmacSHA384 extends KAEHMac {
+        public HmacSHA384() throws NoSuchAlgorithmException {
+            super("SHA384", 48);
+        }
+    }
+    public static final class HmacSHA512 extends KAEHMac {
+        public HmacSHA512() throws NoSuchAlgorithmException {
+            super("SHA512", 64);
+        }
+    }
+    
+    protected static native long nativeInit(byte[] key, int len, String algo);
+
+    protected static native void nativeUpdate(long ctxAddr, byte[] input, int inOffset, int inLen);
+
+    protected static native int nativeFinal(long ctxAddr, byte[] output, int outOffset, int inLen);
+
+    protected static native void nativeFree(long ctxAddr);
+}
diff --git a/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAELog.java b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAELog.java
new file mode 100644
index 000000000..33c1c430f
--- /dev/null
+++ b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAELog.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.openeuler.security.openssl;
+
+import sun.security.util.Debug;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardOpenOption;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.text.SimpleDateFormat;
+import java.util.Arrays;
+import java.util.Date;
+
+public class KAELog {
+  private static final Debug kaeDebug = Debug.getInstance("kae");
+  private static File logFile;
+  private static boolean exist;
+
+  private KAELog() {
+
+  }
+
+  static {
+    kaeLogInit();
+  }
+
+  @SuppressWarnings("removal")
+  private static void kaeLogInit() {
+    AccessController.doPrivileged(new PrivilegedAction<Void>() {
+      public Void run() {
+        initialize();
+        return null;
+      }
+    });
+  }
+
+  private static void initialize() {
+    if (!enableKaeLog()) {
+      if (kaeDebug != null) {
+        kaeDebug.println("kae logging is not enabled");
+      }
+      return;
+    }
+
+    logFile = kaeLogFile("kae.log");
+    File parentFile = logFile.getParentFile();
+    if (!parentFile.exists()) {
+      try {
+        Files.createDirectories(parentFile.toPath());
+      } catch (IOException e) {
+        if (kaeDebug != null) {
+          kaeDebug.println("failed to create directory :" + parentFile);
+          e.printStackTrace();
+        }
+        return;
+      }
+    }
+
+    if (logFile.exists()) {
+      if (kaeDebug != null) {
+        kaeDebug.println("found kae log file :" + logFile);
+      }
+      exist = true;
+    } else {
+      if (kaeDebug != null) {
+        kaeDebug.println("not found kae log file :" + logFile);
+      }
+      try {
+        Path path = Files.createFile(logFile.toPath());
+        if (path != null) {
+          exist = true;
+        }
+      } catch (IOException e) {
+        if (kaeDebug != null) {
+          kaeDebug.println("unable to create new kae log file :" + logFile);
+          e.printStackTrace();
+        }
+      }
+
+      if (exist) {
+        if (kaeDebug != null) {
+          kaeDebug.println("create new kae log file :" + logFile);
+        }
+      }
+    }
+  }
+
+  public static boolean enableKaeLog() {
+    String debug = KAEConfig.privilegedGetOverridable("kae.log");
+    return Boolean.parseBoolean(debug);
+  }
+
+  private static File kaeLogFile(String filename) {
+    String sep = File.separator;
+    String defaultKaeLog = System.getProperty("user.dir") + sep + filename;
+    String kaeLog = KAEConfig.privilegedGetOverridable("kae.log.file", defaultKaeLog);
+    return new File(kaeLog);
+  }
+
+  private static String getLogTime() {
+    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+    return simpleDateFormat.format(new Date());
+  }
+
+  public static void log(String engineId, Throwable throwable, boolean[] engineFlags, boolean[] kaeProviderFlags) {
+    if (engineFlags.length != kaeProviderFlags.length) {
+      if (kaeDebug != null) {
+        kaeDebug.println("The length of engineFlags is not equal to the length of kaeProviderFlags.");
+        kaeDebug.println(String.format("engineFlags : %s", Arrays.toString(engineFlags)));
+        kaeDebug.println(String.format("kaeProviderFlags : %s", Arrays.toString(kaeProviderFlags)));
+      }
+      return;
+    }
+    if (!exist) {
+      return;
+    }
+
+    try (BufferedWriter writer = Files.newBufferedWriter(logFile.toPath(),
+            StandardOpenOption.APPEND)) {
+      logEngine(writer, engineId, throwable);
+      writer.newLine();
+      logAlgorithmStrategy(writer, engineFlags, kaeProviderFlags);
+      writer.newLine();
+    } catch (IOException e) {
+      if (kaeDebug != null) {
+        kaeDebug.println("write kae log failed");
+        e.printStackTrace();
+      }
+    }
+  }
+
+  // log engine
+  private static void logEngine(BufferedWriter writer, String engineId, Throwable throwable) throws IOException {
+    writer.write(String.format("[%s] ", getLogTime()));
+    if (throwable == null) {
+      writer.write(String.format("%s engine was found.", engineId));
+    } else if (throwable instanceof RuntimeException) {
+      writer.write(String.format("%s engine was not found. %s", engineId, throwable.getMessage()));
+    } else {
+      writer.write(throwable.getMessage());
+    }
+  }
+
+  // log algorithm strategy
+  private static void logAlgorithmStrategy(BufferedWriter writer, boolean[] engineFlags, boolean[] kaeProviderFlags)
+          throws IOException {
+    writer.write(String.format("[%s] ", getLogTime()));
+    writer.write("The implementation strategy of each algorithm is as follows : ");
+    for (int i = 0; i < engineFlags.length; i++) {
+      writer.newLine();
+      String algorithmName = KAEConfig.getAlgorithmName(i);
+      String message;
+      if (kaeProviderFlags[i]) {
+        String detail = engineFlags[i] ? "enable KAE hardware acceleration" : "Use openssl soft calculation";
+        message = String.format(" %-11s => %s: %s", algorithmName, "KAEProvider", detail);
+      } else {
+        message = String.format(" %-11s => %s", algorithmName, "Non-KAEProvider");
+      }
+      writer.write(message);
+    }
+  }
+}
\ No newline at end of file
diff --git a/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEMGF1.java b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEMGF1.java
new file mode 100644
index 000000000..dc79a3f62
--- /dev/null
+++ b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEMGF1.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.openeuler.security.openssl;
+
+import java.security.*;
+
+/**
+ * This class implements the MGF1 mask generation function defined in PKCS#1
+ * v2.2 B.2.1 (https://tools.ietf.org/html/rfc8017#appendix-B.2.1). A mask
+ * generation function takes an octet string of variable length and a
+ * desired output length as input and outputs an octet string of the
+ * desired length. MGF1 is a mask generation function based on a hash
+ * function, i.e. message digest algorithm.
+ *
+ * @since   11
+ */
+final class KAEMGF1 {
+
+    private final MessageDigest md;
+
+    /**
+     * Construct an instance of MGF1 based on the specified digest algorithm.
+     */
+    KAEMGF1(String mdAlgo) throws NoSuchAlgorithmException {
+        this.md = MessageDigest.getInstance(mdAlgo);
+    }
+
+    /**
+     * Using the specified seed bytes, generate the mask, xor the mask
+     * with the specified output buffer and store the result into the
+     * output buffer (essentially replaced in place).
+     *
+     * @param seed the buffer holding the seed bytes
+     * @param seedOfs the index of the seed bytes
+     * @param seedLen the length of the seed bytes to be used by MGF1
+     * @param maskLen the intended length of the generated mask
+     * @param out the output buffer holding the mask
+     * @param outOfs the index of the output buffer for the mask
+     */
+    void generateAndXor(byte[] seed, int seedOfs, int seedLen, int maskLen,
+            byte[] out, int outOfs) throws RuntimeException {
+        byte[] C = new byte[4]; // 32 bit counter
+        byte[] digest = new byte[md.getDigestLength()];
+        while (maskLen > 0) {
+            md.update(seed, seedOfs, seedLen);
+            md.update(C);
+            try {
+                md.digest(digest, 0, digest.length);
+            } catch (DigestException e) {
+                // should never happen
+                throw new RuntimeException(e.toString());
+            }
+            for (int i = 0; (i < digest.length) && (maskLen > 0); maskLen--) {
+                out[outOfs++] ^= digest[i++];
+            }
+            if (maskLen > 0) {
+                // increment counter
+                for (int i = C.length - 1; (++C[i] == 0) && (i > 0); i--) {
+                    // empty
+                }
+            }
+        }
+    }
+
+    /**
+     * Returns the name of this MGF1 instance, i.e. "MGF1" followed by the
+     * digest algorithm it based on.
+     */
+    String getName() {
+        return "KAEMGF1" + md.getAlgorithm();
+    }
+}
diff --git a/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEProvider.java b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEProvider.java
new file mode 100644
index 000000000..b3c1fb022
--- /dev/null
+++ b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEProvider.java
@@ -0,0 +1,326 @@
+/*
+ * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.openeuler.security.openssl;
+
+import sun.security.util.Debug;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.Provider;
+import static sun.security.util.SecurityConstants.PROVIDER_VER;
+
+/**
+ * KAE Provider
+ */
+@SuppressWarnings("serial")
+public class KAEProvider extends Provider {
+    private static final Debug kaeDebug = Debug.getInstance("kae");
+
+    // default engine id
+    private static final String DEFAULT_ENGINE_ID = "kae";
+
+    static {
+        initialize();
+    }
+
+    private static void initialize() {
+        loadLibrary();
+        initOpenssl();
+    }
+
+    // load kae.so
+    @SuppressWarnings("removal")
+    private static void loadLibrary() {
+        AccessController.doPrivileged(new PrivilegedAction<Object>() {
+            @Override
+            public Object run() {
+                System.loadLibrary("j2kae");
+                return null;
+            }
+        });
+    }
+
+    // init openssl
+    private static void initOpenssl() {
+        boolean useGlobalMode = useGlobalMode();
+        String engineId = getEngineId();
+        boolean[] algorithmKaeFlags = KAEConfig.getUseKaeEngineFlags();
+        Throwable throwable = null;
+        try {
+            initOpenssl(useGlobalMode, engineId, algorithmKaeFlags);
+        } catch (Throwable t) {
+            throwable = t;
+            if (kaeDebug != null) {
+                kaeDebug.println("initOpenssl failed : " + throwable.getMessage());
+            }
+        }
+        boolean[] engineFlags = getEngineFlags();
+        boolean[] kaeProviderFlags = KAEConfig.getUseKaeProviderFlags();
+        KAELog.log(engineId, throwable, engineFlags, kaeProviderFlags);
+    }
+
+    // get engine id
+    private static String getEngineId() {
+        return KAEConfig.privilegedGetOverridable("kae.engine.id", DEFAULT_ENGINE_ID);
+    }
+
+    // whether to set libcrypto.so to GLOBAL mode, by default libcrypto.so is LOCAL mode
+    private static boolean useGlobalMode() {
+        String explicitLoad = KAEConfig.privilegedGetOverridable(
+                "kae.libcrypto.useGlobalMode", "false");
+        return Boolean.parseBoolean(explicitLoad);
+    }
+
+    @SuppressWarnings({"deprecation", "this-escape"})
+    public KAEProvider() {
+        super("KAEProvider", PROVIDER_VER, "KAE provider");
+        if (KAEConfig.useKaeProvider("kae.md5")) {
+            putMD5();
+        }
+        if (KAEConfig.useKaeProvider("kae.sha256")) {
+            putSHA256();
+        }
+        if (KAEConfig.useKaeProvider("kae.sha384")) {
+            putSHA384();
+        }
+        if (KAEConfig.useKaeProvider("kae.sm3")) {
+            putSM3();
+        }
+        if (KAEConfig.useKaeProvider("kae.aes")) {
+            putAES();
+        }
+        if (KAEConfig.useKaeProvider("kae.sm4")) {
+            putSM4();
+        }
+        if (KAEConfig.useKaeProvider("kae.hmac")) {
+            putHMAC();
+        }
+        if (KAEConfig.useKaeProvider("kae.rsa")) {
+            putRSA();
+            putSignatureRSA();
+        }
+        if (KAEConfig.useKaeProvider("kae.dh")) {
+            putDH();
+        }
+        if (KAEConfig.useKaeProvider("kae.ec")) {
+            putEC();
+        }
+    }
+
+    private void putAES() {
+        final String blockModes = "ECB|CBC|CTR|GCM";
+        final String blockPads = "NOPADDING|PKCS5PADDING";
+
+        put("Cipher.AES SupportedModes", blockModes);
+        put("Cipher.AES SupportedPaddings", blockPads);
+        put("Cipher.AES", "org.openeuler.security.openssl.KAEAESCipher$Aes$Ecb$PKCS5Padding");
+
+        put("Cipher.AES/CBC/PKCS5Padding", "org.openeuler.security.openssl.KAEAESCipher$Aes$Cbc$PKCS5Padding");
+        put("Cipher.AES/CBC/NoPadding", "org.openeuler.security.openssl.KAEAESCipher$Aes$Cbc$NoPadding");
+        put("Alg.Alias.Cipher.AES/CBC/PKCS7Padding", "AES/CBC/PKCS5Padding");
+        put("Cipher.AES/ECB/NoPadding", "org.openeuler.security.openssl.KAEAESCipher$Aes$Ecb$NoPadding");
+        put("Cipher.AES/ECB/PKCS5Padding", "org.openeuler.security.openssl.KAEAESCipher$Aes$Ecb$PKCS5Padding");
+        put("Alg.Alias.Cipher.AES/ECB/PKCS7Padding", "AES/ECB/PKCS5Padding");
+        put("Cipher.AES/CTR/NoPadding", "org.openeuler.security.openssl.KAEAESCipher$Aes$Ctr$NoPadding");
+        put("Cipher.AES/GCM/NoPadding", "org.openeuler.security.openssl.KAEAESCipher$Aes$Gcm$NoPadding");
+        put("Alg.Alias.Cipher.AES/GCM/PKCS5Padding", "AES/GCM/NoPadding"); // PKCS5Padding -> noPadding
+
+        put("Cipher.AES_128/CBC/PKCS5Padding", "org.openeuler.security.openssl.KAEAESCipher$Aes_128$Cbc$PKCS5Padding");
+        put("Cipher.AES_128/CBC/NoPadding", "org.openeuler.security.openssl.KAEAESCipher$Aes_128$Cbc$NoPadding");
+        put("Alg.Alias.Cipher.AES_128/CBC/PKCS7Padding", "AES_128/CBC/PKCS5Padding");
+        put("Cipher.AES_128/ECB/NoPadding", "org.openeuler.security.openssl.KAEAESCipher$Aes_128$Ecb$NoPadding");
+        put("Cipher.AES_128/ECB/PKCS5Padding", "org.openeuler.security.openssl.KAEAESCipher$Aes_128$Ecb$PKCS5Padding");
+        put("Alg.Alias.Cipher.AES_128/ECB/PKCS7Padding", "AES_128/ECB/PKCS5Padding");
+        put("Cipher.AES_128/CTR/NoPadding", "org.openeuler.security.openssl.KAEAESCipher$Aes_128$Ctr$NoPadding");
+        put("Cipher.AES_128/GCM/NoPadding", "org.openeuler.security.openssl.KAEAESCipher$Aes_128$Gcm$NoPadding");
+        put("Alg.Alias.Cipher.AES_128/GCM/PKCS5Padding", "AES/GCM/NoPadding");
+
+        put("Cipher.AES_192/CBC/PKCS5Padding", "org.openeuler.security.openssl.KAEAESCipher$Aes_192$Cbc$PKCS5Padding");
+        put("Cipher.AES_192/CBC/NoPadding", "org.openeuler.security.openssl.KAEAESCipher$Aes_192$Cbc$NoPadding");
+        put("Alg.Alias.Cipher.AES_192/CBC/PKCS7Padding", "AES_192/CBC/PKCS5Padding");
+        put("Cipher.AES_192/ECB/NoPadding", "org.openeuler.security.openssl.KAEAESCipher$Aes_192$Ecb$NoPadding");
+        put("Cipher.AES_192/ECB/PKCS5Padding", "org.openeuler.security.openssl.KAEAESCipher$Aes_192$Ecb$PKCS5Padding");
+        put("Alg.Alias.Cipher.AES_192/ECB/PKCS7Padding", "AES_192/ECB/PKCS5Padding");
+        put("Cipher.AES_192/CTR/NoPadding", "org.openeuler.security.openssl.KAEAESCipher$Aes_192$Ctr$NoPadding");
+        put("Cipher.AES_192/GCM/NoPadding", "org.openeuler.security.openssl.KAEAESCipher$Aes_192$Gcm$NoPadding");
+        put("Alg.Alias.Cipher.AES_192/GCM/PKCS5Padding", "AES/GCM/NoPadding");
+
+        put("Cipher.AES_256/CBC/PKCS5Padding", "org.openeuler.security.openssl.KAEAESCipher$Aes_256$Cbc$PKCS5Padding");
+        put("Cipher.AES_256/CBC/NoPadding", "org.openeuler.security.openssl.KAEAESCipher$Aes_256$Cbc$NoPadding");
+        put("Alg.Alias.Cipher.AES_256/CBC/PKCS7Padding", "AES_256/CBC/PKCS5Padding");
+        put("Cipher.AES_256/ECB/NoPadding", "org.openeuler.security.openssl.KAEAESCipher$Aes_256$Ecb$NoPadding");
+        put("Cipher.AES_256/ECB/PKCS5Padding", "org.openeuler.security.openssl.KAEAESCipher$Aes_256$Ecb$PKCS5Padding");
+        put("Alg.Alias.Cipher.AES_256/ECB/PKCS7Padding", "AES_256/ECB/PKCS5Padding");
+        put("Cipher.AES_256/CTR/NoPadding", "org.openeuler.security.openssl.KAEAESCipher$Aes_256$Ctr$NoPadding");
+        put("Cipher.AES_256/GCM/NoPadding", "org.openeuler.security.openssl.KAEAESCipher$Aes_256$Gcm$NoPadding");
+        put("Alg.Alias.Cipher.AES_256/GCM/PKCS5Padding", "AES/GCM/NoPadding");
+    }
+
+    private void putMD5() {
+        put("MessageDigest.MD5", "org.openeuler.security.openssl.KAEDigest$MD5");
+    }
+
+    private void putSHA256() {
+        put("MessageDigest.SHA-256", "org.openeuler.security.openssl.KAEDigest$SHA256");
+    }
+
+    private void putSHA384() {
+        put("MessageDigest.SHA-384", "org.openeuler.security.openssl.KAEDigest$SHA384");
+    }
+
+    private void putSM3() {
+        put("MessageDigest.SM3", "org.openeuler.security.openssl.KAEDigest$SM3");
+    }
+
+    private void putSM4() {
+        final String blockModes = "ECB|CBC|CTR|OFB";
+        final String blockPads = "NOPADDING|PKCS5PADDING";
+
+        put("Cipher.SM4 SupportedModes", blockModes);
+        put("Cipher.SM4 SupportedPaddings", blockPads);
+        put("Cipher.SM4", "org.openeuler.security.openssl.KAESM4Cipher$Sm4$Ecb$PKCS5Padding");
+
+        put("Cipher.SM4/CBC/PKCS5Padding", "org.openeuler.security.openssl.KAESM4Cipher$Sm4$Cbc$PKCS5Padding");
+        put("Cipher.SM4/CBC/NoPadding", "org.openeuler.security.openssl.KAESM4Cipher$Sm4$Cbc$NoPadding");
+        put("Alg.Alias.Cipher.SM4/CBC/PKCS7Padding", "SM4/CBC/PKCS5Padding");
+        put("Cipher.SM4/ECB/NoPadding", "org.openeuler.security.openssl.KAESM4Cipher$Sm4$Ecb$NoPadding");
+        put("Cipher.SM4/ECB/PKCS5Padding", "org.openeuler.security.openssl.KAESM4Cipher$Sm4$Ecb$PKCS5Padding");
+        put("Alg.Alias.Cipher.SM4/ECB/PKCS7Padding", "SM4/ECB/PKCS5Padding");
+        put("Cipher.SM4/CTR/NoPadding", "org.openeuler.security.openssl.KAESM4Cipher$Sm4$Ctr$NoPadding");
+        put("Cipher.SM4/OFB/NoPadding", "org.openeuler.security.openssl.KAESM4Cipher$Sm4$Ofb$NoPadding");
+        put("Cipher.SM4/OFB/PKCS5Padding", "org.openeuler.security.openssl.KAESM4Cipher$Sm4$Ofb$PKCS5Padding");
+        put("Alg.Alias.Cipher.SM4/OFB/PKCS7Padding", "SM4/OFB/PKCS5Padding");
+
+        put("KeyGenerator.SM4", "org.openeuler.security.openssl.KAESM4KeyGenerator");
+        put("AlgorithmParameters.SM4", "com.sun.crypto.provider.AESParameters");
+    }
+
+    private void putRSA() {
+        // rsa
+        put("KeyPairGenerator.RSA", "org.openeuler.security.openssl.KAERSAKeyPairGenerator$Legacy");
+        put("Alg.Alias.KeyPairGenerator.1.2.840.113549.1.1", "RSA");
+        put("Alg.Alias.KeyPairGenerator.OID.1.2.840.113549.1.1", "RSA");
+
+        put("KeyPairGenerator.RSASSA-PSS", "org.openeuler.security.openssl.KAERSAKeyPairGenerator$PSS");
+        put("Alg.Alias.KeyPairGenerator.1.2.840.113549.1.1.10", "RSASSA-PSS");
+        put("Alg.Alias.KeyPairGenerator.OID.1.2.840.113549.1.1.10", "RSASSA-PSS");
+
+        put("Cipher.RSA", "org.openeuler.security.openssl.KAERSACipher");
+        put("Cipher.RSA SupportedModes", "ECB");
+        put("Cipher.RSA SupportedPaddings",
+                "NOPADDING|PKCS1PADDING|OAEPPADDING"
+                        + "|OAEPWITHMD5ANDMGF1PADDING"
+                        + "|OAEPWITHSHA1ANDMGF1PADDING"
+                        + "|OAEPWITHSHA-1ANDMGF1PADDING"
+                        + "|OAEPWITHSHA-224ANDMGF1PADDING"
+                        + "|OAEPWITHSHA-256ANDMGF1PADDING"
+                        + "|OAEPWITHSHA-384ANDMGF1PADDING"
+                        + "|OAEPWITHSHA-512ANDMGF1PADDING"
+                        + "|OAEPWITHSHA-512/224ANDMGF1PADDING"
+                        + "|OAEPWITHSHA-512/256ANDMGF1PADDING");
+        put("Cipher.RSA SupportedKeyClasses",
+                "java.security.interfaces.RSAPublicKey" +
+                        "|java.security.interfaces.RSAPrivateKey");
+    }
+
+    private void putHMAC() {
+        put("MAC.HmacMD5", "org.openeuler.security.openssl.KAEHMac$HmacMD5");
+        put("MAC.HmacSHA1", "org.openeuler.security.openssl.KAEHMac$HmacSHA1");
+        put("MAC.HmacSHA224", "org.openeuler.security.openssl.KAEHMac$HmacSHA224");
+        put("MAC.HmacSHA256", "org.openeuler.security.openssl.KAEHMac$HmacSHA256");
+        put("MAC.HmacSHA384", "org.openeuler.security.openssl.KAEHMac$HmacSHA384");
+        put("MAC.HmacSHA512", "org.openeuler.security.openssl.KAEHMac$HmacSHA512");
+    }
+
+    private void putDH() {
+        put("KeyPairGenerator.DiffieHellman", "org.openeuler.security.openssl.KAEDHKeyPairGenerator");
+        put("Alg.Alias.KeyPairGenerator.DH", "DiffieHellman");
+        put("KeyAgreement.DiffieHellman", "org.openeuler.security.openssl.KAEDHKeyAgreement");
+        put("Alg.Alias.KeyAgreement.DH", "DiffieHellman");
+    }
+
+    private void putSignatureRSA() {
+        put("Signature.MD5withRSA",
+                "org.openeuler.security.openssl.KAERSASignature$MD5withRSA");
+        put("Signature.SHA1withRSA",
+                "org.openeuler.security.openssl.KAERSASignature$SHA1withRSA");
+        put("Signature.SHA224withRSA",
+                "org.openeuler.security.openssl.KAERSASignature$SHA224withRSA");
+        put("Signature.SHA256withRSA",
+                "org.openeuler.security.openssl.KAERSASignature$SHA256withRSA");
+        put("Signature.SHA384withRSA",
+                "org.openeuler.security.openssl.KAERSASignature$SHA384withRSA");
+        put("Signature.SHA512withRSA",
+                "org.openeuler.security.openssl.KAERSASignature$SHA512withRSA");
+
+        // alias
+        put("Alg.Alias.Signature.1.2.840.113549.1.1.4", "MD5withRSA");
+        put("Alg.Alias.Signature.OID.1.2.840.113549.1.1.4", "MD5withRSA");
+
+        put("Alg.Alias.Signature.1.2.840.113549.1.1.5", "SHA1withRSA");
+        put("Alg.Alias.Signature.OID.1.2.840.113549.1.1.5", "SHA1withRSA");
+        put("Alg.Alias.Signature.1.3.14.3.2.29", "SHA1withRSA");
+
+        put("Alg.Alias.Signature.1.2.840.113549.1.1.14", "SHA224withRSA");
+        put("Alg.Alias.Signature.OID.1.2.840.113549.1.1.14", "SHA224withRSA");
+
+        put("Alg.Alias.Signature.1.2.840.113549.1.1.11", "SHA256withRSA");
+        put("Alg.Alias.Signature.OID.1.2.840.113549.1.1.11", "SHA256withRSA");
+
+        put("Alg.Alias.Signature.1.2.840.113549.1.1.12", "SHA384withRSA");
+        put("Alg.Alias.Signature.OID.1.2.840.113549.1.1.12", "SHA384withRSA");
+
+        put("Alg.Alias.Signature.1.2.840.113549.1.1.13", "SHA512withRSA");
+        put("Alg.Alias.Signature.OID.1.2.840.113549.1.1.13", "SHA512withRSA");
+
+        put("Signature.RSASSA-PSS", "org.openeuler.security.openssl.KAERSAPSSSignature");
+
+        put("Alg.Alias.Signature.1.2.840.113549.1.1.10", "RSASSA-PSS");
+        put("Alg.Alias.Signature.OID.1.2.840.113549.1.1.10", "RSASSA-PSS");
+
+        // attributes for supported key classes
+        String rsaKeyClasses = "java.security.interfaces.RSAPublicKey" +
+                "|java.security.interfaces.RSAPrivateKey";
+        put("Signature.MD5withRSA SupportedKeyClasses", rsaKeyClasses);
+        put("Signature.SHA1withRSA SupportedKeyClasses", rsaKeyClasses);
+        put("Signature.SHA224withRSA SupportedKeyClasses", rsaKeyClasses);
+        put("Signature.SHA256withRSA SupportedKeyClasses", rsaKeyClasses);
+        put("Signature.SHA384withRSA SupportedKeyClasses", rsaKeyClasses);
+        put("Signature.SHA512withRSA SupportedKeyClasses", rsaKeyClasses);
+        put("Signature.RSASSA-PSS SupportedKeyClasses", rsaKeyClasses);
+    }
+
+    private void putEC() {
+        put("KeyPairGenerator.EC", "org.openeuler.security.openssl.KAEECKeyPairGenerator");
+        put("Alg.Alias.KeyPairGenerator.EllipticCurve", "EC");
+        put("KeyAgreement.ECDH", "org.openeuler.security.openssl.KAEECDHKeyAgreement");
+    }
+
+    // init openssl
+    static native void initOpenssl(boolean useGlobalMode, String engineId, boolean[] algorithmKaeFlags)
+            throws RuntimeException;
+
+    static native boolean[] getEngineFlags();
+}
\ No newline at end of file
diff --git a/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAERSACipher.java b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAERSACipher.java
new file mode 100644
index 000000000..a45fb0dac
--- /dev/null
+++ b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAERSACipher.java
@@ -0,0 +1,796 @@
+/*
+ * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.openeuler.security.openssl;
+
+import sun.security.internal.spec.TlsRsaPremasterSecretParameterSpec;
+import sun.security.jca.Providers;
+import sun.security.rsa.RSACore;
+import sun.security.rsa.RSAKeyFactory;
+import sun.security.rsa.RSAPadding;
+import sun.security.util.KeyUtil;
+
+import javax.crypto.*;
+import javax.crypto.spec.OAEPParameterSpec;
+import javax.crypto.spec.PSource;
+import java.lang.ref.PhantomReference;
+import java.lang.ref.ReferenceQueue;
+import java.security.*;
+import java.security.interfaces.RSAKey;
+import java.security.interfaces.RSAPrivateCrtKey;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.InvalidParameterSpecException;
+import java.security.spec.MGF1ParameterSpec;
+import java.util.Arrays;
+import java.util.Locale;
+import java.util.Set;
+import java.util.concurrent.ConcurrentSkipListSet;
+
+
+/**
+ * RSA cipher implementation. Supports RSA en/decryption and signing/verifying
+ * using both PKCS#1 v1.5 and OAEP (v2.2) paddings and without padding (raw RSA).
+ * Note that raw RSA is supported mostly for completeness and should only be
+ * used in rare cases.
+ * <p>
+ * Objects should be instantiated by calling Cipher.getInstance() using the
+ * following algorithm names:
+ * . "RSA/ECB/PKCS1Padding" (or "RSA") for PKCS#1 v1.5 padding.
+ * . "RSA/ECB/OAEPwith<hash>andMGF1Padding" (or "RSA/ECB/OAEPPadding") for
+ * PKCS#1 v2.2 padding.
+ * . "RSA/ECB/NoPadding" for rsa RSA.
+ * <p>
+ * We only do one RSA operation per doFinal() call. If the application passes
+ * more data via calls to update() or doFinal(), we throw an
+ * IllegalBlockSizeException when doFinal() is called (see JCE API spec).
+ * Bulk encryption using RSA does not make sense and is not standardized.
+ * <p>
+ * Note: RSA keys should be at least 512 bits long
+ */
+public final class KAERSACipher extends CipherSpi {
+    // constant for an empty byte array
+    private final static byte[] B0 = new byte[0];
+
+    // mode constant for public key encryption
+    private final static int MODE_ENCRYPT = 1;
+
+    // mode constant for private key decryption
+    private final static int MODE_DECRYPT = 2;
+
+    // mode constant for private key encryption (signing)
+    private final static int MODE_SIGN = 3;
+
+    // mode constant for public key decryption (verifying)
+    private final static int MODE_VERIFY = 4;
+
+    // current mode, one of MODE_* above. Set when init() is called
+    private int mode;
+
+    // active padding type, one of PAD_* above. Set by setPadding()
+    private KAERSAPaddingType paddingType;
+
+    // padding object
+    private RSAPadding padding;
+
+    // cipher parameter for OAEP padding and TLS RSA premaster secret
+    private AlgorithmParameterSpec spec = null;
+
+    // buffer for the data
+    private byte[] buffer;
+
+    // offset into the buffer (number of bytes buffered)
+    private int bufOfs;
+
+    // size of the output
+    private int outputSize;
+
+    // hash algorithm for OAEP
+    private String oaepHashAlgorithm = "SHA-1";
+
+    // the source of randomness
+    private SecureRandom random;
+
+    private RSAKey rsaKey;
+
+    // rsa key holder
+    private KAERSAKeyHolder rsaKeyHolder;
+
+
+    public KAERSACipher() {
+        paddingType = KAERSAPaddingType.PKCS1Padding;
+    }
+
+    // modes do not make sense for RSA, but allow ECB
+    // see JCE spec
+    @Override
+    protected void engineSetMode(String mode) throws NoSuchAlgorithmException {
+        if (!mode.equalsIgnoreCase("ECB")) {
+            throw new NoSuchAlgorithmException("Unsupported mode " + mode);
+        }
+    }
+
+    // set the padding type
+    // see JCE spec
+    @Override
+    protected void engineSetPadding(String paddingName)
+            throws NoSuchPaddingException {
+        if (KAERSAPaddingType.NoPadding.getName().equalsIgnoreCase(paddingName)) {
+            paddingType = KAERSAPaddingType.NoPadding;
+        } else if (KAERSAPaddingType.PKCS1Padding.getName().equalsIgnoreCase(paddingName)) {
+            paddingType = KAERSAPaddingType.PKCS1Padding;
+        } else {
+            String lowerPadding = paddingName.toLowerCase(Locale.ENGLISH);
+            if ("oaeppadding".equals(lowerPadding)) {
+                paddingType = KAERSAPaddingType.OAEP;
+            } else if (lowerPadding.startsWith("oaepwith") &&
+                    lowerPadding.endsWith("andmgf1padding")) {
+                paddingType = KAERSAPaddingType.OAEP;
+                // "oaepwith" length is 8
+                // "andmgf1padding" length is 14
+                oaepHashAlgorithm =
+                        paddingName.substring(8, paddingName.length() - 14);
+                // check if MessageDigest appears to be available
+                // avoid getInstance() call here
+                if (Providers.getProviderList().getService
+                        ("MessageDigest", oaepHashAlgorithm) == null) {
+                    throw new NoSuchPaddingException
+                            ("MessageDigest not available for " + paddingName);
+                }
+            } else {
+                throw new NoSuchPaddingException
+                        ("Padding " + paddingName + " not supported");
+            }
+        }
+    }
+
+    // return 0 as block size, we are not a block cipher
+    // see JCE spec
+    @Override
+    protected int engineGetBlockSize() {
+        return 0;
+    }
+
+    // return the output size
+    // see JCE spec
+    @Override
+    protected int engineGetOutputSize(int inputLen) {
+        return outputSize;
+    }
+
+    // no iv, return null
+    // see JCE spec
+    @Override
+    protected byte[] engineGetIV() {
+        return null;
+    }
+
+    // see JCE spec
+    @Override
+    protected AlgorithmParameters engineGetParameters() {
+        if (spec != null && spec instanceof OAEPParameterSpec) {
+            try {
+                AlgorithmParameters params =
+                        AlgorithmParameters.getInstance("OAEP");
+                params.init(spec);
+                return params;
+            } catch (NoSuchAlgorithmException nsae) {
+                // should never happen
+                throw new RuntimeException("Cannot find OAEP " +
+                        " AlgorithmParameters implementation in SunJCE provider");
+            } catch (InvalidParameterSpecException ipse) {
+                // should never happen
+                throw new RuntimeException("OAEPParameterSpec not supported");
+            }
+        } else {
+            return null;
+        }
+    }
+
+    // see JCE spec
+    @Override
+    protected void engineInit(int opmode, Key key, SecureRandom random)
+            throws InvalidKeyException {
+        try {
+            init(opmode, key, random, null);
+        } catch (InvalidAlgorithmParameterException iape) {
+            // never thrown when null parameters are used;
+            // but re-throw it just in case
+            throw new InvalidKeyException("Wrong parameters", iape);
+        }
+    }
+
+    // see JCE spec
+    @Override
+    protected void engineInit(int opmode, Key key, AlgorithmParameterSpec params, SecureRandom random)
+            throws InvalidKeyException, InvalidAlgorithmParameterException {
+        init(opmode, key, random, params);
+    }
+
+    // see JCE spec
+    @Override
+    protected void engineInit(int opmode, Key key, AlgorithmParameters params, SecureRandom random)
+            throws InvalidKeyException, InvalidAlgorithmParameterException {
+        if (params == null) {
+            init(opmode, key, random, null);
+        } else {
+            try {
+                OAEPParameterSpec oaepParameterSpec =
+                        params.getParameterSpec(OAEPParameterSpec.class);
+                init(opmode, key, random, oaepParameterSpec);
+            } catch (InvalidParameterSpecException ipse) {
+                InvalidAlgorithmParameterException iape =
+                        new InvalidAlgorithmParameterException("Wrong parameter");
+                iape.initCause(ipse);
+                throw iape;
+            }
+        }
+    }
+
+    // check TlsRsaPremasterSecretParameterSpec
+    @SuppressWarnings("deprecation")
+    private void checkTlsRsaPremasterSecretParameterSpec(AlgorithmParameterSpec params)
+            throws InvalidAlgorithmParameterException {
+        if (!(params instanceof TlsRsaPremasterSecretParameterSpec)) {
+            throw new InvalidAlgorithmParameterException(
+                    "Parameters not supported");
+        }
+    }
+
+    // check OAEPParameterSpec
+    private void checkOAEPParameterSpec(AlgorithmParameterSpec params)
+            throws InvalidAlgorithmParameterException {
+        if (!(params instanceof OAEPParameterSpec)) {
+            throw new InvalidAlgorithmParameterException
+                    ("Wrong Parameters for OAEP Padding");
+        }
+
+        // check MGF algorithm
+        OAEPParameterSpec oaepParameterSpec = (OAEPParameterSpec) params;
+        String mgfName = oaepParameterSpec.getMGFAlgorithm();
+        if (!mgfName.equalsIgnoreCase("MGF1")) {
+            throw new InvalidAlgorithmParameterException
+                    ("Unsupported MGF algo: " + mgfName);
+        }
+
+        // check PSource algorithm
+        PSource pSource = oaepParameterSpec.getPSource();
+        String pSourceAlgorithm = pSource.getAlgorithm();
+        if (!pSourceAlgorithm.equalsIgnoreCase("PSpecified")) {
+            throw new InvalidAlgorithmParameterException
+                    ("Unsupported pSource algo: " + pSourceAlgorithm);
+        }
+    }
+
+    // compute OAEP data buffer length
+    private int getOAEPBufferLen(int outputSize, OAEPParameterSpec oaepParameterSpec, boolean encrypt)
+            throws InvalidKeyException {
+        if (!encrypt) {
+            return outputSize;
+        }
+        String mdName = oaepParameterSpec.getDigestAlgorithm();
+        String mgfMdName = ((MGF1ParameterSpec) oaepParameterSpec.getMGFParameters())
+                .getDigestAlgorithm();
+        int digestLen = KAEUtils.getDigestLength(mdName);
+        int bufferLen = outputSize - 2 - 2 * digestLen;
+        if (bufferLen < 0) {
+            throw new InvalidKeyException
+                    ("Key is too short for encryption using OAEPPadding" +
+                            " with " + mdName + " and MGF1" + mgfMdName);
+        }
+        return bufferLen;
+    }
+
+    // non-CRT private key, use the jdk soft calculation.
+    private boolean useJdkSoftCalculation() {
+        return (rsaKey instanceof RSAPrivateKey) && !(rsaKey instanceof RSAPrivateCrtKey);
+    }
+
+    // get the rsa padding
+    private RSAPadding getRSAPadding(KAERSAPaddingType paddingType, int paddedSize,
+                                     SecureRandom random, AlgorithmParameterSpec spec)
+            throws InvalidKeyException, InvalidAlgorithmParameterException {
+        RSAPadding rsaPadding;
+        if (KAERSAPaddingType.NoPadding.equals(paddingType)) {
+            rsaPadding = RSAPadding.getInstance(RSAPadding.PAD_NONE, paddedSize, random);
+        } else if (KAERSAPaddingType.PKCS1Padding.equals(paddingType)) {
+            int blockType = (mode <= MODE_DECRYPT) ? RSAPadding.PAD_BLOCKTYPE_2
+                    : RSAPadding.PAD_BLOCKTYPE_1;
+            rsaPadding = RSAPadding.getInstance(blockType, paddedSize, random);
+        } else {
+            rsaPadding = RSAPadding.getInstance(RSAPadding.PAD_OAEP_MGF1, paddedSize,
+                    random, (OAEPParameterSpec) spec);
+        }
+        return rsaPadding;
+    }
+
+    private boolean isEncrypt(int opmode) throws InvalidKeyException {
+        boolean encrypt;
+        switch (opmode) {
+            case Cipher.ENCRYPT_MODE:
+            case Cipher.WRAP_MODE:
+                encrypt = true;
+                break;
+            case Cipher.DECRYPT_MODE:
+            case Cipher.UNWRAP_MODE:
+                encrypt = false;
+                break;
+            default:
+                throw new InvalidKeyException("Unknown mode: " + opmode);
+        }
+        return encrypt;
+    }
+
+    // initialize this cipher
+    private void init(int opmode, Key key, SecureRandom random, AlgorithmParameterSpec params)
+            throws InvalidKeyException, InvalidAlgorithmParameterException {
+        // check the key, and convert to RSAKey
+        rsaKey = RSAKeyFactory.toRSAKey(key);
+
+        // init mode
+        boolean encrypt = isEncrypt(opmode);
+        if (key instanceof RSAPublicKey) {
+            mode = encrypt ? MODE_ENCRYPT : MODE_VERIFY;
+        } else {
+            mode = encrypt ? MODE_SIGN : MODE_DECRYPT;
+        }
+
+        int bufferLen = RSACore.getByteLength(rsaKey.getModulus());
+        outputSize = bufferLen;
+        bufOfs = 0;
+        if (KAERSAPaddingType.PKCS1Padding.equals(paddingType)) {
+            if (params != null) {
+                checkTlsRsaPremasterSecretParameterSpec(params);
+                spec = params;
+                this.random = random;   // for TLS RSA premaster secret
+            }
+            if (encrypt) {
+                bufferLen -= 11;
+            }
+        } else if (KAERSAPaddingType.OAEP.equals(paddingType)) {
+            if ((mode == MODE_SIGN) || (mode == MODE_VERIFY)) {
+                throw new InvalidKeyException
+                        ("OAEP cannot be used to sign or verify signatures");
+            }
+            if (params != null) {
+                checkOAEPParameterSpec(params);
+                spec = params;
+            } else {
+                spec = new OAEPParameterSpec(oaepHashAlgorithm, "MGF1",
+                        MGF1ParameterSpec.SHA1, PSource.PSpecified.DEFAULT);
+            }
+            bufferLen = getOAEPBufferLen(bufferLen, (OAEPParameterSpec) spec, encrypt);
+        }
+        buffer = new byte[bufferLen];
+
+        if (useJdkSoftCalculation()) {
+            this.padding = getRSAPadding(paddingType, outputSize, random, spec);
+        }
+    }
+
+    // internal update method
+    private void update(byte[] in, int inOfs, int inLen) {
+        if ((inLen == 0) || (in == null)) {
+            return;
+        }
+        if (inLen > (buffer.length - bufOfs)) {
+            bufOfs = buffer.length + 1;
+            return;
+        }
+        System.arraycopy(in, inOfs, buffer, bufOfs, inLen);
+        bufOfs += inLen;
+    }
+
+    // encrypt or decrypt for NoPadding or PKCS1Padding
+    private int doCryptNotOAEPPadding(long keyAddress, byte[] input, byte[] output) throws BadPaddingException {
+        int resultSize;
+        switch (mode) {
+            case MODE_SIGN:
+                resultSize = nativeRSAPrivateEncrypt(keyAddress, input.length, input, output, paddingType.getId());
+                break;
+            case MODE_VERIFY:
+                resultSize = nativeRSAPublicDecrypt(keyAddress, input.length, input, output, paddingType.getId());
+                break;
+            case MODE_ENCRYPT:
+                resultSize = nativeRSAPublicEncrypt(keyAddress, input.length, input, output, paddingType.getId());
+                break;
+            case MODE_DECRYPT:
+                resultSize = nativeRSAPrivateDecrypt(keyAddress, input.length, input, output, paddingType.getId());
+                break;
+            default:
+                throw new AssertionError("Internal error");
+        }
+        return resultSize;
+    }
+
+
+    // encrypt or decrypt for OAEPPadding
+    private int doCryptOAEPPadding(long keyAddress, byte[] input, byte[] output, OAEPParameterSpec oaepParameterSpec)
+            throws BadPaddingException {
+        // oaep digest algorithm
+        String oaepMdAlgorithm = KAEUtils.getKAEDigestName(oaepParameterSpec.getDigestAlgorithm());
+        // mgf1 digest algorithm
+        MGF1ParameterSpec mgf1ParameterSpec = (MGF1ParameterSpec) oaepParameterSpec.getMGFParameters();
+        String mgf1MdAlgorithm = KAEUtils.getKAEDigestName(mgf1ParameterSpec.getDigestAlgorithm());
+        // label
+        PSource pSource = oaepParameterSpec.getPSource();
+        byte[] label = ((PSource.PSpecified) pSource).getValue();
+        int resultSize;
+        switch (mode) {
+            case MODE_ENCRYPT:
+                resultSize = nativeRSAEncryptOAEPPadding(keyAddress, input.length, input, output, paddingType.getId(),
+                        oaepMdAlgorithm, mgf1MdAlgorithm, label);
+                break;
+            case MODE_DECRYPT:
+                resultSize = nativeRSADecryptOAEPPadding(keyAddress, input.length, input, output, paddingType.getId(),
+                        oaepMdAlgorithm, mgf1MdAlgorithm, label);
+                break;
+            default:
+                throw new AssertionError("Internal error");
+        }
+        return resultSize;
+    }
+
+    // get input bytes
+    private byte[] getInputBytes(byte[] buffer, int bufOfs, KAERSAPaddingType paddingType) {
+        if (bufOfs == buffer.length) {
+            return buffer;
+        }
+
+        // if padding type is NoPadding , data should move to end
+        final byte[] input;
+        if (KAERSAPaddingType.NoPadding.equals(paddingType)) {
+            input = new byte[buffer.length];
+            System.arraycopy(buffer, 0, input, buffer.length - bufOfs, bufOfs);
+        } else {
+            input = Arrays.copyOf(buffer, bufOfs);
+        }
+        return input;
+    }
+
+    // internal doFinal() method. Here we perform the actual RSA operation
+    private byte[] doFinal() throws BadPaddingException, IllegalBlockSizeException {
+        if (bufOfs > buffer.length) {
+            throw new IllegalBlockSizeException("Data must not be longer "
+                    + "than " + buffer.length + " bytes");
+        }
+
+        if (useJdkSoftCalculation()) {
+            return doFinalForJdkSoftCalculation(padding);
+        }
+
+        // get input bytes
+        final byte[] input = getInputBytes(buffer, bufOfs, paddingType);
+
+        try {
+            rsaKeyHolder = new KAERSAKeyHolder(this, rsaKey);
+        } catch (InvalidKeyException e) {
+            throw new RuntimeException(e.getMessage());
+        }
+
+        long keyAddress = rsaKeyHolder.keyAddress;
+        byte[] output = new byte[outputSize];
+        int cipherTextLength;
+        try {
+            if (KAERSAPaddingType.OAEP.equals(paddingType)) {
+                // do crypt for OAEPPadding
+                cipherTextLength = doCryptOAEPPadding(keyAddress, input, output, (OAEPParameterSpec) spec);
+            } else {
+                // do crypt for NoPadding or PKCS1Padding
+                cipherTextLength = doCryptNotOAEPPadding(keyAddress, input, output);
+            }
+
+            // If mode is signing or verifying , and the length of the ciphertext is less than output length,
+            // just keep output length ciphertext.
+            if ((mode == MODE_VERIFY || mode == MODE_DECRYPT) && cipherTextLength != output.length) {
+                output = Arrays.copyOf(output, cipherTextLength);
+            }
+        } finally {
+            bufOfs = 0;
+            resetKeyHolder();
+        }
+        return output;
+    }
+
+    private byte[] doFinalForJdkSoftCalculation(RSAPadding padding) throws BadPaddingException {
+        try {
+            byte[] data;
+            switch (mode) {
+                case MODE_SIGN:
+                    data = padding.pad(buffer, 0, bufOfs);
+                    return RSACore.rsa(data, (RSAPrivateKey) rsaKey, true);
+                case MODE_DECRYPT:
+                    byte[] decryptBuffer = RSACore.convert(buffer, 0, bufOfs);
+                    data = RSACore.rsa(decryptBuffer, (RSAPrivateKey) rsaKey, false);
+                    return padding.unpad(data);
+                default:
+                    throw new AssertionError("Internal error");
+            }
+        } finally {
+            bufOfs = 0;
+        }
+    }
+
+    // see JCE spec
+    @Override
+    protected byte[] engineUpdate(byte[] in, int inOfs, int inLen) {
+        update(in, inOfs, inLen);
+        return B0;
+    }
+
+    // see JCE spec
+    @Override
+    protected int engineUpdate(byte[] in, int inOfs, int inLen, byte[] out,
+                               int outOfs) {
+        update(in, inOfs, inLen);
+        return 0;
+    }
+
+    // see JCE spec
+    @Override
+    protected byte[] engineDoFinal(byte[] in, int inOfs, int inLen)
+            throws BadPaddingException, IllegalBlockSizeException {
+        update(in, inOfs, inLen);
+        return doFinal();
+    }
+
+    // see JCE spec
+    @Override
+    protected int engineDoFinal(byte[] in, int inOfs, int inLen, byte[] out, int outOfs)
+            throws ShortBufferException, BadPaddingException, IllegalBlockSizeException {
+        if (outputSize > out.length - outOfs) {
+            throw new ShortBufferException
+                    ("Need " + outputSize + " bytes for output");
+        }
+        update(in, inOfs, inLen);
+        byte[] result = doFinal();
+        int length = result.length;
+        System.arraycopy(result, 0, out, outOfs, length);
+        return length;
+    }
+
+    // see JCE spec
+    @Override
+    protected byte[] engineWrap(Key key) throws InvalidKeyException,
+            IllegalBlockSizeException {
+        byte[] encoded = key.getEncoded();
+        if ((encoded == null) || (encoded.length == 0)) {
+            throw new InvalidKeyException("Could not obtain encoded key");
+        }
+        if (encoded.length > buffer.length) {
+            throw new InvalidKeyException("Key is too long for wrapping");
+        }
+        update(encoded, 0, encoded.length);
+        try {
+            return doFinal();
+        } catch (BadPaddingException e) {
+            // should not occur
+            throw new InvalidKeyException("Wrapping failed", e);
+        }
+    }
+
+    // see JCE spec
+    @Override
+    @SuppressWarnings("deprecation")
+    protected Key engineUnwrap(byte[] wrappedKey, String algorithm, int type)
+            throws InvalidKeyException, NoSuchAlgorithmException {
+        if (wrappedKey.length > buffer.length) {
+            throw new InvalidKeyException("Key is too long for unwrapping");
+        }
+
+        boolean isTlsRsaPremasterSecret = "TlsRsaPremasterSecret".equals(algorithm);
+        Exception failover = null;
+        byte[] encoded = null;
+
+        update(wrappedKey, 0, wrappedKey.length);
+        try {
+            encoded = doFinal();
+        } catch (BadPaddingException e) {
+            if (isTlsRsaPremasterSecret) {
+                failover = e;
+            } else {
+                throw new InvalidKeyException("Unwrapping failed", e);
+            }
+        } catch (IllegalBlockSizeException e) {
+            // should not occur, handled with length check above
+            throw new InvalidKeyException("Unwrapping failed", e);
+        }
+
+        if (isTlsRsaPremasterSecret) {
+            if (!(spec instanceof TlsRsaPremasterSecretParameterSpec)) {
+                throw new IllegalStateException(
+                        "No TlsRsaPremasterSecretParameterSpec specified");
+            }
+
+            // polish the TLS premaster secret
+            encoded = KeyUtil.checkTlsPreMasterSecretKey(
+                    ((TlsRsaPremasterSecretParameterSpec) spec).getClientVersion(),
+                    ((TlsRsaPremasterSecretParameterSpec) spec).getServerVersion(),
+                    random, encoded, (failover != null));
+        }
+        return KAEUtils.ConstructKeys.constructKey(encoded, algorithm, type);
+    }
+
+    // see JCE spec
+    @Override
+    protected int engineGetKeySize(Key key) throws InvalidKeyException {
+        RSAKey newRSAKey = RSAKeyFactory.toRSAKey(key);
+        return newRSAKey.getModulus().bitLength();
+    }
+
+    // reset the key holder
+    private void resetKeyHolder() {
+        if (rsaKeyHolder != null) {
+            rsaKeyHolder.dispose(true);
+            rsaKeyHolder = null;
+        }
+    }
+
+    // create KAE rsa key
+    protected static native long nativeCreateRSAPrivateCrtKey(byte[] n, byte[] e, byte[] d, byte[] p, byte[] q,
+                                                              byte[] dmp1, byte[] dmq1, byte[] iqmp);
+
+    // create KAE rsa public key
+    protected static native long nativeCreateRSAPublicKey(byte[] n, byte[] e);
+
+    // encrypt by private key for padding type (NOPADDING|PKCS1PADDING)
+    protected static native int nativeRSAPrivateEncrypt(long keyAddress, int inLen, byte[] in, byte[] out,
+                                                        int paddingType) throws BadPaddingException;
+
+    // decrypt by private key for padding type (NOPADDING|PKCS1PADDING)
+    protected static native int nativeRSAPrivateDecrypt(long keyAddress, int inLen, byte[] in, byte[] out,
+                                                        int paddingType) throws BadPaddingException;
+
+    // encrypt by public key for padding type (NOPADDING|PKCS1PADDING)
+    protected static native int nativeRSAPublicEncrypt(long keyAddress, int inLen, byte[] in, byte[] out,
+                                                       int paddingType) throws BadPaddingException;
+
+    // decrypt by public key for padding type (NOPADDING|PKCS1PADDING)
+    protected static native int nativeRSAPublicDecrypt(long keyAddress, int inLen, byte[] in, byte[] out,
+                                                       int paddingType) throws BadPaddingException;
+
+    // encrypt by public for padding type (OAEPPADDING)
+    protected static native int nativeRSAEncryptOAEPPadding(long keyAddress, int inLen, byte[] in, byte[] out,
+                                                            int paddingType, String oaepMdAlgo, String mgf1MdAlgo,
+                                                            byte[] label) throws BadPaddingException;
+
+    // decrypt by public for padding type (OAEPPADDING)
+    protected static native int nativeRSADecryptOAEPPadding(long keyAddress, int inLen, byte[] in, byte[] out,
+                                                            int paddingType, String oaepMdAlgo, String mgf1MdAlgo,
+                                                            byte[] label) throws BadPaddingException;
+
+    // free the key
+    protected static native void nativeFreeKey(long keyAddress);
+
+    /**
+     * The rsa openssl key holder , use PhantomReference in case of native memory leaks
+     */
+    private static class KAERSAKeyHolder extends PhantomReference<KAERSACipher>
+            implements Comparable<KAERSAKeyHolder> {
+        private static ReferenceQueue<KAERSACipher> referenceQueue = new ReferenceQueue<>();
+        private static Set<KAERSAKeyHolder> referenceList = new ConcurrentSkipListSet<>();
+        private final long keyAddress;
+
+        KAERSAKeyHolder(KAERSACipher rsaCipher, RSAKey rsaKey) throws InvalidKeyException {
+            super(rsaCipher, referenceQueue);
+            this.keyAddress = getKeyAddress(rsaKey);
+            referenceList.add(this);
+            drainRefQueueBounded();
+        }
+
+        private static void drainRefQueueBounded() {
+            while (true) {
+                KAERSAKeyHolder next = (KAERSAKeyHolder) referenceQueue.poll();
+                if (next == null) {
+                    break;
+                }
+                next.dispose(true);
+            }
+        }
+
+        void dispose(boolean needFree) {
+            referenceList.remove(this);
+            try {
+                if (needFree) {
+                    nativeFreeKey(keyAddress);
+                }
+            } finally {
+                this.clear();
+            }
+        }
+
+        @Override
+        public int compareTo(KAERSAKeyHolder other) {
+            if (this.keyAddress == other.keyAddress) {
+                return 0;
+            } else {
+                return (this.keyAddress < other.keyAddress) ? -1 : 1;
+            }
+        }
+
+        private long getKeyAddress(RSAKey rsaKey) throws InvalidKeyException {
+            long address;
+            if (rsaKey instanceof RSAPrivateCrtKey) { // RSAPrivateCrtKeyImpl
+                address = getKeyAddress((RSAPrivateCrtKey) rsaKey);
+            } else if (rsaKey instanceof RSAPublicKey) { // RSAPublicKeyImpl
+                address = getKeyAddress((RSAPublicKey) rsaKey);
+            } else {
+                throw new InvalidKeyException("Invalid RSAKey implement " + rsaKey.getClass());
+            }
+            return address;
+        }
+
+        private long getKeyAddress(RSAPrivateCrtKey key) throws InvalidKeyException {
+            checkKey(key);
+            try {
+                return nativeCreateRSAPrivateCrtKey(
+                        key.getModulus().toByteArray(),
+                        key.getPublicExponent().toByteArray(),
+                        key.getPrivateExponent().toByteArray(),
+                        key.getPrimeP().toByteArray(),
+                        key.getPrimeQ().toByteArray(),
+                        key.getPrimeExponentP().toByteArray(),
+                        key.getPrimeExponentQ().toByteArray(),
+                        key.getCrtCoefficient().toByteArray());
+            } catch (Exception e) {
+                throw new InvalidKeyException(e);
+            }
+        }
+
+        private long getKeyAddress(RSAPublicKey key) throws InvalidKeyException {
+            checkKey(key);
+            try {
+                return nativeCreateRSAPublicKey(
+                        key.getModulus().toByteArray(),
+                        key.getPublicExponent().toByteArray()
+                );
+            } catch (Exception e) {
+                throw new InvalidKeyException(e);
+            }
+        }
+
+        private void checkKey(RSAPrivateCrtKey key) throws InvalidKeyException {
+            boolean isInValidKey = key.getModulus() == null
+                    || key.getPublicExponent() == null
+                    || key.getPrivateExponent() == null
+                    || key.getPrimeP() == null
+                    || key.getPrimeQ() == null
+                    || key.getPrimeExponentP() == null
+                    || key.getPrimeExponentQ() == null
+                    || key.getCrtCoefficient() == null;
+            if (isInValidKey) {
+                throw new InvalidKeyException("Invalid RSA private key");
+            }
+        }
+
+        private void checkKey(RSAPublicKey key) throws InvalidKeyException {
+            if (key.getModulus() == null || key.getPublicExponent() == null) {
+                throw new InvalidKeyException("Invalid RSA public key");
+            }
+        }
+    }
+}
diff --git a/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAERSAKeyPairGenerator.java b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAERSAKeyPairGenerator.java
new file mode 100644
index 000000000..88bd30574
--- /dev/null
+++ b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAERSAKeyPairGenerator.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.openeuler.security.openssl;
+
+import sun.security.rsa.*;
+import sun.security.rsa.RSAUtil.KeyType;
+import sun.security.util.SecurityProviderConstants;
+
+import java.math.BigInteger;
+import java.security.*;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.RSAKeyGenParameterSpec;
+
+public abstract class KAERSAKeyPairGenerator extends KeyPairGeneratorSpi {
+    // public exponent to use
+    private BigInteger publicExponent;
+
+    // size of the key to generate, >= KAERSAKeyFactory.MIN_MODLEN
+    private int keySize;
+
+    private final KeyType type;
+
+    private AlgorithmParameterSpec keyParams;
+
+
+    KAERSAKeyPairGenerator(KeyType keyType, int keySize) {
+        this.type = keyType;
+        initialize(keySize, null);
+    }
+
+    // initialize the generator. See JCA doc
+    @Override
+    public void initialize(int keySize, SecureRandom random) {
+        try {
+            initialize(new RSAKeyGenParameterSpec(keySize,
+                    RSAKeyGenParameterSpec.F4), null);
+        } catch (InvalidAlgorithmParameterException iape) {
+            throw new InvalidParameterException(iape.getMessage());
+        }
+    }
+
+    // second initialize method. See JCA doc
+    @Override
+    public void initialize(AlgorithmParameterSpec params, SecureRandom random)
+            throws InvalidAlgorithmParameterException {
+        if (!(params instanceof RSAKeyGenParameterSpec)) {
+            throw new InvalidAlgorithmParameterException
+                    ("Params must be instance of RSAKeyGenParameterSpec");
+        }
+
+        RSAKeyGenParameterSpec rsaSpec = (RSAKeyGenParameterSpec) params;
+        int tmpKeySize = rsaSpec.getKeysize();
+        BigInteger tmpPublicExponent = rsaSpec.getPublicExponent();
+        keyParams = rsaSpec.getKeyParams();
+
+        if (tmpPublicExponent == null) {
+            tmpPublicExponent = RSAKeyGenParameterSpec.F4;
+        } else {
+            if (tmpPublicExponent.compareTo(RSAKeyGenParameterSpec.F0) < 0) {
+                throw new InvalidAlgorithmParameterException
+                        ("Public exponent must be 3 or larger");
+            }
+            if (tmpPublicExponent.bitLength() > tmpKeySize) {
+                throw new InvalidAlgorithmParameterException
+                        ("Public exponent must be smaller than key size");
+            }
+        }
+
+        // do not allow unreasonably large key sizes, probably user error
+        try {
+            RSAKeyFactory.checkKeyLengths(tmpKeySize, tmpPublicExponent,
+                    512, 64 * 1024);
+        } catch (InvalidKeyException e) {
+            throw new InvalidAlgorithmParameterException(
+                    "Invalid key sizes", e);
+        }
+
+        this.keySize = tmpKeySize;
+        this.publicExponent = tmpPublicExponent;
+    }
+
+    // generate the keypair. See JCA doc
+    @Override
+    public KeyPair generateKeyPair() {
+        // get the KAE RSA key Parameters
+        byte[][] params = nativeGenerateKeyPair(keySize, publicExponent.toByteArray());
+
+        try {
+            // check KAE RSA key Parameters
+            checkKAERSAParams(params);
+
+            BigInteger n = new BigInteger(params[0]);
+            BigInteger e = new BigInteger(params[1]);
+            BigInteger d = new BigInteger(params[2]);
+            BigInteger p = new BigInteger(params[3]);
+            BigInteger q = new BigInteger(params[4]);
+            BigInteger pe = new BigInteger(params[5]);
+            BigInteger qe = new BigInteger(params[6]);
+            BigInteger coeff = new BigInteger(params[7]);
+
+            // public key
+            PublicKey publicKey = RSAPublicKeyImpl.newKey(type, keyParams, n, e);
+
+            // private key
+            PrivateKey privateKey = RSAPrivateCrtKeyImpl.newKey(type, keyParams, n, e, d, p, q, pe, qe, coeff);
+
+            return new KeyPair(publicKey, privateKey);
+        } catch (InvalidKeyException ex) {
+            throw new RuntimeException(ex);
+        }
+    }
+
+    // check KAE RSA key Parameters
+    private void checkKAERSAParams(byte[][] params) throws InvalidKeyException {
+        if (params == null || params.length < 8) {
+            throw new InvalidKeyException("Invalid KAE RSA key Parameter");
+        }
+
+        for (int i = 0; i < params.length; i++) {
+            if (params[i] == null) {
+                throw new InvalidKeyException("Invalid KAE RSA key Parameter , params[" + i + "] = null");
+            }
+        }
+    }
+
+    public static final class Legacy extends KAERSAKeyPairGenerator {
+        public Legacy() {
+            super(KeyType.RSA, SecurityProviderConstants.DEF_RSA_KEY_SIZE);
+        }
+    }
+
+    public static final class PSS extends KAERSAKeyPairGenerator {
+        public PSS() {
+            super(KeyType.PSS, SecurityProviderConstants.DEF_RSASSA_PSS_KEY_SIZE);
+        }
+    }
+
+    // generate key pair
+    static native byte[][] nativeGenerateKeyPair(int keySize, byte[] publicExponent) throws RuntimeException;
+}
diff --git a/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAERSAPSSSignature.java b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAERSAPSSSignature.java
new file mode 100644
index 000000000..065317148
--- /dev/null
+++ b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAERSAPSSSignature.java
@@ -0,0 +1,683 @@
+/*
+ * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.openeuler.security.openssl;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+import java.security.*;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.PSSParameterSpec;
+import java.security.spec.MGF1ParameterSpec;
+import java.security.interfaces.*;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Locale;
+import java.util.Set;
+
+import sun.security.rsa.PSSParameters;
+import sun.security.rsa.RSACore;
+import sun.security.jca.JCAUtil;
+
+import javax.crypto.BadPaddingException;
+
+/**
+ * PKCS#1 v2.2 RSASSA-PSS signatures with various message digest algorithms.
+ * RSASSA-PSS implementation takes the message digest algorithm, MGF algorithm,
+ * and salt length values through the required signature PSS parameters.
+ * We support SHA-1, SHA-224, SHA-256, SHA-384, SHA-512.
+ * The Openssl does not support rsa signatures with SHA-512/224 and SHA-512/256 as the digest algorithm,
+ * so we have not implemented them.
+ * The Openssl does not support non-CRT private key , when signing with a non-CRT private key, we use the sun sign.
+ */
+@SuppressWarnings({"deprecation", "removal"})
+public class KAERSAPSSSignature extends SignatureSpi {
+    // openssl unsupport rsa sign with digest algorithm
+    private static final Set<String> UNSUPPORTED_DIGEST_ALGORITHM = new HashSet<>(
+            Arrays.asList("SHA-512/224", "SHA-512/256"));
+
+    private static final byte[] EIGHT_BYTES_OF_ZEROS = new byte[8];
+
+    // message digest implementation we use for hashing the data
+    private MessageDigest md;
+
+    // flag indicating whether the digest is reset
+    private boolean digestReset = true;
+
+    // private key, if initialized for signing
+    private RSAPrivateKey privKey = null;
+
+    // public key, if initialized for verifying
+    private RSAPublicKey pubKey = null;
+
+    // PSS parameters from signatures and keys respectively
+    private PSSParameterSpec sigParams = null;
+
+    // PRNG used to generate salt bytes if none given
+    private SecureRandom random;
+
+    /**
+     * Construct a new RSAPSSSignatur with arbitrary digest algorithm
+     */
+    public KAERSAPSSSignature() {
+        this.md = null;
+    }
+
+    // initialize for verification. See JCA doc
+    @Override
+    protected void engineInitVerify(PublicKey publicKey) throws InvalidKeyException {
+        if (!(publicKey instanceof RSAPublicKey)) {
+            throw new InvalidKeyException("key must be RSAPublicKey");
+        }
+        this.pubKey = (RSAPublicKey) isValid((RSAKey) publicKey);
+        this.privKey = null;
+        resetDigest();
+    }
+
+    // initialize for signing. See JCA doc
+    @Override
+    protected void engineInitSign(PrivateKey privateKey) throws InvalidKeyException {
+        engineInitSign(privateKey, null);
+    }
+
+    // initialize for signing. See JCA doc
+    @Override
+    protected void engineInitSign(PrivateKey privateKey, SecureRandom random) throws InvalidKeyException {
+        if (!(privateKey instanceof RSAPrivateKey)) {
+            throw new InvalidKeyException("key must be RSAPrivateKey");
+        }
+        this.privKey = (RSAPrivateKey) isValid((RSAKey) privateKey);
+        this.pubKey = null;
+        this.random =
+                (random == null ? JCAUtil.getSecureRandom() : random);
+        resetDigest();
+    }
+
+    /**
+     * Utility method for checking the key PSS parameters against signature
+     * PSS parameters.
+     * Returns false if any of the digest/MGF algorithms and trailerField
+     * values does not match or if the salt length in key parameters is
+     * larger than the value in signature parameters.
+     */
+    private static boolean isCompatible(AlgorithmParameterSpec keyParams, PSSParameterSpec sigParams) {
+        if (keyParams == null) {
+            // key with null PSS parameters means no restriction
+            return true;
+        }
+        if (!(keyParams instanceof PSSParameterSpec)) {
+            return false;
+        }
+        // nothing to compare yet, defer the check to when sigParams is set
+        if (sigParams == null) {
+            return true;
+        }
+        PSSParameterSpec pssKeyParams = (PSSParameterSpec) keyParams;
+        // first check the salt length requirement
+        if (pssKeyParams.getSaltLength() > sigParams.getSaltLength()) {
+            return false;
+        }
+
+        // compare equality of the rest of fields based on DER encoding
+        PSSParameterSpec keyParams2 =
+                new PSSParameterSpec(pssKeyParams.getDigestAlgorithm(),
+                        pssKeyParams.getMGFAlgorithm(),
+                        pssKeyParams.getMGFParameters(),
+                        sigParams.getSaltLength(),
+                        pssKeyParams.getTrailerField());
+
+        // skip the JCA overhead
+        try {
+            byte[] encoded = PSSParameters.getEncoded(keyParams2);
+            byte[] encoded2 = PSSParameters.getEncoded(sigParams);
+            return Arrays.equals(encoded, encoded2);
+        } catch (IOException e) {
+            return false;
+        }
+    }
+
+    /**
+     * Validate the specified RSAKey and its associated parameters against
+     * internal signature parameters.
+     */
+    private RSAKey isValid(RSAKey rsaKey) throws InvalidKeyException {
+        try {
+            AlgorithmParameterSpec keyParams = rsaKey.getParams();
+            // validate key parameters
+            if (!isCompatible(rsaKey.getParams(), this.sigParams)) {
+                throw new InvalidKeyException
+                        ("Key contains incompatible PSS parameter values");
+            }
+            // validate key length
+            if (this.sigParams != null) {
+                Integer hLen =
+                        KAEUtils.getDigestLength(this.sigParams.getDigestAlgorithm());
+                if (hLen == null) {
+                    throw new ProviderException("Unsupported digest algo: " +
+                            this.sigParams.getDigestAlgorithm());
+                }
+                checkKeyLength(rsaKey, hLen, this.sigParams.getSaltLength());
+            }
+            return rsaKey;
+        } catch (SignatureException e) {
+            throw new InvalidKeyException(e);
+        }
+    }
+
+    /**
+     * Validate the specified Signature PSS parameters.
+     */
+    private PSSParameterSpec validateSigParams(AlgorithmParameterSpec p) throws InvalidAlgorithmParameterException {
+        if (p == null) {
+            throw new InvalidAlgorithmParameterException
+                    ("Parameters cannot be null");
+        }
+        if (!(p instanceof PSSParameterSpec)) {
+            throw new InvalidAlgorithmParameterException
+                    ("parameters must be type PSSParameterSpec");
+        }
+        // no need to validate again if same as current signature parameters
+        PSSParameterSpec params = (PSSParameterSpec) p;
+        if (params == this.sigParams) {
+            return params;
+        }
+
+        RSAKey key = (this.privKey == null ? this.pubKey : this.privKey);
+        // check against keyParams if set
+        if (key != null) {
+            if (!isCompatible(key.getParams(), params)) {
+                throw new InvalidAlgorithmParameterException
+                        ("Signature parameters does not match key parameters");
+            }
+        }
+        // now sanity check the parameter values
+        if (!(params.getMGFAlgorithm().equalsIgnoreCase("MGF1"))) {
+            throw new InvalidAlgorithmParameterException("Only supports MGF1");
+        }
+        if (params.getTrailerField() != PSSParameterSpec.TRAILER_FIELD_BC) {
+            throw new InvalidAlgorithmParameterException("Only supports TrailerFieldBC(1)");
+        }
+        String digestAlgo = params.getDigestAlgorithm();
+        // check key length again
+        if (key != null) {
+            try {
+                int hLen = KAEUtils.getDigestLength(digestAlgo);
+                checkKeyLength(key, hLen, params.getSaltLength());
+            } catch (SignatureException e) {
+                throw new InvalidAlgorithmParameterException(e);
+            }
+        }
+        return params;
+    }
+
+    /**
+     * Ensure the object is initialized with key and parameters and
+     * reset digest
+     */
+    private void ensureInit() throws SignatureException {
+        RSAKey key = (this.privKey == null ? this.pubKey : this.privKey);
+        if (key == null) {
+            throw new SignatureException("Missing key");
+        }
+        if (this.sigParams == null) {
+            // Parameters are required for signature verification
+            throw new SignatureException
+                    ("Parameters required for RSASSA-PSS signatures");
+        }
+    }
+
+    /**
+     * Utility method for checking key length against digest length and
+     * salt length
+     */
+    private static void checkKeyLength(RSAKey key, int digestLen, int saltLen) throws SignatureException {
+        if (key != null) {
+            int keyLength = getKeyLengthInBits(key) >> 3;
+            int minLength = Math.addExact(Math.addExact(digestLen, saltLen), 2);
+            if (keyLength < minLength) {
+                throw new SignatureException
+                        ("Key is too short, need min " + minLength);
+            }
+        }
+    }
+
+    /**
+     * Reset the message digest if it is not already reset.
+     */
+    private void resetDigest() {
+        if (digestReset == false) {
+            this.md.reset();
+            digestReset = true;
+        }
+    }
+
+    /**
+     * Return the message digest value.
+     */
+    private byte[] getDigestValue() {
+        digestReset = true;
+        return this.md.digest();
+    }
+
+    // update the signature with the plaintext data. See JCA doc
+    @Override
+    protected void engineUpdate(byte b) throws SignatureException {
+        ensureInit();
+        this.md.update(b);
+        digestReset = false;
+    }
+
+    // update the signature with the plaintext data. See JCA doc
+    @Override
+    protected void engineUpdate(byte[] b, int off, int len) throws SignatureException {
+        ensureInit();
+        this.md.update(b, off, len);
+        digestReset = false;
+    }
+
+    // update the signature with the plaintext data. See JCA doc
+    @Override
+    protected void engineUpdate(ByteBuffer b) {
+        try {
+            ensureInit();
+        } catch (SignatureException se) {
+            // hack for working around API bug
+            throw new RuntimeException(se.getMessage());
+        }
+        this.md.update(b);
+        digestReset = false;
+    }
+
+    // determine whether the digest is valid
+    private boolean isValidDigest() {
+        String digestName = this.md.getAlgorithm();
+        if (UNSUPPORTED_DIGEST_ALGORITHM.contains(digestName.toUpperCase(Locale.ROOT))) {
+            return false;
+        }
+        AlgorithmParameterSpec mgfParams = this.sigParams.getMGFParameters();
+        String mgfDigestName = "";
+        if (mgfParams != null) {
+            mgfDigestName =
+                    ((MGF1ParameterSpec) mgfParams).getDigestAlgorithm();
+        }
+        return !UNSUPPORTED_DIGEST_ALGORITHM.contains(mgfDigestName.toUpperCase(Locale.ROOT));
+    }
+
+    // determine whether use kae sign
+    private boolean useKaeSign() {
+        return (privKey instanceof RSAPrivateCrtKey) && isValidDigest();
+    }
+
+    // sun sign
+    private byte[] sunSign(byte[] mHash) throws SignatureException {
+        try {
+            byte[] encoded = encodeSignature(mHash);
+            return RSACore.rsa(encoded, privKey, true);
+        } catch (GeneralSecurityException e) {
+            throw new SignatureException("Could not sign data", e);
+        } catch (IOException e) {
+            throw new SignatureException("Could not encode data", e);
+        }
+    }
+
+    // kae sign
+    private byte[] kaeSign(byte[] mHash) throws SignatureException {
+        String kaeDigestName = KAEUtils.getKAEDigestName(this.sigParams.getDigestAlgorithm());
+        String mgfDigestName = kaeDigestName;
+        AlgorithmParameterSpec mgfParams = this.sigParams.getMGFParameters();
+        if (mgfParams != null) {
+            mgfDigestName =
+                    ((MGF1ParameterSpec) mgfParams).getDigestAlgorithm();
+        }
+        String mgf1DigestName = KAEUtils.getKAEDigestName(mgfDigestName);
+
+        RSAPrivateCrtKey privateCrtKey = (RSAPrivateCrtKey) privKey;
+        long keyAddress = KAERSACipher.nativeCreateRSAPrivateCrtKey(
+                privateCrtKey.getModulus().toByteArray(),
+                privateCrtKey.getPublicExponent().toByteArray(),
+                privateCrtKey.getPrivateExponent().toByteArray(),
+                privateCrtKey.getPrimeP().toByteArray(),
+                privateCrtKey.getPrimeQ().toByteArray(),
+                privateCrtKey.getPrimeExponentP().toByteArray(),
+                privateCrtKey.getPrimeExponentQ().toByteArray(),
+                privateCrtKey.getCrtCoefficient().toByteArray());
+        byte[] bytes;
+        try {
+            bytes = KAERSASignatureNative.pssSign(keyAddress, kaeDigestName, mHash,
+                    KAERSAPaddingType.PKCS1PssPadding.getId(),
+                    mgf1DigestName, this.sigParams.getSaltLength());
+        } catch (SignatureException e) {
+            throw e;
+        } finally {
+            KAERSACipher.nativeFreeKey(keyAddress);
+        }
+        return bytes;
+    }
+
+    // sign the data and return the signature. See JCA doc
+    @Override
+    protected byte[] engineSign() throws SignatureException {
+        ensureInit();
+        byte[] mHash = getDigestValue();
+        if (useKaeSign()) {
+            return kaeSign(mHash);
+        }
+        return sunSign(mHash);
+    }
+
+    // determine whether use kae verify
+    private boolean useKaeVerify() {
+        return isValidDigest();
+    }
+
+    // sun verify
+    private boolean sunVerify(byte[] mHash, byte[] sigBytes) throws SignatureException {
+        try {
+            byte[] decrypted = RSACore.rsa(sigBytes, this.pubKey);
+            return decodeSignature(mHash, decrypted);
+        } catch (javax.crypto.BadPaddingException e) {
+            // occurs if the app has used the wrong RSA public key
+            // or if sigBytes is invalid
+            // return false rather than propagating the exception for
+            // compatibility/ease of use
+            return false;
+        } catch (IOException e) {
+            throw new SignatureException("Signature encoding error", e);
+        } finally {
+            resetDigest();
+        }
+    }
+
+    // kae verify
+    private boolean kaeVerify(byte[] mHash, byte[] sigBytes) throws SignatureException {
+        String kaeDigestName = KAEUtils.getKAEDigestName(this.sigParams.getDigestAlgorithm());
+        String mgfDigestName = kaeDigestName;
+        AlgorithmParameterSpec mgfParams = this.sigParams.getMGFParameters();
+        if (mgfParams != null) {
+            mgfDigestName =
+                    ((MGF1ParameterSpec) mgfParams).getDigestAlgorithm();
+        }
+        String mgf1KaeDigestName = KAEUtils.getKAEDigestName(mgfDigestName);
+
+        long keyAddress = KAERSACipher.nativeCreateRSAPublicKey(this.pubKey.getModulus().toByteArray(),
+                this.pubKey.getPublicExponent().toByteArray());
+        boolean verify;
+        try {
+            verify = KAERSASignatureNative.pssVerify(keyAddress, kaeDigestName, mHash,
+                    KAERSAPaddingType.PKCS1PssPadding.getId(), mgf1KaeDigestName,
+                    this.sigParams.getSaltLength(), sigBytes);
+        } catch (SignatureException e) {
+            throw e;
+        } catch (BadPaddingException e) {
+            // occurs if the app has used the wrong RSA public key
+            // or if sigBytes is invalid or sourceBytes is invalid
+            // return false rather than propagating the exception for
+            // compatibility/ease of use
+            return false;
+        } finally {
+            resetDigest();
+            KAERSACipher.nativeFreeKey(keyAddress);
+        }
+        return verify;
+    }
+
+    // verify the data and return the result. See JCA doc
+    // should be reset to the state after engineInitVerify call.
+    @Override
+    protected boolean engineVerify(byte[] sigBytes) throws SignatureException {
+        ensureInit();
+        if (sigBytes.length != RSACore.getByteLength(this.pubKey)) {
+            throw new SignatureException("Signature length not correct: got " +
+                    sigBytes.length + " but was expecting " +
+                    RSACore.getByteLength(this.pubKey));
+        }
+        byte[] mHash = getDigestValue();
+        if (useKaeVerify()) {
+            return kaeVerify(mHash, sigBytes);
+        }
+        return sunVerify(mHash, sigBytes);
+    }
+
+    // return the modulus length in bits
+    private static int getKeyLengthInBits(RSAKey k) {
+        if (k != null) {
+            return k.getModulus().bitLength();
+        }
+        return -1;
+    }
+
+    /**
+     * Encode the digest 'mHash', return the to-be-signed data.
+     * Also used by the PKCS#11 provider.
+     */
+    private byte[] encodeSignature(byte[] mHash) throws IOException, DigestException {
+        AlgorithmParameterSpec mgfParams = this.sigParams.getMGFParameters();
+        String mgfDigestAlgo;
+        if (mgfParams != null) {
+            mgfDigestAlgo =
+                    ((MGF1ParameterSpec) mgfParams).getDigestAlgorithm();
+        } else {
+            mgfDigestAlgo = this.md.getAlgorithm();
+        }
+        try {
+            int emBits = getKeyLengthInBits(this.privKey) - 1;
+            int emLen = (emBits + 7) >> 3;
+            int hLen = this.md.getDigestLength();
+            int dbLen = emLen - hLen - 1;
+            int sLen = this.sigParams.getSaltLength();
+
+            // maps DB into the corresponding region of EM and
+            // stores its bytes directly into EM
+            byte[] em = new byte[emLen];
+
+            // step7 and some of step8
+            em[dbLen - sLen - 1] = (byte) 1; // set DB's padding2 into EM
+            em[em.length - 1] = (byte) 0xBC; // set trailer field of EM
+
+            if (!digestReset) {
+                throw new ProviderException("Digest should be reset");
+            }
+            // step5: generates M' using padding1, mHash, and salt
+            this.md.update(EIGHT_BYTES_OF_ZEROS);
+            digestReset = false; // mark digest as it now has data
+            this.md.update(mHash);
+            if (sLen != 0) {
+                // step4: generate random salt
+                byte[] salt = new byte[sLen];
+                this.random.nextBytes(salt);
+                this.md.update(salt);
+
+                // step8: set DB's salt into EM
+                System.arraycopy(salt, 0, em, dbLen - sLen, sLen);
+            }
+            // step6: generate H using M'
+            this.md.digest(em, dbLen, hLen); // set H field of EM
+            digestReset = true;
+
+            // step7 and 8 are already covered by the code which setting up
+            // EM as above
+
+            // step9 and 10: feed H into MGF and xor with DB in EM
+            KAEMGF1 mgf1 = new KAEMGF1(mgfDigestAlgo);
+            mgf1.generateAndXor(em, dbLen, hLen, dbLen, em, 0);
+            // step11: set the leftmost (8emLen - emBits) bits of the leftmost
+            // octet to 0
+            int numZeroBits = (emLen << 3) - emBits;
+            if (numZeroBits != 0) {
+                byte mask = (byte) (0xff >>> numZeroBits);
+                em[0] = (byte) (em[0] & mask);
+            }
+
+            // step12: em should now holds maskedDB || hash h || 0xBC
+            return em;
+        } catch (NoSuchAlgorithmException | RuntimeException e) {
+            e.printStackTrace();
+            throw new IOException(e.toString());
+        }
+    }
+
+    private String getMgfDigestAlgo() {
+        String mgfDigestAlgo;
+        AlgorithmParameterSpec mgfParams = this.sigParams.getMGFParameters();
+        if (mgfParams != null) {
+            mgfDigestAlgo =
+                    ((MGF1ParameterSpec) mgfParams).getDigestAlgorithm();
+        } else {
+            mgfDigestAlgo = this.md.getAlgorithm();
+        }
+        return mgfDigestAlgo;
+    }
+
+    private void generateAndXor(String mgfDigestAlgo, byte[] em, int dbLen, int hLen) throws IOException {
+        try {
+            KAEMGF1 mgf1 = new KAEMGF1(mgfDigestAlgo);
+            mgf1.generateAndXor(em, dbLen, hLen, dbLen, em, 0);
+        } catch (NoSuchAlgorithmException | RuntimeException e) {
+            e.printStackTrace();
+            throw new IOException(e.toString());
+        }
+    }
+
+    /**
+     * Decode the signature data. Verify that the object identifier matches
+     * and return the message digest.
+     */
+    private boolean decodeSignature(byte[] mHash, byte[] em) throws IOException {
+        int hLen = mHash.length;
+        int sLen = this.sigParams.getSaltLength();
+        int emLen = em.length;
+        int emBits = getKeyLengthInBits(this.pubKey) - 1;
+
+        // step3
+        if (emLen < (hLen + sLen + 2)) {
+            return false;
+        }
+
+        // step4
+        if (em[emLen - 1] != (byte) 0xBC) {
+            return false;
+        }
+
+        // step6: check if the leftmost (8emLen - emBits) bits of the leftmost
+        // octet are 0
+        int numZeroBits = (emLen << 3) - emBits;
+        if (numZeroBits != 0) {
+            byte mask = (byte) (0xff << (8 - numZeroBits));
+            if ((em[0] & mask) != 0) {
+                return false;
+            }
+        }
+
+        // step 7 and 8
+        int dbLen = emLen - hLen - 1;
+
+        // generateAndXor
+        String mgfDigestAlgo = getMgfDigestAlgo();
+        generateAndXor(mgfDigestAlgo, em, dbLen, hLen);
+
+        // step9: set the leftmost (8emLen - emBits) bits of the leftmost
+        // octet to 0
+        if (numZeroBits != 0) {
+            byte mask = (byte) (0xff >>> numZeroBits);
+            em[0] = (byte) (em[0] & mask);
+        }
+
+        // step10
+        int index = 0;
+        for (; index < dbLen - sLen - 1; index++) {
+            if (em[index] != 0) {
+                return false;
+            }
+        }
+        if (em[index] != 0x01) {
+            return false;
+        }
+        // step12 and 13
+        this.md.update(EIGHT_BYTES_OF_ZEROS);
+        digestReset = false;
+        this.md.update(mHash);
+        if (sLen > 0) {
+            this.md.update(em, (dbLen - sLen), sLen);
+        }
+        byte[] digest2 = this.md.digest();
+        digestReset = true;
+
+        // step14
+        byte[] digestInEM = Arrays.copyOfRange(em, dbLen, emLen - 1);
+        return MessageDigest.isEqual(digest2, digestInEM);
+    }
+
+    // set parameter, not supported. See JCA doc
+    @Deprecated
+    @Override
+    protected void engineSetParameter(String param, Object value) throws InvalidParameterException {
+        throw new UnsupportedOperationException("setParameter() not supported");
+    }
+
+    @Override
+    protected void engineSetParameter(AlgorithmParameterSpec params) throws InvalidAlgorithmParameterException {
+        this.sigParams = validateSigParams(params);
+        // disallow changing parameters when digest has been used
+        if (!digestReset) {
+            throw new ProviderException
+                    ("Cannot set parameters during operations");
+        }
+        String newHashAlg = this.sigParams.getDigestAlgorithm();
+        // re-allocate md if not yet assigned or algorithm changed
+        if ((this.md == null) ||
+                !(this.md.getAlgorithm().equalsIgnoreCase(newHashAlg))) {
+            try {
+                this.md = MessageDigest.getInstance(newHashAlg);
+            } catch (NoSuchAlgorithmException nsae) {
+                // should not happen as we pick default digest algorithm
+                throw new InvalidAlgorithmParameterException("Unsupported digest algorithm " + newHashAlg, nsae);
+            }
+        }
+    }
+
+    // get parameter, not supported. See JCA doc
+    @Deprecated
+    @Override
+    protected Object engineGetParameter(String param) throws InvalidParameterException {
+        throw new UnsupportedOperationException("getParameter() not supported");
+    }
+
+    @Override
+    protected AlgorithmParameters engineGetParameters() {
+        AlgorithmParameters ap = null;
+        if (this.sigParams != null) {
+            try {
+                ap = AlgorithmParameters.getInstance("RSASSA-PSS");
+                ap.init(this.sigParams);
+            } catch (GeneralSecurityException gse) {
+                throw new ProviderException(gse.getMessage());
+            }
+        }
+        return ap;
+    }
+}
+
diff --git a/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAERSAPaddingType.java b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAERSAPaddingType.java
new file mode 100644
index 000000000..35e7f2f67
--- /dev/null
+++ b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAERSAPaddingType.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.openeuler.security.openssl;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+enum KAERSAPaddingType {
+    // raw RSA
+    PKCS1Padding(1, "PKCS1Padding"),
+
+    // PKCS#1 v1.5 RSA
+    NoPadding(3, "NoPadding"),
+
+    // PKCS#2 v2.2 OAEP with MGF1
+    OAEP(4, "OAEP", new HashSet<>(
+            Arrays.asList(
+                    "OAEPPADDING",
+                    "OAEPWITHMD5ANDMGF1PADDING",
+                    "OAEPWITHSHA1ANDMGF1PADDING",
+                    "OAEPWITHMD5ANDMGF1PADDING",
+                    "OAEPWITHSHA1ANDMGF1PADDING",
+                    "OAEPWITHSHA-1ANDMGF1PADDING",
+                    "OAEPWITHSHA-224ANDMGF1PADDING",
+                    "OAEPWITHSHA-256ANDMGF1PADDING",
+                    "OAEPWITHSHA-384ANDMGF1PADDING",
+                    "OAEPWITHSHA-512ANDMGF1PADDING",
+                    "OAEPWITHSHA-512/224ANDMGF1PADDING",
+                    "OAEPWITHSHA-512/256ANDMGF1PADDING"))
+    ),
+
+    // PSS
+    PKCS1PssPadding(6, "RSA_PKCS1_PSS_PADDING");
+
+    private final int id;
+    private final String name;
+    private final Set<String> supportPaddings;
+
+    public int getId() {
+        return id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    KAERSAPaddingType(int id, String name) {
+        this(id, name, Collections.singleton(name));
+    }
+
+    KAERSAPaddingType(int id, String name, Set<String> supportPaddings) {
+        this.id = id;
+        this.name = name;
+        this.supportPaddings = supportPaddings;
+    }
+
+    public Set<String> getSupportPaddings() {
+        return supportPaddings;
+    }
+}
diff --git a/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAERSASignature.java b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAERSASignature.java
new file mode 100644
index 000000000..b91a8cdaa
--- /dev/null
+++ b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAERSASignature.java
@@ -0,0 +1,365 @@
+/*
+ * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.openeuler.security.openssl;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+import java.security.*;
+import java.security.interfaces.*;
+import java.security.spec.AlgorithmParameterSpec;
+
+import sun.security.rsa.RSACore;
+import sun.security.rsa.RSAKeyFactory;
+import sun.security.rsa.RSAPadding;
+import sun.security.rsa.RSAUtil;
+import sun.security.rsa.RSAUtil.KeyType;
+import sun.security.util.*;
+import sun.security.x509.AlgorithmId;
+
+import javax.crypto.BadPaddingException;
+
+/**
+ * We support support rsa signatures with MD2, MD5, SHA-1, SHA-224, SHA-256, SHA-384, SHA-512 as the digest algorithm.
+ * The Openssl does not support rsa signatures with SHA-512/224 and SHA-512/256 as the digest algorithm,
+ * so we have not implemented them.
+ * The Openssl does not support non-CRT private key , when signing with a non-CRT private key, we use the sun sign.
+ */
+public abstract class KAERSASignature extends SignatureSpi {
+    // we sign an ASN.1 SEQUENCE of AlgorithmId and digest
+    // it has the form 30:xx:30:xx:[digestOID]:05:00:04:xx:[digest]
+    // this means the encoded length is (8 + digestOID.length + digest.length)
+    private static final int BASE_LENGTH = 8;
+
+    private String digestAlgorithm;
+
+    // object identifier for the message digest algorithm used
+    private final ObjectIdentifier digestOID;
+
+    // length of the encoded signature blob
+    private final int encodedLength;
+
+    // message digest implementation we use
+    private final MessageDigest md;
+
+    // flag indicating whether the digest is reset
+    private boolean digestReset;
+
+    // private key, if initialized for signing
+    private RSAPrivateKey privateKey;
+
+    // public key, if initialized for verifying
+    private RSAPublicKey publicKey;
+
+    // padding to use, set when the initSign/initVerify is called
+    private RSAPadding padding;
+
+    /**
+     * Construct a new RSASignature. Used by subclasses.
+     */
+    KAERSASignature(String algorithm, ObjectIdentifier digestOID, int oidLength) {
+        this.digestAlgorithm = algorithm;
+        this.digestOID = digestOID;
+        try {
+            md = MessageDigest.getInstance(algorithm);
+        } catch (NoSuchAlgorithmException e) {
+            throw new ProviderException(e);
+        }
+        digestReset = true;
+        encodedLength = BASE_LENGTH + oidLength + md.getDigestLength();
+    }
+
+    // initialize for verification. See JCA doc
+    @Override
+    protected void engineInitVerify(PublicKey publicKey) throws InvalidKeyException {
+        RSAPublicKey rsaKey = (RSAPublicKey) RSAKeyFactory.toRSAKey(publicKey);
+        this.privateKey = null;
+        this.publicKey = rsaKey;
+        initCommon(rsaKey, null);
+    }
+
+    // initialize for signing. See JCA doc
+    @Override
+    protected void engineInitSign(PrivateKey privateKey) throws InvalidKeyException {
+        engineInitSign(privateKey, null);
+    }
+
+    // initialize for signing. See JCA doc
+    @Override
+    protected void engineInitSign(PrivateKey privateKey, SecureRandom random) throws InvalidKeyException {
+        RSAPrivateKey rsaKey =
+                (RSAPrivateKey) RSAKeyFactory.toRSAKey(privateKey);
+        this.privateKey = rsaKey;
+        this.publicKey = null;
+        initCommon(rsaKey, random);
+    }
+
+    /**
+     * Init code common to sign and verify.
+     */
+    private void initCommon(RSAKey rsaKey, SecureRandom random) throws InvalidKeyException {
+        try {
+            RSAUtil.checkParamsAgainstType(KeyType.RSA, rsaKey.getParams());
+        } catch (ProviderException e) {
+            throw new InvalidKeyException("Invalid key for RSA signatures", e);
+        }
+        resetDigest();
+        int keySize = RSACore.getByteLength(rsaKey);
+        try {
+            padding = RSAPadding.getInstance
+                    (RSAPadding.PAD_BLOCKTYPE_1, keySize, random);
+        } catch (InvalidAlgorithmParameterException iape) {
+            throw new InvalidKeyException(iape.getMessage());
+        }
+        int maxDataSize = padding.getMaxDataSize();
+        if (encodedLength > maxDataSize) {
+            throw new InvalidKeyException
+                    ("Key is too short for this signature algorithm");
+        }
+    }
+
+    /**
+     * Reset the message digest if it is not already reset.
+     */
+    private void resetDigest() {
+        if (digestReset == false) {
+            md.reset();
+            digestReset = true;
+        }
+    }
+
+    /**
+     * Return the message digest value.
+     */
+    private byte[] getDigestValue() {
+        digestReset = true;
+        return md.digest();
+    }
+
+    // update the signature with the plaintext data. See JCA doc
+    @Override
+    protected void engineUpdate(byte b) throws SignatureException {
+        md.update(b);
+        digestReset = false;
+    }
+
+    // update the signature with the plaintext data. See JCA doc
+    @Override
+    protected void engineUpdate(byte[] b, int off, int len) throws SignatureException {
+        md.update(b, off, len);
+        digestReset = false;
+    }
+
+    // update the signature with the plaintext data. See JCA doc
+    @Override
+    protected void engineUpdate(ByteBuffer b) {
+        md.update(b);
+        digestReset = false;
+    }
+
+    // sign the data and return the signature. See JCA doc
+    @Override
+    protected byte[] engineSign() throws SignatureException {
+        if (privateKey == null) {
+            throw new SignatureException("Missing private key");
+        }
+
+        byte[] digest = getDigestValue();
+        if (useKaeSign()) {
+            return kaeSign(digest);
+        }
+        return sunSign(digest);
+    }
+
+    // determine if use kae sign , openssl do not support non-CRT private key
+    private boolean useKaeSign() {
+        return privateKey instanceof RSAPrivateCrtKey;
+    }
+
+    // sun sign
+    private byte[] sunSign(byte[] digest) throws SignatureException {
+        try {
+            byte[] encoded = encodeSignature(digestOID, digest);
+            byte[] padded = padding.pad(encoded);
+            return RSACore.rsa(padded, privateKey, true);
+        } catch (GeneralSecurityException e) {
+            throw new SignatureException("Could not sign data", e);
+        } catch (IOException e) {
+            throw new SignatureException("Could not encode data", e);
+        }
+    }
+
+    // kae sign
+    private byte[] kaeSign(byte[] digest) throws SignatureException {
+        String kaeDigestName = KAEUtils.getKAEDigestName(this.digestAlgorithm);
+        RSAPrivateCrtKey privateCrtKey = (RSAPrivateCrtKey) privateKey;
+        long keyAddress = KAERSACipher.nativeCreateRSAPrivateCrtKey(
+                privateCrtKey.getModulus().toByteArray(),
+                privateCrtKey.getPublicExponent().toByteArray(),
+                privateCrtKey.getPrivateExponent().toByteArray(),
+                privateCrtKey.getPrimeP().toByteArray(),
+                privateCrtKey.getPrimeQ().toByteArray(),
+                privateCrtKey.getPrimeExponentP().toByteArray(),
+                privateCrtKey.getPrimeExponentQ().toByteArray(),
+                privateCrtKey.getCrtCoefficient().toByteArray());
+        byte[] sigBytes;
+        try {
+            sigBytes = KAERSASignatureNative.rsaSign(keyAddress,
+                    kaeDigestName, digest, KAERSAPaddingType.PKCS1Padding.getId());
+        } catch (SignatureException e) {
+            throw e;
+        } finally {
+            // free keyAddress
+            KAERSACipher.nativeFreeKey(keyAddress);
+        }
+        return sigBytes;
+    }
+
+    // verify the data and return the result. See JCA doc
+    @Override
+    protected boolean engineVerify(byte[] sigBytes) throws SignatureException {
+        if (publicKey == null) {
+            throw new SignatureException("Missing public key");
+        }
+
+        boolean verify;
+        long keyAddress = 0L;
+        try {
+            if (sigBytes.length != RSACore.getByteLength(publicKey)) {
+                throw new SignatureException("Signature length not correct: got " +
+                        sigBytes.length + " but was expecting " +
+                        RSACore.getByteLength(publicKey));
+            }
+
+            String kaeDigestName = KAEUtils.getKAEDigestName(this.digestAlgorithm);
+            byte[] digest = getDigestValue();
+            keyAddress = KAERSACipher.nativeCreateRSAPublicKey(publicKey.getModulus().toByteArray(),
+                    publicKey.getPublicExponent().toByteArray());
+            verify = KAERSASignatureNative.rsaVerify(keyAddress,
+                    kaeDigestName, digest, KAERSAPaddingType.PKCS1Padding.getId(), sigBytes);
+        } catch (SignatureException e) {
+            throw e;
+        } catch (BadPaddingException e) {
+            // occurs if the app has used the wrong RSA public key
+            // or if sigBytes is invalid or sourceBytes is invalid
+            // return false rather than propagating the exception for
+            // compatibility/ease of use
+            return false;
+        } finally {
+            // reset digest
+            resetDigest();
+            // free keyAddress
+            if (keyAddress != 0L) {
+                KAERSACipher.nativeFreeKey(keyAddress);
+            }
+        }
+        return verify;
+    }
+
+    /**
+     * Encode the digest, return the to-be-signed data.
+     * Also used by the PKCS#11 provider.
+     */
+    public static byte[] encodeSignature(ObjectIdentifier oid, byte[] digest) throws IOException {
+        DerOutputStream out = new DerOutputStream();
+        new AlgorithmId(oid).encode(out);
+        out.putOctetString(digest);
+        DerValue result =
+                new DerValue(DerValue.tag_Sequence, out.toByteArray());
+        return result.toByteArray();
+    }
+
+    // set parameter, not supported. See JCA doc
+    @Deprecated
+    @Override
+    protected void engineSetParameter(String param, Object value) throws InvalidParameterException {
+        throw new UnsupportedOperationException("setParameter() not supported");
+    }
+
+    // See JCA doc
+    @Override
+    protected void engineSetParameter(AlgorithmParameterSpec params) throws InvalidAlgorithmParameterException {
+        if (params != null) {
+            throw new InvalidAlgorithmParameterException("No parameters accepted");
+        }
+    }
+
+    // get parameter, not supported. See JCA doc
+    @Deprecated
+    @Override
+    protected Object engineGetParameter(String param) throws InvalidParameterException {
+        throw new UnsupportedOperationException("getParameter() not supported");
+    }
+
+    // See JCA doc
+    @Override
+    protected AlgorithmParameters engineGetParameters() {
+        return null;
+    }
+
+    // Nested class for MD5withRSA signatures
+    public static final class MD5withRSA extends KAERSASignature {
+        public MD5withRSA() {
+            super("MD5", AlgorithmId.MD5_oid, 10);
+        }
+    }
+
+    // Nested class for SHA1withRSA signatures
+    public static final class SHA1withRSA extends KAERSASignature {
+        public SHA1withRSA() {
+            super("SHA-1", AlgorithmId.SHA_oid, 7);
+        }
+    }
+
+    // Nested class for SHA224withRSA signatures
+    public static final class SHA224withRSA extends KAERSASignature {
+        public SHA224withRSA() {
+            super("SHA-224", AlgorithmId.SHA224_oid, 11);
+        }
+    }
+
+    // Nested class for SHA256withRSA signatures
+    public static final class SHA256withRSA extends KAERSASignature {
+        public SHA256withRSA() {
+            super("SHA-256", AlgorithmId.SHA256_oid, 11);
+        }
+    }
+
+    // Nested class for SHA384withRSA signatures
+    public static final class SHA384withRSA extends KAERSASignature {
+        public SHA384withRSA() {
+            super("SHA-384", AlgorithmId.SHA384_oid, 11);
+        }
+    }
+
+    // Nested class for SHA512withRSA signatures
+    public static final class SHA512withRSA extends KAERSASignature {
+        public SHA512withRSA() {
+            super("SHA-512", AlgorithmId.SHA512_oid, 11);
+        }
+    }
+}
diff --git a/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAERSASignatureNative.java b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAERSASignatureNative.java
new file mode 100644
index 000000000..dda2f068d
--- /dev/null
+++ b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAERSASignatureNative.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.openeuler.security.openssl;
+
+import javax.crypto.BadPaddingException;
+import java.security.SignatureException;
+
+public class KAERSASignatureNative {
+    // rsa sign
+    protected static native byte[] rsaSign(long keyAddress, String digestName, byte[] digestBytes, int paddingType)
+        throws SignatureException;
+
+    // rsa verify
+    protected static native boolean rsaVerify(long keyAddress, String digestName, byte[] digestBytes, int paddingType,
+        byte[] sigBytes) throws SignatureException, BadPaddingException;
+
+    // rsa pss sign
+    protected static native byte[] pssSign(long keyAddress, String digestName, byte[] digestBytes, int paddingType,
+        String mgf1DigestName, int saltLen) throws SignatureException;
+
+    // rsa pss verify
+    protected static native boolean pssVerify(long keyAddress, String digestName, byte[] digestBytes, int paddingType,
+        String mgf1DigestName, int saltLen, byte[] sigBytes) throws SignatureException, BadPaddingException;
+}
diff --git a/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAESM4Cipher.java b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAESM4Cipher.java
new file mode 100644
index 000000000..a3e47606d
--- /dev/null
+++ b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAESM4Cipher.java
@@ -0,0 +1,370 @@
+/*
+ * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.openeuler.security.openssl;
+
+import sun.security.util.Debug;
+
+import java.nio.ByteBuffer;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.Key;
+import java.security.ProviderException;
+import java.util.Locale;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.ShortBufferException;
+
+/*
+ * This class currently supports:
+ * - SM4/ECB/NOPADDING
+ * - SM4/ECB/PKCS5PADDING
+ * - SM4/CBC/NOPADDING
+ * - SM4/CBC/PKCS5PADDING
+ * - SM4/CTR/NOPADDING
+ * - SM4/OFB/NOPADDING
+ * - SM4/OFB/PKCS5PADDING
+ */
+abstract class KAESM4Cipher extends KAESymmetricCipherBase {
+
+    private static final Debug debug = Debug.getInstance("kae");
+
+    /*
+     * SM4 max chunk size of each encryption or decryption
+     * when input data does not have an accessible byte[]
+     */
+    private static final int DEFAULT_KAE_SM4_MAX_CHUNK_SIZE = 4096;
+    private static int KAE_SM4_MAX_CHUNK_SIZE;
+    static {
+        initSM4MaxChunkSize();
+    }
+
+    private static void initSM4MaxChunkSize() {
+        String maxChunkSize = KAEConfig.privilegedGetOverridable("kae.sm4.maxChunkSize",
+                DEFAULT_KAE_SM4_MAX_CHUNK_SIZE + "");
+        try {
+            KAE_SM4_MAX_CHUNK_SIZE = Integer.parseInt(maxChunkSize);
+        } catch (NumberFormatException e) {
+            // When parsing string argument to signed decimal integer fails, uses the default chunk size (4096)
+            KAE_SM4_MAX_CHUNK_SIZE = DEFAULT_KAE_SM4_MAX_CHUNK_SIZE;
+            if (debug != null) {
+                debug.println("The configured block size (" + maxChunkSize + ") cannot be converted to an integer, " +
+                        "uses the default chunk size (" + DEFAULT_KAE_SM4_MAX_CHUNK_SIZE + ")");
+                e.printStackTrace();
+            }
+            return;
+        }
+        // when the configured chunk size is less than or equal to 0, uses the default chunk size (4096)
+        if (KAE_SM4_MAX_CHUNK_SIZE <= 0) {
+            KAE_SM4_MAX_CHUNK_SIZE = DEFAULT_KAE_SM4_MAX_CHUNK_SIZE;
+            if (debug != null) {
+                debug.println("The configured chunk size (" + KAE_SM4_MAX_CHUNK_SIZE + ") is less than " +
+                        "or equal to 0, uses the default chunk size (" + DEFAULT_KAE_SM4_MAX_CHUNK_SIZE + ")");
+            }
+            return;
+        }
+        if (debug != null) {
+            debug.println("The configured chunk size is " + KAE_SM4_MAX_CHUNK_SIZE);
+        }
+    }
+
+    /**
+     * Used by the engineUpdate(ByteBuffer, ByteBuffer) and
+     * engineDoFinal(ByteBuffer, ByteBuffer) methods.
+     */
+    private static int getSM4MaxChunkSize(int totalSize) {
+        return Math.min(KAE_SM4_MAX_CHUNK_SIZE, totalSize);
+    }
+
+    public static class Sm4 extends KAESM4Cipher {
+        public Sm4(Mode mode, Padding padding) {
+            super(mode, padding, 16);
+        }
+
+        public static class Cbc extends Sm4 {
+            public Cbc(Padding padding) {
+                super(Mode.CBC, padding);
+            }
+            public static class NoPadding extends Cbc {
+                public NoPadding() {
+                    super(Padding.NOPADDING);
+                }
+            }
+            public static class PKCS5Padding extends Cbc {
+                public PKCS5Padding() {
+                    super(Padding.PKCS5PADDING);
+                }
+            }
+        }
+
+        public static class Ecb extends Sm4 {
+            public Ecb(Padding padding) {
+                super(Mode.ECB, padding);
+            }
+            public static class NoPadding extends Ecb {
+                public NoPadding() {
+                    super(Padding.NOPADDING);
+                }
+            }
+            public static class PKCS5Padding extends Ecb {
+                public PKCS5Padding() {
+                    super(Padding.PKCS5PADDING);
+                }
+            }
+        }
+
+        public static class Ctr extends Sm4 {
+            public Ctr(Padding padding) {
+                super(Mode.CTR, padding);
+            }
+            public static class NoPadding extends Ctr {
+                public NoPadding() {
+                    super(Padding.NOPADDING);
+                }
+            }
+        }
+
+        public static class Ofb extends Sm4 {
+            public Ofb(Padding padding) {
+                super(Mode.OFB, padding);
+            }
+            public static class NoPadding extends Ofb {
+                public NoPadding() {
+                    super(Padding.NOPADDING);
+                }
+            }
+            public static class PKCS5Padding extends Ofb {
+                public PKCS5Padding() {
+                    super(Padding.PKCS5PADDING);
+                }
+            }
+        }
+    }
+
+    KAESM4Cipher(Mode mode, Padding padding, int fixedKeySize) {
+        super(mode, padding, fixedKeySize, "SM4");
+    }
+
+    protected void checkKey(Key key) throws InvalidKeyException {
+        if (key == null || key.getEncoded() == null) {
+            throw new InvalidKeyException("Key cannot be null");
+        } else {
+            int keyLen = key.getEncoded().length;
+            if (keyLen != fixedKeySize) {
+                throw new InvalidKeyException("Only " + fixedKeySize + "-byte keys are accepted. Got: " + keyLen);
+            }
+        }
+    }
+
+    protected String getCipherName(int keyLength, Mode mode) {
+        return "sm4" + "-" + mode.toString().toLowerCase(Locale.US);
+    }
+
+    @Override
+    protected void engineSetMode(String modeStr) throws NoSuchAlgorithmException {
+        if (modeStr == null) {
+            throw new NoSuchAlgorithmException("null mode");
+        }
+
+        if (modeStr.equalsIgnoreCase("ECB")) {
+            mode = Mode.ECB;
+        } else if (modeStr.equalsIgnoreCase("CBC")) {
+            mode = Mode.CBC;
+        } else if (modeStr.equalsIgnoreCase("CTR")) {
+            mode = Mode.CTR;
+        } else if (modeStr.equalsIgnoreCase("OFB")) {
+            mode = Mode.OFB;
+        } else {
+            throw new NoSuchAlgorithmException("Unsupported mode " + mode);
+        }
+    }
+
+    @Override
+    protected void engineSetPadding(String paddingStr) throws NoSuchPaddingException {
+        if (paddingStr == null) {
+            throw new NoSuchPaddingException("null padding");
+        }
+        if (paddingStr.equalsIgnoreCase("PKCS7PADDING")) {
+            paddingStr = "PKCS5Padding";
+        }
+
+        if (paddingStr.equalsIgnoreCase("NOPADDING")) {
+            this.padding = Padding.NOPADDING;
+        } else if(paddingStr.equalsIgnoreCase("PKCS5PADDING")) {
+            if (mode == Mode.CTR) {
+                throw new NoSuchPaddingException("PKCS#5 padding not supported with CTR mode");
+            }
+            this.padding = Padding.PKCS5PADDING;
+        } else {
+            throw new NoSuchPaddingException("Unsupported padding " + paddingStr);
+        }
+    }
+
+    @Override
+    protected int engineUpdate(ByteBuffer input, ByteBuffer output) throws ShortBufferException {
+        try {
+            return bufferCrypt(input, output, true);
+        } catch (IllegalBlockSizeException e) {
+            // never thrown for engineUpdate()
+            throw new ProviderException("Internal error in update()");
+        } catch (BadPaddingException e) {
+            // never thrown for engineUpdate()
+            throw new ProviderException("Internal error in update()");
+        }
+    }
+
+    @Override
+    protected int engineDoFinal(ByteBuffer input, ByteBuffer output)
+            throws ShortBufferException, IllegalBlockSizeException, BadPaddingException {
+        return bufferCrypt(input, output, false);
+    }
+
+    /**
+     * Implementation for encryption using ByteBuffers. Used for both
+     * engineUpdate() and engineDoFinal().
+     */
+    private int bufferCrypt(ByteBuffer input, ByteBuffer output,
+                            boolean isUpdate) throws ShortBufferException,
+            IllegalBlockSizeException, BadPaddingException {
+        if ((input == null) || (output == null)) {
+            throw new NullPointerException
+                    ("Input and output buffers must not be null");
+        }
+        int inPos = input.position();
+        int inLimit = input.limit();
+        int inLen = inLimit - inPos;
+        if (isUpdate && (inLen == 0)) {
+            return 0;
+        }
+        int outLenNeeded = engineGetOutputSize(inLen);
+
+        if (output.remaining() < outLenNeeded) {
+            throw new ShortBufferException("Need at least " + outLenNeeded
+                    + " bytes of space in output buffer");
+        }
+
+        // detecting input and output buffer overlap may be tricky
+        // we can only write directly into output buffer when we
+        // are 100% sure it's safe to do so
+
+        boolean a1 = input.hasArray();
+        boolean a2 = output.hasArray();
+        int total = 0;
+
+        if (a1) { // input has an accessible byte[]
+            byte[] inArray = input.array();
+            int inOfs = input.arrayOffset() + inPos;
+
+            byte[] outArray;
+            if (a2) { // output has an accessible byte[]
+                outArray = output.array();
+                int outPos = output.position();
+                int outOfs = output.arrayOffset() + outPos;
+
+                // check array address and offsets and use temp output buffer
+                // if output offset is larger than input offset and
+                // falls within the range of input data
+                boolean useTempOut = false;
+                if (inArray == outArray &&
+                        ((inOfs < outOfs) && (outOfs < inOfs + inLen))) {
+                    useTempOut = true;
+                    outArray = new byte[outLenNeeded];
+                    outOfs = 0;
+                }
+                if (isUpdate) {
+                    total = engineUpdate(inArray, inOfs, inLen, outArray, outOfs);
+                } else {
+                    total = engineDoFinal(inArray, inOfs, inLen, outArray, outOfs);
+                }
+                if (useTempOut) {
+                    output.put(outArray, outOfs, total);
+                } else {
+                    // adjust output position manually
+                    output.position(outPos + total);
+                }
+            } else { // output does not have an accessible byte[]
+                if (isUpdate) {
+                    outArray = engineUpdate(inArray, inOfs, inLen);
+                } else {
+                    outArray = engineDoFinal(inArray, inOfs, inLen);
+                }
+                if (outArray != null && outArray.length != 0) {
+                    output.put(outArray);
+                    total = outArray.length;
+                }
+            }
+            // adjust input position manually
+            input.position(inLimit);
+        } else { // input does not have an accessible byte[]
+            // have to assume the worst, since we have no way of determine
+            // if input and output overlaps or not
+            byte[] tempOut = new byte[outLenNeeded];
+            int outOfs = 0;
+
+            byte[] tempIn = new byte[getSM4MaxChunkSize(inLen)];
+            do {
+                int chunk = Math.min(inLen, tempIn.length);
+                if (chunk > 0) {
+                    input.get(tempIn, 0, chunk);
+                }
+                int n;
+                if (isUpdate || (inLen > chunk)) {
+                    n = engineUpdate(tempIn, 0, chunk, tempOut, outOfs);
+                } else {
+                    n = engineDoFinal(tempIn, 0, chunk, tempOut, outOfs);
+                }
+                outOfs += n;
+                total += n;
+                inLen -= chunk;
+            } while (inLen > 0);
+            if (total > 0) {
+                output.put(tempOut, 0, total);
+            }
+        }
+
+        return total;
+    }
+
+    protected void checkIvBytes(byte[] ivBytes) throws InvalidAlgorithmParameterException {
+        if (ivBytes == null) {
+            throw new InvalidAlgorithmParameterException("Wrong IV length: iv is null ");
+        }
+        if (mode == Mode.CTR) {
+            // For compatibility, SM4 CTR allows 8 < IV < blockSize, the remaining bytes will be filled with 0 in engineInit
+            if (ivBytes.length < 8 || ivBytes.length > blockSize) {
+                throw new InvalidAlgorithmParameterException("Wrong IV length: CTR mode requires IV of at least" +
+                        "8 bytes, and no greater than " + blockSize + "bytes");
+            }
+            return;
+        }
+        if (ivBytes.length != blockSize) {
+            throw new InvalidAlgorithmParameterException("Wrong IV length: must be " + blockSize + " bytes long.");
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAESM4KeyGenerator.java b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAESM4KeyGenerator.java
new file mode 100644
index 000000000..3f60e804f
--- /dev/null
+++ b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAESM4KeyGenerator.java
@@ -0,0 +1,74 @@
+/*                                                                                                                                           
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Huawei designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Huawei in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please visit https://gitee.com/openeuler/bgmprovider if you need additional
+ * information or have any questions.
+ */
+
+package org.openeuler.security.openssl;
+
+import javax.crypto.KeyGeneratorSpi;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidParameterException;
+import java.security.SecureRandom;
+import java.security.spec.AlgorithmParameterSpec;
+
+public class KAESM4KeyGenerator extends KeyGeneratorSpi {
+    private byte[] key;
+    private int keySize = 16; // default keysize (in number of bytes)
+    private SecureRandom random;
+
+    @Override
+    protected void engineInit(SecureRandom random) {
+        this.random = random;
+    }
+
+    @Override
+    protected void engineInit(AlgorithmParameterSpec params, SecureRandom random)
+            throws InvalidAlgorithmParameterException {
+        throw new InvalidAlgorithmParameterException
+                ("SM4 key generation does not take any parameters");
+    }
+
+    @Override
+    protected void engineInit(int keysize, SecureRandom random) {
+        if (keysize != 128) {
+            throw new InvalidParameterException("SM4 requires a 128 bit key");
+        }
+        this.keySize = keysize / 8;
+        engineInit(random);
+    }
+
+    private static class SecureRandomHolder {
+        static final SecureRandom RANDOM = new SecureRandom();
+    }
+
+    @Override
+    protected SecretKey engineGenerateKey() {
+        key = new byte[keySize];
+        if (random == null) {
+            random = SecureRandomHolder.RANDOM;
+        }
+        random.nextBytes(key);
+        return new SecretKeySpec(key, "SM4");
+    }
+}
diff --git a/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAESymmetricCipherBase.java b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAESymmetricCipherBase.java
new file mode 100644
index 000000000..7b5433b38
--- /dev/null
+++ b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAESymmetricCipherBase.java
@@ -0,0 +1,791 @@
+/*
+ * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.openeuler.security.openssl;
+
+import sun.security.jca.JCAUtil;
+
+import java.lang.ref.PhantomReference;
+import java.lang.ref.ReferenceQueue;
+import java.nio.ByteBuffer;
+import java.security.*;
+import java.security.spec.*;
+import java.util.Arrays;
+import java.util.Set;
+import java.util.concurrent.ConcurrentSkipListSet;
+
+import javax.crypto.*;
+import javax.crypto.spec.GCMParameterSpec;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+
+/*
+ * Cipher wrapper class utilizing openssl APIs.
+ */
+abstract class KAESymmetricCipherBase extends CipherSpi {
+    enum Padding {
+        NOPADDING,
+        PKCS5PADDING
+    }
+
+    enum Mode {
+        ECB,
+        CBC,
+        CTR,
+        OFB,
+        GCM
+    }
+
+    protected final String keyAlgo;
+    protected final int blockSize = 16;
+    protected Mode mode;
+    protected Padding padding;
+    protected int fixedKeySize;
+
+    private CipherContextRef pCtx = null;
+    private byte[] keyValue;
+    protected byte[] iv;
+    private boolean initialized = false;
+    private boolean encrypt = false;
+    private int bytesBuffered = 0;
+
+    private boolean calledUpdate;
+    private String cipherName;
+
+    // for gcm
+    private final int defaultGcmTagLen = blockSize;
+    private final int defaultGcmIvLen = 12;
+    private int tagLengthInBytes;
+    private byte[] lastEncKey = null;
+    private byte[] lastEncIv = null;
+    private byte[] aad;
+
+    private static PublicKey constructPublicKey(byte[] encodedKey, String encodedKeyAlgorithm)
+            throws NoSuchAlgorithmException, InvalidKeyException {
+        PublicKey key;
+        try {
+            KeyFactory keyFactory = KeyFactory.getInstance(encodedKeyAlgorithm);
+            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(encodedKey);
+            key = keyFactory.generatePublic(keySpec);
+        } catch (NoSuchAlgorithmException e) {
+            throw new NoSuchAlgorithmException("No provider found for " + encodedKeyAlgorithm + " KeyFactory");
+        } catch (InvalidKeySpecException e) {
+            throw new InvalidKeyException("Cannot construct public key", e);
+        }
+        return key;
+    }
+
+    private static PrivateKey constructPrivateKey(byte[] encodedKey,
+            String encodedKeyAlgorithm) throws InvalidKeyException, NoSuchAlgorithmException {
+        PrivateKey key = null;
+        try {
+            KeyFactory keyFactory = KeyFactory.getInstance(encodedKeyAlgorithm);
+            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encodedKey);
+            key = keyFactory.generatePrivate(keySpec);
+        } catch (NoSuchAlgorithmException e) {
+            throw new NoSuchAlgorithmException("No provider found for " + encodedKeyAlgorithm + " KeyFactory");
+        } catch (InvalidKeySpecException e) {
+            throw new InvalidKeyException("Cannot construct private key", e);
+        }
+        return key;
+    }
+
+    private static SecretKey constructSecretKey(byte[] encodedKey, String encodedKeyAlgorithm) {
+        return new SecretKeySpec(encodedKey, encodedKeyAlgorithm);
+    }
+
+    static final Key constructKey(int keyType, byte[] encodedKey,
+            String encodedKeyAlgorithm) throws NoSuchAlgorithmException, InvalidKeyException {
+        Key res = null;
+        switch (keyType) {
+            case Cipher.SECRET_KEY:
+                res = constructSecretKey(encodedKey, encodedKeyAlgorithm);
+                break;
+            case Cipher.PRIVATE_KEY:
+                res = constructPrivateKey(encodedKey, encodedKeyAlgorithm);
+                break;
+            case Cipher.PUBLIC_KEY:
+                res = constructPublicKey(encodedKey, encodedKeyAlgorithm);
+                break;
+            default:
+                throw new InvalidKeyException("Unknown keytype " + keyType);
+        }
+        return res;
+    }
+
+    KAESymmetricCipherBase(Mode mode, Padding padding, int fixedKeySize, String keyAlgo) {
+        this.mode = mode;
+        this.padding = padding;
+        this.fixedKeySize = fixedKeySize;
+        this.keyAlgo = keyAlgo;
+    }
+
+    private static class CipherContextRef extends PhantomReference<KAESymmetricCipherBase>
+            implements Comparable<CipherContextRef> {
+        private static ReferenceQueue<KAESymmetricCipherBase> refQueue = new ReferenceQueue<>();
+        private static Set<CipherContextRef> refList = new ConcurrentSkipListSet<>();
+        private static boolean disableKaeDispose = Boolean.getBoolean("kae.disableKaeDispose");
+
+        final long ctxAddress;
+
+        private static void drainRefQueueBounded() {
+            while (true) {
+                CipherContextRef next = (CipherContextRef) refQueue.poll();
+                if (next == null) {
+                    break;
+                }
+                next.dispose(true);
+            }
+        }
+
+        CipherContextRef(KAESymmetricCipherBase kaeCipher, long ctxAddress) {
+            super(kaeCipher, refQueue);
+            this.ctxAddress = ctxAddress;
+            if (!disableKaeDispose) {
+                refList.add(this);
+                drainRefQueueBounded();
+            }
+        }
+
+        @Override
+        public int compareTo(CipherContextRef o) {
+            if (this.ctxAddress == o.ctxAddress) {
+                return 0;
+            } else {
+                return (this.ctxAddress < o.ctxAddress) ? -1 : 1;
+            }
+        }
+
+        void dispose(boolean needFree) {
+            if (!disableKaeDispose) {
+                refList.remove(this);
+                try {
+                    if (needFree) {
+                        nativeFree(ctxAddress);
+                    }
+                } finally {
+                    this.clear();
+                }
+            } else {
+                nativeFree(ctxAddress);
+            }
+        }
+    }
+
+    @Override
+    protected int engineGetBlockSize() {
+        return blockSize;
+    }
+
+    @Override
+    protected int engineGetOutputSize(int inputLen) {
+        return getOutputSizeByOperation(inputLen, true);
+    }
+
+    @Override
+    protected byte[] engineGetIV() {
+        return iv == null ? null : iv.clone();
+    }
+
+    @Override
+    protected AlgorithmParameters engineGetParameters() {
+        if (iv == null) {
+            return null;
+        }
+        AlgorithmParameterSpec spec;
+        AlgorithmParameters params;
+        String algName = keyAlgo;
+        if (mode == Mode.GCM) {
+            algName = "GCM";
+            spec = new GCMParameterSpec(tagLengthInBytes * 8, iv.clone());
+        } else {
+            spec = new IvParameterSpec(iv.clone());
+        }
+        try {
+            params = AlgorithmParameters.getInstance(algName);
+            params.init(spec);
+            return params;
+        } catch (GeneralSecurityException e) {
+            throw new RuntimeException("Could not encode parameters", e);
+        }
+    }
+
+    @Override
+    protected void engineInit(int opmode, Key key, SecureRandom random) throws InvalidKeyException {
+        try {
+            engineInit(opmode, key, (AlgorithmParameterSpec) null, random);
+        } catch (InvalidAlgorithmParameterException e) {
+            throw new InvalidKeyException("init() failed", e);
+        }
+    }
+
+    @Override
+    protected void engineInit(int opmode, Key key, AlgorithmParameters params,
+                    SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException {
+        AlgorithmParameterSpec spec = null;
+        String paramType = null;
+        if (params != null) {
+            try {
+                if (mode == Mode.GCM) {
+                    spec = params.getParameterSpec(GCMParameterSpec.class);
+                    paramType = "GCM";
+                } else {
+                    spec = params.getParameterSpec(IvParameterSpec.class);
+                    paramType = "IV";
+                }
+            } catch (InvalidParameterSpecException e) {
+                throw new InvalidAlgorithmParameterException("Could not decode " + paramType, e);
+            }
+        }
+        engineInit(opmode, key, spec, random);
+    }
+
+    @Override
+    protected void engineInit(int opmode, Key key, AlgorithmParameterSpec params,
+                    SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException {
+        checkKey(key);
+        boolean doEncrypt = (opmode == Cipher.ENCRYPT_MODE || opmode == Cipher.WRAP_MODE);
+
+        byte[] ivBytes = null;
+        int tagLen = -1;
+        if (params != null) {
+            if (mode == Mode.GCM) {
+                if (params instanceof GCMParameterSpec) {
+                    tagLen = ((GCMParameterSpec)params).getTLen();
+                    checkTagLen(tagLen);
+                    tagLen = tagLen >> 3;
+                    ivBytes = ((GCMParameterSpec)params).getIV();
+                } else {
+                    throw new InvalidAlgorithmParameterException("Unsupported parameter: " + params);
+                }
+            } else {
+                if (params instanceof IvParameterSpec) {
+                    ivBytes = ((IvParameterSpec) params).getIV();
+                    checkIvBytes(ivBytes);
+                } else {
+                    throw new InvalidKeyException("IvParameterSpec required. Received: " + params.getClass().getName());
+                }
+            }
+        }
+        if (mode == Mode.ECB) {
+            if (params != null) {
+                throw new InvalidAlgorithmParameterException("No Parameters for ECB mode");
+            }
+        } else if (ivBytes == null) {
+            if (doEncrypt) {
+                if (mode == Mode.GCM) {
+                    ivBytes = new byte[defaultGcmIvLen];
+                } else {
+                    ivBytes = new byte[blockSize];
+                }
+                if (random == null) {
+                    random = JCAUtil.getSecureRandom();
+                }
+                random.nextBytes(ivBytes);
+            } else {
+                throw new InvalidAlgorithmParameterException("Parameters required for decryption");
+            }
+        } else if (keyAlgo.equalsIgnoreCase("SM4") && ivBytes.length < blockSize) {
+            byte[] temp = new byte[blockSize];
+            System.arraycopy(ivBytes, 0, temp, 0, ivBytes.length);
+            ivBytes = temp;
+        }
+        implInit(doEncrypt, key.getEncoded(), ivBytes, tagLen);
+    }
+
+    private void checkTagLen(int tagLen) throws InvalidAlgorithmParameterException {
+        if ((tagLen < 96) || (tagLen > 128) || ((tagLen & 0x07) != 0)) {
+            throw new InvalidAlgorithmParameterException
+                ("Unsupported TLen value; must be one of {128, 120, 112, 104, 96}");
+        }
+    }
+
+    protected abstract void checkIvBytes(byte[] ivBytes) throws InvalidAlgorithmParameterException;
+
+    protected abstract String getCipherName(int keyLength, Mode mode);
+
+    private void implInit(boolean encrypt, byte[] keyVal, byte[] ivVal, int tagLen)
+            throws InvalidAlgorithmParameterException {
+        reset(true);
+        this.encrypt = encrypt;
+        this.keyValue = keyVal;
+        this.iv = ivVal;
+        this.cipherName = getCipherName(keyValue.length * 8, mode);
+
+        if (mode == Mode.GCM) {
+            if (tagLen == -1) {
+                tagLen = defaultGcmTagLen;
+            }
+            this.tagLengthInBytes = tagLen;
+            if (encrypt) {
+                // Check key+iv for encryption in GCM mode.
+                boolean requireReinit = Arrays.equals(ivVal, lastEncIv) && MessageDigest.isEqual(keyVal, lastEncKey);
+                if (requireReinit) {
+                    throw new InvalidAlgorithmParameterException("Cannot reuse iv for GCM encryption");
+                }
+                lastEncIv = ivVal;
+                lastEncKey = keyVal;
+            }
+        }
+
+        // OpenSSL only supports PKCS5 Padding.
+        long pCtxVal;
+        try {
+            pCtxVal = nativeInit(cipherName, encrypt, keyValue, iv, padding == Padding.PKCS5PADDING);
+        } catch (RuntimeException e) {
+            throw new ProviderException("Invoke nativeInit failed for " + cipherName, e);
+        }
+
+        initialized = (pCtxVal != 0L);
+        if (initialized) {
+            pCtx = new CipherContextRef(this, pCtxVal);
+        } else {
+            throw new NullPointerException("pCtxVal == 0");
+        }
+        calledUpdate = false;
+    }
+
+    protected abstract void checkKey(Key key) throws InvalidKeyException;
+
+    @Override
+    protected byte[] engineUpdate(byte[] input, int inputOffset, int inputLen) {
+        byte[] out = new byte[getOutputSizeByOperation(inputLen, false)];
+        int outLen = implUpdate(input, inputOffset, inputLen, out, 0);
+        if (outLen == 0) {
+            return new byte[0];
+        } else if (out.length != outLen) {
+            out = Arrays.copyOf(out, outLen);
+        }
+        return out;
+    }
+
+    @Override
+    protected int engineUpdate(byte[] input, int inputOffset, int inputLen, byte[] output,
+                    int outputOffset) throws ShortBufferException {
+        int min = getOutputSizeByOperation(inputLen, false);
+        if (output == null || output.length - outputOffset < min) {
+            throw new ShortBufferException("min " + min + "-byte buffer needed");
+        }
+        return implUpdate(input, inputOffset, inputLen, output, outputOffset);
+    }
+
+    private int implUpdate(byte[] input, int inputOffset, int inputLen, byte[] output, int outputOffset) {
+        ensureInitialized();
+        if (inputLen <= 0) {
+            return 0;
+        }
+        int outLen;
+        try {
+            outLen = nativeUpdate(pCtx.ctxAddress, input, inputOffset, inputLen, output, outputOffset,
+                    mode == Mode.GCM, aad);
+            aad = null;
+        } catch (ArrayIndexOutOfBoundsException e) {
+            reset(true);
+            throw new ProviderException("Invoke nativeUpdate failed for " + cipherName, e);
+        }
+        bytesBuffered += (inputLen - outLen);
+
+        calledUpdate = true;
+        return outLen;
+    }
+
+    protected int getOutputSizeByOperation(int inLen, boolean isDoFinal) {
+        int ret;
+
+        if (inLen <= 0) {
+            inLen = 0;
+        }
+        if (padding == Padding.NOPADDING) {
+            ret = inLen + bytesBuffered;
+        } else {
+            int len = inLen + bytesBuffered;
+
+            // The amount of data written may be anything from zero bytes to (inl + cipher_block_size - 1) for encrypt.
+            // Refer to {@link https://www.openssl.org/docs/man1.1.0/man3/EVP_CipherUpdate.html} for details.
+            len += (len % blockSize != 0 || encrypt) ? blockSize : 0;
+            ret = len - (len % blockSize);
+        }
+        if (mode == Mode.GCM && isDoFinal) {
+            if (encrypt) {
+                ret = ret + tagLengthInBytes;
+            } else {
+                ret = Math.max(0, ret - tagLengthInBytes);
+            }
+        }
+        return ret;
+    }
+
+    @Override
+    protected byte[] engineDoFinal(byte[] input, int inputOffset,
+                    int inputLen) throws IllegalBlockSizeException, BadPaddingException {
+        byte[] out = new byte[getOutputSizeByOperation(inputLen, true)];
+        try {
+            int outLen = engineDoFinal(input, inputOffset, inputLen, out, 0);
+            if (out.length != outLen) {
+                out = Arrays.copyOf(out, outLen);
+            }
+            return out;
+        } catch (ShortBufferException e) {
+            throw new ProviderException(e);
+        }
+    }
+
+    @Override
+    protected int engineDoFinal(byte[] input, int inputOffset, int inputLen, byte[] output,
+                    int outputOffset) throws ShortBufferException, IllegalBlockSizeException, BadPaddingException {
+        int outLen = 0;
+        int min = getOutputSizeByOperation(inputLen, true);
+        if (output == null || output.length - outputOffset < min) {
+            throw new ShortBufferException("min " + min + "-byte buffer needed");
+        }
+
+        int updateLen = inputLen;
+        if (mode == Mode.GCM && !encrypt) {
+            // Remove tagLengthInBytes suffix in GCM decrypt.
+            updateLen = inputLen - tagLengthInBytes;
+        }
+        outLen = implUpdate(input, inputOffset, updateLen, output, outputOffset);
+        outputOffset += outLen;
+
+        byte[] gcmTag = null;
+        if (mode == Mode.GCM && !encrypt) {
+            if (inputLen - outLen != tagLengthInBytes) {
+                throw new AEADBadTagException("Tag mismatch!");
+            }
+            // The last tagLengthInBytees in the input arg gcmTag.
+            gcmTag = Arrays.copyOfRange(input, inputOffset + inputLen - tagLengthInBytes, inputOffset + inputLen);
+        }
+
+        outLen += implDoFinal(output, outputOffset, gcmTag);
+        return outLen;
+    }
+
+    @Override
+    protected byte[] engineWrap(Key key) throws IllegalBlockSizeException, InvalidKeyException {
+        byte[] res = null;
+        try {
+            byte[] encodedKey = key.getEncoded();
+            if (encodedKey == null || encodedKey.length == 0) {
+                throw new InvalidKeyException("Cannot get an encoding of the key to be wrapped");
+            }
+            res = engineDoFinal(encodedKey, 0, encodedKey.length);
+        } catch (BadPaddingException e) {
+            // Should never happen
+        }
+        return res;
+    }
+
+    @Override
+    protected Key engineUnwrap(byte[] wrappedKey, String wrappedKeyAlgorithm,
+                    int wrappedKeyType) throws InvalidKeyException, NoSuchAlgorithmException {
+        byte[] encodedKey;
+        try {
+            encodedKey = engineDoFinal(wrappedKey, 0, wrappedKey.length);
+        } catch (IllegalBlockSizeException | BadPaddingException e) {
+            throw (InvalidKeyException) (new InvalidKeyException()).initCause(e);
+        }
+        return constructKey(wrappedKeyType, encodedKey, wrappedKeyAlgorithm);
+    }
+
+    @Override
+    protected void engineUpdateAAD(ByteBuffer byteBuffer) {
+        if (aad == null) {
+            aad = new byte[byteBuffer.remaining()];
+            byteBuffer.get(aad);
+        } else {
+            int newSize = aad.length + byteBuffer.remaining();
+            byte[] newaad = new byte[newSize];
+            System.arraycopy(aad, 0, newaad, 0, aad.length);
+            byteBuffer.get(newaad, aad.length, byteBuffer.remaining());
+            aad = newaad;
+        }
+    }
+
+    @Override
+    protected void engineUpdateAAD(byte[] input, int inputOffset, int inputLen) {
+        if (aad == null) {
+            aad = Arrays.copyOfRange(input, inputOffset, inputOffset + inputLen);
+        } else {
+            int newSize = aad.length + inputLen;
+            byte[] newaad = new byte[newSize];
+            System.arraycopy(aad, 0, newaad, 0, aad.length);
+            System.arraycopy(input, inputOffset, newaad, aad.length, inputLen);
+            aad = newaad;
+        }
+    }
+
+    private int implDoFinal(byte[] out, int outputOffset, byte[] gcmTag)
+            throws BadPaddingException, IllegalBlockSizeException {
+        if (!encrypt && !calledUpdate) {
+            return 0;
+        }
+        ensureInitialized();
+
+        int outLen;
+        try {
+            if (mode == Mode.GCM) {
+                outLen = nativeFinalGcm(pCtx.ctxAddress, out, outputOffset, mode == Mode.GCM, tagLengthInBytes,
+                        gcmTag, encrypt);
+            } else {
+                outLen = nativeFinal(pCtx.ctxAddress, out, outputOffset);
+            }
+        } catch (ArrayIndexOutOfBoundsException | BadPaddingException e) {
+            if (e instanceof AEADBadTagException) {
+                throw e; // AEADBadTagException is expected for some tests
+            } else if (e instanceof BadPaddingException) {
+                if (padding == Padding.NOPADDING || e.getMessage().contains("wrong final block length")) {
+                    throw new IllegalBlockSizeException("Input length not multiple of " + blockSize + " bytes");
+                } else {
+                    throw e;
+                }
+            } else {
+                throw new ProviderException("Invoke nativeFinal failed for " + cipherName, e);
+            }
+        } finally {
+            reset(true);
+        }
+
+        return outLen;
+    }
+
+    protected void reset(boolean doCancel) {
+        initialized = false;
+        bytesBuffered = 0;
+        calledUpdate = false;
+
+        // for gcm
+        aad = null;
+
+        if (pCtx != null) {
+            pCtx.dispose(doCancel);
+            pCtx = null;
+        }
+    }
+
+    protected static native long nativeInit(String cipherType, boolean encrypt, byte[] key, byte[] iv, boolean padding)
+            throws RuntimeException;
+
+    protected static native int nativeUpdate(long pContext, byte[] in, int inOfs, int inLen, byte[] out,
+            int outOfs, boolean gcm, byte[] aad) throws ArrayIndexOutOfBoundsException;
+
+    protected static native int nativeFinal(long pContext, byte[] out,
+                    int outOfs) throws ArrayIndexOutOfBoundsException, BadPaddingException;
+
+    protected static native void nativeFree(long pContext);
+
+    protected static native int nativeFinalGcm(long pContext, byte[] out, int outOfs, boolean gcm,
+            int tagLength, byte[] gcmTag, boolean encrypt) throws ArrayIndexOutOfBoundsException, BadPaddingException;
+
+    protected void ensureInitialized() {
+        if (!initialized) {
+            reset(true);
+            long pCtxVal = nativeInit(cipherName, encrypt, keyValue, iv, padding == Padding.PKCS5PADDING);
+            initialized = (pCtxVal != 0L);
+            if (initialized) {
+                pCtx = new CipherContextRef(this, pCtxVal);
+            } else {
+                throw new RuntimeException("Cannot initialize Cipher");
+            }
+        }
+    }
+
+    // copied from sun.security.jca.JCAUtil
+    // will be changed to reference that method once that code has been
+    // integrated and promoted
+    static int getTempArraySize(int totalSize) {
+        return Math.min(4096, totalSize);
+    }
+
+    /**
+     * Continues a multiple-part encryption or decryption operation
+     * (depending on how this cipher was initialized), processing another data
+     * part.
+     *
+     * <p>All <code>input.remaining()</code> bytes starting at
+     * <code>input.position()</code> are processed. The result is stored
+     * in the output buffer.
+     * Upon return, the input buffer's position will be equal
+     * to its limit; its limit will not have changed. The output buffer's
+     * position will have advanced by n, where n is the value returned
+     * by this method; the output buffer's limit will not have changed.
+     *
+     * <p>If <code>output.remaining()</code> bytes are insufficient to
+     * hold the result, a <code>ShortBufferException</code> is thrown.
+     *
+     * <p>Subclasses should consider overriding this method if they can
+     * process ByteBuffers more efficiently than byte arrays.
+     *
+     * @param input the input ByteBuffer
+     * @param output the output ByteByffer
+     *
+     * @return the number of bytes stored in <code>output</code>
+     *
+     * @exception ShortBufferException if there is insufficient space in the
+     * output buffer
+     *
+     * @throws NullPointerException if either parameter is <CODE>null</CODE>
+     * @since 1.5
+     */
+    protected int engineUpdate(ByteBuffer input, ByteBuffer output)
+            throws ShortBufferException {
+        try {
+            return bufferCrypt(input, output, true);
+        } catch (IllegalBlockSizeException e) {
+            // never thrown for engineUpdate()
+            throw new ProviderException("Internal error in update()");
+        } catch (BadPaddingException e) {
+            // never thrown for engineUpdate()
+            throw new ProviderException("Internal error in update()");
+        }
+    }
+
+    /**
+     * Finalize crypto operation with ByteBuffers
+     *
+     * @param input the input ByteBuffer
+     * @param output the output ByteBuffer
+     *
+     * @return output length
+     * @throws ShortBufferException
+     * @throws IllegalBlockSizeException
+     * @throws BadPaddingException
+     */
+    @Override
+    protected int engineDoFinal(ByteBuffer input, ByteBuffer output)
+            throws ShortBufferException, IllegalBlockSizeException,
+            BadPaddingException {
+        return bufferCrypt(input, output, false);
+    }
+
+    /**
+     * Implementation for encryption using ByteBuffers. Used for both
+     * engineUpdate() and engineDoFinal().
+     */
+    private int bufferCrypt(ByteBuffer input, ByteBuffer output,
+                            boolean isUpdate) throws ShortBufferException,
+            IllegalBlockSizeException, BadPaddingException {
+        if ((input == null) || (output == null)) {
+            throw new NullPointerException
+                    ("Input and output buffers must not be null");
+        }
+        int inPos = input.position();
+        int inLimit = input.limit();
+        int inLen = inLimit - inPos;
+        if (isUpdate && (inLen == 0)) {
+            return 0;
+        }
+        int outLenNeeded = getOutputSizeByOperation(inLen, !isUpdate);
+
+        if (output.remaining() < outLenNeeded) {
+            throw new ShortBufferException("Need at least " + outLenNeeded
+                    + " bytes of space in output buffer");
+        }
+
+        // detecting input and output buffer overlap may be tricky
+        // we can only write directly into output buffer when we
+        // are 100% sure it's safe to do so
+
+        boolean a1 = input.hasArray();
+        boolean a2 = output.hasArray();
+        int total = 0;
+
+        if (a1) { // input has an accessible byte[]
+            byte[] inArray = input.array();
+            int inOfs = input.arrayOffset() + inPos;
+
+            if (a2) { // output has an accessible byte[]
+                byte[] outArray = output.array();
+                int outPos = output.position();
+                int outOfs = output.arrayOffset() + outPos;
+
+                // check array address and offsets and use temp output buffer
+                // if output offset is larger than input offset and
+                // falls within the range of input data
+                boolean useTempOut = false;
+                if (inArray == outArray &&
+                        ((inOfs < outOfs) && (outOfs < inOfs + inLen))) {
+                    useTempOut = true;
+                    outArray = new byte[outLenNeeded];
+                    outOfs = 0;
+                }
+                if (isUpdate) {
+                    total = engineUpdate(inArray, inOfs, inLen, outArray, outOfs);
+                } else {
+                    total = engineDoFinal(inArray, inOfs, inLen, outArray, outOfs);
+                }
+                if (useTempOut) {
+                    output.put(outArray, outOfs, total);
+                } else {
+                    // adjust output position manually
+                    output.position(outPos + total);
+                }
+                // adjust input position manually
+                input.position(inLimit);
+            } else { // output does not have an accessible byte[]
+                byte[] outArray = null;
+                if (isUpdate) {
+                    outArray = engineUpdate(inArray, inOfs, inLen);
+                } else {
+                    outArray = engineDoFinal(inArray, inOfs, inLen);
+                }
+                if (outArray != null && outArray.length != 0) {
+                    output.put(outArray);
+                    total = outArray.length;
+                }
+                // adjust input position manually
+                input.position(inLimit);
+            }
+        } else { // input does not have an accessible byte[]
+            // have to assume the worst, since we have no way of determine
+            // if input and output overlaps or not
+            byte[] tempOut = new byte[outLenNeeded];
+            int outOfs = 0;
+
+            byte[] tempIn = new byte[getTempArraySize(inLen)];
+            do {
+                int chunk = Math.min(inLen, tempIn.length);
+                if (chunk > 0) {
+                    input.get(tempIn, 0, chunk);
+                }
+                int n;
+                if (isUpdate || (inLen > chunk)) {
+                    n = engineUpdate(tempIn, 0, chunk, tempOut, outOfs);
+                } else {
+                    n = engineDoFinal(tempIn, 0, chunk, tempOut, outOfs);
+                }
+                outOfs += n;
+                total += n;
+                inLen -= chunk;
+            } while (inLen > 0);
+            if (total > 0) {
+                output.put(tempOut, 0, total);
+            }
+        }
+
+        return total;
+    }
+}
+
diff --git a/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEUtils.java b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEUtils.java
new file mode 100644
index 000000000..a4a005285
--- /dev/null
+++ b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEUtils.java
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.openeuler.security.openssl;
+
+import javax.crypto.Cipher;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
+import java.security.*;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.X509EncodedKeySpec;
+import java.util.*;
+
+class KAEUtils {
+    enum MessageDigestType {
+        MD2("MD2", "md2", 16),
+        MD5("MD5", "md5", 16),
+        SHA1("SHA-1", "sha1", 20,
+                new HashSet<>(Arrays.asList("SHA1", "1.3.14.3.2.26", "OID.1.3.14.3.2.26"))),
+        SHA224("SHA-224", "sha224", 28,
+                new HashSet<>(Arrays.asList("2.16.840.1.101.3.4.2.4", "OID.2.16.840.1.101.3.4.2.4"))),
+        SHA256("SHA-256", "sha256", 32,
+                new HashSet<>(Arrays.asList("2.16.840.1.101.3.4.2.1", "OID.2.16.840.1.101.3.4.2.1"))),
+        SHA384("SHA-384", "sha384", 48,
+                new HashSet<>(Arrays.asList("2.16.840.1.101.3.4.2.2", "OID.2.16.840.1.101.3.4.2.2"))),
+        SHA512("SHA-512", "sha512", 64,
+                new HashSet<>(Arrays.asList("2.16.840.1.101.3.4.2.3", "OID.2.16.840.1.101.3.4.2.3"))),
+        SHA512_224("SHA-512/224", "sha512-224", 28,
+                new HashSet<>(Arrays.asList("2.16.840.1.101.3.4.2.5", "OID.2.16.840.1.101.3.4.2.5"))),
+        SHA_512_256("SHA-512/256", "sha512-256", 32,
+                new HashSet<>(Arrays.asList("2.16.840.1.101.3.4.2.6", "OID.2.16.840.1.101.3.4.2.6")));
+
+        final String digestName;
+        final String kaeDigestName;
+        final int digestLen;
+        final Set<String> aliasNames;
+
+        public String getDigestName() {
+            return digestName;
+        }
+
+        public String getKaeDigestName() {
+            return kaeDigestName;
+        }
+
+        public int getDigestLen() {
+            return digestLen;
+        }
+
+        public Set<String> getAliasNames() {
+            return aliasNames;
+        }
+
+        MessageDigestType(String digestName, String kaeDigestName, int digestLen, Set<String> aliasNames) {
+            this.digestName = digestName;
+            this.kaeDigestName = kaeDigestName;
+            this.digestLen = digestLen;
+            this.aliasNames = aliasNames;
+        }
+
+        MessageDigestType(String digestName, String kaeDigestName, int digestLen) {
+            this(digestName, kaeDigestName, digestLen, Collections.emptySet());
+        }
+    }
+
+    /**
+     * kae digest algorithm info map
+     */
+    private static final Map<String, String> DIGEST_ALGORITHM_NAME_MAP = new HashMap<>();
+    private static final Map<String, Integer> DIGEST_ALGORITHM_LENGTH_MAP = new HashMap<>();
+
+    private static final Map<Integer, String> SIZE_TO_CURVE = new HashMap<>();
+    private static final Map<String, String> CURVE_ALIAS = new HashMap<>();
+
+    static {
+        initDigest();
+        initECDH();
+    }
+
+    private static void initDigest() {
+        MessageDigestType[] messageDigestTypes = MessageDigestType.values();
+        for (MessageDigestType messageDigestType : messageDigestTypes) {
+            DIGEST_ALGORITHM_NAME_MAP.put(messageDigestType.getDigestName(), messageDigestType.getKaeDigestName());
+            DIGEST_ALGORITHM_LENGTH_MAP.put(messageDigestType.getDigestName(), messageDigestType.getDigestLen());
+            for (String aliasName : messageDigestType.getAliasNames()) {
+                DIGEST_ALGORITHM_NAME_MAP.put(aliasName, messageDigestType.getKaeDigestName());
+                DIGEST_ALGORITHM_LENGTH_MAP.put(aliasName, messageDigestType.getDigestLen());
+            }
+        }
+    }
+
+    // get the kae digest algorithm name
+    static String getKAEDigestName(String digestName) {
+        return digestName == null ? null : DIGEST_ALGORITHM_NAME_MAP.get(digestName.toUpperCase(Locale.ROOT));
+    }
+
+    static Integer getDigestLength(String digestName) {
+        return digestName == null ? null : DIGEST_ALGORITHM_LENGTH_MAP.get(digestName.toUpperCase(Locale.ROOT));
+    }
+
+    static class ConstructKeys {
+        /**
+         * Construct a public key from its encoding.
+         *
+         * @param encodedKey          the encoding of a public key.
+         * @param encodedKeyAlgorithm the algorithm the encodedKey is for.
+         * @return a public key constructed from the encodedKey.
+         */
+        private static PublicKey constructPublicKey(byte[] encodedKey,
+                                                    String encodedKeyAlgorithm)
+                throws InvalidKeyException, NoSuchAlgorithmException {
+            try {
+                KeyFactory keyFactory =
+                        KeyFactory.getInstance(encodedKeyAlgorithm);
+                X509EncodedKeySpec keySpec = new X509EncodedKeySpec(encodedKey);
+                return keyFactory.generatePublic(keySpec);
+            } catch (NoSuchAlgorithmException nsae) {
+                throw new NoSuchAlgorithmException("No installed providers " +
+                        "can create keys for the " +
+                        encodedKeyAlgorithm +
+                        "algorithm", nsae);
+            } catch (InvalidKeySpecException ike) {
+                throw new InvalidKeyException("Cannot construct public key", ike);
+            }
+        }
+
+        /**
+         * Construct a private key from its encoding.
+         *
+         * @param encodedKey          the encoding of a private key.
+         * @param encodedKeyAlgorithm the algorithm the wrapped key is for.
+         * @return a private key constructed from the encodedKey.
+         */
+        private static PrivateKey constructPrivateKey(byte[] encodedKey,
+                                                      String encodedKeyAlgorithm) throws InvalidKeyException,
+                NoSuchAlgorithmException {
+            try {
+                KeyFactory keyFactory =
+                        KeyFactory.getInstance(encodedKeyAlgorithm);
+                PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encodedKey);
+                return keyFactory.generatePrivate(keySpec);
+            } catch (NoSuchAlgorithmException nsae) {
+                throw new NoSuchAlgorithmException("No installed providers " +
+                        "can create keys for the " +
+                        encodedKeyAlgorithm +
+                        "algorithm", nsae);
+            } catch (InvalidKeySpecException ike) {
+                throw new InvalidKeyException("Cannot construct private key", ike);
+            }
+        }
+
+        /**
+         * Construct a secret key from its encoding.
+         *
+         * @param encodedKey          the encoding of a secret key.
+         * @param encodedKeyAlgorithm the algorithm the secret key is for.
+         * @return a secret key constructed from the encodedKey.
+         */
+        private static SecretKey constructSecretKey(byte[] encodedKey,
+                                                    String encodedKeyAlgorithm) {
+            return new SecretKeySpec(encodedKey, encodedKeyAlgorithm);
+        }
+
+        static Key constructKey(byte[] encoding, String keyAlgorithm,
+                                int keyType) throws InvalidKeyException, NoSuchAlgorithmException {
+            switch (keyType) {
+                case Cipher.SECRET_KEY:
+                    return constructSecretKey(encoding, keyAlgorithm);
+                case Cipher.PRIVATE_KEY:
+                    return constructPrivateKey(encoding, keyAlgorithm);
+                case Cipher.PUBLIC_KEY:
+                    return constructPublicKey(encoding, keyAlgorithm);
+                default:
+                    throw new InvalidKeyException("Unknown keytype " + keyType);
+            }
+        }
+    }
+
+    private static void initECDH() {
+        SIZE_TO_CURVE.put(224, "secp224r1");
+        SIZE_TO_CURVE.put(256, "prime256v1");
+        SIZE_TO_CURVE.put(384, "secp384r1");
+        SIZE_TO_CURVE.put(521, "secp521r1");
+        CURVE_ALIAS.put("secp256r1", "prime256v1");
+        CURVE_ALIAS.put("1.3.132.0.33", "secp224r1");
+        CURVE_ALIAS.put("1.3.132.0.34", "secp384r1");
+        CURVE_ALIAS.put("1.3.132.0.35", "secp521r1");
+        CURVE_ALIAS.put("1.2.840.10045.3.1.7", "prime256v1");
+    }
+
+    static String getCurveBySize(int size) {
+        return SIZE_TO_CURVE.get(size);
+    }
+
+    static String getCurveByAlias(String alias) {
+        return CURVE_ALIAS.get(alias);
+    }
+}
diff --git a/src/jdk.crypto.kaeprovider/linux/conf/security/kaeprovider.conf b/src/jdk.crypto.kaeprovider/linux/conf/security/kaeprovider.conf
new file mode 100644
index 000000000..49ff98fd8
--- /dev/null
+++ b/src/jdk.crypto.kaeprovider/linux/conf/security/kaeprovider.conf
@@ -0,0 +1,75 @@
+#
+# This is the config file for KAEProvider.
+# These configuration properties support the use of jdk system properties,
+# and jdk system properties take precedence over file configuration properties.
+# For detailed usage, please refer to the user manual:
+# https://gitee.com/openeuler/bishengjdk-8/wikis/%E4%B8%AD%E6%96%87%E6%96%87%E6%A1%A3/KAE%20Provider%E7%94%A8%E6%88%B7%E4%BD%BF%E7%94%A8%E6%89%8B%E5%86%8C
+#
+
+# Algorithms are enabled by default if KAEProvider is used.
+# Delete # if you want to disable certain algorithm.
+# kae.md5=false
+# kae.sha256=false
+# kae.sha384=false
+# kae.sm3=false
+# kae.aes=false
+# kae.sm4=false
+# kae.hmac=false
+# kae.rsa=false
+# kae.dh=false
+# kae.ec=false
+
+# Configure engine id, the default value is kae.
+# kae.engine.id=kae
+
+# Configure whether libcrypto.so uses GLOBAL mode, uses LOCAL mode by default.
+# If you use uadk_engine, you need to enable this option.
+# kae.libcrypto.useGlobalMode=false
+
+# The following configuration will only take effect when using KAEProvider.
+# Configure whether to enable KAE hardware acceleration for each category of algorithm.
+# The configurable value are as follows:
+#     true : enable KAE hardware acceleration by default
+#     false: use openssl soft calculation by default
+# The digest/sm4/rsa/dh category algorithm enable KAE hardware acceleration by default.
+# The aes/hmac/ec category algorithm use openssl soft calculation by default.
+# The ec category algorithm configuration does not take effect temporarily. and it
+# currently does not support KAE hardware acceleration, temporarily use openssl soft calculation.
+# kae.digest.useKaeEngine=true
+# kae.aes.useKaeEngine=false
+# kae.sm4.useKaeEngine=true
+# kae.hmac.useKaeEngine=false
+# kae.rsa.useKaeEngine=true
+# kae.dh.useKaeEngine=true
+# kae.ec.useKaeEngine=false
+#
+# Some engines do not fully support certain categories of algorithms, for example, the digest
+# algorithm implemented by kae engine only supports md5 and sm3.For more information, please refer to:
+# KAE : https://github.com/kunpengcompute/KAE#:~:text=Digest%20algorithm%3A%20SM3/MD5
+# UADK: https://gitee.com/openeuler/uadk/wikis/%E4%BD%BF%E7%94%A8%E6%96%87%E6%A1%A3/UADK%20quick%20start#11-uadk
+#
+# Users can disable unsupported algorithms through the following property configuration.
+# Disable algorithm to enable KAE hardware acceleration, use openssl soft algorithm instead.
+# The sha256, sha384 algorithms are disabled by default.
+# digest : md5,sha256,sha384,sm3
+# aes    : aes-128-ecb,aes-128-cbc,aes-128-ctr,aes-128-gcm,
+#          aes-192-ecb,aes-192-cbc,aes-192-ctr,aes-192-gcm,
+#          aes-256-ecb,aes-256-cbc,aes-256-ctr,aes-256-gcm
+# sm4    : sm4-ecb,sm4-cbc,sm4-ctr,sm4-ofb
+# hmac   : hmac-md5,hmac-sha1,hmac-sha224,hmac-sha256,hmac-sha384,hmac-sha512
+# rsa    : rsa
+# dh     : dh
+# ec     : ec
+# kae.engine.disabledAlgorithms=sha256,sha384
+
+# SM4 max chunk size of each encryption or decryption.
+# when input data does not have an accessible byte[].
+# The default value is 4096, when configuring a non-positive Integer type, use the default value of 4096.
+# kae.sm4.maxChunkSize=4096
+
+# Enable engine load log.
+# kae.log=true
+#
+# It only takes effect when the property kae.log value is true.
+# Configure log file path, default value is System.getProperty("user.dir") + "/ + "kae.log".
+# kae.log.file=/home/user/kae.log
\ No newline at end of file
diff --git a/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_cipher_rsa.c b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_cipher_rsa.c
new file mode 100644
index 000000000..557d3965b
--- /dev/null
+++ b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_cipher_rsa.c
@@ -0,0 +1,471 @@
+/*
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <stdbool.h>
+#include <openssl/rsa.h>
+#include <openssl/evp.h>
+#include "kae_log.h"
+#include "kae_util.h"
+#include "kae_exception.h"
+#include "org_openeuler_security_openssl_KAERSACipher.h"
+
+typedef int RSACryptOperation(int, const unsigned char*, unsigned char*, RSA*, int);
+
+typedef int EvpPkeyCryptOperation(EVP_PKEY_CTX*, unsigned char*, size_t*, const unsigned char*, size_t);
+
+typedef int EvpPkeyCryptInitOperation(EVP_PKEY_CTX*);
+
+/*
+ * RSA encrypt or decrypt for NoPadding or PKCS1Padding , follow the steps below
+ *
+ */
+static int RSACryptNotOAEPPadding(JNIEnv* env, jlong keyAddress, jint inLen, jbyteArray in, jbyteArray out,
+    jint paddingType, RSACryptOperation rsaCryptOperation, char* cryptName) {
+    jbyte* inBytes = NULL;
+    jbyte* outBytes = NULL;
+    int resultSize = 0;
+
+    // get RSA
+    EVP_PKEY* pkey = (EVP_PKEY*) keyAddress;
+
+    // rsa = pkey->rsa
+    RSA* rsa = EVP_PKEY_get1_RSA(pkey);
+    if (rsa == NULL) {
+        KAE_ThrowFromOpenssl(env, "EVP_PKEY_get1_RSA", KAE_ThrowRuntimeException);
+        return 0;
+    }
+
+    // do encrypt or decrypt
+    inBytes = (*env)->GetByteArrayElements(env, in, NULL);
+    if (inBytes == NULL) {
+        KAE_ThrowNullPointerException(env, "GetByteArrayElements failed");
+        goto cleanup;
+    }
+    outBytes = (*env)->GetByteArrayElements(env, out, NULL);
+    if (outBytes == NULL) {
+        KAE_ThrowNullPointerException(env, "GetByteArrayElements failed");
+        goto cleanup;
+    }
+    resultSize = rsaCryptOperation(inLen, (unsigned char*)inBytes, (unsigned char*)outBytes, rsa, paddingType);
+    if (resultSize <= 0) {
+        KAE_ThrowFromOpenssl(env, cryptName, KAE_ThrowBadPaddingException);
+        goto cleanup;
+    }
+    jsize outLen = (*env)->GetArrayLength(env, out);
+    (*env)->SetByteArrayRegion(env, out, 0, outLen, outBytes);
+
+cleanup:
+    if (outBytes != NULL) {
+        (*env)->ReleaseByteArrayElements(env, out, outBytes, 0);
+    }
+    if (inBytes != NULL) {
+        (*env)->ReleaseByteArrayElements(env, in, inBytes, 0);
+    }
+    if (rsa != NULL) {
+        RSA_free(rsa);
+    }
+    return resultSize;
+}
+
+/*
+ * set rsa padding
+ */
+static bool SetRSAPadding(JNIEnv* env, EVP_PKEY_CTX* pkeyCtx, int paddingType) {
+    if (EVP_PKEY_CTX_set_rsa_padding(pkeyCtx, paddingType) <= 0) {
+        KAE_ThrowFromOpenssl(env, "EVP_PKEY_CTX_set_rsa_padding", KAE_ThrowInvalidAlgorithmParameterException);
+        return false;
+    }
+    return true;
+}
+
+/*
+ * set rsa mgf1 md
+ */
+static bool SetRSAMgf1Md(JNIEnv* env, EVP_PKEY_CTX* pkeyCtx, const char* mgf1MdAlgoUTF) {
+    EVP_MD* mgf1MD = (EVP_MD*)EVP_get_digestbyname(mgf1MdAlgoUTF);
+    if (mgf1MD == NULL) {
+        KAE_ThrowFromOpenssl(env, "EVP_get_digestbyname", KAE_ThrowInvalidAlgorithmParameterException);
+        return false;
+    }
+    if (EVP_PKEY_CTX_set_rsa_mgf1_md(pkeyCtx, mgf1MD) <= 0) {
+        KAE_ThrowFromOpenssl(env, "EVP_PKEY_CTX_set_rsa_mgf1_md", KAE_ThrowInvalidAlgorithmParameterException);
+        return false;
+    }
+    return true;
+}
+
+/*
+ * set rsa oaep md
+ */
+static bool SetRSAOaepMd(JNIEnv* env, EVP_PKEY_CTX* pkeyCtx, const char* oaepMdAlgoUTF) {
+    EVP_MD* oaepMD = (EVP_MD*)EVP_get_digestbyname(oaepMdAlgoUTF);
+    if (oaepMD == NULL) {
+        KAE_ThrowFromOpenssl(env, "EVP_get_digestbyname", KAE_ThrowInvalidAlgorithmParameterException);
+        return false;
+    }
+    if (EVP_PKEY_CTX_set_rsa_oaep_md(pkeyCtx, oaepMD) <= 0) {
+        KAE_ThrowFromOpenssl(env, "EVP_PKEY_CTX_set_rsa_oaep_md", KAE_ThrowInvalidAlgorithmParameterException);
+        return false;
+    }
+    return true;
+}
+
+/*
+ * set rsa oaep label
+ */
+static bool SetRSAOaepLabel(JNIEnv* env, EVP_PKEY_CTX* pkeyCtx, jbyte* labelBytes, jsize labelSize) {
+    if (EVP_PKEY_CTX_set0_rsa_oaep_label(pkeyCtx, labelBytes, labelSize) <= 0) {
+        KAE_ThrowFromOpenssl(env, "EVP_PKEY_CTX_set0_rsa_oaep_label", KAE_ThrowInvalidAlgorithmParameterException);
+        return false;
+    }
+    return true;
+}
+
+/*
+ * release rsa oaep temp resource
+ */
+static void ReleaseRSACryptOAEPResource(JNIEnv* env, EVP_PKEY_CTX* pkeyCtx,
+    jstring mgf1MdAlgo, const char* mgf1MdAlgoUTF, jstring oaepMdAlgo, const char* oaepMdAlgoUTF,
+    jbyteArray in, jbyte* inBytes, jbyteArray out, jbyte* outBytes) {
+    if (mgf1MdAlgoUTF != NULL) {
+        (*env)->ReleaseStringUTFChars(env, mgf1MdAlgo, mgf1MdAlgoUTF);
+    }
+    if (oaepMdAlgoUTF != NULL) {
+        (*env)->ReleaseStringUTFChars(env, oaepMdAlgo, oaepMdAlgoUTF);
+    }
+    if (outBytes != NULL) {
+        (*env)->ReleaseByteArrayElements(env, out, outBytes, 0);
+    }
+    if (inBytes != NULL) {
+        (*env)->ReleaseByteArrayElements(env, in, inBytes, 0);
+    }
+    EVP_PKEY_CTX_free(pkeyCtx);
+}
+
+static int RSACryptOAEPPadding(JNIEnv* env, jlong keyAddress, jint inLen, jbyteArray in, jbyteArray out,
+    jint paddingType, jstring oaepMdAlgo, jstring mgf1MdAlgo, jbyteArray label,
+    EvpPkeyCryptInitOperation cryptInitOperation, char* cryptInitName,
+    EvpPkeyCryptOperation cryptOperation, char* cryptName) {
+    EVP_PKEY_CTX* pkeyCtx = NULL;
+    const char* mgf1MdAlgoUTF = NULL;
+    const char* oaepMdAlgoUTF = NULL;
+    jbyte* labelBytes = NULL;
+    jbyte* outBytes = NULL;
+    jbyte* inBytes = NULL;
+    // outLen type should be size_t
+    // EVP_PKEY_encrypt takes the outLen address as a parameter, and the parameter type is size_t*
+    // You can refer to the issue #2774 to see more content
+    size_t outLen = 0;
+    ENGINE* kaeEngine = GetEngineByAlgorithmIndex(RSA_INDEX);
+    KAE_TRACE("RSACryptOAEPPadding: kaeEngine => %p", kaeEngine);
+
+
+    EVP_PKEY* pkey = (EVP_PKEY*) keyAddress;
+
+    // new ctx
+    // rsa encrypt/decrypt init
+    if ((pkeyCtx = EVP_PKEY_CTX_new(pkey, kaeEngine)) == NULL || cryptInitOperation(pkeyCtx) <= 0) {
+        KAE_ThrowFromOpenssl(env, pkeyCtx == NULL ? "EVP_PKEY_CTX_new" : cryptInitName, KAE_ThrowInvalidKeyException);
+        goto cleanup;
+    }
+
+    if ((mgf1MdAlgoUTF = (*env)->GetStringUTFChars(env, mgf1MdAlgo, 0)) == NULL ||
+        (oaepMdAlgoUTF = (*env)->GetStringUTFChars(env, oaepMdAlgo, 0)) == NULL) {
+        KAE_ThrowOOMException(env, "GetStringUTFChars failed");
+        goto cleanup;
+    }
+
+    /*
+     * set padding type
+     * set rsa mgf1 md
+     * set rsa oaep md
+     */
+    if (!SetRSAPadding(env, pkeyCtx, paddingType) || !SetRSAMgf1Md(env, pkeyCtx, mgf1MdAlgoUTF) ||
+        !SetRSAOaepMd(env, pkeyCtx, oaepMdAlgoUTF)) {
+        goto cleanup;
+    }
+
+    // set rsa oaep label
+    jsize labelSize = (*env)->GetArrayLength(env, label);
+    if (labelSize > 0) {
+        // EVP_PKEY_CTX_free will free the labelBytes, so we can not free labelBytes when cleanup.
+        // Only SetRSAOaepLabel failed , free labelBytes.
+        if ((labelBytes = malloc(labelSize)) == NULL) {
+            KAE_ThrowNullPointerException(env, "malloc failed");
+            goto cleanup;
+        }
+        (*env)->GetByteArrayRegion(env, label, 0, labelSize, labelBytes);
+        if (!SetRSAOaepLabel(env, pkeyCtx, labelBytes, labelSize)) {
+            free(labelBytes);
+            goto cleanup;
+        }
+    }
+
+    // do encrypt/decrypt
+    outLen = (size_t)(*env)->GetArrayLength(env, out);
+    if ((outBytes = (*env)->GetByteArrayElements(env, out, NULL)) == NULL ||
+        (inBytes = (*env)->GetByteArrayElements(env, in, NULL)) == NULL) {
+        KAE_ThrowNullPointerException(env, "GetByteArrayElements failed");
+        goto cleanup;
+    }
+    if (cryptOperation(pkeyCtx, (unsigned char*)outBytes, &outLen, (unsigned char*)inBytes, inLen) <= 0) {
+        KAE_ThrowFromOpenssl(env, cryptName, KAE_ThrowBadPaddingException);
+        goto cleanup;
+    }
+    (*env)->SetByteArrayRegion(env, out, 0, outLen, outBytes);
+
+cleanup:
+    ReleaseRSACryptOAEPResource(env, pkeyCtx, mgf1MdAlgo, mgf1MdAlgoUTF, oaepMdAlgo, oaepMdAlgoUTF,
+        in, inBytes, out, outBytes);
+    return outLen;
+}
+
+/*
+ * Release rsa param n,e,d,p,q,dmp1,dmq1,iqmp
+ */
+void ReleaseRSAParams(BIGNUM* bnN, BIGNUM* bnE, BIGNUM* bnD, BIGNUM* bnP, BIGNUM* bnQ,
+                      BIGNUM* bnDMP1, BIGNUM* bnDMQ1, BIGNUM* bnIQMP) {
+    KAE_ReleaseBigNumFromByteArray(bnN);
+    KAE_ReleaseBigNumFromByteArray(bnE);
+    KAE_ReleaseBigNumFromByteArray(bnD);
+    KAE_ReleaseBigNumFromByteArray(bnP);
+    KAE_ReleaseBigNumFromByteArray(bnQ);
+    KAE_ReleaseBigNumFromByteArray(bnDMP1);
+    KAE_ReleaseBigNumFromByteArray(bnDMQ1);
+    KAE_ReleaseBigNumFromByteArray(bnIQMP);
+}
+
+/*
+ * Create rsa private crt key
+ * Class:     org_openeuler_security_openssl_KAERSACipher
+ * Method:    nativeCreateRSAPrivateCrtKey
+ * Signature: ([B[B[B[B[B[B[B[B)J
+ */
+JNIEXPORT jlong JNICALL Java_org_openeuler_security_openssl_KAERSACipher_nativeCreateRSAPrivateCrtKey(JNIEnv* env,
+    jclass cls, jbyteArray n, jbyteArray e, jbyteArray d, jbyteArray p, jbyteArray q,
+    jbyteArray dmp1, jbyteArray dmq1, jbyteArray iqmp) {
+    BIGNUM* bnN = NULL;
+    BIGNUM* bnE = NULL;
+    BIGNUM* bnD = NULL;
+    BIGNUM* bnP = NULL;
+    BIGNUM* bnQ = NULL;
+    BIGNUM* bnDMP1 = NULL;
+    BIGNUM* bnDMQ1 = NULL;
+    BIGNUM* bnIQMP = NULL;
+    RSA* rsa = NULL;
+    EVP_PKEY* pkey = NULL;
+    ENGINE* kaeEngine = GetEngineByAlgorithmIndex(RSA_INDEX);
+    KAE_TRACE("KAERSACipher_nativeCreateRSAPrivateCrtKey: kaeEngine => %p", kaeEngine);
+
+    // convert to big num
+    if ((bnN = KAE_GetBigNumFromByteArray(env, n)) == NULL ||
+        (bnE = KAE_GetBigNumFromByteArray(env, e)) == NULL ||
+        (bnD = KAE_GetBigNumFromByteArray(env, d)) == NULL ||
+        (bnP = KAE_GetBigNumFromByteArray(env, p)) == NULL ||
+        (bnQ = KAE_GetBigNumFromByteArray(env, q)) == NULL ||
+        (bnDMP1 = KAE_GetBigNumFromByteArray(env, dmp1)) == NULL ||
+        (bnDMQ1 = KAE_GetBigNumFromByteArray(env, dmq1)) == NULL ||
+        (bnIQMP = KAE_GetBigNumFromByteArray(env, iqmp)) == NULL) {
+        goto cleanup;
+    }
+
+    // new pkey
+    pkey = EVP_PKEY_new();
+    if (pkey == NULL) {
+        KAE_ThrowFromOpenssl(env, "EVP_PKEY_new", KAE_ThrowRuntimeException);
+        goto cleanup;
+    }
+
+    // new rsa
+    rsa = RSA_new_method(kaeEngine);
+    if (rsa == NULL) {
+        KAE_ThrowFromOpenssl(env, "RSA_new_method", KAE_ThrowRuntimeException);
+        goto cleanup;
+    }
+
+    // set rsa private crt key params n,e,d,p,q,dmp1,dmp1,iqmp
+    if (RSA_set0_key(rsa, bnN, bnE, bnD) <= 0 ||
+        RSA_set0_factors(rsa, bnP, bnQ) <= 0 ||
+        RSA_set0_crt_params(rsa, bnDMP1, bnDMQ1, bnIQMP) <= 0) {
+        KAE_ThrowFromOpenssl(env, "RSA set param", KAE_ThrowRuntimeException);
+        goto cleanup;
+    }
+
+    // assign rsa to pkey
+    int result = EVP_PKEY_assign_RSA(pkey, rsa);
+    if (result <= 0) {
+        KAE_ThrowFromOpenssl(env, "EVP_PKEY_assign_RSA", KAE_ThrowRuntimeException);
+        goto cleanup;
+    }
+    return (jlong)pkey;
+cleanup:
+    ReleaseRSAParams(bnN, bnE, bnD, bnP, bnQ, bnDMP1, bnDMQ1, bnIQMP);
+    RSA_free(rsa);
+    EVP_PKEY_free(pkey);
+    return 0;
+}
+
+/*
+ * Create rsa public key
+ * Class:     org_openeuler_security_openssl_KAERSACipher
+ * Method:    nativeCreateRSAPublicKey
+ * Signature: ([B[B)J
+ */
+JNIEXPORT jlong JNICALL Java_org_openeuler_security_openssl_KAERSACipher_nativeCreateRSAPublicKey(
+    JNIEnv* env, jclass cls, jbyteArray n, jbyteArray e) {
+    BIGNUM* bnN = NULL;
+    BIGNUM* bnE = NULL;
+    RSA* rsa = NULL;
+    EVP_PKEY* pkey = NULL;
+    ENGINE* kaeEngine = GetEngineByAlgorithmIndex(RSA_INDEX);
+    KAE_TRACE("KAERSACipher_nativeCreateRSAPublicKey: kaeEngine => %p", kaeEngine);
+
+    // get public key param n
+    bnN = KAE_GetBigNumFromByteArray(env, n);
+    if (bnN == NULL) {
+        goto cleanup;
+    }
+
+    // get public key param e
+    bnE = KAE_GetBigNumFromByteArray(env, e);
+    if (bnE == NULL) {
+        goto cleanup;
+    }
+
+    // new rsa
+    rsa = RSA_new_method(kaeEngine);
+    if (rsa == NULL) {
+        KAE_ThrowFromOpenssl(env, "RSA_new_method", KAE_ThrowRuntimeException);
+        goto cleanup;
+    }
+
+    // new EVP_PKEY
+    pkey = EVP_PKEY_new();
+    if (pkey == NULL) {
+        KAE_ThrowFromOpenssl(env, "EVP_PKEY_new", KAE_ThrowRuntimeException);
+        goto cleanup;
+    }
+
+    // set rsa public key params n and e
+    if (RSA_set0_key(rsa, bnN, bnE, NULL) <= 0) {
+        KAE_ThrowFromOpenssl(env, "RSA_set0_key", KAE_ThrowRuntimeException);
+        goto cleanup;
+    }
+
+    // assign rsa to pkey
+    int result = EVP_PKEY_assign_RSA(pkey, rsa);
+    if (result <= 0) {
+        KAE_ThrowFromOpenssl(env, "EVP_PKEY_assign_RSA", KAE_ThrowRuntimeException);
+        goto cleanup;
+    }
+    return (jlong)pkey;
+cleanup:
+    KAE_ReleaseBigNumFromByteArray(bnN);
+    KAE_ReleaseBigNumFromByteArray(bnE);
+    RSA_free(rsa);
+    EVP_PKEY_free(pkey);
+    return 0;
+}
+
+/*
+ * Class:     org_openeuler_security_openssl_KAERSACipher
+ * Method:    nativeRSAPrivateEncrypt
+ * Signature: (JI[B[BI)I
+ */
+JNIEXPORT jint JNICALL Java_org_openeuler_security_openssl_KAERSACipher_nativeRSAPrivateEncrypt(JNIEnv* env,
+    jclass cls, jlong keyAddress, jint inLen, jbyteArray in, jbyteArray out, jint paddingType) {
+    return RSACryptNotOAEPPadding(env, keyAddress, inLen, in, out, paddingType, RSA_private_encrypt,
+                                  "RSA_private_encrypt");
+}
+
+/*
+ * Class:     org_openeuler_security_openssl_KAERSACipher
+ * Method:    nativeRSAPrivateDecrypt
+ * Signature: (JI[B[BI)I
+ */
+JNIEXPORT jint JNICALL Java_org_openeuler_security_openssl_KAERSACipher_nativeRSAPrivateDecrypt(JNIEnv* env,
+    jclass cls, jlong keyAddress, jint inLen, jbyteArray in, jbyteArray out, jint paddingType) {
+    return RSACryptNotOAEPPadding(env, keyAddress, inLen, in, out, paddingType, RSA_private_decrypt,
+                                  "RSA_private_decrypt");
+}
+
+/*
+ * Class:     org_openeuler_security_openssl_KAERSACipher
+ * Method:    nativeRSAPublicEncrypt
+ * Signature: (JI[B[BI)I
+ */
+JNIEXPORT jint JNICALL Java_org_openeuler_security_openssl_KAERSACipher_nativeRSAPublicEncrypt(JNIEnv* env,
+    jclass cls, jlong keyAddress, jint inLen, jbyteArray in, jbyteArray out, jint paddingType) {
+    return RSACryptNotOAEPPadding(env, keyAddress, inLen, in, out, paddingType, RSA_public_encrypt,
+                                  "RSA_public_encrypt");
+}
+
+/*
+ * Class:     org_openeuler_security_openssl_KAERSACipher
+ * Method:    nativeRSAPublicDecrypt
+ * Signature: (JI[B[BI)I
+ */
+JNIEXPORT jint JNICALL Java_org_openeuler_security_openssl_KAERSACipher_nativeRSAPublicDecrypt(JNIEnv* env,
+    jclass cls, jlong keyAddress, jint inLen, jbyteArray in, jbyteArray out, jint paddingType) {
+    return RSACryptNotOAEPPadding(env, keyAddress, inLen, in, out, paddingType, RSA_public_decrypt,
+                                  "RSA_public_decrypt");
+}
+
+/*
+ * Class:     org_openeuler_security_openssl_KAERSACipher
+ * Method:    nativeRSAEncryptOAEPPading
+ * Signature: (JI[B[BI[B[B[B)I
+ */
+JNIEXPORT jint JNICALL Java_org_openeuler_security_openssl_KAERSACipher_nativeRSAEncryptOAEPPadding(JNIEnv* env,
+    jclass cls, jlong keyAddress, jint inLen, jbyteArray in, jbyteArray out,
+    jint paddingType, jstring oaepMdAlgo, jstring mgf1MdAlgo, jbyteArray label) {
+    return RSACryptOAEPPadding(env, keyAddress, inLen, in, out, paddingType, oaepMdAlgo, mgf1MdAlgo, label,
+                               EVP_PKEY_encrypt_init, "EVP_PKEY_encrypt_init",
+                               EVP_PKEY_encrypt, "EVP_PKEY_encrypt");
+}
+
+/*
+ * Class:     org_openeuler_security_openssl_KAERSACipher
+ * Method:    nativeRSADecryptOAEPPadding
+ * Signature: (JI[B[BILjava/lang/String;Ljava/lang/String;[B)I
+ */
+JNIEXPORT jint JNICALL Java_org_openeuler_security_openssl_KAERSACipher_nativeRSADecryptOAEPPadding(JNIEnv* env,
+    jclass cls, jlong keyAddress, jint inLen, jbyteArray in, jbyteArray out, jint paddingType,
+    jstring oaepMdAlgo, jstring mgf1MdAlgo, jbyteArray label) {
+    return RSACryptOAEPPadding(env, keyAddress, inLen, in, out, paddingType, oaepMdAlgo, mgf1MdAlgo, label,
+                               EVP_PKEY_decrypt_init, "EVP_PKEY_decrypt_init",
+                               EVP_PKEY_decrypt, "EVP_PKEY_decrypt");
+}
+
+/*
+ * Class:     org_openeuler_security_openssl_KAERSACipher
+ * Method:    nativeFreeKey
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_org_openeuler_security_openssl_KAERSACipher_nativeFreeKey(JNIEnv* env,
+    jclass cls, jlong keyAddress) {
+    EVP_PKEY* pkey = (EVP_PKEY*) keyAddress;
+    if (pkey != NULL) {
+        EVP_PKEY_free(pkey);
+    }
+}
\ No newline at end of file
diff --git a/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_digest.c b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_digest.c
new file mode 100644
index 000000000..82bf477da
--- /dev/null
+++ b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_digest.c
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <string.h>
+#include <openssl/evp.h>
+#include <openssl/md5.h>
+#include "kae_exception.h"
+#include "kae_log.h"
+#include "kae_util.h"
+#include "org_openeuler_security_openssl_KAEDigest.h"
+
+#define DIGEST_STACK_SIZE 1024
+#define DIGEST_CHUNK_SIZE 64*1024
+#define DIGEST_LENGTH_THRESHOLD 48
+
+/*
+ * Class:     org_openeuler_security_openssl_KAEDigest
+ * Method:    nativeInit
+ * Signature: (Ljava/lang/String;)J
+ */
+JNIEXPORT jlong JNICALL
+Java_org_openeuler_security_openssl_KAEDigest_nativeInit(JNIEnv *env, jclass cls, jstring algorithmName)
+{
+    EVP_MD_CTX* ctx = NULL;
+    ENGINE* kaeEngine = NULL;
+
+    if (algorithmName == NULL) {
+        KAE_ThrowNullPointerException(env, "algorithm is null");
+        return 0;
+    }
+
+    // EVP_get_digestbyname
+    const char* algo_utf = (*env)->GetStringUTFChars(env, algorithmName, 0);
+    kaeEngine = GetDigestEngineByAlgorithmName(algo_utf);
+    KAE_TRACE("KAEDigest_nativeInit: kaeEngine => %p", kaeEngine);
+    EVP_MD* md = (EVP_MD*) EVP_get_digestbyname(algo_utf);
+    (*env)->ReleaseStringUTFChars(env, algorithmName, algo_utf);
+    if (md == NULL) {
+        KAE_TRACE("%s not supported", algo_utf);
+        return 0;
+    }
+    KAE_TRACE("KAEDigest_nativeInit: create md => %p", md);
+
+    ctx = EVP_MD_CTX_create();
+    if (ctx == NULL) {
+        KAE_ThrowOOMException(env, "create EVP_MD_CTX fail");
+        return 0;
+    }
+    KAE_TRACE("KAEDigest_nativeInit: create ctx => %p", ctx);
+
+    // EVP_DigestInit_ex
+    int result_code = EVP_DigestInit_ex(ctx, md, kaeEngine);
+    if (result_code == 0) {
+        KAE_ThrowFromOpenssl(env, "EVP_DigestInit_ex failed", KAE_ThrowRuntimeException);
+        goto cleanup;
+    }
+    KAE_TRACE("KAEDigest_nativeInit EVP_DigestInit_ex(ctx = %p, md = %p) success", ctx, md);
+
+    KAE_TRACE("KAEDigest_nativeInit: finished");
+    return (jlong) ctx;
+
+cleanup:
+    EVP_MD_CTX_destroy(ctx);
+    return 0;
+}
+
+/*
+ * Class:     org_openeuler_security_openssl_KAEDigest
+ * Method:    nativeUpdate
+ * Signature: (Ljava/lang/String;J[BII)I
+ */
+JNIEXPORT void JNICALL
+Java_org_openeuler_security_openssl_KAEDigest_nativeUpdate(JNIEnv *env, jclass cls, jlong ctxAddress,
+    jbyteArray input, jint offset, jint inLen)
+{
+    EVP_MD_CTX* ctx = (EVP_MD_CTX*) ctxAddress;
+    KAE_TRACE("KAEDigest_nativeUpdate(ctx = %p, input = %p, offset = %d, inLen = %d", ctx, input, offset, inLen);
+    if (ctx == NULL) {
+        return;
+    }
+
+    jint in_offset = offset;
+    jint in_size = inLen;
+    int result_code = 0;
+    if (in_size <= DIGEST_STACK_SIZE) { // allocation on the stack
+        jbyte buffer[DIGEST_STACK_SIZE];
+        (*env)->GetByteArrayRegion(env, input, offset, inLen, buffer);
+        result_code = EVP_DigestUpdate(ctx, buffer, inLen);
+    } else { // data chunk
+        jint remaining = in_size;
+        jint buf_size = (remaining >= DIGEST_CHUNK_SIZE) ? DIGEST_CHUNK_SIZE : remaining;
+        jbyte* buffer = malloc(buf_size);
+        if (buffer == NULL) {
+            KAE_ThrowOOMException(env, "malloc error");
+            return;
+        }
+        while (remaining > 0) {
+            jint chunk_size = (remaining >= buf_size) ? buf_size : remaining;
+            (*env)->GetByteArrayRegion(env, input, in_offset, chunk_size, buffer);
+            result_code = EVP_DigestUpdate(ctx, buffer, chunk_size);
+            if (!result_code) {
+                break;
+            }
+            in_offset += chunk_size;
+            remaining -= chunk_size;
+        }
+        free(buffer);
+    }
+    if (!result_code) {
+        KAE_ThrowFromOpenssl(env, "EVP_DigestUpdate failed", KAE_ThrowRuntimeException);
+        return;
+    }
+    KAE_TRACE("KAEDigest_nativeUpdate EVP_DigestUpdate success");
+    KAE_TRACE("KAEDigest_nativeUpdate: finished");
+}
+
+/*
+ * Class:     org_openeuler_security_openssl_KAEDigest
+ * Method:    nativeDigest
+ * Signature: (Ljava/lang/String;J[BII)I
+ */
+JNIEXPORT jint JNICALL
+Java_org_openeuler_security_openssl_KAEDigest_nativeDigest(JNIEnv *env, jclass cls,
+    jlong ctxAddress, jbyteArray output, jint offset, jint len)
+{
+    EVP_MD_CTX* ctx = (EVP_MD_CTX*) ctxAddress;
+    KAE_TRACE("KAEDigest_nativeDigest(ctx = %p, output = %p, offset = %d, len = %d", ctx, output, offset, len);
+    unsigned char* md = NULL;
+    unsigned int bytesWritten = 0;
+
+    if (ctx == NULL) {
+        return 0;
+    }
+
+    if (len <= 0 || len > DIGEST_LENGTH_THRESHOLD) {
+        KAE_ThrowRuntimeException(env, "len out of length");
+        return 0;
+    }
+    md = malloc(len);
+    if (md == NULL) {
+        KAE_ThrowOOMException(env, "malloc error");
+        return 0;
+    }
+
+    // EVP_DigestFinal_ex
+    int result_code = EVP_DigestFinal_ex(ctx, md, &bytesWritten);
+    if (result_code == 0) {
+        KAE_ThrowFromOpenssl(env, "EVP_DigestFinal_ex failed", KAE_ThrowRuntimeException);
+        goto cleanup;
+    }
+    KAE_TRACE("KAEDigest_nativeFinal EVP_DigestFinal_ex success, bytesWritten = %d", bytesWritten);
+
+    (*env)->SetByteArrayRegion(env, output, offset, bytesWritten, (jbyte*) md);
+
+    KAE_TRACE("KAEDigest_nativeFinal: finished");
+
+cleanup:
+    free(md);
+    return bytesWritten;
+}
+
+/*
+* Class:     org_openeuler_security_openssl_KAEDigest
+* Method:    nativeClone
+* Signature: (J)J
+*/
+JNIEXPORT jlong JNICALL
+Java_org_openeuler_security_openssl_KAEDigest_nativeClone(JNIEnv *env, jclass cls, jlong ctxAddress)
+{
+    EVP_MD_CTX* ctx = (EVP_MD_CTX*) ctxAddress;
+    KAE_TRACE("KAEDigest_nativeClone: ctx = %p", ctx);
+    if (ctx == NULL) {
+        return 0;
+    }
+
+    EVP_MD_CTX* ctxCopy = EVP_MD_CTX_create();
+    if (ctxCopy == NULL) {
+        KAE_ThrowOOMException(env, "create EVP_MD_CTX fail");
+        return 0;
+    }
+    KAE_TRACE("KAEDigest_nativeClone: create ctxCopy => %p", ctxCopy);
+
+    int result_code = EVP_MD_CTX_copy_ex(ctxCopy, ctx);
+    if (result_code == 0) {
+        KAE_ThrowFromOpenssl(env, "EVP_MD_CTX_copy_ex failed", KAE_ThrowRuntimeException);
+        goto cleanup;
+    }
+    KAE_TRACE("KAEDigest_nativeClone EVP_MD_CTX_copy_ex(ctxCopy = %p, ctx = %p) success", ctxCopy, ctx);
+    KAE_TRACE("KAEDigest_nativeClone: finished");
+    return (jlong) ctxCopy;
+
+cleanup:
+    EVP_MD_CTX_destroy(ctxCopy);
+    return 0;
+}
+
+/*
+ * Class:     org_openeuler_security_openssl_KAEDigest
+ * Method:    nativeFree
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL
+Java_org_openeuler_security_openssl_KAEDigest_nativeFree(JNIEnv *env, jclass cls, jlong ctxAddress)
+{
+    EVP_MD_CTX* ctx = (EVP_MD_CTX*) ctxAddress;
+    KAE_TRACE("KAEDigest_nativeFree(ctx = %p)", ctx);
+    if (ctx != NULL) {
+        EVP_MD_CTX_destroy(ctx);
+    }
+
+    KAE_TRACE("KAEDigest_nativeFree: finished");
+}
\ No newline at end of file
diff --git a/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_exception.c b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_exception.c
new file mode 100644
index 000000000..c0579ebf4
--- /dev/null
+++ b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_exception.c
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include <openssl/rsaerr.h>
+#include "kae_log.h"
+#include "kae_exception.h"
+#include "openssl_ad.h"
+
+void KAE_ThrowByName(JNIEnv* env, const char* name, const char* msg) {
+    jclass cls = (*env)->FindClass(env, name);
+    if (cls != 0) {
+        (*env)->ThrowNew(env, cls, msg);
+        (*env)->DeleteLocalRef(env, cls);
+    }
+}
+
+void KAE_ThrowOOMException(JNIEnv* env, const char* msg) {
+    KAE_ThrowByName(env, "java/lang/OutOfMemoryError", msg);
+}
+
+void KAE_ThrowNullPointerException(JNIEnv* env, const char* msg) {
+    KAE_ThrowByName(env, "java/lang/NullPointerException", msg);
+}
+
+void KAE_ThrowArrayIndexOutOfBoundsException(JNIEnv* env, const char* msg) {
+    KAE_ThrowByName(env, "java/lang/ArrayIndexOutOfBoundsException", msg);
+}
+
+void KAE_ThrowEvpException(JNIEnv* env, int reason, const char* msg, void (* defaultException)(JNIEnv*, const char*)) {
+    switch (reason) {
+        case EVP_R_UNSUPPORTED_ALGORITHM:
+            KAE_ThrowByName(env, "java/security/NoSuchAlgorithmException", msg);
+            break;
+        case EVP_R_MISSING_PARAMETERS:
+            KAE_ThrowByName(env, "java/security/InvalidKeyException", msg);
+            break;
+        case EVP_R_BAD_DECRYPT:
+        case EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH:
+        case EVP_F_EVP_PKEY_DECRYPT:
+        case EVP_R_PUBLIC_KEY_NOT_RSA:
+        case EVP_R_CTRL_NOT_IMPLEMENTED:
+            KAE_ThrowByName(env, "javax/crypto/BadPaddingException", msg);
+            break;
+        default:
+            defaultException(env, msg);
+            break;
+    }
+}
+
+void KAE_ThrowRuntimeException(JNIEnv* env, const char* msg) {
+    KAE_ThrowByName(env, "java/lang/RuntimeException", msg);
+}
+
+void KAE_ThrowBadPaddingException(JNIEnv* env, const char* msg) {
+    KAE_ThrowByName(env, "javax/crypto/BadPaddingException", msg);
+}
+
+void KAE_ThrowInvalidKeyException(JNIEnv* env, const char* msg) {
+    KAE_ThrowByName(env, "java/security/InvalidKeyException", msg);
+}
+
+void KAE_ThrowInvalidAlgorithmParameterException(JNIEnv* env, const char* msg) {
+    KAE_ThrowByName(env, "java/security/InvalidAlgorithmParameterException", msg);
+}
+
+void KAE_ThrowFromOpenssl(JNIEnv* env, const char* msg, void (* defaultException)(JNIEnv*, const char*)) {
+    const char* file = NULL;
+    const char* data = NULL;
+    int line = 0;
+    int flags = 0;
+    unsigned long err;
+    static const int ESTRING_SIZE = 256;
+
+    err = ERR_get_error_line_data(&file, &line, &data, &flags);
+    if (err == 0) {
+        defaultException(env, msg);
+        return;
+    }
+
+    if (!(*env)->ExceptionCheck(env)) {
+        char estring[ESTRING_SIZE];
+        ERR_error_string_n(err, estring, ESTRING_SIZE);
+        int lib = ERR_GET_LIB(err);
+        int func = ERR_GET_FUNC(err);
+        int reason = ERR_GET_REASON(err);
+        KAE_TRACE("OpenSSL error in %s: err=%lx, lib=%x, func=%x, reason=%x, file=%s, line=%d, estring=%s, data=%s", msg, err,
+                  lib, func, reason, file, line, estring, (flags & ERR_TXT_STRING) ? data : "(no data)");
+        // Ignore exceptions in RSA_verify_PKCS1_PSS_mgf1 function
+        if (lib == ERR_LIB_RSA && func == RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1) {
+          return;
+        }
+
+        if (lib == ERR_LIB_EVP || lib == ERR_LIB_RSA) {
+            KAE_ThrowEvpException(env, reason, estring, defaultException);
+        } else {
+            defaultException(env, estring);
+        }
+    }
+
+    ERR_clear_error();
+}
+
+void KAE_ThrowAEADBadTagException(JNIEnv *env, const char *msg) {
+    KAE_ThrowByName(env, "javax/crypto/AEADBadTagException", msg);
+}
+
+void KAE_ThrowSignatureException(JNIEnv* env, const char* msg) {
+    KAE_ThrowByName(env, "java/security/SignatureException", msg);
+}
+
+void KAE_ThrowClassNotFoundException(JNIEnv* env, const char* msg) {
+    KAE_ThrowByName(env, "java/lang/ClassNotFoundException", msg);
+}
diff --git a/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_exception.h b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_exception.h
new file mode 100644
index 000000000..f33f993e4
--- /dev/null
+++ b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_exception.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef KAE_EXCEPTION_H
+#define KAE_EXCEPTION_H
+
+#include <jni.h>
+
+/* Throw a Java exception by name */
+void KAE_ThrowByName(JNIEnv* env, const char* name, const char* msg);
+
+void KAE_ThrowOOMException(JNIEnv* env, const char* msg);
+
+void KAE_ThrowNullPointerException(JNIEnv* env, const char* msg);
+
+void KAE_ThrowArrayIndexOutOfBoundsException(JNIEnv* env, const char* msg);
+
+void KAE_ThrowFromOpenssl(JNIEnv* env, const char* msg, void (* defaultException)(JNIEnv*, const char*));
+
+void KAE_ThrowEvpException(JNIEnv* env, int reason, const char* msg, void (* defaultException)(JNIEnv*, const char*));
+
+void KAE_ThrowRuntimeException(JNIEnv* env, const char* msg);
+
+void KAE_ThrowBadPaddingException(JNIEnv* env, const char* msg);
+
+/* Throw InvalidKeyException */
+void KAE_ThrowInvalidKeyException(JNIEnv* env, const char* msg);
+
+/* Throw AlgorithmParameterException */
+void KAE_ThrowInvalidAlgorithmParameterException(JNIEnv* env, const char* msg);
+
+void KAE_ThrowAEADBadTagException(JNIEnv* env, const char* msg);
+
+void KAE_ThrowSignatureException(JNIEnv* env, const char* msg);
+
+void KAE_ThrowClassNotFoundException(JNIEnv* env, const char* msg);
+#endif
diff --git a/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_hmac.c b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_hmac.c
new file mode 100644
index 000000000..ad7b86ecd
--- /dev/null
+++ b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_hmac.c
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <jni.h>
+#include <string.h>
+#include <openssl/hmac.h>
+#include "kae_exception.h"
+#include "kae_log.h"
+#include "kae_util.h"
+
+static const EVP_MD* EVPGetDigestByName(JNIEnv* env, const char* algo)
+{
+    static const EVP_MD* md5     = NULL;
+    static const EVP_MD* sha1    = NULL;
+    static const EVP_MD* sha224  = NULL;
+    static const EVP_MD* sha256  = NULL;
+    static const EVP_MD* sha384  = NULL;
+    static const EVP_MD* sha512  = NULL;
+
+    if (strcasecmp(algo, "md5") == 0) {
+        return md5 == NULL ? md5 = EVP_get_digestbyname(algo) : md5;
+    } else if (strcasecmp(algo, "sha1") == 0) {
+        return sha1 == NULL ? sha1 = EVP_get_digestbyname(algo) : sha1;
+    } else if (strcasecmp(algo, "sha224") == 0) {
+        return sha224 == NULL ? sha224 = EVP_get_digestbyname(algo) : sha224;
+    } else if (strcasecmp(algo, "sha256") == 0) {
+        return sha256 == NULL ? sha256 = EVP_get_digestbyname(algo) : sha256;
+    } else if (strcasecmp(algo, "sha384") == 0) {
+        return sha384 == NULL ? sha384 = EVP_get_digestbyname(algo) : sha384;
+    } else if (strcasecmp(algo, "sha512") == 0) {
+        return sha512 == NULL ? sha512 = EVP_get_digestbyname(algo) : sha512;
+    } else {
+        KAE_ThrowRuntimeException(env, "EVPGetDigestByName error");
+        return 0;
+    }
+}
+
+/*
+ * Class:     org_openeuler_security_openssl_KAEHMac
+ * Method:    nativeInit
+ * Signature: ([BILjava/lang/String;)J
+ */
+JNIEXPORT jlong JNICALL Java_org_openeuler_security_openssl_KAEHMac_nativeInit
+    (JNIEnv* env, jclass cls, jbyteArray key, jint key_len, jstring algoStr) {
+    if (key == NULL || algoStr == NULL) {
+        KAE_ThrowNullPointerException(env, "param key or algoStr is null");
+        return 0;
+    }
+    if (key_len <= 0) {
+        KAE_ThrowArrayIndexOutOfBoundsException(env, "key");
+        return 0;
+    }
+    HMAC_CTX* ctx = NULL;
+    jbyte* key_buffer = NULL;
+    const EVP_MD* md = NULL;
+    ENGINE* kaeEngine = NULL;
+
+    const char* algo = (*env)->GetStringUTFChars(env, algoStr, 0);
+    md = EVPGetDigestByName(env, algo);
+
+    kaeEngine = GetHmacEngineByAlgorithmName(algo);
+    KAE_TRACE("KAEHMac_nativeInit: kaeEngine => %p", kaeEngine);
+
+    (*env)->ReleaseStringUTFChars(env, algoStr, algo);
+    if (md == NULL) {
+        KAE_ThrowRuntimeException(env, "algorithm unsupport");
+        return 0;
+    }
+
+    // get secret-key
+    key_buffer = malloc(key_len);
+    if (key_buffer == NULL) {
+        KAE_ThrowOOMException(env, "malloc failed");
+        return 0;
+    }
+    (*env)->GetByteArrayRegion(env, key, 0, key_len, key_buffer);
+
+    // create a hmac context
+    ctx = HMAC_CTX_new();
+    if (ctx == NULL) {
+        KAE_ThrowRuntimeException(env, "Hmac_CTX_new invoked failed");
+        goto cleanup;
+    }
+
+    // init hmac context with sc_key and evp_md
+    int result_code = HMAC_Init_ex(ctx, key_buffer, key_len, md, kaeEngine);
+    if (result_code == 0) {
+        KAE_ThrowRuntimeException(env, "Hmac_Init_ex invoked failed");
+        goto cleanup;
+    }
+    free(key_buffer);
+    return (jlong) ctx;
+
+cleanup:
+    free(key_buffer);
+    HMAC_CTX_free(ctx);
+    return 0;
+}
+
+/*
+ * Class:     org_openeuler_security_openssl_KAEHMac
+ * Method:    nativeUpdate
+ * Signature: (J[BII)V
+ */
+JNIEXPORT void JNICALL Java_org_openeuler_security_openssl_KAEHMac_nativeUpdate
+    (JNIEnv* env, jclass cls, jlong hmac_ctx, jbyteArray input, jint in_offset, jint in_len) {
+    KAE_TRACE("KAEHMac_nativeUpdate(ctx = %p, input = %p, offset = %d, inLen = %d)", (void*) hmac_ctx, input, in_offset, in_len);
+    HMAC_CTX* ctx = (HMAC_CTX*) hmac_ctx;
+    if (ctx == NULL || input == NULL) {
+        KAE_ThrowNullPointerException(env, "param ctx or input is null");
+        return;
+    }
+    int input_size = (*env)->GetArrayLength(env, input);
+    if ((in_offset < 0) || (in_len < 0) || (in_offset > input_size - in_len)) {
+        KAE_ThrowArrayIndexOutOfBoundsException(env, "input");
+        return;
+    }
+    // do nothing while in_len is 0
+    if (in_len == 0) {
+        return;
+    }
+
+    jbyte* buffer = malloc(in_len);
+    if (buffer == NULL) {
+        KAE_ThrowOOMException(env, "malloc failed");
+        return;
+    }
+    (*env)->GetByteArrayRegion(env, input, in_offset, in_len, buffer);
+    if (!HMAC_Update(ctx, (unsigned char*) buffer, in_len)) {
+        KAE_ThrowRuntimeException(env, "Hmac_Update invoked failed");
+    }
+    free(buffer);
+}
+
+/*
+ * Class:     org_openeuler_security_openssl_KAEHMac
+ * Method:    nativeFinal
+ * Signature: (J[BII)I
+ */
+JNIEXPORT jint JNICALL Java_org_openeuler_security_openssl_KAEHMac_nativeFinal
+    (JNIEnv* env, jclass cls, jlong hmac_ctx, jbyteArray output, jint out_offset, jint in_len) {
+    HMAC_CTX* ctx = (HMAC_CTX*) hmac_ctx;
+    if (ctx == NULL || output == NULL) {
+        KAE_ThrowNullPointerException(env, "param ctx or input is null");
+        return 0;
+    }
+    int output_size = (*env)->GetArrayLength(env, output);
+    if ((out_offset < 0) || (in_len < 0) || (out_offset > output_size - in_len)) {
+        KAE_ThrowArrayIndexOutOfBoundsException(env, "output");
+        return 0;
+    }
+
+    jbyte* temp_result = NULL;
+
+    temp_result = malloc(in_len);
+    if (temp_result == NULL) {
+        KAE_ThrowOOMException(env, "malloc failed");
+        return 0;
+    }
+    // do final
+    unsigned int bytesWritten = 0;
+    int result_code = HMAC_Final(ctx, (unsigned char*) temp_result, &bytesWritten);
+    if (result_code == 0) {
+        KAE_ThrowRuntimeException(env, "Hmac_Final invoked failed");
+        goto cleanup;
+    }
+
+    // write back to output_array
+    (*env)->SetByteArrayRegion(env, output, out_offset, bytesWritten, (jbyte*) temp_result);
+    KAE_TRACE("KAEHMac_nativeFinal success, output_offset = %d, bytesWritten = %u", out_offset, bytesWritten);
+
+cleanup:
+    free(temp_result);
+    return bytesWritten;
+}
+
+/*
+ * Class:     org_openeuler_security_openssl_KAEHMac
+ * Method:    nativeFree
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_org_openeuler_security_openssl_KAEHMac_nativeFree
+    (JNIEnv* env, jclass cls, jlong hmac_ctx) {
+    HMAC_CTX* ctx = (HMAC_CTX*) hmac_ctx;
+    if (ctx != NULL) {
+        HMAC_CTX_free(ctx);
+    }
+}
diff --git a/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_keyagreement_dh.c b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_keyagreement_dh.c
new file mode 100644
index 000000000..e9dfa4094
--- /dev/null
+++ b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_keyagreement_dh.c
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <memory.h>
+#include <openssl/bio.h>
+#include <openssl/ssl.h>
+#include <openssl/engine.h>
+#include <openssl/dh.h>
+#include <stdio.h>
+#include "kae_util.h"
+#include "kae_exception.h"
+#include "kae_log.h"
+#include "org_openeuler_security_openssl_KAEDHKeyAgreement.h"
+
+
+/*
+ * Class:     org_openeuler_security_openssl_KAEDHKeyAgreement
+ * Method:    nativeComputeKey
+ */
+JNIEXPORT jbyteArray JNICALL Java_org_openeuler_security_openssl_KAEDHKeyAgreement_nativeComputeKey(JNIEnv* env,
+                                 jobject obj, jbyteArray y, jbyteArray x, jbyteArray p, jbyteArray g, jint pSize) {
+
+    KAE_TRACE("Java_org_openeuler_security_openssl_KAEDHKeyAgreement_nativeComputeKey start.");
+
+    DH* dh = NULL;
+    BIGNUM* y_bn = NULL;
+    BIGNUM* x_bn = NULL;
+    BIGNUM* p_bn = NULL;
+    BIGNUM* g_bn = NULL;
+    BIGNUM* computeKeyRetBn = NULL;
+    int computekeyLength = 0;
+    unsigned char* secret = NULL;
+    jbyteArray retByteArray = NULL;
+    ENGINE* kaeEngine = GetEngineByAlgorithmIndex(DH_INDEX);
+    KAE_TRACE("KAEDHKeyAgreement_nativeComputeKey: kaeEngine => %p", kaeEngine);
+
+    // bits to Bytes
+    int pSizeInByte = (pSize +7) >> 3;
+
+    if ((secret = (unsigned char*)malloc(pSizeInByte)) == NULL) {
+        KAE_ThrowOOMException(env, "malloc secret failed.");
+        goto cleanup;
+    }
+    memset(secret, 0, pSizeInByte);
+
+    if ((dh = DH_new_method(kaeEngine)) == NULL) {
+        KAE_ThrowOOMException(env, "Allocate DH failed in nativeComputeKey.");
+        goto cleanup;
+    }
+
+    if ((y_bn = KAE_GetBigNumFromByteArray(env, y)) == NULL) {
+        KAE_ThrowOOMException(env, "Convert y to BIGNUM failed.");
+        goto cleanup;
+    }
+
+    if ((x_bn = KAE_GetBigNumFromByteArray(env, x)) == NULL) {
+        KAE_ThrowOOMException(env, "Convert x to BIGNUM failed.");
+        goto cleanup;
+    }
+
+    if ((p_bn = KAE_GetBigNumFromByteArray(env, p)) == NULL) {
+        KAE_ThrowOOMException(env, "Convert p to BIGNUM failed.");
+        goto cleanup;
+    }
+
+    if ((g_bn = KAE_GetBigNumFromByteArray(env, g)) == NULL) {
+        KAE_ThrowOOMException(env, "Convert g to BIGNUM failed.");
+        goto cleanup;
+    }
+
+    if ((computeKeyRetBn = BN_new()) == NULL) {
+        KAE_ThrowOOMException(env, "Allocate BN failed.");
+        goto cleanup;
+    }
+
+    if (!DH_set0_pqg(dh, BN_dup(p_bn), NULL, BN_dup(g_bn))) {
+        KAE_ThrowRuntimeException(env, "DH_set0_pqg failed.");
+        goto cleanup;
+    }
+
+    if (!DH_set0_key(dh,  NULL, BN_dup(x_bn))) {
+        KAE_ThrowRuntimeException(env, "DH_set0_key failed.");
+        goto cleanup;
+    }
+
+    computekeyLength = DH_compute_key(secret, y_bn, dh);
+
+    if (computekeyLength  <= 0 ) {
+        KAE_ThrowRuntimeException(env, "DH_compute_key failed.");
+        goto cleanup;
+    }
+
+    BN_bin2bn(secret, computekeyLength, computeKeyRetBn);
+
+    retByteArray = KAE_GetByteArrayFromBigNum(env, computeKeyRetBn);
+    if (retByteArray == NULL) {
+        KAE_ThrowRuntimeException(env, "GetByteArrayFromBigNum failed in nativeComputeKey.");
+        goto cleanup;
+    }
+    KAE_TRACE("Java_org_openeuler_security_openssl_KAEDHKeyAgreement_nativeComputeKey finished!");
+
+cleanup:
+    if (dh != NULL)
+        DH_free(dh);
+    if (y_bn != NULL)
+        KAE_ReleaseBigNumFromByteArray(y_bn);
+    if (x_bn != NULL)
+        KAE_ReleaseBigNumFromByteArray(x_bn);
+    if (p_bn != NULL)
+        KAE_ReleaseBigNumFromByteArray(p_bn);
+    if (g_bn != NULL)
+        KAE_ReleaseBigNumFromByteArray(g_bn);
+    if (secret != NULL) {
+        memset(secret, 0, pSizeInByte);
+        free(secret);
+    }
+    if (computeKeyRetBn != NULL)
+        BN_free(computeKeyRetBn);
+
+    return retByteArray;
+}
\ No newline at end of file
diff --git a/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_keyagreement_ecdh.c b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_keyagreement_ecdh.c
new file mode 100644
index 000000000..b0877a25e
--- /dev/null
+++ b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_keyagreement_ecdh.c
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <memory.h>
+#include <openssl/objects.h>
+#include <openssl/ec.h>
+#include "kae_log.h"
+#include "kae_exception.h"
+#include "kae_util.h"
+#include "org_openeuler_security_openssl_KAEECDHKeyAgreement.h"
+
+static void FreeGenerateSecretParam(BIGNUM* s, BIGNUM* wX, BIGNUM* wY,
+    EC_POINT* pub, EC_KEY* eckey, EC_GROUP* group, unsigned char* shareKey, int shareKeyLen)
+{
+    KAE_ReleaseBigNumFromByteArray(s);
+    KAE_ReleaseBigNumFromByteArray(wX);
+    KAE_ReleaseBigNumFromByteArray(wY);
+    if (pub != NULL) {
+        EC_POINT_free(pub);
+    }
+    if (eckey != NULL) {
+        EC_KEY_free(eckey);
+    }
+    if (group != NULL) {
+        EC_GROUP_free(group);
+    }
+    if (shareKey != NULL) {
+        memset(shareKey, 0, shareKeyLen);
+        free(shareKey);
+    }
+}
+
+/*
+ * Class:     org_openeuler_security_openssl_KAEECDHKeyAgreement
+ * Method:    nativeGenerateSecret
+ * Signature: (Ljava/lang/String;[B[B[B)[B
+ */
+JNIEXPORT jbyteArray JNICALL Java_org_openeuler_security_openssl_KAEECDHKeyAgreement_nativeGenerateSecret
+    (JNIEnv* env, jclass cls, jstring curveName, jbyteArray wXArr, jbyteArray wYArr, jbyteArray sArr)
+{
+    EC_GROUP* group = NULL;
+    EC_KEY* eckey = NULL;
+    BIGNUM* wX = NULL;
+    BIGNUM* wY = NULL;
+    BIGNUM* s = NULL;
+    EC_POINT* pub = NULL;
+    jbyteArray javaBytes = NULL;
+    unsigned char* shareKey = NULL;
+    const char *curve = (*env)->GetStringUTFChars(env, curveName, 0);
+    int nid = OBJ_sn2nid(curve);
+    (*env)->ReleaseStringUTFChars(env, curveName, curve);
+
+    // Initialization of secret key.
+    int expectSecretLen = 0;
+
+    if ((nid == NID_undef) || (group = EC_GROUP_new_by_curve_name(nid)) == NULL) {
+        goto cleanup;
+    }
+    if ((s = KAE_GetBigNumFromByteArray(env, sArr)) == NULL || (wX = KAE_GetBigNumFromByteArray(env, wXArr)) == NULL
+        || (wY = KAE_GetBigNumFromByteArray(env, wYArr)) == NULL) {
+        KAE_ThrowOOMException(env, "failed to allocate BN_new");
+        goto cleanup;
+    }
+    if ((eckey = EC_KEY_new()) == NULL || !EC_KEY_set_group(eckey, group)) {
+        goto cleanup;
+    }
+    if ((pub = EC_POINT_new(group)) == NULL) {
+        goto cleanup;
+    }
+    if (!EC_POINT_set_affine_coordinates_GFp(group, pub, wX, wY, NULL)) {
+        goto cleanup;
+    }
+    if (!EC_KEY_set_public_key(eckey, pub) || !EC_KEY_set_private_key(eckey, s)) {
+        goto cleanup;
+    }
+
+    // Get the length of secret key, in bytes.
+    expectSecretLen = (EC_GROUP_get_degree(group) + 7) / 8;
+
+    if ((shareKey = malloc(expectSecretLen)) == NULL) {
+        KAE_ThrowOOMException(env, "malloc error");
+        goto cleanup;
+    }
+    memset(shareKey, 0, expectSecretLen);
+
+    // Perform ecdh keyagreement.
+    if (ECDH_compute_key(shareKey, expectSecretLen, pub, eckey, NULL) != expectSecretLen) {
+        goto cleanup;
+    }
+
+    if ((javaBytes = (*env)->NewByteArray(env, expectSecretLen)) == NULL) {
+        goto cleanup;
+    }
+    (*env)->SetByteArrayRegion(env, javaBytes, 0, expectSecretLen, (jbyte*)shareKey);
+    FreeGenerateSecretParam(s, wX, wY, pub, eckey, group, shareKey, expectSecretLen);
+    return javaBytes;
+
+cleanup:
+    FreeGenerateSecretParam(s, wX, wY, pub, eckey, group, shareKey, expectSecretLen);
+    return NULL;
+}
\ No newline at end of file
diff --git a/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_keypairgenerator_dh.c b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_keypairgenerator_dh.c
new file mode 100644
index 000000000..6315cc6ee
--- /dev/null
+++ b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_keypairgenerator_dh.c
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <openssl/bio.h>
+#include <openssl/ssl.h>
+#include <openssl/engine.h>
+#include <openssl/dh.h>
+#include <stdio.h>
+#include "kae_util.h"
+#include "kae_log.h"
+#include "org_openeuler_security_openssl_KAEDHKeyPairGenerator.h"
+#include "kae_exception.h"
+
+
+/*
+* Class:     org_openeuler_security_openssl_KAEDHKeyPairGenerator
+* Method:    nativeGenerateKeyPair
+* Signature: ([B[BI)[[B
+*/
+
+JNIEXPORT jobjectArray JNICALL Java_org_openeuler_security_openssl_KAEDHKeyPairGenerator_nativeGenerateKeyPair
+    (JNIEnv* env, jclass cls, jbyteArray p, jbyteArray g,  jint lSize)
+{
+    DH* dh = NULL;
+    BIGNUM* p_bn = NULL;
+    BIGNUM* g_bn = NULL;
+    const BIGNUM* pri_key_bn = NULL;
+    const BIGNUM* pub_key_bn = NULL;
+    jclass byteArrayClass = NULL;
+    jobjectArray keys = NULL;
+    jbyteArray pri_key = NULL;
+    jbyteArray pub_key = NULL;
+    ENGINE* kaeEngine = GetEngineByAlgorithmIndex(DH_INDEX);
+    KAE_TRACE("KAEDHKeyPairGenerator_nativeGenerateKeyPair: kaeEngine => %p", kaeEngine);
+
+    KAE_TRACE("Java_org_openeuler_security_openssl_KAEDHKeyPairGenerator_nativeGenerateKeyPair start !");
+
+    if ((dh = DH_new_method(kaeEngine)) == NULL) {
+        KAE_ThrowOOMException(env, "Allocate DH failed in nativeGenerateKeyPair!");
+        goto cleanup;
+    }
+
+    if ((p_bn = KAE_GetBigNumFromByteArray(env, p)) == NULL) {
+        KAE_ThrowOOMException(env, "Allocate p_bn failed in nativeGenerateKeyPair!");
+        goto cleanup;
+    }
+
+    if ((g_bn = KAE_GetBigNumFromByteArray(env, g)) == NULL) {
+        KAE_ThrowOOMException(env, "Allocate g_bn failed in nativeGenerateKeyPair!");
+        goto cleanup;
+    }
+
+    if (!DH_set0_pqg(dh, BN_dup(p_bn), NULL, BN_dup(g_bn))) {
+        KAE_ThrowRuntimeException(env, "DH_set0_pqg failed in nativeGenerateKeyPair.");
+        goto cleanup;
+    }
+
+    // Return value is fixed to 1, nothing to check.
+    DH_set_length(dh, lSize);
+
+    if (!DH_generate_key(dh)) {
+        KAE_ThrowInvalidAlgorithmParameterException(env, "DH generate key failed in nativeGenerateKeyPair.");
+        goto cleanup;
+    }
+
+    if ((byteArrayClass = (*env)->FindClass(env, "[B")) == NULL) {
+        KAE_ThrowClassNotFoundException(env, "Class byte[] not found.");
+        goto cleanup;
+    }
+
+    if ((keys = (*env)->NewObjectArray(env, 2, byteArrayClass, NULL)) == NULL) {
+        KAE_ThrowOOMException(env, "Allocate ByteArray failed in nativeGenerateKeyPair!");
+        goto cleanup;
+    }
+
+    // Return the ptr of private  key in dh.
+    pri_key_bn = DH_get0_priv_key(dh);
+    pub_key_bn = DH_get0_pub_key(dh);
+
+    pub_key = KAE_GetByteArrayFromBigNum(env, pub_key_bn);
+    if (pub_key == NULL) {
+        KAE_ThrowOOMException(env, "PublicKey allocate failed in nativeGenerateKeyPair.");
+        goto cleanup;
+    }
+
+    pri_key = KAE_GetByteArrayFromBigNum(env, pri_key_bn);
+    if (pri_key == NULL) {
+        KAE_ThrowRuntimeException(env, "GetByteArrayFromBigNum failed in nativeGenerateKeyPair.");
+        goto cleanup;
+    }
+
+    (*env)->SetObjectArrayElement(env, keys, 0, pub_key);
+    (*env)->SetObjectArrayElement(env, keys, 1, pri_key);
+
+    KAE_TRACE("Java_org_openeuler_security_openssl_KAEDHKeyPairGenerator_nativeGenerateKeyPair finished !");
+
+cleanup:
+    if (dh != NULL)
+        DH_free(dh);
+    if (p_bn != NULL)
+        KAE_ReleaseBigNumFromByteArray(p_bn);
+    if (g_bn != NULL)
+        KAE_ReleaseBigNumFromByteArray(g_bn);
+    if (byteArrayClass != NULL)
+        (*env)->DeleteLocalRef(env, byteArrayClass);
+    if (pub_key != NULL)
+        (*env)->DeleteLocalRef(env, pub_key);
+    if (pri_key != NULL)
+        (*env)->DeleteLocalRef(env, pri_key);
+
+    return keys;
+}
\ No newline at end of file
diff --git a/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_keypairgenerator_ec.c b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_keypairgenerator_ec.c
new file mode 100644
index 000000000..0449f8a26
--- /dev/null
+++ b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_keypairgenerator_ec.c
@@ -0,0 +1,505 @@
+/*
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <stdbool.h>
+#include <openssl/objects.h>
+#include <openssl/ec.h>
+#include "kae_util.h"
+#include "kae_exception.h"
+#include "kae_log.h"
+#include "org_openeuler_security_openssl_KAEECKeyPairGenerator.h"
+
+#define KAE_EC_PARAM_NUM_SIZE 7
+#define KAE_EC_KEY_NUM_SIZE 3
+
+// ECDH param index.
+typedef enum ECDHParamIndex {
+    ecdhP = 0,
+    ecdhA,
+    ecdhB,
+    ecdhX,
+    ecdhY,
+    ecdhOrder,
+    ecdhCofactor
+} ECDHParamIndex;
+
+// ECDH Key index.
+typedef enum ECDHKeyIndex {
+    ecdhWX = 0,
+    ecdhWY,
+    ecdhS
+} ECDHKeyIndex;
+
+static void FreeECDHCurveParam(JNIEnv* env, BIGNUM* p, BIGNUM* a, BIGNUM* b, jbyteArray paramP,
+    jbyteArray paramA, jbyteArray paramB)
+{
+    if (p != NULL) {
+        BN_free(p);
+    }
+    if (a != NULL) {
+        BN_free(a);
+    }
+    if (b != NULL) {
+        BN_free(b);
+    }
+    if (paramP != NULL) {
+        (*env)->DeleteLocalRef(env, paramP);
+    }
+    if (paramA != NULL) {
+        (*env)->DeleteLocalRef(env, paramA);
+    }
+    if (paramB != NULL) {
+        (*env)->DeleteLocalRef(env, paramB);
+    }
+}
+
+// Set p, a, b in group to params.
+static bool SetECDHCurve(JNIEnv* env, EC_GROUP* group, jobjectArray params)
+{
+    BIGNUM* p = NULL;
+    BIGNUM* a = NULL;
+    BIGNUM* b = NULL;
+    jbyteArray paramP = NULL;
+    jbyteArray paramA = NULL;
+    jbyteArray paramB = NULL;
+    if ((p = BN_new()) == NULL || (a = BN_new()) == NULL || (b = BN_new()) == NULL) {
+        KAE_ThrowOOMException(env, "failed to allocate BN_new");
+        goto cleanup;
+    }
+    if (!EC_GROUP_get_curve_GFp(group, p, a, b, NULL)) {
+        goto cleanup;
+    }
+
+    // Set p.
+    if ((paramP = KAE_GetByteArrayFromBigNum(env, p)) == NULL) {
+        goto cleanup;
+    }
+    (*env)->SetObjectArrayElement(env, params, ecdhP, paramP);
+
+    // Set a.
+    if ((paramA = KAE_GetByteArrayFromBigNum(env, a)) == NULL) {
+        goto cleanup;
+    }
+    (*env)->SetObjectArrayElement(env, params, ecdhA, paramA);
+
+    // Set b.
+    if ((paramB = KAE_GetByteArrayFromBigNum(env, b)) == NULL) {
+        goto cleanup;
+    }
+    (*env)->SetObjectArrayElement(env, params, ecdhB, paramB);
+    FreeECDHCurveParam(env, p, a, b, paramP, paramA, paramB);
+    return true;
+
+cleanup:
+    FreeECDHCurveParam(env, p, a, b, paramP, paramA, paramB);
+    return false;
+}
+
+// Set generator(x, y) in group to params.
+static bool SetECDHPoint(JNIEnv* env, EC_GROUP* group, jobjectArray params)
+{
+    BIGNUM* x = NULL;
+    BIGNUM* y = NULL;
+    const EC_POINT* generator = NULL;
+    jbyteArray paramX = NULL;
+    jbyteArray paramY = NULL;
+    if ((x = BN_new()) == NULL || (y = BN_new()) == NULL) {
+        KAE_ThrowOOMException(env, "failed to allocate BN_new");
+        goto cleanup;
+    }
+    if ((generator = EC_GROUP_get0_generator(group)) == NULL) {
+        KAE_ThrowOOMException(env, "failed to allocate ec generator");
+        goto cleanup;
+    }
+    if (!EC_POINT_get_affine_coordinates_GFp(group, generator, x, y, NULL)) {
+        KAE_ThrowFromOpenssl(env, "EC_POINT_set_affine_coordinates_GFp", KAE_ThrowRuntimeException);
+        goto cleanup;
+    }
+
+    // Set x.
+    if ((paramX = KAE_GetByteArrayFromBigNum(env, x)) == NULL) {
+        goto cleanup;
+    }
+    (*env)->SetObjectArrayElement(env, params, ecdhX, paramX);
+
+    // Set y.
+    if ((paramY = KAE_GetByteArrayFromBigNum(env, y)) == NULL) {
+        goto cleanup;
+    }
+    (*env)->SetObjectArrayElement(env, params, ecdhY, paramY);
+    BN_free(x);
+    BN_free(y);
+    (*env)->DeleteLocalRef(env, paramX);
+    (*env)->DeleteLocalRef(env, paramY);
+    return true;
+
+cleanup:
+    if (x != NULL) {
+        BN_free(x);
+    }
+    if (y != NULL) {
+        BN_free(y);
+    }
+    if (paramX != NULL) {
+        (*env)->DeleteLocalRef(env, paramX);
+    }
+    if (paramY != NULL) {
+        (*env)->DeleteLocalRef(env, paramY);
+    }
+    return false;
+}
+
+// Set order, cofactor in group to params.
+static bool SetECDHOrderAndCofactor(JNIEnv* env, EC_GROUP* group, jobjectArray params)
+{
+    BIGNUM* order = NULL;
+    BIGNUM* cofactor = NULL;
+    jbyteArray paramOrder = NULL;
+    jbyteArray paramCofactor = NULL;
+    if ((order = BN_new()) == NULL || (cofactor = BN_new()) == NULL) {
+        goto cleanup;
+    }
+    if (!EC_GROUP_get_order(group, order, NULL)) {
+        goto cleanup;
+    }
+
+    // Set order.
+    if ((paramOrder = KAE_GetByteArrayFromBigNum(env, order)) == NULL) {
+        goto cleanup;
+    }
+    (*env)->SetObjectArrayElement(env, params, ecdhOrder, paramOrder);
+    if (!EC_GROUP_get_cofactor(group, cofactor, NULL)) {
+        goto cleanup;
+    }
+
+    // Set cofactor.
+    if ((paramCofactor = KAE_GetByteArrayFromBigNum(env, cofactor)) == NULL) {
+        goto cleanup;
+    }
+    (*env)->SetObjectArrayElement(env, params, ecdhCofactor, paramCofactor);
+    BN_free(order);
+    BN_free(cofactor);
+    (*env)->DeleteLocalRef(env, paramOrder);
+    (*env)->DeleteLocalRef(env, paramCofactor);
+    return true;
+
+cleanup:
+    if (order != NULL) {
+        BN_free(order);
+    }
+    if (cofactor != NULL) {
+        BN_free(cofactor);
+    }
+    if (paramOrder != NULL) {
+        (*env)->DeleteLocalRef(env, paramOrder);
+    }
+    if (paramCofactor != NULL) {
+        (*env)->DeleteLocalRef(env, paramCofactor);
+    }
+    return false;
+}
+
+static void FreeECDHKeyParam(JNIEnv* env,
+    BIGNUM* wX, BIGNUM* wY, jbyteArray keyWX, jbyteArray keyWY, jbyteArray keyS)
+{
+    if (wX != NULL) {
+        BN_free(wX);
+    }
+    if (wY != NULL) {
+        BN_free(wY);
+    }
+    if (keyWX != NULL) {
+        (*env)->DeleteLocalRef(env, keyWX);
+    }
+    if (keyWY != NULL) {
+        (*env)->DeleteLocalRef(env, keyWY);
+    }
+    if (keyS != NULL) {
+        (*env)->DeleteLocalRef(env, keyS);
+    }
+}
+
+// Set publicKey(wX, wY) and privateKey(s) in eckey to params.
+static bool SetECDHKey(JNIEnv* env, const EC_GROUP* group, jobjectArray params,
+    const EC_KEY* eckey)
+{
+    BIGNUM* wX = NULL;
+    BIGNUM* wY = NULL;
+    const EC_POINT* pub = NULL;
+    const BIGNUM* s = NULL;
+    jbyteArray keyWX = NULL;
+    jbyteArray keyWY = NULL;
+    jbyteArray keyS = NULL;
+    if ((wX = BN_new()) == NULL || (wY = BN_new()) == NULL) {
+        KAE_ThrowOOMException(env, "failed to allocate array");
+        goto cleanup;
+    }
+
+    if ((pub = EC_KEY_get0_public_key(eckey)) == NULL ||
+        !EC_POINT_get_affine_coordinates_GFp(group, pub, wX, wY, NULL)) {
+        goto cleanup;
+    }
+    if ((s = EC_KEY_get0_private_key(eckey)) == NULL) {
+        goto cleanup;
+    }
+
+    // Set wX.
+    if ((keyWX = KAE_GetByteArrayFromBigNum(env, wX)) == NULL) {
+        goto cleanup;
+    }
+    (*env)->SetObjectArrayElement(env, params, ecdhWX, keyWX);
+
+    // Set wY.
+    if ((keyWY = KAE_GetByteArrayFromBigNum(env, wY)) == NULL) {
+        goto cleanup;
+    }
+    (*env)->SetObjectArrayElement(env, params, ecdhWY, keyWY);
+
+    // Set s.
+    if ((keyS = KAE_GetByteArrayFromBigNum(env, s)) == NULL) {
+        goto cleanup;
+    }
+    (*env)->SetObjectArrayElement(env, params, ecdhS, keyS);
+    FreeECDHKeyParam(env, wX, wY, keyWX, keyWY, keyS);
+    return true;
+
+cleanup:
+    FreeECDHKeyParam(env, wX, wY, keyWX, keyWY, keyS);
+    return false;
+}
+
+// Convert EC_GROUP in openssl to byte[][] in java
+static jobjectArray NewECDHParam(JNIEnv* env, EC_GROUP* group)
+{
+    jclass byteArrayClass = (*env)->FindClass(env, "[B");
+    jobjectArray params = (*env)->NewObjectArray(env, KAE_EC_PARAM_NUM_SIZE, byteArrayClass, NULL);
+    if (params == NULL) {
+        KAE_ThrowOOMException(env, "failed to allocate array");
+        goto cleanup;
+    }
+
+    if (!SetECDHCurve(env, group, params)) {
+        goto cleanup;
+    }
+    if (!SetECDHPoint(env, group, params)) {
+        goto cleanup;
+    }
+    if (!SetECDHOrderAndCofactor(env, group, params)) {
+        goto cleanup;
+    }
+
+    (*env)->DeleteLocalRef(env, byteArrayClass);
+    return params;
+
+cleanup:
+    if (byteArrayClass != NULL) {
+        (*env)->DeleteLocalRef(env, byteArrayClass);
+    }
+    if (params != NULL) {
+        (*env)->DeleteLocalRef(env, params);
+    }
+    return NULL;
+}
+
+// Convert EC_KEY in openssl to byte[][] in java
+static jobjectArray NewECDHKey(JNIEnv* env, const EC_GROUP* group, const EC_KEY* eckey)
+{
+    jclass byteArrayClass = (*env)->FindClass(env, "[B");
+    jobjectArray params = (*env)->NewObjectArray(env, KAE_EC_KEY_NUM_SIZE, byteArrayClass, NULL);
+    if (params == NULL) {
+        KAE_ThrowOOMException(env, "failed to allocate array");
+        goto cleanup;
+    }
+    if (!SetECDHKey(env, group, params, eckey)) {
+        goto cleanup;
+    }
+
+    (*env)->DeleteLocalRef(env, byteArrayClass);
+    return params;
+
+cleanup:
+    if (byteArrayClass != NULL) {
+        (*env)->DeleteLocalRef(env, byteArrayClass);
+    }
+    if (params != NULL) {
+        (*env)->DeleteLocalRef(env, params);
+    }
+    return NULL;
+}
+
+static void FreeECDHParam(BIGNUM* p, BIGNUM* a, BIGNUM* b, BIGNUM* x, BIGNUM* y, BIGNUM* order, BIGNUM* cofactor)
+{
+    KAE_ReleaseBigNumFromByteArray(p);
+    KAE_ReleaseBigNumFromByteArray(a);
+    KAE_ReleaseBigNumFromByteArray(b);
+    KAE_ReleaseBigNumFromByteArray(x);
+    KAE_ReleaseBigNumFromByteArray(y);
+    KAE_ReleaseBigNumFromByteArray(order);
+    KAE_ReleaseBigNumFromByteArray(cofactor);
+}
+
+// Convert params in java to EC_GROUP in openssl
+static EC_GROUP* GetGroupByParam(JNIEnv* env, jbyteArray pArr, jbyteArray aArr, jbyteArray bArr,
+    jbyteArray xArr, jbyteArray yArr, jbyteArray orderArr, jint cofactorInt)
+{
+    BIGNUM* p = NULL;
+    BIGNUM* a = NULL;
+    BIGNUM* b = NULL;
+    BIGNUM* x = NULL;
+    BIGNUM* y = NULL;
+    BIGNUM* order = NULL;
+    BIGNUM* cofactor = NULL;
+    EC_GROUP* group = NULL;
+    BN_CTX* ctx = NULL;
+    EC_POINT* generator = NULL;
+    if ((p = KAE_GetBigNumFromByteArray(env, pArr)) == NULL || (a = KAE_GetBigNumFromByteArray(env, aArr)) == NULL ||
+        (b = KAE_GetBigNumFromByteArray(env, bArr)) == NULL || (x = KAE_GetBigNumFromByteArray(env, xArr)) == NULL ||
+        (y = KAE_GetBigNumFromByteArray(env, yArr)) == NULL || (cofactor = BN_new()) == NULL ||
+        (order = KAE_GetBigNumFromByteArray(env, orderArr)) == NULL || !BN_set_word(cofactor, cofactorInt)) {
+        goto cleanup;
+    }
+
+    // Create the curve.
+    if ((ctx = BN_CTX_new()) == NULL || (group = EC_GROUP_new_curve_GFp(p, a, b, ctx)) == NULL) {
+        goto cleanup;
+    }
+
+    // Create the generator and set x, y.
+    if ((generator = EC_POINT_new(group)) == NULL ||
+            !EC_POINT_set_affine_coordinates_GFp(group, generator, x, y, ctx)) {
+        goto cleanup;
+    }
+
+    // Set the generator, order and cofactor.
+    if (!EC_GROUP_set_generator(group, generator, order, cofactor)) {
+        goto cleanup;
+    }
+
+    FreeECDHParam(p, a, b, x, y, order, cofactor);
+    EC_POINT_free(generator);
+    BN_CTX_free(ctx);
+    return group;
+
+cleanup:
+    FreeECDHParam(p, a, b, x, y, order, cofactor);
+    if (group != NULL) {
+        EC_GROUP_free(group);
+    }
+    if (generator != NULL) {
+        EC_POINT_free(generator);
+    }
+    if (ctx != NULL) {
+        BN_CTX_free(ctx);
+    }
+    return NULL;
+}
+
+
+/*
+ * Class:     org_openeuler_security_openssl_KAEECKeyPairGenerator
+ * Method:    nativeGenerateParam
+ * Signature: (Ljava/lang/String;)[[B
+ */
+JNIEXPORT jobjectArray JNICALL Java_org_openeuler_security_openssl_KAEECKeyPairGenerator_nativeGenerateParam(
+    JNIEnv* env, jclass cls, jstring curveName)
+{
+    EC_GROUP* group = NULL;
+    jobjectArray ecdhParam = NULL;
+
+    const char *curve = (*env)->GetStringUTFChars(env, curveName, 0);
+    KAE_TRACE("KAEECKeyPairGenerator_nativeGenerateParam(curveName = %s)", curve);
+    int nid = OBJ_sn2nid(curve);
+    (*env)->ReleaseStringUTFChars(env, curveName, curve);
+    if (nid == NID_undef) {
+        goto cleanup;
+    }
+    // Construct a builtin curve.
+    if ((group = EC_GROUP_new_by_curve_name(nid)) == NULL) {
+        goto cleanup;
+    }
+    ecdhParam = NewECDHParam(env, group);
+
+    if (group != NULL) {
+        EC_GROUP_free(group);
+    }
+    KAE_TRACE("KAEECKeyPairGenerator_nativeGenerateParam success, ecdhParam = %p", ecdhParam);
+    return ecdhParam;
+
+cleanup:
+    if (group != NULL) {
+        EC_GROUP_free(group);
+    }
+    if (ecdhParam != NULL) {
+        (*env)->DeleteLocalRef(env, ecdhParam);
+    }
+    return NULL;
+}
+
+/*
+ * Class:     org_openeuler_security_openssl_KAEECKeyPairGenerator
+ * Method:    nativeGenerateKeyPair
+ * Signature: ([B[B[B[B[B[BI)[[B
+ */
+JNIEXPORT jobjectArray JNICALL Java_org_openeuler_security_openssl_KAEECKeyPairGenerator_nativeGenerateKeyPair(
+    JNIEnv* env, jclass cls, jbyteArray pArr, jbyteArray aArr, jbyteArray bArr,
+    jbyteArray xArr, jbyteArray yArr, jbyteArray orderArr, jint cofactorInt)
+{
+    EC_GROUP* group = NULL;
+    EC_KEY* eckey = NULL;
+    jobjectArray ecdhKey = NULL;
+
+    if ((group = GetGroupByParam(env, pArr, aArr, bArr, xArr, yArr, orderArr, cofactorInt)) == NULL) {
+        goto cleanup;
+    }
+    if ((eckey = EC_KEY_new()) == NULL) {
+        goto cleanup;
+    }
+    if (!EC_KEY_set_group(eckey, group)) {
+        goto cleanup;
+    }
+    // Generates a new public and private key for the supplied eckey object.
+    // Refer to {@link https://www.openssl.org/docs/man1.1.0/man3/EC_KEY_generate_key.html} for details.
+    if (!EC_KEY_generate_key(eckey)) {
+        goto cleanup;
+    }
+
+    ecdhKey = NewECDHKey(env, group, eckey);
+
+    EC_KEY_free(eckey);
+    EC_GROUP_free(group);
+
+    KAE_TRACE("KAEECKeyPairGenerator_nativeGenerateKeyPair success, ecdhKey = %p", ecdhKey);
+    return ecdhKey;
+
+cleanup:
+    if (eckey != NULL) {
+        EC_KEY_free(eckey);
+    }
+    if (group != NULL) {
+        EC_GROUP_free(group);
+    }
+    if (ecdhKey != NULL) {
+        (*env)->DeleteLocalRef(env, ecdhKey);
+    }
+    return NULL;
+}
\ No newline at end of file
diff --git a/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_keypairgenerator_rsa.c b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_keypairgenerator_rsa.c
new file mode 100644
index 000000000..84c2ed109
--- /dev/null
+++ b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_keypairgenerator_rsa.c
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <stdbool.h>
+#include <openssl/rsa.h>
+#include "kae_log.h"
+#include "kae_util.h"
+#include "kae_exception.h"
+#include "org_openeuler_security_openssl_KAERSAKeyPairGenerator.h"
+#define KAE_RSA_PARAM_SIZE 8
+
+// rsa param index
+typedef enum RSAParamIndex {
+    rsaN = 0,
+    rsaE,
+    rsaD,
+    rsaP,
+    rsaQ,
+    rsaDmp1,
+    rsaDmq1,
+    rsaIqmp
+} RSAParamIndex;
+
+// rsa param name array
+static const char* rsaParamNames[] = {"n", "e", "d", "p", "q", "dmp1", "dmq1", "iqmp"};
+
+// rsa get rsa param function list
+static const BIGNUM* (* GetRSAParamFunctionList[])(const RSA*) = {
+    RSA_get0_n,
+    RSA_get0_e,
+    RSA_get0_d,
+    RSA_get0_p,
+    RSA_get0_q,
+    RSA_get0_dmp1,
+    RSA_get0_dmq1,
+    RSA_get0_iqmp
+};
+
+/*
+ * New RSA and generate rsa key, follow the steps below
+ * step 1.New RSA
+ * step 2.Convert publicExponent to BIGNUM
+ * step 3.Generate rsa key, and all key information is stored in RSA
+ */
+static RSA* NewRSA(JNIEnv* env, jint keySize, jbyteArray publicExponent) {
+    ENGINE* kaeEngine = GetEngineByAlgorithmIndex(RSA_INDEX);
+    KAE_TRACE("NewRSA: kaeEngine => %p", kaeEngine);
+
+    // new rsa
+    RSA* rsa = RSA_new_method(kaeEngine);
+    if (rsa == NULL) {
+        KAE_ThrowFromOpenssl(env, "RSA_new_method", KAE_ThrowRuntimeException);
+        return NULL;
+    }
+
+    // convert publicExponent to BIGNUM
+    BIGNUM* exponent = KAE_GetBigNumFromByteArray(env, publicExponent);
+    if (exponent == NULL) {
+        return NULL;
+    }
+
+    // generate rsa key
+    int result_code = RSA_generate_key_ex(rsa, keySize, exponent, NULL);
+    KAE_ReleaseBigNumFromByteArray(exponent);
+    if (result_code <= 0) {
+        RSA_free(rsa);
+        KAE_ThrowFromOpenssl(env, "RSA_generate_key_ex", KAE_ThrowRuntimeException);
+        return NULL;
+    }
+    return rsa;
+}
+
+/*
+ * release RSA
+ */
+static void ReleaseRSA(RSA* rsa) {
+    if (rsa != NULL) {
+        RSA_free(rsa);
+    }
+}
+
+/*
+ * Set rsa key param, follow the steps below
+ * step 1. Get rsa param value
+ * step 2. Convert paramValue (BIGNUM) to jbyteArray
+ * step 3. Set the rsa param to the param array
+ */
+static bool SetRSAKeyParam(JNIEnv* env, RSA* rsa, jobjectArray params, RSAParamIndex rsaParamIndex) {
+    // get rsa param value
+    const BIGNUM* rsaParamValue = GetRSAParamFunctionList[rsaParamIndex](rsa);
+    if (rsaParamValue == NULL) {
+        return false;
+    }
+
+    // Convert paramValue to jbyteArray
+    jbyteArray param = KAE_GetByteArrayFromBigNum(env, rsaParamValue);
+    if (param == NULL) {
+        return false;
+    }
+
+    // Set the rsa param to the param array
+    (*env)->SetObjectArrayElement(env, params, rsaParamIndex, param);
+    return true;
+}
+
+/*
+ * New rsa key params, follow the steps below
+ * step 1. New rsa key param array
+ * step 2. Set rsa key param
+ */
+static jobjectArray NewRSAKeyParams(JNIEnv* env, RSA* rsa) {
+    // new param array
+    jclass byteArrayClass = (*env)->FindClass(env, "[B");
+    jobjectArray params = (*env)->NewObjectArray(env, KAE_RSA_PARAM_SIZE, byteArrayClass, NULL);
+    if (params == NULL) {
+        KAE_ThrowOOMException(env, "failed to allocate array");
+        return NULL;
+    }
+
+    // set rsa key param
+    RSAParamIndex paramIndex;
+    for (paramIndex = rsaN; paramIndex <= rsaIqmp; paramIndex++) {
+        if (!SetRSAKeyParam(env, rsa, params, paramIndex)) {
+            return NULL;
+        }
+    }
+    return params;
+}
+
+/*
+ * Class:     org_openeuler_security_openssl_KAERSAKeyPairGenerator
+ * Method:    nativeGenerateKeyPair
+ * Signature: (I[B)[[B
+ */
+JNIEXPORT jobjectArray JNICALL Java_org_openeuler_security_openssl_KAERSAKeyPairGenerator_nativeGenerateKeyPair (
+    JNIEnv* env, jclass cls, jint keySize, jbyteArray publicExponent) {
+    if (publicExponent == NULL) {
+        return NULL;
+    }
+
+    // new RSA
+    RSA* rsa = NewRSA(env, keySize, publicExponent);
+    if (rsa == NULL) {
+        return NULL;
+    }
+
+    // new RSA Key Parameters
+    jobjectArray rsaParm = NewRSAKeyParams(env, rsa);
+
+    // release rsa
+    ReleaseRSA(rsa);
+    return rsaParm;
+}
\ No newline at end of file
diff --git a/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_log.h b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_log.h
new file mode 100644
index 000000000..b618546c5
--- /dev/null
+++ b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_log.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef KAE_LOG_H
+#define KAE_LOG_H
+
+#ifdef KAE_DEBUG
+#define KAE_TRACE(...) { fprintf(stdout, __VA_ARGS__); fprintf(stdout, "\n"); }
+#else
+#define KAE_TRACE(...)
+#endif
+
+#endif
diff --git a/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_provider.c b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_provider.c
new file mode 100644
index 000000000..f4f71005a
--- /dev/null
+++ b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_provider.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <openssl/bio.h>
+#include <openssl/ssl.h>
+#include <openssl/engine.h>
+#include <dlfcn.h>
+#include "kae_exception.h"
+#include "kae_util.h"
+#include "org_openeuler_security_openssl_KAEProvider.h"
+
+#define KAE_OPENSSL_LIBRARY "libcrypto.so"
+
+/*
+ * Class:     Java_org_openeuler_security_openssl_KAEProvider
+ * Method:    initOpenssl
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_org_openeuler_security_openssl_KAEProvider_initOpenssl
+        (JNIEnv *env, jclass cls, jboolean useGlobalMode, jstring engineId, jbooleanArray algorithmKaeFlags) {
+    SSL_load_error_strings();
+    ERR_load_BIO_strings();
+    OpenSSL_add_all_algorithms();
+
+    /*
+     * If the same shared object is opened again with dlopen(), the same object handle is returned.
+     * The dynamic linker maintains reference counts for object handles.
+     * An object that was previously opened with RTLD_LOCAL can be promoted to RTLD_GLOBAL in a subsequent dlopen().
+     *
+     * RTLD_GLOBAL
+	 *     The symbols defined by this shared object will be made
+	 *     available for symbol resolution of subsequently loaded
+	 *     shared objects.
+     * RTLD_LOCAL
+	 *     This is the converse of RTLD_GLOBAL, and the default if
+	 *     neither flag is specified.  Symbols defined in this shared
+	 *     object are not made available to resolve references in
+	 *     subsequently loaded shared objects.
+     * For more information see https://man7.org/linux/man-pages/man3/dlopen.3.html.
+     */
+    if (useGlobalMode) {
+        char msg[1024];
+        void *handle = NULL;
+        // Promote the flags of the loaded libcrypto.so library from RTLD_LOCAL to RTLD_GLOBAL
+        handle = dlopen(KAE_OPENSSL_LIBRARY, RTLD_LAZY | RTLD_GLOBAL);
+        if (handle == NULL) {
+            snprintf(msg, sizeof(msg), "Cannot load %s (%s)!", KAE_OPENSSL_LIBRARY,  dlerror());
+            KAE_ThrowByName(env, "java/lang/UnsatisfiedLinkError", msg);
+            return;
+        }
+        dlclose(handle);
+    }
+
+    // check if KaeEngine holder is already set
+    ENGINE* e = GetKaeEngine();
+    if (e != NULL) {
+        ENGINE_free(e);
+        e = NULL;
+    }
+
+    // determine whether KAE is loaded successfully
+    const char* id = (*env)->GetStringUTFChars(env, engineId, 0);
+    e = ENGINE_by_id(id);
+    (*env)->ReleaseStringUTFChars(env, engineId, id);
+    if (e == NULL) {
+        KAE_ThrowFromOpenssl(env, "ENGINE_by_id", KAE_ThrowRuntimeException);
+        return;
+    }
+    SetKaeEngine(e);
+
+    // initialize the engine for each algorithm
+    initEngines(env, algorithmKaeFlags);
+}
+
+/*
+ * Class:     Java_org_openeuler_security_openssl_KAEProvider
+ * Method:    getEngineFlags
+ * Signature: ()V
+ */
+JNIEXPORT jbooleanArray JNICALL Java_org_openeuler_security_openssl_KAEProvider_getEngineFlags
+        (JNIEnv *env, jclass cls) {
+    return getEngineFlags(env);
+}
\ No newline at end of file
diff --git a/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_signature_rsa.c b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_signature_rsa.c
new file mode 100644
index 000000000..496ebc775
--- /dev/null
+++ b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_signature_rsa.c
@@ -0,0 +1,366 @@
+/*
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+#include <stdbool.h>
+#include <string.h>
+#include <openssl/rsa.h>
+#include <openssl/evp.h>
+#include "kae_log.h"
+#include "kae_util.h"
+#include "kae_exception.h"
+
+// get EVP_MD by digestName
+static const EVP_MD* getEvpMd(JNIEnv* env, jstring digestName) {
+    const char* digestNameUtf = (*env)->GetStringUTFChars(env, digestName, 0);
+    const EVP_MD* md = (EVP_MD*)EVP_get_digestbyname(digestNameUtf);
+    (*env)->ReleaseStringUTFChars(env, digestName, digestNameUtf);
+    if (md == NULL) {
+        KAE_ThrowSignatureException(env, "Unsupported digest algorithm.");
+    }
+    return md;
+}
+
+// sign release
+static void signRelease(JNIEnv* env, jbyteArray digestValue, jbyte* digestBytes, jbyte* sigBytes,
+    EVP_PKEY_CTX* pkeyCtx) {
+    if (digestBytes != NULL) {
+        (*env)->ReleaseByteArrayElements(env, digestValue, digestBytes, 0);
+    }
+    if (sigBytes != NULL) {
+        free(sigBytes);
+    }
+    if (pkeyCtx != NULL) {
+        EVP_PKEY_CTX_free(pkeyCtx);
+    }
+}
+
+// verify release
+static void verifyRelease(JNIEnv* env, jbyteArray digestValue, jbyte* digestBytes, jbyteArray sigValue, jbyte* sigBytes,
+    EVP_PKEY_CTX* pkeyCtx) {
+    if (digestBytes != NULL) {
+        (*env)->ReleaseByteArrayElements(env, digestValue, digestBytes, 0);
+    }
+    if (sigBytes != NULL) {
+        (*env)->ReleaseByteArrayElements(env, sigValue, sigBytes, 0);
+    }
+    if (pkeyCtx != NULL) {
+        EVP_PKEY_CTX_free(pkeyCtx);
+    }
+}
+
+// set rsa PkeyCtx parameters
+static bool setRsaPkeyCtxParameters(JNIEnv* env, EVP_PKEY_CTX* pkeyCtx, jint paddingType, jstring digestName) {
+    // set rsa padding
+    if (EVP_PKEY_CTX_set_rsa_padding(pkeyCtx, paddingType) <= 0) {
+        KAE_ThrowFromOpenssl(env, "EVP_PKEY_CTX_set_rsa_padding", KAE_ThrowSignatureException);
+        return false;
+    }
+
+    // set signature md
+    const EVP_MD* md = getEvpMd(env, digestName);
+    if (md == NULL) {
+        return false;
+    }
+
+    if (EVP_PKEY_CTX_set_signature_md(pkeyCtx, md) <= 0) {
+        KAE_ThrowFromOpenssl(env, "EVP_PKEY_CTX_set_signature_md", KAE_ThrowSignatureException);
+        return false;
+    }
+    return true;
+}
+
+/*
+ * Class:     org_openeuler_security_openssl_KAERSASignatureNative
+ * Method:    rsaSign
+ * Signature: (JLjava/lang/String;[BI)[B
+ */
+JNIEXPORT jbyteArray JNICALL Java_org_openeuler_security_openssl_KAERSASignatureNative_rsaSign(JNIEnv* env, jclass cls,
+    jlong keyAddress, jstring digestName, jbyteArray digestValue, jint paddingType) {
+    EVP_PKEY* pkey = (EVP_PKEY*)keyAddress;
+    EVP_PKEY_CTX* pkeyCtx = NULL;
+    jbyte* digestBytes = NULL;
+    jbyte* sigBytes = NULL;
+    jbyteArray sigByteArray = NULL;
+    static ENGINE* kaeEngine = NULL;
+    kaeEngine = (kaeEngine == NULL) ? GetKaeEngine() : kaeEngine;
+    // new EVP_PKEY_CTX
+    if ((pkeyCtx = EVP_PKEY_CTX_new(pkey, kaeEngine)) == NULL) {
+        KAE_ThrowFromOpenssl(env, "EVP_PKEY_new", KAE_ThrowSignatureException);
+        goto cleanup;
+    }
+
+    // sign init
+    if (EVP_PKEY_sign_init(pkeyCtx) <= 0) {
+        KAE_ThrowFromOpenssl(env, "EVP_PKEY_sign_init", KAE_ThrowSignatureException);
+        goto cleanup;
+    }
+
+    // set rsa PkeyCtx parameters
+    if (!setRsaPkeyCtxParameters(env, pkeyCtx, paddingType, digestName)) {
+        goto cleanup;
+    }
+
+    // sign
+    size_t sigLen = (size_t)EVP_PKEY_size(pkey);
+    if (sigLen <= 0) {
+        KAE_ThrowSignatureException(env, "The sigLen size cannot be zero or negative");
+        goto cleanup;
+    }
+    if ((sigBytes = malloc(sigLen)) == NULL) {
+        KAE_ThrowOOMException(env, "malloc failed");
+        goto cleanup;
+    }
+    if ((digestBytes = (*env)->GetByteArrayElements(env, digestValue, NULL)) == NULL) {
+        KAE_ThrowOOMException(env, "GetByteArrayElements failed");
+        goto cleanup;
+    }
+    size_t digestLen = (size_t)(*env)->GetArrayLength(env, digestValue);
+    if (EVP_PKEY_sign(pkeyCtx, (unsigned char*)sigBytes, &sigLen,
+                      (const unsigned char*)digestBytes, digestLen) <= 0) {
+        KAE_ThrowFromOpenssl(env, "EVP_PKEY_sign", KAE_ThrowSignatureException);
+        goto cleanup;
+    }
+
+    // set signature byte to jbyteArray
+    if ((sigByteArray = (*env)->NewByteArray(env, (jsize)sigLen)) == NULL) {
+        KAE_ThrowOOMException(env, "NewByteArray failed");
+        goto cleanup;
+    }
+    (*env)->SetByteArrayRegion(env, sigByteArray, 0, (jsize)sigLen, sigBytes);
+
+cleanup:
+    signRelease(env, digestValue, digestBytes, sigBytes, pkeyCtx);
+    return sigByteArray;
+}
+
+/*
+ * Class:     org_openeuler_security_openssl_KAERSASignatureNative
+ * Method:    rsaVerify
+ * Signature: (JLjava/lang/String;[BI[B)Z
+ */
+JNIEXPORT jboolean JNICALL Java_org_openeuler_security_openssl_KAERSASignatureNative_rsaVerify(JNIEnv* env, jclass cls,
+    jlong keyAddress, jstring digestName, jbyteArray digestValue, jint paddingType, jbyteArray sigValue) {
+    EVP_PKEY* pkey = (EVP_PKEY*)keyAddress;
+    EVP_PKEY_CTX* pkeyCtx = NULL;
+    jbyte* digestBytes = NULL;
+    jbyte* sigBytes = NULL;
+    jboolean isSuccess = JNI_FALSE;
+    static ENGINE* kaeEngine = NULL;
+    kaeEngine = (kaeEngine == NULL) ? GetKaeEngine() : kaeEngine;
+    // new EVP_PKEY_CTX
+    if ((pkeyCtx = EVP_PKEY_CTX_new(pkey, kaeEngine)) == NULL) {
+        KAE_ThrowFromOpenssl(env, "EVP_PKEY_new", KAE_ThrowSignatureException);
+        goto cleanup;
+    }
+
+    // verify init
+    if (EVP_PKEY_verify_init(pkeyCtx) <= 0) {
+        KAE_ThrowFromOpenssl(env, "EVP_PKEY_sign_init", KAE_ThrowSignatureException);
+        goto cleanup;
+    }
+
+    // set rsa PkeyCtx parameters
+    if (!setRsaPkeyCtxParameters(env, pkeyCtx, paddingType, digestName)) {
+        goto cleanup;
+    }
+
+    // verify
+    if ((digestBytes = (*env)->GetByteArrayElements(env, digestValue, NULL)) == NULL) {
+        KAE_ThrowOOMException(env, "GetByteArrayElements failed");
+        goto cleanup;
+    }
+    if ((sigBytes = (*env)->GetByteArrayElements(env, sigValue, NULL)) == NULL) {
+        KAE_ThrowOOMException(env, "GetByteArrayElements failed");
+        goto cleanup;
+    }
+    size_t sigLen = (size_t)(*env)->GetArrayLength(env, sigValue);
+    size_t digestLen = (size_t)(*env)->GetArrayLength(env, digestValue);
+    if (EVP_PKEY_verify(pkeyCtx, (const unsigned char*)sigBytes, sigLen,
+                        (const unsigned char*)digestBytes, digestLen) <= 0) {
+        KAE_ThrowFromOpenssl(env, "EVP_PKEY_verify", KAE_ThrowSignatureException);
+        goto cleanup;
+    }
+    isSuccess = JNI_TRUE;
+
+cleanup:
+    verifyRelease(env, digestValue, digestBytes, sigValue, sigBytes, pkeyCtx);
+    return isSuccess;
+}
+
+// set pss pkeyCtx parameters
+static bool setPssPkeyCtxParameters(JNIEnv* env, EVP_PKEY_CTX* pkeyCtx, jint paddingType, jstring digestName,
+    jstring mgf1DigestName, jint saltLen) {
+    // set rsa padding
+    if (EVP_PKEY_CTX_set_rsa_padding(pkeyCtx, paddingType) <= 0) {
+        KAE_ThrowFromOpenssl(env, "EVP_PKEY_CTX_set_rsa_padding", KAE_ThrowSignatureException);
+        return false;
+    }
+
+    // set signature md
+    const EVP_MD* md = getEvpMd(env, digestName);
+    if (md == NULL) {
+        return false;
+    }
+    if (EVP_PKEY_CTX_set_signature_md(pkeyCtx, md) <= 0) {
+        KAE_ThrowFromOpenssl(env, "EVP_PKEY_CTX_set_signature_md", KAE_ThrowSignatureException);
+        return false;
+    }
+
+    // set rsa mgf1 md
+    const EVP_MD* mgf1Md = getEvpMd(env, mgf1DigestName);
+    if (mgf1Md == NULL) {
+        return false;
+    }
+    if (EVP_PKEY_CTX_set_rsa_mgf1_md(pkeyCtx, mgf1Md) <= 0) {
+        KAE_ThrowFromOpenssl(env, "EVP_PKEY_CTX_set_rsa_mgf1_md", KAE_ThrowSignatureException);
+        return false;
+    }
+
+    // set salt len
+    if (EVP_PKEY_CTX_set_rsa_pss_saltlen(pkeyCtx, saltLen) <= 0) {
+        KAE_ThrowFromOpenssl(env, "EVP_PKEY_CTX_set_rsa_pss_saltlen", KAE_ThrowSignatureException);
+        return false;
+    }
+    return true;
+}
+
+/*
+ * Class:     org_openeuler_security_openssl_KAERSASignatureNative
+ * Method:    pssSign
+ * Signature: (JLjava/lang/String;[BILjava/lang/String;I)[B
+ */
+JNIEXPORT jbyteArray JNICALL Java_org_openeuler_security_openssl_KAERSASignatureNative_pssSign(JNIEnv* env, jclass cls,
+    jlong keyAddress, jstring digestName, jbyteArray digestValue, jint paddingType, jstring mgf1DigestName,
+    jint saltLen) {
+    EVP_PKEY* pkey = (EVP_PKEY*)keyAddress;
+    EVP_PKEY_CTX* pkeyCtx = NULL;
+    jbyte* digestBytes = NULL;
+    jbyte* sigBytes = NULL;
+    jbyteArray sigByteArray = NULL;
+    ENGINE* kaeEngine = GetEngineByAlgorithmIndex(RSA_INDEX);
+    KAE_TRACE("KAERSASignatureNative_pssSign: kaeEngine => %p", kaeEngine);
+
+    // new EVP_PKEY_CTX
+    if ((pkeyCtx = EVP_PKEY_CTX_new(pkey, kaeEngine)) == NULL) {
+        KAE_ThrowFromOpenssl(env, "EVP_PKEY_new", KAE_ThrowSignatureException);
+        goto cleanup;
+    }
+
+    // sign init
+    if (EVP_PKEY_sign_init(pkeyCtx) <= 0) {
+        KAE_ThrowFromOpenssl(env, "EVP_PKEY_sign_init", KAE_ThrowSignatureException);
+        goto cleanup;
+    }
+
+    // set pss pkeyCtx parameters
+    if (!setPssPkeyCtxParameters(env, pkeyCtx, paddingType, digestName, mgf1DigestName, saltLen)) {
+        goto cleanup;
+    }
+
+    // sign
+    size_t sigLen = (size_t)EVP_PKEY_size(pkey);
+    if (sigLen <= 0) {
+        KAE_ThrowSignatureException(env, "The sigLen size cannot be zero or negative");
+        goto cleanup;
+    }
+    if ((sigBytes = malloc(sigLen)) == NULL) {
+        KAE_ThrowOOMException(env, "malloc failed");
+        goto cleanup;
+    }
+    if ((digestBytes = (*env)->GetByteArrayElements(env, digestValue, NULL)) == NULL) {
+        KAE_ThrowOOMException(env, "GetByteArrayElements failed");
+        goto cleanup;
+    }
+    size_t digestLen = (size_t)(*env)->GetArrayLength(env, digestValue);
+    if (EVP_PKEY_sign(pkeyCtx, (unsigned char*)sigBytes, &sigLen,
+                      (const unsigned char*)digestBytes, digestLen) <= 0) {
+        KAE_ThrowFromOpenssl(env, "EVP_PKEY_sign", KAE_ThrowSignatureException);
+        goto cleanup;
+    }
+
+    // set signature byte to jbyteArray
+    if ((sigByteArray = (*env)->NewByteArray(env, (jsize)sigLen)) == NULL) {
+        KAE_ThrowOOMException(env, "NewByteArray failed");
+        goto cleanup;
+    }
+    (*env)->SetByteArrayRegion(env, sigByteArray, 0, (jsize)sigLen, sigBytes);
+
+cleanup:
+    signRelease(env, digestValue, digestBytes, sigBytes, pkeyCtx);
+    return sigByteArray;
+}
+
+/*
+ * Class:     org_openeuler_security_openssl_KAERSASignatureNative
+ * Method:    pssVerify
+ * Signature: (JLjava/lang/String;[BILjava/lang/String;I[B)Z
+ */
+JNIEXPORT jboolean JNICALL Java_org_openeuler_security_openssl_KAERSASignatureNative_pssVerify(JNIEnv* env, jclass cls,
+    jlong keyAddress, jstring digestName, jbyteArray digestValue, jint paddingType, jstring mgf1DigestName,
+    jint saltLen, jbyteArray sigValue) {
+    EVP_PKEY* pkey = (EVP_PKEY*)keyAddress;
+    EVP_PKEY_CTX* pkeyCtx = NULL;
+    jbyte* digestBytes = NULL;
+    jbyte* sigBytes = NULL;
+    jboolean isSuccess = JNI_FALSE;
+    ENGINE* kaeEngine = GetEngineByAlgorithmIndex(RSA_INDEX);
+    KAE_TRACE("KAERSASignatureNative_pssVerify: kaeEngine => %p", kaeEngine);
+
+    // new EVP_PKEY_CTX
+    if ((pkeyCtx = EVP_PKEY_CTX_new(pkey, kaeEngine)) == NULL) {
+        KAE_ThrowFromOpenssl(env, "EVP_PKEY_new", KAE_ThrowSignatureException);
+        goto cleanup;
+    }
+
+    // verify init
+    if (EVP_PKEY_verify_init(pkeyCtx) <= 0) {
+        KAE_ThrowFromOpenssl(env, "EVP_PKEY_sign_init", KAE_ThrowSignatureException);
+        goto cleanup;
+    }
+
+    // set pkeyCtx parameters
+    if (!setPssPkeyCtxParameters(env, pkeyCtx, paddingType, digestName, mgf1DigestName, saltLen)) {
+        goto cleanup;
+    }
+
+    // verify
+    if ((digestBytes = (*env)->GetByteArrayElements(env, digestValue, NULL)) == NULL) {
+        KAE_ThrowOOMException(env, "GetByteArrayElements failed");
+        goto cleanup;
+    }
+    if ((sigBytes = (*env)->GetByteArrayElements(env, sigValue, NULL)) == NULL) {
+        KAE_ThrowOOMException(env, "GetByteArrayElements failed");
+        goto cleanup;
+    }
+    size_t sigLen = (size_t)(*env)->GetArrayLength(env, sigValue);
+    size_t digestLen = (size_t)(*env)->GetArrayLength(env, digestValue);
+    if (EVP_PKEY_verify(pkeyCtx, (const unsigned char*)sigBytes, sigLen,
+                        (const unsigned char*)digestBytes, digestLen) <= 0) {
+        KAE_ThrowFromOpenssl(env, "EVP_PKEY_verify", KAE_ThrowSignatureException);
+        goto cleanup;
+    }
+    isSuccess = JNI_TRUE;
+
+cleanup:
+    verifyRelease(env, digestValue, digestBytes, sigValue, sigBytes, pkeyCtx);
+    return isSuccess;
+}
\ No newline at end of file
diff --git a/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_symmetric_cipher.c b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_symmetric_cipher.c
new file mode 100644
index 000000000..67151f53a
--- /dev/null
+++ b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_symmetric_cipher.c
@@ -0,0 +1,415 @@
+/*
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <memory.h>
+#include <stdbool.h>
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include <string.h>
+#include "kae_exception.h"
+#include "kae_log.h"
+#include "kae_util.h"
+#include "org_openeuler_security_openssl_KAESymmetricCipherBase.h"
+
+bool StartsWith(const char* str1, const char* str2)
+{
+    if (str1 == NULL || str2 == NULL) {
+        return 0;
+    }
+    int len1 = strlen(str1);
+    int len2 = strlen(str2);
+    if (len1 > len2 || (len1 == 0 || len2 == 0)) {
+        return false;
+    }
+    const char *cur = str1;
+    int i = 0;
+    while (*cur != '\0') {
+        if (*cur != str2[i]) {
+            return 0;
+        }
+        cur++;
+        i++;
+    }
+    return true;
+}
+
+static const EVP_CIPHER* EVPGetSm4CipherByName(JNIEnv* env, const char* algo)
+{
+    static const EVP_CIPHER* sm4Ecb = NULL;
+    static const EVP_CIPHER* sm4Cbc = NULL;
+    static const EVP_CIPHER* sm4Ctr = NULL;
+    static const EVP_CIPHER* sm4Ofb = NULL;
+
+    if (strcasecmp(algo, "sm4-ecb") == 0) {
+        return sm4Ecb == NULL ? sm4Ecb = EVP_get_cipherbyname(algo) : sm4Ecb;
+    } else if (strcasecmp(algo, "sm4-cbc") == 0) {
+        return sm4Cbc == NULL ? sm4Cbc = EVP_get_cipherbyname(algo) : sm4Cbc;
+    } else if (strcasecmp(algo, "sm4-ctr") == 0) {
+        return sm4Ctr == NULL ? sm4Ctr = EVP_get_cipherbyname(algo) : sm4Ctr;
+    } else if (strcasecmp(algo, "sm4-ofb") == 0) {
+        return sm4Ofb == NULL ? sm4Ofb = EVP_get_cipherbyname(algo) : sm4Ofb;
+    } else {
+        KAE_ThrowRuntimeException(env, "EVPGetSm4CipherByName error");
+        return 0;
+    }
+}
+
+static const EVP_CIPHER* EVPGetAesCipherByName(JNIEnv* env, const char* algo)
+{
+    static const EVP_CIPHER* aes128Ecb = NULL;
+    static const EVP_CIPHER* aes128Cbc = NULL;
+    static const EVP_CIPHER* aes128Ctr = NULL;
+    static const EVP_CIPHER* aes128Gcm = NULL;
+    static const EVP_CIPHER* aes192Ecb = NULL;
+    static const EVP_CIPHER* aes192Cbc = NULL;
+    static const EVP_CIPHER* aes192Ctr = NULL;
+    static const EVP_CIPHER* aes192Gcm = NULL;
+    static const EVP_CIPHER* aes256Ecb = NULL;
+    static const EVP_CIPHER* aes256Cbc = NULL;
+    static const EVP_CIPHER* aes256Ctr = NULL;
+    static const EVP_CIPHER* aes256Gcm = NULL;
+
+    if (strcasecmp(algo, "aes-128-ecb") == 0) {
+        return aes128Ecb == NULL ? aes128Ecb = EVP_get_cipherbyname(algo) : aes128Ecb;
+    } else if (strcasecmp(algo, "aes-128-cbc") == 0) {
+        return aes128Cbc == NULL ? aes128Cbc = EVP_get_cipherbyname(algo) : aes128Cbc;
+    } else if (strcasecmp(algo, "aes-128-ctr") == 0) {
+        return aes128Ctr == NULL ? aes128Ctr = EVP_get_cipherbyname(algo) : aes128Ctr;
+    } else if (strcasecmp(algo, "aes-128-gcm") == 0) {
+        return aes128Gcm == NULL ? aes128Gcm = EVP_get_cipherbyname(algo) : aes128Gcm;
+    } else if (strcasecmp(algo, "aes-192-ecb") == 0) {
+        return aes192Ecb == NULL ? aes192Ecb = EVP_get_cipherbyname(algo) : aes192Ecb;
+    } else if (strcasecmp(algo, "aes-192-cbc") == 0) {
+        return aes192Cbc == NULL ? aes192Cbc = EVP_get_cipherbyname(algo) : aes192Cbc;
+    } else if (strcasecmp(algo, "aes-192-ctr") == 0) {
+        return aes192Ctr == NULL ? aes192Ctr = EVP_get_cipherbyname(algo) : aes192Ctr;
+    } else if (strcasecmp(algo, "aes-192-gcm") == 0) {
+        return aes192Gcm == NULL ? aes192Gcm = EVP_get_cipherbyname(algo) : aes192Gcm;
+    } else if (strcasecmp(algo, "aes-256-ecb") == 0) {
+        return aes256Ecb == NULL ? aes256Ecb = EVP_get_cipherbyname(algo) : aes256Ecb;
+    } else if (strcasecmp(algo, "aes-256-cbc") == 0) {
+        return aes256Cbc == NULL ? aes256Cbc = EVP_get_cipherbyname(algo) : aes256Cbc;
+    } else if (strcasecmp(algo, "aes-256-ctr") == 0) {
+        return aes256Ctr == NULL ? aes256Ctr = EVP_get_cipherbyname(algo) : aes256Ctr;
+    } else if (strcasecmp(algo, "aes-256-gcm") == 0) {
+        return aes256Gcm == NULL ? aes256Gcm = EVP_get_cipherbyname(algo) : aes256Gcm;
+    } else {
+        KAE_ThrowRuntimeException(env, "EVPGetAesCipherByName error");
+        return 0;
+    }
+}
+
+void FreeMemoryFromInit(JNIEnv* env, jbyteArray iv, jbyte* ivBytes, jbyteArray key, jbyte* keyBytes,
+    int keyLength)
+{
+    if (ivBytes != NULL) {
+        (*env)->ReleaseByteArrayElements(env, iv, ivBytes, 0);
+    }
+    if (keyBytes != NULL) {
+	    memset(keyBytes, 0, keyLength);
+        (*env)->ReleaseByteArrayElements(env, key, keyBytes, JNI_ABORT);
+    }
+}
+
+/*
+ * Class:     org_openeuler_security_openssl_KAESymmetricCipherBase
+ * Method:    nativeInit
+ * Signature: (Ljava/lang/String;Z[B[B)J
+ */
+JNIEXPORT jlong JNICALL
+Java_org_openeuler_security_openssl_KAESymmetricCipherBase_nativeInit(JNIEnv* env, jclass cls,
+    jstring cipherType, jboolean encrypt, jbyteArray key, jbyteArray iv, jboolean padding)
+{
+    EVP_CIPHER_CTX* ctx = NULL;
+    jbyte* keyBytes = NULL;
+    jbyte* ivBytes = NULL;
+    const EVP_CIPHER* cipher = NULL;
+    ENGINE* kaeEngine = NULL;
+    int keyLength = (*env)->GetArrayLength(env, key);
+
+    const char* algo = (*env)->GetStringUTFChars(env, cipherType, 0);
+    if (StartsWith("aes", algo)) {
+        cipher = EVPGetAesCipherByName(env, algo);
+        kaeEngine = GetAesEngineByAlgorithmName(algo);
+    } else {
+        cipher = EVPGetSm4CipherByName(env, algo);
+        kaeEngine = GetSm4EngineByAlgorithmName(algo);
+    }
+
+    KAE_TRACE("KAESymmetricCipherBase_nativeInit: kaeEngine => %p", kaeEngine);
+
+    (*env)->ReleaseStringUTFChars(env, cipherType, algo);
+    if (cipher == NULL) {
+        KAE_ThrowOOMException(env, "create EVP_CIPHER fail");
+        goto cleanup;
+    }
+    if ((ctx = EVP_CIPHER_CTX_new()) == NULL) {
+        KAE_ThrowOOMException(env, "create EVP_CIPHER_CTX fail");
+        goto cleanup;
+    }
+
+    if (iv != NULL) {
+        ivBytes = (*env)->GetByteArrayElements(env, iv, NULL);
+    }
+    if (key != NULL) {
+        keyBytes = (*env)->GetByteArrayElements(env, key, NULL);
+    }
+
+    if (!EVP_CipherInit_ex(ctx, cipher, kaeEngine, (const unsigned char*)keyBytes,
+                           (const unsigned char*)ivBytes, encrypt ? 1 : 0)) {
+        KAE_ThrowFromOpenssl(env, "EVP_CipherInit_ex failed", KAE_ThrowRuntimeException);
+        goto cleanup;
+    }
+
+    EVP_CIPHER_CTX_set_padding(ctx, padding ? 1 : 0);
+
+    FreeMemoryFromInit(env, iv, ivBytes, key, keyBytes, keyLength);
+    return (jlong)ctx;
+
+cleanup:
+    if (ctx != NULL) {
+        EVP_CIPHER_CTX_free(ctx);
+    }
+    FreeMemoryFromInit(env, iv, ivBytes, key, keyBytes, keyLength);
+    return 0;
+}
+
+static void FreeMemoryFromUpdate(unsigned char* in, unsigned char* aad, unsigned char* out)
+{
+    if (in != NULL) {
+        free(in);
+    }
+    if (out != NULL) {
+        free(out);
+    }
+    if (aad != NULL) {
+        free(aad);
+    }
+}
+
+/*
+ * Class:     org_openeuler_security_openssl_KAESymmetricCipherBase
+ * Method:    nativeUpdate
+ * Signature: (J[BII[BIZ[B)I
+ */
+JNIEXPORT jint JNICALL
+Java_org_openeuler_security_openssl_KAESymmetricCipherBase_nativeUpdate(JNIEnv* env, jclass cls, jlong ctxAddress,
+    jbyteArray inArr, jint inOfs, jint inLen, jbyteArray outArr, jint outOfs, jboolean gcm, jbyteArray gcmAAD)
+{
+    unsigned char* in = NULL;
+    unsigned char* aad = NULL;
+    unsigned char* out = NULL;
+
+    EVP_CIPHER_CTX* ctx = (EVP_CIPHER_CTX*)ctxAddress;
+    if (ctx == NULL || inArr == NULL || outArr == NULL) {
+        goto cleanup;
+    }
+
+    in = (unsigned char*)malloc(inLen);
+    int outLen = (*env)->GetArrayLength(env, outArr) - outOfs;
+    out = (unsigned char*)malloc(outLen);
+    if (in == NULL || out == NULL) {
+        KAE_ThrowOOMException(env, "malloc error");
+        goto cleanup;
+    }
+    memset(in, 0, inLen);
+    memset(out, 0, outLen);
+    (*env)->GetByteArrayRegion(env, inArr, inOfs, inLen, (jbyte*)in);
+
+    int bytesWritten = 0;
+    if (gcm && (gcmAAD != NULL)) {
+        int aadLen = (*env)->GetArrayLength(env, gcmAAD);
+        if ((aad = (unsigned char*)malloc(aadLen)) == NULL) {
+            KAE_ThrowOOMException(env, "malloc error");
+            goto cleanup;
+        }
+        memset(aad, 0, aadLen);
+        (*env)->GetByteArrayRegion(env, gcmAAD, 0, aadLen, (jbyte*)aad);
+
+        // Specify aad.
+        if (EVP_CipherUpdate(ctx, NULL, &bytesWritten, aad, aadLen) == 0) {
+            KAE_ThrowFromOpenssl(env, "EVP_CipherUpdate failed", KAE_ThrowRuntimeException);
+            goto cleanup;
+        }
+    }
+
+    if (EVP_CipherUpdate(ctx, out, &bytesWritten, in, inLen) == 0) {
+        KAE_ThrowFromOpenssl(env, "EVP_CipherUpdate failed", KAE_ThrowRuntimeException);
+        goto cleanup;
+    }
+    (*env)->SetByteArrayRegion(env, outArr, outOfs, bytesWritten, (jbyte*)out);
+
+    FreeMemoryFromUpdate(in, aad, out);
+    return bytesWritten;
+
+cleanup:
+    FreeMemoryFromUpdate(in, aad, out);
+    return 0;
+}
+
+/*
+ * Class:     org_openeuler_security_openssl_KAESymmetricCipherBase
+ * Method:    nativeFinal
+ * Signature: (JZ[BI)I
+ */
+JNIEXPORT jint JNICALL
+Java_org_openeuler_security_openssl_KAESymmetricCipherBase_nativeFinal(JNIEnv* env, jclass cls,
+    jlong ctxAddress, jbyteArray outArr, jint outOfs)
+{
+    unsigned char* out = NULL;
+    EVP_CIPHER_CTX* ctx = (EVP_CIPHER_CTX*)ctxAddress;
+    KAE_TRACE("KAESymmetricCipherBase_nativeFinal(ctxAddress = %p, outArr = %p, outOfs = %d)",
+              ctx, outArr, outOfs);
+    if (ctx == NULL || outArr == NULL) {
+        goto cleanup;
+    }
+    int outLen = (*env)->GetArrayLength(env, outArr) - outOfs;
+    out = (unsigned char*)malloc(outLen);
+    if (out == NULL) {
+        KAE_ThrowOOMException(env, "malloc error");
+        goto cleanup;
+    }
+    memset(out, 0, outLen);
+    int bytesWritten = 0;
+    int result_code = EVP_CipherFinal_ex(ctx, out, &bytesWritten);
+    if (result_code == 0) {
+        KAE_ThrowFromOpenssl(env, "EVP_CipherFinal_ex failed", KAE_ThrowBadPaddingException);
+        goto cleanup;
+    }
+    KAE_TRACE("KAESymmetricCipherBase_nativeFinal EVP_CipherFinal_ex success, bytesWritten = %d", bytesWritten);
+    (*env)->SetByteArrayRegion(env, outArr, outOfs, bytesWritten, (jbyte*)out);
+    free(out);
+    KAE_TRACE("KAESymmetricCipherBase_nativeFinal: finished");
+    return bytesWritten;
+
+cleanup:
+    if (out != NULL) {
+        free(out);
+    }
+    return 0;
+}
+
+static void FreeMemoryFromFinalGcm(unsigned char* out, unsigned char* gcmTag, unsigned char* gcmOut)
+{
+    if (out != NULL) {
+        free(out);
+    }
+    if (gcmTag != NULL) {
+        free(gcmTag);
+    }
+    if (gcmOut != NULL) {
+        free(gcmOut);
+    }
+}
+
+/*
+ * Class:     org_openeuler_security_openssl_KAECipherAES
+ * Method:    nativeFinalGcm
+ * Signature: (J[BIZI[BZ)I
+ */
+JNIEXPORT jint JNICALL Java_org_openeuler_security_openssl_KAESymmetricCipherBase_nativeFinalGcm(JNIEnv* env,
+        jclass cls, jlong ctxAddress, jbyteArray outArr, jint outOfs, jboolean gcm, jint tagLength,
+        jbyteArray gcmTagArr, jboolean encrypt)
+{
+    unsigned char* out = NULL;
+    unsigned char* gcmTag = NULL;
+    unsigned char* gcmOut = NULL;
+
+    EVP_CIPHER_CTX* ctx = (EVP_CIPHER_CTX*)ctxAddress;
+    if (ctx == NULL || outArr == NULL) {
+        goto cleanup;
+    }
+
+    int bytesWritten = 0;
+    if (encrypt) {
+        int outLen = (*env)->GetArrayLength(env, outArr) - outOfs;
+        if ((out = malloc(outLen)) == NULL) {
+            KAE_ThrowOOMException(env, "malloc error");
+            goto cleanup;
+        }
+        memset(out, 0, outLen);
+        if (EVP_CipherFinal_ex(ctx, out, &bytesWritten) == 0) {
+            KAE_ThrowFromOpenssl(env, "EVP_CipherFinal_ex failed", KAE_ThrowBadPaddingException);
+            goto cleanup;
+        }
+        (*env)->SetByteArrayRegion(env, outArr, outOfs, bytesWritten, (jbyte*)out);
+
+        // Writes tagLength bytes of the tag value to the buffer.
+        // Refer to {@link https://www.openssl.org/docs/man1.1.0/man3/EVP_CIPHER_CTX_ctrl.html} for details.
+        if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, tagLength, out + bytesWritten) == 0) {
+            KAE_ThrowFromOpenssl(env, "EVP_CIPHER_CTX_ctrl failed", KAE_ThrowRuntimeException);
+            goto cleanup;
+        }
+        (*env)->SetByteArrayRegion(env, outArr, outOfs + bytesWritten, tagLength, (jbyte*)(out + bytesWritten));
+        bytesWritten += tagLength;
+    } else {
+        // gcmOut is the plaintext that has been decrypted in the EVP_CipherUpdate.
+        // outOfs is the length of the gcmOut, where it's always > 0.
+        if ((gcmTag = (unsigned char*)malloc(tagLength)) == NULL || (gcmOut = (unsigned char*)malloc(outOfs)) == NULL) {
+            KAE_ThrowOOMException(env, "malloc error");
+            goto cleanup;
+        }
+        memset(gcmTag, 0, tagLength);
+        memset(gcmOut, 0, outOfs);
+
+        (*env)->GetByteArrayRegion(env, gcmTagArr, 0, tagLength, (jbyte*)gcmTag);
+        // Sets the expected gcmTag to tagLength bytes from gcmTag.
+        // Refer to {@link https://www.openssl.org/docs/man1.1.0/man3/EVP_CIPHER_CTX_ctrl.html} for details.
+        if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, tagLength, gcmTag) == 0) {
+            KAE_ThrowFromOpenssl(env, "EVP_CTRL_AEAD_SET_TAG failed", KAE_ThrowRuntimeException);
+            goto cleanup;
+        }
+
+        (*env)->GetByteArrayRegion(env, outArr, 0, outOfs, (jbyte*)gcmOut);
+        // Finalise: note get no output for GCM
+        if (EVP_CipherFinal_ex(ctx, gcmOut, &bytesWritten) == 0) {
+            KAE_ThrowFromOpenssl(env, "EVP_CipherFinal_ex failed", KAE_ThrowAEADBadTagException);
+            goto cleanup;
+        }
+    }
+    FreeMemoryFromFinalGcm(out, gcmTag, gcmOut);
+
+    return bytesWritten;
+
+cleanup:
+    FreeMemoryFromFinalGcm(out, gcmTag, gcmOut);
+    return 0;
+}
+
+/*
+ * Class:     org_openeuler_security_openssl_KAESymmetricCipherBase
+ * Method:    nativeFree
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL
+Java_org_openeuler_security_openssl_KAESymmetricCipherBase_nativeFree(JNIEnv* env, jclass cls, jlong ctxAddress)
+{
+    EVP_CIPHER_CTX* ctx = (EVP_CIPHER_CTX*)ctxAddress;
+    KAE_TRACE("KAESymmetricCipherBase_nativeFree(ctx = %p)", ctx);
+    if (ctx != NULL) {
+        EVP_CIPHER_CTX_free(ctx);
+        ctx = NULL;
+    }
+
+    KAE_TRACE("KAESymmetricCipherBase_nativeFree: finished");
+}
diff --git a/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_util.c b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_util.c
new file mode 100644
index 000000000..471ae834b
--- /dev/null
+++ b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_util.c
@@ -0,0 +1,246 @@
+/*
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <openssl/evp.h>
+#include <string.h>
+#include "kae_util.h"
+#include "kae_exception.h"
+
+static ENGINE* kaeEngine = NULL;
+
+void SetKaeEngine(ENGINE* engine) {
+    kaeEngine = engine;
+}
+
+ENGINE* GetKaeEngine() {
+    return kaeEngine;
+}
+
+BIGNUM* KAE_GetBigNumFromByteArray(JNIEnv* env, jbyteArray byteArray) {
+    if (byteArray == NULL) {
+        KAE_ThrowNullPointerException(env, "KAE_GetBigNumFromByteArray byteArray is null");
+        return NULL;
+    }
+
+    jsize len = (*env)->GetArrayLength(env, byteArray);
+    if (len == 0) {
+        KAE_ThrowRuntimeException(env, "KAE_GetBigNumFromByteArray byteArray is empty");
+        return NULL;
+    }
+
+    BIGNUM* bn = BN_new();
+    if (bn == NULL) {
+        KAE_ThrowFromOpenssl(env, "BN_new", KAE_ThrowRuntimeException);
+        return NULL;
+    }
+
+    jbyte* bytes = (*env)->GetByteArrayElements(env, byteArray, NULL);
+    if (bytes == NULL) {
+        KAE_ThrowNullPointerException(env,"GetByteArrayElements failed");
+        goto cleanup;
+    }
+    BIGNUM* result = BN_bin2bn((const unsigned char*) bytes, len, bn);
+    (*env)->ReleaseByteArrayElements(env, byteArray, bytes, 0);
+    if (result == NULL) {
+        KAE_ThrowFromOpenssl(env, "BN_bin2bn", KAE_ThrowRuntimeException);
+        goto cleanup;
+    }
+    return bn;
+
+cleanup:
+    BN_free(bn);
+    return NULL;
+}
+
+void KAE_ReleaseBigNumFromByteArray(BIGNUM* bn) {
+    if (bn != NULL) {
+        BN_free(bn);
+    }
+}
+
+jbyteArray KAE_GetByteArrayFromBigNum(JNIEnv* env, const BIGNUM* bn) {
+    if (bn == NULL) {
+        return NULL;
+    }
+    // bn size need plus 1,  for example 65535 , BN_num_bytes return 2
+    int bnSize = BN_num_bytes(bn);
+    if (bnSize <= 0) {
+        return NULL;
+    }
+    bnSize += 1;
+    jbyteArray javaBytes = (*env)->NewByteArray(env, bnSize);
+    if (javaBytes == NULL) {
+        KAE_ThrowOOMException(env, "New byte array failed.");
+        return NULL;
+    }
+    jbyte* bytes = (*env)->GetByteArrayElements(env, javaBytes, NULL);
+    if (bytes == NULL) {
+        KAE_ThrowNullPointerException(env,"GetByteArrayElements failed.");
+        return NULL;
+    }
+    unsigned char* tmp = (unsigned char*) bytes;
+    if (BN_bn2bin(bn, tmp + 1) <= 0) {
+        KAE_ThrowFromOpenssl(env, "BN_bn2bin", KAE_ThrowRuntimeException);
+        javaBytes = NULL;
+        goto cleanup;
+    }
+    (*env)->SetByteArrayRegion(env, javaBytes, 0, bnSize, bytes);
+
+cleanup:
+    (*env)->ReleaseByteArrayElements(env, javaBytes, bytes, 0);
+    return javaBytes;
+}
+
+#define ENGINE_LENGTH (EC_INDEX + 1)
+static ENGINE* engines[ENGINE_LENGTH] = {NULL};
+static jboolean engineFlags[ENGINE_LENGTH] = {JNI_FALSE};
+static KAEAlgorithm kaeAlgorithms[ENGINE_LENGTH] = {
+        {MD5_INDEX,         "md5"},
+        {SHA256_INDEX,      "sha256"},
+        {SHA384_INDEX,      "sha384"},
+        {SM3_INDEX,         "sm3"},
+        {AES_128_ECB_INDEX, "aes-128-ecb"},
+        {AES_128_CBC_INDEX, "aes-128-cbc"},
+        {AES_128_CTR_INDEX, "aes-128-ctr"},
+        {AES_128_GCM_INDEX, "aes-128-gcm"},
+        {AES_192_ECB_INDEX, "aes-192-ecb"},
+        {AES_192_CBC_INDEX, "aes-192-cbc"},
+        {AES_192_CTR_INDEX, "aes-192-ctr"},
+        {AES_192_GCM_INDEX, "aes-192-gcm"},
+        {AES_256_ECB_INDEX, "aes-256-ecb"},
+        {AES_256_CBC_INDEX, "aes-256-cbc"},
+        {AES_256_CTR_INDEX, "aes-256-ctr"},
+        {AES_256_GCM_INDEX, "aes-256-gcm"},
+        {SM4_ECB_INDEX,     "sm4-ecb"},
+        {SM4_CBC_INDEX,     "sm4-cbc"},
+        {SM4_CTR_INDEX,     "sm4-ctr"},
+        {SM4_OFB_INDEX,     "sm4-ofb"},
+        {HMAC_MD5_INDEX,    "hmac-md5"},
+        {HMAC_SHA1_INDEX,   "hmac-sha1"},
+        {HMAC_SHA224_INDEX, "hmac-sha224"},
+        {HMAC_SHA256_INDEX, "hmac-sha256"},
+        {HMAC_SHA384_INDEX, "hmac-sha384"},
+        {HMAC_SHA512_INDEX, "hmac-sha512"},
+        {RSA_INDEX,         "rsa"},
+        {DH_INDEX,          "dh"},
+        {EC_INDEX,          "ec"}
+};
+
+void initEngines(JNIEnv* env, jbooleanArray algorithmKaeFlags) {
+    if (algorithmKaeFlags == NULL) {
+        return;
+    }
+
+    // get jTemp
+    jboolean* jTemp = NULL;
+    int length = (*env)->GetArrayLength(env, algorithmKaeFlags);
+    jTemp = (jboolean*) malloc(length);
+    if (jTemp == NULL) {
+        KAE_ThrowOOMException(env, "initEngines GetArrayLength error");
+        return;
+    }
+    (*env)->GetBooleanArrayRegion(env, algorithmKaeFlags, 0, length, jTemp);
+
+    // assign engines
+    int minLen = length < ENGINE_LENGTH ? length : ENGINE_LENGTH;
+    int i;
+    for (i = 0; i < minLen; i++) {
+        if (jTemp[i]) {
+            engines[i] = kaeEngine;
+            engineFlags[i] = JNI_TRUE;
+        }
+    }
+    if (length < ENGINE_LENGTH) {
+        for (i = minLen; i < ENGINE_LENGTH; i++) {
+            engines[i] = kaeEngine;
+            engineFlags[i] = JNI_TRUE;
+        }
+    }
+
+    // free jTemp
+    if (jTemp != NULL) {
+        free(jTemp);
+    }
+}
+
+jbooleanArray getEngineFlags(JNIEnv* env) {
+    jbooleanArray array = (*env)->NewBooleanArray(env, ENGINE_LENGTH);
+    (*env)->SetBooleanArrayRegion(env, array, 0, ENGINE_LENGTH, engineFlags);
+    return array;
+}
+
+ENGINE* GetEngineByAlgorithmIndex(AlgorithmIndex algorithmIndex) {
+    return engines[algorithmIndex];
+}
+
+/*
+ * Get the engine used by the specified algorithm.
+ * @param beginIndex the beginning index, inclusive.
+ * @param endIndex the ending index, exclusive.
+ * @param algorithmName algorithm name
+ * @return engine
+ */
+ENGINE* GetEngineByBeginIndexAndEndIndex(int beginIndex, int endIndex,
+        const char* algorithmName) {
+    if (beginIndex < 0 || endIndex > ENGINE_LENGTH) {
+        return NULL;
+    }
+
+    int i;
+    for (i = beginIndex; i < endIndex; i++) {
+        if (strcasecmp(kaeAlgorithms[i].algorithmName, algorithmName) == 0) {
+            return engines[kaeAlgorithms[i].algorithmIndex];
+        }
+    }
+    return NULL;
+}
+
+ENGINE* GetHmacEngineByAlgorithmName(const char* algorithmName) {
+    char prefix[] = {"hmac-"};
+    int len = strlen(algorithmName);
+    int newLen = strlen(algorithmName) + strlen(prefix) + 1;
+    char* newAlgorithmName = NULL;
+    newAlgorithmName = malloc(newLen);
+    if (newAlgorithmName == NULL) {
+        return NULL;
+    }
+    strcpy(newAlgorithmName, prefix);
+    strcat(newAlgorithmName, algorithmName);
+    ENGINE* engine = GetEngineByBeginIndexAndEndIndex(HMAC_MD5_INDEX, HMAC_SHA512_INDEX + 1, newAlgorithmName);
+    if (newAlgorithmName != NULL) {
+        free(newAlgorithmName);
+    }
+    return engine;
+}
+
+ENGINE* GetDigestEngineByAlgorithmName(const char* algorithmName) {
+    return GetEngineByBeginIndexAndEndIndex(MD5_INDEX, SM3_INDEX + 1, algorithmName);
+}
+
+ENGINE* GetAesEngineByAlgorithmName(const char* algorithmName) {
+    return GetEngineByBeginIndexAndEndIndex(AES_128_ECB_INDEX, AES_256_GCM_INDEX + 1, algorithmName);
+}
+
+ENGINE* GetSm4EngineByAlgorithmName(const char* algorithmName) {
+    return GetEngineByBeginIndexAndEndIndex(SM4_ECB_INDEX, SM4_OFB_INDEX + 1, algorithmName);
+}
diff --git a/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_util.h b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_util.h
new file mode 100644
index 000000000..6eb980d62
--- /dev/null
+++ b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_util.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef KAE_UTIL_H
+#define KAE_UTIL_H
+
+#include <openssl/bn.h>
+#include <jni.h>
+
+typedef enum {
+    MD5_INDEX,
+    SHA256_INDEX,
+    SHA384_INDEX,
+    SM3_INDEX,
+    AES_128_ECB_INDEX,
+    AES_128_CBC_INDEX,
+    AES_128_CTR_INDEX,
+    AES_128_GCM_INDEX,
+    AES_192_ECB_INDEX,
+    AES_192_CBC_INDEX,
+    AES_192_CTR_INDEX,
+    AES_192_GCM_INDEX,
+    AES_256_ECB_INDEX,
+    AES_256_CBC_INDEX,
+    AES_256_CTR_INDEX,
+    AES_256_GCM_INDEX,
+    SM4_ECB_INDEX,
+    SM4_CBC_INDEX,
+    SM4_CTR_INDEX,
+    SM4_OFB_INDEX,
+    HMAC_MD5_INDEX,
+    HMAC_SHA1_INDEX,
+    HMAC_SHA224_INDEX,
+    HMAC_SHA256_INDEX,
+    HMAC_SHA384_INDEX,
+    HMAC_SHA512_INDEX,
+    RSA_INDEX,
+    DH_INDEX,
+    EC_INDEX
+} AlgorithmIndex;
+
+typedef struct {
+    AlgorithmIndex algorithmIndex;
+    const char* algorithmName;
+} KAEAlgorithm;
+
+/* jbyteArray convert to BIGNUM */
+BIGNUM* KAE_GetBigNumFromByteArray(JNIEnv* env, jbyteArray byteArray);
+
+/* release BIGNUM allocat from */
+void KAE_ReleaseBigNumFromByteArray(BIGNUM* bn);
+
+/* BIGNUM convert to jbyteArray */
+jbyteArray KAE_GetByteArrayFromBigNum(JNIEnv* env, const BIGNUM* bn);
+
+void SetKaeEngine(ENGINE* engine);
+
+ENGINE* GetKaeEngine();
+
+void initEngines(JNIEnv* env, jbooleanArray algorithmKaeFlags);
+
+jbooleanArray getEngineFlags(JNIEnv* env);
+
+ENGINE* GetEngineByAlgorithmIndex(AlgorithmIndex algorithmIndex);
+
+ENGINE* GetHmacEngineByAlgorithmName(const char* algorithmName);
+
+ENGINE* GetDigestEngineByAlgorithmName(const char* algorithmName);
+
+ENGINE* GetAesEngineByAlgorithmName(const char* algorithmName);
+
+ENGINE* GetSm4EngineByAlgorithmName(const char* algorithmName);
+
+#endif
diff --git a/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/openssl_ad.h b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/openssl_ad.h
new file mode 100644
index 000000000..f4b552137
--- /dev/null
+++ b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/openssl_ad.h
@@ -0,0 +1,10 @@
+#include <openssl/opensslv.h>
+#include <openssl/err.h>
+
+#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3
+
+// ERR_GET_FUNC() was removed since Openssl3
+#ifndef ERR_GET_FUNC
+#define ERR_GET_FUNC(e) (int)(((e) >> 12L) & 0xFFFL)
+#endif
+#endif
diff --git a/test/jdk/TEST.groups b/test/jdk/TEST.groups
index 386ea4160..338234faf 100644
--- a/test/jdk/TEST.groups
+++ b/test/jdk/TEST.groups
@@ -255,6 +255,9 @@ jdk_security = \
 jdk_security_infra = \
     security/infra/java/security/cert/CertPathValidator/certification
 
+jdk_kae_security = \
+    org/openeuler/security/openssl
+
 jdk_text = \
     java/text \
     sun/text
diff --git a/test/jdk/java/security/KeyAgreement/KeyAgreementTest.java b/test/jdk/java/security/KeyAgreement/KeyAgreementTest.java
index 1e5eb9680..398e3ea2a 100644
--- a/test/jdk/java/security/KeyAgreement/KeyAgreementTest.java
+++ b/test/jdk/java/security/KeyAgreement/KeyAgreementTest.java
@@ -39,6 +39,7 @@ import java.security.KeyPairGenerator;
 import java.security.spec.NamedParameterSpec;
 import java.security.spec.AlgorithmParameterSpec;
 import java.security.spec.ECGenParameterSpec;
+import java.security.Security;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
@@ -53,7 +54,13 @@ public class KeyAgreementTest {
         String kpgAlgo = args[1];
         String provider = System.getProperty("test.provider.name", args[2]);
         System.out.println("Testing " + kaAlgo);
-        AlgoSpec aSpec = AlgoSpec.valueOf(AlgoSpec.class, kaAlgo);
+        AlgoSpec aSpec;
+        if (Security.getProperty("security.provider.1").equals("KAEProvider") &&
+            kaAlgo.equals("ECDH")) {
+            aSpec = AlgoSpec.valueOf(AlgoSpec.class, "KAEECDH");
+        } else {
+            aSpec = AlgoSpec.valueOf(AlgoSpec.class, kaAlgo);
+        }
         List<AlgorithmParameterSpec> specs = aSpec.getAlgorithmParameterSpecs();
         for (AlgorithmParameterSpec spec : specs) {
             testKeyAgreement(provider, kaAlgo, kpgAlgo, spec);
@@ -70,6 +77,7 @@ public class KeyAgreementTest {
         // "java.base/share/classes/sun/security/util/CurveDB.java"
 
         ECDH("secp256r1", "secp384r1", "secp521r1"),
+        KAEECDH("secp224r1", "secp256r1", "secp384r1", "secp521r1"),
         XDH("X25519", "X448", "x25519"),
         // There is no curve for DiffieHellman
         DiffieHellman(new String[]{});
@@ -81,6 +89,7 @@ public class KeyAgreementTest {
             for (String crv : curves) {
                 switch (this.name()) {
                     case "ECDH":
+                    case "KAEECDH":
                         specs.add(new ECGenParameterSpec(crv));
                         break;
                     case "XDH":
diff --git a/test/jdk/java/security/Signature/SignatureGetInstance.java b/test/jdk/java/security/Signature/SignatureGetInstance.java
index 821c20602..536c3ba67 100644
--- a/test/jdk/java/security/Signature/SignatureGetInstance.java
+++ b/test/jdk/java/security/Signature/SignatureGetInstance.java
@@ -54,9 +54,13 @@ public class SignatureGetInstance {
         MyPrivKey testPriv = new MyPrivKey();
         MyPubKey testPub = new MyPubKey();
 
+        Provider kaeProvider = Security.getProvider("KAEProvider");
+	String expectedProvName = kaeProvider != null ? "KAEProvider" : "SunRsaSign";
+
+
         testDblInit(testPriv, testPub, true, "TestProvider");
         testDblInit(kp.getPrivate(), kp.getPublic(), true,
-                        System.getProperty("test.provider.name", "SunRsaSign"));
+                        System.getProperty("test.provider.name", expectedProName));
         testDblInit(testPriv, kp.getPublic(), false, null);
         testDblInit(kp.getPrivate(), testPub, false, null);
 
diff --git a/test/jdk/org/openeuler/security/openssl/AESTest.java b/test/jdk/org/openeuler/security/openssl/AESTest.java
new file mode 100644
index 000000000..aac14568d
--- /dev/null
+++ b/test/jdk/org/openeuler/security/openssl/AESTest.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import org.openeuler.security.openssl.KAEProvider;
+
+import java.nio.charset.StandardCharsets;
+import java.security.Security;
+import java.security.spec.AlgorithmParameterSpec;
+import javax.crypto.Cipher;
+import javax.crypto.KeyGenerator;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.IvParameterSpec;
+
+/**
+ * @test
+ * @summary Basic test for AES
+ * @modules jdk.crypto.kaeprovider/org.openeuler.security.openssl
+ * @requires os.arch=="aarch64"
+ * @run main AESTest
+ */
+
+public class AESTest {
+    private static final String[] ALGORITHM = {"AES", "AES_128", "AES_192", "AES_256"};
+    private static final String[] MODES = {"ECB", "CBC", "CTR", "GCM"};
+    private static final String[] PADDING = {"NoPadding", "PKCS5Padding"};
+    private static final int AES_128_KEY_LENGTH = 128;
+    private static final int AES_192_KEY_LENGTH = 192;
+    private static final int AES_256_KEY_LENGTH = 256;
+    private static String plainText = "helloworldhellow"; // 16bytes for NoPadding
+    private static String shortPlainText = "helloworld"; // 5 bytes for padding
+
+    public static void main(String[] args) throws Exception {
+        Security.insertProviderAt(new KAEProvider(), 1);
+        for (String algo : ALGORITHM) {
+            for (String mode : MODES) {
+                int padKinds = 2;
+                if (mode.equalsIgnoreCase("CTR")) {
+                    padKinds = 1;
+                }
+                for (int k = 0; k < padKinds; k++) {
+                    test(algo, mode, PADDING[k]);
+                }
+            }
+        }
+    }
+
+    public static void test(String algo, String mo, String pad) throws Exception {
+        AlgorithmParameterSpec aps = null;
+
+        Cipher cipher = Cipher.getInstance(algo + "/" + mo + "/" + pad);
+
+        KeyGenerator kg = KeyGenerator.getInstance("AES");
+        if (algo.equalsIgnoreCase("AES_192")) {
+            kg.init(AES_192_KEY_LENGTH);
+        } else if (algo.equalsIgnoreCase("AES_256")) {
+            kg.init(AES_256_KEY_LENGTH);
+        } else {
+            kg.init(AES_128_KEY_LENGTH);
+        }
+
+        SecretKey key = kg.generateKey();
+
+        // encrypt
+        if (!mo.equalsIgnoreCase("GCM")) {
+            cipher.init(Cipher.ENCRYPT_MODE, key, aps);
+        } else {
+            cipher.init(Cipher.ENCRYPT_MODE, key);
+        }
+
+        String cipherString = null;
+        if (!pad.equalsIgnoreCase("NoPadding")) {
+            cipherString = shortPlainText;
+        } else {
+            cipherString = plainText;
+        }
+        byte[] cipherText = cipher.doFinal(cipherString.getBytes(StandardCharsets.UTF_8));
+        if (!mo.equalsIgnoreCase("ECB")) {
+            aps = new IvParameterSpec(cipher.getIV());
+        } else {
+            aps = null;
+        }
+
+        if (!mo.equalsIgnoreCase("GCM")) {
+            cipher.init(Cipher.DECRYPT_MODE, key, aps);
+        } else {
+            cipher.init(Cipher.DECRYPT_MODE, key, cipher.getParameters());
+        }
+
+        String decryptPlainText = new String(cipher.doFinal(cipherText));
+
+        if (!cipherString.equals(decryptPlainText)) {
+            throw new RuntimeException("aes decryption failed, algo = " + algo + ", mo = " + mo + ", pad = " + pad);
+        }
+    }
+}
diff --git a/test/jdk/org/openeuler/security/openssl/DHTest.java b/test/jdk/org/openeuler/security/openssl/DHTest.java
new file mode 100644
index 000000000..51dab7664
--- /dev/null
+++ b/test/jdk/org/openeuler/security/openssl/DHTest.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.Serializable;
+import java.math.BigInteger;
+import java.security.*;
+import java.util.Arrays;
+import javax.crypto.KeyAgreement;
+import javax.crypto.spec.*;
+import org.openeuler.security.openssl.KAEProvider;
+
+/**
+ * This class implements the Diffie-Hellman key exchange algorithm.
+ * D-H means combining your private key with your partners public key to
+ * generate a number. The peer does the same with its private key and our
+ * public key. Through the magic of Diffie-Hellman we both come up with the
+ * same number. This number is secret (discounting MITM attacks) and hence
+ * called the shared secret. It has the same length as the modulus, e.g. 512
+ * or 1024 bit. Man-in-the-middle attacks are typically countered by an
+ * independent authentication step using certificates (RSA, DSA, etc.).
+ *
+ * The thing to note is that the shared secret is constant for two partners
+ * with constant private keys. This is often not what we want, which is why
+ * it is generally a good idea to create a new private key for each session.
+ * Generating a private key involves one modular exponentiation assuming
+ * suitable D-H parameters are available.
+ *
+ * General usage of this class (TLS DHE case):
+ *  . if we are server, call DHCrypt(keyLength,random). This generates
+ *    an ephemeral keypair of the request length.
+ *  . if we are client, call DHCrypt(modulus, base, random). This
+ *    generates an ephemeral keypair using the parameters specified by
+ *    the server.
+ *  . send parameters and public value to remote peer
+ *  . receive peers ephemeral public key
+ *  . call getAgreedSecret() to calculate the shared secret
+ *
+ * In TLS the server chooses the parameter values itself, the client must use
+ * those sent to it by the server.
+ *
+ * The use of ephemeral keys as described above also achieves what is called
+ * "forward secrecy". This means that even if the authentication keys are
+ * broken at a later date, the shared secret remains secure. The session is
+ * compromised only if the authentication keys are already broken at the
+ * time the key exchange takes place and an active MITM attack is used.
+ * This is in contrast to straightforward encrypting RSA key exchanges.
+ *
+ */
+
+/**
+ * @test
+ * @summary Basic test for DH
+ * @modules jdk.crypto.kaeprovider/org.openeuler.security.openssl
+ * @requires os.arch=="aarch64"
+ * @run main DHTest
+ */
+
+public class DHTest implements Serializable {
+  private static BigInteger g512;
+  private static BigInteger p512;
+
+  private static volatile Provider sunJceProvider;
+  private static volatile Provider kaeProvider;
+
+  public static void main(String[] args) throws Exception {
+    Security.addProvider(new KAEProvider());
+    sunJceProvider = Security.getProvider("SunJCE");
+    kaeProvider = Security.getProvider("KAEProvider");
+
+    g512 = new BigInteger("30270326776012916323988175351831539351616124181011347910931933302640902603480679235129557617566480716138395926949700593986872757726720164601940036524221141391913433558162442022339559255078339658108149162251643458301671465579040759659507434340437396584664407572026953757806341363255195983514333141770938654900099033797866272818739547343977583089845850158637618703095710047154252655157633638171416516716598940884520592858762209135010804267830977334033327483815694794951984230264309784679409488441905236794443014066406150649287037909246107758452315504212879842042858577191624250834553614056794526338841821045329189780334");
+
+    p512 = new BigInteger("27672987386729926592037876826877634387173876890702920770064392919138769821035856568775311919542560094764667151024449425954917954337048895981297730855891532066350935045229294626339548842381843985759061682551900379979643117695834175891578650111093016914264824311693147701566019122696621248493126219217339690346346921463135605151471303957324058301097079967414639146647429422884520134312590056632178576758580657240245655739869017244657144448267757255018625514803292549109401806336918448001843022629625467069714240279603204909633404992842479161100500474744098408277938070656334892106100534117209709263785505019003765693651");
+
+    DHParameterSpec dhParams = new DHParameterSpec(p512, g512);
+    KeyPairGenerator SunJCEkeyGen = KeyPairGenerator.getInstance("DH", sunJceProvider);
+    KeyPairGenerator KAEkeyGen = KeyPairGenerator.getInstance("DH", kaeProvider);
+    SunJCEkeyGen.initialize(dhParams, new SecureRandom());
+    KAEkeyGen.initialize(dhParams, new SecureRandom());
+    KeyAgreement aKeyAgree = KeyAgreement.getInstance("DH", sunJceProvider);
+    KeyPair aPair = SunJCEkeyGen.generateKeyPair();
+    KeyAgreement bKeyAgree = KeyAgreement.getInstance("DH", kaeProvider);
+    KeyPair bPair = KAEkeyGen.generateKeyPair();
+
+    aKeyAgree.init(aPair.getPrivate());
+    bKeyAgree.init(bPair.getPrivate());
+
+    aKeyAgree.doPhase(bPair.getPublic(), true);
+    bKeyAgree.doPhase(aPair.getPublic(), true);
+
+    MessageDigest hash = MessageDigest.getInstance("MD5");
+    byte[] b1 = hash.digest(aKeyAgree.generateSecret());
+    byte[] b2 = hash.digest(bKeyAgree.generateSecret());
+    if(Arrays.equals(b1, b2)){
+      System.out.println("SUCCESS!");
+    }else{
+      System.out.println("Failed!");
+      throw new RuntimeException("Not Equal DH keyagreement ouput from SunJCE and KAE Provider!");
+    }
+  }
+}
\ No newline at end of file
diff --git a/test/jdk/org/openeuler/security/openssl/DigestTest.java b/test/jdk/org/openeuler/security/openssl/DigestTest.java
new file mode 100644
index 000000000..120b6ac47
--- /dev/null
+++ b/test/jdk/org/openeuler/security/openssl/DigestTest.java
@@ -0,0 +1,61 @@
+import org.openeuler.security.openssl.KAEProvider;
+
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.security.Security;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @test
+ * @summary Basic test for MD5 SHA256 SHA384
+ * @modules jdk.crypto.kaeprovider/org.openeuler.security.openssl
+ * @requires os.arch=="aarch64"
+ * @run main/othervm DigestTest
+ */
+public class DigestTest {
+    private static String PLAIN_TEXT = "hello world";
+
+    private static Map<String, byte[]> alg = new HashMap<String, byte[]>();
+
+    static {
+        alg.put("MD5", new byte[] {94, -74, 59, -69, -32, 30, -18, -48, -109, -53, 34, -69, -113, 90, -51, -61});
+        alg.put(
+                "SHA-256",
+                new byte[] {
+                        -71, 77, 39, -71, -109, 77, 62, 8, -91, 46, 82, -41, -38, 125, -85, -6,
+                        -60, -124, -17, -29, 122, 83, -128, -18, -112, -120, -9, -84, -30, -17, -51, -23
+                });
+        alg.put(
+                "SHA-384",
+                new byte[] {
+                        -3, -67, -114, 117, -90, 127, 41, -9, 1, -92, -32, 64, 56, 94, 46, 35,
+                        -104, 99, 3, -22, 16, 35, -110, 17, -81, -112, 127, -53, -72, 53, 120, -77,
+                        -28, 23, -53, 113, -50, 100, 110, -3, 8, 25, -35, -116, 8, -115, -31, -67
+                });
+        alg.put(
+                "SM3",
+                new byte[] {
+                        68, -16, 6, 30, 105, -6, 111, -33, -62, -112, -60, -108, 101, 74, 5,
+                        -36, 12, 5, 61, -89, -27, -59, 43, -124, -17, -109, -87, -42, 125, 63,
+                        -1, -120
+                });
+    }
+
+    public static void main(String[] args) throws Exception {
+        Security.insertProviderAt(new KAEProvider(), 1);
+        for (String key : alg.keySet()) {
+            test(PLAIN_TEXT, key, alg.get(key));
+        }
+    }
+
+    public static void test(String plainText, String algo, byte[] expectRes) throws Exception {
+        MessageDigest md = MessageDigest.getInstance(algo);
+        md.update(plainText.getBytes(StandardCharsets.UTF_8));
+        byte[] res = md.digest();
+        if (!Arrays.equals(res, expectRes)) {
+            throw new RuntimeException(algo + " failed");
+        }
+    }
+}
diff --git a/test/jdk/org/openeuler/security/openssl/ECDHTest.java b/test/jdk/org/openeuler/security/openssl/ECDHTest.java
new file mode 100644
index 000000000..791fec252
--- /dev/null
+++ b/test/jdk/org/openeuler/security/openssl/ECDHTest.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import org.openeuler.security.openssl.KAEProvider;
+import sun.security.ec.ECPrivateKeyImpl;
+import sun.security.ec.ECPublicKeyImpl;
+
+import javax.crypto.KeyAgreement;
+import java.math.BigInteger;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.Provider;
+import java.security.Security;
+import java.security.spec.ECFieldFp;
+import java.security.spec.ECParameterSpec;
+import java.security.spec.ECPoint;
+import java.security.spec.EllipticCurve;
+import java.util.Arrays;
+import java.nio.charset.StandardCharsets;
+import java.security.spec.*;
+import java.security.KeyFactory;
+import java.security.interfaces.ECPrivateKey;
+import java.security.interfaces.ECPublicKey;
+
+/**
+ * @test
+ * @summary Basic test for ECDH
+ * @modules jdk.crypto.kaeprovider/org.openeuler.security.openssl
+ * @modules jdk.crypto.ec/sun.security.ec
+ * @requires os.arch=="aarch64"
+ * @run main ECDHTest
+ */
+
+public class ECDHTest {
+
+    private static KeyPairGenerator keyPairGenerator;
+    private static String algorithm = "EC";
+    private static int[] keyArr = {224, 256, 384, 521};
+
+    public static void main(String[] args) throws Exception {
+        Security.insertProviderAt(new KAEProvider(), 1);
+
+        BigInteger a = new BigInteger("26959946667150639794667015087019630673557916260026308143510066298878");
+        BigInteger b = new BigInteger("18958286285566608000408668544493926415504680968679321075787234672564");
+        BigInteger p = new BigInteger("26959946667150639794667015087019630673557916260026308143510066298881");
+        BigInteger x = new BigInteger("19277929113566293071110308034699488026831934219452440156649784352033");
+        BigInteger y = new BigInteger("19926808758034470970197974370888749184205991990603949537637343198772");
+        EllipticCurve CURVE = new EllipticCurve(new ECFieldFp(p), a, b);
+        ECPoint POINT = new ECPoint(x, y);
+        BigInteger ORDER = new BigInteger("26959946667150639794667015087019625940457807714424391721682722368061");
+        int COFACTOR = 1;
+        ECParameterSpec PARAMS = new ECParameterSpec(CURVE, POINT, ORDER, COFACTOR);
+
+        testKeyPairByParam(PARAMS);
+        for (int keySize : keyArr) {
+            testKeyPairByKeySize(keySize);
+        }
+
+        KeyFactory keyFactory = KeyFactory.getInstance("EC");
+        ECPrivateKeySpec privateKeySpec = new ECPrivateKeySpec(new BigInteger("20135071615800221517902437867016717688420688735490569283842831828983"), PARAMS);
+        ECPrivateKeyImpl ecPrivKey = (ECPrivateKeyImpl)keyFactory.generatePrivate(privateKeySpec);
+
+        ECPoint ecPoint = new ECPoint(new BigInteger("9490267631555585552004372465967099662885480699902812460349461311384"), new BigInteger("1974573604976093871117393045089050409882519645527397292712281520811"));
+        ECPublicKeySpec publicKeySpec = new ECPublicKeySpec(ecPoint,PARAMS);
+        ECPublicKeyImpl ecPublicKey = (ECPublicKeyImpl)keyFactory.generatePublic(publicKeySpec);
+        testKeyAgreement(ecPrivKey, ecPublicKey, new byte[]{-88, -65, 43, -84, 26, 43, 46, 106, 20, 39, -76, 30, -71, 72, -102, 120, 108, -92, -86, -14, -96, -42, 93, -40, -43, -25, 15, -62});
+    }
+
+    public static void testKeyPairByParam(ECParameterSpec PARAMS) throws Exception {
+        keyPairGenerator = KeyPairGenerator.getInstance(algorithm);
+        keyPairGenerator.initialize(PARAMS);
+        KeyPair keyPair = keyPairGenerator.generateKeyPair();
+        ECPrivateKeyImpl ecPrivKey = (ECPrivateKeyImpl) keyPair.getPrivate();
+        ECPublicKeyImpl ecPublicKey = (ECPublicKeyImpl) keyPair.getPublic();
+    }
+
+    public static void testKeyPairByKeySize(int keySize) throws Exception {
+        keyPairGenerator = KeyPairGenerator.getInstance(algorithm);
+        keyPairGenerator.initialize(keySize);
+        KeyPair keyPair = keyPairGenerator.generateKeyPair();
+        ECPrivateKeyImpl ecPrivKey = (ECPrivateKeyImpl) keyPair.getPrivate();
+        ECPublicKeyImpl ecPublicKey = (ECPublicKeyImpl) keyPair.getPublic();
+    }
+
+    public static void testKeyAgreement(ECPrivateKeyImpl ecPrivKey, ECPublicKeyImpl ecPublicKey, byte[] expectRes) throws Exception {
+        KeyAgreement keyAgreement = KeyAgreement.getInstance("ECDH");
+        keyAgreement.init(ecPrivKey);
+        keyAgreement.doPhase(ecPublicKey, true);
+        byte[] res = keyAgreement.generateSecret();
+        if (!Arrays.equals(res, expectRes)) {
+            throw new RuntimeException("keyagreement failed");
+        }
+    }
+}
\ No newline at end of file
diff --git a/test/jdk/org/openeuler/security/openssl/HmacTest.java b/test/jdk/org/openeuler/security/openssl/HmacTest.java
new file mode 100644
index 000000000..bddc37b4c
--- /dev/null
+++ b/test/jdk/org/openeuler/security/openssl/HmacTest.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import org.openeuler.security.openssl.KAEProvider;
+
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+import java.security.Key;
+import java.security.Security;
+import java.util.Arrays;
+
+/**
+ * @test
+ * @summary test for Hmac
+ * @modules jdk.crypto.kaeprovider/org.openeuler.security.openssl
+ * @requires os.arch=="aarch64"
+ * @run main/othervm HmacTest
+ */
+public class HmacTest {
+    private static final byte[] PLAIN_BYTES = "hello world".getBytes();
+    private static final String[] ALGORITHMS = new String[]{
+            "HmacMD5",
+            "HmacSHA1",
+            "HmacSHA224",
+            "HmacSHA256",
+            "HmacSHA384",
+            "HmacSHA512",
+    };
+    private static final byte[][] EXPECTED_BYTES = {
+            {-40, 63, -96, 13, 107, -33, -1, -53, -116, 117, 75, -6, 85, -88, -112, -90},
+            {-68, 104, 112, -36, 123, 123, -92, 104, 89, -90, 63, 56, 84, 45, 12, -7, 41, 103, -105, -27},
+            {-31, 0, 103, 51, -119, -61, 2, -76, -83, -113, 95, 86, 8, 46, 91, 20,
+                    -15, -23, -71, 62, -50, 86, -54, 71, -94, -47, -103, 43},
+            {-69, -83, -3, 7, 61, 38, -122, -59, 7, -53, 106, 114, 58, 102, 65, -118,
+                    54, -50, 116, -56, 110, 54, -71, 36, 60, 84, 14, 97, 78, 18, -119, -24},
+            {100, -58, 106, 64, -96, 91, 99, -33, 36, -78, -53, -50, -78, 116, -110, 85,
+                    84, -5, -63, 17, 51, -69, -39, -122, 65, 8, -122, -43, 39, 13, -41, -52,
+                    45, -38, -59, 70, 17, -87, -63, -126, 4, 120, -77, 71, 119, 96, -2, -68},
+            {-89, 47, -98, -12, 110, -88, 23, 2, 28, 26, -71, 53, -108, 54, -52, 1,
+                    -121, -121, 87, 6, -78, 123, -14, -86, 127, 114, 124, -73, -98, 79, -122, 69,
+                    -32, 50, 48, -79, -110, 66, 38, 70, -3, -76, 95, 55, 74, 48, 57, -121,
+                    22, 60, -83, -109, 59, 79, 0, -49, 107, 88, -82, -35, 87, -36, 49, -54}
+    };
+    private static final Key key = new SecretKeySpec("mac".getBytes(), "");
+
+    public static void main(String[] args) throws Exception {
+        Security.insertProviderAt(new KAEProvider(), 1);
+        for (int i = 0; i < ALGORITHMS.length; i++) {
+            test(ALGORITHMS[i], key, PLAIN_BYTES, EXPECTED_BYTES[i]);
+        }
+    }
+
+    private static void test(String algorithm, Key key, byte[] inputBytes, byte[] expectedBytes) throws Exception {
+        Mac mac = Mac.getInstance(algorithm);
+        mac.init(key);
+        mac.update(inputBytes);
+        byte[] bytes = mac.doFinal();
+        if (!(mac.getProvider() instanceof KAEProvider)) {
+            throw new RuntimeException(algorithm + " failed," +
+                    "provider=" + mac.getProvider().getClass() + "," +
+                    "expectedProvider=" + KAEProvider.class);
+        }
+        if (!Arrays.equals(bytes, expectedBytes)) {
+            throw new RuntimeException(algorithm + " failed," +
+                    "bytes=" + Arrays.toString(bytes) + "," +
+                    "expectedBytes=" + Arrays.toString(expectedBytes));
+        }
+    }
+}
diff --git a/test/jdk/org/openeuler/security/openssl/KAEConfTest.java b/test/jdk/org/openeuler/security/openssl/KAEConfTest.java
new file mode 100644
index 000000000..4076aa2fc
--- /dev/null
+++ b/test/jdk/org/openeuler/security/openssl/KAEConfTest.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import org.openeuler.security.openssl.KAEConfig;
+import org.openeuler.security.openssl.KAEProvider;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.util.ArrayList;
+import java.util.List;
+
+/*
+ * @test
+ * @summary Test KAE Conf
+ * @modules jdk.crypto.kaeprovider/org.openeuler.security.openssl
+ * @requires os.arch=="aarch64"
+ * @run main/othervm KAEConfTest DEFAULT
+ * @run main/othervm KAEConfTest SPECIFY
+ */
+public class KAEConfTest {
+    private static final String DEFAULT_CONF = System.getProperty("java.home") +
+            File.separator + "conf" + File.separator + "kaeprovider.conf";
+
+    private static final String SPECIFY_CONF = System.getProperty("user.dir") +
+            File.separator + "kaeprovider.conf";
+
+    private static final String SPECIFY_LOG_PATH = System.getProperty("user.dir") + File.separator + "kae.log";
+    private static final List<File> files = new ArrayList<>();
+
+    enum Mode {
+        DEFAULT,
+        SPECIFY
+    }
+
+    public static void main(String[] args) throws IOException {
+        Mode mode = getMode(args);
+        try {
+            init(mode);
+            new KAEProvider();
+            test(mode);
+        } finally {
+            KAETestHelper.cleanUp(files);
+        }
+    }
+
+    private static Mode getMode(String[] args) {
+        if (args.length <= 0) {
+            return Mode.DEFAULT;
+        }
+        return Mode.valueOf(args[0]);
+    }
+
+    private static void init(Mode mode) throws IOException {
+        if (Mode.SPECIFY.equals(mode)) {
+            System.setProperty("kae.conf", SPECIFY_CONF);
+            File file = new File(SPECIFY_CONF);
+            if (!file.exists()) {
+                Files.createFile(file.toPath());
+            }
+            files.add(file);
+            try (FileWriter fileWriter = new FileWriter(file)) {
+                fileWriter.write("kae.log=true");
+                fileWriter.flush();
+            }
+        }
+    }
+
+    private static void testDefault() {
+        File file = new File(DEFAULT_CONF);
+        if (!file.exists()) {
+            throw new RuntimeException("test failed");
+        }
+    }
+
+    private static void testSpecify() {
+        String value = KAEConfig.privilegedGetOverridable("kae.log");
+        if (!"true".equals(value)) {
+            throw new RuntimeException("test failed : kae.log=" + value);
+        }
+        File file = new File(SPECIFY_LOG_PATH);
+        if (!file.exists()) {
+            throw new RuntimeException(SPECIFY_LOG_PATH + "does not exist");
+        }
+        // kae log file
+        files.add(file);
+    }
+
+    private static void test(Mode mode) {
+        switch (mode) {
+            case DEFAULT:
+                testDefault();
+                break;
+            case SPECIFY:
+                testSpecify();
+                break;
+            default:
+                throw new IllegalArgumentException("invalid mode");
+        }
+    }
+}
diff --git a/test/jdk/org/openeuler/security/openssl/KAEDisabledAlgorithmsTest.java b/test/jdk/org/openeuler/security/openssl/KAEDisabledAlgorithmsTest.java
new file mode 100644
index 000000000..e8d767f0c
--- /dev/null
+++ b/test/jdk/org/openeuler/security/openssl/KAEDisabledAlgorithmsTest.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import org.openeuler.security.openssl.KAEConfig;
+import org.openeuler.security.openssl.KAEProvider;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/*
+ * @test
+ * @summary Test property kae.engine.disableAlgorithms
+ * @modules jdk.crypto.kaeprovider/org.openeuler.security.openssl
+ * @requires os.arch=="aarch64"
+ * @run main/othervm -Dkae.engine.disabledAlgorithms=md5 KAEDisabledAlgorithmsTest
+ * @run main/othervm -Dkae.engine.disabledAlgorithms=sha256 KAEDisabledAlgorithmsTest
+ * @run main/othervm -Dkae.engine.disabledAlgorithms=sha384 KAEDisabledAlgorithmsTest
+ * @run main/othervm -Dkae.engine.disabledAlgorithms=sm3 KAEDisabledAlgorithmsTest
+ * @run main/othervm -Dkae.engine.disabledAlgorithms=aes-128-ecb KAEDisabledAlgorithmsTest
+ * @run main/othervm -Dkae.engine.disabledAlgorithms=aes-128-cbc KAEDisabledAlgorithmsTest
+ * @run main/othervm -Dkae.engine.disabledAlgorithms=aes-128-ctr KAEDisabledAlgorithmsTest
+ * @run main/othervm -Dkae.engine.disabledAlgorithms=aes-128-gcm KAEDisabledAlgorithmsTest
+ * @run main/othervm -Dkae.engine.disabledAlgorithms=aes-192-ecb KAEDisabledAlgorithmsTest
+ * @run main/othervm -Dkae.engine.disabledAlgorithms=aes-192-cbc KAEDisabledAlgorithmsTest
+ * @run main/othervm -Dkae.engine.disabledAlgorithms=aes-192-ctr KAEDisabledAlgorithmsTest
+ * @run main/othervm -Dkae.engine.disabledAlgorithms=aes-192-gcm KAEDisabledAlgorithmsTest
+ * @run main/othervm -Dkae.engine.disabledAlgorithms=aes-256-ecb KAEDisabledAlgorithmsTest
+ * @run main/othervm -Dkae.engine.disabledAlgorithms=aes-256-cbc KAEDisabledAlgorithmsTest
+ * @run main/othervm -Dkae.engine.disabledAlgorithms=aes-256-ctr KAEDisabledAlgorithmsTest
+ * @run main/othervm -Dkae.engine.disabledAlgorithms=aes-256-gcm KAEDisabledAlgorithmsTest
+ * @run main/othervm -Dkae.engine.disabledAlgorithms=sm4-ecb KAEDisabledAlgorithmsTest
+ * @run main/othervm -Dkae.engine.disabledAlgorithms=sm4-cbc KAEDisabledAlgorithmsTest
+ * @run main/othervm -Dkae.engine.disabledAlgorithms=sm4-ctr KAEDisabledAlgorithmsTest
+ * @run main/othervm -Dkae.engine.disabledAlgorithms=sm4-ofb KAEDisabledAlgorithmsTest
+ * @run main/othervm -Dkae.engine.disabledAlgorithms=hmac-md5 KAEDisabledAlgorithmsTest
+ * @run main/othervm -Dkae.engine.disabledAlgorithms=hmac-sha1 KAEDisabledAlgorithmsTest
+ * @run main/othervm -Dkae.engine.disabledAlgorithms=hmac-sha224 KAEDisabledAlgorithmsTest
+ * @run main/othervm -Dkae.engine.disabledAlgorithms=hmac-sha256 KAEDisabledAlgorithmsTest
+ * @run main/othervm -Dkae.engine.disabledAlgorithms=hmac-sha384 KAEDisabledAlgorithmsTest
+ * @run main/othervm -Dkae.engine.disabledAlgorithms=hmac-sha512 KAEDisabledAlgorithmsTest
+ * @run main/othervm -Dkae.engine.disabledAlgorithms=rsa KAEDisabledAlgorithmsTest
+ * @run main/othervm -Dkae.engine.disabledAlgorithms=dh KAEDisabledAlgorithmsTest
+ * @run main/othervm -Dkae.engine.disabledAlgorithms=ec KAEDisabledAlgorithmsTest
+ * @run main/othervm -Dkae.engine.disabledAlgorithms=aes-128-gcm,aes-192-gcm,aes-256-gcm KAEDisabledAlgorithmsTest
+ * @run main/othervm -Dkae.engine.disabledAlgorithms=md5,aes-128-ecb,sm4-ecb,hmac-sha1,rsa,dh,ec KAEDisabledAlgorithmsTest
+ * @run main/othervm -Dkae.engine.id=uadk_engine -Dkae.libcrypto.useGlobalMode=true -Dkae.engine.disabledAlgorithms=md5 KAEDisabledAlgorithmsTest
+ * @run main/othervm -Dkae.engine.id=uadk_engine -Dkae.libcrypto.useGlobalMode=true -Dkae.engine.disabledAlgorithms=sha256 KAEDisabledAlgorithmsTest
+ * @run main/othervm -Dkae.engine.id=uadk_engine -Dkae.libcrypto.useGlobalMode=true -Dkae.engine.disabledAlgorithms=sha384 KAEDisabledAlgorithmsTest
+ * @run main/othervm -Dkae.engine.id=uadk_engine -Dkae.libcrypto.useGlobalMode=true -Dkae.engine.disabledAlgorithms=sm3 KAEDisabledAlgorithmsTest
+ * @run main/othervm -Dkae.engine.id=uadk_engine -Dkae.libcrypto.useGlobalMode=true -Dkae.engine.disabledAlgorithms=aes-128-ecb KAEDisabledAlgorithmsTest
+ * @run main/othervm -Dkae.engine.id=uadk_engine -Dkae.libcrypto.useGlobalMode=true -Dkae.engine.disabledAlgorithms=aes-128-cbc KAEDisabledAlgorithmsTest
+ * @run main/othervm -Dkae.engine.id=uadk_engine -Dkae.libcrypto.useGlobalMode=true -Dkae.engine.disabledAlgorithms=aes-128-ctr KAEDisabledAlgorithmsTest
+ * @run main/othervm -Dkae.engine.id=uadk_engine -Dkae.libcrypto.useGlobalMode=true -Dkae.engine.disabledAlgorithms=aes-128-gcm KAEDisabledAlgorithmsTest
+ * @run main/othervm -Dkae.engine.id=uadk_engine -Dkae.libcrypto.useGlobalMode=true -Dkae.engine.disabledAlgorithms=aes-192-ecb KAEDisabledAlgorithmsTest
+ * @run main/othervm -Dkae.engine.id=uadk_engine -Dkae.libcrypto.useGlobalMode=true -Dkae.engine.disabledAlgorithms=aes-192-cbc KAEDisabledAlgorithmsTest
+ * @run main/othervm -Dkae.engine.id=uadk_engine -Dkae.libcrypto.useGlobalMode=true -Dkae.engine.disabledAlgorithms=aes-192-ctr KAEDisabledAlgorithmsTest
+ * @run main/othervm -Dkae.engine.id=uadk_engine -Dkae.libcrypto.useGlobalMode=true -Dkae.engine.disabledAlgorithms=aes-192-gcm KAEDisabledAlgorithmsTest
+ * @run main/othervm -Dkae.engine.id=uadk_engine -Dkae.libcrypto.useGlobalMode=true -Dkae.engine.disabledAlgorithms=aes-256-ecb KAEDisabledAlgorithmsTest
+ * @run main/othervm -Dkae.engine.id=uadk_engine -Dkae.libcrypto.useGlobalMode=true -Dkae.engine.disabledAlgorithms=aes-256-cbc KAEDisabledAlgorithmsTest
+ * @run main/othervm -Dkae.engine.id=uadk_engine -Dkae.libcrypto.useGlobalMode=true -Dkae.engine.disabledAlgorithms=aes-256-ctr KAEDisabledAlgorithmsTest
+ * @run main/othervm -Dkae.engine.id=uadk_engine -Dkae.libcrypto.useGlobalMode=true -Dkae.engine.disabledAlgorithms=aes-256-gcm KAEDisabledAlgorithmsTest
+ * @run main/othervm -Dkae.engine.id=uadk_engine -Dkae.libcrypto.useGlobalMode=true -Dkae.engine.disabledAlgorithms=sm4-ecb KAEDisabledAlgorithmsTest
+ * @run main/othervm -Dkae.engine.id=uadk_engine -Dkae.libcrypto.useGlobalMode=true -Dkae.engine.disabledAlgorithms=sm4-cbc KAEDisabledAlgorithmsTest
+ * @run main/othervm -Dkae.engine.id=uadk_engine -Dkae.libcrypto.useGlobalMode=true -Dkae.engine.disabledAlgorithms=sm4-ctr KAEDisabledAlgorithmsTest
+ * @run main/othervm -Dkae.engine.id=uadk_engine -Dkae.libcrypto.useGlobalMode=true -Dkae.engine.disabledAlgorithms=sm4-ofb KAEDisabledAlgorithmsTest
+ * @run main/othervm -Dkae.engine.id=uadk_engine -Dkae.libcrypto.useGlobalMode=true -Dkae.engine.disabledAlgorithms=hmac-md5 KAEDisabledAlgorithmsTest
+ * @run main/othervm -Dkae.engine.id=uadk_engine -Dkae.libcrypto.useGlobalMode=true -Dkae.engine.disabledAlgorithms=hmac-sha1 KAEDisabledAlgorithmsTest
+ * @run main/othervm -Dkae.engine.id=uadk_engine -Dkae.libcrypto.useGlobalMode=true -Dkae.engine.disabledAlgorithms=hmac-sha224 KAEDisabledAlgorithmsTest
+ * @run main/othervm -Dkae.engine.id=uadk_engine -Dkae.libcrypto.useGlobalMode=true -Dkae.engine.disabledAlgorithms=hmac-sha256 KAEDisabledAlgorithmsTest
+ * @run main/othervm -Dkae.engine.id=uadk_engine -Dkae.libcrypto.useGlobalMode=true -Dkae.engine.disabledAlgorithms=hmac-sha384 KAEDisabledAlgorithmsTest
+ * @run main/othervm -Dkae.engine.id=uadk_engine -Dkae.libcrypto.useGlobalMode=true -Dkae.engine.disabledAlgorithms=hmac-sha512 KAEDisabledAlgorithmsTest
+ * @run main/othervm -Dkae.engine.id=uadk_engine -Dkae.libcrypto.useGlobalMode=true -Dkae.engine.disabledAlgorithms=rsa KAEDisabledAlgorithmsTest
+ * @run main/othervm -Dkae.engine.id=uadk_engine -Dkae.libcrypto.useGlobalMode=true -Dkae.engine.disabledAlgorithms=dh KAEDisabledAlgorithmsTest
+ * @run main/othervm -Dkae.engine.id=uadk_engine -Dkae.libcrypto.useGlobalMode=true -Dkae.engine.disabledAlgorithms=ec KAEDisabledAlgorithmsTest
+ * @run main/othervm -Dkae.engine.id=uadk_engine -Dkae.libcrypto.useGlobalMode=true -Dkae.engine.disabledAlgorithms=aes-128-gcm,aes-192-gcm,aes-256-gcm KAEDisabledAlgorithmsTest
+ * @run main/othervm -Dkae.engine.id=uadk_engine -Dkae.libcrypto.useGlobalMode=true -Dkae.engine.disabledAlgorithms=md5,aes-128-ecb,sm4-ecb,hmac-sha1,rsa,dh,ec KAEDisabledAlgorithmsTest
+ */
+public class KAEDisabledAlgorithmsTest {
+
+    public static void main(String[] args) {
+        KAETestHelper.Engine engine = KAETestHelper.getEngine();
+        if (!engine.isValid()) {
+            System.out.println("Skip test, engine " + engine.getEngineId() + " does not exist.");
+            return;
+        }
+        String[] disabledAlgorithms = getDisabledAlgorithms();
+        init();
+        new KAEProvider();
+        test(disabledAlgorithms);
+    }
+
+    private static final String[] PROPERTY_NAMES = new String[]{
+            "kae.digest.useKaeEngine",
+            "kae.aes.useKaeEngine",
+            "kae.sm4.useKaeEngine",
+            "kae.hmac.useKaeEngine",
+            "kae.rsa.useKaeEngine",
+            "kae.dh.useKaeEngine",
+            "kae.ec.useKaeEngine"
+    };
+
+    private static String[] getDisabledAlgorithms() {
+        String value = System.getProperty("kae.engine.disabledAlgorithms");
+        if (value == null) {
+            return new String[0];
+        }
+        return value.split(",");
+    }
+
+    private static void init() {
+        for (String propertyName : PROPERTY_NAMES) {
+            System.setProperty(propertyName, "true");
+        }
+    }
+
+    private static void test(String[] disabledAlgorithms) {
+        boolean[] useKaeEngineFlags = KAEConfig.getUseKaeEngineFlags();
+        Set<Integer> disabledAlgorithmIndexSet = new HashSet<>();
+
+        // test disabled algorithms
+        for (String disabledAlgorithm : disabledAlgorithms) {
+            Integer index = KAETestHelper.getAlgorithmIndex(disabledAlgorithm);
+            if (index == null || index < 0 || index >= useKaeEngineFlags.length) {
+                continue;
+            }
+            if (useKaeEngineFlags[index]) {
+                throw new RuntimeException("test failed");
+            }
+            disabledAlgorithmIndexSet.add(index);
+        }
+
+        // test other algorithms that are not disabled (except ec)
+        for (int i = 0; i < useKaeEngineFlags.length - 1; i++) {
+            if (!disabledAlgorithmIndexSet.contains(i) && !useKaeEngineFlags[i]) {
+                throw new RuntimeException(KAETestHelper.getAlgorithmName(i) + " algorithm is not disabled");
+            }
+        }
+
+        // test whether the ec algorithm is disabled by default
+        if (useKaeEngineFlags[useKaeEngineFlags.length - 1]) {
+            throw new RuntimeException(KAETestHelper.getAlgorithmName(useKaeEngineFlags.length - 1)
+                    + " algorithm is disabled by default");
+        }
+    }
+}
diff --git a/test/jdk/org/openeuler/security/openssl/KAEEngineIdTest.java b/test/jdk/org/openeuler/security/openssl/KAEEngineIdTest.java
new file mode 100644
index 000000000..75248a432
--- /dev/null
+++ b/test/jdk/org/openeuler/security/openssl/KAEEngineIdTest.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import org.openeuler.security.openssl.KAEProvider;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/*
+ * @test
+ * @summary Test KAE  property kae.engine.id and kae.libcrypto.useGlobalMode
+ * @modules jdk.crypto.kaeprovider/org.openeuler.security.openssl
+ * @requires os.arch=="aarch64"
+ * @run main/othervm -Dkae.log=true KAEEngineIdTest
+ * @run main/othervm -Dkae.log=true -Dkae.engine.id=kae KAEEngineIdTest
+ * @run main/othervm -Dkae.log=true -Dkae.engine.id=uadk_engine -Dkae.libcrypto.useGlobalMode=true KAEEngineIdTest
+ */
+public class KAEEngineIdTest {
+
+    private static final String LOG_PATH = System.getProperty("user.dir") +
+            File.separator + "kae.log";
+
+    private static final List<File> files = new ArrayList<>();
+
+    public static void main(String[] args) throws IOException {
+        KAETestHelper.Engine engine =  KAETestHelper.getEngine();
+        if (!engine.isValid()) {
+            System.out.println("Skip test, engine " + engine.getEngineId() + " does not exist.");
+            return;
+        }
+
+        try {
+            new KAEProvider();
+            test(engine);
+        } finally {
+            KAETestHelper.cleanUp(files);
+        }
+    }
+
+    private static void test(KAETestHelper.Engine engine) throws IOException {
+        File file = new File(LOG_PATH);
+        if (!file.exists()) {
+            throw new RuntimeException(LOG_PATH + " does not exist");
+        }
+        files.add(file);
+        try (BufferedReader bufferedReader = new BufferedReader(new FileReader(file))) {
+            String s = bufferedReader.readLine();
+            if (!s.contains(engine.getEngineId() + " engine was found")) {
+                throw new RuntimeException("test failed");
+            }
+        }
+    }
+}
diff --git a/test/jdk/org/openeuler/security/openssl/KAELogTest.java b/test/jdk/org/openeuler/security/openssl/KAELogTest.java
new file mode 100644
index 000000000..f635d96f3
--- /dev/null
+++ b/test/jdk/org/openeuler/security/openssl/KAELogTest.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import org.openeuler.security.openssl.KAEProvider;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+/*
+ * @test
+ * @summary Test KAE log
+ * @modules jdk.crypto.kaeprovider/org.openeuler.security.openssl
+ * @requires os.arch=="aarch64"
+ * @run main/othervm KAELogTest
+ * @run main/othervm -Dkae.log=false KAELogTest
+ * @run main/othervm -Dkae.log=true KAELogTest
+ * @run main/othervm -Dkae.log=true -Dkae.log.file=./KAELogTest/kae.log KAELogTest
+ */
+public class KAELogTest {
+    private static final String DEFAULT_LOG_PATH = System.getProperty("user.dir") +
+            File.separator + "kae.log";
+
+    private static final String SPECIFY_LOG_PATH = System.getProperty("user.dir") +
+            File.separator + "KAELogTest" + File.separator + "kae.log";
+
+    private static final List<File> files = new ArrayList<>();
+
+    enum Mode {
+        DEFAULT,
+        DISABLE,
+        ENABLE,
+        SPECIFY
+    }
+
+    public static void main(String[] args) {
+        Mode mode = getMode();
+        try {
+            new KAEProvider();
+            test(mode);
+        } finally {
+            KAETestHelper.cleanUp(files);
+        }
+    }
+
+    private static Mode getMode() {
+        String enableKaeLog = System.getProperty("kae.log");
+        if (enableKaeLog == null) {
+            return Mode.DEFAULT;
+        } else if ("false".equals(enableKaeLog)) {
+            return Mode.DISABLE;
+        } else {
+            String logPath = System.getProperty("kae.log.file");
+            if (logPath == null) {
+                return Mode.ENABLE;
+            }
+            return Mode.SPECIFY;
+        }
+    }
+
+    private static void testDefault() {
+        testDisable();
+    }
+
+    private static void testDisable() {
+        File file = new File(DEFAULT_LOG_PATH);
+        if (file.exists()) {
+            throw new RuntimeException("test failed");
+        }
+    }
+
+    private static void testEnable() {
+        File file = new File(DEFAULT_LOG_PATH);
+        if (!file.exists()) {
+            throw new RuntimeException("test failed");
+        }
+        files.add(file);
+    }
+
+    private static void testSpecify() {
+        File file = new File(KAELogTest.SPECIFY_LOG_PATH);
+        if (!file.exists()) {
+            throw new RuntimeException("test failed");
+        }
+        files.add(file);
+        files.add(file.getParentFile());
+    }
+
+    private static void test(Mode mode) {
+        switch (mode) {
+            case DEFAULT:
+                testDefault();
+                break;
+            case DISABLE:
+                testDisable();
+                break;
+            case ENABLE:
+                testEnable();
+                break;
+            case SPECIFY:
+                testSpecify();
+                break;
+            default:
+                throw new IllegalArgumentException("invalid mode");
+        }
+    }
+}
diff --git a/test/jdk/org/openeuler/security/openssl/KAETestHelper.java b/test/jdk/org/openeuler/security/openssl/KAETestHelper.java
new file mode 100644
index 000000000..59ad91ddc
--- /dev/null
+++ b/test/jdk/org/openeuler/security/openssl/KAETestHelper.java
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+class KAETestHelper {
+    private static final String KAE_ENGINE_ID = "kae";
+    private static final String UADK_ENGINE_ID = "uadk_engine";
+    private static boolean hasKaeEngine;
+    private static boolean hasUadkEngine;
+
+    private static String engineRootPath;
+
+    // algorithm names
+    private static final String[] ALGORITHM_NAMES = new String[]{
+            "md5",
+            "sha256",
+            "sha384",
+            "sm3",
+            "aes-128-ecb",
+            "aes-128-cbc",
+            "aes-128-ctr",
+            "aes-128-gcm",
+            "aes-192-ecb",
+            "aes-192-cbc",
+            "aes-192-ctr",
+            "aes-192-gcm",
+            "aes-256-ecb",
+            "aes-256-cbc",
+            "aes-256-ctr",
+            "aes-256-gcm",
+            "sm4-ecb",
+            "sm4-cbc",
+            "sm4-ctr",
+            "sm4-ofb",
+            "hmac-md5",
+            "hmac-sha1",
+            "hmac-sha224",
+            "hmac-sha256",
+            "hmac-sha384",
+            "hmac-sha512",
+            "rsa",
+            "dh",
+            "ec"
+    };
+    private static final Map<String, Integer> ALGORITHM_NAME_MAP = new HashMap<>();
+
+    private static final String PROVIDER_NAME = "KAEProvider";
+    private static final String USE_OPENSSL_MSG = "Use openssl soft calculation";
+    private static final String USE_KAE_HARDWARE_MSG = "enable KAE hardware acceleration";
+    private static final Map<String, Boolean> ALGORITHM_MSG_MAP = new HashMap<>();
+
+    static {
+        init();
+    }
+
+    enum Engine {
+        default_engine(hasKaeEngine, KAE_ENGINE_ID),
+        kae(hasKaeEngine, KAE_ENGINE_ID),
+        uadk_engine(hasUadkEngine, UADK_ENGINE_ID);
+        private final boolean isValid;
+        private final String engineId;
+
+        Engine(boolean isValid, String engineId) {
+            this.isValid = isValid;
+            this.engineId = engineId;
+        }
+
+        public boolean isValid() {
+            return isValid;
+        }
+
+        public String getEngineId() {
+            return engineId;
+        }
+    }
+
+    private static void init() {
+        engineRootPath = System.getenv("OPENSSL_ENGINES");
+        if (engineRootPath == null || engineRootPath.equals("")) {
+            System.out.println("Environment variable OPENSSL_ENGINES is not configured");
+        }
+        hasKaeEngine = hasEngine(KAE_ENGINE_ID);
+        hasUadkEngine = hasEngine(UADK_ENGINE_ID);
+
+        for (int i = 0; i < ALGORITHM_NAMES.length; i++) {
+            ALGORITHM_NAME_MAP.put(ALGORITHM_NAMES[i], i);
+        }
+
+        ALGORITHM_MSG_MAP.put(USE_OPENSSL_MSG, false);
+        ALGORITHM_MSG_MAP.put(USE_KAE_HARDWARE_MSG, true);
+    }
+
+    static Integer getAlgorithmIndex(String algorithmName) {
+        return ALGORITHM_NAME_MAP.get(algorithmName);
+    }
+
+    static String getAlgorithmName(Integer algorithmIndex) {
+        return ALGORITHM_NAMES[algorithmIndex];
+    }
+
+    private static boolean hasEngine(String engineId) {
+        String filePath = engineRootPath + File.separator + engineId + ".so";
+        File file = new File(filePath);
+        return file.exists();
+    }
+
+    static boolean hasKaeEngine() {
+        return hasKaeEngine;
+    }
+
+    static boolean hasUadkEngine() {
+        return hasUadkEngine;
+    }
+
+    static void cleanUp(List<File> files) {
+        for (File file : files) {
+            System.out.println("delete file : " + file);
+            file.delete();
+        }
+    }
+
+    static boolean[] parseLog(Engine engine, File file) throws IOException {
+        boolean[] kaeUseEngineFlags;
+        String expectedEngineMsg = engine.getEngineId() + " engine was found";
+        try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
+            // load engine message
+            String engineMsg = reader.readLine();
+            if (engineMsg == null || !engineMsg.contains(expectedEngineMsg)) {
+                throw new RuntimeException("test failed : actual message :" + engineMsg);
+            }
+
+            // summary message
+            String summaryMessage = reader.readLine();
+            if (summaryMessage == null) {
+                throw new RuntimeException("test failed : summary message is null");
+            }
+
+            kaeUseEngineFlags = new boolean[ALGORITHM_NAMES.length];
+            // strategy of each algorithm
+            String strategy;
+            while ((strategy = reader.readLine()) != null) {
+                String[] splitArray = strategy.split("=>");
+                if (splitArray.length < 2) {
+                    throw new RuntimeException("test failed : strategy = " + strategy);
+                }
+
+                // algorithm Index
+                String algorithm = splitArray[0].replace(" ", "");
+                Integer algorithmIndex = ALGORITHM_NAME_MAP.get(algorithm);
+                if (algorithmIndex == null) {
+                    throw new RuntimeException("test failed : illegal algorithm " + algorithm);
+                }
+
+                // provider and algorithm value
+                String detail = splitArray[1];
+                String[] detailArray = detail.split(":");
+                if (detailArray.length < 2) {
+                    throw new RuntimeException("test failed : detail=" + strategy);
+                }
+                String provider = detailArray[0].replace(" ", "");
+                if (!PROVIDER_NAME.equals(provider)) {
+                    throw new RuntimeException("test failed : provider= " + provider);
+                }
+                String algorithmMsg = detailArray[1].trim();
+                Boolean algorithmValue = ALGORITHM_MSG_MAP.get(algorithmMsg);
+                if (algorithmValue == null) {
+                    throw new RuntimeException("test failed : algorithmMsg= " + algorithmMsg);
+                }
+                kaeUseEngineFlags[algorithmIndex] = algorithmValue;
+            }
+        }
+        return kaeUseEngineFlags;
+    }
+
+    static KAETestHelper.Engine getEngine() {
+        String engineId = System.getProperty("kae.engine.id");
+        if (engineId == null) {
+            return KAETestHelper.Engine.default_engine;
+        }
+        return KAETestHelper.Engine.valueOf(engineId);
+    }
+}
diff --git a/test/jdk/org/openeuler/security/openssl/KAEUseEngineTest.java b/test/jdk/org/openeuler/security/openssl/KAEUseEngineTest.java
new file mode 100644
index 000000000..a5b9b5386
--- /dev/null
+++ b/test/jdk/org/openeuler/security/openssl/KAEUseEngineTest.java
@@ -0,0 +1,263 @@
+/*
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import org.openeuler.security.openssl.KAEProvider;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/*
+ * @test
+ * @summary Test KAE property kae.<algorithm>.useKaeEngine
+ * @modules jdk.crypto.kaeprovider/org.openeuler.security.openssl
+ * @requires os.arch=="aarch64"
+ * @run main/othervm -Dkae.log=true -Dall.test=default KAEUseEngineTest
+ * @run main/othervm -Dkae.log=true -Dkae.digest.useKaeEngine=true KAEUseEngineTest
+ * @run main/othervm -Dkae.log=true -Dkae.aes.useKaeEngine=true KAEUseEngineTest
+ * @run main/othervm -Dkae.log=true -Dkae.sm4.useKaeEngine=true KAEUseEngineTest
+ * @run main/othervm -Dkae.log=true -Dkae.hmac.useKaeEngine=true KAEUseEngineTest
+ * @run main/othervm -Dkae.log=true -Dkae.rsa.useKaeEngine=true KAEUseEngineTest
+ * @run main/othervm -Dkae.log=true -Dkae.dh.useKaeEngine=true KAEUseEngineTest
+ * @run main/othervm -Dkae.log=true -Dkae.ec.useKaeEngine=true KAEUseEngineTest
+ * @run main/othervm -Dkae.log=true -Dall.test=enable -Dkae.digest.useKaeEngine=true -Dkae.aes.useKaeEngine=true -Dkae.sm4.useKaeEngine=true  -Dkae.hmac.useKaeEngine=true -Dkae.rsa.useKaeEngine=true -Dkae.dh.useKaeEngine=true -Dkae.ec.useKaeEngine=true   KAEUseEngineTest
+ * @run main/othervm -Dkae.log=true -Dkae.digest.useKaeEngine=false KAEUseEngineTest
+ * @run main/othervm -Dkae.log=true -Dkae.aes.useKaeEngine=true KAEUseEngineTest
+ * @run main/othervm -Dkae.log=true -Dkae.sm4.useKaeEngine=true KAEUseEngineTest
+ * @run main/othervm -Dkae.log=true -Dkae.hmac.useKaeEngine=true KAEUseEngineTest
+ * @run main/othervm -Dkae.log=true -Dkae.rsa.useKaeEngine=true KAEUseEngineTest
+ * @run main/othervm -Dkae.log=true -Dkae.dh.useKaeEngine=true KAEUseEngineTest
+ * @run main/othervm -Dkae.log=true -Dkae.ec.useKaeEngine=true KAEUseEngineTest
+ * @run main/othervm -Dkae.log=true -Dall.test=disable -Dkae.digest.useKaeEngine=false -Dkae.aes.useKaeEngine=false -Dkae.sm4.useKaeEngine=false  -Dkae.hmac.useKaeEngine=false -Dkae.rsa.useKaeEngine=false -Dkae.dh.useKaeEngine=false -Dkae.ec.useKaeEngine=false  KAEUseEngineTest
+ * @run main/othervm -Dkae.log=true -Dall.test=default -Dkae.engine.id=uadk_engine -Dkae.libcrypto.useGlobalMode=true KAEUseEngineTest
+ * @run main/othervm -Dkae.log=true -Dkae.engine.id=uadk_engine -Dkae.libcrypto.useGlobalMode=true -Dkae.digest.useKaeEngine=true KAEUseEngineTest
+ * @run main/othervm -Dkae.log=true -Dkae.engine.id=uadk_engine -Dkae.libcrypto.useGlobalMode=true -Dkae.aes.useKaeEngine=true KAEUseEngineTest
+ * @run main/othervm -Dkae.log=true -Dkae.engine.id=uadk_engine -Dkae.libcrypto.useGlobalMode=true -Dkae.sm4.useKaeEngine=true KAEUseEngineTest
+ * @run main/othervm -Dkae.log=true -Dkae.engine.id=uadk_engine -Dkae.libcrypto.useGlobalMode=true -Dkae.hmac.useKaeEngine=true KAEUseEngineTest
+ * @run main/othervm -Dkae.log=true -Dkae.engine.id=uadk_engine -Dkae.libcrypto.useGlobalMode=true -Dkae.rsa.useKaeEngine=true KAEUseEngineTest
+ * @run main/othervm -Dkae.log=true -Dkae.engine.id=uadk_engine -Dkae.libcrypto.useGlobalMode=true -Dkae.dh.useKaeEngine=true KAEUseEngineTest
+ * @run main/othervm -Dkae.log=true -Dkae.engine.id=uadk_engine -Dkae.libcrypto.useGlobalMode=true -Dkae.ec.useKaeEngine=true KAEUseEngineTest
+ * @run main/othervm -Dkae.log=true -Dall.test=enable -Dkae.engine.id=uadk_engine -Dkae.libcrypto.useGlobalMode=true -Dkae.digest.useKaeEngine=true -Dkae.aes.useKaeEngine=true -Dkae.sm4.useKaeEngine=true  -Dkae.hmac.useKaeEngine=true -Dkae.rsa.useKaeEngine=true -Dkae.dh.useKaeEngine=true -Dkae.ec.useKaeEngine=true   KAEUseEngineTest
+ * @run main/othervm -Dkae.log=true -Dkae.engine.id=uadk_engine -Dkae.libcrypto.useGlobalMode=true -Dkae.digest.useKaeEngine=false KAEUseEngineTest
+ * @run main/othervm -Dkae.log=true -Dkae.engine.id=uadk_engine -Dkae.libcrypto.useGlobalMode=true -Dkae.aes.useKaeEngine=true KAEUseEngineTest
+ * @run main/othervm -Dkae.log=true -Dkae.engine.id=uadk_engine -Dkae.libcrypto.useGlobalMode=true -Dkae.sm4.useKaeEngine=true KAEUseEngineTest
+ * @run main/othervm -Dkae.log=true -Dkae.engine.id=uadk_engine -Dkae.libcrypto.useGlobalMode=true -Dkae.hmac.useKaeEngine=true KAEUseEngineTest
+ * @run main/othervm -Dkae.log=true -Dkae.engine.id=uadk_engine -Dkae.libcrypto.useGlobalMode=true -Dkae.rsa.useKaeEngine=true KAEUseEngineTest
+ * @run main/othervm -Dkae.log=true -Dkae.engine.id=uadk_engine -Dkae.libcrypto.useGlobalMode=true -Dkae.dh.useKaeEngine=true KAEUseEngineTest
+ * @run main/othervm -Dkae.log=true -Dkae.engine.id=uadk_engine -Dkae.libcrypto.useGlobalMode=true -Dkae.ec.useKaeEngine=true KAEUseEngineTest
+ * @run main/othervm -Dkae.log=true -Dall.test=disable -Dkae.engine.id=uadk_engine -Dkae.libcrypto.useGlobalMode=true -Dkae.digest.useKaeEngine=false -Dkae.aes.useKaeEngine=false -Dkae.sm4.useKaeEngine=false  -Dkae.hmac.useKaeEngine=false -Dkae.rsa.useKaeEngine=false -Dkae.dh.useKaeEngine=false -Dkae.ec.useKaeEngine=false  KAEUseEngineTest
+ */
+public class KAEUseEngineTest {
+  enum Mode {
+    DEFAULT(new boolean[]{
+            true, false, false, true, false, false, false, false, false, false,
+            false, false, false, false, false, false, true, true, true, true,
+            false, false, false, false, false, false, true, true, false
+    }),
+    DIGEST_ENABLE(new boolean[]{
+            true, false, false, true, false, false, false, false, false, false,
+            false, false, false, false, false, false, true, true, true, true,
+            false, false, false, false, false, false, true, true, false
+    }, 0, true),
+    AES_ENABLE(new boolean[]{
+            true, false, false, true, true, true, true, true, true, true,
+            true, true, true, true, true, true, true, true, true, true,
+            false, false, false, false, false, false, true, true, false
+    }, 1, true),
+    SM4_ENABLE(new boolean[]{
+            true, false, false, true, false, false, false, false, false, false,
+            false, false, false, false, false, false, true, true, true, true,
+            false, false, false, false, false, false, true, true, false
+    }, 2, true),
+    HMAC_ENABLE(new boolean[]{
+            true, false, false, true, false, false, false, false, false, false,
+            false, false, false, false, false, false, true, true, true, true,
+            true, true, true, true, true, true, true, true, false
+    }, 3, true),
+    RSA_ENABLE(new boolean[]{
+            true, false, false, true, false, false, false, false, false, false,
+            false, false, false, false, false, false, true, true, true, true,
+            false, false, false, false, false, false, true, true, false
+    }, 4, true),
+    DH_ENABLE(new boolean[]{
+            true, false, false, true, false, false, false, false, false, false,
+            false, false, false, false, false, false, true, true, true, true,
+            false, false, false, false, false, false, true, true, false
+    }, 5, true),
+    EC_ENABLE(new boolean[]{
+            true, false, false, true, false, false, false, false, false, false,
+            false, false, false, false, false, false, true, true, true, true,
+            false, false, false, false, false, false, true, true, false
+    }, 6, true),
+    ALL_ENABLE(new boolean[]{
+            true, false, false, true, true, true, true, true, true, true,
+            true, true, true, true, true, true, true, true, true, true,
+            true, true, true, true, true, true, true, true, false
+    }, true),
+    DIGEST_DISABLE(new boolean[]{
+            false, false, false, false, false, false, false, false, false, false,
+            false, false, false, false, false, false, true, true, true, true,
+            false, false, false, false, false, false, true, true, false
+    }, 0, false),
+    AES_DISABLE(new boolean[]{
+            true, false, false, true, false, false, false, false, false, false,
+            false, false, false, false, false, false, true, true, true, true,
+            false, false, false, false, false, false, true, true, false
+    }, 1, false),
+    SM4_DISABLE(new boolean[]{
+            true, false, false, true, false, false, false, false, false, false,
+            false, false, false, false, false, false, false, false, false, false,
+            false, false, false, false, false, false, true, true, false
+    }, 2, false),
+    HMAC_DISABLE(new boolean[]{
+            true, false, false, true, false, false, false, false, false, false,
+            false, false, false, false, false, false, true, true, true, true,
+            false, false, false, false, false, false, true, true, false
+    }, 3, false),
+    RSA_DISABLE(new boolean[]{
+            true, false, false, true, false, false, false, false, false, false,
+            false, false, false, false, false, false, true, true, true, true,
+            false, false, false, false, false, false, false, true, false
+    }, 4, false),
+    DH_DISABLE(new boolean[]{
+            true, false, false, true, false, false, false, false, false, false,
+            false, false, false, false, false, false, true, true, true, true,
+            false, false, false, false, false, false, true, false, false
+    }, 5, false),
+    EC_DISABLE(new boolean[]{
+            true, false, false, true, false, false, false, false, false, false,
+            false, false, false, false, false, false, true, true, true, true,
+            false, false, false, false, false, false, true, true, false
+    }, 6, false),
+    ALL_DISABLE(new boolean[]{
+            false, false, false, false, false, false, false, false, false, false,
+            false, false, false, false, false, false, false, false, false, false,
+            false, false, false, false, false, false, false, false, false
+    }, false);
+    private final boolean[] expectedResult;
+    private final Integer propertyNameIndex;
+    private final boolean enable;
+    private static final Map<String, Mode> modeMap = new HashMap<>();
+
+    static {
+      Mode[] modes = Mode.values();
+      for (Mode mode : modes) {
+        if (mode.propertyNameIndex != null) {
+          modeMap.put(PROPERTY_NAMES[mode.propertyNameIndex] + ":" + mode.enable, mode);
+        }
+      }
+      modeMap.put("default", DEFAULT);
+      modeMap.put("disable", ALL_DISABLE);
+      modeMap.put("enable", ALL_ENABLE);
+    }
+
+    Mode(boolean[] expectedResult) {
+      this(expectedResult, false);
+    }
+
+    Mode(boolean[] expectedResult, boolean enable) {
+      this(expectedResult, null, enable);
+    }
+
+    Mode(boolean[] expectedResult, Integer propertyNameIndex, boolean enable) {
+      this.expectedResult = expectedResult;
+      this.propertyNameIndex = propertyNameIndex;
+      this.enable = enable;
+    }
+
+    static Mode getMode(String name, Boolean enable) {
+      return modeMap.get(name + ":" + enable);
+    }
+
+    static Mode getMode(String key) {
+      return modeMap.get(key);
+    }
+  }
+
+  private static final String KAE_LOG_PATH = System.getProperty("user.dir") +
+          File.separator + "kae.log";
+
+  private static final String[] PROPERTY_NAMES = new String[]{
+          "kae.digest.useKaeEngine",
+          "kae.aes.useKaeEngine",
+          "kae.sm4.useKaeEngine",
+          "kae.hmac.useKaeEngine",
+          "kae.rsa.useKaeEngine",
+          "kae.dh.useKaeEngine",
+          "kae.ec.useKaeEngine"
+  };
+
+  private static final List<File> files = new ArrayList<>();
+
+  public static void main(String[] args) throws IOException {
+    KAETestHelper.Engine engine = KAETestHelper.getEngine();
+    if (!engine.isValid()) {
+      System.out.println("Skip test, engine " + engine.getEngineId() + " does not exist.");
+      return;
+    }
+    Mode mode = getMode();
+    if (mode == null) {
+      throw new RuntimeException("test failed: mode is null");
+    }
+
+    try {
+      new KAEProvider();
+      test(mode, engine);
+    } finally {
+      KAETestHelper.cleanUp(files);
+    }
+  }
+
+  private static Mode getMode() {
+    String value = System.getProperty("all.test");
+    if (value != null) {
+      return Mode.getMode(value);
+    }
+    for (String propertyName : PROPERTY_NAMES) {
+      String property = System.getProperty(propertyName);
+      Boolean enable = null;
+      if (property != null) {
+        enable = Boolean.valueOf(property);
+      }
+      Mode mode = Mode.getMode(propertyName, enable);
+      if (mode != null) {
+        return mode;
+      }
+    }
+    return null;
+  }
+
+  private static void test(Mode mode, KAETestHelper.Engine engine) throws IOException {
+    File file = new File(KAE_LOG_PATH);
+    files.add(file);
+    boolean[] kaeUseEngineFlags = KAETestHelper.parseLog(engine, file);
+    if (!Arrays.equals(mode.expectedResult, kaeUseEngineFlags)) {
+      throw new RuntimeException("test failed : expected : " + Arrays.toString(mode.expectedResult) + "," +
+              "actual:" + Arrays.toString(kaeUseEngineFlags));
+    }
+  }
+}
\ No newline at end of file
diff --git a/test/jdk/org/openeuler/security/openssl/KaeDebugLogTest.java b/test/jdk/org/openeuler/security/openssl/KaeDebugLogTest.java
new file mode 100644
index 000000000..7bffbd6ec
--- /dev/null
+++ b/test/jdk/org/openeuler/security/openssl/KaeDebugLogTest.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import org.openeuler.security.openssl.KAEProvider;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.SecretKeySpec;
+import java.io.PrintStream;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.security.Security;
+import java.util.Objects;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+/**
+ * @test
+ * @summary test for KaeDebugLogTest
+ * @modules jdk.crypto.kaeprovider/org.openeuler.security.openssl
+ * @requires os.arch=="aarch64"
+ * @run main/othervm -Djava.security.debug=kae -Dkae.sm4.maxChunkSize=65536 KaeDebugLogTest
+ * @run main/othervm -Djava.security.debug=kae KaeDebugLogTest
+ * @run main/othervm -Djava.security.auth.debug=kae KaeDebugLogTest
+ * @run main/othervm KaeDebugLogTest
+ */
+
+public class KaeDebugLogTest {
+
+    private static final PrintStream err = System.err;
+
+    public static void main(String[] args) throws Exception {
+        PrintStream printStream = new PrintStream("kaetest.out");
+        System.setErr(printStream);
+        testDebugLog();
+        System.setErr(printStream);
+        testSm4ChunkSize();
+    }
+
+    public static void testDebugLog() throws Exception {
+        new KAEProvider();
+        Stream<String> lines = Files.lines(Paths.get("kaetest.out"));
+        System.setErr(err);
+        String content = lines.collect(Collectors.joining(System.lineSeparator()));
+        if(("kae".equals(System.getProperty("java.security.debug"))
+                || "kae".equals(System.getProperty("java.security..auth.debug")))
+                && !content.contains("reading kae properties file:")){
+            throw new RuntimeException("KaeDebugLogTest Failed! Failed to set the debug log.");
+        }
+        lines.close();
+    }
+
+    public static void testSm4ChunkSize() throws Exception {
+        Security.insertProviderAt(new KAEProvider(), 1);
+        Cipher cipher = Cipher.getInstance("SM4");
+        cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec("sm4EncryptionKey".getBytes(StandardCharsets.UTF_8), "SM4"));
+        Stream<String> lines = Files.lines(Paths.get("kaetest.out"));
+        System.setErr(err);
+        String content = lines.collect(Collectors.joining(System.lineSeparator()));
+        String log = "The configured chunk size is " + System.getProperty("kae.sm4.maxChunkSize");
+        if(("kae".equals(System.getProperty("java.security.debug"))
+                || "kae".equals(System.getProperty("java.security..auth.debug")))
+                && Objects.nonNull(System.getProperty("kae.sm4.maxChunkSize")) &&!content.contains(log)){
+            throw new RuntimeException("KaeDebugLogTest Failed! Failed to set the kae.sm4.maxChunkSize = " + System.getProperty("kae.sm4.maxChunkSize"));
+        }
+        lines.close();
+    }
+
+}
diff --git a/test/jdk/org/openeuler/security/openssl/KaeProviderTest.java b/test/jdk/org/openeuler/security/openssl/KaeProviderTest.java
new file mode 100644
index 000000000..0f4425b6d
--- /dev/null
+++ b/test/jdk/org/openeuler/security/openssl/KaeProviderTest.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import org.openeuler.security.openssl.KAEProvider;
+
+import javax.crypto.Cipher;
+import javax.crypto.Mac;
+import javax.crypto.NoSuchPaddingException;
+import java.security.KeyPairGenerator;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.Security;
+
+/**
+ * @test
+ * @requires os.arch=="aarch64"
+ * @modules jdk.crypto.kaeprovider/org.openeuler.security.openssl
+ * @summary test for KaeProviderTest
+ * @run main/othervm KaeProviderTest
+ * @run main/othervm KaeProviderTest true
+ * @run main/othervm KaeProviderTest false
+ * @run main/othervm KaeProviderTest wrong
+ */
+
+public class KaeProviderTest {
+
+  private static final String[] algorithmKaeProviderPropertyNames = new String[]{
+          "kae.md5",
+          "kae.sha256",
+          "kae.sha384",
+          "kae.sm3",
+          "kae.aes",
+          "kae.sm4",
+          "kae.hmac",
+          "kae.rsa",
+          "kae.dh",
+          "kae.ec"
+  };
+
+  private static final String KAE = "KAEProvider";
+
+  public static void main(String[] args) throws Exception {
+    initProperty(args);
+    Security.insertProviderAt(new KAEProvider(), 1);
+    testALL();
+  }
+
+  private static void initProperty(String[] args) {
+    if (args.length <= 0) {
+      return;
+    }
+    String value = args[0];
+    for (String name : algorithmKaeProviderPropertyNames){
+      System.setProperty(name,value);
+    }
+  }
+
+  public static void testALL() throws Exception {
+    testMd5();
+    testSha256();
+    testSha384();
+    testSm3();
+    testAes();
+    testSm4();
+    testHmac();
+    testRsa();
+    testDh();
+    testEc();
+  }
+
+  public static void testMd5() throws NoSuchAlgorithmException {
+    MessageDigest messageDigest = MessageDigest.getInstance("MD5");
+    judge("kae.md5",messageDigest.getProvider().getName());
+
+  }
+
+  public static void testSha256() throws NoSuchAlgorithmException {
+    MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
+    judge("kae.sha256",messageDigest.getProvider().getName());
+  }
+
+  public static void testSha384() throws NoSuchAlgorithmException {
+    MessageDigest messageDigest = MessageDigest.getInstance("SHA-384");
+    judge("kae.sha384",messageDigest.getProvider().getName());
+  }
+
+  public static void testSm3() throws NoSuchAlgorithmException {
+    try{
+      MessageDigest messageDigest = MessageDigest.getInstance("SM3");
+      judge("kae.sm3",messageDigest.getProvider().getName());
+    }catch (NoSuchAlgorithmException e){
+      if(Boolean.parseBoolean(System.getProperty("kae.sm3"))){
+        throw e;
+      }
+    }
+  }
+
+  public static void testAes() throws NoSuchAlgorithmException, NoSuchPaddingException {
+    Cipher cipher = Cipher.getInstance("AES");
+    judge("kae.aes",cipher.getProvider().getName());
+  }
+
+  public static void testSm4() throws NoSuchAlgorithmException, NoSuchPaddingException {
+    try{
+      Cipher cipher = Cipher.getInstance("SM4");
+      judge("kae.sm4",cipher.getProvider().getName());
+    }catch (NoSuchAlgorithmException e){
+      if(Boolean.parseBoolean(System.getProperty("kae.sm4"))){
+        throw e;
+      }
+    }
+  }
+
+  public static void testHmac() throws NoSuchAlgorithmException {
+    Mac mac = Mac.getInstance("HmacMD5");
+    judge("kae.hmac",mac.getProvider().getName());
+  }
+
+  public static void testRsa() throws NoSuchAlgorithmException, NoSuchPaddingException {
+    Cipher cipher = Cipher.getInstance("RSA");
+    judge("kae.rsa",cipher.getProvider().getName());
+  }
+
+  public static void testDh() throws NoSuchAlgorithmException {
+    KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("DH");
+    judge("kae.dh",keyPairGenerator.getProvider().getName());
+  }
+
+  public static void testEc() throws NoSuchAlgorithmException {
+    KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC");
+    judge("kae.ec",keyPairGenerator.getProvider().getName());
+  }
+
+  private static void judge(String algorithm , String providerName){
+    String value = System.getProperty(algorithm);
+    if (value == null) {
+      if (!KAE.equals(providerName)) {
+        throw new RuntimeException("KaeProviderTest Failed! default Provider.name is not right!");
+      }
+    } else {
+      if (Boolean.parseBoolean(value) && !KAE.equals(providerName)) {
+        throw new RuntimeException("KaeProviderTest Failed! " + algorithm + " is " + value + "," +
+                " Provider.name is not right!");
+      }
+      if (!Boolean.parseBoolean(value) && KAE.equals(providerName)) {
+        throw new RuntimeException("KaeProviderTest Failed! " + algorithm + " is " + value + ", " +
+                " Provider.name is not right!");
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/test/jdk/org/openeuler/security/openssl/RSATest.java b/test/jdk/org/openeuler/security/openssl/RSATest.java
new file mode 100644
index 000000000..8a787e1f7
--- /dev/null
+++ b/test/jdk/org/openeuler/security/openssl/RSATest.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import org.openeuler.security.openssl.KAEProvider;
+
+import java.nio.charset.StandardCharsets;
+import java.security.Security;
+import java.security.spec.AlgorithmParameterSpec;
+import javax.crypto.Cipher;
+import javax.crypto.KeyGenerator;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.IvParameterSpec;
+
+/**
+ * @test
+ * @summary Basic test for AES
+ * @modules jdk.crypto.kaeprovider/org.openeuler.security.openssl
+ * @requires os.arch=="aarch64"
+ * @run main AESTest
+ */
+
+public class AESTest {
+  private static final String[] ALGORITHM = {"AES", "AES_128", "AES_192", "AES_256"};
+  private static final String[] MODES = {"ECB", "CBC", "CTR", "GCM"};
+  private static final String[] PADDING = {"NoPadding", "PKCS5Padding"};
+  private static final int AES_128_KEY_LENGTH = 128;
+  private static final int AES_192_KEY_LENGTH = 192;
+  private static final int AES_256_KEY_LENGTH = 256;
+  private static String plainText = "helloworldhellow"; // 16bytes for NoPadding
+  private static String shortPlainText = "helloworld"; // 5 bytes for padding
+
+  public static void main(String[] args) throws Exception {
+    Security.insertProviderAt(new KAEProvider(), 1);
+    for (String algo : ALGORITHM) {
+      for (String mode : MODES) {
+        int padKinds = 2;
+        if (mode.equalsIgnoreCase("CTR")) {
+          padKinds = 1;
+        }
+        for (int k = 0; k < padKinds; k++) {
+          test(algo, mode, PADDING[k]);
+        }
+      }
+    }
+  }
+
+  public static void test(String algo, String mo, String pad) throws Exception {
+    AlgorithmParameterSpec aps = null;
+
+    Cipher cipher = Cipher.getInstance(algo + "/" + mo + "/" + pad);
+
+    KeyGenerator kg = KeyGenerator.getInstance("AES");
+    if (algo.equalsIgnoreCase("AES_192")) {
+      kg.init(AES_192_KEY_LENGTH);
+    } else if (algo.equalsIgnoreCase("AES_256")) {
+      kg.init(AES_256_KEY_LENGTH);
+    } else {
+      kg.init(AES_128_KEY_LENGTH);
+    }
+
+    SecretKey key = kg.generateKey();
+
+    // encrypt
+    if (!mo.equalsIgnoreCase("GCM")) {
+      cipher.init(Cipher.ENCRYPT_MODE, key, aps);
+    } else {
+      cipher.init(Cipher.ENCRYPT_MODE, key);
+    }
+
+    String cipherString = null;
+    if (!pad.equalsIgnoreCase("NoPadding")) {
+      cipherString = shortPlainText;
+    } else {
+      cipherString = plainText;
+    }
+    byte[] cipherText = cipher.doFinal(cipherString.getBytes(StandardCharsets.UTF_8));
+    if (!mo.equalsIgnoreCase("ECB")) {
+      aps = new IvParameterSpec(cipher.getIV());
+    } else {
+      aps = null;
+    }
+
+    if (!mo.equalsIgnoreCase("GCM")) {
+      cipher.init(Cipher.DECRYPT_MODE, key, aps);
+    } else {
+      cipher.init(Cipher.DECRYPT_MODE, key, cipher.getParameters());
+    }
+
+    String decryptPlainText = new String(cipher.doFinal(cipherText));
+
+    if (!cipherString.equals(decryptPlainText)) {
+      throw new RuntimeException("aes decryption failed, algo = " + algo + ", mo = " + mo + ", pad = " + pad);
+    }
+  }
+}
\ No newline at end of file
diff --git a/test/jdk/org/openeuler/security/openssl/SM3Test.java b/test/jdk/org/openeuler/security/openssl/SM3Test.java
new file mode 100644
index 000000000..e1c5346c9
--- /dev/null
+++ b/test/jdk/org/openeuler/security/openssl/SM3Test.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import org.openeuler.security.openssl.KAEProvider;
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+import java.security.MessageDigest;
+import java.security.Security;
+
+/**
+ * @test
+ * @summary Basic test for sm3
+ * @modules jdk.crypto.kaeprovider/org.openeuler.security.openssl
+ * @run main SM3Test
+ */
+
+public class SM3Test {
+
+    private static String plainText = "helloworldhellow";
+
+    public static void main(String[] args) throws Exception {
+        Security.insertProviderAt(new KAEProvider(), 1);
+        test(plainText, "SM3", new byte[]{40, -103, -71, 4, -80, -49, 94, 112, 11, -75, -66, 121, 63, 80, 62, -14, -45, -75, -34, 66, -77, -34, -26, 26, 33, -23, 45, 52, -74, 67, -18, 118});
+    }
+
+    public static void test(String plainText, String algo, byte[] expectRes) throws Exception {
+       MessageDigest md = MessageDigest.getInstance(algo);
+       md.update(plainText.getBytes(StandardCharsets.UTF_8));
+       byte[] res = md.digest();
+       if (!Arrays.equals(res, expectRes)) {
+           throw new RuntimeException("sm3 failed");
+       }
+    }
+
+}
diff --git a/test/jdk/org/openeuler/security/openssl/SM4Test.java b/test/jdk/org/openeuler/security/openssl/SM4Test.java
new file mode 100644
index 000000000..ac81831ba
--- /dev/null
+++ b/test/jdk/org/openeuler/security/openssl/SM4Test.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import org.openeuler.security.openssl.KAEProvider;
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+import java.security.Security;
+import javax.crypto.Cipher;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+
+/**
+ * @test
+ * @summary Basic test for sm4
+ * @modules jdk.crypto.kaeprovider/org.openeuler.security.openssl
+ * @run main SM4Test
+ */
+
+public class SM4Test {
+
+  private static SecretKeySpec ks = new SecretKeySpec("sm4EncryptionKey".getBytes(StandardCharsets.UTF_8), "SM4");  // key has 16 bytes
+  private static IvParameterSpec iv = new IvParameterSpec("abcdefghabcdefgh".getBytes(StandardCharsets.UTF_8)); // iv has 16 bytes
+  private static IvParameterSpec shortIv = new IvParameterSpec("abcdefgh".getBytes(StandardCharsets.UTF_8)); // CTR support >= 8bytes iv
+  private static String plainText = "helloworldhellow";  // 16bytes for NoPadding
+  private static String shortPlainText = "helloworld"; // 5 bytes for padding
+
+  public static void main(String[] args) throws Exception {
+    Security.insertProviderAt(new KAEProvider(), 1);
+    test(plainText, "SM4/CBC/NOPADDING", new byte[]{86, 69, 47, -115, -63, 54, 35, 24, -2, 114, 113, 102, 82, 20, 69, 59});
+    test(shortPlainText, "SM4/CBC/PKCS5Padding", new byte[]{10, 105, 75, -80, -85, -68, 13, -53, 42, 91, -64, 99, 104, 35, -85, 8});
+    test(plainText, "SM4/ECB/NOPADDING", new byte[]{103, 36, -31, -53, -109, -12, -71, -79, -54, 106, 10, -3, -35, -22, -122, -67});
+    test(shortPlainText, "SM4/ECB/PKCS5Padding", new byte[]{-10, 99, -9, 90, 58, -36, -109, 54, -55, -52, 7, -49, 110, -88, 72, 40});
+    test(plainText, "SM4/CTR/NOPADDING", new byte[]{32, 108, 35, 108, -16, 119, -111, 114, 94, 110, -100, -113, -46, -29, -11, 71});
+    test(plainText, "SM4/OFB/NOPADDING", new byte[]{32, 108, 35, 108, -16, 119, -111, 114, 94, 110, -100, -113, -46, -29, -11, 71});
+    test(shortPlainText, "SM4/OFB/PKCS5Padding", new byte[]{32, 108, 35, 108, -16, 119, -111, 114, 94, 110});
+
+    testCtrShortIv(plainText, "SM4/CTR/NOPADDING", new byte[]{-13, 73, 40, -36, -64, -67, 75, -72, 90, 58, 73, -4, -36, 115, 126, -48});
+
+    testByteBuffer(plainText, "SM4/CBC/NOPADDING", new byte[]{86, 69, 47, -115, -63, 54, 35, 24, -2, 114, 113, 102, 82, 20, 69, 59});
+    testByteBuffer(shortPlainText, "SM4/CBC/PKCS5Padding", new byte[]{10, 105, 75, -80, -85, -68, 13, -53, 42, 91, -64, 99, 104, 35, -85, 8});
+    testByteBuffer(plainText, "SM4/ECB/NOPADDING", new byte[]{103, 36, -31, -53, -109, -12, -71, -79, -54, 106, 10, -3, -35, -22, -122, -67});
+    testByteBuffer(shortPlainText, "SM4/ECB/PKCS5Padding", new byte[]{-10, 99, -9, 90, 58, -36, -109, 54, -55, -52, 7, -49, 110, -88, 72, 40});
+    testByteBuffer(plainText, "SM4/CTR/NOPADDING", new byte[]{32, 108, 35, 108, -16, 119, -111, 114, 94, 110, -100, -113, -46, -29, -11, 71});
+    testByteBuffer(plainText, "SM4/OFB/NOPADDING", new byte[]{32, 108, 35, 108, -16, 119, -111, 114, 94, 110, -100, -113, -46, -29, -11, 71});
+    testByteBuffer(shortPlainText, "SM4/OFB/PKCS5Padding", new byte[]{32, 108, 35, 108, -16, 119, -111, 114, 94, 110});
+
+    System.setProperty("kae.sm4.maxChunkSize", "65536");
+    testByteBuffer(plainText, "SM4/CBC/NOPADDING", new byte[]{86, 69, 47, -115, -63, 54, 35, 24, -2, 114, 113, 102, 82, 20, 69, 59});
+    testByteBuffer(shortPlainText, "SM4/CBC/PKCS5Padding", new byte[]{10, 105, 75, -80, -85, -68, 13, -53, 42, 91, -64, 99, 104, 35, -85, 8});
+    testByteBuffer(plainText, "SM4/ECB/NOPADDING", new byte[]{103, 36, -31, -53, -109, -12, -71, -79, -54, 106, 10, -3, -35, -22, -122, -67});
+    testByteBuffer(shortPlainText, "SM4/ECB/PKCS5Padding", new byte[]{-10, 99, -9, 90, 58, -36, -109, 54, -55, -52, 7, -49, 110, -88, 72, 40});
+    testByteBuffer(plainText, "SM4/CTR/NOPADDING", new byte[]{32, 108, 35, 108, -16, 119, -111, 114, 94, 110, -100, -113, -46, -29, -11, 71});
+    testByteBuffer(plainText, "SM4/OFB/NOPADDING", new byte[]{32, 108, 35, 108, -16, 119, -111, 114, 94, 110, -100, -113, -46, -29, -11, 71});
+    testByteBuffer(shortPlainText, "SM4/OFB/PKCS5Padding", new byte[]{32, 108, 35, 108, -16, 119, -111, 114, 94, 110});
+  }
+
+  public static void test(String plainText, String algo, byte[] expectRes) throws Exception {
+    Cipher encryptCipher = Cipher.getInstance(algo);
+    if (algo.contains("ECB")) {
+      encryptCipher.init(Cipher.ENCRYPT_MODE, ks);
+    } else {
+      encryptCipher.init(Cipher.ENCRYPT_MODE, ks, iv);
+    }
+    byte[] cipherText = encryptCipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));
+    if (!Arrays.equals(cipherText, expectRes)) {
+      throw new RuntimeException("sm4 encryption failed, algo = " + algo);
+    }
+
+    Cipher decryptCipher = Cipher.getInstance(algo);
+    decryptCipher.init(Cipher.DECRYPT_MODE, ks, encryptCipher.getParameters());
+    String decryptPlainText = new String(decryptCipher.doFinal(cipherText));
+    if (!plainText.equals(decryptPlainText)) {
+      throw new RuntimeException("sm4 decryption failed, algo = " + algo);
+    }
+  }
+
+  public static void testCtrShortIv(String plainText, String algo, byte[] expectRes) throws Exception {
+    Cipher encryptCipher = Cipher.getInstance(algo);
+    encryptCipher.init(Cipher.ENCRYPT_MODE, ks, shortIv);
+    byte[] cipherText = encryptCipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));
+    if (!Arrays.equals(cipherText, expectRes)) {
+      throw new RuntimeException("sm4 encryption failed, algo = " + algo);
+    }
+
+    Cipher decryptCipher = Cipher.getInstance(algo);
+    decryptCipher.init(Cipher.DECRYPT_MODE, ks, encryptCipher.getParameters());
+    String decryptPlainText = new String(decryptCipher.doFinal(cipherText));
+    if (!plainText.equals(decryptPlainText)) {
+      throw new RuntimeException("sm4 decryption failed, algo = " + algo);
+    }
+  }
+
+  public static void testByteBuffer(String plainText, String algo, byte[] expectRes) throws Exception {
+    // encrypt
+    Cipher encryptCipher = Cipher.getInstance(algo);
+    if (algo.contains("ECB")) {
+      encryptCipher.init(Cipher.ENCRYPT_MODE, ks);
+    } else {
+      encryptCipher.init(Cipher.ENCRYPT_MODE, ks, iv);
+    }
+    int inputLen = plainText.length();
+    ByteBuffer sourceByteBuffer = ByteBuffer.allocateDirect(inputLen);
+    sourceByteBuffer.put(plainText.getBytes());
+    sourceByteBuffer.flip();
+    int outputLen = encryptCipher.getOutputSize(inputLen);
+    ByteBuffer encryptedByteBuffer = ByteBuffer.allocate(outputLen);
+    encryptCipher.doFinal(sourceByteBuffer,encryptedByteBuffer);
+    encryptedByteBuffer.flip();
+    byte[] encryptedBytes = new byte[encryptedByteBuffer.limit()];
+    encryptedByteBuffer.get(encryptedBytes);
+    if (!Arrays.equals(encryptedBytes, expectRes)) {
+      throw new RuntimeException("sm4 encryption failed, algo = " + algo);
+    }
+    sourceByteBuffer.clear();
+    encryptedByteBuffer.flip();
+
+    // decrypt
+    Cipher decryptCipher = Cipher.getInstance(algo);
+    decryptCipher.init(Cipher.DECRYPT_MODE, ks, encryptCipher.getParameters());
+    outputLen = decryptCipher.getOutputSize(encryptedBytes.length);
+    ByteBuffer decryptedByteBuffer = ByteBuffer.allocate(outputLen);
+    decryptCipher.doFinal(encryptedByteBuffer, decryptedByteBuffer);
+    decryptedByteBuffer.flip();
+    byte[] decryptedBytes = new byte[decryptedByteBuffer.limit()];
+    decryptedByteBuffer.get(decryptedBytes);
+    if (!Arrays.equals(plainText.getBytes(), decryptedBytes)) {
+      throw new RuntimeException("sm4 decryption failed, algo = " + algo);
+    }
+    encryptedByteBuffer.clear();
+    decryptedByteBuffer.clear();
+  }
+}
\ No newline at end of file
diff --git a/test/jdk/sun/security/jca/PreferredProviderNegativeTest.java b/test/jdk/sun/security/jca/PreferredProviderNegativeTest.java
index cd74b5164..52cfbab4e 100644
--- a/test/jdk/sun/security/jca/PreferredProviderNegativeTest.java
+++ b/test/jdk/sun/security/jca/PreferredProviderNegativeTest.java
@@ -107,7 +107,12 @@ public class PreferredProviderNegativeTest {
 
         String expected;
         String value = args[1];
-        expected = System.getProperty("test.provider.name", "SunJCE");
+
+        if (Security.getProperty("security.provider.1").equals("KAEProvider")) {
+            expected = "KAEProvider";
+        } else {
+            expected = "SunJCE";
+        }
 
         if (args.length >= 2) {
             switch (args[0]) {
diff --git a/test/jdk/sun/security/krb5/auto/BasicProc.java b/test/jdk/sun/security/krb5/auto/BasicProc.java
index 0ba0b907b..c67efa446 100644
--- a/test/jdk/sun/security/krb5/auto/BasicProc.java
+++ b/test/jdk/sun/security/krb5/auto/BasicProc.java
@@ -298,7 +298,9 @@ public class BasicProc {
         Proc p = Proc.create("BasicProc")
                 .inheritProp("jdk.net.hosts.file")
                 .prop("java.security.manager", "")
-                .perm(new javax.security.auth.AuthPermission("doAs"));
+                .perm(new javax.security.auth.AuthPermission("doAs"))
+                .perm(new java.util.PropertyPermission(
+                            "kae.disableKaeDispose", "read"));
         if (lib != null) {
             p.env("KRB5_CONFIG", CONF)
                     .env("KRB5_TRACE", Platform.isWindows() ? "CON" : "/dev/stderr")
diff --git a/test/jdk/sun/security/pkcs11/Secmod/policy b/test/jdk/sun/security/pkcs11/Secmod/policy
index e4c95ca6d..60488fd06 100644
--- a/test/jdk/sun/security/pkcs11/Secmod/policy
+++ b/test/jdk/sun/security/pkcs11/Secmod/policy
@@ -3,4 +3,5 @@ grant {
     permission java.io.FilePermission "${test.src}/-", "read";
     permission java.io.FilePermission "${pkcs11test.nss.db}/-", "read";
     permission java.io.FilePermission "${pkcs11test.nss.libdir}/-", "read";
+    permission java.util.PropertyPermission "kae.disableKaeDispose", "read";
 };
\ No newline at end of file
diff --git a/test/jdk/sun/security/pkcs11/policy b/test/jdk/sun/security/pkcs11/policy
index d5a78b6ba..42d22643e 100644
--- a/test/jdk/sun/security/pkcs11/policy
+++ b/test/jdk/sun/security/pkcs11/policy
@@ -1,4 +1,5 @@
 grant {
     permission java.lang.RuntimePermission "setSecurityManager";
     permission java.util.PropertyPermission "test.provider.name", "read";
+    permission java.util.PropertyPermission "kae.disableKaeDispose", "read";
 };
diff --git a/test/jdk/sun/security/ssl/CipherSuite/DisabledCurve.java b/test/jdk/sun/security/ssl/CipherSuite/DisabledCurve.java
index 26304c5df..ca618ccfe 100644
--- a/test/jdk/sun/security/ssl/CipherSuite/DisabledCurve.java
+++ b/test/jdk/sun/security/ssl/CipherSuite/DisabledCurve.java
@@ -91,6 +91,10 @@ public class DisabledCurve extends SSLSocketTemplate {
     }
 
     public static void main(String[] args) throws Exception {
+        // KAEProvider does not support sect283r1
+        if (Security.getProperty("security.provider.1").equals("KAEProvider")) {
+            return;
+        }
         String expected = args[1];
         String disabledName = ("DISABLE_NONE".equals(args[0]) ? "" : args[0]);
         boolean disabled = false;
diff --git a/test/jdk/sun/security/ssl/SSLSocketImpl/NotifyHandshakeTest.policy b/test/jdk/sun/security/ssl/SSLSocketImpl/NotifyHandshakeTest.policy
index b426b173f..6f65e48a3 100644
--- a/test/jdk/sun/security/ssl/SSLSocketImpl/NotifyHandshakeTest.policy
+++ b/test/jdk/sun/security/ssl/SSLSocketImpl/NotifyHandshakeTest.policy
@@ -33,5 +33,7 @@ grant codeBase "file:com.jar" {
 	"javax.net.ssl.trustStore", "write";
     permission java.util.PropertyPermission
 	"javax.net.ssl.trustStorePassword", "write";
+    permission java.util.PropertyPermission
+	"kae.disableKaeDispose", "read";
 };
 
diff --git a/test/micro/org/openeuler/bench/security/openssl/AESBenchmark.java b/test/micro/org/openeuler/bench/security/openssl/AESBenchmark.java
new file mode 100644
index 000000000..8a6e5658d
--- /dev/null
+++ b/test/micro/org/openeuler/bench/security/openssl/AESBenchmark.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.openeuler.bench.security.openssl;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Param;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.Warmup;
+
+import java.security.InvalidKeyException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.NoSuchAlgorithmException;
+import java.security.Provider;
+import java.security.Security;
+import java.util.concurrent.TimeUnit;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.spec.SecretKeySpec;
+
+@Warmup(iterations = 10, time = 2, timeUnit = TimeUnit.SECONDS)
+public class AESBenchmark extends BenchmarkBase {
+
+    @Param({"AES/ECB/PKCS5Padding", "AES/ECB/NoPadding", "AES/CBC/NoPadding", "AES/CBC/PKCS5Padding", "AES/CTR/NoPadding"})
+    private String algorithm;
+
+    @Param({"128", "192", "256"})
+    private int keyLength;
+
+    @Param({"" + 1024, "" + 10 * 1024, "" + 100 * 1024, "" + 1024 * 1024})
+    private int dataSize;
+
+    private byte[][] encryptedData;
+    private Cipher encryptCipher;
+    private Cipher decryptCipher;
+
+    @Setup
+    public void setup() throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
+            InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
+        setupProvider();
+
+        byte[] keystring = fillSecureRandom(new byte[keyLength / 8]);
+        SecretKeySpec ks = new SecretKeySpec(keystring, "AES");
+
+        encryptCipher = (prov == null) ? Cipher.getInstance(algorithm) : Cipher.getInstance(algorithm, prov);
+        encryptCipher.init(Cipher.ENCRYPT_MODE, ks);
+        decryptCipher = (prov == null) ? Cipher.getInstance(algorithm) : Cipher.getInstance(algorithm, prov);
+        decryptCipher.init(Cipher.DECRYPT_MODE, ks, encryptCipher.getParameters());
+
+        data = fillRandom(new byte[SET_SIZE][dataSize]);
+        encryptedData = fillEncrypted(data, encryptCipher);
+    }
+
+    @Benchmark
+    public byte[] encrypt() throws IllegalBlockSizeException, BadPaddingException {
+        byte[] d = data[index];
+        index = (index + 1) % SET_SIZE;
+        return encryptCipher.doFinal(d);
+    }
+
+    @Benchmark
+    @Fork(jvmArgsPrepend = {"-Xms100G", "-Xmx100G", "-XX:+AlwaysPreTouch", "-Dkae.disableKaeDispose=true"}, value = 5)
+    public byte[] encryptDispose() throws IllegalBlockSizeException, BadPaddingException {
+        byte[] d = data[index];
+        index = (index + 1) % SET_SIZE;
+        return encryptCipher.doFinal(d);
+    }
+
+    @Benchmark
+    public byte[] decrypt() throws IllegalBlockSizeException, BadPaddingException {
+        byte[] e = encryptedData[index];
+        index = (index + 1) % SET_SIZE;
+        return decryptCipher.doFinal(e);
+    }
+
+    @Benchmark
+    @Fork(jvmArgsPrepend = {"-Xms100G", "-Xmx100G", "-XX:+AlwaysPreTouch", "-Dkae.disableKaeDispose=true"}, value = 5)
+    public byte[] decryptDispose() throws IllegalBlockSizeException, BadPaddingException {
+        byte[] e = encryptedData[index];
+        index = (index + 1) % SET_SIZE;
+        return decryptCipher.doFinal(e);
+    }
+}
+
diff --git a/test/micro/org/openeuler/bench/security/openssl/AESGCMBenchmark.java b/test/micro/org/openeuler/bench/security/openssl/AESGCMBenchmark.java
new file mode 100644
index 000000000..222405235
--- /dev/null
+++ b/test/micro/org/openeuler/bench/security/openssl/AESGCMBenchmark.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.openeuler.bench.security.openssl;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.Param;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.Fork;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.spec.GCMParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.spec.InvalidParameterSpecException;
+
+import java.security.Provider;
+
+
+public class AESGCMBenchmark extends BenchmarkBase{
+
+    @Param({"AES/GCM/NoPadding","AES/GCM/PKCS5Padding"})
+    private String algorithm;
+
+    @Param({"128", "192", "256"})
+    private int keyLength;
+
+    @Param({""+1024, "" + 10 * 1024, "" + 100 * 1024, "" + 1024 * 1024})
+    private int dataSize;
+
+    byte[] data;
+    byte[] encryptedData;
+    private Cipher encryptCipher;
+    private Cipher decryptCipher;
+    SecretKeySpec ks;
+    GCMParameterSpec gcm_spec;
+    byte[] aad;
+    byte[] iv;
+
+    public static final int IV_BUFFER_SIZE = 32;
+    public static final int IV_MODULO = IV_BUFFER_SIZE - 16;
+    int iv_index = 0;
+
+    private int next_iv_index() {
+        int r = iv_index;
+        iv_index = (iv_index + 1) % IV_MODULO;
+        return r;
+    }
+
+    @Setup
+    public void setup() throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException, InvalidParameterSpecException {
+        setupProvider();
+        assert algorithm.split("/")[1].compareToIgnoreCase("GCM") == 0;
+
+        byte[] keystring = fillSecureRandom(new byte[keyLength / 8]);
+        ks = new SecretKeySpec(keystring, "AES");
+        iv = fillSecureRandom(new byte[IV_BUFFER_SIZE]);
+        gcm_spec = new GCMParameterSpec(96, iv, next_iv_index(), 16);
+        aad = fillSecureRandom(new byte[5]);
+        encryptCipher = makeCipher(prov, algorithm);
+        encryptCipher.init(Cipher.ENCRYPT_MODE, ks, gcm_spec);
+        encryptCipher.updateAAD(aad);
+        decryptCipher = makeCipher(prov, algorithm);
+        decryptCipher.init(Cipher.DECRYPT_MODE, ks, encryptCipher.getParameters().getParameterSpec(GCMParameterSpec.class));
+        decryptCipher.updateAAD(aad);
+        data = fillRandom(new byte[dataSize]);
+        encryptedData = encryptCipher.doFinal(data);
+    }
+
+    @Benchmark
+    public byte[] encrypt() throws BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException, InvalidKeyException {
+        gcm_spec = new GCMParameterSpec(96, iv, next_iv_index(), 16);
+        encryptCipher.init(Cipher.ENCRYPT_MODE, ks, gcm_spec);
+        encryptCipher.updateAAD(aad);
+        return encryptCipher.doFinal(data);
+    }
+
+    @Benchmark
+    @Fork(jvmArgsPrepend = {"-Xms100G", "-Xmx100G", "-XX:+AlwaysPreTouch", "-Dkae.disableKaeDispose=true"}, value = 5)
+    public byte[] encrypt_arg() throws BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException, InvalidKeyException {
+        gcm_spec = new GCMParameterSpec(96, iv, next_iv_index(), 16);
+        encryptCipher.init(Cipher.ENCRYPT_MODE, ks, gcm_spec);
+        encryptCipher.updateAAD(aad);
+        return encryptCipher.doFinal(data);
+    }
+
+    @Benchmark
+    public byte[] decrypt() throws BadPaddingException, IllegalBlockSizeException, InvalidParameterSpecException, InvalidAlgorithmParameterException, InvalidKeyException {
+        decryptCipher.init(Cipher.DECRYPT_MODE, ks, gcm_spec);
+        decryptCipher.updateAAD(aad);
+        return decryptCipher.doFinal(encryptedData);
+    }
+
+    @Benchmark
+    @Fork(jvmArgsPrepend = {"-Xms100G", "-Xmx100G", "-XX:+AlwaysPreTouch", "-Dkae.disableKaeDispose=true"}, value = 5)
+    public byte[] decrypt_arg() throws BadPaddingException, IllegalBlockSizeException, InvalidParameterSpecException, InvalidAlgorithmParameterException, InvalidKeyException {
+        decryptCipher.init(Cipher.DECRYPT_MODE, ks, gcm_spec);
+        decryptCipher.updateAAD(aad);
+        return decryptCipher.doFinal(encryptedData);
+    }
+
+    public static Cipher makeCipher(Provider prov, String algorithm) throws NoSuchPaddingException, NoSuchAlgorithmException {
+        return (prov == null) ? Cipher.getInstance(algorithm) : Cipher.getInstance(algorithm, prov);
+    }
+}
+
diff --git a/test/micro/org/openeuler/bench/security/openssl/BenchmarkBase.java b/test/micro/org/openeuler/bench/security/openssl/BenchmarkBase.java
new file mode 100644
index 000000000..4e3e7f817
--- /dev/null
+++ b/test/micro/org/openeuler/bench/security/openssl/BenchmarkBase.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.openeuler.bench.security.openssl;
+
+import org.openeuler.security.openssl.KAEProvider;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Measurement;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Param;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.Threads;
+import org.openjdk.jmh.annotations.Warmup;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import java.security.Provider;
+import java.security.SecureRandom;
+import java.security.Security;
+import java.util.Random;
+import java.util.concurrent.TimeUnit;
+
+@BenchmarkMode(Mode.Throughput)
+@OutputTimeUnit(TimeUnit.SECONDS)
+@Warmup(iterations = 3, time = 3, timeUnit = TimeUnit.SECONDS)
+@Measurement(iterations = 8, time = 2, timeUnit = TimeUnit.SECONDS)
+@Fork(jvmArgsPrepend = {"-Xms100G", "-Xmx100G", "-XX:+AlwaysPreTouch"}, value = 5)
+@Threads(1)
+@State(Scope.Thread)
+public class BenchmarkBase {
+    public static final int SET_SIZE = 128;
+
+    byte[][] data;
+    int index = 0;
+
+    @Param({"", "KAEProvider"})
+    private String provider;
+
+    public Provider prov = null;
+
+    @Setup
+    public void setupProvider() {
+        Security.addProvider(new KAEProvider());
+        if (provider != null && !provider.isEmpty()) {
+            prov = Security.getProvider(provider);
+            if (prov == null) {
+                throw new RuntimeException("Can't find provider \"" + provider + "\"");
+            }
+        }
+    }
+
+    public static byte[][] fillRandom(byte[][] data) {
+        Random rnd = new Random();
+        for (byte[] d : data) {
+            rnd.nextBytes(d);
+        }
+        return data;
+    }
+
+    public static byte[] fillRandom(byte[] data) {
+        Random rnd = new Random();
+        rnd.nextBytes(data);
+        return data;
+    }
+
+    public static byte[] fillSecureRandom(byte[] data) {
+        SecureRandom rnd = new SecureRandom();
+        rnd.nextBytes(data);
+        return data;
+    }
+
+    public static byte[][] fillEncrypted(byte[][] data, Cipher encryptCipher)
+        throws IllegalBlockSizeException, BadPaddingException {
+        byte[][] encryptedData = new byte[data.length][];
+        for (int i = 0; i < encryptedData.length; i++) {
+            encryptedData[i] = encryptCipher.doFinal(data[i]);
+        }
+        return encryptedData;
+    }
+
+}
diff --git a/test/micro/org/openeuler/bench/security/openssl/DHKeyAgreementBenchMark.java b/test/micro/org/openeuler/bench/security/openssl/DHKeyAgreementBenchMark.java
new file mode 100644
index 000000000..eb5ece804
--- /dev/null
+++ b/test/micro/org/openeuler/bench/security/openssl/DHKeyAgreementBenchMark.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.openeuler.bench.security.openssl;
+
+import java.math.BigInteger;
+import java.security.*;
+import javax.crypto.*;
+import javax.crypto.spec.*;
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.Param;
+import org.openjdk.jmh.annotations.Setup;
+import java.util.concurrent.TimeUnit;
+import org.openjdk.jmh.annotations.Warmup;
+
+import java.security.KeyPairGenerator;
+
+public class DHKeyAgreementBenchMark extends BenchmarkBase {
+    @Param({"DH"})
+    private String algorithm;
+
+    @Param({"512", "1024", "2048", "3072", "4096"})
+    private int keySize;
+
+    private KeyPairGenerator aliceKpairGen;
+    private KeyPairGenerator bobKpairGen;
+    private KeyPairGenerator carolKpairGen;
+
+    private KeyPair aliceKpair;
+    private KeyPair bobKpair;
+    private KeyPair carolKpair;
+
+    private DHParameterSpec dhSkipParamSpec;
+
+    @Setup
+    public void setUp() throws Exception {
+        setupProvider();
+        aliceKpairGen = createKeyPairGenerator();
+        bobKpairGen = createKeyPairGenerator();
+        carolKpairGen = createKeyPairGenerator();
+
+        // Alice creates her own DH key pair
+        aliceKpairGen.initialize(keySize);
+        aliceKpair = aliceKpairGen.generateKeyPair();
+        // Bob creates his own DH key pair
+        bobKpairGen.initialize(keySize);
+        bobKpair = bobKpairGen.generateKeyPair();
+        // Carol creates her own DH key pair
+        carolKpairGen.initialize(keySize);
+        carolKpair = carolKpairGen.generateKeyPair();
+    }
+
+    @Benchmark
+    public void KeyAgreement() throws Exception {
+
+        // Alice initialize
+        KeyAgreement aliceKeyAgree = (prov == null ? KeyAgreement.getInstance("DH") : KeyAgreement.getInstance("DH", prov));
+        aliceKeyAgree.init(aliceKpair.getPrivate());
+        // Bob initialize
+        KeyAgreement bobKeyAgree =  (prov == null ? KeyAgreement.getInstance("DH") : KeyAgreement.getInstance("DH", prov));
+        bobKeyAgree.init(bobKpair.getPrivate());
+        // Carol initialize
+        KeyAgreement carolKeyAgree =  (prov == null ? KeyAgreement.getInstance("DH") : KeyAgreement.getInstance("DH", prov));
+        carolKeyAgree.init(carolKpair.getPrivate());
+        // Alice uses Carol's public key
+        Key ac = aliceKeyAgree.doPhase(carolKpair.getPublic(), false);
+        // Bob uses Alice's public key
+        Key ba = bobKeyAgree.doPhase(aliceKpair.getPublic(), false);
+        // Carol uses Bob's public key
+        Key cb = carolKeyAgree.doPhase(bobKpair.getPublic(), false);
+        // Alice uses Carol's result from above
+        aliceKeyAgree.doPhase(cb, true);
+        // Bob uses Alice's result from above
+        bobKeyAgree.doPhase(ac, true);
+        // Carol uses Bob's result from above
+        carolKeyAgree.doPhase(ba, true);
+
+        // Alice, Bob and Carol compute their secrets
+        byte[] aliceSharedSecret = aliceKeyAgree.generateSecret();
+        int aliceLen = aliceSharedSecret.length;
+
+        byte[] bobSharedSecret = bobKeyAgree.generateSecret();
+        int bobLen = bobSharedSecret.length;
+
+        byte[] carolSharedSecret = carolKeyAgree.generateSecret();
+        int carolLen = carolSharedSecret.length;
+
+        // Compare Alice and Bob
+        if (aliceLen != bobLen) {
+            throw new Exception("Alice and Bob have different lengths");
+        }
+        for (int i=0; i<aliceLen; i++) {
+            if (aliceSharedSecret[i] != bobSharedSecret[i]) {
+                throw new Exception("Alice and Bob differ");
+            }
+        }
+
+        // Compare Bob and Carol
+        if (bobLen != carolLen) {
+            throw new Exception("Bob and Carol have different lengths");
+        }
+        for (int i=0; i<bobLen; i++) {
+            if (bobSharedSecret[i] != carolSharedSecret[i]) {
+                throw new Exception("Bob and Carol differ");
+            }
+        }
+    }
+
+
+    private KeyPairGenerator createKeyPairGenerator() throws Exception {
+        if (prov != null) {
+            return KeyPairGenerator.getInstance(algorithm, prov);
+        }
+        return KeyPairGenerator.getInstance(algorithm);
+    }
+
+}
+
diff --git a/test/micro/org/openeuler/bench/security/openssl/DHKeyPairGeneratorBenchmark.java b/test/micro/org/openeuler/bench/security/openssl/DHKeyPairGeneratorBenchmark.java
new file mode 100644
index 000000000..4e9468a18
--- /dev/null
+++ b/test/micro/org/openeuler/bench/security/openssl/DHKeyPairGeneratorBenchmark.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.openeuler.bench.security.openssl;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.Param;
+import org.openjdk.jmh.annotations.Setup;
+import java.util.concurrent.TimeUnit;
+import org.openjdk.jmh.annotations.Warmup;
+
+import java.security.KeyPairGenerator;
+import java.security.KeyPair;
+
+public class DHKeyPairGeneratorBenchmark extends BenchmarkBase {
+    @Param({"DH"})
+    private String algorithm;
+
+    @Param({"512", "1024", "2048", "3072", "4096"})
+    private int keyLength;
+
+    private KeyPairGenerator keyPairGenerator;
+
+    @Setup
+    public void setUp() throws Exception {
+        setupProvider();
+        keyPairGenerator = createKeyPairGenerator();
+    }
+
+    @Benchmark
+    public KeyPair generateKeyPair() throws Exception {
+        keyPairGenerator.initialize(keyLength);
+        return keyPairGenerator.generateKeyPair();
+    }
+
+    private KeyPairGenerator createKeyPairGenerator() throws Exception {
+        if (prov != null) {
+            return KeyPairGenerator.getInstance(algorithm, prov);
+        }
+        return KeyPairGenerator.getInstance(algorithm);
+    }
+}
+
diff --git a/test/micro/org/openeuler/bench/security/openssl/DigestBenchmark.java b/test/micro/org/openeuler/bench/security/openssl/DigestBenchmark.java
new file mode 100644
index 000000000..c82897df0
--- /dev/null
+++ b/test/micro/org/openeuler/bench/security/openssl/DigestBenchmark.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.openeuler.bench.security.openssl;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Param;
+import org.openjdk.jmh.annotations.Setup;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.Provider;
+import java.security.Security;
+import java.util.concurrent.TimeUnit;
+
+public class DigestBenchmark extends BenchmarkBase {
+
+    @Param({"MD5", "SHA-256", "SHA-384"})
+    private String algorithm;
+
+    @Param({"" + 1024, "" + 10 * 1024, "" + 100 * 1024, "" + 1024 * 1024})
+    int dataSize;
+
+    MessageDigest md;
+
+    @Setup
+    public void setup() throws NoSuchAlgorithmException {
+        setupProvider();
+        data = fillRandom(new byte[SET_SIZE][dataSize]);
+        md = (prov == null) ? MessageDigest.getInstance(algorithm) : MessageDigest.getInstance(algorithm, prov);
+    }
+
+    @Benchmark
+    public byte[] digest() {
+        byte[] d = data[index];
+        index = (index + 1) % SET_SIZE;
+        return md.digest(d);
+    }
+
+    @Benchmark
+    @Fork(jvmArgsPrepend = {"-Xms100G", "-Xmx100G", "-XX:+AlwaysPreTouch", "-Dkae.disableKaeDispose=true"}, value = 5)
+    public byte[] digestDispose() {
+        byte[] d = data[index];
+        index = (index + 1) % SET_SIZE;
+        return md.digest(d);
+    }
+}
+
diff --git a/test/micro/org/openeuler/bench/security/openssl/ECKeyAgreementBenchmark.java b/test/micro/org/openeuler/bench/security/openssl/ECKeyAgreementBenchmark.java
new file mode 100644
index 000000000..088a04f95
--- /dev/null
+++ b/test/micro/org/openeuler/bench/security/openssl/ECKeyAgreementBenchmark.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.openeuler.bench.security.openssl;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.Param;
+import org.openjdk.jmh.annotations.Setup;
+import java.util.concurrent.TimeUnit;
+import org.openjdk.jmh.annotations.Warmup;
+
+import javax.crypto.KeyAgreement;
+import java.security.PublicKey;
+import java.security.PrivateKey;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+
+@Warmup(iterations = 10, time = 2, timeUnit = TimeUnit.SECONDS)
+public class ECKeyAgreementBenchmark extends BenchmarkBase {
+    @Param({"EC"})
+    private String kpgAlgorithm;
+
+    @Param({"ECDH"})
+    private String algorithm;
+
+    @Param({"224", "256", "384", "521"})
+    private int keySize;
+
+    private KeyPairGenerator keyPairGenerator;
+    private KeyAgreement keyAgreement;
+    private PrivateKey privKey;
+    private PublicKey pubKey;
+
+    @Setup
+    public void setUp() throws Exception {
+        setupProvider();
+        keyPairGenerator = createKeyPairGenerator();
+        keyPairGenerator.initialize(keySize);
+        KeyPair kpA = keyPairGenerator.generateKeyPair();
+        privKey = kpA.getPrivate();
+        KeyPair kpB = keyPairGenerator.generateKeyPair();
+        pubKey = kpB.getPublic();
+        keyPairGenerator = createKeyPairGenerator();
+        keyAgreement = createKeyAgreement();
+    }
+
+    @Benchmark
+    public void generateKeyAgreement() throws Exception {
+        keyAgreement.init(privKey);
+        keyAgreement.doPhase(pubKey, true);
+        keyAgreement.generateSecret();
+    }
+
+    private KeyPairGenerator createKeyPairGenerator() throws Exception {
+        if (prov != null) {
+            return KeyPairGenerator.getInstance(kpgAlgorithm, prov);
+        }
+        return KeyPairGenerator.getInstance(kpgAlgorithm);
+    }
+
+    private KeyAgreement createKeyAgreement() throws Exception {
+        if (prov != null) {
+            return KeyAgreement.getInstance(algorithm, prov);
+        }
+        return KeyAgreement.getInstance(algorithm);
+    }
+}
diff --git a/test/micro/org/openeuler/bench/security/openssl/ECKeyPairGeneratorBenchmark.java b/test/micro/org/openeuler/bench/security/openssl/ECKeyPairGeneratorBenchmark.java
new file mode 100644
index 000000000..8e34a00a9
--- /dev/null
+++ b/test/micro/org/openeuler/bench/security/openssl/ECKeyPairGeneratorBenchmark.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.openeuler.bench.security.openssl;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.Param;
+import org.openjdk.jmh.annotations.Setup;
+import java.util.concurrent.TimeUnit;
+import org.openjdk.jmh.annotations.Warmup;
+
+import java.security.KeyPairGenerator;
+
+@Warmup(iterations = 10, time = 2, timeUnit = TimeUnit.SECONDS)
+public class ECKeyPairGeneratorBenchmark extends BenchmarkBase {
+    @Param({"EC"})
+    private String algorithm;
+
+    @Param({"224", "256", "384", "521"})
+    private int keySize;
+
+    private KeyPairGenerator keyPairGenerator;
+
+    @Setup
+    public void setUp() throws Exception {
+        setupProvider();
+        keyPairGenerator = createKeyPairGenerator();
+        keyPairGenerator.initialize(keySize);
+    }
+
+    @Benchmark
+    public void generateKeyPair() throws Exception {
+        keyPairGenerator.generateKeyPair();
+    }
+
+    private KeyPairGenerator createKeyPairGenerator() throws Exception {
+        if (prov != null) {
+            return KeyPairGenerator.getInstance(algorithm, prov);
+        }
+        return KeyPairGenerator.getInstance(algorithm);
+    }
+}
diff --git a/test/micro/org/openeuler/bench/security/openssl/HMacBenchmark.java b/test/micro/org/openeuler/bench/security/openssl/HMacBenchmark.java
new file mode 100644
index 000000000..5ecb76ac4
--- /dev/null
+++ b/test/micro/org/openeuler/bench/security/openssl/HMacBenchmark.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.openeuler.bench.security.openssl;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Param;
+import org.openjdk.jmh.annotations.Setup;
+
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.Provider;
+import java.security.Security;
+import java.util.concurrent.TimeUnit;
+
+import javax.crypto.KeyGenerator;
+import javax.crypto.Mac;
+
+public class HMacBenchmark extends BenchmarkBase {
+
+    @Param({"HmacMD5", "HmacSHA1", "HmacSHA224", "HmacSHA256", "HmacSHA384", "HmacSHA512"})
+    private String algorithm;
+
+    @Param({"" + 1024, "" + 10 * 1024, "" + 100 * 1024, "" + 1024 * 1024})
+    private int dataSize;
+
+    private Mac mac;
+
+    @Setup
+    public void setup() throws NoSuchAlgorithmException, InvalidKeyException {
+        setupProvider();
+        mac = (prov == null) ? Mac.getInstance(algorithm) : Mac.getInstance(algorithm, prov);
+        mac.init(KeyGenerator.getInstance(algorithm).generateKey());
+        data = fillRandom(new byte[SET_SIZE][dataSize]);
+    }
+
+    @Benchmark
+    public byte[] mac() {
+        byte[] d = data[index];
+        index = (index + 1) % SET_SIZE;
+        return mac.doFinal(d);
+    }
+
+    @Benchmark
+    @Fork(jvmArgsPrepend = {"-Xms100G", "-Xmx100G", "-XX:+AlwaysPreTouch", "-Dkae.disableKaeDispose=true"}, value = 5)
+    public byte[] macDispose() {
+        byte[] d = data[index];
+        index = (index + 1) % SET_SIZE;
+        return mac.doFinal(d);
+    }
+}
+
diff --git a/test/micro/org/openeuler/bench/security/openssl/RSACipherBenchmark.java b/test/micro/org/openeuler/bench/security/openssl/RSACipherBenchmark.java
new file mode 100644
index 000000000..eaedb7b19
--- /dev/null
+++ b/test/micro/org/openeuler/bench/security/openssl/RSACipherBenchmark.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.openeuler.bench.security.openssl;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.Param;
+import org.openjdk.jmh.annotations.Setup;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import java.security.InvalidKeyException;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.NoSuchAlgorithmException;
+
+public class RSACipherBenchmark extends BenchmarkBase {
+    @Param({"RSA/ECB/NoPadding", "RSA/ECB/PKCS1Padding", "RSA/ECB/OAEPPadding"})
+    private String algorithm;
+
+    @Param({"512", "1024", "2048", "3072", "4096"})
+    private int keyLength;
+
+    @Param({"true", "false"})
+    private boolean encryptPublicKey;
+
+    private byte[][] data;
+    private byte[][] encryptedData;
+
+    private Cipher encryptCipher;
+    private Cipher decryptCipher;
+    private int index = 0;
+
+    private int getMaxDataSize(int keyLength, String algorithm) {
+        int dataSize = keyLength / 8;
+        if ("RSA/ECB/PKCS1Padding".equals(algorithm)) {
+            return dataSize - 11;
+        }
+
+        if ("RSA/ECB/OAEPPadding".equals(algorithm)) {
+            // SHA-1 digestLen is 20
+            int digestLen = 20;
+            return dataSize - 2 - 2 * digestLen;
+        }
+        return dataSize;
+    }
+
+    @Setup()
+    public void setup() throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
+        setupProvider();
+
+        int dataSize = getMaxDataSize(keyLength, algorithm);
+        data = fillRandom(new byte[SET_SIZE][dataSize - 1]);
+
+        KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
+        kpg.initialize(keyLength);
+        KeyPair keyPair = kpg.generateKeyPair();
+
+        encryptCipher = (prov == null) ? Cipher.getInstance(algorithm) : Cipher.getInstance(algorithm, prov);
+        decryptCipher = (prov == null) ? Cipher.getInstance(algorithm) : Cipher.getInstance(algorithm, prov);
+        if (encryptPublicKey || "RSA/ECB/OAEPPadding".equals(algorithm)) {
+            encryptCipher.init(Cipher.ENCRYPT_MODE, keyPair.getPublic());
+            decryptCipher.init(Cipher.DECRYPT_MODE, keyPair.getPrivate());
+        } else {
+            encryptCipher.init(Cipher.ENCRYPT_MODE, keyPair.getPrivate());
+            decryptCipher.init(Cipher.DECRYPT_MODE, keyPair.getPublic());
+        }
+        encryptedData = fillEncrypted(data, encryptCipher);
+    }
+
+    @Benchmark
+    public byte[] encrypt() throws BadPaddingException, IllegalBlockSizeException {
+        byte[] dataBytes = data[index];
+        index = (index + 1) % data.length;
+        return encryptCipher.doFinal(dataBytes);
+    }
+
+    @Benchmark
+    public byte[] decrypt() throws BadPaddingException, IllegalBlockSizeException {
+        byte[] e = encryptedData[index];
+        index = (index + 1) % encryptedData.length;
+        return decryptCipher.doFinal(e);
+    }
+}
diff --git a/test/micro/org/openeuler/bench/security/openssl/RSAKeyPairGeneratorBenchmark.java b/test/micro/org/openeuler/bench/security/openssl/RSAKeyPairGeneratorBenchmark.java
new file mode 100644
index 000000000..1bbd846b8
--- /dev/null
+++ b/test/micro/org/openeuler/bench/security/openssl/RSAKeyPairGeneratorBenchmark.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.openeuler.bench.security.openssl;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.Param;
+import org.openjdk.jmh.annotations.Setup;
+import java.util.concurrent.TimeUnit;
+import org.openjdk.jmh.annotations.Warmup;
+
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+
+@Warmup(iterations = 10, time = 2, timeUnit = TimeUnit.SECONDS)
+public class RSAKeyPairGeneratorBenchmark extends BenchmarkBase {
+    @Param({"RSA"})
+    private String algorithm;
+
+    @Param({"512", "1024", "2048", "3072", "4096"})
+    private int keySize;
+
+    private KeyPairGenerator keyPairGenerator;
+
+    @Setup
+    public void setUp() throws Exception {
+        setupProvider();
+        keyPairGenerator = createKeyPairGenerator();
+        keyPairGenerator.initialize(keySize);
+    }
+
+    @Benchmark
+    public KeyPair generateKeyPair() throws Exception {
+        return keyPairGenerator.generateKeyPair();
+    }
+
+    private KeyPairGenerator createKeyPairGenerator() throws Exception {
+        if (prov != null) {
+            return KeyPairGenerator.getInstance(algorithm, prov);
+        }
+        return KeyPairGenerator.getInstance(algorithm);
+    }
+}
diff --git a/test/micro/org/openeuler/bench/security/openssl/RSAPSSSignatureBenchmark.java b/test/micro/org/openeuler/bench/security/openssl/RSAPSSSignatureBenchmark.java
new file mode 100644
index 000000000..0992fb9c0
--- /dev/null
+++ b/test/micro/org/openeuler/bench/security/openssl/RSAPSSSignatureBenchmark.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.openeuler.bench.security.openssl;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.Param;
+import org.openjdk.jmh.annotations.Setup;
+
+import java.security.*;
+import java.security.spec.MGF1ParameterSpec;
+import java.security.spec.PSSParameterSpec;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * RSASSA-PSS Signature Benchmark
+ */
+public class RSAPSSSignatureBenchmark extends BenchmarkBase {
+    private static Map<String, PSSParameterSpec> pssParameterSpecMap;
+
+    static {
+        initPSSParameterSpecMap();
+    }
+
+    @Param({"SHA-1", "SHA-224", "SHA-256", "SHA-384", "SHA-512"})
+    private String algorithm;
+
+    @Param({"2048", "3072", "4096"})
+    private int keySize;
+
+    @Param({"" + 1024, "" + 10 * 1024, "" + 100 * 1024, "" + 256 * 1024, "" + 1024 * 1024, "" + 10 * 1024 * 1024})
+    private int dataSize;
+
+    private KeyPair keyPair;
+
+    private byte[][] sigData;
+
+
+    private static void initPSSParameterSpecMap() {
+        pssParameterSpecMap = new HashMap<>();
+        pssParameterSpecMap.put("SHA-1", new PSSParameterSpec("SHA-1",
+                "MGF1", MGF1ParameterSpec.SHA1, 20, PSSParameterSpec.TRAILER_FIELD_BC));
+        pssParameterSpecMap.put("SHA-224", new PSSParameterSpec("SHA-224",
+                "MGF1", MGF1ParameterSpec.SHA224, 28, PSSParameterSpec.TRAILER_FIELD_BC));
+        pssParameterSpecMap.put("SHA-256", new PSSParameterSpec("SHA-256",
+                "MGF1", MGF1ParameterSpec.SHA256, 32, PSSParameterSpec.TRAILER_FIELD_BC));
+        pssParameterSpecMap.put("SHA-384", new PSSParameterSpec("SHA-384",
+                "MGF1", MGF1ParameterSpec.SHA384, 48, PSSParameterSpec.TRAILER_FIELD_BC));
+        pssParameterSpecMap.put("SHA-512", new PSSParameterSpec("SHA-512",
+                "MGF1", MGF1ParameterSpec.SHA512, 64, PSSParameterSpec.TRAILER_FIELD_BC));
+    }
+
+    @Setup
+    public void setup() throws Exception {
+        setupProvider();
+        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
+        keyPairGenerator.initialize(keySize);
+        keyPair = keyPairGenerator.generateKeyPair();
+        data = new byte[SET_SIZE][dataSize];
+        sigData = getSigBytes(data);
+    }
+
+    private byte[][] getSigBytes(byte[][] data) throws Exception {
+        byte[][] sigBytes = new byte[data.length][];
+        Signature signature = prov != null ? Signature.getInstance("RSASSA-PSS", prov) :
+                Signature.getInstance("RSASSA-PSS");
+        signature.setParameter(pssParameterSpecMap.get(algorithm));
+        signature.initSign(keyPair.getPrivate());
+        for (int i = 0; i < sigBytes.length; i++) {
+            signature.update(data[i]);
+            sigBytes[i] = signature.sign();
+        }
+        return sigBytes;
+    }
+
+    @Benchmark
+    public void sign() throws Exception {
+        Signature signature = prov != null ? Signature.getInstance("RSASSA-PSS", prov) :
+                Signature.getInstance("RSASSA-PSS");
+        signature.setParameter(pssParameterSpecMap.get(algorithm));
+        signature.initSign(keyPair.getPrivate());
+        signature.update(data[index]);
+        signature.sign();
+        index = (index + 1) % SET_SIZE;
+    }
+
+    @Benchmark
+    public void verify() throws Exception {
+        Signature signature = prov != null ? Signature.getInstance("RSASSA-PSS", prov) :
+                Signature.getInstance("RSASSA-PSS");
+        signature.setParameter(pssParameterSpecMap.get(algorithm));
+        signature.initVerify(keyPair.getPublic());
+        signature.update(data[index]);
+        signature.verify(sigData[index]);
+        index = (index + 1) % SET_SIZE;
+    }
+}
diff --git a/test/micro/org/openeuler/bench/security/openssl/RSASignatureBenchmark.java b/test/micro/org/openeuler/bench/security/openssl/RSASignatureBenchmark.java
new file mode 100644
index 000000000..31112ea57
--- /dev/null
+++ b/test/micro/org/openeuler/bench/security/openssl/RSASignatureBenchmark.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.openeuler.bench.security.openssl;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.Param;
+import org.openjdk.jmh.annotations.Setup;
+
+import java.security.*;
+
+/**
+ * RSA Signature Benchmark
+ */
+public class RSASignatureBenchmark extends BenchmarkBase {
+    @Param({"MD5withRSA", "SHA1withRSA", "SHA224withRSA", "SHA384withRSA", "SHA256withRSA", "SHA512withRSA"})
+    private String algorithm;
+
+    @Param({"2048", "3072", "4096"})
+    private int keySize;
+
+    @Param({"" + 1024, "" + 10 * 1024, "" + 100 * 1024, "" + 256 * 1024, "" + 1024 * 1024, "" + 10 * 1024 * 1024})
+    private int dataSize;
+
+    private KeyPair keyPair;
+
+    private byte[][] sigData;
+
+    @Setup
+    public void setup() throws Exception {
+        setupProvider();
+        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
+        keyPairGenerator.initialize(keySize);
+        keyPair = keyPairGenerator.generateKeyPair();
+        data = new byte[SET_SIZE][dataSize];
+        sigData = getSigBytes(data);
+    }
+
+    private byte[][] getSigBytes(byte[][] data) throws Exception {
+        byte[][] sigBytes = new byte[data.length][];
+        Signature signature = prov != null ? Signature.getInstance(algorithm, prov) :
+                Signature.getInstance(algorithm);
+        signature.initSign(keyPair.getPrivate());
+        for (int i = 0; i < sigBytes.length; i++) {
+            signature.update(data[i]);
+            sigBytes[i] = signature.sign();
+        }
+        return sigBytes;
+    }
+
+    @Benchmark
+    public void sign() throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
+        Signature signature = prov != null ? Signature.getInstance(algorithm, prov) :
+                Signature.getInstance(algorithm);
+        signature.initSign(keyPair.getPrivate());
+        signature.update(data[index]);
+        signature.sign();
+        index = (index + 1) % SET_SIZE;
+    }
+
+    @Benchmark
+    public void verify() throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
+        Signature signature = prov != null ? Signature.getInstance(algorithm, prov) :
+                Signature.getInstance(algorithm);
+        signature.initVerify(keyPair.getPublic());
+        signature.update(data[index]);
+        signature.verify(sigData[index]);
+        index = (index + 1) % SET_SIZE;
+    }
+}
diff --git a/test/micro/org/openeuler/bench/security/openssl/SM3Benchmark.java b/test/micro/org/openeuler/bench/security/openssl/SM3Benchmark.java
new file mode 100644
index 000000000..eea830dbe
--- /dev/null
+++ b/test/micro/org/openeuler/bench/security/openssl/SM3Benchmark.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.openeuler.bench.security.openssl;
+
+import org.openeuler.security.openssl.KAEProvider;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Measurement;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Param;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.Threads;
+import org.openjdk.jmh.annotations.Warmup;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.Provider;
+import java.security.Security;
+import java.util.Random;
+import java.util.concurrent.TimeUnit;
+
+@BenchmarkMode(Mode.Throughput)
+@OutputTimeUnit(TimeUnit.SECONDS)
+@Warmup(iterations = 3, time = 3, timeUnit = TimeUnit.SECONDS)
+@Measurement(iterations = 8, time = 2, timeUnit = TimeUnit.SECONDS)
+@Fork(jvmArgsPrepend = {"-Xms100G", "-Xmx100G", "-XX:+AlwaysPreTouch"}, value = 5)
+@Threads(1)
+@State(Scope.Thread)
+public class SM3Benchmark {
+    public static final int SET_SIZE = 128;
+    byte[][] data;
+    int index = 0;
+
+    @Param({"SM3"})
+    private String algorithm;
+
+    @Param({"" + 1024, "" + 10 * 1024, "" + 100 * 1024, "" + 1024 * 1024})
+    int dataSize;
+
+    MessageDigest md;
+
+    @Setup
+    public void setup() throws NoSuchAlgorithmException {
+        Security.addProvider(new KAEProvider());
+        Provider prov = Security.getProvider("KAEProvider");
+        data = fillRandom(new byte[SET_SIZE][dataSize]);
+        md = (prov == null) ? MessageDigest.getInstance(algorithm) : MessageDigest.getInstance(algorithm, prov);
+    }
+
+    @Benchmark
+    public byte[] digest() {
+        byte[] d = data[index];
+        index = (index + 1) % SET_SIZE;
+        return md.digest(d);
+    }
+
+    @Benchmark
+    @Fork(jvmArgsPrepend = {"-Xms100G", "-Xmx100G", "-XX:+AlwaysPreTouch", "-Dkae.disableKaeDispose=true"}, value = 5)
+    public byte[] digestDispose() {
+        byte[] d = data[index];
+        index = (index + 1) % SET_SIZE;
+        return md.digest(d);
+    }
+
+    public static byte[][] fillRandom(byte[][] data) {
+        Random rnd = new Random();
+        for (byte[] d : data) {
+            rnd.nextBytes(d);
+        }
+        return data;
+    }
+}
+
diff --git a/test/micro/org/openeuler/bench/security/openssl/SM4Benchmark.java b/test/micro/org/openeuler/bench/security/openssl/SM4Benchmark.java
new file mode 100644
index 000000000..32de2b235
--- /dev/null
+++ b/test/micro/org/openeuler/bench/security/openssl/SM4Benchmark.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, Huawei Technologies Co., Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.openeuler.bench.security.openssl;
+
+import org.openeuler.security.openssl.KAEProvider;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Measurement;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Param;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.Threads;
+import org.openjdk.jmh.annotations.Warmup;
+
+import java.security.InvalidKeyException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.NoSuchAlgorithmException;
+import java.security.Provider;
+import java.security.SecureRandom;
+import java.security.Security;
+import java.util.Random;
+import java.util.concurrent.TimeUnit;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.spec.SecretKeySpec;
+
+@BenchmarkMode(Mode.Throughput)
+@OutputTimeUnit(TimeUnit.SECONDS)
+@Warmup(iterations = 3, time = 3, timeUnit = TimeUnit.SECONDS)
+@Measurement(iterations = 8, time = 2, timeUnit = TimeUnit.SECONDS)
+@Fork(jvmArgsPrepend = {"-Xms100G", "-Xmx100G", "-XX:+AlwaysPreTouch"}, value = 5)
+@Threads(1)
+@State(Scope.Thread)
+public class SM4Benchmark {
+    public static final int SET_SIZE = 128;
+    byte[][] data;
+    int index = 0;
+
+    @Param({"SM4/ECB/NoPadding", "SM4/ECB/PKCS5Padding", "SM4/CBC/NoPadding", "SM4/CBC/PKCS5Padding", "SM4/CTR/NoPadding", "SM4/OFB/NoPadding", "SM4/OFB/PKCS5Padding"})
+    private String algorithm;
+
+    @Param({"128"})
+    private int keyLength;
+
+    @Param({"" + 1024, "" + 10 * 1024, "" + 100 * 1024, "" + 1024 * 1024})
+    private int dataSize;
+
+    private byte[][] encryptedData;
+    private Cipher encryptCipher;
+    private Cipher decryptCipher;
+
+    @Setup
+    public void setup() throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
+            InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
+        Security.addProvider(new KAEProvider());
+        Provider prov = Security.getProvider("KAEProvider");
+
+        byte[] keystring = fillSecureRandom(new byte[keyLength / 8]);
+        SecretKeySpec ks = new SecretKeySpec(keystring, "SM4");
+
+        encryptCipher = (prov == null) ? Cipher.getInstance(algorithm) : Cipher.getInstance(algorithm, prov);
+        encryptCipher.init(Cipher.ENCRYPT_MODE, ks);
+        decryptCipher = (prov == null) ? Cipher.getInstance(algorithm) : Cipher.getInstance(algorithm, prov);
+        decryptCipher.init(Cipher.DECRYPT_MODE, ks, encryptCipher.getParameters());
+
+        data = fillRandom(new byte[SET_SIZE][dataSize]);
+        encryptedData = fillEncrypted(data, encryptCipher);
+    }
+
+    @Benchmark
+    public byte[] encrypt() throws IllegalBlockSizeException, BadPaddingException {
+        byte[] d = data[index];
+        index = (index + 1) % SET_SIZE;
+        return encryptCipher.doFinal(d);
+    }
+
+    @Benchmark
+    @Fork(jvmArgsPrepend = {"-Xms100G", "-Xmx100G", "-XX:+AlwaysPreTouch", "-Dkae.disableKaeDispose=true"}, value = 5)
+    public byte[] encryptDispose() throws IllegalBlockSizeException, BadPaddingException {
+        byte[] d = data[index];
+        index = (index + 1) % SET_SIZE;
+        return encryptCipher.doFinal(d);
+    }
+
+    @Benchmark
+    public byte[] decrypt() throws IllegalBlockSizeException, BadPaddingException {
+        byte[] e = encryptedData[index];
+        index = (index + 1) % SET_SIZE;
+        return decryptCipher.doFinal(e);
+    }
+
+    @Benchmark
+    @Fork(jvmArgsPrepend = {"-Xms100G", "-Xmx100G", "-XX:+AlwaysPreTouch", "-Dkae.disableKaeDispose=true"}, value = 5)
+    public byte[] decryptDispose() throws IllegalBlockSizeException, BadPaddingException {
+        byte[] e = encryptedData[index];
+        index = (index + 1) % SET_SIZE;
+        return decryptCipher.doFinal(e);
+    }
+
+    public static byte[][] fillRandom(byte[][] data) {
+        Random rnd = new Random();
+        for (byte[] d : data) {
+            rnd.nextBytes(d);
+        }
+        return data;
+    }
+
+    public static byte[] fillRandom(byte[] data) {
+        Random rnd = new Random();
+        rnd.nextBytes(data);
+        return data;
+    }
+
+    public static byte[] fillSecureRandom(byte[] data) {
+        SecureRandom rnd = new SecureRandom();
+        rnd.nextBytes(data);
+        return data;
+    }
+
+    public static byte[][] fillEncrypted(byte[][] data, Cipher encryptCipher)
+        throws IllegalBlockSizeException, BadPaddingException {
+        byte[][] encryptedData = new byte[data.length][];
+        for (int i = 0; i < encryptedData.length; i++) {
+            encryptedData[i] = encryptCipher.doFinal(data[i]);
+        }
+        return encryptedData;
+    }
+}
+
-- 
2.47.0.windows.2