lsquic_parse_iquic_common.c revision 06b2a236
1/* Copyright (c) 2017 - 2021 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_DATAGRAM, 293 [0x31] = QUIC_FRAME_DATAGRAM, 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