lsquic_parse_iquic_common.c revision e5d4bc6d
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 87 packet_in->pi_header_type = header_type; 88 89 dcil = p[0] >> 4; 90 if (dcil) 91 dcil += 3; 92 scil = p[0] & 0xF; 93 if (scil) 94 scil += 3; 95 ++p; 96 97 /* Chromium comments state that the client sends packets with destination 98 * CID of 8 bytes and source CID of 0 bytes and the server does it the 99 * other way around. 100 * 101 * XXX When IETF branch is merged, this check for Q044 and higher will 102 * have to be moved to the pf_parse_packet_in_finish(). 103 */ 104 if (is_server) 105 { 106 if (!(dcil == cid_len && scil == 0)) 107 return -1; 108 } 109 else 110 { 111 if (!(dcil == 0 && scil == cid_len)) 112 return -1; 113 } 114 115 if (!verneg) 116 { 117 if (version == LSQVER_044) 118 { 119 packet_in->pi_flags |= GQUIC_PACKNO_LEN_4 << PIBIT_BITS_SHIFT; 120 packet_len = 4; 121 } 122 else 123 { 124 packet_in->pi_flags |= (first_byte & 3) << PIBIT_BITS_SHIFT; 125 packet_len = 1 + (first_byte & 3); 126 } 127 if (end - p < (ptrdiff_t) (dcil + scil + packet_len)) 128 return -1; 129 } 130 else 131 { 132 /* Need at least one version in the version array: add 4 */ 133 if (end - p < (ptrdiff_t) (dcil + scil + 4)) 134 return -1; 135#ifdef WIN32 136 /* Useless initialization: */ 137 packet_len = 0; 138#endif 139 } 140 141 memcpy(&packet_in->pi_conn_id, p, cid_len); 142 p += cid_len; 143 packet_in->pi_flags |= PI_CONN_ID; 144 145 packet_in->pi_packno = 0; 146 147 if (!verneg) 148 { 149 state->pps_p = p; 150 state->pps_nbytes = packet_len; 151 p += packet_len; 152 packet_in->pi_quic_ver = 1; 153 if (is_server || HETY_0RTT != header_type) 154 packet_in->pi_nonce = 0; 155 else 156 { 157 packet_in->pi_nonce = p - packet_in->pi_data; 158 p += 32; 159 } 160 } 161 else 162 { 163 if ((end - p) & 3) 164 return -1; 165 state->pps_p = NULL; 166 state->pps_nbytes = 0; 167 packet_in->pi_quic_ver = p - packet_in->pi_data; 168 p = packet_in->pi_data + length; 169 packet_in->pi_nonce = 0; 170 } 171 172 packet_in->pi_header_sz = p - packet_in->pi_data; 173 packet_in->pi_frame_types = 0; 174 packet_in->pi_data_sz = length; 175 packet_in->pi_refcnt = 0; 176 packet_in->pi_received = 0; 177 178 return 0; 179} 180 181 182int 183lsquic_iquic_parse_packet_in_short_begin (lsquic_packet_in_t *packet_in, 184 size_t length, int is_server, struct packin_parse_state *state) 185{ 186 const unsigned char *p = packet_in->pi_data; 187 const unsigned char *const pend = packet_in->pi_data + length; 188 unsigned cid_len = 8; /* XXX this will need to be passed in */ 189 unsigned packet_len; 190 191 if (*p & 0x40) /* Q046 and higher */ 192 packet_len = 1 + (*p & 3); 193 else 194 { 195 if ((*p & 0x30) != 0x30 || (*p & 3) == 3) 196 return -1; 197 packet_len = 1 << (*p & 3); 198 } 199 200 if (pend - p < (ptrdiff_t) (1 + cid_len + packet_len)) 201 return -1; 202 203 packet_in->pi_flags |= (*p & 3) << PIBIT_BITS_SHIFT; 204 ++p; 205 206 if (is_server) 207 { 208 memcpy(&packet_in->pi_conn_id, p, cid_len); 209 p += cid_len; 210 packet_in->pi_flags |= PI_CONN_ID; 211 } 212 213 /* We could read in the packet number here, but we choose to do it in 214 * the finish() call instead. 215 */ 216 packet_in->pi_packno = 0; 217 state->pps_p = p; 218 state->pps_nbytes = packet_len; 219 p += packet_len; 220 221 packet_in->pi_header_type = HETY_NOT_SET; 222 packet_in->pi_quic_ver = 0; 223 packet_in->pi_nonce = 0; 224 packet_in->pi_header_sz = p - packet_in->pi_data; 225 packet_in->pi_frame_types = 0; 226 packet_in->pi_data_sz = length; 227 packet_in->pi_refcnt = 0; 228 packet_in->pi_received = 0; 229 230 return 0; 231} 232 233 234