.. include:: ../vars.rst

.. _chapter-authentication:

**************
Authentication
**************

Authentication is the process of making sure a |DP| is who it claims to be.
Loading any [#]_ security plugins will configure the |DP| to request the plugins
to authenticate a newly discovered remote participant before initiating
|EP_disc| with that participant.

.. note::

  In the case of |LIGHT_SP_BUILTIN|, which implements |SEC_SPEC_12|
  builtin PSK plugins, the |AuthPlugin| does not perform any operation
  to cryptographically enforce |DP| Authentication.
  Consequently, most of this chapter (with some exceptions such as the
  descriptions of :property:`files_poll_interval` and
  :property:`authentication.enable_custom_allocators`)
  is only applicable to |SP_BUILTIN| or custom security plugins implementing
  3-way handshake PKI-based authentication.

In the case of |SP_BUILTIN|, Authentication is done via a series of
inter-participant challenge and response messages, which are exchanged during a
3-way handshake. These messages perform mutual authentication, so the end result
is that this |DP| authenticates the remote |DP| and vice-versa.

Before a |DP| is enabled, the |AuthPlugin| associated with the |DP| must be configured with three artifacts:

#. The **Identity CA Certificate**, which contains the public key of the Identity CA.

#. The **Private Key** of the |DP|.

#. An **Identity Certificate** that chains up to the Identity CA. This certificate binds the public key of the |DP| to its subject name.

If the |AuthPlugin| fails to verify any of these prerequisites, participant creation fails.

To successfully authenticate a remote participant, that remote participant must present a valid |IdentityCert| (this is known as Identity Certificate Validation, which we describe in :ref:`p2_core/authentication:Identity Certificate Validation`) and prove to have access to the private key associated with the |IdentityCert|'s public key (by signing challenges during the handshake).


Authentication of the remote participant takes place right after the |DP_disc| phase (see :link_connext_dds_pro_um:`Discovery in the Core Libraries User's Manual <#users_manual/Discovery.htm>`). Secure |EP_disc| will only happen between mutually authenticated participants. In other words, if a participant (let's call it |P1|) fails to authenticate a different participant (|P2|), |P1| ignores |EP_disc| traffic from |P2|. Otherwise, |P1| initiates |EP_disc| with |P2| after mutual authentication. If a participant fails to authenticate, |CONNEXT| will try again by initiating a new handshake through the |AuthPlugin|.

Each |DP| can optionally specify a certificate revocation list (CRL) to the |AuthPlugin|. The CRL is checked for revoked certificates as part of the Identity Certificate Validation (see :ref:`p2_core/authentication:Identity Certificate Validation`). Remote participants presenting a revoked certificate will not be authenticated. This way, you can prevent a compromised |DP| from joining your secure domain by revoking its |IdentityCert| and adding it to the CRL.

.. [#] Either |SP_BUILTIN| or custom security plugins. Setting :property:`.load_plugin` will tell the |CONNEXT| core to call the |AuthPlugin|.


Handshake
=========

To perform mutual authentication, |DPs| exchange a series of challenge and
response messages in a 3-way handshake. This handshake is the mechanism by which
participants verify each other's identity and establish a |SharedSecret|. After
mutual authentication over an unsecure channel, a |SharedKey| is derived using
the |SharedSecret|.

Handshake messages are sent over the |AuthT|, which allows the messages to be
directed to a specific recipient (see
:ref:`p2_core/authentication:Authentication Builtin Topic (ParticipantStatelessMessage)`).

The handshake establishes mutual authentication between discovered participants
using the RSA or ECDSA digital signature algorithms, and determines a
|SharedSecret| using Diffie-Hellman (DH) or Elliptic Curve Diffie-Hellman (ECDH)
key establishment methods.

Message Exchange
----------------

Let's analyze the handshake by examining the messages that two participants (|P1| and |P2|) exchange as part of the authentication:


Handshake Request
^^^^^^^^^^^^^^^^^

To initiate the handshake, |P1| sends a |HS_REQ| to |P2| that includes:

* |P1|'s |IdentityCert| (*Cert1*), which includes |P1|'s public key (*PubK1*)

* |P1|'s Participant data (*Pdata1*), which includes |P1|'s DomainParticipantQos and |P1|'s security attributes

* |P1|'s |PermissionsDoc| (*Perm1*)

* A challenge (*Challenge1*) and a Diffie-Hellman public key (*DH1*), which |P1| randomly generates right before initiating the handshake


Handshake Reply
^^^^^^^^^^^^^^^

When |P2| receives the |HS_REQ|, it verifies *Cert1* and *Perm1*'s signature. At this point, |P2| knows whether |P1| has presented a valid |IdentityCert| (that chains up to the shared Identity CA) and |PermissionsDoc| (signed by the shared Permissions CA). If it did, the handshake continues and |P2| sends a |HS_REP| to |P1| that includes:

* |P2|'s |IdentityCert| (*Cert2*), which includes |P2|'s public key (*PubK2*)

* |P2|'s Participant data (*Pdata2*), which includes |P2|'s DomainParticipantQos and |P2|'s security attributes

* |P2|'s |PermissionsDoc| (*Perm2*)

* A challenge (*Challenge2*) and a Diffie-Hellman public key (*DH2*), which |P2| randomly generates upon reception of a |HS_REQ|

* A signature (*Sign2*), which |P2| generates by signing some of the message contents, including *Challenge1* and *DH2*, with its private key (*PrivK2*)


Handshake Final
^^^^^^^^^^^^^^^

When |P1| receives the |HS_REP|, it verifies *Cert2* and *Perm1*'s signature,
thus verifying whether |P2| has presented a valid |IdentityCert| (that chains up
to the shared Identity CA) and |PermissionsDoc| (signed by the shared
Permissions CA). |P1| also verifies *Sign2* against *PubK2*. Hence, |P1| can
verify whether *Sign2* was generated with *PrivK2*. At this point, |P1| knows
whether |P2| is the legitimate holder of the private key associated with
*Cert2*. If the verification succeeds, |P2| is authenticated and |P1| computes
the |SharedSecret| from *DH2* and the Diffie-Hellman private key used for *DH1*.
At this point, |P1| sends a |HS_FIN| to |P2| that includes:

* A signature (*Sign1*), which |P1| generates by signing some of the message
  contents, including *Challenge2* and *DH1*, with its private key (*PrivK1*)

When |P2| receives this message it verifies *Sign1* against *PubK1*. Now, |P2|
knows whether |P1| is the legitimate holder of the private key associated with
*Cert1*. |P1| is now authenticated and |P2| computes the |SharedSecret| from
*DH1* and the Diffie-Hellman private key used for *DH2*. At this point, the
handshake concludes: |P1| and |P2| are mutually authenticated and have a
|SharedSecret| they can use to derive the |SharedKey| they need to communicate
securely.


General Considerations
----------------------

The authentication process is secure, even if the channel where the
authentication happens is not secure. As we mentioned earlier, the |HS_REQ| and
|HS_REP| messages include a random challenge. In both cases, the purpose of this
challenge is to verify that the remote participant currently holds the private
key corresponding to the exchanged certificate. For clarity, let's analyze how
we achieve this using the |HS_REQ|.

In the |HS_REQ|, |P1| is the challenger participant, and |P2| is the challenged
participant. (Note that the mechanism used in the |HS_REP| is the same, but |P1|
and |P2| swap roles.) In this first case, |P1| sends a random challenge that
|P2| needs to sign (along with other information) with its private key, sending
the result back to |P1|. Then |P1| verifies that the signature corresponds to
the public key in |P2|'s certificate. Since the challenge is a random piece of
information unique to the current authentication session, |P1| can verify that
|P2| currently holds the private key corresponding to the public key claimed in
the certificate. With this mechanism, it is not possible to capture a valid
handshake from a previous authentication session and replay it later without it
becoming invalid. Therefore, we can be sure that |P2| is the legitimate holder
of the exchanged certificate. In other words, this verifies that |P2| is who it
claims to be.

During the authentication process, things can go wrong. For example, an
unauthorized participant may present an invalid certificate, an attacker trying
to impersonate one of your participants will be unable to give a valid response
to the challenges, or an attacker may try to break the authentication between
two legitimate participants by sending invalid responses to challenges in lieu
of an authorized participant halfway through the authentication process. An
invalid certificate or response to a challenge will result in a
VALIDATION_FAILURE for that particular handshake message, but authentication
will not fail until it times out. This is to avoid denial-of-service (DoS)
attacks where a third party injects messages during an authentication.

If the authentication process fails (because it times out), the participants can
fall into one of the following states:


Symmetric Authentication Failure
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
If the authentication process is not completed and fails for both participants (|P1| does not authenticate |P2|, and |P2| does not authenticate |P1|), |P1| cleans up all the authentication state of |P2| and |P2| cleans up all the authentication state of |P1|, so the authentication can start from scratch.


Asymmetric Authentication Failure
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Let's analyze the case where |P1| successfully authenticates |P2|, but |P2| did not authenticate |P1|. This can happen if |P1| received the |HS_REP| that was correct, but it couldn't deliver the |HS_FIN| (because of a network failure, for example). In this case, |P2| cannot start authenticating from scratch because from |P1|'s perspective, |P2| has already authenticated (in other words, |P1| has not cleaned up |P2|'s authentication state). 

Asymmetric authentication failure can also happen if authentication succeeds for both participants, then liveliness expires for just one of them.

To solve this problem, by default, |P2| periodically sends |AuthReq| messages to |P1| after a timeout. With an |AuthReq|, |P2| asks |P1| to open a secondary authentication process so it has the opportunity to reauthenticate. If that succeeds, |P1| will replace |P2|'s old authentication state with the new one. At this point, |P1| and |P2| are mutually authenticated.

For more details, see :ref:`p2_core/authentication:Re-Authentication`.


Identity Certificate Validation
-------------------------------

|IdentityCerts| are signed by a CA trusted by both |DPs|. Therefore, |DPs| can verify that the received certificate is legitimate. As per the |SEC_SPEC|, |IdentityCerts| are in PEM format and may contain a human-readable section above the mandatory section delimited by:

.. code-block:: text

  ---BEGIN CERTIFICATE---
  ---END CERTIFICATE---


The human-readable section adds no functionality and is NOT used for validating the certificate. Removing it from the |IdentityCert| before the authentication process reduces the size of the messages on the network.

By default beginning in Connext DDS version 6.0.1, the human-readable part of |IdentityCerts| is stripped when the certificate is loaded. This behavior avoids additional overhead and can be controlled with the boolean property :property:`authentication.propagate_simplified_identity_certificate` (see :numref:`|RTI_SP_PRODUCT_HEADING| Properties for Configuring Authentication`).

Identity Certificate Validation is done when this participant receives the first handshake message from a remote participant, and implies multiple checks:


Step 1. Verifying the certificate validity on the current date and time
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

The |SP_BUILTIN| will check the certificate's X.509 Validity fields (*Not Before* and
*Not After*). If the certificate is received outside this time frame (before it
becomes valid, or after it has expired), validation fails immediately.
Otherwise, the certificate is considered currently valid.


Step 2. Verifying the certificate is not revoked
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

|CONNEXT| supports two orthogonal mechanisms for verifying certificate validity
- |CRL| and |OCSP|.

You can enable |CRL|-based validation by setting the :property:`authentication.crl` property
(see :numref:`|RTI_SP_PRODUCT_HEADING| Properties for Configuring Authentication`).
By doing this, your |DP| will check the certificate against the revocation
list. If the certificate is found to be revoked, validation fails immediately.
Note that each |DP| is responsible for specifying its own |CRL|; a |CRL| is not
exchanged during discovery or handshaking.
Also note that the revocation list is mutable as described in
:ref:`p2_core/authentication:Dynamic Certificate Revocation of Remote |DPs|`.
For further details about |CRL|, refer to :ref:`p2_core/elements_dds_secure_system:Multiple Certificate Revocation Lists`.

Validation with |OCSP| can be enabled by supplying an |IdentityCert| with the
:value:`authorityInfoAccess` extension including an |OCSPResp| URL. To validate a local certificate,
your |DP| will communicate with the |OCSPResp| at the address from the certificate. If
the Responder determines that the certificate is valid, it will reply with an
|OCSPToken| with the :value:`nextUpdate` field set in the future. A local |DP|
will use this token as a proof of certificate validity when authenticating with
remote |DPs|. Remote |DPs| do not contact the local |DP|'s |OCSPResp|, but
they rely exclusively on the |OCSPToken| to determine validity of the
presented certificate. Shortly before expiration, i.e. :value:`nextUpdate` time,
of the |OCSPToken|, the local |DP| contacts the |OCSPResp| again to
get a renewed token, with a new expiration time. Upon its reception, the local
|DP| propagates the new |OCSPToken| to all matched remote |DPs|. For further
details about |OCSP|, refer to
:ref:`p2_core/authentication:Online Certificate Status Protocol`.

|CRL| and |OCSP| can be used simultaneously but are subject to |GovernanceDoc| rules.
For details about |GovernanceDoc| configuration, refer to :ref:`p2_core/authentication:identity_credential_authority_validation`.

Step 3. Verifying that the Identity CA issued the remote's |IdentityCert|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

The local |DP| validates the certificate against the Identity CA specified in
the :property:`dds.sec.auth.identity_ca` property (see
:numref:`DDS Security Properties for Configuring Authentication`). If the issuer
of the |IdentityCert| is an intermediate CA, you should specify the full
certificate chain in the :property:`dds.sec.auth.identity_certificate` property.
In this case, the |IdentityCert| will be verified to chain up to the Identity
CA, as specified in :ref:`p2_core/authentication:Identity Certificate Chaining`.

If the Identity CA is not currently valid or cannot validate an |IdentityCert|,
then the validation will be retried with the alternative certificates specified
in the :property:`authentication.alternative_identity_cas` property (see
:numref:`|RTI_SP_PRODUCT_HEADING| Properties for Configuring Authentication`). If
none of the alternative CAs are currently valid and can validate the file (or
if you did not set this property), the validation process will fail.


GUID Validation
---------------

.. note::

  The |SP_BUILTIN| cause a |DP| to have a different GUID than it would normally have.

If a secure |DP| is allowed to have whatever GUID it wants, then it becomes
possible for an attacker to send a storm of participant announcements with
different GUIDs while using its own certificate and private key to successfully
complete the handshakes with the other |DPs| in the domain. Legitimate |DPs|
that have a GUID that the attacker already used will be unable to join the
domain.

To prevent this denial-of-service attack, a |DP| that would have had a certain
GUID when not using the |SP_BUILTIN| (let's call this the "candidate GUID") will have
this GUID adjusted by the |SP_BUILTIN|. This adjusted GUID becomes the GUID that the
|DP| effectively uses for everything, and it is also the GUID that is outputted
by the API ``DDS_DomainParticipant_get_qos`` in the
``wire_protocol.rtps_host_id``, ``wire_protocol.rtps_app_id``, and
``wire_protocol.rtps_instance_id`` fields of the DomainParticipantQos. The
adjustment works as follows:

* The first bit (bit 0) is set to 1.

* The 47 bits following the first bit (bits 1 to 47) are set to the first 47
  bits of the SHA-256 hash of the ASN.1 DER encoding of the subject name
  appearing in the |IdentityCert|.

* The following 48 bits (bits 48 to 95) are set to the first 48 bits of the
  SHA-256 hash of the candidate GUID.

By mixing in a value that depends on the certificate subject name, the
|DP| GUID selection mechanism is protected from duplication or reuse by |DPs|
that cannot authenticate that their identity is indeed that subject name. Thus,
as part of the processing of a Handshake Reply and a Handshake Final, the
receiver checks that the middle 47 bits of the GUID match the hash of the
subject name. If they do not match, then the validation process will fail.

.. warning::

    Do not re-use |IdentityCerts| or their subject names. Configure each |DP|
    with a unique |IdentityCert| that has a distinct subject name.

    The |SP_BUILTIN| derive the adjusted GUID from the subject name. When two
    |DPs| share the same subject name, they are assigned identical adjusted
    GUIDs. This leads the |SP_BUILTIN| to incorrectly identify them as the
    same entity.

Shared Key Derivation
---------------------

As an additional result of the handshake, the two involved participants will
derive a |SharedKey| from the |SharedSecret| and the Challenges in the Handshake
using HMAC operations. The derived |SharedKey| allows the establishment of a
|SecKeyExchangeCh| (also known as |SecKeyExchangeTName|). The |CryptoPlugin|
will use that channel to securely exchange the symmetric keys that the endpoints
need to  communicate securely. After the handshake concludes with successful
authentication and |SharedKey| establishment, symmetric cryptography is used to
exchange other keys (see :ref:`p2_core/cryptography:Secure Key Exchange`).

Diffie-Hellman adds perfect forward secrecy. This implies that an attacker
cannot deduce the |SharedKey|, even if they have access to all the messages
exchanged in the communication and even if the private keys of the participants
were compromised. Moreover, knowing the |SharedKey| for a session does not
provide information about the |SharedKey| of future sessions.

Authentication Builtin Topic (ParticipantStatelessMessage)
==========================================================

To perform the handshake, |DPs| need to exchange directed messages through a unsecure communication channel. For this purpose, the |SEC_SPEC| introduces a new |AuthT|, also known as the |AuthTName| builtin |TOPIC|. This best-effort stateless |TOPIC| prevents the sequence-number prediction vulnerability that is present in unsecure reliable protocols.

The |AuthT| implements the channel that |DPs| need to perform authentication. Data samples exchanged for this |TOPIC| include both the handshake messages (see :ref:`p2_core/authentication:Handshake`) and the re-authentication messages (see :ref:`p2_core/authentication:Re-Authentication`).


Fragmentation Support for the Authentication Topic
--------------------------------------------------

The |RTI_SP_PRODUCT| support fragmenting |AuthT| samples. This is useful in scenarios with a hard limit on the transport maximum message size.

This feature is enabled by default: fragmentation of |AuthT| samples will be triggered when sending samples that exceed the :property:`message_size_max` configured in the transports used by |CONNEXT| (see :link_connext_dds_pro_um:`Setting Builtin Transport Properties with the PropertyQosPolicy in the Core Libraries User's Manual <#users_manual/Setting_Builtin_Transport_Properties_wit.htm?Highlight=message_size_max>`).


Related Governance Rules
========================

This section describes the authentication attributes that appear in the Governance Document.


Domain-level rules
------------------

The following attributes belong inside a :xmltag:`domain_rule`.


allow_unauthenticated_participants (domain_rule)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

This attribute may be :xmlval:`TRUE` or :xmlval:`FALSE`. It controls whether or
not a remote |DP| that either doesn't support security or fails the
authentication handshake is allowed to proceed in trying to communicate with the
local |DP|. Communication with such a |DP| will happen only on the |TOPICs| for
which all of the topic-level rules are set to :xmlval:`FALSE` or :xmlval:`NONE`
(see :ref:`p2_core/elements_dds_secure_system:Topic-Level Rules`).

.. warning::

  If :xmltag:`allow_unauthenticated_participants` is set to :xmlval:`TRUE`,
  :xmltag:`rtps_protection_kind` must be set to :xmlval:`NONE`.

If the value of :xmltag:`allow_unauthenticated_participants` is :xmlval:`TRUE`,
then the local |DP| will still be able to discover remote |SecDPs| with an
incompatible configuration (see
:ref:`p2_core/cryptography:Discovery of a remote Secure Entity`), running an
incompatible set of plugins, or just failing the authentication process. These
|DPs| will be treated as unauthenticated: communication with them will happen
only on the |TOPICs| for which all of the topic-level rules are set to
:xmlval:`FALSE` or :xmlval:`NONE`.

If the local |DP| is communicating with an unauthenticated |DP|, and the local
|DP| has set the
:property:`dds.participant.discovery_config.use_stateless_participant_discovery_reader`
property to :value:`TRUE` (see
:numref:`Properties Affecting Connext DDS Core Libraries Behavior`), then the
local |DP| can potentially discover another |DP| with the same GUID as the
unauthenticated participant. When this discovery happens, the local |DP| will
attempt to authenticate the new |DP|. If this authentication fails or if the
new |DP| does not support security, then the local |DP| will remain in
communication with the old |DP|. If this authentication succeeds, then the
local |DP| will stop communicating with the old |DP| and start communicating
with the new |DP|.

identity_credential_authority_validation
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

This tag controls a domain's policy towards identity credential authority
mechanisms (|OCSP| and |CRL|), provided as its child tags (:xmltag:`ocsp` and
:xmltag:`crl`, respectively). Each mechanism may have a requirement kind value
from this list:

* :value:`REQUIRED`: The mechanism is mandatory. It must be provided [#provision1]_ at
  all times and must be used to validate local and remote certificates.
  If the mechanism is not provided, a |DP| creation will fail, a property/security
  artifact update will be rejected, and, in the case of |OCSP|, a remote |DP| will be
  rejected if it presents a certificate without a :value:`authorityInfoAccess` field
  populated with |OCSPResp| URL or without a valid |OCSPToken|.

* :value:`AUTO` (default): The mechanism, if provided [#provision1]_, will be used for
  certificate validation and, if unsuccessful, it will result in the certificate
  rejection, with all consequences to a |DP| presenting such certificate. With
  this requirement kind, provision of a mechanism is optional and is not mandated.

* :value:`IGNORED`: The mechanism is not used for certificate validation, even if
  it is provided [#provision1]_.

  .. warning::

    Due to internal |SP_BUILTIN| arrangement, ignoring a mechanism works for
    remote |DPs| but not when a |DP| validates its local identity.
    In case of |OCSP|, ignoring it in |GovernanceDoc| does not prevent a |DP| from
    contacting the |OCSPResp| and validating the certificate at startup. See
    :ref:`p2_core/authentication:Online Certificate Status Protocol` for details.
    Ignoring CRLs in the |GovernanceDoc| does not prevent a |DP| creation
    failure if the |CRL| revokes the local |DP|'s |IdentityCert|.

Each mechanism configuration is orthogonal to other mechanism configurations.

An example |GovernanceDoc| snippet that requires |OCSP| and ignores |CRL|:
  .. code-block:: xml

    ...
    <domain_access_rules>
        <domain_rule>
            <domains>
                <id_range>
                    <min>0</min>
                </id_range>
            </domains>
            <allow_unauthenticated_participants>false
                        </allow_unauthenticated_participants>
            <enable_join_access_control>true
                        </enable_join_access_control>
            <identity_credential_authority_validation>
                        <ocsp>REQUIRED</ocsp>
                        <crl>IGNORED</crl>
            </identity_credential_authority_validation>
    ...

.. [#provision1] |CRL| is provided via property and |OCSP| is provided either via |IdentityCert|
  containing :value:`authorityInfoAccess` field including |OCSPResp| URL or via
  :property:`dds.sec.auth.ocsp_responder_uri` property.


Cryptographic Algorithms
========================

The |RTI_SP_PRODUCT| use different cryptographic algorithms for different purposes. Starting
with version 7.0.0, the user can modify and select algorithms supported and used
by |SecEntity|. This section describes the relationship between the digital
signature and key establishment algorithms that can be configured in the
|AuthPlugin|.

In this section, we also describe the relationship between the
algorithms that can be configured in the |AuthPlugin| and the
:link_connext_dds_api_cpp2:`ParticipantTrustAlgorithmInfo::signature
<classrti_1_1topic_1_1trust_1_1ParticipantTrustAlgorithmInfo.html>` and
:link_connext_dds_api_cpp2:`ParticipantTrustAlgorithmInfo::key_establishment
<classrti_1_1topic_1_1trust_1_1ParticipantTrustAlgorithmInfo.html>` fields,
which are used to propagate the used and supported algorithms for a |DP|.
A complete list of values can be found in :numref:`DigitalSignatureBitValues`
and :numref:`KeyEstablishmentBitValues`.

Note that a |SecEntity| may not propagate through discovery the exact list of
algorithms listed in the |GovernanceDoc|. The reason is that the final value
for a supported mask is an intersection of the algorithms allowed by the
|GovernanceDoc| and the list of algorithms supported by the |DP|. Remember that
the |GovernanceDoc| is about system-wide security requirements. Even if the
|GovernanceDoc| allows an algorithm, the implementation of the |RTI_SP_PRODUCT| for a
|DP| may not support it. For example, the |RTI_SP_PRODUCT| for wolfSSL may support different
algorithms than the |RTI_SP_PRODUCT| for OpenSSL.

Finally, this section also defines discovery defaults for every field of the
:link_connext_dds_api_cpp2:`ParticipantBuiltinTopicData::trust_algorithm_info
<classdds_1_1topic_1_1ParticipantBuiltinTopicData.html#aae52b29b4360c249ee6f2a4885d32735>`.
Discovery defaults are the values that are assumed when no value is propagated
through discovery see :ref:`p2_core/cryptography:Discovery of a remote Secure Entity`
for more details about discovery.

Digital Signature Algorithms
----------------------------

Digital Signature Algorithms collect algorithms used in the |DP| trust chain
as well as for authentication. The following algorithms are supported:

* `RSASSA-PSS-MGF1SHA256+2048+SHA256`
* `RSASSA-PKCS1-V1_5+2048+SHA256`
* `ECDSA-P256+SHA256`
* `ECDSA-P384+SHA384`
* `EDDSA+ED25519+SHA512` (<< experimental >>)
* `EDDSA+ED448+SHAKE256` (<< experimental >>)

Digital Signature Algorithms specify four algorithm definitions:

* ``trust_chain.supported_mask``: A list of supported trust chain algorithms.
  The default value is:   `RSASSA-PSS-MGF1SHA256+2048+SHA256` and `ECDSA-P256+SHA256`.
* ``trust_chain.required_mask``: A list of algorithms used in the |DP|'s
  identity trust chain. |IdentityCert| determines which algorithm is used.
  The default value is: `ECDSA-P256+SHA256`.
* ``message_auth.supported_mask``: A list of supported authentication digital
  signature algorithms. The default value is: `RSASSA-PSS-MGF1SHA256+2048+SHA256`
  and `ECDSA-P256+SHA256`.
* ``message_auth.required_mask``: The authentication digital signature algorithm used by a
  |DP|. |IdentityCert| determines which algorithm is used.
  The default value is: `ECDSA-P256+SHA256`.

.. note::

   The ``trust_chain.supported_mask`` are the list of digital signature
   algorithms supported by the |DP| in the context of creating a chain of trust.
   This means that they are the algorithms used for verifying the |IdentityCert|
   against the Identity Certificate Authority. The |SP_BUILTIN| enforce during
   validation of the remote |IdentityCert| chain that the actual used digital
   signature algorithms are supported.

   The ``message_auth.supported_mask`` are the list of digital signature algorithms
   supported by the |DP| for checking that the remote |DP| is authentic.
   These are the algorithms that a |DP| supports for challenging a remote |DP|
   to prove that it has the |PrivateKey| corresponding to its |IdentityCert|.

Key Establishment Algorithms
----------------------------

Key Establishment Algorithms collect algorithms used in key establishment during
|DP| authentications. The following algorithms are supported:

* `DHE+MODP-2048-256`
* `ECDHE-CEUM+P256`
* `ECDHE-CEUM+P384`
* `ECDHE-CEUM+X25519` (<< experimental >>)
* `ECDHE-CEUM+X448` (<< experimental >>)

Key Establishment Algorithms specify two algorithm definitions:

* ``supported_mask``: A list of supported key establishment algorithms.
  The default value is: `DHE+MODP-2048-256` and `ECDHE-CEUM+P256`.
* ``required_mask``: Indicates the algorithm the |DP| will use as the key
  establishment algorithm  if the |DP| is the authentication initiator
  (if not, the algorithm of the other |DP| will be used). It is determined
  by `dds.sec.auth.key_establishment_algorithm` property (see
  :numref:`|RTI_SP_PRODUCT_HEADING| Properties for Configuring Cryptography`).
  The default value is: `ECDHE-CEUM+P256`.

See :ref:`p2_core/cryptography:allowed_security_algorithms (domain_rule)` to
learn how to configure which of these algorithms are supported.

Advanced Authentication Concepts
================================

Protecting Participant Discovery
--------------------------------

|DP_disc| is sent through an unsecure channel. Consequently, additional
mechanisms need to be put in place to make sure the received information comes
from a legitimate participant. In the |SP_BUILTIN|, the mechanism for
protecting the |DP_disc| information is known as TrustedState.

|RTI_SP_PRODUCT| TrustedState is an RTI extension to the DDS Security Authentication specification that covers two limitations in the |SEC_SPEC|:

* The lack of a standardized mechanism for validating that the |DP_disc| information received by DDS actually matches the information of the authenticated remote |DP|.
* |DP_disc| data is immutable after authentication. This prevents functionality such as updating IP addresses. (Only a limitation in DDS Security 1.0, resolved in 1.1.).

|RTI_SP_PRODUCT| TrustedState is a digest of the |DP_disc| data, plus information that unambiguously identifies the current local participant state and the current authentication session. TrustedState is exchanged as part of the authentication process as a vendor extension. More specifically, TrustedState is included as a binary property in the |HS_REP| and |HS_FIN| messages. Once the authentication completes, involved participants will validate received |DP_disc| information against the received TrustedState. This way, participants can be sure that the received |DP_disc| comes from the authenticated participant.

The |DP_disc| channel is also used to propagate changes in the |DP|'s QoS or in
the locators. In order to securely propagate |DP_disc| changes after
authenticating the remote participant, the |SP_BUILTIN| use the participant's identity
private key to sign the |DP_disc| data plus some additional information
identifying the local participant state (and which is consistent with the one
serialized in the TrustedState). This signature is then serialized as a property
in the |DP_disc| data. This way, other participants can validate that the update
is legitimate by verifying the received |DP_disc| against the participant's
public key.

Please note that in DDS Security 1.0 (which |CONNEXT| 5.3.x implements), the DomainParticipantQos for remote |DPs| is immutable. To overcome this limitation, 5.3.x uses the TrustedState extension. Non-RTI participants do not implement TrustedState; therefore, they cannot update DomainParticipantQos Discovery information after authentication. This limitation is solved by DDS Security 1.1, which is adopted in |CONNEXT| 6.0.0+.

To increase compatibility with other vendors, |SecDPs| that use the |RTI_SP_PRODUCT| will successfully authenticate remote participants that do not provide TrustedState. Non-RTI participants should ignore the TrustedState property in the Handshake since it is a vendor extension.

.. caution::

  The TrustedState mechanism is disabled when |PSKProtection| is enabled.
  Participant announcements are protected with symmetric cryptography
  and there is no need for TrustedState. For details, see
  :ref:`p3_advanced/pre-shared_key:|PSKProtection| and the cloud`.


Identity Certificate Chaining
-----------------------------

This section assumes you are familiar with the concept of a Certificate Chain, as described in  :ref:`p2_core/elements_dds_secure_system:Public Key Infrastructure (PKI)`.

You may specify a certificate chain in the :property:`dds.sec.auth.identity_certificate` property (see :numref:`DDS Security Properties for Configuring Authentication`). You can create the certificate chain by concatenating individual certificates and specifying the concatenated result as a single file or string. The local |IdentityCert| will be verified before creating the local |DP|. It will also be sent on the network as part of the handshake. If a certificate chain is specified, then the whole chain will be sent on the network, which may cause significant overhead.

To avoid additional overhead, beginning in |CONNEXT| version 6.1.0, the human-readable part of |IdentityCerts| is stripped by default when the certificate is loaded. You can control this behavior with the :property:`authentication.propagate_simplified_identity_certificate` property (see :numref:`|RTI_SP_PRODUCT_HEADING| Properties for Configuring Authentication`).

The CRLs specified in the :property:`authentication.crl` property will be used
throughout the verification process (see
:numref:`|RTI_SP_PRODUCT_HEADING| Properties for Configuring Authentication`).
This property may contain any number of CRLs, each one signed by either the
Identity CA (:property:`dds.sec.auth.identity_ca`), one of the alternative CAs
(:property:`authentication.alternative_identity_cas`), or one of the
intermediate CAs in the |IdentityCert| chain.

The |IdentityCert| will be verified against the Identity CA using the following procedure:

#. The current certificate is the first certificate in the |IdentityCert| chain.

#. Check that the current certificate is valid for the current date. Otherwise, the verification fails immediately.

#. If the current certificate is signed and unrevoked by the Identity CA
   (:property:`dds.sec.auth.identity_ca`) or any of the alternative CAs listed
   in :property:`authentication.alternative_identity_cas`, then the verification
   succeeds immediately. Otherwise:

#. If a next certificate exists in the chain and the current certificate is
   signed and unrevoked by that next certificate, then the next certificate
   becomes the current certificate.

If none of the certificates in the |IdentityCert| chain lead to the Identity CA (or any of the alternative Identity CAs), then the verification fails. For details on certificate validation, see :ref:`p2_core/authentication:Identity Certificate Validation`.


Re-Authentication
-----------------

The |RTI_SP_PRODUCT| support securely re-authenticating remote participants as described in
the |SEC_SPEC|. This is needed in scenarios where there is an
asymmetric liveliness loss.

As depicted in :numref:`figure-re-authentication`, asymmetric liveliness loss
occurs between two participants, |P1| and |P2|, when |P1| loses liveliness
with |P2|. When this happens, |P1| cleans up all the associated states,
while |P2| still keeps the authenticated state. Because |P2| keeps an
authenticated state from |P1|, it will not accept new authentication messages
from |P1|. Without the ability to re-authenticate, asymmetric liveliness loss
will lead to communication not recovering. The same occurs in the case of an
asymmetric authentication failure. The |SP_BUILTIN| address this problem by including
a re-authentication capability as described in the |SEC_SPEC|.

If |P1| has not completed an ongoing authentication with |P2| after a specific
period, it will send an |AuthReq| (``dds.sec.auth_request``) message that
includes a nonce to |P2|. This message will give a hint to |P2| that |P1| is
pending authentication with |P2|. This specific period is configured by the
property :property:`dds.participant.trust_plugins.authentication_request_delay.sec`,
see :numref:`Properties for Configuring Authentication Affecting Any
Authentication Plugin`.

When |P2| receives an |AuthReq| message, it will check if it already has a valid
completed authentication with |P1|. If so, that could mean that an asymmetric
liveliness loss has occurred. To verify that the |AuthReq| is legitimate, the
two participants will now conduct a whole authentication process that includes
the nonce received as part of the triggering ``dds.sec.auth_request`` message.
Only if this secondary authentication succeeds, the old state will be removed
in |P2| and replaced with the new one, allowing discovery to complete again and
communication to recover. If this secondary authentication fails (this is,
if |P2| triggers the timeout configured through the
:property:`dds.participant.trust_plugins.authentication_request_timeout.sec`
property), no change will be made in |P2| and the old authenticated session will
be kept.

Because the old authenticated state is kept until the new authentication has
successfully completed, the |SP_BUILTIN| re-authentication is robust against attackers
trying to bring down an existing authentication.

.. figure:: ../static/re-authentication.png
  :scale: 50%
  :alt:
  :name: figure-re-authentication
  :align: center

  Messages Exchanged During the Re-Authentication Process

.. note::

   When running |SP_BUILTIN| in constrained devices, or when the number of total
   |DPs| simultaneously created under the same Domain is high, you may get the
   following error during system startup for a subset of the ongoing
   authentications: :property:`failed to verify challenge signature`.
   This error could trigger as a result of inadequate configuration of the
   authentication process for the system size, leading to mismatched
   authentication processes between |DP| pairs.
   When this error triggers, it will generate unnecessary CPU
   load and network traffic overhead. See section
   :ref:`p2_core/authentication:Guidelines for Minimizing Authentication Negotiation Times`
   for a set of guidelines for minimizing authentication negotiation times.

Guidelines for Minimizing Authentication Negotiation Times
----------------------------------------------------------
To minimize authentication negotiation times during system startup, follow these
guidelines:

* Set :property:`dds.participant.trust_plugins.authentication_timeout.sec` to a
  value that is twice the time it takes to authenticate all of the |DPs|
  during the system startup. A too short value will trigger additional
  authentication negotiations, generating additional CPU load and network traffic,
  and generally slowing down the system startup.
* Set :property:`dds.participant.trust_plugins.authentication_request_delay.sec`
  to a value that is higher than the time it takes to authenticate all of the
  |DPs| during the system startup. A too short value will generate additional
  traffic and potentially additional unnecessary authentication negotiations.
* Set :property:`dds.participant.trust_plugins.authentication_request_timeout.sec`
  to the average time it takes to authenticate a |DP| in your system at startup.
* Make sure that the sum of the configured values for
  :property:`dds.participant.trust_plugins.authentication_request_delay.sec` and
  :property:`dds.participant.trust_plugins.authentication_request_timeout.sec`
  is lower than the
  :property:`dds.participant.trust_plugins.authentication_timeout.sec`.

Dynamic Certificate Revalidation
--------------------------------

A valid |IdentityCert| or Identity CA may not stay valid forever. When one of
them becomes invalid, the |SP_BUILTIN| should take appropriate action on the
corresponding |DP|. Currently, the |SP_BUILTIN| support taking actions based on
the certificate's expiration time (the *Not After* X.509 Validity field),
presence in a CRL, and through |OCSP|. The actions differ between remote |DPs| and
the local |DP|.

Dynamic Certificate Expiration of Remote |DPs|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

If the |IdentityCert| of a remote |DP| is successfully validated during
handshaking (see :ref:`p2_core/authentication:Identity Certificate Validation`),
the |RTI_SP_PRODUCT| note the earliest expiration time among the chain of
certificates that were involved in the validation. At that time,
the |RTI_SP_PRODUCT| performs the
:ref:`p2_core/authentication:Identity Certificate Validation` steps again. If
this revalidation fails, then the |RTI_SP_PRODUCT| will remove the remote |DP|.
Note that the remote |DP| is only removed, not ignored, so it will be allowed to
rejoin the system if it can be recreated with the same GUID and with a valid
|IdentityCert|. If the property
:property:`dds.participant.trust_plugins.key_revision_max_history_depth` is set
to a value other than :value:`0`, then the |RTI_SP_PRODUCT| will also create
a new |KeyRevision| (see
:ref:`p2_core/cryptography:Limiting the Usage of Specific Key Material`) in
order to render the remote |DP|'s Key Material outdated. If this property is
unset or set to :value:`0`, then the |RTI_SP_PRODUCT| will generate this log
message at the :value:`SECURITY` category and the :value:`WARNING` verbosity:

.. code-block:: text

  Precondition not met because the participant has not enabled key regeneration using the "dds.participant.trust_plugins.key_revision_max_history_depth" property. You must enable this property to prevent removed or ignored participants from reading your encrypted data or writing data that looks like it came from you!!!

Dynamic Certificate Expiration of the Local |DP|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

If the |IdentityCert| of the local |DP| is successfully validated during |DP|
creation, and the local |DP| is configured with a *DomainParticipantListener*
and a *StatusMask* that includes
:link_connext_dds_api_cpp2:`INVALID_LOCAL_ADVANCE_NOTICE_STATUS
<classrti_1_1core_1_1status_1_1InvalidLocalAdvanceNoticeStatus.html>`, then
the |SP_BUILTIN| note the earliest expiration time among the chain of certificates that
were involved in the validation. The |SP_BUILTIN| subtract the value of the
:property:`dds.participant.trust_plugins.expiration_advance_notice_duration.sec`
property from that earliest expiration time. At that notification time,
the |SP_BUILTIN| perform the :ref:`p2_core/authentication:Identity Certificate Validation`
steps again for the local |DP|. If this revalidation determines that a
certificate has already expired or will expire within the advance notice
duration, then the |RTI_SP_PRODUCT| will notify the user by invoking the
:link_connext_dds_api_cpp2:`on_invalid_local_status_advance_notice<classdds_1_1domain_1_1DomainParticipantListener.html>`
callback function. After the first notification, the |RTI_SP_PRODUCT| will continue
notifying the user at a configurable period until the certificate chain has
finally expired. The property for configuring this period is
:property:`dds.participant.trust_plugins.expiration_advance_notice_reminder_period.sec`.

Dynamic Certificate Revocation of Remote |DPs|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

If the |IdentityCert| of a remote |DP| does not appear in the local |DP|'s CRL
when the remote |DP| is first discovered, it's still possible for the
|IdentityCert| to appear in the CRL later. The CRL is mutable in two ways:

* Changing the value of the :property:`authentication.crl` property using the
  |DP| ``set_qos`` API. If the new CRL is invalid, then ``set_qos`` will return
  DDS_RETCODE_ERROR, and the old CRL, if it exists, will remain in use.
* Leaving the value of the :property:`authentication.crl` property unchanged
  and instead changing the contents of the actual CRL file. The |SP_BUILTIN| enforce
  these changes as long as :value:`file:` is the prefix of the property value
  and :property:`files_poll_interval` is set to a value other than :value:`0`.
  In this case, the |RTI_SP_PRODUCT| use a separate thread dedicated to
  periodically checking if any of the following have occurred:

  * The CRL file has been deleted.
  * The CRL file modification timestamp has changed.
  * The MD5 hash of the file contents has changed.

  If any of those events have occurred, then the |SP_BUILTIN| will reload the CRL file.
  If the reloaded CRL is invalid or if the CRL file is actually deleted, then
  the previous version of the CRL will remain in use.

As soon as a CRL change is detected, the |RTI_SP_PRODUCT| will remove any newly revoked
remote |DPs|. Note that the |DPs| are removed but not ignored. So if a later
CRL change results in any remote |DPs| becoming unrevoked, then communication
with those |DPs| will resume after any in-progress authentications are timed
out (the timeout is configurable using the property
:property:`dds.participant.trust_plugins.authentication_timeout.sec`) and after
the local |DP| receives participant announcements from the remote |DPs| (the
announcement period is configurable using the field
:property:`DomainParticipantQos::discovery_config::participant_announcement_period`).
If the property
:property:`dds.participant.trust_plugins.key_revision_max_history_depth` is set
to a value other than :value:`0`, then the |SP_BUILTIN| will also create a new
|KeyRevision| (see
:ref:`p2_core/cryptography:Limiting the Usage of Specific Key Material`) in
order to render the remote |DP|'s Key Material outdated. If this property is
unset or set to :value:`0`, then the |SP_BUILTIN| will generate the same log message as
the one described in
:ref:`p2_core/authentication:Dynamic Certificate Expiration of Remote |DPs|`.

Of course, you may combine these two ways of mutability. For example, you may
change the CRL filename from ``one.crl`` to ``two.crl``, change the value of
:property:`authentication.crl` from ``file:one.crl`` to ``file:two.crl``, and
change the contents of ``file:two.crl``.

Dynamic Certificate Revocation of Local |DPs|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Creation of the local |DP| will fail with DDS_RETCODE_ERROR if its
|IdentityCert| appears in the CRL.
However, even if the |IdentityCert| of the local |DP| is not in the CRL upon
|DP| creation, it's still possible for the |IdentityCert| to appear in the CRL
later. This is because the CRL is mutable, as described in
:ref:`p2_core/authentication:Dynamic Certificate Revocation of Remote |DPs|`.

The |RTI_SP_PRODUCT| will detect a change in either the CRL contents (when
:property:`files_poll_interval` is set to a value other than :value:`0`) or in
the value of the :property:`authentication.crl` property itself (through the
|DP| ``set_qos`` API). If the new value is invalid, then the |SP_BUILTIN| will keep using
the previous version of the CRL. If the new value is valid, then the |SP_BUILTIN| will
update the CRL.

The ``set_qos`` API returns DDS_RETCODE_ERROR if the new CRL value is invalid.
Otherwise, the ``set_qos`` API returns DDS_RETCODE_OK. This return code is
independent of whether the |IdentityCert| of the local |DP| appears in the
updated CRL or not.


When the |IdentityCert| of the local |DP| appears in the updated CRL, then the
|SP_BUILTIN| will log an exception message due to a change in the security status. In
particular, the message indicates that the |IdentityCert| of the local |DP| has
been revoked.

Dynamic Certificate Revocation of Remote |DPs| through Whitelisting
-------------------------------------------------------------------
The |SP_BUILTIN| support defining a whitelist of allowed subject names (enabled when
:property:`dds.participant.trust_plugins.subject_name_whitelist` is set).
This whitelist provides a way to dynamically allow/deny access to
|DPs| into a domain.

The whitelist configures a set of (semicolon-separated) allowed subject names
for authenticated |DPs|. If set (even if empty), authenticated |DPs| will be
allowed into the system only if their subject name matches one of the ones in
the whitelist.

Any authenticated |DP| not matching the whitelist will be ignored
automatically upon authentication completion, before it has access to any
secure topic data. The whitelist has no effect on intraparticipant
communication: a |DP| will always be able to communicate with itself
independently of the contents of the whitelist.

.. warning::

    The subject names in the whitelist must be **exactly** as returned in the
    ``Subject`` field by the following |OpenSSL| command:

    .. code-block:: console

        $ openssl x509 -in <certificate> -text -nameopt sep_comma_plus_space,sname,esc_2253
    
    where ``<certificate>`` is the path to the certificate file. Changing the
    order of the attributes is not allowed.

Interactions with allow_unauthenticated_participants
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Since the whitelist is enforced only on authenticated |DPs|, this property does
not impact allowed non-authenticated |DPs|: if
:xmltag:`allow_unauthenticated_participants` is set to :xmlval:`TRUE`, |DPs| not
using security and |DPs| failing authentication early will still be allowed into
the system.

Whitelist mutability
^^^^^^^^^^^^^^^^^^^^
The whitelist allows for dynamic changes in the set of allowed subject names
without restarting the local |DP|. If the list is modified once the |DP| is
enabled, any previously ignored |DP| will be unignored, which will create an
opportunity to successfully authenticate if it is now part of the updated
whitelist (if not, the |DP| will be ignored as usual). The new authentication
will happen after the local |DP| receives a participant announcement from the
remote |DP| (the announcement period is configurable using the field
:property:`DomainParticipantQos::discovery_config::participant_announcement_period`).
Additionally, any previously trusted |DP| that becomes ignored as a result of a
whitelist update will trigger an immediate key regeneration as long as key
regeneration is enabled through the
"dds.participant.trust_plugins.key_revision_max_history_depth" property.

Interactions with ignore_participant API
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|CONNEXT| keeps the state about whitelist-based ignored |DPs| independent from
the state about the |DPs| ignored through a call to the
:property:`ignore_participant` method. Consequently, |DPs| ignored through the
:property:`ignore_participant` method will remain ignored independently of the
whitelist configuration.

Still, whitelist-based ignored |DPs| still count towards the limit set by the
:property:`ignored_entity_allocation` resource limit.

Whitelist format
^^^^^^^^^^^^^^^^
The whitelist expects a set of subject names separated by the semicolon ';'
character. In order to evaluate a |DP|'s subject name as a match against the
list, one of the elements in the list must be evaluated as equal (based on the
result of :property:`strcmp`) against the subject name returned by a call to
:property:`DDS_DomainParticipant_get_discovered_participant_subject_name` for
that |DP|'s :property:`InstanceHandle`.

Whitelist elements are tokenized based on the semicolon ';' delimiter character.
Any whitespace, including whitespace around the semicolons, will be considered
part of the subject names.
If any of the subject names in the list uses a semicolon, you need to escape
this character by adding `\\` before it. Example:

- ``C=US, ST=CA, O=Real Time Innovations\; CN=as one, CN=RTI ECDSA01\; (p256) PEER11, emailAddress=ecdsa01\;Peer\,11@rti.com``

CRL Expiration
--------------
It is possible for a CRL to expire if it is still being used by the time the
value of its ``Next Update`` field (see https://www.ietf.org/rfc/rfc5280.txt)
is reached. When a CRL expires, the behavior is as follows:

* For any |DPs| that are discovered **after** the CRL expires, if the |DP|
  Identity Certificate chain includes a certificate that is signed by the same
  CA that signed the CRL, then the |DP| will fail authentication and be
  rejected. It doesn't matter if the |DP|'s certificate does not appear in the
  CRL. If checking the CRL is required for checking the certificate's validity
  and the CRL is expired, then the |SP_BUILTIN| will assume that the certificate is
  invalid.
* For any |DPs| that are discovered **before** the CRL expires, the |SP_BUILTIN| do
  nothing. The |SP_BUILTIN| do not retroactively reject any previously discovered |DP|
  whose Identity Certificate was signed by the same CA that signed the CRL. If
  a |DP| changes its Identity Certificate and checking the certificate's
  validity requires checking the expired CRL, then the |SP_BUILTIN| will reject the new
  certificate and continue using the old one without ceasing communication with
  the |DP|. If a |DP|'s Identity Certificate expires, then communication will
  still cease as described in
  :ref:`p2_core/authentication:Dynamic Certificate Expiration of Remote |DPs|`.

Dynamic Certificate Renewal of a |DP|
-------------------------------------
When you get notified in advance that your |IdentityCert| is about to expire
(see
:ref:`p2_core/authentication:Dynamic Certificate Expiration of the Local |DP|`),
you may want to update your |IdentityCert| to have a later expiration date.
Currently, the |SP_BUILTIN| supports updating the local |DP|'s |IdentityCert| (but not
its Identity CA) without deleting and recreating the local |DP|. The
|IdentityCert| is mutable in two ways, as long as the
public key and subject name of the leaf certificate (the first certificate in
the chain) remain the same and the digital signature algorithms are allowed
according to
:ref:`p2_core/cryptography:allowed_security_algorithms (domain_rule)` in the
|GovernanceDoc|:

* Changing the value of the :property:`dds.sec.auth.identity_certificate`
  property using the |DP| ``set_qos`` API. If the new |IdentityCert| is
  invalid, then ``set_qos`` will return DDS_RETCODE_ERROR. If the new
  |IdentityCert| violates the aforementioned mutability restrictions, then
  ``set_qos`` will return DDS_RETCODE_NOT_ALLOWED_BY_SECURITY. If
  ``set_qos`` returns a value other than DDS_RETCODE_OK, then the old
  |IdentityCert| will remain in use.
* Leaving the value of the :property:`dds.sec.auth.identity_certificate`
  property unchanged and instead changing the contents of the actual
  |IdentityCert| file. The |SP_BUILTIN| enforce these changes as long as :value:`file:`
  is the prefix of the property value and :property:`files_poll_interval` is
  set to a value other than :value:`0`. In this case, the |RTI_SP_PRODUCT| use a
  separate thread dedicated to periodically checking if any of the following
  have occurred:

  * The |IdentityCert| file has been deleted.
  * The |IdentityCert| file modification timestamp has changed.
  * The MD5 hash of the |IdentityCert| file contents has changed.

  If any of those events have occurred, then the |SP_BUILTIN| will reload the
  |IdentityCert| file.
  If the reloaded |IdentityCert| is invalid or if the
  |IdentityCert| file is actually deleted, then the previous version of
  the |IdentityCert| will remain in use. If the reloaded |IdentityCert| does
  not have any changes in the section between ``-----BEGIN CERTIFICATE-----``
  and ``-----END CERTIFICATE-----``, then no further action is taken.

Once the |SP_BUILTIN| detect that you have successfully updated your |IdentityCert| to
a different one, the |SP_BUILTIN| will propagate your new |IdentityCert| to other |DPs|
via the |SecKeyExchangeCh|. The remote |DPs| will try to validate your new
|IdentityCert|. If this validation is successful for a remote |DP|, then the
remote |DP| will recognize the expiration time of your new |IdentityCert|, and
communication with the remote |DP| will not stop when your old |IdentityCert|
expires. If, for some reason, this validation is unsuccessful for a remote
|DP|, then the remote |DP| will treat you as if you are still using your old
|IdentityCert|, and you can expect communication with the remote |DP| to cease
once your old |IdentityCert| expires. Notice that this |IdentityCert| renewal
process does not involve a whole new handshake because since the public key is
immutable, you do not have to prove again that you have the corresponding
private key, and since the subject name is also immutable, you do not have to
use a new |PermissionsDoc|. If you update your |IdentityCert| while you are in
the middle of an authentication handshake with a remote |DP|, then you will
finish the handshake using your old |IdentityCert| and then send your new
|IdentityCert| to the remote |DP| once the |SecKeyExchangeCh| has been
established with the remote |DP|.

Online Certificate Status Protocol
----------------------------------

|OCSP| is a standard that provides a way to determine the current status of a
given certificate. It is achieved by request-reply communication provided by an
external server, called the |OCSPResp|. By default, the responder can be reached
at the URL provided in the given |IdentityCert| [#responderCert1]_, or at the
URL provided via the :property:`dds.sec.auth.ocsp_responder_uri` property. Any
entity interested in validating the status of the |IdentityCert| can contact the
|OCSPResp|, or validate the |OCSPToken| associated with the certificate. The
|OCSPToken| is issued by the responder and can be forwarded to interested
parties as a proof of validity. With the stapling token, there is no need to
contact the |OCSPResp| every time the |IdentityCert| needs to be validated; the
token can be examined instead to determine the validity.

The |SP_BUILTIN| use the |OCSPToken|. It is maintained by the |DP| whose
|IdentityCert| contains an :value:`authorityInfoAccess` field populated with the
|OCSPResp| URL. This |DP| is responsible for obtaining an |OCSPToken|
corresponding to its |IdentityCert| at startup and then propagating it to its
peers during authentication. The |DP| is also responsible for renewing its token
before expiration (before the :value:`nextUpdate` time is reached) and
propagating its updated version to all matched peers. Other |DPs| validate the
identity of this |DP| by checking the stapling token. Based on this information,
|DPs| can determine if a given certificate is valid or revoked and take action
upon it.

.. warning::

  An |OCSPToken| can be time-bounded by the token's :value:`nextUpdate` field.
  The |OCSPToken|'s :value:`nextUpdate` field is optional in the standard (see
  `RFC 6960, section 2.4 <https://datatracker.ietf.org/doc/html/rfc6960#section-2.4>`_),
  permitting it to be absent. However, the |SP_BUILTIN| mandate the presence of
  this field and its correct value. Without this field and value, the |OCSP|
  response will be rejected and lead to a failed identity validation. The
  |SP_BUILTIN| require the :value:`nextUpdate` field in the response because
  they interpret it as the |OCSPToken| expiration time. An |OCSPToken| that
  doesn't expire defeats the purpose of the |OCSP| mechanism, which is based on
  periodic updates of the |IdentityCert| status. You are responsible for
  ensuring that the |OCSPResps| listed in the :value:`authorityInfoAccess`
  fields of all |IdentityCerts| produce acceptable responses at all times.

By default, |OCSP| is leveraged whenever the certificate includes a :value:`authorityInfoAccess`
field containing an |OCSPResp| URL. The user is responsible for setting up
the |OCSPResp| and maintaining it. An exhaustive discussion about it is beyond
the scope of this document. You may consult :ref:`p3_advanced/design_considerations:Considerations when Enabling OCSP`
for a selection of relevant considerations when setting up an |OCSP|-enabled |CONNEXT| system.

Optionally, the |OCSPResp| URL can be provided via the
:property:`dds.sec.auth.ocsp_responder_uri` property. The URL provided via this
property prevails over the one read from the |IdentityCert|'s
:value:`authorityInfoAccess` field. The Responder itself must meet the same
requirements—that is, use a certificate signed by the same CA as the |DP|'s |IdentityCert| and
include the :value:`nextUpdate` field in its responses. You can use this property for a variety
of purposes, such as retrofitting existing certificates with the :value:`authorityInfoAccess`
field not containing the |OCSPResp| URL (without a need to regenerate the certificate), or
overriding the existing :value:`authorityInfoAccess`'s |OCSPResp| URL value with a different URL.
Note that the change of an existing URL can be done more efficiently on a network level,
and using the property for this use case is a secondary option if the primary option is
infeasible.

|OCSP| can be optionally configured both in the |GovernanceDoc| and via properties.
The |GovernanceDoc| dictates the use of |OCSP| on a domain level via :xmltag:`identity_credential_authority_validation`
and its child tag :xmltag:`ocsp`. There are three possible values:

* :value:`REQUIRED`: Use of |OCSP| is mandated in this domain. Every |DP|
  attempting to join the |Domain| must present a valid |OCSPToken| matching its
  |IdentityCert|. Local |DP| creation will fail if the |IdentityCert| does not
  contain the :value:`authorityInfoAccess` field including an |OCSPResp| URL,
  and the :property:`dds.sec.auth.ocsp_responder_uri` is not set. Local |DP|
  creation will also fail if the |DP| is unable to obtain a valid |OCSPToken|
  from the |OCSPResp|. In addition, an update of the |IdentityCert| will be
  rejected if the new certificate doesn't have the :value:`authorityInfoAccess`
  extension indicating |OCSP| (and the
  :property:`dds.sec.auth.ocsp_responder_uri` is not set). Remote |DPs| must
  also present an |OCSPToken| matching its |IdentityCert| during authentication,
  or the validation will fail and this |DP| will not be allowed in.

* :value:`AUTO` (default): |OCSP| can be used but it is not mandated. If an
  |IdentityCert| with a populated |OCSPResp| URL is presented, it will be
  validated by the |OCSPResp| and the validation must be successful. If the
  |OCSP| response is negative or the |OCSPResp| is not reachable, the
  |IdentityCert| will be rejected, resulting in failure to create the
  |DP| or failed authentication.

* :value:`IGNORED`: |OCSP| is not used in certificate validation, even if the
  |IdentityCert|'s :value:`authorityInfoAccess` field has an |OCSPResp| URL,
  the :property:`dds.sec.auth.ocsp_responder_uri` property is configured,
  or the |OCSPToken| is presented.

.. warning::

  Due to internal |SP_BUILTIN| arrangement, if the |GovernanceDoc| ignores |OCSP| but a
  certificate's :value:`authorityInfoAccess` field is populated with an |OCSPResp| URL, the |DP| will
  still attempt to contact the Responder at the URL provided on startup; |DP| creation
  may fail if the Responder cannot be reached. If you are ignoring |OCSP| in your system,
  also make sure that |OCSPResp| URL is not listed in the :value:`authorityInfoAccess` field in any
  certificates. You may also set the :property:`authentication.ocsp_ignored` property
  to :value:`TRUE`; this will prevent the |DP| from contacting the |OCSPResp| on startup.

The |GovernanceDoc| snippet below mandates |OCSP| use in the system:

  .. code-block:: xml

    ...
    <domain_access_rules>
        <domain_rule>
            <domains>
                <id_range>
                    <min>0</min>
                </id_range>
            </domains>
            <allow_unauthenticated_participants>false
                        </allow_unauthenticated_participants>
            <enable_join_access_control>true
                        </enable_join_access_control>
            <identity_credential_authority_validation>
                        <ocsp>REQUIRED</ocsp>
            </identity_credential_authority_validation>
    ...

|DP| properties associated with |OCSP| are:

 * :property:`certificate_status_advance_update_duration` (default value :value:`60 seconds`):
   Controls how much time in advance (with respect to :value:`nextUpdate` field
   of the current |OCSP| response) the local |DP| is going to start querying its
   responder for a new token.

 * :property:`dds.sec.auth.ocsp_responder_uri` (not set by default):
   You can configure an alternative |OCSPResp| URL by using this property.
   The URL provided in this property prevails over the one read from the
   |IdentityCert|'s :value:`authorityInfoAccess` extension.

   This property is not mutable.

 * :property:`authentication.ocsp_ignored` (default value: :value:`FALSE`):
   A boolean setting that allows you to completely disable all |OCSP|-related
   functionality.

   This property is useful for debugging issues involving |OCSP|. If it is set
   to :value:`TRUE`, it supersedes the |GovernanceDoc|'s :xmltag:`ocsp` element.
   If it is :value:`FALSE`, the |GovernanceDoc| value prevails.

  .. warning::

    This property affects only a local |DP|, where it is set. Other |DPs| work
    according to their local configuration and the |GovernanceDoc|. You may
    encounter interoperability issues if the |GovernanceDoc| requires |OCSP| or
    your |IdentityCert| has an :value:`authorityInfoAccess` element including
    an |OCSPResp| URL.

Consult :ref:`p2_core/authentication:Properties for Configuring Authentication` for details
about these properties.

.. note::

  The |OCSPResp| provided in the certificate must be reachable at the URL at |DP| startup and
  for consecutive stapling token renewal. If the Responder is not available, the |DP| creation
  will fail. If the |OCSPResp| is not available for renewal, other |DPs| may start treating
  the given identity as revoked and subsequently banish it.

For more design considerations for |OCSP|-enabled systems, consult
:ref:`p3_advanced/design_considerations:Considerations when Enabling OCSP`.

.. [#responderCert1] The |OCSPResp|'s certificate must be signed by the same Certificate
  Authority (either root or intermediate) that signed the |DP|'s |IdentityCert|.


Properties for Configuring Authentication
=========================================

:numref:`DDS Security Properties for Configuring Authentication` and :numref:`|RTI_SP_PRODUCT_HEADING| Properties for Configuring Authentication` list the properties that you can set for authentication. These properties are configured through the |DP|'s PROPERTY QosPolicy (see :ref:`section-sp-properties`).

.. list-table:: DDS Security Properties for Configuring Authentication
  :name: DDS Security Properties for Configuring Authentication
  :widths: 40 60
  :header-rows: 1
  :class: longtable

  * - Property Name
    - Property Value Description

  * - :property:`dds.sec.auth.identity_ca`
    - :req:`Required`

      Identity CA certificate. This certificate is used for verifying the |IdentityCerts| of local and remote |DPs| (see :ref:`p2_core/elements_dds_secure_system:Public Key Infrastructure (PKI)`).

      Two participants that want to securely communicate with each other must use the same Identity CA.

      You may specify either the file name or the document contents. See the note below for details.

      :type:`String`.

      Default: :value:`NULL`

  * - :property:`dds.sec.auth.private_key`
    - :req:`Required`

      The private key associated with the first certificate that appears in
      :property:`identity_certificate`.

      You may specify either the file name or the document contents. See the
      note below for details.

      :type:`String`.

      Default: :value:`NULL`

  * - :property:`dds.sec.auth.identity_certificate`
    - :req:`Required`

      |IdentityCert| signed by the Identity CA. Other participants will request
      this certificate to verify the identity of the local participant. This is
      an X.509 certificate in PEM format.

      You may put a chain of certificates in the |IdentityCert| by concatenating
      individual certificates and specifying the concatenated result as a single
      file or string. See
      :ref:`p2_core/authentication:Identity Certificate Chaining` and
      :ref:`p2_core/elements_dds_secure_system:Public Key Infrastructure (PKI)`.

      Notes:
        * For better security, it is recommended, but not required, that
          different participants have different Common Names.
        * You may specify either the file name or the document contents. See the
          note below for details.

      This property is mutable through the |DP| ``set_qos`` API as long as the
      public key and subject name remain the same and the digital signature
      algorithms are allowed according to
      :ref:`p2_core/cryptography:allowed_security_algorithms (domain_rule)` in
      the |GovernanceDoc|. In addition, changes in the |IdentityCert| will be
      enforced if :property:`files_poll_interval` is set to a value other than
      :value:`0`. If you want to be able to update your |IdentityCert|, you must
      ensure :ref:`p2_core/cryptography:enable_key_revision (domain_rule)`
      is set to :xmlval:`true` (the default value) in your system.
      :type:`String`.

      Default: :value:`NULL`

  * - :property:`dds.sec.auth.ocsp_responder_uri`
    - :req:`Optional`

      You can set an alternative |OCSPResp| URL by using this property.
      The URL provided in this property prevails over the one read from the
      |IdentityCert|'s :value:`authorityInfoAccess` extension. You can use this
      property for a variety of purposes, e.g., retrofitting existing certificates
      whose :value:`authorityInfoAccess` field doesn't including the |OCSPResp| URL,
      without needing to regenerate them or override the existing :value:`authorityInfoAccess`'s
      |OCSPResp| URL value with a different URL. The |OCSPResp| at the new address must
      still meet the same requirements: use a certificate signed by the same CA as the
      |DP|'s |IdentityCert| and include the :value:`nextUpdate` field in its responses.

      This property accepts a string following the pattern:
      ``(https://|http://)<responder_address>[:<port>]``. Providing the port is optional.
      If the port is not provided, a default value will be used, i.e., :value:`80` for http
      or :value:`443` for HTTPS.

      This property is not mutable.

      :type:`String`.

      Default: :value:`NULL`

  * - :property:`dds.sec.auth.password`
    - :req:`Only required if` :property:`private_key` :req:`is encrypted`

      The password used to decrypt the :property:`private_key`. The value of this property is interpreted as the Base64 encoding of the symmetric key that will be used to decrypt the :property:`private_key`. For example, if the :property:`private_key` was encrypted using this command:

      .. code-block:: console

        $ openssl req -new -newkey ec:ecdsaparam2 \
        -config example2ECdsa.cnf -keyout peer2keyECdsa.pem \
        -passout pass:MyPassword -out peer2reqECdsa.pem

      you should specify the Base64 encoding of MyPassword, therefore the value of the password property should be :value:`TXlQYXNzd29yZA==`.

      If the :property:`private_key` was not encrypted, then the password must be :value:`NULL`.

      :type:`String`.

      Default: :value:`NULL`

  * - :property:`dds.sec.auth.key_establishment_algorithm`
    - :req:`Optional`

      The algorithm used to establish the |SharedSecret| during authentication.
      The options are Diffie-Hellman Ephemeral with 2048-bit MODP Group
      parameters (:value:`DHE+MODP-2048-256`), Elliptic Curve Diffie-Hellman
      Ephemeral with the NIST P-256 curve (:value:`ECDHE-CEUM+P256`), ECDHE
      with the NIST P-384 curve (:value:`ECDHE-CEUM+P384`),
      ** << experimental>> ** ECDHE using X25519 as specified in RFC7748
      (:value:`ECDHE-CEUM+X25519`), and ** << experimental>> ** ECDHE using X448
      as specified in RFC7748 (:value:`ECDHE-CEUM+X448`). There is also the
      default :value:`AUTO` option, which detects the curve used to sign the
      |IdentityCert| and uses the same one. If the certificate is not an ECDSA
      signed certificate, we will default to :value:`ECDHE-CEUM+P256`.

      If two participants that specify different property values discover each
      other, they will use the algorithm that belongs to the participant with
      the lower-valued ``participant_key``.

      :type:`Enum`:
      :value:`AUTO`, :value:`DHE+MODP-2048-256`, :value:`ECDHE-CEUM+P256`,
      :value:`ECDHE-CEUM+P384`

      Default: :value:`AUTO`

  * - :property:`dds.sec.auth.crl`
    - :req:`Optional`

      A Certificate Revocation List to keep track of untrusted X.509
      certificates.

      If :property:`dds.sec.auth.crl` is set to :value:`NULL`, no CRL is
      checked, and all valid certificates will be considered trusted.

      If :property:`dds.sec.auth.crl` is set to an invalid CRL, the |DP|
      creation will fail. A CRL that is missing the signature of the CA is
      considered invalid.

      If :property:`dds.sec.auth.crl` is set to a valid CRL, the CRL will be
      checked upon local |DP| creation and upon discovering remote |DP|.
      Creating a |DP| with a revoked certificate will fail. If |P1| uses a
      certificate that does not appear in |P1|'s CRL but does appear in |P2|'s
      CRL, then |P2| will reject and ignore |P1|. For details, see
      :ref:`p2_core/authentication:Identity Certificate Validation`.

      A signed CRL that lists no certificates is considered valid. See
      :link_connext_dds_secure_gsg:`Hands-on 4 <cpp11/hands_on_4.html#revoking-an-identity-certificate>` in the |SP_GSG|
      for example OpenSSL commands to generate a CRL.

      The document should be in PEM format. You may specify either the file
      name or the document contents. See the :ref:`"Note regarding document
      format" <note_regarding_document_format>` below for details.

      This property is mutable through the |DP| ``set_qos`` API. In addition,
      changes in the CRL will be enforced if
      :property:`files_poll_interval` is set to a value other than :value:`0`.

      :type:`String`.

      Default: :value:`NULL`

.. _note_regarding_document_format:

.. admonition:: Note regarding document format

  The Identity CA, Private Key, |IdentityCert|, and |CRL| documents in
  :numref:`DDS Security Properties for Configuring Authentication` must be in
  PEM format. You may specify either the file name or the document contents. If
  specifying the file name, the property value must have the fully qualified
  path and name of the file, and a prefix :value:`file:`
  (no space after the colon) is optional. If specifying the contents of the
  document, the property value must have the prefix :value:`data:,` (no space
  after the comma), followed by the contents inside the document.

  Some examples:

  .. code-block:: text

    "data:,-----BEGIN CERTIFICATE-----\nabcdef\n-----END CERTIFICATE-----"

  .. code-block:: text

    "data:,-----BEGIN PRIVATE KEY-----\nabcdef\n-----END PRIVATE KEY-----"

  .. code-block:: text

    "data:,-----BEGIN CERTIFICATE-----\nabcdef\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nghijkl\n-----END CERTIFICATE-----"

  .. code-block:: text

    "data:,-----BEGIN X509 CRL-----\nabcdef\n-----END X509 CRL-----"

  Notice that the two :value:`\n` characters are required.

  .. code-block:: text

    "file:../../../dds_security/cert/ecdsa01/identities/ecdsa01Peer01Cert.pem"

  .. code-block:: text

    "C:\Users\Name\dds_security\cert\ecdsa01\identities\ecdsa01Peer01Cert.pem"


.. list-table:: |RTI_SP_PRODUCT| Properties for Configuring Authentication
  :name: |RTI_SP_PRODUCT_HEADING| Properties for Configuring Authentication
  :widths: 40 60
  :header-rows: 1
  :class: longtable

  * - Property Name (prefix with :property:`com.rti.serv.secure.`) [#fPrefix]_
    - Property Value Description

  * - :property:`authentication.alternative_ca_files` (deprecated)
    - :req:`Optional`

      Note:
        This property is deprecated and has been replaced by
        :property:`authentication.alternative_identity_cas`.

      :type:`String`.

      Default: :value:`NULL`

  * - :property:`authentication.alternative_identity_cas`
    - :req:`Optional`

      List of concatenated alternative Identity CA certificates in PEM format.
      You can prefix this list with :value:`data:,` and specify it directly in
      the property value, or you can prefix it with :value:`file:` and specify a
      file name from which to read the list of certificates. If no prefix is
      given, :value:`file:` is assumed.
      See the :ref:`"Note regarding document format"
      <note_regarding_document_format>` above for details.

      If the verification of a file fails with the main certificate
      (:property:`identity_ca`), verification will be retried with all of the
      corresponding alternative certificates. If none of the alternative
      certificates can be used to verify the file, the verification process will
      fail. If any of the alternative certificate files fail to be loaded, the
      |DP| creation will fail. For details, see
      :ref:`p2_core/authentication:Identity Certificate Validation`.

      :type:`String`.

      Default: :value:`NULL`

  * - :property:`authentication.crl` (deprecated)
    - :req:`Optional`

      Same as :property:`dds.sec.auth.crl`.

      Note:
        This property is deprecated and has been replaced by
        :property:`dds.sec.auth.crl`.

      :type:`String`.

      Default: :value:`NULL`

  * - :property:`authentication.ocsp_ignored`
    - :req:`Optional`

      A boolean setting that allows you to completely disable all |OCSP|-related
      functionality. :value:`TRUE` causes a |DP| to ignore |OCSP| for both local
      and remote certificates. Ignoring |OCSP| means that a |DP| will behave as if
      the |OCSP| was not set in the certificate.

      This property is useful for debugging issues involving |OCSP|. The property
      affects the effectiveness of the |GovernanceDoc|, in particular its
      :xmltag:`identity_credential_authority_validation` :xmltag:`ocsp` element.
      If this property value is :value:`TRUE`, |OCSP| will be ignored, regardless of
      the |GovernanceDoc|'s :xmltag:`identity_credential_authority_validation` :xmltag:`ocsp`
      value. If this property value is :value:`FALSE`, a default (:value:`AUTO`)
      |OCSP| requirement kind is assumed until a |GovernanceDoc| including a valid
      :xmltag:`identity_credential_authority_validation` :xmltag:`ocsp` tag is read;
      then the |GovernanceDoc|'s value overrides the |DP|'s default (:value:`AUTO`)
      |OCSP| requirement kind. For details, see :ref:`p2_core/authentication:Online Certificate Status Protocol`.

      This property is not mutable.

      :type:`Boolean`.

      Default: :value:`FALSE`

  * - :property:`authentication.x509v3_extension_enforcement.key_usage`
    - :req:`Optional`

      How to enforce the presence of the X.509 v3 extension ``keyUsage`` (see https://tools.ietf.org/html/rfc5280#section-4.2.1.3).

      This property has three possible values (case-insensitive):

      * :value:`auto`: The |SP_BUILTIN| will not do anything special to enforce the presence of ``keyUsage`` in a certificate. Note this is the behavior in |CONNEXT| 6.0.0 and below.
      * :value:`inherited`: The |SP_BUILTIN| will enforce the presence of ``keyUsage`` if the certificate's issuer has ``keyUsage``. For example, if the Identity CA (specified in :property:`identity_ca`) has ``keyUsage``, and it signs the |IdentityCert| (specified in :property:`identity_certificate`) that does NOT have ``keyUsage``, then participant creation will fail. The same applies if :property:`identity_certificate` is set to a certificate chain.
      * :value:`force`: The |SP_BUILTIN| will always enforce the presence of ``keyUsage``. This is not the default, but it will force you to make sure that all of the certificates in the system have their extensions properly set.

      :type:`Enum`: :value:`auto`, :value:`inherited` :value:`force`

      Default: :value:`inherited`

  * - :property:`authentication.propagate_simplified_identity_certificate`
    - :req:`Optional`

      If :value:`TRUE`, the human-readable sections from |IdentityCerts| are removed before they are transmitted over the network.

      |IdentityCerts| in PEM format may contain a human-readable section above the mandatory section delimited by:

      .. code-block:: text

        ---BEGIN CERTIFICATE---
        ---END CERTIFICATE---

      The human-readable section adds no functionality and is not protected in any way. Removing it from the |IdentityCert| before the authentication process reduces the size of the messages on the network.

      :type:`Boolean`.

      Default: :value:`TRUE` (only the Base64 part is exchanged)

  * - :property:`authentication.enable_discovery_subject_name_propagation`
    - :req:`Optional`

      If :value:`TRUE`, the Subject Name of the local |DP|'s |IdentityCert| will
      be propagated during discovery. This allows a remote |DP| to get the local
      |IdentityCert|'s subject name before completing authentication.

      If :value:`FALSE`, the Subject Name of the local |DP|'s |IdentityCert|
      will not be propagated during discovery. The consequence is that if a
      remote |DP| calls ``discovered_participant_subject_name`` with the local
      |DP|'s `InstanceHandle_t` and the remote |DP| has not yet authenticated
      the local |DP|, then this function will return DDS_RETCODE_NO_DATA. See
      :property:`discovered_participant_subject_name` in
      :ref:`p3_advanced/apis:Relevant functions`.

      :type:`Boolean`.

      Default: :value:`FALSE`

  * - :property:`authentication.keyform`
    - :req:`Optional`

      The format of the private key specified by :property:`dds.sec.auth.private_key`.

      The value of this property can be one of the following:

      * :value:`pem`: The key is in PEM format and will be loaded as a file or a string, depending on its "file:" or "data:," prefix.
      * :value:`engine`: The key is an array of bytes and will be loaded by the engine specified by :property:`openssl_engine` (see :ref:`p3_advanced/openssl_engines:Support for OpenSSL Engines`).

      :type:`Enum`: :value:`pem` :value:`engine`

      Default: :value:`pem`

  * - :property:`authentication.rsa_pss_pad`
    - :req:`Optional`

      The kind of padding that the |DP| uses and supports for RSA digital
      signatures.

      This property has three possible values:

      * :value:`AUTO`: Detect the RSA padding from the |DPs|'s |IdentityCert|.
        The |RTI_SP_PRODUCT| for OpenSSL supports RSA standard
        (`RSA_PKCS1_PADDING`) and PSS (`RSA_PKCS1_PSS_PADDING`) padding
        |IdentityCerts|. The |RTI_SP_PRODUCT| for wolfSSL supports only RSA
        standard (`RSA_PKCS1_PADDING`) |IdentityCerts|. |IdentityCerts|
        that have a RSA PSS Public Key or Signature are not supported in
        wolfSSL.

      * :value:`TRUE`: Use RSA PSS padding (RSA_PKCS1_PSS_PADDING) as
        specified in the |SEC_SPEC|.

      * :value:`FALSE`: Use standard RSA padding (RSA_PKCS1_PADDING).

      If the value of the property is either :value:`AUTO` or :value:`TRUE`,
      the |DP| will accept (unless stated otherwise by the Governance Document)
      either `RSA_PKCS1_PSS_PADDING` or `RSA_PKCS1_PADDING` padding to verify
      the remote |DP|'s signed messages.

      If the value of the property is :value:`FALSE`, RSA PSS padding is not
      supported. |DPs| that have this property set to :value:`FALSE` won't be
      able to communicate with DomainParticipants that are using RSA PSS
      padding. The ``message_auth.supported_mask`` and
      ``trust_chain.supported_mask`` bits of the
      ``PID_PARTICIPANT_SECURITY_DIGITAL_SIGNATURE_ALGO`` PID (see
      :ref:`p2_core/cryptography:Discovery of a remote Secure Entity`) are not
      set.

      :type:`Enum`.
      :value:`AUTO`, :value:`TRUE`, :value:`FALSE`,

      Default: :value:`TRUE`

  * - :property:`authentication.enable_experimental_algorithms`
    - :req:`Optional`

      **<< EXPERIMENTAL >>**

      Configures whether to enable custom cryptographic algorithms for
      the Authentication plugin. When enabled, the |SP_BUILTIN| will
      enable additional digital signature and key establishment algorithms that
      are not part of the |SEC_SPEC| (EDDSA+ED25519+SHA512,
      EDDSA+ED448+SHAKE256, ECDHE-CEUM+X25519, ECDHE-CEUM+X448).

      Currently only supported in combination with OpenSSL: this property will
      have no effect when used in combination with wolfSSL. When using the
      OpenSSL FIPS provider, the X25519 and X448 key establishment algorithms
      are not supported.

      Two |DPs| with different configurations of this property will still
      interoperate as long as neither of them is using one of the custom
      algorithms.

      Default: :value:`FALSE`

  * - :property:`authentication.enable_custom_allocators`
    - :req:`Optional`

      Configures whether to set custom crypto library (e.g., OpenSSL)
      allocators. When enabled (not the default), the |RTI_SP_PRODUCT| will
      configure custom allocator functions (alloc, realloc, free) to the loaded
      crypto library with the goal of reducing memory fragmentation at the cost
      of a minimum performance impact. This is currently only supported in
      combination with OpenSSL.

      This property is only effective the first time a
      |DP| loads the |RTI_SP_PRODUCT| within the same process:
      subsequent |DP| creations will ignore this property and leave
      the existing configuration unchanged. Moreover, this property is only
      effective if no allocation has been done with the crypto library builtin
      allocators before the |RTI_SP_PRODUCT| have been loaded, otherwise a
      warning will be logged and no change will be made. For example, if you
      are using a dynamically linked VxWorks application and the kernel has the
      IPCRYPTO component, then the kernel will make some allocations at
      startup, and this property will not be effective.

      **Important:** Since the allocator functions
      live within the |RTI_SP_PRODUCT| library, your application must not make
      any calls to the crypto library once the |RTI_SP_PRODUCT| have
      been unloaded from memory.

      **If your application uses heap monitoring**: You should call
      ``OPENSSL_cleanup`` before disabling heap monitoring. ``OPENSSL_cleanup``
      finalizes OpenSSL and frees resources allocated by it. If you don't call
      ``OPENSSL_cleanup``, the function will be called automatically before
      closing down the library. In this case, heap monitoring will report memory
      leaks because resource deallocation happens once it is no longer tracking
      memory. In general, when using custom OpenSSL allocators we recommend you
      call ``OPENSSL_cleanup`` once your application is done with OpenSSL
      (including having destroyed any |CONNEXT| entity relying on the |RTI_SP_PRODUCT| or
      TLS transport), and do it before unloading the |RTI_SP_PRODUCT| library if using
      dynamic loading.

      Default: :value:`FALSE`

  * - :property:`authentication.key_establishment_algorithm` (deprecated)
    - :req:`Optional`

      Same as :property:`dds.sec.auth.key_establishment_algorithm`.

      Note:
        This property is deprecated and has been replaced by
        :property:`dds.sec.auth.key_establishment_algorithm`.

      :type:`Enum`:
      :value:`AUTO`, :value:`DHE+MODP-2048-256`, :value:`ECDHE-CEUM+P256`,
      :value:`ECDHE-CEUM+P384`

  * - :property:`authentication.shared_secret_algorithm` (deprecated)
    - :req:`Optional`

      Same as :property:`dds.sec.auth.key_establishment_algorithm`.

      Note:
        This property is deprecated and has been replaced by
        :property:`dds.sec.auth.key_establishment_algorithm`.

      :type:`Enum`:
      :value:`dh`, :value:`ecdh`

.. The following properties are internal (not documented)
.. only:: internal

  * - :property:`authentication.x509_verify.library`
    - :req:`Optional`

      The dynamic library that contains an ``X509_STORE_CTX_verify_fn`` function. On Linux systems, the library file name must have a :file:`lib` prefix and a :file:`.so` extension. On other OSs, the value of this property must not have a :file:`lib` prefix or a file extension.

      :type:`String`.

      Default: :value:`NULL`

  * - :property:`authentication.x509_verify.function_name`
    - :req:`Optional`

      The name of the ``X509_STORE_CTX_verify_fn`` function that's implemented in :file:`x509_verify.dll`.

      :type:`String`.

      Default: :value:`NULL`


.. [#fPrefix] Assuming you used :value:`com.rti.serv.secure` as the alias to load the
  plugin. If not, change the prefix to match the string used with
  :property:`com.rti.serv.load_plugins`, followed by the :value:`.` character.


Configuration Properties Affecting Any Authentication Plugin
------------------------------------------------------------

:numref:`Properties for Configuring Authentication Affecting Any Authentication Plugin`
lists a set of properties that are not exclusive to the shipped |SP_BUILTIN|, but that
will affect any |AuthPlugin|.

.. list-table:: Properties for Configuring Authentication Affecting Any Authentication Plugin
  :name: Properties for Configuring Authentication Affecting Any Authentication Plugin
  :widths: 40 60
  :header-rows: 1
  :class: longtable

  * - Property Name (prefix with :property:`dds.participant.trust_plugins.`)
    - Property Value Description

  * - :property:`authentication_timeout.sec`
    - :req:`Optional`

      Controls the maximum time (in seconds) that an ongoing authentication can
      remain without completing. After this timeout expires, the authentication
      process is cancelled, and associated resources are released.
      For more details, see
      :ref:`p2_core/authentication:General Considerations`, and
      :ref:`p2_core/authentication:Guidelines for Minimizing Authentication Negotiation Times`.

      A |DP| should set its own :property:`authentication_timeout` to be shorter
      than the :property:`participant_liveliness_lease_duration`
      (in the |DP|'s DISCOVERY_CONFIG QosPolicy) of its peers
      (see :link_connext_dds_pro_um:`DISCOVERY_CONFIG QosPolicy (DDS Extension) <#users_manual/DISCOVERY_CONFIG_Qos.htm>`).
      This restriction helps a temporarily disconnected peer to successfully
      reconnect with the |DP|.

      :type:`Integer`: :value:`[1, INT_MAX]`

      Default: :value:`60`

  * - :property:`authentication_request_delay.sec`
    - :req:`Optional`

      Controls the delay (in seconds) before sending an |AuthReq| to the remote
      |DP|. For more information, please see
      :ref:`p2_core/authentication:Re-Authentication`, and
      :ref:`p2_core/authentication:Guidelines for Minimizing Authentication Negotiation Times`.

      :type:`Integer`: :value:`[1, INT_MAX]`

      Default: :value:`5`

  * - :property:`authentication_request_timeout.sec`
    - :req:`Optional`

      Controls the timeout (in seconds) for authentication negotiations started
      from an authentication request message. For more information, please see
      :ref:`p2_core/authentication:Re-Authentication`, and
      :ref:`p2_core/authentication:Guidelines for Minimizing Authentication Negotiation Times`.

      :type:`Integer`: :value:`[0, authentication_timeout.sec]`. If set to a
      value greater than :property:`authentication_timeout.sec`, then
      :value:`authentication_timeout.sec` will be used instead.

      Default: :value:`20`

  * - :property:`certificate_status_advance_update_duration`
    - :req:`Optional`

      Controls how much time in advance (with respect to the :value:`nextUpdate` field
      of the current |OCSPToken|) the local |DP| will start querying its
      |OCSPResp| for a renewed |OCSPToken|.

      If a query is unsuccessful, the |DP| will try again. The |DP| retries
      up to five times until the :value:`nextUpdate` time. If the |DP| reaches the
      :value:`nextUpdate` time without obtaining a renewed |OCSPToken|, it will
      continue querying its |OCSPResp| indefinitely (until success), in the same intervals.

      After a successful renewal of the |OCSPToken|, the |DP| will query the |OCSPResp|
      again at a time marked by the :property:`certificate_status_advance_update_duration`
      value and the :value:`nextUpdate` value in the renewed |OCSPToken|.

      The format can be either #s#ms#us#ns, or a single integer representing seconds.

      :type:`String`: :value:`[20, 2678400]`.

      Default: :value:`60`

  * - :property:`subject_name_whitelist`
    - :req:`Optional`

      Configures a (semicolon-separated) whitelist of subject names for
      authenticated |DPs|.
      If set (even if empty), authenticated |DPs| will be allowed into the system
      only if their subject name matches one of the ones in the whitelist.

      For more information, please see
      :ref:`p2_core/authentication:Dynamic Certificate Revocation of Remote |DPs| through Whitelisting`.

      :type:`String`.

      Default: :value:`NULL`

Configuration Properties Affecting Connext DDS Core Libraries Behavior
----------------------------------------------------------------------

:numref:`Properties Affecting Connext DDS Core Libraries Behavior` lists other
properties affecting the |CONNEXT| Core Libraries' behavior.

.. list-table:: Properties Affecting Connext DDS Core Libraries Behavior
  :name: Properties Affecting Connext DDS Core Libraries Behavior
  :widths: 40 60
  :header-rows: 1
  :class: longtable

  * - Property Name
    - Property Value Description

  * - :property:`dds.participant.discovery_config.use_stateless_participant_discovery_reader`
    - :req:`Optional`

      If :value:`TRUE`, makes Simple Participant Discovery robust against
      Sequence Number Attacks by switching the local Simple Participant
      Discovery |DR|'s mode to pure stateless. Setting this value to
      :value:`TRUE` is required for allowing discovery of a |DP| (which may
      successfully complete authentication) with the same
      GUID as an existing |DP| (which may not be authenticated if
      :xmltag:`allow_unauthenticated_participants` is set to :xmlval:`TRUE`).

      :type:`Boolean`.

      Default: :value:`FALSE`
