From b64765e37f7c53b0dde0e140ed2198bf00d5ddf1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Luis=20Bueno=20L=C3=B3pez?= <69244257+JLBuenoLopez-eProsima@users.noreply.github.com> Date: Wed, 19 Jan 2022 10:34:44 +0100 Subject: [PATCH] Add support for PKCS#11 in security files (#5) * Add support for PKCS#11 in security files In addition to *.pem files containing the key or certificate, adds support for *.p11 files that contain the PKCS#11 URI of the key or certificate in an HSM. Signed-off-by: Iker Luengo * linters Signed-off-by: Iker Luengo Co-authored-by: Iker Luengo --- rmw_fastrtps_shared_cpp/src/participant.cpp | 119 +++++++++++++++++++- 1 file changed, 118 insertions(+), 1 deletion(-) diff --git a/rmw_fastrtps_shared_cpp/src/participant.cpp b/rmw_fastrtps_shared_cpp/src/participant.cpp index 1c9ee267a..4db213262 100644 --- a/rmw_fastrtps_shared_cpp/src/participant.cpp +++ b/rmw_fastrtps_shared_cpp/src/participant.cpp @@ -17,6 +17,9 @@ #include #include #include +#include +#include +#include #include "fastdds/dds/core/status/StatusMask.hpp" #include "fastdds/dds/domain/DomainParticipantFactory.hpp" @@ -33,6 +36,7 @@ #include "fastdds/rtps/transport/shared_mem/SharedMemTransportDescriptor.h" #include "rcpputils/scope_exit.hpp" +#include "rcpputils/filesystem_helper.hpp" #include "rcutils/env.h" #include "rcutils/filesystem.h" @@ -140,6 +144,119 @@ __create_participant( return participant_info; } +// Processor for security attributes with FILE URI +bool process_file_uri_security_file( + const std::string & prefix, const rcpputils::fs::path & full_path, + std::string & result) +{ + if (!full_path.is_regular_file()) { + return false; + } + result = prefix + full_path.string(); + return true; +} + +// Processor for security attributes with PKCS#11 URI +bool process_pkcs_uri_security_file( + const std::string & /*prefix*/, const rcpputils::fs::path & full_path, + std::string & result) +{ + const std::string p11_prefix("pkcs11:"); + + std::ifstream ifs(full_path.string()); + if (!ifs.is_open()) { + return false; + } + + if (!(ifs >> result)) { + return false; + } + if (result.find(p11_prefix) != 0) { + return false; + } + + return true; +} + +bool get_security_files( + const std::string & prefix, const std::string & secure_root, + std::unordered_map & result) +{ + using std::placeholders::_1; + using std::placeholders::_2; + using std::placeholders::_3; + using security_file_processor = + std::function; + using processor_vector = + std::vector>; + + // Key: the security attribute + // Value: ordered sequence of pairs. Each pair contains one possible file name + // for the attribute and the corresponding processor method + // Pairs are ordered by priority: the first one matching is used. + const std::unordered_map required_files{ + {"IDENTITY_CA", { + {"identity_ca.cert.pem", std::bind(process_file_uri_security_file, _1, _2, _3)}, + {"identity_ca.cert.p11", std::bind(process_pkcs_uri_security_file, _1, _2, _3)}}}, + {"CERTIFICATE", { + {"cert.pem", std::bind(process_file_uri_security_file, _1, _2, _3)}, + {"cert.p11", std::bind(process_pkcs_uri_security_file, _1, _2, _3)}}}, + {"PRIVATE_KEY", { + {"key.pem", std::bind(process_file_uri_security_file, _1, _2, _3)}, + {"key.p11", std::bind(process_pkcs_uri_security_file, _1, _2, _3)}}}, + {"PERMISSIONS_CA", { + {"permissions_ca.cert.pem", std::bind(process_file_uri_security_file, _1, _2, _3)}, + {"permissions_ca.cert.p11", std::bind(process_pkcs_uri_security_file, _1, _2, _3)}}}, + {"GOVERNANCE", { + {"governance.p7s", std::bind(process_file_uri_security_file, _1, _2, _3)}}}, + {"PERMISSIONS", { + {"permissions.p7s", std::bind(process_file_uri_security_file, _1, _2, _3)}}}, + }; + + const std::unordered_map optional_files{ + {"CRL", { + {"crl.pem", std::bind(process_file_uri_security_file, _1, _2, _3)}}} + }; + + for (const std::pair>> & el : required_files) + { + std::string attribute_value; + bool processed = false; + for (auto & proc : el.second) { + rcpputils::fs::path full_path(secure_root); + full_path /= proc.first; + if (proc.second(prefix, full_path, attribute_value)) { + processed = true; + break; + } + } + if (!processed) { + result.clear(); + return false; + } + result[el.first] = attribute_value; + } + + for (const std::pair & el : optional_files) { + std::string attribute_value; + bool processed = false; + for (auto & proc : el.second) { + rcpputils::fs::path full_path(secure_root); + full_path /= proc.first; + if (proc.second(prefix, full_path, attribute_value)) { + processed = true; + break; + } + } + if (processed) { + result[el.first] = attribute_value; + } + } + + return true; +} + CustomParticipantInfo * rmw_fastrtps_shared_cpp::create_participant( const char * identifier, @@ -232,7 +349,7 @@ rmw_fastrtps_shared_cpp::create_participant( // if security_root_path provided, try to find the key and certificate files #if HAVE_SECURITY std::unordered_map security_files_paths; - if (rmw_dds_common::get_security_files( + if (get_security_files( "file://", security_options->security_root_path, security_files_paths)) { eprosima::fastrtps::rtps::PropertyPolicy property_policy;