1 /** @file
2  *
3  *  A brief file description
4  *
5  *  @section license License
6  *
7  *  Licensed to the Apache Software Foundation (ASF) under one
8  *  or more contributor license agreements.  See the NOTICE file
9  *  distributed with this work for additional information
10  *  regarding copyright ownership.  The ASF licenses this file
11  *  to you under the Apache License, Version 2.0 (the
12  *  "License"); you may not use this file except in compliance
13  *  with the License.  You may obtain a copy of the License at
14  *
15  *      http://www.apache.org/licenses/LICENSE-2.0
16  *
17  *  Unless required by applicable law or agreed to in writing, software
18  *  distributed under the License is distributed on an "AS IS" BASIS,
19  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20  *  See the License for the specific language governing permissions and
21  *  limitations under the License.
22  */
23 
24 #pragma once
25 
26 #include <memory>
27 #include <atomic>
28 #include <cstddef>
29 
30 #include "I_IOBuffer.h"
31 
32 #include "QUICTypes.h"
33 #include "QUICRetryIntegrityTag.h"
34 
35 #define QUIC_FIELD_OFFSET_CONNECTION_ID 1
36 #define QUIC_FIELD_OFFSET_PACKET_NUMBER 4
37 #define QUIC_FIELD_OFFSET_PAYLOAD 5
38 
39 class UDPConnection;
40 
41 class QUICPacket
42 {
43 public:
44   static constexpr int MAX_INSTANCE_SIZE = 1024;
45 
46   // Token field in Initial packet could be very long.
47   static constexpr size_t MAX_PACKET_HEADER_LEN = 256;
48 
49   /**
50    * Creates a QUICPacket for sending packets
51    */
52   QUICPacket(bool ack_eliciting, bool probing);
53 
54   virtual ~QUICPacket();
55 
56   virtual QUICPacketType type() const              = 0;
57   virtual QUICConnectionId destination_cid() const = 0;
58   virtual QUICPacketNumber packet_number() const   = 0;
59   bool is_ack_eliciting() const;
60   bool is_probing_packet() const;
61 
62   // TODO These two should be pure virtual
63   virtual Ptr<IOBufferBlock>
header_block()64   header_block() const
65   {
66     return Ptr<IOBufferBlock>();
67   };
68   virtual Ptr<IOBufferBlock>
payload_block()69   payload_block() const
70   {
71     return Ptr<IOBufferBlock>();
72   };
73 
74   /*
75    * Size of whole QUIC packet (header + payload + integrity check)
76    */
77   virtual uint16_t size() const;
78 
79   /*
80    * Size of header
81    */
82   virtual uint16_t header_size() const;
83 
84   /*
85    * Length of payload (payload + integrity check if exists)
86    */
87   virtual uint16_t payload_length() const;
88 
89   /**
90    * Key phase
91    */
92   virtual QUICKeyPhase key_phase() const;
93 
94   // FIXME Remove this and use IOBufferBlock instead
95   void store(uint8_t *buf, size_t *len) const;
96 
97   /***** STATIC MEMBERS *****/
98 
99   static uint8_t calc_packet_number_len(QUICPacketNumber num, QUICPacketNumber base);
100   static bool encode_packet_number(QUICPacketNumber &dst, QUICPacketNumber src, size_t len);
101   static bool decode_packet_number(QUICPacketNumber &dst, QUICPacketNumber src, size_t len, QUICPacketNumber largest_acked);
102 
103 protected:
104   QUICPacket();
105 
106 private:
107   bool _is_ack_eliciting  = false;
108   bool _is_probing_packet = false;
109 };
110 
111 class QUICPacketR : public QUICPacket
112 {
113 public:
114   /**
115    * Creates a QUICPacket for receiving packets
116    */
117   QUICPacketR(UDPConnection *udp_con, IpEndpoint from, IpEndpoint to);
118 
119   virtual QUICPacketType type() const override = 0;
120 
121   UDPConnection *udp_con() const;
122   virtual const IpEndpoint &from() const;
123   virtual const IpEndpoint &to() const;
124 
125   static bool read_essential_info(Ptr<IOBufferBlock> block, QUICPacketType &type, QUICVersion &version, QUICConnectionId &dcid,
126                                   QUICConnectionId &scid, QUICPacketNumber &packet_number, QUICPacketNumber base_packet_number,
127                                   QUICKeyPhase &key_phase);
128   static bool type(QUICPacketType &type, const uint8_t *packet, size_t packet_len);
129 
130 protected:
131   Ptr<IOBufferBlock> _header_block;
132   Ptr<IOBufferBlock> _payload_block;
133 
134 private:
135   UDPConnection *_udp_con = nullptr;
136   const IpEndpoint _from  = {};
137   const IpEndpoint _to    = {};
138 };
139 
140 using QUICPacketDeleterFunc = void (*)(QUICPacket *p);
141 using QUICPacketUPtr        = std::unique_ptr<QUICPacket, QUICPacketDeleterFunc>;
142 
143 class QUICPacketDeleter
144 {
145 public:
146   static void
delete_null_packet(QUICPacket * packet)147   delete_null_packet(QUICPacket *packet)
148   {
149     ink_assert(packet == nullptr);
150   }
151 
152   static void
delete_dont_free(QUICPacket * packet)153   delete_dont_free(QUICPacket *packet)
154   {
155     packet->~QUICPacket();
156   }
157 
158   static void
delete_packet_new(QUICPacket * packet)159   delete_packet_new(QUICPacket *packet)
160   {
161     delete packet;
162   }
163 };
164 
165 class QUICLongHeaderPacket : public QUICPacket
166 {
167 public:
168   /**
169    * For sending packet
170    */
171   QUICLongHeaderPacket(QUICVersion version, const QUICConnectionId &dcid, const QUICConnectionId &scid, bool ack_eliciting,
172                        bool probing, bool crypto);
173 
174   QUICConnectionId source_cid() const;
175 
176   QUICConnectionId destination_cid() const override;
177   uint16_t payload_length() const override;
178   virtual QUICVersion version() const;
179   virtual bool is_crypto_packet() const;
180 
181 protected:
182   size_t _write_common_header(uint8_t *buf) const;
183 
184   Ptr<IOBufferBlock> _payload_block;
185   size_t _payload_length = 0;
186 
187 private:
188   QUICVersion _version;
189   QUICConnectionId _dcid;
190   QUICConnectionId _scid;
191 
192   bool _is_crypto_packet;
193 };
194 
195 class QUICLongHeaderPacketR : public QUICPacketR
196 {
197 public:
198   /**
199    * For receiving packet
200    */
201   QUICLongHeaderPacketR(UDPConnection *udp_con, IpEndpoint from, IpEndpoint to, Ptr<IOBufferBlock> blocks);
202 
~QUICLongHeaderPacketR()203   virtual ~QUICLongHeaderPacketR(){};
204 
205   QUICConnectionId destination_cid() const override;
206   QUICConnectionId source_cid() const;
207   virtual QUICVersion version() const;
208 
209   static bool type(QUICPacketType &type, const uint8_t *packet, size_t packet_len);
210   static bool version(QUICVersion &version, const uint8_t *packet, size_t packet_len);
211   static bool key_phase(QUICKeyPhase &key_phase, const uint8_t *packet, size_t packet_len);
212   static bool length(size_t &length, uint8_t &length_field_len, size_t &length_field_offset, const uint8_t *packet,
213                      size_t packet_len);
214   static bool packet_length(size_t &packet_len, const uint8_t *buf, size_t buf_len);
215   static bool packet_number_offset(size_t &pn_offset, const uint8_t *packet, size_t packet_len);
216 
217 protected:
218   QUICVersion _version;
219   QUICConnectionId _scid;
220   QUICConnectionId _dcid;
221 };
222 
223 class QUICShortHeaderPacket : public QUICPacket
224 {
225 public:
226   /**
227    * For sending packet
228    */
229   QUICShortHeaderPacket(const QUICConnectionId &dcid, QUICPacketNumber packet_number, QUICPacketNumber base_packet_number,
230                         QUICKeyPhase key_phase, bool ack_eliciting, bool probing);
231 
232   QUICPacketType type() const override;
233   QUICKeyPhase key_phase() const override;
234   QUICPacketNumber packet_number() const override;
235   QUICConnectionId destination_cid() const override;
236 
237   uint16_t payload_length() const override;
238   Ptr<IOBufferBlock> header_block() const override;
239   Ptr<IOBufferBlock> payload_block() const override;
240 
241   void attach_payload(Ptr<IOBufferBlock> payload, bool unprotected);
242 
243 private:
244   QUICConnectionId _dcid;
245   QUICPacketNumber _packet_number;
246   QUICKeyPhase _key_phase;
247   int _packet_number_len;
248 
249   Ptr<IOBufferBlock> _payload_block;
250   size_t _payload_length;
251 };
252 
253 class QUICShortHeaderPacketR : public QUICPacketR
254 {
255 public:
256   /**
257    * For receiving packet
258    */
259   QUICShortHeaderPacketR(UDPConnection *udp_con, IpEndpoint from, IpEndpoint to, Ptr<IOBufferBlock> blocks,
260                          QUICPacketNumber base_packet_number);
261 
262   void attach_payload(Ptr<IOBufferBlock> payload, bool unprotected);
263 
264   QUICPacketType type() const override;
265   QUICKeyPhase key_phase() const override;
266   QUICPacketNumber packet_number() const override;
267   QUICConnectionId destination_cid() const override;
268 
269   Ptr<IOBufferBlock> header_block() const override;
270   Ptr<IOBufferBlock> payload_block() const override;
271 
272   static bool packet_number_offset(size_t &pn_offset, const uint8_t *packet, size_t packet_len, int dcil);
273 
274 private:
275   QUICKeyPhase _key_phase;
276   QUICPacketNumber _packet_number;
277   int _packet_number_len;
278   QUICConnectionId _dcid;
279 };
280 
281 class QUICStatelessResetPacket : public QUICPacket
282 {
283 public:
284   /**
285    * For sending packet
286    */
287   QUICStatelessResetPacket(QUICStatelessResetToken token, size_t maximum_size);
288 
289   QUICPacketType type() const override;
290   QUICPacketNumber packet_number() const override;
291   QUICConnectionId destination_cid() const override;
292 
293   Ptr<IOBufferBlock> header_block() const override;
294   Ptr<IOBufferBlock> payload_block() const override;
295 
296   QUICStatelessResetToken token() const;
297 
298 private:
299   QUICStatelessResetToken _token;
300   size_t _maximum_size;
301 };
302 
303 class QUICStatelessResetPacketR : public QUICPacketR
304 {
305 public:
306   /**
307    * For receiving packet
308    */
309   QUICStatelessResetPacketR(UDPConnection *udp_con, IpEndpoint from, IpEndpoint to, Ptr<IOBufferBlock> blocks);
310 
311   QUICPacketType type() const override;
312   QUICPacketNumber packet_number() const override;
313   QUICConnectionId destination_cid() const override;
314 };
315 
316 class QUICVersionNegotiationPacket : public QUICLongHeaderPacket
317 {
318 public:
319   /**
320    * For sending packet
321    */
322   QUICVersionNegotiationPacket(const QUICConnectionId &dcid, const QUICConnectionId &scid, const QUICVersion versions[],
323                                int nversions, QUICVersion version_in_initial);
324 
325   QUICPacketType type() const override;
326   QUICVersion version() const override;
327   QUICPacketNumber packet_number() const override;
328   uint16_t payload_length() const override;
329 
330   Ptr<IOBufferBlock> header_block() const override;
331   Ptr<IOBufferBlock> payload_block() const override;
332 
333   const QUICVersion *versions() const;
334   int nversions() const;
335 
336 private:
337   const QUICVersion *_versions;
338   int _nversions;
339   const QUICVersion _version_in_initial;
340 };
341 
342 class QUICVersionNegotiationPacketR : public QUICLongHeaderPacketR
343 {
344 public:
345   /**
346    * For receiving packet
347    */
348   QUICVersionNegotiationPacketR(UDPConnection *udp_con, IpEndpoint from, IpEndpoint to, Ptr<IOBufferBlock> blocks);
349 
350   QUICPacketType type() const override;
351   QUICPacketNumber packet_number() const override;
352   QUICConnectionId destination_cid() const override;
353 
354   Ptr<IOBufferBlock> header_block() const override;
355   Ptr<IOBufferBlock> payload_block() const override;
356 
357   const QUICVersion supported_version(uint8_t index) const;
358   int nversions() const;
359 
360 private:
361   QUICConnectionId _dcid;
362   uint8_t *_versions;
363   int _nversions;
364 };
365 
366 class QUICInitialPacket : public QUICLongHeaderPacket
367 {
368 public:
369   /**
370    * For sending packet
371    */
372   QUICInitialPacket(QUICVersion version, const QUICConnectionId &dcid, const QUICConnectionId &scid, size_t token_len,
373                     ats_unique_buf token, size_t length, QUICPacketNumber packet_number, bool ack_eliciting, bool probing,
374                     bool crypto);
375 
376   QUICPacketType type() const override;
377   QUICPacketNumber packet_number() const override;
378   QUICKeyPhase key_phase() const override;
379 
380   Ptr<IOBufferBlock> header_block() const override;
381   Ptr<IOBufferBlock> payload_block() const override;
382   void attach_payload(Ptr<IOBufferBlock> payload, bool unprotected);
383 
384 private:
385   size_t _token_len     = 0;
386   ats_unique_buf _token = ats_unique_buf(nullptr);
387   QUICPacketNumber _packet_number;
388 };
389 
390 class QUICInitialPacketR : public QUICLongHeaderPacketR
391 {
392 public:
393   /**
394    * For receiving packet
395    */
396   QUICInitialPacketR(UDPConnection *udp_con, IpEndpoint from, IpEndpoint to, Ptr<IOBufferBlock> blocks,
397                      QUICPacketNumber base_packet_number);
398   ~QUICInitialPacketR();
399 
400   Ptr<IOBufferBlock> header_block() const override;
401   Ptr<IOBufferBlock> payload_block() const override;
402   void attach_payload(Ptr<IOBufferBlock> payload, bool unprotected);
403 
404   QUICPacketType type() const override;
405   QUICPacketNumber packet_number() const override;
406   QUICKeyPhase key_phase() const override;
407 
408   const QUICAddressValidationToken &token() const;
409 
410   static bool token_length(size_t &token_length, uint8_t &field_len, size_t &token_length_filed_offset, const uint8_t *packet,
411                            size_t packet_len);
412 
413 protected:
414   Ptr<IOBufferBlock> _payload_block;
415 
416 private:
417   QUICPacketNumber _packet_number;
418   QUICAddressValidationToken *_token = nullptr;
419 
420   bool _parse();
421 };
422 
423 class QUICZeroRttPacket : public QUICLongHeaderPacket
424 {
425 public:
426   /**
427    * For sending packet
428    */
429   QUICZeroRttPacket(QUICVersion version, const QUICConnectionId &dcid, const QUICConnectionId &scid, size_t length,
430                     QUICPacketNumber packet_number, bool ack_eliciting, bool probing);
431 
432   QUICPacketType type() const override;
433   QUICPacketNumber packet_number() const override;
434   QUICKeyPhase key_phase() const override;
435 
436   Ptr<IOBufferBlock> header_block() const override;
437   Ptr<IOBufferBlock> payload_block() const override;
438   void attach_payload(Ptr<IOBufferBlock> payload, bool unprotected);
439 
440 private:
441   QUICPacketNumber _packet_number;
442 };
443 
444 class QUICZeroRttPacketR : public QUICLongHeaderPacketR
445 {
446 public:
447   /**
448    * For receiving packet
449    */
450   QUICZeroRttPacketR(UDPConnection *udp_con, IpEndpoint from, IpEndpoint to, Ptr<IOBufferBlock> blocks,
451                      QUICPacketNumber base_packet_number);
452 
453   Ptr<IOBufferBlock> header_block() const override;
454   Ptr<IOBufferBlock> payload_block() const override;
455   void attach_payload(Ptr<IOBufferBlock> payload, bool unprotected);
456 
457   QUICPacketType type() const override;
458   QUICPacketNumber packet_number() const override;
459   QUICKeyPhase key_phase() const override;
460 
461 private:
462   QUICPacketNumber _packet_number;
463 };
464 
465 class QUICHandshakePacket : public QUICLongHeaderPacket
466 {
467 public:
468   /**
469    * For sending packet
470    */
471   QUICHandshakePacket(QUICVersion version, const QUICConnectionId &dcid, const QUICConnectionId &scid, size_t length,
472                       QUICPacketNumber packet_number, bool ack_eliciting, bool probing, bool crypto);
473 
474   QUICPacketType type() const override;
475   QUICKeyPhase key_phase() const override;
476   QUICPacketNumber packet_number() const override;
477 
478   Ptr<IOBufferBlock> header_block() const override;
479   Ptr<IOBufferBlock> payload_block() const override;
480   void attach_payload(Ptr<IOBufferBlock> payload, bool unprotected);
481 
482 private:
483   QUICPacketNumber _packet_number;
484 };
485 
486 class QUICHandshakePacketR : public QUICLongHeaderPacketR
487 {
488 public:
489   /**
490    * For receiving packet
491    */
492   QUICHandshakePacketR(UDPConnection *udp_con, IpEndpoint from, IpEndpoint to, Ptr<IOBufferBlock> blocks,
493                        QUICPacketNumber base_packet_number);
494 
495   Ptr<IOBufferBlock> header_block() const override;
496   Ptr<IOBufferBlock> payload_block() const override;
497   void attach_payload(Ptr<IOBufferBlock> payload, bool unprotected);
498 
499   QUICPacketType type() const override;
500   QUICKeyPhase key_phase() const override;
501   QUICPacketNumber packet_number() const override;
502 
503 private:
504   QUICPacketNumber _packet_number;
505 };
506 
507 class QUICRetryPacket : public QUICLongHeaderPacket
508 {
509 public:
510   /**
511    * For sending packet
512    */
513   QUICRetryPacket(QUICVersion version, const QUICConnectionId &dcid, const QUICConnectionId &scid, QUICRetryToken &token);
514 
515   QUICPacketType type() const override;
516   QUICPacketNumber packet_number() const override;
517   uint16_t payload_length() const override;
518 
519   Ptr<IOBufferBlock> header_block() const override;
520   Ptr<IOBufferBlock> payload_block() const override;
521 
522   const QUICRetryToken &token() const;
523 
524 private:
525   QUICRetryToken _token;
526 
527   bool _compute_retry_integrity_tag(uint8_t *out, QUICConnectionId odcid, Ptr<IOBufferBlock> header,
528                                     Ptr<IOBufferBlock> payload) const;
529 };
530 
531 class QUICRetryPacketR : public QUICLongHeaderPacketR
532 {
533 public:
534   /**
535    * For receiving packet
536    */
537   QUICRetryPacketR(UDPConnection *udp_con, IpEndpoint from, IpEndpoint to, Ptr<IOBufferBlock> blocks);
538   ~QUICRetryPacketR();
539 
540   Ptr<IOBufferBlock> header_block() const override;
541   Ptr<IOBufferBlock> payload_block() const override;
542 
543   QUICPacketType type() const override;
544   QUICPacketNumber packet_number() const override;
545 
546   const QUICAddressValidationToken &token() const;
547   bool has_valid_tag(const QUICConnectionId &odcid) const;
548 
549 private:
550   QUICAddressValidationToken *_token = nullptr;
551   uint8_t _integrity_tag[QUICRetryIntegrityTag::LEN];
552   Ptr<IOBufferBlock> _payload_block_without_tag;
553 };
554