IBM Support

FIPS certified cryptography in IBM Semeru Runtimes

General Page

This guide describes the IBM Semeru Runtimes support for FIPS certified cryptography, and how to enable it.

FIPS certified cryptography in IBM Semeru Runtimes

FIPS certified cryptography is a key requirement for many users, especially in government and in regulated industries. On Red Hat® Enterprise Linux® (RHEL) 8 on x86, ppcle, and s390x platforms, IBM® Semeru Runtimes can run in FIPS mode, which guarantees that only FIPS certified cryptography is used when a Java™ application uses Java security libraries or APIs.

FIPS mode is available in both IBM Semeru Runtime™ Certified Edition and IBM Semeru Runtime Open Edition. In the open edition, FIPS mode is available from versions 8.0.352, 11.0.16, and 17.0.4, and in Java 21 and later on RHEL 8 on x86, ppcle, and s390x platforms only. Both ppcle and s390x support require Semeru version 8.0.402.0, 11.0.22.0, 17.0.10.0, 21.0.2.0 or higher.

Note: Information in this guide does not apply for the IBM Semeru Runtime Certified Edition for z/OS. For more information about the certified edition, see IBM Semeru Runtime Certified Edition for z/OS documentation.

Available in Semeru version 11.0.23, 17.0.10.0,  21.0.3.0 or higher, is a technical preview that allows testing of FIPS 140-3 certified cryptography. Refer to FIPS 140-3 evaluation technology in IBM Semeru Runtimes to read more about and use the technical preview for FIPS 140-3. Observe the disclaimer associated with the FIPS 140-3 technical preview.

FIPS mode relies on the operating system's underlying NSS FIPS 140-2 certification. For information about the status of FIPS 140-2 certification in specific minor releases of RHEL 8, see the Red Hat Government Standards article.

Note: FIPS mode is not the same as the FIPS support in IBM SDK, Java Technology Edition Version 8. For example, the configuration and restrictions are different.

Enabling FIPS mode

Follow these instructions to run IBM Semeru Runtimes in FIPS mode:

  1. If you didn't install your RHEL operating system in FIPS mode, switch it to FIPS mode as described in Switching the system to FIPS mode in the RHEL 8 documentation.
  2. Start the Semeru JVM, specifying the -Dsemeru.fips=true system property on the command line. This property instructs the JVM to use only FIPS certified cryptography and ensures that the TLS and SSL protocols use only FIPS certified algorithms. If you want to enable debug tracing also, specify the -Djava.security.debug=semerufips system property.

If you want to run IBM Semeru Runtimes in FIPS mode in a container, ensure that the Network Security Services (nss) package is installed in the container image (you can install it by running the command dnf install nss). Then, switch the host operating system to FIPS mode and run the JVM as described previously.

Keys and certificates in FIPS mode

In FIPS mode, the IBM Semeru Runtimes use the Network Security Services (NSS) database as a read-only PKCS#11 store for keys and certificates. When you specify the -Dsemeru.fips=true system property, the keystore.type security property is set to PKCS#11 and the javax.net.ssl.keyStore system property is set to NONE.

If you want your Java application to use TLS or SSL in FIPS mode while also using custom trust certificates (as in Example 2, later), you might also need to specify the following command-line options. For example, if your application doesn't explicitly specify the provider to use and instead relies on the system-configured trust stores for TLS and SSL, use the following system properties to set the appropriate values for the truststore:

  • javax.net.ssl.trustStoreType="PKCS11"
  • javax.net.ssl.trustStore="NONE"
  • javax.net.ssl.trustStoreProvider=SunPKCS11-NSS-FIPS

For more information about these properties, see the Oracle PKCS11 documentation.

Security profile naming conventions

The java.security profile naming conventions have changed over time to support simultaneous restricted security profiles along with a more robust versioning system for these profiles in support of FIPS. Throughout this document a security profile will be referenced as $PROFILE_NAME. Refer to the following list for the actual name to use in place of $PROFILE_NAME:

  • Semeru versions prior to 8.0.402.0, 11.0.22.0, 17.0.10.0, and 21.0.1.0 make use of the profile name "RestrictedSecurity1”
  • Semeru versions including and higher than 8.0.402.0, 11.0.22.0, 17.0.10.0, and 21.0.1.0 make use of the profile name “RestrictedSecurity.NSS.140-2”

There are two ways to use a PKCS#12 file-based keystore:

  1. Manually import a PKCS#12 file-based keystore file into the NSSDB without making modifications to the java.security file.

    If you want to use a file-based keystore but don't want to make any modifications in your java.security file, you must import it into the NSS database before you use it. Use the pk12util NSS tool to import keys and certificates from a PKCS#12 keystore file into the NSS database. For example,

    pk12util -i keystore.p12 -W changeit -d /etc/pki/nssdb

    where keystore.p12 is the name of the keystore, changeit is the password, and /etc/pki/nssdb is the location of the NSS database repository.

    Note: In FIPS mode, IBM Semeru Runtimes does not support usage of the NSS database with password. While importing the PKCS#12 file-based keystore into the NSS database, if the pk12util tool asks to setup the password, press the Enter key twice to setup an empty password.

  2. Use the certutil tool to confirm that the keystore was imported successfully into the NSS database. For example:

    certutil -K -d /etc/pki/nssdb

    Similarly, use the pk12util tool to import trust anchor certificates from a PKCS#12 truststore file. For example:

    pk12util -i truststore.p12 -W changeit -d /etc/pki/nssdb

    where truststore.p12 is the name of the truststore. After importing the trust certificates, use the certutil tool to mark each of them as a trusted certificate authority (CA) for issuing client and server certificates, by setting the -t or trustargs attribute to CT, CT, CT. You can set this attribute for each individual certificate, for example:

    certutil -M -n myTrustCert -t "CT,CT,CT" -d /etc/pki/nssdb

    where myTrustCert is the name of the trust anchor certificate. Or you can set this attribute for all imported trust certificates by using a single command such as the following:

    certutil -L -d /etc/pki/nssdb | grep ",," | sed 's/ ,,.*//' | sed 's/ *$//' | while read line; do certutil -M -n "$line" -t "CT,CT,CT" -d /etc/pki/nssdb; done

    For more information about the NSS libraries and tools, see the Mozilla NSS documentation.

  3. Use a PKCS#12 file-based keystore file directly by making modifications to the java.security file.

    A PKCS#12 file-based keystore is now supported in FIPS mode. The IBM Semeru FIPS solution enables users to store new keys, or load existing keys, using the PKCS#12 file based key store standard. Compliance with FIPS regulations becomes crucial when keys are moved outside the cryptographic module. In our case, when keys are transferred to a different computer from the one they were generated on. PKCS#12 is not an appropriate FIPS certified process for moving keys outside the cryptographic module. In the case of moving key material to another machine, we need to use a different process using FIPS certified techniques to ensure compliance.

    To comply with FIPS regulations while maintaining flexibility and functionality, non-FIPS algorithms can be used to access PKCS#12 keystores when they are used on the same machine the key was generated on. This approach ensures compliance without compromising the desired use of PKCS#12 file formats. Similar to our previous implementation with IBM Java 8, this approach allows for the support of various key storage mechanisms such as PKCS#12 on local machines. It is the responsibility of applications to ensure that any key material that leaves the machine it was generated on is done in a FIPS compliant manor.

    To create or load a keystore, we use the existing non-FIPS certified services registered in the SunJCE provider. These services, including AlgorithmParameters, Cipher, Mac, and SecretKeyFactory, need to be set in the java.security file for the SunJCE provider to allow for PKCS#12 key file formats to be read and written to.

    For example, if a user wants to load/create a keystore named testkeys.p12, the following keytool command can be used in FIPS mode:

    keytool -J-Dsemeru.fips=true -v -genkeypair -alias rsakeyfips -dname "CN=rsatest" -keystore testkeys.p12 -keyalg RSA -storetype PKCS12 -storepass "1234567890123456"

    The user must enable the following algorithms to work within the java.security file under profile_name.jce.provider.4 = SunJSSE.

    For JDK 11 and later:

    $PROFILE_NAME.jce.provider.5 = SunJCE [{AlgorithmParameters, PBES2, *}, \
    {AlgorithmParameters, PBEWithHmacSHA256AndAES_256, *}, \
    {SecretKeyFactory, PBEWithMD5AndDES, *}, \ 
    {Cipher, PBEWithHmacSHA256AndAES_256, *}, \ 
    {Mac, HmacPBESHA256, *}]

    For JDK 8:

    $PROFILE_NAME.jce.provider.5 = com.sun.crypto.provider.SunJCE \ 
    [{AlgorithmParameters, PBE, *}, \ 
    {AlgorithmParameters, PBEWithSHA1AndDESede, *}, \ 
    {AlgorithmParameters, PBEWithSHA1AndRC2_40, *}, \ 
    {Cipher, PBEWithSHA1AndDESede, *}, \ 
    {Cipher, PBEWithSHA1AndRC2_40, *}, \ 
    {Mac, HmacPBESHA1, *}, \ 
    {SecretKeyFactory, PBEWithMD5AndDES, *}]

    In addition, a PKCS#12 keystore typically needs to use the `Keystore.getInstance()` method implicitly or explicitly. For implicit usage, you probably need to modify the value of profile_name.keystore.type in the java.security file from PKCS11 to PKCS12. This is dependent on the application that you are using. For explicit usage, you most likely just call `Keystore.getInstance(“pkcs12“)` method to get a PKCS#12 keystore instance. You must ensure that the key is greater than 16 bytes long in this case due to FIPS restrictions, otherwise, you will hit this error message or exception:

    • java.io.IOException: keystore password was incorrect or
    • CKR_KEY_SIZE_RANGE

    Currently, the Semeru FIPS solution only supports the import or export of RSA and EC keys, therefore, we only support the loading and creation of PKCS#12 keystores that contain these types of keys as specified by using the `-keyalg` keytool parameter. Any other value for the `-keyalg` parameter will cause exceptions.

    Here is an example to create a PKCS#12 keystore in FIPS mode by using keytool:

    keytool -J-Dsemeru.fips=true -v -genkeypair -alias rsakeyfips -dname "CN=rsatest" -keyalg RSA -keystore testkeys.p12 -storetype PKCS12 -storepass "1234567890123456"

    Here is an example to create a PKCS#12 keystore in FIPS mode by using OpenSSL:

    openssl pkcs12 -export -in test.cer -inkey pkcs8.pem -out testKS.p12 -certpbe AES-256-CBC -keypbe AES-256-CBC -macalg sha256 -password pass:1234567890123456

    If you are using a bigger size of MAC algorithm such as sha384, you must increase the length of the password to at least 24 bytes long. For example,

    openssl pkcs12 -export -in test.cer -inkey pkcs8.pem -out testKS.p12 -certpbe AES-256-CBC -keypbe AES-256-CBC -macalg sha384 -password pass:123456789012345678901234

    When reading PKCS#12 files, the file format might make use of any number of algorithms to securely package the key material within the file. Typically, an exception occurs whenever a PKCS#12 file is read indicating what algorithm has not been allowed whenever the needed algorithm is not present in the java.security file.

    Various algorithms that might need to be enabled in your java.security file include the following values: Note that you do not need to enable all of those listed algorithms. Many of these algorithms can be removed based upon the exact type of PKCS#12 file and the algorithms that are in use by the specific file.

    For JDK 11 and later:

    $PROFILE_NAME.jce.provider.5 = SunJCE [{AlgorithmParameters, PBES2, *}, \ 
    {AlgorithmParameters, AES, *}, \ 
    {AlgorithmParameters, PBEWithHmacSHA1AndAES_128, *}, \ 
    {AlgorithmParameters, PBEWithHmacSHA1AndAES_256, *}, \ 
    {AlgorithmParameters, PBEWithHmacSHA224AndAES_128, *}, \ 
    {AlgorithmParameters, PBEWithHmacSHA224AndAES_256, *}, \ 
    {AlgorithmParameters, PBEWithHmacSHA256AndAES_128, *}, \ 
    {AlgorithmParameters, PBEWithHmacSHA256AndAES_256, *}, \ 
    {AlgorithmParameters, PBEWithHmacSHA384AndAES_128, *}, \ 
    {AlgorithmParameters, PBEWithHmacSHA384AndAES_256, *}, \ 
    {AlgorithmParameters, PBEWithHmacSHA512AndAES_128, *}, \ 
    {AlgorithmParameters, PBEWithHmacSHA512AndAES_256, *}, \ 
    {AlgorithmParameters, PBEWithMD5AndDES, *}, \ 
    {AlgorithmParameters, PBEWithMD5AndTripleDES, *}, \ 
    {AlgorithmParameters, PBEWithSHA1AndDESede, *}, \ 
    {AlgorithmParameters, PBEWithSHA1AndRC2_128, *}, \ 
    {AlgorithmParameters, PBEWithSHA1AndRC2_40, *}, \ 
    {AlgorithmParameters, PBEWithSHA1AndRC4_128, *}, \ 
    {AlgorithmParameters, PBEWithSHA1AndRC4_40, *}, \ 
    {Cipher, PBEWithHmacSHA1AndAES_128, *}, \ 
    {Cipher, PBEWithHmacSHA1AndAES_256, *}, \ 
    {Cipher, PBEWithHmacSHA224AndAES_128, *}, \ 
    {Cipher, PBEWithHmacSHA224AndAES_256, *}, \ 
    {Cipher, PBEWithHmacSHA256AndAES_128, *}, \ 
    {Cipher, PBEWithHmacSHA256AndAES_256, *}, \ 
    {Cipher, PBEWithHmacSHA384AndAES_128, *}, \ 
    {Cipher, PBEWithHmacSHA384AndAES_256, *}, \ 
    {Cipher, PBEWithHmacSHA512AndAES_128, *}, \ 
    {Cipher, PBEWithHmacSHA512AndAES_256, *}, \ 
    {Cipher, PBEWithMD5AndDES, *}, \ 
    {Cipher, PBEWithMD5AndTripleDES, *}, \ 
    {Cipher, PBEWithSHA1AndDESede, *}, \ 
    {Cipher, PBEWithSHA1AndRC2_128, *}, \ 
    {Cipher, PBEWithSHA1AndRC2_40, *}, \ 
    {Cipher, PBEWithSHA1AndRC4_128, *}, \ 
    {Cipher, PBEWithSHA1AndRC4_40, *}, \ 
    {Mac, HmacPBESHA1, *}, \ 
    {Mac, HmacPBESHA224, *}, \ 
    {Mac, HmacPBESHA256, *}, \ 
    {Mac, HmacPBESHA384, *}, \ 
    {Mac, HmacPBESHA512, *}, \ 
    {Mac, PBEWithHmacSHA1, *}, \ 
    {Mac, PBEWithHmacSHA224, *}, \ 
    {Mac, PBEWithHmacSHA256, *}, \ 
    {Mac, PBEWithHmacSHA384, *}, \ 
    {Mac, PBEWithHmacSHA512, *}, \ 
    {SecretKeyFactory, PBEWithHmacSHA1AndAES_128, *}, \ 
    {SecretKeyFactory, PBEWithHmacSHA1AndAES_256, *}, \ 
    {SecretKeyFactory, PBEWithHmacSHA224AndAES_128, *}, \ 
    {SecretKeyFactory, PBEWithHmacSHA224AndAES_256, *}, \ 
    {SecretKeyFactory, PBEWithHmacSHA256AndAES_128, *}, \ 
    {SecretKeyFactory, PBEWithHmacSHA256AndAES_256, *}, \ 
    {SecretKeyFactory, PBEWithHmacSHA384AndAES_128, *}, \ 
    {SecretKeyFactory, PBEWithHmacSHA384AndAES_256, *}, \ 
    {SecretKeyFactory, PBEWithHmacSHA512AndAES_128, *}, \ 
    {SecretKeyFactory, PBEWithHmacSHA512AndAES_256, *}, \ 
    {SecretKeyFactory, PBEWithMD5AndDES, *}, \ 
    {SecretKeyFactory, PBEWithMD5AndTripleDES, *}, \ 
    {SecretKeyFactory, PBEWithSHA1AndDESede, *}, \ 
    {SecretKeyFactory, PBEWithSHA1AndRC2_128, *}, \ 
    {SecretKeyFactory, PBEWithSHA1AndRC2_40, *}, \ 
    {SecretKeyFactory, PBEWithSHA1AndRC4_128, *}, \ 
    {SecretKeyFactory, PBEWithSHA1AndRC4_40, *}, \ 
    {SecretKeyFactory, PBKDF2WithHmacSHA1, *}, \ 
    {SecretKeyFactory, PBKDF2WithHmacSHA224, *}, \ 
    {SecretKeyFactory, PBKDF2WithHmacSHA256, *}, \ 
    {SecretKeyFactory, PBKDF2WithHmacSHA384, *}, \ 
    {SecretKeyFactory, PBKDF2WithHmacSHA512, *}]

    For JDK 8:

    $PROFILE_NAME.jce.provider.5 = com.sun.crypto.provider.SunJCE \ 
    [{AlgorithmParameters, AES, *}, \ 
    {AlgorithmParameters, PBE, *}, \ 
    {AlgorithmParameters, PBES2, *}, \ 
    {AlgorithmParameters, PBEWithHmacSHA1AndAES_128, *}, \ 
    {AlgorithmParameters, PBEWithHmacSHA1AndAES_256, *}, \ 
    {AlgorithmParameters, PBEWithHmacSHA224AndAES_128, *}, \ 
    {AlgorithmParameters, PBEWithHmacSHA224AndAES_256, *}, \ 
    {AlgorithmParameters, PBEWithHmacSHA256AndAES_128, *}, \ 
    {AlgorithmParameters, PBEWithHmacSHA256AndAES_256, *}, \ 
    {AlgorithmParameters, PBEWithHmacSHA384AndAES_128, *}, \ 
    {AlgorithmParameters, PBEWithHmacSHA384AndAES_256, *}, \ 
    {AlgorithmParameters, PBEWithHmacSHA512AndAES_128, *}, \ 
    {AlgorithmParameters, PBEWithHmacSHA512AndAES_256, *}, \ 
    {AlgorithmParameters, PBEWithMD5AndDES, *}, \ 
    {AlgorithmParameters, PBEWithMD5AndTripleDES, *}, \ 
    {AlgorithmParameters, PBEWithSHA1AndDESede, *}, \
    {AlgorithmParameters, PBEWithSHA1AndRC2_128, *}, \ 
    {AlgorithmParameters, PBEWithSHA1AndRC2_40, *}, \ 
    {AlgorithmParameters, PBEWithSHA1AndRC4_128, *}, \ 
    {AlgorithmParameters, PBEWithSHA1AndRC4_40, *}, \ 
    {Cipher, PBEWithHmacSHA1AndAES_128, *}, \ 
    {Cipher, PBEWithHmacSHA1AndAES_256, *}, \ 
    {Cipher, PBEWithHmacSHA224AndAES_128, *}, \ 
    {Cipher, PBEWithHmacSHA224AndAES_256, *}, \ 
    {Cipher, PBEWithHmacSHA256AndAES_128, *}, \ 
    {Cipher, PBEWithHmacSHA256AndAES_256, *}, \ 
    {Cipher, PBEWithHmacSHA384AndAES_128, *}, \ 
    {Cipher, PBEWithHmacSHA384AndAES_256, *}, \ 
    {Cipher, PBEWithHmacSHA512AndAES_128, *}, \ 
    {Cipher, PBEWithHmacSHA512AndAES_256, *}, \ 
    {Cipher, PBEWithMD5AndDES, *}, \ 
    {Cipher, PBEWithMD5AndTripleDES, *}, \ 
    {Cipher, PBEWithSHA1AndDESede, *}, \ 
    {Cipher, PBEWithSHA1AndRC2_128, *}, \ 
    {Cipher, PBEWithSHA1AndRC2_40, *}, \ 
    {Cipher, PBEWithSHA1AndRC4_128, *}, \ 
    {Cipher, PBEWithSHA1AndRC4_40, *}, \ 
    {Mac, HmacPBESHA1, *}, \ 
    {Mac, HmacPBESHA224, *}, \ 
    {Mac, HmacPBESHA256, *}, \ 
    {Mac, HmacPBESHA384, *}, \ 
    {Mac, HmacPBESHA512, *}, \ 
    {Mac, PBEWithHmacSHA1, *}, \ 
    {Mac, PBEWithHmacSHA224, *}, \ 
    {Mac, PBEWithHmacSHA256, *}, \ 
    {Mac, PBEWithHmacSHA384, *}, \ 
    {Mac, PBEWithHmacSHA512, *}, \ 
    {SecretKeyFactory, PBEWithHmacSHA1AndAES_128, *}, \ 
    {SecretKeyFactory, PBEWithHmacSHA1AndAES_256, *}, \ 
    {SecretKeyFactory, PBEWithHmacSHA224AndAES_128, *}, \ 
    {SecretKeyFactory, PBEWithHmacSHA224AndAES_256, *}, \ 
    {SecretKeyFactory, PBEWithHmacSHA256AndAES_128, *}, \ 
    {SecretKeyFactory, PBEWithHmacSHA256AndAES_256, *}, \ 
    {SecretKeyFactory, PBEWithHmacSHA384AndAES_128, *}, \ 
    {SecretKeyFactory, PBEWithHmacSHA384AndAES_256, *}, \ 
    {SecretKeyFactory, PBEWithHmacSHA512AndAES_128, *}, \ 
    {SecretKeyFactory, PBEWithHmacSHA512AndAES_256, *}, \ 
    {SecretKeyFactory, PBEWithMD5AndDES, *}, \ 
    {SecretKeyFactory, PBEWithMD5AndTripleDES, *}, \ 
    {SecretKeyFactory, PBEWithSHA1AndDESede, *}, \ 
    {SecretKeyFactory, PBEWithSHA1AndRC2_128, *}, \ 
    {SecretKeyFactory, PBEWithSHA1AndRC2_40, *}, \ 
    {SecretKeyFactory, PBEWithSHA1AndRC4_128, *}, \ 
    {SecretKeyFactory, PBEWithSHA1AndRC4_40, *}, \ 
    {SecretKeyFactory, PBKDF2WithHmacSHA1, *}, \ 
    {SecretKeyFactory, PBKDF2WithHmacSHA224, *}, \ 
    {SecretKeyFactory, PBKDF2WithHmacSHA256, *}, \ 
    {SecretKeyFactory, PBKDF2WithHmacSHA384, *}, \ 
    {SecretKeyFactory, PBKDF2WithHmacSHA512, *}]

