|
|
|
@ -660,68 +660,47 @@ namespace i2p
@@ -660,68 +660,47 @@ namespace i2p
|
|
|
|
|
clearText[SHORT_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_GATEWAY_FLAG, |
|
|
|
|
clearText[SHORT_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_ENDPOINT_FLAG); |
|
|
|
|
i2p::tunnel::tunnels.AddTransitTunnel (transitTunnel); |
|
|
|
|
|
|
|
|
|
// encrypt reply
|
|
|
|
|
uint8_t nonce[12]; |
|
|
|
|
memset (nonce, 0, 12); |
|
|
|
|
uint8_t * reply = buf + 1; |
|
|
|
|
for (int j = 0; j < num; j++) |
|
|
|
|
{ |
|
|
|
|
nonce[4] = j; // nonce is record #
|
|
|
|
|
if (j == i) |
|
|
|
|
{ |
|
|
|
|
memset (reply + SHORT_RESPONSE_RECORD_OPTIONS_OFFSET, 0, 2); // no options
|
|
|
|
|
reply[SHORT_RESPONSE_RECORD_RET_OFFSET] = 0; // TODO: correct ret code
|
|
|
|
|
if (!i2p::crypto::AEADChaCha20Poly1305 (reply, SHORT_TUNNEL_BUILD_RECORD_SIZE - 16, |
|
|
|
|
noiseState.m_H, 32, replyKey, nonce, reply, SHORT_TUNNEL_BUILD_RECORD_SIZE, true)) // encrypt
|
|
|
|
|
{ |
|
|
|
|
LogPrint (eLogWarning, "I2NP: Short reply AEAD encryption failed"); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
i2p::crypto::ChaCha20 (reply, SHORT_TUNNEL_BUILD_RECORD_SIZE, noiseState.m_CK, nonce, reply); |
|
|
|
|
reply += SHORT_TUNNEL_BUILD_RECORD_SIZE; |
|
|
|
|
} |
|
|
|
|
// send reply
|
|
|
|
|
if (isEndpoint) |
|
|
|
|
{ |
|
|
|
|
// we are endpoint, create OutboundTunnelBuildReply
|
|
|
|
|
auto otbrm = NewI2NPShortMessage (); |
|
|
|
|
auto payload = otbrm->GetPayload (); |
|
|
|
|
payload[0] = num; // num
|
|
|
|
|
payload[1] = i; // slot
|
|
|
|
|
payload +=2; |
|
|
|
|
// reply
|
|
|
|
|
htobe16buf (payload, 3); payload += 2; // length, TODO
|
|
|
|
|
memset (payload, 0, 3); payload += 3; // ClearText: no options, and zero ret code. TODO
|
|
|
|
|
// ShortBuildReplyRecords. Exclude ours
|
|
|
|
|
uint8_t * records = buf + 1; |
|
|
|
|
if (i > 0) |
|
|
|
|
{ |
|
|
|
|
memcpy (payload, records, i*SHORT_TUNNEL_BUILD_RECORD_SIZE); |
|
|
|
|
payload += i*SHORT_TUNNEL_BUILD_RECORD_SIZE; |
|
|
|
|
records += i*SHORT_TUNNEL_BUILD_RECORD_SIZE; |
|
|
|
|
} |
|
|
|
|
if (i < num-1) |
|
|
|
|
{ |
|
|
|
|
memcpy (payload, records, (num-1-i)*SHORT_TUNNEL_BUILD_RECORD_SIZE); |
|
|
|
|
payload += (num-1-i)*SHORT_TUNNEL_BUILD_RECORD_SIZE; |
|
|
|
|
} |
|
|
|
|
otbrm->len += (payload - otbrm->GetPayload ()); |
|
|
|
|
otbrm->FillI2NPMessageHeader (eI2NPOutboundTunnelBuildReply, bufbe32toh (clearText + SHORT_REQUEST_RECORD_SEND_MSG_ID_OFFSET)); |
|
|
|
|
auto replyMsg = NewI2NPShortMessage (); |
|
|
|
|
replyMsg->Concat (buf, len); |
|
|
|
|
replyMsg->FillI2NPMessageHeader (eI2NPShortTunnelBuildReply, bufbe32toh (clearText + SHORT_REQUEST_RECORD_SEND_MSG_ID_OFFSET)); |
|
|
|
|
i2p::crypto::HKDF (noiseState.m_CK, nullptr, 0, "RGarlicKeyAndTag", noiseState.m_CK); |
|
|
|
|
uint64_t tag; |
|
|
|
|
memcpy (&tag, noiseState.m_CK, 8); |
|
|
|
|
// send garlic to reply tunnel
|
|
|
|
|
// we send it to reply tunnel
|
|
|
|
|
transports.SendMessage (clearText + SHORT_REQUEST_RECORD_NEXT_IDENT_OFFSET, |
|
|
|
|
CreateTunnelGatewayMsg (bufbe32toh (clearText + SHORT_REQUEST_RECORD_NEXT_TUNNEL_OFFSET), |
|
|
|
|
i2p::garlic::WrapECIESX25519Message (otbrm, noiseState.m_CK + 32, tag))); |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
// we are participant, encrypt reply
|
|
|
|
|
uint8_t nonce[12]; |
|
|
|
|
memset (nonce, 0, 12); |
|
|
|
|
uint8_t * reply = buf + 1; |
|
|
|
|
for (int j = 0; j < num; j++) |
|
|
|
|
{ |
|
|
|
|
nonce[4] = j; // nonce is record #
|
|
|
|
|
if (j == i) |
|
|
|
|
{ |
|
|
|
|
memset (reply + SHORT_RESPONSE_RECORD_OPTIONS_OFFSET, 0, 2); // no options
|
|
|
|
|
reply[SHORT_RESPONSE_RECORD_RET_OFFSET] = 0; // TODO: correct ret code
|
|
|
|
|
if (!i2p::crypto::AEADChaCha20Poly1305 (reply, SHORT_TUNNEL_BUILD_RECORD_SIZE - 16, |
|
|
|
|
noiseState.m_H, 32, replyKey, nonce, reply, SHORT_TUNNEL_BUILD_RECORD_SIZE, true)) // encrypt
|
|
|
|
|
{ |
|
|
|
|
LogPrint (eLogWarning, "I2NP: Short reply AEAD encryption failed"); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
i2p::crypto::ChaCha20 (reply, SHORT_TUNNEL_BUILD_RECORD_SIZE, noiseState.m_CK, nonce, reply); |
|
|
|
|
reply += SHORT_TUNNEL_BUILD_RECORD_SIZE; |
|
|
|
|
} |
|
|
|
|
CreateTunnelGatewayMsg (bufbe32toh (clearText + SHORT_REQUEST_RECORD_NEXT_TUNNEL_OFFSET), |
|
|
|
|
i2p::garlic::WrapECIESX25519Message (replyMsg, noiseState.m_CK + 32, tag))); |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
transports.SendMessage (clearText + SHORT_REQUEST_RECORD_NEXT_TUNNEL_OFFSET, |
|
|
|
|
CreateI2NPMessage (eI2NPShortTunnelBuild, buf, len, |
|
|
|
|
bufbe32toh (clearText + SHORT_REQUEST_RECORD_SEND_MSG_ID_OFFSET))); |
|
|
|
|
} |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
record += SHORT_TUNNEL_BUILD_RECORD_SIZE; |
|
|
|
@ -843,6 +822,7 @@ namespace i2p
@@ -843,6 +822,7 @@ namespace i2p
|
|
|
|
|
HandleVariableTunnelBuildMsg (msgID, buf, size); |
|
|
|
|
break; |
|
|
|
|
case eI2NPVariableTunnelBuildReply: |
|
|
|
|
case eI2NPShortTunnelBuildReply: |
|
|
|
|
HandleVariableTunnelBuildReplyMsg (msgID, buf, size); |
|
|
|
|
break; |
|
|
|
|
case eI2NPShortTunnelBuild: |
|
|
|
@ -905,6 +885,7 @@ namespace i2p
@@ -905,6 +885,7 @@ namespace i2p
|
|
|
|
|
case eI2NPTunnelBuild: |
|
|
|
|
case eI2NPTunnelBuildReply: |
|
|
|
|
case eI2NPShortTunnelBuild: |
|
|
|
|
case eI2NPShortTunnelBuildReply: |
|
|
|
|
// forward to tunnel thread
|
|
|
|
|
i2p::tunnel::tunnels.PostTunnelData (msg); |
|
|
|
|
break; |
|
|
|
|