Skip to content

Commit d82d23a

Browse files
Add pkcs11 support to get_security_files (#66)
* Adding overload of get_security_files. * Implement changes to support .p11 files. * Security tests converted into TEST_P * Adding pkcs11 specific tests. Signed-off-by: Miguel Company <miguelcompany@eprosima.com>
1 parent ae7df87 commit d82d23a

3 files changed

Lines changed: 391 additions & 45 deletions

File tree

rmw_dds_common/include/rmw_dds_common/security.hpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,38 @@ bool get_security_files(
5252
const std::string & prefix, const std::string & secure_root,
5353
std::unordered_map<std::string, std::string> & result);
5454

55+
/// Get the set of security files in a security enclave.
56+
/**
57+
* This function will look through the passed in 'secure root'
58+
* for a set of required filenames that must be in the enclave.
59+
* If any of the required filenames are missing, the 'result'
60+
* will be empty and the function will return false.
61+
* If all of the required filenames are present, then this function
62+
* will fill in the 'result' map with a key-value pair of
63+
* friendy name -> filename. If the prefix is not empty, then
64+
* the prefix will be applied to the filename.
65+
*
66+
* The friendly names that this function will currently fill in are:
67+
* IDENTITY_CA
68+
* CERTIFICATE
69+
* PRIVATE_KEY
70+
* PERMISSIONS_CA
71+
* GOVERNANCE
72+
* PERMISSIONS
73+
*
74+
* \param[in] supports_pkcs11 Whether the RMW has support for PKCS#11 URIs.
75+
* \param[in] prefix An optional prefix to apply to the filenames when storing them.
76+
* \param[in] secure_root The path to the security enclave to look at.
77+
* \param[out] result The map where the friendly name -> filename pairs are stored.
78+
* \return `true` if all required files exist in the security enclave, `false` otherwise.
79+
*/
80+
RMW_DDS_COMMON_PUBLIC
81+
bool get_security_files(
82+
bool supports_pkcs11,
83+
const std::string & prefix,
84+
const std::string & secure_root,
85+
std::unordered_map<std::string, std::string> & result);
86+
5587
} // namespace rmw_dds_common
5688

5789
#endif // RMW_DDS_COMMON__SECURITY_HPP_

rmw_dds_common/src/security.cpp

Lines changed: 99 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,41 +13,127 @@
1313
// limitations under the License.
1414

1515
#include <filesystem>
16+
#include <fstream>
17+
#include <functional>
1618
#include <string>
1719
#include <utility>
1820
#include <unordered_map>
21+
#include <vector>
1922

2023
#include "rmw_dds_common/security.hpp"
2124