Example 1: Encryption

This example shows how to use the cipher algorithm AES/CBC/PKCS5Padding for encryption in FIPS mode.

  1. Create Java code:
    package com.test.fips;
    import java.security.SecureRandom;
    import javax.crypto.Cipher;
    import javax.crypto.SecretKey;
    import javax.crypto.spec.SecretKeySpec;
    
    public class AES {
    
        public static void main(String[] args) throws Exception {
    
            SecureRandom secureRandom = new SecureRandom(); 
            byte[] key = new byte[16]; 
            byte[] plainText = new byte[32]; 
            secureRandom.nextBytes(key); 
            secureRandom.nextBytes(plainText);
    
            SecretKey secretKey = new SecretKeySpec(key, "AES");
    
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
            cipher.init(Cipher.ENCRYPT_MODE, secretKey);
    
            byte[] cipherText = cipher.doFinal(plainText); 
            System.out.println("Encryption Done"); 
        }
    }
  2. Run the application, specifying both the FIPS system properties on the command line to enable FIPS mode and provide tracing:
    java -Dsemeru.fips=true -Djava.security.debug=semerufips com.test.fips.AES
    The console shows the following output:
    semerufips: FIPS mode detected, loading properties
    semerufips: FIPS mode properties loaded
    Encryption Done

