From 2062305f889c5d335da91603edfb1dfd24ce7ad1 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 24 Apr 2014 11:10:46 -0400 Subject: [PATCH 01/60] moved log file from daemon to log --- Daemon.cpp | 7 +------ Daemon.h | 4 +--- Log.cpp | 23 ++++++++++++++++------- Log.h | 14 ++++++++++++-- 4 files changed, 30 insertions(+), 18 deletions(-) diff --git a/Daemon.cpp b/Daemon.cpp index e0c93cb3..ebd9a52d 100644 --- a/Daemon.cpp +++ b/Daemon.cpp @@ -63,12 +63,7 @@ namespace i2p #else logfile_path.append("\\debug.log"); #endif - logfile.open(logfile_path, std::ofstream::out | std::ofstream::binary | std::ofstream::trunc); - - if (!logfile.is_open()) - exit(-17); - - LogPrint("Logging to file enabled."); + g_Log.SetLogFile (logfile_path); LogPrint("CMD parameters:"); for (int i = 0; i < argc; ++i) diff --git a/Daemon.h b/Daemon.h index 4e27d108..f8f98467 100644 --- a/Daemon.h +++ b/Daemon.h @@ -1,5 +1,5 @@ #pragma once -#include +#include #ifdef _WIN32 #define Daemon i2p::util::DaemonWin32::Instance() @@ -24,8 +24,6 @@ namespace i2p int running; - std::ofstream logfile; - protected: Daemon_Singleton(); virtual ~Daemon_Singleton(); diff --git a/Log.cpp b/Log.cpp index 92fd8a25..4a88f2ba 100644 --- a/Log.cpp +++ b/Log.cpp @@ -1,20 +1,29 @@ #include "Log.h" -#include "Daemon.h" - Log g_Log; void LogMsg::Process() { - if (Daemon.isLogging == 1 && Daemon.logfile.is_open()) - Daemon.logfile << s.str(); - output << s.str(); + + std::cout << s.str (); // TODO: delete later } void Log::Flush () { - if (Daemon.isLogging == 1 && Daemon.logfile.is_open()) - Daemon.logfile.flush(); + if (m_LogFile) + m_LogFile->flush(); } +void Log::SetLogFile (const std::string& fullFilePath) +{ + if (m_LogFile) delete m_LogFile; + m_LogFile = new std::ofstream (fullFilePath, std::ofstream::out | std::ofstream::binary | std::ofstream::trunc); + if (m_LogFile->is_open ()) + LogPrint("Logging to file ", fullFilePath, " enabled."); + else + { + delete m_LogFile; + m_LogFile = nullptr; + } +} diff --git a/Log.h b/Log.h index a5856ba7..f3e7ae53 100644 --- a/Log.h +++ b/Log.h @@ -1,8 +1,10 @@ #ifndef LOG_H__ #define LOG_H__ +#include #include #include +#include #include #include "Queue.h" @@ -20,11 +22,19 @@ class Log: public i2p::util::MsgQueue { public: - Log () { SetOnEmpty (std::bind (&Log::Flush, this)); }; + Log (): m_LogFile (nullptr) { SetOnEmpty (std::bind (&Log::Flush, this)); }; + ~Log () { delete m_LogFile; }; + + void SetLogFile (const std::string& fullFilePath); + std::ofstream * GetLogFile () const { return m_LogFile; }; private: void Flush (); + + private: + + std::ofstream * m_LogFile; }; extern Log g_Log; @@ -45,7 +55,7 @@ void LogPrint (std::stringstream& s, TValue arg, TArgs... args) template void LogPrint (TArgs... args) { - LogMsg * msg = new LogMsg (); + LogMsg * msg = g_Log.GetLogFile () ? new LogMsg (*g_Log.GetLogFile ()) : new LogMsg (); LogPrint (msg->s, args...); msg->s << std::endl; g_Log.Put (msg); From c8a2ce47408b514e88842ccc56cc4943c07760d4 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 30 Apr 2014 14:08:57 -0400 Subject: [PATCH 02/60] handle TunnelBuild (8 records) message --- I2NPProtocol.cpp | 116 ++++++++++++++++++++++++++++++----------------- I2NPProtocol.h | 10 +++- 2 files changed, 83 insertions(+), 43 deletions(-) diff --git a/I2NPProtocol.cpp b/I2NPProtocol.cpp index 0b34f9db..76f6e7d4 100644 --- a/I2NPProtocol.cpp +++ b/I2NPProtocol.cpp @@ -236,6 +236,41 @@ namespace i2p memcpy (record.toPeer, (const uint8_t *)router.GetIdentHash (), 16); } + bool HandleBuildRequestRecords (int num, I2NPBuildRequestRecordElGamalEncrypted * records, I2NPBuildRequestRecordClearText& clearText) + { + for (int i = 0; i < num; i++) + { + if (!memcmp (records[i].toPeer, (const uint8_t *)i2p::context.GetRouterInfo ().GetIdentHash (), 16)) + { + LogPrint ("Record ",i," is ours"); + + i2p::crypto::ElGamalDecrypt (i2p::context.GetPrivateKey (), records[i].encrypted, (uint8_t *)&clearText); + + i2p::tunnel::TransitTunnel * transitTunnel = + i2p::tunnel::CreateTransitTunnel ( + be32toh (clearText.receiveTunnel), + clearText.nextIdent, be32toh (clearText.nextTunnel), + clearText.layerKey, clearText.ivKey, + clearText.flag & 0x80, clearText.flag & 0x40); + i2p::tunnel::tunnels.AddTransitTunnel (transitTunnel); + // replace record to reply + I2NPBuildResponseRecord * reply = (I2NPBuildResponseRecord *)(records + i); + reply->ret = 0; + //TODO: fill filler + CryptoPP::SHA256().CalculateDigest(reply->hash, reply->padding, sizeof (reply->padding) + 1); // + 1 byte of ret + // encrypt reply + CryptoPP::CBC_Mode::Encryption encryption; + for (int j = 0; j < num; j++) + { + encryption.SetKeyWithIV (clearText.replyKey, 32, clearText.replyIV); + encryption.ProcessData((uint8_t *)(records + j), (uint8_t *)(records + j), sizeof (records[j])); + } + return true; + } + } + return false; + } + void HandleVariableTunnelBuildMsg (uint32_t replyMsgID, uint8_t * buf, size_t len) { int num = buf[0]; @@ -260,52 +295,43 @@ namespace i2p else { I2NPBuildRequestRecordElGamalEncrypted * records = (I2NPBuildRequestRecordElGamalEncrypted *)(buf+1); - for (int i = 0; i < num; i++) - { - if (!memcmp (records[i].toPeer, (const uint8_t *)i2p::context.GetRouterInfo ().GetIdentHash (), 16)) - { - LogPrint ("Record ",i," is ours"); - - I2NPBuildRequestRecordClearText clearText; - i2p::crypto::ElGamalDecrypt (i2p::context.GetPrivateKey (), records[i].encrypted, (uint8_t *)&clearText); - - i2p::tunnel::TransitTunnel * transitTunnel = - i2p::tunnel::CreateTransitTunnel ( - be32toh (clearText.receiveTunnel), - clearText.nextIdent, be32toh (clearText.nextTunnel), - clearText.layerKey, clearText.ivKey, - clearText.flag & 0x80, clearText.flag & 0x40); - i2p::tunnel::tunnels.AddTransitTunnel (transitTunnel); - // replace record to reply - I2NPBuildResponseRecord * reply = (I2NPBuildResponseRecord *)(records + i); - reply->ret = 0; - //TODO: fill filler - CryptoPP::SHA256().CalculateDigest(reply->hash, reply->padding, sizeof (reply->padding) + 1); // + 1 byte of ret - // encrypt reply - CryptoPP::CBC_Mode::Encryption encryption; - for (int j = 0; j < num; j++) - { - encryption.SetKeyWithIV (clearText.replyKey, 32, clearText.replyIV); - encryption.ProcessData((uint8_t *)(records + j), (uint8_t *)(records + j), sizeof (records[j])); - } - - if (clearText.flag & 0x40) // we are endpoint of outboud tunnel - { - // so we send it to reply tunnel - i2p::transports.SendMessage (clearText.nextIdent, - CreateTunnelGatewayMsg (be32toh (clearText.nextTunnel), - eI2NPVariableTunnelBuildReply, buf, len, - be32toh (clearText.nextMessageID))); - } - else - i2p::transports.SendMessage (clearText.nextIdent, - CreateI2NPMessage (eI2NPVariableTunnelBuild, buf, len, be32toh (clearText.nextMessageID))); - return; + I2NPBuildRequestRecordClearText clearText; + if (HandleBuildRequestRecords (num, records, clearText)) + { + if (clearText.flag & 0x40) // we are endpoint of outboud tunnel + { + // so we send it to reply tunnel + i2p::transports.SendMessage (clearText.nextIdent, + CreateTunnelGatewayMsg (be32toh (clearText.nextTunnel), + eI2NPVariableTunnelBuildReply, buf, len, + be32toh (clearText.nextMessageID))); } + else + i2p::transports.SendMessage (clearText.nextIdent, + CreateI2NPMessage (eI2NPVariableTunnelBuild, buf, len, be32toh (clearText.nextMessageID))); } } } + void HandleTunnelBuildMsg (uint8_t * buf, size_t len) + { + I2NPBuildRequestRecordClearText clearText; + if (HandleBuildRequestRecords (NUM_TUNNEL_BUILD_RECORDS, (I2NPBuildRequestRecordElGamalEncrypted *)buf, clearText)) + { + if (clearText.flag & 0x40) // we are endpoint of outbound tunnel + { + // so we send it to reply tunnel + i2p::transports.SendMessage (clearText.nextIdent, + CreateTunnelGatewayMsg (be32toh (clearText.nextTunnel), + eI2NPTunnelBuildReply, buf, len, + be32toh (clearText.nextMessageID))); + } + else + i2p::transports.SendMessage (clearText.nextIdent, + CreateI2NPMessage (eI2NPTunnelBuild, buf, len, be32toh (clearText.nextMessageID))); + } + } + void HandleVariableTunnelBuildReplyMsg (uint32_t replyMsgID, uint8_t * buf, size_t len) { LogPrint ("VariableTunnelBuildReplyMsg replyMsgID=", replyMsgID); @@ -444,6 +470,14 @@ namespace i2p LogPrint ("VariableTunnelBuildReply"); HandleVariableTunnelBuildReplyMsg (msgID, buf, size); break; + case eI2NPTunnelBuild: + LogPrint ("TunnelBuild"); + HandleTunnelBuildMsg (buf, size); + break; + case eI2NPTunnelBuildReply: + LogPrint ("TunnelBuildReply"); + // TODO: + break; case eI2NPDatabaseLookup: LogPrint ("DatabaseLookup"); HandleDatabaseLookupMsg (buf, size); diff --git a/I2NPProtocol.h b/I2NPProtocol.h index 5e7900aa..0b6e45d4 100644 --- a/I2NPProtocol.h +++ b/I2NPProtocol.h @@ -87,10 +87,14 @@ namespace i2p eI2NPTunnelData = 18, eI2NPTunnelGateway = 19, eI2NPData = 20, + eI2NPTunnelBuild = 21, + eI2NPTunnelBuildReply = 22, eI2NPVariableTunnelBuild = 23, eI2NPVariableTunnelBuildReply = 24 }; + const int NUM_TUNNEL_BUILD_RECORDS = 8; + namespace tunnel { class InboundTunnel; @@ -164,10 +168,12 @@ namespace tunnel void EncryptBuildRequestRecord (const i2p::data::RouterInfo& router, const I2NPBuildRequestRecordClearText& clearText, I2NPBuildRequestRecordElGamalEncrypted& record); - + + bool HandleBuildRequestRecords (int num, I2NPBuildRequestRecordElGamalEncrypted * records, I2NPBuildRequestRecordClearText& clearText); void HandleVariableTunnelBuildMsg (uint32_t replyMsgID, uint8_t * buf, size_t len); void HandleVariableTunnelBuildReplyMsg (uint32_t replyMsgID, uint8_t * buf, size_t len); - + void HandleTunnelBuildMsg (uint8_t * buf, size_t len); + I2NPMessage * CreateTunnelDataMsg (const uint8_t * buf); I2NPMessage * CreateTunnelDataMsg (uint32_t tunnelID, const uint8_t * payload); From 8ef4f0cef2f6496d4db72b7895ca678af7b87af5 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 2 May 2014 11:42:30 -0400 Subject: [PATCH 03/60] CryptoConst added --- CryptoConst.cpp | 41 +++++++++++++++++++++++++++++++ CryptoConst.h | 64 +++++-------------------------------------------- Makefile | 6 ++--- 3 files changed, 50 insertions(+), 61 deletions(-) create mode 100644 CryptoConst.cpp diff --git a/CryptoConst.cpp b/CryptoConst.cpp new file mode 100644 index 00000000..c06a8837 --- /dev/null +++ b/CryptoConst.cpp @@ -0,0 +1,41 @@ +#include "CryptoConst.h" + +namespace i2p +{ +namespace crypto +{ + const CryptoPP::Integer elgp ( + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" + "15728E5A8AACAA68FFFFFFFFFFFFFFFF" + "h"); + + const CryptoPP::Integer elgg (2); + + const CryptoPP::Integer dsap ( + "9c05b2aa960d9b97b8931963c9cc9e8c3026e9b8ed92fad0a69cc886d5bf8015fcadae31" + "a0ad18fab3f01b00a358de237655c4964afaa2b337e96ad316b9fb1cc564b5aec5b69a9f" + "f6c3e4548707fef8503d91dd8602e867e6d35d2235c1869ce2479c3b9d5401de04e0727f" + "b33d6511285d4cf29538d9e3b6051f5b22cc1c93" + "h"); + const CryptoPP::Integer dsaq ( + "a5dfc28fef4ca1e286744cd8eed9d29d684046b7" + "h"); + + const CryptoPP::Integer dsag ( + "c1f4d27d40093b429e962d7223824e0bbc47e7c832a39236fc683af84889581075ff9082" + "ed32353d4374d7301cda1d23c431f4698599dda02451824ff369752593647cc3ddc197de" + "985e43d136cdcfc6bd5409cd2f450821142a5e6f8eb1c3ab5d0484b8129fcf17bce4f7f3" + "3321c3cb3dbb14a905e7b2b3e93be4708cbcc82" + "h"); +} +} + diff --git a/CryptoConst.h b/CryptoConst.h index df31b494..f96467f5 100644 --- a/CryptoConst.h +++ b/CryptoConst.h @@ -7,67 +7,15 @@ namespace i2p { namespace crypto { - // DH - - inline const CryptoPP::Integer& get_elgp () - { - static const CryptoPP::Integer elgp_ ( - "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" - "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" - "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" - "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" - "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" - "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" - "83655D23DCA3AD961C62F356208552BB9ED529077096966D" - "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" - "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" - "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" - "15728E5A8AACAA68FFFFFFFFFFFFFFFF" - "h"); - return elgp_; - } - #define elgp get_elgp() + // DH + extern const CryptoPP::Integer elgp; + extern const CryptoPP::Integer elgg; - inline const CryptoPP::Integer& get_elgg () - { - static const CryptoPP::Integer elgg_ (2); - return elgg_; - } - #define elgg get_elgg() // DSA - inline const CryptoPP::Integer& get_dsap () - { - static const CryptoPP::Integer dsap_ ( - "9c05b2aa960d9b97b8931963c9cc9e8c3026e9b8ed92fad0a69cc886d5bf8015fcadae31" - "a0ad18fab3f01b00a358de237655c4964afaa2b337e96ad316b9fb1cc564b5aec5b69a9f" - "f6c3e4548707fef8503d91dd8602e867e6d35d2235c1869ce2479c3b9d5401de04e0727f" - "b33d6511285d4cf29538d9e3b6051f5b22cc1c93" - "h"); - return dsap_; - } - #define dsap get_dsap() - - inline const CryptoPP::Integer& get_dsaq () - { - static const CryptoPP::Integer dsaq_ ( - "a5dfc28fef4ca1e286744cd8eed9d29d684046b7" - "h"); - return dsaq_; - } - #define dsaq get_dsaq() - - inline const CryptoPP::Integer& get_dsag () - { - static const CryptoPP::Integer dsag_ ( - "c1f4d27d40093b429e962d7223824e0bbc47e7c832a39236fc683af84889581075ff9082" - "ed32353d4374d7301cda1d23c431f4698599dda02451824ff369752593647cc3ddc197de" - "985e43d136cdcfc6bd5409cd2f450821142a5e6f8eb1c3ab5d0484b8129fcf17bce4f7f3" - "3321c3cb3dbb14a905e7b2b3e93be4708cbcc82" - "h"); - return dsag_; - } - #define dsag get_dsag() + extern const CryptoPP::Integer dsap; + extern const CryptoPP::Integer dsaq; + extern const CryptoPP::Integer dsag; } } diff --git a/Makefile b/Makefile index 33f513bf..73033ff6 100644 --- a/Makefile +++ b/Makefile @@ -1,12 +1,12 @@ CC = g++ CFLAGS = -g -Wall -std=c++0x -OBJECTS = obj/i2p.o obj/base64.o obj/NTCPSession.o obj/RouterInfo.o obj/Transports.o \ +OBJECTS = obj/CryptoConst.o obj/base64.o obj/NTCPSession.o obj/RouterInfo.o obj/Transports.o \ obj/RouterContext.o obj/NetDb.o obj/LeaseSet.o obj/Tunnel.o obj/TunnelEndpoint.o \ obj/TunnelGateway.o obj/TransitTunnel.o obj/I2NPProtocol.o obj/Log.o obj/Garlic.o \ obj/HTTPServer.o obj/Streaming.o obj/Identity.o obj/SSU.o obj/util.o obj/Reseed.o \ - obj/UPnP.o obj/TunnelPool.o obj/HTTPProxy.o obj/AddressBook.o \ - obj/Daemon.o obj/DaemonLinux.o obj/SSUData.o + obj/UPnP.o obj/TunnelPool.o obj/HTTPProxy.o obj/AddressBook.o obj/Daemon.o \ + obj/DaemonLinux.o obj/SSUData.o obj/i2p.o INCFLAGS = LDFLAGS = -Wl,-rpath,/usr/local/lib -lcryptopp -lboost_system -lboost_filesystem -lboost_regex -lboost_program_options -lpthread LIBS = From 8fd183c6de02488c4a3d39caa9000afcc8002787 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 2 May 2014 12:28:58 -0400 Subject: [PATCH 04/60] elgp as byte array --- CryptoConst.cpp | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/CryptoConst.cpp b/CryptoConst.cpp index c06a8837..c231c2cb 100644 --- a/CryptoConst.cpp +++ b/CryptoConst.cpp @@ -1,23 +1,31 @@ +#include #include "CryptoConst.h" namespace i2p { namespace crypto { - const CryptoPP::Integer elgp ( - "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" - "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" - "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" - "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" - "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" - "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" - "83655D23DCA3AD961C62F356208552BB9ED529077096966D" - "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" - "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" - "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" - "15728E5A8AACAA68FFFFFFFFFFFFFFFF" - "h"); + const uint8_t elgp_[256]= + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, + 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, + 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, + 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, + 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, + 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, + 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, + 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, + 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, + 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, + 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, + 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, + 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, + 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, + 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, + 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF + }; + const CryptoPP::Integer elgp (elgp_, 256); const CryptoPP::Integer elgg (2); const CryptoPP::Integer dsap ( From 4fef0dd1cbd56f3503e5cf15cdaae0144ef2be7b Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 2 May 2014 13:46:24 -0400 Subject: [PATCH 05/60] dsa constants as byte array --- CryptoConst.cpp | 47 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 32 insertions(+), 15 deletions(-) diff --git a/CryptoConst.cpp b/CryptoConst.cpp index c231c2cb..045c8989 100644 --- a/CryptoConst.cpp +++ b/CryptoConst.cpp @@ -28,22 +28,39 @@ namespace crypto const CryptoPP::Integer elgp (elgp_, 256); const CryptoPP::Integer elgg (2); - const CryptoPP::Integer dsap ( - "9c05b2aa960d9b97b8931963c9cc9e8c3026e9b8ed92fad0a69cc886d5bf8015fcadae31" - "a0ad18fab3f01b00a358de237655c4964afaa2b337e96ad316b9fb1cc564b5aec5b69a9f" - "f6c3e4548707fef8503d91dd8602e867e6d35d2235c1869ce2479c3b9d5401de04e0727f" - "b33d6511285d4cf29538d9e3b6051f5b22cc1c93" - "h"); - const CryptoPP::Integer dsaq ( - "a5dfc28fef4ca1e286744cd8eed9d29d684046b7" - "h"); + const uint8_t dsap_[128]= + { + 0x9c, 0x05, 0xb2, 0xaa, 0x96, 0x0d, 0x9b, 0x97, 0xb8, 0x93, 0x19, 0x63, 0xc9, 0xcc, 0x9e, 0x8c, + 0x30, 0x26, 0xe9, 0xb8, 0xed, 0x92, 0xfa, 0xd0, 0xa6, 0x9c, 0xc8, 0x86, 0xd5, 0xbf, 0x80, 0x15, + 0xfc, 0xad, 0xae, 0x31, 0xa0, 0xad, 0x18, 0xfa, 0xb3, 0xf0, 0x1b, 0x00, 0xa3, 0x58, 0xde, 0x23, + 0x76, 0x55, 0xc4, 0x96, 0x4a, 0xfa, 0xa2, 0xb3, 0x37, 0xe9, 0x6a, 0xd3, 0x16, 0xb9, 0xfb, 0x1c, + 0xc5, 0x64, 0xb5, 0xae, 0xc5, 0xb6, 0x9a, 0x9f, 0xf6, 0xc3, 0xe4, 0x54, 0x87, 0x07, 0xfe, 0xf8, + 0x50, 0x3d, 0x91, 0xdd, 0x86, 0x02, 0xe8, 0x67, 0xe6, 0xd3, 0x5d, 0x22, 0x35, 0xc1, 0x86, 0x9c, + 0xe2, 0x47, 0x9c, 0x3b, 0x9d, 0x54, 0x01, 0xde, 0x04, 0xe0, 0x72, 0x7f, 0xb3, 0x3d, 0x65, 0x11, + 0x28, 0x5d, 0x4c, 0xf2, 0x95, 0x38, 0xd9, 0xe3, 0xb6, 0x05, 0x1f, 0x5b, 0x22, 0xcc, 0x1c, 0x93 + }; + + const uint8_t dsaq_[20]= + { + 0xa5, 0xdf, 0xc2, 0x8f, 0xef, 0x4c, 0xa1, 0xe2, 0x86, 0x74, 0x4c, 0xd8, 0xee, 0xd9, 0xd2, 0x9d, + 0x68, 0x40, 0x46, 0xb7 + }; + + const uint8_t dsag_[128]= + { + 0x0c, 0x1f, 0x4d, 0x27, 0xd4, 0x00, 0x93, 0xb4, 0x29, 0xe9, 0x62, 0xd7, 0x22, 0x38, 0x24, 0xe0, + 0xbb, 0xc4, 0x7e, 0x7c, 0x83, 0x2a, 0x39, 0x23, 0x6f, 0xc6, 0x83, 0xaf, 0x84, 0x88, 0x95, 0x81, + 0x07, 0x5f, 0xf9, 0x08, 0x2e, 0xd3, 0x23, 0x53, 0xd4, 0x37, 0x4d, 0x73, 0x01, 0xcd, 0xa1, 0xd2, + 0x3c, 0x43, 0x1f, 0x46, 0x98, 0x59, 0x9d, 0xda, 0x02, 0x45, 0x18, 0x24, 0xff, 0x36, 0x97, 0x52, + 0x59, 0x36, 0x47, 0xcc, 0x3d, 0xdc, 0x19, 0x7d, 0xe9, 0x85, 0xe4, 0x3d, 0x13, 0x6c, 0xdc, 0xfc, + 0x6b, 0xd5, 0x40, 0x9c, 0xd2, 0xf4, 0x50, 0x82, 0x11, 0x42, 0xa5, 0xe6, 0xf8, 0xeb, 0x1c, 0x3a, + 0xb5, 0xd0, 0x48, 0x4b, 0x81, 0x29, 0xfc, 0xf1, 0x7b, 0xce, 0x4f, 0x7f, 0x33, 0x32, 0x1c, 0x3c, + 0xb3, 0xdb, 0xb1, 0x4a, 0x90, 0x5e, 0x7b, 0x2b, 0x3e, 0x93, 0xbe, 0x47, 0x08, 0xcb, 0xcc, 0x82 + }; - const CryptoPP::Integer dsag ( - "c1f4d27d40093b429e962d7223824e0bbc47e7c832a39236fc683af84889581075ff9082" - "ed32353d4374d7301cda1d23c431f4698599dda02451824ff369752593647cc3ddc197de" - "985e43d136cdcfc6bd5409cd2f450821142a5e6f8eb1c3ab5d0484b8129fcf17bce4f7f3" - "3321c3cb3dbb14a905e7b2b3e93be4708cbcc82" - "h"); + const CryptoPP::Integer dsap (dsap_, 128); + const CryptoPP::Integer dsaq (dsaq_, 20); + const CryptoPP::Integer dsag (dsag_, 128); } } From 4f429b3e0647ce4b270f905bd1e3ff15a371a6f6 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 3 May 2014 15:29:00 -0400 Subject: [PATCH 06/60] copy constructor for PrivateKeys --- Identity.cpp | 16 ++++++++-------- Identity.h | 8 ++++++-- Streaming.cpp | 5 +++++ 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/Identity.cpp b/Identity.cpp index 5a59e26e..c4782e05 100644 --- a/Identity.cpp +++ b/Identity.cpp @@ -22,14 +22,14 @@ namespace data bool Identity::FromBase64 (const std::string& s) { - size_t count = Base64ToByteStream (s.c_str(), s.length(), reinterpret_cast (this), sizeof (Identity)); + size_t count = Base64ToByteStream (s.c_str(), s.length(), publicKey, sizeof (Identity)); return count == sizeof(Identity); } - IdentHash Identity::Hash() + IdentHash Identity::Hash() const { IdentHash hash; - CryptoPP::SHA256().CalculateDigest(reinterpret_cast(&hash), reinterpret_cast (this), sizeof (Identity)); + CryptoPP::SHA256().CalculateDigest(hash, publicKey, sizeof (Identity)); return hash; } @@ -40,11 +40,11 @@ namespace data return *this; } - bool IdentHash::FromBase32(const std::string& s) - { - size_t count = Base32ToByteStream(s.c_str(), s.length(), m_Hash, sizeof(m_Hash)); - return count == sizeof(m_Hash); - } + bool IdentHash::FromBase32(const std::string& s) + { + size_t count = Base32ToByteStream(s.c_str(), s.length(), m_Hash, sizeof(m_Hash)); + return count == sizeof(m_Hash); + } Keys CreateRandomKeys () { diff --git a/Identity.h b/Identity.h index be9ae901..b2d593b0 100644 --- a/Identity.h +++ b/Identity.h @@ -34,8 +34,8 @@ namespace data uint8_t certificate[3]; Identity& operator=(const Keys& keys); - bool FromBase64(const std::string&); - IdentHash Hash(); + bool FromBase64(const std::string& ); + IdentHash Hash() const; }; struct PrivateKeys // for eepsites @@ -44,6 +44,10 @@ namespace data uint8_t privateKey[256]; uint8_t signingPrivateKey[20]; + PrivateKeys () = default; + PrivateKeys (const PrivateKeys& ) = default; + PrivateKeys (const Keys& keys) { *this = keys; }; + PrivateKeys& operator=(const Keys& keys); }; diff --git a/Streaming.cpp b/Streaming.cpp index d5e3fbcd..86105ca0 100644 --- a/Streaming.cpp +++ b/Streaming.cpp @@ -334,6 +334,7 @@ namespace stream StreamingDestination::StreamingDestination (): m_LeaseSet (nullptr) { m_Keys = i2p::data::CreateRandomKeys (); + m_IdentHash = m_Keys.pub.Hash (); m_SigningPrivateKey.Initialize (i2p::crypto::dsap, i2p::crypto::dsaq, i2p::crypto::dsag, CryptoPP::Integer (m_Keys.signingPrivateKey, 20)); @@ -349,6 +350,10 @@ namespace stream s.read ((char *)&m_Keys, sizeof (m_Keys)); else LogPrint ("Can't open file ", fullPath); + + m_IdentHash = m_Keys.pub.Hash (); + m_SigningPrivateKey.Initialize (i2p::crypto::dsap, i2p::crypto::dsaq, i2p::crypto::dsag, + CryptoPP::Integer (m_Keys.signingPrivateKey, 20)); CryptoPP::DH dh (i2p::crypto::elgp, i2p::crypto::elgg); dh.GenerateKeyPair(i2p::context.GetRandomNumberGenerator (), m_EncryptionPrivateKey, m_EncryptionPublicKey); m_Pool = i2p::tunnel::tunnels.CreateTunnelPool (*this); From 44bba19283aa4948f33ecc52699519761a3a3606 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 4 May 2014 18:57:26 -0400 Subject: [PATCH 07/60] fixed memory leak --- SSU.cpp | 1 + SSUData.cpp | 2 ++ 2 files changed, 3 insertions(+) diff --git a/SSU.cpp b/SSU.cpp index 32dbf681..9711ecef 100644 --- a/SSU.cpp +++ b/SSU.cpp @@ -859,6 +859,7 @@ namespace ssu len = 0; fragmentNum++; } + DeleteI2NPMessage (msg); } void SSUSession::Send (uint8_t type, const uint8_t * payload, size_t len) diff --git a/SSUData.cpp b/SSUData.cpp index 2f3cbec2..6a7f4dc3 100644 --- a/SSUData.cpp +++ b/SSUData.cpp @@ -90,6 +90,8 @@ namespace ssu if (isLast) { + if (!msg) + DeleteI2NPMessage (it->second->msg); delete it->second; m_IncomleteMessages.erase (it); } From d8d8c752b1c145a10d30fe995a92dabaf1424dd8 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 6 May 2014 12:22:22 -0400 Subject: [PATCH 08/60] aes added --- Makefile | 2 +- aes.cpp | 30 ++++++++++++++++++++++++++++++ aes.h | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 aes.cpp create mode 100644 aes.h diff --git a/Makefile b/Makefile index 73033ff6..a30b268c 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ OBJECTS = obj/CryptoConst.o obj/base64.o obj/NTCPSession.o obj/RouterInfo.o obj/ obj/TunnelGateway.o obj/TransitTunnel.o obj/I2NPProtocol.o obj/Log.o obj/Garlic.o \ obj/HTTPServer.o obj/Streaming.o obj/Identity.o obj/SSU.o obj/util.o obj/Reseed.o \ obj/UPnP.o obj/TunnelPool.o obj/HTTPProxy.o obj/AddressBook.o obj/Daemon.o \ - obj/DaemonLinux.o obj/SSUData.o obj/i2p.o + obj/DaemonLinux.o obj/SSUData.o obj/i2p.o obj/aes.o INCFLAGS = LDFLAGS = -Wl,-rpath,/usr/local/lib -lcryptopp -lboost_system -lboost_filesystem -lboost_regex -lboost_program_options -lpthread LIBS = diff --git a/aes.cpp b/aes.cpp new file mode 100644 index 00000000..5f791271 --- /dev/null +++ b/aes.cpp @@ -0,0 +1,30 @@ +#include "aes.h" + +namespace i2p +{ +namespace crypto +{ + void CBCEncryption::Encrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out) + { + for (int i = 0; i < numBlocks; i++) + { + m_LastBlock.ll[0] ^= in[i].ll[0]; + m_LastBlock.ll[1] ^= in[i].ll[1]; + m_ECBEncryption.ProcessData (m_LastBlock.buf, m_LastBlock.buf, 16); + out[i] = m_LastBlock; + } + } + + void CBCDecryption::Decrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out) + { + for (int i = 0; i < numBlocks; i++) + { + m_ECBDecryption.ProcessData (out[i].buf, in[i].buf, 16); + out[i].ll[0] ^= m_IV.ll[0]; + out[i].ll[1] ^= m_IV.ll[1]; + m_IV = in[i]; + } + } +} +} + diff --git a/aes.h b/aes.h new file mode 100644 index 00000000..3d71ebed --- /dev/null +++ b/aes.h @@ -0,0 +1,55 @@ +#ifndef AES_H__ +#define AES_H__ + +#include +#include +#include + +namespace i2p +{ +namespace crypto +{ + union ChipherBlock + { + uint8_t buf[16]; + uint64_t ll[2]; + }; + + class CBCEncryption + { + public: + + CBCEncryption () { memset (m_LastBlock.buf, 0, 16); }; + + void SetKey (uint8_t * key) { m_ECBEncryption.SetKey (key, 32); }; // 32 bytes + void SetIV (uint8_t * iv) { memcpy (m_LastBlock.buf, iv, 16); }; // 16 bytes + + void Encrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out); + + private: + + ChipherBlock m_LastBlock; + CryptoPP::ECB_Mode::Encryption m_ECBEncryption; + }; + + class CBCDecryption + { + public: + + CBCDecryption () { memset (m_IV.buf, 0, 16); }; + + void SetKey (uint8_t * key) { m_ECBDecryption.SetKey (key, 32); }; // 32 bytes + void SetIV (uint8_t * iv) { memcpy (m_IV.buf, iv, 16); }; // 16 bytes + + void Decrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out); + + private: + + ChipherBlock m_IV; + CryptoPP::ECB_Mode::Decryption m_ECBDecryption; + }; +} +} + +#endif + From 81b57141d48c86ee8ba12fdce7cff2c12504b813 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 6 May 2014 13:26:28 -0400 Subject: [PATCH 09/60] encrypt/decrypt same buffer --- aes.cpp | 20 +++++++++++++++++++- aes.h | 2 ++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/aes.cpp b/aes.cpp index 5f791271..14a5b762 100644 --- a/aes.cpp +++ b/aes.cpp @@ -1,3 +1,4 @@ +#include #include "aes.h" namespace i2p @@ -15,16 +16,33 @@ namespace crypto } } + bool CBCEncryption::Encrypt (const uint8_t * in, std::size_t len, uint8_t * out) + { + div_t d = div (len, 16); + if (d.rem) return false; // len is not multipple of 16 + Encrypt (d.quot, (const ChipherBlock *)in, (ChipherBlock *)out); + return true; + } + void CBCDecryption::Decrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out) { for (int i = 0; i < numBlocks; i++) { + ChipherBlock tmp = in[i]; m_ECBDecryption.ProcessData (out[i].buf, in[i].buf, 16); out[i].ll[0] ^= m_IV.ll[0]; out[i].ll[1] ^= m_IV.ll[1]; - m_IV = in[i]; + m_IV = tmp; } } + + bool CBCDecryption::Decrypt (const uint8_t * in, std::size_t len, uint8_t * out) + { + div_t d = div (len, 16); + if (d.rem) return false; // len is not multipple of 16 + Decrypt (d.quot, (const ChipherBlock *)in, (ChipherBlock *)out); + return true; + } } } diff --git a/aes.h b/aes.h index 3d71ebed..763b22eb 100644 --- a/aes.h +++ b/aes.h @@ -25,6 +25,7 @@ namespace crypto void SetIV (uint8_t * iv) { memcpy (m_LastBlock.buf, iv, 16); }; // 16 bytes void Encrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out); + bool Encrypt (const uint8_t * in, std::size_t len, uint8_t * out); private: @@ -42,6 +43,7 @@ namespace crypto void SetIV (uint8_t * iv) { memcpy (m_IV.buf, iv, 16); }; // 16 bytes void Decrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out); + bool Decrypt (const uint8_t * in, std::size_t len, uint8_t * out); private: From 6bf5d98c4d3bbf6b11b365066709cebd849f86f5 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 6 May 2014 22:30:09 -0400 Subject: [PATCH 10/60] use new aes implementation for NTCP --- NTCPSession.cpp | 30 +++++++++++++++++------------- NTCPSession.h | 5 +++-- aes.h | 8 ++++---- 3 files changed, 24 insertions(+), 19 deletions(-) diff --git a/NTCPSession.cpp b/NTCPSession.cpp index 712e8232..88e4eb0a 100644 --- a/NTCPSession.cpp +++ b/NTCPSession.cpp @@ -183,10 +183,12 @@ namespace ntcp uint8_t aesKey[32]; CreateAESKey (m_Phase1.pubKey, aesKey); - m_Encryption.SetKeyWithIV (aesKey, 32, y + 240); - m_Decryption.SetKeyWithIV (aesKey, 32, m_Phase1.HXxorHI + 16); + m_Encryption.SetKey (aesKey); + m_Encryption.SetIV (y + 240); + m_Decryption.SetKey (aesKey); + m_Decryption.SetIV (m_Phase1.HXxorHI + 16); - m_Encryption.ProcessData((uint8_t *)&m_Phase2.encrypted, (uint8_t *)&m_Phase2.encrypted, sizeof(m_Phase2.encrypted)); + m_Encryption.Encrypt ((uint8_t *)&m_Phase2.encrypted, sizeof(m_Phase2.encrypted), (uint8_t *)&m_Phase2.encrypted); boost::asio::async_write (m_Socket, boost::asio::buffer (&m_Phase2, sizeof (m_Phase2)), boost::asio::transfer_all (), boost::bind(&NTCPSession::HandlePhase2Sent, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred, tsB)); @@ -222,10 +224,12 @@ namespace ntcp uint8_t aesKey[32]; CreateAESKey (m_Phase2.pubKey, aesKey); - m_Decryption.SetKeyWithIV (aesKey, 32, m_Phase2.pubKey + 240); - m_Encryption.SetKeyWithIV (aesKey, 32, m_Phase1.HXxorHI + 16); + m_Decryption.SetKey (aesKey); + m_Decryption.SetIV (m_Phase2.pubKey + 240); + m_Encryption.SetKey (aesKey); + m_Encryption.SetIV (m_Phase1.HXxorHI + 16); - m_Decryption.ProcessData((uint8_t *)&m_Phase2.encrypted, (uint8_t *)&m_Phase2.encrypted, sizeof(m_Phase2.encrypted)); + m_Decryption.Decrypt((uint8_t *)&m_Phase2.encrypted, sizeof(m_Phase2.encrypted), (uint8_t *)&m_Phase2.encrypted); // verify uint8_t xy[512], hxy[32]; memcpy (xy, m_DHKeysPair->publicKey, 256); @@ -256,7 +260,7 @@ namespace ntcp s.tsB = m_Phase2.encrypted.timestamp; i2p::context.Sign ((uint8_t *)&s, sizeof (s), m_Phase3.signature); - m_Encryption.ProcessData((uint8_t *)&m_Phase3, (uint8_t *)&m_Phase3, sizeof(m_Phase3)); + m_Encryption.Encrypt((uint8_t *)&m_Phase3, sizeof(m_Phase3), (uint8_t *)&m_Phase3); boost::asio::async_write (m_Socket, boost::asio::buffer (&m_Phase3, sizeof (m_Phase3)), boost::asio::transfer_all (), boost::bind(&NTCPSession::HandlePhase3Sent, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred, tsA)); @@ -288,7 +292,7 @@ namespace ntcp else { LogPrint ("Phase 3 received: ", bytes_transferred); - m_Decryption.ProcessData((uint8_t *)&m_Phase3, (uint8_t *)&m_Phase3, sizeof(m_Phase3)); + m_Decryption.Decrypt ((uint8_t *)&m_Phase3, sizeof(m_Phase3), (uint8_t *)&m_Phase3); m_RemoteRouterInfo.SetRouterIdentity (m_Phase3.ident); SignedData s; @@ -321,7 +325,7 @@ namespace ntcp s.tsA = m_Phase3.timestamp; s.tsB = tsB; i2p::context.Sign ((uint8_t *)&s, sizeof (s), m_Phase4.signature); - m_Encryption.ProcessData((uint8_t *)&m_Phase4, (uint8_t *)&m_Phase4, sizeof(m_Phase4)); + m_Encryption.Encrypt ((uint8_t *)&m_Phase4, sizeof(m_Phase4), (uint8_t *)&m_Phase4); boost::asio::async_write (m_Socket, boost::asio::buffer (&m_Phase4, sizeof (m_Phase4)), boost::asio::transfer_all (), boost::bind(&NTCPSession::HandlePhase4Sent, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); @@ -355,7 +359,7 @@ namespace ntcp else { LogPrint ("Phase 4 received: ", bytes_transferred); - m_Decryption.ProcessData((uint8_t *)&m_Phase4, (uint8_t *)&m_Phase4, sizeof(m_Phase4)); + m_Decryption.Decrypt((uint8_t *)&m_Phase4, sizeof(m_Phase4), (uint8_t *)&m_Phase4); // verify signature SignedData s; @@ -426,7 +430,7 @@ namespace ntcp m_NextMessage = i2p::NewI2NPMessage (); m_NextMessageOffset = 0; - m_Decryption.ProcessData (m_NextMessage->buf, encrypted, 16); + m_Decryption.Decrypt (encrypted, 16, m_NextMessage->buf); uint16_t dataSize = be16toh (*(uint16_t *)m_NextMessage->buf); if (dataSize) { @@ -446,7 +450,7 @@ namespace ntcp } else // message continues { - m_Decryption.ProcessData (m_NextMessage->buf + m_NextMessageOffset, encrypted, 16); + m_Decryption.Decrypt (encrypted, 16, m_NextMessage->buf + m_NextMessageOffset); m_NextMessageOffset += 16; } @@ -490,7 +494,7 @@ namespace ntcp m_Adler.CalculateDigest (sendBuffer + len + 2 + padding, sendBuffer, len + 2+ padding); int l = len + padding + 6; - m_Encryption.ProcessData(sendBuffer, sendBuffer, l); + m_Encryption.Encrypt(sendBuffer, l, sendBuffer); boost::asio::async_write (m_Socket, boost::asio::buffer (sendBuffer, l), boost::asio::transfer_all (), boost::bind(&NTCPSession::HandleSent, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred, msg)); diff --git a/NTCPSession.h b/NTCPSession.h index 83396e11..f453c417 100644 --- a/NTCPSession.h +++ b/NTCPSession.h @@ -7,6 +7,7 @@ #include #include #include +#include "aes.h" #include "Identity.h" #include "RouterInfo.h" #include "I2NPProtocol.h" @@ -123,8 +124,8 @@ namespace ntcp bool m_IsEstablished; i2p::data::DHKeysPair * m_DHKeysPair; // X - for client and Y - for server - CryptoPP::CBC_Mode::Decryption m_Decryption; - CryptoPP::CBC_Mode::Encryption m_Encryption; + i2p::crypto::CBCDecryption m_Decryption; + i2p::crypto::CBCEncryption m_Encryption; CryptoPP::Adler32 m_Adler; i2p::data::RouterInfo& m_RemoteRouterInfo; diff --git a/aes.h b/aes.h index 763b22eb..4cfc37f6 100644 --- a/aes.h +++ b/aes.h @@ -21,8 +21,8 @@ namespace crypto CBCEncryption () { memset (m_LastBlock.buf, 0, 16); }; - void SetKey (uint8_t * key) { m_ECBEncryption.SetKey (key, 32); }; // 32 bytes - void SetIV (uint8_t * iv) { memcpy (m_LastBlock.buf, iv, 16); }; // 16 bytes + void SetKey (const uint8_t * key) { m_ECBEncryption.SetKey (key, 32); }; // 32 bytes + void SetIV (const uint8_t * iv) { memcpy (m_LastBlock.buf, iv, 16); }; // 16 bytes void Encrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out); bool Encrypt (const uint8_t * in, std::size_t len, uint8_t * out); @@ -39,8 +39,8 @@ namespace crypto CBCDecryption () { memset (m_IV.buf, 0, 16); }; - void SetKey (uint8_t * key) { m_ECBDecryption.SetKey (key, 32); }; // 32 bytes - void SetIV (uint8_t * iv) { memcpy (m_IV.buf, iv, 16); }; // 16 bytes + void SetKey (const uint8_t * key) { m_ECBDecryption.SetKey (key, 32); }; // 32 bytes + void SetIV (const uint8_t * iv) { memcpy (m_IV.buf, iv, 16); }; // 16 bytes void Decrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out); bool Decrypt (const uint8_t * in, std::size_t len, uint8_t * out); From 527ac413b18a2ab740de3f6411979580479d1c68 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 7 May 2014 14:48:37 -0400 Subject: [PATCH 11/60] aes key expansion --- aes.cpp | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ aes.h | 15 +++++++++++++ 2 files changed, 85 insertions(+) diff --git a/aes.cpp b/aes.cpp index 14a5b762..2eedf0ad 100644 --- a/aes.cpp +++ b/aes.cpp @@ -5,6 +5,76 @@ namespace i2p { namespace crypto { + +#ifdef __x86_64__ + + #define KeyExpansion256 \ + "pshufd $0xff, %%xmm2, %%xmm2 \n" \ + "movaps %%xmm1, %%xmm4 \n" \ + "pslldq $4, %%xmm4 \n" \ + "pxor %%xmm4, %%xmm1 \n" \ + "pslldq $4, %%xmm4 \n" \ + "pxor %%xmm4, %%xmm1 \n" \ + "pslldq $4, %%xmm4 \n" \ + "pxor %%xmm4, %%xmm1 \n" \ + "pxor %%xmm2, %%xmm1 \n" \ + "movups %%xmm1, (%%rcx) \n" \ + "aeskeygenassist $0, %%xmm1, %%xmm4 \n" \ + "pshufd $0xaa, %%xmm4, %%xmm2 \n" \ + "movaps %%xmm3, %%xmm4 \n" \ + "pslldq $4, %%xmm4 \n" \ + "pxor %%xmm4, %%xmm3 \n" \ + "pslldq $4, %%xmm4 \n" \ + "pxor %%xmm4, %%xmm3 \n" \ + "pslldq $4, %%xmm4 \n" \ + "pxor %%xmm4, %%xmm3 \n" \ + "pxor %%xmm2, %%xmm3 \n" \ + "movups %%xmm3, 16(%%rcx) \n" \ + "add $32, %%rcx \n" + + + void ECNEncryptionAESNI::SetKey (const uint8_t * key) + { + __asm__ + ( + "movups (%%rsi), %%xmm1 \n" + "movups 16(%%rsi), %%xmm3 \n" + "movups %%xmm1, (%%rdi) \n" + "movups %%xmm3, 16(%%rdi) \n" + "lea 32(%%rdi), %%rcx \n" + "aeskeygenassist $1, %%xmm3, %%xmm2 \n" + KeyExpansion256 + "aeskeygenassist $2, %%xmm3, %%xmm2 \n" + KeyExpansion256 + "aeskeygenassist $4, %%xmm3, %%xmm2 \n" + KeyExpansion256 + "aeskeygenassist $8, %%xmm3, %%xmm2 \n" + KeyExpansion256 + "aeskeygenassist $10, %%xmm3, %%xmm2 \n" + KeyExpansion256 + "aeskeygenassist $20, %%xmm3, %%xmm2 \n" + KeyExpansion256 + "aeskeygenassist $40, %%xmm3, %%xmm2 \n" + // key expansion final + "pshufd $0xff, %%xmm2, %%xmm2 \n" + "movaps %%xmm1, %%xmm4 \n" + "pslldq $4, %%xmm4 \n" + "pxor %%xmm4, %%xmm1 \n" + "pslldq $4, %%xmm4 \n" + "pxor %%xmm4, %%xmm1 \n" + "pslldq $4, %%xmm4 \n" + "pxor %%xmm4, %%xmm1 \n" + "pxor %%xmm2, %%xmm1 \n" + "movups %%xmm1, (%%rcx) \n" + : // output + : "S" (key), "D" (m_KeySchedule) // input + : "%rcx" // modified + ); + } + +#endif + + void CBCEncryption::Encrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out) { for (int i = 0; i < numBlocks; i++) diff --git a/aes.h b/aes.h index 4cfc37f6..365c01fd 100644 --- a/aes.h +++ b/aes.h @@ -15,6 +15,21 @@ namespace crypto uint64_t ll[2]; }; +#ifdef __x86_64__ + // AES-NI assumed + class ECNEncryptionAESNI + { + public: + + void SetKey (const uint8_t * key); + + private: + + uint32_t m_KeySchedule[4*(14+1)]; // 14 rounds for AES-256 + }; + +#endif + class CBCEncryption { public: From 236c6065784c4ed5d8e7d6d6696358bc4247dc5a Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 7 May 2014 15:39:30 -0400 Subject: [PATCH 12/60] AES-NI encrypt and decrypt --- aes.cpp | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- aes.h | 6 ++++-- 2 files changed, 59 insertions(+), 3 deletions(-) diff --git a/aes.cpp b/aes.cpp index 2eedf0ad..7c2ff36c 100644 --- a/aes.cpp +++ b/aes.cpp @@ -33,7 +33,7 @@ namespace crypto "add $32, %%rcx \n" - void ECNEncryptionAESNI::SetKey (const uint8_t * key) + void ECNCryptoAESNI::SetKey (const uint8_t * key) { __asm__ ( @@ -72,6 +72,60 @@ namespace crypto ); } + void ECNCryptoAESNI::Encrypt (const ChipherBlock * in, ChipherBlock * out) + { + __asm__ + ( + "movq %0, %%rdx \n" + "movups (%%rsi), %%xmm0 \n" + "pxor (%%rdx), %%xmm0 \n" + "aesenc 16(%%rdx), %%xmm0 \n" + "aesenc 32(%%rdx), %%xmm0 \n" + "aesenc 64(%%rdx), %%xmm0 \n" + "aesenc 80(%%rdx), %%xmm0 \n" + "aesenc 96(%%rdx), %%xmm0 \n" + "aesenc 112(%%rdx), %%xmm0 \n" + "aesenc 128(%%rdx), %%xmm0 \n" + "aesenc 144(%%rdx), %%xmm0 \n" + "aesenc 160(%%rdx), %%xmm0 \n" + "aesenc 176(%%rdx), %%xmm0 \n" + "aesenc 192(%%rdx), %%xmm0 \n" + "aesenc 208(%%rdx), %%xmm0 \n" + "aesenclast 224(%%rdx), %%xmm0 \n" + "movups %%xmm0, (%%rdi) \n" + : + : "S" (in), "D" (out), "r" ((uint64_t)m_KeySchedule) + : "%rdx" + ); + } + + void ECNCryptoAESNI::Decrypt (const ChipherBlock * in, ChipherBlock * out) + { + __asm__ + ( + "movq %0, %%rdx \n" + "movups (%%rsi), %%xmm0 \n" + "pxor 224(%%rdx), %%xmm0 \n" + "aesdec 208(%%rdx), %%xmm0 \n" + "aesdec 192(%%rdx), %%xmm0 \n" + "aesdec 176(%%rdx), %%xmm0 \n" + "aesdec 160(%%rdx), %%xmm0 \n" + "aesdec 144(%%rdx), %%xmm0 \n" + "aesdec 128(%%rdx), %%xmm0 \n" + "aesdec 112(%%rdx), %%xmm0 \n" + "aesdec 96(%%rdx), %%xmm0 \n" + "aesdec 80(%%rdx), %%xmm0 \n" + "aesdec 64(%%rdx), %%xmm0 \n" + "aesdec 32(%%rdx), %%xmm0 \n" + "aesdec 16(%%rdx), %%xmm0 \n" + "aesdeclast (%%rdx), %%xmm0 \n" + "movups %%xmm0, (%%rdi) \n" + : + : "S" (in), "D" (out), "r" ((uint64_t)m_KeySchedule) + : "%rdx" + ); + } + #endif diff --git a/aes.h b/aes.h index 365c01fd..24533eeb 100644 --- a/aes.h +++ b/aes.h @@ -17,12 +17,14 @@ namespace crypto #ifdef __x86_64__ // AES-NI assumed - class ECNEncryptionAESNI + class ECNCryptoAESNI { public: void SetKey (const uint8_t * key); - + void Encrypt (const ChipherBlock * in, ChipherBlock * out); + void Decrypt (const ChipherBlock * in, ChipherBlock * out); + private: uint32_t m_KeySchedule[4*(14+1)]; // 14 rounds for AES-256 From 54e042b08d346c643a082cbf1d8c917eeb8218fa Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 7 May 2014 15:40:24 -0400 Subject: [PATCH 13/60] AES-NI encrypt and decrypt --- aes.cpp | 6 +++--- aes.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/aes.cpp b/aes.cpp index 7c2ff36c..1e75b76d 100644 --- a/aes.cpp +++ b/aes.cpp @@ -33,7 +33,7 @@ namespace crypto "add $32, %%rcx \n" - void ECNCryptoAESNI::SetKey (const uint8_t * key) + void ECBCryptoAESNI::SetKey (const uint8_t * key) { __asm__ ( @@ -72,7 +72,7 @@ namespace crypto ); } - void ECNCryptoAESNI::Encrypt (const ChipherBlock * in, ChipherBlock * out) + void ECBCryptoAESNI::Encrypt (const ChipherBlock * in, ChipherBlock * out) { __asm__ ( @@ -99,7 +99,7 @@ namespace crypto ); } - void ECNCryptoAESNI::Decrypt (const ChipherBlock * in, ChipherBlock * out) + void ECBCryptoAESNI::Decrypt (const ChipherBlock * in, ChipherBlock * out) { __asm__ ( diff --git a/aes.h b/aes.h index 24533eeb..2fbe5b0d 100644 --- a/aes.h +++ b/aes.h @@ -17,7 +17,7 @@ namespace crypto #ifdef __x86_64__ // AES-NI assumed - class ECNCryptoAESNI + class ECBCryptoAESNI { public: From 83131a361d1ab59db6703d92db7f8c57238e0e2b Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 7 May 2014 16:24:28 -0400 Subject: [PATCH 14/60] AES-NI encrypt and decrypt --- aes.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aes.cpp b/aes.cpp index 1e75b76d..888a7dda 100644 --- a/aes.cpp +++ b/aes.cpp @@ -94,7 +94,7 @@ namespace crypto "aesenclast 224(%%rdx), %%xmm0 \n" "movups %%xmm0, (%%rdi) \n" : - : "S" (in), "D" (out), "r" ((uint64_t)m_KeySchedule) + : "r" ((uint64_t)m_KeySchedule), "S" (in), "D" (out) : "%rdx" ); } @@ -121,7 +121,7 @@ namespace crypto "aesdeclast (%%rdx), %%xmm0 \n" "movups %%xmm0, (%%rdi) \n" : - : "S" (in), "D" (out), "r" ((uint64_t)m_KeySchedule) + : "r" ((uint64_t)m_KeySchedule), "S" (in), "D" (out) : "%rdx" ); } From 6ba472eee707534e2fad9b62864c93a850833a9b Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 7 May 2014 19:44:43 -0400 Subject: [PATCH 15/60] 8-bytes alignment --- hmac.h | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/hmac.h b/hmac.h index 971b9f1a..9038cf49 100644 --- a/hmac.h +++ b/hmac.h @@ -18,38 +18,38 @@ namespace crypto // digest is 16 bytes // block size is 64 bytes { - uint8_t buf[2048]; + uint64_t buf[256]; // ikeypad - ((uint64_t *)buf)[0] = ((uint64_t *)key)[0] ^ IPAD; - ((uint64_t *)buf)[1] = ((uint64_t *)key)[1] ^ IPAD; - ((uint64_t *)buf)[2] = ((uint64_t *)key)[2] ^ IPAD; - ((uint64_t *)buf)[3] = ((uint64_t *)key)[3] ^ IPAD; - ((uint64_t *)buf)[4] = IPAD; - ((uint64_t *)buf)[5] = IPAD; - ((uint64_t *)buf)[6] = IPAD; - ((uint64_t *)buf)[7] = IPAD; + buf[0] = ((uint64_t *)key)[0] ^ IPAD; + buf[1] = ((uint64_t *)key)[1] ^ IPAD; + buf[2] = ((uint64_t *)key)[2] ^ IPAD; + buf[3] = ((uint64_t *)key)[3] ^ IPAD; + buf[4] = IPAD; + buf[5] = IPAD; + buf[6] = IPAD; + buf[7] = IPAD; // concatenate with msg - memcpy (buf + 64, msg, len); + memcpy (buf + 8, msg, len); // calculate first hash uint8_t hash[16]; // MD5 - CryptoPP::Weak1::MD5().CalculateDigest (hash, buf, len + 64); + CryptoPP::Weak1::MD5().CalculateDigest (hash, (uint8_t *)buf, len + 64); // okeypad - ((uint64_t *)buf)[0] = ((uint64_t *)key)[0] ^ OPAD; - ((uint64_t *)buf)[1] = ((uint64_t *)key)[1] ^ OPAD; - ((uint64_t *)buf)[2] = ((uint64_t *)key)[2] ^ OPAD; - ((uint64_t *)buf)[3] = ((uint64_t *)key)[3] ^ OPAD; - ((uint64_t *)buf)[4] = OPAD; - ((uint64_t *)buf)[5] = OPAD; - ((uint64_t *)buf)[6] = OPAD; - ((uint64_t *)buf)[7] = OPAD; + buf[0] = ((uint64_t *)key)[0] ^ OPAD; + buf[1] = ((uint64_t *)key)[1] ^ OPAD; + buf[2] = ((uint64_t *)key)[2] ^ OPAD; + buf[3] = ((uint64_t *)key)[3] ^ OPAD; + buf[4] = OPAD; + buf[5] = OPAD; + buf[6] = OPAD; + buf[7] = OPAD; // copy first hash after okeypad - memcpy (buf + 64, hash, 16); + memcpy (buf + 8, hash, 16); // fill next 16 bytes with zeros (first hash size assumed 32 bytes in I2P) - memset (buf + 80, 0, 16); + memset (buf + 10, 0, 16); // calculate digest - CryptoPP::Weak1::MD5().CalculateDigest (digest, buf, 96); + CryptoPP::Weak1::MD5().CalculateDigest (digest, (uint8_t *)buf, 96); } } } From 58a5c0f542de7d0e87e4fa735346fc932a1e54c1 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 8 May 2014 09:52:56 -0400 Subject: [PATCH 16/60] load pointer to rdx directly --- aes.cpp | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/aes.cpp b/aes.cpp index 888a7dda..a0e017b3 100644 --- a/aes.cpp +++ b/aes.cpp @@ -76,7 +76,6 @@ namespace crypto { __asm__ ( - "movq %0, %%rdx \n" "movups (%%rsi), %%xmm0 \n" "pxor (%%rdx), %%xmm0 \n" "aesenc 16(%%rdx), %%xmm0 \n" @@ -93,9 +92,7 @@ namespace crypto "aesenc 208(%%rdx), %%xmm0 \n" "aesenclast 224(%%rdx), %%xmm0 \n" "movups %%xmm0, (%%rdi) \n" - : - : "r" ((uint64_t)m_KeySchedule), "S" (in), "D" (out) - : "%rdx" + : : "d" ((uint64_t)m_KeySchedule), "S" (in), "D" (out) ); } @@ -103,7 +100,6 @@ namespace crypto { __asm__ ( - "movq %0, %%rdx \n" "movups (%%rsi), %%xmm0 \n" "pxor 224(%%rdx), %%xmm0 \n" "aesdec 208(%%rdx), %%xmm0 \n" @@ -120,9 +116,7 @@ namespace crypto "aesdec 16(%%rdx), %%xmm0 \n" "aesdeclast (%%rdx), %%xmm0 \n" "movups %%xmm0, (%%rdi) \n" - : - : "r" ((uint64_t)m_KeySchedule), "S" (in), "D" (out) - : "%rdx" + : : "d" ((uint64_t)m_KeySchedule), "S" (in), "D" (out) ); } From 0408371a84303d7df7c74dc83cac807b4e6e9bf4 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 8 May 2014 11:53:54 -0400 Subject: [PATCH 17/60] fixed key expansion --- aes.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/aes.cpp b/aes.cpp index a0e017b3..0c3d723f 100644 --- a/aes.cpp +++ b/aes.cpp @@ -50,11 +50,11 @@ namespace crypto KeyExpansion256 "aeskeygenassist $8, %%xmm3, %%xmm2 \n" KeyExpansion256 - "aeskeygenassist $10, %%xmm3, %%xmm2 \n" + "aeskeygenassist $16, %%xmm3, %%xmm2 \n" KeyExpansion256 - "aeskeygenassist $20, %%xmm3, %%xmm2 \n" + "aeskeygenassist $32, %%xmm3, %%xmm2 \n" KeyExpansion256 - "aeskeygenassist $40, %%xmm3, %%xmm2 \n" + "aeskeygenassist $64, %%xmm3, %%xmm2 \n" // key expansion final "pshufd $0xff, %%xmm2, %%xmm2 \n" "movaps %%xmm1, %%xmm4 \n" From 4ef971f63cec414f19c9f5cf4c682edbd847c7ea Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 8 May 2014 15:11:38 -0400 Subject: [PATCH 18/60] invert expanded key schedule for decryption --- aes.cpp | 42 +++++++++++++++++++++++++++++++++++------- aes.h | 24 +++++++++++++++++++----- 2 files changed, 54 insertions(+), 12 deletions(-) diff --git a/aes.cpp b/aes.cpp index 0c3d723f..1529487b 100644 --- a/aes.cpp +++ b/aes.cpp @@ -33,7 +33,7 @@ namespace crypto "add $32, %%rcx \n" - void ECBCryptoAESNI::SetKey (const uint8_t * key) + void ECBCryptoAESNI::ExpandKey (const uint8_t * key) { __asm__ ( @@ -68,11 +68,11 @@ namespace crypto "movups %%xmm1, (%%rcx) \n" : // output : "S" (key), "D" (m_KeySchedule) // input - : "%rcx" // modified + : "%rcx" // clogged ); } - void ECBCryptoAESNI::Encrypt (const ChipherBlock * in, ChipherBlock * out) + void ECBEncryptionAESNI::Encrypt (const ChipherBlock * in, ChipherBlock * out) { __asm__ ( @@ -92,11 +92,11 @@ namespace crypto "aesenc 208(%%rdx), %%xmm0 \n" "aesenclast 224(%%rdx), %%xmm0 \n" "movups %%xmm0, (%%rdi) \n" - : : "d" ((uint64_t)m_KeySchedule), "S" (in), "D" (out) + : : "d" (m_KeySchedule), "S" (in), "D" (out) ); - } + } - void ECBCryptoAESNI::Decrypt (const ChipherBlock * in, ChipherBlock * out) + void ECBDecryptionAESNI::Decrypt (const ChipherBlock * in, ChipherBlock * out) { __asm__ ( @@ -116,10 +116,38 @@ namespace crypto "aesdec 16(%%rdx), %%xmm0 \n" "aesdeclast (%%rdx), %%xmm0 \n" "movups %%xmm0, (%%rdi) \n" - : : "d" ((uint64_t)m_KeySchedule), "S" (in), "D" (out) + : : "d" (m_KeySchedule), "S" (in), "D" (out) ); } + #define CallAESIMC(offset) \ + "movups "#offset"(%%rdx), %%xmm0 \n" \ + "aesimc %%xmm0, %%xmm0 \n" \ + "movups %%xmm0, "#offset"(%%rdx) \n" + + void ECBDecryptionAESNI::SetKey (const uint8_t * key) + { + ExpandKey (key); // expand encryption key first + // then invert it using aesimc + __asm__ + ( + CallAESIMC(16) + CallAESIMC(32) + CallAESIMC(48) + CallAESIMC(64) + CallAESIMC(80) + CallAESIMC(96) + CallAESIMC(112) + CallAESIMC(128) + CallAESIMC(144) + CallAESIMC(160) + CallAESIMC(176) + CallAESIMC(192) + CallAESIMC(208) + : : "d" (m_KeySchedule) + ); + } + #endif diff --git a/aes.h b/aes.h index 2fbe5b0d..0b7866ab 100644 --- a/aes.h +++ b/aes.h @@ -18,16 +18,30 @@ namespace crypto #ifdef __x86_64__ // AES-NI assumed class ECBCryptoAESNI + { + protected: + + void ExpandKey (const uint8_t * key); + + protected: + + uint32_t m_KeySchedule[4*(14+1)]; // 14 rounds for AES-256 + }; + + class ECBEncryptionAESNI: public ECBCryptoAESNI { public: - void SetKey (const uint8_t * key); + void SetKey (const uint8_t * key) { ExpandKey (key); }; void Encrypt (const ChipherBlock * in, ChipherBlock * out); - void Decrypt (const ChipherBlock * in, ChipherBlock * out); - - private: + }; - uint32_t m_KeySchedule[4*(14+1)]; // 14 rounds for AES-256 + class ECBDecryptionAESNI: public ECBCryptoAESNI + { + public: + + void SetKey (const uint8_t * key); + void Decrypt (const ChipherBlock * in, ChipherBlock * out); }; #endif From b4d7116ab8a43a43a3357b5af87db34ec34e3e6b Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 8 May 2014 16:16:42 -0400 Subject: [PATCH 19/60] fixed typo --- aes.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/aes.cpp b/aes.cpp index 1529487b..92ae089c 100644 --- a/aes.cpp +++ b/aes.cpp @@ -80,6 +80,7 @@ namespace crypto "pxor (%%rdx), %%xmm0 \n" "aesenc 16(%%rdx), %%xmm0 \n" "aesenc 32(%%rdx), %%xmm0 \n" + "aesenc 48(%%rdx), %%xmm0 \n" "aesenc 64(%%rdx), %%xmm0 \n" "aesenc 80(%%rdx), %%xmm0 \n" "aesenc 96(%%rdx), %%xmm0 \n" @@ -112,6 +113,7 @@ namespace crypto "aesdec 96(%%rdx), %%xmm0 \n" "aesdec 80(%%rdx), %%xmm0 \n" "aesdec 64(%%rdx), %%xmm0 \n" + "aesdec 48(%%rdx), %%xmm0 \n" "aesdec 32(%%rdx), %%xmm0 \n" "aesdec 16(%%rdx), %%xmm0 \n" "aesdeclast (%%rdx), %%xmm0 \n" From 63bf67ba95d678e0878f1734b3bf0997ad15a785 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 8 May 2014 16:49:00 -0400 Subject: [PATCH 20/60] ECBEncryption implementation --- aes.h | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/aes.h b/aes.h index 0b7866ab..b62bf63c 100644 --- a/aes.h +++ b/aes.h @@ -44,6 +44,48 @@ namespace crypto void Decrypt (const ChipherBlock * in, ChipherBlock * out); }; + typedef ECBEncryptionAESNI ECBEncryption; + typedef ECBDecryptionAESNI ECBDecryption; + +#else // use crypto++ + + class ECBEncryption + { + public: + + void SetKey (const uint8_t * key) + { + m_Encryption.SetKey (key, 32); + } + void Encrypt (const ChipherBlock * in, ChipherBlock * out) + { + m_Encryption.ProcessData (out->buf, in->buf, 16); + } + + private: + + CryptoPP::ECB_Mode::Encryption m_Encryption; + }; + + class ECBDecryption + { + public: + + void SetKey (const uint8_t * key) + { + m_Decryption.SetKey (key, 32); + } + void Decrypt (const ChipherBlock * in, ChipherBlock * out) + { + m_Decryption.ProcessData (out->buf, in->buf, 16); + } + + private: + + CryptoPP::ECB_Mode::Decryption m_Decryption; + }; + + #endif class CBCEncryption From 95013e95a998fc775f5784ad3aa0c66ef332b1e8 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 8 May 2014 21:43:08 -0400 Subject: [PATCH 21/60] use AES-NI in new CBC encryption --- aes.cpp | 14 +++++++++++--- aes.h | 15 ++++++++++----- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/aes.cpp b/aes.cpp index 92ae089c..2036ac35 100644 --- a/aes.cpp +++ b/aes.cpp @@ -7,7 +7,15 @@ namespace crypto { #ifdef __x86_64__ - + + ECBCryptoAESNI::ECBCryptoAESNI () + { + m_KeySchedule = m_UnalignedBuffer; + uint8_t rem = ((uint64_t)m_KeySchedule) & 0x0f; + if (rem) + m_KeySchedule += (16 - rem); + } + #define KeyExpansion256 \ "pshufd $0xff, %%xmm2, %%xmm2 \n" \ "movaps %%xmm1, %%xmm4 \n" \ @@ -159,7 +167,7 @@ namespace crypto { m_LastBlock.ll[0] ^= in[i].ll[0]; m_LastBlock.ll[1] ^= in[i].ll[1]; - m_ECBEncryption.ProcessData (m_LastBlock.buf, m_LastBlock.buf, 16); + m_ECBEncryption.Encrypt (&m_LastBlock, &m_LastBlock); out[i] = m_LastBlock; } } @@ -177,7 +185,7 @@ namespace crypto for (int i = 0; i < numBlocks; i++) { ChipherBlock tmp = in[i]; - m_ECBDecryption.ProcessData (out[i].buf, in[i].buf, 16); + m_ECBDecryption.Decrypt (in + i, out + i); out[i].ll[0] ^= m_IV.ll[0]; out[i].ll[1] ^= m_IV.ll[1]; m_IV = tmp; diff --git a/aes.h b/aes.h index b62bf63c..f9dee69c 100644 --- a/aes.h +++ b/aes.h @@ -19,13 +19,18 @@ namespace crypto // AES-NI assumed class ECBCryptoAESNI { + public: + + ECBCryptoAESNI (); + protected: void ExpandKey (const uint8_t * key); protected: - uint32_t m_KeySchedule[4*(14+1)]; // 14 rounds for AES-256 + uint8_t * m_KeySchedule; // start of 16 bytes boundary of m_UnalignedBuffer + uint8_t m_UnalignedBuffer[256]; // 14 rounds for AES-256, 240 + 16 bytes }; class ECBEncryptionAESNI: public ECBCryptoAESNI @@ -94,7 +99,7 @@ namespace crypto CBCEncryption () { memset (m_LastBlock.buf, 0, 16); }; - void SetKey (const uint8_t * key) { m_ECBEncryption.SetKey (key, 32); }; // 32 bytes + void SetKey (const uint8_t * key) { m_ECBEncryption.SetKey (key); }; // 32 bytes void SetIV (const uint8_t * iv) { memcpy (m_LastBlock.buf, iv, 16); }; // 16 bytes void Encrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out); @@ -103,7 +108,7 @@ namespace crypto private: ChipherBlock m_LastBlock; - CryptoPP::ECB_Mode::Encryption m_ECBEncryption; + ECBEncryption m_ECBEncryption; }; class CBCDecryption @@ -112,7 +117,7 @@ namespace crypto CBCDecryption () { memset (m_IV.buf, 0, 16); }; - void SetKey (const uint8_t * key) { m_ECBDecryption.SetKey (key, 32); }; // 32 bytes + void SetKey (const uint8_t * key) { m_ECBDecryption.SetKey (key); }; // 32 bytes void SetIV (const uint8_t * iv) { memcpy (m_IV.buf, iv, 16); }; // 16 bytes void Decrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out); @@ -121,7 +126,7 @@ namespace crypto private: ChipherBlock m_IV; - CryptoPP::ECB_Mode::Decryption m_ECBDecryption; + ECBDecryption m_ECBDecryption; }; } } From 61147def942c1701eb0e01086c73bfd25d8d10d9 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 9 May 2014 07:59:40 -0400 Subject: [PATCH 22/60] use AES-NI for transit tunnel encryption --- TransitTunnel.cpp | 16 +++++++--------- TransitTunnel.h | 9 +++------ 2 files changed, 10 insertions(+), 15 deletions(-) diff --git a/TransitTunnel.cpp b/TransitTunnel.cpp index a96f3d05..146b6572 100644 --- a/TransitTunnel.cpp +++ b/TransitTunnel.cpp @@ -17,22 +17,20 @@ namespace tunnel m_TunnelID (receiveTunnelID), m_NextTunnelID (nextTunnelID), m_NextIdent (nextIdent), m_NumTransmittedBytes (0) { - memcpy (m_LayerKey, layerKey, 32); - memcpy (m_IVKey, ivKey, 32); + m_ECBEncryption.SetKey (ivKey); + m_CBCEncryption.SetKey (layerKey); } void TransitTunnel::EncryptTunnelMsg (I2NPMessage * tunnelMsg) { uint8_t * payload = tunnelMsg->GetPayload () + 4; - m_ECBEncryption.SetKey (m_IVKey, 32); - m_ECBEncryption.ProcessData(payload, payload, 16); // iv - - m_CBCEncryption.SetKeyWithIV (m_LayerKey, 32, payload); - m_CBCEncryption.ProcessData(payload + 16, payload + 16, TUNNEL_DATA_ENCRYPTED_SIZE); // payload + + m_ECBEncryption.Encrypt ((i2p::crypto::ChipherBlock *)payload, (i2p::crypto::ChipherBlock *)payload); // iv - m_ECBEncryption.SetKey (m_IVKey, 32); - m_ECBEncryption.ProcessData(payload, payload, 16); // double iv encryption + m_CBCEncryption.SetIV (payload); + m_CBCEncryption.Encrypt (payload + 16, TUNNEL_DATA_ENCRYPTED_SIZE, payload + 16); // payload + m_ECBEncryption.Encrypt((i2p::crypto::ChipherBlock *)payload, (i2p::crypto::ChipherBlock *)payload); // double iv encryption } void TransitTunnel::HandleTunnelDataMsg (i2p::I2NPMessage * tunnelMsg) diff --git a/TransitTunnel.h b/TransitTunnel.h index feeeaa58..a85c2f2c 100644 --- a/TransitTunnel.h +++ b/TransitTunnel.h @@ -2,8 +2,7 @@ #define TRANSIT_TUNNEL_H__ #include -#include -#include +#include "aes.h" #include "I2NPProtocol.h" #include "TunnelEndpoint.h" #include "TunnelGateway.h" @@ -36,12 +35,10 @@ namespace tunnel uint32_t m_TunnelID, m_NextTunnelID; i2p::data::IdentHash m_NextIdent; - uint8_t m_LayerKey[32]; - uint8_t m_IVKey[32]; size_t m_NumTransmittedBytes; - CryptoPP::ECB_Mode::Encryption m_ECBEncryption; - CryptoPP::CBC_Mode::Encryption m_CBCEncryption; + i2p::crypto::ECBEncryption m_ECBEncryption; + i2p::crypto::CBCEncryption m_CBCEncryption; }; class TransitTunnelGateway: public TransitTunnel From 9372b33c2ccff0d0e2643c6f29e152b89a1b2e0d Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 9 May 2014 11:44:39 -0400 Subject: [PATCH 23/60] ChiperBlock XOR --- aes.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/aes.h b/aes.h index f9dee69c..89a3a62d 100644 --- a/aes.h +++ b/aes.h @@ -13,6 +13,22 @@ namespace crypto { uint8_t buf[16]; uint64_t ll[2]; + + void operator^(const ChipherBlock& other) // XOR + { +#ifdef __x86_64__ + __asm__ + ( + "movups (%[b1]), %%xmm0 \n" + "pxor (%[b2]), %%xmm0 \n" + "movups %%xmm0, (%[b1]) \n" + : : [b1]"r"(buf), [b2]"r"(other.buf): "memory", "%xmm0" + ); +#else + ll[0] ^= other.ll[0]; + ll[1] ^= other.ll[1]; +#endif + } }; #ifdef __x86_64__ From 37c3a9dcf1a34cbe4241e3e056dc7e4c7d00bd9d Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 9 May 2014 12:05:04 -0400 Subject: [PATCH 24/60] ChiperBlock XOR --- aes.cpp | 6 ++---- aes.h | 5 +++-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/aes.cpp b/aes.cpp index 2036ac35..48dc8fc2 100644 --- a/aes.cpp +++ b/aes.cpp @@ -165,8 +165,7 @@ namespace crypto { for (int i = 0; i < numBlocks; i++) { - m_LastBlock.ll[0] ^= in[i].ll[0]; - m_LastBlock.ll[1] ^= in[i].ll[1]; + m_LastBlock ^= in[i]; m_ECBEncryption.Encrypt (&m_LastBlock, &m_LastBlock); out[i] = m_LastBlock; } @@ -186,8 +185,7 @@ namespace crypto { ChipherBlock tmp = in[i]; m_ECBDecryption.Decrypt (in + i, out + i); - out[i].ll[0] ^= m_IV.ll[0]; - out[i].ll[1] ^= m_IV.ll[1]; + out[i] ^= m_IV; m_IV = tmp; } } diff --git a/aes.h b/aes.h index 89a3a62d..dac7d378 100644 --- a/aes.h +++ b/aes.h @@ -14,13 +14,14 @@ namespace crypto uint8_t buf[16]; uint64_t ll[2]; - void operator^(const ChipherBlock& other) // XOR + void operator^=(const ChipherBlock& other) // XOR { #ifdef __x86_64__ __asm__ ( "movups (%[b1]), %%xmm0 \n" - "pxor (%[b2]), %%xmm0 \n" + "movups (%[b2]), %%xmm1 \n" // b2 might not be 16-bytes aligned + "pxor %%xmm1, %%xmm0 \n" "movups %%xmm0, (%[b1]) \n" : : [b1]"r"(buf), [b2]"r"(other.buf): "memory", "%xmm0" ); From 2cdd3c3c26c5f2dbcba1a795f85354fd8ba9e982 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 9 May 2014 14:11:05 -0400 Subject: [PATCH 25/60] eliminate hardcoded registers --- aes.cpp | 96 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 48 insertions(+), 48 deletions(-) diff --git a/aes.cpp b/aes.cpp index 48dc8fc2..ee7d455b 100644 --- a/aes.cpp +++ b/aes.cpp @@ -26,7 +26,7 @@ namespace crypto "pslldq $4, %%xmm4 \n" \ "pxor %%xmm4, %%xmm1 \n" \ "pxor %%xmm2, %%xmm1 \n" \ - "movups %%xmm1, (%%rcx) \n" \ + "movaps %%xmm1, (%%rcx) \n" \ "aeskeygenassist $0, %%xmm1, %%xmm4 \n" \ "pshufd $0xaa, %%xmm4, %%xmm2 \n" \ "movaps %%xmm3, %%xmm4 \n" \ @@ -37,7 +37,7 @@ namespace crypto "pslldq $4, %%xmm4 \n" \ "pxor %%xmm4, %%xmm3 \n" \ "pxor %%xmm2, %%xmm3 \n" \ - "movups %%xmm3, 16(%%rcx) \n" \ + "movaps %%xmm3, 16(%%rcx) \n" \ "add $32, %%rcx \n" @@ -45,11 +45,11 @@ namespace crypto { __asm__ ( - "movups (%%rsi), %%xmm1 \n" - "movups 16(%%rsi), %%xmm3 \n" - "movups %%xmm1, (%%rdi) \n" - "movups %%xmm3, 16(%%rdi) \n" - "lea 32(%%rdi), %%rcx \n" + "movups (%[key]), %%xmm1 \n" + "movups 16(%[key]), %%xmm3 \n" + "movaps %%xmm1, (%[shed]) \n" + "movaps %%xmm3, 16(%[shed]) \n" + "lea 32(%[shed]), %%rcx \n" "aeskeygenassist $1, %%xmm3, %%xmm2 \n" KeyExpansion256 "aeskeygenassist $2, %%xmm3, %%xmm2 \n" @@ -75,8 +75,8 @@ namespace crypto "pxor %%xmm2, %%xmm1 \n" "movups %%xmm1, (%%rcx) \n" : // output - : "S" (key), "D" (m_KeySchedule) // input - : "%rcx" // clogged + : [key]"r"(key), [shed]"r"(m_KeySchedule) // input + : "%rcx", "%xmm1", "%xmm2", "%xmm3", "%xmm4" // clogged ); } @@ -84,24 +84,24 @@ namespace crypto { __asm__ ( - "movups (%%rsi), %%xmm0 \n" - "pxor (%%rdx), %%xmm0 \n" - "aesenc 16(%%rdx), %%xmm0 \n" - "aesenc 32(%%rdx), %%xmm0 \n" - "aesenc 48(%%rdx), %%xmm0 \n" - "aesenc 64(%%rdx), %%xmm0 \n" - "aesenc 80(%%rdx), %%xmm0 \n" - "aesenc 96(%%rdx), %%xmm0 \n" - "aesenc 112(%%rdx), %%xmm0 \n" - "aesenc 128(%%rdx), %%xmm0 \n" - "aesenc 144(%%rdx), %%xmm0 \n" - "aesenc 160(%%rdx), %%xmm0 \n" - "aesenc 176(%%rdx), %%xmm0 \n" - "aesenc 192(%%rdx), %%xmm0 \n" - "aesenc 208(%%rdx), %%xmm0 \n" - "aesenclast 224(%%rdx), %%xmm0 \n" - "movups %%xmm0, (%%rdi) \n" - : : "d" (m_KeySchedule), "S" (in), "D" (out) + "movups (%[in]), %%xmm0 \n" + "pxor (%[shed]), %%xmm0 \n" + "aesenc 16(%[shed]), %%xmm0 \n" + "aesenc 32(%[shed]), %%xmm0 \n" + "aesenc 48(%[shed]), %%xmm0 \n" + "aesenc 64(%[shed]), %%xmm0 \n" + "aesenc 80(%[shed]), %%xmm0 \n" + "aesenc 96(%[shed]), %%xmm0 \n" + "aesenc 112(%[shed]), %%xmm0 \n" + "aesenc 128(%[shed]), %%xmm0 \n" + "aesenc 144(%[shed]), %%xmm0 \n" + "aesenc 160(%[shed]), %%xmm0 \n" + "aesenc 176(%[shed]), %%xmm0 \n" + "aesenc 192(%[shed]), %%xmm0 \n" + "aesenc 208(%[shed]), %%xmm0 \n" + "aesenclast 224(%[shed]), %%xmm0 \n" + "movups %%xmm0, (%[out]) \n" + : : [shed]"r"(m_KeySchedule), [in]"r"(in), [out]"r"(out) : "%xmm0" ); } @@ -109,31 +109,31 @@ namespace crypto { __asm__ ( - "movups (%%rsi), %%xmm0 \n" - "pxor 224(%%rdx), %%xmm0 \n" - "aesdec 208(%%rdx), %%xmm0 \n" - "aesdec 192(%%rdx), %%xmm0 \n" - "aesdec 176(%%rdx), %%xmm0 \n" - "aesdec 160(%%rdx), %%xmm0 \n" - "aesdec 144(%%rdx), %%xmm0 \n" - "aesdec 128(%%rdx), %%xmm0 \n" - "aesdec 112(%%rdx), %%xmm0 \n" - "aesdec 96(%%rdx), %%xmm0 \n" - "aesdec 80(%%rdx), %%xmm0 \n" - "aesdec 64(%%rdx), %%xmm0 \n" - "aesdec 48(%%rdx), %%xmm0 \n" - "aesdec 32(%%rdx), %%xmm0 \n" - "aesdec 16(%%rdx), %%xmm0 \n" - "aesdeclast (%%rdx), %%xmm0 \n" - "movups %%xmm0, (%%rdi) \n" - : : "d" (m_KeySchedule), "S" (in), "D" (out) + "movups (%[in]), %%xmm0 \n" + "pxor 224(%[shed]), %%xmm0 \n" + "aesdec 208(%[shed]), %%xmm0 \n" + "aesdec 192(%[shed]), %%xmm0 \n" + "aesdec 176(%[shed]), %%xmm0 \n" + "aesdec 160(%[shed]), %%xmm0 \n" + "aesdec 144(%[shed]), %%xmm0 \n" + "aesdec 128(%[shed]), %%xmm0 \n" + "aesdec 112(%[shed]), %%xmm0 \n" + "aesdec 96(%[shed]), %%xmm0 \n" + "aesdec 80(%[shed]), %%xmm0 \n" + "aesdec 64(%[shed]), %%xmm0 \n" + "aesdec 48(%[shed]), %%xmm0 \n" + "aesdec 32(%[shed]), %%xmm0 \n" + "aesdec 16(%[shed]), %%xmm0 \n" + "aesdeclast (%[shed]), %%xmm0 \n" + "movups %%xmm0, (%[out]) \n" + : : [shed]"r"(m_KeySchedule), [in]"r"(in), [out]"r"(out) : "%xmm0" ); } #define CallAESIMC(offset) \ - "movups "#offset"(%%rdx), %%xmm0 \n" \ + "movaps "#offset"(%[shed]), %%xmm0 \n" \ "aesimc %%xmm0, %%xmm0 \n" \ - "movups %%xmm0, "#offset"(%%rdx) \n" + "movaps %%xmm0, "#offset"(%[shed]) \n" void ECBDecryptionAESNI::SetKey (const uint8_t * key) { @@ -154,7 +154,7 @@ namespace crypto CallAESIMC(176) CallAESIMC(192) CallAESIMC(208) - : : "d" (m_KeySchedule) + : : [shed]"r"(m_KeySchedule) : "%xmm0" ); } From cc302847a84a2ac956c785ccbf9dfff1f094e3ed Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 9 May 2014 19:34:12 -0400 Subject: [PATCH 26/60] replace tunnel encryption to AES-NI --- Tunnel.cpp | 45 ++++++++++++++++++++++----------------------- Tunnel.h | 13 +------------ TunnelConfig.h | 7 ++++++- 3 files changed, 29 insertions(+), 36 deletions(-) diff --git a/Tunnel.cpp b/Tunnel.cpp index 4b831fbc..8529df4b 100644 --- a/Tunnel.cpp +++ b/Tunnel.cpp @@ -57,10 +57,8 @@ namespace tunnel while (hop) { for (size_t i = ind; i < numRecords; i++) - { - m_CBCDecryption.SetKeyWithIV (hop->replyKey, 32, hop->replyIV); - m_CBCDecryption.ProcessData((uint8_t *)&records[i], (uint8_t *)&records[i], sizeof (I2NPBuildRequestRecordElGamalEncrypted)); - } + hop->decryption.Decrypt((uint8_t *)&records[i], + sizeof (I2NPBuildRequestRecordElGamalEncrypted), (uint8_t *)&records[i]); hop = hop->prev; ind--; } @@ -83,8 +81,7 @@ namespace tunnel for (int i = 0; i < num; i++) { uint8_t * record = msg + 1 + i*sizeof (I2NPBuildResponseRecord); - m_CBCDecryption.SetKeyWithIV(hop->replyKey, 32, hop->replyIV); - m_CBCDecryption.ProcessData(record, record, sizeof (I2NPBuildResponseRecord)); + hop->decryption.Decrypt(record, sizeof (I2NPBuildResponseRecord), record); } hop = hop->prev; num--; @@ -99,21 +96,19 @@ namespace tunnel // if any of participants declined the tunnel is not established m_IsEstablished = false; } + if (m_IsEstablished) + { + // change reply keys to layer keys + TunnelHopConfig * hop = m_Config->GetFirstHop (); + while (hop) + { + hop->decryption.SetKey (hop->layerKey); + hop->ivDecryption.SetKey (hop->ivKey); + hop = hop->next; + } + } return m_IsEstablished; } - - void Tunnel::LayerDecrypt (const uint8_t * in, size_t len, const uint8_t * layerKey, - const uint8_t * iv, uint8_t * out) - { - m_CBCDecryption.SetKeyWithIV (layerKey, 32, iv); - m_CBCDecryption.ProcessData(out, in, len); - } - - void Tunnel::IVDecrypt (const uint8_t * in, const uint8_t * ivKey, uint8_t * out) - { - m_ECBDecryption.SetKey (ivKey, 32); - m_ECBDecryption.ProcessData(out, in, 16); - } void Tunnel::EncryptTunnelMsg (I2NPMessage * tunnelMsg) { @@ -121,10 +116,14 @@ namespace tunnel TunnelHopConfig * hop = m_Config->GetLastHop (); while (hop) { - // iv + data - IVDecrypt (payload, hop->ivKey, payload); - LayerDecrypt (payload + 16, TUNNEL_DATA_ENCRYPTED_SIZE, hop->layerKey, payload, payload+16); - IVDecrypt (payload, hop->ivKey, payload); + // iv + hop->ivDecryption.Decrypt ((i2p::crypto::ChipherBlock *)payload, (i2p::crypto::ChipherBlock *)payload); + // data + hop->decryption.SetIV (payload); + hop->decryption.Decrypt (payload + 16, TUNNEL_DATA_ENCRYPTED_SIZE, payload+16); + // double iv ecncryption + hop->ivDecryption.Decrypt ((i2p::crypto::ChipherBlock *)payload, (i2p::crypto::ChipherBlock *)payload); + hop = hop->prev; } } diff --git a/Tunnel.h b/Tunnel.h index 16ffa9e4..dc345875 100644 --- a/Tunnel.h +++ b/Tunnel.h @@ -8,8 +8,6 @@ #include #include #include -#include -#include #include "Queue.h" #include "TunnelConfig.h" #include "TunnelPool.h" @@ -51,20 +49,11 @@ namespace tunnel uint32_t GetNextTunnelID () const { return m_Config->GetFirstHop ()->tunnelID; }; const i2p::data::IdentHash& GetNextIdentHash () const { return m_Config->GetFirstHop ()->router->GetIdentHash (); }; - private: - - void LayerDecrypt (const uint8_t * in, size_t len, const uint8_t * layerKey, - const uint8_t * iv, uint8_t * out); - void IVDecrypt (const uint8_t * in, const uint8_t * ivKey, uint8_t * out); - private: TunnelConfig * m_Config; TunnelPool * m_Pool; // pool, tunnel belongs to, or null - bool m_IsEstablished, m_IsFailed; - - CryptoPP::ECB_Mode::Decryption m_ECBDecryption; - CryptoPP::CBC_Mode::Decryption m_CBCDecryption; + bool m_IsEstablished, m_IsFailed; }; class OutboundTunnel: public Tunnel diff --git a/TunnelConfig.h b/TunnelConfig.h index b6eccda4..3db6c30e 100644 --- a/TunnelConfig.h +++ b/TunnelConfig.h @@ -4,6 +4,7 @@ #include #include #include +#include "aes.h" #include "RouterInfo.h" #include "RouterContext.h" @@ -22,7 +23,9 @@ namespace tunnel bool isGateway, isEndpoint; TunnelHopConfig * next, * prev; - + i2p::crypto::CBCDecryption decryption; + i2p::crypto::ECBDecryption ivDecryption; + TunnelHopConfig (const i2p::data::RouterInfo * r) { CryptoPP::RandomNumberGenerator& rnd = i2p::context.GetRandomNumberGenerator (); @@ -38,6 +41,8 @@ namespace tunnel next = 0; prev = 0; + decryption.SetKey (replyKey); + decryption.SetIV (replyIV); } void SetNextRouter (const i2p::data::RouterInfo * r) From 3eb4cc9eed6eff629cc685be32267ba316b420e9 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 11 May 2014 22:37:33 -0400 Subject: [PATCH 27/60] use AEN-NI for garlic encryption --- Garlic.cpp | 32 +++++++++++++++++++------------- Garlic.h | 12 ++++++------ aes.h | 11 ----------- 3 files changed, 25 insertions(+), 30 deletions(-) diff --git a/Garlic.cpp b/Garlic.cpp index b4b4623a..85294271 100644 --- a/Garlic.cpp +++ b/Garlic.cpp @@ -20,6 +20,7 @@ namespace garlic { // create new session tags and session key m_Rnd.GenerateBlock (m_SessionKey, 32); + m_Encryption.SetKey (m_SessionKey); if (m_NumTags > 0) { m_SessionTags = new uint8_t[m_NumTags*32]; @@ -77,7 +78,7 @@ namespace garlic uint8_t iv[32]; // IV is first 16 bytes CryptoPP::SHA256().CalculateDigest(iv, elGamal.preIV, 32); m_Destination.GetElGamalEncryption ()->Encrypt ((uint8_t *)&elGamal, sizeof(elGamal), buf, true); - m_Encryption.SetKeyWithIV (m_SessionKey, 32, iv); + m_Encryption.SetIV (iv); buf += 514; len += 514; } @@ -87,7 +88,7 @@ namespace garlic memcpy (buf, m_SessionTags + m_NextTag*32, 32); uint8_t iv[32]; // IV is first 16 bytes CryptoPP::SHA256().CalculateDigest(iv, m_SessionTags + m_NextTag*32, 32); - m_Encryption.SetKeyWithIV (m_SessionKey, 32, iv); + m_Encryption.SetIV (iv); buf += 32; len += 32; @@ -132,7 +133,7 @@ namespace garlic size_t rem = blockSize % 16; if (rem) blockSize += (16-rem); //padding - m_Encryption.ProcessData(buf, buf, blockSize); + m_Encryption.Encrypt(buf, blockSize, buf); return blockSize; } @@ -248,6 +249,9 @@ namespace garlic for (auto it: m_Sessions) delete it.second; m_Sessions.clear (); + for (auto it: m_SessionDecryptions) + delete it; + m_SessionDecryptions.clear (); } I2NPMessage * GarlicRouting::WrapSingleMessage (const i2p::data::RoutingDestination& destination, I2NPMessage * msg) @@ -298,13 +302,12 @@ namespace garlic if (it != m_SessionTags.end ()) { // existing session - std::string sessionKey (it->second); - m_SessionTags.erase (it); // tag might be used only once uint8_t iv[32]; // IV is first 16 bytes CryptoPP::SHA256().CalculateDigest(iv, buf, 32); - m_Decryption.SetKeyWithIV ((uint8_t *)sessionKey.c_str (), 32, iv); // tag is mapped to 32 bytes key - m_Decryption.ProcessData(buf + 32, buf + 32, length - 32); - HandleAESBlock (buf + 32, length - 32, (uint8_t *)sessionKey.c_str ()); + it->second->SetIV (iv); + it->second->Decrypt (buf + 32, length - 32, buf + 32); + HandleAESBlock (buf + 32, length - 32, it->second); + m_SessionTags.erase (it); // tag might be used only once } else { @@ -317,11 +320,14 @@ namespace garlic pool ? pool->GetEncryptionPrivateKey () : i2p::context.GetPrivateKey (), buf, (uint8_t *)&elGamal, true)) { + i2p::crypto::CBCDecryption * decryption = new i2p::crypto::CBCDecryption; + m_SessionDecryptions.push_back (decryption); + decryption->SetKey (elGamal.sessionKey); uint8_t iv[32]; // IV is first 16 bytes CryptoPP::SHA256().CalculateDigest(iv, elGamal.preIV, 32); - m_Decryption.SetKeyWithIV (elGamal.sessionKey, 32, iv); - m_Decryption.ProcessData(buf + 514, buf + 514, length - 514); - HandleAESBlock (buf + 514, length - 514, elGamal.sessionKey); + decryption->SetIV (iv); + decryption->Decrypt(buf + 514, length - 514, buf + 514); + HandleAESBlock (buf + 514, length - 514, decryption); } else LogPrint ("Failed to decrypt garlic"); @@ -329,12 +335,12 @@ namespace garlic DeleteI2NPMessage (msg); } - void GarlicRouting::HandleAESBlock (uint8_t * buf, size_t len, uint8_t * sessionKey) + void GarlicRouting::HandleAESBlock (uint8_t * buf, size_t len, i2p::crypto::CBCDecryption * decryption) { uint16_t tagCount = be16toh (*(uint16_t *)buf); buf += 2; for (int i = 0; i < tagCount; i++) - m_SessionTags[std::string ((const char *)(buf + i*32), 32)] = std::string ((const char *)sessionKey, 32); + m_SessionTags[std::string ((const char *)(buf + i*32), 32)] = decryption; buf += tagCount*32; uint32_t payloadSize = be32toh (*(uint32_t *)buf); if (payloadSize > len) diff --git a/Garlic.h b/Garlic.h index 03fd6fe6..7ffb4ce6 100644 --- a/Garlic.h +++ b/Garlic.h @@ -3,11 +3,11 @@ #include #include +#include #include #include -#include -#include #include +#include "aes.h" #include "I2NPProtocol.h" #include "LeaseSet.h" #include "Tunnel.h" @@ -68,7 +68,7 @@ namespace garlic uint8_t * m_SessionTags; // m_NumTags*32 bytes uint32_t m_TagsCreationTime; // seconds since epoch - CryptoPP::CBC_Mode::Encryption m_Encryption; + i2p::crypto::CBCEncryption m_Encryption; CryptoPP::AutoSeededRandomPool m_Rnd; }; @@ -93,7 +93,7 @@ namespace garlic void Run (); void ProcessGarlicMessage (I2NPMessage * msg); - void HandleAESBlock (uint8_t * buf, size_t len, uint8_t * sessionKey); + void HandleAESBlock (uint8_t * buf, size_t len, i2p::crypto::CBCDecryption * decryption); void HandleGarlicPayload (uint8_t * buf, size_t len); private: @@ -105,8 +105,8 @@ namespace garlic std::map m_Sessions; std::map m_CreatedSessions; // msgID -> session // incoming session - std::map m_SessionTags; // tag -> key - CryptoPP::CBC_Mode::Decryption m_Decryption; + std::list m_SessionDecryptions; // multiple tags refer to one decyption + std::map m_SessionTags; // tag -> decryption }; extern GarlicRouting routing; diff --git a/aes.h b/aes.h index dac7d378..09f9ba21 100644 --- a/aes.h +++ b/aes.h @@ -16,19 +16,8 @@ namespace crypto void operator^=(const ChipherBlock& other) // XOR { -#ifdef __x86_64__ - __asm__ - ( - "movups (%[b1]), %%xmm0 \n" - "movups (%[b2]), %%xmm1 \n" // b2 might not be 16-bytes aligned - "pxor %%xmm1, %%xmm0 \n" - "movups %%xmm0, (%[b1]) \n" - : : [b1]"r"(buf), [b2]"r"(other.buf): "memory", "%xmm0" - ); -#else ll[0] ^= other.ll[0]; ll[1] ^= other.ll[1]; -#endif } }; From e9fc2492ddfa837d08b874114efe291f262dd3c6 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 12 May 2014 22:51:59 -0400 Subject: [PATCH 28/60] CBC encryption through AES-NI --- aes.cpp | 100 ++++++++++++++++++++++++++++++++++++-------------------- aes.h | 4 ++- 2 files changed, 67 insertions(+), 37 deletions(-) diff --git a/aes.cpp b/aes.cpp index ee7d455b..32605db4 100644 --- a/aes.cpp +++ b/aes.cpp @@ -47,9 +47,9 @@ namespace crypto ( "movups (%[key]), %%xmm1 \n" "movups 16(%[key]), %%xmm3 \n" - "movaps %%xmm1, (%[shed]) \n" - "movaps %%xmm3, 16(%[shed]) \n" - "lea 32(%[shed]), %%rcx \n" + "movaps %%xmm1, (%[sched]) \n" + "movaps %%xmm3, 16(%[sched]) \n" + "lea 32(%[sched]), %%rcx \n" "aeskeygenassist $1, %%xmm3, %%xmm2 \n" KeyExpansion256 "aeskeygenassist $2, %%xmm3, %%xmm2 \n" @@ -75,58 +75,64 @@ namespace crypto "pxor %%xmm2, %%xmm1 \n" "movups %%xmm1, (%%rcx) \n" : // output - : [key]"r"(key), [shed]"r"(m_KeySchedule) // input + : [key]"r"(key), [sched]"r"(m_KeySchedule) // input : "%rcx", "%xmm1", "%xmm2", "%xmm3", "%xmm4" // clogged ); } + #define EncryptAES256 \ + "pxor (%[sched]), %%xmm0 \n" \ + "aesenc 16(%[sched]), %%xmm0 \n" \ + "aesenc 32(%[sched]), %%xmm0 \n" \ + "aesenc 48(%[sched]), %%xmm0 \n" \ + "aesenc 64(%[sched]), %%xmm0 \n" \ + "aesenc 80(%[sched]), %%xmm0 \n" \ + "aesenc 96(%[sched]), %%xmm0 \n" \ + "aesenc 112(%[sched]), %%xmm0 \n" \ + "aesenc 128(%[sched]), %%xmm0 \n" \ + "aesenc 144(%[sched]), %%xmm0 \n" \ + "aesenc 160(%[sched]), %%xmm0 \n" \ + "aesenc 176(%[sched]), %%xmm0 \n" \ + "aesenc 192(%[sched]), %%xmm0 \n" \ + "aesenc 208(%[sched]), %%xmm0 \n" \ + "aesenclast 224(%[sched]), %%xmm0 \n" + void ECBEncryptionAESNI::Encrypt (const ChipherBlock * in, ChipherBlock * out) { __asm__ ( "movups (%[in]), %%xmm0 \n" - "pxor (%[shed]), %%xmm0 \n" - "aesenc 16(%[shed]), %%xmm0 \n" - "aesenc 32(%[shed]), %%xmm0 \n" - "aesenc 48(%[shed]), %%xmm0 \n" - "aesenc 64(%[shed]), %%xmm0 \n" - "aesenc 80(%[shed]), %%xmm0 \n" - "aesenc 96(%[shed]), %%xmm0 \n" - "aesenc 112(%[shed]), %%xmm0 \n" - "aesenc 128(%[shed]), %%xmm0 \n" - "aesenc 144(%[shed]), %%xmm0 \n" - "aesenc 160(%[shed]), %%xmm0 \n" - "aesenc 176(%[shed]), %%xmm0 \n" - "aesenc 192(%[shed]), %%xmm0 \n" - "aesenc 208(%[shed]), %%xmm0 \n" - "aesenclast 224(%[shed]), %%xmm0 \n" + EncryptAES256 "movups %%xmm0, (%[out]) \n" - : : [shed]"r"(m_KeySchedule), [in]"r"(in), [out]"r"(out) : "%xmm0" + : : [sched]"r"(m_KeySchedule), [in]"r"(in), [out]"r"(out) : "%xmm0" ); } + #define DecryptAES256 \ + "pxor 224(%[sched]), %%xmm0 \n" \ + "aesdec 208(%[sched]), %%xmm0 \n" \ + "aesdec 192(%[sched]), %%xmm0 \n" \ + "aesdec 176(%[sched]), %%xmm0 \n" \ + "aesdec 160(%[sched]), %%xmm0 \n" \ + "aesdec 144(%[sched]), %%xmm0 \n" \ + "aesdec 128(%[sched]), %%xmm0 \n" \ + "aesdec 112(%[sched]), %%xmm0 \n" \ + "aesdec 96(%[sched]), %%xmm0 \n" \ + "aesdec 80(%[sched]), %%xmm0 \n" \ + "aesdec 64(%[sched]), %%xmm0 \n" \ + "aesdec 48(%[sched]), %%xmm0 \n" \ + "aesdec 32(%[sched]), %%xmm0 \n" \ + "aesdec 16(%[sched]), %%xmm0 \n" \ + "aesdeclast (%[sched]), %%xmm0 \n" + void ECBDecryptionAESNI::Decrypt (const ChipherBlock * in, ChipherBlock * out) { __asm__ ( "movups (%[in]), %%xmm0 \n" - "pxor 224(%[shed]), %%xmm0 \n" - "aesdec 208(%[shed]), %%xmm0 \n" - "aesdec 192(%[shed]), %%xmm0 \n" - "aesdec 176(%[shed]), %%xmm0 \n" - "aesdec 160(%[shed]), %%xmm0 \n" - "aesdec 144(%[shed]), %%xmm0 \n" - "aesdec 128(%[shed]), %%xmm0 \n" - "aesdec 112(%[shed]), %%xmm0 \n" - "aesdec 96(%[shed]), %%xmm0 \n" - "aesdec 80(%[shed]), %%xmm0 \n" - "aesdec 64(%[shed]), %%xmm0 \n" - "aesdec 48(%[shed]), %%xmm0 \n" - "aesdec 32(%[shed]), %%xmm0 \n" - "aesdec 16(%[shed]), %%xmm0 \n" - "aesdeclast (%[shed]), %%xmm0 \n" + DecryptAES256 "movups %%xmm0, (%[out]) \n" - : : [shed]"r"(m_KeySchedule), [in]"r"(in), [out]"r"(out) : "%xmm0" + : : [sched]"r"(m_KeySchedule), [in]"r"(in), [out]"r"(out) : "%xmm0" ); } @@ -163,12 +169,34 @@ namespace crypto void CBCEncryption::Encrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out) { +#ifdef __x86_64__ + __asm__ + ( + "movups (%[iv]), %%xmm1 \n" + "block: \n" + "movups (%[in]), %%xmm0 \n" + "pxor %%xmm1, %%xmm0 \n" + EncryptAES256 + "movaps %%xmm0, %%xmm1 \n" + "movups %%xmm0, (%[out]) \n" + "add $16, %[in] \n" + "add $16, %[out] \n" + "dec %[num] \n" + "jnz block; \n" + "movups %%xmm1, (%[iv]) \n" + : + : [iv]"r"(&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; } +#endif } bool CBCEncryption::Encrypt (const uint8_t * in, std::size_t len, uint8_t * out) diff --git a/aes.h b/aes.h index 09f9ba21..5e3fcf4b 100644 --- a/aes.h +++ b/aes.h @@ -28,7 +28,8 @@ namespace crypto public: ECBCryptoAESNI (); - + uint8_t * GetKeySchedule () { return m_KeySchedule; }; + protected: void ExpandKey (const uint8_t * key); @@ -114,6 +115,7 @@ namespace crypto private: ChipherBlock m_LastBlock; + ECBEncryption m_ECBEncryption; }; From 6bf57cc4ae011e880c5ed1bb072beb665a81b61f Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 13 May 2014 11:03:33 -0400 Subject: [PATCH 29/60] eliminated hadrcoded %rcx --- aes.cpp | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/aes.cpp b/aes.cpp index 32605db4..96b1c39f 100644 --- a/aes.cpp +++ b/aes.cpp @@ -16,7 +16,7 @@ namespace crypto m_KeySchedule += (16 - rem); } - #define KeyExpansion256 \ + #define KeyExpansion256(round0,round1) \ "pshufd $0xff, %%xmm2, %%xmm2 \n" \ "movaps %%xmm1, %%xmm4 \n" \ "pslldq $4, %%xmm4 \n" \ @@ -26,7 +26,7 @@ namespace crypto "pslldq $4, %%xmm4 \n" \ "pxor %%xmm4, %%xmm1 \n" \ "pxor %%xmm2, %%xmm1 \n" \ - "movaps %%xmm1, (%%rcx) \n" \ + "movaps %%xmm1, "#round0"(%[sched]) \n" \ "aeskeygenassist $0, %%xmm1, %%xmm4 \n" \ "pshufd $0xaa, %%xmm4, %%xmm2 \n" \ "movaps %%xmm3, %%xmm4 \n" \ @@ -37,9 +37,7 @@ namespace crypto "pslldq $4, %%xmm4 \n" \ "pxor %%xmm4, %%xmm3 \n" \ "pxor %%xmm2, %%xmm3 \n" \ - "movaps %%xmm3, 16(%%rcx) \n" \ - "add $32, %%rcx \n" - + "movaps %%xmm3, "#round1"(%[sched]) \n" void ECBCryptoAESNI::ExpandKey (const uint8_t * key) { @@ -49,19 +47,18 @@ namespace crypto "movups 16(%[key]), %%xmm3 \n" "movaps %%xmm1, (%[sched]) \n" "movaps %%xmm3, 16(%[sched]) \n" - "lea 32(%[sched]), %%rcx \n" "aeskeygenassist $1, %%xmm3, %%xmm2 \n" - KeyExpansion256 + KeyExpansion256(32,48) "aeskeygenassist $2, %%xmm3, %%xmm2 \n" - KeyExpansion256 + KeyExpansion256(64,80) "aeskeygenassist $4, %%xmm3, %%xmm2 \n" - KeyExpansion256 + KeyExpansion256(96,112) "aeskeygenassist $8, %%xmm3, %%xmm2 \n" - KeyExpansion256 + KeyExpansion256(128,144) "aeskeygenassist $16, %%xmm3, %%xmm2 \n" - KeyExpansion256 + KeyExpansion256(160,176) "aeskeygenassist $32, %%xmm3, %%xmm2 \n" - KeyExpansion256 + KeyExpansion256(192,208) "aeskeygenassist $64, %%xmm3, %%xmm2 \n" // key expansion final "pshufd $0xff, %%xmm2, %%xmm2 \n" @@ -73,10 +70,10 @@ namespace crypto "pslldq $4, %%xmm4 \n" "pxor %%xmm4, %%xmm1 \n" "pxor %%xmm2, %%xmm1 \n" - "movups %%xmm1, (%%rcx) \n" + "movups %%xmm1, 224(%[sched]) \n" : // output : [key]"r"(key), [sched]"r"(m_KeySchedule) // input - : "%rcx", "%xmm1", "%xmm2", "%xmm3", "%xmm4" // clogged + : "%xmm1", "%xmm2", "%xmm3", "%xmm4" // clogged ); } From 99c5331cadf3e63cc30acad7c4140529e6971d80 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 13 May 2014 13:43:07 -0400 Subject: [PATCH 30/60] CBC decryption using AES-NI --- aes.cpp | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/aes.cpp b/aes.cpp index 96b1c39f..3edef651 100644 --- a/aes.cpp +++ b/aes.cpp @@ -170,7 +170,7 @@ namespace crypto __asm__ ( "movups (%[iv]), %%xmm1 \n" - "block: \n" + "block_e: \n" "movups (%[in]), %%xmm0 \n" "pxor %%xmm1, %%xmm0 \n" EncryptAES256 @@ -179,7 +179,7 @@ namespace crypto "add $16, %[in] \n" "add $16, %[out] \n" "dec %[num] \n" - "jnz block; \n" + "jnz block_e; \n" "movups %%xmm1, (%[iv]) \n" : : [iv]"r"(&m_LastBlock), [sched]"r"(m_ECBEncryption.GetKeySchedule ()), @@ -206,6 +206,28 @@ namespace crypto void CBCDecryption::Decrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out) { +#ifdef __x86_64__ + __asm__ + ( + "movups (%[iv]), %%xmm1 \n" + "block_d: \n" + "movups (%[in]), %%xmm0 \n" + "movaps %%xmm0, %%xmm2 \n" + DecryptAES256 + "pxor %%xmm1, %%xmm0 \n" + "movups %%xmm0, (%[out]) \n" + "movaps %%xmm2, %%xmm1 \n" + "add $16, %[in] \n" + "add $16, %[out] \n" + "dec %[num] \n" + "jnz block_d; \n" + "movups %%xmm1, (%[iv]) \n" + : + : [iv]"r"(&m_IV), [sched]"r"(m_ECBDecryption.GetKeySchedule ()), + [in]"r"(in), [out]"r"(out), [num]"r"(numBlocks) + : "%xmm0", "%xmm1", "%xmm2", "cc", "memory" + ); +#else for (int i = 0; i < numBlocks; i++) { ChipherBlock tmp = in[i]; @@ -213,12 +235,13 @@ namespace crypto out[i] ^= m_IV; m_IV = tmp; } +#endif } bool CBCDecryption::Decrypt (const uint8_t * in, std::size_t len, uint8_t * out) { div_t d = div (len, 16); - if (d.rem) return false; // len is not multipple of 16 + if (d.rem) return false; // len is not multiple of 16 Decrypt (d.quot, (const ChipherBlock *)in, (ChipherBlock *)out); return true; } From 0a53555ac7b347a1b6d792dc54a05f8f1e6ae3af Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 14 May 2014 14:54:01 -0400 Subject: [PATCH 31/60] one block CBC encryption --- NTCPSession.cpp | 4 ++-- aes.cpp | 42 ++++++++++++++++++++++++++++++++++++++++++ aes.h | 2 ++ 3 files changed, 46 insertions(+), 2 deletions(-) diff --git a/NTCPSession.cpp b/NTCPSession.cpp index 88e4eb0a..9930dead 100644 --- a/NTCPSession.cpp +++ b/NTCPSession.cpp @@ -430,7 +430,7 @@ namespace ntcp m_NextMessage = i2p::NewI2NPMessage (); m_NextMessageOffset = 0; - m_Decryption.Decrypt (encrypted, 16, m_NextMessage->buf); + m_Decryption.Decrypt (encrypted, m_NextMessage->buf); uint16_t dataSize = be16toh (*(uint16_t *)m_NextMessage->buf); if (dataSize) { @@ -450,7 +450,7 @@ namespace ntcp } else // message continues { - m_Decryption.Decrypt (encrypted, 16, m_NextMessage->buf + m_NextMessageOffset); + m_Decryption.Decrypt (encrypted, m_NextMessage->buf + m_NextMessageOffset); m_NextMessageOffset += 16; } diff --git a/aes.cpp b/aes.cpp index 3edef651..d1d45462 100644 --- a/aes.cpp +++ b/aes.cpp @@ -204,6 +204,27 @@ namespace crypto return true; } + void CBCEncryption::Encrypt (const uint8_t * in, uint8_t * out) + { +#ifdef __x86_64__ + __asm__ + ( + "movups (%[iv]), %%xmm1 \n" + "movups (%[in]), %%xmm0 \n" + "pxor %%xmm1, %%xmm0 \n" + EncryptAES256 + "movups %%xmm0, (%[out]) \n" + "movups %%xmm0, (%[iv]) \n" + : + : [iv]"r"(&m_LastBlock), [sched]"r"(m_ECBEncryption.GetKeySchedule ()), + [in]"r"(in), [out]"r"(out) + : "%xmm0", "%xmm1", "memory" + ); +#else + Encrypt (1, (const ChipherBlock *)in, (ChipherBlock *)out); +#endif + } + void CBCDecryption::Decrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out) { #ifdef __x86_64__ @@ -245,6 +266,27 @@ namespace crypto Decrypt (d.quot, (const ChipherBlock *)in, (ChipherBlock *)out); return true; } + + void CBCDecryption::Decrypt (const uint8_t * in, uint8_t * out) + { +#ifdef __x86_64__ + __asm__ + ( + "movups (%[iv]), %%xmm1 \n" + "movups (%[in]), %%xmm0 \n" + "movups %%xmm0, (%[iv]) \n" + DecryptAES256 + "pxor %%xmm1, %%xmm0 \n" + "movups %%xmm0, (%[out]) \n" + : + : [iv]"r"(&m_IV), [sched]"r"(m_ECBDecryption.GetKeySchedule ()), + [in]"r"(in), [out]"r"(out) + : "%xmm0", "%xmm1", "memory" + ); +#else + Decrypt (1, (const ChipherBlock *)in, (ChipherBlock *)out); +#endif + } } } diff --git a/aes.h b/aes.h index 5e3fcf4b..3cd905b6 100644 --- a/aes.h +++ b/aes.h @@ -111,6 +111,7 @@ namespace crypto void Encrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out); bool Encrypt (const uint8_t * in, std::size_t len, uint8_t * out); + void Encrypt (const uint8_t * in, uint8_t * out); // one block private: @@ -130,6 +131,7 @@ namespace crypto void Decrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out); bool Decrypt (const uint8_t * in, std::size_t len, uint8_t * out); + void Decrypt (const uint8_t * in, uint8_t * out); // one block private: From d3812786fa9a035380ecec14c4ae5c23f62dbcec Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 14 May 2014 22:49:22 -0400 Subject: [PATCH 32/60] session key decryption --- SSU.cpp | 41 ++++++++++++++++++++++++++++++----------- SSU.h | 11 +++++++---- 2 files changed, 37 insertions(+), 15 deletions(-) diff --git a/SSU.cpp b/SSU.cpp index 9711ecef..c6fc81d3 100644 --- a/SSU.cpp +++ b/SSU.cpp @@ -29,7 +29,7 @@ namespace ssu delete m_DHKeysPair; } - void SSUSession::CreateAESandMacKey (const uint8_t * pubKey, uint8_t * aesKey, uint8_t * macKey) + void SSUSession::CreateAESandMacKey (const uint8_t * pubKey) { CryptoPP::DH dh (i2p::crypto::elgp, i2p::crypto::elgg); uint8_t sharedKey[256]; @@ -41,14 +41,14 @@ namespace ssu if (sharedKey[0] & 0x80) { - aesKey[0] = 0; - memcpy (aesKey + 1, sharedKey, 31); - memcpy (macKey, sharedKey + 31, 32); + m_SessionKey[0] = 0; + memcpy (m_SessionKey + 1, sharedKey, 31); + memcpy (m_MacKey, sharedKey + 31, 32); } else if (sharedKey[0]) { - memcpy (aesKey, sharedKey, 32); - memcpy (macKey, sharedKey + 32, 32); + memcpy (m_SessionKey, sharedKey, 32); + memcpy (m_MacKey, sharedKey + 32, 32); } else { @@ -64,10 +64,11 @@ namespace ssu } } - memcpy (aesKey, nonZero, 32); - CryptoPP::SHA256().CalculateDigest(macKey, nonZero, 64 - (nonZero - sharedKey)); + memcpy (m_SessionKey, nonZero, 32); + CryptoPP::SHA256().CalculateDigest(m_MacKey, nonZero, 64 - (nonZero - sharedKey)); } m_IsSessionKey = true; + m_SessionKeyDecryption.SetKey (m_SessionKey); } void SSUSession::ProcessNextMessage (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& senderEndpoint) @@ -83,7 +84,7 @@ namespace ssu { ScheduleTermination (); if (m_IsSessionKey && Validate (buf, len, m_MacKey)) // try session key first - Decrypt (buf, len, m_SessionKey); + DecryptSessionKey (buf, len); else { // try intro key depending on side @@ -164,7 +165,7 @@ namespace ssu m_State = eSessionStateRequestReceived; LogPrint ("Session request received"); m_RemoteEndpoint = senderEndpoint; - CreateAESandMacKey (buf + sizeof (SSUHeader), m_SessionKey, m_MacKey); + CreateAESandMacKey (buf + sizeof (SSUHeader)); SendSessionCreated (buf + sizeof (SSUHeader)); } @@ -182,7 +183,7 @@ namespace ssu uint8_t signedData[532]; // x,y, our IP, our port, remote IP, remote port, relayTag, signed on time uint8_t * payload = buf + sizeof (SSUHeader); uint8_t * y = payload; - CreateAESandMacKey (y, m_SessionKey, m_MacKey); + CreateAESandMacKey (y); memcpy (signedData, m_DHKeysPair->publicKey, 256); // x memcpy (signedData + 256, y, 256); // y payload += 256; @@ -523,6 +524,24 @@ namespace ssu m_Decryption.ProcessData (encrypted, encrypted, encryptedLen); } + void SSUSession::DecryptSessionKey (uint8_t * buf, size_t len) + { + if (len < sizeof (SSUHeader)) + { + LogPrint ("Unexpected SSU packet length ", len); + return; + } + SSUHeader * header = (SSUHeader *)buf; + uint8_t * encrypted = &header->flag; + uint16_t encryptedLen = len - (encrypted - buf); + encryptedLen = (encryptedLen>>4)<<4; // make sure 16 bytes boundary + if (encryptedLen > 0) + { + m_SessionKeyDecryption.SetIV (header->iv); + m_SessionKeyDecryption.Decrypt (encrypted, encryptedLen, encrypted); + } + } + bool SSUSession::Validate (uint8_t * buf, size_t len, const uint8_t * macKey) { if (len < sizeof (SSUHeader)) diff --git a/SSU.h b/SSU.h index 16236a38..d44e23f6 100644 --- a/SSU.h +++ b/SSU.h @@ -9,6 +9,7 @@ #include #include #include +#include "aes.h" #include "I2PEndian.h" #include "Identity.h" #include "RouterInfo.h" @@ -85,7 +86,7 @@ namespace ssu private: - void CreateAESandMacKey (const uint8_t * pubKey, uint8_t * aesKey, uint8_t * macKey); + void CreateAESandMacKey (const uint8_t * pubKey); void ProcessMessage (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& senderEndpoint); // call for established session void ProcessSessionRequest (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& senderEndpoint); @@ -112,7 +113,8 @@ namespace ssu void Send (uint8_t type, const uint8_t * payload, size_t len); // with session key void FillHeaderAndEncrypt (uint8_t payloadType, uint8_t * buf, size_t len, const uint8_t * aesKey, const uint8_t * iv, const uint8_t * macKey); - void Decrypt (uint8_t * buf, size_t len, const uint8_t * aesKey); + void Decrypt (uint8_t * buf, size_t len, const uint8_t * aesKey); + void DecryptSessionKey (uint8_t * buf, size_t len); bool Validate (uint8_t * buf, size_t len, const uint8_t * macKey); const uint8_t * GetIntroKey () const; @@ -132,8 +134,9 @@ namespace ssu bool m_IsSessionKey; uint32_t m_RelayTag; std::set m_PeerTestNonces; - CryptoPP::CBC_Mode::Encryption m_Encryption; - CryptoPP::CBC_Mode::Decryption m_Decryption; + CryptoPP::CBC_Mode::Encryption m_Encryption; // TODO: remove + CryptoPP::CBC_Mode::Decryption m_Decryption; // TODO: remove + i2p::crypto::CBCDecryption m_SessionKeyDecryption; uint8_t m_SessionKey[32], m_MacKey[32]; std::list m_DelayedMessages; SSUData m_Data; From 6557ebb51bfa14548ba236f82ee68239df982cb2 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 15 May 2014 11:00:35 -0400 Subject: [PATCH 33/60] pass key schedule as parameter --- aes.cpp | 76 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/aes.cpp b/aes.cpp index d1d45462..4952c930 100644 --- a/aes.cpp +++ b/aes.cpp @@ -77,57 +77,57 @@ namespace crypto ); } - #define EncryptAES256 \ - "pxor (%[sched]), %%xmm0 \n" \ - "aesenc 16(%[sched]), %%xmm0 \n" \ - "aesenc 32(%[sched]), %%xmm0 \n" \ - "aesenc 48(%[sched]), %%xmm0 \n" \ - "aesenc 64(%[sched]), %%xmm0 \n" \ - "aesenc 80(%[sched]), %%xmm0 \n" \ - "aesenc 96(%[sched]), %%xmm0 \n" \ - "aesenc 112(%[sched]), %%xmm0 \n" \ - "aesenc 128(%[sched]), %%xmm0 \n" \ - "aesenc 144(%[sched]), %%xmm0 \n" \ - "aesenc 160(%[sched]), %%xmm0 \n" \ - "aesenc 176(%[sched]), %%xmm0 \n" \ - "aesenc 192(%[sched]), %%xmm0 \n" \ - "aesenc 208(%[sched]), %%xmm0 \n" \ - "aesenclast 224(%[sched]), %%xmm0 \n" + #define EncryptAES256(sched) \ + "pxor (%["#sched"]), %%xmm0 \n" \ + "aesenc 16(%["#sched"]), %%xmm0 \n" \ + "aesenc 32(%["#sched"]), %%xmm0 \n" \ + "aesenc 48(%["#sched"]), %%xmm0 \n" \ + "aesenc 64(%["#sched"]), %%xmm0 \n" \ + "aesenc 80(%["#sched"]), %%xmm0 \n" \ + "aesenc 96(%["#sched"]), %%xmm0 \n" \ + "aesenc 112(%["#sched"]), %%xmm0 \n" \ + "aesenc 128(%["#sched"]), %%xmm0 \n" \ + "aesenc 144(%["#sched"]), %%xmm0 \n" \ + "aesenc 160(%["#sched"]), %%xmm0 \n" \ + "aesenc 176(%["#sched"]), %%xmm0 \n" \ + "aesenc 192(%["#sched"]), %%xmm0 \n" \ + "aesenc 208(%["#sched"]), %%xmm0 \n" \ + "aesenclast 224(%["#sched"]), %%xmm0 \n" void ECBEncryptionAESNI::Encrypt (const ChipherBlock * in, ChipherBlock * out) { __asm__ ( "movups (%[in]), %%xmm0 \n" - EncryptAES256 + EncryptAES256(sched) "movups %%xmm0, (%[out]) \n" : : [sched]"r"(m_KeySchedule), [in]"r"(in), [out]"r"(out) : "%xmm0" ); } - #define DecryptAES256 \ - "pxor 224(%[sched]), %%xmm0 \n" \ - "aesdec 208(%[sched]), %%xmm0 \n" \ - "aesdec 192(%[sched]), %%xmm0 \n" \ - "aesdec 176(%[sched]), %%xmm0 \n" \ - "aesdec 160(%[sched]), %%xmm0 \n" \ - "aesdec 144(%[sched]), %%xmm0 \n" \ - "aesdec 128(%[sched]), %%xmm0 \n" \ - "aesdec 112(%[sched]), %%xmm0 \n" \ - "aesdec 96(%[sched]), %%xmm0 \n" \ - "aesdec 80(%[sched]), %%xmm0 \n" \ - "aesdec 64(%[sched]), %%xmm0 \n" \ - "aesdec 48(%[sched]), %%xmm0 \n" \ - "aesdec 32(%[sched]), %%xmm0 \n" \ - "aesdec 16(%[sched]), %%xmm0 \n" \ - "aesdeclast (%[sched]), %%xmm0 \n" + #define DecryptAES256(sched) \ + "pxor 224(%["#sched"]), %%xmm0 \n" \ + "aesdec 208(%["#sched"]), %%xmm0 \n" \ + "aesdec 192(%["#sched"]), %%xmm0 \n" \ + "aesdec 176(%["#sched"]), %%xmm0 \n" \ + "aesdec 160(%["#sched"]), %%xmm0 \n" \ + "aesdec 144(%["#sched"]), %%xmm0 \n" \ + "aesdec 128(%["#sched"]), %%xmm0 \n" \ + "aesdec 112(%["#sched"]), %%xmm0 \n" \ + "aesdec 96(%["#sched"]), %%xmm0 \n" \ + "aesdec 80(%["#sched"]), %%xmm0 \n" \ + "aesdec 64(%["#sched"]), %%xmm0 \n" \ + "aesdec 48(%["#sched"]), %%xmm0 \n" \ + "aesdec 32(%["#sched"]), %%xmm0 \n" \ + "aesdec 16(%["#sched"]), %%xmm0 \n" \ + "aesdeclast (%["#sched"]), %%xmm0 \n" void ECBDecryptionAESNI::Decrypt (const ChipherBlock * in, ChipherBlock * out) { __asm__ ( "movups (%[in]), %%xmm0 \n" - DecryptAES256 + DecryptAES256(sched) "movups %%xmm0, (%[out]) \n" : : [sched]"r"(m_KeySchedule), [in]"r"(in), [out]"r"(out) : "%xmm0" ); @@ -173,7 +173,7 @@ namespace crypto "block_e: \n" "movups (%[in]), %%xmm0 \n" "pxor %%xmm1, %%xmm0 \n" - EncryptAES256 + EncryptAES256(sched) "movaps %%xmm0, %%xmm1 \n" "movups %%xmm0, (%[out]) \n" "add $16, %[in] \n" @@ -212,7 +212,7 @@ namespace crypto "movups (%[iv]), %%xmm1 \n" "movups (%[in]), %%xmm0 \n" "pxor %%xmm1, %%xmm0 \n" - EncryptAES256 + EncryptAES256(sched) "movups %%xmm0, (%[out]) \n" "movups %%xmm0, (%[iv]) \n" : @@ -234,7 +234,7 @@ namespace crypto "block_d: \n" "movups (%[in]), %%xmm0 \n" "movaps %%xmm0, %%xmm2 \n" - DecryptAES256 + DecryptAES256(sched) "pxor %%xmm1, %%xmm0 \n" "movups %%xmm0, (%[out]) \n" "movaps %%xmm2, %%xmm1 \n" @@ -275,7 +275,7 @@ namespace crypto "movups (%[iv]), %%xmm1 \n" "movups (%[in]), %%xmm0 \n" "movups %%xmm0, (%[iv]) \n" - DecryptAES256 + DecryptAES256(sched) "pxor %%xmm1, %%xmm0 \n" "movups %%xmm0, (%[out]) \n" : From 6d1d8161539fd62e814304d60a284933c17dd378 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 15 May 2014 11:21:41 -0400 Subject: [PATCH 34/60] tunnel encryption/decryption --- aes.cpp | 15 +++++++++++++++ aes.h | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/aes.cpp b/aes.cpp index 4952c930..8554f490 100644 --- a/aes.cpp +++ b/aes.cpp @@ -1,4 +1,5 @@ #include +#include "TunnelBase.h" #include "aes.h" namespace i2p @@ -287,6 +288,20 @@ namespace crypto Decrypt (1, (const ChipherBlock *)in, (ChipherBlock *)out); #endif } + + void TunnelEncryption::Encrypt (uint8_t * payload) + { + m_IVEncryption.Encrypt ((ChipherBlock *)payload, (ChipherBlock *)payload); // iv + m_LayerEncryption.Encrypt (payload + 16, i2p::tunnel::TUNNEL_DATA_ENCRYPTED_SIZE, payload + 16); // data + m_IVEncryption.Encrypt ((ChipherBlock *)payload, (ChipherBlock *)payload); // double iv + } + + void TunnelDecryption::Decrypt (uint8_t * payload) + { + m_IVDecryption.Decrypt ((ChipherBlock *)payload, (ChipherBlock *)payload); // iv + m_LayerDecryption.Decrypt (payload + 16, i2p::tunnel::TUNNEL_DATA_ENCRYPTED_SIZE, payload + 16); // data + m_IVDecryption.Decrypt ((ChipherBlock *)payload, (ChipherBlock *)payload); // double iv + } } } diff --git a/aes.h b/aes.h index 3cd905b6..967aab92 100644 --- a/aes.h +++ b/aes.h @@ -138,6 +138,42 @@ namespace crypto ChipherBlock m_IV; ECBDecryption m_ECBDecryption; }; + + class TunnelEncryption // with double IV encryption + { + public: + + void SetKeys (uint8_t * layerKey, uint8_t * ivKey) + { + m_LayerEncryption.SetKey (layerKey); + m_IVEncryption.SetKey (ivKey); + } + + void Encrypt (uint8_t * payload); // 1024 bytes (16 IV + 1008 data) + + private: + + ECBEncryption m_IVEncryption; + CBCEncryption m_LayerEncryption; + }; + + class TunnelDecryption // with double IV encryption + { + public: + + void SetKeys (uint8_t * layerKey, uint8_t * ivKey) + { + m_LayerDecryption.SetKey (layerKey); + m_IVDecryption.SetKey (ivKey); + } + + void Decrypt (uint8_t * payload); // 1024 bytes (16 IV + 1008 data) + + private: + + ECBDecryption m_IVDecryption; + CBCDecryption m_LayerDecryption; + }; } } From b4b3ba16cca9981dda3879ed8cca84d801071cbc Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 15 May 2014 12:59:07 -0400 Subject: [PATCH 35/60] tunnel encryption using AES-NI --- aes.cpp | 27 +++++++++++++++++++++++++++ aes.h | 4 ++++ 2 files changed, 31 insertions(+) diff --git a/aes.cpp b/aes.cpp index 8554f490..526ddc76 100644 --- a/aes.cpp +++ b/aes.cpp @@ -291,9 +291,36 @@ namespace crypto void TunnelEncryption::Encrypt (uint8_t * payload) { +#ifdef __x86_64__ + __asm__ + ( + // encrypt IV + "movups (%[payload]), %%xmm0 \n" + EncryptAES256(sched_iv) + "movaps %%xmm0, %%xmm1 \n" + // double IV encryption + EncryptAES256(sched_iv) + "movups %%xmm0, (%[payload]) \n" + // encrypt data, IV is xmm1 + "block_et: \n" + "add $16, %[payload] \n" + "movups (%[payload]), %%xmm0 \n" + "pxor %%xmm1, %%xmm0 \n" + EncryptAES256(sched_l) + "movaps %%xmm0, %%xmm1 \n" + "movups %%xmm0, (%[payload]) \n" + "dec %[num] \n" + "jnz block_et; \n" + : + : [sched_iv]"r"(m_IVEncryption.GetKeySchedule ()), [sched_l]"r"(m_LayerEncryption.GetKeySchedule ()), + [payload]"r"(payload), [num]"r"(63) // 63 blocks = 1008 bytes + : "%xmm0", "%xmm1", "cc", "memory" + ); +#else m_IVEncryption.Encrypt ((ChipherBlock *)payload, (ChipherBlock *)payload); // iv m_LayerEncryption.Encrypt (payload + 16, i2p::tunnel::TUNNEL_DATA_ENCRYPTED_SIZE, payload + 16); // data m_IVEncryption.Encrypt ((ChipherBlock *)payload, (ChipherBlock *)payload); // double iv +#endif } void TunnelDecryption::Decrypt (uint8_t * payload) diff --git a/aes.h b/aes.h index 967aab92..10189f33 100644 --- a/aes.h +++ b/aes.h @@ -154,7 +154,11 @@ namespace crypto private: ECBEncryption m_IVEncryption; +#ifdef __x86_64__ + ECBEncryption m_LayerEncryption; +#else CBCEncryption m_LayerEncryption; +#endif }; class TunnelDecryption // with double IV encryption From 11ac6712e73d5764e9c7a5e7e556c6ae39dcfa1a Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 15 May 2014 13:10:07 -0400 Subject: [PATCH 36/60] tunnel decryption using AES-NI --- aes.cpp | 28 ++++++++++++++++++++++++++++ aes.h | 4 ++++ 2 files changed, 32 insertions(+) diff --git a/aes.cpp b/aes.cpp index 526ddc76..c4b1df17 100644 --- a/aes.cpp +++ b/aes.cpp @@ -325,9 +325,37 @@ namespace crypto void TunnelDecryption::Decrypt (uint8_t * payload) { +#ifdef __x86_64__ + __asm__ + ( + // decrypt IV + "movups (%[payload]), %%xmm0 \n" + DecryptAES256(sched_iv) + "movaps %%xmm0, %%xmm1 \n" + // double IV encryption + DecryptAES256(sched_iv) + "movups %%xmm0, (%[payload]) \n" + // decrypt data, IV is xmm1 + "block_dt: \n" + "add $16, %[payload] \n" + "movups (%[payload]), %%xmm0 \n" + "movaps %%xmm0, %%xmm2 \n" + DecryptAES256(sched_l) + "pxor %%xmm1, %%xmm0 \n" + "movups %%xmm0, (%[payload]) \n" + "movaps %%xmm2, %%xmm1 \n" + "dec %[num] \n" + "jnz block_dt; \n" + : + : [sched_iv]"r"(m_IVDecryption.GetKeySchedule ()), [sched_l]"r"(m_LayerDecryption.GetKeySchedule ()), + [payload]"r"(payload), [num]"r"(63) // 63 blocks = 1008 bytes + : "%xmm0", "%xmm1", "%xmm2", "cc", "memory" + ); +#else m_IVDecryption.Decrypt ((ChipherBlock *)payload, (ChipherBlock *)payload); // iv m_LayerDecryption.Decrypt (payload + 16, i2p::tunnel::TUNNEL_DATA_ENCRYPTED_SIZE, payload + 16); // data m_IVDecryption.Decrypt ((ChipherBlock *)payload, (ChipherBlock *)payload); // double iv +#endif } } } diff --git a/aes.h b/aes.h index 10189f33..541baf4e 100644 --- a/aes.h +++ b/aes.h @@ -176,7 +176,11 @@ namespace crypto private: ECBDecryption m_IVDecryption; +#ifdef __x86_64__ + ECBDecryption m_LayerDecryption; +#else CBCDecryption m_LayerDecryption; +#endif }; } } From 7754968e7abb46d9ae6e51d7542b0d88ab5575ef Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 15 May 2014 17:55:09 -0400 Subject: [PATCH 37/60] TunnelDecryption for transit tunnel --- TransitTunnel.cpp | 14 +++----------- TransitTunnel.h | 3 +-- aes.h | 4 ++-- 3 files changed, 6 insertions(+), 15 deletions(-) diff --git a/TransitTunnel.cpp b/TransitTunnel.cpp index 146b6572..65b0be4f 100644 --- a/TransitTunnel.cpp +++ b/TransitTunnel.cpp @@ -17,20 +17,12 @@ namespace tunnel m_TunnelID (receiveTunnelID), m_NextTunnelID (nextTunnelID), m_NextIdent (nextIdent), m_NumTransmittedBytes (0) { - m_ECBEncryption.SetKey (ivKey); - m_CBCEncryption.SetKey (layerKey); + m_Encryption.SetKeys (layerKey, ivKey); } void TransitTunnel::EncryptTunnelMsg (I2NPMessage * tunnelMsg) - { - uint8_t * payload = tunnelMsg->GetPayload () + 4; - - m_ECBEncryption.Encrypt ((i2p::crypto::ChipherBlock *)payload, (i2p::crypto::ChipherBlock *)payload); // iv - - m_CBCEncryption.SetIV (payload); - m_CBCEncryption.Encrypt (payload + 16, TUNNEL_DATA_ENCRYPTED_SIZE, payload + 16); // payload - - m_ECBEncryption.Encrypt((i2p::crypto::ChipherBlock *)payload, (i2p::crypto::ChipherBlock *)payload); // double iv encryption + { + m_Encryption.Encrypt (tunnelMsg->GetPayload () + 4); } void TransitTunnel::HandleTunnelDataMsg (i2p::I2NPMessage * tunnelMsg) diff --git a/TransitTunnel.h b/TransitTunnel.h index a85c2f2c..ebd7ffd5 100644 --- a/TransitTunnel.h +++ b/TransitTunnel.h @@ -37,8 +37,7 @@ namespace tunnel i2p::data::IdentHash m_NextIdent; size_t m_NumTransmittedBytes; - i2p::crypto::ECBEncryption m_ECBEncryption; - i2p::crypto::CBCEncryption m_CBCEncryption; + i2p::crypto::TunnelEncryption m_Encryption; }; class TransitTunnelGateway: public TransitTunnel diff --git a/aes.h b/aes.h index 541baf4e..46500d7f 100644 --- a/aes.h +++ b/aes.h @@ -143,7 +143,7 @@ namespace crypto { public: - void SetKeys (uint8_t * layerKey, uint8_t * ivKey) + void SetKeys (const uint8_t * layerKey, const uint8_t * ivKey) { m_LayerEncryption.SetKey (layerKey); m_IVEncryption.SetKey (ivKey); @@ -165,7 +165,7 @@ namespace crypto { public: - void SetKeys (uint8_t * layerKey, uint8_t * ivKey) + void SetKeys (const uint8_t * layerKey, const uint8_t * ivKey) { m_LayerDecryption.SetKey (layerKey); m_IVDecryption.SetKey (ivKey); From 0d51f240d0e41bfda33afb968ce5641ce03c1266 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 15 May 2014 18:58:26 -0400 Subject: [PATCH 38/60] TunnelDecryption for tunnels --- I2NPProtocol.cpp | 9 ++++----- Tunnel.cpp | 28 +++++++++++++--------------- TunnelConfig.h | 5 +---- 3 files changed, 18 insertions(+), 24 deletions(-) diff --git a/I2NPProtocol.cpp b/I2NPProtocol.cpp index 76f6e7d4..778d9197 100644 --- a/I2NPProtocol.cpp +++ b/I2NPProtocol.cpp @@ -1,8 +1,6 @@ #include #include "I2PEndian.h" #include -#include -#include #include #include "ElGamal.h" #include "Timestamp.h" @@ -259,11 +257,12 @@ namespace i2p //TODO: fill filler CryptoPP::SHA256().CalculateDigest(reply->hash, reply->padding, sizeof (reply->padding) + 1); // + 1 byte of ret // encrypt reply - CryptoPP::CBC_Mode::Encryption encryption; + i2p::crypto::CBCEncryption encryption; for (int j = 0; j < num; j++) { - encryption.SetKeyWithIV (clearText.replyKey, 32, clearText.replyIV); - encryption.ProcessData((uint8_t *)(records + j), (uint8_t *)(records + j), sizeof (records[j])); + encryption.SetKey (clearText.replyKey); + encryption.SetIV (clearText.replyIV); + encryption.Encrypt((uint8_t *)(records + j), sizeof (records[j]), (uint8_t *)(records + j)); } return true; } diff --git a/Tunnel.cpp b/Tunnel.cpp index 8529df4b..30bbee80 100644 --- a/Tunnel.cpp +++ b/Tunnel.cpp @@ -51,14 +51,17 @@ namespace tunnel i++; hop = hop->next; } - + + i2p::crypto::CBCDecryption decryption; hop = m_Config->GetLastHop ()->prev; size_t ind = numRecords - 1; while (hop) { - for (size_t i = ind; i < numRecords; i++) - hop->decryption.Decrypt((uint8_t *)&records[i], - sizeof (I2NPBuildRequestRecordElGamalEncrypted), (uint8_t *)&records[i]); + decryption.SetKey (hop->replyKey); + decryption.SetIV (hop->replyIV); + for (size_t i = ind; i < numRecords; i++) + decryption.Decrypt((uint8_t *)&records[i], + sizeof (I2NPBuildRequestRecordElGamalEncrypted), (uint8_t *)&records[i]); hop = hop->prev; ind--; } @@ -74,14 +77,17 @@ namespace tunnel { LogPrint ("TunnelBuildResponse ", (int)msg[0], " records."); + i2p::crypto::CBCDecryption decryption; TunnelHopConfig * hop = m_Config->GetLastHop (); int num = msg[0]; while (hop) { + decryption.SetKey (hop->replyKey); + decryption.SetIV (hop->replyIV); for (int i = 0; i < num; i++) { uint8_t * record = msg + 1 + i*sizeof (I2NPBuildResponseRecord); - hop->decryption.Decrypt(record, sizeof (I2NPBuildResponseRecord), record); + decryption.Decrypt(record, sizeof (I2NPBuildResponseRecord), record); } hop = hop->prev; num--; @@ -102,8 +108,7 @@ namespace tunnel TunnelHopConfig * hop = m_Config->GetFirstHop (); while (hop) { - hop->decryption.SetKey (hop->layerKey); - hop->ivDecryption.SetKey (hop->ivKey); + hop->decryption.SetKeys (hop->layerKey, hop->ivKey); hop = hop->next; } } @@ -116,14 +121,7 @@ namespace tunnel TunnelHopConfig * hop = m_Config->GetLastHop (); while (hop) { - // iv - hop->ivDecryption.Decrypt ((i2p::crypto::ChipherBlock *)payload, (i2p::crypto::ChipherBlock *)payload); - // data - hop->decryption.SetIV (payload); - hop->decryption.Decrypt (payload + 16, TUNNEL_DATA_ENCRYPTED_SIZE, payload+16); - // double iv ecncryption - hop->ivDecryption.Decrypt ((i2p::crypto::ChipherBlock *)payload, (i2p::crypto::ChipherBlock *)payload); - + hop->decryption.Decrypt (payload); hop = hop->prev; } } diff --git a/TunnelConfig.h b/TunnelConfig.h index 3db6c30e..5008d4ea 100644 --- a/TunnelConfig.h +++ b/TunnelConfig.h @@ -23,8 +23,7 @@ namespace tunnel bool isGateway, isEndpoint; TunnelHopConfig * next, * prev; - i2p::crypto::CBCDecryption decryption; - i2p::crypto::ECBDecryption ivDecryption; + i2p::crypto::TunnelDecryption decryption; TunnelHopConfig (const i2p::data::RouterInfo * r) { @@ -41,8 +40,6 @@ namespace tunnel next = 0; prev = 0; - decryption.SetKey (replyKey); - decryption.SetIV (replyIV); } void SetNextRouter (const i2p::data::RouterInfo * r) From 6518727270ed410437986b2557c6f872433fb834 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 1 Jun 2014 19:51:27 -0400 Subject: [PATCH 39/60] use CBCEncryption for session key encryption --- SSU.cpp | 49 ++++++++++++++++++++++++++++++------------------- SSU.h | 2 ++ 2 files changed, 32 insertions(+), 19 deletions(-) diff --git a/SSU.cpp b/SSU.cpp index c6fc81d3..2b9b888e 100644 --- a/SSU.cpp +++ b/SSU.cpp @@ -68,6 +68,7 @@ namespace ssu CryptoPP::SHA256().CalculateDigest(m_MacKey, nonZero, 64 - (nonZero - sharedKey)); } m_IsSessionKey = true; + m_SessionKeyEncryption.SetKey (m_SessionKey); m_SessionKeyDecryption.SetKey (m_SessionKey); } @@ -509,6 +510,28 @@ namespace ssu i2p::crypto::HMACMD5Digest (encrypted, encryptedLen + 18, macKey, header->mac); } + void SSUSession::FillHeaderAndEncrypt (uint8_t payloadType, uint8_t * buf, size_t len) + { + if (len < sizeof (SSUHeader)) + { + LogPrint ("Unexpected SSU packet length ", len); + return; + } + SSUHeader * header = (SSUHeader *)buf; + i2p::context.GetRandomNumberGenerator ().GenerateBlock (header->iv, 16); // random iv + m_SessionKeyEncryption.SetIV (header->iv); + header->flag = payloadType << 4; // MSB is 0 + header->time = htobe32 (i2p::util::GetSecondsSinceEpoch ()); + uint8_t * encrypted = &header->flag; + uint16_t encryptedLen = len - (encrypted - buf); + encryptedLen = (encryptedLen>>4)<<4; // make sure 16 bytes boundary, TODO: do we really need it? + m_SessionKeyEncryption.Encrypt (encrypted, encryptedLen, encrypted); + // assume actual buffer size is 18 (16 + 2) bytes more + memcpy (buf + len, header->iv, 16); + *(uint16_t *)(buf + len + 16) = htobe16 (encryptedLen); + i2p::crypto::HMACMD5Digest (encrypted, encryptedLen + 18, m_MacKey, header->mac); + } + void SSUSession::Decrypt (uint8_t * buf, size_t len, const uint8_t * aesKey) { if (len < sizeof (SSUHeader)) @@ -790,17 +813,14 @@ namespace ssu memset (payload, 0, 6); // address and port always zero for Alice payload += 6; // address and port memcpy (payload, introKey, 32); // intro key - uint8_t iv[16]; - rnd.GenerateBlock (iv, 16); // random iv // encrypt message with session key - FillHeaderAndEncrypt (PAYLOAD_TYPE_PEER_TEST, buf, 80, m_SessionKey, iv, m_MacKey); + FillHeaderAndEncrypt (PAYLOAD_TYPE_PEER_TEST, buf, 80); m_Server.Send (buf, 80, m_RemoteEndpoint); } void SSUSession::SendMsgAck (uint32_t msgID) { uint8_t buf[48 + 18]; // actual length is 44 = 37 + 7 but pad it to multiple of 16 - uint8_t iv[16]; uint8_t * payload = buf + sizeof (SSUHeader); *payload = DATA_FLAG_EXPLICIT_ACKS_INCLUDED; // flag payload++; @@ -810,10 +830,8 @@ namespace ssu payload += 4; *payload = 0; // number of fragments - CryptoPP::RandomNumberGenerator& rnd = i2p::context.GetRandomNumberGenerator (); - rnd.GenerateBlock (iv, 16); // random iv // encrypt message with session key - FillHeaderAndEncrypt (PAYLOAD_TYPE_DATA, buf, 48, m_SessionKey, iv, m_MacKey); + FillHeaderAndEncrypt (PAYLOAD_TYPE_DATA, buf, 48); m_Server.Send (buf, 48, m_RemoteEndpoint); } @@ -821,11 +839,9 @@ namespace ssu { if (m_IsSessionKey) { - uint8_t buf[48 + 18], iv[16]; - CryptoPP::RandomNumberGenerator& rnd = i2p::context.GetRandomNumberGenerator (); - rnd.GenerateBlock (iv, 16); // random iv + uint8_t buf[48 + 18]; // encrypt message with session key - FillHeaderAndEncrypt (PAYLOAD_TYPE_SESSION_DESTROYED, buf, 48, m_SessionKey, iv, m_MacKey); + FillHeaderAndEncrypt (PAYLOAD_TYPE_SESSION_DESTROYED, buf, 48); m_Server.Send (buf, 48, m_RemoteEndpoint); } } @@ -840,7 +856,7 @@ namespace ssu uint32_t fragmentNum = 0; while (len > 0) { - uint8_t buf[SSU_MTU + 18], iv[16], * payload = buf + sizeof (SSUHeader); + uint8_t buf[SSU_MTU + 18], * payload = buf + sizeof (SSUHeader); *payload = DATA_FLAG_WANT_REPLY; // for compatibility payload++; *payload = 1; // always 1 message fragment per message @@ -863,10 +879,8 @@ namespace ssu if (size & 0x0F) // make sure 16 bytes boundary size = ((size >> 4) + 1) << 4; // (/16 + 1)*16 - CryptoPP::RandomNumberGenerator& rnd = i2p::context.GetRandomNumberGenerator (); - rnd.GenerateBlock (iv, 16); // random iv // encrypt message with session key - FillHeaderAndEncrypt (PAYLOAD_TYPE_DATA, buf, size, m_SessionKey, iv, m_MacKey); + FillHeaderAndEncrypt (PAYLOAD_TYPE_DATA, buf, size); m_Server.Send (buf, size, m_RemoteEndpoint); if (!isLast) @@ -884,7 +898,6 @@ namespace ssu void SSUSession::Send (uint8_t type, const uint8_t * payload, size_t len) { uint8_t buf[SSU_MTU + 18]; - uint8_t iv[16]; size_t msgSize = len + sizeof (SSUHeader); if (msgSize > SSU_MTU) { @@ -892,10 +905,8 @@ namespace ssu return; } memcpy (buf + sizeof (SSUHeader), payload, len); - CryptoPP::RandomNumberGenerator& rnd = i2p::context.GetRandomNumberGenerator (); - rnd.GenerateBlock (iv, 16); // random iv // encrypt message with session key - FillHeaderAndEncrypt (type, buf, msgSize, m_SessionKey, iv, m_MacKey); + FillHeaderAndEncrypt (type, buf, msgSize); m_Server.Send (buf, msgSize, m_RemoteEndpoint); } diff --git a/SSU.h b/SSU.h index d44e23f6..59cf29c5 100644 --- a/SSU.h +++ b/SSU.h @@ -113,6 +113,7 @@ namespace ssu void Send (uint8_t type, const uint8_t * payload, size_t len); // with session key void FillHeaderAndEncrypt (uint8_t payloadType, uint8_t * buf, size_t len, const uint8_t * aesKey, const uint8_t * iv, const uint8_t * macKey); + void FillHeaderAndEncrypt (uint8_t payloadType, uint8_t * buf, size_t len); // with session key void Decrypt (uint8_t * buf, size_t len, const uint8_t * aesKey); void DecryptSessionKey (uint8_t * buf, size_t len); bool Validate (uint8_t * buf, size_t len, const uint8_t * macKey); @@ -136,6 +137,7 @@ namespace ssu std::set m_PeerTestNonces; CryptoPP::CBC_Mode::Encryption m_Encryption; // TODO: remove CryptoPP::CBC_Mode::Decryption m_Decryption; // TODO: remove + i2p::crypto::CBCEncryption m_SessionKeyEncryption; i2p::crypto::CBCDecryption m_SessionKeyDecryption; uint8_t m_SessionKey[32], m_MacKey[32]; std::list m_DelayedMessages; From a728d9db5bcb7482a04fa1d3935324418cc0a1c8 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 2 Jun 2014 10:05:04 -0400 Subject: [PATCH 40/60] explicit AESNI flag --- Makefile | 7 ++++++- aes.cpp | 14 +++++++------- aes.h | 7 +++---- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/Makefile b/Makefile index a30b268c..149ade28 100644 --- a/Makefile +++ b/Makefile @@ -11,6 +11,11 @@ INCFLAGS = LDFLAGS = -Wl,-rpath,/usr/local/lib -lcryptopp -lboost_system -lboost_filesystem -lboost_regex -lboost_program_options -lpthread LIBS = +#check if AES-NI is supported by CPU +ifneq ($(shell grep -c aes /proc/cpuinfo),0) + CPU_FLAGS = -DAESNI +endif + all: obj i2p i2p: $(OBJECTS:obj/%=obj/%) @@ -20,7 +25,7 @@ i2p: $(OBJECTS:obj/%=obj/%) .SUFFIXES: .c .cc .C .cpp .o obj/%.o : %.cpp - $(CC) -o $@ $< -c $(CFLAGS) $(INCFLAGS) + $(CC) -o $@ $< -c $(CFLAGS) $(INCFLAGS) $(CPU_FLAGS) obj: mkdir -p obj diff --git a/aes.cpp b/aes.cpp index c4b1df17..a2114846 100644 --- a/aes.cpp +++ b/aes.cpp @@ -7,7 +7,7 @@ namespace i2p namespace crypto { -#ifdef __x86_64__ +#ifdef AESNI ECBCryptoAESNI::ECBCryptoAESNI () { @@ -167,7 +167,7 @@ namespace crypto void CBCEncryption::Encrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out) { -#ifdef __x86_64__ +#ifdef AESNI __asm__ ( "movups (%[iv]), %%xmm1 \n" @@ -207,7 +207,7 @@ namespace crypto void CBCEncryption::Encrypt (const uint8_t * in, uint8_t * out) { -#ifdef __x86_64__ +#ifdef AESNI __asm__ ( "movups (%[iv]), %%xmm1 \n" @@ -228,7 +228,7 @@ namespace crypto void CBCDecryption::Decrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out) { -#ifdef __x86_64__ +#ifdef AESNI __asm__ ( "movups (%[iv]), %%xmm1 \n" @@ -270,7 +270,7 @@ namespace crypto void CBCDecryption::Decrypt (const uint8_t * in, uint8_t * out) { -#ifdef __x86_64__ +#ifdef AESNI __asm__ ( "movups (%[iv]), %%xmm1 \n" @@ -291,7 +291,7 @@ namespace crypto void TunnelEncryption::Encrypt (uint8_t * payload) { -#ifdef __x86_64__ +#ifdef AESNI __asm__ ( // encrypt IV @@ -325,7 +325,7 @@ namespace crypto void TunnelDecryption::Decrypt (uint8_t * payload) { -#ifdef __x86_64__ +#ifdef AESNI __asm__ ( // decrypt IV diff --git a/aes.h b/aes.h index 46500d7f..c69764b4 100644 --- a/aes.h +++ b/aes.h @@ -21,8 +21,7 @@ namespace crypto } }; -#ifdef __x86_64__ - // AES-NI assumed +#ifdef AESNI class ECBCryptoAESNI { public: @@ -154,7 +153,7 @@ namespace crypto private: ECBEncryption m_IVEncryption; -#ifdef __x86_64__ +#ifdef AESNI ECBEncryption m_LayerEncryption; #else CBCEncryption m_LayerEncryption; @@ -176,7 +175,7 @@ namespace crypto private: ECBDecryption m_IVDecryption; -#ifdef __x86_64__ +#ifdef AESNI ECBDecryption m_LayerDecryption; #else CBCDecryption m_LayerDecryption; From eb44fdf7a8372003527a1b5e15290a780d76f6df Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 3 Jun 2014 19:57:42 -0400 Subject: [PATCH 41/60] 64-bits alignment for RoutingKey --- Identity.cpp | 9 ++++----- Identity.h | 11 ++++++++--- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/Identity.cpp b/Identity.cpp index c4782e05..756eaec3 100644 --- a/Identity.cpp +++ b/Identity.cpp @@ -98,12 +98,11 @@ namespace data XORMetric operator^(const RoutingKey& key1, const RoutingKey& key2) { - // TODO: implementation depends on CPU XORMetric m; - ((uint64_t *)m.metric)[0] = ((uint64_t *)key1.hash)[0] ^ ((uint64_t *)key2.hash)[0]; - ((uint64_t *)m.metric)[1] = ((uint64_t *)key1.hash)[1] ^ ((uint64_t *)key2.hash)[1]; - ((uint64_t *)m.metric)[2] = ((uint64_t *)key1.hash)[2] ^ ((uint64_t *)key2.hash)[2]; - ((uint64_t *)m.metric)[3] = ((uint64_t *)key1.hash)[3] ^ ((uint64_t *)key2.hash)[3]; + m.metric_ll[0] = key1.hash_ll[0] ^ key2.hash_ll[0]; + m.metric_ll[1] = key1.hash_ll[1] ^ key2.hash_ll[1]; + m.metric_ll[2] = key1.hash_ll[2] ^ key2.hash_ll[2]; + m.metric_ll[3] = key1.hash_ll[3] ^ key2.hash_ll[3]; return m; } } diff --git a/Identity.h b/Identity.h index b2d593b0..9c91e9e6 100644 --- a/Identity.h +++ b/Identity.h @@ -78,7 +78,7 @@ namespace data bool operator== (const IdentHash& other) const { return !memcmp (m_Hash, other.m_Hash, 32); }; bool operator< (const IdentHash& other) const { return memcmp (m_Hash, other.m_Hash, 32) < 0; }; - bool FromBase32(const std::string&); + bool FromBase32(const std::string&); private: @@ -89,14 +89,19 @@ namespace data void CreateRandomDHKeysPair (DHKeysPair * keys); // for transport sessions // kademlia - struct RoutingKey + union RoutingKey { uint8_t hash[32]; + uint64_t hash_ll[4]; }; struct XORMetric { - uint8_t metric[32]; + union + { + uint8_t metric[32]; + uint64_t metric_ll[4]; + }; void SetMin () { memset (metric, 0, 32); }; void SetMax () { memset (metric, 0xFF, 32); }; From a6cc2e647b2c36487b1f076f990eeac311e04600 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 8 Jun 2014 07:56:04 -0400 Subject: [PATCH 42/60] eliminated multiple of 16 check for AES --- SSU.cpp | 2 -- aes.cpp | 15 +++++---------- aes.h | 4 ++-- 3 files changed, 7 insertions(+), 14 deletions(-) diff --git a/SSU.cpp b/SSU.cpp index 2b9b888e..cce2ac3b 100644 --- a/SSU.cpp +++ b/SSU.cpp @@ -524,7 +524,6 @@ namespace ssu header->time = htobe32 (i2p::util::GetSecondsSinceEpoch ()); uint8_t * encrypted = &header->flag; uint16_t encryptedLen = len - (encrypted - buf); - encryptedLen = (encryptedLen>>4)<<4; // make sure 16 bytes boundary, TODO: do we really need it? m_SessionKeyEncryption.Encrypt (encrypted, encryptedLen, encrypted); // assume actual buffer size is 18 (16 + 2) bytes more memcpy (buf + len, header->iv, 16); @@ -557,7 +556,6 @@ namespace ssu SSUHeader * header = (SSUHeader *)buf; uint8_t * encrypted = &header->flag; uint16_t encryptedLen = len - (encrypted - buf); - encryptedLen = (encryptedLen>>4)<<4; // make sure 16 bytes boundary if (encryptedLen > 0) { m_SessionKeyDecryption.SetIV (header->iv); diff --git a/aes.cpp b/aes.cpp index a2114846..518d5c58 100644 --- a/aes.cpp +++ b/aes.cpp @@ -197,12 +197,10 @@ namespace crypto #endif } - bool CBCEncryption::Encrypt (const uint8_t * in, std::size_t len, uint8_t * out) + void CBCEncryption::Encrypt (const uint8_t * in, std::size_t len, uint8_t * out) { - div_t d = div (len, 16); - if (d.rem) return false; // len is not multipple of 16 - Encrypt (d.quot, (const ChipherBlock *)in, (ChipherBlock *)out); - return true; + // len/16 + Encrypt (len >> 4, (const ChipherBlock *)in, (ChipherBlock *)out); } void CBCEncryption::Encrypt (const uint8_t * in, uint8_t * out) @@ -260,12 +258,9 @@ namespace crypto #endif } - bool CBCDecryption::Decrypt (const uint8_t * in, std::size_t len, uint8_t * out) + void CBCDecryption::Decrypt (const uint8_t * in, std::size_t len, uint8_t * out) { - div_t d = div (len, 16); - if (d.rem) return false; // len is not multiple of 16 - Decrypt (d.quot, (const ChipherBlock *)in, (ChipherBlock *)out); - return true; + Decrypt (len >> 4, (const ChipherBlock *)in, (ChipherBlock *)out); } void CBCDecryption::Decrypt (const uint8_t * in, uint8_t * out) diff --git a/aes.h b/aes.h index c69764b4..d1f3c254 100644 --- a/aes.h +++ b/aes.h @@ -109,7 +109,7 @@ namespace crypto void SetIV (const uint8_t * iv) { memcpy (m_LastBlock.buf, iv, 16); }; // 16 bytes void Encrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out); - bool Encrypt (const uint8_t * in, std::size_t len, uint8_t * out); + void Encrypt (const uint8_t * in, std::size_t len, uint8_t * out); void Encrypt (const uint8_t * in, uint8_t * out); // one block private: @@ -129,7 +129,7 @@ namespace crypto void SetIV (const uint8_t * iv) { memcpy (m_IV.buf, iv, 16); }; // 16 bytes void Decrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out); - bool Decrypt (const uint8_t * in, std::size_t len, uint8_t * out); + void Decrypt (const uint8_t * in, std::size_t len, uint8_t * out); void Decrypt (const uint8_t * in, uint8_t * out); // one block private: From f9cd2f6808996fb48df6ff1edd8c4303adce36b0 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 8 Jun 2014 14:43:18 -0400 Subject: [PATCH 43/60] don't use crypto++ AES directly --- SSU.cpp | 22 ++++++++++++---------- SSU.h | 4 ---- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/SSU.cpp b/SSU.cpp index cce2ac3b..e855dd47 100644 --- a/SSU.cpp +++ b/SSU.cpp @@ -204,8 +204,8 @@ namespace ssu payload += 4; // relayTag payload += 4; // signed on time // decrypt DSA signature - m_Decryption.SetKeyWithIV (m_SessionKey, 32, ((SSUHeader *)buf)->iv); - m_Decryption.ProcessData (payload, payload, 48); + m_SessionKeyDecryption.SetIV (((SSUHeader *)buf)->iv); + m_SessionKeyDecryption.Decrypt (payload, 48, payload); // verify CryptoPP::DSA::PublicKey pubKey; pubKey.Initialize (i2p::crypto::dsap, i2p::crypto::dsaq, i2p::crypto::dsag, CryptoPP::Integer (m_RemoteRouter->GetRouterIdentity ().signingKey, 128)); @@ -329,8 +329,8 @@ namespace ssu uint8_t iv[16]; rnd.GenerateBlock (iv, 16); // random iv // encrypt signature and 8 bytes padding with newly created session key - m_Encryption.SetKeyWithIV (m_SessionKey, 32, iv); - m_Encryption.ProcessData (payload, payload, 48); + m_SessionKeyEncryption.SetIV (iv); + m_SessionKeyEncryption.Encrypt (payload, 48, payload); // encrypt message with intro key FillHeaderAndEncrypt (PAYLOAD_TYPE_SESSION_CREATED, buf, 368, introKey, iv, introKey); @@ -501,9 +501,10 @@ namespace ssu header->time = htobe32 (i2p::util::GetSecondsSinceEpoch ()); uint8_t * encrypted = &header->flag; uint16_t encryptedLen = len - (encrypted - buf); - m_Encryption.SetKeyWithIV (aesKey, 32, iv); - encryptedLen = (encryptedLen>>4)<<4; // make sure 16 bytes boundary - m_Encryption.ProcessData (encrypted, encrypted, encryptedLen); + i2p::crypto::CBCEncryption encryption; + encryption.SetKey (aesKey); + encryption.SetIV (iv); + encryption.Encrypt (encrypted, encryptedLen, encrypted); // assume actual buffer size is 18 (16 + 2) bytes more memcpy (buf + len, iv, 16); *(uint16_t *)(buf + len + 16) = htobe16 (encryptedLen); @@ -541,9 +542,10 @@ namespace ssu SSUHeader * header = (SSUHeader *)buf; uint8_t * encrypted = &header->flag; uint16_t encryptedLen = len - (encrypted - buf); - m_Decryption.SetKeyWithIV (aesKey, 32, header->iv); - encryptedLen = (encryptedLen>>4)<<4; // make sure 16 bytes boundary - m_Decryption.ProcessData (encrypted, encrypted, encryptedLen); + i2p::crypto::CBCDecryption decryption; + decryption.SetKey (aesKey); + decryption.SetIV (header->iv); + decryption.Decrypt (encrypted, encryptedLen, encrypted); } void SSUSession::DecryptSessionKey (uint8_t * buf, size_t len) diff --git a/SSU.h b/SSU.h index 59cf29c5..c3563722 100644 --- a/SSU.h +++ b/SSU.h @@ -7,8 +7,6 @@ #include #include #include -#include -#include #include "aes.h" #include "I2PEndian.h" #include "Identity.h" @@ -135,8 +133,6 @@ namespace ssu bool m_IsSessionKey; uint32_t m_RelayTag; std::set m_PeerTestNonces; - CryptoPP::CBC_Mode::Encryption m_Encryption; // TODO: remove - CryptoPP::CBC_Mode::Decryption m_Decryption; // TODO: remove i2p::crypto::CBCEncryption m_SessionKeyEncryption; i2p::crypto::CBCDecryption m_SessionKeyDecryption; uint8_t m_SessionKey[32], m_MacKey[32]; From c9ace095f4ddde8def637e6a20bae592a611c33b Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 9 Jun 2014 22:56:16 -0400 Subject: [PATCH 44/60] removed unused SSU states --- SSU.cpp | 15 ++------------- SSU.h | 10 +--------- 2 files changed, 3 insertions(+), 22 deletions(-) diff --git a/SSU.cpp b/SSU.cpp index e855dd47..a137f1a8 100644 --- a/SSU.cpp +++ b/SSU.cpp @@ -163,7 +163,6 @@ namespace ssu void SSUSession::ProcessSessionRequest (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& senderEndpoint) { - m_State = eSessionStateRequestReceived; LogPrint ("Session request received"); m_RemoteEndpoint = senderEndpoint; CreateAESandMacKey (buf + sizeof (SSUHeader)); @@ -178,7 +177,6 @@ namespace ssu return; } - m_State = eSessionStateCreatedReceived; LogPrint ("Session created received"); m_Timer.cancel (); // connect timer uint8_t signedData[532]; // x,y, our IP, our port, remote IP, remote port, relayTag, signed on time @@ -218,9 +216,7 @@ namespace ssu void SSUSession::ProcessSessionConfirmed (uint8_t * buf, size_t len) { - m_State = eSessionStateConfirmedReceived; LogPrint ("Session confirmed received"); - m_State = eSessionStateEstablished; SendI2NPMessage (CreateDeliveryStatusMsg (0)); Established (); } @@ -244,8 +240,6 @@ namespace ssu CryptoPP::RandomNumberGenerator& rnd = i2p::context.GetRandomNumberGenerator (); rnd.GenerateBlock (iv, 16); // random iv FillHeaderAndEncrypt (PAYLOAD_TYPE_SESSION_REQUEST, buf, 304, introKey, iv, introKey); - - m_State = eSessionStateRequestSent; m_Server.Send (buf, 304, m_RemoteEndpoint); } @@ -278,10 +272,7 @@ namespace ssu if (m_State == eSessionStateEstablished) FillHeaderAndEncrypt (PAYLOAD_TYPE_RELAY_REQUEST, buf, 96, m_SessionKey, iv, m_MacKey); else - { - FillHeaderAndEncrypt (PAYLOAD_TYPE_RELAY_REQUEST, buf, 96, iKey, iv, iKey); - m_State = eSessionStateRelayRequestSent; - } + FillHeaderAndEncrypt (PAYLOAD_TYPE_RELAY_REQUEST, buf, 96, iKey, iv, iKey); m_Server.Send (buf, 96, m_RemoteEndpoint); } @@ -333,8 +324,7 @@ namespace ssu m_SessionKeyEncryption.Encrypt (payload, 48, payload); // encrypt message with intro key - FillHeaderAndEncrypt (PAYLOAD_TYPE_SESSION_CREATED, buf, 368, introKey, iv, introKey); - m_State = eSessionStateCreatedSent; + FillHeaderAndEncrypt (PAYLOAD_TYPE_SESSION_CREATED, buf, 368, introKey, iv, introKey); m_Server.Send (buf, 368, m_RemoteEndpoint); } @@ -373,7 +363,6 @@ namespace ssu rnd.GenerateBlock (iv, 16); // random iv // encrypt message with session key FillHeaderAndEncrypt (PAYLOAD_TYPE_SESSION_CONFIRMED, buf, 480, m_SessionKey, iv, m_MacKey); - m_State = eSessionStateConfirmedSent; m_Server.Send (buf, 480, m_RemoteEndpoint); } diff --git a/SSU.h b/SSU.h index c3563722..9a29a3e1 100644 --- a/SSU.h +++ b/SSU.h @@ -47,15 +47,7 @@ namespace ssu enum SessionState { - eSessionStateUnknown, - eSessionStateRequestSent, - eSessionStateRequestReceived, - eSessionStateCreatedSent, - eSessionStateCreatedReceived, - eSessionStateConfirmedSent, - eSessionStateConfirmedReceived, - eSessionStateRelayRequestSent, - eSessionStateRelayRequestReceived, + eSessionStateUnknown, eSessionStateIntroduced, eSessionStateEstablished, eSessionStateFailed From 7bb50546442dd5a5fdb9be6d75846d5d4090dac1 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 10 Jun 2014 10:39:29 -0400 Subject: [PATCH 45/60] moved sending I2NP messages to SSUData --- SSU.cpp | 72 +++++++++++------------------------------------------ SSU.h | 4 +-- SSUData.cpp | 48 +++++++++++++++++++++++++++++++++++ SSUData.h | 1 + 4 files changed, 65 insertions(+), 60 deletions(-) diff --git a/SSU.cpp b/SSU.cpp index a137f1a8..7a58692f 100644 --- a/SSU.cpp +++ b/SSU.cpp @@ -325,7 +325,7 @@ namespace ssu // encrypt message with intro key FillHeaderAndEncrypt (PAYLOAD_TYPE_SESSION_CREATED, buf, 368, introKey, iv, introKey); - m_Server.Send (buf, 368, m_RemoteEndpoint); + Send (buf, 368); } void SSUSession::SendSessionConfirmed (const uint8_t * y, const uint8_t * ourAddress) @@ -363,7 +363,7 @@ namespace ssu rnd.GenerateBlock (iv, 16); // random iv // encrypt message with session key FillHeaderAndEncrypt (PAYLOAD_TYPE_SESSION_CONFIRMED, buf, 480, m_SessionKey, iv, m_MacKey); - m_Server.Send (buf, 480, m_RemoteEndpoint); + Send (buf, 480); } void SSUSession::ProcessRelayRequest (uint8_t * buf, size_t len) @@ -633,7 +633,7 @@ namespace ssu if (!m_DelayedMessages.empty ()) { for (auto it :m_DelayedMessages) - Send (it); + m_Data.Send (it); m_DelayedMessages.clear (); } if (m_PeerTest && (m_RemoteRouter && m_RemoteRouter->IsPeerTesting ())) @@ -689,7 +689,7 @@ namespace ssu if (msg) { if (m_State == eSessionStateEstablished) - Send (msg); + m_Data.Send (msg); else m_DelayedMessages.push_back (msg); } @@ -804,7 +804,7 @@ namespace ssu memcpy (payload, introKey, 32); // intro key // encrypt message with session key FillHeaderAndEncrypt (PAYLOAD_TYPE_PEER_TEST, buf, 80); - m_Server.Send (buf, 80, m_RemoteEndpoint); + Send (buf, 80); } void SSUSession::SendMsgAck (uint32_t msgID) @@ -821,7 +821,7 @@ namespace ssu // encrypt message with session key FillHeaderAndEncrypt (PAYLOAD_TYPE_DATA, buf, 48); - m_Server.Send (buf, 48, m_RemoteEndpoint); + Send (buf, 48); } void SSUSession::SendSesionDestroyed () @@ -831,59 +831,10 @@ namespace ssu uint8_t buf[48 + 18]; // encrypt message with session key FillHeaderAndEncrypt (PAYLOAD_TYPE_SESSION_DESTROYED, buf, 48); - m_Server.Send (buf, 48, m_RemoteEndpoint); + Send (buf, 48); } } - void SSUSession::Send (i2p::I2NPMessage * msg) - { - uint32_t msgID = htobe32 (msg->ToSSU ()); - size_t payloadSize = SSU_MTU - sizeof (SSUHeader) - 9; // 9 = flag + #frg(1) + messageID(4) + frag info (3) - size_t len = msg->GetLength (); - uint8_t * msgBuf = msg->GetSSUHeader (); - - uint32_t fragmentNum = 0; - while (len > 0) - { - uint8_t buf[SSU_MTU + 18], * payload = buf + sizeof (SSUHeader); - *payload = DATA_FLAG_WANT_REPLY; // for compatibility - payload++; - *payload = 1; // always 1 message fragment per message - payload++; - *(uint32_t *)payload = msgID; - payload += 4; - bool isLast = (len <= payloadSize); - size_t size = isLast ? len : payloadSize; - uint32_t fragmentInfo = (fragmentNum << 17); - if (isLast) - fragmentInfo |= 0x010000; - - fragmentInfo |= size; - fragmentInfo = htobe32 (fragmentInfo); - memcpy (payload, (uint8_t *)(&fragmentInfo) + 1, 3); - payload += 3; - memcpy (payload, msgBuf, size); - - size += payload - buf; - if (size & 0x0F) // make sure 16 bytes boundary - size = ((size >> 4) + 1) << 4; // (/16 + 1)*16 - - // encrypt message with session key - FillHeaderAndEncrypt (PAYLOAD_TYPE_DATA, buf, size); - m_Server.Send (buf, size, m_RemoteEndpoint); - - if (!isLast) - { - len -= payloadSize; - msgBuf += payloadSize; - } - else - len = 0; - fragmentNum++; - } - DeleteI2NPMessage (msg); - } - void SSUSession::Send (uint8_t type, const uint8_t * payload, size_t len) { uint8_t buf[SSU_MTU + 18]; @@ -896,9 +847,14 @@ namespace ssu memcpy (buf + sizeof (SSUHeader), payload, len); // encrypt message with session key FillHeaderAndEncrypt (type, buf, msgSize); - m_Server.Send (buf, msgSize, m_RemoteEndpoint); + Send (buf, msgSize); } + void SSUSession::Send (const uint8_t * buf, size_t size) + { + m_Server.Send (buf, size, m_RemoteEndpoint); + } + SSUServer::SSUServer (int port): m_Thread (nullptr), m_Work (m_Service), m_Endpoint (boost::asio::ip::udp::v4 (), port), m_Socket (m_Service, m_Endpoint) { @@ -961,7 +917,7 @@ namespace ssu return nullptr; } - void SSUServer::Send (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& to) + void SSUServer::Send (const uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& to) { m_Socket.send_to (boost::asio::buffer (buf, len), to); LogPrint ("SSU sent ", len, " bytes"); diff --git a/SSU.h b/SSU.h index 9a29a3e1..80260d99 100644 --- a/SSU.h +++ b/SSU.h @@ -99,8 +99,8 @@ namespace ssu void ProcessData (uint8_t * buf, size_t len); void SendMsgAck (uint32_t msgID); void SendSesionDestroyed (); - void Send (i2p::I2NPMessage * msg); void Send (uint8_t type, const uint8_t * payload, size_t len); // with session key + void Send (const uint8_t * buf, size_t size); void FillHeaderAndEncrypt (uint8_t payloadType, uint8_t * buf, size_t len, const uint8_t * aesKey, const uint8_t * iv, const uint8_t * macKey); void FillHeaderAndEncrypt (uint8_t payloadType, uint8_t * buf, size_t len); // with session key @@ -148,7 +148,7 @@ namespace ssu boost::asio::io_service& GetService () { return m_Socket.get_io_service(); }; const boost::asio::ip::udp::endpoint& GetEndpoint () const { return m_Endpoint; }; - void Send (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& to); + void Send (const uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& to); void AddRelay (uint32_t tag, const boost::asio::ip::udp::endpoint& relay); SSUSession * FindRelaySession (uint32_t tag); diff --git a/SSUData.cpp b/SSUData.cpp index 6a7f4dc3..2683fb79 100644 --- a/SSUData.cpp +++ b/SSUData.cpp @@ -135,6 +135,54 @@ namespace ssu } } + void SSUData::Send (i2p::I2NPMessage * msg) + { + uint32_t msgID = htobe32 (msg->ToSSU ()); + size_t payloadSize = SSU_MTU - sizeof (SSUHeader) - 9; // 9 = flag + #frg(1) + messageID(4) + frag info (3) + size_t len = msg->GetLength (); + uint8_t * msgBuf = msg->GetSSUHeader (); + + uint32_t fragmentNum = 0; + while (len > 0) + { + uint8_t buf[SSU_MTU + 18], * payload = buf + sizeof (SSUHeader); + *payload = DATA_FLAG_WANT_REPLY; // for compatibility + payload++; + *payload = 1; // always 1 message fragment per message + payload++; + *(uint32_t *)payload = msgID; + payload += 4; + bool isLast = (len <= payloadSize); + size_t size = isLast ? len : payloadSize; + uint32_t fragmentInfo = (fragmentNum << 17); + if (isLast) + fragmentInfo |= 0x010000; + + fragmentInfo |= size; + fragmentInfo = htobe32 (fragmentInfo); + memcpy (payload, (uint8_t *)(&fragmentInfo) + 1, 3); + payload += 3; + memcpy (payload, msgBuf, size); + + size += payload - buf; + if (size & 0x0F) // make sure 16 bytes boundary + size = ((size >> 4) + 1) << 4; // (/16 + 1)*16 + + // encrypt message with session key + m_Session.FillHeaderAndEncrypt (PAYLOAD_TYPE_DATA, buf, size); + m_Session.Send (buf, size); + + if (!isLast) + { + len -= payloadSize; + msgBuf += payloadSize; + } + else + len = 0; + fragmentNum++; + } + DeleteI2NPMessage (msg); + } } } diff --git a/SSUData.h b/SSUData.h index 6f6c398d..188ff07b 100644 --- a/SSUData.h +++ b/SSUData.h @@ -27,6 +27,7 @@ namespace ssu ~SSUData (); void ProcessMessage (uint8_t * buf, size_t len); + void Send (i2p::I2NPMessage * msg); private: From 165a079928fbaaf8f252ac1c471c9872fd14a067 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 10 Jun 2014 11:19:31 -0400 Subject: [PATCH 46/60] moved sending acks to SSUData --- SSU.cpp | 16 ---------------- SSU.h | 1 - SSUData.cpp | 19 ++++++++++++++++++- SSUData.h | 4 ++++ 4 files changed, 22 insertions(+), 18 deletions(-) diff --git a/SSU.cpp b/SSU.cpp index 7a58692f..cc125ae0 100644 --- a/SSU.cpp +++ b/SSU.cpp @@ -807,22 +807,6 @@ namespace ssu Send (buf, 80); } - void SSUSession::SendMsgAck (uint32_t msgID) - { - uint8_t buf[48 + 18]; // actual length is 44 = 37 + 7 but pad it to multiple of 16 - uint8_t * payload = buf + sizeof (SSUHeader); - *payload = DATA_FLAG_EXPLICIT_ACKS_INCLUDED; // flag - payload++; - *payload = 1; // number of ACKs - payload++; - *(uint32_t *)(payload) = htobe32 (msgID); // msgID - payload += 4; - *payload = 0; // number of fragments - - // encrypt message with session key - FillHeaderAndEncrypt (PAYLOAD_TYPE_DATA, buf, 48); - Send (buf, 48); - } void SSUSession::SendSesionDestroyed () { diff --git a/SSU.h b/SSU.h index 80260d99..e39a4e2e 100644 --- a/SSU.h +++ b/SSU.h @@ -97,7 +97,6 @@ namespace ssu void ProcessPeerTest (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& senderEndpoint); void SendPeerTest (uint32_t nonce, uint32_t address, uint16_t port, uint8_t * introKey); // Charlie to Alice void ProcessData (uint8_t * buf, size_t len); - void SendMsgAck (uint32_t msgID); void SendSesionDestroyed (); void Send (uint8_t type, const uint8_t * payload, size_t len); // with session key void Send (const uint8_t * buf, size_t size); diff --git a/SSUData.cpp b/SSUData.cpp index 2683fb79..a1b8163b 100644 --- a/SSUData.cpp +++ b/SSUData.cpp @@ -113,7 +113,7 @@ namespace ssu m_IncomleteMessages[msgID] = new IncompleteMessage (msg); if (isLast) { - m_Session.SendMsgAck (msgID); + SendMsgAck (msgID); msg->FromSSU (msgID); if (m_Session.GetState () == eSessionStateEstablished) i2p::HandleI2NPMessage (msg); @@ -183,6 +183,23 @@ namespace ssu } DeleteI2NPMessage (msg); } + + void SSUData::SendMsgAck (uint32_t msgID) + { + uint8_t buf[48 + 18]; // actual length is 44 = 37 + 7 but pad it to multiple of 16 + uint8_t * payload = buf + sizeof (SSUHeader); + *payload = DATA_FLAG_EXPLICIT_ACKS_INCLUDED; // flag + payload++; + *payload = 1; // number of ACKs + payload++; + *(uint32_t *)(payload) = htobe32 (msgID); // msgID + payload += 4; + *payload = 0; // number of fragments + + // encrypt message with session key + m_Session.FillHeaderAndEncrypt (PAYLOAD_TYPE_DATA, buf, 48); + m_Session.Send (buf, 48); + } } } diff --git a/SSUData.h b/SSUData.h index 188ff07b..71273dc2 100644 --- a/SSUData.h +++ b/SSUData.h @@ -29,6 +29,10 @@ namespace ssu void ProcessMessage (uint8_t * buf, size_t len); void Send (i2p::I2NPMessage * msg); + private: + + void SendMsgAck (uint32_t msgID); + private: struct IncompleteMessage From 5f2d9db1315d11408c7089c19259aa940bb7fc2a Mon Sep 17 00:00:00 2001 From: Alexander Ryzhov Date: Wed, 11 Jun 2014 12:01:13 +0400 Subject: [PATCH 47/60] i2p.cpp: fix return code declaration --- i2p.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i2p.cpp b/i2p.cpp index f441fc02..2bd2b5b8 100644 --- a/i2p.cpp +++ b/i2p.cpp @@ -1,5 +1,5 @@ #include - +#include #include "Daemon.h" int main( int argc, char* argv[] ) From 4e09b39735086b166764925b79dc478408b1133a Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 11 Jun 2014 10:56:20 -0400 Subject: [PATCH 48/60] check sequence of fragments --- TunnelEndpoint.cpp | 35 ++++++++++++++++++++++++----------- TunnelEndpoint.h | 7 ++++++- 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/TunnelEndpoint.cpp b/TunnelEndpoint.cpp index fc92ec29..cfbc39ec 100644 --- a/TunnelEndpoint.cpp +++ b/TunnelEndpoint.cpp @@ -26,7 +26,8 @@ namespace tunnel bool isFollowOnFragment = flag & 0x80, isLastFragment = true; uint32_t msgID = 0; - TunnelMessageBlock m; + int fragmentNum = 0; + TunnelMessageBlockEx m; if (!isFollowOnFragment) { // first fragment @@ -68,7 +69,7 @@ namespace tunnel // follow on msgID = be32toh (*(uint32_t *)fragment); // MessageID fragment += 4; - int fragmentNum = (flag >> 1) & 0x3F; // 6 bits + fragmentNum = (flag >> 1) & 0x3F; // 6 bits isLastFragment = flag & 0x01; LogPrint ("Follow on fragment ", fragmentNum, " of message ", msgID, isLastFragment ? " last" : " non-last"); } @@ -101,22 +102,34 @@ namespace tunnel if (msgID) // msgID is presented, assume message is fragmented { if (!isFollowOnFragment) // create new incomlete message + { + m.nextFragmentNum = 1; m_IncompleteMessages[msgID] = m; + } else { auto it = m_IncompleteMessages.find (msgID); if (it != m_IncompleteMessages.end()) { - I2NPMessage * incompleteMessage = it->second.data; - memcpy (incompleteMessage->buf + incompleteMessage->len, fragment, size); // concatenate fragment - incompleteMessage->len += size; - // TODO: check fragmentNum sequence - if (isLastFragment) + if (fragmentNum == it->second.nextFragmentNum) { - // message complete - HandleNextMessage (it->second); - m_IncompleteMessages.erase (it); - } + I2NPMessage * incompleteMessage = it->second.data; + memcpy (incompleteMessage->buf + incompleteMessage->len, fragment, size); // concatenate fragment + incompleteMessage->len += size; + if (isLastFragment) + { + // message complete + HandleNextMessage (it->second); + m_IncompleteMessages.erase (it); + } + else + it->second.nextFragmentNum++; + } + else + { + LogPrint ("Unexpected fragment ", fragmentNum, " instead ", it->second.nextFragmentNum, " of message ", msgID, ". Discarded"); + m_IncompleteMessages.erase (it); // TODO: store unexpect fragment for a while + } } else LogPrint ("First fragment of message ", msgID, " not found. Discarded"); diff --git a/TunnelEndpoint.h b/TunnelEndpoint.h index b18f204b..2323e574 100644 --- a/TunnelEndpoint.h +++ b/TunnelEndpoint.h @@ -26,7 +26,12 @@ namespace tunnel private: - std::map m_IncompleteMessages; + struct TunnelMessageBlockEx: public TunnelMessageBlock + { + uint8_t nextFragmentNum; + }; + + std::map m_IncompleteMessages; size_t m_NumReceivedBytes; }; } From d5fff57edbbd8d1c889c8a03505efc1249d625a9 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 12 Jun 2014 09:12:39 -0400 Subject: [PATCH 49/60] defualt port consistency (17007) --- Daemon.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Daemon.cpp b/Daemon.cpp index ebd9a52d..f5ee6549 100644 --- a/Daemon.cpp +++ b/Daemon.cpp @@ -53,7 +53,7 @@ namespace i2p //TODO: This is an ugly workaround. fix it. //TODO: Autodetect public IP. i2p::context.OverrideNTCPAddress(i2p::util::config::GetCharArg("-host", "127.0.0.1"), - i2p::util::config::GetArg("-port", 17070)); + i2p::util::config::GetArg("-port", 17007)); if (isLogging == 1) { From fccb13cedde9ae63101934070e8311d593243743 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 12 Jun 2014 11:14:22 -0400 Subject: [PATCH 50/60] store sent messages until ack-ed --- SSUData.cpp | 33 +++++++++++++++++++++++++++++---- SSUData.h | 3 +++ 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/SSUData.cpp b/SSUData.cpp index a1b8163b..db71edb7 100644 --- a/SSUData.cpp +++ b/SSUData.cpp @@ -19,8 +19,27 @@ namespace ssu DeleteI2NPMessage (it.second->msg); delete it.second; } + for (auto it: m_SentMessages) + { + for (auto f: it.second) + delete[] f; + } } + void SSUData::ProcessSentMessageAck (uint32_t msgID) + { + auto it = m_SentMessages.find (msgID); + if (it != m_SentMessages.end ()) + { + // delete all ack-ed message's fragments + for (auto f: it->second) + delete[] f; + m_SentMessages.erase (it); + } + else + LogPrint ("SSU ack received for unknown message ", msgID); + } + void SSUData::ProcessMessage (uint8_t * buf, size_t len) { //uint8_t * start = buf; @@ -32,7 +51,8 @@ namespace ssu // explicit ACKs uint8_t numAcks =*buf; buf++; - // TODO: process ACKs + for (int i = 0; i < numAcks; i++) + ProcessSentMessageAck (be32toh (((uint32_t *)buf)[i])); buf += numAcks*4; } if (flag & DATA_FLAG_ACK_BITFIELDS_INCLUDED) @@ -42,8 +62,9 @@ namespace ssu buf++; for (int i = 0; i < numBitfields; i++) { + ProcessSentMessageAck (be32toh (*(uint32_t *)buf)); // TODO: should be replaced to fragments buf += 4; // msgID - // TODO: process ACH bitfields + // TODO: process individual Ack bitfields while (*buf & 0x80) // not last buf++; buf++; // last byte @@ -137,7 +158,9 @@ namespace ssu void SSUData::Send (i2p::I2NPMessage * msg) { - uint32_t msgID = htobe32 (msg->ToSSU ()); + uint32_t msgID = msg->ToSSU (); + auto fragments = m_SentMessages[msgID]; + msgID = htobe32 (msgID); size_t payloadSize = SSU_MTU - sizeof (SSUHeader) - 9; // 9 = flag + #frg(1) + messageID(4) + frag info (3) size_t len = msg->GetLength (); uint8_t * msgBuf = msg->GetSSUHeader (); @@ -145,7 +168,9 @@ namespace ssu uint32_t fragmentNum = 0; while (len > 0) { - uint8_t buf[SSU_MTU + 18], * payload = buf + sizeof (SSUHeader); + uint8_t * buf = new uint8_t[SSU_MTU + 18]; + fragments.push_back (buf); + uint8_t * payload = buf + sizeof (SSUHeader); *payload = DATA_FLAG_WANT_REPLY; // for compatibility payload++; *payload = 1; // always 1 message fragment per message diff --git a/SSUData.h b/SSUData.h index 71273dc2..4829aa56 100644 --- a/SSUData.h +++ b/SSUData.h @@ -3,6 +3,7 @@ #include #include +#include #include "I2NPProtocol.h" namespace i2p @@ -32,6 +33,7 @@ namespace ssu private: void SendMsgAck (uint32_t msgID); + void ProcessSentMessageAck (uint32_t msgID); private: @@ -45,6 +47,7 @@ namespace ssu SSUSession& m_Session; std::map m_IncomleteMessages; + std::map > m_SentMessages; // msgID -> fragments }; } } From 99b818ad15fee4c03bbe1e693d53aa5e20a256ca Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 12 Jun 2014 21:01:04 -0400 Subject: [PATCH 51/60] don't print duplicate acks --- SSUData.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/SSUData.cpp b/SSUData.cpp index db71edb7..e363a2bf 100644 --- a/SSUData.cpp +++ b/SSUData.cpp @@ -36,8 +36,6 @@ namespace ssu delete[] f; m_SentMessages.erase (it); } - else - LogPrint ("SSU ack received for unknown message ", msgID); } void SSUData::ProcessMessage (uint8_t * buf, size_t len) @@ -62,7 +60,6 @@ namespace ssu buf++; for (int i = 0; i < numBitfields; i++) { - ProcessSentMessageAck (be32toh (*(uint32_t *)buf)); // TODO: should be replaced to fragments buf += 4; // msgID // TODO: process individual Ack bitfields while (*buf & 0x80) // not last From 9ecf2500f508798871ba8de92ded1e3dc3599332 Mon Sep 17 00:00:00 2001 From: Mikal Villa Date: Sun, 15 Jun 2014 13:03:29 +0200 Subject: [PATCH 52/60] Adding support for Mac OSX. Compiles fine on 10.9, $ uname -a Darwin mikalv.local 13.1.0 Darwin Kernel Version 13.1.0: Thu Jan 16 19:40:37 PST 2014; root:xnu-2422.90.20~2/RELEASE_X86_64 x86_64 --- I2PEndian.h | 25 +++++++++++++++++++++---- Makefile.osx | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 4 deletions(-) create mode 100644 Makefile.osx diff --git a/I2PEndian.h b/I2PEndian.h index 661179cb..cc97debc 100644 --- a/I2PEndian.h +++ b/I2PEndian.h @@ -5,11 +5,27 @@ #include #elif __FreeBSD__ #include -#elif __MACH__ // Mac OS X -#include +#elif defined(__APPLE__) && defined(__MACH__) + +#include + +#define htobe16(x) OSSwapHostToBigInt16(x) +#define htole16(x) OSSwapHostToLittleInt16(x) +#define be16toh(x) OSSwapBigToHostInt16(x) +#define le16toh(x) OSSwapLittleToHostInt16(x) + +#define htobe32(x) OSSwapHostToBigInt32(x) +#define htole32(x) OSSwapHostToLittleInt32(x) +#define be32toh(x) OSSwapBigToHostInt32(x) +#define le32toh(x) OSSwapLittleToHostInt32(x) + +#define htobe64(x) OSSwapHostToBigInt64(x) +#define htole64(x) OSSwapHostToLittleInt64(x) +#define be64toh(x) OSSwapBigToHostInt64(x) +#define le64toh(x) OSSwapLittleToHostInt64(x) + #else #include - uint16_t htobe16(uint16_t int16); uint32_t htobe32(uint32_t int32); uint64_t htobe64(uint64_t int64); @@ -20,4 +36,5 @@ uint64_t be64toh(uint64_t big64); #endif -#endif // I2PENDIAN_H__ \ No newline at end of file +#endif // I2PENDIAN_H__ + diff --git a/Makefile.osx b/Makefile.osx new file mode 100644 index 00000000..e294971b --- /dev/null +++ b/Makefile.osx @@ -0,0 +1,43 @@ +#CC = clang++ +CC = g++ +CFLAGS = -g -Wall -std=c++11 -lstdc++ +OBJECTS = obj/CryptoConst.o obj/base64.o obj/NTCPSession.o obj/RouterInfo.o obj/Transports.o \ + obj/RouterContext.o obj/NetDb.o obj/LeaseSet.o obj/Tunnel.o obj/TunnelEndpoint.o \ + obj/TunnelGateway.o obj/TransitTunnel.o obj/I2NPProtocol.o obj/Log.o obj/Garlic.o \ + obj/HTTPServer.o obj/Streaming.o obj/Identity.o obj/SSU.o obj/util.o obj/Reseed.o \ + obj/UPnP.o obj/TunnelPool.o obj/HTTPProxy.o obj/AddressBook.o obj/Daemon.o \ + obj/DaemonLinux.o obj/SSUData.o obj/i2p.o obj/aes.o +INCFLAGS = -DCRYPTOPP_DISABLE_ASM +LDFLAGS = -Wl,-rpath,/usr/local/lib -lcryptopp -lboost_system -lboost_filesystem -lboost_regex -lboost_program_options -lpthread +LIBS = + +#check if AES-NI is supported by CPU +ifneq ($(shell grep -c aes /proc/cpuinfo),0) + CPU_FLAGS = -DAESNI +endif + +# Apple Mac OSX +UNAME_S := $(shell uname -s) +ifeq ($(UNAME_S),Darwin) +endif + +all: obj i2p + +i2p: $(OBJECTS:obj/%=obj/%) + $(CC) -o $@ $^ $(LDFLAGS) $(LIBS) + +.SUFFIXES: +.SUFFIXES: .c .cc .C .cpp .o + +obj/%.o : %.cpp + $(CC) -o $@ $< -c $(CFLAGS) $(INCFLAGS) $(CPU_FLAGS) + +obj: + mkdir -p obj + +clean: + rm -fr obj i2p + +.PHONY: all +.PHONY: clean + From d6b97670c4eacaa285b0638bd3f7f6006de4dfdc Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 16 Jun 2014 21:23:22 -0400 Subject: [PATCH 53/60] exploratory if tunnels are not created yet --- HTTPServer.cpp | 7 +++++-- NetDb.cpp | 38 ++++++++++++++++++++++---------------- NetDb.h | 6 ++++++ 3 files changed, 33 insertions(+), 18 deletions(-) diff --git a/HTTPServer.cpp b/HTTPServer.cpp index c2a235fa..038f6321 100644 --- a/HTTPServer.cpp +++ b/HTTPServer.cpp @@ -238,7 +238,7 @@ namespace util void HTTPConnection::FillContent (std::stringstream& s) { s << "Data path: " << i2p::util::filesystem::GetDataDir().string() << "
" << "
"; - s << "Our external address:" << "
" << "
"; + s << "Our external address:" << "
"; for (auto& address : i2p::context.GetRouterInfo().GetAddresses()) { switch (address.transportStyle) @@ -254,7 +254,10 @@ namespace util } s << address.host.to_string() << ":" << address.port << "
"; } - + s << "
Routers: " << i2p::data::netdb.GetNumRouters () << " "; + s << "Floodfills: " << i2p::data::netdb.GetNumFloodfills () << " "; + s << "LeaseSets: " << i2p::data::netdb.GetNumLeaseSets () << "
"; + s << "

