5492 lines
206 KiB
Diff
5492 lines
206 KiB
Diff
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", "/dev/stderr")
|
|
--
|
|
2.19.0
|
|
|