summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJackLivio <jack@livio.io>2018-06-18 14:19:21 -0400
committerGitHub <noreply@github.com>2018-06-18 14:19:21 -0400
commit24edd97c1f2b4fc67eb882245cd865939b075c6f (patch)
tree9134a1b0673b3a411d3f6c2872a1dfda2ed0b763
parent9651cdc35c3e62040d4fac996a8638b6eebe4015 (diff)
parent8a84d14576256b4d6c66200f5c9ca0b379c2a4c7 (diff)
downloadsdl_core-24edd97c1f2b4fc67eb882245cd865939b075c6f.tar.gz
Merge pull request #2217 from smartdevicelink/fix/fix_certificate_path_nonfunctional
Fix nonfunctional certificate/key path keywords
-rw-r--r--src/components/include/security_manager/security_manager_settings.h2
-rw-r--r--src/components/include/test/security_manager/mock_security_manager_settings.h2
-rw-r--r--src/components/security_manager/include/security_manager/crypto_manager_impl.h24
-rw-r--r--src/components/security_manager/include/security_manager/crypto_manager_settings_impl.h8
-rw-r--r--src/components/security_manager/src/crypto_manager_impl.cc109
-rw-r--r--src/components/security_manager/test/crypto_manager_impl_test.cc7
-rw-r--r--src/components/security_manager/test/ssl_certificate_handshake_test.cc12
-rw-r--r--src/components/security_manager/test/ssl_context_test.cc20
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> >