From 3787dc80d90b94d708394a03a755a5737a308b99 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 6 Oct 2014 16:49:41 -0400 Subject: [PATCH] introuduce GarlicDestination --- Garlic.cpp | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ Garlic.h | 19 ++++++++++++++++ 2 files changed, 85 insertions(+) diff --git a/Garlic.cpp b/Garlic.cpp index e3cfa5e1..2c3e309e 100644 --- a/Garlic.cpp +++ b/Garlic.cpp @@ -14,6 +14,72 @@ namespace i2p { namespace garlic { + GarlicDestination::~GarlicDestination () + { + for (auto it: m_Tags) + if (it.second) delete[] it.second; + } + + void GarlicDestination::AddSessionKey (const uint8_t * key, const uint8_t * tag) + { + if (key) + { + uint8_t * newKey = new uint8_t[32]; + memcpy (newKey, key, 32); + m_Tags[SessionTag(tag)] = newKey; + } + } + + void GarlicDestination::HandleGarlicMessage (I2NPMessage * msg) + { + uint8_t * buf = msg->GetPayload (); + uint32_t length = be32toh (*(uint32_t *)buf); + buf += 4; // lentgh + auto it = m_Tags.find (SessionTag(buf)); + if (it != m_Tags.end ()) + { + // tag found. Use AES + uint8_t iv[32]; // IV is first 16 bytes + CryptoPP::SHA256().CalculateDigest(iv, buf, 32); + if (it->second) // separate key + { + i2p::crypto::CBCDecryption decryption; + decryption.SetKey (it->second); + decryption.SetIV (iv); + decryption.Decrypt (buf + 32, length - 32, buf + 32); + delete[] it->second; + } + else // common key + { + m_Decryption.SetIV (iv); + m_Decryption.Decrypt (buf + 32, length - 32, buf + 32); + } + m_Tags.erase (it); // tag might be used only once + } + else + { + // tag not found. Use ElGamal + if (m_LocalDestination) + { + ElGamalBlock elGamal; + if (i2p::crypto::ElGamalDecrypt (m_LocalDestination->GetEncryptionPrivateKey (), buf, (uint8_t *)&elGamal, true)) + { + m_Decryption.SetKey (elGamal.sessionKey); + uint8_t iv[32]; // IV is first 16 bytes + CryptoPP::SHA256().CalculateDigest(iv, elGamal.preIV, 32); + m_Decryption.SetIV (iv); + m_Decryption.Decrypt(buf + 514, length - 514, buf + 514); + } + else + LogPrint ("Failed to decrypt garlic"); + } + else + LogPrint ("Can't use ElGamal without local destination"); + } + DeleteI2NPMessage (msg); + } + + GarlicRoutingSession::GarlicRoutingSession (const i2p::data::RoutingDestination * destination, int numTags): m_Destination (destination), m_IsAcknowledged (false), m_NumTags (numTags), m_NextTag (-1), m_SessionTags (0), m_TagsCreationTime (0), m_LocalLeaseSet (nullptr) diff --git a/Garlic.h b/Garlic.h index b49e7e83..256e9d2b 100644 --- a/Garlic.h +++ b/Garlic.h @@ -13,6 +13,7 @@ #include "LeaseSet.h" #include "Tunnel.h" #include "Queue.h" +#include "Identity.h" namespace i2p { @@ -39,6 +40,24 @@ namespace garlic const int TAGS_EXPIRATION_TIMEOUT = 900; // 15 minutes typedef i2p::data::Tag<32> SessionTag; + class GarlicDestination + { + public: + + GarlicDestination (i2p::data::LocalDestination * localDestination = nullptr): + m_LocalDestination (localDestination) {}; + ~GarlicDestination (); + + void AddSessionKey (const uint8_t * key, const uint8_t * tag); // one tag + void HandleGarlicMessage (I2NPMessage * msg); + + private: + + i2p::crypto::CBCDecryption m_Decryption; + std::map m_Tags; // tag->key, if null use key from decryption + i2p::data::LocalDestination * m_LocalDestination; + }; + class GarlicRoutingSession { public: