diff options
4 files changed, 128 insertions, 1 deletions
diff --git a/src/components/include/security_manager/security_manager_settings.h b/src/components/include/security_manager/security_manager_settings.h index f8eaadce3e..0bbe0f4f96 100644 --- a/src/components/include/security_manager/security_manager_settings.h +++ b/src/components/include/security_manager/security_manager_settings.h @@ -54,6 +54,8 @@ class CryptoManagerSettings { virtual const std::string& certificate_data() const = 0; virtual const std::string& ciphers_list() const = 0; virtual const std::string& ca_cert_path() const = 0; + virtual const std::string& module_cert_path() const = 0; + virtual const std::string& module_key_path() const = 0; virtual size_t update_before_hours() const = 0; virtual size_t maximum_payload_size() const = 0; virtual const std::vector<int>& force_protected_service() const = 0; diff --git a/src/components/security_manager/include/security_manager/crypto_manager_impl.h b/src/components/security_manager/include/security_manager/crypto_manager_impl.h index be0d102a36..f4a13198da 100644 --- a/src/components/security_manager/include/security_manager/crypto_manager_impl.h +++ b/src/components/security_manager/include/security_manager/crypto_manager_impl.h @@ -153,6 +153,30 @@ class CryptoManagerImpl : public CryptoManager { private: bool AreForceProtectionSettingsCorrect() const; bool set_certificate(const std::string& cert_data); + + /** + * @brief Updates certificate and private key for the current SSL context + * @param certificate new certificate to update + * @param key new private key to update + * @return true if certificate and private key were updated successfully, + * otherwise returns false + */ + bool UpdateModuleCertificateData(X509* certificate, EVP_PKEY* key); + + /** + * @brief Loads X509 certificate from file specified in CryptoManagerSettings + * @return returns pointer to the loaded X509 certificate in case of success + * otherwise returns NULL + */ + X509* LoadModuleCertificateFromFile(); + + /** + * @brief Loads private key from file specified in CryptoManagerSettings + * @return returns pointer to the loaded private key in case of success + * otherwise returns NULL + */ + EVP_PKEY* LoadModulePrivateKeyFromFile(); + const utils::SharedPtr<const CryptoManagerSettings> settings_; SSL_CTX* context_; static uint32_t instance_count_; diff --git a/src/components/security_manager/include/security_manager/crypto_manager_settings_impl.h b/src/components/security_manager/include/security_manager/crypto_manager_settings_impl.h index 295a76680f..f20d3e4034 100644 --- a/src/components/security_manager/include/security_manager/crypto_manager_settings_impl.h +++ b/src/components/security_manager/include/security_manager/crypto_manager_settings_impl.h @@ -60,6 +60,14 @@ class CryptoManagerSettingsImpl : public CryptoManagerSettings { return profile_.ca_cert_path(); } + const std::string& module_cert_path() const OVERRIDE { + return profile_.cert_path(); + } + + const std::string& module_key_path() const OVERRIDE { + return profile_.key_path(); + } + size_t update_before_hours() const OVERRIDE { return profile_.update_before_hours(); } diff --git a/src/components/security_manager/src/crypto_manager_impl.cc b/src/components/security_manager/src/crypto_manager_impl.cc index f5908f8043..cf92c2d40c 100644 --- a/src/components/security_manager/src/crypto_manager_impl.cc +++ b/src/components/security_manager/src/crypto_manager_impl.cc @@ -254,6 +254,14 @@ bool CryptoManagerImpl::Init() { << '"'); } + LOG4CXX_DEBUG(logger_, "Setting up module certificate and private key"); + X509* module_certificate = LoadModuleCertificateFromFile(); + EVP_PKEY* module_key = LoadModulePrivateKeyFromFile(); + + if (!UpdateModuleCertificateData(module_certificate, module_key)) { + LOG4CXX_WARN(logger_, "Failed to update module key and certificate"); + } + guard.Dismiss(); const int verify_mode = @@ -273,7 +281,15 @@ bool CryptoManagerImpl::OnCertificateUpdated(const std::string& data) { return false; } - return set_certificate(data); + if (!set_certificate(data)) { + LOG4CXX_ERROR(logger_, "Failed to save certificate data"); + return false; + } + + X509* module_certificate = LoadModuleCertificateFromFile(); + EVP_PKEY* module_key = LoadModulePrivateKeyFromFile(); + + return UpdateModuleCertificateData(module_certificate, module_key); } SSLContext* CryptoManagerImpl::CreateSSLContext() { @@ -394,4 +410,81 @@ bool CryptoManagerImpl::set_certificate(const std::string& cert_data) { return true; } +bool CryptoManagerImpl::UpdateModuleCertificateData(X509* certificate, + EVP_PKEY* key) { + LOG4CXX_AUTO_TRACE(logger_); + if (NULL != certificate) { + if (!SSL_CTX_use_certificate(context_, certificate)) { + LOG4CXX_WARN(logger_, "Could not use certificate: " << LastError()); + return false; + } + } + + if (NULL != key) { + if (!SSL_CTX_use_PrivateKey(context_, key)) { + LOG4CXX_ERROR(logger_, "Could not use key: " << LastError()); + return false; + } + + if (!SSL_CTX_check_private_key(context_)) { + LOG4CXX_ERROR(logger_, "Private key is invalid: " << LastError()); + return false; + } + } + + LOG4CXX_DEBUG(logger_, "Certificate and key are successfully updated"); + return true; +} + +X509* CryptoManagerImpl::LoadModuleCertificateFromFile() { + LOG4CXX_AUTO_TRACE(logger_); + + const std::string cert_path = get_settings().module_cert_path(); + BIO* bio_cert = BIO_new_file(cert_path.c_str(), "r"); + if (NULL == bio_cert) { + LOG4CXX_WARN(logger_, + "Failed to open " << cert_path << " file: " << LastError()); + return NULL; + } + + utils::ScopeGuard bio_guard = utils::MakeGuard(BIO_free, bio_cert); + UNUSED(bio_guard); + + X509* module_certificate = NULL; + if (0 == PEM_read_bio_X509(bio_cert, &module_certificate, NULL, NULL)) { + LOG4CXX_ERROR(logger_, + "Failed to read certificate data from file: " << LastError()); + return NULL; + } + LOG4CXX_DEBUG(logger_, + "Module certificate was loaded: " << module_certificate); + + return module_certificate; +} + +EVP_PKEY* CryptoManagerImpl::LoadModulePrivateKeyFromFile() { + LOG4CXX_AUTO_TRACE(logger_); + + const std::string key_path = get_settings().module_key_path(); + BIO* bio_key = BIO_new_file(key_path.c_str(), "r"); + if (NULL == bio_key) { + LOG4CXX_WARN(logger_, + "Failed to open " << key_path << " file: " << LastError()); + return NULL; + } + + utils::ScopeGuard bio_guard = utils::MakeGuard(BIO_free, bio_key); + UNUSED(bio_guard); + + EVP_PKEY* module_key = NULL; + if (0 == PEM_read_bio_PrivateKey(bio_key, &module_key, NULL, NULL)) { + LOG4CXX_ERROR(logger_, + "Failed to read private key data from file: " << LastError()); + return NULL; + } + LOG4CXX_DEBUG(logger_, "Module private key was loaded: " << module_key); + + return module_key; +} + } // namespace security_manager |