.. include:: ../vars.rst

.. _chapter-design-considerations:

*********************
Design Considerations
*********************

Enabling the |RTI_SP_PRODUCT| will have an impact on your system. When you enable the |RTI_SP_PRODUCT|, there are some processes that change (like Discovery) or that are new (like encrypting messages). Some of these processes involve cryptographic operations that are computationally expensive (increased CPU and memory usage); protecting data requires sending additional information on the wire (increased network traffic). This can affect both the performance and scalability of your system.

Not every system is affected the same way. How much your system is affected will depend on the system architecture and requirements, as well as on its configuration. This chapter discusses some of the considerations that you should take into account when designing your system.

.. contents::
  :depth: 3

Time Requirements for |RTI_SP_PRODUCT|
======================================

The |RTI_SP_PRODUCT| includes time-sensitive operations, 
such as validating security artifacts, performing the handshake, and 
encrypting/decrypting messages. Consider the following design strategies 
to ensure your system can meet the time constraints for these functions 
while maintaining the desired capabilities and flexibility.

Short-Lived Security Artifacts
------------------------------

The |RTI_SP_PRODUCT| enables you to implement short-lived security artifacts, such as
|IdentityCerts| and |PermissionsDocs|. Short-lived security artifacts have a short 
validity period (e.g., minutes or hours). These artifacts can be
used to implement a more dynamic and agile security model, where you can frequently
renew the permissions and identities in your system. |IdentityCerts| also can be 
frequently revalidated with |OCSP|. 

Using short-lived security artifacts may impact system performance and scalability 
because more frequent artifact renewal processes may be required. When determining 
your security artifact validity
periods, consider the trade-off between the security benefits of short-lived artifacts
and the capabilities and limitations of your system. If your system may experience connectivity
breaks or delays, or has limited network and computational resources, consider using longer-lived
security artifacts and start renewal processes earlier to avoid communication failures due
to artifact expiration. 

Minute-level validity periods should be reserved for systems with
very high security requirements and that can afford the additional overhead. Hour-level or
day-level validity periods are a good option for most systems, providing a good balance between
security and performance. We do not recommend using second-level validity periods.

Time Synchronization Requirements
---------------------------------

The |RTI_SP_PRODUCT| exclusively uses the host system clock for internal 
operations. This behavior overrides any |DP| clock settings, 
specifically ignoring the :property:`dds.clock.external_clock` and
the :property:`dds.clock.internal_clock` properties.
When validating externally produced security artifacts, like |IdentityCert| and |PermissionsDocs|, 
the |SP_BUILTIN| validates the absolute timestamps provided in the artifacts against real-world time. A
properly synchronized system clock should show the real-world time. 

In contrast, the monotonic clock is a relative, monotonically increasing timestamp representing the number
of seconds elapsed since an arbitrary point in time (e.g., machine startup). Because this
clock is independent of real-world time, it is infeasible to translate or
compare its values with real-world timestamps. Therefore, if |SP_BUILTIN| was working with a monotonic clock,
it would be unable to correctly determine whether or not a given security artifact is valid.
The |SP_BUILTIN| would not be able to banish remote |DPs| with expired artifacts, or
determine if they have to renew their own. This is the reason the |RTI_SP_PRODUCT| always
use the system clock.

.. note::

  The |LIGHT_SP_BUILTIN| does not work with any security artifact that can expire.
  As a result, it is not sensitive to time discrepancies between |DPs| and other
  system components.

The |SP_BUILTIN|' reliance on system time requires a host and system 
(including Identity CA and Permissions CA) configuration where |DP| and system time remain 
synchronized. Some minor variations (in the order of seconds) are acceptable and
should not adversely impact system operations. 

If the time is not synchronized between different
|DPs|, you may notice some |DPs| banishing others sooner than the rest of the system. This may
become a problem with short-lived security artifacts or with |OCSP| where the acceptable margin
for error is smaller. The time discrepancy may result in unintended communication failures or
complete inability to communicate. For considerations about time synchronization when using
|OCSP| see :ref:`p3_advanced/design_considerations:Time Synchronization Requirements with OCSP` section.

Global time adjustments, such as leap seconds, are transparent to |RTI_SP_PRODUCT|.

Security Considerations for Expiration and Banishment
=====================================================

By default, |RTI_SP_PRODUCT| automatically banishes |DPs| upon security artifacts expiration.
As a result, the expired |DP| is removed from the system and is unable to communicate with
the rest of the system. The expectation is that the banished |DP| will eventually renew the
expired artifacts, reauthenticate, and rejoin the system with the same identity and permissions.

:xmltag:`allow_unauthenticated_participants` domain rule cannot be used to allow the expired
|DP| back into the system as unauthenticated. To rejoin as unauthenticated, the expired |DP|
needs to be recreated without security, or with the |LIGHT_SP_BUILTIN|.

Factors Affecting Performance and Scalability in General
========================================================

There are some factors that have an impact on the performance and scalability of your system at all times.

Security does have a cost. There are additional processes that impact CPU and memory usage, such as validating certificates and permissions, exchanging keys, encrypting samples, etc. Take into account that the memory representation of a |SecDP| and a |SecEP| is larger than for their unsecure counterparts.


Hardware
--------

Some processors have support for cryptographic hardware acceleration. Or your hardware may just have a fast enough processor for the additional overhead to not be a concern.

.. note::

  The OpenSSL libraries that we provide support hardware acceleration.


Algorithms Used
---------------

By default, the Cryptography Plugin uses AES-256 for symmetric encryption and
decryption. This means that a 256-bit key will be used as an input for the AES
algorithm. You can choose the AES-128 encryption option instead by configuring
the :property:`dds.sec.crypto.symmetric_cipher_algorithm` property (see
:numref:`Properties for Configuring Cryptography Affecting Any Cryptography Plugin`).
Note that AES always performs the encryption and decryption operations in blocks
of 128 bits.

Using different encryption algorithms or key lengths will impact performance
since CPU usage and the amount of data sent for key exchange may increase.


Maximum Transmission Unit (MTU)
-------------------------------

You can control the maximum size of the RTPS messages sent on the network by adjusting the :property:`message_size_max` property in your transport configuration (see :link_connext_dds_api_cpp:`NDDS_Transport_Property_t::message_size_max in the RTI Connext DDS Traditional C++ API <structNDDS__Transport__Property__t.html#a4ab89765aee4395142e2dabc7849a46a>`). By setting this property to a value smaller than the maximum payload that fits in the MTU (usually 1472 bytes for UDP over Ethernet), you can avoid IP fragmentation. Hence, |CONNEXT| will fragment RTPS Submessages before sending them to the transport (DDS fragmentation).

If you want to use Origin Authentication Protection, RTPS messages and/or submessages will include a set of |RecSpecificMACs|.
The maximum number of |RecSpecificMACs| that will be included in a message is determined by the :property:`cryptography.max_receiver_specific_macs` property
(see :numref:`|RTI_SP_PRODUCT_HEADING| Properties for Configuring Cryptography`).
By default, this property is set to :value:`AUTO`, which means that any
|RecSpecificMACs| that cannot fit in a message will be included in subsequent
resends of the same message (see
:ref:`p2_core/cryptography:Origin Authentication Protection Implications`). If
you wish to avoid these resends and are willing to sacrifice some security for
better performance (see
:ref:`p2_core/cryptography:Reducing Performance Impact of Origin Authentication`),
then you may want to set :property:`cryptography.max_receiver_specific_macs` to
a positive integer value. In that case, the absolute minimum
:property:`message_size_max` you can use will depend on the
:property:`cryptography.max_receiver_specific_macs` value.

Note that each Receiver-specific MAC will be 20 bytes in size. Therefore, to avoid IP fragmentation
or resends, you have to limit the :property:`cryptography.max_receiver_specific_macs` property to a maximum of

.. math::

  \frac{\mathtt{message\_size\_max} - \mathtt{usable\_rtps\_size}}{20}


where :math:`\mathtt{usable\_rtps\_size}` is the size of all packet bytes besides the MACs (including payload, RTPS headers and other security overhead). Generally, :math:`\mathtt{usable\_rtps\_size}` should be at least :math:`768 \mathrm{B}` to :math:`1 \mathrm{kB}`.


Using OpenSSL Providers
-----------------------
The |RTI_SP_PRODUCT| have support for OpenSSL providers (see
:ref:`p3_advanced/openssl_providers:Support for OpenSSL Providers`). These
providers are called by OpenSSL and provide alternative functions to the
OpenSSL builtin security operations. Using different cryptographic functions
may affect the performance of the |RTI_SP_PRODUCT|. For instance, the functions may perform
optimized cryptographic operations, or use algorithms that have a reduced
computational cost. On the other hand, your OpenSSL provider may implement more
complex algorithms that require more CPU usage.

OpenSSL providers may interact with hardware acceleration for common
cryptographic operations, depending on the provider support.


