java-17-openjdk/fips-17u-bf363eecce3.patch
Andrew Hughes e0450f0029 Update to jdk-17.0.7.0+7
Update release notes to 17.0.7.0+7
Require tzdata 2023c due to local inclusion of JDK-8274864 & JDK-8305113
Update generate_tarball.sh to add support for passing a boot JDK to the configure run
Add POSIX-friendly error codes to generate_tarball.sh and fix whitespace
Remove .jcheck and GitHub support when generating tarballs, as done in upstream release tarballs
Update FIPS support against 17.0.7+6 and bring in latest changes:
- * RH2134669: Add missing attributes when registering services in FIPS mode.
- * test/jdk/sun/security/pkcs11/fips/VerifyMissingAttributes.java: fixed jtreg main class
- * RH1940064: Enable XML Signature provider in FIPS mode
- * RH2173781: Avoid calling C_GetInfo() too early, before cryptoki is initialized
Fix trailing '.' in tarball name
Use portablerelease in vendor version to avoid inclusion of dist tag
Replace local copies of JDK portable binaries with build dependencies
Include the java-17-openjdk-portable.spec file with instructions on how to rebuild.

** This tarball is embargoed until 2023-04-18 @ 1pm PT. **

- Resolves: RHEL-3489
- Resolves: RHEL-36129
- Resolves: RHEL-36131
- Resolves: RHEL-36133
- Resolves: RHEL-36134
2024-05-11 01:02:17 +01:00

7249 lines
314 KiB
Diff

