Ubuntu FIPS builds erronenously return false for OpenSSL.fips_mode
I noticed in another issue after installing the latest nightly FIPS build that OpenSSL.fips_mode
was false
on an Ubuntu 18.04 FIPS AMI:
ubuntu@fips-test-gitaly-1:/opt/gitlab/embedded/service/gitlab-rails$ sudo ua status
SERVICE ENTITLED STATUS DESCRIPTION
cis yes disabled Center for Internet Security Audit Tools
esm-apps yes enabled UA Apps: Extended Security Maintenance (ESM)
esm-infra yes enabled UA Infra: Extended Security Maintenance (ESM)
fips yes enabled NIST-certified core packages
fips-updates yes disabled NIST-certified core packages with priority security updates
livepatch yes n/a Canonical Livepatch service
Enable services with: ua enable <service>
Account: 312968203986
Subscription: 312968203986
Valid until: 9999-12-31 00:00:00
Technical support level: essential
ubuntu@fips-test-gitaly-1:/opt/gitlab/embedded/service/gitlab-rails$ dpkg -l | grep gitlab-ee
ii gitlab-ee 14.9.2+rnightly.fips.233268.406a4c33-0 amd64 GitLab Enterprise Edition (including NGINX, Postgres, Redis)
ubuntu@fips-test-gitaly-1:/opt/gitlab/embedded/service/gitlab-rails$ /opt/gitlab/embedded/bin/bundle exec /opt/gitlab/embedded/bin/irb
irb(main):001:0> require 'openssl'
=> true
irb(main):002:0> OpenSSL.fips_mode
=> false
https://stackoverflow.com/a/54207092/1992201 has a test C file that shows that fips_mode
should be true
(apt install libssl-dev
needed for headers):
ubuntu@fips-test-gitaly-1:/tmp$ ./a.out
Installed library has FIPS support
Note on a RHEL 8 FIPS build, OpenSSL.fips_mode
is true
as it should be.
What's going on here? Looking at the ldd
output, this seems correct:
ubuntu@fips-test-gitaly-1:/$ ldd /opt/gitlab/embedded/lib/ruby/gems/2.7.0/gems/openssl-2.2.0/lib/openssl.so
linux-vdso.so.1 (0x00007ffc18dd2000)
libruby.so.2.7 => /opt/gitlab/embedded/lib/libruby.so.2.7 (0x00007fdd897a3000)
libssl.so.1.1 => /usr/lib/x86_64-linux-gnu/libssl.so.1.1 (0x00007fdd89515000)
libcrypto.so.1.1 => /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1 (0x00007fdd8903d000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fdd88c4c000)
libz.so.1 => /opt/gitlab/embedded/lib/libz.so.1 (0x00007fdd88a2d000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fdd8880e000)
librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007fdd88606000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fdd88402000)
libcrypt.so.1 => /lib/x86_64-linux-gnu/libcrypt.so.1 (0x00007fdd881ca000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fdd87e2c000)
/lib64/ld-linux-x86-64.so.2 (0x00007fdd89fcc000)
You can see that the library is indeed in FIPS mode:
irb(main):014:0> OpenSSL::Digest::MD5.digest('hi')
Traceback (most recent call last):
16: from /opt/gitlab/embedded/lib/ruby/gems/2.7.0/gems/bundler-2.2.33/lib/bundler/vendor/thor/lib/thor.rb:392:in `dispatch'
15: from /opt/gitlab/embedded/lib/ruby/gems/2.7.0/gems/bundler-2.2.33/lib/bundler/vendor/thor/lib/thor/invocation.rb:127:in `invoke_command'
14: from /opt/gitlab/embedded/lib/ruby/gems/2.7.0/gems/bundler-2.2.33/lib/bundler/vendor/thor/lib/thor/command.rb:27:in `run'
13: from /opt/gitlab/embedded/lib/ruby/gems/2.7.0/gems/bundler-2.2.33/lib/bundler/cli.rb:479:in `exec'
12: from /opt/gitlab/embedded/lib/ruby/gems/2.7.0/gems/bundler-2.2.33/lib/bundler/cli/exec.rb:23:in `run'
11: from /opt/gitlab/embedded/lib/ruby/gems/2.7.0/gems/bundler-2.2.33/lib/bundler/cli/exec.rb:58:in `kernel_load'
10: from /opt/gitlab/embedded/lib/ruby/gems/2.7.0/gems/bundler-2.2.33/lib/bundler/cli/exec.rb:58:in `load'
9: from /opt/gitlab/embedded/bin/irb:23:in `<top (required)>'
8: from /opt/gitlab/embedded/bin/irb:23:in `load'
7: from /opt/gitlab/embedded/lib/ruby/gems/2.7.0/gems/irb-1.2.6/exe/irb:11:in `<top (required)>'
6: from (irb):13
5: from (irb):14:in `rescue in irb_binding'
4: from /opt/gitlab/embedded/lib/ruby/gems/2.7.0/gems/openssl-2.2.0/lib/openssl/digest.rb:41:in `block (3 levels) in <class:Digest>'
3: from /opt/gitlab/embedded/lib/ruby/gems/2.7.0/gems/openssl-2.2.0/lib/openssl/digest.rb:41:in `new'
2: from /opt/gitlab/embedded/lib/ruby/gems/2.7.0/gems/openssl-2.2.0/lib/openssl/digest.rb:35:in `block (3 levels) in <class:Digest>'
1: from /opt/gitlab/embedded/lib/ruby/gems/2.7.0/gems/openssl-2.2.0/lib/openssl/digest.rb:35:in `initialize'
OpenSSL::Digest::DigestError (Digest initialization failed: disabled for FIPS)
I think this is just a quirk with the Ruby build that it expects OPENSSL_FIPS
to be defined at compile-time: https://github.com/ruby/ruby/blob/7b6fde4258e700c0e0292bb091aa84a5e473342e/ext/openssl/ossl.c#L433-L448. This seems a bit silly because fips_mode
should be detected dynamically via FIPS_mode()
, although that might not be the case for OpenSSL 3.
We may just need to define OPENSSL_FIPS
when compiling Ruby.