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