so I would like to know if adding the following code to
one of my cpp files is acceptable for FIPS validation
class FIPSInitializer
{
public:
FIPSInitializer()
{
FINGERPRINT_premain();
}
virtual ~FIPSInitializer()
{
}
};
Hmmm... this sounds odd. The only way to enter FIPS mode is though FIPS_mode_set
. If you call FIPS_mode_set
and it returns non-zero, then you are using validated cryptography. If you call FIPS_mode_set
and it fails, then you will still be able to encrypt and decrypt (think a "pluggable" architecture) but you will not be using validated cryptography. See FIPS mode set for details.
Just speculation: if FIPS_mode_set
fails and FINGERPRINT_premain
is not called, then you probably deviated from the procedures required by the OpenSSL FIPS 140-2 Security Policy.
fips_premain.c will do compiler specific solutions for gcc, cl(Microsoft),
cl(Microsoft), cc(SUN), and some others that I am not familiar with...
You do not compile fips_premain.c
. Its compiled when you build the FIPS Object Module or link against the the FIPS Object Module. There's even been talk about removing it altogether.
Anything other than below invalidates the FIPS build procedure, and you will not be using validated cryptography.
$ export OPENSSL_INSTALLDIR=/usr/local/ssl/darwin
$ cd openssl-fips-2.0.5/
$ ./config
$ make
$ sudo make install
The result of the above is fipscanister.o
and friends. You can find them (there's four of them) in $OPENSSL_INSTALLDIR\lib
:
$ ls /usr/local/ssl/darwin/lib/
fipscanister.o fips_premain.c
fipscanister.o.sha1 fips_premain.c.sha1
After you build and install the FIPS Object Module, you then build the FIPS Capable Library. You are free to turn knobs for the FIPS Capable Library, as long as it does not jeopardize the hallowed fipscanister.o
and friends.Note the use of fips
with config
.
$ cd openssl-1.0.1e/
$ ./config fips shared -no-ssl2 -no-ssl3 -no-comp -no-hw -no-engine \
--openssldir=$OPENSSL_INSTALLDIR \
--with-fipsdir=$OPENSSL_INSTALLDIR \
--with-fipslibdir=$OPENSSL_INSTALLDIR/lib/
$ make depend
$ make all
$ sudo -E make install
You have to use -E
because install
also builds components (shame on OpenSSL). During install, I believe the shared object will be linked against the hallowed fipscanister.o
. After linking, the modules signature will be embedded in the resulting executable by fipsld
. fipsld
is used by the OpenSSL build process, and internally calls a program called incore
. incore
writes the actual signature.
When it comes time to build your FIPS validated executable or shared object, you will perform the following:
$ export CC=`find $OPENSSL_INSTALLDIR -name fipsld`
$ echo $CC
/usr/local/ssl/darwin/bin/fipsld
$ export FIPSLD_CC=`find /usr/bin -iname gcc`
$ echo $FIPSLD_CC
/usr/bin/gcc
# Now build your project via make (or though the command line):
$ make
...
When your makefile invokes LD
, its really invoking OpenSSL's fipsld
. fipsld
will ensure your program links against fipspremain.o
, and internally calls a program called incore
. incore
writes the actual signature to your executable or shared object. The following is from openssl-fips-2.0.5
makefile:
fips_premain_dso$(EXE_EXT): fips_premain.c
$(CC) $(CFLAGS) -DFINGERPRINT_PREMAIN_DSO_LOAD -o $@ fips_premain.c \
$(FIPSLIBDIR)fipscanister.o ../libcrypto.a $(EX_LIBS)
If you don't have fipsld
installed, you can find it in, for example, openssl-fips-2.0.5
. Just copy it into $OPENSSL_INSTALLDIR\bin
. I don't recall if make install
copies it (and I seem to recall filing a bug report about it).
You cannot embed a signature in a static library. OpenSSL could not do it when it built libcrypto.a
, and you cannot do it when you build libmycoolness.a
. If you distribute libmycoolness.a
to your customers, they will have to jump through the CC
and FIPSLD_CC
hoops.
If you don't want to jump through the CC
and FIPSLD_CC
hoops, then you should link against fipscanister.o and run incore
manually after building you executable or shared object. The OpenSSL folks don't recommend this, however. They recommend using CC
and FIPSLD_CC
.
Note: you do not compile fips_premain.c
yourself.
If fips_premain.c
pukes an error when trying to build the FIPS Object Module, then your platform is not supported. You should contact Steve Marquess of the OpenSSL Foundation and schedule a talk about validating the platform. See OpenSSL and FIPS 140-2 and OpenSSL FIPS 140-2 Security Policy.
Related, if you are getting undefined symbols due to C++ name decoration, then check out Fipsld and C++
on the OpenSSL wiki.
The solution is to modify fipsld
. Its not a sequestered source, so you can modify it within reason. In this case, fipsld++
effectively performs the following when it compiles fips_premain.c
for you:
${CC} ${CANISTER_O_CMD:+"${CANISTER_O_CMD}"} \
-x c "${PREMAIN_C}" -x none \
${_WL_PREMAIN} "$@"
The change is effectivly the addition of the ${CC} -x c fips_premain.c -x none ...
when compiling fips_premain.c
.