diff --git a/src/hush/tlsmanager.cpp b/src/hush/tlsmanager.cpp index 8fb8ad66d..a5fb5c2fa 100644 --- a/src/hush/tlsmanager.cpp +++ b/src/hush/tlsmanager.cpp @@ -11,6 +11,9 @@ #include "utiltls.h" using namespace std; +// store our preferred cipherlist so we can use it for debug/etc later on +std::string TLS_CIPHERLIST; + namespace hush { static WOLFSSL_EVP_PKEY *mykey; @@ -229,6 +232,7 @@ WOLFSSL* TLSManager::connect(SOCKET hSocket, const CAddress& addrConnect, unsign if (ret == 1) { bConnectedTLS = true; } else { + err_code = wolfSSL_ERR_get_error(); LogPrint("tls", "%s: timed out waiting for %s\n", __func__, addrConnect.ToString()); } } @@ -242,7 +246,11 @@ WOLFSSL* TLSManager::connect(SOCKET hSocket, const CAddress& addrConnect, unsign LogPrintf("TLS: connection to %s has been established (tlsv = %s 0x%04x / ssl = %s 0x%x ). Using cipher: %s\n", addrConnect.ToString(), wolfSSL_get_version(ssl), wolfSSL_version(ssl), wolfSSL_OpenSSL_version(), wolfSSL_lib_version_hex(), wolfSSL_get_cipher_name(ssl)); } else { - LogPrintf("TLS: %s: %s():%d - TLS connection to %s timed out\n", __FILE__, __func__, __LINE__, addrConnect.ToString(), err_code); + if(err_code) { + LogPrintf("TLS: %s: %s():%d - TLS connection to %s failed with err_code=0x%X\n", __FILE__, __func__, __LINE__, addrConnect.ToString(), err_code); + } else { + LogPrintf("TLS: %s: %s():%d - TLS connection to %s timed out\n", __FILE__, __func__, __LINE__, addrConnect.ToString()); + } if (ssl) { wolfSSL_free(ssl); @@ -270,7 +278,7 @@ WOLFSSL_CTX* TLSManager::initCtx(TLSContextType ctxType) return NULL; } - bool bInitialized = false; + bool bInitialized = false; WOLFSSL_CTX* tlsCtx = NULL; byte *pem; @@ -279,7 +287,7 @@ WOLFSSL_CTX* TLSManager::initCtx(TLSContextType ctxType) if ((tlsCtx = wolfSSL_CTX_new(ctxType == SERVER_CONTEXT ? wolfTLSv1_3_server_method() : wolfTLSv1_3_client_method()))) { wolfSSL_CTX_set_mode(tlsCtx, SSL_MODE_AUTO_RETRY); - // Disable TLS < 1.3 ... imho redundant, because v1.3 is required via method + // Disable TLS < 1.3, just in case 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__); @@ -293,12 +301,15 @@ WOLFSSL_CTX* TLSManager::initCtx(TLSContextType ctxType) if(GetRand(100) > 50) { if (wolfSSL_CTX_set_cipher_list(tlsCtx, "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256")) { LogPrintf("%s: Preferring TLS_AES256-GCM-SHA384\n", __func__); + TLS_CIPHERLIST = "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256"; } else { LogPrintf("%s: Setting preferred cipher failed !!!\n", __func__); } } else { if (wolfSSL_CTX_set_cipher_list(tlsCtx, "TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384")) { - LogPrintf("%s: Preferring TLS_AES256-GCM-SHA384\n", __func__); + LogPrintf("%s: Preferring TLS_XCHACHA20_POLY1305\n", __func__); + // WolfSSL 4.6.0 added xchacha but calls it the same ciphersuite, which causes compatibility issues + TLS_CIPHERLIST = "TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384"; } else { LogPrintf("%s: Setting preferred cipher failed !!!\n", __func__); } @@ -359,11 +370,10 @@ WOLFSSL_CTX* TLSManager::initCtx(TLSContextType ctxType) */ bool TLSManager::prepareCredentials() { - mykey = NULL; + mykey = NULL; mycert = NULL; // Generating key and the self-signed certificate for it - // mykey = GenerateEcKey(); if (mykey) { mycert = GenerateCertificate(mykey); @@ -579,15 +589,12 @@ int TLSManager::threadSocketHandler(CNode* pnode, fd_set& fdsetRecv, fd_set& fds __FILE__, __func__, __LINE__, error_str); } // socket closed gracefully (peer disconnected) - // if (!pnode->fDisconnect) LogPrint("tls", "socket closed (%s)\n", pnode->addr.ToString()); pnode->CloseSocketDisconnect(); - } else if (nBytes < 0) { // error - // if (bIsSSL) { if (nRet != WOLFSSL_ERROR_WANT_READ && nRet != WOLFSSL_ERROR_WANT_WRITE) { @@ -602,7 +609,6 @@ int TLSManager::threadSocketHandler(CNode* pnode, fd_set& fdsetRecv, fd_set& fds } else { // preventive measure from exhausting CPU usage - // MilliSleep(1); // 1 msec } } else { @@ -617,9 +623,7 @@ int TLSManager::threadSocketHandler(CNode* pnode, fd_set& fdsetRecv, fd_set& fds } } - // // Send - // if (sendSet) { TRY_LOCK(pnode->cs_vSend, lockSend); if (lockSend) @@ -640,17 +644,13 @@ bool TLSManager::initialize() bool bInitializationStatus = false; // Initialization routines for the WolfSSL library - // wolfSSL_load_error_strings(); wolfSSL_ERR_load_crypto_strings(); wolfSSL_library_init(); // Initialization of the server and client contexts - // - if ((tls_ctx_server = TLSManager::initCtx(SERVER_CONTEXT))) - { - if ((tls_ctx_client = TLSManager::initCtx(CLIENT_CONTEXT))) - { + if ((tls_ctx_server = TLSManager::initCtx(SERVER_CONTEXT))) { + if ((tls_ctx_client = TLSManager::initCtx(CLIENT_CONTEXT))) { LogPrint("tls", "TLS: contexts are initialized\n"); bInitializationStatus = true; } else { diff --git a/src/main.cpp b/src/main.cpp index 19c365b08..fb2bf91ec 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -577,8 +577,8 @@ bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats) { CNodeState *state = State(nodeid); if (state == NULL) return false; - stats.nMisbehavior = state->nMisbehavior; - stats.nSyncHeight = state->pindexBestKnownBlock ? state->pindexBestKnownBlock->GetHeight() : -1; + stats.nMisbehavior = state->nMisbehavior; + stats.nSyncHeight = state->pindexBestKnownBlock ? state->pindexBestKnownBlock->GetHeight() : -1; stats.nCommonHeight = state->pindexLastCommonBlock ? state->pindexLastCommonBlock->GetHeight() : -1; BOOST_FOREACH(const QueuedBlock& queue, state->vBlocksInFlight) { if (queue.pindex) diff --git a/src/net.cpp b/src/net.cpp index 0c1711dce..bfacabe81 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -394,8 +394,7 @@ CNode* FindNode(const CService& addr) return NULL; } -CNode* ConnectNode(CAddress addrConnect, const char *pszDest) -{ +CNode* ConnectNode(CAddress addrConnect, const char *pszDest) { if (pszDest == NULL) { if (IsLocal(addrConnect)) return NULL; @@ -429,7 +428,6 @@ CNode* ConnectNode(CAddress addrConnect, const char *pszDest) WOLFSSL *ssl = NULL; -#ifdef USE_TLS /* TCP connection is ready. Do client side SSL. */ unsigned long err_code = 0; ssl = tlsmanager.connect(hSocket, addrConnect, err_code); @@ -438,11 +436,10 @@ CNode* ConnectNode(CAddress addrConnect, const char *pszDest) CloseSocket(hSocket); return NULL; } - -#endif // USE_TLS // Add node - CNode* pnode = new CNode(hSocket, addrConnect, pszDest ? pszDest : "", false, ssl); + CNode* pnode = new CNode(hSocket, addrConnect, pszDest ? pszDest : "", false, ssl); + pnode->tls_cipher = wolfSSL_get_cipher_name(ssl); pnode->AddRef(); { @@ -619,23 +616,24 @@ void CNode::AddAllowlistedRange(const CSubNet &subnet) { void CNode::copyStats(CNodeStats &stats, const std::vector &m_asmap) { - stats.nodeid = this->GetId(); - stats.nServices = nServices; - stats.addr = addr; - // stats.addrBind = addrBind; - stats.m_mapped_as = addr.GetMappedAS(m_asmap); - stats.nLastSend = nLastSend; - stats.nLastRecv = nLastRecv; - stats.nTimeConnected = nTimeConnected; - stats.nTimeOffset = nTimeOffset; - stats.addrName = addrName; - stats.nVersion = nVersion; - stats.cleanSubVer = cleanSubVer; - stats.fInbound = fInbound; + stats.nodeid = this->GetId(); + stats.nServices = nServices; + stats.addr = addr; + // stats.addrBind = addrBind; + stats.m_mapped_as = addr.GetMappedAS(m_asmap); + stats.nLastSend = nLastSend; + stats.nLastRecv = nLastRecv; + stats.nTimeConnected = nTimeConnected; + stats.nTimeOffset = nTimeOffset; + stats.addrName = addrName; + stats.nVersion = nVersion; + stats.cleanSubVer = cleanSubVer; + stats.fInbound = fInbound; stats.nStartingHeight = nStartingHeight; - stats.nSendBytes = nSendBytes; - stats.nRecvBytes = nRecvBytes; - stats.fAllowlisted = fAllowlisted; + stats.nSendBytes = nSendBytes; + stats.nRecvBytes = nRecvBytes; + stats.fAllowlisted = fAllowlisted; + stats.tls_cipher = tls_cipher; // It is common for nodes with good ping times to suddenly become lagged, // due to a new block arriving or other large transfer. @@ -1103,7 +1101,6 @@ static void AcceptConnection(const ListenSocket& hListenSocket) { SetSocketNonBlocking(hSocket, true); -#ifdef USE_TLS /* TCP connection is ready. Do server side TLS */ unsigned long err_code = 0; ssl = tlsmanager.accept( hSocket, addr, err_code); @@ -1114,13 +1111,12 @@ static void AcceptConnection(const ListenSocket& hListenSocket) { return; } -#endif // USE_TLS - CNode* pnode = new CNode(hSocket, addr, "", true, ssl); pnode->AddRef(); pnode->fAllowlisted = allowlisted; + pnode->tls_cipher = wolfSSL_get_cipher_name(ssl); - LogPrint("net", "connection from %s accepted\n", addr.ToString()); + LogPrint("net", "connection from %s accepted using cipher %s\n", addr.ToString(), pnode->tls_cipher); { LOCK(cs_vNodes); diff --git a/src/net.h b/src/net.h index 7f97632b0..904248163 100644 --- a/src/net.h +++ b/src/net.h @@ -208,6 +208,7 @@ public: uint64_t nServices; bool fTLSEstablished; bool fTLSVerified; + std::string tls_cipher; int64_t nLastSend; int64_t nLastRecv; int64_t nTimeConnected; @@ -279,8 +280,9 @@ public: class CNode { public: - // OpenSSL + // TLS via WolfSSL SSL *ssl; + std::string tls_cipher; // socket uint64_t nServices; diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index b32db9118..8d1e1a66e 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -90,6 +90,8 @@ UniValue getpeerinfo(const UniValue& params, bool fHelp, const CPubKey& mypk) " \"addrlocal\":\"ip:port\", (string) local address\n" " \"services\":\"xxxxxxxxxxxxxxxx\", (string) The services offered\n" " \"tls_established\": true:false, (boolean) Status of TLS connection\n" + " \"tls_verified\": true:false, (boolean) Status of TLS verification\n" + " \"tls_cipher\": \"XXX\", (string) TLS cipher used for this connection\n" " \"lastsend\": ttt, (numeric) The time in seconds since epoch (Jan 1 1970 GMT) of the last send\n" " \"lastrecv\": ttt, (numeric) The time in seconds since epoch (Jan 1 1970 GMT) of the last receive\n" " \"bytessent\": n, (numeric) The total bytes sent\n" @@ -139,6 +141,8 @@ UniValue getpeerinfo(const UniValue& params, bool fHelp, const CPubKey& mypk) } obj.push_back(Pair("services", strprintf("%016x", stats.nServices))); obj.push_back(Pair("tls_established", stats.fTLSEstablished)); + obj.push_back(Pair("tls_verified", stats.fTLSVerified)); + obj.push_back(Pair("tls_cipher", stats.tls_cipher)); obj.push_back(Pair("lastsend", stats.nLastSend)); obj.push_back(Pair("lastrecv", stats.nLastRecv)); obj.push_back(Pair("bytessent", stats.nSendBytes));