Tuesday, December 17, 2013

Configure a FIPS 140-2 Compliant Java Provider on RedHat/CentOS/Fedora

If you're using any form of cryptography in Java, you might be aware of NIST FIPS 140-2, which lays out what you can and cannot use on federal information processing systems.

Oracle documentation, true to form, only gets you 80% of the way there.  Here's their technical notes on FIPS 140 compliance.

So here are the step-by-step instructions for configuring java with a FIPS-compliant Provider (SunPKCS11-NSS).

First, you need to install the libraries if you haven't already.  These are written by Mozilla, and have gone through NIST's Cryptographic Module Validation Program (CMVP).  Luckily, they're available for RedHat/CentOS/Fedora, and can be installed through yum.

sudo yum install nss-pkcs11-devel
 Next, you need to configure your JRE to add the provider.  You do this by editing ${jre.home}/lib/security/java.security and adding a reference to the SunPKCS11 provider.

On my Fedora 19 box, I have both the OpenJDK and SunJDK installed.  Here are the locations of their JREs on my box.

cd /usr/lib/jvm/java-1.7.0-openjdk-
sudo vim java.security
cd /usr/java/jdk1.7.0_15/jre/lib/security
sudo vim java.security
Be careful that you don't update one and then run your app on the other.  I just configured both and now I can run my apps on either.

Anyway, in the picture below, you'll notice that I've added:
security.provider.10=sun.security.pkcs11.SunPKCS11 ${java.home}/lib/security/nss.cfg

In the same directory, edit (or create if it isn't there) your nss.cfg:
sudo vim nss.cfg
The only change I had to make to this file was to set 'nssLibraryDirectory' to /usr/lib64, which is where your libnss3.so library was installed when you ran 'yum install' earlier.

Now, you may use the SunPKCS11-NSS provider in your Java applications, which is FIPS-compliant.  Here's a tiny app that creates a java.security.Signature for creating digital signatures.  It is configured to use the SHA256withRSA algorithm via the SunPKCS11-NSS provider.
 This program just loads the Signature instance - it doesn't do anything with it.  If the program runs without printing a stack trace, then you've successfully configured Java with a FIPS-compliant provider.

You can compile and run your program thus: