.. _section-psk: Lightweight Security Plugin =========================== The *Lightweight Security Plugin* is an addon for |me| that offers an efficient solution for securing RTPS communication at the domain level. This plugin protects your domain from unauthorized participants and ensures the integrity and confidentiality of RTPS messages. Overview -------- The *Lightweight Security Plugin* uses symmetric encryption, deriving keys from a combination of publicly-available data and a user-provided pre-shared key (PSK) seed. Pre-shared key protection offers metadata and data protection to RTPS messages and restricts communication only to *DomainParticipants* holding the correct PSK. This architecture offers a streamlined path to deploy security without the overhead of full public key infrastructure. The *Lightweight Security Plugin* consists of a Platform Independent Library (PIL) and a Transform Platform Support Library (PSL). The Transform PSL is an abstraction layer that allows seamless integration with a cryptographic backend. The plugin includes a reference implementation that integrates with `OpenSSL 3.5 `__ [#]_. This modular design makes the *Lightweight Security Plugin* an ideal choice for applications that demand robust protection without compromising on portability or efficiency. .. [#] You can substitute in your own Transform PSL to meet performance, certification, or compliance requirements. For details, please contact RTI through `support.rti.com `__. Downloading and Installing the Lightweight Security Plugin ---------------------------------------------------------- Once you have purchased the *Lightweight Security Plugin*, you can download the following package files from `support.rti.com `__: * ``rti_connext_dds_micro--lw-security-host.rtipkg`` * ``rti_connext_dds_micro--lw-security-target-openssl-3.5-.rtipkg`` * ``openssl-3.5-micro--target-.rtipkg`` (*Optional*) Download the host package with ```` |version|, and a target package with ```` |version| and ```` matching your CPU and compiler. To install the *Lightweight Security Plugins* packages, follow the same instructions for installing |me| packages in :ref:`section-installing-connext-micro`. Package contents ................ The host package contains the necessary header files for lightweight security development. The target package provides the Platform Independent Library (PIL) and Transform Platform Support Library (PSL) specific to your target architecture. The Transform PSL is dependent on OpenSSL; RTI builds and tests the PSL against `OpenSSL 3.5 `__. The OpenSSL target package simply contains the OpenSSL 3.5 release. RTI provides this for convenience, but you may use any OpenSSL distribution ABI compatible with 3.5.0. The OpenSSL source can be found at https://openssl-library.org/source/. Getting Started --------------- This section will walk you through the steps needed to enable the *Lightweight Security Plugin* in your application and and run it in your domain. We will use the provided reference implementation of the Transform PSL with `OpenSSL 3.5 `_. .. note:: You can also generate an example application with *rtiddsgen* that uses lightweight security. Refer to :ref:`example_generation` for more information. Link application and libraries .............................. To link an application with the lightweight security feature, the following libraries are required in the listed order: * ``RTIMEHOME/lib//`` 1. ``rti_me_ddspsk`` (must be linked before ``rti_me``) * ``RTIMEHOME/lib/-/`` 2. ``rti_me_pskpsl`` (must be linked before ``rti_me``) * ``RTIMEHOME/thirdparty/openssl-3.5.0-/-/lib`` 3. ``libcrypto`` Enable lightweight security in your application ............................................... To use lightweight security, you must first register the *Lightweight Security Plugin* library with |me| via the :link_connextmicro_dds_api_c_up_one:`DDS_PskLibrary_register() ` function, as shown below: .. code-block:: c { struct DDS_PskServiceFactoryProperty psk_svc_property = DDS_PskServiceFactoryProperty_INITIALIZER; psk_svc_property.psl_get_interface_func = PSK_OSSL_get_interface; if(!DDS_PskLibrary_register( registry, &psk_svc_property)) { printf("Lightweight Security Plugin registration error\n"); } } .. note:: When using the C++ API, register the *Lightweight Security Plugin* using the same method as the C API, shown above. This function takes a property structure with the following fields: * :link_connextmicro_dds_api_c_up_one:`service_name `: a unique identifier for this registration within the *DomainParticipantFactory*. The *DomainParticipant* QoS references this name to select which library registration to use. If set to NULL, the default name ``DDS_PSK_DEFAULT_SUITE_NAME`` will be used. * :link_connextmicro_dds_api_c_up_one:`psl_get_interface_func `: a function pointer used to retrieve the Transform PSL interface. When using the reference Transform PSL provided by RTI, set this to ``PSK_OSSL_get_interface`` [#]_. * :link_connextmicro_dds_api_c_up_one:`psl_config `: An opaque pointer passed to the Transform PSL creation function. When using the RTI-provided Transform PSL, this field resolves to :link_connextmicro_dds_api_c_up_one:`DDS_SecTransform_Configuration `. Its type is ``struct DDS_SecTransform_Configuration *``, as shown in the example below: .. code-block:: c struct DDS_SecTransform_Configuration config = *PSK_OSSL_get_default_configuration(); .. [#] This function is provided by ``rti_me_psl/pskpsl/psk_ossl_transform.h``. Specify the plugin in the DomainParticipant QoS ............................................... Assign the :link_connextmicro_dds_api_c_up_one:`service_name ` that you specified during registration to the ``DomainParticipantQos.trust.suite`` field with the following function: .. code-block:: c RT_ComponentFactoryId_set_name(&dp_qos.trust.suite, DDS_PSK_DEFAULT_SUITE_NAME) This function tells the *DomainParticipant* to enable the *Lightweight Security Plugin* and identifies which registered instance to use. Configure the plugin .................... The *Lightweight Security Plugin* accepts the following properties (in the :link_connextmicro_dds_api_c_up_one:`PROPERTY QoS `): * ``dds.sec.crypto.rtps_psk_secret_passphrase`` (*Required*) * ``dds.sec.access.rtps_psk_protection_kind`` (*Optional*) * ``dds.sec.crypto.rtps_psk_symmetric_cipher_algorithm`` (*Optional*) * ``com.rti.serv.secure.cryptography.max_blocks_per_session`` (*Optional*) For more information about these properties, refer to :ref:`section-configuring-psk`. For now, set these properties as shown in the example snippet below: .. code-block:: c { struct DDS_DomainParticipantQos dp_qos = DDS_DomainParticipantQos_INITIALIZER; /* Required property*/ DDS_PropertyQosPolicyHelper_add_property( &dp_qos.property, "dds.sec.crypto.rtps_psk_secret_passphrase", "data:,404166165:castle super radar denial swing lunar kind swarm wet toilet output harbor basic begin margin huge year visit", DDS_BOOLEAN_FALSE); /* Optional Properties */ DDS_PropertyQosPolicyHelper_add_property( &dp_qos.property, "dds.sec.access.rtps_psk_protection_kind", "ENCRYPT", DDS_BOOLEAN_FALSE); DDS_PropertyQosPolicyHelper_add_property( &dp_qos.property, "dds.sec.crypto.rtps_psk_symmetric_cipher_algorithm", "AUTO", DDS_BOOLEAN_FALSE); DDS_PropertyQosPolicyHelper_add_property( &dp_qos.property, "com.rti.serv.secure.cryptography.max_blocks_per_session", "256", DDS_BOOLEAN_FALSE); } Create a protected DomainParticipant .................................... Invoke the function :link_connextmicro_dds_api_c_up_one:`DDS_DomainParticipantFactory_create_participant ` with the QoS ``dp_qos``. At this point, your application is protected by the *Lightweight Security Plugin* and ready to run! .. _section-configuring-psk: Configuring the Lightweight Security Plugin ------------------------------------------- The following table lists the properties used to configure the *Lightweight Security Plugin* and detailed descriptions of their use. Refer to the OMD `DDS Security Specification 1.1 `_ for additional information. All of the properties below have string values. .. list-table:: :widths: 30 70 :header-rows: 1 - * Property Name * Property Description - * ``dds.sec.crypto.rtps_psk_secret_passphrase`` * Passphrase used to derive the per-participant key used for encoding RTPS messages (in combination with other publicly available data). This property is mutable through the *DomainParticipant* ``set_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 with PSK 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 PSK protected traffic will be encoded and decoded with consistent keys. At that point, warning messages will stop. Updating the value of this property implies a change in the secret key AND 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 should not be reused; you may set a new secret key with an old key identifier, but doing so is not advised. In that case, *Lightweight Security Plugin* may end up using the old pre-shared key to try (unsuccessfully) to decode an RTPS message that was encoded using the new key. The passphrase must follow the format ``data:,:``. ```` is a 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.). ```` 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. RTI recommends using 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. ```` is the secret passphrase string that the *Lightweight Security Plugin* will use to derive the per-participant pre-shared key. ```` must contain up to 512 ASCII printable characters (character codes 32 to 126, both included). The first and last characters of the ```` shall not be the space character (character code 32). **Default**: not set .. attention:: It is your responsibility to provide a key seed with good entropy and length. Ideally, the pre-shared key seed 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_symmetric_cipher_algorithm`` * *Optional*. Algorithm used to protect RTPS messages with pre-shared key (PSK) protection. The available options are ``AES256+GCM`` and ``AES128+GCM``. The number indicates the number of bits in the key in either the GMAC or GCM variant of the algorithm. This property only sets the algorithm and key length; see the note below for more information about setting the algorithm's variant. **Enum**: ``AUTO`` (equivalent to ``AES256+GCM``), ``AES128+GCM``, ``AES256+GCM`` **Default**: ``AUTO`` .. note:: This property must be configured consistently throughout your system. All *DomainParticipants* must have the same value in order to communicate. - * ``dds.sec.access.rtps_psk_protection_kind`` * *Optional*. Specifies whether the *Lightweight Security Plugin* should only protect message integrity OR both integrity and confidentiality. **Enum**: ``NONE`` (do not protect), ``SIGN`` (protect integrity), ``ENCRYPT`` (protect integrity and confidentiality). **Default**: ``ENCRYPT`` - * ``com.rti.serv.secure.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 format. This value is an unsigned 64-bit integer. **Unsigned Integer**: ``[1, MAX_UINT64]`` **Default**: ``MAX_UINT64`` Technical Considerations ------------------------ Consider the following when using the *Lightweight Security Plugin*: RTPS transport only ................... The *Lightweight Security Plugin* only protects transports that use the RTPS protocol. That means that INTRA and Zero Copy V2 transports cannot be protected with the *Lightweight Security Plugin*. Maximum Transmission Unit (MTU) ............................... RTI limits the maximum size of a single packet to 65535 bytes. If using a transport that can support an MTU greater than this, the size will be truncated to 65535 bytes. .. note:: Types that exceed this limit can still be fragmented and sent by |me|. This only limits the size of individual packets. Interoperability ---------------- The *Lightweight Security Plugin* interoperates with the |core_pro| *Lightweight Builtin Security Plugins* security solution out of the box, with some considerations explained in the following sections. The *Lightweight Security Plugin* is also compatible with |core_pro|'s *Builtin Security Plugins* when the *Builtin Security Plugins* are configured for compatibility; refer to `Lightweight Builtin Security Plugins and Builtin Security Plugins Interoperability `_ for more information. Additional Authenticated Data (AAD) ................................... The *Lightweight Security Plugin* always uses AAD, which adds a header extension to RTPS messages. |core_pro| allows you to disable this. For successful interoperability between |me| and |core_pro|, you must configure |core_pro| to always enable AAD by setting the :link_external_community_doc_security_plugins_um:`cryptography.enable_additional_authenticated_data ` property to ``TRUE``. Passphrase ID limitations ......................... |me| supports a ``passphrase_id`` (which is part of the passphrase) up to ``MAX_UINT64``. However, |core| 7.3.0 and above only supports a ``passphrase_id`` up to 254. To ensure interoperability between |me| and |core_pro|, choose a ``passphrase_id`` within the range of 0 to 254.