diff --git a/ccsrc/Framework/src/layer_factory.cc b/ccsrc/Framework/src/layer_factory.cc index 2a106304c1160b29020add8d68926fddb16c4431..a28e2dc9a265a761ee255b793d7d12aa265cde43 100644 --- a/ccsrc/Framework/src/layer_factory.cc +++ b/ccsrc/Framework/src/layer_factory.cc @@ -20,7 +20,7 @@ layer_stack_builder::layer_stack_builder() {} void layer_stack_builder::_register_layer_factory(const std::string &p_type, layer_factory *p_layer_factory) { _layer_factories[p_type] = p_layer_factory; } layer *layer_stack_builder::create_layer_stack(const char *p_layer_stack_description) { - loggers::get_instance().log(">>> layer_stack_builder::create_layer_stack: %s", p_layer_stack_description); + loggers::get_instance().log(">>> layer_stack_builder::create_layer_stack: '%s'", p_layer_stack_description); layer *entry = NULL; // Initial layer (the first declared) layer *up = NULL; // Upper layer @@ -36,12 +36,12 @@ layer *layer_stack_builder::create_layer_stack(const char *p_layer_stack_descrip m[2].str().c_str(), m[3].str().c_str()); LayerFactoryMap::iterator i = _layer_factories.find(m[1].str()); if (i == _layer_factories.end()) { - loggers::get_instance().error("layer_stack_builder::create_layer_stack: %s: Unknown layer type", m[1].str().c_str()); + loggers::get_instance().error("layer_stack_builder::create_layer_stack: '%s': Unknown layer type", m[1].str().c_str()); } loggers::get_instance().log("layer_stack_builder::create_layer_stack: Create layer %s, %s", m[1].str().c_str(), m[3].str().c_str()); layer *l = i->second->create_layer(m[1].str(), m[3].str()); if (NULL == l) { - loggers::get_instance().error("layer_stack_builder::create_layer_stack: %s: Layer creation error", m[1].str().c_str()); + loggers::get_instance().error("layer_stack_builder::create_layer_stack: '%s': Layer creation error", m[1].str().c_str()); } loggers::get_instance().log("layer_stack_builder::create_layer_stack: Setup layers for %s - %p", l->to_string().c_str(), (void*)l); diff --git a/ccsrc/Framework/src/params.cc b/ccsrc/Framework/src/params.cc index 5040dbe0837f346ab0f4a40554e7d3a9e5a2d6fe..d58d39a6d403f507f36167a5eff8a37e759097fa 100644 --- a/ccsrc/Framework/src/params.cc +++ b/ccsrc/Framework/src/params.cc @@ -51,7 +51,7 @@ void params::convert(params &p_param, const std::string p_parameters) { if (p_parameters.length() == 0) { return; } - loggers::get_instance().log(">>> params::convert: %s", p_parameters.c_str()); + loggers::get_instance().log(">>> params::convert: '%s'", p_parameters.c_str()); // Extract parameters try { std::regex rgx("(\\w+)=(.*?)(,|$)"); diff --git a/ccsrc/Protocols/ETH/ethernet_layer.cc b/ccsrc/Protocols/ETH/ethernet_layer.cc index 33a79e14bc4b1e9bdec8f24257e738ff750b1ca5..6405a96e2ec330fce344c5a22f6e7fc54b0b5e3c 100644 --- a/ccsrc/Protocols/ETH/ethernet_layer.cc +++ b/ccsrc/Protocols/ETH/ethernet_layer.cc @@ -3,7 +3,7 @@ #include "loggers.hh" ethernet_layer::ethernet_layer(const std::string & p_type, const std::string & p_param) : layer(p_type), _params() { - loggers::get_instance().log(">>> ethernet_layer::ethernet_layer: %s, %s", to_string().c_str(), p_param.c_str()); + loggers::get_instance().log(">>> ethernet_layer::ethernet_layer: '%s', %s", to_string().c_str(), p_param.c_str()); // Setup parameters params::convert(_params, p_param); params::const_iterator it = _params.find("mac_src"); diff --git a/ccsrc/Protocols/Http/http_codec.cc b/ccsrc/Protocols/Http/http_codec.cc index a5818f1c910503dab07f22053b28b2e7d078f105..f0763bbbb7a3d37fea0bfb702f1889c8cfd9c819 100644 --- a/ccsrc/Protocols/Http/http_codec.cc +++ b/ccsrc/Protocols/Http/http_codec.cc @@ -220,7 +220,7 @@ int http_codec::encode_request(const LibHttp__TypesAndValues::Request &p_request // Encode Content-Length header p_encoding_buffer.put_cs("Content-Length: "); if (_ec.length != 0) { - loggers::get_instance().log("http_codec::encode_request: Content-Length: %s", + loggers::get_instance().log("http_codec::encode_request: Content-Length: '%s'", static_cast<const char *>(int2str(_ec.length + 2 /*Stand for the last CRLF*/))); p_encoding_buffer.put_cs(static_cast<const char *>(int2str(_ec.length))); _ec.is_content_length_present = 0x01; @@ -319,7 +319,7 @@ int http_codec::encode_response(const LibHttp__TypesAndValues::Response &p_respo // Encode Content-Length header p_encoding_buffer.put_cs("Content-Length: "); if (_ec.length != 0) { - loggers::get_instance().log("http_codec::encode_request: Content-Length: %s", + loggers::get_instance().log("http_codec::encode_request: Content-Length: '%s'", static_cast<const char *>(int2str(_ec.length + 2 /*Stand for the last CRLF*/))); p_encoding_buffer.put_cs(static_cast<const char *>(int2str(_ec.length))); _ec.is_content_length_present = 0x01; @@ -576,7 +576,7 @@ int http_codec::decode_body(TTCN_Buffer &decoding_buffer, LibHttp__MessageBodyTy // Convert into string params p; p["decode_str"] = std::string(static_cast<const unsigned char *>(body), body.lengthof() + static_cast<const unsigned char *>(body)); - loggers::get_instance().log("http_codec::decode_body: decode_str: %s", p["decode_str"].c_str()); + loggers::get_instance().log("http_codec::decode_body: decode_str: '%s'", p["decode_str"].c_str()); // Try to identify xml if (p["decode_str"].find("<?xml version=") != std::string::npos) { loggers::get_instance().log("http_codec::decode_body: Find xml message"); @@ -642,7 +642,7 @@ int http_codec::get_line(TTCN_Buffer &buffer, CHARSTRING &to, const bool concate } void http_codec::set_payload_codecs(const std::string &p_codecs) { - loggers::get_instance().log(">>> http_codec::set_payload_codecs: %s", p_codecs.c_str()); + loggers::get_instance().log(">>> http_codec::set_payload_codecs: '%s'", p_codecs.c_str()); // Sanity check if (p_codecs.length() == 0) { @@ -673,7 +673,7 @@ void http_codec::set_payload_codecs(const std::string &p_codecs) { } // End of 'for' statement loggers::get_instance().log("http_codec::set_payload_codecs: _codecs length=%d - %p", _codecs.size(), this); } catch (const std::logic_error &e) { - loggers::get_instance().warning("http_codec::set_payload_codecs: std::logic_error: %s", e.what()); + loggers::get_instance().warning("http_codec::set_payload_codecs: std::logic_error: '%s'", e.what()); _codecs.clear(); } } diff --git a/ccsrc/Protocols/Http/http_layer.cc b/ccsrc/Protocols/Http/http_layer.cc index 451c7d6cf997876baa8115f07175e5dd6516662b..23f911c51d48489ec2c7646a01b807547119d246 100644 --- a/ccsrc/Protocols/Http/http_layer.cc +++ b/ccsrc/Protocols/Http/http_layer.cc @@ -13,7 +13,7 @@ using namespace std; // Required for isnan() http_layer::http_layer(const std::string &p_type, const std::string ¶m) : t_layer<LibHttp__TestSystem::HttpPort>(p_type), _params(), _codec(nullptr), _device_mode{false} { - loggers::get_instance().log(">>> http_layer::http_layer: %s, %s", to_string().c_str(), param.c_str()); + loggers::get_instance().log(">>> http_layer::http_layer: '%s', %s", to_string().c_str(), param.c_str()); // Setup parameters params::convert(_params, param); diff --git a/ccsrc/Protocols/Pcap/pcap_cygwin_layer.cc b/ccsrc/Protocols/Pcap/pcap_cygwin_layer.cc index 56f9bbc9dee95c905693ff0c45f93947f1c64527..f45d70e8bb0fabf0cc99094f052ed3617bbf930a 100644 --- a/ccsrc/Protocols/Pcap/pcap_cygwin_layer.cc +++ b/ccsrc/Protocols/Pcap/pcap_cygwin_layer.cc @@ -54,7 +54,7 @@ static char * _bin2hex(char *hex, size_t hlen, const char *bin, size_t blen pcap_layer::pcap_layer(const std::string &p_type, const std::string ¶m) : layer(p_type), PORT(p_type.c_str()), _params(), _device(NULL), _running(FALSE), _time_key("pcap_layer::Handle_Fd_Event_Readable") { - loggers::get_instance().log(">>> pcap_layer::pcap_layer: %s, %s", p_type.c_str(), param.c_str()); + loggers::get_instance().log(">>> pcap_layer::pcap_layer: '%s', %s", p_type.c_str(), param.c_str()); params::convert(_params, param); char error_buffer[PCAP_ERRBUF_SIZE]; @@ -128,7 +128,7 @@ pcap_layer::pcap_layer(const std::string &p_type, const std::string ¶m) } // Log final PCAP filter - loggers::get_instance().user("pcap_layer::pcap_layer: Filter: %s", filter.c_str()); + loggers::get_instance().user("pcap_layer::pcap_layer: Filter: '%s'", filter.c_str()); // setup filter { @@ -147,7 +147,7 @@ pcap_layer::pcap_layer(const std::string &p_type, const std::string ¶m) // create pipe and run thread if (pipe2(_fd, O_NONBLOCK) == -1) { - loggers::get_instance().error("pcap_layer::pcap_layer: Failed to create a pipe: %s", ::strerror(errno)); + loggers::get_instance().error("pcap_layer::pcap_layer: Failed to create a pipe: '%s'", ::strerror(errno)); } // Pass the pipe handler to the polling procedure loggers::get_instance().log("pcap_layer::pcap_layer: Call handler with descriptor %d", _fd[0]); @@ -238,7 +238,7 @@ void *pcap_layer::thread() { void pcap_layer::send_data(OCTETSTRING &data, params ¶ms) { loggers::get_instance().log_msg(">>> pcap_layer::send_data: ", data); if (pcap_sendpacket(_device, static_cast<const unsigned char *>(data), data.lengthof()) == -1) { - loggers::get_instance().error("pcap_layer::send_data: Failed to send packet: %s", pcap_geterr(_device)); + loggers::get_instance().error("pcap_layer::send_data: Failed to send packet: '%s'", pcap_geterr(_device)); } } diff --git a/ccsrc/Protocols/Pcap/pcap_layer.cc b/ccsrc/Protocols/Pcap/pcap_layer.cc index 8313c9f3018f9e44df87985ecb6f27cb970f9c07..94f7e8b65b4e587082eaf47dbad5726e440a80db 100644 --- a/ccsrc/Protocols/Pcap/pcap_layer.cc +++ b/ccsrc/Protocols/Pcap/pcap_layer.cc @@ -16,7 +16,7 @@ typedef struct timeval pcap_o_timeval; pcap_layer::pcap_layer(const std::string& p_type, const std::string& param) : layer(p_type), PORT(p_type.c_str()), _params(), _device(NULL), _pcap_h(-1), _thread(NULL), _running(FALSE), _resume(), _sent_file(NULL), _time_key("pcap_layer::Handle_Fd_Event_Readable") { bool online = false; - loggers::get_instance().log(">>> pcap_layer::pcap_layer: %s, %s", to_string().c_str(), param.c_str()); + loggers::get_instance().log(">>> pcap_layer::pcap_layer: '%s', %s", to_string().c_str(), param.c_str()); _fd[0] = -1; _fd[1] = -1; // Setup parameters params::convert(_params, param); @@ -42,7 +42,7 @@ pcap_layer::pcap_layer(const std::string& p_type, const std::string& param) : la } // else, continue // Set non-blocking flag for the polling procedure if (pcap_setnonblock(_device, 1, error_buffer) != 0) { - loggers::get_instance().error("pcap_layer::pcap_layer: Failed to set blocking mode: %s", error_buffer); + loggers::get_instance().error("pcap_layer::pcap_layer: Failed to set blocking mode: '%s'", error_buffer); } // Retrieve the device file handler _pcap_h = pcap_get_selectable_fd(_device); @@ -70,7 +70,7 @@ pcap_layer::pcap_layer(const std::string& p_type, const std::string& param) : la int i = _params["file"].find(".pcap"); if (i > 0) { std::string f(_params["file"].substr(0, i) + ext + ".pcap"); - loggers::get_instance().log("pcap_layer::pcap_layer: Save file name: %s", f.c_str()); + loggers::get_instance().log("pcap_layer::pcap_layer: Save file name: '%s'", f.c_str()); if ((_sent_file = pcap_dump_open(_device, f.c_str())) == NULL) { loggers::get_instance().warning("pcap_layer::pcap_layer: Failed to open save file %s", f.c_str()); } @@ -105,7 +105,7 @@ pcap_layer::pcap_layer(const std::string& p_type, const std::string& param) : la } // else nothing to do } // Log final PCAP filter - loggers::get_instance().user("pcap_layer::pcap_layer: Filter: %s", filter.c_str()); + loggers::get_instance().user("pcap_layer::pcap_layer: Filter: '%s'", filter.c_str()); if (!filter.empty()) { struct bpf_program f = {0}; if (pcap_compile(_device, &f, filter.c_str(), 1, PCAP_NETMASK_UNKNOWN) != 0) { @@ -123,7 +123,7 @@ pcap_layer::pcap_layer(const std::string& p_type, const std::string& param) : la } else { // Offline capture or cygwin // Create a pipe if (pipe2(_fd, O_NONBLOCK) == -1) { - loggers::get_instance().error("pcap_layer::pcap_layer: Failed to create a pipe: %s", ::strerror(errno)); + loggers::get_instance().error("pcap_layer::pcap_layer: Failed to create a pipe: '%s'", ::strerror(errno)); } if(online){ _pcap_h = _fd[0]; @@ -212,7 +212,7 @@ void pcap_layer::send_data(OCTETSTRING& data, params& params) { if (_pcap_h != -1) { // Check if offline mode is used if (pcap_sendpacket(_device, static_cast<const unsigned char *>(data), data.lengthof()) == -1) { - loggers::get_instance().error("pcap_layer::send_data: Failed to send packet: %s", pcap_geterr(_device)); + loggers::get_instance().error("pcap_layer::send_data: Failed to send packet: '%s'", pcap_geterr(_device)); } } else if (_sent_file != NULL) { struct pcap_pkthdr hdr; diff --git a/ccsrc/Protocols/Pcap/pcap_linux_layer.cc b/ccsrc/Protocols/Pcap/pcap_linux_layer.cc index fecb2b34c78e683e9939fe1c6e5744cc029b99ca..ab9b5b87e20d3f636b5e1653696eadf9213014ed 100644 --- a/ccsrc/Protocols/Pcap/pcap_linux_layer.cc +++ b/ccsrc/Protocols/Pcap/pcap_linux_layer.cc @@ -42,7 +42,7 @@ pcap_layer::pcap_layer(const std::string &p_type, const std::string ¶m) params::const_iterator it; std::string nic; - loggers::get_instance().log(">>> pcap_layer::pcap_layer: %s, %s", to_string().c_str(), param.c_str()); + loggers::get_instance().log(">>> pcap_layer::pcap_layer: '%s', %s", to_string().c_str(), param.c_str()); // Setup parameters params::convert(_params, param); // Prepare capture processing @@ -69,7 +69,7 @@ pcap_layer::pcap_layer(const std::string &p_type, const std::string ¶m) } // else, continue // Set non-blocking flag for the polling procedure if (pcap_setnonblock(_device, 1, error_buffer) != 0) { - loggers::get_instance().error("pcap_layer::pcap_layer: Failed to set blocking mode: %s", error_buffer); + loggers::get_instance().error("pcap_layer::pcap_layer: Failed to set blocking mode: '%s'", error_buffer); } // Retrieve the device file handler _pcap_h = pcap_get_selectable_fd(_device); @@ -125,7 +125,7 @@ pcap_layer::pcap_layer(const std::string &p_type, const std::string ¶m) filter += std::string(" ") + it->second; } // Log final PCAP filter - loggers::get_instance().user("pcap_layer::pcap_layer: Filter: %s", filter.c_str()); + loggers::get_instance().user("pcap_layer::pcap_layer: Filter: '%s'", filter.c_str()); { struct bpf_program f = {0}; @@ -155,7 +155,7 @@ void pcap_layer::send_data(OCTETSTRING &data, params ¶ms) { loggers::get_instance().log_msg(">>> pcap_layer::send_data: ", data); if (pcap_sendpacket(_device, static_cast<const unsigned char *>(data), data.lengthof()) == -1) { - loggers::get_instance().error("pcap_layer::send_data: Failed to send packet: %s", pcap_geterr(_device)); + loggers::get_instance().error("pcap_layer::send_data: Failed to send packet: '%s'", pcap_geterr(_device)); } } diff --git a/ccsrc/Protocols/Pcap/pcap_offline_layer.cc b/ccsrc/Protocols/Pcap/pcap_offline_layer.cc index d8afc3a19c4415a02065eb8cf146bee1f8bc2911..b84cfc2e5fb19ae4137034fa2c972d09e61db934 100644 --- a/ccsrc/Protocols/Pcap/pcap_offline_layer.cc +++ b/ccsrc/Protocols/Pcap/pcap_offline_layer.cc @@ -33,7 +33,7 @@ typedef struct timeval pcap_o_timeval; pcap_offline_layer::pcap_offline_layer(const std::string &p_type, const std::string ¶m) : layer(p_type), PORT(p_type.c_str()), _params(), _device(NULL), _running(FALSE), _time_key("pcap_offline_layer::Handle_Fd_Event_Readable") { - loggers::get_instance().log(">>> pcap_offline_layer::pcap_offline_layer: %s, %s", p_type.c_str(), param.c_str()); + loggers::get_instance().log(">>> pcap_offline_layer::pcap_offline_layer: '%s', %s", p_type.c_str(), param.c_str()); params::convert(_params, param); _o_params.insert(std::pair<std::string, std::string>(std::string("timestamp"), std::string())); @@ -58,7 +58,7 @@ pcap_offline_layer::pcap_offline_layer(const std::string &p_type, const std::str if ((it != _params.end()) && !it->second.empty()) { const std::string &filter = it->second; // Log final PCAP filter - loggers::get_instance().user("pcap_offline_layer::pcap_offline_layer: Filter: %s", filter.c_str()); + loggers::get_instance().user("pcap_offline_layer::pcap_offline_layer: Filter: '%s'", filter.c_str()); struct bpf_program f = {0}; if (pcap_compile(_device, &f, filter.c_str(), 1, PCAP_NETMASK_UNKNOWN) != 0) { loggers::get_instance().error("pcap_offline_layer::pcap_offline_layer: Failed to compile PCAP filter"); @@ -72,7 +72,7 @@ pcap_offline_layer::pcap_offline_layer(const std::string &p_type, const std::str // create pipe and run thread if (pipe2(_fd, O_NONBLOCK) == -1) { - loggers::get_instance().error("pcap_offline_layer::pcap_offline_layer: Failed to create a pipe: %s", ::strerror(errno)); + loggers::get_instance().error("pcap_offline_layer::pcap_offline_layer: Failed to create a pipe: '%s'", ::strerror(errno)); } // Pass the pipe handler to the polling procedure loggers::get_instance().log("pcap_offline_layer::pcap_offline_layer: Call handler with descriptor %d", _fd[0]); diff --git a/ccsrc/Protocols/Tcp/tcp_layer.cc b/ccsrc/Protocols/Tcp/tcp_layer.cc index 18dea58953e23efa1fa983e17cbcb93dcf60d0d2..945a1487a1cb1de5326afc98b9e63b98c1e8cc11 100644 --- a/ccsrc/Protocols/Tcp/tcp_layer.cc +++ b/ccsrc/Protocols/Tcp/tcp_layer.cc @@ -9,7 +9,7 @@ #include "loggers.hh" tcp_layer::tcp_layer(const std::string & p_type, const std::string & param) : layer(p_type), SSL_Socket(), PORT(p_type.c_str()), _params(), _client_id{-1}, _time_key("tcp_layer::Handle_Fd_Event_Readable"), _reconnect_on_send{false} { - loggers::get_instance().log(">>> tcp_layer::tcp_layer (1): %s, %s", to_string().c_str(), param.c_str()); + loggers::get_instance().log(">>> tcp_layer::tcp_layer (1): '%s', %s", to_string().c_str(), param.c_str()); // Setup parameters params::convert(_params, param); _params.log(); @@ -17,7 +17,7 @@ tcp_layer::tcp_layer(const std::string & p_type, const std::string & param) : la init(); } tcp_layer::tcp_layer(const std::string & p_type, const params & param) : layer(p_type), SSL_Socket(), PORT(p_type.c_str()), _params(), _client_id{-1}, _time_key("tcp_layer::Handle_Fd_Event_Readable"), _reconnect_on_send{false} { - loggers::get_instance().log(">>> tcp_layer::tcp_layer (2): %s", to_string().c_str()); + loggers::get_instance().log(">>> tcp_layer::tcp_layer (2): '%s'", to_string().c_str()); // Setup parameters _params = param; @@ -50,7 +50,7 @@ void tcp_layer::init() { _params.insert(std::pair<std::string, std::string>(std::string("server"), "127.0.0.1")); // TODO Try using params::server instead of std::string("server") } if (!parameter_set(params::server.c_str(), _params[params::server].c_str())) { - loggers::get_instance().warning("tcp_layer::set_parameter: Unprocessed parameter: %s", params::server.c_str()); + loggers::get_instance().warning("tcp_layer::set_parameter: Unprocessed parameter: '%s'", params::server.c_str()); } bool ssl_mode = false; it = _params.find(params::use_ssl); @@ -70,7 +70,7 @@ void tcp_layer::init() { } } if (!parameter_set(remote_port_name(), _params[params::port].c_str())) { - loggers::get_instance().warning("tcp_layer::set_parameter: Unprocessed parameter: %s", params::port.c_str()); + loggers::get_instance().warning("tcp_layer::set_parameter: Unprocessed parameter: '%s'", params::port.c_str()); } it = _params.find(params::local_port); if (it == _params.cend()) { @@ -81,7 +81,7 @@ void tcp_layer::init() { } } if (!parameter_set(local_port_name(), _params[params::local_port].c_str())) { - loggers::get_instance().warning("tcp_layer::set_parameter: Unprocessed parameter: %s", params::local_port.c_str()); + loggers::get_instance().warning("tcp_layer::set_parameter: Unprocessed parameter: '%s'", params::local_port.c_str()); } parameter_set(use_connection_ASPs_name(), (!server_mode) ? "yes" : "no"); @@ -138,7 +138,7 @@ void tcp_layer::init() { parameter_set(client_TCP_reconnect_name(), "yes"); if (server_mode == 0) { - loggers::get_instance().log("tcp_layer::init: Establish connection: %s/%s", _params[params::server].c_str(), _params[params::port].c_str()); + loggers::get_instance().log("tcp_layer::init: Establish connection: '%s'/%s", _params[params::server].c_str(), _params[params::port].c_str()); open_client_connection(_params[params::server].c_str(), _params[params::port].c_str(), NULL, NULL); } } @@ -170,12 +170,12 @@ void tcp_layer::send_data(OCTETSTRING& data, params& params) { loggers::get_instance().log_msg(">>> tcp_layer::send_data: ", data); loggers::get_instance().log("tcp_layer::send_data: SSL mode: %x", get_ssl_use_ssl()); - loggers::get_instance().log("tcp_layer::send_data: server_mode: %s", _params[params::server_mode].c_str()); + loggers::get_instance().log("tcp_layer::send_data: server_mode: '%s'", _params[params::server_mode].c_str()); loggers::get_instance().log("tcp_layer::send_data: peer_list_get_nr_of_peers: %d", peer_list_get_nr_of_peers()); if ((_params[params::server_mode].compare("0") == 0) && (peer_list_get_nr_of_peers() == 0)) { // Reconnect (e.g. HTTP connection lost - loggers::get_instance().log("tcp_layer::send_data: Re-establish connection: %s/%s", _params[params::server].c_str(), _params[params::port].c_str()); + loggers::get_instance().log("tcp_layer::send_data: Re-establish connection: '%s'/%s", _params[params::server].c_str(), _params[params::port].c_str()); open_client_connection(_params[params::server].c_str(), _params[params::port].c_str(), NULL, NULL); } send_outgoing(static_cast<const unsigned char*>(data), data.lengthof(), _client_id); diff --git a/ccsrc/Protocols/UDP/udp_layer.cc b/ccsrc/Protocols/UDP/udp_layer.cc index 04a673715bbcd915cb00b0b786c99dc13d9ef40c..b44d38268262ff73f89ed1c0efedf3010ee22f00 100644 --- a/ccsrc/Protocols/UDP/udp_layer.cc +++ b/ccsrc/Protocols/UDP/udp_layer.cc @@ -14,7 +14,7 @@ udp_layer::udp_layer(const std::string &p_type, const std::string ¶m) : layer(p_type), PORT(p_type.c_str()), _params(), _saddr{0}, _daddr{0}, _reuse_incoming_source_adddress(false), _fd(-1), _time_key("udp_layer::Handle_Fd_Event_Readable") { - loggers::get_instance().log(">>> udp_layer::udp_layer (1): %s, %s, %p", to_string().c_str(), param.c_str(), (void*)this); + loggers::get_instance().log(">>> udp_layer::udp_layer (1): '%s', %s, %p", to_string().c_str(), param.c_str(), (void*)this); // Setup parameters params::convert(_params, param); @@ -25,7 +25,7 @@ udp_layer::udp_layer(const std::string &p_type, const std::string ¶m) udp_layer::udp_layer(const std::string &p_type, const params ¶m) : layer(p_type), PORT(p_type.c_str()), _params(), _saddr{0}, _daddr{0}, _reuse_incoming_source_adddress(false), _fd(-1), _time_key("udp_layer::Handle_Fd_Event_Readable") { - loggers::get_instance().log(">>> udp_layer::udp_layer (2): %s", to_string().c_str()); + loggers::get_instance().log(">>> udp_layer::udp_layer (2): '%s'", to_string().c_str()); // Setup parameters _params = param; @@ -148,7 +148,7 @@ void udp_layer::Handle_Fd_Event_Readable(int fd) { std::copy((unsigned char *)buffer, (unsigned char *)((unsigned char *)buffer + result), std::back_inserter(acc)); if (_reuse_incoming_source_adddress) { // Reuse the incoming address/port for sending memcpy((void *)&_daddr, (const void *)&from, sizeof(struct sockaddr_in)); - loggers::get_instance().log("udp_layer::Handle_Fd_Event_Readable: New _daddr: %s:%d", ::inet_ntoa(_daddr.sin_addr), ntohs(_daddr.sin_port)); + loggers::get_instance().log("udp_layer::Handle_Fd_Event_Readable: New _daddr: '%s':%d", ::inet_ntoa(_daddr.sin_addr), ntohs(_daddr.sin_port)); } } params.insert(std::pair<std::string, std::string>( @@ -182,13 +182,13 @@ unsigned long udp_layer::get_host_id(const std::string &p_host_name) { struct hostent *hptr; if ((hptr = ::gethostbyname(p_host_name.c_str())) == 0) { close(); - loggers::get_instance().error("udp_layer::get_host_id: Invalid host name: %s", p_host_name.c_str()); + loggers::get_instance().error("udp_layer::get_host_id: Invalid host name: '%s'", p_host_name.c_str()); } ip_addr = *((unsigned long *)hptr->h_addr_list[0]); } } - loggers::get_instance().log("udp_layer::get_host_id: Host name: %s, Host address: %u", p_host_name.c_str(), ip_addr); + loggers::get_instance().log("udp_layer::get_host_id: Host name: '%s', Host address: %u", p_host_name.c_str(), ip_addr); return htonl(ip_addr); } diff --git a/ccsrc/Protocols/Xml/src/xml_converters.cc b/ccsrc/Protocols/Xml/src/xml_converters.cc index 363cc9a5bd468375e44c9d798bd572060258fdce..014504de8924a74f3bca58ae484bf306a9b6d5c0 100644 --- a/ccsrc/Protocols/Xml/src/xml_converters.cc +++ b/ccsrc/Protocols/Xml/src/xml_converters.cc @@ -18,7 +18,7 @@ xml_converters* xml_converters::_instance = nullptr; int xml_converters::xml_canonicalization(const std::string& p_to_canonical, std::string& p_canonicalized) const { - loggers::get_instance().log(">>> xml_converters::xml_canonicalization"); + loggers::get_instance().log(">>> xml_converters::xml_canonicalization: '%s'", p_to_canonical.c_str()); xmlDocPtr doc = xmlParseMemory(p_to_canonical.c_str(), p_to_canonical.length()); if (doc == nullptr) { @@ -52,7 +52,7 @@ int xml_converters::xml_canonicalization(const std::string& p_to_canonical, std: xmlOutputBufferClose(buffer); xmlFreeDoc(doc); - loggers::get_instance().log("<<< xml_converters::xml_canonicalization: %s", p_canonicalized.c_str()); + loggers::get_instance().log("<<< xml_converters::xml_canonicalization: '%s'", p_canonicalized.c_str()); return 0; } diff --git a/ccsrc/security/include/certs_cache.hh b/ccsrc/security/include/certs_cache.hh new file mode 100644 index 0000000000000000000000000000000000000000..e51f5e6633557124132148ba131d3dda469aa9d3 --- /dev/null +++ b/ccsrc/security/include/certs_cache.hh @@ -0,0 +1,102 @@ +/*! + * \file certs_cache.hh + * \brief Header file for a certificates caching storage mechanism. + * It is used to store certificates received from neighbors and not present in the data base + * \author ETSI STF637 + * \copyright ETSI Copyright Notification + * No part may be reproduced except as authorized by written permission. + * The copyright and the foregoing restriction extend to reproduction in all media. + * All rights reserved. + * \version 0.1 + */ +#pragma once + +#include <map> +#include <memory> +#include <string> +#include <vector> + +#include <openssl/x509.h> + +#include "certs_db_record.hh" + +/*! + * \class certs_cache + * \brief This class provides security record description for in memory security database. In memory mens there is no disk load/save mechanism + */ +class certs_cache { + static bool fill_vector(std::string& p_vector, const std::string& p_org); + +protected: /*! \protectedsection */ + // TODO Enforce with const security_cache_record, and const std::string + std::map<std::string, const std::string> _certificates_idx; //! List of the certificate names indexed by the certificate identifier, i.e. the SH1 of the certificate name + std::map<std::string, std::unique_ptr<const certs_db_record>> _certificates; //! List of the certificates indexed by the certificate identifier + +public: /*! \publicsection */ + /*! + * \brief Default ctor + */ + certs_cache(); + /*! + * \brief Default private dtor + */ + virtual ~certs_cache(); + + int get_certificate(const std::string& p_certificate_name, const std::string& p_private_key_name, const X509** p_certificate); + /*! + * \fn int get_certificate(const std::string& p_hashed_id8, const X509** p_certificate); + * \brief Retrive the specified certificate either from memory + * \param[in] p_certificate_id The certificate name + * \param[out] p_certificate The X509 certificate + * \return 0 on success, -1 otherwise + */ + int get_certificate(const std::string& p_certificate_id, const X509** p_certificate); + /*! + * \fn int get_private_key(const std::string &p_certificate_id, const EVP_PKEY** p_private_key); + * \brief Retrive the private key of the specified certificate + * \param[in] p_certificate_id The certificate name + * \param[out] p_private_key The private key + * \return 0 on success, -1 otherwise + */ + int get_private_key(const std::string &p_certificate_id, const EVP_PKEY** p_private_key); + /*! + * \fn int get_public_keys(const std::string &p_certificate_id, const EVP_PKEY** p_public_key); + * \brief Retrive the public keys (in uncompressed format) of the specified certificate + * \param[in] p_certificate_id The certificate name + * \param[out] p_public_key The public key + * \return 0 on success, -1 otherwise + */ + int get_public_keys(const std::string &p_certificate_id, const EVP_PKEY** p_public_key); + + virtual int store_certificate(const std::string& p_certificate_name, const std::string& p_certificate, const EVP_PKEY* p_private_key); + + /*! + * \fn int int clear(); + * \brief Cleanup the cache + * \return 0 on success, -1 otherwise + * \virtual + */ + virtual int clear(); + + void dump() const; + +private: /*! \privatesection */ + /*! + * \fn int load_certificate(const std::string &p_certificate_name, const std::string &p_private_key_name, const certs_db_record** p_record); + * \brief Retrive the specified certificate either from memory of from storage location + * \param[in] p_certificate_name The certificate name + * \param[in] p_private_key_name The certificate's private key name + * \param[out] p_record A reference to the certificate record + * \return 0 on success, -1 otherwise + */ + int load_certificate(const std::string &p_certificate_name, const std::string &p_private_key_name, const certs_db_record** p_record); + /*! + * \fn int load_certificate(const std::string& p_certificate_id, const certs_db_record** p_record); + * \brief Retrive the specified certificate either from memory of from storage location + * \param[in] p_certificate_id The certificate identifier + * \param[out] p_record A reference to the certificate record + * \return 0 on success, -1 otherwise + */ + int load_certificate(const std::string &p_certificate_id, const certs_db_record** p_record); + +}; // End of class certs_cache diff --git a/ccsrc/security/include/certs_db.hh b/ccsrc/security/include/certs_db.hh new file mode 100644 index 0000000000000000000000000000000000000000..0f08fa44e0ad84aacde32642539fbc0db98a8c43 --- /dev/null +++ b/ccsrc/security/include/certs_db.hh @@ -0,0 +1,49 @@ +/*! + * \file certs_db.hh + * \brief Header file for a list of certificates storage mechanism. + * It is used to store certificates received from neighbors and not present in the data base + * \author ETSI STF637 + * \copyright ETSI Copyright Notification + * No part may be reproduced except as authorized by written permission. + * The copyright and the foregoing restriction extend to reproduction in all media. + * All rights reserved. + * \version 0.1 + */ +#pragma once + +#include "certs_cache.hh" + +/*! + * \class certs_db + * \brief This class provides security record description for security database + */ +class certs_db : public certs_cache { + +public: /*! \publicsection */ + /*! + * \brief Ctor with full path to the certificates storage + * \param[in] p_db_path The full path to the certificates storage + */ + certs_db(const std::string &p_db_path); + /*! + * \brief Default dtor + */ + ~certs_db(); + + /*! + * \fn int store_certificate(const std::string& p_certificate_name, const std::string& p_certificate, const EVP_PKEY* p_private_key); + * \brief Store a new certificate + * \param[in] p_certificate_name The certificate name + * \return 0 on success, -1 otherwise + */ + int store_certificate(const std::string& p_certificate_name, const std::string& p_certificate, const EVP_PKEY* p_private_key); + +private: /*! \privatesection */ + /*! + * \fn int initialize_cache(const std::string& p_db_path); + * \brief Initialise the storage of certificates mechanism + * \param[in] p_db_path The full path to the certificates storage + * \return 0 on success, -1 otherwise + */ + int initialize_cache(const std::string &p_db_path); +}; // End of class certs_db diff --git a/ccsrc/security/include/certs_db_record.hh b/ccsrc/security/include/certs_db_record.hh new file mode 100644 index 0000000000000000000000000000000000000000..f98f82a903d8255c8266e5fb1cab95a91e9832fc --- /dev/null +++ b/ccsrc/security/include/certs_db_record.hh @@ -0,0 +1,62 @@ +/*! + * \file certs_db_record.hh + * \brief Header file for a storage of certificates mechanism. + * \author ETSI STF637 + * \copyright ETSI Copyright Notification + * No part may be reproduced except as authorized by written permission. + * The copyright and the foregoing restriction extend to reproduction in all media. + * All rights reserved. + * \version 0.1 + */ +#pragma once + +#include <string> + +#include <openssl/x509.h> + +/*! + * \class certs_db_record + * \brief This class provides security record description for security database + */ +class certs_db_record { + + std::string _certificate_id; /*!< Certificate name */ + X509* _certificate; /*!< X509 Certificate */ + EVP_PKEY* _private_key; /*!< Private key */ + +public: /*! \publicsection */ + /*! + * \brief Default ctor + */ + explicit certs_db_record() + : _certificate_id(nullptr), _certificate(nullptr), _private_key(nullptr) {}; + /*! + * \brief Specialised ctor + * \param[in] p_certificate_id The certificate identifier + * \param[in] p_certificate The X509 certificate in openssl format + * \param[in] p_private_key The certificate's private key in openssl format + */ + certs_db_record(const std::string &p_certificate_id, X509* p_certificate, EVP_PKEY* p_private_key); + + /*! + * \brief Default dtor + */ + ~certs_db_record(); + + /*! + * \inline + * \fn const std::string& certificate_id() const; + * \brief Retrieve the certificate identifier value + * \return The certificate identifier + */ + inline const std::string &certificate_id() const { return _certificate_id; }; + /*! + * \inline + * \fn const X509* certificate() const; + * \brief Retrieve the COER encoded certificate + * \return The COER encoded certificate + */ + inline const X509* certificate() const { return _certificate; }; + inline const EVP_PKEY* private_key() const { return _private_key; }; + inline const EVP_PKEY* public_key() const { return ::X509_get_pubkey(_certificate); }; +}; // End of class certs_db_record diff --git a/ccsrc/security/include/certs_loader.hh b/ccsrc/security/include/certs_loader.hh new file mode 100644 index 0000000000000000000000000000000000000000..42fd16296a5e807e1a2c1aa6958bff6f78be5651 --- /dev/null +++ b/ccsrc/security/include/certs_loader.hh @@ -0,0 +1,97 @@ +/*! + * \file certs_loader.hh + * \brief Header file for X506 PEM certificates loader definition. + * \author ETSI STF625 + * \copyright ETSI Copyright Notification + * No part may be reproduced except as authorized by written permission. + * The copyright and the foregoing restriction extend to reproduction in all media. + * All rights reserved. + * \version 0.1 + * \remark Use `openssl x509 -in <certificate.pem> -noout -text` to view the certficate content + * Use `openssl [rsa|dsa|...] -inform PEM -in <private-key.pem> -text -noout` to view the private key content + * Use `openssl x509 -in <certificate.der> -out <certificate.pem>` to convert a DER certificate into a PEM certificate + */ +#pragma once + +#include <map> +#include <set> +#include <string> +#include <vector> + +#include <experimental/filesystem> + +#include <openssl/bio.h> +#include <openssl/err.h> +#include <openssl/pem.h> +#include <openssl/x509.h> + +#include "certs_db_record.hh" + +/*! + * \class certs_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 certs_loader { + std::experimental::filesystem::path _db_path; //! Path of the certificates storage + bool _is_cache_initialized; //! Set to true when certificates are successfully loaded from file system + static certs_loader* instance; //! Unique static object reference of this class + + /*! + * \brief Default private ctor + */ + certs_loader(); + /*! + * \brief Default private dtor + */ + ~certs_loader() { + if (instance != NULL) { + delete instance; + instance = NULL; + } + }; + +public: /*! \publicsection */ + /*! + * \brief Public accessor to the single object reference + */ + inline static certs_loader &get_instance() { + if (instance == NULL) + instance = new certs_loader(); + return *instance; + }; + + /*! + * \fn int build_path(const std::string &p_root_directory); + * \brief Set the pass of the certificate storage + * \param[in] p_db_path The pass of the certificate storage + */ + int build_path(const std::string& p_root_directory); + /*! + * \fn int get_certificate_id(const std::string& p_certificate_name, std::string& p_certificate_id); + * \brief Compute the SHA-1 hash of the certificate name to provide the certificate identifier + * \param[in] p_certificate_name The certificate name + * \param[out] p_certificate_id The certificate identifier + * \return 0 on success, -1 otherwise + */ + int get_certificate_id(const std::string& p_certificate_name, std::string& p_certificate_id); + /*! + * \fn int load_certificate(const std::string& p_certificate_name, const std::string& p_private_key_name, std::map<std::string, std::unique_ptr<const certs_db_record>> & p_certificates); + * \brief Store in memory the specified certificate + * \param[in] p_certificate_name The certificate full path bame + * \param[in] p_private_key_name The certificate's private key full path name + * \param[out] p_certificate_id The certificate identifier + * \param[inout] p_certificates The map of the loaded in memory certificates + * \return 0 on success, -1 otherwise + */ + int load_certificate(const std::string& p_certificate_name, const std::string& p_private_key_name, std::string& p_certificate_id, std::map<std::string, std::unique_ptr<const certs_db_record>> & p_certificates); + /*! + * \fn int save_certificate(const certs_db_record &p_certificate); + * \brief Save the specified certificate and update the internal maps + * \param[in] p_certificate The certificate to save + * \param[out] p_certificate_id The certificate identifier + * \return 0 on success, -1 otherwise + */ + int save_certificate(const certs_db_record &p_certificate, std::string& p_certificate_id); +}; // End of class certs_loader + diff --git a/ccsrc/security/include/hmac.hh b/ccsrc/security/include/hmac.hh new file mode 100644 index 0000000000000000000000000000000000000000..cbd1ccd985edbb18026279ecf9e186a3cd290cbe --- /dev/null +++ b/ccsrc/security/include/hmac.hh @@ -0,0 +1,69 @@ +/*! + * \file hmac.hh + * \brief Header file for HMAC helper methods. + * \author ETSI STF637 + * \copyright ETSI Copyright Notification + * No part may be reproduced except as authorized by written permission. + * The copyright and the foregoing restriction extend to reproduction in all media. + * All rights reserved. + * \version 0.1 + */ +#pragma once + +#include <vector> + +#include <openssl/hmac.h> + +class OCTETSTRING; //! TITAN forward declaration + +/*! + * \enum Supported hash algorithms + */ +enum class hash_algorithms : unsigned char { + sha_256, /*!< HMAC with SHA-256 */ + sha_384 /*!< HMAC with SHA-384 */ +}; // End of class hash_algorithms + +/*! + * \class hmac + * \brief This class provides description of HMAC helper methods + */ +class hmac { + HMAC_CTX * _ctx; //! HMAC context + hash_algorithms _hash_algorithms; //! HMAC hash algorithm to use +public: + /*! + * \brief Default constructor + * Create a new instance of the hmac class + * \param[in] p_hash_algorithms The hash algorithm to be used to compute the HMAC. Default: sha_256 + */ + hmac(const hash_algorithms p_hash_algorithms = hash_algorithms::sha_256) : _ctx{::HMAC_CTX_new()}, _hash_algorithms(p_hash_algorithms){}; + /*! + * \brief Default destructor + */ + virtual ~hmac() { + if (_ctx != nullptr) { + ::HMAC_CTX_free(_ctx); + }; + }; + + /*! + * \fn int generate(const OCTETSTRING p_buffer, const OCTETSTRING p_secret_key, OCTETSTRING& p_hmac); + * \brief Generate the HMAC of data using a secret key + * \Param[in] p_buffer The data tobe hashed + * \param[in] p_secret_key The secret key to be used to generate the HMAC + * \param[out] p_hmac The HMAC value based of the provided data + * \return 0 on success, -1 otherwise + */ + int generate(const OCTETSTRING p_buffer, const OCTETSTRING p_secret_key, OCTETSTRING &p_hmac); // TODO Use reference & + + /*! + * \fn int generate(const unsigned char* p_buffer, const size_t p_buffer_length, const unsigned char* p_secret_key, const size_t p_secret_key_length, + * OCTETSTRING& p_hmac); \brief Generate the HMAC of data using a secret key \param[in] p_buffer The data to be hashed \param[in] p_buffer_length The size of + * the data \param[in] p_secret_key The secret key to be used to generate the HMAC \param[in] p_secret_key_length The size of the secret key \param[out] + * p_hmac The HMAC value based of the provided data \return 0 on success, -1 otherwise + */ + int generate(const unsigned char *p_buffer, const size_t p_buffer_length, const unsigned char *p_secret_key, const size_t p_secret_key_length, + OCTETSTRING &p_hmac); + +}; // End of class hmac diff --git a/ccsrc/security/include/security_services.hh b/ccsrc/security/include/security_services.hh new file mode 100644 index 0000000000000000000000000000000000000000..99bfb5f8631a7e817addb929f8ef8da86944bc1a --- /dev/null +++ b/ccsrc/security/include/security_services.hh @@ -0,0 +1,40 @@ +#pragma once + +#include <memory> + +#include <openssl/err.h> +#include <openssl/pem.h> +#include <openssl/x509.h> + +#include "certs_db.hh" + +class CHARSTRING; +class OCTETSTRING; + + +class security_services { + /*std::unique_ptr<certs_db> _certs_db*/; + static certs_db* _certs_db; + +public: /*! \publicsection */ + /*! + * \brief Default private ctor + */ + security_services()/* : _certs_db{nullptr}*/ {}; + /*! + * \brief Default private dtor + */ + ~security_services() { + //_certs_db.reset(); + delete _certs_db; + }; + + int initialize(const std::string& p_certs_db_path); + int load_certificate(const std::string& p_certificate_name, const std::string& p_private_key_name, const X509** p_certificate); + /*! + * \fn int build_path(const std::string &p_root_directory); + * \brief Set the pass of the certificate storage + * \param[in] p_db_path The pass of the certificate storage + */ + int do_sign(const OCTETSTRING& p_encoded_message, const CHARSTRING& p_certificate_name, OCTETSTRING& p_signature, OCTETSTRING& p_digest, CHARSTRING& p_x509_certificate_subject, CHARSTRING& p_x509_certificate_pem); +}; \ No newline at end of file diff --git a/ccsrc/security/include/sha1.hh b/ccsrc/security/include/sha1.hh new file mode 100644 index 0000000000000000000000000000000000000000..69f35dae16df31a1cc8199da631b07373c7a6517 --- /dev/null +++ b/ccsrc/security/include/sha1.hh @@ -0,0 +1,66 @@ +/*! + * \file sha1.hh + * \brief Header file for SHA-1 helper methods. + * \author ETSI STF637 + * \copyright ETSI Copyright Notification + * No part may be reproduced except as authorized by written permission. + * The copyright and the foregoing restriction extend to reproduction in all media. + * All rights reserved. + * \version 0.1 + */ +#pragma once + +#include <openssl/objects.h> +#include <openssl/sha.h> + +class OCTETSTRING; //! TITAN forward declaration + +/*! + * \class sha1 + * \brief This class provides description of SHA-1 helper methods + */ +class sha1 { + SHA_CTX _ctx; //! SHA context +public: + /*! + * \brief Default constructor + * Create a new instance of the sha1 class + */ + explicit sha1() : _ctx{} {}; + /*! + * \brief Default destructor + */ + virtual ~sha1(){}; + + /*! + * \fn int generate(const OCTETSTRING& p_buffer, OCTETSTRING& p_hash); + * \brief Receive bytes formated data from the lower layers + * \param[in] p_buffer The data used to generate the SHA-1 hash + * \param[out] p_hash The SHA-1 hash value based of the provided data + * \return 0 on success, -1 otherwise + */ + int generate(const OCTETSTRING &p_buffer, OCTETSTRING &p_hash); + + /*! + * \fn int generate(const unsigned char* p_buffer, OCTETSTRING& p_hash); + * \brief Receive bytes formated data from the lower layers + * \param[in] p_buffer The data used to generate the SHA-1 hash + * \param[in] The length of the data buffer + * \param[out] p_hash The SHA-1 hash value based of the provided data + * \return 0 on success, -1 otherwise + */ + int generate(const unsigned char *p_buffer, const size_t p_length, OCTETSTRING &p_hash); + + /*! + * \fn const OCTETSTRING get_sha1_empty_string() const; + * \brief Return the SHA-1 of an empty string + * \return The SHA-1 of an empty string + */ + inline const OCTETSTRING get_sha1_empty_string() const { + static unsigned char sha1_empty_string[] = { + 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, + 0xaf, 0xd8, 0x07, 0x09}; //! SHA-1 of an empty string + return OCTETSTRING(20, sha1_empty_string); + }; + +}; // End of class sha1 diff --git a/ccsrc/security/include/sha256.hh b/ccsrc/security/include/sha256.hh new file mode 100644 index 0000000000000000000000000000000000000000..fbb972dec298b0037e4f8af048740a0edc35dead --- /dev/null +++ b/ccsrc/security/include/sha256.hh @@ -0,0 +1,66 @@ +/*! + * \file sha256.hh + * \brief Header file for SHA-256 helper methods. + * \author ETSI STF637 + * \copyright ETSI Copyright Notification + * No part may be reproduced except as authorized by written permission. + * The copyright and the foregoing restriction extend to reproduction in all media. + * All rights reserved. + * \version 0.1 + */ +#pragma once + +#include <openssl/objects.h> +#include <openssl/sha.h> + +class OCTETSTRING; //! TITAN forward declaration + +/*! + * \class sha256 + * \brief This class provides description of SHA-256 helper methods + */ +class sha256 { + SHA256_CTX _ctx; //! SHA context +public: + /*! + * \brief Default constructor + * Create a new instance of the sha256 class + */ + explicit sha256() : _ctx{} {}; + /*! + * \brief Default destructor + */ + virtual ~sha256(){}; + + /*! + * \fn int generate(const OCTETSTRING& p_buffer, OCTETSTRING& p_hash); + * \brief Receive bytes formated data from the lower layers + * \param[in] p_buffer The data used to generate the SHA-256 hash + * \param[out] p_hash The SHA-256 hash value based of the provided data + * \return 0 on success, -1 otherwise + */ + int generate(const OCTETSTRING &p_buffer, OCTETSTRING &p_hash); + + /*! + * \fn int generate(const unsigned char* p_buffer, OCTETSTRING& p_hash); + * \brief Receive bytes formated data from the lower layers + * \param[in] p_buffer The data used to generate the SHA-256 hash + * \param[in] The length of the data buffer + * \param[out] p_hash The SHA-256 hash value based of the provided data + * \return 0 on success, -1 otherwise + */ + int generate(const unsigned char *p_buffer, const size_t p_length, OCTETSTRING &p_hash); + + /*! + * \fn const OCTETSTRING get_sha256_empty_string() const; + * \brief Return the SHA-256 of an empty string + * \return The SHA-256 of an empty string + */ + inline const OCTETSTRING get_sha256_empty_string() const { + static unsigned char sha256_empty_string[] = { + 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, + 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55}; //! SHA-256 of an empty string + return OCTETSTRING(32, sha256_empty_string); + }; + +}; // End of class sha256 diff --git a/ccsrc/security/include/sha384.hh b/ccsrc/security/include/sha384.hh new file mode 100644 index 0000000000000000000000000000000000000000..016c54f81128099bf0dd3297b78a7d9c85948e51 --- /dev/null +++ b/ccsrc/security/include/sha384.hh @@ -0,0 +1,60 @@ +/*! + * \file sha384.hh + * \brief Header file for SHA-384 helper methods. + * \author ETSI STF637 + * \copyright ETSI Copyright Notification + * No part may be reproduced except as authorized by written permission. + * The copyright and the foregoing restriction extend to reproduction in all media. + * All rights reserved. + * \version 0.1 + */ +#pragma once + +#include <openssl/objects.h> +#include <openssl/sha.h> + +class OCTETSTRING; //! TITAN forward declaration + +/*! + * \class sha384 + * \brief This class provides description of SHA-384 helper methods + */ +class sha384 { + SHA512_CTX _ctx; //! SHA context +public: //! \publicsection + /*! + * \brief Default constructor + * Create a new instance of the sha384 class + */ + explicit sha384() : _ctx{} {}; + /*! + * \brief Default destructor + */ + virtual ~sha384(){}; + + /*! + * \fn int generate(const OCTETSTRING& p_buffer, OCTETSTRING& p_hash); + * \brief Receive bytes formated data from the lower layers + * \param[in] p_buffer The data used to generate the SHA-384 hash + * \param[out] p_hash The SHA-384 hash value based of the provided data + * \return 0 on success, -1 otherwise + */ + int generate(const OCTETSTRING &p_buffer, OCTETSTRING &p_hash); + + /*! + * \fn int generate(const OCTETSTRING p_buffer, OCTETSTRING& p_hash); + * \brief Receive bytes formated data from the lower layers + * \param[in] p_buffer The data used to generate the SHA-384 hash + * \param[in] The length of the data buffer + * \param[out] p_hash The SHA-384 hash value based of the provided data + * \return 0 on success, -1 otherwise + */ + int generate(const unsigned char *p_buffer, const size_t p_length, OCTETSTRING &p_hash); + + /*! + * \fn const OCTETSTRING get_sha384_empty_string() const; + * \brief Return the SHA-384 of an empty string + * \return The SHA-384 of an empty string + */ + const OCTETSTRING get_sha384_empty_string() const; +}; // End of class sha384 diff --git a/ccsrc/security/module.mk b/ccsrc/security/module.mk new file mode 100644 index 0000000000000000000000000000000000000000..ac2c199314ab3f34e853c80c775437a146ae4278 --- /dev/null +++ b/ccsrc/security/module.mk @@ -0,0 +1,13 @@ +sources := \ + src/security_externals.cc \ + src/sha1.cc \ + src/sha256.cc \ + src/sha384.cc \ + src/hmac.cc \ + src/certs_db_record.cc \ + src/certs_db.cc \ + src/certs_cache.cc \ + src/certs_loader.cc \ + src/securty_services.cc + +includes := ./include diff --git a/ccsrc/security/src/certs_cache.cc b/ccsrc/security/src/certs_cache.cc new file mode 100644 index 0000000000000000000000000000000000000000..b0b413a38995b99dd1ccfcc85f50b9645133ee3f --- /dev/null +++ b/ccsrc/security/src/certs_cache.cc @@ -0,0 +1,152 @@ +/*! + * \file certs_cache.cc + * \brief Source file for a certificates caching storage mechanism. + * It is used to store certificates received from neighbors and not present in the data base + * \author ETSI STF637 + * \copyright ETSI Copyright Notification + * No part may be reproduced except as authorized by written permission. + * The copyright and the foregoing restriction extend to reproduction in all media. + * All rights reserved. + * \version 0.1 + */ +#include "certs_cache.hh" +#include "certs_loader.hh" + +#include "TTCN3.hh" +#include "sha1.hh" + +#include "converter.hh" + +#include "loggers.hh" + +certs_cache::certs_cache() : _certificates_idx(), _certificates() { loggers::get_instance().log(">>> certs_cache::certs_cache"); } // End of ctor + +certs_cache::~certs_cache() { + loggers::get_instance().log(">>> certs_cache::~certs_cache"); + clear(); +} // End of dtor + +int certs_cache::clear() { + loggers::get_instance().log(">>> certs_cache::clear"); + _certificates.clear(); // Smart pointers will do the job + _certificates_idx.clear(); + + return 0; +} // End of clear method + +int certs_cache::load_certificate(const std::string &p_certificate_id, const certs_db_record** p_record) { + loggers::get_instance().log(">>> certs_cache::load_certificate (1): '%s'", p_certificate_id.c_str()); + + // Sanity check + std::map<std::string, std::unique_ptr<const certs_db_record>>::const_iterator it = _certificates.find(p_certificate_id); + if (it == _certificates.cend()) { + loggers::get_instance().warning("certs_cache::load_certificate: Failed to load certificate"); + return -1; + } + + *p_record = it->second.get(); + + return 0; +} + +int certs_cache::load_certificate(const std::string &p_certificate_name, const std::string &p_private_key_name, const certs_db_record** p_record) { + loggers::get_instance().log(">>> certs_cache::load_certificate (2): '%s'", p_certificate_name.c_str()); + + std::string certificate_id; + if (certs_loader::get_instance().get_certificate_id(p_certificate_name, certificate_id) != 0) { + loggers::get_instance().warning("certs_cache::load_certificate: Failed to retrieve certificate identifier"); + return -1; + } + loggers::get_instance().log("certs_cache::load_certificate (2): certificate_id: '%s'", certificate_id.c_str()); + + std::map<std::string, const std::string>::const_iterator s = _certificates_idx.find(certificate_id); + if (s == _certificates_idx.cend()) { // Certificate is not in the DB + loggers::get_instance().log("certs_cache::load_certificate (2): Record not found"); + if (certs_loader::get_instance().load_certificate(p_certificate_name, p_private_key_name, certificate_id, _certificates) == -1) { + loggers::get_instance().warning("certs_cache::load_certificate: Failed to load certificate"); + return -1; + } + // Mapping certificate id/certificate name + _certificates_idx.insert(std::pair<std::string, const std::string>(certificate_id, p_certificate_name)); + } + + // Certificate is on the DB, load it if required + std::map<std::string, std::unique_ptr<const certs_db_record>>::const_iterator it = _certificates.find(certificate_id); + *p_record = it->second.get(); + + return 0; +} + +int certs_cache::get_certificate(const std::string& p_certificate_name, const std::string &p_private_key_name, const X509** p_certificate) { + loggers::get_instance().log(">>> certs_cache::get_certificate (1): '%s'", p_certificate_name.c_str()); + + const certs_db_record* record; + if (load_certificate(p_certificate_name, p_private_key_name, &record) == -1) { + loggers::get_instance().warning("certs_cache::get_certificate (1): Failed to load certificate"); + return -1; + } + + *p_certificate = record->certificate(); + loggers::get_instance().log("certs_cache::get_certificate (1): p_certificate: '%p'", *p_certificate); + + return 0; +} + +int certs_cache::get_certificate(const std::string &p_certificate_id, const X509** p_certificate) { + loggers::get_instance().log(">>> certs_cache::get_certificate (2): '%s'", p_certificate_id.c_str()); + + const certs_db_record* record; + if (load_certificate(p_certificate_id, &record) == -1) { + loggers::get_instance().warning("certs_cache::get_certificate (2): Failed to load certificate"); + return -1; + } + + *p_certificate = record->certificate(); + loggers::get_instance().log("certs_cache::get_certificate (2): p_certificate: '%p'", *p_certificate); + + return 0; +} + +int certs_cache::get_private_key(const std::string &p_certificate_id, const EVP_PKEY** p_private_key) { + loggers::get_instance().log(">>> certs_cache::get_private_key: '%s'", p_certificate_id.c_str()); + + const certs_db_record *record; + if (load_certificate(p_certificate_id, &record) == -1) { + loggers::get_instance().warning("certs_cache::get_private_key: Failed to load certificate"); + return -1; + } + + *p_private_key = record->private_key(); + loggers::get_instance().log("certs_cache::get_private_key: p_private_key: '%p'", *p_private_key); + + return 0; +} + +int certs_cache::get_public_keys(const std::string &p_certificate_id, const EVP_PKEY** p_public_key) { + loggers::get_instance().log(">>> certs_cache::get_public_keys: '%s'", p_certificate_id.c_str()); + + const certs_db_record* record; + if (load_certificate(p_certificate_id, &record) == -1) { + loggers::get_instance().warning("certs_cache::get_public_keys: Failed to load certificate"); + return -1; + } + + *p_public_key = record->public_key(); + loggers::get_instance().log("certs_cache::p_public_key: p_public_key: '%p'", *p_public_key); + + return 0; +} + +int certs_cache::store_certificate(const std::string& p_certificate_name, const std::string& p_certificate, const EVP_PKEY* p_private_key) { + loggers::get_instance().log(">>> certs_cache::store_certificate: '%s'", p_certificate_name.c_str()); + + return -1; +} + +void certs_cache::dump() const { + loggers::get_instance().log("certs_cache::dump_certificates: # items = %d", _certificates.size()); + + for (std::map<std::string, std::unique_ptr<const certs_db_record>>::const_iterator it = _certificates.cbegin(); it != _certificates.cend(); ++it) { + const certs_db_record *p = it->second.get(); + } // End of 'for' statement +} // End of method dump diff --git a/ccsrc/security/src/certs_db.cc b/ccsrc/security/src/certs_db.cc new file mode 100644 index 0000000000000000000000000000000000000000..055551999437434e64597c8ae935d7bb6b1f26d7 --- /dev/null +++ b/ccsrc/security/src/certs_db.cc @@ -0,0 +1,32 @@ +#include "certs_db.hh" + +#include "params.hh" +#include "loggers.hh" +#include "converter.hh" + +using namespace std; // Required for isnan() +#include "certs_loader.hh" + +certs_db::certs_db(const std::string &p_db_path) { + loggers::get_instance().log(">>> certs_db::certs_db: '%s'", p_db_path.c_str()); + + initialize_cache(p_db_path); + loggers::get_instance().log("<<< certs_db::certs_db"); +} // End of ctor + +certs_db::~certs_db() { loggers::get_instance().log(">>> certs_db::~certs_db"); } // End of dtor + +int certs_db::initialize_cache(const std::string &p_db_path) { + loggers::get_instance().log(">>> certs_db::initialize_cache: '%s'", p_db_path.c_str()); + + certs_loader::get_instance().build_path(p_db_path); + + loggers::get_instance().log("<<< certs_db::initialize_cache"); + return 0; +} + +int certs_db::store_certificate(const std::string& p_certificate_name, const std::string& p_certificate, const EVP_PKEY* p_private_key) { + loggers::get_instance().log(">>> certs_db::store_certificate: '%s'", p_certificate_name.c_str()); + + return -1; +} diff --git a/ccsrc/security/src/certs_db_record.cc b/ccsrc/security/src/certs_db_record.cc new file mode 100644 index 0000000000000000000000000000000000000000..59a0bd14c9d5c9e7068da31447a1e1a3e7728f22 --- /dev/null +++ b/ccsrc/security/src/certs_db_record.cc @@ -0,0 +1,29 @@ +/*! + * \file certs_db_record.cc + * \brief Source file for a storage of certificates mechanism. + * \author ETSI STF637 + * \copyright ETSI Copyright Notification + * No part may be reproduced except as authorized by written permission. + * The copyright and the foregoing restriction extend to reproduction in all media. + * All rights reserved. + * \version 0.1 + */ + +#include <openssl/x509.h> + +#include "loggers.hh" + +#include "certs_db_record.hh" + +certs_db_record::certs_db_record(const std::string &p_certificate_id, X509* p_certificate, EVP_PKEY* p_private_key) : _certificate_id(p_certificate_id), _certificate(p_certificate), _private_key(p_private_key) { + loggers::get_instance().log(">>> certs_db_record::certs_db_record: p_certificate_id: '%s'", p_certificate_id.c_str()); + loggers::get_instance().log(">>> certs_db_record::certs_db_record: p_certificate: '%p'", p_certificate); + loggers::get_instance().log(">>> certs_db_record::certs_db_record: p_private_key: '%p'", p_private_key); +} + +certs_db_record::~certs_db_record() { + if (_certificate != nullptr) { + ::X509_free(_certificate); + ::EVP_PKEY_free(_private_key); + } +} diff --git a/ccsrc/security/src/certs_loader.cc b/ccsrc/security/src/certs_loader.cc new file mode 100644 index 0000000000000000000000000000000000000000..dcb4b77677395747dfcec7c1a64143f5180b4e20 --- /dev/null +++ b/ccsrc/security/src/certs_loader.cc @@ -0,0 +1,143 @@ +#include <fstream> +#include <iostream> + +#include <openssl/bio.h> +#include <openssl/err.h> +#include <openssl/pem.h> +#include <openssl/x509.h> + +#include <TTCN3.hh> + +#include "sha1.hh" +#include "certs_loader.hh" + +#include "loggers.hh" + +certs_loader *certs_loader::instance = nullptr; + +certs_loader::certs_loader() : _db_path(), _is_cache_initialized{false} { + loggers::get_instance().log(">>> certs_loader::certs_loader"); +} // End of ctor + +int certs_loader::build_path(const std::string& p_root_directory) { + loggers::get_instance().log(">>> certs_loader::build_path: '%s'", p_root_directory.c_str()); + + // Sanity check + if (_is_cache_initialized) { + return 0; + } + + // Build full path + if (!p_root_directory.empty()) { + _db_path = p_root_directory; + if (!std::experimental::filesystem::exists(_db_path) || + !std::experimental::filesystem::is_directory(_db_path)) { // FIXME Coredump when app hasn't the rights to create the directory!!!! + // Create directory + if (!std::experimental::filesystem::create_directory(_db_path)) { + _db_path = "./"; + } else { // Set rights for all users + std::experimental::filesystem::permissions(_db_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); + } + } + } else { + _db_path = "./"; + } + std::experimental::filesystem::canonical(_db_path); + loggers::get_instance().log("certs_loader::build_path: full path: %s", _db_path.string().c_str()); + if (!std::experimental::filesystem::exists(_db_path)) { + loggers::get_instance().warning("certificates_loader::build_path: Invalid path"); + _db_path.clear(); + return -1; + } + + + loggers::get_instance().log("<<< certs_loader::build_path"); + return 0; +} + +int certs_loader::get_certificate_id(const std::string& p_certificate_name, std::string& p_certificate_id) { + loggers::get_instance().log(">>> certs_loader::get_certificate_id: '%s'", p_certificate_name.c_str()); + + // Build the certificate identifier + sha1 s; + const OCTETSTRING buffer = OCTETSTRING(p_certificate_name.length(), (unsigned char*)p_certificate_name.c_str()); + OCTETSTRING hash; + if (s.generate(buffer, hash) != 0) { + loggers::get_instance().warning("certs_cache::load_certificate: Failed to build the certificate identifier"); + return -1; + } + loggers::get_instance().log_msg("certs_loader::get_certificate_id: hash: ", hash); + CHARSTRING hash_str = oct2str(hash); + p_certificate_id.assign(static_cast<const char*>(hash_str), static_cast<const char*>(hash_str) + hash_str.lengthof()); + + loggers::get_instance().log("<<< certs_loader::get_certificate_id: '%s'", p_certificate_id.c_str()); + return 0; +} + +int certs_loader::load_certificate(const std::string& p_certificate_name, const std::string& p_private_key_name, std::string& p_certificate_id, std::map<std::string, std::unique_ptr<const certs_db_record>> & p_certificates) { + loggers::get_instance().log(">>> certs_loader::load_certificate %s", p_certificate_name.c_str()); + loggers::get_instance().log(">>> certs_loader::load_certificate: '%s'", p_private_key_name.c_str()); + + // Load certificate file + BIO* certbio = ::BIO_new(::BIO_s_file()); + if (certbio == nullptr) { + loggers::get_instance().warning("certs_loader::load_certificate: Error creating BIO"); + return -1; + } + std::experimental::filesystem::path p = _db_path.string() + "/" + p_certificate_name; + int ret = BIO_read_filename(certbio, p.string().c_str()); + X509* cert = ::PEM_read_bio_X509(certbio, NULL, 0, NULL); + if (cert == nullptr) { + loggers::get_instance().warning("certs_loader::load_certificate: Error loading cert into memory"); + ::BIO_free_all(certbio); + return -1; + } + ::BIO_free_all(certbio); + + // Load private key file + certbio = ::BIO_new(::BIO_s_file()); + if (certbio == nullptr) { + loggers::get_instance().warning("certs_loader::load_certificate: Error creating BIO"); + ::X509_free(cert); + return -1; + } + p = _db_path.string() + "/" + p_private_key_name; + ret = BIO_read_filename(certbio, p.string().c_str()); + EVP_PKEY* private_key = ::PEM_read_bio_PrivateKey(certbio, NULL, 0, NULL); + if (private_key == nullptr) { + loggers::get_instance().warning("certs_loader::load_certificate: Error loading cert into memory"); + ::X509_free(cert); + ::BIO_free_all(certbio); + return -1; + } + ::BIO_free_all(certbio); + + // Build the certificate identifier + if (get_certificate_id(p_certificate_name, p_certificate_id) != 0) { + loggers::get_instance().warning("certs_cache::load_certificate: Failed to build the certificate identifier"); + return -1; + } + loggers::get_instance().log("certs_loader::load_certificate: p_certificate_name: '%s'", p_certificate_name.c_str()); + loggers::get_instance().log("certs_loader::load_certificate: p_certificate_id: '%s'", p_certificate_id.c_str()); + loggers::get_instance().log("certs_loader::load_certificate: cert: '%p'", cert); + loggers::get_instance().log("certs_loader::load_certificate: private_key: '%p'", private_key); + + // Create new record + certs_db_record *r = new certs_db_record(p_certificate_name, cert, private_key); + std::pair<std::map<std::string, std::unique_ptr<const certs_db_record>>::iterator, bool> result = p_certificates.insert(std::pair<std::string, std::unique_ptr<const certs_db_record>>(p_certificate_id, std::unique_ptr<const certs_db_record>(r))); + if (result.second == false) { + loggers::get_instance().warning("certs_loader::build_certificates_cache: Failed to insert new record '%s'", p_certificate_name.c_str()); + delete r; + return -1; + } + + return 0; +} + +int certs_loader::save_certificate(const certs_db_record &p_certificate, std::string& p_certificate_id) { + + return -1; +} // End of method save_certificate + diff --git a/ccsrc/security/src/hmac.cc b/ccsrc/security/src/hmac.cc new file mode 100644 index 0000000000000000000000000000000000000000..ab5c2485b268a0f97e52d4e75c6d08f39e8c9017 --- /dev/null +++ b/ccsrc/security/src/hmac.cc @@ -0,0 +1,54 @@ +/*! + * \file hmac.cc + * \brief Source file for HMAC helper methods. + * \author ETSI STF637 + * \copyright ETSI Copyright Notification + * No part may be reproduced except as authorized by written permission. + * The copyright and the foregoing restriction extend to reproduction in all media. + * All rights reserved. + * \version 0.1 + */ +#include <TTCN3.hh> + +#include "hmac.hh" + +#include "loggers.hh" + +int hmac::generate(const OCTETSTRING p_buffer, const OCTETSTRING p_secret_key, OCTETSTRING &p_hmac) { + // Sanity check + if (p_buffer.lengthof() == 0) { + return -1; + } + + return generate(static_cast<const unsigned char *>(p_buffer), p_buffer.lengthof(), static_cast<const unsigned char *>(p_secret_key), p_secret_key.lengthof(), + p_hmac); +} + +int hmac::generate(const unsigned char *p_buffer, const size_t p_buffer_length, const unsigned char *p_secret_key, const size_t p_secret_key_length, + OCTETSTRING &p_hmac) { + // Sanity check + if ((p_buffer == nullptr) || (p_secret_key == nullptr)) { + return -1; + } + ::HMAC_CTX_reset(_ctx); + + p_hmac = int2oct(0, EVP_MAX_MD_SIZE); + if (_hash_algorithms == hash_algorithms::sha_256) { + ::HMAC_Init_ex(_ctx, (const void *)p_secret_key, (long unsigned int)p_secret_key_length, EVP_sha256(), NULL); + } else if (_hash_algorithms == hash_algorithms::sha_384) { + ::HMAC_Init_ex(_ctx, (const void *)p_secret_key, (long unsigned int)p_secret_key_length, EVP_sha384(), NULL); + } else { // TODO To be continued + return -1; + } + // Compute the hash value + ::HMAC_Update(_ctx, p_buffer, p_buffer_length); + unsigned int length = p_hmac.lengthof(); + ::HMAC_Final(_ctx, (unsigned char *)static_cast<const unsigned char *>(p_hmac), &length); + loggers::get_instance().log_to_hexa("hmac::generate: ", (unsigned char *)static_cast<const unsigned char *>(p_hmac), length); + // Resize the hmac + if (_hash_algorithms == hash_algorithms::sha_256) { + p_hmac = OCTETSTRING(16, static_cast<const unsigned char *>(p_hmac)); + } // FIXME Check length for the other hash algorithm + + return 0; +} diff --git a/ccsrc/security/src/security_externals.cc b/ccsrc/security/src/security_externals.cc new file mode 100644 index 0000000000000000000000000000000000000000..96d5b8d10e76c790a6c527de7f361285bc3bd30b --- /dev/null +++ b/ccsrc/security/src/security_externals.cc @@ -0,0 +1,82 @@ +#include "LibSecurity_Hash.hh" +#include "LibSecurity_Signature.hh" +#include "LibSecurity_Certificates.hh" + +#include "loggers.hh" + +#include "sha1.hh" +#include "sha256.hh" +#include "sha384.hh" +#include "certs_db.hh" +#include "security_services.hh" + +static std::unique_ptr<security_services> _security_services; + +INTEGER LibSecurity__Certificates::fx__init__certs__db(const CHARSTRING& p_certs_db_path) { + loggers::get_instance().log_msg(">>> fx__init__certs__db: ", p_certs_db_path); + + int ret = _security_services->initialize(std::string(static_cast<const char*>(p_certs_db_path))); + + loggers::get_instance().log("<<< fx__init__certs__db."); + return ret; +} + +INTEGER LibSecurity__Certificates::fx__load__certificate(const CHARSTRING& p_certificate_name, const CHARSTRING& p_private_key_name) { + loggers::get_instance().log_msg(">>> fx__load__certificate: ", p_certificate_name); + loggers::get_instance().log_msg(">>> fx__load__certificate: ", p_private_key_name); + + const X509* certificate; + int ret = _security_services->load_certificate(std::string(static_cast<const char*>(p_certificate_name)), std::string(static_cast<const char*>(p_private_key_name)), &certificate); + loggers::get_instance().log("fx__load__certificate: certificate: '%p'", certificate); + if (ret == 0) { + ASN1_INTEGER* asn1_serial = ::X509_get_serialNumber((X509*)certificate); + if (asn1_serial == nullptr) { + loggers::get_instance().log("fx__load__certificate: Failed to retrieve X509 serial number"); + return -1; + } + uint64_t v; + ASN1_INTEGER_get_uint64(&v, asn1_serial); + loggers::get_instance().log("fx__load__certificate: Loaded certificate: serial number: %ld", v); + } + + loggers::get_instance().log("<<< fx__load__certificate"); + return ret; +} + +OCTETSTRING LibSecurity__Hash::fx__hash(const OCTETSTRING& p_to_be_hashed, const LibSecurity__Hash::HashAlgorithm& p_hash_algorithm) { + loggers::get_instance().log_msg(">>> fx__hash: ", p_to_be_hashed); + + OCTETSTRING hash; + switch (p_hash_algorithm) { + case LibSecurity__Hash::HashAlgorithm::e__sha1: { + sha1 s; + s.generate(p_to_be_hashed, hash); + } + break; + case LibSecurity__Hash::HashAlgorithm::e__sha256: { + sha256 s; + s.generate(p_to_be_hashed, hash); + } + break; + case LibSecurity__Hash::HashAlgorithm::e__sha384: { + sha384 s; + s.generate(p_to_be_hashed, hash); + } + break; + } // End of 'switch' statement + + loggers::get_instance().log_msg("<<< fx__hash: ", hash); + return hash; +} + +INTEGER LibSecurity__Signature::fx__sign(const OCTETSTRING& p_encoded_message, const CHARSTRING& p_certificate_name, OCTETSTRING& p_signature, OCTETSTRING& p_digest, CHARSTRING& p_x509_certificate_subject, CHARSTRING& p_x509_certificate_pem) { + loggers::get_instance().log_msg(">>> fx__sign: ", p_encoded_message); + + if (_security_services->do_sign(p_encoded_message, p_certificate_name, p_signature, p_digest, p_x509_certificate_subject, p_x509_certificate_pem) == -1) { + loggers::get_instance().log("fx__sign: Failed to signed message"); + return -1; + } + + return 0; +} + \ No newline at end of file diff --git a/ccsrc/security/src/securty_services.cc b/ccsrc/security/src/securty_services.cc new file mode 100644 index 0000000000000000000000000000000000000000..455df75146b1f027e13099bbe832e13a25424f5a --- /dev/null +++ b/ccsrc/security/src/securty_services.cc @@ -0,0 +1,122 @@ +#include <openssl/evp.h> +#include <openssl/pem.h> +#include <openssl/err.h> + +#include "loggers.hh" + +#include "xml_converters.hh" + +#include "TTCN3.hh" + +#include "sha1.hh" +#include "sha256.hh" +#include "certs_loader.hh" +#include "security_services.hh" + +certs_db* security_services::_certs_db = nullptr; + +int security_services::initialize(const std::string& p_certs_db_path) { + loggers::get_instance().log(">>> security_services::initialize: '%s'", p_certs_db_path.c_str()); + + security_services::_certs_db = new certs_db(p_certs_db_path); + if (security_services::_certs_db == nullptr) { // Memory allocation issue + loggers::get_instance().warning("security_services::setup: _security_db pointer is NULL"); + return -1; + } + + loggers::get_instance().log("<<< security_services::initialize"); + return 0; +} + +int security_services::load_certificate(const std::string& p_certificate_name, const std::string& p_private_key_name, const X509** p_certificate) { + loggers::get_instance().log("security_services::load_certificate: '%s'", p_certificate_name.c_str()); + loggers::get_instance().log("security_services::load_certificate: '%s'", p_private_key_name.c_str()); + + return _certs_db->get_certificate(p_certificate_name, p_private_key_name, p_certificate); +} + +int security_services::do_sign(const OCTETSTRING& p_encoded_message, const CHARSTRING& p_certificate_name, OCTETSTRING& p_signature, OCTETSTRING& p_digest, CHARSTRING& p_x509_certificate_subject, CHARSTRING& p_x509_certificate_pem) { + loggers::get_instance().log_msg(">>> security_services::do_sign: ", p_encoded_message); + loggers::get_instance().log_msg(">>> security_services::do_sign: ", p_certificate_name); + + // Canonicalization + std::string canonicalized; + xml_converters::get_instance().xml_canonicalization(std::string((const char*)(static_cast<const unsigned char*>(p_encoded_message))), canonicalized); + OCTETSTRING encoded_message(char2oct(CHARSTRING(canonicalized.c_str()))); + loggers::get_instance().log("security_services::do_sign: canonicalized: '%s", canonicalized.c_str()); + + // Retrieve certificate + std::string certificate_id; + if (certs_loader::get_instance().get_certificate_id(std::string(static_cast<const char*>(p_certificate_name)), certificate_id) != 0) { + loggers::get_instance().warning("fx__sign: Failed to retrieve certificate identifier"); + return -1; + } + loggers::get_instance().log("fx__sign: certificate_id: '%s'", certificate_id.c_str()); + const X509* certificate; + if (_certs_db->get_certificate(certificate_id, &certificate) != 0) { + loggers::get_instance().warning("fx__sign: Failed to retrieve certificate"); + return -1; + } + X509_NAME* sn = X509_get_subject_name((X509*)certificate); + std::string subject(512, (char)0x00); + X509_NAME_oneline(sn, (char*)subject.c_str(), subject.length()); + loggers::get_instance().log("fx__sign: certificate_id: X509_NAME_oneline: '%s'", subject.c_str()); + p_x509_certificate_subject = CHARSTRING(subject.c_str()); + X509_free((X509*)certificate); + + p_x509_certificate_pem = ""; // TODO + + // Compute the digest + sha256 digest; + digest.generate(char2oct(CHARSTRING(canonicalized.c_str())), p_digest); + loggers::get_instance().log_msg("fx__sign: certificate_id: p_digest: ", p_digest); + + // Retrive the private key + const EVP_PKEY* private_key; + int ret = _certs_db->get_private_key(certificate_id, &private_key); + if (ret == 1) { + loggers::get_instance().warning("fx__sign: Failed to retrieve private key"); + return -1; + } + loggers::get_instance().log("fx__sign: certificate_id: private_key: '%p'", private_key); + + // Create signing context + EVP_MD_CTX* ctx = ::EVP_MD_CTX_new(); + if (ctx == NULL) { + loggers::get_instance().warning("fx__sign: EVP_MD_CTX_create failed, error 0x%lx", ::ERR_get_error()); + return -1; + } + if (::EVP_DigestSignInit(ctx, NULL, EVP_sha256(), NULL, (EVP_PKEY*)private_key) != 1) { // FIXME Add parameter to chose the digest algorithm + loggers::get_instance().warning("fx__sign: EVP_DigestSignInit failed, error 0x%lx", ::ERR_get_error()); + ::EVP_MD_CTX_free(ctx); + return -1; + } + if (::EVP_DigestSignUpdate(ctx, (const unsigned char*)canonicalized.c_str(), canonicalized.length()) != 1) { + loggers::get_instance().warning("fx__sign: EVP_DigestSignUpdate failed, error 0x%lx", ::ERR_get_error()); + ::EVP_MD_CTX_free(ctx); + return -1; + } + // Get signature lengthof + size_t signature_length = 0; + if (::EVP_DigestSignFinal(ctx, NULL, &signature_length) != 1) { + loggers::get_instance().warning("fx__sign: EVP_DigestSignUpdate failed, error 0x%lx", ::ERR_get_error()); + ::EVP_MD_CTX_free(ctx); + return -1; + } + loggers::get_instance().log("fx__sign: signature_length: %d", signature_length); + std::vector<unsigned char> s(signature_length, 0x00); + unsigned char* val = s.data(); + if (::EVP_DigestSignFinal(ctx, val, &signature_length) != 1) { + loggers::get_instance().warning("fx__sign: EVP_DigestSignUpdate failed, error 0x%lx", ::ERR_get_error()); + ::EVP_MD_CTX_free(ctx); + s.clear(); + return -1; + } + + p_signature = OCTETSTRING(signature_length, s.data()); + + ::EVP_MD_CTX_free(ctx); + loggers::get_instance().log_msg("fx__sign: signature: ", p_signature); + + return 0; +} \ No newline at end of file diff --git a/ccsrc/security/src/sha1.cc b/ccsrc/security/src/sha1.cc new file mode 100644 index 0000000000000000000000000000000000000000..bd9386d1d0075e36de8de94a263757ba97df84cd --- /dev/null +++ b/ccsrc/security/src/sha1.cc @@ -0,0 +1,39 @@ +/*! + * \file sha1.cc + * \brief Source file for SHA-1 helper methods. + * \author ETSI STF637 + * \copyright ETSI Copyright Notification + * No part may be reproduced except as authorized by written permission. + * The copyright and the foregoing restriction extend to reproduction in all media. + * All rights reserved. + * \version 0.1 + */ +#include <TTCN3.hh> + +#include "sha1.hh" + +int sha1::generate(const OCTETSTRING& p_buffer, OCTETSTRING& p_hash) { + // Sanity check + if (p_buffer.lengthof() == 0) { + p_hash = get_sha1_empty_string(); + return 0; + } + + return generate(static_cast<const unsigned char*>(p_buffer), p_buffer.lengthof(), p_hash); +} + +int sha1::generate(const unsigned char* p_buffer, const size_t p_length, OCTETSTRING& p_hash) { + // Sanity check + if ((p_buffer == nullptr) || (p_length == 0)) { + p_hash = get_sha1_empty_string(); + return 0; + } + + // Resize data buffer + p_hash = int2oct(0, SHA_DIGEST_LENGTH); + // Compute the hash value + ::SHA1_Init(&_ctx); + ::SHA1_Update(&_ctx, p_buffer, p_length); + ::SHA1_Final((unsigned char*)static_cast<const unsigned char*>(p_hash), &_ctx); + return 0; +}; diff --git a/ccsrc/security/src/sha256.cc b/ccsrc/security/src/sha256.cc new file mode 100644 index 0000000000000000000000000000000000000000..e1fdf07ef2076cddaef3cc7648d30c40e96533db --- /dev/null +++ b/ccsrc/security/src/sha256.cc @@ -0,0 +1,39 @@ +/*! + * \file sha256.cc + * \brief Source file for SHA-256 helper methods. + * \author ETSI STF637 + * \copyright ETSI Copyright Notification + * No part may be reproduced except as authorized by written permission. + * The copyright and the foregoing restriction extend to reproduction in all media. + * All rights reserved. + * \version 0.1 + */ +#include <TTCN3.hh> + +#include "sha256.hh" + +int sha256::generate(const OCTETSTRING& p_buffer, OCTETSTRING& p_hash) { + // Sanity check + if (p_buffer.lengthof() == 0) { + p_hash = get_sha256_empty_string(); + return 0; + } + + return generate(static_cast<const unsigned char*>(p_buffer), p_buffer.lengthof(), p_hash); +} + +int sha256::generate(const unsigned char* p_buffer, const size_t p_length, OCTETSTRING& p_hash) { + // Sanity check + if ((p_buffer == nullptr) || (p_length == 0)) { + p_hash = get_sha256_empty_string(); + return 0; + } + + // Resize data buffer + p_hash = int2oct(0, SHA256_DIGEST_LENGTH); + // Compute the hash value + ::SHA256_Init(&_ctx); + ::SHA256_Update(&_ctx, p_buffer, p_length); + ::SHA256_Final((unsigned char*)static_cast<const unsigned char*>(p_hash), &_ctx); + return 0; +}; diff --git a/ccsrc/security/src/sha384.cc b/ccsrc/security/src/sha384.cc new file mode 100644 index 0000000000000000000000000000000000000000..9ad92fbd043f3e5d838ca089147ee16510b13891 --- /dev/null +++ b/ccsrc/security/src/sha384.cc @@ -0,0 +1,47 @@ +/*! + * \file sha384.cc + * \brief Sorce file for SHA-384 helper methods. + * \author ETSI STF637 + * \copyright ETSI Copyright Notification + * No part may be reproduced except as authorized by written permission. + * The copyright and the foregoing restriction extend to reproduction in all media. + * All rights reserved. + * \version 0.1 + */ +#include <TTCN3.hh> + +#include "sha384.hh" + +int sha384::generate(const OCTETSTRING &p_buffer, OCTETSTRING &p_hash) { + // Sanity check + if (p_buffer.lengthof() == 0) { + p_hash = get_sha384_empty_string(); + return 0; + } + + return generate(static_cast<const unsigned char *>(p_buffer), p_buffer.lengthof(), p_hash); +} + +int sha384::generate(const unsigned char *p_buffer, const size_t p_length, OCTETSTRING &p_hash) { + // Sanity check + if ((p_buffer == nullptr) || (p_length == 0)) { + p_hash = get_sha384_empty_string(); + return 0; + } + + // Resize data buffer + p_hash = int2oct(0, SHA384_DIGEST_LENGTH); + // Compute the hash value + ::SHA384_Init(&_ctx); + ::SHA384_Update(&_ctx, p_buffer, p_length); + ::SHA384_Final((unsigned char *)static_cast<const unsigned char *>(p_hash), &_ctx); + return 0; +} + +const OCTETSTRING sha384::get_sha384_empty_string() const { + static unsigned char + sha384_empty_string[] = {0x38, 0xb0, 0x60, 0xa7, 0x51, 0xac, 0x96, 0x38, 0x4c, 0xd9, 0x32, 0x7e, 0xb1, 0xb1, 0xe3, 0x6a, + 0x21, 0xfd, 0xb7, 0x11, 0x14, 0xbe, 0x07, 0x43, 0x4c, 0x0c, 0xc7, 0xbf, 0x63, 0xf6, 0xe1, 0xda, + 0x27, 0x4e, 0xde, 0xbf, 0xe7, 0x6f, 0x65, 0xfb, 0xd5, 0x1a, 0xd2, 0xf1, 0x48, 0x98, 0xb9, 0x5b}; //! SHA-384 of an empty string + return OCTETSTRING(48, sha384_empty_string); +} diff --git a/ttcn/LibSecurity/module.mk b/ttcn/LibSecurity/module.mk new file mode 100644 index 0000000000000000000000000000000000000000..4514de44b0bc85ce6118e9784c5667f77a419276 --- /dev/null +++ b/ttcn/LibSecurity/module.mk @@ -0,0 +1,5 @@ +sources := \ + ttcn/LibSecurity_Hash.ttcn \ + ttcn/LibSecurity_Hmac.ttcn \ + ttcn/LibSecurity_Signature.ttcn \ + ttcn/LibSecurity_Certificates.ttcn diff --git a/ttcn/LibSecurity/ttcn/LibSecurity_Certificates.ttcn b/ttcn/LibSecurity/ttcn/LibSecurity_Certificates.ttcn new file mode 100644 index 0000000000000000000000000000000000000000..4fba516a91f186d096bae5d885d0c454a1f84015 --- /dev/null +++ b/ttcn/LibSecurity/ttcn/LibSecurity_Certificates.ttcn @@ -0,0 +1,15 @@ +module LibSecurity_Certificates { + + external function fx_init_certs_db(in charstring p_certs_db_path) return integer; + + external function fx_load_certificate(in charstring p_certificate_name, in charstring p_private_key_name) return integer; + + function f_init_certs_db(in charstring p_certs_db_path) return integer { + return fx_init_certs_db(p_certs_db_path); + } + + function f_load_certificate(in charstring p_certificate_name, in charstring p_private_key_name) return integer { + return fx_load_certificate(p_certificate_name, p_private_key_name); + } + +} // End of LibSecurity_Certificates \ No newline at end of file diff --git a/ttcn/LibSecurity/ttcn/LibSecurity_Hash.ttcn b/ttcn/LibSecurity/ttcn/LibSecurity_Hash.ttcn new file mode 100644 index 0000000000000000000000000000000000000000..ecebd4f4da81c71c051e918bcb1695cdff7449b1 --- /dev/null +++ b/ttcn/LibSecurity/ttcn/LibSecurity_Hash.ttcn @@ -0,0 +1,21 @@ +module LibSecurity_Hash { + + type enumerated HashAlgorithm { + e_sha1, + e_sha256, + e_sha384 + } // End of type HashAlgorithm + + function f_hash( + in octetstring p_to_be_hased, + in HashAlgorithm p_hash_algorithm + ) return octetstring { + return fx_hash(p_to_be_hased, p_hash_algorithm); + } // End of function f_hash + + external function fx_hash( + in octetstring p_to_be_hased, + in HashAlgorithm p_hash_algorithm + ) return octetstring; + +} // End of module LibSecurity_Hash diff --git a/ttcn/LibSecurity/ttcn/LibSecurity_Hmac.ttcn b/ttcn/LibSecurity/ttcn/LibSecurity_Hmac.ttcn new file mode 100644 index 0000000000000000000000000000000000000000..8f99e4eb542dcd04d69e9b4c1bc540f3389505a9 --- /dev/null +++ b/ttcn/LibSecurity/ttcn/LibSecurity_Hmac.ttcn @@ -0,0 +1,2 @@ +module LibSecurity_Hmac { +} // End of LibSecurity_Hmac \ No newline at end of file diff --git a/ttcn/LibSecurity/ttcn/LibSecurity_Signature.ttcn b/ttcn/LibSecurity/ttcn/LibSecurity_Signature.ttcn new file mode 100644 index 0000000000000000000000000000000000000000..614caf60416be6fc98534369b6d55cb38b95c9d5 --- /dev/null +++ b/ttcn/LibSecurity/ttcn/LibSecurity_Signature.ttcn @@ -0,0 +1,26 @@ +module LibSecurity_Signature { + + import from LibSecurity_Hash all; + + /** + * @desc + * @param [in] p_encoded_message The raw message to be signed + * @param [in] p_hash_algorithm The Hash algorithm to use + * @param [in] p_certificate_name The certificate to use for the signature + * @param [in] p_signature The raw signature + * @return 0 on success, -1 otherwise + */ + function f_sign( + in octetstring p_encoded_message, + in charstring p_certificate_name, + out octetstring p_signature, + out octetstring p_digest, + out charstring p_x509_certificate_subject, + out charstring p_x509_certificate_pem + ) return integer { + return fx_sign(p_encoded_message, p_certificate_name, p_signature, p_digest, p_x509_certificate_subject, p_x509_certificate_pem); + } + + external function fx_sign(in octetstring p_encoded_message, in charstring p_certificate_name, out octetstring p_signature, out octetstring p_digest, out charstring p_x509_certificate_subject, out charstring p_x509_certificate_pem) return integer; + +} // End of LibSecurity_Signature \ No newline at end of file