lsquic_parse_iquic_common.c revision b4069a69
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