DecryptRecord per tunnel hop

pull/1677/head
orignal 3 years ago
parent 847225c6bf
commit ed0c2e68a5

@ -78,18 +78,14 @@ namespace tunnel
} }
// decrypt real records // decrypt real records
i2p::crypto::CBCDecryption decryption;
hop = m_Config->GetLastHop ()->prev; hop = m_Config->GetLastHop ()->prev;
while (hop) while (hop)
{ {
decryption.SetKey (hop->replyKey);
// decrypt records after current hop // decrypt records after current hop
TunnelHopConfig * hop1 = hop->next; TunnelHopConfig * hop1 = hop->next;
while (hop1) while (hop1)
{ {
decryption.SetIV (hop->replyIV); hop->DecryptRecord (records, hop1->recordIndex);
uint8_t * record = records + hop1->recordIndex*TUNNEL_BUILD_RECORD_SIZE;
decryption.Decrypt(record, TUNNEL_BUILD_RECORD_SIZE, record);
hop1 = hop1->next; hop1 = hop1->next;
} }
hop = hop->prev; hop = hop->prev;
@ -132,11 +128,7 @@ namespace tunnel
{ {
auto idx = hop1->recordIndex; auto idx = hop1->recordIndex;
if (idx >= 0 && idx < msg[0]) if (idx >= 0 && idx < msg[0])
{ hop->DecryptRecord (msg + 1, idx);
uint8_t * record = msg + 1 + idx*TUNNEL_BUILD_RECORD_SIZE;
decryption.SetIV (hop->replyIV);
decryption.Decrypt(record, TUNNEL_BUILD_RECORD_SIZE, record);
}
else else
LogPrint (eLogWarning, "Tunnel: hop index ", idx, " is out of range"); LogPrint (eLogWarning, "Tunnel: hop index ", idx, " is out of range");
hop1 = hop1->prev; hop1 = hop1->prev;

@ -77,6 +77,15 @@ namespace tunnel
isGateway = false; isGateway = false;
} }
} }
void TunnelHopConfig::DecryptRecord (uint8_t * records, int index) const
{
uint8_t * record = records + index*TUNNEL_BUILD_RECORD_SIZE;
i2p::crypto::CBCDecryption decryption;
decryption.SetKey (replyKey);
decryption.SetIV (replyIV);
decryption.Decrypt(record, TUNNEL_BUILD_RECORD_SIZE, record);
}
void ElGamalTunnelHopConfig::CreateBuildRequestRecord (uint8_t * record, uint32_t replyMsgID, BN_CTX * ctx) void ElGamalTunnelHopConfig::CreateBuildRequestRecord (uint8_t * record, uint32_t replyMsgID, BN_CTX * ctx)
{ {
@ -104,7 +113,7 @@ namespace tunnel
memcpy (record + BUILD_REQUEST_RECORD_TO_PEER_OFFSET, (const uint8_t *)ident->GetIdentHash (), 16); memcpy (record + BUILD_REQUEST_RECORD_TO_PEER_OFFSET, (const uint8_t *)ident->GetIdentHash (), 16);
} }
bool ElGamalTunnelHopConfig::DecryptBuildResponseRecord (const uint8_t * encrypted, uint8_t * clearText) bool ElGamalTunnelHopConfig::DecryptBuildResponseRecord (const uint8_t * encrypted, uint8_t * clearText) const
{ {
i2p::crypto::CBCDecryption decryption; i2p::crypto::CBCDecryption decryption;
decryption.SetKey (replyKey); decryption.SetKey (replyKey);
@ -137,10 +146,8 @@ namespace tunnel
MixHash (encrypted, len + 16); // h = SHA256(h || ciphertext) MixHash (encrypted, len + 16); // h = SHA256(h || ciphertext)
} }
bool ECIESTunnelHopConfig::DecryptECIES (const uint8_t * key, const uint8_t * encrypted, size_t len, uint8_t * clearText) bool ECIESTunnelHopConfig::DecryptECIES (const uint8_t * key, const uint8_t * nonce, const uint8_t * encrypted, size_t len, uint8_t * clearText) const
{ {
uint8_t nonce[12];
memset (nonce, 0, 12);
return i2p::crypto::AEADChaCha20Poly1305 (encrypted, len - 16, m_H, 32, key, nonce, clearText, len - 16, false); // decrypt return i2p::crypto::AEADChaCha20Poly1305 (encrypted, len - 16, m_H, 32, key, nonce, clearText, len - 16, false); // decrypt
} }
@ -169,9 +176,11 @@ namespace tunnel
memcpy (record + BUILD_REQUEST_RECORD_TO_PEER_OFFSET, (const uint8_t *)ident->GetIdentHash (), 16); memcpy (record + BUILD_REQUEST_RECORD_TO_PEER_OFFSET, (const uint8_t *)ident->GetIdentHash (), 16);
} }
bool LongECIESTunnelHopConfig::DecryptBuildResponseRecord (const uint8_t * encrypted, uint8_t * clearText) bool LongECIESTunnelHopConfig::DecryptBuildResponseRecord (const uint8_t * encrypted, uint8_t * clearText) const
{ {
if (!DecryptECIES (m_CK, encrypted, TUNNEL_BUILD_RECORD_SIZE, clearText)) uint8_t nonce[12];
memset (nonce, 0, 12);
if (!DecryptECIES (m_CK, nonce, encrypted, TUNNEL_BUILD_RECORD_SIZE, clearText))
{ {
LogPrint (eLogWarning, "Tunnel: Response AEAD decryption failed"); LogPrint (eLogWarning, "Tunnel: Response AEAD decryption failed");
return false; return false;
@ -214,14 +223,26 @@ namespace tunnel
memcpy (record + BUILD_REQUEST_RECORD_TO_PEER_OFFSET, (const uint8_t *)ident->GetIdentHash (), 16); memcpy (record + BUILD_REQUEST_RECORD_TO_PEER_OFFSET, (const uint8_t *)ident->GetIdentHash (), 16);
} }
bool ShortECIESTunnelHopConfig::DecryptBuildResponseRecord (const uint8_t * encrypted, uint8_t * clearText) bool ShortECIESTunnelHopConfig::DecryptBuildResponseRecord (const uint8_t * encrypted, uint8_t * clearText) const
{ {
if (!DecryptECIES (replyKey, encrypted, SHORT_TUNNEL_BUILD_RECORD_SIZE, clearText)) uint8_t nonce[12];
memset (nonce, 0, 12);
nonce[4] = recordIndex; // nonce is record index
if (!DecryptECIES (replyKey, nonce, encrypted, SHORT_TUNNEL_BUILD_RECORD_SIZE, clearText))
{ {
LogPrint (eLogWarning, "Tunnel: Response AEAD decryption failed"); LogPrint (eLogWarning, "Tunnel: Response AEAD decryption failed");
return false; return false;
} }
return true; return true;
} }
void ShortECIESTunnelHopConfig::DecryptRecord (uint8_t * records, int index) const
{
uint8_t * record = records + index*SHORT_TUNNEL_BUILD_RECORD_SIZE;
uint8_t nonce[12];
memset (nonce, 0, 12);
nonce[4] = index; // nonce is index
i2p::crypto::ChaCha20 (record, SHORT_TUNNEL_BUILD_RECORD_SIZE, replyKey, nonce, record);
}
} }
} }

