diff --git a/binaries/aarch64/nfqws b/binaries/aarch64/nfqws index d43f14c..5d0aa70 100755 Binary files a/binaries/aarch64/nfqws and b/binaries/aarch64/nfqws differ diff --git a/binaries/arm/nfqws b/binaries/arm/nfqws index 11804a9..3c21e5c 100755 Binary files a/binaries/arm/nfqws and b/binaries/arm/nfqws differ diff --git a/binaries/freebsd-x64/dvtws b/binaries/freebsd-x64/dvtws index 5cc836c..4b03c88 100755 Binary files a/binaries/freebsd-x64/dvtws and b/binaries/freebsd-x64/dvtws differ diff --git a/binaries/mips32r1-lsb/nfqws b/binaries/mips32r1-lsb/nfqws index 8bcfe49..be3d5fd 100755 Binary files a/binaries/mips32r1-lsb/nfqws and b/binaries/mips32r1-lsb/nfqws differ diff --git a/binaries/mips32r1-msb/nfqws b/binaries/mips32r1-msb/nfqws index e21b31b..8670990 100755 Binary files a/binaries/mips32r1-msb/nfqws and b/binaries/mips32r1-msb/nfqws differ diff --git a/binaries/mips64r2-msb/nfqws b/binaries/mips64r2-msb/nfqws index 6f5a9fc..411484e 100755 Binary files a/binaries/mips64r2-msb/nfqws and b/binaries/mips64r2-msb/nfqws differ diff --git a/binaries/ppc/nfqws b/binaries/ppc/nfqws index 706c7ea..881a3b8 100755 Binary files a/binaries/ppc/nfqws and b/binaries/ppc/nfqws differ diff --git a/binaries/x86/nfqws b/binaries/x86/nfqws index 6037e83..20787f2 100755 Binary files a/binaries/x86/nfqws and b/binaries/x86/nfqws differ diff --git a/binaries/x86_64/nfqws b/binaries/x86_64/nfqws index ca591a1..c137993 100755 Binary files a/binaries/x86_64/nfqws and b/binaries/x86_64/nfqws differ diff --git a/nfq/crypto/aes-gcm.c b/nfq/crypto/aes-gcm.c index 21d93d4..1d0a046 100644 --- a/nfq/crypto/aes-gcm.c +++ b/nfq/crypto/aes-gcm.c @@ -1,38 +1,13 @@ #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 ret = 0; // our return value - gcm_context ctx; // includes the AES context structure - - size_t tag_len = 0; - unsigned char * tag_buf = NULL; +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; + gcm_context ctx; gcm_setkey(&ctx, key, (const uint)key_len); - - ret = gcm_crypt_and_tag(&ctx, ENCRYPT, iv, iv_len, NULL, 0, - input, output, input_length, tag_buf, tag_len); - + ret = gcm_crypt_and_tag(&ctx, mode, iv, iv_len, adata, adata_len, input, output, input_length, atag, atag_len); 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); - -} \ No newline at end of file diff --git a/nfq/crypto/aes-gcm.h b/nfq/crypto/aes-gcm.h index b5855e3..1741930 100644 --- a/nfq/crypto/aes-gcm.h +++ b/nfq/crypto/aes-gcm.h @@ -2,5 +2,5 @@ #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); -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); +// mode : ENCRYPT, DECRYPT +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); diff --git a/nfq/protocol.c b/nfq/protocol.c index e920523..4013ba9 100644 --- a/nfq/protocol.c +++ b/nfq/protocol.c @@ -247,6 +247,10 @@ static bool is_quic_version_with_v1_labels(uint32_t version) return true; 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) @@ -424,7 +428,18 @@ bool QUICDecryptInitial(const uint8_t *data, size_t data_len, uint8_t *clean, si *clean_len = cryptlen; 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) @@ -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) { - // long header, fixed bit, type=initial - if (len < 512 || (data[0] & 0xF0) != 0xC0) return false; - const uint8_t *p = data + 1; - uint32_t ver = ntohl(*(uint32_t*)p); + // too small packets are not likely to be initials with client hello + if (len < 256) return false; + + // this also ensures long header + uint32_t ver = QUICExtractVersion(data,len); if (QUICDraftVersion(ver) < 11) return false; - p += 4; - if (!*p || *p > QUIC_MAX_CID_LENGTH) return false; - return true; + + // quic v1 : initial packets are 00b + // 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; }