Cryptography is the process of making sure no adversaries can manipulate or
eavesdrop on communication. The Security Plugins cover this process by means of the
Cryptography Plugin. To prevent adversaries from manipulating messages, the
Cryptography Plugin appends a message authentication code (MAC) to the message being
protected, therefore protecting its integrity. To prevent eavesdropping, the
Cryptography Plugin can additionally encrypt the message, protecting its
confidentiality.
Definitions
The Cryptography Plugin 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 Security Plugins, you can specify a different level of protection to each of your
Topics (see 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 SIGN in the
Governance Document. 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 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
NONE, which could be useful to achieve compatibility with unsecure
parts of your system or to save resources.
Note
In the case of Lightweight Builtin Security Plugins, which implements OMG DDS Security 1.2 specification
builtin PSK plugins, the Cryptography Plugin does not support Topic level
protection.
Consequently, the sections in this chapter covering Topic level protection
are only applicable to Builtin Security Plugins or custom security plugins supporting
Topic level protection.
Secure DomainParticipants, Secure DataWriters, and Secure DataReaders use symmetric cryptography to protect the
messages they send. Each of these Secure Entities is associated with different
cryptographic material, preventing unauthorized Entities from participating
in secure communication (see Secure Entities). For
example, when you create a Secure DataWriter, some keys are associated with it. We call
these keys Key Material, and the contents of Key Material are described in
Local Sender’s Key Material. By only
sharing its Key Material with authorized DataReaders, your Secure DataWriter makes sure that
only these Secure DataReaders 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.
Definitions
Unless the documentation indicates differently, the keys (or Key Material)
associated with the Secure Entities are considered to be
AXK. AXK keys are
exchanged after the authentication process is complete and allow granular
security and topic-level protection. On the other hand, there are
Pre-Shared keys (PSK), which are always distributed
out-of-band to Secure DomainParticipants (they are never associated with Secure DataWriters or Secure DataReaders)
and they allow you to protect all traffic from the start-up of a DDS Entity.
For further details, see Pre-Shared Key Protection.
The Cryptography Plugin also puts in place a mechanism to prevent insiders from
pretending to be a different entity. For instance, consider a DataReader that
legitimately subscribes to a DataWriter for a particular Topic. Since symmetric
encryption is used to protect data, the DataReader could potentially use the DataWriter’s
key to send arbitrary samples, thus impersonating it. DataWriters can avoid this
situation by protecting samples with Origin Authentication Protection (see
Origin Authentication Protection).
6.1.1. Cryptography Plugin as an Enabler for Other Plugins
Protecting the confidentiality and integrity of data ensures that other
plugins can do their job correctly.
For example, the Access Control Plugin will prevent your secure DataWriters from
sending samples to DataReaders that do not have permission to subscribe to a specific
Topic. However, if the Cryptography Plugin does not enforce confidentiality by
encrypting your samples, malicious DataReaders 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 Cryptography Plugin provides us
with the building blocks that enable other plugins to work properly. Access Control
decides whether an entity has permission to do something; Cryptography enforces
entities to meet this requirement.
The Authentication Plugin interacts in a similar way with the Cryptography Plugin. While the
Authentication Plugin makes sure a participant is who it claims to be, it is the
Cryptography Plugin that enforces that only authenticated participants have access to
the domain. The Cryptography Plugin achieves this by protecting messages with
keys that have been only shared with successfully authenticated and
authorized participants.
To establish a DDS Secure communication, Secure Entities (i.e., Secure DomainParticipants,
Secure DataWriters, and Secure DataReaders) perform some cryptographic transformations based on some
security parameters and keys. Secure Entities 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
Secure Entities.
In order to exchange the keys that Secure Entities need, mutually authenticated
participants establish an end-to-end channel to exchange sensitive cryptographic
material securely. This Secure Key Exchange Channel allows your Secure DomainParticipants to
confidentially exchange the Key Material that Secure DataWriters and Secure DataReaders need to
communicate. We will describe this channel in more detail in
Secure Key Exchange Channel (ParticipantVolatileMessageSecure Topic).
Secure DataWriters and DataReaders are not only used to protect the user-defined Topics. New secure builtin Endpoint (DataWriters and DataReaders) will be created when you protect the discovery traffic or the liveliness assertions. More concretely, when you protect a Topic’s discovery information, your DomainParticipants will exchange the discovery information for that Topic through the Builtin Secure Discovery Topics. You can also protect liveliness messages exchanged for Topics that have AUTOMATIC or MANUAL_BY_PARTICIPANT (see enable_liveliness_protection (topic_rule)). Protecting liveliness will result in your DomainParticipants exchanging these messages through the Builtin Secure Liveliness Topic (see Builtin Secure Liveliness Topic). Note that these secure builtin Endpoints 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 Security Protections Applied by DDS Entities).
For example, Serialized Data Protection allows you to protect the samples published in a
particular Topic. You could also decide to protect the RTPS submessages for
that particular Topic. Submessage Protection covers both DATA
submessages – which contain the (potentially already-protected) serialized
payload – and submessages containing metadata, such as ACKNACK and
HEARTBEAT submessages (see
Overview of the Reliable Protocol in the Core Libraries User’s Manual).
Finally, you could enable RTPS Protection to protect the complete RTPS
messages that your DomainParticipants put on the network. Note that the protections at
different stages are not mutually exclusive: the Cryptography Plugin 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 Figure 6.1.
For further details, see
Securing DDS Messages on The Wire.
Figure 6.1 Parts of the Message Protected by Each Protection Kind
The Cryptography Plugin uses AES-GCM to protect the traffic (see
Cryptographic Algorithms
for details). 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 DataWriter shares the same key with
multiple DataReaders and, in spite of this, the DataWriter needs to ensure origin
authentication. In this situation the DataWriter should create a separate
Receiver-Specific Key used only for authentication and append additional
Receiver-Specific MACs, each computed with one of the
Receiver-Specific Keys (see Origin Authentication Protection).
The Security Plugins use different cryptographic algorithms for different purposes. Starting
with version 7.0.0, the user can modify and select algorithms supported and used
by Secure Entities. This section describes the symmetric cipher algorithms
that can be configured in the Cryptography Plugin.
In this section, we also describe the relationship between the algorithms that
can be configured in the Cryptography Plugin and the
ParticipantTrustAlgorithmInfo and
EndpointTrustAlgorithmInfo fields,
which are used to propagate the used and supported algorithms for a DomainParticipant.
A complete list of values can be found in Table 18.10.
Note that a Secure Entity may not propagate through discovery the exact list of
algorithms listed in the Governance Document. The reason is that the final value
for a supported mask is an intersection of the algorithms allowed by the
Governance Document and the list of algorithms supported by the DomainParticipant. Remember that
the Governance Document is about system-wide security requirements. Even if the
Governance Document allows an algorithm, the implementation of the Security Plugins for a
DomainParticipant may not support it. For example, the Security Plugins for wolfSSL may support different
algorithms than the Security Plugins for OpenSSL.
Participant Symmetric Cipher Algorithms collect algorithms used to encode
DomainParticipant builtin Endpoint traffic. The following algorithms are supported:
AES-128-GCM
AES-256-GCM
Participant Symmetric Cipher Algorithms specify three algorithm definitions:
supported_mask: A list of symmetric cipher algorithms supported by a DomainParticipant.
The default value includes AES-128-GCM and AES-256-GCM.
builtin_endpoints_required_mask: Indicates the algorithm the DomainParticipant will use
as the symmetric cipher algorithm to encode its protected builtin Endpoints’
traffic. It is determined by the dds.sec.crypto.symmetric_cipher_algorithm
property (see Table 6.8).
By default, it is set to AES-256-GCM.
builtin_kx_endpoints_required_mask: The algorithm used by the DomainParticipant’s
builtin Endpoints to encode key exchange traffic. The default is not set.
user_endpoints_default_required_mask: The default algorithm used by the DomainParticipant’s
Endpoints to encode user data traffic. If the Endpoints’ symmetric cipher
required_mask (see Endpoint Symmetric Cipher Algorithms)
is not serialized on the wire, then the Security Plugins assume that this is the algorithm
used to protect the Endpoints’ traffic.
Endpoint Symmetric Cipher Algorithms collect algorithms used to encode
endpoints’ traffic. The following algorithms are supported:
AES-128-GCM
AES-256-GCM
Endpoint Symmetric Cipher Algorithms specify two algorithm definitions:
supported_mask: A list of the symmetric cipher algorithms supported by the
Endpoint. This field is not propagated as part of the Endpoint Discovery process.
It is also not populated as part of the builtin topic data
trust_algorithm_info
parameter in the
on_data_available
callback. Instead, all bits of the mask are set by default (0xffffffff).
When the builtin topic data is retrieved through the
matched_publication_data
or matched_subscription_data APIs
(depending on whether the Endpoint is a DataWriter or a DataReader) the field is populated
with the information from the associated DomainParticipant’s
supported mask.
required_mask: Indicates the algorithm the Endpoint will use as the symmetric
cipher algorithm to encode its traffic. It must be an algorithm that is
propagated in the DomainParticipant list of supported symmetric cipher algorithms. By default,
it is set to AES-256-GCM. The symmetric cipher that an Endpoint uses is
determined by dds.sec.crypto.symmetric_cipher_algorithm (see
Table 6.8)
We will use the term Secure Entity to refer to one of the following three DDS Entities:
Secure DataWriter: can perform Serialized Data Protection and/or Submessage Protection.
Secure DataReader: can perform Submessage Protection.
Secure DomainParticipant: can perform RTPS Protection.
In other words, a Secure Entity is a DataWriter, a DataReader, or a DomainParticipant that has at least a protection kind different than NONE in its associated Governance Rules.
When a Secure DataWriter sends a sample to its matching DataReaders, it will protect the sample
by applying a cryptographic transformation (parametrized with a key). If, for
example, this is a reliable Topic, the DataReaders also need to send
ACKNACKs to the DataWriter, and these will be protected using the same
cryptographic transformation, but using different keys. As you can see, both
DataWriters and DataReaders need to send protected information to the other Endpoint. In this
sense, we talk about Sender (the entity sending a secure message) and Receiver
(the entity receiving a secure message). Note that every Secure Entity 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 Key Material, 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 Key Material is securely exchanged between matching Secure Entities through the Secure Key Exchange Channel, as described in Secure Key Exchange Channel (ParticipantVolatileMessageSecure Topic).
Secure Entities have some attributes (configuration) and mechanisms (algorithms)
that allow them to communicate securely. In addition, each Secure Entity 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.
Secure Entities need to store and use keys as parameters for the cryptographic
algorithms. Upon its creation, each Secure Entity generates the local Sender’s
Key Material. Receivers in matching Secure Entities need a copy of this
Key Material to validate (and potentially decrypt) the messages from this
Sender, as depicted in Figure 6.2.
Figure 6.2 Architecture Overview of Two Matching Secure Entities. Important: this
figure is a simplified overview, Key Material is never used directly to
protect messages (Session Keys derived from the Key Material are used instead).
To communicate securely, Secure Entities need to perform operations that involve the Cryptography Plugin. 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 Session Key with a limited lifetime. The Session Key derives from cryptographic material generated by the Sender entity upon its creation, then sent to the Receiver upon discovery of the remote entity. The Session Key is a temporary key that will be valid for a particular session and derives from the Sender’s Key Material and Session ID. The Sender will periodically change the Session Key used to protect the messages by changing the Session ID. To let the Receiver know what Session Key it needs to use, the Sender includes the Session ID in every protected message.
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 Governance Rules that apply to this Topic and need to be the same in every Endpoint for this Topic in the secure domain (see Discovery of a Remote Secure Entity). (Governance Rules are user-defined in the Governance Document, see Governance Document).
In the case of a Secure DataWriter, the security attributes define whether the Sender will protect the serialized data and/or the RTPS submessage. Secure DataReaders are limited to protecting the outgoing RTPS submessage, while Secure DomainParticipants 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 Session Key to protect the outgoing messages; matching Receivers will use this same Session Key to validate (and potentially decrypt) the incoming messages.
Upon its creation, Secure Entities generate the local Sender’s Key Material. The
local Sender uses this cryptographic material to communicate with the remote
Receivers securely. The local Sender’s Key Material includes:
the Sender Key
the Sender Key ID, which identifies the Sender Key
the Transformation Kind, which is the algorithm that the Sender uses for
protecting its contents.
Cryptographic algorithms do not use the Sender Key directly to protect
communications. Instead, the Sender derives temporary Session Keys from its
Sender Key (and other parameters from its Key Material). Cryptographic
operations use these temporary keys to protect outgoing messages. These
messages also include the Sender Key ID to allow the Receiver to identify,
within all the Key Material received from a remote DomainParticipant, what Key Material
was used to protect the message. Note that RTPS messages already contain the
Secure Entity’s GUID that identifies the DomainParticipant from which the message originated.
Additionally, the outgoing messages also include a Session ID, which allows
the Receiver to derive the right Session Key by applying certain cryptographic
operations over the selected Sender Key (see
Figure 6.3).
When Origin Authentication Protection is enabled, one additional Receiver-Specific Key per Receiver (identified by the Receiver-Specific Key IDs) are stored in the Secure Entity along with the local Sender’s Key Material. This key is used to derive the Receiver-Specific Session Key, which in turn is used as input to the cryptographic operation that computes the Receiver-Specific MAC of the outgoing messages.
Note that while the Sender Key does not change in the whole lifecycle of the Secure Entity; the Session ID changes periodically (see Secure Communication).
Figure 6.3 Derivation of the Session Key and Receiver-Specific Session Keys
The Receiver in the local Secure Entity needs the remote Sender’s Key Material to validate (and potentially decrypt) messages coming from that remote Sender. Note this is the same Key Material we introduced in Local Sender’s Key Material, but from the Receiver’s perspective. The local Secure Entity will receive the remote Sender’s Key Material through the Secure Key Exchange Channel after the two matching Secure Entities discover and validate each other. The local Receiver derives the Session Key from the remote Sender’s Key Material and the Session ID included in each message. Then, it uses the Session Key to validate (and potentially decrypt) incoming messages (see Secure Communication).
When the Receiver gets a message from the network, it takes the Sender Key ID and the remote Secure Entity’s GUID from the RTPS message. With this information, the Receiver can identify the Sender Key that the Sender used to protect the message from the list of its received keys. Then, it uses the Session ID, also included in the protected message, to compute the Session Key. Finally, the Receiver uses the Session Key to validate (and potentially decrypt) the message.
When Origin Authentication Protection is enabled, an additional Receiver-Specific Key is assigned to the local Receiver. This key is identified by the Receiver-Specific Key ID and is stored as part of the remote Sender’s Key Material. This key is used to derive the Receiver-Specific Session Key, which in turn is used to verify the Receiver-Specific MAC of the incoming messages.
Figure 6.4 Key Derivation in the Sender. The Key Material is stored in the Secure Entity.
Figure 6.5 Key Derivation in the Receiver. The Key Material stored in the Secure Entity is identified with the Sender Key ID, present in the incoming message.
Upon the creation of a Secure Entity, the local Sender Key is generated and stored locally. This is done after the checks from the Access Control Plugin, which verifies that the Entity has permission to do what it’s being created for. Refer to Local Sender’s Key Material for further details on the generated cryptographic material.
To successfully discover, DomainParticipants need to have a compatible configuration for the
participant security attributes. A compatible configuration involves
having the same RTPS Protection kind, the same Discovery Protection, and the
same Liveliness Protection.
The same logic applies to Secure Endpoints and the endpoint security attributes. To
communicate, two matching Secure Endpoints (a Secure DataWriter and a Secure DataReader) need to present the
same Governance Rules for the Topic of these Secure Endpoints.
To support these 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
Governance Compatibility Validation.
Secure DomainParticipants propagate information about their supported and used cryptographic
algorithms during discovery. This information is used to determine matching
between DomainParticipants, matching between Endpoints, and for early detection of configuration
issues. The information that Secure DomainParticipant propagate during discovery about their
cryptographic algorithms has the purpose of optimizing discovery traffic
(do not match with DomainParticipants that do not support your local security algorithms) and
improving debuggability. They are for improving system deployability and making
it easier to detect configuration errors; they are not to enforce security.
DomainParticipants propagate information about cryptographic algorithms in the following
PIDs:
Digital Signature Algorithms: PID_PARTICIPANT_SECURITY_DIGITAL_SIGNATURE_ALGO.
If any of the PID values are set to defaults, or if security is disabled, they
are not propagated. The defaults are compatible with previous Security Plugins releases;
communication with earlier releases is not affected. For detailed information
about supported and default cryptographic algorithms, see
Cryptographic Algorithms in the “Authentication”
chapter and Cryptographic Algorithms in the
“Cryptography” chapter.
Each of these PIDs transmits the following information:
PID_PARTICIPANT_SECURITY_DIGITAL_SIGNATURE_ALGO: This PID has the
authentication and the identity trust chain digital signature algorithms.
The masks are as follows:
message_auth.supported_mask
message_auth.required_mask
trust_chain.supported_mask
trust_chain.required_mask
PID_PARTICIPANT_SECURITY_KEY_ESTABLISHMENT_ALGO: This PID contains a
supported mask and a required mask for the key establishment algorithms.
shared_secret.supported_mask
shared_secret.required_mask
PID_PARTICIPANT_SECURITY_SYMMETRIC_CIPHER_ALGO: This PID contains the
following masks. The local DomainParticipant only checks that the value of these masks is
compatible when protection is enabled at the RTPS level (see
RTPS Protection).
supported_mask: mask of supported algorithms that affects all
endpoints.
builtin_endpoints_required_mask: mask of required algorithms that
affects all builtin endpoints besides the key exchange one.
builtin_kx_endpoints_required_mask: mask of required algorithms that
affects only the key exchange builtin endpoints.
user_endpoints_default_required_mask: mask indicating the default
algorithm used by the DomainParticipant’s Endpoints to encode user data traffic. This
algorithm is assumed to be used by Endpoints that do not send the
PID_ENDPOINT_SECURITY_SYMMETRIC_CIPHER_ALGO PID.
PID_ENDPOINT_SECURITY_SYMMETRIC_CIPHER_ALGO: This PID contains a required
mask with the algorithms that the remote Endpoint must support. The algorithms
that the local Endpoint supports are not part of this PID. They are derived from
the algorithms that the DomainParticipant supports (PID in the previous bullet-point).
Two Secure Entities are compatible with respect to their cryptographic algorithms
if their supported and required masks are compatible. Compatibility between a
supported and required mask depends on whether the highest bit of the required
mask is set. The Security Plugins define the highest bit with a name of
RTI_SECURITY_CRYPTO_ALGORITHM_INFO_BIT_COMPATIBILITY_MODE and its value is the
result of the bitwise AND operation between the required mask and 0x1<<31.
If the highest bit is set, it means that the masks are compatible
as long as they intersect (one of the other bits is set in both). If the
highest bit is not set, it means that all required algorithms must be supported.
In this version of the Security Plugins, the
RTI_SECURITY_CRYPTO_ALGORITHM_INFO_BIT_COMPATIBILITY_MODE bit is only used as
part of the trust_chain.required_mask. In the context of the identity trust
chain, the local DomainParticipant doesn’t have to support all of the digital signature
algorithms from the remote DomainParticipant. One algorithm is enough (as long as it’s one
of the algorithms defined in the OMG DDS Security specification, or it’s a
vendor-specific algorithm but the local and remote DomainParticipants are from
the same vendor). This is because the chain is not always validated completely,
since any of the intermediate certificates in the Identity Certificate might be signed by
the Identity CA. As a result, two DomainParticipants can match but still result in error
during validation of the Identity Certificate.
The RTI_SECURITY_CRYPTO_ALGORITHM_INFO_BIT_COMPATIBILITY_MODE bit is ignored
in the message_auth.supported_mask, message_auth.required_mask,
shared_secret.supported_mask, shared_secret.required_mask,
and the three symmetric cipher algorithm masks.
In the case of the authentication digital signature algorithms, the remote DomainParticipant
computes a signature using the algorithm specified in its
message_auth.required_mask. The local DomainParticipant must support it in order to
verify the signature, and confirm its authenticity. The same requirement is also
true for symmetric cipher algorithms.
Regarding key establishment algorithms, two DomainParticipants will use the preferred key
establishment algorithm from the DomainParticipant that is the authentication initiator. In
that sense, we could argue that it is enough to do the intersection of the
initiator participant shared_secret.required_mask and the non-initiator
shared_secret.supported_mask to determine key establishment algorithm
compatibility. The rationale for doing the matching for both DomainParticipants’
shared_secret.required_mask and shared_secret.supported_mask
is to make sure systems behave consistently independently of who is the
initiator DomainParticipant (i.e., independently of the assigned DomainParticipant’s GUIDs): if
communication would fail depending on who is the initiator, the
key establishment algorithm configuration is determined to be incompatible.
Once the Secure Entities have fully matched (same Topic, same type, compatible QoS, same security attributes) and permissions are checked, they exchange the Key Material through the Secure Key Exchange Channel.
Each of the Secure Entities will register the local Sender’s Key Material and the remote Sender’s Key Material (that is received through the Secure Key Exchange Channel). As specified in Creation of the Secure Entity, the common part of the local Sender’s Key Material is generated upon the entity creation.
When Origin Authentication Protection is enabled, the Receiver-Specific Key Material is also exchanged. In this case, the local DomainParticipant maintains a list with the Receiver-Specific Keys that correspond to the discovered Secure Entities. Since Entities in the same DomainParticipant run in the same application memory space, a single Receiver-Specific Key is assigned to every Secure Entity in a remote DomainParticipant.
At this point, the Secure Entities 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 Sender Key ID and the Session ID. The message will also contain the MAC (a.k.a. the Common MAC), and the Receiver-Specific MACs when Origin Authentication Protection is enabled.
6.3.3. Algorithms Involved in Protecting Secure Entities Traffic
Senders use AES-GCM to encrypt and MAC messages when the ENCRYPT
protection kind is in use. Alternatively, when the 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-bit and 256-bit keys (see
dds.sec.crypto.symmetric_cipher_algorithm in
Table 6.8).
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
Builtin Security Plugins and Lightweight Builtin Security Plugins, the Session Key is used as the symmetric
key, while the Initialization Vector is the
concatenation of the Session ID and the so-called Initialization Vector Suffix.
The same Initialization Vector is associated with all the session keys of a specific Sender,
including the common Session Key and all the Receiver-Specific Session Keys. The
Initialization Vector Suffix is incremented each time any of these keys are used to encrypt
and/or compute a MAC.
The Session ID and Initialization Vector Suffix are sent as part of the protected message,
allowing the Receiver to derive the Session Key and the Receiver-Specific Key that
it will use to validate (and potentially decrypt) the received messages.
As stated in the OMG 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 Session Key and
the Initialization Vector. This is very important for DDS because a DataReader may not receive all the
samples written by a matched DataWriter. The use of DDS ContentFilteredTopics as well
as DDS QoS policies such as History (with KEEP_LAST kind), Reliability
(with BEST_EFFORT kind), Lifespan, and TimeBasedFilter, among others,
can result in a DataReader receiving a subset of the samples written by a DataWriter.
6.3.3.1. Limiting the Usage of a Specific Session Key
The Session Block Counter is an internal counter that keeps track of the number of blocks protected with the same Session Key. Note that GCM uses 128-bit blocks. The purpose of this counter is to ensure that a single Session Key is not used to protect more than the maximum blocks per session, as configured by the cryptography.max_blocks_per_session property (see Table 6.7). The Session Block Counter and the size of the plaintext are used to ensure that 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 Session ID (and derive new session keys) prior to transforming any of the input plaintext.
The change in the Session ID triggers the creation of new session keys, randomizes the Initialization Vector Suffix, and resets the Session Block Counter.
Since the original Key Material (see Local Sender’s Key Material) stays the same even after creating new session
keys, this mechanism is not useful for removing DomainParticipants from the system. The next
section describes the mechanism that may be used for that purpose.
6.3.3.2. Limiting the Usage of Specific Key Material
In order to prevent removed remote DomainParticipants from processing encoded traffic from
the local DomainParticipant, the local DomainParticipant must ensure that the remote DomainParticipants do not have the
Key Material to decode that traffic. And in order to prevent removed malicious
remote DomainParticipants from impersonating trusted DomainParticipants by using previously received
Key Material to do message authentication, the local DomainParticipant must change its
Key Material and tell its peers to use the new Key Material in place of the
old one when authenticating messages. The Security Plugins add all of this functionality to
banish_ignored_participants. When this method is called, the local DomainParticipant
creates a Key Revision. A Key Revision represents a revision of the
Key Material used by the local DomainParticipant and its contained DataReader and DataWriter entities.
After sending the Key Revision to currently legitimate remote DomainParticipants via the
Secure Key Exchange Channel and receiving acknowledgments that the Key Revision was
received, the local DomainParticipant may activate the Key Revision. When a
Key Revision is activated, the new Key Material becomes the Key Material
that is used for encoding new content. Then, this new content will become
indecipherable by remote DomainParticipants that have been removed, while still being
decipherable by currently legitimate remote DomainParticipants. And this new Key Material
will be distinguishable from the old Key Material, which illegitimate remote
DomainParticipants may still possess, so a successful message authentication will actually
be trustworthy.
banish_ignored_participants will still create a new Key Revision even if
there are no new removed DomainParticipants since the last time
banish_ignored_participants was called.
Since Receiver-Specific Keys are only shared with a subset of trusted receivers and
since they are always used in combination with the new Key Material, there is
no need to regenerate Receiver-Specific Keys.
Key Revisions are enabled by default. A DomainParticipant that sets enable_key_revision
Governance Rule to false will not communicate with a DomainParticipant that sets this
Governance Rule to true or with a DomainParticipant of a release older than the 7.0.0
Security Plugins, unless allow_unauthenticated_participants is set to true.
In this case, the two DomainParticipants may communicate either unsecurely or using exclusively Pre-Shared Key Protection.
This happens because on enabling Key Revisions, the contents of the Crypto Header (see
Cryptographic Information Added to RTPS Messages)
become different. The Core Libraries check the compatibility of
enable_key_revision at
DomainParticipant discovery time, which is when it checks for Governance
compatibility in general (see
Governance Compatibility Validation).
Note
In the case of Lightweight Builtin Security Plugins, which implements OMG DDS Security 1.2 specification
builtin PSK plugins, Key Revisions are not applicable (as there is no
Key Material exchanged through the wire). Still, the PSK (distributed
out-of-band) is mutable and can be updated at runtime in order to securely
stop communication with newly-untrusted DomainParticipants.
While you may call the banish_ignored_participants method whenever you want
to, you may not always know when you should call it. To help solve this
problem, the Security Plugins will automatically introduce a new Key Revision under
a set of reasonable circumstances.
As described in Dynamic Certificate Revalidation,
if a DomainParticipant that you are currently communicating with suddenly has its certificate
revoked or expired, then the Security Plugins will stop communicating with it and create a
new Key Revision.
But what if this sudden invalidation of a certificate happens to a DomainParticipant that
you were formerly communicating with? How do the Security Plugins keep track of DomainParticipants
that you are no longer communicating with? This is where the
dds.participant.trust_plugins.max_removed_participants_per_key_revision
property comes into play. When you set this property to a value other than
0, the Security Plugins will keep a minimum state associated with this number of
remote DomainParticipants after you stop communicating with them and after the database
thread removes the deleted remote DomainParticipant records. The Security Plugins will automatically
introduce a new Key Revision and purge all of the elements in this minimum
state when either of the following occurs:
The number of remote DomainParticipants in this state is about to exceed the limit set by
dds.participant.trust_plugins.max_removed_participants_per_key_revision.
Any of the DomainParticipants in this state has its certificate invalidated (e.g., revoked
or expired).
In addition, the minimal state is purged whenever a new Key Revision is
introduced for any reason.
The Security Plugins use this mechanism to ensure that removed remote DomainParticipants whose
certificates are invalidated after their removal are properly banished. As you
would expect, if you set the property to 0, then the Security Plugins will
automatically create a new Key Revision whenever you stop communicating with
any remote DomainParticipant, and therefore the Security Plugins will have no need to keep this minimal
state. So this property empowers you to balance the overhead of frequent
banishments with the overhead of this minimal state. See
Configuration Properties Affecting Any Cryptography Plugin
for the memory footprint of this minimal state.
In order to perform key exchange between Secure Entities, DomainParticipants 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 VOLATILE. The OMG DDS Security specification introduces a new Secure Key Exchange Builtin Topic, also known as the ParticipantVolatileMessageSecure builtin Topic, to exchange these messages.
6.4.1. Secure Key Exchange Builtin Topic Characteristics And Security Attributes
The purpose of the Secure Key Exchange Builtin Topic is to reliably and securely transport the
Key Material between the Secure Entities of different DomainParticipants. This Topic uses a
RELIABILITY QosPolicy of kind RELIABLE and a HISTORY QosPolicy of kind
KEEP_ALL to make sure that keys get to the remote Secure Entity. Also, a
DURABILITY QosPolicy of kind VOLATILE is used to prevent sending data
to unauthorized late joiners. Finally, to protect the confidentiality of
messages sent on this channel, the Secure Key Exchange Builtin Endpoints use encryption as the
Submessage Protection.
The Secure Key Exchange Channel requires a Secure DataWriter and a Secure DataReader in both the local
participant (P1) and the remote participant (P2). The Key Material that
allows a DataWriter and its matching DataReaders to communicate securely is normally
exchanged through this Secure Key Exchange Channel. The only exception is the
Key Material used by this channel’s Secure Endpoints, a Shared Key that will derive
from the information resulting from the authentication process. More concretely,
the Shared Key is derived using HMAC operations on the Challenges exchanged in
the Handshake and the Shared Secret that results from the authentication
process. For more information on these parameters, see
Handshake.
The Key Material derived for the Secure DataWriter and DataReader is identical. Nonetheless,
since only P1 and P2 know the Shared Key, 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 Shared Key is particular to a single authentication session between a
pair of DomainParticipants. 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 Shared Key.
Once the Secure Key Exchange Channel is established, the Key Material for every other Secure Entity is exchanged through it. This Key Material includes the Transformation Kind, Sender Key and Sender Key ID, as well as the Receiver-Specific Key (see Architecture of Secure Entities).
DomainParticipants use this Topic to exchange the Key Material that will be used to protect outgoing RTPS messages (when RTPS Protection is enabled). After that, DomainParticipants exchange the Key Material for the builtin Secure Endpoints, including the Builtin Secure Publication DataWriter and DataReader used for Secure Endpoint Discovery (see Security Builtin Topics). Once your DomainParticipants have exchanged the keys for the builtin Secure Endpoints, they can perform secure discovery, and once they discover particular user-defined DataWriters and DataReaders, the participants will also use this channel to exchange the keys for those Endpoint.
More concretely, during Endpoint Discovery, two mutually authenticated participants (P1 and P2) will send publication and subscription DATA messages to inform their counterpart about their local DataWriters and DataReaders. When P1 discovers that P2 has a DataReader (DR2) matching a local DataWriter (DW1), P1 will register DR2 as a remote endpoint. If Origin Authentication Protection is enabled, P1 will assign DR2 Receiver-Specific Key Material. After this, P1 will send DW1’s local Sender Key Material through the Secure Key Exchange Channel. This message will include DR2’s Receiver-Specific Key Material. P2 will follow the same process: register DW1, assign it some Receiver-Specific Key Material (if Origin Authentication Protection is enabled), and send DR2’s local Sender Key Material to P1. At this point, DW1 and DR2 have all the cryptographic material that they need to communicate securely (see Local Sender’s Key Material).
Suppose that while DW1 and DR2 are communicating, a third DomainParticipant
(P3) and its DataReader (DR3) join the system. DW1 communicates with DR3 for
a while, but then P1 decides that P3 is no longer trustworthy, so P1
calls ignore_participant on P3 and then calls
banish_ignored_participants
(see Limiting the Usage of Specific Key Material).
This call creates a new Key Revision that is shared by bothP1andDW1, as well as by any of P1’s secure builtin endpoints. P1 sends
sends this Key Revision to P2 over the Secure Key Exchange Channel. While P1 waits
for P2 to acknowledge the Key Revision, P1 still uses its old
Key Material to protect outgoing RTPS messages, and DW1 still uses its old
Key Material to protect its outgoing RTPS submessages and data payloads. As
soon as P1 receives an acknowledgment for the Key Revision, P1 activates
the Key Revision, and P1 and DW1 both use the same Key Revision to derive
new Key Material from their respective old Key Material. Then, P1 and DW1
both start using their new Key Material.
If there is a fourth DomainParticipant (P4, which is still trusted) in the system, and
P4 takes too long to acknowledge the Key Revision, then P1 will remove
P4 from its list of legitimate remote participants. You can configure the
timeout for this removal using
dds.participant.trust_plugins.max_key_redistribution_delay.sec.
After P1 removes P4, P1 will activate the Key Revision.
If P1 calls banish_ignored_participants while still waiting to activate
the previous Key Revision, then banish_ignored_participants will not
block. Instead, the Event thread (see
Event Thread in the Core Libraries User’s Manual)
will check every one second if the previous Key Revision has been activated.
When it is activated, the Event thread will create and send the new
Key Revision.
6.5.1. 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 HEARTBEATs, ACKNACKs, etc. To sum up, inside a single RTPS message you can have multiple submessages with different bits of information (see Figure 6.7).
Depending on the protection kind, different parts of the message will be protected.
You can enable Serialized Data Protection by setting the data_protection_kind Governance Rule to a value other than NONE (see data_protection_kind (topic_rule)).
Serialized Data Protection only applies to the Sender in the DataWriter. If not batching, the
DataWriter protects the sample payload right after the serialization. If batching, the
DataWriter protects the entire batch right before the flush. The protected sample or
batch (including the MAC and potentially being encrypted) is stored in the
DataWriter’s queue until sent. When resending samples (for instance, for sending
repairs), the sample is already in the DataWriter’s queue, so additional cryptographic
operations are not needed (see
Interaction Between the Security Plugins and Batching QoS).
Note
Secure DataWriters can only communicate with compatible Secure DataReaders, as described in Discovery of a Remote Secure Entity. In other words, secure and unsecure Endpoints cannot communicate.
From an RTPS point of view, the Serialized Data Protection only protects the payload inside the DATA submessages. Therefore, the Serialized Payload now becomes a Crypto Header, a Serialized Payload/Crypto Content element, and a Crypto Footer, as Figure 6.8 depicts. Note that the Serialized Payload element (unchanged from input) is used when only protecting data integrity (data_protection_kind = SIGN); the Crypto Content element (encrypted Serialized Payload) is used when also protecting data confidentiality (data_protection_kind = ENCRYPT). Also, note that the submessage structure (and number) is not modified.
Figure 6.8 RTPS Message Transformation with Serialized Data Protection
If not batching, then Serialized Data Protection is also applied to instance key data. If
you set
DATA_WRITER_PROTOCOL QosPolicy’s serialize_key_with_dispose
to TRUE, then instance key data will get sent with dispose samples, so
it has to be protected. The protection is applied when you register the
instance, and the protected instance key data is stored in the DataWriter’s queue.
Consequently, no additional cryptographic operations are needed when sending
dispose samples, and a decoding operation is needed if the DataWriter calls
get_key_value.
If batching, then Serialized Data Protection is not applied to instance key data because
Serialized Data Protection is already applied to the entire batch, so there is no need
for further cryptographic operations on the instance key data. Consequently, no
additional cryptographic operations are needed if the DataWriter calls
get_key_value.
You can enable Submessage Protection by setting the metadata_protection_kind Governance Rule to a value other than NONE (see metadata_protection_kind (topic_rule)).
Submessage Protection applies to messages sent both by the DataWriter and the DataReader. The Secure Endpoint will protect the following types of RTPS submessages right before putting them in the wire.
AckNack
AppAck
AppAckConf
Data
DataBatch
DataFrag
DataSession
Gap
Heartbeat
HeartbeatFrag
HeartbeatVirtual
NackFrag
Note
Secure DataWriters can only communicate with compatible Secure DataReaders, as described in Discovery of a Remote Secure Entity. In other words, secure and unsecure Endpoints cannot communicate.
From an RTPS point of view, Submessage Protection protects the submessages by prepending a Secure Prefix Submessage (SEC_PREFIX) – which contains the Crypto Header – to the Secure Body Submessage (SEC_BODY) – which contains the Crypto Content. It also appends a Secure Postfix Submessage (SEC_POSTFIX) – which contains the Crypto Footer. Therefore, the submessage becomes SEC_PREFIX + SEC_BODY + 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 6.9 RTPS Message Transformation with Submessage Protection
RTPS Protection affects the DomainParticipant and applies to every packet [1] that is sent
by protecting the whole RTPS message right before putting it on the network.
The resulting protected packet will consist of an SRTPS Prefix[2]
– which contains the Crypto Header – followed by an SRTPS Body
– which contains the Crypto Content – and an SRTPS Postfix
– which contains the Crypto Footer. RTPS Protection 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.
Note
DomainParticipants with RTPS Protection can only communicate with DomainParticipants that have this
same protection. In other words, when you enable RTPS Protection, secure and
unsecure DomainParticipants cannot interoperate.
From an RTPS point of view, RTPS Protection protects the whole RTPS message, including
the RTPS header. To protect the RTPS header (and its extensions), RTPS Protection uses
one of the following methods:
Copying the RTPS Header into the SRTPS Body and protecting its
integrity with the same mechanism as the rest of the message content.
Figure 6.10 depicts the aforementioned
structure. We will use this protection method when:
cryptography.enable_additional_authenticated_data property is set to
AUTO (the default value), for AXK messages not including an RTPS
Header Extension.
cryptography.enable_additional_authenticated_data property is set to
FALSE, for all messages.
Figure 6.10 RTPS Message Transformation with RTPS Protection
Leveraging Additional Authenticated Data (AAD) of the AES-GCM algorithm.
This protection method does not involve copying the RTPS Header into the
SRTPS Body. Figure 6.11
depicts such a message. We will use this protection method when:
cryptography.enable_additional_authenticated_data property is set
to AUTO (the default value). With this option, messages protected with
PSK and messages including an RTPS Header Extension submessage are protected with
AAD.
cryptography.enable_additional_authenticated_data property is set
to TRUE. With this option, all protected messages are protected with AAD.
Figure 6.11 RTPS Message protected with AAD. Includes an optional RTPS Header Extension submessage.
Note
Lightweight Builtin Security Plugins always protects its outgoing RTPS messages with AAD. It is not
possible to change the protection method.
Origin Authentication Protection 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 DataReader that legitimately subscribes to a DataWriter for a particular Topic. Since symmetric encryption is used to protect data, the DataReader could potentially use the DataWriter’s key to send arbitrary samples, thus impersonating it. DataWriters can avoid this situation by protecting samples with Origin Authentication Protection.
Hint
You can add Origin Authentication Protection to Submessage Protection by setting the metadata_protection_kind Governance Rule to SIGN_WITH_ORIGIN_AUTHENTICATION or ENCRYPT_WITH_ORIGIN_AUTHENTICATION.
You can add Origin Authentication Protection to RTPS Protection by setting the rtps_protection_kind Governance Rule to SIGN_WITH_ORIGIN_AUTHENTICATION or ENCRYPT_WITH_ORIGIN_AUTHENTICATION.
This protection involves computing additional Receiver-Specific MACs 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 Receiver-Specific Key to the Common MAC, and appending the result to it in the Crypto Footer.
The number of Receiver-Specific MACs in an RTPS message is the union of the Receiver-Specific MACs 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 Submessage Protection were set to protect the origin authentication, the first submessage would have the Receiver-Specific MAC for A, the second submessage would have the Receiver-Specific MAC for B, and the third submessage would have the Receiver-Specific MAC for all the matching Endpoints, let’s say A, B, C, and D. Therefore, to satisfy the requirements of every submessage, the RTPS message will include the following Receiver-Specific MACs:
Figure 6.12 Receiver-Specific MACs included in an RTPS Message that uses RTPS Protection with Origin Authentication
Note that adding Origin Authentication Protection to Serialized Data Protection is not allowed (i.e., the 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, Serialized Data Protection happens right before the sample is saved in the DataWriter’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 DataWriter has no information about the DataReaders interested in it. If a DataReader 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 Receiver-Specific MAC appended to it.
The diagram in Figure 6.13 summarizes the location of the protection.
Figure 6.13 Location of the Different Kinds of Protection
Warning
Origin Authentication Protection allows the Receiver to make sure that the Sender is
who it claims to be according to the SampleInfo::publication_handle. If
the Sender uses a different GUID field (i.e., the
SampleInfo::original_publication_virtual_guid or the
SampleInfo::source_guid) to claim to be a different sender,
and the Receiver also uses this field to determine the sender’s origin,
then Origin Authentication Protection does not protect against this kind of
impersonation. This kind of protection comes from the Governance Document and
Permissions Document. For more information, see
DataWriters Acting as a Proxy for other DataWriters.
6.5.2. 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 Session Key. More concretely, the secured message will contain these elements: a Crypto Header, Crypto Content (or Serialized Payload) and a Crypto Footer.
The Crypto Header 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 consists of a transformation_kind
part and a transformation_key_id part. The transformation_key_id contains the
Sender Key ID: four bytes that are used in combination with the identity of
the sending DomainParticipant (already present in the RTPS header) to uniquely identify the
Key Material used to derive the Session Key that protected the message.
The transformation_kind are another four bytes:
If the RTPS message is protected using
Pre-Shared Key Protection, then the first three
bytes are the passphrase key revision (see
Passphrase Identifier). Otherwise, these
three bytes are the identifier of the Key Revision that was used to
protect the message (see
Limiting the Usage of Specific Key Material and
the documentation for the
dds.participant.trust_plugins.key_revision_max_history_depth
property). An identifier of 0 indicates that the original Key
Material (without applying any Key Revisions) was used to protect the
message.
The fourth and final byte is the same Transformation Kind that was sent
during the Secure Key Exchange.
session_id: The session_id is used in combination with the Key Material to derive the cryptographic keys used for the encryption and MAC operations, including the Session Key and the Receiver-Specific Session Key.
initialization_vector_suffix: The initialization_vector_suffix is concatenated with the session_id to produce the Initialization Vector used as an input to the AES-GCM and AES-GMAC cryptographic operations/transformations.
The Crypto Content 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 ENCRYPT protection kinds). Alternatively, the Serialized Payload is sent in plaintext when only the message’s integrity is protected (with SIGN protection kinds).
The Crypto Footer consists of the Common MAC (and the Receiver-Specific MACs, when Origin Authentication Protection is used).
Common MAC: The Common MAC in the Crypto Footer is the authentication tag generated by the AES-GMAC transformation using the Session Key and the Initialization Vector. This transformation operates on the message being protected in plaintext when the SIGN protection kind is used, or on the encrypted message when the protection kind is ENCRYPT. The result is a 128-bit (16-byte) MAC that protects the message integrity.
Receiver-Specific MACs: (only when Origin Authentication Protection is used) The Receiver-Specific MACs in the Crypto Footer are the AES-GMAC tags computed on the Common MAC using each of the Receiver-Specific Session Keys and the same Initialization Vector. Each of the Receiver-Specific MACs is 128-bit (16-byte).
The Receiver-Specific MACs are computed with a secret key that the Sender shares only with a set of Receivers (ideally one). The Receiver-Specific MACs 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 Origin Authentication Protection Implications.
6.6. Security Protections Applied by DDS Entities
Secure Entities 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 Governance Document, you are actually defining the Entities and Secure Entities that are used to transmit the information related to that Topic. This includes:
Whether Secure DataWriters and DataReaders (or regular DataWriters and DataReaders) will be used to transmit the Topic’s payload (along with the Endpoint’s metadata such as HEARTBEATs, ACKNACKs and GAPs submessages).
Whether the Endpoint Discovery 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 AUTOMATIC or MANUAL_BY_PARTICIPANT, as described in enable_liveliness_protection (topic_rule)).
Also, when you enable RTPS Protection, your Secure DomainParticipants 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 DomainParticipants in your secure domain need to protect the different parts of the communication related to your Topic the same way. For this reason, your DomainParticipants need to load compatible Governance documents (see 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.
In an unsecure scenario, Endpoints send packets directly to the network, without going through any DomainParticipant-level protection. This remains the same when you don’t use RTPS Protection. However, you can enable the RTPS Protection by setting the rtps_protection_kind to a value other than NONE. Then the DomainParticipant will intercept the RTPS message produced by your Endpoints (with a callback) and protect the whole message before putting it on the network.
Note that the DomainParticipant will apply RTPS Protection to every outgoing RTPS message except for the following:
DCPSParticipant builtin Topic messages (used in the Participant Discovery Phase)
Binding Ping messages (can be protected with
dds.sec.crypto.rtps_psk_secret_passphrase).
The levels of protection that the Secure DomainParticipant can apply are listed in Table 6.1. Note that this protection will apply to every RTPS message sent by your DomainParticipants. Therefore if you have another type of protection enabled, multiple nested cryptographic operations will be performed on your data.
Table 6.1 Protection Levels Applied by Secure DomainParticipants During RTPS Protection
Governance Rule
ProtectionKind
Level of Protection
rtps_protection_kind
NONE
No protection
SIGN
Integrity
ENCRYPT
Integrity and confidentiality
SIGN_WITH_ORIGIN_AUTHENTICATION
Integrity and origin authentication
ENCRYPT_WITH_ORIGIN_AUTHENTICATION
Integrity, confidentiality, and origin authentication
User-defined Endpoint are responsible for exchanging the Topic’s payload with the Security parameters that you define. You can configure user-defined Endpoints 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 DATA submessages.
Protecting the RTPS submessages implies protecting both DATA submessages (which contain the payload) and other submessages that contain metadata (such as HEARTBEATs, ACKNACKs and GAPs submessages).
Serialized Data Protection and Submessage Protection are performed by the same Secure Entity, but at different stages:
Serialized Data Protection is applied to data in the DataWriter’s queue, before encapsulating it in an RTPS submessage.
Submessage Protection 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 Endpoint to apply different levels of protection at each of these stages, as shown in Table 6.2 and Table Table 6.3.
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 Secure Endpoints you could set data_protection_kind to ENCRYPT and metadata_protection_kind to SIGN. Note that in this case, your DataWriter will perform an AES-GCM operation over the serialized data, storing the encrypted and MAC’d payload in its queue (with its corresponding format: Crypto Header | Crypto Content | Crypto Footer). Then right before putting the data on the network, it will perform an AES-GMAC operation to the DATA submessage, inserting the MAC’d submessage in an RTPS message (with its corresponding format: SEC Prefix | SEC Body | SEC Postfix).
Table 6.2 Protection Levels Applied by user-defined Endpoints for Serialized Data Protection
Governance Rule
ProtectionKind
Level of Protection
data_protection_kind
NONE
No protection
SIGN
Integrity
ENCRYPT
Integrity and confidentiality
Table 6.3 Protection Levels Applied by user-defined Endpoints for Submessage Protection
Governance Rule
ProtectionKind
Level of Protection
metadata_protection_kind
NONE
No protection
SIGN
Integrity
ENCRYPT
Integrity and confidentiality
SIGN_WITH_ORIGIN_AUTHENTICATION
Integrity and origin authentication
ENCRYPT_WITH_ORIGIN_AUTHENTICATION
Integrity, confidentiality, and origin authentication
Builtin Discovery Endpoint are responsible for exchanging the Endpoint Discovery information that allows the local DomainParticipant to discover remote Endpoint (and remote participants to discover the local DomainParticipant’s Endpoint). You can configure whether to use the secure version (or the regular unsecure version) of the Builtin Discovery Endpoints with the enable_discovery_protection Governance Rule. If you set this Governance Rule to 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 Endpoint will apply Submessage Protection to the level you configure with the discovery_protection_kind Governance Rule.
The levels of protection that the Builtin Secure Discovery Endpoints can apply are listed in table Table 6.4. Note that this protection level will apply to the discovery and topic query information for every Topic that sets enable_discovery_protection = TRUE.
Table 6.4 Protection Levels Applied by Builtin Secure Discovery Endpoints and Builtin Secure ServiceRequest Endpoints in the Submessage Protection Stage
Governance Rule
ProtectionKind
Level of Protection
discovery_protection_kind
NONE
No protection
SIGN
Integrity
ENCRYPT
Integrity and confidentiality
SIGN_WITH_ORIGIN_AUTHENTICATION
Integrity and origin authentication
ENCRYPT_WITH_ORIGIN_AUTHENTICATION
Integrity, confidentiality, and origin authentication
6.6.3.1. Secure Topic Query and Locator Reachability Support
Builtin Service Request Endpoint are responsible for exchanging Topic Queries and Locator Reachability responses. The Builtin Secure Service Request Endpoint will apply Submessage Protection to the level you configure with the discovery_protection_kind Governance Rule. (See Builtin Secure ServiceRequest Topic).
The decision about which version of the Builtin Service Request endpoint (secure or not secure) the DataReader uses to send Topic Queries will depend on the value configured for the enable_discovery_protection Governance Rule for that DataReader.
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 Liveliness Endpoint are responsible for maintaining the liveliness of Topics that set the LIVELINESS QosPolicy to AUTOMATIC or MANUAL_BY_PARTICIPANT (see 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 enable_liveliness_protection Governance Rule. If you set this Governance Rule to 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 Endpoint will apply Submessage Protection to the level you configure with the liveliness_protection_kind Governance Rule.
The levels of protection that the Builtin Secure Liveliness Endpoints can apply are listed in table Table 6.5. Note that this protection level will only apply to Topics that set the LIVELINESS QosPolicy to one of the values listed above and set enable_liveliness_protection = TRUE.
Table 6.5 Protection Levels Applied by Builtin Secure Liveliness Endpoints at the Submessage Protection Stage
Governance Rule
ProtectionKind
Level of Protection
liveliness_protection_kind
NONE
No protection
SIGN
Integrity
ENCRYPT
Integrity and confidentiality
SIGN_WITH_ORIGIN_AUTHENTICATION
Integrity and origin authentication
ENCRYPT_WITH_ORIGIN_AUTHENTICATION
Integrity, confidentiality, and origin authentication
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 Governance Document. For information on what Secure Entity is responsible for protecting each part of the message, see Security Protections Applied by DDS Entities.
Attributes whose names end with _protection_kind share a type called
ProtectionKind. The OMG DDS Security specification lists five possible values of
ProtectionKind, all of which are supported by the Security Plugins.
NONE indicates that no cryptographic transformation is applied.
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 Crypto Footer). If the Receiver finds a missing or incorrect MAC, the Receiver will reject the content.
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 Crypto Footer). If the Receiver finds a missing or incorrect MAC, the Receiver will reject the content.
ProtectionKinds ending in _WITH_ORIGIN_AUTHENTICATION indicate that
in addition to using the Sender’s key to generate a Common MAC, the Sender
generates Receiver-Specific MACs using keys that are only shared with a subset of
Receivers (ideally, only one). The additional MACs are placed after the
Common MAC (also in the Crypto Footer). 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 Common MAC, the
Receiver will reject the content. If the Receiver finds a missing or incorrect
Receiver-Specific MAC that was computed using its own Receiver-Specific Key, the Receiver
will reject the content. For further details,
see Origin Authentication Protection).
Note
The rtps_protection_kind values ending in
_WITH_ORIGIN_AUTHENTICATION are allowed only if the value of the
property cryptography.max_receiver_specific_macs is not
0.
All other *_protection_kind values ending in
_WITH_ORIGIN_AUTHENTICATION are allowed only if the value of the
property cryptography.max_receiver_specific_macs is greater
than 1 (In particular, AUTO is not allowed. See
Table 6.7
and
Origin Authentication Protection Implications.)
The ProtectionKinds ending in _WITH_ORIGIN_AUTHENTICATION are as follows:
SIGN_WITH_ORIGIN_AUTHENTICATION indicates that a Common MAC is performed on the content, and Receiver-Specific MACs are performed on the Common MAC. This provides integrity and origin authentication protections.
ENCRYPT_WITH_ORIGIN_AUTHENTICATION indicates that a GCM is performed on the content, and Receiver-Specific MACs are performed on the Common MAC. This provides integrity, confidentiality, and origin authentication protections.
This ProtectionKind specifies how to protect a DomainParticipant’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 allow_unauthenticated_participants = TRUE,
rtps_protection_kind must be set to NONE. Setting
rtps_protection_kind to NONE will cause the DomainParticipant to accept
both protected and unprotected incoming RTPS messages. Setting
rtps_protection_kind to something other than NONE will
cause the DomainParticipant to reject incoming RTPS messages that have a missing or
incorrect MAC.
This ProtectionKind specifies how to protect RTPS bootstrapping messages.
From the point of view of the Security Plugins, we consider RTPS bootstrapping messages
to include all the messages that are exchanged before the Secure Key Exchange
Channel (see
Secure Key Exchange Channel (ParticipantVolatileMessageSecure Topic))
can deliver the participant symmetric keys.
RTPS bootstrapping messages currently include: SPDP messages,
SPDP2 bootstrap messages, Authentication messages, Secure Key Exchange Channel
messages, and Locator Ping messages. Bootstrapping messages aren’t protected by
the rtps_protection_kind ProtectionKind.
The rtps_psk_protection_kind ProtectionKind supports the values
NONE, SIGN, and ENCRYPT. The
WITH_ORIGIN_AUTHENTICATION protection kinds are not allowed. Values
different than NONE require setting a pre-shared key seed and
algorithm consistently throughout your system. For details on
the dds.sec.crypto.rtps_psk_secret_passphrase and
dds.sec.crypto.rtps_psk_symmetric_cipher_algorithm properties, see
Table 6.8.
To learn more about how Pre-Shared Key Protection works, read the
Pre-Shared Key Protection section.
A special case is when Pre-Shared Key Protection is enabled and the value of
rtps_protection_kind is NONE. If so, the Cryptography Plugin protect all
RTPS messages according to the ProtectionKind in
rtps_psk_protection_kind. In this case, to reduce discovery-time
overhead, consider using the Lightweight Builtin Security Plugins (read
The Lightweight Builtin Security Plugins) if your
application doesn’t require authentication or access control.
Warning
The Lightweight Builtin Security Plugins do not support the Governance Document, so they have the
dds.sec.access.rtps_psk_protection_kind property for
configuring this ProtectionKind. This property has the same effect as the
rtps_psk_protection_kind Governance Rule. Do not configure the
dds.sec.access.rtps_psk_protection_kind property in the
Builtin Security Plugins.
This ProtectionKind specifies the metadata_protection_kind used for
the secure builtin DataWriter and DataReader entities used for discovery, Topic Queries,
and Locator Reachability Responses.
The discovery_protection_kind will protect Endpoint Discovery for the Topics
that set enable_discovery_protection. This includes information
exchanged for discovering new Endpoint and for updating existing ones, as described
in enable_discovery_protection (topic_rule). The
discovery_protection_kind will also protect messages that contain
updates to the existing DomainParticipants. Note that new DomainParticipant discovery announcements are
never protected (but updates to existing DomainParticipants are protected).
This ProtectionKind specifies the metadata_protection_kind used for
the secure builtin DataWriter and DataReader entities used for liveliness.
The liveliness_protection_kind will protect liveliness information
from Topics that set enable_liveliness_protection (only if the
DataWriter’s LIVELINESS QosPolicy is AUTOMATIC or
MANUAL_BY_PARTICIPANT, as described in
enable_liveliness_protection (topic_rule)).
This ProtectionKind specifies the metadata_protection_kind used
for the builtin DataWriter and DataReader entities used for exchanging periodic and
event metrics in the RTI Connext Observability Framework. If it is not
present in the Governance Document, the protection level is inherited from
discovery_protection_kind.
The final value used for the protection kind (originating either from
monitoring_metrics_protection_kind or discovery_protection_kind)
has an impact on DomainParticipant matching.
If the monitoring metrics channel is enabled on both the local and remote DomainParticipant, the
protection kind used by the builtin entities must be equal.
This ProtectionKind specifies the metadata_protection_kind used
for the builtin DataWriter and DataReader entities used for exchanging logging messages
in the RTI Connext Observability Framework. If it is not present in the
Governance Document, the protection level is inherited from
discovery_protection_kind.
The final value used for the protection kind (originating either from
monitoring_logging_protection_kind or discovery_protection_kind)
has an impact on DomainParticipant matching.
If the monitoring logging channel is enabled on both the local and remote DomainParticipant, the
protection kind used by the builtin entities must be equal.
This ProtectionKind specifies the metadata_protection_kind used
for the builtin ServiceRequest DataWriter and DataReader. The ServiceRequest channel is a
builtin channel created per DomainParticipant. It is used for a variety of features, including
Topic Query, Instance State Consistency and Locator Reachability.
If the service_request_protection_kind tag is not present in the Governance Document,
the protection kind is derived from the discovery_protection_kind.
The final value used for the protection kind (originating either from
service_request_protection_kind or discovery_protection_kind)
has an impact on DomainParticipant matching.
This ProtectionKind specifies the metadata_protection_kind used
by the builtin DataWriters and DataReaders of the Instance State Consistency channel(s).
Instance State Consistency DataWriters and DataReaders are builtin DataWriter and DataReader that are
created per Publisher and Subscriber. They are only created if a user’s DataWriter or
DataReader within that Publisher or Subscriber has configured Instance State Consistency
within the Reliability QoS Policy.
If the instance_state_consistency_protection_kind tag is not present
in the Governance Document, the protection kind is derived from the
discovery_protection_kind.
The final value used for the protection kind (originating either from
instance_state_consistency_protection_kind or
discovery_protection_kind) has an impact on endpoint matching. When
entities with instance state consistency enabled are created, the protection
kind configured for the instance state consistency is compared, and if not
equal the participants are marked as incompatible. This compatibility check is
only performed if both the DomainParticipants use versions of DDS that support
Instance State Consistency.
This ProtectionKind specifies the metadata_protection_kind used
by the builtin DataWriters and DataReaders of the TypeLookup Service Channel. By default the
protection kind of the TypeLookup Service Channel is ENCRYPT (matching
the configuration of the Secure Key Exchange Builtin Topic).
The type_lookup_protection_kind provides the ability to configure the
ProtectionKind to something other than ENCRYPT. This configuration
option is not part of the OMG DDS Security specification (which explicitly states that
the ProtectionKind of the TypeLookup Service Channel should be
ENCRYPT). See Differences Affecting Builtin Plugins to be Addressed by Next DDS Security Specification
for more information about this configuration setting.
The protection of the TypeLookup Service Channel is defined explicitly in the
DDS-Secure specification without this ProtectionKind. However, the specification
does not provide a way to prevent insider attacks (by way of configuring origin
authnetication on the channel). This extension to the specification provides a
way for users to mitigate inisder attacks.
This ProtectionKind is optional. If left unset, the protection of the TypeLookup
Service channel will be exactly as defined by the specification.
This element determines the security algorithms that are allowed in your system.
There are four families of algorithms. You can specify the list of approved
system-wide algorithms for each of the families:
digital_signature: Configures the digital signature algorithms that
DomainParticipants can use for generating and validating signatures during the
authentication process. Unless
digital_signature_identity_trust_chain is set,
digital_signature also configures the digital signature algorithms
that DomainParticipants can use in the context of the identity trust chain. These are the
algorithms that are allowed when verifying the Identity Certificate (local or
remote) against the Identity Certificate Authority. Its possible values are
RSASSA-PSS-MGF1SHA256+2048+SHA256,
RSASSA-PKCS1-V1_5+2048+SHA256, ECDSA+P256+SHA256, and
ECDSA+P384+SHA384.
digital_signature_identity_trust_chain: If set, overwrites the
configuration of digital_signature for configuring the digital
signature algorithms that DomainParticipants can use in the context of the identity trust
chain. These are the algorithms that are allowed when verifying the
Identity Certificate (local or remote) against the Identity Certificate Authority.
Its possible values are: RSASSA-PSS-MGF1SHA256+2048+SHA256,
RSASSA-PKCS1-V1_5+2048+SHA256, ECDSA+P256+SHA256,
ECDSA+P384+SHA384, EDDSA+ED25519+SHA512
(<< experimental >>), and EDDSA+ED448+SHAKE256 (<< experimental >>).
key_establishment: Algorithms that DomainParticipants can use for key
establishment. Its possible values are: DHE+MODP-2048-256,
ECDHE-CEUM+P256, ECDHE-CEUM+P384,
ECDHE-CEUM+X25519 (<< experimental >>), and
ECDHE-CEUM+X448 (<< experimental >>).
symmetric_cipher: Algorithms that DomainParticipants and their endpoints can use
for symmetric cipher operations. Its possible values are:
AES128+GCM, and AES256+GCM.
Secure DomainParticipants propagate their list of supported and allowed algorithms during
discovery. Two DomainParticipants will match or not, depending on their supported and allowed
algorithms. They will try to authenticate each other only if they are
compatible.
You can allow the DomainParticipants in your system to use any supported security
algorithm if you don’t add the allowed_security_algorithms XML
element to the Governance Document. In that case, the only restriction comes from
the implementation of the Cryptography Plugin. For example, a particular crypto library may
not support some algorithms. The Cryptography Plugin will internally populate the supported
algorithms and let other DomainParticipants know about them during discovery.
Instead of allowing all security algorithms, you can minimize discovery overhead
by choosing the values of your allowed_security_algorithms to match
the OMG DDS Security 1.2 specification defaults for discovery. You can do so with a Governance Document
like the following one:
<?xml version="1.0" encoding="UTF-8"?><ddsxmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:noNamespaceSchemaLocation="../schema/dds_security_governance.xsd"><domain_access_rules><domain_rule><domains><id_range><min>0</min></id_range></domains><!-- This configuration allows for the default algorithms defined in the OMG DDS Security 1.2 spec. --><allowed_security_algorithms><digital_signature_identity_trust_chain><algorithm>RSASSA-PSS-MGF1SHA256+2048+SHA256</algorithm><algorithm>RSASSA-PKCS1-V1_5+2048+SHA256</algorithm><algorithm>ECDSA+P256+SHA256</algorithm></digital_signature_identity_trust_chain><digital_signature><algorithm>RSASSA-PSS-MGF1SHA256+2048+SHA256</algorithm><algorithm>ECDSA+P256+SHA256</algorithm></digital_signature><key_establishment><algorithm>DHE+MODP-2048-256</algorithm><algorithm>ECDHE-CEUM+P256</algorithm></key_establishment><symmetric_cipher><algorithm>AES128+GCM</algorithm><algorithm>AES256+GCM</algorithm></symmetric_cipher></allowed_security_algorithms><!-- Use the allowed_security_algorithms above to minimize discovery overhead. This configuration also: * Ensures interoperability with DomainParticipants prior to version 7.0.0. * But it is not required for it. You can use a Governance Document that doesn't restrict the security algorithms throughout your system, and interoperability with older versions will not be affected. * Is required for interoperability between: * The Security Plugins 7.0, 7.1, or 7.2. * The Security Plugins 7.3 (or later), or any other secure implementation supporting the discovery algorithm information specified in the OMG DDS Security 1.2 spec. --><allow_unauthenticated_participants>false</allow_unauthenticated_participants><enable_join_access_control>true</enable_join_access_control><discovery_protection_kind>ENCRYPT</discovery_protection_kind><liveliness_protection_kind>SIGN</liveliness_protection_kind><rtps_protection_kind>SIGN</rtps_protection_kind><topic_access_rules><topic_rule><topic_expression>*</topic_expression><enable_discovery_protection>true</enable_discovery_protection><enable_liveliness_protection>true</enable_liveliness_protection><enable_read_access_control>true</enable_read_access_control><enable_write_access_control>true</enable_write_access_control><metadata_protection_kind>ENCRYPT</metadata_protection_kind><data_protection_kind>ENCRYPT</data_protection_kind></topic_rule></topic_access_rules></domain_rule></domain_access_rules></dds>
These defaults are the values that remote DomainParticipants assume if no information
regarding the security algorithms is received from a DomainParticipant. Unless your system
has to support additional algorithms, use this combination in order to minimize
discovery traffic.
Warning
The Security Plugins did not support restricting their algorithms before
version 7.0.0. New DomainParticipants will assume that old DomainParticipants support and use the
default algorithms. These algorithms are specified in the OMG DDS Security 1.2 specification and
listed in the Governance Document above.
Interoperability with DomainParticipants prior to version 7.0.0 is not affected if you
don’t add the allowed_security_algorithms XML element to the
Governance Document (it means, all security algorithms are supported). This is
the case if you use a single Governance Document for all the DomainParticipants in your
system (new and old). Besides minimizing discovery traffic, the
Governance Document above also ensures interoperability with DomainParticipants prior to
version 7.0.0.
However, communication may fail with older DomainParticipants if the
allowed_security_algorithms tag in the Governance Document of the new
DomainParticipants is different from the one in this section (the OMG default values for
discovery). Communication will not happen if matching between the
allowed_security_algorithms configured in the Governance Document
and the OMG-default algorithms (assumed by the new DomainParticipant about the old one)
fail. This mismatch may certainly be a result of a wrong assumption. After
all, the new DomainParticipant can’t do better because it doesn’t know the actual
algorithms used and supported by the old DomainParticipant. In this case, you have this
information when designing your system. Choose the security algorithms that
your DomainParticipants allow so that interoperability is not affected. For example,
matching with older DomainParticipants may fail if you don’t allow the
AES128+GCM symmetric cipher algorithm. The reason is the default
value of the cryptography.encryption_algorithm property
(dds.sec.crypto.symmetric_cipher_algorithm in newer releases)
changed in version 7.0.0 from AES128+GCM to AES256+GCM.
Note that interoperability with the Security Plugins 7.0, 7.1, and 7.2
feature releases requires using the Governance Document in this section.
If the dds.participant.trust_plugins.key_revision_max_history_depth
property is not set, then setting enable_key_revision to
true will effectively set
dds.participant.trust_plugins.key_revision_max_history_depth to a
non-zero value, and setting enable_key_revision to
false will effectively set
dds.participant.trust_plugins.key_revision_max_history_depth to
0.
If the dds.participant.trust_plugins.key_revision_max_history_depth
property is set, then it may be 0 if and only if
enable_key_revision is false; otherwise, DomainParticipant creation will
fail with an error message similar to this one:
PRESParticipant_setupSecurity:INCONSISTENT FAILURE | dds.participant.trust_plugins.key_revision_max_history_depth property value should be 0 if and only if key revisions are disabled in the trust plugins. Your property value is 8.
enable_key_revision is an optional element. If it is not specified,
the default value is true.
This ProtectionKind specifies how to protect a DataWriter’s or DataReader’s outgoing RTPS submessages. These submessages include, but are not limited to, DATA, HEARTBEAT, ACKNACK, APP_ACK, and GAP. (For the full list of affected RTPS submessages, refer to Submessage Protection.) Note that DATA submessage is an envelope around a serialized payload, so metadata_protection_kind affects data as well as metadata.
This attribute may be NONE, SIGN, or ENCRYPT. It specifies how to protect a DataWriter’s serialized payload, as described in Serialized Data Protection.
The DataWriter applies this protection upon adding the serialized payload to the DataWriter’s queue (the DataWriter’s queue stores the protected payload). In that sense, one difference between metadata_protection_kind and data_protection_kind is that for 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.
Receiver-Specific MACs are never included in this protection, so the ProtectionKinds ending in _WITH_ORIGIN_AUTHENTICATION are not allowed for this attribute.
This attribute may be TRUE or FALSE. It specifies whether to use the secure or unsecure builtin Endpoint for certain outgoing traffic related to this Topic. Such traffic includes Endpoint Discovery messages, TopicQuery messages, and Instance State Transition requests. enable_discovery_protection also specifies whether or not to reject unsecure incoming Endpoint Discovery messages related to this Topic. For further details, see Builtin Secure Discovery Endpoints.
This attribute may be TRUE or FALSE. The value of this attribute matters only if the DataWriter’s LIVELINESS QosPolicy is AUTOMATIC or MANUAL_BY_PARTICIPANT (see LIVELINESS QosPolicy in the Core Libraries User’s Manual). In either of these cases, enable_liveliness_protection specifies whether or not to use the secure builtin Endpoint for exchanging liveliness messages for DataWriters of this Topic. Otherwise, when LIVELINESS QosPolicy is MANUAL_BY_TOPIC, this attribute does not take effect and it is the user-defined Secure Endpoints that take care of liveliness assertions, which are protected with metadata_protection_kind. For further details, see Builtin Secure Discovery Endpoints.
6.8.1. 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 data_protection_kind, metadata_protection_kind, or rtps_protection_kind to a value other than NONE, the DataReader may reject a sample due to MAC verification (for example, if the sample is tampered). When this happens, the DataReader does not deliver the sample to the application, and the sample is lost. If the RELIABILITY QosPolicy is set to RELIABLE, however, the DataWriter 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 metadata_protection_kind or rtps_protection_kind is a value other than NONE, the sample will be rejected before reaching the DataReader queue.
If Submessage and RTPS Protection checks passed, and data_protection_kind is set to a value other than NONE, the sample will be rejected by the DataReader queue (or lost, in the case of best effort communication).
6.8.2. Configuring Reliability Protocol Settings of the Secure Key Exchange Topic
The Security Plugins support configuring the reliability protocol settings of the Secure Key Exchange (ParticipantVolatileMessageSecure) builtin topic, which is a reliable Topic. You can configure this by modifying the DDS_DiscoveryConfigQosPolicy (see 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 Table 6.6.
If a Secure Key Exchange DataWriter marks a Secure Key Exchange DataReader as inactive
(due to a lack of response within the max_heartbeat_retries number of
periodic heartbeats), and if allow_unauthenticated_participants =
FALSE, then the DataWriter’s DomainParticipant will remove the DataReader’s DomainParticipant as if
liveliness were lost. Without this removal, the DomainParticipants will unrecoverably stop
communicating with each other due to a pending Secure Key Exchange sample being
removed from the writer queue and never resent. Removing the DomainParticipant will at least
provide an opportunity to reestablish communication after a new round of
discovery, authentication, and key exchange. The only time this removal doesn’t
happen is when allow_unauthenticated_participants = TRUE
and the local Secure Key Exchange DataWriter or DataReader has never successfully received
traffic from the DomainParticipant. In that case, the local DomainParticipant will treat the remote DomainParticipant
as an unauthenticated DomainParticipant and will only communicate with its unsecure
endpoints.
Table 6.6 DDS_DiscoveryConfigQosPolicy Fields Affecting the RTPS Protocol-Related Configuration of the Secure Key Exchange Builtin Topic
As mentioned in Submessage Protection, the protection of AppAck submessages is determined by metadata_protection_kind. Therefore, if an AppAck contains valid response data, that response data’s protection is determined by metadata_protection_kind (not data_protection_kind). Moreover, the Topic’s enable_read_access_control (not enable_write_access_control) determines whether the DataReader is allowed to match with a DataWriter and send such AppAcks. With that in mind, a DomainParticipant with permission to read but not write the Topic could create a DataReader (let’s call it DR1) whose response data always contains all of the sample’s contents being acknowledged. Even if no other DataReaders can interpret the AppAck response data as a data sample (because the response data would not be coming from a 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 metadata_protection_kind to ENCRYPT. Doing so will force DR1 to set metadata_protection_kind to ENCRYPT to match with the DataWriter, ensuring that DR1 will encrypt its response data.
Warning
In version 5.3.x or below of the Security Plugins, it’s still possible to misconfigure DR1 not to encrypt its response data – DR1 would still match with the DataWriter despite setting metadata_protection_kind not equal to ENCRYPT.
As described in Origin Authentication Protection, protecting the origin authentication of a message involves computing and sending a Receiver-Specific MAC to each of the message’s Receivers.
By default (i.e., when cryptography.max_receiver_specific_macs is
AUTO), when rtps_protection_kind is set to a value ending in
_WITH_ORIGIN_AUTHENTICATION, each receiving DomainParticipant is assigned a unique
Receiver-Specific Key, and the Builtin Security Plugins send the Receiver-Specific MACs of all
of the message’s destinations when sending a message. If these
Receiver-Specific MACs cause the message to exceed the message_size_max
configured in the transports used by Connext
(see Setting Builtin Transport Properties with the PropertyQosPolicy in the Core Libraries User’s Manual),
then Connext will continuously resend the same message, appending different
Receiver-Specific MACs with each resend, until it sends all of the
Receiver-Specific MACs.
Note
The value of the property
cryptography.max_receiver_specific_macs cannot be AUTO (default)
if any non-rtps*_protection_kind values end in
_WITH_ORIGIN_AUTHENTICATION. The only
_WITH_ORIGIN_AUTHENTICATION protection kind that supports
AUTO is rtps_protection_kind (see
Table 6.7).
6.8.4.1. Reducing Performance Impact of Origin Authentication
You can reduce the performance impact of ProtectionKinds ending in
_WITH_ORIGIN_AUTHENTICATION by limiting the number of
Receiver-Specific MACs in your Secure Domain with the
cryptography.max_receiver_specific_macs property (see
Table 6.7).
However, this is not recommended because it will make your system more
vulnerable to integrity and availability attacks. Do not set the
cryptography.max_receiver_specific_macs property unless you
understand the security risks.
A couple of examples:
Assume that you set cryptography.max_receiver_specific_macs to 10,
and you have 20 DomainParticipants in your Secure Domain. In this case, you will have
groups of 2 participants who share the same Receiver-Specific Key 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.
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 Receiver-Specific Key. 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 Sender Key: generated by the Sender on the Secure Entity creation. It is
only exchanged with Secure Entities matching that of the Sender – for instance,
two DataReaders in different DomainParticipants matching the same DataWriter.
The Receiver-Specific Key: assigned by a DomainParticipant to the other DomainParticipants it discovers.
The cryptography.max_receiver_specific_macs property, when set to
a positive integer, limits the number of different Receiver-Specific Keys a DomainParticipant
will assign. These keys are assigned in a round-robin fashion – for
instance, with cryptography.max_receiver_specific_macs set to
5, P6 and P1 will share the same Receiver-Specific Key.
Choosing a reasonable value for this property will depend on multiple factors, such as your system’s number of DomainParticipants and number of Topics.
Let’s consider the following scenarios, assuming that all the DomainParticipants in your
system set cryptography.max_receiver_specific_macs to 5:
In a Secure Domain in which DomainParticipantP0 sends content to six other DomainParticipants, only P1 and P6 will share the Receiver-Specific Key. 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 DataReaders for the same Topic and have matched the same DataWriter (otherwise, they won’t have the Sender Key to generate the Common MAC.
In a Secure Domain with 100 DomainParticipants, there will be five groups of 20 participants with the same Receiver-Specific Key. In this case, a malicious DomainParticipant could only impersonate the other 19 DomainParticipants with which it shares the Receiver-Specific Key.
As suggested by the second example, the cryptography.max_receiver_specific_macs allows you to divide DomainParticipants 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 Receiver-Specific Keys. 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.
6.8.5. Reencoding Protected Data when Regenerating Keys
As mentioned in Serialized Data Protection and
Instance Key Data Protection, a DataWriter
that protects its serialized data stores the protected serialized data and
instance key data in its queue. And as described in
Limiting the Usage of Specific Key Material, it is
possible for a DataWriter to change its Key Material during its lifetime. In this
section, we describe what happens to the stored protected data when new
Key Revisions are introduced.
The enable_key_revision Governance Rule determines whether or not to enable
Key Revisions, and the property
dds.participant.trust_plugins.key_revision_max_history_depth
determines how many
Key Revisions to keep locally. When the DomainParticipant calls banish_ignored_participants
enough times for the number of Key Revisions to reach this limit, the DomainParticipant
must remove the oldest Key Revision in order to make space for the next
Key Revision. But what if there still exists a sample in the queue that was
protected using the oldest Key Revision?
Let’s consider that we have the following:
S0: A sample that was protected using the oldest Key Revision.
DW1: The sample S0 exists in this DataWriter’s queue.
P1: The local DomainParticipant that is calling banish_ignored_participants. DW1
belongs to this DomainParticipant.
P2: A new DomainParticipant that joins the system.
DR2: A DataReader with DURABILITY QosPolicy of kind TRANSIENT_LOCAL that
belongs to P2.
Then, the following could happen:
P1 removes the oldest Key Revision.
P2 joins the system.
P1 sends P2 its seven most recent Key Revisions (see
Secure Key Exchange), which do not include the
oldest Key Revision because it was just removed.
When DR2 receives S0 from DW1, DR2 is unable to decode S0
because it doesn’t have the necessary Key Revision.
To solve this problem, DW1 has to reencode S0 with the latest
Key Revision before P1 removes the oldest Key Revision. The reencoding
involves these steps, which are automatically done by the Security Plugins:
Block the DataWriter’s Publisher. The DataWriter has to stop writing data during the
reencoding.
Decode using the same Key Revision that was used to encode. The
Key Revision identifier in the Crypto Header
identifies which Key Revision was used to encode.
Encode using the latest Key Revision.
After this reencoding, DR2 will have the necessary Key Revision to decode
S0.
Note that P1 sends P2 only its seven most recent Key Revisions. This
number is called the Key Revision Window Size. The number is eight instead
of key_revision_max_history_depth in order to do the following:
Limit the amount of memory P2 needs for keeping track of the Key Revisions
used by P1 and all of the other DomainParticipants communicating with P2.
Limit the amount of network traffic P1 needs for sending Key Revisions to
late-joining DomainParticipants.
As a further optimization, the
Key Revision Window Size is reduced from seven to one if P1 never creates any
DataWriters with the RELIABILITY QosPolicy kind set to RELIABLE and
the data_protection_kind Governance Rule set to a value other than
NONE.
Also note that key_revision_max_history_depth is allowed to be greater than
eight. Consider this scenario:
P1 has key_revision_max_history_depth set to 8.
A KEEP_LAST DataWriter from P1 encodes S0 using the original Key Material
(revision 0).
When P1 has to make space for revision 8, the DataWriter has to
reencode S0.
Before sending out S0 to any DataReaders, the DataWriter writes a sample that
replaces S0 in the DataWriter’s queue.
That reencoding of S0 has become wasted effort.
To avoid this wasted effort, P1 can set key_revision_max_history_depth to
a value greater than 8. Then, the DataWriter will only reencode S0 if
it is actually requested by a DataReader through a NACK message. This is known as
lazy reencoding because it only happens when it’s required by a DataReader. This
configuration avoids wasted reencodings at the cost of additional memory. See
Configuration Properties Affecting Any Cryptography Plugin
for the memory footprint of Key Revisions.
Unlike non-lazy reencoding, lazy reencoding does not require blocking the
DataWriter’s Publisher.
When you enable security, RTIPersistence Service will perform Serialized Data Protection before storing data into the database, at the level specified by data_protection_kind (topic_rule). To do so, Persistence Service creates Secure DataReaders to subscribe to Topics with TRANSIENT or PERSISTENT durability (see Introduction to RTI Persistence Service in the Core Libraries User’s Manual), and Secure DataWriters to write data to both the network and the database. Hence, after discovering a Topic, Persistence Service creates a PRSTDataReader and a PRSTDataWriter.
The PRSTDataReader receives data from the Connext Databus and verifies (and potentially decrypts) it. The PRSTDataWriter reencodes 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 Crypto Header and Crypto Footer (see Serialized Data Protection).
The first time Persistence Service creates a PRSTDataWriter, it
randomly generates a Sender Key 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 dds.data_writer.history.key_material_key
(see Table 20.1). The
Cryptography Plugin 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 (Initialization Vector) used in the encryption. Persistence Service stores the random salt
along with the PRSTDataWriter’s encrypted Sender Key. If
Key Revisions are enabled (see
Limiting the Usage of Specific Key Material), then
Persistence Service also stores the key_revision_max_history_depth most
recent Key Revisions, which will be necessary to decode the data upon
restarting Persistence Service (see
Reencoding Protected Data when Regenerating Keys.
Upon restarting Persistence Service, we use the original
PRSTDataWriter’s Key Revision to decode, and we use the new
PRSTDataWriter’s latest Key Revision to encode). The Key Revisions
are encrypted in the same way as the Sender Key.
When Persistence Service restarts, it loads each PRSTDataWriter’s Sender Key and Key Revisions from the database. To do so, Persistence Service needs the same configuration. If a different configuration is provided (e.g., wrong value for dds.data_writer.history.key_material_key), Persistence Service creation will fail.
Note that when Persistence Service reads the data from the database, the PRSTDataWriter does NOT verify the MAC stored with the data before sending it out on the wire. It is up to the user DataReaders to verify the MAC. Consequently, if an attacker alters the database’s data, the PRSTDataWriter will resend the tampered data many times over the wire until the reliability protocol causes the data to be lost.
For more information about the Security Plugins’s interactions with Zero Copy
transfer over shared memory, see the following section in the
RTI Connext DDS Core Libraries User’s Manual:
To avoid the discovery-time overhead of mutual authentication and key exchange,
you may use the Lightweight Builtin Security Plugins described in
The Lightweight Builtin Security Plugins and provide a
pre-shared key seed with the
dds.sec.crypto.rtps_psk_secret_passphrase property. In
addition to the integrity and authentication of RTPS messages, Lightweight Builtin Security Plugins can
also protect their confidentiality (for more information, see the
dds.sec.crypto.rtps_psk_symmetric_cipher_algorithm property).
Pre-Shared Key Protection is available in both the Builtin Security Plugins and the Lightweight Builtin Security Plugins
libraries.
You can read the Pre-Shared Key Protection section to
learn more about Pre-Shared Key Protection, including how it works, how to configure it,
and the difference between using it in the Builtin Security Plugins library or in the
Lightweight Builtin Security Plugins library.
6.8.9. Interactions with Instance State Consistency
Instance State Consistency uses the builtin DataWriter and DataReader that are
shared by all user-created DataWriters and DataReaders within the same Publisher or Subscriber.
When security is enabled, these builtin entities will ensure that the
topic granular security offered by Connext is maintained.
If the user-created DataWriter or DataReader uses either Serialized Data Protection or Submessage
Protection, these entities’ builtin instance state endpoint will be secure.
It is possible that both the secure and non-secure variants of the builtin
instance state endpoints are created within a Publisher or Subscriber (if that Publisher or
Subscriber contains both secure and non-secure endpoints).
When security is used, the request for instance state data is sent using the builtin
secure service request DataWriter. Protection for this DataWriter is configured via the
service_request_protection_kind tag (see
service_request_protection_kind (domain_rule) for
more information on the protection configuration of the service request channel).
The actual response samples sent by the instance state DataWriter may contain
sensitive data (such as key hashes, timestamps, GUIDs). This data would normally
be protected by the user DataWriter’s protection info. To maintain the
topic-level security offered by Connext, each instance state response sample
is protected using Serialized Data Protection, with the protection info of the
DataWriter whose instance state data is being requested. Although the builtin instance
state DataWriter is shared by multiple user DataWriters, each response sample only contains
instance state data from a single user DataWriter.
The instance_state_consistency_protection_kind goverance rule
(see instance_state_consistency_protection_kind (domain_rule))
configures the submessage protection of the builtin secure instance
state DataWriter and DataReader.
Secure TypeLookup Service is described in the OMG DDS Security 1.2 specification. As described by that
specification, a “Secure Type”—a type only used by Topics configured with
enable_discovery_protection (see
enable_discovery_protection (topic_rule)) set to
true—can only be
propagated via the Secure TypeLookup Service channel. Specifically, this means:
If a request for a secure type is received on the non-secure TypeLookup Service
channel, the request will be ignored.
If a request for a non-secure type is received on the secure TypeLookup Service
channel, the request will be processed and a response will be sent on the
secure channel.
A TypeLookup request can contain a mix of both secure types and non-secure types.
If a request containing both secure and non-secure types is received
on the non-secure channel, only the non-secure types will be included in
the response and the response will be sent on the non-secure channel.
If a request containing both secure and non-secure types is received on the
secure channel, all of the types will be included in the response and the
response will be sent on the secure channel.
A TypeLookup Service response will only ever be sent in response to a request sample,
and it will be made on the same channel that the request was received on. A response will
never be sent on the non-secure channel for a request received on the secure channel
(and a response will never be sent on the secure channel for a request received on
the non-secure channel).
If a requester receives a response on a different channel than the request was
issued on, the response will be dropped.
When security is enabled on a DomainParticipant, all types registered by that DomainParticipant initially start as
Secure Types. A Secure Type transitions to being non-secure if a Topic is created using
that type and has its enable_discovery_protection set to false
(see enable_discovery_protection (topic_rule)).
Once a Type becomes non-secure, it will never be secure again,
even if the Topic that caused the transition to non-secure is deleted.
Table 6.7 Security Plugins Properties for Configuring Cryptography
Property Name (prefix with com.rti.serv.secure.) [3]
Property Value Description
cryptography.max_blocks_per_session
Optional
The number of message blocks that can be protected with the same
Session Key. Whenever the number of blocks exceeds this value, a new
Session Key is computed. The block size is always 128 bits (the AES
block size).
You can specify this value in decimal, octal, or hex. This value is an
unsigned 64-bit integer.
Unsigned integer: [1-MAX_UINT64]
Default: MAX_UINT64
cryptography.encryption_algorithm (deprecated)
Optional
Deprecated. Use dds.sec.crypto.symmetric_cipher_algorithm
instead.
cryptography.max_receiver_specific_macs
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 DomainParticipant is configured to protect both RTPS messages and submessages with Origin Authentication Protection, there could be 32 Receiver-Specific MACs in the result of encode_datawriter_submessage, and there could be another 32 Receiver-Specific MACs 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 DomainParticipant will always be assigned the same Receiver-Specific MAC.
Integer: [2,3275], or 0 to completely disable Receiver-Specific MACs,
or AUTO to allow an unlimited number of Receiver-Specific MACs if
rtps_protection_kind ends in WITH_ORIGIN_AUTHENTICATION.
Default: AUTO (non-rtps*_protection_kind values ending in WITH_ORIGIN_AUTHENTICATION are not allowed)
Indicator of whether the metadata and data encoding operations share the same Key Material or use different keys. By default, DataWriters with both metadata_protection_kind and data_protection_kind set to a value other than NONE use the same Key Material for protecting both RTPS submessages and serialized data. To change this behavior, set this property to FALSE.
Boolean.
Default: TRUE (they share Key Material)
cryptography.enable_additional_authenticated_data
Optional
Available in:Builtin Security Plugins
Enable Additional Authenticated Data (AAD) for encode operations that support
it. Currently only applicable to RTPS protection
(rtps_protection_kind set to a value other than NONE),
where it is used to protect the RTPS Header and RTPS Header Extension
Submessage if present.
It’s of an enum type:
TRUE enables AAD for all protected messages,
FALSE disables it for all protected messages,
AUTO enables AAD for messages protected with PSK and for messages
containing an RTPS Header Extension submessage. Disables AAD for messages
protected with AXK.
Must be set to TRUE or AUTO if using RTPS protection in
combination with RTPS 2.5 Header Extension.
This property is not available in Lightweight Builtin Security Plugins, which always use AAD.
Enum: AUTO (default), TRUE, FALSE
Default: AUTO.
6.9.1. Configuration Properties Affecting Any Cryptography Plugin
Table 6.8
lists a set of Security Plugins Properties that are
not exclusive to the shipped builtin plugins, but that will affect any
Cryptography Plugin.
Table 6.8 Properties for Configuring Cryptography Affecting Any Cryptography Plugin
Property Name
Property Value Description
dds.sec.crypto.symmetric_cipher_algorithm
Optional
Encryption algorithm that the Sender uses for protecting RTPS messages with
AXK keys. The value of this property determines the Transformation Kind
sent through the Secure Key Exchange Channel (and in the Crypto Header) to inform the
Receiver about the transformation used to protect the data.
The options are AES128+GCM and AES256+GCM. The number indicates
the number of bits in the key in either the GMAC or GCM variant of the algorithm.
This property sets the algorithm and key length only. To set the variant
of the algorithm, set the Governance Document’s protection_kind
either to ENCRYPT, for GCM, or to SIGN, to use the GMAC
variant of this algorithm.
This property is set for DomainParticipants, and affects both user and builtin Endpoints.
The exceptions are the Secure Key Exchange DataWriter and DataReader, which always
use AES256+GCM for the encryption transformation.
Enum: AUTO (equivalent to AES256+GCM),
AES128+GCM, AES256+GCM
Default: AUTO
Warning
This DDS Security property behaves exactly like the previous
Security Pluginscryptography.encryption_algorithm property.
cryptography.encryption_algorithm is deprecated. Use
dds.sec.crypto.symmetric_cipher_algorithm instead.
Algorithm used to protect RTPS messages protected with
Pre-Shared Key Protection. The available options are
AES256+GCM (default) and AES128+GCM. The number indicates
the number of bits in the key in either the GMAC or GCM variant of the algorithm.
The Lightweight Builtin Security Plugins offer an additional cryptographic algorithm, SM4+GCM,
which uses 128-bit long keys. This property sets the algorithm and key length
only; see the note below for more information about setting the algorithm’s variant.
This property must be set if Pre-Shared Key Protection is enabled (see
rtps_psk_protection_kind (domain_rule)).
It must be configured consistently throughout your system. That is, all
the DomainParticipants need to have the same value in order to communicate.
The value of this property (combined with rtps_psk_protection_kind)
determines the Transformation Kind sent through the Secure Key Exchange Channel and
in the Crypto Header.
Enum: AUTO (equivalent to AES256+GCM),
AES128+GCM, AES256+GCM, SM4+GCM (Lightweight Builtin Security Plugins only).
Default: AUTO
Note
The Lightweight Builtin Security Plugins (see
Lightweight Security Pre-Shared Key RTPS Protection)
protect all RTPS messages with Pre-Shared Key Protection. The Builtin Security Plugins protect
all RTPS Messages with a PSK only if the rtps_protection_kind Governance Rule
is set to NONE. If the rtps_protection_kind value is
different than NONE, the Builtin Security Plugins will use Pre-Shared Key Protection to
protect only bootstrapping RTPS messages. Once the authentication process
is complete, the Builtin Security Plugins protect RTPS messages using AXK keys and
the algorithm specified by the dds.sec.crypto.symmetric_cipher_algorithm
property.
You can configure whether to protect only the integrity of messages
(GMAC variant of this algorithm) or both the confidentiality and
integrity (GCM variant). To do so in the Builtin Security Plugins, set the
rtps_psk_protection_kind Governance Rule (see
rtps_psk_protection_kind (domain_rule))
in the Governance Document to either ENCRYPT (GCM) or
SIGN (GMAC). In the Lightweight Builtin Security Plugins, configuration can be done
through the dds.sec.access.rtps_psk_protection_kind property.
dds.sec.crypto.rtps_psk_secret_passphrase
Optional
This property must be set if Pre-Shared Key Protection is enabled (see
rtps_psk_protection_kind (domain_rule)).
It must be configured consistently throughout your system. That is, all
the DomainParticipants need to have the same value in order to communicate. The only
exception is when the DomainParticipants have additional decode-only passphrases
configured with the
dds.sec.crypto.rtps_psk_secret_passphrase_extra property.
The Security Plugins use this secret passphrase (in combination with other
publicly available data) to derive the per-participant key used for
encoding RTPS messages.
This property is mutable through the DomainParticipantset_qos API.
The DomainParticipant will use the updated passphrase to derive the new local and remote
pre-shared keys. From that point on, the DomainParticipant will use the new keys to
encrypt and decrypt RTPS messages protected with Pre-Shared Key Protection.
You should expect warning messages (about receiving messages encoded with
a different pre-shared key identifier) as you change the property value
throughout your system. Once all your DomainParticipants have the same passphrase, all
pre-shared key protected traffic will be encoded and decoded with
consistent keys. At that point, warning messages will stop. You can
configure the dds.sec.crypto.rtps_psk_secret_passphrase_extra
property to update the passphrase without losing any RTPS messages.
Updating the value of this property implies not only a change in the
secret key, but also a change in the key identifier. Each secret key
should be associated with a unique key identifier.
Updating the secret key without changing the key identifier is not
allowed and will result in set_qos returning
DDS_RETCODE_NOT_ALLOWED_BY_SECURITY.
The pre-shared secret identifier shouldn’t be re-used either. You may set
a new secret key with an old key identifier, but doing so is not advised.
In that case, the Security Plugins may end up using the old pre-shared key
to try (without success) to decode an RTPS message that was encoded using
the new key.
String. There are two acceptable formats for this property:
Passphrase value explicitly in the property: It must follow the format
data:,<passphrase_id>:<passphrase>. <passphrase_id> is an
unique four-byte integer number that identifies the key. It must be in
the [0,2^32-1] range, excluding the values that have
0xFF as the least significant byte (e.g. 255, 1023, 2047, etc).
Interoperability with releases older than 7.4.0 requires the passphrase
id to be a value between 0 and 254.
<passphrase> is the secret passphrase string that the
Security Plugins will use to derive the per-participant pre-shared key.
Path and name of a supplemental file that contains the passphrase value.
May start with the file: prefix, followed by a path to a file.
If no prefix is provided, the Security Plugins assume the value is a
file path. The file content must follow the format
<passphrase_id>:<passphrase>, exactly the same as if it were
provided explicitly. If the passphrase is provided in a file, the
Security Plugins can track this file for changes and update used keys if
a valid change is detected. The file will be tracked automatically if
the value of files_poll_interval is different than 0.
If you delete this file, the Security Plugins will keep using the last
valid passphrase. Similarly, if you remove the contents of the tracked
file, the Security Plugins will fail to read the new passphrase and
keep using the last one.
It is recommended that you take the appropriate measures to protect
any file containing this key, or alternatively to securely retrieve
and set up this property programmatically.
<passphrase_id> must be provided to support proper handling of
different passphrase revisions, and it must be consistent across all the
DomainParticipants within a domain. This value must be different with every passphrase
change, otherwise the update will be rejected. It is good practice to use
incremental, subsequent values for every new key provided.
Rolling back to a lower number (e.g., 0) after the indexes have been
exhausted is acceptable.
<passphrase> must be a string containing up to 512 ASCII printable
characters (character codes 32 to 126, both included). The first and last
characters of the <passphrase> shall not be the space character
(character code 32).
Default: not set
Attention
It is strongly encouraged (and the user’s responsibility) to provide a
key passphrase with good entropy and length. Ideally, the pre-shared key
passphrase should be a true random 256-bit seed. There are a few methods
to obtain such a string. For example, one could use a specialized
dictionary (e.g., BIP39) to draw words from, or a Base64-encoded sequence
of random binary bits. Note that actual entropy may be less than what
the length of the string suggests. For example, the ASCII character
space does not use the whole 8-bit space: instead, only 5-6 bits are
used. To obtain the desirable entropy and strength one would need at
least 256/5.5 = 47 truly random characters. A dictionary-based approach
offers less entropy, and the seed created this way would need to be
longer.
dds.sec.crypto.rtps_psk_secret_passphrase_extra
Optional
This property allows configuring an extra pre-shared key passphrase. It
can be used in conjunction with dds.sec.crypto.rtps_psk_secret_passphrase
if there is a requirement for a seamless transition to a new passphrase,
while allowing a grace period for the entire system to update and avoid
message loss because of slow-to-update participants.
PSK Protection uses this pre-shared key passphrase to derive the key used
for decoding RTPS messages only. Encoding RTPS messages does not use this
passphrase.
This property is mutable through the DomainParticipantset_qos API, or through
file tracking (see files_poll_interval property). You should
only set its value during an update of the primary passphrase. See section
Updating the PSK Passphrase Without Message Loss
for more information. The Security Plugins will stop using the extra
passphrases if you do one of the following: remove the
dds.sec.crypto.rtps_psk_secret_passphrase_extra property,
assign the empty string ("") to the property value, delete the tracked
file, or delete the contents of the tracked file (empty the file).
String. This property accepts a list of passphrases separated by
either a new line (\n character), a carriage return (\r
character), or a combination of both. The passphrases can be provided
directly in the property value (data:, prefix) or in a supplemental
file (no prefix or \file: prefix). Each passphrase follows the same
format as dds.sec.crypto.rtps_psk_secret_passphrase
(<passphrase_id>:<passphrase>).
This property can have a maximum of two passphrases, but one of them
must be equal to the primary passphrase (the one in
dds.sec.crypto.rtps_psk_secret_passphrase). That is, only one
unique new passphrase is allowed. The property value is not valid if
there are more than two passphrases, or if there are two passphrases and
one of them doesn’t match the primary passphrase. For example,
data:,0:my_extra_passphrase, or
data:,0:my_extra_passphrase\n1:my_primary_passphrase would both be
valid options. However,
data:,0:my_extra_passphrase\n1:another_extra_passphrase is not a valid
value because this property does not support two new passphrases, and the
value must include the current primary passphrase.
Controls the number of key revisions that are used to encode samples in
the DataWriter queues. As the value increases, the reencoding of writer queue
historical samples gets more delayed or even avoided, but the memory
footprint of the DomainParticipant increases. The memory used for key revisions is
preallocated, and it is roughly equal to 36 bytes (or 164 bytes if the
DomainParticipant has at least one DataWriter using ODBC writer history)
multiplied by the key_revision_max_history_depth. If there is at least
one reliable DataWriter that is protecting its payload, then the DomainParticipant will send
8 key revisions instead of just 1 to each late joiner DomainParticipant. Each key
revision adds about 128 bytes of network traffic, so that’s
128 * (8 - 1) = 896 more bytes per late joiner DomainParticipant.
A DomainParticipant that sets this property to a value other than 0 will not
communicate with a DomainParticipant that sets this property to 0 or with a
DomainParticipant of a release older than the 7.0.0 Security Plugins.
Integer: [8,1000000], or 0 to completely
disable Key Regeneration.
Default: 14 if enable_key_revision is true
or unspecified, 0 if enable_key_revision is false.
Controls the maximum time in seconds between generating and using a new
key revision. After this time, remote DomainParticipants that have not yet
acknowledged the new key revision will be completely removed.
Integer: [1,MAX_INT32], or -1 to wait
indefinitely for key revision acknowledgements.
Controls the number of DomainParticipants that you were formerly communicating with to
keep track of before automatically creating a new Key Revision. As the
value increases, the overhead of creating a new Key Revision occurs less
frequently, but the memory footprint of the DomainParticipant increases. The memory
used for keeping track of these removed DomainParticipants is preallocated, and it is
roughly equal to 72 bytes multiplied by the
max_removed_participants_per_key_revision, plus an additional 512 bytes.
This property is deprecated and has no effect. A warning message will be
logged if this property is set to TRUE.
Boolean.
Default: FALSE
dds.data_writer.cryptography.taint_data
Optional
Simulate tainted data.
Connext DDS will modify one byte of encoded data after the GMAC is
computed. This property applies to the DataWriterQos, and can be used for
testing validation of the GMAC hash. Note that Connext DDS will only taint
live data (repair data is not tainted). Also, tainting
requires running on a little-endian machine.
If TRUE, then the encoded data is modified after computing the
final layer of GMAC or GCM.
After failing to validate the GMAC hash, the Security Plugins will log the following
message with DDS_LOGGING_ERROR_LEVEL level:
DecryptFinal failed. Possible GCM authentication failure