Add FIPS Module to OpenSSL 3.0.11 on Debian 12 Bookworm
I had a task to create a container image based on Debian 12 (Bookworm) which had the OpenSSL FIPS 140-2 module. By default, OpenSSL version 3.0.11 (current version on Debian 12 as of writing) does not have the FIPS module built in it. OpenSSL 3.0 requires that the module be built from the version that has a valid FIPS certificate, which was 3.0.9 at the time of writing.
A few things required to get this done,
- OpenSSL 3.0 installed from deb package
- Locally built OpenSSL 3.0.9 from source code
- Modified openssl.cnf to enable FIPS mode
- Set environment variable OPENSSL_CONF
OpenSSL 3.0 installed from deb package
$ apt update && apt install --no-install-recommends --no-install-suggests -y openssl
Locally built OpenSSL 3.0.9 from source code
These steps are simplified specific version of the process provided in Need steps to compile openssl-debian-openssl-3.0.11-1_deb12u2 with FIPS complaint openssl-3.0.8.
We build everything but only install the FIPS module.
$ curl -O https://www.openssl.org/source/old/3.0/openssl-3.0.9.tar.gz $ tar xvzf openssl-3.0.9.tar.gz $ cd openssl-3.0.9 $ ./Configure enable-fips --prefix=usr --openssldir=/usr/lib/ssl --libdir=lib/x86_64-linux-gnu $ make $ sudo make install_fips
Modified openssl.cnf to enable FIPS mode
$ sudo cp /usr/lib/ssl/fipsmodule.cnf /etc/ssl/fipsmodule.cnf
Create /etc/ssl/openssl-fips.cnf which will enable the FIPS module. It is a modified copy of the stock /etc/ssl/openssl.cnf file that comes with the openssl deb package.
$ sed \ -e '51d' \ -e '52i ##' \ -e '52i ## https://www.openssl.org/docs/manmaster/man7/fips_module.html' \ -e '52i ##' \ -e '52i .include /etc/ssl/fipsmodule.cnf' \ -e '54d' \ -e '55i providers = provider_sect' \ -e '55i alg_section = algorithm_sect' \ -e '57d' \ -e '58d' \ -e '59i [provider_sect]' \ -e '59i default = default_sect' \ -e '59i \\n' \ -e '61d' \ -e '62i fips = fips_sect' \ -e '71d' \ -e '72d' \ -e '73i [default_sect]' \ -e '73i activate = 1' \ -e '73i [algorithm_sect]' \ -e '73i default_properties = fips=yes' \ -e '73i \\n' \ /etc/ssl/openssl.cnf | sudo tee /etc/ssl/openssl-fips.cnf
In the sed
command above, we are inserting lines in specific places and
removing specific lines. This is specific to the openssl deb package version
3.0.11-1 and may not work for other versions. This result could be achieved by
regex search and replace as well but that is left up to you.
Set environment variable OPENSSL_CONF
openssl
uses environment variable OPENSSL_CONF to set the default
configuration file. By default this variable is not set and in Debian the
default file is /etc/ssl/openssl.cnf.
To switch to the FIPS config file we created above, set the environment variable,
$ export OPENSSL_CONF=/etc/ssl/openssl-fips.cnf
Verify FIPS is enabled
Check md5
MD5 will work when FIPS is not enabled,
$ openssl md5 /dev/null MD5(/dev/null)= d41d8cd98f00b204e9800998ecf8427e
MD5 will not work when FIPS is enabled,
$ openssl md5 /dev/null Error setting digest
Check supported ciphers
CHACHA20_POLY1305 is not supported in FIPS module. If it is present, openssl is not using FIPS.
For example, in the output below we see CHACHA20_POLY1305 is present, thus FIPS is not enabled,
$ openssl ciphers | tr ':' '\n' | sort AES128-GCM-SHA256 AES128-SHA AES128-SHA256 AES256-GCM-SHA384 AES256-SHA AES256-SHA256 DHE-PSK-AES128-CBC-SHA DHE-PSK-AES128-CBC-SHA256 DHE-PSK-AES128-GCM-SHA256 DHE-PSK-AES256-CBC-SHA DHE-PSK-AES256-CBC-SHA384 DHE-PSK-AES256-GCM-SHA384 DHE-PSK-CHACHA20-POLY1305 DHE-RSA-AES128-GCM-SHA256 DHE-RSA-AES128-SHA DHE-RSA-AES128-SHA256 DHE-RSA-AES256-GCM-SHA384 DHE-RSA-AES256-SHA DHE-RSA-AES256-SHA256 DHE-RSA-CHACHA20-POLY1305 ECDHE-ECDSA-AES128-GCM-SHA256 ECDHE-ECDSA-AES128-SHA ECDHE-ECDSA-AES128-SHA256 ECDHE-ECDSA-AES256-GCM-SHA384 ECDHE-ECDSA-AES256-SHA ECDHE-ECDSA-AES256-SHA384 ECDHE-ECDSA-CHACHA20-POLY1305 ECDHE-PSK-AES128-CBC-SHA ECDHE-PSK-AES128-CBC-SHA256 ECDHE-PSK-AES256-CBC-SHA ECDHE-PSK-AES256-CBC-SHA384 ECDHE-PSK-CHACHA20-POLY1305 ECDHE-RSA-AES128-GCM-SHA256 ECDHE-RSA-AES128-SHA ECDHE-RSA-AES128-SHA256 ECDHE-RSA-AES256-GCM-SHA384 ECDHE-RSA-AES256-SHA ECDHE-RSA-AES256-SHA384 ECDHE-RSA-CHACHA20-POLY1305 PSK-AES128-CBC-SHA PSK-AES128-CBC-SHA256 PSK-AES128-GCM-SHA256 PSK-AES256-CBC-SHA PSK-AES256-CBC-SHA384 PSK-AES256-GCM-SHA384 PSK-CHACHA20-POLY1305 RSA-PSK-AES128-CBC-SHA RSA-PSK-AES128-CBC-SHA256 RSA-PSK-AES128-GCM-SHA256 RSA-PSK-AES256-CBC-SHA RSA-PSK-AES256-CBC-SHA384 RSA-PSK-AES256-GCM-SHA384 RSA-PSK-CHACHA20-POLY1305 SRP-AES-128-CBC-SHA SRP-AES-256-CBC-SHA SRP-RSA-AES-128-CBC-SHA SRP-RSA-AES-256-CBC-SHA TLS_AES_128_GCM_SHA256 TLS_AES_256_GCM_SHA384 TLS_CHACHA20_POLY1305_SHA256
In the output below CHACHA20_POLY1305 is not present, thus FIPS is enabled,
$ openssl ciphers | tr ':' '\n' | sort AES128-GCM-SHA256 AES128-SHA AES128-SHA256 AES256-GCM-SHA384 AES256-SHA AES256-SHA256 DHE-PSK-AES128-CBC-SHA DHE-PSK-AES128-CBC-SHA256 DHE-PSK-AES128-GCM-SHA256 DHE-PSK-AES256-CBC-SHA DHE-PSK-AES256-CBC-SHA384 DHE-PSK-AES256-GCM-SHA384 DHE-RSA-AES128-GCM-SHA256 DHE-RSA-AES128-SHA DHE-RSA-AES128-SHA256 DHE-RSA-AES256-GCM-SHA384 DHE-RSA-AES256-SHA DHE-RSA-AES256-SHA256 ECDHE-ECDSA-AES128-GCM-SHA256 ECDHE-ECDSA-AES128-SHA ECDHE-ECDSA-AES128-SHA256 ECDHE-ECDSA-AES256-GCM-SHA384 ECDHE-ECDSA-AES256-SHA ECDHE-ECDSA-AES256-SHA384 ECDHE-PSK-AES128-CBC-SHA ECDHE-PSK-AES128-CBC-SHA256 ECDHE-PSK-AES256-CBC-SHA ECDHE-PSK-AES256-CBC-SHA384 ECDHE-RSA-AES128-GCM-SHA256 ECDHE-RSA-AES128-SHA ECDHE-RSA-AES128-SHA256 ECDHE-RSA-AES256-GCM-SHA384 ECDHE-RSA-AES256-SHA ECDHE-RSA-AES256-SHA384 PSK-AES128-CBC-SHA PSK-AES128-CBC-SHA256 PSK-AES128-GCM-SHA256 PSK-AES256-CBC-SHA PSK-AES256-CBC-SHA384 PSK-AES256-GCM-SHA384 RSA-PSK-AES128-CBC-SHA RSA-PSK-AES128-CBC-SHA256 RSA-PSK-AES128-GCM-SHA256 RSA-PSK-AES256-CBC-SHA RSA-PSK-AES256-CBC-SHA384 RSA-PSK-AES256-GCM-SHA384 SRP-AES-128-CBC-SHA SRP-AES-256-CBC-SHA SRP-RSA-AES-128-CBC-SHA SRP-RSA-AES-256-CBC-SHA TLS_AES_128_GCM_SHA256 TLS_AES_256_GCM_SHA384
Verify https ciphers
If you have configured a web server with TLS, for example nginx, you can also verify the ciphers it supports. If CHACHA20_POLY1305 is not present then FIPS is enabled.
In our example below, google.com has not enabled FIPS so we see CHACHA20_POLY1305.
$ nmap --script ssl-enum-ciphers -p 443 google.com Starting Nmap 7.95 ( https://nmap.org ) at 2024-05-07 18:26 PDT Nmap scan report for google.com (142.250.217.78) Host is up (0.013s latency). Other addresses for google.com (not scanned): 2607:f8b0:400a:80a::200e rDNS record for 142.250.217.78: sea09s29-in-f14.1e100.net PORT STATE SERVICE 443/tcp open https | ssl-enum-ciphers: | TLSv1.0: | ciphers: | TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (ecdh_x25519) - A | TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA (ecdh_x25519) - A | TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (ecdh_x25519) - A | TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (ecdh_x25519) - A | TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A | TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A | TLS_RSA_WITH_3DES_EDE_CBC_SHA (rsa 2048) - C | compressors: | NULL | cipher preference: server | warnings: | 64-bit block cipher 3DES vulnerable to SWEET32 attack | TLSv1.1: | ciphers: | TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (ecdh_x25519) - A | TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA (ecdh_x25519) - A | TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (ecdh_x25519) - A | TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (ecdh_x25519) - A | TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A | TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A | TLS_RSA_WITH_3DES_EDE_CBC_SHA (rsa 2048) - C | compressors: | NULL | cipher preference: server | warnings: | 64-bit block cipher 3DES vulnerable to SWEET32 attack | TLSv1.2: | ciphers: | TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (ecdh_x25519) - A | TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 (ecdh_x25519) - A | TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA (ecdh_x25519) - A | TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 (ecdh_x25519) - A | TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 (ecdh_x25519) - A | TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (ecdh_x25519) - A | TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (ecdh_x25519) - A | TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (ecdh_x25519) - A | TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (ecdh_x25519) - A | TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (ecdh_x25519) - A | TLS_RSA_WITH_3DES_EDE_CBC_SHA (rsa 2048) - C | TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A | TLS_RSA_WITH_AES_128_GCM_SHA256 (rsa 2048) - A | TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A | TLS_RSA_WITH_AES_256_GCM_SHA384 (rsa 2048) - A | compressors: | NULL | cipher preference: client | warnings: | 64-bit block cipher 3DES vulnerable to SWEET32 attack | TLSv1.3: | ciphers: | TLS_AKE_WITH_AES_128_GCM_SHA256 (ecdh_x25519) - A | TLS_AKE_WITH_AES_256_GCM_SHA384 (ecdh_x25519) - A | TLS_AKE_WITH_CHACHA20_POLY1305_SHA256 (ecdh_x25519) - A | cipher preference: client |_ least strength: C Nmap done: 1 IP address (1 host up) scanned in 1.62 seconds