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