Skip to content

Commit

Permalink
Remaster tls parser for quic crypto
Browse files Browse the repository at this point in the history
  • Loading branch information
Waujito committed Jan 2, 2025
1 parent b36d1ee commit c79d6c2
Show file tree
Hide file tree
Showing 6 changed files with 364 additions and 124 deletions.
14 changes: 8 additions & 6 deletions src/mangle.c
Original file line number Diff line number Diff line change
Expand Up @@ -177,11 +177,13 @@ int process_tcp_packet(const struct section_config_t *section, const uint8_t *ra
lgtrace_addp("TLS analyzed");

if (vrd.sni_len != 0) {
lgtrace_addp("SNI detected: %.*s", vrd.sni_len, data + vrd.sni_offset);
lgtrace_addp("SNI detected: %.*s", vrd.sni_len, vrd.sni_ptr);
}

if (vrd.target_sni) {
lgdebugmsg("Target SNI detected: %.*s", vrd.sni_len, data + vrd.sni_offset);
lgdebugmsg("Target SNI detected: %.*s", vrd.sni_len, vrd.sni_ptr);
size_t sni_offset = vrd.sni_ptr - data;
size_t target_sni_offset = vrd.target_sni_ptr - data;

uint32_t payload_len = raw_payload_len;
NETBUF_ALLOC(payload, MAX_PACKET_SIZE);
Expand Down Expand Up @@ -238,8 +240,8 @@ int process_tcp_packet(const struct section_config_t *section, const uint8_t *ra

switch (section->fragmentation_strategy) {
case FRAG_STRAT_TCP: {
ipd_offset = vrd.sni_target_offset;
mid_offset = ipd_offset + vrd.sni_target_len / 2;
ipd_offset = target_sni_offset;
mid_offset = ipd_offset + vrd.target_sni_len / 2;

uint32_t poses[2];
int cnt = 0;
Expand Down Expand Up @@ -269,8 +271,8 @@ int process_tcp_packet(const struct section_config_t *section, const uint8_t *ra
break;
case FRAG_STRAT_IP:
if (ipxv == IP4VERSION) {
ipd_offset = ((char *)data - (char *)tcph) + vrd.sni_target_offset;
mid_offset = ipd_offset + vrd.sni_target_len / 2;
ipd_offset = ((char *)data - (char *)tcph) + target_sni_offset;
mid_offset = ipd_offset + vrd.target_sni_len / 2;
mid_offset += 8 - mid_offset % 8;

uint32_t poses[2];
Expand Down
63 changes: 49 additions & 14 deletions src/quic.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ uint64_t quic_parse_varlength(const uint8_t *variable, uint64_t *mlen) {
uint8_t len = 1 << (*variable >> 6);

if (mlen) {
if (*mlen < len) return 0;
if (*mlen < len) {
*mlen = 0;
return 0;
}
*mlen = len;
}

Expand Down Expand Up @@ -164,6 +167,47 @@ int quic_parse_initial_header(const uint8_t *inpayload, uint32_t inplen,
return -EINVAL;
}

ssize_t quic_parse_crypto(struct quic_frame_crypto *crypto_frame,
const uint8_t *frame, uint64_t flen) {
const uint8_t *curptr = frame;
uint64_t curptr_len = flen;
uint64_t vln;
*crypto_frame = (struct quic_frame_crypto){0};

if (flen == 0 || *frame != QUIC_FRAME_CRYPTO ||
crypto_frame == NULL)
return -EINVAL;


curptr++, curptr_len--;

vln = curptr_len;
uint64_t offset = quic_parse_varlength(curptr, &vln);
curptr += vln, curptr_len -= vln;
if (vln == 0) {
return -EINVAL;
}

vln = curptr_len;
uint64_t length = quic_parse_varlength(curptr, &vln);
curptr += vln, curptr_len -= vln;
if (vln == 0) {
return -EINVAL;
}

if (length > curptr_len)
return -EINVAL;

crypto_frame->offset = offset;
crypto_frame->payload_length = length;
crypto_frame->payload = curptr;

curptr += length;
curptr_len -= length;

return flen - curptr_len;
}

int udp_fail_packet(struct udp_failing_strategy strategy, uint8_t *payload, uint32_t *plen, uint32_t avail_buflen) {
void *iph;
uint32_t iph_len;
Expand Down Expand Up @@ -313,20 +357,11 @@ int detect_udp_filtered(const struct section_config_t *section,

lgtrace_addp("QUIC detected");

uint8_t qtype = qch->type;
if (qch->version == QUIC_V1)
qtype = quic_convtype_v1(qtype);
else if (qch->version == QUIC_V2)
qtype = quic_convtype_v2(qtype);

if (qtype != QUIC_INITIAL_TYPE) {
lgtrace_addp("QUIC message type: %d", qtype);
goto match_port;

if (quic_check_is_initial(qch)) {
lgtrace_addp("QUIC initial message");
goto approve;
}

lgtrace_addp("QUIC initial message");

goto approve;
}

match_port:
Expand Down
17 changes: 17 additions & 0 deletions src/quic.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@
#define QUIC_RETRY_TYPE_V2 0b00
#define quic_convtype_v2(type) (((type) + 1) & 0b11)

#define QUIC_FRAME_CRYPTO 0x06
#define QUIC_FRAME_PADDING 0x00

#define QUIC_V1 1 // RFC 9000
#define QUIC_V2 0x6b3343cf // RFC 9369

Expand Down Expand Up @@ -130,6 +133,8 @@ int quic_parse_data(const uint8_t *raw_payload, uint32_t raw_payload_len,
*
* \mlen Used to signal about variable length and validate left length
* in the buffer.
*
* On error/buffer overflow mlen set to 0, otherwise it is higher
*/
uint64_t quic_parse_varlength(const uint8_t *variable, uint64_t *mlen);

Expand Down Expand Up @@ -161,6 +166,18 @@ int64_t quic_get_version(const struct quic_lhdr *qch);
*/
int quic_check_is_initial(const struct quic_lhdr *qch);

struct quic_frame_crypto {
uint64_t offset;
uint64_t payload_length;
const uint8_t *payload;
};
/**
* Parses quic crypto frame
* Returns parsed size or -EINVAL on error
*/
ssize_t quic_parse_crypto(struct quic_frame_crypto *crypto_frame,
const uint8_t *frame, uint64_t flen);


/**
* Parses QUIC initial message header.
Expand Down
Loading

0 comments on commit c79d6c2

Please sign in to comment.