.. 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. 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_um:`Discovery in the Core Libraries User's Manual `). 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 |RTI_SP| 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 a 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 performs mutual authentication between discovered participants using the RSA or ECDSA digital signature algorithms, and establishes a |SharedSecret| using Diffie-Hellman (DH) or Elliptic Curve Diffie-Hellman (ECDH) key agreement 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 |PermissionsFile| (*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 |PermissionsFile| (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 |PermissionsFile| (*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 |PermissionsFile| (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 every 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 DDS Security Specification, |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 Security Plugins 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| 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. Step 2. Verifying that the certificate is not revoked ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ You can specify a CRL by setting the :property:`authentication.crl` property (see :numref:`RTI Security Plugins 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 the revocation list is immutable (it is not exchanged during discovery or handshaking) and changes in the CRL are not enforced until the |DP| using it is deleted and recreated. For further details, refer to :ref:`p2_core/elements_dds_secure_system:Multiple Certificate Revocation Lists`. 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 cannot validate an |IdentityCert|, the validation will be retried with the alternative certificates specified in the :property:`authentication.alternative_ca_files` property (see :numref:`RTI Security Plugins Properties for Configuring Authentication`). If none of the alternative CAs can validate the file (or if you did not set this property), the validation process will fail. 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 perform secure communication. After the handshake concludes with successful authentication and |SharedKey| derivation, 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 DDS Security specification 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 Security Plugins 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_um:`Setting Builtin Transport Properties with the PropertyQosPolicy in the Core Libraries User's Manual `). 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`). .. note:: If :xmltag:`allow_unauthenticated_participants` is set to :xmlval:`TRUE`, :xmltag:`rtps_protection_kind` must be set to :xmlval:`NONE`. 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|, the mechanism for protecting the |DP_disc| information is known as TrustedState. Security Plugins TrustedState is an RTI extension to the DDS Security Authentication specification that covers two limitations in the DDS Security specification: * 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.). Security Plugins 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| 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| 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:: When the :property:`authentication.participant_discovery_protection_key` property is set (see :numref:`RTI Security Plugins Properties for Configuring Authentication`), the TrustedState mechanism is disabled. Instead, symmetric cryptography based on the pre-shared key specified by this property is used to protect the participant announcements' integrity. Note that, in this scenario, |DPs| cannot validate that the |DP_disc| information received by |CONNEXT| matches the authenticated remote |DPs|. Note that the :property:`authentication.participant_discovery_protection_key` property is required to use |CDS| and the |SP| together. 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 Security Plugins Properties for Configuring Authentication`). The CRLs specified in the :property:`authentication.crl` property will be used throughout the verification process (see :numref:`RTI Security Plugins 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_ca_files`), 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_ca_files`, 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 |SP| support securely re-authenticating remote participants as described in the DDS Security specification. 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 state, 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| address this problem by including a re-authentication capability as described in the DDS Security specification. 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 Connext DDS Core Libraries Behavior`. 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, no change will be made in |P1| and the old authenticated session will be kept. Because the old authenticated state is kept until the new authentication has successfully completed, the |SP| 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 Properties for Configuring Authentication ========================================= :numref:`DDS Security Properties for Configuring Authentication` and :numref:`RTI Security Plugins 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:`p2_core/elements_dds_secure_system:QoS 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. :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` .. admonition:: Note regarding document format The Identity CA, Private Key, and |IdentityCert| 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 prefix :value:`file:` (no space after the colon), followed by the fully qualified path and name of the file. 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-----" Notice that the two :value:`\n` characters are required. .. code-block:: text "file:../../../dds_security/cert/ecdsa01/identities/ecdsa01Peer01Cert.pem" .. list-table:: |RTI_SP| Properties for Configuring Authentication :name: RTI Security Plugins 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.shared_secret_algorithm` - :req:`Optional` The algorithm used to establish the |SharedSecret| during authentication. The options are :value:`dh` and :value:`ecdh` for (Elliptic Curve) Diffie-Hellman. If two participants discover each other and they specify different values for this algorithm, the algorithm that is used is the one that belongs to the participant with the lower-valued ``participant_key``. :type:`Enum`: :value:`dh`, :value:`ecdh` Default: :value:`ecdh` * - :property:`authentication.alternative_ca_files` - :req:`Optional` A comma-separated list of alternative Identity CA Certificates. 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`. Each of the elements in the list must be the fully qualified path to the certificate file. This property value may optionally contain :value:`file:` (no space after the colon) as a prefix to any of the elements in the list. :type:`String`. Default: :value:`NULL` * - :property:`authentication.crl` - :req:`Optional` A Certificate Revocation List to keep track of untrusted X.509 certificates. If :property:`authentication.crl` is set to :value:`NULL`, no CRL is checked, and all valid certificates will be considered trusted. If :property:`authentication.crl` is set to an invalid CRL file, the |DP| creation will fail. If :property:`authentication.crl` is set to a valid CRL file, 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`. The document should be in PEM format. You may specify either the file name or the document contents. See the note above for details. This property is immutable: changes in the CRL will not be enforced until the |DP| using the CRL is deleted and recreated. :type:`String`. Default: :value:`NULL` * - :property:`authentication.crl_file` - :req:`Optional` Same as :property:`authentication.crl`, but you may choose to not specify a :value:`file:` or :value:`data:,` prefix, in which case the property value is interpreted as a file name. Note: This property is deprecated and has been replaced by :property:`authentication.crl`. :type:`String`. Default: :value:`NULL` * - :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| 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| 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| 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.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 used when signing and verifying documents. The value is a boolean that means: * :value:`TRUE`: Use RSA PSS padding (RSA_PKCS1_PSS_PADDING) as specified in the DDS Security specification. * :value:`FALSE`: Use standard RSA padding (RSA_PKCS1_PADDING). This property takes effect only on certificate authorities that use RSA. All of the |DPs| in the system must set this property to the same value in order to communicate with each other. :type:`Boolean`. Default: :value:`TRUE` * - :property:`authentication.participant_discovery_protection_key` - :req:`Optional` Pre-shared key from which |SP| derive the HMAC Key used to compute message authentication codes over :type:`ParticipantBuiltinTopicData` messages. This key shares many of the same details as :property:`hmac_only.cryptography.key`. See that property's description in :numref:`Properties for Configuring HMAC-Only Mode` for the details. If this property is set, then :type:`ParticipantBuiltinTopicData` messages will be protected with an HMAC operation. |DPs| must set this property to the same value in order to communicate with each other. When this property is set, the |DPs| will not interoperate with non-|CONNEXTSECURE| |DPs|. The purpose of this pre-shared key is to protect against certain DoS attacks against |RTI_CDS|. The value of this property is not used to protect any traffic other than :type:`ParticipantBuiltinTopicData` messages. All other RTPS traffic still gets protected by the standard |CryptoPlugin|, which uses dynamically-generated keys that are exchanged after authentication completes. This property takes effect regardless of the value of :property:`hmac_only.enabled`. If |RTI_CDS| is using |SP|, then this property is required by all the |DPs| in the |DOMAIN|. For more information, please refer to :ref:`p4_integrations/real-time_wan_transport:Security Considerations when Using Cloud Discovery Service`. :type:`String`. Since this key is provided as a String, it is recommended that you take the appropriate measures to protect any configuration XML file containing this key, or alternatively to securely retrieve and set up this property programmatically. Default: not set .. 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 Connext DDS Core Libraries Behavior ---------------------------------------------------------------------- :numref:`Properties for Configuring Authentication Affecting Connext DDS Core Libraries Behavior` lists a set of properties that are not exclusive to the shipped |SP|, but that will affect any |AuthPlugin|. :numref:`Properties Affecting Connext DDS Core Libraries Behavior` lists other properties affecting the |CONNEXT| Core Libraries' behavior. .. list-table:: Properties for Configuring Authentication Affecting Connext DDS Core Libraries Behavior :name: Properties for Configuring Authentication Affecting Connext DDS Core Libraries Behavior :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`. A |DP| should set its own :property:`authentication_timeout` to be shorter than the :property:`participant_liveliness_lease_duration` (in the DomainParticipant's DISCOVERY_CONFIG QosPolicy) of its peers (see :link_um:`DISCOVERY_CONFIG QosPolicy (DDS Extension) `). 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 participant. For more information, please see :ref:`p2_core/authentication:Re-Authentication`. :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. :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` .. 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. :type:`Boolean`. Default: :value:`FALSE`