std::shared_ptr<I2NPMessage> RequestedDestination::CreateRequestMessage (std::shared_ptr<const RouterInfo> router, std::shared_ptr<const i2p::tunnel::InboundTunnel> replyTunnel) { I2NPMessage * msg = i2p::CreateRouterInfoDatabaseLookupMsg (m_Destination, replyTunnel->GetNextIdentHash (), replyTunnel->GetNextTunnelID (), m_IsExploratory, &m_ExcludedPeers); m_ExcludedPeers.insert (router->GetIdentHash ()); m_CreationTime = i2p::util::GetSecondsSinceEpoch (); return ToSharedI2NPMessage (msg); }
void RouterContext::HandleI2NPMessage (const uint8_t * buf, size_t len, std::shared_ptr<i2p::tunnel::InboundTunnel> from) { i2p::HandleI2NPMessage (ToSharedI2NPMessage(CreateI2NPMessage (buf, GetI2NPMessageLength (buf), from))); }
std::shared_ptr<I2NPMessage> GarlicRoutingSession::WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg) { auto m = ToSharedI2NPMessage(NewI2NPMessage ()); m->Align (12); // in order to get buf aligned to 16 (12 + 4) size_t len = 0; uint8_t * buf = m->GetPayload () + 4; // 4 bytes for length // find non-expired tag bool tagFound = false; SessionTag tag; if (m_NumTags > 0) { uint32_t ts = i2p::util::GetSecondsSinceEpoch (); while (!m_SessionTags.empty ()) { if (ts < m_SessionTags.front ().creationTime + OUTGOING_TAGS_EXPIRATION_TIMEOUT) { tag = m_SessionTags.front (); m_SessionTags.pop_front (); // use same tag only once tagFound = true; break; } else m_SessionTags.pop_front (); // remove expired tag } } // create message if (!tagFound) // new session { LogPrint ("No garlic tags available. Use ElGamal"); if (!m_Destination) { LogPrint ("Can't use ElGamal for unknown destination"); return nullptr; } // create ElGamal block ElGamalBlock elGamal; memcpy (elGamal.sessionKey, m_SessionKey, 32); m_Rnd.GenerateBlock (elGamal.preIV, 32); // Pre-IV 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.SetIV (iv); buf += 514; len += 514; } else // existing session { // session tag memcpy (buf, tag, 32); uint8_t iv[32]; // IV is first 16 bytes CryptoPP::SHA256().CalculateDigest(iv, tag, 32); m_Encryption.SetIV (iv); buf += 32; len += 32; } // AES block len += CreateAESBlock (buf, msg); htobe32buf (m->GetPayload (), len); m->len += len + 4; m->FillI2NPMessageHeader (eI2NPGarlic); return m; }