diff --git a/.gitignore b/.gitignore index 0e4f3a3..fa4f400 100644 --- a/.gitignore +++ b/.gitignore @@ -43,3 +43,4 @@ /openjdk-24.0.2+12.tar.xz /openjdk-25+36.tar.xz /openjdk-25.0.1+8.tar.xz +/nssadapter-0.1.0.tar.xz diff --git a/TestSecurityProperties.java b/TestSecurityProperties.java index 2507ceb..a6e586e 100644 --- a/TestSecurityProperties.java +++ b/TestSecurityProperties.java @@ -21,15 +21,32 @@ import java.security.Security; import java.util.Properties; public class TestSecurityProperties { + private static final String JAVA_HOME = System.getProperty("java.home"); // JDK 11 - private static final String JDK_PROPS_FILE_JDK_11 = System.getProperty("java.home") + "/conf/security/java.security"; + private static final String JDK_PROPS_FILE_JDK_11 = JAVA_HOME + "/conf/security/java.security"; // JDK 8 - private static final String JDK_PROPS_FILE_JDK_8 = System.getProperty("java.home") + "/lib/security/java.security"; + private static final String JDK_PROPS_FILE_JDK_8 = JAVA_HOME + "/lib/security/java.security"; + // JDK 25 + // Omit fips.properties files since they are not relevant to this test. + // Omit JAVA_HOME + "/conf/security/redhat/crypto-policies.properties" which simply includes + // true/crypto-policies.properties in case redhat.crypto-policies is left undefined. + private static final String[] JDK_PROPS_FILES_JDK_25_ENABLED = { + JAVA_HOME + "/conf/security/redhat/true/crypto-policies.properties", + "/etc/crypto-policies/back-ends/java.config" + }; + private static final String[] JDK_PROPS_FILES_JDK_25_DISABLED = { + JAVA_HOME + "/conf/security/redhat/false/crypto-policies.properties" + }; private static final String POLICY_FILE = "/etc/crypto-policies/back-ends/java.config"; private static final String MSG_PREFIX = "DEBUG: "; + private static final String javaVersion = System.getProperty("java.version"); + + // float for java 1.8 + private static final float JAVA_FEATURE = Float.parseFloat(System.getProperty("java.specification.version")); + public static void main(String[] args) { if (args.length == 0) { System.err.println("TestSecurityProperties "); @@ -40,18 +57,24 @@ public class TestSecurityProperties { boolean enabled = Boolean.valueOf(args[0]); System.out.println(MSG_PREFIX + "System security properties enabled: " + enabled); Properties jdkProps = new Properties(); - loadProperties(jdkProps); + loadProperties(jdkProps, enabled); if (enabled) { loadPolicy(jdkProps); } - for (Object key: jdkProps.keySet()) { - String sKey = (String)key; + for (Object key : jdkProps.keySet()) { + String sKey = (String) key; + if (JAVA_FEATURE >= 25 && sKey.equals("include")) { + // Avoid the following exception on 25: IllegalArgumentException: Key 'include' is + // reserved and cannot be used as a Security property name. Hard-code the includes + // in JDK_PROPS_FILES_JDK_25_ENABLED and JDK_PROPS_FILES_JDK_25_DISABLED instead. + continue; + } System.out.println(MSG_PREFIX + "Checking " + sKey); String securityVal = Security.getProperty(sKey); String jdkSecVal = jdkProps.getProperty(sKey); if (!jdkSecVal.equals(securityVal)) { String msg = "Expected value '" + jdkSecVal + "' for key '" + - sKey + "'" + " but got value '" + securityVal + "'"; + sKey + "'" + " but got value '" + securityVal + "'"; throw new RuntimeException("Test failed! " + msg); } else { System.out.println(MSG_PREFIX + sKey + " = " + jdkSecVal + " as expected."); @@ -60,17 +83,26 @@ public class TestSecurityProperties { System.out.println("TestSecurityProperties PASSED!"); } - private static void loadProperties(Properties props) { - String javaVersion = System.getProperty("java.version"); + private static void loadPropertiesFile(Properties props, String propsFile) { + try (FileInputStream fin = new FileInputStream(propsFile)) { + props.load(fin); + } catch (Exception e) { + throw new RuntimeException("Test failed!", e); + } + } + + private static void loadProperties(Properties props, boolean enabled) { System.out.println(MSG_PREFIX + "Java version is " + javaVersion); String propsFile = JDK_PROPS_FILE_JDK_11; if (javaVersion.startsWith("1.8.0")) { propsFile = JDK_PROPS_FILE_JDK_8; } - try (FileInputStream fin = new FileInputStream(propsFile)) { - props.load(fin); - } catch (Exception e) { - throw new RuntimeException("Test failed!", e); + loadPropertiesFile(props, propsFile); + if (JAVA_FEATURE >= 25) { + for (String file : enabled ? JDK_PROPS_FILES_JDK_25_ENABLED : JDK_PROPS_FILES_JDK_25_DISABLED) { + System.out.println(MSG_PREFIX + "Loading " + file); + loadPropertiesFile(props, file); + } } } @@ -83,3 +115,17 @@ public class TestSecurityProperties { } } + +/* + * Local Variables: + * compile-command: "\ + * /usr/lib/jvm/java-25-openjdk/bin/javac TestSecurityProperties.java \ + * && (/usr/lib/jvm/java-25-openjdk/bin/java TestSecurityProperties false ; [[ $? == 1 ]]) \ + * && (/usr/lib/jvm/java-25-openjdk/bin/java -Dredhat.crypto-policies=true TestSecurityProperties false ; [[ $? == 1 ]]) \ + * && (/usr/lib/jvm/java-25-openjdk/bin/java -Dredhat.crypto-policies=false TestSecurityProperties true ; [[ $? == 1 ]]) \ + * && /usr/lib/jvm/java-25-openjdk/bin/java TestSecurityProperties true \ + * && /usr/lib/jvm/java-25-openjdk/bin/java -Dredhat.crypto-policies=true TestSecurityProperties true \ + * && /usr/lib/jvm/java-25-openjdk/bin/java -Dredhat.crypto-policies=false TestSecurityProperties false" \ + * fill-column: 124 + * End: + */ diff --git a/create-redhat-properties-files.bash b/create-redhat-properties-files.bash new file mode 100644 index 0000000..39c7ffc --- /dev/null +++ b/create-redhat-properties-files.bash @@ -0,0 +1,174 @@ +#!/bin/bash +# +# Create Red Hat OpenJDK security properties directory hierarchy. +# +# Copyright (C) 2025 IBM Corporation. All rights reserved. +# +# Written by: +# Francisco Ferrari Bihurriet +# Thomas Fitzsimmons +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program 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 Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +# Usage: +# +# bash create-redhat-properties-files.bash +# +# Example usage in spec file: +# +# bash -x create-redhat-properties-files.bash ${imagepath}/conf/security +# +# When you make changes to the file set here, also update the %files +# section in the spec file, and the JDK_PROPS_FILES_JDK_25 variables +# in TestSecurityProperties.java. + +[[ $# == 1 ]] || exit 1 + +SECURITY="${1}" +VENDOR="${SECURITY}"/redhat +install --directory --mode=755 "${VENDOR}" +install --directory --mode=755 "${VENDOR}"/true +install --directory --mode=755 "${VENDOR}"/false + +# /usr/lib/jvm/java-25-openjdk/conf/security/redhat/SunPKCS11-FIPS.cfg +install --mode 644 /dev/stdin "${VENDOR}"/SunPKCS11-FIPS.cfg <<'EOF' +name = FIPS +library = ${java.home}/lib/libnssadapter.so +slot = 3 +nssUseSecmod = false +attributes(*,CKO_SECRET_KEY,*)={ CKA_SIGN=true CKA_ENCRYPT=true } +EOF + +# /usr/lib/jvm/java-25-openjdk/conf/security/redhat/false/crypto-policies.properties +install --mode 644 /dev/stdin "${VENDOR}"/false/crypto-policies.properties <<'EOF' +# Empty on purpose, for ${redhat.crypto-policies}=false +EOF + +# /usr/lib/jvm/java-25-openjdk/conf/security/redhat/true/crypto-policies.properties +install --mode 644 /dev/stdin "${VENDOR}"/true/crypto-policies.properties <<'EOF' +# +# Apply the system-wide crypto policy +# +include /etc/crypto-policies/back-ends/java.config + +# +# Apply the FIPS-specific security properties, if needed +# +include ../${__redhat_fips__}/fips.properties +EOF + +# /usr/lib/jvm/java-25-openjdk/conf/security/redhat/crypto-policies.properties +install --mode 644 /dev/stdin "${VENDOR}"/crypto-policies.properties <<'EOF' +# +# Default choice for the crypto-policies setup +# +include true/crypto-policies.properties +EOF + +# /usr/lib/jvm/java-25-openjdk/conf/security/redhat/false/fips.properties +install --mode 644 /dev/stdin "${VENDOR}"/false/fips.properties <<'EOF' +# Empty on purpose, for when FIPS is disabled. +EOF + +# /usr/lib/jvm/java-25-openjdk/conf/security/redhat/true/fips.properties +install --mode 644 /dev/stdin "${VENDOR}"/true/fips.properties <<'EOF' +# +# Enable the downstream-patch RedHatFIPSFilter code +# +__redhat_fips_filter__=true + +# +# FIPS mode Security Providers List +# +security.provider.1=SunPKCS11 ${java.home}/conf/security/redhat/SunPKCS11-FIPS.cfg +security.provider.2=SUN +security.provider.3=SunEC +security.provider.4=SunJSSE +security.provider.5=SunJCE +security.provider.6=SunRsaSign +security.provider.7=XMLDSig +security.provider.8= +# ^ empty on purpose, to finish the Providers List + +# +# FIPS mode default keystore type +# +keystore.type=pkcs12 +EOF + +# /usr/lib/jvm/java-25-openjdk/conf/security/redhat/fips.properties +# For now, this prevents an include cycle on JDKs that do not support +# ${__redhat_fips__}. In the future the goal is for it be overwritten +# (based on /proc/sys/crypto/fips_enabled) at FIPS configuration time +# (by fips-mode-setup or by grubby), at RPM install time by a +# post-install hook, and/or during boot by a systemd oneshot service. +install --mode 644 /dev/stdin "${VENDOR}"/fips.properties <<'EOF' +include false/fips.properties +EOF + +cat >> "${SECURITY}"/java.security <<'EOF' + +# +# System-wide crypto-policies and FIPS setup +# +# The following crypto-policies setup automatically detects when the system +# is in FIPS mode and configures OpenJDK accordingly. If OpenJDK needs to +# ignore the system and disable its FIPS setup, just disable the usage of +# the system crypto-policies, by any of the methods described below. +# +# The redhat.crypto-policies system property is a boolean switch that +# controls the usage on a per-run basis. For example, pass +# -Dredhat.crypto-policies=false to disable the system crypto-policies. +# +# This setup consists of the following files in $JAVA_HOME/conf/security: +# +# 'redhat/false/crypto-policies.properties' (policies usage disabled file) +# Empty file, applied when the boolean switch is passed as false. +# +# 'redhat/true/crypto-policies.properties' (policies usage enabled file) +# Performs the crypto-policies and FIPS setup, applied when the boolean +# switch is passed as true. +# +# 'redhat/crypto-policies.properties' (policies usage default file) +# Determines the default choice by including one of the previous files, +# applied when the boolean switch is not passed. +# The system crypto-policies usage is enabled by default: +# include true/crypto-policies.properties +# +# To enable or disable the usage of the crypto-policies on a per-deployment +# basis, edit the policies usage default file, changing the included file. +# For example, execute the following command to persistently disable the +# crypto-policies: +# sed -i s/true/false/ $JAVA_HOME/conf/security/redhat/crypto-policies.properties +# Applications can still override this on a per-run basis, for example by +# passing -Dredhat.crypto-policies=true. +# +# To disable the redhat.crypto-policies boolean switch, modify the following +# include directive as follows. Replace ${redhat.crypto-policies} by true to +# force-apply the system crypto-policies: +# include redhat/true/crypto-policies.properties +# Remove or comment out the include directive to force-disable the setup: +# #include redhat/${redhat.crypto-policies}/crypto-policies.properties +# +include redhat/${redhat.crypto-policies}/crypto-policies.properties +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +# WARNING: anything placed after this include directive will apply on top +# of the described setup. Adding properties below this section is strongly +# discouraged, as it poses a risk of overriding the system crypto-policies +# or invalidating the FIPS deployment. +EOF + +# Local Variables: +# compile-command: "shellcheck create-redhat-properties-files.bash" +# End: diff --git a/java-25-openjdk.spec b/java-25-openjdk.spec index f45a6b0..75e6832 100644 --- a/java-25-openjdk.spec +++ b/java-25-openjdk.spec @@ -353,8 +353,10 @@ %global icedteaver 6.0.0pre00-c848b93a8598 # Define current Git revision for the crypto policy & FIPS support patches %global fipsver 9203d50836c +# Define nssadapter version +%global nssadapter_version 0.1.0 # Define whether the crypto policy is expected to be active when testing -%global crypto_policy_active false +%global crypto_policy_active true # Define JDK versions %global newjavaver %{featurever}.%{interimver}.%{updatever}.%{patchver} %global javaver %{featurever} @@ -376,7 +378,7 @@ %global top_level_dir_name %{vcstag} %global top_level_dir_name_backup %{top_level_dir_name}-backup %global buildver 8 -%global rpmrelease 2 +%global rpmrelease 3 # Settings used by the portable build %global portablerelease 1 # Portable suffix differs between RHEL and CentOS @@ -386,13 +388,6 @@ %global portablerhel 9 %endif %global portablebuilddir /builddir/build/BUILD -%global portablesuffix el%{portablerhel} -# Check if pandoc was available to generate docs (including man pages) -%if 0%{?portablerhel} == 8 -%global pandoc_available 1 -%else -%global pandoc_available 0 -%endif %if 0%{?almalinux} %ifarch riscv64 @@ -400,6 +395,13 @@ %else %global portablesuffix el9 %endif +%endif +%global portablesuffix el%{portablerhel} +# Check if pandoc was available to generate docs (including man pages) +%if 0%{?portablerhel} == 8 +%global pandoc_available 1 +%else +%global pandoc_available 0 %endif # Priority must be 8 digits in total; up to openjdk 1.8, we were using 18..... so when we moved to 11, we had to add another digit @@ -853,6 +855,7 @@ fi %{_jvmdir}/%{sdkdir -- %{?1}}/lib/libmlib_image.so %{_jvmdir}/%{sdkdir -- %{?1}}/lib/libnet.so %{_jvmdir}/%{sdkdir -- %{?1}}/lib/libnio.so +%{_jvmdir}/%{sdkdir -- %{?1}}/lib/libnssadapter.so %{_jvmdir}/%{sdkdir -- %{?1}}/lib/libprefs.so %{_jvmdir}/%{sdkdir -- %{?1}}/lib/librmi.so # Some architectures don't have the serviceability agent @@ -912,6 +915,22 @@ fi %config(noreplace) %{etcjavadir -- %{?1}}/conf/security/policy/unlimited/default_US_export.policy %{etcjavadir -- %{?1}}/conf/security/policy/README.txt %config(noreplace) %{etcjavadir -- %{?1}}/conf/security/java.security +%dir %{etcjavadir -- %{?1}}/conf/security/redhat +%dir %{etcjavadir -- %{?1}}/conf/security/redhat/false +%dir %{etcjavadir -- %{?1}}/conf/security/redhat/true +# config-noreplace in case the system administrator wants to adjust +# the FIPS configuration +%config(noreplace) %{etcjavadir -- %{?1}}/conf/security/redhat/SunPKCS11-FIPS.cfg +# config-noreplace in case the system administrator wants to change +# the default for crypto-policies usage +%config(noreplace) %{etcjavadir -- %{?1}}/conf/security/redhat/crypto-policies.properties +# The system administrator is never expected to change these files -- they +# are implementation details -- so leave them as not config-noreplace +%config %{etcjavadir -- %{?1}}/conf/security/redhat/false/crypto-policies.properties +%config %{etcjavadir -- %{?1}}/conf/security/redhat/true/crypto-policies.properties +%config %{etcjavadir -- %{?1}}/conf/security/redhat/fips.properties +%config %{etcjavadir -- %{?1}}/conf/security/redhat/false/fips.properties +%config %{etcjavadir -- %{?1}}/conf/security/redhat/true/fips.properties %config(noreplace) %{etcjavadir -- %{?1}}/conf/management/jmxremote.access # This is a config template, thus not config-noreplace %config %{etcjavadir -- %{?1}}/conf/management/jmxremote.password.template @@ -1363,6 +1382,12 @@ Source29: 0007-Tools.gmk-Exclude-systemtap-sdt-devel-on-s390x-ppc64.patch # Use update repository on RHEL rather than GA (OPENJDK-3589) Source30: 0008-Tools.gmk-Use-update-repository-on-RHEL-rather-than-.patch +# FIPS support sources. +# For libnssadapter.so (RHEL-128413) +Source31: https://github.com/rh-openjdk/nss-native-fips-key-import-export-adapter/releases/download/%{nssadapter_version}/nssadapter-%{nssadapter_version}.tar.xz +# Create OpenJDK's crypto-policies hierarchy (RHEL-128409) +Source32: create-redhat-properties-files.bash + # Setup variables to reference correct sources %global releasezip %{_jvmdir}/%{name}-%{version}-%{prelease}.portable.unstripped.jdk.%{_arch}.tar.xz %global staticlibzip %{_jvmdir}/%{name}-%{version}-%{prelease}.portable.static-libs.%{_arch}.tar.xz @@ -1497,6 +1522,10 @@ BuildRequires: systemtap-sdt-devel %endif BuildRequires: make +# libnssadapter.so build requirements +BuildRequires: nss-devel +BuildRequires: nss-softokn-devel + %if %{system_libs} BuildRequires: freetype-devel BuildRequires: giflib-devel @@ -1880,6 +1909,8 @@ fi export XZ_OPT="-T0" %setup -q -c -n %{uniquesuffix ""} -T -a 0 +# Prepare libnssadapter.so source code +tar -xJf %{SOURCE31} # https://bugzilla.redhat.com/show_bug.cgi?id=1189084 prioritylength=`expr length %{priority}` if [ $prioritylength -ne 8 ] ; then @@ -1957,9 +1988,9 @@ function customisejdk() { local imagepath=${1} if [ -d ${imagepath} ] ; then - # Turn on system security properties - sed -i -e "s:^security.useSystemPropertiesFile=.*:security.useSystemPropertiesFile=true:" \ - ${imagepath}/conf/security/java.security + # Install crypto-policies FIPS configuration files and append + # include line to java.security + bash -x %{SOURCE32} ${imagepath}/conf/security # Use system-wide tzdata rm ${imagepath}/lib/tzdb.dat @@ -1984,12 +2015,16 @@ for suffix in %{build_loop} ; do if [ "x$suffix" = "x" ] ; then jdkzip=%{releasezip} staticlibzip=%{staticlibzip} + make -C nssadapter-%{nssadapter_version} elif [ "x$suffix" = "x%{fastdebug_suffix_unquoted}" ] ; then jdkzip=%{fastdebugzip} staticlibzip=%{fastdebugstaticlibzip} + make -C nssadapter-%{nssadapter_version} else # slowdebug jdkzip=%{slowdebugzip} staticlibzip=%{slowdebugstaticlibzip} + # Disable _FORTIFY_SOURCE to allow for no optimization + make -C nssadapter-%{nssadapter_version} CFLAGS="${CFLAGS} -O0 -Wp,-U_FORTIFY_SOURCE" fi installdir=%{installoutputdir -- ${suffix}} @@ -1999,6 +2034,10 @@ for suffix in %{build_loop} ; do tar -xJf ${staticlibzip} mv java-%{featurever}-openjdk* ${installdir} + # Install and clean libnssadapter.so + install -m 755 nssadapter-%{nssadapter_version}/bin/libnssadapter.so ${installdir}/lib + make -C nssadapter-%{nssadapter_version} clean + # Fix build paths in ELF files so it looks like we built them portablenvr="%{name}-%{VERSION}-%{prelease}.%{portablesuffix}.%{_arch}" for file in $(find ${installdir} -type f) ; do @@ -2064,7 +2103,7 @@ $JAVA_HOME/bin/java -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -versi export PROG=$(echo $(basename %{SOURCE15})|sed "s|\.java||") export SEC_DEBUG="-Djava.security.debug=properties" $JAVA_HOME/bin/java ${SEC_DEBUG} ${PROG} %{crypto_policy_active} - $JAVA_HOME/bin/java ${SEC_DEBUG} -Djava.security.disableSystemPropertiesFile=true ${PROG} false + $JAVA_HOME/bin/java ${SEC_DEBUG} -Dredhat.crypto-policies=false ${PROG} false # Check correct vendor values have been set $JAVA_HOME/bin/javac -d . %{SOURCE16} @@ -2560,9 +2599,17 @@ exit 0 %endif %changelog -* Mon Nov 24 2025 Eduard Abdullin - 1:25.0.1.0.8-2.alma.1 +* Thu Nov 27 2025 Eduard Abdullin - 1:25.0.1.0.8-3.alma.1 - Use el9 portable packages +* Mon Nov 24 2025 Thomas Fitzsimmons - 1:25.0.1.0.8-3 +- Add libnssadapter.so +- Add FIPS crypto-policies configuration +- Remove obsolete security.useSystemPropertiesFile setup +- Update TestSecurityProperties.java test and calling convention +- Resolves: RHEL-128413 +- Resolves: RHEL-128409 + * Wed Nov 12 2025 Andrew Hughes - 1:25.0.1.0.8-2 - Remove superfluous backslashes that cause two alternative commands to be combined - Related: RHEL-120553 diff --git a/sources b/sources index 81afaec..1e2c7e3 100644 --- a/sources +++ b/sources @@ -1,2 +1,3 @@ SHA512 (tapsets-icedtea-6.0.0pre00-c848b93a8598.tar.xz) = 97d026212363b3c83f6a04100ad7f6fdde833d16579717f8756e2b8c2eb70e144a41a330cb9ccde9c3badd37a2d54fdf4650a950ec21d8b686d545ecb2a64d30 SHA512 (openjdk-25.0.1+8.tar.xz) = eb84d876f81ca02803283e8294c89b6acbed3753426811c3bcc228615c9618deefc85da4aa702800cac2feb103e628ee8b92292b316e9d7e12a58b6de69c5085 +SHA512 (nssadapter-0.1.0.tar.xz) = 581f49d1a27550e3a2fa0a9d407f43c507627a8439827904d14daaf24e071d9f73884a2abe4cb3d36d26f1af09ef7d20724b2d40c9bac202e0316fac6c1a636b