|RTI_SP_PRODUCT_HEADING| File Tracking
--------------------------------------
The |RTI_SP_PRODUCT| offer a file tracking capability that periodically checks some of the |RTI_SP_PRODUCT|'
mutable files for changes and automatically updates the |RTI_SP_PRODUCT|' internal state. This
functionality features a dedicated thread and internal infrastructure that is
allocated at |RTI_SP_PRODUCT| creation and works until |RTI_SP_PRODUCT| finalization. File tracker and
its creation can be controlled via the :property:`files_poll_interval` property.
File tracker is created and enabled if the property value is greater than 0,
regardless of whether there are any files to be tracked.
If the property is 0, the file tracker is not going to be created, and |RTI_SP_PRODUCT| will
consume minimally fewer resources. By default, :property:`files_poll_interval`
equals 5, and the file tracker is created. If the resource consumption is a
concern and file tracking is not required, consider setting
:property:`files_poll_interval` to 0. Note that it is possible to programmatically
trigger reloading of the affected files through the |DP| ``set_qos`` API,
when file tracking is disabled.

.. attention::

  Some of the RTI Infrastructure Services depend on the |RTI_SP_PRODUCT| file tracking
  and disabling it may limit system functionality.


|RTI_SP_PRODUCT_HEADING|' Impact on Scalability at Startup
==========================================================
When a DDS system starts up, |DPs| discover each other through the *Simple Discovery Protocol* (see :link_connext_dds_pro_um:`Discovery in the RTI Core Libraries User's Manual <#users_manual/Discovery.htm>`). The scale of your system has a fundamental role in the time that it will take until it reaches a steady state where every |DP| knows all its peer |DPs| and user data flows through every part of the system where it is needed.


Impact of the |RTI_SP_PRODUCT_HEADING| on the Discovery Process
---------------------------------------------------------------
When you enable the |RTI_SP_PRODUCT|, your DDS applications will require some extra steps to create the |DPs| and perform the DDS Discovery process, as depicted in :numref:`figure-changes-discovery-process-SP-enabled`. These steps make sure that the security rules defined in your |GovernanceDoc| apply, that |DPs| are mutually authenticated, and that they only have access to the data they are allowed to access (as defined in the |PermissionsDocs|), to cite a few examples.

Let's assume that we are starting a DDS application that contains a local |DP| (|P1|) that will communicate with an existing remote |DP| (|P2|). Let's analyze the differences in Discovery (and application startup, in general) when we enable security.

.. figure:: ../static/discovery-differences.png
  :scale: 50%
  :name: figure-changes-discovery-process-SP-enabled
  :align: center

  Changes in the Discovery Process When the |RTI_SP_PRODUCT| Are Enabled


Differences in DomainParticipant Creation
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The first thing your application needs to communicate using DDS is a |DP|. The local |DP| (|P1|) is created from a certain configuration (default QoS or a selected profile).

When you enable security, you need to specify additional settings to make your
|DP| load the |RTI_SP_PRODUCT|
(see :ref:`p2_core/building_apps:Building and Running |RTI_SP_PRODUCT_HEADING|-Based Applications`).
In addition, your |DP| will load and validate the security artifacts that you specify in the properties.
These artifacts include the |GovernanceDoc|, |PermissionsDoc|, Permissions CA,
Identity CA, |IdentityCert| and |PrivateKey|
(see :ref:`p1_welcome/using_dds_secure:Using |RTI_SP_PRODUCT_HEADING|`). If any of
these artifacts are missing, or if they cannot be verified/don't match (e.g.,
the |IdentityCert| is not signed by the provided Identity CA or the |OCSPResp| does
not respond with a valid |OCSPToken|), the |DP| creation fails at this first
stage.

Your |DP| also needs permissions. We check whether it has a valid :xmltag:`grant` (matching the subject name in its |IdentityCert|) that is valid for the current date and time. If it doesn't, the creation of the |DP| fails immediately. Next, local participant-level permissions are checked to verify whether |P1| has permission to join the domain. If |P1| is not allowed to join the domain, the |DP| creation fails. For further details, refer to :ref:`p2_core/elements_dds_secure_system:How the Permissions are Interpreted`.


Differences in Endpoints Creation
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The local |DP| (|P1|) will have |DWs| and |DRs| for both builtin topics (such as the participant discovery |TOPIC|) and user-defined topics (user |EP| for data exchange). In addition, we need to allocate resources for discovering remote |DPs| and |EP|.

When security is enabled, |PermissionsDocs| establish what |DPs| and |EP| are allowed to do. When you enable Endpoint-level permissions checking for a certain |TOPIC|, |P1| needs to verify whether it is allowed to publish/subscribe to that |TOPIC| before creating a |DW|/|DR| for it (see :ref:`p2_core/access_control:Topic-level rules`). If it is not allowed to do so, the endpoint creation fails.


Differences in Remote DomainParticipants Discovery
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
In the Participant Discovery phase, your local |DP| learns about other |DPs| in
the domain, and vice-versa. As part of this process, the |DPs| exchange some
details, including GUIDs, transport locators and DomainParticipantQos. These
details only involve |DP| information (they do not involve |EP|). For further
information, see
:link_connext_dds_pro_um:`Simple Participant Discovery in the Core Libraries User's Manual <#users_manual/Simple_Participant_Discovery.htm>`.

Unless |PSKProtection| (:ref:`p3_advanced/pre-shared_key:|PSKProtection|`)
is enabled, the |DP| discovery data is exchanged unsecurely. In
other words, the bootstrapping part of discovery happens without protection --
this only contains information about the |DP| that does not require protection
and does not involve |EPs|. Participant declaration messages will include
additional properties, as required by the |SEC_SPEC|:

* ``PID_IDENTITY_TOKEN`` contains summary information on the identity of a |DP|.
  The |RTI_SP_PRODUCT| use the presence or absence of this token to determine whether or not
  the remote |DP| has security enabled.
* ``PID_PERMISSIONS_TOKEN`` contains summary information on the permissions for
  a |DP|. The |RTI_SP_PRODUCT| currently do not use this token.
* ``PID_PARTICIPANT_SECURITY_INFO`` validates Governance compatibility. If local
  and remote |GovernanceDocs| are not compatible, |P1| will reject matching
  |P2|. For further information, see :ref:`p2_core/elements_dds_secure_system:Elements of a |RTI_SP_PRODUCT_HEADING| system`.
* ``PID_DIGITAL_SIGNATURES_ALGO`` contains summary information on the digital
  signature algorithms used and supported by the |DP|. If local and remote
  algorithms are not compatible, |P1| will reject matching |P2|. You can read
  about what makes the remote and local algorithms compatible in
  :ref:`p2_core/cryptography:Discovery of a Remote Secure Entity`.
* ``PID_KEY_ESTABLISHMENT_ALGO``: contains summary information on the key
  establishment algorithms used and supported by the |DP|.  If local and remote
  algorithms are not compatible, |P1| will reject matching |P2|.
* ``PID_PARTICIPANT_SYMMETRIC_CIPHER_ALGO``: contains summary information on the
  symmetric cipher algorithms used and supported by the |DP|. If local and
  remote algorithms are not compatible, |P1| will reject matching |P2|.

When |P1| and |P2| know about each other, they proceed to mutual authentication.
As part of the Authentication process (1 in
:numref:`figure-changes-discovery-process-SP-enabled`), |P1| and |P2| will
exchange some artifacts by sending them on the wire as part of the handshake.
These artifacts include the |IdentityCerts| and Permission Files. In the
Authentication process, |P1| verifies |P2|'s |IdentityCert| against the
Identity CA. If this verification fails, |P1| will reject communicating with
|P2| (see :ref:`p2_core/authentication:Identity Certificate Validation`). This
mutual authentication process happens in both directions.

Next, |P1| checks that |P2| has the necessary permissions and that they are
valid (2 in :numref:`figure-changes-discovery-process-SP-enabled`). If |P2|
doesn't have a grant matching the subject name in its |IdentityCert|, |P1| will
reject communicating with |P2|. If |P2|'s participant-level permissions are
enabled (:xmltag:`enable_join_access_control` = :xmlval:`TRUE`), but |P2| does
not have permission to join the domain, |P1| will also reject communicating with
|P2| (see :ref:`p2_core/access_control:enable_join_access_control (within a domain_rule)`).
Permissions checking also happens in both directions.

As a result of the handshake, the two involved |DPs| will derive a Shared Key
and establish a Secure Key Exchange Channel. The Cryptography plugin will use
that channel to securely exchange the symmetric keys that the |EP| need to
perform secure communication. After the handshake concludes with successful
authentication and Shared Key derivation, symmetric cryptography is used to
exchange other keys (see :ref:`p2_core/cryptography:Secure Key Exchange`).


Differences in Remote Endpoints Discovery
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
During the Endpoint Discovery phase, your local |DP| learns about the |EP| of
the remote |DPs|, and vice-versa. To do this, your |DP| sends
publication/subscription declarations to inform discovered |DPs| about the local
|DRs| and |DWs| and their properties (GUID, QoS, etc.). For details, see
:link_connext_dds_pro_um:`Simple Participant Discovery in the Core Libraries User's Manual <#users_manual/Simple_Participant_Discovery.htm>`.

These declarations are exchanged until each |DP| has a complete database of
information about the |DPs| in its peers list and their entities.

When a remote |DW|/|DR| is discovered, |CONNEXT| determines if the local
application has a matching |DR|/|DW|. A 'match' between the local and remote
entities occurs only if the |DR| and |DW| have the same |TOPIC|, same data type,
compatible QosPolicies, and compatible security algorithms.

