3

I am trying to use a statically link OpenSSL in FIPS mode on IBM PLinux using xlC_r as the compiler/linker. This combination is not supported by fipsld or fips_premain.c. fipld will add linker options to call FINGERPRINT_premain on uname -s in {OSF1, IRIX, HP-UX, AIX, Darwin}, fips_premain.c will do compiler specific solutions for gcc, cl(Microsoft), cc(SUN), and some others that I am not familiar with. Unfortunately xlC_r on IBM PLinux is not covered by either of those so I would like to know if adding the following code to one of my cpp files is acceptable for FIPS validation or if I need to change my compiler/linker to gcc or is there another way(linker options?) to keep xlC_r. Please include some justification.

#if defined(PREMAIN_NOT_COVERED)
extern "C" void FINGERPRINT_premain(void);

class FIPSInitializer
{
public:
    FIPSInitializer()
    {
        FINGERPRINT_premain();
    }
    virtual ~FIPSInitializer()
    {
    }
};
extern FIPSInitializer fips_initializer;
FIPSInitializer fips_initializer;
#endif

I also tried using -Wl,init,FINGERPRINT_premain while linking, but then our test would segfault while using our shared library.

OpenSSL User Guide: http://www.openssl.org/docs/fips/UserGuide-1.1.1.pdf

OpenSSL Security Policy: http://www.openssl.org/docs/fips/SecurityPolicy-2.0.pdf

TylerEli
  • 31
  • 4

1 Answers1

2

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.

jww
  • 97,681
  • 90
  • 411
  • 885
  • It looks like you are saying I need to use gcc to compile my_library_with_static_140_2_openssl.so. Could you provide a link to a FIPS or OpenSSL document that says this? I know using gcc would work, but I can not use that as a reason to switch our compiler. – TylerEli Dec 02 '13 at 16:00
  • Tyler - my bad. You don't need to use GCC to compile your library. That's an area where you are allowed to turn knobs. (I would have to talk to Steve Marquess *if* the question was "do I have to compile OpenSSL FIPS Object Module with GCC". That question falls into the grey area of "what's a platform" in the context of FIPS 140-2 and software modules). – jww Dec 02 '13 at 20:02