diff --git a/ccsrc/Framework/include/converter.hh b/ccsrc/Framework/include/converter.hh index 844b43c393e052b1c15b8c58d37a6e3e48b58823..7f2adeb95c0c3b21cb2fd96f6d1c20f0199e4fc4 100644 --- a/ccsrc/Framework/include/converter.hh +++ b/ccsrc/Framework/include/converter.hh @@ -371,17 +371,17 @@ public: * \param[in] p_value The buffer value * \return The Base64 encoded buffert */ - std::vector buffer_to_base64(const std::vector &p_value); + std::vector buffer_to_base64(const std::vector &p_value, const bool p_is_url = false); /*! * \brief Convert the provided Base64 buffer * \param[in] p_value The buffer value * \return The Base64 encoded buffert */ - std::vector base64_to_buffer(const std::vector &p_value); + std::vector base64_to_buffer(const std::vector &p_value, const bool p_remove_crlf = true); static const std::string lut_u; static const std::string lut_l; - static const std::string base64_enc_map; + static const std::string base64_enc_map[2]; }; // End of class converter diff --git a/ccsrc/Framework/src/converter.cc b/ccsrc/Framework/src/converter.cc index 7a9a0cc1102ab5ff65cbf54da6e44182b4028096..0b2f376fea4df9c80abafdaec532f356cbbb1b81 100644 --- a/ccsrc/Framework/src/converter.cc +++ b/ccsrc/Framework/src/converter.cc @@ -1,5 +1,7 @@ #include "converter.hh" + #include + converter *converter::instance = NULL; uint16_t converter::swap(const uint16_t p_value) { @@ -40,22 +42,22 @@ std::string converter::string_to_hexa(const std::string& p_value, const bo } std::string converter::bytes_to_hexa(const std::vector &p_value, const bool p_uppercase) { - std::string ret; - ret.assign(p_value.size() * 2, ' '); + std::string out; + out.assign(p_value.size() * 2, ' '); if (p_uppercase) { // TODO Use pointer to reduce code size for (size_t i = 0; i < p_value.size(); i++) { uint8_t c = p_value[i]; - ret[i * 2] = lut_u[c >> 4]; - ret[i * 2 + 1] = lut_u[c & 0xF]; + out[i * 2] = lut_u[c >> 4]; + out[i * 2 + 1] = lut_u[c & 0xF]; } } else { for (size_t i = 0; i < p_value.size(); i++) { uint8_t c = p_value[i]; - ret[i * 2] = lut_l[c >> 4]; - ret[i * 2 + 1] = lut_l[c & 0xF]; + out[i * 2] = lut_l[c >> 4]; + out[i * 2 + 1] = lut_l[c & 0xF]; } } - return ret; + return out; } inline uint8_t char2byte(const char p_ch) { @@ -147,49 +149,112 @@ std::vector converter::split_arguments_line(const std::string& p_va return output; } -const std::string converter::base64_enc_map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +const std::string converter::base64_enc_map[2] = { + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" + }; + +/** + * @brief Return the position of chr within base64_encode() + * @param[in] chr + * @return Return the position of chr within base64_encode() + */ +static unsigned char pos_of_char(const unsigned char chr) { + if ((chr >= 'A' && chr <= 'Z')) { + return static_cast(chr - 'A'); + } else if ((chr >= 'a' && chr <= 'z')) { + return static_cast(chr - 'a' + ('Z' - 'A') + 1); + } else if ((chr >= '0' && chr <= '9')) { + return static_cast(chr - '0' + ('Z' - 'A') + ('z' - 'a') + 2); + } else if ((chr == '+' || chr == '-')) { + return 62; // Be liberal with input and accept both url ('-') and non-url ('+') base 64 characters ( + } else if ((chr == '/' || chr == '_')) { + return 63; // Idem for '/' and '_' + } else { + throw std::runtime_error("Input is not valid base64-encoded data."); + } +} + +static std::string insert_linebreaks(std::string str, size_t distance) { + if (!str.length()) { + return ""; + } + size_t pos = distance; + while (pos < str.size()) { + str.insert(pos, "\n"); + pos += distance + 1; + } + return str; +} + +std::vector converter::buffer_to_base64(const std::vector &p_value, const bool p_is_url) { + const std::string& base64_enc_map_ = converter::base64_enc_map[(p_is_url) ? 1 : 0]; + const unsigned char trailing_char = (p_is_url) ? '.' : '='; -std::vector converter::buffer_to_base64(const std::vector &p_value) { std::vector out; + //out.resize((p_value.size() + 2) / 3 * 4); - int val = 0, valb = -6; - for (unsigned char c : p_value) { - val = (val << 8) + c; - valb += 8; - while (valb >= 0) { - out.push_back(converter::base64_enc_map[(val >> valb) & 0x3F]); - valb -= 6; + unsigned int pos = 0; + while (pos < p_value.size()) { + out.push_back(base64_enc_map_[(p_value[pos + 0] & 0xfc) >> 2]); + + if (pos+1 < p_value.size()) { + out.push_back(base64_enc_map_[((p_value[pos + 0] & 0x03) << 4) + ((p_value[pos + 1] & 0xf0) >> 4)]); + + if (pos+2 < p_value.size()) { + out.push_back(base64_enc_map_[((p_value[pos + 1] & 0x0f) << 2) + ((p_value[pos + 2] & 0xc0) >> 6)]); + out.push_back(base64_enc_map_[ p_value[pos + 2] & 0x3f]); + } else { + out.push_back(base64_enc_map_[(p_value[pos + 1] & 0x0f) << 2]); + out.push_back(trailing_char); + } + } else { + out.push_back(base64_enc_map_[(p_value[pos + 0] & 0x03) << 4]); + out.push_back(trailing_char); + out.push_back(trailing_char); + } + pos += 3; } // End of 'while' statement - } // End of 'for' statement - if (valb > -6) { - out.push_back(converter::base64_enc_map[((val << 8) >> (valb + 8)) & 0x3F]); - } - while (out.size() % 4) { - out.push_back('='); - } // End of 'while' statement return out; } -std::vector converter::base64_to_buffer(const std::vector &p_value) { - std::vector out; +std::vector converter::base64_to_buffer(const std::vector &p_value, const bool p_remove_crlf) { - std::vector T(256, -1); - for (int i = 0; i < 64; i++) { - T[converter::base64_enc_map[i]] = i; + if (p_value.size() == 0) { + return std::vector(); } - int val = 0, valb = -8; - for (unsigned char c : p_value) { - if (T[c] == -1) { - break; - } - val = (val << 6) + T[c]; - valb += 6; - if (valb >= 0) { - out.push_back((unsigned char)char((val >> valb) & 0xFF)); - valb -= 8; + std::vector value(p_value); + if (p_remove_crlf) { + value.erase(std::remove(value.begin(), value.end(), '\r'), value.end()); + value.erase(std::remove(value.begin(), value.end(), '\n'), value.end()); + } + + std::vector out; + //out.resize(value.size() / 4 * 3); + + size_t pos = 0; + while (pos < value.size()) { + size_t pos_of_char_1 = pos_of_char(value[pos + 1]); + out.push_back(((pos_of_char(value[pos])) << 2 ) + ( (pos_of_char_1 & 0x30 ) >> 4)); + + if ((pos + 2 < value.size()) && // Check for data that is not padded with equal signs (which is allowed by RFC 2045) + value[pos + 2] != '=' && + value[pos + 2] != '.' // accept URL-safe base 64 strings, too, so check for '.' also. + ) { + //Emit a chunk's second byte (which might not be produced in the last chunk). + unsigned int pos_of_char_2 = pos_of_char(value[pos + 2]); + out.push_back(((pos_of_char_1 & 0x0f) << 4) + ((pos_of_char_2 & 0x3c) >> 2)); + + if ((pos + 3 < value.size()) && value[pos + 3] != '=' && value[pos + 3] != '.' ) { + // Emit a chunk's third byte (which might not be produced in the last chunk). + out.push_back(((pos_of_char_2 & 0x03 ) << 6) + pos_of_char(value[pos + 3])); + } } - } // End of 'for' statement + + pos += 4; + } // End of 'while' statement + return out; } diff --git a/ccsrc/Protocols/Http/http_codec.cc b/ccsrc/Protocols/Http/http_codec.cc index 9240129ff9232034ad107dffd43bfb78286473df..270c6c19e65c8b76211eb7c6d96bd9ebecf51d22 100644 --- a/ccsrc/Protocols/Http/http_codec.cc +++ b/ccsrc/Protocols/Http/http_codec.cc @@ -449,8 +449,8 @@ int http_codec::encode_body(const LibHttp__MessageBodyTypes::HttpMessageBody &p_ } } else if (p_message_body.ischosen(LibHttp__MessageBodyTypes::HttpMessageBody::ALT_xml__body)) { const LibHttp__XmlMessageBodyTypes::XmlBody &xml_body = p_message_body.xml__body(); - if (xml_body.ischosen(LibHttp__XmlMessageBodyTypes::XmlBody::ALT_raw)) { - p_encoding_buffer = OCTETSTRING(xml_body.raw().lengthof(), (unsigned char *)static_cast(xml_body.raw())); + if (xml_body.msg().ischosen(LibHttp__XmlMessageBodyTypes::XmlBodyMsg::ALT_raw)) { + p_encoding_buffer = OCTETSTRING(xml_body.msg().raw().lengthof(), (unsigned char *)static_cast(xml_body.msg().raw())); } else { encode_body_xml(xml_body, p_encoding_buffer, p_content_type); } diff --git a/ccsrc/Protocols/Tcp/tcp_layer.cc b/ccsrc/Protocols/Tcp/tcp_layer.cc index c077355c5e9b6994d60803e4c1a10cc9b40d3227..fdbeb3580a1341164497fe821dcd46708d0fbe7c 100644 --- a/ccsrc/Protocols/Tcp/tcp_layer.cc +++ b/ccsrc/Protocols/Tcp/tcp_layer.cc @@ -37,6 +37,8 @@ void tcp_layer::init() { it = _params.find(std::string("tcp_fragmented")); if (it == _params.cend()) { _params.insert(std::pair(std::string("tcp_fragmented"), "0")); + } else { + _params.insert(std::pair(std::string("tcp_fragmented"), "1")); } bool server_mode = false; it = _params.find(params::server_mode); @@ -257,7 +259,7 @@ int tcp_layer::receive_message_on_fd(int p_client_id) loggers::get_instance().log("tcp_layer::receive_message_on_fd: Non secured mode"); if (_params[std::string("tcp_fragmented")].compare("1") == 0) { - sleep(5); // FIXME When HTTP paquet is fragmented into several TCP packets, a timer is required. This is a Q&D solution + sleep(4); // FIXME When HTTP paquet is fragmented into several TCP packets, a timer is required. This is a Q&D solution } return Abstract_Socket::receive_message_on_fd(p_client_id); } diff --git a/ccsrc/security/include/certs_cache.hh b/ccsrc/security/include/certs_cache.hh index 7d33e4ffc9b9161f7ebb63078bb275e4638de0d0..70e24a3f6b92f332face82f492268b72ff1f6d9a 100644 --- a/ccsrc/security/include/certs_cache.hh +++ b/ccsrc/security/include/certs_cache.hh @@ -30,6 +30,7 @@ class certs_cache { protected: /*! \protectedsection */ // TODO Enforce with const security_cache_record, and const std::string std::map _certificates_idx; //! List of the certificate names indexed by the certificate identifier, i.e. the SH1 of the certificate name + std::map _certificates_subject; //! List of the certificates indexed by the certificate subject name std::map> _certificates; //! List of the certificates indexed by the certificate identifier public: /*! \publicsection */ @@ -42,7 +43,7 @@ public: /*! \publicsection */ */ virtual ~certs_cache(); - int get_certificate(const std::string& p_certificate_name, const std::string& p_private_key_name, const X509** p_certificate); + int get_certificate(const std::string& p_certificate_name, const std::string& p_private_key_name, const std::string& p_private_key_passwd, 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 @@ -51,7 +52,9 @@ public: /*! \publicsection */ * \return 0 on success, -1 otherwise */ int get_certificate(const std::string& p_certificate_id, const X509** p_certificate); - /*! + + int get_certificate_by_subject_name(const std::string& p_certificate_subject_name, 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 @@ -70,7 +73,7 @@ public: /*! \publicsection */ int get_certificate_pem(const std::string& p_certificate_id, std::string& p_certificate_pem); - virtual int store_certificate(const std::string& p_certificate_name, const std::string& p_certificate, const EVP_PKEY* p_private_key); + int store_certificate(const std::string& p_certificate_name, const std::string& p_certificate, std::string& p_certificate_id, const certs_db_record** p_record); /*! * \fn int int clear(); @@ -84,14 +87,15 @@ public: /*! \publicsection */ 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); + * \fn int load_certificate(const std::string& p_certificate_name, const std::string& p_private_key_name, const std::string& p_private_key_passwd, 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[in] p_private_key_name The certificate's private key name, in PKCS#8 format + * \param[in] p_private_key_passwd The certificate's private key password for PKCS#8 format encryption. Empty if no encryption * \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); + int load_certificate(const std::string& p_certificate_name, const std::string& p_private_key_name, const std::string& p_private_key_passwd, 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 diff --git a/ccsrc/security/include/certs_db.hh b/ccsrc/security/include/certs_db.hh index adb4e141ab4e280b4b441453b8116fe679bd0e51..609ae4f6f0cd8cbff33adc809e6e536d11ca31cc 100644 --- a/ccsrc/security/include/certs_db.hh +++ b/ccsrc/security/include/certs_db.hh @@ -30,14 +30,6 @@ public: /*! \publicsection */ */ ~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); diff --git a/ccsrc/security/include/certs_db_record.hh b/ccsrc/security/include/certs_db_record.hh index 17de815833866285292d5992366e6e2aef8b1a9e..302b0f89a1e7f7c43b570d4c6bf851b6a656f916 100644 --- a/ccsrc/security/include/certs_db_record.hh +++ b/ccsrc/security/include/certs_db_record.hh @@ -61,5 +61,6 @@ public: /*! \publicsection */ 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); }; + inline const X509_NAME* subject_name() const { return ::X509_get_subject_name(_certificate); }; inline const std::string& pem() const { return _pem; }; }; // End of class certs_db_record diff --git a/ccsrc/security/include/certs_loader.hh b/ccsrc/security/include/certs_loader.hh index 3f408c6617c83b51cd626e6b8620a2da5ec03c70..ef7de835558334e0918434e8f78b33d24eadb75a 100644 --- a/ccsrc/security/include/certs_loader.hh +++ b/ccsrc/security/include/certs_loader.hh @@ -76,22 +76,24 @@ public: /*! \publicsection */ */ 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> & p_certificates); + * \fn int load_certificate(const std::string& p_certificate_name, const std::string& p_private_key_name, const std::string& p_private_key_passwd, std::map> & 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[in] p_private_key_name The certificate's private key full path name, in PKCS#8 format + * \param[in] p_private_key_passwd The certificate's private key password for PKCS#8 format encryption. Empty if no encryption * \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> & p_certificates); + int load_certificate(const std::string& p_certificate_name, const std::string& p_private_key_name, const std::string& p_private_key_passwd, std::string& p_certificate_id, std::map> & p_certificates); /*! - * \fn int save_certificate(const certs_db_record &p_certificate); + * \fn int store_certificate(const std::string& p_certificate_name, const std::string& p_certificate_pem, std::string& p_certificate_id, std::map> & p_certificates); * \brief Save the specified certificate and update the internal maps - * \param[in] p_certificate The certificate to save + * \param[in] p_certificate_name The certificate neame + * \param[in] p_certificate_pem The certificate to save in PEM format * \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); + int store_certificate(const std::string& p_certificate_name, const std::string& p_certificate_pem, std::string& p_certificate_id, std::map> & p_certificates); }; // End of class certs_loader diff --git a/ccsrc/security/include/security_services.hh b/ccsrc/security/include/security_services.hh index 07b43eca8ecd6678c31596f29c48267989dd36e9..55befe0acc9b95566bad23b0a01248c72fce13a5 100644 --- a/ccsrc/security/include/security_services.hh +++ b/ccsrc/security/include/security_services.hh @@ -30,11 +30,34 @@ public: /*! \publicsection */ }; 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 load_certificate(const std::string& p_certificate_name, const std::string& p_private_key_name, const std::string& p_private_key_passwd, std::map> & 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, in PKCS#8 format + * \param[in] p_private_key_passwd The certificate's private key password for PKCS#8 format encryption. Empty if no encryption + * \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, const std::string& p_private_key_passwd, const X509** p_certificate); + /*! + * \fn int do_sign(const OCTETSTRING& p_encoded_message, const CHARSTRING& p_certificate_name, const CHARSTRING& p_private_key_name, const CHARSTRING& p_private_key_passwd, OCTETSTRING& p_signature, OCTETSTRING& p_digest, CHARSTRING& p_x509_certificate_subject, CHARSTRING& p_x509_certificate_pem); + * \brief Sign message + * \param[in] p_encoded_message The raw message to be signed + * \param[in] p_encoded_message The raw message to be signed + * \param[in] p_encoded_message The raw message to be signed + * \param[in] p_encoded_message The raw message to be signed + * \param[in] p_encoded_message The raw message to be signed + * \return 0 on success, -1 otherwise + */ + int do_sign(const OCTETSTRING& p_encoded_message, const CHARSTRING& p_certificate_name, const CHARSTRING& p_private_key_name, const CHARSTRING& p_private_key_passwd, OCTETSTRING& p_signature, OCTETSTRING& p_digest, CHARSTRING& p_x509_certificate_subject, CHARSTRING& p_x509_certificate_pem, CHARSTRING& p_pull_request_signed_canonicalized); /*! * \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 + * \brief Verify message signature + * \param[in] p_message The raw message to be verified + * \param[in] TODO + * \return true on success, false otherwise */ - 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); + bool do_sign_verify(const CHARSTRING& p_message, const UNIVERSAL_CHARSTRING& p_canonicalization_method, const UNIVERSAL_CHARSTRING& p_signature_method, const UNIVERSAL_CHARSTRING& p_digest_method, const UNIVERSAL_CHARSTRING& p_digest_value, const UNIVERSAL_CHARSTRING& p_signature_value, const UNIVERSAL_CHARSTRING& p_subject_name, const UNIVERSAL_CHARSTRING& p_certificate); }; \ No newline at end of file diff --git a/ccsrc/security/src/certs_cache.cc b/ccsrc/security/src/certs_cache.cc index 2aa7a5c7488d1ed06b5362133cb28f725c915d6c..c41d7b06f6b07841525ec14d954ccce3f3517d50 100644 --- a/ccsrc/security/src/certs_cache.cc +++ b/ccsrc/security/src/certs_cache.cc @@ -19,7 +19,7 @@ #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() : _certificates_idx(), _certificates_subject(), _certificates() { loggers::get_instance().log(">>> certs_cache::certs_cache"); } // End of ctor certs_cache::~certs_cache() { loggers::get_instance().log(">>> certs_cache::~certs_cache"); @@ -30,6 +30,7 @@ int certs_cache::clear() { loggers::get_instance().log(">>> certs_cache::clear"); _certificates.clear(); // Smart pointers will do the job _certificates_idx.clear(); + _certificates_subject.clear(); return 0; } // End of clear method @@ -49,7 +50,7 @@ int certs_cache::load_certificate(const std::string& p_certificate_id, const cer 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) { +int certs_cache::load_certificate(const std::string& p_certificate_name, const std::string& p_private_key_name, const std::string& p_private_key_passwd, 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; @@ -62,26 +63,34 @@ int certs_cache::load_certificate(const std::string& p_certificate_name, const s std::map::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) { + if (certs_loader::get_instance().load_certificate(p_certificate_name, p_private_key_name, p_private_key_passwd, certificate_id, _certificates) == -1) { loggers::get_instance().warning("certs_cache::load_certificate: Failed to load certificate"); return -1; } + // Certificate is on the DB, load it + std::map>::const_iterator it = _certificates.find(certificate_id); + *p_record = it->second.get(); // Mapping certificate id/certificate name _certificates_idx.insert(std::pair(certificate_id, p_certificate_name)); + std::string sn(512, (char)0x00); + const X509_NAME* subject = (*p_record)->subject_name(); + ::X509_NAME_oneline(subject, sn.data(), sn.length()); + loggers::get_instance().log("certs_cache::load_certificate: sn: '%s'", sn.c_str()); + _certificates_subject.insert(std::pair(sn, certificate_id)); + } else { + // Certificate is on the DB, load it + std::map>::const_iterator it = _certificates.find(certificate_id); + *p_record = it->second.get(); } - // Certificate is on the DB, load it if required - std::map>::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) { +int certs_cache::get_certificate(const std::string& p_certificate_name, const std::string& p_private_key_name, const std::string& p_private_key_passwd, 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) { + if (load_certificate(p_certificate_name, p_private_key_name, p_private_key_passwd, &record) == -1) { loggers::get_instance().warning("certs_cache::get_certificate (1): Failed to load certificate"); return -1; } @@ -107,6 +116,24 @@ int certs_cache::get_certificate(const std::string& p_certificate_id, const X509 return 0; } +int certs_cache::get_certificate_by_subject_name(const std::string& p_certificate_subject_name, const X509** p_certificate) { + loggers::get_instance().log(">>> certs_cache::get_certificate_by_subject_name: '%s'", p_certificate_subject_name.c_str()); + + std::map::const_iterator s = _certificates_subject.find(p_certificate_subject_name); + if (s == _certificates_subject.cend()) { // Certificate is not in the DB + loggers::get_instance().warning("certs_cache::get_certificate_by_subject_name: Record not found"); + return -1; + } + + if (get_certificate(s->second, p_certificate) == -1) { + loggers::get_instance().error("certs_cache::get_certificate_by_subject_name: DB corrupted: '%s'", s->second.c_str()); + return -1; + } + loggers::get_instance().log("certs_cache::get_certificate_by_subject_name: 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()); @@ -147,15 +174,30 @@ int certs_cache::get_certificate_pem(const std::string& p_certificate_id, std::s } p_certificate_pem = record->pem(); - loggers::get_instance().log("certs_cache::get_certificate_pem: p_certificate_pem: '%s'", p_certificate_pem); + loggers::get_instance().log("certs_cache::get_certificate_pem: p_certificate_pem: '%s'", p_certificate_pem.c_str()); return 0; } -int certs_cache::store_certificate(const std::string& p_certificate_name, const std::string& p_certificate, const EVP_PKEY* p_private_key) { +int certs_cache::store_certificate(const std::string& p_certificate_name, const std::string& p_certificate_pem, std::string& p_certificate_id, const certs_db_record** p_record) { loggers::get_instance().log(">>> certs_cache::store_certificate: '%s'", p_certificate_name.c_str()); - return -1; + if (certs_loader::get_instance().store_certificate(p_certificate_name, p_certificate_pem, p_certificate_id, _certificates) == -1) { + loggers::get_instance().warning("certs_cache::store_certificate: Failed to load certificate"); + return -1; + } + // Certificate is on the DB, load it + std::map>::const_iterator it = _certificates.find(p_certificate_id); + *p_record = it->second.get(); + // Mapping certificate id/certificate name + _certificates_idx.insert(std::pair(p_certificate_id, p_certificate_name)); + std::string sn(512, (char)0x00); + const X509_NAME* subject = (*p_record)->subject_name(); + ::X509_NAME_oneline(subject, sn.data(), sn.length()); + loggers::get_instance().log("certs_cache::store_certificate: sn: '%s'", sn.c_str()); + _certificates_subject.insert(std::pair(sn, p_certificate_id)); + + return 0; } void certs_cache::dump() const { diff --git a/ccsrc/security/src/certs_db.cc b/ccsrc/security/src/certs_db.cc index b4cfc430818ad2fc76459704dcd2b4224beb010c..4bc3193c9ae2eed4631c13a86ae04000e91b944d 100644 --- a/ccsrc/security/src/certs_db.cc +++ b/ccsrc/security/src/certs_db.cc @@ -24,9 +24,3 @@ int certs_db::initialize_cache(const std::string& 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 index a5c34ba0f3bbf7e630e927b9e301c2fdd316ac78..2439e4afbd27a25e00cfccea0a071331ad806146 100644 --- a/ccsrc/security/src/certs_db_record.cc +++ b/ccsrc/security/src/certs_db_record.cc @@ -17,14 +17,16 @@ certs_db_record::certs_db_record(const std::string& p_certificate_id, X509* p_certificate, EVP_PKEY* p_private_key, const std::string& p_certificate_pem) : _certificate_id(p_certificate_id), _certificate(p_certificate), _private_key(p_private_key), _pem(p_certificate_pem) { loggers::get_instance().log(">>> certs_db_record::certs_db_record: p_certificate_id: '%s'", _certificate_id.c_str()); - loggers::get_instance().log(">>> certs_db_record::certs_db_record: p_certificate: '%p'", _certificate_id); - loggers::get_instance().log(">>> certs_db_record::certs_db_record: p_private_key: '%p'", _private_key); - loggers::get_instance().log(">>> certs_db_record::certs_db_record: p_private_key: '%s'", _pem); + // loggers::get_instance().log(">>> certs_db_record::certs_db_record: p_certificate: '%p'", _certificate_id); + // loggers::get_instance().log(">>> certs_db_record::certs_db_record: p_private_key: '%p'", _private_key); + //loggers::get_instance().log(">>> certs_db_record::certs_db_record: p_private_key: '%s'", _pem.c_str()); } certs_db_record::~certs_db_record() { if (_certificate != nullptr) { ::X509_free(_certificate); - ::EVP_PKEY_free(_private_key); + if (_private_key != nullptr) { + ::EVP_PKEY_free(_private_key); + } } } diff --git a/ccsrc/security/src/certs_loader.cc b/ccsrc/security/src/certs_loader.cc index 0fa3eb738a3d7f71d8cf311b41c2866d8a63aeed..ec98eae39ccdded86de8aba5ce82f406597a5eac 100644 --- a/ccsrc/security/src/certs_loader.cc +++ b/ccsrc/security/src/certs_loader.cc @@ -76,8 +76,8 @@ int certs_loader::get_certificate_id(const std::string& p_certificate_name, std: 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> & p_certificates) { - loggers::get_instance().log(">>> certs_loader::load_certificate %s", p_certificate_name.c_str()); +int certs_loader::load_certificate(const std::string& p_certificate_name, const std::string& p_private_key_name, const std::string& p_private_key_passwd, std::string& p_certificate_id, std::map> & 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 @@ -87,6 +87,7 @@ int certs_loader::load_certificate(const std::string& p_certificate_name, const return -1; } std::experimental::filesystem::path p = _db_path.string() + "/" + p_certificate_name; + loggers::get_instance().log("certs_loader::load_certificate: p='%s'", p.string().c_str()); int ret = BIO_read_filename(certbio, p.string().c_str()); X509* cert = ::PEM_read_bio_X509(certbio, NULL, 0, NULL); @@ -114,14 +115,14 @@ int certs_loader::load_certificate(const std::string& p_certificate_name, const } std::string pem(mem->data, mem->length); // Remove labels - loggers::get_instance().log("certs_loader::load_certificate: certificate pem (1): '%s'", pem.c_str()); + //loggers::get_instance().log("certs_loader::load_certificate: certificate pem (1): '%s'", pem.c_str()); std::string s("-----BEGIN CERTIFICATE-----\n"); std::string::size_type idx = pem.find_first_of(s); pem = pem.substr(s.length()); s = "\n-----END CERTIFICATE-----\n"; idx = pem.rfind(s); pem = pem.substr(0, pem.length() - s.length()); - loggers::get_instance().log("certs_loader::load_certificate: certificate pem (2): '%s'", pem.c_str()); + //loggers::get_instance().log("certs_loader::load_certificate: certificate pem (2): '%s'", pem.c_str()); ::BIO_free_all(certbio); @@ -134,7 +135,11 @@ int certs_loader::load_certificate(const std::string& p_certificate_name, const } 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); + pem_password_cb* cb = NULL; + if (!p_private_key_passwd.empty() > 0) { + // TODO + } + EVP_PKEY* private_key = ::PEM_read_bio_PrivateKey(certbio, NULL, cb, NULL); if (private_key == nullptr) { loggers::get_instance().warning("certs_loader::load_certificate: Error loading cert into memory"); ::X509_free(cert); @@ -152,7 +157,7 @@ int certs_loader::load_certificate(const std::string& p_certificate_name, const 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); - loggers::get_instance().log("certs_loader::load_certificate: certificate pem: '%s'", pem.c_str()); + //loggers::get_instance().log("certs_loader::load_certificate: certificate pem: '%s'", pem.c_str()); // Create new record certs_db_record *r = new certs_db_record(p_certificate_name, cert, private_key, pem); @@ -166,8 +171,54 @@ int certs_loader::load_certificate(const std::string& p_certificate_name, const return 0; } -int certs_loader::save_certificate(const certs_db_record &p_certificate, std::string& p_certificate_id) { +int certs_loader::store_certificate(const std::string& p_certificate_name, const std::string& p_certificate_pem, std::string& p_certificate_id, std::map> & p_certificates) { + loggers::get_instance().log(">>> certs_loader::store_certificate '%s'", p_certificate_name.c_str()); + loggers::get_instance().log(">>> certs_loader::store_certificate: '%s'", p_certificate_pem.c_str()); + + // Build the certificate identifier + if (get_certificate_id(p_certificate_name, p_certificate_id) != 0) { + loggers::get_instance().warning("certs_cache::store_certificate: Failed to build the certificate identifier"); + return -1; + } - return -1; -} // End of method save_certificate + // Load certificate file + std::string s("-----BEGIN CERTIFICATE-----\n"); + if (p_certificate_pem.find(s) == std::string::npos) { // Add delimeters + loggers::get_instance().log("certs_loader::store_certificate: Add delimeters"); + s = s.append(p_certificate_pem); + s = s.append("\n-----END CERTIFICATE-----\n"); + } else { + loggers::get_instance().log("certs_loader::store_certificate: Do not add delimeters"); + s = p_certificate_pem; + } + loggers::get_instance().log("certs_loader::store_certificate: pem: '%s'", s.c_str()); + BIO* certbio = ::BIO_new_mem_buf(s.c_str(), -1); + if (certbio == nullptr) { + loggers::get_instance().warning("certs_loader::store_certificate: Error creating in memory BIO"); + return -1; + } + + X509* cert = ::PEM_read_bio_X509(certbio, NULL, 0, NULL); + if (cert == nullptr) { + loggers::get_instance().warning("certs_loader::store_certificate: Error loading cert into memory"); + ::BIO_free_all(certbio); + return -1; + } + ::BIO_free(certbio); + + loggers::get_instance().log("certs_loader::store_certificate: p_certificate_name: '%s'", p_certificate_name.c_str()); + loggers::get_instance().log("certs_loader::store_certificate: p_certificate_id: '%s'", p_certificate_id.c_str()); + loggers::get_instance().log("certs_loader::store_certificate: cert: '%p'", cert); + + // Create new record + certs_db_record *r = new certs_db_record(p_certificate_name, cert, nullptr, p_certificate_pem); + std::pair>::iterator, bool> result = p_certificates.insert(std::pair>(p_certificate_id, std::unique_ptr(r))); + if (result.second == false) { + loggers::get_instance().warning("certs_loader::store_certificate: Failed to insert new record '%s'", p_certificate_name.c_str()); + delete r; + return -1; + } + + return 0; +} // End of method store_certificate diff --git a/ccsrc/security/src/security_externals.cc b/ccsrc/security/src/security_externals.cc index 96d5b8d10e76c790a6c527de7f361285bc3bd30b..452ce0847508e7287e0ceab409ca3eeb8f6b2dfe 100644 --- a/ccsrc/security/src/security_externals.cc +++ b/ccsrc/security/src/security_externals.cc @@ -21,12 +21,12 @@ INTEGER LibSecurity__Certificates::fx__init__certs__db(const CHARSTRING& p_certs return ret; } -INTEGER LibSecurity__Certificates::fx__load__certificate(const CHARSTRING& p_certificate_name, const CHARSTRING& p_private_key_name) { +INTEGER LibSecurity__Certificates::fx__load__certificate(const CHARSTRING& p_certificate_name, const CHARSTRING& p_private_key_name, const CHARSTRING& p_private_key_passwd) { 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(p_certificate_name)), std::string(static_cast(p_private_key_name)), &certificate); + int ret = _security_services->load_certificate(std::string(static_cast(p_certificate_name)), std::string(static_cast(p_private_key_name)), std::string(static_cast(p_private_key_passwd)), &certificate); loggers::get_instance().log("fx__load__certificate: certificate: '%p'", certificate); if (ret == 0) { ASN1_INTEGER* asn1_serial = ::X509_get_serialNumber((X509*)certificate); @@ -69,14 +69,25 @@ OCTETSTRING LibSecurity__Hash::fx__hash(const OCTETSTRING& p_to_be_hashed, const 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) { +INTEGER LibSecurity__Signature::fx__sign(const OCTETSTRING& p_encoded_message, const CHARSTRING& p_certificate_name, const CHARSTRING& p_private_key_name, const CHARSTRING& p_private_key_passwd, OCTETSTRING& p_signature, OCTETSTRING& p_digest, CHARSTRING& p_x509_certificate_subject, CHARSTRING& p_x509_certificate_pem, CHARSTRING& p_pull_request_signed_canonicalized) { 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) { + if (_security_services->do_sign(p_encoded_message, p_certificate_name, p_private_key_name, p_private_key_passwd, p_signature, p_digest, p_x509_certificate_subject, p_x509_certificate_pem, p_pull_request_signed_canonicalized) == -1) { loggers::get_instance().log("fx__sign: Failed to signed message"); return -1; } return 0; } + +BOOLEAN LibSecurity__Signature::fx__do__sign__verify(const CHARSTRING& p_message, const UNIVERSAL_CHARSTRING& p_canonicalization_method, const UNIVERSAL_CHARSTRING& p_signature_method, const UNIVERSAL_CHARSTRING& p_digest_method, const UNIVERSAL_CHARSTRING& p_digest_value, const UNIVERSAL_CHARSTRING& p_signature_value, const UNIVERSAL_CHARSTRING& p_subject_name, const UNIVERSAL_CHARSTRING& p_certificate) { + loggers::get_instance().log(">>> fx__do__sign__verify"); + + if (!_security_services->do_sign_verify(p_message, p_canonicalization_method, p_signature_method, p_digest_method, p_digest_value, p_signature_value, p_subject_name, p_certificate)) { + loggers::get_instance().log("fx__do__sign__verify: Failed to verify message signature"); + return false; + } + + return true; +} \ No newline at end of file diff --git a/ccsrc/security/src/securty_services.cc b/ccsrc/security/src/securty_services.cc index 0103af52678383cf1343435be68519c86a39f0fd..cca8948cb8e7a8aa39f4c19e1f41fa372b290ba9 100644 --- a/ccsrc/security/src/securty_services.cc +++ b/ccsrc/security/src/securty_services.cc @@ -2,6 +2,8 @@ #include #include +#include "converter.hh" + #include "loggers.hh" #include "xml_converters.hh" @@ -28,45 +30,49 @@ int security_services::initialize(const std::string& p_certs_db_path) { return 0; } -int security_services::load_certificate(const std::string& p_certificate_name, const std::string& p_private_key_name, const X509** p_certificate) { +int security_services::load_certificate(const std::string& p_certificate_name, const std::string& p_private_key_name, const std::string& p_private_key_passwd, 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()); + loggers::get_instance().log("security_services::load_certificate: '%s'", p_private_key_passwd.c_str()); - return _certs_db->get_certificate(p_certificate_name, p_private_key_name, p_certificate); + return _certs_db->get_certificate(p_certificate_name, p_private_key_name, p_private_key_passwd, 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) { +int security_services::do_sign(const OCTETSTRING& p_encoded_message, const CHARSTRING& p_certificate_name, const CHARSTRING& p_private_key_name, const CHARSTRING& p_private_key_passwd, OCTETSTRING& p_signature, OCTETSTRING& p_digest, CHARSTRING& p_x509_certificate_subject, CHARSTRING& p_x509_certificate_pem, CHARSTRING& p_pull_request_signed_canonicalized) { loggers::get_instance().log_msg(">>> security_services::do_sign: ", p_encoded_message); loggers::get_instance().log_msg(">>> security_services::do_sign: ", p_certificate_name); + loggers::get_instance().log_msg(">>> security_services::do_sign: ", p_private_key_name); + loggers::get_instance().log_msg(">>> security_services::do_sign: ", p_private_key_passwd); // Canonicalization std::string canonicalized; xml_converters::get_instance().xml_canonicalization(std::string((const char*)(static_cast(p_encoded_message)), p_encoded_message.lengthof()), canonicalized); - OCTETSTRING encoded_message(char2oct(CHARSTRING(canonicalized.c_str()))); - loggers::get_instance().log("security_services::do_sign: canonicalized: '%s", canonicalized.c_str()); + p_pull_request_signed_canonicalized = CHARSTRING(canonicalized.c_str()); + OCTETSTRING encoded_message(char2oct(p_pull_request_signed_canonicalized)); + loggers::get_instance().log_msg("security_services::do_sign: p_pull_request_signed_canonicalized: ", p_pull_request_signed_canonicalized); // Retrieve certificate std::string certificate_id; if (certs_loader::get_instance().get_certificate_id(std::string(static_cast(p_certificate_name)), certificate_id) != 0) { - loggers::get_instance().warning("fx__sign: Failed to retrieve certificate identifier"); + loggers::get_instance().warning("security_services::do_sign: Failed to retrieve certificate identifier"); return -1; } - loggers::get_instance().log("fx__sign: certificate_id: '%s'", certificate_id.c_str()); + loggers::get_instance().log("security_services::do_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"); + loggers::get_instance().warning("security_services::do_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()); + ::X509_NAME_oneline(sn, (char*)subject.c_str(), subject.length()); + loggers::get_instance().log("security_services::do_sign: X509_NAME_oneline: '%s'", subject.c_str()); p_x509_certificate_subject = CHARSTRING(subject.c_str()); X509_free((X509*)certificate); std::string str; if (_certs_db->get_certificate_pem(certificate_id, str) != 0) { - loggers::get_instance().warning("fx__sign: Failed to retrieve certificate PEM"); + loggers::get_instance().warning("security_services::do_sign: Failed to retrieve certificate PEM"); return -1; } p_x509_certificate_pem = CHARSTRING(str.c_str()); @@ -74,45 +80,45 @@ int security_services::do_sign(const OCTETSTRING& p_encoded_message, const CHARS // 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); + loggers::get_instance().log_msg("security_services::do_sign: 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"); + loggers::get_instance().warning("security_services::do_sign: Failed to retrieve private key"); return -1; } - loggers::get_instance().log("fx__sign: certificate_id: private_key: '%p'", private_key); + loggers::get_instance().log("security_services::do_sign: 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()); + loggers::get_instance().warning("security_services::do_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()); + loggers::get_instance().warning("security_services::do_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()); + loggers::get_instance().warning("security_services::do_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()); + loggers::get_instance().warning("security_services::do_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); + loggers::get_instance().log("security_services::do_sign: signature_length: %d", signature_length); std::vector 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()); + loggers::get_instance().warning("security_services::do_sign: EVP_DigestSignUpdate failed, error 0x%lx", ::ERR_get_error()); ::EVP_MD_CTX_free(ctx); s.clear(); return -1; @@ -121,7 +127,109 @@ int security_services::do_sign(const OCTETSTRING& p_encoded_message, const CHARS p_signature = OCTETSTRING(signature_length, s.data()); ::EVP_MD_CTX_free(ctx); - loggers::get_instance().log_msg("fx__sign: signature: ", p_signature); + loggers::get_instance().log_msg("<<< security_services::do_sign: signature: ", p_signature); return 0; -} \ No newline at end of file +} + +bool security_services::do_sign_verify(const CHARSTRING& p_message, const UNIVERSAL_CHARSTRING& p_canonicalization_method, const UNIVERSAL_CHARSTRING& p_signature_method, const UNIVERSAL_CHARSTRING& p_digest_method, const UNIVERSAL_CHARSTRING& p_digest_value, const UNIVERSAL_CHARSTRING& p_signature_value, const UNIVERSAL_CHARSTRING& p_subject_name, const UNIVERSAL_CHARSTRING& p_certificate) { + loggers::get_instance().log_msg(">>> security_services::do_sign_verify: p_message: ", p_message); + loggers::get_instance().log_msg(">>> security_services::do_sign_verify: p_canonicalization_method: ", p_canonicalization_method); + loggers::get_instance().log_msg(">>> security_services::do_sign_verify: p_subject_name: ", p_subject_name); + loggers::get_instance().log_msg(">>> security_services::do_sign_verify: p_signature_method: ", p_signature_method); + + // Compute the digest + sha256 digest; + OCTETSTRING dg; + digest.generate(char2oct(p_message), dg); + loggers::get_instance().log_msg("security_services::do_sign_verify: digest: ", dg); + + // Retrieve certificate + std::string sn(static_cast(unichar2char(p_subject_name))); + std::string certificate_id; + const X509* certificate; + if (_certs_db->get_certificate_by_subject_name(sn, &certificate) != 0) { + loggers::get_instance().warning("security_services::do_sign_verify: Failed to retrieve certificate"); + // Use provided certificate if any + size_t i = sn.find_first_of("CN="); + if (i == std::string::npos) { + loggers::get_instance().warning("security_services::do_sign_verify: Failed to extract certificate name"); + return false; + } + size_t j = sn.find_first_of(","); + std::string certificate_name = sn.substr(i + 3, j - i - 3); + loggers::get_instance().log("security_services::do_sign_verify: certificate name: '%s'", certificate_name.c_str()); + const certs_db_record* record; + if (_certs_db->store_certificate(certificate_name, std::string(static_cast(unichar2char(p_certificate))), certificate_id, &record) == -1) { + loggers::get_instance().warning("security_services::do_sign_verify: Failed to store certificate"); + return false; + } + loggers::get_instance().log("security_services::do_sign_verify: certificate id: '%s'", record->certificate_id().c_str()); + } + + // Retrive the public key + const EVP_PKEY* public_key; + int ret = _certs_db->get_public_keys(certificate_id, &public_key); + if (ret == 1) { + loggers::get_instance().warning("security_services::do_sign_verify: Failed to retrieve public key"); + return false; + } + loggers::get_instance().log("security_services::do_sign: public_key: '%p'", public_key); + + // Create signing context + EVP_MD_CTX* ctx = ::EVP_MD_CTX_new(); + if (ctx == NULL) { + loggers::get_instance().warning("security_services::do_sign_verify: EVP_MD_CTX_create failed, error 0x%lx", ::ERR_get_error()); + return false; + } + std::string signature_method(static_cast(unichar2char(p_signature_method))); // E.g. http://www.w3.org/2000/09/xmldsig#rsa-sha1 + const EVP_MD *md; + if (signature_method.find("sha1") != std::string::npos) { + md = EVP_sha1(); + } else if (signature_method.find("sha256") != std::string::npos) { + md = EVP_sha256(); + } else if (signature_method.find("sha384") != std::string::npos) { + md = EVP_sha384(); + } else { + return false; + } + if (::EVP_DigestVerifyInit(ctx, NULL, md, NULL, (EVP_PKEY*)public_key) != 1) { // FIXME Add parameter to chose the digest algorithm + loggers::get_instance().warning("security_services::do_sign_verify: EVP_DigestVerifyInit failed, error 0x%lx", ::ERR_get_error()); + ::EVP_MD_CTX_free(ctx); + return false; + } + std::string signature_value(static_cast(unichar2char(p_signature_value))); + // Remove CR/LF if any + //signature_value.erase(std::remove(signature_value.begin(), signature_value.end(), '\r'), signature_value.end()); + //signature_value.erase(std::remove(signature_value.begin(), signature_value.end(), '\n'), signature_value.end()); + loggers::get_instance().warning("security_services::do_sign_verify: Before B64 decoded: '%s'", signature_value.c_str()); + // Convert into bytes buffer + const std::vector to_decode((const unsigned char*)signature_value.c_str(), static_cast((const unsigned char*)signature_value.c_str() + signature_value.length())); + std::vector b64 = converter::get_instance().base64_to_buffer(to_decode); + loggers::get_instance().warning("security_services::do_sign_verify: B64 decoded: '%s'", converter::get_instance().bytes_to_hexa(b64, true).c_str()); + + + // EVP_ENCODE_CTX *ctx_ = ::EVP_ENCODE_CTX_new(); + // ::EVP_DecodeInit(ctx_); + // std::vector b64_(1024, 0x00); + // int outl1 = 0; + // int outl2 = 0; + // ::EVP_DecodeUpdate(ctx_, b64_.data(), &outl1, to_decode.data(), to_decode.size()); + // ::EVP_DecodeFinal(ctx_, b64_.data(), &outl2); + // ::EVP_ENCODE_CTX_free(ctx_); + // b64_.resize(outl1 + outl2); + // loggers::get_instance().log("security_services::do_sign_verify: B64_ decoded: '%s'", converter::get_instance().bytes_to_hexa(b64_, true).c_str()); + + + + // Check signature + if(::EVP_DigestVerifyFinal(ctx, b64.data(), b64.size()) != 1) { + loggers::get_instance().warning("security_services::do_sign_verify: EVP_DigestVerifyFinal failed, error 0x%lx", ::ERR_get_error()); + ::EVP_MD_CTX_free(ctx); + return false; + } + + ::EVP_MD_CTX_free(ctx); + + return true; +} diff --git a/ttcn/LibHttp/ttcn/LibHttp_XmlMessageBodyTypes.ttcn b/ttcn/LibHttp/ttcn/LibHttp_XmlMessageBodyTypes.ttcn index 147f0c3fe0d1ae3498daff65822b46824c21a289..567df6c553e8b4af3987f0c97830e021c5f0533b 100644 --- a/ttcn/LibHttp/ttcn/LibHttp_XmlMessageBodyTypes.ttcn +++ b/ttcn/LibHttp/ttcn/LibHttp_XmlMessageBodyTypes.ttcn @@ -6,13 +6,17 @@ module LibHttp_XmlMessageBodyTypes { */ // TODO Add here your custom RFCs import - type union XmlBody { + type union XmlBodyMsg { // TODO Add here your custom variants - charstring raw } with { variant "" } + type record XmlBody { + XmlBodyMsg msg, + charstring raw optional + } + } with { variant "" } // End of LibHttp_XmlMessageBodyTypes diff --git a/ttcn/LibSecurity/ttcn/LibSecurity_Certificates.ttcn b/ttcn/LibSecurity/ttcn/LibSecurity_Certificates.ttcn index 4fba516a91f186d096bae5d885d0c454a1f84015..4af73996d10bab2f29b9ee54ee6b8bace3f593c2 100644 --- a/ttcn/LibSecurity/ttcn/LibSecurity_Certificates.ttcn +++ b/ttcn/LibSecurity/ttcn/LibSecurity_Certificates.ttcn @@ -2,14 +2,14 @@ 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; + external function fx_load_certificate(in charstring p_certificate_name, in charstring p_private_key_name, in charstring p_private_key_passwd) 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); + function f_load_certificate(in charstring p_certificate_name, in charstring p_private_key_name, in charstring p_private_key_passwd) return integer { + return fx_load_certificate(p_certificate_name, p_private_key_name, p_private_key_passwd); } } // End of LibSecurity_Certificates \ No newline at end of file diff --git a/ttcn/LibSecurity/ttcn/LibSecurity_Signature.ttcn b/ttcn/LibSecurity/ttcn/LibSecurity_Signature.ttcn index 614caf60416be6fc98534369b6d55cb38b95c9d5..198c03c601c1ecffa76468c24775868e974af266 100644 --- a/ttcn/LibSecurity/ttcn/LibSecurity_Signature.ttcn +++ b/ttcn/LibSecurity/ttcn/LibSecurity_Signature.ttcn @@ -1,26 +1,52 @@ module LibSecurity_Signature { - import from LibSecurity_Hash all; - /** - * @desc + * @desc Sign message * @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 + * @param [in] p_private_key_name The private key to use for the signature, in PCKS#8 format + * @param [in] p_private_key_passwd The password tpo decrypt the private key. Empty if no encryption + * @param [out] p_signature The raw signature + * @param [out] p_digest The Hash algorithm to use + * @param [out] p_x509_certificate_subject The certificate subject + * @param [out] p_x509_certificate_pem The certificate in PEM format * @return 0 on success, -1 otherwise */ function f_sign( in octetstring p_encoded_message, - in charstring p_certificate_name, + in charstring p_certificate_name, + in charstring p_private_key_name, + in charstring p_private_key_passwd, out octetstring p_signature, out octetstring p_digest, out charstring p_x509_certificate_subject, - out charstring p_x509_certificate_pem + out charstring p_x509_certificate_pem, + out charstring p_pull_request_signed_canonicalized ) return integer { - return fx_sign(p_encoded_message, p_certificate_name, p_signature, p_digest, p_x509_certificate_subject, p_x509_certificate_pem); + return fx_sign(p_encoded_message, p_certificate_name, p_private_key_name, p_private_key_passwd, p_signature, p_digest, p_x509_certificate_subject, p_x509_certificate_pem, p_pull_request_signed_canonicalized); + } + + external function fx_sign(in octetstring p_encoded_message, in charstring p_certificate_name, in charstring p_private_key_name, in charstring p_private_key_passwd, out octetstring p_signature, out octetstring p_digest, out charstring p_x509_certificate_subject, out charstring p_x509_certificate_pem, out charstring p_pull_request_signed_canonicalized) return integer; + + /** + * @desc Verify signature + * @param [in] p_message The raw message to be verified + * @param [in] TODO + * @return true on success, false otherwise + */ + function f_do_sign_verify( + in charstring p_message, + in universal charstring p_canonicalization_method, + in universal charstring p_signature_method, + in universal charstring p_digest_method, + in universal charstring p_digest_value, + in universal charstring p_signature_value, + in universal charstring p_subject_name, + in universal charstring p_certificate + ) return boolean { + return fx_do_sign_verify(p_message, p_canonicalization_method, p_signature_method, p_digest_method, p_digest_value, p_signature_value, p_subject_name, p_certificate); } - 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; + external function fx_do_sign_verify(in charstring p_message, in universal charstring p_canonicalization_method, in universal charstring p_signature_method, in universal charstring p_digest_method, in universal charstring p_digest_value, in universal charstring p_signature_value, in universal charstring p_subject_name, in universal charstring p_certificate) return boolean; } // End of LibSecurity_Signature \ No newline at end of file