diff --git a/java-1.8.0-openjdk.spec b/java-1.8.0-openjdk.spec index bf1c06e..7b79555 100644 --- a/java-1.8.0-openjdk.spec +++ b/java-1.8.0-openjdk.spec @@ -587,6 +587,9 @@ exit 0 %{_jvmdir}/%{jredir -- %{?1}}/lib/%{archinstall}/libnet.so %{_jvmdir}/%{jredir -- %{?1}}/lib/%{archinstall}/libnio.so %{_jvmdir}/%{jredir -- %{?1}}/lib/%{archinstall}/libnpt.so +%ifarch %{aarch64} +%{_jvmdir}/%{jredir -- %{?1}}/lib/%{archinstall}/libj2kae.so +%endif %ifarch %{sa_arches} %{_jvmdir}/%{jredir -- %{?1}}/lib/%{archinstall}/libsaproc.so %endif @@ -628,6 +631,9 @@ exit 0 %{_jvmdir}/%{jredir -- %{?1}}/lib/ext/sunjce_provider.jar %{_jvmdir}/%{jredir -- %{?1}}/lib/ext/sunpkcs11.jar %{_jvmdir}/%{jredir -- %{?1}}/lib/ext/zipfs.jar +%ifarch %{aarch64} +%{_jvmdir}/%{jredir -- %{?1}}/lib/ext/kae_openssl.jar +%endif %ifarch %{jfr_arches} %{_jvmdir}/%{jredir -- %{?1}}/lib/jfr.jar %{_jvmdir}/%{jredir -- %{?1}}/lib/jfr/default.jfc @@ -915,7 +921,7 @@ Provides: java-%{javaver}-%{origin}-accessibility%{?1} = %{epoch}:%{version}-%{r Name: java-%{javaver}-%{origin} Version: %{javaver}.%{updatever}.%{buildver} -Release: 5 +Release: 6 # java-1.5.0-ibm from jpackage.org set Epoch to 1 for unknown reasons # and this change was brought into RHEL-4. java-1.5.0-ibm packages # also included the epoch in their virtual provides. This created a @@ -1072,6 +1078,9 @@ Patch148: 8237894.patch Patch149: Remove-the-parentheses-around-company-name.patch Patch150: 8240353.patch +# 8u292 +Patch151: kae-phase1.patch + ############################################# # # Upstreamable patches @@ -1154,6 +1163,7 @@ BuildRequires: pkgconfig BuildRequires: xorg-x11-proto-devel BuildRequires: zip BuildRequires: unzip +BuildRequires: openssl-devel BuildRequires: java-1.8.0-openjdk-devel @@ -1495,6 +1505,7 @@ pushd %{top_level_dir_name} %patch148 -p1 %patch149 -p1 %patch150 -p1 +%patch151 -p1 popd @@ -2111,6 +2122,9 @@ require "copy_jdk_configs.lua" %endif %changelog +* Wed Mar 17 2021 noah - 1:1.8.0.292-b01.1 +- add kae-phase1.patch + * Fri Feb 5 2021 noah - 1:1.8.0.282-b08.5 - delete some file header diff --git a/kae-phase1.patch b/kae-phase1.patch new file mode 100644 index 0000000..bc0f6ef --- /dev/null +++ b/kae-phase1.patch @@ -0,0 +1,5496 @@ +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 implements Comparable { ++ ++ private static ReferenceQueue refQueue = new ReferenceQueue<>(); ++ private static Set 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 ++ implements Comparable { ++ ++ private static ReferenceQueue referenceQueue = new ReferenceQueue<>(); ++ private static Set 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 ++ implements Comparable { ++ ++ private static ReferenceQueue referenceQueue = new ReferenceQueue<>(); ++ private static Set 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. ++ *

++ * 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/OAEPwithandMGF1Padding" (or "RSA/ECB/OAEPPadding") for ++ * PKCS#1 v2.2 padding. ++ * . "RSA/ECB/NoPadding" for rsa RSA. ++ *

++ * 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. ++ *

++ * 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 ++ implements Comparable { ++ private static ReferenceQueue referenceQueue = new ReferenceQueue<>(); ++ private static Set 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 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 supportPaddings) { ++ this.id = id; ++ this.name = name; ++ this.supportPaddings = supportPaddings; ++ } ++ ++ public Set 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 aliasNames; ++ ++ public String getDigestName() { ++ return digestName; ++ } ++ ++ public String getKaeDigestName() { ++ return kaeDigestName; ++ } ++ ++ public int getDigestLen() { ++ return digestLen; ++ } ++ ++ public Set getAliasNames() { ++ return aliasNames; ++ } ++ ++ MessageDigestType(String digestName, String kaeDigestName, int digestLen, Set 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 DIGEST_ALGORITHM_NAME_MAP = new HashMap<>(); ++ private static final Map 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 ++#include ++#include ++#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 ++#include ++#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 ++#include ++#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 ++#include ++#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 ++ ++/* 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 ++#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 ++#include ++#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 ++#include ++#include ++#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 ++#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 ++#include ++ ++/* 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 +