mirror of
https://github.com/SoftEtherVPN/SoftEtherVPN.git
synced 2024-11-22 17:39:53 +03:00
Cedar: implement UDP acceleration version 2, powered by ChaCha20-Poly1305
This commit is contained in:
parent
82a81a3ce6
commit
2ea5c2a7b0
@ -253,7 +253,7 @@ void UdpAccelSendBlock(UDP_ACCEL *a, BLOCK *b)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
UdpAccelSend(a, b->Buf, b->Size, b->Compressed, a->MaxUdpPacketSize, b->PriorityQoS);
|
UdpAccelSend(a, b->Buf, b->Size, b->Compressed ? 1 : 0, a->MaxUdpPacketSize, b->PriorityQoS);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate the best MSS
|
// Calculate the best MSS
|
||||||
@ -285,7 +285,7 @@ UINT UdpAccelCalcMss(UDP_ACCEL *a)
|
|||||||
if (a->PlainTextMode == false)
|
if (a->PlainTextMode == false)
|
||||||
{
|
{
|
||||||
// IV
|
// IV
|
||||||
ret -= UDP_ACCELERATION_PACKET_IV_SIZE;
|
ret -= UDP_ACCELERATION_PACKET_IV_SIZE_V1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cookie
|
// Cookie
|
||||||
@ -306,7 +306,7 @@ UINT UdpAccelCalcMss(UDP_ACCEL *a)
|
|||||||
if (a->PlainTextMode == false)
|
if (a->PlainTextMode == false)
|
||||||
{
|
{
|
||||||
// Verify
|
// Verify
|
||||||
ret -= UDP_ACCELERATION_PACKET_IV_SIZE;
|
ret -= UDP_ACCELERATION_PACKET_IV_SIZE_V1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ethernet header (communication packets)
|
// Ethernet header (communication packets)
|
||||||
@ -322,19 +322,13 @@ UINT UdpAccelCalcMss(UDP_ACCEL *a)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Send
|
// Send
|
||||||
void UdpAccelSend(UDP_ACCEL *a, UCHAR *data, UINT data_size, bool compressed, UINT max_size, bool high_priority)
|
void UdpAccelSend(UDP_ACCEL *a, UCHAR *data, UINT data_size, UCHAR flag, UINT max_size, bool high_priority)
|
||||||
{
|
{
|
||||||
UCHAR tmp[UDP_ACCELERATION_TMP_BUF_SIZE];
|
UCHAR buffer[UDP_ACCELERATION_TMP_BUF_SIZE];
|
||||||
UCHAR *buf;
|
UCHAR *buf = buffer;
|
||||||
UINT size;
|
UINT size = 0;
|
||||||
UCHAR key[UDP_ACCELERATION_PACKET_KEY_SIZE];
|
UINT64 tmp;
|
||||||
UINT64 ui64;
|
UINT ret;
|
||||||
USHORT us;
|
|
||||||
UCHAR c;
|
|
||||||
UINT current_size;
|
|
||||||
UINT ui32;
|
|
||||||
bool fatal_error = false;
|
|
||||||
UINT r;
|
|
||||||
// Validate arguments
|
// Validate arguments
|
||||||
if (a == NULL || (data_size != 0 && data == NULL))
|
if (a == NULL || (data_size != 0 && data == NULL))
|
||||||
{
|
{
|
||||||
@ -345,171 +339,167 @@ void UdpAccelSend(UDP_ACCEL *a, UCHAR *data, UINT data_size, bool compressed, UI
|
|||||||
max_size = INFINITE;
|
max_size = INFINITE;
|
||||||
}
|
}
|
||||||
|
|
||||||
buf = tmp;
|
|
||||||
size = 0;
|
|
||||||
|
|
||||||
// IV
|
|
||||||
if (a->PlainTextMode == false)
|
if (a->PlainTextMode == false)
|
||||||
{
|
{
|
||||||
// IV
|
if (a->Version > 1)
|
||||||
Copy(buf, a->NextIv, UDP_ACCELERATION_PACKET_IV_SIZE);
|
|
||||||
|
|
||||||
buf += UDP_ACCELERATION_PACKET_IV_SIZE;
|
|
||||||
size += UDP_ACCELERATION_PACKET_IV_SIZE;
|
|
||||||
|
|
||||||
// Calculate the key
|
|
||||||
UdpAccelCalcKey(key, a->MyKey, a->NextIv);
|
|
||||||
|
|
||||||
if (false)
|
|
||||||
{
|
{
|
||||||
char tmp1[256];
|
Copy(buf, a->NextIv_V2, UDP_ACCELERATION_PACKET_IV_SIZE_V2);
|
||||||
char tmp2[256];
|
|
||||||
char tmp3[256];
|
buf += UDP_ACCELERATION_PACKET_IV_SIZE_V2;
|
||||||
BinToStr(tmp1, sizeof(tmp1), a->MyKey, sizeof(a->MyKey));
|
size += UDP_ACCELERATION_PACKET_IV_SIZE_V2;
|
||||||
BinToStr(tmp2, sizeof(tmp2), a->NextIv, UDP_ACCELERATION_PACKET_IV_SIZE);
|
}
|
||||||
BinToStr(tmp3, sizeof(tmp3), key, sizeof(key));
|
else
|
||||||
Debug("My Key : %s\n"
|
{
|
||||||
"IV : %s\n"
|
Copy(buf, a->NextIv, UDP_ACCELERATION_PACKET_IV_SIZE_V1);
|
||||||
"Comm Key: %s\n",
|
|
||||||
tmp1, tmp2, tmp3);
|
buf += UDP_ACCELERATION_PACKET_IV_SIZE_V1;
|
||||||
|
size += UDP_ACCELERATION_PACKET_IV_SIZE_V1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cookie
|
// Cookie
|
||||||
ui32 = Endian32(a->YourCookie);
|
tmp = Endian32(a->YourCookie);
|
||||||
Copy(buf, &ui32, sizeof(UINT));
|
Copy(buf, &tmp, sizeof(UINT));
|
||||||
buf += sizeof(UINT);
|
buf += sizeof(UINT);
|
||||||
size += sizeof(UINT);
|
size += sizeof(UINT);
|
||||||
|
|
||||||
// My Tick
|
// My tick
|
||||||
ui64 = Endian64(a->Now == 0 ? 1ULL : a->Now);
|
tmp = Endian64(a->Now == 0 ? 1ULL : a->Now);
|
||||||
Copy(buf, &ui64, sizeof(UINT64));
|
Copy(buf, &tmp, sizeof(UINT64));
|
||||||
buf += sizeof(UINT64);
|
buf += sizeof(UINT64);
|
||||||
size += sizeof(UINT64);
|
size += sizeof(UINT64);
|
||||||
|
|
||||||
// Your Tick
|
// Your tick
|
||||||
ui64 = Endian64(a->LastRecvYourTick);
|
tmp = Endian64(a->LastRecvYourTick);
|
||||||
Copy(buf, &ui64, sizeof(UINT64));
|
Copy(buf, &tmp, sizeof(UINT64));
|
||||||
buf += sizeof(UINT64);
|
buf += sizeof(UINT64);
|
||||||
size += sizeof(UINT64);
|
size += sizeof(UINT64);
|
||||||
|
|
||||||
// Size
|
// Size
|
||||||
us = Endian16(data_size);
|
tmp = Endian16(data_size);
|
||||||
Copy(buf, &us, sizeof(USHORT));
|
Copy(buf, &tmp, sizeof(USHORT));
|
||||||
buf += sizeof(USHORT);
|
buf += sizeof(USHORT);
|
||||||
size += sizeof(USHORT);
|
size += sizeof(USHORT);
|
||||||
|
|
||||||
// Compress Flag
|
// Flag
|
||||||
c = (compressed ? 1 : 0);
|
Copy(buf, &flag, sizeof(UCHAR));
|
||||||
Copy(buf, &c, sizeof(UCHAR));
|
|
||||||
buf += sizeof(UCHAR);
|
buf += sizeof(UCHAR);
|
||||||
size += sizeof(UCHAR);
|
size += sizeof(UCHAR);
|
||||||
|
|
||||||
// Data
|
// Data
|
||||||
if (data_size >= 1)
|
Copy(buf, data, data_size);
|
||||||
{
|
buf += data_size;
|
||||||
Copy(buf, data, data_size);
|
size += data_size;
|
||||||
buf += data_size;
|
|
||||||
size += data_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (a->PlainTextMode == false)
|
if (a->PlainTextMode == false)
|
||||||
{
|
{
|
||||||
static UCHAR zero[UDP_ACCELERATION_PACKET_IV_SIZE] = {0};
|
// Add padding to make protocol identification harder to accomplish
|
||||||
CRYPT *c;
|
const UINT current_total_size = size + (a->Version > 1 ? UDP_ACCELERATION_PACKET_MAC_SIZE_V2 : UDP_ACCELERATION_PACKET_IV_SIZE_V1);
|
||||||
|
if (current_total_size < max_size)
|
||||||
current_size = UDP_ACCELERATION_PACKET_IV_SIZE + sizeof(UINT) + sizeof(UINT64) * 2 +
|
|
||||||
sizeof(USHORT) + sizeof(UCHAR) + data_size + UDP_ACCELERATION_PACKET_IV_SIZE;
|
|
||||||
|
|
||||||
if (current_size < max_size)
|
|
||||||
{
|
{
|
||||||
// Padding
|
|
||||||
UCHAR pad[UDP_ACCELERATION_MAX_PADDING_SIZE];
|
UCHAR pad[UDP_ACCELERATION_MAX_PADDING_SIZE];
|
||||||
UINT pad_size = MIN(max_size - current_size, UDP_ACCELERATION_MAX_PADDING_SIZE);
|
UINT pad_size = MIN(max_size - current_total_size, UDP_ACCELERATION_MAX_PADDING_SIZE);
|
||||||
pad_size = rand() % pad_size;
|
pad_size = rand() % pad_size;
|
||||||
|
|
||||||
Zero(pad, sizeof(pad));
|
Zero(pad, sizeof(pad));
|
||||||
Copy(buf, pad, pad_size);
|
Copy(buf, pad, pad_size);
|
||||||
buf += pad_size;
|
buf += pad_size;
|
||||||
size += pad_size;
|
size += pad_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify
|
if (a->Version > 1)
|
||||||
Copy(buf, zero, UDP_ACCELERATION_PACKET_IV_SIZE);
|
{
|
||||||
buf += UDP_ACCELERATION_PACKET_IV_SIZE;
|
const UINT inner_size = size - UDP_ACCELERATION_PACKET_IV_SIZE_V2;
|
||||||
size += UDP_ACCELERATION_PACKET_IV_SIZE;
|
UCHAR *inner = buffer + UDP_ACCELERATION_PACKET_IV_SIZE_V2;
|
||||||
|
|
||||||
// Encryption
|
ret = CipherProcessAead(a->CipherEncrypt, a->NextIv_V2, inner + inner_size, UDP_ACCELERATION_PACKET_MAC_SIZE_V2, inner, inner, inner_size, NULL, 0);
|
||||||
c = NewCrypt(key, UDP_ACCELERATION_PACKET_KEY_SIZE);
|
if (ret == 0)
|
||||||
Encrypt(c, tmp + UDP_ACCELERATION_PACKET_IV_SIZE, tmp + UDP_ACCELERATION_PACKET_IV_SIZE, size - UDP_ACCELERATION_PACKET_IV_SIZE);
|
{
|
||||||
FreeCrypt(c);
|
Debug("UdpAccelSend(): CipherProcessAead() failed!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Next Iv
|
Copy(a->NextIv_V2, inner, UDP_ACCELERATION_PACKET_IV_SIZE_V2);
|
||||||
Copy(a->NextIv, buf - UDP_ACCELERATION_PACKET_IV_SIZE, UDP_ACCELERATION_PACKET_IV_SIZE);
|
|
||||||
|
// Tag (appended to the buffer by CipherProcessAead())
|
||||||
|
size += UDP_ACCELERATION_PACKET_MAC_SIZE_V2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UCHAR *inner = buffer + UDP_ACCELERATION_PACKET_IV_SIZE_V1;
|
||||||
|
UCHAR key[UDP_ACCELERATION_PACKET_KEY_SIZE_V1];
|
||||||
|
const UINT inner_size = size; // We don't have to subtract because we add below
|
||||||
|
CRYPT *c;
|
||||||
|
|
||||||
|
// Simple integrity check system: we fill some bytes with zeroes.
|
||||||
|
// The remote host verifies whether all the zeroes are present.
|
||||||
|
Zero(buf, UDP_ACCELERATION_PACKET_IV_SIZE_V1);
|
||||||
|
buf += UDP_ACCELERATION_PACKET_IV_SIZE_V1;
|
||||||
|
size += UDP_ACCELERATION_PACKET_IV_SIZE_V1;
|
||||||
|
|
||||||
|
UdpAccelCalcKeyV1(key, a->MyKey, a->NextIv);
|
||||||
|
|
||||||
|
c = NewCrypt(key, UDP_ACCELERATION_PACKET_KEY_SIZE_V1);
|
||||||
|
Encrypt(c, inner, inner, inner_size);
|
||||||
|
FreeCrypt(c);
|
||||||
|
|
||||||
|
Copy(a->NextIv, buf - UDP_ACCELERATION_PACKET_IV_SIZE_V1, UDP_ACCELERATION_PACKET_IV_SIZE_V1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send
|
|
||||||
SetSockHighPriority(a->UdpSock, high_priority);
|
SetSockHighPriority(a->UdpSock, high_priority);
|
||||||
|
|
||||||
r = SendTo(a->UdpSock, &a->YourIp, a->YourPort, tmp, size);
|
ret = SendTo(a->UdpSock, &a->YourIp, a->YourPort, buffer, size);
|
||||||
if (r == 0 && a->UdpSock->IgnoreSendErr == false)
|
if (ret == 0 && a->UdpSock->IgnoreSendErr == false)
|
||||||
{
|
|
||||||
fatal_error = true;
|
|
||||||
Debug("Error: SendTo: %r %u %u\n", &a->YourIp, a->YourPort, size);
|
|
||||||
WHERE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data_size == 0)
|
|
||||||
{
|
|
||||||
if (UdpAccelIsSendReady(a, true) == false)
|
|
||||||
{
|
|
||||||
if ((a->YourPortByNatTServer != 0) && (a->YourPort != a->YourPortByNatTServer))
|
|
||||||
{
|
|
||||||
r = SendTo(a->UdpSock, &a->YourIp, a->YourPortByNatTServer, tmp, size);
|
|
||||||
if (r == 0 && a->UdpSock->IgnoreSendErr == false)
|
|
||||||
{
|
|
||||||
fatal_error = true;
|
|
||||||
WHERE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data_size == 0)
|
|
||||||
{
|
|
||||||
if (IsZeroIP(&a->YourIp2) == false && CmpIpAddr(&a->YourIp, &a->YourIp2) != 0)
|
|
||||||
{
|
|
||||||
if (UdpAccelIsSendReady(a, true) == false)
|
|
||||||
{
|
|
||||||
// When the KeepAlive, if the opponent may be behind a NAT,
|
|
||||||
// send the packet to the IP address of outside of the NAT
|
|
||||||
r = SendTo(a->UdpSock, &a->YourIp2, a->YourPort, tmp, size);
|
|
||||||
if (r == 0 && a->UdpSock->IgnoreSendErr == false)
|
|
||||||
{
|
|
||||||
fatal_error = true;
|
|
||||||
WHERE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((a->YourPortByNatTServer != 0) && (a->YourPort != a->YourPortByNatTServer))
|
|
||||||
{
|
|
||||||
r = SendTo(a->UdpSock, &a->YourIp2, a->YourPortByNatTServer, tmp, size);
|
|
||||||
if (r == 0 && a->UdpSock->IgnoreSendErr == false)
|
|
||||||
{
|
|
||||||
fatal_error = true;
|
|
||||||
WHERE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fatal_error)
|
|
||||||
{
|
{
|
||||||
a->FatalError = true;
|
a->FatalError = true;
|
||||||
WHERE;
|
Debug("UdpAccelSend(): SendTo() failed! IP: %r, port: %u, size: %u\n", &a->YourIp, a->YourPort, size);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Debug("UDP Send: %u\n", size);
|
if (data_size > 0 || UdpAccelIsSendReady(a, true))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a->YourPortByNatTServer != 0 && a->YourPortByNatTServer != a->YourPort)
|
||||||
|
{
|
||||||
|
ret = SendTo(a->UdpSock, &a->YourIp, a->YourPortByNatTServer, buffer, size);
|
||||||
|
if (ret == 0 && a->UdpSock->IgnoreSendErr == false)
|
||||||
|
{
|
||||||
|
a->FatalError = true;
|
||||||
|
Debug("UdpAccelSend(): SendTo() failed! IP: %r, port: %u, size: %u\n", &a->YourIp, a->YourPortByNatTServer, size);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (UdpAccelIsSendReady(a, true))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsZeroIP(&a->YourIp2) == false && CmpIpAddr(&a->YourIp, &a->YourIp2) != 0)
|
||||||
|
{
|
||||||
|
// We sent the packet, but the remote host didn't reply.
|
||||||
|
// It may be behind a NAT, let's try to send the packet to the alternative IP address.
|
||||||
|
ret = SendTo(a->UdpSock, &a->YourIp2, a->YourPort, buffer, size);
|
||||||
|
if (ret == 0 && a->UdpSock->IgnoreSendErr == false)
|
||||||
|
{
|
||||||
|
a->FatalError = true;
|
||||||
|
Debug("UdpAccelSend(): SendTo() failed! IP: %r, port: %u, size: %u\n", &a->YourIp2, a->YourPort, size);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a->YourPortByNatTServer != 0 && a->YourPortByNatTServer != a->YourPort)
|
||||||
|
{
|
||||||
|
ret = SendTo(a->UdpSock, &a->YourIp2, a->YourPortByNatTServer, buffer, size);
|
||||||
|
if (ret == 0 && a->UdpSock->IgnoreSendErr == false)
|
||||||
|
{
|
||||||
|
a->FatalError = true;
|
||||||
|
Debug("UdpAccelSend(): SendTo() failed! IP: %r, port: %u, size: %u\n", &a->YourIp2, a->YourPortByNatTServer, size);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine whether transmission is possible
|
// Determine whether transmission is possible
|
||||||
@ -570,15 +560,11 @@ bool UdpAccelIsSendReady(UDP_ACCEL *a, bool check_keepalive)
|
|||||||
// Process the received packet
|
// Process the received packet
|
||||||
BLOCK *UdpAccelProcessRecvPacket(UDP_ACCEL *a, UCHAR *buf, UINT size, IP *src_ip, UINT src_port)
|
BLOCK *UdpAccelProcessRecvPacket(UDP_ACCEL *a, UCHAR *buf, UINT size, IP *src_ip, UINT src_port)
|
||||||
{
|
{
|
||||||
UCHAR key[UDP_ACCELERATION_PACKET_KEY_SIZE];
|
|
||||||
UCHAR *iv;
|
|
||||||
CRYPT *c;
|
|
||||||
UINT64 my_tick, your_tick;
|
UINT64 my_tick, your_tick;
|
||||||
UINT inner_size;
|
UINT inner_size;
|
||||||
UCHAR *inner_data = NULL;
|
UCHAR *inner_data = NULL;
|
||||||
UINT pad_size;
|
|
||||||
UCHAR *verify;
|
|
||||||
bool compress_flag;
|
bool compress_flag;
|
||||||
|
UCHAR raw_flag;
|
||||||
BLOCK *b = NULL;
|
BLOCK *b = NULL;
|
||||||
UINT cookie;
|
UINT cookie;
|
||||||
// Validate arguments
|
// Validate arguments
|
||||||
@ -589,36 +575,54 @@ BLOCK *UdpAccelProcessRecvPacket(UDP_ACCEL *a, UCHAR *buf, UINT size, IP *src_ip
|
|||||||
|
|
||||||
if (a->PlainTextMode == false)
|
if (a->PlainTextMode == false)
|
||||||
{
|
{
|
||||||
// IV
|
UCHAR *iv = buf;
|
||||||
if (size < UDP_ACCELERATION_PACKET_IV_SIZE)
|
|
||||||
|
if (a->Version > 1)
|
||||||
{
|
{
|
||||||
return NULL;
|
UINT data_size;
|
||||||
|
|
||||||
|
if (size < UDP_ACCELERATION_PACKET_IV_SIZE_V2)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf += UDP_ACCELERATION_PACKET_IV_SIZE_V2;
|
||||||
|
size -= UDP_ACCELERATION_PACKET_IV_SIZE_V2;
|
||||||
|
|
||||||
|
if (size < UDP_ACCELERATION_PACKET_MAC_SIZE_V2)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
data_size = size - UDP_ACCELERATION_PACKET_MAC_SIZE_V2;
|
||||||
|
|
||||||
|
if (CipherProcessAead(a->CipherDecrypt, iv, buf + data_size, UDP_ACCELERATION_PACKET_MAC_SIZE_V2, buf, buf, data_size, NULL, 0) == 0)
|
||||||
|
{
|
||||||
|
Debug("UdpAccelProcessRecvPacket(): CipherProcessAead() failed!\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
size -= UDP_ACCELERATION_PACKET_MAC_SIZE_V2;
|
||||||
}
|
}
|
||||||
iv = buf;
|
else
|
||||||
buf += UDP_ACCELERATION_PACKET_IV_SIZE;
|
|
||||||
size -= UDP_ACCELERATION_PACKET_IV_SIZE;
|
|
||||||
|
|
||||||
// Calculate the key
|
|
||||||
UdpAccelCalcKey(key, a->YourKey, iv);
|
|
||||||
|
|
||||||
if (false)
|
|
||||||
{
|
{
|
||||||
char tmp1[256];
|
UCHAR key[UDP_ACCELERATION_PACKET_KEY_SIZE_V1];
|
||||||
char tmp2[256];
|
CRYPT *c;
|
||||||
char tmp3[256];
|
|
||||||
BinToStr(tmp1, sizeof(tmp1), a->YourKey, sizeof(a->YourKey));
|
|
||||||
BinToStr(tmp2, sizeof(tmp2), iv, UDP_ACCELERATION_PACKET_IV_SIZE);
|
|
||||||
BinToStr(tmp3, sizeof(tmp3), key, sizeof(key));
|
|
||||||
Debug("Your Key: %s\n"
|
|
||||||
"IV : %s\n"
|
|
||||||
"Comm Key: %s\n",
|
|
||||||
tmp1, tmp2, tmp3);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decryption
|
if (size < UDP_ACCELERATION_PACKET_IV_SIZE_V1)
|
||||||
c = NewCrypt(key, UDP_ACCELERATION_PACKET_KEY_SIZE);
|
{
|
||||||
Encrypt(c, buf, buf, size);
|
return NULL;
|
||||||
FreeCrypt(c);
|
}
|
||||||
|
|
||||||
|
buf += UDP_ACCELERATION_PACKET_IV_SIZE_V1;
|
||||||
|
size -= UDP_ACCELERATION_PACKET_IV_SIZE_V1;
|
||||||
|
|
||||||
|
UdpAccelCalcKeyV1(key, a->YourKey, iv);
|
||||||
|
|
||||||
|
c = NewCrypt(key, UDP_ACCELERATION_PACKET_KEY_SIZE_V1);
|
||||||
|
Encrypt(c, buf, buf, size);
|
||||||
|
FreeCrypt(c);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cookie
|
// Cookie
|
||||||
@ -635,7 +639,7 @@ BLOCK *UdpAccelProcessRecvPacket(UDP_ACCEL *a, UCHAR *buf, UINT size, IP *src_ip
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// My Tick
|
// My tick
|
||||||
if (size < sizeof(UINT64))
|
if (size < sizeof(UINT64))
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -644,7 +648,7 @@ BLOCK *UdpAccelProcessRecvPacket(UDP_ACCEL *a, UCHAR *buf, UINT size, IP *src_ip
|
|||||||
buf += sizeof(UINT64);
|
buf += sizeof(UINT64);
|
||||||
size -= sizeof(UINT64);
|
size -= sizeof(UINT64);
|
||||||
|
|
||||||
// Your Tick
|
// Your tick
|
||||||
if (size < sizeof(UINT64))
|
if (size < sizeof(UINT64))
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -653,7 +657,7 @@ BLOCK *UdpAccelProcessRecvPacket(UDP_ACCEL *a, UCHAR *buf, UINT size, IP *src_ip
|
|||||||
buf += sizeof(UINT64);
|
buf += sizeof(UINT64);
|
||||||
size -= sizeof(UINT64);
|
size -= sizeof(UINT64);
|
||||||
|
|
||||||
// inner_size
|
// Inner data size
|
||||||
if (size < sizeof(USHORT))
|
if (size < sizeof(USHORT))
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -662,12 +666,20 @@ BLOCK *UdpAccelProcessRecvPacket(UDP_ACCEL *a, UCHAR *buf, UINT size, IP *src_ip
|
|||||||
buf += sizeof(USHORT);
|
buf += sizeof(USHORT);
|
||||||
size -= sizeof(USHORT);
|
size -= sizeof(USHORT);
|
||||||
|
|
||||||
// compress_flag
|
// Flag
|
||||||
if (size < sizeof(UCHAR))
|
if (size < sizeof(UCHAR))
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
compress_flag = *((UCHAR *)buf);
|
if (a->ReadRawFlagMode == false)
|
||||||
|
{
|
||||||
|
compress_flag = *((UCHAR *)buf);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
raw_flag = *((UCHAR *)buf);
|
||||||
|
}
|
||||||
|
|
||||||
buf += sizeof(UCHAR);
|
buf += sizeof(UCHAR);
|
||||||
size -= sizeof(UCHAR);
|
size -= sizeof(UCHAR);
|
||||||
|
|
||||||
@ -676,7 +688,7 @@ BLOCK *UdpAccelProcessRecvPacket(UDP_ACCEL *a, UCHAR *buf, UINT size, IP *src_ip
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// inner_data
|
// Inner_data
|
||||||
if (inner_size >= 1)
|
if (inner_size >= 1)
|
||||||
{
|
{
|
||||||
inner_data = buf;
|
inner_data = buf;
|
||||||
@ -686,26 +698,29 @@ BLOCK *UdpAccelProcessRecvPacket(UDP_ACCEL *a, UCHAR *buf, UINT size, IP *src_ip
|
|||||||
|
|
||||||
if (a->PlainTextMode == false)
|
if (a->PlainTextMode == false)
|
||||||
{
|
{
|
||||||
// padding
|
// Verify packet integrity
|
||||||
if (size < UDP_ACCELERATION_PACKET_IV_SIZE)
|
if (a->Version == 1)
|
||||||
{
|
{
|
||||||
return false;
|
UINT pad_size;
|
||||||
}
|
|
||||||
pad_size = size - UDP_ACCELERATION_PACKET_IV_SIZE;
|
|
||||||
buf += pad_size;
|
|
||||||
size -= pad_size;
|
|
||||||
|
|
||||||
// verify
|
if (size < UDP_ACCELERATION_PACKET_IV_SIZE_V1)
|
||||||
if (size != UDP_ACCELERATION_PACKET_IV_SIZE)
|
{
|
||||||
{
|
return false;
|
||||||
return NULL;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
verify = buf;
|
pad_size = size - UDP_ACCELERATION_PACKET_IV_SIZE_V1;
|
||||||
|
buf += pad_size;
|
||||||
|
size -= pad_size;
|
||||||
|
|
||||||
if (IsZero(verify, UDP_ACCELERATION_PACKET_IV_SIZE) == false)
|
if (size != UDP_ACCELERATION_PACKET_IV_SIZE_V1)
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsZero(buf, UDP_ACCELERATION_PACKET_IV_SIZE_V1) == false)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -722,7 +737,11 @@ BLOCK *UdpAccelProcessRecvPacket(UDP_ACCEL *a, UCHAR *buf, UINT size, IP *src_ip
|
|||||||
|
|
||||||
if (inner_size >= 1)
|
if (inner_size >= 1)
|
||||||
{
|
{
|
||||||
b = NewBlock(Clone(inner_data, inner_size), inner_size, compress_flag ? -1 : 0);
|
b = NewBlock(Clone(inner_data, inner_size), inner_size, a->ReadRawFlagMode == false ? (compress_flag ? -1 : 0) : 0);
|
||||||
|
if (a->ReadRawFlagMode)
|
||||||
|
{
|
||||||
|
b->RawFlagRetUdpAccel = raw_flag;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (a->LastSetSrcIpAndPortTick < a->LastRecvYourTick)
|
if (a->LastSetSrcIpAndPortTick < a->LastRecvYourTick)
|
||||||
@ -751,18 +770,18 @@ BLOCK *UdpAccelProcessRecvPacket(UDP_ACCEL *a, UCHAR *buf, UINT size, IP *src_ip
|
|||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate the key
|
// Calculate V1 key
|
||||||
void UdpAccelCalcKey(UCHAR *key, UCHAR *common_key, UCHAR *iv)
|
void UdpAccelCalcKeyV1(UCHAR *key, UCHAR *common_key, UCHAR *iv)
|
||||||
{
|
{
|
||||||
UCHAR tmp[UDP_ACCELERATION_COMMON_KEY_SIZE + UDP_ACCELERATION_PACKET_IV_SIZE];
|
UCHAR tmp[UDP_ACCELERATION_COMMON_KEY_SIZE_V1 + UDP_ACCELERATION_PACKET_IV_SIZE_V1];
|
||||||
// Validate arguments
|
// Validate arguments
|
||||||
if (key == NULL || common_key == NULL || iv == NULL)
|
if (key == NULL || common_key == NULL || iv == NULL)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Copy(tmp, common_key, UDP_ACCELERATION_COMMON_KEY_SIZE);
|
Copy(tmp, common_key, UDP_ACCELERATION_COMMON_KEY_SIZE_V1);
|
||||||
Copy(tmp + UDP_ACCELERATION_COMMON_KEY_SIZE, iv, UDP_ACCELERATION_PACKET_IV_SIZE);
|
Copy(tmp + UDP_ACCELERATION_COMMON_KEY_SIZE_V1, iv, UDP_ACCELERATION_PACKET_IV_SIZE_V1);
|
||||||
|
|
||||||
Sha1(key, tmp, sizeof(tmp));
|
Sha1(key, tmp, sizeof(tmp));
|
||||||
}
|
}
|
||||||
@ -790,15 +809,25 @@ bool UdpAccelInitServer(UDP_ACCEL *a, UCHAR *client_key, IP *client_ip, UINT cli
|
|||||||
}
|
}
|
||||||
|
|
||||||
IPToStr(tmp, sizeof(tmp), client_ip);
|
IPToStr(tmp, sizeof(tmp), client_ip);
|
||||||
Debug("UdpAccelInitServer: client_ip=%s, client_port=%u, server_cookie=%u, client_cookie=%u\n", tmp, client_port,
|
Debug("UdpAccelInitServer(): version: %u, client IP: %s, client port: %u, server cookie: %u, client cookie: %u\n", a->Version, tmp, client_port, a->MyCookie, a->YourCookie);
|
||||||
a->MyCookie, a->YourCookie);
|
|
||||||
|
|
||||||
if (IsIP6(client_ip) != a->IsIPv6)
|
if (IsIP6(client_ip) != a->IsIPv6)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Copy(a->YourKey, client_key, UDP_ACCELERATION_COMMON_KEY_SIZE);
|
if (a->Version > 1)
|
||||||
|
{
|
||||||
|
a->CipherEncrypt = NewCipher("ChaCha20-Poly1305");
|
||||||
|
a->CipherDecrypt = NewCipher("ChaCha20-Poly1305");
|
||||||
|
|
||||||
|
SetCipherKey(a->CipherEncrypt, a->MyKey_V2, true);
|
||||||
|
SetCipherKey(a->CipherDecrypt, client_key, false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Copy(a->YourKey, client_key, sizeof(a->YourKey));
|
||||||
|
}
|
||||||
|
|
||||||
Copy(&a->YourIp, client_ip, sizeof(IP));
|
Copy(&a->YourIp, client_ip, sizeof(IP));
|
||||||
Copy(&a->YourIp2, client_ip_2, sizeof(IP));
|
Copy(&a->YourIp2, client_ip_2, sizeof(IP));
|
||||||
@ -822,14 +851,25 @@ bool UdpAccelInitClient(UDP_ACCEL *a, UCHAR *server_key, IP *server_ip, UINT ser
|
|||||||
}
|
}
|
||||||
|
|
||||||
IPToStr(tmp, sizeof(tmp), server_ip);
|
IPToStr(tmp, sizeof(tmp), server_ip);
|
||||||
Debug("UdpAccelInitClient: server_ip=%s, server_port=%u, server_cookie=%u, client_cookie=%u\n", tmp, server_port, server_cookie, client_cookie);
|
Debug("UdpAccelInitClient(): version: %u, client IP: %s, client port: %u, server cookie: %u, client cookie: %u\n", a->Version, tmp, server_port, server_cookie, client_cookie);
|
||||||
|
|
||||||
if (IsIP6(server_ip) != a->IsIPv6)
|
if (IsIP6(server_ip) != a->IsIPv6)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Copy(a->YourKey, server_key, UDP_ACCELERATION_COMMON_KEY_SIZE);
|
if (a->Version > 1)
|
||||||
|
{
|
||||||
|
a->CipherEncrypt = NewCipher("ChaCha20-Poly1305");
|
||||||
|
a->CipherDecrypt = NewCipher("ChaCha20-Poly1305");
|
||||||
|
|
||||||
|
SetCipherKey(a->CipherEncrypt, a->MyKey_V2, true);
|
||||||
|
SetCipherKey(a->CipherDecrypt, server_key, false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Copy(a->YourKey, server_key, sizeof(a->YourKey));
|
||||||
|
}
|
||||||
|
|
||||||
Copy(&a->YourIp, server_ip, sizeof(IP));
|
Copy(&a->YourIp, server_ip, sizeof(IP));
|
||||||
Copy(&a->YourIp2, server_ip_2, sizeof(IP));
|
Copy(&a->YourIp2, server_ip_2, sizeof(IP));
|
||||||
@ -911,6 +951,7 @@ UDP_ACCEL *NewUdpAccel(CEDAR *cedar, IP *ip, bool client_mode, bool random_port,
|
|||||||
|
|
||||||
a->NoNatT = no_nat_t;
|
a->NoNatT = no_nat_t;
|
||||||
|
|
||||||
|
a->Version = 1;
|
||||||
|
|
||||||
a->NatT_TranId = Rand64();
|
a->NatT_TranId = Rand64();
|
||||||
|
|
||||||
@ -922,8 +963,9 @@ UDP_ACCEL *NewUdpAccel(CEDAR *cedar, IP *ip, bool client_mode, bool random_port,
|
|||||||
|
|
||||||
a->Now = Tick64();
|
a->Now = Tick64();
|
||||||
a->UdpSock = s;
|
a->UdpSock = s;
|
||||||
|
|
||||||
Rand(a->MyKey, sizeof(a->MyKey));
|
Rand(a->MyKey, sizeof(a->MyKey));
|
||||||
Rand(a->YourKey, sizeof(a->YourKey));
|
Rand(a->MyKey_V2, sizeof(a->MyKey_V2));
|
||||||
|
|
||||||
Copy(&a->MyIp, ip, sizeof(IP));
|
Copy(&a->MyIp, ip, sizeof(IP));
|
||||||
a->MyPort = s->LocalPort;
|
a->MyPort = s->LocalPort;
|
||||||
@ -938,6 +980,7 @@ UDP_ACCEL *NewUdpAccel(CEDAR *cedar, IP *ip, bool client_mode, bool random_port,
|
|||||||
a->RecvBlockQueue = NewQueue();
|
a->RecvBlockQueue = NewQueue();
|
||||||
|
|
||||||
Rand(a->NextIv, sizeof(a->NextIv));
|
Rand(a->NextIv, sizeof(a->NextIv));
|
||||||
|
Rand(a->NextIv_V2, sizeof(a->NextIv_V2));
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
@ -1091,6 +1134,8 @@ void FreeUdpAccel(UDP_ACCEL *a)
|
|||||||
|
|
||||||
ReleaseCedar(a->Cedar);
|
ReleaseCedar(a->Cedar);
|
||||||
|
|
||||||
|
FreeCipher(a->CipherEncrypt);
|
||||||
|
FreeCipher(a->CipherDecrypt);
|
||||||
|
|
||||||
Free(a);
|
Free(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,9 +9,14 @@
|
|||||||
#define UDPACCEL_H
|
#define UDPACCEL_H
|
||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
#define UDP_ACCELERATION_COMMON_KEY_SIZE 20 // Common key size
|
#define UDP_ACCELERATION_COMMON_KEY_SIZE_V1 20 // V1: Common key size
|
||||||
#define UDP_ACCELERATION_PACKET_KEY_SIZE 20 // Key size for the packet
|
#define UDP_ACCELERATION_PACKET_KEY_SIZE_V1 20 // V1: Key size for the packet
|
||||||
#define UDP_ACCELERATION_PACKET_IV_SIZE 20 // IV size for the packet
|
#define UDP_ACCELERATION_PACKET_IV_SIZE_V1 20 // V1: IV size for the packet
|
||||||
|
|
||||||
|
#define UDP_ACCELERATION_COMMON_KEY_SIZE_V2 128 // V2: Common key size
|
||||||
|
#define UDP_ACCELERATION_PACKET_IV_SIZE_V2 12 // V2: IV size for the packet
|
||||||
|
#define UDP_ACCELERATION_PACKET_MAC_SIZE_V2 16 // V2: MAC size for the packet
|
||||||
|
|
||||||
#define UDP_ACCELERATION_TMP_BUF_SIZE 2048 // Temporary buffer size
|
#define UDP_ACCELERATION_TMP_BUF_SIZE 2048 // Temporary buffer size
|
||||||
#define UDP_ACCELERATION_WINDOW_SIZE_MSEC (30 * 1000) // Receive window size (in milliseconds)
|
#define UDP_ACCELERATION_WINDOW_SIZE_MSEC (30 * 1000) // Receive window size (in milliseconds)
|
||||||
|
|
||||||
@ -45,8 +50,10 @@ struct UDP_ACCEL
|
|||||||
bool ClientMode; // Whether client mode
|
bool ClientMode; // Whether client mode
|
||||||
bool IsInCedarPortList; // Whether included in the port list of the Cedar
|
bool IsInCedarPortList; // Whether included in the port list of the Cedar
|
||||||
UINT64 Now; // Current time
|
UINT64 Now; // Current time
|
||||||
UCHAR MyKey[UDP_ACCELERATION_COMMON_KEY_SIZE]; // Submit-direction common key
|
CIPHER *CipherEncrypt; // Encryption context
|
||||||
UCHAR YourKey[UDP_ACCELERATION_COMMON_KEY_SIZE]; // Receiving-direction common key
|
CIPHER *CipherDecrypt; // Decryption context
|
||||||
|
UCHAR MyKey[UDP_ACCELERATION_COMMON_KEY_SIZE_V1]; // Send-direction common key
|
||||||
|
UCHAR YourKey[UDP_ACCELERATION_COMMON_KEY_SIZE_V1]; // Receive-direction common key
|
||||||
SOCK *UdpSock; // UDP socket
|
SOCK *UdpSock; // UDP socket
|
||||||
UINT MyPort; // My port number
|
UINT MyPort; // My port number
|
||||||
UINT YourPort; // Port number of the other party
|
UINT YourPort; // Port number of the other party
|
||||||
@ -63,7 +70,7 @@ struct UDP_ACCEL
|
|||||||
UINT64 LastSetSrcIpAndPortTick; // Opponent's tick ??value at the time of storing the IP address and port number of the opponent at the end
|
UINT64 LastSetSrcIpAndPortTick; // Opponent's tick ??value at the time of storing the IP address and port number of the opponent at the end
|
||||||
UINT64 LastRecvTick; // Tick when data has received at the end
|
UINT64 LastRecvTick; // Tick when data has received at the end
|
||||||
UINT64 NextSendKeepAlive; // Next time to send a KeepAlive packet
|
UINT64 NextSendKeepAlive; // Next time to send a KeepAlive packet
|
||||||
UCHAR NextIv[UDP_ACCELERATION_PACKET_IV_SIZE]; // IV to be used next
|
UCHAR NextIv[UDP_ACCELERATION_PACKET_IV_SIZE_V1]; // IV to be used next
|
||||||
UINT MyCookie; // My cookie
|
UINT MyCookie; // My cookie
|
||||||
UINT YourCookie; // Cookie of the other party
|
UINT YourCookie; // Cookie of the other party
|
||||||
bool Inited; // Initialized flag
|
bool Inited; // Initialized flag
|
||||||
@ -94,6 +101,10 @@ struct UDP_ACCEL
|
|||||||
UCHAR UdpIpQueryPacketData[16]; // Query packet data (final transmission)
|
UCHAR UdpIpQueryPacketData[16]; // Query packet data (final transmission)
|
||||||
UINT UdpIpQueryPacketSize; // Query packet data size (final transmission)
|
UINT UdpIpQueryPacketSize; // Query packet data size (final transmission)
|
||||||
UCHAR UdpHostUniqueKey[SHA1_SIZE]; // Unique key for UDP self endpoint query
|
UCHAR UdpHostUniqueKey[SHA1_SIZE]; // Unique key for UDP self endpoint query
|
||||||
|
UINT Version; // Version
|
||||||
|
UCHAR MyKey_V2[UDP_ACCELERATION_COMMON_KEY_SIZE_V2]; // Send-direction common key (version 2)
|
||||||
|
UCHAR NextIv_V2[UDP_ACCELERATION_PACKET_IV_SIZE_V2]; // IV to be used next (version 2)
|
||||||
|
bool ReadRawFlagMode; // Read raw flag mode
|
||||||
};
|
};
|
||||||
|
|
||||||
// Function prototype
|
// Function prototype
|
||||||
@ -104,9 +115,9 @@ bool UdpAccelInitServer(UDP_ACCEL *a, UCHAR *client_key, IP *client_ip, UINT cli
|
|||||||
void UdpAccelPoll(UDP_ACCEL *a);
|
void UdpAccelPoll(UDP_ACCEL *a);
|
||||||
void UdpAccelSetTick(UDP_ACCEL *a, UINT64 tick64);
|
void UdpAccelSetTick(UDP_ACCEL *a, UINT64 tick64);
|
||||||
BLOCK *UdpAccelProcessRecvPacket(UDP_ACCEL *a, UCHAR *buf, UINT size, IP *src_ip, UINT src_port);
|
BLOCK *UdpAccelProcessRecvPacket(UDP_ACCEL *a, UCHAR *buf, UINT size, IP *src_ip, UINT src_port);
|
||||||
void UdpAccelCalcKey(UCHAR *key, UCHAR *common_key, UCHAR *iv);
|
void UdpAccelCalcKeyV1(UCHAR *key, UCHAR *common_key, UCHAR *iv);
|
||||||
bool UdpAccelIsSendReady(UDP_ACCEL *a, bool check_keepalive);
|
bool UdpAccelIsSendReady(UDP_ACCEL *a, bool check_keepalive);
|
||||||
void UdpAccelSend(UDP_ACCEL *a, UCHAR *data, UINT data_size, bool compressed, UINT max_size, bool high_priority);
|
void UdpAccelSend(UDP_ACCEL *a, UCHAR *data, UINT data_size, UCHAR flag, UINT max_size, bool high_priority);
|
||||||
void UdpAccelSendBlock(UDP_ACCEL *a, BLOCK *b);
|
void UdpAccelSendBlock(UDP_ACCEL *a, BLOCK *b);
|
||||||
UINT UdpAccelCalcMss(UDP_ACCEL *a);
|
UINT UdpAccelCalcMss(UDP_ACCEL *a);
|
||||||
void NatT_GetIpThread(THREAD *thread, void *param);
|
void NatT_GetIpThread(THREAD *thread, void *param);
|
||||||
|
Loading…
Reference in New Issue
Block a user