There are several approaches you could take. With two library contexts:
fips_libctx = OSSL_LIB_CTX_new();
non_fips_libctx = OSSL_LIB_CTX_new();
fipsp = OSSL_PROVIDER_load(fips_libctx, "fips");
basep = OSSL_PROVIDER_load(fips_libctx,"base"); /* can't load keys
without this */
defp = OSSL_PROVIDER_load(non_fips_libctx, "default");
nullp = OSSL_PROVIDER_load(NULL, "null"); /* Disallow falling
back to the default library context */
Then use either fips_libctx or non_fips_libctx for operations.
Alternatively, it can be done in one library context (the default here),
although there is some risk of using non-FIPS crypto in a FIPS context:
fipsp = OSSL_PROVIDER_load(NULL, "fips");
defp = OSSL_PROVIDER_load(non_fips_libctx, "default");
For FIPS, make sure that "fips=yes" is included as a property query.
The easiest way is to do this globally:
EVP_set_default_properties(NULL, “fips=yes”);
For non-FIPS, just don't do anything.
Personally, I'd do the former two library contexts based approach and
not worry about the properties.
Pauli
On 24/10/21 2:58 am, Jason Schultz wrote:
Quick aside: I know the 3.0 FIPS module is not "approved" yet, I'm
just trying to get my application updates done in advance.
I’m porting an application from OpenSSL 1.1.1, which was originally
written for OpenSSL 1.0.2, to OpenSSL 3.0. Going to 3.0, I need to
incorporate FIPS usage. My Linux application basically is told if its
user wants to use FIPS or not. We don’t use the cryptographic APIs
(EVP_*), we just need to create an SSL_CTX, and SSL objects created
with SSL_new() based on this SSL_CTX, which will then call SSL_read(),
SSL_write(), etc. The application won’t “fetch” any algorithms. So my
focus can been on Section 7.7 of the Wiki:
https://wiki.openssl.org/index.php/OpenSSL_3.0#Using_the_FIPS_module_in_SSL.2FTLS
Based on if FIPS is on or off, I will use the replacement for
SSL_CTX_new() and call SSL_CTX_new_ex() either something like this:
ctx = SSL_CTX_new_ex(non_fips_libctx, NULL, TLS_method());
or this:
ctx = SSL_CTX_new_ex(fips_libctx, NULL, TLS_method());
Depending on if the users does not want FIPS, or wants FIPS,
respectively.
Based on that and what Section 7.7 tells me, I know I need:
1. A non-default library context with the FIPS provider loaded
(called fips_libctx), and
2. A non-default library context with the default provider loaded
(called non_fips_libctx)
I know that I don’t want all applications using OpenSSL to use the
FIPS module by default, so I’m just trying to configure mine
correctly, using the APIs (and possibly config files). I also
obviously don’t want to make my application use the FIPS module only.
Given all of the above I’m confused on how to set up #1 and #2. It
seems like I need to use a combination of configuration files and
programmatically calling APIs in my application. In the Wiki and the
fips_module man page there is a section called “Programmatically
loading the FIPS module (nondefault library context)”. I’m pretty sure
this is what I want. The code example says it “assumes the existence
of a config file called openssl-fips.cnf that automatically loads and
configures the FIPS and base providers.”
The .cnf files that I have after the (FIPS) install of OpenSSL 3.0 are
in /usr/local/ssl/: openssl.cnf and fipsmodule.cnf.
I guess the first thing is I’m confused on if the “openssl-fips.cnf”
file referred to in the example is in addition to the two files above,
or a replacement for one of them, and also what the contents of it
need to be.
I had already made changes to the openssl.cnf file for FIPS (described
in earlier sections of the Wiki):
# For FIPS
# Optionally include a file that is generated by the OpenSSL fipsinstall
# application. This file contains configuration data required by the
OpenSSL
# fips provider. It contains a named section e.g. [fips_sect] which is
# referenced from the [provider_sect] below.
# Refer to the OpenSSL security policy for more information.
.include */usr/local/ssl/fipsmodule.cnf****ß***uncommented
[openssl_init]
providers = provider_sect
# List of providers to load
[provider_sect]
default = default_sect
# The fips section name should match the section name inside the
# included fipsmodule.cnf.
fips = fips_sectßuncommented
# If no providers are activated explicitly, the default one is
activated implicitly.
# See man 7 OSSL_PROVIDER-default for more details.
#
# If you add a section explicitly activating any other provider(s),
you most
# probably need to explicitly activate the default provider, otherwise it
# becomes unavailable in openssl.As a consequence applications
depending on
# OpenSSL may not work correctly which could lead to significant system
# problems including inability to remotely access the system.
[default_sect]
activate = 1ßuncommented
I did this to make sure the FIPS provider was available and make sure
the default provider was activated.
I also changed the fipsmodule.cnf file to comment out the activate = 1
line:
[fips_sect]
# activate = 1
conditional-errors = 1
security-checks = 1
module-mac =
E4:0D:C8:C3:1E:DB:2B:30:E6:F2:49:7B:F5:BD:10:5C:9A:2B:CC:C1:33:49:31:B5:C5:AF:50:AB:82:1E:AE:C9
That was from the “Programmatically loading the FIPS module (default
library context)” section, so I’m wondering if this was a mistake.
But currently, with the configs files as described above, my
application is loading both providers:
fipsp = OSSL_PROVIDER_load(NULL, "fips");
if (fipsp == NULL)
{
/* error handling */
}
defp = OSSL_PROVIDER_load(NULL, "default");
if (defp == NULL)
{
/* error handling */
}
And then creating two library contexts:
fips_libctx = OSSL_LIB_CTX_new();
non_fips_libctx = OSSL_LIB_CTX_new();
Which are later used to create SSL_CTX’s as needed:
if (user does not want fips)
{
ctx = SSL_CTX_new_ex(non_fips_libctx, NULL, TLS_method());
}
else (user wants fips)
{
ctx = SSL_CTX_new_ex(fips_libctx, NULL, TLS_method());
}
But I think the 2^nd to last step is probably creating two library
contexts, both using fips because of my changes to the default
configuration file. (more on my changes to the default file later)
Looking at section 7.5 of the Wiki, I’m thinking I need to create a
file called openssl-fips.cnf with the contents something like(or maybe
a minimum of):
[fips_sect]
activate = 1
conditional-errors = 1
security-checks = 1
module-mac =
E4:0D:C8:C3:1E:DB:2B:30:E6:F2:49:7B:F5:BD:10:5C:9A:2B:CC:C1:33:49:31:B5:C5:AF:50:AB:82:1E:AE:C9
[base_sect]
activate = 1
Then before creating SSL_CTX’s and after the OSSL_LIB_CTX() calls, I
need to call:
OSSL_LIB_CTX_load_config(fips_libctx, “openssl-fips.cnf”);
Which will get the FIPS and base providers in the fips_libctx. The
non_fips_libctx will use the default config file and have the default
provider, which is what I want.
Also, it seems like I need to call:
defctxnull = OSSL_PROVIDER_load(NULL, “null”);
Which is to “prevent anything from using the default library context”?
Also, I probably need to revert my changes to the default config file
to not activate additional providers, which means only the default one
will be activate implicitly. Then the non_fips_libctx =
OSSL_LIB_CTX_new(); line will set up the default provider in
non_fips_libctx.
I’m hoping someone can point me in the right direction, because the
other problem is that I’m not sure how to validate what I’ve done is
correct. As in, how do I know fips_libctx is actually “FIPS”
compliant, and/or the SSL_CTX’s I create are “FIPS”. I realize there
are probably several ways to do this, but I’m looking to isolate my
application only this way, and not affect any other applications on
the system.
Thanks in advance.
Jason