13. Support for OpenSSL Providers

Note

This chapter does NOT apply if you are using OpenSSL® version 1.1.1w or below, which has reached end-of-life. For those versions, see Support for OpenSSL Engines.

OpenSSL providers allow you to define custom implementations for security operations. When you load a provider, OpenSSL will call the security functions defined by the provider instead of its default builtin functions. The Security Plugins support the option of using OpenSSL providers, enabling you to use optimized cryptographic libraries, add support for custom hardware acceleration, etc.

13.1. Instructions for Loading Providers

To load OpenSSL providers, you have to follow three steps:

  • Construct a configuration file.

  • Set environment variables.

  • Verify that you are using the providers that you think you are using.

13.1.1. Constructing a Configuration File

Section “Provider Configuration” on this page describes how to construct a configuration file that can use your provider. You can just modify the configuration file that comes with an RTI OpenSSL target bundle: $NDDSHOME/third_party/openssl-<version>/$ARCH/release/openssl.cnf. Here is an example of a configuration file that specifies activating the Base and FIPS providers:

#
# (c) Copyright, Real-Time Innovations, 2024.
# All rights reserved.
#
# Permission to modify and use for internal purposes granted.
# This software is provided "as is", without warranty, express or implied.
#
# OpenSSL example configuration file.
# See doc/man5/config.pod for more info.
#
# This is used for auto loading of the FIPS provider.

# This definition stops the following lines choking if HOME isn't
# defined.
HOME			= .

# Use this configuration in order to automatically load providers.
#
# The OpenSSL configuration looks up the value of openssl_conf in the default
# section and takes that as the name of a section that specifies how to
# configure any modules in the library.
# openssl_conf is the entry point for our configuration.
# More information in https://www.openssl.org/docs/man3.0/man5/config.html
openssl_conf = openssl_init

# Comment out the next line to ignore configuration errors
config_diagnostics = 1

[openssl_init]
# providers in the initialization section names the section containing
# cryptographic provider configuration. The name/value assignments in this
# section each name a provider, and point to the configuration section for that
# provider.
providers = provider_sect

# alg_section in the initialization section names the section containing
# algorithmic properties when using the EVP API.
alg_section = algorithm_sect

# List of providers to load
#
# OpenSSL comes with several providers: default, base, fips, legacy, and NULL.
# See https://www.openssl.org/docs/man3.0/man7/crypto.html
[provider_sect]
# The fips section name should match the section name inside the
# included fipsmodule.cnf.
fips = fips_sect
base = base_sect
default = default_sect

# 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.
#
# This fips_sect is taken directly from fipsmodule.cnf. This file contains
# configuration data required by the OpenSSL fips provider. We don't do
#
# .include /path/to/fipsmodule.cnf
#
# because we don't know the absolute path to this file at
# runtime (and a relative path is not relative to the location of openssl.cnf).
# Instead, we directly include the file's contents. Substitute
# FIPS_MODULE_MAC_VALUE with the value that's in fipsmodule.cnf.
[fips_sect]
activate = 1
conditional-errors = 1
security-checks = 1
module-mac = @FIPS_MODULE_MAC_VALUE@

[base_sect]
# Besides the FIPS provider, we require the base one. This provider is designed
# to be used in conjunction with the FIPS module, and it does not invalidate
# FIPS compliance. It provides auxiliary, non-cryptographic functions.
# We do disable the default provider, which contains cryptographic algorithms.
activate = 1

[default_sect]
# This line is commented out because we don't want to use the default provider.
# Note: "activate = 0" DOES NOT WORK. See
# https://www.openssl.org/docs/man3.0/man7/fips_module.html : "note that
# setting this value to 0 is not sufficient".
# activate = 1

[algorithm_sect]
# By default, use algorithm implementations that conform to FIPS standards. See
# https://www.openssl.org/docs/man3.0/man7/fips_module.html
# "Loading the FIPS module at the same time as other providers"
default_properties = fips=yes

13.1.2. Setting Environment Variables

Section “ENVIRONMENT” in this page describes some environment variables. To load provider(s), you must set two of them:

  • OPENSSL_CONF: The path and filename of the configuration file you constructed (e.g., $NDDSHOME/third_party/openssl-<version>/$ARCH/release/openssl.cnf).

  • OPENSSL_MODULES: The path (without filename) that contains the provider(s) that you want to load (e.g., $NDDSHOME/third_party/openssl-<version>/$ARCH/release/lib/ossl-modules because this directory contains fips.so for Linux).

In the case of dynamic linking, these environment variables are in addition to the usual library search path variable described in Dynamic Linking.

Note

It is possible to use providers in either a statically or dynamically linked application.

13.1.3. Verifying the Usage of Providers

To verify that you are using the providers that you think you are using, you may temporarily set the logging verbosity of the SECURITY category to STATUS_LOCAL. Here is an example in Modern C++:

Logger::instance().verbosity_by_category(
        LogCategory::security,
        Verbosity::STATUS_LOCAL);

Alternatively, you may temporarily change the logging.verbosity value to NOTICE. Here is an example in XML:

<domain_participant_qos>
    <property>
        <value>
            <element>
                <name>com.rti.serv.secure.logging.verbosity</name>
                <value>NOTICE</value>
            </element>
        </value>
    </property>
</domain_participant_qos>

Here is an example of what the application output would look like:

RTI_Security_CryptoLibAdapter_listProviderInfo:Providers:
RTI_Security_CryptoLibAdapter_listProviderInfo:  base
RTI_Security_CryptoLibAdapter_listProviderInfo:    name: OpenSSL Base Provider
RTI_Security_CryptoLibAdapter_listProviderInfo:    version: 3.0.12
RTI_Security_CryptoLibAdapter_listProviderInfo:    status: active
RTI_Security_CryptoLibAdapter_listProviderInfo:  fips
RTI_Security_CryptoLibAdapter_listProviderInfo:    name: OpenSSL FIPS Provider
RTI_Security_CryptoLibAdapter_listProviderInfo:    version: 3.0.12
RTI_Security_CryptoLibAdapter_listProviderInfo:    status: active

This output indicates that the application is using the Base and FIPS providers.

If you see something like this:

RTI_Security_CryptoLibAdapter_listProviderInfo:Providers:
RTI_Security_CryptoLibAdapter_listProviderInfo:  default
RTI_Security_CryptoLibAdapter_listProviderInfo:    name: OpenSSL Default Provider
RTI_Security_CryptoLibAdapter_listProviderInfo:    version: 3.0.12
RTI_Security_CryptoLibAdapter_listProviderInfo:    status: active

then you are using only the Default Provider, and you need to review your configuration file and/or environment variables if you want to use a different provider.

13.2. How Providers Impact Security Plugins Behavior

During DomainParticipant creation, the Security Plugins determine if any algorithms are not supported by the providers. For those algorithms, their bits in the supported_mask fields are automatically cleared for you. It is as if you had excluded those algorithms from your value of allowed_security_algorithms (domain_rule) in your Governance Document.

When performing security operations, the Security Plugins will call OpenSSL functions in the usual manner. The Security Plugins rely on implicit instead of explicit fetching and do not perform any property queries, so if you have loaded multiple providers that implement the same algorithm, you will have to rely on either the default_properties field in your configuration file or the “default search criteria” mentioned here. We recommend having only one provider per algorithm.

13.3. The FIPS Provider

The OpenSSL FIPS provider conforms to Federal Information Processing Standards (FIPS). The RTI OpenSSL target packages (i.e., the files named openssl-<openssl version>-<connext version>-target-<target architecture>.rtipkg) for Android, Linux, and Windows include the FIPS module configuration file and provider library (the packages were built using the enable-fips option and make install_fips command described in this OpenSSL README file). You can use the fipsmodule.cnf and fips_3_0.so (Android), fips.so (Linux), or fips.dll (Windows) files to validate that the Security Plugins work with the FIPS provider.

Note

Keep in mind that the latest OpenSSL version that has been FIPS-validated by the Cryptographic Module Validation Program (CMVP) may not be the version that is in your RTI OpenSSL target package. See https://www.openssl.org/source for the latest FIPS-validated version.

RTI has tested that the Security Plugins work with the OpenSSL FIPS provider. The only configuration that doesn’t work is setting the property authentication.key_establishment_algorithm to DHE+MODP-2048-256 because OpenSSL excludes this Diffie-Hellman named group from the FIPS version of their libcrypto library. DomainParticipant creation will fail if you attempt to use DHE+MODP-2048-256 with the FIPS provider.