Newer
Older
#include "converter.hh"
#include "loggers.hh"
certificates_loader * certificates_loader::instance = nullptr;
certificates_loader::certificates_loader(): _certificateExt{".crt"}, _privateKeyExt{".pkey"}, _publicKeysExt{".vkey"}, _publicCompKeysExt(".cvkey"), _privateEncKeyExt{".pekey"}, _publicEncKeysExt{".vekey"}, _hashedidDigestExt{".hashedid"}, _issuerDigestExt{".issuer"}, _full_path(), _is_cache_initialized{false}, _directory_filter{".svn", "._.DS_Store", ".DS_Store"} {
loggers::get_instance().log(">>> certificates_loader::certificates_loader");
int certificates_loader::build_path(const std::string& p_root_directory) {
loggers::get_instance().log(">>> certificates_loader::build_path: '%s'", p_root_directory.c_str());
// Build full path
if (!p_root_directory.empty()) {
_full_path = p_root_directory;
if (!std::experimental::filesystem::exists(_full_path) || !std::experimental::filesystem::is_directory(_full_path)) { // FIXME Coredump when app hasn't the rights to create the directory!!!!
// Create directory
if (!std::experimental::filesystem::create_directory(_full_path)) {
_full_path = "./";
} else { // Set rights for all users
std::experimental::filesystem::permissions(_full_path, std::experimental::filesystem::perms::add_perms | std::experimental::filesystem::perms::owner_all | std::experimental::filesystem::perms::group_all | std::experimental::filesystem::perms::others_all);
std::experimental::filesystem::canonical(_full_path);
loggers::get_instance().log("certificates_loader::build_path: full path: %s", _full_path.string().c_str());
if (!std::experimental::filesystem::exists(_full_path)) {
loggers::get_instance().warning("certificates_loader::build_path: Invalid path");
_full_path.clear();
return -1;
}
return 0;
} // End of method build_path
int certificates_loader::load_certificates(std::map<std::string, std::unique_ptr<security_db_record> >& p_certificates, std::map<std::vector<unsigned char>, std::string>& p_hashed_id8s) {
loggers::get_instance().log(">>> certificates_loader::load_certificates");
// Sanity check
if (_is_cache_initialized) {
return 0;
}
std::set<std::experimental::filesystem::path> files;
loggers::get_instance().warning("certificates_loader::load_certificates: Failed to build the list of certificate files");
if (build_certificates_cache(files, p_certificates, p_hashed_id8s) == -1) {
loggers::get_instance().warning("certificates_loader::load_certificates: Failed to build the certificate cache");
return -1;
}
_is_cache_initialized = true;
return 0;
} // End of method load_certificates
int certificates_loader::retrieve_certificates_list(std::set<std::experimental::filesystem::path>& p_files) {
loggers::get_instance().log(">>> certificates_loader::retrieve_certificates_list");
// Walk through directories
std::set<std::experimental::filesystem::path> folders;
for (const std::experimental::filesystem::directory_entry it : std::experimental::filesystem::recursive_directory_iterator(_full_path.string())) {
loggers::get_instance().log("certificates_loader::retrieve_certificates_list: Processing directory '%s'", it.path().string().c_str());
if (std::experimental::filesystem::is_directory(it)) {
std::set<std::string>::const_iterator i = _directory_filter.find(it.path().filename());
if (i != _directory_filter.cend()) {
loggers::get_instance().log("certificates_loader::retrieve_certificates_list: Exclude directory '%s'", it.path().string().c_str());
continue;
}
loggers::get_instance().log("certificates_loader::retrieve_certificates_list: Add directory '%s'", it.path().string().c_str());
folders.insert(it.path());
}
} // End of 'for' statement
if (folders.size() == 0) {
loggers::get_instance().warning("certificates_loader::retrieve_certificates_list: No folder after filtering");
std::set<std::string> extensions_filter{ _certificateExt, _privateKeyExt, _publicKeysExt, _publicCompKeysExt, _privateEncKeyExt, _publicEncKeysExt, _hashedidDigestExt, _issuerDigestExt };
for (std::set<std::experimental::filesystem::path>::const_reverse_iterator f = folders.crbegin(); f != folders.crend(); ++f) {
loggers::get_instance().log("certificates_loader::retrieve_certificates_list: Processing directory '%s'", f->string().c_str());
for(const std::experimental::filesystem::directory_entry it : std::experimental::filesystem::recursive_directory_iterator(*f)) {
loggers::get_instance().log("certificates_loader::retrieve_certificates_list: Processing file '%s'", it.path().filename().string().c_str());
if (std::experimental::filesystem::is_regular_file(it)) {
loggers::get_instance().log("certificates_loader::retrieve_certificates_list: Check extension '%s'", it.path().extension().string().c_str());
std::set<std::string>::const_iterator i = extensions_filter.find(it.path().extension().string());
if (i != extensions_filter.cend()) {
loggers::get_instance().log("certificates_loader::retrieve_certificates_list: Add file '%s'", it.path().filename().string().c_str());
p_files.insert(it);
}
}
} // End of 'for' statement
} // End of 'for' statement
loggers::get_instance().log("certificates_loader::retrieve_certificates_list: # of files to cache: %d", p_files.size());
if (p_files.size() == 0) {
loggers::get_instance().warning("certificates_loader::retrieve_certificates_list: No certificate found");
return -1;
}
return 0;
} // End of method retrieve_certificates_list
int certificates_loader::build_certificates_cache(std::set<std::experimental::filesystem::path>& p_files, std::map<std::string, std::unique_ptr<security_db_record> >& p_certificates, std::map<std::vector<unsigned char>, std::string>& p_hashed_id8s) {
loggers::get_instance().log(">>> certificates_loader::build_certificates_cache");
std::set<std::experimental::filesystem::path>::const_iterator it = p_files.cbegin();
do {
loggers::get_instance().log("certificates_loader::build_certificates_cache: Caching '%s'", it->string().c_str());
std::experimental::filesystem::path p = *it;
const std::string& key = p.stem();
loggers::get_instance().log("certificates_loader::build_certificates_cache: Key = '%s'", key.c_str());
// Load certificate file
it = p_files.find(p.replace_extension(_certificateExt));
if (it == p_files.cend()) {
loggers::get_instance().warning("certificates_loader::build_certificates_cache: Certificate file not found for '%s'", key.c_str());
return -1;
}
loggers::get_instance().log("certificates_loader::build_certificates_cache: Caching certificate '%s'", it->string().c_str());
std::ifstream is(it->string(), ios::in | ios::binary);
std::vector<unsigned char> certificate(std::experimental::filesystem::file_size(*it), 0x00);
is.read(reinterpret_cast<char *>(certificate.data()), certificate.size());
is.close();
// Remove items from the list
p_files.erase(it);
// Load private key file
it = p_files.find(p.replace_extension(_privateKeyExt));
if (it == p_files.cend()) {
loggers::get_instance().warning("certificates_loader::build_certificates_cache: Private keys file not found for '%s'", key.c_str());
return -1;
}
loggers::get_instance().log("certificates_loader::build_certificates_cache: Caching private keys '%s'", it->string().c_str());
is.open(it->string(), ios::in | ios::binary);
int size = std::experimental::filesystem::file_size(*it);
if ((size != 32) && (size != 48)) {
loggers::get_instance().warning("certificates_loader::build_certificates_cache: Private key size is incorrect for '%s'", key.c_str());
return -1;
}
std::vector<unsigned char> private_key(size, 0x00);
is.read(reinterpret_cast<char *>(private_key.data()), private_key.size());
is.close();
// Remove items from the list
p_files.erase(it);
// Load public keys file
it = p_files.find(p.replace_extension(_publicKeysExt));
if (it == p_files.cend()) {
loggers::get_instance().warning("certificates_loader::build_certificates_cache: Public keys file not found for '%s'", key.c_str());
return -1;
}
loggers::get_instance().log("certificates_loader::build_certificates_cache: Caching public keys '%s'", it->string().c_str());
is.open(it->string(), ios::in | ios::binary);
size = std::experimental::filesystem::file_size(*it);
loggers::get_instance().warning("certificates_loader::build_certificates_cache: Public keys size is incorrect for '%s'", key.c_str());
return -1;
}
std::vector<unsigned char> public_key_x(size / 2, 0x00);
is.read(reinterpret_cast<char *>(public_key_x.data()), public_key_x.size());
std::vector<unsigned char> public_key_y(size / 2, 0x00);
is.read(reinterpret_cast<char *>(public_key_y.data()), public_key_y.size());
is.close();
// Remove items from the list
p_files.erase(it);
// Load public compressed key file
it = p_files.find(p.replace_extension(_publicCompKeysExt));
if (it == p_files.cend()) {
loggers::get_instance().warning("certificates_loader::build_certificates_cache: Public compress key file not found for '%s'", key.c_str());
return -1;
}
loggers::get_instance().log("certificates_loader::build_certificates_cache: Caching public compressed ke '%s'", it->string().c_str());
is.open(it->string(), ios::in | ios::binary);
size = std::experimental::filesystem::file_size(*it);
if ((size != 33) && (size != 49)) {
loggers::get_instance().warning("certificates_loader::build_certificates_cache: Public compressed key size is incorrect for '%s'", key.c_str());
return -1;
}
std::vector<unsigned char> public_comp_key(size, 0x00);
is.read(reinterpret_cast<char *>(public_comp_key.data()), public_comp_key.size());
is.close();
// Remove items from the list
p_files.erase(it);
// Load private encryption key file if present
std::vector<unsigned char> private_enc_key;
it = p_files.find(p.replace_extension(_privateEncKeyExt));
if (it != p_files.cend()) {
loggers::get_instance().log("certificates_loader::build_certificates_cache: Caching private encryption keys '%s'", it->string().c_str());
is.open(it->string(), ios::in | ios::binary);
int size = std::experimental::filesystem::file_size(*it);
if (size != 32) { // IEEE Std 1609.2 2017: NistP256 or BrainpoolP256r1
loggers::get_instance().warning("certificates_loader::build_certificates_cache: Private encryption key size is incorrect for '%s'", key.c_str());
return -1;
}
private_enc_key.resize(size, 0x00);
is.read(reinterpret_cast<char *>(private_enc_key.data()), private_enc_key.size());
is.close();
// Remove items from the list
p_files.erase(it);
}
// Load public encryption key file
std::vector<unsigned char> public_enc_key_x;
std::vector<unsigned char> public_enc_key_y;
it = p_files.find(p.replace_extension(_publicEncKeysExt));
if (it != p_files.cend()) {
loggers::get_instance().log("certificates_loader::build_certificates_cache: Caching public encryption keys '%s'", it->string().c_str());
is.open(it->string(), ios::in | ios::binary);
size = std::experimental::filesystem::file_size(*it);
if (size != 64) { // IEEE Std 1609.2 2017: NistP256 or BrainpoolP256r1
loggers::get_instance().warning("certificates_loader::build_certificates_cache: Public encryption keys size is incorrect for '%s'", key.c_str());
return -1;
}
public_enc_key_x.resize(size / 2, 0x00);
is.read(reinterpret_cast<char *>(public_enc_key_x.data()), public_enc_key_x.size());
public_enc_key_y.resize(size / 2, 0x00);
is.read(reinterpret_cast<char *>(public_enc_key_y.data()), public_enc_key_y.size());
is.close();
// Remove items from the list
p_files.erase(it);
}
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
// Load issuer
it = p_files.find(p.replace_extension(_issuerDigestExt));
if (it == p_files.cend()) {
loggers::get_instance().warning("certificates_loader::build_certificates_cache: Issuer keys file not found for '%s'", key.c_str());
return -1;
}
loggers::get_instance().log("certificates_loader::build_certificates_cache: Caching issuer keys '%s'", it->string().c_str());
is.open(it->string(), ios::in | ios::binary);
size = std::experimental::filesystem::file_size(*it);
if (size != 8) {
loggers::get_instance().warning("certificates_loader::build_certificates_cache: Issuer keys file not found for '%s'", key.c_str());
return -1;
}
std::vector<unsigned char> issuer(size, 0x00);
is.read(reinterpret_cast<char *>(issuer.data()), issuer.size());
is.close();
// Remove items from the list
p_files.erase(it);
// Load hashed_id
it = p_files.find(p.replace_extension(_hashedidDigestExt));
if (it == p_files.cend()) {
loggers::get_instance().warning("certificates_loader::build_certificates_cache: Hashed_Id keys file not found for '%s'", key.c_str());
return -1;
}
loggers::get_instance().log("certificates_loader::build_certificates_cache: Caching hashed_id keys '%s'", it->string().c_str());
is.open(it->string(), ios::in | ios::binary);
size = std::experimental::filesystem::file_size(*it);
if (size != 8) {
loggers::get_instance().warning("certificates_loader::build_certificates_cache: Hashed_Id keys file not found for '%s'", key.c_str());
return -1;
}
std::vector<unsigned char> hashed_id(size, 0x00);
is.read(reinterpret_cast<char *>(hashed_id.data()), hashed_id.size());
is.close();
// Remove items from the list
p_files.erase(it);
IEEE1609dot2::CertificateBase decoded_certificate;
OCTETSTRING os(certificate.size(), certificate.data());
codec.decode(os, decoded_certificate);
loggers::get_instance().log_msg("certificates_loader::build_certificates_cache: Decoded certificate: ", decoded_certificate);
p_certificates.insert(std::pair<const std::string, std::unique_ptr<security_db_record> >(key, std::unique_ptr<security_db_record>(
new security_db_record(
key,
certificate, // Certificate
public_key_x, // public keys X-coordinate
public_key_y, // public keys Y-coordinate
public_comp_key, // public compressed key, 33 or 49 bytes length, byte #0 indicating compressed-y-0 (0x02) or compressed-y-1 (0x03)
private_enc_key, // Private enciption key
public_enc_key_x, // Public enciption key X-coordinate
public_enc_key_y // Public enciption key Y-coordinate
std::map<std::string, std::unique_ptr<security_db_record> >::const_iterator i = p_certificates.find(key);
if (i == p_certificates.cend()) {
loggers::get_instance().warning("certificates_loader::build_certificates_cache: Failed to insert new record '%s'", key.c_str());
return -1;
}
p_hashed_id8s.insert(std::pair<std::vector<unsigned char>, std::string>(i->second.get()->hashed_id(), i->first));
// Reset pointer
it = p_files.cbegin();
} while (it != p_files.cend());
return 0;
} // End of method build_certificates_cache
int certificates_loader::save_certificate(const security_db_record& p_certificate) {
loggers::get_instance().log(">>> certificates_loader::save_certificate");
// Certificate file
std::experimental::filesystem::path p(_full_path);
p /= p_certificate.certificate_id();
if (std::experimental::filesystem::exists(p)) {
std::experimental::filesystem::remove(p);
}
loggers::get_instance().log("certificates_loader::save_certificate: Certificate file: '%s'", p.string().c_str());
std::ofstream os(p.string(), ios::out | ios::binary);
os.write(reinterpret_cast<const char *>(p_certificate.certificate().data()), p_certificate.certificate().size());
os.close();
std::experimental::filesystem::permissions(p, std::experimental::filesystem::perms::add_perms | std::experimental::filesystem::perms::owner_all | std::experimental::filesystem::perms::group_all | std::experimental::filesystem::perms::others_all);
// Private key
p = _full_path;
p /= p_certificate.certificate_id();
if (std::experimental::filesystem::exists(p)) {
std::experimental::filesystem::remove(p);
}
loggers::get_instance().log("certificates_loader::save_certificate: Private key file: '%s'", p.string().c_str());
os.open(p.string(), ios::out | ios::binary);
os.write(reinterpret_cast<const char *>(p_certificate.private_key().data()), p_certificate.private_key().size());
os.close();
std::experimental::filesystem::permissions(p, std::experimental::filesystem::perms::add_perms | std::experimental::filesystem::perms::owner_all | std::experimental::filesystem::perms::group_all | std::experimental::filesystem::perms::others_all);
// Public keys
p = _full_path;
p /= p_certificate.certificate_id();
p += _publicKeysExt;
if (std::experimental::filesystem::exists(p)) {
std::experimental::filesystem::remove(p);
}
loggers::get_instance().log("certificates_loader::save_certificate: Public keys file: '%s'", p.string().c_str());
os.open(p.string(), ios::out | ios::binary);
os.write(reinterpret_cast<const char *>(p_certificate.public_key_x().data()), p_certificate.public_key_x().size());
os.write(reinterpret_cast<const char *>(p_certificate.public_key_y().data()), p_certificate.public_key_y().size());
os.close();
std::experimental::filesystem::permissions(p, std::experimental::filesystem::perms::add_perms | std::experimental::filesystem::perms::owner_all | std::experimental::filesystem::perms::group_all | std::experimental::filesystem::perms::others_all);
// Public compressed key
p = _full_path;
p /= p_certificate.certificate_id();
p += _publicCompKeysExt;
if (std::experimental::filesystem::exists(p)) {
std::experimental::filesystem::remove(p);
}
loggers::get_instance().log("certificates_loader::save_certificate: Public compressed keys file: '%s'", p.string().c_str());
os.open(p.string(), ios::out | ios::binary);
os.write(reinterpret_cast<const char *>(p_certificate.public_comp_key().data()), p_certificate.public_comp_key().size());
os.close();
std::experimental::filesystem::permissions(p, std::experimental::filesystem::perms::add_perms | std::experimental::filesystem::perms::owner_all | std::experimental::filesystem::perms::group_all | std::experimental::filesystem::perms::others_all);
// Private encryption key
if (p_certificate.private_enc_key().size() != 0) {
p = _full_path;
p /= p_certificate.certificate_id();
p += _privateEncKeyExt;
if (std::experimental::filesystem::exists(p)) {
std::experimental::filesystem::remove(p);
}
loggers::get_instance().log("certificates_loader::save_certificate: Private encryption key file: '%s'", p.string().c_str());
os.open(p.string(), ios::out | ios::binary);
os.write(reinterpret_cast<const char *>(p_certificate.private_enc_key().data()), p_certificate.private_enc_key().size());
os.close();
std::experimental::filesystem::permissions(p, std::experimental::filesystem::perms::add_perms | std::experimental::filesystem::perms::owner_all | std::experimental::filesystem::perms::group_all | std::experimental::filesystem::perms::others_all);
// Public encription keys
p = _full_path;
p /= p_certificate.certificate_id();
p += _publicEncKeysExt;
if (std::experimental::filesystem::exists(p)) {
std::experimental::filesystem::remove(p);
}
loggers::get_instance().log("certificates_loader::save_certificate: Public encryption keys file: '%s'", p.string().c_str());
os.open(p.string(), ios::out | ios::binary);
os.write(reinterpret_cast<const char *>(p_certificate.public_enc_key_x().data()), p_certificate.public_enc_key_x().size());
os.write(reinterpret_cast<const char *>(p_certificate.public_enc_key_y().data()), p_certificate.public_enc_key_y().size());
os.close();
std::experimental::filesystem::permissions(p, std::experimental::filesystem::perms::add_perms | std::experimental::filesystem::perms::owner_all | std::experimental::filesystem::perms::group_all | std::experimental::filesystem::perms::others_all);
}
// Issuer
p = _full_path;
p /= p_certificate.certificate_id();
p += _issuerDigestExt;
if (std::experimental::filesystem::exists(p)) {
std::experimental::filesystem::remove(p);
}
loggers::get_instance().log("certificates_loader::save_certificate: Issuer digest file: '%s'", p.string().c_str());
os.open(p.string(), ios::out | ios::binary);
os.write(reinterpret_cast<const char *>(p_certificate.issuer().data()), p_certificate.issuer().size());
os.close();
std::experimental::filesystem::permissions(p, std::experimental::filesystem::perms::add_perms | std::experimental::filesystem::perms::owner_all | std::experimental::filesystem::perms::group_all | std::experimental::filesystem::perms::others_all);
// Hashedid8
p = _full_path;
p /= p_certificate.certificate_id();
p += _hashedidDigestExt;
if (std::experimental::filesystem::exists(p)) {
std::experimental::filesystem::remove(p);
}
loggers::get_instance().log("certificates_loader::save_certificate: Hashedid8 digest file: '%s'", p.string().c_str());
os.open(p.string(), ios::out | ios::binary);
os.write(reinterpret_cast<const char *>(p_certificate.hashed_id().data()), p_certificate.hashed_id().size());
os.close();
std::experimental::filesystem::permissions(p, std::experimental::filesystem::perms::add_perms | std::experimental::filesystem::perms::owner_all | std::experimental::filesystem::perms::group_all | std::experimental::filesystem::perms::others_all);
} // End of method save_certificate