When security is enabled, |P1| and |P2| use the Secure Key Exchange Channel to
exchange the Key Material for the Builtin Secure Endpoints  (3 in
:numref:`figure-changes-discovery-process-SP-enabled`), including the
Publication Secure |DW| and |DR| used for secure endpoint discovery (see
:ref:`p2_core/cryptography:Secure Key Exchange`). Note that secure endpoint
discovery only applies to topics that enable it (see
:ref:`p2_core/cryptography:enable_discovery_protection (topic_rule)`).

At this point, |P1| performs endpoint discovery. For topics that enable
|DiscoveryProtection|, endpoint declarations are sent over the |SecDiscoveryTopics|.
Otherwise, the unsecure version of the Builtin Discovery Topics are used. In all
cases, the |RTI_SP_PRODUCT| check Governance compatibility by means of the
``PID_ENDPOINT_SECURITY_INFO`` and ``PID_ENDPOINT_SYMMETRIC_CIPHER_ALGO``
parameters to check the endpoint security attributes and help perform matching
decisions (see :ref:`p2_core/elements_dds_secure_system:Governance Compatibility Validation`).

Then we will check the endpoint permissions, this time for the writers and the
readers.

Once your |DPs| go through all these steps, they will exchange keys for each of
their |SecEntities| (see :ref:`p3_advanced/design_considerations:Impact of Key Exchange on Scalability at Startup`).
After this, your |DPs| will enter the steady state where they will exchange user
samples (see :ref:`p3_advanced/design_considerations:|RTI_SP_PRODUCT_HEADING| Impact on Scalability and Performance During Steady State`).


Participant Discovery Information Validation and Updates
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Initial Participant Discovery is a process that happens unprotected, if
|PSKProtection| (:ref:`p3_advanced/pre-shared_key:|PSKProtection|`)is disabled.
However, Participant Discovery information is validated as part of the
authentication process. This ensures that the right information is received
during discovery, and that Participant Declaration Messages have not been
injected by a malicious entity. In other words, Participant Discovery is mainly
for bootstrapping, but then as part of authentication, we make sure that
discovery information that we have received is valid.

After authentication (and bootstrapping), any further updates that need to be
propagated through participant discovery are sent over the secure version of
the participant discovery |TOPIC|.


Impact of the Secure Versions of Builtin Endpoints
--------------------------------------------------
Secure versions of the Builtin Endpoints are always created when you enable the |RTI_SP_PRODUCT|, regardless of the protection kind specified in the |GovernanceDoc|. This generates additional traffic at startup in the form of :submsg:`HEARTBEATS` and :submsg:`ACKS` when a remote |DP| is discovered.


Impact of Key Exchange on Scalability at Startup
------------------------------------------------
After Authentication (and key derivation) are complete, symmetric cryptography is used to exchange other keys. More concretely, two mutually authenticated |DPs| will use their exclusive secure key exchange channel (DCPSParticipantVolatileMessageSecure) to set the symmetric keys for both builtin and regular |EP|.

When you enable security for a |TOPIC|, every |DW|/|DR| for that |TOPIC| will have its own |SenderKey| that needs to be sent to every matching |DR|/|DW|. These keys need to be generated and then exchanged between every pair of |DPs| publishing or subscribing to the secured |TOPIC|, which will have an impact on the network traffic and CPU usage. Note that this applies to both builtin and user-defined topics. For further details, refer to :ref:`p2_core/cryptography:Lifecycle of Secure Entities`.

The following subsections describe the |SecEntities| whose Key Material must be exchanged by your |DPs|.

Participant Key Material
^^^^^^^^^^^^^^^^^^^^^^^^
If you enable |RTPSProtection| by setting :xmltag:`rtps_protection_kind` to a value other than :xmlval:`NONE` in your |GovernanceDoc|, your |DPs| will behave as |SecEntities| and they will have their own Key Material. |DPs| secured this way will need to exchange this Key Material in order to perform any secure communication.

Builtin Secure Endpoints
^^^^^^^^^^^^^^^^^^^^^^^^
You can choose to use the secure version of the builtin |EP| to protect discovery and liveliness information for each of your topics. For example, you can use the |SecEPs| for discovery by setting :xmltag:`enable_discovery_protection` to :xmlval:`TRUE` in one of your topics. In this case, you will want to set the :xmltag:`discovery_protection_kind` to a value other than :xmlval:`NONE`; otherwise, you will not add any security. Note that enabling discovery protection for a |TOPIC| when the discovery protection kind is :xmlval:`NONE` is still a valid configuration that you can use for debuggability purposes.

If :xmltag:`discovery_protection_kind` is other than :xmlval:`NONE`, your |DPs| will need to generate and exchange the Key Material for the secure version of the Builtin Discovery Endpoints, causing additional network usage. More concretely, the Cryptography Plugin will generate and exchange keys for the following |EP|:

* DCPSParticipantSecure |DW|
* DCPSParticipantSecure |DR|
* DCPSPublicationSecure |DW|
* DCPSPublicationSecure |DR|
* DCPSSubscriptionSecure |DW|
* DCPSSubscriptionSecure |DR|

In addition, your |DPs| will need to apply the corresponding cryptographic transformation to discovery samples using |SubmsgProtection|. This comes with an additional computational cost and increased network usage (see :ref:`p3_advanced/design_considerations:Submessage Protection`).

The same applies to |LivelinessProtection|. When you set :xmltag:`liveliness_protection_kind` to a value other than :xmlval:`NONE`, your |DPs| will exchange keys for the following |EPs|:

* DCPSParticipantMessageSecure |DW|
* DCPSParticipantMessageSecure |DR|

Note that :xmltag:`discovery_protection_kind` also controls the level of protection that Builtin Secure Service Request Endpoints will have. Therefore, if :xmltag:`discovery_protection_kind` is a value other than :xmlval:`NONE`, keys for the following |EP| may need to be exchanged:

* Service Request Secure |DW|
* Service Request Secure |DR|

.. note::

  The creation of the Builtin Secure Discovery Endpoints is fully controlled by :xmltag:`discovery_protection_kind` and does not depend on the value of :xmltag:`enable_discovery_protection` on particular topics. Similarly, the Builtin Secure Liveliness Endpoints' creation only depends on :xmltag:`liveliness_protection_kind`, not on the value of :xmltag:`enable_liveliness_protection` on particular topics.


