I’m having an issue trying to use the OpenSSL shared library (libcrypto) compiled to be FIPS capable on a MIPS device.
I cross-compiled the FIPS Object Module and then the OpenSSL library in the following way (summarizing):
export FIPS_SIG=<my_path>/incore ./config fips --with-fipsdir=<my_path>/fips-2.0 make depend make make install
I did all the needed steps, so I’m able to compile and install the library.
The issue appears when I try to run the FIPS_mod_set(1)
API from an application linking the OpenSSL library.
The FIPS mode initialization fails receiving this error:
2010346568:error:2D06B06F:lib(45):func(107):reason(111):NA:0:
Debugging the FIPS code, I found that the issue is inside the FIPS_check_incore_fingerprint(void)
function:
the check memcmp(FIPS_signature,sig,sizeof(FIPS_signature))
fails.
Going deeper in the debug I discovered that the FIPS_signature value remains the default one, so I have the doubt that the incore script, called by the fipsld utility, is not embedding properly the fingerprint inside the OpenSSL shared object.
How can I check if the incore script embedded the fingerprint inside the shared object?
How can I print the expected fingerprint?
Do I need to adapt the incore script? (I suppose it’s not allowed)
Do you have any suggestion?
Thanks a lot!
P.S.: I’m cross-compiling using an x86 Linux machine.
Advertisement
Answer
I found the issue! I’ll try to explain the whole debugging process and the solution.
INTRODUCTION:
When OpenSSL is configured to be FIPS capable, during the compilation the Makefile calls a utility, fipsld, which both performs the check of the FIPS
Object Module and generates the new HMAC-SHA-1 digest for the application executable (as explained in the official OpenSSL user guide https://www.openssl.org/docs/fips/UserGuide-2.0.pdf)
The fipsld command requires that the CC and FIPSLD_CC environment variables be set,
with the latter taking precedence.
In the Makefile you will find something like this:
libcrypto$(SHLIB_EXT): libcrypto.a fips_premain_dso$(EXE_EXT) @if [ "$(SHLIB_TARGET)" != "" ]; then if [ "$(FIPSCANLIB)" = "libcrypto" ]; then FIPSLD_LIBCRYPTO=libcrypto.a ; FIPSLD_CC="$(CC)"; CC=$(FIPSDIR)/bin/fipsld; export CC FIPSLD_CC FIPSLD_LIBCRYPTO; fi; $(MAKE) -e SHLIBDIRS=crypto CC="$${CC:-$(CC)}" build-shared && (touch -c fips_premain_dso$(EXE_EXT) || :); else echo "There's no support for shared libraries on this platform" >&2; exit 1; fi
Then, the fipsld utility invokes a shell script, incore, used to embed the FIPS Object Module’s expected fingerprint in the OpenSSL shared object. It’s important to specify the incore path via FIPS_SIG env variable, e.g.:
export FIPS_SIG=$PWD/opensslfips2.0/util/incore
DEBUGGING:
Debugging the incore script, I could see that the script tried to embed the signature into the shared object at the offset 0x001EE6B0 while the FIPS_signature symbol inside the shared object was located at a different offset, to be more specific at 0x001F0630:
objdump -t libcrypto.so.1.0.0 | grep FIPS_signature 001f0630 g O .data 00000014 FIPS_signature readelf -a libcrypto.so.1.0.0 | grep FIPS_signature 870: 001f0630 20 OBJECT GLOBAL DEFAULT 18 FIPS_signature 3925: 001f0630 20 OBJECT GLOBAL DEFAULT 18 FIPS_signature
Furthermore dumping the shared object I wasn’t able to find the generated signature at the offset 0x001EE6B0 so I reached the conclusion that the shared object was edited after the signature embedding procedure by some other process.
SOLUTION:
I was using a package Makefile for the OpenSSL packet formatted in the following way:
$(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR) <options> all $(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR) <options> build-shared rm $(PKG_BUILD_DIR)/libssl.so.*.*.* $(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR) <options> do_linux-shared $(MAKE) -C $(PKG_BUILD_DIR) <options> install
As suspected, make build-shared and make do_linux-shared commands were responsible for changing the shared object in the wrong way.
NOTICE that make build-shared was called without using the proper environment variables.
I changed the package Makefile:
$(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR) <options> all $(MAKE) -C $(PKG_BUILD_DIR) <options> install
Now the FIPS_check_incore_fingerprint(void)
function returns with success and everything is working fine!
NOTE:
The following guide for Android devices has been very useful to find the proper solution. https://wiki.openssl.org/index.php/FIPS_Library_and_Android