.. include:: vars.rst


.. _section-sec-HO4:

Hands-On 4: Generating and Revoking Your Own Certificates Using OpenSSL
=======================================================================

In this Hands-On, you will take control of your project's keys and
certificates. This way, you will not need to rely on the example artifacts
provided with |CONNEXT| to secure your applications. We will start by
generating a self-signed Identity CA, which will issue the |IdentityCerts|
for Alice and Bob. This will require us to set up a minimal
security infrastructure first. Then we will generate a new Permissions CA
that will sign the |GovernanceDoc| and all the |PermissionsDocs|. After
each certificate generation, we will refer to the modifications needed to
make your project load the new artifacts. Finally, we will revoke one
|IdentityCert| and use a Certificate Revocation List (CRL) to avoid
communicating with the revoked |DP|.

We will show examples for ECDSA and RSA as the public-key algorithm to
generate the certificates. Note that you can use any public-key algorithm listed
in :link_connext_dds_secure_um:`Supported Cryptographic Algorithms
<p1_welcome/overview.html#section-supported-cryptographic-algorithms>`
in the |SP_UM|.

.. note::

   We will use the **OpenSSL CLI** to perform the security operations in the
   generation of the security artifacts. Make sure to include in the path your
   OpenSSL binary directory [#openssl_lm_path]_. The installation process is
   described in the |SP_IG_LINK|.

   Note that the |RTI_SP_PRODUCT| do not depend on OpenSSL to generate these artifacts; you
   can use the security toolkit of your choice. With that said, we recommend
   using |OpenSSL| to make sure that the certificates are in the right format.

.. _section-sec-HO4-preliminary-steps:

Preliminary Steps
-----------------

Setting up a security infrastructure requires some preliminary configuration.
We will cover a minimal setup here.

#. If you followed the steps in :ref:`section-sec-HO1`, you should have an
   OpenSSL configuration file named :file:`cert/ecdsa01/ca/ecdsa01RootCa.cnf` [#]_.
   Make two copies of this file and call them :file:`pmiIdentityCa.cnf` and
   :file:`pmiPermissionsCa.cnf`. To better organize your project, save these
   copies in a new directory called :file:`cert/pmi/ca`:

   .. tabs::

    .. group-tab:: Linux

      .. code-block:: console

        $ cp cert/ecdsa01/ca/ecdsa01RootCa.cnf cert/pmi/ca/pmiIdentityCa.cnf
        $ cp cert/ecdsa01/ca/ecdsa01RootCa.cnf cert/pmi/ca/pmiPermissionsCa.cnf

    .. group-tab:: macOS

      .. code-block:: console

        $ cp cert/ecdsa01/ca/ecdsa01RootCa.cnf cert/pmi/ca/pmiIdentityCa.cnf
        $ cp cert/ecdsa01/ca/ecdsa01RootCa.cnf cert/pmi/ca/pmiPermissionsCa.cnf

    .. group-tab:: Windows

      .. code-block:: doscon

        > copy cert\ecdsa01\ca\ecdsa01RootCa.cnf cert\pmi\ca\pmiIdentityCa.cnf
                1 file(s) copied.
        > copy cert\ecdsa01\ca\ecdsa01RootCa.cnf cert\pmi\ca\pmiPermissionsCa.cnf
                1 file(s) copied.

   .. hint::

     If you want to use RSA as your public-key algorithm, you may want to copy
     the homologous example files from the :file:`cert/rsa01/` directory.

#. Modify :file:`pmiIdentityCa.cnf` to redefine the ``name`` variable. Note that
   this configuration file uses this variable to derive some filenames, such as
   those used in the next section:

   .. code-block:: openssl

      ...
      # Variables defining this CA
      name = pmiIdentityCa                      # Name
      desc =                                    # Description
      ...

.. [#] Read the official `documentation
   <https://www.openssl.org/docs/manmaster/man5/config.html>`_ for more
   information on the OpenSSL configuration files.

.. _section-sec-HO4-initialize-openssl-ca-database:

Initialize the OpenSSL CA Database
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

When using a CA to perform an operation, OpenSSL relies on special database
files to keep track of the issued certificates, serial numbers, revoked
certificates, etc. We need to create these database files to be able to use
the :command:`openssl x509 -req` command:

.. tabs::

   .. group-tab:: Linux

      .. code-block:: console

         $ mkdir cert/pmi/ca/database
         $ touch cert/pmi/ca/database/pmiIdentityCaIndex
         $ echo 01 > cert/pmi/ca/database/pmiIdentityCaSerial

   .. group-tab:: macOS

      .. code-block:: console

         $ mkdir cert/pmi/ca/database
         $ touch cert/pmi/ca/database/pmiIdentityCaIndex
         $ echo 01 > cert/pmi/ca/database/pmiIdentityCaSerial

   .. group-tab:: Windows

      .. code-block:: doscon

         > mkdir cert\pmi\ca\database
         > type nul > cert\pmi\ca\database\pmiIdentityCaIndex
         > echo 01> cert\pmi\ca\database\pmiIdentityCaSerial

Limit the Access of the CA's Private Key
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

It is also a good practice to store the CA's private key in a separate
directory with more restrictive access rights, so only you can sign certificates.

.. tabs::

   .. group-tab:: Linux

      .. code-block:: console

         $ mkdir cert/pmi/ca/private
         $ chmod 700 cert/pmi/ca/private

   .. group-tab:: macOS

      .. code-block:: console

         $ mkdir cert/pmi/ca/private
         $ chmod 700 cert/pmi/ca/private

   .. group-tab:: Windows

      .. code-block:: doscon

         > mkdir cert\pmi\ca\private

         > icacls cert\pmi\ca\private /t /inheritance:d
         processed file: cert\pmi\ca\private
         Successfully processed 1 files; Failed processing 0 files

         > icacls cert\pmi\ca\private /t /remove Administrator "Authenticated Users" BUILTIN Everyone System Users
         processed file: cert\pmi\ca\private
         Successfully processed 1 files; Failed processing 0 files

         > icacls cert\pmi\ca\private /grant %USERNAME%:F
         processed file: cert\pmi\ca\private
         Successfully processed 1 files; Failed processing 0 files


.. _section-sec-HO4-generating-new-identity-ca:

Generating a New Identity CA
----------------------------

#. Modify :file:`cert/pmi/ca/pmiIdentityCa.cnf` and specify the fields in the
   ``req_distinguished_name`` section. This information will be incorporated
   into your certificate:

   .. code-block:: openssl

      ...
      [ req_distinguished_name ]

      countryName          = US
      stateOrProvinceName  = CA
      localityName         = Santa Clara
      0.organizationName   = Patient Monitoring Innovations
      commonName           = PMI Identity CA
      emailAddress         = identityca@pmi.com
      ...

#. Use the OpenSSL CLI to generate a self-signed certificate using
   the Identity CA's configuration. Run the following command from the
   :file:`cert/pmi` directory:

   .. tabs::

      .. group-tab:: ECDSA secp256r1

         .. code-block:: text

            openssl req -nodes -x509 -days 1825 -text -sha256 -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 -keyout ca/private/pmiIdentityCaKey.pem -out ca/pmiIdentityCaCert.pem -config ca/pmiIdentityCa.cnf

      .. group-tab:: ECDSA secp384r1

         .. code-block:: text

            openssl req -nodes -x509 -days 1825 -text -sha384 -newkey ec -pkeyopt ec_paramgen_curve:secp384r1 -keyout ca/private/pmiIdentityCaKey.pem -out ca/pmiIdentityCaCert.pem -config ca/pmiIdentityCa.cnf

      .. group-tab:: RSA

         .. code-block:: text

            openssl req -nodes -x509 -days 1825 -text -sha256 -newkey rsa:2048 -keyout ca/private/pmiIdentityCaKey.pem -out ca/pmiIdentityCaCert.pem -config ca/pmiIdentityCa.cnf

   This will produce a new private key, ``pmiIdentityCaKey.pem`` in the
   ``cert/pmi/ca/private`` directory, and a new certificate,
   ``pmiIdentityCaCert.pem``, in the ``cert/pmi/ca`` directory. This
   certificate will be valid for 1825 days (5 years) starting today.


.. _section-sec-HO4-specifying-new-identity-ca-cert-qos-profiles:

Specifying the New Identity CA Certificate in QoS Profiles
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Modify :file:`USER_QOS_PROFILES.xml` to make your |DPs| load the
certificate of the new Identity CA:

.. code-block:: xml

    ...
    <element>
        <name>dds.sec.auth.identity_ca</name>
        <value>file:./cert/pmi/ca/pmiIdentityCaCert.pem</value>
    </element>
    ...

.. _section-sec-HO4-generating-identity-certificates:

Generating Identity Certificates
--------------------------------

As explained in :ref:`section-sec-intro`, |IdentityCerts| are
verified against the Identity CA when authenticating remote
|DPs|. Therefore, in the simplest scenario, it is the
Identity CA that is responsible for issuing |IdentityCerts|. [#]_
We will create a certificate signing request (CSR) for Alice. Then we will
use the new Identity CA to issue the certificate requested by the CSR.

#. Add the information you want to include in Alice's certificate in a file
   called :file:`pmiAlice.cnf`. Save this file in a new directory called
   :file:`cert/pmi/identities`. You may want to use the following contents as a
   reference:

   .. code-block:: openssl
      :caption: Sample contents of pmiAlice.cnf

      prompt              = no
      distinguished_name  = req_distinguished_name

      [ req_distinguished_name ]
      countryName          = US
      stateOrProvinceName  = CA
      localityName         = Santa Clara
      organizationName     = Patient Monitoring Innovations
      emailAddress         = alice@pmi.com
      commonName           = Alice

   You are free to modify any field except ``countryName``,
   ``stateOrProvinceName``, and ``organizationName``. These fields must match
   the ones of the Identity CA; otherwise it will refuse to issue the requested
   certificate (note that a ``commonName`` is also required). These requirements
   are specified in :file:`pmiIdentityCa.cnf`, in the ``policy_match`` section.
   |br| |br|

#. Generate Alice's key and CSR. Run the following command from the
   :file:`cert/pmi` directory:

   .. tabs::

      .. group-tab:: ECDSA secp256r1

         .. code-block:: text

            openssl req -nodes -new -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 -config identities/pmiAlice.cnf -keyout identities/pmiAliceKey.pem -out identities/pmiAlice.csr

      .. group-tab:: ECDSA secp384r1

         .. code-block:: text

            openssl req -nodes -new -newkey ec -pkeyopt ec_paramgen_curve:secp384r1 -config identities/pmiAlice.cnf -keyout identities/pmiAliceKey.pem -out identities/pmiAlice.csr

      .. group-tab:: RSA

         .. code-block:: text

            openssl req -nodes -new -newkey rsa:2048 -config identities/pmiAlice.cnf -keyout identities/pmiAliceKey.pem -out identities/pmiAlice.csr

   This will produce an RSA private key, :file:`pmiAliceKey.pem`, and a CSR
   based on that key, :file:`pmiAlice.csr`. Since CSRs have all the information
   and cryptographic material that a CA needs to issue a certificate, Alice's
   private key must never be known to anyone but her. |br| |br|

#. Use the new Identity CA's certificate and private key to issue Alice's
   |IdentityCert|. Run the following command from the :file:`cert/pmi`
   directory:

   .. tabs::

      .. group-tab:: ECDSA secp256r1

         .. code-block:: text

            openssl x509 -req -days 730 -text -CAserial ca/database/pmiIdentityCaSerial -CA ca/pmiIdentityCaCert.pem -CAkey ca/private/pmiIdentityCaKey.pem -in identities/pmiAlice.csr -out identities/pmiAliceCert.pem

      .. group-tab:: ECDSA secp384r1

         .. code-block:: text

            openssl x509 -req -days 730 -sha384 -text -CAserial ca/database/pmiIdentityCaSerial -CA ca/pmiIdentityCaCert.pem -CAkey ca/private/pmiIdentityCaKey.pem -in identities/pmiAlice.csr -out identities/pmiAliceCert.pem

      .. group-tab:: RSA

         .. code-block:: text

            openssl x509 -req -days 730 -text -CAserial ca/database/pmiIdentityCaSerial -CA ca/pmiIdentityCaCert.pem -CAkey ca/private/pmiIdentityCaKey.pem -in identities/pmiAlice.csr -out identities/pmiAliceCert.pem

   The Identity CA will issue Alice's public
   certificate, :file:`pmiAliceCert.pem`, which will be valid for 730 days (2
   years) starting today.

.. [#] Depending on your use case, the |IdentityCerts| may be
   issued by an intermediate CA in your PKI instead. For further information,
   see :link_connext_dds_secure_um:`Public Key Infrastructure (PKI)
   <p2_core/elements_dds_secure_system.html#public-key-infrastructure-pki>`
   in the |SP_UM|.

.. _section-sec-HO4-specifying-new-identity-certificates-your-qos-profiles:

Specifying the New Identity Certificates to Your QoS Profiles
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Modify :file:`USER_QOS_PROFILES.xml` to make your publisher application load the
new pair of certificate and private key:

.. code-block:: xml

        ...
        <!-- Participant Public Certificate and Private Key -->
        <element>
            <name>dds.sec.auth.identity_certificate</name>
            <value>file:./cert/pmi/identities/pmiAliceCert.pem</value>
        </element>
        <element>
            <name>dds.sec.auth.private_key</name>
            <value>file:./cert/pmi/identities/pmiAliceKey.pem</value>
        </element>
        ...


.. _section-sec-HO4-updating-permissions-files-new-credentials:

Updating Permissions Documents with New Credentials
---------------------------------------------------

As explained in :ref:`section-sec-HO3-binding-permissions-file`, grants in a
|PermissionsDoc| are bound to |DP| identities. We will update
Alice's |PermissionsDoc| with the same information we included in Alice's
|IdentityCert|.

#. To meet the format requirements of the |PermissionsDoc|, you may want to
   check your certificate's information with the following command:

   .. tabs::

      .. group-tab:: Linux

         .. code-block:: console
            :emphasize-lines: 11

            $ openssl x509 -in cert/pmi/identities/pmiAliceCert.pem -text -noout
            Certificate:
                Data:
                    Version: 1 (0x0)
                    Serial Number: 1 (0x1)
                Signature Algorithm: ecdsa-with-SHA256
                    Issuer: C=US, ST=CA, L=Santa Clara, O=Patient Monitoring Innovations, CN=PMI Identity CA, emailAddress=identityca@pmi.com
                    Validity
                        Not Before: Feb  7 15:37:09 2021 GMT
                        Not After : Feb  7 15:37:09 2023 GMT
                    Subject: C=US, ST=CA, O=Patient Monitoring Innovations, CN=Alice, emailAddress=alice@pmi.com
                    Subject Public Key Info:
                    ...

      .. group-tab:: macOS 

         .. code-block:: console 
            :emphasize-lines: 11

            $ openssl x509 -in cert/pmi/identities/pmiAliceCert.pem -text -noout
            Certificate:
                Data:
                    Version: 1 (0x0)
                    Serial Number: 1 (0x1)
                Signature Algorithm: ecdsa-with-SHA256
                    Issuer: C=US, ST=CA, L=Santa Clara, O=Patient Monitoring Innovations, CN=PMI Identity CA, emailAddress=identityca@pmi.com
                    Validity
                        Not Before: Feb  7 15:37:09 2021 GMT
                        Not After : Feb  7 15:37:09 2023 GMT
                    Subject: C=US, ST=CA, O=Patient Monitoring Innovations, CN=Alice, emailAddress=alice@pmi.com
                    Subject Public Key Info:
                    ...

      .. group-tab:: Windows

         .. code-block:: doscon
            :emphasize-lines: 11

            > openssl x509 -in cert\pmi\identities\pmiAliceCert.pem -text -noout
            Certificate:
                Data:
                    Version: 1 (0x0)
                    Serial Number: 1 (0x1)
                Signature Algorithm: ecdsa-with-SHA256
                    Issuer: C=US, ST=CA, L=Santa Clara, O=Patient Monitoring Innovations, CN=PMI Identity CA, emailAddress=identityca@pmi.com
                    Validity
                        Not Before: Feb  7 15:37:09 2021 GMT
                        Not After : Feb  7 15:37:09 2023 GMT
                    Subject: C=US, ST=CA, O=Patient Monitoring Innovations, CN=Alice, emailAddress=alice@pmi.com
                    Subject Public Key Info:
                    ...

#. Modify the :xmltag:`subject_name` in the |PermissionsDoc|,
   :file:`xml/pmiPermissionsAlice.xml`, to match the certificate's subject.
   |br| |br|

#. You may also want to update the :xmltag:`validity` tag with the information
   from the |IdentityCert|. Note that you are not required to have the
   same validity dates in the |PermissionsDoc| and the |IdentityCert|
   (upon creation, your |DP| will independently verify that the
   |IdentityCert| and the grant in your |PermissionsDoc| are valid for the
   current date). If you decide to update the :xmltag:`validity` tag, pay
   attention to the date/time format.

   .. code-block:: xml

       ...
       <!-- Grants for a specific DomainParticipant will be grouped under this tag -->
       <grant name="ParticipantAlice">
           <!-- 1. The rules below will apply to the DomainParticipant 
                   whose identity certificate contains this subject name -->
           <subject_name>C=US, ST=CA, O=Patient Monitoring Innovations, CN=Alice, emailAddress=alice@pmi.com</subject_name>
           <!-- 2. Validity dates for this grant -->
           <validity>
               <!-- Format is CCYY-MM-DDThh:mm:ss[Z|(+|-)hh:mm] in GMT -->
               <not_before>2019-11-25T16:17:07</not_before>
               <not_after>2021-11-24T16:17:07</not_after>
           </validity>
           ...

.. _section-sec-HO4-generating-new-permissions-ca:

Generating a New Permissions CA
-------------------------------

.. note::

   * The Identity CA and Permissions CA may be the same, depending on
     your use case.
   * This section is analogous to :ref:`section-sec-HO4-generating-new-identity-ca`.

#. Modify :file:`cert/pmi/ca/pmiPermissionsCa.cnf` and specify the fields under
   the :file:`req_distinguished_name` section.

   This information will be incorporated into your certificate:

   .. code-block:: openssl

      ...
      [ req_distinguished_name ]

      countryName          = US
      stateOrProvinceName  = CA
      localityName         = Santa Clara
      0.organizationName   = Patient Monitoring Innovations
      commonName           = PMI Permissions CA
      emailAddress         = permissionsca@pmi.com
      ...

#. Use the OpenSSL CLI to generate a self-signed certificate using
   the Permissions CA's configuration. Run the following command from the
   :file:`cert/pmi` directory:

   .. tabs::

      .. group-tab:: ECDSA secp256r1

         .. code-block:: text

            openssl req -nodes -x509 -days 1825 -text -sha256 -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 -keyout ca/private/pmiPermissionsCaKey.pem -out ca/pmiPermissionsCaCert.pem -config ca/pmiPermissionsCa.cnf

      .. group-tab:: ECDSA secp384r1

         .. code-block:: text

            openssl req -nodes -x509 -days 1825 -text -sha384 -newkey ec -pkeyopt ec_paramgen_curve:secp384r1 -keyout ca/private/pmiPermissionsCaKey.pem -out ca/pmiPermissionsCaCert.pem -config ca/pmiPermissionsCa.cnf

      .. group-tab:: RSA

         .. code-block:: text

            openssl req -nodes -x509 -days 1825 -text -sha256 -newkey rsa:2048 -keyout ca/private/pmiPermissionsCaKey.pem -out ca/pmiPermissionsCaCert.pem -config ca/pmiPermissionsCa.cnf

   This will produce a new private key, :file:`pmiPermissionsCaKey.pem` in
   the :file:`cert/pmi/ca/private` directory, and a new certificate,
   :file:`pmiPermissionsCaCert.pem`, in the :file:`cert/pmi/ca` directory. This
   certificate will be valid for 1825 days (5 years) starting today.

.. _section-sec-HO4-specifying-new-permissions-ca-certificates-qos-profiles:

Specifying the New Permissions CA Certificate in QoS Profiles
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Modify :file:`USER_QOS_PROFILES.xml` to make your |DPs| load the
certificate of the new Permissions CA:

.. code-block:: xml

    ...
        <element>
            <name>dds.sec.access.permissions_ca</name>
            <value>file:./cert/pmi/ca/pmiPermissionsCaCert.pem</value>
        </element>
        ...

.. _section-sec-HO4-signing-governance-permissions-files:

Signing the Governance and Permissions Documents
------------------------------------------------

.. note::

   This section was covered in :ref:`section-sec-HO2-signing-governance-file`
   and :ref:`section-sec-HO3-signing-permissions-files`.

We will use the Permissions CA's certificate and key that we generated to
sign the Governance and Permissions Documents that we composed in previous
Hands-On sections.

#. Run the command below to create the signed |GovernanceDoc| (with PKCS#7
   format) named :file:`xml/signed/pmiSigned_pmiGovernance.p7s`:

   .. code-block:: text

      openssl cms -sign -in xml/pmiGovernance.xml -text -out xml/signed/pmiSigned_pmiGovernance.p7s -signer cert/pmi/ca/pmiPermissionsCaCert.pem -inkey cert/pmi/ca/private/pmiPermissionsCaKey.pem

#. Run the command below to create the signed |PermissionsDoc|
   (with PKCS#7 format) named :file:`xml/signed/pmiSigned_pmiPermissionsAlice.p7s`:

   .. code-block:: text

      openssl cms -sign -in xml/pmiPermissionsAlice.xml -text -out xml/signed/pmiSigned_pmiPermissionsAlice.p7s -signer cert/pmi/ca/pmiPermissionsCaCert.pem -inkey cert/pmi/ca/private/pmiPermissionsCaKey.pem


.. _section-sec-HO4-specifying-new-governance-permissions-files-your-qos-profiles:

Specifying the New Governance and Permissions Documents in Your QoS Profiles
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Lastly, update :file:`USER_QOS_PROFILES.xml` so that your |DPs| will
load the Governance and Permissions Documents signed by your Permissions CA:

.. code-block:: xml

    ...
    <!-- Signed Governance and Permissions Documents -->
    <element>
        <name>dds.sec.access.governance</name>
        <value>file:./xml/signed/pmiSigned_pmiGovernance.p7s</value>
    </element>
    <element>
        <name>dds.sec.access.permissions</name>
        <value>file:./xml/signed/pmiSigned_pmiPermissionsAlice.p7s</value>
    </element>
    ...


.. _section-sec-HO4-updating-subscriber-configuration:

Updating the Subscriber's Configuration
---------------------------------------

At this point, you have control of the keys and certificates used in your
project. Congratulations!

In the previous steps, we have focused on updating
your publisher application, Alice, with a new identity and matching permissions.
Now, we will update Bob's identity and permissions accordingly.

#. Create an identity for your subscriber application, Bob, as described in
   :ref:`section-sec-HO4-generating-identity-certificates`. After this step,
   Bob's QoS profile in :file:`USER_QOS_PROFILES.xml` should load his new
   |IdentityCert|, :file:`pmiBob.pem`, and private key, :file:`pmiBobKey.pem`.

#. Update Bob's |PermissionsDoc|, :file:`pmiPermissionsBob.xml`, to match his
   new credentials (see
   :ref:`section-sec-HO4-updating-permissions-files-new-credentials`).

#. Finally, sign Bob's |PermissionsDoc| with your new Permissions CA, as
   explained in :ref:`section-sec-HO4-signing-governance-permissions-files`.
   After this step, Bob's QoS profile in :file:`USER_QOS_PROFILES.xml` should
   load the signed version of his new |PermissionsDoc|,
   :file:`pmiSigned_pmiPermissionsBob.p7s`.

Now, run your publisher and subscriber using |DOMAIN| *1* (specified with the
:command:`-d` option in the command line). You should see communication.

   .. only:: cpp98

      .. tabs::

         .. group-tab:: Linux

            Publisher:

            .. literalinclude:: snippets/snippets.py
               :language: console
               :start-after: snippet_console_publisher_cpp98_d1_ok
               :end-before: """

            Subscriber:

            .. literalinclude:: snippets/snippets.py
               :language: console
               :start-after: snippet_console_subscriber_cpp98_d1_ok
               :end-before: """

         .. group-tab:: macOS

            Publisher:

            .. literalinclude:: snippets/snippets.py
               :language: console
               :start-after: snippet_console_publisher_cpp98_d1_ok
               :end-before: """

            Subscriber:

            .. literalinclude:: snippets/snippets.py
               :language: console
               :start-after: snippet_console_subscriber_cpp98_d1_ok
               :end-before: """

         .. group-tab:: Windows

            Publisher:

            .. literalinclude:: snippets/snippets.py
               :language: doscon
               :start-after: snippet_doscon_publisher_cpp98_d1_ok
               :end-before: """

            Subscriber:

            .. literalinclude:: snippets/snippets.py
               :language: doscon
               :start-after: snippet_doscon_subscriber_cpp98_d1_ok
               :end-before: """

   .. only:: cpp11

      .. tabs::

         .. group-tab:: Linux

            Publisher:

            .. literalinclude:: snippets/snippets.py
               :language: console
               :start-after: snippet_console_publisher_cpp11_d1_ok
               :end-before: """

            Subscriber:

            .. literalinclude:: snippets/snippets.py
               :language: console
               :start-after: snippet_console_subscriber_cpp11_d1_ok
               :end-before: """

         .. group-tab:: macOS

            Publisher:

            .. literalinclude:: snippets/snippets.py
               :language: console
               :start-after: snippet_console_publisher_cpp11_d1_ok
               :end-before: """

            Subscriber:

            .. literalinclude:: snippets/snippets.py
               :language: console
               :start-after: snippet_console_subscriber_cpp11_d1_ok
               :end-before: """

         .. group-tab:: Windows

            Publisher:

            .. literalinclude:: snippets/snippets.py
               :language: doscon
               :start-after: snippet_doscon_publisher_cpp11_d1_ok
               :end-before: """

            Subscriber:

            .. literalinclude:: snippets/snippets.py
               :language: doscon
               :start-after: snippet_doscon_subscriber_cpp11_d1_ok
               :end-before: """

.. [#openssl_lm_path] In the :link_connext_dds_secure_ig:`free <#security_plugins/installation_guide/install_evaluation.html>`
   version (with ``lm`` in the bundle name), OpenSSL is installed automatically 
   when you install the |CONNEXT| host bundle. After installation, OpenSSL will 
   be in ``<installdir>/third_party/openssl-<version>``.


.. _section-sec-HO4-revoking-identity-certificate:

Revoking an Identity Certificate
--------------------------------

At this point, Alice and Bob are communicating using |IdentityCerts| that you
generated yourself. Congratulations!

Now, we will learn how to revoke Alice's |IdentityCert| and how Bob can react
to Alice's change in status.

#. To revoke Alice's |IdentityCert|, run the following command from the
   :file:`cert/pmi` directory:

   .. tabs::

      .. group-tab:: Linux

         .. code-block:: console

            $ openssl ca -config ca/pmiIdentityCa.cnf -batch -revoke identities/pmiAliceCert.pem

      .. group-tab:: macOS

         .. code-block:: console

            $ openssl ca -config ca/pmiIdentityCa.cnf -batch -revoke identities/pmiAliceCert.pem

      .. group-tab:: Windows

         .. code-block:: doscon

            > openssl ca -config ca\pmiIdentityCa.cnf -batch -revoke identities\pmiAliceCert.pem

   You may repeat this command to revoke more certificates issued by the same CA.

   If you would like to generate a valid CRL without revoking any certificates,
   you may skip this step and proceed directly to the next step.

#. When you are done revoking certificates, you have to inform the |DPs| about
   the revoked certificates by generating a list of the revoked identities,
   which is called a Certificate Revocation List (CRL). To generate the list,
   run the following commands from the :file:`cert/pmi` directory:

.. tabs::

   .. group-tab:: Linux

      .. code-block:: console

         $ echo 01 > ca/database/pmiIdentityCaCrlNumber
         $ openssl ca -config ca/pmiIdentityCa.cnf -batch -gencrl -out ca/pmi.crl

   .. group-tab:: macOS

      .. code-block:: console

         $ echo 01 > ca/database/pmiIdentityCaCrlNumber
         $ openssl ca -config ca/pmiIdentityCa.cnf -batch -gencrl -out ca/pmi.crl

   .. group-tab:: Windows

      .. code-block:: doscon

         > echo 01> ca\database\pmiIdentityCaCrlNumber
         > openssl ca -config ca\pmiIdentityCa.cnf -batch -gencrl -out ca\pmi.crl


.. _section-sec-HO4-specifying-new-crl-qos-profiles:

Specifying the New Certificate Revocation List in QoS Profiles
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Each |DP| that cares about avoiding communication with revoked |DPs| needs to
load this list. Let's assume Bob cares about avoiding communication with
Alice. Modify :file:`USER_QOS_PROFILES.xml` to make Bob's |DP| load the new
CRL:

.. code-block:: xml

    ...
    <element>
        <name>dds.sec.auth.crl</name>
        <value>file:./cert/pmi/ca/pmi.crl</value>
    </element>
    ...

Stop and restart the subscriber application so that Bob reads the updated QoS
and loads the new CRL. Now, when Bob discovers Alice, Bob will print this error:

.. code-block:: text

  "X509_verify_cert returned 0 with error 23: certificate revoked
  subject name: /C=US/ST=CA/L=Santa Clara/O=Patient Monitoring Innovations/emailAddress=alice@pmi.com/CN=Alice
  issuer name: /C=US/ST=CA/L=Santa Clara/O=Patient Monitoring Innovations/CN=PMI Identity CA/emailAddress=identityca@pmi.com"

Communication will not occur between Alice and Bob.

.. note::

    The :property:`com.rti.serv.secure.authentication.crl` property is mutable,
    so you can change it at runtime. To do so, use the
    :link_connext_dds_api_cpp2:`set_qos API <classdds_1_1domain_1_1DomainParticipant.html#a38abfca34c034a359e9a4feb0a9b48b8>`
    or, if file tracker is enabled, directly change the contents of the file
    that the property points to. You can start with an empty CRL file, and then
    add entries to it as you revoke more certificates.

.. _section-sec-HO4-troubleshooting:

Troubleshooting
---------------

* When I run my subscriber, I get the following error:

  .. code-block:: text

    [CREATE Participant] RTI_Security_CertHelper_loadPrivateKey:private_key is not encrypted, yet password is supplied. Aborting participant creation due to inconsistent configuration.

  In previous Hands-On sections, your subscriber used the
  :file:`ecdsa01Peer02Key.pem` private key, which is password protected. If you
  did not specify a password for :file:`BobKey.pem`, make sure you remove the
  :property:`dds.sec.auth.password` property from Bob's profile in
  :file:`USER_QOS_PROFILES.xml`.
  |br| |br|

* How can I verify whether a CA correctly issued an Identity Certificate?

  .. code-block:: text

    openssl verify -CAfile <identityCACert> <peerIdentityCert>

* How can I verify the signed Governance and Permissions Documents?

  .. code-block:: text

    openssl cms -verify -CAfile <permissionsCACert> -in <signedFile>

* I am using the |RTI_SP_PRODUCT| with wolfSSL and see the following error when running
  either my publisher or my subscriber:

  .. code-block:: text

    RTI_Security_CertHelper_loadCertsCrls:WolfSSL function PEM_X509_INFO_read_bio failed with error: (error details not available)
    RTI_Security_CertHelper_loadCertsCrls:Error loading certificates

  This might be caused by the certificates being in an incompatible format. We
  recommend generating the certificates using |OpenSSL| version 1.1.1k or
  above, which you can install using the process described in the
  |SP_IG_LINK|.

* When I attempt to create a |DP|, I get the following error:

  .. code-block:: text

    X509_verify_cert returned 0 with error 79: invalid CA certificate

  You may be using an X.509 v3 Identity CA that does not have
  ``basicConstraints = CA:true``. Refer to
  :link_connext_dds_secure_um:`The basicConstraints X.509 v3 extension <p2_core/elements_dds_secure_system.html#the-basicconstraints-x-509v3-extension>`
  in the |SP_UM| for more details. In :file:`pmiIdentityCa.cnf`, make sure the
  ``x509_extensions = v3_ca`` line is not commented out.

  .. note::

    When running ``openssl ca`` or ``openssl x509``, OpenSSL version 3.2.0 and
    above generate X.509 v3 (as opposed to v1) certificates by default.

For further troubleshooting, see :ref:`Troubleshooting in Hands-On 3
<section-sec-HO3-troubleshooting>`.
