diff options
Diffstat (limited to 'src/components/security_manager/src/ssl_context_impl.cc')
-rw-r--r-- | src/components/security_manager/src/ssl_context_impl.cc | 197 |
1 files changed, 116 insertions, 81 deletions
diff --git a/src/components/security_manager/src/ssl_context_impl.cc b/src/components/security_manager/src/ssl_context_impl.cc index 6f53234867..fb049aa497 100644 --- a/src/components/security_manager/src/ssl_context_impl.cc +++ b/src/components/security_manager/src/ssl_context_impl.cc @@ -68,7 +68,7 @@ std::string CryptoManagerImpl::SSLContextImpl::LastError() const { } bool CryptoManagerImpl::SSLContextImpl::IsInitCompleted() const { - sync_primitives::AutoLock locker(bio_locker); + sync_primitives::AutoLock locker(ssl_locker_); return SSL_is_init_finished(connection_); } @@ -114,21 +114,27 @@ size_t des_cbc3_sha_max_block_size(size_t mtu) { std::map<std::string, CryptoManagerImpl::SSLContextImpl::BlockSizeGetter> CryptoManagerImpl::SSLContextImpl::create_max_block_sizes() { std::map<std::string, CryptoManagerImpl::SSLContextImpl::BlockSizeGetter> rc; + rc.insert(std::make_pair(std::string("AES128-GCM-SHA256"), + aes128_gcm_sha256_max_block_size)); + rc.insert(std::make_pair(std::string("AES128-SHA256"), + aes128_sha256_max_block_size)); + rc.insert(std::make_pair(std::string("AES128-SHA"), seed_sha_max_block_size)); + rc.insert(std::make_pair(std::string("AES256-GCM-SHA384"), + aes128_gcm_sha256_max_block_size)); + rc.insert(std::make_pair(std::string("AES256-SHA256"), + aes128_sha256_max_block_size)); + rc.insert(std::make_pair(std::string("AES256-SHA"), seed_sha_max_block_size)); rc.insert( - std::make_pair("AES128-GCM-SHA256", aes128_gcm_sha256_max_block_size)); - rc.insert(std::make_pair("AES128-SHA256", aes128_sha256_max_block_size)); - rc.insert(std::make_pair("AES128-SHA", seed_sha_max_block_size)); + std::make_pair(std::string("CAMELLIA128-SHA"), seed_sha_max_block_size)); rc.insert( - std::make_pair("AES256-GCM-SHA384", aes128_gcm_sha256_max_block_size)); - rc.insert(std::make_pair("AES256-SHA256", aes128_sha256_max_block_size)); - rc.insert(std::make_pair("AES256-SHA", seed_sha_max_block_size)); - rc.insert(std::make_pair("CAMELLIA128-SHA", seed_sha_max_block_size)); - rc.insert(std::make_pair("CAMELLIA256-SHA", seed_sha_max_block_size)); - rc.insert(std::make_pair("DES-CBC3-SHA", des_cbc3_sha_max_block_size)); - rc.insert(std::make_pair("DES-CBC-SHA", des_cbc3_sha_max_block_size)); - rc.insert(std::make_pair("RC4-MD5", rc4_md5_max_block_size)); - rc.insert(std::make_pair("RC4-SHA", rc4_sha_max_block_size)); - rc.insert(std::make_pair("SEED-SHA", seed_sha_max_block_size)); + std::make_pair(std::string("CAMELLIA256-SHA"), seed_sha_max_block_size)); + rc.insert( + std::make_pair(std::string("DES-CBC3-SHA"), des_cbc3_sha_max_block_size)); + rc.insert( + std::make_pair(std::string("DES-CBC-SHA"), des_cbc3_sha_max_block_size)); + rc.insert(std::make_pair(std::string("RC4-MD5"), rc4_md5_max_block_size)); + rc.insert(std::make_pair(std::string("RC4-SHA"), rc4_sha_max_block_size)); + rc.insert(std::make_pair(std::string("SEED-SHA"), seed_sha_max_block_size)); return rc; } @@ -143,13 +149,13 @@ void CryptoManagerImpl::SSLContextImpl::PrintCertData( char* subj = X509_NAME_oneline(subj_name, NULL, 0); if (subj) { std::replace(subj, subj + strlen(subj), '/', ' '); - LOG4CXX_DEBUG(logger_, cert_owner << " subject:" << subj); + LOGGER_DEBUG(logger_, cert_owner << " subject:" << subj); OPENSSL_free(subj); } char* issuer = X509_NAME_oneline(X509_get_issuer_name(cert), NULL, 0); if (issuer) { std::replace(issuer, issuer + strlen(issuer), '/', ' '); - LOG4CXX_DEBUG(logger_, cert_owner << " issuer:" << issuer); + LOGGER_DEBUG(logger_, cert_owner << " issuer:" << issuer); OPENSSL_free(issuer); } @@ -157,15 +163,16 @@ void CryptoManagerImpl::SSLContextImpl::PrintCertData( ASN1_TIME* notAfter = X509_get_notAfter(cert); if (notBefore) { - LOG4CXX_DEBUG(logger_, " Start date: " << (char*)notBefore->data); + LOGGER_DEBUG(logger_, " Start date: " << (char*)notBefore->data); } if (notAfter) { - LOG4CXX_DEBUG(logger_, " End date: " << (char*)notAfter->data); + LOGGER_DEBUG(logger_, " End date: " << (char*)notAfter->data); } } } void CryptoManagerImpl::SSLContextImpl::PrintCertInfo() { + sync_primitives::AutoLock locker(ssl_locker_); PrintCertData(SSL_get_certificate(connection_), "HU's"); STACK_OF(X509)* peer_certs = SSL_get_peer_cert_chain(connection_); @@ -190,18 +197,18 @@ CryptoManagerImpl::SSLContextImpl::CheckCertContext() { const std::string& sn = GetTextBy(subj_name, NID_serialNumber); if (!(hsh_context_.expected_cn.CompareIgnoreCase(cn.c_str()))) { - LOG4CXX_ERROR(logger_, - "Trying to run handshake with wrong app name: " - << cn << ". Expected app name: " - << hsh_context_.expected_cn.AsMBString()); + LOGGER_ERROR(logger_, + "Trying to run handshake with wrong app name: " + << cn << ". Expected app name: " + << hsh_context_.expected_cn.AsMBString()); return Handshake_Result_AppNameMismatch; } if (!(hsh_context_.expected_sn.CompareIgnoreCase(sn.c_str()))) { - LOG4CXX_ERROR(logger_, - "Trying to run handshake with wrong app id: " - << sn << ". Expected app id: " - << hsh_context_.expected_sn.AsMBString()); + LOGGER_ERROR(logger_, + "Trying to run handshake with wrong app id: " + << sn << ". Expected app id: " + << hsh_context_.expected_sn.AsMBString()); return Handshake_Result_AppIDMismatch; } return Handshake_Result_Success; @@ -209,12 +216,13 @@ CryptoManagerImpl::SSLContextImpl::CheckCertContext() { bool CryptoManagerImpl::SSLContextImpl::ReadHandshakeData( const uint8_t** const out_data, size_t* out_data_size) { - LOG4CXX_AUTO_TRACE(logger_); + LOGGER_AUTO_TRACE(logger_); + sync_primitives::AutoLock locker(ssl_locker_); const size_t pend = BIO_ctrl_pending(bioOut_); - LOG4CXX_DEBUG(logger_, "Available " << pend << " bytes for handshake"); + LOGGER_DEBUG(logger_, "Available " << pend << " bytes for handshake"); if (pend > 0) { - LOG4CXX_DEBUG(logger_, "Reading handshake data"); + LOGGER_DEBUG(logger_, "Reading handshake data"); EnsureBufferSizeEnough(pend); const int read_count = BIO_read(bioOut_, buffer_, pend); @@ -222,7 +230,7 @@ bool CryptoManagerImpl::SSLContextImpl::ReadHandshakeData( *out_data_size = read_count; *out_data = buffer_; } else { - LOG4CXX_WARN(logger_, "BIO read fail"); + LOGGER_WARN(logger_, "BIO read fail"); is_handshake_pending_ = false; ResetConnection(); return false; @@ -234,7 +242,8 @@ bool CryptoManagerImpl::SSLContextImpl::ReadHandshakeData( bool CryptoManagerImpl::SSLContextImpl::WriteHandshakeData( const uint8_t* const in_data, size_t in_data_size) { - LOG4CXX_AUTO_TRACE(logger_); + LOGGER_AUTO_TRACE(logger_); + sync_primitives::AutoLock locker(ssl_locker_); if (in_data && in_data_size) { const int ret = BIO_write(bioIn_, in_data, in_data_size); if (ret <= 0) { @@ -250,46 +259,68 @@ SSLContext::HandshakeResult CryptoManagerImpl::SSLContextImpl::PerformHandshake() { const int handshake_result = SSL_do_handshake(connection_); if (handshake_result == 1) { - const HandshakeResult result = CheckCertContext(); - if (result != Handshake_Result_Success) { - ResetConnection(); - is_handshake_pending_ = false; - return result; - } - - LOG4CXX_DEBUG(logger_, "SSL handshake successfully finished"); - // Handshake is successful - bioFilter_ = BIO_new(BIO_f_ssl()); - BIO_set_ssl(bioFilter_, connection_, BIO_NOCLOSE); - - const SSL_CIPHER* cipher = SSL_get_current_cipher(connection_); - max_block_size_ = max_block_sizes[SSL_CIPHER_get_name(cipher)]; - is_handshake_pending_ = false; - + return ProcessSuccessHandshake(); } else if (handshake_result == 0) { + sync_primitives::AutoLock locker(ssl_locker_); SSL_clear(connection_); is_handshake_pending_ = false; return Handshake_Result_Fail; } else { - const int error = SSL_get_error(connection_, handshake_result); - if (error != SSL_ERROR_WANT_READ) { - const long error = SSL_get_verify_result(connection_); - SetHandshakeError(error); - LOG4CXX_WARN(logger_, - "Handshake failed with error " - << " -> " << SSL_get_error(connection_, error) << " \"" - << LastError() << '"'); - ResetConnection(); - is_handshake_pending_ = false; + return ProcessHandshakeError(handshake_result); + } + return Handshake_Result_Success; +} + +SSLContext::HandshakeResult +CryptoManagerImpl::SSLContextImpl::ProcessSuccessHandshake() { + sync_primitives::AutoLock locker(ssl_locker_); + const HandshakeResult result = CheckCertContext(); + if (result != Handshake_Result_Success) { + ResetConnection(); + is_handshake_pending_ = false; + return result; + } - // In case error happened but ssl verification shows OK - // method will return AbnormalFail. - if (X509_V_OK == error) { - return Handshake_Result_AbnormalFail; - } - return openssl_error_convert_to_internal(error); + LOGGER_DEBUG(logger_, "SSL handshake successfully finished"); + // Handshake is successful + bioFilter_ = BIO_new(BIO_f_ssl()); + BIO_set_ssl(bioFilter_, connection_, BIO_NOCLOSE); + + const SSL_CIPHER* cipher = SSL_get_current_cipher(connection_); + max_block_size_ = max_block_sizes[SSL_CIPHER_get_name(cipher)]; + is_handshake_pending_ = false; + + return result; +} + +SSLContext::HandshakeResult +CryptoManagerImpl::SSLContextImpl::ProcessHandshakeError( + const int handshake_error) { + // Since the LastError function uses lock and this one is public + // we need to cache its value before execute code below + // in order to prevent dead lock, since our mutex is not recursive one. + const std::string& last_error = LastError(); + + sync_primitives::AutoLock locker(ssl_locker_); + const int error = SSL_get_error(connection_, handshake_error); + if (error != SSL_ERROR_WANT_READ) { + const long error = SSL_get_verify_result(connection_); + SetHandshakeError(error); + LOGGER_WARN(logger_, + "Handshake failed with error " + << " -> " << SSL_get_error(connection_, error) << " \"" + << last_error << '"'); + ResetConnection(); + is_handshake_pending_ = false; + + // In case error happened but ssl verification shows OK + // method will return AbnormalFail. + if (X509_V_OK == error) { + return Handshake_Result_AbnormalFail; } + return openssl_error_convert_to_internal(error); } + return Handshake_Result_Success; } @@ -298,21 +329,14 @@ SSLContext::HandshakeResult CryptoManagerImpl::SSLContextImpl::DoHandshakeStep( size_t in_data_size, const uint8_t** const out_data, size_t* out_data_size) { - LOG4CXX_AUTO_TRACE(logger_); + LOGGER_AUTO_TRACE(logger_); DCHECK(out_data); DCHECK(out_data_size); *out_data = NULL; *out_data_size = 0; - // TODO(Ezamakhov): add test - hanshake fail -> restart StartHandshake - { - sync_primitives::AutoLock locker(bio_locker); - - if (SSL_is_init_finished(connection_)) { - LOG4CXX_DEBUG(logger_, "SSL initilization is finished"); - is_handshake_pending_ = false; - return Handshake_Result_Success; - } + if (CheckInitFinished()) { + return Handshake_Result_Success; } if (!WriteHandshakeData(in_data, in_data_size)) { @@ -333,11 +357,22 @@ SSLContext::HandshakeResult CryptoManagerImpl::SSLContextImpl::DoHandshakeStep( return res; } +bool CryptoManagerImpl::SSLContextImpl::CheckInitFinished() { + // TODO(Ezamakhov): add test - hanshake fail -> restart StartHandshake + sync_primitives::AutoLock locker(ssl_locker_); + if (SSL_is_init_finished(connection_)) { + LOGGER_DEBUG(logger_, "SSL initilization is finished"); + is_handshake_pending_ = false; + return true; + } + return false; +} + bool CryptoManagerImpl::SSLContextImpl::Encrypt(const uint8_t* const in_data, size_t in_data_size, const uint8_t** const out_data, size_t* out_data_size) { - sync_primitives::AutoLock locker(bio_locker); + sync_primitives::AutoLock locker(ssl_locker_); if (!SSL_is_init_finished(connection_) || !in_data || !in_data_size) { return false; } @@ -363,7 +398,7 @@ 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) { - sync_primitives::AutoLock locker(bio_locker); + sync_primitives::AutoLock locker(ssl_locker_); if (!SSL_is_init_finished(connection_)) { return false; } @@ -424,19 +459,19 @@ void CryptoManagerImpl::SSLContextImpl::SetHandshakeError(const int error) { } void CryptoManagerImpl::SSLContextImpl::ResetConnection() { - LOG4CXX_AUTO_TRACE(logger_); + LOGGER_AUTO_TRACE(logger_); const int shutdown_result = SSL_shutdown(connection_); if (shutdown_result != 1) { const size_t pend = BIO_ctrl_pending(bioOut_); - LOG4CXX_DEBUG(logger_, "Available " << pend << " bytes for shutdown"); + LOGGER_DEBUG(logger_, "Available " << pend << " bytes for shutdown"); if (pend > 0) { - LOG4CXX_DEBUG(logger_, "Reading shutdown data"); + LOGGER_DEBUG(logger_, "Reading shutdown data"); EnsureBufferSizeEnough(pend); BIO_read(bioOut_, buffer_, pend); } SSL_shutdown(connection_); } - LOG4CXX_DEBUG(logger_, "SSL connection recreation"); + LOGGER_DEBUG(logger_, "SSL connection recreation"); SSL_CTX* ssl_context = connection_->ctx; SSL_free(connection_); connection_ = SSL_new(ssl_context); @@ -488,8 +523,8 @@ std::string CryptoManagerImpl::SSLContextImpl::GetTextBy(X509_NAME* name, const int req_len = X509_NAME_get_text_by_NID(name, object, NULL, 0); if (-1 == req_len) { - LOG4CXX_WARN(logger_, - "Unable to obtain object: " << object << " from certificate"); + LOGGER_WARN(logger_, + "Unable to obtain object: " << object << " from certificate"); return std::string(); } |