From 0dfa40dbd887746b2db9af99f8ebd1e2cd4089ad Mon Sep 17 00:00:00 2001 From: Tao Liu Date: Wed, 4 Oct 2023 16:36:58 -0400 Subject: [PATCH] Restrict SunPKCS11 non-FIPS algorithms --- .../internal/security/RestrictedSecurity.java | 68 +++++++++++++------ .../share/conf/security/java.security | 22 +++--- 2 files changed, 59 insertions(+), 31 deletions(-) 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 3d972a23f00..63c9e9d14e7 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 @@ -668,7 +668,7 @@ private void initConstraints() { continue; } - // Remove the whitespaces in the format separator if there are. + // Remove the whitespaces in the format separator if present. providerInfo = providerInfo.trim() .replaceAll("\\[\\s+\\{", "[{") .replaceAll("\\}\\s+\\]", "}]") @@ -690,18 +690,31 @@ private void initConstraints() { // For each constraint type, algorithm and attributes. Constraint[] constraints = new Constraint[constrArray.length]; + Boolean allowFlag = null; int cNum = 0; for (String constr : constrArray) { String[] input = constr.split(","); - // Each constraint must includes 3 fields(type, algorithm, attributes). - if (input.length != 3) { + // Each constraint must includes 4 fields(isAllow, type, algorithm, attributes). + if (input.length != 4) { printStackTraceAndExit("Constraint format is incorrect: " + providerInfo); } - String inType = input[0].trim(); - String inAlgorithm = input[1].trim(); - String inAttributes = input[2].trim(); + Boolean inIsAllow = Boolean.valueOf(input[0].trim()); + String inType = input[1].trim(); + String inAlgorithm = input[2].trim(); + String inAttributes = input[3].trim(); + + // All contraints either all allowed or all disallowed. + if (allowFlag == null) { + allowFlag = inIsAllow; + } else { + if (!allowFlag.equals(inIsAllow)) { + printStackTraceAndExit( + "Constraint format is incorrect. All contraints either all allowed or all disallowed: " + + providerInfo); + } + } // Each attribute must includes 2 fields (key and value) or *. if (!isAsterisk(inAttributes)) { @@ -715,11 +728,12 @@ private void initConstraints() { } } - Constraint constraint = new Constraint(inType, inAlgorithm, inAttributes); + Constraint constraint = new Constraint(inIsAllow.booleanValue(), inType, inAlgorithm, inAttributes); if (debug != null) { debug.println("Loading constraints for security provider: " + providerName - + " with constraints type: " + inType + + " with constraints isAllow: " + inIsAllow + + " type: " + inType + " algorithm: " + inAlgorithm + " attributes: " + inAttributes); } @@ -754,6 +768,10 @@ boolean isRestrictedServiceAllowed(Service service) { if (constraints == null) { // Disallow unknown providers. + if (debug != null) { + debug.println("Security constraints check." + + " Disallow unknown provider: " + providerName); + } return false; } else if (constraints.length == 0) { // Allow this provider with no constraints. @@ -764,7 +782,9 @@ boolean isRestrictedServiceAllowed(Service service) { String type = service.getType(); String algorithm = service.getAlgorithm(); + boolean cIsAllow = false; for (Constraint constraint : constraints) { + cIsAllow = constraint.isAllow; String cType = constraint.type; String cAlgorithm = constraint.algorithm; String cAttribute = constraint.attributes; @@ -774,7 +794,7 @@ boolean isRestrictedServiceAllowed(Service service) { continue; } if (!isAsterisk(cAlgorithm) && !algorithm.equalsIgnoreCase(cAlgorithm)) { - // The constraint doesn't apply to the service algorith. + // The constraint doesn't apply to the service algorithm. continue; } @@ -784,16 +804,17 @@ boolean isRestrictedServiceAllowed(Service service) { debug.println("Security constraints check." + " Service type: " + type + " Algorithm: " + algorithm - + " is allowed in provider " + providerName); + + " is allowed: " + cIsAllow + + " in provider: " + providerName); } - return true; + return cIsAllow; } // For type and algorithm match, and attribute is not *. // Then continue checking attributes. String[] cAttributeArray = cAttribute.split(":"); - // For each attribute, must be all matched for return allowed. + // For each attribute, must be all matched for return allow: cIsAllow. for (String attribute : cAttributeArray) { String[] input = attribute.split("=", 2); @@ -801,16 +822,17 @@ boolean isRestrictedServiceAllowed(Service service) { String cValue = input[1].trim(); String sValue = service.getAttribute(cName); if ((sValue == null) || !cValue.equalsIgnoreCase(sValue)) { - // If any attribute doesn't match, return service is not allowed. + // If any attribute doesn't match, return service allow: !cIsAllow. if (debug != null) { debug.println( "Security constraints check." + " Service type: " + type + " Algorithm: " + algorithm + " Attribute: " + cAttribute - + " is NOT allowed in provider: " + providerName); + + " is allowed: " + !cIsAllow + + " in provider: " + providerName); } - return false; + return !cIsAllow; } } if (debug != null) { @@ -819,18 +841,20 @@ boolean isRestrictedServiceAllowed(Service service) { + " Service type: " + type + " Algorithm: " + algorithm + " Attribute: " + cAttribute - + " is allowed in provider: " + providerName); + + " is allowed: " + cIsAllow + + " in provider: " + providerName); } - return true; + return cIsAllow; } if (debug != null) { debug.println("Security constraints check." + " Service type: " + type + " Algorithm: " + algorithm - + " is NOT allowed in provider " + providerName); + + " is allowed: " + cIsAllow + + " in provider: " + providerName); } - // No match for any constraint, return NOT allowed. - return false; + // No constraint found, return service allow: !cIsAllow. + return !cIsAllow; } /** @@ -1061,12 +1085,14 @@ private static boolean isAsterisk(String string) { * A class representing the constraints of a provider. */ private static final class Constraint { + final boolean isAllow; final String type; final String algorithm; final String attributes; - Constraint(String type, String algorithm, String attributes) { + Constraint(boolean isAllow, String type, String algorithm, String attributes) { super(); + this.isAllow = isAllow; this.type = type; this.algorithm = algorithm; this.attributes = attributes; diff --git a/src/java.base/share/conf/security/java.security b/src/java.base/share/conf/security/java.security index 84606b0eae5..8cbbb834653 100644 --- a/src/java.base/share/conf/security/java.security +++ b/src/java.base/share/conf/security/java.security @@ -134,17 +134,19 @@ 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}, \ - {KeyStore, PKCS12, *}] -RestrictedSecurity1.jce.provider.3 = SunEC [{KeyFactory, EC, ImplementedIn=Software: \ +RestrictedSecurity1.jce.provider.1 = SunPKCS11 ${java.home}/conf/security/nss.fips.cfg \ + [{false, MessageDigest, MD2, *}, \ + {false, MessageDigest, MD5, *}] +RestrictedSecurity1.jce.provider.2 = SUN [{true, CertificateFactory, X.509, ImplementedIn=Software}, \ + {true, CertStore, Collection, ImplementedIn=Software}, \ + {true, CertStore, com.sun.security.IndexedCollection, ImplementedIn=Software}, \ + {true, Policy, JavaPolicy, *}, {true, Configuration, JavaLoginConfig, *}, \ + {true, CertPathBuilder, PKIX, ValidationAlgorithm=RFC5280:ImplementedIn=Software}, \ + {true, CertPathValidator, PKIX, ValidationAlgorithm=RFC5280:ImplementedIn=Software}, \ + {true, KeyStore, PKCS12, *}] +RestrictedSecurity1.jce.provider.3 = SunEC [{true, KeyFactory, EC, ImplementedIn=Software: \ SupportedKeyClasses=java.security.interfaces.ECPublicKey|java.security.interfaces.ECPrivateKey: \ - KeySize=256}, {AlgorithmParameters, EC, *}] + KeySize=256}, {true, AlgorithmParameters, EC, *}] RestrictedSecurity1.jce.provider.4 = SunJSSE RestrictedSecurity1.jce.provider.5 = SunSASL