lsquic_parse_iquic_common.c revision feca77f5
1/* Copyright (c) 2017 - 2020 LiteSpeed Technologies Inc.  See LICENSE. */
2/*
3 * Parsing routines shared by all IETF QUIC versions.
4 */
5
6#include <assert.h>
7#include <stddef.h>
8#include <stdint.h>
9#include <string.h>
10#include <sys/queue.h>
11#include <sys/types.h>
12
13#include <openssl/rand.h>
14
15#include "lsquic_types.h"
16#include "lsquic_int_types.h"
17#include "lsquic_packet_common.h"
18#include "lsquic_packet_in.h"
19#include "lsquic_parse_common.h"
20#include "lsquic_parse.h"
21#include "lsquic_version.h"
22#include "lsquic.h"
23#include "lsquic_logger.h"
24#include "lsquic_byteswap.h"
25#include "lsquic_varint.h"
26#include "lsquic_enc_sess.h"
27#include "lsquic_tokgen.h"
28#include "lsquic_mm.h"
29#include "lsquic_engine_public.h"
30#include "lsquic_ietf.h"
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
43int
44lsquic_Q046_parse_packet_in_long_begin (struct lsquic_packet_in *packet_in,
45                size_t length, int is_server, unsigned cid_len,
46                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    unsigned char first_byte;
55    lsquic_packno_t packno;
56
57    if (length < 6)
58        return -1;
59    first_byte = *p++;
60
61    memcpy(&tag, p, 4);
62    p += 4;
63    verneg = 0 == tag;
64    if (!verneg)
65        header_type = bits2ht[ (first_byte >> 4) & 3 ];
66    else
67        header_type = HETY_VERNEG;
68
69    packet_in->pi_header_type = header_type;
70
71    dcil = p[0] >> 4;
72    if (dcil)
73        dcil += 3;
74    scil = p[0] & 0xF;
75    if (scil)
76        scil += 3;
77    ++p;
78
79    /* Chromium comments state that the client sends packets with destination
80     * CID of 8 bytes and source CID of 0 bytes and the server does it the
81     * other way around.
82     */
83    if (is_server)
84    {
85        if (!(dcil == cid_len && scil == 0))
86            return -1;
87    }
88    else
89    if (!(dcil == 0 && scil == cid_len))
90        return -1;
91
92    if (!verneg)
93    {
94        packet_in->pi_flags |= (first_byte & 3) << PIBIT_BITS_SHIFT;
95        packet_len = 1 + (first_byte & 3);
96        if (end - p < (ptrdiff_t) (dcil + scil + packet_len))
97            return -1;
98    }
99    else
100    {
101        /* Need at least one version in the version array: add 4 */
102        if (end - p < (ptrdiff_t) (dcil + scil + 4))
103            return -1;
104#ifdef WIN32
105        /* Useless initialization: */
106        packet_len = 0;
107#endif
108    }
109
110    memcpy(&packet_in->pi_dcid.idbuf, p, cid_len);
111    packet_in->pi_dcid.len = cid_len;
112    p += cid_len;
113    packet_in->pi_flags |= PI_CONN_ID;
114
115    if (!verneg)
116    {
117        READ_UINT(packno, 64, p, packet_len);
118        packet_in->pi_packno = packno;
119        p += packet_len;
120        packet_in->pi_quic_ver = 1;
121        if (is_server || HETY_0RTT != header_type)
122            packet_in->pi_nonce = 0;
123        else
124        {
125            packet_in->pi_nonce = p - packet_in->pi_data;
126            p += 32;
127        }
128    }
129    else
130    {
131        if (p >= end || (3 & (uintptr_t) (end - p)))
132            return -1;
133        packet_in->pi_quic_ver = p - packet_in->pi_data;
134        p = end;
135    }
136
137    packet_in->pi_header_sz    = p - packet_in->pi_data;
138    packet_in->pi_frame_types  = 0;
139    packet_in->pi_data_sz      = length;
140    packet_in->pi_refcnt       = 0;
141    packet_in->pi_received     = 0;
142
143    return 0;
144}
145
146
147int
148lsquic_Q046_parse_packet_in_short_begin (lsquic_packet_in_t *packet_in,
149            size_t length, int is_server, unsigned cid_len,
150            struct packin_parse_state *state)
151{
152    const unsigned char *p = packet_in->pi_data;
153    const unsigned char *const pend = packet_in->pi_data + length;
154    unsigned packet_len, header_len;
155    lsquic_packno_t packno;
156
157    if (*p & 0x40)  /* Q046 and higher */
158        packet_len = 1 + (*p & 3);
159    else
160        return -1;
161
162    if (is_server)
163        header_len = 1 + cid_len + packet_len;
164    else
165        header_len = 1 + packet_len;
166
167    if (pend - p < (ptrdiff_t) header_len)
168        return -1;
169
170    packet_in->pi_flags |= (*p & 3) << PIBIT_BITS_SHIFT;
171    ++p;
172    if (is_server)
173    {
174        memcpy(packet_in->pi_dcid.idbuf, packet_in->pi_data + 1, cid_len);
175        packet_in->pi_dcid.len = cid_len;
176        packet_in->pi_flags |= PI_CONN_ID;
177        p += cid_len;
178    }
179
180    READ_UINT(packno, 64, p, packet_len);
181    packet_in->pi_packno = packno;
182    p += packet_len;
183
184    packet_in->pi_header_type  = HETY_NOT_SET;
185    packet_in->pi_quic_ver     = 0;
186    packet_in->pi_nonce        = 0;
187    packet_in->pi_header_sz    = p - packet_in->pi_data;
188    packet_in->pi_frame_types  = 0;
189    packet_in->pi_data_sz      = length;
190    packet_in->pi_refcnt       = 0;
191    packet_in->pi_received     = 0;
192
193    return 0;
194}
195
196
197/* This is a bare-bones version of lsquic_Q046_parse_packet_in_long_begin()
198 */
199int
200lsquic_is_valid_iquic_hs_packet (const unsigned char *buf, size_t length,
201                                                        lsquic_ver_tag_t *tagp)
202{
203    const unsigned char *p = buf;
204    const unsigned char *const end = p + length;
205    lsquic_ver_tag_t tag;
206    unsigned dcil, scil, packet_len;
207    unsigned char first_byte;
208    const unsigned cid_len = 8;
209
210    if (length < 6)
211        return 0;
212    first_byte = *p++;
213
214    memcpy(&tag, p, 4);
215    p += 4;
216    if (0 == tag)
217        return 0;   /* Client never sends version negotiation */
218
219    dcil = p[0] >> 4;
220    if (dcil)
221        dcil += 3;
222    scil = p[0] & 0xF;
223    if (scil)
224        scil += 3;
225    ++p;
226
227    if (!(dcil == cid_len && scil == 0))
228        return 0;
229
230    packet_len = first_byte & 3;
231
232    if (end - p >= (ptrdiff_t) (dcil + scil + packet_len))
233    {
234        *tagp = tag;
235        return 1;
236    }
237    else
238        return 0;
239}
240
241
242const enum quic_frame_type lsquic_iquic_byte2type[0x40] =
243{
244    [0x00] = QUIC_FRAME_PADDING,
245    [0x01] = QUIC_FRAME_PING,
246    [0x02] = QUIC_FRAME_ACK,
247    [0x03] = QUIC_FRAME_ACK,
248    [0x04] = QUIC_FRAME_RST_STREAM,
249    [0x05] = QUIC_FRAME_STOP_SENDING,
250    [0x06] = QUIC_FRAME_CRYPTO,
251    [0x07] = QUIC_FRAME_NEW_TOKEN,
252    [0x08] = QUIC_FRAME_STREAM,
253    [0x09] = QUIC_FRAME_STREAM,
254    [0x0A] = QUIC_FRAME_STREAM,
255    [0x0B] = QUIC_FRAME_STREAM,
256    [0x0C] = QUIC_FRAME_STREAM,
257    [0x0D] = QUIC_FRAME_STREAM,
258    [0x0E] = QUIC_FRAME_STREAM,
259    [0x0F] = QUIC_FRAME_STREAM,
260    [0x10] = QUIC_FRAME_MAX_DATA,
261    [0x11] = QUIC_FRAME_MAX_STREAM_DATA,
262    [0x12] = QUIC_FRAME_MAX_STREAMS,
263    [0x13] = QUIC_FRAME_MAX_STREAMS,
264    [0x14] = QUIC_FRAME_BLOCKED,
265    [0x15] = QUIC_FRAME_STREAM_BLOCKED,
266    [0x16] = QUIC_FRAME_STREAMS_BLOCKED,
267    [0x17] = QUIC_FRAME_STREAMS_BLOCKED,
268    [0x18] = QUIC_FRAME_NEW_CONNECTION_ID,
269    [0x19] = QUIC_FRAME_RETIRE_CONNECTION_ID,
270    [0x1A] = QUIC_FRAME_PATH_CHALLENGE,
271    [0x1B] = QUIC_FRAME_PATH_RESPONSE,
272    [0x1C] = QUIC_FRAME_CONNECTION_CLOSE,
273    [0x1D] = QUIC_FRAME_CONNECTION_CLOSE,
274    [0x1E] = QUIC_FRAME_HANDSHAKE_DONE,
275    [0x1F] = QUIC_FRAME_INVALID,
276    [0x20] = QUIC_FRAME_INVALID,
277    [0x21] = QUIC_FRAME_INVALID,
278    [0x22] = QUIC_FRAME_INVALID,
279    [0x23] = QUIC_FRAME_INVALID,
280    [0x24] = QUIC_FRAME_INVALID,
281    [0x25] = QUIC_FRAME_INVALID,
282    [0x26] = QUIC_FRAME_INVALID,
283    [0x27] = QUIC_FRAME_INVALID,
284    [0x28] = QUIC_FRAME_INVALID,
285    [0x29] = QUIC_FRAME_INVALID,
286    [0x2A] = QUIC_FRAME_INVALID,
287    [0x2B] = QUIC_FRAME_INVALID,
288    [0x2C] = QUIC_FRAME_INVALID,
289    [0x2D] = QUIC_FRAME_INVALID,
290    [0x2E] = QUIC_FRAME_INVALID,
291    [0x2F] = QUIC_FRAME_INVALID,
292    [0x30] = QUIC_FRAME_INVALID,
293    [0x31] = QUIC_FRAME_INVALID,
294    [0x32] = QUIC_FRAME_INVALID,
295    [0x33] = QUIC_FRAME_INVALID,
296    [0x34] = QUIC_FRAME_INVALID,
297    [0x35] = QUIC_FRAME_INVALID,
298    [0x36] = QUIC_FRAME_INVALID,
299    [0x37] = QUIC_FRAME_INVALID,
300    [0x38] = QUIC_FRAME_INVALID,
301    [0x39] = QUIC_FRAME_INVALID,
302    [0x3A] = QUIC_FRAME_INVALID,
303    [0x3B] = QUIC_FRAME_INVALID,
304    [0x3C] = QUIC_FRAME_INVALID,
305    [0x3D] = QUIC_FRAME_INVALID,
306    [0x3E] = QUIC_FRAME_INVALID,
307    [0x3F] = QUIC_FRAME_INVALID,
308};
309
310
311#if __GNUC__
312#   define popcount __builtin_popcount
313#else
314static int
315popcount (unsigned v)
316{
317    int count, i;
318    for (i = 0, count = 0; i < sizeof(v) * 8; ++i)
319        if (v & (1 << i))
320            ++count;
321    return count;
322}
323
324
325#endif
326
327
328int
329lsquic_Q046_gen_ver_nego_pkt (unsigned char *buf, size_t bufsz,
330         const lsquic_cid_t *scid, const lsquic_cid_t *dcid, unsigned versions,
331         uint8_t rand)
332{
333    unsigned slen, dlen;
334    size_t need;
335    int r;
336
337    need = 1 /* Type */ + 4 /* Packet number */ + 1 /* SCIL */
338                        + scid->len + dcid->len + popcount(versions) * 4;
339
340    if (need > bufsz)
341        return -1;
342
343    *buf++ = 0x80 | 0x40 | rand;
344    memset(buf, 0, 4);
345    buf += 4;
346
347    /* From [draft-ietf-quic-transport-11], Section 4.3:
348     *
349     *  The server MUST include the value from the Source Connection ID field
350     *  of the packet it receives in the Destination Connection ID field.
351     *  The value for Source Connection ID MUST be copied from the
352     *  Destination Connection ID of the received packet, which is initially
353     *  randomly selected by a client.  Echoing both connection IDs gives
354     *  clients some assurance that the server received the packet and that
355     *  the Version Negotiation packet was not generated by an off-path
356     *  attacker.
357     */
358
359    dlen = dcid->len;
360    if (dlen)
361        dlen -= 3;
362    slen = scid->len;
363    if (slen)
364        slen -= 3;
365    *buf++ = (dlen << 4) | slen;
366
367    memcpy(buf, dcid->idbuf, dcid->len);
368    buf += dcid->len;
369    memcpy(buf, scid->idbuf, scid->len);
370    buf += scid->len;
371
372    r = lsquic_gen_ver_tags(buf, bufsz - 1 - 4 - 1 - dcid->len - scid->len,
373                                                                    versions);
374    if (r < 0)
375        return -1;
376    assert((unsigned) r == popcount(versions) * 4u);
377
378    return need;
379}
380
381
382