2225
namespace rmw_dds_common
2326
{
2427

28+
// Processor for security attributes with FILE URI
29+
static bool process_file_uri_security_file(
30+
bool /*supports_pkcs11*/,
31+
const std::string & prefix,
32+
const std::filesystem::path & full_path,
33+
std::string & result)
34+
{
35+
if (!std::filesystem::is_regular_file(full_path)) {
36+
return false;
37+
}
38+
result = prefix + full_path.generic_string();
39+
return true;
40+
}
41+
42+
// Processor for security attributes with PKCS#11 URI
43+
static bool process_pkcs_uri_security_file(
44+
bool supports_pkcs11,
45+
const std::string & /*prefix*/,
46+
const std::filesystem::path & full_path,
47+
std::string & result)
48+
{
49+
if (!supports_pkcs11) {
50+
return false;
51+
}
52+
53+
const std::string p11_prefix("pkcs11:");
54+
55+
std::ifstream ifs(full_path);
56+
if (!ifs.is_open()) {
57+
return false;
58+
}
59+
60+
if (!(ifs >> result)) {
61+
return false;
62+
}
63+
if (result.find(p11_prefix) != 0) {
64+
return false;
65+
}
66+
67+
return true;
68+
}
69+
2570
bool get_security_files(
2671
const std::string & prefix, const std::string & secure_root,
2772
std::unordered_map<std::string, std::string> & result)
2873
{
29-
const std::unordered_map<std::string, std::string> required_files{
30-
{"IDENTITY_CA", "identity_ca.cert.pem"},
31-
{"CERTIFICATE", "cert.pem"},
32-
{"PRIVATE_KEY", "key.pem"},
33-
{"PERMISSIONS_CA", "permissions_ca.cert.pem"},
34-
{"GOVERNANCE", "governance.p7s"},
35-
{"PERMISSIONS", "permissions.p7s"},
74+
return get_security_files(false, prefix, secure_root, result);
75+
}
76+
77+
bool get_security_files(
78+
bool supports_pkcs11,
79+
const std::string & prefix,
80+
const std::string & secure_root,
81+
std::unordered_map<std::string, std::string> & result)
82+
{
83+
using std::placeholders::_1;
84+
using std::placeholders::_2;
85+
using std::placeholders::_3;
86+
using std::placeholders::_4;
87+
using security_file_processor =
88+
std::function<bool (bool, const std::string &, const std::filesystem::path &, std::string &)>;
89+
using processor_vector =
90+
std::vector<std::pair<std::string, security_file_processor>>;
91+
92+
// Key: the security attribute
93+
// Value: ordered sequence of pairs. Each pair contains one possible file name
94+
// for the attribute and the corresponding processor method
95+
// Pairs are ordered by priority: the first one matching is used.
96+
const std::unordered_map<std::string, processor_vector> required_files{
97+
{"IDENTITY_CA", {
98+
{"identity_ca.cert.p11", std::bind(process_pkcs_uri_security_file, _1, _2, _3, _4)},
99+
{"identity_ca.cert.pem", std::bind(process_file_uri_security_file, _1, _2, _3, _4)}}},
100+
{"CERTIFICATE", {
101+
{"cert.p11", std::bind(process_pkcs_uri_security_file, _1, _2, _3, _4)},
102+
{"cert.pem", std::bind(process_file_uri_security_file, _1, _2, _3, _4)}}},
103+
{"PRIVATE_KEY", {
104+
{"key.p11", std::bind(process_pkcs_uri_security_file, _1, _2, _3, _4)},
105+
{"key.pem", std::bind(process_file_uri_security_file, _1, _2, _3, _4)}}},
106+
{"PERMISSIONS_CA", {
107+
{"permissions_ca.cert.p11", std::bind(process_pkcs_uri_security_file, _1, _2, _3, _4)},
108+
{"permissions_ca.cert.pem", std::bind(process_file_uri_security_file, _1, _2, _3, _4)}}},
109+
{"GOVERNANCE", {
110+
{"governance.p7s", std::bind(process_file_uri_security_file, _1, _2, _3, _4)}}},
111+
{"PERMISSIONS", {
112+
{"permissions.p7s", std::bind(process_file_uri_security_file, _1, _2, _3, _4)}}},
36113
};
37114

38115
const std::unordered_map<std::string, std::string> optional_files{
39116
{"CRL", "crl.pem"},
40117
};
41118

42-
for (const std::pair<const std::string, std::string> & el : required_files) {
43-
std::filesystem::path full_path(secure_root);
44-
full_path /= el.second;
45-
if (!std::filesystem::is_regular_file(full_path)) {
119+
for (const std::pair<const std::string,
120+
std::vector<std::pair<std::string, security_file_processor>>> & el : required_files)
121+
{
122+
std::string attribute_value;
123+
bool processed = false;
124+
for (auto & proc : el.second) {
125+
std::filesystem::path full_path(secure_root);
126+
full_path /= proc.first;
127+
if (proc.second(supports_pkcs11, prefix, full_path, attribute_value)) {
128+
processed = true;
129+
break;
130+
}
131+
}
132+
if (!processed) {
46133
result.clear();
47134
return false;
48135
}
49-
50-
result[el.first] = prefix + full_path.generic_string();
136+
result[el.first] = attribute_value;
51137
}
52138

53139
for (const std::pair<const std::string, std::string> & el : optional_files) {

0 commit comments

Comments
 (0)