Saturday, October 16. 2021
OpenSSL3 FIPS for wildfly?


Today's entry is going to continue with wildfly and the security standard FIPS. The previous entry was about configuring the application server with the bouncy castle FIPS implementation. But this time the (in)famous openssl library will be used instead. Until now the openssl FIPS was a separate module that only worked with version 1.0.2, but the recent release of version 3.0.0 introduces the idea of crypto providers, and a new FIPS provider is now included by default. On the other side wildfly can be configured to use openssl instead of the native JSSE implementation. The projects wildfly-openssl and wildfly-openssl-natives wrap the C library in order to transform it into a Java SSL engine. So, with both ideas in place, there is a new easy option to configure FIPS inside wildfly.
Nevertheless the previous statement is not right or, better said, it is not right yet. There are mainly two snags:
The wildfly projects should be modified to make the server work with the new openssl version 3. Hopefully the enhancement will be managed by issues WFSSL-80 and SSLNTV-13.
The new openssl3 FIPS implementation is still not validated by the NIST. Currently the request is submitted for review and it is expected to take several months.
So today's entry is going to configure a FIPS setup for wildfly which is still not ready. But, once the previous two points are fixed, the combination of openssl and wildfly will be FIPS compliant. In my humble opinion that setup can be very useful. The rest of the entry is going to describe step by step how to perform that configuration.
Download, compile and install the openssl. Nowadays the last version 3.0.0 is still not included by default in any common linux distribution. So the bundle will be compiled manually with the FIPS provider enabled.
wget https://www.openssl.org/source/openssl-3.0.0.tar.gz tar zxvf openssl-3.0.0.tar.gz cd openssl-3.0.0/ ./Configure enable-fips --prefix=/path/to/openssl-3.0.0 make make test make install
Modify the configuration file openssl.cnf following the FIPS documentation presented before.
diff -Naur openssl.cnf.ORIG openssl.cnf --- openssl.cnf.ORIG 2021-10-09 19:32:01.537655962 +0200 +++ openssl.cnf 2021-10-09 19:44:20.252969136 +0200 @@ -48,17 +48,18 @@ # fips provider. It contains a named section e.g. [fips_sect] which is # referenced from the [provider_sect] below. # Refer to the OpenSSL security policy for more information. -# .include fipsmodule.cnf +.include /path/to/openssl-3.0.0/ssl/fipsmodule.cnf [openssl_init] providers = provider_sect # List of providers to load [provider_sect] -default = default_sect +#default = default_sect # The fips section name should match the section name inside the # included fipsmodule.cnf. -# fips = fips_sect +fips = fips_sect +base = base_sect # If no providers are activated explicitly, the default one is activated implicitly. # See man 7 OSSL_PROVIDER-default for more details. @@ -71,6 +72,8 @@ [default_sect] # activate = 1 +[base_sect] +activate = 1 #################################################################### [ ca ]
FIPS is enabled globally for the library. The idea is that the default provider is commented out and the new FIPS one is added as the only activated algorithm provider (from now on all the applications will use FIPS compulsorily). For example if the ciphers command is executed for TLSv1.3 only the two FIPS compliant ciphers are displayed (TLS_CHACHA20_POLY1305_SHA256 is also available in the out of the box configuration but not listed when FIPS is enforced).
./openssl ciphers -s -v -tls1_3 TLS_AES_256_GCM_SHA384 TLSv1.3 Kx=any Au=any Enc=AESGCM(256) Mac=AEAD TLS_AES_128_GCM_SHA256 TLSv1.3 Kx=any Au=any Enc=AESGCM(128) Mac=AEAD
Time for the wildfly installation. Today this point is not going to be detailed because a development version of the project is necessary. As commented before both wildfly-openssl projects need modifications in order to work with openssl version 3. So for the entry a compiled version of wildfly is used with both modules upgraded with the fixes incorporated.
unzip wildfly-26.0.0.Beta1-SNAPSHOT.zip cd wildfly-26.0.0.Beta1-SNAPSHOT/bin/ ./add-user.sh -u admin -p admin
Generate a RSA key to be used by the server.
keytool -genkeypair -alias localhost -keyalg RSA -keysize 2048 -validity 365 -keystore ../standalone/configuration/keystore.p12 -storetype pkcs12 -dname "CN=localhost" -storepass password -ext san=dns:localhost,ip:127.0.0.1
Start the server using a JDK version 11 and pointing to the compiled openssl3 libraries to not use the default system ones.
export JAVA_HOME=/usr/lib/jvm/java-11 ./standalone.sh -Dorg.wildfly.openssl.path.ssl=/path/to/openssl-3.0.0/lib64/libssl.so -Dorg.wildfly.openssl.path.crypto=/path/to/openssl-3.0.0/lib64/libcrypto.so
Finally configure the security subsystem to use openssl and the RSA certificate just created. Note that in order to make TLSv1.3 available the option cipher-suite-names should be set with the wanted values (in our case the two complaint ciphers listed before).
/subsystem=elytron/key-store=sslKS:add(path=keystore.p12, type=PKCS12, relative-to=jboss.server.config.dir, credential-reference={clear-text=password}) /subsystem=elytron/key-manager=sslKM:add(key-store=sslKS, algorithm="PKIX", credential-reference={clear-text=password}) /subsystem=elytron/server-ssl-context=sslSSC:add(providers=openssl, key-manager=sslKM, protocols=[TLSv1.2, TLSv1.3], cipher-suite-names=TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256) /subsystem=undertow/server=default-server/https-listener=https:write-attribute(name=ssl-context, value=sslSSC) reload
And that is all. Now the boot messages should contain the following line saying that the version 3.0.0 of openssl is used.
17:19:09,633 INFO [org.wildfly.openssl.SSL] (MSC service thread 1-5) WFOPENSSL0002 OpenSSL Version OpenSSL 3.0.0 7 sep 2021
Using curl the TLS_AES_256_GCM_SHA384 cipher is selected for TLSv1.3:
curl -k -v -I https://localhost:8443/ * Trying 127.0.0.1:8443... * Connected to localhost (127.0.0.1) port 8443 (#0) * ALPN, offering h2 * ALPN, offering http/1.1 * successfully set certificate verify locations: * CAfile: /etc/pki/tls/certs/ca-bundle.crt * CApath: none * TLSv1.3 (OUT), TLS handshake, Client hello (1): * TLSv1.3 (IN), TLS handshake, Server hello (2): * TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8): * TLSv1.3 (IN), TLS handshake, Certificate (11): * TLSv1.3 (IN), TLS handshake, CERT verify (15): * TLSv1.3 (IN), TLS handshake, Finished (20): * TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1): * TLSv1.3 (OUT), TLS handshake, Finished (20): * SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384 * ALPN, server accepted to use h2 * Server certificate: * subject: CN=localhost * start date: Oct 10 11:08:18 2021 GMT * expire date: Oct 10 11:08:18 2022 GMT * issuer: CN=localhost * SSL certificate verify result: self signed certificate (18), continuing anyway. * Using HTTP2, server supports multi-use * Connection state changed (HTTP/2 confirmed) * Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0 * Using Stream ID: 1 (easy handle 0x55b4e9f48c30) > HEAD / HTTP/2 > Host: localhost:8443 > user-agent: curl/7.76.1 > accept: */* > * TLSv1.3 (IN), TLS handshake, Newsession Ticket (4): * TLSv1.3 (IN), TLS handshake, Newsession Ticket (4): * old SSL session ID is stale, removing * Connection state changed (MAX_CONCURRENT_STREAMS == 4294967295)! < HTTP/2 200 HTTP/2 200 < last-modified: Sun, 10 Oct 2021 10:32:16 GMT last-modified: Sun, 10 Oct 2021 10:32:16 GMT < content-length: 1504 content-length: 1504 < content-type: text/html content-type: text/html < accept-ranges: bytes accept-ranges: bytes < date: Wed, 13 Oct 2021 15:21:27 GMT date: Wed, 13 Oct 2021 15:21:27 GMT
And forcing TLSv1.2 the cipher ECDHE-RSA-AES256-GCM-SHA384 is used:
curl -k -v -I --tls-max 1.2 https://localhost:8443/ * Trying 127.0.0.1:8443... * Connected to localhost (127.0.0.1) port 8443 (#0) * ALPN, offering h2 * ALPN, offering http/1.1 * successfully set certificate verify locations: * CAfile: /etc/pki/tls/certs/ca-bundle.crt * CApath: none * TLSv1.2 (OUT), TLS handshake, Client hello (1): * TLSv1.2 (IN), TLS handshake, Server hello (2): * TLSv1.2 (IN), TLS handshake, Certificate (11): * TLSv1.2 (IN), TLS handshake, Server key exchange (12): * TLSv1.2 (IN), TLS handshake, Server finished (14): * TLSv1.2 (OUT), TLS handshake, Client key exchange (16): * TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1): * TLSv1.2 (OUT), TLS handshake, Finished (20): * TLSv1.2 (IN), TLS handshake, Finished (20): * SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384 * ALPN, server accepted to use h2 * Server certificate: * subject: CN=localhost * start date: Oct 10 11:08:18 2021 GMT * expire date: Oct 10 11:08:18 2022 GMT * issuer: CN=localhost * SSL certificate verify result: self signed certificate (18), continuing anyway. * Using HTTP2, server supports multi-use * Connection state changed (HTTP/2 confirmed) * Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0 * Using Stream ID: 1 (easy handle 0x558282f4dc30) > HEAD / HTTP/2 > Host: localhost:8443 > user-agent: curl/7.76.1 > accept: */* > * Connection state changed (MAX_CONCURRENT_STREAMS == 4294967295)! < HTTP/2 200 HTTP/2 200 < last-modified: Sun, 10 Oct 2021 10:32:16 GMT last-modified: Sun, 10 Oct 2021 10:32:16 GMT < content-length: 1504 content-length: 1504 < content-type: text/html content-type: text/html < accept-ranges: bytes accept-ranges: bytes < date: Wed, 13 Oct 2021 15:22:55 GMT date: Wed, 13 Oct 2021 15:22:55 GMT
The current entry is just an advance of a new SSL FIPS configuration that will be available in wildfly. The idea is using the new openssl3 configured in FIPS mode as the provider for the elytron context. The setup is not ready at this moment, some PRs should be merged for wildfly and the openssl3 is not a certified FIPS implementation yet. If everything goes as expected the setup will be ready in some months.
FIPS regards!
Comments