Browse Source

wait for Ack for SessionConfirmed or resend

pull/1771/head
orignal 3 years ago
parent
commit
dd1dd3b7cf
  1. 1
      libi2pd/SSU2.cpp
  2. 21
      libi2pd/SSU2Session.cpp
  3. 3
      libi2pd/SSU2Session.h

1
libi2pd/SSU2.cpp

@ -359,6 +359,7 @@ namespace transport
switch (m_LastSession->GetState ()) switch (m_LastSession->GetState ())
{ {
case eSSU2SessionStateEstablished: case eSSU2SessionStateEstablished:
case eSSU2SessionStateSessionConfirmedSent:
m_LastSession->ProcessData (buf, len); m_LastSession->ProcessData (buf, len);
break; break;
case eSSU2SessionStateSessionCreatedSent: case eSSU2SessionStateSessionCreatedSent:

21
libi2pd/SSU2Session.cpp

@ -306,8 +306,7 @@ namespace transport
// resend handshake packet // resend handshake packet
if (m_SentHandshakePacket && ts >= m_SentHandshakePacket->nextResendTime) if (m_SentHandshakePacket && ts >= m_SentHandshakePacket->nextResendTime)
{ {
// TODO: implement SessionConfirmed LogPrint (eLogDebug, "SSU2: Resending ", (int)m_State);
LogPrint (eLogDebug, "SSU2: Resending ", (m_State == eSSU2SessionStateSessionRequestSent) ? "SessionRequest" : "SessionCreated");
m_Server.Send (m_SentHandshakePacket->header.buf, 16, m_SentHandshakePacket->headerX, 48, m_Server.Send (m_SentHandshakePacket->header.buf, 16, m_SentHandshakePacket->headerX, 48,
m_SentHandshakePacket->payload, m_SentHandshakePacket->payloadSize, m_RemoteEndpoint); m_SentHandshakePacket->payload, m_SentHandshakePacket->payloadSize, m_RemoteEndpoint);
m_SentHandshakePacket->numResends++; m_SentHandshakePacket->numResends++;
@ -575,7 +574,6 @@ namespace transport
m_Server.AddSession (shared_from_this ()); m_Server.AddSession (shared_from_this ());
SendSessionConfirmed (headerX + 16); SendSessionConfirmed (headerX + 16);
KDFDataPhase (m_KeyDataSend, m_KeyDataReceive); KDFDataPhase (m_KeyDataSend, m_KeyDataReceive);
Established ();
return true; return true;
} }
@ -583,10 +581,14 @@ namespace transport
void SSU2Session::SendSessionConfirmed (const uint8_t * Y) void SSU2Session::SendSessionConfirmed (const uint8_t * Y)
{ {
// we are Alice // we are Alice
m_SentHandshakePacket.reset (new HandshakePacket);
auto ts = i2p::util::GetSecondsSinceEpoch ();
m_SentHandshakePacket->nextResendTime = ts + SSU2_HANDSHAKE_RESEND_INTERVAL;
uint8_t kh2[32]; uint8_t kh2[32];
i2p::crypto::HKDF (m_NoiseState->m_CK, nullptr, 0, "SessionConfirmed", kh2, 32); // k_header_2 = HKDF(chainKey, ZEROLEN, "SessionConfirmed", 32) i2p::crypto::HKDF (m_NoiseState->m_CK, nullptr, 0, "SessionConfirmed", kh2, 32); // k_header_2 = HKDF(chainKey, ZEROLEN, "SessionConfirmed", 32)
// fill packet // fill packet
Header header; Header& header = m_SentHandshakePacket->header;
header.h.connID = m_DestConnID; // dest id header.h.connID = m_DestConnID; // dest id
header.h.packetNum = 0; header.h.packetNum = 0;
header.h.type = eSSU2SessionConfirmed; header.h.type = eSSU2SessionConfirmed;
@ -594,7 +596,7 @@ namespace transport
header.h.flags[0] = 1; // frag, total fragments always 1 header.h.flags[0] = 1; // frag, total fragments always 1
// payload // payload
const size_t maxPayloadSize = SSU2_MAX_PAYLOAD_SIZE - 48; // part 2 const size_t maxPayloadSize = SSU2_MAX_PAYLOAD_SIZE - 48; // part 2
uint8_t payload[maxPayloadSize + 16]; uint8_t * payload = m_SentHandshakePacket->payload;
size_t payloadSize = CreateRouterInfoBlock (payload, maxPayloadSize, i2p::context.GetSharedRouterInfo ()); size_t payloadSize = CreateRouterInfoBlock (payload, maxPayloadSize, i2p::context.GetSharedRouterInfo ());
// TODO: check is RouterInfo doesn't fit and split by two fragments // TODO: check is RouterInfo doesn't fit and split by two fragments
if (payloadSize < maxPayloadSize) if (payloadSize < maxPayloadSize)
@ -602,7 +604,7 @@ namespace transport
// KDF for Session Confirmed part 1 // KDF for Session Confirmed part 1
m_NoiseState->MixHash (header.buf, 16); // h = SHA256(h || header) m_NoiseState->MixHash (header.buf, 16); // h = SHA256(h || header)
// Encrypt part 1 // Encrypt part 1
uint8_t part1[48]; uint8_t * part1 = m_SentHandshakePacket->headerX;
uint8_t nonce[12]; uint8_t nonce[12];
CreateNonce (1, nonce); CreateNonce (1, nonce);
i2p::crypto::AEADChaCha20Poly1305 (i2p::context.GetSSU2StaticPublicKey (), 32, m_NoiseState->m_H, 32, m_NoiseState->m_CK + 32, nonce, part1, 48, true); i2p::crypto::AEADChaCha20Poly1305 (i2p::context.GetSSU2StaticPublicKey (), 32, m_NoiseState->m_H, 32, m_NoiseState->m_CK + 32, nonce, part1, 48, true);
@ -619,6 +621,8 @@ namespace transport
// Encrypt header // Encrypt header
header.ll[0] ^= CreateHeaderMask (m_Address->i, payload + (payloadSize - 24)); header.ll[0] ^= CreateHeaderMask (m_Address->i, payload + (payloadSize - 24));
header.ll[1] ^= CreateHeaderMask (kh2, payload + (payloadSize - 12)); header.ll[1] ^= CreateHeaderMask (kh2, payload + (payloadSize - 12));
m_State = eSSU2SessionStateSessionConfirmedSent;
m_SentHandshakePacket->payloadSize = payloadSize;
// send // send
m_Server.Send (header.buf, 16, part1, 48, payload, payloadSize, m_RemoteEndpoint); m_Server.Send (header.buf, 16, part1, 48, payload, payloadSize, m_RemoteEndpoint);
m_SendPacketNum++; m_SendPacketNum++;
@ -1199,6 +1203,11 @@ namespace transport
void SSU2Session::HandleAck (const uint8_t * buf, size_t len) void SSU2Session::HandleAck (const uint8_t * buf, size_t len)
{ {
if (m_State == eSSU2SessionStateSessionConfirmedSent)
{
Established ();
return;
}
if (m_SentPackets.empty ()) return; if (m_SentPackets.empty ()) return;
if (len < 5) return; if (len < 5) return;
// acnt // acnt

3
libi2pd/SSU2Session.h

@ -83,6 +83,7 @@ namespace transport
eSSU2SessionStateTokenReceived, eSSU2SessionStateTokenReceived,
eSSU2SessionStateSessionRequestSent, eSSU2SessionStateSessionRequestSent,
eSSU2SessionStateSessionCreatedSent, eSSU2SessionStateSessionCreatedSent,
eSSU2SessionStateSessionConfirmedSent,
eSSU2SessionStateEstablished, eSSU2SessionStateEstablished,
eSSU2SessionStateTerminated, eSSU2SessionStateTerminated,
eSSU2SessionStateFailed, eSSU2SessionStateFailed,
@ -163,7 +164,7 @@ namespace transport
struct HandshakePacket: public SentPacket struct HandshakePacket: public SentPacket
{ {
Header header; Header header;
uint8_t headerX[48]; // not used in SessionConfirmed uint8_t headerX[48]; // part1 for SessionConfirmed
}; };
typedef std::function<void ()> OnEstablished; typedef std::function<void ()> OnEstablished;

Loading…
Cancel
Save