FIPS_mode_set() code not found in openssl package

4.6k views Asked by At

I am new to openssl, and I downloaded openssl-fips-2.0.1 codes from openssl, however, I was not able to trace to the definition of FIPS_mode_set() as stated in the documentation and security policy. I did find, however, fips_set_mode() in fips.c, but they are not referring to the same, am I right?

Where is the definition? Please advise me.

4

There are 4 answers

6
jww On BEST ANSWER

FIPS_mode_set() code not found in openssl package

You have to know how to ask...

openssl-1.0.1f$ grep -R FIPS_mode_set *
apps/openssl.c:     if (!FIPS_mode_set(1)) {
CHANGES:  *) Functions FIPS_mode_set() and FIPS_mode() which call the underlying
crypto/cpt_err.c:{ERR_FUNC(CRYPTO_F_FIPS_MODE_SET), "FIPS_mode_set"},
crypto/evp/evp_cnf.c:   if (!FIPS_mode() && !FIPS_mode_set(1))
crypto/crypto.h:int FIPS_mode_set(int r);
crypto/o_fips.c:int FIPS_mode_set(int r)
Binary file fips_premain_dso matches
ssl/ssltest.c:      if(!FIPS_mode_set(1))
util/libeay.num:FIPS_mode_set    3253    EXIST::FUNCTION:
openssl-1.0.1f$ 

The declaration is in crypto/crypto.h and the definition is in crypto/o_fips.c. Here's from o_fips.c:

int FIPS_mode_set(int r)
    {
    OPENSSL_init();
#ifdef OPENSSL_FIPS
#ifndef FIPS_AUTH_USER_PASS
#define FIPS_AUTH_USER_PASS "Default FIPS Crypto User Password"
#endif
    if (!FIPS_module_mode_set(r, FIPS_AUTH_USER_PASS))
        return 0;
    if (r)
        RAND_set_rand_method(FIPS_rand_get_method());
    else
        RAND_set_rand_method(NULL);
    return 1;
#else
    if (r == 0)
        return 1;
    CRYPTOerr(CRYPTO_F_FIPS_MODE_SET, CRYPTO_R_FIPS_MODE_NOT_SUPPORTED);
    return 0;
#endif
    }

If you were looking for FIPS_mode_set to enter into "FIPS mode" with special setup or switch some algorithms, that does not happen at this step.

It happens earlier when linking. What happens under the hood is fipsld is you compiler, and it looks for an invocation of LD. If LD is not invoked, then fipsld just calls your regular compiler (probably /usr/bin/gcc). If it sees an invocation of LD, then it does three things.

First, it compiles fips_premin.c. Then it calls the real ld to perform the final link with all your object file and the fips_premain.o it produced. Finally, it calls incore to swap in the FIPS Object Module, calculate the signature over the relevant text and data (relevant means the FIPS code and data), and then embeds the signature in the executable.

The signature is generated with an HMAC, and the key is embedded in the executable. There's nothing special about it, and its constant across all executables throughout the world. Here's the key used: etaonrishdlcupfm.


If you are not taking special steps when build your executable, then you are probably missing some steps. Here are the steps to use fipsld and incore:

$ export CC=`find /usr/local -name fipsld`
$ echo $CC 
/usr/local/ssl/fips-2.0/bin/fipsld
$ export FIPSLD_CC=`find /usr/bin -name gcc`
$ echo $FIPSLD_CC 
/usr/bin/gcc

Now, do a standard config and make. Sometimes you have to do config, then adjust CC and FIPSLD_CC, and then run make because some config files choke on the arrangement. Sometimes you have to open a Makefile after config and change CC to /usr/local/ssl/fips-2.0/bin/fipsld. There's lots of ways to do it in an effort to work around particular packaging.


I downloaded openssl-fips-2.0.1 codes from openssl, however, I was not able to trace to the definition of FIPS_mode_set()

openssl-fips-NNN provides the FIPS validated cryptography if you build the FIPS Object Module according to the Security Policy. You can find the OpenSSL FIPS 1402- Security Policy at here.

If all you did was download and build openssl-fips-NNN, then you are probably not using FIPS validated cryptography. There's a procedure to follow, and that includes getting a "trusted" copy of the source code. You can download and verify a signature, but you need a FIPS validated signature checker, which creates a chicken-and-the-egg problem because you can't build it from sources. So the practical solution is to order the CD from the OpenSSL Foundation. Its bizarre, but its the truth. See, for example, the OpenSSL FIPS User Guide or the OpenSSL FIPS Security Policy, Appendix B, Controlled Distribution File Fingerprint.

Once you have the FIPS Object Module built and installed, you can build the FIPS Capable version of the library. The FIPS Capable OpenSSL will use the FIPS Object Module, if available. Think of it as a "pluggable" architecture.

The FIPS Capable version of the library is simply openssl-NNN, such as openssl-1.0.1e and openssl-1.0.1f. Its what you know and love.


You might also consider something like ctags as a source code browser to help you find things and jump around. See Exuberant Ctags on Sourceforge.

2
doptimusprime On

Please refer header file crypto.h. I am able to find its definition there at line 566 as follows:

int FIPS_mode_set(int r);

Documentation clearly mention that it is in header file <openssl/crypto.h>.

So, in your code, include openssl/crypto.h to include the definition of this function. If you face other problem, you can browse through questions of OpenSSL that may help you.

4
alk On

For linkage FIPS_mode_set() should be available from libcrypto (*.a for static linkage and *.so for run-time linkage).

libcrypto.a/.so comes with your distro's openssl's developer package, or as a result of bulding openssl-x.y.z yourself.

You find the sources for FIPS_mode_set() in the sources for openssl-x.y.z, in the file crypto/o_fips.c.

0
Oleksandr Ismailov On

Official documentation migration guide explain that should be used different functions:

https://www.openssl.org/docs/manmaster/man7/migration_guide.html

Removed FIPS_mode() and FIPS_mode_set()

These functions are legacy APIs that are not applicable to the new provider model. Applications should instead use EVP_default_properties_is_fips_enabled(3) and EVP_default_properties_enable_fips(3).

I have added this one(I am not sure still that it is good, but hope should be for all versions):

#if OPENSSL_VERSION_MAJOR < 3
    FIPS_mode_set(0);
#else
    EVP_default_properties_enable_fips(nullptr, 0);
#endif