lsquic_parse_iquic_common.c revision 842caba2
1/* Copyright (c) 2017 - 2019 LiteSpeed Technologies Inc.  See LICENSE. */
2#include <stddef.h>
3#include <stdint.h>
4#include <string.h>
5#include <sys/queue.h>
6#include <sys/types.h>
7
8#include <openssl/rand.h>
9
10#include "lsquic_types.h"
11#include "lsquic_int_types.h"
12#include "lsquic_packet_common.h"
13#include "lsquic_packet_in.h"
14#include "lsquic_parse_common.h"
15#include "lsquic_parse.h"
16#include "lsquic_version.h"
17#include "lsquic.h"
18#include "lsquic_logger.h"
19#include "lsquic_byteswap.h"
20#include "lsquic_str.h"
21#include "lsquic_handshake.h"
22
23
24static const enum header_type bin_2_header_type_Q044[0x100] =
25{
26    [0x80 | 0x7F]  =  HETY_INITIAL,
27    [0x80 | 0x7E]  =  HETY_RETRY,
28    [0x80 | 0x7D]  =  HETY_HANDSHAKE,
29    [0x80 | 0x7C]  =  HETY_0RTT,
30};
31
32
33/* [draft-ietf-quic-transport-17] Section-17.2 */
34static const enum header_type bits2ht[4] =
35{
36    [0] = HETY_INITIAL,
37    [1] = HETY_0RTT,
38    [2] = HETY_HANDSHAKE,
39    [3] = HETY_RETRY,
40};
41
42
43/* This function supports versions Q044 and higher */
44int
45lsquic_iquic_parse_packet_in_long_begin (lsquic_packet_in_t *packet_in,
46            size_t length, int is_server, struct packin_parse_state *state)
47{
48    const unsigned char *p = packet_in->pi_data;
49    const unsigned char *const end = p + length;
50    lsquic_ver_tag_t tag;
51    enum header_type header_type;
52    unsigned dcil, scil, packet_len;
53    int verneg;
54    enum lsquic_version version;
55    unsigned char first_byte;
56    const unsigned cid_len = 8;
57
58    if (length < 6)
59        return -1;
60    first_byte = *p++;
61
62    memcpy(&tag, p, 4);
63    p += 4;
64    verneg = 0 == tag;
65    if (!verneg)
66    {
67        version = lsquic_tag2ver(tag);
68        if (version == LSQVER_044)
69        {
70            header_type = bin_2_header_type_Q044[ first_byte ];
71            if (!header_type)
72                return -1;
73        }
74        else
75            header_type = bits2ht[ (first_byte >> 4) & 3 ];
76    }
77    else
78    {
79        header_type = HETY_VERNEG;
80#ifdef WIN32
81        /* Useless initialization */
82        version = -1;
83#endif
84    }
85
86    packet_in->pi_header_type = header_type;
87
88    dcil = p[0] >> 4;
89    if (dcil)
90        dcil += 3;
91    scil = p[0] & 0xF;
92    if (scil)
93        scil += 3;
94    ++p;
95
96    /* Chromium comments state that the client sends packets with destination
97     * CID of 8 bytes and source CID of 0 bytes and the server does it the
98     * other way around.
99     *
100     * XXX When IETF branch is merged, this check for Q044 and higher will
101     * have to be moved to the pf_parse_packet_in_finish().
102     */
103    if (is_server)
104    {
105        if (!(dcil == cid_len && scil == 0))
106            return -1;
107    }
108    else
109    {
110        if (!(dcil == 0 && scil == cid_len))
111            return -1;
112    }
113
114    if (!verneg)
115    {
116        if (version == LSQVER_044)
117        {
118            packet_in->pi_flags |= GQUIC_PACKNO_LEN_4 << PIBIT_BITS_SHIFT;
119            packet_len = 4;
120        }
121        else
122        {
123            packet_in->pi_flags |= (first_byte & 3) << PIBIT_BITS_SHIFT;
124            packet_len = 1 + (first_byte & 3);
125        }
126        if (end - p < (ptrdiff_t) (dcil + scil + packet_len))
127            return -1;
128    }
129    else
130    {
131        /* Need at least one version in the version array: add 4 */
132        if (end - p < (ptrdiff_t) (dcil + scil + 4))
133            return -1;
134#ifdef WIN32
135        /* Useless initialization */
136        packet_len = 0
137#endif
138    }
139
140    memcpy(&packet_in->pi_conn_id, p, cid_len);
141    p += cid_len;
142    packet_in->pi_flags |= PI_CONN_ID;
143
144    packet_in->pi_packno       = 0;
145
146    if (!verneg)
147    {
148        state->pps_p      = p;
149        state->pps_nbytes = packet_len;
150        p += packet_len;
151        packet_in->pi_quic_ver = 1;
152        if (is_server || HETY_0RTT != header_type)
153            packet_in->pi_nonce = 0;
154        else
155        {
156            packet_in->pi_nonce = p - packet_in->pi_data;
157            p += 32;
158        }
159    }
160    else
161    {
162        if ((end - p) & 3)
163            return -1;
164        state->pps_p      = NULL;
165        state->pps_nbytes = 0;
166        packet_in->pi_quic_ver = p - packet_in->pi_data;
167        p = packet_in->pi_data + length;
168        packet_in->pi_nonce = 0;
169    }
170
171    packet_in->pi_header_sz    = p - packet_in->pi_data;
172    packet_in->pi_frame_types  = 0;
173    packet_in->pi_data_sz      = length;
174    packet_in->pi_refcnt       = 0;
175    packet_in->pi_received     = 0;
176
177    return 0;
178}
179
180
181int
182lsquic_iquic_parse_packet_in_short_begin (lsquic_packet_in_t *packet_in,
183            size_t length, int is_server, struct packin_parse_state *state)
184{
185    const unsigned char *p = packet_in->pi_data;
186    const unsigned char *const pend = packet_in->pi_data + length;
187    unsigned cid_len = 8;   /* XXX this will need to be passed in */
188    unsigned packet_len;
189
190    if (*p & 0x40)  /* Q046 and higher */
191        packet_len = 1 + (*p & 3);
192    else
193    {
194        if ((*p & 0x30) != 0x30 || (*p & 3) == 3)
195            return -1;
196        packet_len = 1 << (*p & 3);
197    }
198
199    if (pend - p < (ptrdiff_t) (1 + cid_len + packet_len))
200        return -1;
201
202    packet_in->pi_flags |= (*p & 3) << PIBIT_BITS_SHIFT;
203    ++p;
204
205    if (is_server)
206    {
207        memcpy(&packet_in->pi_conn_id, p, cid_len);
208        p += cid_len;
209        packet_in->pi_flags |= PI_CONN_ID;
210    }
211
212    /* We could read in the packet number here, but we choose to do it in
213     * the finish() call instead.
214     */
215    packet_in->pi_packno       = 0;
216    state->pps_p      = p;
217    state->pps_nbytes = packet_len;
218    p += packet_len;
219
220    packet_in->pi_header_type  = HETY_NOT_SET;
221    packet_in->pi_quic_ver     = 0;
222    packet_in->pi_nonce        = 0;
223    packet_in->pi_header_sz    = p - packet_in->pi_data;
224    packet_in->pi_frame_types  = 0;
225    packet_in->pi_data_sz      = length;
226    packet_in->pi_refcnt       = 0;
227    packet_in->pi_received     = 0;
228
229    return 0;
230}
231
232
233