Example 2: Using a PKCS#12 keystore and truststore in FIPS mode

  1. Generate the keys and trust certificates by using OpenSSL commands:
    openssl req -x509 -newkey rsa:4096 -passin pass:changeit -passout pass:changeit -keyout key.pem -out cert.pem -sha256 -days 365  -subj '/C=CA/ST=ON/L=TORONTO/CN=www.ibm.com'
    openssl pkcs12 -export -keypbe AES-128-CBC -passin pass:changeit -passout pass:changeit -name myKeyCert -out keystore.p12 -inkey key.pem -in cert.pem
    openssl pkcs12 -export -nokeys -passout pass:changeit -caname myTrustCert -in cert.pem -out truststore.p12
    For more information about the OpenSSL utilities for generating certificates, see the OpenSSL documentation.
  2. Create Java code that reads the PKCS#12 keystore then prints its entries:
    char[] password = "changeit".toCharArray();
    byte[] byteArray = Files.readAllBytes(Paths.get("keystore.p12"));
    bais = new ByteArrayInputStream(byteArray);
    KeyStore ks = KeyStore.getInstance("pkcs12");
    ks.load(bais, password);
    
    Enumeration<String> enumeration = ks.aliases();
    while(enumeration.hasMoreElements()) {
        String alias = enumeration.nextElement();
        System.out.println("PKCS12 alias name: " + alias);
        System.out.println("PKCS12 certificate: \n" + ks.getCertificate(alias).toString());
    }
    Repeat the code, replacing keystore.p12 with truststore.p12, to read the PKCS#12 truststore and print its entries.
  3. Run the application without enabling FIPS mode to see the output for the PKCS#12 keystore and truststore.
  4. To run the application in FIPS mode, the keystore and truststore must reside in the PKCS#11 based NSS database. Import the PKCS#12 keystore and truststore into the NSS database then mark the truststore certificates as trusted CA:
    pk12util -i keystore.p12 -W changeit -d /etc/pki/nssdb
    pk12util -i truststore.p12 -W changeit -d /etc/pki/nssdb
    certutil -M -n myTrustCert -t "CT,CT,CT" -d /etc/pki/nssdb
  5. Modify the Java code to read the PKCS#11 keystore then print its entries:
    char[] password = "changeit".toCharArray();
    KeyStore ks = KeyStore.getInstance("pkcs11");
    ks.load(null, password);
    
    Enumeration<String> enumeration = ks.aliases();
    while(enumeration.hasMoreElements()) {
        String alias = enumeration.nextElement();
        System.out.println("PKCS11 alias name: " + alias);
        System.out.println("PKCS11 certificate: \n" + ks.getCertificate(alias).toString());
    }
    Do the same for the truststore.
  6. Run the application with FIPS mode enabled to see the output for the PKCS#11 keystore and truststore in the NSS database.

Example 3: Configuring Open Liberty to use FIPS mode

  1. Enable FIPS mode by following the earlier instructions.
  2. Import the keystore into the NSS database:
    pk12util -i keystore.p12 -W changeit -d /etc/pki/nssdb
  3. Create an Open Liberty configuration file, called pkcs11cfg.cfg for example, to point to the NSS library required for reading the PKCS#11 keystore. Create the file in a location that is accessible to the Open Liberty server, then add the following content to the file:
    name = NSS-FIPS
    library = /usr/lib64/libsoftokn3.so
    slot = 3
    showInfo=true
  4. Modify the Open Liberty server.xml configuration file to reference the file that you created in the previous step and specify that the NSS keystore is accessed using PKCS#11. For example:
    <keyStore id="daytrader7" location="pkcs11cfg.cfg" type="PKCS11-NSS-FIPS" fileBased="false" password="changeit" provider="SunPKCS11-NSS-FIPS"/>
    This change instructs Open Liberty to use the NSS PKCS#11 based keystore instead of the file based keystore. For more information about the keystore element, see the Open Liberty documentation.

Example 4: Using a PKCS#12 keystore and truststore in FIPS mode by editing the java.security file

  1. Generate the keys and trust certificates by using OpenSSL commands:
    openssl req -x509 -newkey rsa:4096 -passin pass:1234567890123456 -passout pass:1234567890123456 -keyout key.pem -out cert.pem -sha256 -days 365 -subj '/C=CA/ST=ON/L=TORONTO/CN=www.ibm.com'
    openssl pkcs12 -export -keypbe AES-256-CBC -passin pass:1234567890123456 -passout pass:1234567890123456 -name myKeyCert -out keystore.p12 -inkey key.pem -in cert.pem
    openssl pkcs12 -export -nokeys -passout pass:1234567890123456 -caname myTrustCert -in cert.pem -out truststore.p12
    For more information about the OpenSSL utilities for generating certificates, see the OpenSSL documentation.
  2. Modify your java.security file by adding those under the profile_name.jce.provider.4 = SunJSSE

    For JDK 11 and later:

    $PROFILE_NAME.jce.provider.5 = SunJCE [{AlgorithmParameters, PBEWithSHA1AndDESede, *}, \
    {AlgorithmParameters, PBEWithMD5AndDES, *}, \
    {SecretKeyFactory, PBEWithMD5AndDES, *}, \
    {Cipher, PBEWithSHA1AndDESede, *}, \
    {Mac, HmacPBESHA1, *}]
    

    For JDK 8:

    $PROFILE_NAME.jce.provider.5 = com.sun.crypto.provider.SunJCE \
    [{AlgorithmParameters, PBEWithSHA1AndDESede, *}, \
    {AlgorithmParameters, PBE, *}, \
    {SecretKeyFactory, PBEWithMD5AndDES, *}, \
    {Cipher, PBEWithSHA1AndDESede, *}, \
    {Mac, HmacPBESHA1, *}]
    
  3. Create Java code that reads the PKCS#12 keystore then prints its entries:
    import java.nio.file.Files;
    import java.nio.file.Paths;
    import java.security.KeyStore;
    import java.util.Enumeration;
    import java.io.ByteArrayInputStream;
    	
    public class demo {
       public static void main(String[] args) throws Exception {
    	char[] password = "1234567890123456".toCharArray();
    	byte[] byteArray = Files.readAllBytes(Paths.get("keystore.p12"));
    	ByteArrayInputStream bais = new ByteArrayInputStream(byteArray);
    	KeyStore ks = KeyStore.getInstance("pkcs12");
    	ks.load(bais, password);
    	
    	Enumeration enumeration = ks.aliases();
    	while(enumeration.hasMoreElements()) {
    	String alias = enumeration.nextElement();
    	System.out.println("PKCS12 alias name: " + alias);
    	System.out.println("PKCS12 certificate: \n" + ks.getCertificate(alias).toString());
    	}
          }
    }
    Repeat the code, replacing keystore.p12 with truststore.p12, to read the PKCS#12 truststore and print its entries.

