Skip to content

Commit 6209167

Browse files
authored
Merge pull request #103 from WilburZjh/enable-fips
FIPS Mode for RHEL x86
2 parents 6e2aa7d + 27dde73 commit 6209167

File tree

10 files changed

+336
-57
lines changed

10 files changed

+336
-57
lines changed

closed/custom/modules/java.base/Copy.gmk

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,3 +240,15 @@ ifneq ($(OPENSSL_BUNDLE_LIB_PATH), )
240240
endif # OPENJ9_ENABLE_JITSERVER
241241
endif # OPENSSL_BUNDLE_LIB_PATH
242242
################################################################################
243+
# Copy the nss.fips.cfg only on x86 linux
244+
245+
ifeq ($(OPENJDK_TARGET_OS)-$(OPENJDK_TARGET_CPU_ARCH), linux-x86)
246+
NSS_FIPS_CFG_SRC := $(TOPDIR)/closed/src/java.base/share/conf/security/nss.fips.cfg
247+
NSS_FIPS_CFG_DST := $(CONF_DST_DIR)/security/nss.fips.cfg
248+
249+
$(NSS_FIPS_CFG_DST) : $(NSS_FIPS_CFG_SRC)
250+
$(call install-file)
251+
252+
TARGETS += $(NSS_FIPS_CFG_DST)
253+
endif
254+
################################################################################
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
/*
2+
* ===========================================================================
3+
* (c) Copyright IBM Corp. 2022, 2022 All Rights Reserved
4+
* ===========================================================================
5+
*
6+
* This code is free software; you can redistribute it and/or modify it
7+
* under the terms of the GNU General Public License version 2 only, as
8+
* published by the Free Software Foundation.
9+
*
10+
* IBM designates this particular file as subject to the "Classpath" exception
11+
* as provided by IBM in the LICENSE file that accompanied this code.
12+
*
13+
* This code is distributed in the hope that it will be useful, but WITHOUT
14+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16+
* version 2 for more details (a copy is included in the LICENSE file that
17+
* accompanied this code).
18+
*
19+
* You should have received a copy of the GNU General Public License version
20+
* 2 along with this work; if not, see <http://www.gnu.org/licenses/>.
21+
*
22+
* ===========================================================================
23+
*/
24+
25+
package openj9.internal.security;
26+
27+
import java.util.Iterator;
28+
import java.util.Map.Entry;
29+
import java.util.Properties;
30+
import java.security.AccessController;
31+
import java.security.PrivilegedAction;
32+
33+
import sun.security.util.Debug;
34+
35+
/**
36+
* Configures the security providers when in FIPS mode.
37+
*/
38+
public final class FIPSConfigurator {
39+
40+
private static final Debug debug = Debug.getInstance("semerufips");
41+
42+
// FIPS mode enable check, only supported on Linux x64.
43+
private static final boolean userEnabledFIPS;
44+
private static final boolean isFIPSSupported;
45+
private static final boolean shouldEnableFIPS;
46+
47+
static {
48+
String[] props = AccessController.doPrivileged(
49+
new PrivilegedAction<>() {
50+
@Override
51+
public String[] run() {
52+
return new String[] {System.getProperty("semeru.fips"),
53+
System.getProperty("os.name"),
54+
System.getProperty("os.arch")};
55+
}
56+
});
57+
userEnabledFIPS = Boolean.parseBoolean(props[0]);
58+
isFIPSSupported = "Linux".equalsIgnoreCase(props[1])
59+
&& "amd64".equalsIgnoreCase(props[2]);
60+
shouldEnableFIPS = userEnabledFIPS && isFIPSSupported;
61+
}
62+
63+
private FIPSConfigurator() {
64+
super();
65+
}
66+
67+
/**
68+
* FIPS mode will be enabled only if the semeru.fips system
69+
* property is true (default as false).
70+
*
71+
* @return true if FIPS is enabled
72+
*/
73+
public static boolean enableFIPS() {
74+
return shouldEnableFIPS;
75+
}
76+
77+
/**
78+
* Remove the security providers and only add the FIPS security providers.
79+
*
80+
* @param props the java.security properties
81+
* @return true if the FIPS properties loaded successfully
82+
*/
83+
public static boolean configureFIPS(Properties props) {
84+
boolean loadedProps = false;
85+
86+
// Check if FIPS is supported on this platform.
87+
if (userEnabledFIPS && !isFIPSSupported) {
88+
throw new RuntimeException("FIPS is not supported on this platform.");
89+
}
90+
91+
try {
92+
if (shouldEnableFIPS) {
93+
if (debug != null) {
94+
debug.println("FIPS mode detected, loading properties");
95+
}
96+
97+
// Remove all security providers.
98+
Iterator<Entry<Object, Object>> i = props.entrySet().iterator();
99+
while (i.hasNext()) {
100+
Entry<Object, Object> e = i.next();
101+
if (((String) e.getKey()).startsWith("security.provider")) {
102+
if (debug != null) {
103+
debug.println("Removing provider: " + e);
104+
}
105+
i.remove();
106+
}
107+
}
108+
109+
// Add FIPS security providers.
110+
props.put("security.provider.1", "SunPKCS11 ${java.home}/conf/security/nss.fips.cfg");
111+
props.put("security.provider.2", "SUN");
112+
props.put("security.provider.3", "SunEC");
113+
props.put("security.provider.4", "SunJSSE");
114+
115+
// Add FIPS security properties.
116+
props.put("keystore.type", "PKCS11");
117+
System.setProperty("javax.net.ssl.keyStore", "NONE");
118+
119+
// Add FIPS disabled algorithms.
120+
String disabledAlgorithms = props.get("jdk.tls.disabledAlgorithms")
121+
+ ", X25519, X448"
122+
+ ", SSLv3, TLSv1, TLSv1.1"
123+
+ ", TLS_CHACHA20_POLY1305_SHA256"
124+
+ ", TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, TLS_DHE_DSS_WITH_AES_256_GCM_SHA384"
125+
+ ", TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_DSS_WITH_AES_128_GCM_SHA256"
126+
+ ", TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, TLS_DHE_DSS_WITH_AES_256_CBC_SHA256"
127+
+ ", TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_DSS_WITH_AES_128_CBC_SHA256"
128+
+ ", TLS_DHE_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_DSS_WITH_AES_256_CBC_SHA"
129+
+ ", TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA"
130+
+ ", TLS_RSA_WITH_AES_256_GCM_SHA384, TLS_RSA_WITH_AES_128_GCM_SHA256"
131+
+ ", TLS_RSA_WITH_AES_256_CBC_SHA256, TLS_RSA_WITH_AES_128_CBC_SHA256"
132+
+ ", TLS_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA"
133+
+ ", TLS_AES_256_GCM_SHA384, TLS_AES_128_GCM_SHA256"
134+
+ ", TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"
135+
+ ", TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"
136+
+ ", TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384"
137+
+ ", TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256"
138+
+ ", TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256"
139+
+ ", TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256"
140+
+ ", TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256"
141+
+ ", TLS_EMPTY_RENEGOTIATION_INFO_SCSV";
142+
props.put("jdk.tls.disabledAlgorithms", disabledAlgorithms);
143+
144+
if (debug != null) {
145+
debug.println("FIPS mode properties loaded");
146+
debug.println(props.toString());
147+
}
148+
149+
loadedProps = true;
150+
}
151+
} catch (Exception e) {
152+
if (debug != null) {
153+
debug.println("Unable to load FIPS configuration");
154+
e.printStackTrace();
155+
}
156+
}
157+
return loadedProps;
158+
}
159+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# ===========================================================================
2+
# (c) Copyright IBM Corp. 2022, 2022 All Rights Reserved
3+
# ===========================================================================
4+
# This code is free software; you can redistribute it and/or modify it
5+
# under the terms of the GNU General Public License version 2 only, as
6+
# published by the Free Software Foundation.
7+
#
8+
# IBM designates this particular file as subject to the "Classpath" exception
9+
# as provided by IBM in the LICENSE file that accompanied this code.
10+
#
11+
# This code is distributed in the hope that it will be useful, but WITHOUT
12+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
# version 2 for more details (a copy is included in the LICENSE file that
15+
# accompanied this code).
16+
#
17+
# You should have received a copy of the GNU General Public License version
18+
# 2 along with this work; if not, see <http://www.gnu.org/licenses/>.
19+
# ===========================================================================
20+
21+
name = NSS-FIPS
22+
nssLibraryDirectory = /usr/lib64
23+
nssSecmodDirectory = /etc/pki/nssdb
24+
nssDbMode = readOnly
25+
nssModule = fips

src/java.base/share/classes/java/security/SecureRandom.java

Lines changed: 36 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@
2323
* questions.
2424
*/
2525

26+
/*
27+
* ===========================================================================
28+
* (c) Copyright IBM Corp. 2022, 2022 All Rights Reserved
29+
* ===========================================================================
30+
*/
31+
2632
package java.security;
2733

2834
import java.math.BigInteger;
@@ -37,6 +43,8 @@
3743
import sun.security.provider.SunEntries;
3844
import sun.security.util.Debug;
3945

46+
import openj9.internal.security.FIPSConfigurator;
47+
4048
/**
4149
* This class provides a cryptographically strong random number
4250
* generator (RNG).
@@ -267,23 +275,38 @@ public SecureRandom(byte[] seed) {
267275
private void getDefaultPRNG(boolean setSeed, byte[] seed) {
268276
Service prngService = null;
269277
String prngAlgorithm = null;
270-
for (Provider p : Providers.getProviderList().providers()) {
271-
// SUN provider uses the SunEntries.DEF_SECURE_RANDOM_ALGO
272-
// as the default SecureRandom algorithm; for other providers,
273-
// Provider.getDefaultSecureRandom() will use the 1st
274-
// registered SecureRandom algorithm
275-
if (p.getName().equals("SUN")) {
276-
prngAlgorithm = SunEntries.DEF_SECURE_RANDOM_ALGO;
277-
prngService = p.getService("SecureRandom", prngAlgorithm);
278-
break;
279-
} else {
280-
prngService = p.getDefaultSecureRandomService();
281-
if (prngService != null) {
282-
prngAlgorithm = prngService.getAlgorithm();
278+
279+
// If in FIPS mode, use the SecureRandom from the FIPS provider.
280+
if (FIPSConfigurator.enableFIPS()) {
281+
Provider p = Security.getProvider("SunPKCS11-NSS-FIPS");
282+
prngAlgorithm = "PKCS11";
283+
if (p == null) {
284+
throw new RuntimeException("could not find SunPKCS11-NSS-FIPS provider for FIPS mode");
285+
}
286+
prngService = p.getService("SecureRandom", prngAlgorithm);
287+
if (prngService == null) {
288+
throw new RuntimeException("could not find SecureRandom implementation from SunPKCS11-NSS-FIPS");
289+
}
290+
} else {
291+
for (Provider p : Providers.getProviderList().providers()) {
292+
// SUN provider uses the SunEntries.DEF_SECURE_RANDOM_ALGO
293+
// as the default SecureRandom algorithm; for other providers,
294+
// Provider.getDefaultSecureRandom() will use the 1st
295+
// registered SecureRandom algorithm
296+
if (p.getName().equals("SUN")) {
297+
prngAlgorithm = SunEntries.DEF_SECURE_RANDOM_ALGO;
298+
prngService = p.getService("SecureRandom", prngAlgorithm);
283299
break;
300+
} else {
301+
prngService = p.getDefaultSecureRandomService();
302+
if (prngService != null) {
303+
prngAlgorithm = prngService.getAlgorithm();
304+
break;
305+
}
284306
}
285307
}
286308
}
309+
287310
// per javadoc, if none of the Providers support a RNG algorithm,
288311
// then an implementation-specific default is returned.
289312
if (prngService == null) {

src/java.base/share/classes/java/security/Security.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@
5050
import openj9.internal.criu.security.CRIUConfigurator;
5151
/*[ENDIF] CRIU_SUPPORT*/
5252

53+
import openj9.internal.security.FIPSConfigurator;
54+
5355
/**
5456
* <p>This class centralizes all security properties and common security
5557
* methods. One of its primary uses is to manage providers.
@@ -211,6 +213,17 @@ private static void initialize() {
211213
}
212214
/*[ENDIF] CRIU_SUPPORT*/
213215

216+
// Load FIPS properties
217+
if (loadedProps) {
218+
boolean fipsEnabled = FIPSConfigurator.configureFIPS(props);
219+
if (sdebug != null) {
220+
if (fipsEnabled) {
221+
sdebug.println("FIPS mode enabled.");
222+
} else {
223+
sdebug.println("FIPS mode disabled.");
224+
}
225+
}
226+
}
214227
}
215228

216229
/*

src/java.base/share/classes/module-info.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@
2323
* questions.
2424
*/
2525

26+
/*
27+
* ===========================================================================
28+
* (c) Copyright IBM Corp. 2022, 2022 All Rights Reserved
29+
* ===========================================================================
30+
*/
31+
2632
/**
2733
* Defines the foundational APIs of the Java SE Platform.
2834
*
@@ -363,6 +369,8 @@
363369
jdk.localedata;
364370
exports jdk.internal.invoke to
365371
jdk.incubator.foreign;
372+
exports openj9.internal.security to
373+
jdk.crypto.ec;
366374

367375
// the service types defined by the APIs in this module
368376

0 commit comments

Comments
 (0)