diff --git a/src/java.base/share/classes/javopenjdk.orig///security/Security.java openjdk///src/java.base/share/classes/java/security/Security.java --- openjdk.orig/src/java.base/share/classes/java/security/Security.java +++ openjdk/src/java.base/share/classes/java/security/Security.java @@ -196,26 +196,8 @@ if (disableSystemProps == null && "true".equalsIgnoreCase(props.getProperty ("security.useSystemPropertiesFile"))) { - - // now load the system file, if it exists, so its values - // will win if they conflict with the earlier values - try (BufferedInputStream bis = - new BufferedInputStream(new FileInputStream(SYSTEM_PROPERTIES))) { - props.load(bis); + if (SystemConfigurator.configure(props)) { loadedProps = true; - - if (sdebug != null) { - sdebug.println("reading system security properties file " + - SYSTEM_PROPERTIES); - sdebug.println(props.toString()); - } - } catch (IOException e) { - if (sdebug != null) { - sdebug.println - ("unable to load security properties from " + - SYSTEM_PROPERTIES); - e.printStackTrace(); - } } } diff --git a/src/java.base/share/classes/javopenjdk.orig///security/SystemConfigurator.java openjdk///src/java.base/share/classes/java/security/SystemConfigurator.java new file mode 100644 --- /dev/null +++ openjdk/src/java.base/share/classes/java/security/SystemConfigurator.java @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2019, 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. + */ + +package java.security; + +import java.io.BufferedInputStream; +import java.io.FileInputStream; +import java.io.IOException; + +import java.nio.file.Files; +import java.nio.file.Path; + +import java.util.Iterator; +import java.util.Map.Entry; +import java.util.Properties; +import java.util.function.Consumer; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import sun.security.util.Debug; + +/** + * Internal class to align OpenJDK with global crypto-policies. + * Called from java.security.Security class initialization, + * during startup. + * + */ + +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 final String CRYPTO_POLICIES_CONFIG = + CRYPTO_POLICIES_BASE_DIR + "/config"; + + private static final class SecurityProviderInfo { + int number; + String key; + String value; + SecurityProviderInfo(int number, String key, String value) { + this.number = number; + this.key = key; + this.value = value; + } + } + + /* + * Invoked when java.security.Security class is initialized, if + * java.security.disableSystemPropertiesFile property is not set and + * security.useSystemPropertiesFile is true. + */ + static boolean configure(Properties props) { + boolean loadedProps = false; + + try (BufferedInputStream bis = + new BufferedInputStream( + new FileInputStream(CRYPTO_POLICIES_JAVA_CONFIG))) { + props.load(bis); + loadedProps = true; + if (sdebug != null) { + sdebug.println("reading system security properties file " + + CRYPTO_POLICIES_JAVA_CONFIG); + sdebug.println(props.toString()); + } + } catch (IOException e) { + if (sdebug != null) { + sdebug.println("unable to load security properties from " + + CRYPTO_POLICIES_JAVA_CONFIG); + e.printStackTrace(); + } + } + + try { + if (enableFips()) { + if (sdebug != null) { sdebug.println("FIPS mode detected"); } + loadedProps = false; + // Remove all security providers + Iterator> i = props.entrySet().iterator(); + while (i.hasNext()) { + Entry 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); + } + loadedProps = true; + } + } catch (Exception e) { + if (sdebug != null) { + sdebug.println("unable to load FIPS configuration"); + e.printStackTrace(); + } + } + return loadedProps; + } + + /* + * FIPS is enabled only if crypto-policies are set to "FIPS" + * and the com.redhat.fips property is true. + */ + private static boolean enableFips() throws Exception { + boolean fipsEnabled = Boolean.valueOf(System.getProperty("com.redhat.fips", "true")); + if (fipsEnabled) { + String cryptoPoliciesConfig = new String(Files.readAllBytes(Path.of(CRYPTO_POLICIES_CONFIG))); + if (sdebug != null) { sdebug.println("Crypto config:\n" + cryptoPoliciesConfig); } + Pattern pattern = Pattern.compile("^FIPS$", Pattern.MULTILINE); + return pattern.matcher(cryptoPoliciesConfig).find(); + } else { + return false; + } + } +} diff --git openjdk.orig///src/java.base/share/conf/security/java.security openjdk///src/java.base/share/conf/security/java.security --- openjdk.orig/src/java.base/share/conf/security/java.security +++ openjdk/src/java.base/share/conf/security/java.security @@ -87,6 +87,14 @@ #security.provider.tbd=SunPKCS11 ${java.home}/lib/security/nss.cfg # +# Security providers used when global crypto-policies are set to FIPS. +# +fips.provider.1=SunPKCS11 ${java.home}/conf/security/nss.fips.cfg +fips.provider.2=SUN +fips.provider.3=SunEC +fips.provider.4=com.sun.net.ssl.internal.ssl.Provider SunPKCS11-NSS-FIPS + +# # A list of preferred providers for specific algorithms. These providers will # be searched for matching algorithms before the list of registered providers. # Entries containing errors (parsing, etc) will be ignored. Use the