Known issues

If your application uses the SecureRandom.getInstanceStrong() method, you might see the following error when you run the application in FIPS mode:

Exception in thread "main" java.security.NoSuchAlgorithmException: No strong SecureRandom impls available: NativePRNGBlocking:SUN,DRBG:SUN

This issue exists because the default algorithm that is specified by the securerandom.strongAlgorithms property is not FIPS compliant. You can solve this issue in one of the following ways:

  • Change your application to use the SecureRandom.getInstance("PKCS11") method instead of the the SecureRandom.getInstanceStrong() method.
  • Change the securerandom.strongAlgorithms property in your java.security file to specify a different strong, secure algorithm. (The java.security file is located in the $JAVA_HOME/conf/security directory for version 11 and later, and in $JAVA_HOME/jre/lib/security for version 8.) Find this line:

    securerandom.strongAlgorithms=NativePRNGBlocking:SUN,DRBG:SUN

    Change the line to the following text:

    securerandom.strongAlgorithms=PKCS11:SunPKCS11
    <keyStore id="daytrader7" location="pkcs11cfg.cfg" type="PKCS11-NSS-FIPS" fileBased="false" password="changeit" provider="SunPKCS11-NSS-FIPS"/>
This change instructs Open Liberty to use the NSS PKCS#11 based keystore instead of the file based keystore. For more information about the keystore element, see the Open Liberty documentation.

[{"Type":"MASTER","Line of Business":{"code":"LOB45","label":"Automation"},"Business Unit":{"code":"BU059","label":"IBM Software w\/o TPS"},"Product":{"code":"SSA3RN","label":"IBM Semeru Runtimes"},"ARM Category":[],"Platform":[{"code":"PF025","label":"Platform Independent"}],"Version":"8.0.0;and future releases"}]

Document Information

Modified date:
28 May 2024

UID

ibm16612693