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