lsquic_parse_iquic_common.c revision e5d4bc6d
1229fce07SDmitri Tikhonov/* Copyright (c) 2017 - 2019 LiteSpeed Technologies Inc.  See LICENSE. */
29626cfc2SDmitri Tikhonov#include <stddef.h>
39626cfc2SDmitri Tikhonov#include <stdint.h>
49626cfc2SDmitri Tikhonov#include <string.h>
59626cfc2SDmitri Tikhonov#include <sys/queue.h>
69626cfc2SDmitri Tikhonov#include <sys/types.h>
79626cfc2SDmitri Tikhonov
89626cfc2SDmitri Tikhonov#include <openssl/rand.h>
99626cfc2SDmitri Tikhonov
109626cfc2SDmitri Tikhonov#include "lsquic_types.h"
119626cfc2SDmitri Tikhonov#include "lsquic_int_types.h"
129626cfc2SDmitri Tikhonov#include "lsquic_packet_common.h"
139626cfc2SDmitri Tikhonov#include "lsquic_packet_in.h"
149626cfc2SDmitri Tikhonov#include "lsquic_parse_common.h"
159626cfc2SDmitri Tikhonov#include "lsquic_parse.h"
169626cfc2SDmitri Tikhonov#include "lsquic_version.h"
179626cfc2SDmitri Tikhonov#include "lsquic.h"
189626cfc2SDmitri Tikhonov#include "lsquic_logger.h"
199626cfc2SDmitri Tikhonov#include "lsquic_byteswap.h"
209626cfc2SDmitri Tikhonov#include "lsquic_str.h"
219626cfc2SDmitri Tikhonov#include "lsquic_handshake.h"
229626cfc2SDmitri Tikhonov
239626cfc2SDmitri Tikhonov
24c7d81ce1SDmitri Tikhonovstatic const enum header_type bin_2_header_type_Q044[0x100] =
259626cfc2SDmitri Tikhonov{
269626cfc2SDmitri Tikhonov    [0x80 | 0x7F]  =  HETY_INITIAL,
279626cfc2SDmitri Tikhonov    [0x80 | 0x7E]  =  HETY_RETRY,
289626cfc2SDmitri Tikhonov    [0x80 | 0x7D]  =  HETY_HANDSHAKE,
299626cfc2SDmitri Tikhonov    [0x80 | 0x7C]  =  HETY_0RTT,
309626cfc2SDmitri Tikhonov};
319626cfc2SDmitri Tikhonov
329626cfc2SDmitri Tikhonov
33c7d81ce1SDmitri Tikhonov/* [draft-ietf-quic-transport-17] Section-17.2 */
34c7d81ce1SDmitri Tikhonovstatic const enum header_type bits2ht[4] =
35c7d81ce1SDmitri Tikhonov{
36c7d81ce1SDmitri Tikhonov    [0] = HETY_INITIAL,
37c7d81ce1SDmitri Tikhonov    [1] = HETY_0RTT,
38c7d81ce1SDmitri Tikhonov    [2] = HETY_HANDSHAKE,
39c7d81ce1SDmitri Tikhonov    [3] = HETY_RETRY,
40c7d81ce1SDmitri Tikhonov};
41c7d81ce1SDmitri Tikhonov
42c7d81ce1SDmitri Tikhonov
43c7d81ce1SDmitri Tikhonov/* This function supports versions Q044 and higher */
449626cfc2SDmitri Tikhonovint
459626cfc2SDmitri Tikhonovlsquic_iquic_parse_packet_in_long_begin (lsquic_packet_in_t *packet_in,
469626cfc2SDmitri Tikhonov            size_t length, int is_server, struct packin_parse_state *state)
479626cfc2SDmitri Tikhonov{
489626cfc2SDmitri Tikhonov    const unsigned char *p = packet_in->pi_data;
499626cfc2SDmitri Tikhonov    const unsigned char *const end = p + length;
509626cfc2SDmitri Tikhonov    lsquic_ver_tag_t tag;
519626cfc2SDmitri Tikhonov    enum header_type header_type;
52c7d81ce1SDmitri Tikhonov    unsigned dcil, scil, packet_len;
539626cfc2SDmitri Tikhonov    int verneg;
54c7d81ce1SDmitri Tikhonov    enum lsquic_version version;
559626cfc2SDmitri Tikhonov    unsigned char first_byte;
569626cfc2SDmitri Tikhonov    const unsigned cid_len = 8;
579626cfc2SDmitri Tikhonov
589626cfc2SDmitri Tikhonov    if (length < 6)
599626cfc2SDmitri Tikhonov        return -1;
609626cfc2SDmitri Tikhonov    first_byte = *p++;
619626cfc2SDmitri Tikhonov
629626cfc2SDmitri Tikhonov    memcpy(&tag, p, 4);
639626cfc2SDmitri Tikhonov    p += 4;
649626cfc2SDmitri Tikhonov    verneg = 0 == tag;
659626cfc2SDmitri Tikhonov    if (!verneg)
669626cfc2SDmitri Tikhonov    {
67c7d81ce1SDmitri Tikhonov        version = lsquic_tag2ver(tag);
68c7d81ce1SDmitri Tikhonov        if (version == LSQVER_044)
69c7d81ce1SDmitri Tikhonov        {
70c7d81ce1SDmitri Tikhonov            header_type = bin_2_header_type_Q044[ first_byte ];
71c7d81ce1SDmitri Tikhonov            if (!header_type)
72c7d81ce1SDmitri Tikhonov                return -1;
73c7d81ce1SDmitri Tikhonov        }
74c7d81ce1SDmitri Tikhonov        else
75c7d81ce1SDmitri Tikhonov            header_type = bits2ht[ (first_byte >> 4) & 3 ];
769626cfc2SDmitri Tikhonov    }
779626cfc2SDmitri Tikhonov    else
78e5d4bc6dSDmitri Tikhonov    {
799626cfc2SDmitri Tikhonov        header_type = HETY_VERNEG;
80e5d4bc6dSDmitri Tikhonov#ifdef WIN32
81e5d4bc6dSDmitri Tikhonov        /* Useless initialization: */
82e5d4bc6dSDmitri Tikhonov        version = -1;
83e5d4bc6dSDmitri Tikhonov#endif
84e5d4bc6dSDmitri Tikhonov    }
85e5d4bc6dSDmitri Tikhonov
869626cfc2SDmitri Tikhonov
879626cfc2SDmitri Tikhonov    packet_in->pi_header_type = header_type;
889626cfc2SDmitri Tikhonov
899626cfc2SDmitri Tikhonov    dcil = p[0] >> 4;
909626cfc2SDmitri Tikhonov    if (dcil)
919626cfc2SDmitri Tikhonov        dcil += 3;
929626cfc2SDmitri Tikhonov    scil = p[0] & 0xF;
939626cfc2SDmitri Tikhonov    if (scil)
949626cfc2SDmitri Tikhonov        scil += 3;
959626cfc2SDmitri Tikhonov    ++p;
969626cfc2SDmitri Tikhonov
979626cfc2SDmitri Tikhonov    /* Chromium comments state that the client sends packets with destination
989626cfc2SDmitri Tikhonov     * CID of 8 bytes and source CID of 0 bytes and the server does it the
999626cfc2SDmitri Tikhonov     * other way around.
1009626cfc2SDmitri Tikhonov     *
101c7d81ce1SDmitri Tikhonov     * XXX When IETF branch is merged, this check for Q044 and higher will
102c7d81ce1SDmitri Tikhonov     * have to be moved to the pf_parse_packet_in_finish().
1039626cfc2SDmitri Tikhonov     */
1049626cfc2SDmitri Tikhonov    if (is_server)
1059626cfc2SDmitri Tikhonov    {
1069626cfc2SDmitri Tikhonov        if (!(dcil == cid_len && scil == 0))
1079626cfc2SDmitri Tikhonov            return -1;
1089626cfc2SDmitri Tikhonov    }
1099626cfc2SDmitri Tikhonov    else
1109626cfc2SDmitri Tikhonov    {
1119626cfc2SDmitri Tikhonov        if (!(dcil == 0 && scil == cid_len))
1129626cfc2SDmitri Tikhonov            return -1;
1139626cfc2SDmitri Tikhonov    }
1149626cfc2SDmitri Tikhonov
115c7d81ce1SDmitri Tikhonov    if (!verneg)
116c7d81ce1SDmitri Tikhonov    {
117c7d81ce1SDmitri Tikhonov        if (version == LSQVER_044)
118c7d81ce1SDmitri Tikhonov        {
119c7d81ce1SDmitri Tikhonov            packet_in->pi_flags |= GQUIC_PACKNO_LEN_4 << PIBIT_BITS_SHIFT;
120c7d81ce1SDmitri Tikhonov            packet_len = 4;
121c7d81ce1SDmitri Tikhonov        }
122c7d81ce1SDmitri Tikhonov        else
123c7d81ce1SDmitri Tikhonov        {
124c7d81ce1SDmitri Tikhonov            packet_in->pi_flags |= (first_byte & 3) << PIBIT_BITS_SHIFT;
125c7d81ce1SDmitri Tikhonov            packet_len = 1 + (first_byte & 3);
126c7d81ce1SDmitri Tikhonov        }
127c7d81ce1SDmitri Tikhonov        if (end - p < (ptrdiff_t) (dcil + scil + packet_len))
128c7d81ce1SDmitri Tikhonov            return -1;
129c7d81ce1SDmitri Tikhonov    }
130c7d81ce1SDmitri Tikhonov    else
131c7d81ce1SDmitri Tikhonov    {
132c7d81ce1SDmitri Tikhonov        /* Need at least one version in the version array: add 4 */
133c7d81ce1SDmitri Tikhonov        if (end - p < (ptrdiff_t) (dcil + scil + 4))
134c7d81ce1SDmitri Tikhonov            return -1;
135e5d4bc6dSDmitri Tikhonov#ifdef WIN32
136e5d4bc6dSDmitri Tikhonov        /* Useless initialization: */
137e5d4bc6dSDmitri Tikhonov        packet_len = 0;
138e5d4bc6dSDmitri Tikhonov#endif
139c7d81ce1SDmitri Tikhonov    }
1409626cfc2SDmitri Tikhonov
1419626cfc2SDmitri Tikhonov    memcpy(&packet_in->pi_conn_id, p, cid_len);
1429626cfc2SDmitri Tikhonov    p += cid_len;
1439626cfc2SDmitri Tikhonov    packet_in->pi_flags |= PI_CONN_ID;
1449626cfc2SDmitri Tikhonov
1459626cfc2SDmitri Tikhonov    packet_in->pi_packno       = 0;
1469626cfc2SDmitri Tikhonov
1479626cfc2SDmitri Tikhonov    if (!verneg)
1489626cfc2SDmitri Tikhonov    {
1499626cfc2SDmitri Tikhonov        state->pps_p      = p;
1509626cfc2SDmitri Tikhonov        state->pps_nbytes = packet_len;
1519626cfc2SDmitri Tikhonov        p += packet_len;
1529626cfc2SDmitri Tikhonov        packet_in->pi_quic_ver = 1;
1539626cfc2SDmitri Tikhonov        if (is_server || HETY_0RTT != header_type)
1549626cfc2SDmitri Tikhonov            packet_in->pi_nonce = 0;
1559626cfc2SDmitri Tikhonov        else
1569626cfc2SDmitri Tikhonov        {
1579626cfc2SDmitri Tikhonov            packet_in->pi_nonce = p - packet_in->pi_data;
1589626cfc2SDmitri Tikhonov            p += 32;
1599626cfc2SDmitri Tikhonov        }
1609626cfc2SDmitri Tikhonov    }
1619626cfc2SDmitri Tikhonov    else
1629626cfc2SDmitri Tikhonov    {
1639626cfc2SDmitri Tikhonov        if ((end - p) & 3)
1649626cfc2SDmitri Tikhonov            return -1;
1659626cfc2SDmitri Tikhonov        state->pps_p      = NULL;
1669626cfc2SDmitri Tikhonov        state->pps_nbytes = 0;
1679626cfc2SDmitri Tikhonov        packet_in->pi_quic_ver = p - packet_in->pi_data;
1689626cfc2SDmitri Tikhonov        p = packet_in->pi_data + length;
1699626cfc2SDmitri Tikhonov        packet_in->pi_nonce = 0;
1709626cfc2SDmitri Tikhonov    }
1719626cfc2SDmitri Tikhonov
1729626cfc2SDmitri Tikhonov    packet_in->pi_header_sz    = p - packet_in->pi_data;
1739626cfc2SDmitri Tikhonov    packet_in->pi_frame_types  = 0;
1749626cfc2SDmitri Tikhonov    packet_in->pi_data_sz      = length;
1759626cfc2SDmitri Tikhonov    packet_in->pi_refcnt       = 0;
1769626cfc2SDmitri Tikhonov    packet_in->pi_received     = 0;
1779626cfc2SDmitri Tikhonov
1789626cfc2SDmitri Tikhonov    return 0;
1799626cfc2SDmitri Tikhonov}
1809626cfc2SDmitri Tikhonov
1819626cfc2SDmitri Tikhonov
1829626cfc2SDmitri Tikhonovint
1839626cfc2SDmitri Tikhonovlsquic_iquic_parse_packet_in_short_begin (lsquic_packet_in_t *packet_in,
1849626cfc2SDmitri Tikhonov            size_t length, int is_server, struct packin_parse_state *state)
1859626cfc2SDmitri Tikhonov{
1869626cfc2SDmitri Tikhonov    const unsigned char *p = packet_in->pi_data;
1879626cfc2SDmitri Tikhonov    const unsigned char *const pend = packet_in->pi_data + length;
1889626cfc2SDmitri Tikhonov    unsigned cid_len = 8;   /* XXX this will need to be passed in */
1899626cfc2SDmitri Tikhonov    unsigned packet_len;
1909626cfc2SDmitri Tikhonov
191c7d81ce1SDmitri Tikhonov    if (*p & 0x40)  /* Q046 and higher */
192c7d81ce1SDmitri Tikhonov        packet_len = 1 + (*p & 3);
193c7d81ce1SDmitri Tikhonov    else
194c7d81ce1SDmitri Tikhonov    {
195c7d81ce1SDmitri Tikhonov        if ((*p & 0x30) != 0x30 || (*p & 3) == 3)
196c7d81ce1SDmitri Tikhonov            return -1;
197c7d81ce1SDmitri Tikhonov        packet_len = 1 << (*p & 3);
198c7d81ce1SDmitri Tikhonov    }
1999626cfc2SDmitri Tikhonov
200a37b0c96SDmitri Tikhonov    if (pend - p < (ptrdiff_t) (1 + cid_len + packet_len))
2019626cfc2SDmitri Tikhonov        return -1;
2029626cfc2SDmitri Tikhonov
203c7d81ce1SDmitri Tikhonov    packet_in->pi_flags |= (*p & 3) << PIBIT_BITS_SHIFT;
2049626cfc2SDmitri Tikhonov    ++p;
2059626cfc2SDmitri Tikhonov
2069626cfc2SDmitri Tikhonov    if (is_server)
2079626cfc2SDmitri Tikhonov    {
2089626cfc2SDmitri Tikhonov        memcpy(&packet_in->pi_conn_id, p, cid_len);
2099626cfc2SDmitri Tikhonov        p += cid_len;
210dee31d56SDmitri Tikhonov        packet_in->pi_flags |= PI_CONN_ID;
2119626cfc2SDmitri Tikhonov    }
2129626cfc2SDmitri Tikhonov
2139626cfc2SDmitri Tikhonov    /* We could read in the packet number here, but we choose to do it in
2149626cfc2SDmitri Tikhonov     * the finish() call instead.
2159626cfc2SDmitri Tikhonov     */
2169626cfc2SDmitri Tikhonov    packet_in->pi_packno       = 0;
2179626cfc2SDmitri Tikhonov    state->pps_p      = p;
2189626cfc2SDmitri Tikhonov    state->pps_nbytes = packet_len;
2199626cfc2SDmitri Tikhonov    p += packet_len;
2209626cfc2SDmitri Tikhonov
2219626cfc2SDmitri Tikhonov    packet_in->pi_header_type  = HETY_NOT_SET;
2229626cfc2SDmitri Tikhonov    packet_in->pi_quic_ver     = 0;
2239626cfc2SDmitri Tikhonov    packet_in->pi_nonce        = 0;
2249626cfc2SDmitri Tikhonov    packet_in->pi_header_sz    = p - packet_in->pi_data;
2259626cfc2SDmitri Tikhonov    packet_in->pi_frame_types  = 0;
2269626cfc2SDmitri Tikhonov    packet_in->pi_data_sz      = length;
2279626cfc2SDmitri Tikhonov    packet_in->pi_refcnt       = 0;
2289626cfc2SDmitri Tikhonov    packet_in->pi_received     = 0;
2299626cfc2SDmitri Tikhonov
2309626cfc2SDmitri Tikhonov    return 0;
2319626cfc2SDmitri Tikhonov}
2329626cfc2SDmitri Tikhonov
2339626cfc2SDmitri Tikhonov
234