.. include:: ../vars.rst .. _chapter-cryptography: ************ Cryptography ************ Introduction ============ Cryptography is the process of making sure no adversaries can manipulate or eavesdrop on communication. The |SP| cover this process by means of the |CryptoPlugin|. To prevent adversaries from manipulating messages, the |CryptoPlugin| appends a message authentication code (MAC) to the message being protected, therefore protecting its integrity. To prevent eavesdropping, the |CryptoPlugin| can additionally encrypt the message, protecting its confidentiality. .. admonition:: Definitions The |CryptoPlugin| defines multiple protection levels that are applied to different parts of your communication. By **"protect a message"**, we refer to applying any of these protections to any particular part of your communication before sending it out. In other words, "to protect" implies "to perform the MAC cryptographic operations" -- when data integrity is protected; or "to perform the encrypt and MAC cryptographic operations" -- when both data integrity and data confidentiality are protected. On the receiver side, we will "validate" a message to verify it was not manipulated -- when data integrity is protected. We may also need to "decrypt" a message the sender protected against eavesdroppers -- when data confidentiality is protected. Therefore, **"validate (and potentially decrypt)"** is equivalent to "verify the MAC (and decrypt, only if the message was encrypted)". With the |SP|, you can specify a different level of protection to each of your |TOPICs| (see :ref:`p2_core/elements_dds_secure_system:Topic-level rules`). For example, you can protect the data integrity of a particular |TOPIC| by setting the protection kind associated with that |TOPIC| to :xmlval:`SIGN` in the |GovernanceDoc|. If the data sent on that |TOPIC| should also be protected from potential eavesdropping, you can additionally protect its confidentiality by setting its protection kind to :xmlval:`ENCRYPT`. This allows you to protect each of your |TOPICs| with the level of protection that it requires. You can also leave some of your |TOPICs| unprotected by setting its protection kind to :xmlval:`NONE`, which could be useful to achieve compatibility with unsecure parts of your system or to save resources. |SecDPs|, |SecDWs|, and |SecDRs| use symmetric cryptography to protect the messages they send. Each of these |SecEntities| is associated with different cryptographic material, preventing unauthorized |Entities| from participating in secure communication (see :ref:`p2_core/cryptography:Secure Entities`). For example, when you create a |SecDW|, some keys are associated with it. By only sharing its |KeyMaterial| with authorized |DRs|, your |SecDW| makes sure that only these |SecDRs| can read that information. This scheme, combined with the fact that you can define different protection levels for your |DDS_ENTITIES| based on DDS attributes (e.g., domain, topic name), provides granular security. The |CryptoPlugin| also puts in place a mechanism to prevent insiders from pretending to be a different entity. For instance, consider a |DR| that legitimately subscribes to a |DW| for a particular |TOPIC|. Since symmetric encryption is used to protect data, the |DR| could potentially use the |DW|'s key to send arbitrary samples, thus impersonating it. |DWs| can avoid this situation by protecting samples with |OrigAuthProtection| (see :ref:`p2_core/cryptography:Origin Authentication protection`). Cryptography Plugin as an Enabler for Other Plugins --------------------------------------------------- Protecting the confidentiality and integrity of data ensures that other security plugins can do their job correctly. For example, the |AccessControlPlugin| will prevent your secure |DWs| from sending samples to |DRs| that do not have permission to subscribe to a specific |TOPIC|. However, if the |CryptoPlugin| does not enforce confidentiality by encrypting your samples, malicious |DRs| could listen to the traffic on your network, thus getting access to the data you wanted to protect and defeating the purpose of Access Control. In this sense, the |CryptoPlugin| provides us with the building blocks that enable other |SP| to work properly. Access Control decides whether an entity has permission to do something; Cryptography enforces entities to meet this requirement. The |AuthPlugin| interacts in a similar way with the |CryptoPlugin|. While the |AuthPlugin| makes sure a participant is who it claims to be, it is the |CryptoPlugin| that enforces that only authenticated participants have access to the domain. The |CryptoPlugin| achieves this by protecting messages with encryption keys that have been only shared with successfully authenticated and authorized participants. Overview of How Cryptography Works in DDS ----------------------------------------- To establish a DDS Secure communication, |SecEntities| (i.e., |SecDPs|, |SecDWs|, and |SecDRs|) perform some cryptographic transformations based on some security parameters and keys. |SecEntities| use symmetric cryptography to MAC (and potentially encrypt) the information they protect. Therefore, a sender and its matching receivers will use the same cryptographic material to communicate securely. We will describe this in more detail in the section dedicated to :ref:`p2_core/cryptography:Secure Entities`. In order to exchange the keys that |SecEntities| need, mutually authenticated participants establish an end-to-end channel to exchange sensitive cryptographic material securely. This |SecKeyExchangeCh| allows your |SecDPs| to confidentially exchange the |KeyMaterial| that |SecDWs| and |SecDRs| need to communicate. We will describe this channel in more detail in :ref:`p2_core/cryptography:Secure Key Exchange Channel (ParticipantVolatileMessageSecure topic)`. |SecDWs| and |DRs| are not only used to protect the user-defined |TOPICs|. New secure builtin |EP| (|DWs| and |DRs|) will be created when you protect the discovery traffic or the liveliness assertions. More concretely, when you protect a |TOPIC|'s discovery information, your |DPs| will exchange the discovery information for that |TOPIC| through the |SecDiscoveryTopics|. You can also protect liveliness messages exchanged for |TOPICs| that have :value:`AUTOMATIC` or :value:`MANUAL_BY_PARTICIPANT` (see :ref:`p2_core/cryptography:enable_liveliness_protection (topic_rule)`). Protecting liveliness will result in your |DPs| exchanging these messages through the |SecLivelinessTopic| (see :ref:`p2_core/elements_dds_secure_system:Builtin Secure Liveliness Topic`). Note that these secure builtin |EPs| will coexist with their unsecure versions that will be used for |TOPICs| that aren't using Discovery/Liveliness Protection. Protecting different parts of your communication implies that your messages will have cryptographic transformations applied at different stages (see :ref:`p2_core/cryptography:Security Protections Applied by DDS Entities`). For example, |DataProtection| allows you to protect the samples published in a particular |TOPIC|. You could also decide to protect the RTPS submessages for that particular |TOPIC|. |SubmsgProtection| covers both :submsg:`DATA` submessages -- which contain the (potentially already-protected) serialized payload -- and submessages containing metadata, such as :submsg:`ACKNACK` and :submsg:`HEARTBEAT` submessages. Finally, you could enable |RTPSProtection| to protect the complete RTPS messages that your |DPs| put on the network. Note that the protections at different stages are not mutually exclusive: the |CryptoPlugin| gives you the flexibility to combine different levels of protection in the way that best fits your security requirements. Also, applying cryptographic transformations at different stages implies protecting different parts of the RTPS message, as depicted in :numref:`Parts of the Message Protected by Each Protection Kind`. For further details, see :ref:`p2_core/cryptography:Securing DDS Messages on The Wire`. .. figure:: ../static/protection-kinds.png :scale: 50% :name: Parts of the message protected by each protection kind :align: center Parts of the Message Protected by Each Protection Kind The |CryptoPlugin| uses AES-GCM to protect the traffic. The AES-GCM transformation produces both the ciphertext and a message authentication code (MAC) using the same secret key. This is sufficient to protect the plaintext and ensure integrity. However there are situations where multiple MACs are required. For example when a |DW| shares the same key with multiple |DRs| and, in spite of this, the |DW| needs to ensure origin authentication. In this situation the |DW| should create a separate |RecSpecificKey| used only for authentication and append additional |RecSpecificMACs|, each computed with one of the |RecSpecificKeys| (see :ref:`p2_core/cryptography:Origin Authentication protection`). Secure Entities =============== .. admonition:: Definition We will use the term |SecEntity| to refer to one of the following three |DDS_ENTITIES|: - |SecDW|: can perform |DataProtection| and/or |SubmsgProtection|. - |SecDR|: can perform |SubmsgProtection|. - |SecDP|: can perform |RTPSProtection|. In other words, a |SecEntity| is a |DW|, a |DR|, or a |DP| that has at least a protection kind different than :xmlval:`NONE` in its associated |GovRules|. When a |SecDW| sends a sample to its matching |DRs|, it will protect the sample by applying a cryptographic transformation (parametrized with a key). If, for example, this is a reliable |TOPIC|, the |DRs| also need to send :submsg:`ACKNACKs` to the |DW|, and these will be protected using the same cryptographic transformation, but using different keys. As you can see, both |DWs| and |DRs| need to send protected information to the other |EP|. In this sense, we talk about Sender (the entity sending a secure message) and Receiver (the entity receiving a secure message). Note that every |SecEntity| will have its own Sender and Receiver. The Sender will protect the messages; the Receiver will validate (and potentially decrypt) the messages. To communicate with the other end, both the Sender and the Receiver will have a copy of the same |KeyMaterial|, from which we derive the key that is used by the cryptographic transformations. Each Sender will generate its own key to protect the outgoing messages; Receivers for that Sender will need the same key to validate (and potentially decrypt) the incoming messages. This |KeyMaterial| is securely exchanged between matching |SecEntities| through the |SecKeyExchangeCh|, as described in :ref:`p2_core/cryptography:Secure Key Exchange Channel (ParticipantVolatileMessageSecure Topic)`. Architecture of Secure Entities ------------------------------- |SecEntities| have some attributes (configuration) and mechanisms (algorithms) that allow them to communicate securely. In addition, each |SecEntity| has a Sender and a Receiver: the Sender handles the outgoing messages by protecting them; the Receiver handles the incoming messages by validating (and potentially decrypting) them. |SecEntities| need to store and use keys as parameters for the cryptographic algorithms. Upon its creation, each |SecEntity| generates the local Sender's |KeyMaterial|. Receivers in matching |SecEntities| need a copy of this |KeyMaterial| to validate (and potentially decrypt) the messages from this Sender, as depicted in :numref:`Architecture Overview of Two Matching Secure Entities`. .. figure:: ../static/secure-entity-architecture.png :scale: 50% :name: Architecture Overview of Two Matching Secure Entities :align: center Architecture Overview of Two Matching |SecEntities| Security Mechanisms ^^^^^^^^^^^^^^^^^^^ To communicate securely, |SecEntities| need to perform operations that involve the |CryptoPlugin|. These operations include protecting the outgoing messages in the sender side and validating (and potentially decrypting) the incoming messages in the receiver side with the same symmetric key. The key used by the cryptographic functions is a symmetric |SessionKey| with a limited lifetime. The |SessionKey| derives from cryptographic material generated by the Sender entity upon its creation, then sent to the Receiver upon discovery of the remote entity. The |SessionKey| is a temporary key that will be valid for a particular session and derives from the Sender's |KeyMaterial| and |SessionID|. The Sender will periodically change the |SessionKey| used to protect the messages by changing the |SessionID|. To let the Receiver know what |SessionKey| it needs to use, the Sender includes the |SessionID| in every protected message. Security Attributes ^^^^^^^^^^^^^^^^^^^ The security attributes define what part of the messages will be protected by the Sender and how, i.e., what transformation is applied and how it changes the transmitted packets. Security attributes come from the |GovRules| that apply to this |TOPIC| and need to be the same in every |EP| for this |TOPIC| in the secure domain (see :ref:`p2_core/cryptography:Discovery of a Remote Secure Entity`). (|GovRules| are user-defined in the Governance File, see :ref:`p2_core/elements_dds_secure_system:Governance File`). In the case of a |SecDW|, the security attributes define whether the Sender will protect the serialized data and/or the RTPS submessage. |SecDRs| are limited to protecting the outgoing RTPS submessage, while |SecDPs| can protect outgoing RTPS messages at the RTPS message level. The security attributes also define whether the Sender will MAC the protected message or it will encrypt and MAC it. In either case, the Sender will use the |SessionKey| to protect the outgoing messages; matching Receivers will use this same |SessionKey| to validate (and potentially decrypt) the incoming messages. Local Sender's Key Material ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Upon its creation, |SecEntities| generate the local Sender's |KeyMaterial|. The local Sender uses this cryptographic material to communicate with the remote Receivers securely. The local Sender's |KeyMaterial| includes the |SenderKey| and is identified by the |SenderKeyID|. Cryptographic algorithms do not use the |SenderKey| directly to protect communications. Instead, the Sender derives temporary |SessionKeys| from its |SenderKey| (and other parameters from its |KeyMaterial|). Cryptographic operations use these temporary keys to protect outgoing messages. These messages also include the |SenderKeyID| to allow the Receiver to identify, within all the |KeyMaterial| received from a remote |DP|, what |KeyMaterial| was used to protect the message. Note that RTPS messages already contain the |SecEntity|'s GUID that identifies the |DP| from which the message originated. Additionally, the outgoing messages also include a |SessionID|, which allows the Receiver to derive the right |SessionKey| by applying certain cryptographic operations over the selected |SenderKey| (see :numref:`Derivation of the Session Key and Receiver-Specific Session Keys`). When |OrigAuthProtection| is enabled, one additional |RecSpecificKey| per Receiver (identified by the |RecSpecificKeyIDs|) are stored in the |SecEntity| along with the local Sender's |KeyMaterial|. This key is used to derive the |RecSpecificSessionKey|, which in turn is used as input to the cryptographic operation that computes the |RecSpecificMAC| of the outgoing messages. Note that while the |SenderKey| does not change in the whole lifecycle of the |SecEntity|; the |SessionID| changes periodically (see :ref:`p2_core/cryptography:Secure Communication`). .. figure:: ../static/derivation-session-keys.png :scale: 50% :name: Derivation of the Session Key and Receiver-Specific Session Keys :align: center Derivation of the |SessionKey| and |RecSpecificSessionKeys| Remote Sender's Key Material ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The Receiver in the local |SecEntity| needs the remote Sender's |KeyMaterial| to validate (and potentially decrypt) messages coming from that remote Sender. Note this is the same |KeyMaterial| we introduced in :ref:`p2_core/cryptography:Local Sender's Key Material`, but from the Receiver's perspective. The local |SecEntity| will receive the remote Sender's |KeyMaterial| through the |SecKeyExchangeCh| after the two matching |SecEntities| discover and validate each other. The local Receiver derives the |SessionKey| from the remote Sender's |KeyMaterial| and the |SessionID| included in each message. Then, it uses the |SessionKey| to validate (and potentially decrypt) incoming messages (see :ref:`p2_core/cryptography:Secure Communication`). When the Receiver gets a message from the network, it takes the |SenderKeyID| and the remote |SecEntity|'s GUID from the RTPS message. With this information, the Receiver can identify the |SenderKey| that the Sender used to protect the message from the list of its received keys. Then, it uses the |SessionID|, also included in the protected message, to compute the |SessionKey|. Finally, the Receiver uses the |SessionKey| to validate (and potentially decrypt) the message. When |OrigAuthProtection| is enabled, an additional |RecSpecificKey| is assigned to the local Receiver. This key is identified by the |RecSpecificKeyID| and is stored as part of the remote Sender's |KeyMaterial|. This key is used to derive the |RecSpecificSessionKey|, which in turn is used to verify the |RecSpecificMAC| of the incoming messages. .. figure:: ../static/key-material-sender.png :scale: 50% :name: Key Derivation in the Sender :align: center Key Derivation in the Sender. The |KeyMaterial| is stored in the |SecEntity|. .. figure:: ../static/key-material-receiver.png :scale: 50% :name: Key Derivation in the Receiver :align: center Key Derivation in the Receiver. The |KeyMaterial| stored in the |SecEntity| is identified with the |SenderKeyID|, present in the incoming message. Lifecycle of Secure Entities ---------------------------- Creation of the Secure Entity ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Upon the creation of a |SecEntity|, the local |SenderKey| is generated and stored locally. This is done after the checks from the |AccessControlPlugin|, which verifies that the |Entity| has permission to do what it's being created for. Refer to :ref:`p2_core/cryptography:Local Sender's Key Material` for further details on the generated cryptographic material. Discovery of a Remote Secure Entity ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ To successfully discover, |DPs| need to have a compatible configuration for the :misdef:`participant security attributes`. A compatible configuration involves having the same |RTPSProtection| kind, the same |DiscoveryProtection|, and the same |LivelinessProtection|. The same logic applies to |SecEPs| and the :misdef:`endpoint security attributes`. To communicate, two matching |SecEPs| (a |SecDW| and a |SecDR|) need to present the same |GovRules| for the |TOPIC| of these |SecEPs|. To support this Governance compatibility checks, when you enable security, |CONNEXT| sends additional properties as part of the discovery information. These properties support making matching decisions. For further details, see :ref:`p2_core/elements_dds_secure_system:Governance Compatibility Validation`. Key Material Exchange ^^^^^^^^^^^^^^^^^^^^^ Once the |SecEntities| have fully matched (same |TOPIC|, same type, compatible QoS, same security attributes) and permissions are checked, they exchange the |KeyMaterial| through the |SecKeyExchangeCh|. Each of the |SecEntities| will register the local Sender's |KeyMaterial| and the remote Sender's |KeyMaterial| (that is received through the |SecKeyExchangeCh|). As specified in :ref:`p2_core/cryptography:Creation of the Secure Entity`, the common part of the local Sender's |KeyMaterial| is generated upon the entity creation. When |OrigAuthProtection| is enabled, the |RecSpecificKeyMaterial| is also exchanged. In this case, the local |DP| maintains a list with the |RecSpecificKeys| that correspond to the discovered |SecEntities|. Since |Entities| in the same |DP| run in the same application memory space, a single |RecSpecificKey| is assigned to every |SecEntity| in a remote |DP|. For further details on |KeyMaterial| Exchange, see :ref:`p2_core/cryptography:Secure Key Exchange`. Secure Communication ^^^^^^^^^^^^^^^^^^^^ At this point, the |SecEntities| can communicate securely. The Sender will add additional information in the outgoing messages so the Receiver can validate (and potentially decrypt) them. This includes the |SenderKeyID| and the |SessionID|. The message will also contain the MAC (a.k.a the |CommonMAC|), and the |RecSpecificMACs| when |OrigAuthProtection| is enabled. :numref:`Reception of a Secure Message` depicts the process of receiving a secured incoming message. Details on how the communication is protected on the wire are covered in :ref:`p2_core/cryptography:Cryptographic Information Added to RTPS Messages`. .. figure:: ../static/reception-secure-msg.png :scale: 55% :name: Reception of a Secure Message :align: center Reception of a Secure Message Algorithms Involved in Protecting Secure Entities Traffic --------------------------------------------------------- Senders use AES-GCM to encrypt and MAC messages when the :xmlval:`ENCRYPT` protection kind is in use. Alternatively, when the :xmlval:`SIGN` protection kind is configured, Senders use AES-GMAC to MAC-only data. On the counterpart side, Receivers use the same algorithms to validate the MAC of (and potentially decrypt) incoming data. Note that AES-GMAC transformation is a particular case of AES-GCM, which produces only a MAC and leaves the input message unencrypted. AES-GCM can operate with 128-, 192-, and 256-bit keys (see :property:`cryptography.encryption_algorithm` in :numref:`RTI Security Plugins Properties for Configuring Cryptography`). Regardless of the key size, AES-GCM always operates in 128-bit (16-byte) blocks. Hence, all the MACs are 128-bit (16-byte) long. AES-GCM requires a symmetric key and an initialization vector to operate. In |SP|, the |SessionKey| is used as the symmetric key, while the |IV| is the concatenation of the |SessionID| and the so-called |IVsuffix|. The same |IV| is associated with all the session keys of a specific Sender, including the common |SessionKey| and all the |RecSpecificSessionKeys|. The |IVsuffix| is incremented each time any of these keys are used to encrypt and/or compute a MAC. The |SessionID| and |IVsuffix| are sent as part of the protected message, allowing the Receiver to derive the |SessionKey| and the |RecSpecificKey| that it will use to validate (and potentially decrypt) the received messages. As stated in the DDS Security specification, the use of (Galois) counter mode allows authenticated decryption of blocks in an arbitrary order. All that is needed to decrypt and validate the authentication tag are the |SessionKey| and the |IV|. This is very important for DDS because a |DR| may not receive all the samples written by a matched |DW|. The use of DDS ContentFilteredTopics as well as DDS QoS policies such as History (with :value:`KEEP_LAST` kind), Reliability (with :value:`BEST_EFFORTS` kind), Lifespan, and TimeBasedFilter, among others, can result in a |DR| receiving a subset of the samples written by a |DW|. Limiting the Usage of a Specific Session Key ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The |SessionBlockCounter| is an internal counter that keeps track of the number of blocks protected with the same |SessionKey|. Note that GCM uses 128-bit blocks. The purpose of this counter is to ensure that a single |SessionKey| is not used to protect more than the maximum blocks per session, as configured by the :property:`cryptography.max_blocks_per_session` property (see :numref:`RTI Security Plugins Properties for Configuring Cryptography`). The |SessionBlockCounter| and the size of the plaintext are used to ensure that :property:`cryptography.max_blocks_per_session` will not be exceeded during the encode operation. If the encode operation detects that the counter would exceed the maximum then it will modify the |SessionID| (and derive new session keys) prior to transforming any of the input plaintext. The change in the |SessionID| triggers the creation of new session keys, randomizes the |IVsuffix|, and resets the |SessionBlockCounter|. Note that |SP| 6.1.0 does NOT support key renewal. However, the |SessionID| changes when a certain number of blocks have been encrypted with the same |SessionKey|. This results in using a different |SessionKey| for the following messages without the need of generating and exchanging new |KeyMaterial|. Since the original |KeyMaterial| stays the same, this mechanism is not useful for kicking off participants from the system. Secure Key Exchange Channel (ParticipantVolatileMessageSecure Topic) ==================================================================== In order to perform key exchange between |SecEntities|, |DPs| need to send directed messages to each other using a reliable and secure channel. These messages are intended only for participants that are currently in the system and therefore use a DURABILITY QoS of kind :value:`VOLATILE`. The DDS Security specification introduces a new |SecKeyExchangeT|, also known as the |SecKeyExchangeTName| builtin |TOPIC|, to exchange these messages. Secure Key Exchange Builtin Topic Characteristics And Security Attributes ------------------------------------------------------------------------- The purpose of the |SecKeyExchangeT| is to reliably and securely transport the |KeyMaterial| between the |SecEntities|. This |TOPIC| uses a RELIABILITY QosPolicy of kind :value:`RELIABLE` and a HISTORY QosPolicy of kind :value:`KEEP_ALL` to make sure that keys get to the remote |SecEntity|. Also, a DURABILITY QosPolicy of kind :value:`VOLATILE` is used to prevent sending data to unauthorized late joiners. Finally, to protect the confidentiality of messages sent on this channel, the |SecKeyExchangeEPs| use encryption as the |SubmsgProtection|. The |SecKeyExchangeCh| requires a |SecDW| and a |SecDR| in both the local participant (|P1|) and the remote participant (|P2|). The |KeyMaterial| that allows a |DW| and its matching |DRs| to communicate securely is normally exchanged through this |SecKeyExchangeCh|. The only exception is the |KeyMaterial| used by this channel's |SecEPs|, a |SharedKey| that will derive from the information resulting from the authentication process. More concretely, the |SharedKey| is derived using HMAC operations on the Challenges exchanged in the Handshake and the |SharedSecret| that results from the authentication process. For more information on these parameters, see :ref:`p2_core/authentication:Handshake`. The |KeyMaterial| derived for the |SecDW| and |DR| is identical. Nonetheless, since only |P1| and |P2| know the |SharedKey|, this cryptographic material is unique for |P1| and |P2|. In other words, this is a direct channel between |P1| and |P2|. That means that if there were a third participant (|P3|) in the system, there would be different keys for communicating between |P1| and |P3|. So a |SharedKey| is particular to a single authentication session between a pair of |DPs|. Hence, if somehow |P2| loses liveliness and |P1| cleans the state associated with |P2|, and then |P1| rediscovers |P2|, they will end up with a different |SharedKey|. Secure Key Exchange ------------------- Once the |SecKeyExchangeCh| is established, the |KeyMaterial| for every other |SecEntity| is exchanged through it. This |KeyMaterial| includes the |TransformationKind|, |SenderKey| and |SenderKeyID|, as well as the |RecSpecificKey| (see :ref:`p2_core/cryptography:Architecture of Secure Entities`). |DPs| use this |TOPIC| to exchange the |KeyMaterial| that will be used to protect outgoing RTPS messages (when |RTPSProtection| is enabled). After that, |DPs| exchange the |KeyMaterial| for the builtin |SecEPs|, including the |SecPublicationDW| and |DR| used for Secure |EP_disc| (see :ref:`p2_core/elements_dds_secure_system:Security Builtin Topics`). Once your |DPs| have exchanged the keys for the builtin |SecEPs|, they can perform secure discovery, and once they discover particular user-defined |DWs| and |DRs|, the participants will also use this channel to exchange the keys for those |EP|. More concretely, during |EP_disc|, two mutually authenticated participants (|P1| and |P2|) will send publication and subscription :submsg:`DATA` messages to inform their counterpart about their local |DWs| and |DRs|. When |P1| discovers that |P2| has a |DR| (|DR2|) matching a local |DW| (|DW1|), |P1| will register |DR2| as a remote endpoint. If |OrigAuthProtection| is enabled, |P1| will assign |DR2| |RecSpecificKeyMaterial|. After this, |P1| will send |DW1|'s local Sender |KeyMaterial| through the |SecKeyExchangeCh|. This message will include |DR2|'s |RecSpecificKeyMaterial|. |P2| will follow the same process: register |DW1|, assign it some |RecSpecificKeyMaterial| (if |OrigAuthProtection| is enabled), and send |DR2|'s local Sender |KeyMaterial| to |P1|. At this point, |DW1| and |DR2| have all the cryptographic material that they need to communicate securely (see :ref:`p2_core/cryptography:Local Sender's Key Material`). Securing DDS Messages on The Wire ================================= When sending a protected message, some cryptographic information is added to let the Receiver know how the message was protected (|TransformationKind|) and what keys were used (identified by the |SenderKeyID|). This information goes in the |CryptoHeader|. Then the |CryptoContent| submessage element is used to wrap a Serialized Payload, an RTPS submessage, or a complete RTPS message. The |CryptoContent| is the result of applying one of the cryptographic transformations to the protected message. Also, a |CryptoFooter| is appended to the (potentially encrypted) message. The |CryptoFooter| contains the authentication tag that protects the message integrity (aka |CommonMAC|). If |OrigAuthProtection| is enabled, the |CryptoFooter| will also contain the |RecSpecificMACs|. Depending on where you apply the protection, the message that is sent on the wire will be secured in different ways. This has further implications that we analyze next. RTPS Protocol Changes to Support Secure Entities Traffic -------------------------------------------------------- In the RTPS protocol, the main component is the RTPS message. RTPS messages have a header containing information about the sending entity, and have different units of information that are divided into submessages. In turn, each submessage has a header and its own elements. For example, a submessage can contain user data; it will have a data header and then contain your user data. Other submessages could contain metadata needed in DDS, such as :submsg:`HEARTBEATs`, :submsg:`ACKNACKs`, etc. To sum up, inside a single RTPS message you can have multiple submessages with different bits of information (see :numref:`General Structure of an RTPS Message`). Depending on the protection kind, different parts of the message will be protected. .. figure:: ../static/rtps-msg-structure.png :scale: 55% :name: General Structure of an RTPS Message :align: center General Structure of an RTPS Message Serialized Data Protection ^^^^^^^^^^^^^^^^^^^^^^^^^^ You can enable |DataProtection| by setting the :xmltag:`data_protection_kind` |GovRule| to a value other than :xmlval:`NONE` (see :ref:`p2_core/cryptography:data_protection_kind (topic_rule)`). |DataProtection| only applies to the Sender in the |DW|. The |DW| protects the sample payload right after the serialization. The protected sample (including the MAC and potentially being encrypted) is stored in the |DW|'s queue until sent (it may be sent in a batch). When resending samples (for instance, for sending repairs), the sample is already in the |DW|'s queue, so additional cryptographic operations are not needed (see :ref:`p3_advanced/design_considerations:Interaction Between the Security Plugins and Batching QoS`). .. note:: |SecDWs| can only communicate with compatible |SecDRs|, as described in :ref:`p2_core/cryptography:Discovery of a remote Secure Entity`. In other words, secure and unsecure |EPs| cannot communicate. From an RTPS point of view, the |DataProtection| only protects the payload inside the :submsg:`DATA` submessages. Therefore, the Serialized Payload now becomes a |CryptoHeader|, a |SerializedPayload|/|CryptoContent| element, and a |CryptoFooter|, as :numref:`RTPS Message Transformation with Serialized Data Protection` depicts. Note that the |SerializedPayload| element (unchanged from input) is used when only protecting data integrity (:xmltag:`data_protection_kind` = :xmlval:`SIGN`); the |CryptoContent| element (encrypted |SerializedPayload|) is used when also protecting data confidentiality (:xmltag:`data_protection_kind` = :xmlval:`ENCRYPT`). Also, note that the submessage structure (and number) is not modified. .. figure:: /../shared_content/static/data-protection.png :scale: 50% :name: RTPS Message Transformation with Serialized Data Protection :align: center RTPS Message Transformation with |DataProtection| Submessage Protection ^^^^^^^^^^^^^^^^^^^^^ You can enable |SubmsgProtection| by setting the :xmltag:`metadata_protection_kind` |GovRule| to a value other than :xmlval:`NONE` (see :ref:`p2_core/cryptography:metadata_protection_kind (topic_rule)`). |SubmsgProtection| applies to messages sent both by the |DW| and the |DR|. The |SecEP| will protect the following types of RTPS submessages right before putting them in the wire. * :submsg:`AckNack` * :submsg:`AppAck` * :submsg:`AppAckConf` * :submsg:`Data` * :submsg:`DataBatch` * :submsg:`DataFrag` * :submsg:`DataSession` * :submsg:`Gap` * :submsg:`Heartbeat` * :submsg:`HeartbeatFrag` * :submsg:`HeartbeatVirtual` * :submsg:`NackFrag` .. note:: |SecDWs| can only communicate with compatible |SecDRs|, as described in :ref:`p2_core/cryptography:Discovery of a remote Secure Entity`. In other words, secure and unsecure |EPs| cannot communicate. From an RTPS point of view, |SubmsgProtection| protects the submessages by prepending a Secure Prefix Submessage (:submsg:`SEC_PREFIX`) -- which contains the |CryptoHeader| -- to the Secure Body Submessage (:submsg:`SEC_BODY`) -- which contains the |CryptoContent|. It also appends a Secure Postfix Submessage (:submsg:`SEC_POSTFIX`) -- which contains the |CryptoFooter|. Therefore, the submessage becomes :submsg:`SEC_PREFIX` + :submsg:`SEC_BODY` + :submsg:`SEC_POSTFIX`, as the following diagram depicts. Note that the number of RTPS submessages increases, but the overall RTPS message structure is not modified. .. figure:: ../static/submsg-protection.png :scale: 50% :name: RTPS Message Transformation with Submessage Protection :align: center RTPS Message Transformation with |SubmsgProtection| RTPS Protection ^^^^^^^^^^^^^^^ You can enable |RTPSProtection| by setting the :xmltag:`rtps_protection_kind` |GovRule| to a value other than :xmlval:`NONE` (see :ref:`p2_core/cryptography:rtps_protection_kind (domain_rule)`). |RTPSProtection| affects the |DP| and applies to every packet [#]_ that is sent by protecting the whole RTPS message right before putting it on the network. .. note:: |DPs| with |RTPSProtection| can only communicate with |DPs| that have this same protection. In other words, when you enable |RTPSProtection|, secure and unsecure |DPs| cannot interoperate. From an RTPS point of view, |RTPSProtection| protects the whole RTPS message by copying the RTPS header, then protecting the whole RTPS message (including its header). The resulting protected packet will consist of an :submsg:`SRTPS Prefix` [#]_ -- which contains the |CryptoHeader| -- followed by an :submsg:`SRTPS Body` -- which contains the |CryptoContent| -- and an :submsg:`SRTPS Postfix` -- which contains the |CryptoFooter|. Note that |RTPSProtection| modifies the structure of the whole RTPS message and, when encryption is used, the confidentiality of all the content (except the RTPS header) is protected. .. figure:: ../static/rtps-protection.png :scale: 50% :name: RTPS Message Transformation with RTPS Protection :align: center RTPS Message Transformation with |RTPSProtection| .. [#] Exceptions of RTPS messages to which |RTPSProtection| applies are covered in :ref:`p2_core/cryptography:DomainParticipants`. .. [#] SRTPS stands for Secure RTPS. Origin Authentication Protection ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |OrigAuthProtection| allows the Receiver to make sure that the Sender is who it claims to be (i.e., it can authenticate the origin), even when the Sender communicates with multiple Receivers via multicast and shares the same encryption key with all of them. For instance, consider a |DR| that legitimately subscribes to a |DW| for a particular |TOPIC|. Since symmetric encryption is used to protect data, the |DR| could potentially use the |DW|'s key to send arbitrary samples, thus impersonating it. |DWs| can avoid this situation by protecting samples with |OrigAuthProtection|. .. hint:: You can add |OrigAuthProtection| to |SubmsgProtection| by setting the :xmltag:`metadata_protection_kind` |GovRule| to :xmlval:`SIGN_WITH_ORIGIN_AUTHENTICATION` or :xmlval:`ENCRYPT_WITH_ORIGIN_AUTHENTICATION`. You can add |OrigAuthProtection| to |RTPSProtection| by setting the :xmltag:`rtps_protection_kind` |GovRule| to :xmlval:`SIGN_WITH_ORIGIN_AUTHENTICATION` or :xmlval:`ENCRYPT_WITH_ORIGIN_AUTHENTICATION`. For further information, see :ref:`p2_core/cryptography:Understanding ProtectionKinds`. This protection involves computing additional |RecSpecificMACs| with a secret key that the Sender shares only with a set of Receivers (ideally one). The additional MACs are computed by applying the AES-GMAC algorithm parameterized with the |RecSpecificKey| to the |CommonMAC|, and appending the result to it in the |CryptoFooter|. The number of |RecSpecificMACs| in an RTPS message is the union of the |RecSpecificMACs| each of its submessages would need. For example, assume that you have an RTPS message with three submessages. The first submessage is directed to a receiver |A|, the receiver of the second submessage is |B|, and the receiver of the third submessage is unknown. In this situation, if |SubmsgProtection| were set to protect the origin authentication, the first submessage would have the |RecSpecificMAC| for |A|, the second submessage would have the |RecSpecificMAC| for |B|, and the third submessage would have the |RecSpecificMAC| for all the matching |EPs|, let's say |A|, |B|, |C|, and |D|. Therefore, to satisfy the requirements of every submessage, the RTPS message will include the following |RecSpecificMACs|: .. math:: \lbrace A\rbrace\cup\lbrace B\rbrace\cup\lbrace A,B,C,D\rbrace=\lbrace A,B,C,D\rbrace .. figure:: ../static/rec-specific-macs-multiple-receivers.png :scale: 50% :name: Receiver-specific MACs included in an RTPS Message that uses RTPS Protection with Origin Authentication :align: center |RecSpecificMACs| included in an RTPS Message that uses |RTPSProtection| with Origin Authentication Note that adding |OrigAuthProtection| to |DataProtection| is not allowed (i.e., the :xmlval:`DATA_WITH_ORIGIN_AUTHENTICATION` ProtectionKind does not exist). This is a consequence of the stage at which data is secured. On one hand, RTPS and Submessage Protections happen at wire-serialization time, right before handing the data to the transport. On the other hand, |DataProtection| happens right before the sample is saved in the |DW|'s queue. The writer history stores the protected payload and this happens only once. While RTPS messages and submessages are re-protected when they are re-sent, user data is not. Once the sample is in the queue, the |DW| has no information about the |DRs| interested in it. If a |DR| joins later and wants to receive historical data, the current sample in the queue would not be valid because it wouldn't have the new |RecSpecificMAC| appended to it. The diagram in :numref:`Location of the Different Kinds of Protection` summarizes the location of the protection. .. figure:: ../static/applying-protection.png :scale: 50% :name: Location of the Different Kinds of Protection :align: center Location of the Different Kinds of Protection Cryptographic Information Added to RTPS Messages ------------------------------------------------ When the Sender protects a message, it appends the MACs to the message and includes some information that the Receiver will need in order to derive the |SessionKey|. More concretely, the secured message will contain these elements: a |CryptoHeader|, |CryptoContent| (or |SerializedPayload|) and a |CryptoFooter|. Crypto Header ^^^^^^^^^^^^^ The |CryptoHeader| element indicates to the Receiver the cryptographic transformation that was used to protect the message. It also identifies the cryptographic material used to protect the message. It has three parts: * transformation_id: The transformation_id includes the |TransformationKind| and the |SenderKeyID|, and is used in combination with the identity of the sending |DP| (already present in the RTPS header) to identify the |KeyMaterial| used to derive the |SessionKey| that protected the message. * session_id: The session_id is used in combination with the |KeyMaterial| to derive the cryptographic keys used for the encryption and MAC operations, including the |SessionKey| and the |RecSpecificSessionKey|. * initialization_vector_suffix: The initialization_vector_suffix is concatenated with the session_id to produce the |IV| used as an input to the AES-GCM and AES-GMAC cryptographic operations/transformations. Crypto Content / Serialized Payload ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The |CryptoContent| is a sequence of octets that contain the encrypted version of the protected message when protecting both the integrity and confidentiality of the message (with :xmlval:`ENCRYPT` protection kinds). Alternatively, the |SerializedPayload| is sent in plaintext when only the message's integrity is protected (with :xmlval:`SIGN` protection kinds). Crypto Footer ^^^^^^^^^^^^^ The |CryptoFooter| consists of the |CommonMAC| (and the |RecSpecificMACs|, when |OrigAuthProtection| is used). * |CommonMAC|: The |CommonMAC| in the |CryptoFooter| is the authentication tag generated by the AES-GMAC transformation using the |SessionKey| and the |IV|. This transformation operates on the message being protected in plaintext when the :xmlval:`SIGN` protection kind is used, or on the encrypted message when the protection kind is :xmlval:`ENCRYPT`. The result is a 128-bit (16-byte) MAC that protects the message integrity. * |RecSpecificMACs|: (only when |OrigAuthProtection| is used) The |RecSpecificMACs| in the |CryptoFooter| are the AES-GMAC tags computed on the |CommonMAC| using each of the |RecSpecificSessionKeys| and the same |IV|. Each of the |RecSpecificMACs| is 128-bit (16-byte). The |RecSpecificMACs| are computed with a secret key that the Sender shares only with a set of Receivers (ideally one). The |RecSpecificMACs| provide origin authentication to the Receiver even when the Sender is communicating with multiple Receivers via multicast and shares the same encryption key with all of them. For more information, see :ref:`p2_core/cryptography:Origin Authentication Protection Implications`. Security Protections Applied by DDS Entities ============================================ |SecEntities| are responsible for protecting the messages that they put on the wire. When you protect different parts of the communication related to a |TOPIC| in your |GovernanceFile|, you are actually defining the |Entities| and |SecEntities| that are used to transmit the information related to that |TOPIC|. This includes: #. Whether |SecDWs| and |DRs| (or regular |DWs| and |DRs|) will be used to transmit the |TOPIC|'s payload (along with the Endpoint's metadata such as :submsg:`HEARTBEATs`, :submsg:`ACKNACKs` and :submsg:`GAPs` submessages). #. Whether the |EP_disc| traffic will be exchanged through the secure version of the Builtin Discovery Endpoints. #. Whether the liveliness assertions will be exchanged through the secure version of the Builtin Participant Message Endpoints (if the LIVELINESS QosPolicy is :value:`AUTOMATIC` or :value:`MANUAL_BY_PARTICIPANT`, as described in :ref:`p2_core/cryptography:enable_liveliness_protection (topic_rule)`). Also, when you enable |RTPSProtection|, your |SecDPs| will additionally protect every RTPS message that is put on the network. (Of course, this includes the messages related to this |TOPIC|). Keep in mind that to be able to communicate, the |DPs| in your secure domain need to protect the different parts of the communication related to your |TOPIC| the same way. For this reason, your |DPs| need to load compatible Governance documents (see :ref:`p2_core/elements_dds_secure_system:Governance Compatibility Validation`). Let's analyze what part of the communication (related to your |TOPIC|) each of these (potentially *Secure*) |Entities| can protect and what the valid levels of protection are. DomainParticipants ------------------ In an unsecure scenario, |EPs| send packets directly to the network, without going through any |DP|-level protection. This remains the same when you don't use |RTPSProtection|. However, you can enable the |RTPSProtection| by setting the :xmltag:`rtps_protection_kind` to a value other than :xmlval:`NONE`. Then the |DP| will intercept the RTPS message produced by your |EPs| (with a callback) and protect the whole message before putting it on the network. Note that the |DP| will apply |RTPSProtection| to every outgoing RTPS message except for the following: * DCPSParticipant builtin |TOPIC| messages (used in the |DP_disc| Phase) * Authentication (ParticipantStatelessMessage) builtin |TOPIC| messages * Secure Key Exchange (|SecKeyExchangeTName|) builtin |TOPIC| messages * UDP WAN transport binding ping messages (can be protected with either :property:`hmac_only.cryptography.key` or :property:`cryptography.rtps_protection_key`) The levels of protection that the |SecDP| can apply are listed in :numref:`Protection Levels Applied by SecDPs During RTPSProtection`. Note that this protection will apply to every RTPS message sent by your |DPs|. Therefore if you have another type of protection enabled, multiple nested cryptographic operations will be performed on your data. .. table:: Protection Levels Applied by |SecDPs| During |RTPSProtection| :name: Protection Levels Applied by SecDPs During RTPSProtection +--------------------------------+----------------------------------------------+-------------------------------------------------------+ | Governance Rule | ProtectionKind | Level of Protection | +================================+==============================================+=======================================================+ | :xmltag:`rtps_protection_kind` | :xmlval:`NONE` | No protection | | +----------------------------------------------+-------------------------------------------------------+ | | :xmlval:`SIGN` | Integrity | | +----------------------------------------------+-------------------------------------------------------+ | | :xmlval:`ENCRYPT` | Integrity and confidentiality | | +----------------------------------------------+-------------------------------------------------------+ | | :xmlval:`SIGN_WITH_ORIGIN_AUTHENTICATION` | Integrity and origin authentication | | +----------------------------------------------+-------------------------------------------------------+ | | :xmlval:`ENCRYPT_WITH_ORIGIN_AUTHENTICATION` | Integrity, confidentiality, and origin authentication | +--------------------------------+----------------------------------------------+-------------------------------------------------------+ User-Defined Endpoints (DataWriters/DataReaders) ------------------------------------------------ User-defined |EP| are responsible for exchanging the |TOPIC|'s payload with the Security parameters that you define. You can configure user-defined |EPs| to protect either the Serialized Data, the RTPS submessages or both. Protecting the Serialized Data implies protecting the |TOPIC|'s payload, which is contained in :submsg:`DATA` submessages. Protecting the RTPS submessages implies protecting both :submsg:`DATA` submessages (which contain the payload) and other submessages that contain metadata (such as :submsg:`HEARTBEATs`, :submsg:`ACKNACKs` and :submsg:`GAPs` submessages). |DataProtection| and |SubmsgProtection| are performed by the same |SecEntity|, but at different stages: * |DataProtection| is applied to data in the |DW|'s queue, before encapsulating it in an RTPS submessage. * |SubmsgProtection| is applied right before putting the information on the network. Note that a batch of serialized data elements could be sent in the same submessage. You can configure user-defined |EP| to apply different levels of protection at each of these stages, as shown in :numref:`Protection Levels Applied by user-defined EPs for DataProtection` and Table :numref:`Protection Levels Applied by user-defined EPs for SubmsgProtection`. You can configure the level of protection applied at each level independently. So if you want to protect the confidentiality of the payload and the integrity of the metadata sent by your user-defined |SecEPs| you could set :xmltag:`data_protection_kind` to :xmlval:`ENCRYPT` and :xmltag:`metadata_protection_kind` to :xmlval:`SIGN`. Note that in this case, your |DW| will perform an AES-GCM operation over the serialized data, storing the encrypted and MAC'd payload in its queue (with its corresponding format: |CryptoHeader| | |CryptoContent| | |CryptoFooter|). Then right before putting the data on the network, it will perform an AES-GMAC operation to the :submsg:`DATA` submessage, inserting the MAC'd submessage in an RTPS message (with its corresponding format: SEC Prefix | SEC Body | SEC Postfix). .. table:: Protection Levels Applied by user-defined |EPs| for |DataProtection| :name: Protection Levels Applied by user-defined EPs for DataProtection :width: 100% +--------------------------------+-------------------+-------------------------------+ | Governance Rule | ProtectionKind | Level of Protection | +================================+===================+===============================+ | :xmltag:`data_protection_kind` | :xmlval:`NONE` | No protection | | +-------------------+-------------------------------+ | | :xmlval:`SIGN` | Integrity | | +-------------------+-------------------------------+ | | :xmlval:`ENCRYPT` | Integrity and confidentiality | +--------------------------------+-------------------+-------------------------------+ .. table:: Protection Levels Applied by user-defined |EPs| for |SubmsgProtection| :name: Protection Levels Applied by user-defined EPs for SubmsgProtection +------------------------------------+----------------------------------------------+-------------------------------------------------------+ | Governance Rule | ProtectionKind | Level of Protection | +====================================+==============================================+=======================================================+ | :xmltag:`metadata_protection_kind` | :xmlval:`NONE` | No protection | | +----------------------------------------------+-------------------------------------------------------+ | | :xmlval:`SIGN` | Integrity | | +----------------------------------------------+-------------------------------------------------------+ | | :xmlval:`ENCRYPT` | Integrity and confidentiality | | +----------------------------------------------+-------------------------------------------------------+ | | :xmlval:`SIGN_WITH_ORIGIN_AUTHENTICATION` | Integrity and origin authentication | | +----------------------------------------------+-------------------------------------------------------+ | | :xmlval:`ENCRYPT_WITH_ORIGIN_AUTHENTICATION` | Integrity, confidentiality, and origin authentication | +------------------------------------+----------------------------------------------+-------------------------------------------------------+ Builtin Secure Discovery Endpoints ---------------------------------- Builtin Discovery |EP| are responsible for exchanging the |EP_disc| information that allows the local |DP| to discover remote |EP| (and remote participants to discover the local |DP|'s |EP|). You can configure whether to use the secure version (or the regular unsecure version) of the Builtin Discovery Endpoints with the :xmltag:`enable_discovery_protection` |GovRule|. If you set this |GovRule| to :xmlval:`TRUE`, discovery information related to your |TOPIC| will be exchanged through the Builtin Secure Discovery Endpoints, and Topic Queries related to your |TOPIC| will be communicated through the Builtin Secure ServiceRequest Endpoints. These |EP| will apply |SubmsgProtection| to the level you configure with the :xmltag:`discovery_protection_kind` |GovRule|. The levels of protection that the Builtin Secure Discovery Endpoints can apply are listed in table :numref:`Protection Levels Applied by Builtin Secure Discovery Endpoints and Builtin Secure ServiceRequest Endpoints`. Note that this protection level will apply to the discovery and topic query information for every |TOPIC| that sets :xmltag:`enable_discovery_protection` = :xmlval:`TRUE`. .. table:: Protection Levels Applied by Builtin Secure Discovery Endpoints and Builtin Secure ServiceRequest Endpoints in the |SubmsgProtection| Stage :name: Protection Levels Applied by Builtin Secure Discovery Endpoints and Builtin Secure ServiceRequest Endpoints +-------------------------------------+----------------------------------------------+-------------------------------------------------------+ | Governance Rule | ProtectionKind | Level of Protection | +=====================================+==============================================+=======================================================+ | :xmltag:`discovery_protection_kind` | :xmlval:`NONE` | No protection | | +----------------------------------------------+-------------------------------------------------------+ | | :xmlval:`SIGN` | Integrity | | +----------------------------------------------+-------------------------------------------------------+ | | :xmlval:`ENCRYPT` | Integrity and confidentiality | | +----------------------------------------------+-------------------------------------------------------+ | | :xmlval:`SIGN_WITH_ORIGIN_AUTHENTICATION` | Integrity and origin authentication | | +----------------------------------------------+-------------------------------------------------------+ | | :xmlval:`ENCRYPT_WITH_ORIGIN_AUTHENTICATION` | Integrity, confidentiality, and origin authentication | +-------------------------------------+----------------------------------------------+-------------------------------------------------------+ Secure Topic Query and Locator Reachability Support ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Builtin Service Request |EP| are responsible for exchanging Topic Queries and Locator Reachability responses. The Builtin Secure Service Request |EP| will apply |SubmsgProtection| to the level you configure with the :xmltag:`discovery_protection_kind` |GovRule|. (See :ref:`p2_core/elements_dds_secure_system:Builtin Secure ServiceRequest Topic`). The decision about which version of the Builtin Service Request endpoint (secure or not secure) the |DR| uses to send Topic Queries will depend on the value configured for the :xmltag:`enable_discovery_protection` |GovRule| for that |DR|. The decision about which version of the Builtin Service Request endpoint (secure or not secure) the Participant uses to send Locator Reachability responses to a remote Participant will be based on whether or not that remote Participant is using security. Builtin Secure Liveliness Endpoints ----------------------------------- Builtin Liveliness |EP| are responsible for maintaining the liveliness of |TOPICs| that set the LIVELINESS QosPolicy to :value:`AUTOMATIC` or :value:`MANUAL_BY_PARTICIPANT` (see :ref:`p2_core/cryptography:enable_liveliness_protection (topic_rule)`). You can configure whether to use the secure version (or the regular unsecure version) of the Builtin Liveliness Endpoints with the :xmltag:`enable_liveliness_protection` |GovRule|. If you set this |GovRule| to :xmlval:`TRUE`, liveliness information related to your |TOPIC| will be exchanged through the Builtin Secure Liveliness Endpoints (only if the LIVELINESS QosPolicy is set to one of the values listed above). These |EP| will apply |SubmsgProtection| to the level you configure with the :xmltag:`liveliness_protection_kind` |GovRule|. The levels of protection that the Builtin Secure Liveliness Endpoints can apply are listed in table :numref:`Protection Levels Applied by Builtin Secure Liveliness Endpoints`. Note that this protection level will only apply to |TOPICs| that set the LIVELINESS QosPolicy to one of the values listed above and set :xmltag:`enable_liveliness_protection` = :xmlval:`TRUE`. .. table:: Protection Levels Applied by Builtin Secure Liveliness Endpoints at the |SubmsgProtection| Stage :name: Protection Levels Applied by Builtin Secure Liveliness Endpoints +--------------------------------------+----------------------------------------------+-------------------------------------------------------+ | Governance Rule | ProtectionKind | Level of Protection | +======================================+==============================================+=======================================================+ | :xmltag:`liveliness_protection_kind` | :xmlval:`NONE` | No protection | | +----------------------------------------------+-------------------------------------------------------+ | | :xmlval:`SIGN` | Integrity | | +----------------------------------------------+-------------------------------------------------------+ | | :xmlval:`ENCRYPT` | Integrity and confidentiality | | +----------------------------------------------+-------------------------------------------------------+ | | :xmlval:`SIGN_WITH_ORIGIN_AUTHENTICATION` | Integrity and origin authentication | | +----------------------------------------------+-------------------------------------------------------+ | | :xmlval:`ENCRYPT_WITH_ORIGIN_AUTHENTICATION` | Integrity, confidentiality, and origin authentication | +--------------------------------------+----------------------------------------------+-------------------------------------------------------+ Related Governance Rules ======================== You can control what protection kind you apply to different parts of your communication. You can do this by setting some Cryptography rules in your |GovernanceDoc|. For information on what |SecEntity| is responsible for protecting each part of the message, see :ref:`p2_core/cryptography:Security Protections Applied by DDS Entities`. Understanding ProtectionKinds ----------------------------- Attributes whose names end with ``_protection_kind`` share a type called ProtectionKind. The DDS Security specification lists five possible values of ProtectionKind, all of which are supported by the |SP|. * :xmlval:`NONE` indicates that no cryptographic transformation is applied. * :xmlval:`SIGN` indicates that the cryptographic transformation is purely a Galois message authentication code (GMAC, referred to as MAC), which protects the integrity of the message the protection applies to. No encryption is performed. The MAC is placed after the content (in the |CryptoFooter|). If the Receiver finds a missing or incorrect MAC, the Receiver will reject the content. * :xmlval:`ENCRYPT` indicates that the cryptographic transformation is AES encrypted followed by a MAC computed on the ciphertext, also known as Galois/Counter Mode (GCM), protecting both the integrity and confidentiality of the messages. The MAC is placed after the content (in the |CryptoFooter|). If the Receiver finds a missing or incorrect MAC, the Receiver will reject the content. * ProtectionKinds ending in :xmlval:`_WITH_ORIGIN_AUTHENTICATION` indicate that in addition to using the Sender's key to generate a |CommonMAC|, the Sender generates |RecSpecificMACs| using keys that are only shared with a subset of Receivers (ideally, only one). The additional MACs are placed after the |CommonMAC| (also in the |CryptoFooter|). They prove to the Receiver that the Sender originated the message, preventing other Receivers from impersonating the Sender. If the Receiver finds a missing or incorrect |CommonMAC|, the Receiver will reject the content. If the Receiver finds a missing or incorrect |RecSpecificMAC| that was computed using its own |RecSpecificKey|, the Receiver will reject the content. For further details, see :ref:`p2_core/cryptography:Origin Authentication Protection`). .. note:: The ProtectionKinds ending in :xmlval:`_WITH_ORIGIN_AUTHENTICATION` are allowed only if the value of the property :property:`cryptography.max_receiver_specific_macs` is greater than :value:`1` (see :numref:`RTI Security Plugins Properties for Configuring Cryptography`). The ProtectionKinds ending in :xmlval:`_WITH_ORIGIN_AUTHENTICATION` are as follows: * :xmlval:`SIGN_WITH_ORIGIN_AUTHENTICATION` indicates that a |CommonMAC| is performed on the content, and |RecSpecificMACs| are performed on the |CommonMAC|. This provides integrity and origin authentication protections. * :xmlval:`ENCRYPT_WITH_ORIGIN_AUTHENTICATION` indicates that a GCM is performed on the content, and |RecSpecificMACs| are performed on the |CommonMAC|. This provides integrity, confidentiality, and origin authentication protections. Domain-Level Rules ------------------ The following attributes belong inside a :xmltag:`domain_rule`. rtps_protection_kind (domain_rule) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This ProtectionKind specifies how to protect a |DP|'s outgoing messages and what kind of protection is required of incoming messages. A message consists of an RTPS header and submessages, so a message is an envelope around submessages. If :xmltag:`allow_unauthenticated_participants` = :xmlval:`TRUE`, :xmltag:`rtps_protection_kind` must be set to :xmlval:`NONE`. Setting :xmltag:`rtps_protection_kind` to :xmlval:`NONE` will cause the |DP| to accept both protected and unprotected incoming RTPS messages. Setting :xmltag:`rtps_protection_kind` to something other than :xmlval:`NONE` will cause the |DP| to reject incoming RTPS messages that have a missing or incorrect MAC. discovery_protection_kind (domain_rule) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This ProtectionKind specifies the :xmltag:`metadata_protection_kind` used for the secure builtin |DW| and |DR| entities used for discovery, Topic Queries, and Locator Reachability Responses. The :xmltag:`discovery_protection_kind` will protect |EP_disc| for the |TOPICs| that set :xmltag:`enable_discovery_protection`. This includes information exchanged for discovering new |EP| and for updating existing ones, as described in :ref:`p2_core/cryptography:enable_discovery_protection (topic_rule)`. The :xmltag:`discovery_protection_kind` will also protect messages that contain updates to the existing |DPs|. Note that new |DP| discovery announcements are never protected (but updates to existing |DPs| are protected). liveliness_protection_kind (domain_rule) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This ProtectionKind specifies the :xmltag:`metadata_protection_kind` used for the secure builtin |DW| and |DR| entities used for liveliness. The :xmltag:`liveliness_protection_kind` will protect liveliness information from |TOPICs| that set :xmltag:`enable_liveliness_protection` (only if the |DW|'s LIVELINESS QosPolicy is :value:`AUTOMATIC` or :value:`MANUAL_BY_PARTICIPANT`, as described in :ref:`p2_core/cryptography:enable_liveliness_protection (topic_rule)`). Topic-Level Rules ----------------- The following attributes belong inside a :xmltag:`topic_rule`. metadata_protection_kind (topic_rule) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This ProtectionKind specifies how to protect a |DW|'s or |DR|'s outgoing RTPS submessages. These submessages include, but are not limited to, :submsg:`DATA`, :submsg:`HEARTBEAT`, :submsg:`ACKNACK`, :submsg:`APP_ACK`, and :submsg:`GAP`. (For the full list of affected RTPS submessages, refer to :ref:`p2_core/cryptography:Submessage protection`.) Note that :submsg:`DATA` submessage is an envelope around a serialized payload, so :xmltag:`metadata_protection_kind` affects data as well as metadata. data_protection_kind (topic_rule) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This attribute may be :xmlval:`NONE`, :xmlval:`SIGN`, or :xmlval:`ENCRYPT`. It specifies how to protect a |DW|'s serialized payload, as described in :ref:`p2_core/cryptography:Serialized data protection`. The |DW| applies this protection upon adding the serialized payload to the |DW|'s queue (the |DW|'s queue stores the protected payload). In that sense, one difference between :xmltag:`metadata_protection_kind` and :xmltag:`data_protection_kind` is that for :xmltag:`metadata_protection_kind`, the submessage protection takes effect immediately before sending out the content, so if a given serialized payload needs to be resent multiple times, the submessage protection will be re-computed every time the serialized payload is (re)sent; on the other hand, the serialized data protection is applied only when the sample is added to the writer queue and, therefore, this protection does not need to be re-computed every time the serialized payload is sent. |RecSpecificMACs| are never included in this protection, so the ProtectionKinds ending in :xmlval:`_WITH_ORIGIN_AUTHENTICATION` are not allowed for this attribute. enable_discovery_protection (topic_rule) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This attribute may be :xmlval:`TRUE` or :xmlval:`FALSE`. It specifies whether to use the secure or unsecure builtin |EP| for certain outgoing traffic related to this |TOPIC|. Such traffic includes |EP_disc| messages and TopicQuery messages. :xmltag:`enable_discovery_protection` also specifies whether or not to reject unsecure incoming |EP_disc| messages related to this |TOPIC|. For further details, see :ref:`p2_core/cryptography:Builtin Secure Discovery Endpoints`. enable_liveliness_protection (topic_rule) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This attribute may be :xmlval:`TRUE` or :xmlval:`FALSE`. The value of this attribute matters only if the |DW|'s LIVELINESS QosPolicy is :value:`AUTOMATIC` or :value:`MANUAL_BY_PARTICIPANT` (see :link_um:`LIVELINESS QosPolicy in the Core Libraries User's Manual `). In either of these cases, :xmltag:`enable_liveliness_protection` specifies whether or not to use the secure builtin |EP| for exchanging liveliness messages for |DWs| of this |TOPIC|. Otherwise, when LIVELINESS QosPolicy is :value:`MANUAL_BY_TOPIC`, this attribute does not take effect and it is the user-defined |SecEPs| that take care of liveliness assertions, which are protected with :xmltag:`metadata_protection_kind`. For further details, see :ref:`p2_core/cryptography:Builtin Secure Discovery Endpoints`. Advanced Cryptography Concepts ============================== Reliability Behavior When MAC Verification Fails ------------------------------------------------ From a security point of view, message corruption due to random errors produced on the network cannot be distinguished from malicious tampering. When setting :xmltag:`data_protection_kind`, :xmltag:`metadata_protection_kind`, or :xmltag:`rtps_protection_kind` to a value other than :xmlval:`NONE`, the |DR| may reject a sample due to MAC verification (for example, if the sample is tampered). When this happens, the |DR| does not deliver the sample to the application, and the sample is lost. If the RELIABILITY QosPolicy is set to :xmlval:`RELIABLE`, however, the |DW| will still repair the lost sample. Note that depending on the level of protection, a tampered/replayed sample may be rejected at different levels: * If :xmltag:`metadata_protection_kind` or :xmltag:`rtps_protection_kind` is a value other than :xmlval:`NONE`, the sample will be rejected before reaching the |DR| queue. * If Submessage and RTPS Protection checks passed, and :xmltag:`data_protection_kind` is set to a value other than :xmlval:`NONE`, the sample will be rejected by the |DR| queue (or lost, in the case of best effort communication). Enabling Asynchronous Publishing for the Secure Key Exchange Topic ------------------------------------------------------------------ The |SP| support fragmenting Secure Key Exchange (|SecKeyExchangeTName|) Builtin |TOPIC| samples. This is useful in scenarios with a hard limit on the transport maximum message size. Key Exchange is a reliable |TOPIC|; therefore, enabling fragmentation requires changing the publish mode to asynchronous publishing. For more information about how to configure the |SecKeyExchangeT| publish mode, see :numref:`DDS_DiscoveryConfigQosPolicy Fields Affecting the Secure Key Exchange Topic`. .. list-table:: DDS_DiscoveryConfigQosPolicy Fields Affecting the |SecKeyExchangeT| :name: DDS_DiscoveryConfigQosPolicy Fields Affecting the Secure Key Exchange Topic :widths: auto :header-rows: 1 :class: longtable * - Type - Field Name - Description * - :link_um:`PUBLISH_MODE QosPolicy (DDS Extension) ` - ``secure_volatile_writer_publish_mode`` - Determines whether the Key Exchange builtin subscription |DW| publishes data synchronously or asynchronously, and how. Configuring Reliability Protocol Settings of the Secure Key Exchange Topic -------------------------------------------------------------------------- The |SP| support configuring the reliability protocol settings of the Secure Key Exchange (|SecKeyExchangeTName|) builtin topic, which is a reliable |TOPIC|. You can configure this by modifying the DDS_DiscoveryConfigQosPolicy (see :link_um:`DISCOVERY_CONFIG QosPolicy (DDS Extension) in the Core Libraries User's Manual `). For more information about how to configure the Key Exchange topic reliability protocol settings, see :numref:`DDS_DiscoveryConfigQosPolicy Fields Affecting the RTPS Protocol-Related Configuration of the Secure Key Exchange Topic`. .. list-table:: DDS_DiscoveryConfigQosPolicy Fields Affecting the RTPS Protocol-Related Configuration of the |SecKeyExchangeT| :name: DDS_DiscoveryConfigQosPolicy Fields Affecting the RTPS Protocol-Related Configuration of the Secure Key Exchange Topic :widths: auto :header-rows: 1 :class: longtable * - Type - Field Name - Description * - :link_um:`RtpsReliableWriterProtocol_t ` - ``secure_volatile_writer`` - RTPS protocol-related configuration settings for the builtin Secure Key Exchange writer * - :link_um:`DDS_RtpsReliableReaderProtocol_t ` - ``secure_volatile_reader`` - RTPS protocol-related configuration settings for the builtin Secure Key Exchange reader Securing Application-Level Acknowledgments ------------------------------------------ As mentioned in :ref:`p2_core/cryptography:Submessage Protection`, the protection of :submsg:`AppAck` submessages is determined by :xmltag:`metadata_protection_kind`. Therefore, if an AppAck contains valid response data, that response data's protection is determined by :xmltag:`metadata_protection_kind` (not :xmltag:`data_protection_kind`). Moreover, the |TOPIC|'s :xmltag:`enable_read_access_control` (not :xmltag:`enable_write_access_control`) determines whether the |DR| is allowed to match with a |DW| and send such AppAcks. With that in mind, a |DP| with permission to read but not write the |TOPIC| could create a |DR| (let's call it |DR1|) whose response data always contains all of the sample's contents being acknowledged. Even if no other |DRs| can interpret the AppAck response data as a data sample (because the response data would not be coming from a :submsg:`DATA` submessage), |DR1| could compromise the |TOPIC|'s payload confidentiality by putting samples in plaintext on the wire. You can mitigate this threat by setting :xmltag:`metadata_protection_kind` to :xmlval:`ENCRYPT`. Doing so will force |DR1| to set :xmltag:`metadata_protection_kind` to :xmlval:`ENCRYPT` to match with the |DW|, ensuring that |DR1| will encrypt its response data. Note that this is only true as long as the |DW|'s |DP| leaves the :property:`dds.participant.discovery_config.disable_endpoint_security_info_propagation` property set to :value:`FALSE`. .. warning:: In |SP| 5.3.x or below, it's still possible to misconfigure |DR1| not to encrypt its response data -- |DR1| would still match with the |DW| despite setting :xmltag:`metadata_protection_kind` not equal to :xmlval:`ENCRYPT`. Origin Authentication Protection Implications --------------------------------------------- As described in :ref:`p2_core/cryptography:Origin Authentication Protection`, protecting the origin authentication of a message involves computing and sending a |RecSpecificMAC| to each of the message's Receivers. You can reduce the performance impact of ProtectionKinds ending in :xmlval:`_WITH_ORIGIN_AUTHENTICATION` by limiting the number of |RecSpecificMACs| in your Secure Domain with the :property:`cryptography.max_receiver_specific_macs` property (see :numref:`RTI Security Plugins Properties for Configuring Cryptography`). Setting this resource limit will have security implications. For instance, assume that you set :property:`cryptography.max_receiver_specific_macs` to 10, and you have 20 |DPs| in your Secure Domain. In this case, you will have groups of 2 participants who share the same |RecSpecificKey| and could pretend to be the other participant. Note that, with this setup, all the participants would have a single peer that could be a potential attacker. If this resource limit is unchanged, as the number of participants grows, an increasing number of participants will share the same key. Hence, each participant could impersonate an increasing number of other participants. For example, suppose you have 100 participants and set this limit to 5. Since the keys will rotate every 5 participants (like in a circular buffer), you will have five groups of 20 participants with the same |RecSpecificKey|. If they happen to have writers and readers for the same |TOPIC|, they could potentially attack the origin authentication. To successfully perform this attack, a malicious participant needs two keys: * The |SenderKey|: generated by the Sender on the |SecEntity| creation. It is only exchanged with |SecEntities| matching that of the Sender -- for instance, two DRs in different |DPs| matching the same |DW|. * The |RecSpecificKey|: assigned by a |DP| to the other |DPs| it discovers. The :property:`cryptography.max_receiver_specific_macs` property limits the number of different |RecSpecificKeys| a |DP| will assign. These keys are assigned in a round-robin fashion -- for instance, with :property:`cryptography.max_receiver_specific_macs` set to :value:`5`, |P6| and |P1| will share the same |RecSpecificKey|. Choosing a reasonable value for this property will depend on multiple factors, such as your system's number of |DPs| and number of |TOPICs|. Let's consider the following scenarios, assuming that all the DPs in your system set cryptography.max_receiver_specific_macs to 5: #. In a Secure Domain in which |DP| |P0| sends content to six other |DPs|, only |P1| and |P6| will share the |RecSpecificKey|. Therefore, |P1| could potentially pretend to be |P0| when sending content to |P6| and vice versa. This impersonation can only happen if |P1| and |P6| have |DRs| for the same Topic and have matched the same |DW| (otherwise, they won't have the |SenderKey| to generate the |CommonMAC|. #. In a Secure Domain with 100 |DPs|, there will be five groups of 20 participants with the same |RecSpecificKey|. In this case, a malicious |DP| could only impersonate the other 19 |DPs| with which it shares the |RecSpecificKey|. As suggested by the second example, the cryptography.max_receiver_specific_macs allows you to divide |DPs| into groups, reducing the impact of a potential attack against the origin authentication. Which group a participant belongs in depends on the order of discovery, and therefore, is randomized. In this sense, the cryptography.max_receiver_specific_macs defines the size of a circular buffer with |RecSpecificKeys|. When |P1| discovers |P2|, |P1| assigns the next key in its buffer to |P2|. Suppose |P2| loses liveliness with |P1|, and they discover again. In that case, |P1| will assign |P2| the next key in its circular buffer, which may differ from the previous one, potentially resulting in a group change with respect to |P1|. Interactions with Persistence Service ------------------------------------- When you enable security, |RTI_PERSISTENCESERVICE| will perform |DataProtection| before storing data into the database, at the level specified by :ref:`p2_core/cryptography:data_protection_kind (topic_rule)`. To do so, |PERSISTENCESERVICE| creates |SecDRs| to subscribe to |TOPICs| with TRANSIENT or PERSISTENT durability (see :link_um:`Introduction to RTI Persistence Service in the Core Libraries User's Manual `), and |SecDWs| to write data to both the network and the database. Hence, after discovering a |TOPIC|, |PERSISTENCESERVICE| creates a :entity:`PRSTDataReader` and a :entity:`PRSTDataWriter`. The :entity:`PRSTDataReader` receives data from the |CONNEXTDATABUS| and verifies (and potentially decrypts) it. The :entity:`PRSTDataWriter` re-encodes the data with its own key before inserting it into the database. The stored encoded data includes the payload and the metadata necessary to validate (and potentially decrypt) it, such as the |CryptoHeader| and |CryptoFooter| (see :ref:`p2_core/cryptography:Serialized data protection`). The first time |PERSISTENCESERVICE| creates a :entity:`PRSTDataWriter`, it randomly generates a |SenderKey| that it stores encrypted in the database row containing the information about the writer. The key used for this encryption is the output of a derivation function whose input is the required user-specified property :property:`dds.data_writer.history.key_material_key` (see :numref:`Properties for Configuring Secure Persistence Service`). The |CryptoPlugin| uses PBKDF2 (Password-Based Key Derivation Function) with SHA-512 (Secure Hash Algorithm with a 512-bit hash value) as the key derivation function, which also takes a random salt as input; and AES-256-GCM as the encryption algorithm. The key derivation function derives both the key and the IV (|IV|) used in the encryption. |PERSISTENCESERVICE| stores the random salt along with the :entity:`PRSTDataWriter`'s encrypted |SenderKey|. When |PERSISTENCESERVICE| restarts, it loads each :entity:`PRSTDataWriter`'s |SenderKey| from the database. To do so, |PERSISTENCESERVICE| needs the same configuration. If a different configuration is provided (e.g., wrong value for :property:`dds.data_writer.history.key_material_key`), |PERSISTENCESERVICE| creation will fail. Note that when |PERSISTENCESERVICE| reads the data from the database, the :entity:`PRSTDataWriter` does NOT verify the MAC stored with the data before sending it out on the wire. It is up to the user |DRs| to verify the MAC. Consequently, if an attacker alters the database's data, the :entity:`PRSTDataWriter` will resend the tampered data many times over the wire until the reliability protocol causes the data to be lost. For further information, see :ref:`p4_integrations/persistence_service:Support for RTI Persistence Service`. Interactions with FlatData and Zero Copy ---------------------------------------- For more information about |SP|'s interactions with |RTI_FLATDATA_TM| *language binding* and *Zero Copy transfer over shared memory*, see the following sections in the *RTI Connext DDS Core Libraries User's Manual*: * :link_um:`Using FlatData Language Binding in the Core Libraries User's Manual ` (see "Interactions with |RTI_SP| and Compression") * :link_um:`Using Zero Copy Transfer Over Shared Memory in the Core Libraries User's Manual ` (see "Interactions with |RTI_SP| and Compression") Pre-Shared Key RTPS Protection ------------------------------ To avoid the discovery-time overhead of mutual authentication and key exchange, you may use the *RTPS-HMAC-Only Plugins* described in :ref:`p3_advanced/rtps_hmac_only_mode:RTPS-HMAC-Only Mode` and provide a pre-shared key with the :property:`hmac_only.cryptography.key` property (see :numref:`Properties for Configuring HMAC-Only Mode`). If you are using the UDP WAN transport and you do not want to use the *RTPS-HMAC-Only Plugins*, you may provide a pre-shared key via the :property:`cryptography.rtps_protection_key` property to protect the binding pings (see :numref:`RTI Security Plugins Properties for Configuring Cryptography`). Properties for Configuring Cryptography ======================================= The :ref:`p2_core/elements_dds_secure_system:QoS Properties` listed in :numref:`RTI Security Plugins Properties for Configuring Cryptography` configure Cryptography: .. list-table:: |RTI_SP| Properties for Configuring Cryptography :name: RTI Security Plugins Properties for Configuring Cryptography :widths: 40 60 :header-rows: 1 :class: longtable * - Property Name (prefix with :property:`com.rti.serv.secure.`) [#fPrefix]_ - Property Value Description * - :property:`cryptography.max_blocks_per_session` - :required:`Optional` The number of message blocks that can be protected with the same |SessionKey|. Whenever the number of blocks exceeds this value, a new |SessionKey| is computed. The block size depends on the encryption algorithm. You can specify this value in decimal, octal, or hex. This value is an unsigned 64-bit integer. :type:`Unsigned integer`: :value:`[1 - MAX_UINT64]` Default: :value:`MAX_UINT64` * - :property:`cryptography.encryption_algorithm` - :required:`Optional` The algorithm that the Sender uses for the encryption transformation. The value of this property determines the |TransformationKind| sent in the protected messages (and through the |SecKeyExchangeCh|) to inform the Receiver about the transformation used to protect the data. The options are :value:`aes-128-gcm`, :value:`aes-192-gcm`, and :value:`aes-256-gcm` ("gcm" is Galois/Counter Mode (GCM) authenticated encryption). The number indicates the number of bits in the key. |DPs| are not required to set this property to the same value in order to communicate with each other. In the |GovernanceDoc|, a :xmltag:`protection_kind` set to :xmlval:`ENCRYPT` will use GCM, and a :xmltag:`protection_kind` set to :xmlval:`SIGN` will use the GMAC variant of this algorithm. :type:`Enum`: :value:`aes-128-gcm`, :value:`aes-192-gcm`, :value:`aes-256-gcm` Default: :value:`aes-128-gcm` * - :property:`cryptography.max_receiver_specific_macs` - :required:`Optional` The maximum number of Receiver-Specific Message Authentication Codes (MACs) that are appended to an encoded result. For example, if this value is 32, and the |DP| is configured to protect both RTPS messages and submessages with |OrigAuthProtection|, there could be 32 |RecSpecificMACs| in the result of ``encode_datawriter_submessage``, and there could be another 32 |RecSpecificMACs| in the result of ``encode_rtps_message``. If there are more than 32 Receivers, the Receivers will be assigned one of the 32 possible MACs in a round-robin fashion. Note that in the case of ``encode_datawriter_submessage``, all the readers belonging to the same |DP| will always be assigned the same |RecSpecificMAC|. Setting this value to :value:`0` will completely disable |RecSpecificMACs|. For further details see :ref:`p2_core/cryptography:Origin Authentication Protection Implications`. :type:`Integer`: :value:`[2, 3275]`, or :value:`0` to completely disable |RecSpecificMACs|. Default: :value:`0` (:xmlval:`WITH_ORIGIN_AUTHENTICATION` protection kinds not allowed) * - :property:`cryptography.share_key_for_metadata_and_data_protection` - :required:`Optional` Indicator of whether the metadata and data encoding operations share the same |KeyMaterial| or use different keys. By default, |DWs| with both :xmltag:`metadata_protection_kind` and :xmltag:`data_protection_kind` set to a value other than :xmlval:`NONE` use the same |KeyMaterial| for protecting both RTPS submessages and serialized data. To change this behavior, set this property to :xmlval:`FALSE`. :type:`Boolean`. Default: :value:`TRUE` (they share |KeyMaterial|) * - :property:`cryptography.rtps_protection_key` - :required:`Optional` Pre-shared key from which |SP| derive the HMAC Key used to compute message authentication codes over UDP WAN binding pings. 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 not set, then UDP WAN binding pings will not be protected with an HMAC operation. |DPs| must set this property to the same value in order to communicate with each other. The purpose of this pre-shared key is to protect against certain DoS attacks against the |RWT|. The value of this property is not used to protect any traffic other than UDP WAN binding pings. All other RTPS traffic still gets protected by the standard |CryptoPlugin|, which uses dynamically-generated keys that are exchanged after authentication completes. For more information, please refer to :ref:`p4_integrations/real-time_wan_transport:Support for RTI Real-Time WAN Transport`. :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 .. [#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 Cryptography Common to Any Cryptography Plugin` lists a set of :ref:`p2_core/elements_dds_secure_system:QoS Properties` that are not exclusive to the shipped |SP|, but that will affect any |CryptoPlugin|. .. list-table:: Properties for Configuring Cryptography Common to Any |CryptoPlugin| :name: Properties for Configuring Cryptography Common to Any Cryptography Plugin :widths: 40 60 :header-rows: 1 :class: longtable * - Property Name - Property Value Description * - :property:`dds.data_writer.history.use_530_encoding_alignment` - :required:`Optional` Determines whether or not to align a serialized payload to a 4-byte boundary before encoding it. If :value:`TRUE`, this alignment does not occur; this is consistent with |CONNEXT| 5.3.0 behavior. If :value:`FALSE`, then this alignment does occur; this is the only way to make the builtin |CryptoPlugin| work with :xmltag:`data_protection_kind` = :xmlval:`SIGN`. This property applies to the DataWriterQos. :type:`Boolean`. Default: :value:`FALSE`