diff --git a/Config.cpp b/Config.cpp index 8d42895a..d7cef879 100644 --- a/Config.cpp +++ b/Config.cpp @@ -131,6 +131,11 @@ namespace config { #endif ; + options_description limits("Limits options"); + limits.add_options() + ("limits.transittunnels", value()->default_value(2500), "Maximum active transit sessions (default:2500)") + ; + options_description httpserver("HTTP Server options"); httpserver.add_options() ("http.enabled", value()->default_value(true), "Enable or disable webconsole") @@ -180,14 +185,27 @@ namespace config { ("i2pcontrol.key", value()->default_value("i2pcontrol.key.pem"), "I2PCP connection cerificate key") ; + options_description precomputation("Precomputation options"); + precomputation.add_options() + ("precomputation.elgamal", +#if defined(__x86_64__) + value()->default_value(false), +#else + value()->default_value(true), +#endif + "Enable or disable elgamal precomputation table") + ; + m_OptionsDesc .add(general) + .add(limits) .add(httpserver) .add(httpproxy) .add(socksproxy) .add(sam) .add(bob) .add(i2pcontrol) + .add(precomputation) ; } diff --git a/Crypto.cpp b/Crypto.cpp index 0ec0f020..742296f5 100644 --- a/Crypto.cpp +++ b/Crypto.cpp @@ -148,11 +148,85 @@ namespace crypto // DH/ElGamal const int ELGAMAL_SHORT_EXPONENT_NUM_BITS = 226; + const int ELGAMAL_SHORT_EXPONENT_NUM_BYTES = ELGAMAL_SHORT_EXPONENT_NUM_BITS/8+1; const int ELGAMAL_FULL_EXPONENT_NUM_BITS = 2048; - + const int ELGAMAL_FULL_EXPONENT_NUM_BYTES = ELGAMAL_FULL_EXPONENT_NUM_BITS/8; + #define elgp GetCryptoConstants ().elgp #define elgg GetCryptoConstants ().elgg + static BN_MONT_CTX * g_MontCtx = nullptr; + static void PrecalculateElggTable (BIGNUM * table[][255], int len) // table is len's array of array of 255 bignums + { + if (len <= 0) return; + BN_CTX * ctx = BN_CTX_new (); + g_MontCtx = BN_MONT_CTX_new (); + BN_MONT_CTX_set (g_MontCtx, elgp, ctx); + auto montCtx = BN_MONT_CTX_new (); + BN_MONT_CTX_copy (montCtx, g_MontCtx); + for (int i = 0; i < len; i++) + { + table[i][0] = BN_new (); + if (!i) + BN_to_montgomery (table[0][0], elgg, montCtx, ctx); + else + BN_mod_mul_montgomery (table[i][0], table[i-1][254], table[i-1][0], montCtx, ctx); + for (int j = 1; j < 255; j++) + { + table[i][j] = BN_new (); + BN_mod_mul_montgomery (table[i][j], table[i][j-1], table[i][0], montCtx, ctx); + } + } + BN_MONT_CTX_free (montCtx); + BN_CTX_free (ctx); + } + + static void DestroyElggTable (BIGNUM * table[][255], int len) + { + for (int i = 0; i < len; i++) + for (int j = 0; j < 255; j++) + { + BN_free (table[i][j]); + table[i][j] = nullptr; + } + BN_MONT_CTX_free (g_MontCtx); + } + + static BIGNUM * ElggPow (const uint8_t * exp, int len, BIGNUM * table[][255], BN_CTX * ctx) + // exp is in Big Endian + { + if (len <= 0) return nullptr; + auto montCtx = BN_MONT_CTX_new (); + BN_MONT_CTX_copy (montCtx, g_MontCtx); + BIGNUM * res = nullptr; + for (int i = 0; i < len; i++) + { + if (res) + { + if (exp[i]) + BN_mod_mul_montgomery (res, res, table[len-1-i][exp[i]-1], montCtx, ctx); + } + else if (exp[i]) + res = BN_dup (table[len-i-1][exp[i]-1]); + } + if (res) + BN_from_montgomery (res, res, montCtx, ctx); + BN_MONT_CTX_free (montCtx); + return res; + } + + static BIGNUM * ElggPow (const BIGNUM * exp, BIGNUM * table[][255], BN_CTX * ctx) + { + auto len = BN_num_bytes (exp); + uint8_t * buf = new uint8_t[len]; + BN_bn2bin (exp, buf); + auto ret = ElggPow (buf, len, table, ctx); + delete[] buf; + return ret; + } + + static BIGNUM * (* g_ElggTable)[255] = nullptr; + // DH DHKeys::DHKeys (): m_IsUpdated (true) @@ -173,11 +247,23 @@ namespace crypto { if (m_DH->priv_key) { BN_free (m_DH->priv_key); m_DH->priv_key = NULL; }; if (m_DH->pub_key) { BN_free (m_DH->pub_key); m_DH->pub_key = NULL; }; -#if !defined(__x86_64__) // use short exponent for non x64 +#if !defined(__x86_64__) // use short exponent for non x64 m_DH->priv_key = BN_new (); - BN_rand (m_DH->priv_key, ELGAMAL_SHORT_EXPONENT_NUM_BITS, 0, 1); -#endif - DH_generate_key (m_DH); + BN_rand (m_DH->priv_key, ELGAMAL_SHORT_EXPONENT_NUM_BITS, 0, 1); +#endif + if (g_ElggTable) + { +#if defined(__x86_64__) + m_DH->priv_key = BN_new (); + BN_rand (m_DH->priv_key, ELGAMAL_FULL_EXPONENT_NUM_BITS, 0, 1); +#endif + auto ctx = BN_CTX_new (); + m_DH->pub_key = ElggPow (m_DH->priv_key, g_ElggTable, ctx); + BN_CTX_free (ctx); + } + else + DH_generate_key (m_DH); + if (priv) bn2buf (m_DH->priv_key, priv, 256); if (pub) bn2buf (m_DH->pub_key, pub, 256); m_IsUpdated = true; @@ -212,10 +298,14 @@ namespace crypto BN_rand (k, ELGAMAL_FULL_EXPONENT_NUM_BITS, -1, 1); // full exponent for x64 #else BN_rand (k, ELGAMAL_SHORT_EXPONENT_NUM_BITS, -1, 1); // short exponent of 226 bits -#endif - // caulculate a +#endif + // calculate a a = BN_new (); - BN_mod_exp (a, elgg, k, elgp, ctx); + if (g_ElggTable) + a = ElggPow (k, g_ElggTable, ctx); + else + BN_mod_exp (a, elgg, k, elgp, ctx); + BIGNUM * y = BN_new (); BN_bin2bn (key, 256, y); // calculate b1 @@ -709,17 +799,38 @@ namespace crypto } }*/ - void InitCrypto () + void InitCrypto (bool precomputation) { SSL_library_init (); /* auto numLocks = CRYPTO_num_locks(); for (int i = 0; i < numLocks; i++) m_OpenSSLMutexes.emplace_back (new std::mutex); CRYPTO_set_locking_callback (OpensslLockingCallback);*/ + if (precomputation) + { +#if defined(__x86_64__) + g_ElggTable = new BIGNUM * [ELGAMAL_FULL_EXPONENT_NUM_BYTES][255]; + PrecalculateElggTable (g_ElggTable, ELGAMAL_FULL_EXPONENT_NUM_BYTES); +#else + g_ElggTable = new BIGNUM * [ELGAMAL_SHORT_EXPONENT_NUM_BYTES][255]; + PrecalculateElggTable (g_ElggTable, ELGAMAL_SHORT_EXPONENT_NUM_BYTES); +#endif + } } void TerminateCrypto () { + if (g_ElggTable) + { + DestroyElggTable (g_ElggTable, +#if defined(__x86_64__) + ELGAMAL_FULL_EXPONENT_NUM_BYTES +#else + ELGAMAL_SHORT_EXPONENT_NUM_BYTES +#endif + ); + delete[] g_ElggTable; g_ElggTable = nullptr; + } /* CRYPTO_set_locking_callback (nullptr); m_OpenSSLMutexes.clear ();*/ } diff --git a/Crypto.h b/Crypto.h index e633f8bf..e333940e 100644 --- a/Crypto.h +++ b/Crypto.h @@ -273,7 +273,7 @@ namespace crypto #endif }; - void InitCrypto (); + void InitCrypto (bool precomputation); void TerminateCrypto (); } } diff --git a/Daemon.cpp b/Daemon.cpp index f15fe3e3..81bbcdd5 100644 --- a/Daemon.cpp +++ b/Daemon.cpp @@ -117,7 +117,8 @@ namespace i2p LogPrint(eLogDebug, "FS: main config file: ", config); LogPrint(eLogDebug, "FS: data directory: ", datadir); - i2p::crypto::InitCrypto (); + bool precomputation; i2p::config::GetOption("precomputation.elgamal", precomputation); + i2p::crypto::InitCrypto (precomputation); i2p::context.Init (); uint16_t port; i2p::config::GetOption("port", port); @@ -140,6 +141,8 @@ namespace i2p i2p::context.SetSupportsV6 (ipv6); i2p::context.SetSupportsV4 (ipv4); i2p::context.SetAcceptsTunnels (!transit); + uint16_t transitTunnels; i2p::config::GetOption("limits.transittunnels", transitTunnels); + SetMaxNumTransitTunnels (transitTunnels); bool isFloodfill; i2p::config::GetOption("floodfill", isFloodfill); if (isFloodfill) { diff --git a/HTTPServer.cpp b/HTTPServer.cpp index 06fabc31..6c2c6112 100644 --- a/HTTPServer.cpp +++ b/HTTPServer.cpp @@ -1,7 +1,6 @@ #include #include #include -#include #include #include "Base.h" #include "FS.h" @@ -24,7 +23,6 @@ namespace i2p { namespace util { - const std::string HTTPConnection::itoopieImage = "\"ICToopie HTTPConnection::reply::to_buffers(int status) { std::vector buffers; @@ -237,7 +234,7 @@ namespace util default: status_string += "WTF"; } buffers.push_back(boost::asio::buffer(status_string, status_string.size())); - buffers.push_back(boost::asio::buffer(misc_strings::crlf)); + buffers.push_back(boost::asio::buffer(misc_strings::crlf)); for (std::size_t i = 0; i < headers.size(); ++i) { @@ -831,7 +828,7 @@ namespace util if (!i2p::client::context.GetAddressBook ().GetIdentHash (address, destination)) { LogPrint (eLogWarning, "HTTPServer: Unknown address ", address); - SendReply ("" + itoopieImage + "
\r\nUnknown address " + address + "", 404); + SendError ("Unknown address " + address); return; } @@ -855,11 +852,13 @@ namespace util if (ecode != boost::asio::error::operation_aborted) { auto leaseSet = i2p::client::context.GetSharedLocalDestination ()->FindLeaseSet (destination); - if (leaseSet && !leaseSet->IsExpired ()) + if (leaseSet && !leaseSet->IsExpired ()) { SendToDestination (leaseSet, port, buf, len); - else - // still no LeaseSet - SendReply (leaseSet ? "" + itoopieImage + "
\r\nLeases expired" : "" + itoopieImage + "LeaseSet not found", 504); + } else if (leaseSet) { + SendError ("LeaseSet expired"); + } else { + SendError ("LeaseSet not found"); + } } } @@ -893,7 +892,7 @@ namespace util else { if (ecode == boost::asio::error::timed_out) - SendReply ("" + itoopieImage + "
\r\nNot responding", 504); + SendError ("Host not responding"); else if (ecode != boost::asio::error::operation_aborted) Terminate (); } @@ -911,7 +910,7 @@ namespace util m_Reply.headers[0].name = "Date"; m_Reply.headers[0].value = std::string(time_buff); m_Reply.headers[1].name = "Content-Length"; - m_Reply.headers[1].value = boost::lexical_cast(m_Reply.content.size()); + m_Reply.headers[1].value = std::to_string(m_Reply.content.size()); m_Reply.headers[2].name = "Content-Type"; m_Reply.headers[2].value = "text/html"; } @@ -920,6 +919,11 @@ namespace util std::bind (&HTTPConnection::HandleWriteReply, shared_from_this (), std::placeholders::_1)); } + void HTTPConnection::SendError(const std::string& content) + { + SendReply ("" + itoopieImage + "
\r\n" + content + "", 504); + } + HTTPServer::HTTPServer (const std::string& address, int port): m_Thread (nullptr), m_Work (m_Service), m_Acceptor (m_Service, boost::asio::ip::tcp::endpoint (boost::asio::ip::address::from_string(address), port)) @@ -978,6 +982,3 @@ namespace util } } } - - - diff --git a/HTTPServer.h b/HTTPServer.h index f70e27dc..66083d85 100644 --- a/HTTPServer.h +++ b/HTTPServer.h @@ -59,6 +59,7 @@ namespace util void HandleWriteReply(const boost::system::error_code& ecode); void HandleWrite (const boost::system::error_code& ecode); void SendReply (const std::string& content, int status = 200); + void SendError (const std::string& message); void HandleRequest (const std::string& address); void HandleCommand (const std::string& command, std::stringstream& s); diff --git a/I2NPProtocol.cpp b/I2NPProtocol.cpp index 7cebf96a..9674fdca 100644 --- a/I2NPProtocol.cpp +++ b/I2NPProtocol.cpp @@ -286,6 +286,16 @@ namespace i2p return !msg->GetPayload ()[DATABASE_STORE_TYPE_OFFSET]; // 0- RouterInfo } + static uint16_t g_MaxNumTransitTunnels = DEFAULT_MAX_NUM_TRANSIT_TUNNELS; // TODO: + void SetMaxNumTransitTunnels (uint16_t maxNumTransitTunnels) + { + if (maxNumTransitTunnels > 0 && maxNumTransitTunnels <= 10000 && g_MaxNumTransitTunnels != maxNumTransitTunnels) + { + LogPrint (eLogDebug, "I2NP: Max number of transit tunnels set to ", maxNumTransitTunnels); + g_MaxNumTransitTunnels = maxNumTransitTunnels; + } + } + bool HandleBuildRequestRecords (int num, uint8_t * records, uint8_t * clearText) { for (int i = 0; i < num; i++) @@ -298,7 +308,7 @@ namespace i2p i2p::crypto::ElGamalDecrypt (i2p::context.GetEncryptionPrivateKey (), record + BUILD_REQUEST_RECORD_ENCRYPTED_OFFSET, clearText); // replace record to reply if (i2p::context.AcceptsTunnels () && - i2p::tunnel::tunnels.GetTransitTunnels ().size () <= MAX_NUM_TRANSIT_TUNNELS && + i2p::tunnel::tunnels.GetTransitTunnels ().size () <= g_MaxNumTransitTunnels && !i2p::transport::transports.IsBandwidthExceeded ()) { auto transitTunnel = i2p::tunnel::CreateTransitTunnel ( diff --git a/I2NPProtocol.h b/I2NPProtocol.h index 6450e958..cf8f4266 100644 --- a/I2NPProtocol.h +++ b/I2NPProtocol.h @@ -97,8 +97,6 @@ namespace i2p const uint8_t DATABASE_LOOKUP_TYPE_ROUTERINFO_LOOKUP = 0x08; // 1000 const uint8_t DATABASE_LOOKUP_TYPE_EXPLORATORY_LOOKUP = 0x0C; // 1100 - const unsigned int MAX_NUM_TRANSIT_TUNNELS = 2500; - namespace tunnel { class InboundTunnel; @@ -259,6 +257,9 @@ namespace tunnel std::vector > m_TunnelMsgs, m_TunnelGatewayMsgs; }; + + const uint16_t DEFAULT_MAX_NUM_TRANSIT_TUNNELS = 2500; + void SetMaxNumTransitTunnels (uint16_t maxNumTransitTunnels); } #endif diff --git a/README.md b/README.md index 4f167754..b985abf4 100644 --- a/README.md +++ b/README.md @@ -15,14 +15,11 @@ Donations BTC: 1K7Ds6KUeR8ya287UC4rYTjvC96vXyZbDY LTC: LKQirrYrDeTuAPnpYq5y7LVKtywfkkHi59 ANC: AQJYweYYUqM1nVfLqfoSMpUMfzxvS4Xd7z +DOGE: DNXLQKziRPAsD9H3DFNjk4fLQrdaSX893Y -Downloads ------------- - -Official binary releases could be found at: -http://i2pd.website/releases/ -older releases -http://download.i2p.io/purplei2p/i2pd/releases/ +Documentation: +-------------- +http://i2pd.readthedocs.org Supported OS ------------ diff --git a/TunnelEndpoint.cpp b/TunnelEndpoint.cpp index a3907ce5..842b624f 100644 --- a/TunnelEndpoint.cpp +++ b/TunnelEndpoint.cpp @@ -119,7 +119,7 @@ namespace tunnel if (ret.second) HandleOutOfSequenceFragment (msgID, ret.first->second); else - LogPrint (eLogError, "TunnelMessage: Incomplete message ", msgID, "already exists"); + LogPrint (eLogError, "TunnelMessage: Incomplete message ", msgID, " already exists"); } else { diff --git a/Win32/Resource.rc b/Win32/Resource.rc index bdc532e9..c885c044 100644 --- a/Win32/Resource.rc +++ b/Win32/Resource.rc @@ -52,8 +52,8 @@ END // Icon with lowest ID value placed first to ensure application icon // remains consistent on all systems. -//MAINICON ICON "ictoopie.ico" -MAINICON ICON "anke.ico" +MAINICON ICON "ictoopie.ico" +//MAINICON ICON "anke.ico" MASCOT BITMAP "Anke_700px.bmp" diff --git a/api.cpp b/api.cpp index 64648743..1828901b 100644 --- a/api.cpp +++ b/api.cpp @@ -28,7 +28,11 @@ namespace api i2p::fs::DetectDataDir(datadir, false); i2p::fs::Init(); - i2p::crypto::InitCrypto (); +#if defined(__x86_64__) + i2p::crypto::InitCrypto (false); +#else + i2p::crypto::InitCrypto (true); +#endif i2p::context.Init (); } diff --git a/docs/configuration.md b/docs/configuration.md index ac5c4684..2a639be3 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -59,7 +59,11 @@ All options below still possible in cmdline, but better write it in config file: * --i2pcontrol.address= - The address to listen on (I2P control service) * --i2pcontrol.port= - Port of I2P control service. Usually 7650. I2PControl is off if not specified -* --i2pcontrol.enabled= - If I2P control is enabled. false by default +* --i2pcontrol.enabled= - If I2P control is enabled. false by default + +* --precomputation.elgamal= - Use ElGamal precomputated tables. false for x64 and true for other platforms by default + +* --limits.transittunnels= - Override maximum number of transit tunnels. 2500 by default Config files ------------