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