.. include:: ../vars.rst

.. _chapter-openssl-providers:

*****************************
Support for OpenSSL Providers
*****************************

.. note::

  This chapter does *NOT* apply if you are using |OpenSSL_TM| version 1.1.1w or
  below, which has reached end-of-life. For those versions, see
  :ref:`p3_advanced/openssl_engines: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
|RTI_SP_PRODUCT| support the option of using |OpenSSL| providers, enabling you to use
optimized cryptographic libraries, add support for custom hardware
acceleration, etc.

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.

Constructing a Configuration File
---------------------------------

`Section "Provider Configuration" on this page <https://www.openssl.org/docs/man3.0/man5/config.html>`_
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:

.. literalinclude:: ../../../example/opensslFips.in
  :language: text
  :class: break-lines
  :emphasize-lines: 73

Don't forget to modify ``@FIPS_MODULE_MAC_VALUE@`` with the value in your
``fipsmodule.cnf`` file.

Setting Environment Variables
-----------------------------

`Section "ENVIRONMENT" in this page <https://www.openssl.org/docs/man3.0/man5/config.html>`_
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
:ref:`p2_core/building_apps:Dynamic Linking`.

.. note::

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


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++:

.. code-block:: c++

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

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

.. code-block:: 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:

.. code-block:: console

  RTI_Security_CryptoLibAdapter_listProviderInfo:Providers:
  RTI_Security_CryptoLibAdapter_listProviderInfo:  base
  RTI_Security_CryptoLibAdapter_listProviderInfo:    name: OpenSSL Base Provider
  RTI_Security_CryptoLibAdapter_listProviderInfo:    version: 3.5.5
  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.5.5
  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:

.. code-block:: console

  RTI_Security_CryptoLibAdapter_listProviderInfo:Providers:
  RTI_Security_CryptoLibAdapter_listProviderInfo:  default
  RTI_Security_CryptoLibAdapter_listProviderInfo:    name: OpenSSL Default Provider
  RTI_Security_CryptoLibAdapter_listProviderInfo:    version: 3.5.5
  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.

How Providers Impact |RTI_SP_PRODUCT_HEADING| Behavior
======================================================

During |DP| creation, the |RTI_SP_PRODUCT| determine if any algorithms are not supported by
the providers. For those algorithms, their bits in the
:link_connext_dds_api_cpp2:`supported_mask <classrti_1_1topic_1_1trust_1_1TrustAlgorithmRequirements.html>`
fields are automatically cleared for you. It is as if you had excluded those
algorithms from your value of
:ref:`p2_core/cryptography:allowed_security_algorithms (domain_rule)` in your
|GovernanceDoc|.

When performing security operations, the |RTI_SP_PRODUCT| will call |OpenSSL| functions in
the usual manner. The |RTI_SP_PRODUCT| rely on
`implicit instead of explicit fetching <https://www.openssl.org/docs/manmaster/man7/crypto.html>`_
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 <https://www.openssl.org/docs/man3.0/man5/config.html>`_
or the
`"default search criteria" mentioned here <https://www.openssl.org/docs/manmaster/man7/crypto.html>`_.
We recommend having only one provider per algorithm.

The FIPS Provider
=================

The |OpenSSL| FIPS provider conforms to Federal Information
Processing Standards (FIPS). The RTI |OpenSSL| target packages (i.e., the files
named
:file:`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 <https://github.com/openssl/openssl/blob/openssl-3.5.5/README-FIPS.md>`_).
You can use the ``fipsmodule.cnf`` and ``fips_3_0.so`` (Android), ``fips.so``
(Linux), or ``fips.dll`` (Windows) files to validate that the |RTI_SP_PRODUCT| 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 |RTI_SP_PRODUCT| work with the |OpenSSL| FIPS provider.
The following configurations do not work:

* Setting the property :property:`dds.sec.auth.key_establishment_algorithm` to
  :value:`DHE+MODP-2048-256`, because |OpenSSL|
  `excludes this Diffie-Hellman named group from the FIPS version of their libcrypto library <https://github.com/openssl/openssl/blob/openssl-3.5.5/crypto/ffc/ffc_dh.c#L88>`_.
  |DP| creation will fail if you attempt to use :value:`DHE+MODP-2048-256` with
  the FIPS provider.
* Setting the property :property:`authentication.enable_experimental_algorithms`
  to :value:`TRUE` and the :property:`dds.sec.auth.key_establishment_algorithm`
  to :value:`ECDHE-CEUM+X25519` or :value:`ECDHE-CEUM+X448`, because the
  `X25519 and X448 key exchange implementation in the FIPS provider is unapproved and has fips=no property
  <https://github.com/openssl/openssl/blob/openssl-3.4.0/CHANGES.md#openssl-34>`_.
  |DP| creation will fail if you attempt to use this combination of properties
  with the FIPS provider.
