mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-02-02 02:44:15 +00:00
avoid replay upon SSU packet resend
This commit is contained in:
parent
8e25226574
commit
e50abbb250
@ -326,8 +326,7 @@ namespace transport
|
|||||||
{
|
{
|
||||||
Fragment * fragment = new Fragment;
|
Fragment * fragment = new Fragment;
|
||||||
fragment->fragmentNum = fragmentNum;
|
fragment->fragmentNum = fragmentNum;
|
||||||
uint8_t * buf = fragment->buf;
|
uint8_t * payload = fragment->buf + sizeof (SSUHeader);
|
||||||
uint8_t * payload = buf + sizeof (SSUHeader);
|
|
||||||
*payload = DATA_FLAG_WANT_REPLY; // for compatibility
|
*payload = DATA_FLAG_WANT_REPLY; // for compatibility
|
||||||
payload++;
|
payload++;
|
||||||
*payload = 1; // always 1 message fragment per message
|
*payload = 1; // always 1 message fragment per message
|
||||||
@ -346,14 +345,20 @@ namespace transport
|
|||||||
payload += 3;
|
payload += 3;
|
||||||
memcpy (payload, msgBuf, size);
|
memcpy (payload, msgBuf, size);
|
||||||
|
|
||||||
size += payload - buf;
|
size += payload - fragment->buf;
|
||||||
if (size & 0x0F) // make sure 16 bytes boundary
|
uint8_t rem = size & 0x0F;
|
||||||
size = ((size >> 4) + 1) << 4; // (/16 + 1)*16
|
if (rem) // make sure 16 bytes boundary
|
||||||
|
{
|
||||||
|
auto padding = 16 - rem;
|
||||||
|
memset (fragment->buf + size, 0, padding);
|
||||||
|
size += padding;
|
||||||
|
}
|
||||||
fragment->len = size;
|
fragment->len = size;
|
||||||
fragments.push_back (std::unique_ptr<Fragment> (fragment));
|
fragments.push_back (std::unique_ptr<Fragment> (fragment));
|
||||||
|
|
||||||
// encrypt message with session key
|
// encrypt message with session key
|
||||||
m_Session.FillHeaderAndEncrypt (PAYLOAD_TYPE_DATA, buf, size);
|
uint8_t buf[SSU_V4_MAX_PACKET_SIZE + 18];
|
||||||
|
m_Session.FillHeaderAndEncrypt (PAYLOAD_TYPE_DATA, fragment->buf, size, buf);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
m_Session.Send (buf, size);
|
m_Session.Send (buf, size);
|
||||||
@ -432,6 +437,7 @@ namespace transport
|
|||||||
{
|
{
|
||||||
if (ecode != boost::asio::error::operation_aborted)
|
if (ecode != boost::asio::error::operation_aborted)
|
||||||
{
|
{
|
||||||
|
uint8_t buf[SSU_V4_MAX_PACKET_SIZE + 18];
|
||||||
uint32_t ts = i2p::util::GetSecondsSinceEpoch ();
|
uint32_t ts = i2p::util::GetSecondsSinceEpoch ();
|
||||||
int numResent = 0;
|
int numResent = 0;
|
||||||
for (auto it = m_SentMessages.begin (); it != m_SentMessages.end ();)
|
for (auto it = m_SentMessages.begin (); it != m_SentMessages.end ();)
|
||||||
@ -444,8 +450,9 @@ namespace transport
|
|||||||
if (f)
|
if (f)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
m_Session.Send (f->buf, f->len); // resend
|
m_Session.FillHeaderAndEncrypt (PAYLOAD_TYPE_DATA, f->buf, f->len, buf);
|
||||||
|
m_Session.Send (buf, f->len); // resend
|
||||||
numResent++;
|
numResent++;
|
||||||
}
|
}
|
||||||
catch (boost::system::system_error& ec)
|
catch (boost::system::system_error& ec)
|
||||||
|
@ -744,27 +744,33 @@ namespace transport
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SSUSession::FillHeaderAndEncrypt (uint8_t payloadType, uint8_t * buf, size_t len)
|
void SSUSession::FillHeaderAndEncrypt (uint8_t payloadType, uint8_t * buf, size_t len)
|
||||||
|
{
|
||||||
|
FillHeaderAndEncrypt (payloadType, buf, len, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SSUSession::FillHeaderAndEncrypt (uint8_t payloadType, uint8_t * in, size_t len, uint8_t * out)
|
||||||
{
|
{
|
||||||
if (len < sizeof (SSUHeader))
|
if (len < sizeof (SSUHeader))
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "SSU: Unexpected packet length ", len);
|
LogPrint (eLogError, "SSU: Unexpected packet length ", len);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SSUHeader * header = (SSUHeader *)buf;
|
SSUHeader * header = (SSUHeader *)out;
|
||||||
RAND_bytes (header->iv, 16); // random iv
|
RAND_bytes (header->iv, 16); // random iv
|
||||||
m_SessionKeyEncryption.SetIV (header->iv);
|
m_SessionKeyEncryption.SetIV (header->iv);
|
||||||
header->flag = payloadType << 4; // MSB is 0
|
SSUHeader * inHeader = (SSUHeader *)in;
|
||||||
htobe32buf (header->time, i2p::util::GetSecondsSinceEpoch ());
|
inHeader->flag = payloadType << 4; // MSB is 0
|
||||||
uint8_t * encrypted = &header->flag;
|
htobe32buf (inHeader->time, i2p::util::GetSecondsSinceEpoch ());
|
||||||
uint16_t encryptedLen = len - (encrypted - buf);
|
uint8_t * encrypted = &header->flag, * clear = &inHeader->flag;
|
||||||
m_SessionKeyEncryption.Encrypt (encrypted, encryptedLen, encrypted);
|
uint16_t encryptedLen = len - (encrypted - out);
|
||||||
// assume actual buffer size is 18 (16 + 2) bytes more
|
m_SessionKeyEncryption.Encrypt (clear, encryptedLen, encrypted);
|
||||||
memcpy (buf + len, header->iv, 16);
|
// assume actual out buffer size is 18 (16 + 2) bytes more
|
||||||
|
memcpy (out + len, header->iv, 16);
|
||||||
uint16_t netid = i2p::context.GetNetID ();
|
uint16_t netid = i2p::context.GetNetID ();
|
||||||
htobe16buf (buf + len + 16, (netid == I2PD_NET_ID) ? encryptedLen : encryptedLen ^ ((netid - 2) << 8));
|
htobe16buf (out + len + 16, (netid == I2PD_NET_ID) ? encryptedLen : encryptedLen ^ ((netid - 2) << 8));
|
||||||
i2p::crypto::HMACMD5Digest (encrypted, encryptedLen + 18, m_MacKey, header->mac);
|
i2p::crypto::HMACMD5Digest (encrypted, encryptedLen + 18, m_MacKey, header->mac);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SSUSession::Decrypt (uint8_t * buf, size_t len, const i2p::crypto::AESKey& aesKey)
|
void SSUSession::Decrypt (uint8_t * buf, size_t len, const i2p::crypto::AESKey& aesKey)
|
||||||
{
|
{
|
||||||
if (len < sizeof (SSUHeader))
|
if (len < sizeof (SSUHeader))
|
||||||
|
@ -138,6 +138,7 @@ namespace transport
|
|||||||
void FillHeaderAndEncrypt (uint8_t payloadType, uint8_t * buf, size_t len, const i2p::crypto::AESKey& aesKey,
|
void FillHeaderAndEncrypt (uint8_t payloadType, uint8_t * buf, size_t len, const i2p::crypto::AESKey& aesKey,
|
||||||
const uint8_t * iv, const i2p::crypto::MACKey& macKey, uint8_t flag = 0);
|
const uint8_t * iv, const i2p::crypto::MACKey& macKey, uint8_t flag = 0);
|
||||||
void FillHeaderAndEncrypt (uint8_t payloadType, uint8_t * buf, size_t len); // with session key
|
void FillHeaderAndEncrypt (uint8_t payloadType, uint8_t * buf, size_t len); // with session key
|
||||||
|
void FillHeaderAndEncrypt (uint8_t payloadType, uint8_t * in, size_t len, uint8_t * out); // with session key
|
||||||
void Decrypt (uint8_t * buf, size_t len, const i2p::crypto::AESKey& aesKey);
|
void Decrypt (uint8_t * buf, size_t len, const i2p::crypto::AESKey& aesKey);
|
||||||
void DecryptSessionKey (uint8_t * buf, size_t len);
|
void DecryptSessionKey (uint8_t * buf, size_t len);
|
||||||
bool Validate (uint8_t * buf, size_t len, const i2p::crypto::MACKey& macKey);
|
bool Validate (uint8_t * buf, size_t len, const i2p::crypto::MACKey& macKey);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user