From 8545f560d406db592303b09fc576c13ba9a8caa0 Mon Sep 17 00:00:00 2001
From: kuenking111 <wangkun49@huawei.com>
Date: Sat, 3 Sep 2022 14:18:42 +0000
Subject: [PATCH 2/6] kae-usability-enhancement

---
 jdk/make/CopyFiles.gmk                        |   2 +-
 jdk/make/mapfiles/libj2kae/mapfile-vers       |   1 +
 jdk/src/share/lib/security/kaeprovider.conf   |  65 ++-
 .../openeuler/security/openssl/KAEConfig.java | 386 ++++++++++++++++++
 .../openeuler/security/openssl/KAELog.java    | 183 +++++++++
 .../security/openssl/KAEProvider.java         | 151 ++++---
 .../security/openssl/KAESM4Cipher.java        | 181 ++++++++
 .../security/openssl/kae_cipher_rsa.c         |  13 +-
 .../openeuler/security/openssl/kae_digest.c   |   9 +-
 .../org/openeuler/security/openssl/kae_hmac.c |   9 +-
 .../security/openssl/kae_keyagreement_dh.c    |   4 +-
 .../openssl/kae_keypairgenerator_dh.c         |   4 +-
 .../openssl/kae_keypairgenerator_rsa.c        |   6 +-
 .../openeuler/security/openssl/kae_provider.c |  54 ++-
 .../security/openssl/kae_signature_rsa.c      |  21 +-
 .../security/openssl/kae_symmetric_cipher.c   |   9 +-
 .../org/openeuler/security/openssl/kae_util.c | 138 ++++++-
 .../org/openeuler/security/openssl/kae_util.h |  51 ++-
 .../openeuler/security/openssl/AESTest.java   | 114 ++++++
 .../openeuler/security/openssl/DHTest.java    |   9 +-
 .../security/openssl/DigestTest.java          |  60 +++
 .../openeuler/security/openssl/ECDHTest.java  |   1 +
 .../openeuler/security/openssl/HmacTest.java  |  88 ++++
 .../security/openssl/KAEConfTest.java         | 121 ++++++
 .../openssl/KAEDisabledAlgorithmsTest.java    | 164 ++++++++
 .../security/openssl/KAEEngineIdTest.java     |  76 ++++
 .../security/openssl/KAELogTest.java          | 126 ++++++
 .../security/openssl/KAETestHelper.java       | 209 ++++++++++
 .../security/openssl/KAEUseEngineTest.java    | 262 ++++++++++++
 .../security/openssl/KaeDebugLogTest.java     |  88 ++++
 .../security/openssl/KaeProviderTest.java     | 170 ++++++++
 .../openeuler/security/openssl/RSATest.java   | 137 +++++++
 .../openeuler/security/openssl/SM3Test.java   |  54 ---
 .../openeuler/security/openssl/SM4Test.java   |  62 ++-
 34 files changed, 2844 insertions(+), 184 deletions(-)
 create mode 100644 jdk/src/solaris/classes/org/openeuler/security/openssl/KAEConfig.java
 create mode 100644 jdk/src/solaris/classes/org/openeuler/security/openssl/KAELog.java
 create mode 100644 jdk/test/org/openeuler/security/openssl/AESTest.java
 create mode 100644 jdk/test/org/openeuler/security/openssl/DigestTest.java
 create mode 100644 jdk/test/org/openeuler/security/openssl/HmacTest.java
 create mode 100644 jdk/test/org/openeuler/security/openssl/KAEConfTest.java
 create mode 100644 jdk/test/org/openeuler/security/openssl/KAEDisabledAlgorithmsTest.java
 create mode 100644 jdk/test/org/openeuler/security/openssl/KAEEngineIdTest.java
 create mode 100644 jdk/test/org/openeuler/security/openssl/KAELogTest.java
 create mode 100644 jdk/test/org/openeuler/security/openssl/KAETestHelper.java
 create mode 100644 jdk/test/org/openeuler/security/openssl/KAEUseEngineTest.java
 create mode 100644 jdk/test/org/openeuler/security/openssl/KaeDebugLogTest.java
 create mode 100644 jdk/test/org/openeuler/security/openssl/KaeProviderTest.java
 create mode 100644 jdk/test/org/openeuler/security/openssl/RSATest.java
 delete mode 100644 jdk/test/org/openeuler/security/openssl/SM3Test.java

diff --git a/jdk/make/CopyFiles.gmk b/jdk/make/CopyFiles.gmk
index 2a6fc0932..806d7bec1 100644
--- a/jdk/make/CopyFiles.gmk
+++ b/jdk/make/CopyFiles.gmk
@@ -634,7 +634,7 @@ endif
 ifeq ($(ENABLE_KAE), true)
   ifeq ($(OPENJDK_TARGET_CPU_ARCH), aarch64)
   
-    KAE_CONF_PATH= $(JDK_OUTPUTDIR)/lib/ext
+    KAE_CONF_PATH= $(JDK_OUTPUTDIR)/lib
     $(KAE_CONF_PATH)/kaeprovider.conf: $(JDK_TOPDIR)/src/share/lib/security/kaeprovider.conf
 	$(call install-file)
 
