deque = new LinkedList<>();
+
+ for (char ch : string.toCharArray()) {
+ if (ch == '{' || ch == '[' || ch == '(') {
+ deque.addFirst(ch);
+ } else if (ch == '}' || ch == ']' || ch == ')') {
+ if (!deque.isEmpty()
+ && ((deque.peekFirst() == '{' && ch == '}')
+ || (deque.peekFirst() == '[' && ch == ']')
+ || (deque.peekFirst() == '(' && ch == ')'))) {
+ deque.removeFirst();
+ } else {
+ return false;
+ }
+ }
+ }
+ return deque.isEmpty();
+ }
+
+ /**
+ * Check if the input string is asterisk (*).
+ *
+ * @param string input string for checking
+ * @return true if the input string is asterisk
+ */
+ private boolean isAsterisk(String string) {
+ return "*".equals(string);
+ }
+
+ /**
+ * Nested class for provider's constraints
+ */
+ private final class Constraint {
+ final String type;
+ final String algorithm;
+ final String attributes;
+
+ Constraint(String type, String algorithm, String attributes) {
+ super();
+ this.type = type;
+ this.algorithm = algorithm;
+ this.attributes = attributes;
+ }
+ }
+ }
+}
diff --git a/src/java.base/share/classes/java/security/Provider.java b/src/java.base/share/classes/java/security/Provider.java
index fa8c0bd5912..33ab5241afa 100644
--- a/src/java.base/share/classes/java/security/Provider.java
+++ b/src/java.base/share/classes/java/security/Provider.java
@@ -23,6 +23,12 @@
* questions.
*/
+/*
+ * ===========================================================================
+ * (c) Copyright IBM Corp. 2022, 2023 All Rights Reserved
+ * ===========================================================================
+ */
+
package java.security;
import jdk.internal.event.SecurityProviderServiceEvent;
@@ -37,6 +43,8 @@
import java.util.function.Function;
import java.util.concurrent.ConcurrentHashMap;
+import openj9.internal.security.RestrictedSecurity;
+
/**
* This class represents a "provider" for the
* Java Security API, where a provider implements some or all parts of
@@ -1383,6 +1391,11 @@ protected void putService(Service s) {
throw new IllegalArgumentException
("service.getProvider() must match this Provider object");
}
+ if (!RestrictedSecurity.isServiceAllowed(s)) {
+ // We're in restricted security mode which does not allow this service,
+ // then return without registering.
+ return;
+ }
String type = s.getType();
String algorithm = s.getAlgorithm();
ServiceKey key = new ServiceKey(type, algorithm, true);
diff --git a/src/java.base/share/classes/java/security/SecureRandom.java b/src/java.base/share/classes/java/security/SecureRandom.java
index 7b317cb4b7b..47fb0ab4595 100644
--- a/src/java.base/share/classes/java/security/SecureRandom.java
+++ b/src/java.base/share/classes/java/security/SecureRandom.java
@@ -25,7 +25,7 @@
/*
* ===========================================================================
- * (c) Copyright IBM Corp. 2022, 2022 All Rights Reserved
+ * (c) Copyright IBM Corp. 2022, 2023 All Rights Reserved
* ===========================================================================
*/
@@ -43,7 +43,7 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import openj9.internal.security.FIPSConfigurator;
+import openj9.internal.security.RestrictedSecurity;
/**
* This class provides a cryptographically strong random number
@@ -276,36 +276,33 @@ private void getDefaultPRNG(boolean setSeed, byte[] seed) {
Service prngService = null;
String prngAlgorithm = null;
- // If in FIPS mode, use the SecureRandom from the FIPS provider.
- if (FIPSConfigurator.enableFIPS()) {
- Provider p = Security.getProvider("SunPKCS11-NSS-FIPS");
- prngAlgorithm = "PKCS11";
- if (p == null) {
- throw new RuntimeException("could not find SunPKCS11-NSS-FIPS provider for FIPS mode");
- }
- prngService = p.getService("SecureRandom", prngAlgorithm);
- if (prngService == null) {
- throw new RuntimeException("could not find SecureRandom implementation from SunPKCS11-NSS-FIPS");
- }
- } else {
- for (Provider p : Providers.getProviderList().providers()) {
- // SUN provider uses the SunEntries.DEF_SECURE_RANDOM_ALGO
- // as the default SecureRandom algorithm; for other providers,
- // Provider.getDefaultSecureRandom() will use the 1st
- // registered SecureRandom algorithm
- if (p.getName().equals("SUN")) {
- prngAlgorithm = SunEntries.DEF_SECURE_RANDOM_ALGO;
+ for (Provider p : Providers.getProviderList().providers()) {
+ // In restricted security mode, use the SecureRandom from restricted security provider.
+ if (RestrictedSecurity.isEnabled()) {
+ String srProvider = RestrictedSecurity.getRandomProvider();
+ if (p.getName().equals(srProvider)) {
+ prngAlgorithm = RestrictedSecurity.getRandomAlgorithm();
prngService = p.getService("SecureRandom", prngAlgorithm);
break;
- } else {
- prngService = p.getDefaultSecureRandomService();
- if (prngService != null) {
- prngAlgorithm = prngService.getAlgorithm();
- break;
- }
+ }
+ }
+ // SUN provider uses the SunEntries.DEF_SECURE_RANDOM_ALGO
+ // as the default SecureRandom algorithm; for other providers,
+ // Provider.getDefaultSecureRandom() will use the 1st
+ // registered SecureRandom algorithm
+ else if (p.getName().equals("SUN")) {
+ prngAlgorithm = SunEntries.DEF_SECURE_RANDOM_ALGO;
+ prngService = p.getService("SecureRandom", prngAlgorithm);
+ break;
+ } else {
+ prngService = p.getDefaultSecureRandomService();
+ if (prngService != null) {
+ prngAlgorithm = prngService.getAlgorithm();
+ break;
}
}
}
+
// per javadoc, if none of the Providers support an RNG algorithm,
// then an implementation-specific default is returned.
if (prngService == null) {
diff --git a/src/java.base/share/classes/java/security/Security.java b/src/java.base/share/classes/java/security/Security.java
index bc8ea5b3e2f..d74841e71fb 100644
--- a/src/java.base/share/classes/java/security/Security.java
+++ b/src/java.base/share/classes/java/security/Security.java
@@ -25,7 +25,7 @@
/*
* ===========================================================================
- * (c) Copyright IBM Corp. 2022, 2022 All Rights Reserved
+ * (c) Copyright IBM Corp. 2022, 2023 All Rights Reserved
* ===========================================================================
*/
@@ -52,7 +52,7 @@
import openj9.internal.criu.security.CRIUConfigurator;
/*[ENDIF] CRIU_SUPPORT */
-import openj9.internal.security.FIPSConfigurator;
+import openj9.internal.security.RestrictedSecurity;
/**
* This class centralizes all security properties and common security
@@ -144,10 +144,11 @@ private static void initialize() {
}
/*[ENDIF] CRIU_SUPPORT */
- // Load FIPS properties.
- boolean fipsEnabled = FIPSConfigurator.configureFIPS(props);
+ // Load restricted security mode properties.
+ boolean restrictedSecurityEnabled = RestrictedSecurity.configure(props);
if (sdebug != null) {
- sdebug.println(fipsEnabled ? "FIPS mode enabled.": "FIPS mode disabled.");
+ sdebug.println(restrictedSecurityEnabled ? "Restricted security mode enabled."
+ : "Restricted security mode disabled.");
}
}
diff --git a/src/java.base/share/classes/java/util/ServiceLoader.java b/src/java.base/share/classes/java/util/ServiceLoader.java
index 531ffa3f09c..dd6e263e14d 100644
--- a/src/java.base/share/classes/java/util/ServiceLoader.java
+++ b/src/java.base/share/classes/java/util/ServiceLoader.java
@@ -23,6 +23,12 @@
* questions.
*/
+/*
+ * ===========================================================================
+ * (c) Copyright IBM Corp. 2022, 2023 All Rights Reserved
+ * ===========================================================================
+ */
+
package java.util;
import java.io.BufferedReader;
@@ -57,6 +63,8 @@
import jdk.internal.reflect.CallerSensitive;
import jdk.internal.reflect.Reflection;
+import openj9.internal.security.RestrictedSecurity;
+
/**
* A facility to load implementations of a service.
*
@@ -880,6 +888,12 @@ private Provider loadProvider(ServiceProvider provider) {
fail(service, clazz + " is not public");
}
+ if (!RestrictedSecurity.isProviderAllowed(clazz)) {
+ // We're in restricted security mode which does not allow this provider,
+ // then skip it.
+ return null;
+ }
+
// if provider in explicit module then check for static factory method
if (inExplicitModule(clazz)) {
Method factoryMethod = findStaticProviderMethod(clazz);
@@ -1235,6 +1249,11 @@ private boolean hasNextService() {
}
if (service.isAssignableFrom(clazz)) {
+ if (!RestrictedSecurity.isProviderAllowed(clazz)) {
+ // We're in restricted security mode which does not allow this provider,
+ // then skip it.
+ continue;
+ }
Class extends S> type = (Class extends S>) clazz;
Constructor extends S> ctor
= (Constructor extends S>)getConstructor(clazz);
diff --git a/src/java.base/share/classes/sun/security/jca/ProviderConfig.java b/src/java.base/share/classes/sun/security/jca/ProviderConfig.java
index db370e23306..759e3e0bd91 100644
--- a/src/java.base/share/classes/sun/security/jca/ProviderConfig.java
+++ b/src/java.base/share/classes/sun/security/jca/ProviderConfig.java
@@ -39,6 +39,8 @@
import sun.security.util.PropertyExpander;
+import openj9.internal.security.RestrictedSecurity;
+
/**
* Class representing a configured provider which encapsulates configuration
* (provider name + optional argument), the provider loading logic, and
@@ -167,6 +169,11 @@ public String toString() {
*/
@SuppressWarnings("deprecation")
Provider getProvider() {
+ if (!RestrictedSecurity.isProviderAllowed(provName)) {
+ // We're in restricted security mode which does not allow this provider,
+ // then return without loading.
+ return null;
+ }
// volatile variable load
Provider p = provider;
if (p != null) {
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 2bef3b39aa8..45d8ba562f7 100644
--- a/src/java.base/share/classes/sun/security/provider/SunEntries.java
+++ b/src/java.base/share/classes/sun/security/provider/SunEntries.java
@@ -50,8 +50,6 @@
import sun.security.util.SecurityProviderConstants;
import static sun.security.util.SecurityProviderConstants.getAliases;
-import openj9.internal.security.FIPSConfigurator;
-
/**
* Defines the entries of the SUN provider.
*
@@ -157,10 +155,6 @@ public final class SunEntries {
"sun.security.provider.certpath.PKIXCertPathValidator",
attrs);
- if (FIPSConfigurator.enableFIPS()) {
- return;
- }
-
attrs.clear();
/*
* SecureRandom engines
diff --git a/src/java.base/share/conf/security/java.security b/src/java.base/share/conf/security/java.security
index 8156eea7e11..3dbe01fbe6f 100644
--- a/src/java.base/share/conf/security/java.security
+++ b/src/java.base/share/conf/security/java.security
@@ -85,6 +85,58 @@ security.provider.tbd=Apple
#endif
security.provider.tbd=SunPKCS11
+#ifdef linux-x86
+#
+# Java Restricted Security Mode
+#
+RestrictedSecurity1.desc.name = Red Hat Enterprise Linux 8 NSS Cryptographic Module FIPS 140-2
+RestrictedSecurity1.desc.number = Certificate #3946
+RestrictedSecurity1.desc.policy = https://csrc.nist.gov/projects/cryptographic-module-validation-program/certificate/3946
+RestrictedSecurity1.desc.sunsetDate = 2026-06-06
+
+RestrictedSecurity1.tls.disabledNamedCurves =
+RestrictedSecurity1.tls.disabledAlgorithms = X25519, X448, SSLv3, TLSv1, TLSv1.1, \
+ TLS_CHACHA20_POLY1305_SHA256, TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, \
+ TLS_DHE_DSS_WITH_AES_256_GCM_SHA384, TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, \
+ TLS_DHE_DSS_WITH_AES_128_GCM_SHA256, TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, \
+ TLS_DHE_DSS_WITH_AES_256_CBC_SHA256, TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, \
+ TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, TLS_DHE_RSA_WITH_AES_256_CBC_SHA, \
+ TLS_DHE_DSS_WITH_AES_256_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, \
+ TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_256_GCM_SHA384, \
+ TLS_RSA_WITH_AES_128_GCM_SHA256, TLS_RSA_WITH_AES_256_CBC_SHA256, \
+ TLS_RSA_WITH_AES_128_CBC_SHA256, TLS_RSA_WITH_AES_256_CBC_SHA, \
+ TLS_RSA_WITH_AES_128_CBC_SHA, TLS_AES_256_GCM_SHA384, \
+ TLS_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, \
+ TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, \
+ TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, \
+ TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, \
+ TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, \
+ TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256, \
+ TLS_EMPTY_RENEGOTIATION_INFO_SCSV
+RestrictedSecurity1.tls.ephemeralDHKeySize =
+RestrictedSecurity1.tls.legacyAlgorithms =
+
+RestrictedSecurity1.jce.certpath.disabledAlgorithms =
+RestrictedSecurity1.jce.legacyAlgorithms =
+RestrictedSecurity1.jce.provider.1 = SunPKCS11 ${java.home}/conf/security/nss.fips.cfg
+RestrictedSecurity1.jce.provider.2 = SUN [{CertificateFactory, X.509, ImplementedIn=Software}, \
+ {CertStore, Collection, ImplementedIn=Software}, \
+ {CertStore, com.sun.security.IndexedCollection, ImplementedIn=Software}, \
+ {Policy, JavaPolicy, *}, {Configuration, JavaLoginConfig, *}, \
+ {CertPathBuilder, PKIX, ValidationAlgorithm=RFC5280:ImplementedIn=Software}, \
+ {CertPathValidator, PKIX, ValidationAlgorithm=RFC5280:ImplementedIn=Software}]
+RestrictedSecurity1.jce.provider.3 = SunEC [{KeyFactory, EC, ImplementedIn=Software: \
+ SupportedKeyClasses=java.security.interfaces.ECPublicKey|java.security.interfaces.ECPrivateKey: \
+ KeySize=256}, {AlgorithmParameters, EC, *}]
+RestrictedSecurity1.jce.provider.4 = SunJSSE
+
+RestrictedSecurity1.keystore.type = PKCS11
+RestrictedSecurity1.javax.net.ssl.keyStore = NONE
+
+RestrictedSecurity1.securerandom.provider = SunPKCS11-NSS-FIPS
+RestrictedSecurity1.securerandom.algorithm = PKCS11
+#endif
+
#
# A list of preferred providers for specific algorithms. These providers will
# be searched for matching algorithms before the list of registered providers.
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 d18ad43313e..f4e3e4d21b6 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
@@ -55,7 +55,7 @@
import com.sun.crypto.provider.ChaCha20Poly1305Parameters;
import jdk.internal.misc.InnocuousThread;
-import openj9.internal.security.FIPSConfigurator;
+import openj9.internal.security.RestrictedSecurity;
import sun.security.util.Debug;
import sun.security.util.ResourcesMgr;
import static sun.security.util.SecurityConstants.PROVIDER_VER;
@@ -120,7 +120,7 @@ public final class SunPKCS11 extends AuthProvider {
// This is the SunPKCS11 provider instance
// there can only be a single PKCS11 provider in
- // FIPS mode.
+ // restricted security FIPS mode.
static SunPKCS11 mysunpkcs11;
Token getToken() {
@@ -439,11 +439,11 @@ private static T checkNull(T obj) {
nssModule.setProvider(this);
}
- // When FIPS mode is enabled, configure p11 object to FIPS mode
- // and pass the parent object so it can callback.
- if (FIPSConfigurator.enableFIPS()) {
+ // When restricted security FIPS mode is enabled, configure p11 object
+ // to FIPS mode and pass the parent object so it can callback.
+ if (RestrictedSecurity.isFIPSEnabled()) {
if (debug != null) {
- System.out.println("FIPS mode in SunPKCS11");
+ debug.println("Restricted security FIPS mode in SunPKCS11");
}
@SuppressWarnings("unchecked")
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 b1984f5015d..f1213f4061c 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
@@ -159,7 +159,7 @@ static boolean isKey(CK_ATTRIBUTE[] attrs) {
// This is the SunPKCS11 provider instance
// there can only be a single PKCS11 provider in
- // FIPS mode.
+ // restricted security FIPS mode.
private static SunPKCS11 mysunpkcs11;
private static final class InnerPKCS11 extends PKCS11 implements Consumer {
@@ -167,15 +167,15 @@ private static final class InnerPKCS11 extends PKCS11 implements Consumer