summaryrefslogtreecommitdiff
path: root/src/components/security_manager
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/security_manager')
-rw-r--r--src/components/security_manager/include/security_manager/crypto_manager_impl.h72
-rw-r--r--src/components/security_manager/include/security_manager/crypto_manager_settings_impl.h29
-rw-r--r--src/components/security_manager/include/security_manager/security_manager_impl.h87
-rw-r--r--src/components/security_manager/src/crypto_manager_impl.cc295
-rw-r--r--src/components/security_manager/src/security_manager_impl.cc191
-rw-r--r--src/components/security_manager/src/ssl_context_impl.cc134
-rw-r--r--src/components/security_manager/test/crypto_manager_impl_test.cc49
-rw-r--r--src/components/security_manager/test/security_manager_test.cc255
-rw-r--r--src/components/security_manager/test/ssl_certificate_handshake_test.cc349
-rw-r--r--src/components/security_manager/test/ssl_context_test.cc224
10 files changed, 1146 insertions, 539 deletions
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 4e48858e5c..aa3be0f430 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
@@ -71,6 +71,8 @@ class CryptoManagerImpl : public CryptoManager {
size_t* out_data_size) OVERRIDE;
bool IsInitCompleted() const OVERRIDE;
bool IsHandshakePending() const OVERRIDE;
+ bool GetCertificateDueDate(time_t& due_date) const OVERRIDE;
+ bool HasCertificate() const OVERRIDE;
size_t get_max_block_size(size_t mtu) const OVERRIDE;
std::string LastError() const OVERRIDE;
void ResetConnection() OVERRIDE;
@@ -101,6 +103,22 @@ class CryptoManagerImpl : public CryptoManager {
std::string GetTextBy(X509_NAME* name, int object) const;
+ /**
+ * @brief Pulls number stored in buffer of chars
+ * and returns it as integer
+ * @param buf where symbols stored
+ * @param idx index of required char to be converted
+ * @return number in integer representation
+ */
+ int get_number_from_char_buf(char* buf, int* idx) const;
+ /**
+ * @brief Converts time from ASN1 format (used in OpenSSL)
+ * to time_t data type
+ * @param time_to_convert time to be converted
+ * @return time in time_t format
+ */
+ time_t convert_asn1_time_to_time_t(ASN1_TIME* time_to_convert) const;
+
SSL* connection_;
BIO* bioIn_;
BIO* bioOut_;
@@ -128,23 +146,65 @@ class CryptoManagerImpl : public CryptoManager {
SSLContext* CreateSSLContext() OVERRIDE;
void ReleaseSSLContext(SSLContext* context) OVERRIDE;
std::string LastError() const OVERRIDE;
- virtual bool IsCertificateUpdateRequired() const OVERRIDE;
+ bool IsCertificateUpdateRequired(
+ const time_t system_time, const time_t certificates_time) const OVERRIDE;
virtual const CryptoManagerSettings& get_settings() const OVERRIDE;
private:
+ bool AreForceProtectionSettingsCorrect() const;
bool set_certificate(const std::string& cert_data);
- int pull_number_from_buf(char* buf, int* idx);
- void asn1_time_to_tm(ASN1_TIME* time);
+ /**
+ * @brief Saves new certificate data on the file system
+ * @param cert_data certificate data in PEM format
+ * @return true if new certificate data was successfully saved on the file
+ * system, otherwise returns false
+ */
+ bool SaveCertificateData(const std::string& cert_data) const;
+
+ /**
+ * @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();
+
+ /**
+ * @brief Saves new X509 certificate data to file specified in
+ * CryptoManagerSettings
+ * @param certificate new X509 certificate data
+ * @return true if certificate data was saved to the file system otherwise
+ * returns false
+ */
+ bool SaveModuleCertificateToFile(X509* certificate) const;
/**
- * @brief Sets initial certificate datetime
+ * @brief Saves new private key data to file specified in
+ * CryptoManagerSettings
+ * @param key new private key data
+ * @return true if private key data was saved to the file system otherwise
+ * returns false
*/
- void InitCertExpTime();
+ bool SaveModuleKeyToFile(EVP_PKEY* key) const;
const utils::SharedPtr<const CryptoManagerSettings> settings_;
SSL_CTX* context_;
- mutable struct tm expiration_time_;
static uint32_t instance_count_;
static sync_primitives::Lock instance_lock_;
DISALLOW_COPY_AND_ASSIGN(CryptoManagerImpl);
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 1e4699b77a..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
@@ -17,6 +17,7 @@ class CryptoManagerSettingsImpl : public CryptoManagerSettings {
return profile_.ssl_mode() == "SERVER" ? security_manager::SERVER
: security_manager::CLIENT;
}
+
Protocol security_manager_protocol_name() const OVERRIDE {
CREATE_LOGGERPTR_LOCAL(logger_, "SecurityManager")
@@ -33,33 +34,59 @@ class CryptoManagerSettingsImpl : public CryptoManagerSettings {
if (protocol_str == "SSLv3") {
return security_manager::SSLv3;
}
+ if (protocol_str == "DTLSv1.0") {
+ return security_manager::DTLSv1;
+ }
+
LOG4CXX_ERROR(
logger_,
"Unknown protocol: " << profile_.security_manager_protocol_name());
return static_cast<security_manager::Protocol>(-1);
}
+
bool verify_peer() const OVERRIDE {
return profile_.verify_peer();
}
+
const std::string& certificate_data() const OVERRIDE {
return certificate_data_;
}
+
const std::string& ciphers_list() const OVERRIDE {
return profile_.ciphers_list();
}
+
const std::string& ca_cert_path() const OVERRIDE {
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();
}
+
size_t maximum_payload_size() const OVERRIDE {
return profile_.maximum_payload_size();
}
+ const std::vector<int>& force_protected_service() const {
+ return profile_.force_protected_service();
+ }
+
+ const std::vector<int>& force_unprotected_service() const {
+ return profile_.force_unprotected_service();
+ }
+
private:
const profile::Profile& profile_;
const std::string certificate_data_;
};
-}
+} // namespace security_manager
#endif // SRC_COMPONENTS_SECURITY_MANAGER_INCLUDE_SECURITY_MANAGER_CRYPTO_MANAGER_SETTINGS_IMPL_H_
diff --git a/src/components/security_manager/include/security_manager/security_manager_impl.h b/src/components/security_manager/include/security_manager/security_manager_impl.h
index 469b97d1e1..70b87de0ef 100644
--- a/src/components/security_manager/include/security_manager/security_manager_impl.h
+++ b/src/components/security_manager/include/security_manager/security_manager_impl.h
@@ -35,6 +35,8 @@
#include <list>
#include <string>
+#include <set>
+#include <memory>
#include "utils/macro.h"
#include "utils/message_queue.h"
@@ -44,6 +46,7 @@
#include "security_manager/security_query.h"
#include "protocol_handler/protocol_handler.h"
#include "protocol/common.h"
+#include "utils/system_time_handler.h"
namespace security_manager {
/**
@@ -67,12 +70,21 @@ typedef threads::MessageLoopThread<SecurityMessageQueue> SecurityMessageLoop;
* \brief SecurityManagerImpl class implements SecurityManager interface
*/
class SecurityManagerImpl : public SecurityManager,
- public SecurityMessageLoop::Handler {
+ public SecurityMessageLoop::Handler,
+ public utils::SystemTimeListener {
public:
/**
* \brief Constructor
+ * \param system_time_handler allows to work with system time.
*/
- SecurityManagerImpl();
+ explicit SecurityManagerImpl(
+ std::unique_ptr<utils::SystemTimeHandler>&& system_time_handler);
+
+ /**
+ * \brief Destructor
+ */
+ ~SecurityManagerImpl();
+
/**
* \brief Add received from Mobile Application message
* Overriden ProtocolObserver::OnMessageReceived method
@@ -131,9 +143,11 @@ class SecurityManagerImpl : public SecurityManager,
* Do not notify listeners, send security error on occure
* \param connection_key Unique key used by other components as session
* identifier
+ * @param cc_strategy - SSL context creation strategy
* @return new \c SSLContext or \c NULL on any error
*/
- SSLContext* CreateSSLContext(const uint32_t& connection_key) OVERRIDE;
+ SSLContext* CreateSSLContext(const uint32_t& connection_key,
+ ContextCreationStrategy cc_strategy) OVERRIDE;
/**
* \brief Start handshake as SSL client
@@ -141,16 +155,33 @@ class SecurityManagerImpl : public SecurityManager,
void StartHandshake(uint32_t connection_key) OVERRIDE;
/**
+ * @brief PostponeHandshake allows to postpone handshake. It notifies
+ * cryptomanager that certificate should be updated and adds specified
+ * connection key to the list of the certificate awaiting connections.
+ * @param connection_key the identifier for connection to postpone handshake.
+ */
+ void PostponeHandshake(const uint32_t connection_key) OVERRIDE;
+
+ /**
* @brief Checks whether certificate should be updated
+ * @param connection_key the connection identifier to check certificate for.
* @return true if certificate should be updated otherwise false
*/
- bool IsCertificateUpdateRequired() OVERRIDE;
+ bool IsCertificateUpdateRequired(const uint32_t connection_key) OVERRIDE;
+
+ /**
+ * @brief Checks whether system time ready notification
+ * was received from hmi
+ * @return true if received otherwise false
+ */
+ bool IsSystemTimeProviderReady() const OVERRIDE;
/**
* \brief Add/Remove for SecurityManagerListener
*/
void AddListener(SecurityManagerListener* const listener) OVERRIDE;
void RemoveListener(SecurityManagerListener* const listener) OVERRIDE;
+
/**
* \brief Notifiers for listeners
* \param connection_key Unique key used by other components as session
@@ -173,6 +204,11 @@ class SecurityManagerImpl : public SecurityManager,
void NotifyOnCertificateUpdateRequired() OVERRIDE;
/**
+ * @brief Notify all listeners that handshake was failed
+ */
+ void NotifyListenersOnHandshakeFailed() OVERRIDE;
+
+ /**
* @brief Check is policy certificate data is empty
* @return true if policy certificate data is not empty otherwise false
*/
@@ -217,6 +253,39 @@ class SecurityManagerImpl : public SecurityManager,
*/
void SendQuery(const SecurityQuery& query, const uint32_t connection_key);
+ /**
+ * @brief OnCertificateUpdated allows to obtain notification when certificate
+ * has been updated with policy table update. Pass this certificate to crypto
+ * manager for further processing. Also process postopnes handshake for the
+ * certain connection key.
+ *
+ * @param data the certificates content.
+ * @return always true.
+ */
+ bool OnCertificateUpdated(const std::string& data) OVERRIDE;
+
+ /**
+ * @brief ResumeHandshake allows to resume handshake after certificate has
+ * been updated.
+ * @param connection_key the connection identifier to start handshake.
+ */
+ void ResumeHandshake(uint32_t connection_key);
+
+ /**
+ * @brief ProceedHandshake starts the handshake process.
+ * @param ssl_context ssl context for the handshake. COntains certificate,
+ * keys, etc.
+ * @param connection_key the connection identifier to process handshake.
+ */
+ void ProceedHandshake(SSLContext* ssl_context, uint32_t connection_key);
+
+ /**
+ * @brief OnSystemTimeArrived method which notifies
+ * crypto manager with updated time in order to check certificate validity
+ * @param utc_time the current system time.
+ */
+ void OnSystemTimeArrived(const time_t utc_time) OVERRIDE;
+
// Thread that pumps handshake data
SecurityMessageLoop security_messages_;
@@ -235,7 +304,17 @@ class SecurityManagerImpl : public SecurityManager,
/**
*\brief List of listeners for notify handshake done result
*/
+
std::list<SecurityManagerListener*> listeners_;
+
+ std::unique_ptr<utils::SystemTimeHandler> system_time_handler_;
+ sync_primitives::Lock connections_lock_;
+ std::set<uint32_t> awaiting_certificate_connections_;
+ std::set<uint32_t> awaiting_time_connections_;
+
+ mutable sync_primitives::Lock waiters_lock_;
+ volatile bool waiting_for_certificate_;
+ volatile bool waiting_for_time_;
DISALLOW_COPY_AND_ASSIGN(SecurityManagerImpl);
};
} // namespace security_manager
diff --git a/src/components/security_manager/src/crypto_manager_impl.cc b/src/components/security_manager/src/crypto_manager_impl.cc
index f3dfa8bb1d..1506382bce 100644
--- a/src/components/security_manager/src/crypto_manager_impl.cc
+++ b/src/components/security_manager/src/crypto_manager_impl.cc
@@ -41,6 +41,7 @@
#include <iostream>
#include <stdio.h>
#include <ctime>
+#include <algorithm>
#include "security_manager/security_manager.h"
#include "utils/logger.h"
@@ -63,7 +64,12 @@ namespace {
int debug_callback(int preverify_ok, X509_STORE_CTX* ctx) {
if (!preverify_ok) {
const int error = X509_STORE_CTX_get_error(ctx);
- UNUSED(error);
+ if (error == X509_V_ERR_CERT_NOT_YET_VALID ||
+ error == X509_V_ERR_CERT_HAS_EXPIRED) {
+ // return success result code instead of error because start
+ // and expiration cert dates will be checked by SDL
+ return 1;
+ }
LOG4CXX_WARN(logger_,
"Certificate verification failed with error "
<< error << " \"" << X509_verify_cert_error_string(error)
@@ -93,7 +99,6 @@ CryptoManagerImpl::CryptoManagerImpl(
OpenSSL_add_all_algorithms();
SSL_library_init();
}
- InitCertExpTime();
}
CryptoManagerImpl::~CryptoManagerImpl() {
@@ -113,10 +118,35 @@ CryptoManagerImpl::~CryptoManagerImpl() {
}
}
+bool CryptoManagerImpl::AreForceProtectionSettingsCorrect() const {
+ LOG4CXX_AUTO_TRACE(logger_);
+ const std::vector<int>& forced_unprotected_services =
+ get_settings().force_unprotected_service();
+ const std::vector<int>& forced_protected_services =
+ get_settings().force_protected_service();
+
+ for (auto& item : forced_protected_services) {
+ if (0 == item) {
+ continue;
+ }
+
+ if (std::find(forced_unprotected_services.begin(),
+ forced_unprotected_services.end(),
+ item) != forced_unprotected_services.end()) {
+ return false;
+ }
+ }
+ return true;
+}
+
bool CryptoManagerImpl::Init() {
LOG4CXX_AUTO_TRACE(logger_);
const Mode mode = get_settings().security_manager_mode();
+ if (!AreForceProtectionSettingsCorrect()) {
+ LOG4CXX_DEBUG(logger_, "Force protection settings of ini file are wrong!");
+ return false;
+ }
const bool is_server = (mode == SERVER);
if (is_server) {
LOG4CXX_DEBUG(logger_, "Server mode");
@@ -133,7 +163,7 @@ bool CryptoManagerImpl::Init() {
#if OPENSSL_VERSION_NUMBER < CONST_SSL_METHOD_MINIMAL_VERSION
SSL_METHOD* method;
#else
- const SSL_METHOD* method;
+ const SSL_METHOD* method = NULL;
#endif
switch (get_settings().security_manager_protocol_name()) {
case SSLv3:
@@ -141,13 +171,16 @@ bool CryptoManagerImpl::Init() {
LOG4CXX_WARN(logger_, "OpenSSL does not support SSL3 protocol");
return false;
#else
+ LOG4CXX_DEBUG(logger_, "SSLv3 is used");
method = is_server ? SSLv3_server_method() : SSLv3_client_method();
break;
#endif
case TLSv1:
+ LOG4CXX_DEBUG(logger_, "TLSv1 is used");
method = is_server ? TLSv1_server_method() : TLSv1_client_method();
break;
case TLSv1_1:
+ LOG4CXX_DEBUG(logger_, "TLSv1_1 is used");
#if OPENSSL_VERSION_NUMBER < TLS1_1_MINIMAL_VERSION
LOG4CXX_WARN(
logger_,
@@ -158,6 +191,7 @@ bool CryptoManagerImpl::Init() {
#endif
break;
case TLSv1_2:
+ LOG4CXX_DEBUG(logger_, "TLSv1_2 is used");
#if OPENSSL_VERSION_NUMBER < TLS1_1_MINIMAL_VERSION
LOG4CXX_WARN(
logger_,
@@ -167,6 +201,10 @@ bool CryptoManagerImpl::Init() {
method = is_server ? TLSv1_2_server_method() : TLSv1_2_client_method();
#endif
break;
+ case DTLSv1:
+ LOG4CXX_DEBUG(logger_, "DTLSv1 is used");
+ method = is_server ? DTLSv1_server_method() : DTLSv1_client_method();
+ break;
default:
LOG4CXX_ERROR(logger_,
"Unknown protocol: "
@@ -183,7 +221,7 @@ bool CryptoManagerImpl::Init() {
// Disable SSL2 as deprecated
SSL_CTX_set_options(context_, SSL_OP_NO_SSLv2);
- set_certificate(get_settings().certificate_data());
+ SaveCertificateData(get_settings().certificate_data());
if (get_settings().ciphers_list().empty()) {
LOG4CXX_WARN(logger_, "Empty ciphers list");
@@ -216,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 =
@@ -235,17 +288,33 @@ bool CryptoManagerImpl::OnCertificateUpdated(const std::string& data) {
return false;
}
- return set_certificate(data);
+ if (!SaveCertificateData(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() {
- if (context_ == NULL) {
+ if (NULL == context_) {
return NULL;
}
SSL* conn = SSL_new(context_);
- if (conn == NULL)
+ if (NULL == conn) {
return NULL;
+ }
if (get_settings().security_manager_mode() == SERVER) {
SSL_set_accept_state(conn);
@@ -269,24 +338,17 @@ std::string CryptoManagerImpl::LastError() const {
return std::string(reason ? reason : "");
}
-bool CryptoManagerImpl::IsCertificateUpdateRequired() const {
+bool CryptoManagerImpl::IsCertificateUpdateRequired(
+ const time_t system_time, const time_t certificates_time) const {
LOG4CXX_AUTO_TRACE(logger_);
- const time_t cert_date = mktime(&expiration_time_);
+ const double seconds = difftime(certificates_time, system_time);
- if (cert_date == -1) {
- LOG4CXX_WARN(logger_,
- "The certifiacte expiration time cannot be represented.");
- return false;
- }
- const time_t now = time(NULL);
- const double seconds = difftime(cert_date, now);
+ LOG4CXX_DEBUG(
+ logger_, "Certificate UTC time: " << asctime(gmtime(&certificates_time)));
- LOG4CXX_DEBUG(logger_,
- "Certificate expiration time: " << asctime(&expiration_time_));
- LOG4CXX_DEBUG(logger_,
- "Host time: " << asctime(localtime(&now))
- << ". Seconds before expiration: " << seconds);
+ LOG4CXX_DEBUG(logger_, "Host UTC time: " << asctime(gmtime(&system_time)));
+ LOG4CXX_DEBUG(logger_, "Seconds before expiration: " << seconds);
if (seconds < 0) {
LOG4CXX_WARN(logger_, "Certificate is already expired.");
return true;
@@ -300,7 +362,8 @@ const CryptoManagerSettings& CryptoManagerImpl::get_settings() const {
return *settings_;
}
-bool CryptoManagerImpl::set_certificate(const std::string& cert_data) {
+bool CryptoManagerImpl::SaveCertificateData(
+ const std::string& cert_data) const {
LOG4CXX_AUTO_TRACE(logger_);
if (cert_data.empty()) {
@@ -315,100 +378,162 @@ bool CryptoManagerImpl::set_certificate(const std::string& cert_data) {
UNUSED(bio_guard)
X509* cert = NULL;
- PEM_read_bio_X509(bio_cert, &cert, 0, 0);
+ if (!PEM_read_bio_X509(bio_cert, &cert, 0, 0)) {
+ LOG4CXX_WARN(logger_, "Could not read certificate data: " << LastError());
+ return false;
+ }
- EVP_PKEY* pkey = NULL;
- if (1 == BIO_reset(bio_cert)) {
- PEM_read_bio_PrivateKey(bio_cert, &pkey, 0, 0);
- } else {
+ utils::ScopeGuard cert_guard = utils::MakeGuard(X509_free, cert);
+ UNUSED(cert_guard);
+
+ if (1 != BIO_reset(bio_cert)) {
LOG4CXX_WARN(logger_,
"Unabled to reset BIO in order to read private key, "
<< LastError());
}
- if (NULL == cert || NULL == pkey) {
- LOG4CXX_WARN(logger_, "Either certificate or key not valid.");
+ EVP_PKEY* pkey = NULL;
+ if (!PEM_read_bio_PrivateKey(bio_cert, &pkey, 0, 0)) {
+ LOG4CXX_WARN(logger_, "Could not read private key data: " << LastError());
return false;
}
- if (!SSL_CTX_use_certificate(context_, cert)) {
- LOG4CXX_WARN(logger_, "Could not use certificate: " << LastError());
- return false;
- }
+ utils::ScopeGuard key_guard = utils::MakeGuard(EVP_PKEY_free, pkey);
+ UNUSED(key_guard);
- asn1_time_to_tm(X509_get_notAfter(cert));
+ return SaveModuleCertificateToFile(cert) && SaveModuleKeyToFile(pkey);
+}
- if (!SSL_CTX_use_PrivateKey(context_, pkey)) {
- LOG4CXX_ERROR(logger_, "Could not use key: " << LastError());
- return false;
+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 (!SSL_CTX_check_private_key(context_)) {
- LOG4CXX_ERROR(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;
+ }
- X509_STORE* store = SSL_CTX_get_cert_store(context_);
- if (store) {
- X509* extra_cert = NULL;
- while ((extra_cert = PEM_read_bio_X509(bio_cert, NULL, 0, 0))) {
- if (extra_cert != cert) {
- LOG4CXX_DEBUG(logger_,
- "Added new certificate to store: " << extra_cert);
- X509_STORE_add_cert(store, extra_cert);
- }
+ if (!SSL_CTX_check_private_key(context_)) {
+ LOG4CXX_ERROR(logger_, "Private key is invalid: " << LastError());
+ return false;
}
}
- LOG4CXX_DEBUG(logger_, "Certificate and key successfully updated");
+ LOG4CXX_DEBUG(logger_, "Certificate and key are successfully updated");
return true;
}
-int CryptoManagerImpl::pull_number_from_buf(char* buf, int* idx) {
- if (!idx) {
- return 0;
+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;
}
- const int val = ((buf[*idx] - '0') * 10) + buf[(*idx) + 1] - '0';
- *idx = *idx + 2;
- return val;
+ LOG4CXX_DEBUG(logger_,
+ "Module certificate was loaded: " << module_certificate);
+
+ return module_certificate;
}
-void CryptoManagerImpl::asn1_time_to_tm(ASN1_TIME* time) {
- char* buf = (char*)time->data;
- int index = 0;
- const int year = pull_number_from_buf(buf, &index);
- if (V_ASN1_GENERALIZEDTIME == time->type) {
- expiration_time_.tm_year =
- (year * 100 - 1900) + pull_number_from_buf(buf, &index);
- } else {
- expiration_time_.tm_year = year < 50 ? year + 100 : year;
+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);
- const int mon = pull_number_from_buf(buf, &index);
- const int day = pull_number_from_buf(buf, &index);
- const int hour = pull_number_from_buf(buf, &index);
- const int mn = pull_number_from_buf(buf, &index);
+ return module_key;
+}
- expiration_time_.tm_mon = mon - 1;
- expiration_time_.tm_mday = day;
- expiration_time_.tm_hour = hour;
- expiration_time_.tm_min = mn;
+bool CryptoManagerImpl::SaveModuleCertificateToFile(X509* certificate) const {
+ LOG4CXX_AUTO_TRACE(logger_);
- if (buf[index] == 'Z') {
- expiration_time_.tm_sec = 0;
+ if (!certificate) {
+ LOG4CXX_WARN(logger_, "Empty certificate. Saving will be skipped");
+ return false;
}
- if ((buf[index] == '+') || (buf[index] == '-')) {
- const int mn = pull_number_from_buf(buf, &index);
- const int mn1 = pull_number_from_buf(buf, &index);
- expiration_time_.tm_sec = (mn * 3600) + (mn1 * 60);
- } else {
- const int sec = pull_number_from_buf(buf, &index);
- expiration_time_.tm_sec = sec;
+
+ const std::string cert_path = get_settings().module_cert_path();
+ BIO* bio_cert = BIO_new_file(cert_path.c_str(), "w");
+ if (!bio_cert) {
+ LOG4CXX_ERROR(logger_,
+ "Failed to open " << cert_path << " file: " << LastError());
+ return false;
+ }
+
+ utils::ScopeGuard bio_guard = utils::MakeGuard(BIO_free, bio_cert);
+ UNUSED(bio_guard);
+
+ if (!PEM_write_bio_X509(bio_cert, certificate)) {
+ LOG4CXX_ERROR(logger_,
+ "Failed to write certificate to file: " << LastError());
+ return false;
}
+
+ return true;
}
-void CryptoManagerImpl::InitCertExpTime() {
- strptime("1 Jan 1970 00:00:00", "%d %b %Y %H:%M:%S", &expiration_time_);
+bool CryptoManagerImpl::SaveModuleKeyToFile(EVP_PKEY* key) const {
+ LOG4CXX_AUTO_TRACE(logger_);
+
+ if (!key) {
+ LOG4CXX_WARN(logger_, "Empty private key. Saving will be skipped");
+ return false;
+ }
+
+ const std::string key_path = get_settings().module_key_path();
+ BIO* bio_key = BIO_new_file(key_path.c_str(), "w");
+ if (!bio_key) {
+ LOG4CXX_ERROR(logger_,
+ "Failed to open " << key_path << " file: " << LastError());
+ return false;
+ }
+
+ utils::ScopeGuard bio_guard = utils::MakeGuard(BIO_free, bio_key);
+ UNUSED(bio_guard);
+
+ if (!PEM_write_bio_PrivateKey(bio_key, key, NULL, NULL, 0, NULL, NULL)) {
+ LOG4CXX_ERROR(logger_, "Failed to write key to file: " << LastError());
+ return false;
+ }
+
+ return true;
}
} // namespace security_manager
diff --git a/src/components/security_manager/src/security_manager_impl.cc b/src/components/security_manager/src/security_manager_impl.cc
index 1853b218b4..1faaddee1c 100644
--- a/src/components/security_manager/src/security_manager_impl.cc
+++ b/src/components/security_manager/src/security_manager_impl.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Ford Motor Company
+ * Copyright (c) 2018, Ford Motor Company
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -31,11 +31,13 @@
*/
#include "security_manager/security_manager_impl.h"
+#include <functional>
#include "security_manager/crypto_manager_impl.h"
#include "protocol_handler/protocol_packet.h"
#include "utils/logger.h"
#include "utils/byte_order.h"
#include "json/json.h"
+#include "utils/helpers.h"
namespace security_manager {
@@ -44,11 +46,22 @@ CREATE_LOGGERPTR_GLOBAL(logger_, "SecurityManager")
static const char* kErrId = "id";
static const char* kErrText = "text";
-SecurityManagerImpl::SecurityManagerImpl()
+SecurityManagerImpl::SecurityManagerImpl(
+ std::unique_ptr<utils::SystemTimeHandler>&& system_time_handler)
: security_messages_("SecurityManager", this)
, session_observer_(NULL)
, crypto_manager_(NULL)
- , protocol_handler_(NULL) {}
+ , protocol_handler_(NULL)
+ , system_time_handler_(std::move(system_time_handler))
+ , waiting_for_certificate_(false)
+ , waiting_for_time_(false) {
+ DCHECK(system_time_handler_);
+ system_time_handler_->SubscribeOnSystemTime(this);
+}
+
+SecurityManagerImpl::~SecurityManagerImpl() {
+ system_time_handler_->UnsubscribeFromSystemTime(this);
+}
void SecurityManagerImpl::OnMessageReceived(
const ::protocol_handler::RawMessagePtr message) {
@@ -136,19 +149,23 @@ void SecurityManagerImpl::Handle(const SecurityMessage message) {
}
security_manager::SSLContext* SecurityManagerImpl::CreateSSLContext(
- const uint32_t& connection_key) {
+ const uint32_t& connection_key, ContextCreationStrategy cc_strategy) {
LOG4CXX_INFO(logger_, "ProtectService processing");
DCHECK(session_observer_);
DCHECK(crypto_manager_);
- security_manager::SSLContext* ssl_context = session_observer_->GetSSLContext(
- connection_key, protocol_handler::kControl);
- // return exists SSLCOntext for current connection/session
- if (ssl_context) {
- return ssl_context;
+ if (kUseExisting == cc_strategy) {
+ security_manager::SSLContext* ssl_context =
+ session_observer_->GetSSLContext(connection_key,
+ protocol_handler::kControl);
+ // If SSLContext for current connection/session exists - return it
+ if (ssl_context) {
+ return ssl_context;
+ }
}
- ssl_context = crypto_manager_->CreateSSLContext();
+ security_manager::SSLContext* ssl_context =
+ crypto_manager_->CreateSSLContext();
if (!ssl_context) {
const std::string error_text("CryptoManager could not create SSL context.");
LOG4CXX_ERROR(logger_, error_text);
@@ -172,6 +189,40 @@ security_manager::SSLContext* SecurityManagerImpl::CreateSSLContext(
return ssl_context;
}
+void SecurityManagerImpl::PostponeHandshake(const uint32_t connection_key) {
+ LOG4CXX_TRACE(logger_, "Handshake postponed");
+ sync_primitives::AutoLock lock(connections_lock_);
+ if (waiting_for_certificate_) {
+ awaiting_certificate_connections_.insert(connection_key);
+ }
+ if (waiting_for_time_) {
+ awaiting_time_connections_.insert(connection_key);
+ }
+}
+
+void SecurityManagerImpl::ResumeHandshake(uint32_t connection_key) {
+ LOG4CXX_TRACE(logger_, "Handshake resumed");
+
+ security_manager::SSLContext* ssl_context =
+ CreateSSLContext(connection_key, kForceRecreation);
+
+ if (!ssl_context) {
+ LOG4CXX_WARN(logger_,
+ "Unable to resume handshake. No SSL context for key "
+ << connection_key);
+ return;
+ }
+
+ ssl_context->ResetConnection();
+ if (!waiting_for_certificate_ && !ssl_context->HasCertificate()) {
+ NotifyListenersOnHandshakeDone(connection_key,
+ SSLContext::Handshake_Result_Fail);
+ return;
+ }
+
+ ProceedHandshake(ssl_context, connection_key);
+}
+
void SecurityManagerImpl::StartHandshake(uint32_t connection_key) {
DCHECK(session_observer_);
LOG4CXX_INFO(logger_, "StartHandshake: connection_key " << connection_key);
@@ -187,6 +238,35 @@ void SecurityManagerImpl::StartHandshake(uint32_t connection_key) {
SSLContext::Handshake_Result_Fail);
return;
}
+ if (!ssl_context->HasCertificate()) {
+ LOG4CXX_ERROR(logger_, "Security certificate is absent");
+ sync_primitives::AutoLock lock(waiters_lock_);
+ waiting_for_certificate_ = true;
+ NotifyOnCertificateUpdateRequired();
+ }
+
+ {
+ sync_primitives::AutoLock lock(waiters_lock_);
+ waiting_for_time_ = true;
+ }
+
+ PostponeHandshake(connection_key);
+ system_time_handler_->QuerySystemTime();
+}
+
+bool SecurityManagerImpl::IsSystemTimeProviderReady() const {
+ return system_time_handler_->system_time_can_be_received();
+}
+
+void SecurityManagerImpl::ProceedHandshake(
+ security_manager::SSLContext* ssl_context, uint32_t connection_key) {
+ LOG4CXX_AUTO_TRACE(logger_);
+ if (!ssl_context) {
+ LOG4CXX_WARN(logger_,
+ "Unable to process handshake. No SSL context for key "
+ << connection_key);
+ return;
+ }
if (ssl_context->IsInitCompleted()) {
NotifyListenersOnHandshakeDone(connection_key,
@@ -194,8 +274,33 @@ void SecurityManagerImpl::StartHandshake(uint32_t connection_key) {
return;
}
- ssl_context->SetHandshakeContext(
- session_observer_->GetHandshakeContext(connection_key));
+ time_t cert_due_date;
+ if (!ssl_context->GetCertificateDueDate(cert_due_date)) {
+ LOG4CXX_ERROR(logger_, "Failed to get certificate due date!");
+ return;
+ }
+
+ if (crypto_manager_->IsCertificateUpdateRequired(
+ system_time_handler_->GetUTCTime(), cert_due_date)) {
+ LOG4CXX_DEBUG(logger_, "Host certificate update required");
+ if (helpers::in_range(awaiting_certificate_connections_, connection_key)) {
+ NotifyListenersOnHandshakeDone(connection_key,
+ SSLContext::Handshake_Result_CertExpired);
+ return;
+ }
+ {
+ sync_primitives::AutoLock lock(waiters_lock_);
+ waiting_for_certificate_ = true;
+ }
+ PostponeHandshake(connection_key);
+ NotifyOnCertificateUpdateRequired();
+ return;
+ }
+
+ SSLContext::HandshakeContext handshake_context =
+ session_observer_->GetHandshakeContext(connection_key);
+ handshake_context.system_time = system_time_handler_->GetUTCTime();
+ ssl_context->SetHandshakeContext(handshake_context);
size_t data_size = 0;
const uint8_t* data = NULL;
@@ -216,9 +321,21 @@ void SecurityManagerImpl::StartHandshake(uint32_t connection_key) {
}
}
-bool SecurityManagerImpl::IsCertificateUpdateRequired() {
+bool SecurityManagerImpl::IsCertificateUpdateRequired(
+ const uint32_t connection_key) {
LOG4CXX_AUTO_TRACE(logger_);
- return crypto_manager_->IsCertificateUpdateRequired();
+ security_manager::SSLContext* ssl_context =
+ CreateSSLContext(connection_key, kUseExisting);
+ DCHECK_OR_RETURN(ssl_context, true);
+ LOG4CXX_DEBUG(logger_,
+ "Set SSL context to connection_key " << connection_key);
+ time_t cert_due_date;
+ if (!ssl_context->GetCertificateDueDate(cert_due_date)) {
+ LOG4CXX_ERROR(logger_, "Failed to get certificate due date!");
+ return true;
+ }
+ return crypto_manager_->IsCertificateUpdateRequired(
+ system_time_handler_->GetUTCTime(), cert_due_date);
}
void SecurityManagerImpl::AddListener(SecurityManagerListener* const listener) {
@@ -227,7 +344,6 @@ void SecurityManagerImpl::AddListener(SecurityManagerListener* const listener) {
"Invalid (NULL) pointer to SecurityManagerListener.");
return;
}
- LOG4CXX_DEBUG(logger_, "Adding listener " << listener);
listeners_.push_back(listener);
}
@@ -241,6 +357,37 @@ void SecurityManagerImpl::RemoveListener(
listeners_.remove(listener);
}
+bool SecurityManagerImpl::OnCertificateUpdated(const std::string& data) {
+ LOG4CXX_AUTO_TRACE(logger_);
+ {
+ sync_primitives::AutoLock lock(waiters_lock_);
+ waiting_for_certificate_ = false;
+ }
+ crypto_manager_->OnCertificateUpdated(data);
+ std::for_each(
+ awaiting_certificate_connections_.begin(),
+ awaiting_certificate_connections_.end(),
+ std::bind1st(std::mem_fun(&SecurityManagerImpl::ResumeHandshake), this));
+
+ awaiting_certificate_connections_.clear();
+ return true;
+}
+
+void SecurityManagerImpl::OnSystemTimeArrived(const time_t utc_time) {
+ LOG4CXX_AUTO_TRACE(logger_);
+ {
+ sync_primitives::AutoLock lock(waiters_lock_);
+ waiting_for_time_ = false;
+ }
+
+ std::for_each(
+ awaiting_time_connections_.begin(),
+ awaiting_time_connections_.end(),
+ std::bind1st(std::mem_fun(&SecurityManagerImpl::ResumeHandshake), this));
+
+ awaiting_time_connections_.clear();
+}
+
void SecurityManagerImpl::NotifyListenersOnHandshakeDone(
const uint32_t& connection_key, SSLContext::HandshakeResult error) {
LOG4CXX_AUTO_TRACE(logger_);
@@ -269,6 +416,20 @@ void SecurityManagerImpl::NotifyOnCertificateUpdateRequired() {
}
}
+void SecurityManagerImpl::NotifyListenersOnHandshakeFailed() {
+ LOG4CXX_AUTO_TRACE(logger_);
+ std::list<SecurityManagerListener*>::iterator it = listeners_.begin();
+ while (it != listeners_.end()) {
+ if ((*it)->OnHandshakeFailed()) {
+ LOG4CXX_DEBUG(logger_, "Destroying listener: " << *it);
+ delete (*it);
+ it = listeners_.erase(it);
+ } else {
+ ++it;
+ }
+ }
+}
+
bool SecurityManagerImpl::IsPolicyCertificateDataEmpty() {
LOG4CXX_AUTO_TRACE(logger_);
diff --git a/src/components/security_manager/src/ssl_context_impl.cc b/src/components/security_manager/src/ssl_context_impl.cc
index 0b30198f4c..67be17db63 100644
--- a/src/components/security_manager/src/ssl_context_impl.cc
+++ b/src/components/security_manager/src/ssl_context_impl.cc
@@ -36,6 +36,7 @@
#include <map>
#include <algorithm>
#include <vector>
+#include <time.h>
#include <openssl/bio.h>
#include <openssl/ssl.h>
@@ -77,6 +78,7 @@ bool CryptoManagerImpl::SSLContextImpl::IsInitCompleted() const {
SSLContext::HandshakeResult CryptoManagerImpl::SSLContextImpl::StartHandshake(
const uint8_t** const out_data, size_t* out_data_size) {
+ LOG4CXX_AUTO_TRACE(logger_);
is_handshake_pending_ = true;
return DoHandshakeStep(NULL, 0, out_data, out_data_size);
}
@@ -112,6 +114,12 @@ size_t des_cbc3_sha_max_block_size(size_t mtu) {
return 0;
return ((mtu - 29) & 0xfffffff8) - 5;
}
+time_t get_time_zone_offset(time_t in_time) {
+ tm gmt_cert_tm = *gmtime(&in_time);
+ tm local_cert_tm = *localtime(&in_time);
+
+ return mktime(&local_cert_tm) - mktime(&gmt_cert_tm);
+}
} // namespace
std::map<std::string, CryptoManagerImpl::SSLContextImpl::BlockSizeGetter>
@@ -174,6 +182,7 @@ const std::string CryptoManagerImpl::SSLContextImpl::RemoveDisallowedInfo(
void CryptoManagerImpl::SSLContextImpl::PrintCertData(
X509* cert, const std::string& cert_owner) {
+ LOG4CXX_AUTO_TRACE(logger_);
if (!cert) {
LOG4CXX_DEBUG(logger_, "Empty certificate data");
return;
@@ -206,6 +215,7 @@ void CryptoManagerImpl::SSLContextImpl::PrintCertData(
}
void CryptoManagerImpl::SSLContextImpl::PrintCertInfo() {
+ LOG4CXX_AUTO_TRACE(logger_);
PrintCertData(SSL_get_certificate(connection_), "HU's");
STACK_OF(X509)* peer_certs = SSL_get_peer_cert_chain(connection_);
@@ -217,26 +227,47 @@ void CryptoManagerImpl::SSLContextImpl::PrintCertInfo() {
SSLContext::HandshakeResult
CryptoManagerImpl::SSLContextImpl::CheckCertContext() {
+ LOG4CXX_AUTO_TRACE(logger_);
X509* cert = SSL_get_peer_certificate(connection_);
if (!cert) {
// According to the openssl documentation the peer certificate
// might be ommitted for the SERVER but required for the cient.
return CLIENT == mode_ ? Handshake_Result_Fail : Handshake_Result_Success;
}
+ ASN1_TIME* notBefore = X509_get_notBefore(cert);
+ ASN1_TIME* notAfter = X509_get_notAfter(cert);
- X509_NAME* subj_name = X509_get_subject_name(cert);
+ time_t start = convert_asn1_time_to_time_t(notBefore);
+ time_t end = convert_asn1_time_to_time_t(notAfter);
- const std::string& cn = GetTextBy(subj_name, NID_commonName);
- const std::string& sn = GetTextBy(subj_name, NID_serialNumber);
+ const double start_seconds = difftime(hsh_context_.system_time, start);
+ const double end_seconds = difftime(end, hsh_context_.system_time);
+
+ if (start_seconds < 0) {
+ LOG4CXX_ERROR(logger_,
+ "Certificate is not yet valid. Time before validity "
+ << start_seconds << " seconds");
+ return Handshake_Result_NotYetValid;
+ } else {
+ LOG4CXX_DEBUG(logger_,
+ "Time since certificate validity " << start_seconds
+ << "seconds");
+ }
- if (!(hsh_context_.expected_cn.CompareIgnoreCase(cn.c_str()))) {
+ if (end_seconds < 0) {
LOG4CXX_ERROR(logger_,
- "Trying to run handshake with wrong app name: "
- << cn << ". Expected app name: "
- << hsh_context_.expected_cn.AsMBString());
- return Handshake_Result_AppNameMismatch;
+ "Certificate already expired. Time after expiration "
+ << end_seconds << " seconds");
+ return Handshake_Result_CertExpired;
+ } else {
+ LOG4CXX_DEBUG(logger_,
+ "Time until expiration " << end_seconds << "seconds");
}
+ X509_NAME* subj_name = X509_get_subject_name(cert);
+
+ const std::string& sn = GetTextBy(subj_name, NID_serialNumber);
+
if (!(hsh_context_.expected_sn.CompareIgnoreCase(sn.c_str()))) {
LOG4CXX_ERROR(logger_,
"Trying to run handshake with wrong app id: "
@@ -247,6 +278,60 @@ CryptoManagerImpl::SSLContextImpl::CheckCertContext() {
return Handshake_Result_Success;
}
+int CryptoManagerImpl::SSLContextImpl::get_number_from_char_buf(
+ char* buf, int* idx) const {
+ if (!idx) {
+ return 0;
+ }
+ const int val = ((buf[*idx] - '0') * 10) + buf[(*idx) + 1] - '0';
+ *idx = *idx + 2;
+ return val;
+}
+
+time_t CryptoManagerImpl::SSLContextImpl::convert_asn1_time_to_time_t(
+ ASN1_TIME* time_to_convert) const {
+ struct tm cert_time;
+ memset(&cert_time, 0, sizeof(struct tm));
+ // the minimum value for day of month is 1, otherwise exception will be thrown
+ cert_time.tm_mday = 1;
+ char* buf = reinterpret_cast<char*>(time_to_convert->data);
+ int index = 0;
+ const int year = get_number_from_char_buf(buf, &index);
+ if (V_ASN1_GENERALIZEDTIME == time_to_convert->type) {
+ cert_time.tm_year =
+ (year * 100 - 1900) + get_number_from_char_buf(buf, &index);
+ } else {
+ cert_time.tm_year = year < 50 ? year + 100 : year;
+ }
+
+ const int mon = get_number_from_char_buf(buf, &index);
+ const int day = get_number_from_char_buf(buf, &index);
+ const int hour = get_number_from_char_buf(buf, &index);
+ const int mn = get_number_from_char_buf(buf, &index);
+
+ cert_time.tm_mon = mon - 1;
+ cert_time.tm_mday = day;
+ cert_time.tm_hour = hour;
+ cert_time.tm_min = mn;
+
+ if (buf[index] == 'Z') {
+ cert_time.tm_sec = 0;
+ }
+ if ((buf[index] == '+') || (buf[index] == '-')) {
+ const int mn = get_number_from_char_buf(buf, &index);
+ const int mn1 = get_number_from_char_buf(buf, &index);
+ cert_time.tm_sec = (mn * 3600) + (mn1 * 60);
+ } else {
+ const int sec = get_number_from_char_buf(buf, &index);
+ cert_time.tm_sec = sec;
+ }
+
+ const time_t local_cert_time = mktime(&cert_time);
+ const time_t time_offset = get_time_zone_offset(local_cert_time);
+
+ return local_cert_time + time_offset;
+}
+
bool CryptoManagerImpl::SSLContextImpl::ReadHandshakeData(
const uint8_t** const out_data, size_t* out_data_size) {
LOG4CXX_AUTO_TRACE(logger_);
@@ -288,7 +373,9 @@ bool CryptoManagerImpl::SSLContextImpl::WriteHandshakeData(
SSLContext::HandshakeResult
CryptoManagerImpl::SSLContextImpl::PerformHandshake() {
+ LOG4CXX_AUTO_TRACE(logger_);
const int handshake_result = SSL_do_handshake(connection_);
+ LOG4CXX_TRACE(logger_, "Handshake result: " << handshake_result);
if (handshake_result == 1) {
const HandshakeResult result = CheckCertContext();
if (result != Handshake_Result_Success) {
@@ -307,6 +394,7 @@ CryptoManagerImpl::SSLContextImpl::PerformHandshake() {
is_handshake_pending_ = false;
} else if (handshake_result == 0) {
+ LOG4CXX_DEBUG(logger_, "SSL handshake failed");
SSL_clear(connection_);
is_handshake_pending_ = false;
return Handshake_Result_Fail;
@@ -403,25 +491,32 @@ bool CryptoManagerImpl::SSLContextImpl::Decrypt(const uint8_t* const in_data,
size_t in_data_size,
const uint8_t** const out_data,
size_t* out_data_size) {
+ LOG4CXX_AUTO_TRACE(logger_);
sync_primitives::AutoLock locker(bio_locker);
if (!SSL_is_init_finished(connection_)) {
+ LOG4CXX_ERROR(logger_, "SSL initilization is not finished");
return false;
}
- if (!in_data || !in_data_size) {
+ if (!in_data || (0 == in_data_size)) {
+ LOG4CXX_ERROR(logger_, "IN data ptr or IN data size is 0");
return false;
}
+
BIO_write(bioIn_, in_data, in_data_size);
int len = BIO_ctrl_pending(bioFilter_);
+
ptrdiff_t offset = 0;
*out_data_size = 0;
- while (len) {
+ *out_data = NULL;
+ while (len > 0) {
EnsureBufferSizeEnough(len + offset);
len = BIO_read(bioFilter_, buffer_ + offset, len);
// TODO(EZamakhov): investigate BIO_read return 0, -1 and -2 meanings
if (len <= 0) {
// Reset filter and connection deinitilization instead
+ LOG4CXX_ERROR(logger_, "Read error occured. Read data lenght : " << len);
BIO_ctrl(bioFilter_, BIO_CTRL_RESET, 0, NULL);
return false;
}
@@ -447,6 +542,25 @@ bool CryptoManagerImpl::SSLContextImpl::IsHandshakePending() const {
return is_handshake_pending_;
}
+bool CryptoManagerImpl::SSLContextImpl::GetCertificateDueDate(
+ time_t& due_date) const {
+ LOG4CXX_AUTO_TRACE(logger_);
+
+ X509* cert = SSL_get_certificate(connection_);
+ if (!cert) {
+ LOG4CXX_DEBUG(logger_, "Get certificate failed.");
+ return false;
+ }
+
+ due_date = convert_asn1_time_to_time_t(X509_get_notAfter(cert));
+
+ return true;
+}
+
+bool CryptoManagerImpl::SSLContextImpl::HasCertificate() const {
+ return SSL_get_certificate(connection_) != NULL;
+}
+
CryptoManagerImpl::SSLContextImpl::~SSLContextImpl() {
SSL_shutdown(connection_);
SSL_free(connection_);
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 b30684e5f6..74b071793d 100644
--- a/src/components/security_manager/test/crypto_manager_impl_test.cc
+++ b/src/components/security_manager/test/crypto_manager_impl_test.cc
@@ -52,6 +52,10 @@ namespace {
const size_t kUpdatesBeforeHour = 24;
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;
@@ -89,6 +93,8 @@ class CryptoManagerTest : public testing::Test {
utils::MakeShared<MockCryptoManagerSettings>();
crypto_manager_ =
utils::MakeShared<CryptoManagerImpl>(mock_security_manager_settings_);
+ forced_protected_services_.reserve(kMaxSizeVector);
+ forced_unprotected_services_.reserve(kMaxSizeVector);
}
void InitSecurityManager() {
@@ -101,6 +107,10 @@ class CryptoManagerTest : public testing::Test {
void SetInitialValues(security_manager::Mode mode,
security_manager::Protocol protocol,
const std::string& cipher) {
+ ON_CALL(*mock_security_manager_settings_, force_unprotected_service())
+ .WillByDefault(ReturnRef(forced_unprotected_services_));
+ ON_CALL(*mock_security_manager_settings_, force_protected_service())
+ .WillByDefault(ReturnRef(forced_protected_services_));
ON_CALL(*mock_security_manager_settings_, security_manager_mode())
.WillByDefault(Return(mode));
ON_CALL(*mock_security_manager_settings_, security_manager_protocol_name())
@@ -111,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));
}
@@ -118,7 +132,10 @@ class CryptoManagerTest : public testing::Test {
utils::SharedPtr<CryptoManagerImpl> crypto_manager_;
utils::SharedPtr<MockCryptoManagerSettings> mock_security_manager_settings_;
static std::string certificate_data_base64_;
+ std::vector<int> forced_protected_services_;
+ std::vector<int> forced_unprotected_services_;
};
+
std::string CryptoManagerTest::certificate_data_base64_;
TEST_F(CryptoManagerTest, UsingBeforeInit) {
@@ -133,16 +150,15 @@ TEST_F(CryptoManagerTest, WrongInit) {
// Unknown protocol version
security_manager::Protocol UNKNOWN =
static_cast<security_manager::Protocol>(-1);
+ // Unexistent cipher value
+ const std::string invalid_cipher = "INVALID_UNKNOWN_CIPHER";
+ const security_manager::Mode mode = security_manager::SERVER;
- EXPECT_CALL(*mock_security_manager_settings_, security_manager_mode())
- .WillRepeatedly(Return(security_manager::SERVER));
- EXPECT_CALL(*mock_security_manager_settings_,
- security_manager_protocol_name()).WillOnce(Return(UNKNOWN));
- EXPECT_FALSE(crypto_manager_->Init());
+ SetInitialValues(mode, UNKNOWN, invalid_cipher);
+ EXPECT_FALSE(crypto_manager_->Init());
EXPECT_NE(std::string(), crypto_manager_->LastError());
- // Unexistent cipher value
- const std::string invalid_cipher = "INVALID_UNKNOWN_CIPHER";
+
EXPECT_CALL(*mock_security_manager_settings_,
security_manager_protocol_name())
.WillOnce(Return(security_manager::TLSv1_2));
@@ -151,7 +167,6 @@ TEST_F(CryptoManagerTest, WrongInit) {
EXPECT_CALL(*mock_security_manager_settings_, ciphers_list())
.WillRepeatedly(ReturnRef(invalid_cipher));
EXPECT_FALSE(crypto_manager_->Init());
-
EXPECT_NE(std::string(), crypto_manager_->LastError());
}
@@ -176,10 +191,18 @@ TEST_F(CryptoManagerTest, CorrectInit) {
security_manager::CLIENT, security_manager::TLSv1_1, kFordCipher);
EXPECT_TRUE(crypto_manager_->Init());
+ SetInitialValues(
+ security_manager::CLIENT, security_manager::DTLSv1, kFordCipher);
+ EXPECT_TRUE(crypto_manager_->Init());
+
// Cipher value
SetInitialValues(
security_manager::SERVER, security_manager::TLSv1_2, kAllCiphers);
EXPECT_TRUE(crypto_manager_->Init());
+
+ SetInitialValues(
+ security_manager::SERVER, security_manager::DTLSv1, kAllCiphers);
+ EXPECT_TRUE(crypto_manager_->Init());
}
// #endif // __QNX__
@@ -198,7 +221,6 @@ TEST_F(CryptoManagerTest, CreateReleaseSSLContext) {
EXPECT_CALL(*mock_security_manager_settings_, maximum_payload_size())
.Times(1)
.WillRepeatedly(Return(max_payload_size));
-
security_manager::SSLContext* context = crypto_manager_->CreateSSLContext();
EXPECT_TRUE(context);
EXPECT_NO_THROW(crypto_manager_->ReleaseSSLContext(context));
@@ -210,7 +232,10 @@ TEST_F(CryptoManagerTest, OnCertificateUpdated) {
}
TEST_F(CryptoManagerTest, OnCertificateUpdated_UpdateNotRequired) {
+ time_t system_time = 0;
+ time_t certificates_time = 1;
size_t updates_before = 0;
+
SetInitialValues(
security_manager::CLIENT, security_manager::TLSv1_2, kAllCiphers);
ASSERT_TRUE(crypto_manager_->Init());
@@ -218,7 +243,8 @@ TEST_F(CryptoManagerTest, OnCertificateUpdated_UpdateNotRequired) {
EXPECT_CALL(*mock_security_manager_settings_, update_before_hours())
.WillOnce(Return(updates_before));
- EXPECT_FALSE(crypto_manager_->IsCertificateUpdateRequired());
+ EXPECT_FALSE(crypto_manager_->IsCertificateUpdateRequired(system_time,
+ certificates_time));
size_t max_updates_ = std::numeric_limits<size_t>::max();
SetInitialValues(
@@ -227,7 +253,8 @@ TEST_F(CryptoManagerTest, OnCertificateUpdated_UpdateNotRequired) {
.WillOnce(Return(max_updates_));
ASSERT_TRUE(crypto_manager_->Init());
- EXPECT_TRUE(crypto_manager_->IsCertificateUpdateRequired());
+ EXPECT_TRUE(crypto_manager_->IsCertificateUpdateRequired(system_time,
+ certificates_time));
}
TEST_F(CryptoManagerTest, OnCertificateUpdated_NotInitialized) {
diff --git a/src/components/security_manager/test/security_manager_test.cc b/src/components/security_manager/test/security_manager_test.cc
index b334e78e19..3523bb7f44 100644
--- a/src/components/security_manager/test/security_manager_test.cc
+++ b/src/components/security_manager/test/security_manager_test.cc
@@ -44,6 +44,7 @@
#include "security_manager/mock_ssl_context.h"
#include "security_manager/mock_crypto_manager.h"
#include "security_manager/mock_security_manager_listener.h"
+#include "utils/mock_system_time_handler.h"
#include "utils/make_shared.h"
#include "utils/test_async_waiter.h"
@@ -76,11 +77,11 @@ using ::testing::_;
namespace {
// Sample data for handshake data emulation
-const int32_t key = 0x1;
-const int32_t seq_number = 0x2;
-const ServiceType secureServiceType = kControl;
-const uint32_t protocolVersion = PROTOCOL_VERSION_2;
-const bool is_final = false;
+const int32_t kKey = 0x1;
+const int32_t kSeqNumber = 0x2;
+const ServiceType kSecureServiceType = kControl;
+const uint32_t kProtocolVersion = PROTOCOL_VERSION_2;
+const bool kIsFinal = false;
const uint8_t handshake_data[] = {0x1, 0x2, 0x3, 0x4, 0x5};
const size_t handshake_data_size =
@@ -95,8 +96,12 @@ const uint32_t kAsyncExpectationsTimeout = 10000u;
class SecurityManagerTest : public ::testing::Test {
protected:
+ SecurityManagerTest()
+ : mock_system_time_handler(
+ std::unique_ptr<MockSystemTimeHandler>(new MockSystemTimeHandler()))
+ , security_manager_(
+ new SecurityManagerImpl(std::move(mock_system_time_handler))) {}
void SetUp() OVERRIDE {
- security_manager_.reset(new SecurityManagerImpl());
security_manager_->set_session_observer(&mock_session_observer);
security_manager_->set_protocol_handler(&mock_protocol_handler);
mock_sm_listener.reset(new testing::StrictMock<
@@ -105,7 +110,7 @@ class SecurityManagerTest : public ::testing::Test {
}
void SetMockCryptoManager() {
- EXPECT_CALL(mock_crypto_manager, IsCertificateUpdateRequired())
+ EXPECT_CALL(mock_crypto_manager, IsCertificateUpdateRequired(_, _))
.WillRepeatedly(Return(false));
security_manager_->set_crypto_manager(&mock_crypto_manager);
}
@@ -116,7 +121,7 @@ class SecurityManagerTest : public ::testing::Test {
uint32_t dataSize,
const ServiceType serviceType) {
const RawMessagePtr rawMessagePtr(utils::MakeShared<RawMessage>(
- key, protocolVersion, data, dataSize, serviceType));
+ kKey, kProtocolVersion, data, dataSize, serviceType));
security_manager_->OnMessageReceived(rawMessagePtr);
}
/*
@@ -147,13 +152,14 @@ class SecurityManagerTest : public ::testing::Test {
const int repeat_count = 1) {
const SecurityQuery::QueryHeader header(SecurityQuery::NOTIFICATION,
SecurityQuery::SEND_HANDSHAKE_DATA,
- seq_number);
+ kSeqNumber);
for (int c = 0; c < repeat_count; ++c) {
EmulateMobileMessage(header, data, data_size);
}
}
- ::utils::SharedPtr<SecurityManagerImpl> security_manager_;
+
// Strict mocks (same as all methods EXPECT_CALL().Times(0))
+
testing::StrictMock<protocol_handler_test::MockSessionObserver>
mock_session_observer;
testing::StrictMock<protocol_handler_test::MockProtocolHandler>
@@ -166,6 +172,8 @@ class SecurityManagerTest : public ::testing::Test {
mock_ssl_context_exists;
std::unique_ptr<testing::StrictMock<
security_manager_test::MockSecurityManagerListener> > mock_sm_listener;
+ std::unique_ptr<MockSystemTimeHandler> mock_system_time_handler;
+ std::shared_ptr<SecurityManagerImpl> security_manager_;
};
// Test Bodies
@@ -174,7 +182,6 @@ class SecurityManagerTest : public ::testing::Test {
* and shall not call any methodes
*/
TEST_F(SecurityManagerTest, SetNULL_Intefaces) {
- security_manager_.reset(new SecurityManagerImpl());
security_manager_->set_session_observer(NULL);
security_manager_->set_protocol_handler(NULL);
security_manager_->set_crypto_manager(NULL);
@@ -209,9 +216,9 @@ TEST_F(SecurityManagerTest, Listeners_NoListeners) {
security_manager_->RemoveListener(&mock_listener2);
security_manager_->NotifyListenersOnHandshakeDone(
- key, SSLContext::Handshake_Result_Success);
+ kKey, SSLContext::Handshake_Result_Success);
security_manager_->NotifyListenersOnHandshakeDone(
- key, SSLContext::Handshake_Result_Fail);
+ kKey, SSLContext::Handshake_Result_Fail);
}
/*
* Notifying two listeners
@@ -228,11 +235,11 @@ TEST_F(SecurityManagerTest, Listeners_Notifying) {
const SSLContext::HandshakeResult first_call_value =
SSLContext::Handshake_Result_Success;
// Expect call both listeners on 1st call
- EXPECT_CALL(*mock_listener1, OnHandshakeDone(key, first_call_value))
+ EXPECT_CALL(*mock_listener1, OnHandshakeDone(kKey, first_call_value))
.
// Emulate false (reject) result
WillOnce(Return(false));
- EXPECT_CALL(*mock_listener2, OnHandshakeDone(key, first_call_value))
+ EXPECT_CALL(*mock_listener2, OnHandshakeDone(kKey, first_call_value))
.
// Emulate true (accept) result
WillOnce(Return(true));
@@ -244,7 +251,7 @@ TEST_F(SecurityManagerTest, Listeners_Notifying) {
const SSLContext::HandshakeResult second_call_value =
SSLContext::Handshake_Result_Fail;
// Expect call last listener on 2d call
- EXPECT_CALL(*mock_listener1, OnHandshakeDone(key, second_call_value))
+ EXPECT_CALL(*mock_listener1, OnHandshakeDone(kKey, second_call_value))
.
// Emulate false (reject) result
WillOnce(Return(true));
@@ -254,14 +261,14 @@ TEST_F(SecurityManagerTest, Listeners_Notifying) {
security_manager_->AddListener(mock_listener1);
security_manager_->AddListener(mock_listener2);
// 1st call
- security_manager_->NotifyListenersOnHandshakeDone(key, first_call_value);
+ security_manager_->NotifyListenersOnHandshakeDone(kKey, first_call_value);
security_manager_->NotifyOnCertificateUpdateRequired();
// 2nd call
- security_manager_->NotifyListenersOnHandshakeDone(key, second_call_value);
+ security_manager_->NotifyListenersOnHandshakeDone(kKey, second_call_value);
security_manager_->NotifyOnCertificateUpdateRequired();
// 3nd call
security_manager_->NotifyListenersOnHandshakeDone(
- key, SSLContext::Handshake_Result_Fail);
+ kKey, SSLContext::Handshake_Result_Fail);
security_manager_->NotifyOnCertificateUpdateRequired();
}
@@ -275,7 +282,7 @@ TEST_F(SecurityManagerTest, SecurityManager_NULLCryptoManager) {
uint8_t session_id = 0;
TestAsyncWaiter waiter;
- EXPECT_CALL(mock_session_observer, PairFromKey(key, _, _));
+ EXPECT_CALL(mock_session_observer, PairFromKey(kKey, _, _));
EXPECT_CALL(mock_session_observer,
ProtocolVersionUsed(connection_id, session_id, _))
.WillOnce(Return(true));
@@ -283,7 +290,7 @@ TEST_F(SecurityManagerTest, SecurityManager_NULLCryptoManager) {
EXPECT_CALL(mock_protocol_handler,
SendMessageToMobileApp(
InternalErrorWithErrId(SecurityManager::ERROR_NOT_SUPPORTED),
- is_final)).WillOnce(NotifyTestAsyncWaiter(&waiter));
+ kIsFinal)).WillOnce(NotifyTestAsyncWaiter(&waiter));
const SecurityQuery::QueryHeader header(SecurityQuery::REQUEST,
// It could be any query id
SecurityQuery::INVALID_QUERY_ID);
@@ -298,7 +305,7 @@ TEST_F(SecurityManagerTest, SecurityManager_NULLCryptoManager) {
TEST_F(SecurityManagerTest, OnMobileMessageSent) {
const uint8_t* data_param = NULL;
const RawMessagePtr rawMessagePtr(
- utils::MakeShared<RawMessage>(key, protocolVersion, data_param, 0));
+ utils::MakeShared<RawMessage>(kKey, kProtocolVersion, data_param, 0));
security_manager_->OnMobileMessageSent(rawMessagePtr);
}
/*
@@ -319,7 +326,7 @@ TEST_F(SecurityManagerTest, GetEmptyQuery) {
uint32_t connection_id = 0;
uint8_t session_id = 0;
// uint8_t protocol_version = 0;
- EXPECT_CALL(mock_session_observer, PairFromKey(key, _, _));
+ EXPECT_CALL(mock_session_observer, PairFromKey(kKey, _, _));
EXPECT_CALL(mock_session_observer,
ProtocolVersionUsed(connection_id, session_id, _))
.WillOnce(Return(true));
@@ -328,9 +335,9 @@ TEST_F(SecurityManagerTest, GetEmptyQuery) {
mock_protocol_handler,
SendMessageToMobileApp(
InternalErrorWithErrId(SecurityManager::ERROR_INVALID_QUERY_SIZE),
- is_final));
+ kIsFinal));
// Call with NULL data
- call_OnMessageReceived(NULL, 0, secureServiceType);
+ call_OnMessageReceived(NULL, 0, kSecureServiceType);
}
/*
* Shall send InternallError on null data recieved
@@ -340,7 +347,7 @@ TEST_F(SecurityManagerTest, GetWrongJSONSize) {
uint32_t connection_id = 0;
uint8_t session_id = 0;
// uint8_t protocol_version = 0;
- EXPECT_CALL(mock_session_observer, PairFromKey(key, _, _));
+ EXPECT_CALL(mock_session_observer, PairFromKey(kKey, _, _));
EXPECT_CALL(mock_session_observer,
ProtocolVersionUsed(connection_id, session_id, _))
.WillOnce(Return(true));
@@ -349,7 +356,7 @@ TEST_F(SecurityManagerTest, GetWrongJSONSize) {
mock_protocol_handler,
SendMessageToMobileApp(
InternalErrorWithErrId(SecurityManager::ERROR_INVALID_QUERY_SIZE),
- is_final));
+ kIsFinal));
SecurityQuery::QueryHeader header(SecurityQuery::REQUEST,
SecurityQuery::INVALID_QUERY_ID);
header.json_size = 0x0FFFFFFF;
@@ -365,7 +372,7 @@ TEST_F(SecurityManagerTest, GetInvalidQueryId) {
TestAsyncWaiter waiter;
uint32_t times = 0;
- EXPECT_CALL(mock_session_observer, PairFromKey(key, _, _))
+ EXPECT_CALL(mock_session_observer, PairFromKey(kKey, _, _))
.WillOnce(NotifyTestAsyncWaiter(&waiter));
times++;
EXPECT_CALL(mock_session_observer,
@@ -378,7 +385,7 @@ TEST_F(SecurityManagerTest, GetInvalidQueryId) {
mock_protocol_handler,
SendMessageToMobileApp(
InternalErrorWithErrId(SecurityManager::ERROR_INVALID_QUERY_ID),
- is_final)).WillOnce(NotifyTestAsyncWaiter(&waiter));
+ kIsFinal)).WillOnce(NotifyTestAsyncWaiter(&waiter));
times++;
const SecurityQuery::QueryHeader header(SecurityQuery::REQUEST,
SecurityQuery::INVALID_QUERY_ID);
@@ -395,10 +402,12 @@ TEST_F(SecurityManagerTest, CreateSSLContext_ServiceAlreadyProtected) {
SetMockCryptoManager();
// Return mock SSLContext
- EXPECT_CALL(mock_session_observer, GetSSLContext(key, kControl))
+ EXPECT_CALL(mock_session_observer, GetSSLContext(kKey, kControl))
.WillOnce(Return(&mock_ssl_context_new));
- const SSLContext* result = security_manager_->CreateSSLContext(key);
+ const SSLContext* result = security_manager_->CreateSSLContext(
+ kKey,
+ security_manager::SecurityManager::ContextCreationStrategy::kUseExisting);
EXPECT_EQ(&mock_ssl_context_new, result);
}
/*
@@ -410,21 +419,23 @@ TEST_F(SecurityManagerTest, CreateSSLContext_ErrorCreateSSL) {
uint32_t connection_id = 0;
uint8_t session_id = 0;
// uint8_t protocol_version = 0;
- EXPECT_CALL(mock_session_observer, PairFromKey(key, _, _));
+ EXPECT_CALL(mock_session_observer, PairFromKey(kKey, _, _));
EXPECT_CALL(mock_session_observer,
ProtocolVersionUsed(connection_id, session_id, _))
.WillOnce(Return(true));
EXPECT_CALL(
mock_protocol_handler,
SendMessageToMobileApp(
- InternalErrorWithErrId(SecurityManager::ERROR_INTERNAL), is_final));
+ InternalErrorWithErrId(SecurityManager::ERROR_INTERNAL), kIsFinal));
// Emulate SessionObserver and CryptoManager result
- EXPECT_CALL(mock_session_observer, GetSSLContext(key, kControl))
+ EXPECT_CALL(mock_session_observer, GetSSLContext(kKey, kControl))
.WillOnce(ReturnNull());
EXPECT_CALL(mock_crypto_manager, CreateSSLContext()).WillOnce(ReturnNull());
- const SSLContext* result = security_manager_->CreateSSLContext(key);
+ const SSLContext* result = security_manager_->CreateSSLContext(
+ kKey,
+ security_manager::SecurityManager::ContextCreationStrategy::kUseExisting);
EXPECT_EQ(NULL, result);
}
/*
@@ -437,7 +448,7 @@ TEST_F(SecurityManagerTest, CreateSSLContext_SetSSLContextError) {
uint32_t connection_id = 0;
uint8_t session_id = 0;
// uint8_t protocol_version = 0;
- EXPECT_CALL(mock_session_observer, PairFromKey(key, _, _));
+ EXPECT_CALL(mock_session_observer, PairFromKey(kKey, _, _));
EXPECT_CALL(mock_session_observer,
ProtocolVersionUsed(connection_id, session_id, _))
.WillOnce(Return(true));
@@ -446,18 +457,20 @@ TEST_F(SecurityManagerTest, CreateSSLContext_SetSSLContextError) {
mock_protocol_handler,
SendMessageToMobileApp(
InternalErrorWithErrId(SecurityManager::ERROR_UNKNOWN_INTERNAL_ERROR),
- is_final));
+ kIsFinal));
// Emulate SessionObserver and CryptoManager result
- EXPECT_CALL(mock_session_observer, GetSSLContext(key, kControl))
+ EXPECT_CALL(mock_session_observer, GetSSLContext(kKey, kControl))
.WillOnce(ReturnNull());
EXPECT_CALL(mock_crypto_manager, CreateSSLContext())
.WillOnce(Return(&mock_ssl_context_new));
EXPECT_CALL(mock_crypto_manager, ReleaseSSLContext(&mock_ssl_context_new));
- EXPECT_CALL(mock_session_observer, SetSSLContext(key, &mock_ssl_context_new))
+ EXPECT_CALL(mock_session_observer, SetSSLContext(kKey, &mock_ssl_context_new))
.WillOnce(Return(SecurityManager::ERROR_UNKNOWN_INTERNAL_ERROR));
- const SSLContext* result = security_manager_->CreateSSLContext(key);
+ const SSLContext* result = security_manager_->CreateSSLContext(
+ kKey,
+ security_manager::SecurityManager::ContextCreationStrategy::kUseExisting);
EXPECT_EQ(NULL, result);
}
/*
@@ -469,17 +482,17 @@ TEST_F(SecurityManagerTest, CreateSSLContext_Success) {
// Expect no notifying listeners - it will be done after handshake
// Emulate SessionObserver and CryptoManager result
- EXPECT_CALL(mock_session_observer, GetSSLContext(key, kControl))
- .WillOnce(ReturnNull())
- .
- // additional check for debug code
- WillOnce(Return(&mock_ssl_context_exists));
+ EXPECT_CALL(mock_session_observer, GetSSLContext(kKey, kControl))
+ .WillOnce(Return(&mock_ssl_context_exists));
EXPECT_CALL(mock_crypto_manager, CreateSSLContext())
.WillOnce(Return(&mock_ssl_context_new));
- EXPECT_CALL(mock_session_observer, SetSSLContext(key, &mock_ssl_context_new))
+ EXPECT_CALL(mock_session_observer, SetSSLContext(kKey, &mock_ssl_context_new))
.WillOnce(Return(SecurityManager::ERROR_SUCCESS));
- const SSLContext* result = security_manager_->CreateSSLContext(key);
+ const SSLContext* result = security_manager_->CreateSSLContext(
+ kKey,
+ security_manager::SecurityManager::ContextCreationStrategy::
+ kForceRecreation);
EXPECT_EQ(&mock_ssl_context_new, result);
}
/*
@@ -490,7 +503,7 @@ TEST_F(SecurityManagerTest, StartHandshake_ServiceStillUnprotected) {
uint32_t connection_id = 0;
uint8_t session_id = 0;
// uint8_t protocol_version = 0;
- EXPECT_CALL(mock_session_observer, PairFromKey(key, _, _));
+ EXPECT_CALL(mock_session_observer, PairFromKey(kKey, _, _));
EXPECT_CALL(mock_session_observer,
ProtocolVersionUsed(connection_id, session_id, _))
.WillOnce(Return(true));
@@ -498,17 +511,17 @@ TEST_F(SecurityManagerTest, StartHandshake_ServiceStillUnprotected) {
EXPECT_CALL(
mock_protocol_handler,
SendMessageToMobileApp(
- InternalErrorWithErrId(SecurityManager::ERROR_INTERNAL), is_final));
+ InternalErrorWithErrId(SecurityManager::ERROR_INTERNAL), kIsFinal));
// Expect notifying listeners (unsuccess)
EXPECT_CALL(*mock_sm_listener,
- OnHandshakeDone(key, SSLContext::Handshake_Result_Fail))
+ OnHandshakeDone(kKey, SSLContext::Handshake_Result_Fail))
.WillOnce(Return(true));
// Emulate SessionObserver result
- EXPECT_CALL(mock_session_observer, GetSSLContext(key, kControl))
+ EXPECT_CALL(mock_session_observer, GetSSLContext(kKey, kControl))
.WillOnce(ReturnNull());
- security_manager_->StartHandshake(key);
+ security_manager_->StartHandshake(kKey);
// Listener was destroyed after OnHandshakeDone call
mock_sm_listener.release();
@@ -521,109 +534,27 @@ TEST_F(SecurityManagerTest, StartHandshake_SSLInternalError) {
uint32_t connection_id = 0;
uint8_t session_id = 0;
- // uint8_t protocol_version = 0;
- EXPECT_CALL(mock_session_observer, PairFromKey(key, _, _));
- EXPECT_CALL(mock_session_observer, GetHandshakeContext(key))
- .WillOnce(Return(SSLContext::HandshakeContext()));
+
+ EXPECT_CALL(mock_session_observer, PairFromKey(kKey, _, _));
EXPECT_CALL(mock_session_observer,
ProtocolVersionUsed(connection_id, session_id, _))
.WillOnce(Return(true));
-
+ // Expect notifying listeners (unsuccess)
+ EXPECT_CALL(*mock_sm_listener,
+ OnHandshakeDone(kKey, SSLContext::Handshake_Result_Fail))
+ .WillOnce(Return(true));
+ EXPECT_CALL(mock_session_observer, GetSSLContext(kKey, kControl))
+ .WillOnce(ReturnNull());
// Expect InternalError with ERROR_ID
EXPECT_CALL(
mock_protocol_handler,
SendMessageToMobileApp(
- InternalErrorWithErrId(SecurityManager::ERROR_INTERNAL), is_final));
- // Expect notifying listeners (unsuccess)
- EXPECT_CALL(*mock_sm_listener,
- OnHandshakeDone(key, SSLContext::Handshake_Result_Fail))
- .WillOnce(Return(true));
+ InternalErrorWithErrId(SecurityManager::ERROR_INTERNAL), kIsFinal));
- // Emulate SessionObserver result
- EXPECT_CALL(mock_session_observer, GetSSLContext(key, kControl))
- .WillOnce(Return(&mock_ssl_context_exists));
- EXPECT_CALL(mock_ssl_context_exists, IsInitCompleted())
- .WillOnce(Return(false));
- EXPECT_CALL(mock_ssl_context_exists, SetHandshakeContext(_));
- EXPECT_CALL(mock_ssl_context_exists, StartHandshake(_, _))
- .WillOnce(DoAll(SetArgPointee<0>(handshake_data_out_pointer),
- SetArgPointee<1>(handshake_data_out_size),
- Return(SSLContext::Handshake_Result_Fail)));
-
- security_manager_->StartHandshake(key);
-
- // Listener was destroyed after OnHandshakeDone call
+ security_manager_->StartHandshake(kKey);
mock_sm_listener.release();
}
-/*
- * Shall send data on call StartHandshake
- */
-TEST_F(SecurityManagerTest, StartHandshake_SSLInitIsNotComplete) {
- SetMockCryptoManager();
- uint32_t connection_id = 0;
- uint8_t session_id = 0;
- // uint8_t protocol_version = 0;
- EXPECT_CALL(mock_session_observer, PairFromKey(key, _, _));
- EXPECT_CALL(mock_session_observer, GetHandshakeContext(key))
- .Times(3)
- .WillRepeatedly(Return(SSLContext::HandshakeContext()));
- EXPECT_CALL(mock_session_observer,
- ProtocolVersionUsed(connection_id, session_id, _))
- .WillOnce(Return(true));
-
- // Expect send one message (with correct pointer and size data)
- EXPECT_CALL(mock_protocol_handler, SendMessageToMobileApp(_, is_final));
-
- // Return mock SSLContext
- EXPECT_CALL(mock_session_observer, GetSSLContext(key, kControl))
- .Times(3)
- .WillRepeatedly(Return(&mock_ssl_context_exists));
- // Expect initialization check on each call StartHandshake
- EXPECT_CALL(mock_ssl_context_exists, IsInitCompleted())
- .Times(3)
- .WillRepeatedly(Return(false));
- EXPECT_CALL(mock_ssl_context_exists, SetHandshakeContext(_)).Times(3);
-
- // Emulate SSLContext::StartHandshake with different parameters
- // Only on both correct - data and size shall be send message to mobile app
- EXPECT_CALL(mock_ssl_context_exists, StartHandshake(_, _))
- .WillOnce(DoAll(SetArgPointee<0>(handshake_data_out_pointer),
- SetArgPointee<1>(0),
- Return(SSLContext::Handshake_Result_Success)))
- .WillOnce(DoAll(SetArgPointee<0>((uint8_t*)NULL),
- SetArgPointee<1>(handshake_data_out_size),
- Return(SSLContext::Handshake_Result_Success)))
- .WillOnce(DoAll(SetArgPointee<0>(handshake_data_out_pointer),
- SetArgPointee<1>(handshake_data_out_size),
- Return(SSLContext::Handshake_Result_Success)));
- security_manager_->StartHandshake(key);
- security_manager_->StartHandshake(key);
- security_manager_->StartHandshake(key);
-}
-/*
- * Shall notify listeners on call StartHandshake after SSLContext initialization
- * complete
- */
-TEST_F(SecurityManagerTest, StartHandshake_SSLInitIsComplete) {
- SetMockCryptoManager();
- // Expect no message send
- // Expect notifying listeners (success)
- EXPECT_CALL(*mock_sm_listener,
- OnHandshakeDone(key, SSLContext::Handshake_Result_Success))
- .WillOnce(Return(true));
-
- // Emulate SessionObserver result
- EXPECT_CALL(mock_session_observer, GetSSLContext(key, kControl))
- .WillOnce(Return(&mock_ssl_context_exists));
- EXPECT_CALL(mock_ssl_context_exists, IsInitCompleted())
- .WillOnce(Return(true));
-
- security_manager_->StartHandshake(key);
-
- // Listener was destroyed after OnHandshakeDone call
- mock_sm_listener.release();
-}
/*
* Shall send InternallError on
* getting SEND_HANDSHAKE_DATA with NULL data
@@ -634,7 +565,7 @@ TEST_F(SecurityManagerTest, ProccessHandshakeData_WrongDataSize) {
uint8_t session_id = 0;
TestAsyncWaiter waiter;
- EXPECT_CALL(mock_session_observer, PairFromKey(key, _, _));
+ EXPECT_CALL(mock_session_observer, PairFromKey(kKey, _, _));
EXPECT_CALL(mock_session_observer,
ProtocolVersionUsed(connection_id, session_id, _))
.WillOnce(Return(true));
@@ -644,7 +575,7 @@ TEST_F(SecurityManagerTest, ProccessHandshakeData_WrongDataSize) {
mock_protocol_handler,
SendMessageToMobileApp(
InternalErrorWithErrId(SecurityManager::ERROR_INVALID_QUERY_SIZE),
- is_final)).WillOnce(NotifyTestAsyncWaiter(&waiter));
+ kIsFinal)).WillOnce(NotifyTestAsyncWaiter(&waiter));
EmulateMobileMessageHandshake(NULL, 0);
@@ -664,7 +595,7 @@ TEST_F(SecurityManagerTest,
TestAsyncWaiter waiter;
uint32_t times = 0;
- EXPECT_CALL(mock_session_observer, PairFromKey(key, _, _))
+ EXPECT_CALL(mock_session_observer, PairFromKey(kKey, _, _))
.WillOnce(NotifyTestAsyncWaiter(&waiter));
times++;
EXPECT_CALL(mock_session_observer,
@@ -675,17 +606,17 @@ TEST_F(SecurityManagerTest,
mock_protocol_handler,
SendMessageToMobileApp(
InternalErrorWithErrId(SecurityManager::ERROR_SERVICE_NOT_PROTECTED),
- is_final)).WillOnce(NotifyTestAsyncWaiter(&waiter));
+ kIsFinal)).WillOnce(NotifyTestAsyncWaiter(&waiter));
times++;
// Expect notifying listeners (unsuccess)
EXPECT_CALL(*mock_sm_listener,
- OnHandshakeDone(key, SSLContext::Handshake_Result_Fail))
+ OnHandshakeDone(kKey, SSLContext::Handshake_Result_Fail))
.WillOnce(DoAll(NotifyTestAsyncWaiter(&waiter), Return(true)));
times++;
// Emulate SessionObserver result
- EXPECT_CALL(mock_session_observer, GetSSLContext(key, kControl))
+ EXPECT_CALL(mock_session_observer, GetSSLContext(kKey, kControl))
.WillOnce(DoAll(NotifyTestAsyncWaiter(&waiter), ReturnNull()));
times++;
@@ -713,7 +644,7 @@ TEST_F(SecurityManagerTest, ProccessHandshakeData_InvalidData) {
TestAsyncWaiter waiter;
uint32_t times = 0;
- EXPECT_CALL(mock_session_observer, PairFromKey(key, _, _))
+ EXPECT_CALL(mock_session_observer, PairFromKey(kKey, _, _))
.Times(handshake_emulates)
.WillRepeatedly(NotifyTestAsyncWaiter(&waiter));
times += handshake_emulates;
@@ -728,18 +659,18 @@ TEST_F(SecurityManagerTest, ProccessHandshakeData_InvalidData) {
mock_protocol_handler,
SendMessageToMobileApp(
InternalErrorWithErrId(SecurityManager::ERROR_SSL_INVALID_DATA),
- is_final))
+ kIsFinal))
.Times(handshake_emulates)
.WillRepeatedly(NotifyTestAsyncWaiter(&waiter));
times += handshake_emulates;
// Expect notifying listeners (unsuccess)
EXPECT_CALL(*mock_sm_listener,
- OnHandshakeDone(key, SSLContext::Handshake_Result_Fail))
+ OnHandshakeDone(kKey, SSLContext::Handshake_Result_Fail))
.WillOnce(DoAll(NotifyTestAsyncWaiter(&waiter), Return(true)));
times++;
// Emulate SessionObserver and CryptoManager result
- EXPECT_CALL(mock_session_observer, GetSSLContext(key, kControl))
+ EXPECT_CALL(mock_session_observer, GetSSLContext(kKey, kControl))
.Times(handshake_emulates)
.WillRepeatedly(Return(&mock_ssl_context_exists));
@@ -794,7 +725,7 @@ TEST_F(SecurityManagerTest, ProccessHandshakeData_Answer) {
TestAsyncWaiter waiter;
uint32_t times = 0;
- EXPECT_CALL(mock_session_observer, PairFromKey(key, _, _))
+ EXPECT_CALL(mock_session_observer, PairFromKey(kKey, _, _))
.Times(handshake_emulates)
.WillRepeatedly(NotifyTestAsyncWaiter(&waiter));
times += handshake_emulates;
@@ -808,14 +739,14 @@ TEST_F(SecurityManagerTest, ProccessHandshakeData_Answer) {
const size_t raw_message_size = 15;
EXPECT_CALL(
mock_protocol_handler,
- SendMessageToMobileApp(RawMessageEqSize(raw_message_size), is_final))
+ SendMessageToMobileApp(RawMessageEqSize(raw_message_size), kIsFinal))
.Times(handshake_emulates)
.WillRepeatedly(NotifyTestAsyncWaiter(&waiter));
times += handshake_emulates;
// Expect notifying listeners (unsuccess)
EXPECT_CALL(*mock_sm_listener,
- OnHandshakeDone(key, SSLContext::Handshake_Result_Fail))
+ OnHandshakeDone(kKey, SSLContext::Handshake_Result_Fail))
.WillOnce(DoAll(NotifyTestAsyncWaiter(&waiter), Return(true)));
times++;
@@ -824,7 +755,7 @@ TEST_F(SecurityManagerTest, ProccessHandshakeData_Answer) {
.Times(handshake_emulates)
.WillRepeatedly(DoAll(NotifyTestAsyncWaiter(&waiter), Return(false)));
times += handshake_emulates;
- EXPECT_CALL(mock_session_observer, GetSSLContext(key, kControl))
+ EXPECT_CALL(mock_session_observer, GetSSLContext(kKey, kControl))
.Times(handshake_emulates)
.WillRepeatedly(DoAll(NotifyTestAsyncWaiter(&waiter),
Return(&mock_ssl_context_exists)));
@@ -870,12 +801,12 @@ TEST_F(SecurityManagerTest, ProccessHandshakeData_HandshakeFinished) {
// Expect no errors
// Expect notifying listeners (success)
EXPECT_CALL(*mock_sm_listener,
- OnHandshakeDone(key, SSLContext::Handshake_Result_Success))
+ OnHandshakeDone(kKey, SSLContext::Handshake_Result_Success))
.WillOnce(DoAll(NotifyTestAsyncWaiter(&waiter), Return(true)));
times++;
// Emulate SessionObserver and CryptoManager result
- EXPECT_CALL(mock_session_observer, GetSSLContext(key, kControl))
+ EXPECT_CALL(mock_session_observer, GetSSLContext(kKey, kControl))
.Times(handshake_emulates)
.WillRepeatedly(DoAll(NotifyTestAsyncWaiter(&waiter),
Return(&mock_ssl_context_exists)));
@@ -928,14 +859,14 @@ TEST_F(SecurityManagerTest, ProccessHandshakeData_HandshakeFinished) {
uint32_t connection_id = 0;
uint8_t session_id = 0;
// uint8_t protocol_version = 0;
- EXPECT_CALL(mock_session_observer, PairFromKey(key, _, _)).Times(2);
+ EXPECT_CALL(mock_session_observer, PairFromKey(kKey, _, _)).Times(2);
EXPECT_CALL(mock_session_observer,
ProtocolVersionUsed(connection_id, session_id, _))
.Times(2)
.WillRepeatedly(DoAll(NotifyTestAsyncWaiter(&waiter), Return(true)));
times += 2; // matches to the number above
- EXPECT_CALL(mock_protocol_handler, SendMessageToMobileApp(_, is_final))
+ EXPECT_CALL(mock_protocol_handler, SendMessageToMobileApp(_, kIsFinal))
.Times(2)
.WillRepeatedly(NotifyTestAsyncWaiter(&waiter));
times += 2; // matches to the number above
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 dc335c8da2..83ffa33b44 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 =
@@ -66,36 +70,42 @@ const std::string server_expired_cert_file =
const bool verify_peer = true;
const bool skip_peer_verification = false;
-const size_t updates_before_hour = 24;
-
} // namespace
+struct Protocol {
+ security_manager::Protocol server_protocol;
+ security_manager::Protocol client_protocol;
+
+ Protocol(security_manager::Protocol s_protocol,
+ security_manager::Protocol c_protocol)
+ : server_protocol(s_protocol), client_protocol(c_protocol) {}
+};
-class SSLHandshakeTest : public testing::Test {
+class SSLHandshakeTest : public testing::TestWithParam<Protocol> {
protected:
void SetUp() OVERRIDE {
- mock_server_manager_settings = new testing::NiceMock<
+ mock_server_manager_settings_ = new testing::NiceMock<
security_manager_test::MockCryptoManagerSettings>();
- server_manager = new security_manager::CryptoManagerImpl(
+ server_manager_ = new security_manager::CryptoManagerImpl(
utils::SharedPtr<security_manager::CryptoManagerSettings>(
- mock_server_manager_settings));
- ASSERT_TRUE(server_manager);
- mock_client_manager_settings = new testing::NiceMock<
+ mock_server_manager_settings_));
+ ASSERT_TRUE(server_manager_);
+ mock_client_manager_settings_ = new testing::NiceMock<
security_manager_test::MockCryptoManagerSettings>();
- client_manager = new security_manager::CryptoManagerImpl(
+ client_manager_ = new security_manager::CryptoManagerImpl(
utils::SharedPtr<security_manager::CryptoManagerSettings>(
- mock_client_manager_settings));
- ASSERT_TRUE(client_manager);
- server_ctx = NULL;
- client_ctx = NULL;
+ mock_client_manager_settings_));
+ ASSERT_TRUE(client_manager_);
+ server_ctx_ = NULL;
+ client_ctx_ = NULL;
}
void TearDown() OVERRIDE {
- server_manager->ReleaseSSLContext(server_ctx);
- delete server_manager;
- client_manager->ReleaseSSLContext(client_ctx);
- delete client_manager;
+ server_manager_->ReleaseSSLContext(server_ctx_);
+ delete server_manager_;
+ client_manager_->ReleaseSSLContext(client_ctx_);
+ delete client_manager_;
}
void SetServerInitialValues(const security_manager::Protocol protocol,
@@ -106,18 +116,25 @@ class SSLHandshakeTest : public testing::Test {
server_certificate_ = cert;
server_ciphers_list_ = server_ciphers_list;
server_ca_certificate_path_ = ca_certificate_path;
-
- ON_CALL(*mock_server_manager_settings, security_manager_mode())
+ ON_CALL(*mock_server_manager_settings_, force_unprotected_service())
+ .WillByDefault(ReturnRef(forced_unprotected_service_));
+ ON_CALL(*mock_server_manager_settings_, force_protected_service())
+ .WillByDefault(ReturnRef(forced_protected_service_));
+ ON_CALL(*mock_server_manager_settings_, security_manager_mode())
.WillByDefault(Return(security_manager::SERVER));
- ON_CALL(*mock_server_manager_settings, security_manager_protocol_name())
+ ON_CALL(*mock_server_manager_settings_, security_manager_protocol_name())
.WillByDefault(Return(protocol));
- ON_CALL(*mock_server_manager_settings, certificate_data())
+ ON_CALL(*mock_server_manager_settings_, certificate_data())
.WillByDefault(ReturnRef(server_certificate_));
- ON_CALL(*mock_server_manager_settings, ciphers_list())
+ ON_CALL(*mock_server_manager_settings_, ciphers_list())
.WillByDefault(ReturnRef(server_ciphers_list_));
- ON_CALL(*mock_server_manager_settings, ca_cert_path())
+ ON_CALL(*mock_server_manager_settings_, ca_cert_path())
.WillByDefault(ReturnRef(server_ca_certificate_path_));
- ON_CALL(*mock_server_manager_settings, verify_peer())
+ 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));
}
void SetClientInitialValues(const security_manager::Protocol protocol,
@@ -129,17 +146,25 @@ class SSLHandshakeTest : public testing::Test {
client_ciphers_list_ = client_ciphers_list;
client_ca_certificate_path_ = ca_certificate_path;
- ON_CALL(*mock_client_manager_settings, security_manager_mode())
+ ON_CALL(*mock_client_manager_settings_, force_unprotected_service())
+ .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_, security_manager_mode())
.WillByDefault(Return(security_manager::CLIENT));
- ON_CALL(*mock_client_manager_settings, security_manager_protocol_name())
+ ON_CALL(*mock_client_manager_settings_, security_manager_protocol_name())
.WillByDefault(Return(protocol));
- ON_CALL(*mock_client_manager_settings, certificate_data())
+ ON_CALL(*mock_client_manager_settings_, certificate_data())
.WillByDefault(ReturnRef(client_certificate_));
- ON_CALL(*mock_client_manager_settings, ciphers_list())
+ ON_CALL(*mock_client_manager_settings_, ciphers_list())
.WillByDefault(ReturnRef(client_ciphers_list_));
- ON_CALL(*mock_client_manager_settings, ca_cert_path())
+ ON_CALL(*mock_client_manager_settings_, ca_cert_path())
.WillByDefault(ReturnRef(client_ca_certificate_path_));
- ON_CALL(*mock_client_manager_settings, verify_peer())
+ 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));
}
@@ -156,19 +181,19 @@ class SSLHandshakeTest : public testing::Test {
cert.close();
SetServerInitialValues(
protocol, ss.str(), ciphers_list, verify_peer, ca_certificate_path);
- const bool initialized = server_manager->Init();
+ const bool initialized = server_manager_->Init();
if (!initialized) {
return false;
}
- server_ctx = server_manager->CreateSSLContext();
+ server_ctx_ = server_manager_->CreateSSLContext();
- if (!server_ctx) {
+ if (!server_ctx_) {
return false;
}
- server_ctx->SetHandshakeContext(
+ server_ctx_->SetHandshakeContext(
security_manager::SSLContext::HandshakeContext(
custom_str::CustomString("SPT"),
custom_str::CustomString("client")));
@@ -192,17 +217,17 @@ class SSLHandshakeTest : public testing::Test {
ciphers_list,
verify_peer,
ca_certificate_path);
- const bool initialized = client_manager->Init();
+ const bool initialized = client_manager_->Init();
if (!initialized) {
return false;
}
- client_ctx = client_manager->CreateSSLContext();
- if (!client_ctx) {
+ client_ctx_ = client_manager_->CreateSSLContext();
+ if (!client_ctx_) {
return false;
}
- client_ctx->SetHandshakeContext(
+ client_ctx_->SetHandshakeContext(
security_manager::SSLContext::HandshakeContext(
custom_str::CustomString("SPT"),
custom_str::CustomString("server")));
@@ -211,17 +236,17 @@ class SSLHandshakeTest : public testing::Test {
}
void ResetConnections() {
- ASSERT_NO_THROW(server_ctx->ResetConnection());
- ASSERT_NO_THROW(client_ctx->ResetConnection());
+ ASSERT_NO_THROW(server_ctx_->ResetConnection());
+ ASSERT_NO_THROW(client_ctx_->ResetConnection());
}
void StartHandshake() {
using security_manager::SSLContext;
ASSERT_EQ(SSLContext::Handshake_Result_Success,
- client_ctx->StartHandshake(&client_buf, &client_buf_len));
- ASSERT_FALSE(client_buf == NULL);
- ASSERT_GT(client_buf_len, 0u);
+ client_ctx_->StartHandshake(&client_buf_, &client_buf_len_));
+ ASSERT_FALSE(client_buf_ == NULL);
+ ASSERT_GT(client_buf_len_, 0u);
}
void HandshakeProcedure_Success() {
@@ -229,23 +254,25 @@ class SSLHandshakeTest : public testing::Test {
StartHandshake();
while (true) {
- ASSERT_EQ(SSLContext::Handshake_Result_Success,
- server_ctx->DoHandshakeStep(
- client_buf, client_buf_len, &server_buf, &server_buf_len))
+ ASSERT_EQ(
+ SSLContext::Handshake_Result_Success,
+ server_ctx_->DoHandshakeStep(
+ client_buf_, client_buf_len_, &server_buf_, &server_buf_len_))
<< ERR_reason_error_string(ERR_get_error());
- ASSERT_FALSE(server_buf == NULL);
- ASSERT_GT(server_buf_len, 0u);
+ ASSERT_FALSE(server_buf_ == NULL);
+ ASSERT_GT(server_buf_len_, 0u);
- ASSERT_EQ(SSLContext::Handshake_Result_Success,
- client_ctx->DoHandshakeStep(
- server_buf, server_buf_len, &client_buf, &client_buf_len))
+ ASSERT_EQ(
+ SSLContext::Handshake_Result_Success,
+ client_ctx_->DoHandshakeStep(
+ server_buf_, server_buf_len_, &client_buf_, &client_buf_len_))
<< ERR_reason_error_string(ERR_get_error());
- if (server_ctx->IsInitCompleted()) {
+ if (server_ctx_->IsInitCompleted()) {
break;
}
- ASSERT_FALSE(client_buf == NULL);
- ASSERT_GT(client_buf_len, 0u);
+ ASSERT_FALSE(client_buf_ == NULL);
+ ASSERT_GT(client_buf_len_, 0u);
}
}
@@ -255,9 +282,9 @@ class SSLHandshakeTest : public testing::Test {
StartHandshake();
while (true) {
- const SSLContext::HandshakeResult result = server_ctx->DoHandshakeStep(
- client_buf, client_buf_len, &server_buf, &server_buf_len);
- ASSERT_FALSE(server_ctx->IsInitCompleted())
+ const SSLContext::HandshakeResult result = server_ctx_->DoHandshakeStep(
+ client_buf_, client_buf_len_, &server_buf_, &server_buf_len_);
+ ASSERT_FALSE(server_ctx_->IsInitCompleted())
<< "Expected server side handshake fail";
// First few handshake will be successful
@@ -265,18 +292,19 @@ class SSLHandshakeTest : public testing::Test {
// Test successfully passed with handshake fail
return;
}
- ASSERT_FALSE(server_buf == NULL);
- ASSERT_GT(server_buf_len, 0u);
+ ASSERT_FALSE(server_buf_ == NULL);
+ ASSERT_GT(server_buf_len_, 0u);
- ASSERT_EQ(SSLContext::Handshake_Result_Success,
- client_ctx->DoHandshakeStep(
- server_buf, server_buf_len, &client_buf, &client_buf_len))
+ ASSERT_EQ(
+ SSLContext::Handshake_Result_Success,
+ client_ctx_->DoHandshakeStep(
+ server_buf_, server_buf_len_, &client_buf_, &client_buf_len_))
<< ERR_reason_error_string(ERR_get_error());
- ASSERT_FALSE(client_ctx->IsInitCompleted())
+ ASSERT_FALSE(client_ctx_->IsInitCompleted())
<< "Expected server side handshake fail";
- ASSERT_FALSE(client_buf == NULL);
- ASSERT_GT(client_buf_len, 0u);
+ ASSERT_FALSE(client_buf_ == NULL);
+ ASSERT_GT(client_buf_len_, 0u);
}
FAIL() << "Expected server side handshake fail";
}
@@ -288,17 +316,18 @@ class SSLHandshakeTest : public testing::Test {
StartHandshake();
while (true) {
- ASSERT_EQ(SSLContext::Handshake_Result_Success,
- server_ctx->DoHandshakeStep(
- client_buf, client_buf_len, &server_buf, &server_buf_len))
+ ASSERT_EQ(
+ SSLContext::Handshake_Result_Success,
+ server_ctx_->DoHandshakeStep(
+ client_buf_, client_buf_len_, &server_buf_, &server_buf_len_))
<< ERR_reason_error_string(ERR_get_error());
- ASSERT_FALSE(server_buf == NULL);
- ASSERT_GT(server_buf_len, 0u);
+ ASSERT_FALSE(server_buf_ == NULL);
+ ASSERT_GT(server_buf_len_, 0u);
- const SSLContext::HandshakeResult result = client_ctx->DoHandshakeStep(
- server_buf, server_buf_len, &client_buf, &client_buf_len);
- ASSERT_FALSE(client_ctx->IsInitCompleted())
+ const SSLContext::HandshakeResult result = client_ctx_->DoHandshakeStep(
+ server_buf_, server_buf_len_, &client_buf_, &client_buf_len_);
+ ASSERT_FALSE(client_ctx_->IsInitCompleted())
<< "Expected client side handshake fail";
// First few handsahke will be successful
@@ -308,25 +337,25 @@ class SSLHandshakeTest : public testing::Test {
return;
}
- ASSERT_FALSE(client_buf == NULL);
- ASSERT_GT(client_buf_len, 0u);
+ ASSERT_FALSE(client_buf_ == NULL);
+ ASSERT_GT(client_buf_len_, 0u);
}
FAIL() << "Expected client side handshake fail";
}
- security_manager::CryptoManager* server_manager;
- security_manager::CryptoManager* client_manager;
- security_manager::SSLContext* server_ctx;
- security_manager::SSLContext* client_ctx;
+ security_manager::CryptoManager* server_manager_;
+ security_manager::CryptoManager* client_manager_;
+ security_manager::SSLContext* server_ctx_;
+ security_manager::SSLContext* client_ctx_;
testing::NiceMock<security_manager_test::MockCryptoManagerSettings>*
- mock_server_manager_settings;
+ mock_server_manager_settings_;
testing::NiceMock<security_manager_test::MockCryptoManagerSettings>*
- mock_client_manager_settings;
+ mock_client_manager_settings_;
- const uint8_t* server_buf;
- const uint8_t* client_buf;
- size_t server_buf_len;
- size_t client_buf_len;
+ const uint8_t* server_buf_;
+ const uint8_t* client_buf_;
+ size_t server_buf_len_;
+ size_t client_buf_len_;
std::string server_certificate_;
std::string server_ciphers_list_;
@@ -335,188 +364,175 @@ class SSLHandshakeTest : public testing::Test {
std::string client_certificate_;
std::string client_ciphers_list_;
std::string client_ca_certificate_path_;
+
+ const std::vector<int> forced_protected_service_;
+ const std::vector<int> forced_unprotected_service_;
};
-TEST_F(SSLHandshakeTest, NoVerification) {
- ASSERT_TRUE(InitServerManagers(security_manager::TLSv1_2,
+INSTANTIATE_TEST_CASE_P(
+ CorrectProtocol,
+ SSLHandshakeTest,
+ ::testing::Values(
+ Protocol(security_manager::TLSv1, security_manager::TLSv1),
+ Protocol(security_manager::TLSv1_1, security_manager::TLSv1_1),
+ Protocol(security_manager::TLSv1_2, security_manager::TLSv1_2),
+ Protocol(security_manager::DTLSv1, security_manager::DTLSv1)));
+
+TEST_P(SSLHandshakeTest, NoVerification) {
+ ASSERT_TRUE(InitServerManagers(GetParam().server_protocol,
server_certificate,
"ALL",
skip_peer_verification,
""))
- << server_manager->LastError();
- ASSERT_TRUE(InitClientManagers(security_manager::TLSv1_2,
+ << server_manager_->LastError();
+
+ ASSERT_TRUE(InitClientManagers(GetParam().client_protocol,
client_certificate,
"ALL",
skip_peer_verification,
""))
- << client_manager->LastError();
+ << client_manager_->LastError();
GTEST_TRACE(HandshakeProcedure_Success());
}
-TEST_F(SSLHandshakeTest, CAVerification_ServerSide) {
- ASSERT_TRUE(InitServerManagers(security_manager::TLSv1_2,
+TEST_P(SSLHandshakeTest, CAVerification_ServerSide) {
+ ASSERT_TRUE(InitServerManagers(GetParam().server_protocol,
server_certificate,
"ALL",
verify_peer,
client_ca_cert_filename))
- << server_manager->LastError();
- ASSERT_TRUE(InitClientManagers(security_manager::TLSv1_2,
+ << server_manager_->LastError();
+ ASSERT_TRUE(InitClientManagers(GetParam().client_protocol,
client_certificate,
"ALL",
skip_peer_verification,
""))
- << client_manager->LastError();
+ << client_manager_->LastError();
GTEST_TRACE(HandshakeProcedure_Success());
}
-TEST_F(SSLHandshakeTest, CAVerification_ServerSide_NoCACertificate) {
+TEST_P(SSLHandshakeTest, CAVerification_ServerSide_NoCACertificate) {
ASSERT_TRUE(InitServerManagers(
- security_manager::TLSv1_2, "", "ALL", verify_peer, "unex"))
- << server_manager->LastError();
- ASSERT_TRUE(InitClientManagers(security_manager::TLSv1_2,
+ GetParam().server_protocol, "", "ALL", verify_peer, "unex"))
+ << server_manager_->LastError();
+ ASSERT_TRUE(InitClientManagers(GetParam().client_protocol,
client_certificate,
"ALL",
skip_peer_verification,
""))
- << client_manager->LastError();
+ << client_manager_->LastError();
GTEST_TRACE(HandshakeProcedure_ServerSideFail());
- ASSERT_TRUE(InitServerManagers(security_manager::TLSv1_2,
+ ASSERT_TRUE(InitServerManagers(GetParam().server_protocol,
server_certificate,
"ALL",
verify_peer,
client_ca_cert_filename))
- << server_manager->LastError();
+ << server_manager_->LastError();
GTEST_TRACE(ResetConnections());
GTEST_TRACE(HandshakeProcedure_Success());
}
-TEST_F(SSLHandshakeTest, CAVerification_ClientSide) {
- ASSERT_TRUE(InitServerManagers(security_manager::TLSv1_2,
- server_certificate,
- "ALL",
- verify_peer,
- client_ca_cert_filename))
- << server_manager->LastError();
- ASSERT_TRUE(InitClientManagers(security_manager::TLSv1_2,
- client_certificate,
- "ALL",
- verify_peer,
- server_ca_cert_filename))
- << client_manager->LastError();
-
- GTEST_TRACE(HandshakeProcedure_Success());
-}
-
-TEST_F(SSLHandshakeTest, CAVerification_ClientSide_NoCACertificate) {
- ASSERT_TRUE(InitServerManagers(security_manager::TLSv1_2,
+TEST_P(SSLHandshakeTest, CAVerification_ClientSide_NoCACertificate) {
+ ASSERT_TRUE(InitServerManagers(GetParam().server_protocol,
server_certificate,
"ALL",
skip_peer_verification,
""))
- << server_manager->LastError();
- ASSERT_TRUE(InitClientManagers(security_manager::TLSv1_2,
+ << server_manager_->LastError();
+ ASSERT_TRUE(InitClientManagers(GetParam().client_protocol,
"",
"ALL",
verify_peer,
"client_ca_cert_filename"))
- << client_manager->LastError();
+ << client_manager_->LastError();
GTEST_TRACE(HandshakeProcedure_ClientSideFail(
security_manager::SSLContext::Handshake_Result_Fail));
- ASSERT_TRUE(InitClientManagers(security_manager::TLSv1_2,
+ ASSERT_TRUE(InitClientManagers(GetParam().client_protocol,
client_certificate,
"ALL",
verify_peer,
server_ca_cert_filename))
- << client_manager->LastError();
+ << client_manager_->LastError();
GTEST_TRACE(ResetConnections());
GTEST_TRACE(HandshakeProcedure_Success());
}
-TEST_F(SSLHandshakeTest, CAVerification_BothSides) {
- ASSERT_TRUE(InitServerManagers(security_manager::TLSv1_2,
+TEST_P(SSLHandshakeTest, CAVerification_BothSides) {
+ ASSERT_TRUE(InitServerManagers(GetParam().server_protocol,
server_certificate,
"ALL",
verify_peer,
client_ca_cert_filename))
- << server_manager->LastError();
- ASSERT_TRUE(InitClientManagers(security_manager::TLSv1_2,
+ << server_manager_->LastError();
+ ASSERT_TRUE(InitClientManagers(GetParam().client_protocol,
client_certificate,
"ALL",
verify_peer,
server_ca_cert_filename))
- << client_manager->LastError();
+ << client_manager_->LastError();
GTEST_TRACE(HandshakeProcedure_Success());
}
-TEST_F(SSLHandshakeTest, UnsignedCert) {
- ASSERT_TRUE(InitServerManagers(security_manager::TLSv1_2,
+TEST_P(SSLHandshakeTest, UnsignedCert) {
+ ASSERT_TRUE(InitServerManagers(GetParam().server_protocol,
server_unsigned_cert_file,
"ALL",
skip_peer_verification,
""))
- << server_manager->LastError();
- ASSERT_TRUE(InitClientManagers(security_manager::TLSv1_2,
+ << server_manager_->LastError();
+ ASSERT_TRUE(InitClientManagers(GetParam().client_protocol,
client_certificate,
"ALL",
verify_peer,
client_ca_cert_filename))
- << client_manager->LastError();
+ << client_manager_->LastError();
GTEST_TRACE(HandshakeProcedure_ClientSideFail(
security_manager::SSLContext::Handshake_Result_CertNotSigned));
}
-TEST_F(SSLHandshakeTest, ExpiredCert) {
- ASSERT_TRUE(InitServerManagers(security_manager::TLSv1_2,
+TEST_P(SSLHandshakeTest, ExpiredCert) {
+ ASSERT_TRUE(InitServerManagers(GetParam().server_protocol,
server_expired_cert_file,
"ALL",
verify_peer,
client_ca_cert_filename))
- << server_manager->LastError();
- ASSERT_TRUE(InitClientManagers(security_manager::TLSv1_2,
+ << server_manager_->LastError();
+ ASSERT_TRUE(InitClientManagers(GetParam().client_protocol,
client_certificate,
"ALL",
verify_peer,
server_ca_cert_filename))
- << client_manager->LastError();
+ << client_manager_->LastError();
GTEST_TRACE(HandshakeProcedure_ClientSideFail(
security_manager::SSLContext::Handshake_Result_CertExpired));
}
-TEST_F(SSLHandshakeTest, AppNameAndAppIDInvalid) {
- ASSERT_TRUE(InitServerManagers(security_manager::TLSv1_2,
+TEST_P(SSLHandshakeTest, AppNameAndAppIDInvalid) {
+ ASSERT_TRUE(InitServerManagers(GetParam().server_protocol,
server_certificate,
"ALL",
verify_peer,
client_ca_cert_filename))
- << server_manager->LastError();
- ASSERT_TRUE(InitClientManagers(security_manager::TLSv1_2,
+ << server_manager_->LastError();
+ ASSERT_TRUE(InitClientManagers(GetParam().client_protocol,
client_certificate,
"ALL",
verify_peer,
server_ca_cert_filename))
- << client_manager->LastError();
+ << client_manager_->LastError();
- client_ctx->SetHandshakeContext(
- security_manager::SSLContext::HandshakeContext(
- custom_str::CustomString("server"),
- custom_str::CustomString("Wrong")));
-
- GTEST_TRACE(HandshakeProcedure_ClientSideFail(
- security_manager::SSLContext::Handshake_Result_AppNameMismatch));
-
- ResetConnections();
- client_ctx->SetHandshakeContext(
+ client_ctx_->SetHandshakeContext(
security_manager::SSLContext::HandshakeContext(
custom_str::CustomString("Wrong"),
custom_str::CustomString("server")));
@@ -525,19 +541,19 @@ TEST_F(SSLHandshakeTest, AppNameAndAppIDInvalid) {
security_manager::SSLContext::Handshake_Result_AppIDMismatch));
}
-TEST_F(SSLHandshakeTest, NoVerification_ResetConnection) {
- ASSERT_TRUE(InitServerManagers(security_manager::TLSv1_2,
+TEST_P(SSLHandshakeTest, NoVerification_ResetConnection) {
+ ASSERT_TRUE(InitServerManagers(GetParam().server_protocol,
server_certificate,
"ALL",
skip_peer_verification,
""))
- << server_manager->LastError();
- ASSERT_TRUE(InitClientManagers(security_manager::TLSv1_2,
+ << server_manager_->LastError();
+ ASSERT_TRUE(InitClientManagers(GetParam().client_protocol,
client_certificate,
"ALL",
skip_peer_verification,
""))
- << client_manager->LastError();
+ << client_manager_->LastError();
const int times = 100;
for (int i = 0; i < times; ++i) {
@@ -549,19 +565,19 @@ TEST_F(SSLHandshakeTest, NoVerification_ResetConnection) {
}
}
-TEST_F(SSLHandshakeTest, CAVerification_BothSides_ResetConnection) {
- ASSERT_TRUE(InitServerManagers(security_manager::TLSv1_2,
+TEST_P(SSLHandshakeTest, CAVerification_BothSides_ResetConnection) {
+ ASSERT_TRUE(InitServerManagers(GetParam().server_protocol,
server_certificate,
"ALL",
verify_peer,
client_ca_cert_filename))
- << server_manager->LastError();
- ASSERT_TRUE(InitClientManagers(security_manager::TLSv1_2,
+ << server_manager_->LastError();
+ ASSERT_TRUE(InitClientManagers(GetParam().client_protocol,
client_certificate,
"ALL",
skip_peer_verification,
server_ca_cert_filename))
- << client_manager->LastError();
+ << client_manager_->LastError();
const int times = 100;
for (int i = 0; i < times; ++i) {
@@ -572,7 +588,6 @@ TEST_F(SSLHandshakeTest, CAVerification_BothSides_ResetConnection) {
GTEST_TRACE(ResetConnections());
}
}
-
// TODO(EZamakhov): add fail tests -broken or not full ca certificate chain
} // namespace ssl_handshake_test
diff --git a/src/components/security_manager/test/ssl_context_test.cc b/src/components/security_manager/test/ssl_context_test.cc
index a77cd98b27..20e509ebc6 100644
--- a/src/components/security_manager/test/ssl_context_test.cc
+++ b/src/components/security_manager/test/ssl_context_test.cc
@@ -49,8 +49,11 @@ using ::testing::ReturnRef;
using ::testing::NiceMock;
namespace {
-const size_t kUpdatesBeforeHour = 24;
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";
@@ -70,19 +73,19 @@ namespace ssl_context_test {
namespace custom_str = utils::custom_string;
struct ProtocolAndCipher {
- security_manager::Protocol server_protocol;
- security_manager::Protocol client_protocol;
- std::string server_ciphers_list;
- std::string client_ciphers_list;
+ security_manager::Protocol server_protocol_;
+ security_manager::Protocol client_protocol_;
+ std::string server_ciphers_list_;
+ std::string client_ciphers_list_;
ProtocolAndCipher(security_manager::Protocol s_protocol,
security_manager::Protocol c_protocol,
std::string s_ciphers_list,
std::string c_ciphers_list)
- : server_protocol(s_protocol)
- , client_protocol(c_protocol)
- , server_ciphers_list(s_ciphers_list)
- , client_ciphers_list(c_ciphers_list) {}
+ : server_protocol_(s_protocol)
+ , client_protocol_(c_protocol)
+ , server_ciphers_list_(s_ciphers_list)
+ , client_ciphers_list_(c_ciphers_list) {}
};
class SSLTest : public testing::Test {
@@ -127,6 +130,16 @@ class SSLTest : public testing::Test {
.WillRepeatedly(ReturnRef(kCaPath));
EXPECT_CALL(*mock_crypto_manager_settings_, verify_peer())
.WillOnce(Return(false));
+
+ ON_CALL(*mock_crypto_manager_settings_, force_unprotected_service())
+ .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);
@@ -150,6 +163,16 @@ class SSLTest : public testing::Test {
.WillRepeatedly(ReturnRef(kCaPath));
EXPECT_CALL(*mock_client_manager_settings_, verify_peer())
.WillOnce(Return(false));
+
+ ON_CALL(*mock_client_manager_settings_, force_unprotected_service())
+ .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);
@@ -159,19 +182,19 @@ class SSLTest : public testing::Test {
.WillByDefault(Return(kMaximumPayloadSize));
EXPECT_CALL(*mock_crypto_manager_settings_, security_manager_mode())
.WillRepeatedly(Return(security_manager::SERVER));
- server_ctx = crypto_manager_->CreateSSLContext();
+ server_ctx_ = crypto_manager_->CreateSSLContext();
EXPECT_CALL(*mock_client_manager_settings_, security_manager_mode())
.Times(2)
.WillRepeatedly(Return(security_manager::CLIENT));
- client_ctx = client_manager_->CreateSSLContext();
+ client_ctx_ = client_manager_->CreateSSLContext();
using custom_str::CustomString;
security_manager::SSLContext::HandshakeContext ctx(CustomString("SPT"),
CustomString("client"));
- server_ctx->SetHandshakeContext(ctx);
+ server_ctx_->SetHandshakeContext(ctx);
ctx.expected_cn = "server";
- client_ctx->SetHandshakeContext(ctx);
+ client_ctx_->SetHandshakeContext(ctx);
kServerBuf = NULL;
kClientBuf = NULL;
@@ -180,8 +203,8 @@ class SSLTest : public testing::Test {
}
void TearDown() OVERRIDE {
- crypto_manager_->ReleaseSSLContext(server_ctx);
- client_manager_->ReleaseSSLContext(client_ctx);
+ crypto_manager_->ReleaseSSLContext(server_ctx_);
+ client_manager_->ReleaseSSLContext(client_ctx_);
delete crypto_manager_;
delete client_manager_;
@@ -194,11 +217,14 @@ class SSLTest : public testing::Test {
mock_crypto_manager_settings_;
utils::SharedPtr<NiceMock<security_manager_test::MockCryptoManagerSettings> >
mock_client_manager_settings_;
- security_manager::SSLContext* server_ctx;
- security_manager::SSLContext* client_ctx;
+ security_manager::SSLContext* server_ctx_;
+ security_manager::SSLContext* client_ctx_;
static std::string client_certificate_data_base64_;
static std::string server_certificate_data_base64_;
+
+ const std::vector<int> forced_unprotected_service_;
+ const std::vector<int> forced_protected_service_;
};
std::string SSLTest::client_certificate_data_base64_;
std::string SSLTest::server_certificate_data_base64_;
@@ -222,37 +248,38 @@ class SSLTestParam : public testing::TestWithParam<ProtocolAndCipher> {
NiceMock<security_manager_test::MockCryptoManagerSettings> >();
utils::SharedPtr<security_manager::CryptoManagerSettings> server_crypto(
mock_crypto_manager_settings_);
- crypto_manager = new security_manager::CryptoManagerImpl(server_crypto);
+ crypto_manager_ = new security_manager::CryptoManagerImpl(server_crypto);
- SetServerInitialValues(GetParam().server_protocol,
- GetParam().server_ciphers_list);
+ SetServerInitialValues(GetParam().server_protocol_,
+ GetParam().server_ciphers_list_);
- const bool crypto_manager_initialization = crypto_manager->Init();
- ASSERT_TRUE(crypto_manager_initialization);
+ const bool crypto_manager_initialization = crypto_manager_->Init();
+ EXPECT_TRUE(crypto_manager_initialization);
mock_client_manager_settings_ = utils::MakeShared<
NiceMock<security_manager_test::MockCryptoManagerSettings> >();
utils::SharedPtr<security_manager::CryptoManagerSettings> client_crypto(
mock_client_manager_settings_);
- client_manager = new security_manager::CryptoManagerImpl(client_crypto);
+ client_manager_ = new security_manager::CryptoManagerImpl(client_crypto);
- SetClientInitialValues(GetParam().client_protocol,
- GetParam().client_ciphers_list);
+ SetClientInitialValues(GetParam().client_protocol_,
+ GetParam().client_ciphers_list_);
- const bool client_manager_initialization = client_manager->Init();
- ASSERT_TRUE(client_manager_initialization);
+ const bool client_manager_initialization = client_manager_->Init();
+ EXPECT_TRUE(client_manager_initialization);
- server_ctx = crypto_manager->CreateSSLContext();
- client_ctx = client_manager->CreateSSLContext();
+ server_ctx_ = crypto_manager_->CreateSSLContext();
+ client_ctx_ = client_manager_->CreateSSLContext();
using custom_str::CustomString;
- security_manager::SSLContext::HandshakeContext ctx(CustomString("SPT"),
- CustomString("client"));
- server_ctx->SetHandshakeContext(ctx);
- ctx.expected_cn = "server";
- client_ctx->SetHandshakeContext(ctx);
+ server_ctx_->SetHandshakeContext(
+ security_manager::SSLContext::HandshakeContext(CustomString("SPT"),
+ CustomString("client")));
+ client_ctx_->SetHandshakeContext(
+ security_manager::SSLContext::HandshakeContext(CustomString("SPT"),
+ CustomString("server")));
kServerBuf = NULL;
kClientBuf = NULL;
@@ -261,18 +288,19 @@ class SSLTestParam : public testing::TestWithParam<ProtocolAndCipher> {
}
void TearDown() OVERRIDE {
- if (crypto_manager) {
- crypto_manager->ReleaseSSLContext(server_ctx);
- }
- if (client_manager) {
- client_manager->ReleaseSSLContext(client_ctx);
- }
- delete crypto_manager;
- delete client_manager;
+ crypto_manager_->ReleaseSSLContext(server_ctx_);
+ client_manager_->ReleaseSSLContext(client_ctx_);
+
+ delete crypto_manager_;
+ delete client_manager_;
}
void SetServerInitialValues(security_manager::Protocol protocol,
const std::string& server_ciphers_list) {
+ ON_CALL(*mock_crypto_manager_settings_, force_unprotected_service())
+ .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_, security_manager_mode())
.WillByDefault(Return(security_manager::SERVER));
ON_CALL(*mock_crypto_manager_settings_, security_manager_protocol_name())
@@ -285,9 +313,18 @@ 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,
const std::string& client_ciphers_list) {
+ ON_CALL(*mock_client_manager_settings_, force_unprotected_service())
+ .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_, security_manager_mode())
.WillByDefault(Return(security_manager::CLIENT));
ON_CALL(*mock_client_manager_settings_, security_manager_protocol_name())
@@ -300,17 +337,23 @@ 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> >
mock_crypto_manager_settings_;
utils::SharedPtr<NiceMock<security_manager_test::MockCryptoManagerSettings> >
mock_client_manager_settings_;
- security_manager::CryptoManager* crypto_manager = NULL;
- security_manager::CryptoManager* client_manager = NULL;
- security_manager::SSLContext* server_ctx = NULL;
- security_manager::SSLContext* client_ctx = NULL;
+ security_manager::CryptoManager* crypto_manager_;
+ security_manager::CryptoManager* client_manager_;
+ security_manager::SSLContext* server_ctx_;
+ security_manager::SSLContext* client_ctx_;
std::string certificate_data_base64_;
+ const std::vector<int> forced_unprotected_service_;
+ const std::vector<int> forced_protected_service_;
};
class SSLTestForTLS1_2 : public SSLTestParam {};
@@ -319,7 +362,7 @@ class SSLTestForTLS1_2 : public SSLTestParam {};
INSTANTIATE_TEST_CASE_P(
CorrectProtocolAndCiphers,
SSLTestParam,
- ::testing::Values(ProtocolAndCipher(security_manager::TLSv1,
+ ::testing::Values(ProtocolAndCipher(security_manager::TLSv1_1,
security_manager::TLSv1,
kFordCipher,
kFordCipher),
@@ -334,7 +377,11 @@ INSTANTIATE_TEST_CASE_P(
kFordCipher,
kFordCipher)
#endif
- ));
+ ,
+ ProtocolAndCipher(security_manager::DTLSv1,
+ security_manager::DTLSv1,
+ kFordCipher,
+ kFordCipher)));
INSTANTIATE_TEST_CASE_P(
IncorrectProtocolAndCiphers,
@@ -365,6 +412,22 @@ INSTANTIATE_TEST_CASE_P(
security_manager::SSLv3,
kFordCipher,
kFordCipher),
+ ProtocolAndCipher(security_manager::TLSv1,
+ security_manager::DTLSv1,
+ kFordCipher,
+ kFordCipher),
+ ProtocolAndCipher(security_manager::DTLSv1,
+ security_manager::TLSv1_1,
+ kFordCipher,
+ kFordCipher),
+ ProtocolAndCipher(security_manager::TLSv1_2,
+ security_manager::DTLSv1,
+ kFordCipher,
+ kFordCipher),
+ ProtocolAndCipher(security_manager::TLSv1_1,
+ security_manager::DTLSv1,
+ kFordCipher,
+ kFordCipher),
ProtocolAndCipher(security_manager::TLSv1_2,
security_manager::SSLv3,
kFordCipher,
@@ -382,7 +445,8 @@ INSTANTIATE_TEST_CASE_P(
TEST_F(SSLTest, OnTSL2Protocol_BrokenHandshake) {
ASSERT_EQ(security_manager::SSLContext::Handshake_Result_Success,
- client_ctx->StartHandshake(&kClientBuf, &client_buf_len));
+ client_ctx_->StartHandshake(&kClientBuf, &client_buf_len));
+
ASSERT_FALSE(NULL == kClientBuf);
ASSERT_LT(0u, client_buf_len);
// Broke 3 bytes for get abnormal fail of handshake
@@ -390,26 +454,26 @@ TEST_F(SSLTest, OnTSL2Protocol_BrokenHandshake) {
const_cast<uint8_t*>(kClientBuf)[client_buf_len / 2] ^= 0xFF;
const_cast<uint8_t*>(kClientBuf)[client_buf_len - 1] ^= 0xFF;
ASSERT_EQ(security_manager::SSLContext::Handshake_Result_AbnormalFail,
- server_ctx->DoHandshakeStep(
+ server_ctx_->DoHandshakeStep(
kClientBuf, client_buf_len, &kServerBuf, &server_buf_len));
- EXPECT_EQ("Initialization is not completed", server_ctx->LastError());
- EXPECT_EQ("Initialization is not completed", client_ctx->LastError());
+ EXPECT_EQ("Initialization is not completed", server_ctx_->LastError());
+ EXPECT_EQ("Initialization is not completed", client_ctx_->LastError());
}
// TODO {AKozoriz} : Unexpected uncomplited init of SSL component.
// In this and next tests.
// Must be fixed after merge to develop.
TEST_F(SSLTest, OnTSL2Protocol_Positive) {
- ASSERT_EQ(client_ctx->StartHandshake(&kClientBuf, &client_buf_len),
+ ASSERT_EQ(client_ctx_->StartHandshake(&kClientBuf, &client_buf_len),
security_manager::SSLContext::Handshake_Result_Success);
- EXPECT_FALSE(server_ctx->IsInitCompleted());
+ EXPECT_FALSE(server_ctx_->IsInitCompleted());
while (true) {
ASSERT_TRUE(NULL != kClientBuf);
ASSERT_LT(0u, client_buf_len);
const security_manager::SSLContext::HandshakeResult server_result =
- server_ctx->DoHandshakeStep(
+ server_ctx_->DoHandshakeStep(
kClientBuf, client_buf_len, &kServerBuf, &server_buf_len);
ASSERT_EQ(security_manager::SSLContext::Handshake_Result_Success,
server_result);
@@ -417,11 +481,11 @@ TEST_F(SSLTest, OnTSL2Protocol_Positive) {
ASSERT_LT(0u, server_buf_len);
const security_manager::SSLContext::HandshakeResult client_result =
- client_ctx->DoHandshakeStep(
+ client_ctx_->DoHandshakeStep(
kServerBuf, server_buf_len, &kClientBuf, &client_buf_len);
ASSERT_EQ(security_manager::SSLContext::Handshake_Result_Success,
client_result);
- if (server_ctx->IsInitCompleted()) {
+ if (server_ctx_->IsInitCompleted()) {
break;
}
@@ -432,22 +496,22 @@ TEST_F(SSLTest, OnTSL2Protocol_Positive) {
ASSERT_TRUE(NULL == kClientBuf);
ASSERT_EQ(0u, client_buf_len);
// expect both side initialization complete
- EXPECT_TRUE(client_ctx->IsInitCompleted());
- EXPECT_TRUE(server_ctx->IsInitCompleted());
+ EXPECT_TRUE(client_ctx_->IsInitCompleted());
+ EXPECT_TRUE(server_ctx_->IsInitCompleted());
// Encrypt text on client side
const uint8_t* text = reinterpret_cast<const uint8_t*>("abra");
const uint8_t* encrypted_text = 0;
size_t text_len = 4;
size_t encrypted_text_len;
- EXPECT_TRUE(client_ctx->Encrypt(
+ EXPECT_TRUE(client_ctx_->Encrypt(
text, text_len, &encrypted_text, &encrypted_text_len));
ASSERT_NE(reinterpret_cast<void*>(NULL), encrypted_text);
ASSERT_LT(0u, encrypted_text_len);
// Decrypt text on server side
- EXPECT_TRUE(server_ctx->Decrypt(
+ EXPECT_TRUE(server_ctx_->Decrypt(
encrypted_text, encrypted_text_len, &text, &text_len));
ASSERT_NE(reinterpret_cast<void*>(NULL), text);
ASSERT_LT(0u, text_len);
@@ -457,34 +521,34 @@ TEST_F(SSLTest, OnTSL2Protocol_Positive) {
TEST_F(SSLTest, OnTSL2Protocol_EcncryptionFail) {
ASSERT_EQ(security_manager::SSLContext::Handshake_Result_Success,
- client_ctx->StartHandshake(&kClientBuf, &client_buf_len));
+ client_ctx_->StartHandshake(&kClientBuf, &client_buf_len));
- while (!server_ctx->IsInitCompleted()) {
+ while (!server_ctx_->IsInitCompleted()) {
ASSERT_FALSE(NULL == kClientBuf);
ASSERT_LT(0u, client_buf_len);
ASSERT_EQ(security_manager::SSLContext::Handshake_Result_Success,
- server_ctx->DoHandshakeStep(
+ server_ctx_->DoHandshakeStep(
kClientBuf, client_buf_len, &kServerBuf, &server_buf_len));
ASSERT_FALSE(NULL == kServerBuf);
ASSERT_LT(0u, server_buf_len);
ASSERT_EQ(security_manager::SSLContext::Handshake_Result_Success,
- client_ctx->DoHandshakeStep(
+ client_ctx_->DoHandshakeStep(
kServerBuf, server_buf_len, &kClientBuf, &client_buf_len));
}
// Expect empty buffers after init complete
ASSERT_TRUE(NULL == kClientBuf);
ASSERT_EQ(0u, client_buf_len);
// Expect both side initialization complete
- EXPECT_TRUE(client_ctx->IsInitCompleted());
- EXPECT_TRUE(server_ctx->IsInitCompleted());
+ EXPECT_TRUE(client_ctx_->IsInitCompleted());
+ EXPECT_TRUE(server_ctx_->IsInitCompleted());
// Encrypt text on client side
const uint8_t* text = reinterpret_cast<const uint8_t*>("abra");
const uint8_t* encrypted_text = 0;
size_t text_len = 4;
size_t encrypted_text_len;
- EXPECT_TRUE(client_ctx->Encrypt(
+ EXPECT_TRUE(client_ctx_->Encrypt(
text, text_len, &encrypted_text, &encrypted_text_len));
ASSERT_NE(reinterpret_cast<void*>(NULL), encrypted_text);
ASSERT_LT(0u, encrypted_text_len);
@@ -497,29 +561,30 @@ TEST_F(SSLTest, OnTSL2Protocol_EcncryptionFail) {
const uint8_t* out_text;
size_t out_text_size;
// Decrypt broken text on server side
- EXPECT_FALSE(server_ctx->Decrypt(
+ EXPECT_FALSE(server_ctx_->Decrypt(
&broken[0], broken.size(), &out_text, &out_text_size));
// Check after broken message that server encryption and decryption fail
// Encrypte message on server side
- EXPECT_FALSE(server_ctx->Decrypt(
+ EXPECT_FALSE(server_ctx_->Decrypt(
encrypted_text, encrypted_text_len, &out_text, &out_text_size));
- EXPECT_FALSE(server_ctx->Encrypt(
+ EXPECT_FALSE(server_ctx_->Encrypt(
text, text_len, &encrypted_text, &encrypted_text_len));
}
TEST_P(SSLTestParam, ClientAndServerNotTLSv1_2_HandshakeFailed) {
ASSERT_EQ(security_manager::SSLContext::Handshake_Result_AbnormalFail,
- client_ctx->StartHandshake(&kClientBuf, &client_buf_len));
+ client_ctx_->StartHandshake(&kClientBuf, &client_buf_len));
+
EXPECT_TRUE(NULL == kClientBuf);
EXPECT_EQ(0u, client_buf_len);
ASSERT_EQ(security_manager::SSLContext::Handshake_Result_Success,
- server_ctx->DoHandshakeStep(
+ server_ctx_->DoHandshakeStep(
kClientBuf, client_buf_len, &kServerBuf, &server_buf_len));
EXPECT_TRUE(NULL == kServerBuf);
EXPECT_EQ(0u, server_buf_len);
- EXPECT_FALSE(server_ctx->IsInitCompleted());
+ EXPECT_FALSE(server_ctx_->IsInitCompleted());
}
INSTANTIATE_TEST_CASE_P(
@@ -544,16 +609,19 @@ INSTANTIATE_TEST_CASE_P(
TEST_P(SSLTestForTLS1_2, HandshakeFailed) {
ASSERT_EQ(security_manager::SSLContext::Handshake_Result_Success,
- client_ctx->StartHandshake(&kClientBuf, &client_buf_len));
+ client_ctx_->StartHandshake(&kClientBuf, &client_buf_len));
EXPECT_FALSE(NULL == kClientBuf);
ASSERT_LT(0u, client_buf_len);
+
ASSERT_EQ(security_manager::SSLContext::Handshake_Result_AbnormalFail,
- server_ctx->DoHandshakeStep(
- kClientBuf, client_buf_len, &kServerBuf, &server_buf_len));
+ server_ctx_->DoHandshakeStep(
+ kClientBuf, client_buf_len, &kServerBuf, &server_buf_len))
+ << ERR_reason_error_string(ERR_get_error());
+
EXPECT_TRUE(NULL == kServerBuf);
EXPECT_EQ(0u, server_buf_len);
- EXPECT_FALSE(server_ctx->IsInitCompleted());
+ EXPECT_FALSE(server_ctx_->IsInitCompleted());
}
} // namespace ssl_context_test