mirror of
https://github.com/Waujito/youtubeUnblock.git
synced 2024-12-22 06:15:31 +00:00
Skeleton for quic initial message parser
This commit is contained in:
parent
d5db8c18e5
commit
4a8f0d18a9
137
quic.c
Normal file
137
quic.c
Normal file
@ -0,0 +1,137 @@
|
||||
#include "quic.h"
|
||||
|
||||
static const uint32_t supported_versions[] = {
|
||||
1, // version 1, RFC 9000
|
||||
0x6b3343cf, // version 2, RFC 9369
|
||||
};
|
||||
|
||||
/**
|
||||
* Packet number.
|
||||
*/
|
||||
struct quic_pnumber {
|
||||
uint8_t d1;
|
||||
uint8_t d2;
|
||||
uint8_t d3;
|
||||
uint8_t d4;
|
||||
};
|
||||
|
||||
uint64_t quic_parse_varlength(uint8_t *variable, uint64_t *mlen) {
|
||||
if (mlen && *mlen == 0) return 0;
|
||||
uint64_t vr = (*variable & 0x3F);
|
||||
uint8_t len = 1 << (*variable >> 6);
|
||||
|
||||
if (mlen) {
|
||||
if (*mlen < len) return 0;
|
||||
*mlen = len;
|
||||
}
|
||||
|
||||
++variable;
|
||||
for (uint8_t i = 1; i < len; i++) {
|
||||
vr = (vr << 8) + *variable;
|
||||
++variable;
|
||||
}
|
||||
|
||||
return vr;
|
||||
}
|
||||
|
||||
int quic_parse_data(uint8_t *raw_payload, uint32_t raw_payload_len,
|
||||
struct quic_lhdr **qch, uint32_t *qch_len,
|
||||
struct quic_cids *qci,
|
||||
uint8_t **payload, uint32_t *plen) {
|
||||
if ( raw_payload == NULL ||
|
||||
raw_payload_len < sizeof(struct quic_lhdr))
|
||||
goto invalid_packet;
|
||||
|
||||
struct quic_lhdr *nqch = (struct quic_lhdr *)raw_payload;
|
||||
uint32_t left_len = raw_payload_len - sizeof(struct quic_lhdr);
|
||||
uint8_t *cur_rawptr = raw_payload + sizeof(struct quic_lhdr);
|
||||
if (!nqch->fixed)
|
||||
return -EPROTO;
|
||||
|
||||
uint8_t found = 0;
|
||||
for (uint8_t i = 0; i < sizeof(supported_versions); i++) {
|
||||
if (nqch->version == supported_versions[i]) {
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
return -EPROTO;
|
||||
|
||||
if (left_len < 2) goto invalid_packet;
|
||||
struct quic_cids nqci = {0};
|
||||
|
||||
nqci.dst_len = *cur_rawptr++;
|
||||
left_len--;
|
||||
if (left_len < nqci.dst_len) goto invalid_packet;
|
||||
nqci.dst_id = cur_rawptr;
|
||||
cur_rawptr += nqci.dst_len;
|
||||
left_len -= nqci.dst_len;
|
||||
|
||||
nqci.src_len = *cur_rawptr++;
|
||||
left_len--;
|
||||
if (left_len < nqci.src_len) goto invalid_packet;
|
||||
nqci.src_id = cur_rawptr;
|
||||
cur_rawptr += nqci.src_len;
|
||||
left_len -= nqci.src_len;
|
||||
|
||||
if (qch) *qch = nqch;
|
||||
if (qch_len) {
|
||||
*qch_len = sizeof(struct quic_lhdr) +
|
||||
nqci.src_len + nqci.dst_len;
|
||||
}
|
||||
if (qci) *qci = nqci;
|
||||
if (payload) *payload = cur_rawptr;
|
||||
if (plen) *plen = left_len;
|
||||
|
||||
return 0;
|
||||
|
||||
invalid_packet:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int quic_parse_initial_message(uint8_t *inpayload, uint32_t inplen,
|
||||
const struct quic_lhdr *qch,
|
||||
struct quici_hdr *qhdr,
|
||||
uint8_t **payload, uint32_t *plen) {
|
||||
if (inplen < 3) goto invalid_packet;
|
||||
struct quici_hdr nqhdr;
|
||||
|
||||
uint8_t *cur_ptr = inpayload;
|
||||
uint32_t left_len = inplen;
|
||||
uint64_t tlen = left_len;
|
||||
|
||||
nqhdr.token_len = quic_parse_varlength(cur_ptr, &tlen);
|
||||
nqhdr.token = cur_ptr + tlen;
|
||||
|
||||
if (left_len < nqhdr.token_len + tlen)
|
||||
goto invalid_packet;
|
||||
cur_ptr += tlen + nqhdr.token_len;
|
||||
left_len -= tlen + nqhdr.token_len;
|
||||
|
||||
tlen = left_len;
|
||||
nqhdr.length = quic_parse_varlength(cur_ptr, &tlen);
|
||||
|
||||
if (left_len != nqhdr.length + tlen &&
|
||||
left_len <= qch->number_length + 1)
|
||||
goto invalid_packet;
|
||||
|
||||
uint32_t packet_number = 0;
|
||||
|
||||
for (uint8_t i = 0; i <= qch->number_length; i++) {
|
||||
packet_number = (packet_number << 8) + *cur_ptr++;
|
||||
left_len--;
|
||||
}
|
||||
|
||||
nqhdr.packet_number = packet_number;
|
||||
|
||||
if (qhdr) *qhdr = nqhdr;
|
||||
if (payload) *payload = cur_ptr;
|
||||
if (plen) *plen = left_len;
|
||||
|
||||
return 0;
|
||||
|
||||
invalid_packet:
|
||||
lgerror("QUIC invalid Initial packet", -EINVAL);
|
||||
return -EINVAL;
|
||||
}
|
113
quic.h
Normal file
113
quic.h
Normal file
@ -0,0 +1,113 @@
|
||||
#ifndef QUIC_H
|
||||
#define QUIC_H
|
||||
#include "types.h"
|
||||
|
||||
/**
|
||||
* @macro
|
||||
*
|
||||
* :macro:`NGTCP2_INITIAL_SALT_V1` is a salt value which is used to
|
||||
* derive initial secret. It is used for QUIC v1.
|
||||
*/
|
||||
#define QUIC_INITIAL_SALT_V1 \
|
||||
"\x38\x76\x2c\xf7\xf5\x59\x34\xb3\x4d\x17\x9a\xe6\xa4\xc8\x0c\xad" \
|
||||
"\xcc\xbb\x7f\x0a"
|
||||
|
||||
/**
|
||||
* @macro
|
||||
*
|
||||
* :macro:`NGTCP2_INITIAL_SALT_V2` is a salt value which is used to
|
||||
* derive initial secret. It is used for QUIC v2.
|
||||
*/
|
||||
#define QUIC_INITIAL_SALT_V2 \
|
||||
"\x0d\xed\xe3\xde\xf7\x00\xa6\xdb\x81\x93\x81\xbe\x6e\x26\x9d\xcb" \
|
||||
"\xf9\xbd\x2e\xd9"
|
||||
|
||||
#define QUIC_INITIAL_TYPE_V1 0x00
|
||||
#define QUIC_0_RTT_TYPE_V1 0x01
|
||||
#define QUIC_HANDSHAKE_TYPE_V1 0x02
|
||||
#define QUIC_RETRY_TYPE_V1 0x03
|
||||
|
||||
#define QUIC_INITIAL_TYPE_V2 0b01
|
||||
#define QUIC_0_RTT_TYPE_V2 0b10
|
||||
#define QUIC_HANDSHAKE_TYPE_V2 0b11
|
||||
#define QUIC_RETRY_TYPE_V2 0b00
|
||||
|
||||
/**
|
||||
* Quic Large Header
|
||||
*/
|
||||
struct quic_lhdr {
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
uint8_t number_length: 2;
|
||||
uint8_t reserved: 2;
|
||||
uint8_t type: 2;
|
||||
uint8_t fixed: 1;
|
||||
uint8_t form: 1;
|
||||
#elif __BYTE_ORDER == __BIG_ENDIAN
|
||||
uint8_t form: 1;
|
||||
uint8_t fixed: 1;
|
||||
uint8_t type: 2;
|
||||
uint8_t reserved: 2;
|
||||
uint8_t number_length: 2;
|
||||
#else
|
||||
#error "Undefined endian"
|
||||
#endif
|
||||
|
||||
uint32_t version;
|
||||
};
|
||||
|
||||
/**
|
||||
* Quic Large Header Ids
|
||||
* (separated from the original header because of varying dst
|
||||
*/
|
||||
struct quic_cids {
|
||||
uint8_t dst_len;
|
||||
uint8_t *dst_id;
|
||||
uint8_t src_len;
|
||||
uint8_t *src_id;
|
||||
};
|
||||
|
||||
/**
|
||||
* Parses QUIС raw data (UDP payload) to quic large header and
|
||||
* quic payload.
|
||||
*
|
||||
* \qch_len is sizeof(qch) + qci->dst_len + qci->src_id
|
||||
* \payload is Type-Specific payload (#17.2).
|
||||
*/
|
||||
int quic_parse_data(uint8_t *raw_payload, uint32_t raw_payload_len,
|
||||
struct quic_lhdr **qch, uint32_t *qch_len,
|
||||
struct quic_cids *qci,
|
||||
uint8_t **payload, uint32_t *plen);
|
||||
|
||||
|
||||
/**
|
||||
* Parses QUIC variable-length integer. (#16)
|
||||
* \variable is a pointer to the sequence to be parsed
|
||||
* (varlen integer in big endian format)
|
||||
*
|
||||
* \mlen Used to signal about variable length and validate left length
|
||||
* in the buffer.
|
||||
*/
|
||||
uint64_t quic_parse_varlength(uint8_t *variable, uint64_t *mlen);
|
||||
|
||||
// quici stands for QUIC Initial
|
||||
|
||||
/**
|
||||
* This structure should be parsed
|
||||
*/
|
||||
struct quici_hdr {
|
||||
uint64_t token_len;
|
||||
uint8_t *token;
|
||||
uint64_t length;
|
||||
uint32_t packet_number;
|
||||
};
|
||||
|
||||
/**
|
||||
* Parses QUIC initial payload.
|
||||
* \inpayload is a raw QUIC payload (payload after quic large header)
|
||||
*/
|
||||
int quic_parse_initial_message(uint8_t *inpayload, uint32_t inplen,
|
||||
const struct quic_lhdr *qch,
|
||||
struct quici_hdr *qhdr,
|
||||
uint8_t **payload, uint32_t *plen);
|
||||
|
||||
#endif /* QUIC_H */
|
Loading…
Reference in New Issue
Block a user