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:
- OpenSSL 1.0.1e
- OpenSSL FIPS Object Module 2.0 (with ECC support)
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)
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`
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.
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...
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....
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
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...
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.
These instructions are still valid for OpenSSL 1.0.1j and FIPS object module 2.0.8.