Tunnels

"; for (auto it: i2p::tunnel::tunnels.GetOutboundTunnels ()) { diff --git a/NetDb.cpp b/NetDb.cpp index 553ee52b..e80c5f78 100644 --- a/NetDb.cpp +++ b/NetDb.cpp @@ -533,21 +533,21 @@ namespace data } void NetDb::Explore () - { - auto exploratoryPool = i2p::tunnel::tunnels.GetExploratoryPool (); - auto outbound = exploratoryPool ? exploratoryPool->GetNextOutboundTunnel () : nullptr; - auto inbound = exploratoryPool ? exploratoryPool->GetNextInboundTunnel () : nullptr; - if (outbound && inbound) - { - CryptoPP::RandomNumberGenerator& rnd = i2p::context.GetRandomNumberGenerator (); - uint8_t randomHash[32]; - rnd.GenerateBlock (randomHash, 32); - RequestedDestination * dest = CreateRequestedDestination (IdentHash (randomHash), false, true); - dest->SetLastOutboundTunnel (outbound); - auto floodfill = GetClosestFloodfill (randomHash, dest->GetExcludedPeers ()); - if (floodfill) + { + CryptoPP::RandomNumberGenerator& rnd = i2p::context.GetRandomNumberGenerator (); + uint8_t randomHash[32]; + rnd.GenerateBlock (randomHash, 32); + RequestedDestination * dest = CreateRequestedDestination (IdentHash (randomHash), false, true); + auto floodfill = GetClosestFloodfill (randomHash, dest->GetExcludedPeers ()); + if (floodfill) + { + LogPrint ("Exploring new routers ..."); + auto exploratoryPool = i2p::tunnel::tunnels.GetExploratoryPool (); + auto outbound = exploratoryPool ? exploratoryPool->GetNextOutboundTunnel () : nullptr; + auto inbound = exploratoryPool ? exploratoryPool->GetNextInboundTunnel () : nullptr; + if (outbound && inbound) { - LogPrint ("Exploring new routers ..."); + dest->SetLastOutboundTunnel (outbound); std::vector msgs; msgs.push_back (i2p::tunnel::TunnelMessageBlock { @@ -564,8 +564,14 @@ namespace data outbound->SendTunnelDataMsg (msgs); } else - DeleteRequestedDestination (dest); - } + { + dest->SetLastOutboundTunnel (nullptr); + dest->SetLastReplyTunnel (nullptr); + i2p::transports.SendMessage (floodfill->GetIdentHash (), dest->CreateRequestMessage (floodfill->GetIdentHash ())); + } + } + else + DeleteRequestedDestination (dest); } void NetDb::Publish () diff --git a/NetDb.h b/NetDb.h index 35fbe844..632affe3 100644 --- a/NetDb.h +++ b/NetDb.h @@ -33,6 +33,7 @@ namespace data void ClearExcludedPeers (); const RouterInfo * GetLastRouter () const { return m_LastRouter; }; const i2p::tunnel::InboundTunnel * GetLastReplyTunnel () const { return m_LastReplyTunnel; }; + void SetLastReplyTunnel (i2p::tunnel::InboundTunnel * tunnel) { m_LastReplyTunnel = tunnel; }; bool IsExploratory () const { return m_IsExploratory; }; bool IsLeaseSet () const { return m_IsLeaseSet; }; bool IsExcluded (const IdentHash& ident) const { return m_ExcludedPeers.count (ident); }; @@ -78,6 +79,11 @@ namespace data const RouterInfo * GetRandomRouter (const RouterInfo * compatibleWith = nullptr, uint8_t caps = 0) const; void PostI2NPMsg (I2NPMessage * msg); + + // for web interface + int GetNumRouters () const { return m_RouterInfos.size (); }; + int GetNumFloodfills () const { return m_Floodfills.size (); }; + int GetNumLeaseSets () const { return m_LeaseSets.size (); }; private: From 566909a50c721b5c650d1a327f008db7a3022222 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 16 Jun 2014 22:30:34 -0400 Subject: [PATCH 54/60] explore 5 addresses at the time --- NetDb.cpp | 77 +++++++++++++++++++++++++++++++------------------------ NetDb.h | 2 +- 2 files changed, 45 insertions(+), 34 deletions(-) diff --git a/NetDb.cpp b/NetDb.cpp index e80c5f78..0582bf08 100644 --- a/NetDb.cpp +++ b/NetDb.cpp @@ -122,7 +122,10 @@ namespace data } } else // if no new DatabaseStore coming, explore it - Explore (); + { + auto numRouters = m_RouterInfos.size (); + Explore (numRouters < 1500 ? 5 : 1); + } uint64_t ts = i2p::util::GetSecondsSinceEpoch (); if (ts - lastSave >= 60) // save routers and validate subscriptions every minute @@ -532,46 +535,54 @@ namespace data i2p::DeleteI2NPMessage (msg); } - void NetDb::Explore () + void NetDb::Explore (int numDestinations) { + auto exploratoryPool = i2p::tunnel::tunnels.GetExploratoryPool (); + auto outbound = exploratoryPool ? exploratoryPool->GetNextOutboundTunnel () : nullptr; + auto inbound = exploratoryPool ? exploratoryPool->GetNextInboundTunnel () : nullptr; + bool throughTunnels = outbound && inbound; + CryptoPP::RandomNumberGenerator& rnd = i2p::context.GetRandomNumberGenerator (); uint8_t randomHash[32]; - rnd.GenerateBlock (randomHash, 32); - RequestedDestination * dest = CreateRequestedDestination (IdentHash (randomHash), false, true); - auto floodfill = GetClosestFloodfill (randomHash, dest->GetExcludedPeers ()); - if (floodfill) + std::vector msgs; + std::set floodfills; + LogPrint ("Exploring new ", numDestinations, " routers ..."); + for (int i = 0; i < numDestinations; i++) { - LogPrint ("Exploring new routers ..."); - auto exploratoryPool = i2p::tunnel::tunnels.GetExploratoryPool (); - auto outbound = exploratoryPool ? exploratoryPool->GetNextOutboundTunnel () : nullptr; - auto inbound = exploratoryPool ? exploratoryPool->GetNextInboundTunnel () : nullptr; - if (outbound && inbound) + rnd.GenerateBlock (randomHash, 32); + RequestedDestination * dest = CreateRequestedDestination (IdentHash (randomHash), false, true); + auto floodfill = GetClosestFloodfill (randomHash, dest->GetExcludedPeers ()); + if (floodfill && !floodfills.count (floodfill)) // request floodfill only once { - dest->SetLastOutboundTunnel (outbound); - std::vector msgs; - msgs.push_back (i2p::tunnel::TunnelMessageBlock - { - i2p::tunnel::eDeliveryTypeRouter, - floodfill->GetIdentHash (), 0, - CreateDatabaseStoreMsg () // tell floodfill about us - }); - msgs.push_back (i2p::tunnel::TunnelMessageBlock - { - i2p::tunnel::eDeliveryTypeRouter, - floodfill->GetIdentHash (), 0, - dest->CreateRequestMessage (floodfill, inbound) // explore - }); - outbound->SendTunnelDataMsg (msgs); + floodfills.insert (floodfill); + if (throughTunnels) + { + dest->SetLastOutboundTunnel (outbound); + msgs.push_back (i2p::tunnel::TunnelMessageBlock + { + i2p::tunnel::eDeliveryTypeRouter, + floodfill->GetIdentHash (), 0, + CreateDatabaseStoreMsg () // tell floodfill about us + }); + msgs.push_back (i2p::tunnel::TunnelMessageBlock + { + i2p::tunnel::eDeliveryTypeRouter, + floodfill->GetIdentHash (), 0, + dest->CreateRequestMessage (floodfill, inbound) // explore + }); + } + else + { + dest->SetLastOutboundTunnel (nullptr); + dest->SetLastReplyTunnel (nullptr); + i2p::transports.SendMessage (floodfill->GetIdentHash (), dest->CreateRequestMessage (floodfill->GetIdentHash ())); + } } else - { - dest->SetLastOutboundTunnel (nullptr); - dest->SetLastReplyTunnel (nullptr); - i2p::transports.SendMessage (floodfill->GetIdentHash (), dest->CreateRequestMessage (floodfill->GetIdentHash ())); - } + DeleteRequestedDestination (dest); } - else - DeleteRequestedDestination (dest); + if (throughTunnels && msgs.size () > 0) + outbound->SendTunnelDataMsg (msgs); } void NetDb::Publish () diff --git a/NetDb.h b/NetDb.h index 632affe3..165580bd 100644 --- a/NetDb.h +++ b/NetDb.h @@ -91,7 +91,7 @@ namespace data void Load (const char * directory); void SaveUpdated (const char * directory); void Run (); // exploratory thread - void Explore (); + void Explore (int numDestinations); void Publish (); void ValidateSubscriptions (); const RouterInfo * GetClosestFloodfill (const IdentHash& destination, const std::set& excluded) const; From ebd64c9337f9a8b1c61f65537904663ef24cb043 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 17 Jun 2014 13:15:32 -0400 Subject: [PATCH 55/60] check for duplicates --- SSU.cpp | 5 +++++ SSU.h | 18 +++++++++++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/SSU.cpp b/SSU.cpp index cc125ae0..c7b180ef 100644 --- a/SSU.cpp +++ b/SSU.cpp @@ -84,6 +84,11 @@ namespace ssu else { ScheduleTermination (); + // check for duplicate + const uint8_t * iv = ((SSUHeader *)buf)->iv; + if (m_ReceivedIVs.count (iv)) return; // duplicate detected + m_ReceivedIVs.insert (iv); + if (m_IsSessionKey && Validate (buf, len, m_MacKey)) // try session key first DecryptSessionKey (buf, len); else diff --git a/SSU.h b/SSU.h index e39a4e2e..b0930370 100644 --- a/SSU.h +++ b/SSU.h @@ -2,6 +2,7 @@ #define SSU_H__ #include +#include #include #include #include @@ -112,7 +113,21 @@ namespace ssu void HandleTerminationTimer (const boost::system::error_code& ecode); private: - + + union IV + { + uint8_t buf[16]; + uint64_t ll[2]; + + IV (const IV&) = default; + IV (const uint8_t * iv) { memcpy (buf, iv, 16); }; + bool operator< (const IV& other) const + { + if (ll[0] != other.ll[0]) return ll[0] < other.ll[0]; + return ll[1] < other.ll[1]; + }; + }; + friend class SSUData; // TODO: change in later SSUServer& m_Server; boost::asio::ip::udp::endpoint m_RemoteEndpoint; @@ -128,6 +143,7 @@ namespace ssu i2p::crypto::CBCDecryption m_SessionKeyDecryption; uint8_t m_SessionKey[32], m_MacKey[32]; std::list m_DelayedMessages; + std::set m_ReceivedIVs; SSUData m_Data; }; From b95caaf219be23335b3ece8e2db98f5eb749d0a3 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 18 Jun 2014 10:41:59 -0400 Subject: [PATCH 56/60] exclude hidden routers from tunnels --- NetDb.cpp | 7 +++---- NetDb.h | 2 +- RouterInfo.cpp | 5 ++++- RouterInfo.h | 5 ++++- 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/NetDb.cpp b/NetDb.cpp index 0582bf08..efd12c7c 100644 --- a/NetDb.cpp +++ b/NetDb.cpp @@ -633,7 +633,7 @@ namespace data } } - const RouterInfo * NetDb::GetRandomRouter (const RouterInfo * compatibleWith, uint8_t caps) const + const RouterInfo * NetDb::GetRandomRouter (const RouterInfo * compatibleWith) const { CryptoPP::RandomNumberGenerator& rnd = i2p::context.GetRandomNumberGenerator (); uint32_t ind = rnd.GenerateWord32 (0, m_RouterInfos.size () - 1); @@ -644,9 +644,8 @@ namespace data { if (i >= ind) { - if (!it.second->IsUnreachable () && - (!compatibleWith || it.second->IsCompatible (*compatibleWith)) && - (!caps || (it.second->GetCaps () & caps) == caps)) + if (!it.second->IsUnreachable () && !it.second->IsHidden () && + (!compatibleWith || it.second->IsCompatible (*compatibleWith))) return it.second; } else diff --git a/NetDb.h b/NetDb.h index 165580bd..d9451f7c 100644 --- a/NetDb.h +++ b/NetDb.h @@ -76,7 +76,7 @@ namespace data void HandleDatabaseStoreMsg (uint8_t * buf, size_t len); void HandleDatabaseSearchReplyMsg (I2NPMessage * msg); - const RouterInfo * GetRandomRouter (const RouterInfo * compatibleWith = nullptr, uint8_t caps = 0) const; + const RouterInfo * GetRandomRouter (const RouterInfo * compatibleWith = nullptr) const; void PostI2NPMsg (I2NPMessage * msg); diff --git a/RouterInfo.cpp b/RouterInfo.cpp index da829c47..9ffe7edf 100644 --- a/RouterInfo.cpp +++ b/RouterInfo.cpp @@ -214,7 +214,10 @@ namespace data break; case 'C': m_Caps |= Caps::eSSUIntroducer; - break; + break; + case 'H': + m_Caps |= Caps::eHidden; + break; default: ; } cap++; diff --git a/RouterInfo.h b/RouterInfo.h index d730c5f8..9ce9b006 100644 --- a/RouterInfo.h +++ b/RouterInfo.h @@ -31,7 +31,8 @@ namespace data eHighBandwidth = 0x02, eReachable = 0x04, eSSUTesting = 0x08, - eSSUIntroducer = 0x10 + eSSUIntroducer = 0x10, + eHidden = 0x20 }; enum TransportStyle @@ -88,6 +89,8 @@ namespace data bool UsesIntroducer () const; bool IsIntroducer () const { return m_Caps & eSSUIntroducer; }; bool IsPeerTesting () const { return m_Caps & eSSUTesting; }; + bool IsHidden () const { return m_Caps & eHidden; }; + uint8_t GetCaps () const { return m_Caps; }; void SetUnreachable (bool unreachable) { m_IsUnreachable = unreachable; }; From 59439ebf26968504d7f45a042ac381ef8a1d96d7 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 18 Jun 2014 19:38:21 -0400 Subject: [PATCH 57/60] don't rely on order in tunnel build message. assign index to hop instead --- Tunnel.cpp | 36 ++++++++++++++++++++++++------------ TunnelConfig.h | 1 + 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/Tunnel.cpp b/Tunnel.cpp index 30bbee80..3e270846 100644 --- a/Tunnel.cpp +++ b/Tunnel.cpp @@ -48,22 +48,27 @@ namespace tunnel hop->next ? rnd.GenerateWord32 () : replyMsgID, // we set replyMsgID for last hop only hop->isGateway, hop->isEndpoint), records[i]); + hop->recordIndex = i; //TODO: i++; hop = hop->next; } i2p::crypto::CBCDecryption decryption; hop = m_Config->GetLastHop ()->prev; - size_t ind = numRecords - 1; while (hop) { decryption.SetKey (hop->replyKey); decryption.SetIV (hop->replyIV); - for (size_t i = ind; i < numRecords; i++) - decryption.Decrypt((uint8_t *)&records[i], - sizeof (I2NPBuildRequestRecordElGamalEncrypted), (uint8_t *)&records[i]); + // decrypt records after current hop + TunnelHopConfig * hop1 = hop->next; + while (hop1) + { + decryption.Decrypt((uint8_t *)&records[hop1->recordIndex], + sizeof (I2NPBuildRequestRecordElGamalEncrypted), + (uint8_t *)&records[hop1->recordIndex]); + hop1 = hop1->next; + } hop = hop->prev; - ind--; } FillI2NPMessageHeader (msg, eI2NPVariableTunnelBuild); @@ -76,21 +81,28 @@ namespace tunnel bool Tunnel::HandleTunnelBuildResponse (uint8_t * msg, size_t len) { LogPrint ("TunnelBuildResponse ", (int)msg[0], " records."); - + auto numHops = m_Config->GetNumHops (); + if (msg[0] != numHops) + { + LogPrint ("Number of records in response ", (int)msg[0], " doesn't match ", numHops); + return false; + } + i2p::crypto::CBCDecryption decryption; TunnelHopConfig * hop = m_Config->GetLastHop (); - int num = msg[0]; while (hop) { decryption.SetKey (hop->replyKey); decryption.SetIV (hop->replyIV); - for (int i = 0; i < num; i++) - { - uint8_t * record = msg + 1 + i*sizeof (I2NPBuildResponseRecord); + // decrypt records before and including current hop + TunnelHopConfig * hop1 = hop; + while (hop1) + { + uint8_t * record = msg + 1 + hop1->recordIndex*sizeof (I2NPBuildResponseRecord); decryption.Decrypt(record, sizeof (I2NPBuildResponseRecord), record); - } + hop1 = hop1->prev; + } hop = hop->prev; - num--; } m_IsEstablished = true; diff --git a/TunnelConfig.h b/TunnelConfig.h index 5008d4ea..7cac47a0 100644 --- a/TunnelConfig.h +++ b/TunnelConfig.h @@ -24,6 +24,7 @@ namespace tunnel TunnelHopConfig * next, * prev; i2p::crypto::TunnelDecryption decryption; + int recordIndex; // record # in tunnel build message TunnelHopConfig (const i2p::data::RouterInfo * r) { From 53be08e2396c5607671de14aef944b3c32705126 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 18 Jun 2014 21:24:24 -0400 Subject: [PATCH 58/60] fake tunnel build ecord --- Tunnel.cpp | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/Tunnel.cpp b/Tunnel.cpp index 3e270846..3525724c 100644 --- a/Tunnel.cpp +++ b/Tunnel.cpp @@ -27,7 +27,7 @@ namespace tunnel void Tunnel::Build (uint32_t replyMsgID, OutboundTunnel * outboundTunnel) { CryptoPP::RandomNumberGenerator& rnd = i2p::context.GetRandomNumberGenerator (); - size_t numRecords = m_Config->GetNumHops (); + int numRecords = m_Config->GetNumHops () + 1; // +1 fake record. TODO: I2NPMessage * msg = NewI2NPMessage (); *msg->GetPayload () = numRecords; msg->len += numRecords*sizeof (I2NPBuildRequestRecordElGamalEncrypted) + 1; @@ -52,7 +52,13 @@ namespace tunnel i++; hop = hop->next; } - + // fill up fake records with random data + while (i < numRecords) + { + rnd.GenerateBlock ((uint8_t *)(records + i), sizeof (records[i])); + i++; + } + i2p::crypto::CBCDecryption decryption; hop = m_Config->GetLastHop ()->prev; while (hop) @@ -81,12 +87,6 @@ namespace tunnel bool Tunnel::HandleTunnelBuildResponse (uint8_t * msg, size_t len) { LogPrint ("TunnelBuildResponse ", (int)msg[0], " records."); - auto numHops = m_Config->GetNumHops (); - if (msg[0] != numHops) - { - LogPrint ("Number of records in response ", (int)msg[0], " doesn't match ", numHops); - return false; - } i2p::crypto::CBCDecryption decryption; TunnelHopConfig * hop = m_Config->GetLastHop (); @@ -98,26 +98,34 @@ namespace tunnel TunnelHopConfig * hop1 = hop; while (hop1) { - uint8_t * record = msg + 1 + hop1->recordIndex*sizeof (I2NPBuildResponseRecord); - decryption.Decrypt(record, sizeof (I2NPBuildResponseRecord), record); + auto idx = hop1->recordIndex; + if (idx >= 0 && idx < msg[0]) + { + uint8_t * record = msg + 1 + idx*sizeof (I2NPBuildResponseRecord); + decryption.Decrypt(record, sizeof (I2NPBuildResponseRecord), record); + } + else + LogPrint ("Tunnel hop index ", idx, " is out of range"); hop1 = hop1->prev; } hop = hop->prev; } m_IsEstablished = true; - for (int i = 0; i < msg[0]; i++) + hop = m_Config->GetFirstHop (); + while (hop) { - I2NPBuildResponseRecord * record = (I2NPBuildResponseRecord *)(msg + 1 + i*sizeof (I2NPBuildResponseRecord)); + I2NPBuildResponseRecord * record = (I2NPBuildResponseRecord *)(msg + 1 + hop->recordIndex*sizeof (I2NPBuildResponseRecord)); LogPrint ("Ret code=", (int)record->ret); if (record->ret) // if any of participants declined the tunnel is not established m_IsEstablished = false; + hop = hop->next; } if (m_IsEstablished) { // change reply keys to layer keys - TunnelHopConfig * hop = m_Config->GetFirstHop (); + hop = m_Config->GetFirstHop (); while (hop) { hop->decryption.SetKeys (hop->layerKey, hop->ivKey); From 92dc9b35428e56fc1228b9c3286210efa10880f3 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 24 Jun 2014 19:33:30 -0400 Subject: [PATCH 59/60] set replyIV for each hop decryption --- Tunnel.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tunnel.cpp b/Tunnel.cpp index 3525724c..4e0ec7c0 100644 --- a/Tunnel.cpp +++ b/Tunnel.cpp @@ -64,11 +64,11 @@ namespace tunnel while (hop) { decryption.SetKey (hop->replyKey); - decryption.SetIV (hop->replyIV); // decrypt records after current hop TunnelHopConfig * hop1 = hop->next; while (hop1) { + decryption.SetIV (hop->replyIV); decryption.Decrypt((uint8_t *)&records[hop1->recordIndex], sizeof (I2NPBuildRequestRecordElGamalEncrypted), (uint8_t *)&records[hop1->recordIndex]); @@ -93,7 +93,6 @@ namespace tunnel while (hop) { decryption.SetKey (hop->replyKey); - decryption.SetIV (hop->replyIV); // decrypt records before and including current hop TunnelHopConfig * hop1 = hop; while (hop1) @@ -102,6 +101,7 @@ namespace tunnel if (idx >= 0 && idx < msg[0]) { uint8_t * record = msg + 1 + idx*sizeof (I2NPBuildResponseRecord); + decryption.SetIV (hop->replyIV); decryption.Decrypt(record, sizeof (I2NPBuildResponseRecord), record); } else From ec21138bd249f43dfe2a920c6014d78f49f63eec Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 25 Jun 2014 19:28:33 -0400 Subject: [PATCH 60/60] specify number of hops for a tunnel pool --- Streaming.cpp | 4 ++-- Tunnel.cpp | 6 +++--- Tunnel.h | 2 +- TunnelConfig.h | 6 ++++-- TunnelPool.cpp | 23 +++++++++++++---------- TunnelPool.h | 4 ++-- 6 files changed, 25 insertions(+), 20 deletions(-) diff --git a/Streaming.cpp b/Streaming.cpp index 86105ca0..7b6ef7c6 100644 --- a/Streaming.cpp +++ b/Streaming.cpp @@ -340,7 +340,7 @@ namespace stream CryptoPP::Integer (m_Keys.signingPrivateKey, 20)); CryptoPP::DH dh (i2p::crypto::elgp, i2p::crypto::elgg); dh.GenerateKeyPair(i2p::context.GetRandomNumberGenerator (), m_EncryptionPrivateKey, m_EncryptionPublicKey); - m_Pool = i2p::tunnel::tunnels.CreateTunnelPool (*this); + m_Pool = i2p::tunnel::tunnels.CreateTunnelPool (*this, 3); // 3-hops tunnel } StreamingDestination::StreamingDestination (const std::string& fullPath): m_LeaseSet (nullptr) @@ -356,7 +356,7 @@ namespace stream CryptoPP::Integer (m_Keys.signingPrivateKey, 20)); CryptoPP::DH dh (i2p::crypto::elgp, i2p::crypto::elgg); dh.GenerateKeyPair(i2p::context.GetRandomNumberGenerator (), m_EncryptionPrivateKey, m_EncryptionPublicKey); - m_Pool = i2p::tunnel::tunnels.CreateTunnelPool (*this); + m_Pool = i2p::tunnel::tunnels.CreateTunnelPool (*this, 3); // 3-hops tunnel } StreamingDestination::~StreamingDestination () diff --git a/Tunnel.cpp b/Tunnel.cpp index 4e0ec7c0..0c1fe454 100644 --- a/Tunnel.cpp +++ b/Tunnel.cpp @@ -275,9 +275,9 @@ namespace tunnel return tunnel; } - TunnelPool * Tunnels::CreateTunnelPool (i2p::data::LocalDestination& localDestination) + TunnelPool * Tunnels::CreateTunnelPool (i2p::data::LocalDestination& localDestination, int numHops) { - auto pool = new TunnelPool (localDestination); + auto pool = new TunnelPool (localDestination, numHops); m_Pools[pool->GetIdentHash ()] = pool; return pool; } @@ -441,7 +441,7 @@ namespace tunnel LogPrint ("Creating zero hops inbound tunnel..."); CreateZeroHopsInboundTunnel (); if (!m_ExploratoryPool) - m_ExploratoryPool = CreateTunnelPool (i2p::context); + m_ExploratoryPool = CreateTunnelPool (i2p::context, 2); // 2-hop exploratory return; } diff --git a/Tunnel.h b/Tunnel.h index dc345875..8ae3e392 100644 --- a/Tunnel.h +++ b/Tunnel.h @@ -114,7 +114,7 @@ namespace tunnel void PostTunnelData (I2NPMessage * msg); template TTunnel * CreateTunnel (TunnelConfig * config, OutboundTunnel * outboundTunnel = 0); - TunnelPool * CreateTunnelPool (i2p::data::LocalDestination& localDestination); + TunnelPool * CreateTunnelPool (i2p::data::LocalDestination& localDestination, int numHops); void DeleteTunnelPool (TunnelPool * pool); private: diff --git a/TunnelConfig.h b/TunnelConfig.h index 7cac47a0..429fa679 100644 --- a/TunnelConfig.h +++ b/TunnelConfig.h @@ -134,9 +134,9 @@ namespace tunnel return m_LastHop; } - size_t GetNumHops () const + int GetNumHops () const { - size_t num = 0; + int num = 0; TunnelHopConfig * hop = m_FirstHop; while (hop) { @@ -183,6 +183,8 @@ namespace tunnel newConfig->m_LastHop = newHop; if (hop->isGateway) // inbound tunnel newHop->SetReplyHop (m_FirstHop); // use it as reply tunnel + else + newHop->SetNextRouter (&i2p::context.GetRouterInfo ()); } if (!hop->next) newConfig->m_FirstHop = newHop; // last hop diff --git a/TunnelPool.cpp b/TunnelPool.cpp index 875a51f6..1b6fa8cb 100644 --- a/TunnelPool.cpp +++ b/TunnelPool.cpp @@ -10,8 +10,8 @@ namespace i2p { namespace tunnel { - TunnelPool::TunnelPool (i2p::data::LocalDestination& localDestination, int numTunnels): - m_LocalDestination (localDestination), m_NumTunnels (numTunnels), m_LastOutboundTunnel (nullptr) + TunnelPool::TunnelPool (i2p::data::LocalDestination& localDestination, int numHops, int numTunnels): + m_LocalDestination (localDestination), m_NumHops (numHops), m_NumTunnels (numTunnels), m_LastOutboundTunnel (nullptr) { } @@ -189,15 +189,18 @@ namespace tunnel if (inboundTunnel) { LogPrint ("Creating destination outbound tunnel..."); - auto firstHop = i2p::data::netdb.GetRandomRouter (&i2p::context.GetRouterInfo ()); - auto secondHop = i2p::data::netdb.GetRandomRouter (firstHop); + + const i2p::data::RouterInfo * prevHop = &i2p::context.GetRouterInfo (); + std::vector hops; + for (int i = 0; i < m_NumHops; i++) + { + auto hop = i2p::data::netdb.GetRandomRouter (prevHop); + prevHop = hop; + hops.push_back (hop); + } + auto * tunnel = tunnels.CreateTunnel ( - new TunnelConfig (std::vector - { - firstHop, - secondHop - }, - inboundTunnel->GetTunnelConfig ())); + new TunnelConfig (hops, inboundTunnel->GetTunnelConfig ())); tunnel->SetTunnelPool (this); } } diff --git a/TunnelPool.h b/TunnelPool.h index 1ff66cf3..27848bfb 100644 --- a/TunnelPool.h +++ b/TunnelPool.h @@ -23,7 +23,7 @@ namespace tunnel { public: - TunnelPool (i2p::data::LocalDestination& localDestination, int numTunnels = 5); + TunnelPool (i2p::data::LocalDestination& localDestination, int numHops, int numTunnels = 5); ~TunnelPool (); const uint8_t * GetEncryptionPrivateKey () const { return m_LocalDestination.GetEncryptionPrivateKey (); }; @@ -53,7 +53,7 @@ namespace tunnel private: i2p::data::LocalDestination& m_LocalDestination; - int m_NumTunnels; + int m_NumHops, m_NumTunnels; std::set m_InboundTunnels; // recent tunnel appears first std::set m_OutboundTunnels; std::map > m_Tests;