openssl: Cannot dynamically load FIPS module from alternate location
This issue deals with the exact problem from ticket #17301 but is larger than that issue since I have duplicated the problem on both Windows and Android.
Basically, I want to load the OpenSLL FIPS module when the executable and config files are not in the standard location simply by dynamically loading the library and making function calls. My end-use case is on Android but when I couldn’t get it to work on Android, I switched to trying the same thing on Windows since I personally find it much easier to debug on Windows.
I built v3.0.4 for 64-bit Windows. I specified --prefix and --openssldir when I configured since I don’t want them put in the usual place. This is a very minimal build since all I want is FIPS crypto without any extra algorithms or any SSL / TLS support. The install_fips portion of “nmake install” did successfully run and created the .cnf file with the module-mac data.
I copied libcrypto-3-x64.dll, fips.dll and myconfig.cnf to a test directory location. My config file is (told you it was a minimal build / use):
[openssl_init]
providers = provider_sect
[provider_sect]
fips = fips_sect
[fips_sect]
conditional-errors = 1
security-checks = 1
module-mac = <<<value copied from the cnf file created during fips install>>>
I created a console application to load the FIPS module. It is linked so that libcrypto is delay loaded, and I have verified that it is delay loaded (see my breakpoint discussion below). Here’s my code:
SetEnvironmentVariable ("OPENSSL_CONF", "e:\\temp\\testloc\\myconfig.cnf");
SetEnvironmentVariable ("OPENSSL_MODULES", "e:\\temp\\testloc");
... print out environ vars and verify they are set to the above
LoadLibrary ("e:\\temp\\testloc\\libcrypto-3-x64.dll");
OSSL_LIB_CTX* fipsLibCtx = OSSL_LIB_CTX_new ();
... error check
OSSL_PROVIDER_set_default_search_path (fipsLibCtx, "e:\\temp\\testloc");
... error check
OSSL_LIB_CTX_load_config (fipsLibCtx, "e:\\temp\\testloc\\myconfig.cnf");
... error check
OSSL_PROVIDER* fipsProv = OSSL_PROVIDER_load (fipsibCtx, "fips");
the last line fails and the errors from ERR_print_errors are:
E4E0000:error:1C8000D5:Provider routines:SELF_TEST_post:missing config data::0:
E4E0000:error:1C8000E0:Provider routines:ossl_set_error_state:fips module entering error state::0:
E4E0000:error:1C8000D8:Provider routines:OSSL_provider_init_int:self test post failure::0:
E4E0000:error:078C0105:common libcrypto routines:provider_init:init fail::0:name=fips
Note - I have tried this with activate = 1 in the cnf file and the behavior is identical.
I have the following breakpoints set when I run this code:
-
first line of CONF_get1_default_config_file – this is the ONLY place in the source code that I could find that uses the OPENSSL_CONF environment variable and this break point is never hit – where is the fips self-test getting its verification data from?
-
DllMain for both libcrypto and fips – libcrypto bp is hit during the execution of LoadLibrary and fips bp is hit during OSS_PROVIDER_load
-
call to fips_get_params_from_core in OSSL_provider_init_int – bp is hit and the call succeeds, so it thinks it has read the parameters successfully
-
both lines in SELF_TEST_post that can return PROV_R_MISSING_CONFIG_DATA – the first bp is hit indicating that module_checksum_data is NULL
As far as I can tell, the issue is that my .cnf file is never read in and therefore the verification data is never set for the self test.
I can’t duplicate setting breakpoints in libcrypto when running this on Android but it fails at OSSL_PROVIDER_load with the exact same error messages, so this isn’t OS specific. The Android C code is exactly the same (using android/linux calls for environment variables and library load) and uses the location “/data/user/0/com.example.myapp/files” which is my app’s private file area.
So, my issue is … what am I missing to force it to find that config file?
Thanks, Judy
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Comments: 16 (6 by maintainers)
Yes, it works on Android. In my final version, I also needed the base provider so that is now included.
My config and SO are located in the files directory of my app. I get that path at the Java level by
activity.getFilesDir().getAbsolutePath()I then pass that directory down to native code to do the OpenSSL init.config file is:
startup code (error checking removed):
Since this is a dynamic load of the fips library, I have to do a
dlsymlookup for each of theOSSL_xxxfunctions and then call through the returned function pointer.