Commit a3c982c7 authored by garciay's avatar garciay
Browse files

Add certificates loader

parent bc1f01cc
......@@ -4,6 +4,8 @@
#include "sha384.hh"
#include "ec_keys.hh"
#include "security_services.hh"
#include <openssl/ec.h>
#include <openssl/ecdsa.h>
......@@ -56,7 +58,7 @@ namespace LibItsSecurity__Functions
OCTETSTRING fx__signWithEcdsaNistp256WithSha256(
const OCTETSTRING& p__toBeSignedSecuredMessage,
const OCTETSTRING& p__privateKey
) {
) {
// Calculate the SHA256 of the data
sha256 hash;
std::vector<unsigned char> hashData;
......@@ -90,7 +92,7 @@ namespace LibItsSecurity__Functions
OCTETSTRING fx__signWithEcdsaBrainpoolp256WithSha256(
const OCTETSTRING& p__toBeSignedSecuredMessage,
const OCTETSTRING& p__privateKey
) {
) {
// Calculate the SHA256 of the data
sha256 hash;
std::vector<unsigned char> hashData;
......@@ -124,7 +126,7 @@ namespace LibItsSecurity__Functions
OCTETSTRING fx__signWithEcdsaBrainpoolp384WithSha384(
const OCTETSTRING& p__toBeSignedSecuredMessage,
const OCTETSTRING& p__privateKey
) {
) {
// Calculate the SHA384 of the data
sha384 hash;
std::vector<unsigned char> hashData;
......@@ -195,7 +197,7 @@ namespace LibItsSecurity__Functions
const OCTETSTRING& p__signature,
const OCTETSTRING& p__ecdsaBrainpoolp256PublicKeyX,
const OCTETSTRING& p__ecdsaBrainpoolp256PublicKeyY
) {
) {
// Calculate the hash
sha256 hash;
std::vector<unsigned char> hashData;
......@@ -228,7 +230,7 @@ namespace LibItsSecurity__Functions
const OCTETSTRING& p__signature,
const OCTETSTRING& p__ecdsaBrainpoolp384PublicKeyX,
const OCTETSTRING& p__ecdsaBrainpoolp384PublicKeyY
) {
) {
// Calculate the hash
sha384 hash;
std::vector<unsigned char> hashData;
......@@ -260,7 +262,7 @@ namespace LibItsSecurity__Functions
OCTETSTRING& p__privateKey,
OCTETSTRING& p__publicKeyX,
OCTETSTRING& p__publicKeyY
) {
) {
ec_keys k(ec_elliptic_curves::nist_p_256);
if (k.generate() != 0) {
p__privateKey = OCTETSTRING();
......@@ -288,7 +290,7 @@ namespace LibItsSecurity__Functions
OCTETSTRING& p__privateKey,
OCTETSTRING& p__publicKeyX,
OCTETSTRING& p__publicKeyY
) {
) {
ec_keys k(ec_elliptic_curves::brainpool_p_256_r1);
if (k.generate() != 0) {
p__privateKey = OCTETSTRING();
......@@ -316,7 +318,7 @@ namespace LibItsSecurity__Functions
OCTETSTRING& p__privateKey,
OCTETSTRING& p__publicKeyX,
OCTETSTRING& p__publicKeyY
) {
) {
ec_keys k(ec_elliptic_curves::brainpool_p_384_r1);
if (k.generate() != 0) {
p__privateKey = OCTETSTRING();
......@@ -335,7 +337,8 @@ namespace LibItsSecurity__Functions
// group certificatesLoader
/* * @desc Load in memory cache the certificates available in the specified directory
/*
* @desc Load in memory cache the certificates available in the specified directory
* @param p_rootDirectory Root directory to access to the certificates identified by the certificate ID
* @param p_configId A configuration identifier
* @remark This method SHALL be call before any usage of certificates
......@@ -346,10 +349,26 @@ namespace LibItsSecurity__Functions
const CHARSTRING& p__rootDirectory,
const CHARSTRING& p__configId
) {
loggers::get_instance().log("GeoNetworkingLayer::GeoNetworkingLayer: ###################");
Params params;
params.insert(std::pair<std::string, std::string>(std::string("sec_db_path"), std::string(static_cast<const char*>(p__rootDirectory))));
if (security_services::get_instance().setup(params) == -1) {
return FALSE;
}
return TRUE;
}
/* * @desc Unload from memory cache the certificates
BOOLEAN fx__store__certificate(const CHARSTRING& p__cert__id, const OCTETSTRING& p__cert, const OCTETSTRING& p__private__key, const OCTETSTRING& p__public__key__x, const OCTETSTRING& p__public__key__y, const OCTETSTRING& p__hashid8, const OCTETSTRING& p__issuer) {
if (security_services::get_instance().store_certificate(p__cert__id, p__cert, p__private__key, p__public__key__x, p__public__key__y, p__hashid8, p__issuer) == -1) {
return FALSE;
}
return TRUE;
}
/*
* @desc Unload from memory cache the certificates
* @return true on success, false otherwise
fx_unloadCertificates() return boolean;
*/
......
......@@ -91,7 +91,7 @@ GeoNetworkingLayer::GeoNetworkingLayer(const std::string & p_type, const std::st
if (it == _params.cend()) {
_params.insert(std::pair<std::string, std::string>(std::string("signature"), "NISTP-256"));
}
// Set up security services
// Set up security services even if secured_mode is set to 0. Later, we can receive an AcEnableSecurity request, the sertificate caching will be ready to go
security_services::get_instance().setup(_params);
Params::const_iterator i = _params.find(Params::beaconing);
......
#include <iostream>
#include <fstream>
#include "certificates_loader.hh"
namespace fs = std::experimental::filesystem;
#include "converter.hh"
#include "loggers.hh"
certificates_loader * certificates_loader::instance = nullptr;
certificates_loader::certificates_loader(): _certificateExt{".crt"}, _privateKeyExt{".pkey"}, _publicKeysExt{".vkey"}, _full_path(), _is_cache_initialized{false}, _directory_filter{".svn", "._.DS_Store", ".DS_Store"} {
loggers::get_instance().log(">>> certificates_loader::certificates_loader");
} // End of ctor
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;
} else {
_full_path = "./";
}
fs::canonical(_full_path);
loggers::get_instance().log("certificates_loader::build_path: full path: %s", _full_path.string().c_str());
if (!fs::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<const std::string, std::unique_ptr<security_db_record> >& p_certificates, std::map<const std::vector<unsigned char>, const std::string&>& p_hashed_id8s) {
loggers::get_instance().log(">>> certificates_loader::load_certificates");
// Sanity check
if (_full_path.empty()) {
return -1;
}
if (_is_cache_initialized) {
return 0;
}
// Retrieve the list of the files in the path
std::set<fs::path> files;
if (retrieve_certificates_list(files) == -1) {
return -1;
}
// Build the certificates cache
if (build_certificates_cache(files, p_certificates, p_hashed_id8s) == -1) {
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<fs::path> folders;
for (const fs::directory_entry it : fs::recursive_directory_iterator(_full_path.string())) {
loggers::get_instance().log("certificates_loader::retrieve_certificates_list: Processing directory '%s'", it.path().string().c_str());
if (fs::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");
return -1;
}
// Process files
p_files.clear();
std::set<std::string> extensions_filter{ _certificateExt, _privateKeyExt, _publicKeysExt };
for (std::set<fs::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 fs::directory_entry it : fs::recursive_directory_iterator(*f)) {
loggers::get_instance().log("certificates_loader::retrieve_certificates_list: Processing file '%s'", it.path().filename().string().c_str());
if (fs::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:", 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<const std::string, std::unique_ptr<security_db_record> >& p_certificates, std::map<const std::vector<unsigned char>, const 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());
fs::path p = *it;
std::string key = p.filename();
// 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(fs::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 public key 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);
int size = fs::file_size(*it);
if ((size != 64) && (size != 96)) {
loggers::get_instance().warning("certificates_loader::build_certificates_cache: Public keys file not found 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);
// FIXME Caching private key, digest and issuer
// FIXME create new record
/*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
issuer, // Hashed ID fo the issuer, empty for CA
h, // Hashed ID
private_key, // Private key
public_key_x, // Public key X
public_key_y // Public key Y
))
));
std::map<const std::string, std::unique_ptr<security_db_record> >::const_iterator i = p_certificates.find(key);
if (i == _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<const std::vector<unsigned char>, const 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
#pragma once
#include <set>
#include <map>
#include <string>
#include <experimental/filesystem>
#include "security_db_record.hh"
/*!
* \class certificates_loader
* \brief This class provides mechanism to load the certificates from the filesystem according the struecture defined in ETSI TS 103 099
* \remark Singleton pattern
*/
class certificates_loader {
std::string _certificateExt;
std::string _privateKeyExt;
std::string _publicKeysExt;
/*!
* \brief The full folder path to load certificates
*/
std::experimental::filesystem::path _full_path;
/*!
* \brief Set to true when certificates are successfully loaded from file system
*/
bool _is_cache_initialized;
/*!
* \brief Directory filter (for local development purposes only
*/
std::set<std::string> _directory_filter;
/*!
* \brief Unique static object reference of this class
*/
static certificates_loader* instance;
/*!
* \brief Default private ctor
*/
certificates_loader();
/*!
* \brief Default private dtor
*/
~certificates_loader() {
if (instance != NULL) {
delete instance;
instance = NULL;
}
};
public: /*! \publicsection */
/*!
* \brief Public accessor to the single object reference
*/
inline static certificates_loader& get_instance() {
if (instance == NULL) instance = new certificates_loader();
return *instance;
};
int build_path(const std::string& p_root_directory);
int load_certificates(std::map<const std::string, std::unique_ptr<security_db_record> >& p_certificates, std::map<const std::vector<unsigned char>, const std::string&>& p_hashed_id8s);
private:
int retrieve_certificates_list(std::set<std::experimental::filesystem::path>& p_files);
int build_certificates_cache(std::set<std::experimental::filesystem::path>& p_files, std::map<const std::string, std::unique_ptr<security_db_record> >& p_certificates, std::map<const std::vector<unsigned char>, const std::string&>& p_hashed_id8s);
}; // End of class certificates_loader
This diff is collapsed.
......@@ -8,6 +8,7 @@
#include "security_db_record.hh"
class OCTETSTRING;
class CHARSTRING;
/*!
* \class security_db
......@@ -37,7 +38,11 @@ public: /*! \publicsection */
int get_hashed_id(const std::string& p_certifcate_id, OCTETSTRING& p_hashed_id) const;
int get_private_key(const std::string& p_certifcate_id, OCTETSTRING& p_private_key) const;
int get_public_keys(const std::string& p_certifcate_id, OCTETSTRING& p_public_key_x, OCTETSTRING& p_public_key_y) const;
int store_certificate(const CHARSTRING& p_cert_id, const OCTETSTRING& p_cert, const OCTETSTRING& p_private_key, const OCTETSTRING& p_public_key_x, const OCTETSTRING& p_public_key_y, const OCTETSTRING& p_hashid8, const OCTETSTRING& p_issuer);
void dump() const;
int clear();
private:
int load_from_files(const std::string& p_db_path);
......
......@@ -18,13 +18,13 @@
#include "converter.hh"
security_services * security_services::instance = NULL;
security_services * security_services::instance = nullptr;
security_services::security_services() : _ec_keys(nullptr), _security_db(nullptr) {
loggers::get_instance().log(">>> security_services::security_services");
} // End of ctor
int security_services::setup(Params& p_params) {
int security_services::setup(Params& p_params) { // FIXME Rename this method
loggers::get_instance().log("security_services::setup");
p_params.log();
......@@ -36,6 +36,16 @@ int security_services::setup(Params& p_params) {
return 0;
}
int security_services::store_certificate(const CHARSTRING& p_cert_id, const OCTETSTRING& p_cert, const OCTETSTRING& p_private_key, const OCTETSTRING& p_public_key_x, const OCTETSTRING& p_public_key_y, const OCTETSTRING& p_hashid8, const OCTETSTRING& p_issuer) {
loggers::get_instance().log_msg(">>> security_services::store_certificate: ", p_cert_id);
// Sanity checks
if (_security_db.get() == nullptr) { // Setup not called
return -1;
}
return _security_db.get()->store_certificate(p_cert_id, p_cert, p_private_key, p_public_key_x, p_public_key_y, p_hashid8, p_issuer);
}
int security_services::verify_and_extract_gn_payload(const OCTETSTRING& p_secured_gn_payload, const bool p_verify, OCTETSTRING& p_unsecured_gn_payload, Params& p_params) {
loggers::get_instance().log_msg(">>> security_services::verify_and_extract_gn_payload: ", p_secured_gn_payload);
......
......@@ -35,8 +35,7 @@ class security_services {
/*!
* \brief Unique static object reference of this class
*/
static security_services * instance;
static security_services* instance;
std::unique_ptr<ec_keys> _ec_keys;
std::unique_ptr<security_db> _security_db;
......@@ -61,13 +60,11 @@ public: /*! \publicsection */
/*!
* \brief Public accessor to the single object reference
*/
inline static security_services & get_instance() {
inline static security_services& get_instance() {
if (instance == NULL) instance = new security_services();
return *instance;
};
int setup(Params &p_params);
/*!
* \brief Decrypt (if required), verify and extract the unsecured payload from the provided secured payload
* \param[in] p_secured_gn_payload The secured payload to be processed
......@@ -79,6 +76,11 @@ public: /*! \publicsection */
int secure_gn_payload(const OCTETSTRING& p_unsecured_gn_payload, const bool p_add_certificate, OCTETSTRING& p_secured_gn_payload, Params& p_params);
int setup(Params &p_params);
int store_certificate(const CHARSTRING& p_cert_id, const OCTETSTRING& p_cert, const OCTETSTRING& p_private_key, const OCTETSTRING& p_public_key_x, const OCTETSTRING& p_public_key_y, const OCTETSTRING& p_hashid8, const OCTETSTRING& p_issuer);
private:
/*!
* \brief Decrypt (if required), verify and extract the unsecured payload from the IEEE1609dot2::Ieee1609Dot2Content data structure
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment