diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4514ff5971d..b2e92a1df75 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -165,6 +165,7 @@ if(SECURITY)
 else()
     find_package(OpenSSL)
 endif()
+find_package(LibP11)
 
 if(OPENSSL_FOUND)
     message(STATUS "OpenSSL library ${OPENSSL_VERSION} found...")
diff --git a/README.md b/README.md
index af7c2724a96..4e47ab248aa 100644
--- a/README.md
+++ b/README.md
@@ -93,6 +93,22 @@ choco install -y -s <PATH\TO\DOWNLOADS\> asio tinyxml2
 
 Please replace `<PATH\TO\DOWNLOADS>` with the folder you downloaded the packages to.
 
+##### Libp11 library
+
+Libp11 provides PKCS#11 support for openSSL. This is an optional dependency,
+that is needed only when *eprosima Fast DDS* is used with security and PKCS#11 URLs.
+
+On Linux, you can install libp11 using the package manager of your Linux distribution.
+For example, on Ubuntu you can install them by using its package manager with the next command.
+
+```bash
+sudo apt install libp11-dev libengine-pkcs11-openssl
+```
+
+On Windows, you can download and compile the library from this
+[ROS2 Github repository](https://github.com/OpenSC/libp11).
+Follow the instructions on the repository to compile it on your platform.
+
 #### Colcon installation
 
 [colcon](https://colcon.readthedocs.io) is a command line tool to build sets of software packages.
diff --git a/cmake/modules/FindLibP11.cmake b/cmake/modules/FindLibP11.cmake
new file mode 100644
index 00000000000..ebaaa7289b2
--- /dev/null
+++ b/cmake/modules/FindLibP11.cmake
@@ -0,0 +1,43 @@
+# FindLibP11
+#
+# Generates an imported target associated to an available pksc11 library:
+#
+#   + On linux relies on the apt package libp11-dev
+#
+#   + On Windows the library must be build from sources available at https://github.com/OpenSC/libp11.git
+#     Given that each user must build its own binaries the following environment variables must be set to hint
+#     where to locate headers and binaries (semicolon-separated list see https://cmake.org/cmake/help/v3.22/variable/PackageName_ROOT.html):
+#       + LibP11_ROOT_32 -> to reference sources and 32 bit binaries location
+#       + LibP11_ROOT_64 -> to reference sources and 64 bit binaries location
+
+if(TARGET eProsima_p11)
+    return()
+endif()
+
+if(CMAKE_SIZEOF_VOID_P EQUAL 4)
+    set(LibP11_ROOT "$ENV{LibP11_ROOT_32}")
+else()
+    set(LibP11_ROOT "$ENV{LibP11_ROOT_64}")
+endif()
+
+find_path(LIBP11_INCLUDE_DIR NAMES libp11.h HINTS ${LibP11_ROOT})
+find_library(LIBP11_LIBRARY NAMES libp11.a libp11.lib HINTS ${LibP11_ROOT})
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(LibP11 DEFAULT_MSG LIBP11_LIBRARY LIBP11_INCLUDE_DIR)
+
+if(LibP11_FOUND)
+    # add the target
+    add_library(eProsima_p11 STATIC IMPORTED)
+
+    # update the properties
+    set_target_properties(eProsima_p11 PROPERTIES
+        IMPORTED_LOCATION "${LIBP11_LIBRARY}"
+        INTERFACE_INCLUDE_DIRECTORIES "${LIBP11_INCLUDE_DIR}"
+    )
+endif()
+
+# clean local variables
+unset(LIBP11_INCLUDE_DIR)
+unset(LIBP11_LIBRARY)
+unset(LibP11_ROOT)
diff --git a/include/fastrtps/config.h.in b/include/fastrtps/config.h.in
index 5c437832970..22ef7331cfc 100644
--- a/include/fastrtps/config.h.in
+++ b/include/fastrtps/config.h.in
@@ -25,69 +25,73 @@
 // C++20 support defines
 #ifndef HAVE_CXX20
 #define HAVE_CXX20 @HAVE_CXX20@
-#endif
+#endif /* ifndef HAVE_CXX20 */
 
 // C++17 support defines
 #ifndef HAVE_CXX17
 #define HAVE_CXX17 @HAVE_CXX17@
-#endif
+#endif /* ifndef HAVE_CXX17 */
 
 // C++14 support defines
 #ifndef HAVE_CXX14
 #define HAVE_CXX14 @HAVE_CXX14@
-#endif
+#endif /* ifndef HAVE_CXX14 */
 
 // C++1Y support defines
 #ifndef HAVE_CXX1Y
 #define HAVE_CXX1Y @HAVE_CXX1Y@
-#endif
+#endif /* ifndef HAVE_CXX1Y */
 
 // C++11 support defines
 #ifndef HAVE_CXX11
 #define HAVE_CXX11 @HAVE_CXX11@
-#endif
+#endif /* ifndef HAVE_CXX11 */
 
 // C++0x support defines
 #ifndef HAVE_CXX0X
 #define HAVE_CXX0X @HAVE_CXX0X@
-#endif
+#endif /* ifndef HAVE_CXX0X */
 
 // C++ constexpr support
 #ifndef HAVE_CXX_CONSTEXPR
 #define HAVE_CXX_CONSTEXPR @HAVE_CXX_CONSTEXPR@
-#endif
+#endif /* ifndef HAVE_CXX_CONSTEXPR */
 
 #if HAVE_CXX_CONSTEXPR
 #define CONSTEXPR constexpr
 #else
 #define CONSTEXPR const
-#endif
+#endif /* if HAVE_CXX_CONSTEXPR */
 
 // Endianness defines
 #ifndef FASTDDS_IS_BIG_ENDIAN_TARGET
 #define FASTDDS_IS_BIG_ENDIAN_TARGET @FASTDDS_IS_BIG_ENDIAN_TARGET@
-#endif
+#endif /* ifndef FASTDDS_IS_BIG_ENDIAN_TARGET */
 
 // Security
 #ifndef HAVE_SECURITY
 #define HAVE_SECURITY @HAVE_SECURITY@
-#endif
+#endif /* ifndef HAVE_SECURITY */
+
+#ifndef HAVE_LIBP11
+#define HAVE_LIBP11 @HAVE_LIBP11@
+#endif /* ifndef HAVE_LIBP11 */
 
 //Sqlite3 support
 #ifndef HAVE_SQLITE3
 #define HAVE_SQLITE3 @HAVE_SQLITE3@
-#endif
+#endif /* ifndef HAVE_SQLITE3 */
 
 
 // TLS support
 #ifndef TLS_FOUND
 #define TLS_FOUND @TLS_FOUND@
-#endif
+#endif /* ifndef TLS_FOUND */
 
 // Strict real-time
 #ifndef HAVE_STRICT_REALTIME
 #define HAVE_STRICT_REALTIME @HAVE_STRICT_REALTIME@
-#endif
+#endif /* ifndef HAVE_STRICT_REALTIME */
 
 /* Log Macros */
 
@@ -95,17 +99,17 @@
 #cmakedefine FASTDDS_ENFORCE_LOG_INFO
 #ifndef HAVE_LOG_NO_INFO
 #define HAVE_LOG_NO_INFO @HAVE_LOG_NO_INFO@
-#endif
+#endif /* ifndef HAVE_LOG_NO_INFO */
 
 // Log Warning
 #ifndef HAVE_LOG_NO_WARNING
 #define HAVE_LOG_NO_WARNING @HAVE_LOG_NO_WARNING@
-#endif
+#endif /* ifndef HAVE_LOG_NO_WARNING */
 
 // Log Error
 #ifndef HAVE_LOG_NO_ERROR
 #define HAVE_LOG_NO_ERROR @HAVE_LOG_NO_ERROR@
-#endif
+#endif /* ifndef HAVE_LOG_NO_ERROR */
 
 // Statistics
 #cmakedefine FASTDDS_STATISTICS
@@ -119,7 +123,7 @@
 #define FASTRTPS_DEPRECATED(msg) __declspec(deprecated(msg))
 #else
 #define FASTRTPS_DEPRECATED(msg)
-#endif
+#endif /* if __cplusplus >= 201402L */
 
 // Deprecation with version
 #define FASTDDS_DEPRECATED_UNTIL(major, entity_name, msg)                                                           \
@@ -128,7 +132,7 @@
 
 #define FASTDDS_TODO_BEFORE(major, minor, msg)                                          \
     static_assert((FASTRTPS_VERSION_MAJOR < major) ||                                   \
-                  (FASTRTPS_VERSION_MAJOR == major && FASTRTPS_VERSION_MINOR < minor),  \
-                  "TODO before version " #major "." #minor " : " #msg);
+            (FASTRTPS_VERSION_MAJOR == major && FASTRTPS_VERSION_MINOR < minor),  \
+            "TODO before version " #major "." #minor " : " #msg);
 
 #endif // _FASTRTPS_CONFIG_H_
diff --git a/src/cpp/CMakeLists.txt b/src/cpp/CMakeLists.txt
index 53b987cfeb8..f7160c0039f 100644
--- a/src/cpp/CMakeLists.txt
+++ b/src/cpp/CMakeLists.txt
@@ -296,6 +296,8 @@ set(${PROJECT_NAME}_security_source_files
     security/accesscontrol/GovernanceParser.cpp
     security/accesscontrol/PermissionsParser.cpp
     security/logging/LogTopic.cpp
+    security/artifact_providers/FileProvider.cpp
+    security/artifact_providers/Pkcs11Provider.cpp
     )
 
 if(SECURITY)
@@ -303,8 +305,14 @@ if(SECURITY)
         ${${PROJECT_NAME}_security_source_files}
         )
     set(HAVE_SECURITY 1)
+    if(LIBP11_FOUND)
+        set(HAVE_LIBP11 1)
+    else()
+        set(HAVE_LIBP11 0)
+    endif()
 else()
     set(HAVE_SECURITY 0)
+    set(HAVE_LIBP11 0)
 endif()
 
 if(WIN32 AND (MSVC OR MSVC_IDE))
@@ -437,6 +445,7 @@ target_link_libraries(${PROJECT_NAME} ${PRIVACY} fastcdr foonathan_memory
     $<$<BOOL:${WIN32}>:iphlpapi$<SEMICOLON>Shlwapi>
     ${THIRDPARTY_BOOST_LINK_LIBS}
     PRIVATE eProsima_atomic
+    $<$<BOOL:${LibP11_FOUND}>:eProsima_p11>  # $<TARGET_NAME_IF_EXISTS:eProsima_p11>
     )
 
 if(MSVC OR MSVC_IDE)
diff --git a/src/cpp/security/accesscontrol/Permissions.cpp b/src/cpp/security/accesscontrol/Permissions.cpp
index 55915643117..91bcccada6c 100644
--- a/src/cpp/security/accesscontrol/Permissions.cpp
+++ b/src/cpp/security/accesscontrol/Permissions.cpp
@@ -43,6 +43,8 @@
 #include <openssl/err.h>
 #include <openssl/obj_mac.h>
 
+#include <security/artifact_providers/FileProvider.hpp>
+
 #include <cassert>
 #include <fstream>
 
@@ -351,105 +353,13 @@ static X509_STORE* load_permissions_ca(
         std::string& ca_algo,
         SecurityException& exception)
 {
-    X509_STORE* store = X509_STORE_new();
-
-    if (store != nullptr)
-    {
-        if (permissions_ca.size() >= 7 && permissions_ca.compare(0, 7, "file://") == 0)
-        {
-            BIO* in = BIO_new(BIO_s_file());
-
-            if (in != nullptr)
-            {
-                if (BIO_read_filename(in, permissions_ca.substr(7).c_str()) > 0)
-                {
-                    STACK_OF(X509_INFO) * inf = PEM_X509_INFO_read_bio(in, NULL, NULL, NULL);
-
-                    if (inf != nullptr)
-                    {
-                        int i, count = 0;
-                        there_are_crls = false;
-
-                        for (i = 0; i < sk_X509_INFO_num(inf); i++)
-                        {
-                            X509_INFO* itmp = sk_X509_INFO_value(inf, i);
-
-                            if (itmp->x509)
-                            {
-                                // Retrieve subject name for future use.
-                                if (ca_sn.empty())
-                                {
-                                    X509_NAME* ca_subject_name = X509_get_subject_name(itmp->x509);
-                                    assert(ca_subject_name != nullptr);
-                                    char* ca_subject_name_str = X509_NAME_oneline(ca_subject_name, 0, 0);
-                                    assert(ca_subject_name_str != nullptr);
-                                    ca_sn = ca_subject_name_str;
-                                    OPENSSL_free(ca_subject_name_str);
-                                }
-
-                                // Retrieve signature algorithm
-                                if (ca_algo.empty())
-                                {
-                                    if (get_signature_algorithm(itmp->x509, ca_algo, exception))
-                                    {
-                                        X509_STORE_add_cert(store, itmp->x509);
-                                        count++;
-                                    }
-                                }
-                                else
-                                {
-                                    X509_STORE_add_cert(store, itmp->x509);
-                                    count++;
-                                }
-                            }
-                            if (itmp->crl)
-                            {
-                                X509_STORE_add_crl(store, itmp->crl);
-                                there_are_crls = true;
-                            }
-                        }
-
-                        sk_X509_INFO_pop_free(inf, X509_INFO_free);
-
-                        if (count > 0)
-                        {
-                            BIO_free(in);
-
-                            return store;
-                        }
-                    }
-                    else
-                    {
-                        exception = _SecurityException_(std::string(
-                                            "OpenSSL library cannot read X509 info in file ") +
-                                        permissions_ca.substr(7));
-                    }
-                }
-                else
-                {
-                    exception = _SecurityException_(std::string(
-                                        "OpenSSL library cannot read file ") + permissions_ca.substr(7));
-                }
-
-                BIO_free(in);
-            }
-            else
-            {
-                exception = _SecurityException_("OpenSSL library cannot allocate file");
-            }
-        }
-        else
-        {
-            exception = _SecurityException_("Unsupported permissions_ca format");
-        }
-
-        X509_STORE_free(store);
-    }
-    else
+    if (permissions_ca.size() >= 7 && permissions_ca.compare(0, 7, "file://") == 0)
     {
-        exception = _SecurityException_("Creation of X509 storage");
+        return detail::FileProvider::load_ca(permissions_ca, there_are_crls, ca_sn, ca_algo, get_signature_algorithm,
+                       exception);
     }
 
+    exception = _SecurityException_(std::string("Unsupported URI format ") + permissions_ca);
     return nullptr;
 }
 
diff --git a/src/cpp/security/artifact_providers/FileProvider.cpp b/src/cpp/security/artifact_providers/FileProvider.cpp
new file mode 100644
index 00000000000..e9dcd3a065e
--- /dev/null
+++ b/src/cpp/security/artifact_providers/FileProvider.cpp
@@ -0,0 +1,261 @@
+// Copyright 2021 Proyectos y Sistemas de Mantenimiento SL (eProsima).
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @file FileProvider.cpp
+ */
+
+#include <security/artifact_providers/FileProvider.hpp>
+
+#include <cassert>
+#include <cstring>
+#include <iostream>
+
+#define S1(x) #x
+#define S2(x) S1(x)
+#define LOCATION " (" __FILE__ ":" S2(__LINE__) ")"
+#define _SecurityException_(str) SecurityException(std::string(str) + LOCATION)
+
+
+namespace eprosima {
+namespace fastrtps {
+namespace rtps {
+namespace security {
+namespace detail {
+
+X509_STORE* FileProvider::load_ca(
+        const std::string& ca,
+        bool& there_are_crls,
+        std::string& ca_sn,
+        std::string& ca_algo,
+        std::function<bool(X509*, std::string&, SecurityException&)> get_signature_algorithm,
+        SecurityException& exception)
+{
+    X509_STORE* store = X509_STORE_new();
+
+    if (store != nullptr)
+    {
+        BIO* in = BIO_new(BIO_s_file());
+
+        if (in != nullptr)
+        {
+            if (BIO_read_filename(in, ca.substr(7).c_str()) > 0)
+            {
+                STACK_OF(X509_INFO) * inf = PEM_X509_INFO_read_bio(in, NULL, NULL, NULL);
+
+                if (inf != nullptr)
+                {
+                    int i, count = 0;
+                    there_are_crls = false;
+
+                    for (i = 0; i < sk_X509_INFO_num(inf); i++)
+                    {
+                        X509_INFO* itmp = sk_X509_INFO_value(inf, i);
+
+                        if (itmp->x509)
+                        {
+                            // Retrieve subject name for future use.
+                            if (ca_sn.empty())
+                            {
+                                X509_NAME* ca_subject_name = X509_get_subject_name(itmp->x509);
+                                assert(ca_subject_name != nullptr);
+                                char* ca_subject_name_str = X509_NAME_oneline(ca_subject_name, 0, 0);
+                                assert(ca_subject_name_str != nullptr);
+                                ca_sn = ca_subject_name_str;
+                                OPENSSL_free(ca_subject_name_str);
+                            }
+
+                            // Retrieve signature algorithm
+                            if (ca_algo.empty())
+                            {
+                                if (get_signature_algorithm(itmp->x509, ca_algo, exception))
+                                {
+                                    X509_STORE_add_cert(store, itmp->x509);
+                                    count++;
+                                }
+                            }
+                            else
+                            {
+                                X509_STORE_add_cert(store, itmp->x509);
+                                count++;
+                            }
+                        }
+                        if (itmp->crl)
+                        {
+                            X509_STORE_add_crl(store, itmp->crl);
+                            there_are_crls = true;
+                        }
+                    }
+
+                    sk_X509_INFO_pop_free(inf, X509_INFO_free);
+
+                    if (count > 0)
+                    {
+                        BIO_free(in);
+
+                        return store;
+                    }
+                }
+                else
+                {
+                    exception = _SecurityException_(std::string(
+                                        "OpenSSL library cannot read X509 info in file ") + ca.substr(7));
+                }
+            }
+            else
+            {
+                exception = _SecurityException_(std::string(
+                                    "OpenSSL library cannot read file ") + ca.substr(7));
+            }
+
+            BIO_free(in);
+        }
+        else
+        {
+            exception = _SecurityException_("OpenSSL library cannot allocate file");
+        }
+
+        X509_STORE_free(store);
+    }
+    else
+    {
+        exception = _SecurityException_("Creation of X509 storage");
+    }
+
+    return nullptr;
+}
+
+X509* FileProvider::load_certificate(
+        const std::string& identity_cert,
+        SecurityException& exception)
+{
+    X509* returnedValue = nullptr;
+    BIO* in = BIO_new(BIO_s_file());
+
+    if (in != nullptr)
+    {
+        if (BIO_read_filename(in, identity_cert.substr(7).c_str()) > 0)
+        {
+            returnedValue = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
+        }
+        else
+        {
+            exception =
+                    _SecurityException_(std::string("OpenSSL library cannot read file ") + identity_cert.substr(7));
+        }
+
+        BIO_free(in);
+    }
+    else
+    {
+        exception = _SecurityException_("OpenSSL library cannot allocate file");
+    }
+
+    return returnedValue;
+}
+
+static int private_key_password_callback(
+        char* buf,
+        int bufsize,
+        int /*verify*/,
+        const char* password)
+{
+    assert(password != nullptr);
+
+    int returnedValue = static_cast<int>(strlen(password));
+
+    if (returnedValue > bufsize)
+    {
+        returnedValue = bufsize;
+    }
+
+    memcpy(buf, password, returnedValue);
+    return returnedValue;
+}
+
+EVP_PKEY* FileProvider::load_private_key(
+        X509* certificate,
+        const std::string& pkey,
+        const std::string& password,
+        SecurityException& exception)
+{
+    EVP_PKEY* returnedValue = nullptr;
+    BIO* in = BIO_new(BIO_s_file());
+
+    if (in != nullptr)
+    {
+        if (BIO_read_filename(in, pkey.substr(7).c_str()) > 0)
+        {
+            returnedValue =
+                    PEM_read_bio_PrivateKey(in, NULL, (pem_password_cb*)private_key_password_callback,
+                            (void*)password.c_str());
+
+            // Verify private key.
+            if (!X509_check_private_key(certificate, returnedValue))
+            {
+                exception = _SecurityException_(std::string("Error verifying private key ") + pkey.substr(7));
+                EVP_PKEY_free(returnedValue);
+                returnedValue = nullptr;
+            }
+        }
+        else
+        {
+            exception = _SecurityException_(std::string("OpenSSL library cannot read file ") + pkey.substr(7));
+        }
+
+        BIO_free(in);
+    }
+    else
+    {
+        exception = _SecurityException_("OpenSSL library cannot allocate file");
+    }
+
+    return returnedValue;
+}
+
+X509_CRL* FileProvider::load_crl(
+        const std::string& identity_crl,
+        SecurityException& exception)
+{
+    X509_CRL* returnedValue = nullptr;
+
+    BIO* in = BIO_new(BIO_s_file());
+
+    if (in != nullptr)
+    {
+        if (BIO_read_filename(in, identity_crl.substr(7).c_str()) > 0)
+        {
+            returnedValue = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
+        }
+        else
+        {
+            exception = _SecurityException_(std::string("OpenSSL library cannot read file ") + identity_crl.substr(7));
+        }
+
+        BIO_free(in);
+    }
+    else
+    {
+        exception = _SecurityException_("OpenSSL library cannot allocate file");
+    }
+
+    return returnedValue;
+}
+
+} // namespace detail
+} //namespace security
+} //namespace rtps
+} //namespace fastrtps
+} //namespace eprosima
+
diff --git a/src/cpp/security/artifact_providers/FileProvider.hpp b/src/cpp/security/artifact_providers/FileProvider.hpp
new file mode 100644
index 00000000000..ca3459fd66d
--- /dev/null
+++ b/src/cpp/security/artifact_providers/FileProvider.hpp
@@ -0,0 +1,72 @@
+// Copyright 2021 Proyectos y Sistemas de Mantenimiento SL (eProsima).
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @file FileProvider.hpp
+ */
+
+#ifndef _SECURITY_ARTIFACTPROVIDERS_FILEPROVIDER_HPP_
+#define _SECURITY_ARTIFACTPROVIDERS_FILEPROVIDER_HPP_
+
+#include <functional>
+
+#include <openssl/engine.h>
+#include <openssl/err.h>
+#include <openssl/ssl.h>
+
+#include <fastdds/rtps/security/exceptions/SecurityException.h>
+
+
+namespace eprosima {
+namespace fastrtps {
+namespace rtps {
+namespace security {
+namespace detail {
+
+class FileProvider
+{
+
+public:
+
+    static X509_STORE* load_ca(
+            const std::string& ca,
+            bool& there_are_crls,
+            std::string& ca_sn,
+            std::string& ca_algo,
+            std::function<bool(X509*, std::string&, SecurityException&)> get_signature_algorithm,
+            SecurityException& exception);
+
+    static EVP_PKEY* load_private_key(
+            X509* certificate,
+            const std::string& file,
+            const std::string& password,
+            SecurityException& exception);
+
+    static X509* load_certificate(
+            const std::string& identity_cert,
+            SecurityException& exception);
+
+    static X509_CRL* load_crl(
+            const std::string& identity_crl,
+            SecurityException& exception);
+
+};
+
+} // namespace detail
+} //namespace security
+} //namespace rtps
+} //namespace fastrtps
+} //namespace eprosima
+
+#endif  // _SECURITY_ARTIFACTPROVIDERS_FILEPROVIDER_HPP_
diff --git a/src/cpp/security/artifact_providers/Pkcs11Provider.cpp b/src/cpp/security/artifact_providers/Pkcs11Provider.cpp
new file mode 100644
index 00000000000..c0a7daf6de7
--- /dev/null
+++ b/src/cpp/security/artifact_providers/Pkcs11Provider.cpp
@@ -0,0 +1,164 @@
+// Copyright 2021 Proyectos y Sistemas de Mantenimiento SL (eProsima).
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @file Pkcs11Provider.cpp
+ */
+
+#include <security/artifact_providers/Pkcs11Provider.hpp>
+
+#include <iostream>
+
+#include <fastdds/dds/log/Log.hpp>
+#include <utils/SystemInfo.hpp>
+
+#define S1(x) #x
+#define S2(x) S1(x)
+#define LOCATION " (" __FILE__ ":" S2(__LINE__) ")"
+#define _SecurityException_(str) SecurityException(std::string(str) + LOCATION)
+
+
+namespace eprosima {
+namespace fastrtps {
+namespace rtps {
+namespace security {
+namespace detail {
+
+constexpr const char* FASTDDS_PKCS11_PIN = "FASTDDS_PKCS11_PIN";
+constexpr const char* PKCS11_ENGINE_ID = "pkcs11";
+
+static int ui_open(
+        UI* ui)
+{
+    return UI_method_get_opener(UI_OpenSSL())(ui);
+}
+
+static int ui_read(
+        UI* ui,
+        UI_STRING* uis)
+{
+    switch (UI_get_string_type(uis))
+    {
+        case UIT_PROMPT:
+        case UIT_VERIFY:
+        {
+            logWarning(PKCS11_PROVIDER, "PKCS#11 engine is asking: " << UI_get0_output_string(uis));
+            // Return an empty password without asking the user
+            UI_set_result(ui, uis, "");
+            return 1;
+        }
+        default:
+            break;
+    }
+
+    // Call the default method of the engine provider
+    return UI_method_get_reader(UI_OpenSSL())(ui, uis);
+}
+
+static int ui_close(
+        UI* ui)
+{
+    return UI_method_get_closer(UI_OpenSSL())(ui);
+}
+
+Pkcs11Provider::Pkcs11Provider()
+{
+    SSL_load_error_strings();                /* readable error messages */
+    SSL_library_init();                      /* initialize library */
+
+    // Create an UI method to use with the engine
+    // This will be used to retrieve the PIN if none was given in the ENV nor in the URI
+    ui_method_ = UI_create_method("OpenSSL application user interface");
+    UI_method_set_opener(ui_method_, ui_open);
+    UI_method_set_reader(ui_method_, ui_read);
+    UI_method_set_closer(ui_method_, ui_close);
+
+    // Load the engine
+    ENGINE_load_builtin_engines();
+    pkcs11_ = ENGINE_by_id(PKCS11_ENGINE_ID);
+    if (!pkcs11_)
+    {
+        has_initialization_error_ = true;
+        initialization_exception_ = _SecurityException_(std::string("Error retrieving 'pkcs11' engine"));
+    }
+
+    // Load the PIN from the environment
+    std::string pin;
+    if (ReturnCode_t::RETCODE_OK == SystemInfo::get_env(FASTDDS_PKCS11_PIN, pin))
+    {
+        if (!ENGINE_ctrl_cmd_string( pkcs11_, "PIN", pin.c_str(), 0))
+        {
+            has_initialization_error_ = true;
+            initialization_exception_ =
+                    _SecurityException_(std::string("Error setting the PIN in the 'pkcs11' engine"));
+            ENGINE_free(pkcs11_);
+        }
+    }
+
+    // Init the engine with the PIN (if any)
+    if (!ENGINE_init(pkcs11_))
+    {
+        has_initialization_error_ = true;
+        initialization_exception_ = _SecurityException_(std::string("Error initializing the HSM provider library"));
+        ENGINE_free(pkcs11_);
+    }
+}
+
+Pkcs11Provider::~Pkcs11Provider()
+{
+    ENGINE_finish(pkcs11_);
+    ENGINE_free(pkcs11_);
+
+    if (ui_method_)
+    {
+        UI_destroy_method(ui_method_);
+    }
+}
+
+EVP_PKEY* Pkcs11Provider::load_private_key(
+        X509* certificate,
+        const std::string& pkey,
+        const std::string& /*password*/,
+        SecurityException& exception)
+{
+    if (has_initialization_error_)
+    {
+        exception = initialization_exception_;
+        return nullptr;
+    }
+
+    EVP_PKEY* returnedValue = ENGINE_load_private_key(pkcs11_, pkey.c_str(), ui_method_, nullptr);
+    if (!returnedValue)
+    {
+        exception = _SecurityException_(std::string("Error opening the private key ") + pkey.substr(7));
+        return returnedValue;
+    }
+
+    // Verify private key.
+    if (!X509_check_private_key(certificate, returnedValue))
+    {
+        exception = _SecurityException_(std::string("Error verifying private key ") + pkey.substr(7)
+                        + "\n ERROR: " + ERR_error_string(ERR_get_error(), nullptr));
+        EVP_PKEY_free(returnedValue);
+        returnedValue = nullptr;
+    }
+
+    return returnedValue;
+}
+
+} // namespace detail
+} // namespace security
+} // namespace rtps
+} // namespace fastrtps
+} // namespace eprosima
diff --git a/src/cpp/security/artifact_providers/Pkcs11Provider.hpp b/src/cpp/security/artifact_providers/Pkcs11Provider.hpp
new file mode 100644
index 00000000000..87f558c1ef6
--- /dev/null
+++ b/src/cpp/security/artifact_providers/Pkcs11Provider.hpp
@@ -0,0 +1,74 @@
+// Copyright 2021 Proyectos y Sistemas de Mantenimiento SL (eProsima).
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @file Pkcs11Provider.hpp
+ */
+
+#ifndef _SECURITY_ARTIFACTPROVIDERS_PKCS11PROVIDER_HPP_
+#define _SECURITY_ARTIFACTPROVIDERS_PKCS11PROVIDER_HPP_
+
+#include <openssl/engine.h>
+#include <openssl/err.h>
+#include <openssl/ssl.h>
+
+#if HAVE_LIBP11
+#include <libp11.h>
+#endif // HAVE_LIBP11
+
+#include <fastdds/rtps/security/exceptions/SecurityException.h>
+
+
+namespace eprosima {
+namespace fastrtps {
+namespace rtps {
+namespace security {
+namespace detail {
+
+class Pkcs11Provider
+{
+
+public:
+
+    EVP_PKEY* load_private_key(
+            X509* certificate,
+            const std::string& file,
+            const std::string& password,
+            SecurityException& exception);
+
+    Pkcs11Provider();
+
+    ~Pkcs11Provider();
+
+private:
+
+    EVP_PKEY* load_private_key_impl(
+            X509* certificate,
+            const std::string& file,
+            const std::string& password,
+            SecurityException& exception);
+
+    SecurityException initialization_exception_;
+    bool has_initialization_error_ = false;
+    ENGINE* pkcs11_ = nullptr;
+    UI_METHOD* ui_method_ = nullptr;
+};
+
+} // namespace detail
+} //namespace security
+} //namespace rtps
+} //namespace fastrtps
+} //namespace eprosima
+
+#endif  // _SECURITY_ARTIFACTPROVIDERS_PKCS11PROVIDER_HPP_
diff --git a/src/cpp/security/authentication/PKIDH.cpp b/src/cpp/security/authentication/PKIDH.cpp
index 2dfcbf32d05..d51859b5f53 100644
--- a/src/cpp/security/authentication/PKIDH.cpp
+++ b/src/cpp/security/authentication/PKIDH.cpp
@@ -45,6 +45,9 @@
 #include <openssl/err.h>
 #include <openssl/obj_mac.h>
 
+#include <security/artifact_providers/FileProvider.hpp>
+#include <security/artifact_providers/Pkcs11Provider.hpp>
+
 #include <cassert>
 #include <algorithm>
 
@@ -158,100 +161,13 @@ static X509_STORE* load_identity_ca(
         std::string& ca_algo,
         SecurityException& exception)
 {
-    X509_STORE* store = X509_STORE_new();
-
-    if (store != nullptr)
-    {
-        if (identity_ca.size() >= 7 && identity_ca.compare(0, 7, "file://") == 0)
-        {
-            BIO* in = BIO_new(BIO_s_file());
-
-            if (in != nullptr)
-            {
-                if (BIO_read_filename(in, identity_ca.substr(7).c_str()) > 0)
-                {
-                    STACK_OF(X509_INFO) * inf = PEM_X509_INFO_read_bio(in, NULL, NULL, NULL);
-
-                    if (inf != nullptr)
-                    {
-                        int i, count = 0;
-                        there_are_crls = false;
-
-                        for (i = 0; i < sk_X509_INFO_num(inf); i++)
-                        {
-                            X509_INFO* itmp = sk_X509_INFO_value(inf, i);
-
-                            if (itmp->x509)
-                            {
-                                // Retrieve subject name for future use.
-                                if (ca_sn.empty())
-                                {
-                                    X509_NAME* ca_subject_name = X509_get_subject_name(itmp->x509);
-                                    assert(ca_subject_name != nullptr);
-                                    char* ca_subject_name_str = X509_NAME_oneline(ca_subject_name, 0, 0);
-                                    assert(ca_subject_name_str != nullptr);
-                                    ca_sn = ca_subject_name_str;
-                                    OPENSSL_free(ca_subject_name_str);
-                                }
-
-                                // Retrieve signature algorithm
-                                if (ca_algo.empty())
-                                {
-                                    if (get_signature_algorithm(itmp->x509, ca_algo, exception))
-                                    {
-                                        X509_STORE_add_cert(store, itmp->x509);
-                                        count++;
-                                    }
-                                }
-                                else
-                                {
-                                    X509_STORE_add_cert(store, itmp->x509);
-                                    count++;
-                                }
-                            }
-                            if (itmp->crl)
-                            {
-                                X509_STORE_add_crl(store, itmp->crl);
-                                there_are_crls = true;
-                            }
-                        }
-
-                        sk_X509_INFO_pop_free(inf, X509_INFO_free);
-
-                        if (count > 0)
-                        {
-                            BIO_free(in);
-
-                            return store;
-                        }
-                    }
-                    else
-                    {
-                        exception = _SecurityException_(std::string(
-                                            "OpenSSL library cannot read X509 info in file ") + identity_ca.substr(7));
-                    }
-                }
-                else
-                {
-                    exception = _SecurityException_(std::string(
-                                        "OpenSSL library cannot read file ") + identity_ca.substr(7));
-                }
-
-                BIO_free(in);
-            }
-            else
-            {
-                exception = _SecurityException_("OpenSSL library cannot allocate file");
-            }
-        }
-
-        X509_STORE_free(store);
-    }
-    else
+    if (identity_ca.size() >= 7 && identity_ca.compare(0, 7, "file://") == 0)
     {
-        exception = _SecurityException_("Creation of X509 storage");
+        return detail::FileProvider::load_ca(identity_ca, there_are_crls, ca_sn, ca_algo, get_signature_algorithm,
+                       exception);
     }
 
+    exception = _SecurityException_(std::string("Unsupported URI format ") + identity_ca);
     return nullptr;
 }
 
@@ -259,33 +175,13 @@ static X509* load_certificate(
         const std::string& identity_cert,
         SecurityException& exception)
 {
-    X509* returnedValue = nullptr;
-
     if (identity_cert.size() >= 7 && identity_cert.compare(0, 7, "file://") == 0)
     {
-        BIO* in = BIO_new(BIO_s_file());
-
-        if (in != nullptr)
-        {
-            if (BIO_read_filename(in, identity_cert.substr(7).c_str()) > 0)
-            {
-                returnedValue = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
-            }
-            else
-            {
-                exception =
-                        _SecurityException_(std::string("OpenSSL library cannot read file ") + identity_cert.substr(7));
-            }
-
-            BIO_free(in);
-        }
-        else
-        {
-            exception = _SecurityException_("OpenSSL library cannot allocate file");
-        }
+        return detail::FileProvider::load_certificate(identity_cert, exception);
     }
 
-    return returnedValue;
+    exception = _SecurityException_(std::string("Unsupported URI format ") + identity_cert);
+    return nullptr;
 }
 
 static X509* load_certificate(
@@ -355,66 +251,34 @@ static bool verify_certificate(
     return returnedValue;
 }
 
-static int private_key_password_callback(
-        char* buf,
-        int bufsize,
-        int /*verify*/,
-        const char* password)
-{
-    assert(password != nullptr);
-
-    int returnedValue = static_cast<int>(strlen(password));
-
-    if (returnedValue > bufsize)
-    {
-        returnedValue = bufsize;
-    }
-
-    memcpy(buf, password, returnedValue);
-    return returnedValue;
-}
-
 static EVP_PKEY* load_private_key(
         X509* certificate,
         const std::string& file,
         const std::string& password,
-        SecurityException& exception)
+        SecurityException& exception,
+        PKIDH& pkidh)
 {
-    EVP_PKEY* returnedValue = nullptr;
     if (file.size() >= 7 && file.compare(0, 7, "file://") == 0)
     {
-        BIO* in = BIO_new(BIO_s_file());
-
-        if (in != nullptr)
-        {
-            if (BIO_read_filename(in, file.substr(7).c_str()) > 0)
-            {
-                returnedValue =
-                        PEM_read_bio_PrivateKey(in, NULL, (pem_password_cb*)private_key_password_callback,
-                                (void*)password.c_str());
-
-                // Verify private key.
-                if (!X509_check_private_key(certificate, returnedValue))
-                {
-                    exception = _SecurityException_(std::string("Error verifying private key ") + file.substr(7));
-                    EVP_PKEY_free(returnedValue);
-                    returnedValue = nullptr;
-                }
-            }
-            else
-            {
-                exception = _SecurityException_(std::string("OpenSSL library cannot read file ") + file.substr(7));
-            }
-
-            BIO_free(in);
-        }
-        else
+        return detail::FileProvider::load_private_key(certificate, file, password, exception);
+    }
+    else if (file.size() >= 7 && file.compare(0, 7, "pkcs11:") == 0)
+    {
+#if HAVE_LIBP11
+        if (!pkidh.pkcs11_provider)
         {
-            exception = _SecurityException_("OpenSSL library cannot allocate file");
+            pkidh.pkcs11_provider.reset(new detail::Pkcs11Provider());
         }
+        return pkidh.pkcs11_provider->load_private_key(certificate, file, password, exception);
+#else  // HAVE_LIBP11
+        static_cast<void>(pkidh);
+        exception = _SecurityException_(std::string("PKCS11 URIs require libp11 ") + file);
+        return nullptr;
+#endif // HAVE_LIBP11
     }
 
-    return returnedValue;
+    exception = _SecurityException_(std::string("Unsupported URI format ") + file);
+    return nullptr;
 }
 
 static bool store_certificate_in_buffer(
@@ -613,33 +477,13 @@ static X509_CRL* load_crl(
         const std::string& identity_crl,
         SecurityException& exception)
 {
-    X509_CRL* returnedValue = nullptr;
-
     if (identity_crl.size() >= 7 && identity_crl.compare(0, 7, "file://") == 0)
     {
-        BIO* in = BIO_new(BIO_s_file());
-
-        if (in != nullptr)
-        {
-            if (BIO_read_filename(in, identity_crl.substr(7).c_str()) > 0)
-            {
-                returnedValue = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
-            }
-            else
-            {
-                exception = _SecurityException_(std::string("OpenSSL library cannot read file ") + identity_crl.substr(
-                                    7));
-            }
-
-            BIO_free(in);
-        }
-        else
-        {
-            exception = _SecurityException_("OpenSSL library cannot allocate file");
-        }
+        return detail::FileProvider::load_crl(identity_crl, exception);
     }
 
-    return returnedValue;
+    exception = _SecurityException_(std::string("Unsupported URI format ") + identity_crl);
+    return nullptr;
 }
 
 static bool adjust_participant_key(
@@ -1241,7 +1085,7 @@ ValidationResult_t PKIDH::validate_local_identity(
                 {
                     if (get_signature_algorithm((*ih)->cert_, (*ih)->sign_alg_, exception))
                     {
-                        (*ih)->pkey_ = load_private_key((*ih)->cert_, *private_key, *password, exception);
+                        (*ih)->pkey_ = load_private_key((*ih)->cert_, *private_key, *password, exception, *this);
 
                         if ((*ih)->pkey_ != nullptr)
                         {
diff --git a/src/cpp/security/authentication/PKIDH.h b/src/cpp/security/authentication/PKIDH.h
index 33214388b1d..e1ef422fd4d 100644
--- a/src/cpp/security/authentication/PKIDH.h
+++ b/src/cpp/security/authentication/PKIDH.h
@@ -22,6 +22,7 @@
 #include <fastdds/rtps/security/authentication/Authentication.h>
 #include <fastdds/rtps/attributes/PropertyPolicy.h>
 #include <security/authentication/PKIHandshakeHandle.h>
+#include <security/artifact_providers/Pkcs11Provider.hpp>
 
 namespace eprosima {
 namespace fastrtps {
@@ -30,84 +31,106 @@ namespace security {
 
 class PKIDH : public Authentication
 {
-    public:
-
-        ValidationResult_t validate_local_identity(IdentityHandle** local_identity_handle,
-                GUID_t& adjusted_participant_key,
-                const uint32_t domain_id,
-                const RTPSParticipantAttributes& participant_attr,
-                const GUID_t& candidate_participant_key,
-                SecurityException& exception) override;
-
-        ValidationResult_t validate_remote_identity(IdentityHandle** remote_identity_handle,
-                const IdentityHandle& local_identity_handle,
-                const IdentityToken& remote_identity_token,
-                const GUID_t& remote_participant_key,
-                SecurityException& exception) override;
-
-        ValidationResult_t begin_handshake_request(HandshakeHandle** handshake_handle,
-                HandshakeMessageToken** handshake_message,
-                const IdentityHandle& initiator_identity_handle,
-                IdentityHandle& replier_identity_handle,
-                const CDRMessage_t& cdr_participant_data,
-                SecurityException& exception) override;
-
-        ValidationResult_t begin_handshake_reply(HandshakeHandle** handshake_handle,
-                HandshakeMessageToken** handshake_message_out,
-                HandshakeMessageToken&& handshake_message_in,
-                IdentityHandle& initiator_identity_handle,
-                const IdentityHandle& replier_identity_handle,
-                const CDRMessage_t& cdr_participant_data,
-                SecurityException& exception) override;
-
-        ValidationResult_t process_handshake(HandshakeMessageToken** handshake_message_out,
-                HandshakeMessageToken&& handshake_message_in,
-                HandshakeHandle& handshake_handle,
-                SecurityException& exception) override;
-
-        SharedSecretHandle* get_shared_secret(const HandshakeHandle& handshake_handle,
-                SecurityException& exception) override;
-
-        bool set_listener(AuthenticationListener* listener,
-                SecurityException& exception) override;
-
-        bool get_identity_token(IdentityToken** identity_token,
-                const IdentityHandle& handle,
-                SecurityException& exception) override;
-
-        bool return_identity_token(IdentityToken* token,
-                SecurityException& exception) override;
-
-        bool return_handshake_handle(HandshakeHandle* handshake_handle,
-                SecurityException& exception) override;
-
-        bool return_identity_handle(IdentityHandle* identity_handle,
-                SecurityException& exception) override;
-
-        bool return_sharedsecret_handle(SharedSecretHandle* sharedsecret_handle,
-                SecurityException& exception) override;
-
-        bool set_permissions_credential_and_token(IdentityHandle& identity_handle,
-                PermissionsCredentialToken& permissions_credential_token,
-                SecurityException& ex) override;
-
-        bool get_authenticated_peer_credential_token(PermissionsCredentialToken **token,
-                const IdentityHandle& identity_handle, SecurityException& exception) override;
-
-        bool return_authenticated_peer_credential_token(PermissionsCredentialToken* token,
-                SecurityException& ex) override;
-
-    private:
-
-        ValidationResult_t process_handshake_request(HandshakeMessageToken** handshake_message_out,
-                HandshakeMessageToken&& handshake_message_in,
-                PKIHandshakeHandle& handshake_handle,
-                SecurityException& exception);
-
-        ValidationResult_t process_handshake_reply(HandshakeMessageToken** handshake_message_out,
-                HandshakeMessageToken&& handshake_message_in,
-                PKIHandshakeHandle& handshake_handle,
-                SecurityException& exception);
+public:
+
+    ValidationResult_t validate_local_identity(
+            IdentityHandle** local_identity_handle,
+            GUID_t& adjusted_participant_key,
+            const uint32_t domain_id,
+            const RTPSParticipantAttributes& participant_attr,
+            const GUID_t& candidate_participant_key,
+            SecurityException& exception) override;
+
+    ValidationResult_t validate_remote_identity(
+            IdentityHandle** remote_identity_handle,
+            const IdentityHandle& local_identity_handle,
+            const IdentityToken& remote_identity_token,
+            const GUID_t& remote_participant_key,
+            SecurityException& exception) override;
+
+    ValidationResult_t begin_handshake_request(
+            HandshakeHandle** handshake_handle,
+            HandshakeMessageToken** handshake_message,
+            const IdentityHandle& initiator_identity_handle,
+            IdentityHandle& replier_identity_handle,
+            const CDRMessage_t& cdr_participant_data,
+            SecurityException& exception) override;
+
+    ValidationResult_t begin_handshake_reply(
+            HandshakeHandle** handshake_handle,
+            HandshakeMessageToken** handshake_message_out,
+            HandshakeMessageToken&& handshake_message_in,
+            IdentityHandle& initiator_identity_handle,
+            const IdentityHandle& replier_identity_handle,
+            const CDRMessage_t& cdr_participant_data,
+            SecurityException& exception) override;
+
+    ValidationResult_t process_handshake(
+            HandshakeMessageToken** handshake_message_out,
+            HandshakeMessageToken&& handshake_message_in,
+            HandshakeHandle& handshake_handle,
+            SecurityException& exception) override;
+
+    SharedSecretHandle* get_shared_secret(
+            const HandshakeHandle& handshake_handle,
+            SecurityException& exception) override;
+
+    bool set_listener(
+            AuthenticationListener* listener,
+            SecurityException& exception) override;
+
+    bool get_identity_token(
+            IdentityToken** identity_token,
+            const IdentityHandle& handle,
+            SecurityException& exception) override;
+
+    bool return_identity_token(
+            IdentityToken* token,
+            SecurityException& exception) override;
+
+    bool return_handshake_handle(
+            HandshakeHandle* handshake_handle,
+            SecurityException& exception) override;
+
+    bool return_identity_handle(
+            IdentityHandle* identity_handle,
+            SecurityException& exception) override;
+
+    bool return_sharedsecret_handle(
+            SharedSecretHandle* sharedsecret_handle,
+            SecurityException& exception) override;
+
+    bool set_permissions_credential_and_token(
+            IdentityHandle& identity_handle,
+            PermissionsCredentialToken& permissions_credential_token,
+            SecurityException& ex) override;
+
+    bool get_authenticated_peer_credential_token(
+            PermissionsCredentialToken** token,
+            const IdentityHandle& identity_handle,
+            SecurityException& exception) override;
+
+    bool return_authenticated_peer_credential_token(
+            PermissionsCredentialToken* token,
+            SecurityException& ex) override;
+
+#if HAVE_LIBP11
+    std::unique_ptr<detail::Pkcs11Provider> pkcs11_provider;
+#endif // HAVE_LIBP11
+
+private:
+
+    ValidationResult_t process_handshake_request(
+            HandshakeMessageToken** handshake_message_out,
+            HandshakeMessageToken&& handshake_message_in,
+            PKIHandshakeHandle& handshake_handle,
+            SecurityException& exception);
+
+    ValidationResult_t process_handshake_reply(
+            HandshakeMessageToken** handshake_message_out,
+            HandshakeMessageToken&& handshake_message_in,
+            PKIHandshakeHandle& handshake_handle,
+            SecurityException& exception);
 
 };
 
diff --git a/test/blackbox/CMakeLists.txt b/test/blackbox/CMakeLists.txt
index bc771212308..f679fac0842 100644
--- a/test/blackbox/CMakeLists.txt
+++ b/test/blackbox/CMakeLists.txt
@@ -21,7 +21,7 @@ macro(add_blackbox_gtest)
         set(test "${ARGV0}")
         set(command "${test}")
     endif()
-    set(multiValueArgs SOURCES ENVIRONMENTS DEPENDENCIES LABELS)
+    set(multiValueArgs SOURCES ENVIRONMENTS DEPENDENCIES LABELS IGNORE)
     cmake_parse_arguments(GTEST "" "${uniValueArgs}" "${multiValueArgs}" ${ARGN})
 
     if(GTEST_NAME)
@@ -29,6 +29,12 @@ macro(add_blackbox_gtest)
         set(command ${GTEST_COMMAND})
     endif()
 
+    # IGNORE keeps a filter expression for the test list:
+    #   +   if GTEST_INDIVIDUAL is enforced the expressions are regular expression and the matching tests would be disabled
+    #       using cmake add_test DISABLE property
+    #   +   if no GTEST_INDIVIDUAL is enforce the filtering will be added to gtest command via --gtest_filter and it's
+    #       own filtering syntax
+
     if(GTEST_INDIVIDUAL)
         if(WIN32)
             set(WIN_PATH "$ENV{PATH}")
@@ -55,6 +61,15 @@ macro(add_blackbox_gtest)
                 add_test(NAME ${test}.${GTEST_GROUP_NAME}.${GTEST_TEST_NAME}
                     COMMAND ${command} --gtest_filter=${GTEST_GROUP_NAME}.${GTEST_TEST_NAME})
 
+                # decide if disable
+                unset(GTEST_USER_DISABLED)
+                foreach(GTEST_USER_FILTER ${GTEST_IGNORE})
+                    string(REGEX MATCH ${GTEST_USER_FILTER} GTEST_USER_DISABLED ${GTEST_TEST_NAME})
+                    if(GTEST_USER_DISABLED)
+                        break()
+                    endif()
+                endforeach()
+
                 # Add environment
                 if(WIN32)
                     set_property(TEST ${test}.${GTEST_GROUP_NAME}.${GTEST_TEST_NAME} APPEND PROPERTY ENVIRONMENT "PATH=${WIN_PATH}")
@@ -64,8 +79,10 @@ macro(add_blackbox_gtest)
                     set_property(TEST ${test}.${GTEST_GROUP_NAME}.${GTEST_TEST_NAME} APPEND PROPERTY ENVIRONMENT "${property}")
                 endforeach()
 
-                # Add labels
-                set_property(TEST ${test}.${GTEST_GROUP_NAME}.${GTEST_TEST_NAME} PROPERTY LABELS "${GTEST_LABELS}")
+                # Add labels and enable
+                set_tests_properties(${test}.${GTEST_GROUP_NAME}.${GTEST_TEST_NAME} PROPERTIES
+                    LABELS "${GTEST_LABELS}"
+                    DISABLED $<BOOL:${GTEST_USER_DISABLED}>)
 
             endforeach()
             file(STRINGS ${GTEST_SOURCE_FILE} GTEST_TEST_NAMES REGEX "^TEST_P" )
@@ -77,6 +94,15 @@ macro(add_blackbox_gtest)
                 add_test(NAME ${test}.${GTEST_GROUP_NAME}.${GTEST_TEST_NAME}.Transport
                     COMMAND ${command} --gtest_filter=*/${GTEST_GROUP_NAME}.${GTEST_TEST_NAME}/Transport*)
 
+                # decide if disable
+                unset(GTEST_USER_DISABLED)
+                foreach(GTEST_USER_FILTER ${GTEST_IGNORE})
+                    string(REGEX MATCH ${GTEST_USER_FILTER} GTEST_USER_DISABLED ${GTEST_TEST_NAME})
+                    if(GTEST_USER_DISABLED)
+                        break()
+                    endif()
+                endforeach()
+
                 # Add environment
                 if(WIN32)
                     set_property(TEST ${test}.${GTEST_GROUP_NAME}.${GTEST_TEST_NAME}.Transport APPEND PROPERTY ENVIRONMENT "PATH=${WIN_PATH}")
@@ -86,8 +112,10 @@ macro(add_blackbox_gtest)
                     set_property(TEST ${test}.${GTEST_GROUP_NAME}.${GTEST_TEST_NAME}.Transport APPEND PROPERTY ENVIRONMENT "${property}")
                 endforeach()
 
-                # Add labels
-                set_property(TEST ${test}.${GTEST_GROUP_NAME}.${GTEST_TEST_NAME}.Transport PROPERTY LABELS "${GTEST_LABELS}")
+                # Add labels and enable
+                set_tests_properties(${test}.${GTEST_GROUP_NAME}.${GTEST_TEST_NAME}.Transport PROPERTIES
+                    LABELS "${GTEST_LABELS}"
+                    DISABLED $<BOOL:${GTEST_USER_DISABLED}>)
 
                 add_test(NAME ${test}.${GTEST_GROUP_NAME}.${GTEST_TEST_NAME}.Intraprocess
                     COMMAND ${command} --gtest_filter=*/${GTEST_GROUP_NAME}.${GTEST_TEST_NAME}/Intraprocess*)
@@ -101,8 +129,10 @@ macro(add_blackbox_gtest)
                     set_property(TEST ${test}.${GTEST_GROUP_NAME}.${GTEST_TEST_NAME}.Intraprocess APPEND PROPERTY ENVIRONMENT "${property}")
                 endforeach()
 
-                # Add labels
-                set_property(TEST ${test}.${GTEST_GROUP_NAME}.${GTEST_TEST_NAME}.Intraprocess PROPERTY LABELS "${GTEST_LABELS}")
+                # Add labels and enable
+                set_tests_properties(${test}.${GTEST_GROUP_NAME}.${GTEST_TEST_NAME}.Intraprocess PROPERTIES
+                    LABELS "${GTEST_LABELS}"
+                    DISABLED $<BOOL:${GTEST_USER_DISABLED}>)
 
                 if(${test} MATCHES ".*_DDS_PIM$")
                     add_test(NAME ${test}.${GTEST_GROUP_NAME}.${GTEST_TEST_NAME}.Datasharing
@@ -117,13 +147,22 @@ macro(add_blackbox_gtest)
                         set_property(TEST ${test}.${GTEST_GROUP_NAME}.${GTEST_TEST_NAME}.Datasharing APPEND PROPERTY ENVIRONMENT "${property}")
                     endforeach()
 
-                    # Add labels
-                    set_property(TEST ${test}.${GTEST_GROUP_NAME}.${GTEST_TEST_NAME}.Datasharing PROPERTY LABELS "${GTEST_LABELS}")
+                    # Add labels and enable
+                    set_tests_properties(${test}.${GTEST_GROUP_NAME}.${GTEST_TEST_NAME}.Datasharing PROPERTIES
+                        LABELS "${GTEST_LABELS}"
+                        DISABLED $<BOOL:${GTEST_USER_DISABLED}>)
+
                 endif()
 
             endforeach()
         endforeach()
     else()
+
+        # add filtering statement if required
+        if(GTEST_IGNORE)
+            set(command "${command} --gtest_filter=${GTEST_IGNORE}")
+        endif()
+
         add_test(NAME ${test} COMMAND ${command})
 
         # Add environment
@@ -164,9 +203,28 @@ if(WIN32)
         )
 endif()
 
+# OpenSSL on Windows requires a hint on which config file to load
+if(WIN32 AND OPENSSL_FOUND)
+    get_filename_component(OPENSSL_DIR "${OPENSSL_INCLUDE_DIR}" DIRECTORY)
+    set(OPENSSL_CONF "${OPENSSL_DIR}/bin/cnf/openssl.cnf")
+    unset(OPENSSL_DIR)
+endif()
+
 ###############################################################################
-# Unit tests
+# Blackbox tests
 ###############################################################################
+
+# Filter pksc11 related tests if library is not available
+# TODO: restore for windows when CI gets operational
+#if(NOT LibP11_FOUND)
+if(WIN32 OR NOT LibP11_FOUND)
+    if(GTEST_INDIVIDUAL)
+        set(pkcs_filter "[Pp][Kk][Cc][Ss]")
+    else()
+        set(pkcs_filter "-*pcks*")
+    endif() # GTEST_INDIVIDUAL
+endif() # LibP11_FOUND
+
 file(GLOB RTPS_BLACKBOXTESTS_TEST_SOURCE "common/RTPSBlackboxTests*.cpp")
 set(RTPS_BLACKBOXTESTS_SOURCE ${RTPS_BLACKBOXTESTS_TEST_SOURCE}
     types/HelloWorld.cpp
@@ -199,7 +257,7 @@ target_compile_definitions(BlackboxTests_RTPS PRIVATE
 target_include_directories(BlackboxTests_RTPS PRIVATE
     ${Asio_INCLUDE_DIR})
 target_link_libraries(BlackboxTests_RTPS fastrtps fastcdr foonathan_memory GTest::gtest)
-add_blackbox_gtest(BlackboxTests_RTPS SOURCES ${RTPS_BLACKBOXTESTS_TEST_SOURCE})
+add_blackbox_gtest(BlackboxTests_RTPS SOURCES ${RTPS_BLACKBOXTESTS_TEST_SOURCE} IGNORE ${pkcs_filter})
 
 file(GLOB BLACKBOXTESTS_TEST_SOURCE "common/BlackboxTests*.cpp")
 set(BLACKBOXTESTS_SOURCE ${BLACKBOXTESTS_TEST_SOURCE}
@@ -280,13 +338,22 @@ if(FASTRTPS_API_TESTS)
     target_include_directories(BlackboxTests_FastRTPS PRIVATE
         ${Asio_INCLUDE_DIR}
         api/fastrtps_deprecated)
-    target_link_libraries(BlackboxTests_FastRTPS fastrtps fastcdr foonathan_memory GTest::gtest)
+    target_link_libraries(BlackboxTests_FastRTPS
+        fastrtps
+        fastcdr
+        foonathan_memory
+        GTest::gtest
+        $<$<BOOL:${LibP11_FOUND}>:eProsima_p11>  # $<TARGET_NAME_IF_EXISTS:eProsima_p11>
+        )
+       
     add_blackbox_gtest(BlackboxTests_FastRTPS SOURCES ${BLACKBOXTESTS_TEST_SOURCE}
         ENVIRONMENTS "CERTS_PATH=${PROJECT_SOURCE_DIR}/test/certs"
         "TOPIC_RANDOM_NUMBER=${TOPIC_RANDOM_NUMBER}"
         "W_UNICAST_PORT_RANDOM_NUMBER=${W_UNICAST_PORT_RANDOM_NUMBER}"
         "R_UNICAST_PORT_RANDOM_NUMBER=${R_UNICAST_PORT_RANDOM_NUMBER}"
         "MULTICAST_PORT_RANDOM_NUMBER=${MULTICAST_PORT_RANDOM_NUMBER}"
+        $<$<BOOL:${OPENSSL_CONF}>:OPENSSL_CONF=${OPENSSL_CONF}>
+        IGNORE ${pkcs_filter}
         )
 endif(FASTRTPS_API_TESTS)
 
@@ -319,13 +386,21 @@ if(FASTDDS_PIM_API_TESTS)
     target_include_directories(BlackboxTests_DDS_PIM PRIVATE
         ${Asio_INCLUDE_DIR}
         api/dds-pim)
-    target_link_libraries(BlackboxTests_DDS_PIM fastrtps fastcdr foonathan_memory GTest::gtest)
+    target_link_libraries(BlackboxTests_DDS_PIM
+        fastrtps
+        fastcdr
+        foonathan_memory
+        GTest::gtest
+        $<$<BOOL:${LibP11_FOUND}>:eProsima_p11>  # $<TARGET_NAME_IF_EXISTS:eProsima_p11>
+        )
     add_blackbox_gtest(BlackboxTests_DDS_PIM SOURCES ${DDS_BLACKBOXTESTS_SOURCE}
         ENVIRONMENTS "CERTS_PATH=${PROJECT_SOURCE_DIR}/test/certs"
         "TOPIC_RANDOM_NUMBER=${TOPIC_RANDOM_NUMBER}"
         "W_UNICAST_PORT_RANDOM_NUMBER=${W_UNICAST_PORT_RANDOM_NUMBER}"
         "R_UNICAST_PORT_RANDOM_NUMBER=${R_UNICAST_PORT_RANDOM_NUMBER}"
         "MULTICAST_PORT_RANDOM_NUMBER=${MULTICAST_PORT_RANDOM_NUMBER}"
+        $<$<BOOL:${OPENSSL_CONF}>:OPENSSL_CONF=${OPENSSL_CONF}>
+        IGNORE ${pkcs_filter}
         )
 endif(FASTDDS_PIM_API_TESTS)
 
diff --git a/test/blackbox/api/dds-pim/PubSubReader.hpp b/test/blackbox/api/dds-pim/PubSubReader.hpp
index 0a27fbdbb40..7697a4b3667 100644
--- a/test/blackbox/api/dds-pim/PubSubReader.hpp
+++ b/test/blackbox/api/dds-pim/PubSubReader.hpp
@@ -349,26 +349,27 @@ class PubSubReader
                 participant_qos_,
                 &participant_listener_,
                 eprosima::fastdds::dds::StatusMask::none());
-            ASSERT_NE(participant_, nullptr);
-            ASSERT_TRUE(participant_->is_enabled());
         }
 
-        participant_guid_ = participant_->guid();
+        if (participant_ != nullptr)
+        {
+            participant_guid_ = participant_->guid();
 
-        type_.reset(new type_support());
+            type_.reset(new type_support());
 
-        // Register type
-        ASSERT_EQ(participant_->register_type(type_), ReturnCode_t::RETCODE_OK);
+            // Register type
+            ASSERT_EQ(participant_->register_type(type_), ReturnCode_t::RETCODE_OK);
 
-        // Create topic
-        topic_ =
-                participant_->create_topic(topic_name_, type_->getName(),
-                        eprosima::fastdds::dds::TOPIC_QOS_DEFAULT);
-        ASSERT_NE(topic_, nullptr);
-        ASSERT_TRUE(topic_->is_enabled());
+            // Create topic
+            topic_ =
+                    participant_->create_topic(topic_name_, type_->getName(),
+                            eprosima::fastdds::dds::TOPIC_QOS_DEFAULT);
+            ASSERT_NE(topic_, nullptr);
+            ASSERT_TRUE(topic_->is_enabled());
 
-        // Create publisher
-        createSubscriber();
+            // Create publisher
+            createSubscriber();
+        }
     }
 
     virtual void createSubscriber()
diff --git a/test/blackbox/api/fastrtps_deprecated/PubSubReader.hpp b/test/blackbox/api/fastrtps_deprecated/PubSubReader.hpp
index 2ae8b618bf0..a5e40ab3dff 100644
--- a/test/blackbox/api/fastrtps_deprecated/PubSubReader.hpp
+++ b/test/blackbox/api/fastrtps_deprecated/PubSubReader.hpp
@@ -301,22 +301,23 @@ class PubSubReader
 
         participant_ = eprosima::fastrtps::Domain::createParticipant(participant_attr, &participant_listener_);
 
-        ASSERT_NE(participant_, nullptr);
-
-        participant_guid_ = participant_->getGuid();
+        if (participant_ != nullptr)
+        {
+            participant_guid_ = participant_->getGuid();
 
-        // Register type
-        ASSERT_EQ(eprosima::fastrtps::Domain::registerType(participant_, &type_), true);
+            // Register type
+            ASSERT_EQ(eprosima::fastrtps::Domain::registerType(participant_, &type_), true);
 
-        //Create subscribe r
-        subscriber_ = eprosima::fastrtps::Domain::createSubscriber(participant_, subscriber_attr, &listener_);
+            //Create subscribe r
+            subscriber_ = eprosima::fastrtps::Domain::createSubscriber(participant_, subscriber_attr, &listener_);
 
-        if (subscriber_ != nullptr)
-        {
-            std::cout << "Created subscriber " << subscriber_->getGuid() << " for topic " <<
-                subscriber_attr_.topic.topicName << std::endl;
+            if (subscriber_ != nullptr)
+            {
+                std::cout << "Created subscriber " << subscriber_->getGuid() << " for topic " <<
+                    subscriber_attr_.topic.topicName << std::endl;
 
-            initialized_ = true;
+                initialized_ = true;
+            }
         }
     }
 
diff --git a/test/blackbox/common/BlackboxTestsSecurity.cpp b/test/blackbox/common/BlackboxTestsSecurity.cpp
index 9a51b2dfbd8..f8898919521 100644
--- a/test/blackbox/common/BlackboxTestsSecurity.cpp
+++ b/test/blackbox/common/BlackboxTestsSecurity.cpp
@@ -22,6 +22,9 @@
 #include "PubSubParticipant.hpp"
 
 #include <gtest/gtest.h>
+#include <fstream>
+#include <map>
+#include <algorithm>
 
 #include <fastrtps/xmlparser/XMLProfileManager.h>
 #include <fastdds/rtps/transport/shared_mem/SharedMemTransportDescriptor.h>
@@ -83,6 +86,151 @@ class Security : public testing::TestWithParam<communication_type>
 
 };
 
+
+class SecurityPkcs : public ::testing::Test
+{
+public:
+
+    struct HsmToken
+    {
+        std::string pin;
+        std::string id;
+        std::string serial;
+        std::map<std::string, std::string> urls;
+    };
+
+    static void create_hsm_token(
+            const char* token_id)
+    {
+        // Init the token
+        std::stringstream cmd;
+        cmd << "softhsm2-util --init-token --free --label " << token_id << " --pin " << hsm_token_pin
+            << " --so-pin " << hsm_token_pin << "";
+        ASSERT_EQ(0, std::system (cmd.str().c_str()));
+        tokens[token_id] = HsmToken();
+        tokens[token_id].pin = hsm_token_pin;
+        tokens[token_id].id = token_id;
+
+        // Get the serial number of the HSM slot
+        std::stringstream serial_stream;
+#ifdef _WIN32 // We are running windows
+        ASSERT_EQ(0,
+                std::system ("powershell -C \"softhsm2-util --show-slots | sls 'Serial number:\\s*([\\d\\w]+)' | " \
+                "% { $_.Matches.Groups[1].Value } | Out-File -FilePath softhsm_serial -Encoding ASCII\""));
+#else // We are running something with sh
+        ASSERT_EQ(0,
+                std::system ("softhsm2-util --show-slots | grep -oP 'Serial number:\\s*\\K(\\d|\\w)+' > softhsm_serial"));
+#endif // _WIN32
+        serial_stream << std::ifstream("softhsm_serial").rdbuf();
+        std::remove ("softhsm_serial");
+
+        // Read each serial number one by one
+        while (!serial_stream.eof())
+        {
+            std::string serial;
+            serial_stream >> serial;
+            if (!serial.empty())
+            {
+                if (tokens.end() == std::find_if(tokens.begin(), tokens.end(), [&serial](std::pair<const char* const,
+                        const HsmToken> t)
+                        {
+                            return t.second.serial == serial;
+                        }))
+                {
+                    tokens[token_id].serial = serial;
+                    break;
+                }
+            }
+        }
+    }
+
+    static void delete_hsm_token(
+            const char* token_id)
+    {
+        auto it = tokens.find(token_id);
+        if (it != tokens.end())
+        {
+            // Delete the token
+            std::stringstream cmd;
+            cmd << "softhsm2-util --delete-token --token " << token_id << " --pin " << hsm_token_pin
+                << " --so-pin " << hsm_token_pin << "";
+            ASSERT_EQ(0, std::system (cmd.str().c_str()));
+            tokens.erase(it);
+        }
+    }
+
+    static void SetUpTestCase()
+    {
+        // Init the tokens
+        create_hsm_token(hsm_token_id_no_pin);
+        create_hsm_token(hsm_token_id_url_pin);
+        create_hsm_token(hsm_token_id_env_pin);
+
+        // Add the keys to the tokens
+        import_private_key(std::string(certs_path) + "/mainsubkey.pem", hsm_mainsubkey_label,
+                "1A2B3C", hsm_token_id_no_pin);
+        import_private_key(std::string(certs_path) + "/mainpubkey.pem", hsm_mainpubkey_label,
+                "ABCDEF", hsm_token_id_no_pin);
+        import_private_key(std::string(certs_path) + "/mainsubkey.pem", hsm_mainsubkey_label,
+                "123456", hsm_token_id_url_pin);
+        import_private_key(std::string(certs_path) + "/mainpubkey.pem", hsm_mainpubkey_label,
+                "789ABC", hsm_token_id_url_pin);
+        import_private_key(std::string(certs_path) + "/mainsubkey.pem", hsm_mainsubkey_label,
+                "2468AC", hsm_token_id_env_pin);
+        import_private_key(std::string(certs_path) + "/mainpubkey.pem", hsm_mainpubkey_label,
+                "13579B", hsm_token_id_env_pin);
+    }
+
+    static void TearDownTestCase()
+    {
+        // delete the tokens
+        delete_hsm_token(hsm_token_id_no_pin);
+        delete_hsm_token(hsm_token_id_url_pin);
+        delete_hsm_token(hsm_token_id_env_pin);
+    }
+
+    static void import_private_key(
+            const std::string& key_file,
+            const char* key_label,
+            const char* key_id,
+            const char* token_id)
+    {
+        ASSERT_NE(tokens.end(), tokens.find(token_id));
+
+        std::stringstream cmd;
+        cmd << "softhsm2-util --import " << key_file << " --token " << token_id << " --label " << key_label
+            << " --pin " << hsm_token_pin << " --id " << key_id << "";
+        // Import the key
+        ASSERT_EQ(0,
+                std::system(cmd.str().c_str()));
+        // Construct the key URL
+        std::stringstream id_url;
+        for (unsigned int i = 0; i < strlen(key_id); i += 2)
+        {
+            id_url << "%" << key_id[i] << key_id[i + 1];
+        }
+
+        tokens[token_id].urls[key_label] = "pkcs11:model=SoftHSM%20v2;manufacturer=SoftHSM%20project;serial=" +
+                tokens[token_id].serial + ";token=" + token_id + ";id=" + id_url.str() + ";object=" + key_label +
+                ";type=private";
+    }
+
+    static const char* const hsm_token_id_no_pin;
+    static const char* const hsm_token_id_url_pin;
+    static const char* const hsm_token_id_env_pin;
+
+    static constexpr const char* hsm_token_pin = "1234";
+    static constexpr const char* hsm_mainsubkey_label = "mainsubkey";
+    static constexpr const char* hsm_mainpubkey_label = "mainpubkey";
+
+    static std::map<const char*, HsmToken> tokens;
+};
+
+std::map<const char*, SecurityPkcs::HsmToken> SecurityPkcs::tokens;
+const char* const SecurityPkcs::hsm_token_id_no_pin = "testing_token_no_pin";
+const char* const SecurityPkcs::hsm_token_id_url_pin = "testing_token_url_pin";
+const char* const SecurityPkcs::hsm_token_id_env_pin = "testing_token_env_pin";
+
 TEST_P(Security, BuiltinAuthenticationPlugin_PKIDH_validation_ok)
 {
     PubSubReader<HelloWorldType> reader(TEST_TOPIC_NAME);
@@ -2896,6 +3044,157 @@ TEST_P(Security, BuiltinAuthenticationAndAccessAndCryptoPlugin_Permissions_valid
     }
 }
 
+#if HAVE_LIBP11
+
+template <typename DataType>
+void prepare_pkcs11_nodes(
+        PubSubReader<DataType>& reader,
+        PubSubWriter<DataType>& writer,
+        const std::string& reader_private_key_url,
+        const std::string& writer_private_key_url)
+{
+    std::string governance_file("governance_helloworld_all_enable.smime");
+
+    // With no PIN, the load of the private key fails
+    PropertyPolicy pub_property_policy;
+    PropertyPolicy sub_property_policy;
+
+    sub_property_policy.properties().emplace_back(Property("dds.sec.auth.plugin",
+            "builtin.PKI-DH"));
+    sub_property_policy.properties().emplace_back(Property("dds.sec.auth.builtin.PKI-DH.identity_ca",
+            "file://" + std::string(certs_path) + "/maincacert.pem"));
+    sub_property_policy.properties().emplace_back(Property("dds.sec.auth.builtin.PKI-DH.identity_certificate",
+            "file://" + std::string(certs_path) + "/mainsubcert.pem"));
+    sub_property_policy.properties().emplace_back(Property("dds.sec.auth.builtin.PKI-DH.private_key",
+            reader_private_key_url));
+    sub_property_policy.properties().emplace_back(Property("dds.sec.crypto.plugin",
+            "builtin.AES-GCM-GMAC"));
+    sub_property_policy.properties().emplace_back(Property("dds.sec.access.plugin",
+            "builtin.Access-Permissions"));
+    sub_property_policy.properties().emplace_back(Property(
+                "dds.sec.access.builtin.Access-Permissions.permissions_ca",
+                "file://" + std::string(certs_path) + "/maincacert.pem"));
+    sub_property_policy.properties().emplace_back(Property("dds.sec.access.builtin.Access-Permissions.governance",
+            "file://" + std::string(certs_path) + "/" + governance_file));
+    sub_property_policy.properties().emplace_back(Property("dds.sec.access.builtin.Access-Permissions.permissions",
+            "file://" + std::string(certs_path) + "/permissions_helloworld.smime"));
+
+    reader.history_depth(10).
+            reliability(eprosima::fastrtps::RELIABLE_RELIABILITY_QOS).
+            property_policy(sub_property_policy).init();
+
+    pub_property_policy.properties().emplace_back(Property("dds.sec.auth.plugin",
+            "builtin.PKI-DH"));
+    pub_property_policy.properties().emplace_back(Property("dds.sec.auth.builtin.PKI-DH.identity_ca",
+            "file://" + std::string(certs_path) + "/maincacert.pem"));
+    pub_property_policy.properties().emplace_back(Property("dds.sec.auth.builtin.PKI-DH.identity_certificate",
+            "file://" + std::string(certs_path) + "/mainpubcert.pem"));
+    pub_property_policy.properties().emplace_back(Property("dds.sec.auth.builtin.PKI-DH.private_key",
+            writer_private_key_url));
+    pub_property_policy.properties().emplace_back(Property("dds.sec.crypto.plugin",
+            "builtin.AES-GCM-GMAC"));
+    pub_property_policy.properties().emplace_back(Property("dds.sec.access.plugin",
+            "builtin.Access-Permissions"));
+    pub_property_policy.properties().emplace_back(Property(
+                "dds.sec.access.builtin.Access-Permissions.permissions_ca",
+                "file://" + std::string(certs_path) + "/maincacert.pem"));
+    pub_property_policy.properties().emplace_back(Property("dds.sec.access.builtin.Access-Permissions.governance",
+            "file://" + std::string(certs_path) + "/" + governance_file));
+    pub_property_policy.properties().emplace_back(Property("dds.sec.access.builtin.Access-Permissions.permissions",
+            "file://" + std::string(certs_path) + "/permissions_helloworld.smime"));
+
+    writer.history_depth(10).
+            property_policy(pub_property_policy).init();
+}
+
+TEST_F(SecurityPkcs, BuiltinAuthenticationAndAccessAndCryptoPlugin_pkcs11_key)
+{
+    {
+        PubSubReader<HelloWorldType> reader("HelloWorldTopic");
+        PubSubWriter<HelloWorldType> writer("HelloWorldTopic");
+        prepare_pkcs11_nodes(reader, writer,
+                tokens[hsm_token_id_no_pin].urls[hsm_mainsubkey_label],
+                tokens[hsm_token_id_no_pin].urls[hsm_mainpubkey_label]);
+
+        ASSERT_FALSE(reader.isInitialized());
+        ASSERT_FALSE(writer.isInitialized());
+    }
+    {
+        PubSubReader<HelloWorldType> reader("HelloWorldTopic");
+        PubSubWriter<HelloWorldType> writer("HelloWorldTopic");
+        prepare_pkcs11_nodes(reader, writer,
+                tokens[hsm_token_id_url_pin].urls[hsm_mainsubkey_label] + "?pin-value=" + hsm_token_pin,
+                tokens[hsm_token_id_url_pin].urls[hsm_mainpubkey_label] + "?pin-value=" + hsm_token_pin);
+
+        ASSERT_TRUE(reader.isInitialized());
+        ASSERT_TRUE(writer.isInitialized());
+
+        // Wait for authorization
+        reader.waitAuthorized();
+        writer.waitAuthorized();
+
+        // Wait for discovery.
+        writer.wait_discovery();
+        reader.wait_discovery();
+
+        auto data = default_helloworld_data_generator();
+
+        reader.startReception(data);
+
+        // Send data
+        writer.send(data);
+        // In this test all data should be sent.
+        ASSERT_TRUE(data.empty());
+        // Block reader until reception finished or timeout.
+        reader.block_for_all();
+
+    }
+    {
+        // Set the PIN on the environment variable
+#ifdef _WIN32
+        _putenv_s("FASTDDS_PKCS11_PIN", "1234");
+#else
+        setenv("FASTDDS_PKCS11_PIN", "1234", 1);
+#endif // ifdef _WIN32
+
+        PubSubReader<HelloWorldType> reader("HelloWorldTopic");
+        PubSubWriter<HelloWorldType> writer("HelloWorldTopic");
+        prepare_pkcs11_nodes(reader, writer,
+                tokens[hsm_token_id_env_pin].urls[hsm_mainsubkey_label],
+                tokens[hsm_token_id_env_pin].urls[hsm_mainpubkey_label]);
+
+        ASSERT_TRUE(reader.isInitialized());
+        ASSERT_TRUE(writer.isInitialized());
+
+        // Wait for authorization
+        reader.waitAuthorized();
+        writer.waitAuthorized();
+
+        // Wait for discovery.
+        writer.wait_discovery();
+        reader.wait_discovery();
+
+        auto data = default_helloworld_data_generator();
+
+        reader.startReception(data);
+
+        // Send data
+        writer.send(data);
+        // In this test all data should be sent.
+        ASSERT_TRUE(data.empty());
+        // Block reader until reception finished or timeout.
+        reader.block_for_all();
+
+        // unset the PIN environment variable for the next round
+#ifdef _WIN32
+        _putenv_s("FASTDDS_PKCS11_PIN", "");
+#else
+        unsetenv("FASTDDS_PKCS11_PIN");
+#endif // ifdef _WIN32
+    }
+}
+#endif // HAVE_LIBP11
+
 static void BuiltinAuthenticationAndAccessAndCryptoPlugin_Permissions_validation_ok_common(
         PubSubReader<HelloWorldType>& reader,
         PubSubWriter<HelloWorldType>& writer,
diff --git a/test/unittest/dds/publisher/CMakeLists.txt b/test/unittest/dds/publisher/CMakeLists.txt
index 3b5305eb46f..6efdb519daf 100644
--- a/test/unittest/dds/publisher/CMakeLists.txt
+++ b/test/unittest/dds/publisher/CMakeLists.txt
@@ -235,6 +235,7 @@ set(DATAWRITERTESTS_SOURCE DataWriterTests.cpp
             ${PROJECT_SOURCE_DIR}/src/cpp/rtps/security/logging/Logging.cpp
             ${PROJECT_SOURCE_DIR}/src/cpp/rtps/security/SecurityManager.cpp
             ${PROJECT_SOURCE_DIR}/src/cpp/rtps/security/SecurityPluginFactory.cpp
+            ${PROJECT_SOURCE_DIR}/src/cpp/security/artifact_providers/Pkcs11Provider.cpp
             ${PROJECT_SOURCE_DIR}/src/cpp/security/authentication/PKIDH.cpp
             ${PROJECT_SOURCE_DIR}/src/cpp/security/accesscontrol/Permissions.cpp
             ${PROJECT_SOURCE_DIR}/src/cpp/security/cryptography/AESGCMGMAC.cpp
@@ -242,6 +243,7 @@ set(DATAWRITERTESTS_SOURCE DataWriterTests.cpp
             ${PROJECT_SOURCE_DIR}/src/cpp/security/cryptography/AESGCMGMAC_KeyFactory.cpp
             ${PROJECT_SOURCE_DIR}/src/cpp/security/cryptography/AESGCMGMAC_Transform.cpp
             ${PROJECT_SOURCE_DIR}/src/cpp/security/cryptography/AESGCMGMAC_Types.cpp
+            ${PROJECT_SOURCE_DIR}/src/cpp/security/artifact_providers/FileProvider.cpp
             ${PROJECT_SOURCE_DIR}/src/cpp/security/authentication/PKIIdentityHandle.cpp
             ${PROJECT_SOURCE_DIR}/src/cpp/security/authentication/PKIHandshakeHandle.cpp
             ${PROJECT_SOURCE_DIR}/src/cpp/security/accesscontrol/AccessPermissionsHandle.cpp
@@ -318,6 +320,7 @@ target_link_libraries(DataWriterTests fastcdr foonathan_memory
     $<$<BOOL:${LINK_SSL}>:OpenSSL::SSL$<SEMICOLON>OpenSSL::Crypto>
     $<$<BOOL:${WIN32}>:iphlpapi$<SEMICOLON>Shlwapi>
     ${THIRDPARTY_BOOST_LINK_LIBS}
+    $<$<BOOL:${LibP11_FOUND}>:eProsima_p11>  # $<TARGET_NAME_IF_EXISTS:eProsima_p11>
     eProsima_atomic
     )
 if(MSVC OR MSVC_IDE)
diff --git a/test/unittest/security/accesscontrol/CMakeLists.txt b/test/unittest/security/accesscontrol/CMakeLists.txt
index 2e84c4456ef..a13c4695f42 100644
--- a/test/unittest/security/accesscontrol/CMakeLists.txt
+++ b/test/unittest/security/accesscontrol/CMakeLists.txt
@@ -56,10 +56,13 @@ add_executable(AccessControlTests ${COMMON_SOURCES_ACCESS_CONTROL_TEST_SOURCE}
     ${PROJECT_SOURCE_DIR}/src/cpp/security/accesscontrol/GovernanceParser.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/security/accesscontrol/Permissions.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/security/accesscontrol/PermissionsParser.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/security/artifact_providers/FileProvider.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/security/artifact_providers/Pkcs11Provider.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/utils/md5.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/utils/IPFinder.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/utils/IPLocator.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/utils/StringMatching.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/utils/SystemInfo.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/publisher/qos/WriterQos.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/AccessControlTests.cpp)
 
@@ -91,6 +94,7 @@ target_link_libraries(AccessControlTests
     foonathan_memory
     $<$<BOOL:${WIN32}>:ws2_32>
     ${TINYXML2_LIBRARY}
+    $<$<BOOL:${LibP11_FOUND}>:eProsima_p11>  # $<TARGET_NAME_IF_EXISTS:eProsima_p11>
     )
 
 if(MSVC OR MSVC_IDE)
diff --git a/test/unittest/security/authentication/CMakeLists.txt b/test/unittest/security/authentication/CMakeLists.txt
index 50037265c63..f30a76e3960 100644
--- a/test/unittest/security/authentication/CMakeLists.txt
+++ b/test/unittest/security/authentication/CMakeLists.txt
@@ -44,9 +44,12 @@ add_executable(BuiltinPKIDH ${COMMON_SOURCES_AUTH_PLUGIN_TEST_SOURCE}
     ${PROJECT_SOURCE_DIR}/src/cpp/security/authentication/PKIDH.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/security/authentication/PKIIdentityHandle.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/security/authentication/PKIHandshakeHandle.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/security/artifact_providers/FileProvider.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/security/artifact_providers/Pkcs11Provider.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/utils/md5.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/utils/IPFinder.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/utils/IPLocator.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/utils/SystemInfo.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/BuiltinPKIDHTests.cpp)
 target_compile_definitions(BuiltinPKIDH PRIVATE FASTRTPS_NO_LIB
     BOOST_ASIO_STANDALONE
@@ -61,7 +64,14 @@ target_include_directories(BuiltinPKIDH PRIVATE
     ${PROJECT_SOURCE_DIR}/include ${PROJECT_BINARY_DIR}/include
     ${PROJECT_SOURCE_DIR}/src/cpp
     )
-target_link_libraries(BuiltinPKIDH GTest::gtest ${OPENSSL_LIBRARIES} fastcdr foonathan_memory $<$<BOOL:${WIN32}>:ws2_32>)
+target_link_libraries(BuiltinPKIDH
+    GTest::gtest
+    ${OPENSSL_LIBRARIES}
+    fastcdr
+    foonathan_memory
+    $<$<BOOL:${WIN32}>:ws2_32>
+    $<$<BOOL:${LibP11_FOUND}>:eProsima_p11>  # $<TARGET_NAME_IF_EXISTS:eProsima_p11>
+    )
 add_gtest(BuiltinPKIDH
     SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/BuiltinPKIDHTests.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/AuthenticationPluginTests.hpp
diff --git a/test/unittest/statistics/dds/CMakeLists.txt b/test/unittest/statistics/dds/CMakeLists.txt
index 4ec673f91d4..fcc8c98a2a1 100644
--- a/test/unittest/statistics/dds/CMakeLists.txt
+++ b/test/unittest/statistics/dds/CMakeLists.txt
@@ -280,6 +280,7 @@ if (SQLITE3_SUPPORT AND FASTDDS_STATISTICS)
             ${PROJECT_SOURCE_DIR}/src/cpp/rtps/security/logging/Logging.cpp
             ${PROJECT_SOURCE_DIR}/src/cpp/rtps/security/SecurityManager.cpp
             ${PROJECT_SOURCE_DIR}/src/cpp/rtps/security/SecurityPluginFactory.cpp
+            ${PROJECT_SOURCE_DIR}/src/cpp/security/artifact_providers/FileProvider.cpp
             ${PROJECT_SOURCE_DIR}/src/cpp/security/authentication/PKIDH.cpp
             ${PROJECT_SOURCE_DIR}/src/cpp/security/accesscontrol/Permissions.cpp
             ${PROJECT_SOURCE_DIR}/src/cpp/security/cryptography/AESGCMGMAC.cpp
diff --git a/test/unittest/transport/TCPv4Tests.cpp b/test/unittest/transport/TCPv4Tests.cpp
index 43780e9a8a0..e46ee0580e7 100644
--- a/test/unittest/transport/TCPv4Tests.cpp
+++ b/test/unittest/transport/TCPv4Tests.cpp
@@ -533,11 +533,11 @@ TEST_F(TCPv4Tests, send_and_receive_between_secure_ports_client_verifies)
                                     (std::chrono::steady_clock::now() + std::chrono::microseconds(100)));
                     while (!sent)
                     {
-                        Locators input_begin(locator_list.begin());
-                        Locators input_end(locator_list.end());
+                        Locators l_input_begin(locator_list.begin());
+                        Locators l_input_end(locator_list.end());
 
                         sent =
-                                send_resource_list.at(0)->send(message, 5, &input_begin, &input_end,
+                                send_resource_list.at(0)->send(message, 5, &l_input_begin, &l_input_end,
                                         (std::chrono::steady_clock::now() + std::chrono::microseconds(100)));
                         std::this_thread::sleep_for(std::chrono::milliseconds(100));
                     }
@@ -633,11 +633,11 @@ TEST_F(TCPv4Tests, send_and_receive_between_secure_ports_server_verifies)
                                     (std::chrono::steady_clock::now() + std::chrono::microseconds(100)));
                     while (!sent)
                     {
-                        Locators input_begin(locator_list.begin());
-                        Locators input_end(locator_list.end());
+                        Locators l_input_begin(locator_list.begin());
+                        Locators l_input_end(locator_list.end());
 
                         sent =
-                                send_resource_list.at(0)->send(message, 5,  &input_begin, &input_end,
+                                send_resource_list.at(0)->send(message, 5,  &l_input_begin, &l_input_end,
                                         (std::chrono::steady_clock::now() + std::chrono::microseconds(100)));
                         std::this_thread::sleep_for(std::chrono::milliseconds(100));
                     }
@@ -735,11 +735,11 @@ TEST_F(TCPv4Tests, send_and_receive_between_both_secure_ports)
                                     (std::chrono::steady_clock::now() + std::chrono::microseconds(100)));
                     while (!sent)
                     {
-                        Locators input_begin(locator_list.begin());
-                        Locators input_end(locator_list.end());
+                        Locators l_input_begin(locator_list.begin());
+                        Locators l_input_end(locator_list.end());
 
                         sent =
-                                send_resource_list.at(0)->send(message, 5, &input_begin, &input_end,
+                                send_resource_list.at(0)->send(message, 5, &l_input_begin, &l_input_end,
                                         (std::chrono::steady_clock::now() + std::chrono::microseconds(100)));
                         std::this_thread::sleep_for(std::chrono::milliseconds(100));
                     }
@@ -839,11 +839,11 @@ TEST_F(TCPv4Tests, send_and_receive_between_both_secure_ports_untrusted)
                     int count = 0;
                     while (!sent && count < 30)
                     {
-                        Locators input_begin(locator_list.begin());
-                        Locators input_end(locator_list.end());
+                        Locators l_input_begin(locator_list.begin());
+                        Locators l_input_end(locator_list.end());
 
                         sent =
-                                send_resource_list.at(0)->send(message, 5, &input_begin, &input_end,
+                                send_resource_list.at(0)->send(message, 5, &l_input_begin, &l_input_end,
                                         (std::chrono::steady_clock::now() + std::chrono::microseconds(100)));
                         std::this_thread::sleep_for(std::chrono::milliseconds(100));
                         ++count;
@@ -943,11 +943,11 @@ TEST_F(TCPv4Tests, send_and_receive_between_secure_clients_1)
                                     (std::chrono::steady_clock::now() + std::chrono::microseconds(100)));
                     while (!sent)
                     {
-                        Locators input_begin(locator_list.begin());
-                        Locators input_end(locator_list.end());
+                        Locators l_input_begin(locator_list.begin());
+                        Locators l_input_end(locator_list.end());
 
                         sent =
-                                send_resource_list.at(0)->send(message, 5, &input_begin, &input_end,
+                                send_resource_list.at(0)->send(message, 5, &l_input_begin, &l_input_end,
                                         (std::chrono::steady_clock::now() + std::chrono::microseconds(100)));
                         std::this_thread::sleep_for(std::chrono::milliseconds(100));
                     }
@@ -1132,10 +1132,10 @@ TEST_F(TCPv4Tests, send_and_receive_between_secure_ports_untrusted_server)
                     int count = 0;
                     while (!sent && count < 30)
                     {
-                        Locators input_begin(locator_list.begin());
-                        Locators input_end(locator_list.end());
+                        Locators l_input_begin(locator_list.begin());
+                        Locators l_input_end(locator_list.end());
                         sent =
-                                send_resource_list.at(0)->send(message, 5, &input_begin, &input_end,
+                                send_resource_list.at(0)->send(message, 5, &l_input_begin, &l_input_end,
                                         (std::chrono::steady_clock::now() + std::chrono::microseconds(100)));
                         std::this_thread::sleep_for(std::chrono::milliseconds(100));
                         ++count;