Finally, the Builtin Secure Logging Endpoints will apply :xmlval:`SIGN` [#f1]_ protection to RTPS Submessages for logged security events. Note that the Builtin Secure Logging Endpoints will only be created when you set the :value:`SECURITY_TOPIC` mask in the :property:`logging.mode_mask` property [#f2]_ (see :numref:`|RTI_SP_PRODUCT_HEADING| Properties for Configuring Logging`). In this case, keys for the Builtin Logging |DW| and matching |DRs| will need to be exchanged.

For further details on the Builtin Secure Endpoints, refer to :ref:`p2_core/elements_dds_secure_system:Security Builtin Topics`.


.. [#f1] In |CONNEXT| 5.3.0, the |LoggingT| did not use |SubmsgProtection| (which did not comply with the |SEC_SPEC|). For backward compatibility with 5.3.0, you can choose to disable |SubmsgProtection| in this |TOPIC| with the :property:`access_control.use_530_logging_protection` property (see :numref:`Additional |RTI_SP_PRODUCT_HEADING| Properties for Configuring Logging Distributed Over DDS`).

.. [#f2] In |CONNEXT| 6.0.1 and before, the creation of the Builtin Secure Logging Endpoints was controlled with the :property:`logging.distribute.enable` property.


User-Defined Secure Endpoints
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
You can choose to protect each of the user-defined topics separately. The impact of exchanging keys for your user-defined secure endpoints will be directly related to the number of Endpoints in your participants.

By default, |SubmsgProtection| and |DataProtection| use the same Key Material. Therefore, each of your topics will have a single key, regardless of whether you protect your |TOPIC| with |SubmsgProtection|, |DataProtection|, or both.

You can choose not to use the same keys for Serialized Data and Submessage Protections by setting the :property:`cryptography.share_key_for_metadata_and_data_protection` property to :value:`FALSE`, as specified in :numref:`|RTI_SP_PRODUCT_HEADING| Properties for Configuring Cryptography`. Then your participants will need to generate and exchange two different keys for each of your |SecDWs|.

.. list-table:: Size of the RTPS message containing the Key Material exchanged on the wire for each |Entity|, assuming AES-GCM-128, which has a key length of 16 Bytes
  :name: Size of the RTPS message containing the Key Material
  :widths: auto
  :header-rows: 1
  :class: longtable

  * - Without Origin Authentication Protection
    - With Origin Authentication Protection
      (requries sending an additional receiver-specific key)

  * - 364 Bytes
    - 380 Bytes


You can estimate the number of keys your |DPs| will put on the network for your
user-defined endpoints. For each |TOPIC|, multiply the number of |DWs| by the
number of compatible |DRs| (i.e., matching |DRs| with compatible QoS). The sum
will tell you how many keys will be exchanged when new matches are discovered.

In addition, when you use Topic Queries (see :link_connext_dds_pro_um:`Topic Queries in the Core Libraries User's Manual <#users_manual/TopicQueries.htm>`), one additional key is exchanged per matching |DW|/|DR|. This is required because internally, |CONNEXT| uses two GUIDs for each |DW|. The same mechanism is put in place for Multi-channel |DWs| (see :link_connext_dds_pro_um:`Multi-channel DataWriters in the Core Libraries User's Manual <#users_manual/MultichannelDatawriters.htm>`). In this latter case, :math:`N-1` additional keys are exchanged, where :math:`N` is the number of channels.


Receiver-Specific Keys
^^^^^^^^^^^^^^^^^^^^^^
If you enable the Origin Authentication Protection for a |TOPIC|, each |SecEntity| for that |TOPIC| will have its own receiver-specific key. This implies that the Key Material for |DWs| and |DRs| of that |TOPIC| will be around :math:`1.5\times` the size since it will include a |SenderKey| and a Receiver-specific Key. This implies that topics protected with Origin Authentication Protection will produce around :math:`1.5\times` the traffic during the key exchange process.

Note that you can apply Origin Authentication Protection to either builtin and user-defined topics by tuning the corresponding |GovRules| (see :ref:`p2_core/cryptography:Security Protections Applied by DDS Entities`).

Factors Impacting Performance and Scalability at Startup
--------------------------------------------------------
Now you know the additional processes that happen when security is enabled. Now we will list a set of factors that will impact scalability at startup.

Impact of OCSP
^^^^^^^^^^^^^^
Use of |OCSP| may have a great impact on |DP| creation time. If
a |DP| is configured to use |OCSP|, then the |DP| will contact the
|OCSPResp| listed in the certificate to verify the certificate validity and
obtain the |OCSPToken| that can be presented as a proof of certificate
validity to its peers. This is a blocking operation which holds the |DP|
creation process until the |OCSP| response is received. It may take a
significant amount of time and is highly dependent on the network and
the responder reachability and availability. If a short startup time is
important in your system consider using |CRL| as an alternative to |OCSP| and
remove the |OCSPResp| URL from your certificates. In addition, on a |DP|
configuration level, you may set :property:`authentication.ocsp_ignored`
to :value:`TRUE` in order to disable all OCSP-related functionality on the
local |DP|. Note that, due to internal |RTI_SP_PRODUCT| arrangement, setting
:xmltag:`identity_credential_authority_validation` :xmltag:`ocsp` to
:value:`IGNORED` is not enough to prevent the |DP| from contacting the
|OCSPResp| at |DP| creation.

Number of Participants and Endpoints in Your Secure Domain
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The number of participants in your |SecDomain| will certainly have an impact on scalability. The reason is that discovery and mutual authentication occur between each pair of |DPs|. This is not much different from the unsecure scenario. However, the |RTI_SP_PRODUCT| add Discovery time, both by adding additional operations and sending additional messages and files. In general, you can expect :math:`3\times` the traffic you would have without security for each pair of |DPs|.

Also, since every |DP| needs to authenticate with every other |DP| in your |SecDomain|, the traffic will increase as the number of participants grows. If the discovery traffic for each pair of |DPs| increases by :math:`3`, then the traffic in your |SecDomain| will increase by :math:`1.5\cdot N\cdot (N-1)`, where :math:`N` is the number of participants in your |SecDomain|.

The factors that you can tune and that will have the bigger impact are covered below.


Contents of the Identity Certificates
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
During the Authentication process, |DPs| exchange their Identity Certificates (as specified in the :property:`dds.sec.auth.identity_certificate` property in :numref:`DDS Security Properties for Configuring Authentication`. These artifacts are X.509 digital certificates in PEM format that may include a human-readable part and the Base64 representation of the certificate. By default, the |SP_BUILTIN| trim out the human-readable part of the certificate before sending it to save some bandwidth. You may want to have the human-readable part sent for debugging purposes. You can control this behavior with the :property:`authentication.propagate_simplified_identity_certificate` property.


Contents of Your Permissions Documents
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
During the Authentication process, |DPs| exchange their |PermissionsDoc| (as specified in the :property:`dds.sec.access.permissions` property in :numref:`DDS Security Properties for Configuring Authentication`. The Permissions Document is specified in an XML file that defines the access control permissions per domain and per |TOPIC| for individual |DPs|. The Permissions CA must sign the |PermissionsDoc|. Hence, the |PermissionsDoc| is sent "as is" on the wire so that other |DPs| can verify the signature.

You can potentially set the same |PermissionsDoc| across all of the participants in your system. For example, you have |P1| load a |PermissionsDoc| that includes permissions for both |P1| and |P2|. Then, you can have |P2| load the same |PermissionsDoc|.

Having the same |PermissionsDoc| across all the participants in your system can be handy for prototyping. However, it requires sending the same |PermissionsDoc| on the network during each authentication.

A better option would be to define the permissions so that you use a different file for each of your participants. For |P1| you will have the permissions for that participant, for |P2|, you will have the permissions for that different participant. This way, you will reduce network traffic by not sending unnecessary information, especially if you have a big system with hundreds of participants.

Selecting the right granularity for your |PermissionsDocs| has a big impact on scalability. For example, compare the following scenarios in a system with :math:`100` participants.

#. Each participant has its own |PermissionsDoc| containing only one grant: each participant sends its permissions to every other participant (:math:`100\times 1\times 99 = 9,900` permission grants exchanged).

#. All the participants have the same |PermissionsDoc|: each participant sends around :math:`N` times its permissions to every other participant (:math:`100\times 100\times 99 = 990,000`  permission grants exchanged)


Assuming that the permission grant for a single participant is around :math:`1 \mathrm{kB}` in size, with only :math:`100` participants you can reduce the total network load from :math:`990 \mathrm{MB}` to around :math:`10 \mathrm{MB}`, saving up to :math:`980 \mathrm{MB}` of network traffic.

As a general rule, :math:`N\times (N-1)` |PermissionsDoc| are sent on your network (where :math:`N` is the number of |DPs| in your |SecDomain|).


Impact of Different Protection Kinds
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
If you use |DiscoveryProtection|, some parts of the discovery process will require additional cryptographic operations (see :ref:`p2_core/cryptography:discovery_protection_kind (domain_rule)`). In this case, part of the messages sent during discovery will be protected with |SubmsgProtection| (see :ref:`p2_core/cryptography:Submessage Protection`), at the level specified by the :xmltag:`discovery_protection_kind` |GovRule|.

Also, when you set different protection kinds, symmetric keys need to be exchanged, which will be sent on the network through the Secure Key Exchange Channel. For instance, additional Receiver-specific keys are exchanged when you use Origin Authentication Protection. See :ref:`p3_advanced/design_considerations:Impact of Key Exchange on Scalability at Startup`, where we explain which protection kinds require sending which keys.

Here is a summary of the keys that need to be generated and exchanged:

- :xmlval:`ENCRYPT` and :xmlval:`SIGN` protections will require exchanging one key per |DW| and |DR| of the |TOPIC| being protected. By default, this is independent of where you apply the protection (see :ref:`p3_advanced/design_considerations:User-defined Secure Endpoints`).

- Protection kinds ending in :xmlval:`_WITH_ORIGIN_AUTHENTICATION` will require exchanging one additional key per |DW| and |DR| of the |TOPIC| being protected.


|RTI_SP_PRODUCT_HEADING| Impact on Scalability and Performance During Steady State
==================================================================================
The |RTI_SP_PRODUCT|' impact on performance will depend on multiple factors, including the security requirements of your systems, hardware considerations, and interactions with other |CONNEXT| features.

Overhead of the Different Protection Kinds
------------------------------------------
When an application uses security, the contents of the RTPS packets will be different. For example, cryptographic metadata will be added around the protected parts, which may be encrypted depending on the configured protection.

Protecting your data will always have an overhead. Depending on what you protect (user data, metadata, rtps packet, liveliness, etc), different parts of the RTPS packets will be different.

The following sections discuss the packet growth that you can expect for each of the protection kinds.


Discovery Protection
^^^^^^^^^^^^^^^^^^^^
You can enable |DiscoveryProtection| by setting the :xmltag:`discovery_protection_kind` |GovRule| to a value other than :xmlval:`NONE`.

The greatest impact of enabling |DiscoveryProtection| for a |TOPIC| is at startup, since the discovery data for that |TOPIC| will be sent protected (increased CPU and network usage, as explained in :ref:`p3_advanced/design_considerations:Builtin Secure Endpoints`). Still, it has some impact on steady state, since TopicQuery requests related to your |TOPIC| will be exchanged through the |SecServiceReqTopic|, whose configuration is controlled the same way as |SecDiscoveryEPs| (see :ref:`p2_core/cryptography:Builtin Secure Discovery Endpoints` and :ref:`p3_advanced/design_considerations:Interaction with Topic Queries`).

You could also modify some of your |DW|/|DR| QoS policies (such as partitions), or a network change could indirectly trigger a change in the |DW|/|DR| information. In this situation, the policies need to be propagated. If |DiscoveryProtection| is enabled for your |TOPIC|, the endpoint declarations used to propagate the QoS will be sent using the |SecDiscoveryEPs| (see :ref:`p2_core/cryptography:Builtin Secure Discovery Endpoints`). These endpoints will apply RTPS |SubmsgProtection| to the level you configure with the :xmltag:`discovery_protection_kind` |GovRule|, increasing both CPU usage and network usage. (For the overhead caused by the |SubmsgProtection|, see :ref:`p3_advanced/design_considerations:Submessage Protection`.)

Finally, you could modify some of your DomainParticipantQos policies. If |DiscoveryProtection| is enabled, the participant declarations used to propagate the QoS will be sent using the |SecDiscoveryEPs| (see :ref:`p2_core/cryptography:Builtin Secure Discovery Endpoints`). Note that participant declarations are also sent on IP mobility events (and these will be protected if |DiscoveryProtection| is enabled). For further information, see :ref:`p2_core/cryptography:RTPS Protocol Changes to Support Secure Entities Traffic`.



Liveliness Protection
^^^^^^^^^^^^^^^^^^^^^
You can enable |LivelinessProtection| by setting the :xmltag:`liveliness_protection_kind` |GovRule| to a value other than :xmlval:`NONE`.

When you enable |LivelinessProtection| for a |TOPIC|, liveliness information related to your |TOPIC| will be exchanged through the Builtin Secure Liveliness Endpoints (only if the LIVELINESS QosPolicy is set to :value:`AUTOMATIC` or :value:`MANUAL_BY_PARTICIPANT`). These endpoints will apply RTPS |SubmsgProtection| to the level you configure with the :xmltag:`liveliness_protection_kind` |GovRule|, increasing both CPU usage and network usage. (For the overhead caused by the |SubmsgProtection|, see :ref:`p3_advanced/design_considerations:Submessage Protection`.) For further information, see :ref:`p2_core/cryptography:RTPS Protocol Changes to Support Secure Entities Traffic`.

Serialized Data Protection
^^^^^^^^^^^^^^^^^^^^^^^^^^
You can enable |DataProtection| by setting the :xmltag:`data_protection_kind` |GovRule| to a value other than :xmlval:`NONE`.

When you enable |DataProtection|, data in the |DW|'s queue will be protected before encapsulating it in an RTPS Submessage. Therefore, user data is only protected once and retransmissions do not need re-encryption.

The length of the data field increases (in the RTPS Submessage) because the ``serializedData`` field now includes a header and a footer with cryptographic information. The |CryptoHeader| includes information such as an identifier for the key used to encrypt the payload. The |CryptoFooter| includes the generated message authentication code (MAC). This extra  information allows the receiver to decrypt the message (when needed) and verify its integrity. See :ref:`p2_core/cryptography:Security Protections Applied by DDS Entities` and :ref:`p2_core/cryptography:RTPS Protocol Changes to Support Secure Entities Traffic`.

More concretely, each sample (i.e., :submsg:`DATA` submessage) sent by your |DWs| will have an additional 40 bytes (in the case of :xmlval:`SIGN` protection) or 44 bytes (in the case of :xmlval:`ENCRYPT` protection), as shown in :numref:`Expected growth of serialized payload when applying Serialized Data Protection`. **This is independent of the sample length.**

Note that, in some cases, this overhead could trigger fragmentation for samples that were just below the fragmentation limit before applying the protection.

.. list-table:: Expected Growth of serialized payload when applying Serialized Data Protection, in Bytes
  :name: Expected growth of serialized payload when applying Serialized Data Protection
  :widths: auto
  :header-rows: 1
  :class: longtable

  * - Element
    - Extra bytes when using :xmlval:`SIGN`
    - Extra bytes when using :xmlval:`ENCRYPT`

  * - |CryptoHeader|
    - 20
    - 20

  * - |CryptoContent|
    - 0
    - 4

  * - |CryptoFooter|
    - 20
    - 20

  * - Total
    - 40
    - 44


Submessage Protection
^^^^^^^^^^^^^^^^^^^^^
You can enable |SubmsgProtection| by setting the :xmltag:`metadata_protection_kind` |GovRule| to a value other than :xmlval:`NONE`.

|SubmsgProtection| applies to messages sent both by the |DW| and the |DR|. Secure Endpoints will protect submessages right before putting them on the network. Note that a batch containing multiple samples is considered a single submessage. Refer to :ref:`p2_core/cryptography:Submessage Protection` for a comprehensive list of all protected submessages.

Note that |SubmsgProtection| implies adding a Secure Prefix Submessage and a Secure Postfix Submessage to the RTPS message. For further details, see :ref:`p2_core/cryptography:Security Protections Applied by DDS Entities` and :ref:`p2_core/cryptography:RTPS Protocol Changes to Support Secure Entities Traffic`.

The growth in size caused by |SubmsgProtection| is slightly higher than with |DataProtection|. However, note that |SubmsgProtection| applies to submessages sent by both |DWs| and |DRs| for the |TOPIC| being protected. Therefore, each submessage protected by your |DWs| or |DRs| will have an additional 48 bytes (in the case of :xmlval:`SIGN`) or 56 bytes (in the case of :xmlval:`ENCRYPT`), as shown in :numref:`Expected growth of serialized payload when applying Submessage Protection`. This overhead is independent of the sample length.

If you enable Origin Authentication Protection (with :xmlval:`SIGN_WITH_ORIGIN_AUTHENTICATION` or with :xmlval:`ENCRYPT_WITH_ORIGIN_AUTHENTICATION`), each submessage that your |DWs| and |DRs| protect will have an additional 20 bytes in the |CryptoFooter| per matching |DR|/|DW|. This overhead is limited by the :property:`cryptography.max_receiver_specific_macs` property (see :numref:`|RTI_SP_PRODUCT_HEADING| Properties for Configuring Cryptography`).


.. list-table:: Expected Growth of Serialized Payload When Applying |SubmsgProtection|, in Bytes
  :name: Expected growth of serialized payload when applying Submessage Protection
  :widths: auto
  :header-rows: 1
  :class: longtable

  * - Element
    - Extra bytes when using :xmlval:`SIGN`
    - Extra bytes when using :xmlval:`ENCRYPT`
    - Extra bytes when using :xmlval:`_WITH_ORIGIN_AUTHENTICATION` [#f3]_

  * - :submsg:`SEC_PREFIX`
    - 24
    - 24
    - 0

  * - :submsg:`SEC_BODY`
    - 0
    - 8
    - 0

  * - :submsg:`SEC_POSTFIX`
    - 24
    - 24
    - 20 per matching entity

  * - Total
    - 48
    - 56
    - 20 per matching entity


.. [#f3] This overhead is limited by the :property:`cryptography.max_receiver_specific_macs` property (see :numref:`|RTI_SP_PRODUCT_HEADING| Properties for Configuring Cryptography`).

Note that if you wish to enable Origin Authentication Protection on
:xmltag:`metadata_protection_kind`, :xmltag:`discovery_protection_kind`, or any
other protection kind that affects submessage protection, then you must set the
:property:`cryptography.max_receiver_specific_macs` property to a positive
integer value; :value:`AUTO` is not allowed in this situation.

RTPS Protection
^^^^^^^^^^^^^^^
You can enable |RTPSProtection| by setting the :xmltag:`rtps_protection_kind`
|GovRule| to a value other than :xmlval:`NONE`.

|RTPSProtection| affects the |DP| and applies to every packet that is sent by
protecting the whole RTPS message right before putting it on the network. The
only exception to |RTPSProtection| is:

* Traffic during the initial Participant Discovery used in the bootstrapping,
  which is never protected.
* Traffic of the |AuthT| (|AuthTName|), which is never protected.
* Traffic of the |SecKeyExchangeT| (|SecKeyExchangeTName|), which use
  :xmlval:`ENCRYPT` protection at the Submessage level instead.

For further details, see :ref:`p2_core/cryptography:Security Protections Applied by DDS Entities`
and :ref:`p2_core/cryptography:RTPS Protocol Changes to Support Secure Entities Traffic`.

|RTPSProtection| implies a growth in every RTPS message that your |DPs| send on
the |SecDomain| [#]_. Each RTPS message sent by your participants will have an
additional 72 bytes (in the case of :xmlval:`SIGN`) or 80 bytes (in the case of
:xmlval:`ENCRYPT`), as shown in :numref:`Expected growth of serialized size when applying RTPS Protection`.
This is independent of the sample length.

If the :property:`cryptography.enable_additional_authenticated_data` property
(see :numref:`|RTI_SP_PRODUCT_HEADING| Properties for Configuring Cryptography`) is
set to :value:`FALSE`, then the contents will include a copy of the RTPS header
(20 bytes) - for more information, read
:ref:`p2_core/cryptography:RTPS Protection`. Therefore, if Additional
Authenticated Data is disabled, each RTPS message will have a total number of
92 extra bytes (in the case of :xmlval:`SIGN`) or 100 bytes (in the case of
:xmlval:`ENCRYPT`).

If you enable Origin Authentication Protection (with :xmlval:`SIGN_WITH_ORIGIN_AUTHENTICATION`
or with :xmlval:`ENCRYPT_WITH_ORIGIN_AUTHENTICATION`), each RTPS message sent by
your participant will have an additional 20 bytes in the |CryptoFooter| per
receiver. This overhead may optionally be limited by the :property:`cryptography.max_receiver_specific_macs`
property (see
:numref:`|RTI_SP_PRODUCT_HEADING| Properties for Configuring Cryptography`). If
it is not limited, then any |RecSpecificMACs| that cannot fit in a message will
be included in subsequent resends of the same message (see
:ref:`p2_core/cryptography:Origin Authentication Protection Implications`).

The number of |RecSpecificMACs| in an RTPS message is the union of the
|RecSpecificMACs| each of its submessages would need. For example, assume that
you have an RTPS message with three submessages. The first submessage is
directed to a receiver A, the receiver of the second submessage is B, and the
receiver of the third submessage is unknown. In this situation, if
|SubmsgProtection| was 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 |RecSpecificMACs|:

.. math::

  \lbrace A\rbrace\cup\lbrace B\rbrace\cup\lbrace A,B,C,D\rbrace=\lbrace A,B,C,D\rbrace


.. figure:: ../static/rec-specific-macs-multiple-receivers.png
  :scale: 50%
  :name: design_considerations:Receiver-specific MACs included in an RTPS Message that uses RTPS Protection with Origin Authentication
  :align: center

  Receiver-Specific MACs Included in an RTPS Message that Uses RTPS Protection
  with Origin Authentication


.. list-table:: Expected Growth of Serialized Size When Applying |RTPSProtection| (AAD disabled), in Bytes
  :name: Expected growth of serialized size when applying RTPS Protection
  :widths: auto
  :header-rows: 1
  :class: longtable

  * - Element
    - Extra bytes when using :xmlval:`SIGN`
    - Extra bytes when using :xmlval:`ENCRYPT`
    - Extra bytes when using :xmlval:`_WITH_ORIGIN_AUTHENTICATION` [#f4]_

  * - :submsg:`SRTPS_PREFIX`
    - 24
    - 24
    - 0

  * - :submsg:`SRTPS_BODY`
    - 24
    - 32
    - 0

  * - :submsg:`SRTPS_POSTFIX`
    - 24
    - 24
    - 20 per matching entity

  * - Total
    - 72
    - 80
    - 20 per matching entity


.. [#f4] This overhead may optionally be limited by the :property:`cryptography.max_receiver_specific_macs`
   property (see :numref:`|RTI_SP_PRODUCT_HEADING| Properties for Configuring Cryptography`).

.. [#] Exceptions of RTPS messages to which |RTPSProtection| applies are covered
   in :ref:`p2_core/cryptography:DomainParticipants`.


Origin Authentication Protection
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
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 is communicating with multiple Receivers via multicast and shares the same encryption key with all of them.

You can add Origin Authentication protection to |SubmsgProtection| by setting the :xmltag:`metadata_protection_kind` |GovRule| to :xmlval:`SIGN_WITH_ORIGIN_AUTHENTICATION` or :xmlval:`ENCRYPT_WITH_ORIGIN_AUTHENTICATION`.
You can add Origin Authentication protection to |RTPSProtection| by setting the :xmltag:`rtps_protection_kind` |GovRule| to :xmlval:`SIGN_WITH_ORIGIN_AUTHENTICATION` or :xmlval:`ENCRYPT_WITH_ORIGIN_AUTHENTICATION`.

This protection involves computing additional |RecSpecificMACs| with a secret key that the Sender shares only with one Receiver.
More concretely, the |CryptoFooter| will contain 1 additional MAC for every receiver targeted by the message.
For example, if a |DW| sends a message to 10 different |DRs| (in 10 different |DPs|), you can expect 10 additional MACs added to the |CryptoFooter|.
Note that Receivers in the same remote |DP| will share the Receiver-specific Key and therefore, a single |RecSpecificMAC| will be added for all of them.
You can optionally limit the number of |RecSpecificMACs| that are appended to a message by tuning the :property:`cryptography.max_receiver_specific_macs` property
(This has security implications. Please refer to
:ref:`p2_core/cryptography:Reducing Performance Impact of Origin Authentication`
for more information).
For further information, see :ref:`p2_core/cryptography:Origin Authentication Protection Implications`.

Note that the major implication of this protection is that |RecSpecificMACs| will be added to the packet, which increases its length.


SIGN VS ENCRYPT
^^^^^^^^^^^^^^^
:xmlval:`ENCRYPT` protection is slightly more expensive than :xmlval:`SIGN`. Since :xmlval:`ENCRYPT` adds a length field in the |CryptoContent|, the network usage of :xmlval:`ENCRYPT` is slightly greater than the network usage of :xmlval:`SIGN`. The computational cost of :xmlval:`ENCRYPT` is also higher than :xmlval:`SIGN`, especially as the sample gets larger.

However, the difference between :xmlval:`SIGN` and :xmlval:`ENCRYPT` protections is so small that the impact on throughput and latency is usually minimal. Please note that you can combine :xmlval:`SIGN` and :xmlval:`ENCRYPT` by applying different protections at different stages. For example, you can potentially protect the integrity and confidentiality of a particular |TOPIC|'s payload (by setting |DataProtection| to :xmlval:`ENCRYPT` for that |TOPIC|) while protecting the integrity of all the traffic (by setting |RTPSProtection| to :xmlval:`SIGN`). In this scenario, your application will require :math:`\sim 2 \times` CPU time to compute the cryptographic operations, if we compare it with a scenario where a single protection is enabled. Enabling different protections at the same time will certainly impact the throughput and latency of your application.

For further information on what entities are responsible for each protection kind, see :ref:`p2_core/cryptography:Security Protections Applied by DDS Entities`.

OCSP revalidation
^^^^^^^^^^^^^^^^^
Using OCSP adds some network communication overhead that grows with an increasing number
of |DPs| in a domain. The overhead also grows when the certificate validity period
(configured in the |OCSPResp|) is shortened. The network overhead consists of
an HTTP(s) request/response between a |DP| and the |OCSPResp|, and the propagation of
the renewed |OCSP| stapling token to all |DP| peers.

Factors Impacting Performance and Scalability During Steady State
-----------------------------------------------------------------

Performance Impact of Different Protection Kinds
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The protection kinds determine which cryptographic operations will be applied to which messages and submessages. For instance, protecting the submessages with :xmlval:`ENCRYPT_WITH_ORIGIN_AUTHENTICATION` requires more operations than protecting the same submessages with :xmlval:`SIGN`. It is also important to see what you protect. For example, if you set :xmltag:`payload_protection_kind`, :xmltag:`metadata_protection_kind`, and :xmltag:`rtps_protection_kind` to :xmlval:`ENCRYPT` in a reliable |TOPIC|, every sample that your |DW| publishes will be encrypted three times; and every :submsg:`HEARTBEAT` and every :submsg:`ACKNACK` sent for that |TOPIC| will be encrypted twice. Hence, one of the major performance implications with respect to security is the protection kinds set in your |GovernanceDoc|.

For best performance, adjust your |GovernanceDoc| to set the levels of protection that best fits your use case.


Interaction Between the |RTI_SP_PRODUCT_HEADING| and Batching QoS
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Payload protection is applied to an entire batch instead of to each individual sample within a batch. Therefore, with |DataProtection|, you will achieve the throughput of |SubmsgProtection| when sending live batches without having to re-encode when resending repair batches.


Interaction Between the |RTI_SP_PRODUCT_HEADING| and Multicast
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Multicast does not interact with how many times cryptographic operations are
called to protect data, but can help reduce the network usage. Unlike
TLS transports, which do not allow multicast at all, the |RTI_SP_PRODUCT| can take advantage of multicast to boost the performance of your system. Using multicast along with the |RTI_SP_PRODUCT| will provide a performance boost similar (or identical) to the one that you will have in an unsecure scenario.

In general, when you enable security, each message is protected once (see :ref:`p3_advanced/design_considerations:Interaction with Asynchronous Publishing`). Then the protected message is delivered to the transport once per destination. When you enable multicast, the protected sample is sent once to the network, as if it were a single destination, and the network will propagate it to the actual recipients. This is a great performance improvement over TLS, where each sample needs to be protected once per destination, then sent to each destination with multiple socket write operations.

.. figure:: ../static/multicast.png
  :scale: 50%
  :name: Transport Security VS DDS Security
  :align: center

  Transport Security VS DDS Security


Interaction with Reliability
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|DataProtection| does not interact with reliability since the protection occurs before putting the samples in the |DW|'s queue. Therefore, repairing or resending a sample does not require additional cryptographic operations when using |DataProtection|.

In contrast, |SubmsgProtection| and |RTPSProtection| apply the cryptographic operation right before sending the sample to the transport. Therefore, repairing or resending a sample will require additional cryptographic operations, such as re-encrypting it.


Scalability Considerations for Origin Authentication Protection
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
When you use :xmlval:`SIGN_WITH_ORIGIN_AUTHENTICATION` or :xmlval:`ENCRYPT_WITH_ORIGIN_AUTHENTICATION`, a |RecSpecificMAC| is added to the message being protected. As an optimization, when using the |DP|, this MAC is the same for every matching |DR| within a remote |DP| (i.e., the number of MACs does not grow per |DR|, but per |DP|). Therefore, the higher the number of |DPs| in your system, the bigger your RTPS packets will be.

For further details, see :ref:`p2_core/cryptography:Origin Authentication Protection Implications`.


Interaction with Content Filtered Topics
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
For Writer-side filtering: if |DataProtection| is in use and set to :xmlval:`ENCRYPT`, the |DW|'s queue will have samples encrypted. This is done to avoid encrypting each time a sample is sent, such as for repairs. However, this comes with some drawbacks: to apply Writer-side filtering, the |DW| needs to decrypt the samples in its queue, see if they match the filter, then send the corresponding samples. This is only needed for historical data: live samples are filtered before encrypting (i.e., which locators the sample will be sent to is decided before encrypting).


Interaction with Topic Queries
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
When you enable |DiscoveryProtection| for a |TOPIC| (by setting :xmltag:`enable_discovery_protection` to :xmlval:`TRUE`), TopicQuery requests related to that |TOPIC| will be exchanged through the Builtin Secure Service Request Topic. |SubmsgProtection| is applied to this |TOPIC|, at the level defined by the :xmltag:`discovery_protection_kind` |GovRule| (see :ref:`p2_core/cryptography:Builtin Secure Discovery Endpoints`).

Protecting TopicQuery requests is needed in order not to leak information about your |TOPIC|. For example, in a hospital scenario, if you request information about a particular patient and the request was not protected, the patient name could be leaked.

For further information on the overhead produced by this kind of protection, refer to :ref:`p3_advanced/design_considerations:Submessage Protection`.


Interaction with Asynchronous Publishing
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
In general, the following sequence of events is used to protect-then-send a message to multiple destinations:

#. Serialize the RTPS message with all its submessages.
#. Only when using |SubmsgProtection| or RTPS Protection: Apply the cryptographic operations to protect the message with the configured level of protection.
#. Send the protected RTPS message to multiple destinations.

When you enable the Asynchronous Publishing feature (see :link_connext_dds_pro_um:`ASYNCHRONOUS_PUBLISHER QosPolicy (DDS Extension) in the Core Libraries User's Manual <#users_manual/ASYNCHRONOUS_PUBL_Qos.htm>`), all this processing is done independently for each destination. This is required to support mechanisms such as flow controllers. Therefore, when Asynchronous Publishing is enabled, sending a message to multiple destinations will require the following steps for each destination:

#. Serialize the RTPS message with all its submessages.
#. Only when using Submessage Protection or RTPS Protection: Apply the cryptographic operations to protect the message with the configured level of protection.
#. Send the protected RTPS message to a single destination.

As you can see, the latter case requires more cryptographic operations.

When you enable |DataProtection|, you need to increase :link_connext_dds_pro_um:`DDS_FlowControllerTokenBucketProperty_t::bytes_per_token <#users_manual/Token_Bucket_Properties.htm>` to include the overhead described in :ref:`p3_advanced/design_considerations:Serialized data protection` if you want to publish samples at the same frequency.


Interaction with Compression
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
When compression and |DataProtection| are enabled, compression will take place first, then the sample will be protected and stored in the |DW|'s Queue.

The combination of compression, batching and |DataProtection| is supported. In this combination, compression is applied to the batch, and then |DataProtection| is applied to the compressed batch.

Keep in mind that both compression and protection add a significant CPU overhead with performance penalties to consider, so they only make sense under specific scenarios.


Interaction with CRC
^^^^^^^^^^^^^^^^^^^^
|CONNEXT| provides two different ways to add CRC to every RTPS message sent.
The first one is a legacy CRC mechanism sent on a dedicated, RTI-specific
RTPS CRC32 submessage
(see :link_connext_dds_pro_um:`WIRE_PROTOCOL QosPolicy (DDS Extension) in the Core Libraries User's Manual <#users_manual/WIRE_PROTOCOL_Qos.htm>`).
The second option is defined in the RTPS Specification 2.5 and involves a CRC
that is optionally transported on the RTPS Header Extension. Both options enable a
recipient of the message to verify its integrity and discard it if corruption is
detected. Only the CRC in RTPS Header Extension is compatible with |RTI_SP_PRODUCT| whereas
the legacy CRC is not compatible with |RTI_SP_PRODUCT|.

The |RTI_SP_PRODUCT| use 16-byte MACs to detect unexpected modifications on the received
messages (see :ref:`p2_core/cryptography:Cryptography`). Note that the |RTI_SP_PRODUCT|
rely on the transport to detect and discard corrupted messages. Therefore, if
the Cryptography plugin cannot validate a MAC upon a message reception, it will
consider that the message was tampered with, compromising its integrity. This
is a more secure approach and also discards corrupted messages.

Interaction with Transport UDPv4_WAN
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
UDP WAN binding pings can be protected with |PSKProtection|. See
:ref:`p4_integrations/real-time_wan_transport:Support for RTI Real-Time WAN Transport`
for details.

.. _section-recommendations-for-usage-with-observability:

Recommendations for Usage with |OBSERVABILITY_HEADING|
======================================================

The |RTI_SP_PRODUCT| can secure DDS communications between |RTI_MONITORINGLIBRARY2|
and |RTI_COLLECTORSERVICE| (see :ref:`chapter-observability-framework` for further
details). If you are planning on using this capability, you should consider the following:

* In the |GovernanceDoc|, **do not set** :xmltag:`allow_unauthenticated_participants`
  to :xmlval:`TRUE`. |RTI_MONITORINGLIBRARY2| does not have the ability to
  communicate with both authenticated and unauthenticated |DPs| at the
  same time. Setting :xmltag:`allow_unauthenticated_participants` to
  :xmlval:`TRUE` will generate an internal logic overhead that is not
  necessary for |RTI_MONITORINGLIBRARY2|.

* In the |GovernanceDoc|, **set** :xmltag:`monitoring_metrics_protection_kind` and/or
  :xmltag:`monitoring_logging_protection_kind` (at least one of them) to a value
  different than :xmlval:`NONE`. If you do not plan to protect any telemetry data,
  it is better to not use the |RTI_SP_PRODUCT|.

Security Considerations when Enabling Compression
=================================================

When enabling data compression (see
:link_connext_dds_pro_um:`Data Compression in the Core Libraries User's Manual <#users_manual/DATAREPRESENTATION_Qos.htm#59.3.2_Data_Compression>`)
in combination with any level of |RTI_SP_PRODUCT| protection,
compression will take place first, then the |RTI_SP_PRODUCT| will protect
the compressed payload.

Using compression before encryption for confidential data can enable oracle
attacks if a malicious actor has partial control of the compressed data.
In particular, using adaptive data compression on a payload containing a
mixture of unknown confidential plaintext and chosen plaintext can result
in content-sensitive changes in the resulting compressed text length. By
observing these length changes, a malicious actor can determine when the
injected chosen plaintext is similar to the unknown confidential plaintext,
making it much easier for the malicious actor to find out the content
of the confidential plaintext. The
`CRIME <https://en.wikipedia.org/wiki/CRIME>`__ and
`BREACH <https://en.wikipedia.org/wiki/BREACH>`__
attacks are examples of protocol attacks using this phenomenon.

To prevent information disclosure threats,
enabling compression for confidential data is discouraged.
The only exceptions are scenarios where the compressed data is guaranteed to
contain information generated only by actors that are allowed to know the
contents of the whole compressed payload.

Considerations when Enabling OCSP
=================================

In comparison to using a |CRL|, enabling |OCSP| simplifies the logistics of
revoking |IdentityCerts| before their expiration. There is no need to distribute
|CRL| files or update properties over all |DPs| in the system. With |OCSP|, all
certificate status management can be done in one place and |DPs| automatically
fetch the latest |IdentityCert| status themselves. Furthermore, enabling |OCSP|
is straightforward from the point of view of |DP| configuration. In the basic
scenario, it only requires a certificate with the :value:`authorityInfoAccess`
field including an |OCSPResp| URL. However, enabling |OCSP| requires additional
work on the system level and in the |OCSPResp|. In this section we discuss high-level
considerations when enabling |OCSP|. This is not an exhaustive list.

.. warning::

    The |OCSP| feature is currently only available in the |RTI_SP_PRODUCT| for
    OpenSSL |OPENSSLVERSION|. The |RTI_SP_PRODUCT| for OpenSSL 1 and the
    |RTI_SP_PRODUCT| for wolfSSL |WOLFSSLVERSION| do not support |OCSP|.

When OCSP is Not Recommended
------------------------------

On one hand, the |RTI_SP_PRODUCT| require knowing the updated status of the |IdentityCerts|
at any moment. On the other hand, |OCSP| is a network-based, request-reply protocol, and
querying for the status of a certificate takes some time. As a solution, the |RTI_SP_PRODUCT|
query the |DP|'s |OCSPResp| some time in advance. However, a slow, unresponsive |OCSPResp|
can be the cause of identity validation failures. The following list contains some
high-level requirements and conditions where we do not recommend using |OCSP|:

* Short and reliable startup time. A |DP| has to contact its |OCSPResp| while
  being created, and that is a blocking operation. This means that the startup time
  is as short and reliable as request-reply communication with your
  |OCSPResp|. In the worst-case scenario, this may take a long time and may
  eventually cause the |DP| creation to fail. However, if you have high
  confidence in communication with your |OCSPResp|, this scenario might not be
  a concern.

* Very unstable network environment, with a real risk of extended periods of time when the
  |OCSPResp| is not available.

* A strictly controlled network in conjunction with a system that also permits a dynamic set
  of multiple Certificate Authorities/|OCSPResps| located outside of the network.

* An isolated, static, resource-constrained system, where regular |OCSP| token updates
  may introduce too much overhead.

Responder Availability
----------------------

When |OCSP| is enabled, |DPs| will query their |OCSPResp| when they start up,
and then periodically during their lifecycle. During this whole time, the
|OCSPResp| must be network-reachable and available. Otherwise, the |DPs| may
encounter startup issues, or be banished from their |Domain| after a failure to
get an updated |OCSPToken|. There are a few measures that you can implement if
you cannot guarantee an |OCSPResp|'s immediate availability at all times, or if
you allow/expect intermittent outages:

* In the |OCSPResp|, configure the :value:`nextUpdate`. The |SP_BUILTIN| mandate
  the presence of this field in the responses. Make sure that the value is large
  enough to ensure the desired |OCSPToken|'s validity interval.

* On |DPs|, configure the :property:`certificate_status_advance_update_duration`
  property. The value must be large enough so that, in the event of an
  |OCSPResp| outage, there is time for retries. If validating the local
  |OCSPToken| fails (either because the |OCSPResp| doesn't respond or because
  the response is invalid), then the |DP| will keep retrying with a fixed
  frequency: five times for each
  :property:`certificate_status_advance_update_duration` period (limited to a
  maximum of one retry every 10 seconds).

It is important to consider how the :value:`nextUpdate` and
:property:`certificate_status_advance_update_duration` values interact. An
|OCSPResp| outage can still affect a system with a large |OCSPToken| validity
interval, if |DPs| have configured a short value for the
:property:`certificate_status_advance_update_duration` property. On the other
hand, a larger :property:`certificate_status_advance_update_duration` value will
increase network overhead and CPU usage. The |SP_BUILTIN| also limit the number
of updates to one every 10 seconds, in case you configure the values of
:value:`nextUpdate` and :property:`certificate_status_advance_update_duration`
so that they are too close to each other.

.. note::

  On startup (and restart), the number of retries is bounded and happens in
  fixed intervals. The amount of retries and the time between them is currently
  not configurable: up to 10 attempts, with a 5-second sleep between each one.
  If all attempts fail, the |DP| creation will fail. Make an extra effort to
  reduce the |OCSPResp| outage probability and minimize downtime. If you cannot
  do this, implement fallback mechanisms in your application—for example, try
  again or provide an alternative |IdentityCert| that does not contain an
  :value:`authorityInfoAccess` field with an |OCSPResp| URL (your
  |GovernanceDoc| must not require |OCSP| for this approach to work).

OCSP Token Validity Interval
----------------------------

An |OCSPToken| is valid for a limited time, which depends on the |OCSPResp|
configuration. The |OCSPToken| Validity Interval is defined as the time between
the query and the |OCSPToken|'s expiration time, i.e. :value:`thisUpdate` and
:value:`nextUpdate` fields' values in the |OCSPToken|. A certificate is deemed
valid and not revoked during this interval, even if the certificate is revoked
on the |OCSPResp| in the meantime. Because of this, it is desirable to keep this
interval short to ensure that a revoked |DP| is promptly removed from the system.
However, a short validity interval creates its own challenges:

* Increased network overhead caused by more frequent |OCSPToken| renewal
  requests and token propagation between |DPs| (each |DP| propagates its update
  to all its peers in the same domain). The stress on the network grows with the
  number of |DPs| and shorter intervals, and in some resource-challenged systems
  |OCSP| may have a noticeable impact, especially if a larger number of |DPs|
  are created at the same time.

* Limited margin of error for |OCSPResp| outages or for a slower network—see
  :ref:`p3_advanced/design_considerations:Responder Availability` for details
  about this.

The |OCSP| standard does not impose any minimum size on the |OCSPToken| Validity Interval,
except a high-level guidance, i.e. :value:`thisUpdate` < :value:`currentLocalTime` < :value:`nextUpdate`,
which implies that the interval must take into account some variability that may be
reflected in latency. |RTI| sets :property:`certificate_status_advance_update_duration`
(the time of the first query for |OCSPToken| renewal) to 60 seconds by default. We expect
this time should be enough for a slow query to complete and should leave some margin
for retries, if neccessary. We expect this is a reasonable time in a well-working system
and network that ensures a high degree of availability. The minimal value for this property
is 20 seconds, which would leave very little time for possible retries. Given all of the
above, we expect that, for most cases, a Validity Interval length in the order of hours
provides a reasonable balance in a well-working system, with excellent |OCSP| availability
and little dynamics when it comes to certificates and trust towards |DPs|. Naturally,
this highly depends on your use case and you should do your own analysis first before
deciding on a specific value.

Time Synchronization Requirements with OCSP
-------------------------------------------

An |OCSPToken| includes two time values: :value:`thisUpdate` and
:value:`nextUpdate`. The |RTI_SP_PRODUCT| interpret :value:`thisUpdate` as the
time when the |OCSPToken| becomes valid. The identity of the associated |DP| is
not valid before this date. There is also the :value:`nextUpdate` time, which
the |RTI_SP_PRODUCT| interpret as the expiration time of the |OCSPToken|. The
identity of the associated |DP| is not valid after this date. The pair of values
creates an |OCSPToken| validity period during which the corresponding
|IdentityCert| is considered valid: :value:`[thisUpdate, nextUpdate]`.

Note that these times are set by the
|OCSPResp| according to its internal clock, and are interpreted by |DPs| according
to their internal clocks. Naturally, this creates a requirement on some level of time
synchronization among these devices. Desynchronized clocks may lead to rejecting
a valid |OCSPToken| because, according to one device's internal clock, the token is not yet
valid or is already expired.

It is your responsibility to ensure that all devices in the system have their
clocks fairly synchronized. To relax a requirement for a sub-second time
synchronization, which can be difficult to achieve in some applications, we
introduced a tolerance of 10 seconds, which should eliminate most obvious time
synchronization issues. This 10-second value is currently not configurable.
This means the actual |OCSPToken| validity period is extended by 10s into the
past and into the future, that is: :value:`[thisUpdate - 10s, nextUpdate + 10s]`.

For more information about time requirements in |RTI_SP_PRODUCT| see
:ref:`p3_advanced/design_considerations:Time Requirements for |RTI_SP_PRODUCT|`.

GUID consistency enforcement
============================

|OrigAuthProtection| allows the Receiver to make sure that the Sender is
who it claims to be **according to the SampleInfo::publication_handle.**
In the C API, you can translate the ``SampleInfo::publication_handle`` to a
GUID using
:link_connext_dds_api_c:`DDS_BuiltinTopicKey_from_instance_handle<group__DDSBuiltInTopicCommonModule.html#ga0740298d4c1a703c529f4464ec62e3f1l>`
followed by
:link_connext_dds_api_c:`DDS_BuiltinTopicKey_to_guid<group__DDSBuiltInTopicCommonModule.html#gac292dd5549e602dc5e3ed6a5655ea9ae>`.
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 relies on this field to identify the Sender's origin, then
|OrigAuthProtection| alone is insufficient to prevent impersonation. In such
cases, |OrigAuthProtection| must be combined with appropriate access control
policies (specifically, by not granting proxy permissions to the Sender). This
additional layer of protection is enforced through the |GovernanceDoc| and
|PermissionsDoc|. For more information, see
:ref:`p2_core/access_control:DataWriters Acting as a Proxy for other DataWriters`.

Recommendations When Enabling ROS 2 Interoperability
====================================================

The :property:`dds.ros.enable_interoperability` property exists to allow |CONNEXT| applications to
communicate with ROS 2 applications. For more information on this feature, see the
`Connext + ROS 2 Community Page <https://community.rti.com/ros>`__.

This property can be set within the |DP|, the |DW|, or the |DR|:

* If the :property:`dds.ros.enable_interoperability` property is set to :xmlval:`true` within the |DP|,
  and the |GovernanceDoc|/|PermissionsDoc| only contains the aliased |TOPIC| name ("rt/<topic-name>"), the protection information 
  provided for the aliased |TOPIC| will still be applied to the |TOPIC|.
* If the :property:`dds.ros.enable_interoperability` property is set to :xmlval:`true` in either the |DR|
  or the |DW|, and the |GovernanceDoc|/|PermissionsDoc| only contains the aliased |TOPIC| name ("rt/<topic-name>"), the
  protection and permissions information provided for the aliased |TOPIC| will not be applied to
  the |TOPIC|, which could result in unexpected system behavior. This includes, but is not
  limited to, entity creation errors, lack of communication, and incorrect security policy
  enforcement.

When enabling interoperability with ROS 2 applications, we recommend:

* Setting the :property:`dds.ros.enable_interoperability` property in the |DP|
  (as opposed to the |DR| or |DW|).
* Explicitly listing both the original |TOPIC| names and aliased |TOPIC| names in
  the |GovernanceDoc|/|PermissionsDoc|.
