diff --git a/Config.cpp b/Config.cpp index b994496b..c54b9c3f 100644 --- a/Config.cpp +++ b/Config.cpp @@ -164,7 +164,7 @@ namespace config { reseed.add_options() ("reseed.verify", value()->default_value(false), "Verify .su3 signature") ("reseed.floodfill", value()->default_value(""), "Path to router info of floodfill to reseed from") - ("reseed.file", value()->default_value(""), "Path to .su3 file") + ("reseed.file", value()->default_value(""), "Path to local .su3 file or HTTPS URL to reseed from") ("reseed.urls", value()->default_value( "https://reseed.i2p-projekt.de/," "https://i2p.mooo.com/netDb/," diff --git a/Crypto.cpp b/Crypto.cpp index f9478646..54180677 100644 --- a/Crypto.cpp +++ b/Crypto.cpp @@ -595,16 +595,16 @@ namespace crypto "jnz 1b \n" "movups %%xmm1, (%[iv]) \n" : - : [iv]"r"(&m_LastBlock), [sched]"r"(m_ECBEncryption.GetKeySchedule ()), + : [iv]"r"((uint8_t *)m_LastBlock), [sched]"r"(m_ECBEncryption.GetKeySchedule ()), [in]"r"(in), [out]"r"(out), [num]"r"(numBlocks) : "%xmm0", "%xmm1", "cc", "memory" ); #else for (int i = 0; i < numBlocks; i++) { - m_LastBlock ^= in[i]; - m_ECBEncryption.Encrypt (&m_LastBlock, &m_LastBlock); - out[i] = m_LastBlock; + *m_LastBlock.GetChipherBlock () ^= in[i]; + m_ECBEncryption.Encrypt (m_LastBlock.GetChipherBlock (), m_LastBlock.GetChipherBlock ()); + out[i] = *m_LastBlock.GetChipherBlock (); } #endif } @@ -629,7 +629,7 @@ namespace crypto "movups %%xmm0, (%[out]) \n" "movups %%xmm0, (%[iv]) \n" : - : [iv]"r"(&m_LastBlock), [sched]"r"(m_ECBEncryption.GetKeySchedule ()), + : [iv]"r"((uint8_t *)m_LastBlock), [sched]"r"(m_ECBEncryption.GetKeySchedule ()), [in]"r"(in), [out]"r"(out) : "%xmm0", "%xmm1", "memory" ); @@ -657,7 +657,7 @@ namespace crypto "jnz 1b \n" "movups %%xmm1, (%[iv]) \n" : - : [iv]"r"(&m_IV), [sched]"r"(m_ECBDecryption.GetKeySchedule ()), + : [iv]"r"((uint8_t *)m_IV), [sched]"r"(m_ECBDecryption.GetKeySchedule ()), [in]"r"(in), [out]"r"(out), [num]"r"(numBlocks) : "%xmm0", "%xmm1", "%xmm2", "cc", "memory" ); @@ -666,8 +666,8 @@ namespace crypto { ChipherBlock tmp = in[i]; m_ECBDecryption.Decrypt (in + i, out + i); - out[i] ^= m_IV; - m_IV = tmp; + out[i] ^= *m_IV.GetChipherBlock (); + *m_IV.GetChipherBlock () = tmp; } #endif } @@ -691,7 +691,7 @@ namespace crypto "pxor %%xmm1, %%xmm0 \n" "movups %%xmm0, (%[out]) \n" : - : [iv]"r"(&m_IV), [sched]"r"(m_ECBDecryption.GetKeySchedule ()), + : [iv]"r"((uint8_t *)m_IV), [sched]"r"(m_ECBDecryption.GetKeySchedule ()), [in]"r"(in), [out]"r"(out) : "%xmm0", "%xmm1", "memory" ); diff --git a/Crypto.h b/Crypto.h index 0bc1e03c..ee5f49ca 100644 --- a/Crypto.h +++ b/Crypto.h @@ -112,7 +112,9 @@ namespace crypto operator uint8_t * () { return m_Buf; }; operator const uint8_t * () const { return m_Buf; }; - + ChipherBlock * GetChipherBlock () { return (ChipherBlock *)m_Buf; }; + const ChipherBlock * GetChipherBlock () const { return (const ChipherBlock *)m_Buf; }; + private: uint8_t m_UnalignedBuffer[sz + 15]; // up to 15 bytes alignment @@ -200,10 +202,10 @@ namespace crypto { public: - CBCEncryption () { memset (m_LastBlock.buf, 0, 16); }; + CBCEncryption () { memset ((uint8_t *)m_LastBlock, 0, 16); }; void SetKey (const AESKey& key) { m_ECBEncryption.SetKey (key); }; // 32 bytes - void SetIV (const uint8_t * iv) { memcpy (m_LastBlock.buf, iv, 16); }; // 16 bytes + void SetIV (const uint8_t * iv) { memcpy ((uint8_t *)m_LastBlock, iv, 16); }; // 16 bytes void Encrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out); void Encrypt (const uint8_t * in, std::size_t len, uint8_t * out); @@ -211,7 +213,7 @@ namespace crypto private: - ChipherBlock m_LastBlock; + AESAlignedBuffer<16> m_LastBlock; ECBEncryption m_ECBEncryption; }; @@ -220,10 +222,10 @@ namespace crypto { public: - CBCDecryption () { memset (m_IV.buf, 0, 16); }; + CBCDecryption () { memset ((uint8_t *)m_IV, 0, 16); }; void SetKey (const AESKey& key) { m_ECBDecryption.SetKey (key); }; // 32 bytes - void SetIV (const uint8_t * iv) { memcpy (m_IV.buf, iv, 16); }; // 16 bytes + void SetIV (const uint8_t * iv) { memcpy ((uint8_t *)m_IV, iv, 16); }; // 16 bytes void Decrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out); void Decrypt (const uint8_t * in, std::size_t len, uint8_t * out); @@ -231,7 +233,7 @@ namespace crypto private: - ChipherBlock m_IV; + AESAlignedBuffer<16> m_IV; ECBDecryption m_ECBDecryption; }; @@ -300,7 +302,11 @@ inline void DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **p { *pr = sig->r; *ps = sig->s; } inline int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s) - { sig->r = r; sig->s = s; return 1; } + { + if (sig->r) BN_free (sig->r); + if (sig->s) BN_free (sig->s); + sig->r = r; sig->s = s; return 1; + } inline void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps) { *pr = sig->r; *ps = sig->s; } diff --git a/NTCPSession.cpp b/NTCPSession.cpp index f9116e3d..b65532be 100644 --- a/NTCPSession.cpp +++ b/NTCPSession.cpp @@ -574,17 +574,17 @@ namespace transport if (dataSize) { // new message - if (dataSize + 16U > NTCP_MAX_MESSAGE_SIZE - 2) // + 6 + padding + if (dataSize + 16U + 15U > NTCP_MAX_MESSAGE_SIZE - 2) // + 6 + padding { LogPrint (eLogError, "NTCP: data size ", dataSize, " exceeds max size"); return false; } - auto msg = (dataSize + 16U) <= I2NP_MAX_SHORT_MESSAGE_SIZE - 2 ? NewI2NPShortMessage () : NewI2NPMessage (); - m_NextMessage = msg; - memcpy (m_NextMessage->buf, buf, 16); + m_NextMessage = (dataSize + 16U + 15U) <= I2NP_MAX_SHORT_MESSAGE_SIZE - 2 ? NewI2NPShortMessage () : NewI2NPMessage (); + m_NextMessage->Align (16); + m_NextMessage->offset += 2; // size field + m_NextMessage->len = m_NextMessage->offset + dataSize; + memcpy (m_NextMessage->GetBuffer () - 2, buf, 16); m_NextMessageOffset = 16; - m_NextMessage->offset = 2; // size field - m_NextMessage->len = dataSize + 2; } else { @@ -595,16 +595,16 @@ namespace transport } else // message continues { - m_Decryption.Decrypt (encrypted, m_NextMessage->buf + m_NextMessageOffset); + m_Decryption.Decrypt (encrypted, m_NextMessage->GetBuffer () - 2 + m_NextMessageOffset); m_NextMessageOffset += 16; } - if (m_NextMessageOffset >= m_NextMessage->len + 4) // +checksum + if (m_NextMessageOffset >= m_NextMessage->GetLength () + 2 + 4) // +checksum { // we have a complete I2NP message uint8_t checksum[4]; - htobe32buf (checksum, adler32 (adler32 (0, Z_NULL, 0), m_NextMessage->buf, m_NextMessageOffset - 4)); - if (!memcmp (m_NextMessage->buf + m_NextMessageOffset - 4, checksum, 4)) + htobe32buf (checksum, adler32 (adler32 (0, Z_NULL, 0), m_NextMessage->GetBuffer () - 2, m_NextMessageOffset - 4)); + if (!memcmp (m_NextMessage->GetBuffer () - 2 + m_NextMessageOffset - 4, checksum, 4)) { if (!m_NextMessage->IsExpired ()) { diff --git a/Reseed.cpp b/Reseed.cpp index 3ea69eff..adba530b 100644 --- a/Reseed.cpp +++ b/Reseed.cpp @@ -41,19 +41,23 @@ namespace data std::string filename; i2p::config::GetOption("reseed.file", filename); if (filename.length() > 0) // reseed file is specified { + if (filename.length() > 8 && filename.substr(0, 8) == "https://") + { + return ReseedFromSU3 (filename); // reseed from https URL + } else { auto num = ProcessSU3File (filename.c_str ()); if (num > 0) return num; // success LogPrint (eLogWarning, "Can't reseed from ", filename, " . Trying from hosts"); + } } auto ind = rand () % httpsReseedHostList.size (); - std::string& reseedHost = httpsReseedHostList[ind]; - return ReseedFromSU3 (reseedHost); + std::string reseedUrl = httpsReseedHostList[ind] + "i2pseeds.su3"; + return ReseedFromSU3 (reseedUrl); } - int Reseeder::ReseedFromSU3 (const std::string& host) + int Reseeder::ReseedFromSU3 (const std::string& url) { - std::string url = host + "i2pseeds.su3"; - LogPrint (eLogInfo, "Reseed: Downloading SU3 from ", host); + LogPrint (eLogInfo, "Reseed: Downloading SU3 from ", url); std::string su3 = HttpsRequest (url); if (su3.length () > 0) { diff --git a/Reseed.h b/Reseed.h index 560a31d3..de47c0b1 100644 --- a/Reseed.h +++ b/Reseed.h @@ -29,7 +29,7 @@ namespace data void LoadCertificate (const std::string& filename); - int ReseedFromSU3 (const std::string& host); + int ReseedFromSU3 (const std::string& url); int ProcessSU3File (const char * filename); int ProcessSU3Stream (std::istream& s); diff --git a/Signature.h b/Signature.h index 1d90d8a3..a4f37980 100644 --- a/Signature.h +++ b/Signature.h @@ -155,9 +155,10 @@ namespace crypto ECDSAVerifier (const uint8_t * signingKey) { m_PublicKey = EC_KEY_new_by_curve_name (curve); - EC_KEY_set_public_key_affine_coordinates (m_PublicKey, - BN_bin2bn (signingKey, keyLen/2, NULL), - BN_bin2bn (signingKey + keyLen/2, keyLen/2, NULL)); + BIGNUM * x = BN_bin2bn (signingKey, keyLen/2, NULL); + BIGNUM * y = BN_bin2bn (signingKey + keyLen/2, keyLen/2, NULL); + EC_KEY_set_public_key_affine_coordinates (m_PublicKey, x, y); + BN_free (x); BN_free (y); } ~ECDSAVerifier () diff --git a/Streaming.cpp b/Streaming.cpp index 97cfad0a..762dd9d6 100644 --- a/Streaming.cpp +++ b/Streaming.cpp @@ -611,22 +611,19 @@ namespace stream return; } } - if (!m_CurrentOutboundTunnel) // first message to send + if (!m_RoutingSession || !m_RoutingSession->GetOwner ()) // expired and detached + m_RoutingSession = m_LocalDestination.GetOwner ()->GetRoutingSession (m_RemoteLeaseSet, true); + if (!m_CurrentOutboundTunnel && m_RoutingSession) // first message to send { // try to get shared path first - if (!m_RoutingSession) - m_RoutingSession = m_LocalDestination.GetOwner ()->GetRoutingSession (m_RemoteLeaseSet, true); - if (m_RoutingSession) - { - auto routingPath = m_RoutingSession->GetSharedRoutingPath (); - if (routingPath) - { - m_CurrentOutboundTunnel = routingPath->outboundTunnel; - m_CurrentRemoteLease = routingPath->remoteLease; - m_RTT = routingPath->rtt; - m_RTO = m_RTT*1.5; // TODO: implement it better - } - } + auto routingPath = m_RoutingSession->GetSharedRoutingPath (); + if (routingPath) + { + m_CurrentOutboundTunnel = routingPath->outboundTunnel; + m_CurrentRemoteLease = routingPath->remoteLease; + m_RTT = routingPath->rtt; + m_RTO = m_RTT*1.5; // TODO: implement it better + } } if (!m_CurrentOutboundTunnel || !m_CurrentOutboundTunnel->IsEstablished ()) m_CurrentOutboundTunnel = m_LocalDestination.GetOwner ()->GetTunnelPool ()->GetNewOutboundTunnel (m_CurrentOutboundTunnel); @@ -900,13 +897,13 @@ namespace stream if (packet->IsSYN () && !packet->GetSeqn ()) // new incoming stream { uint32_t receiveStreamID = packet->GetReceiveStreamID (); - /* if (receiveStreamID == m_LastIncomingReceiveStreamID) + if (receiveStreamID == m_LastIncomingReceiveStreamID) { // already pending LogPrint(eLogWarning, "Streaming: Incoming streaming with rSID=", receiveStreamID, " already exists"); delete packet; // drop it, because previous should be connected return; - } */ + } auto incomingStream = CreateNewIncomingStream (); incomingStream->HandleNextPacket (packet); // SYN auto ident = incomingStream->GetRemoteIdentity(); diff --git a/docs/i2pd.conf b/docs/i2pd.conf index 5e2770f6..0cdd0de8 100644 --- a/docs/i2pd.conf +++ b/docs/i2pd.conf @@ -97,8 +97,10 @@ verify = true ## URLs to request reseed data from, separated by comma ## Default: "mainline" I2P Network reseeds # urls = https://reseed.i2p-projekt.de/,https://i2p.mooo.com/netDb/,https://netdb.i2p2.no/ -## Path to reseed data file (.su3) for manual reseeding +## Path to local reseed data file (.su3) for manual reseeding # file = /path/to/i2pseeds.su3 +## or HTTPS URL to reseed from +# file = https://legit-website.com/i2pseeds.su3 [addressbook] ## AddressBook subscription URL for initial setup