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
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)34 int ngtcp2_crypto_km_new(ngtcp2_crypto_km **pckm, const uint8_t *secret,
35 size_t secretlen,
36 const ngtcp2_crypto_aead_ctx *aead_ctx,
37 const uint8_t *iv, size_t ivlen,
38 const ngtcp2_mem *mem) {
39 int rv = ngtcp2_crypto_km_nocopy_new(pckm, secretlen, ivlen, mem);
40 if (rv != 0) {
41 return rv;
42 }
43
44 if (secretlen) {
45 memcpy((*pckm)->secret.base, secret, secretlen);
46 }
47 if (aead_ctx) {
48 (*pckm)->aead_ctx = *aead_ctx;
49 }
50 memcpy((*pckm)->iv.base, iv, ivlen);
51
52 return 0;
53 }
54
ngtcp2_crypto_km_nocopy_new(ngtcp2_crypto_km ** pckm,size_t secretlen,size_t ivlen,const ngtcp2_mem * mem)55 int ngtcp2_crypto_km_nocopy_new(ngtcp2_crypto_km **pckm, size_t secretlen,
56 size_t ivlen, const ngtcp2_mem *mem) {
57 size_t len;
58 uint8_t *p;
59
60 len = sizeof(ngtcp2_crypto_km) + secretlen + ivlen;
61
62 *pckm = ngtcp2_mem_malloc(mem, len);
63 if (*pckm == NULL) {
64 return NGTCP2_ERR_NOMEM;
65 }
66
67 p = (uint8_t *)(*pckm) + sizeof(ngtcp2_crypto_km);
68 (*pckm)->secret.base = p;
69 (*pckm)->secret.len = secretlen;
70 p += secretlen;
71 (*pckm)->iv.base = p;
72 (*pckm)->iv.len = ivlen;
73 (*pckm)->aead_ctx.native_handle = NULL;
74 (*pckm)->pkt_num = -1;
75 (*pckm)->use_count = 0;
76 (*pckm)->flags = NGTCP2_CRYPTO_KM_FLAG_NONE;
77
78 return 0;
79 }
80
ngtcp2_crypto_km_del(ngtcp2_crypto_km * ckm,const ngtcp2_mem * mem)81 void ngtcp2_crypto_km_del(ngtcp2_crypto_km *ckm, const ngtcp2_mem *mem) {
82 if (ckm == NULL) {
83 return;
84 }
85
86 ngtcp2_mem_free(mem, ckm);
87 }
88
ngtcp2_crypto_create_nonce(uint8_t * dest,const uint8_t * iv,size_t ivlen,int64_t pkt_num)89 void ngtcp2_crypto_create_nonce(uint8_t *dest, const uint8_t *iv, size_t ivlen,
90 int64_t pkt_num) {
91 size_t i;
92 uint64_t n;
93
94 assert(ivlen >= 8);
95
96 memcpy(dest, iv, ivlen);
97 n = ngtcp2_htonl64((uint64_t)pkt_num);
98
99 for (i = 0; i < 8; ++i) {
100 dest[ivlen - 8 + i] ^= ((uint8_t *)&n)[i];
101 }
102 }
103
104 /*
105 * varint_paramlen returns the length of a single transport parameter
106 * which has variable integer in its parameter.
107 */
varint_paramlen(ngtcp2_transport_param_id id,uint64_t param)108 static size_t varint_paramlen(ngtcp2_transport_param_id id, uint64_t param) {
109 size_t valuelen = ngtcp2_put_varint_len(param);
110 return ngtcp2_put_varint_len(id) + ngtcp2_put_varint_len(valuelen) + valuelen;
111 }
112
113 /*
114 * write_varint_param writes parameter |id| of the given |value| in
115 * varint encoding. It returns p + the number of bytes written.
116 */
write_varint_param(uint8_t * p,ngtcp2_transport_param_id id,uint64_t value)117 static uint8_t *write_varint_param(uint8_t *p, ngtcp2_transport_param_id id,
118 uint64_t value) {
119 p = ngtcp2_put_varint(p, id);
120 p = ngtcp2_put_varint(p, ngtcp2_put_varint_len(value));
121 return ngtcp2_put_varint(p, value);
122 }
123
124 /*
125 * cid_paramlen returns the length of a single transport parameter
126 * which has |cid| as value.
127 */
cid_paramlen(ngtcp2_transport_param_id id,const ngtcp2_cid * cid)128 static size_t cid_paramlen(ngtcp2_transport_param_id id,
129 const ngtcp2_cid *cid) {
130 return ngtcp2_put_varint_len(id) + ngtcp2_put_varint_len(cid->datalen) +
131 cid->datalen;
132 }
133
134 /*
135 * write_cid_param writes parameter |id| of the given |cid|. It
136 * returns p + the number of bytes written.
137 */
write_cid_param(uint8_t * p,ngtcp2_transport_param_id id,const ngtcp2_cid * cid)138 static uint8_t *write_cid_param(uint8_t *p, ngtcp2_transport_param_id id,
139 const ngtcp2_cid *cid) {
140 assert(cid->datalen == 0 || cid->datalen >= NGTCP2_MIN_CIDLEN);
141 assert(cid->datalen <= NGTCP2_MAX_CIDLEN);
142
143 p = ngtcp2_put_varint(p, id);
144 p = ngtcp2_put_varint(p, cid->datalen);
145 if (cid->datalen) {
146 p = ngtcp2_cpymem(p, cid->data, cid->datalen);
147 }
148 return p;
149 }
150
151 static const uint8_t empty_address[16];
152
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)153 ngtcp2_ssize ngtcp2_encode_transport_params_versioned(
154 uint8_t *dest, size_t destlen, ngtcp2_transport_params_type exttype,
155 int transport_params_version, const ngtcp2_transport_params *params) {
156 uint8_t *p;
157 size_t len = 0;
158 /* For some reason, gcc 7.3.0 requires this initialization. */
159 size_t preferred_addrlen = 0;
160 (void)transport_params_version;
161
162 switch (exttype) {
163 case NGTCP2_TRANSPORT_PARAMS_TYPE_CLIENT_HELLO:
164 break;
165 case NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS:
166 len +=
167 cid_paramlen(NGTCP2_TRANSPORT_PARAM_ORIGINAL_DESTINATION_CONNECTION_ID,
168 ¶ms->original_dcid);
169
170 if (params->stateless_reset_token_present) {
171 len +=
172 ngtcp2_put_varint_len(NGTCP2_TRANSPORT_PARAM_STATELESS_RESET_TOKEN) +
173 ngtcp2_put_varint_len(NGTCP2_STATELESS_RESET_TOKENLEN) +
174 NGTCP2_STATELESS_RESET_TOKENLEN;
175 }
176 if (params->preferred_address_present) {
177 assert(params->preferred_address.cid.datalen >= NGTCP2_MIN_CIDLEN);
178 assert(params->preferred_address.cid.datalen <= NGTCP2_MAX_CIDLEN);
179 preferred_addrlen = 4 /* ipv4Address */ + 2 /* ipv4Port */ +
180 16 /* ipv6Address */ + 2 /* ipv6Port */
181 + 1 +
182 params->preferred_address.cid.datalen /* CID */ +
183 NGTCP2_STATELESS_RESET_TOKENLEN;
184 len += ngtcp2_put_varint_len(NGTCP2_TRANSPORT_PARAM_PREFERRED_ADDRESS) +
185 ngtcp2_put_varint_len(preferred_addrlen) + preferred_addrlen;
186 }
187 if (params->retry_scid_present) {
188 len += cid_paramlen(NGTCP2_TRANSPORT_PARAM_RETRY_SOURCE_CONNECTION_ID,
189 ¶ms->retry_scid);
190 }
191 break;
192 default:
193 return NGTCP2_ERR_INVALID_ARGUMENT;
194 }
195
196 len += cid_paramlen(NGTCP2_TRANSPORT_PARAM_INITIAL_SOURCE_CONNECTION_ID,
197 ¶ms->initial_scid);
198
199 if (params->initial_max_stream_data_bidi_local) {
200 len += varint_paramlen(
201 NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL,
202 params->initial_max_stream_data_bidi_local);
203 }
204 if (params->initial_max_stream_data_bidi_remote) {
205 len += varint_paramlen(
206 NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE,
207 params->initial_max_stream_data_bidi_remote);
208 }
209 if (params->initial_max_stream_data_uni) {
210 len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_UNI,
211 params->initial_max_stream_data_uni);
212 }
213 if (params->initial_max_data) {
214 len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_DATA,
215 params->initial_max_data);
216 }
217 if (params->initial_max_streams_bidi) {
218 len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_BIDI,
219 params->initial_max_streams_bidi);
220 }
221 if (params->initial_max_streams_uni) {
222 len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_UNI,
223 params->initial_max_streams_uni);
224 }
225 if (params->max_udp_payload_size !=
226 NGTCP2_DEFAULT_MAX_RECV_UDP_PAYLOAD_SIZE) {
227 len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_MAX_UDP_PAYLOAD_SIZE,
228 params->max_udp_payload_size);
229 }
230 if (params->ack_delay_exponent != NGTCP2_DEFAULT_ACK_DELAY_EXPONENT) {
231 len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_ACK_DELAY_EXPONENT,
232 params->ack_delay_exponent);
233 }
234 if (params->disable_active_migration) {
235 len +=
236 ngtcp2_put_varint_len(NGTCP2_TRANSPORT_PARAM_DISABLE_ACTIVE_MIGRATION) +
237 ngtcp2_put_varint_len(0);
238 }
239 if (params->max_ack_delay != NGTCP2_DEFAULT_MAX_ACK_DELAY) {
240 len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_MAX_ACK_DELAY,
241 params->max_ack_delay / NGTCP2_MILLISECONDS);
242 }
243 if (params->max_idle_timeout) {
244 len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_MAX_IDLE_TIMEOUT,
245 params->max_idle_timeout / NGTCP2_MILLISECONDS);
246 }
247 if (params->active_connection_id_limit &&
248 params->active_connection_id_limit !=
249 NGTCP2_DEFAULT_ACTIVE_CONNECTION_ID_LIMIT) {
250 len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_ACTIVE_CONNECTION_ID_LIMIT,
251 params->active_connection_id_limit);
252 }
253 if (params->max_datagram_frame_size) {
254 len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_MAX_DATAGRAM_FRAME_SIZE,
255 params->max_datagram_frame_size);
256 }
257 if (params->grease_quic_bit) {
258 len += ngtcp2_put_varint_len(NGTCP2_TRANSPORT_PARAM_GREASE_QUIC_BIT) +
259 ngtcp2_put_varint_len(0);
260 }
261
262 if (destlen < len) {
263 return NGTCP2_ERR_NOBUF;
264 }
265
266 p = dest;
267
268 if (exttype == NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS) {
269 p = write_cid_param(
270 p, NGTCP2_TRANSPORT_PARAM_ORIGINAL_DESTINATION_CONNECTION_ID,
271 ¶ms->original_dcid);
272
273 if (params->stateless_reset_token_present) {
274 p = ngtcp2_put_varint(p, NGTCP2_TRANSPORT_PARAM_STATELESS_RESET_TOKEN);
275 p = ngtcp2_put_varint(p, sizeof(params->stateless_reset_token));
276 p = ngtcp2_cpymem(p, params->stateless_reset_token,
277 sizeof(params->stateless_reset_token));
278 }
279 if (params->preferred_address_present) {
280 p = ngtcp2_put_varint(p, NGTCP2_TRANSPORT_PARAM_PREFERRED_ADDRESS);
281 p = ngtcp2_put_varint(p, preferred_addrlen);
282
283 if (params->preferred_address.ipv4_present) {
284 p = ngtcp2_cpymem(p, params->preferred_address.ipv4_addr,
285 sizeof(params->preferred_address.ipv4_addr));
286 p = ngtcp2_put_uint16be(p, params->preferred_address.ipv4_port);
287 } else {
288 p = ngtcp2_cpymem(p, empty_address,
289 sizeof(params->preferred_address.ipv4_addr));
290 p = ngtcp2_put_uint16be(p, 0);
291 }
292
293 if (params->preferred_address.ipv6_present) {
294 p = ngtcp2_cpymem(p, params->preferred_address.ipv6_addr,
295 sizeof(params->preferred_address.ipv6_addr));
296 p = ngtcp2_put_uint16be(p, params->preferred_address.ipv6_port);
297 } else {
298 p = ngtcp2_cpymem(p, empty_address,
299 sizeof(params->preferred_address.ipv6_addr));
300 p = ngtcp2_put_uint16be(p, 0);
301 }
302
303 *p++ = (uint8_t)params->preferred_address.cid.datalen;
304 if (params->preferred_address.cid.datalen) {
305 p = ngtcp2_cpymem(p, params->preferred_address.cid.data,
306 params->preferred_address.cid.datalen);
307 }
308 p = ngtcp2_cpymem(
309 p, params->preferred_address.stateless_reset_token,
310 sizeof(params->preferred_address.stateless_reset_token));
311 }
312 if (params->retry_scid_present) {
313 p = write_cid_param(p, NGTCP2_TRANSPORT_PARAM_RETRY_SOURCE_CONNECTION_ID,
314 ¶ms->retry_scid);
315 }
316 }
317
318 p = write_cid_param(p, NGTCP2_TRANSPORT_PARAM_INITIAL_SOURCE_CONNECTION_ID,
319 ¶ms->initial_scid);
320
321 if (params->initial_max_stream_data_bidi_local) {
322 p = write_varint_param(
323 p, NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL,
324 params->initial_max_stream_data_bidi_local);
325 }
326
327 if (params->initial_max_stream_data_bidi_remote) {
328 p = write_varint_param(
329 p, NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE,
330 params->initial_max_stream_data_bidi_remote);
331 }
332
333 if (params->initial_max_stream_data_uni) {
334 p = write_varint_param(p,
335 NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_UNI,
336 params->initial_max_stream_data_uni);
337 }
338
339 if (params->initial_max_data) {
340 p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_DATA,
341 params->initial_max_data);
342 }
343
344 if (params->initial_max_streams_bidi) {
345 p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_BIDI,
346 params->initial_max_streams_bidi);
347 }
348
349 if (params->initial_max_streams_uni) {
350 p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_UNI,
351 params->initial_max_streams_uni);
352 }
353
354 if (params->max_udp_payload_size !=
355 NGTCP2_DEFAULT_MAX_RECV_UDP_PAYLOAD_SIZE) {
356 p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_MAX_UDP_PAYLOAD_SIZE,
357 params->max_udp_payload_size);
358 }
359
360 if (params->ack_delay_exponent != NGTCP2_DEFAULT_ACK_DELAY_EXPONENT) {
361 p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_ACK_DELAY_EXPONENT,
362 params->ack_delay_exponent);
363 }
364
365 if (params->disable_active_migration) {
366 p = ngtcp2_put_varint(p, NGTCP2_TRANSPORT_PARAM_DISABLE_ACTIVE_MIGRATION);
367 p = ngtcp2_put_varint(p, 0);
368 }
369
370 if (params->max_ack_delay != NGTCP2_DEFAULT_MAX_ACK_DELAY) {
371 p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_MAX_ACK_DELAY,
372 params->max_ack_delay / NGTCP2_MILLISECONDS);
373 }
374
375 if (params->max_idle_timeout) {
376 p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_MAX_IDLE_TIMEOUT,
377 params->max_idle_timeout / NGTCP2_MILLISECONDS);
378 }
379
380 if (params->active_connection_id_limit &&
381 params->active_connection_id_limit !=
382 NGTCP2_DEFAULT_ACTIVE_CONNECTION_ID_LIMIT) {
383 p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_ACTIVE_CONNECTION_ID_LIMIT,
384 params->active_connection_id_limit);
385 }
386
387 if (params->max_datagram_frame_size) {
388 p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_MAX_DATAGRAM_FRAME_SIZE,
389 params->max_datagram_frame_size);
390 }
391
392 if (params->grease_quic_bit) {
393 p = ngtcp2_put_varint(p, NGTCP2_TRANSPORT_PARAM_GREASE_QUIC_BIT);
394 p = ngtcp2_put_varint(p, 0);
395 }
396
397 assert((size_t)(p - dest) == len);
398
399 return (ngtcp2_ssize)len;
400 }
401
402 /*
403 * decode_varint decodes a single varint from the buffer pointed by
404 * |p| of length |end - p|. If it decodes an integer successfully, it
405 * stores the integer in |*pdest| and returns 0. Otherwise it returns
406 * -1.
407 */
decode_varint(uint64_t * pdest,const uint8_t * p,const uint8_t * end)408 static ngtcp2_ssize decode_varint(uint64_t *pdest, const uint8_t *p,
409 const uint8_t *end) {
410 size_t len;
411
412 if (p == end) {
413 return -1;
414 }
415
416 len = ngtcp2_get_varint_len(p);
417 if ((uint64_t)(end - p) < len) {
418 return -1;
419 }
420
421 *pdest = ngtcp2_get_varint(&len, p);
422
423 return (ngtcp2_ssize)len;
424 }
425
426 /*
427 * decode_varint_param decodes length prefixed value from the buffer
428 * pointed by |p| of length |end - p|. The length and value are
429 * encoded in varint form. If it decodes a value successfully, it
430 * stores the value in |*pdest| and returns 0. Otherwise it returns
431 * -1.
432 */
decode_varint_param(uint64_t * pdest,const uint8_t * p,const uint8_t * end)433 static ngtcp2_ssize decode_varint_param(uint64_t *pdest, const uint8_t *p,
434 const uint8_t *end) {
435 const uint8_t *begin = p;
436 ngtcp2_ssize nread;
437 uint64_t valuelen;
438 size_t n;
439
440 nread = decode_varint(&valuelen, p, end);
441 if (nread < 0) {
442 return -1;
443 }
444
445 p += nread;
446
447 if (p == end) {
448 return -1;
449 }
450
451 if ((uint64_t)(end - p) < valuelen) {
452 return -1;
453 }
454
455 if (ngtcp2_get_varint_len(p) != valuelen) {
456 return -1;
457 }
458
459 *pdest = ngtcp2_get_varint(&n, p);
460
461 p += valuelen;
462
463 return (ngtcp2_ssize)(p - begin);
464 }
465
466 /*
467 * decode_cid_param decodes length prefixed ngtcp2_cid from the buffer
468 * pointed by |p| of length |end - p|. The length is encoded in
469 * varint form. If it decodes a value successfully, it stores the
470 * value in |*pdest| and returns the number of bytes read. Otherwise
471 * it returns -1.
472 */
decode_cid_param(ngtcp2_cid * pdest,const uint8_t * p,const uint8_t * end)473 static ngtcp2_ssize decode_cid_param(ngtcp2_cid *pdest, const uint8_t *p,
474 const uint8_t *end) {
475 const uint8_t *begin = p;
476 uint64_t valuelen;
477 ngtcp2_ssize nread = decode_varint(&valuelen, p, end);
478
479 if (nread < 0) {
480 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
481 }
482
483 p += nread;
484
485 if ((valuelen != 0 && valuelen < NGTCP2_MIN_CIDLEN) ||
486 valuelen > NGTCP2_MAX_CIDLEN || (size_t)(end - p) < valuelen) {
487 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
488 }
489
490 ngtcp2_cid_init(pdest, p, (size_t)valuelen);
491
492 p += valuelen;
493
494 return (ngtcp2_ssize)(p - begin);
495 }
496
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)497 int ngtcp2_decode_transport_params_versioned(
498 int transport_params_version, ngtcp2_transport_params *params,
499 ngtcp2_transport_params_type exttype, const uint8_t *data, size_t datalen) {
500 const uint8_t *p, *end;
501 size_t len;
502 uint64_t param_type;
503 uint64_t valuelen;
504 ngtcp2_ssize nread;
505 int initial_scid_present = 0;
506 int original_dcid_present = 0;
507 (void)transport_params_version;
508
509 if (datalen == 0) {
510 return NGTCP2_ERR_REQUIRED_TRANSPORT_PARAM;
511 }
512
513 /* Set default values */
514 memset(params, 0, sizeof(*params));
515 params->initial_max_streams_bidi = 0;
516 params->initial_max_streams_uni = 0;
517 params->initial_max_stream_data_bidi_local = 0;
518 params->initial_max_stream_data_bidi_remote = 0;
519 params->initial_max_stream_data_uni = 0;
520 params->max_udp_payload_size = NGTCP2_DEFAULT_MAX_RECV_UDP_PAYLOAD_SIZE;
521 params->ack_delay_exponent = NGTCP2_DEFAULT_ACK_DELAY_EXPONENT;
522 params->stateless_reset_token_present = 0;
523 params->preferred_address_present = 0;
524 params->disable_active_migration = 0;
525 params->max_ack_delay = NGTCP2_DEFAULT_MAX_ACK_DELAY;
526 params->max_idle_timeout = 0;
527 params->active_connection_id_limit =
528 NGTCP2_DEFAULT_ACTIVE_CONNECTION_ID_LIMIT;
529 params->retry_scid_present = 0;
530 params->max_datagram_frame_size = 0;
531 memset(¶ms->retry_scid, 0, sizeof(params->retry_scid));
532 memset(¶ms->initial_scid, 0, sizeof(params->initial_scid));
533 memset(¶ms->original_dcid, 0, sizeof(params->original_dcid));
534
535 p = data;
536 end = data + datalen;
537
538 for (; (size_t)(end - p) >= 2;) {
539 nread = decode_varint(¶m_type, p, end);
540 if (nread < 0) {
541 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
542 }
543 p += nread;
544
545 switch (param_type) {
546 case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL:
547 nread = decode_varint_param(¶ms->initial_max_stream_data_bidi_local,
548 p, end);
549 if (nread < 0) {
550 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
551 }
552 p += nread;
553 break;
554 case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE:
555 nread = decode_varint_param(¶ms->initial_max_stream_data_bidi_remote,
556 p, end);
557 if (nread < 0) {
558 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
559 }
560 p += nread;
561 break;
562 case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_UNI:
563 nread = decode_varint_param(¶ms->initial_max_stream_data_uni, p, end);
564 if (nread < 0) {
565 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
566 }
567 p += nread;
568 break;
569 case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_DATA:
570 nread = decode_varint_param(¶ms->initial_max_data, p, end);
571 if (nread < 0) {
572 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
573 }
574 p += nread;
575 break;
576 case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_BIDI:
577 nread = decode_varint_param(¶ms->initial_max_streams_bidi, p, end);
578 if (nread < 0) {
579 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
580 }
581 if (params->initial_max_streams_bidi > NGTCP2_MAX_STREAMS) {
582 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
583 }
584 p += nread;
585 break;
586 case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_UNI:
587 nread = decode_varint_param(¶ms->initial_max_streams_uni, p, end);
588 if (nread < 0) {
589 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
590 }
591 if (params->initial_max_streams_uni > NGTCP2_MAX_STREAMS) {
592 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
593 }
594 p += nread;
595 break;
596 case NGTCP2_TRANSPORT_PARAM_MAX_IDLE_TIMEOUT:
597 nread = decode_varint_param(¶ms->max_idle_timeout, p, end);
598 if (nread < 0) {
599 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
600 }
601 params->max_idle_timeout *= NGTCP2_MILLISECONDS;
602 p += nread;
603 break;
604 case NGTCP2_TRANSPORT_PARAM_MAX_UDP_PAYLOAD_SIZE:
605 nread = decode_varint_param(¶ms->max_udp_payload_size, p, end);
606 if (nread < 0) {
607 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
608 }
609 p += nread;
610 break;
611 case NGTCP2_TRANSPORT_PARAM_STATELESS_RESET_TOKEN:
612 if (exttype != NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS) {
613 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
614 }
615 nread = decode_varint(&valuelen, p, end);
616 if (nread < 0) {
617 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
618 }
619 p += nread;
620 if ((size_t)valuelen != sizeof(params->stateless_reset_token)) {
621 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
622 }
623 if ((size_t)(end - p) < sizeof(params->stateless_reset_token)) {
624 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
625 }
626
627 memcpy(params->stateless_reset_token, p,
628 sizeof(params->stateless_reset_token));
629 params->stateless_reset_token_present = 1;
630
631 p += sizeof(params->stateless_reset_token);
632 break;
633 case NGTCP2_TRANSPORT_PARAM_ACK_DELAY_EXPONENT:
634 nread = decode_varint_param(¶ms->ack_delay_exponent, p, end);
635 if (nread < 0 || params->ack_delay_exponent > 20) {
636 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
637 }
638 p += nread;
639 break;
640 case NGTCP2_TRANSPORT_PARAM_PREFERRED_ADDRESS:
641 if (exttype != NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS) {
642 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
643 }
644 nread = decode_varint(&valuelen, p, end);
645 if (nread < 0) {
646 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
647 }
648 p += nread;
649 if ((size_t)(end - p) < valuelen) {
650 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
651 }
652 len = 4 /* ipv4Address */ + 2 /* ipv4Port */ + 16 /* ipv6Address */ +
653 2 /* ipv6Port */
654 + 1 /* cid length */ + NGTCP2_STATELESS_RESET_TOKENLEN;
655 if (valuelen < len) {
656 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
657 }
658
659 memcpy(params->preferred_address.ipv4_addr, p,
660 sizeof(params->preferred_address.ipv4_addr));
661 p += sizeof(params->preferred_address.ipv4_addr);
662 params->preferred_address.ipv4_port = ngtcp2_get_uint16(p);
663 p += sizeof(uint16_t);
664
665 if (params->preferred_address.ipv4_port ||
666 memcmp(empty_address, params->preferred_address.ipv4_addr,
667 sizeof(params->preferred_address.ipv4_addr)) != 0) {
668 params->preferred_address.ipv4_present = 1;
669 }
670
671 memcpy(params->preferred_address.ipv6_addr, p,
672 sizeof(params->preferred_address.ipv6_addr));
673 p += sizeof(params->preferred_address.ipv6_addr);
674 params->preferred_address.ipv6_port = ngtcp2_get_uint16(p);
675 p += sizeof(uint16_t);
676
677 if (params->preferred_address.ipv6_port ||
678 memcmp(empty_address, params->preferred_address.ipv6_addr,
679 sizeof(params->preferred_address.ipv6_addr)) != 0) {
680 params->preferred_address.ipv6_present = 1;
681 }
682
683 /* cid */
684 params->preferred_address.cid.datalen = *p++;
685 len += params->preferred_address.cid.datalen;
686 if (valuelen != len ||
687 params->preferred_address.cid.datalen > NGTCP2_MAX_CIDLEN ||
688 params->preferred_address.cid.datalen < NGTCP2_MIN_CIDLEN) {
689 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
690 }
691 if (params->preferred_address.cid.datalen) {
692 memcpy(params->preferred_address.cid.data, p,
693 params->preferred_address.cid.datalen);
694 p += params->preferred_address.cid.datalen;
695 }
696
697 /* stateless reset token */
698 memcpy(params->preferred_address.stateless_reset_token, p,
699 sizeof(params->preferred_address.stateless_reset_token));
700 p += sizeof(params->preferred_address.stateless_reset_token);
701 params->preferred_address_present = 1;
702 break;
703 case NGTCP2_TRANSPORT_PARAM_DISABLE_ACTIVE_MIGRATION:
704 nread = decode_varint(&valuelen, p, end);
705 if (nread < 0 || valuelen != 0) {
706 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
707 }
708 p += nread;
709 params->disable_active_migration = 1;
710 break;
711 case NGTCP2_TRANSPORT_PARAM_ORIGINAL_DESTINATION_CONNECTION_ID:
712 if (exttype != NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS) {
713 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
714 }
715 nread = decode_cid_param(¶ms->original_dcid, p, end);
716 if (nread < 0) {
717 return (int)nread;
718 }
719 original_dcid_present = 1;
720 p += nread;
721 break;
722 case NGTCP2_TRANSPORT_PARAM_RETRY_SOURCE_CONNECTION_ID:
723 if (exttype != NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS) {
724 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
725 }
726 nread = decode_cid_param(¶ms->retry_scid, p, end);
727 if (nread < 0) {
728 return (int)nread;
729 }
730 params->retry_scid_present = 1;
731 p += nread;
732 break;
733 case NGTCP2_TRANSPORT_PARAM_INITIAL_SOURCE_CONNECTION_ID:
734 nread = decode_cid_param(¶ms->initial_scid, p, end);
735 if (nread < 0) {
736 return (int)nread;
737 }
738 initial_scid_present = 1;
739 p += nread;
740 break;
741 case NGTCP2_TRANSPORT_PARAM_MAX_ACK_DELAY:
742 nread = decode_varint_param(¶ms->max_ack_delay, p, end);
743 if (nread < 0 || params->max_ack_delay >= 16384) {
744 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
745 }
746 params->max_ack_delay *= NGTCP2_MILLISECONDS;
747 p += nread;
748 break;
749 case NGTCP2_TRANSPORT_PARAM_ACTIVE_CONNECTION_ID_LIMIT:
750 nread = decode_varint_param(¶ms->active_connection_id_limit, p, end);
751 if (nread < 0) {
752 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
753 }
754 p += nread;
755 break;
756 case NGTCP2_TRANSPORT_PARAM_MAX_DATAGRAM_FRAME_SIZE:
757 nread = decode_varint_param(¶ms->max_datagram_frame_size, p, end);
758 if (nread < 0) {
759 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
760 }
761 p += nread;
762 break;
763 case NGTCP2_TRANSPORT_PARAM_GREASE_QUIC_BIT:
764 nread = decode_varint(&valuelen, p, end);
765 if (nread < 0 || valuelen != 0) {
766 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
767 }
768 p += nread;
769 params->grease_quic_bit = 1;
770 break;
771 default:
772 /* Ignore unknown parameter */
773 nread = decode_varint(&valuelen, p, end);
774 if (nread < 0) {
775 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
776 }
777 p += nread;
778 if ((size_t)(end - p) < valuelen) {
779 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
780 }
781 p += valuelen;
782 break;
783 }
784 }
785
786 if (end - p != 0) {
787 return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
788 }
789
790 if (!initial_scid_present ||
791 (exttype == NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS &&
792 !original_dcid_present)) {
793 return NGTCP2_ERR_REQUIRED_TRANSPORT_PARAM;
794 }
795
796 return 0;
797 }
798