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 #include "QUICPacketFactory.h"
25 #include "QUICPacketProtectionKeyInfo.h"
26 #include "QUICDebugNames.h"
27 
28 using namespace std::literals;
29 static constexpr std::string_view tag   = "quic_packet"sv;
30 static constexpr std::string_view tag_v = "v_quic_packet"sv;
31 
32 #define QUICDebug(dcid, scid, fmt, ...) \
33   Debug(tag.data(), "[%08" PRIx32 "-%08" PRIx32 "] " fmt, dcid.h32(), scid.h32(), ##__VA_ARGS__);
34 #define QUICVDebug(dcid, scid, fmt, ...) \
35   Debug(tag_v.data(), "[%08" PRIx32 "-%08" PRIx32 "] " fmt, dcid.h32(), scid.h32(), ##__VA_ARGS__);
36 
37 //
38 // QUICPacketNumberGenerator
39 //
QUICPacketNumberGenerator()40 QUICPacketNumberGenerator::QUICPacketNumberGenerator() {}
41 
42 QUICPacketNumber
next()43 QUICPacketNumberGenerator::next()
44 {
45   // TODO Increment the number at least one but not only always one
46   return this->_current++;
47 }
48 
49 void
reset()50 QUICPacketNumberGenerator::reset()
51 {
52   this->_current = 0;
53 }
54 
55 //
56 // QUICPacketFactory
57 //
58 QUICPacketUPtr
create_null_packet()59 QUICPacketFactory::create_null_packet()
60 {
61   return {nullptr, &QUICPacketDeleter::delete_null_packet};
62 }
63 
64 QUICPacketUPtr
create(uint8_t * packet_buf,UDPConnection * udp_con,IpEndpoint from,IpEndpoint to,ats_unique_buf buf,size_t len,QUICPacketNumber base_packet_number,QUICPacketCreationResult & result)65 QUICPacketFactory::create(uint8_t *packet_buf, UDPConnection *udp_con, IpEndpoint from, IpEndpoint to, ats_unique_buf buf,
66                           size_t len, QUICPacketNumber base_packet_number, QUICPacketCreationResult &result)
67 {
68   QUICPacket *packet = nullptr;
69 
70   // FIXME This is temporal. Receive IOBufferBlock from the caller.
71   Ptr<IOBufferBlock> whole_data = make_ptr<IOBufferBlock>(new_IOBufferBlock());
72   whole_data->alloc(iobuffer_size_to_index(len, BUFFER_SIZE_INDEX_32K));
73   memcpy(whole_data->start(), buf.get(), len);
74   whole_data->fill(len);
75 
76   QUICPacketType type;
77   QUICVersion version;
78   QUICConnectionId dcid;
79   QUICConnectionId scid;
80   QUICPacketNumber packet_number;
81   QUICKeyPhase key_phase;
82 
83   if (QUICPacketR::read_essential_info(whole_data, type, version, dcid, scid, packet_number, base_packet_number, key_phase)) {
84     QUICVDebug(scid, dcid, "Decrypting %s packet #%" PRIu64 " using %s", QUICDebugNames::packet_type(type), packet_number,
85                QUICDebugNames::key_phase(key_phase));
86 
87     if (type != QUICPacketType::PROTECTED && !QUICTypeUtil::is_supported_version(version)) {
88       if (type == QUICPacketType::VERSION_NEGOTIATION) {
89         packet = new QUICVersionNegotiationPacketR(udp_con, from, to, whole_data);
90         result = QUICPacketCreationResult::SUCCESS;
91       } else {
92         // We can't decrypt packets that have unknown versions
93         // What we can use is invariant field of Long Header - version, dcid, and scid
94         result = QUICPacketCreationResult::UNSUPPORTED;
95       }
96     } else {
97       Ptr<IOBufferBlock> plain;
98       switch (type) {
99       case QUICPacketType::STATELESS_RESET:
100         packet = new (packet_buf) QUICStatelessResetPacketR(udp_con, from, to, whole_data);
101         result = QUICPacketCreationResult::SUCCESS;
102         break;
103       case QUICPacketType::RETRY:
104         packet = new (packet_buf) QUICRetryPacketR(udp_con, from, to, whole_data);
105         result = QUICPacketCreationResult::SUCCESS;
106         break;
107       case QUICPacketType::PROTECTED:
108         packet = new (packet_buf) QUICShortHeaderPacketR(udp_con, from, to, whole_data, base_packet_number);
109         if (this->_pp_key_info.is_decryption_key_available(packet->key_phase())) {
110           plain = this->_pp_protector.unprotect(packet->header_block(), packet->payload_block(), packet->packet_number(),
111                                                 packet->key_phase());
112           if (plain != nullptr) {
113             static_cast<QUICShortHeaderPacketR *>(packet)->attach_payload(plain, true);
114             result = QUICPacketCreationResult::SUCCESS;
115           } else {
116             result = QUICPacketCreationResult::FAILED;
117           }
118         } else {
119           result = QUICPacketCreationResult::NOT_READY;
120         }
121         break;
122       case QUICPacketType::INITIAL:
123         packet = new (packet_buf) QUICInitialPacketR(udp_con, from, to, whole_data, base_packet_number);
124         if (this->_pp_key_info.is_decryption_key_available(QUICKeyPhase::INITIAL)) {
125           plain = this->_pp_protector.unprotect(packet->header_block(), packet->payload_block(), packet->packet_number(),
126                                                 packet->key_phase());
127           if (plain != nullptr) {
128             static_cast<QUICInitialPacketR *>(packet)->attach_payload(plain, true);
129             result = QUICPacketCreationResult::SUCCESS;
130           } else {
131             result = QUICPacketCreationResult::FAILED;
132           }
133         } else {
134           result = QUICPacketCreationResult::IGNORED;
135         }
136         break;
137       case QUICPacketType::HANDSHAKE:
138         packet = new (packet_buf) QUICHandshakePacketR(udp_con, from, to, whole_data, base_packet_number);
139         if (this->_pp_key_info.is_decryption_key_available(QUICKeyPhase::HANDSHAKE)) {
140           plain = this->_pp_protector.unprotect(packet->header_block(), packet->payload_block(), packet->packet_number(),
141                                                 packet->key_phase());
142           if (plain != nullptr) {
143             static_cast<QUICHandshakePacketR *>(packet)->attach_payload(plain, true);
144             result = QUICPacketCreationResult::SUCCESS;
145           } else {
146             result = QUICPacketCreationResult::FAILED;
147           }
148         } else {
149           result = QUICPacketCreationResult::IGNORED;
150         }
151         break;
152       case QUICPacketType::ZERO_RTT_PROTECTED:
153         packet = new (packet_buf) QUICZeroRttPacketR(udp_con, from, to, whole_data, base_packet_number);
154         if (this->_pp_key_info.is_decryption_key_available(QUICKeyPhase::ZERO_RTT)) {
155           plain = this->_pp_protector.unprotect(packet->header_block(), packet->payload_block(), packet->packet_number(),
156                                                 packet->key_phase());
157           if (plain != nullptr) {
158             static_cast<QUICZeroRttPacketR *>(packet)->attach_payload(plain, true);
159             result = QUICPacketCreationResult::SUCCESS;
160           } else {
161             result = QUICPacketCreationResult::IGNORED;
162           }
163         } else {
164           result = QUICPacketCreationResult::NOT_READY;
165         }
166         break;
167       default:
168         result = QUICPacketCreationResult::FAILED;
169         break;
170       }
171     }
172   } else {
173     Debug(tag.data(), "Failed to read essential field");
174     uint8_t *buf = reinterpret_cast<uint8_t *>(whole_data->start());
175     if (len > 16) {
176       Debug(tag_v.data(), "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", buf[0], buf[1], buf[2],
177             buf[3], buf[4], buf[5], buf[6], buf[7], buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15]);
178     }
179     if (len > 32) {
180       Debug(tag_v.data(), "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", buf[16 + 0],
181             buf[16 + 1], buf[16 + 2], buf[16 + 3], buf[16 + 4], buf[16 + 5], buf[16 + 6], buf[16 + 7], buf[16 + 8], buf[16 + 9],
182             buf[16 + 10], buf[16 + 11], buf[16 + 12], buf[16 + 13], buf[16 + 14], buf[16 + 15]);
183     }
184     if (len > 48) {
185       Debug(tag_v.data(), "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", buf[32 + 0],
186             buf[32 + 1], buf[32 + 2], buf[32 + 3], buf[32 + 4], buf[32 + 5], buf[32 + 6], buf[32 + 7], buf[32 + 8], buf[32 + 9],
187             buf[32 + 10], buf[32 + 11], buf[32 + 12], buf[32 + 13], buf[32 + 14], buf[32 + 15]);
188     }
189     result = QUICPacketCreationResult::FAILED;
190   }
191 
192   if (result != QUICPacketCreationResult::SUCCESS && result != QUICPacketCreationResult::UNSUPPORTED) {
193     packet = nullptr;
194   }
195 
196   return QUICPacketUPtr(packet, &QUICPacketDeleter::delete_dont_free);
197 }
198 
199 QUICPacketUPtr
create_version_negotiation_packet(QUICConnectionId dcid,QUICConnectionId scid,QUICVersion version_in_initial)200 QUICPacketFactory::create_version_negotiation_packet(QUICConnectionId dcid, QUICConnectionId scid, QUICVersion version_in_initial)
201 {
202   return QUICPacketUPtr(
203     new QUICVersionNegotiationPacket(dcid, scid, QUIC_SUPPORTED_VERSIONS, countof(QUIC_SUPPORTED_VERSIONS), version_in_initial),
204     &QUICPacketDeleter::delete_packet_new);
205 }
206 
207 QUICPacketUPtr
create_initial_packet(uint8_t * packet_buf,QUICConnectionId destination_cid,QUICConnectionId source_cid,QUICPacketNumber base_packet_number,Ptr<IOBufferBlock> payload,size_t length,bool ack_eliciting,bool probing,bool crypto,ats_unique_buf token,size_t token_len)208 QUICPacketFactory::create_initial_packet(uint8_t *packet_buf, QUICConnectionId destination_cid, QUICConnectionId source_cid,
209                                          QUICPacketNumber base_packet_number, Ptr<IOBufferBlock> payload, size_t length,
210                                          bool ack_eliciting, bool probing, bool crypto, ats_unique_buf token, size_t token_len)
211 {
212   QUICPacketNumberSpace index = QUICTypeUtil::pn_space(QUICEncryptionLevel::INITIAL);
213   QUICPacketNumber pn         = this->_packet_number_generator[static_cast<int>(index)].next();
214 
215   QUICInitialPacket *packet = new (packet_buf) QUICInitialPacket(this->_version, destination_cid, source_cid, token_len,
216                                                                  std::move(token), length, pn, ack_eliciting, probing, crypto);
217 
218   packet->attach_payload(payload, true); // Attach a cleartext payload with extra headers
219   Ptr<IOBufferBlock> protected_payload =
220     this->_pp_protector.protect(packet->header_block(), packet->payload_block(), packet->packet_number(), packet->key_phase());
221   if (protected_payload != nullptr) {
222     packet->attach_payload(protected_payload, false); // Replace its payload with the protected payload
223   } else {
224     QUICDebug(destination_cid, source_cid, "Failed to encrypt a packet");
225     packet = nullptr;
226   }
227 
228   return QUICPacketUPtr(packet, &QUICPacketDeleter::delete_dont_free);
229 }
230 
231 QUICPacketUPtr
create_retry_packet(QUICVersion version,QUICConnectionId destination_cid,QUICConnectionId source_cid,QUICRetryToken & token)232 QUICPacketFactory::create_retry_packet(QUICVersion version, QUICConnectionId destination_cid, QUICConnectionId source_cid,
233                                        QUICRetryToken &token)
234 {
235   return QUICPacketUPtr(new QUICRetryPacket(version, destination_cid, source_cid, token), &QUICPacketDeleter::delete_packet_new);
236 }
237 
238 QUICPacketUPtr
create_handshake_packet(uint8_t * packet_buf,QUICConnectionId destination_cid,QUICConnectionId source_cid,QUICPacketNumber base_packet_number,Ptr<IOBufferBlock> payload,size_t length,bool ack_eliciting,bool probing,bool crypto)239 QUICPacketFactory::create_handshake_packet(uint8_t *packet_buf, QUICConnectionId destination_cid, QUICConnectionId source_cid,
240                                            QUICPacketNumber base_packet_number, Ptr<IOBufferBlock> payload, size_t length,
241                                            bool ack_eliciting, bool probing, bool crypto)
242 {
243   QUICPacketNumberSpace index = QUICTypeUtil::pn_space(QUICEncryptionLevel::HANDSHAKE);
244   QUICPacketNumber pn         = this->_packet_number_generator[static_cast<int>(index)].next();
245 
246   QUICHandshakePacket *packet =
247     new (packet_buf) QUICHandshakePacket(this->_version, destination_cid, source_cid, length, pn, ack_eliciting, probing, crypto);
248 
249   packet->attach_payload(payload, true); // Attach a cleartext payload with extra headers
250   Ptr<IOBufferBlock> protected_payload =
251     this->_pp_protector.protect(packet->header_block(), packet->payload_block(), packet->packet_number(), packet->key_phase());
252   if (protected_payload != nullptr) {
253     packet->attach_payload(protected_payload, false); // Replace its payload with the protected payload
254   } else {
255     QUICDebug(destination_cid, source_cid, "Failed to encrypt a packet");
256     packet = nullptr;
257   }
258 
259   return QUICPacketUPtr(packet, &QUICPacketDeleter::delete_dont_free);
260 }
261 
262 QUICPacketUPtr
create_zero_rtt_packet(uint8_t * packet_buf,QUICConnectionId destination_cid,QUICConnectionId source_cid,QUICPacketNumber base_packet_number,Ptr<IOBufferBlock> payload,size_t length,bool ack_eliciting,bool probing)263 QUICPacketFactory::create_zero_rtt_packet(uint8_t *packet_buf, QUICConnectionId destination_cid, QUICConnectionId source_cid,
264                                           QUICPacketNumber base_packet_number, Ptr<IOBufferBlock> payload, size_t length,
265                                           bool ack_eliciting, bool probing)
266 {
267   QUICPacketNumberSpace index = QUICTypeUtil::pn_space(QUICEncryptionLevel::ZERO_RTT);
268   QUICPacketNumber pn         = this->_packet_number_generator[static_cast<int>(index)].next();
269 
270   QUICZeroRttPacket *packet =
271     new (packet_buf) QUICZeroRttPacket(this->_version, destination_cid, source_cid, length, pn, ack_eliciting, probing);
272 
273   packet->attach_payload(payload, true); // Attach a cleartext payload with extra headers
274   Ptr<IOBufferBlock> protected_payload =
275     this->_pp_protector.protect(packet->header_block(), packet->payload_block(), packet->packet_number(), packet->key_phase());
276   if (protected_payload != nullptr) {
277     packet->attach_payload(protected_payload, false); // Replace its payload with the protected payload
278   } else {
279     QUICDebug(destination_cid, source_cid, "Failed to encrypt a packet");
280     packet = nullptr;
281   }
282 
283   return QUICPacketUPtr(packet, &QUICPacketDeleter::delete_dont_free);
284 }
285 
286 QUICPacketUPtr
create_short_header_packet(uint8_t * packet_buf,QUICConnectionId destination_cid,QUICPacketNumber base_packet_number,Ptr<IOBufferBlock> payload,size_t length,bool ack_eliciting,bool probing)287 QUICPacketFactory::create_short_header_packet(uint8_t *packet_buf, QUICConnectionId destination_cid,
288                                               QUICPacketNumber base_packet_number, Ptr<IOBufferBlock> payload, size_t length,
289                                               bool ack_eliciting, bool probing)
290 {
291   QUICPacketNumberSpace index = QUICTypeUtil::pn_space(QUICEncryptionLevel::ONE_RTT);
292   QUICPacketNumber pn         = this->_packet_number_generator[static_cast<int>(index)].next();
293 
294   // TODO Key phase should be picked up from QUICHandshakeProtocol, probably
295   QUICShortHeaderPacket *packet =
296     new (packet_buf) QUICShortHeaderPacket(destination_cid, pn, base_packet_number, QUICKeyPhase::PHASE_0, ack_eliciting, probing);
297 
298   packet->attach_payload(payload, true); // Attach a cleartext payload with extra headers
299   Ptr<IOBufferBlock> protected_payload =
300     this->_pp_protector.protect(packet->header_block(), packet->payload_block(), packet->packet_number(), packet->key_phase());
301   if (protected_payload != nullptr) {
302     packet->attach_payload(protected_payload, false); // Replace its payload with the protected payload
303   } else {
304     QUICDebug(destination_cid, QUICConnectionId::ZERO(), "Failed to encrypt a packet");
305     packet = nullptr;
306   }
307 
308   return QUICPacketUPtr(packet, &QUICPacketDeleter::delete_dont_free);
309 }
310 
311 QUICPacketUPtr
create_stateless_reset_packet(QUICStatelessResetToken stateless_reset_token,size_t maximum_size)312 QUICPacketFactory::create_stateless_reset_packet(QUICStatelessResetToken stateless_reset_token, size_t maximum_size)
313 {
314   return QUICPacketUPtr(new QUICStatelessResetPacket(stateless_reset_token, maximum_size), &QUICPacketDeleter::delete_packet_new);
315 }
316 
317 void
set_version(QUICVersion negotiated_version)318 QUICPacketFactory::set_version(QUICVersion negotiated_version)
319 {
320   this->_version = negotiated_version;
321 }
322 
323 bool
is_ready_to_create_protected_packet()324 QUICPacketFactory::is_ready_to_create_protected_packet()
325 {
326   return this->_pp_key_info.is_encryption_key_available(QUICKeyPhase::PHASE_0) ||
327          this->_pp_key_info.is_encryption_key_available(QUICKeyPhase::PHASE_1);
328 }
329 
330 void
reset()331 QUICPacketFactory::reset()
332 {
333   for (auto i = 0; i < QUIC_N_PACKET_SPACES; i++) {
334     this->_packet_number_generator[i].reset();
335   }
336 }
337