1
0
mirror of https://github.com/SoftEtherVPN/SoftEtherVPN.git synced 2024-11-26 19:39:53 +03:00

Mayaqua: implement R-UDP version 2, powered by ChaCha20-Poly1305

This commit is contained in:
Davide Beatrici 2019-11-23 04:38:20 +01:00
parent 2ea5c2a7b0
commit 6b08a451da
2 changed files with 257 additions and 118 deletions

View File

@ -2397,21 +2397,64 @@ void RUDPInterruptProc(RUDP_STACK *r)
void RUDPBulkSend(RUDP_STACK *r, RUDP_SESSION *se, void *data, UINT data_size) void RUDPBulkSend(RUDP_STACK *r, RUDP_SESSION *se, void *data, UINT data_size)
{ {
UCHAR *buf; UCHAR *buf;
UINT buf_size; UINT i, icmp_type, buf_size, padding_size;
UINT padding_size;
UINT i;
CRYPT *c;
UCHAR crypt_key_src[SHA1_SIZE * 2];
UCHAR crypt_key[SHA1_SIZE];
UINT icmp_type = 0;
UCHAR sign[SHA1_SIZE];
UCHAR iv[SHA1_SIZE + 1];
// Validate arguments // Validate arguments
if (r == NULL || se == NULL || (data == NULL && data_size != 0)) if (r == NULL || se == NULL || (data == NULL && data_size != 0))
{ {
return; return;
} }
if (se->BulkSendKey->Size == RUDP_BULK_KEY_SIZE_V2)
{
UCHAR *tmp, iv[RUDP_BULK_IV_SIZE_V2];
UINT size;
CIPHER *c;
padding_size = Rand32() % 31 + 1;
size = sizeof(UINT64) + data_size + padding_size;
// Packet: IV + Encrypted(SEQ_NO + Data + padding) + MAC
buf_size = RUDP_BULK_IV_SIZE_V2 + sizeof(UINT64) + data_size + padding_size + RUDP_BULK_MAC_SIZE_V2;
buf = Malloc(buf_size);
// IV
Copy(iv, se->BulkNextIv_V2, RUDP_BULK_IV_SIZE_V2);
Copy(buf, iv, RUDP_BULK_IV_SIZE_V2);
// SEQ NO
WRITE_UINT64(buf + RUDP_BULK_IV_SIZE_V2, se->BulkNextSeqNo);
se->BulkNextSeqNo++;
// Data
Copy(buf + RUDP_BULK_IV_SIZE_V2 + sizeof(UINT64), data, data_size);
// Padding
for (i = 0;i < padding_size;i++)
{
buf[RUDP_BULK_IV_SIZE_V2 + sizeof(UINT64) + data_size + i] = (UCHAR)padding_size;
}
size = sizeof(UINT64) + data_size + padding_size;
tmp = buf + RUDP_BULK_IV_SIZE_V2;
// Encryption
c = NewCipher("ChaCha20-Poly1305");
SetCipherKey(c, se->BulkSendKey->Data, true);
CipherProcessAead(c, iv, tmp + size, RUDP_BULK_MAC_SIZE_V2, tmp, tmp, size - RUDP_BULK_MAC_SIZE_V2, NULL, 0);
FreeCipher(c);
// Next IV
Copy(se->BulkNextIv_V2, buf + sizeof(UINT64) + data_size + padding_size, RUDP_BULK_IV_SIZE_V2);
}
else
{
UCHAR crypt_key_src[SHA1_SIZE * 2];
UCHAR crypt_key[SHA1_SIZE];
UCHAR sign[SHA1_SIZE];
UCHAR iv[SHA1_SIZE];
CRYPT *c;
padding_size = Rand32() % 31 + 1; padding_size = Rand32() % 31 + 1;
buf_size = SHA1_SIZE + SHA1_SIZE + sizeof(UINT64) + data_size + padding_size; buf_size = SHA1_SIZE + SHA1_SIZE + sizeof(UINT64) + data_size + padding_size;
@ -2456,6 +2499,7 @@ void RUDPBulkSend(RUDP_STACK *r, RUDP_SESSION *se, void *data, UINT data_size)
// Next IV // Next IV
Copy(se->BulkNextIv, buf + buf_size - SHA1_SIZE, SHA1_SIZE); Copy(se->BulkNextIv, buf + buf_size - SHA1_SIZE, SHA1_SIZE);
}
if (r->Protocol == RUDP_PROTOCOL_ICMP) if (r->Protocol == RUDP_PROTOCOL_ICMP)
{ {
@ -2465,6 +2509,7 @@ void RUDPBulkSend(RUDP_STACK *r, RUDP_SESSION *se, void *data, UINT data_size)
{ {
icmp_type = se->Dns_TranId; icmp_type = se->Dns_TranId;
} }
RUDPSendPacket(r, &se->YourIp, se->YourPort, buf, buf_size, icmp_type); RUDPSendPacket(r, &se->YourIp, se->YourPort, buf, buf_size, icmp_type);
Free(buf); Free(buf);
@ -2591,6 +2636,41 @@ bool RUDPCheckSignOfRecvPacket(RUDP_STACK *r, RUDP_SESSION *se, void *recv_data,
} }
// Verification signature (bulk packet) // Verification signature (bulk packet)
if (se->BulkRecvKey->Size == RUDP_BULK_KEY_SIZE_V2)
{
UCHAR *iv = p;
CIPHER *c;
// Packet: IV + Encrypted(SEQ_NO + Data + padding) + MAC
// IV
if (size < RUDP_BULK_IV_SIZE_V2)
{
return false;
}
iv = p;
p += RUDP_BULK_IV_SIZE_V2;
size -= RUDP_BULK_IV_SIZE_V2;
// Decrypt
if (size < (RUDP_BULK_MAC_SIZE_V2 + 1))
{
return false;
}
c = NewCipher("ChaCha20-Poly1305");
SetCipherKey(c, se->BulkRecvKey->Data, false);
size = CipherProcessAead(c, iv, p + size, RUDP_BULK_MAC_SIZE_V2, r->TmpBuf, p, size - RUDP_BULK_MAC_SIZE_V2, NULL, 0);
FreeCipher(c);
if (size == 0)
{
return false;
}
return true;
}
else
{
if (se->UseHMac == false) if (se->UseHMac == false)
{ {
Copy(sign, p, SHA1_SIZE); Copy(sign, p, SHA1_SIZE);
@ -2610,6 +2690,7 @@ bool RUDPCheckSignOfRecvPacket(RUDP_STACK *r, RUDP_SESSION *se, void *recv_data,
se->UseHMac = true; se->UseHMac = true;
return true; return true;
} }
}
return false; return false;
} }
@ -2617,14 +2698,9 @@ bool RUDPCheckSignOfRecvPacket(RUDP_STACK *r, RUDP_SESSION *se, void *recv_data,
// Process the received packet (bulk) // Process the received packet (bulk)
bool RUDPProcessBulkRecvPacket(RUDP_STACK *r, RUDP_SESSION *se, void *recv_data, UINT recv_size) bool RUDPProcessBulkRecvPacket(RUDP_STACK *r, RUDP_SESSION *se, void *recv_data, UINT recv_size)
{ {
UCHAR sign[SHA1_SIZE];
UCHAR sign2[SHA1_SIZE];
UCHAR *p; UCHAR *p;
UCHAR *iv; UCHAR *iv;
UINT size; UINT size;
UCHAR keygen[SHA1_SIZE * 2];
UCHAR key[SHA1_SIZE];
CRYPT *c;
UCHAR padlen; UCHAR padlen;
UINT64 seq_no; UINT64 seq_no;
UCHAR *payload; UCHAR *payload;
@ -2642,6 +2718,62 @@ bool RUDPProcessBulkRecvPacket(RUDP_STACK *r, RUDP_SESSION *se, void *recv_data,
return false; return false;
} }
if (se->BulkRecvKey->Size == RUDP_BULK_KEY_SIZE_V2)
{
UINT ret;
CIPHER *c;
// Packet: IV + Encrypted(SEQ_NO + Data + padding) + MAC
// IV
if (size < RUDP_BULK_IV_SIZE_V2)
{
WHERE;
return false;
}
iv = p;
p += RUDP_BULK_IV_SIZE_V2;
size -= RUDP_BULK_IV_SIZE_V2;
// Decrypt
if (size < (RUDP_BULK_MAC_SIZE_V2 + 1))
{
WHERE;
return false;
}
c = NewCipher("ChaCha20-Poly1305");
SetCipherKey(c, se->BulkRecvKey->Data, false);
ret = CipherProcessAead(c, iv, p + size, RUDP_BULK_MAC_SIZE_V2, p, p, size - RUDP_BULK_MAC_SIZE_V2, NULL, 0);
FreeCipher(c);
if (ret == 0)
{
WHERE;
return false;
}
size -= RUDP_BULK_MAC_SIZE_V2;
// padlen
padlen = p[size - 1];
if (padlen == 0)
{
WHERE;
return false;
}
if (size < padlen)
{
WHERE;
return false;
}
size -= padlen;
}
else
{
CRYPT *c;
UCHAR sign[SHA1_SIZE], sign2[SHA1_SIZE];
UCHAR key[SHA1_SIZE], keygen[SHA1_SIZE * 2];
// Validate the signature // Validate the signature
if (se->UseHMac == false) if (se->UseHMac == false)
{ {
@ -2663,9 +2795,6 @@ bool RUDPProcessBulkRecvPacket(RUDP_STACK *r, RUDP_SESSION *se, void *recv_data,
se->UseHMac = true; se->UseHMac = true;
} }
} }
else
{
}
} }
else else
{ {
@ -2713,6 +2842,7 @@ bool RUDPProcessBulkRecvPacket(RUDP_STACK *r, RUDP_SESSION *se, void *recv_data,
return false; return false;
} }
size -= padlen; size -= padlen;
}
// SEQ NO // SEQ NO
seq_no = READ_UINT64(p); seq_no = READ_UINT64(p);
@ -3525,8 +3655,8 @@ RUDP_SESSION *RUDPNewSession(bool server_mode, IP *my_ip, UINT my_port, IP *your
RUDP_SESSION *se; RUDP_SESSION *se;
UCHAR key1[SHA1_SIZE]; UCHAR key1[SHA1_SIZE];
UCHAR key2[SHA1_SIZE]; UCHAR key2[SHA1_SIZE];
UCHAR bulk_send_key[SHA1_SIZE]; UCHAR bulk_send_key[RUDP_BULK_KEY_SIZE_MAX];
UCHAR bulk_recv_key[SHA1_SIZE]; UCHAR bulk_recv_key[RUDP_BULK_KEY_SIZE_MAX];
BUF *b; BUF *b;
se = ZeroMalloc(sizeof(RUDP_SESSION)); se = ZeroMalloc(sizeof(RUDP_SESSION));
@ -3612,6 +3742,8 @@ RUDP_SESSION *RUDPNewSession(bool server_mode, IP *my_ip, UINT my_port, IP *your
se->BulkRecvKey = NewSharedBuffer(bulk_recv_key, sizeof(bulk_recv_key)); se->BulkRecvKey = NewSharedBuffer(bulk_recv_key, sizeof(bulk_recv_key));
Rand(se->BulkNextIv, sizeof(se->BulkNextIv)); Rand(se->BulkNextIv, sizeof(se->BulkNextIv));
Rand(se->BulkNextIv_V2, sizeof(se->BulkNextIv_V2));
se->BulkNextSeqNo = 1; se->BulkNextSeqNo = 1;
return se; return se;

View File

@ -576,6 +576,12 @@ struct IPBLOCK
#define RUDP_TIMEOUT 12000 // Time-out of R-UDP communication #define RUDP_TIMEOUT 12000 // Time-out of R-UDP communication
#define RUDP_DIRECT_CONNECT_TIMEOUT 5000 // R-UDP direct connection time-out #define RUDP_DIRECT_CONNECT_TIMEOUT 5000 // R-UDP direct connection time-out
#define RUDP_MAX_SEGMENT_SIZE 512 // Maximum segment size #define RUDP_MAX_SEGMENT_SIZE 512 // Maximum segment size
#define RUDP_BULK_KEY_SIZE_MAX 128 // Bulk key size Max
#define RUDP_BULK_KEY_SIZE_V2 32 // V2: Bulk key size
#define RUDP_BULK_IV_SIZE_V2 12 // V2: Bulk IV size
#define RUDP_BULK_MAC_SIZE_V2 16 // V2: Bulk MAC size
// Maximum R-UDP packet size // Maximum R-UDP packet size
#define RUDP_MAX_PACKET_SIZE (RUDP_MAX_SEGMENT_SIZE + sizeof(UINT64) * RUDP_MAX_NUM_ACK + SHA1_SIZE * 2 + sizeof(UINT64) * 4 + sizeof(UINT) + 255) #define RUDP_MAX_PACKET_SIZE (RUDP_MAX_SEGMENT_SIZE + sizeof(UINT64) * RUDP_MAX_NUM_ACK + SHA1_SIZE * 2 + sizeof(UINT64) * 4 + sizeof(UINT) + 255)
#define RUDP_MAX_NUM_ACK 64 // Maximum number of ACKs #define RUDP_MAX_NUM_ACK 64 // Maximum number of ACKs
@ -664,6 +670,7 @@ struct RUDP_SESSION
UINT64 BulkNextSeqNo; // Next SEQ NO to the bulk send UINT64 BulkNextSeqNo; // Next SEQ NO to the bulk send
bool FlushBulkSendTube; // Flag to be Flush the bulk send Tube bool FlushBulkSendTube; // Flag to be Flush the bulk send Tube
UINT64 BulkRecvSeqNoMax; // Highest sequence number received UINT64 BulkRecvSeqNoMax; // Highest sequence number received
UCHAR BulkNextIv_V2[RUDP_BULK_IV_SIZE_V2]; // Next IV to the bulk send (version 2)
}; };
// NAT Traversal Server Information // NAT Traversal Server Information