diff --git a/closed/src/java.base/share/classes/openj9/internal/security/RestrictedSecurity.java b/closed/src/java.base/share/classes/openj9/internal/security/RestrictedSecurity.java
index 8746034d959..1f805ecf20c 100644
--- a/closed/src/java.base/share/classes/openj9/internal/security/RestrictedSecurity.java
+++ b/closed/src/java.base/share/classes/openj9/internal/security/RestrictedSecurity.java
@@ -232,14 +232,27 @@ public static boolean isFIPSEnabled() {
}
/**
- * Check if the service is allowed in restricted security mode.
+ * Check if the service is allowed to be used in restricted security mode.
*
* @param service the service to check
- * @return true if the service is allowed
+ * @return true if the service is allowed to be used
*/
public static boolean isServiceAllowed(Service service) {
if (securityEnabled) {
- return restricts.isRestrictedServiceAllowed(service);
+ return restricts.isRestrictedServiceAllowed(service, true);
+ }
+ return true;
+ }
+
+ /**
+ * Check if the service is allowed to be registered in restricted security mode.
+ *
+ * @param service the service to check
+ * @return true if the service is allowed to be registered
+ */
+ public static boolean canServiceBeRegistered(Service service) {
+ if (securityEnabled) {
+ return restricts.isRestrictedServiceAllowed(service, false);
}
return true;
}
@@ -740,10 +753,11 @@ private RestrictedSecurityProperties(String profileID, ProfileParser parser) {
/**
* Check if the Service is allowed in restricted security mode.
*
- * @param service the Service to check
+ * @param service the Service to check
+ * @param checkUse should its attempted use be checked against the accepted
* @return true if the Service is allowed
*/
- boolean isRestrictedServiceAllowed(Service service) {
+ boolean isRestrictedServiceAllowed(Service service, boolean checkUse) {
Provider provider = service.getProvider();
String providerClassName = provider.getClass().getName();
@@ -779,11 +793,13 @@ boolean isRestrictedServiceAllowed(Service service) {
String cType = constraint.type;
String cAlgorithm = constraint.algorithm;
String cAttribute = constraint.attributes;
+ String cAcceptedUses = constraint.acceptedUses;
if (debug != null) {
debug.println("Checking provider constraint:"
+ "\n\tService type: " + cType
+ "\n\tAlgorithm: " + cAlgorithm
- + "\n\tAttributes: " + cAttribute);
+ + "\n\tAttributes: " + cAttribute
+ + "\n\tAccepted uses: " + cAcceptedUses);
}
if (!isAsterisk(cType) && !type.equals(cType)) {
@@ -801,56 +817,114 @@ boolean isRestrictedServiceAllowed(Service service) {
continue;
}
- // For type and algorithm match, and attribute is *.
- if (isAsterisk(cAttribute)) {
- if (debug != null) {
- debug.println("The following service:"
- + "\n\tService type: " + type
- + "\n\tAlgorithm: " + algorithm
- + "\nis allowed in provider: " + providerClassName);
- }
- return true;
- }
-
// For type and algorithm match, and attribute is not *.
// Then continue checking attributes.
- String[] cAttributeArray = cAttribute.split(":");
+ if (!isAsterisk(cAttribute)) {
+ String[] cAttributeArray = cAttribute.split(":");
- // For each attribute, must be all matched for return allowed.
- for (String attribute : cAttributeArray) {
- String[] input = attribute.split("=", 2);
+ // For each attribute, must be all matched for return allowed.
+ for (String attribute : cAttributeArray) {
+ String[] input = attribute.split("=", 2);
- String cName = input[0].trim();
- String cValue = input[1].trim();
- String sValue = service.getAttribute(cName);
- if (debug != null) {
- debug.println("Checking specific attribute with:"
- + "\n\tName: " + cName
- + "\n\tValue: " + cValue
- + "\nagainst the service attribute value: " + sValue);
+ String cName = input[0].trim();
+ String cValue = input[1].trim();
+ String sValue = service.getAttribute(cName);
+ if (debug != null) {
+ debug.println("Checking specific attribute with:"
+ + "\n\tName: " + cName
+ + "\n\tValue: " + cValue
+ + "\nagainst the service attribute value: " + sValue);
+ }
+ if ((sValue == null) || !cValue.equalsIgnoreCase(sValue)) {
+ // If any attribute doesn't match, return service is not allowed.
+ if (debug != null) {
+ debug.println("Attributes don't match!");
+ debug.println("The following service:"
+ + "\n\tService type: " + type
+ + "\n\tAlgorithm: " + algorithm
+ + "\n\tAttribute: " + cAttribute
+ + "\nis NOT allowed in provider: " + providerClassName);
+ }
+ return false;
+ }
+ if (debug != null) {
+ debug.println("Attributes match!");
+ }
}
- if ((sValue == null) || !cValue.equalsIgnoreCase(sValue)) {
- // If any attribute doesn't match, return service is not allowed.
+ }
+
+ // See if accepted uses have been specified and apply
+ // them to the call stack.
+ if (checkUse && (cAcceptedUses != null)) {
+ String[] optionAndValue = cAcceptedUses.split(":");
+ String option = optionAndValue[0];
+ String value = optionAndValue[1];
+ StackTraceElement[] stackElements = Thread.currentThread().getStackTrace();
+ boolean found = false;
+ for (StackTraceElement stackElement : stackElements) {
if (debug != null) {
- debug.println("Attributes don't match!");
+ debug.println("Attempting to match " + stackElement + " with: " + option + " : " + value);
+ }
+ String stackElemModule = stackElement.getModuleName();
+ String stackElemFullClassName = stackElement.getClassName();
+ int stackElemEnd = stackElemFullClassName.lastIndexOf('.');
+ String stackElemPackage = null;
+ if (stackElemEnd != -1) {
+ stackElemPackage = stackElemFullClassName.substring(0, stackElemEnd);
+ }
+ String module;
+ switch (option) {
+ case "ModuleAndFullClassName":
+ String[] moduleAndFullClassName = value.split("/");
+ module = moduleAndFullClassName[0];
+ String fullClassName = moduleAndFullClassName[1];
+ found = module.equals(stackElemModule) && stackElemFullClassName.equals(fullClassName);
+ break;
+ case "ModuleAndPackage":
+ String[] moduleAndPackage = value.split("/");
+ module = moduleAndPackage[0];
+ String packageValue = moduleAndPackage[1];
+ found = module.equals(stackElemModule) && packageValue.equals(stackElemPackage);
+ break;
+ case "FullClassName":
+ found = stackElemFullClassName.equals(value);
+ break;
+ case "Package":
+ found = value.equals(stackElemPackage);
+ break;
+ default:
+ printStackTraceAndExit("Incorrect option to match in constraint: " + constraint);
+ break;
+ }
+
+ if (found) {
+ break;
+ }
+ }
+
+ // If nothing matching the accepted uses is found in the call stack,
+ // this service is not allowed.
+ if (!found) {
+ if (debug != null) {
+ debug.println("Classes in call stack are not part of accepted uses!");
debug.println("The following service:"
+ "\n\tService type: " + type
+ "\n\tAlgorithm: " + algorithm
+ "\n\tAttribute: " + cAttribute
+ + "\n\tAccepted uses: " + cAcceptedUses
+ "\nis NOT allowed in provider: " + providerClassName);
}
return false;
}
- if (debug != null) {
- debug.println("Attributes match!");
- }
}
+
if (debug != null) {
debug.println("All attributes matched!");
debug.println("The following service:"
+ "\n\tService type: " + type
+ "\n\tAlgorithm: " + algorithm
+ "\n\tAttribute: " + cAttribute
+ + "\n\tAccepted uses: " + cAcceptedUses
+ "\nis allowed in provider: " + providerClassName);
}
return true;
@@ -1437,7 +1511,8 @@ private void setConstraints(String providerName, String providerInfo, boolean pr
final String typeRE = "\\w+";
final String algoRE = "[A-Za-z0-9./_-]+";
final String attrRE = "[A-Za-z0-9=*|.:]+";
- final String consRE = "\\{(" + typeRE + "),(" + algoRE + "),(" + attrRE + ")\\}";
+ final String usesRE = "[A-Za-z0-9._:/$]+";
+ final String consRE = "\\{(" + typeRE + "),(" + algoRE + "),(" + attrRE + ")(," + usesRE + ")?\\}";
p = Pattern.compile(
"\\["
+ "([+-]?)" // option to append or remove
@@ -1460,6 +1535,42 @@ private void setConstraints(String providerName, String providerInfo, boolean pr
String inType = m.group(1);
String inAlgorithm = m.group(2);
String inAttributes = m.group(3);
+ String inAcceptedUses = m.group(4);
+
+ if (inAcceptedUses != null) {
+ inAcceptedUses = inAcceptedUses.substring(1);
+ boolean isSpecIncorrect = false;
+ String[] optionAndValue = inAcceptedUses.split(":");
+ if (optionAndValue.length != 2) {
+ isSpecIncorrect = true;
+ } else {
+ String option = optionAndValue[0];
+ String value = optionAndValue[1];
+ switch (option) {
+ case "ModuleAndFullClassName":
+ if (value.split("/").length != 2) {
+ isSpecIncorrect = true;
+ }
+ break;
+ case "ModuleAndPackage":
+ if (value.split("/").length != 2) {
+ isSpecIncorrect = true;
+ }
+ break;
+ case "FullClassName":
+ case "Package":
+ // Nothing further to check in those options.
+ break;
+ default:
+ isSpecIncorrect = true;
+ break;
+ }
+ }
+ if (isSpecIncorrect) {
+ printStackTraceAndExit("Incorrect specification of accepted uses in constraint for "
+ + inType + ", " + inAlgorithm + ": " + inAcceptedUses);
+ }
+ }
// Each attribute must includes 2 fields (key and value) or *.
if (!isAsterisk(inAttributes)) {
@@ -1472,7 +1583,8 @@ private void setConstraints(String providerName, String providerInfo, boolean pr
}
}
}
- Constraint constraint = new Constraint(inType, inAlgorithm, inAttributes);
+
+ Constraint constraint = new Constraint(inType, inAlgorithm, inAttributes, inAcceptedUses);
constraints.add(constraint);
}
@@ -1743,7 +1855,7 @@ private static void checkProviderFormat(String providerInfo, boolean update) {
+ "(\\[" // constraints [optional]
+ "\\s*"
+ "([+-])?" // action [optional]
- + "[A-Za-z0-9{}.=*|:,/_\\s-]+" // constraint definition
+ + "[A-Za-z0-9{}.=*|:$,/_\\s-]+" // constraint definition
+ "\\])?"
+ "\\s*"
+ "$");
@@ -1806,17 +1918,27 @@ private static final class Constraint {
final String type;
final String algorithm;
final String attributes;
+ final String acceptedUses;
- Constraint(String type, String algorithm, String attributes) {
+ Constraint(String type, String algorithm, String attributes, String acceptedUses) {
super();
this.type = type;
this.algorithm = algorithm;
this.attributes = attributes;
+ this.acceptedUses = acceptedUses;
}
@Override
public String toString() {
- return "{" + type + ", " + algorithm + ", " + attributes + "}";
+ StringBuilder buffer = new StringBuilder();
+ buffer.append("{").append(type);
+ buffer.append(", ").append(algorithm);
+ buffer.append(", ").append(attributes);
+ if (acceptedUses != null) {
+ buffer.append(", ").append(acceptedUses);
+ }
+ buffer.append("}");
+ return buffer.toString();
}
@Override
@@ -1827,14 +1949,15 @@ public boolean equals(Object obj) {
if (obj instanceof Constraint other) {
return Objects.equals(type, other.type)
&& Objects.equals(algorithm, other.algorithm)
- && Objects.equals(attributes, other.attributes);
+ && Objects.equals(attributes, other.attributes)
+ && Objects.equals(acceptedUses, other.acceptedUses);
}
return false;
}
@Override
public int hashCode() {
- return Objects.hash(type, algorithm, attributes);
+ return Objects.hash(type, algorithm, attributes, acceptedUses);
}
}
}
diff --git a/closed/test/jdk/openj9/internal/security/TestConstraintsFailure.java b/closed/test/jdk/openj9/internal/security/TestConstraintsFailure.java
new file mode 100644
index 00000000000..4a778bccd23
--- /dev/null
+++ b/closed/test/jdk/openj9/internal/security/TestConstraintsFailure.java
@@ -0,0 +1,186 @@
+/*
+ * ===========================================================================
+ * (c) Copyright IBM Corp. 2025, 2025 All Rights Reserved
+ * ===========================================================================
+ *
+ * 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.
+ *
+ * IBM designates this particular file as subject to the "Classpath" exception
+ * as provided by IBM 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, see .
+ *
+ * ===========================================================================
+ */
+
+/*
+ * @test
+ * @summary Test Restricted Security Mode Constraints
+ * @library /test/lib
+ * @run junit TestConstraintsFailure
+ */
+import org.junit.jupiter.api.Test;
+
+import java.security.AlgorithmParameterGenerator;
+import java.security.KeyFactory;
+import java.security.KeyPairGenerator;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.Signature;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.CertPathValidator;
+import java.security.cert.CertStore;
+
+import javax.crypto.Cipher;
+//import javax.crypto.KDF;
+import javax.crypto.KeyAgreement;
+import javax.crypto.KeyGenerator;
+import javax.crypto.Mac;
+import javax.crypto.SecretKeyFactory;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManagerFactory;
+
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
+
+public class TestConstraintsFailure {
+
+ private static void getInstances() throws Exception {
+ try {
+ CertificateFactory.getInstance("X.509");
+ throw new RuntimeException("A CertificateException should have been thrown");
+ } catch (CertificateException ce) {
+ // Do nothing. This is expected.
+ }
+ try {
+ CertPathValidator.getInstance("PKIX");
+ throw new RuntimeException("A NoSuchAlgorithmException should have been thrown");
+ } catch (NoSuchAlgorithmException nsae) {
+ // Do nothing. This is expected.
+ }
+ try {
+ MessageDigest.getInstance("SHA-512");
+ throw new RuntimeException("A NoSuchAlgorithmException should have been thrown");
+ } catch (NoSuchAlgorithmException nsae) {
+ // Do nothing. This is expected.
+ }
+ try {
+ KeyStore.getInstance("PKCS12");
+ throw new RuntimeException("A KeyStoreException should have been thrown");
+ } catch (KeyStoreException ke) {
+ // Do nothing. This is expected.
+ }
+ try {
+ Signature.getInstance("SHA256withECDSA");
+ throw new RuntimeException("A NoSuchAlgorithmException should have been thrown");
+ } catch (NoSuchAlgorithmException nsae) {
+ // Do nothing. This is expected.
+ }
+ try {
+ KeyPairGenerator.getInstance("EC");
+ throw new RuntimeException("A NoSuchAlgorithmException should have been thrown");
+ } catch (NoSuchAlgorithmException nsae) {
+ // Do nothing. This is expected.
+ }
+ try {
+ KeyAgreement.getInstance("ECDH");
+ throw new RuntimeException("A NoSuchAlgorithmException should have been thrown");
+ } catch (NoSuchAlgorithmException nsae) {
+ // Do nothing. This is expected.
+ }
+ try {
+ KeyFactory.getInstance("EC");
+ throw new RuntimeException("A NoSuchAlgorithmException should have been thrown");
+ } catch (NoSuchAlgorithmException nsae) {
+ // Do nothing. This is expected.
+ }
+ try {
+ Cipher.getInstance("RSA");
+ throw new RuntimeException("A NoSuchAlgorithmException should have been thrown");
+ } catch (NoSuchAlgorithmException nsae) {
+ // Do nothing. This is expected.
+ }
+ try {
+ KeyGenerator.getInstance("AES");
+ throw new RuntimeException("A NoSuchAlgorithmException should have been thrown");
+ } catch (NoSuchAlgorithmException nsae) {
+ // Do nothing. This is expected.
+ }
+ try {
+ AlgorithmParameterGenerator.getInstance("DiffieHellman");
+ throw new RuntimeException("A NoSuchAlgorithmException should have been thrown");
+ } catch (NoSuchAlgorithmException nsae) {
+ // Do nothing. This is expected.
+ }
+
+ // Still a preview, but can be enabled in future versions.
+ /*
+ try {
+ KDF.getInstance("HKDF-SHA256");
+ throw new RuntimeException("A NoSuchAlgorithmException should have been thrown");
+ } catch (NoSuchAlgorithmException nsae) {
+ // Do nothing. This is expected.
+ }
+ */
+
+ try {
+ SecretKeyFactory.getInstance("PBEWithMD5AndDES");
+ throw new RuntimeException("A NoSuchAlgorithmException should have been thrown");
+ } catch (NoSuchAlgorithmException nsae) {
+ // Do nothing. This is expected.
+ }
+ try {
+ Mac.getInstance("HmacSHA256");
+ throw new RuntimeException("A NoSuchAlgorithmException should have been thrown");
+ } catch (NoSuchAlgorithmException nsae) {
+ // Do nothing. This is expected.
+ }
+
+ try {
+ KeyManagerFactory.getInstance("SunX509");
+ throw new RuntimeException("A NoSuchAlgorithmException should have been thrown");
+ } catch (NoSuchAlgorithmException nsae) {
+ // Do nothing. This is expected.
+ }
+ try {
+ TrustManagerFactory.getInstance("SunX509");
+ throw new RuntimeException("A NoSuchAlgorithmException should have been thrown");
+ } catch (NoSuchAlgorithmException nsae) {
+ // Do nothing. This is expected.
+ }
+ try {
+ SSLContext.getInstance("TLSv1.3");
+ throw new RuntimeException("A NoSuchAlgorithmException should have been thrown");
+ } catch (NoSuchAlgorithmException nsae) {
+ // Do nothing. This is expected.
+ }
+ }
+
+ @Test
+ public void runWithConstraints() throws Exception {
+ OutputAnalyzer outputAnalyzer = ProcessTools.executeTestJava(
+ "-Dsemeru.customprofile=TestConstraints.Version",
+ "-Djava.security.properties=" + System.getProperty("test.src") + "/constraints-java.security",
+ "TestConstraintsFailure"
+ );
+ outputAnalyzer.reportDiagnosticSummary();
+ outputAnalyzer.shouldHaveExitValue(0);
+ }
+
+ public static void main(String[] args) throws Exception {
+ getInstances();
+ }
+}
diff --git a/closed/test/jdk/openj9/internal/security/TestConstraintsSuccess.java b/closed/test/jdk/openj9/internal/security/TestConstraintsSuccess.java
new file mode 100644
index 00000000000..1b0b672479a
--- /dev/null
+++ b/closed/test/jdk/openj9/internal/security/TestConstraintsSuccess.java
@@ -0,0 +1,96 @@
+/*
+ * ===========================================================================
+ * (c) Copyright IBM Corp. 2025, 2025 All Rights Reserved
+ * ===========================================================================
+ *
+ * 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.
+ *
+ * IBM designates this particular file as subject to the "Classpath" exception
+ * as provided by IBM 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, see .
+ *
+ * ===========================================================================
+ */
+
+/*
+ * @test
+ * @summary Test Restricted Security Mode Constraints
+ * @library /test/lib
+ * @run junit TestConstraintsSuccess
+ */
+import org.junit.jupiter.api.Test;
+
+import java.security.AlgorithmParameterGenerator;
+import java.security.KeyFactory;
+import java.security.KeyPairGenerator;
+import java.security.KeyStore;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.Signature;
+import java.security.cert.CertificateFactory;
+import java.security.cert.CertPathValidator;
+import java.security.cert.CertStore;
+
+import javax.crypto.Cipher;
+//import javax.crypto.KDF;
+import javax.crypto.KeyAgreement;
+import javax.crypto.KeyGenerator;
+import javax.crypto.Mac;
+import javax.crypto.SecretKeyFactory;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManagerFactory;
+
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
+
+public class TestConstraintsSuccess {
+
+ private static void getInstances() throws Exception {
+ CertificateFactory.getInstance("X.509");
+ CertPathValidator.getInstance("PKIX");
+ MessageDigest.getInstance("SHA-512");
+ KeyStore.getInstance("PKCS12");
+ Signature.getInstance("SHA256withECDSA");
+ KeyPairGenerator.getInstance("EC");
+ KeyAgreement.getInstance("ECDH");
+ KeyFactory.getInstance("EC");
+ Cipher.getInstance("RSA");
+ KeyGenerator.getInstance("AES");
+ AlgorithmParameterGenerator.getInstance("DiffieHellman");
+
+ // Still a preview, but can be enabled in future versions.
+ // KDF.getInstance("HKDF-SHA256");
+
+ SecretKeyFactory.getInstance("PBEWithMD5AndDES");
+ Mac.getInstance("HmacSHA256");
+ KeyManagerFactory.getInstance("SunX509");
+ TrustManagerFactory.getInstance("SunX509");
+ SSLContext.getInstance("TLSv1.3");
+ }
+
+ @Test
+ public void runWithConstraints() throws Exception {
+ OutputAnalyzer outputAnalyzer = ProcessTools.executeTestJava(
+ "-Dsemeru.customprofile=TestConstraints.Version",
+ "-Djava.security.properties=" + System.getProperty("test.src") + "/constraints-java.security",
+ "TestConstraintsSuccess"
+ );
+ outputAnalyzer.reportDiagnosticSummary();
+ outputAnalyzer.shouldHaveExitValue(0);
+ }
+
+ public static void main(String[] args) throws Exception {
+ getInstances();
+ }
+}
diff --git a/closed/test/jdk/openj9/internal/security/constraints-java.security b/closed/test/jdk/openj9/internal/security/constraints-java.security
new file mode 100644
index 00000000000..bcc7eb1fd4b
--- /dev/null
+++ b/closed/test/jdk/openj9/internal/security/constraints-java.security
@@ -0,0 +1,63 @@
+# ===========================================================================
+# (c) Copyright IBM Corp. 2025, 2025 All Rights Reserved
+# ===========================================================================
+# 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.
+#
+# IBM designates this particular file as subject to the "Classpath" exception
+# as provided by IBM 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, see .
+# ===========================================================================
+
+RestrictedSecurity.TestConstraints.Version.desc.name = Test Base Profile
+RestrictedSecurity.TestConstraints.Version.desc.default = false
+RestrictedSecurity.TestConstraints.Version.desc.fips = false
+RestrictedSecurity.TestConstraints.Version.desc.hash = SHA256:b7b4188e2932d3c805eacf21a0feaf282a7906743f94e31e0a32641980d6e459
+RestrictedSecurity.TestConstraints.Version.desc.number = Certificate #XXX
+RestrictedSecurity.TestConstraints.Version.desc.policy =
+RestrictedSecurity.TestConstraints.Version.fips.mode = test
+
+RestrictedSecurity.TestConstraints.Version.jce.provider.1 = sun.security.provider.Sun [ \
+ {CertificateFactory, X.509, *, FullClassName:TestConstraintsSuccess}, \
+ {CertStore, Collection, *, FullClassName:TestConstraintsSuccess}, \
+ {Configuration, JavaLoginConfig, *, FullClassName:TestConstraintsSuccess}, \
+ {CertPathBuilder, PKIX, *, FullClassName:TestConstraintsSuccess}, \
+ {CertPathValidator, PKIX, *, FullClassName:TestConstraintsSuccess}, \
+ {SecureRandom, SHA1PRNG, *, FullClassName:TestConstraintsSuccess}, \
+ {MessageDigest, SHA-256, *}, \
+ {MessageDigest, SHA-512, *, FullClassName:TestConstraintsSuccess}, \
+ {KeyStore, PKCS12, *, FullClassName:TestConstraintsSuccess}]
+RestrictedSecurity.TestConstraints.Version.jce.provider.2 = sun.security.ec.SunEC [ \
+ {AlgorithmParameters, EC, *, ModuleAndFullClassName:java.base/java.security.KeyPairGenerator}, \
+ {Signature, SHA256withECDSA, *, FullClassName:TestConstraintsSuccess}, \
+ {KeyPairGenerator, EC, *, FullClassName:TestConstraintsSuccess}, \
+ {KeyAgreement, ECDH, *, FullClassName:TestConstraintsSuccess}, \
+ {KeyFactory, EC, *, FullClassName:TestConstraintsSuccess}]
+RestrictedSecurity.TestConstraints.Version.jce.provider.3 = com.sun.crypto.provider.SunJCE [ \
+ {Cipher, RSA, *, FullClassName:TestConstraintsSuccess}, \
+ {KeyGenerator, AES, *, FullClassName:TestConstraintsSuccess}, \
+ {AlgorithmParameterGenerator, DiffieHellman, *, FullClassName:TestConstraintsSuccess}, \
+ {KDF, HKDF-SHA256, *, FullClassName:TestConstraintsSuccess}, \
+ {SecretKeyFactory, PBEWithMD5AndDES, *, FullClassName:TestConstraintsSuccess}, \
+ {Mac, HmacSHA256, *, FullClassName:TestConstraintsSuccess}, \
+ {AlgorithmParameters, PBES2, *, ModuleAndFullClassName:java.base/sun.security.pkcs12.PKCS12KeyStore}, \
+ {AlgorithmParameters, PBEWithHmacSHA256AndAES_256, *, ModuleAndFullClassName:java.base/sun.security.pkcs12.PKCS12KeyStore}, \
+ {SecretKeyFactory, PBEWithMD5AndDES, *, ModuleAndFullClassName:java.base/sun.security.pkcs12.PKCS12KeyStore}, \
+ {Cipher, PBEWithHmacSHA256AndAES_256, *, ModuleAndFullClassName:java.base/sun.security.pkcs12.PKCS12KeyStore}, \
+ {Mac, HmacPBESHA256, *, ModuleAndFullClassName:java.base/sun.security.pkcs12.PKCS12KeyStore}]
+RestrictedSecurity.TestConstraints.Version.jce.provider.4 = sun.security.ssl.SunJSSE [ \
+ {KeyManagerFactory, SunX509, *, FullClassName:TestConstraintsSuccess}, \
+ {TrustManagerFactory, SunX509, *, FullClassName:TestConstraintsSuccess}, \
+ {SSLContext, TLSv1.3, *, FullClassName:TestConstraintsSuccess}]
+
+RestrictedSecurity.TestConstraints.Version.securerandom.provider = SUN
+RestrictedSecurity.TestConstraints.Version.securerandom.algorithm = SHA512DRBG
diff --git a/src/java.base/share/classes/java/security/Provider.java b/src/java.base/share/classes/java/security/Provider.java
index 9e757a88da2..24176e40c15 100644
--- a/src/java.base/share/classes/java/security/Provider.java
+++ b/src/java.base/share/classes/java/security/Provider.java
@@ -25,7 +25,7 @@
/*
* ===========================================================================
- * (c) Copyright IBM Corp. 2022, 2023 All Rights Reserved
+ * (c) Copyright IBM Corp. 2022, 2025 All Rights Reserved
* ===========================================================================
*/
@@ -1238,7 +1238,7 @@ protected void putService(Service s) {
throw new IllegalArgumentException
("service.getProvider() must match this Provider object");
}
- if (!RestrictedSecurity.isServiceAllowed(s)) {
+ if (!RestrictedSecurity.canServiceBeRegistered(s)) {
// We're in restricted security mode which does not allow this service,
// return without registering.
return;
diff --git a/src/java.base/share/conf/security/java.security b/src/java.base/share/conf/security/java.security
index 5b7f268e850..c66191bea90 100644
--- a/src/java.base/share/conf/security/java.security
+++ b/src/java.base/share/conf/security/java.security
@@ -212,7 +212,7 @@ RestrictedSecurity.NSS.140-2.securerandom.algorithm = PKCS11
RestrictedSecurity.OpenJCEPlusFIPS.FIPS140-3.desc.name = OpenJCEPlusFIPS Cryptographic Module FIPS 140-3
RestrictedSecurity.OpenJCEPlusFIPS.FIPS140-3.desc.default = false
RestrictedSecurity.OpenJCEPlusFIPS.FIPS140-3.desc.fips = true
-RestrictedSecurity.OpenJCEPlusFIPS.FIPS140-3.desc.hash = SHA256:d817223b9a608c35ee1301ee8a42fcca0ca5c6a9b830c5658c18dc7818fd5f27
+RestrictedSecurity.OpenJCEPlusFIPS.FIPS140-3.desc.hash = SHA256:255c7615e983c0a5b13a6a5fbcde19b373c182db4fbf80aac81a11954e86a80e
RestrictedSecurity.OpenJCEPlusFIPS.FIPS140-3.desc.number = Certificate #XXX
RestrictedSecurity.OpenJCEPlusFIPS.FIPS140-3.desc.policy = https://csrc.nist.gov/projects/cryptographic-module-validation-program/certificate/
RestrictedSecurity.OpenJCEPlusFIPS.FIPS140-3.desc.sunsetDate = 2026-09-21
@@ -294,6 +294,8 @@ RestrictedSecurity.OpenJCEPlusFIPS.FIPS140-3.jce.provider.1 = com.ibm.crypto.plu
{Mac, HmacSHA3-512, *}, \
{Mac, HmacSHA384, *}, \
{Mac, HmacSHA512, *}, \
+ {MessageDigest, MD5, *, ModuleAndFullClassName:java.base/java.util.UUID}, \
+ {MessageDigest, SHA-1, *, ModuleAndFullClassName:java.base/java.io.ObjectStreamClass}, \
{MessageDigest, SHA-224, *}, \
{MessageDigest, SHA-256, *}, \
{MessageDigest, SHA-384, *}, \