diff --git a/jdk/make/mapfiles/libj2kae/mapfile-vers b/jdk/make/mapfiles/libj2kae/mapfile-vers
index 128d1e322..a1bdb830b 100644
--- a/jdk/make/mapfiles/libj2kae/mapfile-vers
+++ b/jdk/make/mapfiles/libj2kae/mapfile-vers
@@ -27,6 +27,7 @@ SUNWprivate_1.1 {
 	global:
 		JNI_OnLoad;
 		Java_org_openeuler_security_openssl_KAEProvider_initOpenssl;
+		Java_org_openeuler_security_openssl_KAEProvider_getEngineFlags;
 		Java_org_openeuler_security_openssl_KAEDigest_nativeInit;
 		Java_org_openeuler_security_openssl_KAEDigest_nativeUpdate;
 		Java_org_openeuler_security_openssl_KAEDigest_nativeDigest;
diff --git a/jdk/src/share/lib/security/kaeprovider.conf b/jdk/src/share/lib/security/kaeprovider.conf
index a48969669..cc50611d1 100644
--- a/jdk/src/share/lib/security/kaeprovider.conf
+++ b/jdk/src/share/lib/security/kaeprovider.conf
@@ -1,9 +1,13 @@
 #
-# This is the config file for KAEProvider
+# 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.
 
+# 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
@@ -15,5 +19,58 @@
 # kae.dh=false
 # kae.ec=false
 
-# enable KAEProvider log setting
+# 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
+
diff --git a/jdk/src/solaris/classes/org/openeuler/security/openssl/KAEConfig.java b/jdk/src/solaris/classes/org/openeuler/security/openssl/KAEConfig.java
new file mode 100644
index 000000000..07294dbd6
--- /dev/null
+++ b/jdk/src/solaris/classes/org/openeuler/security/openssl/KAEConfig.java
@@ -0,0 +1,386 @@
+/*
+ * Copyright (c) 2022, 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 {
+        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 + "lib" + 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("\\,");
+    }
+
+    public static String privilegedGetProperty(String key) {
+        if (System.getSecurityManager() == null) {
+            return getProperty(key);
+        } else {
+            return AccessController.doPrivileged((PrivilegedAction<String>) () -> getOverridableProperty(key));
+        }
+    }
+
+    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/jdk/src/solaris/classes/org/openeuler/security/openssl/KAELog.java b/jdk/src/solaris/classes/org/openeuler/security/openssl/KAELog.java
new file mode 100644
index 000000000..434f773a1
--- /dev/null
+++ b/jdk/src/solaris/classes/org/openeuler/security/openssl/KAELog.java
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 2022, 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 {
+        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);
+        }
+    }
+}
diff --git a/jdk/src/solaris/classes/org/openeuler/security/openssl/KAEProvider.java b/jdk/src/solaris/classes/org/openeuler/security/openssl/KAEProvider.java
index 83ed8649c..3e7f54638 100644
--- a/jdk/src/solaris/classes/org/openeuler/security/openssl/KAEProvider.java
+++ b/jdk/src/solaris/classes/org/openeuler/security/openssl/KAEProvider.java
@@ -24,116 +24,103 @@
 
 package org.openeuler.security.openssl;
 
-import java.io.BufferedWriter;
-import java.io.BufferedInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.InputStream;
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.nio.file.StandardOpenOption;
-import java.util.Date;
-import java.util.Properties;
+import sun.security.util.Debug;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.security.Provider;
 
 /**
  * KAE Provider
  */
 public class KAEProvider extends Provider {
-    private static Throwable excp;
-    private static boolean needLog = true;
+    private static final Debug kaeDebug = Debug.getInstance("kae");
+
+    // default engine id
+    private static final String DEFAULT_ENGINE_ID = "kae";
 
     static {
-        Throwable status = null;
-        try {
-            System.loadLibrary("j2kae");
-            initOpenssl();
-        } catch (UnsatisfiedLinkError t) {
-            status = t;
-        } catch (RuntimeException e) {
-            status = e;
-        }
-        excp = status;
+        initialize();
     }
 
-    private void logStart(Throwable excp) {
-        File file = new File(System.getProperty("user.dir"), "kae.log");
-        Path fpath = file.toPath();
-        if (!Files.exists(fpath)) {
-            try {
-                file.createNewFile();
-            } catch (IOException e) {
-                e.printStackTrace();
-            }
-        }
+    private static void initialize() {
+        loadLibrary();
+        initOpenssl();
+    }
 
-        try (BufferedWriter writer = Files.newBufferedWriter(fpath, StandardOpenOption.APPEND)) {
-            if (excp != null) {
-                writer.write(excp.getMessage());
-            } else {
-                writer.write("KAE Engine was found");
+    // load kae.so
+    private static void loadLibrary() {
+        AccessController.doPrivileged(new PrivilegedAction<Object>() {
+            @Override
+            public Object run() {
+                System.loadLibrary("j2kae");
+                return null;
             }
-            writer.write("    " + new Date());
-            writer.newLine();
-        } catch (IOException e) {
-            e.initCause(excp).printStackTrace();
-        }
-        KAEProvider.excp = null; // Exception already logged, clean it.
+        });
     }
 
-    private Properties getProp() {
-        Properties props = new Properties();
-        String sep = File.separator;
-        File propFile = new File(System.getProperty("java.home") + sep + "lib" + sep +
-                        "ext" + sep + "kaeprovider.conf");
-        if (propFile.exists()) {
-            try (InputStream is = new BufferedInputStream(new FileInputStream(propFile))) {
-                props.load(is);
-            } catch (IOException e) {
-                e.printStackTrace();
+    // 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());
             }
         }
-        return props;
+        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);
     }
 
     public KAEProvider() {
         super("KAEProvider", 1.8d, "KAE provider");
-        Properties props = getProp();
-        if (needLog && "true".equalsIgnoreCase(props.getProperty("kae.log"))) {
-            logStart(excp);
-            needLog = false; // Log only once
-        }
-        if (!"false".equalsIgnoreCase(props.getProperty("kae.md5"))) {
+        if (KAEConfig.useKaeProvider("kae.md5")) {
             putMD5();
         }
-        if (!"false".equalsIgnoreCase(props.getProperty("kae.sha256"))) {
+        if (KAEConfig.useKaeProvider("kae.sha256")) {
             putSHA256();
         }
-        if (!"false".equalsIgnoreCase(props.getProperty("kae.sha384"))) {
+        if (KAEConfig.useKaeProvider("kae.sha384")) {
             putSHA384();
         }
-        if (!"false".equalsIgnoreCase(props.getProperty("kae.sm3"))) {
+        if (KAEConfig.useKaeProvider("kae.sm3")) {
             putSM3();
         }
-        if (!"false".equalsIgnoreCase(props.getProperty("kae.aes"))) {
+        if (KAEConfig.useKaeProvider("kae.aes")) {
             putAES();
         }
-        if (!"false".equalsIgnoreCase(props.getProperty("kae.sm4"))) {
+        if (KAEConfig.useKaeProvider("kae.sm4")) {
             putSM4();
         }
-        if (!"false".equalsIgnoreCase(props.getProperty("kae.hmac"))) {
+        if (KAEConfig.useKaeProvider("kae.hmac")) {
             putHMAC();
         }
-        if (!"false".equalsIgnoreCase(props.getProperty("kae.rsa"))) {
+        if (KAEConfig.useKaeProvider("kae.rsa")) {
             putRSA();
             putSignatureRSA();
         }
-        if (!"false".equalsIgnoreCase(props.getProperty("kae.dh"))) {
+        if (KAEConfig.useKaeProvider("kae.dh")) {
             putDH();
         }
-        if (!"false".equalsIgnoreCase(props.getProperty("kae.ec"))) {
+        if (KAEConfig.useKaeProvider("kae.ec")) {
             putEC();
         }
     }
@@ -285,28 +272,28 @@ public class KAEProvider extends Provider {
                 "org.openeuler.security.openssl.KAERSASignature$SHA512withRSA");
 
         // alias
-        put("Alg.Alias.Signature.1.2.840.113549.1.1.4",     "MD5withRSA");
+        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.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.3.14.3.2.29", "SHA1withRSA");
 
-        put("Alg.Alias.Signature.1.2.840.113549.1.1.14",     "SHA224withRSA");
+        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.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.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.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.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
@@ -326,6 +313,10 @@ public class KAEProvider extends Provider {
         put("Alg.Alias.KeyPairGenerator.EllipticCurve", "EC");
         put("KeyAgreement.ECDH", "org.openeuler.security.openssl.KAEECDHKeyAgreement");
     }
+
     // init openssl
-    static native void initOpenssl() throws RuntimeException;
+    static native void initOpenssl(boolean useGlobalMode, String engineId, boolean[] algorithmKaeFlags)
+            throws RuntimeException;
+
+    static native boolean[] getEngineFlags();
 }
diff --git a/jdk/src/solaris/classes/org/openeuler/security/openssl/KAESM4Cipher.java b/jdk/src/solaris/classes/org/openeuler/security/openssl/KAESM4Cipher.java
index b189bea3a..cca619e1a 100644
--- a/jdk/src/solaris/classes/org/openeuler/security/openssl/KAESM4Cipher.java
+++ b/jdk/src/solaris/classes/org/openeuler/security/openssl/KAESM4Cipher.java
@@ -26,13 +26,20 @@
 
 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:
@@ -46,6 +53,55 @@ import javax.crypto.NoSuchPaddingException;
  */
 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);
@@ -170,6 +226,131 @@ abstract class KAESM4Cipher extends KAESymmetricCipherBase {
         }
     }
 
+    @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 ");
diff --git a/jdk/src/solaris/native/org/openeuler/security/openssl/kae_cipher_rsa.c b/jdk/src/solaris/native/org/openeuler/security/openssl/kae_cipher_rsa.c
index 80a0e58b9..d9b16ab9d 100644
--- a/jdk/src/solaris/native/org/openeuler/security/openssl/kae_cipher_rsa.c
+++ b/jdk/src/solaris/native/org/openeuler/security/openssl/kae_cipher_rsa.c
@@ -24,12 +24,11 @@
 #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"
 
-static ENGINE* kaeEngine = NULL;
-
 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);
@@ -176,7 +175,9 @@ static int RSACryptOAEPPadding(JNIEnv* env, jlong keyAddress, jint inLen, jbyteA
     // outLen type should be size_t
     // EVP_PKEY_encrypt takes the outLen address as a parameter, and the parameter type is size_t*
     size_t outLen = 0;
-    kaeEngine = (kaeEngine == NULL) ? GetKaeEngine() : kaeEngine;
+    ENGINE* kaeEngine = GetEngineByAlgorithmIndex(RSA_INDEX);
+    KAE_TRACE("RSACryptOAEPPadding: kaeEngine => %p", kaeEngine);
+
 
     EVP_PKEY* pkey = (EVP_PKEY*) keyAddress;
 
@@ -272,7 +273,8 @@ JNIEXPORT jlong JNICALL Java_org_openeuler_security_openssl_KAERSACipher_nativeC
     BIGNUM* bnIQMP = NULL;
     RSA* rsa = NULL;
     EVP_PKEY* pkey = NULL;
-    kaeEngine = (kaeEngine == NULL) ? GetKaeEngine() : kaeEngine;
+    ENGINE* kaeEngine = GetEngineByAlgorithmIndex(RSA_INDEX);
+    KAE_TRACE("KAERSACipher_nativeCreateRSAPrivateCrtKey: kaeEngine => %p", kaeEngine);
 
     // convert to big num
     if ((bnN = KAE_GetBigNumFromByteArray(env, n)) == NULL ||
@@ -334,7 +336,8 @@ JNIEXPORT jlong JNICALL Java_org_openeuler_security_openssl_KAERSACipher_nativeC
     BIGNUM* bnE = NULL;
     RSA* rsa = NULL;
     EVP_PKEY* pkey = NULL;
-    kaeEngine = (kaeEngine == NULL) ? GetKaeEngine() : kaeEngine;
+    ENGINE* kaeEngine = GetEngineByAlgorithmIndex(RSA_INDEX);
+    KAE_TRACE("KAERSACipher_nativeCreateRSAPublicKey: kaeEngine => %p", kaeEngine);
 
     // get public key param n
     bnN = KAE_GetBigNumFromByteArray(env, n);
diff --git a/jdk/src/solaris/native/org/openeuler/security/openssl/kae_digest.c b/jdk/src/solaris/native/org/openeuler/security/openssl/kae_digest.c
index f0e7b0be4..23b178978 100644
--- a/jdk/src/solaris/native/org/openeuler/security/openssl/kae_digest.c
+++ b/jdk/src/solaris/native/org/openeuler/security/openssl/kae_digest.c
@@ -42,7 +42,7 @@ JNIEXPORT jlong JNICALL
 Java_org_openeuler_security_openssl_KAEDigest_nativeInit(JNIEnv *env, jclass cls, jstring algorithmName)
 {
     EVP_MD_CTX* ctx = NULL;
-    static ENGINE* kaeEngine = NULL;
+    ENGINE* kaeEngine = NULL;
 
     if (algorithmName == NULL) {
         KAE_ThrowNullPointerException(env, "algorithm is null");
@@ -51,11 +51,8 @@ Java_org_openeuler_security_openssl_KAEDigest_nativeInit(JNIEnv *env, jclass cls
 
     // EVP_get_digestbyname
     const char* algo_utf = (*env)->GetStringUTFChars(env, algorithmName, 0);
-    if ((strcasecmp(algo_utf, "md5") == 0) || (strcasecmp(algo_utf, "sm3") == 0)) {
-        kaeEngine = (kaeEngine == NULL) ? GetKaeEngine() : kaeEngine;
-    } else {
-        kaeEngine = NULL;
-    }
+    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) {
diff --git a/jdk/src/solaris/native/org/openeuler/security/openssl/kae_hmac.c b/jdk/src/solaris/native/org/openeuler/security/openssl/kae_hmac.c
index 554a9750c..1efacbb5b 100644
--- a/jdk/src/solaris/native/org/openeuler/security/openssl/kae_hmac.c
+++ b/jdk/src/solaris/native/org/openeuler/security/openssl/kae_hmac.c
@@ -73,9 +73,14 @@ JNIEXPORT jlong JNICALL Java_org_openeuler_security_openssl_KAEHMac_nativeInit
     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);
+    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");
@@ -98,7 +103,7 @@ JNIEXPORT jlong JNICALL Java_org_openeuler_security_openssl_KAEHMac_nativeInit
     }
 
     // init hmac context with sc_key and evp_md
-    int result_code = HMAC_Init_ex(ctx, key_buffer, key_len, md, NULL);
+    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;
diff --git a/jdk/src/solaris/native/org/openeuler/security/openssl/kae_keyagreement_dh.c b/jdk/src/solaris/native/org/openeuler/security/openssl/kae_keyagreement_dh.c
index 7cdf790cb..d8d2ee7cb 100644
--- a/jdk/src/solaris/native/org/openeuler/security/openssl/kae_keyagreement_dh.c
+++ b/jdk/src/solaris/native/org/openeuler/security/openssl/kae_keyagreement_dh.c
@@ -51,8 +51,8 @@ JNIEXPORT jbyteArray JNICALL Java_org_openeuler_security_openssl_KAEDHKeyAgreeme
     int computekeyLength = 0;
     unsigned char* secret = NULL;
     jbyteArray retByteArray = NULL;
-    static ENGINE* kaeEngine = NULL;
-    kaeEngine = (kaeEngine == NULL) ? GetKaeEngine() : kaeEngine;
+    ENGINE* kaeEngine = GetEngineByAlgorithmIndex(DH_INDEX);
+    KAE_TRACE("KAEDHKeyAgreement_nativeComputeKey: kaeEngine => %p", kaeEngine);
 
     // bits to Bytes
     int pSizeInByte = (pSize +7) >> 3;
diff --git a/jdk/src/solaris/native/org/openeuler/security/openssl/kae_keypairgenerator_dh.c b/jdk/src/solaris/native/org/openeuler/security/openssl/kae_keypairgenerator_dh.c
index 54dc07edd..d16b42b41 100644
--- a/jdk/src/solaris/native/org/openeuler/security/openssl/kae_keypairgenerator_dh.c
+++ b/jdk/src/solaris/native/org/openeuler/security/openssl/kae_keypairgenerator_dh.c
@@ -50,8 +50,8 @@ JNIEXPORT jobjectArray JNICALL Java_org_openeuler_security_openssl_KAEDHKeyPairG
     jobjectArray keys = NULL;
     jbyteArray pri_key = NULL;
     jbyteArray pub_key = NULL;
-    static ENGINE* kaeEngine = NULL;
-    kaeEngine = (kaeEngine == NULL) ? GetKaeEngine() : kaeEngine;
+    ENGINE* kaeEngine = GetEngineByAlgorithmIndex(DH_INDEX);
+    KAE_TRACE("KAEDHKeyPairGenerator_nativeGenerateKeyPair: kaeEngine => %p", kaeEngine);
 
     KAE_TRACE("Java_org_openeuler_security_openssl_KAEDHKeyPairGenerator_nativeGenerateKeyPair start !");
 
diff --git a/jdk/src/solaris/native/org/openeuler/security/openssl/kae_keypairgenerator_rsa.c b/jdk/src/solaris/native/org/openeuler/security/openssl/kae_keypairgenerator_rsa.c
index 2ca978bbe..9251b56c4 100644
--- a/jdk/src/solaris/native/org/openeuler/security/openssl/kae_keypairgenerator_rsa.c
+++ b/jdk/src/solaris/native/org/openeuler/security/openssl/kae_keypairgenerator_rsa.c
@@ -23,6 +23,7 @@
 
 #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"
@@ -62,8 +63,9 @@ static const BIGNUM* (* GetRSAParamFunctionList[])(const RSA*) = {
  * step 3.Generate rsa key, and all key information is stored in RSA
  */
 static RSA* NewRSA(JNIEnv* env, jint keySize, jbyteArray publicExponent) {
-    static ENGINE* kaeEngine = NULL;
-    kaeEngine = (kaeEngine == NULL) ? GetKaeEngine() : kaeEngine;
+    ENGINE* kaeEngine = GetEngineByAlgorithmIndex(RSA_INDEX);
+    KAE_TRACE("NewRSA: kaeEngine => %p", kaeEngine);
+
     // new rsa
     RSA* rsa = RSA_new_method(kaeEngine);
     if (rsa == NULL) {
diff --git a/jdk/src/solaris/native/org/openeuler/security/openssl/kae_provider.c b/jdk/src/solaris/native/org/openeuler/security/openssl/kae_provider.c
index aa46e737e..fca035b04 100644
--- a/jdk/src/solaris/native/org/openeuler/security/openssl/kae_provider.c
+++ b/jdk/src/solaris/native/org/openeuler/security/openssl/kae_provider.c
@@ -24,21 +24,53 @@
 #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) {
+        (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) {
@@ -47,11 +79,25 @@ JNIEXPORT void JNICALL Java_org_openeuler_security_openssl_KAEProvider_initOpens
     }
 
     // determine whether KAE is loaded successfully
-    e = ENGINE_by_id("kae");
+    const char* id = (*env)->GetStringUTFChars(env, engineId, 0);
+    e = ENGINE_by_id(id);
+    (*env)->ReleaseStringUTFChars(env, engineId, id);
     if (e == NULL) {
-        ERR_clear_error();
-        KAE_ThrowRuntimeException(env, "kae engine not found");
+        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/jdk/src/solaris/native/org/openeuler/security/openssl/kae_signature_rsa.c b/jdk/src/solaris/native/org/openeuler/security/openssl/kae_signature_rsa.c
index e81dc1406..6c401356d 100644
--- a/jdk/src/solaris/native/org/openeuler/security/openssl/kae_signature_rsa.c
+++ b/jdk/src/solaris/native/org/openeuler/security/openssl/kae_signature_rsa.c
@@ -24,6 +24,7 @@
 #include <string.h>
 #include <openssl/rsa.h>
 #include <openssl/evp.h>
+#include "kae_log.h"
 #include "kae_util.h"
 #include "kae_exception.h"
 
@@ -99,8 +100,9 @@ JNIEXPORT jbyteArray JNICALL Java_org_openeuler_security_openssl_KAERSASignature
     jbyte* digestBytes = NULL;
     jbyte* sigBytes = NULL;
     jbyteArray sigByteArray = NULL;
-    static ENGINE* kaeEngine = NULL;
-    kaeEngine = (kaeEngine == NULL) ? GetKaeEngine() : kaeEngine;
+    ENGINE* kaeEngine = GetEngineByAlgorithmIndex(RSA_INDEX);
+    KAE_TRACE("KAERSASignatureNative_rsaSign: kaeEngine => %p", kaeEngine);
+
     // new EVP_PKEY_CTX
     if ((pkeyCtx = EVP_PKEY_CTX_new(pkey, kaeEngine)) == NULL) {
         KAE_ThrowFromOpenssl(env, "EVP_PKEY_new", KAE_ThrowSignatureException);
@@ -163,8 +165,9 @@ JNIEXPORT jboolean JNICALL Java_org_openeuler_security_openssl_KAERSASignatureNa
     jbyte* digestBytes = NULL;
     jbyte* sigBytes = NULL;
     jboolean isSuccess = JNI_FALSE;
-    static ENGINE* kaeEngine = NULL;
-    kaeEngine = (kaeEngine == NULL) ? GetKaeEngine() : kaeEngine;
+    ENGINE* kaeEngine = GetEngineByAlgorithmIndex(RSA_INDEX);
+    KAE_TRACE("KAERSASignatureNative_rsaVerify: kaeEngine => %p", kaeEngine);
+
     // new EVP_PKEY_CTX
     if ((pkeyCtx = EVP_PKEY_CTX_new(pkey, kaeEngine)) == NULL) {
         KAE_ThrowFromOpenssl(env, "EVP_PKEY_new", KAE_ThrowSignatureException);
@@ -255,8 +258,9 @@ JNIEXPORT jbyteArray JNICALL Java_org_openeuler_security_openssl_KAERSASignature
     jbyte* digestBytes = NULL;
     jbyte* sigBytes = NULL;
     jbyteArray sigByteArray = NULL;
-    static ENGINE* kaeEngine = NULL;
-    kaeEngine = (kaeEngine == NULL) ? GetKaeEngine() : kaeEngine;
+    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);
@@ -320,8 +324,9 @@ JNIEXPORT jboolean JNICALL Java_org_openeuler_security_openssl_KAERSASignatureNa
     jbyte* digestBytes = NULL;
     jbyte* sigBytes = NULL;
     jboolean isSuccess = JNI_FALSE;
-    static ENGINE* kaeEngine = NULL;
-    kaeEngine = (kaeEngine == NULL) ? GetKaeEngine() : kaeEngine;
+    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);
diff --git a/jdk/src/solaris/native/org/openeuler/security/openssl/kae_symmetric_cipher.c b/jdk/src/solaris/native/org/openeuler/security/openssl/kae_symmetric_cipher.c
index 71c28bdea..43f6326b2 100644
--- a/jdk/src/solaris/native/org/openeuler/security/openssl/kae_symmetric_cipher.c
+++ b/jdk/src/solaris/native/org/openeuler/security/openssl/kae_symmetric_cipher.c
@@ -142,16 +142,19 @@ Java_org_openeuler_security_openssl_KAESymmetricCipherBase_nativeInit(JNIEnv* en
     jbyte* keyBytes = NULL;
     jbyte* ivBytes = NULL;
     const EVP_CIPHER* cipher = NULL;
-    static ENGINE* kaeEngine = NULL;
+    ENGINE* kaeEngine = NULL;
 
     const char* algo = (*env)->GetStringUTFChars(env, cipherType, 0);
     if (StartsWith("aes", algo)) {
         cipher = EVPGetAesCipherByName(env, algo);
-        kaeEngine = NULL;
+        kaeEngine = GetAesEngineByAlgorithmName(algo);
     } else {
         cipher = EVPGetSm4CipherByName(env, algo);
-        kaeEngine = (kaeEngine == NULL) ? GetKaeEngine() : kaeEngine;
+        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");
diff --git a/jdk/src/solaris/native/org/openeuler/security/openssl/kae_util.c b/jdk/src/solaris/native/org/openeuler/security/openssl/kae_util.c
index 0e656a834..a16d944c4 100644
--- a/jdk/src/solaris/native/org/openeuler/security/openssl/kae_util.c
+++ b/jdk/src/solaris/native/org/openeuler/security/openssl/kae_util.c
@@ -22,6 +22,7 @@
  */
 
 #include <openssl/evp.h>
+#include <string.h>
 #include "kae_util.h"
 #include "kae_exception.h"
 
@@ -55,7 +56,7 @@ BIGNUM* KAE_GetBigNumFromByteArray(JNIEnv* env, jbyteArray byteArray) {
 
     jbyte* bytes = (*env)->GetByteArrayElements(env, byteArray, NULL);
     if (bytes == NULL) {
-        KAE_ThrowNullPointerException(env,"GetByteArrayElements failed");
+        KAE_ThrowNullPointerException(env, "GetByteArrayElements failed");
         goto cleanup;
     }
     BIGNUM* result = BN_bin2bn((const unsigned char*) bytes, len, bn);
@@ -109,3 +110,138 @@ 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/jdk/src/solaris/native/org/openeuler/security/openssl/kae_util.h b/jdk/src/solaris/native/org/openeuler/security/openssl/kae_util.h
index 13bd5976d..347337509 100644
--- a/jdk/src/solaris/native/org/openeuler/security/openssl/kae_util.h
+++ b/jdk/src/solaris/native/org/openeuler/security/openssl/kae_util.h
@@ -27,6 +27,43 @@
 #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);
 
@@ -40,8 +77,18 @@ void SetKaeEngine(ENGINE* engine);
 
 ENGINE* GetKaeEngine();
 
-void SetKaeEngine(ENGINE* engine);
+void initEngines(JNIEnv* env, jbooleanArray algorithmKaeFlags);
 
-ENGINE* GetKaeEngine();
+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/jdk/test/org/openeuler/security/openssl/AESTest.java b/jdk/test/org/openeuler/security/openssl/AESTest.java
new file mode 100644
index 000000000..77da5ecc2
--- /dev/null
+++ b/jdk/test/org/openeuler/security/openssl/AESTest.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2022, 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
+ * @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/jdk/test/org/openeuler/security/openssl/DHTest.java b/jdk/test/org/openeuler/security/openssl/DHTest.java
index 6eb5e7c96..ee5d63684 100644
--- a/jdk/test/org/openeuler/security/openssl/DHTest.java
+++ b/jdk/test/org/openeuler/security/openssl/DHTest.java
@@ -28,7 +28,6 @@ import java.io.Serializable;
 import java.math.BigInteger;
 import java.security.*;
 import java.util.Arrays;
-import java.util.Date;
 import javax.crypto.KeyAgreement;
 import javax.crypto.spec.*;
 import org.openeuler.security.openssl.KAEProvider;
@@ -75,18 +74,16 @@ import org.openeuler.security.openssl.KAEProvider;
 /**
  * @test
  * @summary Basic test for DH
+ * @requires os.arch=="aarch64"
  * @run main DHTest
  */
 
-final class DHTest implements Serializable {
-    private  static int bitLength = 8192;
+public class DHTest implements Serializable {
     private static BigInteger g512;
     private static BigInteger p512;
-    Throwable t = null;
 
     private static volatile Provider sunJceProvider;
     private static volatile Provider kaeProvider;
-    Date d = new Date();
 
     public static void main(String[] args) throws Exception {
         Security.addProvider(new KAEProvider());
@@ -97,8 +94,6 @@ final class DHTest implements Serializable {
 
         p512 = new BigInteger("27672987386729926592037876826877634387173876890702920770064392919138769821035856568775311919542560094764667151024449425954917954337048895981297730855891532066350935045229294626339548842381843985759061682551900379979643117695834175891578650111093016914264824311693147701566019122696621248493126219217339690346346921463135605151471303957324058301097079967414639146647429422884520134312590056632178576758580657240245655739869017244657144448267757255018625514803292549109401806336918448001843022629625467069714240279603204909633404992842479161100500474744098408277938070656334892106100534117209709263785505019003765693651");
 
-        DHTest.bitLength = 0;
-
         DHParameterSpec dhParams = new DHParameterSpec(p512, g512);
         KeyPairGenerator SunJCEkeyGen = KeyPairGenerator.getInstance("DH", sunJceProvider);
         KeyPairGenerator KAEkeyGen = KeyPairGenerator.getInstance("DH", kaeProvider);
diff --git a/jdk/test/org/openeuler/security/openssl/DigestTest.java b/jdk/test/org/openeuler/security/openssl/DigestTest.java
new file mode 100644
index 000000000..a293f7268
--- /dev/null
+++ b/jdk/test/org/openeuler/security/openssl/DigestTest.java
@@ -0,0 +1,60 @@
+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
+ * @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/jdk/test/org/openeuler/security/openssl/ECDHTest.java b/jdk/test/org/openeuler/security/openssl/ECDHTest.java
index 590c31154..069c32295 100644
--- a/jdk/test/org/openeuler/security/openssl/ECDHTest.java
+++ b/jdk/test/org/openeuler/security/openssl/ECDHTest.java
@@ -41,6 +41,7 @@ import java.nio.charset.StandardCharsets;
 /**
  * @test
  * @summary Basic test for ECDH
+ * @requires os.arch=="aarch64"
  * @run main ECDHTest
  */
 
diff --git a/jdk/test/org/openeuler/security/openssl/HmacTest.java b/jdk/test/org/openeuler/security/openssl/HmacTest.java
new file mode 100644
index 000000000..9ff328629
--- /dev/null
+++ b/jdk/test/org/openeuler/security/openssl/HmacTest.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2022, 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
+ * @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/jdk/test/org/openeuler/security/openssl/KAEConfTest.java b/jdk/test/org/openeuler/security/openssl/KAEConfTest.java
new file mode 100644
index 000000000..9028d28b5
--- /dev/null
+++ b/jdk/test/org/openeuler/security/openssl/KAEConfTest.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2022, 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
+ * @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 + "lib" + 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/jdk/test/org/openeuler/security/openssl/KAEDisabledAlgorithmsTest.java b/jdk/test/org/openeuler/security/openssl/KAEDisabledAlgorithmsTest.java
new file mode 100644
index 000000000..6301b6d76
--- /dev/null
+++ b/jdk/test/org/openeuler/security/openssl/KAEDisabledAlgorithmsTest.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2022, 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
+ * @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/jdk/test/org/openeuler/security/openssl/KAEEngineIdTest.java b/jdk/test/org/openeuler/security/openssl/KAEEngineIdTest.java
new file mode 100644
index 000000000..2ddaf6712
--- /dev/null
+++ b/jdk/test/org/openeuler/security/openssl/KAEEngineIdTest.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2022, 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
+ * @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/jdk/test/org/openeuler/security/openssl/KAELogTest.java b/jdk/test/org/openeuler/security/openssl/KAELogTest.java
new file mode 100644
index 000000000..31c8f5d99
--- /dev/null
+++ b/jdk/test/org/openeuler/security/openssl/KAELogTest.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2022, 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
+ * @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/jdk/test/org/openeuler/security/openssl/KAETestHelper.java b/jdk/test/org/openeuler/security/openssl/KAETestHelper.java
new file mode 100644
index 000000000..31e22493a
--- /dev/null
+++ b/jdk/test/org/openeuler/security/openssl/KAETestHelper.java
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2022, 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/jdk/test/org/openeuler/security/openssl/KAEUseEngineTest.java b/jdk/test/org/openeuler/security/openssl/KAEUseEngineTest.java
new file mode 100644
index 000000000..4e57f775e
--- /dev/null
+++ b/jdk/test/org/openeuler/security/openssl/KAEUseEngineTest.java
@@ -0,0 +1,262 @@
+/*
+ * Copyright (c) 2022, 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
+ * @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));
+        }
+    }
+}
diff --git a/jdk/test/org/openeuler/security/openssl/KaeDebugLogTest.java b/jdk/test/org/openeuler/security/openssl/KaeDebugLogTest.java
new file mode 100644
index 000000000..bcce9cb8b
--- /dev/null
+++ b/jdk/test/org/openeuler/security/openssl/KaeDebugLogTest.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2021, 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
+ * @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/jdk/test/org/openeuler/security/openssl/KaeProviderTest.java b/jdk/test/org/openeuler/security/openssl/KaeProviderTest.java
new file mode 100644
index 000000000..d8587891b
--- /dev/null
+++ b/jdk/test/org/openeuler/security/openssl/KaeProviderTest.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2021, 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"
+ * @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!");
+            }
+        }
+    }
+}
diff --git a/jdk/test/org/openeuler/security/openssl/RSATest.java b/jdk/test/org/openeuler/security/openssl/RSATest.java
new file mode 100644
index 000000000..1f740af0b
--- /dev/null
+++ b/jdk/test/org/openeuler/security/openssl/RSATest.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2022, 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.*;
+import java.security.spec.*;
+import javax.crypto.Cipher;
+
+/**
+ * @test
+ * @summary Basic test for RSA
+ * @run main RSATest
+ */
+
+public class RSATest {
+    private static final String algorithm = "RSA";
+    private static KeyPairGenerator keyPairGenerator;
+    private static byte[] privateKey;
+    private static byte[] publicKey;
+    private static String plainText = "helloworld";
+    //    512, 768,
+    private static int[] keySizes = {1024, 2048, 4096, 5120, 6144};
+    private static String[] signAlgorithms = {
+            "MD2withRSA", "MD5withRSA", "SHA1withRSA", "SHA224withRSA", "SHA256withRSA", "SHA384withRSA", "SHA512withRSA"
+    };
+    private static String[] signAlgorithmsPSS = {"SHA-1", "SHA-224", "SHA-256", "SHA-384", "SHA-512"};
+
+    public static void main(String[] args) throws Exception {
+        Security.insertProviderAt(new KAEProvider(), 1);
+
+        for (int keySize : keySizes) {
+            testKeyPairByKeySize(keySize);
+            testRSACipher(keySize);
+            testSignature();
+            testPSSSignature(keySize);
+        }
+    }
+
+    public static void testKeyPairByKeySize(int keySize) throws Exception {
+        keyPairGenerator = KeyPairGenerator.getInstance(algorithm);
+        keyPairGenerator.initialize(keySize);
+        KeyPair keyPair = keyPairGenerator.generateKeyPair();
+
+        PrivateKey pairPrivate = keyPair.getPrivate();
+        PublicKey pairPublic = keyPair.getPublic();
+
+        privateKey = pairPrivate.getEncoded();
+        publicKey = pairPublic.getEncoded();
+    }
+
+    public static void testRSACipher(int keySize) throws Exception {
+        PublicKey pubKey = KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(publicKey));
+        Cipher cipher = Cipher.getInstance("RSA");
+        cipher.init(Cipher.ENCRYPT_MODE, pubKey);
+
+        byte[] cipherText = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));
+
+        PrivateKey priKey = KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(privateKey));
+
+        cipher.init(Cipher.DECRYPT_MODE, priKey);
+
+        String decryptText = new String(cipher.doFinal(cipherText));
+
+        if (!plainText.equals(decryptText)) {
+            throw new RuntimeException("rsa decryption failed. keySize = " + keySize);
+        }
+    }
+
+    public static void testSignature() throws Exception {
+        PrivateKey priKey = KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(privateKey));
+        PublicKey pubKey = KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(publicKey));
+
+        for (String algorithm : signAlgorithms) {
+            Signature sign = Signature.getInstance(algorithm);
+            sign.initSign(priKey);
+            sign.update(plainText.getBytes());
+            byte[] signInfo = sign.sign();
+
+            sign.initVerify(pubKey);
+            sign.update(plainText.getBytes());
+            if (!sign.verify(signInfo)) {
+                throw new RuntimeException("rsa testSignature failed. digest algorithm = " + algorithm);
+            }
+        }
+    }
+
+    public static void testPSSSignature(int keySize) throws Exception {
+        PrivateKey priKey = KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(privateKey));
+        PublicKey pubKey = KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(publicKey));
+
+        Signature sign = Signature.getInstance("RSASSA-PSS");
+
+        for (String algorithm : signAlgorithmsPSS) {
+            if (algorithm.equals(signAlgorithmsPSS[4]) && keySize <= 1024) {
+                continue;
+            }
+            sign.initSign(priKey);
+
+            MessageDigest digest = MessageDigest.getInstance(algorithm);
+            byte[] digestByte = digest.digest(plainText.getBytes());
+            sign.setParameter(
+                    new PSSParameterSpec(algorithm, "MGF1", new MGF1ParameterSpec(algorithm), digestByte.length, 1));
+
+            sign.update(plainText.getBytes());
+            byte[] signInfo = sign.sign();
+
+            sign.initVerify(pubKey);
+
+            sign.update(plainText.getBytes());
+            if (!sign.verify(signInfo)) {
+                throw new RuntimeException("rsa testPSSSignature failed. digest algorithm = " + algorithm);
+            }
+        }
+    }
+}
diff --git a/jdk/test/org/openeuler/security/openssl/SM3Test.java b/jdk/test/org/openeuler/security/openssl/SM3Test.java
deleted file mode 100644
index 181f708ff..000000000
--- a/jdk/test/org/openeuler/security/openssl/SM3Test.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2021, 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
- * @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/jdk/test/org/openeuler/security/openssl/SM4Test.java b/jdk/test/org/openeuler/security/openssl/SM4Test.java
index 4c28dc5b6..1029fe897 100644
--- a/jdk/test/org/openeuler/security/openssl/SM4Test.java
+++ b/jdk/test/org/openeuler/security/openssl/SM4Test.java
@@ -22,9 +22,10 @@
  */
 
 import org.openeuler.security.openssl.KAEProvider;
+
+import java.nio.ByteBuffer;
 import java.nio.charset.StandardCharsets;
 import java.util.Arrays;
-import java.security.NoSuchAlgorithmException;
 import java.security.Security;
 import javax.crypto.Cipher;
 import javax.crypto.spec.IvParameterSpec;
@@ -55,6 +56,25 @@ public class SM4Test {
         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 {
@@ -92,4 +112,44 @@ public class SM4Test {
            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();
+    }
 }
-- 
2.17.1

