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_pkt.h"
26 
27 #include <assert.h>
28 #include <string.h>
29 #include <stdio.h>
30 
31 #include "ngtcp2_conv.h"
32 #include "ngtcp2_str.h"
33 #include "ngtcp2_macro.h"
34 #include "ngtcp2_cid.h"
35 #include "ngtcp2_mem.h"
36 #include "ngtcp2_vec.h"
37 
ngtcp2_pkt_chain_new(ngtcp2_pkt_chain ** ppc,const ngtcp2_path * path,const ngtcp2_pkt_info * pi,const uint8_t * pkt,size_t pktlen,size_t dgramlen,ngtcp2_tstamp ts,const ngtcp2_mem * mem)38 int ngtcp2_pkt_chain_new(ngtcp2_pkt_chain **ppc, const ngtcp2_path *path,
39                          const ngtcp2_pkt_info *pi, const uint8_t *pkt,
40                          size_t pktlen, size_t dgramlen, ngtcp2_tstamp ts,
41                          const ngtcp2_mem *mem) {
42   *ppc = ngtcp2_mem_malloc(mem, sizeof(ngtcp2_pkt_chain) + pktlen);
43   if (*ppc == NULL) {
44     return NGTCP2_ERR_NOMEM;
45   }
46 
47   ngtcp2_path_storage_init2(&(*ppc)->path, path);
48   (*ppc)->pi = *pi;
49   (*ppc)->next = NULL;
50   (*ppc)->pkt = (uint8_t *)(*ppc) + sizeof(ngtcp2_pkt_chain);
51   (*ppc)->pktlen = pktlen;
52   (*ppc)->dgramlen = dgramlen;
53   (*ppc)->ts = ts;
54 
55   memcpy((*ppc)->pkt, pkt, pktlen);
56 
57   return 0;
58 }
59 
ngtcp2_pkt_chain_del(ngtcp2_pkt_chain * pc,const ngtcp2_mem * mem)60 void ngtcp2_pkt_chain_del(ngtcp2_pkt_chain *pc, const ngtcp2_mem *mem) {
61   ngtcp2_mem_free(mem, pc);
62 }
63 
ngtcp2_pkt_decode_version_cid(uint32_t * pversion,const uint8_t ** pdcid,size_t * pdcidlen,const uint8_t ** pscid,size_t * pscidlen,const uint8_t * data,size_t datalen,size_t short_dcidlen)64 int ngtcp2_pkt_decode_version_cid(uint32_t *pversion, const uint8_t **pdcid,
65                                   size_t *pdcidlen, const uint8_t **pscid,
66                                   size_t *pscidlen, const uint8_t *data,
67                                   size_t datalen, size_t short_dcidlen) {
68   size_t len;
69   uint32_t version;
70   size_t dcidlen, scidlen;
71 
72   assert(datalen);
73 
74   if (data[0] & NGTCP2_HEADER_FORM_BIT) {
75     /* 1 byte (Header Form, Fixed Bit, Long Packet Type, Type-Specific bits)
76      * 4 bytes Version
77      * 1 byte DCID Length
78      * 1 byte SCID Length
79      */
80     len = 1 + 4 + 1 + 1;
81     if (datalen < len) {
82       return NGTCP2_ERR_INVALID_ARGUMENT;
83     }
84 
85     dcidlen = data[5];
86     len += dcidlen;
87     if (datalen < len) {
88       return NGTCP2_ERR_INVALID_ARGUMENT;
89     }
90     scidlen = data[5 + 1 + dcidlen];
91     len += scidlen;
92     if (datalen < len) {
93       return NGTCP2_ERR_INVALID_ARGUMENT;
94     }
95 
96     version = ngtcp2_get_uint32(&data[1]);
97 
98     if ((version == 0 || version == NGTCP2_PROTO_VER_V1 ||
99          (NGTCP2_PROTO_VER_DRAFT_MIN <= version &&
100           version <= NGTCP2_PROTO_VER_DRAFT_MAX)) &&
101         (dcidlen > NGTCP2_MAX_CIDLEN || scidlen > NGTCP2_MAX_CIDLEN)) {
102       return NGTCP2_ERR_INVALID_ARGUMENT;
103     }
104 
105     *pversion = version;
106     *pdcid = &data[6];
107     *pdcidlen = dcidlen;
108     *pscid = &data[6 + dcidlen + 1];
109     *pscidlen = scidlen;
110 
111     if (version && version != NGTCP2_PROTO_VER_V1 &&
112         (version < NGTCP2_PROTO_VER_DRAFT_MIN ||
113          NGTCP2_PROTO_VER_DRAFT_MAX < version)) {
114       return NGTCP2_ERR_VERSION_NEGOTIATION;
115     }
116     return 0;
117   }
118 
119   assert(short_dcidlen <= NGTCP2_MAX_CIDLEN);
120 
121   len = 1 + short_dcidlen;
122   if (datalen < len) {
123     return NGTCP2_ERR_INVALID_ARGUMENT;
124   }
125 
126   *pversion = 0;
127   *pdcid = &data[1];
128   *pdcidlen = short_dcidlen;
129   *pscid = NULL;
130   *pscidlen = 0;
131 
132   return 0;
133 }
134 
ngtcp2_pkt_hd_init(ngtcp2_pkt_hd * hd,uint8_t flags,uint8_t type,const ngtcp2_cid * dcid,const ngtcp2_cid * scid,int64_t pkt_num,size_t pkt_numlen,uint32_t version,size_t len)135 void ngtcp2_pkt_hd_init(ngtcp2_pkt_hd *hd, uint8_t flags, uint8_t type,
136                         const ngtcp2_cid *dcid, const ngtcp2_cid *scid,
137                         int64_t pkt_num, size_t pkt_numlen, uint32_t version,
138                         size_t len) {
139   hd->flags = flags;
140   hd->type = type;
141   if (dcid) {
142     hd->dcid = *dcid;
143   } else {
144     ngtcp2_cid_zero(&hd->dcid);
145   }
146   if (scid) {
147     hd->scid = *scid;
148   } else {
149     ngtcp2_cid_zero(&hd->scid);
150   }
151   hd->pkt_num = pkt_num;
152   hd->token.base = NULL;
153   hd->token.len = 0;
154   hd->pkt_numlen = pkt_numlen;
155   hd->version = version;
156   hd->len = len;
157 }
158 
has_mask(uint8_t b,uint8_t mask)159 static int has_mask(uint8_t b, uint8_t mask) { return (b & mask) == mask; }
160 
ngtcp2_pkt_decode_hd_long(ngtcp2_pkt_hd * dest,const uint8_t * pkt,size_t pktlen)161 ngtcp2_ssize ngtcp2_pkt_decode_hd_long(ngtcp2_pkt_hd *dest, const uint8_t *pkt,
162                                        size_t pktlen) {
163   uint8_t type;
164   uint32_t version;
165   size_t dcil, scil;
166   const uint8_t *p;
167   size_t len = 0;
168   size_t n;
169   size_t ntokenlen = 0;
170   const uint8_t *token = NULL;
171   size_t tokenlen = 0;
172   uint64_t vi;
173   uint8_t flags = NGTCP2_PKT_FLAG_LONG_FORM;
174 
175   if (pktlen < 5) {
176     return NGTCP2_ERR_INVALID_ARGUMENT;
177   }
178 
179   if (!(pkt[0] & NGTCP2_HEADER_FORM_BIT)) {
180     return NGTCP2_ERR_INVALID_ARGUMENT;
181   }
182 
183   version = ngtcp2_get_uint32(&pkt[1]);
184 
185   if (version == 0) {
186     type = NGTCP2_PKT_VERSION_NEGOTIATION;
187     /* This must be Version Negotiation packet which lacks packet
188        number and payload length fields. */
189     len = 5 + 2;
190   } else {
191     if (!(pkt[0] & NGTCP2_FIXED_BIT_MASK)) {
192       flags |= NGTCP2_PKT_FLAG_FIXED_BIT_CLEAR;
193     }
194 
195     type = ngtcp2_pkt_get_type_long(pkt[0]);
196     switch (type) {
197     case NGTCP2_PKT_INITIAL:
198       len = 1 /* Token Length */ + NGTCP2_MIN_LONG_HEADERLEN -
199             1; /* Cut packet number field */
200       break;
201     case NGTCP2_PKT_RETRY:
202       /* Retry packet does not have packet number and length fields */
203       len = 5 + 2;
204       break;
205     case NGTCP2_PKT_HANDSHAKE:
206     case NGTCP2_PKT_0RTT:
207       len = NGTCP2_MIN_LONG_HEADERLEN - 1; /* Cut packet number field */
208       break;
209     default:
210       /* Unreachable */
211       assert(0);
212     }
213   }
214 
215   if (pktlen < len) {
216     return NGTCP2_ERR_INVALID_ARGUMENT;
217   }
218 
219   p = &pkt[5];
220   dcil = *p;
221   if (dcil > NGTCP2_MAX_CIDLEN) {
222     /* QUIC v1 implementation never expect to receive CID length more
223        than NGTCP2_MAX_CIDLEN. */
224     return NGTCP2_ERR_INVALID_ARGUMENT;
225   }
226   len += dcil;
227 
228   if (pktlen < len) {
229     return NGTCP2_ERR_INVALID_ARGUMENT;
230   }
231 
232   p += 1 + dcil;
233   scil = *p;
234   if (scil > NGTCP2_MAX_CIDLEN) {
235     return NGTCP2_ERR_INVALID_ARGUMENT;
236   }
237   len += scil;
238 
239   if (pktlen < len) {
240     return NGTCP2_ERR_INVALID_ARGUMENT;
241   }
242 
243   p += 1 + scil;
244 
245   if (type == NGTCP2_PKT_INITIAL) {
246     /* Token Length */
247     ntokenlen = ngtcp2_get_varint_len(p);
248     len += ntokenlen - 1;
249 
250     if (pktlen < len) {
251       return NGTCP2_ERR_INVALID_ARGUMENT;
252     }
253 
254     vi = ngtcp2_get_varint(&ntokenlen, p);
255     if (pktlen - len < vi) {
256       return NGTCP2_ERR_INVALID_ARGUMENT;
257     }
258     tokenlen = (size_t)vi;
259     len += tokenlen;
260 
261     p += ntokenlen;
262 
263     if (tokenlen) {
264       token = p;
265     }
266 
267     p += tokenlen;
268   }
269 
270   switch (type) {
271   case NGTCP2_PKT_VERSION_NEGOTIATION:
272   case NGTCP2_PKT_RETRY:
273     break;
274   default:
275     /* Length */
276     n = ngtcp2_get_varint_len(p);
277     len += n - 1;
278 
279     if (pktlen < len) {
280       return NGTCP2_ERR_INVALID_ARGUMENT;
281     }
282   }
283 
284   dest->flags = flags;
285   dest->type = type;
286   dest->version = version;
287   dest->pkt_num = 0;
288   dest->pkt_numlen = 0;
289 
290   p = &pkt[6];
291   ngtcp2_cid_init(&dest->dcid, p, dcil);
292   p += dcil + 1;
293   ngtcp2_cid_init(&dest->scid, p, scil);
294   p += scil;
295 
296   dest->token.base = (uint8_t *)token;
297   dest->token.len = tokenlen;
298   p += ntokenlen + tokenlen;
299 
300   switch (type) {
301   case NGTCP2_PKT_VERSION_NEGOTIATION:
302   case NGTCP2_PKT_RETRY:
303     dest->len = 0;
304     break;
305   default:
306     vi = ngtcp2_get_varint(&n, p);
307     if (vi > SIZE_MAX) {
308       return NGTCP2_ERR_INVALID_ARGUMENT;
309     }
310     dest->len = (size_t)vi;
311     p += n;
312   }
313 
314   assert((size_t)(p - pkt) == len);
315 
316   return (ngtcp2_ssize)len;
317 }
318 
ngtcp2_pkt_decode_hd_short(ngtcp2_pkt_hd * dest,const uint8_t * pkt,size_t pktlen,size_t dcidlen)319 ngtcp2_ssize ngtcp2_pkt_decode_hd_short(ngtcp2_pkt_hd *dest, const uint8_t *pkt,
320                                         size_t pktlen, size_t dcidlen) {
321   size_t len = 1 + dcidlen;
322   const uint8_t *p = pkt;
323   uint8_t flags = NGTCP2_PKT_FLAG_NONE;
324 
325   assert(dcidlen <= NGTCP2_MAX_CIDLEN);
326 
327   if (pktlen < len) {
328     return NGTCP2_ERR_INVALID_ARGUMENT;
329   }
330 
331   if (pkt[0] & NGTCP2_HEADER_FORM_BIT) {
332     return NGTCP2_ERR_INVALID_ARGUMENT;
333   }
334 
335   if (!(pkt[0] & NGTCP2_FIXED_BIT_MASK)) {
336     flags |= NGTCP2_PKT_FLAG_FIXED_BIT_CLEAR;
337   }
338 
339   p = &pkt[1];
340 
341   dest->type = NGTCP2_PKT_SHORT;
342 
343   ngtcp2_cid_init(&dest->dcid, p, dcidlen);
344   p += dcidlen;
345 
346   /* Set 0 to SCID so that we don't accidentally reference it and gets
347      garbage. */
348   ngtcp2_cid_zero(&dest->scid);
349 
350   dest->flags = flags;
351   dest->version = 0;
352   dest->len = 0;
353   dest->pkt_num = 0;
354   dest->pkt_numlen = 0;
355 
356   assert((size_t)(p - pkt) == len);
357 
358   return (ngtcp2_ssize)len;
359 }
360 
ngtcp2_pkt_encode_hd_long(uint8_t * out,size_t outlen,const ngtcp2_pkt_hd * hd)361 ngtcp2_ssize ngtcp2_pkt_encode_hd_long(uint8_t *out, size_t outlen,
362                                        const ngtcp2_pkt_hd *hd) {
363   uint8_t *p;
364   size_t len = NGTCP2_MIN_LONG_HEADERLEN + hd->dcid.datalen + hd->scid.datalen -
365                2; /* NGTCP2_MIN_LONG_HEADERLEN includes 1 byte for
366                      len and 1 byte for packet number. */
367 
368   if (hd->type != NGTCP2_PKT_RETRY) {
369     len += 2 /* Length */ + hd->pkt_numlen;
370   }
371 
372   if (hd->type == NGTCP2_PKT_INITIAL) {
373     len += ngtcp2_put_varint_len(hd->token.len) + hd->token.len;
374   }
375 
376   if (outlen < len) {
377     return NGTCP2_ERR_NOBUF;
378   }
379 
380   p = out;
381 
382   *p = (uint8_t)(NGTCP2_HEADER_FORM_BIT | (hd->type << 4) |
383                  (uint8_t)(hd->pkt_numlen - 1));
384   if (!(hd->flags & NGTCP2_PKT_FLAG_FIXED_BIT_CLEAR)) {
385     *p |= NGTCP2_FIXED_BIT_MASK;
386   }
387 
388   ++p;
389 
390   p = ngtcp2_put_uint32be(p, hd->version);
391   *p++ = (uint8_t)hd->dcid.datalen;
392   if (hd->dcid.datalen) {
393     p = ngtcp2_cpymem(p, hd->dcid.data, hd->dcid.datalen);
394   }
395   *p++ = (uint8_t)hd->scid.datalen;
396   if (hd->scid.datalen) {
397     p = ngtcp2_cpymem(p, hd->scid.data, hd->scid.datalen);
398   }
399 
400   if (hd->type == NGTCP2_PKT_INITIAL) {
401     p = ngtcp2_put_varint(p, hd->token.len);
402     if (hd->token.len) {
403       p = ngtcp2_cpymem(p, hd->token.base, hd->token.len);
404     }
405   }
406 
407   if (hd->type != NGTCP2_PKT_RETRY) {
408     p = ngtcp2_put_varint14(p, (uint16_t)hd->len);
409     p = ngtcp2_put_pkt_num(p, hd->pkt_num, hd->pkt_numlen);
410   }
411 
412   assert((size_t)(p - out) == len);
413 
414   return (ngtcp2_ssize)len;
415 }
416 
ngtcp2_pkt_encode_hd_short(uint8_t * out,size_t outlen,const ngtcp2_pkt_hd * hd)417 ngtcp2_ssize ngtcp2_pkt_encode_hd_short(uint8_t *out, size_t outlen,
418                                         const ngtcp2_pkt_hd *hd) {
419   uint8_t *p;
420   size_t len = 1 + hd->dcid.datalen + hd->pkt_numlen;
421 
422   if (outlen < len) {
423     return NGTCP2_ERR_NOBUF;
424   }
425 
426   p = out;
427 
428   *p = (uint8_t)(hd->pkt_numlen - 1);
429   if (!(hd->flags & NGTCP2_PKT_FLAG_FIXED_BIT_CLEAR)) {
430     *p |= NGTCP2_FIXED_BIT_MASK;
431   }
432   if (hd->flags & NGTCP2_PKT_FLAG_KEY_PHASE) {
433     *p |= NGTCP2_SHORT_KEY_PHASE_BIT;
434   }
435 
436   ++p;
437 
438   if (hd->dcid.datalen) {
439     p = ngtcp2_cpymem(p, hd->dcid.data, hd->dcid.datalen);
440   }
441 
442   p = ngtcp2_put_pkt_num(p, hd->pkt_num, hd->pkt_numlen);
443 
444   assert((size_t)(p - out) == len);
445 
446   return (ngtcp2_ssize)len;
447 }
448 
ngtcp2_pkt_decode_frame(ngtcp2_frame * dest,const uint8_t * payload,size_t payloadlen)449 ngtcp2_ssize ngtcp2_pkt_decode_frame(ngtcp2_frame *dest, const uint8_t *payload,
450                                      size_t payloadlen) {
451   uint8_t type;
452 
453   if (payloadlen == 0) {
454     return 0;
455   }
456 
457   type = payload[0];
458 
459   switch (type) {
460   case NGTCP2_FRAME_PADDING:
461     return (ngtcp2_ssize)ngtcp2_pkt_decode_padding_frame(&dest->padding,
462                                                          payload, payloadlen);
463   case NGTCP2_FRAME_RESET_STREAM:
464     return ngtcp2_pkt_decode_reset_stream_frame(&dest->reset_stream, payload,
465                                                 payloadlen);
466   case NGTCP2_FRAME_CONNECTION_CLOSE:
467   case NGTCP2_FRAME_CONNECTION_CLOSE_APP:
468     return ngtcp2_pkt_decode_connection_close_frame(&dest->connection_close,
469                                                     payload, payloadlen);
470   case NGTCP2_FRAME_MAX_DATA:
471     return ngtcp2_pkt_decode_max_data_frame(&dest->max_data, payload,
472                                             payloadlen);
473   case NGTCP2_FRAME_MAX_STREAM_DATA:
474     return ngtcp2_pkt_decode_max_stream_data_frame(&dest->max_stream_data,
475                                                    payload, payloadlen);
476   case NGTCP2_FRAME_MAX_STREAMS_BIDI:
477   case NGTCP2_FRAME_MAX_STREAMS_UNI:
478     return ngtcp2_pkt_decode_max_streams_frame(&dest->max_streams, payload,
479                                                payloadlen);
480   case NGTCP2_FRAME_PING:
481     return ngtcp2_pkt_decode_ping_frame(&dest->ping, payload, payloadlen);
482   case NGTCP2_FRAME_DATA_BLOCKED:
483     return ngtcp2_pkt_decode_data_blocked_frame(&dest->data_blocked, payload,
484                                                 payloadlen);
485   case NGTCP2_FRAME_STREAM_DATA_BLOCKED:
486     return ngtcp2_pkt_decode_stream_data_blocked_frame(
487         &dest->stream_data_blocked, payload, payloadlen);
488   case NGTCP2_FRAME_STREAMS_BLOCKED_BIDI:
489   case NGTCP2_FRAME_STREAMS_BLOCKED_UNI:
490     return ngtcp2_pkt_decode_streams_blocked_frame(&dest->streams_blocked,
491                                                    payload, payloadlen);
492   case NGTCP2_FRAME_NEW_CONNECTION_ID:
493     return ngtcp2_pkt_decode_new_connection_id_frame(&dest->new_connection_id,
494                                                      payload, payloadlen);
495   case NGTCP2_FRAME_STOP_SENDING:
496     return ngtcp2_pkt_decode_stop_sending_frame(&dest->stop_sending, payload,
497                                                 payloadlen);
498   case NGTCP2_FRAME_ACK:
499   case NGTCP2_FRAME_ACK_ECN:
500     return ngtcp2_pkt_decode_ack_frame(&dest->ack, payload, payloadlen);
501   case NGTCP2_FRAME_PATH_CHALLENGE:
502     return ngtcp2_pkt_decode_path_challenge_frame(&dest->path_challenge,
503                                                   payload, payloadlen);
504   case NGTCP2_FRAME_PATH_RESPONSE:
505     return ngtcp2_pkt_decode_path_response_frame(&dest->path_response, payload,
506                                                  payloadlen);
507   case NGTCP2_FRAME_CRYPTO:
508     return ngtcp2_pkt_decode_crypto_frame(&dest->crypto, payload, payloadlen);
509   case NGTCP2_FRAME_NEW_TOKEN:
510     return ngtcp2_pkt_decode_new_token_frame(&dest->new_token, payload,
511                                              payloadlen);
512   case NGTCP2_FRAME_RETIRE_CONNECTION_ID:
513     return ngtcp2_pkt_decode_retire_connection_id_frame(
514         &dest->retire_connection_id, payload, payloadlen);
515   case NGTCP2_FRAME_HANDSHAKE_DONE:
516     return ngtcp2_pkt_decode_handshake_done_frame(&dest->handshake_done,
517                                                   payload, payloadlen);
518   case NGTCP2_FRAME_DATAGRAM:
519   case NGTCP2_FRAME_DATAGRAM_LEN:
520     return ngtcp2_pkt_decode_datagram_frame(&dest->datagram, payload,
521                                             payloadlen);
522   default:
523     if (has_mask(type, NGTCP2_FRAME_STREAM)) {
524       return ngtcp2_pkt_decode_stream_frame(&dest->stream, payload, payloadlen);
525     }
526     return NGTCP2_ERR_FRAME_ENCODING;
527   }
528 }
529 
ngtcp2_pkt_decode_stream_frame(ngtcp2_stream * dest,const uint8_t * payload,size_t payloadlen)530 ngtcp2_ssize ngtcp2_pkt_decode_stream_frame(ngtcp2_stream *dest,
531                                             const uint8_t *payload,
532                                             size_t payloadlen) {
533   uint8_t type;
534   size_t len = 1 + 1;
535   const uint8_t *p;
536   size_t datalen;
537   size_t ndatalen = 0;
538   size_t n;
539   uint64_t vi;
540 
541   if (payloadlen < len) {
542     return NGTCP2_ERR_FRAME_ENCODING;
543   }
544 
545   type = payload[0];
546 
547   p = payload + 1;
548 
549   n = ngtcp2_get_varint_len(p);
550   len += n - 1;
551 
552   if (payloadlen < len) {
553     return NGTCP2_ERR_FRAME_ENCODING;
554   }
555 
556   p += n;
557 
558   if (type & NGTCP2_STREAM_OFF_BIT) {
559     ++len;
560     if (payloadlen < len) {
561       return NGTCP2_ERR_FRAME_ENCODING;
562     }
563 
564     n = ngtcp2_get_varint_len(p);
565     len += n - 1;
566 
567     if (payloadlen < len) {
568       return NGTCP2_ERR_FRAME_ENCODING;
569     }
570 
571     p += n;
572   }
573 
574   if (type & NGTCP2_STREAM_LEN_BIT) {
575     ++len;
576     if (payloadlen < len) {
577       return NGTCP2_ERR_FRAME_ENCODING;
578     }
579 
580     ndatalen = ngtcp2_get_varint_len(p);
581     len += ndatalen - 1;
582 
583     if (payloadlen < len) {
584       return NGTCP2_ERR_FRAME_ENCODING;
585     }
586 
587     vi = ngtcp2_get_varint(&ndatalen, p);
588     if (payloadlen - len < vi) {
589       return NGTCP2_ERR_FRAME_ENCODING;
590     }
591     datalen = (size_t)vi;
592     len += datalen;
593   } else {
594     len = payloadlen;
595   }
596 
597   p = payload + 1;
598 
599   dest->type = NGTCP2_FRAME_STREAM;
600   dest->flags = (uint8_t)(type & ~NGTCP2_FRAME_STREAM);
601   dest->fin = (type & NGTCP2_STREAM_FIN_BIT) != 0;
602   dest->stream_id = (int64_t)ngtcp2_get_varint(&n, p);
603   p += n;
604 
605   if (type & NGTCP2_STREAM_OFF_BIT) {
606     dest->offset = ngtcp2_get_varint(&n, p);
607     p += n;
608   } else {
609     dest->offset = 0;
610   }
611 
612   if (type & NGTCP2_STREAM_LEN_BIT) {
613     p += ndatalen;
614   } else {
615     datalen = payloadlen - (size_t)(p - payload);
616   }
617 
618   if (datalen) {
619     dest->data[0].len = datalen;
620     dest->data[0].base = (uint8_t *)p;
621     dest->datacnt = 1;
622     p += datalen;
623   } else {
624     dest->datacnt = 0;
625   }
626 
627   assert((size_t)(p - payload) == len);
628 
629   return (ngtcp2_ssize)len;
630 }
631 
ngtcp2_pkt_decode_ack_frame(ngtcp2_ack * dest,const uint8_t * payload,size_t payloadlen)632 ngtcp2_ssize ngtcp2_pkt_decode_ack_frame(ngtcp2_ack *dest,
633                                          const uint8_t *payload,
634                                          size_t payloadlen) {
635   size_t num_blks, max_num_blks;
636   size_t nnum_blks;
637   size_t len = 1 + 1 + 1 + 1 + 1;
638   const uint8_t *p;
639   size_t i, j;
640   ngtcp2_ack_blk *blk;
641   size_t n;
642   uint8_t type;
643   uint64_t vi;
644 
645   if (payloadlen < len) {
646     return NGTCP2_ERR_FRAME_ENCODING;
647   }
648 
649   type = payload[0];
650 
651   p = payload + 1;
652 
653   /* Largest Acknowledged */
654   n = ngtcp2_get_varint_len(p);
655   len += n - 1;
656 
657   if (payloadlen < len) {
658     return NGTCP2_ERR_FRAME_ENCODING;
659   }
660 
661   p += n;
662 
663   /* ACK Delay */
664   n = ngtcp2_get_varint_len(p);
665   len += n - 1;
666 
667   if (payloadlen < len) {
668     return NGTCP2_ERR_FRAME_ENCODING;
669   }
670 
671   p += n;
672 
673   /* ACK Block Count */
674   nnum_blks = ngtcp2_get_varint_len(p);
675   len += nnum_blks - 1;
676 
677   if (payloadlen < len) {
678     return NGTCP2_ERR_FRAME_ENCODING;
679   }
680 
681   vi = ngtcp2_get_varint(&nnum_blks, p);
682   if (vi > SIZE_MAX / (1 + 1) || payloadlen - len < vi * (1 + 1)) {
683     return NGTCP2_ERR_FRAME_ENCODING;
684   }
685 
686   num_blks = (size_t)vi;
687   len += num_blks * (1 + 1);
688 
689   p += nnum_blks;
690 
691   /* First ACK Block */
692   n = ngtcp2_get_varint_len(p);
693   len += n - 1;
694 
695   if (payloadlen < len) {
696     return NGTCP2_ERR_FRAME_ENCODING;
697   }
698 
699   p += n;
700 
701   for (i = 0; i < num_blks; ++i) {
702     /* Gap, and Additional ACK Block */
703     for (j = 0; j < 2; ++j) {
704       n = ngtcp2_get_varint_len(p);
705       len += n - 1;
706 
707       if (payloadlen < len) {
708         return NGTCP2_ERR_FRAME_ENCODING;
709       }
710 
711       p += n;
712     }
713   }
714 
715   if (type == NGTCP2_FRAME_ACK_ECN) {
716     len += 3;
717     if (payloadlen < len) {
718       return NGTCP2_ERR_FRAME_ENCODING;
719     }
720 
721     for (i = 0; i < 3; ++i) {
722       n = ngtcp2_get_varint_len(p);
723       len += n - 1;
724 
725       if (payloadlen < len) {
726         return NGTCP2_ERR_FRAME_ENCODING;
727       }
728 
729       p += n;
730     }
731   }
732 
733   /* TODO We might not decode all blocks.  It could be very large. */
734   max_num_blks = ngtcp2_min(NGTCP2_MAX_ACK_BLKS, num_blks);
735 
736   p = payload + 1;
737 
738   dest->type = type;
739   dest->largest_ack = (int64_t)ngtcp2_get_varint(&n, p);
740   p += n;
741   dest->ack_delay = ngtcp2_get_varint(&n, p);
742   /* This value will be assigned in the upper layer. */
743   dest->ack_delay_unscaled = 0;
744   p += n;
745   dest->num_blks = max_num_blks;
746   p += nnum_blks;
747   dest->first_ack_blklen = ngtcp2_get_varint(&n, p);
748   p += n;
749 
750   for (i = 0; i < max_num_blks; ++i) {
751     blk = &dest->blks[i];
752     blk->gap = ngtcp2_get_varint(&n, p);
753     p += n;
754     blk->blklen = ngtcp2_get_varint(&n, p);
755     p += n;
756   }
757   for (i = max_num_blks; i < num_blks; ++i) {
758     p += ngtcp2_get_varint_len(p);
759     p += ngtcp2_get_varint_len(p);
760   }
761 
762   if (type == NGTCP2_FRAME_ACK_ECN) {
763     dest->ecn.ect0 = ngtcp2_get_varint(&n, p);
764     p += n;
765 
766     dest->ecn.ect1 = ngtcp2_get_varint(&n, p);
767     p += n;
768 
769     dest->ecn.ce = ngtcp2_get_varint(&n, p);
770     p += n;
771   }
772 
773   assert((size_t)(p - payload) == len);
774 
775   return (ngtcp2_ssize)len;
776 }
777 
ngtcp2_pkt_decode_padding_frame(ngtcp2_padding * dest,const uint8_t * payload,size_t payloadlen)778 size_t ngtcp2_pkt_decode_padding_frame(ngtcp2_padding *dest,
779                                        const uint8_t *payload,
780                                        size_t payloadlen) {
781   const uint8_t *p, *ep;
782 
783   assert(payloadlen > 0);
784 
785   p = payload + 1;
786   ep = payload + payloadlen;
787 
788   for (; p != ep && *p == NGTCP2_FRAME_PADDING; ++p)
789     ;
790 
791   dest->type = NGTCP2_FRAME_PADDING;
792   dest->len = (size_t)(p - payload);
793 
794   return dest->len;
795 }
796 
ngtcp2_pkt_decode_reset_stream_frame(ngtcp2_reset_stream * dest,const uint8_t * payload,size_t payloadlen)797 ngtcp2_ssize ngtcp2_pkt_decode_reset_stream_frame(ngtcp2_reset_stream *dest,
798                                                   const uint8_t *payload,
799                                                   size_t payloadlen) {
800   size_t len = 1 + 1 + 1 + 1;
801   const uint8_t *p;
802   size_t n;
803 
804   if (payloadlen < len) {
805     return NGTCP2_ERR_FRAME_ENCODING;
806   }
807 
808   p = payload + 1;
809 
810   n = ngtcp2_get_varint_len(p);
811   len += n - 1;
812   if (payloadlen < len) {
813     return NGTCP2_ERR_FRAME_ENCODING;
814   }
815   p += n;
816   n = ngtcp2_get_varint_len(p);
817   len += n - 1;
818   if (payloadlen < len) {
819     return NGTCP2_ERR_FRAME_ENCODING;
820   }
821   p += n;
822   n = ngtcp2_get_varint_len(p);
823   len += n - 1;
824   if (payloadlen < len) {
825     return NGTCP2_ERR_FRAME_ENCODING;
826   }
827 
828   p = payload + 1;
829 
830   dest->type = NGTCP2_FRAME_RESET_STREAM;
831   dest->stream_id = (int64_t)ngtcp2_get_varint(&n, p);
832   p += n;
833   dest->app_error_code = ngtcp2_get_varint(&n, p);
834   p += n;
835   dest->final_size = ngtcp2_get_varint(&n, p);
836   p += n;
837 
838   assert((size_t)(p - payload) == len);
839 
840   return (ngtcp2_ssize)len;
841 }
842 
ngtcp2_pkt_decode_connection_close_frame(ngtcp2_connection_close * dest,const uint8_t * payload,size_t payloadlen)843 ngtcp2_ssize ngtcp2_pkt_decode_connection_close_frame(
844     ngtcp2_connection_close *dest, const uint8_t *payload, size_t payloadlen) {
845   size_t len = 1 + 1 + 1;
846   const uint8_t *p;
847   size_t reasonlen;
848   size_t nreasonlen;
849   size_t n;
850   uint8_t type;
851   uint64_t vi;
852 
853   if (payloadlen < len) {
854     return NGTCP2_ERR_FRAME_ENCODING;
855   }
856 
857   type = payload[0];
858 
859   p = payload + 1;
860 
861   n = ngtcp2_get_varint_len(p);
862   len += n - 1;
863   if (payloadlen < len) {
864     return NGTCP2_ERR_FRAME_ENCODING;
865   }
866 
867   p += n;
868 
869   if (type == NGTCP2_FRAME_CONNECTION_CLOSE) {
870     ++len;
871 
872     n = ngtcp2_get_varint_len(p);
873     len += n - 1;
874     if (payloadlen < len) {
875       return NGTCP2_ERR_FRAME_ENCODING;
876     }
877 
878     p += n;
879   }
880 
881   nreasonlen = ngtcp2_get_varint_len(p);
882   len += nreasonlen - 1;
883   if (payloadlen < len) {
884     return NGTCP2_ERR_FRAME_ENCODING;
885   }
886 
887   vi = ngtcp2_get_varint(&nreasonlen, p);
888   if (payloadlen - len < vi) {
889     return NGTCP2_ERR_FRAME_ENCODING;
890   }
891   reasonlen = (size_t)vi;
892   len += reasonlen;
893 
894   p = payload + 1;
895 
896   dest->type = type;
897   dest->error_code = ngtcp2_get_varint(&n, p);
898   p += n;
899   if (type == NGTCP2_FRAME_CONNECTION_CLOSE) {
900     dest->frame_type = ngtcp2_get_varint(&n, p);
901     p += n;
902   } else {
903     dest->frame_type = 0;
904   }
905   dest->reasonlen = reasonlen;
906   p += nreasonlen;
907   if (reasonlen == 0) {
908     dest->reason = NULL;
909   } else {
910     dest->reason = (uint8_t *)p;
911     p += reasonlen;
912   }
913 
914   assert((size_t)(p - payload) == len);
915 
916   return (ngtcp2_ssize)len;
917 }
918 
ngtcp2_pkt_decode_max_data_frame(ngtcp2_max_data * dest,const uint8_t * payload,size_t payloadlen)919 ngtcp2_ssize ngtcp2_pkt_decode_max_data_frame(ngtcp2_max_data *dest,
920                                               const uint8_t *payload,
921                                               size_t payloadlen) {
922   size_t len = 1 + 1;
923   const uint8_t *p;
924   size_t n;
925 
926   if (payloadlen < len) {
927     return NGTCP2_ERR_FRAME_ENCODING;
928   }
929 
930   p = payload + 1;
931 
932   n = ngtcp2_get_varint_len(p);
933   len += n - 1;
934 
935   if (payloadlen < len) {
936     return NGTCP2_ERR_FRAME_ENCODING;
937   }
938 
939   dest->type = NGTCP2_FRAME_MAX_DATA;
940   dest->max_data = ngtcp2_get_varint(&n, p);
941   p += n;
942 
943   assert((size_t)(p - payload) == len);
944 
945   return (ngtcp2_ssize)len;
946 }
947 
ngtcp2_pkt_decode_max_stream_data_frame(ngtcp2_max_stream_data * dest,const uint8_t * payload,size_t payloadlen)948 ngtcp2_ssize ngtcp2_pkt_decode_max_stream_data_frame(
949     ngtcp2_max_stream_data *dest, const uint8_t *payload, size_t payloadlen) {
950   size_t len = 1 + 1 + 1;
951   const uint8_t *p;
952   size_t n;
953 
954   if (payloadlen < len) {
955     return NGTCP2_ERR_FRAME_ENCODING;
956   }
957 
958   p = payload + 1;
959 
960   n = ngtcp2_get_varint_len(p);
961   len += n - 1;
962 
963   if (payloadlen < len) {
964     return NGTCP2_ERR_FRAME_ENCODING;
965   }
966 
967   p += n;
968 
969   n = ngtcp2_get_varint_len(p);
970   len += n - 1;
971 
972   if (payloadlen < len) {
973     return NGTCP2_ERR_FRAME_ENCODING;
974   }
975 
976   p = payload + 1;
977 
978   dest->type = NGTCP2_FRAME_MAX_STREAM_DATA;
979   dest->stream_id = (int64_t)ngtcp2_get_varint(&n, p);
980   p += n;
981   dest->max_stream_data = ngtcp2_get_varint(&n, p);
982   p += n;
983 
984   assert((size_t)(p - payload) == len);
985 
986   return (ngtcp2_ssize)len;
987 }
988 
ngtcp2_pkt_decode_max_streams_frame(ngtcp2_max_streams * dest,const uint8_t * payload,size_t payloadlen)989 ngtcp2_ssize ngtcp2_pkt_decode_max_streams_frame(ngtcp2_max_streams *dest,
990                                                  const uint8_t *payload,
991                                                  size_t payloadlen) {
992   size_t len = 1 + 1;
993   const uint8_t *p;
994   size_t n;
995 
996   if (payloadlen < len) {
997     return NGTCP2_ERR_FRAME_ENCODING;
998   }
999 
1000   p = payload + 1;
1001 
1002   n = ngtcp2_get_varint_len(p);
1003   len += n - 1;
1004 
1005   if (payloadlen < len) {
1006     return NGTCP2_ERR_FRAME_ENCODING;
1007   }
1008 
1009   dest->type = payload[0];
1010   dest->max_streams = ngtcp2_get_varint(&n, p);
1011   p += n;
1012 
1013   assert((size_t)(p - payload) == len);
1014 
1015   return (ngtcp2_ssize)len;
1016 }
1017 
ngtcp2_pkt_decode_ping_frame(ngtcp2_ping * dest,const uint8_t * payload,size_t payloadlen)1018 ngtcp2_ssize ngtcp2_pkt_decode_ping_frame(ngtcp2_ping *dest,
1019                                           const uint8_t *payload,
1020                                           size_t payloadlen) {
1021   (void)payload;
1022   (void)payloadlen;
1023 
1024   dest->type = NGTCP2_FRAME_PING;
1025   return 1;
1026 }
1027 
ngtcp2_pkt_decode_data_blocked_frame(ngtcp2_data_blocked * dest,const uint8_t * payload,size_t payloadlen)1028 ngtcp2_ssize ngtcp2_pkt_decode_data_blocked_frame(ngtcp2_data_blocked *dest,
1029                                                   const uint8_t *payload,
1030                                                   size_t payloadlen) {
1031   size_t len = 1 + 1;
1032   const uint8_t *p;
1033   size_t n;
1034 
1035   if (payloadlen < len) {
1036     return NGTCP2_ERR_FRAME_ENCODING;
1037   }
1038 
1039   p = payload + 1;
1040 
1041   n = ngtcp2_get_varint_len(p);
1042   len += n - 1;
1043 
1044   if (payloadlen < len) {
1045     return NGTCP2_ERR_FRAME_ENCODING;
1046   }
1047 
1048   dest->type = NGTCP2_FRAME_DATA_BLOCKED;
1049   dest->offset = ngtcp2_get_varint(&n, p);
1050   p += n;
1051 
1052   assert((size_t)(p - payload) == len);
1053 
1054   return (ngtcp2_ssize)len;
1055 }
1056 
1057 ngtcp2_ssize
ngtcp2_pkt_decode_stream_data_blocked_frame(ngtcp2_stream_data_blocked * dest,const uint8_t * payload,size_t payloadlen)1058 ngtcp2_pkt_decode_stream_data_blocked_frame(ngtcp2_stream_data_blocked *dest,
1059                                             const uint8_t *payload,
1060                                             size_t payloadlen) {
1061   size_t len = 1 + 1 + 1;
1062   const uint8_t *p;
1063   size_t n;
1064 
1065   if (payloadlen < len) {
1066     return NGTCP2_ERR_FRAME_ENCODING;
1067   }
1068 
1069   p = payload + 1;
1070 
1071   n = ngtcp2_get_varint_len(p);
1072   len += n - 1;
1073 
1074   if (payloadlen < len) {
1075     return NGTCP2_ERR_FRAME_ENCODING;
1076   }
1077 
1078   p += n;
1079 
1080   n = ngtcp2_get_varint_len(p);
1081   len += n - 1;
1082 
1083   if (payloadlen < len) {
1084     return NGTCP2_ERR_FRAME_ENCODING;
1085   }
1086 
1087   p = payload + 1;
1088 
1089   dest->type = NGTCP2_FRAME_STREAM_DATA_BLOCKED;
1090   dest->stream_id = (int64_t)ngtcp2_get_varint(&n, p);
1091   p += n;
1092   dest->offset = ngtcp2_get_varint(&n, p);
1093   p += n;
1094 
1095   assert((size_t)(p - payload) == len);
1096 
1097   return (ngtcp2_ssize)len;
1098 }
1099 
ngtcp2_pkt_decode_streams_blocked_frame(ngtcp2_streams_blocked * dest,const uint8_t * payload,size_t payloadlen)1100 ngtcp2_ssize ngtcp2_pkt_decode_streams_blocked_frame(
1101     ngtcp2_streams_blocked *dest, const uint8_t *payload, size_t payloadlen) {
1102   size_t len = 1 + 1;
1103   const uint8_t *p;
1104   size_t n;
1105 
1106   if (payloadlen < len) {
1107     return NGTCP2_ERR_FRAME_ENCODING;
1108   }
1109 
1110   p = payload + 1;
1111 
1112   n = ngtcp2_get_varint_len(p);
1113   len += n - 1;
1114 
1115   if (payloadlen < len) {
1116     return NGTCP2_ERR_FRAME_ENCODING;
1117   }
1118 
1119   dest->type = payload[0];
1120   dest->max_streams = ngtcp2_get_varint(&n, p);
1121   p += n;
1122 
1123   assert((size_t)(p - payload) == len);
1124 
1125   return (ngtcp2_ssize)len;
1126 }
1127 
ngtcp2_pkt_decode_new_connection_id_frame(ngtcp2_new_connection_id * dest,const uint8_t * payload,size_t payloadlen)1128 ngtcp2_ssize ngtcp2_pkt_decode_new_connection_id_frame(
1129     ngtcp2_new_connection_id *dest, const uint8_t *payload, size_t payloadlen) {
1130   size_t len = 1 + 1 + 1 + 1 + 16;
1131   const uint8_t *p;
1132   size_t n;
1133   size_t cil;
1134 
1135   if (payloadlen < len) {
1136     return NGTCP2_ERR_FRAME_ENCODING;
1137   }
1138 
1139   p = payload + 1;
1140 
1141   n = ngtcp2_get_varint_len(p);
1142   len += n - 1;
1143   if (payloadlen < len) {
1144     return NGTCP2_ERR_FRAME_ENCODING;
1145   }
1146 
1147   p += n;
1148 
1149   n = ngtcp2_get_varint_len(p);
1150   len += n - 1;
1151   if (payloadlen < len) {
1152     return NGTCP2_ERR_FRAME_ENCODING;
1153   }
1154 
1155   p += n;
1156 
1157   cil = *p;
1158   if (cil < NGTCP2_MIN_CIDLEN || cil > NGTCP2_MAX_CIDLEN) {
1159     return NGTCP2_ERR_FRAME_ENCODING;
1160   }
1161 
1162   len += cil;
1163   if (payloadlen < len) {
1164     return NGTCP2_ERR_FRAME_ENCODING;
1165   }
1166 
1167   p = payload + 1;
1168 
1169   dest->type = NGTCP2_FRAME_NEW_CONNECTION_ID;
1170   dest->seq = ngtcp2_get_varint(&n, p);
1171   p += n;
1172   dest->retire_prior_to = ngtcp2_get_varint(&n, p);
1173   p += n + 1;
1174   ngtcp2_cid_init(&dest->cid, p, cil);
1175   p += cil;
1176   memcpy(dest->stateless_reset_token, p, NGTCP2_STATELESS_RESET_TOKENLEN);
1177   p += NGTCP2_STATELESS_RESET_TOKENLEN;
1178 
1179   assert((size_t)(p - payload) == len);
1180 
1181   return (ngtcp2_ssize)len;
1182 }
1183 
ngtcp2_pkt_decode_stop_sending_frame(ngtcp2_stop_sending * dest,const uint8_t * payload,size_t payloadlen)1184 ngtcp2_ssize ngtcp2_pkt_decode_stop_sending_frame(ngtcp2_stop_sending *dest,
1185                                                   const uint8_t *payload,
1186                                                   size_t payloadlen) {
1187   size_t len = 1 + 1 + 1;
1188   const uint8_t *p;
1189   size_t n;
1190 
1191   if (payloadlen < len) {
1192     return NGTCP2_ERR_FRAME_ENCODING;
1193   }
1194 
1195   p = payload + 1;
1196 
1197   n = ngtcp2_get_varint_len(p);
1198   len += n - 1;
1199 
1200   if (payloadlen < len) {
1201     return NGTCP2_ERR_FRAME_ENCODING;
1202   }
1203   p += n;
1204   n = ngtcp2_get_varint_len(p);
1205   len += n - 1;
1206 
1207   if (payloadlen < len) {
1208     return NGTCP2_ERR_FRAME_ENCODING;
1209   }
1210 
1211   p = payload + 1;
1212 
1213   dest->type = NGTCP2_FRAME_STOP_SENDING;
1214   dest->stream_id = (int64_t)ngtcp2_get_varint(&n, p);
1215   p += n;
1216   dest->app_error_code = ngtcp2_get_varint(&n, p);
1217   p += n;
1218 
1219   assert((size_t)(p - payload) == len);
1220 
1221   return (ngtcp2_ssize)len;
1222 }
1223 
ngtcp2_pkt_decode_path_challenge_frame(ngtcp2_path_challenge * dest,const uint8_t * payload,size_t payloadlen)1224 ngtcp2_ssize ngtcp2_pkt_decode_path_challenge_frame(ngtcp2_path_challenge *dest,
1225                                                     const uint8_t *payload,
1226                                                     size_t payloadlen) {
1227   size_t len = 1 + 8;
1228   const uint8_t *p;
1229 
1230   if (payloadlen < len) {
1231     return NGTCP2_ERR_FRAME_ENCODING;
1232   }
1233 
1234   p = payload + 1;
1235 
1236   dest->type = NGTCP2_FRAME_PATH_CHALLENGE;
1237   ngtcp2_cpymem(dest->data, p, sizeof(dest->data));
1238   p += sizeof(dest->data);
1239 
1240   assert((size_t)(p - payload) == len);
1241 
1242   return (ngtcp2_ssize)len;
1243 }
1244 
ngtcp2_pkt_decode_path_response_frame(ngtcp2_path_response * dest,const uint8_t * payload,size_t payloadlen)1245 ngtcp2_ssize ngtcp2_pkt_decode_path_response_frame(ngtcp2_path_response *dest,
1246                                                    const uint8_t *payload,
1247                                                    size_t payloadlen) {
1248   size_t len = 1 + 8;
1249   const uint8_t *p;
1250 
1251   if (payloadlen < len) {
1252     return NGTCP2_ERR_FRAME_ENCODING;
1253   }
1254 
1255   p = payload + 1;
1256 
1257   dest->type = NGTCP2_FRAME_PATH_RESPONSE;
1258   ngtcp2_cpymem(dest->data, p, sizeof(dest->data));
1259   p += sizeof(dest->data);
1260 
1261   assert((size_t)(p - payload) == len);
1262 
1263   return (ngtcp2_ssize)len;
1264 }
1265 
ngtcp2_pkt_decode_crypto_frame(ngtcp2_crypto * dest,const uint8_t * payload,size_t payloadlen)1266 ngtcp2_ssize ngtcp2_pkt_decode_crypto_frame(ngtcp2_crypto *dest,
1267                                             const uint8_t *payload,
1268                                             size_t payloadlen) {
1269   size_t len = 1 + 1 + 1;
1270   const uint8_t *p;
1271   size_t datalen;
1272   size_t ndatalen;
1273   size_t n;
1274   uint64_t vi;
1275 
1276   if (payloadlen < len) {
1277     return NGTCP2_ERR_FRAME_ENCODING;
1278   }
1279 
1280   p = payload + 1;
1281 
1282   n = ngtcp2_get_varint_len(p);
1283   len += n - 1;
1284 
1285   if (payloadlen < len) {
1286     return NGTCP2_ERR_FRAME_ENCODING;
1287   }
1288 
1289   p += n;
1290 
1291   ndatalen = ngtcp2_get_varint_len(p);
1292   len += ndatalen - 1;
1293 
1294   if (payloadlen < len) {
1295     return NGTCP2_ERR_FRAME_ENCODING;
1296   }
1297 
1298   vi = ngtcp2_get_varint(&ndatalen, p);
1299   if (payloadlen - len < vi) {
1300     return NGTCP2_ERR_FRAME_ENCODING;
1301   }
1302 
1303   datalen = (size_t)vi;
1304   len += datalen;
1305 
1306   p = payload + 1;
1307 
1308   dest->type = NGTCP2_FRAME_CRYPTO;
1309   dest->offset = ngtcp2_get_varint(&n, p);
1310   p += n;
1311   dest->data[0].len = datalen;
1312   p += ndatalen;
1313   if (dest->data[0].len) {
1314     dest->data[0].base = (uint8_t *)p;
1315     p += dest->data[0].len;
1316     dest->datacnt = 1;
1317   } else {
1318     dest->data[0].base = NULL;
1319     dest->datacnt = 0;
1320   }
1321 
1322   assert((size_t)(p - payload) == len);
1323 
1324   return (ngtcp2_ssize)len;
1325 }
1326 
ngtcp2_pkt_decode_new_token_frame(ngtcp2_new_token * dest,const uint8_t * payload,size_t payloadlen)1327 ngtcp2_ssize ngtcp2_pkt_decode_new_token_frame(ngtcp2_new_token *dest,
1328                                                const uint8_t *payload,
1329                                                size_t payloadlen) {
1330   size_t len = 1 + 1;
1331   const uint8_t *p;
1332   size_t n;
1333   size_t datalen;
1334   uint64_t vi;
1335 
1336   if (payloadlen < len) {
1337     return NGTCP2_ERR_FRAME_ENCODING;
1338   }
1339 
1340   p = payload + 1;
1341 
1342   n = ngtcp2_get_varint_len(p);
1343   len += n - 1;
1344 
1345   if (payloadlen < len) {
1346     return NGTCP2_ERR_FRAME_ENCODING;
1347   }
1348 
1349   vi = ngtcp2_get_varint(&n, p);
1350   if (payloadlen - len < vi) {
1351     return NGTCP2_ERR_FRAME_ENCODING;
1352   }
1353   datalen = (size_t)vi;
1354   len += datalen;
1355 
1356   dest->type = NGTCP2_FRAME_NEW_TOKEN;
1357   dest->token.len = datalen;
1358   p += n;
1359   dest->token.base = (uint8_t *)p;
1360   p += dest->token.len;
1361 
1362   assert((size_t)(p - payload) == len);
1363 
1364   return (ngtcp2_ssize)len;
1365 }
1366 
1367 ngtcp2_ssize
ngtcp2_pkt_decode_retire_connection_id_frame(ngtcp2_retire_connection_id * dest,const uint8_t * payload,size_t payloadlen)1368 ngtcp2_pkt_decode_retire_connection_id_frame(ngtcp2_retire_connection_id *dest,
1369                                              const uint8_t *payload,
1370                                              size_t payloadlen) {
1371   size_t len = 1 + 1;
1372   const uint8_t *p;
1373   size_t n;
1374 
1375   if (payloadlen < len) {
1376     return NGTCP2_ERR_FRAME_ENCODING;
1377   }
1378 
1379   p = payload + 1;
1380 
1381   n = ngtcp2_get_varint_len(p);
1382   len += n - 1;
1383 
1384   if (payloadlen < len) {
1385     return NGTCP2_ERR_FRAME_ENCODING;
1386   }
1387 
1388   dest->type = NGTCP2_FRAME_RETIRE_CONNECTION_ID;
1389   dest->seq = ngtcp2_get_varint(&n, p);
1390   p += n;
1391 
1392   assert((size_t)(p - payload) == len);
1393 
1394   return (ngtcp2_ssize)len;
1395 }
1396 
ngtcp2_pkt_decode_handshake_done_frame(ngtcp2_handshake_done * dest,const uint8_t * payload,size_t payloadlen)1397 ngtcp2_ssize ngtcp2_pkt_decode_handshake_done_frame(ngtcp2_handshake_done *dest,
1398                                                     const uint8_t *payload,
1399                                                     size_t payloadlen) {
1400   (void)payload;
1401   (void)payloadlen;
1402 
1403   dest->type = NGTCP2_FRAME_HANDSHAKE_DONE;
1404   return 1;
1405 }
1406 
ngtcp2_pkt_decode_datagram_frame(ngtcp2_datagram * dest,const uint8_t * payload,size_t payloadlen)1407 ngtcp2_ssize ngtcp2_pkt_decode_datagram_frame(ngtcp2_datagram *dest,
1408                                               const uint8_t *payload,
1409                                               size_t payloadlen) {
1410   size_t len = 1;
1411   const uint8_t *p;
1412   uint8_t type;
1413   size_t datalen;
1414   size_t n;
1415   uint64_t vi;
1416 
1417   if (payloadlen < len) {
1418     return NGTCP2_ERR_FRAME_ENCODING;
1419   }
1420 
1421   type = payload[0];
1422 
1423   p = payload + 1;
1424 
1425   switch (type) {
1426   case NGTCP2_FRAME_DATAGRAM:
1427     datalen = payloadlen - 1;
1428     len = payloadlen;
1429     break;
1430   case NGTCP2_FRAME_DATAGRAM_LEN:
1431     ++len;
1432     if (payloadlen < len) {
1433       return NGTCP2_ERR_FRAME_ENCODING;
1434     }
1435 
1436     n = ngtcp2_get_varint_len(p);
1437     len += n - 1;
1438 
1439     if (payloadlen < len) {
1440       return NGTCP2_ERR_FRAME_ENCODING;
1441     }
1442 
1443     vi = ngtcp2_get_varint(&n, p);
1444     if (payloadlen - len < vi) {
1445       return NGTCP2_ERR_FRAME_ENCODING;
1446     }
1447 
1448     datalen = (size_t)vi;
1449     len += datalen;
1450     break;
1451   default:
1452     assert(0);
1453     abort();
1454   }
1455 
1456   dest->type = type;
1457 
1458   if (datalen == 0) {
1459     dest->datacnt = 0;
1460     dest->data = NULL;
1461 
1462     if (type == NGTCP2_FRAME_DATAGRAM_LEN) {
1463       p += n;
1464     }
1465   } else {
1466     dest->datacnt = 1;
1467     dest->data = dest->rdata;
1468     dest->rdata[0].len = datalen;
1469 
1470     if (type == NGTCP2_FRAME_DATAGRAM_LEN) {
1471       p += n;
1472     }
1473 
1474     dest->rdata[0].base = (uint8_t *)p;
1475     p += datalen;
1476   }
1477 
1478   assert((size_t)(p - payload) == len);
1479 
1480   return (ngtcp2_ssize)len;
1481 }
1482 
ngtcp2_pkt_encode_frame(uint8_t * out,size_t outlen,ngtcp2_frame * fr)1483 ngtcp2_ssize ngtcp2_pkt_encode_frame(uint8_t *out, size_t outlen,
1484                                      ngtcp2_frame *fr) {
1485   switch (fr->type) {
1486   case NGTCP2_FRAME_STREAM:
1487     return ngtcp2_pkt_encode_stream_frame(out, outlen, &fr->stream);
1488   case NGTCP2_FRAME_ACK:
1489   case NGTCP2_FRAME_ACK_ECN:
1490     return ngtcp2_pkt_encode_ack_frame(out, outlen, &fr->ack);
1491   case NGTCP2_FRAME_PADDING:
1492     return ngtcp2_pkt_encode_padding_frame(out, outlen, &fr->padding);
1493   case NGTCP2_FRAME_RESET_STREAM:
1494     return ngtcp2_pkt_encode_reset_stream_frame(out, outlen, &fr->reset_stream);
1495   case NGTCP2_FRAME_CONNECTION_CLOSE:
1496   case NGTCP2_FRAME_CONNECTION_CLOSE_APP:
1497     return ngtcp2_pkt_encode_connection_close_frame(out, outlen,
1498                                                     &fr->connection_close);
1499   case NGTCP2_FRAME_MAX_DATA:
1500     return ngtcp2_pkt_encode_max_data_frame(out, outlen, &fr->max_data);
1501   case NGTCP2_FRAME_MAX_STREAM_DATA:
1502     return ngtcp2_pkt_encode_max_stream_data_frame(out, outlen,
1503                                                    &fr->max_stream_data);
1504   case NGTCP2_FRAME_MAX_STREAMS_BIDI:
1505   case NGTCP2_FRAME_MAX_STREAMS_UNI:
1506     return ngtcp2_pkt_encode_max_streams_frame(out, outlen, &fr->max_streams);
1507   case NGTCP2_FRAME_PING:
1508     return ngtcp2_pkt_encode_ping_frame(out, outlen, &fr->ping);
1509   case NGTCP2_FRAME_DATA_BLOCKED:
1510     return ngtcp2_pkt_encode_data_blocked_frame(out, outlen, &fr->data_blocked);
1511   case NGTCP2_FRAME_STREAM_DATA_BLOCKED:
1512     return ngtcp2_pkt_encode_stream_data_blocked_frame(
1513         out, outlen, &fr->stream_data_blocked);
1514   case NGTCP2_FRAME_STREAMS_BLOCKED_BIDI:
1515   case NGTCP2_FRAME_STREAMS_BLOCKED_UNI:
1516     return ngtcp2_pkt_encode_streams_blocked_frame(out, outlen,
1517                                                    &fr->streams_blocked);
1518   case NGTCP2_FRAME_NEW_CONNECTION_ID:
1519     return ngtcp2_pkt_encode_new_connection_id_frame(out, outlen,
1520                                                      &fr->new_connection_id);
1521   case NGTCP2_FRAME_STOP_SENDING:
1522     return ngtcp2_pkt_encode_stop_sending_frame(out, outlen, &fr->stop_sending);
1523   case NGTCP2_FRAME_PATH_CHALLENGE:
1524     return ngtcp2_pkt_encode_path_challenge_frame(out, outlen,
1525                                                   &fr->path_challenge);
1526   case NGTCP2_FRAME_PATH_RESPONSE:
1527     return ngtcp2_pkt_encode_path_response_frame(out, outlen,
1528                                                  &fr->path_response);
1529   case NGTCP2_FRAME_CRYPTO:
1530     return ngtcp2_pkt_encode_crypto_frame(out, outlen, &fr->crypto);
1531   case NGTCP2_FRAME_NEW_TOKEN:
1532     return ngtcp2_pkt_encode_new_token_frame(out, outlen, &fr->new_token);
1533   case NGTCP2_FRAME_RETIRE_CONNECTION_ID:
1534     return ngtcp2_pkt_encode_retire_connection_id_frame(
1535         out, outlen, &fr->retire_connection_id);
1536   case NGTCP2_FRAME_HANDSHAKE_DONE:
1537     return ngtcp2_pkt_encode_handshake_done_frame(out, outlen,
1538                                                   &fr->handshake_done);
1539   case NGTCP2_FRAME_DATAGRAM:
1540   case NGTCP2_FRAME_DATAGRAM_LEN:
1541     return ngtcp2_pkt_encode_datagram_frame(out, outlen, &fr->datagram);
1542   default:
1543     return NGTCP2_ERR_INVALID_ARGUMENT;
1544   }
1545 }
1546 
ngtcp2_pkt_encode_stream_frame(uint8_t * out,size_t outlen,ngtcp2_stream * fr)1547 ngtcp2_ssize ngtcp2_pkt_encode_stream_frame(uint8_t *out, size_t outlen,
1548                                             ngtcp2_stream *fr) {
1549   size_t len = 1;
1550   uint8_t flags = NGTCP2_STREAM_LEN_BIT;
1551   uint8_t *p;
1552   size_t i;
1553   size_t datalen = 0;
1554 
1555   if (fr->fin) {
1556     flags |= NGTCP2_STREAM_FIN_BIT;
1557   }
1558 
1559   if (fr->offset) {
1560     flags |= NGTCP2_STREAM_OFF_BIT;
1561     len += ngtcp2_put_varint_len(fr->offset);
1562   }
1563 
1564   len += ngtcp2_put_varint_len((uint64_t)fr->stream_id);
1565 
1566   for (i = 0; i < fr->datacnt; ++i) {
1567     datalen += fr->data[i].len;
1568   }
1569 
1570   len += ngtcp2_put_varint_len(datalen);
1571   len += datalen;
1572 
1573   if (outlen < len) {
1574     return NGTCP2_ERR_NOBUF;
1575   }
1576 
1577   p = out;
1578 
1579   *p++ = flags | NGTCP2_FRAME_STREAM;
1580 
1581   fr->flags = flags;
1582 
1583   p = ngtcp2_put_varint(p, (uint64_t)fr->stream_id);
1584 
1585   if (fr->offset) {
1586     p = ngtcp2_put_varint(p, fr->offset);
1587   }
1588 
1589   p = ngtcp2_put_varint(p, datalen);
1590 
1591   for (i = 0; i < fr->datacnt; ++i) {
1592     assert(fr->data[i].len);
1593     assert(fr->data[i].base);
1594     p = ngtcp2_cpymem(p, fr->data[i].base, fr->data[i].len);
1595   }
1596 
1597   assert((size_t)(p - out) == len);
1598 
1599   return (ngtcp2_ssize)len;
1600 }
1601 
ngtcp2_pkt_encode_ack_frame(uint8_t * out,size_t outlen,ngtcp2_ack * fr)1602 ngtcp2_ssize ngtcp2_pkt_encode_ack_frame(uint8_t *out, size_t outlen,
1603                                          ngtcp2_ack *fr) {
1604   size_t len = 1 + ngtcp2_put_varint_len((uint64_t)fr->largest_ack) +
1605                ngtcp2_put_varint_len(fr->ack_delay) +
1606                ngtcp2_put_varint_len(fr->num_blks) +
1607                ngtcp2_put_varint_len(fr->first_ack_blklen);
1608   uint8_t *p;
1609   size_t i;
1610   const ngtcp2_ack_blk *blk;
1611 
1612   for (i = 0; i < fr->num_blks; ++i) {
1613     blk = &fr->blks[i];
1614     len += ngtcp2_put_varint_len(blk->gap);
1615     len += ngtcp2_put_varint_len(blk->blklen);
1616   }
1617 
1618   if (fr->type == NGTCP2_FRAME_ACK_ECN) {
1619     len += ngtcp2_put_varint_len(fr->ecn.ect0) +
1620            ngtcp2_put_varint_len(fr->ecn.ect1) +
1621            ngtcp2_put_varint_len(fr->ecn.ce);
1622   }
1623 
1624   if (outlen < len) {
1625     return NGTCP2_ERR_NOBUF;
1626   }
1627 
1628   p = out;
1629 
1630   *p++ = fr->type;
1631   p = ngtcp2_put_varint(p, (uint64_t)fr->largest_ack);
1632   p = ngtcp2_put_varint(p, fr->ack_delay);
1633   p = ngtcp2_put_varint(p, fr->num_blks);
1634   p = ngtcp2_put_varint(p, fr->first_ack_blklen);
1635 
1636   for (i = 0; i < fr->num_blks; ++i) {
1637     blk = &fr->blks[i];
1638     p = ngtcp2_put_varint(p, blk->gap);
1639     p = ngtcp2_put_varint(p, blk->blklen);
1640   }
1641 
1642   if (fr->type == NGTCP2_FRAME_ACK_ECN) {
1643     p = ngtcp2_put_varint(p, fr->ecn.ect0);
1644     p = ngtcp2_put_varint(p, fr->ecn.ect1);
1645     p = ngtcp2_put_varint(p, fr->ecn.ce);
1646   }
1647 
1648   assert((size_t)(p - out) == len);
1649 
1650   return (ngtcp2_ssize)len;
1651 }
1652 
ngtcp2_pkt_encode_padding_frame(uint8_t * out,size_t outlen,const ngtcp2_padding * fr)1653 ngtcp2_ssize ngtcp2_pkt_encode_padding_frame(uint8_t *out, size_t outlen,
1654                                              const ngtcp2_padding *fr) {
1655   if (outlen < fr->len) {
1656     return NGTCP2_ERR_NOBUF;
1657   }
1658 
1659   memset(out, 0, fr->len);
1660 
1661   return (ngtcp2_ssize)fr->len;
1662 }
1663 
1664 ngtcp2_ssize
ngtcp2_pkt_encode_reset_stream_frame(uint8_t * out,size_t outlen,const ngtcp2_reset_stream * fr)1665 ngtcp2_pkt_encode_reset_stream_frame(uint8_t *out, size_t outlen,
1666                                      const ngtcp2_reset_stream *fr) {
1667   size_t len = 1 + ngtcp2_put_varint_len((uint64_t)fr->stream_id) +
1668                ngtcp2_put_varint_len(fr->app_error_code) +
1669                ngtcp2_put_varint_len(fr->final_size);
1670   uint8_t *p;
1671 
1672   if (outlen < len) {
1673     return NGTCP2_ERR_NOBUF;
1674   }
1675 
1676   p = out;
1677 
1678   *p++ = NGTCP2_FRAME_RESET_STREAM;
1679   p = ngtcp2_put_varint(p, (uint64_t)fr->stream_id);
1680   p = ngtcp2_put_varint(p, fr->app_error_code);
1681   p = ngtcp2_put_varint(p, fr->final_size);
1682 
1683   assert((size_t)(p - out) == len);
1684 
1685   return (ngtcp2_ssize)len;
1686 }
1687 
1688 ngtcp2_ssize
ngtcp2_pkt_encode_connection_close_frame(uint8_t * out,size_t outlen,const ngtcp2_connection_close * fr)1689 ngtcp2_pkt_encode_connection_close_frame(uint8_t *out, size_t outlen,
1690                                          const ngtcp2_connection_close *fr) {
1691   size_t len = 1 + ngtcp2_put_varint_len(fr->error_code) +
1692                (fr->type == NGTCP2_FRAME_CONNECTION_CLOSE
1693                     ? ngtcp2_put_varint_len(fr->frame_type)
1694                     : 0) +
1695                ngtcp2_put_varint_len(fr->reasonlen) + fr->reasonlen;
1696   uint8_t *p;
1697 
1698   if (outlen < len) {
1699     return NGTCP2_ERR_NOBUF;
1700   }
1701 
1702   p = out;
1703 
1704   *p++ = fr->type;
1705   p = ngtcp2_put_varint(p, fr->error_code);
1706   if (fr->type == NGTCP2_FRAME_CONNECTION_CLOSE) {
1707     p = ngtcp2_put_varint(p, fr->frame_type);
1708   }
1709   p = ngtcp2_put_varint(p, fr->reasonlen);
1710   if (fr->reasonlen) {
1711     p = ngtcp2_cpymem(p, fr->reason, fr->reasonlen);
1712   }
1713 
1714   assert((size_t)(p - out) == len);
1715 
1716   return (ngtcp2_ssize)len;
1717 }
1718 
ngtcp2_pkt_encode_max_data_frame(uint8_t * out,size_t outlen,const ngtcp2_max_data * fr)1719 ngtcp2_ssize ngtcp2_pkt_encode_max_data_frame(uint8_t *out, size_t outlen,
1720                                               const ngtcp2_max_data *fr) {
1721   size_t len = 1 + ngtcp2_put_varint_len(fr->max_data);
1722   uint8_t *p;
1723 
1724   if (outlen < len) {
1725     return NGTCP2_ERR_NOBUF;
1726   }
1727 
1728   p = out;
1729 
1730   *p++ = NGTCP2_FRAME_MAX_DATA;
1731   p = ngtcp2_put_varint(p, fr->max_data);
1732 
1733   assert((size_t)(p - out) == len);
1734 
1735   return (ngtcp2_ssize)len;
1736 }
1737 
1738 ngtcp2_ssize
ngtcp2_pkt_encode_max_stream_data_frame(uint8_t * out,size_t outlen,const ngtcp2_max_stream_data * fr)1739 ngtcp2_pkt_encode_max_stream_data_frame(uint8_t *out, size_t outlen,
1740                                         const ngtcp2_max_stream_data *fr) {
1741   size_t len = 1 + ngtcp2_put_varint_len((uint64_t)fr->stream_id) +
1742                ngtcp2_put_varint_len(fr->max_stream_data);
1743   uint8_t *p;
1744 
1745   if (outlen < len) {
1746     return NGTCP2_ERR_NOBUF;
1747   }
1748 
1749   p = out;
1750 
1751   *p++ = NGTCP2_FRAME_MAX_STREAM_DATA;
1752   p = ngtcp2_put_varint(p, (uint64_t)fr->stream_id);
1753   p = ngtcp2_put_varint(p, fr->max_stream_data);
1754 
1755   assert((size_t)(p - out) == len);
1756 
1757   return (ngtcp2_ssize)len;
1758 }
1759 
ngtcp2_pkt_encode_max_streams_frame(uint8_t * out,size_t outlen,const ngtcp2_max_streams * fr)1760 ngtcp2_ssize ngtcp2_pkt_encode_max_streams_frame(uint8_t *out, size_t outlen,
1761                                                  const ngtcp2_max_streams *fr) {
1762   size_t len = 1 + ngtcp2_put_varint_len(fr->max_streams);
1763   uint8_t *p;
1764 
1765   if (outlen < len) {
1766     return NGTCP2_ERR_NOBUF;
1767   }
1768 
1769   p = out;
1770 
1771   *p++ = fr->type;
1772   p = ngtcp2_put_varint(p, fr->max_streams);
1773 
1774   assert((size_t)(p - out) == len);
1775 
1776   return (ngtcp2_ssize)len;
1777 }
1778 
ngtcp2_pkt_encode_ping_frame(uint8_t * out,size_t outlen,const ngtcp2_ping * fr)1779 ngtcp2_ssize ngtcp2_pkt_encode_ping_frame(uint8_t *out, size_t outlen,
1780                                           const ngtcp2_ping *fr) {
1781   (void)fr;
1782 
1783   if (outlen < 1) {
1784     return NGTCP2_ERR_NOBUF;
1785   }
1786 
1787   *out++ = NGTCP2_FRAME_PING;
1788 
1789   return 1;
1790 }
1791 
1792 ngtcp2_ssize
ngtcp2_pkt_encode_data_blocked_frame(uint8_t * out,size_t outlen,const ngtcp2_data_blocked * fr)1793 ngtcp2_pkt_encode_data_blocked_frame(uint8_t *out, size_t outlen,
1794                                      const ngtcp2_data_blocked *fr) {
1795   size_t len = 1 + ngtcp2_put_varint_len(fr->offset);
1796   uint8_t *p;
1797 
1798   if (outlen < len) {
1799     return NGTCP2_ERR_NOBUF;
1800   }
1801 
1802   p = out;
1803 
1804   *p++ = NGTCP2_FRAME_DATA_BLOCKED;
1805   p = ngtcp2_put_varint(p, fr->offset);
1806 
1807   assert((size_t)(p - out) == len);
1808 
1809   return (ngtcp2_ssize)len;
1810 }
1811 
ngtcp2_pkt_encode_stream_data_blocked_frame(uint8_t * out,size_t outlen,const ngtcp2_stream_data_blocked * fr)1812 ngtcp2_ssize ngtcp2_pkt_encode_stream_data_blocked_frame(
1813     uint8_t *out, size_t outlen, const ngtcp2_stream_data_blocked *fr) {
1814   size_t len = 1 + ngtcp2_put_varint_len((uint64_t)fr->stream_id) +
1815                ngtcp2_put_varint_len(fr->offset);
1816   uint8_t *p;
1817 
1818   if (outlen < len) {
1819     return NGTCP2_ERR_NOBUF;
1820   }
1821 
1822   p = out;
1823 
1824   *p++ = NGTCP2_FRAME_STREAM_DATA_BLOCKED;
1825   p = ngtcp2_put_varint(p, (uint64_t)fr->stream_id);
1826   p = ngtcp2_put_varint(p, fr->offset);
1827 
1828   assert((size_t)(p - out) == len);
1829 
1830   return (ngtcp2_ssize)len;
1831 }
1832 
1833 ngtcp2_ssize
ngtcp2_pkt_encode_streams_blocked_frame(uint8_t * out,size_t outlen,const ngtcp2_streams_blocked * fr)1834 ngtcp2_pkt_encode_streams_blocked_frame(uint8_t *out, size_t outlen,
1835                                         const ngtcp2_streams_blocked *fr) {
1836   size_t len = 1 + ngtcp2_put_varint_len(fr->max_streams);
1837   uint8_t *p;
1838 
1839   if (outlen < len) {
1840     return NGTCP2_ERR_NOBUF;
1841   }
1842 
1843   p = out;
1844 
1845   *p++ = fr->type;
1846   p = ngtcp2_put_varint(p, fr->max_streams);
1847 
1848   assert((size_t)(p - out) == len);
1849 
1850   return (ngtcp2_ssize)len;
1851 }
1852 
1853 ngtcp2_ssize
ngtcp2_pkt_encode_new_connection_id_frame(uint8_t * out,size_t outlen,const ngtcp2_new_connection_id * fr)1854 ngtcp2_pkt_encode_new_connection_id_frame(uint8_t *out, size_t outlen,
1855                                           const ngtcp2_new_connection_id *fr) {
1856   size_t len = 1 + ngtcp2_put_varint_len(fr->seq) +
1857                ngtcp2_put_varint_len(fr->retire_prior_to) + 1 +
1858                fr->cid.datalen + NGTCP2_STATELESS_RESET_TOKENLEN;
1859   uint8_t *p;
1860 
1861   if (outlen < len) {
1862     return NGTCP2_ERR_NOBUF;
1863   }
1864 
1865   p = out;
1866 
1867   *p++ = NGTCP2_FRAME_NEW_CONNECTION_ID;
1868   p = ngtcp2_put_varint(p, fr->seq);
1869   p = ngtcp2_put_varint(p, fr->retire_prior_to);
1870   *p++ = (uint8_t)fr->cid.datalen;
1871   p = ngtcp2_cpymem(p, fr->cid.data, fr->cid.datalen);
1872   p = ngtcp2_cpymem(p, fr->stateless_reset_token,
1873                     NGTCP2_STATELESS_RESET_TOKENLEN);
1874 
1875   assert((size_t)(p - out) == len);
1876 
1877   return (ngtcp2_ssize)len;
1878 }
1879 
1880 ngtcp2_ssize
ngtcp2_pkt_encode_stop_sending_frame(uint8_t * out,size_t outlen,const ngtcp2_stop_sending * fr)1881 ngtcp2_pkt_encode_stop_sending_frame(uint8_t *out, size_t outlen,
1882                                      const ngtcp2_stop_sending *fr) {
1883   size_t len = 1 + ngtcp2_put_varint_len((uint64_t)fr->stream_id) +
1884                ngtcp2_put_varint_len(fr->app_error_code);
1885   uint8_t *p;
1886 
1887   if (outlen < len) {
1888     return NGTCP2_ERR_NOBUF;
1889   }
1890 
1891   p = out;
1892 
1893   *p++ = NGTCP2_FRAME_STOP_SENDING;
1894   p = ngtcp2_put_varint(p, (uint64_t)fr->stream_id);
1895   p = ngtcp2_put_varint(p, fr->app_error_code);
1896 
1897   assert((size_t)(p - out) == len);
1898 
1899   return (ngtcp2_ssize)len;
1900 }
1901 
1902 ngtcp2_ssize
ngtcp2_pkt_encode_path_challenge_frame(uint8_t * out,size_t outlen,const ngtcp2_path_challenge * fr)1903 ngtcp2_pkt_encode_path_challenge_frame(uint8_t *out, size_t outlen,
1904                                        const ngtcp2_path_challenge *fr) {
1905   size_t len = 1 + 8;
1906   uint8_t *p;
1907 
1908   if (outlen < len) {
1909     return NGTCP2_ERR_NOBUF;
1910   }
1911 
1912   p = out;
1913 
1914   *p++ = NGTCP2_FRAME_PATH_CHALLENGE;
1915   p = ngtcp2_cpymem(p, fr->data, sizeof(fr->data));
1916 
1917   assert((size_t)(p - out) == len);
1918 
1919   return (ngtcp2_ssize)len;
1920 }
1921 
1922 ngtcp2_ssize
ngtcp2_pkt_encode_path_response_frame(uint8_t * out,size_t outlen,const ngtcp2_path_response * fr)1923 ngtcp2_pkt_encode_path_response_frame(uint8_t *out, size_t outlen,
1924                                       const ngtcp2_path_response *fr) {
1925   size_t len = 1 + 8;
1926   uint8_t *p;
1927 
1928   if (outlen < len) {
1929     return NGTCP2_ERR_NOBUF;
1930   }
1931 
1932   p = out;
1933 
1934   *p++ = NGTCP2_FRAME_PATH_RESPONSE;
1935   p = ngtcp2_cpymem(p, fr->data, sizeof(fr->data));
1936 
1937   assert((size_t)(p - out) == len);
1938 
1939   return (ngtcp2_ssize)len;
1940 }
1941 
ngtcp2_pkt_encode_crypto_frame(uint8_t * out,size_t outlen,const ngtcp2_crypto * fr)1942 ngtcp2_ssize ngtcp2_pkt_encode_crypto_frame(uint8_t *out, size_t outlen,
1943                                             const ngtcp2_crypto *fr) {
1944   size_t len = 1;
1945   uint8_t *p;
1946   size_t i;
1947   size_t datalen = 0;
1948 
1949   len += ngtcp2_put_varint_len(fr->offset);
1950 
1951   for (i = 0; i < fr->datacnt; ++i) {
1952     datalen += fr->data[i].len;
1953   }
1954 
1955   len += ngtcp2_put_varint_len(datalen);
1956   len += datalen;
1957 
1958   if (outlen < len) {
1959     return NGTCP2_ERR_NOBUF;
1960   }
1961 
1962   p = out;
1963 
1964   *p++ = NGTCP2_FRAME_CRYPTO;
1965 
1966   p = ngtcp2_put_varint(p, fr->offset);
1967   p = ngtcp2_put_varint(p, datalen);
1968 
1969   for (i = 0; i < fr->datacnt; ++i) {
1970     assert(fr->data[i].base);
1971     p = ngtcp2_cpymem(p, fr->data[i].base, fr->data[i].len);
1972   }
1973 
1974   assert((size_t)(p - out) == len);
1975 
1976   return (ngtcp2_ssize)len;
1977 }
1978 
ngtcp2_pkt_encode_new_token_frame(uint8_t * out,size_t outlen,const ngtcp2_new_token * fr)1979 ngtcp2_ssize ngtcp2_pkt_encode_new_token_frame(uint8_t *out, size_t outlen,
1980                                                const ngtcp2_new_token *fr) {
1981   size_t len = 1 + ngtcp2_put_varint_len(fr->token.len) + fr->token.len;
1982   uint8_t *p;
1983 
1984   assert(fr->token.len);
1985 
1986   if (outlen < len) {
1987     return NGTCP2_ERR_NOBUF;
1988   }
1989 
1990   p = out;
1991 
1992   *p++ = NGTCP2_FRAME_NEW_TOKEN;
1993 
1994   p = ngtcp2_put_varint(p, fr->token.len);
1995   p = ngtcp2_cpymem(p, fr->token.base, fr->token.len);
1996 
1997   assert((size_t)(p - out) == len);
1998 
1999   return (ngtcp2_ssize)len;
2000 }
2001 
ngtcp2_pkt_encode_retire_connection_id_frame(uint8_t * out,size_t outlen,const ngtcp2_retire_connection_id * fr)2002 ngtcp2_ssize ngtcp2_pkt_encode_retire_connection_id_frame(
2003     uint8_t *out, size_t outlen, const ngtcp2_retire_connection_id *fr) {
2004   size_t len = 1 + ngtcp2_put_varint_len(fr->seq);
2005   uint8_t *p;
2006 
2007   if (outlen < len) {
2008     return NGTCP2_ERR_NOBUF;
2009   }
2010 
2011   p = out;
2012 
2013   *p++ = NGTCP2_FRAME_RETIRE_CONNECTION_ID;
2014 
2015   p = ngtcp2_put_varint(p, fr->seq);
2016 
2017   assert((size_t)(p - out) == len);
2018 
2019   return (ngtcp2_ssize)len;
2020 }
2021 
2022 ngtcp2_ssize
ngtcp2_pkt_encode_handshake_done_frame(uint8_t * out,size_t outlen,const ngtcp2_handshake_done * fr)2023 ngtcp2_pkt_encode_handshake_done_frame(uint8_t *out, size_t outlen,
2024                                        const ngtcp2_handshake_done *fr) {
2025   (void)fr;
2026 
2027   if (outlen < 1) {
2028     return NGTCP2_ERR_NOBUF;
2029   }
2030 
2031   *out++ = NGTCP2_FRAME_HANDSHAKE_DONE;
2032 
2033   return 1;
2034 }
2035 
ngtcp2_pkt_encode_datagram_frame(uint8_t * out,size_t outlen,const ngtcp2_datagram * fr)2036 ngtcp2_ssize ngtcp2_pkt_encode_datagram_frame(uint8_t *out, size_t outlen,
2037                                               const ngtcp2_datagram *fr) {
2038   uint64_t datalen = ngtcp2_vec_len(fr->data, fr->datacnt);
2039   uint64_t len =
2040       1 +
2041       (fr->type == NGTCP2_FRAME_DATAGRAM ? 0 : ngtcp2_put_varint_len(datalen)) +
2042       datalen;
2043   uint8_t *p;
2044   size_t i;
2045 
2046   assert(fr->type == NGTCP2_FRAME_DATAGRAM ||
2047          fr->type == NGTCP2_FRAME_DATAGRAM_LEN);
2048 
2049   if (outlen < len) {
2050     return NGTCP2_ERR_NOBUF;
2051   }
2052 
2053   p = out;
2054 
2055   *p++ = fr->type;
2056   if (fr->type == NGTCP2_FRAME_DATAGRAM_LEN) {
2057     p = ngtcp2_put_varint(p, datalen);
2058   }
2059 
2060   for (i = 0; i < fr->datacnt; ++i) {
2061     assert(fr->data[i].len);
2062     assert(fr->data[i].base);
2063     p = ngtcp2_cpymem(p, fr->data[i].base, fr->data[i].len);
2064   }
2065 
2066   assert((size_t)(p - out) == len);
2067 
2068   return (ngtcp2_ssize)len;
2069 }
2070 
ngtcp2_pkt_write_version_negotiation(uint8_t * dest,size_t destlen,uint8_t unused_random,const uint8_t * dcid,size_t dcidlen,const uint8_t * scid,size_t scidlen,const uint32_t * sv,size_t nsv)2071 ngtcp2_ssize ngtcp2_pkt_write_version_negotiation(
2072     uint8_t *dest, size_t destlen, uint8_t unused_random, const uint8_t *dcid,
2073     size_t dcidlen, const uint8_t *scid, size_t scidlen, const uint32_t *sv,
2074     size_t nsv) {
2075   size_t len = 1 + 4 + 1 + dcidlen + 1 + scidlen + nsv * 4;
2076   uint8_t *p;
2077   size_t i;
2078 
2079   assert(dcidlen < 256);
2080   assert(scidlen < 256);
2081 
2082   if (destlen < len) {
2083     return NGTCP2_ERR_NOBUF;
2084   }
2085 
2086   p = dest;
2087 
2088   *p++ = 0x80 | unused_random;
2089   p = ngtcp2_put_uint32be(p, 0);
2090   *p++ = (uint8_t)dcidlen;
2091   if (dcidlen) {
2092     p = ngtcp2_cpymem(p, dcid, dcidlen);
2093   }
2094   *p++ = (uint8_t)scidlen;
2095   if (scidlen) {
2096     p = ngtcp2_cpymem(p, scid, scidlen);
2097   }
2098 
2099   for (i = 0; i < nsv; ++i) {
2100     p = ngtcp2_put_uint32be(p, sv[i]);
2101   }
2102 
2103   assert((size_t)(p - dest) == len);
2104 
2105   return (ngtcp2_ssize)len;
2106 }
2107 
ngtcp2_pkt_decode_version_negotiation(uint32_t * dest,const uint8_t * payload,size_t payloadlen)2108 size_t ngtcp2_pkt_decode_version_negotiation(uint32_t *dest,
2109                                              const uint8_t *payload,
2110                                              size_t payloadlen) {
2111   const uint8_t *end = payload + payloadlen;
2112 
2113   assert((payloadlen % sizeof(uint32_t)) == 0);
2114 
2115   for (; payload != end; payload += sizeof(uint32_t)) {
2116     *dest++ = ngtcp2_get_uint32(payload);
2117   }
2118 
2119   return payloadlen / sizeof(uint32_t);
2120 }
2121 
ngtcp2_pkt_decode_stateless_reset(ngtcp2_pkt_stateless_reset * sr,const uint8_t * payload,size_t payloadlen)2122 int ngtcp2_pkt_decode_stateless_reset(ngtcp2_pkt_stateless_reset *sr,
2123                                       const uint8_t *payload,
2124                                       size_t payloadlen) {
2125   const uint8_t *p = payload;
2126 
2127   if (payloadlen <
2128       NGTCP2_MIN_STATELESS_RESET_RANDLEN + NGTCP2_STATELESS_RESET_TOKENLEN) {
2129     return NGTCP2_ERR_INVALID_ARGUMENT;
2130   }
2131 
2132   sr->rand = p;
2133   sr->randlen = payloadlen - NGTCP2_STATELESS_RESET_TOKENLEN;
2134   p += sr->randlen;
2135   memcpy(sr->stateless_reset_token, p, NGTCP2_STATELESS_RESET_TOKENLEN);
2136 
2137   return 0;
2138 }
2139 
ngtcp2_pkt_decode_retry(ngtcp2_pkt_retry * dest,const uint8_t * payload,size_t payloadlen)2140 int ngtcp2_pkt_decode_retry(ngtcp2_pkt_retry *dest, const uint8_t *payload,
2141                             size_t payloadlen) {
2142   size_t len = /* token */ 1 + NGTCP2_RETRY_TAGLEN;
2143 
2144   if (payloadlen < len) {
2145     return NGTCP2_ERR_INVALID_ARGUMENT;
2146   }
2147 
2148   dest->token.base = (uint8_t *)payload;
2149   dest->token.len = (size_t)(payloadlen - NGTCP2_RETRY_TAGLEN);
2150   ngtcp2_cpymem(dest->tag, payload + dest->token.len, NGTCP2_RETRY_TAGLEN);
2151 
2152   return 0;
2153 }
2154 
ngtcp2_pkt_adjust_pkt_num(int64_t max_pkt_num,int64_t pkt_num,size_t n)2155 int64_t ngtcp2_pkt_adjust_pkt_num(int64_t max_pkt_num, int64_t pkt_num,
2156                                   size_t n) {
2157   int64_t expected = max_pkt_num + 1;
2158   int64_t win = (int64_t)1 << n;
2159   int64_t hwin = win / 2;
2160   int64_t mask = win - 1;
2161   int64_t cand = (expected & ~mask) | pkt_num;
2162 
2163   if (cand <= expected - hwin) {
2164     assert(cand <= (int64_t)NGTCP2_MAX_VARINT - win);
2165     return cand + win;
2166   }
2167   if (cand > expected + hwin && cand >= win) {
2168     return cand - win;
2169   }
2170   return cand;
2171 }
2172 
ngtcp2_pkt_validate_ack(ngtcp2_ack * fr)2173 int ngtcp2_pkt_validate_ack(ngtcp2_ack *fr) {
2174   int64_t largest_ack = fr->largest_ack;
2175   size_t i;
2176 
2177   if (largest_ack < (int64_t)fr->first_ack_blklen) {
2178     return NGTCP2_ERR_ACK_FRAME;
2179   }
2180 
2181   largest_ack -= (int64_t)fr->first_ack_blklen;
2182 
2183   for (i = 0; i < fr->num_blks; ++i) {
2184     if (largest_ack < (int64_t)fr->blks[i].gap + 2) {
2185       return NGTCP2_ERR_ACK_FRAME;
2186     }
2187 
2188     largest_ack -= (int64_t)fr->blks[i].gap + 2;
2189 
2190     if (largest_ack < (int64_t)fr->blks[i].blklen) {
2191       return NGTCP2_ERR_ACK_FRAME;
2192     }
2193 
2194     largest_ack -= (int64_t)fr->blks[i].blklen;
2195   }
2196 
2197   return 0;
2198 }
2199 
2200 ngtcp2_ssize
ngtcp2_pkt_write_stateless_reset(uint8_t * dest,size_t destlen,const uint8_t * stateless_reset_token,const uint8_t * rand,size_t randlen)2201 ngtcp2_pkt_write_stateless_reset(uint8_t *dest, size_t destlen,
2202                                  const uint8_t *stateless_reset_token,
2203                                  const uint8_t *rand, size_t randlen) {
2204   uint8_t *p;
2205 
2206   if (destlen <
2207       NGTCP2_MIN_STATELESS_RESET_RANDLEN + NGTCP2_STATELESS_RESET_TOKENLEN) {
2208     return NGTCP2_ERR_NOBUF;
2209   }
2210 
2211   if (randlen < NGTCP2_MIN_STATELESS_RESET_RANDLEN) {
2212     return NGTCP2_ERR_INVALID_ARGUMENT;
2213   }
2214 
2215   p = dest;
2216 
2217   randlen = ngtcp2_min(destlen - NGTCP2_STATELESS_RESET_TOKENLEN, randlen);
2218 
2219   p = ngtcp2_cpymem(p, rand, randlen);
2220   p = ngtcp2_cpymem(p, stateless_reset_token, NGTCP2_STATELESS_RESET_TOKENLEN);
2221   *dest = (uint8_t)((*dest & 0x7fu) | 0x40u);
2222 
2223   return p - dest;
2224 }
2225 
ngtcp2_pkt_write_retry(uint8_t * dest,size_t destlen,uint32_t version,const ngtcp2_cid * dcid,const ngtcp2_cid * scid,const ngtcp2_cid * odcid,const uint8_t * token,size_t tokenlen,ngtcp2_encrypt encrypt,const ngtcp2_crypto_aead * aead,const ngtcp2_crypto_aead_ctx * aead_ctx)2226 ngtcp2_ssize ngtcp2_pkt_write_retry(
2227     uint8_t *dest, size_t destlen, uint32_t version, const ngtcp2_cid *dcid,
2228     const ngtcp2_cid *scid, const ngtcp2_cid *odcid, const uint8_t *token,
2229     size_t tokenlen, ngtcp2_encrypt encrypt, const ngtcp2_crypto_aead *aead,
2230     const ngtcp2_crypto_aead_ctx *aead_ctx) {
2231   ngtcp2_pkt_hd hd;
2232   uint8_t pseudo_retry[1500];
2233   ngtcp2_ssize pseudo_retrylen;
2234   uint8_t tag[NGTCP2_RETRY_TAGLEN];
2235   int rv;
2236   uint8_t *p;
2237   size_t offset;
2238   const uint8_t *nonce;
2239   size_t noncelen;
2240 
2241   assert(tokenlen > 0);
2242   assert(!ngtcp2_cid_eq(scid, odcid));
2243 
2244   /* Retry packet is sent at most once per one connection attempt.  In
2245      the first connection attempt, client has to send random DCID
2246      which is at least 8 bytes long. */
2247   if (odcid->datalen < 8) {
2248     return NGTCP2_ERR_INVALID_ARGUMENT;
2249   }
2250 
2251   ngtcp2_pkt_hd_init(&hd, NGTCP2_PKT_FLAG_LONG_FORM, NGTCP2_PKT_RETRY, dcid,
2252                      scid, /* pkt_num = */ 0, /* pkt_numlen = */ 1, version,
2253                      /* len = */ 0);
2254 
2255   pseudo_retrylen =
2256       ngtcp2_pkt_encode_pseudo_retry(pseudo_retry, sizeof(pseudo_retry), &hd,
2257                                      /* unused = */ 0, odcid, token, tokenlen);
2258   if (pseudo_retrylen < 0) {
2259     return pseudo_retrylen;
2260   }
2261 
2262   if (version == NGTCP2_PROTO_VER_V1) {
2263     nonce = (const uint8_t *)NGTCP2_RETRY_NONCE_V1;
2264     noncelen = sizeof(NGTCP2_RETRY_NONCE_V1) - 1;
2265   } else {
2266     nonce = (const uint8_t *)NGTCP2_RETRY_NONCE_DRAFT;
2267     noncelen = sizeof(NGTCP2_RETRY_NONCE_DRAFT) - 1;
2268   }
2269 
2270   /* OpenSSL does not like NULL plaintext. */
2271   rv = encrypt(tag, aead, aead_ctx, (const uint8_t *)"", 0, nonce, noncelen,
2272                pseudo_retry, (size_t)pseudo_retrylen);
2273   if (rv != 0) {
2274     return rv;
2275   }
2276 
2277   offset = 1 + odcid->datalen;
2278   if (destlen < (size_t)pseudo_retrylen + sizeof(tag) - offset) {
2279     return NGTCP2_ERR_NOBUF;
2280   }
2281 
2282   p = ngtcp2_cpymem(dest, pseudo_retry + offset,
2283                     (size_t)pseudo_retrylen - offset);
2284   p = ngtcp2_cpymem(p, tag, sizeof(tag));
2285 
2286   return p - dest;
2287 }
2288 
ngtcp2_pkt_encode_pseudo_retry(uint8_t * dest,size_t destlen,const ngtcp2_pkt_hd * hd,uint8_t unused,const ngtcp2_cid * odcid,const uint8_t * token,size_t tokenlen)2289 ngtcp2_ssize ngtcp2_pkt_encode_pseudo_retry(
2290     uint8_t *dest, size_t destlen, const ngtcp2_pkt_hd *hd, uint8_t unused,
2291     const ngtcp2_cid *odcid, const uint8_t *token, size_t tokenlen) {
2292   uint8_t *p = dest;
2293   ngtcp2_ssize nwrite;
2294 
2295   if (destlen < 1 + odcid->datalen) {
2296     return NGTCP2_ERR_NOBUF;
2297   }
2298 
2299   *p++ = (uint8_t)odcid->datalen;
2300   p = ngtcp2_cpymem(p, odcid->data, odcid->datalen);
2301   destlen -= (size_t)(p - dest);
2302 
2303   nwrite = ngtcp2_pkt_encode_hd_long(p, destlen, hd);
2304   if (nwrite < 0) {
2305     return nwrite;
2306   }
2307 
2308   if (destlen < (size_t)nwrite + tokenlen) {
2309     return NGTCP2_ERR_NOBUF;
2310   }
2311 
2312   *p &= 0xf0;
2313   *p |= unused;
2314 
2315   p += nwrite;
2316 
2317   p = ngtcp2_cpymem(p, token, tokenlen);
2318 
2319   return p - dest;
2320 }
2321 
ngtcp2_pkt_verify_retry_tag(uint32_t version,const ngtcp2_pkt_retry * retry,const uint8_t * pkt,size_t pktlen,ngtcp2_encrypt encrypt,const ngtcp2_crypto_aead * aead,const ngtcp2_crypto_aead_ctx * aead_ctx)2322 int ngtcp2_pkt_verify_retry_tag(uint32_t version, const ngtcp2_pkt_retry *retry,
2323                                 const uint8_t *pkt, size_t pktlen,
2324                                 ngtcp2_encrypt encrypt,
2325                                 const ngtcp2_crypto_aead *aead,
2326                                 const ngtcp2_crypto_aead_ctx *aead_ctx) {
2327   uint8_t pseudo_retry[1500];
2328   size_t pseudo_retrylen;
2329   uint8_t *p = pseudo_retry;
2330   int rv;
2331   uint8_t tag[NGTCP2_RETRY_TAGLEN];
2332   const uint8_t *nonce;
2333   size_t noncelen;
2334 
2335   assert(pktlen >= sizeof(retry->tag));
2336 
2337   if (sizeof(pseudo_retry) <
2338       1 + retry->odcid.datalen + pktlen - sizeof(retry->tag)) {
2339     return NGTCP2_ERR_PROTO;
2340   }
2341 
2342   *p++ = (uint8_t)retry->odcid.datalen;
2343   p = ngtcp2_cpymem(p, retry->odcid.data, retry->odcid.datalen);
2344   p = ngtcp2_cpymem(p, pkt, pktlen - sizeof(retry->tag));
2345 
2346   pseudo_retrylen = (size_t)(p - pseudo_retry);
2347 
2348   if (version == NGTCP2_PROTO_VER_V1) {
2349     nonce = (const uint8_t *)NGTCP2_RETRY_NONCE_V1;
2350     noncelen = sizeof(NGTCP2_RETRY_NONCE_V1) - 1;
2351   } else {
2352     nonce = (const uint8_t *)NGTCP2_RETRY_NONCE_DRAFT;
2353     noncelen = sizeof(NGTCP2_RETRY_NONCE_DRAFT) - 1;
2354   }
2355 
2356   /* OpenSSL does not like NULL plaintext. */
2357   rv = encrypt(tag, aead, aead_ctx, (const uint8_t *)"", 0, nonce, noncelen,
2358                pseudo_retry, pseudo_retrylen);
2359   if (rv != 0) {
2360     return rv;
2361   }
2362 
2363   if (0 != memcmp(retry->tag, tag, sizeof(retry->tag))) {
2364     return NGTCP2_ERR_PROTO;
2365   }
2366 
2367   return 0;
2368 }
2369 
ngtcp2_pkt_stream_max_datalen(int64_t stream_id,uint64_t offset,uint64_t len,size_t left)2370 size_t ngtcp2_pkt_stream_max_datalen(int64_t stream_id, uint64_t offset,
2371                                      uint64_t len, size_t left) {
2372   size_t n = 1 /* type */ + ngtcp2_put_varint_len((uint64_t)stream_id) +
2373              (offset ? ngtcp2_put_varint_len(offset) : 0);
2374 
2375   if (left <= n) {
2376     return (size_t)-1;
2377   }
2378 
2379   left -= n;
2380 
2381   if (left > 8 + 1073741823 && len > 1073741823) {
2382 #if SIZE_MAX > UINT32_MAX
2383     len = ngtcp2_min(len, 4611686018427387903lu);
2384 #endif /* SIZE_MAX > UINT32_MAX */
2385     return (size_t)ngtcp2_min(len, (uint64_t)(left - 8));
2386   }
2387 
2388   if (left > 4 + 16383 && len > 16383) {
2389     len = ngtcp2_min(len, 1073741823);
2390     return (size_t)ngtcp2_min(len, (uint64_t)(left - 4));
2391   }
2392 
2393   if (left > 2 + 63 && len > 63) {
2394     len = ngtcp2_min(len, 16383);
2395     return (size_t)ngtcp2_min(len, (uint64_t)(left - 2));
2396   }
2397 
2398   len = ngtcp2_min(len, 63);
2399   return (size_t)ngtcp2_min(len, (uint64_t)(left - 1));
2400 }
2401 
ngtcp2_pkt_crypto_max_datalen(uint64_t offset,size_t len,size_t left)2402 size_t ngtcp2_pkt_crypto_max_datalen(uint64_t offset, size_t len, size_t left) {
2403   size_t n = 1 /* type */ + ngtcp2_put_varint_len(offset);
2404 
2405   /* CRYPTO frame must contain nonzero length data.  Return -1 if
2406      there is no space to write crypto data. */
2407   if (left <= n + 1) {
2408     return (size_t)-1;
2409   }
2410 
2411   left -= n;
2412 
2413   if (left > 8 + 1073741823 && len > 1073741823) {
2414 #if SIZE_MAX > UINT32_MAX
2415     len = ngtcp2_min(len, 4611686018427387903lu);
2416 #endif /* SIZE_MAX > UINT32_MAX */
2417     return ngtcp2_min(len, left - 8);
2418   }
2419 
2420   if (left > 4 + 16383 && len > 16383) {
2421     len = ngtcp2_min(len, 1073741823);
2422     return ngtcp2_min(len, left - 4);
2423   }
2424 
2425   if (left > 2 + 63 && len > 63) {
2426     len = ngtcp2_min(len, 16383);
2427     return ngtcp2_min(len, left - 2);
2428   }
2429 
2430   len = ngtcp2_min(len, 63);
2431   return ngtcp2_min(len, left - 1);
2432 }
2433 
ngtcp2_pkt_datagram_framelen(size_t len)2434 size_t ngtcp2_pkt_datagram_framelen(size_t len) {
2435   return 1 /* type */ + ngtcp2_put_varint_len(len) + len;
2436 }
2437 
ngtcp2_pkt_get_type_long(uint8_t c)2438 uint8_t ngtcp2_pkt_get_type_long(uint8_t c) {
2439   return (uint8_t)((c & NGTCP2_LONG_TYPE_MASK) >> 4);
2440 }
2441 
ngtcp2_pkt_verify_reserved_bits(uint8_t c)2442 int ngtcp2_pkt_verify_reserved_bits(uint8_t c) {
2443   if (c & NGTCP2_HEADER_FORM_BIT) {
2444     return (c & NGTCP2_LONG_RESERVED_BIT_MASK) == 0 ? 0 : NGTCP2_ERR_PROTO;
2445   }
2446   return (c & NGTCP2_SHORT_RESERVED_BIT_MASK) == 0 ? 0 : NGTCP2_ERR_PROTO;
2447 }
2448