mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-01-22 21:37:17 +01:00
DecryptRecord per tunnel hop
This commit is contained in:
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…
Reference in a new issue