Chapter 17. FIPS 140-2 support The Federal Information Processing Standard Publication 140-2, (FIPS 140-2), is a U.S. government computer security standard used to approve cryptographic modules. Red Hat build of Keycloak supports running in FIPS 140-2 compliant mode. In this case, Red Hat build of Keycloak will use only FIPS approved cryptography algorithms for its functionality. To run in FIPS 140-2, Red Hat build of Keycloak should run on a FIPS 140-2 enabled system. This requirement usually assumes RHEL or Fedora where FIPS was enabled during installation. See RHEL documentation for the details. When the system is in FIPS mode, it makes sure that the underlying OpenJDK is in FIPS mode as well and would use only FIPS enabled security providers . To check that the system is in FIPS mode, you can check it with the following command from the command line: fips-mode-setup --check If the system is not in FIPS mode, you can enable it with the following command, however it is recommended that system is in FIPS mode since the installation rather than subsequently enabling it as follows: fips-mode-setup --enable 17.1. BouncyCastle library Red Hat build of Keycloak internally uses the BouncyCastle library for many cryptography utilities. Please note that the default version of the BouncyCastle library that shipped with Red Hat build of Keycloak is not FIPS compliant; however, BouncyCastle also provides a FIPS validated version of its library. The FIPS validated BouncyCastle library cannot be shipped with Red Hat build of Keycloak due to license constraints and Red Hat build of Keycloak cannot provide official support of it. Therefore, to run in FIPS compliant mode, you need to download BouncyCastle-FIPS bits and add them to the Red Hat build of Keycloak distribution. When Red Hat build of Keycloak executes in fips mode, it will use the BCFIPS bits instead of the default BouncyCastle bits, which achieves FIPS compliance. 17.1.1. BouncyCastle FIPS bits BouncyCastle FIPS can be downloaded from the BouncyCastle official page . Then you can add them to the directory KEYCLOAK_HOME/providers of your distribution. Make sure to use proper versions compatible with BouncyCastle Red Hat build of Keycloak dependencies. The supported BCFIPS bits needed are: bc-fips version 2.0.0. bctls-fips version 2.0.19. bcpkix-fips version 2.0.7. bcutil-fips version 2.0.3. 17.2. Generating keystore You can create either pkcs12 or bcfks keystore to be used for the Red Hat build of Keycloak server SSL. 17.2.1. PKCS12 keystore The p12 (or pkcs12 ) keystore (and/or truststore) works well in BCFIPS non-approved mode. PKCS12 keystore can be generated with OpenJDK 21 Java on RHEL 9 in the standard way. For instance, the following command can be used to generate the keystore: keytool -genkeypair -sigalg SHA512withRSA -keyalg RSA -storepass passwordpassword \ -keystore USDKEYCLOAK_HOME/conf/server.keystore \ -alias localhost \ -dname CN=localhost -keypass passwordpassword The pkcs12 keystores in FIPS mode do not manage secret (symmetric) keys. This limitation is imposed by the BCFIPS provider which does not allow this type of keys inside the pkcs12 keystore type. When the system is in FIPS mode, the default java.security file is changed in order to use FIPS enabled security providers, so no additional configuration is needed. Additionally, in the PKCS12 keystore, you can store PBE (password-based encryption) keys simply by using the keytool command, which makes it ideal for using it with Red Hat build of Keycloak KeyStore Vault and/or to store configuration properties in the KeyStore Config Source. For more details, see the Configuring Red Hat build of Keycloak and the Using a vault . 17.2.2. BCFKS keystore BCFKS keystore generation requires the use of the BouncyCastle FIPS libraries and a custom security file. You can start by creating a helper file, such as /tmp/kc.keystore-create.java.security . The content of the file needs only to have the following property: , enter a command such as the following to generate the keystore: keytool -keystore USDKEYCLOAK_HOME/conf/server.keystore \ -storetype bcfks \ -providername BCFIPS \ -providerclass org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider \ -provider org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider \ -providerpath USDKEYCLOAK_HOME/providers/bc-fips-*.jar \ -alias localhost \ -genkeypair -sigalg SHA512withRSA -keyalg RSA -storepass passwordpassword \ -dname CN=localhost -keypass passwordpassword \ -J-Djava.security.properties=/tmp/kc.keystore-create.java.security Warning Using self-signed certificates is for demonstration purposes only, so replace these certificates with proper certificates when you move to a production environment. Similar options are needed when you are doing any other manipulation with keystore/truststore of bcfks type. 17.3. Running the server. To run the server with BCFIPS in non-approved mode, enter the following command bin/kc.[sh|bat] start --features=fips --hostname=localhost --https-key-store-password=passwordpassword --log-level=INFO,org.keycloak.common.crypto:TRACE,org.keycloak.crypto:TRACE Note In non-approved mode, the default keystore type (as well as default truststore type) is PKCS12. Hence if you generated a BCFKS keystore as described above, it is also required to use the command --https-key-store-type=bcfks . A similar command might be needed for the truststore as well if you want to use it. Note You can disable logging in production if everything works as expected. 17.4. Strict mode There is the fips-mode option, which is automatically set to non-strict when the fips feature is enabled. This means to run BCFIPS in the "non-approved mode". The more secure alternative is to use --features=fips --fips-mode=strict in which case BouncyCastle FIPS will use "approved mode". Using that option results in stricter security requirements on cryptography and security algorithms. Note In strict mode, the default keystore type (as well as default truststore type) is BCFKS. If you want to use a different keystore type it is required to use the option --https-key-store-type with appropriate type. A similar command might be needed for the truststore as well if you want to use it. When starting the server, you can check that the startup log contains KC provider with the note about Approved Mode such as the following: 17.4.1. Cryptography restrictions in strict mode As mentioned in the section, strict mode may not work with pkcs12 keystore. It is required to use another keystore (like bcfks ) as mentioned earlier. Also jks and pkcs12 keystores are not supported in Red Hat build of Keycloak when using strict mode. Some examples are importing or generating a keystore of an OIDC or SAML client in the Admin Console or for a java-keystore provider in the realm keys. User passwords must be 14 characters or longer. Red Hat build of Keycloak uses PBKDF2 based password encoding by default. BCFIPS approved mode requires passwords to be at least 112 bits (effectively 14 characters) with PBKDF2 algorithm. If you want to allow a shorter password, set the property max-padding-length of provider pbkdf2-sha512 of SPI password-hashing to 14 to provide additional padding when verifying a hash created by this algorithm. This setting is also backwards compatible with previously stored passwords. For example, if the user's database is in a non-FIPS environment and you have shorter passwords and you want to verify them now with Red Hat build of Keycloak using BCFIPS in approved mode, the passwords should work. So effectively, you can use an option such as the following when starting the server: Note Using the option above does not break FIPS compliance. However, note that longer passwords are good practice anyway. For example, passwords auto-generated by modern browsers match this requirement as they are longer than 14 characters. If you want to omit the option for max-padding-length, you can set the password policy to your realms to have passwords at least 14 characters long. Note When you are migrating from Red Hat build of Keycloak older than 24, or if you explicitly set the password policy to override the default hashing algorithm, it is possible that some of your users use an older algorithm like pbkdf2-sha256 . In this case, consider adding the --spi-password-hashing-pbkdf2-sha256-max-padding-length=14 option to ensure that users having their passwords hashed with the older pbkdf2-sha256 can log in because their passwords may be shorter than 14 characters. RSA keys of 1024 bits do not work (2048 is the minimum). This applies for keys used by the Red Hat build of Keycloak realm itself (Realm keys from the Keys tab in the admin console), but also client keys and IDP keys HMAC SHA-XXX keys must be at least 112 bits (or 14 characters long). For example if you use OIDC clients with the client authentication Signed Jwt with Client Secret (or client-secret-jwt in the OIDC notation), then your client secrets should be at least 14 characters long. Note that for good security, it is recommended to use client secrets generated by the Red Hat build of Keycloak server, which always fulfils this requirement. The bc-fips version 1.0.2.4 deals with the end of the transition period for PKCS 1.5 RSA encryption. Therefore JSON Web Encryption (JWE) with algorithm RSA1_5 is not allowed in strict mode by default (BC provides the system property -Dorg.bouncycastle.rsa.allow_pkcs15_enc=true as backward compatibility option for the moment). RSA-OAEP and RSA-OAEP-256 are still available as before. 17.5. Other restrictions To have SAML working, make sure that a XMLDSig security provider is available in your security providers. To have Kerberos working, make sure that a SunJGSS security provider is available. In FIPS enabled RHEL 9 in OpenJDK 21, the XMLDSig security provider may be already enabled in the java.security by default and the same applies with latest OpenJDK 17. But with older OpenJDK 17, it may not be enabled by default, which means that SAML effectively cannot work. To have SAML working, you can manually add the provider into JAVA_HOME/conf/security/java.security into the list fips providers. For example, add the line such as the following in case that it is not already available in your FIPS security providers: Adding this security provider should work well. In fact, it is FIPS compliant and is already added by default in the OpenJDK 21 and newer versions of OpenJDK 17. Details are in the bugzilla . Note It is recommended to look at JAVA_HOME/conf/security/java.security and check all configured providers here and make sure that the number matches. In other words, fips.provider.7 assumes that there are already 6 providers configured with prefix like fips.provider.N in this file. If you prefer not to edit your java.security file inside java itself, you can create a custom java security file (for example named kc.java.security ) and add only the single property above for adding XMLDSig provider into that file. Then start your Red Hat build of Keycloak server with this property file attached: For Kerberos/SPNEGO, the security provider SunJGSS is not yet fully FIPS compliant. Hence it is not recommended to add it to your list of security providers if you want to be FIPS compliant. The KERBEROS feature is disabled by default in Red Hat build of Keycloak when it is executed on FIPS platform and when security provider is not available. Details are in the bugzilla . The algorithm EdDSA cannot be used in FIPS mode. Although the current BCFIPS provider supports Ed25519 and Ed448 curves, the resulting keys do not implement the standard JDK interfaces to manage them ( EdECKey , EdECPublicKey , EdECPrivateKey ,... ), and Red Hat build of Keycloak cannot use them for signatures. 17.6. Run the CLI on the FIPS host If you want to run Client Registration CLI ( kcreg.sh|bat script) or Admin CLI ( kcadm.sh|bat script), the CLI must also use the BouncyCastle FIPS dependencies instead of plain BouncyCastle dependencies. To achieve this, you may copy the jars to the CLI library folder and that is enough. CLI tool will automatically use BCFIPS dependencies instead of plain BC when it detects that corresponding BCFIPS jars are present (see above for the versions used). For example, use command such as the following before running the CLI: Note When trying to use BCFKS truststore/keystore with CLI, you may see issues due this truststore is not the default java keystore type. It can be good to specify it as default in java security properties. For example run this command on unix based systems before doing any operation with kcadm|kcreg clients: 17.7. Red Hat build of Keycloak server in FIPS mode in containers When you want Red Hat build of Keycloak in FIPS mode to be executed inside a container, your "host" must be using FIPS mode as well. The container will then "inherit" FIPS mode from the parent host. See this section in the RHEL documentation for the details. The Red Hat build of Keycloak container image will automatically be in fips mode when executed from the host in FIPS mode. However, make sure that the Red Hat build of Keycloak container also uses BCFIPS jars (instead of BC jars) and proper options when started. Regarding this, it is best to build your own container image as described in the Running Red Hat build of Keycloak in a container and tweak it to use BCFIPS etc. For example in the current directory, you can create sub-directory files and add: BC FIPS jar files as described above Custom keystore file - named for example keycloak-fips.keystore.bcfks Security file kc.java.security with added provider for SAML (Not needed with OpenJDK 21 or newer OpenJDK 17) Then create Containerfile in the current directory similar to this: Containerfile: FROM registry.redhat.io/rhbk/keycloak-rhel9:26 as builder ADD files /tmp/files/ WORKDIR /opt/keycloak RUN cp /tmp/files/*.jar /opt/keycloak/providers/ RUN cp /tmp/files/keycloak-fips.keystore.* /opt/keycloak/conf/server.keystore RUN cp /tmp/files/kc.java.security /opt/keycloak/conf/ RUN /opt/keycloak/bin/kc.sh build --features=fips --fips-mode=strict FROM registry.redhat.io/rhbk/keycloak-rhel9:26 COPY --from=builder /opt/keycloak/ /opt/keycloak/ ENTRYPOINT ["/opt/keycloak/bin/kc.sh"] Then build FIPS as an optimized Docker image and start it as described in the Running Red Hat build of Keycloak in a container . These steps require that you use arguments as described above when starting the image. 17.8. Migration from non-fips environment If you previously used Red Hat build of Keycloak in a non-fips environment, it is possible to migrate it to a FIPS environment including its data. However, restrictions and considerations exist as mentioned in sections, namely: Starting with Red Hat build of Keycloak 25, the default algorithm for password hashing is argon2 . However, this algorithm is not supported for FIPS 140-2. This means that if your users hashed their password with argon2 , they will not be able to login after switch to the FIPS environment. If you plan to migrate to the FIPS environment, consider setting the Password policy for your realm from the beginning (before any users are created) and override the default algorithm for example to pbkdf2-sha512 , which is FIPS compliant. This strategy helps to make the migration to the FIPS environment to be smooth. Otherwise, if your users are already on argon2 passwords, simply ask users to reset the password after migrating to the FIPS environment. For instance, ask users to use "Forget password" or send the email for reset-password to all users. Make sure all the Red Hat build of Keycloak functionality relying on keystores uses only supported keystore types. This differs based on whether strict or non-strict mode is used. Kerberos authentication may not work. If your authentication flow uses Kerberos authenticator, this authenticator will be automatically switched to DISABLED when migrated to FIPS environment. It is recommended to remove any Kerberos user storage providers from your realm and disable Kerberos related functionality in LDAP providers before switching to FIPS environment. In addition to the preceding requirements, be sure to doublecheck this before switching to FIPS strict mode: Make sure that all the Red Hat build of Keycloak functionality relying on keys (for example, realm or client keys) use RSA keys of at least 2048 bits Make sure that clients relying on Signed JWT with Client Secret use at least 14 characters long secrets (ideally generated secrets) Password length restriction as described earlier. In case your users have shorter passwords, be sure to start the server with the max padding length set to 14 of PBKDF2 provider as mentioned earlier. If you prefer to avoid this option, you can for instance ask all your users to reset their password (for example by the Forgot password link) during the first authentication in the new environment. 17.9. Red Hat build of Keycloak FIPS mode on the non-fips system Red Hat build of Keycloak is supported and tested on a FIPS enabled RHEL 8 system and ubi8 image. It is supported with RHEL 9 (and ubi9 image) as well. Running on the non-RHEL compatible platform or on the non-FIPS enabled platform, the FIPS compliance cannot be strictly guaranteed and cannot be officially supported. If you are still restricted to running Red Hat build of Keycloak on such a system, you can at least update your security providers configured in java.security file. This update does not amount to FIPS compliance, but at least the setup is closer to it. It can be done by providing a custom security file with only an overridden list of security providers as described earlier. For a list of recommended providers, see the OpenJDK 21 documentation . You can check the Red Hat build of Keycloak server log at startup to see if the correct security providers are used. TRACE logging should be enabled for crypto-related Red Hat build of Keycloak packages as described in the Keycloak startup command earlier.

