Merge pull request #478 from PurpleI2P/openssl

recent changes
This commit is contained in:
orignal 2016-04-22 12:49:42 -04:00
commit 799d25925a
10 changed files with 108 additions and 44 deletions

View file

@ -131,6 +131,11 @@ namespace config {
#endif #endif
; ;
options_description limits("Limits options");
limits.add_options()
("limits.transittunnels", value<uint16_t>()->default_value(2500), "Maximum active transit sessions (default:2500)")
;
options_description httpserver("HTTP Server options"); options_description httpserver("HTTP Server options");
httpserver.add_options() httpserver.add_options()
("http.enabled", value<bool>()->default_value(true), "Enable or disable webconsole") ("http.enabled", value<bool>()->default_value(true), "Enable or disable webconsole")
@ -180,14 +185,27 @@ namespace config {
("i2pcontrol.key", value<std::string>()->default_value("i2pcontrol.key.pem"), "I2PCP connection cerificate key") ("i2pcontrol.key", value<std::string>()->default_value("i2pcontrol.key.pem"), "I2PCP connection cerificate key")
; ;
options_description precomputation("Precomputation options");
precomputation.add_options()
("precomputation.elgamal",
#if defined(__x86_64__)
value<bool>()->default_value(false),
#else
value<bool>()->default_value(true),
#endif
"Enable or disable elgamal precomputation table")
;
m_OptionsDesc m_OptionsDesc
.add(general) .add(general)
.add(limits)
.add(httpserver) .add(httpserver)
.add(httpproxy) .add(httpproxy)
.add(socksproxy) .add(socksproxy)
.add(sam) .add(sam)
.add(bob) .add(bob)
.add(i2pcontrol) .add(i2pcontrol)
.add(precomputation)
; ;
} }

View file

@ -150,12 +150,11 @@ namespace crypto
const int ELGAMAL_SHORT_EXPONENT_NUM_BITS = 226; 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_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_BITS = 2048;
const int ELGAMAL_FULL_EXPONENT_NUM_BYTES = ELGAMAL_FULL_EXPONENT_NUM_BITS/8;
#define elgp GetCryptoConstants ().elgp #define elgp GetCryptoConstants ().elgp
#define elgg GetCryptoConstants ().elgg #define elgg GetCryptoConstants ().elgg
#if !defined(__x86_64__) // use precalculated table
static BN_MONT_CTX * g_MontCtx = nullptr; 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 static void PrecalculateElggTable (BIGNUM * table[][255], int len) // table is len's array of array of 255 bignums
{ {
@ -226,9 +225,7 @@ namespace crypto
return ret; return ret;
} }
BIGNUM * g_ElggTable[ELGAMAL_SHORT_EXPONENT_NUM_BYTES][255]; static BIGNUM * (* g_ElggTable)[255] = nullptr;
#endif
// DH // DH
@ -253,12 +250,20 @@ namespace crypto
#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 (); m_DH->priv_key = BN_new ();
BN_rand (m_DH->priv_key, ELGAMAL_SHORT_EXPONENT_NUM_BITS, 0, 1); BN_rand (m_DH->priv_key, ELGAMAL_SHORT_EXPONENT_NUM_BITS, 0, 1);
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);
#endif #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 (priv) bn2buf (m_DH->priv_key, priv, 256);
if (pub) bn2buf (m_DH->pub_key, pub, 256); if (pub) bn2buf (m_DH->pub_key, pub, 256);
m_IsUpdated = true; m_IsUpdated = true;
@ -291,14 +296,16 @@ namespace crypto
BIGNUM * k = BN_new (); BIGNUM * k = BN_new ();
#if defined(__x86_64__) #if defined(__x86_64__)
BN_rand (k, ELGAMAL_FULL_EXPONENT_NUM_BITS, -1, 1); // full exponent for x64 BN_rand (k, ELGAMAL_FULL_EXPONENT_NUM_BITS, -1, 1); // full exponent for x64
// calculate a
a = BN_new ();
BN_mod_exp (a, elgg, k, elgp, ctx);
#else #else
BN_rand (k, ELGAMAL_SHORT_EXPONENT_NUM_BITS, -1, 1); // short exponent of 226 bits BN_rand (k, ELGAMAL_SHORT_EXPONENT_NUM_BITS, -1, 1); // short exponent of 226 bits
// calculate a
a = ElggPow (k, g_ElggTable, ctx);
#endif #endif
// calculate a
a = BN_new ();
if (g_ElggTable)
a = ElggPow (k, g_ElggTable, ctx);
else
BN_mod_exp (a, elgg, k, elgp, ctx);
BIGNUM * y = BN_new (); BIGNUM * y = BN_new ();
BN_bin2bn (key, 256, y); BN_bin2bn (key, 256, y);
// calculate b1 // calculate b1
@ -792,23 +799,38 @@ namespace crypto
} }
}*/ }*/
void InitCrypto () void InitCrypto (bool precomputation)
{ {
SSL_library_init (); SSL_library_init ();
/* auto numLocks = CRYPTO_num_locks(); /* auto numLocks = CRYPTO_num_locks();
for (int i = 0; i < numLocks; i++) for (int i = 0; i < numLocks; i++)
m_OpenSSLMutexes.emplace_back (new std::mutex); m_OpenSSLMutexes.emplace_back (new std::mutex);
CRYPTO_set_locking_callback (OpensslLockingCallback);*/ CRYPTO_set_locking_callback (OpensslLockingCallback);*/
#if !defined(__x86_64__) if (precomputation)
PrecalculateElggTable (g_ElggTable, ELGAMAL_SHORT_EXPONENT_NUM_BYTES); {
#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 #endif
}
} }
void TerminateCrypto () void TerminateCrypto ()
{ {
#if !defined(__x86_64__) if (g_ElggTable)
DestroyElggTable (g_ElggTable, ELGAMAL_SHORT_EXPONENT_NUM_BYTES); {
DestroyElggTable (g_ElggTable,
#if defined(__x86_64__)
ELGAMAL_FULL_EXPONENT_NUM_BYTES
#else
ELGAMAL_SHORT_EXPONENT_NUM_BYTES
#endif #endif
);
delete[] g_ElggTable; g_ElggTable = nullptr;
}
/* CRYPTO_set_locking_callback (nullptr); /* CRYPTO_set_locking_callback (nullptr);
m_OpenSSLMutexes.clear ();*/ m_OpenSSLMutexes.clear ();*/
} }

View file

@ -273,7 +273,7 @@ namespace crypto
#endif #endif
}; };
void InitCrypto (); void InitCrypto (bool precomputation);
void TerminateCrypto (); void TerminateCrypto ();
} }
} }

View file

@ -117,7 +117,8 @@ namespace i2p
LogPrint(eLogDebug, "FS: main config file: ", config); LogPrint(eLogDebug, "FS: main config file: ", config);
LogPrint(eLogDebug, "FS: data directory: ", datadir); LogPrint(eLogDebug, "FS: data directory: ", datadir);
i2p::crypto::InitCrypto (); bool precomputation; i2p::config::GetOption("precomputation.elgamal", precomputation);
i2p::crypto::InitCrypto (precomputation);
i2p::context.Init (); i2p::context.Init ();
uint16_t port; i2p::config::GetOption("port", port); uint16_t port; i2p::config::GetOption("port", port);
@ -140,6 +141,8 @@ namespace i2p
i2p::context.SetSupportsV6 (ipv6); i2p::context.SetSupportsV6 (ipv6);
i2p::context.SetSupportsV4 (ipv4); i2p::context.SetSupportsV4 (ipv4);
i2p::context.SetAcceptsTunnels (!transit); i2p::context.SetAcceptsTunnels (!transit);
uint16_t transitTunnels; i2p::config::GetOption("limits.transittunnels", transitTunnels);
SetMaxNumTransitTunnels (transitTunnels);
bool isFloodfill; i2p::config::GetOption("floodfill", isFloodfill); bool isFloodfill; i2p::config::GetOption("floodfill", isFloodfill);
if (isFloodfill) { if (isFloodfill) {

View file

@ -1,7 +1,6 @@
#include <ctime> #include <ctime>
#include <iomanip> #include <iomanip>
#include <boost/bind.hpp> #include <boost/bind.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/date_time/posix_time/posix_time.hpp> #include <boost/date_time/posix_time/posix_time.hpp>
#include "Base.h" #include "Base.h"
#include "FS.h" #include "FS.h"
@ -24,7 +23,6 @@ namespace i2p
{ {
namespace util namespace util
{ {
const std::string HTTPConnection::itoopieImage = const std::string HTTPConnection::itoopieImage =
"<img alt=\"ICToopie Icon\" src=\"data:image/png;base64," "<img alt=\"ICToopie Icon\" src=\"data:image/png;base64,"
"iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAYAAADDPmHLAAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXM" "iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAYAAADDPmHLAAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXM"
@ -206,7 +204,6 @@ namespace util
const char HTTP_COMMAND_JUMPSERVICES[] = "jumpservices="; const char HTTP_COMMAND_JUMPSERVICES[] = "jumpservices=";
const char HTTP_PARAM_ADDRESS[] = "address"; const char HTTP_PARAM_ADDRESS[] = "address";
namespace misc_strings namespace misc_strings
{ {
@ -237,7 +234,7 @@ namespace util
default: status_string += "WTF"; default: status_string += "WTF";
} }
buffers.push_back(boost::asio::buffer(status_string, status_string.size())); 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) for (std::size_t i = 0; i < headers.size(); ++i)
{ {
@ -831,7 +828,7 @@ namespace util
if (!i2p::client::context.GetAddressBook ().GetIdentHash (address, destination)) if (!i2p::client::context.GetAddressBook ().GetIdentHash (address, destination))
{ {
LogPrint (eLogWarning, "HTTPServer: Unknown address ", address); LogPrint (eLogWarning, "HTTPServer: Unknown address ", address);
SendReply ("<html>" + itoopieImage + "<br>\r\nUnknown address " + address + "</html>", 404); SendError ("Unknown address " + address);
return; return;
} }
@ -855,11 +852,13 @@ namespace util
if (ecode != boost::asio::error::operation_aborted) if (ecode != boost::asio::error::operation_aborted)
{ {
auto leaseSet = i2p::client::context.GetSharedLocalDestination ()->FindLeaseSet (destination); auto leaseSet = i2p::client::context.GetSharedLocalDestination ()->FindLeaseSet (destination);
if (leaseSet && !leaseSet->IsExpired ()) if (leaseSet && !leaseSet->IsExpired ()) {
SendToDestination (leaseSet, port, buf, len); SendToDestination (leaseSet, port, buf, len);
else } else if (leaseSet) {
// still no LeaseSet SendError ("LeaseSet expired");
SendReply (leaseSet ? "<html>" + itoopieImage + "<br>\r\nLeases expired</html>" : "<html>" + itoopieImage + "LeaseSet not found</html>", 504); } else {
SendError ("LeaseSet not found");
}
} }
} }
@ -893,7 +892,7 @@ namespace util
else else
{ {
if (ecode == boost::asio::error::timed_out) if (ecode == boost::asio::error::timed_out)
SendReply ("<html>" + itoopieImage + "<br>\r\nNot responding</html>", 504); SendError ("Host not responding");
else if (ecode != boost::asio::error::operation_aborted) else if (ecode != boost::asio::error::operation_aborted)
Terminate (); Terminate ();
} }
@ -911,7 +910,7 @@ namespace util
m_Reply.headers[0].name = "Date"; m_Reply.headers[0].name = "Date";
m_Reply.headers[0].value = std::string(time_buff); m_Reply.headers[0].value = std::string(time_buff);
m_Reply.headers[1].name = "Content-Length"; m_Reply.headers[1].name = "Content-Length";
m_Reply.headers[1].value = boost::lexical_cast<std::string>(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].name = "Content-Type";
m_Reply.headers[2].value = "text/html"; m_Reply.headers[2].value = "text/html";
} }
@ -920,6 +919,11 @@ namespace util
std::bind (&HTTPConnection::HandleWriteReply, shared_from_this (), std::placeholders::_1)); std::bind (&HTTPConnection::HandleWriteReply, shared_from_this (), std::placeholders::_1));
} }
void HTTPConnection::SendError(const std::string& content)
{
SendReply ("<html>" + itoopieImage + "<br>\r\n" + content + "</html>", 504);
}
HTTPServer::HTTPServer (const std::string& address, int port): HTTPServer::HTTPServer (const std::string& address, int port):
m_Thread (nullptr), m_Work (m_Service), m_Thread (nullptr), m_Work (m_Service),
m_Acceptor (m_Service, boost::asio::ip::tcp::endpoint (boost::asio::ip::address::from_string(address), port)) m_Acceptor (m_Service, boost::asio::ip::tcp::endpoint (boost::asio::ip::address::from_string(address), port))
@ -978,6 +982,3 @@ namespace util
} }
} }
} }

View file

@ -59,6 +59,7 @@ namespace util
void HandleWriteReply(const boost::system::error_code& ecode); void HandleWriteReply(const boost::system::error_code& ecode);
void HandleWrite (const boost::system::error_code& ecode); void HandleWrite (const boost::system::error_code& ecode);
void SendReply (const std::string& content, int status = 200); void SendReply (const std::string& content, int status = 200);
void SendError (const std::string& message);
void HandleRequest (const std::string& address); void HandleRequest (const std::string& address);
void HandleCommand (const std::string& command, std::stringstream& s); void HandleCommand (const std::string& command, std::stringstream& s);

View file

@ -286,6 +286,16 @@ namespace i2p
return !msg->GetPayload ()[DATABASE_STORE_TYPE_OFFSET]; // 0- RouterInfo 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) bool HandleBuildRequestRecords (int num, uint8_t * records, uint8_t * clearText)
{ {
for (int i = 0; i < num; i++) 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); i2p::crypto::ElGamalDecrypt (i2p::context.GetEncryptionPrivateKey (), record + BUILD_REQUEST_RECORD_ENCRYPTED_OFFSET, clearText);
// replace record to reply // replace record to reply
if (i2p::context.AcceptsTunnels () && if (i2p::context.AcceptsTunnels () &&
i2p::tunnel::tunnels.GetTransitTunnels ().size () <= MAX_NUM_TRANSIT_TUNNELS && i2p::tunnel::tunnels.GetTransitTunnels ().size () <= g_MaxNumTransitTunnels &&
!i2p::transport::transports.IsBandwidthExceeded ()) !i2p::transport::transports.IsBandwidthExceeded ())
{ {
auto transitTunnel = i2p::tunnel::CreateTransitTunnel ( auto transitTunnel = i2p::tunnel::CreateTransitTunnel (

View file

@ -97,8 +97,6 @@ namespace i2p
const uint8_t DATABASE_LOOKUP_TYPE_ROUTERINFO_LOOKUP = 0x08; // 1000 const uint8_t DATABASE_LOOKUP_TYPE_ROUTERINFO_LOOKUP = 0x08; // 1000
const uint8_t DATABASE_LOOKUP_TYPE_EXPLORATORY_LOOKUP = 0x0C; // 1100 const uint8_t DATABASE_LOOKUP_TYPE_EXPLORATORY_LOOKUP = 0x0C; // 1100
const unsigned int MAX_NUM_TRANSIT_TUNNELS = 2500;
namespace tunnel namespace tunnel
{ {
class InboundTunnel; class InboundTunnel;
@ -259,6 +257,9 @@ namespace tunnel
std::vector<std::shared_ptr<I2NPMessage> > m_TunnelMsgs, m_TunnelGatewayMsgs; std::vector<std::shared_ptr<I2NPMessage> > m_TunnelMsgs, m_TunnelGatewayMsgs;
}; };
const uint16_t DEFAULT_MAX_NUM_TRANSIT_TUNNELS = 2500;
void SetMaxNumTransitTunnels (uint16_t maxNumTransitTunnels);
} }
#endif #endif

View file

@ -28,7 +28,11 @@ namespace api
i2p::fs::DetectDataDir(datadir, false); i2p::fs::DetectDataDir(datadir, false);
i2p::fs::Init(); i2p::fs::Init();
i2p::crypto::InitCrypto (); #if defined(__x86_64__)
i2p::crypto::InitCrypto (false);
#else
i2p::crypto::InitCrypto (true);
#endif
i2p::context.Init (); i2p::context.Init ();
} }

View file

@ -61,6 +61,10 @@ All options below still possible in cmdline, but better write it in config file:
* --i2pcontrol.port= - Port of I2P control service. Usually 7650. I2PControl is off if not specified * --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 Config files
------------ ------------