mirror of
https://github.com/bol-van/zapret.git
synced 2024-11-30 05:50:53 +03:00
nfqws: verify quic auth tag. improve initial packet detection
This commit is contained in:
parent
3753349058
commit
2eec88c2bf
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,38 +1,13 @@
|
|||||||
#include "aes-gcm.h"
|
#include "aes-gcm.h"
|
||||||
|
|
||||||
int aes_gcm_encrypt(unsigned char* output, const unsigned char* input, size_t input_length, const unsigned char* key, const size_t key_len, const unsigned char * iv, const size_t iv_len) {
|
int aes_gcm_crypt(int mode, uint8_t *output, const uint8_t *input, size_t input_length, const uint8_t *key, const size_t key_len, const uint8_t *iv, const size_t iv_len, const uint8_t *adata, size_t adata_len, uint8_t *atag, size_t atag_len)
|
||||||
|
{
|
||||||
int ret = 0; // our return value
|
int ret = 0;
|
||||||
gcm_context ctx; // includes the AES context structure
|
gcm_context ctx;
|
||||||
|
|
||||||
size_t tag_len = 0;
|
|
||||||
unsigned char * tag_buf = NULL;
|
|
||||||
|
|
||||||
gcm_setkey(&ctx, key, (const uint)key_len);
|
gcm_setkey(&ctx, key, (const uint)key_len);
|
||||||
|
ret = gcm_crypt_and_tag(&ctx, mode, iv, iv_len, adata, adata_len, input, output, input_length, atag, atag_len);
|
||||||
ret = gcm_crypt_and_tag(&ctx, ENCRYPT, iv, iv_len, NULL, 0,
|
|
||||||
input, output, input_length, tag_buf, tag_len);
|
|
||||||
|
|
||||||
gcm_zero_ctx(&ctx);
|
gcm_zero_ctx(&ctx);
|
||||||
|
|
||||||
return(ret);
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int aes_gcm_decrypt(unsigned char* output, const unsigned char* input, size_t input_length, const unsigned char* key, const size_t key_len, const unsigned char * iv, const size_t iv_len) {
|
|
||||||
|
|
||||||
int ret = 0; // our return value
|
|
||||||
gcm_context ctx; // includes the AES context structure
|
|
||||||
|
|
||||||
size_t tag_len = 0;
|
|
||||||
unsigned char * tag_buf = NULL;
|
|
||||||
|
|
||||||
gcm_setkey(&ctx, key, (const uint)key_len);
|
|
||||||
|
|
||||||
ret = gcm_crypt_and_tag(&ctx, DECRYPT, iv, iv_len, NULL, 0,
|
|
||||||
input, output, input_length, tag_buf, tag_len);
|
|
||||||
|
|
||||||
gcm_zero_ctx(&ctx);
|
|
||||||
|
|
||||||
return(ret);
|
|
||||||
|
|
||||||
}
|
|
@ -2,5 +2,5 @@
|
|||||||
|
|
||||||
#include "gcm.h"
|
#include "gcm.h"
|
||||||
|
|
||||||
int aes_gcm_encrypt(unsigned char* output, const unsigned char* input, size_t input_length, const unsigned char* key, const size_t key_len, const unsigned char * iv, const size_t iv_len);
|
// mode : ENCRYPT, DECRYPT
|
||||||
int aes_gcm_decrypt(unsigned char* output, const unsigned char* input, size_t input_length, const unsigned char* key, const size_t key_len, const unsigned char * iv, const size_t iv_len);
|
int aes_gcm_crypt(int mode, uint8_t *output, const uint8_t *input, size_t input_length, const uint8_t *key, const size_t key_len, const uint8_t *iv, const size_t iv_len, const uint8_t *adata, size_t adata_len, uint8_t *atag, size_t atag_len);
|
||||||
|
@ -247,6 +247,10 @@ static bool is_quic_version_with_v1_labels(uint32_t version)
|
|||||||
return true;
|
return true;
|
||||||
return is_quic_draft_max(QUICDraftVersion(version), 34);
|
return is_quic_draft_max(QUICDraftVersion(version), 34);
|
||||||
}
|
}
|
||||||
|
static bool is_quic_v2(uint32_t version)
|
||||||
|
{
|
||||||
|
return version == 0x709A50C4;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool quic_hkdf_expand_label(const uint8_t *secret, uint8_t secret_len, const char *label, uint8_t *out, size_t out_len)
|
static bool quic_hkdf_expand_label(const uint8_t *secret, uint8_t secret_len, const char *label, uint8_t *out, size_t out_len)
|
||||||
@ -424,7 +428,18 @@ bool QUICDecryptInitial(const uint8_t *data, size_t data_len, uint8_t *clean, si
|
|||||||
*clean_len = cryptlen;
|
*clean_len = cryptlen;
|
||||||
const uint8_t *decrypt_begin = data + pn_offset + pkn_len;
|
const uint8_t *decrypt_begin = data + pn_offset + pkn_len;
|
||||||
|
|
||||||
return !aes_gcm_decrypt(clean, decrypt_begin, cryptlen, aeskey, sizeof(aeskey), aesiv, sizeof(aesiv));
|
uint8_t atag[16],header[256];
|
||||||
|
size_t header_len = pn_offset + pkn_len;
|
||||||
|
if (header_len > sizeof(header)) return false; // not likely header will be so large
|
||||||
|
memcpy(header, data, header_len);
|
||||||
|
header[0] = packet0;
|
||||||
|
for(uint8_t i = 0; i < pkn_len; i++) header[header_len - 1 - i] = (uint8_t)(pkn >> (8 * i));
|
||||||
|
|
||||||
|
if (aes_gcm_crypt(DECRYPT, clean, decrypt_begin, cryptlen, aeskey, sizeof(aeskey), aesiv, sizeof(aesiv), header, header_len, atag, sizeof(atag)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// check if message was decrypted correctly : good keys , no data corruption
|
||||||
|
return !memcmp(data + pn_offset + pkn_len + cryptlen, atag, 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QUICDefragCrypto(const uint8_t *clean,size_t clean_len, uint8_t *defrag,size_t *defrag_len)
|
bool QUICDefragCrypto(const uint8_t *clean,size_t clean_len, uint8_t *defrag,size_t *defrag_len)
|
||||||
@ -509,12 +524,38 @@ bool QUICExtractHostFromInitial(const uint8_t *data, size_t data_len, char *host
|
|||||||
|
|
||||||
bool IsQUICInitial(const uint8_t *data, size_t len)
|
bool IsQUICInitial(const uint8_t *data, size_t len)
|
||||||
{
|
{
|
||||||
// long header, fixed bit, type=initial
|
// too small packets are not likely to be initials with client hello
|
||||||
if (len < 512 || (data[0] & 0xF0) != 0xC0) return false;
|
if (len < 256) return false;
|
||||||
const uint8_t *p = data + 1;
|
|
||||||
uint32_t ver = ntohl(*(uint32_t*)p);
|
// this also ensures long header
|
||||||
|
uint32_t ver = QUICExtractVersion(data,len);
|
||||||
if (QUICDraftVersion(ver) < 11) return false;
|
if (QUICDraftVersion(ver) < 11) return false;
|
||||||
p += 4;
|
|
||||||
if (!*p || *p > QUIC_MAX_CID_LENGTH) return false;
|
// quic v1 : initial packets are 00b
|
||||||
return true;
|
// quic v2 : initial packets are 01b
|
||||||
|
if ((data[0] & 0x30) != (is_quic_v2(ver) ? 0x10 : 0x00)) return false;
|
||||||
|
|
||||||
|
uint64_t offset=5, sz;
|
||||||
|
|
||||||
|
// DCID. must be present
|
||||||
|
if (!data[offset] || data[offset] > QUIC_MAX_CID_LENGTH) return false;
|
||||||
|
offset += 1 + data[offset];
|
||||||
|
|
||||||
|
// SCID
|
||||||
|
if (data[offset] > QUIC_MAX_CID_LENGTH) return false;
|
||||||
|
offset += 1 + data[offset];
|
||||||
|
|
||||||
|
// token length
|
||||||
|
offset += tvb_get_varint(data + offset, &sz);
|
||||||
|
offset += sz;
|
||||||
|
if (offset >= len) return false;
|
||||||
|
|
||||||
|
// payload length
|
||||||
|
if ((offset + tvb_get_size(data[offset])) >= len) return false;
|
||||||
|
tvb_get_varint(data + offset, &sz);
|
||||||
|
offset += sz;
|
||||||
|
if (offset > len) return false;
|
||||||
|
|
||||||
|
// client hello cannot be too small. likely ACK
|
||||||
|
return sz>=96;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user