11276 lines
435 KiB
Diff
11276 lines
435 KiB
Diff
From a194df3ac3f63326436378e54b2d3aa64f429a3f Mon Sep 17 00:00:00 2001
|
|
From: miaomiao <miaomiao@miaomiaos-MacBook-Pro.local>
|
|
Date: Tue, 20 Sep 2022 21:32:41 +0800
|
|
Subject: [PATCH] test2
|
|
|
|
---
|
|
make/ZipSecurity.gmk | 1 +
|
|
make/autoconf/configure.ac | 1 +
|
|
make/autoconf/jdk-options.m4 | 23 +
|
|
make/autoconf/spec.gmk.in | 1 +
|
|
make/common/Modules.gmk | 13 +
|
|
make/copy/Copy-jdk.crypto.kaeprovider.gmk | 46 +
|
|
make/lib/Lib-jdk.crypto.kaeprovider.gmk | 45 +
|
|
make/nb_native/nbproject/configurations.xml | 104 +++
|
|
src/java.base/share/classes/module-info.java | 10 +-
|
|
.../share/lib/security/default.policy | 5 +
|
|
.../share/classes/module-info.java | 6 +
|
|
.../linux/classes/module-info.java | 39 +
|
|
.../security/openssl/KAEAESCipher.java | 365 ++++++++
|
|
.../security/openssl/KAEDHKeyAgreement.java | 289 +++++++
|
|
.../openssl/KAEDHKeyPairGenerator.java | 166 ++++
|
|
.../openeuler/security/openssl/KAEDigest.java | 264 ++++++
|
|
.../security/openssl/KAEECDHKeyAgreement.java | 146 ++++
|
|
.../openssl/KAEECKeyPairGenerator.java | 154 ++++
|
|
.../openeuler/security/openssl/KAEHMac.java | 228 +++++
|
|
.../security/openssl/KAEProvider.java | 338 ++++++++
|
|
.../security/openssl/KAERSACipher.java | 796 ++++++++++++++++++
|
|
.../openssl/KAERSAKeyPairGenerator.java | 164 ++++
|
|
.../security/openssl/KAERSAPSSSignature.java | 713 ++++++++++++++++
|
|
.../security/openssl/KAERSAPaddingType.java | 83 ++
|
|
.../security/openssl/KAERSASignature.java | 365 ++++++++
|
|
.../openssl/KAERSASignatureNative.java | 46 +
|
|
.../security/openssl/KAESM4Cipher.java | 188 +++++
|
|
.../openssl/KAESymmetricCipherBase.java | 615 ++++++++++++++
|
|
.../openeuler/security/openssl/KAEUtils.java | 220 +++++
|
|
.../linux/conf/security/kaeprovider.conf | 19 +
|
|
.../security/openssl/kae_cipher_rsa.c | 467 ++++++++++
|
|
.../openeuler/security/openssl/kae_digest.c | 235 ++++++
|
|
.../security/openssl/kae_exception.c | 134 +++
|
|
.../security/openssl/kae_exception.h | 57 ++
|
|
.../org/openeuler/security/openssl/kae_hmac.c | 203 +++++
|
|
.../security/openssl/kae_keyagreement_dh.c | 139 +++
|
|
.../security/openssl/kae_keyagreement_ecdh.c | 115 +++
|
|
.../openssl/kae_keypairgenerator_dh.c | 132 +++
|
|
.../openssl/kae_keypairgenerator_ec.c | 508 +++++++++++
|
|
.../openssl/kae_keypairgenerator_rsa.c | 167 ++++
|
|
.../org/openeuler/security/openssl/kae_log.h | 33 +
|
|
.../openeuler/security/openssl/kae_provider.c | 57 ++
|
|
.../security/openssl/kae_signature_rsa.c | 363 ++++++++
|
|
.../security/openssl/kae_symmetric_cipher.c | 409 +++++++++
|
|
.../org/openeuler/security/openssl/kae_util.c | 111 +++
|
|
.../org/openeuler/security/openssl/kae_util.h | 47 ++
|
|
test/jdk/TEST.groups | 3 +
|
|
.../KeyAgreement/KeyAgreementTest.java | 12 +-
|
|
.../Signature/SignatureGetInstance.java | 5 +-
|
|
.../openeuler/security/openssl/DHTest.java | 130 +++
|
|
.../openeuler/security/openssl/ECDHTest.java | 117 +++
|
|
.../openeuler/security/openssl/SM3Test.java | 54 ++
|
|
.../openeuler/security/openssl/SM4Test.java | 95 +++
|
|
.../jca/PreferredProviderNegativeTest.java | 2 +
|
|
.../jdk/sun/security/krb5/auto/BasicProc.java | 4 +-
|
|
test/jdk/sun/security/pkcs11/Secmod/policy | 1 +
|
|
test/jdk/sun/security/pkcs11/policy | 1 +
|
|
.../ssl/CipherSuite/DisabledCurve.java | 4 +
|
|
.../SSLSocketImpl/NotifyHandshakeTest.policy | 2 +
|
|
.../bench/security/openssl/AESBenchmark.java | 108 +++
|
|
.../security/openssl/AESGCMBenchmark.java | 133 +++
|
|
.../bench/security/openssl/BenchmarkBase.java | 106 +++
|
|
.../openssl/DHKeyAgreementBenchMark.java | 139 +++
|
|
.../openssl/DHKeyPairGeneratorBenchmark.java | 64 ++
|
|
.../security/openssl/DigestBenchmark.java | 69 ++
|
|
.../openssl/ECKeyAgreementBenchmark.java | 88 ++
|
|
.../openssl/ECKeyPairGeneratorBenchmark.java | 63 ++
|
|
.../bench/security/openssl/HMacBenchmark.java | 73 ++
|
|
.../security/openssl/RSACipherBenchmark.java | 107 +++
|
|
.../openssl/RSAKeyPairGeneratorBenchmark.java | 64 ++
|
|
.../openssl/RSAPSSSignatureBenchmark.java | 118 +++
|
|
.../openssl/RSASignatureBenchmark.java | 90 ++
|
|
.../bench/security/openssl/SM3Benchmark.java | 98 +++
|
|
.../bench/security/openssl/SM4Benchmark.java | 157 ++++
|
|
74 files changed, 10533 insertions(+), 4 deletions(-)
|
|
create mode 100644 make/copy/Copy-jdk.crypto.kaeprovider.gmk
|
|
create mode 100644 make/lib/Lib-jdk.crypto.kaeprovider.gmk
|
|
create mode 100644 src/jdk.crypto.kaeprovider/linux/classes/module-info.java
|
|
create mode 100644 src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEAESCipher.java
|
|
create mode 100644 src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEDHKeyAgreement.java
|
|
create mode 100644 src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEDHKeyPairGenerator.java
|
|
create mode 100644 src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEDigest.java
|
|
create mode 100644 src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEECDHKeyAgreement.java
|
|
create mode 100644 src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEECKeyPairGenerator.java
|
|
create mode 100644 src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEHMac.java
|
|
create mode 100644 src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEProvider.java
|
|
create mode 100644 src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAERSACipher.java
|
|
create mode 100644 src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAERSAKeyPairGenerator.java
|
|
create mode 100644 src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAERSAPSSSignature.java
|
|
create mode 100644 src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAERSAPaddingType.java
|
|
create mode 100644 src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAERSASignature.java
|
|
create mode 100644 src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAERSASignatureNative.java
|
|
create mode 100644 src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAESM4Cipher.java
|
|
create mode 100644 src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAESymmetricCipherBase.java
|
|
create mode 100644 src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEUtils.java
|
|
create mode 100644 src/jdk.crypto.kaeprovider/linux/conf/security/kaeprovider.conf
|
|
create mode 100644 src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_cipher_rsa.c
|
|
create mode 100644 src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_digest.c
|
|
create mode 100644 src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_exception.c
|
|
create mode 100644 src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_exception.h
|
|
create mode 100644 src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_hmac.c
|
|
create mode 100644 src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_keyagreement_dh.c
|
|
create mode 100644 src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_keyagreement_ecdh.c
|
|
create mode 100644 src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_keypairgenerator_dh.c
|
|
create mode 100644 src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_keypairgenerator_ec.c
|
|
create mode 100644 src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_keypairgenerator_rsa.c
|
|
create mode 100644 src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_log.h
|
|
create mode 100644 src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_provider.c
|
|
create mode 100644 src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_signature_rsa.c
|
|
create mode 100644 src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_symmetric_cipher.c
|
|
create mode 100644 src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_util.c
|
|
create mode 100644 src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_util.h
|
|
create mode 100644 test/jdk/org/openeuler/security/openssl/DHTest.java
|
|
create mode 100644 test/jdk/org/openeuler/security/openssl/ECDHTest.java
|
|
create mode 100644 test/jdk/org/openeuler/security/openssl/SM3Test.java
|
|
create mode 100644 test/jdk/org/openeuler/security/openssl/SM4Test.java
|
|
create mode 100644 test/micro/org/openeuler/bench/security/openssl/AESBenchmark.java
|
|
create mode 100644 test/micro/org/openeuler/bench/security/openssl/AESGCMBenchmark.java
|
|
create mode 100644 test/micro/org/openeuler/bench/security/openssl/BenchmarkBase.java
|
|
create mode 100644 test/micro/org/openeuler/bench/security/openssl/DHKeyAgreementBenchMark.java
|
|
create mode 100644 test/micro/org/openeuler/bench/security/openssl/DHKeyPairGeneratorBenchmark.java
|
|
create mode 100644 test/micro/org/openeuler/bench/security/openssl/DigestBenchmark.java
|
|
create mode 100644 test/micro/org/openeuler/bench/security/openssl/ECKeyAgreementBenchmark.java
|
|
create mode 100644 test/micro/org/openeuler/bench/security/openssl/ECKeyPairGeneratorBenchmark.java
|
|
create mode 100644 test/micro/org/openeuler/bench/security/openssl/HMacBenchmark.java
|
|
create mode 100644 test/micro/org/openeuler/bench/security/openssl/RSACipherBenchmark.java
|
|
create mode 100644 test/micro/org/openeuler/bench/security/openssl/RSAKeyPairGeneratorBenchmark.java
|
|
create mode 100644 test/micro/org/openeuler/bench/security/openssl/RSAPSSSignatureBenchmark.java
|
|
create mode 100644 test/micro/org/openeuler/bench/security/openssl/RSASignatureBenchmark.java
|
|
create mode 100644 test/micro/org/openeuler/bench/security/openssl/SM3Benchmark.java
|
|
create mode 100644 test/micro/org/openeuler/bench/security/openssl/SM4Benchmark.java
|
|
|
|
diff --git a/make/ZipSecurity.gmk b/make/ZipSecurity.gmk
|
|
index ba5664122..382ca4218 100644
|
|
--- a/make/ZipSecurity.gmk
|
|
+++ b/make/ZipSecurity.gmk
|
|
@@ -42,6 +42,7 @@ $(eval $(call SetupZipArchive,BUILD_SEC_BIN_ZIP, \
|
|
modules/java.base/sun/security/internal/spec \
|
|
modules/java.base/com/sun/crypto/provider \
|
|
modules/jdk.crypto.ec/sun/security/ec \
|
|
+ modules/jdk.crypto.kaeprovider/org/openeuler/security/openssl \
|
|
modules/jdk.crypto.mscapi/sun/security/mscapi \
|
|
modules/jdk.crypto.cryptoki/sun/security/pkcs11 \
|
|
modules/jdk.crypto.cryptoki/sun/security/pkcs11/wrapper \
|
|
diff --git a/make/autoconf/configure.ac b/make/autoconf/configure.ac
|
|
index 6672d26a5..c3e8ceb35 100644
|
|
--- a/make/autoconf/configure.ac
|
|
+++ b/make/autoconf/configure.ac
|
|
@@ -232,6 +232,7 @@ HOTSPOT_SETUP_JVM_FEATURES
|
|
#
|
|
###############################################################################
|
|
|
|
+JDKOPT_DETECT_KAE
|
|
JDKOPT_DETECT_INTREE_EC
|
|
JDKOPT_ENABLE_DISABLE_FAILURE_HANDLER
|
|
JDKOPT_ENABLE_DISABLE_GENERATE_CLASSLIST
|
|
diff --git a/make/autoconf/jdk-options.m4 b/make/autoconf/jdk-options.m4
|
|
index 9d64b31bf..e20eafa60 100644
|
|
--- a/make/autoconf/jdk-options.m4
|
|
+++ b/make/autoconf/jdk-options.m4
|
|
@@ -280,6 +280,29 @@ AC_DEFUN_ONCE([JDKOPT_DETECT_INTREE_EC],
|
|
AC_SUBST(ENABLE_INTREE_EC)
|
|
])
|
|
|
|
+###############################################################################
|
|
+#
|
|
+# Enable or disable the kae crypto implementation
|
|
+#
|
|
+AC_DEFUN_ONCE([JDKOPT_DETECT_KAE],
|
|
+[
|
|
+ AC_ARG_ENABLE(kae, [AS_HELP_STRING([--enable-kae],
|
|
+ [enable KAE support on aarch64 @<:@disabled@:>@])])
|
|
+ ENABLE_KAE="false"
|
|
+ AC_MSG_CHECKING([if kae should be enabled])
|
|
+ if test "x$enable_kae" = "xyes"; then
|
|
+ AC_MSG_RESULT([yes])
|
|
+ ENABLE_KAE="true"
|
|
+ elif test "x$enable_kae" = "x" || test "x$enable_kae" = "xno"; then
|
|
+ AC_MSG_RESULT([no])
|
|
+ ENABLE_KAE="false"
|
|
+ else
|
|
+ AC_MSG_ERROR([Invalid value for --enable-kae: $enable_kae])
|
|
+ fi
|
|
+
|
|
+ AC_SUBST(ENABLE_KAE)
|
|
+])
|
|
+
|
|
AC_DEFUN_ONCE([JDKOPT_SETUP_DEBUG_SYMBOLS],
|
|
[
|
|
#
|
|
diff --git a/make/autoconf/spec.gmk.in b/make/autoconf/spec.gmk.in
|
|
index e1f2feb72..789126311 100644
|
|
--- a/make/autoconf/spec.gmk.in
|
|
+++ b/make/autoconf/spec.gmk.in
|
|
@@ -773,6 +773,7 @@ TAR_SUPPORTS_TRANSFORM:=@TAR_SUPPORTS_TRANSFORM@
|
|
# Build setup
|
|
ENABLE_AOT:=@ENABLE_AOT@
|
|
ENABLE_INTREE_EC:=@ENABLE_INTREE_EC@
|
|
+ENABLE_KAE:=@ENABLE_KAE@
|
|
USE_EXTERNAL_LIBJPEG:=@USE_EXTERNAL_LIBJPEG@
|
|
USE_EXTERNAL_LIBGIF:=@USE_EXTERNAL_LIBGIF@
|
|
USE_EXTERNAL_LIBZ:=@USE_EXTERNAL_LIBZ@
|
|
diff --git a/make/common/Modules.gmk b/make/common/Modules.gmk
|
|
index 41533e566..9fa545605 100644
|
|
--- a/make/common/Modules.gmk
|
|
+++ b/make/common/Modules.gmk
|
|
@@ -118,6 +118,12 @@ PLATFORM_MODULES += \
|
|
jdk.zipfs \
|
|
#
|
|
|
|
+ifeq ($(ENABLE_KAE), true)
|
|
+ ifeq ($(OPENJDK_TARGET_CPU_ARCH), aarch64)
|
|
+ PLATFORM_MODULES += jdk.crypto.kaeprovider
|
|
+ endif
|
|
+endif
|
|
+
|
|
ifeq ($(call isTargetOs, windows), true)
|
|
PLATFORM_MODULES += jdk.crypto.mscapi
|
|
endif
|
|
@@ -228,6 +234,13 @@ ifeq ($(ENABLE_AOT), false)
|
|
MODULES_FILTER += jdk.aot
|
|
endif
|
|
|
|
+################################################################################
|
|
+# Filter out kae specific modules if kae is disabled or cpu is not aarch64
|
|
+
|
|
+ifneq ($(ENABLE_KAE)-$(OPENJDK_TARGET_CPU_ARCH), true-aarch64)
|
|
+ MODULES_FILTER += jdk.crypto.kaeprovider
|
|
+endif
|
|
+
|
|
################################################################################
|
|
# Module list macros
|
|
|
|
diff --git a/make/copy/Copy-jdk.crypto.kaeprovider.gmk b/make/copy/Copy-jdk.crypto.kaeprovider.gmk
|
|
new file mode 100644
|
|
index 000000000..ef0bfd88a
|
|
--- /dev/null
|
|
+++ b/make/copy/Copy-jdk.crypto.kaeprovider.gmk
|
|
@@ -0,0 +1,46 @@
|
|
+#
|
|
+# 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. 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.
|
|
+#
|
|
+
|
|
+include CopyCommon.gmk
|
|
+
|
|
+################################################################################
|
|
+
|
|
+ifeq ($(ENABLE_KAE), true)
|
|
+ ifeq ($(OPENJDK_TARGET_CPU_ARCH), aarch64)
|
|
+
|
|
+ KAEPROVIDER_CONF_SRC := $(TOPDIR)/src/jdk.crypto.kaeprovider/linux/conf/security/kaeprovider.conf
|
|
+ KAEPROVIDER_CONF_DST := $(CONF_DST_DIR)/kaeprovider.conf
|
|
+
|
|
+ $(KAEPROVIDER_CONF_DST): $(KAEPROVIDER_CONF_SRC)
|
|
+ $(call install-file)
|
|
+
|
|
+ TARGETS += $(KAEPROVIDER_CONF_DST)
|
|
+
|
|
+ endif
|
|
+endif
|
|
+
|
|
+
|
|
+################################################################################
|
|
diff --git a/make/lib/Lib-jdk.crypto.kaeprovider.gmk b/make/lib/Lib-jdk.crypto.kaeprovider.gmk
|
|
new file mode 100644
|
|
index 000000000..d4362f3a6
|
|
--- /dev/null
|
|
+++ b/make/lib/Lib-jdk.crypto.kaeprovider.gmk
|
|
@@ -0,0 +1,45 @@
|
|
+#
|
|
+# 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.
|
|
+#
|
|
+
|
|
+include LibCommon.gmk
|
|
+
|
|
+################################################################################
|
|
+
|
|
+ifeq ($(ENABLE_KAE), true)
|
|
+ ifeq ($(OPENJDK_TARGET_CPU_ARCH), aarch64)
|
|
+ $(eval $(call SetupJdkLibrary, BUILD_LIBJ2KAE, \
|
|
+ NAME := j2kae, \
|
|
+ OPTIMIZATION := LOW, \
|
|
+ CFLAGS := $(CFLAGS_JDKLIB), \
|
|
+ LDFLAGS := $(LDFLAGS_JDKLIB) \
|
|
+ $(call SET_SHARED_LIBRARY_ORIGIN), \
|
|
+ LIBS_unix := $(LIBDL) -lssl -lcrypto, \
|
|
+ ))
|
|
+
|
|
+ TARGETS += $(BUILD_LIBJ2KAE)
|
|
+ endif
|
|
+endif
|
|
+
|
|
+################################################################################
|
|
diff --git a/make/nb_native/nbproject/configurations.xml b/make/nb_native/nbproject/configurations.xml
|
|
index fb07d54c1..38da09395 100644
|
|
--- a/make/nb_native/nbproject/configurations.xml
|
|
+++ b/make/nb_native/nbproject/configurations.xml
|
|
@@ -5366,6 +5366,30 @@
|
|
</df>
|
|
</df>
|
|
</df>
|
|
+ <df name="jdk.crypto.kaeprovider">
|
|
+ <df name="linux">
|
|
+ <df name="native">
|
|
+ <df name="libj2kae">
|
|
+ <in>kae_cipher_rsa.c</in>
|
|
+ <in>kae_digest.c</in>
|
|
+ <in>kae_exception.c</in>
|
|
+ <in>kae_exception.h</in>
|
|
+ <in>kae_hmac.c</in>
|
|
+ <in>kae_keyagreement_dh.c</in>
|
|
+ <in>kae_keyagreement_ecdh.c</in>
|
|
+ <in>kae_keypairgenerator_dh.c</in>
|
|
+ <in>kae_keypairgenerator_ec.c</in>
|
|
+ <in>kae_keypairgenerator_rsa.c</in>
|
|
+ <in>kae_provider.c</in>
|
|
+ <in>kae_signature_rsa.c</in>
|
|
+ <in>kae_symmetric_cipher.c</in>
|
|
+ <in>kae_util.c</in>
|
|
+ <in>kae_util.h</in>
|
|
+ <in>kae_log.h</in>
|
|
+ </df>
|
|
+ </df>
|
|
+ </df>
|
|
+ </df>
|
|
<df name="jdk.hotspot.agent">
|
|
<df name="linux">
|
|
<df name="native">
|
|
@@ -38406,6 +38430,86 @@
|
|
tool="3"
|
|
flavor2="0">
|
|
</item>
|
|
+ <item path="../../src/jdk.crypto.kaeprovider/linux/native/org/openeuler/security/openssl/kae_cipher_rsa.c"
|
|
+ ex="false"
|
|
+ tool="0"
|
|
+ flavor2="0">
|
|
+ </item>
|
|
+ <item path="../../src/jdk.crypto.kaeprovider/linux/native/org/openeuler/security/openssl/kae_digest.c"
|
|
+ ex="false"
|
|
+ tool="0"
|
|
+ flavor2="0">
|
|
+ </item>
|
|
+ <item path="../../src/jdk.crypto.kaeprovider/linux/native/org/openeuler/security/openssl/kae_exception.c"
|
|
+ ex="false"
|
|
+ tool="0"
|
|
+ flavor2="0">
|
|
+ </item>
|
|
+ <item path="../../src/jdk.crypto.kaeprovider/linux/native/org/openeuler/security/openssl/kae_exception.h"
|
|
+ ex="false"
|
|
+ tool="3"
|
|
+ flavor2="0">
|
|
+ </item>
|
|
+ <item path="../../src/jdk.crypto.kaeprovider/linux/native/org/openeuler/security/openssl/kae_hmac.c"
|
|
+ ex="false"
|
|
+ tool="0"
|
|
+ flavor2="0">
|
|
+ </item>
|
|
+ <item path="../../src/jdk.crypto.kaeprovider/linux/native/org/openeuler/security/openssl/kae_keyagreement_dh.c"
|
|
+ ex="false"
|
|
+ tool="0"
|
|
+ flavor2="0">
|
|
+ </item>
|
|
+ <item path="../../src/jdk.crypto.kaeprovider/linux/native/org/openeuler/security/openssl/kae_keyagreement_ecdh.c"
|
|
+ ex="false"
|
|
+ tool="0"
|
|
+ flavor2="0">
|
|
+ </item>
|
|
+ <item path="../../src/jdk.crypto.kaeprovider/linux/native/org/openeuler/security/openssl/kae_keypairgenerator_dh.c"
|
|
+ ex="false"
|
|
+ tool="0"
|
|
+ flavor2="0">
|
|
+ </item>
|
|
+ <item path="../../src/jdk.crypto.kaeprovider/linux/native/org/openeuler/security/openssl/kae_keypairgenerator_ec.c"
|
|
+ ex="false"
|
|
+ tool="0"
|
|
+ flavor2="0">
|
|
+ </item>
|
|
+ <item path="../../src/jdk.crypto.kaeprovider/linux/native/org/openeuler/security/openssl/kae_keypairgenerator_rsa.c"
|
|
+ ex="false"
|
|
+ tool="0"
|
|
+ flavor2="0">
|
|
+ </item>
|
|
+ <item path="../../src/jdk.crypto.kaeprovider/linux/native/org/openeuler/security/openssl/kae_provider.c"
|
|
+ ex="false"
|
|
+ tool="0"
|
|
+ flavor2="0">
|
|
+ </item>
|
|
+ <item path="../../src/jdk.crypto.kaeprovider/linux/native/org/openeuler/security/openssl/kae_signature_rsa.c"
|
|
+ ex="false"
|
|
+ tool="0"
|
|
+ flavor2="0">
|
|
+ </item>
|
|
+ <item path="../../src/jdk.crypto.kaeprovider/linux/native/org/openeuler/security/openssl/kae_symmetric_cipher.c"
|
|
+ ex="false"
|
|
+ tool="0"
|
|
+ flavor2="0">
|
|
+ </item>
|
|
+ <item path="../../src/jdk.crypto.kaeprovider/linux/native/org/openeuler/security/openssl/kae_util.c"
|
|
+ ex="false"
|
|
+ tool="0"
|
|
+ flavor2="0">
|
|
+ </item>
|
|
+ <item path="../../src/jdk.crypto.kaeprovider/linux/native/org/openeuler/security/openssl/kae_util.h"
|
|
+ ex="false"
|
|
+ tool="3"
|
|
+ flavor2="0">
|
|
+ </item>
|
|
+ <item path="../../src/jdk.crypto.kaeprovider/linux/native/org/openeuler/security/openssl/kae_log.h"
|
|
+ ex="false"
|
|
+ tool="3"
|
|
+ flavor2="0">
|
|
+ </item>
|
|
<item path="../../src/jdk.hotspot.agent/linux/native/libsaproc/LinuxDebuggerLocal.c"
|
|
ex="false"
|
|
tool="0"
|
|
diff --git a/src/java.base/share/classes/module-info.java b/src/java.base/share/classes/module-info.java
|
|
index 7351627db..21c317647 100644
|
|
--- a/src/java.base/share/classes/module-info.java
|
|
+++ b/src/java.base/share/classes/module-info.java
|
|
@@ -275,11 +275,13 @@ module java.base {
|
|
exports sun.security.internal.interfaces to
|
|
jdk.crypto.cryptoki;
|
|
exports sun.security.internal.spec to
|
|
+ jdk.crypto.kaeprovider,
|
|
jdk.crypto.cryptoki;
|
|
exports sun.security.jca to
|
|
java.smartcardio,
|
|
jdk.crypto.ec,
|
|
jdk.crypto.cryptoki,
|
|
+ jdk.crypto.kaeprovider,
|
|
jdk.naming.dns;
|
|
exports sun.security.pkcs to
|
|
jdk.crypto.ec,
|
|
@@ -288,12 +290,16 @@ module java.base {
|
|
java.rmi,
|
|
java.security.jgss,
|
|
jdk.crypto.cryptoki,
|
|
+ jdk.crypto.kaeprovider,
|
|
jdk.security.auth;
|
|
exports sun.security.provider.certpath to
|
|
java.naming,
|
|
jdk.jartool;
|
|
exports sun.security.rsa to
|
|
- jdk.crypto.cryptoki;
|
|
+ jdk.crypto.cryptoki,
|
|
+ jdk.crypto.kaeprovider;
|
|
+ opens sun.security.rsa to
|
|
+ jdk.crypto.kaeprovider;
|
|
exports sun.security.ssl to
|
|
java.security.jgss;
|
|
exports sun.security.timestamp to
|
|
@@ -310,6 +316,7 @@ module java.base {
|
|
java.xml.crypto,
|
|
jdk.crypto.ec,
|
|
jdk.crypto.cryptoki,
|
|
+ jdk.crypto.kaeprovider,
|
|
jdk.jartool,
|
|
jdk.naming.ldap,
|
|
jdk.security.auth,
|
|
@@ -321,6 +328,7 @@ module java.base {
|
|
exports sun.security.x509 to
|
|
jdk.crypto.ec,
|
|
jdk.crypto.cryptoki,
|
|
+ jdk.crypto.kaeprovider,
|
|
jdk.jartool;
|
|
exports sun.security.validator to
|
|
jdk.jartool;
|
|
diff --git a/src/java.base/share/lib/security/default.policy b/src/java.base/share/lib/security/default.policy
|
|
index 41f5979da..13b01d016 100644
|
|
--- a/src/java.base/share/lib/security/default.policy
|
|
+++ b/src/java.base/share/lib/security/default.policy
|
|
@@ -123,6 +123,11 @@ grant codeBase "jrt:/jdk.crypto.ec" {
|
|
permission java.security.SecurityPermission "removeProviderProperty.SunEC";
|
|
};
|
|
|
|
+grant codeBase "jrt:/jdk.crypto.kaeprovider" {
|
|
+ permission java.lang.RuntimePermission
|
|
+ "accessClassInPackage.sun.security.*";
|
|
+};
|
|
+
|
|
grant codeBase "jrt:/jdk.crypto.cryptoki" {
|
|
permission java.lang.RuntimePermission
|
|
"accessClassInPackage.com.sun.crypto.provider";
|
|
diff --git a/src/jdk.crypto.ec/share/classes/module-info.java b/src/jdk.crypto.ec/share/classes/module-info.java
|
|
index 9ba6e6195..67bb6e00e 100644
|
|
--- a/src/jdk.crypto.ec/share/classes/module-info.java
|
|
+++ b/src/jdk.crypto.ec/share/classes/module-info.java
|
|
@@ -32,5 +32,11 @@
|
|
* @since 9
|
|
*/
|
|
module jdk.crypto.ec {
|
|
+ exports sun.security.ec to
|
|
+ jdk.crypto.kaeprovider;
|
|
+
|
|
+ opens sun.security.ec to
|
|
+ jdk.crypto.kaeprovider;
|
|
+
|
|
provides java.security.Provider with sun.security.ec.SunEC;
|
|
}
|
|
diff --git a/src/jdk.crypto.kaeprovider/linux/classes/module-info.java b/src/jdk.crypto.kaeprovider/linux/classes/module-info.java
|
|
new file mode 100644
|
|
index 000000000..87b29bdf9
|
|
--- /dev/null
|
|
+++ b/src/jdk.crypto.kaeprovider/linux/classes/module-info.java
|
|
@@ -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. 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.
|
|
+ */
|
|
+
|
|
+/**
|
|
+* Provides the implementation of KAEProvider.
|
|
+*
|
|
+* @provides java.security.Provider
|
|
+* @moduleGraph
|
|
+* @since 11
|
|
+*/
|
|
+module jdk.crypto.kaeprovider {
|
|
+ // Depends on SunEC provider for EC related functionality
|
|
+ requires jdk.crypto.ec;
|
|
+
|
|
+ exports org.openeuler.security.openssl to java.base;
|
|
+ provides java.security.Provider with org.openeuler.security.openssl.KAEProvider;
|
|
+}
|
|
diff --git a/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEAESCipher.java b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEAESCipher.java
|
|
new file mode 100644
|
|
index 000000000..6ef3620b0
|
|
--- /dev/null
|
|
+++ b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEAESCipher.java
|
|
@@ -0,0 +1,365 @@
|
|
+/*
|
|
+ * 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.security.InvalidAlgorithmParameterException;
|
|
+import java.security.InvalidKeyException;
|
|
+import java.security.NoSuchAlgorithmException;
|
|
+import java.security.Key;
|
|
+import java.util.Locale;
|
|
+
|
|
+import javax.crypto.NoSuchPaddingException;
|
|
+
|
|
+/*
|
|
+ * This class currently supports:
|
|
+ * - AES/ECB/NOPADDING
|
|
+ * - AES/ECB/PKCS5PADDING
|
|
+ * - AES/CBC/NOPADDING
|
|
+ * - AES/CBC/PKCS5PADDING
|
|
+ * - AES/CTR/NOPADDING
|
|
+ * - AES/GCM/NOPADDING
|
|
+ */
|
|
+abstract class KAEAESCipher extends KAESymmetricCipherBase {
|
|
+
|
|
+ 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 Gcm extends Aes {
|
|
+ public Gcm(Padding padding) {
|
|
+ super(Mode.GCM, padding);
|
|
+ }
|
|
+ public static class NoPadding extends Gcm {
|
|
+ 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 Gcm extends Aes_128 {
|
|
+ public Gcm(Padding padding) {
|
|
+ super(Mode.GCM, padding);
|
|
+ }
|
|
+ public static class NoPadding extends Gcm {
|
|
+ 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 Gcm extends Aes_192 {
|
|
+ public Gcm(Padding padding) {
|
|
+ super(Mode.GCM, padding);
|
|
+ }
|
|
+ public static class NoPadding extends Gcm {
|
|
+ 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);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public static class Gcm extends Aes_256 {
|
|
+ public Gcm(Padding padding) {
|
|
+ super(Mode.GCM, padding);
|
|
+ }
|
|
+ public static class NoPadding extends Gcm {
|
|
+ public NoPadding() {
|
|
+ super(Padding.NOPADDING);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ KAEAESCipher(Mode mode, Padding padding, int fixedKeySize) {
|
|
+ super(mode, padding, fixedKeySize, "AES");
|
|
+ }
|
|
+
|
|
+ protected void 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);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ protected String getCipherName(int keyLength, Mode mode) {
|
|
+ return "aes-" + keyLength + "-" + mode.toString().toLowerCase(Locale.US);
|
|
+ }
|
|
+
|
|
+ @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 if (modeStr.equalsIgnoreCase("GCM")) {
|
|
+ mode = Mode.GCM;
|
|
+ } 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("PKCS7PADDING")) {
|
|
+ paddingStr = "PKCS5Padding";
|
|
+ }
|
|
+
|
|
+ // GCM has no Padding, pkcs5-> nopadding in sunjce
|
|
+ if (mode == Mode.GCM) {
|
|
+ this.padding = Padding.NOPADDING;
|
|
+ } else 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 " + paddingStr);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ protected void checkIvBytes(byte[] ivBytes) throws InvalidAlgorithmParameterException {
|
|
+ if ((ivBytes == null) || (ivBytes.length != blockSize)) {
|
|
+ throw new InvalidAlgorithmParameterException("Wrong IV length: must be " + blockSize + " bytes long.");
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
diff --git a/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEDHKeyAgreement.java b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEDHKeyAgreement.java
|
|
new file mode 100644
|
|
index 000000000..6986d2548
|
|
--- /dev/null
|
|
+++ b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEDHKeyAgreement.java
|
|
@@ -0,0 +1,289 @@
|
|
+/*
|
|
+ * 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.util.KeyUtil;
|
|
+import java.math.BigInteger;
|
|
+import java.security.KeyFactory;
|
|
+import java.security.InvalidKeyException;
|
|
+import java.security.SecureRandom;
|
|
+import java.security.Key;
|
|
+import java.security.InvalidAlgorithmParameterException;
|
|
+import java.security.NoSuchAlgorithmException;
|
|
+import java.security.AlgorithmParameterGeneratorSpi;
|
|
+import java.security.AccessController;
|
|
+import java.security.ProviderException;
|
|
+import java.security.PrivilegedAction;
|
|
+import java.security.spec.InvalidKeySpecException;
|
|
+import java.security.spec.AlgorithmParameterSpec;
|
|
+import javax.crypto.KeyAgreementSpi;
|
|
+import javax.crypto.SecretKey;
|
|
+import javax.crypto.ShortBufferException;
|
|
+import javax.crypto.interfaces.DHPrivateKey;
|
|
+import javax.crypto.interfaces.DHPublicKey;
|
|
+import javax.crypto.spec.DHParameterSpec;
|
|
+import javax.crypto.spec.SecretKeySpec;
|
|
+import javax.crypto.spec.DHPublicKeySpec;
|
|
+import javax.crypto.SecretKeyFactory;
|
|
+import javax.crypto.spec.DESedeKeySpec;
|
|
+import javax.crypto.spec.DESKeySpec;
|
|
+
|
|
+public class KAEDHKeyAgreement extends KeyAgreementSpi {
|
|
+ private boolean generateSecret = false;
|
|
+ private BigInteger p;
|
|
+ private BigInteger g;
|
|
+ private BigInteger x;
|
|
+ private BigInteger y;
|
|
+ static final int[] AES_KEYSIZES = {16, 24, 32};
|
|
+ static final int BLOWFISH_MAX_KEYSIZE = 56;
|
|
+
|
|
+ private static class AllowKDF {
|
|
+ private static final boolean VALUE = getValue();
|
|
+
|
|
+ private static boolean getValue() {
|
|
+ return AccessController.doPrivileged(
|
|
+ (PrivilegedAction<Boolean>)
|
|
+ () -> Boolean.getBoolean("jdk.crypto.KeyAgreement.legacyKDF"));
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public KAEDHKeyAgreement() {
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ protected void engineInit(Key key, SecureRandom random) throws InvalidKeyException {
|
|
+ try {
|
|
+ engineInit(key, null, random);
|
|
+ } catch (InvalidAlgorithmParameterException e) {
|
|
+ // never happens, because we did not pass any parameters
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ protected void engineInit(Key key, AlgorithmParameterSpec params,
|
|
+ SecureRandom random)
|
|
+ throws InvalidKeyException, InvalidAlgorithmParameterException {
|
|
+
|
|
+ // ignore "random" parameter, because our implementation does not
|
|
+ // require any source of randomness
|
|
+ generateSecret = false;
|
|
+ p = null;
|
|
+ g = null;
|
|
+
|
|
+ if ((params != null) && !(params instanceof DHParameterSpec)) {
|
|
+ throw new InvalidAlgorithmParameterException("Diffie-Hellman parameters expected");
|
|
+ }
|
|
+
|
|
+ if (!(key instanceof DHPrivateKey)) {
|
|
+ throw new InvalidKeyException("Diffie-Hellman private key expected");
|
|
+ }
|
|
+
|
|
+ DHPrivateKey privateKey = (DHPrivateKey) key;
|
|
+
|
|
+ // check if private key parameters are compatible with
|
|
+ // initialized ones
|
|
+ if (params != null) {
|
|
+ p = ((DHParameterSpec) params).getP();
|
|
+ g = ((DHParameterSpec) params).getG();
|
|
+ }
|
|
+
|
|
+ BigInteger priv_p = privateKey.getParams().getP();
|
|
+ BigInteger priv_g = privateKey.getParams().getG();
|
|
+ if (p != null && priv_p != null && !(p.equals(priv_p))) {
|
|
+ throw new InvalidKeyException("Incompatible parameters");
|
|
+ }
|
|
+ if (g != null && priv_g != null && !(g.equals(priv_g))) {
|
|
+ throw new InvalidKeyException("Incompatible parameters");
|
|
+ }
|
|
+ if ((p == null && priv_p == null) ||
|
|
+ (g == null) && priv_g == null) {
|
|
+ throw new InvalidKeyException("Missing parameters");
|
|
+ }
|
|
+ p = priv_p;
|
|
+ g = priv_g;
|
|
+
|
|
+ // store the x value
|
|
+ x = privateKey.getX();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ protected Key engineDoPhase(Key key, boolean lastPhase)
|
|
+ throws InvalidKeyException, IllegalStateException {
|
|
+ if (!(key instanceof DHPublicKey)) {
|
|
+ throw new InvalidKeyException("Diffie-Hellman public "
|
|
+ + "expected");
|
|
+ }
|
|
+ DHPublicKey publicKey = (DHPublicKey) key;
|
|
+ if (p == null || g == null) {
|
|
+ throw new IllegalStateException("Not initialized");
|
|
+ }
|
|
+ BigInteger pub_p = publicKey.getParams().getP();
|
|
+ BigInteger pub_g = publicKey.getParams().getG();
|
|
+ if (pub_p != null && !(p.equals(pub_p))) {
|
|
+ throw new InvalidKeyException("Incompatible parameters");
|
|
+ }
|
|
+ if (pub_g != null && !(g.equals(pub_g))) {
|
|
+ throw new InvalidKeyException("Incompatible parameters");
|
|
+ }
|
|
+ KeyUtil.validate(publicKey);
|
|
+ y = publicKey.getY();
|
|
+ generateSecret = true;
|
|
+ if (lastPhase == false) {
|
|
+ byte[] intermediate = engineGenerateSecret();
|
|
+ try {
|
|
+ KeyFactory fk = KeyFactory.getInstance("DH");
|
|
+ DHPublicKey newPublicKey = (DHPublicKey) fk.generatePublic(
|
|
+ new DHPublicKeySpec(new BigInteger(1, intermediate), p, g));
|
|
+ return newPublicKey;
|
|
+ } catch (NoSuchAlgorithmException noalg) {
|
|
+ throw new ProviderException(noalg);
|
|
+ } catch (InvalidKeySpecException ikse) {
|
|
+ throw new ProviderException(ikse);
|
|
+ }
|
|
+ } else {
|
|
+ return null;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ protected byte[] engineGenerateSecret()
|
|
+ throws IllegalStateException {
|
|
+ int expectedLen = (p.bitLength() + 7) >>> 3;
|
|
+ byte[] result = new byte[expectedLen];
|
|
+ try {
|
|
+ engineGenerateSecret(result, 0);
|
|
+ } catch (ShortBufferException shortBufferException) {
|
|
+ // should never happen since length are identical
|
|
+ }
|
|
+ return result;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ protected int engineGenerateSecret(byte[] sharedSecret, int offset)
|
|
+ throws IllegalStateException, ShortBufferException {
|
|
+ if (!generateSecret) {
|
|
+ throw new IllegalStateException("Key agreement has not bee complated yet");
|
|
+ }
|
|
+ if (sharedSecret == null) {
|
|
+ throw new ShortBufferException("No buffer provided for shared secret");
|
|
+ }
|
|
+ BigInteger modulus = p;
|
|
+ int expectedLen = (modulus.bitLength() + 7) >>> 3;
|
|
+ if ((sharedSecret.length - offset) < expectedLen) {
|
|
+ throw new ShortBufferException("Buffer too short for shared secret");
|
|
+ }
|
|
+ generateSecret = false;
|
|
+ byte[] secret = nativeComputeKey(y.toByteArray(), x.toByteArray(),
|
|
+ p.toByteArray(), g.toByteArray(), modulus.bitLength());
|
|
+
|
|
+ if (secret.length == expectedLen) {
|
|
+ System.arraycopy(secret, 0, sharedSecret, offset,
|
|
+ secret.length);
|
|
+ } else {
|
|
+ // Array too short, pad it w/ leading 0s
|
|
+ if (secret.length < expectedLen) {
|
|
+ System.arraycopy(secret, 0, sharedSecret,
|
|
+ offset + (expectedLen - secret.length),
|
|
+ secret.length);
|
|
+ } else {
|
|
+ // Array too long, check and trim off the excess
|
|
+ if ((secret.length == (expectedLen + 1)) && secret[0] == 0) {
|
|
+ // ignore the leading sign byte
|
|
+ System.arraycopy(secret, 1, sharedSecret, offset, expectedLen);
|
|
+ } else {
|
|
+ throw new ProviderException("Generated secret is out-of-range");
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return expectedLen;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ protected SecretKey engineGenerateSecret(String algorithm)
|
|
+ throws IllegalStateException, NoSuchAlgorithmException, InvalidKeyException {
|
|
+ if (algorithm == null) {
|
|
+ throw new NoSuchAlgorithmException("null algorithm");
|
|
+ }
|
|
+
|
|
+ if (!algorithm.equalsIgnoreCase("TlsPremasterSecret") &&
|
|
+ !AllowKDF.VALUE) {
|
|
+
|
|
+ throw new NoSuchAlgorithmException("Unsupported secret key "
|
|
+ + "algorithm: " + algorithm);
|
|
+ }
|
|
+
|
|
+ byte[] secret = engineGenerateSecret();
|
|
+ if (algorithm.equalsIgnoreCase("DES")) {
|
|
+ // DES
|
|
+ try {
|
|
+ SecretKeyFactory factory = SecretKeyFactory.getInstance("DES");
|
|
+ return factory.generateSecret(new DESKeySpec(secret));
|
|
+ } catch (InvalidKeySpecException e) {
|
|
+ throw new ProviderException("Generate DES Secret failed.", e);
|
|
+ }
|
|
+ } else if (algorithm.equalsIgnoreCase("DESede")
|
|
+ || algorithm.equalsIgnoreCase("TripleDES")) {
|
|
+ // Triple DES
|
|
+ try {
|
|
+ SecretKeyFactory factory = SecretKeyFactory.getInstance("DESede");
|
|
+ return factory.generateSecret(new DESedeKeySpec(secret));
|
|
+ } catch (InvalidKeySpecException e) {
|
|
+ throw new ProviderException("Generate DESede Secret failed.", e);
|
|
+ }
|
|
+ } else if (algorithm.equalsIgnoreCase("Blowfish")) {
|
|
+ // Blowfish
|
|
+ int keysize = secret.length;
|
|
+ if (keysize >= BLOWFISH_MAX_KEYSIZE)
|
|
+ keysize = BLOWFISH_MAX_KEYSIZE;
|
|
+ return new SecretKeySpec(secret, 0, keysize, "Blowfish");
|
|
+ } else if (algorithm.equalsIgnoreCase("AES")) {
|
|
+ int idx = AES_KEYSIZES.length - 1;
|
|
+ int keysize = secret.length;
|
|
+ SecretKeySpec secretKey = null;
|
|
+ while (secretKey == null && idx >= 0) {
|
|
+ if (keysize >= AES_KEYSIZES[idx]) {
|
|
+ keysize = AES_KEYSIZES[idx];
|
|
+ secretKey = new SecretKeySpec(secret, 0, keysize, "AES");
|
|
+ }
|
|
+ idx--;
|
|
+ }
|
|
+ if (secretKey == null) {
|
|
+ throw new InvalidKeyException("Key material is too short");
|
|
+ }
|
|
+ return secretKey;
|
|
+ } else if (algorithm.equals("TlsPremasterSecret")) {
|
|
+ // remove leading zero bytes per RFC 5246 Section 8.1.2
|
|
+ return new SecretKeySpec(
|
|
+ KeyUtil.trimZeroes(secret), "TlsPremasterSecret");
|
|
+ } else {
|
|
+ throw new NoSuchAlgorithmException("Unsupported secret key "
|
|
+ + "algorithm: " + algorithm);
|
|
+ }
|
|
+ }
|
|
+ protected native byte[] nativeComputeKey(byte[] y, byte[] x, byte[] p, byte[] g, int pSize);
|
|
+}
|
|
diff --git a/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEDHKeyPairGenerator.java b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEDHKeyPairGenerator.java
|
|
new file mode 100644
|
|
index 000000000..429c65fc0
|
|
--- /dev/null
|
|
+++ b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEDHKeyPairGenerator.java
|
|
@@ -0,0 +1,166 @@
|
|
+/*
|
|
+ * 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.math.BigInteger;
|
|
+import java.util.Map;
|
|
+import java.util.concurrent.ConcurrentHashMap;
|
|
+import java.security.spec.AlgorithmParameterSpec;
|
|
+import java.security.KeyPairGeneratorSpi;
|
|
+import java.security.SecureRandom;
|
|
+import java.security.InvalidAlgorithmParameterException;
|
|
+import java.security.KeyPair;
|
|
+import java.security.Key;
|
|
+import java.security.NoSuchAlgorithmException;
|
|
+import java.security.InvalidParameterException;
|
|
+import java.security.GeneralSecurityException;
|
|
+import java.security.ProviderException;
|
|
+import java.security.KeyFactory;
|
|
+import java.security.spec.InvalidKeySpecException;
|
|
+import sun.security.jca.JCAUtil;
|
|
+import sun.security.provider.ParameterCache;
|
|
+import javax.crypto.spec.DHPublicKeySpec;
|
|
+import javax.crypto.spec.DHPrivateKeySpec;
|
|
+import javax.crypto.spec.DHParameterSpec;
|
|
+import javax.crypto.interfaces.DHPublicKey;
|
|
+import javax.crypto.interfaces.DHPrivateKey;
|
|
+
|
|
+import static sun.security.util.SecurityProviderConstants.DEF_DH_KEY_SIZE;
|
|
+
|
|
+public class KAEDHKeyPairGenerator
|
|
+ extends KeyPairGeneratorSpi {
|
|
+ private DHParameterSpec parameterSpec;
|
|
+ // The size in bits of the random exponent (private value)
|
|
+ private int pSize;
|
|
+ // The size in bits of the random exponent (private value)
|
|
+ private int lSize;
|
|
+ private SecureRandom random;
|
|
+
|
|
+ public KAEDHKeyPairGenerator() {
|
|
+ super();
|
|
+ initialize(DEF_DH_KEY_SIZE, null);
|
|
+ }
|
|
+
|
|
+ private static void checkKeySize(int keySize) {
|
|
+ if ((keySize < 512) || (keySize > 8192) || ((keySize & 0x3F) != 0)) {
|
|
+ throw new InvalidParameterException(
|
|
+ "DH key size must be multiple of 64, and can only range " +
|
|
+ "from 512 to 8192(inclusize). " +
|
|
+ "The specific key size " + keySize + " is not supported");
|
|
+ }
|
|
+ }
|
|
+ @Override
|
|
+ public void initialize(AlgorithmParameterSpec params, SecureRandom random)
|
|
+ throws InvalidAlgorithmParameterException {
|
|
+
|
|
+ if (!(params instanceof DHParameterSpec)){
|
|
+ throw new InvalidAlgorithmParameterException
|
|
+ ("Inappropriate parameter type");
|
|
+ }
|
|
+
|
|
+ parameterSpec = (DHParameterSpec) params;
|
|
+ pSize = parameterSpec.getP().bitLength();
|
|
+
|
|
+ try {
|
|
+ checkKeySize(pSize);
|
|
+ } catch (InvalidParameterException e) {
|
|
+ throw new InvalidAlgorithmParameterException(e.getMessage());
|
|
+ }
|
|
+
|
|
+ // exponent size is optional, could be 0
|
|
+ lSize = parameterSpec.getL();
|
|
+
|
|
+ // Require exponentSize < primeSize
|
|
+ if ((lSize != 0) && (lSize > pSize)) {
|
|
+ throw new InvalidAlgorithmParameterException
|
|
+ ("Exponent size must not be larger than modulus size");
|
|
+ }
|
|
+
|
|
+ this.random = random;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void initialize(int keysize, SecureRandom random) {
|
|
+ checkKeySize(keysize);
|
|
+ this.parameterSpec = ParameterCache.getCachedDHParameterSpec(keysize);
|
|
+ if ((this.parameterSpec == null) && (keysize > 1024)) {
|
|
+ throw new InvalidParameterException("Unsupported " + keysize + "-bit DH parameter generation.");
|
|
+ }
|
|
+ this.pSize = keysize;
|
|
+ this.lSize = 0;
|
|
+ this.random = random;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public KeyPair generateKeyPair() {
|
|
+
|
|
+ if (random == null) {
|
|
+ random = JCAUtil.getSecureRandom();
|
|
+ }
|
|
+
|
|
+ if (parameterSpec == null) {
|
|
+ try {
|
|
+ parameterSpec = ParameterCache.getDHParameterSpec(pSize, random);
|
|
+ } catch (GeneralSecurityException e) {
|
|
+ // should never happen
|
|
+ throw new ProviderException(e);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ BigInteger p = parameterSpec.getP();
|
|
+ BigInteger g = parameterSpec.getG();
|
|
+
|
|
+ if (lSize <= 0) {
|
|
+ lSize = pSize >> 1;
|
|
+ // use an exponent size of (pSize / 2) but at least 384 bits
|
|
+ if (lSize < 384) {
|
|
+ lSize = 384;
|
|
+ }
|
|
+ }
|
|
+ byte[][] keys;
|
|
+ try {
|
|
+ keys = nativeGenerateKeyPair(p.toByteArray(), g.toByteArray(), lSize);
|
|
+ } catch (Exception e){
|
|
+ throw new ProviderException("Invoke nativeGenerateKeyPair failed.", e);
|
|
+ }
|
|
+
|
|
+ BigInteger pubKey = new BigInteger(keys[0]);
|
|
+ BigInteger priKey = new BigInteger(keys[1]);
|
|
+
|
|
+ try{
|
|
+ KeyFactory fk = KeyFactory.getInstance("DH");
|
|
+ DHPublicKey publicKey = (DHPublicKey)fk.generatePublic(new DHPublicKeySpec(pubKey, p , g));
|
|
+ DHPrivateKey privateKey = (DHPrivateKey)fk.generatePrivate(new DHPrivateKeySpec(priKey, p, g));
|
|
+ return new KeyPair(publicKey, privateKey);
|
|
+ } catch (NoSuchAlgorithmException noalg) {
|
|
+ throw new ProviderException(noalg);
|
|
+ } catch (InvalidKeySpecException ikse) {
|
|
+ throw new ProviderException(ikse);
|
|
+ }
|
|
+ }
|
|
+ protected native static byte[][] nativeGenerateKeyPair(byte[] p, byte[] g, int lSize);
|
|
+}
|
|
diff --git a/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEDigest.java b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEDigest.java
|
|
new file mode 100644
|
|
index 000000000..bb5c8681b
|
|
--- /dev/null
|
|
+++ b/src/jdk.crypto.kaeprovider/linux/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/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEECDHKeyAgreement.java b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEECDHKeyAgreement.java
|
|
new file mode 100644
|
|
index 000000000..7a9cc5cc5
|
|
--- /dev/null
|
|
+++ b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEECDHKeyAgreement.java
|
|
@@ -0,0 +1,146 @@
|
|
+/*
|
|
+ * Copyright (c) 2009, 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. 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.ec.ECKeyFactory;
|
|
+
|
|
+import java.math.BigInteger;
|
|
+import java.security.InvalidAlgorithmParameterException;
|
|
+import java.security.InvalidParameterException;
|
|
+import java.security.InvalidKeyException;
|
|
+import java.security.Key;
|
|
+import java.security.NoSuchAlgorithmException;
|
|
+import java.security.PrivateKey;
|
|
+import java.security.SecureRandom;
|
|
+import java.security.interfaces.ECPrivateKey;
|
|
+import java.security.interfaces.ECPublicKey;
|
|
+import java.security.spec.AlgorithmParameterSpec;
|
|
+import java.security.spec.ECParameterSpec;
|
|
+import java.security.spec.ECPoint;
|
|
+import javax.crypto.KeyAgreementSpi;
|
|
+import javax.crypto.SecretKey;
|
|
+import javax.crypto.ShortBufferException;
|
|
+import javax.crypto.spec.SecretKeySpec;
|
|
+
|
|
+public class KAEECDHKeyAgreement extends KeyAgreementSpi {
|
|
+ private ECPrivateKey privateKey;
|
|
+ private ECPublicKey publicKey;
|
|
+
|
|
+ // Length of the secret to be derived.
|
|
+ private int expectedSecretLen;
|
|
+ private String curveName;
|
|
+
|
|
+ @Override
|
|
+ protected void engineInit(Key key, SecureRandom random) throws InvalidKeyException {
|
|
+ if (!(key instanceof PrivateKey)) {
|
|
+ throw new InvalidKeyException("Key must be instance of PrivateKey");
|
|
+ }
|
|
+ privateKey = (ECPrivateKey) ECKeyFactory.toECKey(key);
|
|
+ publicKey = null;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ protected void engineInit(Key key, AlgorithmParameterSpec params, SecureRandom random)
|
|
+ throws InvalidKeyException, InvalidAlgorithmParameterException {
|
|
+ if (params != null) {
|
|
+ throw new InvalidAlgorithmParameterException("Parameters not supported");
|
|
+ }
|
|
+ engineInit(key, random);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ protected Key engineDoPhase(Key key, boolean lastPhase) throws InvalidKeyException, IllegalStateException {
|
|
+ if (privateKey == null) {
|
|
+ throw new IllegalStateException("Not initialized");
|
|
+ }
|
|
+ if (publicKey != null) {
|
|
+ throw new IllegalStateException("Phase already executed");
|
|
+ }
|
|
+ if (!lastPhase) {
|
|
+ throw new IllegalStateException
|
|
+ ("Only two party agreement supported, lastPhase must be true");
|
|
+ }
|
|
+ if (!(key instanceof ECPublicKey)) {
|
|
+ throw new InvalidKeyException
|
|
+ ("Key must be a PublicKey with algorithm EC");
|
|
+ }
|
|
+
|
|
+ publicKey = (ECPublicKey) key;
|
|
+ ECParameterSpec params = publicKey.getParams();
|
|
+ int keyLenBits = params.getCurve().getField().getFieldSize();
|
|
+ // Bits to bytes.
|
|
+ expectedSecretLen = (keyLenBits + 7) >> 3;
|
|
+
|
|
+ curveName = KAEUtils.getCurveBySize(keyLenBits);
|
|
+ if (curveName == null) {
|
|
+ throw new InvalidParameterException("unknown keyLenBits " + keyLenBits);
|
|
+ }
|
|
+ if (KAEUtils.getCurveByAlias(curveName) != null) {
|
|
+ curveName = KAEUtils.getCurveByAlias(curveName);
|
|
+ }
|
|
+ return null;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ protected byte[] engineGenerateSecret() throws IllegalStateException {
|
|
+ if ((privateKey == null) || (publicKey == null)) {
|
|
+ throw new IllegalStateException("Not initialized correctly");
|
|
+ }
|
|
+ ECPoint w = publicKey.getW();
|
|
+ BigInteger wX = w.getAffineX();
|
|
+ BigInteger wY = w.getAffineY();
|
|
+
|
|
+ BigInteger s = privateKey.getS();
|
|
+ byte[] secret = nativeGenerateSecret(curveName, wX.toByteArray(), wY.toByteArray(), s.toByteArray());
|
|
+ if (secret == null || secret.length != expectedSecretLen) {
|
|
+ throw new RuntimeException("nativeGenerateSecret error. Expected: " + expectedSecretLen + ", actual: " + (secret == null ? "null" : secret.length));
|
|
+ }
|
|
+ return secret;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ protected int engineGenerateSecret(byte[] sharedSecret, int offset) throws IllegalStateException, ShortBufferException {
|
|
+ if (offset + expectedSecretLen > sharedSecret.length) {
|
|
+ throw new ShortBufferException("Need " + expectedSecretLen +
|
|
+ " bytes, only " + (sharedSecret.length - offset) + "available");
|
|
+ }
|
|
+ byte[] secret = engineGenerateSecret();
|
|
+ System.arraycopy(secret, 0, sharedSecret, offset, secret.length);
|
|
+ return secret.length;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ protected SecretKey engineGenerateSecret(String algorithm) throws IllegalStateException,
|
|
+ NoSuchAlgorithmException, InvalidKeyException {
|
|
+ if (algorithm == null) {
|
|
+ throw new NoSuchAlgorithmException("Algorithm must not be null");
|
|
+ }
|
|
+ return new SecretKeySpec(engineGenerateSecret(), algorithm);
|
|
+ }
|
|
+
|
|
+ protected static native byte[] nativeGenerateSecret(String curveName, byte[] wX, byte[] wY, byte[] s);
|
|
+}
|
|
diff --git a/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEECKeyPairGenerator.java b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEECKeyPairGenerator.java
|
|
new file mode 100644
|
|
index 000000000..60fa8183c
|
|
--- /dev/null
|
|
+++ b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEECKeyPairGenerator.java
|
|
@@ -0,0 +1,154 @@
|
|
+/*
|
|
+ * 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.ec.ECPrivateKeyImpl;
|
|
+import sun.security.ec.ECPublicKeyImpl;
|
|
+
|
|
+import java.math.BigInteger;
|
|
+import java.security.InvalidAlgorithmParameterException;
|
|
+import java.security.InvalidParameterException;
|
|
+import java.security.InvalidKeyException;
|
|
+import java.security.KeyPair;
|
|
+import java.security.KeyPairGeneratorSpi;
|
|
+import java.security.ProviderException;
|
|
+import java.security.SecureRandom;
|
|
+import java.security.spec.AlgorithmParameterSpec;
|
|
+import java.security.spec.ECFieldFp;
|
|
+import java.security.spec.ECField;
|
|
+import java.security.spec.ECGenParameterSpec;
|
|
+import java.security.spec.ECParameterSpec;
|
|
+import java.security.spec.ECPoint;
|
|
+import java.security.spec.EllipticCurve;
|
|
+import java.util.HashMap;
|
|
+import java.util.Map;
|
|
+
|
|
+import java.lang.reflect.Constructor;
|
|
+import java.lang.reflect.InvocationTargetException;
|
|
+
|
|
+public class KAEECKeyPairGenerator extends KeyPairGeneratorSpi {
|
|
+ private ECParameterSpec param = null;
|
|
+ private final int defaultKeySize = 256;
|
|
+
|
|
+ @Override
|
|
+ public void initialize(int keysize, SecureRandom random) {
|
|
+ String curveName = KAEUtils.getCurveBySize(keysize);
|
|
+ if (curveName == null) {
|
|
+ throw new InvalidParameterException("unknown key size " + keysize);
|
|
+ }
|
|
+ if (KAEUtils.getCurveByAlias(curveName) != null) {
|
|
+ curveName = KAEUtils.getCurveByAlias(curveName);
|
|
+ }
|
|
+ this.param = getParamsByCurve(curveName);
|
|
+ }
|
|
+
|
|
+ private ECParameterSpec getParamsByCurve(String curveName) {
|
|
+ byte[][] params = nativeGenerateParam(curveName);
|
|
+ if (params == null) {
|
|
+ throw new InvalidParameterException("unknown curve " + curveName);
|
|
+ }
|
|
+ BigInteger p = new BigInteger(params[0]);
|
|
+ BigInteger a = new BigInteger(params[1]);
|
|
+ BigInteger b = new BigInteger(params[2]);
|
|
+ BigInteger x = new BigInteger(params[3]);
|
|
+ BigInteger y = new BigInteger(params[4]);
|
|
+ BigInteger order = new BigInteger(params[5]);
|
|
+ BigInteger cofactor = new BigInteger(params[6]);
|
|
+ ECField field = new ECFieldFp(p);
|
|
+ EllipticCurve curve = new EllipticCurve(field, a, b);
|
|
+ ECPoint g = new ECPoint(x, y);
|
|
+ ECParameterSpec spec = new ECParameterSpec(curve, g, order, cofactor.intValue());
|
|
+ return spec;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void initialize(AlgorithmParameterSpec param, SecureRandom random) throws InvalidAlgorithmParameterException {
|
|
+ if (param instanceof ECParameterSpec) {
|
|
+ this.param = (ECParameterSpec) param;
|
|
+ } else if (param instanceof ECGenParameterSpec) {
|
|
+ ECGenParameterSpec ecParam = (ECGenParameterSpec)param;
|
|
+ String curveName = ecParam.getName();
|
|
+ if (KAEUtils.getCurveByAlias(curveName) != null) {
|
|
+ curveName = KAEUtils.getCurveByAlias(curveName);
|
|
+ }
|
|
+ this.param = getParamsByCurve(curveName);
|
|
+ } else {
|
|
+ throw new InvalidAlgorithmParameterException("ECParameterSpec or ECGenParameterSpec for EC");
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public KeyPair generateKeyPair() {
|
|
+ if (param == null) {
|
|
+ String curveName = KAEUtils.getCurveBySize(defaultKeySize);
|
|
+ param = getParamsByCurve(curveName);
|
|
+ }
|
|
+ EllipticCurve curve = param.getCurve();
|
|
+ ECFieldFp field = (ECFieldFp) curve.getField();
|
|
+ BigInteger p = field.getP();
|
|
+ BigInteger a = curve.getA();
|
|
+ BigInteger b = curve.getB();
|
|
+ ECPoint generator = param.getGenerator();
|
|
+ BigInteger x = generator.getAffineX();
|
|
+ BigInteger y = generator.getAffineY();
|
|
+ BigInteger order = param.getOrder();
|
|
+ int cofactor = param.getCofactor();
|
|
+
|
|
+ byte[][] keys = nativeGenerateKeyPair(p.toByteArray(), a.toByteArray(),
|
|
+ b.toByteArray(), x.toByteArray(), y.toByteArray(), order.toByteArray(), cofactor);
|
|
+ if (keys == null) {
|
|
+ throw new RuntimeException("nativeGenerateKeyPair failed");
|
|
+ }
|
|
+ BigInteger wX = new BigInteger(keys[0]);
|
|
+ BigInteger wY = new BigInteger(keys[1]);
|
|
+ BigInteger s = new BigInteger(keys[2]);
|
|
+ ECPoint w = new ECPoint(wX, wY);
|
|
+
|
|
+ ECPrivateKeyImpl privateKey = null;
|
|
+ ECPublicKeyImpl publicKey = null;
|
|
+ try {
|
|
+ Class<?> pubKeyImpl = Class.forName("sun.security.ec.ECPublicKeyImpl");
|
|
+ Constructor<?> conPubKeyImpl = pubKeyImpl.getDeclaredConstructor(ECPoint.class, ECParameterSpec.class);
|
|
+ conPubKeyImpl.setAccessible(true);
|
|
+ publicKey = (ECPublicKeyImpl) conPubKeyImpl.newInstance(w, param);
|
|
+
|
|
+ Class<?> priKeyImpl = Class.forName("sun.security.ec.ECPrivateKeyImpl");
|
|
+ Constructor<?> conPriKeyImpl = priKeyImpl.getDeclaredConstructor(BigInteger.class, ECParameterSpec.class);
|
|
+ conPriKeyImpl.setAccessible(true);
|
|
+ privateKey = (ECPrivateKeyImpl) conPriKeyImpl.newInstance(s, param);
|
|
+ } catch (ClassNotFoundException | NoSuchMethodException | InstantiationException |
|
|
+ IllegalAccessException | InvocationTargetException e) {
|
|
+ throw new ProviderException(e);
|
|
+ }
|
|
+ return new KeyPair(publicKey, privateKey);
|
|
+ }
|
|
+
|
|
+ protected static native byte[][] nativeGenerateParam(String curveName);
|
|
+
|
|
+ protected static native byte[][] nativeGenerateKeyPair(byte[] p, byte[] a, byte[] b, byte[] x, byte[] y,
|
|
+ byte[] order, int cofactor);
|
|
+}
|
|
diff --git a/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEHMac.java b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEHMac.java
|
|
new file mode 100644
|
|
index 000000000..c66fa2ff7
|
|
--- /dev/null
|
|
+++ b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEHMac.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 KAEHMac extends MacSpi {
|
|
+
|
|
+ private final String algorithm;
|
|
+
|
|
+ /**
|
|
+ * The secret key used in this keyed HMAC.
|
|
+ */
|
|
+ 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 KAEHMac(String algo, int size) {
|
|
+ this.algorithm = algo;
|
|
+ this.digestSize = size;
|
|
+ }
|
|
+
|
|
+ private static class HmacContextRef extends PhantomReference<KAEHMac>
|
|
+ implements Comparable<HmacContextRef> {
|
|
+
|
|
+ private static ReferenceQueue<KAEHMac> referenceQueue = new ReferenceQueue<>();
|
|
+ private static Set<HmacContextRef> referenceList = new ConcurrentSkipListSet<>();
|
|
+ private static boolean disableKaeDispose = Boolean.getBoolean("kae.disableKaeDispose");
|
|
+
|
|
+ private final long address;
|
|
+
|
|
+ HmacContextRef(KAEHMac kaeHMac, long address) {
|
|
+ super(kaeHMac, 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 KAEHMac {
|
|
+ public HmacMD5() {
|
|
+ super("MD5", 16);
|
|
+ }
|
|
+ }
|
|
+ public static final class HmacSHA1 extends KAEHMac {
|
|
+ public HmacSHA1() {
|
|
+ super("SHA1", 20);
|
|
+ }
|
|
+ }
|
|
+ public static final class HmacSHA224 extends KAEHMac {
|
|
+ public HmacSHA224() throws NoSuchAlgorithmException {
|
|
+ super("SHA224", 28);
|
|
+ }
|
|
+ }
|
|
+ public static final class HmacSHA256 extends KAEHMac {
|
|
+ public HmacSHA256() throws NoSuchAlgorithmException {
|
|
+ super("SHA256", 32);
|
|
+ }
|
|
+ }
|
|
+ public static final class HmacSHA384 extends KAEHMac {
|
|
+ public HmacSHA384() throws NoSuchAlgorithmException {
|
|
+ super("SHA384", 48);
|
|
+ }
|
|
+ }
|
|
+ public static final class HmacSHA512 extends KAEHMac {
|
|
+ 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/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEProvider.java b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEProvider.java
|
|
new file mode 100644
|
|
index 000000000..12fee8861
|
|
--- /dev/null
|
|
+++ b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEProvider.java
|
|
@@ -0,0 +1,338 @@
|
|
+/*
|
|
+ * 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.BufferedInputStream;
|
|
+import java.io.File;
|
|
+import java.io.FileInputStream;
|
|
+import java.io.InputStream;
|
|
+import java.io.IOException;
|
|
+import java.nio.file.Files;
|
|
+import java.nio.file.Path;
|
|
+import java.nio.file.Paths;
|
|
+import java.nio.file.StandardOpenOption;
|
|
+import java.util.Date;
|
|
+import java.util.Properties;
|
|
+import java.security.Provider;
|
|
+
|
|
+import static sun.security.util.SecurityConstants.PROVIDER_VER;
|
|
+
|
|
+/**
|
|
+ * KAE Provider
|
|
+ */
|
|
+public class KAEProvider extends Provider {
|
|
+
|
|
+ private static final long serialVersionUID = -9077316390050005439L;
|
|
+
|
|
+ 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 Properties getProp() {
|
|
+ Properties props = new Properties();
|
|
+ String sep = File.separator;
|
|
+ File propFile = new File(System.getProperty("java.home") + sep + "conf" + sep +
|
|
+ "kaeprovider.conf");
|
|
+ if (propFile.exists()) {
|
|
+ try (InputStream is = new BufferedInputStream(new FileInputStream(propFile))) {
|
|
+ props.load(is);
|
|
+ } catch (IOException e) {
|
|
+ e.printStackTrace();
|
|
+ }
|
|
+ }
|
|
+ return props;
|
|
+ }
|
|
+
|
|
+ public KAEProvider() {
|
|
+ super("KAEProvider", PROVIDER_VER, "KAE provider");
|
|
+ Properties props = getProp();
|
|
+ if (needLog && "true".equalsIgnoreCase(props.getProperty("kae.log"))) {
|
|
+ logStart(excp);
|
|
+ needLog = false; // Log only once
|
|
+ } else {
|
|
+ KAEProvider.excp = null; // Ignore exception.
|
|
+ }
|
|
+ if (!"false".equalsIgnoreCase(props.getProperty("kae.md5"))) {
|
|
+ putMD5();
|
|
+ }
|
|
+ if (!"false".equalsIgnoreCase(props.getProperty("kae.sha256"))) {
|
|
+ putSHA256();
|
|
+ }
|
|
+ if (!"false".equalsIgnoreCase(props.getProperty("kae.sha384"))) {
|
|
+ putSHA384();
|
|
+ }
|
|
+ if (!"false".equalsIgnoreCase(props.getProperty("kae.sm3"))) {
|
|
+ putSM3();
|
|
+ }
|
|
+ if (!"false".equalsIgnoreCase(props.getProperty("kae.aes"))) {
|
|
+ putAES();
|
|
+ }
|
|
+ if (!"false".equalsIgnoreCase(props.getProperty("kae.sm4"))) {
|
|
+ putSM4();
|
|
+ }
|
|
+ if (!"false".equalsIgnoreCase(props.getProperty("kae.hmac"))) {
|
|
+ putHMAC();
|
|
+ }
|
|
+ if (!"false".equalsIgnoreCase(props.getProperty("kae.rsa"))) {
|
|
+ putRSA();
|
|
+ putSignatureRSA();
|
|
+ }
|
|
+ if (!"false".equalsIgnoreCase(props.getProperty("kae.dh"))) {
|
|
+ putDH();
|
|
+ }
|
|
+ if (!"false".equalsIgnoreCase(props.getProperty("kae.ec"))) {
|
|
+ putEC();
|
|
+ }
|
|
+ }
|
|
+
|
|
+ private void putAES() {
|
|
+ final String blockModes = "ECB|CBC|CTR|GCM";
|
|
+ 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/GCM/NoPadding", "org.openeuler.security.openssl.KAEAESCipher$Aes$Gcm$NoPadding");
|
|
+ put("Alg.Alias.Cipher.AES/GCM/PKCS5Padding", "AES/GCM/NoPadding"); // PKCS5Padding -> 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_128/GCM/NoPadding", "org.openeuler.security.openssl.KAEAESCipher$Aes_128$Gcm$NoPadding");
|
|
+ put("Alg.Alias.Cipher.AES_128/GCM/PKCS5Padding", "AES/GCM/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_192/GCM/NoPadding", "org.openeuler.security.openssl.KAEAESCipher$Aes_192$Gcm$NoPadding");
|
|
+ put("Alg.Alias.Cipher.AES_192/GCM/PKCS5Padding", "AES/GCM/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");
|
|
+ put("Cipher.AES_256/GCM/NoPadding", "org.openeuler.security.openssl.KAEAESCipher$Aes_256$Gcm$NoPadding");
|
|
+ put("Alg.Alias.Cipher.AES_256/GCM/PKCS5Padding", "AES/GCM/NoPadding");
|
|
+ }
|
|
+
|
|
+ private void putMD5() {
|
|
+ put("MessageDigest.MD5", "org.openeuler.security.openssl.KAEDigest$MD5");
|
|
+ }
|
|
+
|
|
+ private void putSHA256() {
|
|
+ put("MessageDigest.SHA-256", "org.openeuler.security.openssl.KAEDigest$SHA256");
|
|
+ }
|
|
+
|
|
+ private void putSHA384() {
|
|
+ put("MessageDigest.SHA-384", "org.openeuler.security.openssl.KAEDigest$SHA384");
|
|
+ }
|
|
+
|
|
+ private void putSM3() {
|
|
+ put("MessageDigest.SM3", "org.openeuler.security.openssl.KAEDigest$SM3");
|
|
+ }
|
|
+
|
|
+ private void putSM4() {
|
|
+ final String blockModes = "ECB|CBC|CTR|OFB";
|
|
+ final String blockPads = "NOPADDING|PKCS5PADDING";
|
|
+
|
|
+ put("Cipher.SM4 SupportedModes", blockModes);
|
|
+ put("Cipher.SM4 SupportedPaddings", blockPads);
|
|
+ put("Cipher.SM4", "org.openeuler.security.openssl.KAESM4Cipher$Sm4$Ecb$PKCS5Padding");
|
|
+
|
|
+ put("Cipher.SM4/CBC/PKCS5Padding", "org.openeuler.security.openssl.KAESM4Cipher$Sm4$Cbc$PKCS5Padding");
|
|
+ put("Cipher.SM4/CBC/NoPadding", "org.openeuler.security.openssl.KAESM4Cipher$Sm4$Cbc$NoPadding");
|
|
+ put("Alg.Alias.Cipher.SM4/CBC/PKCS7Padding", "SM4/CBC/PKCS5Padding");
|
|
+ put("Cipher.SM4/ECB/NoPadding", "org.openeuler.security.openssl.KAESM4Cipher$Sm4$Ecb$NoPadding");
|
|
+ put("Cipher.SM4/ECB/PKCS5Padding", "org.openeuler.security.openssl.KAESM4Cipher$Sm4$Ecb$PKCS5Padding");
|
|
+ put("Alg.Alias.Cipher.SM4/ECB/PKCS7Padding", "SM4/ECB/PKCS5Padding");
|
|
+ put("Cipher.SM4/CTR/NoPadding", "org.openeuler.security.openssl.KAESM4Cipher$Sm4$Ctr$NoPadding");
|
|
+ put("Cipher.SM4/OFB/NoPadding", "org.openeuler.security.openssl.KAESM4Cipher$Sm4$Ofb$NoPadding");
|
|
+ put("Cipher.SM4/OFB/PKCS5Padding", "org.openeuler.security.openssl.KAESM4Cipher$Sm4$Ofb$PKCS5Padding");
|
|
+ put("Alg.Alias.Cipher.SM4/OFB/PKCS7Padding", "SM4/OFB/PKCS5Padding");
|
|
+
|
|
+ put("KeyGenerator.SM4", "com.sun.crypto.provider.AESKeyGenerator");
|
|
+ put("AlgorithmParameters.SM4", "com.sun.crypto.provider.AESParameters");
|
|
+ }
|
|
+
|
|
+ private void putRSA() {
|
|
+ // 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 putHMAC() {
|
|
+ put("MAC.HmacMD5", "org.openeuler.security.openssl.KAEHMac$HmacMD5");
|
|
+ put("MAC.HmacSHA1", "org.openeuler.security.openssl.KAEHMac$HmacSHA1");
|
|
+ put("MAC.HmacSHA224", "org.openeuler.security.openssl.KAEHMac$HmacSHA224");
|
|
+ put("MAC.HmacSHA256", "org.openeuler.security.openssl.KAEHMac$HmacSHA256");
|
|
+ put("MAC.HmacSHA384", "org.openeuler.security.openssl.KAEHMac$HmacSHA384");
|
|
+ put("MAC.HmacSHA512", "org.openeuler.security.openssl.KAEHMac$HmacSHA512");
|
|
+ }
|
|
+
|
|
+ private void putDH() {
|
|
+ put("KeyPairGenerator.DiffieHellman", "org.openeuler.security.openssl.KAEDHKeyPairGenerator");
|
|
+ put("Alg.Alias.KeyPairGenerator.DH", "DiffieHellman");
|
|
+ put("KeyAgreement.DiffieHellman", "org.openeuler.security.openssl.KAEDHKeyAgreement");
|
|
+ put("Alg.Alias.KeyAgreement.DH", "DiffieHellman");
|
|
+ }
|
|
+
|
|
+ private void putSignatureRSA() {
|
|
+ put("Signature.MD5withRSA",
|
|
+ "org.openeuler.security.openssl.KAERSASignature$MD5withRSA");
|
|
+ put("Signature.SHA1withRSA",
|
|
+ "org.openeuler.security.openssl.KAERSASignature$SHA1withRSA");
|
|
+ put("Signature.SHA224withRSA",
|
|
+ "org.openeuler.security.openssl.KAERSASignature$SHA224withRSA");
|
|
+ put("Signature.SHA256withRSA",
|
|
+ "org.openeuler.security.openssl.KAERSASignature$SHA256withRSA");
|
|
+ put("Signature.SHA384withRSA",
|
|
+ "org.openeuler.security.openssl.KAERSASignature$SHA384withRSA");
|
|
+ put("Signature.SHA512withRSA",
|
|
+ "org.openeuler.security.openssl.KAERSASignature$SHA512withRSA");
|
|
+
|
|
+ // alias
|
|
+ put("Alg.Alias.Signature.1.2.840.113549.1.1.4", "MD5withRSA");
|
|
+ put("Alg.Alias.Signature.OID.1.2.840.113549.1.1.4", "MD5withRSA");
|
|
+
|
|
+ put("Alg.Alias.Signature.1.2.840.113549.1.1.5", "SHA1withRSA");
|
|
+ put("Alg.Alias.Signature.OID.1.2.840.113549.1.1.5", "SHA1withRSA");
|
|
+ put("Alg.Alias.Signature.1.3.14.3.2.29", "SHA1withRSA");
|
|
+
|
|
+ put("Alg.Alias.Signature.1.2.840.113549.1.1.14", "SHA224withRSA");
|
|
+ put("Alg.Alias.Signature.OID.1.2.840.113549.1.1.14", "SHA224withRSA");
|
|
+
|
|
+ put("Alg.Alias.Signature.1.2.840.113549.1.1.11", "SHA256withRSA");
|
|
+ put("Alg.Alias.Signature.OID.1.2.840.113549.1.1.11", "SHA256withRSA");
|
|
+
|
|
+ put("Alg.Alias.Signature.1.2.840.113549.1.1.12", "SHA384withRSA");
|
|
+ put("Alg.Alias.Signature.OID.1.2.840.113549.1.1.12", "SHA384withRSA");
|
|
+
|
|
+ put("Alg.Alias.Signature.1.2.840.113549.1.1.13", "SHA512withRSA");
|
|
+ put("Alg.Alias.Signature.OID.1.2.840.113549.1.1.13", "SHA512withRSA");
|
|
+
|
|
+ put("Signature.RSASSA-PSS", "org.openeuler.security.openssl.KAERSAPSSSignature");
|
|
+
|
|
+ put("Alg.Alias.Signature.1.2.840.113549.1.1.10", "RSASSA-PSS");
|
|
+ put("Alg.Alias.Signature.OID.1.2.840.113549.1.1.10", "RSASSA-PSS");
|
|
+
|
|
+ // attributes for supported key classes
|
|
+ String rsaKeyClasses = "java.security.interfaces.RSAPublicKey" +
|
|
+ "|java.security.interfaces.RSAPrivateKey";
|
|
+ put("Signature.MD5withRSA SupportedKeyClasses", rsaKeyClasses);
|
|
+ put("Signature.SHA1withRSA SupportedKeyClasses", rsaKeyClasses);
|
|
+ put("Signature.SHA224withRSA SupportedKeyClasses", rsaKeyClasses);
|
|
+ put("Signature.SHA256withRSA SupportedKeyClasses", rsaKeyClasses);
|
|
+ put("Signature.SHA384withRSA SupportedKeyClasses", rsaKeyClasses);
|
|
+ put("Signature.SHA512withRSA SupportedKeyClasses", rsaKeyClasses);
|
|
+ put("Signature.RSASSA-PSS SupportedKeyClasses", rsaKeyClasses);
|
|
+ }
|
|
+
|
|
+ private void putEC() {
|
|
+ put("KeyPairGenerator.EC", "org.openeuler.security.openssl.KAEECKeyPairGenerator");
|
|
+ put("Alg.Alias.KeyPairGenerator.EllipticCurve", "EC");
|
|
+ put("KeyAgreement.ECDH", "org.openeuler.security.openssl.KAEECDHKeyAgreement");
|
|
+ }
|
|
+ // init openssl
|
|
+ static native void initOpenssl() throws RuntimeException;
|
|
+}
|
|
diff --git a/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAERSACipher.java b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAERSACipher.java
|
|
new file mode 100644
|
|
index 000000000..0935ebb23
|
|
--- /dev/null
|
|
+++ b/src/jdk.crypto.kaeprovider/linux/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
|
|
+ @SuppressWarnings("deprecation")
|
|
+ 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
|
|
+ @SuppressWarnings("deprecation")
|
|
+ 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);
|
|
+ try {
|
|
+ return 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());
|
|
+ } catch (Exception e) {
|
|
+ throw new InvalidKeyException(e);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ private long getKeyAddress(RSAPublicKey key) throws InvalidKeyException {
|
|
+ checkKey(key);
|
|
+ try {
|
|
+ return nativeCreateRSAPublicKey(
|
|
+ key.getModulus().toByteArray(),
|
|
+ key.getPublicExponent().toByteArray()
|
|
+ );
|
|
+ } catch (Exception e) {
|
|
+ throw new InvalidKeyException(e);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ private void checkKey(RSAPrivateCrtKey key) throws InvalidKeyException {
|
|
+ boolean isInValidKey = key.getModulus() == null
|
|
+ || key.getPublicExponent() == null
|
|
+ || key.getPrivateExponent() == null
|
|
+ || key.getPrimeP() == null
|
|
+ || key.getPrimeQ() == null
|
|
+ || key.getPrimeExponentP() == null
|
|
+ || key.getPrimeExponentQ() == null
|
|
+ || key.getCrtCoefficient() == null;
|
|
+ if (isInValidKey) {
|
|
+ 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/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAERSAKeyPairGenerator.java b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAERSAKeyPairGenerator.java
|
|
new file mode 100644
|
|
index 000000000..51d7a95eb
|
|
--- /dev/null
|
|
+++ b/src/jdk.crypto.kaeprovider/linux/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/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAERSAPSSSignature.java b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAERSAPSSSignature.java
|
|
new file mode 100644
|
|
index 000000000..65c4e0382
|
|
--- /dev/null
|
|
+++ b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAERSAPSSSignature.java
|
|
@@ -0,0 +1,713 @@
|
|
+/*
|
|
+ * Copyright (c) 2018, 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 java.io.IOException;
|
|
+import java.lang.reflect.Constructor;
|
|
+import java.lang.reflect.InvocationTargetException;
|
|
+import java.lang.reflect.Method;
|
|
+import java.nio.ByteBuffer;
|
|
+
|
|
+import java.security.*;
|
|
+import java.security.spec.AlgorithmParameterSpec;
|
|
+import java.security.spec.PSSParameterSpec;
|
|
+import java.security.spec.MGF1ParameterSpec;
|
|
+import java.security.interfaces.*;
|
|
+
|
|
+import java.util.Arrays;
|
|
+import java.util.HashSet;
|
|
+import java.util.Locale;
|
|
+import java.util.Set;
|
|
+
|
|
+import sun.security.rsa.PSSParameters;
|
|
+import sun.security.rsa.RSACore;
|
|
+import sun.security.jca.JCAUtil;
|
|
+
|
|
+import javax.crypto.BadPaddingException;
|
|
+
|
|
+/**
|
|
+ * PKCS#1 v2.2 RSASSA-PSS signatures with various message digest algorithms.
|
|
+ * RSASSA-PSS implementation takes the message digest algorithm, MGF algorithm,
|
|
+ * and salt length values through the required signature PSS parameters.
|
|
+ * We support SHA-1, SHA-224, SHA-256, SHA-384, SHA-512.
|
|
+ * The Openssl does not support rsa signatures with SHA-512/224 and SHA-512/256 as the digest algorithm,
|
|
+ * so we have not implemented them.
|
|
+ * The Openssl does not support non-CRT private key , when signing with a non-CRT private key, we use the sun sign.
|
|
+ */
|
|
+@SuppressWarnings("deprecation")
|
|
+public class KAERSAPSSSignature extends SignatureSpi {
|
|
+ // openssl unsupport rsa sign with digest algorithm
|
|
+ private static final Set<String> UNSUPPORTED_DIGEST_ALGORITHM = new HashSet<>(
|
|
+ Arrays.asList("SHA-512/224", "SHA-512/256"));
|
|
+
|
|
+ private static Method generateAndXorMethod;
|
|
+
|
|
+ private static Constructor<?> mgf1Constructor;
|
|
+
|
|
+ private static final byte[] EIGHT_BYTES_OF_ZEROS = new byte[8];
|
|
+
|
|
+ private static Exception exception;
|
|
+
|
|
+ static {
|
|
+ AccessController.doPrivileged(new PrivilegedAction<Void>() {
|
|
+ @Override
|
|
+ public Void run() {
|
|
+ try {
|
|
+ Class<?> mgf1Class = Class.forName("sun.security.rsa.MGF1");
|
|
+ generateAndXorMethod = mgf1Class.getDeclaredMethod("generateAndXor",
|
|
+ byte[].class, int.class, int.class, int.class, byte[].class, int.class);
|
|
+ generateAndXorMethod.setAccessible(true);
|
|
+ mgf1Constructor = mgf1Class.getDeclaredConstructor(String.class);
|
|
+ mgf1Constructor.setAccessible(true);
|
|
+ } catch (ClassNotFoundException | NoSuchMethodException e) {
|
|
+ exception = e;
|
|
+ }
|
|
+ return null;
|
|
+ }
|
|
+ });
|
|
+ }
|
|
+
|
|
+ // message digest implementation we use for hashing the data
|
|
+ private MessageDigest md;
|
|
+
|
|
+ // flag indicating whether the digest is reset
|
|
+ private boolean digestReset = true;
|
|
+
|
|
+ // private key, if initialized for signing
|
|
+ private RSAPrivateKey privKey = null;
|
|
+
|
|
+ // public key, if initialized for verifying
|
|
+ private RSAPublicKey pubKey = null;
|
|
+
|
|
+ // PSS parameters from signatures and keys respectively
|
|
+ private PSSParameterSpec sigParams = null;
|
|
+
|
|
+ // PRNG used to generate salt bytes if none given
|
|
+ private SecureRandom random;
|
|
+
|
|
+ /**
|
|
+ * Construct a new RSAPSSSignatur with arbitrary digest algorithm
|
|
+ */
|
|
+ public KAERSAPSSSignature() throws SignatureException {
|
|
+ if (exception != null) {
|
|
+ throw new SignatureException(exception.getMessage());
|
|
+ }
|
|
+ this.md = null;
|
|
+ }
|
|
+
|
|
+ // initialize for verification. See JCA doc
|
|
+ @Override
|
|
+ protected void engineInitVerify(PublicKey publicKey) throws InvalidKeyException {
|
|
+ if (!(publicKey instanceof RSAPublicKey)) {
|
|
+ throw new InvalidKeyException("key must be RSAPublicKey");
|
|
+ }
|
|
+ this.pubKey = (RSAPublicKey) isValid((RSAKey) publicKey);
|
|
+ this.privKey = null;
|
|
+ resetDigest();
|
|
+ }
|
|
+
|
|
+ // initialize for signing. See JCA doc
|
|
+ @Override
|
|
+ protected void engineInitSign(PrivateKey privateKey) throws InvalidKeyException {
|
|
+ engineInitSign(privateKey, null);
|
|
+ }
|
|
+
|
|
+ // initialize for signing. See JCA doc
|
|
+ @Override
|
|
+ protected void engineInitSign(PrivateKey privateKey, SecureRandom random) throws InvalidKeyException {
|
|
+ if (!(privateKey instanceof RSAPrivateKey)) {
|
|
+ throw new InvalidKeyException("key must be RSAPrivateKey");
|
|
+ }
|
|
+ this.privKey = (RSAPrivateKey) isValid((RSAKey) privateKey);
|
|
+ this.pubKey = null;
|
|
+ this.random =
|
|
+ (random == null ? JCAUtil.getSecureRandom() : random);
|
|
+ resetDigest();
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Utility method for checking the key PSS parameters against signature
|
|
+ * PSS parameters.
|
|
+ * Returns false if any of the digest/MGF algorithms and trailerField
|
|
+ * values does not match or if the salt length in key parameters is
|
|
+ * larger than the value in signature parameters.
|
|
+ */
|
|
+ private static boolean isCompatible(AlgorithmParameterSpec keyParams, PSSParameterSpec sigParams) {
|
|
+ if (keyParams == null) {
|
|
+ // key with null PSS parameters means no restriction
|
|
+ return true;
|
|
+ }
|
|
+ if (!(keyParams instanceof PSSParameterSpec)) {
|
|
+ return false;
|
|
+ }
|
|
+ // nothing to compare yet, defer the check to when sigParams is set
|
|
+ if (sigParams == null) {
|
|
+ return true;
|
|
+ }
|
|
+ PSSParameterSpec pssKeyParams = (PSSParameterSpec) keyParams;
|
|
+ // first check the salt length requirement
|
|
+ if (pssKeyParams.getSaltLength() > sigParams.getSaltLength()) {
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ // compare equality of the rest of fields based on DER encoding
|
|
+ PSSParameterSpec keyParams2 =
|
|
+ new PSSParameterSpec(pssKeyParams.getDigestAlgorithm(),
|
|
+ pssKeyParams.getMGFAlgorithm(),
|
|
+ pssKeyParams.getMGFParameters(),
|
|
+ sigParams.getSaltLength(),
|
|
+ pssKeyParams.getTrailerField());
|
|
+
|
|
+ // skip the JCA overhead
|
|
+ try {
|
|
+ byte[] encoded = PSSParameters.getEncoded(keyParams2);
|
|
+ byte[] encoded2 = PSSParameters.getEncoded(sigParams);
|
|
+ return Arrays.equals(encoded, encoded2);
|
|
+ } catch (IOException e) {
|
|
+ return false;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Validate the specified RSAKey and its associated parameters against
|
|
+ * internal signature parameters.
|
|
+ */
|
|
+ private RSAKey isValid(RSAKey rsaKey) throws InvalidKeyException {
|
|
+ try {
|
|
+ AlgorithmParameterSpec keyParams = rsaKey.getParams();
|
|
+ // validate key parameters
|
|
+ if (!isCompatible(rsaKey.getParams(), this.sigParams)) {
|
|
+ throw new InvalidKeyException
|
|
+ ("Key contains incompatible PSS parameter values");
|
|
+ }
|
|
+ // validate key length
|
|
+ if (this.sigParams != null) {
|
|
+ Integer hLen =
|
|
+ KAEUtils.getDigestLength(this.sigParams.getDigestAlgorithm());
|
|
+ if (hLen == null) {
|
|
+ throw new ProviderException("Unsupported digest algo: " +
|
|
+ this.sigParams.getDigestAlgorithm());
|
|
+ }
|
|
+ checkKeyLength(rsaKey, hLen, this.sigParams.getSaltLength());
|
|
+ }
|
|
+ return rsaKey;
|
|
+ } catch (SignatureException e) {
|
|
+ throw new InvalidKeyException(e);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Validate the specified Signature PSS parameters.
|
|
+ */
|
|
+ private PSSParameterSpec validateSigParams(AlgorithmParameterSpec p) throws InvalidAlgorithmParameterException {
|
|
+ if (p == null) {
|
|
+ throw new InvalidAlgorithmParameterException
|
|
+ ("Parameters cannot be null");
|
|
+ }
|
|
+ if (!(p instanceof PSSParameterSpec)) {
|
|
+ throw new InvalidAlgorithmParameterException
|
|
+ ("parameters must be type PSSParameterSpec");
|
|
+ }
|
|
+ // no need to validate again if same as current signature parameters
|
|
+ PSSParameterSpec params = (PSSParameterSpec) p;
|
|
+ if (params == this.sigParams) {
|
|
+ return params;
|
|
+ }
|
|
+
|
|
+ RSAKey key = (this.privKey == null ? this.pubKey : this.privKey);
|
|
+ // check against keyParams if set
|
|
+ if (key != null) {
|
|
+ if (!isCompatible(key.getParams(), params)) {
|
|
+ throw new InvalidAlgorithmParameterException
|
|
+ ("Signature parameters does not match key parameters");
|
|
+ }
|
|
+ }
|
|
+ // now sanity check the parameter values
|
|
+ if (!(params.getMGFAlgorithm().equalsIgnoreCase("MGF1"))) {
|
|
+ throw new InvalidAlgorithmParameterException("Only supports MGF1");
|
|
+ }
|
|
+ if (params.getTrailerField() != PSSParameterSpec.TRAILER_FIELD_BC) {
|
|
+ throw new InvalidAlgorithmParameterException("Only supports TrailerFieldBC(1)");
|
|
+ }
|
|
+ String digestAlgo = params.getDigestAlgorithm();
|
|
+ // check key length again
|
|
+ if (key != null) {
|
|
+ try {
|
|
+ int hLen = KAEUtils.getDigestLength(digestAlgo);
|
|
+ checkKeyLength(key, hLen, params.getSaltLength());
|
|
+ } catch (SignatureException e) {
|
|
+ throw new InvalidAlgorithmParameterException(e);
|
|
+ }
|
|
+ }
|
|
+ return params;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Ensure the object is initialized with key and parameters and
|
|
+ * reset digest
|
|
+ */
|
|
+ private void ensureInit() throws SignatureException {
|
|
+ RSAKey key = (this.privKey == null ? this.pubKey : this.privKey);
|
|
+ if (key == null) {
|
|
+ throw new SignatureException("Missing key");
|
|
+ }
|
|
+ if (this.sigParams == null) {
|
|
+ // Parameters are required for signature verification
|
|
+ throw new SignatureException
|
|
+ ("Parameters required for RSASSA-PSS signatures");
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Utility method for checking key length against digest length and
|
|
+ * salt length
|
|
+ */
|
|
+ private static void checkKeyLength(RSAKey key, int digestLen, int saltLen) throws SignatureException {
|
|
+ if (key != null) {
|
|
+ int keyLength = getKeyLengthInBits(key) >> 3;
|
|
+ int minLength = Math.addExact(Math.addExact(digestLen, saltLen), 2);
|
|
+ if (keyLength < minLength) {
|
|
+ throw new SignatureException
|
|
+ ("Key is too short, need min " + minLength);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Reset the message digest if it is not already reset.
|
|
+ */
|
|
+ private void resetDigest() {
|
|
+ if (digestReset == false) {
|
|
+ this.md.reset();
|
|
+ digestReset = true;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Return the message digest value.
|
|
+ */
|
|
+ private byte[] getDigestValue() {
|
|
+ digestReset = true;
|
|
+ return this.md.digest();
|
|
+ }
|
|
+
|
|
+ // update the signature with the plaintext data. See JCA doc
|
|
+ @Override
|
|
+ protected void engineUpdate(byte b) throws SignatureException {
|
|
+ ensureInit();
|
|
+ this.md.update(b);
|
|
+ digestReset = false;
|
|
+ }
|
|
+
|
|
+ // update the signature with the plaintext data. See JCA doc
|
|
+ @Override
|
|
+ protected void engineUpdate(byte[] b, int off, int len) throws SignatureException {
|
|
+ ensureInit();
|
|
+ this.md.update(b, off, len);
|
|
+ digestReset = false;
|
|
+ }
|
|
+
|
|
+ // update the signature with the plaintext data. See JCA doc
|
|
+ @Override
|
|
+ protected void engineUpdate(ByteBuffer b) {
|
|
+ try {
|
|
+ ensureInit();
|
|
+ } catch (SignatureException se) {
|
|
+ // hack for working around API bug
|
|
+ throw new RuntimeException(se.getMessage());
|
|
+ }
|
|
+ this.md.update(b);
|
|
+ digestReset = false;
|
|
+ }
|
|
+
|
|
+ // determine whether the digest is valid
|
|
+ private boolean isValidDigest() {
|
|
+ String digestName = this.md.getAlgorithm();
|
|
+ if (UNSUPPORTED_DIGEST_ALGORITHM.contains(digestName.toUpperCase(Locale.ROOT))) {
|
|
+ return false;
|
|
+ }
|
|
+ AlgorithmParameterSpec mgfParams = this.sigParams.getMGFParameters();
|
|
+ String mgfDigestName = "";
|
|
+ if (mgfParams != null) {
|
|
+ mgfDigestName =
|
|
+ ((MGF1ParameterSpec) mgfParams).getDigestAlgorithm();
|
|
+ }
|
|
+ return !UNSUPPORTED_DIGEST_ALGORITHM.contains(mgfDigestName.toUpperCase(Locale.ROOT));
|
|
+ }
|
|
+
|
|
+ // determine whether use kae sign
|
|
+ private boolean useKaeSign() {
|
|
+ return (privKey instanceof RSAPrivateCrtKey) && isValidDigest();
|
|
+ }
|
|
+
|
|
+ // sun sign
|
|
+ private byte[] sunSign(byte[] mHash) throws SignatureException {
|
|
+ try {
|
|
+ byte[] encoded = encodeSignature(mHash);
|
|
+ return RSACore.rsa(encoded, privKey, true);
|
|
+ } catch (GeneralSecurityException e) {
|
|
+ throw new SignatureException("Could not sign data", e);
|
|
+ } catch (IOException e) {
|
|
+ throw new SignatureException("Could not encode data", e);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ // kae sign
|
|
+ private byte[] kaeSign(byte[] mHash) throws SignatureException {
|
|
+ String kaeDigestName = KAEUtils.getKAEDigestName(this.sigParams.getDigestAlgorithm());
|
|
+ String mgfDigestName = kaeDigestName;
|
|
+ AlgorithmParameterSpec mgfParams = this.sigParams.getMGFParameters();
|
|
+ if (mgfParams != null) {
|
|
+ mgfDigestName =
|
|
+ ((MGF1ParameterSpec) mgfParams).getDigestAlgorithm();
|
|
+ }
|
|
+ String mgf1DigestName = KAEUtils.getKAEDigestName(mgfDigestName);
|
|
+
|
|
+ RSAPrivateCrtKey privateCrtKey = (RSAPrivateCrtKey) privKey;
|
|
+ long keyAddress = KAERSACipher.nativeCreateRSAPrivateCrtKey(
|
|
+ privateCrtKey.getModulus().toByteArray(),
|
|
+ privateCrtKey.getPublicExponent().toByteArray(),
|
|
+ privateCrtKey.getPrivateExponent().toByteArray(),
|
|
+ privateCrtKey.getPrimeP().toByteArray(),
|
|
+ privateCrtKey.getPrimeQ().toByteArray(),
|
|
+ privateCrtKey.getPrimeExponentP().toByteArray(),
|
|
+ privateCrtKey.getPrimeExponentQ().toByteArray(),
|
|
+ privateCrtKey.getCrtCoefficient().toByteArray());
|
|
+ byte[] bytes;
|
|
+ try {
|
|
+ bytes = KAERSASignatureNative.pssSign(keyAddress, kaeDigestName, mHash,
|
|
+ KAERSAPaddingType.PKCS1PssPadding.getId(),
|
|
+ mgf1DigestName, this.sigParams.getSaltLength());
|
|
+ } catch (SignatureException e) {
|
|
+ throw e;
|
|
+ } finally {
|
|
+ KAERSACipher.nativeFreeKey(keyAddress);
|
|
+ }
|
|
+ return bytes;
|
|
+ }
|
|
+
|
|
+ // sign the data and return the signature. See JCA doc
|
|
+ @Override
|
|
+ protected byte[] engineSign() throws SignatureException {
|
|
+ ensureInit();
|
|
+ byte[] mHash = getDigestValue();
|
|
+ if (useKaeSign()) {
|
|
+ return kaeSign(mHash);
|
|
+ }
|
|
+ return sunSign(mHash);
|
|
+ }
|
|
+
|
|
+ // determine whether use kae verify
|
|
+ private boolean useKaeVerify() {
|
|
+ return isValidDigest();
|
|
+ }
|
|
+
|
|
+ // sun verify
|
|
+ private boolean sunVerify(byte[] mHash, byte[] sigBytes) throws SignatureException {
|
|
+ try {
|
|
+ byte[] decrypted = RSACore.rsa(sigBytes, this.pubKey);
|
|
+ return decodeSignature(mHash, decrypted);
|
|
+ } catch (javax.crypto.BadPaddingException e) {
|
|
+ // occurs if the app has used the wrong RSA public key
|
|
+ // or if sigBytes is invalid
|
|
+ // return false rather than propagating the exception for
|
|
+ // compatibility/ease of use
|
|
+ return false;
|
|
+ } catch (IOException e) {
|
|
+ throw new SignatureException("Signature encoding error", e);
|
|
+ } finally {
|
|
+ resetDigest();
|
|
+ }
|
|
+ }
|
|
+
|
|
+ // kae verify
|
|
+ private boolean kaeVerify(byte[] mHash, byte[] sigBytes) throws SignatureException {
|
|
+ String kaeDigestName = KAEUtils.getKAEDigestName(this.sigParams.getDigestAlgorithm());
|
|
+ String mgfDigestName = kaeDigestName;
|
|
+ AlgorithmParameterSpec mgfParams = this.sigParams.getMGFParameters();
|
|
+ if (mgfParams != null) {
|
|
+ mgfDigestName =
|
|
+ ((MGF1ParameterSpec) mgfParams).getDigestAlgorithm();
|
|
+ }
|
|
+ String mgf1KaeDigestName = KAEUtils.getKAEDigestName(mgfDigestName);
|
|
+
|
|
+ long keyAddress = KAERSACipher.nativeCreateRSAPublicKey(this.pubKey.getModulus().toByteArray(),
|
|
+ this.pubKey.getPublicExponent().toByteArray());
|
|
+ boolean verify;
|
|
+ try {
|
|
+ verify = KAERSASignatureNative.pssVerify(keyAddress, kaeDigestName, mHash,
|
|
+ KAERSAPaddingType.PKCS1PssPadding.getId(), mgf1KaeDigestName,
|
|
+ this.sigParams.getSaltLength(), sigBytes);
|
|
+ } catch (SignatureException e) {
|
|
+ throw e;
|
|
+ } catch (BadPaddingException e) {
|
|
+ // occurs if the app has used the wrong RSA public key
|
|
+ // or if sigBytes is invalid or sourceBytes is invalid
|
|
+ // return false rather than propagating the exception for
|
|
+ // compatibility/ease of use
|
|
+ return false;
|
|
+ } finally {
|
|
+ resetDigest();
|
|
+ KAERSACipher.nativeFreeKey(keyAddress);
|
|
+ }
|
|
+ return verify;
|
|
+ }
|
|
+
|
|
+ // verify the data and return the result. See JCA doc
|
|
+ // should be reset to the state after engineInitVerify call.
|
|
+ @Override
|
|
+ protected boolean engineVerify(byte[] sigBytes) throws SignatureException {
|
|
+ ensureInit();
|
|
+ if (sigBytes.length != RSACore.getByteLength(this.pubKey)) {
|
|
+ throw new SignatureException("Signature length not correct: got " +
|
|
+ sigBytes.length + " but was expecting " +
|
|
+ RSACore.getByteLength(this.pubKey));
|
|
+ }
|
|
+ byte[] mHash = getDigestValue();
|
|
+ if (useKaeVerify()) {
|
|
+ return kaeVerify(mHash, sigBytes);
|
|
+ }
|
|
+ return sunVerify(mHash, sigBytes);
|
|
+ }
|
|
+
|
|
+ // return the modulus length in bits
|
|
+ private static int getKeyLengthInBits(RSAKey k) {
|
|
+ if (k != null) {
|
|
+ return k.getModulus().bitLength();
|
|
+ }
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Encode the digest 'mHash', return the to-be-signed data.
|
|
+ * Also used by the PKCS#11 provider.
|
|
+ */
|
|
+ private byte[] encodeSignature(byte[] mHash) throws IOException, DigestException {
|
|
+ AlgorithmParameterSpec mgfParams = this.sigParams.getMGFParameters();
|
|
+ String mgfDigestAlgo;
|
|
+ if (mgfParams != null) {
|
|
+ mgfDigestAlgo =
|
|
+ ((MGF1ParameterSpec) mgfParams).getDigestAlgorithm();
|
|
+ } else {
|
|
+ mgfDigestAlgo = this.md.getAlgorithm();
|
|
+ }
|
|
+ try {
|
|
+ int emBits = getKeyLengthInBits(this.privKey) - 1;
|
|
+ int emLen = (emBits + 7) >> 3;
|
|
+ int hLen = this.md.getDigestLength();
|
|
+ int dbLen = emLen - hLen - 1;
|
|
+ int sLen = this.sigParams.getSaltLength();
|
|
+
|
|
+ // maps DB into the corresponding region of EM and
|
|
+ // stores its bytes directly into EM
|
|
+ byte[] em = new byte[emLen];
|
|
+
|
|
+ // step7 and some of step8
|
|
+ em[dbLen - sLen - 1] = (byte) 1; // set DB's padding2 into EM
|
|
+ em[em.length - 1] = (byte) 0xBC; // set trailer field of EM
|
|
+
|
|
+ if (!digestReset) {
|
|
+ throw new ProviderException("Digest should be reset");
|
|
+ }
|
|
+ // step5: generates M' using padding1, mHash, and salt
|
|
+ this.md.update(EIGHT_BYTES_OF_ZEROS);
|
|
+ digestReset = false; // mark digest as it now has data
|
|
+ this.md.update(mHash);
|
|
+ if (sLen != 0) {
|
|
+ // step4: generate random salt
|
|
+ byte[] salt = new byte[sLen];
|
|
+ this.random.nextBytes(salt);
|
|
+ this.md.update(salt);
|
|
+
|
|
+ // step8: set DB's salt into EM
|
|
+ System.arraycopy(salt, 0, em, dbLen - sLen, sLen);
|
|
+ }
|
|
+ // step6: generate H using M'
|
|
+ this.md.digest(em, dbLen, hLen); // set H field of EM
|
|
+ digestReset = true;
|
|
+
|
|
+ // step7 and 8 are already covered by the code which setting up
|
|
+ // EM as above
|
|
+
|
|
+ // step9 and 10: feed H into MGF and xor with DB in EM
|
|
+ Object mgf1 = mgf1Constructor.newInstance(mgfDigestAlgo);
|
|
+ generateAndXorMethod.invoke(mgf1, em, dbLen, hLen, dbLen, em, 0);
|
|
+ // step11: set the leftmost (8emLen - emBits) bits of the leftmost
|
|
+ // octet to 0
|
|
+ int numZeroBits = (emLen << 3) - emBits;
|
|
+ if (numZeroBits != 0) {
|
|
+ byte mask = (byte) (0xff >>> numZeroBits);
|
|
+ em[0] = (byte) (em[0] & mask);
|
|
+ }
|
|
+
|
|
+ // step12: em should now holds maskedDB || hash h || 0xBC
|
|
+ return em;
|
|
+ } catch (IllegalAccessException | InstantiationException | InvocationTargetException e) {
|
|
+ throw new IOException(e.toString());
|
|
+ }
|
|
+ }
|
|
+
|
|
+ private String getMgfDigestAlgo() {
|
|
+ String mgfDigestAlgo;
|
|
+ AlgorithmParameterSpec mgfParams = this.sigParams.getMGFParameters();
|
|
+ if (mgfParams != null) {
|
|
+ mgfDigestAlgo =
|
|
+ ((MGF1ParameterSpec) mgfParams).getDigestAlgorithm();
|
|
+ } else {
|
|
+ mgfDigestAlgo = this.md.getAlgorithm();
|
|
+ }
|
|
+ return mgfDigestAlgo;
|
|
+ }
|
|
+
|
|
+ private void generateAndXor(String mgfDigestAlgo, byte[] em, int dbLen, int hLen) throws IOException {
|
|
+ Object mgf1;
|
|
+ try {
|
|
+ mgf1 = mgf1Constructor.newInstance(mgfDigestAlgo);
|
|
+ generateAndXorMethod.invoke(mgf1, em, dbLen, hLen, dbLen, em, 0);
|
|
+ } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
|
|
+ throw new IOException(e.toString());
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Decode the signature data. Verify that the object identifier matches
|
|
+ * and return the message digest.
|
|
+ */
|
|
+ private boolean decodeSignature(byte[] mHash, byte[] em) throws IOException {
|
|
+ int hLen = mHash.length;
|
|
+ int sLen = this.sigParams.getSaltLength();
|
|
+ int emLen = em.length;
|
|
+ int emBits = getKeyLengthInBits(this.pubKey) - 1;
|
|
+
|
|
+ // step3
|
|
+ if (emLen < (hLen + sLen + 2)) {
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ // step4
|
|
+ if (em[emLen - 1] != (byte) 0xBC) {
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ // step6: check if the leftmost (8emLen - emBits) bits of the leftmost
|
|
+ // octet are 0
|
|
+ int numZeroBits = (emLen << 3) - emBits;
|
|
+ if (numZeroBits != 0) {
|
|
+ byte mask = (byte) (0xff << (8 - numZeroBits));
|
|
+ if ((em[0] & mask) != 0) {
|
|
+ return false;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ // step 7 and 8
|
|
+ int dbLen = emLen - hLen - 1;
|
|
+
|
|
+ // generateAndXor
|
|
+ String mgfDigestAlgo = getMgfDigestAlgo();
|
|
+ generateAndXor(mgfDigestAlgo, em, dbLen, hLen);
|
|
+
|
|
+ // step9: set the leftmost (8emLen - emBits) bits of the leftmost
|
|
+ // octet to 0
|
|
+ if (numZeroBits != 0) {
|
|
+ byte mask = (byte) (0xff >>> numZeroBits);
|
|
+ em[0] = (byte) (em[0] & mask);
|
|
+ }
|
|
+
|
|
+ // step10
|
|
+ int index = 0;
|
|
+ for (; index < dbLen - sLen - 1; index++) {
|
|
+ if (em[index] != 0) {
|
|
+ return false;
|
|
+ }
|
|
+ }
|
|
+ if (em[index] != 0x01) {
|
|
+ return false;
|
|
+ }
|
|
+ // step12 and 13
|
|
+ this.md.update(EIGHT_BYTES_OF_ZEROS);
|
|
+ digestReset = false;
|
|
+ this.md.update(mHash);
|
|
+ if (sLen > 0) {
|
|
+ this.md.update(em, (dbLen - sLen), sLen);
|
|
+ }
|
|
+ byte[] digest2 = this.md.digest();
|
|
+ digestReset = true;
|
|
+
|
|
+ // step14
|
|
+ byte[] digestInEM = Arrays.copyOfRange(em, dbLen, emLen - 1);
|
|
+ return MessageDigest.isEqual(digest2, digestInEM);
|
|
+ }
|
|
+
|
|
+ // set parameter, not supported. See JCA doc
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ protected void engineSetParameter(String param, Object value) throws InvalidParameterException {
|
|
+ throw new UnsupportedOperationException("setParameter() not supported");
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ protected void engineSetParameter(AlgorithmParameterSpec params) throws InvalidAlgorithmParameterException {
|
|
+ this.sigParams = validateSigParams(params);
|
|
+ // disallow changing parameters when digest has been used
|
|
+ if (!digestReset) {
|
|
+ throw new ProviderException
|
|
+ ("Cannot set parameters during operations");
|
|
+ }
|
|
+ String newHashAlg = this.sigParams.getDigestAlgorithm();
|
|
+ // re-allocate md if not yet assigned or algorithm changed
|
|
+ if ((this.md == null) ||
|
|
+ !(this.md.getAlgorithm().equalsIgnoreCase(newHashAlg))) {
|
|
+ try {
|
|
+ this.md = MessageDigest.getInstance(newHashAlg);
|
|
+ } catch (NoSuchAlgorithmException nsae) {
|
|
+ // should not happen as we pick default digest algorithm
|
|
+ throw new InvalidAlgorithmParameterException("Unsupported digest algorithm " + newHashAlg, nsae);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ // get parameter, not supported. See JCA doc
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ protected Object engineGetParameter(String param) throws InvalidParameterException {
|
|
+ throw new UnsupportedOperationException("getParameter() not supported");
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ protected AlgorithmParameters engineGetParameters() {
|
|
+ AlgorithmParameters ap = null;
|
|
+ if (this.sigParams != null) {
|
|
+ try {
|
|
+ ap = AlgorithmParameters.getInstance("RSASSA-PSS");
|
|
+ ap.init(this.sigParams);
|
|
+ } catch (GeneralSecurityException gse) {
|
|
+ throw new ProviderException(gse.getMessage());
|
|
+ }
|
|
+ }
|
|
+ return ap;
|
|
+ }
|
|
+}
|
|
+
|
|
diff --git a/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAERSAPaddingType.java b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAERSAPaddingType.java
|
|
new file mode 100644
|
|
index 000000000..022271d94
|
|
--- /dev/null
|
|
+++ b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAERSAPaddingType.java
|
|
@@ -0,0 +1,83 @@
|
|
+/*
|
|
+ * 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"))
|
|
+ ),
|
|
+
|
|
+ // PSS
|
|
+ PKCS1PssPadding(6, "RSA_PKCS1_PSS_PADDING");
|
|
+
|
|
+ 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/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAERSASignature.java b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAERSASignature.java
|
|
new file mode 100644
|
|
index 000000000..84893445d
|
|
--- /dev/null
|
|
+++ b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAERSASignature.java
|
|
@@ -0,0 +1,365 @@
|
|
+/*
|
|
+ * 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 java.io.IOException;
|
|
+import java.nio.ByteBuffer;
|
|
+
|
|
+import java.security.*;
|
|
+import java.security.interfaces.*;
|
|
+import java.security.spec.AlgorithmParameterSpec;
|
|
+
|
|
+import sun.security.rsa.RSACore;
|
|
+import sun.security.rsa.RSAKeyFactory;
|
|
+import sun.security.rsa.RSAPadding;
|
|
+import sun.security.rsa.RSAUtil;
|
|
+import sun.security.rsa.RSAUtil.KeyType;
|
|
+import sun.security.util.*;
|
|
+import sun.security.x509.AlgorithmId;
|
|
+
|
|
+import javax.crypto.BadPaddingException;
|
|
+
|
|
+/**
|
|
+ * We support support rsa signatures with MD2, MD5, SHA-1, SHA-224, SHA-256, SHA-384, SHA-512 as the digest algorithm.
|
|
+ * The Openssl does not support rsa signatures with SHA-512/224 and SHA-512/256 as the digest algorithm,
|
|
+ * so we have not implemented them.
|
|
+ * The Openssl does not support non-CRT private key , when signing with a non-CRT private key, we use the sun sign.
|
|
+ */
|
|
+public abstract class KAERSASignature extends SignatureSpi {
|
|
+ // we sign an ASN.1 SEQUENCE of AlgorithmId and digest
|
|
+ // it has the form 30:xx:30:xx:[digestOID]:05:00:04:xx:[digest]
|
|
+ // this means the encoded length is (8 + digestOID.length + digest.length)
|
|
+ private static final int BASE_LENGTH = 8;
|
|
+
|
|
+ private String digestAlgorithm;
|
|
+
|
|
+ // object identifier for the message digest algorithm used
|
|
+ private final ObjectIdentifier digestOID;
|
|
+
|
|
+ // length of the encoded signature blob
|
|
+ private final int encodedLength;
|
|
+
|
|
+ // message digest implementation we use
|
|
+ private final MessageDigest md;
|
|
+
|
|
+ // flag indicating whether the digest is reset
|
|
+ private boolean digestReset;
|
|
+
|
|
+ // private key, if initialized for signing
|
|
+ private RSAPrivateKey privateKey;
|
|
+
|
|
+ // public key, if initialized for verifying
|
|
+ private RSAPublicKey publicKey;
|
|
+
|
|
+ // padding to use, set when the initSign/initVerify is called
|
|
+ private RSAPadding padding;
|
|
+
|
|
+ /**
|
|
+ * Construct a new RSASignature. Used by subclasses.
|
|
+ */
|
|
+ KAERSASignature(String algorithm, ObjectIdentifier digestOID, int oidLength) {
|
|
+ this.digestAlgorithm = algorithm;
|
|
+ this.digestOID = digestOID;
|
|
+ try {
|
|
+ md = MessageDigest.getInstance(algorithm);
|
|
+ } catch (NoSuchAlgorithmException e) {
|
|
+ throw new ProviderException(e);
|
|
+ }
|
|
+ digestReset = true;
|
|
+ encodedLength = BASE_LENGTH + oidLength + md.getDigestLength();
|
|
+ }
|
|
+
|
|
+ // initialize for verification. See JCA doc
|
|
+ @Override
|
|
+ protected void engineInitVerify(PublicKey publicKey) throws InvalidKeyException {
|
|
+ RSAPublicKey rsaKey = (RSAPublicKey) RSAKeyFactory.toRSAKey(publicKey);
|
|
+ this.privateKey = null;
|
|
+ this.publicKey = rsaKey;
|
|
+ initCommon(rsaKey, null);
|
|
+ }
|
|
+
|
|
+ // initialize for signing. See JCA doc
|
|
+ @Override
|
|
+ protected void engineInitSign(PrivateKey privateKey) throws InvalidKeyException {
|
|
+ engineInitSign(privateKey, null);
|
|
+ }
|
|
+
|
|
+ // initialize for signing. See JCA doc
|
|
+ @Override
|
|
+ protected void engineInitSign(PrivateKey privateKey, SecureRandom random) throws InvalidKeyException {
|
|
+ RSAPrivateKey rsaKey =
|
|
+ (RSAPrivateKey) RSAKeyFactory.toRSAKey(privateKey);
|
|
+ this.privateKey = rsaKey;
|
|
+ this.publicKey = null;
|
|
+ initCommon(rsaKey, random);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Init code common to sign and verify.
|
|
+ */
|
|
+ private void initCommon(RSAKey rsaKey, SecureRandom random) throws InvalidKeyException {
|
|
+ try {
|
|
+ RSAUtil.checkParamsAgainstType(KeyType.RSA, rsaKey.getParams());
|
|
+ } catch (ProviderException e) {
|
|
+ throw new InvalidKeyException("Invalid key for RSA signatures", e);
|
|
+ }
|
|
+ resetDigest();
|
|
+ int keySize = RSACore.getByteLength(rsaKey);
|
|
+ try {
|
|
+ padding = RSAPadding.getInstance
|
|
+ (RSAPadding.PAD_BLOCKTYPE_1, keySize, random);
|
|
+ } catch (InvalidAlgorithmParameterException iape) {
|
|
+ throw new InvalidKeyException(iape.getMessage());
|
|
+ }
|
|
+ int maxDataSize = padding.getMaxDataSize();
|
|
+ if (encodedLength > maxDataSize) {
|
|
+ throw new InvalidKeyException
|
|
+ ("Key is too short for this signature algorithm");
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Reset the message digest if it is not already reset.
|
|
+ */
|
|
+ private void resetDigest() {
|
|
+ if (digestReset == false) {
|
|
+ md.reset();
|
|
+ digestReset = true;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Return the message digest value.
|
|
+ */
|
|
+ private byte[] getDigestValue() {
|
|
+ digestReset = true;
|
|
+ return md.digest();
|
|
+ }
|
|
+
|
|
+ // update the signature with the plaintext data. See JCA doc
|
|
+ @Override
|
|
+ protected void engineUpdate(byte b) throws SignatureException {
|
|
+ md.update(b);
|
|
+ digestReset = false;
|
|
+ }
|
|
+
|
|
+ // update the signature with the plaintext data. See JCA doc
|
|
+ @Override
|
|
+ protected void engineUpdate(byte[] b, int off, int len) throws SignatureException {
|
|
+ md.update(b, off, len);
|
|
+ digestReset = false;
|
|
+ }
|
|
+
|
|
+ // update the signature with the plaintext data. See JCA doc
|
|
+ @Override
|
|
+ protected void engineUpdate(ByteBuffer b) {
|
|
+ md.update(b);
|
|
+ digestReset = false;
|
|
+ }
|
|
+
|
|
+ // sign the data and return the signature. See JCA doc
|
|
+ @Override
|
|
+ protected byte[] engineSign() throws SignatureException {
|
|
+ if (privateKey == null) {
|
|
+ throw new SignatureException("Missing private key");
|
|
+ }
|
|
+
|
|
+ byte[] digest = getDigestValue();
|
|
+ if (useKaeSign()) {
|
|
+ return kaeSign(digest);
|
|
+ }
|
|
+ return sunSign(digest);
|
|
+ }
|
|
+
|
|
+ // determine if use kae sign , openssl do not support non-CRT private key
|
|
+ private boolean useKaeSign() {
|
|
+ return privateKey instanceof RSAPrivateCrtKey;
|
|
+ }
|
|
+
|
|
+ // sun sign
|
|
+ private byte[] sunSign(byte[] digest) throws SignatureException {
|
|
+ try {
|
|
+ byte[] encoded = encodeSignature(digestOID, digest);
|
|
+ byte[] padded = padding.pad(encoded);
|
|
+ return RSACore.rsa(padded, privateKey, true);
|
|
+ } catch (GeneralSecurityException e) {
|
|
+ throw new SignatureException("Could not sign data", e);
|
|
+ } catch (IOException e) {
|
|
+ throw new SignatureException("Could not encode data", e);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ // kae sign
|
|
+ private byte[] kaeSign(byte[] digest) throws SignatureException {
|
|
+ String kaeDigestName = KAEUtils.getKAEDigestName(this.digestAlgorithm);
|
|
+ RSAPrivateCrtKey privateCrtKey = (RSAPrivateCrtKey) privateKey;
|
|
+ long keyAddress = KAERSACipher.nativeCreateRSAPrivateCrtKey(
|
|
+ privateCrtKey.getModulus().toByteArray(),
|
|
+ privateCrtKey.getPublicExponent().toByteArray(),
|
|
+ privateCrtKey.getPrivateExponent().toByteArray(),
|
|
+ privateCrtKey.getPrimeP().toByteArray(),
|
|
+ privateCrtKey.getPrimeQ().toByteArray(),
|
|
+ privateCrtKey.getPrimeExponentP().toByteArray(),
|
|
+ privateCrtKey.getPrimeExponentQ().toByteArray(),
|
|
+ privateCrtKey.getCrtCoefficient().toByteArray());
|
|
+ byte[] sigBytes;
|
|
+ try {
|
|
+ sigBytes = KAERSASignatureNative.rsaSign(keyAddress,
|
|
+ kaeDigestName, digest, KAERSAPaddingType.PKCS1Padding.getId());
|
|
+ } catch (SignatureException e) {
|
|
+ throw e;
|
|
+ } finally {
|
|
+ // free keyAddress
|
|
+ KAERSACipher.nativeFreeKey(keyAddress);
|
|
+ }
|
|
+ return sigBytes;
|
|
+ }
|
|
+
|
|
+ // verify the data and return the result. See JCA doc
|
|
+ @Override
|
|
+ protected boolean engineVerify(byte[] sigBytes) throws SignatureException {
|
|
+ if (publicKey == null) {
|
|
+ throw new SignatureException("Missing public key");
|
|
+ }
|
|
+
|
|
+ boolean verify;
|
|
+ long keyAddress = 0L;
|
|
+ try {
|
|
+ if (sigBytes.length != RSACore.getByteLength(publicKey)) {
|
|
+ throw new SignatureException("Signature length not correct: got " +
|
|
+ sigBytes.length + " but was expecting " +
|
|
+ RSACore.getByteLength(publicKey));
|
|
+ }
|
|
+
|
|
+ String kaeDigestName = KAEUtils.getKAEDigestName(this.digestAlgorithm);
|
|
+ byte[] digest = getDigestValue();
|
|
+ keyAddress = KAERSACipher.nativeCreateRSAPublicKey(publicKey.getModulus().toByteArray(),
|
|
+ publicKey.getPublicExponent().toByteArray());
|
|
+ verify = KAERSASignatureNative.rsaVerify(keyAddress,
|
|
+ kaeDigestName, digest, KAERSAPaddingType.PKCS1Padding.getId(), sigBytes);
|
|
+ } catch (SignatureException e) {
|
|
+ throw e;
|
|
+ } catch (BadPaddingException e) {
|
|
+ // occurs if the app has used the wrong RSA public key
|
|
+ // or if sigBytes is invalid or sourceBytes is invalid
|
|
+ // return false rather than propagating the exception for
|
|
+ // compatibility/ease of use
|
|
+ return false;
|
|
+ } finally {
|
|
+ // reset digest
|
|
+ resetDigest();
|
|
+ // free keyAddress
|
|
+ if (keyAddress != 0L) {
|
|
+ KAERSACipher.nativeFreeKey(keyAddress);
|
|
+ }
|
|
+ }
|
|
+ return verify;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Encode the digest, return the to-be-signed data.
|
|
+ * Also used by the PKCS#11 provider.
|
|
+ */
|
|
+ public static byte[] encodeSignature(ObjectIdentifier oid, byte[] digest) throws IOException {
|
|
+ DerOutputStream out = new DerOutputStream();
|
|
+ new AlgorithmId(oid).encode(out);
|
|
+ out.putOctetString(digest);
|
|
+ DerValue result =
|
|
+ new DerValue(DerValue.tag_Sequence, out.toByteArray());
|
|
+ return result.toByteArray();
|
|
+ }
|
|
+
|
|
+ // set parameter, not supported. See JCA doc
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ protected void engineSetParameter(String param, Object value) throws InvalidParameterException {
|
|
+ throw new UnsupportedOperationException("setParameter() not supported");
|
|
+ }
|
|
+
|
|
+ // See JCA doc
|
|
+ @Override
|
|
+ protected void engineSetParameter(AlgorithmParameterSpec params) throws InvalidAlgorithmParameterException {
|
|
+ if (params != null) {
|
|
+ throw new InvalidAlgorithmParameterException("No parameters accepted");
|
|
+ }
|
|
+ }
|
|
+
|
|
+ // get parameter, not supported. See JCA doc
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ protected Object engineGetParameter(String param) throws InvalidParameterException {
|
|
+ throw new UnsupportedOperationException("getParameter() not supported");
|
|
+ }
|
|
+
|
|
+ // See JCA doc
|
|
+ @Override
|
|
+ protected AlgorithmParameters engineGetParameters() {
|
|
+ return null;
|
|
+ }
|
|
+
|
|
+ // Nested class for MD5withRSA signatures
|
|
+ public static final class MD5withRSA extends KAERSASignature {
|
|
+ public MD5withRSA() {
|
|
+ super("MD5", AlgorithmId.MD5_oid, 10);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ // Nested class for SHA1withRSA signatures
|
|
+ public static final class SHA1withRSA extends KAERSASignature {
|
|
+ public SHA1withRSA() {
|
|
+ super("SHA-1", AlgorithmId.SHA_oid, 7);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ // Nested class for SHA224withRSA signatures
|
|
+ public static final class SHA224withRSA extends KAERSASignature {
|
|
+ public SHA224withRSA() {
|
|
+ super("SHA-224", AlgorithmId.SHA224_oid, 11);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ // Nested class for SHA256withRSA signatures
|
|
+ public static final class SHA256withRSA extends KAERSASignature {
|
|
+ public SHA256withRSA() {
|
|
+ super("SHA-256", AlgorithmId.SHA256_oid, 11);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ // Nested class for SHA384withRSA signatures
|
|
+ public static final class SHA384withRSA extends KAERSASignature {
|
|
+ public SHA384withRSA() {
|
|
+ super("SHA-384", AlgorithmId.SHA384_oid, 11);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ // Nested class for SHA512withRSA signatures
|
|
+ public static final class SHA512withRSA extends KAERSASignature {
|
|
+ public SHA512withRSA() {
|
|
+ super("SHA-512", AlgorithmId.SHA512_oid, 11);
|
|
+ }
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAERSASignatureNative.java b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAERSASignatureNative.java
|
|
new file mode 100644
|
|
index 000000000..8f256ffe5
|
|
--- /dev/null
|
|
+++ b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAERSASignatureNative.java
|
|
@@ -0,0 +1,46 @@
|
|
+/*
|
|
+ * 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 javax.crypto.BadPaddingException;
|
|
+import java.security.SignatureException;
|
|
+
|
|
+public class KAERSASignatureNative {
|
|
+ // rsa sign
|
|
+ protected static native byte[] rsaSign(long keyAddress, String digestName, byte[] digestBytes, int paddingType)
|
|
+ throws SignatureException;
|
|
+
|
|
+ // rsa verify
|
|
+ protected static native boolean rsaVerify(long keyAddress, String digestName, byte[] digestBytes, int paddingType,
|
|
+ byte[] sigBytes) throws SignatureException, BadPaddingException;
|
|
+
|
|
+ // rsa pss sign
|
|
+ protected static native byte[] pssSign(long keyAddress, String digestName, byte[] digestBytes, int paddingType,
|
|
+ String mgf1DigestName, int saltLen) throws SignatureException;
|
|
+
|
|
+ // rsa pss verify
|
|
+ protected static native boolean pssVerify(long keyAddress, String digestName, byte[] digestBytes, int paddingType,
|
|
+ String mgf1DigestName, int saltLen, byte[] sigBytes) throws SignatureException, BadPaddingException;
|
|
+}
|
|
diff --git a/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAESM4Cipher.java b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAESM4Cipher.java
|
|
new file mode 100644
|
|
index 000000000..b189bea3a
|
|
--- /dev/null
|
|
+++ b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAESM4Cipher.java
|
|
@@ -0,0 +1,188 @@
|
|
+/*
|
|
+ * 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.security.InvalidAlgorithmParameterException;
|
|
+import java.security.InvalidKeyException;
|
|
+import java.security.NoSuchAlgorithmException;
|
|
+import java.security.Key;
|
|
+import java.util.Locale;
|
|
+
|
|
+import javax.crypto.NoSuchPaddingException;
|
|
+
|
|
+/*
|
|
+ * This class currently supports:
|
|
+ * - SM4/ECB/NOPADDING
|
|
+ * - SM4/ECB/PKCS5PADDING
|
|
+ * - SM4/CBC/NOPADDING
|
|
+ * - SM4/CBC/PKCS5PADDING
|
|
+ * - SM4/CTR/NOPADDING
|
|
+ * - SM4/OFB/NOPADDING
|
|
+ * - SM4/OFB/PKCS5PADDING
|
|
+ */
|
|
+abstract class KAESM4Cipher extends KAESymmetricCipherBase {
|
|
+
|
|
+ public static class Sm4 extends KAESM4Cipher {
|
|
+ public Sm4(Mode mode, Padding padding) {
|
|
+ super(mode, padding, 16);
|
|
+ }
|
|
+
|
|
+ public static class Cbc extends Sm4 {
|
|
+ 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 Sm4 {
|
|
+ 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 Sm4 {
|
|
+ public Ctr(Padding padding) {
|
|
+ super(Mode.CTR, padding);
|
|
+ }
|
|
+ public static class NoPadding extends Ctr {
|
|
+ public NoPadding() {
|
|
+ super(Padding.NOPADDING);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public static class Ofb extends Sm4 {
|
|
+ public Ofb(Padding padding) {
|
|
+ super(Mode.OFB, padding);
|
|
+ }
|
|
+ public static class NoPadding extends Ofb {
|
|
+ public NoPadding() {
|
|
+ super(Padding.NOPADDING);
|
|
+ }
|
|
+ }
|
|
+ public static class PKCS5Padding extends Ofb {
|
|
+ public PKCS5Padding() {
|
|
+ super(Padding.PKCS5PADDING);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ KAESM4Cipher(Mode mode, Padding padding, int fixedKeySize) {
|
|
+ super(mode, padding, fixedKeySize, "SM4");
|
|
+ }
|
|
+
|
|
+ protected void checkKey(Key key) throws InvalidKeyException {
|
|
+ if (key == null || key.getEncoded() == null) {
|
|
+ throw new InvalidKeyException("Key cannot be null");
|
|
+ } else {
|
|
+ int keyLen = key.getEncoded().length;
|
|
+ if (keyLen != fixedKeySize) {
|
|
+ throw new InvalidKeyException("Only " + fixedKeySize + "-byte keys are accepted. Got: " + keyLen);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ protected String getCipherName(int keyLength, Mode mode) {
|
|
+ return "sm4" + "-" + mode.toString().toLowerCase(Locale.US);
|
|
+ }
|
|
+
|
|
+ @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 if (modeStr.equalsIgnoreCase("OFB")) {
|
|
+ mode = Mode.OFB;
|
|
+ } 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("PKCS7PADDING")) {
|
|
+ paddingStr = "PKCS5Padding";
|
|
+ }
|
|
+
|
|
+ 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 " + paddingStr);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ protected void checkIvBytes(byte[] ivBytes) throws InvalidAlgorithmParameterException {
|
|
+ if (ivBytes == null) {
|
|
+ throw new InvalidAlgorithmParameterException("Wrong IV length: iv is null ");
|
|
+ }
|
|
+ if (mode == Mode.CTR) {
|
|
+ if (ivBytes.length < 8) {
|
|
+ throw new InvalidAlgorithmParameterException("Wrong IV length: CTR mode requires IV of at least: 8 bytes.");
|
|
+ }
|
|
+ return;
|
|
+ }
|
|
+ if (ivBytes.length != blockSize) {
|
|
+ throw new InvalidAlgorithmParameterException("Wrong IV length: must be " + blockSize + " bytes long.");
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
diff --git a/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAESymmetricCipherBase.java b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAESymmetricCipherBase.java
|
|
new file mode 100644
|
|
index 000000000..b2ff94754
|
|
--- /dev/null
|
|
+++ b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAESymmetricCipherBase.java
|
|
@@ -0,0 +1,615 @@
|
|
+/*
|
|
+ * 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.nio.ByteBuffer;
|
|
+import java.security.*;
|
|
+import java.security.spec.*;
|
|
+import java.util.Arrays;
|
|
+import java.util.Set;
|
|
+import java.util.concurrent.ConcurrentSkipListSet;
|
|
+
|
|
+import javax.crypto.*;
|
|
+import javax.crypto.spec.GCMParameterSpec;
|
|
+import javax.crypto.spec.IvParameterSpec;
|
|
+import javax.crypto.spec.SecretKeySpec;
|
|
+
|
|
+/*
|
|
+ * Cipher wrapper class utilizing openssl APIs.
|
|
+ */
|
|
+abstract class KAESymmetricCipherBase extends CipherSpi {
|
|
+ enum Padding {
|
|
+ NOPADDING,
|
|
+ PKCS5PADDING
|
|
+ }
|
|
+
|
|
+ enum Mode {
|
|
+ ECB,
|
|
+ CBC,
|
|
+ CTR,
|
|
+ OFB,
|
|
+ GCM
|
|
+ }
|
|
+
|
|
+ protected final String keyAlgo;
|
|
+ protected final int blockSize = 16;
|
|
+ protected Mode mode;
|
|
+ protected Padding padding;
|
|
+ protected 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;
|
|
+
|
|
+ // for gcm
|
|
+ private final int defaultGcmTagLen = blockSize;
|
|
+ private final int defaultGcmIvLen = 12;
|
|
+ private int tagLengthInBytes;
|
|
+ private byte[] lastEncKey = null;
|
|
+ private byte[] lastEncIv = null;
|
|
+ private byte[] aad;
|
|
+
|
|
+ private static 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 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 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;
|
|
+ }
|
|
+
|
|
+ KAESymmetricCipherBase(Mode mode, Padding padding, int fixedKeySize, String keyAlgo) {
|
|
+ this.mode = mode;
|
|
+ this.padding = padding;
|
|
+ this.fixedKeySize = fixedKeySize;
|
|
+ this.keyAlgo = keyAlgo;
|
|
+ }
|
|
+
|
|
+ private static class CipherContextRef extends PhantomReference<KAESymmetricCipherBase>
|
|
+ implements Comparable<CipherContextRef> {
|
|
+ private static ReferenceQueue<KAESymmetricCipherBase> 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(KAESymmetricCipherBase 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 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;
|
|
+ }
|
|
+ AlgorithmParameterSpec spec;
|
|
+ AlgorithmParameters params;
|
|
+ String algName = keyAlgo;
|
|
+ if (mode == Mode.GCM) {
|
|
+ algName = "GCM";
|
|
+ spec = new GCMParameterSpec(tagLengthInBytes * 8, iv.clone());
|
|
+ } else {
|
|
+ spec = new IvParameterSpec(iv.clone());
|
|
+ }
|
|
+ try {
|
|
+ params = AlgorithmParameters.getInstance(algName);
|
|
+ params.init(spec);
|
|
+ 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 spec = null;
|
|
+ String paramType = null;
|
|
+ if (params != null) {
|
|
+ try {
|
|
+ if (mode == Mode.GCM) {
|
|
+ spec = params.getParameterSpec(GCMParameterSpec.class);
|
|
+ paramType = "GCM";
|
|
+ } else {
|
|
+ spec = params.getParameterSpec(IvParameterSpec.class);
|
|
+ paramType = "IV";
|
|
+ }
|
|
+ } catch (InvalidParameterSpecException e) {
|
|
+ throw new InvalidAlgorithmParameterException("Could not decode " + paramType, e);
|
|
+ }
|
|
+ }
|
|
+ engineInit(opmode, key, spec, 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;
|
|
+ int tagLen = -1;
|
|
+ if (params != null) {
|
|
+ if (mode == Mode.GCM) {
|
|
+ if (params instanceof GCMParameterSpec) {
|
|
+ tagLen = ((GCMParameterSpec)params).getTLen();
|
|
+ checkTagLen(tagLen);
|
|
+ tagLen = tagLen >> 3;
|
|
+ ivBytes = ((GCMParameterSpec)params).getIV();
|
|
+ } else {
|
|
+ throw new InvalidAlgorithmParameterException("Unsupported parameter: " + params);
|
|
+ }
|
|
+ } else {
|
|
+ if (params instanceof IvParameterSpec) {
|
|
+ ivBytes = ((IvParameterSpec) params).getIV();
|
|
+ checkIvBytes(ivBytes);
|
|
+ } else {
|
|
+ throw new InvalidKeyException("IvParameterSpec required. Received: " + params.getClass().getName());
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ if (mode == Mode.ECB) {
|
|
+ if (params != null) {
|
|
+ throw new InvalidAlgorithmParameterException("No Parameters for ECB mode");
|
|
+ }
|
|
+ } else if (ivBytes == null) {
|
|
+ if (doEncrypt) {
|
|
+ if (mode == Mode.GCM) {
|
|
+ ivBytes = new byte[defaultGcmIvLen];
|
|
+ } else {
|
|
+ ivBytes = new byte[blockSize];
|
|
+ }
|
|
+ if (random == null) {
|
|
+ random = JCAUtil.getSecureRandom();
|
|
+ }
|
|
+ random.nextBytes(ivBytes);
|
|
+ } else {
|
|
+ throw new InvalidAlgorithmParameterException("Parameters required for decryption");
|
|
+ }
|
|
+ } else if (keyAlgo.equalsIgnoreCase("SM4") && ivBytes.length < blockSize) {
|
|
+ byte[] temp = new byte[blockSize];
|
|
+ System.arraycopy(ivBytes, 0, temp, 0, ivBytes.length);
|
|
+ ivBytes = temp;
|
|
+ }
|
|
+ implInit(doEncrypt, key.getEncoded(), ivBytes, tagLen);
|
|
+ }
|
|
+
|
|
+ private void checkTagLen(int tagLen) throws InvalidAlgorithmParameterException {
|
|
+ if ((tagLen < 96) || (tagLen > 128) || ((tagLen & 0x07) != 0)) {
|
|
+ throw new InvalidAlgorithmParameterException
|
|
+ ("Unsupported TLen value; must be one of {128, 120, 112, 104, 96}");
|
|
+ }
|
|
+ }
|
|
+
|
|
+ protected abstract void checkIvBytes(byte[] ivBytes) throws InvalidAlgorithmParameterException;
|
|
+
|
|
+ protected abstract String getCipherName(int keyLength, Mode mode);
|
|
+
|
|
+ private void implInit(boolean encrypt, byte[] keyVal, byte[] ivVal, int tagLen)
|
|
+ throws InvalidAlgorithmParameterException {
|
|
+ reset(true);
|
|
+ this.encrypt = encrypt;
|
|
+ this.keyValue = keyVal;
|
|
+ this.iv = ivVal;
|
|
+ this.cipherName = getCipherName(keyValue.length * 8, mode);
|
|
+
|
|
+ if (mode == Mode.GCM) {
|
|
+ if (tagLen == -1) {
|
|
+ tagLen = defaultGcmTagLen;
|
|
+ }
|
|
+ this.tagLengthInBytes = tagLen;
|
|
+ if (encrypt) {
|
|
+ // Check key+iv for encryption in GCM mode.
|
|
+ boolean requireReinit = Arrays.equals(ivVal, lastEncIv) && MessageDigest.isEqual(keyVal, lastEncKey);
|
|
+ if (requireReinit) {
|
|
+ throw new InvalidAlgorithmParameterException("Cannot reuse iv for GCM encryption");
|
|
+ }
|
|
+ lastEncIv = ivVal;
|
|
+ lastEncKey = keyVal;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ // 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;
|
|
+ }
|
|
+
|
|
+ protected abstract void checkKey(Key key) throws InvalidKeyException;
|
|
+
|
|
+ @Override
|
|
+ protected byte[] engineUpdate(byte[] input, int inputOffset, int inputLen) {
|
|
+ byte[] out = new byte[getOutputSizeByOperation(inputLen, false)];
|
|
+ int outLen = implUpdate(input, inputOffset, inputLen, out, 0);
|
|
+ if (outLen == 0) {
|
|
+ return new byte[0];
|
|
+ } else if (out.length != outLen) {
|
|
+ out = Arrays.copyOf(out, outLen);
|
|
+ }
|
|
+ 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 == null || output.length - outputOffset < min) {
|
|
+ throw new ShortBufferException("min " + min + "-byte buffer needed");
|
|
+ }
|
|
+ return implUpdate(input, inputOffset, inputLen, output, outputOffset);
|
|
+ }
|
|
+
|
|
+ private int implUpdate(byte[] input, int inputOffset, int inputLen, byte[] output, int outputOffset) {
|
|
+ ensureInitialized();
|
|
+ if (inputLen <= 0) {
|
|
+ return 0;
|
|
+ }
|
|
+ int outLen;
|
|
+ try {
|
|
+ outLen = nativeUpdate(pCtx.ctxAddress, input, inputOffset, inputLen, output, outputOffset,
|
|
+ mode == Mode.GCM, aad);
|
|
+ aad = null;
|
|
+ } catch (ArrayIndexOutOfBoundsException e) {
|
|
+ reset(true);
|
|
+ throw new ProviderException("Invoke nativeUpdate failed for " + cipherName, e);
|
|
+ }
|
|
+ bytesBuffered += (inputLen - outLen);
|
|
+
|
|
+ calledUpdate = true;
|
|
+ return outLen;
|
|
+ }
|
|
+
|
|
+ protected int getOutputSizeByOperation(int inLen, boolean isDoFinal) {
|
|
+ int ret;
|
|
+
|
|
+ if (inLen <= 0) {
|
|
+ inLen = 0;
|
|
+ }
|
|
+ if (padding == Padding.NOPADDING) {
|
|
+ ret = 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;
|
|
+ ret = len - (len % blockSize);
|
|
+ }
|
|
+ if (mode == Mode.GCM && isDoFinal) {
|
|
+ if (encrypt) {
|
|
+ ret = ret + tagLengthInBytes;
|
|
+ } else {
|
|
+ ret = Math.max(0, ret - tagLengthInBytes);
|
|
+ }
|
|
+ }
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ @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 == null || output.length - outputOffset < min) {
|
|
+ throw new ShortBufferException("min " + min + "-byte buffer needed");
|
|
+ }
|
|
+
|
|
+ int updateLen = inputLen;
|
|
+ if (mode == Mode.GCM && !encrypt) {
|
|
+ // Remove tagLengthInBytes suffix in GCM decrypt.
|
|
+ updateLen = inputLen - tagLengthInBytes;
|
|
+ }
|
|
+ outLen = implUpdate(input, inputOffset, updateLen, output, outputOffset);
|
|
+ outputOffset += outLen;
|
|
+
|
|
+ byte[] gcmTag = null;
|
|
+ if (mode == Mode.GCM && !encrypt) {
|
|
+ if (inputLen - outLen != tagLengthInBytes) {
|
|
+ throw new AEADBadTagException("Tag mismatch!");
|
|
+ }
|
|
+ // The last tagLengthInBytees in the input arg gcmTag.
|
|
+ gcmTag = Arrays.copyOfRange(input, inputOffset + inputLen - tagLengthInBytes, inputOffset + inputLen);
|
|
+ }
|
|
+
|
|
+ outLen += implDoFinal(output, outputOffset, gcmTag);
|
|
+ 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);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ protected void engineUpdateAAD(ByteBuffer byteBuffer) {
|
|
+ if (aad == null) {
|
|
+ aad = new byte[byteBuffer.remaining()];
|
|
+ byteBuffer.get(aad);
|
|
+ } else {
|
|
+ int newSize = aad.length + byteBuffer.remaining();
|
|
+ byte[] newaad = new byte[newSize];
|
|
+ System.arraycopy(aad, 0, newaad, 0, aad.length);
|
|
+ byteBuffer.get(newaad, aad.length, byteBuffer.remaining());
|
|
+ aad = newaad;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ protected void engineUpdateAAD(byte[] input, int inputOffset, int inputLen) {
|
|
+ if (aad == null) {
|
|
+ aad = Arrays.copyOfRange(input, inputOffset, inputOffset + inputLen);
|
|
+ } else {
|
|
+ int newSize = aad.length + inputLen;
|
|
+ byte[] newaad = new byte[newSize];
|
|
+ System.arraycopy(aad, 0, newaad, 0, aad.length);
|
|
+ System.arraycopy(input, inputOffset, newaad, aad.length, inputLen);
|
|
+ aad = newaad;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ private int implDoFinal(byte[] out, int outputOffset, byte[] gcmTag)
|
|
+ throws BadPaddingException, IllegalBlockSizeException {
|
|
+ if (!encrypt && !calledUpdate) {
|
|
+ return 0;
|
|
+ }
|
|
+ ensureInitialized();
|
|
+
|
|
+ int outLen;
|
|
+ try {
|
|
+ if (mode == Mode.GCM) {
|
|
+ outLen = nativeFinalGcm(pCtx.ctxAddress, out, outputOffset, mode == Mode.GCM, tagLengthInBytes,
|
|
+ gcmTag, encrypt);
|
|
+ } else {
|
|
+ outLen = nativeFinal(pCtx.ctxAddress, out, outputOffset);
|
|
+ }
|
|
+ } catch (ArrayIndexOutOfBoundsException | BadPaddingException e) {
|
|
+ if (e instanceof AEADBadTagException) {
|
|
+ throw e; // AEADBadTagException is expected for some tests
|
|
+ } else if (e instanceof BadPaddingException) {
|
|
+ if (padding == Padding.NOPADDING || e.getMessage().contains("wrong final block length")) {
|
|
+ throw new IllegalBlockSizeException("Input length not multiple of " + blockSize + " bytes");
|
|
+ } else {
|
|
+ throw e;
|
|
+ }
|
|
+ } else {
|
|
+ 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;
|
|
+
|
|
+ // for gcm
|
|
+ aad = null;
|
|
+
|
|
+ if (pCtx != null) {
|
|
+ pCtx.dispose(doCancel);
|
|
+ pCtx = null;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ protected static native long nativeInit(String cipherType, boolean encrypt, byte[] key, byte[] iv, boolean padding)
|
|
+ throws RuntimeException;
|
|
+
|
|
+ protected static native int nativeUpdate(long pContext, byte[] in, int inOfs, int inLen, byte[] out,
|
|
+ int outOfs, boolean gcm, byte[] aad) throws ArrayIndexOutOfBoundsException;
|
|
+
|
|
+ protected static native int nativeFinal(long pContext, byte[] out,
|
|
+ int outOfs) throws ArrayIndexOutOfBoundsException, BadPaddingException;
|
|
+
|
|
+ protected static native void nativeFree(long pContext);
|
|
+
|
|
+ protected static native int nativeFinalGcm(long pContext, byte[] out, int outOfs, boolean gcm,
|
|
+ int tagLength, byte[] gcmTag, boolean encrypt) throws ArrayIndexOutOfBoundsException, BadPaddingException;
|
|
+
|
|
+ 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/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEUtils.java b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEUtils.java
|
|
new file mode 100644
|
|
index 000000000..f7093a1f4
|
|
--- /dev/null
|
|
+++ b/src/jdk.crypto.kaeprovider/linux/classes/org/openeuler/security/openssl/KAEUtils.java
|
|
@@ -0,0 +1,220 @@
|
|
+/*
|
|
+ * 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<>();
|
|
+
|
|
+ private static final Map<Integer, String> SIZE_TO_CURVE = new HashMap<>();
|
|
+ private static final Map<String, String> CURVE_ALIAS = new HashMap<>();
|
|
+
|
|
+ static {
|
|
+ initDigest();
|
|
+ initECDH();
|
|
+ }
|
|
+
|
|
+ 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 digestName == null ? null : DIGEST_ALGORITHM_NAME_MAP.get(digestName.toUpperCase(Locale.ROOT));
|
|
+ }
|
|
+
|
|
+ static Integer getDigestLength(String digestName) {
|
|
+ return digestName == null ? null : DIGEST_ALGORITHM_LENGTH_MAP.get(digestName.toUpperCase(Locale.ROOT));
|
|
+ }
|
|
+
|
|
+ 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);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ private static void initECDH() {
|
|
+ SIZE_TO_CURVE.put(224, "secp224r1");
|
|
+ SIZE_TO_CURVE.put(256, "prime256v1");
|
|
+ SIZE_TO_CURVE.put(384, "secp384r1");
|
|
+ SIZE_TO_CURVE.put(521, "secp521r1");
|
|
+ CURVE_ALIAS.put("secp256r1", "prime256v1");
|
|
+ CURVE_ALIAS.put("1.3.132.0.33", "secp224r1");
|
|
+ CURVE_ALIAS.put("1.3.132.0.34", "secp384r1");
|
|
+ CURVE_ALIAS.put("1.3.132.0.35", "secp521r1");
|
|
+ CURVE_ALIAS.put("1.2.840.10045.3.1.7", "prime256v1");
|
|
+ }
|
|
+
|
|
+ static String getCurveBySize(int size) {
|
|
+ return SIZE_TO_CURVE.get(size);
|
|
+ }
|
|
+
|
|
+ static String getCurveByAlias(String alias) {
|
|
+ return CURVE_ALIAS.get(alias);
|
|
+ }
|
|
+}
|
|
diff --git a/src/jdk.crypto.kaeprovider/linux/conf/security/kaeprovider.conf b/src/jdk.crypto.kaeprovider/linux/conf/security/kaeprovider.conf
|
|
new file mode 100644
|
|
index 000000000..a48969669
|
|
--- /dev/null
|
|
+++ b/src/jdk.crypto.kaeprovider/linux/conf/security/kaeprovider.conf
|
|
@@ -0,0 +1,19 @@
|
|
+#
|
|
+# This is the config file for KAEProvider
|
|
+#
|
|
+# Algorithms are enabled by default if KAEProvider is used.
|
|
+# Delete # if you want to disable certain algorithm.
|
|
+
|
|
+# kae.md5=false
|
|
+# kae.sha256=false
|
|
+# kae.sha384=false
|
|
+# kae.sm3=false
|
|
+# kae.aes=false
|
|
+# kae.sm4=false
|
|
+# kae.hmac=false
|
|
+# kae.rsa=false
|
|
+# kae.dh=false
|
|
+# kae.ec=false
|
|
+
|
|
+# enable KAEProvider log setting
|
|
+# kae.log=true
|
|
diff --git a/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_cipher_rsa.c b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_cipher_rsa.c
|
|
new file mode 100644
|
|
index 000000000..fa616ae5f
|
|
--- /dev/null
|
|
+++ b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_cipher_rsa.c
|
|
@@ -0,0 +1,467 @@
|
|
+/*
|
|
+ * 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 <stdbool.h>
|
|
+#include <openssl/rsa.h>
|
|
+#include <openssl/evp.h>
|
|
+#include "kae_util.h"
|
|
+#include "kae_exception.h"
|
|
+#include "org_openeuler_security_openssl_KAERSACipher.h"
|
|
+
|
|
+static ENGINE* kaeEngine = NULL;
|
|
+
|
|
+typedef int RSACryptOperation(int, const unsigned char*, unsigned char*, RSA*, int);
|
|
+
|
|
+typedef int EvpPkeyCryptOperation(EVP_PKEY_CTX*, unsigned char*, size_t*, const unsigned char*, size_t);
|
|
+
|
|
+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);
|
|
+ }
|
|
+ if (rsa != NULL) {
|
|
+ RSA_free(rsa);
|
|
+ }
|
|
+ return resultSize;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * set rsa padding
|
|
+ */
|
|
+static bool 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 false;
|
|
+ }
|
|
+ return true;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * set rsa mgf1 md
|
|
+ */
|
|
+static bool 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 false;
|
|
+ }
|
|
+ if (EVP_PKEY_CTX_set_rsa_mgf1_md(pkeyCtx, mgf1MD) <= 0) {
|
|
+ KAE_ThrowFromOpenssl(env, "EVP_PKEY_CTX_set_rsa_mgf1_md", KAE_ThrowInvalidAlgorithmParameterException);
|
|
+ return false;
|
|
+ }
|
|
+ return true;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * set rsa oaep md
|
|
+ */
|
|
+static bool 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 false;
|
|
+ }
|
|
+ if (EVP_PKEY_CTX_set_rsa_oaep_md(pkeyCtx, oaepMD) <= 0) {
|
|
+ KAE_ThrowFromOpenssl(env, "EVP_PKEY_CTX_set_rsa_oaep_md", KAE_ThrowInvalidAlgorithmParameterException);
|
|
+ return false;
|
|
+ }
|
|
+ return true;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * set rsa oaep label
|
|
+ */
|
|
+static bool 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 false;
|
|
+ }
|
|
+ return true;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * 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;
|
|
+ kaeEngine = (kaeEngine == NULL) ? GetKaeEngine() : kaeEngine;
|
|
+
|
|
+ EVP_PKEY* pkey = (EVP_PKEY*)keyAddress;
|
|
+
|
|
+ // new ctx
|
|
+ // rsa encrypt/decrypt init
|
|
+ if ((pkeyCtx = EVP_PKEY_CTX_new(pkey, kaeEngine)) == 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) || !SetRSAMgf1Md(env, pkeyCtx, mgf1MdAlgoUTF) ||
|
|
+ !SetRSAOaepMd(env, pkeyCtx, oaepMdAlgoUTF)) {
|
|
+ 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)) {
|
|
+ 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;
|
|
+ kaeEngine = (kaeEngine == NULL) ? GetKaeEngine() : kaeEngine;
|
|
+
|
|
+ // 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 cleanup;
|
|
+ }
|
|
+
|
|
+ // new pkey
|
|
+ pkey = EVP_PKEY_new();
|
|
+ if (pkey == NULL) {
|
|
+ KAE_ThrowFromOpenssl(env, "EVP_PKEY_new", KAE_ThrowRuntimeException);
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ // new rsa
|
|
+ rsa = RSA_new_method(kaeEngine);
|
|
+ if (rsa == NULL) {
|
|
+ KAE_ThrowFromOpenssl(env, "RSA_new_method", KAE_ThrowRuntimeException);
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ // 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 cleanup;
|
|
+ }
|
|
+
|
|
+ // 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 cleanup;
|
|
+ }
|
|
+ return (jlong)pkey;
|
|
+cleanup:
|
|
+ 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;
|
|
+ kaeEngine = (kaeEngine == NULL) ? GetKaeEngine() : kaeEngine;
|
|
+
|
|
+ // get public key param n
|
|
+ bnN = KAE_GetBigNumFromByteArray(env, n);
|
|
+ if (bnN == NULL) {
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ // get public key param e
|
|
+ bnE = KAE_GetBigNumFromByteArray(env, e);
|
|
+ if (bnE == NULL) {
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ // new rsa
|
|
+ rsa = RSA_new_method(kaeEngine);
|
|
+ if (rsa == NULL) {
|
|
+ KAE_ThrowFromOpenssl(env, "RSA_new_method", KAE_ThrowRuntimeException);
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ // new EVP_PKEY
|
|
+ pkey = EVP_PKEY_new();
|
|
+ if (pkey == NULL) {
|
|
+ KAE_ThrowFromOpenssl(env, "EVP_PKEY_new", KAE_ThrowRuntimeException);
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ // 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 cleanup;
|
|
+ }
|
|
+
|
|
+ // 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 cleanup;
|
|
+ }
|
|
+ return (jlong)pkey;
|
|
+cleanup:
|
|
+ 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/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_digest.c b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_digest.c
|
|
new file mode 100644
|
|
index 000000000..f0e7b0be4
|
|
--- /dev/null
|
|
+++ b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_digest.c
|
|
@@ -0,0 +1,235 @@
|
|
+/*
|
|
+ * 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 <string.h>
|
|
+#include <openssl/evp.h>
|
|
+#include <openssl/md5.h>
|
|
+#include "kae_exception.h"
|
|
+#include "kae_log.h"
|
|
+#include "kae_util.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;
|
|
+ static ENGINE* kaeEngine = NULL;
|
|
+
|
|
+ if (algorithmName == NULL) {
|
|
+ KAE_ThrowNullPointerException(env, "algorithm is null");
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ // EVP_get_digestbyname
|
|
+ const char* algo_utf = (*env)->GetStringUTFChars(env, algorithmName, 0);
|
|
+ if ((strcasecmp(algo_utf, "md5") == 0) || (strcasecmp(algo_utf, "sm3") == 0)) {
|
|
+ kaeEngine = (kaeEngine == NULL) ? GetKaeEngine() : kaeEngine;
|
|
+ } else {
|
|
+ kaeEngine = NULL;
|
|
+ }
|
|
+ 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, kaeEngine);
|
|
+ if (result_code == 0) {
|
|
+ KAE_ThrowFromOpenssl(env, "EVP_DigestInit_ex failed", KAE_ThrowRuntimeException);
|
|
+ goto cleanup;
|
|
+ }
|
|
+ KAE_TRACE("KAEDigest_nativeInit EVP_DigestInit_ex(ctx = %p, md = %p) success", ctx, md);
|
|
+
|
|
+ KAE_TRACE("KAEDigest_nativeInit: finished");
|
|
+ return (jlong) ctx;
|
|
+
|
|
+cleanup:
|
|
+ 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 cleanup;
|
|
+ }
|
|
+ KAE_TRACE("KAEDigest_nativeClone EVP_MD_CTX_copy_ex(ctxCopy = %p, ctx = %p) success", ctxCopy, ctx);
|
|
+ KAE_TRACE("KAEDigest_nativeClone: finished");
|
|
+ return (jlong) ctxCopy;
|
|
+
|
|
+cleanup:
|
|
+ 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/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_exception.c b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_exception.c
|
|
new file mode 100644
|
|
index 000000000..f684f6eea
|
|
--- /dev/null
|
|
+++ b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_exception.c
|
|
@@ -0,0 +1,134 @@
|
|
+/*
|
|
+ * 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_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:
|
|
+ case EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH:
|
|
+ case EVP_F_EVP_PKEY_DECRYPT:
|
|
+ case EVP_R_PUBLIC_KEY_NOT_RSA:
|
|
+ case EVP_R_CTRL_NOT_IMPLEMENTED:
|
|
+ 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) {
|
|
+ defaultException(env, msg);
|
|
+ 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:
|
|
+ case ERR_LIB_RSA:
|
|
+ KAE_ThrowEvpException(env, reason, estring, defaultException);
|
|
+ break;
|
|
+ default:
|
|
+ defaultException(env, estring);
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ ERR_clear_error();
|
|
+}
|
|
+
|
|
+void KAE_ThrowAEADBadTagException(JNIEnv *env, const char *msg) {
|
|
+ KAE_ThrowByName(env, "javax/crypto/AEADBadTagException", msg);
|
|
+}
|
|
+
|
|
+void KAE_ThrowSignatureException(JNIEnv* env, const char* msg) {
|
|
+ KAE_ThrowByName(env, "java/security/SignatureException", msg);
|
|
+}
|
|
+
|
|
+void KAE_ThrowClassNotFoundException(JNIEnv* env, const char* msg) {
|
|
+ KAE_ThrowByName(env, "java/lang/ClassNotFoundException", msg);
|
|
+}
|
|
+
|
|
+
|
|
diff --git a/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_exception.h b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_exception.h
|
|
new file mode 100644
|
|
index 000000000..532953995
|
|
--- /dev/null
|
|
+++ b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_exception.h
|
|
@@ -0,0 +1,57 @@
|
|
+/*
|
|
+ * 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);
|
|
+
|
|
+void KAE_ThrowAEADBadTagException(JNIEnv* env, const char* msg);
|
|
+
|
|
+void KAE_ThrowSignatureException(JNIEnv* env, const char* msg);
|
|
+
|
|
+void KAE_ThrowClassNotFoundException(JNIEnv* env, const char* msg);
|
|
+#endif
|
|
diff --git a/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_hmac.c b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_hmac.c
|
|
new file mode 100644
|
|
index 000000000..7b28fa1fa
|
|
--- /dev/null
|
|
+++ b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_hmac.c
|
|
@@ -0,0 +1,203 @@
|
|
+/*
|
|
+ * 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 <string.h>
|
|
+#include <openssl/hmac.h>
|
|
+#include "kae_exception.h"
|
|
+#include "kae_log.h"
|
|
+#include "kae_util.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_KAEHMac
|
|
+ * Method: nativeInit
|
|
+ * Signature: ([BILjava/lang/String;)J
|
|
+ */
|
|
+JNIEXPORT jlong JNICALL Java_org_openeuler_security_openssl_KAEHMac_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 cleanup;
|
|
+ }
|
|
+
|
|
+ // 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 cleanup;
|
|
+ }
|
|
+ free(key_buffer);
|
|
+ return (jlong) ctx;
|
|
+
|
|
+cleanup:
|
|
+ free(key_buffer);
|
|
+ HMAC_CTX_free(ctx);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Class: org_openeuler_security_openssl_KAEHMac
|
|
+ * Method: nativeUpdate
|
|
+ * Signature: (J[BII)V
|
|
+ */
|
|
+JNIEXPORT void JNICALL Java_org_openeuler_security_openssl_KAEHMac_nativeUpdate
|
|
+ (JNIEnv* env, jclass cls, jlong hmac_ctx, jbyteArray input, jint in_offset, jint in_len) {
|
|
+ KAE_TRACE("KAEHMac_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_KAEHMac
|
|
+ * Method: nativeFinal
|
|
+ * Signature: (J[BII)I
|
|
+ */
|
|
+JNIEXPORT jint JNICALL Java_org_openeuler_security_openssl_KAEHMac_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("KAEHMac_nativeFinal success, output_offset = %d, bytesWritten = %d", out_offset, bytesWritten);
|
|
+
|
|
+cleanup:
|
|
+ free(temp_result);
|
|
+ return bytesWritten;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Class: org_openeuler_security_openssl_KAEHMac
|
|
+ * Method: nativeFree
|
|
+ * Signature: (J)V
|
|
+ */
|
|
+JNIEXPORT void JNICALL Java_org_openeuler_security_openssl_KAEHMac_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/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_keyagreement_dh.c b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_keyagreement_dh.c
|
|
new file mode 100644
|
|
index 000000000..b1c272411
|
|
--- /dev/null
|
|
+++ b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_keyagreement_dh.c
|
|
@@ -0,0 +1,139 @@
|
|
+/*
|
|
+ * 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 <memory.h>
|
|
+#include <openssl/bio.h>
|
|
+#include <openssl/ssl.h>
|
|
+#include <openssl/engine.h>
|
|
+#include <openssl/dh.h>
|
|
+#include <stdio.h>
|
|
+#include "kae_util.h"
|
|
+#include "kae_exception.h"
|
|
+#include "kae_log.h"
|
|
+#include "org_openeuler_security_openssl_KAEDHKeyAgreement.h"
|
|
+
|
|
+
|
|
+/*
|
|
+ * Class: org_openeuler_security_openssl_KAEDHKeyAgreement
|
|
+ * Method: nativeComputeKey
|
|
+ */
|
|
+JNIEXPORT jbyteArray JNICALL Java_org_openeuler_security_openssl_KAEDHKeyAgreement_nativeComputeKey(JNIEnv* env,
|
|
+ jobject obj, jbyteArray y, jbyteArray x, jbyteArray p, jbyteArray g, jint pSize) {
|
|
+
|
|
+ KAE_TRACE("Java_org_openeuler_security_openssl_KAEDHKeyAgreement_nativeComputeKey start.");
|
|
+
|
|
+ DH* dh = NULL;
|
|
+ BIGNUM* y_bn = NULL;
|
|
+ BIGNUM* x_bn = NULL;
|
|
+ BIGNUM* p_bn = NULL;
|
|
+ BIGNUM* g_bn = NULL;
|
|
+ BIGNUM* computeKeyRetBn = NULL;
|
|
+ int computekeyLength = 0;
|
|
+ unsigned char* secret = NULL;
|
|
+ jbyteArray retByteArray = NULL;
|
|
+ static ENGINE* kaeEngine = NULL;
|
|
+ kaeEngine = (kaeEngine == NULL) ? GetKaeEngine() : kaeEngine;
|
|
+
|
|
+ // bits to Bytes
|
|
+ int pSizeInByte = (pSize +7) >> 3;
|
|
+
|
|
+ if ((secret = (unsigned char*)malloc(pSizeInByte)) == NULL) {
|
|
+ KAE_ThrowOOMException(env, "malloc secret failed.");
|
|
+ goto cleanup;
|
|
+ }
|
|
+ memset(secret, 0, pSizeInByte);
|
|
+
|
|
+ if ((dh = DH_new_method(kaeEngine)) == NULL) {
|
|
+ KAE_ThrowOOMException(env, "Allocate DH failed in nativeComputeKey.");
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ if ((y_bn = KAE_GetBigNumFromByteArray(env, y)) == NULL) {
|
|
+ KAE_ThrowOOMException(env, "Convert y to BIGNUM failed.");
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ if ((x_bn = KAE_GetBigNumFromByteArray(env, x)) == NULL) {
|
|
+ KAE_ThrowOOMException(env, "Convert x to BIGNUM failed.");
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ if ((p_bn = KAE_GetBigNumFromByteArray(env, p)) == NULL) {
|
|
+ KAE_ThrowOOMException(env, "Convert p to BIGNUM failed.");
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ if ((g_bn = KAE_GetBigNumFromByteArray(env, g)) == NULL) {
|
|
+ KAE_ThrowOOMException(env, "Convert g to BIGNUM failed.");
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ if ((computeKeyRetBn = BN_new()) == NULL) {
|
|
+ KAE_ThrowOOMException(env, "Allocate BN failed.");
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ if (!DH_set0_pqg(dh, BN_dup(p_bn), NULL, BN_dup(g_bn))) {
|
|
+ KAE_ThrowRuntimeException(env, "DH_set0_pqg failed.");
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ if (!DH_set0_key(dh, NULL, BN_dup(x_bn))) {
|
|
+ KAE_ThrowRuntimeException(env, "DH_set0_key failed.");
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ computekeyLength = DH_compute_key(secret, y_bn, dh);
|
|
+
|
|
+ if (computekeyLength <= 0 ) {
|
|
+ KAE_ThrowRuntimeException(env, "DH_compute_key failed.");
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ BN_bin2bn(secret, computekeyLength, computeKeyRetBn);
|
|
+
|
|
+ retByteArray = KAE_GetByteArrayFromBigNum(env, computeKeyRetBn);
|
|
+ if (retByteArray == NULL) {
|
|
+ KAE_ThrowRuntimeException(env, "GetByteArrayFromBigNum failed in nativeComputeKey.");
|
|
+ goto cleanup;
|
|
+ }
|
|
+ KAE_TRACE("Java_org_openeuler_security_openssl_KAEDHKeyAgreement_nativeGenerateSecret finished!");
|
|
+
|
|
+cleanup:
|
|
+ if (dh != NULL)
|
|
+ DH_free(dh);
|
|
+ if (y_bn != NULL)
|
|
+ KAE_ReleaseBigNumFromByteArray(y_bn);
|
|
+ if (x_bn != NULL)
|
|
+ KAE_ReleaseBigNumFromByteArray(x_bn);
|
|
+ if (p_bn != NULL)
|
|
+ KAE_ReleaseBigNumFromByteArray(p_bn);
|
|
+ if (g_bn != NULL)
|
|
+ KAE_ReleaseBigNumFromByteArray(g_bn);
|
|
+ if (secret != NULL)
|
|
+ free(secret);
|
|
+ if (computeKeyRetBn != NULL)
|
|
+ BN_free(computeKeyRetBn);
|
|
+
|
|
+ return retByteArray;
|
|
+}
|
|
diff --git a/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_keyagreement_ecdh.c b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_keyagreement_ecdh.c
|
|
new file mode 100644
|
|
index 000000000..5fc4d68fd
|
|
--- /dev/null
|
|
+++ b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_keyagreement_ecdh.c
|
|
@@ -0,0 +1,115 @@
|
|
+/*
|
|
+ * 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 <memory.h>
|
|
+#include <openssl/objects.h>
|
|
+#include <openssl/ec.h>
|
|
+#include "kae_log.h"
|
|
+#include "kae_exception.h"
|
|
+#include "kae_util.h"
|
|
+#include "org_openeuler_security_openssl_KAEECDHKeyAgreement.h"
|
|
+
|
|
+static void FreeGenerateSecretParam(BIGNUM* s, BIGNUM* wX, BIGNUM* wY,
|
|
+ EC_POINT* pub, EC_KEY* eckey, EC_GROUP* group, unsigned char* shareKey)
|
|
+{
|
|
+ KAE_ReleaseBigNumFromByteArray(s);
|
|
+ KAE_ReleaseBigNumFromByteArray(wX);
|
|
+ KAE_ReleaseBigNumFromByteArray(wY);
|
|
+ if (pub != NULL) {
|
|
+ EC_POINT_free(pub);
|
|
+ }
|
|
+ if (eckey != NULL) {
|
|
+ EC_KEY_free(eckey);
|
|
+ }
|
|
+ if (group != NULL) {
|
|
+ EC_GROUP_free(group);
|
|
+ }
|
|
+ if (shareKey != NULL) {
|
|
+ free(shareKey);
|
|
+ }
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Class: org_openeuler_security_openssl_KAEECDHKeyAgreement
|
|
+ * Method: nativeGenerateSecret
|
|
+ * Signature: (Ljava/lang/String;[B[B[B)[B
|
|
+ */
|
|
+JNIEXPORT jbyteArray JNICALL Java_org_openeuler_security_openssl_KAEECDHKeyAgreement_nativeGenerateSecret
|
|
+ (JNIEnv* env, jclass cls, jstring curveName, jbyteArray wXArr, jbyteArray wYArr, jbyteArray sArr)
|
|
+{
|
|
+ EC_GROUP* group = NULL;
|
|
+ EC_KEY* eckey = NULL;
|
|
+ BIGNUM* wX = NULL;
|
|
+ BIGNUM* wY = NULL;
|
|
+ BIGNUM* s = NULL;
|
|
+ EC_POINT* pub = NULL;
|
|
+ jbyteArray javaBytes = NULL;
|
|
+ unsigned char* shareKey = NULL;
|
|
+ const char *curve = (*env)->GetStringUTFChars(env, curveName, 0);
|
|
+ int nid = OBJ_sn2nid(curve);
|
|
+ (*env)->ReleaseStringUTFChars(env, curveName, curve);
|
|
+ if ((nid == NID_undef) || (group = EC_GROUP_new_by_curve_name(nid)) == NULL) {
|
|
+ goto cleanup;
|
|
+ }
|
|
+ if ((s = KAE_GetBigNumFromByteArray(env, sArr)) == NULL || (wX = KAE_GetBigNumFromByteArray(env, wXArr)) == NULL
|
|
+ || (wY = KAE_GetBigNumFromByteArray(env, wYArr)) == NULL) {
|
|
+ KAE_ThrowOOMException(env, "failed to allocate BN_new");
|
|
+ goto cleanup;
|
|
+ }
|
|
+ if ((eckey = EC_KEY_new()) == NULL || !EC_KEY_set_group(eckey, group)) {
|
|
+ goto cleanup;
|
|
+ }
|
|
+ if ((pub = EC_POINT_new(group)) == NULL) {
|
|
+ goto cleanup;
|
|
+ }
|
|
+ if (!EC_POINT_set_affine_coordinates_GFp(group, pub, wX, wY, NULL)) {
|
|
+ goto cleanup;
|
|
+ }
|
|
+ if (!EC_KEY_set_public_key(eckey, pub) || !EC_KEY_set_private_key(eckey, s)) {
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ // Get the length of secret key, in bytes.
|
|
+ int expectSecretLen = (EC_GROUP_get_degree(group) + 7) / 8;
|
|
+ if ((shareKey = malloc(expectSecretLen)) == NULL) {
|
|
+ KAE_ThrowOOMException(env, "malloc error");
|
|
+ goto cleanup;
|
|
+ }
|
|
+ memset(shareKey, 0, expectSecretLen);
|
|
+
|
|
+ // Perform ecdh keyagreement.
|
|
+ if (ECDH_compute_key(shareKey, expectSecretLen, pub, eckey, NULL) != expectSecretLen) {
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ if ((javaBytes = (*env)->NewByteArray(env, expectSecretLen)) == NULL) {
|
|
+ goto cleanup;
|
|
+ }
|
|
+ (*env)->SetByteArrayRegion(env, javaBytes, 0, expectSecretLen, (jbyte*)shareKey);
|
|
+ FreeGenerateSecretParam(s, wX, wY, pub, eckey, group, shareKey);
|
|
+ return javaBytes;
|
|
+
|
|
+cleanup:
|
|
+ FreeGenerateSecretParam(s, wX, wY, pub, eckey, group, shareKey);
|
|
+ return NULL;
|
|
+}
|
|
diff --git a/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_keypairgenerator_dh.c b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_keypairgenerator_dh.c
|
|
new file mode 100644
|
|
index 000000000..54dc07edd
|
|
--- /dev/null
|
|
+++ b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_keypairgenerator_dh.c
|
|
@@ -0,0 +1,132 @@
|
|
+/*
|
|
+ * 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 <openssl/dh.h>
|
|
+#include <stdio.h>
|
|
+#include "kae_util.h"
|
|
+#include "kae_log.h"
|
|
+#include "org_openeuler_security_openssl_KAEDHKeyPairGenerator.h"
|
|
+#include "kae_exception.h"
|
|
+
|
|
+
|
|
+/*
|
|
+* Class: org_openeuler_security_openssl_KAEDHKeyPairGenerator
|
|
+* Method: nativeGenerateKeyPair
|
|
+* Signature: ([B[BI)[[B
|
|
+*/
|
|
+
|
|
+JNIEXPORT jobjectArray JNICALL Java_org_openeuler_security_openssl_KAEDHKeyPairGenerator_nativeGenerateKeyPair
|
|
+ (JNIEnv* env, jclass cls, jbyteArray p, jbyteArray g, jint lSize)
|
|
+{
|
|
+ DH* dh = NULL;
|
|
+ BIGNUM* p_bn = NULL;
|
|
+ BIGNUM* g_bn = NULL;
|
|
+ const BIGNUM* pri_key_bn = NULL;
|
|
+ const BIGNUM* pub_key_bn = NULL;
|
|
+ jclass byteArrayClass = NULL;
|
|
+ jobjectArray keys = NULL;
|
|
+ jbyteArray pri_key = NULL;
|
|
+ jbyteArray pub_key = NULL;
|
|
+ static ENGINE* kaeEngine = NULL;
|
|
+ kaeEngine = (kaeEngine == NULL) ? GetKaeEngine() : kaeEngine;
|
|
+
|
|
+ KAE_TRACE("Java_org_openeuler_security_openssl_KAEDHKeyPairGenerator_nativeGenerateKeyPair start !");
|
|
+
|
|
+ if ((dh = DH_new_method(kaeEngine)) == NULL) {
|
|
+ KAE_ThrowOOMException(env, "Allocate DH failed in nativeGenerateKeyPair!");
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ if ((p_bn = KAE_GetBigNumFromByteArray(env, p)) == NULL) {
|
|
+ KAE_ThrowOOMException(env, "Allocate p_bn failed in nativeGenerateKeyPair!");
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ if ((g_bn = KAE_GetBigNumFromByteArray(env, g)) == NULL) {
|
|
+ KAE_ThrowOOMException(env, "Allocate g_bn failed in nativeGenerateKeyPair!");
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ if (!DH_set0_pqg(dh, BN_dup(p_bn), NULL, BN_dup(g_bn))) {
|
|
+ KAE_ThrowRuntimeException(env, "DH_set0_pqg failed in nativeGenerateKeyPair.");
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ // Return value is fixed to 1, nothing to check.
|
|
+ DH_set_length(dh, lSize);
|
|
+
|
|
+ if (!DH_generate_key(dh)) {
|
|
+ KAE_ThrowInvalidAlgorithmParameterException(env, "DH generate key failed in nativeGenerateKeyPair.");
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ if ((byteArrayClass = (*env)->FindClass(env, "[B")) == NULL) {
|
|
+ KAE_ThrowClassNotFoundException(env, "Class byte[] not found.");
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ if ((keys = (*env)->NewObjectArray(env, 2, byteArrayClass, NULL)) == NULL) {
|
|
+ KAE_ThrowOOMException(env, "Allocate ByteArray failed in nativeGenerateKeyPair!");
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ // Return the ptr of private key in dh.
|
|
+ pri_key_bn = DH_get0_priv_key(dh);
|
|
+ pub_key_bn = DH_get0_pub_key(dh);
|
|
+
|
|
+ pub_key = KAE_GetByteArrayFromBigNum(env, pub_key_bn);
|
|
+ if (pub_key == NULL) {
|
|
+ KAE_ThrowOOMException(env, "PublicKey allocate failed in nativeGenerateKeyPair.");
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ pri_key = KAE_GetByteArrayFromBigNum(env, pri_key_bn);
|
|
+ if (pri_key == NULL) {
|
|
+ KAE_ThrowRuntimeException(env, "GetByteArrayFromBigNum failed in nativeGenerateKeyPair.");
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ (*env)->SetObjectArrayElement(env, keys, 0, pub_key);
|
|
+ (*env)->SetObjectArrayElement(env, keys, 1, pri_key);
|
|
+
|
|
+ KAE_TRACE("Java_org_openeuler_security_openssl_KAEDHKeyPairGenerator_nativeGenerateKeyPair finished !");
|
|
+
|
|
+cleanup:
|
|
+ if (dh != NULL)
|
|
+ DH_free(dh);
|
|
+ if (p_bn != NULL)
|
|
+ KAE_ReleaseBigNumFromByteArray(p_bn);
|
|
+ if (g_bn != NULL)
|
|
+ KAE_ReleaseBigNumFromByteArray(g_bn);
|
|
+ if (byteArrayClass != NULL)
|
|
+ (*env)->DeleteLocalRef(env, byteArrayClass);
|
|
+ if (pub_key != NULL)
|
|
+ (*env)->DeleteLocalRef(env, pub_key);
|
|
+ if (pri_key != NULL)
|
|
+ (*env)->DeleteLocalRef(env, pri_key);
|
|
+
|
|
+ return keys;
|
|
+}
|
|
diff --git a/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_keypairgenerator_ec.c b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_keypairgenerator_ec.c
|
|
new file mode 100644
|
|
index 000000000..5b387d708
|
|
--- /dev/null
|
|
+++ b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_keypairgenerator_ec.c
|
|
@@ -0,0 +1,508 @@
|
|
+/*
|
|
+ * 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 <stdbool.h>
|
|
+#include <openssl/objects.h>
|
|
+#include <openssl/ec.h>
|
|
+#include "kae_util.h"
|
|
+#include "kae_exception.h"
|
|
+#include "kae_log.h"
|
|
+#include "org_openeuler_security_openssl_KAEECKeyPairGenerator.h"
|
|
+
|
|
+#define KAE_EC_PARAM_NUM_SIZE 7
|
|
+#define KAE_EC_KEY_NUM_SIZE 3
|
|
+
|
|
+// ECDH param index.
|
|
+typedef enum ECDHParamIndex {
|
|
+ ecdhP = 0,
|
|
+ ecdhA,
|
|
+ ecdhB,
|
|
+ ecdhX,
|
|
+ ecdhY,
|
|
+ ecdhOrder,
|
|
+ ecdhCofactor
|
|
+} ECDHParamIndex;
|
|
+
|
|
+// ECDH Key index.
|
|
+typedef enum ECDHKeyIndex {
|
|
+ ecdhWX = 0,
|
|
+ ecdhWY,
|
|
+ ecdhS
|
|
+} ECDHKeyIndex;
|
|
+
|
|
+static void FreeECDHCurveParam(JNIEnv* env, BIGNUM* p, BIGNUM* a, BIGNUM* b, jbyteArray paramP,
|
|
+ jbyteArray paramA, jbyteArray paramB)
|
|
+{
|
|
+ if (p != NULL) {
|
|
+ BN_free(p);
|
|
+ }
|
|
+ if (a != NULL) {
|
|
+ BN_free(a);
|
|
+ }
|
|
+ if (b != NULL) {
|
|
+ BN_free(b);
|
|
+ }
|
|
+ if (paramP != NULL) {
|
|
+ (*env)->DeleteLocalRef(env, paramP);
|
|
+ }
|
|
+ if (paramA != NULL) {
|
|
+ (*env)->DeleteLocalRef(env, paramA);
|
|
+ }
|
|
+ if (paramB != NULL) {
|
|
+ (*env)->DeleteLocalRef(env, paramB);
|
|
+ }
|
|
+}
|
|
+
|
|
+// Set p, a, b in group to params.
|
|
+static bool SetECDHCurve(JNIEnv* env, EC_GROUP* group, jobjectArray params)
|
|
+{
|
|
+ BIGNUM* p = NULL;
|
|
+ BIGNUM* a = NULL;
|
|
+ BIGNUM* b = NULL;
|
|
+ jbyteArray paramP = NULL;
|
|
+ jbyteArray paramA = NULL;
|
|
+ jbyteArray paramB = NULL;
|
|
+ if ((p = BN_new()) == NULL || (a = BN_new()) == NULL || (b = BN_new()) == NULL) {
|
|
+ KAE_ThrowOOMException(env, "failed to allocate BN_new");
|
|
+ goto cleanup;
|
|
+ }
|
|
+ if (!EC_GROUP_get_curve_GFp(group, p, a, b, NULL)) {
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ // Set p.
|
|
+ if ((paramP = KAE_GetByteArrayFromBigNum(env, p)) == NULL) {
|
|
+ goto cleanup;
|
|
+ }
|
|
+ (*env)->SetObjectArrayElement(env, params, ecdhP, paramP);
|
|
+
|
|
+ // Set a.
|
|
+ if ((paramA = KAE_GetByteArrayFromBigNum(env, a)) == NULL) {
|
|
+ goto cleanup;
|
|
+ }
|
|
+ (*env)->SetObjectArrayElement(env, params, ecdhA, paramA);
|
|
+
|
|
+ // Set b.
|
|
+ if ((paramB = KAE_GetByteArrayFromBigNum(env, b)) == NULL) {
|
|
+ goto cleanup;
|
|
+ }
|
|
+ (*env)->SetObjectArrayElement(env, params, ecdhB, paramB);
|
|
+ FreeECDHCurveParam(env, p, a, b, paramP, paramA, paramB);
|
|
+ return true;
|
|
+
|
|
+cleanup:
|
|
+ FreeECDHCurveParam(env, p, a, b, paramP, paramA, paramB);
|
|
+ return false;
|
|
+}
|
|
+
|
|
+// Set generator(x, y) in group to params.
|
|
+static bool SetECDHPoint(JNIEnv* env, EC_GROUP* group, jobjectArray params)
|
|
+{
|
|
+ BIGNUM* x = NULL;
|
|
+ BIGNUM* y = NULL;
|
|
+ const EC_POINT* generator = NULL;
|
|
+ jbyteArray paramX = NULL;
|
|
+ jbyteArray paramY = NULL;
|
|
+ if ((x = BN_new()) == NULL || (y = BN_new()) == NULL) {
|
|
+ KAE_ThrowOOMException(env, "failed to allocate BN_new");
|
|
+ goto cleanup;
|
|
+ }
|
|
+ if ((generator = EC_GROUP_get0_generator(group)) == NULL) {
|
|
+ KAE_ThrowOOMException(env, "failed to allocate ec generator");
|
|
+ goto cleanup;
|
|
+ }
|
|
+ if (!EC_POINT_get_affine_coordinates_GFp(group, generator, x, y, NULL)) {
|
|
+ KAE_ThrowFromOpenssl(env, "EC_POINT_set_affine_coordinates_GFp", KAE_ThrowRuntimeException);
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ // Set x.
|
|
+ if ((paramX = KAE_GetByteArrayFromBigNum(env, x)) == NULL) {
|
|
+ goto cleanup;
|
|
+ }
|
|
+ (*env)->SetObjectArrayElement(env, params, ecdhX, paramX);
|
|
+
|
|
+ // Set y.
|
|
+ if ((paramY = KAE_GetByteArrayFromBigNum(env, y)) == NULL) {
|
|
+ goto cleanup;
|
|
+ }
|
|
+ (*env)->SetObjectArrayElement(env, params, ecdhY, paramY);
|
|
+ BN_free(x);
|
|
+ BN_free(y);
|
|
+ (*env)->DeleteLocalRef(env, paramX);
|
|
+ (*env)->DeleteLocalRef(env, paramY);
|
|
+ return true;
|
|
+
|
|
+cleanup:
|
|
+ if (x != NULL) {
|
|
+ BN_free(x);
|
|
+ }
|
|
+ if (y != NULL) {
|
|
+ BN_free(y);
|
|
+ }
|
|
+ if (paramX != NULL) {
|
|
+ (*env)->DeleteLocalRef(env, paramX);
|
|
+ }
|
|
+ if (paramY != NULL) {
|
|
+ (*env)->DeleteLocalRef(env, paramY);
|
|
+ }
|
|
+ return false;
|
|
+}
|
|
+
|
|
+// Set order, cofactor in group to params.
|
|
+static bool SetECDHOrderAndCofactor(JNIEnv* env, EC_GROUP* group, jobjectArray params)
|
|
+{
|
|
+ BIGNUM* order = NULL;
|
|
+ BIGNUM* cofactor = NULL;
|
|
+ jbyteArray paramOrder = NULL;
|
|
+ jbyteArray paramCofactor = NULL;
|
|
+ if ((order = BN_new()) == NULL || (cofactor = BN_new()) == NULL) {
|
|
+ goto cleanup;
|
|
+ }
|
|
+ if (!EC_GROUP_get_order(group, order, NULL)) {
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ // Set order.
|
|
+ if ((paramOrder = KAE_GetByteArrayFromBigNum(env, order)) == NULL) {
|
|
+ goto cleanup;
|
|
+ }
|
|
+ (*env)->SetObjectArrayElement(env, params, ecdhOrder, paramOrder);
|
|
+ if (!EC_GROUP_get_cofactor(group, cofactor, NULL)) {
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ // Set cofactor.
|
|
+ if ((paramCofactor = KAE_GetByteArrayFromBigNum(env, cofactor)) == NULL) {
|
|
+ goto cleanup;
|
|
+ }
|
|
+ (*env)->SetObjectArrayElement(env, params, ecdhCofactor, paramCofactor);
|
|
+ BN_free(order);
|
|
+ BN_free(cofactor);
|
|
+ (*env)->DeleteLocalRef(env, paramOrder);
|
|
+ (*env)->DeleteLocalRef(env, paramCofactor);
|
|
+ return true;
|
|
+
|
|
+cleanup:
|
|
+ if (order != NULL) {
|
|
+ BN_free(order);
|
|
+ }
|
|
+ if (cofactor != NULL) {
|
|
+ BN_free(cofactor);
|
|
+ }
|
|
+ if (paramOrder != NULL) {
|
|
+ (*env)->DeleteLocalRef(env, paramOrder);
|
|
+ }
|
|
+ if (paramCofactor != NULL) {
|
|
+ (*env)->DeleteLocalRef(env, paramCofactor);
|
|
+ }
|
|
+ return false;
|
|
+}
|
|
+
|
|
+static void FreeECDHKeyParam(JNIEnv* env,
|
|
+ BIGNUM* wX, BIGNUM* wY, jbyteArray keyWX, jbyteArray keyWY, jbyteArray keyS)
|
|
+{
|
|
+ if (wX != NULL) {
|
|
+ BN_free(wX);
|
|
+ }
|
|
+ if (wY != NULL) {
|
|
+ BN_free(wY);
|
|
+ }
|
|
+ if (keyWX != NULL) {
|
|
+ (*env)->DeleteLocalRef(env, keyWX);
|
|
+ }
|
|
+ if (keyWY != NULL) {
|
|
+ (*env)->DeleteLocalRef(env, keyWY);
|
|
+ }
|
|
+ if (keyS != NULL) {
|
|
+ (*env)->DeleteLocalRef(env, keyS);
|
|
+ }
|
|
+}
|
|
+
|
|
+// Set publicKey(wX, wY) and privateKey(s) in eckey to params.
|
|
+static bool SetECDHKey(JNIEnv* env, const EC_GROUP* group, jobjectArray params,
|
|
+ const EC_KEY* eckey)
|
|
+{
|
|
+ BIGNUM* wX = NULL;
|
|
+ BIGNUM* wY = NULL;
|
|
+ const EC_POINT* pub = NULL;
|
|
+ const BIGNUM* s = NULL;
|
|
+ jbyteArray keyWX = NULL;
|
|
+ jbyteArray keyWY = NULL;
|
|
+ jbyteArray keyS = NULL;
|
|
+ if ((wX = BN_new()) == NULL || (wY = BN_new()) == NULL) {
|
|
+ KAE_ThrowOOMException(env, "failed to allocate array");
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ if ((pub = EC_KEY_get0_public_key(eckey)) == NULL ||
|
|
+ !EC_POINT_get_affine_coordinates_GFp(group, pub, wX, wY, NULL)) {
|
|
+ goto cleanup;
|
|
+ }
|
|
+ if ((s = EC_KEY_get0_private_key(eckey)) == NULL) {
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ // Set wX.
|
|
+ if ((keyWX = KAE_GetByteArrayFromBigNum(env, wX)) == NULL) {
|
|
+ goto cleanup;
|
|
+ }
|
|
+ (*env)->SetObjectArrayElement(env, params, ecdhWX, keyWX);
|
|
+
|
|
+ // Set wY.
|
|
+ if ((keyWY = KAE_GetByteArrayFromBigNum(env, wY)) == NULL) {
|
|
+ goto cleanup;
|
|
+ }
|
|
+ (*env)->SetObjectArrayElement(env, params, ecdhWY, keyWY);
|
|
+
|
|
+ // Set s.
|
|
+ if ((keyS = KAE_GetByteArrayFromBigNum(env, s)) == NULL) {
|
|
+ goto cleanup;
|
|
+ }
|
|
+ (*env)->SetObjectArrayElement(env, params, ecdhS, keyS);
|
|
+ FreeECDHKeyParam(env, wX, wY, keyWX, keyWY, keyS);
|
|
+ return true;
|
|
+
|
|
+cleanup:
|
|
+ FreeECDHKeyParam(env, wX, wY, keyWX, keyWY, keyS);
|
|
+ return false;
|
|
+}
|
|
+
|
|
+// Convert EC_GROUP in openssl to byte[][] in java
|
|
+static jobjectArray NewECDHParam(JNIEnv* env, EC_GROUP* group)
|
|
+{
|
|
+ jclass byteArrayClass = (*env)->FindClass(env, "[B");
|
|
+ jobjectArray params = (*env)->NewObjectArray(env, KAE_EC_PARAM_NUM_SIZE, byteArrayClass, NULL);
|
|
+ if (params == NULL) {
|
|
+ KAE_ThrowOOMException(env, "failed to allocate array");
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ if (!SetECDHCurve(env, group, params)) {
|
|
+ goto cleanup;
|
|
+ }
|
|
+ if (!SetECDHPoint(env, group, params)) {
|
|
+ goto cleanup;
|
|
+ }
|
|
+ if (!SetECDHOrderAndCofactor(env, group, params)) {
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ (*env)->DeleteLocalRef(env, byteArrayClass);
|
|
+ return params;
|
|
+
|
|
+cleanup:
|
|
+ if (byteArrayClass != NULL) {
|
|
+ (*env)->DeleteLocalRef(env, byteArrayClass);
|
|
+ }
|
|
+ if (params != NULL) {
|
|
+ (*env)->DeleteLocalRef(env, params);
|
|
+ }
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+// Convert EC_KEY in openssl to byte[][] in java
|
|
+static jobjectArray NewECDHKey(JNIEnv* env, const EC_GROUP* group, const EC_KEY* eckey)
|
|
+{
|
|
+ jclass byteArrayClass = NULL;
|
|
+ jobjectArray params = NULL;
|
|
+
|
|
+ byteArrayClass = (*env)->FindClass(env, "[B");
|
|
+ params = (*env)->NewObjectArray(env, KAE_EC_KEY_NUM_SIZE, byteArrayClass, NULL);
|
|
+ if (params == NULL) {
|
|
+ KAE_ThrowOOMException(env, "failed to allocate array");
|
|
+ goto cleanup;
|
|
+ }
|
|
+ if (!SetECDHKey(env, group, params, eckey)) {
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ (*env)->DeleteLocalRef(env, byteArrayClass);
|
|
+ return params;
|
|
+
|
|
+cleanup:
|
|
+ if (byteArrayClass != NULL) {
|
|
+ (*env)->DeleteLocalRef(env, byteArrayClass);
|
|
+ }
|
|
+ if (params != NULL) {
|
|
+ (*env)->DeleteLocalRef(env, params);
|
|
+ }
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+static void FreeECDHParam(BIGNUM* p, BIGNUM* a, BIGNUM* b, BIGNUM* x, BIGNUM* y, BIGNUM* order, BIGNUM* cofactor)
|
|
+{
|
|
+ KAE_ReleaseBigNumFromByteArray(p);
|
|
+ KAE_ReleaseBigNumFromByteArray(a);
|
|
+ KAE_ReleaseBigNumFromByteArray(b);
|
|
+ KAE_ReleaseBigNumFromByteArray(x);
|
|
+ KAE_ReleaseBigNumFromByteArray(y);
|
|
+ KAE_ReleaseBigNumFromByteArray(order);
|
|
+ KAE_ReleaseBigNumFromByteArray(cofactor);
|
|
+}
|
|
+
|
|
+// Convert params in java to EC_GROUP in openssl
|
|
+static EC_GROUP* GetGroupByParam(JNIEnv* env, jbyteArray pArr, jbyteArray aArr, jbyteArray bArr,
|
|
+ jbyteArray xArr, jbyteArray yArr, jbyteArray orderArr, jint cofactorInt)
|
|
+{
|
|
+ BIGNUM* p = NULL;
|
|
+ BIGNUM* a = NULL;
|
|
+ BIGNUM* b = NULL;
|
|
+ BIGNUM* x = NULL;
|
|
+ BIGNUM* y = NULL;
|
|
+ BIGNUM* order = NULL;
|
|
+ BIGNUM* cofactor = NULL;
|
|
+ EC_GROUP* group = NULL;
|
|
+ BN_CTX* ctx = NULL;
|
|
+ EC_POINT* generator = NULL;
|
|
+ if ((p = KAE_GetBigNumFromByteArray(env, pArr)) == NULL || (a = KAE_GetBigNumFromByteArray(env, aArr)) == NULL ||
|
|
+ (b = KAE_GetBigNumFromByteArray(env, bArr)) == NULL || (x = KAE_GetBigNumFromByteArray(env, xArr)) == NULL ||
|
|
+ (y = KAE_GetBigNumFromByteArray(env, yArr)) == NULL || (cofactor = BN_new()) == NULL ||
|
|
+ (order = KAE_GetBigNumFromByteArray(env, orderArr)) == NULL || !BN_set_word(cofactor, cofactorInt)) {
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ // Create the curve.
|
|
+ if ((ctx = BN_CTX_new()) == NULL || (group = EC_GROUP_new_curve_GFp(p, a, b, ctx)) == NULL) {
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ // Create the generator and set x, y.
|
|
+ if ((generator = EC_POINT_new(group)) == NULL ||
|
|
+ !EC_POINT_set_affine_coordinates_GFp(group, generator, x, y, ctx)) {
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ // Set the generator, order and cofactor.
|
|
+ if (!EC_GROUP_set_generator(group, generator, order, cofactor)) {
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ FreeECDHParam(p, a, b, x, y, order, cofactor);
|
|
+ EC_POINT_free(generator);
|
|
+ BN_CTX_free(ctx);
|
|
+ return group;
|
|
+
|
|
+cleanup:
|
|
+ FreeECDHParam(p, a, b, x, y, order, cofactor);
|
|
+ if (group != NULL) {
|
|
+ EC_GROUP_free(group);
|
|
+ }
|
|
+ if (generator != NULL) {
|
|
+ EC_POINT_free(generator);
|
|
+ }
|
|
+ if (ctx != NULL) {
|
|
+ BN_CTX_free(ctx);
|
|
+ }
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+
|
|
+/*
|
|
+ * Class: org_openeuler_security_openssl_KAEECKeyPairGenerator
|
|
+ * Method: nativeGenerateParam
|
|
+ * Signature: (Ljava/lang/String;)[[B
|
|
+ */
|
|
+JNIEXPORT jobjectArray JNICALL Java_org_openeuler_security_openssl_KAEECKeyPairGenerator_nativeGenerateParam(
|
|
+ JNIEnv* env, jclass cls, jstring curveName)
|
|
+{
|
|
+ EC_GROUP* group = NULL;
|
|
+ jobjectArray ecdhParam = NULL;
|
|
+
|
|
+ const char *curve = (*env)->GetStringUTFChars(env, curveName, 0);
|
|
+ KAE_TRACE("KAEECKeyPairGenerator_nativeGenerateParam(curveName = %s)", curve);
|
|
+ int nid = OBJ_sn2nid(curve);
|
|
+ (*env)->ReleaseStringUTFChars(env, curveName, curve);
|
|
+ if (nid == NID_undef) {
|
|
+ goto cleanup;
|
|
+ }
|
|
+ // Construct a builtin curve.
|
|
+ if ((group = EC_GROUP_new_by_curve_name(nid)) == NULL) {
|
|
+ goto cleanup;
|
|
+ }
|
|
+ ecdhParam = NewECDHParam(env, group);
|
|
+
|
|
+ if (group != NULL) {
|
|
+ EC_GROUP_free(group);
|
|
+ }
|
|
+ KAE_TRACE("KAEECKeyPairGenerator_nativeGenerateParam success, ecdhParam = %p", ecdhParam);
|
|
+ return ecdhParam;
|
|
+
|
|
+cleanup:
|
|
+ if (group != NULL) {
|
|
+ EC_GROUP_free(group);
|
|
+ }
|
|
+ if (ecdhParam != NULL) {
|
|
+ (*env)->DeleteLocalRef(env, ecdhParam);
|
|
+ }
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Class: org_openeuler_security_openssl_KAEECKeyPairGenerator
|
|
+ * Method: nativeGenerateKeyPair
|
|
+ * Signature: ([B[B[B[B[B[BI)[[B
|
|
+ */
|
|
+JNIEXPORT jobjectArray JNICALL Java_org_openeuler_security_openssl_KAEECKeyPairGenerator_nativeGenerateKeyPair(
|
|
+ JNIEnv* env, jclass cls, jbyteArray pArr, jbyteArray aArr, jbyteArray bArr,
|
|
+ jbyteArray xArr, jbyteArray yArr, jbyteArray orderArr, jint cofactorInt)
|
|
+{
|
|
+ EC_GROUP* group = NULL;
|
|
+ EC_KEY* eckey = NULL;
|
|
+ jobjectArray ecdhKey = NULL;
|
|
+
|
|
+ if ((group = GetGroupByParam(env, pArr, aArr, bArr, xArr, yArr, orderArr, cofactorInt)) == NULL) {
|
|
+ goto cleanup;
|
|
+ }
|
|
+ if ((eckey = EC_KEY_new()) == NULL) {
|
|
+ goto cleanup;
|
|
+ }
|
|
+ if (!EC_KEY_set_group(eckey, group)) {
|
|
+ goto cleanup;
|
|
+ }
|
|
+ // Generates a new public and private key for the supplied eckey object.
|
|
+ // Refer to {@link https://www.openssl.org/docs/man1.1.0/man3/EC_KEY_generate_key.html} for details.
|
|
+ if (!EC_KEY_generate_key(eckey)) {
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ ecdhKey = NewECDHKey(env, group, eckey);
|
|
+
|
|
+ EC_KEY_free(eckey);
|
|
+ EC_GROUP_free(group);
|
|
+
|
|
+ KAE_TRACE("KAEECKeyPairGenerator_nativeGenerateKeyPair success, ecdhKey = %p", ecdhKey);
|
|
+ return ecdhKey;
|
|
+
|
|
+cleanup:
|
|
+ if (eckey != NULL) {
|
|
+ EC_KEY_free(eckey);
|
|
+ }
|
|
+ if (group != NULL) {
|
|
+ EC_GROUP_free(group);
|
|
+ }
|
|
+ if (ecdhKey != NULL) {
|
|
+ (*env)->DeleteLocalRef(env, ecdhKey);
|
|
+ }
|
|
+ return NULL;
|
|
+}
|
|
diff --git a/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_keypairgenerator_rsa.c b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_keypairgenerator_rsa.c
|
|
new file mode 100644
|
|
index 000000000..d4c9d6ac4
|
|
--- /dev/null
|
|
+++ b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_keypairgenerator_rsa.c
|
|
@@ -0,0 +1,167 @@
|
|
+/*
|
|
+ * 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 <stdbool.h>
|
|
+#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
|
|
+
|
|
+// rsa param index
|
|
+typedef enum RSAParamIndex {
|
|
+ rsaN = 0,
|
|
+ rsaE,
|
|
+ rsaD,
|
|
+ rsaP,
|
|
+ rsaQ,
|
|
+ rsaDmp1,
|
|
+ rsaDmq1,
|
|
+ rsaIqmp
|
|
+} RSAParamIndex;
|
|
+
|
|
+// 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) {
|
|
+ static ENGINE* kaeEngine = NULL;
|
|
+ kaeEngine = (kaeEngine == NULL) ? GetKaeEngine() : kaeEngine;
|
|
+ // new rsa
|
|
+ RSA* rsa = RSA_new_method(kaeEngine);
|
|
+ if (rsa == NULL) {
|
|
+ KAE_ThrowFromOpenssl(env, "RSA_new_method", 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 value
|
|
+ * step 2. Convert paramValue (BIGNUM) to jbyteArray
|
|
+ * step 3. Set the rsa param to the param array
|
|
+ */
|
|
+static bool SetRSAKeyParam(JNIEnv* env, RSA* rsa, jobjectArray params, RSAParamIndex rsaParamIndex) {
|
|
+ // get rsa param value
|
|
+ const BIGNUM* rsaParamValue = GetRSAParamFunctionList[rsaParamIndex](rsa);
|
|
+ if (rsaParamValue == NULL) {
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ // Convert paramValue to jbyteArray
|
|
+ jbyteArray param = KAE_GetByteArrayFromBigNum(env, rsaParamValue);
|
|
+ if (param == NULL) {
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ // Set the rsa param to the param array
|
|
+ (*env)->SetObjectArrayElement(env, params, rsaParamIndex, param);
|
|
+ return true;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * 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 = rsaN; paramIndex <= rsaIqmp; paramIndex++) {
|
|
+ if (!SetRSAKeyParam(env, rsa, params, paramIndex)) {
|
|
+ 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/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_log.h b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_log.h
|
|
new file mode 100644
|
|
index 000000000..d8d9c7b32
|
|
--- /dev/null
|
|
+++ b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/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/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_provider.c b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_provider.c
|
|
new file mode 100644
|
|
index 000000000..aa46e737e
|
|
--- /dev/null
|
|
+++ b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_provider.c
|
|
@@ -0,0 +1,57 @@
|
|
+/*
|
|
+ * 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 "kae_util.h"
|
|
+#include "org_openeuler_security_openssl_KAEProvider.h"
|
|
+
|
|
+/*
|
|
+ * Class: Java_org_openeuler_security_openssl_KAEProvider
|
|
+ * Method: initOpenssl
|
|
+ * Signature: ()V
|
|
+ */
|
|
+JNIEXPORT void JNICALL Java_org_openeuler_security_openssl_KAEProvider_initOpenssl
|
|
+ (JNIEnv *env, jclass cls) {
|
|
+ SSL_load_error_strings();
|
|
+ ERR_load_BIO_strings();
|
|
+ OpenSSL_add_all_algorithms();
|
|
+
|
|
+ // check if KaeEngine holder is already set
|
|
+ ENGINE* e = GetKaeEngine();
|
|
+ if (e != NULL) {
|
|
+ ENGINE_free(e);
|
|
+ e = NULL;
|
|
+ }
|
|
+
|
|
+ // determine whether KAE is loaded successfully
|
|
+ e = ENGINE_by_id("kae");
|
|
+ if (e == NULL) {
|
|
+ ERR_clear_error();
|
|
+ KAE_ThrowRuntimeException(env, "kae engine not found");
|
|
+ return;
|
|
+ }
|
|
+ SetKaeEngine(e);
|
|
+}
|
|
diff --git a/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_signature_rsa.c b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_signature_rsa.c
|
|
new file mode 100644
|
|
index 000000000..e81dc1406
|
|
--- /dev/null
|
|
+++ b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_signature_rsa.c
|
|
@@ -0,0 +1,363 @@
|
|
+/*
|
|
+ * 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 <stdbool.h>
|
|
+#include <string.h>
|
|
+#include <openssl/rsa.h>
|
|
+#include <openssl/evp.h>
|
|
+#include "kae_util.h"
|
|
+#include "kae_exception.h"
|
|
+
|
|
+// get EVP_MD by digestName
|
|
+static const EVP_MD* getEvpMd(JNIEnv* env, jstring digestName) {
|
|
+ const char* digestNameUtf = (*env)->GetStringUTFChars(env, digestName, 0);
|
|
+ const EVP_MD* md = (EVP_MD*)EVP_get_digestbyname(digestNameUtf);
|
|
+ (*env)->ReleaseStringUTFChars(env, digestName, digestNameUtf);
|
|
+ if (md == NULL) {
|
|
+ KAE_ThrowSignatureException(env, "Unsupported digest algorithm.");
|
|
+ }
|
|
+ return md;
|
|
+}
|
|
+
|
|
+// sign release
|
|
+static void signRelease(JNIEnv* env, jbyteArray digestValue, jbyte* digestBytes, jbyte* sigBytes,
|
|
+ EVP_PKEY_CTX* pkeyCtx) {
|
|
+ if (digestBytes != NULL) {
|
|
+ (*env)->ReleaseByteArrayElements(env, digestValue, digestBytes, 0);
|
|
+ }
|
|
+ if (sigBytes != NULL) {
|
|
+ free(sigBytes);
|
|
+ }
|
|
+ if (pkeyCtx != NULL) {
|
|
+ EVP_PKEY_CTX_free(pkeyCtx);
|
|
+ }
|
|
+}
|
|
+
|
|
+// verify release
|
|
+static void verifyRelease(JNIEnv* env, jbyteArray digestValue, jbyte* digestBytes, jbyteArray sigValue, jbyte* sigBytes,
|
|
+ EVP_PKEY_CTX* pkeyCtx) {
|
|
+ if (digestBytes != NULL) {
|
|
+ (*env)->ReleaseByteArrayElements(env, digestValue, digestBytes, 0);
|
|
+ }
|
|
+ if (sigBytes != NULL) {
|
|
+ (*env)->ReleaseByteArrayElements(env, sigValue, sigBytes, 0);
|
|
+ }
|
|
+ if (pkeyCtx != NULL) {
|
|
+ EVP_PKEY_CTX_free(pkeyCtx);
|
|
+ }
|
|
+}
|
|
+
|
|
+// set rsa PkeyCtx parameters
|
|
+static bool setRsaPkeyCtxParameters(JNIEnv* env, EVP_PKEY_CTX* pkeyCtx, jint paddingType, jstring digestName) {
|
|
+ // set rsa padding
|
|
+ if (EVP_PKEY_CTX_set_rsa_padding(pkeyCtx, paddingType) <= 0) {
|
|
+ KAE_ThrowFromOpenssl(env, "EVP_PKEY_CTX_set_rsa_padding", KAE_ThrowSignatureException);
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ // set signature md
|
|
+ const EVP_MD* md = getEvpMd(env, digestName);
|
|
+ if (md == NULL) {
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ if (EVP_PKEY_CTX_set_signature_md(pkeyCtx, md) <= 0) {
|
|
+ KAE_ThrowFromOpenssl(env, "EVP_PKEY_CTX_set_signature_md", KAE_ThrowSignatureException);
|
|
+ return false;
|
|
+ }
|
|
+ return true;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Class: org_openeuler_security_openssl_KAERSASignatureNative
|
|
+ * Method: rsaSign
|
|
+ * Signature: (JLjava/lang/String;[BI)[B
|
|
+ */
|
|
+JNIEXPORT jbyteArray JNICALL Java_org_openeuler_security_openssl_KAERSASignatureNative_rsaSign(JNIEnv* env, jclass cls,
|
|
+ jlong keyAddress, jstring digestName, jbyteArray digestValue, jint paddingType) {
|
|
+ EVP_PKEY* pkey = (EVP_PKEY*)keyAddress;
|
|
+ EVP_PKEY_CTX* pkeyCtx = NULL;
|
|
+ jbyte* digestBytes = NULL;
|
|
+ jbyte* sigBytes = NULL;
|
|
+ jbyteArray sigByteArray = NULL;
|
|
+ static ENGINE* kaeEngine = NULL;
|
|
+ kaeEngine = (kaeEngine == NULL) ? GetKaeEngine() : kaeEngine;
|
|
+ // new EVP_PKEY_CTX
|
|
+ if ((pkeyCtx = EVP_PKEY_CTX_new(pkey, kaeEngine)) == NULL) {
|
|
+ KAE_ThrowFromOpenssl(env, "EVP_PKEY_new", KAE_ThrowSignatureException);
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ // sign init
|
|
+ if (EVP_PKEY_sign_init(pkeyCtx) <= 0) {
|
|
+ KAE_ThrowFromOpenssl(env, "EVP_PKEY_sign_init", KAE_ThrowSignatureException);
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ // set rsa PkeyCtx parameters
|
|
+ if (!setRsaPkeyCtxParameters(env, pkeyCtx, paddingType, digestName)) {
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ // sign
|
|
+ size_t sigLen = (size_t)EVP_PKEY_size(pkey);
|
|
+ if (sigLen <= 0) {
|
|
+ KAE_ThrowSignatureException(env, "The sigLen size cannot be zero or negative");
|
|
+ goto cleanup;
|
|
+ }
|
|
+ if ((sigBytes = malloc(sigLen)) == NULL) {
|
|
+ KAE_ThrowOOMException(env, "malloc failed");
|
|
+ goto cleanup;
|
|
+ }
|
|
+ if ((digestBytes = (*env)->GetByteArrayElements(env, digestValue, NULL)) == NULL) {
|
|
+ KAE_ThrowOOMException(env, "GetByteArrayElements failed");
|
|
+ goto cleanup;
|
|
+ }
|
|
+ size_t digestLen = (size_t)(*env)->GetArrayLength(env, digestValue);
|
|
+ if (EVP_PKEY_sign(pkeyCtx, (unsigned char*)sigBytes, &sigLen,
|
|
+ (const unsigned char*)digestBytes, digestLen) <= 0) {
|
|
+ KAE_ThrowFromOpenssl(env, "EVP_PKEY_sign", KAE_ThrowSignatureException);
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ // set signature byte to jbyteArray
|
|
+ if ((sigByteArray = (*env)->NewByteArray(env, (jsize)sigLen)) == NULL) {
|
|
+ KAE_ThrowOOMException(env, "NewByteArray failed");
|
|
+ goto cleanup;
|
|
+ }
|
|
+ (*env)->SetByteArrayRegion(env, sigByteArray, 0, (jsize)sigLen, sigBytes);
|
|
+
|
|
+cleanup:
|
|
+ signRelease(env, digestValue, digestBytes, sigBytes, pkeyCtx);
|
|
+ return sigByteArray;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Class: org_openeuler_security_openssl_KAERSASignatureNative
|
|
+ * Method: rsaVerify
|
|
+ * Signature: (JLjava/lang/String;[BI[B)Z
|
|
+ */
|
|
+JNIEXPORT jboolean JNICALL Java_org_openeuler_security_openssl_KAERSASignatureNative_rsaVerify(JNIEnv* env, jclass cls,
|
|
+ jlong keyAddress, jstring digestName, jbyteArray digestValue, jint paddingType, jbyteArray sigValue) {
|
|
+ EVP_PKEY* pkey = (EVP_PKEY*)keyAddress;
|
|
+ EVP_PKEY_CTX* pkeyCtx = NULL;
|
|
+ jbyte* digestBytes = NULL;
|
|
+ jbyte* sigBytes = NULL;
|
|
+ jboolean isSuccess = JNI_FALSE;
|
|
+ static ENGINE* kaeEngine = NULL;
|
|
+ kaeEngine = (kaeEngine == NULL) ? GetKaeEngine() : kaeEngine;
|
|
+ // new EVP_PKEY_CTX
|
|
+ if ((pkeyCtx = EVP_PKEY_CTX_new(pkey, kaeEngine)) == NULL) {
|
|
+ KAE_ThrowFromOpenssl(env, "EVP_PKEY_new", KAE_ThrowSignatureException);
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ // verify init
|
|
+ if (EVP_PKEY_verify_init(pkeyCtx) <= 0) {
|
|
+ KAE_ThrowFromOpenssl(env, "EVP_PKEY_sign_init", KAE_ThrowSignatureException);
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ // set rsa PkeyCtx parameters
|
|
+ if (!setRsaPkeyCtxParameters(env, pkeyCtx, paddingType, digestName)) {
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ // verify
|
|
+ if ((digestBytes = (*env)->GetByteArrayElements(env, digestValue, NULL)) == NULL) {
|
|
+ KAE_ThrowOOMException(env, "GetByteArrayElements failed");
|
|
+ goto cleanup;
|
|
+ }
|
|
+ if ((sigBytes = (*env)->GetByteArrayElements(env, sigValue, NULL)) == NULL) {
|
|
+ KAE_ThrowOOMException(env, "GetByteArrayElements failed");
|
|
+ goto cleanup;
|
|
+ }
|
|
+ size_t sigLen = (size_t)(*env)->GetArrayLength(env, sigValue);
|
|
+ size_t digestLen = (size_t)(*env)->GetArrayLength(env, digestValue);
|
|
+ if (EVP_PKEY_verify(pkeyCtx, (const unsigned char*)sigBytes, sigLen,
|
|
+ (const unsigned char*)digestBytes, digestLen) <= 0) {
|
|
+ KAE_ThrowFromOpenssl(env, "EVP_PKEY_verify", KAE_ThrowSignatureException);
|
|
+ goto cleanup;
|
|
+ }
|
|
+ isSuccess = JNI_TRUE;
|
|
+
|
|
+cleanup:
|
|
+ verifyRelease(env, digestValue, digestBytes, sigValue, sigBytes, pkeyCtx);
|
|
+ return isSuccess;
|
|
+}
|
|
+
|
|
+// set pss pkeyCtx parameters
|
|
+static bool setPssPkeyCtxParameters(JNIEnv* env, EVP_PKEY_CTX* pkeyCtx, jint paddingType, jstring digestName,
|
|
+ jstring mgf1DigestName, jint saltLen) {
|
|
+ // set rsa padding
|
|
+ if (EVP_PKEY_CTX_set_rsa_padding(pkeyCtx, paddingType) <= 0) {
|
|
+ KAE_ThrowFromOpenssl(env, "EVP_PKEY_CTX_set_rsa_padding", KAE_ThrowSignatureException);
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ // set signature md
|
|
+ const EVP_MD* md = getEvpMd(env, digestName);
|
|
+ if (md == NULL) {
|
|
+ return false;
|
|
+ }
|
|
+ if (EVP_PKEY_CTX_set_signature_md(pkeyCtx, md) <= 0) {
|
|
+ KAE_ThrowFromOpenssl(env, "EVP_PKEY_CTX_set_signature_md", KAE_ThrowSignatureException);
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ // set rsa mgf1 md
|
|
+ const EVP_MD* mgf1Md = getEvpMd(env, mgf1DigestName);
|
|
+ if (mgf1Md == NULL) {
|
|
+ return false;
|
|
+ }
|
|
+ if (EVP_PKEY_CTX_set_rsa_mgf1_md(pkeyCtx, mgf1Md) <= 0) {
|
|
+ KAE_ThrowFromOpenssl(env, "EVP_PKEY_CTX_set_rsa_mgf1_md", KAE_ThrowSignatureException);
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ // set salt len
|
|
+ if (EVP_PKEY_CTX_set_rsa_pss_saltlen(pkeyCtx, saltLen) <= 0) {
|
|
+ KAE_ThrowFromOpenssl(env, "EVP_PKEY_CTX_set_rsa_pss_saltlen", KAE_ThrowSignatureException);
|
|
+ return false;
|
|
+ }
|
|
+ return true;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Class: org_openeuler_security_openssl_KAERSASignatureNative
|
|
+ * Method: pssSign
|
|
+ * Signature: (JLjava/lang/String;[BILjava/lang/String;I)[B
|
|
+ */
|
|
+JNIEXPORT jbyteArray JNICALL Java_org_openeuler_security_openssl_KAERSASignatureNative_pssSign(JNIEnv* env, jclass cls,
|
|
+ jlong keyAddress, jstring digestName, jbyteArray digestValue, jint paddingType, jstring mgf1DigestName,
|
|
+ jint saltLen) {
|
|
+ EVP_PKEY* pkey = (EVP_PKEY*)keyAddress;
|
|
+ EVP_PKEY_CTX* pkeyCtx = NULL;
|
|
+ jbyte* digestBytes = NULL;
|
|
+ jbyte* sigBytes = NULL;
|
|
+ jbyteArray sigByteArray = NULL;
|
|
+ static ENGINE* kaeEngine = NULL;
|
|
+ kaeEngine = (kaeEngine == NULL) ? GetKaeEngine() : kaeEngine;
|
|
+ // new EVP_PKEY_CTX
|
|
+ if ((pkeyCtx = EVP_PKEY_CTX_new(pkey, kaeEngine)) == NULL) {
|
|
+ KAE_ThrowFromOpenssl(env, "EVP_PKEY_new", KAE_ThrowSignatureException);
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ // sign init
|
|
+ if (EVP_PKEY_sign_init(pkeyCtx) <= 0) {
|
|
+ KAE_ThrowFromOpenssl(env, "EVP_PKEY_sign_init", KAE_ThrowSignatureException);
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ // set pss pkeyCtx parameters
|
|
+ if (!setPssPkeyCtxParameters(env, pkeyCtx, paddingType, digestName, mgf1DigestName, saltLen)) {
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ // sign
|
|
+ size_t sigLen = (size_t)EVP_PKEY_size(pkey);
|
|
+ if (sigLen <= 0) {
|
|
+ KAE_ThrowSignatureException(env, "The sigLen size cannot be zero or negative");
|
|
+ goto cleanup;
|
|
+ }
|
|
+ if ((sigBytes = malloc(sigLen)) == NULL) {
|
|
+ KAE_ThrowOOMException(env, "malloc failed");
|
|
+ goto cleanup;
|
|
+ }
|
|
+ if ((digestBytes = (*env)->GetByteArrayElements(env, digestValue, NULL)) == NULL) {
|
|
+ KAE_ThrowOOMException(env, "GetByteArrayElements failed");
|
|
+ goto cleanup;
|
|
+ }
|
|
+ size_t digestLen = (size_t)(*env)->GetArrayLength(env, digestValue);
|
|
+ if (EVP_PKEY_sign(pkeyCtx, (unsigned char*)sigBytes, &sigLen,
|
|
+ (const unsigned char*)digestBytes, digestLen) <= 0) {
|
|
+ KAE_ThrowFromOpenssl(env, "EVP_PKEY_sign", KAE_ThrowSignatureException);
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ // set signature byte to jbyteArray
|
|
+ if ((sigByteArray = (*env)->NewByteArray(env, (jsize)sigLen)) == NULL) {
|
|
+ KAE_ThrowOOMException(env, "NewByteArray failed");
|
|
+ goto cleanup;
|
|
+ }
|
|
+ (*env)->SetByteArrayRegion(env, sigByteArray, 0, (jsize)sigLen, sigBytes);
|
|
+
|
|
+cleanup:
|
|
+ signRelease(env, digestValue, digestBytes, sigBytes, pkeyCtx);
|
|
+ return sigByteArray;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Class: org_openeuler_security_openssl_KAERSASignatureNative
|
|
+ * Method: pssVerify
|
|
+ * Signature: (JLjava/lang/String;[BILjava/lang/String;I[B)Z
|
|
+ */
|
|
+JNIEXPORT jboolean JNICALL Java_org_openeuler_security_openssl_KAERSASignatureNative_pssVerify(JNIEnv* env, jclass cls,
|
|
+ jlong keyAddress, jstring digestName, jbyteArray digestValue, jint paddingType, jstring mgf1DigestName,
|
|
+ jint saltLen, jbyteArray sigValue) {
|
|
+ EVP_PKEY* pkey = (EVP_PKEY*)keyAddress;
|
|
+ EVP_PKEY_CTX* pkeyCtx = NULL;
|
|
+ jbyte* digestBytes = NULL;
|
|
+ jbyte* sigBytes = NULL;
|
|
+ jboolean isSuccess = JNI_FALSE;
|
|
+ static ENGINE* kaeEngine = NULL;
|
|
+ kaeEngine = (kaeEngine == NULL) ? GetKaeEngine() : kaeEngine;
|
|
+ // new EVP_PKEY_CTX
|
|
+ if ((pkeyCtx = EVP_PKEY_CTX_new(pkey, kaeEngine)) == NULL) {
|
|
+ KAE_ThrowFromOpenssl(env, "EVP_PKEY_new", KAE_ThrowSignatureException);
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ // verify init
|
|
+ if (EVP_PKEY_verify_init(pkeyCtx) <= 0) {
|
|
+ KAE_ThrowFromOpenssl(env, "EVP_PKEY_sign_init", KAE_ThrowSignatureException);
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ // set pkeyCtx parameters
|
|
+ if (!setPssPkeyCtxParameters(env, pkeyCtx, paddingType, digestName, mgf1DigestName, saltLen)) {
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ // verify
|
|
+ if ((digestBytes = (*env)->GetByteArrayElements(env, digestValue, NULL)) == NULL) {
|
|
+ KAE_ThrowOOMException(env, "GetByteArrayElements failed");
|
|
+ goto cleanup;
|
|
+ }
|
|
+ if ((sigBytes = (*env)->GetByteArrayElements(env, sigValue, NULL)) == NULL) {
|
|
+ KAE_ThrowOOMException(env, "GetByteArrayElements failed");
|
|
+ goto cleanup;
|
|
+ }
|
|
+ size_t sigLen = (size_t)(*env)->GetArrayLength(env, sigValue);
|
|
+ size_t digestLen = (size_t)(*env)->GetArrayLength(env, digestValue);
|
|
+ if (EVP_PKEY_verify(pkeyCtx, (const unsigned char*)sigBytes, sigLen,
|
|
+ (const unsigned char*)digestBytes, digestLen) <= 0) {
|
|
+ KAE_ThrowFromOpenssl(env, "EVP_PKEY_verify", KAE_ThrowSignatureException);
|
|
+ goto cleanup;
|
|
+ }
|
|
+ isSuccess = JNI_TRUE;
|
|
+
|
|
+cleanup:
|
|
+ verifyRelease(env, digestValue, digestBytes, sigValue, sigBytes, pkeyCtx);
|
|
+ return isSuccess;
|
|
+}
|
|
\ No newline at end of file
|
|
diff --git a/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_symmetric_cipher.c b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_symmetric_cipher.c
|
|
new file mode 100644
|
|
index 000000000..c92574fbd
|
|
--- /dev/null
|
|
+++ b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_symmetric_cipher.c
|
|
@@ -0,0 +1,409 @@
|
|
+/*
|
|
+ * 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 <memory.h>
|
|
+#include <stdbool.h>
|
|
+#include <openssl/evp.h>
|
|
+#include <openssl/err.h>
|
|
+#include <string.h>
|
|
+#include "kae_exception.h"
|
|
+#include "kae_log.h"
|
|
+#include "kae_util.h"
|
|
+#include "org_openeuler_security_openssl_KAESymmetricCipherBase.h"
|
|
+
|
|
+bool StartsWith(const char* str1, const char* str2)
|
|
+{
|
|
+ if (str1 == NULL || str2 == NULL) {
|
|
+ return 0;
|
|
+ }
|
|
+ int len1 = strlen(str1);
|
|
+ int len2 = strlen(str2);
|
|
+ if (len1 > len2 || (len1 == 0 || len2 == 0)) {
|
|
+ return false;
|
|
+ }
|
|
+ const char *cur = str1;
|
|
+ int i = 0;
|
|
+ while (*cur != '\0') {
|
|
+ if (*cur != str2[i]) {
|
|
+ return 0;
|
|
+ }
|
|
+ cur++;
|
|
+ i++;
|
|
+ }
|
|
+ return true;
|
|
+}
|
|
+
|
|
+static const EVP_CIPHER* EVPGetSm4CipherByName(JNIEnv* env, const char* algo)
|
|
+{
|
|
+ static const EVP_CIPHER* sm4Ecb = NULL;
|
|
+ static const EVP_CIPHER* sm4Cbc = NULL;
|
|
+ static const EVP_CIPHER* sm4Ctr = NULL;
|
|
+ static const EVP_CIPHER* sm4Ofb = NULL;
|
|
+
|
|
+ if (strcasecmp(algo, "sm4-ecb") == 0) {
|
|
+ return sm4Ecb == NULL ? sm4Ecb = EVP_get_cipherbyname(algo) : sm4Ecb;
|
|
+ } else if (strcasecmp(algo, "sm4-cbc") == 0) {
|
|
+ return sm4Cbc == NULL ? sm4Cbc = EVP_get_cipherbyname(algo) : sm4Cbc;
|
|
+ } else if (strcasecmp(algo, "sm4-ctr") == 0) {
|
|
+ return sm4Ctr == NULL ? sm4Ctr = EVP_get_cipherbyname(algo) : sm4Ctr;
|
|
+ } else if (strcasecmp(algo, "sm4-ofb") == 0) {
|
|
+ return sm4Ofb == NULL ? sm4Ofb = EVP_get_cipherbyname(algo) : sm4Ofb;
|
|
+ } else {
|
|
+ KAE_ThrowRuntimeException(env, "EVPGetSm4CipherByName error");
|
|
+ return 0;
|
|
+ }
|
|
+}
|
|
+
|
|
+static const EVP_CIPHER* EVPGetAesCipherByName(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* aes128Gcm = NULL;
|
|
+ static const EVP_CIPHER* aes192Ecb = NULL;
|
|
+ static const EVP_CIPHER* aes192Cbc = NULL;
|
|
+ static const EVP_CIPHER* aes192Ctr = NULL;
|
|
+ static const EVP_CIPHER* aes192Gcm = NULL;
|
|
+ static const EVP_CIPHER* aes256Ecb = NULL;
|
|
+ static const EVP_CIPHER* aes256Cbc = NULL;
|
|
+ static const EVP_CIPHER* aes256Ctr = NULL;
|
|
+ static const EVP_CIPHER* aes256Gcm = 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-128-gcm") == 0) {
|
|
+ return aes128Gcm == NULL ? aes128Gcm = EVP_get_cipherbyname(algo) : aes128Gcm;
|
|
+ } 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-192-gcm") == 0) {
|
|
+ return aes192Gcm == NULL ? aes192Gcm = EVP_get_cipherbyname(algo) : aes192Gcm;
|
|
+ } 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 if (strcasecmp(algo, "aes-256-gcm") == 0) {
|
|
+ return aes256Gcm == NULL ? aes256Gcm = EVP_get_cipherbyname(algo) : aes256Gcm;
|
|
+ } else {
|
|
+ KAE_ThrowRuntimeException(env, "EVPGetAesCipherByName error");
|
|
+ return 0;
|
|
+ }
|
|
+}
|
|
+
|
|
+void FreeMemoryFromInit(JNIEnv* env, jbyteArray iv, jbyte* ivBytes, jbyteArray key, jbyte* keyBytes)
|
|
+{
|
|
+ if (ivBytes != NULL) {
|
|
+ (*env)->ReleaseByteArrayElements(env, iv, ivBytes, 0);
|
|
+ }
|
|
+ if (keyBytes != NULL) {
|
|
+ (*env)->ReleaseByteArrayElements(env, key, keyBytes, 0);
|
|
+ }
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Class: org_openeuler_security_openssl_KAESymmetricCipherBase
|
|
+ * Method: nativeInit
|
|
+ * Signature: (Ljava/lang/String;Z[B[B)J
|
|
+ */
|
|
+JNIEXPORT jlong JNICALL
|
|
+Java_org_openeuler_security_openssl_KAESymmetricCipherBase_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;
|
|
+ static ENGINE* kaeEngine = NULL;
|
|
+
|
|
+ const char* algo = (*env)->GetStringUTFChars(env, cipherType, 0);
|
|
+ if (StartsWith("aes", algo)) {
|
|
+ cipher = EVPGetAesCipherByName(env, algo);
|
|
+ kaeEngine = NULL;
|
|
+ } else {
|
|
+ cipher = EVPGetSm4CipherByName(env, algo);
|
|
+ kaeEngine = (kaeEngine == NULL) ? GetKaeEngine() : kaeEngine;
|
|
+ }
|
|
+ (*env)->ReleaseStringUTFChars(env, cipherType, algo);
|
|
+ if (cipher == NULL) {
|
|
+ KAE_ThrowOOMException(env, "create EVP_CIPHER fail");
|
|
+ goto cleanup;
|
|
+ }
|
|
+ if ((ctx = EVP_CIPHER_CTX_new()) == NULL) {
|
|
+ KAE_ThrowOOMException(env, "create EVP_CIPHER_CTX fail");
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ if (iv != NULL) {
|
|
+ ivBytes = (*env)->GetByteArrayElements(env, iv, NULL);
|
|
+ }
|
|
+ if (key != NULL) {
|
|
+ keyBytes = (*env)->GetByteArrayElements(env, key, NULL);
|
|
+ }
|
|
+
|
|
+ if (!EVP_CipherInit_ex(ctx, cipher, kaeEngine, (const unsigned char*)keyBytes,
|
|
+ (const unsigned char*)ivBytes, encrypt ? 1 : 0)) {
|
|
+ KAE_ThrowFromOpenssl(env, "EVP_CipherInit_ex failed", KAE_ThrowRuntimeException);
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ EVP_CIPHER_CTX_set_padding(ctx, padding ? 1 : 0);
|
|
+
|
|
+ FreeMemoryFromInit(env, iv, ivBytes, key, keyBytes);
|
|
+ return (jlong)ctx;
|
|
+
|
|
+cleanup:
|
|
+ if (ctx != NULL) {
|
|
+ EVP_CIPHER_CTX_free(ctx);
|
|
+ }
|
|
+ FreeMemoryFromInit(env, iv, ivBytes, key, keyBytes);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static void FreeMemoryFromUpdate(unsigned char* in, unsigned char* aad, unsigned char* out)
|
|
+{
|
|
+ if (in != NULL) {
|
|
+ free(in);
|
|
+ }
|
|
+ if (out != NULL) {
|
|
+ free(out);
|
|
+ }
|
|
+ if (aad != NULL) {
|
|
+ free(aad);
|
|
+ }
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Class: org_openeuler_security_openssl_KAESymmetricCipherBase
|
|
+ * Method: nativeUpdate
|
|
+ * Signature: (J[BII[BIZ[B)I
|
|
+ */
|
|
+JNIEXPORT jint JNICALL
|
|
+Java_org_openeuler_security_openssl_KAESymmetricCipherBase_nativeUpdate(JNIEnv* env, jclass cls, jlong ctxAddress,
|
|
+ jbyteArray inArr, jint inOfs, jint inLen, jbyteArray outArr, jint outOfs, jboolean gcm, jbyteArray gcmAAD)
|
|
+{
|
|
+ unsigned char* in = NULL;
|
|
+ unsigned char* aad = NULL;
|
|
+ unsigned char* out = NULL;
|
|
+
|
|
+ EVP_CIPHER_CTX* ctx = (EVP_CIPHER_CTX*)ctxAddress;
|
|
+ if (ctx == NULL || inArr == NULL || outArr == NULL) {
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ in = (unsigned char*)malloc(inLen);
|
|
+ int outLen = (*env)->GetArrayLength(env, outArr) - outOfs;
|
|
+ out = (unsigned char*)malloc(outLen);
|
|
+ if (in == NULL || out == NULL) {
|
|
+ KAE_ThrowOOMException(env, "malloc error");
|
|
+ goto cleanup;
|
|
+ }
|
|
+ memset(in, 0, inLen);
|
|
+ memset(out, 0, outLen);
|
|
+ (*env)->GetByteArrayRegion(env, inArr, inOfs, inLen, (jbyte*)in);
|
|
+
|
|
+ int bytesWritten = 0;
|
|
+ if (gcm && (gcmAAD != NULL)) {
|
|
+ int aadLen = (*env)->GetArrayLength(env, gcmAAD);
|
|
+ if ((aad = (unsigned char*)malloc(aadLen)) == NULL) {
|
|
+ KAE_ThrowOOMException(env, "malloc error");
|
|
+ goto cleanup;
|
|
+ }
|
|
+ memset(aad, 0, aadLen);
|
|
+ (*env)->GetByteArrayRegion(env, gcmAAD, 0, aadLen, (jbyte*)aad);
|
|
+
|
|
+ // Specify aad.
|
|
+ if (EVP_CipherUpdate(ctx, NULL, &bytesWritten, aad, aadLen) == 0) {
|
|
+ KAE_ThrowFromOpenssl(env, "EVP_CipherUpdate failed", KAE_ThrowRuntimeException);
|
|
+ goto cleanup;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (EVP_CipherUpdate(ctx, out, &bytesWritten, in, inLen) == 0) {
|
|
+ KAE_ThrowFromOpenssl(env, "EVP_CipherUpdate failed", KAE_ThrowRuntimeException);
|
|
+ goto cleanup;
|
|
+ }
|
|
+ (*env)->SetByteArrayRegion(env, outArr, outOfs, bytesWritten, (jbyte*)out);
|
|
+
|
|
+ FreeMemoryFromUpdate(in, aad, out);
|
|
+ return bytesWritten;
|
|
+
|
|
+cleanup:
|
|
+ FreeMemoryFromUpdate(in, aad, out);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Class: org_openeuler_security_openssl_KAESymmetricCipherBase
|
|
+ * Method: nativeFinal
|
|
+ * Signature: (JZ[BI)I
|
|
+ */
|
|
+JNIEXPORT jint JNICALL
|
|
+Java_org_openeuler_security_openssl_KAESymmetricCipherBase_nativeFinal(JNIEnv* env, jclass cls,
|
|
+ jlong ctxAddress, jbyteArray outArr, jint outOfs)
|
|
+{
|
|
+ unsigned char* out = NULL;
|
|
+ EVP_CIPHER_CTX* ctx = (EVP_CIPHER_CTX*)ctxAddress;
|
|
+ KAE_TRACE("KAESymmetricCipherBase_nativeFinal(ctxAddress = %p, outArr = %p, outOfs = %d)",
|
|
+ ctx, outArr, outOfs);
|
|
+ if (ctx == NULL || outArr == NULL) {
|
|
+ goto cleanup;
|
|
+ }
|
|
+ int outLen = (*env)->GetArrayLength(env, outArr) - outOfs;
|
|
+ out = (unsigned char*)malloc(outLen);
|
|
+ if (out == NULL) {
|
|
+ KAE_ThrowOOMException(env, "malloc error");
|
|
+ goto cleanup;
|
|
+ }
|
|
+ memset(out, 0, outLen);
|
|
+ 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 cleanup;
|
|
+ }
|
|
+ KAE_TRACE("KAESymmetricCipherBase_nativeFinal EVP_CipherFinal_ex success, bytesWritten = %d", bytesWritten);
|
|
+ (*env)->SetByteArrayRegion(env, outArr, outOfs, bytesWritten, (jbyte*)out);
|
|
+ free(out);
|
|
+ KAE_TRACE("KAESymmetricCipherBase_nativeFinal: finished");
|
|
+ return bytesWritten;
|
|
+
|
|
+cleanup:
|
|
+ if (out != NULL) {
|
|
+ free(out);
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static void FreeMemoryFromFinalGcm(unsigned char* out, unsigned char* gcmTag, unsigned char* gcmOut)
|
|
+{
|
|
+ if (out != NULL) {
|
|
+ free(out);
|
|
+ }
|
|
+ if (gcmTag != NULL) {
|
|
+ free(gcmTag);
|
|
+ }
|
|
+ if (gcmOut != NULL) {
|
|
+ free(gcmOut);
|
|
+ }
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Class: org_openeuler_security_openssl_KAECipherAES
|
|
+ * Method: nativeFinalGcm
|
|
+ * Signature: (J[BIZI[BZ)I
|
|
+ */
|
|
+JNIEXPORT jint JNICALL Java_org_openeuler_security_openssl_KAESymmetricCipherBase_nativeFinalGcm(JNIEnv* env,
|
|
+ jclass cls, jlong ctxAddress, jbyteArray outArr, jint outOfs, jboolean gcm, jint tagLength,
|
|
+ jbyteArray gcmTagArr, jboolean encrypt)
|
|
+{
|
|
+ unsigned char* out = NULL;
|
|
+ unsigned char* gcmTag = NULL;
|
|
+ unsigned char* gcmOut = NULL;
|
|
+
|
|
+ EVP_CIPHER_CTX* ctx = (EVP_CIPHER_CTX*)ctxAddress;
|
|
+ if (ctx == NULL || outArr == NULL) {
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ int bytesWritten = 0;
|
|
+ if (encrypt) {
|
|
+ int outLen = (*env)->GetArrayLength(env, outArr) - outOfs;
|
|
+ if ((out = malloc(outLen)) == NULL) {
|
|
+ KAE_ThrowOOMException(env, "malloc error");
|
|
+ goto cleanup;
|
|
+ }
|
|
+ memset(out, 0, outLen);
|
|
+ if (EVP_CipherFinal_ex(ctx, out, &bytesWritten) == 0) {
|
|
+ KAE_ThrowFromOpenssl(env, "EVP_CipherFinal_ex failed", KAE_ThrowBadPaddingException);
|
|
+ goto cleanup;
|
|
+ }
|
|
+ (*env)->SetByteArrayRegion(env, outArr, outOfs, bytesWritten, (jbyte*)out);
|
|
+
|
|
+ // Writes tagLength bytes of the tag value to the buffer.
|
|
+ // Refer to {@link https://www.openssl.org/docs/man1.1.0/man3/EVP_CIPHER_CTX_ctrl.html} for details.
|
|
+ if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, tagLength, out + bytesWritten) == 0) {
|
|
+ KAE_ThrowFromOpenssl(env, "EVP_CIPHER_CTX_ctrl failed", KAE_ThrowRuntimeException);
|
|
+ goto cleanup;
|
|
+ }
|
|
+ (*env)->SetByteArrayRegion(env, outArr, outOfs + bytesWritten, tagLength, (jbyte*)(out + bytesWritten));
|
|
+ bytesWritten += tagLength;
|
|
+ } else {
|
|
+ // gcmOut is the plaintext that has been decrypted in the EVP_CipherUpdate.
|
|
+ // outOfs is the length of the gcmOut, where it's always > 0.
|
|
+ if ((gcmTag = (unsigned char*)malloc(tagLength)) == NULL || (gcmOut = (unsigned char*)malloc(outOfs)) == NULL) {
|
|
+ KAE_ThrowOOMException(env, "malloc error");
|
|
+ goto cleanup;
|
|
+ }
|
|
+ memset(gcmTag, 0, tagLength);
|
|
+ memset(gcmOut, 0, outOfs);
|
|
+
|
|
+ (*env)->GetByteArrayRegion(env, gcmTagArr, 0, tagLength, (jbyte*)gcmTag);
|
|
+ // Sets the expected gcmTag to tagLength bytes from gcmTag.
|
|
+ // Refer to {@link https://www.openssl.org/docs/man1.1.0/man3/EVP_CIPHER_CTX_ctrl.html} for details.
|
|
+ if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, tagLength, gcmTag) == 0) {
|
|
+ KAE_ThrowFromOpenssl(env, "EVP_CTRL_AEAD_SET_TAG failed", KAE_ThrowRuntimeException);
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ (*env)->GetByteArrayRegion(env, outArr, 0, outOfs, (jbyte*)gcmOut);
|
|
+ // Finalise: note get no output for GCM
|
|
+ if (EVP_CipherFinal_ex(ctx, gcmOut, &bytesWritten) == 0) {
|
|
+ KAE_ThrowFromOpenssl(env, "EVP_CipherFinal_ex failed", KAE_ThrowAEADBadTagException);
|
|
+ goto cleanup;
|
|
+ }
|
|
+ }
|
|
+ FreeMemoryFromFinalGcm(out, gcmTag, gcmOut);
|
|
+
|
|
+ return bytesWritten;
|
|
+
|
|
+cleanup:
|
|
+ FreeMemoryFromFinalGcm(out, gcmTag, gcmOut);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Class: org_openeuler_security_openssl_KAESymmetricCipherBase
|
|
+ * Method: nativeFree
|
|
+ * Signature: (J)V
|
|
+ */
|
|
+JNIEXPORT void JNICALL
|
|
+Java_org_openeuler_security_openssl_KAESymmetricCipherBase_nativeFree(JNIEnv* env, jclass cls, jlong ctxAddress)
|
|
+{
|
|
+ EVP_CIPHER_CTX* ctx = (EVP_CIPHER_CTX*)ctxAddress;
|
|
+ KAE_TRACE("KAESymmetricCipherBase_nativeFree(ctx = %p)", ctx);
|
|
+ if (ctx != NULL) {
|
|
+ EVP_CIPHER_CTX_free(ctx);
|
|
+ ctx = NULL;
|
|
+ }
|
|
+
|
|
+ KAE_TRACE("KAESymmetricCipherBase_nativeFree: finished");
|
|
+}
|
|
diff --git a/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_util.c b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_util.c
|
|
new file mode 100644
|
|
index 000000000..7ac3cbe8d
|
|
--- /dev/null
|
|
+++ b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_util.c
|
|
@@ -0,0 +1,111 @@
|
|
+/*
|
|
+ * 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"
|
|
+
|
|
+static ENGINE* kaeEngine = NULL;
|
|
+
|
|
+void SetKaeEngine(ENGINE* engine) {
|
|
+ kaeEngine = engine;
|
|
+}
|
|
+
|
|
+ENGINE* GetKaeEngine() {
|
|
+ return kaeEngine;
|
|
+}
|
|
+
|
|
+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 cleanup;
|
|
+ }
|
|
+ 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 cleanup;
|
|
+ }
|
|
+ return bn;
|
|
+
|
|
+cleanup:
|
|
+ BN_free(bn);
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+void KAE_ReleaseBigNumFromByteArray(BIGNUM* bn) {
|
|
+ if (bn != NULL) {
|
|
+ BN_free(bn);
|
|
+ }
|
|
+}
|
|
+
|
|
+jbyteArray KAE_GetByteArrayFromBigNum(JNIEnv* env, const BIGNUM* bn) {
|
|
+ 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/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_util.h b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_util.h
|
|
new file mode 100644
|
|
index 000000000..13bd5976d
|
|
--- /dev/null
|
|
+++ b/src/jdk.crypto.kaeprovider/linux/native/libj2kae/org/openeuler/security/openssl/kae_util.h
|
|
@@ -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.
|
|
+ */
|
|
+
|
|
+#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);
|
|
+
|
|
+void SetKaeEngine(ENGINE* engine);
|
|
+
|
|
+ENGINE* GetKaeEngine();
|
|
+
|
|
+void SetKaeEngine(ENGINE* engine);
|
|
+
|
|
+ENGINE* GetKaeEngine();
|
|
+
|
|
+#endif
|
|
diff --git a/test/jdk/TEST.groups b/test/jdk/TEST.groups
|
|
index 4073eec20..8dc2abf86 100644
|
|
--- a/test/jdk/TEST.groups
|
|
+++ b/test/jdk/TEST.groups
|
|
@@ -242,6 +242,9 @@ jdk_security = \
|
|
jdk_security_infra = \
|
|
security/infra/java/security/cert/CertPathValidator/certification
|
|
|
|
+jdk_kae_security = \
|
|
+ org/openeuler/security/openssl
|
|
+
|
|
jdk_text = \
|
|
java/text \
|
|
sun/text
|
|
diff --git a/test/jdk/java/security/KeyAgreement/KeyAgreementTest.java b/test/jdk/java/security/KeyAgreement/KeyAgreementTest.java
|
|
index 8f705abd7..9968dea56 100644
|
|
--- a/test/jdk/java/security/KeyAgreement/KeyAgreementTest.java
|
|
+++ b/test/jdk/java/security/KeyAgreement/KeyAgreementTest.java
|
|
@@ -39,6 +39,7 @@ import java.security.KeyPairGenerator;
|
|
import java.security.spec.NamedParameterSpec;
|
|
import java.security.spec.AlgorithmParameterSpec;
|
|
import java.security.spec.ECGenParameterSpec;
|
|
+import java.security.Security;
|
|
import java.util.ArrayList;
|
|
import java.util.Arrays;
|
|
import java.util.List;
|
|
@@ -52,7 +53,14 @@ public class KeyAgreementTest {
|
|
String kaAlgo = args[0];
|
|
String kpgAlgo = args[1];
|
|
String provider = args[2];
|
|
- AlgoSpec aSpec = AlgoSpec.valueOf(AlgoSpec.class, kaAlgo);
|
|
+ AlgoSpec aSpec;
|
|
+ if (Security.getProperty("security.provider.1").equals("KAEProvider") &&
|
|
+ kaAlgo.equals("ECDH")) {
|
|
+ aSpec = AlgoSpec.valueOf(AlgoSpec.class, "KAEECDH");
|
|
+ } else {
|
|
+ aSpec = AlgoSpec.valueOf(AlgoSpec.class, kaAlgo);
|
|
+ }
|
|
+
|
|
List<AlgorithmParameterSpec> specs = aSpec.getAlgorithmParameterSpecs();
|
|
for (AlgorithmParameterSpec spec : specs) {
|
|
testKeyAgreement(provider, kaAlgo, kpgAlgo, spec);
|
|
@@ -87,6 +95,7 @@ public class KeyAgreementTest {
|
|
"X9.62 c2tnb239v1", "X9.62 c2tnb239v2", "X9.62 c2tnb239v3",
|
|
"X9.62 c2tnb359v1", "X9.62 c2tnb431r1"
|
|
),
|
|
+ KAEECDH("secp224r1", "secp256r1", "secp384r1", "secp521r1"),
|
|
XDH("X25519", "X448"),
|
|
// There is no curve for DiffieHellman
|
|
DiffieHellman(new String[]{});
|
|
@@ -98,6 +107,7 @@ public class KeyAgreementTest {
|
|
for (String crv : curves) {
|
|
switch (this.name()) {
|
|
case "ECDH":
|
|
+ case "KAEECDH":
|
|
specs.add(new ECGenParameterSpec(crv));
|
|
break;
|
|
case "XDH":
|
|
diff --git a/test/jdk/java/security/Signature/SignatureGetInstance.java b/test/jdk/java/security/Signature/SignatureGetInstance.java
|
|
index c246773f8..b69258cd9 100644
|
|
--- a/test/jdk/java/security/Signature/SignatureGetInstance.java
|
|
+++ b/test/jdk/java/security/Signature/SignatureGetInstance.java
|
|
@@ -49,8 +49,11 @@ public class SignatureGetInstance {
|
|
MyPrivKey testPriv = new MyPrivKey();
|
|
MyPubKey testPub = new MyPubKey();
|
|
|
|
+ Provider kaeProvider = Security.getProvider("KAEProvider");
|
|
+ String expectedProvName = kaeProvider != null ? "KAEProvider" : "SunRsaSign";
|
|
+
|
|
testDblInit(testPriv, testPub, true, "TestProvider");
|
|
- testDblInit(kp.getPrivate(), kp.getPublic(), true, "SunRsaSign");
|
|
+ testDblInit(kp.getPrivate(), kp.getPublic(), true, expectedProvName);
|
|
testDblInit(testPriv, kp.getPublic(), false, null);
|
|
testDblInit(kp.getPrivate(), testPub, false, null);
|
|
|
|
diff --git a/test/jdk/org/openeuler/security/openssl/DHTest.java b/test/jdk/org/openeuler/security/openssl/DHTest.java
|
|
new file mode 100644
|
|
index 000000000..6eb5e7c96
|
|
--- /dev/null
|
|
+++ b/test/jdk/org/openeuler/security/openssl/DHTest.java
|
|
@@ -0,0 +1,130 @@
|
|
+/*
|
|
+ * 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.
|
|
+ */
|
|
+
|
|
+
|
|
+import java.io.Serializable;
|
|
+import java.math.BigInteger;
|
|
+import java.security.*;
|
|
+import java.util.Arrays;
|
|
+import java.util.Date;
|
|
+import javax.crypto.KeyAgreement;
|
|
+import javax.crypto.spec.*;
|
|
+import org.openeuler.security.openssl.KAEProvider;
|
|
+
|
|
+/**
|
|
+ * This class implements the Diffie-Hellman key exchange algorithm.
|
|
+ * D-H means combining your private key with your partners public key to
|
|
+ * generate a number. The peer does the same with its private key and our
|
|
+ * public key. Through the magic of Diffie-Hellman we both come up with the
|
|
+ * same number. This number is secret (discounting MITM attacks) and hence
|
|
+ * called the shared secret. It has the same length as the modulus, e.g. 512
|
|
+ * or 1024 bit. Man-in-the-middle attacks are typically countered by an
|
|
+ * independent authentication step using certificates (RSA, DSA, etc.).
|
|
+ *
|
|
+ * The thing to note is that the shared secret is constant for two partners
|
|
+ * with constant private keys. This is often not what we want, which is why
|
|
+ * it is generally a good idea to create a new private key for each session.
|
|
+ * Generating a private key involves one modular exponentiation assuming
|
|
+ * suitable D-H parameters are available.
|
|
+ *
|
|
+ * General usage of this class (TLS DHE case):
|
|
+ * . if we are server, call DHCrypt(keyLength,random). This generates
|
|
+ * an ephemeral keypair of the request length.
|
|
+ * . if we are client, call DHCrypt(modulus, base, random). This
|
|
+ * generates an ephemeral keypair using the parameters specified by
|
|
+ * the server.
|
|
+ * . send parameters and public value to remote peer
|
|
+ * . receive peers ephemeral public key
|
|
+ * . call getAgreedSecret() to calculate the shared secret
|
|
+ *
|
|
+ * In TLS the server chooses the parameter values itself, the client must use
|
|
+ * those sent to it by the server.
|
|
+ *
|
|
+ * The use of ephemeral keys as described above also achieves what is called
|
|
+ * "forward secrecy". This means that even if the authentication keys are
|
|
+ * broken at a later date, the shared secret remains secure. The session is
|
|
+ * compromised only if the authentication keys are already broken at the
|
|
+ * time the key exchange takes place and an active MITM attack is used.
|
|
+ * This is in contrast to straightforward encrypting RSA key exchanges.
|
|
+ *
|
|
+ */
|
|
+
|
|
+
|
|
+/**
|
|
+ * @test
|
|
+ * @summary Basic test for DH
|
|
+ * @run main DHTest
|
|
+ */
|
|
+
|
|
+final class DHTest implements Serializable {
|
|
+ private static int bitLength = 8192;
|
|
+ private static BigInteger g512;
|
|
+ private static BigInteger p512;
|
|
+ Throwable t = null;
|
|
+
|
|
+ private static volatile Provider sunJceProvider;
|
|
+ private static volatile Provider kaeProvider;
|
|
+ Date d = new Date();
|
|
+
|
|
+ public static void main(String[] args) throws Exception {
|
|
+ Security.addProvider(new KAEProvider());
|
|
+ sunJceProvider = Security.getProvider("SunJCE");
|
|
+ kaeProvider = Security.getProvider("KAEProvider");
|
|
+
|
|
+ g512 = new BigInteger("30270326776012916323988175351831539351616124181011347910931933302640902603480679235129557617566480716138395926949700593986872757726720164601940036524221141391913433558162442022339559255078339658108149162251643458301671465579040759659507434340437396584664407572026953757806341363255195983514333141770938654900099033797866272818739547343977583089845850158637618703095710047154252655157633638171416516716598940884520592858762209135010804267830977334033327483815694794951984230264309784679409488441905236794443014066406150649287037909246107758452315504212879842042858577191624250834553614056794526338841821045329189780334");
|
|
+
|
|
+ p512 = new BigInteger("27672987386729926592037876826877634387173876890702920770064392919138769821035856568775311919542560094764667151024449425954917954337048895981297730855891532066350935045229294626339548842381843985759061682551900379979643117695834175891578650111093016914264824311693147701566019122696621248493126219217339690346346921463135605151471303957324058301097079967414639146647429422884520134312590056632178576758580657240245655739869017244657144448267757255018625514803292549109401806336918448001843022629625467069714240279603204909633404992842479161100500474744098408277938070656334892106100534117209709263785505019003765693651");
|
|
+
|
|
+ DHTest.bitLength = 0;
|
|
+
|
|
+ DHParameterSpec dhParams = new DHParameterSpec(p512, g512);
|
|
+ KeyPairGenerator SunJCEkeyGen = KeyPairGenerator.getInstance("DH", sunJceProvider);
|
|
+ KeyPairGenerator KAEkeyGen = KeyPairGenerator.getInstance("DH", kaeProvider);
|
|
+ SunJCEkeyGen.initialize(dhParams, new SecureRandom());
|
|
+ KAEkeyGen.initialize(dhParams, new SecureRandom());
|
|
+ KeyAgreement aKeyAgree = KeyAgreement.getInstance("DH", sunJceProvider);
|
|
+ KeyPair aPair = SunJCEkeyGen.generateKeyPair();
|
|
+ KeyAgreement bKeyAgree = KeyAgreement.getInstance("DH", kaeProvider);
|
|
+ KeyPair bPair = KAEkeyGen.generateKeyPair();
|
|
+
|
|
+ aKeyAgree.init(aPair.getPrivate());
|
|
+ bKeyAgree.init(bPair.getPrivate());
|
|
+
|
|
+ aKeyAgree.doPhase(bPair.getPublic(), true);
|
|
+ bKeyAgree.doPhase(aPair.getPublic(), true);
|
|
+
|
|
+ MessageDigest hash = MessageDigest.getInstance("MD5");
|
|
+ byte[] b1 = hash.digest(aKeyAgree.generateSecret());
|
|
+ byte[] b2 = hash.digest(bKeyAgree.generateSecret());
|
|
+ if(Arrays.equals(b1, b2)){
|
|
+ System.out.println("SUCCESS!");
|
|
+ }else{
|
|
+ System.out.println("Failed!");
|
|
+ throw new RuntimeException("Not Equal DH keyagreement ouput from SunJCE and KAE Provider!");
|
|
+ }
|
|
+
|
|
+ }
|
|
+
|
|
+}
|
|
diff --git a/test/jdk/org/openeuler/security/openssl/ECDHTest.java b/test/jdk/org/openeuler/security/openssl/ECDHTest.java
|
|
new file mode 100644
|
|
index 000000000..9c836495b
|
|
--- /dev/null
|
|
+++ b/test/jdk/org/openeuler/security/openssl/ECDHTest.java
|
|
@@ -0,0 +1,117 @@
|
|
+/*
|
|
+ * Copyright (c) 2021, Huawei Technologies Co., Ltd. All rights reserved.
|
|
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
+ *
|
|
+ * This code is free software; you can redistribute it and/or modify it
|
|
+ * under the terms of the GNU General Public License version 2 only, as
|
|
+ * published by the Free Software Foundation.
|
|
+ *
|
|
+ * This code is distributed in the hope that it will be useful, but WITHOUT
|
|
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
+ * version 2 for more details (a copy is included in the LICENSE file that
|
|
+ * accompanied this code).
|
|
+ *
|
|
+ * You should have received a copy of the GNU General Public License version
|
|
+ * 2 along with this work; if not, write to the Free Software Foundation,
|
|
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
+ *
|
|
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
+ * or visit www.oracle.com if you need additional information or have any
|
|
+ * questions.
|
|
+ */
|
|
+
|
|
+import org.openeuler.security.openssl.KAEProvider;
|
|
+import sun.security.ec.ECPrivateKeyImpl;
|
|
+import sun.security.ec.ECPublicKeyImpl;
|
|
+
|
|
+import javax.crypto.KeyAgreement;
|
|
+import java.lang.reflect.Constructor;
|
|
+import java.lang.reflect.InvocationTargetException;
|
|
+import java.math.BigInteger;
|
|
+import java.security.KeyPair;
|
|
+import java.security.KeyPairGenerator;
|
|
+import java.security.Provider;
|
|
+import java.security.Security;
|
|
+import java.security.spec.ECFieldFp;
|
|
+import java.security.spec.ECParameterSpec;
|
|
+import java.security.spec.ECPoint;
|
|
+import java.security.spec.EllipticCurve;
|
|
+import java.util.Arrays;
|
|
+import java.nio.charset.StandardCharsets;
|
|
+
|
|
+/**
|
|
+ * @test
|
|
+ * @summary Basic test for ECDH
|
|
+ * @run main ECDHTest
|
|
+ */
|
|
+
|
|
+public class ECDHTest {
|
|
+
|
|
+ private static KeyPairGenerator keyPairGenerator;
|
|
+ private static String algorithm = "EC";
|
|
+ private static int[] keyArr = {224, 256, 384, 521};
|
|
+
|
|
+ public static void main(String[] args) throws Exception {
|
|
+ Security.insertProviderAt(new KAEProvider(), 1);
|
|
+
|
|
+ BigInteger a = new BigInteger("26959946667150639794667015087019630673557916260026308143510066298878");
|
|
+ BigInteger b = new BigInteger("18958286285566608000408668544493926415504680968679321075787234672564");
|
|
+ BigInteger p = new BigInteger("26959946667150639794667015087019630673557916260026308143510066298881");
|
|
+ BigInteger x = new BigInteger("19277929113566293071110308034699488026831934219452440156649784352033");
|
|
+ BigInteger y = new BigInteger("19926808758034470970197974370888749184205991990603949537637343198772");
|
|
+ EllipticCurve CURVE = new EllipticCurve(new ECFieldFp(p), a, b);
|
|
+ ECPoint POINT = new ECPoint(x, y);
|
|
+ BigInteger ORDER = new BigInteger("26959946667150639794667015087019625940457807714424391721682722368061");
|
|
+ int COFACTOR = 1;
|
|
+ ECParameterSpec PARAMS = new ECParameterSpec(CURVE, POINT, ORDER, COFACTOR);
|
|
+
|
|
+ testKeyPairByParam(PARAMS);
|
|
+ for (int keySize : keyArr) {
|
|
+ testKeyPairByKeySize(keySize);
|
|
+ }
|
|
+
|
|
+ Class<?> priKeyImpl = Class.forName("sun.security.ec.ECPrivateKeyImpl");
|
|
+ Constructor<?> conPriKeyImpl = priKeyImpl.getDeclaredConstructor(BigInteger.class, ECParameterSpec.class);
|
|
+ conPriKeyImpl.setAccessible(true);
|
|
+ ECPrivateKeyImpl ecPrivKey = (ECPrivateKeyImpl) conPriKeyImpl.newInstance(
|
|
+ new BigInteger("20135071615800221517902437867016717688420688735490569283842831828983"), PARAMS);
|
|
+
|
|
+ ECPoint ecPoint = new ECPoint(new BigInteger("9490267631555585552004372465967099662885480699902812460349461311384"),
|
|
+ new BigInteger("1974573604976093871117393045089050409882519645527397292712281520811"));
|
|
+ Class<?> pubKeyImpl = Class.forName("sun.security.ec.ECPublicKeyImpl");
|
|
+ Constructor<?> conPubKeyImpl = pubKeyImpl.getDeclaredConstructor(ECPoint.class, ECParameterSpec.class);
|
|
+ conPubKeyImpl.setAccessible(true);
|
|
+ ECPublicKeyImpl ecPublicKey = (ECPublicKeyImpl) conPubKeyImpl.newInstance(ecPoint, PARAMS);
|
|
+
|
|
+ testKeyAgreement(ecPrivKey, ecPublicKey,
|
|
+ new byte[]{-88, -65, 43, -84, 26, 43, 46, 106, 20, 39, -76, 30, -71, 72, -102, 120, 108, -92, -86, -14, -96, -42, 93, -40, -43, -25, 15, -62});
|
|
+
|
|
+ }
|
|
+
|
|
+ public static void testKeyPairByParam(ECParameterSpec PARAMS) throws Exception {
|
|
+ keyPairGenerator = KeyPairGenerator.getInstance(algorithm);
|
|
+ keyPairGenerator.initialize(PARAMS);
|
|
+ KeyPair keyPair = keyPairGenerator.generateKeyPair();
|
|
+ ECPrivateKeyImpl ecPrivKey = (ECPrivateKeyImpl) keyPair.getPrivate();
|
|
+ ECPublicKeyImpl ecPublicKey = (ECPublicKeyImpl) keyPair.getPublic();
|
|
+ }
|
|
+
|
|
+ public static void testKeyPairByKeySize(int keySize) throws Exception {
|
|
+ keyPairGenerator = KeyPairGenerator.getInstance(algorithm);
|
|
+ keyPairGenerator.initialize(keySize);
|
|
+ KeyPair keyPair = keyPairGenerator.generateKeyPair();
|
|
+ ECPrivateKeyImpl ecPrivKey = (ECPrivateKeyImpl) keyPair.getPrivate();
|
|
+ ECPublicKeyImpl ecPublicKey = (ECPublicKeyImpl) keyPair.getPublic();
|
|
+ }
|
|
+
|
|
+ public static void testKeyAgreement(ECPrivateKeyImpl ecPrivKey, ECPublicKeyImpl ecPublicKey, byte[] expectRes) throws Exception {
|
|
+ KeyAgreement keyAgreement = KeyAgreement.getInstance("ECDH");
|
|
+ keyAgreement.init(ecPrivKey);
|
|
+ keyAgreement.doPhase(ecPublicKey, true);
|
|
+ byte[] res = keyAgreement.generateSecret();
|
|
+ if (!Arrays.equals(res, expectRes)) {
|
|
+ throw new RuntimeException("keyagreement failed");
|
|
+ }
|
|
+ }
|
|
+}
|
|
diff --git a/test/jdk/org/openeuler/security/openssl/SM3Test.java b/test/jdk/org/openeuler/security/openssl/SM3Test.java
|
|
new file mode 100644
|
|
index 000000000..181f708ff
|
|
--- /dev/null
|
|
+++ b/test/jdk/org/openeuler/security/openssl/SM3Test.java
|
|
@@ -0,0 +1,54 @@
|
|
+/*
|
|
+ * Copyright (c) 2021, Huawei Technologies Co., Ltd. All rights reserved.
|
|
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
+ *
|
|
+ * This code is free software; you can redistribute it and/or modify it
|
|
+ * under the terms of the GNU General Public License version 2 only, as
|
|
+ * published by the Free Software Foundation.
|
|
+ *
|
|
+ * This code is distributed in the hope that it will be useful, but WITHOUT
|
|
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
+ * version 2 for more details (a copy is included in the LICENSE file that
|
|
+ * accompanied this code).
|
|
+ *
|
|
+ * You should have received a copy of the GNU General Public License version
|
|
+ * 2 along with this work; if not, write to the Free Software Foundation,
|
|
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
+ *
|
|
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
+ * or visit www.oracle.com if you need additional information or have any
|
|
+ * questions.
|
|
+ */
|
|
+
|
|
+import org.openeuler.security.openssl.KAEProvider;
|
|
+import java.nio.charset.StandardCharsets;
|
|
+import java.util.Arrays;
|
|
+import java.security.MessageDigest;
|
|
+import java.security.Security;
|
|
+
|
|
+/**
|
|
+ * @test
|
|
+ * @summary Basic test for sm3
|
|
+ * @run main SM3Test
|
|
+ */
|
|
+
|
|
+public class SM3Test {
|
|
+
|
|
+ private static String plainText = "helloworldhellow";
|
|
+
|
|
+ public static void main(String[] args) throws Exception {
|
|
+ Security.insertProviderAt(new KAEProvider(), 1);
|
|
+ test(plainText, "SM3", new byte[]{40, -103, -71, 4, -80, -49, 94, 112, 11, -75, -66, 121, 63, 80, 62, -14, -45, -75, -34, 66, -77, -34, -26, 26, 33, -23, 45, 52, -74, 67, -18, 118});
|
|
+ }
|
|
+
|
|
+ public static void test(String plainText, String algo, byte[] expectRes) throws Exception {
|
|
+ MessageDigest md = MessageDigest.getInstance(algo);
|
|
+ md.update(plainText.getBytes(StandardCharsets.UTF_8));
|
|
+ byte[] res = md.digest();
|
|
+ if (!Arrays.equals(res, expectRes)) {
|
|
+ throw new RuntimeException("sm3 failed");
|
|
+ }
|
|
+ }
|
|
+
|
|
+}
|
|
diff --git a/test/jdk/org/openeuler/security/openssl/SM4Test.java b/test/jdk/org/openeuler/security/openssl/SM4Test.java
|
|
new file mode 100644
|
|
index 000000000..4c28dc5b6
|
|
--- /dev/null
|
|
+++ b/test/jdk/org/openeuler/security/openssl/SM4Test.java
|
|
@@ -0,0 +1,95 @@
|
|
+/*
|
|
+ * Copyright (c) 2021, Huawei Technologies Co., Ltd. All rights reserved.
|
|
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
+ *
|
|
+ * This code is free software; you can redistribute it and/or modify it
|
|
+ * under the terms of the GNU General Public License version 2 only, as
|
|
+ * published by the Free Software Foundation.
|
|
+ *
|
|
+ * This code is distributed in the hope that it will be useful, but WITHOUT
|
|
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
+ * version 2 for more details (a copy is included in the LICENSE file that
|
|
+ * accompanied this code).
|
|
+ *
|
|
+ * You should have received a copy of the GNU General Public License version
|
|
+ * 2 along with this work; if not, write to the Free Software Foundation,
|
|
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
+ *
|
|
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
+ * or visit www.oracle.com if you need additional information or have any
|
|
+ * questions.
|
|
+ */
|
|
+
|
|
+import org.openeuler.security.openssl.KAEProvider;
|
|
+import java.nio.charset.StandardCharsets;
|
|
+import java.util.Arrays;
|
|
+import java.security.NoSuchAlgorithmException;
|
|
+import java.security.Security;
|
|
+import javax.crypto.Cipher;
|
|
+import javax.crypto.spec.IvParameterSpec;
|
|
+import javax.crypto.spec.SecretKeySpec;
|
|
+
|
|
+/**
|
|
+ * @test
|
|
+ * @summary Basic test for sm4
|
|
+ * @run main SM4Test
|
|
+ */
|
|
+
|
|
+public class SM4Test {
|
|
+
|
|
+ private static SecretKeySpec ks = new SecretKeySpec("sm4EncryptionKey".getBytes(StandardCharsets.UTF_8), "SM4"); // key has 16 bytes
|
|
+ private static IvParameterSpec iv = new IvParameterSpec("abcdefghabcdefgh".getBytes(StandardCharsets.UTF_8)); // iv has 16 bytes
|
|
+ private static IvParameterSpec shortIv = new IvParameterSpec("abcdefgh".getBytes(StandardCharsets.UTF_8)); // CTR support >= 8bytes iv
|
|
+ private static String plainText = "helloworldhellow"; // 16bytes for NoPadding
|
|
+ private static String shortPlainText = "helloworld"; // 5 bytes for padding
|
|
+
|
|
+ public static void main(String[] args) throws Exception {
|
|
+ Security.insertProviderAt(new KAEProvider(), 1);
|
|
+ test(plainText, "SM4/CBC/NOPADDING", new byte[]{86, 69, 47, -115, -63, 54, 35, 24, -2, 114, 113, 102, 82, 20, 69, 59});
|
|
+ test(shortPlainText, "SM4/CBC/PKCS5Padding", new byte[]{10, 105, 75, -80, -85, -68, 13, -53, 42, 91, -64, 99, 104, 35, -85, 8});
|
|
+ test(plainText, "SM4/ECB/NOPADDING", new byte[]{103, 36, -31, -53, -109, -12, -71, -79, -54, 106, 10, -3, -35, -22, -122, -67});
|
|
+ test(shortPlainText, "SM4/ECB/PKCS5Padding", new byte[]{-10, 99, -9, 90, 58, -36, -109, 54, -55, -52, 7, -49, 110, -88, 72, 40});
|
|
+ test(plainText, "SM4/CTR/NOPADDING", new byte[]{32, 108, 35, 108, -16, 119, -111, 114, 94, 110, -100, -113, -46, -29, -11, 71});
|
|
+ test(plainText, "SM4/OFB/NOPADDING", new byte[]{32, 108, 35, 108, -16, 119, -111, 114, 94, 110, -100, -113, -46, -29, -11, 71});
|
|
+ test(shortPlainText, "SM4/OFB/PKCS5Padding", new byte[]{32, 108, 35, 108, -16, 119, -111, 114, 94, 110});
|
|
+
|
|
+ testCtrShortIv(plainText, "SM4/CTR/NOPADDING", new byte[]{-13, 73, 40, -36, -64, -67, 75, -72, 90, 58, 73, -4, -36, 115, 126, -48});
|
|
+ }
|
|
+
|
|
+ public static void test(String plainText, String algo, byte[] expectRes) throws Exception {
|
|
+ Cipher encryptCipher = Cipher.getInstance(algo);
|
|
+ if (algo.contains("ECB")) {
|
|
+ encryptCipher.init(Cipher.ENCRYPT_MODE, ks);
|
|
+ } else {
|
|
+ encryptCipher.init(Cipher.ENCRYPT_MODE, ks, iv);
|
|
+ }
|
|
+ byte[] cipherText = encryptCipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));
|
|
+ if (!Arrays.equals(cipherText, expectRes)) {
|
|
+ throw new RuntimeException("sm4 encryption failed, algo = " + algo);
|
|
+ }
|
|
+
|
|
+ Cipher decryptCipher = Cipher.getInstance(algo);
|
|
+ decryptCipher.init(Cipher.DECRYPT_MODE, ks, encryptCipher.getParameters());
|
|
+ String decryptPlainText = new String(decryptCipher.doFinal(cipherText));
|
|
+ if (!plainText.equals(decryptPlainText)) {
|
|
+ throw new RuntimeException("sm4 decryption failed, algo = " + algo);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public static void testCtrShortIv(String plainText, String algo, byte[] expectRes) throws Exception {
|
|
+ Cipher encryptCipher = Cipher.getInstance(algo);
|
|
+ encryptCipher.init(Cipher.ENCRYPT_MODE, ks, shortIv);
|
|
+ byte[] cipherText = encryptCipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));
|
|
+ if (!Arrays.equals(cipherText, expectRes)) {
|
|
+ throw new RuntimeException("sm4 encryption failed, algo = " + algo);
|
|
+ }
|
|
+
|
|
+ Cipher decryptCipher = Cipher.getInstance(algo);
|
|
+ decryptCipher.init(Cipher.DECRYPT_MODE, ks, encryptCipher.getParameters());
|
|
+ String decryptPlainText = new String(decryptCipher.doFinal(cipherText));
|
|
+ if (!plainText.equals(decryptPlainText)) {
|
|
+ throw new RuntimeException("sm4 decryption failed, algo = " + algo);
|
|
+ }
|
|
+ }
|
|
+}
|
|
diff --git a/test/jdk/sun/security/jca/PreferredProviderNegativeTest.java b/test/jdk/sun/security/jca/PreferredProviderNegativeTest.java
|
|
index aee691016..6433416de 100644
|
|
--- a/test/jdk/sun/security/jca/PreferredProviderNegativeTest.java
|
|
+++ b/test/jdk/sun/security/jca/PreferredProviderNegativeTest.java
|
|
@@ -110,6 +110,8 @@ public class PreferredProviderNegativeTest {
|
|
// If OS is solaris, expect OracleUcrypto, otherwise SunJCE
|
|
if (System.getProperty("os.name").toLowerCase().contains("sun")) {
|
|
expected = "OracleUcrypto";
|
|
+ } else if (Security.getProperty("security.provider.1").equals("KAEProvider")) {
|
|
+ expected = "KAEProvider";
|
|
} else {
|
|
expected = "SunJCE";
|
|
}
|
|
diff --git a/test/jdk/sun/security/krb5/auto/BasicProc.java b/test/jdk/sun/security/krb5/auto/BasicProc.java
|
|
index 9e681af03..311cc7212 100644
|
|
--- a/test/jdk/sun/security/krb5/auto/BasicProc.java
|
|
+++ b/test/jdk/sun/security/krb5/auto/BasicProc.java
|
|
@@ -297,7 +297,9 @@ public class BasicProc {
|
|
Proc p = Proc.create("BasicProc")
|
|
.inheritProp("jdk.net.hosts.file")
|
|
.prop("java.security.manager", "")
|
|
- .perm(new javax.security.auth.AuthPermission("doAs"));
|
|
+ .perm(new javax.security.auth.AuthPermission("doAs"))
|
|
+ .perm(new java.util.PropertyPermission(
|
|
+ "kae.disableKaeDispose", "read"));
|
|
if (lib != null) {
|
|
p.env("KRB5_CONFIG", CONF)
|
|
.env("KRB5_TRACE", Platform.isWindows() ? "CON" : "/dev/stderr")
|
|
diff --git a/test/jdk/sun/security/pkcs11/Secmod/policy b/test/jdk/sun/security/pkcs11/Secmod/policy
|
|
index e4c95ca6d..60488fd06 100644
|
|
--- a/test/jdk/sun/security/pkcs11/Secmod/policy
|
|
+++ b/test/jdk/sun/security/pkcs11/Secmod/policy
|
|
@@ -3,4 +3,5 @@ grant {
|
|
permission java.io.FilePermission "${test.src}/-", "read";
|
|
permission java.io.FilePermission "${pkcs11test.nss.db}/-", "read";
|
|
permission java.io.FilePermission "${pkcs11test.nss.libdir}/-", "read";
|
|
+ permission java.util.PropertyPermission "kae.disableKaeDispose", "read";
|
|
};
|
|
\ No newline at end of file
|
|
diff --git a/test/jdk/sun/security/pkcs11/policy b/test/jdk/sun/security/pkcs11/policy
|
|
index 54281a781..4d887e239 100644
|
|
--- a/test/jdk/sun/security/pkcs11/policy
|
|
+++ b/test/jdk/sun/security/pkcs11/policy
|
|
@@ -1,3 +1,4 @@
|
|
grant {
|
|
permission java.lang.RuntimePermission "setSecurityManager";
|
|
+ permission java.util.PropertyPermission "kae.disableKaeDispose", "read";
|
|
};
|
|
\ No newline at end of file
|
|
diff --git a/test/jdk/sun/security/ssl/CipherSuite/DisabledCurve.java b/test/jdk/sun/security/ssl/CipherSuite/DisabledCurve.java
|
|
index c1be3a50e..8bf84f062 100644
|
|
--- a/test/jdk/sun/security/ssl/CipherSuite/DisabledCurve.java
|
|
+++ b/test/jdk/sun/security/ssl/CipherSuite/DisabledCurve.java
|
|
@@ -89,6 +89,10 @@ public class DisabledCurve extends SSLSocketTemplate {
|
|
}
|
|
|
|
public static void main(String[] args) throws Exception {
|
|
+ // KAEProvider does not support sect283r1
|
|
+ if (Security.getProperty("security.provider.1").equals("KAEProvider")) {
|
|
+ return;
|
|
+ }
|
|
String expected = args[1];
|
|
String disabledName = ("DISABLE_NONE".equals(args[0]) ? "" : args[0]);
|
|
if (disabledName.equals("")) {
|
|
diff --git a/test/jdk/sun/security/ssl/SSLSocketImpl/NotifyHandshakeTest.policy b/test/jdk/sun/security/ssl/SSLSocketImpl/NotifyHandshakeTest.policy
|
|
index b426b173f..6f65e48a3 100644
|
|
--- a/test/jdk/sun/security/ssl/SSLSocketImpl/NotifyHandshakeTest.policy
|
|
+++ b/test/jdk/sun/security/ssl/SSLSocketImpl/NotifyHandshakeTest.policy
|
|
@@ -33,5 +33,7 @@ grant codeBase "file:com.jar" {
|
|
"javax.net.ssl.trustStore", "write";
|
|
permission java.util.PropertyPermission
|
|
"javax.net.ssl.trustStorePassword", "write";
|
|
+ permission java.util.PropertyPermission
|
|
+ "kae.disableKaeDispose", "read";
|
|
};
|
|
|
|
diff --git a/test/micro/org/openeuler/bench/security/openssl/AESBenchmark.java b/test/micro/org/openeuler/bench/security/openssl/AESBenchmark.java
|
|
new file mode 100644
|
|
index 000000000..e075bb039
|
|
--- /dev/null
|
|
+++ b/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(jvmArgsPrepend = {"-Xms100G", "-Xmx100G", "-XX:+AlwaysPreTouch", "-Dkae.disableKaeDispose=true"}, value = 5)
|
|
+ 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(jvmArgsPrepend = {"-Xms100G", "-Xmx100G", "-XX:+AlwaysPreTouch", "-Dkae.disableKaeDispose=true"}, value = 5)
|
|
+ public byte[] decryptDispose() throws IllegalBlockSizeException, BadPaddingException {
|
|
+ byte[] e = encryptedData[index];
|
|
+ index = (index + 1) % SET_SIZE;
|
|
+ return decryptCipher.doFinal(e);
|
|
+ }
|
|
+}
|
|
+
|
|
diff --git a/test/micro/org/openeuler/bench/security/openssl/AESGCMBenchmark.java b/test/micro/org/openeuler/bench/security/openssl/AESGCMBenchmark.java
|
|
new file mode 100644
|
|
index 000000000..92eb6a592
|
|
--- /dev/null
|
|
+++ b/test/micro/org/openeuler/bench/security/openssl/AESGCMBenchmark.java
|
|
@@ -0,0 +1,133 @@
|
|
+/*
|
|
+ * 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. 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.bench.security.openssl;
|
|
+
|
|
+import org.openjdk.jmh.annotations.Benchmark;
|
|
+import org.openjdk.jmh.annotations.Param;
|
|
+import org.openjdk.jmh.annotations.Setup;
|
|
+import org.openjdk.jmh.annotations.Fork;
|
|
+
|
|
+import javax.crypto.BadPaddingException;
|
|
+import javax.crypto.Cipher;
|
|
+import javax.crypto.IllegalBlockSizeException;
|
|
+import javax.crypto.NoSuchPaddingException;
|
|
+import javax.crypto.spec.GCMParameterSpec;
|
|
+import javax.crypto.spec.SecretKeySpec;
|
|
+import java.security.InvalidAlgorithmParameterException;
|
|
+import java.security.InvalidKeyException;
|
|
+import java.security.NoSuchAlgorithmException;
|
|
+import java.security.spec.InvalidParameterSpecException;
|
|
+
|
|
+import java.security.Provider;
|
|
+
|
|
+
|
|
+public class AESGCMBenchmark extends BenchmarkBase{
|
|
+
|
|
+ @Param({"AES/GCM/NoPadding","AES/GCM/PKCS5Padding"})
|
|
+ private String algorithm;
|
|
+
|
|
+ @Param({"128", "192", "256"})
|
|
+ private int keyLength;
|
|
+
|
|
+ @Param({""+1024, "" + 10 * 1024, "" + 100 * 1024, "" + 1024 * 1024})
|
|
+ private int dataSize;
|
|
+
|
|
+ byte[] data;
|
|
+ byte[] encryptedData;
|
|
+ private Cipher encryptCipher;
|
|
+ private Cipher decryptCipher;
|
|
+ SecretKeySpec ks;
|
|
+ GCMParameterSpec gcm_spec;
|
|
+ byte[] aad;
|
|
+ byte[] iv;
|
|
+
|
|
+ public static final int IV_BUFFER_SIZE = 32;
|
|
+ public static final int IV_MODULO = IV_BUFFER_SIZE - 16;
|
|
+ int iv_index = 0;
|
|
+
|
|
+ private int next_iv_index() {
|
|
+ int r = iv_index;
|
|
+ iv_index = (iv_index + 1) % IV_MODULO;
|
|
+ return r;
|
|
+ }
|
|
+
|
|
+ @Setup
|
|
+ public void setup() throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException, InvalidParameterSpecException {
|
|
+ setupProvider();
|
|
+ assert algorithm.split("/")[1].compareToIgnoreCase("GCM") == 0;
|
|
+
|
|
+ byte[] keystring = fillSecureRandom(new byte[keyLength / 8]);
|
|
+ ks = new SecretKeySpec(keystring, "AES");
|
|
+ iv = fillSecureRandom(new byte[IV_BUFFER_SIZE]);
|
|
+ gcm_spec = new GCMParameterSpec(96, iv, next_iv_index(), 16);
|
|
+ aad = fillSecureRandom(new byte[5]);
|
|
+ encryptCipher = makeCipher(prov, algorithm);
|
|
+ encryptCipher.init(Cipher.ENCRYPT_MODE, ks, gcm_spec);
|
|
+ encryptCipher.updateAAD(aad);
|
|
+ decryptCipher = makeCipher(prov, algorithm);
|
|
+ decryptCipher.init(Cipher.DECRYPT_MODE, ks, encryptCipher.getParameters().getParameterSpec(GCMParameterSpec.class));
|
|
+ decryptCipher.updateAAD(aad);
|
|
+ data = fillRandom(new byte[dataSize]);
|
|
+ encryptedData = encryptCipher.doFinal(data);
|
|
+ }
|
|
+
|
|
+ @Benchmark
|
|
+ public byte[] encrypt() throws BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException, InvalidKeyException {
|
|
+ gcm_spec = new GCMParameterSpec(96, iv, next_iv_index(), 16);
|
|
+ encryptCipher.init(Cipher.ENCRYPT_MODE, ks, gcm_spec);
|
|
+ encryptCipher.updateAAD(aad);
|
|
+ return encryptCipher.doFinal(data);
|
|
+ }
|
|
+
|
|
+ @Benchmark
|
|
+ @Fork(jvmArgsPrepend = {"-Xms100G", "-Xmx100G", "-XX:+AlwaysPreTouch", "-Dkae.disableKaeDispose=true"}, value = 5)
|
|
+ public byte[] encrypt_arg() throws BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException, InvalidKeyException {
|
|
+ gcm_spec = new GCMParameterSpec(96, iv, next_iv_index(), 16);
|
|
+ encryptCipher.init(Cipher.ENCRYPT_MODE, ks, gcm_spec);
|
|
+ encryptCipher.updateAAD(aad);
|
|
+ return encryptCipher.doFinal(data);
|
|
+ }
|
|
+
|
|
+ @Benchmark
|
|
+ public byte[] decrypt() throws BadPaddingException, IllegalBlockSizeException, InvalidParameterSpecException, InvalidAlgorithmParameterException, InvalidKeyException {
|
|
+ decryptCipher.init(Cipher.DECRYPT_MODE, ks, gcm_spec);
|
|
+ decryptCipher.updateAAD(aad);
|
|
+ return decryptCipher.doFinal(encryptedData);
|
|
+ }
|
|
+
|
|
+ @Benchmark
|
|
+ @Fork(jvmArgsPrepend = {"-Xms100G", "-Xmx100G", "-XX:+AlwaysPreTouch", "-Dkae.disableKaeDispose=true"}, value = 5)
|
|
+ public byte[] decrypt_arg() throws BadPaddingException, IllegalBlockSizeException, InvalidParameterSpecException, InvalidAlgorithmParameterException, InvalidKeyException {
|
|
+ decryptCipher.init(Cipher.DECRYPT_MODE, ks, gcm_spec);
|
|
+ decryptCipher.updateAAD(aad);
|
|
+ return decryptCipher.doFinal(encryptedData);
|
|
+ }
|
|
+
|
|
+ public static Cipher makeCipher(Provider prov, String algorithm) throws NoSuchPaddingException, NoSuchAlgorithmException {
|
|
+ return (prov == null) ? Cipher.getInstance(algorithm) : Cipher.getInstance(algorithm, prov);
|
|
+ }
|
|
+}
|
|
+
|
|
diff --git a/test/micro/org/openeuler/bench/security/openssl/BenchmarkBase.java b/test/micro/org/openeuler/bench/security/openssl/BenchmarkBase.java
|
|
new file mode 100644
|
|
index 000000000..9aef6dc62
|
|
--- /dev/null
|
|
+++ b/test/micro/org/openeuler/bench/security/openssl/BenchmarkBase.java
|
|
@@ -0,0 +1,106 @@
|
|
+/*
|
|
+ * 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.Throughput)
|
|
+@OutputTimeUnit(TimeUnit.SECONDS)
|
|
+@Warmup(iterations = 3, time = 3, timeUnit = TimeUnit.SECONDS)
|
|
+@Measurement(iterations = 8, time = 2, timeUnit = TimeUnit.SECONDS)
|
|
+@Fork(jvmArgsPrepend = {"-Xms100G", "-Xmx100G", "-XX:+AlwaysPreTouch"}, value = 5)
|
|
+@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[] fillRandom(byte[] data) {
|
|
+ Random rnd = new Random();
|
|
+ rnd.nextBytes(data);
|
|
+ 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/test/micro/org/openeuler/bench/security/openssl/DHKeyAgreementBenchMark.java b/test/micro/org/openeuler/bench/security/openssl/DHKeyAgreementBenchMark.java
|
|
new file mode 100644
|
|
index 000000000..c204f4ceb
|
|
--- /dev/null
|
|
+++ b/test/micro/org/openeuler/bench/security/openssl/DHKeyAgreementBenchMark.java
|
|
@@ -0,0 +1,139 @@
|
|
+/*
|
|
+ * 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 java.math.BigInteger;
|
|
+import java.security.*;
|
|
+import javax.crypto.*;
|
|
+import javax.crypto.spec.*;
|
|
+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;
|
|
+
|
|
+public class DHKeyAgreementBenchMark extends BenchmarkBase {
|
|
+ @Param({"DH"})
|
|
+ private String algorithm;
|
|
+
|
|
+ @Param({"512", "1024", "2048", "3072", "4096"})
|
|
+ private int keySize;
|
|
+
|
|
+ private KeyPairGenerator aliceKpairGen;
|
|
+ private KeyPairGenerator bobKpairGen;
|
|
+ private KeyPairGenerator carolKpairGen;
|
|
+
|
|
+ private KeyPair aliceKpair;
|
|
+ private KeyPair bobKpair;
|
|
+ private KeyPair carolKpair;
|
|
+
|
|
+ private DHParameterSpec dhSkipParamSpec;
|
|
+
|
|
+ @Setup
|
|
+ public void setUp() throws Exception {
|
|
+ setupProvider();
|
|
+ aliceKpairGen = createKeyPairGenerator();
|
|
+ bobKpairGen = createKeyPairGenerator();
|
|
+ carolKpairGen = createKeyPairGenerator();
|
|
+
|
|
+ // Alice creates her own DH key pair
|
|
+ aliceKpairGen.initialize(keySize);
|
|
+ aliceKpair = aliceKpairGen.generateKeyPair();
|
|
+ // Bob creates his own DH key pair
|
|
+ bobKpairGen.initialize(keySize);
|
|
+ bobKpair = bobKpairGen.generateKeyPair();
|
|
+ // Carol creates her own DH key pair
|
|
+ carolKpairGen.initialize(keySize);
|
|
+ carolKpair = carolKpairGen.generateKeyPair();
|
|
+ }
|
|
+
|
|
+ @Benchmark
|
|
+ public void KeyAgreement() throws Exception {
|
|
+
|
|
+ // Alice initialize
|
|
+ KeyAgreement aliceKeyAgree = (prov == null ? KeyAgreement.getInstance("DH") : KeyAgreement.getInstance("DH", prov));
|
|
+ aliceKeyAgree.init(aliceKpair.getPrivate());
|
|
+ // Bob initialize
|
|
+ KeyAgreement bobKeyAgree = (prov == null ? KeyAgreement.getInstance("DH") : KeyAgreement.getInstance("DH", prov));
|
|
+ bobKeyAgree.init(bobKpair.getPrivate());
|
|
+ // Carol initialize
|
|
+ KeyAgreement carolKeyAgree = (prov == null ? KeyAgreement.getInstance("DH") : KeyAgreement.getInstance("DH", prov));
|
|
+ carolKeyAgree.init(carolKpair.getPrivate());
|
|
+ // Alice uses Carol's public key
|
|
+ Key ac = aliceKeyAgree.doPhase(carolKpair.getPublic(), false);
|
|
+ // Bob uses Alice's public key
|
|
+ Key ba = bobKeyAgree.doPhase(aliceKpair.getPublic(), false);
|
|
+ // Carol uses Bob's public key
|
|
+ Key cb = carolKeyAgree.doPhase(bobKpair.getPublic(), false);
|
|
+ // Alice uses Carol's result from above
|
|
+ aliceKeyAgree.doPhase(cb, true);
|
|
+ // Bob uses Alice's result from above
|
|
+ bobKeyAgree.doPhase(ac, true);
|
|
+ // Carol uses Bob's result from above
|
|
+ carolKeyAgree.doPhase(ba, true);
|
|
+
|
|
+ // Alice, Bob and Carol compute their secrets
|
|
+ byte[] aliceSharedSecret = aliceKeyAgree.generateSecret();
|
|
+ int aliceLen = aliceSharedSecret.length;
|
|
+
|
|
+ byte[] bobSharedSecret = bobKeyAgree.generateSecret();
|
|
+ int bobLen = bobSharedSecret.length;
|
|
+
|
|
+ byte[] carolSharedSecret = carolKeyAgree.generateSecret();
|
|
+ int carolLen = carolSharedSecret.length;
|
|
+
|
|
+ // Compare Alice and Bob
|
|
+ if (aliceLen != bobLen) {
|
|
+ throw new Exception("Alice and Bob have different lengths");
|
|
+ }
|
|
+ for (int i=0; i<aliceLen; i++) {
|
|
+ if (aliceSharedSecret[i] != bobSharedSecret[i]) {
|
|
+ throw new Exception("Alice and Bob differ");
|
|
+ }
|
|
+ }
|
|
+
|
|
+ // Compare Bob and Carol
|
|
+ if (bobLen != carolLen) {
|
|
+ throw new Exception("Bob and Carol have different lengths");
|
|
+ }
|
|
+ for (int i=0; i<bobLen; i++) {
|
|
+ if (bobSharedSecret[i] != carolSharedSecret[i]) {
|
|
+ throw new Exception("Bob and Carol differ");
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+
|
|
+ private KeyPairGenerator createKeyPairGenerator() throws Exception {
|
|
+ if (prov != null) {
|
|
+ return KeyPairGenerator.getInstance(algorithm, prov);
|
|
+ }
|
|
+ return KeyPairGenerator.getInstance(algorithm);
|
|
+ }
|
|
+
|
|
+}
|
|
+
|
|
diff --git a/test/micro/org/openeuler/bench/security/openssl/DHKeyPairGeneratorBenchmark.java b/test/micro/org/openeuler/bench/security/openssl/DHKeyPairGeneratorBenchmark.java
|
|
new file mode 100644
|
|
index 000000000..b3f65b283
|
|
--- /dev/null
|
|
+++ b/test/micro/org/openeuler/bench/security/openssl/DHKeyPairGeneratorBenchmark.java
|
|
@@ -0,0 +1,64 @@
|
|
+/*
|
|
+ * 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;
|
|
+import java.security.KeyPair;
|
|
+
|
|
+public class DHKeyPairGeneratorBenchmark extends BenchmarkBase {
|
|
+ @Param({"DH"})
|
|
+ private String algorithm;
|
|
+
|
|
+ @Param({"512", "1024", "2048", "3072", "4096"})
|
|
+ private int keyLength;
|
|
+
|
|
+ private KeyPairGenerator keyPairGenerator;
|
|
+
|
|
+ @Setup
|
|
+ public void setUp() throws Exception {
|
|
+ setupProvider();
|
|
+ keyPairGenerator = createKeyPairGenerator();
|
|
+ }
|
|
+
|
|
+ @Benchmark
|
|
+ public KeyPair generateKeyPair() throws Exception {
|
|
+ keyPairGenerator.initialize(keyLength);
|
|
+ return keyPairGenerator.generateKeyPair();
|
|
+ }
|
|
+
|
|
+ private KeyPairGenerator createKeyPairGenerator() throws Exception {
|
|
+ if (prov != null) {
|
|
+ return KeyPairGenerator.getInstance(algorithm, prov);
|
|
+ }
|
|
+ return KeyPairGenerator.getInstance(algorithm);
|
|
+ }
|
|
+}
|
|
+
|
|
diff --git a/test/micro/org/openeuler/bench/security/openssl/DigestBenchmark.java b/test/micro/org/openeuler/bench/security/openssl/DigestBenchmark.java
|
|
new file mode 100644
|
|
index 000000000..161841951
|
|
--- /dev/null
|
|
+++ b/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(jvmArgsPrepend = {"-Xms100G", "-Xmx100G", "-XX:+AlwaysPreTouch", "-Dkae.disableKaeDispose=true"}, value = 5)
|
|
+ public byte[] digestDispose() {
|
|
+ byte[] d = data[index];
|
|
+ index = (index + 1) % SET_SIZE;
|
|
+ return md.digest(d);
|
|
+ }
|
|
+}
|
|
+
|
|
diff --git a/test/micro/org/openeuler/bench/security/openssl/ECKeyAgreementBenchmark.java b/test/micro/org/openeuler/bench/security/openssl/ECKeyAgreementBenchmark.java
|
|
new file mode 100644
|
|
index 000000000..611998b0d
|
|
--- /dev/null
|
|
+++ b/test/micro/org/openeuler/bench/security/openssl/ECKeyAgreementBenchmark.java
|
|
@@ -0,0 +1,88 @@
|
|
+/*
|
|
+ * 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 javax.crypto.KeyAgreement;
|
|
+import java.security.PublicKey;
|
|
+import java.security.PrivateKey;
|
|
+import java.security.KeyPair;
|
|
+import java.security.KeyPairGenerator;
|
|
+
|
|
+@Warmup(iterations = 10, time = 2, timeUnit = TimeUnit.SECONDS)
|
|
+public class ECKeyAgreementBenchmark extends BenchmarkBase {
|
|
+ @Param({"EC"})
|
|
+ private String kpgAlgorithm;
|
|
+
|
|
+ @Param({"ECDH"})
|
|
+ private String algorithm;
|
|
+
|
|
+ @Param({"224", "256", "384", "521"})
|
|
+ private int keySize;
|
|
+
|
|
+ private KeyPairGenerator keyPairGenerator;
|
|
+ private KeyAgreement keyAgreement;
|
|
+ private PrivateKey privKey;
|
|
+ private PublicKey pubKey;
|
|
+
|
|
+ @Setup
|
|
+ public void setUp() throws Exception {
|
|
+ setupProvider();
|
|
+ keyPairGenerator = createKeyPairGenerator();
|
|
+ keyPairGenerator.initialize(keySize);
|
|
+ KeyPair kpA = keyPairGenerator.generateKeyPair();
|
|
+ privKey = kpA.getPrivate();
|
|
+ KeyPair kpB = keyPairGenerator.generateKeyPair();
|
|
+ pubKey = kpB.getPublic();
|
|
+ keyPairGenerator = createKeyPairGenerator();
|
|
+ keyAgreement = createKeyAgreement();
|
|
+ }
|
|
+
|
|
+ @Benchmark
|
|
+ public void generateKeyAgreement() throws Exception {
|
|
+ keyAgreement.init(privKey);
|
|
+ keyAgreement.doPhase(pubKey, true);
|
|
+ keyAgreement.generateSecret();
|
|
+ }
|
|
+
|
|
+ private KeyPairGenerator createKeyPairGenerator() throws Exception {
|
|
+ if (prov != null) {
|
|
+ return KeyPairGenerator.getInstance(kpgAlgorithm, prov);
|
|
+ }
|
|
+ return KeyPairGenerator.getInstance(kpgAlgorithm);
|
|
+ }
|
|
+
|
|
+ private KeyAgreement createKeyAgreement() throws Exception {
|
|
+ if (prov != null) {
|
|
+ return KeyAgreement.getInstance(algorithm, prov);
|
|
+ }
|
|
+ return KeyAgreement.getInstance(algorithm);
|
|
+ }
|
|
+}
|
|
diff --git a/test/micro/org/openeuler/bench/security/openssl/ECKeyPairGeneratorBenchmark.java b/test/micro/org/openeuler/bench/security/openssl/ECKeyPairGeneratorBenchmark.java
|
|
new file mode 100644
|
|
index 000000000..5c37a4f10
|
|
--- /dev/null
|
|
+++ b/test/micro/org/openeuler/bench/security/openssl/ECKeyPairGeneratorBenchmark.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 ECKeyPairGeneratorBenchmark extends BenchmarkBase {
|
|
+ @Param({"EC"})
|
|
+ private String algorithm;
|
|
+
|
|
+ @Param({"224", "256", "384", "521"})
|
|
+ private int keySize;
|
|
+
|
|
+ private KeyPairGenerator keyPairGenerator;
|
|
+
|
|
+ @Setup
|
|
+ public void setUp() throws Exception {
|
|
+ setupProvider();
|
|
+ keyPairGenerator = createKeyPairGenerator();
|
|
+ keyPairGenerator.initialize(keySize);
|
|
+ }
|
|
+
|
|
+ @Benchmark
|
|
+ public void generateKeyPair() throws Exception {
|
|
+ keyPairGenerator.generateKeyPair();
|
|
+ }
|
|
+
|
|
+ private KeyPairGenerator createKeyPairGenerator() throws Exception {
|
|
+ if (prov != null) {
|
|
+ return KeyPairGenerator.getInstance(algorithm, prov);
|
|
+ }
|
|
+ return KeyPairGenerator.getInstance(algorithm);
|
|
+ }
|
|
+}
|
|
diff --git a/test/micro/org/openeuler/bench/security/openssl/HMacBenchmark.java b/test/micro/org/openeuler/bench/security/openssl/HMacBenchmark.java
|
|
new file mode 100644
|
|
index 000000000..c9678b747
|
|
--- /dev/null
|
|
+++ b/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(jvmArgsPrepend = {"-Xms100G", "-Xmx100G", "-XX:+AlwaysPreTouch", "-Dkae.disableKaeDispose=true"}, value = 5)
|
|
+ public byte[] macDispose() {
|
|
+ byte[] d = data[index];
|
|
+ index = (index + 1) % SET_SIZE;
|
|
+ return mac.doFinal(d);
|
|
+ }
|
|
+}
|
|
+
|
|
diff --git a/test/micro/org/openeuler/bench/security/openssl/RSACipherBenchmark.java b/test/micro/org/openeuler/bench/security/openssl/RSACipherBenchmark.java
|
|
new file mode 100644
|
|
index 000000000..2a5eb9c76
|
|
--- /dev/null
|
|
+++ b/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/test/micro/org/openeuler/bench/security/openssl/RSAKeyPairGeneratorBenchmark.java b/test/micro/org/openeuler/bench/security/openssl/RSAKeyPairGeneratorBenchmark.java
|
|
new file mode 100644
|
|
index 000000000..b17392227
|
|
--- /dev/null
|
|
+++ b/test/micro/org/openeuler/bench/security/openssl/RSAKeyPairGeneratorBenchmark.java
|
|
@@ -0,0 +1,64 @@
|
|
+/*
|
|
+ * 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.KeyPair;
|
|
+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();
|
|
+ keyPairGenerator.initialize(keySize);
|
|
+ }
|
|
+
|
|
+ @Benchmark
|
|
+ public KeyPair generateKeyPair() throws Exception {
|
|
+ return keyPairGenerator.generateKeyPair();
|
|
+ }
|
|
+
|
|
+ private KeyPairGenerator createKeyPairGenerator() throws Exception {
|
|
+ if (prov != null) {
|
|
+ return KeyPairGenerator.getInstance(algorithm, prov);
|
|
+ }
|
|
+ return KeyPairGenerator.getInstance(algorithm);
|
|
+ }
|
|
+}
|
|
diff --git a/test/micro/org/openeuler/bench/security/openssl/RSAPSSSignatureBenchmark.java b/test/micro/org/openeuler/bench/security/openssl/RSAPSSSignatureBenchmark.java
|
|
new file mode 100644
|
|
index 000000000..ade15f46c
|
|
--- /dev/null
|
|
+++ b/test/micro/org/openeuler/bench/security/openssl/RSAPSSSignatureBenchmark.java
|
|
@@ -0,0 +1,118 @@
|
|
+/*
|
|
+ * Copyright (c) 2021, Huawei Technologies Co., Ltd. All rights reserved.
|
|
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. 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.security.*;
|
|
+import java.security.spec.MGF1ParameterSpec;
|
|
+import java.security.spec.PSSParameterSpec;
|
|
+import java.util.HashMap;
|
|
+import java.util.Map;
|
|
+
|
|
+/**
|
|
+ * RSASSA-PSS Signature Benchmark
|
|
+ */
|
|
+public class RSAPSSSignatureBenchmark extends BenchmarkBase {
|
|
+ private static Map<String, PSSParameterSpec> pssParameterSpecMap;
|
|
+
|
|
+ static {
|
|
+ initPSSParameterSpecMap();
|
|
+ }
|
|
+
|
|
+ @Param({"SHA-1", "SHA-224", "SHA-256", "SHA-384", "SHA-512"})
|
|
+ private String algorithm;
|
|
+
|
|
+ @Param({"2048", "3072", "4096"})
|
|
+ private int keySize;
|
|
+
|
|
+ @Param({"" + 1024, "" + 10 * 1024, "" + 100 * 1024, "" + 256 * 1024, "" + 1024 * 1024, "" + 10 * 1024 * 1024})
|
|
+ private int dataSize;
|
|
+
|
|
+ private KeyPair keyPair;
|
|
+
|
|
+ private byte[][] sigData;
|
|
+
|
|
+
|
|
+ private static void initPSSParameterSpecMap() {
|
|
+ pssParameterSpecMap = new HashMap<>();
|
|
+ pssParameterSpecMap.put("SHA-1", new PSSParameterSpec("SHA-1",
|
|
+ "MGF1", MGF1ParameterSpec.SHA1, 20, PSSParameterSpec.TRAILER_FIELD_BC));
|
|
+ pssParameterSpecMap.put("SHA-224", new PSSParameterSpec("SHA-224",
|
|
+ "MGF1", MGF1ParameterSpec.SHA224, 28, PSSParameterSpec.TRAILER_FIELD_BC));
|
|
+ pssParameterSpecMap.put("SHA-256", new PSSParameterSpec("SHA-256",
|
|
+ "MGF1", MGF1ParameterSpec.SHA256, 32, PSSParameterSpec.TRAILER_FIELD_BC));
|
|
+ pssParameterSpecMap.put("SHA-384", new PSSParameterSpec("SHA-384",
|
|
+ "MGF1", MGF1ParameterSpec.SHA384, 48, PSSParameterSpec.TRAILER_FIELD_BC));
|
|
+ pssParameterSpecMap.put("SHA-512", new PSSParameterSpec("SHA-512",
|
|
+ "MGF1", MGF1ParameterSpec.SHA512, 64, PSSParameterSpec.TRAILER_FIELD_BC));
|
|
+ }
|
|
+
|
|
+ @Setup
|
|
+ public void setup() throws Exception {
|
|
+ setupProvider();
|
|
+ KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
|
|
+ keyPairGenerator.initialize(keySize);
|
|
+ keyPair = keyPairGenerator.generateKeyPair();
|
|
+ data = new byte[SET_SIZE][dataSize];
|
|
+ sigData = getSigBytes(data);
|
|
+ }
|
|
+
|
|
+ private byte[][] getSigBytes(byte[][] data) throws Exception {
|
|
+ byte[][] sigBytes = new byte[data.length][];
|
|
+ Signature signature = prov != null ? Signature.getInstance("RSASSA-PSS", prov) :
|
|
+ Signature.getInstance("RSASSA-PSS");
|
|
+ signature.setParameter(pssParameterSpecMap.get(algorithm));
|
|
+ signature.initSign(keyPair.getPrivate());
|
|
+ for (int i = 0; i < sigBytes.length; i++) {
|
|
+ signature.update(data[i]);
|
|
+ sigBytes[i] = signature.sign();
|
|
+ }
|
|
+ return sigBytes;
|
|
+ }
|
|
+
|
|
+ @Benchmark
|
|
+ public void sign() throws Exception {
|
|
+ Signature signature = prov != null ? Signature.getInstance("RSASSA-PSS", prov) :
|
|
+ Signature.getInstance("RSASSA-PSS");
|
|
+ signature.setParameter(pssParameterSpecMap.get(algorithm));
|
|
+ signature.initSign(keyPair.getPrivate());
|
|
+ signature.update(data[index]);
|
|
+ signature.sign();
|
|
+ index = (index + 1) % SET_SIZE;
|
|
+ }
|
|
+
|
|
+ @Benchmark
|
|
+ public void verify() throws Exception {
|
|
+ Signature signature = prov != null ? Signature.getInstance("RSASSA-PSS", prov) :
|
|
+ Signature.getInstance("RSASSA-PSS");
|
|
+ signature.setParameter(pssParameterSpecMap.get(algorithm));
|
|
+ signature.initVerify(keyPair.getPublic());
|
|
+ signature.update(data[index]);
|
|
+ signature.verify(sigData[index]);
|
|
+ index = (index + 1) % SET_SIZE;
|
|
+ }
|
|
+}
|
|
diff --git a/test/micro/org/openeuler/bench/security/openssl/RSASignatureBenchmark.java b/test/micro/org/openeuler/bench/security/openssl/RSASignatureBenchmark.java
|
|
new file mode 100644
|
|
index 000000000..f1cd4b641
|
|
--- /dev/null
|
|
+++ b/test/micro/org/openeuler/bench/security/openssl/RSASignatureBenchmark.java
|
|
@@ -0,0 +1,90 @@
|
|
+/*
|
|
+ * Copyright (c) 2021, Huawei Technologies Co., Ltd. All rights reserved.
|
|
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. 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.security.*;
|
|
+
|
|
+/**
|
|
+ * RSA Signature Benchmark
|
|
+ */
|
|
+public class RSASignatureBenchmark extends BenchmarkBase {
|
|
+ @Param({"MD5withRSA", "SHA1withRSA", "SHA224withRSA", "SHA384withRSA", "SHA256withRSA", "SHA512withRSA"})
|
|
+ private String algorithm;
|
|
+
|
|
+ @Param({"2048", "3072", "4096"})
|
|
+ private int keySize;
|
|
+
|
|
+ @Param({"" + 1024, "" + 10 * 1024, "" + 100 * 1024, "" + 256 * 1024, "" + 1024 * 1024, "" + 10 * 1024 * 1024})
|
|
+ private int dataSize;
|
|
+
|
|
+ private KeyPair keyPair;
|
|
+
|
|
+ private byte[][] sigData;
|
|
+
|
|
+ @Setup
|
|
+ public void setup() throws Exception {
|
|
+ setupProvider();
|
|
+ KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
|
|
+ keyPairGenerator.initialize(keySize);
|
|
+ keyPair = keyPairGenerator.generateKeyPair();
|
|
+ data = new byte[SET_SIZE][dataSize];
|
|
+ sigData = getSigBytes(data);
|
|
+ }
|
|
+
|
|
+ private byte[][] getSigBytes(byte[][] data) throws Exception {
|
|
+ byte[][] sigBytes = new byte[data.length][];
|
|
+ Signature signature = prov != null ? Signature.getInstance(algorithm, prov) :
|
|
+ Signature.getInstance(algorithm);
|
|
+ signature.initSign(keyPair.getPrivate());
|
|
+ for (int i = 0; i < sigBytes.length; i++) {
|
|
+ signature.update(data[i]);
|
|
+ sigBytes[i] = signature.sign();
|
|
+ }
|
|
+ return sigBytes;
|
|
+ }
|
|
+
|
|
+ @Benchmark
|
|
+ public void sign() throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
|
|
+ Signature signature = prov != null ? Signature.getInstance(algorithm, prov) :
|
|
+ Signature.getInstance(algorithm);
|
|
+ signature.initSign(keyPair.getPrivate());
|
|
+ signature.update(data[index]);
|
|
+ signature.sign();
|
|
+ index = (index + 1) % SET_SIZE;
|
|
+ }
|
|
+
|
|
+ @Benchmark
|
|
+ public void verify() throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
|
|
+ Signature signature = prov != null ? Signature.getInstance(algorithm, prov) :
|
|
+ Signature.getInstance(algorithm);
|
|
+ signature.initVerify(keyPair.getPublic());
|
|
+ signature.update(data[index]);
|
|
+ signature.verify(sigData[index]);
|
|
+ index = (index + 1) % SET_SIZE;
|
|
+ }
|
|
+}
|
|
diff --git a/test/micro/org/openeuler/bench/security/openssl/SM3Benchmark.java b/test/micro/org/openeuler/bench/security/openssl/SM3Benchmark.java
|
|
new file mode 100644
|
|
index 000000000..664650374
|
|
--- /dev/null
|
|
+++ b/test/micro/org/openeuler/bench/security/openssl/SM3Benchmark.java
|
|
@@ -0,0 +1,98 @@
|
|
+/*
|
|
+ * 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.Benchmark;
|
|
+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.Scope;
|
|
+import org.openjdk.jmh.annotations.Param;
|
|
+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 java.security.MessageDigest;
|
|
+import java.security.NoSuchAlgorithmException;
|
|
+import java.security.Provider;
|
|
+import java.security.Security;
|
|
+import java.util.Random;
|
|
+import java.util.concurrent.TimeUnit;
|
|
+
|
|
+@BenchmarkMode(Mode.Throughput)
|
|
+@OutputTimeUnit(TimeUnit.SECONDS)
|
|
+@Warmup(iterations = 3, time = 3, timeUnit = TimeUnit.SECONDS)
|
|
+@Measurement(iterations = 8, time = 2, timeUnit = TimeUnit.SECONDS)
|
|
+@Fork(jvmArgsPrepend = {"-Xms100G", "-Xmx100G", "-XX:+AlwaysPreTouch"}, value = 5)
|
|
+@Threads(1)
|
|
+@State(Scope.Thread)
|
|
+public class SM3Benchmark {
|
|
+ public static final int SET_SIZE = 128;
|
|
+ byte[][] data;
|
|
+ int index = 0;
|
|
+
|
|
+ @Param({"SM3"})
|
|
+ private String algorithm;
|
|
+
|
|
+ @Param({"" + 1024, "" + 10 * 1024, "" + 100 * 1024, "" + 1024 * 1024})
|
|
+ int dataSize;
|
|
+
|
|
+ MessageDigest md;
|
|
+
|
|
+ @Setup
|
|
+ public void setup() throws NoSuchAlgorithmException {
|
|
+ Security.addProvider(new KAEProvider());
|
|
+ Provider prov = Security.getProvider("KAEProvider");
|
|
+ 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(jvmArgsPrepend = {"-Xms100G", "-Xmx100G", "-XX:+AlwaysPreTouch", "-Dkae.disableKaeDispose=true"}, value = 5)
|
|
+ public byte[] digestDispose() {
|
|
+ byte[] d = data[index];
|
|
+ index = (index + 1) % SET_SIZE;
|
|
+ return md.digest(d);
|
|
+ }
|
|
+
|
|
+ public static byte[][] fillRandom(byte[][] data) {
|
|
+ Random rnd = new Random();
|
|
+ for (byte[] d : data) {
|
|
+ rnd.nextBytes(d);
|
|
+ }
|
|
+ return data;
|
|
+ }
|
|
+}
|
|
+
|
|
diff --git a/test/micro/org/openeuler/bench/security/openssl/SM4Benchmark.java b/test/micro/org/openeuler/bench/security/openssl/SM4Benchmark.java
|
|
new file mode 100644
|
|
index 000000000..e62e68c4c
|
|
--- /dev/null
|
|
+++ b/test/micro/org/openeuler/bench/security/openssl/SM4Benchmark.java
|
|
@@ -0,0 +1,157 @@
|
|
+/*
|
|
+ * 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.Benchmark;
|
|
+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.Scope;
|
|
+import org.openjdk.jmh.annotations.Param;
|
|
+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 java.security.InvalidKeyException;
|
|
+import java.security.InvalidAlgorithmParameterException;
|
|
+import java.security.NoSuchAlgorithmException;
|
|
+import java.security.Provider;
|
|
+import java.security.SecureRandom;
|
|
+import java.security.Security;
|
|
+import java.util.Random;
|
|
+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;
|
|
+
|
|
+@BenchmarkMode(Mode.Throughput)
|
|
+@OutputTimeUnit(TimeUnit.SECONDS)
|
|
+@Warmup(iterations = 3, time = 3, timeUnit = TimeUnit.SECONDS)
|
|
+@Measurement(iterations = 8, time = 2, timeUnit = TimeUnit.SECONDS)
|
|
+@Fork(jvmArgsPrepend = {"-Xms100G", "-Xmx100G", "-XX:+AlwaysPreTouch"}, value = 5)
|
|
+@Threads(1)
|
|
+@State(Scope.Thread)
|
|
+public class SM4Benchmark {
|
|
+ public static final int SET_SIZE = 128;
|
|
+ byte[][] data;
|
|
+ int index = 0;
|
|
+
|
|
+ @Param({"SM4/ECB/NoPadding", "SM4/ECB/PKCS5Padding", "SM4/CBC/NoPadding", "SM4/CBC/PKCS5Padding", "SM4/CTR/NoPadding", "SM4/OFB/NoPadding", "SM4/OFB/PKCS5Padding"})
|
|
+ private String algorithm;
|
|
+
|
|
+ @Param({"128"})
|
|
+ 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 {
|
|
+ Security.addProvider(new KAEProvider());
|
|
+ Provider prov = Security.getProvider("KAEProvider");
|
|
+
|
|
+ byte[] keystring = fillSecureRandom(new byte[keyLength / 8]);
|
|
+ SecretKeySpec ks = new SecretKeySpec(keystring, "SM4");
|
|
+
|
|
+ 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(jvmArgsPrepend = {"-Xms100G", "-Xmx100G", "-XX:+AlwaysPreTouch", "-Dkae.disableKaeDispose=true"}, value = 5)
|
|
+ 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(jvmArgsPrepend = {"-Xms100G", "-Xmx100G", "-XX:+AlwaysPreTouch", "-Dkae.disableKaeDispose=true"}, value = 5)
|
|
+ public byte[] decryptDispose() throws IllegalBlockSizeException, BadPaddingException {
|
|
+ byte[] e = encryptedData[index];
|
|
+ index = (index + 1) % SET_SIZE;
|
|
+ return decryptCipher.doFinal(e);
|
|
+ }
|
|
+
|
|
+ public static byte[][] fillRandom(byte[][] data) {
|
|
+ Random rnd = new Random();
|
|
+ for (byte[] d : data) {
|
|
+ rnd.nextBytes(d);
|
|
+ }
|
|
+ return data;
|
|
+ }
|
|
+
|
|
+ public static byte[] fillRandom(byte[] data) {
|
|
+ Random rnd = new Random();
|
|
+ rnd.nextBytes(data);
|
|
+ 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;
|
|
+ }
|
|
+}
|
|
+
|
|
--
|
|
2.30.1 (Apple Git-130)
|
|
|