Commands:
fips-mode-setup --check
fips-mode-setup --enable
keytool -genkeypair -sigalg SHA512withRSA -keyalg RSA -storepass passwordpassword -keystore USDKEYCLOAK_HOME/conf/server.keystore -alias localhost -dname CN=localhost -keypass passwordpassword
securerandom.strongAlgorithms=PKCS11:SunPKCS11-NSS-FIPS
keytool -keystore USDKEYCLOAK_HOME/conf/server.keystore -storetype bcfks -providername BCFIPS -providerclass org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider -provider org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider -providerpath USDKEYCLOAK_HOME/providers/bc-fips-*.jar -alias localhost -genkeypair -sigalg SHA512withRSA -keyalg RSA -storepass passwordpassword -dname CN=localhost -keypass passwordpassword -J-Djava.security.properties=/tmp/kc.keystore-create.java.security
bin/kc.[sh|bat] start --features=fips --hostname=localhost --https-key-store-password=passwordpassword --log-level=INFO,org.keycloak.common.crypto:TRACE,org.keycloak.crypto:TRACE
KC(BCFIPS version 2.0 Approved Mode, FIPS-JVM: enabled) version 1.0 - class org.keycloak.crypto.fips.KeycloakFipsSecurityProvider,
--spi-password-hashing-pbkdf2-sha512-max-padding-length=14
fips.provider.7=XMLDSig
-Djava.security.properties=/location/to/your/file/kc.java.security
cp USDKEYCLOAK_HOME/providers/bc-fips-*.jar USDKEYCLOAK_HOME/bin/client/lib/ cp USDKEYCLOAK_HOME/providers/bctls-fips-*.jar USDKEYCLOAK_HOME/bin/client/lib/ cp USDKEYCLOAK_HOME/providers/bcutil-fips-*.jar USDKEYCLOAK_HOME/bin/client/lib/
echo "keystore.type=bcfks fips.keystore.type=bcfks" > /tmp/kcadm.java.security export KC_OPTS="-Djava.security.properties=/tmp/kcadm.java.security"
FROM registry.redhat.io/rhbk/keycloak-rhel9:26 as builder ADD files /tmp/files/ WORKDIR /opt/keycloak RUN cp /tmp/files/*.jar /opt/keycloak/providers/ RUN cp /tmp/files/keycloak-fips.keystore.* /opt/keycloak/conf/server.keystore RUN cp /tmp/files/kc.java.security /opt/keycloak/conf/ RUN /opt/keycloak/bin/kc.sh build --features=fips --fips-mode=strict FROM registry.redhat.io/rhbk/keycloak-rhel9:26 COPY --from=builder /opt/keycloak/ /opt/keycloak/ ENTRYPOINT ["/opt/keycloak/bin/kc.sh"]