@ -42,7 +42,8 @@ namespace tunnel
virtual bool IsECIES () const { return false; }; virtual bool IsECIES () const { return false; };
virtual void CreateBuildRequestRecord (uint8_t * record, uint32_t replyMsgID, BN_CTX * ctx) = 0; virtual void CreateBuildRequestRecord (uint8_t * record, uint32_t replyMsgID, BN_CTX * ctx) = 0;
virtual bool DecryptBuildResponseRecord (const uint8_t * encrypted, uint8_t * clearText) = 0; virtual bool DecryptBuildResponseRecord (const uint8_t * encrypted, uint8_t * clearText) const = 0;
virtual void DecryptRecord (uint8_t * records, int index) const; // AES
}; };
struct ElGamalTunnelHopConfig: public TunnelHopConfig struct ElGamalTunnelHopConfig: public TunnelHopConfig
@ -50,7 +51,7 @@ namespace tunnel
ElGamalTunnelHopConfig (std::shared_ptr<const i2p::data::IdentityEx> r): ElGamalTunnelHopConfig (std::shared_ptr<const i2p::data::IdentityEx> r):
TunnelHopConfig (r) {}; TunnelHopConfig (r) {};
void CreateBuildRequestRecord (uint8_t * record, uint32_t replyMsgID, BN_CTX * ctx); void CreateBuildRequestRecord (uint8_t * record, uint32_t replyMsgID, BN_CTX * ctx);
bool DecryptBuildResponseRecord (const uint8_t * encrypted, uint8_t * clearText); bool DecryptBuildResponseRecord (const uint8_t * encrypted, uint8_t * clearText) const;
}; };
struct ECIESTunnelHopConfig: public TunnelHopConfig, public i2p::crypto::NoiseSymmetricState struct ECIESTunnelHopConfig: public TunnelHopConfig, public i2p::crypto::NoiseSymmetricState
@ -59,7 +60,7 @@ namespace tunnel
TunnelHopConfig (r) {}; TunnelHopConfig (r) {};
bool IsECIES () const { return true; }; bool IsECIES () const { return true; };
void EncryptECIES (const uint8_t * clearText, size_t len, uint8_t * encrypted); void EncryptECIES (const uint8_t * clearText, size_t len, uint8_t * encrypted);
bool DecryptECIES (const uint8_t * key, const uint8_t * encrypted, size_t len, uint8_t * clearText); bool DecryptECIES (const uint8_t * key, const uint8_t * nonce, const uint8_t * encrypted, size_t len, uint8_t * clearText) const;
}; };
struct LongECIESTunnelHopConfig: public ECIESTunnelHopConfig struct LongECIESTunnelHopConfig: public ECIESTunnelHopConfig
@ -67,7 +68,7 @@ namespace tunnel
LongECIESTunnelHopConfig (std::shared_ptr<const i2p::data::IdentityEx> r): LongECIESTunnelHopConfig (std::shared_ptr<const i2p::data::IdentityEx> r):
ECIESTunnelHopConfig (r) {}; ECIESTunnelHopConfig (r) {};
void CreateBuildRequestRecord (uint8_t * record, uint32_t replyMsgID, BN_CTX * ctx); void CreateBuildRequestRecord (uint8_t * record, uint32_t replyMsgID, BN_CTX * ctx);
bool DecryptBuildResponseRecord (const uint8_t * encrypted, uint8_t * clearText); bool DecryptBuildResponseRecord (const uint8_t * encrypted, uint8_t * clearText) const;
}; };
struct ShortECIESTunnelHopConfig: public ECIESTunnelHopConfig struct ShortECIESTunnelHopConfig: public ECIESTunnelHopConfig
@ -75,20 +76,21 @@ namespace tunnel
ShortECIESTunnelHopConfig (std::shared_ptr<const i2p::data::IdentityEx> r): ShortECIESTunnelHopConfig (std::shared_ptr<const i2p::data::IdentityEx> r):
ECIESTunnelHopConfig (r) {}; ECIESTunnelHopConfig (r) {};
void CreateBuildRequestRecord (uint8_t * record, uint32_t replyMsgID, BN_CTX * ctx); void CreateBuildRequestRecord (uint8_t * record, uint32_t replyMsgID, BN_CTX * ctx);
bool DecryptBuildResponseRecord (const uint8_t * encrypted, uint8_t * clearText); bool DecryptBuildResponseRecord (const uint8_t * encrypted, uint8_t * clearText) const;
void DecryptRecord (uint8_t * records, int index) const override; // Chacha20
}; };
class TunnelConfig class TunnelConfig
{ {
public: public:
TunnelConfig (std::vector<std::shared_ptr<const i2p::data::IdentityEx> > peers) // inbound TunnelConfig (const std::vector<std::shared_ptr<const i2p::data::IdentityEx> >& peers) // inbound
{ {
CreatePeers (peers); CreatePeers (peers);
m_LastHop->SetNextIdent (i2p::context.GetIdentHash ()); m_LastHop->SetNextIdent (i2p::context.GetIdentHash ());
} }
TunnelConfig (std::vector<std::shared_ptr<const i2p::data::IdentityEx> > peers, TunnelConfig (const std::vector<std::shared_ptr<const i2p::data::IdentityEx> >& peers,
uint32_t replyTunnelID, const i2p::data::IdentHash& replyIdent) // outbound uint32_t replyTunnelID, const i2p::data::IdentHash& replyIdent) // outbound
{ {
CreatePeers (peers); CreatePeers (peers);
@ -180,8 +182,7 @@ namespace tunnel
private: private:
template<class Peers> void CreatePeers (const std::vector<std::shared_ptr<const i2p::data::IdentityEx> >& peers)
void CreatePeers (const Peers& peers)
{ {
TunnelHopConfig * prev = nullptr; TunnelHopConfig * prev = nullptr;
for (const auto& it: peers) for (const auto& it: peers)

Loading…
Cancel
Save