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