Building a FIPS capable OpenSSL (Gentoo)

2013-03-08 08:24 by Ian

This is an anecdotal account of building OpenSSL with the FIPS container module on Gentoo. However, these instructions should be applicable to any other distribution with minimal translation effort. The result will be a static OpenSSL build suitable for inclusion into secure application software (provided you follow the OpenSSL documentation).

The source for nearly all of this knowledge is the OpenSSL-UserGuide. It supersedes anything I might say on this page. The FIPS build criteria are strict, and you can fail them even if your library compiles and returns correct results for everything. One of the points emphasized in the user guide is that you must obtain and verify a physical copy of the source code shipped to you on a CD-ROM. So by following this guide, you are technically already sinning. :-) OpenSSL has given their doc a big shot in the arm recently, so it isn't nearly as painful as it used to be.

The versions of the relevant software follow:

Notes on ECC support in the FIPS canister:
Because of potential patent encumbrances, the OpenSSL devs release two versions of the canister. I am using the version the includes ECC.

My build-system's kernel specifications:

Linux coRTex 3.6.11-gentoo #1 SMP Mon Jan 28 23:44:41 MST 2013 x86_64 Intel(R) Atom(TM) CPU D525 @ 1.80GHz GenuineIntel GNU/Linux

gcc -v
Using built-in specs.
COLLECT_GCC=/usr/x86_64-pc-linux-gnu/gcc-bin/4.6.3/gcc
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-pc-linux-gnu/4.6.3/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: /var/tmp/portage/sys-devel/gcc-4.6.3/work/gcc-4.6.3/configure --prefix=/usr --bindir=/usr/x86_64-pc-linux-gnu/gcc-bin/4.6.3 --includedir=/usr/lib/gcc/x86_64-pc-linux-gnu/4.6.3/include --datadir=/usr/share/gcc-data/x86_64-pc-linux-gnu/4.6.3 --mandir=/usr/share/gcc-data/x86_64-pc-linux-gnu/4.6.3/man --infodir=/usr/share/gcc-data/x86_64-pc-linux-gnu/4.6.3/info --with-gxx-include-dir=/usr/lib/gcc/x86_64-pc-linux-gnu/4.6.3/include/g++-v4 --host=x86_64-pc-linux-gnu --build=x86_64-pc-linux-gnu --disable-altivec --disable-fixed-point --without-ppl --without-cloog --enable-lto --enable-nls --without-included-gettext --with-system-zlib --enable-obsolete --disable-werror --enable-secureplt --disable-multilib --enable-libmudflap --disable-libssp --enable-libgomp --with-python-dir=/share/gcc-data/x86_64-pc-linux-gnu/4.6.3/python --enable-checking=release --disable-libgcj --enable-libstdcxx-time --enable-languages=c,c++,fortran --enable-shared --enable-threads=posix --enable-__cxa_atexit --enable-clocale=gnu --enable-targets=all --with-bugurl=http://bugs.gentoo.org/ --with-pkgversion='Gentoo 4.6.3 p1.11, pie-0.5.2'
Thread model: posix
gcc version 4.6.3 (Gentoo 4.6.3 p1.11, pie-0.5.2)


Prep-Work

You may want to do whatever it is you do to bring your linux installation up-to-date and take a snapshot for backups. I use Mark Kolich's method for physical machines.

Create a working directory, get the source...

mkdir ~/openssl-fips; cd ~/openssl-fips
wget http://www.openssl.org/source/openssl-1.0.1e.tar.gz
wget http://www.openssl.org/source/openssl-fips-2.0.2.tar.gz

...SHA1 verify it (should return one result per command. If it returns nothing, the verification failed)...

sha1sum openssl-1.0.1e.tar.gz |grep `curl http://www.openssl.org/source/openssl-1.0.1e.tar.gz.sha1`
sha1sum openssl-fips-2.0.2.tar.gz |grep `curl http://www.openssl.org/source/openssl-fips-2.0.2.tar.gz.sha1`

...unpack...

tar zxvf openssl-fips-2.0.2.tar.gz
tar zxvf openssl-1.0.1e.tar.gz


Build FIPS Object Module:

Now enter the directory containing the FIPS Object source. We need to build and install this before we can do anything with OpenSSL.

cd openssl-fips*

There is a way to build the FIPS canister as a shared object, thereby allowing the creation of a shared OpenSSL with FIPS support. But this is expressly discouraged in the user guide, so I will be building static libraries.

Remember earlier, I mentioned the guide was strict? From the User's Guide...

Note that as a condition of the FIPS 140-2 validation no other user specified configuration options may be specified. This restriction means that an optional install prefix cannot be specified – however, there is no restriction on subsequent manual relocation of the generated files to the desired final location.

./config

You ought to be greeted by a response like this:

Configured for linux-x86_64.

WARNING: OpenSSL has been configured to generate a fipscanister.o object module.
That compiled module is NOT FIPS 140-2 validated or suitable for use in
satisfying a requirement for the use of FIPS 140-2 validated cryptography
UNLESS the requirements of the Security Policy are followed exactly (see
http://openssl.org/docs/fips/ or http://csrc.nist.gov/cryptval/).

This is the OpenSSL FIPS 2.0 module.

Also, notice the first lines of the config script's output. FIPS disables certain algorithms on purpose. So don't kill yourself trying to figure out why any manual ./config arguments to OpenSSL aren't working as expected later on.

Away we go....

make -j3

This will spin for a short while. If it finishes successfully, then you have built the FIPS Object Module. We ought to copy some header files to a place where the OpenSSL build will be able to use them...

cp fips/*.h ../openssl-1.0.1e/include/openssl/
cp fips/rand/*.h ../openssl-1.0.1e/include/openssl/

There are also a few binaries that we need to use in the next steps, but are not present. Under normal circumstances, we might simply alter the makefile. But this would break from the procedure. So we fake it...

sudo mkdir -p /usr/local/ssl/fips-2.0/bin
sudo cp fips/fipsld /usr/local/ssl/fips-2.0/bin/
sudo ln -s `which openssl` /usr/local/ssl/fips-2.0/bin/openssl


Build OpenSSL:

Now back out of the FIPS directory and enter the OpenSSL source tree.

cd ..; cd openssl-1.0.1*
./config fips no-shared --with-fipslibdir=~/openssl/openssl-fips-2.0.2/fips/
make depend
make -j3

As previously mentioned, we are only building a static library, for reasons pertaining to security as well as system integrity. This means that any software that you build with FIPS capability must include its own private copy of this static library. If you've come this far, you ought to have these files...

libcrypto.a 
libssl.a

If you wanted to, you could "make install" and the expected thing will happen. Since I don't want portage to complain about out-of-band software (or worse, build against it), I am not actually going to install the built OpenSSL. When I want to compile against this version of OpenSSL, I will reference the build directory directly. By keeping my include files and static libraries away from those for the rest of my system, I am avoiding breaking things like SSH. This is especially important for those of you using a binary distro of some stripe (CentOS, Ubuntu, etc).

Clean up your mess and hang onto the binaries and include files. You will need both in order to incorporate this work into your own. I am going to leave the fipsld binary and the link to openssl where I created them. They might come in handy later.

cd ~/openssl
mkdir `date +%Y-%m-%d.%s`
mv openssl-1.0.1e `date +%Y-%m-%d`*
mv openssl-fips-2.0.2 `date +%Y-%m-%d`*

The next entry will cover building a test program using these libraries.

NOTE 2014.11.11
These instructions are still valid for OpenSSL 1.0.1j and FIPS object module 2.0.8.

Previous:
Next: