1 /*
2 * ngtcp2
3 *
4 * Copyright (c) 2017 ngtcp2 contributors
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 */
25 #include "ngtcp2_crypto.h"
26
27 #include <string.h>
28 #include <assert.h>
29
30 #include "ngtcp2_str.h"
31 #include "ngtcp2_conv.h"
32 #include "ngtcp2_conn.h"
33 #include "ngtcp2_net.h"
34
ngtcp2_crypto_km_new(ngtcp2_crypto_km ** pckm,const uint8_t * secret,size_t secretlen,const ngtcp2_crypto_aead_ctx * aead_ctx,const uint8_t * iv,size_t ivlen,const ngtcp2_mem * mem)35 int ngtcp2_crypto_km_new(ngtcp2_crypto_km **pckm, const uint8_t *secret,
36 size_t secretlen,
37 const ngtcp2_crypto_aead_ctx *aead_ctx,
38 const uint8_t *iv, size_t ivlen,
39 const ngtcp2_mem *mem) {
40 int rv = ngtcp2_crypto_km_nocopy_new(pckm, secretlen, ivlen, mem);
41 if (rv != 0) {
42 return rv;
43 }
44
45 if (secretlen) {
46 memcpy((*pckm)->secret.base, secret, secretlen);
47 }
48 if (aead_ctx) {
49 (*pckm)->aead_ctx = *aead_ctx;
50 }
51 memcpy((*pckm)->iv.base, iv, ivlen);
52
53 return 0;
54 }
55
ngtcp2_crypto_km_nocopy_new(ngtcp2_crypto_km ** pckm,size_t secretlen,size_t ivlen,const ngtcp2_mem * mem)56 int ngtcp2_crypto_km_nocopy_new(ngtcp2_crypto_km **pckm, size_t secretlen,
57 size_t ivlen, const ngtcp2_mem *mem) {
58 size_t len;
59 uint8_t *p;
60
61 len = sizeof(ngtcp2_crypto_km) + secretlen + ivlen;
62
63 *pckm = ngtcp2_mem_malloc(mem, len);
64 if (*pckm == NULL) {
65 return NGTCP2_ERR_NOMEM;
66 }
67
68 p = (uint8_t *)(*pckm) + sizeof(ngtcp2_crypto_km);
69 (*pckm)->secret.base = p;
70 (*pckm)->secret.len = secretlen;
71 p += secretlen;
72 (*pckm)->iv.base = p;
73 (*pckm)->iv.len = ivlen;
74 (*pckm)->aead_ctx.native_handle = NULL;
75 (*pckm)->pkt_num = -1;
76 (*pckm)->use_count = 0;
77 (*pckm)->flags = NGTCP2_CRYPTO_KM_FLAG_NONE;
78
79 return 0;
80 }
81
ngtcp2_crypto_km_del(ngtcp2_crypto_km * ckm,const ngtcp2_mem * mem)82 void ngtcp2_crypto_km_del(ngtcp2_crypto_km *ckm, const ngtcp2_mem *mem) {
83 if (ckm == NULL) {
84 return;
85 }
86
87 ngtcp2_mem_free(mem, ckm);
88 }
89
ngtcp2_crypto_create_nonce(uint8_t * dest,const uint8_t * iv,size_t ivlen,int64_t pkt_num)90 void ngtcp2_crypto_create_nonce(uint8_t *dest, const uint8_t *iv, size_t ivlen,
91 int64_t pkt_num) {
92 size_t i;
93 uint64_t n;
94
95 assert(ivlen >= 8);
96
97 memcpy(dest, iv, ivlen);
98 n = ngtcp2_htonl64((uint64_t)pkt_num);
99
100 for (i = 0; i < 8; ++i) {
101 dest[ivlen - 8 + i] ^= ((uint8_t *)&n)[i];
102 }
103 }
104
105 /*
106 * varint_paramlen returns the length of a single transport parameter
107 * which has variable integer in its parameter.
108 */
varint_paramlen(ngtcp2_transport_param_id id,uint64_t param)109 static size_t varint_paramlen(ngtcp2_transport_param_id id, uint64_t param) {
110 size_t valuelen = ngtcp2_put_varint_len(param);
111 return ngtcp2_put_varint_len(id) + ngtcp2_put_varint_len(valuelen) + valuelen;
112 }
113
114 /*
115 * write_varint_param writes parameter |id| of the given |value| in
116 * varint encoding. It returns p + the number of bytes written.
117 */
write_varint_param(uint8_t * p,ngtcp2_transport_param_id id,uint64_t value)118 static uint8_t *write_varint_param(uint8_t *p, ngtcp2_transport_param_id id,
119 uint64_t value) {
120 p = ngtcp2_put_varint(p, id);
121 p = ngtcp2_put_varint(p, ngtcp2_put_varint_len(value));
122 return ngtcp2_put_varint(p, value);
123 }
124
125 /*
126 * cid_paramlen returns the length of a single transport parameter
127 * which has |cid| as value.
128 */
cid_paramlen(ngtcp2_transport_param_id id,const ngtcp2_cid * cid)129 static size_t cid_paramlen(ngtcp2_transport_param_id id,
130 const ngtcp2_cid *cid) {
131 return ngtcp2_put_varint_len(id) + ngtcp2_put_varint_len(cid->datalen) +
132 cid->datalen;
133 }
134
135 /*
136 * write_cid_param writes parameter |id| of the given |cid|. It
137 * returns p + the number of bytes written.
138 */
write_cid_param(uint8_t * p,ngtcp2_transport_param_id id,const ngtcp2_cid * cid)139 static uint8_t *write_cid_param(uint8_t *p, ngtcp2_transport_param_id id,
140 const ngtcp2_cid *cid) {
141 assert(cid->datalen == 0 || cid->datalen >= NGTCP2_MIN_CIDLEN);
142 assert(cid->datalen <= NGTCP2_MAX_CIDLEN);
143
144 p = ngtcp2_put_varint(p, id);
145 p = ngtcp2_put_varint(p, cid->datalen);
146 if (cid->datalen) {
147 p = ngtcp2_cpymem(p, cid->data, cid->datalen);
148 }
149 return p;
150 }
151
152 static const uint8_t empty_address[16];
153
ngtcp2_encode_transport_params_versioned(uint8_t * dest,size_t destlen,ngtcp2_transport_params_type exttype,int transport_params_version,const ngtcp2_transport_params * params)154 ngtcp2_ssize ngtcp2_encode_transport_params_versioned(
155 uint8_t *dest, size_t destlen, ngtcp2_transport_params_type exttype,
156 int transport_params_version, const ngtcp2_transport_params *params) {
157 uint8_t *p;
158 size_t len = 0;
159 /* For some reason, gcc 7.3.0 requires this initialization. */
160 size_t preferred_addrlen = 0;
161 size_t version_infolen = 0;
162 (void)transport_params_version;
163
164 switch (exttype) {
165 case NGTCP2_TRANSPORT_PARAMS_TYPE_CLIENT_HELLO:
166 break;
167 case NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS:
168 len +=
169 cid_paramlen(NGTCP2_TRANSPORT_PARAM_ORIGINAL_DESTINATION_CONNECTION_ID,
170 ¶ms->original_dcid);
171
172 if (params->stateless_reset_token_present) {
173 len +=
174 ngtcp2_put_varint_len(NGTCP2_TRANSPORT_PARAM_STATELESS_RESET_TOKEN) +
175 ngtcp2_put_varint_len(NGTCP2_STATELESS_RESET_TOKENLEN) +
176 NGTCP2_STATELESS_RESET_TOKENLEN;
177 }
178 if (params->preferred_address_present) {
179 assert(params->preferred_address.cid.datalen >= NGTCP2_MIN_CIDLEN);
180 assert(params->preferred_address.cid.datalen <= NGTCP2_MAX_CIDLEN);
181 preferred_addrlen = 4 /* ipv4Address */ + 2 /* ipv4Port */ +
182 16 /* ipv6Address */ + 2 /* ipv6Port */
183 + 1 +
184 params->preferred_address.cid.datalen /* CID */ +
185 NGTCP2_STATELESS_RESET_TOKENLEN;
186 len += ngtcp2_put_varint_len(NGTCP2_TRANSPORT_PARAM_PREFERRED_ADDRESS) +
187 ngtcp2_put_varint_len(preferred_addrlen) + preferred_addrlen;
188 }
189 if (params->retry_scid_present) {
190 len += cid_paramlen(NGTCP2_TRANSPORT_PARAM_RETRY_SOURCE_CONNECTION_ID,
191 ¶ms->retry_scid);
192 }
193 break;
194 default:
195 return NGTCP2_ERR_INVALID_ARGUMENT;
196 }
197
198 len += cid_paramlen(NGTCP2_TRANSPORT_PARAM_INITIAL_SOURCE_CONNECTION_ID,
199 ¶ms->initial_scid);
200
201 if (params->initial_max_stream_data_bidi_local) {
202 len += varint_paramlen(
203 NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL,
204 params->initial_max_stream_data_bidi_local);
205 }
206 if (params->initial_max_stream_data_bidi_remote) {
207 len += varint_paramlen(
208 NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE,
209 params->initial_max_stream_data_bidi_remote);
210 }
211 if (params->initial_max_stream_data_uni) {
212 len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_UNI,
213 params->initial_max_stream_data_uni);
214 }
215 if (params->initial_max_data) {
216 len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_DATA,
217 params->initial_max_data);
218 }
219 if (params->initial_max_streams_bidi) {
220 len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_BIDI,
221 params->initial_max_streams_bidi);
222 }
223 if (params->initial_max_streams_uni) {
224 len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_UNI,
225 params->initial_max_streams_uni);
226 }
227 if (params->max_udp_payload_size !=
228 NGTCP2_DEFAULT_MAX_RECV_UDP_PAYLOAD_SIZE) {
229 len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_MAX_UDP_PAYLOAD_SIZE,
230 params->max_udp_payload_size);
231 }
232 if (params->ack_delay_exponent != NGTCP2_DEFAULT_ACK_DELAY_EXPONENT) {
233 len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_ACK_DELAY_EXPONENT,
234 params->ack_delay_exponent);
235 }
236 if (params->disable_active_migration) {
237 len +=
238 ngtcp2_put_varint_len(NGTCP2_TRANSPORT_PARAM_DISABLE_ACTIVE_MIGRATION) +
239 ngtcp2_put_varint_len(0);
240 }
241 if (params->max_ack_delay != NGTCP2_DEFAULT_MAX_ACK_DELAY) {
242 len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_MAX_ACK_DELAY,
243 params->max_ack_delay / NGTCP2_MILLISECONDS);
244 }
245 if (params->max_idle_timeout) {
246 len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_MAX_IDLE_TIMEOUT,
247 params->max_idle_timeout / NGTCP2_MILLISECONDS);
248 }
249 if (params->active_connection_id_limit &&
250 params->active_connection_id_limit !=
251 NGTCP2_DEFAULT_ACTIVE_CONNECTION_ID_LIMIT) {
252 len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_ACTIVE_CONNECTION_ID_LIMIT,
253 params->active_connection_id_limit);
254 }
255 if (params->max_datagram_frame_size) {
256 len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_MAX_DATAGRAM_FRAME_SIZE,
257 params->max_datagram_frame_size);
258 }
259 if (params->grease_quic_bit) {
260 len += ngtcp2_put_varint_len(NGTCP2_TRANSPORT_PARAM_GREASE_QUIC_BIT) +
261 ngtcp2_put_varint_len(0);
262 }
263 if (params->version_info_present) {
264 version_infolen = sizeof(uint32_t) + params->version_info.other_versionslen;
265 len += ngtcp2_put_varint_len(
266 NGTCP2_TRANSPORT_PARAM_VERSION_INFORMATION_DRAFT) +
267 ngtcp2_put_varint_len(version_infolen) + version_infolen;
268 }
269
270 if (dest == NULL && destlen == 0) {
271 return (ngtcp2_ssize)len;
272 }
273
274 if (destlen < len) {
275 return NGTCP2_ERR_NOBUF;
276 }
277
278 p = dest;
279
280 if (exttype == NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS) {
281 p = write_cid_param(
282 p, NGTCP2_TRANSPORT_PARAM_ORIGINAL_DESTINATION_CONNECTION_ID,
283 ¶ms->original_dcid);
284
285 if (params->stateless_reset_token_present) {
286 p = ngtcp2_put_varint(p, NGTCP2_TRANSPORT_PARAM_STATELESS_RESET_TOKEN);
287 p = ngtcp2_put_varint(p, sizeof(params->stateless_reset_token));
288 p = ngtcp2_cpymem(p, params->stateless_reset_token,
289 sizeof(params->stateless_reset_token));
290 }
291 if (params->preferred_address_present) {
292 p = ngtcp2_put_varint(p, NGTCP2_TRANSPORT_PARAM_PREFERRED_ADDRESS);
293 p = ngtcp2_put_varint(p, preferred_addrlen);
294
295 if (params->preferred_address.ipv4_present) {
296 p = ngtcp2_cpymem(p, params->preferred_address.ipv4_addr,
297 sizeof(params->preferred_address.ipv4_addr));
298 p = ngtcp2_put_uint16be(p, params->preferred_address.ipv4_port);
299 } else {
300 p = ngtcp2_cpymem(p, empty_address,
301 sizeof(params->preferred_address.ipv4_addr));
302 p = ngtcp2_put_uint16be(p, 0);
303 }
304
305 if (params->preferred_address.ipv6_present) {
306 p = ngtcp2_cpymem(p, params->preferred_address.ipv6_addr,
307 sizeof(params->preferred_address.ipv6_addr));
308 p = ngtcp2_put_uint16be(p, params->preferred_address.ipv6_port);
309 } else {
310 p = ngtcp2_cpymem(p, empty_address,
311 sizeof(params->preferred_address.ipv6_addr));
312 p = ngtcp2_put_uint16be(p, 0);
313 }
314
315 *p++ = (uint8_t)params->preferred_address.cid.datalen;
316 if (params->preferred_address.cid.datalen) {
317 p = ngtcp2_cpymem(p, params->preferred_address.cid.data,
318 params->preferred_address.cid.datalen);
319 }
320 p = ngtcp2_cpymem(
321 p, params->preferred_address.stateless_reset_token,
322 sizeof(params->preferred_address.stateless_reset_token));
323 }
324 if (params->retry_scid_present) {
325 p = write_cid_param(p, NGTCP2_TRANSPORT_PARAM_RETRY_SOURCE_CONNECTION_ID,
326 ¶ms->retry_scid);
327 }
328 }
329
330 p = write_cid_param(p, NGTCP2_TRANSPORT_PARAM_INITIAL_SOURCE_CONNECTION_ID,
331 ¶ms->initial_scid);
332
333 if (params->initial_max_stream_data_bidi_local) {
334 p = write_varint_param(
335 p, NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL,
336 params->initial_max_stream_data_bidi_local);
337 }
338
339 if (params->initial_max_stream_data_bidi_remote) {
340 p = write_varint_param(
341 p, NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE,
342 params->initial_max_stream_data_bidi_remote);
343 }
344
345 if (params->initial_max_stream_data_uni) {
346 p = write_varint_param(p,
347 NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_UNI,
348 params->initial_max_stream_data_uni);
349 }
350
351 if (params->initial_max_data) {
352 p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_DATA,
353 params->initial_max_data);
354 }
355
356 if (params->initial_max_streams_bidi) {
357 p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_BIDI,
358 params->initial_max_streams_bidi);
359 }
360
361 if (params->initial_max_streams_uni) {
362 p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_UNI,
363 params->initial_max_streams_uni);
364 }
365
366 if (params->max_udp_payload_size !=
367 NGTCP2_DEFAULT_MAX_RECV_UDP_PAYLOAD_SIZE) {
368 p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_MAX_UDP_PAYLOAD_SIZE,
369 params->max_udp_payload_size);
370 }
371
372 if (params->ack_delay_exponent != NGTCP2_DEFAULT_ACK_DELAY_EXPONENT) {
373 p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_ACK_DELAY_EXPONENT,
374 params->ack_delay_exponent);
375 }
376
377 if (params->disable_active_migration) {
378 p = ngtcp2_put_varint(p, NGTCP2_TRANSPORT_PARAM_DISABLE_ACTIVE_MIGRATION);
379 p = ngtcp2_put_varint(p, 0);
380 }
381
382 if (params->max_ack_delay != NGTCP2_DEFAULT_MAX_ACK_DELAY) {
383 p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_MAX_ACK_DELAY,
384 params->max_ack_delay / NGTCP2_MILLISECONDS);
385 }
386
387 if (params->max_idle_timeout) {
388 p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_MAX_IDLE_TIMEOUT,
389 params->max_idle_timeout / NGTCP2_MILLISECONDS);
390 }
391
392 if (params->active_connection_id_limit &&
393 params->active_connection_id_limit !=
394 NGTCP2_DEFAULT_ACTIVE_CONNECTION_ID_LIMIT) {
395 p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_ACTIVE_CONNECTION_ID_LIMIT,
396 params->active_connection_id_limit);
397 }
398
399 if (params->max_datagram_frame_size) {
400 p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_MAX_DATAGRAM_FRAME_SIZE,
401 params->max_datagram_frame_size);
402 }
403
404 if (params->grease_quic_bit) {
405 p = ngtcp2_put_varint(p, NGTCP2_TRANSPORT_PARAM_GREASE_QUIC_BIT);
406 p = ngtcp2_put_varint(p, 0);
407 }
408
409 if (params->version_info_present) {
410 p = ngtcp2_put_varint(p, NGTCP2_TRANSPORT_PARAM_VERSION_INFORMATION_DRAFT);
411 p = ngtcp2_put_varint(p, version_infolen);
412 p = ngtcp2_put_uint32be(p, params->version_info.chosen_version);
413 if (params->version_info.other_versionslen) {
414 p = ngtcp2_cpymem(p, params->version_info.other_versions,
415 params->version_info.other_versionslen);
416 }
417 }
418
419 assert((size_t)(p - dest) == len);
420
421 return (ngtcp2_ssize)len;
422 }
423
424 /*
425 * decode_varint decodes a single varint from the buffer pointed by
426 * |p| of length |end - p|. If it decodes an integer successfully, it
427 * stores the integer in |*pdest| and returns 0. Otherwise it returns
428 * -1.
429 */
decode_varint(uint64_t * pdest,const uint8_t * p,const uint8_t * end)430 static ngtcp2_ssize decode_varint(uint64_t *pdest, const uint8_t *p,
431 const uint8_t *end) {
432 size_t len;
433
434 if (p == end) {
435 return -1;
436 }
437
438 len = ngtcp2_get_varint_len(p);
439 if ((uint64_t)(end - p) < len) {
440 return -1;
441 }
442
443 *pdest = ngtcp2_get_varint(&len, p);
444
445 return (ngtcp2_ssize)len;
446 }
447
448 /*
449 * decode_varint_param decodes length prefixed value from the buffer
450 * pointed by |p| of length |end - p|. The length and value are
451 * encoded in varint form. If it decodes a value successfully, it
452 * stores the value in |*pdest| and returns 0. Otherwise it returns
453 * -1.
454 */
decode_varint_param(uint64_t * pdest,const uint8_t * p,const uint8_t * end)455 static ngtcp2_ssize decode_varint_param(uint64_t *pdest, const uint8_t *p,
456 const uint8_t *end) {
457 const uint8_t *begin = p;
458 ngtcp2_ssize nread;
459 uint64_t valuelen;
460 size_t n;
461
462 nread = decode_varint(&valuelen, p, end);
463 if (nread < 0) {
464 return -1;
465 }
466
467 p += nread;
468
469 if (p == end) {
470 return -1;
471 }
472
473 if ((uint64_t)(end - p) < valuelen) {
474 return -1;
475 }
476
477 if (ngtcp2_get_varint_len(p) != valuelen) {
478 return -1;
479 }
480
481 *pdest = ngtcp2_get_varint(&n, p);
482
483 p += valuelen;
484
485 return (ngtcp2_ssize)(p - begin);
486 }
487
488 /*
489 * decode_cid_param decodes length prefixed ngtcp2_cid from the buffer
490 * pointed by |p| of length |end - p|. The length is encoded in
491 * varint form. If it decodes a value successfully, it stores the
492 * value in |*pdest| and returns the number of bytes read. Otherwise
493 * it returns -1.
494 */
decode_cid_param(ngtcp2_cid * pdest,const uint8_t * p,const uint8_t * end)495 static ngtcp2_ssize decode_cid_param(ngtcp2_cid *pdest, const uint8_t *p,
496 const uint8_t *end) {
497 const uint8_t *begin = p;
498 uint64_t valuelen;
499 ngtcp2_ssize nread = decode_varint(&valuelen, p, end);
500
501 if (nread < 0) {
502 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
503 }
504
505 p += nread;
506
507 if ((valuelen != 0 && valuelen < NGTCP2_MIN_CIDLEN) ||
508 valuelen > NGTCP2_MAX_CIDLEN || (size_t)(end - p) < valuelen) {
509 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
510 }
511
512 ngtcp2_cid_init(pdest, p, (size_t)valuelen);
513
514 p += valuelen;
515
516 return (ngtcp2_ssize)(p - begin);
517 }
518
ngtcp2_decode_transport_params_versioned(int transport_params_version,ngtcp2_transport_params * params,ngtcp2_transport_params_type exttype,const uint8_t * data,size_t datalen)519 int ngtcp2_decode_transport_params_versioned(
520 int transport_params_version, ngtcp2_transport_params *params,
521 ngtcp2_transport_params_type exttype, const uint8_t *data, size_t datalen) {
522 const uint8_t *p, *end;
523 size_t len;
524 uint64_t param_type;
525 uint64_t valuelen;
526 ngtcp2_ssize nread;
527 int initial_scid_present = 0;
528 int original_dcid_present = 0;
529 size_t i;
530 (void)transport_params_version;
531
532 if (datalen == 0) {
533 return NGTCP2_ERR_REQUIRED_TRANSPORT_PARAM;
534 }
535
536 /* Set default values */
537 memset(params, 0, sizeof(*params));
538 params->initial_max_streams_bidi = 0;
539 params->initial_max_streams_uni = 0;
540 params->initial_max_stream_data_bidi_local = 0;
541 params->initial_max_stream_data_bidi_remote = 0;
542 params->initial_max_stream_data_uni = 0;
543 params->max_udp_payload_size = NGTCP2_DEFAULT_MAX_RECV_UDP_PAYLOAD_SIZE;
544 params->ack_delay_exponent = NGTCP2_DEFAULT_ACK_DELAY_EXPONENT;
545 params->stateless_reset_token_present = 0;
546 params->preferred_address_present = 0;
547 params->disable_active_migration = 0;
548 params->max_ack_delay = NGTCP2_DEFAULT_MAX_ACK_DELAY;
549 params->max_idle_timeout = 0;
550 params->active_connection_id_limit =
551 NGTCP2_DEFAULT_ACTIVE_CONNECTION_ID_LIMIT;
552 params->retry_scid_present = 0;
553 params->max_datagram_frame_size = 0;
554 memset(¶ms->retry_scid, 0, sizeof(params->retry_scid));
555 memset(¶ms->initial_scid, 0, sizeof(params->initial_scid));
556 memset(¶ms->original_dcid, 0, sizeof(params->original_dcid));
557 params->version_info_present = 0;
558
559 p = data;
560 end = data + datalen;
561
562 for (; (size_t)(end - p) >= 2;) {
563 nread = decode_varint(¶m_type, p, end);
564 if (nread < 0) {
565 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
566 }
567 p += nread;
568
569 switch (param_type) {
570 case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL:
571 nread = decode_varint_param(¶ms->initial_max_stream_data_bidi_local,
572 p, end);
573 if (nread < 0) {
574 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
575 }
576 p += nread;
577 break;
578 case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE:
579 nread = decode_varint_param(¶ms->initial_max_stream_data_bidi_remote,
580 p, end);
581 if (nread < 0) {
582 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
583 }
584 p += nread;
585 break;
586 case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_UNI:
587 nread = decode_varint_param(¶ms->initial_max_stream_data_uni, p, end);
588 if (nread < 0) {
589 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
590 }
591 p += nread;
592 break;
593 case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_DATA:
594 nread = decode_varint_param(¶ms->initial_max_data, p, end);
595 if (nread < 0) {
596 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
597 }
598 p += nread;
599 break;
600 case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_BIDI:
601 nread = decode_varint_param(¶ms->initial_max_streams_bidi, p, end);
602 if (nread < 0) {
603 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
604 }
605 if (params->initial_max_streams_bidi > NGTCP2_MAX_STREAMS) {
606 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
607 }
608 p += nread;
609 break;
610 case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_UNI:
611 nread = decode_varint_param(¶ms->initial_max_streams_uni, p, end);
612 if (nread < 0) {
613 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
614 }
615 if (params->initial_max_streams_uni > NGTCP2_MAX_STREAMS) {
616 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
617 }
618 p += nread;
619 break;
620 case NGTCP2_TRANSPORT_PARAM_MAX_IDLE_TIMEOUT:
621 nread = decode_varint_param(¶ms->max_idle_timeout, p, end);
622 if (nread < 0) {
623 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
624 }
625 params->max_idle_timeout *= NGTCP2_MILLISECONDS;
626 p += nread;
627 break;
628 case NGTCP2_TRANSPORT_PARAM_MAX_UDP_PAYLOAD_SIZE:
629 nread = decode_varint_param(¶ms->max_udp_payload_size, p, end);
630 if (nread < 0) {
631 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
632 }
633 p += nread;
634 break;
635 case NGTCP2_TRANSPORT_PARAM_STATELESS_RESET_TOKEN:
636 if (exttype != NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS) {
637 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
638 }
639 nread = decode_varint(&valuelen, p, end);
640 if (nread < 0) {
641 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
642 }
643 p += nread;
644 if ((size_t)valuelen != sizeof(params->stateless_reset_token)) {
645 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
646 }
647 if ((size_t)(end - p) < sizeof(params->stateless_reset_token)) {
648 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
649 }
650
651 memcpy(params->stateless_reset_token, p,
652 sizeof(params->stateless_reset_token));
653 params->stateless_reset_token_present = 1;
654
655 p += sizeof(params->stateless_reset_token);
656 break;
657 case NGTCP2_TRANSPORT_PARAM_ACK_DELAY_EXPONENT:
658 nread = decode_varint_param(¶ms->ack_delay_exponent, p, end);
659 if (nread < 0 || params->ack_delay_exponent > 20) {
660 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
661 }
662 p += nread;
663 break;
664 case NGTCP2_TRANSPORT_PARAM_PREFERRED_ADDRESS:
665 if (exttype != NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS) {
666 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
667 }
668 nread = decode_varint(&valuelen, p, end);
669 if (nread < 0) {
670 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
671 }
672 p += nread;
673 if ((size_t)(end - p) < valuelen) {
674 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
675 }
676 len = 4 /* ipv4Address */ + 2 /* ipv4Port */ + 16 /* ipv6Address */ +
677 2 /* ipv6Port */
678 + 1 /* cid length */ + NGTCP2_STATELESS_RESET_TOKENLEN;
679 if (valuelen < len) {
680 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
681 }
682
683 memcpy(params->preferred_address.ipv4_addr, p,
684 sizeof(params->preferred_address.ipv4_addr));
685 p += sizeof(params->preferred_address.ipv4_addr);
686 params->preferred_address.ipv4_port = ngtcp2_get_uint16(p);
687 p += sizeof(uint16_t);
688
689 if (params->preferred_address.ipv4_port ||
690 memcmp(empty_address, params->preferred_address.ipv4_addr,
691 sizeof(params->preferred_address.ipv4_addr)) != 0) {
692 params->preferred_address.ipv4_present = 1;
693 }
694
695 memcpy(params->preferred_address.ipv6_addr, p,
696 sizeof(params->preferred_address.ipv6_addr));
697 p += sizeof(params->preferred_address.ipv6_addr);
698 params->preferred_address.ipv6_port = ngtcp2_get_uint16(p);
699 p += sizeof(uint16_t);
700
701 if (params->preferred_address.ipv6_port ||
702 memcmp(empty_address, params->preferred_address.ipv6_addr,
703 sizeof(params->preferred_address.ipv6_addr)) != 0) {
704 params->preferred_address.ipv6_present = 1;
705 }
706
707 /* cid */
708 params->preferred_address.cid.datalen = *p++;
709 len += params->preferred_address.cid.datalen;
710 if (valuelen != len ||
711 params->preferred_address.cid.datalen > NGTCP2_MAX_CIDLEN ||
712 params->preferred_address.cid.datalen < NGTCP2_MIN_CIDLEN) {
713 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
714 }
715 if (params->preferred_address.cid.datalen) {
716 memcpy(params->preferred_address.cid.data, p,
717 params->preferred_address.cid.datalen);
718 p += params->preferred_address.cid.datalen;
719 }
720
721 /* stateless reset token */
722 memcpy(params->preferred_address.stateless_reset_token, p,
723 sizeof(params->preferred_address.stateless_reset_token));
724 p += sizeof(params->preferred_address.stateless_reset_token);
725 params->preferred_address_present = 1;
726 break;
727 case NGTCP2_TRANSPORT_PARAM_DISABLE_ACTIVE_MIGRATION:
728 nread = decode_varint(&valuelen, p, end);
729 if (nread < 0 || valuelen != 0) {
730 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
731 }
732 p += nread;
733 params->disable_active_migration = 1;
734 break;
735 case NGTCP2_TRANSPORT_PARAM_ORIGINAL_DESTINATION_CONNECTION_ID:
736 if (exttype != NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS) {
737 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
738 }
739 nread = decode_cid_param(¶ms->original_dcid, p, end);
740 if (nread < 0) {
741 return (int)nread;
742 }
743 original_dcid_present = 1;
744 p += nread;
745 break;
746 case NGTCP2_TRANSPORT_PARAM_RETRY_SOURCE_CONNECTION_ID:
747 if (exttype != NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS) {
748 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
749 }
750 nread = decode_cid_param(¶ms->retry_scid, p, end);
751 if (nread < 0) {
752 return (int)nread;
753 }
754 params->retry_scid_present = 1;
755 p += nread;
756 break;
757 case NGTCP2_TRANSPORT_PARAM_INITIAL_SOURCE_CONNECTION_ID:
758 nread = decode_cid_param(¶ms->initial_scid, p, end);
759 if (nread < 0) {
760 return (int)nread;
761 }
762 initial_scid_present = 1;
763 p += nread;
764 break;
765 case NGTCP2_TRANSPORT_PARAM_MAX_ACK_DELAY:
766 nread = decode_varint_param(¶ms->max_ack_delay, p, end);
767 if (nread < 0 || params->max_ack_delay >= 16384) {
768 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
769 }
770 params->max_ack_delay *= NGTCP2_MILLISECONDS;
771 p += nread;
772 break;
773 case NGTCP2_TRANSPORT_PARAM_ACTIVE_CONNECTION_ID_LIMIT:
774 nread = decode_varint_param(¶ms->active_connection_id_limit, p, end);
775 if (nread < 0) {
776 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
777 }
778 p += nread;
779 break;
780 case NGTCP2_TRANSPORT_PARAM_MAX_DATAGRAM_FRAME_SIZE:
781 nread = decode_varint_param(¶ms->max_datagram_frame_size, p, end);
782 if (nread < 0) {
783 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
784 }
785 p += nread;
786 break;
787 case NGTCP2_TRANSPORT_PARAM_GREASE_QUIC_BIT:
788 nread = decode_varint(&valuelen, p, end);
789 if (nread < 0 || valuelen != 0) {
790 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
791 }
792 p += nread;
793 params->grease_quic_bit = 1;
794 break;
795 case NGTCP2_TRANSPORT_PARAM_VERSION_INFORMATION_DRAFT:
796 nread = decode_varint(&valuelen, p, end);
797 if (nread < 0) {
798 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
799 }
800 p += nread;
801 if ((size_t)(end - p) < valuelen) {
802 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
803 }
804 if (valuelen < sizeof(uint32_t) || (valuelen & 0x3)) {
805 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
806 }
807 params->version_info.chosen_version = ngtcp2_get_uint32(p);
808 if (params->version_info.chosen_version == 0) {
809 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
810 }
811 p += sizeof(uint32_t);
812 if (valuelen > sizeof(uint32_t)) {
813 params->version_info.other_versions = (uint8_t *)p;
814 params->version_info.other_versionslen =
815 (size_t)valuelen - sizeof(uint32_t);
816
817 for (i = sizeof(uint32_t); i < valuelen;
818 i += sizeof(uint32_t), p += sizeof(uint32_t)) {
819 if (ngtcp2_get_uint32(p) == 0) {
820 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
821 }
822 }
823 }
824 params->version_info_present = 1;
825 break;
826 default:
827 /* Ignore unknown parameter */
828 nread = decode_varint(&valuelen, p, end);
829 if (nread < 0) {
830 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
831 }
832 p += nread;
833 if ((size_t)(end - p) < valuelen) {
834 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
835 }
836 p += valuelen;
837 break;
838 }
839 }
840
841 if (end - p != 0) {
842 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
843 }
844
845 if (!initial_scid_present ||
846 (exttype == NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS &&
847 !original_dcid_present)) {
848 return NGTCP2_ERR_REQUIRED_TRANSPORT_PARAM;
849 }
850
851 return 0;
852 }
853
transport_params_copy_new(ngtcp2_transport_params ** pdest,const ngtcp2_transport_params * src,const ngtcp2_mem * mem)854 static int transport_params_copy_new(ngtcp2_transport_params **pdest,
855 const ngtcp2_transport_params *src,
856 const ngtcp2_mem *mem) {
857 size_t len = sizeof(**pdest);
858 ngtcp2_transport_params *dest;
859 uint8_t *p;
860
861 if (src->version_info_present) {
862 len += src->version_info.other_versionslen;
863 }
864
865 dest = ngtcp2_mem_malloc(mem, len);
866 if (dest == NULL) {
867 return NGTCP2_ERR_NOMEM;
868 }
869
870 *dest = *src;
871
872 if (src->version_info_present && src->version_info.other_versionslen) {
873 p = (uint8_t *)dest + sizeof(*dest);
874 memcpy(p, src->version_info.other_versions,
875 src->version_info.other_versionslen);
876 dest->version_info.other_versions = p;
877 }
878
879 *pdest = dest;
880
881 return 0;
882 }
883
ngtcp2_decode_transport_params_new(ngtcp2_transport_params ** pparams,ngtcp2_transport_params_type exttype,const uint8_t * data,size_t datalen,const ngtcp2_mem * mem)884 int ngtcp2_decode_transport_params_new(ngtcp2_transport_params **pparams,
885 ngtcp2_transport_params_type exttype,
886 const uint8_t *data, size_t datalen,
887 const ngtcp2_mem *mem) {
888 int rv;
889 ngtcp2_transport_params params;
890
891 rv = ngtcp2_decode_transport_params(¶ms, exttype, data, datalen);
892 if (rv < 0) {
893 return rv;
894 }
895
896 if (mem == NULL) {
897 mem = ngtcp2_mem_default();
898 }
899
900 return transport_params_copy_new(pparams, ¶ms, mem);
901 }
902
ngtcp2_transport_params_del(ngtcp2_transport_params * params,const ngtcp2_mem * mem)903 void ngtcp2_transport_params_del(ngtcp2_transport_params *params,
904 const ngtcp2_mem *mem) {
905 if (params == NULL) {
906 return;
907 }
908
909 if (mem == NULL) {
910 mem = ngtcp2_mem_default();
911 }
912
913 ngtcp2_mem_free(mem, params);
914 }
915
ngtcp2_transport_params_copy_new(ngtcp2_transport_params ** pdest,const ngtcp2_transport_params * src,const ngtcp2_mem * mem)916 int ngtcp2_transport_params_copy_new(ngtcp2_transport_params **pdest,
917 const ngtcp2_transport_params *src,
918 const ngtcp2_mem *mem) {
919 if (src == NULL) {
920 *pdest = NULL;
921 return 0;
922 }
923
924 return transport_params_copy_new(pdest, src, mem);
925 }
926