nfqws: quic protocol code optimizations

This commit is contained in:
bol-van
2022-03-26 10:08:10 +03:00
parent f7c0c35670
commit 3753349058
11 changed files with 16 additions and 31 deletions

View File

@@ -67,18 +67,7 @@ static uint8_t tvb_get_varint(const uint8_t *tvb, uint64_t *value)
}
static uint8_t tvb_get_size(uint8_t tvb)
{
switch(tvb >> 6)
{
case 0: /* 0b00 => 1 byte length (6 bits Usable) */
return 1;
case 1: /* 0b01 => 2 bytes length (14 bits Usable) */
return 2;
case 2: /* 0b10 => 4 bytes length (30 bits Usable) */
return 4;
case 3: /* 0b11 => 8 bytes length (62 bits Usable) */
return 8;
}
return 0;
return 1 << (tvb >> 6);
}
bool IsQUICCryptoHello(const uint8_t *data, size_t len, size_t *hello_offset, size_t *hello_len)
@@ -91,8 +80,8 @@ bool IsQUICCryptoHello(const uint8_t *data, size_t len, size_t *hello_offset, si
// offset must be 0 if it's a full segment, not just a chunk
if (coff || (offset+tvb_get_size(data[offset])) >= len) return false;
offset += tvb_get_varint(data + offset, &clen);
if (data[offset] != 0x01 || (offset + coff + clen) > len) return false;
if (hello_offset) *hello_offset = offset + coff;
if (data[offset] != 0x01 || (offset + clen) > len) return false;
if (hello_offset) *hello_offset = offset;
if (hello_len) *hello_len = (size_t)clen;
return true;
}
@@ -247,24 +236,20 @@ uint8_t QUICDraftVersion(uint32_t version)
return 0;
}
static inline bool is_quic_draft_max(uint32_t draft_version, uint8_t max_version)
static bool is_quic_draft_max(uint32_t draft_version, uint8_t max_version)
{
return draft_version && draft_version <= max_version;
}
static bool is_quic_ver_less_than(uint32_t version, uint8_t max_version)
{
return is_quic_draft_max(QUICDraftVersion(version), max_version);
}
static bool is_version_with_v1_labels(uint32_t version)
static bool is_quic_version_with_v1_labels(uint32_t version)
{
if (((version & 0xFFFFFF00) == 0x51303500) /* Q05X */ ||
((version & 0xFFFFFF00) == 0x54303500)) /* T05X */
return true;
return is_quic_ver_less_than(version, 34);
return is_quic_draft_max(QUICDraftVersion(version), 34);
}
static bool quic_hkdf_expand_label(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)
{
uint8_t hkdflabel[64];
@@ -395,7 +380,7 @@ bool QUICDecryptInitial(const uint8_t *data, size_t data_len, uint8_t *clean, si
if (!quic_derive_initial_secret(&dcid, client_initial_secret, ver)) return false;
uint8_t aeskey[16], aesiv[12], aeshp[16];
bool v1_label = is_version_with_v1_labels(ver);
bool v1_label = is_quic_version_with_v1_labels(ver);
if (!quic_hkdf_expand_label(client_initial_secret, SHA256HashSize, v1_label ? "tls13 quic key" : "tls13 quicv2 key", aeskey, sizeof(aeskey)) ||
!quic_hkdf_expand_label(client_initial_secret, SHA256HashSize, v1_label ? "tls13 quic iv" : "tls13 quicv2 iv", aesiv, sizeof(aesiv)) ||
!quic_hkdf_expand_label(client_initial_secret, SHA256HashSize, v1_label ? "tls13 quic hp" : "tls13 quicv2 hp", aeshp, sizeof(aeshp)))
@@ -408,10 +393,10 @@ bool QUICDecryptInitial(const uint8_t *data, size_t data_len, uint8_t *clean, si
pn_offset = 1 + 4 + 1 + data[5];
if (pn_offset >= data_len) return false;
pn_offset += 1 + data[pn_offset];
if ((pn_offset + 8) > data_len) return false;
if ((pn_offset + tvb_get_size(data[pn_offset])) >= data_len) return false;
pn_offset += tvb_get_varint(data + pn_offset, &token_len);
pn_offset += token_len;
if ((pn_offset + 8) > data_len) return false;
if ((pn_offset + tvb_get_size(data[pn_offset])) >= data_len) return false;
pn_offset += tvb_get_varint(data + pn_offset, &payload_len);
if (payload_len<20 || (pn_offset + payload_len)>data_len) return false;
@@ -425,12 +410,12 @@ bool QUICDecryptInitial(const uint8_t *data, size_t data_len, uint8_t *clean, si
memcpy(mask, sample_enc, sizeof(mask));
uint8_t packet0 = data[0] ^ (mask[0] & 0x0f);
uint32_t pkn_len = (packet0 & 0x03) + 1;
uint8_t pkn_len = (packet0 & 0x03) + 1;
uint8_t pkn_bytes[4];
memcpy(pkn_bytes, data + pn_offset, pkn_len);
uint32_t pkn = 0;
for (uint32_t i = 0; i < pkn_len; i++) pkn |= (uint32_t)(pkn_bytes[i] ^ mask[1 + i]) << (8 * (pkn_len - 1 - i));
for (uint8_t i = 0; i < pkn_len; i++) pkn |= (uint32_t)(pkn_bytes[i] ^ mask[1 + i]) << (8 * (pkn_len - 1 - i));
phton64(aesiv + sizeof(aesiv) - 8, pntoh64(aesiv + sizeof(aesiv) - 8) ^ pkn);
@@ -522,11 +507,11 @@ bool QUICExtractHostFromInitial(const uint8_t *data, size_t data_len, char *host
return TLSHelloExtractHostFromHandshake(defrag + hello_offset, hello_len, host, len_host);
}
bool IsQUICInitial(uint8_t *data, size_t len)
bool IsQUICInitial(const uint8_t *data, size_t len)
{
// long header, fixed bit, type=initial
if (len < 512 || (data[0] & 0xF0) != 0xC0) return false;
uint8_t *p = data + 1;
const uint8_t *p = data + 1;
uint32_t ver = ntohl(*(uint32_t*)p);
if (QUICDraftVersion(ver) < 11) return false;
p += 4;

View File

@@ -21,7 +21,7 @@ typedef struct quic_cid {
uint8_t cid[QUIC_MAX_CID_LENGTH];
} quic_cid_t;
bool IsQUICInitial(uint8_t *data, size_t len);
bool IsQUICInitial(const uint8_t *data, size_t len);
bool IsQUICCryptoHello(const uint8_t *data, size_t len, size_t *hello_offset, size_t *hello_len);
bool QUICIsLongHeader(const uint8_t *data, size_t len);
uint32_t QUICExtractVersion(const uint8_t *data, size_t len);
@@ -30,4 +30,4 @@ bool QUICExtractDCID(const uint8_t *data, size_t len, quic_cid_t *cid);
bool QUICDecryptInitial(const uint8_t *data, size_t data_len, uint8_t *clean, size_t *clean_len);
bool QUICDefragCrypto(const uint8_t *clean,size_t clean_len, uint8_t *defrag,size_t *defrag_len);
bool QUICExtractHostFromInitial(const uint8_t *data, size_t data_len, char *host, size_t len_host, bool *bDecryptOK, bool *bIsCryptoHello);
bool QUICExtractHostFromInitial(const uint8_t *data, size_t data_len, char *host, size_t len_host, bool *bDecryptOK, bool *bIsCryptoHello);