Bug Summary

File:out/../deps/ngtcp2/ngtcp2/lib/ngtcp2_crypto.c
Warning:line 366, column 5
Value stored to 'p' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name ngtcp2_crypto.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/home/maurizio/node-v18.6.0/out -resource-dir /usr/local/lib/clang/16.0.0 -D _U_= -D V8_DEPRECATION_WARNINGS -D V8_IMMINENT_DEPRECATION_WARNINGS -D _GLIBCXX_USE_CXX11_ABI=1 -D NODE_OPENSSL_CONF_NAME=nodejs_conf -D NODE_OPENSSL_HAS_QUIC -D __STDC_FORMAT_MACROS -D OPENSSL_NO_PINSHARED -D OPENSSL_THREADS -D BUILDING_NGTCP2 -D NGTCP2_STATICLIB -D HAVE_ARPA_INET_H -D HAVE_NETINET_IN_H -D NDEBUG -D OPENSSL_USE_NODELETE -D L_ENDIAN -D OPENSSL_BUILDING_OPENSSL -D AES_ASM -D BSAES_ASM -D CMLL_ASM -D ECP_NISTZ256_ASM -D GHASH_ASM -D KECCAK1600_ASM -D MD5_ASM -D OPENSSL_BN_ASM_GF2m -D OPENSSL_BN_ASM_MONT -D OPENSSL_BN_ASM_MONT5 -D OPENSSL_CPUID_OBJ -D OPENSSL_IA32_SSE2 -D PADLOCK_ASM -D POLY1305_ASM -D SHA1_ASM -D SHA256_ASM -D SHA512_ASM -D VPAES_ASM -D WHIRLPOOL_ASM -D X25519_ASM -D OPENSSL_PIC -I ../deps/ngtcp2 -I ../deps/ngtcp2/ngtcp2/lib/includes -I ../deps/ngtcp2/ngtcp2/crypto/includes -I ../deps/ngtcp2/ngtcp2/lib -I ../deps/ngtcp2/ngtcp2/crypto -I ../deps/openssl/openssl/include -I ../deps/openssl/openssl/crypto/include -I ../deps/openssl/config/archs/linux-x86_64/asm/include -I ../deps/openssl/config/archs/linux-x86_64/asm -internal-isystem /usr/local/lib/clang/16.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/8/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O3 -Wno-unused-parameter -fdebug-compilation-dir=/home/maurizio/node-v18.6.0/out -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2022-08-22-142216-507842-1 -x c ../deps/ngtcp2/ngtcp2/lib/ngtcp2_crypto.c
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
34int 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
55int 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
81void 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
89void 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 */
106static 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 */
115static 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 */
126static 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 */
136static 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
149ngtcp2_ssize
150ngtcp2_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 &params->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 &params->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 &params->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 &params->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 &params->retry_scid);
294 }
295 }
296
297 p = write_cid_param(p, NGTCP2_TRANSPORT_PARAM_INITIAL_SOURCE_CONNECTION_ID,
298 &params->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 */
381static 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 */
406static 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 */
446static 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
470int 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(&params->retry_scid, 0, sizeof(params->retry_scid));
503 memset(&params->initial_scid, 0, sizeof(params->initial_scid));
504 memset(&params->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(&param_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(&params->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(&params->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(&params->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(&params->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(&params->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(&params->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(&params->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(&params->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(&params->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(&params->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(&params->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(&params->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(&params->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(&params->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(&params->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}