Skip to content

Commit

Permalink
FIPS Support for Linux x86 RHEL
Browse files Browse the repository at this point in the history
Signed-off-by: Jinhang Zhang <Jinhang.Zhang@ibm.com>
  • Loading branch information
JinhangZhang committed Aug 16, 2022
1 parent 28c0dde commit 2c1071c
Show file tree
Hide file tree
Showing 7 changed files with 313 additions and 47 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
/*
* ===========================================================================
* (c) Copyright IBM Corp. 2022, 2022 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 <http://www.gnu.org/licenses/>.
*
* ===========================================================================
*/

package openj9.internal.security;

import java.util.Iterator;
import java.util.Map.Entry;
import java.util.Properties;
import java.security.AccessController;
import java.security.PrivilegedAction;

import sun.security.util.Debug;

/**
* Configures the security providers when in FIPS mode.
*/
public final class FIPSConfigurator {

private static final Debug debug = Debug.getInstance("semerufips");

// FIPS mode enable check, only supported on Linux x64.
private static final boolean userEnabledFIPS;
private static final boolean isFIPSSupported;
private static final boolean shouldEnableFIPS;

static {
String[] props = AccessController.doPrivileged(
new PrivilegedAction<String[]>() {
@Override
public String[] run() {
return new String[] {System.getProperty("semeru.fips"),
System.getProperty("os.name"),
System.getProperty("os.arch")};
}
});
userEnabledFIPS = Boolean.parseBoolean(props[0]);
isFIPSSupported = "Linux".equalsIgnoreCase(props[1])
&& "amd64".equalsIgnoreCase(props[2]);
shouldEnableFIPS = userEnabledFIPS && isFIPSSupported;
}

private FIPSConfigurator() {
super();
}

/**
* FIPS mode will be enabled only if the semeru.fips system
* property is true (default as false).
*
* @return true if FIPS is enabled
*/
public static boolean enableFIPS() {
return shouldEnableFIPS;
}

/**
* Remove the security providers and only add the FIPS security providers.
*
* @param props the java.security properties
* @return true if the FIPS properties loaded successfully
*/
public static boolean configureFIPS(Properties props) {
boolean loadedProps = false;

// Check if FIPS is supported on this platform.
if (userEnabledFIPS && !isFIPSSupported) {
throw new RuntimeException("FIPS is not supported on this platform.");
}

try {
if (shouldEnableFIPS) {
if (debug != null) {
debug.println("FIPS mode detected, loading properties");
}

// 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 (debug != null) {
debug.println("Removing provider: " + e);
}
i.remove();
}
}

// Add FIPS security providers.
props.put("security.provider.1", "sun.security.pkcs11.SunPKCS11 ${java.home}/lib/security/nss.fips.cfg");
props.put("security.provider.2", "sun.security.provider.Sun");
props.put("security.provider.3", "sun.security.ec.SunEC");
props.put("security.provider.4", "com.sun.net.ssl.internal.ssl.Provider");

// Add FIPS security properties.
props.put("keystore.type", "PKCS11");
System.setProperty("javax.net.ssl.keyStore", "NONE");

// Add FIPS disabled algorithms.
String disabledAlgorithms = props.get("jdk.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";
props.put("jdk.tls.disabledAlgorithms", disabledAlgorithms);

if (debug != null) {
debug.println("FIPS mode properties loaded");
debug.println(props.toString());
}

loadedProps = true;
}
} catch (Exception e) {
if (debug != null) {
debug.println("Unable to load FIPS configuration");
e.printStackTrace();
}
}
return loadedProps;
}
}
25 changes: 25 additions & 0 deletions closed/adds/jdk/src/share/lib/security/nss.fips.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# ===========================================================================
# (c) Copyright IBM Corp. 2022, 2022 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 <http://www.gnu.org/licenses/>.
# ===========================================================================

name = NSS-FIPS
nssLibraryDirectory = /usr/lib64
nssSecmodDirectory = /etc/pki/nssdb
nssDbMode = readOnly
nssModule = fips
14 changes: 13 additions & 1 deletion closed/make/CopyFiles.gmk
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# ===========================================================================
# (c) Copyright IBM Corp. 2017, 2020 All Rights Reserved
# (c) Copyright IBM Corp. 2017, 2022 All Rights Reserved
# ===========================================================================
#
# This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -30,3 +30,15 @@ $(JDK_OUTPUTDIR)/include/ibmjvmti.h: $(SRC_ROOT)/openj9/runtime/include/ibmjvmti
$(call install-file)

COPY_FILES += $(JDK_OUTPUTDIR)/include/ibmjvmti.h

# Copy the nss.fips.cfg only on x86 linux

ifeq ($(OPENJDK_TARGET_OS)-$(OPENJDK_TARGET_CPU_ARCH), linux-x86)
NSS_FIPS_CFG_SRC := $(TOPDIR)/closed/adds/jdk/src/share/lib/security/nss.fips.cfg
NSS_FIPS_CFG_DST := $(JDK_OUTPUTDIR)/lib/security/nss.fips.cfg

$(NSS_FIPS_CFG_DST) : $(NSS_FIPS_CFG_SRC)
$(call install-file)

COPY_FILES += $(NSS_FIPS_CFG_DST)
endif
26 changes: 25 additions & 1 deletion jdk/src/share/classes/java/security/SecureRandom.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@
* questions.
*/

/*
* ===========================================================================
* (c) Copyright IBM Corp. 2022, 2022 All Rights Reserved
* ===========================================================================
*/

package java.security;

import java.util.*;
Expand All @@ -34,6 +40,8 @@
import sun.security.jca.GetInstance.Instance;
import sun.security.util.Debug;

import openj9.internal.security.FIPSConfigurator;

/**
* This class provides a cryptographically strong random number
* generator (RNG).
Expand Down Expand Up @@ -191,7 +199,23 @@ public SecureRandom(byte seed[]) {
}

private void getDefaultPRNG(boolean setSeed, byte[] seed) {
String prng = getPrngAlgorithm();
String prng;

// If in FIPS mode, use the SecureRandom from the FIPS provider.
if (FIPSConfigurator.enableFIPS()) {
Provider p = Security.getProvider("SunPKCS11-NSS-FIPS");
prng = "PKCS11";
if (p == null) {
throw new RuntimeException("could not find SunPKCS11-NSS-FIPS provider for FIPS mode");
}
Service prngService = p.getService("SecureRandom", prng);
if (prngService == null) {
throw new RuntimeException("could not find SecureRandom implementation from SunPKCS11-NSS-FIPS");
}
} else {
prng = getPrngAlgorithm();
}

if (prng == null) {
// bummer, get the SUN implementation
prng = "SHA1PRNG";
Expand Down
20 changes: 20 additions & 0 deletions jdk/src/share/classes/java/security/Security.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@
* questions.
*/

/*
* ===========================================================================
* (c) Copyright IBM Corp. 2022, 2022 All Rights Reserved
* ===========================================================================
*/

package java.security;

import java.lang.reflect.*;
Expand All @@ -35,6 +41,8 @@

import sun.security.jca.*;

import openj9.internal.security.FIPSConfigurator;

/**
* <p>This class centralizes all security properties and common security
* methods. One of its primary uses is to manage providers.
Expand Down Expand Up @@ -187,6 +195,18 @@ private static void initialize() {
}
}

// Load FIPS properties
if (loadedProps) {
boolean fipsEnabled = FIPSConfigurator.configureFIPS(props);
if (sdebug != null) {
if (fipsEnabled) {
sdebug.println("FIPS mode enabled.");
} else {
sdebug.println("FIPS mode disabled.");
}
}
}

}

/*
Expand Down
Loading

0 comments on commit 2c1071c

Please sign in to comment.