diff options
author | JackLivio <jack@livio.io> | 2018-06-18 14:19:21 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-06-18 14:19:21 -0400 |
commit | 24edd97c1f2b4fc67eb882245cd865939b075c6f (patch) | |
tree | 9134a1b0673b3a411d3f6c2872a1dfda2ed0b763 | |
parent | 9651cdc35c3e62040d4fac996a8638b6eebe4015 (diff) | |
parent | 8a84d14576256b4d6c66200f5c9ca0b379c2a4c7 (diff) | |
download | sdl_core-24edd97c1f2b4fc67eb882245cd865939b075c6f.tar.gz |
Merge pull request #2217 from smartdevicelink/fix/fix_certificate_path_nonfunctional
Fix nonfunctional certificate/key path keywords
8 files changed, 183 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/include/test/security_manager/mock_security_manager_settings.h b/src/components/include/test/security_manager/mock_security_manager_settings.h index 961b5e2ff8..b1c869cd1b 100644 --- a/src/components/include/test/security_manager/mock_security_manager_settings.h +++ b/src/components/include/test/security_manager/mock_security_manager_settings.h @@ -50,6 +50,8 @@ class MockCryptoManagerSettings MOCK_CONST_METHOD0(certificate_data, const std::string&()); MOCK_CONST_METHOD0(ciphers_list, const std::string&()); MOCK_CONST_METHOD0(ca_cert_path, const std::string&()); + MOCK_CONST_METHOD0(module_cert_path, const std::string&()); + MOCK_CONST_METHOD0(module_key_path, const std::string&()); MOCK_CONST_METHOD0(update_before_hours, size_t()); MOCK_CONST_METHOD0(maximum_payload_size, size_t()); MOCK_CONST_METHOD0(force_protected_service, const std::vector<int>&()); 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..34727fedf9 100644 --- a/src/components/security_manager/src/crypto_manager_impl.cc +++ b/src/components/security_manager/src/crypto_manager_impl.cc @@ -254,6 +254,21 @@ bool CryptoManagerImpl::Init() { << '"'); } + LOG4CXX_DEBUG(logger_, "Setting up module certificate and private key"); + + X509* module_certificate = LoadModuleCertificateFromFile(); + utils::ScopeGuard certificate_guard = + utils::MakeGuard(X509_free, module_certificate); + UNUSED(certificate_guard); + + EVP_PKEY* module_key = LoadModulePrivateKeyFromFile(); + utils::ScopeGuard key_guard = utils::MakeGuard(EVP_PKEY_free, module_key); + UNUSED(key_guard); + + if (!UpdateModuleCertificateData(module_certificate, module_key)) { + LOG4CXX_WARN(logger_, "Failed to update module key and certificate"); + } + guard.Dismiss(); const int verify_mode = @@ -273,7 +288,22 @@ 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(); + + utils::ScopeGuard certificate_guard = + utils::MakeGuard(X509_free, module_certificate); + UNUSED(certificate_guard); + + utils::ScopeGuard key_guard = utils::MakeGuard(EVP_PKEY_free, module_key); + UNUSED(key_guard); + + return UpdateModuleCertificateData(module_certificate, module_key); } SSLContext* CryptoManagerImpl::CreateSSLContext() { @@ -394,4 +424,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 (certificate) { + if (!SSL_CTX_use_certificate(context_, certificate)) { + LOG4CXX_WARN(logger_, "Could not use certificate: " << LastError()); + return false; + } + } + + if (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 (!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 (!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 (!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 (!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 diff --git a/src/components/security_manager/test/crypto_manager_impl_test.cc b/src/components/security_manager/test/crypto_manager_impl_test.cc index 46429ea0e9..47e63dc194 100644 --- a/src/components/security_manager/test/crypto_manager_impl_test.cc +++ b/src/components/security_manager/test/crypto_manager_impl_test.cc @@ -54,6 +54,9 @@ const std::string kAllCiphers = "ALL"; const std::string kCaCertPath = ""; const uint32_t kServiceNumber = 2u; const size_t kMaxSizeVector = 1u; +const std::string kCertPath = "certificate.crt"; +const std::string kPrivateKeyPath = "private.key"; + #ifdef __QNXNTO__ const std::string kFordCipher = SSL3_TXT_RSA_DES_192_CBC3_SHA; #else @@ -118,6 +121,10 @@ class CryptoManagerTest : public testing::Test { .WillByDefault(ReturnRef(cipher)); ON_CALL(*mock_security_manager_settings_, ca_cert_path()) .WillByDefault(ReturnRef(kCaCertPath)); + ON_CALL(*mock_security_manager_settings_, module_cert_path()) + .WillByDefault(ReturnRef(kCertPath)); + ON_CALL(*mock_security_manager_settings_, module_key_path()) + .WillByDefault(ReturnRef(kPrivateKeyPath)); ON_CALL(*mock_security_manager_settings_, verify_peer()) .WillByDefault(Return(false)); } diff --git a/src/components/security_manager/test/ssl_certificate_handshake_test.cc b/src/components/security_manager/test/ssl_certificate_handshake_test.cc index 2423ab00b7..d5bb1ecaee 100644 --- a/src/components/security_manager/test/ssl_certificate_handshake_test.cc +++ b/src/components/security_manager/test/ssl_certificate_handshake_test.cc @@ -56,6 +56,10 @@ namespace custom_str = utils::custom_string; namespace { const std::string server_ca_cert_filename = "server"; const std::string client_ca_cert_filename = "client"; +const std::string client_cert_filename = "client.crt"; +const std::string server_cert_filename = "server.crt"; +const std::string client_key_filename = "client_private.key"; +const std::string server_key_filename = "server_private.key"; const std::string client_certificate = "client/client_credential.pem"; const std::string server_certificate = "server/spt_credential.pem"; const std::string server_unsigned_cert_file = @@ -126,6 +130,10 @@ class SSLHandshakeTest : public testing::TestWithParam<Protocol> { .WillByDefault(ReturnRef(server_ciphers_list_)); ON_CALL(*mock_server_manager_settings_, ca_cert_path()) .WillByDefault(ReturnRef(server_ca_certificate_path_)); + ON_CALL(*mock_server_manager_settings_, module_cert_path()) + .WillByDefault(ReturnRef(server_cert_filename)); + ON_CALL(*mock_server_manager_settings_, module_key_path()) + .WillByDefault(ReturnRef(server_key_filename)); ON_CALL(*mock_server_manager_settings_, verify_peer()) .WillByDefault(Return(verify_peer)); } @@ -152,6 +160,10 @@ class SSLHandshakeTest : public testing::TestWithParam<Protocol> { .WillByDefault(ReturnRef(client_ciphers_list_)); ON_CALL(*mock_client_manager_settings_, ca_cert_path()) .WillByDefault(ReturnRef(client_ca_certificate_path_)); + ON_CALL(*mock_client_manager_settings_, module_cert_path()) + .WillByDefault(ReturnRef(client_cert_filename)); + ON_CALL(*mock_client_manager_settings_, module_key_path()) + .WillByDefault(ReturnRef(client_key_filename)); ON_CALL(*mock_client_manager_settings_, verify_peer()) .WillByDefault(Return(verify_peer)); } diff --git a/src/components/security_manager/test/ssl_context_test.cc b/src/components/security_manager/test/ssl_context_test.cc index 7a4a9c3a87..20e509ebc6 100644 --- a/src/components/security_manager/test/ssl_context_test.cc +++ b/src/components/security_manager/test/ssl_context_test.cc @@ -50,6 +50,10 @@ using ::testing::NiceMock; namespace { const std::string kCaPath = ""; +const std::string kClientCertPath = "client_certificate.crt"; +const std::string kClientPrivateKeyPath = "client_private.key"; +const std::string kServerCertPath = "server_certificate.crt"; +const std::string kServerPrivateKeyPath = "server_private.key"; const uint8_t* kServerBuf; const uint8_t* kClientBuf; const std::string kAllCiphers = "ALL"; @@ -131,6 +135,10 @@ class SSLTest : public testing::Test { .WillByDefault(ReturnRef(forced_unprotected_service_)); ON_CALL(*mock_crypto_manager_settings_, force_protected_service()) .WillByDefault(ReturnRef(forced_protected_service_)); + ON_CALL(*mock_crypto_manager_settings_, module_cert_path()) + .WillByDefault(ReturnRef(kServerCertPath)); + ON_CALL(*mock_crypto_manager_settings_, module_key_path()) + .WillByDefault(ReturnRef(kServerPrivateKeyPath)); const bool crypto_manager_initialization = crypto_manager_->Init(); EXPECT_TRUE(crypto_manager_initialization); @@ -160,6 +168,10 @@ class SSLTest : public testing::Test { .WillByDefault(ReturnRef(forced_unprotected_service_)); ON_CALL(*mock_client_manager_settings_, force_protected_service()) .WillByDefault(ReturnRef(forced_protected_service_)); + ON_CALL(*mock_client_manager_settings_, module_cert_path()) + .WillByDefault(ReturnRef(kClientCertPath)); + ON_CALL(*mock_client_manager_settings_, module_key_path()) + .WillByDefault(ReturnRef(kClientPrivateKeyPath)); const bool client_manager_initialization = client_manager_->Init(); EXPECT_TRUE(client_manager_initialization); @@ -301,6 +313,10 @@ class SSLTestParam : public testing::TestWithParam<ProtocolAndCipher> { .WillByDefault(ReturnRef(kCaPath)); ON_CALL(*mock_crypto_manager_settings_, verify_peer()) .WillByDefault(Return(false)); + ON_CALL(*mock_crypto_manager_settings_, module_cert_path()) + .WillByDefault(ReturnRef(kServerCertPath)); + ON_CALL(*mock_crypto_manager_settings_, module_key_path()) + .WillByDefault(ReturnRef(kServerPrivateKeyPath)); } void SetClientInitialValues(security_manager::Protocol protocol, @@ -321,6 +337,10 @@ class SSLTestParam : public testing::TestWithParam<ProtocolAndCipher> { .WillByDefault(ReturnRef(kCaPath)); ON_CALL(*mock_client_manager_settings_, verify_peer()) .WillByDefault(Return(false)); + ON_CALL(*mock_client_manager_settings_, module_cert_path()) + .WillByDefault(ReturnRef(kClientCertPath)); + ON_CALL(*mock_client_manager_settings_, module_key_path()) + .WillByDefault(ReturnRef(kClientPrivateKeyPath)); } utils::SharedPtr<NiceMock<security_manager_test::MockCryptoManagerSettings> > |