From 4993e7a69c88f01dc8c858cfa429c3904a632462 Mon Sep 17 00:00:00 2001
Date: Tue, 16 Mar 2021 06:03:50 +0000
Subject: [PATCH 3/3] add kae feature

---
 common/autoconf/generated-configure.sh        |  28 +
 common/autoconf/jdk-options.m4                |  14 +
 common/autoconf/spec.gmk.in                   |   1 +
 jdk/make/CompileJavaClasses.gmk               |  28 +-
 jdk/make/CreateJars.gmk                       |   1 +
 jdk/make/CreateSecurityJars.gmk               |  29 +
 jdk/make/SignJars.gmk                         |   6 +
 jdk/make/lib/SecurityLibraries.gmk            |  25 +
 jdk/make/mapfiles/libj2kae/mapfile-vers       |  57 ++
 jdk/make/profile-includes.txt                 |  12 +
 .../security/openssl/KAEAESCipher.java        | 725 ++++++++++++++++
 .../openeuler/security/openssl/KAEDigest.java | 264 ++++++
 .../openeuler/security/openssl/KAEMac.java    | 228 +++++
 .../security/openssl/KAEProvider.java         | 180 ++++
 .../security/openssl/KAERSACipher.java        | 796 ++++++++++++++++++
 .../openssl/KAERSAKeyPairGenerator.java       | 164 ++++
 .../security/openssl/KAERSAPaddingType.java   |  80 ++
 .../openeuler/security/openssl/KAEUtils.java  | 196 +++++
 .../security/openssl/kae_cipher_aes.c         | 255 ++++++
 .../security/openssl/kae_cipher_rsa.c         | 463 ++++++++++
 .../openeuler/security/openssl/kae_digest.c   | 227 +++++
 .../security/openssl/kae_exception.c          | 116 +++
 .../security/openssl/kae_exception.h          |  52 ++
 .../openssl/kae_keypairgenerator_rsa.c        | 173 ++++
 .../org/openeuler/security/openssl/kae_log.h  |  33 +
 .../org/openeuler/security/openssl/kae_mac.c  | 201 +++++
 .../openeuler/security/openssl/kae_provider.c |  47 ++
 .../org/openeuler/security/openssl/kae_util.c | 102 +++
 .../org/openeuler/security/openssl/kae_util.h |  39 +
 jdk/test/java/net/URLPermission/policy.1      |   1 +
 jdk/test/java/net/URLPermission/policy.2      |   1 +
 jdk/test/java/net/URLPermission/policy.3      |   1 +
 .../bench/security/openssl/AESBenchmark.java  | 108 +++
 .../bench/security/openssl/BenchmarkBase.java | 100 +++
 .../security/openssl/DigestBenchmark.java     |  69 ++
 .../bench/security/openssl/HMacBenchmark.java |  73 ++
 .../security/openssl/RSACipherBenchmark.java  | 107 +++
 .../openssl/RSAKeyPairGeneratorBenchmark.java |  63 ++
 .../sun/security/krb5/auto/BasicProc.java     |   4 +-
 39 files changed, 5066 insertions(+), 3 deletions(-)
 create mode 100644 jdk/make/mapfiles/libj2kae/mapfile-vers
 create mode 100644 jdk/src/solaris/classes/org/openeuler/security/openssl/KAEAESCipher.java
 create mode 100644 jdk/src/solaris/classes/org/openeuler/security/openssl/KAEDigest.java
 create mode 100644 jdk/src/solaris/classes/org/openeuler/security/openssl/KAEMac.java
 create mode 100644 jdk/src/solaris/classes/org/openeuler/security/openssl/KAEProvider.java
 create mode 100644 jdk/src/solaris/classes/org/openeuler/security/openssl/KAERSACipher.java
 create mode 100644 jdk/src/solaris/classes/org/openeuler/security/openssl/KAERSAKeyPairGenerator.java
 create mode 100644 jdk/src/solaris/classes/org/openeuler/security/openssl/KAERSAPaddingType.java
 create mode 100644 jdk/src/solaris/classes/org/openeuler/security/openssl/KAEUtils.java
 create mode 100644 jdk/src/solaris/native/org/openeuler/security/openssl/kae_cipher_aes.c
 create mode 100644 jdk/src/solaris/native/org/openeuler/security/openssl/kae_cipher_rsa.c
 create mode 100644 jdk/src/solaris/native/org/openeuler/security/openssl/kae_digest.c
 create mode 100644 jdk/src/solaris/native/org/openeuler/security/openssl/kae_exception.c
 create mode 100644 jdk/src/solaris/native/org/openeuler/security/openssl/kae_exception.h
 create mode 100644 jdk/src/solaris/native/org/openeuler/security/openssl/kae_keypairgenerator_rsa.c
 create mode 100644 jdk/src/solaris/native/org/openeuler/security/openssl/kae_log.h
 create mode 100644 jdk/src/solaris/native/org/openeuler/security/openssl/kae_mac.c
 create mode 100644 jdk/src/solaris/native/org/openeuler/security/openssl/kae_provider.c
 create mode 100644 jdk/src/solaris/native/org/openeuler/security/openssl/kae_util.c
 create mode 100644 jdk/src/solaris/native/org/openeuler/security/openssl/kae_util.h
 create mode 100644 jdk/test/micro/org/openeuler/bench/security/openssl/AESBenchmark.java
 create mode 100644 jdk/test/micro/org/openeuler/bench/security/openssl/BenchmarkBase.java
 create mode 100644 jdk/test/micro/org/openeuler/bench/security/openssl/DigestBenchmark.java
 create mode 100644 jdk/test/micro/org/openeuler/bench/security/openssl/HMacBenchmark.java
 create mode 100644 jdk/test/micro/org/openeuler/bench/security/openssl/RSACipherBenchmark.java
 create mode 100644 jdk/test/micro/org/openeuler/bench/security/openssl/RSAKeyPairGeneratorBenchmark.java

diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh
index d754f1d6..ea43a7a0 100644
--- a/common/autoconf/generated-configure.sh
+++ b/common/autoconf/generated-configure.sh
@@ -845,6 +845,7 @@ JDK_MINOR_VERSION
 JDK_MAJOR_VERSION
 USER_RELEASE_SUFFIX
 ENABLE_JFR
+ENABLE_KAE
 COMPRESS_JARS
 UNLIMITED_CRYPTO
 CACERTS_FILE
@@ -1060,6 +1061,7 @@ enable_hotspot_test_in_build
 with_cacerts_file
 enable_unlimited_crypto
 enable_jfr
+enable_kae
 with_milestone
 with_update_version
 with_user_release_suffix
@@ -1847,6 +1849,7 @@ Optional Features:
   --enable-unlimited-crypto
                           Enable unlimited crypto policy [disabled]
   --disable-jfr           Disable Java Flight Recorder support [enabled]
+  --disable-kae           Disable KAE support on aarch64 [enabled]
   --disable-debug-symbols disable generation of debug symbols [enabled]
   --disable-zip-debug-info
                           disable zipping of debug-info files [enabled]
@@ -19843,6 +19846,31 @@ fi
 $as_echo "$ENABLE_JFR" >&6; }
 
 
+  ###############################################################################
+  #
+  # Enable or disable KAE
+  #
+  # Check whether --enable-kae was given.
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build KAE" >&5
+$as_echo_n "checking whether to build KAE... " >&6; }
+if test "${enable_kae+set}" = set; then :
+  enableval=$enable_kae; enable_kae="${enableval}"
+else
+  #default enable on aarch64
+  if test "x$OPENJDK_TARGET_CPU" = xaarch64; then
+    enable_kae="yes"
+  else
+    enable_kae="no"
+  fi
+fi
+
+  if test "x$enable_kae" = "xyes"; then
+    ENABLE_KAE=true
+  elif test "x$enable_kae" = "xno"; then
+    ENABLE_KAE=false
+  fi
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ENABLE_KAE" >&5
+$as_echo "$ENABLE_KAE" >&6; }
 
   # Source the version numbers
   . $AUTOCONF_DIR/version-numbers
diff --git a/common/autoconf/jdk-options.m4 b/common/autoconf/jdk-options.m4
index e4eb2352..23db9275 100644
--- a/common/autoconf/jdk-options.m4
+++ b/common/autoconf/jdk-options.m4
@@ -461,6 +461,20 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_JDK_OPTIONS],
   fi
   AC_MSG_RESULT([$ENABLE_JFR])
   AC_SUBST(ENABLE_JFR)
+
+  ###############################################################################
+  #
+  # Enable or disable kae
+  #
+  AC_ARG_ENABLE(kae, [AS_HELP_STRING([--disable-kae],
+      [disable KAE @<:@disabled@:>@])],,
+      [enable_kae=no])
+  if test "x$enable_kae" = "xyes"; then
+    ENABLE_KAE=true
+  else
+    ENABLE_KAE=false
+  fi
+  AC_SUBST(ENABLE_KAE)
 ])
 
 ###############################################################################
diff --git a/common/autoconf/spec.gmk.in b/common/autoconf/spec.gmk.in
index 506cf617..4c3a9f61 100644
--- a/common/autoconf/spec.gmk.in
+++ b/common/autoconf/spec.gmk.in
@@ -602,6 +602,7 @@ endif
 
 # Build setup
 ENABLE_JFR=@ENABLE_JFR@
+ENABLE_KAE=@ENABLE_KAE@
 ENABLE_INTREE_EC=@ENABLE_INTREE_EC@
 USE_EXTERNAL_LIBJPEG:=@USE_EXTERNAL_LIBJPEG@
 USE_EXTERNAL_LIBGIF:=@USE_EXTERNAL_LIBGIF@
diff --git a/jdk/make/CompileJavaClasses.gmk b/jdk/make/CompileJavaClasses.gmk
index 3ec63e87..b0ae8e97 100644
--- a/jdk/make/CompileJavaClasses.gmk
+++ b/jdk/make/CompileJavaClasses.gmk
@@ -284,6 +284,7 @@ endif
 # The security classes should not end up in the classes directory as that will prevent them
 # from working when running the exploded jdk image. Compile them separately to a different
 # directory from where the jars can be created.
+
 SECURITY_PKGS := \
     com/oracle/security/ucrypto \
     com/sun/crypto/provider \
@@ -294,6 +295,9 @@ SECURITY_PKGS := \
     sun/security/pkcs11 \
     #
 
+# KAE classes
+KAE_PKG := org/openeuler/security/openssl
+
 AIX_SRC_DIRS :=
 ifeq ($(OPENJDK_TARGET_OS),aix)
      AIX_SRC_DIRS += $(JDK_TOPDIR)/src/aix/classes
@@ -339,7 +343,7 @@ $(eval $(call SetupJavaCompilation,BUILD_JDK,\
         $(JDK_OUTPUTDIR)/gensrc_no_srczip \
         $(CLOSED_SRC_DIRS),\
     INCLUDES:=$(JDK_USER_DEFINED_FILTER),\
-    EXCLUDES:=$(EXCLUDES) $(SECURITY_PKGS),\
+    EXCLUDES:=$(EXCLUDES) $(SECURITY_PKGS) $(KAE_PKG),\
     EXCLUDE_FILES:=$(EXFILES),\
     BIN:=$(JDK_OUTPUTDIR)/classes,\
     COPY:=$(COPY_PATTERNS),\
@@ -363,6 +367,26 @@ $(eval $(call SetupJavaCompilation,BUILD_SECURITY, \
 
 $(BUILD_SECURITY): $(BUILD_JDK)
 
+
+##########################################################################################
+ifeq ($(ENABLE_KAE), true)
+  ifeq ($(OPENJDK_TARGET_CPU_ARCH), aarch64)
+    $(eval $(call SetupJavaCompilation,BUILD_KAE, \
+        SETUP := GENERATE_JDKBYTECODE, \
+        SRC := $(JDK_TOPDIR)/src/share/classes \
+            $(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/classes \
+            $(MACOSX_SRC_DIRS) \
+            $(CLOSED_SRC_DIRS), \
+        INCLUDES := $(KAE_PKG), \
+        EXCLUDES := $(EXCLUDES), \
+        EXCLUDE_FILES := $(EXFILES), \
+        BIN := $(JDK_OUTPUTDIR)/classes_kae, \
+        HEADERS := $(JDK_OUTPUTDIR)/gensrc_headers))
+
+    $(BUILD_KAE): $(BUILD_JDK)
+  endif
+endif
+
 ##########################################################################################
 
 $(JDK_OUTPUTDIR)/classes/META-INF/services/com.sun.tools.xjc.Plugin:
@@ -410,7 +434,7 @@ $(JDK_OUTPUTDIR)/classes/META-INF/services/com.sun.tools.xjc.Plugin:
 
 ##########################################################################################
 
-all: $(BUILD_JDK) $(BUILD_SECURITY) $(COPY_EXTRA) \
+all: $(BUILD_JDK) $(BUILD_SECURITY) $(BUILD_KAE) $(COPY_EXTRA) \
     $(JDK_OUTPUTDIR)/classes/META-INF/services/com.sun.tools.xjc.Plugin \
     $(BUILD_ACCESSBRIDGE_32) $(BUILD_ACCESSBRIDGE_64) \
     $(BUILD_ACCESSBRIDGE_LEGACY)
diff --git a/jdk/make/CreateJars.gmk b/jdk/make/CreateJars.gmk
index 559a62b6..cb3f26b3 100644
--- a/jdk/make/CreateJars.gmk
+++ b/jdk/make/CreateJars.gmk
@@ -168,6 +168,7 @@ RT_JAR_EXCLUDES += \
     META-INF/services/com.sun.tools.attach.spi.AttachProvider \
     META-INF/services/com.sun.tools.xjc.Plugin \
     META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor \
+    org/openeuler/security \
     org/relaxng/datatype \
     sun/awt/HKSCS.class \
     sun/awt/motif/X11GB2312.class \
diff --git a/jdk/make/CreateSecurityJars.gmk b/jdk/make/CreateSecurityJars.gmk
index da9cc207..e991d994 100644
--- a/jdk/make/CreateSecurityJars.gmk
+++ b/jdk/make/CreateSecurityJars.gmk
@@ -371,6 +371,35 @@ ifeq ($(OPENJDK_TARGET_OS), solaris)
 
   endif
 endif
+##########################################################################################
+
+ifeq ($(ENABLE_KAE), true)
+  ifeq ($(OPENJDK_TARGET_CPU_ARCH), aarch64)
+    KAE_JAR_DST := $(JDK_OUTPUTDIR)/lib/ext/kae_openssl.jar
+    KAE_JAR_UNSIGNED := $(JDK_OUTPUTDIR)/jce/unsigned/kae_openssl.jar
+
+  $(eval $(call SetupArchive,BUILD_OPENSSL_JAR, , \
+        SRCS := $(JDK_OUTPUTDIR)/classes_kae, \
+        SUFFIXES := .class, \
+        INCLUDES := org/openeuler/security/openssl, \
+        JAR := $(KAE_JAR_UNSIGNED), \
+        MANIFEST := $(JCE_MANIFEST), \
+        SKIP_METAINF := true))
+  $(KAE_JAR_UNSIGNED): $(JCE_MANIFEST)
+  ifndef OPENJDK
+    KAE_JAR_SRC := $(JDK_TOPDIR)/make/closed/tools/crypto/openssl/kae_openssl.jar
+    $(KAE_JAR_DST): $(KAE_JAR_SRC)
+	@$(ECHO) $(LOG_INFO) Copying prebuilt $(@F)
+	$(install-file)
+  else
+    $(KAE_JAR_DST): $(KAE_JAR_UNSIGNED)
+	$(install-file)
+  endif
+
+  TARGETS += $(KAE_JAR_UNSIGNED) $(KAE_JAR_DST)
+
+  endif
+endif
 
 all: $(TARGETS)
 
diff --git a/jdk/make/SignJars.gmk b/jdk/make/SignJars.gmk
index 21647889..babd8684 100644
--- a/jdk/make/SignJars.gmk
+++ b/jdk/make/SignJars.gmk
@@ -99,6 +99,12 @@ JAR_LIST := \
     ucrypto.jar \
     #
 
+ifeq ($(ENABLE_KAE), true)
+  ifeq ($(OPENJDK_TARGET_CPU_ARCH), aarch64)
+      JAR_LIST += kae_openssl.jar
+  endif
+endif
+
 UNSIGNED_JARS := $(wildcard $(addprefix $(JDK_OUTPUTDIR)/jce/unsigned/, $(JAR_LIST)))
 
 ifeq ($(UNSIGNED_JARS), )
diff --git a/jdk/make/lib/SecurityLibraries.gmk b/jdk/make/lib/SecurityLibraries.gmk
index a8eeceb3..62226836 100644
--- a/jdk/make/lib/SecurityLibraries.gmk
+++ b/jdk/make/lib/SecurityLibraries.gmk
@@ -287,3 +287,28 @@ ifeq ($(OPENJDK_TARGET_OS), solaris)
 
   endif
 endif
+##########################################################################################
+ifeq ($(ENABLE_KAE), true)
+  ifeq ($(OPENJDK_TARGET_CPU_ARCH), aarch64)
+    $(eval $(call SetupNativeCompilation,BUILD_LIBJ2KAE, \
+        LIBRARY := j2kae, \
+        OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
+        SRC := $(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/native/org/openeuler/security/openssl, \
+        LANG := C, \
+        OPTIMIZATION := LOW, \
+        EXTRA_FILES := $(HOTSPOT_TOPDIR)/src/os_cpu/linux_x86/vm/memcpy.cpp, \
+        CFLAGS := $(CFLAGS_JDKLIB) \
+             -I$(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/native/org/openeuler/security/openssl, \
+        MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libj2kae/mapfile-vers, \
+        LDFLAGS := $(LDFLAGS_JDKLIB) \
+              $(call SET_SHARED_LIBRARY_ORIGIN), \
+        LDFLAGS_SUFFIX_linux := $(LIBDL) -lssl -lcrypto, \
+        LDFLAGS_SUFFIX_posix := $(LIBDL), \
+        LDFLAGS_SUFFIX_solaris := -lc, \
+        VERSIONINFO_RESOURCE := $(JDK_TOPDIR)/src/windows/resource/version.rc, \
+        OBJECT_DIR := $(JDK_OUTPUTDIR)/objs/libj2kae, \
+        DEBUG_SYMBOLS := $(DEBUG_ALL_BINARIES)))
+
+    BUILD_LIBRARIES += $(BUILD_LIBJ2KAE)
+  endif
+endif
diff --git a/jdk/make/mapfiles/libj2kae/mapfile-vers b/jdk/make/mapfiles/libj2kae/mapfile-vers
new file mode 100644
index 00000000..6ed331b2
--- /dev/null
+++ b/jdk/make/mapfiles/libj2kae/mapfile-vers
@@ -0,0 +1,57 @@
+#
+# Copyright (c) 2020, 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.
+#
+
+# Define public interface.
+
+SUNWprivate_1.1 {
+	global:
+		JNI_OnLoad;
+		Java_org_openeuler_security_openssl_KAEProvider_initOpenssl;
+		Java_org_openeuler_security_openssl_KAEDigest_nativeInit;
+		Java_org_openeuler_security_openssl_KAEDigest_nativeUpdate;
+		Java_org_openeuler_security_openssl_KAEDigest_nativeDigest;
+		Java_org_openeuler_security_openssl_KAEDigest_nativeClone;
+		Java_org_openeuler_security_openssl_KAEDigest_nativeFree;
+		Java_org_openeuler_security_openssl_KAEAESCipher_nativeInit;
+		Java_org_openeuler_security_openssl_KAEAESCipher_nativeUpdate;
+		Java_org_openeuler_security_openssl_KAEAESCipher_nativeFinal;
+		Java_org_openeuler_security_openssl_KAEAESCipher_nativeFree;
+		Java_org_openeuler_security_openssl_KAEMac_nativeInit;
+		Java_org_openeuler_security_openssl_KAEMac_nativeUpdate;
+		Java_org_openeuler_security_openssl_KAEMac_nativeFinal;
+		Java_org_openeuler_security_openssl_KAEMac_nativeFree;
+		Java_org_openeuler_security_openssl_KAERSAKeyPairGenerator_nativeGenerateKeyPair;
+		Java_org_openeuler_security_openssl_KAERSACipher_nativeCreateRSAPrivateCrtKey;
+		Java_org_openeuler_security_openssl_KAERSACipher_nativeCreateRSAPrivateKey;
+		Java_org_openeuler_security_openssl_KAERSACipher_nativeCreateRSAPublicKey;
+		Java_org_openeuler_security_openssl_KAERSACipher_nativeRSAPrivateEncrypt;
+		Java_org_openeuler_security_openssl_KAERSACipher_nativeRSAPrivateDecrypt;
+		Java_org_openeuler_security_openssl_KAERSACipher_nativeRSAPublicEncrypt;
+		Java_org_openeuler_security_openssl_KAERSACipher_nativeRSAPublicDecrypt;
+		Java_org_openeuler_security_openssl_KAERSACipher_nativeRSAEncryptOAEPPadding;
+		Java_org_openeuler_security_openssl_KAERSACipher_nativeRSADecryptOAEPPadding;
+		Java_org_openeuler_security_openssl_KAERSACipher_nativeFreeKey;
+
+	local:
+		*;
+};
diff --git a/jdk/make/profile-includes.txt b/jdk/make/profile-includes.txt
index 68bb27e5..013c426c 100644
--- a/jdk/make/profile-includes.txt
+++ b/jdk/make/profile-includes.txt
@@ -195,6 +195,12 @@ PROFILE_1_JRE_LIB_FILES += \
     security/trusted.libraries \
     tzdb.dat
 
+ifeq ($(ENABLE_KAE), true)
+  ifeq ($(OPENJDK_TARGET_CPU_ARCH), aarch64)
+      PROFILE_1_JRE_LIB_FILES += ext/kae_openssl.jar
+  endif
+endif
+
 ifeq ($(OPENJDK_TARGET_OS), windows)
     PROFILE_1_JRE_LIB_FILES += tzmappings
 else
@@ -225,6 +231,12 @@ PROFILE_1_JRE_JAR_FILES := \
     security/policy/limited/local_policy.jar \
     security/policy/unlimited/local_policy.jar
 
+ifeq ($(ENABLE_KAE), true)
+  ifeq ($(OPENJDK_TARGET_CPU_ARCH), aarch64)
+      PROFILE_1_JRE_JAR_FILES += ext/kae_openssl.jar
+  endif
+endif
+
 
 PROFILE_2_JRE_BIN_FILES := \
     rmid$(EXE_SUFFIX) \
diff --git a/jdk/src/solaris/classes/org/openeuler/security/openssl/KAEAESCipher.java b/jdk/src/solaris/classes/org/openeuler/security/openssl/KAEAESCipher.java
new file mode 100644
index 00000000..2dd5bf4a
--- /dev/null
+++ b/jdk/src/solaris/classes/org/openeuler/security/openssl/KAEAESCipher.java
@@ -0,0 +1,725 @@
+/*
+ * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.openeuler.security.openssl;
+
+import sun.security.jca.JCAUtil;
+
+import java.lang.ref.PhantomReference;
+import java.lang.ref.ReferenceQueue;
+import java.security.*;
+import java.security.spec.*;
+import java.util.Arrays;
+import java.util.Locale;
+import java.util.Set;
+import java.util.concurrent.ConcurrentSkipListSet;
+
+import javax.crypto.*;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+
+/*
+ * Cipher wrapper class utilizing openssl APIs. This class currently supports
+ * - AES/ECB/NOPADDING
+ * - AES/ECB/PKCS5PADDING
+ * - AES/CBC/NOPADDING
+ * - AES/CBC/PKCS5PADDING
+ * - AES/CTR/NOPADDING
+ */
+abstract class KAEAESCipher extends CipherSpi {
+
+    public static class Aes extends KAEAESCipher {
+        public Aes(Mode mode, Padding padding) {
+            super(mode, padding, -1);
+        }
+
+        public static class Cbc extends Aes {
+            public Cbc(Padding padding) {
+                super(Mode.CBC, padding);
+            }
+            public static class NoPadding extends Cbc {
+                public NoPadding() {
+                    super(Padding.NOPADDING);
+                }
+            }
+            public static class PKCS5Padding extends Cbc {
+                public PKCS5Padding() {
+                    super(Padding.PKCS5PADDING);
+                }
+            }
+        }
+        public static class Ecb extends Aes {
+            public Ecb(Padding padding) {
+                super(Mode.ECB, padding);
+            }
+            public static class NoPadding extends Ecb {
+                public NoPadding() {
+                    super(Padding.NOPADDING);
+                }
+            }
+            public static class PKCS5Padding extends Ecb {
+                public PKCS5Padding() {
+                    super(Padding.PKCS5PADDING);
+                }
+            }
+        }
+
+        public static class Ctr extends Aes {
+            public Ctr(Padding padding) {
+                super(Mode.CTR, padding);
+            }
+            public static class NoPadding extends Ctr {
+                public NoPadding() {
+                    super(Padding.NOPADDING);
+                }
+            }
+        }
+    }
+
+    public static class Aes_128 extends KAEAESCipher {
+        public Aes_128(Mode mode, Padding padding) {
+            super(mode, padding, 16);
+        }
+        public static class Cbc extends Aes_128 {
+            public Cbc(Padding padding) {
+                super(Mode.CBC, padding);
+            }
+            public static class NoPadding extends Cbc {
+                public NoPadding() {
+                    super(Padding.NOPADDING);
+                }
+            }
+            public static class PKCS5Padding extends Cbc {
+                public PKCS5Padding() {
+                    super(Padding.PKCS5PADDING);
+                }
+            }
+        }
+        public static class Ecb extends Aes_128 {
+            public Ecb(Padding padding) {
+                super(Mode.ECB, padding);
+            }
+            public static class NoPadding extends Ecb {
+                public NoPadding() {
+                    super(Padding.NOPADDING);
+                }
+            }
+            public static class PKCS5Padding extends Ecb {
+                public PKCS5Padding() {
+                    super(Padding.PKCS5PADDING);
+                }
+            }
+        }
+
+        public static class Ctr extends Aes_128 {
+            public Ctr(Padding padding) {
+                super(Mode.CTR, padding);
+            }
+            public static class NoPadding extends Ctr {
+                public NoPadding() {
+                    super(Padding.NOPADDING);
+                }
+            }
+        }
+    }
+
+    public static class Aes_192 extends KAEAESCipher {
+        public Aes_192(Mode mode, Padding padding) {
+            super(mode, padding, 24);
+        }
+        public static class Cbc extends Aes_192 {
+            public Cbc(Padding padding) {
+                super(Mode.CBC, padding);
+            }
+            public static class NoPadding extends Cbc {
+                public NoPadding() {
+                    super(Padding.NOPADDING);
+                }
+            }
+            public static class PKCS5Padding extends Cbc {
+                public PKCS5Padding() {
+                    super(Padding.PKCS5PADDING);
+                }
+            }
+        }
+        public static class Ecb extends Aes_192 {
+            public Ecb(Padding padding) {
+                super(Mode.ECB, padding);
+            }
+            public static class NoPadding extends Ecb {
+                public NoPadding() {
+                    super(Padding.NOPADDING);
+                }
+            }
+            public static class PKCS5Padding extends Ecb {
+                public PKCS5Padding() {
+                    super(Padding.PKCS5PADDING);
+                }
+            }
+        }
+
+        public static class Ctr extends Aes_192 {
+            public Ctr(Padding padding) {
+                super(Mode.CTR, padding);
+            }
+            public static class NoPadding extends Ctr {
+                public NoPadding() {
+                    super(Padding.NOPADDING);
+                }
+            }
+        }
+    }
+
+    public static class Aes_256 extends KAEAESCipher {
+        public Aes_256(Mode mode, Padding padding) {
+            super(mode, padding, 32);
+        }
+        public static class Cbc extends Aes_256 {
+            public Cbc(Padding padding) {
+                super(Mode.CBC, padding);
+            }
+            public static class NoPadding extends Cbc {
+                public NoPadding() {
+                    super(Padding.NOPADDING);
+                }
+            }
+            public static class PKCS5Padding extends Cbc {
+                public PKCS5Padding() {
+                    super(Padding.PKCS5PADDING);
+                }
+            }
+        }
+        public static class Ecb extends Aes_256 {
+            public Ecb(Padding padding) {
+                super(Mode.ECB, padding);
+            }
+            public static class NoPadding extends Ecb {
+                public NoPadding() {
+                    super(Padding.NOPADDING);
+                }
+            }
+            public static class PKCS5Padding extends Ecb {
+                public PKCS5Padding() {
+                    super(Padding.PKCS5PADDING);
+                }
+            }
+        }
+
+        public static class Ctr extends Aes_256 {
+            public Ctr(Padding padding) {
+                super(Mode.CTR, padding);
+            }
+            public static class NoPadding extends Ctr {
+                public NoPadding() {
+                    super(Padding.NOPADDING);
+                }
+            }
+        }
+    }
+
+    enum Padding {
+        NOPADDING,
+        PKCS5PADDING
+    }
+
+    enum Mode {
+        ECB,
+        CBC,
+        CTR,
+    }
+
+    private final String keyAlgo = "AES";
+    private final int blockSize = 16;
+    private Mode mode;
+    private Padding padding;
+    private int fixedKeySize;
+
+    private CipherContextRef pCtx = null;
+    private byte[] keyValue;
+    protected byte[] iv;
+    private boolean initialized = false;
+    private boolean encrypt = false;
+    private int bytesBuffered = 0;
+
+    private boolean calledUpdate;
+    private String cipherName;
+
+    private static final PublicKey constructPublicKey(byte[] encodedKey, String encodedKeyAlgorithm) throws NoSuchAlgorithmException, InvalidKeyException {
+        PublicKey key;
+        try {
+            KeyFactory keyFactory = KeyFactory.getInstance(encodedKeyAlgorithm);
+            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(encodedKey);
+            key = keyFactory.generatePublic(keySpec);
+        } catch (NoSuchAlgorithmException e) {
+            throw new NoSuchAlgorithmException("No provider found for " + encodedKeyAlgorithm + " KeyFactory");
+        } catch (InvalidKeySpecException e) {
+            throw new InvalidKeyException("Cannot construct public key", e);
+        }
+        return key;
+    }
+
+    private static final PrivateKey constructPrivateKey(byte[] encodedKey,
+            String encodedKeyAlgorithm) throws InvalidKeyException, NoSuchAlgorithmException {
+        PrivateKey key = null;
+        try {
+            KeyFactory keyFactory = KeyFactory.getInstance(encodedKeyAlgorithm);
+            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encodedKey);
+            key = keyFactory.generatePrivate(keySpec);
+        } catch (NoSuchAlgorithmException e) {
+            throw new NoSuchAlgorithmException("No provider found for " + encodedKeyAlgorithm + " KeyFactory");
+        } catch (InvalidKeySpecException e) {
+            throw new InvalidKeyException("Cannot construct private key", e);
+        }
+        return key;
+    }
+
+    private static final SecretKey constructSecretKey(byte[] encodedKey, String encodedKeyAlgorithm) {
+        return new SecretKeySpec(encodedKey, encodedKeyAlgorithm);
+    }
+
+    static final Key constructKey(int keyType, byte[] encodedKey,
+            String encodedKeyAlgorithm) throws NoSuchAlgorithmException, InvalidKeyException {
+        Key res = null;
+        switch (keyType) {
+            case Cipher.SECRET_KEY:
+                res = constructSecretKey(encodedKey, encodedKeyAlgorithm);
+                break;
+            case Cipher.PRIVATE_KEY:
+                res = constructPrivateKey(encodedKey, encodedKeyAlgorithm);
+                break;
+            case Cipher.PUBLIC_KEY:
+                res = constructPublicKey(encodedKey, encodedKeyAlgorithm);
+                break;
+            default:
+                throw new InvalidKeyException("Unknown keytype " + keyType);
+        }
+        return res;
+    }
+
+    KAEAESCipher(Mode mode, Padding padding, int fixedKeySize) {
+        this.mode = mode;
+        this.padding = padding;
+        this.fixedKeySize = fixedKeySize;
+    }
+
+    private static class CipherContextRef extends PhantomReference<KAEAESCipher> implements Comparable<CipherContextRef> {
+
+        private static ReferenceQueue<KAEAESCipher> refQueue = new ReferenceQueue<>();
+        private static Set<CipherContextRef> refList = new ConcurrentSkipListSet<>();
+        private static boolean disableKaeDispose = Boolean.getBoolean("kae.disableKaeDispose");
+
+        final long ctxAddress;
+
+        private static void drainRefQueueBounded() {
+            while (true) {
+                CipherContextRef next = (CipherContextRef) refQueue.poll();
+                if (next == null) {
+                    break;
+                }
+                next.dispose(true);
+            }
+        }
+
+        CipherContextRef(KAEAESCipher kaeCipher, long ctxAddress) {
+            super(kaeCipher, refQueue);
+            this.ctxAddress = ctxAddress;
+            if (!disableKaeDispose) {
+                refList.add(this);
+                drainRefQueueBounded();
+            }
+        }
+
+        @Override
+        public int compareTo(CipherContextRef o) {
+            if (this.ctxAddress == o.ctxAddress) {
+                return 0;
+            } else {
+                return (this.ctxAddress < o.ctxAddress) ? -1 : 1;
+            }
+        }
+
+        void dispose(boolean needFree) {
+            if (!disableKaeDispose) {
+                refList.remove(this);
+                try {
+                    if (needFree) {
+                        nativeFree(ctxAddress);
+                    }
+                } finally {
+                    this.clear();
+                }
+            } else {
+                nativeFree(ctxAddress);
+            }
+        }
+    }
+
+
+    @Override
+    protected void engineSetMode(String modeStr) throws NoSuchAlgorithmException {
+        if (modeStr == null) {
+            throw new NoSuchAlgorithmException("null mode");
+        }
+
+        if (modeStr.equalsIgnoreCase("ECB")) {
+            mode = Mode.ECB;
+        } else if (modeStr.equalsIgnoreCase("CBC")) {
+            mode = Mode.CBC;
+        } else if (modeStr.equalsIgnoreCase("CTR")) {
+            mode = Mode.CTR;
+        } else {
+            throw new NoSuchAlgorithmException("Unsupported mode " + mode);
+        }
+
+    }
+
+    @Override
+    protected void engineSetPadding(String paddingStr) throws NoSuchPaddingException {
+        if (paddingStr == null) {
+            throw new NoSuchPaddingException("null padding");
+        }
+
+        if (paddingStr.equalsIgnoreCase("NOPADDING")) {
+            this.padding = Padding.NOPADDING;
+        } else if(paddingStr.equalsIgnoreCase("PKCS5PADDING")) {
+            if (mode == Mode.CTR) {
+                throw new NoSuchPaddingException("PKCS#5 padding not supported with CTR mode");
+            }
+            this.padding = Padding.PKCS5PADDING;
+        } else {
+            throw new NoSuchPaddingException("Unsupported padding "+padding);
+        }
+    }
+
+
+    @Override
+    protected int engineGetBlockSize() {
+        return blockSize;
+    }
+
+    @Override
+    protected int engineGetOutputSize(int inputLen) {
+        return getOutputSizeByOperation(inputLen, true);
+    }
+
+    @Override
+    protected byte[] engineGetIV() {
+        return iv == null ? null : iv.clone();
+    }
+
+    @Override
+    protected AlgorithmParameters engineGetParameters() {
+        if (iv == null) {
+            return null;
+        }
+        IvParameterSpec ivSpec = new IvParameterSpec(iv.clone());
+        try {
+            AlgorithmParameters params = AlgorithmParameters.getInstance(keyAlgo);
+            params.init(ivSpec);
+            return params;
+        } catch (GeneralSecurityException e) {
+            throw new RuntimeException("Could not encode parameters", e);
+        }
+    }
+
+    @Override
+    protected void engineInit(int opmode, Key key, SecureRandom random) throws InvalidKeyException {
+        try {
+            engineInit(opmode, key, (AlgorithmParameterSpec) null, random);
+        } catch (InvalidAlgorithmParameterException e) {
+            throw new InvalidKeyException("init() failed", e);
+        }
+    }
+
+    @Override
+    protected void engineInit(int opmode, Key key, AlgorithmParameters params,
+                    SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException {
+        AlgorithmParameterSpec ivSpec = null;
+        if (params != null) {
+            try {
+                ivSpec = params.getParameterSpec(IvParameterSpec.class);
+            } catch (InvalidParameterSpecException e) {
+                throw new InvalidAlgorithmParameterException("Could not decode IV", e);
+            }
+        }
+        engineInit(opmode, key, ivSpec, random);
+    }
+
+    @Override
+    protected void engineInit(int opmode, Key key, AlgorithmParameterSpec params,
+                    SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException {
+        checkKey(key);
+        boolean doEncrypt = (opmode == Cipher.ENCRYPT_MODE || opmode == Cipher.WRAP_MODE);
+
+        byte[] ivBytes = null;
+
+        if (params != null) {
+            if (!(params instanceof IvParameterSpec)) {
+                throw new InvalidKeyException("IvParameterSpec required. Received: " + params.getClass().getName());
+            } else {
+                ivBytes = ((IvParameterSpec) params).getIV();
+                if (ivBytes.length != blockSize) {
+                    throw new InvalidAlgorithmParameterException("Wrong IV length: must be " + blockSize +
+                                    " bytes long. Received length:" + ivBytes.length);
+                }
+            }
+        }
+        if (mode == Mode.ECB) {
+            if (params != null) {
+                throw new InvalidAlgorithmParameterException("No Parameters for ECB mode");
+            }
+        } else if (ivBytes == null) {
+            if (doEncrypt) {
+                ivBytes = new byte[blockSize];
+                if (random == null) {
+                    random = JCAUtil.getSecureRandom();
+                }
+                random.nextBytes(ivBytes);
+            } else {
+                throw new InvalidAlgorithmParameterException("Parameters required for decryption");
+            }
+        }
+        implInit(doEncrypt, key.getEncoded(), ivBytes);
+    }
+
+    private void implInit(boolean encrypt, byte[] keyVal, byte[] ivVal) {
+
+        reset(true);
+        this.encrypt = encrypt;
+        this.keyValue = keyVal;
+        this.iv = ivVal;
+        this.cipherName = "aes-" + (keyVal.length * 8) + "-" + mode.toString().toLowerCase(Locale.US);
+
+        // OpenSSL only supports PKCS5 Padding
+        long pCtxVal;
+        try {
+            pCtxVal = nativeInit(cipherName, encrypt, keyValue, iv, padding == Padding.PKCS5PADDING);
+        } catch (RuntimeException e) {
+            throw new ProviderException("Invoke nativeInit failed for " + cipherName, e);
+        }
+
+        initialized = (pCtxVal != 0L);
+        if (initialized) {
+            pCtx = new CipherContextRef(this, pCtxVal);
+        } else {
+            throw new NullPointerException("pCtxVal == 0");
+        }
+        calledUpdate = false;
+    }
+
+    final int checkKey(Key key) throws InvalidKeyException {
+        if (key == null || key.getEncoded() == null) {
+            throw new InvalidKeyException("Key cannot be null");
+        } else {
+            if (!keyAlgo.equalsIgnoreCase(key.getAlgorithm())) {
+                throw new InvalidKeyException("Key algorithm must be " + keyAlgo);
+            }
+            int keyLen = key.getEncoded().length;
+            if (fixedKeySize == -1) {
+                if (keyLen != 16 && keyLen != 24 & keyLen != 32) {
+                    throw new InvalidKeyException("Key size is not valid. Got key length of: " + keyLen);
+                }
+            } else {
+                if (keyLen != fixedKeySize) {
+                    throw new InvalidKeyException("Only " + fixedKeySize + "-byte keys are accepted. Got: " + keyLen);
+                }
+            }
+            return keyLen;
+        }
+    }
+
+    @Override
+    protected byte[] engineUpdate(byte[] input, int inputOffset, int inputLen) {
+        byte[] out = new byte[getOutputSizeByOperation(inputLen, false)];
+        int n = implUpdate(input, inputOffset, inputLen, out, 0);
+        if (n == 0) {
+            return new byte[0];
+        } else if (out.length != n) {
+            out = Arrays.copyOf(out, n);
+        }
+        return out;
+    }
+
+    @Override
+    protected int engineUpdate(byte[] input, int inputOffset, int inputLen, byte[] output,
+                    int outputOffset) throws ShortBufferException {
+        int min = getOutputSizeByOperation(inputLen, false);
+        if (output.length - outputOffset < min) {
+            throw new ShortBufferException("min" + min + "-byte buffer needed");
+        }
+        return implUpdate(input, inputOffset, inputLen, output, outputOffset);
+    }
+
+    private int implUpdate(byte[] in, int inOfs, int inLen, byte[] output, int outOfs) {
+        ensureInitialized();
+        if (inLen <= 0) {
+            return 0;
+        }
+        int k;
+        try {
+            k = nativeUpdate(pCtx.ctxAddress, in, inOfs, inLen, output, outOfs);
+        } catch (ArrayIndexOutOfBoundsException e) {
+            reset(true);
+            throw new ProviderException("Invoke nativeUpdate failed for " + cipherName, e);
+        }
+        bytesBuffered += (inLen - k);
+
+        calledUpdate = true;
+        return k;
+    }
+
+    protected int getOutputSizeByOperation(int inLen, boolean isDoFinal) {
+        if (inLen <= 0) {
+            inLen = 0;
+        }
+        if (!isDoFinal && inLen == 0) {
+            return 0;
+        }
+        if (padding == Padding.NOPADDING) {
+            return inLen + bytesBuffered;
+        } else {
+            int len = inLen + bytesBuffered;
+
+            /*
+             * The amount of data written may be anything from zero bytes to (inl + cipher_block_size - 1) for encrypt.
+             * Refer to {@link https://www.openssl.org/docs/man1.1.0/man3/EVP_CipherUpdate.html} for details.
+             */
+            len += (len % blockSize != 0 || encrypt) ? blockSize : 0;
+            return len - (len % blockSize);
+        }
+    }
+
+    @Override
+    protected byte[] engineDoFinal(byte[] input, int inputOffset,
+                    int inputLen) throws IllegalBlockSizeException, BadPaddingException {
+        byte[] out = new byte[getOutputSizeByOperation(inputLen, true)];
+        try {
+            int outLen = engineDoFinal(input, inputOffset, inputLen, out, 0);
+            if (out.length != outLen) {
+                out = Arrays.copyOf(out, outLen);
+            }
+            return out;
+        } catch (ShortBufferException e) {
+            throw new ProviderException(e);
+        }
+    }
+
+    @Override
+    protected int engineDoFinal(byte[] input, int inputOffset, int inputLen, byte[] output,
+                    int outputOffset) throws ShortBufferException, IllegalBlockSizeException, BadPaddingException {
+        int outLen = 0;
+        int min = getOutputSizeByOperation(inputLen, true);
+        if (output.length - outputOffset < min) {
+            throw new ShortBufferException("min" + min + "-byte buffer needed");
+        }
+        if (inputLen > 0) {
+            outLen = implUpdate(input, inputOffset, inputLen, output, outputOffset);
+            outputOffset += outLen;
+        }
+        outLen += implDoFinal(output, outputOffset);
+        return outLen;
+    }
+
+    @Override
+    protected byte[] engineWrap(Key key) throws IllegalBlockSizeException, InvalidKeyException {
+        byte[] res = null;
+        try {
+            byte[] encodedKey = key.getEncoded();
+            if (encodedKey == null || encodedKey.length == 0) {
+                throw new InvalidKeyException("Cannot get an encoding of the key to be wrapped");
+            }
+            res = engineDoFinal(encodedKey, 0, encodedKey.length);
+        } catch (BadPaddingException e) {
+            // Should never happen
+        }
+        return res;
+    }
+
+    @Override
+    protected Key engineUnwrap(byte[] wrappedKey, String wrappedKeyAlgorithm,
+                    int wrappedKeyType) throws InvalidKeyException, NoSuchAlgorithmException {
+        byte[] encodedKey;
+        try {
+            encodedKey = engineDoFinal(wrappedKey, 0, wrappedKey.length);
+        } catch (IllegalBlockSizeException | BadPaddingException e) {
+            throw (InvalidKeyException) (new InvalidKeyException()).initCause(e);
+        }
+        return constructKey(wrappedKeyType, encodedKey, wrappedKeyAlgorithm);
+    }
+
+    private int implDoFinal(byte[] out, int outOfs) {
+
+        if (!encrypt && !calledUpdate) {
+            return 0;
+        }
+        ensureInitialized();
+
+        int outLen;
+        try {
+            outLen = nativeFinal(pCtx.ctxAddress, out, outOfs);
+        } catch (ArrayIndexOutOfBoundsException | BadPaddingException e) {
+            throw new ProviderException("Invoke nativeFinal failed for " + cipherName, e);
+        } finally {
+            reset(true);
+        }
+
+        return outLen;
+    }
+
+    protected void reset(boolean doCancel) {
+        initialized = false;
+        bytesBuffered = 0;
+        calledUpdate = false;
+        if (pCtx != null) {
+            pCtx.dispose(doCancel);
+            pCtx = null;
+        }
+    }
+
+    protected native static long nativeInit(String cipherType, boolean encrypt, byte[] key, byte[] iv, boolean padding) throws RuntimeException;
+
+    protected native static int nativeUpdate(long pContext, byte[] in, int inOfs, int inLen, byte[] out,
+                    int outOfs) throws ArrayIndexOutOfBoundsException;
+
+    protected native static int nativeFinal(long pContext, byte[] out,
+                    int outOfs) throws ArrayIndexOutOfBoundsException, BadPaddingException;
+
+    protected native static void nativeFree(long pContext);
+
+    protected void ensureInitialized() {
+        if (!initialized) {
+            reset(true);
+            long pCtxVal = nativeInit(cipherName, encrypt, keyValue, iv, padding == Padding.PKCS5PADDING);
+            initialized = (pCtxVal != 0L);
+            if (initialized) {
+                pCtx = new CipherContextRef(this, pCtxVal);
+            } else {
+                throw new RuntimeException("Cannot initialize Cipher");
+            }
+        }
+    }
+}
+
diff --git a/jdk/src/solaris/classes/org/openeuler/security/openssl/KAEDigest.java b/jdk/src/solaris/classes/org/openeuler/security/openssl/KAEDigest.java
new file mode 100644
index 00000000..bb5c8681
--- /dev/null
+++ b/jdk/src/solaris/classes/org/openeuler/security/openssl/KAEDigest.java
@@ -0,0 +1,264 @@
+/*
+ * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.openeuler.security.openssl;
+
+import java.lang.ref.PhantomReference;
+import java.lang.ref.ReferenceQueue;
+import java.security.DigestException;
+import java.security.MessageDigestSpi;
+import java.security.ProviderException;
+import java.util.Set;
+import java.util.concurrent.ConcurrentSkipListSet;
+
+/**
+ * KAE Digest
+ */
+abstract class KAEDigest extends MessageDigestSpi implements Cloneable {
+
+    public static final class MD5 extends KAEDigest {
+        private static final long initContext = nativeInit("md5");
+
+        public MD5() {
+            super("md5", 16, initContext);
+        }
+    }
+
+    public static final class SM3 extends KAEDigest {
+        private static final long initContext = nativeInit("sm3");
+
+        public SM3() {
+            super("sm3", 32, initContext);
+        }
+    }
+
+    public static final class SHA256 extends KAEDigest {
+        private static final long initContext = nativeInit("sha256");
+
+        public SHA256() {
+            super("sha256", 32, initContext);
+        }
+    }
+
+    public static final class SHA384 extends KAEDigest {
+        private static final long initContext = nativeInit("sha384");
+
+        public SHA384() {
+            super("sha384", 48, initContext);
+        }
+    }
+
+    private final int digestLength;
+
+    private final String algorithm;
+    private final long initContext;
+
+    // field for ensuring native memory is freed
+    private DigestContextRef contextRef = null;
+
+    KAEDigest(String algorithm, int digestLength, long initContext) {
+        this.algorithm = algorithm;
+        this.digestLength = digestLength;
+        this.initContext = initContext;
+    }
+
+    private static class DigestContextRef extends PhantomReference<KAEDigest>
+        implements Comparable<DigestContextRef> {
+
+        private static ReferenceQueue<KAEDigest> referenceQueue = new ReferenceQueue<>();
+        private static Set<DigestContextRef> referenceList = new ConcurrentSkipListSet<>();
+        private static boolean disableKaeDispose = Boolean.getBoolean("kae.disableKaeDispose");
+
+        private final long ctxAddress;
+
+        DigestContextRef(KAEDigest kaeDigest, long ctxAddress) {
+            super(kaeDigest, referenceQueue);
+            this.ctxAddress = ctxAddress;
+            if (!disableKaeDispose) {
+                referenceList.add(this);
+                drainRefQueueBounded();
+            }
+        }
+
+        @Override
+        public int compareTo(DigestContextRef other) {
+            if (this.ctxAddress == other.ctxAddress) {
+                return 0;
+            } else {
+                return (this.ctxAddress < other.ctxAddress) ? -1 : 1;
+            }
+        }
+
+        private static void drainRefQueueBounded() {
+            while (true) {
+                DigestContextRef next = (DigestContextRef) referenceQueue.poll();
+                if (next == null) {
+                    break;
+                }
+                next.dispose();
+            }
+        }
+
+        void dispose() {
+            if (!disableKaeDispose) {
+                referenceList.remove(this);
+                try {
+                    nativeFree(ctxAddress);
+                } finally {
+                    this.clear();
+                }
+            } else {
+                nativeFree(ctxAddress);
+            }
+        }
+    }
+
+    // single byte update. See JCA doc.
+    @Override
+    protected synchronized void engineUpdate(byte input) {
+        byte[] oneByte = new byte[]{input};
+        engineUpdate(oneByte, 0, 1);
+    }
+
+
+    // array update. See JCA doc.
+    @Override
+    protected synchronized void engineUpdate(byte[] input, int offset, int len) {
+        if (len == 0 || input == null) {
+            return;
+        }
+        if ((offset < 0) || (len < 0) || (offset > input.length - len)) {
+            throw new ArrayIndexOutOfBoundsException();
+        }
+        if (contextRef == null) {
+            contextRef = createDigestContext(this);
+        }
+
+        try {
+            nativeUpdate(contextRef.ctxAddress, input, offset, len);
+        } catch (Exception e) {
+            engineReset();
+            throw new ProviderException("nativeUpdate failed for " + algorithm, e);
+        }
+    }
+
+
+    // return the digest. See JCA doc.
+    @Override
+    protected synchronized byte[] engineDigest() {
+        final byte[] output = new byte[digestLength];
+        try {
+            engineDigest(output, 0, digestLength);
+        } catch (Exception e) {
+            throw new ProviderException("Internal error", e);
+        }
+        return output;
+    }
+
+    // return the digest in the specified array. See JCA doc.
+    @Override
+    protected int engineDigest(byte[] output, int offset, int len) throws DigestException {
+        if (output == null) {
+            return 0;
+        }
+        if (len < digestLength) {
+            throw new DigestException("Length must be at least "
+                    + digestLength + " for " + algorithm + " digests");
+        }
+        if ((offset < 0) || (len < 0) || (offset > output.length - len)) {
+            throw new DigestException("Buffer too short to store digest");
+        }
+        if (contextRef == null) {
+            contextRef = createDigestContext(this);
+        }
+        try {
+            nativeDigest(contextRef.ctxAddress, output, offset, digestLength);
+        } catch (Exception e) {
+            throw new ProviderException("Invoke nativeDigest failed for " + algorithm, e);
+        } finally {
+            engineReset();
+        }
+        return digestLength;
+    }
+
+    // reset this object. See JCA doc.
+    @Override
+    protected synchronized void engineReset() {
+        if (contextRef != null) {
+            contextRef.dispose();
+            contextRef = null;
+        }
+    }
+
+    // return digest length. See JCA doc.
+    @Override
+    protected int engineGetDigestLength() {
+        return digestLength;
+    }
+
+    @Override
+    public synchronized Object clone() throws CloneNotSupportedException {
+        KAEDigest kaeDigest = (KAEDigest) super.clone();
+        if (kaeDigest.contextRef != null && kaeDigest.contextRef.ctxAddress != 0) {
+            long addr;
+            try {
+                addr = nativeClone(kaeDigest.contextRef.ctxAddress);
+            } catch (Exception e) {
+                throw new ProviderException("Invoke nativeClone failed for " + algorithm, e);
+            }
+            kaeDigest.contextRef = new DigestContextRef(kaeDigest, addr);
+        }
+        return kaeDigest;
+    }
+
+    private DigestContextRef createDigestContext(KAEDigest kaeDigest) {
+        long addr;
+        try {
+            addr = nativeClone(initContext);
+        } catch (Exception e) {
+            throw new ProviderException("Invoke nativeInit failed for " + algorithm, e);
+        }
+        if (addr == 0) {
+            throw new RuntimeException("Cannot initialize EVP_MD_CTX for " + algorithm);
+        }
+        return new DigestContextRef(kaeDigest, addr);
+    }
+
+    // return pointer to the context
+    protected native static long nativeInit(String algorithmName);
+
+    // update the input byte
+    protected native static void nativeUpdate(long ctxAddress, byte[] input, int offset, int inLen);
+
+    // digest and store the digest message to output
+    protected native static int nativeDigest(long ctxAddress, byte[] output, int offset, int len);
+
+    // digest clone
+    protected static native long nativeClone(long ctxAddress);
+
+    // free the specified context
+    protected native static void nativeFree(long ctxAddress);
+}
diff --git a/jdk/src/solaris/classes/org/openeuler/security/openssl/KAEMac.java b/jdk/src/solaris/classes/org/openeuler/security/openssl/KAEMac.java
new file mode 100644
index 00000000..54c5cbdf
--- /dev/null
+++ b/jdk/src/solaris/classes/org/openeuler/security/openssl/KAEMac.java
@@ -0,0 +1,228 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * 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.
+ */
+
+package org.openeuler.security.openssl;
+
+import javax.crypto.MacSpi;
+import javax.crypto.SecretKey;
+import java.lang.ref.PhantomReference;
+import java.lang.ref.ReferenceQueue;
+import java.nio.ByteBuffer;
+import java.security.*;
+import java.security.spec.AlgorithmParameterSpec;
+import java.util.Set;
+import java.util.concurrent.ConcurrentSkipListSet;
+
+public abstract class KAEMac extends MacSpi implements Cloneable {
+
+    private final String algorithm;
+
+    /**
+     * The secret key used in this keyed MAC.
+     */
+    private byte[] keyBytes;
+
+    /**
+     * Holds the output size of the message digest.
+     */
+    private final int digestSize;
+
+    /**
+     * Holds a dummy buffer for writing single bytes to the digest.
+     */
+    private final byte[] singleByte = new byte[1];
+
+    private HmacContextRef contextRef = null;
+
+    private KAEMac(String algo, int size) {
+        this.algorithm = algo;
+        this.digestSize = size;
+    }
+
+    private static class HmacContextRef extends PhantomReference<KAEMac>
+            implements Comparable<HmacContextRef> {
+
+        private static ReferenceQueue<KAEMac> referenceQueue = new ReferenceQueue<>();
+        private static Set<HmacContextRef> referenceList = new ConcurrentSkipListSet<>();
+        private static boolean disableKaeDispose = Boolean.getBoolean("kae.disableKaeDispose");
+
+        private final long address;
+
+        HmacContextRef(KAEMac kaeMac, long address) {
+            super(kaeMac, referenceQueue);
+            this.address = address;
+            if (!disableKaeDispose) {
+                referenceList.add(this);
+                drainRefQueueBounded();
+            }
+        }
+
+        @Override
+        public int compareTo(HmacContextRef other) {
+            if (this.address == other.address) {
+                return 0;
+            } else {
+                return (this.address < other.address) ? -1 : 1;
+            }
+        }
+
+        private static void drainRefQueueBounded() {
+            while (true) {
+                HmacContextRef next = (HmacContextRef) referenceQueue.poll();
+                if (next == null) break;
+                next.dispose(true);
+            }
+        }
+
+        void dispose(boolean needFree) {
+            if (!disableKaeDispose) {
+                referenceList.remove(this);
+                try {
+                    if (needFree) {
+                        nativeFree(address);
+                    }
+                } finally {
+                    this.clear();
+                }
+            } else {
+                nativeFree(address);
+            }
+        }
+    }
+
+    private void checkAndInitHmacContext () {
+        try {
+            if (contextRef == null) {
+                long ctxAddr = nativeInit(keyBytes, keyBytes.length, algorithm);
+                contextRef = new HmacContextRef(this, ctxAddr);
+            }
+        }
+        catch (Exception e) {
+            throw new ProviderException(e.getMessage()) ;
+        }
+    }
+
+    @Override
+    protected int engineGetMacLength() {
+        return digestSize;
+    }
+
+    @Override
+    protected void engineInit(Key key, AlgorithmParameterSpec params)
+            throws InvalidKeyException, InvalidAlgorithmParameterException {
+        if (!(key instanceof SecretKey)) {
+            throw new InvalidKeyException("key must be a SecretKey");
+        }
+        if (params != null) {
+            throw new InvalidAlgorithmParameterException("unknown parameter type");
+        }
+        keyBytes = key.getEncoded();
+        if (keyBytes == null) {
+            throw new InvalidKeyException("key cannot be encoded");
+        }
+    }
+
+    @Override
+    protected void engineUpdate(byte input) {
+        singleByte[0] = input;
+        engineUpdate(singleByte, 0, 1);
+    }
+
+    @Override
+    protected void engineUpdate(byte[] input, int offset, int len) {
+        checkAndInitHmacContext();
+        try {
+            nativeUpdate(contextRef.address, input, offset, len);
+        }
+        catch (Exception e) {
+            engineReset();
+            throw new ProviderException(e.getMessage());
+        }
+    }
+
+
+    @Override
+    protected byte[] engineDoFinal() {
+        final byte[] output = new byte[digestSize];
+        checkAndInitHmacContext();
+        final byte[] res;
+        try {
+            int bytesWritten = nativeFinal(contextRef.address, output, 0, digestSize);
+            res = new byte[bytesWritten];
+            System.arraycopy(output, 0, res, 0, bytesWritten);
+        }
+        catch (Exception e) {
+            engineReset();
+            throw new ProviderException(e.getMessage());
+        }
+        return res;
+    }
+
+    @Override
+    protected void engineReset() {
+        if (contextRef != null) {
+            contextRef.dispose(true);
+            contextRef = null;
+        }
+    }
+
+    public static final class HmacMD5 extends KAEMac {
+        public HmacMD5() {
+            super("MD5", 16);
+        }
+    }
+    public static final class HmacSHA1 extends KAEMac {
+        public HmacSHA1() {
+            super("SHA1", 20);
+        }
+    }
+    public static final class HmacSHA224 extends KAEMac {
+        public HmacSHA224() throws NoSuchAlgorithmException {
+            super("SHA224", 28);
+        }
+    }
+    public static final class HmacSHA256 extends KAEMac {
+        public HmacSHA256() throws NoSuchAlgorithmException {
+            super("SHA256", 32);
+        }
+    }
+    public static final class HmacSHA384 extends KAEMac {
+        public HmacSHA384() throws NoSuchAlgorithmException {
+            super("SHA384", 48);
+        }
+    }
+    public static final class HmacSHA512 extends KAEMac {
+        public HmacSHA512() throws NoSuchAlgorithmException {
+            super("SHA512", 64);
+        }
+    }
+    
+    protected static native long nativeInit(byte[] key, int len, String algo);
+
+    protected static native void nativeUpdate(long ctxAddr, byte[] input, int inOffset, int inLen);
+
+    protected static native int nativeFinal(long ctxAddr, byte[] output, int outOffset, int inLen);
+
+    protected static native void nativeFree(long ctxAddr);
+}
diff --git a/jdk/src/solaris/classes/org/openeuler/security/openssl/KAEProvider.java b/jdk/src/solaris/classes/org/openeuler/security/openssl/KAEProvider.java
new file mode 100644
index 00000000..fb84b768
--- /dev/null
+++ b/jdk/src/solaris/classes/org/openeuler/security/openssl/KAEProvider.java
@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
+ * 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.
+ */
+
+package org.openeuler.security.openssl;
+
+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.Paths;
+import java.nio.file.StandardOpenOption;
+import java.util.Date;
+import java.security.Provider;
+
+/**
+ * KAE Provider
+ */
+public class KAEProvider extends Provider {
+    private static Throwable excp;
+    private static boolean needLog = true;
+
+    static {
+        Throwable status = null;
+        try {
+            System.loadLibrary("j2kae");
+            initOpenssl();
+        } catch (UnsatisfiedLinkError t) {
+            status = t;
+        } catch (RuntimeException e) {
+            status = e;
+        }
+        excp = status;
+    }
+
+    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();
+            }
+        }
+
+        try (BufferedWriter writer = Files.newBufferedWriter(fpath, StandardOpenOption.APPEND)) {
+            if (excp != null) {
+                writer.write(excp.getMessage());
+            } else {
+                writer.write("KAE Engine was found");
+            }
+            writer.write("    " + new Date());
+            writer.newLine();
+        } catch (IOException e) {
+            e.initCause(excp).printStackTrace();
+        }
+        KAEProvider.excp = null; // Exception already logged, clean it.
+    }
+
+    private void putCipherAES() {
+        final String blockModes = "ECB|CBC|CTR";
+        final String blockPads = "NOPADDING|PKCS5PADDING";
+
+        put("Cipher.AES SupportedModes", blockModes);
+        put("Cipher.AES SupportedPaddings", blockPads);
+        put("Cipher.AES", "org.openeuler.security.openssl.KAEAESCipher$Aes$Ecb$PKCS5Padding");
+
+        put("Cipher.AES/CBC/PKCS5Padding", "org.openeuler.security.openssl.KAEAESCipher$Aes$Cbc$PKCS5Padding");
+        put("Cipher.AES/CBC/NoPadding", "org.openeuler.security.openssl.KAEAESCipher$Aes$Cbc$NoPadding");
+        put("Alg.Alias.Cipher.AES/CBC/PKCS7Padding", "AES/CBC/PKCS5Padding");
+        put("Cipher.AES/ECB/NoPadding", "org.openeuler.security.openssl.KAEAESCipher$Aes$Ecb$NoPadding");
+        put("Cipher.AES/ECB/PKCS5Padding", "org.openeuler.security.openssl.KAEAESCipher$Aes$Ecb$PKCS5Padding");
+        put("Alg.Alias.Cipher.AES/ECB/PKCS7Padding", "AES/ECB/PKCS5Padding");
+        put("Cipher.AES/CTR/NoPadding", "org.openeuler.security.openssl.KAEAESCipher$Aes$Ctr$NoPadding");
+
+        put("Cipher.AES_128/CBC/PKCS5Padding", "org.openeuler.security.openssl.KAEAESCipher$Aes_128$Cbc$PKCS5Padding");
+        put("Cipher.AES_128/CBC/NoPadding", "org.openeuler.security.openssl.KAEAESCipher$Aes_128$Cbc$NoPadding");
+        put("Alg.Alias.Cipher.AES_128/CBC/PKCS7Padding", "AES_128/CBC/PKCS5Padding");
+        put("Cipher.AES_128/ECB/NoPadding", "org.openeuler.security.openssl.KAEAESCipher$Aes_128$Ecb$NoPadding");
+        put("Cipher.AES_128/ECB/PKCS5Padding", "org.openeuler.security.openssl.KAEAESCipher$Aes_128$Ecb$PKCS5Padding");
+        put("Alg.Alias.Cipher.AES_128/ECB/PKCS7Padding", "AES_128/ECB/PKCS5Padding");
+        put("Cipher.AES_128/CTR/NoPadding", "org.openeuler.security.openssl.KAEAESCipher$Aes_128$Ctr$NoPadding");
+
+        put("Cipher.AES_192/CBC/PKCS5Padding", "org.openeuler.security.openssl.KAEAESCipher$Aes_192$Cbc$PKCS5Padding");
+        put("Cipher.AES_192/CBC/NoPadding", "org.openeuler.security.openssl.KAEAESCipher$Aes_192$Cbc$NoPadding");
+        put("Alg.Alias.Cipher.AES_192/CBC/PKCS7Padding", "AES_192/CBC/PKCS5Padding");
+        put("Cipher.AES_192/ECB/NoPadding", "org.openeuler.security.openssl.KAEAESCipher$Aes_192$Ecb$NoPadding");
+        put("Cipher.AES_192/ECB/PKCS5Padding", "org.openeuler.security.openssl.KAEAESCipher$Aes_192$Ecb$PKCS5Padding");
+        put("Alg.Alias.Cipher.AES_192/ECB/PKCS7Padding", "AES_192/ECB/PKCS5Padding");
+        put("Cipher.AES_192/CTR/NoPadding", "org.openeuler.security.openssl.KAEAESCipher$Aes_192$Ctr$NoPadding");
+
+        put("Cipher.AES_256/CBC/PKCS5Padding", "org.openeuler.security.openssl.KAEAESCipher$Aes_256$Cbc$PKCS5Padding");
+        put("Cipher.AES_256/CBC/NoPadding", "org.openeuler.security.openssl.KAEAESCipher$Aes_256$Cbc$NoPadding");
+        put("Alg.Alias.Cipher.AES_256/CBC/PKCS7Padding", "AES_256/CBC/PKCS5Padding");
+        put("Cipher.AES_256/ECB/NoPadding", "org.openeuler.security.openssl.KAEAESCipher$Aes_256$Ecb$NoPadding");
+        put("Cipher.AES_256/ECB/PKCS5Padding", "org.openeuler.security.openssl.KAEAESCipher$Aes_256$Ecb$PKCS5Padding");
+        put("Alg.Alias.Cipher.AES_256/ECB/PKCS7Padding", "AES_256/ECB/PKCS5Padding");
+        put("Cipher.AES_256/CTR/NoPadding", "org.openeuler.security.openssl.KAEAESCipher$Aes_256$Ctr$NoPadding");
+    }
+
+    private void putMessageDigest() {
+        put("MessageDigest.MD5", "org.openeuler.security.openssl.KAEDigest$MD5");
+        put("MessageDigest.SHA-256", "org.openeuler.security.openssl.KAEDigest$SHA256");
+        put("MessageDigest.SHA-384", "org.openeuler.security.openssl.KAEDigest$SHA384");
+    }
+
+    private void putCipherRSA() {
+        // rsa
+        put("KeyPairGenerator.RSA", "org.openeuler.security.openssl.KAERSAKeyPairGenerator$Legacy");
+        put("Alg.Alias.KeyPairGenerator.1.2.840.113549.1.1", "RSA");
+        put("Alg.Alias.KeyPairGenerator.OID.1.2.840.113549.1.1", "RSA");
+
+        put("KeyPairGenerator.RSASSA-PSS", "org.openeuler.security.openssl.KAERSAKeyPairGenerator$PSS");
+        put("Alg.Alias.KeyPairGenerator.1.2.840.113549.1.1.10", "RSASSA-PSS");
+        put("Alg.Alias.KeyPairGenerator.OID.1.2.840.113549.1.1.10", "RSASSA-PSS");
+
+        put("Cipher.RSA", "org.openeuler.security.openssl.KAERSACipher");
+        put("Cipher.RSA SupportedModes", "ECB");
+        put("Cipher.RSA SupportedPaddings",
+                "NOPADDING|PKCS1PADDING|OAEPPADDING"
+                        + "|OAEPWITHMD5ANDMGF1PADDING"
+                        + "|OAEPWITHSHA1ANDMGF1PADDING"
+                        + "|OAEPWITHSHA-1ANDMGF1PADDING"
+                        + "|OAEPWITHSHA-224ANDMGF1PADDING"
+                        + "|OAEPWITHSHA-256ANDMGF1PADDING"
+                        + "|OAEPWITHSHA-384ANDMGF1PADDING"
+                        + "|OAEPWITHSHA-512ANDMGF1PADDING"
+                        + "|OAEPWITHSHA-512/224ANDMGF1PADDING"
+                        + "|OAEPWITHSHA-512/256ANDMGF1PADDING");
+        put("Cipher.RSA SupportedKeyClasses",
+                "java.security.interfaces.RSAPublicKey" +
+                        "|java.security.interfaces.RSAPrivateKey");
+    }
+
+    private void putMAC() {
+        put("MAC.HmacMD5", "org.openeuler.security.openssl.KAEMac$HmacMD5");
+        put("MAC.HmacSHA1", "org.openeuler.security.openssl.KAEMac$HmacSHA1");
+        put("MAC.HmacSHA224", "org.openeuler.security.openssl.KAEMac$HmacSHA224");
+        put("MAC.HmacSHA256", "org.openeuler.security.openssl.KAEMac$HmacSHA256");
+        put("MAC.HmacSHA384", "org.openeuler.security.openssl.KAEMac$HmacSHA384");
+        put("MAC.HmacSHA512", "org.openeuler.security.openssl.KAEMac$HmacSHA512");
+    }
+
+    public KAEProvider() {
+        super("KAEProvider", 1.8d, "KAE provider");
+        if (needLog) {
+            logStart(excp);
+            needLog = false; // Log only once
+        }
+        putMessageDigest();
+        putCipherAES();
+        putMAC();
+        putCipherRSA();
+    }
+
+    // init openssl
+    static native void initOpenssl() throws RuntimeException;
+}
diff --git a/jdk/src/solaris/classes/org/openeuler/security/openssl/KAERSACipher.java b/jdk/src/solaris/classes/org/openeuler/security/openssl/KAERSACipher.java
new file mode 100644
index 00000000..a7bc172a
--- /dev/null
+++ b/jdk/src/solaris/classes/org/openeuler/security/openssl/KAERSACipher.java
@@ -0,0 +1,796 @@
+/*
+ * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.openeuler.security.openssl;
+
+import sun.security.internal.spec.TlsRsaPremasterSecretParameterSpec;
+import sun.security.jca.Providers;
+import sun.security.rsa.RSACore;
+import sun.security.rsa.RSAKeyFactory;
+import sun.security.rsa.RSAPadding;
+import sun.security.util.KeyUtil;
+
+import javax.crypto.*;
+import javax.crypto.spec.OAEPParameterSpec;
+import javax.crypto.spec.PSource;
+import java.lang.ref.PhantomReference;
+import java.lang.ref.ReferenceQueue;
+import java.security.*;
+import java.security.interfaces.RSAKey;
+import java.security.interfaces.RSAPrivateCrtKey;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.InvalidParameterSpecException;
+import java.security.spec.MGF1ParameterSpec;
+import java.util.Arrays;
+import java.util.Locale;
+import java.util.Set;
+import java.util.concurrent.ConcurrentSkipListSet;
+
+
+/**
+ * RSA cipher implementation. Supports RSA en/decryption and signing/verifying
+ * using both PKCS#1 v1.5 and OAEP (v2.2) paddings and without padding (raw RSA).
+ * Note that raw RSA is supported mostly for completeness and should only be
+ * used in rare cases.
+ * <p>
+ * Objects should be instantiated by calling Cipher.getInstance() using the
+ * following algorithm names:
+ * . "RSA/ECB/PKCS1Padding" (or "RSA") for PKCS#1 v1.5 padding.
+ * . "RSA/ECB/OAEPwith<hash>andMGF1Padding" (or "RSA/ECB/OAEPPadding") for
+ * PKCS#1 v2.2 padding.
+ * . "RSA/ECB/NoPadding" for rsa RSA.
+ * <p>
+ * We only do one RSA operation per doFinal() call. If the application passes
+ * more data via calls to update() or doFinal(), we throw an
+ * IllegalBlockSizeException when doFinal() is called (see JCE API spec).
+ * Bulk encryption using RSA does not make sense and is not standardized.
+ * <p>
+ * Note: RSA keys should be at least 512 bits long
+ */
+public final class KAERSACipher extends CipherSpi {
+    // constant for an empty byte array
+    private final static byte[] B0 = new byte[0];
+
+    // mode constant for public key encryption
+    private final static int MODE_ENCRYPT = 1;
+
+    // mode constant for private key decryption
+    private final static int MODE_DECRYPT = 2;
+
+    // mode constant for private key encryption (signing)
+    private final static int MODE_SIGN = 3;
+
+    // mode constant for public key decryption (verifying)
+    private final static int MODE_VERIFY = 4;
+
+    // current mode, one of MODE_* above. Set when init() is called
+    private int mode;
+
+    // active padding type, one of PAD_* above. Set by setPadding()
+    private KAERSAPaddingType paddingType;
+
+    // padding object
+    private RSAPadding padding;
+
+    // cipher parameter for OAEP padding and TLS RSA premaster secret
+    private AlgorithmParameterSpec spec = null;
+
+    // buffer for the data
+    private byte[] buffer;
+    // offset into the buffer (number of bytes buffered)
+    private int bufOfs;
+
+    // size of the output
+    private int outputSize;
+
+    // hash algorithm for OAEP
+    private String oaepHashAlgorithm = "SHA-1";
+
+    // the source of randomness
+    private SecureRandom random;
+
+    private RSAKey rsaKey;
+
+    // rsa key holder
+    private KAERSAKeyHolder rsaKeyHolder;
+
+
+    public KAERSACipher() {
+        paddingType = KAERSAPaddingType.PKCS1Padding;
+    }
+
+    // modes do not make sense for RSA, but allow ECB
+    // see JCE spec
+    @Override
+    protected void engineSetMode(String mode) throws NoSuchAlgorithmException {
+        if (!mode.equalsIgnoreCase("ECB")) {
+            throw new NoSuchAlgorithmException("Unsupported mode " + mode);
+        }
+    }
+
+    // set the padding type
+    // see JCE spec
+    @Override
+    protected void engineSetPadding(String paddingName)
+            throws NoSuchPaddingException {
+        if (KAERSAPaddingType.NoPadding.getName().equalsIgnoreCase(paddingName)) {
+            paddingType = KAERSAPaddingType.NoPadding;
+        } else if (KAERSAPaddingType.PKCS1Padding.getName().equalsIgnoreCase(paddingName)) {
+            paddingType = KAERSAPaddingType.PKCS1Padding;
+        } else {
+            String lowerPadding = paddingName.toLowerCase(Locale.ENGLISH);
+            if ("oaeppadding".equals(lowerPadding)) {
+                paddingType = KAERSAPaddingType.OAEP;
+            } else if (lowerPadding.startsWith("oaepwith") &&
+                    lowerPadding.endsWith("andmgf1padding")) {
+                paddingType = KAERSAPaddingType.OAEP;
+                // "oaepwith" length is 8
+                // "andmgf1padding" length is 14
+                oaepHashAlgorithm =
+                        paddingName.substring(8, paddingName.length() - 14);
+                // check if MessageDigest appears to be available
+                // avoid getInstance() call here
+                if (Providers.getProviderList().getService
+                        ("MessageDigest", oaepHashAlgorithm) == null) {
+                    throw new NoSuchPaddingException
+                            ("MessageDigest not available for " + paddingName);
+                }
+            } else {
+                throw new NoSuchPaddingException
+                        ("Padding " + paddingName + " not supported");
+            }
+        }
+    }
+
+    // return 0 as block size, we are not a block cipher
+    // see JCE spec
+    @Override
+    protected int engineGetBlockSize() {
+        return 0;
+    }
+
+    // return the output size
+    // see JCE spec
+    @Override
+    protected int engineGetOutputSize(int inputLen) {
+        return outputSize;
+    }
+
+    // no iv, return null
+    // see JCE spec
+    @Override
+    protected byte[] engineGetIV() {
+        return null;
+    }
+
+    // see JCE spec
+    @Override
+    protected AlgorithmParameters engineGetParameters() {
+        if (spec != null && spec instanceof OAEPParameterSpec) {
+            try {
+                AlgorithmParameters params =
+                        AlgorithmParameters.getInstance("OAEP");
+                params.init(spec);
+                return params;
+            } catch (NoSuchAlgorithmException nsae) {
+                // should never happen
+                throw new RuntimeException("Cannot find OAEP " +
+                        " AlgorithmParameters implementation in SunJCE provider");
+            } catch (InvalidParameterSpecException ipse) {
+                // should never happen
+                throw new RuntimeException("OAEPParameterSpec not supported");
+            }
+        } else {
+            return null;
+        }
+    }
+
+    // see JCE spec
+    @Override
+    protected void engineInit(int opmode, Key key, SecureRandom random)
+            throws InvalidKeyException {
+        try {
+            init(opmode, key, random, null);
+        } catch (InvalidAlgorithmParameterException iape) {
+            // never thrown when null parameters are used;
+            // but re-throw it just in case
+            throw new InvalidKeyException("Wrong parameters", iape);
+        }
+    }
+
+    // see JCE spec
+    @Override
+    protected void engineInit(int opmode, Key key, AlgorithmParameterSpec params, SecureRandom random)
+            throws InvalidKeyException, InvalidAlgorithmParameterException {
+        init(opmode, key, random, params);
+    }
+
+    // see JCE spec
+    @Override
+    protected void engineInit(int opmode, Key key, AlgorithmParameters params, SecureRandom random)
+            throws InvalidKeyException, InvalidAlgorithmParameterException {
+        if (params == null) {
+            init(opmode, key, random, null);
+        } else {
+            try {
+                OAEPParameterSpec oaepParameterSpec =
+                        params.getParameterSpec(OAEPParameterSpec.class);
+                init(opmode, key, random, oaepParameterSpec);
+            } catch (InvalidParameterSpecException ipse) {
+                InvalidAlgorithmParameterException iape =
+                        new InvalidAlgorithmParameterException("Wrong parameter");
+                iape.initCause(ipse);
+                throw iape;
+            }
+        }
+    }
+
+    // check TlsRsaPremasterSecretParameterSpec
+    private void checkTlsRsaPremasterSecretParameterSpec(AlgorithmParameterSpec params)
+            throws InvalidAlgorithmParameterException {
+        if (!(params instanceof TlsRsaPremasterSecretParameterSpec)) {
+            throw new InvalidAlgorithmParameterException(
+                    "Parameters not supported");
+        }
+    }
+
+    // check OAEPParameterSpec
+    private void checkOAEPParameterSpec(AlgorithmParameterSpec params)
+            throws InvalidAlgorithmParameterException {
+        if (!(params instanceof OAEPParameterSpec)) {
+            throw new InvalidAlgorithmParameterException
+                    ("Wrong Parameters for OAEP Padding");
+        }
+
+        // check MGF algorithm
+        OAEPParameterSpec oaepParameterSpec = (OAEPParameterSpec) params;
+        String mgfName = oaepParameterSpec.getMGFAlgorithm();
+        if (!mgfName.equalsIgnoreCase("MGF1")) {
+            throw new InvalidAlgorithmParameterException
+                    ("Unsupported MGF algo: " + mgfName);
+        }
+
+        // check PSource algorithm
+        PSource pSource = oaepParameterSpec.getPSource();
+        String pSourceAlgorithm = pSource.getAlgorithm();
+        if (!pSourceAlgorithm.equalsIgnoreCase("PSpecified")) {
+            throw new InvalidAlgorithmParameterException
+                    ("Unsupported pSource algo: " + pSourceAlgorithm);
+        }
+    }
+
+    // compute OAEP data buffer length
+    private int getOAEPBufferLen(int outputSize, OAEPParameterSpec oaepParameterSpec, boolean encrypt)
+            throws InvalidKeyException {
+        if (!encrypt) {
+            return outputSize;
+        }
+        String mdName = oaepParameterSpec.getDigestAlgorithm();
+        String mgfMdName = ((MGF1ParameterSpec) oaepParameterSpec.getMGFParameters())
+                .getDigestAlgorithm();
+        int digestLen = KAEUtils.getDigestLength(mdName);
+        int bufferLen = outputSize - 2 - 2 * digestLen;
+        if (bufferLen < 0) {
+            throw new InvalidKeyException
+                    ("Key is too short for encryption using OAEPPadding" +
+                            " with " + mdName + " and MGF1" + mgfMdName);
+        }
+        return bufferLen;
+    }
+
+    // non-CRT private key, use the jdk soft calculation.
+    private boolean useJdkSoftCalculation() {
+        return (rsaKey instanceof RSAPrivateKey) && !(rsaKey instanceof RSAPrivateCrtKey);
+    }
+
+    // get the rsa padding
+    private RSAPadding getRSAPadding(KAERSAPaddingType paddingType, int paddedSize,
+                                     SecureRandom random, AlgorithmParameterSpec spec)
+            throws InvalidKeyException, InvalidAlgorithmParameterException {
+        RSAPadding rsaPadding;
+        if (KAERSAPaddingType.NoPadding.equals(paddingType)) {
+            rsaPadding = RSAPadding.getInstance(RSAPadding.PAD_NONE, paddedSize, random);
+        } else if (KAERSAPaddingType.PKCS1Padding.equals(paddingType)) {
+            int blockType = (mode <= MODE_DECRYPT) ? RSAPadding.PAD_BLOCKTYPE_2
+                    : RSAPadding.PAD_BLOCKTYPE_1;
+            rsaPadding = RSAPadding.getInstance(blockType, paddedSize, random);
+        } else {
+            rsaPadding = RSAPadding.getInstance(RSAPadding.PAD_OAEP_MGF1, paddedSize,
+                    random, (OAEPParameterSpec) spec);
+        }
+        return rsaPadding;
+    }
+
+    private boolean isEncrypt(int opmode) throws InvalidKeyException {
+        boolean encrypt;
+        switch (opmode) {
+            case Cipher.ENCRYPT_MODE:
+            case Cipher.WRAP_MODE:
+                encrypt = true;
+                break;
+            case Cipher.DECRYPT_MODE:
+            case Cipher.UNWRAP_MODE:
+                encrypt = false;
+                break;
+            default:
+                throw new InvalidKeyException("Unknown mode: " + opmode);
+        }
+        return encrypt;
+    }
+
+    // initialize this cipher
+    private void init(int opmode, Key key, SecureRandom random, AlgorithmParameterSpec params)
+            throws InvalidKeyException, InvalidAlgorithmParameterException {
+        // check the key, and convert to RSAKey
+        rsaKey = RSAKeyFactory.toRSAKey(key);
+
+        // init mode
+        boolean encrypt = isEncrypt(opmode);
+        if (key instanceof RSAPublicKey) {
+            mode = encrypt ? MODE_ENCRYPT : MODE_VERIFY;
+        } else {
+            mode = encrypt ? MODE_SIGN : MODE_DECRYPT;
+        }
+
+        int bufferLen = RSACore.getByteLength(rsaKey.getModulus());
+        outputSize = bufferLen;
+        bufOfs = 0;
+        if (KAERSAPaddingType.PKCS1Padding.equals(paddingType)) {
+            if (params != null) {
+                checkTlsRsaPremasterSecretParameterSpec(params);
+                spec = params;
+                this.random = random;   // for TLS RSA premaster secret
+            }
+            if (encrypt) {
+                bufferLen -= 11;
+            }
+        } else if (KAERSAPaddingType.OAEP.equals(paddingType)) {
+            if ((mode == MODE_SIGN) || (mode == MODE_VERIFY)) {
+                throw new InvalidKeyException
+                        ("OAEP cannot be used to sign or verify signatures");
+            }
+            if (params != null) {
+                checkOAEPParameterSpec(params);
+                spec = params;
+            } else {
+                spec = new OAEPParameterSpec(oaepHashAlgorithm, "MGF1",
+                        MGF1ParameterSpec.SHA1, PSource.PSpecified.DEFAULT);
+            }
+            bufferLen = getOAEPBufferLen(bufferLen, (OAEPParameterSpec) spec, encrypt);
+        }
+        buffer = new byte[bufferLen];
+
+        if (useJdkSoftCalculation()) {
+            this.padding = getRSAPadding(paddingType, outputSize, random, spec);
+        }
+    }
+
+    // internal update method
+    private void update(byte[] in, int inOfs, int inLen) {
+        if ((inLen == 0) || (in == null)) {
+            return;
+        }
+        if (inLen > (buffer.length - bufOfs)) {
+            bufOfs = buffer.length + 1;
+            return;
+        }
+        System.arraycopy(in, inOfs, buffer, bufOfs, inLen);
+        bufOfs += inLen;
+    }
+
+    // encrypt or decrypt for NoPadding or PKCS1Padding
+    private int doCryptNotOAEPPadding(long keyAddress, byte[] input, byte[] output) throws BadPaddingException {
+        int resultSize;
+        switch (mode) {
+            case MODE_SIGN:
+                resultSize = nativeRSAPrivateEncrypt(keyAddress, input.length, input, output, paddingType.getId());
+                break;
+            case MODE_VERIFY:
+                resultSize = nativeRSAPublicDecrypt(keyAddress, input.length, input, output, paddingType.getId());
+                break;
+            case MODE_ENCRYPT:
+                resultSize = nativeRSAPublicEncrypt(keyAddress, input.length, input, output, paddingType.getId());
+                break;
+            case MODE_DECRYPT:
+                resultSize = nativeRSAPrivateDecrypt(keyAddress, input.length, input, output, paddingType.getId());
+                break;
+            default:
+                throw new AssertionError("Internal error");
+        }
+        return resultSize;
+    }
+
+
+    // encrypt or decrypt for OAEPPadding
+    private int doCryptOAEPPadding(long keyAddress, byte[] input, byte[] output, OAEPParameterSpec oaepParameterSpec)
+            throws BadPaddingException {
+        // oaep digest algorithm
+        String oaepMdAlgorithm = KAEUtils.getKAEDigestName(oaepParameterSpec.getDigestAlgorithm());
+        // mgf1 digest algorithm
+        MGF1ParameterSpec mgf1ParameterSpec = (MGF1ParameterSpec) oaepParameterSpec.getMGFParameters();
+        String mgf1MdAlgorithm = KAEUtils.getKAEDigestName(mgf1ParameterSpec.getDigestAlgorithm());
+        // label
+        PSource pSource = oaepParameterSpec.getPSource();
+        byte[] label = ((PSource.PSpecified) pSource).getValue();
+        int resultSize;
+        switch (mode) {
+            case MODE_ENCRYPT:
+                resultSize = nativeRSAEncryptOAEPPadding(keyAddress, input.length, input, output, paddingType.getId(),
+                        oaepMdAlgorithm, mgf1MdAlgorithm, label);
+                break;
+            case MODE_DECRYPT:
+                resultSize = nativeRSADecryptOAEPPadding(keyAddress, input.length, input, output, paddingType.getId(),
+                        oaepMdAlgorithm, mgf1MdAlgorithm, label);
+                break;
+            default:
+                throw new AssertionError("Internal error");
+        }
+        return resultSize;
+    }
+
+    // get input bytes
+    private byte[] getInputBytes(byte[] buffer, int bufOfs, KAERSAPaddingType paddingType) {
+        if (bufOfs == buffer.length) {
+            return buffer;
+        }
+
+        // if padding type is NoPadding , data should move to end
+        final byte[] input;
+        if (KAERSAPaddingType.NoPadding.equals(paddingType)) {
+            input = new byte[buffer.length];
+            System.arraycopy(buffer, 0, input, buffer.length - bufOfs, bufOfs);
+        } else {
+            input = Arrays.copyOf(buffer, bufOfs);
+        }
+        return input;
+    }
+
+    // internal doFinal() method. Here we perform the actual RSA operation
+    private byte[] doFinal() throws BadPaddingException, IllegalBlockSizeException {
+        if (bufOfs > buffer.length) {
+            throw new IllegalBlockSizeException("Data must not be longer "
+                    + "than " + buffer.length + " bytes");
+        }
+
+        if (useJdkSoftCalculation()) {
+            return doFinalForJdkSoftCalculation(padding);
+        }
+
+        // get input bytes
+        final byte[] input = getInputBytes(buffer, bufOfs, paddingType);
+
+        try {
+            rsaKeyHolder = new KAERSAKeyHolder(this, rsaKey);
+        } catch (InvalidKeyException e) {
+            throw new RuntimeException(e.getMessage());
+        }
+
+        long keyAddress = rsaKeyHolder.keyAddress;
+        byte[] output = new byte[outputSize];
+        int cipherTextLength;
+        try {
+            if (KAERSAPaddingType.OAEP.equals(paddingType)) {
+                // do crypt for OAEPPadding
+                cipherTextLength = doCryptOAEPPadding(keyAddress, input, output, (OAEPParameterSpec) spec);
+            } else {
+                // do crypt for NoPadding or PKCS1Padding
+                cipherTextLength = doCryptNotOAEPPadding(keyAddress, input, output);
+            }
+
+            // If mode is signing or verifying , and the length of the ciphertext is less than output length,
+            // just keep output length ciphertext.
+            if ((mode == MODE_VERIFY || mode == MODE_DECRYPT) && cipherTextLength != output.length) {
+                output = Arrays.copyOf(output, cipherTextLength);
+            }
+        } finally {
+            bufOfs = 0;
+            resetKeyHolder();
+        }
+        return output;
+    }
+
+    private byte[] doFinalForJdkSoftCalculation(RSAPadding padding) throws BadPaddingException {
+        try {
+            byte[] data;
+            switch (mode) {
+                case MODE_SIGN:
+                    data = padding.pad(buffer, 0, bufOfs);
+                    return RSACore.rsa(data, (RSAPrivateKey) rsaKey, true);
+                case MODE_DECRYPT:
+                    byte[] decryptBuffer = RSACore.convert(buffer, 0, bufOfs);
+                    data = RSACore.rsa(decryptBuffer, (RSAPrivateKey) rsaKey, false);
+                    return padding.unpad(data);
+                default:
+                    throw new AssertionError("Internal error");
+            }
+        } finally {
+            bufOfs = 0;
+        }
+    }
+
+    // see JCE spec
+    @Override
+    protected byte[] engineUpdate(byte[] in, int inOfs, int inLen) {
+        update(in, inOfs, inLen);
+        return B0;
+    }
+
+    // see JCE spec
+    @Override
+    protected int engineUpdate(byte[] in, int inOfs, int inLen, byte[] out,
+                               int outOfs) {
+        update(in, inOfs, inLen);
+        return 0;
+    }
+
+    // see JCE spec
+    @Override
+    protected byte[] engineDoFinal(byte[] in, int inOfs, int inLen)
+            throws BadPaddingException, IllegalBlockSizeException {
+        update(in, inOfs, inLen);
+        return doFinal();
+    }
+
+    // see JCE spec
+    @Override
+    protected int engineDoFinal(byte[] in, int inOfs, int inLen, byte[] out, int outOfs)
+            throws ShortBufferException, BadPaddingException, IllegalBlockSizeException {
+        if (outputSize > out.length - outOfs) {
+            throw new ShortBufferException
+                    ("Need " + outputSize + " bytes for output");
+        }
+        update(in, inOfs, inLen);
+        byte[] result = doFinal();
+        int length = result.length;
+        System.arraycopy(result, 0, out, outOfs, length);
+        return length;
+    }
+
+    // see JCE spec
+    @Override
+    protected byte[] engineWrap(Key key) throws InvalidKeyException,
+            IllegalBlockSizeException {
+        byte[] encoded = key.getEncoded();
+        if ((encoded == null) || (encoded.length == 0)) {
+            throw new InvalidKeyException("Could not obtain encoded key");
+        }
+        if (encoded.length > buffer.length) {
+            throw new InvalidKeyException("Key is too long for wrapping");
+        }
+        update(encoded, 0, encoded.length);
+        try {
+            return doFinal();
+        } catch (BadPaddingException e) {
+            // should not occur
+            throw new InvalidKeyException("Wrapping failed", e);
+        }
+    }
+
+    // see JCE spec
+    @Override
+    protected Key engineUnwrap(byte[] wrappedKey, String algorithm, int type)
+            throws InvalidKeyException, NoSuchAlgorithmException {
+        if (wrappedKey.length > buffer.length) {
+            throw new InvalidKeyException("Key is too long for unwrapping");
+        }
+
+        boolean isTlsRsaPremasterSecret = "TlsRsaPremasterSecret".equals(algorithm);
+        Exception failover = null;
+        byte[] encoded = null;
+
+        update(wrappedKey, 0, wrappedKey.length);
+        try {
+            encoded = doFinal();
+        } catch (BadPaddingException e) {
+            if (isTlsRsaPremasterSecret) {
+                failover = e;
+            } else {
+                throw new InvalidKeyException("Unwrapping failed", e);
+            }
+        } catch (IllegalBlockSizeException e) {
+            // should not occur, handled with length check above
+            throw new InvalidKeyException("Unwrapping failed", e);
+        }
+
+        if (isTlsRsaPremasterSecret) {
+            if (!(spec instanceof TlsRsaPremasterSecretParameterSpec)) {
+                throw new IllegalStateException(
+                        "No TlsRsaPremasterSecretParameterSpec specified");
+            }
+
+            // polish the TLS premaster secret
+            encoded = KeyUtil.checkTlsPreMasterSecretKey(
+                    ((TlsRsaPremasterSecretParameterSpec) spec).getClientVersion(),
+                    ((TlsRsaPremasterSecretParameterSpec) spec).getServerVersion(),
+                    random, encoded, (failover != null));
+        }
+        return KAEUtils.ConstructKeys.constructKey(encoded, algorithm, type);
+    }
+
+    // see JCE spec
+    @Override
+    protected int engineGetKeySize(Key key) throws InvalidKeyException {
+        RSAKey newRSAKey = RSAKeyFactory.toRSAKey(key);
+        return newRSAKey.getModulus().bitLength();
+    }
+
+    // reset the key holder
+    private void resetKeyHolder() {
+        if (rsaKeyHolder != null) {
+            rsaKeyHolder.dispose(true);
+            rsaKeyHolder = null;
+        }
+    }
+
+    // create KAE rsa key
+    protected static native long nativeCreateRSAPrivateCrtKey(byte[] n, byte[] e, byte[] d, byte[] p, byte[] q,
+                                                              byte[] dmp1, byte[] dmq1, byte[] iqmp);
+
+    // create KAE rsa public key
+    protected static native long nativeCreateRSAPublicKey(byte[] n, byte[] e);
+
+    // encrypt by private key for padding type (NOPADDING|PKCS1PADDING)
+    protected static native int nativeRSAPrivateEncrypt(long keyAddress, int inLen, byte[] in, byte[] out,
+                                                        int paddingType) throws BadPaddingException;
+
+    // decrypt by private key for padding type (NOPADDING|PKCS1PADDING)
+    protected static native int nativeRSAPrivateDecrypt(long keyAddress, int inLen, byte[] in, byte[] out,
+                                                        int paddingType) throws BadPaddingException;
+
+    // encrypt by public key for padding type (NOPADDING|PKCS1PADDING)
+    protected static native int nativeRSAPublicEncrypt(long keyAddress, int inLen, byte[] in, byte[] out,
+                                                       int paddingType) throws BadPaddingException;
+
+    // decrypt by public key for padding type (NOPADDING|PKCS1PADDING)
+    protected static native int nativeRSAPublicDecrypt(long keyAddress, int inLen, byte[] in, byte[] out,
+                                                       int paddingType) throws BadPaddingException;
+
+    // encrypt by public for padding type (OAEPPADDING)
+    protected static native int nativeRSAEncryptOAEPPadding(long keyAddress, int inLen, byte[] in, byte[] out,
+                                                            int paddingType, String oaepMdAlgo, String mgf1MdAlgo,
+                                                            byte[] label) throws BadPaddingException;
+
+    // decrypt by public for padding type (OAEPPADDING)
+    protected static native int nativeRSADecryptOAEPPadding(long keyAddress, int inLen, byte[] in, byte[] out,
+                                                            int paddingType, String oaepMdAlgo, String mgf1MdAlgo,
+                                                            byte[] label) throws BadPaddingException;
+
+    // free the key
+    protected static native void nativeFreeKey(long keyAddress);
+
+    /**
+     * The rsa openssl key holder , use PhantomReference in case of native memory leaks
+     */
+    private static class KAERSAKeyHolder extends PhantomReference<KAERSACipher>
+            implements Comparable<KAERSAKeyHolder> {
+        private static ReferenceQueue<KAERSACipher> referenceQueue = new ReferenceQueue<>();
+        private static Set<KAERSAKeyHolder> referenceList = new ConcurrentSkipListSet<>();
+        private final long keyAddress;
+
+        KAERSAKeyHolder(KAERSACipher rsaCipher, RSAKey rsaKey) throws InvalidKeyException {
+            super(rsaCipher, referenceQueue);
+            this.keyAddress = getKeyAddress(rsaKey);
+            referenceList.add(this);
+            drainRefQueueBounded();
+        }
+
+        private static void drainRefQueueBounded() {
+            while (true) {
+                KAERSAKeyHolder next = (KAERSAKeyHolder) referenceQueue.poll();
+                if (next == null) {
+                    break;
+                }
+                next.dispose(true);
+            }
+        }
+
+        void dispose(boolean needFree) {
+            referenceList.remove(this);
+            try {
+                if (needFree) {
+                    nativeFreeKey(keyAddress);
+                }
+            } finally {
+                this.clear();
+            }
+        }
+
+        @Override
+        public int compareTo(KAERSAKeyHolder other) {
+            if (this.keyAddress == other.keyAddress) {
+                return 0;
+            } else {
+                return (this.keyAddress < other.keyAddress) ? -1 : 1;
+            }
+        }
+
+        private long getKeyAddress(RSAKey rsaKey) throws InvalidKeyException {
+            long address;
+            if (rsaKey instanceof RSAPrivateCrtKey) { // RSAPrivateCrtKeyImpl
+                address = getKeyAddress((RSAPrivateCrtKey) rsaKey);
+            } else if (rsaKey instanceof RSAPublicKey) { // RSAPublicKeyImpl
+                address = getKeyAddress((RSAPublicKey) rsaKey);
+            } else {
+                throw new InvalidKeyException("Invalid RSAKey implement " + rsaKey.getClass());
+            }
+            return address;
+        }
+
+        private long getKeyAddress(RSAPrivateCrtKey key) throws InvalidKeyException {
+            checkKey(key);
+            long address;
+            try {
+                address = nativeCreateRSAPrivateCrtKey(
+                        key.getModulus().toByteArray(),
+                        key.getPublicExponent().toByteArray(),
+                        key.getPrivateExponent().toByteArray(),
+                        key.getPrimeP().toByteArray(),
+                        key.getPrimeQ().toByteArray(),
+                        key.getPrimeExponentP().toByteArray(),
+                        key.getPrimeExponentQ().toByteArray(),
+                        key.getCrtCoefficient().toByteArray());
+                return address;
+            } catch (Exception e) {
+                throw new InvalidKeyException(e);
+            }
+        }
+
+        private long getKeyAddress(RSAPublicKey key) throws InvalidKeyException {
+            checkKey(key);
+            long address;
+            try {
+                address = nativeCreateRSAPublicKey(
+                        key.getModulus().toByteArray(),
+                        key.getPublicExponent().toByteArray()
+                );
+                return address;
+            } catch (Exception e) {
+                throw new InvalidKeyException(e);
+            }
+        }
+
+        private void checkKey(RSAPrivateCrtKey key) throws InvalidKeyException {
+            if (key.getModulus() == null
+                    || key.getPublicExponent() == null
+                    || key.getPrivateExponent() == null
+                    || key.getPrimeP() == null
+                    || key.getPrimeQ() == null
+                    || key.getPrimeExponentP() == null
+                    || key.getPrimeExponentQ() == null
+                    || key.getCrtCoefficient() == null) {
+                throw new InvalidKeyException("Invalid RSA private key");
+            }
+        }
+
+        private void checkKey(RSAPublicKey key) throws InvalidKeyException {
+            if (key.getModulus() == null || key.getPublicExponent() == null) {
+                throw new InvalidKeyException("Invalid RSA public key");
+            }
+        }
+    }
+}
diff --git a/jdk/src/solaris/classes/org/openeuler/security/openssl/KAERSAKeyPairGenerator.java b/jdk/src/solaris/classes/org/openeuler/security/openssl/KAERSAKeyPairGenerator.java
new file mode 100644
index 00000000..51d7a95e
--- /dev/null
+++ b/jdk/src/solaris/classes/org/openeuler/security/openssl/KAERSAKeyPairGenerator.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.openeuler.security.openssl;
+
+import sun.security.rsa.*;
+import sun.security.rsa.RSAUtil.KeyType;
+import sun.security.util.SecurityProviderConstants;
+
+import java.math.BigInteger;
+import java.security.*;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.RSAKeyGenParameterSpec;
+
+public abstract class KAERSAKeyPairGenerator extends KeyPairGeneratorSpi {
+    // public exponent to use
+    private BigInteger publicExponent;
+
+    // size of the key to generate, >= KAERSAKeyFactory.MIN_MODLEN
+    private int keySize;
+
+    private final KeyType type;
+
+    private AlgorithmParameterSpec keyParams;
+
+
+    KAERSAKeyPairGenerator(KeyType keyType, int keySize) {
+        this.type = keyType;
+        initialize(keySize, null);
+    }
+
+    // initialize the generator. See JCA doc
+    @Override
+    public void initialize(int keySize, SecureRandom random) {
+        try {
+            initialize(new RSAKeyGenParameterSpec(keySize,
+                    RSAKeyGenParameterSpec.F4), null);
+        } catch (InvalidAlgorithmParameterException iape) {
+            throw new InvalidParameterException(iape.getMessage());
+        }
+    }
+
+    // second initialize method. See JCA doc
+    @Override
+    public void initialize(AlgorithmParameterSpec params, SecureRandom random)
+            throws InvalidAlgorithmParameterException {
+        if (!(params instanceof RSAKeyGenParameterSpec)) {
+            throw new InvalidAlgorithmParameterException
+                    ("Params must be instance of RSAKeyGenParameterSpec");
+        }
+
+        RSAKeyGenParameterSpec rsaSpec = (RSAKeyGenParameterSpec) params;
+        int tmpKeySize = rsaSpec.getKeysize();
+        BigInteger tmpPublicExponent = rsaSpec.getPublicExponent();
+        keyParams = rsaSpec.getKeyParams();
+
+        if (tmpPublicExponent == null) {
+            tmpPublicExponent = RSAKeyGenParameterSpec.F4;
+        } else {
+            if (tmpPublicExponent.compareTo(RSAKeyGenParameterSpec.F0) < 0) {
+                throw new InvalidAlgorithmParameterException
+                        ("Public exponent must be 3 or larger");
+            }
+            if (tmpPublicExponent.bitLength() > tmpKeySize) {
+                throw new InvalidAlgorithmParameterException
+                        ("Public exponent must be smaller than key size");
+            }
+        }
+
+        // do not allow unreasonably large key sizes, probably user error
+        try {
+            RSAKeyFactory.checkKeyLengths(tmpKeySize, tmpPublicExponent,
+                    512, 64 * 1024);
+        } catch (InvalidKeyException e) {
+            throw new InvalidAlgorithmParameterException(
+                    "Invalid key sizes", e);
+        }
+
+        this.keySize = tmpKeySize;
+        this.publicExponent = tmpPublicExponent;
+    }
+
+    // generate the keypair. See JCA doc
+    @Override
+    public KeyPair generateKeyPair() {
+        // get the KAE RSA key Parameters
+        byte[][] params = nativeGenerateKeyPair(keySize, publicExponent.toByteArray());
+
+        try {
+            // check KAE RSA key Parameters
+            checkKAERSAParams(params);
+
+            BigInteger n = new BigInteger(params[0]);
+            BigInteger e = new BigInteger(params[1]);
+            BigInteger d = new BigInteger(params[2]);
+            BigInteger p = new BigInteger(params[3]);
+            BigInteger q = new BigInteger(params[4]);
+            BigInteger pe = new BigInteger(params[5]);
+            BigInteger qe = new BigInteger(params[6]);
+            BigInteger coeff = new BigInteger(params[7]);
+
+            // public key
+            PublicKey publicKey = RSAPublicKeyImpl.newKey(type, keyParams, n, e);
+
+            // private key
+            PrivateKey privateKey = RSAPrivateCrtKeyImpl.newKey(type, keyParams, n, e, d, p, q, pe, qe, coeff);
+
+            return new KeyPair(publicKey, privateKey);
+        } catch (InvalidKeyException ex) {
+            throw new RuntimeException(ex);
+        }
+    }
+
+    // check KAE RSA key Parameters
+    private void checkKAERSAParams(byte[][] params) throws InvalidKeyException {
+        if (params == null || params.length < 8) {
+            throw new InvalidKeyException("Invalid KAE RSA key Parameter");
+        }
+
+        for (int i = 0; i < params.length; i++) {
+            if (params[i] == null) {
+                throw new InvalidKeyException("Invalid KAE RSA key Parameter , params[" + i + "] = null");
+            }
+        }
+    }
+
+    public static final class Legacy extends KAERSAKeyPairGenerator {
+        public Legacy() {
+            super(KeyType.RSA, SecurityProviderConstants.DEF_RSA_KEY_SIZE);
+        }
+    }
+
+    public static final class PSS extends KAERSAKeyPairGenerator {
+        public PSS() {
+            super(KeyType.PSS, SecurityProviderConstants.DEF_RSASSA_PSS_KEY_SIZE);
+        }
+    }
+
+    // generate key pair
+    static native byte[][] nativeGenerateKeyPair(int keySize, byte[] publicExponent) throws RuntimeException;
+}
diff --git a/jdk/src/solaris/classes/org/openeuler/security/openssl/KAERSAPaddingType.java b/jdk/src/solaris/classes/org/openeuler/security/openssl/KAERSAPaddingType.java
new file mode 100644
index 00000000..04036b8d
--- /dev/null
+++ b/jdk/src/solaris/classes/org/openeuler/security/openssl/KAERSAPaddingType.java
@@ -0,0 +1,80 @@
+/*
+ * 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.
+ */
+
+package org.openeuler.security.openssl;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+enum KAERSAPaddingType {
+    // raw RSA
+    PKCS1Padding(1, "PKCS1Padding"),
+
+    // PKCS#1 v1.5 RSA
+    NoPadding(3, "NoPadding"),
+
+    // PKCS#2 v2.2 OAEP with MGF1
+    OAEP(4, "OAEP", new HashSet<>(
+            Arrays.asList(
+                    "OAEPPADDING",
+                    "OAEPWITHMD5ANDMGF1PADDING",
+                    "OAEPWITHSHA1ANDMGF1PADDING",
+                    "OAEPWITHMD5ANDMGF1PADDING",
+                    "OAEPWITHSHA1ANDMGF1PADDING",
+                    "OAEPWITHSHA-1ANDMGF1PADDING",
+                    "OAEPWITHSHA-224ANDMGF1PADDING",
+                    "OAEPWITHSHA-256ANDMGF1PADDING",
+                    "OAEPWITHSHA-384ANDMGF1PADDING",
+                    "OAEPWITHSHA-512ANDMGF1PADDING",
+                    "OAEPWITHSHA-512/224ANDMGF1PADDING",
+                    "OAEPWITHSHA-512/256ANDMGF1PADDING"))
+    );
+
+    private final int id;
+    private final String name;
+    private final Set<String> supportPaddings;
+
+    public int getId() {
+        return id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    KAERSAPaddingType(int id, String name) {
+        this(id, name, Collections.singleton(name));
+    }
+
+    KAERSAPaddingType(int id, String name, Set<String> supportPaddings) {
+        this.id = id;
+        this.name = name;
+        this.supportPaddings = supportPaddings;
+    }
+
+    public Set<String> getSupportPaddings() {
+        return supportPaddings;
+    }
+}
diff --git a/jdk/src/solaris/classes/org/openeuler/security/openssl/KAEUtils.java b/jdk/src/solaris/classes/org/openeuler/security/openssl/KAEUtils.java
new file mode 100644
index 00000000..f563fd07
--- /dev/null
+++ b/jdk/src/solaris/classes/org/openeuler/security/openssl/KAEUtils.java
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * 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.
+ */
+
+package org.openeuler.security.openssl;
+
+import javax.crypto.Cipher;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
+import java.security.*;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.X509EncodedKeySpec;
+import java.util.*;
+
+class KAEUtils {
+    enum MessageDigestType {
+        MD2("MD2", "md2", 16),
+        MD5("MD5", "md5", 16),
+        SHA1("SHA-1", "sha1", 20,
+                new HashSet<>(Arrays.asList("SHA1", "1.3.14.3.2.26", "OID.1.3.14.3.2.26"))),
+        SHA224("SHA-224", "sha224", 28,
+                new HashSet<>(Arrays.asList("2.16.840.1.101.3.4.2.4", "OID.2.16.840.1.101.3.4.2.4"))),
+        SHA256("SHA-256", "sha256", 32,
+                new HashSet<>(Arrays.asList("2.16.840.1.101.3.4.2.1", "OID.2.16.840.1.101.3.4.2.1"))),
+        SHA384("SHA-384", "sha384", 48,
+                new HashSet<>(Arrays.asList("2.16.840.1.101.3.4.2.2", "OID.2.16.840.1.101.3.4.2.2"))),
+        SHA512("SHA-512", "sha512", 64,
+                new HashSet<>(Arrays.asList("2.16.840.1.101.3.4.2.3", "OID.2.16.840.1.101.3.4.2.3"))),
+        SHA512_224("SHA-512/224", "sha512-224", 28,
+                new HashSet<>(Arrays.asList("2.16.840.1.101.3.4.2.5", "OID.2.16.840.1.101.3.4.2.5"))),
+        SHA_512_256("SHA-512/256", "sha512-256", 32,
+                new HashSet<>(Arrays.asList("2.16.840.1.101.3.4.2.6", "OID.2.16.840.1.101.3.4.2.6")));
+
+        final String digestName;
+        final String kaeDigestName;
+        final int digestLen;
+        final Set<String> aliasNames;
+
+        public String getDigestName() {
+            return digestName;
+        }
+
+        public String getKaeDigestName() {
+            return kaeDigestName;
+        }
+
+        public int getDigestLen() {
+            return digestLen;
+        }
+
+        public Set<String> getAliasNames() {
+            return aliasNames;
+        }
+
+        MessageDigestType(String digestName, String kaeDigestName, int digestLen, Set<String> aliasNames) {
+            this.digestName = digestName;
+            this.kaeDigestName = kaeDigestName;
+            this.digestLen = digestLen;
+            this.aliasNames = aliasNames;
+        }
+
+        MessageDigestType(String digestName, String kaeDigestName, int digestLen) {
+            this(digestName, kaeDigestName, digestLen, Collections.emptySet());
+        }
+    }
+
+    /**
+     * kae digest algorithm info map
+     */
+    private static final Map<String, String> DIGEST_ALGORITHM_NAME_MAP = new HashMap<>();
+    private static final Map<String, Integer> DIGEST_ALGORITHM_LENGTH_MAP = new HashMap<>();
+
+    static {
+        initDigest();
+    }
+
+    private static void initDigest() {
+        MessageDigestType[] messageDigestTypes = MessageDigestType.values();
+        for (MessageDigestType messageDigestType : messageDigestTypes) {
+            DIGEST_ALGORITHM_NAME_MAP.put(messageDigestType.getDigestName(), messageDigestType.getKaeDigestName());
+            DIGEST_ALGORITHM_LENGTH_MAP.put(messageDigestType.getDigestName(), messageDigestType.getDigestLen());
+            for (String aliasName : messageDigestType.getAliasNames()) {
+                DIGEST_ALGORITHM_NAME_MAP.put(aliasName, messageDigestType.getKaeDigestName());
+                DIGEST_ALGORITHM_LENGTH_MAP.put(aliasName, messageDigestType.getDigestLen());
+            }
+        }
+    }
+
+    // get the kae digest algorithm name
+    static String getKAEDigestName(String digestName) {
+        return DIGEST_ALGORITHM_NAME_MAP.get(digestName);
+    }
+
+    static int getDigestLength(String digestName) {
+        return DIGEST_ALGORITHM_LENGTH_MAP.get(digestName);
+    }
+
+    static class ConstructKeys {
+        /**
+         * Construct a public key from its encoding.
+         *
+         * @param encodedKey          the encoding of a public key.
+         * @param encodedKeyAlgorithm the algorithm the encodedKey is for.
+         * @return a public key constructed from the encodedKey.
+         */
+        private static PublicKey constructPublicKey(byte[] encodedKey,
+                                                    String encodedKeyAlgorithm)
+                throws InvalidKeyException, NoSuchAlgorithmException {
+            try {
+                KeyFactory keyFactory =
+                        KeyFactory.getInstance(encodedKeyAlgorithm);
+                X509EncodedKeySpec keySpec = new X509EncodedKeySpec(encodedKey);
+                return keyFactory.generatePublic(keySpec);
+            } catch (NoSuchAlgorithmException nsae) {
+                throw new NoSuchAlgorithmException("No installed providers " +
+                        "can create keys for the " +
+                        encodedKeyAlgorithm +
+                        "algorithm", nsae);
+            } catch (InvalidKeySpecException ike) {
+                throw new InvalidKeyException("Cannot construct public key", ike);
+            }
+        }
+
+        /**
+         * Construct a private key from its encoding.
+         *
+         * @param encodedKey          the encoding of a private key.
+         * @param encodedKeyAlgorithm the algorithm the wrapped key is for.
+         * @return a private key constructed from the encodedKey.
+         */
+        private static PrivateKey constructPrivateKey(byte[] encodedKey,
+                                                      String encodedKeyAlgorithm) throws InvalidKeyException,
+                NoSuchAlgorithmException {
+            try {
+                KeyFactory keyFactory =
+                        KeyFactory.getInstance(encodedKeyAlgorithm);
+                PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encodedKey);
+                return keyFactory.generatePrivate(keySpec);
+            } catch (NoSuchAlgorithmException nsae) {
+                throw new NoSuchAlgorithmException("No installed providers " +
+                        "can create keys for the " +
+                        encodedKeyAlgorithm +
+                        "algorithm", nsae);
+            } catch (InvalidKeySpecException ike) {
+                throw new InvalidKeyException("Cannot construct private key", ike);
+            }
+        }
+
+        /**
+         * Construct a secret key from its encoding.
+         *
+         * @param encodedKey          the encoding of a secret key.
+         * @param encodedKeyAlgorithm the algorithm the secret key is for.
+         * @return a secret key constructed from the encodedKey.
+         */
+        private static SecretKey constructSecretKey(byte[] encodedKey,
+                                                    String encodedKeyAlgorithm) {
+            return new SecretKeySpec(encodedKey, encodedKeyAlgorithm);
+        }
+
+        static Key constructKey(byte[] encoding, String keyAlgorithm,
+                                int keyType) throws InvalidKeyException, NoSuchAlgorithmException {
+            switch (keyType) {
+                case Cipher.SECRET_KEY:
+                    return constructSecretKey(encoding, keyAlgorithm);
+                case Cipher.PRIVATE_KEY:
+                    return constructPrivateKey(encoding, keyAlgorithm);
+                case Cipher.PUBLIC_KEY:
+                    return constructPublicKey(encoding, keyAlgorithm);
+                default:
+                    throw new InvalidKeyException("Unknown keytype " + keyType);
+            }
+        }
+    }
+}
diff --git a/jdk/src/solaris/native/org/openeuler/security/openssl/kae_cipher_aes.c b/jdk/src/solaris/native/org/openeuler/security/openssl/kae_cipher_aes.c
new file mode 100644
index 00000000..8a9526a2
--- /dev/null
+++ b/jdk/src/solaris/native/org/openeuler/security/openssl/kae_cipher_aes.c
@@ -0,0 +1,255 @@
+/*
+ * 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.
+ */
+
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include <string.h>
+#include "kae_log.h"
+#include "kae_exception.h"
+#include "org_openeuler_security_openssl_KAEAESCipher.h"
+
+static const EVP_CIPHER* EVPGetCipherByName(JNIEnv* env, const char* algo)
+{
+    static const EVP_CIPHER* aes128Ecb = NULL;
+    static const EVP_CIPHER* aes128Cbc = NULL;
+    static const EVP_CIPHER* aes128Ctr = NULL;
+    static const EVP_CIPHER* aes192Ecb = NULL;
+    static const EVP_CIPHER* aes192Cbc = NULL;
+    static const EVP_CIPHER* aes192Ctr = NULL;
+    static const EVP_CIPHER* aes256Ecb = NULL;
+    static const EVP_CIPHER* aes256Cbc = NULL;
+    static const EVP_CIPHER* aes256Ctr = NULL;
+
+    if (strcasecmp(algo, "aes-128-ecb") == 0) {
+        return aes128Ecb == NULL ? aes128Ecb = EVP_get_cipherbyname(algo) : aes128Ecb;
+    } else if (strcasecmp(algo, "aes-128-cbc") == 0) {
+        return aes128Cbc == NULL ? aes128Cbc = EVP_get_cipherbyname(algo) : aes128Cbc;
+    } else if (strcasecmp(algo, "aes-128-ctr") == 0) {
+        return aes128Ctr == NULL ? aes128Ctr = EVP_get_cipherbyname(algo) : aes128Ctr;
+    } else if (strcasecmp(algo, "aes-192-ecb") == 0) {
+        return aes192Ecb == NULL ? aes192Ecb = EVP_get_cipherbyname(algo) : aes192Ecb;
+    } else if (strcasecmp(algo, "aes-192-cbc") == 0) {
+        return aes192Cbc == NULL ? aes192Cbc = EVP_get_cipherbyname(algo) : aes192Cbc;
+    } else if (strcasecmp(algo, "aes-192-ctr") == 0) {
+        return aes192Ctr == NULL ? aes192Ctr = EVP_get_cipherbyname(algo) : aes192Ctr;
+    } else if (strcasecmp(algo, "aes-256-ecb") == 0) {
+        return aes256Ecb == NULL ? aes256Ecb = EVP_get_cipherbyname(algo) : aes256Ecb;
+    } else if (strcasecmp(algo, "aes-256-cbc") == 0) {
+        return aes256Cbc == NULL ? aes256Cbc = EVP_get_cipherbyname(algo) : aes256Cbc;
+    } else if (strcasecmp(algo, "aes-256-ctr") == 0) {
+        return aes256Ctr == NULL ? aes256Ctr = EVP_get_cipherbyname(algo) : aes256Ctr;
+    } else {
+        KAE_ThrowRuntimeException(env, "EVPGetCipherByName error");
+        return 0;
+    }
+}
+
+/*
+ * Class:     org_openeuler_security_openssl_KAEAESCipher
+ * Method:    nativeInit
+ * Signature: (Ljava/lang/String;Z[B[B)J
+ */
+JNIEXPORT jlong JNICALL
+Java_org_openeuler_security_openssl_KAEAESCipher_nativeInit(JNIEnv* env, jclass cls,
+    jstring cipherType, jboolean encrypt, jbyteArray key, jbyteArray iv, jboolean padding)
+{
+    EVP_CIPHER_CTX* ctx = NULL;
+    jbyte* keyBytes = NULL;
+    jbyte* ivBytes = NULL;
+    const EVP_CIPHER* cipher = NULL;
+
+    const char* algo = (*env)->GetStringUTFChars(env, cipherType, 0);
+    cipher = EVPGetCipherByName(env, algo);
+    (*env)->ReleaseStringUTFChars(env, cipherType, algo);
+    if (cipher == NULL) {
+        KAE_ThrowOOMException(env, "create EVP_CIPHER fail");
+        goto err;
+    }
+
+    ctx = EVP_CIPHER_CTX_new();
+    if (ctx == NULL) {
+        KAE_ThrowOOMException(env, "create EVP_CIPHER_CTX fail");
+        goto err;
+    }
+
+    if (iv != NULL) {
+        ivBytes = (*env)->GetByteArrayElements(env, iv, NULL);
+    }
+    const unsigned char* i = (const unsigned char*) ivBytes;
+
+    if (key != NULL) {
+        keyBytes = (*env)->GetByteArrayElements(env, key, NULL);
+    }
+    const unsigned char* k = (const unsigned char*) keyBytes;
+
+    if (!EVP_CipherInit_ex(ctx, cipher, NULL, k, i, encrypt ? 1 : 0)) {
+        KAE_ThrowFromOpenssl(env, "EVP_CipherInit_ex failed", KAE_ThrowRuntimeException);
+        goto err;
+    }
+    KAE_TRACE("KAEAESCipher_nativeInit EVP_CipherInit_ex(ctx = %p, cipher = %p, key = %p, iv = %p, encrypt = %d) "
+              "success", ctx, cipher, key, iv, encrypt ? 1 : 0);
+
+    EVP_CIPHER_CTX_set_padding(ctx, padding ? 1 : 0);
+
+    if (iv != NULL) {
+        (*env)->ReleaseByteArrayElements(env, iv, ivBytes, 0);
+    }
+    (*env)->ReleaseByteArrayElements(env, key, keyBytes, 0);
+    return (jlong) ctx;
+err:
+    if (ctx != NULL) {
+        EVP_CIPHER_CTX_free(ctx);
+    }
+    if (ivBytes != NULL) {
+        (*env)->ReleaseByteArrayElements(env, iv, ivBytes, 0);
+    }
+    if (keyBytes != NULL) {
+        (*env)->ReleaseByteArrayElements(env, key, keyBytes, 0);
+    }
+    return 0;
+}
+
+/*
+ * Class:     org_openeuler_security_openssl_KAEAESCipher
+ * Method:    nativeUpdate
+ * Signature: (JZ[BII[BI)I
+ */
+JNIEXPORT jint JNICALL
+Java_org_openeuler_security_openssl_KAEAESCipher_nativeUpdate(JNIEnv* env, jclass cls,
+    jlong ctxAddress, jbyteArray inArr, jint inOfs, jint inLen, jbyteArray outArr, jint outOfs)
+{
+    jbyte* in = NULL;
+    unsigned char* out = NULL;
+
+    EVP_CIPHER_CTX* ctx = (EVP_CIPHER_CTX*) ctxAddress;
+    if (ctx == NULL) {
+        goto err;
+    }
+
+    if (inArr == NULL || outArr == NULL) {
+        goto err;
+    }
+    int inputLen = (*env)->GetArrayLength(env, inArr);
+    if ((inOfs < 0) || (inOfs > inputLen) || (inLen < 0) || (inLen > inputLen - inOfs)) {
+        KAE_ThrowArrayIndexOutOfBoundsException(env, "inArr");
+        goto err;
+    }
+    in = malloc(sizeof(jbyte) * inputLen);
+    if (in == NULL) {
+        KAE_ThrowOOMException(env, "malloc error");
+        goto err;
+    }
+    (*env)->GetByteArrayRegion(env, inArr, 0, inputLen, in);
+
+    int outputLen = (*env)->GetArrayLength(env, outArr);
+    if ((outOfs < 0) || (outOfs > outputLen) || (inLen < 0) || (inLen > outputLen - outOfs)) {
+        KAE_ThrowArrayIndexOutOfBoundsException(env, "outArr");
+        goto err;
+    }
+    out = malloc(outputLen - outOfs);
+    if (out == NULL) {
+        KAE_ThrowOOMException(env, "malloc error");
+        goto err;
+    }
+
+    unsigned int bytesWritten = 0;
+    if (EVP_CipherUpdate(ctx, out, &bytesWritten, in + inOfs, inLen) == 0) {
+        KAE_ThrowFromOpenssl(env, "EVP_CipherUpdate failed", KAE_ThrowRuntimeException);
+        goto err;
+    }
+    KAE_TRACE("KAEAESCipher_nativeUpdate EVP_CipherUpdate success, bytesWritten = %d", bytesWritten);
+    (*env)->SetByteArrayRegion(env, outArr, outOfs, bytesWritten, (jbyte*) out);
+
+    free(in);
+    free(out);
+    return bytesWritten;
+err:
+    if (in != NULL) {
+        free(in);
+    }
+    if (out != NULL) {
+        free(out);
+    }
+    return 0;
+}
+
+/*
+ * Class:     org_openeuler_security_openssl_KAEAESCipher
+ * Method:    nativeFinal
+ * Signature: (JZ[BI)I
+ */
+JNIEXPORT jint JNICALL
+Java_org_openeuler_security_openssl_KAEAESCipher_nativeFinal(JNIEnv* env, jclass cls,
+    jlong ctxAddress, jbyteArray outArr, jint outOfs)
+{
+    unsigned char* out;
+    EVP_CIPHER_CTX* ctx = (EVP_CIPHER_CTX*) ctxAddress;
+    KAE_TRACE("KAEAESCipher_nativeFinal(ctxAddress = %p, outArr = %p, outOfs = %d)",
+              ctx, outArr, outOfs);
+    if (ctx == NULL) {
+        goto err;
+    }
+    if (outArr == NULL) {
+        goto err;
+    }
+    int outputLen = (*env)->GetArrayLength(env, outArr);
+    out = malloc(outputLen - outOfs);
+    if (out == NULL) {
+        KAE_ThrowOOMException(env, "malloc error");
+        goto err;
+    }
+    unsigned int bytesWritten = 0;
+    int result_code = EVP_CipherFinal_ex(ctx, out, &bytesWritten);
+    if (result_code == 0) {
+        KAE_ThrowFromOpenssl(env, "EVP_CipherFinal_ex failed", KAE_ThrowBadPaddingException);
+        goto err;
+    }
+    KAE_TRACE("KAEAESCipher_nativeFinal EVP_CipherFinal_ex success, bytesWritten = %d", bytesWritten);
+    (*env)->SetByteArrayRegion(env, outArr, outOfs, bytesWritten, (jbyte*) out);
+    free(out);
+    KAE_TRACE("KAEAESCipher_nativeFinal: finished");
+    return bytesWritten;
+
+err:
+    if (out != NULL) {
+        free(out);
+    }
+    return 0;
+}
+
+/*
+ * Class:     org_openeuler_security_openssl_KAEAESCipher
+ * Method:    nativeFree
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL
+Java_org_openeuler_security_openssl_KAEAESCipher_nativeFree(JNIEnv* env, jclass cls, jlong ctxAddress)
+{
+    EVP_CIPHER_CTX* ctx = (EVP_CIPHER_CTX*) ctxAddress;
+    KAE_TRACE("KAEAESCipher_nativeFree(ctx = %p)", ctx);
+    if (ctx != NULL) {
+        EVP_CIPHER_CTX_free(ctx);
+    }
+
+    KAE_TRACE("KAEAESCipher_nativeFree: finished");
+}
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
new file mode 100644
index 00000000..ed645698
--- /dev/null
+++ b/jdk/src/solaris/native/org/openeuler/security/openssl/kae_cipher_rsa.c
@@ -0,0 +1,463 @@
+/*
+ * 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.
+ */
+
+#include <openssl/rsa.h>
+#include <openssl/evp.h>
+#include "kae_util.h"
+#include "kae_exception.h"
+#include "org_openeuler_security_openssl_KAERSACipher.h"
+
+#define SUCCESS 1
+#define FAILED -1
+
+typedef int RSACryptOperation(int, const unsigned char*, unsigned char*, RSA*, int);
+
+typedef int EvpPkeyCryptOperation(EVP_PKEY_CTX*, unsigned char*, size_t*, const unsigned char*, size_t);
+
+typedef int EvpPkeyCryptInitOperation(EVP_PKEY_CTX*);
+
+/*
+ * RSA encrypt or decrypt for NoPadding or PKCS1Padding , follow the steps below
+ *
+ */
+static int RSACryptNotOAEPPadding(JNIEnv* env, jlong keyAddress, jint inLen, jbyteArray in, jbyteArray out,
+    jint paddingType, RSACryptOperation rsaCryptOperation, char* cryptName) {
+    jbyte* inBytes = NULL;
+    jbyte* outBytes = NULL;
+    int resultSize = 0;
+
+    // get RSA
+    EVP_PKEY* pkey = (EVP_PKEY*)keyAddress;
+
+    // rsa = pkey->rsa
+    RSA* rsa = EVP_PKEY_get1_RSA(pkey);
+    if (rsa == NULL) {
+        KAE_ThrowFromOpenssl(env, "EVP_PKEY_get1_RSA", KAE_ThrowRuntimeException);
+        return 0;
+    }
+
+    // do encrypt or decrypt
+    inBytes = (*env)->GetByteArrayElements(env, in, NULL);
+    if (inBytes == NULL) {
+        KAE_ThrowNullPointerException(env, "GetByteArrayElements failed");
+        goto cleanup;
+    }
+    outBytes = (*env)->GetByteArrayElements(env, out, NULL);
+    if (outBytes == NULL) {
+        KAE_ThrowNullPointerException(env, "GetByteArrayElements failed");
+        goto cleanup;
+    }
+    resultSize = rsaCryptOperation(inLen, (unsigned char*)inBytes, (unsigned char*)outBytes, rsa, paddingType);
+    if (resultSize <= 0) {
+        KAE_ThrowFromOpenssl(env, cryptName, KAE_ThrowBadPaddingException);
+        goto cleanup;
+    }
+    jsize outLen = (*env)->GetArrayLength(env, out);
+    (*env)->SetByteArrayRegion(env, out, 0, outLen, outBytes);
+
+cleanup:
+    if (outBytes != NULL) {
+        (*env)->ReleaseByteArrayElements(env, out, outBytes, 0);
+    }
+    if (inBytes != NULL) {
+        (*env)->ReleaseByteArrayElements(env, in, inBytes, 0);
+    }
+    return resultSize;
+}
+
+/*
+ * set rsa padding
+ */
+static int SetRSAPadding(JNIEnv* env, EVP_PKEY_CTX* pkeyCtx, int paddingType) {
+    if (EVP_PKEY_CTX_set_rsa_padding(pkeyCtx, paddingType) <= 0) {
+        KAE_ThrowFromOpenssl(env, "EVP_PKEY_CTX_set_rsa_padding", KAE_ThrowInvalidAlgorithmParameterException);
+        return FAILED;
+    }
+    return SUCCESS;
+}
+
+/*
+ * set rsa mgf1 md
+ */
+static int SetRSAMgf1Md(JNIEnv* env, EVP_PKEY_CTX* pkeyCtx, const char* mgf1MdAlgoUTF) {
+    EVP_MD* mgf1MD = (EVP_MD*)EVP_get_digestbyname(mgf1MdAlgoUTF);
+    if (mgf1MD == NULL) {
+        KAE_ThrowFromOpenssl(env, "EVP_get_digestbyname", KAE_ThrowInvalidAlgorithmParameterException);
+        return FAILED;
+    }
+    if (EVP_PKEY_CTX_set_rsa_mgf1_md(pkeyCtx, mgf1MD) <= 0) {
+        KAE_ThrowFromOpenssl(env, "EVP_PKEY_CTX_set_rsa_mgf1_md", KAE_ThrowInvalidAlgorithmParameterException);
+        return FAILED;
+    }
+    return SUCCESS;
+}
+
+/*
+ * set rsa oaep md
+ */
+static int SetRSAOaepMd(JNIEnv* env, EVP_PKEY_CTX* pkeyCtx, const char* oaepMdAlgoUTF) {
+    EVP_MD* oaepMD = (EVP_MD*)EVP_get_digestbyname(oaepMdAlgoUTF);
+    if (oaepMD == NULL) {
+        KAE_ThrowFromOpenssl(env, "EVP_get_digestbyname", KAE_ThrowInvalidAlgorithmParameterException);
+        return FAILED;
+    }
+    if (EVP_PKEY_CTX_set_rsa_oaep_md(pkeyCtx, oaepMD) <= 0) {
+        KAE_ThrowFromOpenssl(env, "EVP_PKEY_CTX_set_rsa_oaep_md", KAE_ThrowInvalidAlgorithmParameterException);
+        return FAILED;
+    }
+    return SUCCESS;
+}
+
+/*
+ * set rsa oaep label
+ */
+static int SetRSAOaepLabel(JNIEnv* env, EVP_PKEY_CTX* pkeyCtx, jbyte* labelBytes, jsize labelSize) {
+    if (EVP_PKEY_CTX_set0_rsa_oaep_label(pkeyCtx, labelBytes, labelSize) <= 0) {
+        KAE_ThrowFromOpenssl(env, "EVP_PKEY_CTX_set0_rsa_oaep_label", KAE_ThrowInvalidAlgorithmParameterException);
+        return FAILED;
+    }
+    return SUCCESS;
+}
+
+/*
+ * release rsa oaep temp resource
+ */
+static void ReleaseRSACryptOAEPResource(JNIEnv* env, EVP_PKEY_CTX* pkeyCtx,
+    jstring mgf1MdAlgo, const char* mgf1MdAlgoUTF, jstring oaepMdAlgo, const char* oaepMdAlgoUTF,
+    jbyteArray in, jbyte* inBytes, jbyteArray out, jbyte* outBytes) {
+    if (mgf1MdAlgoUTF != NULL) {
+        (*env)->ReleaseStringUTFChars(env, mgf1MdAlgo, mgf1MdAlgoUTF);
+    }
+    if (oaepMdAlgoUTF != NULL) {
+        (*env)->ReleaseStringUTFChars(env, oaepMdAlgo, oaepMdAlgoUTF);
+    }
+    if (outBytes != NULL) {
+        (*env)->ReleaseByteArrayElements(env, out, outBytes, 0);
+    }
+    if (inBytes != NULL) {
+        (*env)->ReleaseByteArrayElements(env, in, inBytes, 0);
+    }
+    EVP_PKEY_CTX_free(pkeyCtx);
+}
+
+static int RSACryptOAEPPadding(JNIEnv* env, jlong keyAddress, jint inLen, jbyteArray in, jbyteArray out,
+    jint paddingType, jstring oaepMdAlgo, jstring mgf1MdAlgo, jbyteArray label,
+    EvpPkeyCryptInitOperation cryptInitOperation, char* cryptInitName,
+    EvpPkeyCryptOperation cryptOperation, char* cryptName) {
+    EVP_PKEY_CTX* pkeyCtx = NULL;
+    const char* mgf1MdAlgoUTF = NULL;
+    const char* oaepMdAlgoUTF = NULL;
+    jbyte* labelBytes = NULL;
+    jbyte* outBytes = NULL;
+    jbyte* inBytes = NULL;
+    // outLen type should be size_t
+    // EVP_PKEY_encrypt takes the outLen address as a parameter, and the parameter type is size_t*
+    // You can refer to the issue #2774 to see more content
+    size_t outLen = 0;
+
+    EVP_PKEY* pkey = (EVP_PKEY*) keyAddress;
+
+    // new ctx
+    // rsa encrypt/decrypt init
+    if ((pkeyCtx = EVP_PKEY_CTX_new(pkey, NULL)) == NULL || cryptInitOperation(pkeyCtx) <= 0) {
+        KAE_ThrowFromOpenssl(env, pkeyCtx == NULL ? "EVP_PKEY_CTX_new" : cryptInitName, KAE_ThrowInvalidKeyException);
+        goto cleanup;
+    }
+
+    if ((mgf1MdAlgoUTF = (*env)->GetStringUTFChars(env, mgf1MdAlgo, 0)) == NULL ||
+        (oaepMdAlgoUTF = (*env)->GetStringUTFChars(env, oaepMdAlgo, 0)) == NULL) {
+        KAE_ThrowOOMException(env, "GetStringUTFChars failed");
+        goto cleanup;
+    }
+
+    /*
+     * set padding type
+     * set rsa mgf1 md
+     * set rsa oaep md
+     */
+    if(SetRSAPadding(env, pkeyCtx, paddingType) == FAILED ||
+       SetRSAMgf1Md(env, pkeyCtx, mgf1MdAlgoUTF) == FAILED ||
+       SetRSAOaepMd(env, pkeyCtx, oaepMdAlgoUTF) == FAILED) {
+        goto cleanup;
+    }
+
+    // set rsa oaep label
+    jsize labelSize = (*env)->GetArrayLength(env, label);
+    if (labelSize > 0) {
+        // EVP_PKEY_CTX_free will free the labelBytes, so we can not free labelBytes when cleanup.
+        // Only SetRSAOaepLabel failed , free labelBytes.
+        if ((labelBytes = malloc(labelSize)) == NULL) {
+            KAE_ThrowNullPointerException(env, "malloc failed");
+            goto cleanup;
+        }
+        (*env)->GetByteArrayRegion(env, label, 0, labelSize, labelBytes);
+        if(SetRSAOaepLabel(env, pkeyCtx, labelBytes, labelSize) == FAILED) {
+            free(labelBytes);
+            goto cleanup;
+        }
+    }
+
+    // do encrypt/decrypt
+    outLen = (size_t)(*env)->GetArrayLength(env, out);
+    if ((outBytes = (*env)->GetByteArrayElements(env, out, NULL)) == NULL ||
+        (inBytes = (*env)->GetByteArrayElements(env, in, NULL)) == NULL) {
+        KAE_ThrowNullPointerException(env, "GetByteArrayElements failed");
+        goto cleanup;
+    }
+    if (cryptOperation(pkeyCtx, (unsigned char*)outBytes, &outLen, (unsigned char*)inBytes, inLen) <= 0) {
+        KAE_ThrowFromOpenssl(env, cryptName, KAE_ThrowBadPaddingException);
+        goto cleanup;
+    }
+    (*env)->SetByteArrayRegion(env, out, 0, outLen, outBytes);
+
+cleanup:
+    ReleaseRSACryptOAEPResource(env, pkeyCtx, mgf1MdAlgo, mgf1MdAlgoUTF, oaepMdAlgo, oaepMdAlgoUTF,
+        in, inBytes, out, outBytes);
+    return outLen;
+}
+
+/*
+ * Release rsa param n,e,d,p,q,dmp1,dmq1,iqmp
+ */
+void ReleaseRSAParams(BIGNUM* bnN, BIGNUM* bnE, BIGNUM* bnD, BIGNUM* bnP, BIGNUM* bnQ,
+                      BIGNUM* bnDMP1, BIGNUM* bnDMQ1, BIGNUM* bnIQMP) {
+    KAE_ReleaseBigNumFromByteArray(bnN);
+    KAE_ReleaseBigNumFromByteArray(bnE);
+    KAE_ReleaseBigNumFromByteArray(bnD);
+    KAE_ReleaseBigNumFromByteArray(bnP);
+    KAE_ReleaseBigNumFromByteArray(bnQ);
+    KAE_ReleaseBigNumFromByteArray(bnDMP1);
+    KAE_ReleaseBigNumFromByteArray(bnDMQ1);
+    KAE_ReleaseBigNumFromByteArray(bnIQMP);
+}
+
+/*
+ * Create rsa private crt key
+ * Class:     org_openeuler_security_openssl_KAERSACipher
+ * Method:    nativeCreateRSAPrivateCrtKey
+ * Signature: ([B[B[B[B[B[B[B[B)J
+ */
+JNIEXPORT jlong JNICALL Java_org_openeuler_security_openssl_KAERSACipher_nativeCreateRSAPrivateCrtKey(JNIEnv* env,
+    jclass cls, jbyteArray n, jbyteArray e, jbyteArray d, jbyteArray p, jbyteArray q,
+    jbyteArray dmp1, jbyteArray dmq1, jbyteArray iqmp) {
+    BIGNUM* bnN = NULL;
+    BIGNUM* bnE = NULL;
+    BIGNUM* bnD = NULL;
+    BIGNUM* bnP = NULL;
+    BIGNUM* bnQ = NULL;
+    BIGNUM* bnDMP1 = NULL;
+    BIGNUM* bnDMQ1 = NULL;
+    BIGNUM* bnIQMP = NULL;
+    RSA* rsa = NULL;
+    EVP_PKEY* pkey = NULL;
+
+    // convert to big num
+    if ((bnN = KAE_GetBigNumFromByteArray(env, n)) == NULL ||
+        (bnE = KAE_GetBigNumFromByteArray(env, e)) == NULL ||
+        (bnD = KAE_GetBigNumFromByteArray(env, d)) == NULL ||
+        (bnP = KAE_GetBigNumFromByteArray(env, p)) == NULL ||
+        (bnQ = KAE_GetBigNumFromByteArray(env, q)) == NULL ||
+        (bnDMP1 = KAE_GetBigNumFromByteArray(env, dmp1)) == NULL ||
+        (bnDMQ1 = KAE_GetBigNumFromByteArray(env, dmq1)) == NULL ||
+        (bnIQMP = KAE_GetBigNumFromByteArray(env, iqmp)) == NULL) {
+        goto err;
+    }
+
+    // new pkey
+    pkey = EVP_PKEY_new();
+    if (pkey == NULL) {
+        KAE_ThrowFromOpenssl(env, "EVP_PKEY_new", KAE_ThrowRuntimeException);
+        goto err;
+    }
+
+    // new rsa
+    rsa = RSA_new();
+    if (rsa == NULL) {
+        KAE_ThrowFromOpenssl(env, "RSA_new", KAE_ThrowRuntimeException);
+        goto err;
+    }
+
+    // set rsa private crt key params n,e,d,p,q,dmp1,dmp1,iqmp
+    if (RSA_set0_key(rsa, bnN, bnE, bnD) <= 0 ||
+        RSA_set0_factors(rsa, bnP, bnQ) <= 0 ||
+        RSA_set0_crt_params(rsa, bnDMP1, bnDMQ1, bnIQMP) <= 0) {
+        KAE_ThrowFromOpenssl(env, "RSA set param", KAE_ThrowRuntimeException);
+        goto err;
+    }
+
+    // assign rsa to pkey
+    int result = EVP_PKEY_assign_RSA(pkey, rsa);
+    if (result <= 0) {
+        KAE_ThrowFromOpenssl(env, "EVP_PKEY_assign_RSA", KAE_ThrowRuntimeException);
+        goto err;
+    }
+    return (jlong)pkey;
+err:
+    ReleaseRSAParams(bnN, bnE, bnD, bnP, bnQ, bnDMP1, bnDMQ1, bnIQMP);
+    RSA_free(rsa);
+    EVP_PKEY_free(pkey);
+    return 0;
+}
+
+/*
+ * Create rsa public key
+ * Class:     org_openeuler_security_openssl_KAERSACipher
+ * Method:    nativeCreateRSAPublicKey
+ * Signature: ([B[B)J
+ */
+JNIEXPORT jlong JNICALL Java_org_openeuler_security_openssl_KAERSACipher_nativeCreateRSAPublicKey(
+    JNIEnv* env, jclass cls, jbyteArray n, jbyteArray e) {
+    BIGNUM* bnN = NULL;
+    BIGNUM* bnE = NULL;
+    RSA* rsa = NULL;
+    EVP_PKEY* pkey = NULL;
+
+    // get public key param n
+    bnN = KAE_GetBigNumFromByteArray(env, n);
+    if (bnN == NULL) {
+        goto err;
+    }
+
+    // get public key param e
+    bnE = KAE_GetBigNumFromByteArray(env, e);
+    if (bnE == NULL) {
+        goto err;
+    }
+
+    // new RSA
+    rsa = RSA_new();
+    if (rsa == NULL) {
+        KAE_ThrowFromOpenssl(env, "RSA_new", KAE_ThrowRuntimeException);
+        goto err;
+    }
+
+    // new EVP_PKEY
+    pkey = EVP_PKEY_new();
+    if (pkey == NULL) {
+        KAE_ThrowFromOpenssl(env, "EVP_PKEY_new", KAE_ThrowRuntimeException);
+        goto err;
+    }
+
+    // set rsa public key params n and e
+    if(RSA_set0_key(rsa, bnN, bnE, NULL) <= 0) {
+        KAE_ThrowFromOpenssl(env, "RSA_set0_key", KAE_ThrowRuntimeException);
+        goto err;
+    }
+
+    // assign rsa to pkey
+    int result = EVP_PKEY_assign_RSA(pkey, rsa);
+    if (result <= 0) {
+        KAE_ThrowFromOpenssl(env, "EVP_PKEY_assign_RSA", KAE_ThrowRuntimeException);
+        goto err;
+    }
+    return (jlong)pkey;
+err:
+    KAE_ReleaseBigNumFromByteArray(bnN);
+    KAE_ReleaseBigNumFromByteArray(bnE);
+    RSA_free(rsa);
+    EVP_PKEY_free(pkey);
+    return 0;
+}
+
+/*
+ * Class:     org_openeuler_security_openssl_KAERSACipher
+ * Method:    nativeRSAPrivateEncrypt
+ * Signature: (JI[B[BI)I
+ */
+JNIEXPORT jint JNICALL Java_org_openeuler_security_openssl_KAERSACipher_nativeRSAPrivateEncrypt(JNIEnv* env,
+    jclass cls, jlong keyAddress, jint inLen, jbyteArray in, jbyteArray out, jint paddingType) {
+    return RSACryptNotOAEPPadding(env, keyAddress, inLen, in, out, paddingType, RSA_private_encrypt,
+                                  "RSA_private_encrypt");
+}
+
+/*
+ * Class:     org_openeuler_security_openssl_KAERSACipher
+ * Method:    nativeRSAPrivateDecrypt
+ * Signature: (JI[B[BI)I
+ */
+JNIEXPORT jint JNICALL Java_org_openeuler_security_openssl_KAERSACipher_nativeRSAPrivateDecrypt(JNIEnv* env,
+    jclass cls, jlong keyAddress, jint inLen, jbyteArray in, jbyteArray out, jint paddingType) {
+    return RSACryptNotOAEPPadding(env, keyAddress, inLen, in, out, paddingType, RSA_private_decrypt,
+                                  "RSA_private_decrypt");
+}
+
+/*
+ * Class:     org_openeuler_security_openssl_KAERSACipher
+ * Method:    nativeRSAPublicEncrypt
+ * Signature: (JI[B[BI)I
+ */
+JNIEXPORT jint JNICALL Java_org_openeuler_security_openssl_KAERSACipher_nativeRSAPublicEncrypt(JNIEnv* env,
+    jclass cls, jlong keyAddress, jint inLen, jbyteArray in, jbyteArray out, jint paddingType) {
+    return RSACryptNotOAEPPadding(env, keyAddress, inLen, in, out, paddingType, RSA_public_encrypt,
+                                  "RSA_public_encrypt");
+}
+
+/*
+ * Class:     org_openeuler_security_openssl_KAERSACipher
+ * Method:    nativeRSAPublicDecrypt
+ * Signature: (JI[B[BI)I
+ */
+JNIEXPORT jint JNICALL Java_org_openeuler_security_openssl_KAERSACipher_nativeRSAPublicDecrypt(JNIEnv* env,
+    jclass cls, jlong keyAddress, jint inLen, jbyteArray in, jbyteArray out, jint paddingType) {
+    return RSACryptNotOAEPPadding(env, keyAddress, inLen, in, out, paddingType, RSA_public_decrypt,
+                                  "RSA_public_decrypt");
+}
+
+/*
+ * Class:     org_openeuler_security_openssl_KAERSACipher
+ * Method:    nativeRSAEncryptOAEPPading
+ * Signature: (JI[B[BI[B[B[B)I
+ */
+JNIEXPORT jint JNICALL Java_org_openeuler_security_openssl_KAERSACipher_nativeRSAEncryptOAEPPadding(JNIEnv* env,
+    jclass cls, jlong keyAddress, jint inLen, jbyteArray in, jbyteArray out,
+    jint paddingType,jstring oaepMdAlgo, jstring mgf1MdAlgo, jbyteArray label) {
+    return RSACryptOAEPPadding(env, keyAddress, inLen, in, out, paddingType, oaepMdAlgo, mgf1MdAlgo, label,
+                               EVP_PKEY_encrypt_init, "EVP_PKEY_encrypt_init",
+                               EVP_PKEY_encrypt, "EVP_PKEY_encrypt");
+}
+
+/*
+ * Class:     org_openeuler_security_openssl_KAERSACipher
+ * Method:    nativeRSADecryptOAEPPadding
+ * Signature: (JI[B[BILjava/lang/String;Ljava/lang/String;[B)I
+ */
+JNIEXPORT jint JNICALL Java_org_openeuler_security_openssl_KAERSACipher_nativeRSADecryptOAEPPadding(JNIEnv* env,
+    jclass cls, jlong keyAddress, jint inLen, jbyteArray in, jbyteArray out, jint paddingType,
+    jstring oaepMdAlgo, jstring mgf1MdAlgo, jbyteArray label) {
+    return RSACryptOAEPPadding(env, keyAddress, inLen, in, out, paddingType, oaepMdAlgo, mgf1MdAlgo, label,
+                               EVP_PKEY_decrypt_init, "EVP_PKEY_decrypt_init",
+                               EVP_PKEY_decrypt, "EVP_PKEY_decrypt");
+}
+
+/*
+ * Class:     org_openeuler_security_openssl_KAERSACipher
+ * Method:    nativeFreeKey
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_org_openeuler_security_openssl_KAERSACipher_nativeFreeKey(JNIEnv* env,
+    jclass cls, jlong keyAddress) {
+    EVP_PKEY* pkey = (EVP_PKEY*) keyAddress;
+    if (pkey != NULL) {
+        EVP_PKEY_free(pkey);
+    }
+}
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
new file mode 100644
index 00000000..6ae14969
--- /dev/null
+++ b/jdk/src/solaris/native/org/openeuler/security/openssl/kae_digest.c
@@ -0,0 +1,227 @@
+/*
+ * 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.
+ */
+
+#include <openssl/evp.h>
+#include <openssl/md5.h>
+#include "kae_log.h"
+#include "kae_exception.h"
+#include "org_openeuler_security_openssl_KAEDigest.h"
+
+#define DIGEST_STACK_SIZE 1024
+#define DIGEST_CHUNK_SIZE 64*1024
+#define DIGEST_LENGTH_THRESHOLD 48
+
+/*
+ * Class:     org_openeuler_security_openssl_KAEDigest
+ * Method:    nativeInit
+ * Signature: (Ljava/lang/String;)J
+ */
+JNIEXPORT jlong JNICALL
+Java_org_openeuler_security_openssl_KAEDigest_nativeInit(JNIEnv *env, jclass cls, jstring algorithmName)
+{
+    EVP_MD_CTX* ctx = NULL;
+
+    if (algorithmName == NULL) {
+        KAE_ThrowNullPointerException(env, "algorithm is null");
+        return 0;
+    }
+
+    // EVP_get_digestbyname
+    const char* algo_utf = (*env)->GetStringUTFChars(env, algorithmName, 0);
+    EVP_MD* md = (EVP_MD*) EVP_get_digestbyname(algo_utf);
+    (*env)->ReleaseStringUTFChars(env, algorithmName, algo_utf);
+    if (md == NULL) {
+        KAE_TRACE("%s not supported", algo_utf);
+        return 0;
+    }
+    KAE_TRACE("KAEDigest_nativeInit: create md => %p", md);
+
+    ctx = EVP_MD_CTX_create();
+    if (ctx == NULL) {
+        KAE_ThrowOOMException(env, "create EVP_MD_CTX fail");
+        return 0;
+    }
+    KAE_TRACE("KAEDigest_nativeInit: create ctx => %p", ctx);
+
+    // EVP_DigestInit_ex
+    int result_code = EVP_DigestInit_ex(ctx, md, NULL);
+    if (result_code == 0) {
+        KAE_ThrowFromOpenssl(env, "EVP_DigestInit_ex failed", KAE_ThrowRuntimeException);
+        goto err;
+    }
+    KAE_TRACE("KAEDigest_nativeInit EVP_DigestInit_ex(ctx = %p, md = %p) success", ctx, md);
+
+    KAE_TRACE("KAEDigest_nativeInit: finished");
+    return (jlong) ctx;
+
+err:
+    EVP_MD_CTX_destroy(ctx);
+    return 0;
+}
+
+/*
+ * Class:     org_openeuler_security_openssl_KAEDigest
+ * Method:    nativeUpdate
+ * Signature: (Ljava/lang/String;J[BII)I
+ */
+JNIEXPORT void JNICALL
+Java_org_openeuler_security_openssl_KAEDigest_nativeUpdate(JNIEnv *env, jclass cls, jlong ctxAddress,
+    jbyteArray input, jint offset, jint inLen)
+{
+    EVP_MD_CTX* ctx = (EVP_MD_CTX*) ctxAddress;
+    KAE_TRACE("KAEDigest_nativeUpdate(ctx = %p, input = %p, offset = %d, inLen = %d", ctx, input, offset, inLen);
+    if (ctx == NULL) {
+        return;
+    }
+
+    jint in_offset = offset;
+    jint in_size = inLen;
+    int result_code = 0;
+    if (in_size <= DIGEST_STACK_SIZE) { // allocation on the stack
+        jbyte buffer[DIGEST_STACK_SIZE];
+        (*env)->GetByteArrayRegion(env, input, offset, inLen, buffer);
+        result_code = EVP_DigestUpdate(ctx, buffer, inLen);
+    } else { // data chunk
+        jint remaining = in_size;
+        jint buf_size = (remaining >= DIGEST_CHUNK_SIZE) ? DIGEST_CHUNK_SIZE : remaining;
+        jbyte* buffer = malloc(buf_size);
+        if (buffer == NULL) {
+            KAE_ThrowOOMException(env, "malloc error");
+            return;
+        }
+        while (remaining > 0) {
+            jint chunk_size = (remaining >= buf_size) ? buf_size : remaining;
+            (*env)->GetByteArrayRegion(env, input, in_offset, chunk_size, buffer);
+            result_code = EVP_DigestUpdate(ctx, buffer, chunk_size);
+            if (!result_code) {
+                break;
+            }
+            in_offset += chunk_size;
+            remaining -= chunk_size;
+        }
+        free(buffer);
+    }
+    if (!result_code) {
+        KAE_ThrowFromOpenssl(env, "EVP_DigestUpdate failed", KAE_ThrowRuntimeException);
+        return;
+    }
+    KAE_TRACE("KAEDigest_nativeUpdate EVP_DigestUpdate success");
+    KAE_TRACE("KAEDigest_nativeUpdate: finished");
+}
+
+/*
+ * Class:     org_openeuler_security_openssl_KAEDigest
+ * Method:    nativeDigest
+ * Signature: (Ljava/lang/String;J[BII)I
+ */
+JNIEXPORT jint JNICALL
+Java_org_openeuler_security_openssl_KAEDigest_nativeDigest(JNIEnv *env, jclass cls,
+    jlong ctxAddress, jbyteArray output, jint offset, jint len)
+{
+    EVP_MD_CTX* ctx = (EVP_MD_CTX*) ctxAddress;
+    KAE_TRACE("KAEDigest_nativeDigest(ctx = %p, output = %p, offset = %d, len = %d", ctx, output, offset, len);
+    unsigned char* md = NULL;
+    unsigned int bytesWritten = 0;
+
+    if (ctx == NULL) {
+        return 0;
+    }
+
+    if (len <= 0 || len > DIGEST_LENGTH_THRESHOLD) {
+        KAE_ThrowRuntimeException(env, "len out of length");
+        return 0;
+    }
+    md = malloc(len);
+    if (md == NULL) {
+        KAE_ThrowOOMException(env, "malloc error");
+        return 0;
+    }
+
+    // EVP_DigestFinal_ex
+    int result_code = EVP_DigestFinal_ex(ctx, md, &bytesWritten);
+    if (result_code == 0) {
+        KAE_ThrowFromOpenssl(env, "EVP_DigestFinal_ex failed", KAE_ThrowRuntimeException);
+        goto cleanup;
+    }
+    KAE_TRACE("KAEDigest_nativeFinal EVP_DigestFinal_ex success, bytesWritten = %d", bytesWritten);
+
+    (*env)->SetByteArrayRegion(env, output, offset, bytesWritten, (jbyte*) md);
+
+    KAE_TRACE("KAEDigest_nativeFinal: finished");
+
+cleanup:
+    free(md);
+    return bytesWritten;
+}
+
+/*
+* Class:     org_openeuler_security_openssl_KAEDigest
+* Method:    nativeClone
+* Signature: (J)J
+*/
+JNIEXPORT jlong JNICALL
+Java_org_openeuler_security_openssl_KAEDigest_nativeClone(JNIEnv *env, jclass cls, jlong ctxAddress)
+{
+    EVP_MD_CTX* ctx = (EVP_MD_CTX*) ctxAddress;
+    KAE_TRACE("KAEDigest_nativeClone: ctx = %p", ctx);
+    if (ctx == NULL) {
+        return 0;
+    }
+
+    EVP_MD_CTX* ctxCopy = EVP_MD_CTX_create();
+    if (ctxCopy == NULL) {
+        KAE_ThrowOOMException(env, "create EVP_MD_CTX fail");
+        return 0;
+    }
+    KAE_TRACE("KAEDigest_nativeClone: create ctxCopy => %p", ctxCopy);
+
+    int result_code = EVP_MD_CTX_copy_ex(ctxCopy, ctx);
+    if (result_code == 0) {
+        KAE_ThrowFromOpenssl(env, "EVP_MD_CTX_copy_ex failed", KAE_ThrowRuntimeException);
+        goto err;
+    }
+    KAE_TRACE("KAEDigest_nativeClone EVP_MD_CTX_copy_ex(ctxCopy = %p, ctx = %p) success", ctxCopy, ctx);
+    KAE_TRACE("KAEDigest_nativeClone: finished");
+    return (jlong) ctxCopy;
+
+err:
+    EVP_MD_CTX_destroy(ctxCopy);
+    return 0;
+}
+
+/*
+ * Class:     org_openeuler_security_openssl_KAEDigest
+ * Method:    nativeFree
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL
+Java_org_openeuler_security_openssl_KAEDigest_nativeFree(JNIEnv *env, jclass cls, jlong ctxAddress)
+{
+    EVP_MD_CTX* ctx = (EVP_MD_CTX*) ctxAddress;
+    KAE_TRACE("KAEDigest_nativeFree(ctx = %p)", ctx);
+    if (ctx != NULL) {
+        EVP_MD_CTX_destroy(ctx);
+    }
+
+    KAE_TRACE("KAEDigest_nativeFree: finished");
+}
diff --git a/jdk/src/solaris/native/org/openeuler/security/openssl/kae_exception.c b/jdk/src/solaris/native/org/openeuler/security/openssl/kae_exception.c
new file mode 100644
index 00000000..b1a29334
--- /dev/null
+++ b/jdk/src/solaris/native/org/openeuler/security/openssl/kae_exception.c
@@ -0,0 +1,116 @@
+/*
+ * 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.
+ */
+ 
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include "kae_util.h"
+#include "kae_log.h"
+#include "kae_exception.h"
+
+void KAE_ThrowByName(JNIEnv* env, const char* name, const char* msg) {
+    jclass cls = (*env)->FindClass(env, name);
+    if (cls != 0) {
+        (*env)->ThrowNew(env, cls, msg);
+        (*env)->DeleteLocalRef(env, cls);
+    }
+}
+
+void KAE_ThrowOOMException(JNIEnv* env, const char* msg) {
+    KAE_ThrowByName(env, "java/lang/OutOfMemoryError", msg);
+}
+
+void KAE_ThrowNullPointerException(JNIEnv* env, const char* msg) {
+    KAE_ThrowByName(env, "java/lang/NullPointerException", msg);
+}
+
+void KAE_ThrowArrayIndexOutOfBoundsException(JNIEnv* env, const char* msg) {
+    KAE_ThrowByName(env, "java/lang/ArrayIndexOutOfBoundsException", msg);
+}
+
+void KAE_ThrowEvpException(JNIEnv* env, int reason, const char* msg, void (* defaultException)(JNIEnv*, const char*)) {
+    switch (reason) {
+        case EVP_R_UNSUPPORTED_ALGORITHM:
+            KAE_ThrowByName(env, "java/security/NoSuchAlgorithmException", msg);
+            break;
+        case EVP_R_MISSING_PARAMETERS:
+            KAE_ThrowByName(env, "java/security/InvalidKeyException", msg);
+            break;
+        case EVP_R_BAD_DECRYPT:
+            KAE_ThrowByName(env, "javax/crypto/BadPaddingException", msg);
+            break;
+        default:
+            defaultException(env, msg);
+            break;
+    }
+}
+
+void KAE_ThrowRuntimeException(JNIEnv* env, const char* msg) {
+    KAE_ThrowByName(env, "java/lang/RuntimeException", msg);
+}
+
+void KAE_ThrowBadPaddingException(JNIEnv* env, const char* msg) {
+    KAE_ThrowByName(env, "javax/crypto/BadPaddingException", msg);
+}
+
+void KAE_ThrowInvalidKeyException(JNIEnv* env, const char* msg) {
+    KAE_ThrowByName(env, "java/security/InvalidKeyException", msg);
+}
+
+void KAE_ThrowInvalidAlgorithmParameterException(JNIEnv* env, const char* msg) {
+    KAE_ThrowByName(env, "java/security/InvalidAlgorithmParameterException", msg);
+}
+
+void KAE_ThrowFromOpenssl(JNIEnv* env, const char* msg, void (* defaultException)(JNIEnv*, const char*)) {
+    const char* file = NULL;
+    const char* data = NULL;
+    int line = 0;
+    int flags = 0;
+    unsigned long err;
+    static const int ESTRING_SIZE = 256;
+
+    err = ERR_get_error_line_data(&file, &line, &data, &flags);
+    if (err == 0) {
+        KAE_ThrowRuntimeException(env, "Unknown OpenSSL error");
+        return;
+    }
+
+    if (!(*env)->ExceptionCheck(env)) {
+        char estring[ESTRING_SIZE];
+        ERR_error_string_n(err, estring, ESTRING_SIZE);
+        int lib = ERR_GET_LIB(err);
+        int reason = ERR_GET_REASON(err);
+        KAE_TRACE("OpenSSL error in %s: err=%lx, lib=%x, reason=%x, file=%s, line=%d, estring=%s, data=%s", msg, err,
+                  lib, reason, file, line, estring, (flags & ERR_TXT_STRING) ? data : "(no data)");
+
+        switch (lib) {
+            case ERR_LIB_EVP:
+                KAE_ThrowEvpException(env, reason, estring, defaultException);
+                break;
+            default:
+                defaultException(env, estring);
+                break;
+        }
+    }
+
+    ERR_clear_error();
+}
diff --git a/jdk/src/solaris/native/org/openeuler/security/openssl/kae_exception.h b/jdk/src/solaris/native/org/openeuler/security/openssl/kae_exception.h
new file mode 100644
index 00000000..f528ad4a
--- /dev/null
+++ b/jdk/src/solaris/native/org/openeuler/security/openssl/kae_exception.h
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+
+#ifndef KAE_EXCEPTION_H
+#define KAE_EXCEPTION_H
+
+#include <jni.h>
+
+/* Throw a Java exception by name */
+void KAE_ThrowByName(JNIEnv* env, const char* name, const char* msg);
+
+void KAE_ThrowOOMException(JNIEnv* env, const char* msg);
+
+void KAE_ThrowNullPointerException(JNIEnv* env, const char* msg);
+
+void KAE_ThrowArrayIndexOutOfBoundsException(JNIEnv* env, const char* msg);
+
+void KAE_ThrowFromOpenssl(JNIEnv* env, const char* msg, void (* defaultException)(JNIEnv*, const char*));
+
+void KAE_ThrowEvpException(JNIEnv* env, int reason, const char* msg, void (* defaultException)(JNIEnv*, const char*));
+
+void KAE_ThrowRuntimeException(JNIEnv* env, const char* msg);
+
+void KAE_ThrowBadPaddingException(JNIEnv* env, const char* msg);
+
+/* Throw InvalidKeyException */
+void KAE_ThrowInvalidKeyException(JNIEnv* env, const char* msg);
+
+/* Throw AlgorithmParameterException */
+void KAE_ThrowInvalidAlgorithmParameterException(JNIEnv* env, const char* msg);
+
+#endif
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
new file mode 100644
index 00000000..01848c0e
--- /dev/null
+++ b/jdk/src/solaris/native/org/openeuler/security/openssl/kae_keypairgenerator_rsa.c
@@ -0,0 +1,173 @@
+/*
+ * 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.
+ */
+#include <openssl/rsa.h>
+#include "kae_util.h"
+#include "kae_exception.h"
+#include "org_openeuler_security_openssl_KAERSAKeyPairGenerator.h"
+#define KAE_RSA_PARAM_SIZE 8
+#define SUCCESS 1
+#define FAILED -1
+
+
+// rsa param index
+typedef enum RSAParamIndex {
+    rsa_n = 0,
+    rsa_e = 1,
+    rsa_d = 2,
+    rsa_p = 3,
+    rsa_q = 4,
+    rsa_dmp1 = 5,
+    rsa_dmq1 = 6,
+    rsa_iqmp = 7
+} RSAParamIndex;
+
+// rsa param name array
+static const char* RSAParamNames[] = {"n", "e", "d", "p", "q", "dmp1", "dmq1", "iqmp"};
+
+// rsa get rsa param function list
+static const BIGNUM* (* GetRSAParamFunctionList[])(const RSA*) = {
+    RSA_get0_n,
+    RSA_get0_e,
+    RSA_get0_d,
+    RSA_get0_p,
+    RSA_get0_q,
+    RSA_get0_dmp1,
+    RSA_get0_dmq1,
+    RSA_get0_iqmp
+};
+
+/*
+ * New RSA and generate rsa key, follow the steps below
+ * step 1.New RSA
+ * step 2.Convert publicExponent to BIGNUM
+ * step 3.Generate rsa key, and all key information is stored in RSA
+ */
+static RSA* NewRSA(JNIEnv* env, jint keySize, jbyteArray publicExponent) {
+    // RSA_new
+    RSA* rsa = RSA_new();
+    if (rsa == NULL) {
+        KAE_ThrowFromOpenssl(env, "RSA_new", KAE_ThrowRuntimeException);
+        return NULL;
+    }
+
+    // convert publicExponent to BIGNUM
+    BIGNUM* exponent = KAE_GetBigNumFromByteArray(env, publicExponent);
+    if (exponent == NULL) {
+        return NULL;
+    }
+
+    // generate rsa key
+    int result_code = RSA_generate_key_ex(rsa, keySize, exponent, NULL);
+    KAE_ReleaseBigNumFromByteArray(exponent);
+    if (result_code <= 0) {
+        RSA_free(rsa);
+        KAE_ThrowFromOpenssl(env, "RSA_generate_key_ex", KAE_ThrowRuntimeException);
+        return NULL;
+    }
+    return rsa;
+}
+
+/*
+ * release RSA
+ */
+static void ReleaseRSA(RSA* rsa) {
+    if (rsa != NULL) {
+        RSA_free(rsa);
+    }
+}
+
+/*
+ * Set rsa key param, follow the steps below
+ * step 1. Get rsa param name
+ * step 2. Get rsa param value
+ * step 3. Convert paramValue (BIGNUM) to jbyteArray
+ * step 4. Set the rsa param to the param array
+ */
+static int SetRSAKeyParam(JNIEnv* env, RSA* rsa, jobjectArray params, RSAParamIndex rsaParamIndex) {
+    // get rsa param name
+    const char* rsaParamName = RSAParamNames[rsaParamIndex];
+
+    // get rsa param value
+    const BIGNUM* rsaParamValue = GetRSAParamFunctionList[rsaParamIndex](rsa);
+    if (rsaParamValue == NULL) {
+        return FAILED;
+    }
+
+    // Convert paramValue to jbyteArray
+    jbyteArray param = KAE_GetByteArrayFromBigNum(env, rsaParamValue, rsaParamName);
+    if (param == NULL) {
+        return FAILED;
+    }
+
+    // Set the rsa param to the param array
+    (*env)->SetObjectArrayElement(env, params, rsaParamIndex, param);
+    return SUCCESS;
+}
+
+/*
+ * New rsa key params, follow the steps below
+ * step 1. New rsa key param array
+ * step 2. Set rsa key param
+ */
+static jobjectArray NewRSAKeyParams(JNIEnv* env, RSA* rsa) {
+    // new param array
+    jclass byteArrayClass = (*env)->FindClass(env, "[B");
+    jobjectArray params = (*env)->NewObjectArray(env, KAE_RSA_PARAM_SIZE, byteArrayClass, NULL);
+    if (params == NULL) {
+        KAE_ThrowOOMException(env, "failed to allocate array");
+        return NULL;
+    }
+
+    // set rsa key param
+    for (RSAParamIndex paramIndex = rsa_n; paramIndex <= rsa_iqmp; paramIndex++) {
+        if (SetRSAKeyParam(env, rsa, params, paramIndex) == FAILED) {
+            return NULL;
+        }
+    }
+    return params;
+}
+
+/*
+ * Class:     org_openeuler_security_openssl_KAERSAKeyPairGenerator
+ * Method:    nativeGenerateKeyPair
+ * Signature: (I[B)[[B
+ */
+JNIEXPORT jobjectArray JNICALL Java_org_openeuler_security_openssl_KAERSAKeyPairGenerator_nativeGenerateKeyPair
+        (JNIEnv* env, jclass cls, jint keySize, jbyteArray publicExponent) {
+    if (publicExponent == NULL) {
+        return NULL;
+    }
+
+    // new RSA
+    RSA* rsa = NewRSA(env, keySize, publicExponent);
+    if (rsa == NULL) {
+        return NULL;
+    }
+
+    // new RSA Key Parameters
+    jobjectArray rsaParm = NewRSAKeyParams(env, rsa);
+
+    // release rsa
+    ReleaseRSA(rsa);
+    return rsaParm;
+}
diff --git a/jdk/src/solaris/native/org/openeuler/security/openssl/kae_log.h b/jdk/src/solaris/native/org/openeuler/security/openssl/kae_log.h
new file mode 100644
index 00000000..d8d9c7b3
--- /dev/null
+++ b/jdk/src/solaris/native/org/openeuler/security/openssl/kae_log.h
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+#ifndef KAE_LOG_H
+#define KAE_LOG_H
+
+#ifdef KAE_DEBUG
+#define KAE_TRACE(...) { fprintf(stdout, __VA_ARGS__); fprintf(stdout, "\n"); }
+#else
+#define KAE_TRACE(...)
+#endif
+
+#endif
diff --git a/jdk/src/solaris/native/org/openeuler/security/openssl/kae_mac.c b/jdk/src/solaris/native/org/openeuler/security/openssl/kae_mac.c
new file mode 100644
index 00000000..2df2a9cb
--- /dev/null
+++ b/jdk/src/solaris/native/org/openeuler/security/openssl/kae_mac.c
@@ -0,0 +1,201 @@
+/*
+ * 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.
+ */
+
+#include <jni.h>
+#include <openssl/hmac.h>
+#include "kae_exception.h"
+#include "kae_log.h"
+
+static const EVP_MD* EVPGetDigestByName(JNIEnv* env, const char* algo)
+{
+    static const EVP_MD* md5     = NULL;
+    static const EVP_MD* sha1    = NULL;
+    static const EVP_MD* sha224  = NULL;
+    static const EVP_MD* sha256  = NULL;
+    static const EVP_MD* sha384  = NULL;
+    static const EVP_MD* sha512  = NULL;
+
+    if (strcasecmp(algo, "md5") == 0) {
+        return md5 == NULL ? md5 = EVP_get_digestbyname(algo) : md5;
+    } else if (strcasecmp(algo, "sha1") == 0) {
+        return sha1 == NULL ? sha1 = EVP_get_digestbyname(algo) : sha1;
+    } else if (strcasecmp(algo, "sha224") == 0) {
+        return sha224 == NULL ? sha224 = EVP_get_digestbyname(algo) : sha224;
+    } else if (strcasecmp(algo, "sha256") == 0) {
+        return sha256 == NULL ? sha256 = EVP_get_digestbyname(algo) : sha256;
+    } else if (strcasecmp(algo, "sha384") == 0) {
+        return sha384 == NULL ? sha384 = EVP_get_digestbyname(algo) : sha384;
+    } else if (strcasecmp(algo, "sha512") == 0) {
+        return sha512 == NULL ? sha512 = EVP_get_digestbyname(algo) : sha512;
+    } else {
+        KAE_ThrowRuntimeException(env, "EVPGetDigestByName error");
+        return 0;
+    }
+}
+
+/*
+ * Class:     org_openeuler_security_openssl_KAEMac
+ * Method:    nativeInit
+ * Signature: ([BILjava/lang/String;)J
+ */
+JNIEXPORT jlong JNICALL Java_org_openeuler_security_openssl_KAEMac_nativeInit
+    (JNIEnv* env, jclass cls, jbyteArray key, jint key_len, jstring algoStr) {
+    if (key == NULL || algoStr == NULL) {
+        KAE_ThrowNullPointerException(env, "param key or algoStr is null");
+        return 0;
+    }
+    if (key_len <= 0) {
+        KAE_ThrowArrayIndexOutOfBoundsException(env, "key");
+        return 0;
+    }
+    HMAC_CTX* ctx = NULL;
+    jbyte* key_buffer = NULL;
+    const EVP_MD* md = NULL;
+
+    const char* algo = (*env)->GetStringUTFChars(env, algoStr, 0);
+    md  = EVPGetDigestByName(env, algo);
+    (*env)->ReleaseStringUTFChars(env, algoStr, algo);
+    if (md == NULL) {
+        KAE_ThrowRuntimeException(env, "algorithm unsupport");
+        return 0;
+    }
+
+    // get secret-key
+    key_buffer = malloc(key_len);
+    if (key_buffer == NULL) {
+        KAE_ThrowOOMException(env, "malloc failed");
+        return 0;
+    }
+    (*env)->GetByteArrayRegion(env, key, 0, key_len, key_buffer);
+
+    // create a hmac context
+    ctx = HMAC_CTX_new();
+    if (ctx == NULL) {
+        KAE_ThrowRuntimeException(env, "Hmac_CTX_new invoked failed");
+        goto err;
+    }
+
+    // init hmac context with sc_key and evp_md
+    int result_code = HMAC_Init_ex(ctx, key_buffer, key_len, md, NULL);
+    if (result_code == 0) {
+        KAE_ThrowRuntimeException(env, "Hmac_Init_ex invoked failed");
+        goto err;
+    }
+    free(key_buffer);
+    return (jlong) ctx;
+
+err:
+    free(key_buffer);
+    HMAC_CTX_free(ctx);
+    return 0;
+}
+
+/*
+ * Class:     org_openeuler_security_openssl_KAEMac
+ * Method:    nativeUpdate
+ * Signature: (J[BII)V
+ */
+JNIEXPORT void JNICALL Java_org_openeuler_security_openssl_KAEMac_nativeUpdate
+    (JNIEnv* env, jclass cls, jlong hmac_ctx, jbyteArray input, jint in_offset, jint in_len) {
+    KAE_TRACE("KAEMac_nativeUpdate(ctx = %p, input = %p, offset = %d, inLen = %d", hmac_ctx, input, in_offset, in_len);
+    HMAC_CTX* ctx = (HMAC_CTX*) hmac_ctx;
+    if (ctx == NULL || input == NULL) {
+        KAE_ThrowNullPointerException(env, "param ctx or input is null");
+        return;
+    }
+    int input_size = (*env)->GetArrayLength(env, input);
+    if ((in_offset < 0) || (in_len < 0) || (in_offset > input_size - in_len)) {
+        KAE_ThrowArrayIndexOutOfBoundsException(env, "input");
+        return;
+    }
+    // do nothing while in_len is 0
+    if (in_len == 0) {
+        return;
+    }
+
+    jbyte* buffer = malloc(in_len);
+    if (buffer == NULL) {
+        KAE_ThrowOOMException(env, "malloc failed");
+        return;
+    }
+    (*env)->GetByteArrayRegion(env, input, in_offset, in_len, buffer);
+    if (!HMAC_Update(ctx, (unsigned char*) buffer, in_len)) {
+        KAE_ThrowRuntimeException(env, "Hmac_Update invoked failed");
+    }
+    free(buffer);
+}
+
+/*
+ * Class:     org_openeuler_security_openssl_KAEMac
+ * Method:    nativeFinal
+ * Signature: (J[BII)I
+ */
+JNIEXPORT jint JNICALL Java_org_openeuler_security_openssl_KAEMac_nativeFinal
+    (JNIEnv* env, jclass cls, jlong hmac_ctx, jbyteArray output, jint out_offset, jint in_len) {
+    HMAC_CTX* ctx = (HMAC_CTX*) hmac_ctx;
+    if (ctx == NULL || output == NULL) {
+        KAE_ThrowNullPointerException(env, "param ctx or input is null");
+        return 0;
+    }
+    int output_size = (*env)->GetArrayLength(env, output);
+    if ((out_offset < 0) || (in_len < 0) || (out_offset > output_size - in_len)) {
+        KAE_ThrowArrayIndexOutOfBoundsException(env, "output");
+        return 0;
+    }
+
+    jbyte* temp_result = NULL;
+
+    temp_result = malloc(in_len);
+    if (temp_result == NULL) {
+        KAE_ThrowOOMException(env, "malloc failed");
+        return 0;
+    }
+    // do final
+    unsigned int bytesWritten = 0;
+    int result_code = HMAC_Final(ctx, (unsigned char*) temp_result, &bytesWritten);
+    if (result_code == 0) {
+        KAE_ThrowRuntimeException(env, "Hmac_Final invoked failed");
+        goto cleanup;
+    }
+
+    // write back to output_array
+    (*env)->SetByteArrayRegion(env, output, out_offset, bytesWritten, (jbyte*) temp_result);
+    KAE_TRACE("KAEMac_nativeFinal success, output_offset = %d, bytesWritten = %d", out_offset, bytesWritten);
+
+cleanup:
+    free(temp_result);
+    return bytesWritten;
+}
+
+/*
+ * Class:     org_openeuler_security_openssl_KAEMac
+ * Method:    nativeFree
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_org_openeuler_security_openssl_KAEMac_nativeFree
+    (JNIEnv* env, jclass cls, jlong hmac_ctx) {
+    HMAC_CTX* ctx = (HMAC_CTX*) hmac_ctx;
+    if (ctx != NULL) {
+        HMAC_CTX_free(ctx);
+    }
+}
diff --git a/jdk/src/solaris/native/org/openeuler/security/openssl/kae_provider.c b/jdk/src/solaris/native/org/openeuler/security/openssl/kae_provider.c
new file mode 100644
index 00000000..cfd2480e
--- /dev/null
+++ b/jdk/src/solaris/native/org/openeuler/security/openssl/kae_provider.c
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+#include <openssl/bio.h>
+#include <openssl/ssl.h>
+#include <openssl/engine.h>
+#include "kae_exception.h"
+#include "org_openeuler_security_openssl_KAEProvider.h"
+/*
+ * Class:     org_openeuler_security_openssl_WdProvider
+ * Method:    initOpenssl
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_org_openeuler_security_openssl_KAEProvider_initOpenssl
+        (JNIEnv *env, jclass cls) {
+    SSL_load_error_strings();
+    ERR_load_BIO_strings();
+    OpenSSL_add_all_algorithms();
+
+    // determine whether KAE is loaded successfully
+    ENGINE *e = ENGINE_by_id("kae");
+    if (e == NULL) {
+        KAE_ThrowRuntimeException(env, "kae engine not found");
+        return;
+    }
+    ENGINE_free(e);
+}
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
new file mode 100644
index 00000000..4e4c31ec
--- /dev/null
+++ b/jdk/src/solaris/native/org/openeuler/security/openssl/kae_util.c
@@ -0,0 +1,102 @@
+/*
+ * 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.
+ */
+
+#include <openssl/evp.h>
+#include "kae_util.h"
+#include "kae_exception.h"
+
+
+BIGNUM* KAE_GetBigNumFromByteArray(JNIEnv* env, jbyteArray byteArray) {
+    if (byteArray == NULL) {
+        KAE_ThrowNullPointerException(env, "KAE_GetBigNumFromByteArray byteArray is null");
+        return NULL;
+    }
+
+    jsize len = (*env)->GetArrayLength(env, byteArray);
+    if (len == 0) {
+        KAE_ThrowRuntimeException(env, "KAE_GetBigNumFromByteArray byteArray is empty");
+        return NULL;
+    }
+
+    BIGNUM* bn = BN_new();
+    if (bn == NULL) {
+        KAE_ThrowFromOpenssl(env, "BN_new", KAE_ThrowRuntimeException);
+        return NULL;
+    }
+
+    jbyte* bytes = (*env)->GetByteArrayElements(env, byteArray, NULL);
+    if (bytes == NULL) {
+        KAE_ThrowNullPointerException(env,"GetByteArrayElements failed");
+        goto error;
+    }
+    BIGNUM* result = BN_bin2bn((const unsigned char*) bytes, len, bn);
+    (*env)->ReleaseByteArrayElements(env, byteArray, bytes, 0);
+    if (result == NULL) {
+        KAE_ThrowFromOpenssl(env, "BN_bin2bn", KAE_ThrowRuntimeException);
+        goto error;
+    }
+    return bn;
+
+error:
+    BN_free(bn);
+    return NULL;
+}
+
+void KAE_ReleaseBigNumFromByteArray(BIGNUM* bn) {
+    if (bn != NULL) {
+        BN_free(bn);
+    }
+}
+
+jbyteArray KAE_GetByteArrayFromBigNum(JNIEnv* env, const BIGNUM* bn, const char* sourceName) {
+    if (bn == NULL) {
+        return NULL;
+    }
+    // bn size need plus 1,  for example 65535 , BN_num_bytes return 2
+    int bnSize = BN_num_bytes(bn);
+    if (bnSize <= 0) {
+        return NULL;
+    }
+    bnSize += 1;
+    jbyteArray javaBytes = (*env)->NewByteArray(env, bnSize);
+    if (javaBytes == NULL) {
+        KAE_ThrowOOMException(env, "new byte array failed");
+        return NULL;
+    }
+    jbyte* bytes = (*env)->GetByteArrayElements(env, javaBytes, NULL);
+    if (bytes == NULL) {
+        KAE_ThrowNullPointerException(env,"GetByteArrayElements failed");
+        return NULL;
+    }
+    unsigned char* tmp = (unsigned char*) bytes;
+    if (BN_bn2bin(bn, tmp + 1) <= 0) {
+        KAE_ThrowFromOpenssl(env, "BN_bn2bin", KAE_ThrowRuntimeException);
+        javaBytes = NULL;
+        goto cleanup;
+    }
+    (*env)->SetByteArrayRegion(env, javaBytes, 0, bnSize, bytes);
+
+cleanup:
+    (*env)->ReleaseByteArrayElements(env, javaBytes, bytes, 0);
+    return javaBytes;
+}
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
new file mode 100644
index 00000000..35715e1c
--- /dev/null
+++ b/jdk/src/solaris/native/org/openeuler/security/openssl/kae_util.h
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+
+#ifndef KAE_UTIL_H
+#define KAE_UTIL_H
+
+#include <openssl/bn.h>
+#include <jni.h>
+
+/* jbyteArray convert to BIGNUM */
+BIGNUM* KAE_GetBigNumFromByteArray(JNIEnv* env, jbyteArray byteArray);
+
+/* release BIGNUM allocat from */
+void KAE_ReleaseBigNumFromByteArray(BIGNUM* bn);
+
+/* BIGNUM convert to jbyteArray */
+jbyteArray KAE_GetByteArrayFromBigNum(JNIEnv* env, const BIGNUM* bn, const char* sourceName);
+
+#endif
diff --git a/jdk/test/java/net/URLPermission/policy.1 b/jdk/test/java/net/URLPermission/policy.1
index 5816cdbf..40bb7258 100644
--- a/jdk/test/java/net/URLPermission/policy.1
+++ b/jdk/test/java/net/URLPermission/policy.1
@@ -34,6 +34,7 @@ grant {
     //permission "java.io.FilePermission" "/tmp/-", "read,write";
     permission "java.lang.RuntimePermission" "modifyThread";
     permission "java.lang.RuntimePermission" "setFactory";
+    permission "java.util.PropertyPermission" "kae.disableKaeDispose", "read";
 };
 
 // Normal permissions that aren't granted when run under jtreg
diff --git a/jdk/test/java/net/URLPermission/policy.2 b/jdk/test/java/net/URLPermission/policy.2
index d1d774f4..21345c53 100644
--- a/jdk/test/java/net/URLPermission/policy.2
+++ b/jdk/test/java/net/URLPermission/policy.2
@@ -34,6 +34,7 @@ grant {
     //permission "java.io.FilePermission" "/tmp/-", "read,write";
     permission "java.lang.RuntimePermission" "modifyThread";
     permission "java.lang.RuntimePermission" "setFactory";
+    permission "java.util.PropertyPermission" "kae.disableKaeDispose", "read";
 };
 
 grant codeBase "file:${{java.ext.dirs}}/*" {
diff --git a/jdk/test/java/net/URLPermission/policy.3 b/jdk/test/java/net/URLPermission/policy.3
index 47f213fa..d86617f7 100644
--- a/jdk/test/java/net/URLPermission/policy.3
+++ b/jdk/test/java/net/URLPermission/policy.3
@@ -34,6 +34,7 @@ grant {
     //permission "java.io.FilePermission" "/tmp/-", "read,write";
     permission "java.lang.RuntimePermission" "modifyThread";
     permission "java.lang.RuntimePermission" "setFactory";
+    permission "java.util.PropertyPermission" "kae.disableKaeDispose", "read";
 };
 
 // Normal permissions that aren't granted when run under jtreg
diff --git a/jdk/test/micro/org/openeuler/bench/security/openssl/AESBenchmark.java b/jdk/test/micro/org/openeuler/bench/security/openssl/AESBenchmark.java
new file mode 100644
index 00000000..0034b67c
--- /dev/null
+++ b/jdk/test/micro/org/openeuler/bench/security/openssl/AESBenchmark.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 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.
+ */
+package org.openeuler.bench.security.openssl;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Param;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.Warmup;
+
+import java.security.InvalidKeyException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.NoSuchAlgorithmException;
+import java.security.Provider;
+import java.security.Security;
+import java.util.concurrent.TimeUnit;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.spec.SecretKeySpec;
+
+@Warmup(iterations = 10, time = 2, timeUnit = TimeUnit.SECONDS)
+public class AESBenchmark extends BenchmarkBase {
+
+    @Param({"AES/ECB/PKCS5Padding", "AES/ECB/NoPadding", "AES/CBC/NoPadding", "AES/CBC/PKCS5Padding", "AES/CTR/NoPadding"})
+    private String algorithm;
+
+    @Param({"128", "192", "256"})
+    private int keyLength;
+
+    @Param({"" + 1024, "" + 10 * 1024, "" + 100 * 1024, "" + 1024 * 1024})
+    private int dataSize;
+
+    private byte[][] encryptedData;
+    private Cipher encryptCipher;
+    private Cipher decryptCipher;
+
+    @Setup
+    public void setup() throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
+            InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
+        setupProvider();
+
+        byte[] keystring = fillSecureRandom(new byte[keyLength / 8]);
+        SecretKeySpec ks = new SecretKeySpec(keystring, "AES");
+
+        encryptCipher = (prov == null) ? Cipher.getInstance(algorithm) : Cipher.getInstance(algorithm, prov);
+        encryptCipher.init(Cipher.ENCRYPT_MODE, ks);
+        decryptCipher = (prov == null) ? Cipher.getInstance(algorithm) : Cipher.getInstance(algorithm, prov);
+        decryptCipher.init(Cipher.DECRYPT_MODE, ks, encryptCipher.getParameters());
+
+        data = fillRandom(new byte[SET_SIZE][dataSize]);
+        encryptedData = fillEncrypted(data, encryptCipher);
+    }
+
+    @Benchmark
+    public byte[] encrypt() throws IllegalBlockSizeException, BadPaddingException {
+        byte[] d = data[index];
+        index = (index + 1) % SET_SIZE;
+        return encryptCipher.doFinal(d);
+    }
+
+    @Benchmark
+    @Fork(jvmArgsAppend = {"-Dkae.disableKaeDispose=true"})
+    public byte[] encryptDispose() throws IllegalBlockSizeException, BadPaddingException {
+        byte[] d = data[index];
+        index = (index + 1) % SET_SIZE;
+        return encryptCipher.doFinal(d);
+    }
+
+    @Benchmark
+    public byte[] decrypt() throws IllegalBlockSizeException, BadPaddingException {
+        byte[] e = encryptedData[index];
+        index = (index + 1) % SET_SIZE;
+        return decryptCipher.doFinal(e);
+    }
+
+    @Benchmark
+    @Fork(jvmArgsAppend = {"-Dkae.disableKaeDispose=true"})
+    public byte[] decryptDispose() throws IllegalBlockSizeException, BadPaddingException {
+        byte[] e = encryptedData[index];
+        index = (index + 1) % SET_SIZE;
+        return decryptCipher.doFinal(e);
+    }
+}
+
diff --git a/jdk/test/micro/org/openeuler/bench/security/openssl/BenchmarkBase.java b/jdk/test/micro/org/openeuler/bench/security/openssl/BenchmarkBase.java
new file mode 100644
index 00000000..41c56e49
--- /dev/null
+++ b/jdk/test/micro/org/openeuler/bench/security/openssl/BenchmarkBase.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * 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.
+ */
+package org.openeuler.bench.security.openssl;
+
+import org.openeuler.security.openssl.KAEProvider;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Measurement;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Param;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.Threads;
+import org.openjdk.jmh.annotations.Warmup;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import java.security.Provider;
+import java.security.SecureRandom;
+import java.security.Security;
+import java.util.Random;
+import java.util.concurrent.TimeUnit;
+
+@BenchmarkMode(Mode.AverageTime)
+@OutputTimeUnit(TimeUnit.MICROSECONDS)
+@Warmup(iterations = 2, time = 2, timeUnit = TimeUnit.SECONDS)
+@Measurement(iterations = 3, time = 2, timeUnit = TimeUnit.SECONDS)
+@Fork(jvmArgsPrepend = {"-Xms100G", "-Xmx100G", "-XX:+AlwaysPreTouch"}, value = 1)
+@Threads(1)
+@State(Scope.Thread)
+public class BenchmarkBase {
+    public static final int SET_SIZE = 128;
+
+    byte[][] data;
+    int index = 0;
+
+    @Param({"", "KAEProvider"})
+    private String provider;
+
+    public Provider prov = null;
+
+    @Setup
+    public void setupProvider() {
+        Security.addProvider(new KAEProvider());
+        if (provider != null && !provider.isEmpty()) {
+            prov = Security.getProvider(provider);
+            if (prov == null) {
+                throw new RuntimeException("Can't find provider \"" + provider + "\"");
+            }
+        }
+    }
+
+    public static byte[][] fillRandom(byte[][] data) {
+        Random rnd = new Random();
+        for (byte[] d : data) {
+            rnd.nextBytes(d);
+        }
+        return data;
+    }
+
+    public static byte[] fillSecureRandom(byte[] data) {
+        SecureRandom rnd = new SecureRandom();
+        rnd.nextBytes(data);
+        return data;
+    }
+
+    public static byte[][] fillEncrypted(byte[][] data, Cipher encryptCipher)
+        throws IllegalBlockSizeException, BadPaddingException {
+        byte[][] encryptedData = new byte[data.length][];
+        for (int i = 0; i < encryptedData.length; i++) {
+            encryptedData[i] = encryptCipher.doFinal(data[i]);
+        }
+        return encryptedData;
+    }
+
+}
diff --git a/jdk/test/micro/org/openeuler/bench/security/openssl/DigestBenchmark.java b/jdk/test/micro/org/openeuler/bench/security/openssl/DigestBenchmark.java
new file mode 100644
index 00000000..96d2a24f
--- /dev/null
+++ b/jdk/test/micro/org/openeuler/bench/security/openssl/DigestBenchmark.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 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.
+ */
+package org.openeuler.bench.security.openssl;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Param;
+import org.openjdk.jmh.annotations.Setup;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.Provider;
+import java.security.Security;
+import java.util.concurrent.TimeUnit;
+
+public class DigestBenchmark extends BenchmarkBase {
+
+    @Param({"MD5", "SHA-256", "SHA-384"})
+    private String algorithm;
+
+    @Param({"" + 1024, "" + 10 * 1024, "" + 100 * 1024, "" + 1024 * 1024})
+    int dataSize;
+
+    MessageDigest md;
+
+    @Setup
+    public void setup() throws NoSuchAlgorithmException {
+        setupProvider();
+        data = fillRandom(new byte[SET_SIZE][dataSize]);
+        md = (prov == null) ? MessageDigest.getInstance(algorithm) : MessageDigest.getInstance(algorithm, prov);
+    }
+
+    @Benchmark
+    public byte[] digest() {
+        byte[] d = data[index];
+        index = (index + 1) % SET_SIZE;
+        return md.digest(d);
+    }
+
+    @Benchmark
+    @Fork(jvmArgsAppend = {"-Dkae.disableKaeDispose=true"})
+    public byte[] digestDispose() {
+        byte[] d = data[index];
+        index = (index + 1) % SET_SIZE;
+        return md.digest(d);
+    }
+}
+
diff --git a/jdk/test/micro/org/openeuler/bench/security/openssl/HMacBenchmark.java b/jdk/test/micro/org/openeuler/bench/security/openssl/HMacBenchmark.java
new file mode 100644
index 00000000..584484f3
--- /dev/null
+++ b/jdk/test/micro/org/openeuler/bench/security/openssl/HMacBenchmark.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 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.
+ */
+package org.openeuler.bench.security.openssl;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Param;
+import org.openjdk.jmh.annotations.Setup;
+
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.Provider;
+import java.security.Security;
+import java.util.concurrent.TimeUnit;
+
+import javax.crypto.KeyGenerator;
+import javax.crypto.Mac;
+
+public class HMacBenchmark extends BenchmarkBase {
+
+    @Param({"HmacMD5", "HmacSHA1", "HmacSHA224", "HmacSHA256", "HmacSHA384", "HmacSHA512"})
+    private String algorithm;
+
+    @Param({"" + 1024, "" + 10 * 1024, "" + 100 * 1024, "" + 1024 * 1024})
+    private int dataSize;
+
+    private Mac mac;
+
+    @Setup
+    public void setup() throws NoSuchAlgorithmException, InvalidKeyException {
+        setupProvider();
+        mac = (prov == null) ? Mac.getInstance(algorithm) : Mac.getInstance(algorithm, prov);
+        mac.init(KeyGenerator.getInstance(algorithm).generateKey());
+        data = fillRandom(new byte[SET_SIZE][dataSize]);
+    }
+
+    @Benchmark
+    public byte[] mac() {
+        byte[] d = data[index];
+        index = (index + 1) % SET_SIZE;
+        return mac.doFinal(d);
+    }
+
+    @Benchmark
+    @Fork(jvmArgsAppend = {"-Dkae.disableKaeDispose=true"})
+    public byte[] macDispose() {
+        byte[] d = data[index];
+        index = (index + 1) % SET_SIZE;
+        return mac.doFinal(d);
+    }
+}
+
diff --git a/jdk/test/micro/org/openeuler/bench/security/openssl/RSACipherBenchmark.java b/jdk/test/micro/org/openeuler/bench/security/openssl/RSACipherBenchmark.java
new file mode 100644
index 00000000..2a5eb9c7
--- /dev/null
+++ b/jdk/test/micro/org/openeuler/bench/security/openssl/RSACipherBenchmark.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 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.
+ */
+
+package org.openeuler.bench.security.openssl;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.Param;
+import org.openjdk.jmh.annotations.Setup;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import java.security.InvalidKeyException;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.NoSuchAlgorithmException;
+
+public class RSACipherBenchmark extends BenchmarkBase {
+    @Param({"RSA/ECB/NoPadding", "RSA/ECB/PKCS1Padding", "RSA/ECB/OAEPPadding"})
+    private String algorithm;
+
+    @Param({"512", "1024", "2048", "3072", "4096"})
+    private int keyLength;
+
+    @Param({"true", "false"})
+    private boolean encryptPublicKey;
+
+    private byte[][] data;
+    private byte[][] encryptedData;
+
+    private Cipher encryptCipher;
+    private Cipher decryptCipher;
+    private int index = 0;
+
+    private int getMaxDataSize(int keyLength, String algorithm) {
+        int dataSize = keyLength / 8;
+        if ("RSA/ECB/PKCS1Padding".equals(algorithm)) {
+            return dataSize - 11;
+        }
+
+        if ("RSA/ECB/OAEPPadding".equals(algorithm)) {
+            // SHA-1 digestLen is 20
+            int digestLen = 20;
+            return dataSize - 2 - 2 * digestLen;
+        }
+        return dataSize;
+    }
+
+    @Setup()
+    public void setup() throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
+        setupProvider();
+
+        int dataSize = getMaxDataSize(keyLength, algorithm);
+        data = fillRandom(new byte[SET_SIZE][dataSize - 1]);
+
+        KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
+        kpg.initialize(keyLength);
+        KeyPair keyPair = kpg.generateKeyPair();
+
+        encryptCipher = (prov == null) ? Cipher.getInstance(algorithm) : Cipher.getInstance(algorithm, prov);
+        decryptCipher = (prov == null) ? Cipher.getInstance(algorithm) : Cipher.getInstance(algorithm, prov);
+        if (encryptPublicKey || "RSA/ECB/OAEPPadding".equals(algorithm)) {
+            encryptCipher.init(Cipher.ENCRYPT_MODE, keyPair.getPublic());
+            decryptCipher.init(Cipher.DECRYPT_MODE, keyPair.getPrivate());
+        } else {
+            encryptCipher.init(Cipher.ENCRYPT_MODE, keyPair.getPrivate());
+            decryptCipher.init(Cipher.DECRYPT_MODE, keyPair.getPublic());
+        }
+        encryptedData = fillEncrypted(data, encryptCipher);
+    }
+
+    @Benchmark
+    public byte[] encrypt() throws BadPaddingException, IllegalBlockSizeException {
+        byte[] dataBytes = data[index];
+        index = (index + 1) % data.length;
+        return encryptCipher.doFinal(dataBytes);
+    }
+
+    @Benchmark
+    public byte[] decrypt() throws BadPaddingException, IllegalBlockSizeException {
+        byte[] e = encryptedData[index];
+        index = (index + 1) % encryptedData.length;
+        return decryptCipher.doFinal(e);
+    }
+}
diff --git a/jdk/test/micro/org/openeuler/bench/security/openssl/RSAKeyPairGeneratorBenchmark.java b/jdk/test/micro/org/openeuler/bench/security/openssl/RSAKeyPairGeneratorBenchmark.java
new file mode 100644
index 00000000..65bb8bf8
--- /dev/null
+++ b/jdk/test/micro/org/openeuler/bench/security/openssl/RSAKeyPairGeneratorBenchmark.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * 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.
+ */
+
+package org.openeuler.bench.security.openssl;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.Param;
+import org.openjdk.jmh.annotations.Setup;
+import java.util.concurrent.TimeUnit;
+import org.openjdk.jmh.annotations.Warmup;
+
+import java.security.KeyPairGenerator;
+
+@Warmup(iterations = 10, time = 2, timeUnit = TimeUnit.SECONDS)
+public class RSAKeyPairGeneratorBenchmark extends BenchmarkBase {
+    @Param({"RSA"})
+    private String algorithm;
+
+    @Param({"512", "1024", "2048", "3072", "4096"})
+    private int keySize;
+
+    private KeyPairGenerator keyPairGenerator;
+
+    @Setup
+    public void setUp() throws Exception {
+        setupProvider();
+        keyPairGenerator = createKeyPairGenerator();
+    }
+
+    @Benchmark
+    public void generateKeyPair() throws Exception {
+        keyPairGenerator.initialize(keySize);
+        keyPairGenerator.generateKeyPair();
+    }
+
+    private KeyPairGenerator createKeyPairGenerator() throws Exception {
+        if (prov != null) {
+            return KeyPairGenerator.getInstance(algorithm, prov);
+        }
+        return KeyPairGenerator.getInstance(algorithm);
+    }
+}
diff --git a/jdk/test/sun/security/krb5/auto/BasicProc.java b/jdk/test/sun/security/krb5/auto/BasicProc.java
index 50f65eab..a388c76a 100644
--- a/jdk/test/sun/security/krb5/auto/BasicProc.java
+++ b/jdk/test/sun/security/krb5/auto/BasicProc.java
@@ -297,7 +297,9 @@ public class BasicProc {
         Proc p = Proc.create("BasicProc")
                 .prop("java.security.manager", "")
                 .prop("sun.net.spi.nameservice.provider.1", "ns,mock")
-                .perm(new javax.security.auth.AuthPermission("doAs"));
+                .perm(new javax.security.auth.AuthPermission("doAs"))
+                .perm(new java.util.PropertyPermission(
+                            "kae.disableKaeDispose", "read"));
         if (lib != null) {
             p.env("KRB5_CONFIG", CONF)
                     .env("KRB5_TRACE", "/dev/stderr")
-- 
2.19.0

