@ -1,13 +1,10 @@
// Copyright (c) 2019-2020 The Hush developers
// Distributed under the GPLv3 software license, see the accompanying
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
# include <openssl/conf.h>
# include <openssl/ssl.h>
# include <openssl/err.h>
# ifndef HEADER_DH_H
# include <openssl/dh.h>
# endif
# include <wolfssl/options.h>
# include <wolfssl/ssl.h>
# include <wolfssl/openssl/dh.h>
# include <wolfssl/wolfcrypt/asn.h>
# include <boost/filesystem.hpp>
# include <boost/thread.hpp>
@ -23,7 +20,7 @@ namespace hush
// it is OK to hard code it (or as an alternative to read it from a file)
// ----
// generated via: openssl dhparam -C 2048
static DH * get_dh2048 ( void )
static WOLFSSL_ DH * get_dh2048 ( void )
{
static unsigned char dhp_2048 [ ] = {
0xFF , 0x4A , 0xA8 , 0x6C , 0x68 , 0xD4 , 0x4C , 0x41 , 0x73 , 0x8D ,
@ -56,24 +53,20 @@ static DH *get_dh2048(void)
static unsigned char dhg_2048 [ ] = {
0x02
} ;
DH * dh = DH_new ( ) ;
BIGNUM * p , * g ;
WOLFSSL_DH * dh = wolfSSL_DH_new ( ) ;
if ( dh = = NULL )
return NULL ;
p = BN_bin2bn ( dhp_2048 , sizeof ( dhp_2048 ) , NULL ) ;
g = BN_bin2bn ( dhg_2048 , sizeof ( dhg_2048 ) , NULL ) ;
if ( p = = NULL | | g = = NULL
| | ! DH_set0_pqg ( dh , p , NULL , g ) ) {
DH_free ( dh ) ;
BN_free ( p ) ;
BN_free ( g ) ;
if ( wc_DhSetKey ( ( DhKey * ) dh - > internal , dhp_2048 , sizeof ( dhp_2048 ) , dhg_2048 , sizeof ( dhg_2048 ) ) ! = 0 ) {
wolfSSL_DH_free ( dh ) ;
return NULL ;
}
return dh ;
}
DH * tmp_dh_callback ( SSL * ssl , int is_export , int keylength )
DH * tmp_dh_callback ( WOLF SSL * ssl , int is_export , int keylength )
{
LogPrint ( " tls " , " TLS: %s: %s():%d - Using Diffie-Hellman param for PFS: is_export=%d, keylength=%d \n " ,
__FILE__ , __func__ , __LINE__ , is_export , keylength ) ;
@ -82,64 +75,53 @@ DH *tmp_dh_callback(SSL *ssl, int is_export, int keylength)
}
/** if 'tls' debug category is enabled, collect info about certificates relevant to the passed context and print them on logs */
static void dumpCertificateDebugInfo ( int preverify_ok , X509_STORE_CTX * chainContext )
static void dumpCertificateDebugInfo ( int preverify_ok , WOLFSSL_ X509_STORE_CTX* chainContext )
{
if ( ! LogAcceptCategory ( " tls " ) )
if ( ! LogAcceptCategory ( " tls " ) ) {
return ;
}
char buf [ 256 ] = { } ;
X509 * cert ;
WOLFSSL_ X509 * cert ;
int err , depth ;
cert = X509_STORE_CTX_get_current_cert ( chainContext ) ;
err = X509_STORE_CTX_get_error ( chainContext ) ;
depth = X509_STORE_CTX_get_error_depth ( chainContext ) ;
cert = wolfSSL_ X509_STORE_CTX_get_current_cert( chainContext ) ;
err = wolfSSL_ X509_STORE_CTX_get_error( chainContext ) ;
depth = wolfSSL_ X509_STORE_CTX_get_error_depth( chainContext ) ;
LogPrintf ( " TLS: %s: %s():%d - preverify_ok=%d, errCode=%d, depth=%d \n " ,
__FILE__ , __func__ , __LINE__ , preverify_ok , err , depth ) ;
// is not useful checking preverify_ok because, after the chain root verification, it is set accordingly
// to the return value of this callback, and we choose to always return 1
if ( err ! = X509_V_OK )
{
if ( err ! = X509_V_OK ) {
LogPrintf ( " TLS: %s: %s():%d - Certificate Verification ERROR=%d: [%s] at chain depth=%d \n " ,
__FILE__ , __func__ , __LINE__ , err , X509_verify_cert_error_string ( err ) , depth ) ;
__FILE__ , __func__ , __LINE__ , err , wolfSSL_ X509_verify_cert_error_string( err ) , depth ) ;
if ( cert & & err = = X509_V_ERR_CERT_HAS_EXPIRED )
{
struct tm t = { } ;
const ASN1_TIME * at = X509_get0_notAfter ( cert ) ;
int ret = ASN1_TIME_to_tm ( at , & t ) ;
if ( ret = = 1 )
{
( void ) strftime ( buf , sizeof ( buf ) , " %c " , & t ) ;
if ( cert & & err = = X509_V_ERR_CERT_HAS_EXPIRED ) {
char time_buf [ MAX_TIME_STRING_SZ ] ;
ASN1_TIME * at = wolfSSL_X509_get_notAfter ( cert ) ;
if ( wolfSSL_ASN1_TIME_to_string ( at , time_buf , sizeof ( time_buf ) ) ! = NULL ) {
LogPrintf ( " TLS: %s: %s():%d - expired on=%s \n " ,
__FILE__ , __func__ , __LINE__ , buf ) ;
}
}
}
else if ( cert )
{
X509_NAME_oneline ( X509_get_subject_name ( cert ) , buf , 256 ) ;
} else if ( cert ) {
wolfSSL_X509_NAME_oneline ( wolfSSL_X509_get_subject_name ( cert ) , buf , 256 ) ;
LogPrintf ( " TLS: %s: %s():%d - subj name=%s \n " ,
__FILE__ , __func__ , __LINE__ , buf ) ;
X509_NAME_oneline ( X509_get_issuer_name ( cert ) , buf , 256 ) ;
wolfSSL_ X509_NAME_oneline( wolfSSL_ X509_get_issuer_name( cert ) , buf , 256 ) ;
LogPrintf ( " TLS: %s: %s():%d - issuer name=%s \n " ,
__FILE__ , __func__ , __LINE__ , buf ) ;
struct tm t = { } ;
const ASN1_TIME * at = X509_get0_notAfter ( cert ) ;
int ret = ASN1_TIME_to_tm ( at , & t ) ;
if ( ret = = 1 )
{
( void ) strftime ( buf , sizeof ( buf ) , " %c " , & t ) ;
char time_buf [ MAX_TIME_STRING_SZ ] ;
WOLFSSL_ASN1_TIME * at = wolfSSL_X509_get_notAfter ( cert ) ;
if ( wolfSSL_ASN1_TIME_to_string ( at , time_buf , sizeof ( time_buf ) ) ! = NULL ) {
LogPrintf ( " TLS: %s: %s():%d - expiring on=%s \n " ,
__FILE__ , __func__ , __LINE__ , buf ) ;
}
}
else
{
} else {
// should never happen
LogPrintf ( " TLS: %s: %s():%d - invalid cert/err \n " , __FILE__ , __func__ , __LINE__ ) ;
}
@ -152,7 +134,7 @@ static void dumpCertificateDebugInfo(int preverify_ok, X509_STORE_CTX* chainCont
* @ param chainContext
* @ return int
*/
int tlsCertVerificationCallback ( int preverify_ok , X509_STORE_CTX * chainContext )
int tlsCertVerificationCallback ( int preverify_ok , WOLFSSL_ X509_STORE_CTX* chainContext )
{
dumpCertificateDebugInfo ( preverify_ok , chainContext ) ;
@ -175,23 +157,23 @@ int tlsCertVerificationCallback(int preverify_ok, X509_STORE_CTX* chainContext)
* @ param timeoutSec timeout in seconds .
* @ return int returns nError corresponding to the connection event .
*/
int TLSManager : : waitFor ( SSLConnectionRoutine eRoutine , SOCKET hSocket , SSL * ssl , int timeoutSec , unsigned long & err_code )
int TLSManager : : waitFor ( SSLConnectionRoutine eRoutine , SOCKET hSocket , WOLF SSL* ssl , int timeoutSec , unsigned long & err_code )
{
int retOp = 0 ;
err_code = 0 ;
while ( true ) {
while ( true )
{
// clear the current thread's error queue
ERR_clear_error ( ) ;
wolfSSL_ ERR_clear_error( ) ;
switch ( eRoutine ) {
case SSL_CONNECT :
{
retOp = SSL_connect ( ssl ) ;
if ( retOp = = 0 )
{
err_code = ERR_get_error ( ) ;
const char * error_str = ERR_error_string ( err_code , NULL ) ;
retOp = wolfSSL_connect ( ssl ) ;
if ( retOp = = 0 ) {
err_code = wolfSSL_ERR_get_error ( ) ;
const char * error_str = wolfSSL_ERR_error_string ( err_code , NULL ) ;
LogPrint ( " tls " , " TLS: WARNING: %s: %s():%d - SSL_CONNECT err: %s \n " ,
__FILE__ , __func__ , __LINE__ , error_str ) ;
return - 1 ;
@ -201,11 +183,10 @@ int TLSManager::waitFor(SSLConnectionRoutine eRoutine, SOCKET hSocket, SSL* ssl,
case SSL_ACCEPT :
{
retOp = SSL_accept ( ssl ) ;
if ( retOp = = 0 )
{
err_code = ERR_get_error ( ) ;
const char * error_str = ERR_error_string ( err_code , NULL ) ;
retOp = wolfSSL_accept ( ssl ) ;
if ( retOp = = 0 ) {
err_code = wolfSSL_ERR_get_error ( ) ;
const char * error_str = wolfSSL_ERR_error_string ( err_code , NULL ) ;
LogPrint ( " tls " , " TLS: WARNING: %s: %s():%d - SSL_ACCEPT err: %s \n " ,
__FILE__ , __func__ , __LINE__ , error_str ) ;
return - 1 ;
@ -215,19 +196,17 @@ int TLSManager::waitFor(SSLConnectionRoutine eRoutine, SOCKET hSocket, SSL* ssl,
case SSL_SHUTDOWN :
{
if ( hSocket ! = INVALID_SOCKET )
{
if ( hSocket ! = INVALID_SOCKET ) {
std : : string disconnectedPeer ( " no info " ) ;
struct sockaddr_in addr ;
socklen_t serv_len = sizeof ( addr ) ;
int ret = getpeername ( hSocket , ( struct sockaddr * ) & addr , & serv_len ) ;
if ( ret = = 0 )
{
if ( ret = = 0 ) {
disconnectedPeer = std : : string ( inet_ntoa ( addr . sin_addr ) ) + " : " + std : : to_string ( ntohs ( addr . sin_port ) ) ;
}
LogPrint ( " tls " , " TLS: shutting down fd=%d, peer=%s \n " , hSocket , disconnectedPeer ) ;
}
retOp = SSL_shutdown ( ssl ) ;
retOp = wolf SSL_shutdown( ssl ) ;
}
break ;
@ -236,41 +215,34 @@ int TLSManager::waitFor(SSLConnectionRoutine eRoutine, SOCKET hSocket, SSL* ssl,
}
if ( eRoutine = = SSL_SHUTDOWN ) {
if ( retOp = = 0 )
{
if ( retOp = = 0 ) {
LogPrint ( " tls " , " TLS: WARNING: %s: %s():%d - SSL_SHUTDOWN: The close_notify was sent but the peer did not send it back yet. \n " ,
__FILE__ , __func__ , __LINE__ ) ;
// do not call SSL_get_error() because it may misleadingly indicate an error even though no error occurred.
break ;
}
else
if ( retOp = = 1 )
{
} else if ( retOp = = 1 ) {
LogPrint ( " tls " , " TLS: %s: %s():%d - SSL_SHUTDOWN completed \n " , __FILE__ , __func__ , __LINE__ ) ;
break ;
}
else
{
} else {
LogPrint ( " tls " , " TLS: %s: %s():%d - SSL_SHUTDOWN failed \n " , __FILE__ , __func__ , __LINE__ ) ;
// the error will be read afterwards
}
} else {
if ( retOp = = 1 )
{
if ( retOp = = 1 ) {
LogPrint ( " tls " , " TLS: %s: %s():%d - %s completed \n " , __FILE__ , __func__ , __LINE__ ,
eRoutine = = SSL_CONNECT ? " SSL_CONNECT " : " SSL_ACCEPT " ) ;
break ;
}
}
int sslErr = SSL_get_error ( ssl , retOp ) ;
int sslErr = wolf SSL_get_error( ssl , retOp ) ;
if ( sslErr ! = SSL_ERROR_WANT_READ & & sslErr ! = SSL_ERROR_WANT_WRITE ) {
err_code = ERR_get_error ( ) ;
const char * error_str = ERR_error_string ( err_code , NULL ) ;
if ( sslErr ! = WOLF SSL_ERROR_WANT_READ & & sslErr ! = WOLF SSL_ERROR_WANT_WRITE) {
err_code = wolfSSL_ ERR_get_error( ) ;
const char * error_str = wolfSSL_ ERR_error_string( err_code , NULL ) ;
LogPrint ( " tls " , " TLS: WARNING: %s: %s():%d - routine(%d), sslErr[0x%x], retOp[%d], errno[0x%x], lib[0x%x], func[0x%x], reas[0x%x]-> err: %s \n " ,
__FILE__ , __func__ , __LINE__ ,
eRoutine , sslErr , retOp , errno , ERR_GET_LIB ( err_code ) , ERR_GET_FUNC ( err_code ) , ERR_GET_REASON ( err_code ) , error_str ) ;
eRoutine , sslErr , retOp , errno , wolfSSL_ ERR_GET_LIB( err_code ) , ERR_GET_FUNC ( err_code ) , wolfSSL_ ERR_GET_REASON( err_code ) , error_str ) ;
retOp = - 1 ;
break ;
}
@ -281,7 +253,7 @@ int TLSManager::waitFor(SSLConnectionRoutine eRoutine, SOCKET hSocket, SSL* ssl,
struct timeval timeout = { timeoutSec , 0 } ;
if ( sslErr = = SSL_ERROR_WANT_READ ) {
if ( sslErr = = WOLF SSL_ERROR_WANT_READ) {
int result = select ( hSocket + 1 , & socketSet , NULL , NULL , & timeout ) ;
if ( result = = 0 ) {
LogPrint ( " tls " , " TLS: ERROR: %s: %s():%d - WANT_READ timeout on %s \n " , __FILE__ , __func__ , __LINE__ ,
@ -323,18 +295,18 @@ int TLSManager::waitFor(SSLConnectionRoutine eRoutine, SOCKET hSocket, SSL* ssl,
* @ param hSocket socket
* @ param addrConnect the outgoing address
* @ param tls_ctx_client TLS Client context
* @ return SSL * returns a ssl * if successful , otherwise returns NULL .
* @ return WOLF SSL* returns a ssl * if successful , otherwise returns NULL .
*/
SSL * TLSManager : : connect ( SOCKET hSocket , const CAddress & addrConnect , unsigned long & err_code )
WOLF SSL* TLSManager : : connect ( SOCKET hSocket , const CAddress & addrConnect , unsigned long & err_code )
{
LogPrint ( " tls " , " TLS: establishing connection (tid = %X), (peerid = %s) \n " , pthread_self ( ) , addrConnect . ToString ( ) ) ;
err_code = 0 ;
SSL * ssl = NULL ;
WOLF SSL* ssl = NULL ;
bool bConnectedTLS = false ;
if ( ( ssl = SSL_new ( tls_ctx_client ) ) ) {
if ( SSL_set_fd ( ssl , hSocket ) ) {
if ( ( ssl = wolf SSL_new( tls_ctx_client ) ) ) {
if ( wolf SSL_set_fd( ssl , hSocket ) ) {
int ret = TLSManager : : waitFor ( SSL_CONNECT , hSocket , ssl , ( DEFAULT_CONNECT_TIMEOUT / 1000 ) , err_code ) ;
if ( ret = = 1 )
{
@ -344,25 +316,25 @@ SSL* TLSManager::connect(SOCKET hSocket, const CAddress& addrConnect, unsigned l
}
else
{
err_code = ERR_get_error ( ) ;
const char * error_str = ERR_error_string ( err_code , NULL ) ;
err_code = wolfSSL_ ERR_get_error( ) ;
const char * error_str = wolfSSL_ ERR_error_string( err_code , NULL ) ;
LogPrint ( " tls " , " TLS: %s: %s():%d - SSL_new failed err: %s \n " ,
__FILE__ , __func__ , __LINE__ , error_str ) ;
}
if ( bConnectedTLS ) {
LogPrintf ( " TLS: connection to %s has been established (tlsv = %s 0x%04x / ssl = %s 0x%x ). Using cipher: %s \n " ,
addrConnect . ToString ( ) , SSL_get_version ( ssl ) , SSL_version ( ssl ) , OpenSSL_version ( OPENSSL_VERSION ) , OpenSSL_version_num ( ) , SSL_get_cipher ( ssl ) ) ;
addrConnect . ToString ( ) , wolf SSL_get_version( ssl ) , wolf SSL_version( ssl ) , wolfSSL_ OpenSSL_version( ) , wolfSSL_lib_version_hex ( ) , wolf SSL_get_cipher_name ( ssl ) ) ;
} else {
LogPrintf ( " TLS: %s: %s():%d - TLS connection to %s failed (err_code 0x%X) \n " ,
__FILE__ , __func__ , __LINE__ , addrConnect . ToString ( ) , err_code ) ;
if ( ssl ) {
SSL_free ( ssl ) ;
wolf SSL_free( ssl ) ;
ssl = NULL ;
}
}
return ssl ;
}
/**
@ -372,9 +344,9 @@ SSL* TLSManager::connect(SOCKET hSocket, const CAddress& addrConnect, unsigned l
* @ param privateKeyFile private key file path
* @ param certificateFile certificate key file path
* @ param trustedDirs trusted directories
* @ return SSL_CTX * returns the context .
* @ return WOL SSL_CTX* returns the context .
*/
SSL_CTX * TLSManager : : initCtx (
WOLF SSL_CTX* TLSManager : : initCtx (
TLSContextType ctxType ,
const boost : : filesystem : : path & privateKeyFile ,
const boost : : filesystem : : path & certificateFile ,
@ -383,90 +355,87 @@ SSL_CTX* TLSManager::initCtx(
LogPrintf ( " TLS: %s: %s():%d - Initializing %s context \n " ,
__FILE__ , __func__ , __LINE__ , ctxType = = SERVER_CONTEXT ? " server " : " client " ) ;
if ( ! boost : : filesystem : : exists ( privateKeyFile ) | |
! boost : : filesystem : : exists ( certificateFile ) )
return NULL ;
if ( ! boost : : filesystem : : exists ( privateKeyFile ) | | ! boost : : filesystem : : exists ( certificateFile ) ) {
return NULL ;
}
bool bInitialized = false ;
SSL_CTX * tlsCtx = NULL ;
WOLF SSL_CTX* tlsCtx = NULL ;
if ( ( tlsCtx = SSL_CTX_new ( ctxType = = SERVER_CONTEXT ? TLS_server_method ( ) : TLS_client_method ( ) ) ) ) {
SSL_CTX_set_mode ( tlsCtx , SSL_MODE_AUTO_RETRY ) ;
if ( ( tlsCtx = wolf SSL_CTX_new( ctxType = = SERVER_CONTEXT ? wolf TLSv1_3 _server_method( ) : wolf TLSv1_3 _client_method( ) ) ) ) {
wolf SSL_CTX_set_mode( tlsCtx , SSL_MODE_AUTO_RETRY ) ;
// Disable TLS < 1.3
int ret = SSL_CTX_set_min_proto_version ( tlsCtx , TLS1_3_VERSION ) ;
if ( ret = = 0 )
{
// Disable TLS < 1.3 ... imho redundant, because v1.3 is required via method
int ret = wolfSSL_CTX_set_min_proto_version ( tlsCtx , TLS1_3_VERSION ) ;
if ( ret = = 0 ) {
LogPrintf ( " TLS: WARNING: %s: %s():%d - failed to set min TLS version \n " , __FILE__ , __func__ , __LINE__ ) ;
}
LogPrintf ( " TLS: %s: %s():%d - setting cipher list \n " , __FILE__ , __func__ , __LINE__ ) ;
SSL_CTX_set_cipher_list ( tlsCtx , " " ) ; // removes all <= TLS1.2 ciphers
// default is "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256"
// Nodes will randomly choose to prefer one suite or the other, to create diversity on the network
// Default TLSv1.3 cipher list is "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256"
// Nodes will randomly choose to prefer first cipher or the second, to create diversity on the network
// and not be in the situation where all nodes have the same list so the first is always used
if ( GetRand ( 100 ) > 50 ) {
if ( SSL_CTX_set_ciphersui tes ( tlsCtx , " TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256 " ) ) {
if ( wolf SSL_CTX_set_cipher_li st( tlsCtx , " TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256 " ) ) {
LogPrintf ( " %s: Preferring TLS_AES256-GCM-SHA384 \n " , __func__ ) ;
} else {
LogPrintf ( " %s: Setting preferred cipher failed !!! \n " , __func__ ) ;
}
} else {
if ( SSL_CTX_set_ciphersui tes ( tlsCtx , " TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384 " ) ) {
if ( wolf SSL_CTX_set_cipher_li st( tlsCtx , " TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384 " ) ) {
LogPrintf ( " %s: Preferring TLS_AES256-GCM-SHA384 \n " , __func__ ) ;
} else {
LogPrintf ( " %s: Setting preferred cipher failed !!! \n " , __func__ ) ;
}
}
// TLS 1.3 has ephemeral Diffie-Hellman as the only key exchange mechanism, so that perfect forward
// secrecy is ensured.
// TLSv1.3 has ephemeral Diffie-Hellman as the only key exchange mechanism, so that perfect forward secrecy is ensured.
if ( ctxType = = SERVER_CONTEXT )
{
if ( ctxType = = SERVER_CONTEXT ) {
// amongst the Cl/Srv mutually-acceptable set, pick the one that the server prefers most instead of the one that
// the client prefers most
SSL_CTX_set_options ( tlsCtx , SSL_OP_CIPHER_SERVER_PREFERENCE ) ;
wolf SSL_CTX_set_options( tlsCtx , SSL_OP_CIPHER_SERVER_PREFERENCE ) ;
LogPrintf ( " TLS: %s: %s():%d - setting dh callback \n " , __FILE__ , __func__ , __LINE__ ) ;
SSL_CTX_set_tmp_dh_callback ( tlsCtx , tmp_dh_callback ) ;
}
// Fix for Secure Client-Initiated Renegotiation DoS threat
SSL_CTX_set_options ( tlsCtx , SSL_OP_NO_RENEGOTIATION ) ;
int min_ver = SSL_CTX_get_min_proto_version ( tlsCtx ) ;
int max_ver = SSL_CTX_get_max_proto_version ( tlsCtx ) ; // 0x0 means auto
int opt_mask = SSL_CTX_get_options ( tlsCtx ) ;
LogPrintf ( " TLS: proto version: min/max 0x%04x/0x04%x, opt_mask=0x%x \n " , min_ver , max_ver , opt_mask ) ;
// Fix for Secure Client-Initiated Renegotiation DoS threat:
// In WolfSSL library renegotiation is disabled by default build config
// Support for TLSv1.3 should be the only one compiled
// ./configure --disable-oldtls --disable-tlsv12
int rootCertsNum = LoadDefaultRootCertificates ( tlsCtx ) ;
int trustedPathsNum = 0 ;
for ( boost : : filesystem : : path trustedDir : trustedDirs ) {
if ( SSL_CTX_load_verify_locations ( tlsCtx , NULL , trustedDir . string ( ) . c_str ( ) ) = = 1 )
for ( boost : : filesystem : : path trustedDir : trustedDirs )
{
if ( wolfSSL_CTX_load_verify_locations ( tlsCtx , NULL , trustedDir . string ( ) . c_str ( ) ) = = 1 ) {
trustedPathsNum + + ;
}
}
if ( rootCertsNum = = 0 & & trustedPathsNum = = 0 )
if ( rootCertsNum = = 0 & & trustedPathsNum = = 0 ) {
LogPrintf ( " TLS: WARNING: %s: %s: failed to set up verified certificates. It will be impossible to verify peer certificates. \n " , __FILE__ , __func__ ) ;
}
SSL_CTX_set_verify ( tlsCtx , SSL_VERIFY_PEER , tlsCertVerificationCallback ) ;
wolf SSL_CTX_set_verify( tlsCtx , WOLF SSL_VERIFY_PEER, tlsCertVerificationCallback ) ;
if ( SSL_CTX_use_certificate_file ( tlsCtx , certificateFile . string ( ) . c_str ( ) , SSL_FILETYPE_PEM ) > 0 ) {
if ( SSL_CTX_use_PrivateKey_file ( tlsCtx , privateKeyFile . string ( ) . c_str ( ) , SSL_FILETYPE_PEM ) > 0 ) {
if ( SSL_CTX_check_private_key ( tlsCtx ) ) {
if ( wolf SSL_CTX_use_certificate_file( tlsCtx , certificateFile . string ( ) . c_str ( ) , WOLF SSL_FILETYPE_PEM) > 0 ) {
if ( wolf SSL_CTX_use_PrivateKey_file( tlsCtx , privateKeyFile . string ( ) . c_str ( ) , WOLF SSL_FILETYPE_PEM) > 0 ) {
if ( wolf SSL_CTX_check_private_key( tlsCtx ) ) {
bInitialized = true ;
} else {
LogPrintf ( " TLS: ERROR: %s: %s: private key does not match the certificate public key \n " , __FILE__ , __func__ ) ;
}
} else
LogPrintf ( " TLS: ERROR: %s: %s: failed to use privateKey file \n " , __FILE__ , __func__ ) ;
} else {
LogPrintf ( " TLS: ERROR: %s: %s: failed to use privateKey file \n " , __FILE__ , __func__ ) ;
}
} else {
LogPrintf ( " TLS: ERROR: %s: %s: failed to use certificate file \n " , __FILE__ , __func__ ) ;
ERR_print _errors_fp ( stderr ) ;
wolfSSL_ ERR_dum p_errors_fp( stderr ) ;
}
} else {
LogPrintf ( " TLS: ERROR: %s: %s: failed to create TLS context \n " , __FILE__ , __func__ ) ;
@ -474,7 +443,7 @@ SSL_CTX* TLSManager::initCtx(
if ( ! bInitialized ) {
if ( tlsCtx ) {
SSL_CTX_free ( tlsCtx ) ;
wolf SSL_CTX_free( tlsCtx ) ;
tlsCtx = NULL ;
}
}
@ -524,18 +493,18 @@ bool TLSManager::prepareCredentials()
* @ param hSocket the TLS socket .
* @ param addr incoming address .
* @ param tls_ctx_server TLS server context .
* @ return SSL * returns pointer to the ssl object if successful , otherwise returns NULL
* @ return WOLF SSL* returns pointer to the ssl object if successful , otherwise returns NULL
*/
SSL * TLSManager : : accept ( SOCKET hSocket , const CAddress & addr , unsigned long & err_code )
WOLF SSL* TLSManager : : accept ( SOCKET hSocket , const CAddress & addr , unsigned long & err_code )
{
LogPrint ( " tls " , " TLS: accepting connection from %s (tid = %X) \n " , addr . ToString ( ) , pthread_self ( ) ) ;
err_code = 0 ;
SSL * ssl = NULL ;
WOLF SSL* ssl = NULL ;
bool bAcceptedTLS = false ;
if ( ( ssl = SSL_new ( tls_ctx_server ) ) ) {
if ( SSL_set_fd ( ssl , hSocket ) ) {
if ( ( ssl = wolf SSL_new( tls_ctx_server ) ) ) {
if ( wolf SSL_set_fd( ssl , hSocket ) ) {
int ret = TLSManager : : waitFor ( SSL_ACCEPT , hSocket , ssl , ( DEFAULT_CONNECT_TIMEOUT / 1000 ) , err_code ) ;
if ( ret = = 1 )
{
@ -545,20 +514,20 @@ SSL* TLSManager::accept(SOCKET hSocket, const CAddress& addr, unsigned long& err
}
else
{
err_code = ERR_get_error ( ) ;
const char * error_str = ERR_error_string ( err_code , NULL ) ;
err_code = wolfSSL_ ERR_get_error( ) ;
const char * error_str = wolfSSL_ ERR_error_string( err_code , NULL ) ;
LogPrint ( " tls " , " TLS: %s: %s():%d - SSL_new failed err: %s \n " ,
__FILE__ , __func__ , __LINE__ , error_str ) ;
}
if ( bAcceptedTLS ) {
LogPrintf ( " TLS: connection from %s has been accepted (tlsv = %s 0x%04x / ssl = %s 0x%x ). Using cipher: %s \n " ,
addr . ToString ( ) , SSL_get_version ( ssl ) , SSL_version ( ssl ) , OpenSSL_version ( OPENSSL_VERSION ) , OpenSSL_version_num ( ) , SSL_get_cipher ( ssl ) ) ;
addr . ToString ( ) , wolf SSL_get_version( ssl ) , wolf SSL_version( ssl ) , wolfSSL_ OpenSSL_version( ) , wolfSSL_lib_version_hex ( ) , wolf SSL_get_cipher( ssl ) ) ;
STACK_OF ( SSL_CIPHER ) * sk = SSL_get_ciphers ( ssl ) ;
for ( int i = 0 ; i < sk_SSL_CIPHER_num ( sk ) ; i + + ) {
const SSL_CIPHER * c = sk_SSL_CIPHER_value ( sk , i ) ;
LogPrint ( " tls " , " TLS: supporting cipher: %s \n " , SSL_CIPHER_get_name ( c ) ) ;
WOLFSSL_STACK * sk = wolf SSL_get_ciphers_compat ( ssl ) ;
for ( int i = 0 ; i < wolfSSL_ sk_SSL_CIPHER_num( sk ) ; i + + ) {
const WOLF SSL_CIPHER * c = wolfSSL_ sk_SSL_CIPHER_value( sk , i ) ;
LogPrint ( " tls " , " TLS: supporting cipher: %s \n " , wolf SSL_CIPHER_get_name( c ) ) ;
}
} else {
LogPrintf ( " TLS: %s: %s():%d - TLS connection from %s failed (err_code 0x%X) \n " ,
@ -663,9 +632,9 @@ int TLSManager::threadSocketHandler(CNode* pnode, fd_set& fdsetRecv, fd_set& fds
bIsSSL = ( pnode - > ssl ! = NULL ) ;
if ( bIsSSL ) {
ERR_clear_error ( ) ; // clear the error queue, otherwise we may be reading an old error that occurred previously in the current thread
nBytes = SSL_read ( pnode - > ssl , pchBuf , sizeof ( pchBuf ) ) ;
nRet = SSL_get_error ( pnode - > ssl , nBytes ) ;
wolfSSL_ ERR_clear_error( ) ; // clear the error queue, otherwise we may be reading an old error that occurred previously in the current thread
nBytes = wolf SSL_read( pnode - > ssl , pchBuf , sizeof ( pchBuf ) ) ;
nRet = wolf SSL_get_error( pnode - > ssl , nBytes ) ;
} else {
nBytes = recv ( pnode - > hSocket , pchBuf , sizeof ( pchBuf ) , MSG_DONTWAIT ) ;
nRet = WSAGetLastError ( ) ;
@ -697,7 +666,7 @@ int TLSManager::threadSocketHandler(CNode* pnode, fd_set& fdsetRecv, fd_set& fds
// error
//
if ( bIsSSL ) {
if ( nRet ! = SSL_ERROR_WANT_READ & & nRet ! = SSL_ERROR_WANT_WRITE ) // SSL_read() operation has to be repeated because of SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE (https://wiki.openssl.org/index.php/Manual:SSL_read(3)#NOTES)
if ( nRet ! = WOLF SSL_ERROR_WANT_READ & & nRet ! = WOLF SSL_ERROR_WANT_WRITE)
{
if ( ! pnode - > fDisconnect )
LogPrintf ( " TSL: ERROR: SSL_read %s \n " , ERR_error_string ( nRet , NULL ) ) ;
@ -747,10 +716,10 @@ bool TLSManager::initialize()
// Initialization routines for the OpenSSL library
//
SSL_load_error_strings ( ) ;
ERR_load_crypto_strings ( ) ;
OpenSSL_add_ssl_algorithms ( ) ; // OpenSSL_add_ssl_algorithms() always returns "1", so it is safe to discard the return value.
wolf SSL_load_error_strings( ) ;
wolfSSL_ ERR_load_crypto_strings( ) ;
wolfSSL_library_init ( ) ;
namespace fs = boost : : filesystem ;
fs : : path certFile = GetArg ( " -tlscertpath " , " " ) ;
if ( ! fs : : exists ( certFile ) )
@ -784,7 +753,7 @@ bool TLSManager::initialize()
bInitializationStatus = true ;
} else {
LogPrintf ( " TLS: ERROR: %s: %s: failed to initialize TLS client context \n " , __FILE__ , __func__ ) ;
SSL_CTX_free ( tls_ctx_server ) ;
wolf SSL_CTX_free ( tls_ctx_server ) ;
}
} else {
LogPrintf ( " TLS: ERROR: %s: %s: failed to initialize TLS server context \n " , __FILE__ , __func__ ) ;