diff --git a/make/autoconf/build-aux/pkg.m4 b/make/autoconf/build-aux/pkg.m4
index 5f4b22bb27f..1ca9f5b8ffe 100644
--- a/make/autoconf/build-aux/pkg.m4
+++ b/make/autoconf/build-aux/pkg.m4
@@ -179,3 +179,19 @@ else
ifelse([$3], , :, [$3])
fi[]dnl
])# PKG_CHECK_MODULES
+
+dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE,
+dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+dnl -------------------------------------------
+dnl Since: 0.28
+dnl
+dnl Retrieves the value of the pkg-config variable for the given module.
+AC_DEFUN([PKG_CHECK_VAR],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl
+
+_PKG_CONFIG([$1], [variable="][$3]["], [$2])
+AS_VAR_COPY([$1], [pkg_cv_][$1])
+
+AS_VAR_IF([$1], [""], [$5], [$4])dnl
+])dnl PKG_CHECK_VAR
diff --git a/make/autoconf/lib-sysconf.m4 b/make/autoconf/lib-sysconf.m4
new file mode 100644
index 00000000000..f48fc7f7e80
--- /dev/null
+++ b/make/autoconf/lib-sysconf.m4
@@ -0,0 +1,87 @@
+#
+# Copyright (c) 2021, Red Hat, Inc.
+# 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.
+#
+
+################################################################################
+# Setup system configuration libraries
+################################################################################
+AC_DEFUN_ONCE([LIB_SETUP_SYSCONF_LIBS],
+[
+ ###############################################################################
+ #
+ # Check for the NSS library
+ #
+ AC_MSG_CHECKING([for NSS library directory])
+ PKG_CHECK_VAR(NSS_LIBDIR, nss, libdir, [AC_MSG_RESULT([$NSS_LIBDIR])], [AC_MSG_RESULT([not found])])
+
+ AC_MSG_CHECKING([whether to link the system NSS library with the System Configurator (libsysconf)])
+
+ # default is not available
+ DEFAULT_SYSCONF_NSS=no
+
+ AC_ARG_ENABLE([sysconf-nss], [AS_HELP_STRING([--enable-sysconf-nss],
+ [build the System Configurator (libsysconf) using the system NSS library if available @<:@disabled@:>@])],
+ [
+ case "${enableval}" in
+ yes)
+ sysconf_nss=yes
+ ;;
+ *)
+ sysconf_nss=no
+ ;;
+ esac
+ ],
+ [
+ sysconf_nss=${DEFAULT_SYSCONF_NSS}
+ ])
+ AC_MSG_RESULT([$sysconf_nss])
+
+ USE_SYSCONF_NSS=false
+ if test "x${sysconf_nss}" = "xyes"; then
+ PKG_CHECK_MODULES(NSS, nss >= 3.53, [NSS_FOUND=yes], [NSS_FOUND=no])
+ if test "x${NSS_FOUND}" = "xyes"; then
+ AC_MSG_CHECKING([for system FIPS support in NSS])
+ saved_libs="${LIBS}"
+ saved_cflags="${CFLAGS}"
+ CFLAGS="${CFLAGS} ${NSS_CFLAGS}"
+ LIBS="${LIBS} ${NSS_LIBS}"
+ AC_LANG_PUSH([C])
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <nss3/pk11pub.h>]],
+ [[SECMOD_GetSystemFIPSEnabled()]])],
+ [AC_MSG_RESULT([yes])],
+ [AC_MSG_RESULT([no])
+ AC_MSG_ERROR([System NSS FIPS detection unavailable])])
+ AC_LANG_POP([C])
+ CFLAGS="${saved_cflags}"
+ LIBS="${saved_libs}"
+ USE_SYSCONF_NSS=true
+ else
+ dnl NSS 3.53 is the one that introduces the SECMOD_GetSystemFIPSEnabled API
+ dnl in nss3/pk11pub.h.
+ AC_MSG_ERROR([--enable-sysconf-nss specified, but NSS 3.53 or above not found.])
+ fi
+ fi
+ AC_SUBST(USE_SYSCONF_NSS)
+ AC_SUBST(NSS_LIBDIR)
+])
diff --git a/make/autoconf/libraries.m4 b/make/autoconf/libraries.m4
index a65d91ee974..a8f054c1397 100644
--- a/make/autoconf/libraries.m4
+++ b/make/autoconf/libraries.m4
@@ -33,6 +33,7 @@ m4_include([lib-std.m4])
m4_include([lib-x11.m4])
m4_include([lib-fontconfig.m4])
m4_include([lib-tests.m4])
+m4_include([lib-sysconf.m4])
################################################################################
# Determine which libraries are needed for this configuration
@@ -104,6 +105,7 @@ AC_DEFUN_ONCE([LIB_SETUP_LIBRARIES],
LIB_SETUP_BUNDLED_LIBS
LIB_SETUP_MISC_LIBS
LIB_TESTS_SETUP_GTEST
+ LIB_SETUP_SYSCONF_LIBS
BASIC_JDKLIB_LIBS=""
if test "x$TOOLCHAIN_TYPE" != xmicrosoft; then
diff --git a/make/autoconf/spec.gmk.in b/make/autoconf/spec.gmk.in
index 537c3e3043c..16ad3df6f09 100644
--- a/make/autoconf/spec.gmk.in
+++ b/make/autoconf/spec.gmk.in
@@ -841,6 +841,11 @@ INSTALL_SYSCONFDIR=@sysconfdir@
# Libraries
#
+USE_SYSCONF_NSS:=@USE_SYSCONF_NSS@
+NSS_LIBS:=@NSS_LIBS@
+NSS_CFLAGS:=@NSS_CFLAGS@
+NSS_LIBDIR:=@NSS_LIBDIR@
+
USE_EXTERNAL_LCMS:=@USE_EXTERNAL_LCMS@
LCMS_CFLAGS:=@LCMS_CFLAGS@
LCMS_LIBS:=@LCMS_LIBS@
diff --git a/make/modules/java.base/Gendata.gmk b/make/modules/java.base/Gendata.gmk
index 4b894eeae4a..51567071aa8 100644
--- a/make/modules/java.base/Gendata.gmk
+++ b/make/modules/java.base/Gendata.gmk
@@ -98,3 +98,17 @@ $(GENDATA_JAVA_SECURITY): $(BUILD_TOOLS_JDK) $(GENDATA_JAVA_SECURITY_SRC) $(REST
TARGETS += $(GENDATA_JAVA_SECURITY)
################################################################################
+
+GENDATA_NSS_FIPS_CFG_SRC := $(TOPDIR)/src/java.base/share/conf/security/nss.fips.cfg.in
+GENDATA_NSS_FIPS_CFG := $(SUPPORT_OUTPUTDIR)/modules_conf/java.base/security/nss.fips.cfg
+
+$(GENDATA_NSS_FIPS_CFG): $(GENDATA_NSS_FIPS_CFG_SRC)
+ $(call LogInfo, Generating nss.fips.cfg)
+ $(call MakeTargetDir)
+ $(call ExecuteWithLog, $(SUPPORT_OUTPUTDIR)/gensrc/java.base/_$(@F), \
+ ( $(SED) -e 's:@NSS_LIBDIR@:$(NSS_LIBDIR):g' $< ) > $@ \
+ )
+
+TARGETS += $(GENDATA_NSS_FIPS_CFG)
+
+################################################################################
diff --git a/make/modules/java.base/Lib.gmk b/make/modules/java.base/Lib.gmk
index 5658ff342e5..c8bc5bde1e1 100644
--- a/make/modules/java.base/Lib.gmk
+++ b/make/modules/java.base/Lib.gmk
@@ -167,6 +167,29 @@ ifeq ($(call isTargetOsType, unix), true)
endif
endif
+################################################################################
+# Create the systemconf library
+
+LIBSYSTEMCONF_CFLAGS :=
+LIBSYSTEMCONF_CXXFLAGS :=
+
+ifeq ($(USE_SYSCONF_NSS), true)
+ LIBSYSTEMCONF_CFLAGS += $(NSS_CFLAGS) -DSYSCONF_NSS
+ LIBSYSTEMCONF_CXXFLAGS += $(NSS_CFLAGS) -DSYSCONF_NSS
+endif
+
+$(eval $(call SetupJdkLibrary, BUILD_LIBSYSTEMCONF, \
+ NAME := systemconf, \
+ OPTIMIZATION := LOW, \
+ CFLAGS := $(CFLAGS_JDKLIB) $(LIBSYSTEMCONF_CFLAGS), \
+ CXXFLAGS := $(CXXFLAGS_JDKLIB) $(LIBSYSTEMCONF_CXXFLAGS), \
+ LDFLAGS := $(LDFLAGS_JDKLIB) \
+ $(call SET_SHARED_LIBRARY_ORIGIN), \
+ LIBS_unix := $(LIBDL) $(NSS_LIBS), \
+))
+
+TARGETS += $(BUILD_LIBSYSTEMCONF)
+
################################################################################
# Create the symbols file for static builds.
diff --git a/src/java.base/share/classes/com/sun/crypto/provider/HmacPKCS12PBECore.java b/src/java.base/share/classes/com/sun/crypto/provider/HmacPKCS12PBECore.java
index 1fd6230d83b..683e3dd3a8d 100644
--- a/src/java.base/share/classes/com/sun/crypto/provider/HmacPKCS12PBECore.java
+++ b/src/java.base/share/classes/com/sun/crypto/provider/HmacPKCS12PBECore.java
@@ -25,13 +25,12 @@
package com.sun.crypto.provider;
-import java.util.Arrays;
-
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
-import javax.crypto.spec.PBEParameterSpec;
+import javax.crypto.spec.PBEKeySpec;
import java.security.*;
import java.security.spec.*;
+import sun.security.util.PBEUtil;
/**
* This is an implementation of the HMAC algorithms as defined
@@ -108,79 +107,15 @@ abstract class HmacPKCS12PBECore extends HmacCore {
*/
protected void engineInit(Key key, AlgorithmParameterSpec params)
throws InvalidKeyException, InvalidAlgorithmParameterException {
- char[] passwdChars;
- byte[] salt = null;
- int iCount = 0;
- if (key instanceof javax.crypto.interfaces.PBEKey) {
- javax.crypto.interfaces.PBEKey pbeKey =
- (javax.crypto.interfaces.PBEKey) key;
- passwdChars = pbeKey.getPassword();
- salt = pbeKey.getSalt(); // maybe null if unspecified
- iCount = pbeKey.getIterationCount(); // maybe 0 if unspecified
- } else if (key instanceof SecretKey) {
- byte[] passwdBytes;
- if (!(key.getAlgorithm().regionMatches(true, 0, "PBE", 0, 3)) ||
- (passwdBytes = key.getEncoded()) == null) {
- throw new InvalidKeyException("Missing password");
- }
- passwdChars = new char[passwdBytes.length];
- for (int i=0; i<passwdChars.length; i++) {
- passwdChars[i] = (char) (passwdBytes[i] & 0x7f);
- }
- Arrays.fill(passwdBytes, (byte)0x00);
- } else {
- throw new InvalidKeyException("SecretKey of PBE type required");
- }
-
+ PBEKeySpec keySpec = PBEUtil.getPBAKeySpec(key, params);
byte[] derivedKey;
try {
- if (params == null) {
- // should not auto-generate default values since current
- // javax.crypto.Mac api does not have any method for caller to
- // retrieve the generated defaults.
- if ((salt == null) || (iCount == 0)) {
- throw new InvalidAlgorithmParameterException
- ("PBEParameterSpec required for salt and iteration count");
- }
- } else if (!(params instanceof PBEParameterSpec)) {
- throw new InvalidAlgorithmParameterException
- ("PBEParameterSpec type required");
- } else {
- PBEParameterSpec pbeParams = (PBEParameterSpec) params;
- // make sure the parameter values are consistent
- if (salt != null) {
- if (!Arrays.equals(salt, pbeParams.getSalt())) {
- throw new InvalidAlgorithmParameterException
- ("Inconsistent value of salt between key and params");
- }
- } else {
- salt = pbeParams.getSalt();
- }
- if (iCount != 0) {
- if (iCount != pbeParams.getIterationCount()) {
- throw new InvalidAlgorithmParameterException
- ("Different iteration count between key and params");
- }
- } else {
- iCount = pbeParams.getIterationCount();
- }
- }
- // For security purpose, we need to enforce a minimum length
- // for salt; just require the minimum salt length to be 8-byte
- // which is what PKCS#5 recommends and openssl does.
- if (salt.length < 8) {
- throw new InvalidAlgorithmParameterException
- ("Salt must be at least 8 bytes long");
- }
- if (iCount <= 0) {
- throw new InvalidAlgorithmParameterException
- ("IterationCount must be a positive number");
- }
- derivedKey = PKCS12PBECipherCore.derive(passwdChars, salt,
- iCount, engineGetMacLength(), PKCS12PBECipherCore.MAC_KEY,
- algorithm, bl);
+ derivedKey = PKCS12PBECipherCore.derive(
+ keySpec.getPassword(), keySpec.getSalt(),
+ keySpec.getIterationCount(), engineGetMacLength(),
+ PKCS12PBECipherCore.MAC_KEY, algorithm, bl);
} finally {
- Arrays.fill(passwdChars, '\0');
+ keySpec.clearPassword();
}
SecretKey cipherKey = new SecretKeySpec(derivedKey, "HmacSHA1");
super.engineInit(cipherKey, null);
diff --git a/src/java.base/share/classes/com/sun/crypto/provider/PBES2Core.java b/src/java.base/share/classes/com/sun/crypto/provider/PBES2Core.java
index db56dfcd505..07e34e95c05 100644
--- a/src/java.base/share/classes/com/sun/crypto/provider/PBES2Core.java
+++ b/src/java.base/share/classes/com/sun/crypto/provider/PBES2Core.java
@@ -27,10 +27,11 @@ package com.sun.crypto.provider;
import java.security.*;
import java.security.spec.*;
-import java.util.Arrays;
import javax.crypto.*;
import javax.crypto.spec.*;
+import sun.security.util.PBEUtil;
+
/**
* This class represents password-based encryption as defined by the PKCS #5
* standard.
@@ -54,9 +55,8 @@ abstract class PBES2Core extends CipherSpi {
private final PBKDF2Core kdf;
private final String pbeAlgo;
private final String cipherAlgo;
- private int iCount = DEFAULT_COUNT;
- private byte[] salt = null;
- private IvParameterSpec ivSpec = null;
+ private final PBEUtil.PBES2Helper pbes2Helper = new PBEUtil.PBES2Helper(
+ DEFAULT_SALT_LENGTH, DEFAULT_COUNT);
/**
* Creates an instance of PBE Scheme 2 according to the selected
@@ -129,32 +129,8 @@ abstract class PBES2Core extends CipherSpi {
}
protected AlgorithmParameters engineGetParameters() {
- AlgorithmParameters params = null;
- if (salt == null) {
- // generate random salt and use default iteration count
- salt = new byte[DEFAULT_SALT_LENGTH];
- SunJCE.getRandom().nextBytes(salt);
- iCount = DEFAULT_COUNT;
- }
- if (ivSpec == null) {
- // generate random IV
- byte[] ivBytes = new byte[blkSize];
- SunJCE.getRandom().nextBytes(ivBytes);
- ivSpec = new IvParameterSpec(ivBytes);
- }
- PBEParameterSpec pbeSpec = new PBEParameterSpec(salt, iCount, ivSpec);
- try {
- params = AlgorithmParameters.getInstance(pbeAlgo,
- SunJCE.getInstance());
- params.init(pbeSpec);
- } catch (NoSuchAlgorithmException nsae) {
- // should never happen
- throw new RuntimeException("SunJCE called, but not configured");
- } catch (InvalidParameterSpecException ipse) {
- // should never happen
- throw new RuntimeException("PBEParameterSpec not supported");
- }
- return params;
+ return pbes2Helper.getAlgorithmParameters(
+ blkSize, pbeAlgo, SunJCE.getInstance(), SunJCE.getRandom());
}
protected void engineInit(int opmode, Key key, SecureRandom random)
@@ -174,105 +150,8 @@ abstract class PBES2Core extends CipherSpi {
SecureRandom random)
throws InvalidKeyException, InvalidAlgorithmParameterException {
- if (key == null) {
- throw new InvalidKeyException("Null key");
- }
-
- byte[] passwdBytes = key.getEncoded();
- char[] passwdChars = null;
- PBEKeySpec pbeSpec;
- try {
- if ((passwdBytes == null) ||
- !(key.getAlgorithm().regionMatches(true, 0, "PBE", 0, 3))) {
- throw new InvalidKeyException("Missing password");
- }
-
- // TBD: consolidate the salt, ic and IV parameter checks below
-
- // Extract salt and iteration count from the key, if present
- if (key instanceof javax.crypto.interfaces.PBEKey) {
- salt = ((javax.crypto.interfaces.PBEKey)key).getSalt();
- if (salt != null && salt.length < 8) {
- throw new InvalidAlgorithmParameterException(
- "Salt must be at least 8 bytes long");
- }
- iCount = ((javax.crypto.interfaces.PBEKey)key).getIterationCount();
- if (iCount == 0) {
- iCount = DEFAULT_COUNT;
- } else if (iCount < 0) {
- throw new InvalidAlgorithmParameterException(
- "Iteration count must be a positive number");
- }
- }
-
- // Extract salt, iteration count and IV from the params, if present
- if (params == null) {
- if (salt == null) {
- // generate random salt and use default iteration count
- salt = new byte[DEFAULT_SALT_LENGTH];
- random.nextBytes(salt);
- iCount = DEFAULT_COUNT;
- }
- if ((opmode == Cipher.ENCRYPT_MODE) ||
- (opmode == Cipher.WRAP_MODE)) {
- // generate random IV
- byte[] ivBytes = new byte[blkSize];
- random.nextBytes(ivBytes);
- ivSpec = new IvParameterSpec(ivBytes);
- }
- } else {
- if (!(params instanceof PBEParameterSpec)) {
- throw new InvalidAlgorithmParameterException
- ("Wrong parameter type: PBE expected");
- }
- // salt and iteration count from the params take precedence
- byte[] specSalt = ((PBEParameterSpec) params).getSalt();
- if (specSalt != null && specSalt.length < 8) {
- throw new InvalidAlgorithmParameterException(
- "Salt must be at least 8 bytes long");
- }
- salt = specSalt;
- int specICount = ((PBEParameterSpec) params).getIterationCount();
- if (specICount == 0) {
- specICount = DEFAULT_COUNT;
- } else if (specICount < 0) {
- throw new InvalidAlgorithmParameterException(
- "Iteration count must be a positive number");
- }
- iCount = specICount;
-
- AlgorithmParameterSpec specParams =
- ((PBEParameterSpec) params).getParameterSpec();
- if (specParams != null) {
- if (specParams instanceof IvParameterSpec) {
- ivSpec = (IvParameterSpec)specParams;
- } else {
- throw new InvalidAlgorithmParameterException(
- "Wrong parameter type: IV expected");
- }
- } else if ((opmode == Cipher.ENCRYPT_MODE) ||
- (opmode == Cipher.WRAP_MODE)) {
- // generate random IV
- byte[] ivBytes = new byte[blkSize];
- random.nextBytes(ivBytes);
- ivSpec = new IvParameterSpec(ivBytes);
- } else {
- throw new InvalidAlgorithmParameterException(
- "Missing parameter type: IV expected");
- }
- }
-
- passwdChars = new char[passwdBytes.length];
- for (int i = 0; i < passwdChars.length; i++)
- passwdChars[i] = (char) (passwdBytes[i] & 0x7f);
-
- pbeSpec = new PBEKeySpec(passwdChars, salt, iCount, keyLength);
- // password char[] was cloned in PBEKeySpec constructor,
- // so we can zero it out here
- } finally {
- if (passwdChars != null) Arrays.fill(passwdChars, '\0');
- if (passwdBytes != null) Arrays.fill(passwdBytes, (byte)0x00);
- }
+ PBEKeySpec pbeSpec = pbes2Helper.getPBEKeySpec(blkSize, keyLength,
+ opmode, key, params, random);
PBKDF2KeyImpl s;
@@ -291,22 +170,14 @@ abstract class PBES2Core extends CipherSpi {
SecretKeySpec cipherKey = new SecretKeySpec(derivedKey, cipherAlgo);
// initialize the underlying cipher
- cipher.init(opmode, cipherKey, ivSpec, random);
+ cipher.init(opmode, cipherKey, pbes2Helper.getIvSpec(), random);
}
protected void engineInit(int opmode, Key key, AlgorithmParameters params,
SecureRandom random)
throws InvalidKeyException, InvalidAlgorithmParameterException {
- AlgorithmParameterSpec pbeSpec = null;
- if (params != null) {
- try {
- pbeSpec = params.getParameterSpec(PBEParameterSpec.class);
- } catch (InvalidParameterSpecException ipse) {
- throw new InvalidAlgorithmParameterException(
- "Wrong parameter type: PBE expected");
- }
- }
- engineInit(opmode, key, pbeSpec, random);
+ engineInit(opmode, key, PBEUtil.PBES2Helper.getParameterSpec(params),
+ random);
}
protected byte[] engineUpdate(byte[] input, int inputOffset, int inputLen) {
diff --git a/src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java b/src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java
index a020e1c15d8..3c064965e82 100644
--- a/src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java
+++ b/src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java
@@ -31,6 +31,7 @@ import java.security.SecureRandom;
import java.security.PrivilegedAction;
import java.util.HashMap;
import java.util.List;
+import jdk.internal.access.SharedSecrets;
import static sun.security.util.SecurityConstants.PROVIDER_VER;
import static sun.security.util.SecurityProviderConstants.*;
@@ -78,6 +79,10 @@ import static sun.security.util.SecurityProviderConstants.*;
public final class SunJCE extends Provider {
+ private static final boolean systemFipsEnabled =
+ SharedSecrets.getJavaSecuritySystemConfiguratorAccess()
+ .isSystemFipsEnabled();
+
@java.io.Serial
private static final long serialVersionUID = 6812507587804302833L;
@@ -143,285 +148,287 @@ public final class SunJCE extends Provider {
void putEntries() {
// reuse attribute map and reset before each reuse
HashMap<String, String> attrs = new HashMap<>(3);
- attrs.put("SupportedModes", "ECB");
- attrs.put("SupportedPaddings", "NOPADDING|PKCS1PADDING|OAEPPADDING"
- + "|OAEPWITHMD5ANDMGF1PADDING"
- + "|OAEPWITHSHA1ANDMGF1PADDING"
- + "|OAEPWITHSHA-1ANDMGF1PADDING"
- + "|OAEPWITHSHA-224ANDMGF1PADDING"
- + "|OAEPWITHSHA-256ANDMGF1PADDING"
- + "|OAEPWITHSHA-384ANDMGF1PADDING"
- + "|OAEPWITHSHA-512ANDMGF1PADDING"
- + "|OAEPWITHSHA-512/224ANDMGF1PADDING"
- + "|OAEPWITHSHA-512/256ANDMGF1PADDING");
- attrs.put("SupportedKeyClasses",
- "java.security.interfaces.RSAPublicKey" +
- "|java.security.interfaces.RSAPrivateKey");
- ps("Cipher", "RSA",
- "com.sun.crypto.provider.RSACipher", null, attrs);
-
- // common block cipher modes, pads
- final String BLOCK_MODES = "ECB|CBC|PCBC|CTR|CTS|CFB|OFB" +
- "|CFB8|CFB16|CFB24|CFB32|CFB40|CFB48|CFB56|CFB64" +
- "|OFB8|OFB16|OFB24|OFB32|OFB40|OFB48|OFB56|OFB64";
- final String BLOCK_MODES128 = BLOCK_MODES +
- "|CFB72|CFB80|CFB88|CFB96|CFB104|CFB112|CFB120|CFB128" +
- "|OFB72|OFB80|OFB88|OFB96|OFB104|OFB112|OFB120|OFB128";
- final String BLOCK_PADS = "NOPADDING|PKCS5PADDING|ISO10126PADDING";
-
- attrs.clear();
- attrs.put("SupportedModes", BLOCK_MODES);
- attrs.put("SupportedPaddings", BLOCK_PADS);
- attrs.put("SupportedKeyFormats", "RAW");
- ps("Cipher", "DES",
- "com.sun.crypto.provider.DESCipher", null, attrs);
- psA("Cipher", "DESede", "com.sun.crypto.provider.DESedeCipher",
- attrs);
- ps("Cipher", "Blowfish",
- "com.sun.crypto.provider.BlowfishCipher", null, attrs);
-
- ps("Cipher", "RC2",
- "com.sun.crypto.provider.RC2Cipher", null, attrs);
-
- attrs.clear();
- attrs.put("SupportedModes", BLOCK_MODES128);
- attrs.put("SupportedPaddings", BLOCK_PADS);
- attrs.put("SupportedKeyFormats", "RAW");
- psA("Cipher", "AES",
- "com.sun.crypto.provider.AESCipher$General", attrs);
-
- attrs.clear();
- attrs.put("SupportedKeyFormats", "RAW");
- psA("Cipher", "AES/KW/NoPadding",
- "com.sun.crypto.provider.KeyWrapCipher$AES_KW_NoPadding",
- attrs);
- ps("Cipher", "AES/KW/PKCS5Padding",
- "com.sun.crypto.provider.KeyWrapCipher$AES_KW_PKCS5Padding",
- null, attrs);
- psA("Cipher", "AES/KWP/NoPadding",
- "com.sun.crypto.provider.KeyWrapCipher$AES_KWP_NoPadding",
- attrs);
-
- psA("Cipher", "AES_128/ECB/NoPadding",
- "com.sun.crypto.provider.AESCipher$AES128_ECB_NoPadding",
- attrs);
- psA("Cipher", "AES_128/CBC/NoPadding",
- "com.sun.crypto.provider.AESCipher$AES128_CBC_NoPadding",
- attrs);
- psA("Cipher", "AES_128/OFB/NoPadding",
- "com.sun.crypto.provider.AESCipher$AES128_OFB_NoPadding",
- attrs);
- psA("Cipher", "AES_128/CFB/NoPadding",
- "com.sun.crypto.provider.AESCipher$AES128_CFB_NoPadding",
- attrs);
- psA("Cipher", "AES_128/KW/NoPadding",
- "com.sun.crypto.provider.KeyWrapCipher$AES128_KW_NoPadding",
- attrs);
- ps("Cipher", "AES_128/KW/PKCS5Padding",
- "com.sun.crypto.provider.KeyWrapCipher$AES128_KW_PKCS5Padding",
- null, attrs);
- psA("Cipher", "AES_128/KWP/NoPadding",
- "com.sun.crypto.provider.KeyWrapCipher$AES128_KWP_NoPadding",
- attrs);
-
- psA("Cipher", "AES_192/ECB/NoPadding",
- "com.sun.crypto.provider.AESCipher$AES192_ECB_NoPadding",
- attrs);
- psA("Cipher", "AES_192/CBC/NoPadding",
- "com.sun.crypto.provider.AESCipher$AES192_CBC_NoPadding",
- attrs);
- psA("Cipher", "AES_192/OFB/NoPadding",
- "com.sun.crypto.provider.AESCipher$AES192_OFB_NoPadding",
- attrs);
- psA("Cipher", "AES_192/CFB/NoPadding",
- "com.sun.crypto.provider.AESCipher$AES192_CFB_NoPadding",
- attrs);
- psA("Cipher", "AES_192/KW/NoPadding",
- "com.sun.crypto.provider.KeyWrapCipher$AES192_KW_NoPadding",
- attrs);
- ps("Cipher", "AES_192/KW/PKCS5Padding",
- "com.sun.crypto.provider.KeyWrapCipher$AES192_KW_PKCS5Padding",
- null, attrs);
- psA("Cipher", "AES_192/KWP/NoPadding",
- "com.sun.crypto.provider.KeyWrapCipher$AES192_KWP_NoPadding",
- attrs);
-
- psA("Cipher", "AES_256/ECB/NoPadding",
- "com.sun.crypto.provider.AESCipher$AES256_ECB_NoPadding",
- attrs);
- psA("Cipher", "AES_256/CBC/NoPadding",
- "com.sun.crypto.provider.AESCipher$AES256_CBC_NoPadding",
- attrs);
- psA("Cipher", "AES_256/OFB/NoPadding",
- "com.sun.crypto.provider.AESCipher$AES256_OFB_NoPadding",
- attrs);
- psA("Cipher", "AES_256/CFB/NoPadding",
- "com.sun.crypto.provider.AESCipher$AES256_CFB_NoPadding",
- attrs);
- psA("Cipher", "AES_256/KW/NoPadding",
- "com.sun.crypto.provider.KeyWrapCipher$AES256_KW_NoPadding",
- attrs);
- ps("Cipher", "AES_256/KW/PKCS5Padding",
- "com.sun.crypto.provider.KeyWrapCipher$AES256_KW_PKCS5Padding",
- null, attrs);
- psA("Cipher", "AES_256/KWP/NoPadding",
- "com.sun.crypto.provider.KeyWrapCipher$AES256_KWP_NoPadding",
- attrs);
-
- attrs.clear();
- attrs.put("SupportedModes", "GCM");
- attrs.put("SupportedKeyFormats", "RAW");
-
- ps("Cipher", "AES/GCM/NoPadding",
- "com.sun.crypto.provider.GaloisCounterMode$AESGCM", null,
- attrs);
- psA("Cipher", "AES_128/GCM/NoPadding",
- "com.sun.crypto.provider.GaloisCounterMode$AES128",
- attrs);
- psA("Cipher", "AES_192/GCM/NoPadding",
- "com.sun.crypto.provider.GaloisCounterMode$AES192",
- attrs);
- psA("Cipher", "AES_256/GCM/NoPadding",
- "com.sun.crypto.provider.GaloisCounterMode$AES256",
- attrs);
-
- attrs.clear();
- attrs.put("SupportedModes", "CBC");
- attrs.put("SupportedPaddings", "NOPADDING");
- attrs.put("SupportedKeyFormats", "RAW");
- ps("Cipher", "DESedeWrap",
- "com.sun.crypto.provider.DESedeWrapCipher", null, attrs);
-
- attrs.clear();
- attrs.put("SupportedModes", "ECB");
- attrs.put("SupportedPaddings", "NOPADDING");
- attrs.put("SupportedKeyFormats", "RAW");
- psA("Cipher", "ARCFOUR",
- "com.sun.crypto.provider.ARCFOURCipher", attrs);
-
- attrs.clear();
- attrs.put("SupportedKeyFormats", "RAW");
- ps("Cipher", "ChaCha20",
- "com.sun.crypto.provider.ChaCha20Cipher$ChaCha20Only",
- null, attrs);
- psA("Cipher", "ChaCha20-Poly1305",
- "com.sun.crypto.provider.ChaCha20Cipher$ChaCha20Poly1305",
- attrs);
-
- // PBES1
- psA("Cipher", "PBEWithMD5AndDES",
- "com.sun.crypto.provider.PBEWithMD5AndDESCipher",
- null);
- ps("Cipher", "PBEWithMD5AndTripleDES",
- "com.sun.crypto.provider.PBEWithMD5AndTripleDESCipher");
- psA("Cipher", "PBEWithSHA1AndDESede",
- "com.sun.crypto.provider.PKCS12PBECipherCore$PBEWithSHA1AndDESede",
- null);
- psA("Cipher", "PBEWithSHA1AndRC2_40",
- "com.sun.crypto.provider.PKCS12PBECipherCore$PBEWithSHA1AndRC2_40",
- null);
- psA("Cipher", "PBEWithSHA1AndRC2_128",
- "com.sun.crypto.provider.PKCS12PBECipherCore$PBEWithSHA1AndRC2_128",
- null);
- psA("Cipher", "PBEWithSHA1AndRC4_40",
- "com.sun.crypto.provider.PKCS12PBECipherCore$PBEWithSHA1AndRC4_40",
- null);
-
- psA("Cipher", "PBEWithSHA1AndRC4_128",
- "com.sun.crypto.provider.PKCS12PBECipherCore$PBEWithSHA1AndRC4_128",
- null);
-
- // PBES2
- ps("Cipher", "PBEWithHmacSHA1AndAES_128",
- "com.sun.crypto.provider.PBES2Core$HmacSHA1AndAES_128");
-
- ps("Cipher", "PBEWithHmacSHA224AndAES_128",
- "com.sun.crypto.provider.PBES2Core$HmacSHA224AndAES_128");
-
- ps("Cipher", "PBEWithHmacSHA256AndAES_128",
- "com.sun.crypto.provider.PBES2Core$HmacSHA256AndAES_128");
-
- ps("Cipher", "PBEWithHmacSHA384AndAES_128",
- "com.sun.crypto.provider.PBES2Core$HmacSHA384AndAES_128");
-
- ps("Cipher", "PBEWithHmacSHA512AndAES_128",
- "com.sun.crypto.provider.PBES2Core$HmacSHA512AndAES_128");
-
- ps("Cipher", "PBEWithHmacSHA1AndAES_256",
- "com.sun.crypto.provider.PBES2Core$HmacSHA1AndAES_256");
-
- ps("Cipher", "PBEWithHmacSHA224AndAES_256",
- "com.sun.crypto.provider.PBES2Core$HmacSHA224AndAES_256");
-
- ps("Cipher", "PBEWithHmacSHA256AndAES_256",
- "com.sun.crypto.provider.PBES2Core$HmacSHA256AndAES_256");
-
- ps("Cipher", "PBEWithHmacSHA384AndAES_256",
- "com.sun.crypto.provider.PBES2Core$HmacSHA384AndAES_256");
-
- ps("Cipher", "PBEWithHmacSHA512AndAES_256",
- "com.sun.crypto.provider.PBES2Core$HmacSHA512AndAES_256");
-
- /*
- * Key(pair) Generator engines
- */
- ps("KeyGenerator", "DES",
- "com.sun.crypto.provider.DESKeyGenerator");
- psA("KeyGenerator", "DESede",
- "com.sun.crypto.provider.DESedeKeyGenerator",
- null);
- ps("KeyGenerator", "Blowfish",
- "com.sun.crypto.provider.BlowfishKeyGenerator");
- psA("KeyGenerator", "AES",
- "com.sun.crypto.provider.AESKeyGenerator",
- null);
- ps("KeyGenerator", "RC2",
- "com.sun.crypto.provider.KeyGeneratorCore$RC2KeyGenerator");
- psA("KeyGenerator", "ARCFOUR",
- "com.sun.crypto.provider.KeyGeneratorCore$ARCFOURKeyGenerator",
- null);
- ps("KeyGenerator", "ChaCha20",
- "com.sun.crypto.provider.KeyGeneratorCore$ChaCha20KeyGenerator");
- ps("KeyGenerator", "HmacMD5",
- "com.sun.crypto.provider.HmacMD5KeyGenerator");
-
- psA("KeyGenerator", "HmacSHA1",
- "com.sun.crypto.provider.HmacSHA1KeyGenerator", null);
- psA("KeyGenerator", "HmacSHA224",
- "com.sun.crypto.provider.KeyGeneratorCore$HmacKG$SHA224",
- null);
- psA("KeyGenerator", "HmacSHA256",
- "com.sun.crypto.provider.KeyGeneratorCore$HmacKG$SHA256",
- null);
- psA("KeyGenerator", "HmacSHA384",
- "com.sun.crypto.provider.KeyGeneratorCore$HmacKG$SHA384",
- null);
- psA("KeyGenerator", "HmacSHA512",
- "com.sun.crypto.provider.KeyGeneratorCore$HmacKG$SHA512",
- null);
- psA("KeyGenerator", "HmacSHA512/224",
- "com.sun.crypto.provider.KeyGeneratorCore$HmacKG$SHA512_224",
- null);
- psA("KeyGenerator", "HmacSHA512/256",
- "com.sun.crypto.provider.KeyGeneratorCore$HmacKG$SHA512_256",
- null);
-
- psA("KeyGenerator", "HmacSHA3-224",
- "com.sun.crypto.provider.KeyGeneratorCore$HmacKG$SHA3_224",
- null);
- psA("KeyGenerator", "HmacSHA3-256",
- "com.sun.crypto.provider.KeyGeneratorCore$HmacKG$SHA3_256",
- null);
- psA("KeyGenerator", "HmacSHA3-384",
- "com.sun.crypto.provider.KeyGeneratorCore$HmacKG$SHA3_384",
- null);
- psA("KeyGenerator", "HmacSHA3-512",
- "com.sun.crypto.provider.KeyGeneratorCore$HmacKG$SHA3_512",
- null);
-
- psA("KeyPairGenerator", "DiffieHellman",
- "com.sun.crypto.provider.DHKeyPairGenerator",
- null);
+ if (!systemFipsEnabled) {
+ attrs.put("SupportedModes", "ECB");
+ attrs.put("SupportedPaddings", "NOPADDING|PKCS1PADDING|OAEPPADDING"
+ + "|OAEPWITHMD5ANDMGF1PADDING"
+ + "|OAEPWITHSHA1ANDMGF1PADDING"
+ + "|OAEPWITHSHA-1ANDMGF1PADDING"
+ + "|OAEPWITHSHA-224ANDMGF1PADDING"
+ + "|OAEPWITHSHA-256ANDMGF1PADDING"
+ + "|OAEPWITHSHA-384ANDMGF1PADDING"
+ + "|OAEPWITHSHA-512ANDMGF1PADDING"
+ + "|OAEPWITHSHA-512/224ANDMGF1PADDING"
+ + "|OAEPWITHSHA-512/256ANDMGF1PADDING");
+ attrs.put("SupportedKeyClasses",
+ "java.security.interfaces.RSAPublicKey" +
+ "|java.security.interfaces.RSAPrivateKey");
+ ps("Cipher", "RSA",
+ "com.sun.crypto.provider.RSACipher", null, attrs);
+
+ // common block cipher modes, pads
+ final String BLOCK_MODES = "ECB|CBC|PCBC|CTR|CTS|CFB|OFB" +
+ "|CFB8|CFB16|CFB24|CFB32|CFB40|CFB48|CFB56|CFB64" +
+ "|OFB8|OFB16|OFB24|OFB32|OFB40|OFB48|OFB56|OFB64";
+ final String BLOCK_MODES128 = BLOCK_MODES +
+ "|CFB72|CFB80|CFB88|CFB96|CFB104|CFB112|CFB120|CFB128" +
+ "|OFB72|OFB80|OFB88|OFB96|OFB104|OFB112|OFB120|OFB128";
+ final String BLOCK_PADS = "NOPADDING|PKCS5PADDING|ISO10126PADDING";
+
+ attrs.clear();
+ attrs.put("SupportedModes", BLOCK_MODES);
+ attrs.put("SupportedPaddings", BLOCK_PADS);
+ attrs.put("SupportedKeyFormats", "RAW");
+ ps("Cipher", "DES",
+ "com.sun.crypto.provider.DESCipher", null, attrs);
+ psA("Cipher", "DESede", "com.sun.crypto.provider.DESedeCipher",
+ attrs);
+ ps("Cipher", "Blowfish",
+ "com.sun.crypto.provider.BlowfishCipher", null, attrs);
+
+ ps("Cipher", "RC2",
+ "com.sun.crypto.provider.RC2Cipher", null, attrs);
+
+ attrs.clear();
+ attrs.put("SupportedModes", BLOCK_MODES128);
+ attrs.put("SupportedPaddings", BLOCK_PADS);
+ attrs.put("SupportedKeyFormats", "RAW");
+ psA("Cipher", "AES",
+ "com.sun.crypto.provider.AESCipher$General", attrs);
+
+ attrs.clear();
+ attrs.put("SupportedKeyFormats", "RAW");
+ psA("Cipher", "AES/KW/NoPadding",
+ "com.sun.crypto.provider.KeyWrapCipher$AES_KW_NoPadding",
+ attrs);
+ ps("Cipher", "AES/KW/PKCS5Padding",
+ "com.sun.crypto.provider.KeyWrapCipher$AES_KW_PKCS5Padding",
+ null, attrs);
+ psA("Cipher", "AES/KWP/NoPadding",
+ "com.sun.crypto.provider.KeyWrapCipher$AES_KWP_NoPadding",
+ attrs);
+
+ psA("Cipher", "AES_128/ECB/NoPadding",
+ "com.sun.crypto.provider.AESCipher$AES128_ECB_NoPadding",
+ attrs);
+ psA("Cipher", "AES_128/CBC/NoPadding",
+ "com.sun.crypto.provider.AESCipher$AES128_CBC_NoPadding",
+ attrs);
+ psA("Cipher", "AES_128/OFB/NoPadding",
+ "com.sun.crypto.provider.AESCipher$AES128_OFB_NoPadding",
+ attrs);
+ psA("Cipher", "AES_128/CFB/NoPadding",
+ "com.sun.crypto.provider.AESCipher$AES128_CFB_NoPadding",
+ attrs);
+ psA("Cipher", "AES_128/KW/NoPadding",
+ "com.sun.crypto.provider.KeyWrapCipher$AES128_KW_NoPadding",
+ attrs);
+ ps("Cipher", "AES_128/KW/PKCS5Padding",
+ "com.sun.crypto.provider.KeyWrapCipher$AES128_KW_PKCS5Padding",
+ null, attrs);
+ psA("Cipher", "AES_128/KWP/NoPadding",
+ "com.sun.crypto.provider.KeyWrapCipher$AES128_KWP_NoPadding",
+ attrs);
+
+ psA("Cipher", "AES_192/ECB/NoPadding",
+ "com.sun.crypto.provider.AESCipher$AES192_ECB_NoPadding",
+ attrs);
+ psA("Cipher", "AES_192/CBC/NoPadding",
+ "com.sun.crypto.provider.AESCipher$AES192_CBC_NoPadding",
+ attrs);
+ psA("Cipher", "AES_192/OFB/NoPadding",
+ "com.sun.crypto.provider.AESCipher$AES192_OFB_NoPadding",
+ attrs);
+ psA("Cipher", "AES_192/CFB/NoPadding",
+ "com.sun.crypto.provider.AESCipher$AES192_CFB_NoPadding",
+ attrs);
+ psA("Cipher", "AES_192/KW/NoPadding",
+ "com.sun.crypto.provider.KeyWrapCipher$AES192_KW_NoPadding",
+ attrs);
+ ps("Cipher", "AES_192/KW/PKCS5Padding",
+ "com.sun.crypto.provider.KeyWrapCipher$AES192_KW_PKCS5Padding",
+ null, attrs);
+ psA("Cipher", "AES_192/KWP/NoPadding",
+ "com.sun.crypto.provider.KeyWrapCipher$AES192_KWP_NoPadding",
+ attrs);
+
+ psA("Cipher", "AES_256/ECB/NoPadding",
+ "com.sun.crypto.provider.AESCipher$AES256_ECB_NoPadding",
+ attrs);
+ psA("Cipher", "AES_256/CBC/NoPadding",
+ "com.sun.crypto.provider.AESCipher$AES256_CBC_NoPadding",
+ attrs);
+ psA("Cipher", "AES_256/OFB/NoPadding",
+ "com.sun.crypto.provider.AESCipher$AES256_OFB_NoPadding",
+ attrs);
+ psA("Cipher", "AES_256/CFB/NoPadding",
+ "com.sun.crypto.provider.AESCipher$AES256_CFB_NoPadding",
+ attrs);
+ psA("Cipher", "AES_256/KW/NoPadding",
+ "com.sun.crypto.provider.KeyWrapCipher$AES256_KW_NoPadding",
+ attrs);
+ ps("Cipher", "AES_256/KW/PKCS5Padding",
+ "com.sun.crypto.provider.KeyWrapCipher$AES256_KW_PKCS5Padding",
+ null, attrs);
+ psA("Cipher", "AES_256/KWP/NoPadding",
+ "com.sun.crypto.provider.KeyWrapCipher$AES256_KWP_NoPadding",
+ attrs);
+
+ attrs.clear();
+ attrs.put("SupportedModes", "GCM");
+ attrs.put("SupportedKeyFormats", "RAW");
+
+ ps("Cipher", "AES/GCM/NoPadding",
+ "com.sun.crypto.provider.GaloisCounterMode$AESGCM", null,
+ attrs);
+ psA("Cipher", "AES_128/GCM/NoPadding",
+ "com.sun.crypto.provider.GaloisCounterMode$AES128",
+ attrs);
+ psA("Cipher", "AES_192/GCM/NoPadding",
+ "com.sun.crypto.provider.GaloisCounterMode$AES192",
+ attrs);
+ psA("Cipher", "AES_256/GCM/NoPadding",
+ "com.sun.crypto.provider.GaloisCounterMode$AES256",
+ attrs);
+
+ attrs.clear();
+ attrs.put("SupportedModes", "CBC");
+ attrs.put("SupportedPaddings", "NOPADDING");
+ attrs.put("SupportedKeyFormats", "RAW");
+ ps("Cipher", "DESedeWrap",
+ "com.sun.crypto.provider.DESedeWrapCipher", null, attrs);
+
+ attrs.clear();
+ attrs.put("SupportedModes", "ECB");
+ attrs.put("SupportedPaddings", "NOPADDING");
+ attrs.put("SupportedKeyFormats", "RAW");
+ psA("Cipher", "ARCFOUR",
+ "com.sun.crypto.provider.ARCFOURCipher", attrs);
+
+ attrs.clear();
+ attrs.put("SupportedKeyFormats", "RAW");
+ ps("Cipher", "ChaCha20",
+ "com.sun.crypto.provider.ChaCha20Cipher$ChaCha20Only",
+ null, attrs);
+ psA("Cipher", "ChaCha20-Poly1305",
+ "com.sun.crypto.provider.ChaCha20Cipher$ChaCha20Poly1305",
+ attrs);
+
+ // PBES1
+ psA("Cipher", "PBEWithMD5AndDES",
+ "com.sun.crypto.provider.PBEWithMD5AndDESCipher",
+ null);
+ ps("Cipher", "PBEWithMD5AndTripleDES",
+ "com.sun.crypto.provider.PBEWithMD5AndTripleDESCipher");
+ psA("Cipher", "PBEWithSHA1AndDESede",
+ "com.sun.crypto.provider.PKCS12PBECipherCore$PBEWithSHA1AndDESede",
+ null);
+ psA("Cipher", "PBEWithSHA1AndRC2_40",
+ "com.sun.crypto.provider.PKCS12PBECipherCore$PBEWithSHA1AndRC2_40",
+ null);
+ psA("Cipher", "PBEWithSHA1AndRC2_128",
+ "com.sun.crypto.provider.PKCS12PBECipherCore$PBEWithSHA1AndRC2_128",
+ null);
+ psA("Cipher", "PBEWithSHA1AndRC4_40",
+ "com.sun.crypto.provider.PKCS12PBECipherCore$PBEWithSHA1AndRC4_40",
+ null);
+
+ psA("Cipher", "PBEWithSHA1AndRC4_128",
+ "com.sun.crypto.provider.PKCS12PBECipherCore$PBEWithSHA1AndRC4_128",
+ null);
+
+ // PBES2
+ ps("Cipher", "PBEWithHmacSHA1AndAES_128",
+ "com.sun.crypto.provider.PBES2Core$HmacSHA1AndAES_128");
+
+ ps("Cipher", "PBEWithHmacSHA224AndAES_128",
+ "com.sun.crypto.provider.PBES2Core$HmacSHA224AndAES_128");
+
+ ps("Cipher", "PBEWithHmacSHA256AndAES_128",
+ "com.sun.crypto.provider.PBES2Core$HmacSHA256AndAES_128");
+
+ ps("Cipher", "PBEWithHmacSHA384AndAES_128",
+ "com.sun.crypto.provider.PBES2Core$HmacSHA384AndAES_128");
+
+ ps("Cipher", "PBEWithHmacSHA512AndAES_128",
+ "com.sun.crypto.provider.PBES2Core$HmacSHA512AndAES_128");
+
+ ps("Cipher", "PBEWithHmacSHA1AndAES_256",
+ "com.sun.crypto.provider.PBES2Core$HmacSHA1AndAES_256");
+
+ ps("Cipher", "PBEWithHmacSHA224AndAES_256",
+ "com.sun.crypto.provider.PBES2Core$HmacSHA224AndAES_256");
+
+ ps("Cipher", "PBEWithHmacSHA256AndAES_256",
+ "com.sun.crypto.provider.PBES2Core$HmacSHA256AndAES_256");
+
+ ps("Cipher", "PBEWithHmacSHA384AndAES_256",
+ "com.sun.crypto.provider.PBES2Core$HmacSHA384AndAES_256");
+
+ ps("Cipher", "PBEWithHmacSHA512AndAES_256",
+ "com.sun.crypto.provider.PBES2Core$HmacSHA512AndAES_256");
+
+ /*
+ * Key(pair) Generator engines
+ */
+ ps("KeyGenerator", "DES",
+ "com.sun.crypto.provider.DESKeyGenerator");
+ psA("KeyGenerator", "DESede",
+ "com.sun.crypto.provider.DESedeKeyGenerator",
+ null);
+ ps("KeyGenerator", "Blowfish",
+ "com.sun.crypto.provider.BlowfishKeyGenerator");
+ psA("KeyGenerator", "AES",
+ "com.sun.crypto.provider.AESKeyGenerator",
+ null);
+ ps("KeyGenerator", "RC2",
+ "com.sun.crypto.provider.KeyGeneratorCore$RC2KeyGenerator");
+ psA("KeyGenerator", "ARCFOUR",
+ "com.sun.crypto.provider.KeyGeneratorCore$ARCFOURKeyGenerator",
+ null);
+ ps("KeyGenerator", "ChaCha20",
+ "com.sun.crypto.provider.KeyGeneratorCore$ChaCha20KeyGenerator");
+ ps("KeyGenerator", "HmacMD5",
+ "com.sun.crypto.provider.HmacMD5KeyGenerator");
+
+ psA("KeyGenerator", "HmacSHA1",
+ "com.sun.crypto.provider.HmacSHA1KeyGenerator", null);
+ psA("KeyGenerator", "HmacSHA224",
+ "com.sun.crypto.provider.KeyGeneratorCore$HmacKG$SHA224",
+ null);
+ psA("KeyGenerator", "HmacSHA256",
+ "com.sun.crypto.provider.KeyGeneratorCore$HmacKG$SHA256",
+ null);
+ psA("KeyGenerator", "HmacSHA384",
+ "com.sun.crypto.provider.KeyGeneratorCore$HmacKG$SHA384",
+ null);
+ psA("KeyGenerator", "HmacSHA512",
+ "com.sun.crypto.provider.KeyGeneratorCore$HmacKG$SHA512",
+ null);
+ psA("KeyGenerator", "HmacSHA512/224",
+ "com.sun.crypto.provider.KeyGeneratorCore$HmacKG$SHA512_224",
+ null);
+ psA("KeyGenerator", "HmacSHA512/256",
+ "com.sun.crypto.provider.KeyGeneratorCore$HmacKG$SHA512_256",
+ null);
+
+ psA("KeyGenerator", "HmacSHA3-224",
+ "com.sun.crypto.provider.KeyGeneratorCore$HmacKG$SHA3_224",
+ null);
+ psA("KeyGenerator", "HmacSHA3-256",
+ "com.sun.crypto.provider.KeyGeneratorCore$HmacKG$SHA3_256",
+ null);
+ psA("KeyGenerator", "HmacSHA3-384",
+ "com.sun.crypto.provider.KeyGeneratorCore$HmacKG$SHA3_384",
+ null);
+ psA("KeyGenerator", "HmacSHA3-512",
+ "com.sun.crypto.provider.KeyGeneratorCore$HmacKG$SHA3_512",
+ null);
+
+ psA("KeyPairGenerator", "DiffieHellman",
+ "com.sun.crypto.provider.DHKeyPairGenerator",
+ null);
+ }
/*
* Algorithm parameter generation engines
@@ -430,15 +437,17 @@ public final class SunJCE extends Provider {
"DiffieHellman", "com.sun.crypto.provider.DHParameterGenerator",
null);
- /*
- * Key Agreement engines
- */
- attrs.clear();
- attrs.put("SupportedKeyClasses", "javax.crypto.interfaces.DHPublicKey" +
- "|javax.crypto.interfaces.DHPrivateKey");
- psA("KeyAgreement", "DiffieHellman",
- "com.sun.crypto.provider.DHKeyAgreement",
- attrs);
+ if (!systemFipsEnabled) {
+ /*
+ * Key Agreement engines
+ */
+ attrs.clear();
+ attrs.put("SupportedKeyClasses", "javax.crypto.interfaces.DHPublicKey" +
+ "|javax.crypto.interfaces.DHPrivateKey");
+ psA("KeyAgreement", "DiffieHellman",
+ "com.sun.crypto.provider.DHKeyAgreement",
+ attrs);
+ }
/*
* Algorithm Parameter engines
@@ -610,118 +619,120 @@ public final class SunJCE extends Provider {
ps("SecretKeyFactory", "PBEWithHmacSHA512AndAES_256",
"com.sun.crypto.provider.PBEKeyFactory$PBEWithHmacSHA512AndAES_256");
- // PBKDF2
- psA("SecretKeyFactory", "PBKDF2WithHmacSHA1",
- "com.sun.crypto.provider.PBKDF2Core$HmacSHA1",
- null);
- ps("SecretKeyFactory", "PBKDF2WithHmacSHA224",
- "com.sun.crypto.provider.PBKDF2Core$HmacSHA224");
- ps("SecretKeyFactory", "PBKDF2WithHmacSHA256",
- "com.sun.crypto.provider.PBKDF2Core$HmacSHA256");
- ps("SecretKeyFactory", "PBKDF2WithHmacSHA384",
- "com.sun.crypto.provider.PBKDF2Core$HmacSHA384");
- ps("SecretKeyFactory", "PBKDF2WithHmacSHA512",
- "com.sun.crypto.provider.PBKDF2Core$HmacSHA512");
-
- /*
- * MAC
- */
- attrs.clear();
- attrs.put("SupportedKeyFormats", "RAW");
- ps("Mac", "HmacMD5", "com.sun.crypto.provider.HmacMD5", null, attrs);
- psA("Mac", "HmacSHA1", "com.sun.crypto.provider.HmacSHA1",
- attrs);
- psA("Mac", "HmacSHA224",
- "com.sun.crypto.provider.HmacCore$HmacSHA224", attrs);
- psA("Mac", "HmacSHA256",
- "com.sun.crypto.provider.HmacCore$HmacSHA256", attrs);
- psA("Mac", "HmacSHA384",
- "com.sun.crypto.provider.HmacCore$HmacSHA384", attrs);
- psA("Mac", "HmacSHA512",
- "com.sun.crypto.provider.HmacCore$HmacSHA512", attrs);
- psA("Mac", "HmacSHA512/224",
- "com.sun.crypto.provider.HmacCore$HmacSHA512_224", attrs);
- psA("Mac", "HmacSHA512/256",
- "com.sun.crypto.provider.HmacCore$HmacSHA512_256", attrs);
- psA("Mac", "HmacSHA3-224",
- "com.sun.crypto.provider.HmacCore$HmacSHA3_224", attrs);
- psA("Mac", "HmacSHA3-256",
- "com.sun.crypto.provider.HmacCore$HmacSHA3_256", attrs);
- psA("Mac", "HmacSHA3-384",
- "com.sun.crypto.provider.HmacCore$HmacSHA3_384", attrs);
- psA("Mac", "HmacSHA3-512",
- "com.sun.crypto.provider.HmacCore$HmacSHA3_512", attrs);
-
- ps("Mac", "HmacPBESHA1",
- "com.sun.crypto.provider.HmacPKCS12PBECore$HmacPKCS12PBE_SHA1",
- null, attrs);
- ps("Mac", "HmacPBESHA224",
- "com.sun.crypto.provider.HmacPKCS12PBECore$HmacPKCS12PBE_SHA224",
- null, attrs);
- ps("Mac", "HmacPBESHA256",
- "com.sun.crypto.provider.HmacPKCS12PBECore$HmacPKCS12PBE_SHA256",
- null, attrs);
- ps("Mac", "HmacPBESHA384",
- "com.sun.crypto.provider.HmacPKCS12PBECore$HmacPKCS12PBE_SHA384",
- null, attrs);
- ps("Mac", "HmacPBESHA512",
- "com.sun.crypto.provider.HmacPKCS12PBECore$HmacPKCS12PBE_SHA512",
- null, attrs);
- ps("Mac", "HmacPBESHA512/224",
- "com.sun.crypto.provider.HmacPKCS12PBECore$HmacPKCS12PBE_SHA512_224",
- null, attrs);
- ps("Mac", "HmacPBESHA512/256",
- "com.sun.crypto.provider.HmacPKCS12PBECore$HmacPKCS12PBE_SHA512_256",
- null, attrs);
-
-
- // PBMAC1
- ps("Mac", "PBEWithHmacSHA1",
- "com.sun.crypto.provider.PBMAC1Core$HmacSHA1", null, attrs);
- ps("Mac", "PBEWithHmacSHA224",
- "com.sun.crypto.provider.PBMAC1Core$HmacSHA224", null, attrs);
- ps("Mac", "PBEWithHmacSHA256",
- "com.sun.crypto.provider.PBMAC1Core$HmacSHA256", null, attrs);
- ps("Mac", "PBEWithHmacSHA384",
- "com.sun.crypto.provider.PBMAC1Core$HmacSHA384", null, attrs);
- ps("Mac", "PBEWithHmacSHA512",
- "com.sun.crypto.provider.PBMAC1Core$HmacSHA512", null, attrs);
- ps("Mac", "SslMacMD5",
- "com.sun.crypto.provider.SslMacCore$SslMacMD5", null, attrs);
- ps("Mac", "SslMacSHA1",
- "com.sun.crypto.provider.SslMacCore$SslMacSHA1", null, attrs);
-
- /*
- * KeyStore
- */
- ps("KeyStore", "JCEKS",
- "com.sun.crypto.provider.JceKeyStore");
-
- /*
- * SSL/TLS mechanisms
- *
- * These are strictly internal implementations and may
- * be changed at any time. These names were chosen
- * because PKCS11/SunPKCS11 does not yet have TLS1.2
- * mechanisms, and it will cause calls to come here.
- */
- ps("KeyGenerator", "SunTlsPrf",
- "com.sun.crypto.provider.TlsPrfGenerator$V10");
- ps("KeyGenerator", "SunTls12Prf",
- "com.sun.crypto.provider.TlsPrfGenerator$V12");
-
- ps("KeyGenerator", "SunTlsMasterSecret",
- "com.sun.crypto.provider.TlsMasterSecretGenerator",
- List.of("SunTls12MasterSecret", "SunTlsExtendedMasterSecret"),
- null);
-
- ps("KeyGenerator", "SunTlsKeyMaterial",
- "com.sun.crypto.provider.TlsKeyMaterialGenerator",
- List.of("SunTls12KeyMaterial"), null);
-
- ps("KeyGenerator", "SunTlsRsaPremasterSecret",
- "com.sun.crypto.provider.TlsRsaPremasterSecretGenerator",
- List.of("SunTls12RsaPremasterSecret"), null);
+ if (!systemFipsEnabled) {
+ // PBKDF2
+ psA("SecretKeyFactory", "PBKDF2WithHmacSHA1",
+ "com.sun.crypto.provider.PBKDF2Core$HmacSHA1",
+ null);
+ ps("SecretKeyFactory", "PBKDF2WithHmacSHA224",
+ "com.sun.crypto.provider.PBKDF2Core$HmacSHA224");
+ ps("SecretKeyFactory", "PBKDF2WithHmacSHA256",
+ "com.sun.crypto.provider.PBKDF2Core$HmacSHA256");
+ ps("SecretKeyFactory", "PBKDF2WithHmacSHA384",
+ "com.sun.crypto.provider.PBKDF2Core$HmacSHA384");
+ ps("SecretKeyFactory", "PBKDF2WithHmacSHA512",
+ "com.sun.crypto.provider.PBKDF2Core$HmacSHA512");
+
+ /*
+ * MAC
+ */
+ attrs.clear();
+ attrs.put("SupportedKeyFormats", "RAW");
+ ps("Mac", "HmacMD5", "com.sun.crypto.provider.HmacMD5", null, attrs);
+ psA("Mac", "HmacSHA1", "com.sun.crypto.provider.HmacSHA1",
+ attrs);
+ psA("Mac", "HmacSHA224",
+ "com.sun.crypto.provider.HmacCore$HmacSHA224", attrs);
+ psA("Mac", "HmacSHA256",
+ "com.sun.crypto.provider.HmacCore$HmacSHA256", attrs);
+ psA("Mac", "HmacSHA384",
+ "com.sun.crypto.provider.HmacCore$HmacSHA384", attrs);
+ psA("Mac", "HmacSHA512",
+ "com.sun.crypto.provider.HmacCore$HmacSHA512", attrs);
+ psA("Mac", "HmacSHA512/224",
+ "com.sun.crypto.provider.HmacCore$HmacSHA512_224", attrs);
+ psA("Mac", "HmacSHA512/256",
+ "com.sun.crypto.provider.HmacCore$HmacSHA512_256", attrs);
+ psA("Mac", "HmacSHA3-224",
+ "com.sun.crypto.provider.HmacCore$HmacSHA3_224", attrs);
+ psA("Mac", "HmacSHA3-256",
+ "com.sun.crypto.provider.HmacCore$HmacSHA3_256", attrs);
+ psA("Mac", "HmacSHA3-384",
+ "com.sun.crypto.provider.HmacCore$HmacSHA3_384", attrs);
+ psA("Mac", "HmacSHA3-512",
+ "com.sun.crypto.provider.HmacCore$HmacSHA3_512", attrs);
+
+ ps("Mac", "HmacPBESHA1",
+ "com.sun.crypto.provider.HmacPKCS12PBECore$HmacPKCS12PBE_SHA1",
+ null, attrs);
+ ps("Mac", "HmacPBESHA224",
+ "com.sun.crypto.provider.HmacPKCS12PBECore$HmacPKCS12PBE_SHA224",
+ null, attrs);
+ ps("Mac", "HmacPBESHA256",
+ "com.sun.crypto.provider.HmacPKCS12PBECore$HmacPKCS12PBE_SHA256",
+ null, attrs);
+ ps("Mac", "HmacPBESHA384",
+ "com.sun.crypto.provider.HmacPKCS12PBECore$HmacPKCS12PBE_SHA384",
+ null, attrs);
+ ps("Mac", "HmacPBESHA512",
+ "com.sun.crypto.provider.HmacPKCS12PBECore$HmacPKCS12PBE_SHA512",
+ null, attrs);
+ ps("Mac", "HmacPBESHA512/224",
+ "com.sun.crypto.provider.HmacPKCS12PBECore$HmacPKCS12PBE_SHA512_224",
+ null, attrs);
+ ps("Mac", "HmacPBESHA512/256",
+ "com.sun.crypto.provider.HmacPKCS12PBECore$HmacPKCS12PBE_SHA512_256",
+ null, attrs);
+
+
+ // PBMAC1
+ ps("Mac", "PBEWithHmacSHA1",
+ "com.sun.crypto.provider.PBMAC1Core$HmacSHA1", null, attrs);
+ ps("Mac", "PBEWithHmacSHA224",
+ "com.sun.crypto.provider.PBMAC1Core$HmacSHA224", null, attrs);
+ ps("Mac", "PBEWithHmacSHA256",
+ "com.sun.crypto.provider.PBMAC1Core$HmacSHA256", null, attrs);
+ ps("Mac", "PBEWithHmacSHA384",
+ "com.sun.crypto.provider.PBMAC1Core$HmacSHA384", null, attrs);
+ ps("Mac", "PBEWithHmacSHA512",
+ "com.sun.crypto.provider.PBMAC1Core$HmacSHA512", null, attrs);
+ ps("Mac", "SslMacMD5",
+ "com.sun.crypto.provider.SslMacCore$SslMacMD5", null, attrs);
+ ps("Mac", "SslMacSHA1",
+ "com.sun.crypto.provider.SslMacCore$SslMacSHA1", null, attrs);
+
+ /*
+ * KeyStore
+ */
+ ps("KeyStore", "JCEKS",
+ "com.sun.crypto.provider.JceKeyStore");
+
+ /*
+ * SSL/TLS mechanisms
+ *
+ * These are strictly internal implementations and may
+ * be changed at any time. These names were chosen
+ * because PKCS11/SunPKCS11 does not yet have TLS1.2
+ * mechanisms, and it will cause calls to come here.
+ */
+ ps("KeyGenerator", "SunTlsPrf",
+ "com.sun.crypto.provider.TlsPrfGenerator$V10");
+ ps("KeyGenerator", "SunTls12Prf",
+ "com.sun.crypto.provider.TlsPrfGenerator$V12");
+
+ ps("KeyGenerator", "SunTlsMasterSecret",
+ "com.sun.crypto.provider.TlsMasterSecretGenerator",
+ List.of("SunTls12MasterSecret", "SunTlsExtendedMasterSecret"),
+ null);
+
+ ps("KeyGenerator", "SunTlsKeyMaterial",
+ "com.sun.crypto.provider.TlsKeyMaterialGenerator",
+ List.of("SunTls12KeyMaterial"), null);
+
+ ps("KeyGenerator", "SunTlsRsaPremasterSecret",
+ "com.sun.crypto.provider.TlsRsaPremasterSecretGenerator",
+ List.of("SunTls12RsaPremasterSecret"), null);
+ }
}
// Return the instance of this class or create one if needed.
diff --git a/src/java.base/share/classes/java/security/Security.java b/src/java.base/share/classes/java/security/Security.java
index 2477027969c..06b1b6c671c 100644
--- a/src/java.base/share/classes/java/security/Security.java
+++ b/src/java.base/share/classes/java/security/Security.java
@@ -33,6 +33,7 @@ import java.net.URL;
import jdk.internal.access.JavaSecurityPropertiesAccess;
import jdk.internal.event.EventHelper;
import jdk.internal.event.SecurityPropertyModificationEvent;
+import jdk.internal.access.JavaSecuritySystemConfiguratorAccess;
import jdk.internal.access.SharedSecrets;
import jdk.internal.util.StaticProperty;
import sun.security.util.Debug;
@@ -57,6 +58,11 @@ import sun.security.jca.*;
public final class Security {
+ private static final String SYS_PROP_SWITCH =
+ "java.security.disableSystemPropertiesFile";
+ private static final String SEC_PROP_SWITCH =
+ "security.useSystemPropertiesFile";
+
/* Are we debugging? -- for developers */
private static final Debug sdebug =
Debug.getInstance("properties");
@@ -74,6 +80,19 @@ public final class Security {
}
static {
+ // Initialise here as used by code with system properties disabled
+ SharedSecrets.setJavaSecuritySystemConfiguratorAccess(
+ new JavaSecuritySystemConfiguratorAccess() {
+ @Override
+ public boolean isSystemFipsEnabled() {
+ return SystemConfigurator.isSystemFipsEnabled();
+ }
+ @Override
+ public boolean isPlainKeySupportEnabled() {
+ return SystemConfigurator.isPlainKeySupportEnabled();
+ }
+ });
+
// doPrivileged here because there are multiple
// things in initialize that might require privs.
// (the FileInputStream call and the File.exists call,
@@ -97,6 +116,7 @@ public final class Security {
private static void initialize() {
props = new Properties();
boolean overrideAll = false;
+ boolean systemSecPropsEnabled = false;
// first load the system properties file
// to determine the value of security.overridePropertiesFile
@@ -117,6 +137,60 @@ public final class Security {
}
loadProps(null, extraPropFile, overrideAll);
}
+
+ boolean sysUseProps = Boolean.valueOf(System.getProperty(SYS_PROP_SWITCH, "false"));
+ boolean secUseProps = Boolean.valueOf(props.getProperty(SEC_PROP_SWITCH));
+ if (sdebug != null) {
+ sdebug.println(SYS_PROP_SWITCH + "=" + sysUseProps);
+ sdebug.println(SEC_PROP_SWITCH + "=" + secUseProps);
+ }
+ if (!sysUseProps && secUseProps) {
+ systemSecPropsEnabled = SystemConfigurator.configureSysProps(props);
+ if (!systemSecPropsEnabled) {
+ if (sdebug != null) {
+ sdebug.println("WARNING: System security properties could not be loaded.");
+ }
+ }
+ } else {
+ if (sdebug != null) {
+ sdebug.println("System security property support disabled by user.");
+ }
+ }
+
+ if (systemSecPropsEnabled) {
+ boolean shouldEnable;
+ String sysProp = System.getProperty("com.redhat.fips");
+ if (sysProp == null) {
+ shouldEnable = true;
+ if (sdebug != null) {
+ sdebug.println("com.redhat.fips unset, using default value of true");
+ }
+ } else {
+ shouldEnable = Boolean.valueOf(sysProp);
+ if (sdebug != null) {
+ sdebug.println("com.redhat.fips set, using its value " + shouldEnable);
+ }
+ }
+ if (shouldEnable) {
+ boolean fipsEnabled = SystemConfigurator.configureFIPS(props);
+ if (sdebug != null) {
+ if (fipsEnabled) {
+ sdebug.println("FIPS mode support configured and enabled.");
+ } else {
+ sdebug.println("FIPS mode support disabled.");
+ }
+ }
+ } else {
+ if (sdebug != null ) {
+ sdebug.println("FIPS mode support disabled by user.");
+ }
+ }
+ } else {
+ if (sdebug != null) {
+ sdebug.println("WARNING: FIPS mode support can not be enabled without " +
+ "system security properties being enabled.");
+ }
+ }
initialSecurityProperties = (Properties) props.clone();
if (sdebug != null) {
for (String key : props.stringPropertyNames()) {
@@ -124,10 +198,9 @@ public final class Security {
props.getProperty(key));
}
}
-
}
- private static boolean loadProps(File masterFile, String extraPropFile, boolean overrideAll) {
+ static boolean loadProps(File masterFile, String extraPropFile, boolean overrideAll) {
InputStream is = null;
try {
if (masterFile != null && masterFile.exists()) {
diff --git a/src/java.base/share/classes/java/security/SystemConfigurator.java b/src/java.base/share/classes/java/security/SystemConfigurator.java
new file mode 100644
index 00000000000..9d26a54f5d4
--- /dev/null
+++ b/src/java.base/share/classes/java/security/SystemConfigurator.java
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) 2019, 2021, Red Hat, Inc.
+ *
+ * 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 java.security;
+
+import java.io.BufferedInputStream;
+import java.io.FileInputStream;
+import java.io.IOException;
+
+import java.util.Iterator;
+import java.util.Map.Entry;
+import java.util.Properties;
+
+import sun.security.util.Debug;
+
+/**
+ * Internal class to align OpenJDK with global crypto-policies.
+ * Called from java.security.Security class initialization,
+ * during startup.
+ *
+ */
+
+final class SystemConfigurator {
+
+ private static final Debug sdebug =
+ Debug.getInstance("properties");
+
+ private static final String CRYPTO_POLICIES_BASE_DIR =
+ "/etc/crypto-policies";
+
+ private static final String CRYPTO_POLICIES_JAVA_CONFIG =
+ CRYPTO_POLICIES_BASE_DIR + "/back-ends/java.config";
+
+ private static boolean systemFipsEnabled = false;
+ private static boolean plainKeySupportEnabled = false;
+
+ private static final String SYSTEMCONF_NATIVE_LIB = "systemconf";
+
+ private static native boolean getSystemFIPSEnabled()
+ throws IOException;
+
+ static {
+ @SuppressWarnings("removal")
+ var dummy = AccessController.doPrivileged(new PrivilegedAction<Void>() {
+ public Void run() {
+ System.loadLibrary(SYSTEMCONF_NATIVE_LIB);
+ return null;
+ }
+ });
+ }
+
+ /*
+ * Invoked when java.security.Security class is initialized, if
+ * java.security.disableSystemPropertiesFile property is not set and
+ * security.useSystemPropertiesFile is true.
+ */
+ static boolean configureSysProps(Properties props) {
+ // now load the system file, if it exists, so its values
+ // will win if they conflict with the earlier values
+ return Security.loadProps(null, CRYPTO_POLICIES_JAVA_CONFIG, false);
+ }
+
+ /*
+ * Invoked at the end of java.security.Security initialisation
+ * if java.security properties have been loaded
+ */
+ static boolean configureFIPS(Properties props) {
+ boolean loadedProps = false;
+
+ try {
+ if (enableFips()) {
+ if (sdebug != null) { sdebug.println("FIPS mode detected"); }
+ // Remove all security providers
+ Iterator<Entry<Object, Object>> i = props.entrySet().iterator();
+ while (i.hasNext()) {
+ Entry<Object, Object> e = i.next();
+ if (((String) e.getKey()).startsWith("security.provider")) {
+ if (sdebug != null) { sdebug.println("Removing provider: " + e); }
+ i.remove();
+ }
+ }
+ // Add FIPS security providers
+ String fipsProviderValue = null;
+ for (int n = 1;
+ (fipsProviderValue = (String) props.get("fips.provider." + n)) != null; n++) {
+ String fipsProviderKey = "security.provider." + n;
+ if (sdebug != null) {
+ sdebug.println("Adding provider " + n + ": " +
+ fipsProviderKey + "=" + fipsProviderValue);
+ }
+ props.put(fipsProviderKey, fipsProviderValue);
+ }
+ // Add other security properties
+ String keystoreTypeValue = (String) props.get("fips.keystore.type");
+ if (keystoreTypeValue != null) {
+ String nonFipsKeystoreType = props.getProperty("keystore.type");
+ props.put("keystore.type", keystoreTypeValue);
+ if (keystoreTypeValue.equals("PKCS11")) {
+ // If keystore.type is PKCS11, javax.net.ssl.keyStore
+ // must be "NONE". See JDK-8238264.
+ System.setProperty("javax.net.ssl.keyStore", "NONE");
+ }
+ if (System.getProperty("javax.net.ssl.trustStoreType") == null) {
+ // If no trustStoreType has been set, use the
+ // previous keystore.type under FIPS mode. In
+ // a default configuration, the Trust Store will
+ // be 'cacerts' (JKS type).
+ System.setProperty("javax.net.ssl.trustStoreType",
+ nonFipsKeystoreType);
+ }
+ if (sdebug != null) {
+ sdebug.println("FIPS mode default keystore.type = " +
+ keystoreTypeValue);
+ sdebug.println("FIPS mode javax.net.ssl.keyStore = " +
+ System.getProperty("javax.net.ssl.keyStore", ""));
+ sdebug.println("FIPS mode javax.net.ssl.trustStoreType = " +
+ System.getProperty("javax.net.ssl.trustStoreType", ""));
+ }
+ }
+ loadedProps = true;
+ systemFipsEnabled = true;
+ String plainKeySupport = System.getProperty("com.redhat.fips.plainKeySupport",
+ "true");
+ plainKeySupportEnabled = !"false".equals(plainKeySupport);
+ if (sdebug != null) {
+ if (plainKeySupportEnabled) {
+ sdebug.println("FIPS support enabled with plain key support");
+ } else {
+ sdebug.println("FIPS support enabled without plain key support");
+ }
+ }
+ } else {
+ if (sdebug != null) { sdebug.println("FIPS mode not detected"); }
+ }
+ } catch (Exception e) {
+ if (sdebug != null) {
+ sdebug.println("unable to load FIPS configuration");
+ e.printStackTrace();
+ }
+ }
+ return loadedProps;
+ }
+
+ /**
+ * Returns whether or not global system FIPS alignment is enabled.
+ *
+ * Value is always 'false' before java.security.Security class is
+ * initialized.
+ *
+ * Call from out of this package through SharedSecrets:
+ * SharedSecrets.getJavaSecuritySystemConfiguratorAccess()
+ * .isSystemFipsEnabled();
+ *
+ * @return a boolean value indicating whether or not global
+ * system FIPS alignment is enabled.
+ */
+ static boolean isSystemFipsEnabled() {
+ return systemFipsEnabled;
+ }
+
+ /**
+ * Returns {@code true} if system FIPS alignment is enabled
+ * and plain key support is allowed. Plain key support is
+ * enabled by default but can be disabled with
+ * {@code -Dcom.redhat.fips.plainKeySupport=false}.
+ *
+ * @return a boolean indicating whether plain key support
+ * should be enabled.
+ */
+ static boolean isPlainKeySupportEnabled() {
+ return plainKeySupportEnabled;
+ }
+
+ /**
+ * Determines whether FIPS mode should be enabled.
+ *
+ * OpenJDK FIPS mode will be enabled only if the system is in
+ * FIPS mode.
+ *
+ * Calls to this method only occur if the system property
+ * com.redhat.fips is not set to false.
+ *
+ * There are 2 possible ways in which OpenJDK detects that the system
+ * is in FIPS mode: 1) if the NSS SECMOD_GetSystemFIPSEnabled API is
+ * available at OpenJDK's built-time, it is called; 2) otherwise, the
+ * /proc/sys/crypto/fips_enabled file is read.
+ *
+ * @return true if the system is in FIPS mode
+ */
+ private static boolean enableFips() throws Exception {
+ if (sdebug != null) {
+ sdebug.println("Calling getSystemFIPSEnabled (libsystemconf)...");
+ }
+ try {
+ boolean fipsEnabled = getSystemFIPSEnabled();
+ if (sdebug != null) {
+ sdebug.println("Call to getSystemFIPSEnabled (libsystemconf) returned: "
+ + fipsEnabled);
+ }
+ return fipsEnabled;
+ } catch (IOException e) {
+ if (sdebug != null) {
+ sdebug.println("Call to getSystemFIPSEnabled (libsystemconf) failed:");
+ sdebug.println(e.getMessage());
+ }
+ throw e;
+ }
+ }
+}
diff --git a/src/java.base/share/classes/jdk/internal/access/JavaSecuritySystemConfiguratorAccess.java b/src/java.base/share/classes/jdk/internal/access/JavaSecuritySystemConfiguratorAccess.java
new file mode 100644
index 00000000000..3f3caac64dc
--- /dev/null
+++ b/src/java.base/share/classes/jdk/internal/access/JavaSecuritySystemConfiguratorAccess.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2020, Red Hat, Inc.
+ * 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 jdk.internal.access;
+
+public interface JavaSecuritySystemConfiguratorAccess {
+ boolean isSystemFipsEnabled();
+ boolean isPlainKeySupportEnabled();
+}
diff --git a/src/java.base/share/classes/jdk/internal/access/SharedSecrets.java b/src/java.base/share/classes/jdk/internal/access/SharedSecrets.java
index ea28bb8747e..77161eb3844 100644
--- a/src/java.base/share/classes/jdk/internal/access/SharedSecrets.java
+++ b/src/java.base/share/classes/jdk/internal/access/SharedSecrets.java
@@ -40,6 +40,7 @@ import java.io.FilePermission;
import java.io.ObjectInputStream;
import java.io.RandomAccessFile;
import java.security.ProtectionDomain;
+import java.security.Security;
import java.security.Signature;
/** A repository of "shared secrets", which are a mechanism for
@@ -83,6 +84,7 @@ public class SharedSecrets {
private static JavaSecuritySpecAccess javaSecuritySpecAccess;
private static JavaxCryptoSealedObjectAccess javaxCryptoSealedObjectAccess;
private static JavaxCryptoSpecAccess javaxCryptoSpecAccess;
+ private static JavaSecuritySystemConfiguratorAccess javaSecuritySystemConfiguratorAccess;
public static void setJavaUtilCollectionAccess(JavaUtilCollectionAccess juca) {
javaUtilCollectionAccess = juca;
@@ -457,4 +459,15 @@ public class SharedSecrets {
MethodHandles.lookup().ensureInitialized(c);
} catch (IllegalAccessException e) {}
}
+
+ public static void setJavaSecuritySystemConfiguratorAccess(JavaSecuritySystemConfiguratorAccess jssca) {
+ javaSecuritySystemConfiguratorAccess = jssca;
+ }
+
+ public static JavaSecuritySystemConfiguratorAccess getJavaSecuritySystemConfiguratorAccess() {
+ if (javaSecuritySystemConfiguratorAccess == null) {
+ ensureClassInitialized(Security.class);
+ }
+ return javaSecuritySystemConfiguratorAccess;
+ }
}
diff --git a/src/java.base/share/classes/module-info.java b/src/java.base/share/classes/module-info.java
index fad70bdc058..29a813a485f 100644
--- a/src/java.base/share/classes/module-info.java
+++ b/src/java.base/share/classes/module-info.java
@@ -152,6 +152,8 @@ module java.base {
java.naming,
java.rmi,
jdk.charsets,
+ jdk.crypto.cryptoki,
+ jdk.crypto.ec,
jdk.jartool,
jdk.jlink,
jdk.jfr,
diff --git a/src/java.base/share/classes/sun/security/provider/SunEntries.java b/src/java.base/share/classes/sun/security/provider/SunEntries.java
index 912cad59714..7803e97f7ef 100644
--- a/src/java.base/share/classes/sun/security/provider/SunEntries.java
+++ b/src/java.base/share/classes/sun/security/provider/SunEntries.java
@@ -30,6 +30,7 @@ import java.net.*;
import java.util.*;
import java.security.*;
+import jdk.internal.access.SharedSecrets;
import jdk.internal.util.StaticProperty;
import sun.security.action.GetPropertyAction;
import sun.security.util.SecurityProviderConstants;
@@ -83,6 +84,10 @@ import static sun.security.util.SecurityProviderConstants.getAliases;
public final class SunEntries {
+ private static final boolean systemFipsEnabled =
+ SharedSecrets.getJavaSecuritySystemConfiguratorAccess()
+ .isSystemFipsEnabled();
+
// the default algo used by SecureRandom class for new SecureRandom() calls
public static final String DEF_SECURE_RANDOM_ALGO;
@@ -94,89 +99,92 @@ public final class SunEntries {
// common attribute map
HashMap<String, String> attrs = new HashMap<>(3);
- /*
- * SecureRandom engines
- */
- attrs.put("ThreadSafe", "true");
- if (NativePRNG.isAvailable()) {
- add(p, "SecureRandom", "NativePRNG",
- "sun.security.provider.NativePRNG", attrs);
- }
- if (NativePRNG.Blocking.isAvailable()) {
- add(p, "SecureRandom", "NativePRNGBlocking",
- "sun.security.provider.NativePRNG$Blocking", attrs);
- }
- if (NativePRNG.NonBlocking.isAvailable()) {
- add(p, "SecureRandom", "NativePRNGNonBlocking",
- "sun.security.provider.NativePRNG$NonBlocking", attrs);
- }
- attrs.put("ImplementedIn", "Software");
- add(p, "SecureRandom", "DRBG", "sun.security.provider.DRBG", attrs);
- add(p, "SecureRandom", "SHA1PRNG",
- "sun.security.provider.SecureRandom", attrs);
-
- /*
- * Signature engines
- */
- attrs.clear();
- String dsaKeyClasses = "java.security.interfaces.DSAPublicKey" +
- "|java.security.interfaces.DSAPrivateKey";
- attrs.put("SupportedKeyClasses", dsaKeyClasses);
- attrs.put("ImplementedIn", "Software");
-
- attrs.put("KeySize", "1024"); // for NONE and SHA1 DSA signatures
-
- addWithAlias(p, "Signature", "SHA1withDSA",
- "sun.security.provider.DSA$SHA1withDSA", attrs);
- addWithAlias(p, "Signature", "NONEwithDSA",
- "sun.security.provider.DSA$RawDSA", attrs);
-
- // for DSA signatures with 224/256-bit digests
- attrs.put("KeySize", "2048");
-
- addWithAlias(p, "Signature", "SHA224withDSA",
- "sun.security.provider.DSA$SHA224withDSA", attrs);
- addWithAlias(p, "Signature", "SHA256withDSA",
- "sun.security.provider.DSA$SHA256withDSA", attrs);
-
- addWithAlias(p, "Signature", "SHA3-224withDSA",
- "sun.security.provider.DSA$SHA3_224withDSA", attrs);
- addWithAlias(p, "Signature", "SHA3-256withDSA",
- "sun.security.provider.DSA$SHA3_256withDSA", attrs);
-
- attrs.put("KeySize", "3072"); // for DSA sig using 384/512-bit digests
-
- addWithAlias(p, "Signature", "SHA384withDSA",
- "sun.security.provider.DSA$SHA384withDSA", attrs);
- addWithAlias(p, "Signature", "SHA512withDSA",
- "sun.security.provider.DSA$SHA512withDSA", attrs);
- addWithAlias(p, "Signature", "SHA3-384withDSA",
- "sun.security.provider.DSA$SHA3_384withDSA", attrs);
- addWithAlias(p, "Signature", "SHA3-512withDSA",
- "sun.security.provider.DSA$SHA3_512withDSA", attrs);
+ if (!systemFipsEnabled) {
+ /*
+ * SecureRandom engines
+ */
+ attrs.put("ThreadSafe", "true");
+ if (NativePRNG.isAvailable()) {
+ add(p, "SecureRandom", "NativePRNG",
+ "sun.security.provider.NativePRNG", attrs);
+ }
+ if (NativePRNG.Blocking.isAvailable()) {
+ add(p, "SecureRandom", "NativePRNGBlocking",
+ "sun.security.provider.NativePRNG$Blocking", attrs);
+ }
+ if (NativePRNG.NonBlocking.isAvailable()) {
+ add(p, "SecureRandom", "NativePRNGNonBlocking",
+ "sun.security.provider.NativePRNG$NonBlocking", attrs);
+ }
+ attrs.put("ImplementedIn", "Software");
+ add(p, "SecureRandom", "DRBG", "sun.security.provider.DRBG", attrs);
+ add(p, "SecureRandom", "SHA1PRNG",
+ "sun.security.provider.SecureRandom", attrs);
- attrs.remove("KeySize");
+ /*
+ * Signature engines
+ */
+ attrs.clear();
+ String dsaKeyClasses = "java.security.interfaces.DSAPublicKey" +
+ "|java.security.interfaces.DSAPrivateKey";
+ attrs.put("SupportedKeyClasses", dsaKeyClasses);
+ attrs.put("ImplementedIn", "Software");
+
+ attrs.put("KeySize", "1024"); // for NONE and SHA1 DSA signatures
+
+ addWithAlias(p, "Signature", "SHA1withDSA",
+ "sun.security.provider.DSA$SHA1withDSA", attrs);
+ addWithAlias(p, "Signature", "NONEwithDSA",
+ "sun.security.provider.DSA$RawDSA", attrs);
+
+ // for DSA signatures with 224/256-bit digests
+ attrs.put("KeySize", "2048");
+
+ addWithAlias(p, "Signature", "SHA224withDSA",
+ "sun.security.provider.DSA$SHA224withDSA", attrs);
+ addWithAlias(p, "Signature", "SHA256withDSA",
+ "sun.security.provider.DSA$SHA256withDSA", attrs);
+
+ addWithAlias(p, "Signature", "SHA3-224withDSA",
+ "sun.security.provider.DSA$SHA3_224withDSA", attrs);
+ addWithAlias(p, "Signature", "SHA3-256withDSA",
+ "sun.security.provider.DSA$SHA3_256withDSA", attrs);
+
+ attrs.put("KeySize", "3072"); // for DSA sig using 384/512-bit digests
+
+ addWithAlias(p, "Signature", "SHA384withDSA",
+ "sun.security.provider.DSA$SHA384withDSA", attrs);
+ addWithAlias(p, "Signature", "SHA512withDSA",
+ "sun.security.provider.DSA$SHA512withDSA", attrs);
+ addWithAlias(p, "Signature", "SHA3-384withDSA",
+ "sun.security.provider.DSA$SHA3_384withDSA", attrs);
+ addWithAlias(p, "Signature", "SHA3-512withDSA",
+ "sun.security.provider.DSA$SHA3_512withDSA", attrs);
+
+ attrs.remove("KeySize");
+
+ add(p, "Signature", "SHA1withDSAinP1363Format",
+ "sun.security.provider.DSA$SHA1withDSAinP1363Format");
+ add(p, "Signature", "NONEwithDSAinP1363Format",
+ "sun.security.provider.DSA$RawDSAinP1363Format");
+ add(p, "Signature", "SHA224withDSAinP1363Format",
+ "sun.security.provider.DSA$SHA224withDSAinP1363Format");
+ add(p, "Signature", "SHA256withDSAinP1363Format",
+ "sun.security.provider.DSA$SHA256withDSAinP1363Format");
+ add(p, "Signature", "SHA384withDSAinP1363Format",
+ "sun.security.provider.DSA$SHA384withDSAinP1363Format");
+ add(p, "Signature", "SHA512withDSAinP1363Format",
+ "sun.security.provider.DSA$SHA512withDSAinP1363Format");
+ add(p, "Signature", "SHA3-224withDSAinP1363Format",
+ "sun.security.provider.DSA$SHA3_224withDSAinP1363Format");
+ add(p, "Signature", "SHA3-256withDSAinP1363Format",
+ "sun.security.provider.DSA$SHA3_256withDSAinP1363Format");
+ add(p, "Signature", "SHA3-384withDSAinP1363Format",
+ "sun.security.provider.DSA$SHA3_384withDSAinP1363Format");
+ add(p, "Signature", "SHA3-512withDSAinP1363Format",
+ "sun.security.provider.DSA$SHA3_512withDSAinP1363Format");
+ }
- add(p, "Signature", "SHA1withDSAinP1363Format",
- "sun.security.provider.DSA$SHA1withDSAinP1363Format");
- add(p, "Signature", "NONEwithDSAinP1363Format",
- "sun.security.provider.DSA$RawDSAinP1363Format");
- add(p, "Signature", "SHA224withDSAinP1363Format",
- "sun.security.provider.DSA$SHA224withDSAinP1363Format");
- add(p, "Signature", "SHA256withDSAinP1363Format",
- "sun.security.provider.DSA$SHA256withDSAinP1363Format");
- add(p, "Signature", "SHA384withDSAinP1363Format",
- "sun.security.provider.DSA$SHA384withDSAinP1363Format");
- add(p, "Signature", "SHA512withDSAinP1363Format",
- "sun.security.provider.DSA$SHA512withDSAinP1363Format");
- add(p, "Signature", "SHA3-224withDSAinP1363Format",
- "sun.security.provider.DSA$SHA3_224withDSAinP1363Format");
- add(p, "Signature", "SHA3-256withDSAinP1363Format",
- "sun.security.provider.DSA$SHA3_256withDSAinP1363Format");
- add(p, "Signature", "SHA3-384withDSAinP1363Format",
- "sun.security.provider.DSA$SHA3_384withDSAinP1363Format");
- add(p, "Signature", "SHA3-512withDSAinP1363Format",
- "sun.security.provider.DSA$SHA3_512withDSAinP1363Format");
/*
* Key Pair Generator engines
*/
@@ -184,9 +192,11 @@ public final class SunEntries {
attrs.put("ImplementedIn", "Software");
attrs.put("KeySize", "2048"); // for DSA KPG and APG only
- String dsaKPGImplClass = "sun.security.provider.DSAKeyPairGenerator$";
- dsaKPGImplClass += (useLegacyDSA? "Legacy" : "Current");
- addWithAlias(p, "KeyPairGenerator", "DSA", dsaKPGImplClass, attrs);
+ if (!systemFipsEnabled) {
+ String dsaKPGImplClass = "sun.security.provider.DSAKeyPairGenerator$";
+ dsaKPGImplClass += (useLegacyDSA? "Legacy" : "Current");
+ addWithAlias(p, "KeyPairGenerator", "DSA", dsaKPGImplClass, attrs);
+ }
/*
* Algorithm Parameter Generator engines
@@ -201,40 +211,42 @@ public final class SunEntries {
addWithAlias(p, "AlgorithmParameters", "DSA",
"sun.security.provider.DSAParameters", attrs);
- /*
- * Key factories
- */
- addWithAlias(p, "KeyFactory", "DSA",
- "sun.security.provider.DSAKeyFactory", attrs);
-
- /*
- * Digest engines
- */
- add(p, "MessageDigest", "MD2", "sun.security.provider.MD2", attrs);
- add(p, "MessageDigest", "MD5", "sun.security.provider.MD5", attrs);
- addWithAlias(p, "MessageDigest", "SHA-1", "sun.security.provider.SHA",
- attrs);
+ if (!systemFipsEnabled) {
+ /*
+ * Key factories
+ */
+ addWithAlias(p, "KeyFactory", "DSA",
+ "sun.security.provider.DSAKeyFactory", attrs);
- addWithAlias(p, "MessageDigest", "SHA-224",
- "sun.security.provider.SHA2$SHA224", attrs);
- addWithAlias(p, "MessageDigest", "SHA-256",
- "sun.security.provider.SHA2$SHA256", attrs);
- addWithAlias(p, "MessageDigest", "SHA-384",
- "sun.security.provider.SHA5$SHA384", attrs);
- addWithAlias(p, "MessageDigest", "SHA-512",
- "sun.security.provider.SHA5$SHA512", attrs);
- addWithAlias(p, "MessageDigest", "SHA-512/224",
- "sun.security.provider.SHA5$SHA512_224", attrs);
- addWithAlias(p, "MessageDigest", "SHA-512/256",
- "sun.security.provider.SHA5$SHA512_256", attrs);
- addWithAlias(p, "MessageDigest", "SHA3-224",
- "sun.security.provider.SHA3$SHA224", attrs);
- addWithAlias(p, "MessageDigest", "SHA3-256",
- "sun.security.provider.SHA3$SHA256", attrs);
- addWithAlias(p, "MessageDigest", "SHA3-384",
- "sun.security.provider.SHA3$SHA384", attrs);
- addWithAlias(p, "MessageDigest", "SHA3-512",
- "sun.security.provider.SHA3$SHA512", attrs);
+ /*
+ * Digest engines
+ */
+ add(p, "MessageDigest", "MD2", "sun.security.provider.MD2", attrs);
+ add(p, "MessageDigest", "MD5", "sun.security.provider.MD5", attrs);
+ addWithAlias(p, "MessageDigest", "SHA-1", "sun.security.provider.SHA",
+ attrs);
+
+ addWithAlias(p, "MessageDigest", "SHA-224",
+ "sun.security.provider.SHA2$SHA224", attrs);
+ addWithAlias(p, "MessageDigest", "SHA-256",
+ "sun.security.provider.SHA2$SHA256", attrs);
+ addWithAlias(p, "MessageDigest", "SHA-384",
+ "sun.security.provider.SHA5$SHA384", attrs);
+ addWithAlias(p, "MessageDigest", "SHA-512",
+ "sun.security.provider.SHA5$SHA512", attrs);
+ addWithAlias(p, "MessageDigest", "SHA-512/224",
+ "sun.security.provider.SHA5$SHA512_224", attrs);
+ addWithAlias(p, "MessageDigest", "SHA-512/256",
+ "sun.security.provider.SHA5$SHA512_256", attrs);
+ addWithAlias(p, "MessageDigest", "SHA3-224",
+ "sun.security.provider.SHA3$SHA224", attrs);
+ addWithAlias(p, "MessageDigest", "SHA3-256",
+ "sun.security.provider.SHA3$SHA256", attrs);
+ addWithAlias(p, "MessageDigest", "SHA3-384",
+ "sun.security.provider.SHA3$SHA384", attrs);
+ addWithAlias(p, "MessageDigest", "SHA3-512",
+ "sun.security.provider.SHA3$SHA512", attrs);
+ }
/*
* Certificates
diff --git a/src/java.base/share/classes/sun/security/rsa/SunRsaSignEntries.java b/src/java.base/share/classes/sun/security/rsa/SunRsaSignEntries.java
index ca79f25cc44..a12fcbbd6e7 100644
--- a/src/java.base/share/classes/sun/security/rsa/SunRsaSignEntries.java
+++ b/src/java.base/share/classes/sun/security/rsa/SunRsaSignEntries.java
@@ -27,6 +27,7 @@ package sun.security.rsa;
import java.util.*;
import java.security.Provider;
+import jdk.internal.access.SharedSecrets;
import static sun.security.util.SecurityProviderConstants.getAliases;
/**
@@ -36,6 +37,10 @@ import static sun.security.util.SecurityProviderConstants.getAliases;
*/
public final class SunRsaSignEntries {
+ private static final boolean systemFipsEnabled =
+ SharedSecrets.getJavaSecuritySystemConfiguratorAccess()
+ .isSystemFipsEnabled();
+
private void add(Provider p, String type, String algo, String cn,
List<String> aliases, HashMap<String, String> attrs) {
services.add(new Provider.Service(p, type, algo, cn,
@@ -63,42 +68,49 @@ public final class SunRsaSignEntries {
add(p, "KeyFactory", "RSA",
"sun.security.rsa.RSAKeyFactory$Legacy",
getAliases("PKCS1"), null);
- add(p, "KeyPairGenerator", "RSA",
- "sun.security.rsa.RSAKeyPairGenerator$Legacy",
- getAliases("PKCS1"), null);
- addA(p, "Signature", "MD2withRSA",
- "sun.security.rsa.RSASignature$MD2withRSA", attrs);
- addA(p, "Signature", "MD5withRSA",
- "sun.security.rsa.RSASignature$MD5withRSA", attrs);
- addA(p, "Signature", "SHA1withRSA",
- "sun.security.rsa.RSASignature$SHA1withRSA", attrs);
- addA(p, "Signature", "SHA224withRSA",
- "sun.security.rsa.RSASignature$SHA224withRSA", attrs);
- addA(p, "Signature", "SHA256withRSA",
- "sun.security.rsa.RSASignature$SHA256withRSA", attrs);
- addA(p, "Signature", "SHA384withRSA",
- "sun.security.rsa.RSASignature$SHA384withRSA", attrs);
- addA(p, "Signature", "SHA512withRSA",
- "sun.security.rsa.RSASignature$SHA512withRSA", attrs);
- addA(p, "Signature", "SHA512/224withRSA",
- "sun.security.rsa.RSASignature$SHA512_224withRSA", attrs);
- addA(p, "Signature", "SHA512/256withRSA",
- "sun.security.rsa.RSASignature$SHA512_256withRSA", attrs);
- addA(p, "Signature", "SHA3-224withRSA",
- "sun.security.rsa.RSASignature$SHA3_224withRSA", attrs);
- addA(p, "Signature", "SHA3-256withRSA",
- "sun.security.rsa.RSASignature$SHA3_256withRSA", attrs);
- addA(p, "Signature", "SHA3-384withRSA",
- "sun.security.rsa.RSASignature$SHA3_384withRSA", attrs);
- addA(p, "Signature", "SHA3-512withRSA",
- "sun.security.rsa.RSASignature$SHA3_512withRSA", attrs);
+
+ if (!systemFipsEnabled) {
+ add(p, "KeyPairGenerator", "RSA",
+ "sun.security.rsa.RSAKeyPairGenerator$Legacy",
+ getAliases("PKCS1"), null);
+ addA(p, "Signature", "MD2withRSA",
+ "sun.security.rsa.RSASignature$MD2withRSA", attrs);
+ addA(p, "Signature", "MD5withRSA",
+ "sun.security.rsa.RSASignature$MD5withRSA", attrs);
+ addA(p, "Signature", "SHA1withRSA",
+ "sun.security.rsa.RSASignature$SHA1withRSA", attrs);
+ addA(p, "Signature", "SHA224withRSA",
+ "sun.security.rsa.RSASignature$SHA224withRSA", attrs);
+ addA(p, "Signature", "SHA256withRSA",
+ "sun.security.rsa.RSASignature$SHA256withRSA", attrs);
+ addA(p, "Signature", "SHA384withRSA",
+ "sun.security.rsa.RSASignature$SHA384withRSA", attrs);
+ addA(p, "Signature", "SHA512withRSA",
+ "sun.security.rsa.RSASignature$SHA512withRSA", attrs);
+ addA(p, "Signature", "SHA512/224withRSA",
+ "sun.security.rsa.RSASignature$SHA512_224withRSA", attrs);
+ addA(p, "Signature", "SHA512/256withRSA",
+ "sun.security.rsa.RSASignature$SHA512_256withRSA", attrs);
+ addA(p, "Signature", "SHA3-224withRSA",
+ "sun.security.rsa.RSASignature$SHA3_224withRSA", attrs);
+ addA(p, "Signature", "SHA3-256withRSA",
+ "sun.security.rsa.RSASignature$SHA3_256withRSA", attrs);
+ addA(p, "Signature", "SHA3-384withRSA",
+ "sun.security.rsa.RSASignature$SHA3_384withRSA", attrs);
+ addA(p, "Signature", "SHA3-512withRSA",
+ "sun.security.rsa.RSASignature$SHA3_512withRSA", attrs);
+ }
addA(p, "KeyFactory", "RSASSA-PSS",
"sun.security.rsa.RSAKeyFactory$PSS", attrs);
- addA(p, "KeyPairGenerator", "RSASSA-PSS",
- "sun.security.rsa.RSAKeyPairGenerator$PSS", attrs);
- addA(p, "Signature", "RSASSA-PSS",
- "sun.security.rsa.RSAPSSSignature", attrs);
+
+ if (!systemFipsEnabled) {
+ addA(p, "KeyPairGenerator", "RSASSA-PSS",
+ "sun.security.rsa.RSAKeyPairGenerator$PSS", attrs);
+ addA(p, "Signature", "RSASSA-PSS",
+ "sun.security.rsa.RSAPSSSignature", attrs);
+ }
+
addA(p, "AlgorithmParameters", "RSASSA-PSS",
"sun.security.rsa.PSSParameters", null);
}
diff --git a/src/java.base/share/classes/sun/security/util/PBEUtil.java b/src/java.base/share/classes/sun/security/util/PBEUtil.java
new file mode 100644
index 00000000000..dc8bc72fccb
--- /dev/null
+++ b/src/java.base/share/classes/sun/security/util/PBEUtil.java
@@ -0,0 +1,297 @@
+/*
+ * Copyright (c) 2022, Red Hat, Inc.
+ * 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 sun.security.util;
+
+import java.security.AlgorithmParameters;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.NoSuchAlgorithmException;
+import java.security.Provider;
+import java.security.SecureRandom;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.InvalidParameterSpecException;
+import java.util.Arrays;
+import javax.crypto.Cipher;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.PBEKeySpec;
+import javax.crypto.spec.PBEParameterSpec;
+
+public final class PBEUtil {
+
+ // Used by SunJCE and SunPKCS11
+ public final static class PBES2Helper {
+ private int iCount;
+ private byte[] salt;
+ private IvParameterSpec ivSpec;
+ private final int defaultSaltLength;
+ private final int defaultCount;
+
+ public PBES2Helper(int defaultSaltLength, int defaultCount) {
+ this.defaultSaltLength = defaultSaltLength;
+ this.defaultCount = defaultCount;
+ }
+
+ public IvParameterSpec getIvSpec() {
+ return ivSpec;
+ }
+
+ public AlgorithmParameters getAlgorithmParameters(
+ int blkSize, String pbeAlgo, Provider p, SecureRandom random) {
+ AlgorithmParameters params = null;
+ if (salt == null) {
+ // generate random salt and use default iteration count
+ salt = new byte[defaultSaltLength];
+ random.nextBytes(salt);
+ iCount = defaultCount;
+ }
+ if (ivSpec == null) {
+ // generate random IV
+ byte[] ivBytes = new byte[blkSize];
+ random.nextBytes(ivBytes);
+ ivSpec = new IvParameterSpec(ivBytes);
+ }
+ PBEParameterSpec pbeSpec = new PBEParameterSpec(
+ salt, iCount, ivSpec);
+ try {
+ params = (p == null) ?
+ AlgorithmParameters.getInstance(pbeAlgo) :
+ AlgorithmParameters.getInstance(pbeAlgo, p);
+ params.init(pbeSpec);
+ } catch (NoSuchAlgorithmException nsae) {
+ // should never happen
+ throw new RuntimeException("AlgorithmParameters for "
+ + pbeAlgo + " not configured");
+ } catch (InvalidParameterSpecException ipse) {
+ // should never happen
+ throw new RuntimeException("PBEParameterSpec not supported");
+ }
+ return params;
+ }
+
+ public PBEKeySpec getPBEKeySpec(
+ int blkSize, int keyLength, int opmode, Key key,
+ AlgorithmParameterSpec params, SecureRandom random)
+ throws InvalidKeyException, InvalidAlgorithmParameterException {
+
+ if (key == null) {
+ throw new InvalidKeyException("Null key");
+ }
+
+ byte[] passwdBytes = key.getEncoded();
+ char[] passwdChars = null;
+ PBEKeySpec pbeSpec;
+ try {
+ if ((passwdBytes == null) || !(key.getAlgorithm().regionMatches(
+ true, 0, "PBE", 0, 3))) {
+ throw new InvalidKeyException("Missing password");
+ }
+
+ // TBD: consolidate the salt, ic and IV parameter checks below
+
+ // Extract salt and iteration count from the key, if present
+ if (key instanceof javax.crypto.interfaces.PBEKey) {
+ salt = ((javax.crypto.interfaces.PBEKey)key).getSalt();
+ if (salt != null && salt.length < 8) {
+ throw new InvalidAlgorithmParameterException(
+ "Salt must be at least 8 bytes long");
+ }
+ iCount = ((javax.crypto.interfaces.PBEKey)key)
+ .getIterationCount();
+ if (iCount == 0) {
+ iCount = defaultCount;
+ } else if (iCount < 0) {
+ throw new InvalidAlgorithmParameterException(
+ "Iteration count must be a positive number");
+ }
+ }
+
+ // Extract salt, iteration count and IV from the params,
+ // if present
+ if (params == null) {
+ if (salt == null) {
+ // generate random salt and use default iteration count
+ salt = new byte[defaultSaltLength];
+ random.nextBytes(salt);
+ iCount = defaultCount;
+ }
+ if ((opmode == Cipher.ENCRYPT_MODE) ||
+ (opmode == Cipher.WRAP_MODE)) {
+ // generate random IV
+ byte[] ivBytes = new byte[blkSize];
+ random.nextBytes(ivBytes);
+ ivSpec = new IvParameterSpec(ivBytes);
+ }
+ } else {
+ if (!(params instanceof PBEParameterSpec)) {
+ throw new InvalidAlgorithmParameterException
+ ("Wrong parameter type: PBE expected");
+ }
+ // salt and iteration count from the params take precedence
+ byte[] specSalt = ((PBEParameterSpec) params).getSalt();
+ if (specSalt != null && specSalt.length < 8) {
+ throw new InvalidAlgorithmParameterException(
+ "Salt must be at least 8 bytes long");
+ }
+ salt = specSalt;
+ int specICount = ((PBEParameterSpec) params)
+ .getIterationCount();
+ if (specICount == 0) {
+ specICount = defaultCount;
+ } else if (specICount < 0) {
+ throw new InvalidAlgorithmParameterException(
+ "Iteration count must be a positive number");
+ }
+ iCount = specICount;
+
+ AlgorithmParameterSpec specParams =
+ ((PBEParameterSpec) params).getParameterSpec();
+ if (specParams != null) {
+ if (specParams instanceof IvParameterSpec) {
+ ivSpec = (IvParameterSpec)specParams;
+ } else {
+ throw new InvalidAlgorithmParameterException(
+ "Wrong parameter type: IV expected");
+ }
+ } else if ((opmode == Cipher.ENCRYPT_MODE) ||
+ (opmode == Cipher.WRAP_MODE)) {
+ // generate random IV
+ byte[] ivBytes = new byte[blkSize];
+ random.nextBytes(ivBytes);
+ ivSpec = new IvParameterSpec(ivBytes);
+ } else {
+ throw new InvalidAlgorithmParameterException(
+ "Missing parameter type: IV expected");
+ }
+ }
+
+ passwdChars = new char[passwdBytes.length];
+ for (int i = 0; i < passwdChars.length; i++)
+ passwdChars[i] = (char) (passwdBytes[i] & 0x7f);
+
+ pbeSpec = new PBEKeySpec(passwdChars, salt, iCount, keyLength);
+ // password char[] was cloned in PBEKeySpec constructor,
+ // so we can zero it out here
+ } finally {
+ if (passwdChars != null) Arrays.fill(passwdChars, '\0');
+ if (passwdBytes != null) Arrays.fill(passwdBytes, (byte)0x00);
+ }
+ return pbeSpec;
+ }
+
+ public static AlgorithmParameterSpec getParameterSpec(
+ AlgorithmParameters params)
+ throws InvalidAlgorithmParameterException {
+ AlgorithmParameterSpec pbeSpec = null;
+ if (params != null) {
+ try {
+ pbeSpec = params.getParameterSpec(PBEParameterSpec.class);
+ } catch (InvalidParameterSpecException ipse) {
+ throw new InvalidAlgorithmParameterException(
+ "Wrong parameter type: PBE expected");
+ }
+ }
+ return pbeSpec;
+ }
+ }
+
+ // Used by SunJCE and SunPKCS11
+ public static PBEKeySpec getPBAKeySpec(Key key, AlgorithmParameterSpec params)
+ throws InvalidKeyException, InvalidAlgorithmParameterException {
+ char[] passwdChars;
+ byte[] salt = null;
+ int iCount = 0;
+ if (key instanceof javax.crypto.interfaces.PBEKey) {
+ javax.crypto.interfaces.PBEKey pbeKey =
+ (javax.crypto.interfaces.PBEKey) key;
+ passwdChars = pbeKey.getPassword();
+ salt = pbeKey.getSalt(); // maybe null if unspecified
+ iCount = pbeKey.getIterationCount(); // maybe 0 if unspecified
+ } else if (key instanceof SecretKey) {
+ byte[] passwdBytes;
+ if (!(key.getAlgorithm().regionMatches(true, 0, "PBE", 0, 3)) ||
+ (passwdBytes = key.getEncoded()) == null) {
+ throw new InvalidKeyException("Missing password");
+ }
+ passwdChars = new char[passwdBytes.length];
+ for (int i=0; i<passwdChars.length; i++) {
+ passwdChars[i] = (char) (passwdBytes[i] & 0x7f);
+ }
+ Arrays.fill(passwdBytes, (byte)0x00);
+ } else {
+ throw new InvalidKeyException("SecretKey of PBE type required");
+ }
+
+ try {
+ if (params == null) {
+ // should not auto-generate default values since current
+ // javax.crypto.Mac api does not have any method for caller to
+ // retrieve the generated defaults.
+ if ((salt == null) || (iCount == 0)) {
+ throw new InvalidAlgorithmParameterException
+ ("PBEParameterSpec required for salt and iteration count");
+ }
+ } else if (!(params instanceof PBEParameterSpec)) {
+ throw new InvalidAlgorithmParameterException
+ ("PBEParameterSpec type required");
+ } else {
+ PBEParameterSpec pbeParams = (PBEParameterSpec) params;
+ // make sure the parameter values are consistent
+ if (salt != null) {
+ if (!Arrays.equals(salt, pbeParams.getSalt())) {
+ throw new InvalidAlgorithmParameterException
+ ("Inconsistent value of salt between key and params");
+ }
+ } else {
+ salt = pbeParams.getSalt();
+ }
+ if (iCount != 0) {
+ if (iCount != pbeParams.getIterationCount()) {
+ throw new InvalidAlgorithmParameterException
+ ("Different iteration count between key and params");
+ }
+ } else {
+ iCount = pbeParams.getIterationCount();
+ }
+ }
+ // For security purpose, we need to enforce a minimum length
+ // for salt; just require the minimum salt length to be 8-byte
+ // which is what PKCS#5 recommends and openssl does.
+ if (salt.length < 8) {
+ throw new InvalidAlgorithmParameterException
+ ("Salt must be at least 8 bytes long");
+ }
+ if (iCount <= 0) {
+ throw new InvalidAlgorithmParameterException
+ ("IterationCount must be a positive number");
+ }
+ return new PBEKeySpec(passwdChars, salt, iCount);
+ } finally {
+ Arrays.fill(passwdChars, '\0');
+ }
+ }
+}
diff --git a/src/java.base/share/conf/security/java.security b/src/java.base/share/conf/security/java.security
index fab52688c04..29337576f37 100644
--- a/src/java.base/share/conf/security/java.security
+++ b/src/java.base/share/conf/security/java.security
@@ -82,6 +82,17 @@ security.provider.tbd=Apple
#endif
security.provider.tbd=SunPKCS11
+#
+# Security providers used when FIPS mode support is active
+#
+fips.provider.1=SunPKCS11 ${java.home}/conf/security/nss.fips.cfg
+fips.provider.2=SUN
+fips.provider.3=SunEC
+fips.provider.4=SunJSSE
+fips.provider.5=SunJCE
+fips.provider.6=SunRsaSign
+fips.provider.7=XMLDSig
+
#
# A list of preferred providers for specific algorithms. These providers will
# be searched for matching algorithms before the list of registered providers.
@@ -292,6 +303,47 @@ policy.ignoreIdentityScope=false
#
keystore.type=pkcs12
+#
+# Default keystore type used when global crypto-policies are set to FIPS.
+#
+fips.keystore.type=pkcs12
+
+#
+# Location of the NSS DB keystore (PKCS11) in FIPS mode.
+#
+# The syntax for this property is identical to the 'nssSecmodDirectory'
+# attribute available in the SunPKCS11 NSS configuration file. Use the
+# 'sql:' prefix to refer to an SQLite DB.
+#
+# If the system property fips.nssdb.path is also specified, it supersedes
+# the security property value defined here.
+#
+# Note: the default value for this property points to an NSS DB that might be
+# readable by multiple operating system users and unsuitable to store keys.
+#
+fips.nssdb.path=sql:/etc/pki/nssdb
+
+#
+# PIN for the NSS DB keystore (PKCS11) in FIPS mode.
+#
+# Values must take any of the following forms:
+# 1) pin:<value>
+# Value: clear text PIN value.
+# 2) env:<value>
+# Value: environment variable containing the PIN value.
+# 3) file:<value>
+# Value: path to a file containing the PIN value in its first
+# line.
+#
+# If the system property fips.nssdb.pin is also specified, it supersedes
+# the security property value defined here.
+#
+# When used as a system property, UTF-8 encoded values are valid. When
+# used as a security property (such as in this file), encode non-Basic
+# Latin Unicode characters with \uXXXX.
+#
+fips.nssdb.pin=pin:
+
#
# Controls compatibility mode for JKS and PKCS12 keystore types.
#
@@ -329,6 +381,13 @@ package.definition=sun.misc.,\
#
security.overridePropertiesFile=true
+#
+# Determines whether this properties file will be appended to
+# using the system properties file stored at
+# /etc/crypto-policies/back-ends/java.config
+#
+security.useSystemPropertiesFile=false
+
#
# Determines the default key and trust manager factory algorithms for
# the javax.net.ssl package.
diff --git a/src/java.base/share/conf/security/nss.fips.cfg.in b/src/java.base/share/conf/security/nss.fips.cfg.in
new file mode 100644
index 00000000000..55bbba98b7a
--- /dev/null
+++ b/src/java.base/share/conf/security/nss.fips.cfg.in
@@ -0,0 +1,8 @@
+name = NSS-FIPS
+nssLibraryDirectory = @NSS_LIBDIR@
+nssSecmodDirectory = ${fips.nssdb.path}
+nssDbMode = readWrite
+nssModule = fips
+
+attributes(*,CKO_SECRET_KEY,CKK_GENERIC_SECRET)={ CKA_SIGN=true }
+
diff --git a/src/java.base/share/lib/security/default.policy b/src/java.base/share/lib/security/default.policy
index b22f26947af..02bea84e210 100644
--- a/src/java.base/share/lib/security/default.policy
+++ b/src/java.base/share/lib/security/default.policy
@@ -121,6 +121,7 @@ grant codeBase "jrt:/jdk.charsets" {
grant codeBase "jrt:/jdk.crypto.ec" {
permission java.lang.RuntimePermission
"accessClassInPackage.sun.security.*";
+ permission java.lang.RuntimePermission "accessClassInPackage.jdk.internal.access";
permission java.lang.RuntimePermission "loadLibrary.sunec";
permission java.security.SecurityPermission "putProviderProperty.SunEC";
permission java.security.SecurityPermission "clearProviderProperties.SunEC";
@@ -130,6 +131,7 @@ grant codeBase "jrt:/jdk.crypto.ec" {
grant codeBase "jrt:/jdk.crypto.cryptoki" {
permission java.lang.RuntimePermission
"accessClassInPackage.com.sun.crypto.provider";
+ permission java.lang.RuntimePermission "accessClassInPackage.jdk.internal.access";
permission java.lang.RuntimePermission "accessClassInPackage.jdk.internal.misc";
permission java.lang.RuntimePermission
"accessClassInPackage.sun.security.*";
@@ -140,6 +142,8 @@ grant codeBase "jrt:/jdk.crypto.cryptoki" {
permission java.util.PropertyPermission "os.name", "read";
permission java.util.PropertyPermission "os.arch", "read";
permission java.util.PropertyPermission "jdk.crypto.KeyAgreement.legacyKDF", "read";
+ permission java.util.PropertyPermission "fips.nssdb.path", "read,write";
+ permission java.util.PropertyPermission "fips.nssdb.pin", "read";
permission java.security.SecurityPermission "putProviderProperty.*";
permission java.security.SecurityPermission "clearProviderProperties.*";
permission java.security.SecurityPermission "removeProviderProperty.*";
diff --git a/src/java.base/share/native/libsystemconf/systemconf.c b/src/java.base/share/native/libsystemconf/systemconf.c
new file mode 100644
index 00000000000..ddf9befe5bc
--- /dev/null
+++ b/src/java.base/share/native/libsystemconf/systemconf.c
@@ -0,0 +1,236 @@
+/*
+ * Copyright (c) 2021, Red Hat, Inc.
+ * 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 <jni.h>
+#include <jni_util.h>
+#include "jvm_md.h"
+#include <stdio.h>
+
+#ifdef LINUX
+
+#ifdef SYSCONF_NSS
+#include <nss3/pk11pub.h>
+#else
+#include <dlfcn.h>
+#endif //SYSCONF_NSS
+
+#include "java_security_SystemConfigurator.h"
+
+#define MSG_MAX_SIZE 256
+#define FIPS_ENABLED_PATH "/proc/sys/crypto/fips_enabled"
+
+typedef int (SECMOD_GET_SYSTEM_FIPS_ENABLED_TYPE)(void);
+
+static SECMOD_GET_SYSTEM_FIPS_ENABLED_TYPE *getSystemFIPSEnabled;
+static jmethodID debugPrintlnMethodID = NULL;
+static jobject debugObj = NULL;
+
+static void dbgPrint(JNIEnv *env, const char* msg)
+{
+ jstring jMsg;
+ if (debugObj != NULL) {
+ jMsg = (*env)->NewStringUTF(env, msg);
+ CHECK_NULL(jMsg);
+ (*env)->CallVoidMethod(env, debugObj, debugPrintlnMethodID, jMsg);
+ }
+}
+
+static void throwIOException(JNIEnv *env, const char *msg)
+{
+ jclass cls = (*env)->FindClass(env, "java/io/IOException");
+ if (cls != 0)
+ (*env)->ThrowNew(env, cls, msg);
+}
+
+static void handle_msg(JNIEnv *env, const char* msg, int msg_bytes)
+{
+ if (msg_bytes > 0 && msg_bytes < MSG_MAX_SIZE) {
+ dbgPrint(env, msg);
+ } else {
+ dbgPrint(env, "systemconf: cannot render message");
+ }
+}
+
+// Only used when NSS is not linked at build time
+#ifndef SYSCONF_NSS
+
+static void *nss_handle;
+
+static jboolean loadNSS(JNIEnv *env)
+{
+ char msg[MSG_MAX_SIZE];
+ int msg_bytes;
+ const char* errmsg;
+
+ nss_handle = dlopen(JNI_LIB_NAME("nss3"), RTLD_LAZY);
+ if (nss_handle == NULL) {
+ errmsg = dlerror();
+ msg_bytes = snprintf(msg, MSG_MAX_SIZE, "loadNSS: dlopen: %s\n",
+ errmsg);
+ handle_msg(env, msg, msg_bytes);
+ return JNI_FALSE;
+ }
+ dlerror(); /* Clear errors */
+ getSystemFIPSEnabled = (SECMOD_GET_SYSTEM_FIPS_ENABLED_TYPE*)dlsym(nss_handle, "SECMOD_GetSystemFIPSEnabled");
+ if ((errmsg = dlerror()) != NULL) {
+ msg_bytes = snprintf(msg, MSG_MAX_SIZE, "loadNSS: dlsym: %s\n",
+ errmsg);
+ handle_msg(env, msg, msg_bytes);
+ return JNI_FALSE;
+ }
+ return JNI_TRUE;
+}
+
+static void closeNSS(JNIEnv *env)
+{
+ char msg[MSG_MAX_SIZE];
+ int msg_bytes;
+ const char* errmsg;
+
+ if (dlclose(nss_handle) != 0) {
+ errmsg = dlerror();
+ msg_bytes = snprintf(msg, MSG_MAX_SIZE, "closeNSS: dlclose: %s\n",
+ errmsg);
+ handle_msg(env, msg, msg_bytes);
+ }
+}
+
+#endif
+
+/*
+ * Class: java_security_SystemConfigurator
+ * Method: JNI_OnLoad
+ */
+JNIEXPORT jint JNICALL DEF_JNI_OnLoad(JavaVM *vm, void *reserved)
+{
+ JNIEnv *env;
+ jclass sysConfCls, debugCls;
+ jfieldID sdebugFld;
+
+ if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_2) != JNI_OK) {
+ return JNI_EVERSION; /* JNI version not supported */
+ }
+
+ sysConfCls = (*env)->FindClass(env,"java/security/SystemConfigurator");
+ if (sysConfCls == NULL) {
+ printf("libsystemconf: SystemConfigurator class not found\n");
+ return JNI_ERR;
+ }
+ sdebugFld = (*env)->GetStaticFieldID(env, sysConfCls,
+ "sdebug", "Lsun/security/util/Debug;");
+ if (sdebugFld == NULL) {
+ printf("libsystemconf: SystemConfigurator::sdebug field not found\n");
+ return JNI_ERR;
+ }
+ debugObj = (*env)->GetStaticObjectField(env, sysConfCls, sdebugFld);
+ if (debugObj != NULL) {
+ debugCls = (*env)->FindClass(env,"sun/security/util/Debug");
+ if (debugCls == NULL) {
+ printf("libsystemconf: Debug class not found\n");
+ return JNI_ERR;
+ }
+ debugPrintlnMethodID = (*env)->GetMethodID(env, debugCls,
+ "println", "(Ljava/lang/String;)V");
+ if (debugPrintlnMethodID == NULL) {
+ printf("libsystemconf: Debug::println(String) method not found\n");
+ return JNI_ERR;
+ }
+ debugObj = (*env)->NewGlobalRef(env, debugObj);
+ }
+
+#ifdef SYSCONF_NSS
+ getSystemFIPSEnabled = *SECMOD_GetSystemFIPSEnabled;
+#else
+ if (loadNSS(env) == JNI_FALSE) {
+ dbgPrint(env, "libsystemconf: Failed to load NSS library.");
+ }
+#endif
+
+ return (*env)->GetVersion(env);
+}
+
+/*
+ * Class: java_security_SystemConfigurator
+ * Method: JNI_OnUnload
+ */
+JNIEXPORT void JNICALL DEF_JNI_OnUnload(JavaVM *vm, void *reserved)
+{
+ JNIEnv *env;
+
+ if (debugObj != NULL) {
+ if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_2) != JNI_OK) {
+ return; /* Should not happen */
+ }
+#ifndef SYSCONF_NSS
+ closeNSS(env);
+#endif
+ (*env)->DeleteGlobalRef(env, debugObj);
+ }
+}
+
+JNIEXPORT jboolean JNICALL Java_java_security_SystemConfigurator_getSystemFIPSEnabled
+ (JNIEnv *env, jclass cls)
+{
+ int fips_enabled;
+ char msg[MSG_MAX_SIZE];
+ int msg_bytes;
+
+ if (getSystemFIPSEnabled != NULL) {
+ dbgPrint(env, "getSystemFIPSEnabled: calling SECMOD_GetSystemFIPSEnabled");
+ fips_enabled = (*getSystemFIPSEnabled)();
+ msg_bytes = snprintf(msg, MSG_MAX_SIZE, "getSystemFIPSEnabled:" \
+ " SECMOD_GetSystemFIPSEnabled returned 0x%x", fips_enabled);
+ handle_msg(env, msg, msg_bytes);
+ return (fips_enabled == 1 ? JNI_TRUE : JNI_FALSE);
+ } else {
+ FILE *fe;
+
+ dbgPrint(env, "getSystemFIPSEnabled: reading " FIPS_ENABLED_PATH);
+ if ((fe = fopen(FIPS_ENABLED_PATH, "r")) == NULL) {
+ throwIOException(env, "Cannot open " FIPS_ENABLED_PATH);
+ return JNI_FALSE;
+ }
+ fips_enabled = fgetc(fe);
+ fclose(fe);
+ if (fips_enabled == EOF) {
+ throwIOException(env, "Cannot read " FIPS_ENABLED_PATH);
+ return JNI_FALSE;
+ }
+ msg_bytes = snprintf(msg, MSG_MAX_SIZE, "getSystemFIPSEnabled:" \
+ " read character is '%c'", fips_enabled);
+ handle_msg(env, msg, msg_bytes);
+ return (fips_enabled == '1' ? JNI_TRUE : JNI_FALSE);
+ }
+}
+
+#else // !LINUX
+
+JNIEXPORT jboolean JNICALL Java_java_security_SystemConfigurator_getSystemFIPSEnabled
+ (JNIEnv *env, jclass cls)
+{
+ return JNI_FALSE;
+}
+
+#endif
diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/FIPSKeyImporter.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/FIPSKeyImporter.java
new file mode 100644
index 00000000000..d3f0bffb821
--- /dev/null
+++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/FIPSKeyImporter.java
@@ -0,0 +1,457 @@
+/*
+ * Copyright (c) 2021, Red Hat, Inc.
+ * 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 sun.security.pkcs11;
+
+import java.math.BigInteger;
+import java.security.KeyFactory;
+import java.security.Provider;
+import java.security.Security;
+import java.security.interfaces.RSAPrivateCrtKey;
+import java.security.interfaces.RSAPrivateKey;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.locks.ReentrantLock;
+
+import javax.crypto.Cipher;
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.SecretKeySpec;
+import javax.crypto.spec.IvParameterSpec;
+
+import sun.security.jca.JCAUtil;
+import sun.security.pkcs11.TemplateManager;
+import sun.security.pkcs11.wrapper.CK_ATTRIBUTE;
+import sun.security.pkcs11.wrapper.CK_MECHANISM;
+import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
+import static sun.security.pkcs11.wrapper.PKCS11Exception.*;
+import sun.security.pkcs11.wrapper.PKCS11Exception;
+import sun.security.rsa.RSAPrivateCrtKeyImpl;
+import sun.security.rsa.RSAUtil;
+import sun.security.rsa.RSAUtil.KeyType;
+import sun.security.util.Debug;
+import sun.security.util.ECUtil;
+
+final class FIPSKeyImporter {
+
+ private static final Debug debug =
+ Debug.getInstance("sunpkcs11");
+
+ private static volatile P11Key importerKey = null;
+ private static SecretKeySpec exporterKey = null;
+ private static volatile P11Key exporterKeyP11 = null;
+ private static final ReentrantLock importerKeyLock = new ReentrantLock();
+ // Do not take the exporterKeyLock with the importerKeyLock held.
+ private static final ReentrantLock exporterKeyLock = new ReentrantLock();
+ private static volatile CK_MECHANISM importerKeyMechanism = null;
+ private static volatile CK_MECHANISM exporterKeyMechanism = null;
+ private static Cipher importerCipher = null;
+ private static Cipher exporterCipher = null;
+
+ private static volatile Provider sunECProvider = null;
+ private static final ReentrantLock sunECProviderLock = new ReentrantLock();
+
+ static Long importKey(SunPKCS11 sunPKCS11, long hSession, CK_ATTRIBUTE[] attributes)
+ throws PKCS11Exception {
+ long keyID = -1;
+ Token token = sunPKCS11.getToken();
+ if (debug != null) {
+ debug.println("Private or Secret key will be imported in" +
+ " system FIPS mode.");
+ }
+ if (importerKey == null) {
+ importerKeyLock.lock();
+ try {
+ if (importerKey == null) {
+ if (importerKeyMechanism == null) {
+ // Importer Key creation has not been tried yet. Try it.
+ createImporterKey(token);
+ }
+ if (importerKey == null || importerCipher == null) {
+ if (debug != null) {
+ debug.println("Importer Key could not be" +
+ " generated.");
+ }
+ throw new PKCS11Exception(CKR_GENERAL_ERROR,
+ " fips key importer");
+ }
+ if (debug != null) {
+ debug.println("Importer Key successfully" +
+ " generated.");
+ }
+ }
+ } finally {
+ importerKeyLock.unlock();
+ }
+ }
+ long importerKeyID = importerKey.getKeyID();
+ try {
+ byte[] keyBytes = null;
+ byte[] encKeyBytes = null;
+ long keyClass = 0L;
+ long keyType = 0L;
+ Map<Long, CK_ATTRIBUTE> attrsMap = new HashMap<>();
+ for (CK_ATTRIBUTE attr : attributes) {
+ if (attr.type == CKA_CLASS) {
+ keyClass = attr.getLong();
+ } else if (attr.type == CKA_KEY_TYPE) {
+ keyType = attr.getLong();
+ }
+ attrsMap.put(attr.type, attr);
+ }
+ BigInteger v = null;
+ if (keyClass == CKO_PRIVATE_KEY) {
+ if (keyType == CKK_RSA) {
+ if (debug != null) {
+ debug.println("Importing an RSA private key...");
+ }
+ keyBytes = sun.security.rsa.RSAPrivateCrtKeyImpl.newKey(
+ KeyType.RSA,
+ null,
+ ((v = attrsMap.get(CKA_MODULUS).getBigInteger()) != null)
+ ? v : BigInteger.ZERO,
+ ((v = attrsMap.get(CKA_PUBLIC_EXPONENT).getBigInteger()) != null)
+ ? v : BigInteger.ZERO,
+ ((v = attrsMap.get(CKA_PRIVATE_EXPONENT).getBigInteger()) != null)
+ ? v : BigInteger.ZERO,
+ ((v = attrsMap.get(CKA_PRIME_1).getBigInteger()) != null)
+ ? v : BigInteger.ZERO,
+ ((v = attrsMap.get(CKA_PRIME_2).getBigInteger()) != null)
+ ? v : BigInteger.ZERO,
+ ((v = attrsMap.get(CKA_EXPONENT_1).getBigInteger()) != null)
+ ? v : BigInteger.ZERO,
+ ((v = attrsMap.get(CKA_EXPONENT_2).getBigInteger()) != null)
+ ? v : BigInteger.ZERO,
+ ((v = attrsMap.get(CKA_COEFFICIENT).getBigInteger()) != null)
+ ? v : BigInteger.ZERO
+ ).getEncoded();
+ } else if (keyType == CKK_DSA) {
+ if (debug != null) {
+ debug.println("Importing a DSA private key...");
+ }
+ keyBytes = new sun.security.provider.DSAPrivateKey(
+ ((v = attrsMap.get(CKA_VALUE).getBigInteger()) != null)
+ ? v : BigInteger.ZERO,
+ ((v = attrsMap.get(CKA_PRIME).getBigInteger()) != null)
+ ? v : BigInteger.ZERO,
+ ((v = attrsMap.get(CKA_SUBPRIME).getBigInteger()) != null)
+ ? v : BigInteger.ZERO,
+ ((v = attrsMap.get(CKA_BASE).getBigInteger()) != null)
+ ? v : BigInteger.ZERO
+ ).getEncoded();
+ if (token.config.getNssNetscapeDbWorkaround() &&
+ attrsMap.get(CKA_NETSCAPE_DB) == null) {
+ attrsMap.put(CKA_NETSCAPE_DB,
+ new CK_ATTRIBUTE(CKA_NETSCAPE_DB, BigInteger.ZERO));
+ }
+ } else if (keyType == CKK_EC) {
+ if (debug != null) {
+ debug.println("Importing an EC private key...");
+ }
+ if (sunECProvider == null) {
+ sunECProviderLock.lock();
+ try {
+ if (sunECProvider == null) {
+ sunECProvider = Security.getProvider("SunEC");
+ }
+ } finally {
+ sunECProviderLock.unlock();
+ }
+ }
+ keyBytes = ECUtil.generateECPrivateKey(
+ ((v = attrsMap.get(CKA_VALUE).getBigInteger()) != null)
+ ? v : BigInteger.ZERO,
+ ECUtil.getECParameterSpec(sunECProvider,
+ attrsMap.get(CKA_EC_PARAMS).getByteArray()))
+ .getEncoded();
+ if (token.config.getNssNetscapeDbWorkaround() &&
+ attrsMap.get(CKA_NETSCAPE_DB) == null) {
+ attrsMap.put(CKA_NETSCAPE_DB,
+ new CK_ATTRIBUTE(CKA_NETSCAPE_DB, BigInteger.ZERO));
+ }
+ } else {
+ if (debug != null) {
+ debug.println("Unrecognized private key type.");
+ }
+ throw new PKCS11Exception(CKR_GENERAL_ERROR,
+ " fips key importer");
+ }
+ } else if (keyClass == CKO_SECRET_KEY) {
+ if (debug != null) {
+ debug.println("Importing a secret key...");
+ }
+ keyBytes = attrsMap.get(CKA_VALUE).getByteArray();
+ }
+ if (keyBytes == null || keyBytes.length == 0) {
+ if (debug != null) {
+ debug.println("Private or secret key plain bytes could" +
+ " not be obtained. Import failed.");
+ }
+ throw new PKCS11Exception(CKR_GENERAL_ERROR,
+ " fips key importer");
+ }
+ attributes = new CK_ATTRIBUTE[attrsMap.size()];
+ attrsMap.values().toArray(attributes);
+ importerKeyLock.lock();
+ try {
+ // No need to reset the cipher object because no multi-part
+ // operations are performed.
+ encKeyBytes = importerCipher.doFinal(keyBytes);
+ } finally {
+ importerKeyLock.unlock();
+ }
+ attributes = token.getAttributes(TemplateManager.O_IMPORT,
+ keyClass, keyType, attributes);
+ keyID = token.p11.C_UnwrapKey(hSession,
+ importerKeyMechanism, importerKeyID, encKeyBytes, attributes);
+ if (debug != null) {
+ debug.println("Imported key ID: " + keyID);
+ }
+ } catch (Throwable t) {
+ if (t instanceof PKCS11Exception) {
+ throw (PKCS11Exception)t;
+ }
+ throw new PKCS11Exception(CKR_GENERAL_ERROR,
+ t.getMessage());
+ } finally {
+ importerKey.releaseKeyID();
+ }
+ return Long.valueOf(keyID);
+ }
+
+ static void exportKey(SunPKCS11 sunPKCS11, long hSession, long hObject,
+ long keyClass, long keyType, Map<Long, CK_ATTRIBUTE> sensitiveAttrs)
+ throws PKCS11Exception {
+ Token token = sunPKCS11.getToken();
+ if (debug != null) {
+ debug.println("Private or Secret key will be exported in" +
+ " system FIPS mode.");
+ }
+ if (exporterKeyP11 == null) {
+ try {
+ exporterKeyLock.lock();
+ if (exporterKeyP11 == null) {
+ if (exporterKeyMechanism == null) {
+ // Exporter Key creation has not been tried yet. Try it.
+ createExporterKey(token);
+ }
+ if (exporterKeyP11 == null || exporterCipher == null) {
+ if (debug != null) {
+ debug.println("Exporter Key could not be" +
+ " generated.");
+ }
+ throw new PKCS11Exception(CKR_GENERAL_ERROR,
+ " fips key exporter");
+ }
+ if (debug != null) {
+ debug.println("Exporter Key successfully" +
+ " generated.");
+ }
+ }
+ } finally {
+ exporterKeyLock.unlock();
+ }
+ }
+ long exporterKeyID = exporterKeyP11.getKeyID();
+ try {
+ byte[] wrappedKeyBytes = token.p11.C_WrapKey(hSession,
+ exporterKeyMechanism, exporterKeyID, hObject);
+ byte[] plainExportedKey = null;
+ exporterKeyLock.lock();
+ try {
+ // No need to reset the cipher object because no multi-part
+ // operations are performed.
+ plainExportedKey = exporterCipher.doFinal(wrappedKeyBytes);
+ } finally {
+ exporterKeyLock.unlock();
+ }
+ if (keyClass == CKO_PRIVATE_KEY) {
+ exportPrivateKey(sensitiveAttrs, keyType, plainExportedKey);
+ } else if (keyClass == CKO_SECRET_KEY) {
+ checkAttrs(sensitiveAttrs, "CKO_SECRET_KEY", CKA_VALUE);
+ // CKA_VALUE is guaranteed to be present, since sensitiveAttrs'
+ // size is greater than 0 and no invalid attributes exist
+ sensitiveAttrs.get(CKA_VALUE).pValue = plainExportedKey;
+ } else {
+ throw new PKCS11Exception(CKR_GENERAL_ERROR,
+ " fips key exporter");
+ }
+ } catch (Throwable t) {
+ if (t instanceof PKCS11Exception) {
+ throw (PKCS11Exception)t;
+ }
+ throw new PKCS11Exception(CKR_GENERAL_ERROR,
+ t.getMessage());
+ } finally {
+ exporterKeyP11.releaseKeyID();
+ }
+ }
+
+ private static void exportPrivateKey(
+ Map<Long, CK_ATTRIBUTE> sensitiveAttrs, long keyType,
+ byte[] plainExportedKey) throws Throwable {
+ if (keyType == CKK_RSA) {
+ checkAttrs(sensitiveAttrs, "CKO_PRIVATE_KEY CKK_RSA",
+ CKA_PRIVATE_EXPONENT, CKA_PRIME_1, CKA_PRIME_2,
+ CKA_EXPONENT_1, CKA_EXPONENT_2, CKA_COEFFICIENT);
+ RSAPrivateKey rsaPKey = RSAPrivateCrtKeyImpl.newKey(
+ RSAUtil.KeyType.RSA, "PKCS#8", plainExportedKey);
+ CK_ATTRIBUTE attr;
+ if ((attr = sensitiveAttrs.get(CKA_PRIVATE_EXPONENT)) != null) {
+ attr.pValue = rsaPKey.getPrivateExponent().toByteArray();
+ }
+ if (rsaPKey instanceof RSAPrivateCrtKey) {
+ RSAPrivateCrtKey rsaPCrtKey = (RSAPrivateCrtKey) rsaPKey;
+ if ((attr = sensitiveAttrs.get(CKA_PRIME_1)) != null) {
+ attr.pValue = rsaPCrtKey.getPrimeP().toByteArray();
+ }
+ if ((attr = sensitiveAttrs.get(CKA_PRIME_2)) != null) {
+ attr.pValue = rsaPCrtKey.getPrimeQ().toByteArray();
+ }
+ if ((attr = sensitiveAttrs.get(CKA_EXPONENT_1)) != null) {
+ attr.pValue = rsaPCrtKey.getPrimeExponentP().toByteArray();
+ }
+ if ((attr = sensitiveAttrs.get(CKA_EXPONENT_2)) != null) {
+ attr.pValue = rsaPCrtKey.getPrimeExponentQ().toByteArray();
+ }
+ if ((attr = sensitiveAttrs.get(CKA_COEFFICIENT)) != null) {
+ attr.pValue = rsaPCrtKey.getCrtCoefficient().toByteArray();
+ }
+ } else {
+ checkAttrs(sensitiveAttrs, "CKO_PRIVATE_KEY CKK_RSA",
+ CKA_PRIVATE_EXPONENT);
+ }
+ } else if (keyType == CKK_DSA) {
+ checkAttrs(sensitiveAttrs, "CKO_PRIVATE_KEY CKK_DSA", CKA_VALUE);
+ // CKA_VALUE is guaranteed to be present, since sensitiveAttrs'
+ // size is greater than 0 and no invalid attributes exist
+ sensitiveAttrs.get(CKA_VALUE).pValue =
+ new sun.security.provider.DSAPrivateKey(plainExportedKey)
+ .getX().toByteArray();
+ } else if (keyType == CKK_EC) {
+ checkAttrs(sensitiveAttrs, "CKO_PRIVATE_KEY CKK_EC", CKA_VALUE);
+ // CKA_VALUE is guaranteed to be present, since sensitiveAttrs'
+ // size is greater than 0 and no invalid attributes exist
+ sensitiveAttrs.get(CKA_VALUE).pValue =
+ ECUtil.decodePKCS8ECPrivateKey(plainExportedKey)
+ .getS().toByteArray();
+ } else {
+ throw new PKCS11Exception(CKR_GENERAL_ERROR,
+ " unsupported CKO_PRIVATE_KEY key type: " + keyType);
+ }
+ }
+
+ private static void checkAttrs(Map<Long, CK_ATTRIBUTE> sensitiveAttrs,
+ String keyName, long... validAttrs)
+ throws PKCS11Exception {
+ int sensitiveAttrsCount = sensitiveAttrs.size();
+ if (sensitiveAttrsCount <= validAttrs.length) {
+ int validAttrsCount = 0;
+ for (long validAttr : validAttrs) {
+ if (sensitiveAttrs.containsKey(validAttr)) validAttrsCount++;
+ }
+ if (validAttrsCount == sensitiveAttrsCount) return;
+ }
+ throw new PKCS11Exception(CKR_GENERAL_ERROR,
+ " invalid attribute types for a " + keyName + " key object");
+ }
+
+ private static void createImporterKey(Token token) {
+ if (debug != null) {
+ debug.println("Generating Importer Key...");
+ }
+ byte[] iv = new byte[16];
+ JCAUtil.getSecureRandom().nextBytes(iv);
+ importerKeyMechanism = new CK_MECHANISM(CKM_AES_CBC_PAD, iv);
+ try {
+ CK_ATTRIBUTE[] attributes = token.getAttributes(TemplateManager.O_GENERATE,
+ CKO_SECRET_KEY, CKK_AES, new CK_ATTRIBUTE[] {
+ new CK_ATTRIBUTE(CKA_CLASS, CKO_SECRET_KEY),
+ new CK_ATTRIBUTE(CKA_VALUE_LEN, 256 >> 3)});
+ Session s = null;
+ try {
+ s = token.getObjSession();
+ long keyID = token.p11.C_GenerateKey(
+ s.id(), new CK_MECHANISM(CKM_AES_KEY_GEN),
+ attributes);
+ if (debug != null) {
+ debug.println("Importer Key ID: " + keyID);
+ }
+ importerKey = (P11Key)P11Key.secretKey(s, keyID, "AES",
+ 256 >> 3, null);
+ } catch (PKCS11Exception e) {
+ // best effort
+ } finally {
+ token.releaseSession(s);
+ }
+ if (importerKey != null) {
+ importerCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
+ importerCipher.init(Cipher.ENCRYPT_MODE, importerKey,
+ new IvParameterSpec(
+ (byte[])importerKeyMechanism.pParameter), null);
+ }
+ } catch (Throwable t) {
+ // best effort
+ importerKey = null;
+ importerCipher = null;
+ // importerKeyMechanism value is kept initialized to indicate that
+ // Importer Key creation has been tried and failed.
+ if (debug != null) {
+ debug.println("Error generating the Importer Key");
+ }
+ }
+ }
+
+ private static void createExporterKey(Token token) {
+ if (debug != null) {
+ debug.println("Generating Exporter Key...");
+ }
+ byte[] iv = new byte[16];
+ JCAUtil.getSecureRandom().nextBytes(iv);
+ exporterKeyMechanism = new CK_MECHANISM(CKM_AES_CBC_PAD, iv);
+ byte[] exporterKeyRaw = new byte[32];
+ JCAUtil.getSecureRandom().nextBytes(exporterKeyRaw);
+ exporterKey = new SecretKeySpec(exporterKeyRaw, "AES");
+ try {
+ SecretKeyFactory skf = SecretKeyFactory.getInstance("AES");
+ exporterKeyP11 = (P11Key)(skf.translateKey(exporterKey));
+ if (exporterKeyP11 != null) {
+ exporterCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
+ exporterCipher.init(Cipher.DECRYPT_MODE, exporterKey,
+ new IvParameterSpec(
+ (byte[])exporterKeyMechanism.pParameter), null);
+ }
+ } catch (Throwable t) {
+ // best effort
+ exporterKey = null;
+ exporterKeyP11 = null;
+ exporterCipher = null;
+ // exporterKeyMechanism value is kept initialized to indicate that
+ // Exporter Key creation has been tried and failed.
+ if (debug != null) {
+ debug.println("Error generating the Exporter Key");
+ }
+ }
+ }
+}
diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/FIPSTokenLoginHandler.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/FIPSTokenLoginHandler.java
new file mode 100644
index 00000000000..f8d505ca815
--- /dev/null
+++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/FIPSTokenLoginHandler.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2022, Red Hat, Inc.
+ * 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 sun.security.pkcs11;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardOpenOption;
+import java.security.ProviderException;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
+import sun.security.util.Debug;
+import sun.security.util.SecurityProperties;
+
+final class FIPSTokenLoginHandler implements CallbackHandler {
+
+ private static final String FIPS_NSSDB_PIN_PROP = "fips.nssdb.pin";
+
+ private static final Debug debug = Debug.getInstance("sunpkcs11");
+
+ public void handle(Callback[] callbacks)
+ throws IOException, UnsupportedCallbackException {
+ if (!(callbacks[0] instanceof PasswordCallback)) {
+ throw new UnsupportedCallbackException(callbacks[0]);
+ }
+ PasswordCallback pc = (PasswordCallback)callbacks[0];
+ pc.setPassword(getFipsNssdbPin());
+ }
+
+ private static char[] getFipsNssdbPin() throws ProviderException {
+ if (debug != null) {
+ debug.println("FIPS: Reading NSS DB PIN for token...");
+ }
+ String pinProp = SecurityProperties
+ .privilegedGetOverridable(FIPS_NSSDB_PIN_PROP);
+ if (pinProp != null && !pinProp.isEmpty()) {
+ String[] pinPropParts = pinProp.split(":", 2);
+ if (pinPropParts.length < 2) {
+ throw new ProviderException("Invalid " + FIPS_NSSDB_PIN_PROP +
+ " property value.");
+ }
+ String prefix = pinPropParts[0].toLowerCase();
+ String value = pinPropParts[1];
+ String pin = null;
+ if (prefix.equals("env")) {
+ if (debug != null) {
+ debug.println("FIPS: PIN value from the '" + value +
+ "' environment variable.");
+ }
+ pin = System.getenv(value);
+ } else if (prefix.equals("file")) {
+ if (debug != null) {
+ debug.println("FIPS: PIN value from the '" + value +
+ "' file.");
+ }
+ pin = getPinFromFile(Paths.get(value));
+ } else if (prefix.equals("pin")) {
+ if (debug != null) {
+ debug.println("FIPS: PIN value from the " +
+ FIPS_NSSDB_PIN_PROP + " property.");
+ }
+ pin = value;
+ } else {
+ throw new ProviderException("Unsupported prefix for " +
+ FIPS_NSSDB_PIN_PROP + ".");
+ }
+ if (pin != null && !pin.isEmpty()) {
+ if (debug != null) {
+ debug.println("FIPS: non-empty PIN.");
+ }
+ /*
+ * C_Login in libj2pkcs11 receives the PIN in a char[] and
+ * discards the upper byte of each char, before passing
+ * the value to the NSS Software Token. However, the
+ * NSS Software Token accepts any UTF-8 PIN value. Thus,
+ * expand the PIN here to account for later truncation.
+ */
+ byte[] pinUtf8 = pin.getBytes(StandardCharsets.UTF_8);
+ char[] pinChar = new char[pinUtf8.length];
+ for (int i = 0; i < pinChar.length; i++) {
+ pinChar[i] = (char)(pinUtf8[i] & 0xFF);
+ }
+ return pinChar;
+ }
+ }
+ if (debug != null) {
+ debug.println("FIPS: empty PIN.");
+ }
+ return null;
+ }
+
+ /*
+ * This method extracts the token PIN from the first line of a password
+ * file in the same way as NSS modutil. See for example the -newpwfile
+ * argument used to change the password for an NSS DB.
+ */
+ private static String getPinFromFile(Path f) throws ProviderException {
+ try (InputStream is =
+ Files.newInputStream(f, StandardOpenOption.READ)) {
+ /*
+ * SECU_FilePasswd in NSS (nss/cmd/lib/secutil.c), used by modutil,
+ * reads up to 4096 bytes. In addition, the NSS Software Token
+ * does not accept PINs longer than 500 bytes (see SFTK_MAX_PIN
+ * in nss/lib/softoken/pkcs11i.h).
+ */
+ BufferedReader in =
+ new BufferedReader(new InputStreamReader(
+ new ByteArrayInputStream(is.readNBytes(4096)),
+ StandardCharsets.UTF_8));
+ return in.readLine();
+ } catch (IOException ioe) {
+ throw new ProviderException("Error reading " + FIPS_NSSDB_PIN_PROP +
+ " from the '" + f + "' file.", ioe);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Key.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Key.java
index 9b69072280e..5696b904979 100644
--- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Key.java
+++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Key.java
@@ -37,6 +37,8 @@ import javax.crypto.*;
import javax.crypto.interfaces.*;
import javax.crypto.spec.*;
+import jdk.internal.access.SharedSecrets;
+
import sun.security.rsa.RSAUtil.KeyType;
import sun.security.rsa.RSAPublicKeyImpl;
import sun.security.rsa.RSAPrivateCrtKeyImpl;
@@ -69,6 +71,9 @@ import sun.security.jca.JCAUtil;
*/
abstract class P11Key implements Key, Length {
+ private static final boolean plainKeySupportEnabled = SharedSecrets
+ .getJavaSecuritySystemConfiguratorAccess().isPlainKeySupportEnabled();
+
private static final long serialVersionUID = -2575874101938349339L;
private static final String PUBLIC = "public";
@@ -136,9 +141,7 @@ abstract class P11Key implements Key, Length {
this.tokenObject = tokenObject;
this.sensitive = sensitive;
this.extractable = extractable;
- char[] tokenLabel = this.token.tokenInfo.label;
- boolean isNSS = (tokenLabel[0] == 'N' && tokenLabel[1] == 'S'
- && tokenLabel[2] == 'S');
+ boolean isNSS = P11Util.isNSS(this.token);
boolean extractKeyInfo = (!DISABLE_NATIVE_KEYS_EXTRACTION && isNSS &&
extractable && !tokenObject);
this.keyIDHolder = new NativeKeyHolder(this, keyID, session,
@@ -379,7 +382,9 @@ abstract class P11Key implements Key, Length {
new CK_ATTRIBUTE(CKA_SENSITIVE),
new CK_ATTRIBUTE(CKA_EXTRACTABLE),
});
- if (attributes[1].getBoolean() || (attributes[2].getBoolean() == false)) {
+ boolean exportable = plainKeySupportEnabled && !algorithm.equals("DH");
+ if (!exportable && (attributes[1].getBoolean() ||
+ (attributes[2].getBoolean() == false))) {
return new P11PrivateKey
(session, keyID, algorithm, keyLength, attributes);
} else {
@@ -461,7 +466,8 @@ abstract class P11Key implements Key, Length {
}
public String getFormat() {
token.ensureValid();
- if (sensitive || (extractable == false)) {
+ if (!plainKeySupportEnabled &&
+ (sensitive || (extractable == false))) {
return null;
} else {
return "RAW";
diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Mac.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Mac.java
index ba0b7faf3f8..4840a116b34 100644
--- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Mac.java
+++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Mac.java
@@ -29,14 +29,17 @@ import java.nio.ByteBuffer;
import java.security.*;
import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.InvalidKeySpecException;
import javax.crypto.MacSpi;
+import javax.crypto.spec.PBEKeySpec;
import sun.nio.ch.DirectBuffer;
import sun.security.pkcs11.wrapper.*;
import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
import static sun.security.pkcs11.wrapper.PKCS11Exception.*;
+import sun.security.util.PBEUtil;
/**
* MAC implementation class. This class currently supports HMAC using
@@ -202,12 +205,23 @@ final class P11Mac extends MacSpi {
// see JCE spec
protected void engineInit(Key key, AlgorithmParameterSpec params)
throws InvalidKeyException, InvalidAlgorithmParameterException {
- if (params != null) {
- throw new InvalidAlgorithmParameterException
- ("Parameters not supported");
+ if (algorithm.startsWith("HmacPBE")) {
+ PBEKeySpec pbeSpec = PBEUtil.getPBAKeySpec(key, params);
+ reset(true);
+ try {
+ p11Key = P11SecretKeyFactory.derivePBEKey(
+ token, pbeSpec, algorithm);
+ } catch (InvalidKeySpecException e) {
+ throw new InvalidKeyException(e);
+ }
+ } else {
+ if (params != null) {
+ throw new InvalidAlgorithmParameterException
+ ("Parameters not supported");
+ }
+ reset(true);
+ p11Key = P11SecretKeyFactory.convertKey(token, key, algorithm);
}
- reset(true);
- p11Key = P11SecretKeyFactory.convertKey(token, key, algorithm);
try {
initialize();
} catch (PKCS11Exception e) {
diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11PBECipher.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11PBECipher.java
new file mode 100644
index 00000000000..ae4262703e6
--- /dev/null
+++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11PBECipher.java
@@ -0,0 +1,200 @@
+/*
+ * Copyright (c) 2022, Red Hat, Inc.
+ * 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 sun.security.pkcs11;
+
+import java.security.AlgorithmParameters;
+import java.security.Key;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.InvalidKeySpecException;
+import javax.crypto.BadPaddingException;
+import javax.crypto.CipherSpi;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.ShortBufferException;
+import javax.crypto.spec.PBEKeySpec;
+
+import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
+import sun.security.jca.JCAUtil;
+import sun.security.pkcs11.wrapper.PKCS11Exception;
+import sun.security.util.PBEUtil;
+
+final class P11PBECipher extends CipherSpi {
+
+ private static final int DEFAULT_SALT_LENGTH = 20;
+ private static final int DEFAULT_COUNT = 4096;
+
+ private final Token token;
+ private final String pbeAlg;
+ private final P11Cipher cipher;
+ private final int blkSize;
+ private final int keyLen;
+ private final PBEUtil.PBES2Helper pbes2Helper = new PBEUtil.PBES2Helper(
+ DEFAULT_SALT_LENGTH, DEFAULT_COUNT);
+
+ P11PBECipher(Token token, String pbeAlg, long cipherMech)
+ throws PKCS11Exception, NoSuchAlgorithmException {
+ super();
+ String cipherTrans;
+ if (cipherMech == CKM_AES_CBC_PAD || cipherMech == CKM_AES_CBC) {
+ cipherTrans = "AES/CBC/PKCS5Padding";
+ } else {
+ throw new NoSuchAlgorithmException(
+ "Cipher transformation not supported.");
+ }
+ cipher = new P11Cipher(token, cipherTrans, cipherMech);
+ blkSize = cipher.engineGetBlockSize();
+ assert P11Util.kdfDataMap.get(pbeAlg) != null;
+ keyLen = P11Util.kdfDataMap.get(pbeAlg).keyLen;
+ this.pbeAlg = pbeAlg;
+ this.token = token;
+ }
+
+ // see JCE spec
+ @Override
+ protected void engineSetMode(String mode)
+ throws NoSuchAlgorithmException {
+ cipher.engineSetMode(mode);
+ }
+
+ // see JCE spec
+ @Override
+ protected void engineSetPadding(String padding)
+ throws NoSuchPaddingException {
+ cipher.engineSetPadding(padding);
+ }
+
+ // see JCE spec
+ @Override
+ protected int engineGetBlockSize() {
+ return cipher.engineGetBlockSize();
+ }
+
+ // see JCE spec
+ @Override
+ protected int engineGetOutputSize(int inputLen) {
+ return cipher.engineGetOutputSize(inputLen);
+ }
+
+ // see JCE spec
+ @Override
+ protected byte[] engineGetIV() {
+ return cipher.engineGetIV();
+ }
+
+ // see JCE spec
+ @Override
+ protected AlgorithmParameters engineGetParameters() {
+ return pbes2Helper.getAlgorithmParameters(
+ blkSize, pbeAlg, null, JCAUtil.getSecureRandom());
+ }
+
+ // see JCE spec
+ @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("requires PBE parameters", e);
+ }
+ }
+
+ // see JCE spec
+ @Override
+ protected void engineInit(int opmode, Key key,
+ AlgorithmParameterSpec params, SecureRandom random)
+ throws InvalidKeyException,
+ InvalidAlgorithmParameterException {
+
+ PBEKeySpec pbeSpec = pbes2Helper.getPBEKeySpec(blkSize, keyLen,
+ opmode, key, params, random);
+
+ Key derivedKey;
+ try {
+ derivedKey = P11SecretKeyFactory.derivePBEKey(
+ token, pbeSpec, pbeAlg);
+ } catch (InvalidKeySpecException e) {
+ throw new InvalidKeyException(e);
+ }
+ cipher.engineInit(opmode, derivedKey, pbes2Helper.getIvSpec(), random);
+ }
+
+ // see JCE spec
+ @Override
+ protected void engineInit(int opmode, Key key,
+ AlgorithmParameters params, SecureRandom random)
+ throws InvalidKeyException,
+ InvalidAlgorithmParameterException {
+ engineInit(opmode, key, PBEUtil.PBES2Helper.getParameterSpec(params),
+ random);
+ }
+
+ // see JCE spec
+ @Override
+ protected byte[] engineUpdate(byte[] input, int inputOffset,
+ int inputLen) {
+ return cipher.engineUpdate(input, inputOffset, inputLen);
+ }
+
+ // see JCE spec
+ @Override
+ protected int engineUpdate(byte[] input, int inputOffset,
+ int inputLen, byte[] output, int outputOffset)
+ throws ShortBufferException {
+ return cipher.engineUpdate(input, inputOffset, inputLen,
+ output, outputOffset);
+ }
+
+ // see JCE spec
+ @Override
+ protected byte[] engineDoFinal(byte[] input, int inputOffset,
+ int inputLen)
+ throws IllegalBlockSizeException, BadPaddingException {
+ return cipher.engineDoFinal(input, inputOffset, inputLen);
+ }
+
+ // see JCE spec
+ @Override
+ protected int engineDoFinal(byte[] input, int inputOffset,
+ int inputLen, byte[] output, int outputOffset)
+ throws ShortBufferException, IllegalBlockSizeException,
+ BadPaddingException {
+ return cipher.engineDoFinal(input, inputOffset, inputLen, output,
+ outputOffset);
+ }
+
+ // see JCE spec
+ @Override
+ protected int engineGetKeySize(Key key)
+ throws InvalidKeyException {
+ return cipher.engineGetKeySize(key);
+ }
+
+}
diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11SecretKeyFactory.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11SecretKeyFactory.java
index 8d1b8ccb0ae..7ea9b4c5e7f 100644
--- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11SecretKeyFactory.java
+++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11SecretKeyFactory.java
@@ -31,6 +31,7 @@ import java.security.*;
import java.security.spec.*;
import javax.crypto.*;
+import javax.crypto.interfaces.PBEKey;
import javax.crypto.spec.*;
import static sun.security.pkcs11.TemplateManager.*;
@@ -194,6 +195,130 @@ final class P11SecretKeyFactory extends SecretKeyFactorySpi {
return p11Key;
}
+ static P11Key derivePBEKey(Token token, PBEKeySpec keySpec, String algo)
+ throws InvalidKeySpecException {
+ token.ensureValid();
+ if (keySpec == null) {
+ throw new InvalidKeySpecException("PBEKeySpec must not be null");
+ }
+ Session session = null;
+ try {
+ session = token.getObjSession();
+ P11Util.KDFData kdfData = P11Util.kdfDataMap.get(algo);
+ CK_MECHANISM ckMech;
+ char[] password = keySpec.getPassword();
+ byte[] salt = keySpec.getSalt();
+ int itCount = keySpec.getIterationCount();
+ int keySize = keySpec.getKeyLength();
+ if (kdfData.keyLen != -1) {
+ if (keySize == 0) {
+ keySize = kdfData.keyLen;
+ } else if (keySize != kdfData.keyLen) {
+ throw new InvalidKeySpecException(
+ "Key length is invalid for " + algo);
+ }
+ }
+
+ if (kdfData.kdfMech == CKM_PKCS5_PBKD2) {
+ CK_INFO p11Info = token.p11.getInfo();
+ CK_VERSION p11Ver = (p11Info != null ? p11Info.cryptokiVersion
+ : null);
+ if (P11Util.isNSS(token) || p11Ver != null && (p11Ver.major <
+ 2 || p11Ver.major == 2 && p11Ver.minor < 40)) {
+ // NSS keeps using the old structure beyond PKCS #11 v2.40
+ ckMech = new CK_MECHANISM(kdfData.kdfMech,
+ new CK_PKCS5_PBKD2_PARAMS(password, salt,
+ itCount, kdfData.prfMech));
+ } else {
+ ckMech = new CK_MECHANISM(kdfData.kdfMech,
+ new CK_PKCS5_PBKD2_PARAMS2(password, salt,
+ itCount, kdfData.prfMech));
+ }
+ } else {
+ // PKCS #12 "General Method" PBKD (RFC 7292, Appendix B.2)
+ if (P11Util.isNSS(token)) {
+ // According to PKCS #11, "password" in CK_PBE_PARAMS has
+ // a CK_UTF8CHAR_PTR type. This suggests that it is encoded
+ // in UTF-8. However, NSS expects the password to be encoded
+ // as BMPString with a NULL terminator when C_GenerateKey
+ // is called for a PKCS #12 "General Method" derivation
+ // (see RFC 7292, Appendix B.1).
+ //
+ // The char size in Java is 2 bytes. When a char is
+ // converted to a CK_UTF8CHAR, the high-order byte is
+ // discarded (see jCharArrayToCKUTF8CharArray in
+ // p11_util.c). In order to have a BMPString passed to
+ // C_GenerateKey, we need to account for that and expand:
+ // the high and low parts of each char are split into 2
+ // chars. As an example, this is the transformation for
+ // a NULL terminated password "a":
+ // char[] => [ 0x0061, 0x0000 ]
+ // / \ / \
+ // Expansion => [0x0000, 0x0061, 0x0000, 0x0000]
+ // | | | |
+ // BMPString => [ 0x00, 0x61, 0x00, 0x00]
+ //
+ int inputLength = (password == null) ? 0 : password.length;
+ char[] expPassword = new char[inputLength * 2 + 2];
+ for (int i = 0, j = 0; i < inputLength; i++, j += 2) {
+ expPassword[j] = (char) ((password[i] >>> 8) & 0xFF);
+ expPassword[j + 1] = (char) (password[i] & 0xFF);
+ }
+ password = expPassword;
+ }
+ ckMech = new CK_MECHANISM(kdfData.kdfMech,
+ new CK_PBE_PARAMS(password, salt, itCount));
+ }
+
+ long keyType = getKeyType(kdfData.keyAlgo);
+ CK_ATTRIBUTE[] attrs = new CK_ATTRIBUTE[
+ switch (kdfData.op) {
+ case ENCRYPTION, AUTHENTICATION -> 4;
+ case GENERIC -> 5;
+ }];
+ attrs[0] = new CK_ATTRIBUTE(CKA_CLASS, CKO_SECRET_KEY);
+ attrs[1] = new CK_ATTRIBUTE(CKA_VALUE_LEN, keySize >> 3);
+ attrs[2] = new CK_ATTRIBUTE(CKA_KEY_TYPE, keyType);
+ switch (kdfData.op) {
+ case ENCRYPTION -> attrs[3] = CK_ATTRIBUTE.ENCRYPT_TRUE;
+ case AUTHENTICATION -> attrs[3] = CK_ATTRIBUTE.SIGN_TRUE;
+ case GENERIC -> {
+ attrs[3] = CK_ATTRIBUTE.ENCRYPT_TRUE;
+ attrs[4] = CK_ATTRIBUTE.SIGN_TRUE;
+ }
+ }
+ CK_ATTRIBUTE[] attr = token.getAttributes(
+ O_GENERATE, CKO_SECRET_KEY, keyType, attrs);
+ long keyID = token.p11.C_GenerateKey(session.id(), ckMech, attr);
+ return (P11Key)P11Key.secretKey(
+ session, keyID, kdfData.keyAlgo, keySize, attr);
+ } catch (PKCS11Exception e) {
+ throw new InvalidKeySpecException("Could not create key", e);
+ } finally {
+ token.releaseSession(session);
+ }
+ }
+
+ static P11Key derivePBEKey(Token token, PBEKey key, String algo)
+ throws InvalidKeyException {
+ token.ensureValid();
+ if (key == null) {
+ throw new InvalidKeyException("PBEKey must not be null");
+ }
+ P11Key p11Key = token.secretCache.get(key);
+ if (p11Key != null) {
+ return p11Key;
+ }
+ try {
+ p11Key = derivePBEKey(token, new PBEKeySpec(key.getPassword(),
+ key.getSalt(), key.getIterationCount()), algo);
+ } catch (InvalidKeySpecException e) {
+ throw new InvalidKeyException(e);
+ }
+ token.secretCache.put(key, p11Key);
+ return p11Key;
+ }
+
static void fixDESParity(byte[] key, int offset) {
for (int i = 0; i < 8; i++) {
int b = key[offset] & 0xfe;
@@ -320,6 +445,9 @@ final class P11SecretKeyFactory extends SecretKeyFactorySpi {
keySpec = new SecretKeySpec(keyBytes, "DESede");
return engineGenerateSecret(keySpec);
}
+ } else if (keySpec instanceof PBEKeySpec) {
+ return (SecretKey)derivePBEKey(token,
+ (PBEKeySpec)keySpec, algorithm);
}
throw new InvalidKeySpecException
("Unsupported spec: " + keySpec.getClass().getName());
@@ -373,6 +501,9 @@ final class P11SecretKeyFactory extends SecretKeyFactorySpi {
// see JCE spec
protected SecretKey engineTranslateKey(SecretKey key)
throws InvalidKeyException {
+ if (key instanceof PBEKey) {
+ return (SecretKey)derivePBEKey(token, (PBEKey)key, algorithm);
+ }
return (SecretKey)convertKey(token, key, algorithm);
}
diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Util.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Util.java
index 262cfc062ad..72b64f72c0a 100644
--- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Util.java
+++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Util.java
@@ -27,6 +27,10 @@ package sun.security.pkcs11;
import java.math.BigInteger;
import java.security.*;
+import java.util.HashMap;
+import java.util.Map;
+
+import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
/**
* Collection of static utility methods.
@@ -40,10 +44,106 @@ public final class P11Util {
private static volatile Provider sun, sunRsaSign, sunJce;
+ // Used by PBE
+ static final class KDFData {
+ public enum Operation {ENCRYPTION, AUTHENTICATION, GENERIC}
+ public long kdfMech;
+ public long prfMech;
+ public String keyAlgo;
+ public int keyLen;
+ public Operation op;
+ KDFData(long kdfMech, long prfMech, String keyAlgo,
+ int keyLen, Operation op) {
+ this.kdfMech = kdfMech;
+ this.prfMech = prfMech;
+ this.keyAlgo = keyAlgo;
+ this.keyLen = keyLen;
+ this.op = op;
+ }
+
+ public static void addPbkdf2Data(String algo, long kdfMech,
+ long prfMech) {
+ kdfDataMap.put(algo, new KDFData(kdfMech, prfMech,
+ "Generic", -1, Operation.GENERIC));
+ }
+
+ public static void addPbkdf2AesData(String algo, long kdfMech,
+ long prfMech, int keyLen) {
+ kdfDataMap.put(algo, new KDFData(kdfMech, prfMech,
+ "AES", keyLen, Operation.ENCRYPTION));
+ }
+
+ public static void addPkcs12KDData(String algo, long kdfMech,
+ int keyLen) {
+ kdfDataMap.put(algo, new KDFData(kdfMech, -1,
+ "Generic", keyLen, Operation.AUTHENTICATION));
+ }
+ }
+
+ static final Map<String, KDFData> kdfDataMap = new HashMap<>();
+
+ static {
+ KDFData.addPbkdf2AesData("PBEWithHmacSHA1AndAES_128",
+ CKM_PKCS5_PBKD2, CKP_PKCS5_PBKD2_HMAC_SHA1, 128);
+ KDFData.addPbkdf2AesData("PBEWithHmacSHA224AndAES_128",
+ CKM_PKCS5_PBKD2, CKP_PKCS5_PBKD2_HMAC_SHA224, 128);
+ KDFData.addPbkdf2AesData("PBEWithHmacSHA256AndAES_128",
+ CKM_PKCS5_PBKD2, CKP_PKCS5_PBKD2_HMAC_SHA256, 128);
+ KDFData.addPbkdf2AesData("PBEWithHmacSHA384AndAES_128",
+ CKM_PKCS5_PBKD2, CKP_PKCS5_PBKD2_HMAC_SHA384, 128);
+ KDFData.addPbkdf2AesData("PBEWithHmacSHA512AndAES_128",
+ CKM_PKCS5_PBKD2, CKP_PKCS5_PBKD2_HMAC_SHA512, 128);
+ KDFData.addPbkdf2AesData("PBEWithHmacSHA1AndAES_256",
+ CKM_PKCS5_PBKD2, CKP_PKCS5_PBKD2_HMAC_SHA1, 256);
+ KDFData.addPbkdf2AesData("PBEWithHmacSHA224AndAES_256",
+ CKM_PKCS5_PBKD2, CKP_PKCS5_PBKD2_HMAC_SHA224, 256);
+ KDFData.addPbkdf2AesData("PBEWithHmacSHA256AndAES_256",
+ CKM_PKCS5_PBKD2, CKP_PKCS5_PBKD2_HMAC_SHA256, 256);
+ KDFData.addPbkdf2AesData("PBEWithHmacSHA384AndAES_256",
+ CKM_PKCS5_PBKD2, CKP_PKCS5_PBKD2_HMAC_SHA384, 256);
+ KDFData.addPbkdf2AesData("PBEWithHmacSHA512AndAES_256",
+ CKM_PKCS5_PBKD2, CKP_PKCS5_PBKD2_HMAC_SHA512, 256);
+
+ KDFData.addPbkdf2Data("PBKDF2WithHmacSHA1",
+ CKM_PKCS5_PBKD2, CKP_PKCS5_PBKD2_HMAC_SHA1);
+ KDFData.addPbkdf2Data("PBKDF2WithHmacSHA224",
+ CKM_PKCS5_PBKD2, CKP_PKCS5_PBKD2_HMAC_SHA224);
+ KDFData.addPbkdf2Data("PBKDF2WithHmacSHA256",
+ CKM_PKCS5_PBKD2, CKP_PKCS5_PBKD2_HMAC_SHA256);
+ KDFData.addPbkdf2Data("PBKDF2WithHmacSHA384",
+ CKM_PKCS5_PBKD2, CKP_PKCS5_PBKD2_HMAC_SHA384);
+ KDFData.addPbkdf2Data("PBKDF2WithHmacSHA512",
+ CKM_PKCS5_PBKD2, CKP_PKCS5_PBKD2_HMAC_SHA512);
+
+ KDFData.addPkcs12KDData("HmacPBESHA1",
+ CKM_PBA_SHA1_WITH_SHA1_HMAC, 160);
+ KDFData.addPkcs12KDData("HmacPBESHA224",
+ CKM_NSS_PKCS12_PBE_SHA224_HMAC_KEY_GEN, 224);
+ KDFData.addPkcs12KDData("HmacPBESHA256",
+ CKM_NSS_PKCS12_PBE_SHA256_HMAC_KEY_GEN, 256);
+ KDFData.addPkcs12KDData("HmacPBESHA384",
+ CKM_NSS_PKCS12_PBE_SHA384_HMAC_KEY_GEN, 384);
+ KDFData.addPkcs12KDData("HmacPBESHA512",
+ CKM_NSS_PKCS12_PBE_SHA512_HMAC_KEY_GEN, 512);
+ KDFData.addPkcs12KDData("HmacPBESHA512/224",
+ CKM_NSS_PKCS12_PBE_SHA512_HMAC_KEY_GEN, 512);
+ KDFData.addPkcs12KDData("HmacPBESHA512/256",
+ CKM_NSS_PKCS12_PBE_SHA512_HMAC_KEY_GEN, 512);
+ }
+
private P11Util() {
// empty
}
+ static boolean isNSS(Token token) {
+ char[] tokenLabel = token.tokenInfo.label;
+ if (tokenLabel != null && tokenLabel.length >= 3) {
+ return (tokenLabel[0] == 'N' && tokenLabel[1] == 'S'
+ && tokenLabel[2] == 'S');
+ }
+ return false;
+ }
+
static Provider getSunProvider() {
Provider p = sun;
if (p == null) {
diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SunPKCS11.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SunPKCS11.java
index aa35e8fa668..1855e5631bd 100644
--- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SunPKCS11.java
+++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SunPKCS11.java
@@ -26,6 +26,9 @@
package sun.security.pkcs11;
import java.io.*;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
import java.util.*;
import java.security.*;
@@ -42,10 +45,12 @@ import javax.security.auth.callback.PasswordCallback;
import com.sun.crypto.provider.ChaCha20Poly1305Parameters;
+import jdk.internal.access.SharedSecrets;
import jdk.internal.misc.InnocuousThread;
import sun.security.util.Debug;
import sun.security.util.ResourcesMgr;
import static sun.security.util.SecurityConstants.PROVIDER_VER;
+import sun.security.util.SecurityProperties;
import static sun.security.util.SecurityProviderConstants.getAliases;
import sun.security.pkcs11.Secmod.*;
@@ -62,6 +67,39 @@ import static sun.security.pkcs11.wrapper.PKCS11Exception.*;
*/
public final class SunPKCS11 extends AuthProvider {
+ private static final boolean systemFipsEnabled = SharedSecrets
+ .getJavaSecuritySystemConfiguratorAccess().isSystemFipsEnabled();
+
+ private static final boolean plainKeySupportEnabled = SharedSecrets
+ .getJavaSecuritySystemConfiguratorAccess().isPlainKeySupportEnabled();
+
+ private static final MethodHandle fipsImportKey;
+ private static final MethodHandle fipsExportKey;
+ static {
+ MethodHandle fipsImportKeyTmp = null;
+ MethodHandle fipsExportKeyTmp = null;
+ if (plainKeySupportEnabled) {
+ try {
+ fipsImportKeyTmp = MethodHandles.lookup().findStatic(
+ FIPSKeyImporter.class, "importKey",
+ MethodType.methodType(Long.class, SunPKCS11.class,
+ long.class, CK_ATTRIBUTE[].class));
+ fipsExportKeyTmp = MethodHandles.lookup().findStatic(
+ FIPSKeyImporter.class, "exportKey",
+ MethodType.methodType(void.class, SunPKCS11.class,
+ long.class, long.class,
+ long.class, long.class, Map.class));
+ } catch (Throwable t) {
+ throw new SecurityException("FIPS key importer-exporter" +
+ " initialization failed", t);
+ }
+ }
+ fipsImportKey = fipsImportKeyTmp;
+ fipsExportKey = fipsExportKeyTmp;
+ }
+
+ private static final String FIPS_NSSDB_PATH_PROP = "fips.nssdb.path";
+
private static final long serialVersionUID = -1354835039035306505L;
static final Debug debug = Debug.getInstance("sunpkcs11");
@@ -115,6 +153,29 @@ public final class SunPKCS11 extends AuthProvider {
return AccessController.doPrivileged(new PrivilegedExceptionAction<>() {
@Override
public SunPKCS11 run() throws Exception {
+ if (systemFipsEnabled) {
+ /*
+ * The nssSecmodDirectory attribute in the SunPKCS11
+ * NSS configuration file takes the value of the
+ * fips.nssdb.path System property after expansion.
+ * Security properties expansion is unsupported.
+ */
+ String nssdbPath =
+ SecurityProperties.privilegedGetOverridable(
+ FIPS_NSSDB_PATH_PROP);
+ if (System.getSecurityManager() != null) {
+ AccessController.doPrivileged(
+ (PrivilegedAction<Void>) () -> {
+ System.setProperty(
+ FIPS_NSSDB_PATH_PROP,
+ nssdbPath);
+ return null;
+ });
+ } else {
+ System.setProperty(
+ FIPS_NSSDB_PATH_PROP, nssdbPath);
+ }
+ }
return new SunPKCS11(new Config(newConfigName));
}
});
@@ -320,10 +381,19 @@ public final class SunPKCS11 extends AuthProvider {
// request multithreaded access first
initArgs.flags = CKF_OS_LOCKING_OK;
PKCS11 tmpPKCS11;
+ MethodHandle fipsKeyImporter = null;
+ MethodHandle fipsKeyExporter = null;
+ if (plainKeySupportEnabled) {
+ fipsKeyImporter = MethodHandles.insertArguments(
+ fipsImportKey, 0, this);
+ fipsKeyExporter = MethodHandles.insertArguments(
+ fipsExportKey, 0, this);
+ }
try {
tmpPKCS11 = PKCS11.getInstance(
library, functionList, initArgs,
- config.getOmitInitialize());
+ config.getOmitInitialize(), fipsKeyImporter,
+ fipsKeyExporter);
} catch (PKCS11Exception e) {
if (debug != null) {
debug.println("Multi-threaded initialization failed: " + e);
@@ -339,11 +409,12 @@ public final class SunPKCS11 extends AuthProvider {
initArgs.flags = 0;
}
tmpPKCS11 = PKCS11.getInstance(library,
- functionList, initArgs, config.getOmitInitialize());
+ functionList, initArgs, config.getOmitInitialize(), fipsKeyImporter,
+ fipsKeyExporter);
}
p11 = tmpPKCS11;
- CK_INFO p11Info = p11.C_GetInfo();
+ CK_INFO p11Info = p11.getInfo();
if (p11Info.cryptokiVersion.major < 2) {
throw new ProviderException("Only PKCS#11 v2.0 and later "
+ "supported, library version is v" + p11Info.cryptokiVersion);
@@ -417,14 +488,19 @@ public final class SunPKCS11 extends AuthProvider {
final String className;
final List<String> aliases;
final int[] mechanisms;
+ final int[] requiredMechs;
+ // mechanisms is a list of possible mechanisms that implement the
+ // algorithm, at least one of them must be available. requiredMechs
+ // is a list of auxiliary mechanisms, all of them must be available
private Descriptor(String type, String algorithm, String className,
- List<String> aliases, int[] mechanisms) {
+ List<String> aliases, int[] mechanisms, int[] requiredMechs) {
this.type = type;
this.algorithm = algorithm;
this.className = className;
this.aliases = aliases;
this.mechanisms = mechanisms;
+ this.requiredMechs = requiredMechs;
}
private P11Service service(Token token, int mechanism) {
return new P11Service
@@ -458,18 +534,29 @@ public final class SunPKCS11 extends AuthProvider {
private static void d(String type, String algorithm, String className,
int[] m) {
- register(new Descriptor(type, algorithm, className, null, m));
+ register(new Descriptor(type, algorithm, className, null, m, null));
}
private static void d(String type, String algorithm, String className,
List<String> aliases, int[] m) {
- register(new Descriptor(type, algorithm, className, aliases, m));
+ register(new Descriptor(type, algorithm, className, aliases, m, null));
+ }
+
+ private static void d(String type, String algorithm, String className,
+ int[] m, int[] requiredMechs) {
+ register(new Descriptor(type, algorithm, className, null, m,
+ requiredMechs));
+ }
+ private static void dA(String type, String algorithm, String className,
+ int[] m, int[] requiredMechs) {
+ register(new Descriptor(type, algorithm, className,
+ getAliases(algorithm), m, requiredMechs));
}
private static void dA(String type, String algorithm, String className,
int[] m) {
register(new Descriptor(type, algorithm, className,
- getAliases(algorithm), m));
+ getAliases(algorithm), m, null));
}
private static void register(Descriptor d) {
@@ -525,6 +612,7 @@ public final class SunPKCS11 extends AuthProvider {
String P11Cipher = "sun.security.pkcs11.P11Cipher";
String P11RSACipher = "sun.security.pkcs11.P11RSACipher";
String P11AEADCipher = "sun.security.pkcs11.P11AEADCipher";
+ String P11PBECipher = "sun.security.pkcs11.P11PBECipher";
String P11Signature = "sun.security.pkcs11.P11Signature";
String P11PSSSignature = "sun.security.pkcs11.P11PSSSignature";
@@ -587,6 +675,30 @@ public final class SunPKCS11 extends AuthProvider {
d(MAC, "SslMacSHA1", P11Mac,
m(CKM_SSL3_SHA1_MAC));
+ if (systemFipsEnabled) {
+ /*
+ * PBA HMacs
+ *
+ * KeyDerivationMech must be supported
+ * for these services to be available.
+ *
+ */
+ d(MAC, "HmacPBESHA1", P11Mac, m(CKM_SHA_1_HMAC),
+ m(CKM_PBA_SHA1_WITH_SHA1_HMAC));
+ d(MAC, "HmacPBESHA224", P11Mac, m(CKM_SHA224_HMAC),
+ m(CKM_NSS_PKCS12_PBE_SHA224_HMAC_KEY_GEN));
+ d(MAC, "HmacPBESHA256", P11Mac, m(CKM_SHA256_HMAC),
+ m(CKM_NSS_PKCS12_PBE_SHA256_HMAC_KEY_GEN));
+ d(MAC, "HmacPBESHA384", P11Mac, m(CKM_SHA384_HMAC),
+ m(CKM_NSS_PKCS12_PBE_SHA384_HMAC_KEY_GEN));
+ d(MAC, "HmacPBESHA512", P11Mac, m(CKM_SHA512_HMAC),
+ m(CKM_NSS_PKCS12_PBE_SHA512_HMAC_KEY_GEN));
+ d(MAC, "HmacPBESHA512/224", P11Mac, m(CKM_SHA512_224_HMAC),
+ m(CKM_NSS_PKCS12_PBE_SHA512_HMAC_KEY_GEN));
+ d(MAC, "HmacPBESHA512/256", P11Mac, m(CKM_SHA512_256_HMAC),
+ m(CKM_NSS_PKCS12_PBE_SHA512_HMAC_KEY_GEN));
+ }
+
d(KPG, "RSA", P11KeyPairGenerator,
getAliases("PKCS1"),
m(CKM_RSA_PKCS_KEY_PAIR_GEN));
@@ -685,6 +797,66 @@ public final class SunPKCS11 extends AuthProvider {
d(SKF, "ChaCha20", P11SecretKeyFactory,
m(CKM_CHACHA20_POLY1305));
+ if (systemFipsEnabled) {
+ /*
+ * PBE Secret Key Factories
+ *
+ * KeyDerivationPrf must be supported for these services
+ * to be available.
+ *
+ */
+ d(SKF, "PBEWithHmacSHA1AndAES_128",
+ P11SecretKeyFactory, m(CKM_PKCS5_PBKD2), m(CKM_SHA_1_HMAC));
+ d(SKF, "PBEWithHmacSHA224AndAES_128",
+ P11SecretKeyFactory, m(CKM_PKCS5_PBKD2), m(CKM_SHA224_HMAC));
+ d(SKF, "PBEWithHmacSHA256AndAES_128",
+ P11SecretKeyFactory, m(CKM_PKCS5_PBKD2), m(CKM_SHA256_HMAC));
+ d(SKF, "PBEWithHmacSHA384AndAES_128",
+ P11SecretKeyFactory, m(CKM_PKCS5_PBKD2), m(CKM_SHA384_HMAC));
+ d(SKF, "PBEWithHmacSHA512AndAES_128",
+ P11SecretKeyFactory, m(CKM_PKCS5_PBKD2), m(CKM_SHA512_HMAC));
+ d(SKF, "PBEWithHmacSHA1AndAES_256",
+ P11SecretKeyFactory, m(CKM_PKCS5_PBKD2), m(CKM_SHA_1_HMAC));
+ d(SKF, "PBEWithHmacSHA224AndAES_256",
+ P11SecretKeyFactory, m(CKM_PKCS5_PBKD2), m(CKM_SHA224_HMAC));
+ d(SKF, "PBEWithHmacSHA256AndAES_256",
+ P11SecretKeyFactory, m(CKM_PKCS5_PBKD2), m(CKM_SHA256_HMAC));
+ d(SKF, "PBEWithHmacSHA384AndAES_256",
+ P11SecretKeyFactory, m(CKM_PKCS5_PBKD2), m(CKM_SHA384_HMAC));
+ d(SKF, "PBEWithHmacSHA512AndAES_256",
+ P11SecretKeyFactory, m(CKM_PKCS5_PBKD2), m(CKM_SHA512_HMAC));
+ /*
+ * PBA Secret Key Factories
+ */
+ d(SKF, "HmacPBESHA1", P11SecretKeyFactory,
+ m(CKM_PBA_SHA1_WITH_SHA1_HMAC));
+ d(SKF, "HmacPBESHA224", P11SecretKeyFactory,
+ m(CKM_NSS_PKCS12_PBE_SHA224_HMAC_KEY_GEN));
+ d(SKF, "HmacPBESHA256", P11SecretKeyFactory,
+ m(CKM_NSS_PKCS12_PBE_SHA256_HMAC_KEY_GEN));
+ d(SKF, "HmacPBESHA384", P11SecretKeyFactory,
+ m(CKM_NSS_PKCS12_PBE_SHA384_HMAC_KEY_GEN));
+ d(SKF, "HmacPBESHA512", P11SecretKeyFactory,
+ m(CKM_NSS_PKCS12_PBE_SHA512_HMAC_KEY_GEN));
+ d(SKF, "HmacPBESHA512/224", P11SecretKeyFactory,
+ m(CKM_NSS_PKCS12_PBE_SHA512_HMAC_KEY_GEN));
+ d(SKF, "HmacPBESHA512/256", P11SecretKeyFactory,
+ m(CKM_NSS_PKCS12_PBE_SHA512_HMAC_KEY_GEN));
+ /*
+ * PBKDF2 Secret Key Factories
+ */
+ dA(SKF, "PBKDF2WithHmacSHA1", P11SecretKeyFactory,
+ m(CKM_PKCS5_PBKD2), m(CKM_SHA_1_HMAC));
+ d(SKF, "PBKDF2WithHmacSHA224", P11SecretKeyFactory,
+ m(CKM_PKCS5_PBKD2), m(CKM_SHA224_HMAC));
+ d(SKF, "PBKDF2WithHmacSHA256", P11SecretKeyFactory,
+ m(CKM_PKCS5_PBKD2), m(CKM_SHA256_HMAC));
+ d(SKF, "PBKDF2WithHmacSHA384", P11SecretKeyFactory,
+ m(CKM_PKCS5_PBKD2), m(CKM_SHA384_HMAC));
+ d(SKF, "PBKDF2WithHmacSHA512", P11SecretKeyFactory,
+ m(CKM_PKCS5_PBKD2), m(CKM_SHA512_HMAC));
+ }
+
// XXX attributes for Ciphers (supported modes, padding)
dA(CIP, "ARCFOUR", P11Cipher,
m(CKM_RC4));
@@ -754,6 +926,46 @@ public final class SunPKCS11 extends AuthProvider {
d(CIP, "RSA/ECB/NoPadding", P11RSACipher,
m(CKM_RSA_X_509));
+ if (systemFipsEnabled) {
+ /*
+ * PBE Ciphers
+ *
+ * KeyDerivationMech and KeyDerivationPrf must be supported
+ * for these services to be available.
+ *
+ */
+ d(CIP, "PBEWithHmacSHA1AndAES_128", P11PBECipher,
+ m(CKM_AES_CBC_PAD, CKM_AES_CBC),
+ m(CKM_PKCS5_PBKD2, CKM_SHA_1_HMAC));
+ d(CIP, "PBEWithHmacSHA224AndAES_128", P11PBECipher,
+ m(CKM_AES_CBC_PAD, CKM_AES_CBC),
+ m(CKM_PKCS5_PBKD2, CKM_SHA224_HMAC));
+ d(CIP, "PBEWithHmacSHA256AndAES_128", P11PBECipher,
+ m(CKM_AES_CBC_PAD, CKM_AES_CBC),
+ m(CKM_PKCS5_PBKD2, CKM_SHA256_HMAC));
+ d(CIP, "PBEWithHmacSHA384AndAES_128", P11PBECipher,
+ m(CKM_AES_CBC_PAD, CKM_AES_CBC),
+ m(CKM_PKCS5_PBKD2, CKM_SHA384_HMAC));
+ d(CIP, "PBEWithHmacSHA512AndAES_128", P11PBECipher,
+ m(CKM_AES_CBC_PAD, CKM_AES_CBC),
+ m(CKM_PKCS5_PBKD2, CKM_SHA512_HMAC));
+ d(CIP, "PBEWithHmacSHA1AndAES_256", P11PBECipher,
+ m(CKM_AES_CBC_PAD, CKM_AES_CBC),
+ m(CKM_PKCS5_PBKD2, CKM_SHA_1_HMAC));
+ d(CIP, "PBEWithHmacSHA224AndAES_256", P11PBECipher,
+ m(CKM_AES_CBC_PAD, CKM_AES_CBC),
+ m(CKM_PKCS5_PBKD2, CKM_SHA224_HMAC));
+ d(CIP, "PBEWithHmacSHA256AndAES_256", P11PBECipher,
+ m(CKM_AES_CBC_PAD, CKM_AES_CBC),
+ m(CKM_PKCS5_PBKD2, CKM_SHA256_HMAC));
+ d(CIP, "PBEWithHmacSHA384AndAES_256", P11PBECipher,
+ m(CKM_AES_CBC_PAD, CKM_AES_CBC),
+ m(CKM_PKCS5_PBKD2, CKM_SHA384_HMAC));
+ d(CIP, "PBEWithHmacSHA512AndAES_256", P11PBECipher,
+ m(CKM_AES_CBC_PAD, CKM_AES_CBC),
+ m(CKM_PKCS5_PBKD2, CKM_SHA512_HMAC));
+ }
+
d(SIG, "RawDSA", P11Signature,
List.of("NONEwithDSA"),
m(CKM_DSA));
@@ -1144,9 +1356,21 @@ public final class SunPKCS11 extends AuthProvider {
if (ds == null) {
continue;
}
+ descLoop:
for (Descriptor d : ds) {
Integer oldMech = supportedAlgs.get(d);
if (oldMech == null) {
+ if (d.requiredMechs != null) {
+ // Check that other mechanisms required for the
+ // service are supported before listing it as
+ // available for the first time.
+ for (int requiredMech : d.requiredMechs) {
+ if (token.getMechanismInfo(
+ requiredMech & 0xFFFFFFFFL) == null) {
+ continue descLoop;
+ }
+ }
+ }
supportedAlgs.put(d, integerMech);
continue;
}
@@ -1220,11 +1444,52 @@ public final class SunPKCS11 extends AuthProvider {
}
@Override
+ @SuppressWarnings("removal")
public Object newInstance(Object param)
throws NoSuchAlgorithmException {
if (token.isValid() == false) {
throw new NoSuchAlgorithmException("Token has been removed");
}
+ if (systemFipsEnabled && !token.fipsLoggedIn &&
+ !getType().equals("KeyStore")) {
+ /*
+ * The NSS Software Token in FIPS 140-2 mode requires a
+ * user login for most operations. See sftk_fipsCheck
+ * (nss/lib/softoken/fipstokn.c). In case of a KeyStore
+ * service, let the caller perform the login with
+ * KeyStore::load. Keytool, for example, does this to pass a
+ * PIN from either the -srcstorepass or -deststorepass
+ * argument. In case of a non-KeyStore service, perform the
+ * login now with the PIN available in the fips.nssdb.pin
+ * property.
+ */
+ try {
+ if (System.getSecurityManager() != null) {
+ try {
+ AccessController.doPrivileged(
+ (PrivilegedExceptionAction<Void>) () -> {
+ token.ensureLoggedIn(null);
+ return null;
+ });
+ } catch (PrivilegedActionException pae) {
+ Exception e = pae.getException();
+ if (e instanceof LoginException le) {
+ throw le;
+ } else if (e instanceof PKCS11Exception p11e) {
+ throw p11e;
+ } else {
+ throw new RuntimeException(e);
+ }
+ }
+ } else {
+ token.ensureLoggedIn(null);
+ }
+ } catch (PKCS11Exception | LoginException e) {
+ throw new ProviderException("FIPS: error during the Token" +
+ " login required for the " + getType() +
+ " service.", e);
+ }
+ }
try {
return newInstance0(param);
} catch (PKCS11Exception e) {
@@ -1244,6 +1509,8 @@ public final class SunPKCS11 extends AuthProvider {
} else if (algorithm.endsWith("GCM/NoPadding") ||
algorithm.startsWith("ChaCha20-Poly1305")) {
return new P11AEADCipher(token, algorithm, mechanism);
+ } else if (algorithm.startsWith("PBE")) {
+ return new P11PBECipher(token, algorithm, mechanism);
} else {
return new P11Cipher(token, algorithm, mechanism);
}
@@ -1579,6 +1846,9 @@ public final class SunPKCS11 extends AuthProvider {
try {
session = token.getOpSession();
p11.C_Logout(session.id());
+ if (systemFipsEnabled) {
+ token.fipsLoggedIn = false;
+ }
if (debug != null) {
debug.println("logout succeeded");
}
diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/Token.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/Token.java
index 9858a5faedf..e63585486d9 100644
--- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/Token.java
+++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/Token.java
@@ -33,6 +33,7 @@ import java.lang.ref.*;
import java.security.*;
import javax.security.auth.login.LoginException;
+import jdk.internal.access.SharedSecrets;
import sun.security.jca.JCAUtil;
import sun.security.pkcs11.wrapper.*;
@@ -48,6 +49,9 @@ import static sun.security.pkcs11.wrapper.PKCS11Exception.*;
*/
class Token implements Serializable {
+ private static final boolean systemFipsEnabled = SharedSecrets
+ .getJavaSecuritySystemConfiguratorAccess().isSystemFipsEnabled();
+
// need to be serializable to allow SecureRandom to be serialized
private static final long serialVersionUID = 2541527649100571747L;
@@ -114,6 +118,10 @@ class Token implements Serializable {
// flag indicating whether we are logged in
private volatile boolean loggedIn;
+ // Flag indicating the login status for the NSS Software Token in FIPS mode.
+ // This Token is never asynchronously removed. Used from SunPKCS11.
+ volatile boolean fipsLoggedIn;
+
// time we last checked login status
private long lastLoginCheck;
@@ -232,7 +240,12 @@ class Token implements Serializable {
// call provider.login() if not
void ensureLoggedIn(Session session) throws PKCS11Exception, LoginException {
if (isLoggedIn(session) == false) {
- provider.login(null, null);
+ if (systemFipsEnabled) {
+ provider.login(null, new FIPSTokenLoginHandler());
+ fipsLoggedIn = true;
+ } else {
+ provider.login(null, null);
+ }
}
}
diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/CK_ECDH1_DERIVE_PARAMS.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/CK_ECDH1_DERIVE_PARAMS.java
index 88ff8a71fc3..47a2f97eddf 100644
--- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/CK_ECDH1_DERIVE_PARAMS.java
+++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/CK_ECDH1_DERIVE_PARAMS.java
@@ -100,9 +100,9 @@ public class CK_ECDH1_DERIVE_PARAMS {
}
/**
- * Returns the string representation of CK_PKCS5_PBKD2_PARAMS.
+ * Returns the string representation of CK_ECDH1_DERIVE_PARAMS.
*
- * @return the string representation of CK_PKCS5_PBKD2_PARAMS
+ * @return the string representation of CK_ECDH1_DERIVE_PARAMS
*/
public String toString() {
StringBuilder sb = new StringBuilder();
diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/CK_MECHANISM.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/CK_MECHANISM.java
index 0c9ebb289c1..b4b2448464d 100644
--- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/CK_MECHANISM.java
+++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/CK_MECHANISM.java
@@ -160,6 +160,18 @@ public class CK_MECHANISM {
init(mechanism, params);
}
+ public CK_MECHANISM(long mechanism, CK_PBE_PARAMS params) {
+ init(mechanism, params);
+ }
+
+ public CK_MECHANISM(long mechanism, CK_PKCS5_PBKD2_PARAMS params) {
+ init(mechanism, params);
+ }
+
+ public CK_MECHANISM(long mechanism, CK_PKCS5_PBKD2_PARAMS2 params) {
+ init(mechanism, params);
+ }
+
// For PSS. the parameter may be set multiple times, use the
// CK_MECHANISM(long) constructor and setParameter(CK_RSA_PKCS_PSS_PARAMS)
// methods instead of creating yet another constructor
diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/CK_PBE_PARAMS.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/CK_PBE_PARAMS.java
index e8b048869c4..a25fa1c39e5 100644
--- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/CK_PBE_PARAMS.java
+++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/CK_PBE_PARAMS.java
@@ -50,15 +50,15 @@ package sun.security.pkcs11.wrapper;
/**
- * class CK_PBE_PARAMS provides all of the necessary information required byte
+ * class CK_PBE_PARAMS provides all the necessary information required by
* the CKM_PBE mechanisms and the CKM_PBA_SHA1_WITH_SHA1_HMAC mechanism.<p>
* <B>PKCS#11 structure:</B>
* <PRE>
* typedef struct CK_PBE_PARAMS {
- * CK_CHAR_PTR pInitVector;
- * CK_CHAR_PTR pPassword;
+ * CK_BYTE_PTR pInitVector;
+ * CK_UTF8CHAR_PTR pPassword;
* CK_ULONG ulPasswordLen;
- * CK_CHAR_PTR pSalt;
+ * CK_BYTE_PTR pSalt;
* CK_ULONG ulSaltLen;
* CK_ULONG ulIteration;
* } CK_PBE_PARAMS;
@@ -72,15 +72,15 @@ public class CK_PBE_PARAMS {
/**
* <B>PKCS#11:</B>
* <PRE>
- * CK_CHAR_PTR pInitVector;
+ * CK_BYTE_PTR pInitVector;
* </PRE>
*/
- public char[] pInitVector;
+ public byte[] pInitVector;
/**
* <B>PKCS#11:</B>
* <PRE>
- * CK_CHAR_PTR pPassword;
+ * CK_UTF8CHAR_PTR pPassword;
* CK_ULONG ulPasswordLen;
* </PRE>
*/
@@ -89,11 +89,11 @@ public class CK_PBE_PARAMS {
/**
* <B>PKCS#11:</B>
* <PRE>
- * CK_CHAR_PTR pSalt
+ * CK_BYTE_PTR pSalt
* CK_ULONG ulSaltLen;
* </PRE>
*/
- public char[] pSalt;
+ public byte[] pSalt;
/**
* <B>PKCS#11:</B>
@@ -103,6 +103,12 @@ public class CK_PBE_PARAMS {
*/
public long ulIteration;
+ public CK_PBE_PARAMS(char[] pPassword, byte[] pSalt, long ulIteration) {
+ this.pPassword = pPassword;
+ this.pSalt = pSalt;
+ this.ulIteration = ulIteration;
+ }
+
/**
* Returns the string representation of CK_PBE_PARAMS.
*
diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/CK_PKCS5_PBKD2_PARAMS.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/CK_PKCS5_PBKD2_PARAMS.java
index fb90bfced27..a01beb0753a 100644
--- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/CK_PKCS5_PBKD2_PARAMS.java
+++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/CK_PKCS5_PBKD2_PARAMS.java
@@ -47,7 +47,7 @@
package sun.security.pkcs11.wrapper;
-
+import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
/**
* class CK_PKCS5_PBKD2_PARAMS provides the parameters to the CKM_PKCS5_PBKD2
@@ -55,13 +55,15 @@ package sun.security.pkcs11.wrapper;
* <B>PKCS#11 structure:</B>
* <PRE>
* typedef struct CK_PKCS5_PBKD2_PARAMS {
- * CK_PKCS5_PBKD2_SALT_SOURCE_TYPE saltSource;
+ * CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE saltSource;
* CK_VOID_PTR pSaltSourceData;
* CK_ULONG ulSaltSourceDataLen;
* CK_ULONG iterations;
* CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE prf;
* CK_VOID_PTR pPrfData;
* CK_ULONG ulPrfDataLen;
+ * CK_UTF8CHAR_PTR pPassword;
+ * CK_ULONG_PTR ulPasswordLen;
* } CK_PKCS5_PBKD2_PARAMS;
* </PRE>
*
@@ -112,6 +114,24 @@ public class CK_PKCS5_PBKD2_PARAMS {
*/
public byte[] pPrfData;
+ /**
+ * <b>PKCS#11:</b>
+ * <pre>
+ * CK_UTF8CHAR_PTR pPassword
+ * CK_ULONG_PTR ulPasswordLen;
+ * </pre>
+ */
+ public char[] pPassword;
+
+ public CK_PKCS5_PBKD2_PARAMS(char[] pPassword, byte[] pSalt,
+ long iterations, long prf) {
+ this.pPassword = pPassword;
+ this.pSaltSourceData = pSalt;
+ this.iterations = iterations;
+ this.prf = prf;
+ this.saltSource = CKZ_SALT_SPECIFIED;
+ }
+
/**
* Returns the string representation of CK_PKCS5_PBKD2_PARAMS.
*
diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/CK_PKCS5_PBKD2_PARAMS2.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/CK_PKCS5_PBKD2_PARAMS2.java
new file mode 100644
index 00000000000..935db656639
--- /dev/null
+++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/CK_PKCS5_PBKD2_PARAMS2.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2022, Red Hat, Inc.
+ * 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 sun.security.pkcs11.wrapper;
+
+import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
+
+/**
+ * class CK_PKCS5_PBKD2_PARAMS2 provides the parameters to the CKM_PKCS5_PBKD2
+ * mechanism.<p>
+ * <b>PKCS#11 structure:</b>
+ * <pre>
+ * typedef struct CK_PKCS5_PBKD2_PARAMS2 {
+ * CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE saltSource;
+ * CK_VOID_PTR pSaltSourceData;
+ * CK_ULONG ulSaltSourceDataLen;
+ * CK_ULONG iterations;
+ * CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE prf;
+ * CK_VOID_PTR pPrfData;
+ * CK_ULONG ulPrfDataLen;
+ * CK_UTF8CHAR_PTR pPassword;
+ * CK_ULONG ulPasswordLen;
+ * } CK_PKCS5_PBKD2_PARAMS2;
+ * </pre>
+ *
+ */
+public class CK_PKCS5_PBKD2_PARAMS2 {
+
+ /**
+ * <b>PKCS#11:</b>
+ * <pre>
+ * CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE saltSource;
+ * </pre>
+ */
+ public long saltSource;
+
+ /**
+ * <b>PKCS#11:</b>
+ * <pre>
+ * CK_VOID_PTR pSaltSourceData;
+ * CK_ULONG ulSaltSourceDataLen;
+ * </pre>
+ */
+ public byte[] pSaltSourceData;
+
+ /**
+ * <b>PKCS#11:</b>
+ * <pre>
+ * CK_ULONG iterations;
+ * </pre>
+ */
+ public long iterations;
+
+ /**
+ * <b>PKCS#11:</b>
+ * <pre>
+ * CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE prf;
+ * </pre>
+ */
+ public long prf;
+
+ /**
+ * <b>PKCS#11:</b>
+ * <pre>
+ * CK_VOID_PTR pPrfData;
+ * CK_ULONG ulPrfDataLen;
+ * </pre>
+ */
+ public byte[] pPrfData;
+
+ /**
+ * <b>PKCS#11:</b>
+ * <pre>
+ * CK_UTF8CHAR_PTR pPassword
+ * CK_ULONG ulPasswordLen;
+ * </pre>
+ */
+ public char[] pPassword;
+
+ public CK_PKCS5_PBKD2_PARAMS2(char[] pPassword, byte[] pSalt,
+ long iterations, long prf) {
+ this.pPassword = pPassword;
+ this.pSaltSourceData = pSalt;
+ this.iterations = iterations;
+ this.prf = prf;
+ this.saltSource = CKZ_SALT_SPECIFIED;
+ }
+
+ /**
+ * Returns the string representation of CK_PKCS5_PBKD2_PARAMS2.
+ *
+ * @return the string representation of CK_PKCS5_PBKD2_PARAMS2
+ */
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+
+ sb.append(Constants.INDENT);
+ sb.append("saltSource: ");
+ sb.append(saltSource);
+ sb.append(Constants.NEWLINE);
+
+ sb.append(Constants.INDENT);
+ sb.append("pSaltSourceData: ");
+ sb.append(Functions.toHexString(pSaltSourceData));
+ sb.append(Constants.NEWLINE);
+
+ sb.append(Constants.INDENT);
+ sb.append("ulSaltSourceDataLen: ");
+ sb.append(pSaltSourceData.length);
+ sb.append(Constants.NEWLINE);
+
+ sb.append(Constants.INDENT);
+ sb.append("iterations: ");
+ sb.append(iterations);
+ sb.append(Constants.NEWLINE);
+
+ sb.append(Constants.INDENT);
+ sb.append("prf: ");
+ sb.append(prf);
+ sb.append(Constants.NEWLINE);
+
+ sb.append(Constants.INDENT);
+ sb.append("pPrfData: ");
+ sb.append(Functions.toHexString(pPrfData));
+ sb.append(Constants.NEWLINE);
+
+ sb.append(Constants.INDENT);
+ sb.append("ulPrfDataLen: ");
+ sb.append(pPrfData.length);
+
+ return sb.toString();
+ }
+
+}
diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/CK_X9_42_DH1_DERIVE_PARAMS.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/CK_X9_42_DH1_DERIVE_PARAMS.java
index 1f9c4d39f57..5e3c1b9d29f 100644
--- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/CK_X9_42_DH1_DERIVE_PARAMS.java
+++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/CK_X9_42_DH1_DERIVE_PARAMS.java
@@ -94,9 +94,9 @@ public class CK_X9_42_DH1_DERIVE_PARAMS {
public byte[] pPublicData;
/**
- * Returns the string representation of CK_PKCS5_PBKD2_PARAMS.
+ * Returns the string representation of CK_X9_42_DH1_DERIVE_PARAMS.
*
- * @return the string representation of CK_PKCS5_PBKD2_PARAMS
+ * @return the string representation of CK_X9_42_DH1_DERIVE_PARAMS
*/
public String toString() {
StringBuilder sb = new StringBuilder();
diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/PKCS11.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/PKCS11.java
index 5c0aacd1a67..d796aaa3075 100644
--- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/PKCS11.java
+++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/PKCS11.java
@@ -49,6 +49,9 @@ package sun.security.pkcs11.wrapper;
import java.io.File;
import java.io.IOException;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
import java.util.*;
import java.security.AccessController;
@@ -113,6 +116,8 @@ public class PKCS11 {
private long pNativeData;
+ private volatile CK_INFO pInfo;
+
/**
* This method does the initialization of the native library. It is called
* exactly once for this class.
@@ -145,23 +150,48 @@ public class PKCS11 {
* @postconditions
*/
PKCS11(String pkcs11ModulePath, String functionListName)
- throws IOException {
+ throws IOException, PKCS11Exception {
connect(pkcs11ModulePath, functionListName);
this.pkcs11ModulePath = pkcs11ModulePath;
}
+ /*
+ * Compatibility wrapper to allow this method to work as before
+ * when FIPS mode support is not active.
+ */
+ public static synchronized PKCS11 getInstance(String pkcs11ModulePath,
+ String functionList, CK_C_INITIALIZE_ARGS pInitArgs,
+ boolean omitInitialize) throws IOException, PKCS11Exception {
+ return getInstance(pkcs11ModulePath, functionList,
+ pInitArgs, omitInitialize, null, null);
+ }
+
public static synchronized PKCS11 getInstance(String pkcs11ModulePath,
String functionList, CK_C_INITIALIZE_ARGS pInitArgs,
- boolean omitInitialize) throws IOException, PKCS11Exception {
+ boolean omitInitialize, MethodHandle fipsKeyImporter,
+ MethodHandle fipsKeyExporter)
+ throws IOException, PKCS11Exception {
// we may only call C_Initialize once per native .so/.dll
// so keep a cache using the (non-canonicalized!) path
PKCS11 pkcs11 = moduleMap.get(pkcs11ModulePath);
if (pkcs11 == null) {
+ boolean nssFipsMode = fipsKeyImporter != null &&
+ fipsKeyExporter != null;
if ((pInitArgs != null)
&& ((pInitArgs.flags & CKF_OS_LOCKING_OK) != 0)) {
- pkcs11 = new PKCS11(pkcs11ModulePath, functionList);
+ if (nssFipsMode) {
+ pkcs11 = new FIPSPKCS11(pkcs11ModulePath, functionList,
+ fipsKeyImporter, fipsKeyExporter);
+ } else {
+ pkcs11 = new PKCS11(pkcs11ModulePath, functionList);
+ }
} else {
- pkcs11 = new SynchronizedPKCS11(pkcs11ModulePath, functionList);
+ if (nssFipsMode) {
+ pkcs11 = new SynchronizedFIPSPKCS11(pkcs11ModulePath,
+ functionList, fipsKeyImporter, fipsKeyExporter);
+ } else {
+ pkcs11 = new SynchronizedPKCS11(pkcs11ModulePath, functionList);
+ }
}
if (omitInitialize == false) {
try {
@@ -179,6 +209,28 @@ public class PKCS11 {
return pkcs11;
}
+ /**
+ * Returns the CK_INFO structure fetched at initialization with
+ * C_GetInfo. This structure represent Cryptoki library information.
+ */
+ public CK_INFO getInfo() {
+ CK_INFO lPInfo = pInfo;
+ if (lPInfo == null) {
+ synchronized (this) {
+ lPInfo = pInfo;
+ if (lPInfo == null) {
+ try {
+ lPInfo = C_GetInfo();
+ pInfo = lPInfo;
+ } catch (PKCS11Exception e) {
+ // Some PKCS #11 tokens require initialization first.
+ }
+ }
+ }
+ }
+ return lPInfo;
+ }
+
/**
* Connects this object to the specified PKCS#11 library. This method is for
* internal use only.
@@ -1625,7 +1677,7 @@ public class PKCS11 {
static class SynchronizedPKCS11 extends PKCS11 {
SynchronizedPKCS11(String pkcs11ModulePath, String functionListName)
- throws IOException {
+ throws IOException, PKCS11Exception {
super(pkcs11ModulePath, functionListName);
}
@@ -1911,4 +1963,194 @@ static class SynchronizedPKCS11 extends PKCS11 {
super.C_GenerateRandom(hSession, randomData);
}
}
+
+// PKCS11 subclass that allows using plain private or secret keys in
+// FIPS-configured NSS Software Tokens. Only used when System FIPS
+// is enabled.
+static class FIPSPKCS11 extends PKCS11 {
+ private MethodHandle fipsKeyImporter;
+ private MethodHandle fipsKeyExporter;
+ private MethodHandle hC_GetAttributeValue;
+ FIPSPKCS11(String pkcs11ModulePath, String functionListName,
+ MethodHandle fipsKeyImporter, MethodHandle fipsKeyExporter)
+ throws IOException, PKCS11Exception {
+ super(pkcs11ModulePath, functionListName);
+ this.fipsKeyImporter = fipsKeyImporter;
+ this.fipsKeyExporter = fipsKeyExporter;
+ try {
+ hC_GetAttributeValue = MethodHandles.insertArguments(
+ MethodHandles.lookup().findSpecial(PKCS11.class,
+ "C_GetAttributeValue", MethodType.methodType(
+ void.class, long.class, long.class,
+ CK_ATTRIBUTE[].class),
+ FIPSPKCS11.class), 0, this);
+ } catch (Throwable t) {
+ throw new RuntimeException(
+ "sun.security.pkcs11.wrapper.PKCS11" +
+ "::C_GetAttributeValue method not found.", t);
+ }
+ }
+
+ public long C_CreateObject(long hSession,
+ CK_ATTRIBUTE[] pTemplate) throws PKCS11Exception {
+ // Creating sensitive key objects from plain key material in a
+ // FIPS-configured NSS Software Token is not allowed. We apply
+ // a key-unwrapping scheme to achieve so.
+ if (FIPSPKCS11Helper.isSensitiveObject(pTemplate)) {
+ try {
+ return ((Long)fipsKeyImporter.invoke(hSession, pTemplate))
+ .longValue();
+ } catch (Throwable t) {
+ if (t instanceof PKCS11Exception) {
+ throw (PKCS11Exception)t;
+ }
+ throw new PKCS11Exception(CKR_GENERAL_ERROR,
+ t.getMessage());
+ }
+ }
+ return super.C_CreateObject(hSession, pTemplate);
+ }
+
+ public void C_GetAttributeValue(long hSession, long hObject,
+ CK_ATTRIBUTE[] pTemplate) throws PKCS11Exception {
+ FIPSPKCS11Helper.C_GetAttributeValue(hC_GetAttributeValue,
+ fipsKeyExporter, hSession, hObject, pTemplate);
+ }
+}
+
+// FIPSPKCS11 synchronized counterpart.
+static class SynchronizedFIPSPKCS11 extends SynchronizedPKCS11 {
+ private MethodHandle fipsKeyImporter;
+ private MethodHandle fipsKeyExporter;
+ private MethodHandle hC_GetAttributeValue;
+ SynchronizedFIPSPKCS11(String pkcs11ModulePath, String functionListName,
+ MethodHandle fipsKeyImporter, MethodHandle fipsKeyExporter)
+ throws IOException, PKCS11Exception {
+ super(pkcs11ModulePath, functionListName);
+ this.fipsKeyImporter = fipsKeyImporter;
+ this.fipsKeyExporter = fipsKeyExporter;
+ try {
+ hC_GetAttributeValue = MethodHandles.insertArguments(
+ MethodHandles.lookup().findSpecial(SynchronizedPKCS11.class,
+ "C_GetAttributeValue", MethodType.methodType(
+ void.class, long.class, long.class,
+ CK_ATTRIBUTE[].class),
+ SynchronizedFIPSPKCS11.class), 0, this);
+ } catch (Throwable t) {
+ throw new RuntimeException(
+ "sun.security.pkcs11.wrapper.SynchronizedPKCS11" +
+ "::C_GetAttributeValue method not found.", t);
+ }
+ }
+
+ public synchronized long C_CreateObject(long hSession,
+ CK_ATTRIBUTE[] pTemplate) throws PKCS11Exception {
+ // See FIPSPKCS11::C_CreateObject.
+ if (FIPSPKCS11Helper.isSensitiveObject(pTemplate)) {
+ try {
+ return ((Long)fipsKeyImporter.invoke(hSession, pTemplate))
+ .longValue();
+ } catch (Throwable t) {
+ if (t instanceof PKCS11Exception) {
+ throw (PKCS11Exception)t;
+ }
+ throw new PKCS11Exception(CKR_GENERAL_ERROR,
+ t.getMessage());
+ }
+ }
+ return super.C_CreateObject(hSession, pTemplate);
+ }
+
+ public synchronized void C_GetAttributeValue(long hSession, long hObject,
+ CK_ATTRIBUTE[] pTemplate) throws PKCS11Exception {
+ FIPSPKCS11Helper.C_GetAttributeValue(hC_GetAttributeValue,
+ fipsKeyExporter, hSession, hObject, pTemplate);
+ }
+}
+
+private static class FIPSPKCS11Helper {
+ static boolean isSensitiveObject(CK_ATTRIBUTE[] pTemplate) {
+ for (CK_ATTRIBUTE attr : pTemplate) {
+ if (attr.type == CKA_CLASS &&
+ (attr.getLong() == CKO_PRIVATE_KEY ||
+ attr.getLong() == CKO_SECRET_KEY)) {
+ return true;
+ }
+ }
+ return false;
+ }
+ static void C_GetAttributeValue(MethodHandle hC_GetAttributeValue,
+ MethodHandle fipsKeyExporter, long hSession, long hObject,
+ CK_ATTRIBUTE[] pTemplate) throws PKCS11Exception {
+ Map<Long, CK_ATTRIBUTE> sensitiveAttrs = new HashMap<>();
+ List<CK_ATTRIBUTE> nonSensitiveAttrs = new LinkedList<>();
+ FIPSPKCS11Helper.getAttributesBySensitivity(pTemplate,
+ sensitiveAttrs, nonSensitiveAttrs);
+ try {
+ if (sensitiveAttrs.size() > 0) {
+ long keyClass = -1L;
+ long keyType = -1L;
+ try {
+ // Secret and private keys have both class and type
+ // attributes, so we can query them at once.
+ CK_ATTRIBUTE[] queryAttrs = new CK_ATTRIBUTE[]{
+ new CK_ATTRIBUTE(CKA_CLASS),
+ new CK_ATTRIBUTE(CKA_KEY_TYPE),
+ };
+ hC_GetAttributeValue.invoke(hSession, hObject, queryAttrs);
+ keyClass = queryAttrs[0].getLong();
+ keyType = queryAttrs[1].getLong();
+ } catch (PKCS11Exception e) {
+ // If the query fails, the object is neither a secret nor a
+ // private key. As this case won't be handled with the FIPS
+ // Key Exporter, we keep keyClass initialized to -1L.
+ }
+ if (keyClass == CKO_SECRET_KEY || keyClass == CKO_PRIVATE_KEY) {
+ fipsKeyExporter.invoke(hSession, hObject, keyClass, keyType,
+ sensitiveAttrs);
+ if (nonSensitiveAttrs.size() > 0) {
+ CK_ATTRIBUTE[] pNonSensitiveAttrs =
+ new CK_ATTRIBUTE[nonSensitiveAttrs.size()];
+ int i = 0;
+ for (CK_ATTRIBUTE nonSensAttr : nonSensitiveAttrs) {
+ pNonSensitiveAttrs[i++] = nonSensAttr;
+ }
+ hC_GetAttributeValue.invoke(hSession, hObject,
+ pNonSensitiveAttrs);
+ // libj2pkcs11 allocates new CK_ATTRIBUTE objects, so we
+ // update the reference on the previous CK_ATTRIBUTEs
+ i = 0;
+ for (CK_ATTRIBUTE nonSensAttr : nonSensitiveAttrs) {
+ nonSensAttr.pValue = pNonSensitiveAttrs[i++].pValue;
+ }
+ }
+ return;
+ }
+ }
+ hC_GetAttributeValue.invoke(hSession, hObject, pTemplate);
+ } catch (Throwable t) {
+ if (t instanceof PKCS11Exception) {
+ throw (PKCS11Exception)t;
+ }
+ throw new PKCS11Exception(CKR_GENERAL_ERROR,
+ t.getMessage());
+ }
+ }
+ private static void getAttributesBySensitivity(CK_ATTRIBUTE[] pTemplate,
+ Map<Long, CK_ATTRIBUTE> sensitiveAttrs,
+ List<CK_ATTRIBUTE> nonSensitiveAttrs) {
+ for (CK_ATTRIBUTE attr : pTemplate) {
+ long type = attr.type;
+ // Aligned with NSS' sftk_isSensitive in lib/softoken/pkcs11u.c
+ if (type == CKA_VALUE || type == CKA_PRIVATE_EXPONENT ||
+ type == CKA_PRIME_1 || type == CKA_PRIME_2 ||
+ type == CKA_EXPONENT_1 || type == CKA_EXPONENT_2 ||
+ type == CKA_COEFFICIENT) {
+ sensitiveAttrs.put(type, attr);
+ } else {
+ nonSensitiveAttrs.add(attr);
+ }
+ }
+ }
+}
}
diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/PKCS11Constants.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/PKCS11Constants.java
index 0d65ee26805..38fd4aff1f3 100644
--- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/PKCS11Constants.java
+++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/PKCS11Constants.java
@@ -1104,17 +1104,6 @@ public interface PKCS11Constants {
public static final long CKD_BLAKE2B_384_KDF = 0x00000019L;
public static final long CKD_BLAKE2B_512_KDF = 0x0000001aL;
- public static final long CKP_PKCS5_PBKD2_HMAC_SHA1 = 0x00000001L;
- public static final long CKP_PKCS5_PBKD2_HMAC_GOSTR3411 = 0x00000002L;
- public static final long CKP_PKCS5_PBKD2_HMAC_SHA224 = 0x00000003L;
- public static final long CKP_PKCS5_PBKD2_HMAC_SHA256 = 0x00000004L;
- public static final long CKP_PKCS5_PBKD2_HMAC_SHA384 = 0x00000005L;
- public static final long CKP_PKCS5_PBKD2_HMAC_SHA512 = 0x00000006L;
- public static final long CKP_PKCS5_PBKD2_HMAC_SHA512_224 = 0x00000007L;
- public static final long CKP_PKCS5_PBKD2_HMAC_SHA512_256 = 0x00000008L;
-
- public static final long CKZ_SALT_SPECIFIED = 0x00000001L;
-
public static final long CK_OTP_VALUE = 0x00000000L;
public static final long CK_OTP_PIN = 0x00000001L;
public static final long CK_OTP_CHALLENGE = 0x00000002L;
@@ -1150,12 +1139,23 @@ public interface PKCS11Constants {
public static final long CKF_HKDF_SALT_KEY = 0x00000004L;
*/
+ // PBKDF2 support, used in P11Util
+ public static final long CKZ_SALT_SPECIFIED = 0x00000001L;
+ public static final long CKP_PKCS5_PBKD2_HMAC_SHA1 = 0x00000001L;
+ public static final long CKP_PKCS5_PBKD2_HMAC_GOSTR3411 = 0x00000002L;
+ public static final long CKP_PKCS5_PBKD2_HMAC_SHA224 = 0x00000003L;
+ public static final long CKP_PKCS5_PBKD2_HMAC_SHA256 = 0x00000004L;
+ public static final long CKP_PKCS5_PBKD2_HMAC_SHA384 = 0x00000005L;
+ public static final long CKP_PKCS5_PBKD2_HMAC_SHA512 = 0x00000006L;
+ public static final long CKP_PKCS5_PBKD2_HMAC_SHA512_224 = 0x00000007L;
+ public static final long CKP_PKCS5_PBKD2_HMAC_SHA512_256 = 0x00000008L;
+
// private NSS attribute (for DSA and DH private keys)
public static final long CKA_NETSCAPE_DB = 0xD5A0DB00L;
// base number of NSS private attributes
public static final long CKA_NETSCAPE_BASE /*0x80000000L + 0x4E534350L*/
- = 0xCE534350L;
+ /* now known as CKM_NSS ^ */ = 0xCE534350L;
// object type for NSS trust
public static final long CKO_NETSCAPE_TRUST = 0xCE534353L;
@@ -1180,4 +1180,14 @@ public interface PKCS11Constants {
= 0xCE534355L;
public static final long CKT_NETSCAPE_VALID = 0xCE53435AL;
public static final long CKT_NETSCAPE_VALID_DELEGATOR = 0xCE53435BL;
+
+ // Additional PKCS #12 PBE key derivation algorithms defined in NSS v3.29
+ public static final long CKM_NSS_PKCS12_PBE_SHA224_HMAC_KEY_GEN
+ /* (CKM_NSS + 29) */ = 0xCE53436DL;
+ public static final long CKM_NSS_PKCS12_PBE_SHA256_HMAC_KEY_GEN
+ /* (CKM_NSS + 30) */ = 0xCE53436EL;
+ public static final long CKM_NSS_PKCS12_PBE_SHA384_HMAC_KEY_GEN
+ /* (CKM_NSS + 31) */ = 0xCE53436FL;
+ public static final long CKM_NSS_PKCS12_PBE_SHA512_HMAC_KEY_GEN
+ /* (CKM_NSS + 32) */ = 0xCE534370L;
}
diff --git a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_convert.c b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_convert.c
index d941b574cc7..e2de13648be 100644
--- a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_convert.c
+++ b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_convert.c
@@ -1515,6 +1515,10 @@ CK_VOID_PTR jMechParamToCKMechParamPtrSlow(JNIEnv *env, jobject jParam,
case CKM_PBE_SHA1_DES3_EDE_CBC:
case CKM_PBE_SHA1_DES2_EDE_CBC:
case CKM_PBA_SHA1_WITH_SHA1_HMAC:
+ case CKM_NSS_PKCS12_PBE_SHA224_HMAC_KEY_GEN:
+ case CKM_NSS_PKCS12_PBE_SHA256_HMAC_KEY_GEN:
+ case CKM_NSS_PKCS12_PBE_SHA384_HMAC_KEY_GEN:
+ case CKM_NSS_PKCS12_PBE_SHA512_HMAC_KEY_GEN:
ckpParamPtr = jPbeParamToCKPbeParamPtr(env, jParam, ckpLength);
break;
case CKM_PKCS5_PBKD2:
@@ -1658,13 +1662,13 @@ jPbeParamToCKPbeParamPtr(JNIEnv *env, jobject jParam, CK_ULONG *pLength)
// retrieve java values
jPbeParamsClass = (*env)->FindClass(env, CLASS_PBE_PARAMS);
if (jPbeParamsClass == NULL) { return NULL; }
- fieldID = (*env)->GetFieldID(env, jPbeParamsClass, "pInitVector", "[C");
+ fieldID = (*env)->GetFieldID(env, jPbeParamsClass, "pInitVector", "[B");
if (fieldID == NULL) { return NULL; }
jInitVector = (*env)->GetObjectField(env, jParam, fieldID);
fieldID = (*env)->GetFieldID(env, jPbeParamsClass, "pPassword", "[C");
if (fieldID == NULL) { return NULL; }
jPassword = (*env)->GetObjectField(env, jParam, fieldID);
- fieldID = (*env)->GetFieldID(env, jPbeParamsClass, "pSalt", "[C");
+ fieldID = (*env)->GetFieldID(env, jPbeParamsClass, "pSalt", "[B");
if (fieldID == NULL) { return NULL; }
jSalt = (*env)->GetObjectField(env, jParam, fieldID);
fieldID = (*env)->GetFieldID(env, jPbeParamsClass, "ulIteration", "J");
@@ -1680,15 +1684,15 @@ jPbeParamToCKPbeParamPtr(JNIEnv *env, jobject jParam, CK_ULONG *pLength)
// populate using java values
ckParamPtr->ulIteration = jLongToCKULong(jIteration);
- jCharArrayToCKCharArray(env, jInitVector, &(ckParamPtr->pInitVector), &ckTemp);
+ jByteArrayToCKByteArray(env, jInitVector, &(ckParamPtr->pInitVector), &ckTemp);
if ((*env)->ExceptionCheck(env)) {
goto cleanup;
}
- jCharArrayToCKCharArray(env, jPassword, &(ckParamPtr->pPassword), &(ckParamPtr->ulPasswordLen));
+ jCharArrayToCKUTF8CharArray(env, jPassword, &(ckParamPtr->pPassword), &(ckParamPtr->ulPasswordLen));
if ((*env)->ExceptionCheck(env)) {
goto cleanup;
}
- jCharArrayToCKCharArray(env, jSalt, &(ckParamPtr->pSalt), &(ckParamPtr->ulSaltLen));
+ jByteArrayToCKByteArray(env, jSalt, &(ckParamPtr->pSalt), &(ckParamPtr->ulSaltLen));
if ((*env)->ExceptionCheck(env)) {
goto cleanup;
}
@@ -1767,31 +1771,59 @@ void copyBackPBEInitializationVector(JNIEnv *env, CK_MECHANISM *ckMechanism, job
}
}
+#define PBKD2_PARAM_SET(member, value) \
+ do { \
+ if(ckParamPtr->version == PARAMS) { \
+ ckParamPtr->params.v1.member = value; \
+ } else { \
+ ckParamPtr->params.v2.member = value; \
+ } \
+ } while(0)
+
+#define PBKD2_PARAM_ADDR(member) \
+ ( \
+ (ckParamPtr->version == PARAMS) ? \
+ (void*) &ckParamPtr->params.v1.member : \
+ (void*) &ckParamPtr->params.v2.member \
+ )
+
/*
- * converts the Java CK_PKCS5_PBKD2_PARAMS object to a CK_PKCS5_PBKD2_PARAMS
+ * converts a Java CK_PKCS5_PBKD2_PARAMS object to a CK_PKCS5_PBKD2_PARAMS
+ * pointer, or a Java CK_PKCS5_PBKD2_PARAMS2 object to a CK_PKCS5_PBKD2_PARAMS2
* pointer
*
- * @param env - used to call JNI funktions to get the Java classes and objects
- * @param jParam - the Java CK_PKCS5_PBKD2_PARAMS object to convert
+ * @param env - used to call JNI functions to get the Java classes and objects
+ * @param jParam - the Java object to convert
* @param pLength - length of the allocated memory of the returned pointer
- * @return pointer to the new CK_PKCS5_PBKD2_PARAMS structure
+ * @return pointer to the new structure
*/
-CK_PKCS5_PBKD2_PARAMS_PTR
+CK_VOID_PTR
jPkcs5Pbkd2ParamToCKPkcs5Pbkd2ParamPtr(JNIEnv *env, jobject jParam, CK_ULONG *pLength)
{
- CK_PKCS5_PBKD2_PARAMS_PTR ckParamPtr;
+ VersionedPbkd2ParamsPtr ckParamPtr;
+ ParamVersion paramVersion;
+ CK_ULONG_PTR pUlPasswordLen;
jclass jPkcs5Pbkd2ParamsClass;
jfieldID fieldID;
jlong jSaltSource, jIteration, jPrf;
- jobject jSaltSourceData, jPrfData;
+ jobject jSaltSourceData, jPrfData, jPassword;
if (pLength != NULL) {
*pLength = 0L;
}
// retrieve java values
- jPkcs5Pbkd2ParamsClass = (*env)->FindClass(env, CLASS_PKCS5_PBKD2_PARAMS);
- if (jPkcs5Pbkd2ParamsClass == NULL) { return NULL; }
+ if ((jPkcs5Pbkd2ParamsClass =
+ (*env)->FindClass(env, CLASS_PKCS5_PBKD2_PARAMS)) != NULL
+ && (*env)->IsInstanceOf(env, jParam, jPkcs5Pbkd2ParamsClass)) {
+ paramVersion = PARAMS;
+ } else if ((jPkcs5Pbkd2ParamsClass =
+ (*env)->FindClass(env, CLASS_PKCS5_PBKD2_PARAMS2)) != NULL
+ && (*env)->IsInstanceOf(env, jParam, jPkcs5Pbkd2ParamsClass)) {
+ paramVersion = PARAMS2;
+ } else {
+ return NULL;
+ }
fieldID = (*env)->GetFieldID(env, jPkcs5Pbkd2ParamsClass, "saltSource", "J");
if (fieldID == NULL) { return NULL; }
jSaltSource = (*env)->GetLongField(env, jParam, fieldID);
@@ -1807,36 +1839,60 @@ jPkcs5Pbkd2ParamToCKPkcs5Pbkd2ParamPtr(JNIEnv *env, jobject jParam, CK_ULONG *pL
fieldID = (*env)->GetFieldID(env, jPkcs5Pbkd2ParamsClass, "pPrfData", "[B");
if (fieldID == NULL) { return NULL; }
jPrfData = (*env)->GetObjectField(env, jParam, fieldID);
+ fieldID = (*env)->GetFieldID(env, jPkcs5Pbkd2ParamsClass, "pPassword", "[C");
+ if (fieldID == NULL) { return NULL; }
+ jPassword = (*env)->GetObjectField(env, jParam, fieldID);
- // allocate memory for CK_PKCS5_PBKD2_PARAMS pointer
- ckParamPtr = calloc(1, sizeof(CK_PKCS5_PBKD2_PARAMS));
+ // allocate memory for VersionedPbkd2Params and store the structure version
+ ckParamPtr = calloc(1, sizeof(VersionedPbkd2Params));
if (ckParamPtr == NULL) {
throwOutOfMemoryError(env, 0);
return NULL;
}
+ ckParamPtr->version = paramVersion;
// populate using java values
- ckParamPtr->saltSource = jLongToCKULong(jSaltSource);
- jByteArrayToCKByteArray(env, jSaltSourceData, (CK_BYTE_PTR *)
- &(ckParamPtr->pSaltSourceData), &(ckParamPtr->ulSaltSourceDataLen));
+ PBKD2_PARAM_SET(saltSource, jLongToCKULong(jSaltSource));
+ jByteArrayToCKByteArray(env, jSaltSourceData,
+ (CK_BYTE_PTR *) PBKD2_PARAM_ADDR(pSaltSourceData),
+ PBKD2_PARAM_ADDR(ulSaltSourceDataLen));
if ((*env)->ExceptionCheck(env)) {
goto cleanup;
}
- ckParamPtr->iterations = jLongToCKULong(jIteration);
- ckParamPtr->prf = jLongToCKULong(jPrf);
- jByteArrayToCKByteArray(env, jPrfData, (CK_BYTE_PTR *)
- &(ckParamPtr->pPrfData), &(ckParamPtr->ulPrfDataLen));
+ PBKD2_PARAM_SET(iterations, jLongToCKULong(jIteration));
+ PBKD2_PARAM_SET(prf, jLongToCKULong(jPrf));
+ jByteArrayToCKByteArray(env, jPrfData,
+ (CK_BYTE_PTR *) PBKD2_PARAM_ADDR(pPrfData),
+ PBKD2_PARAM_ADDR(ulPrfDataLen));
+ if ((*env)->ExceptionCheck(env)) {
+ goto cleanup;
+ }
+ if (ckParamPtr->version == PARAMS) {
+ pUlPasswordLen = calloc(1, sizeof(CK_ULONG));
+ if (pUlPasswordLen == NULL) {
+ throwOutOfMemoryError(env, 0);
+ goto cleanup;
+ }
+ ckParamPtr->params.v1.ulPasswordLen = pUlPasswordLen;
+ } else {
+ pUlPasswordLen = &ckParamPtr->params.v2.ulPasswordLen;
+ }
+ jCharArrayToCKUTF8CharArray(env, jPassword,
+ (CK_CHAR_PTR *) PBKD2_PARAM_ADDR(pPassword),
+ pUlPasswordLen);
if ((*env)->ExceptionCheck(env)) {
goto cleanup;
}
if (pLength != NULL) {
- *pLength = sizeof(CK_PKCS5_PBKD2_PARAMS);
+ *pLength = (ckParamPtr->version == PARAMS ?
+ sizeof(ckParamPtr->params.v1) :
+ sizeof(ckParamPtr->params.v2));
}
+ // VersionedPbkd2ParamsPtr is equivalent to CK_PKCS5_PBKD2_PARAMS[2]_PTR
return ckParamPtr;
cleanup:
- free(ckParamPtr->pSaltSourceData);
- free(ckParamPtr->pPrfData);
+ FREE_VERSIONED_PBKD2_MEMBERS(ckParamPtr);
free(ckParamPtr);
return NULL;
diff --git a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_util.c b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_util.c
index 520bd52a2cd..aa76945283d 100644
--- a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_util.c
+++ b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_util.c
@@ -410,11 +410,27 @@ void freeCKMechanismPtr(CK_MECHANISM_PTR mechPtr) {
case CKM_CAMELLIA_CTR:
// params do not contain pointers
break;
+ case CKM_PKCS5_PBKD2:
+ // get the versioned structure from behind memory
+ TRACE0(((VersionedPbkd2ParamsPtr)tmp)->version == PARAMS ?
+ "[ CK_PKCS5_PBKD2_PARAMS ]\n" :
+ "[ CK_PKCS5_PBKD2_PARAMS2 ]\n");
+ FREE_VERSIONED_PBKD2_MEMBERS((VersionedPbkd2ParamsPtr)tmp);
+ break;
+ case CKM_PBA_SHA1_WITH_SHA1_HMAC:
+ case CKM_NSS_PKCS12_PBE_SHA224_HMAC_KEY_GEN:
+ case CKM_NSS_PKCS12_PBE_SHA256_HMAC_KEY_GEN:
+ case CKM_NSS_PKCS12_PBE_SHA384_HMAC_KEY_GEN:
+ case CKM_NSS_PKCS12_PBE_SHA512_HMAC_KEY_GEN:
+ free(((CK_PBE_PARAMS_PTR)tmp)->pInitVector);
+ free(((CK_PBE_PARAMS_PTR)tmp)->pPassword);
+ free(((CK_PBE_PARAMS_PTR)tmp)->pSalt);
+ break;
default:
// currently unsupported mechs by SunPKCS11 provider
// CKM_RSA_PKCS_OAEP, CKM_ECMQV_DERIVE,
// CKM_X9_42_*, CKM_KEA_DERIVE, CKM_RC2_*, CKM_RC5_*,
- // CKM_SKIPJACK_*, CKM_KEY_WRAP_SET_OAEP, CKM_PKCS5_PBKD2,
+ // CKM_SKIPJACK_*, CKM_KEY_WRAP_SET_OAEP,
// PBE mechs, WTLS mechs, CMS mechs,
// CKM_EXTRACT_KEY_FROM_KEY, CKM_OTP, CKM_KIP,
// CKM_DSA_PARAMETER_GEN?, CKM_GOSTR3410_*
@@ -517,12 +533,11 @@ void jBooleanArrayToCKBBoolArray(JNIEnv *env, const jbooleanArray jArray, CK_BBO
jboolean* jpTemp;
CK_ULONG i;
- if(jArray == NULL) {
+ *ckpLength = jArray == NULL ? 0L : (*env)->GetArrayLength(env, jArray);
+ if(*ckpLength == 0L) {
*ckpArray = NULL_PTR;
- *ckpLength = 0L;
return;
}
- *ckpLength = (*env)->GetArrayLength(env, jArray);
jpTemp = (jboolean*) calloc(*ckpLength, sizeof(jboolean));
if (jpTemp == NULL) {
throwOutOfMemoryError(env, 0);
@@ -559,12 +574,11 @@ void jByteArrayToCKByteArray(JNIEnv *env, const jbyteArray jArray, CK_BYTE_PTR *
jbyte* jpTemp;
CK_ULONG i;
- if(jArray == NULL) {
+ *ckpLength = jArray == NULL ? 0L : (*env)->GetArrayLength(env, jArray);
+ if(*ckpLength == 0L) {
*ckpArray = NULL_PTR;
- *ckpLength = 0L;
return;
}
- *ckpLength = (*env)->GetArrayLength(env, jArray);
jpTemp = (jbyte*) calloc(*ckpLength, sizeof(jbyte));
if (jpTemp == NULL) {
throwOutOfMemoryError(env, 0);
@@ -606,12 +620,11 @@ void jLongArrayToCKULongArray(JNIEnv *env, const jlongArray jArray, CK_ULONG_PTR
jlong* jTemp;
CK_ULONG i;
- if(jArray == NULL) {
+ *ckpLength = jArray == NULL ? 0L : (*env)->GetArrayLength(env, jArray);
+ if(*ckpLength == 0L) {
*ckpArray = NULL_PTR;
- *ckpLength = 0L;
return;
}
- *ckpLength = (*env)->GetArrayLength(env, jArray);
jTemp = (jlong*) calloc(*ckpLength, sizeof(jlong));
if (jTemp == NULL) {
throwOutOfMemoryError(env, 0);
@@ -648,12 +661,11 @@ void jCharArrayToCKCharArray(JNIEnv *env, const jcharArray jArray, CK_CHAR_PTR *
jchar* jpTemp;
CK_ULONG i;
- if(jArray == NULL) {
+ *ckpLength = jArray == NULL ? 0L : (*env)->GetArrayLength(env, jArray);
+ if(*ckpLength == 0L) {
*ckpArray = NULL_PTR;
- *ckpLength = 0L;
return;
}
- *ckpLength = (*env)->GetArrayLength(env, jArray);
jpTemp = (jchar*) calloc(*ckpLength, sizeof(jchar));
if (jpTemp == NULL) {
throwOutOfMemoryError(env, 0);
@@ -690,12 +702,11 @@ void jCharArrayToCKUTF8CharArray(JNIEnv *env, const jcharArray jArray, CK_UTF8CH
jchar* jTemp;
CK_ULONG i;
- if(jArray == NULL) {
+ *ckpLength = jArray == NULL ? 0L : (*env)->GetArrayLength(env, jArray);
+ if(*ckpLength == 0L) {
*ckpArray = NULL_PTR;
- *ckpLength = 0L;
return;
}
- *ckpLength = (*env)->GetArrayLength(env, jArray);
jTemp = (jchar*) calloc(*ckpLength, sizeof(jchar));
if (jTemp == NULL) {
throwOutOfMemoryError(env, 0);
diff --git a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/pkcs11wrapper.h b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/pkcs11wrapper.h
index eb6d01b9e47..450e4d27d62 100644
--- a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/pkcs11wrapper.h
+++ b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/pkcs11wrapper.h
@@ -68,6 +68,7 @@
/* extra PKCS#11 constants not in the standard include files */
#define CKA_NETSCAPE_BASE (0x80000000 + 0x4E534350)
+/* ^ now known as CKM_NSS (CKM_VENDOR_DEFINED | NSSCK_VENDOR_NSS) */
#define CKA_NETSCAPE_TRUST_BASE (CKA_NETSCAPE_BASE + 0x2000)
#define CKA_NETSCAPE_TRUST_SERVER_AUTH (CKA_NETSCAPE_TRUST_BASE + 8)
#define CKA_NETSCAPE_TRUST_CLIENT_AUTH (CKA_NETSCAPE_TRUST_BASE + 9)
@@ -76,6 +77,12 @@
#define CKA_NETSCAPE_DB 0xD5A0DB00
#define CKM_NSS_TLS_PRF_GENERAL 0x80000373
+/* additional PKCS #12 PBE key derivation algorithms defined in NSS v3.29 */
+#define CKM_NSS_PKCS12_PBE_SHA224_HMAC_KEY_GEN (CKA_NETSCAPE_BASE + 29)
+#define CKM_NSS_PKCS12_PBE_SHA256_HMAC_KEY_GEN (CKA_NETSCAPE_BASE + 30)
+#define CKM_NSS_PKCS12_PBE_SHA384_HMAC_KEY_GEN (CKA_NETSCAPE_BASE + 31)
+#define CKM_NSS_PKCS12_PBE_SHA512_HMAC_KEY_GEN (CKA_NETSCAPE_BASE + 32)
+
/*
Define the PKCS#11 functions to include and exclude. Reduces the size
@@ -265,6 +272,7 @@ void printDebug(const char *format, ...);
#define CLASS_PBE_PARAMS "sun/security/pkcs11/wrapper/CK_PBE_PARAMS"
#define PBE_INIT_VECTOR_SIZE 8
#define CLASS_PKCS5_PBKD2_PARAMS "sun/security/pkcs11/wrapper/CK_PKCS5_PBKD2_PARAMS"
+#define CLASS_PKCS5_PBKD2_PARAMS2 "sun/security/pkcs11/wrapper/CK_PKCS5_PBKD2_PARAMS2"
#define CLASS_EXTRACT_PARAMS "sun/security/pkcs11/wrapper/CK_EXTRACT_PARAMS"
#define CLASS_ECDH1_DERIVE_PARAMS "sun/security/pkcs11/wrapper/CK_ECDH1_DERIVE_PARAMS"
@@ -378,7 +386,7 @@ CK_VOID_PTR jMechParamToCKMechParamPtr(JNIEnv *env, jobject jParam, CK_MECHANISM
CK_RSA_PKCS_OAEP_PARAMS_PTR jRsaPkcsOaepParamToCKRsaPkcsOaepParamPtr(JNIEnv *env,
jobject jParam, CK_ULONG* pLength);
CK_PBE_PARAMS_PTR jPbeParamToCKPbeParamPtr(JNIEnv *env, jobject jParam, CK_ULONG* pLength);
-CK_PKCS5_PBKD2_PARAMS_PTR jPkcs5Pbkd2ParamToCKPkcs5Pbkd2ParamPtr(JNIEnv *env, jobject jParam, CK_ULONG* pLength);
+CK_VOID_PTR jPkcs5Pbkd2ParamToCKPkcs5Pbkd2ParamPtr(JNIEnv *env, jobject jParam, CK_ULONG* pLength);
CK_SSL3_MASTER_KEY_DERIVE_PARAMS_PTR jSsl3MasterKeyDeriveParamToCKSsl3MasterKeyDeriveParamPtr(JNIEnv *env, jobject jParam, CK_ULONG* pLength);
CK_SSL3_KEY_MAT_PARAMS_PTR jSsl3KeyMatParamToCKSsl3KeyMatParamPtr(JNIEnv *env, jobject jParam, CK_ULONG* pLength);
CK_KEY_DERIVATION_STRING_DATA jKeyDerivationStringDataToCKKeyDerivationStringData(JNIEnv *env, jobject jParam);
@@ -388,6 +396,31 @@ CK_ECDH2_DERIVE_PARAMS_PTR jEcdh2DeriveParamToCKEcdh2DeriveParamPtr(JNIEnv *env,
CK_X9_42_DH1_DERIVE_PARAMS_PTR jX942Dh1DeriveParamToCKX942Dh1DeriveParamPtr(JNIEnv *env, jobject jParam, CK_ULONG* pLength);
CK_X9_42_DH2_DERIVE_PARAMS_PTR jX942Dh2DeriveParamToCKX942Dh2DeriveParamPtr(JNIEnv *env, jobject jParam, CK_ULONG* pLength);
+/* handling of CK_PKCS5_PBKD2_PARAMS and CK_PKCS5_PBKD2_PARAMS2 */
+typedef enum {PARAMS=0, PARAMS2} ParamVersion;
+
+typedef struct {
+ union {
+ CK_PKCS5_PBKD2_PARAMS v1;
+ CK_PKCS5_PBKD2_PARAMS2 v2;
+ } params;
+ ParamVersion version;
+} VersionedPbkd2Params, *VersionedPbkd2ParamsPtr;
+
+#define FREE_VERSIONED_PBKD2_MEMBERS(verParamsPtr) \
+ do { \
+ if ((verParamsPtr)->version == PARAMS) { \
+ free((verParamsPtr)->params.v1.pSaltSourceData); \
+ free((verParamsPtr)->params.v1.pPrfData); \
+ free((verParamsPtr)->params.v1.pPassword); \
+ free((verParamsPtr)->params.v1.ulPasswordLen); \
+ } else { \
+ free((verParamsPtr)->params.v2.pSaltSourceData); \
+ free((verParamsPtr)->params.v2.pPrfData); \
+ free((verParamsPtr)->params.v2.pPassword); \
+ } \
+ } while(0)
+
/* functions to copy the returned values inside CK-mechanism back to Java object */
void copyBackPBEInitializationVector(JNIEnv *env, CK_MECHANISM *ckMechanism, jobject jMechanism);
diff --git a/src/jdk.crypto.ec/share/classes/sun/security/ec/SunEC.java b/src/jdk.crypto.ec/share/classes/sun/security/ec/SunEC.java
index 8c9e4f9dbe6..883dc04758e 100644
--- a/src/jdk.crypto.ec/share/classes/sun/security/ec/SunEC.java
+++ b/src/jdk.crypto.ec/share/classes/sun/security/ec/SunEC.java
@@ -38,6 +38,7 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
+import jdk.internal.access.SharedSecrets;
import sun.security.ec.ed.EdDSAAlgorithmParameters;
import sun.security.ec.ed.EdDSAKeyFactory;
import sun.security.ec.ed.EdDSAKeyPairGenerator;
@@ -56,6 +57,10 @@ public final class SunEC extends Provider {
private static final long serialVersionUID = -2279741672933606418L;
+ private static final boolean systemFipsEnabled =
+ SharedSecrets.getJavaSecuritySystemConfiguratorAccess()
+ .isSystemFipsEnabled();
+
private static class ProviderServiceA extends ProviderService {
ProviderServiceA(Provider p, String type, String algo, String cn,
HashMap<String, String> attrs) {
@@ -249,85 +254,86 @@ public final class SunEC extends Provider {
putXDHEntries();
putEdDSAEntries();
-
- /*
- * Signature engines
- */
- putService(new ProviderService(this, "Signature",
- "NONEwithECDSA", "sun.security.ec.ECDSASignature$Raw",
- null, ATTRS));
- putService(new ProviderServiceA(this, "Signature",
- "SHA1withECDSA", "sun.security.ec.ECDSASignature$SHA1",
- ATTRS));
- putService(new ProviderServiceA(this, "Signature",
- "SHA224withECDSA", "sun.security.ec.ECDSASignature$SHA224",
- ATTRS));
- putService(new ProviderServiceA(this, "Signature",
- "SHA256withECDSA", "sun.security.ec.ECDSASignature$SHA256",
- ATTRS));
- putService(new ProviderServiceA(this, "Signature",
- "SHA384withECDSA", "sun.security.ec.ECDSASignature$SHA384",
- ATTRS));
- putService(new ProviderServiceA(this, "Signature",
- "SHA512withECDSA", "sun.security.ec.ECDSASignature$SHA512",
- ATTRS));
- putService(new ProviderServiceA(this, "Signature",
- "SHA3-224withECDSA", "sun.security.ec.ECDSASignature$SHA3_224",
- ATTRS));
- putService(new ProviderServiceA(this, "Signature",
- "SHA3-256withECDSA", "sun.security.ec.ECDSASignature$SHA3_256",
- ATTRS));
- putService(new ProviderServiceA(this, "Signature",
- "SHA3-384withECDSA", "sun.security.ec.ECDSASignature$SHA3_384",
- ATTRS));
- putService(new ProviderServiceA(this, "Signature",
- "SHA3-512withECDSA", "sun.security.ec.ECDSASignature$SHA3_512",
- ATTRS));
-
- putService(new ProviderService(this, "Signature",
- "NONEwithECDSAinP1363Format",
- "sun.security.ec.ECDSASignature$RawinP1363Format"));
- putService(new ProviderService(this, "Signature",
- "SHA1withECDSAinP1363Format",
- "sun.security.ec.ECDSASignature$SHA1inP1363Format"));
- putService(new ProviderService(this, "Signature",
- "SHA224withECDSAinP1363Format",
- "sun.security.ec.ECDSASignature$SHA224inP1363Format"));
- putService(new ProviderService(this, "Signature",
- "SHA256withECDSAinP1363Format",
- "sun.security.ec.ECDSASignature$SHA256inP1363Format"));
- putService(new ProviderService(this, "Signature",
- "SHA384withECDSAinP1363Format",
- "sun.security.ec.ECDSASignature$SHA384inP1363Format"));
- putService(new ProviderService(this, "Signature",
- "SHA512withECDSAinP1363Format",
- "sun.security.ec.ECDSASignature$SHA512inP1363Format"));
-
- putService(new ProviderService(this, "Signature",
- "SHA3-224withECDSAinP1363Format",
- "sun.security.ec.ECDSASignature$SHA3_224inP1363Format"));
- putService(new ProviderService(this, "Signature",
- "SHA3-256withECDSAinP1363Format",
- "sun.security.ec.ECDSASignature$SHA3_256inP1363Format"));
- putService(new ProviderService(this, "Signature",
- "SHA3-384withECDSAinP1363Format",
- "sun.security.ec.ECDSASignature$SHA3_384inP1363Format"));
- putService(new ProviderService(this, "Signature",
- "SHA3-512withECDSAinP1363Format",
- "sun.security.ec.ECDSASignature$SHA3_512inP1363Format"));
-
- /*
- * Key Pair Generator engine
- */
- putService(new ProviderService(this, "KeyPairGenerator",
- "EC", "sun.security.ec.ECKeyPairGenerator",
- List.of("EllipticCurve"), ATTRS));
-
- /*
- * Key Agreement engine
- */
- putService(new ProviderService(this, "KeyAgreement",
- "ECDH", "sun.security.ec.ECDHKeyAgreement", null, ATTRS));
+ if (!systemFipsEnabled) {
+ /*
+ * Signature engines
+ */
+ putService(new ProviderService(this, "Signature",
+ "NONEwithECDSA", "sun.security.ec.ECDSASignature$Raw",
+ null, ATTRS));
+ putService(new ProviderServiceA(this, "Signature",
+ "SHA1withECDSA", "sun.security.ec.ECDSASignature$SHA1",
+ ATTRS));
+ putService(new ProviderServiceA(this, "Signature",
+ "SHA224withECDSA", "sun.security.ec.ECDSASignature$SHA224",
+ ATTRS));
+ putService(new ProviderServiceA(this, "Signature",
+ "SHA256withECDSA", "sun.security.ec.ECDSASignature$SHA256",
+ ATTRS));
+ putService(new ProviderServiceA(this, "Signature",
+ "SHA384withECDSA", "sun.security.ec.ECDSASignature$SHA384",
+ ATTRS));
+ putService(new ProviderServiceA(this, "Signature",
+ "SHA512withECDSA", "sun.security.ec.ECDSASignature$SHA512",
+ ATTRS));
+ putService(new ProviderServiceA(this, "Signature",
+ "SHA3-224withECDSA", "sun.security.ec.ECDSASignature$SHA3_224",
+ ATTRS));
+ putService(new ProviderServiceA(this, "Signature",
+ "SHA3-256withECDSA", "sun.security.ec.ECDSASignature$SHA3_256",
+ ATTRS));
+ putService(new ProviderServiceA(this, "Signature",
+ "SHA3-384withECDSA", "sun.security.ec.ECDSASignature$SHA3_384",
+ ATTRS));
+ putService(new ProviderServiceA(this, "Signature",
+ "SHA3-512withECDSA", "sun.security.ec.ECDSASignature$SHA3_512",
+ ATTRS));
+
+ putService(new ProviderService(this, "Signature",
+ "NONEwithECDSAinP1363Format",
+ "sun.security.ec.ECDSASignature$RawinP1363Format"));
+ putService(new ProviderService(this, "Signature",
+ "SHA1withECDSAinP1363Format",
+ "sun.security.ec.ECDSASignature$SHA1inP1363Format"));
+ putService(new ProviderService(this, "Signature",
+ "SHA224withECDSAinP1363Format",
+ "sun.security.ec.ECDSASignature$SHA224inP1363Format"));
+ putService(new ProviderService(this, "Signature",
+ "SHA256withECDSAinP1363Format",
+ "sun.security.ec.ECDSASignature$SHA256inP1363Format"));
+ putService(new ProviderService(this, "Signature",
+ "SHA384withECDSAinP1363Format",
+ "sun.security.ec.ECDSASignature$SHA384inP1363Format"));
+ putService(new ProviderService(this, "Signature",
+ "SHA512withECDSAinP1363Format",
+ "sun.security.ec.ECDSASignature$SHA512inP1363Format"));
+
+ putService(new ProviderService(this, "Signature",
+ "SHA3-224withECDSAinP1363Format",
+ "sun.security.ec.ECDSASignature$SHA3_224inP1363Format"));
+ putService(new ProviderService(this, "Signature",
+ "SHA3-256withECDSAinP1363Format",
+ "sun.security.ec.ECDSASignature$SHA3_256inP1363Format"));
+ putService(new ProviderService(this, "Signature",
+ "SHA3-384withECDSAinP1363Format",
+ "sun.security.ec.ECDSASignature$SHA3_384inP1363Format"));
+ putService(new ProviderService(this, "Signature",
+ "SHA3-512withECDSAinP1363Format",
+ "sun.security.ec.ECDSASignature$SHA3_512inP1363Format"));
+
+ /*
+ * Key Pair Generator engine
+ */
+ putService(new ProviderService(this, "KeyPairGenerator",
+ "EC", "sun.security.ec.ECKeyPairGenerator",
+ List.of("EllipticCurve"), ATTRS));
+
+ /*
+ * Key Agreement engine
+ */
+ putService(new ProviderService(this, "KeyAgreement",
+ "ECDH", "sun.security.ec.ECDHKeyAgreement", null, ATTRS));
+ }
}
private void putXDHEntries() {
@@ -344,23 +350,25 @@ public final class SunEC extends Provider {
"X448", "sun.security.ec.XDHKeyFactory.X448",
ATTRS));
- putService(new ProviderService(this, "KeyPairGenerator",
- "XDH", "sun.security.ec.XDHKeyPairGenerator", null, ATTRS));
- putService(new ProviderServiceA(this, "KeyPairGenerator",
- "X25519", "sun.security.ec.XDHKeyPairGenerator.X25519",
- ATTRS));
- putService(new ProviderServiceA(this, "KeyPairGenerator",
- "X448", "sun.security.ec.XDHKeyPairGenerator.X448",
- ATTRS));
-
- putService(new ProviderService(this, "KeyAgreement",
- "XDH", "sun.security.ec.XDHKeyAgreement", null, ATTRS));
- putService(new ProviderServiceA(this, "KeyAgreement",
- "X25519", "sun.security.ec.XDHKeyAgreement.X25519",
- ATTRS));
- putService(new ProviderServiceA(this, "KeyAgreement",
- "X448", "sun.security.ec.XDHKeyAgreement.X448",
- ATTRS));
+ if (!systemFipsEnabled) {
+ putService(new ProviderService(this, "KeyPairGenerator",
+ "XDH", "sun.security.ec.XDHKeyPairGenerator", null, ATTRS));
+ putService(new ProviderServiceA(this, "KeyPairGenerator",
+ "X25519", "sun.security.ec.XDHKeyPairGenerator.X25519",
+ ATTRS));
+ putService(new ProviderServiceA(this, "KeyPairGenerator",
+ "X448", "sun.security.ec.XDHKeyPairGenerator.X448",
+ ATTRS));
+
+ putService(new ProviderService(this, "KeyAgreement",
+ "XDH", "sun.security.ec.XDHKeyAgreement", null, ATTRS));
+ putService(new ProviderServiceA(this, "KeyAgreement",
+ "X25519", "sun.security.ec.XDHKeyAgreement.X25519",
+ ATTRS));
+ putService(new ProviderServiceA(this, "KeyAgreement",
+ "X448", "sun.security.ec.XDHKeyAgreement.X448",
+ ATTRS));
+ }
}
private void putEdDSAEntries() {
@@ -375,21 +383,23 @@ public final class SunEC extends Provider {
putService(new ProviderServiceA(this, "KeyFactory",
"Ed448", "sun.security.ec.ed.EdDSAKeyFactory.Ed448", ATTRS));
- putService(new ProviderService(this, "KeyPairGenerator",
- "EdDSA", "sun.security.ec.ed.EdDSAKeyPairGenerator", null, ATTRS));
- putService(new ProviderServiceA(this, "KeyPairGenerator",
- "Ed25519", "sun.security.ec.ed.EdDSAKeyPairGenerator.Ed25519",
- ATTRS));
- putService(new ProviderServiceA(this, "KeyPairGenerator",
- "Ed448", "sun.security.ec.ed.EdDSAKeyPairGenerator.Ed448",
- ATTRS));
-
- putService(new ProviderService(this, "Signature",
- "EdDSA", "sun.security.ec.ed.EdDSASignature", null, ATTRS));
- putService(new ProviderServiceA(this, "Signature",
- "Ed25519", "sun.security.ec.ed.EdDSASignature.Ed25519", ATTRS));
- putService(new ProviderServiceA(this, "Signature",
- "Ed448", "sun.security.ec.ed.EdDSASignature.Ed448", ATTRS));
+ if (!systemFipsEnabled) {
+ putService(new ProviderService(this, "KeyPairGenerator",
+ "EdDSA", "sun.security.ec.ed.EdDSAKeyPairGenerator", null, ATTRS));
+ putService(new ProviderServiceA(this, "KeyPairGenerator",
+ "Ed25519", "sun.security.ec.ed.EdDSAKeyPairGenerator.Ed25519",
+ ATTRS));
+ putService(new ProviderServiceA(this, "KeyPairGenerator",
+ "Ed448", "sun.security.ec.ed.EdDSAKeyPairGenerator.Ed448",
+ ATTRS));
+
+ putService(new ProviderService(this, "Signature",
+ "EdDSA", "sun.security.ec.ed.EdDSASignature", null, ATTRS));
+ putService(new ProviderServiceA(this, "Signature",
+ "Ed25519", "sun.security.ec.ed.EdDSASignature.Ed25519", ATTRS));
+ putService(new ProviderServiceA(this, "Signature",
+ "Ed448", "sun.security.ec.ed.EdDSASignature.Ed448", ATTRS));
+ }
}
}
diff --git a/test/jdk/sun/security/pkcs11/Cipher/PBECipher.java b/test/jdk/sun/security/pkcs11/Cipher/PBECipher.java
new file mode 100644
index 00000000000..a184a169732
--- /dev/null
+++ b/test/jdk/sun/security/pkcs11/Cipher/PBECipher.java
@@ -0,0 +1,233 @@
+/*
+ * Copyright (c) 2022, Red Hat, Inc.
+ *
+ * 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 java.math.BigInteger;
+import java.security.AlgorithmParameters;
+import java.security.NoSuchAlgorithmException;
+import java.security.Provider;
+import java.security.SecureRandom;
+import java.security.Security;
+import java.util.Map;
+
+import javax.crypto.Cipher;
+import javax.crypto.SecretKey;
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.interfaces.PBEKey;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.PBEKeySpec;
+import javax.crypto.spec.PBEParameterSpec;
+
+/*
+ * @test
+ * @bug 9999999
+ * @summary test password based encryption on SunPKCS11's Cipher service
+ * @requires (jdk.version.major >= 8)
+ * @library /test/lib ..
+ * @run main/othervm/timeout=30 PBECipher
+ */
+
+public final class PBECipher {
+ public static void main(String[] args) throws Exception {
+ java.security.Security.getProviders();
+ PBECipher2.main(args);
+ }
+}
+
+final class PBECipher2 extends PKCS11Test {
+ private static final char[] password = "123456".toCharArray();
+ private static final byte[] salt = "abcdefgh".getBytes();
+ private static final byte[] iv = new byte[16];
+ private static final int iterations = 1000;
+ private static final String plainText = "This is a know plain text!";
+ private static final String sep =
+ "=========================================================================";
+
+ private static enum Configuration {
+ // Provide salt and iterations through a PBEParameterSpec instance
+ PBEParameterSpec,
+
+ // Provide salt and iterations through a AlgorithmParameters instance
+ AlgorithmParameters,
+
+ // Provide salt and iterations through an anonymous class implementing
+ // the javax.crypto.interfaces.PBEKey interface
+ AnonymousPBEKey,
+ }
+
+ private static Provider sunJCE = Security.getProvider("SunJCE");
+
+ // Generated with SunJCE
+ private static final Map<String, BigInteger> assertionData = Map.of(
+ "PBEWithHmacSHA1AndAES_128", new BigInteger("8eebe98a580fb09d026" +
+ "dbfe60b3733b079e0de9ea7b0b1ccba011a1652d1e257", 16),
+ "PBEWithHmacSHA224AndAES_128", new BigInteger("1cbabdeb5d483af4a" +
+ "841942f4b1095b7d6f60e46fabfd2609c015adc38cc227", 16),
+ "PBEWithHmacSHA256AndAES_128", new BigInteger("4d82f6591df3508d2" +
+ "4531f06cdc4f90f4bdab7aeb07fbb57a3712e999d5b6f59", 16),
+ "PBEWithHmacSHA384AndAES_128", new BigInteger("3a0ed0959d51f40b9" +
+ "ba9f506a5277f430521f2fbe1ba94bae368835f221b6cb9", 16),
+ "PBEWithHmacSHA512AndAES_128", new BigInteger("1388287a446009309" +
+ "1418f4eca3ba1735b1fa025423d74ced36ce578d8ebf9da", 16),
+ "PBEWithHmacSHA1AndAES_256", new BigInteger("80f8208daab27ed02dd" +
+ "8a354ef6f23ff7813c84dd1c8a1b081d6f4dee27182a2", 16),
+ "PBEWithHmacSHA224AndAES_256", new BigInteger("7e3b9ce20aec2e52f" +
+ "f6c781602d4f79a55a88495b5217f1e22e1a068268e6247", 16),
+ "PBEWithHmacSHA256AndAES_256", new BigInteger("9d6a8b6a351dfd0dd" +
+ "9e9f45924b2860dca7719c4c07e207a64ebc1acd16cc157", 16),
+ "PBEWithHmacSHA384AndAES_256", new BigInteger("6f1b386cee3a8e2d9" +
+ "8c2e81828da0467dec8b989d22258efeab5932580d01d53", 16),
+ "PBEWithHmacSHA512AndAES_256", new BigInteger("30aaa346b2edd394f" +
+ "50916187876ac32f1287b19d55c5eea6f7ef9b84aaf291e", 16)
+ );
+
+ private static final class NoRandom extends SecureRandom {
+ @Override
+ public void nextBytes(byte[] bytes) {
+ return;
+ }
+ }
+
+ public void main(Provider sunPKCS11) throws Exception {
+ System.out.println("SunPKCS11: " + sunPKCS11.getName());
+ for (Configuration conf : Configuration.values()) {
+ testWith(sunPKCS11, "PBEWithHmacSHA1AndAES_128", conf);
+ testWith(sunPKCS11, "PBEWithHmacSHA224AndAES_128", conf);
+ testWith(sunPKCS11, "PBEWithHmacSHA256AndAES_128", conf);
+ testWith(sunPKCS11, "PBEWithHmacSHA384AndAES_128", conf);
+ testWith(sunPKCS11, "PBEWithHmacSHA512AndAES_128", conf);
+ testWith(sunPKCS11, "PBEWithHmacSHA1AndAES_256", conf);
+ testWith(sunPKCS11, "PBEWithHmacSHA224AndAES_256", conf);
+ testWith(sunPKCS11, "PBEWithHmacSHA256AndAES_256", conf);
+ testWith(sunPKCS11, "PBEWithHmacSHA384AndAES_256", conf);
+ testWith(sunPKCS11, "PBEWithHmacSHA512AndAES_256", conf);
+ }
+ System.out.println("TEST PASS - OK");
+ }
+
+ private void testWith(Provider sunPKCS11, String algorithm,
+ Configuration conf) throws Exception {
+ System.out.println(sep + System.lineSeparator() + algorithm
+ + " (with " + conf.name() + ")");
+
+ Cipher pbeCipher = getCipher(sunPKCS11, algorithm, conf);
+ BigInteger cipherText = new BigInteger(1, pbeCipher.doFinal(
+ plainText.getBytes()));
+ printByteArray("Cipher Text", cipherText);
+
+ BigInteger expectedCipherText = null;
+ if (sunJCE != null) {
+ Cipher c = getCipher(sunJCE, algorithm, conf);
+ if (c != null) {
+ expectedCipherText = new BigInteger(1, c.doFinal(
+ plainText.getBytes()));
+ } else {
+ // Move to assertionData as it's unlikely that any of
+ // the algorithms are available.
+ sunJCE = null;
+ }
+ }
+ if (expectedCipherText == null) {
+ // If SunJCE or the algorithm are not available, assertionData
+ // is used instead.
+ expectedCipherText = assertionData.get(algorithm);
+ }
+
+ if (!cipherText.equals(expectedCipherText)) {
+ printByteArray("Expected Cipher Text", expectedCipherText);
+ throw new Exception("Expected Cipher Text did not match");
+ }
+ }
+
+ private Cipher getCipher(Provider p, String algorithm,
+ Configuration conf) throws Exception {
+ Cipher pbeCipher = null;
+ try {
+ pbeCipher = Cipher.getInstance(algorithm, p);
+ } catch (NoSuchAlgorithmException e) {
+ return null;
+ }
+ switch (conf) {
+ case PBEParameterSpec, AlgorithmParameters -> {
+ SecretKey key = getPasswordOnlyPBEKey();
+ PBEParameterSpec paramSpec = new PBEParameterSpec(
+ salt, iterations, new IvParameterSpec(iv));
+ switch (conf) {
+ case PBEParameterSpec -> {
+ pbeCipher.init(Cipher.ENCRYPT_MODE, key, paramSpec);
+ }
+ case AlgorithmParameters -> {
+ AlgorithmParameters algoParams =
+ AlgorithmParameters.getInstance("PBES2");
+ algoParams.init(paramSpec);
+ pbeCipher.init(Cipher.ENCRYPT_MODE, key, algoParams);
+ }
+ }
+ }
+ case AnonymousPBEKey -> {
+ SecretKey key = getPasswordSaltIterationsPBEKey();
+ pbeCipher.init(Cipher.ENCRYPT_MODE, key, new NoRandom());
+ }
+ }
+ return pbeCipher;
+ }
+
+ private static SecretKey getPasswordOnlyPBEKey() throws Exception {
+ PBEKeySpec keySpec = new PBEKeySpec(password);
+ SecretKeyFactory skFac = SecretKeyFactory.getInstance("PBE");
+ SecretKey skey = skFac.generateSecret(keySpec);
+ keySpec.clearPassword();
+ return skey;
+ }
+
+ private static SecretKey getPasswordSaltIterationsPBEKey() {
+ return new PBEKey() {
+ public byte[] getSalt() { return salt.clone(); }
+ public int getIterationCount() { return iterations; }
+ public String getAlgorithm() { return "PBE"; }
+ public String getFormat() { return "RAW"; }
+ public char[] getPassword() { return null; } // unused in PBE Cipher
+ public byte[] getEncoded() {
+ byte[] passwdBytes = new byte[password.length];
+ for (int i = 0; i < password.length; i++)
+ passwdBytes[i] = (byte) (password[i] & 0x7f);
+ return passwdBytes;
+ }
+ };
+ }
+
+ private static void printByteArray(String title, BigInteger b) {
+ String repr = (b == null) ? "buffer is null" : b.toString(16);
+ System.out.println(title + ": " + repr + System.lineSeparator());
+ }
+
+ public static void main(String[] args) throws Exception {
+ PBECipher2 test = new PBECipher2();
+ Provider p = Security.getProvider("SunPKCS11-NSS-FIPS");
+ if (p != null) {
+ test.main(p);
+ } else {
+ main(test);
+ }
+ }
+}
diff --git a/test/jdk/sun/security/pkcs11/KeyStore/ImportKeyToP12.java b/test/jdk/sun/security/pkcs11/KeyStore/ImportKeyToP12.java
new file mode 100644
index 00000000000..360e11c339d
--- /dev/null
+++ b/test/jdk/sun/security/pkcs11/KeyStore/ImportKeyToP12.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2022, Red Hat, Inc.
+ *
+ * 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 java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.security.Key;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.MessageDigest;
+import java.security.Provider;
+import java.security.Security;
+
+import javax.crypto.spec.SecretKeySpec;
+
+/*
+ * @test
+ * @bug 9999999
+ * @summary test SunPKCS11's password based privacy and integrity
+ * applied to PKCS#12 keystores
+ * @requires (jdk.version.major >= 8)
+ * @library /test/lib ..
+ * @modules java.base/sun.security.util
+ * @run main/othervm/timeout=30 -Dcom.redhat.fips=false -DNO_DEFAULT=true ImportKeyToP12
+ */
+
+public final class ImportKeyToP12 {
+ public static void main(String[] args) throws Exception {
+ java.security.Security.getProviders();
+ ImportKeyToP122.main(args);
+ }
+}
+
+final class ImportKeyToP122 extends PKCS11Test {
+ private static final String alias = "alias";
+ private static final char[] password = "123456".toCharArray();
+ private static final Key key = new SecretKeySpec(new byte[] {
+ 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
+ 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf }, "AES");
+ private static final String[] pbeCipherAlgs = new String[] {
+ "PBEWithHmacSHA1AndAES_128", "PBEWithHmacSHA224AndAES_128",
+ "PBEWithHmacSHA256AndAES_128", "PBEWithHmacSHA384AndAES_128",
+ "PBEWithHmacSHA512AndAES_128", "PBEWithHmacSHA1AndAES_256",
+ "PBEWithHmacSHA224AndAES_256", "PBEWithHmacSHA256AndAES_256",
+ "PBEWithHmacSHA384AndAES_256", "PBEWithHmacSHA512AndAES_256"
+ };
+ private static final String[] pbeMacAlgs = new String[] {
+ "HmacPBESHA1", "HmacPBESHA224", "HmacPBESHA256",
+ "HmacPBESHA384", "HmacPBESHA512"
+ };
+ private static final KeyStore p12;
+ private static final String sep =
+ "=========================================================================";
+
+ static {
+ KeyStore tP12 = null;
+ try {
+ tP12 = KeyStore.getInstance("PKCS12");
+ } catch (KeyStoreException e) {}
+ p12 = tP12;
+ }
+
+ public void main(Provider sunPKCS11) throws Exception {
+ System.out.println("SunPKCS11: " + sunPKCS11.getName());
+ // Test all privacy PBE algorithms with an integrity algorithm fixed
+ for (String pbeCipherAlg : pbeCipherAlgs) {
+ testWith(sunPKCS11, pbeCipherAlg, pbeMacAlgs[0]);
+ }
+ // Test all integrity PBE algorithms with a privacy algorithm fixed
+ for (String pbeMacAlg : pbeMacAlgs) {
+ testWith(sunPKCS11, pbeCipherAlgs[0], pbeMacAlg);
+ }
+ System.out.println("TEST PASS - OK");
+ }
+
+ /*
+ * Consistency test: 1) store a secret key in a PKCS#12 keystore using
+ * PBE algorithms from SunPKCS11 and, 2) read the secret key from the
+ * PKCS#12 keystore using PBE algorithms from other security providers
+ * such as SunJCE.
+ */
+ private void testWith(Provider sunPKCS11, String pbeCipherAlg,
+ String pbeMacAlg) throws Exception {
+ System.out.println(sep + System.lineSeparator() +
+ "Cipher PBE: " + pbeCipherAlg + System.lineSeparator() +
+ "Mac PBE: " + pbeMacAlg);
+
+ System.setProperty("keystore.pkcs12.macAlgorithm", pbeMacAlg);
+ System.setProperty("keystore.pkcs12.keyProtectionAlgorithm",
+ pbeCipherAlg);
+
+ // Create an empty PKCS#12 keystore
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ p12.load(null, password);
+
+ // Use PBE privacy and integrity algorithms from SunPKCS11 to store
+ // the secret key
+ Security.insertProviderAt(sunPKCS11, 1);
+ p12.setKeyEntry(alias, key, password, null);
+ p12.store(baos, password);
+
+ // Use PBE privacy and integrity algorithms from other security
+ // providers, such as SunJCE, to read the secret key
+ Security.removeProvider(sunPKCS11.getName());
+ p12.load(new ByteArrayInputStream(baos.toByteArray()), password);
+ Key k = p12.getKey(alias, password);
+
+ if (!MessageDigest.isEqual(key.getEncoded(), k.getEncoded())) {
+ throw new Exception("Keys differ. Consistency check failed.");
+ }
+ System.out.println("Secret key import successful" + System.lineSeparator() + sep);
+ }
+
+ public static void main(String[] args) throws Exception {
+ main(new ImportKeyToP122());
+ }
+}
diff --git a/test/jdk/sun/security/pkcs11/Mac/PBAMac.java b/test/jdk/sun/security/pkcs11/Mac/PBAMac.java
new file mode 100644
index 00000000000..6b5662f6b4c
--- /dev/null
+++ b/test/jdk/sun/security/pkcs11/Mac/PBAMac.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2022, Red Hat, Inc.
+ *
+ * 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 java.math.BigInteger;
+import java.security.NoSuchAlgorithmException;
+import java.security.Provider;
+import java.security.Security;
+import java.util.Map;
+
+import javax.crypto.Mac;
+import javax.crypto.SecretKey;
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.interfaces.PBEKey;
+import javax.crypto.spec.PBEKeySpec;
+import javax.crypto.spec.PBEParameterSpec;
+
+/*
+ * @test
+ * @bug 9999999
+ * @summary test password based authentication on SunPKCS11's Mac service
+ * @requires (jdk.version.major >= 8)
+ * @library /test/lib ..
+ * @run main/othervm/timeout=30 PBAMac
+ */
+
+public final class PBAMac {
+ public static void main(String[] args) throws Exception {
+ java.security.Security.getProviders();
+ PBAMac2.main(args);
+ }
+}
+
+final class PBAMac2 extends PKCS11Test {
+ private static final char[] password = "123456".toCharArray();
+ private static final byte[] salt = "abcdefgh".getBytes();
+ private static final int iterations = 1000;
+ private static final String plainText = "This is a know plain text!";
+ private static final String sep =
+ "=========================================================================";
+
+ private static enum Configuration {
+ // Provide salt & iterations through a PBEParameterSpec instance
+ PBEParameterSpec,
+
+ // Provide salt & iterations through an anonymous class implementing
+ // the javax.crypto.interfaces.PBEKey interface
+ AnonymousPBEKey,
+ }
+
+ // Generated with SunJCE
+ private static final Map<String, BigInteger> assertionData = Map.of(
+ "HmacPBESHA1", new BigInteger("febd26da5d63ce819770a2af1fc2857e" +
+ "e2c9c41c", 16),
+ "HmacPBESHA224", new BigInteger("aa6a3a1c35a4b266fea62d1a871508" +
+ "bd45f8ec326bcf16e09699063", 16),
+ "HmacPBESHA256", new BigInteger("af4d71121fd4e9d52eb42944d99b77" +
+ "8ff64376fcf6af8d1dca3ec688dfada5c8", 16),
+ "HmacPBESHA384", new BigInteger("5d6d37764205985ffca7e4a6222752" +
+ "a8bbd0520858da08ecafdc57e6246894675e375b9ba084f9ce7142" +
+ "35f202cc3452", 16),
+ "HmacPBESHA512", new BigInteger("f586c2006cc2de73fd5743e5cca701" +
+ "c942d3741a7a54a2a649ea36898996cf3c483f2d734179b47751db" +
+ "e8373c980b4072136d2e2810f4e7276024a3e9081cc1", 16)
+ );
+
+ private static Provider sunJCE = Security.getProvider("SunJCE");
+
+ public void main(Provider sunPKCS11) throws Exception {
+ System.out.println("SunPKCS11: " + sunPKCS11.getName());
+ for (Configuration conf : Configuration.values()) {
+ testWith(sunPKCS11, "HmacPBESHA1", conf);
+ testWith(sunPKCS11, "HmacPBESHA224", conf);
+ testWith(sunPKCS11, "HmacPBESHA256", conf);
+ testWith(sunPKCS11, "HmacPBESHA384", conf);
+ testWith(sunPKCS11, "HmacPBESHA512", conf);
+ }
+ System.out.println("TEST PASS - OK");
+ }
+
+ private void testWith(Provider sunPKCS11, String algorithm,
+ Configuration conf) throws Exception {
+ System.out.println(sep + System.lineSeparator() + algorithm
+ + " (with " + conf.name() + ")");
+
+ BigInteger macResult = computeMac(sunPKCS11, algorithm, conf);
+ printByteArray("HMAC Result", macResult);
+
+ BigInteger expectedMacResult = computeExpectedMac(algorithm, conf);
+
+ if (!macResult.equals(expectedMacResult)) {
+ printByteArray("Expected HMAC Result", expectedMacResult);
+ throw new Exception("Expected HMAC Result did not match");
+ }
+ }
+
+ private BigInteger computeMac(Provider p, String algorithm,
+ Configuration conf) throws Exception {
+ Mac pbaMac;
+ try {
+ pbaMac = Mac.getInstance(algorithm, p);
+ } catch (NoSuchAlgorithmException e) {
+ return null;
+ }
+ switch (conf) {
+ case PBEParameterSpec -> {
+ SecretKey key = getPasswordOnlyPBEKey();
+ pbaMac.init(key, new PBEParameterSpec(salt, iterations));
+ }
+ case AnonymousPBEKey -> {
+ SecretKey key = getPasswordSaltIterationsPBEKey();
+ pbaMac.init(key);
+ }
+ }
+ return new BigInteger(1, pbaMac.doFinal(plainText.getBytes()));
+ }
+
+ private BigInteger computeExpectedMac(String algorithm, Configuration conf)
+ throws Exception {
+ if (sunJCE != null) {
+ BigInteger macResult = computeMac(sunJCE, algorithm, conf);
+ if (macResult != null) {
+ return macResult;
+ }
+ // Move to assertionData as it's unlikely that any of
+ // the algorithms are available.
+ sunJCE = null;
+ }
+ // If SunJCE or the algorithm are not available, assertionData
+ // is used instead.
+ return assertionData.get(algorithm);
+ }
+
+ private static SecretKey getPasswordOnlyPBEKey() throws Exception {
+ PBEKeySpec keySpec = new PBEKeySpec(password);
+ SecretKeyFactory skFac = SecretKeyFactory.getInstance("PBE");
+ SecretKey skey = skFac.generateSecret(keySpec);
+ keySpec.clearPassword();
+ return skey;
+ }
+
+ private static SecretKey getPasswordSaltIterationsPBEKey() {
+ return new PBEKey() {
+ public byte[] getSalt() { return salt.clone(); }
+ public int getIterationCount() { return iterations; }
+ public String getAlgorithm() { return "PBE"; }
+ public String getFormat() { return "RAW"; }
+ public char[] getPassword() { return password.clone(); }
+ public byte[] getEncoded() { return null; } // unused in PBA Mac
+ };
+ }
+
+ private static void printByteArray(String title, BigInteger b) {
+ String repr = (b == null) ? "buffer is null" : b.toString(16);
+ System.out.println(title + ": " + repr + System.lineSeparator());
+ }
+
+ public static void main(String[] args) throws Exception {
+ PBAMac2 test = new PBAMac2();
+ Provider p = Security.getProvider("SunPKCS11-NSS-FIPS");
+ if (p != null) {
+ test.main(p);
+ } else {
+ main(test);
+ }
+ }
+}
diff --git a/test/jdk/sun/security/pkcs11/SecretKeyFactory/TestPBKD.java b/test/jdk/sun/security/pkcs11/SecretKeyFactory/TestPBKD.java
new file mode 100644
index 00000000000..67c3cee5970
--- /dev/null
+++ b/test/jdk/sun/security/pkcs11/SecretKeyFactory/TestPBKD.java
@@ -0,0 +1,296 @@
+/*
+ * Copyright (c) 2022, Red Hat, Inc.
+ *
+ * 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 java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.math.BigInteger;
+import java.security.NoSuchAlgorithmException;
+import java.security.Provider;
+import java.security.Security;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.PBEKeySpec;
+
+/*
+ * @test
+ * @bug 9999999
+ * @summary test key derivation on SunPKCS11's SecretKeyFactory service
+ * @requires (jdk.version.major >= 8)
+ * @library /test/lib ..
+ * @modules java.base/com.sun.crypto.provider:open
+ * @run main/othervm/timeout=30 TestPBKD
+ */
+
+public final class TestPBKD {
+ public static void main(String[] args) throws Exception {
+ java.security.Security.getProviders();
+ TestPBKD2.main(args);
+ }
+}
+
+final class TestPBKD2 extends PKCS11Test {
+ private static final char[] password = "123456".toCharArray();
+ private static final byte[] salt = "abcdefgh".getBytes();
+ private static final int iterations = 1000;
+ private static final String sep =
+ "=========================================================================";
+
+ private static Provider sunJCE = Security.getProvider("SunJCE");
+
+ // Generated with SunJCE
+ private static final Map<String, BigInteger> assertionData =
+ new HashMap<>() {{
+ put("HmacPBESHA1", new BigInteger("5f7d1c360d1703cede76f47db" +
+ "2fa3facc62e7694", 16));
+ put("HmacPBESHA224", new BigInteger("289563f799b708f522ab2a3" +
+ "8d283d0afa8fc1d3d227fcb9236c3a035", 16));
+ put("HmacPBESHA256", new BigInteger("888defcf4ef37eb0647014a" +
+ "d172dd6fa3b3e9d024b962dba47608eea9b9c4b79", 16));
+ put("HmacPBESHA384", new BigInteger("f5464b34253fadab8838d0d" +
+ "b11980c1787a99bf6f6304f2d8c942e30bada523494f9d5a0f3" +
+ "741e411de21add8b5718a8", 16));
+ put("HmacPBESHA512", new BigInteger("18ae94337b132c68c611bc2" +
+ "e723ac24dcd44a46d900dae2dd6170380d4c34f90fef7bdeb5f" +
+ "6fddeb0d2230003e329b7a7eefcd35810d364ba95d31b68bb61" +
+ "e52", 16));
+ put("PBEWithHmacSHA1AndAES_128", new BigInteger("fdb3dcc2e81" +
+ "244d4d56bf7ec8dd61dd7", 16));
+ put("PBEWithHmacSHA224AndAES_128", new BigInteger("5ef9e5c6f" +
+ "df7c355f3b424233a9f24c2", 16));
+ put("PBEWithHmacSHA256AndAES_128", new BigInteger("c5af597b0" +
+ "1b4f6baac8f62ff6f22bfb1", 16));
+ put("PBEWithHmacSHA384AndAES_128", new BigInteger("c3208ebc5" +
+ "d6db88858988ec00153847d", 16));
+ put("PBEWithHmacSHA512AndAES_128", new BigInteger("b27e8f7fb" +
+ "6a4bd5ebea892cd9a7f5043", 16));
+ put("PBEWithHmacSHA1AndAES_256", new BigInteger("fdb3dcc2e81" +
+ "244d4d56bf7ec8dd61dd78a1b6fb3ad11d9ebd7f62027a2ccde" +
+ "98", 16));
+ put("PBEWithHmacSHA224AndAES_256", new BigInteger("5ef9e5c6f" +
+ "df7c355f3b424233a9f24c2c9c41793cb0948b8ea3aac240b8d" +
+ "f64d", 16));
+ put("PBEWithHmacSHA256AndAES_256", new BigInteger("c5af597b0" +
+ "1b4f6baac8f62ff6f22bfb1f319c3278c8b31cc616294716d4e" +
+ "ab08", 16));
+ put("PBEWithHmacSHA384AndAES_256", new BigInteger("c3208ebc5" +
+ "d6db88858988ec00153847d5b1b7a8723640a022dc332bcaefe" +
+ "b356", 16));
+ put("PBEWithHmacSHA512AndAES_256", new BigInteger("b27e8f7fb" +
+ "6a4bd5ebea892cd9a7f5043cefff9c38b07e599721e8d116189" +
+ "5482", 16));
+ put("PBKDF2WithHmacSHA1", new BigInteger("fdb3dcc2e81244d4d5" +
+ "6bf7ec8dd61dd78a1b6fb3ad11d9ebd7f62027a2cc", 16));
+ put("PBKDF2WithHmacSHA224", new BigInteger("5ef9e5c6fdf7c355" +
+ "f3b424233a9f24c2c9c41793cb0948b8ea3aac240b8df64d1a0" +
+ "736ec1c69eef1c7b2", 16));
+ put("PBKDF2WithHmacSHA256", new BigInteger("c5af597b01b4f6ba" +
+ "ac8f62ff6f22bfb1f319c3278c8b31cc616294716d4eab080b9" +
+ "add9db34a42ceb2fea8d27adc00f4", 16));
+ put("PBKDF2WithHmacSHA384", new BigInteger("c3208ebc5d6db888" +
+ "58988ec00153847d5b1b7a8723640a022dc332bcaefeb356995" +
+ "d076a949d35c42c7e1e1ca936c12f8dc918e497edf279a522b7" +
+ "c99580e2613846b3919af637da", 16));
+ put("PBKDF2WithHmacSHA512", new BigInteger("b27e8f7fb6a4bd5e" +
+ "bea892cd9a7f5043cefff9c38b07e599721e8d1161895482da2" +
+ "55746844cc1030be37ba1969df10ff59554d1ac5468fa9b7297" +
+ "7bb7fd52103a0a7b488cdb8957616c3e23a16bca92120982180" +
+ "c6c11a4f14649b50d0ade3a", 16));
+ }};
+
+ static interface AssertData {
+ BigInteger derive(String pbAlgo, PBEKeySpec keySpec) throws Exception;
+ }
+
+ static final class P12PBKDAssertData implements AssertData {
+ private final int outLen;
+ private final String kdfAlgo;
+ private final int blockLen;
+
+ P12PBKDAssertData(int outLen, String kdfAlgo, int blockLen) {
+ this.outLen = outLen;
+ this.kdfAlgo = kdfAlgo;
+ this.blockLen = blockLen;
+ }
+
+ @Override
+ public BigInteger derive(String pbAlgo, PBEKeySpec keySpec)
+ throws Exception {
+ // Since we need to access an internal SunJCE API, we use reflection
+ Class<?> PKCS12PBECipherCore = Class.forName(
+ "com.sun.crypto.provider.PKCS12PBECipherCore");
+
+ Field macKeyField = PKCS12PBECipherCore.getDeclaredField("MAC_KEY");
+ macKeyField.setAccessible(true);
+ int MAC_KEY = (int) macKeyField.get(null);
+
+ Method deriveMethod = PKCS12PBECipherCore.getDeclaredMethod(
+ "derive", char[].class, byte[].class, int.class,
+ int.class, int.class, String.class, int.class);
+ deriveMethod.setAccessible(true);
+
+ return new BigInteger(1, (byte[]) deriveMethod.invoke(null,
+ keySpec.getPassword(), keySpec.getSalt(),
+ keySpec.getIterationCount(), this.outLen,
+ MAC_KEY, this.kdfAlgo, this.blockLen));
+ }
+ }
+
+ static final class PBKD2AssertData implements AssertData {
+ private final String kdfAlgo;
+ private final int keyLen;
+
+ PBKD2AssertData(String kdfAlgo, int keyLen) {
+ // Key length is pinned by the algorithm name (not kdfAlgo,
+ // but the algorithm under test: PBEWithHmacSHA*AndAES_*)
+ this.kdfAlgo = kdfAlgo;
+ this.keyLen = keyLen;
+ }
+
+ PBKD2AssertData(String kdfAlgo) {
+ // Key length is variable for the algorithm under test
+ // (kdfAlgo is the algorithm under test: PBKDF2WithHmacSHA*)
+ this(kdfAlgo, -1);
+ }
+
+ @Override
+ public BigInteger derive(String pbAlgo, PBEKeySpec keySpec)
+ throws Exception {
+ if (this.keyLen != -1) {
+ keySpec = new PBEKeySpec(
+ keySpec.getPassword(), keySpec.getSalt(),
+ keySpec.getIterationCount(), this.keyLen);
+ }
+ if (sunJCE != null) {
+ try {
+ return new BigInteger(1, SecretKeyFactory.getInstance(
+ this.kdfAlgo, sunJCE).generateSecret(keySpec)
+ .getEncoded());
+ } catch (NoSuchAlgorithmException e) {
+ // Move to assertionData as it's unlikely that any of
+ // the algorithms are available.
+ sunJCE = null;
+ }
+ }
+ // If SunJCE or the algorithm are not available, assertionData
+ // is used instead.
+ return assertionData.get(pbAlgo);
+ }
+ }
+
+ public void main(Provider sunPKCS11) throws Exception {
+ System.out.println("SunPKCS11: " + sunPKCS11.getName());
+ testWith(sunPKCS11, "HmacPBESHA1",
+ new P12PBKDAssertData(20, "SHA-1", 64));
+ testWith(sunPKCS11, "HmacPBESHA224",
+ new P12PBKDAssertData(28, "SHA-224", 64));
+ testWith(sunPKCS11, "HmacPBESHA256",
+ new P12PBKDAssertData(32, "SHA-256", 64));
+ testWith(sunPKCS11, "HmacPBESHA384",
+ new P12PBKDAssertData(48, "SHA-384", 128));
+ testWith(sunPKCS11, "HmacPBESHA512",
+ new P12PBKDAssertData(64, "SHA-512", 128));
+
+ testWith(sunPKCS11, "PBEWithHmacSHA1AndAES_128",
+ new PBKD2AssertData("PBKDF2WithHmacSHA1", 128));
+ testWith(sunPKCS11, "PBEWithHmacSHA224AndAES_128",
+ new PBKD2AssertData("PBKDF2WithHmacSHA224", 128));
+ testWith(sunPKCS11, "PBEWithHmacSHA256AndAES_128",
+ new PBKD2AssertData("PBKDF2WithHmacSHA256", 128));
+ testWith(sunPKCS11, "PBEWithHmacSHA384AndAES_128",
+ new PBKD2AssertData("PBKDF2WithHmacSHA384", 128));
+ testWith(sunPKCS11, "PBEWithHmacSHA512AndAES_128",
+ new PBKD2AssertData("PBKDF2WithHmacSHA512", 128));
+ testWith(sunPKCS11, "PBEWithHmacSHA1AndAES_256",
+ new PBKD2AssertData("PBKDF2WithHmacSHA1", 256));
+ testWith(sunPKCS11, "PBEWithHmacSHA224AndAES_256",
+ new PBKD2AssertData("PBKDF2WithHmacSHA224", 256));
+ testWith(sunPKCS11, "PBEWithHmacSHA256AndAES_256",
+ new PBKD2AssertData("PBKDF2WithHmacSHA256", 256));
+ testWith(sunPKCS11, "PBEWithHmacSHA384AndAES_256",
+ new PBKD2AssertData("PBKDF2WithHmacSHA384", 256));
+ testWith(sunPKCS11, "PBEWithHmacSHA512AndAES_256",
+ new PBKD2AssertData("PBKDF2WithHmacSHA512", 256));
+
+ // Use 1,5 * digest size as the testing derived key length (in bits)
+ testWith(sunPKCS11, "PBKDF2WithHmacSHA1", 240,
+ new PBKD2AssertData("PBKDF2WithHmacSHA1"));
+ testWith(sunPKCS11, "PBKDF2WithHmacSHA224", 336,
+ new PBKD2AssertData("PBKDF2WithHmacSHA224"));
+ testWith(sunPKCS11, "PBKDF2WithHmacSHA256", 384,
+ new PBKD2AssertData("PBKDF2WithHmacSHA256"));
+ testWith(sunPKCS11, "PBKDF2WithHmacSHA384", 576,
+ new PBKD2AssertData("PBKDF2WithHmacSHA384"));
+ testWith(sunPKCS11, "PBKDF2WithHmacSHA512", 768,
+ new PBKD2AssertData("PBKDF2WithHmacSHA512"));
+
+ System.out.println("TEST PASS - OK");
+ }
+
+ private static void testWith(Provider sunPKCS11, String algorithm,
+ AssertData assertData) throws Exception {
+ PBEKeySpec keySpec = new PBEKeySpec(password, salt, iterations);
+ testWith(sunPKCS11, algorithm, keySpec, assertData);
+ }
+
+ private static void testWith(Provider sunPKCS11, String algorithm,
+ int keyLen, AssertData assertData) throws Exception {
+ PBEKeySpec keySpec = new PBEKeySpec(password, salt, iterations, keyLen);
+ testWith(sunPKCS11, algorithm, keySpec, assertData);
+ }
+
+ private static void testWith(Provider sunPKCS11, String algorithm,
+ PBEKeySpec keySpec, AssertData assertData) throws Exception {
+ System.out.println(sep + System.lineSeparator() + algorithm);
+
+ SecretKeyFactory skFac = SecretKeyFactory.getInstance(
+ algorithm, sunPKCS11);
+ BigInteger derivedKey = new BigInteger(1,
+ skFac.generateSecret(keySpec).getEncoded());
+ printByteArray("Derived Key", derivedKey);
+
+ BigInteger expectedDerivedKey = assertData.derive(algorithm, keySpec);
+
+ if (!derivedKey.equals(expectedDerivedKey)) {
+ printByteArray("Expected Derived Key", expectedDerivedKey);
+ throw new Exception("Expected Derived Key did not match");
+ }
+ }
+
+ private static void printByteArray(String title, BigInteger b) {
+ String repr = (b == null) ? "buffer is null" : b.toString(16);
+ System.out.println(title + ": " + repr + System.lineSeparator());
+ }
+
+ public static void main(String[] args) throws Exception {
+ TestPBKD2 test = new TestPBKD2();
+ Provider p = Security.getProvider("SunPKCS11-NSS-FIPS");
+ if (p != null) {
+ test.main(p);
+ } else {
+ main(test);
+ }
+ }
+}
diff --git a/test/jdk/sun/security/pkcs11/fips/NssdbPin.java b/test/jdk/sun/security/pkcs11/fips/NssdbPin.java
new file mode 100644
index 00000000000..ce01c655eb8
--- /dev/null
+++ b/test/jdk/sun/security/pkcs11/fips/NssdbPin.java
@@ -0,0 +1,349 @@
+/*
+ * Copyright (c) 2022, Red Hat, Inc.
+ *
+ * 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 java.lang.reflect.Method;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.security.KeyStore;
+import java.security.Provider;
+import java.security.Security;
+import java.util.Arrays;
+import java.util.function.Consumer;
+import java.util.List;
+import javax.crypto.Cipher;
+import javax.crypto.spec.SecretKeySpec;
+
+import jdk.test.lib.process.Proc;
+import jdk.test.lib.util.FileUtils;
+
+/*
+ * @test
+ * @bug 9999999
+ * @summary
+ * Test that the fips.nssdb.path and fips.nssdb.pin properties can be used
+ * for a successful login into an NSS DB. Some additional unitary testing
+ * is then performed. This test depends on NSS modutil and must be run in
+ * FIPS mode (the SunPKCS11-NSS-FIPS security provider has to be available).
+ * @modules jdk.crypto.cryptoki/sun.security.pkcs11:+open
+ * @library /test/lib
+ * @requires (jdk.version.major >= 8)
+ * @run main/othervm/timeout=600 NssdbPin
+ * @author Martin Balao (mbalao@redhat.com)
+ */
+
+public final class NssdbPin {
+
+ // Public properties and names
+ private static final String FIPS_NSSDB_PATH_PROP = "fips.nssdb.path";
+ private static final String FIPS_NSSDB_PIN_PROP = "fips.nssdb.pin";
+ private static final String FIPS_PROVIDER_NAME = "SunPKCS11-NSS-FIPS";
+ private static final String NSSDB_TOKEN_NAME =
+ "NSS FIPS 140-2 Certificate DB";
+
+ // Data to be tested
+ private static final String[] PINS_TO_TEST =
+ new String[] {
+ "",
+ "1234567890abcdef1234567890ABCDEF\uA4F7"
+ };
+ private static enum PropType { SYSTEM, SECURITY }
+ private static enum LoginType { IMPLICIT, EXPLICIT }
+
+ // Internal test fields
+ private static final boolean DEBUG = true;
+ private static class TestContext {
+ String pin;
+ PropType propType;
+ Path workspace;
+ String nssdbPath;
+ Path nssdbPinFile;
+ LoginType loginType;
+ TestContext(String pin, Path workspace) {
+ this.pin = pin;
+ this.workspace = workspace;
+ this.nssdbPath = "sql:" + workspace;
+ this.loginType = LoginType.IMPLICIT;
+ }
+ }
+
+ public static void main(String[] args) throws Throwable {
+ if (args.length == 3) {
+ // Executed by a child process.
+ mainChild(args[0], args[1], LoginType.valueOf(args[2]));
+ } else if (args.length == 0) {
+ // Executed by the parent process.
+ mainLauncher();
+ // Test defaults
+ mainChild("sql:/etc/pki/nssdb", "", LoginType.IMPLICIT);
+ System.out.println("TEST PASS - OK");
+ } else {
+ throw new Exception("Unexpected number of arguments.");
+ }
+ }
+
+ private static void mainChild(String expectedPath, String expectedPin,
+ LoginType loginType) throws Throwable {
+ if (DEBUG) {
+ for (String prop : Arrays.asList(FIPS_NSSDB_PATH_PROP,
+ FIPS_NSSDB_PIN_PROP)) {
+ System.out.println(prop + " (System): " +
+ System.getProperty(prop));
+ System.out.println(prop + " (Security): " +
+ Security.getProperty(prop));
+ }
+ }
+
+ /*
+ * Functional cross-test against an NSS DB generated by modutil
+ * with the same PIN. Check that we can perform a crypto operation
+ * that requires a login. The login might be explicit or implicit.
+ */
+ Provider p = Security.getProvider(FIPS_PROVIDER_NAME);
+ if (DEBUG) {
+ System.out.println(FIPS_PROVIDER_NAME + ": " + p);
+ }
+ if (p == null) {
+ throw new Exception(FIPS_PROVIDER_NAME + " initialization failed.");
+ }
+ if (DEBUG) {
+ System.out.println("Login type: " + loginType);
+ }
+ if (loginType == LoginType.EXPLICIT) {
+ // Do the expansion to account for truncation, so C_Login in
+ // the NSS Software Token gets a UTF-8 encoded PIN.
+ byte[] pinUtf8 = expectedPin.getBytes(StandardCharsets.UTF_8);
+ char[] pinChar = new char[pinUtf8.length];
+ for (int i = 0; i < pinChar.length; i++) {
+ pinChar[i] = (char)(pinUtf8[i] & 0xFF);
+ }
+ KeyStore.getInstance("PKCS11", p).load(null, pinChar);
+ if (DEBUG) {
+ System.out.println("Explicit login succeeded.");
+ }
+ }
+ if (DEBUG) {
+ System.out.println("Trying a crypto operation...");
+ }
+ final int blockSize = 16;
+ Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding", p);
+ cipher.init(Cipher.ENCRYPT_MODE,
+ new SecretKeySpec(new byte[blockSize], "AES"));
+ if (cipher.doFinal(new byte[blockSize]).length != blockSize) {
+ throw new Exception("Could not perform a crypto operation.");
+ }
+ if (DEBUG) {
+ if (loginType == LoginType.IMPLICIT) {
+ System.out.println("Implicit login succeeded.");
+ }
+ System.out.println("Crypto operation after login succeeded.");
+ }
+
+ if (loginType == LoginType.IMPLICIT) {
+ /*
+ * Additional unitary testing. Expected to succeed at this point.
+ */
+ if (DEBUG) {
+ System.out.println("Trying unitary test...");
+ }
+ String sysPathProp = System.getProperty(FIPS_NSSDB_PATH_PROP);
+ if (DEBUG) {
+ System.out.println("Path value (as a System property): " +
+ sysPathProp);
+ }
+ if (!expectedPath.equals(sysPathProp)) {
+ throw new Exception("Path is different than expected: " +
+ sysPathProp + " (actual) vs " + expectedPath +
+ " (expected).");
+ }
+ Class<?> c = Class
+ .forName("sun.security.pkcs11.FIPSTokenLoginHandler");
+ Method m = c.getDeclaredMethod("getFipsNssdbPin");
+ m.setAccessible(true);
+ String pin = null;
+ char[] pinChar = (char[]) m.invoke(c);
+ if (pinChar != null) {
+ byte[] pinUtf8 = new byte[pinChar.length];
+ for (int i = 0; i < pinUtf8.length; i++) {
+ pinUtf8[i] = (byte) pinChar[i];
+ }
+ pin = new String(pinUtf8, StandardCharsets.UTF_8);
+ }
+ if (!expectedPin.isEmpty() && !expectedPin.equals(pin) ||
+ expectedPin.isEmpty() && pin != null) {
+ throw new Exception("PIN is different than expected: '" + pin +
+ "' (actual) vs '" + expectedPin + "' (expected).");
+ }
+ if (DEBUG) {
+ System.out.println("PIN value: " + pin);
+ System.out.println("Unitary test succeeded.");
+ }
+ }
+ }
+
+ private static void mainLauncher() throws Throwable {
+ for (String pin : PINS_TO_TEST) {
+ Path workspace = Files.createTempDirectory(null);
+ try {
+ TestContext ctx = new TestContext(pin, workspace);
+ createNSSDB(ctx);
+ {
+ ctx.loginType = LoginType.IMPLICIT;
+ for (PropType propType : PropType.values()) {
+ ctx.propType = propType;
+ pinLauncher(ctx);
+ envLauncher(ctx);
+ fileLauncher(ctx);
+ }
+ }
+ explicitLoginLauncher(ctx);
+ } finally {
+ FileUtils.deleteFileTreeWithRetry(workspace);
+ }
+ }
+ }
+
+ private static void pinLauncher(TestContext ctx) throws Throwable {
+ launchTest(p -> {}, "pin:" + ctx.pin, ctx);
+ }
+
+ private static void envLauncher(TestContext ctx) throws Throwable {
+ final String NSSDB_PIN_ENV_VAR = "NSSDB_PIN_ENV_VAR";
+ launchTest(p -> p.env(NSSDB_PIN_ENV_VAR, ctx.pin),
+ "env:" + NSSDB_PIN_ENV_VAR, ctx);
+ }
+
+ private static void fileLauncher(TestContext ctx) throws Throwable {
+ // The file containing the PIN (ctx.nssdbPinFile) was created by the
+ // generatePinFile method, called from createNSSDB.
+ launchTest(p -> {}, "file:" + ctx.nssdbPinFile, ctx);
+ }
+
+ private static void explicitLoginLauncher(TestContext ctx)
+ throws Throwable {
+ ctx.loginType = LoginType.EXPLICIT;
+ ctx.propType = PropType.SYSTEM;
+ launchTest(p -> {}, "Invalid PIN, must be ignored", ctx);
+ }
+
+ private static void launchTest(Consumer<Proc> procCb, String pinPropVal,
+ TestContext ctx) throws Throwable {
+ if (DEBUG) {
+ System.out.println("Launching JVM with " + FIPS_NSSDB_PATH_PROP +
+ "=" + ctx.nssdbPath + " and " + FIPS_NSSDB_PIN_PROP +
+ "=" + pinPropVal);
+ }
+ Proc p = Proc.create(NssdbPin.class.getName())
+ .args(ctx.nssdbPath, ctx.pin, ctx.loginType.name());
+ if (ctx.propType == PropType.SYSTEM) {
+ p.prop(FIPS_NSSDB_PATH_PROP, ctx.nssdbPath);
+ p.prop(FIPS_NSSDB_PIN_PROP, pinPropVal);
+ // Make sure that Security properties defaults are not used.
+ p.secprop(FIPS_NSSDB_PATH_PROP, "");
+ p.secprop(FIPS_NSSDB_PIN_PROP, "");
+ } else if (ctx.propType == PropType.SECURITY) {
+ p.secprop(FIPS_NSSDB_PATH_PROP, ctx.nssdbPath);
+ pinPropVal = escapeForPropsFile(pinPropVal);
+ p.secprop(FIPS_NSSDB_PIN_PROP, pinPropVal);
+ } else {
+ throw new Exception("Unsupported property type.");
+ }
+ if (DEBUG) {
+ p.inheritIO();
+ p.prop("java.security.debug", "sunpkcs11");
+ p.debug(NssdbPin.class.getName());
+
+ // Need the launched process to connect to a debugger?
+ //System.setProperty("test.vm.opts", "-Xdebug -Xrunjdwp:" +
+ // "transport=dt_socket,address=localhost:8000,suspend=y");
+ } else {
+ p.nodump();
+ }
+ procCb.accept(p);
+ p.start().waitFor(0);
+ }
+
+ private static String escapeForPropsFile(String str) throws Throwable {
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0; i < str.length(); i++) {
+ int cp = str.codePointAt(i);
+ if (Character.UnicodeBlock.of(cp)
+ == Character.UnicodeBlock.BASIC_LATIN) {
+ sb.append(Character.toChars(cp));
+ } else {
+ sb.append("\\u").append(String.format("%04X", cp));
+ }
+ }
+ return sb.toString();
+ }
+
+ private static void createNSSDB(TestContext ctx) throws Throwable {
+ ProcessBuilder pb = getModutilPB(ctx, "-create");
+ if (DEBUG) {
+ System.out.println("Creating an NSS DB in " + ctx.workspace +
+ "...");
+ System.out.println("cmd: " + String.join(" ", pb.command()));
+ }
+ if (pb.start().waitFor() != 0) {
+ throw new Exception("NSS DB creation failed.");
+ }
+ generatePinFile(ctx);
+ pb = getModutilPB(ctx, "-changepw", NSSDB_TOKEN_NAME,
+ "-newpwfile", ctx.nssdbPinFile.toString());
+ if (DEBUG) {
+ System.out.println("NSS DB created.");
+ System.out.println("Changing NSS DB PIN...");
+ System.out.println("cmd: " + String.join(" ", pb.command()));
+ }
+ if (pb.start().waitFor() != 0) {
+ throw new Exception("NSS DB PIN change failed.");
+ }
+ if (DEBUG) {
+ System.out.println("NSS DB PIN changed.");
+ }
+ }
+
+ private static ProcessBuilder getModutilPB(TestContext ctx, String... args)
+ throws Throwable {
+ ProcessBuilder pb = new ProcessBuilder("modutil", "-force");
+ List<String> pbCommand = pb.command();
+ if (args != null) {
+ pbCommand.addAll(Arrays.asList(args));
+ }
+ pbCommand.add("-dbdir");
+ pbCommand.add(ctx.nssdbPath);
+ if (DEBUG) {
+ pb.inheritIO();
+ } else {
+ pb.redirectError(ProcessBuilder.Redirect.INHERIT);
+ }
+ return pb;
+ }
+
+ private static void generatePinFile(TestContext ctx) throws Throwable {
+ ctx.nssdbPinFile = Files.createTempFile(ctx.workspace, null, null);
+ Files.writeString(ctx.nssdbPinFile, ctx.pin + System.lineSeparator() +
+ "2nd line with garbage");
+ }
+}
diff --git a/test/jdk/sun/security/pkcs11/fips/VerifyMissingAttributes.java b/test/jdk/sun/security/pkcs11/fips/VerifyMissingAttributes.java
new file mode 100644
index 00000000000..87f1ad04505
--- /dev/null
+++ b/test/jdk/sun/security/pkcs11/fips/VerifyMissingAttributes.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2022, Red Hat, Inc.
+ *
+ * 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 java.security.Provider;
+import java.security.Security;
+
+/*
+ * @test
+ * @bug 9999999
+ * @requires (jdk.version.major >= 8)
+ * @run main/othervm/timeout=30 VerifyMissingAttributes
+ * @author Martin Balao (mbalao@redhat.com)
+ */
+
+public final class VerifyMissingAttributes {
+
+ private static final String[] svcAlgImplementedIn = {
+ "AlgorithmParameterGenerator.DSA",
+ "AlgorithmParameters.DSA",
+ "CertificateFactory.X.509",
+ "KeyStore.JKS",
+ "KeyStore.CaseExactJKS",
+ "KeyStore.DKS",
+ "CertStore.Collection",
+ "CertStore.com.sun.security.IndexedCollection"
+ };
+
+ public static void main(String[] args) throws Throwable {
+ Provider sunProvider = Security.getProvider("SUN");
+ for (String svcAlg : svcAlgImplementedIn) {
+ String filter = svcAlg + " ImplementedIn:Software";
+ doQuery(sunProvider, filter);
+ }
+ if (Double.parseDouble(
+ System.getProperty("java.specification.version")) >= 17) {
+ String filter = "KeyFactory.RSASSA-PSS SupportedKeyClasses:" +
+ "java.security.interfaces.RSAPublicKey" +
+ "|java.security.interfaces.RSAPrivateKey";
+ doQuery(Security.getProvider("SunRsaSign"), filter);
+ }
+ System.out.println("TEST PASS - OK");
+ }
+
+ private static void doQuery(Provider expectedProvider, String filter)
+ throws Exception {
+ if (expectedProvider == null) {
+ throw new Exception("Provider not found.");
+ }
+ Provider[] providers = Security.getProviders(filter);
+ if (providers == null || providers.length != 1 ||
+ providers[0] != expectedProvider) {
+ throw new Exception("Failure retrieving the provider with this" +
+ " query: " + filter);
+ }
+ }
+}