lsquic_parse_iquic_common.c revision c7d81ce1
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
789626cfc2SDmitri Tikhonov        header_type = HETY_VERNEG;
799626cfc2SDmitri Tikhonov
809626cfc2SDmitri Tikhonov    packet_in->pi_header_type = header_type;
819626cfc2SDmitri Tikhonov
829626cfc2SDmitri Tikhonov    dcil = p[0] >> 4;
839626cfc2SDmitri Tikhonov    if (dcil)
849626cfc2SDmitri Tikhonov        dcil += 3;
859626cfc2SDmitri Tikhonov    scil = p[0] & 0xF;
869626cfc2SDmitri Tikhonov    if (scil)
879626cfc2SDmitri Tikhonov        scil += 3;
889626cfc2SDmitri Tikhonov    ++p;
899626cfc2SDmitri Tikhonov
909626cfc2SDmitri Tikhonov    /* Chromium comments state that the client sends packets with destination
919626cfc2SDmitri Tikhonov     * CID of 8 bytes and source CID of 0 bytes and the server does it the
929626cfc2SDmitri Tikhonov     * other way around.
939626cfc2SDmitri Tikhonov     *
94c7d81ce1SDmitri Tikhonov     * XXX When IETF branch is merged, this check for Q044 and higher will
95c7d81ce1SDmitri Tikhonov     * have to be moved to the pf_parse_packet_in_finish().
969626cfc2SDmitri Tikhonov     */
979626cfc2SDmitri Tikhonov    if (is_server)
989626cfc2SDmitri Tikhonov    {
999626cfc2SDmitri Tikhonov        if (!(dcil == cid_len && scil == 0))
1009626cfc2SDmitri Tikhonov            return -1;
1019626cfc2SDmitri Tikhonov    }
1029626cfc2SDmitri Tikhonov    else
1039626cfc2SDmitri Tikhonov    {
1049626cfc2SDmitri Tikhonov        if (!(dcil == 0 && scil == cid_len))
1059626cfc2SDmitri Tikhonov            return -1;
1069626cfc2SDmitri Tikhonov    }
1079626cfc2SDmitri Tikhonov
108c7d81ce1SDmitri Tikhonov    if (!verneg)
109c7d81ce1SDmitri Tikhonov    {
110c7d81ce1SDmitri Tikhonov        if (version == LSQVER_044)
111c7d81ce1SDmitri Tikhonov        {
112c7d81ce1SDmitri Tikhonov            packet_in->pi_flags |= GQUIC_PACKNO_LEN_4 << PIBIT_BITS_SHIFT;
113c7d81ce1SDmitri Tikhonov            packet_len = 4;
114c7d81ce1SDmitri Tikhonov        }
115c7d81ce1SDmitri Tikhonov        else
116c7d81ce1SDmitri Tikhonov        {
117c7d81ce1SDmitri Tikhonov            packet_in->pi_flags |= (first_byte & 3) << PIBIT_BITS_SHIFT;
118c7d81ce1SDmitri Tikhonov            packet_len = 1 + (first_byte & 3);
119c7d81ce1SDmitri Tikhonov        }
120c7d81ce1SDmitri Tikhonov        if (end - p < (ptrdiff_t) (dcil + scil + packet_len))
121c7d81ce1SDmitri Tikhonov            return -1;
122c7d81ce1SDmitri Tikhonov    }
123c7d81ce1SDmitri Tikhonov    else
124c7d81ce1SDmitri Tikhonov    {
125c7d81ce1SDmitri Tikhonov        /* Need at least one version in the version array: add 4 */
126c7d81ce1SDmitri Tikhonov        if (end - p < (ptrdiff_t) (dcil + scil + 4))
127c7d81ce1SDmitri Tikhonov            return -1;
128c7d81ce1SDmitri Tikhonov    }
1299626cfc2SDmitri Tikhonov
1309626cfc2SDmitri Tikhonov    memcpy(&packet_in->pi_conn_id, p, cid_len);
1319626cfc2SDmitri Tikhonov    p += cid_len;
1329626cfc2SDmitri Tikhonov    packet_in->pi_flags |= PI_CONN_ID;
1339626cfc2SDmitri Tikhonov
1349626cfc2SDmitri Tikhonov    packet_in->pi_packno       = 0;
1359626cfc2SDmitri Tikhonov
1369626cfc2SDmitri Tikhonov    if (!verneg)
1379626cfc2SDmitri Tikhonov    {
1389626cfc2SDmitri Tikhonov        state->pps_p      = p;
1399626cfc2SDmitri Tikhonov        state->pps_nbytes = packet_len;
1409626cfc2SDmitri Tikhonov        p += packet_len;
1419626cfc2SDmitri Tikhonov        packet_in->pi_quic_ver = 1;
1429626cfc2SDmitri Tikhonov        if (is_server || HETY_0RTT != header_type)
1439626cfc2SDmitri Tikhonov            packet_in->pi_nonce = 0;
1449626cfc2SDmitri Tikhonov        else
1459626cfc2SDmitri Tikhonov        {
1469626cfc2SDmitri Tikhonov            packet_in->pi_nonce = p - packet_in->pi_data;
1479626cfc2SDmitri Tikhonov            p += 32;
1489626cfc2SDmitri Tikhonov        }
1499626cfc2SDmitri Tikhonov    }
1509626cfc2SDmitri Tikhonov    else
1519626cfc2SDmitri Tikhonov    {
1529626cfc2SDmitri Tikhonov        if ((end - p) & 3)
1539626cfc2SDmitri Tikhonov            return -1;
1549626cfc2SDmitri Tikhonov        state->pps_p      = NULL;
1559626cfc2SDmitri Tikhonov        state->pps_nbytes = 0;
1569626cfc2SDmitri Tikhonov        packet_in->pi_quic_ver = p - packet_in->pi_data;
1579626cfc2SDmitri Tikhonov        p = packet_in->pi_data + length;
1589626cfc2SDmitri Tikhonov        packet_in->pi_nonce = 0;
1599626cfc2SDmitri Tikhonov    }
1609626cfc2SDmitri Tikhonov
1619626cfc2SDmitri Tikhonov    packet_in->pi_header_sz    = p - packet_in->pi_data;
1629626cfc2SDmitri Tikhonov    packet_in->pi_frame_types  = 0;
1639626cfc2SDmitri Tikhonov    packet_in->pi_data_sz      = length;
1649626cfc2SDmitri Tikhonov    packet_in->pi_refcnt       = 0;
1659626cfc2SDmitri Tikhonov    packet_in->pi_received     = 0;
1669626cfc2SDmitri Tikhonov
1679626cfc2SDmitri Tikhonov    return 0;
1689626cfc2SDmitri Tikhonov}
1699626cfc2SDmitri Tikhonov
1709626cfc2SDmitri Tikhonov
1719626cfc2SDmitri Tikhonovint
1729626cfc2SDmitri Tikhonovlsquic_iquic_parse_packet_in_short_begin (lsquic_packet_in_t *packet_in,
1739626cfc2SDmitri Tikhonov            size_t length, int is_server, struct packin_parse_state *state)
1749626cfc2SDmitri Tikhonov{
1759626cfc2SDmitri Tikhonov    const unsigned char *p = packet_in->pi_data;
1769626cfc2SDmitri Tikhonov    const unsigned char *const pend = packet_in->pi_data + length;
1779626cfc2SDmitri Tikhonov    unsigned cid_len = 8;   /* XXX this will need to be passed in */
1789626cfc2SDmitri Tikhonov    unsigned packet_len;
1799626cfc2SDmitri Tikhonov
180c7d81ce1SDmitri Tikhonov    if (*p & 0x40)  /* Q046 and higher */
181c7d81ce1SDmitri Tikhonov        packet_len = 1 + (*p & 3);
182c7d81ce1SDmitri Tikhonov    else
183c7d81ce1SDmitri Tikhonov    {
184c7d81ce1SDmitri Tikhonov        if ((*p & 0x30) != 0x30 || (*p & 3) == 3)
185c7d81ce1SDmitri Tikhonov            return -1;
186c7d81ce1SDmitri Tikhonov        packet_len = 1 << (*p & 3);
187c7d81ce1SDmitri Tikhonov    }
1889626cfc2SDmitri Tikhonov
189a37b0c96SDmitri Tikhonov    if (pend - p < (ptrdiff_t) (1 + cid_len + packet_len))
1909626cfc2SDmitri Tikhonov        return -1;
1919626cfc2SDmitri Tikhonov
192c7d81ce1SDmitri Tikhonov    packet_in->pi_flags |= (*p & 3) << PIBIT_BITS_SHIFT;
1939626cfc2SDmitri Tikhonov    ++p;
1949626cfc2SDmitri Tikhonov
1959626cfc2SDmitri Tikhonov    if (is_server)
1969626cfc2SDmitri Tikhonov    {
1979626cfc2SDmitri Tikhonov        memcpy(&packet_in->pi_conn_id, p, cid_len);
1989626cfc2SDmitri Tikhonov        p += cid_len;
199dee31d56SDmitri Tikhonov        packet_in->pi_flags |= PI_CONN_ID;
2009626cfc2SDmitri Tikhonov    }
2019626cfc2SDmitri Tikhonov
2029626cfc2SDmitri Tikhonov    /* We could read in the packet number here, but we choose to do it in
2039626cfc2SDmitri Tikhonov     * the finish() call instead.
2049626cfc2SDmitri Tikhonov     */
2059626cfc2SDmitri Tikhonov    packet_in->pi_packno       = 0;
2069626cfc2SDmitri Tikhonov    state->pps_p      = p;
2079626cfc2SDmitri Tikhonov    state->pps_nbytes = packet_len;
2089626cfc2SDmitri Tikhonov    p += packet_len;
2099626cfc2SDmitri Tikhonov
2109626cfc2SDmitri Tikhonov    packet_in->pi_header_type  = HETY_NOT_SET;
2119626cfc2SDmitri Tikhonov    packet_in->pi_quic_ver     = 0;
2129626cfc2SDmitri Tikhonov    packet_in->pi_nonce        = 0;
2139626cfc2SDmitri Tikhonov    packet_in->pi_header_sz    = p - packet_in->pi_data;
2149626cfc2SDmitri Tikhonov    packet_in->pi_frame_types  = 0;
2159626cfc2SDmitri Tikhonov    packet_in->pi_data_sz      = length;
2169626cfc2SDmitri Tikhonov    packet_in->pi_refcnt       = 0;
2179626cfc2SDmitri Tikhonov    packet_in->pi_received     = 0;
2189626cfc2SDmitri Tikhonov
2199626cfc2SDmitri Tikhonov    return 0;
2209626cfc2SDmitri Tikhonov}
2219626cfc2SDmitri Tikhonov
2229626cfc2SDmitri Tikhonov
223