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 "QUICHandshake.h"
25
26 #include <utility>
27
28 #include "QUICEvents.h"
29 #include "QUICGlobals.h"
30 #include "QUICHandshakeProtocol.h"
31 #include "QUICPacketFactory.h"
32 #include "QUICVersionNegotiator.h"
33 #include "QUICConfig.h"
34
35 #define QUICHSDebug(fmt, ...) Debug("quic_handshake", "[%s] " fmt, this->_qc->cids().data(), ##__VA_ARGS__)
36
37 #define QUICVHSDebug(fmt, ...) Debug("v_quic_handshake", "[%s] " fmt, this->_qc->cids().data(), ##__VA_ARGS__)
38
39 #define I_WANNA_DUMP_THIS_BUF(buf, len) \
40 { \
41 static constexpr char dump_tag[] = "v_quic_handshake_dump_pkt"; \
42 int i; \
43 Debug(dump_tag, "len=%" PRId64 "\n", len); \
44 for (i = 0; i < len / 8; i++) { \
45 Debug(dump_tag, "%02x %02x %02x %02x %02x %02x %02x %02x ", buf[i * 8 + 0], buf[i * 8 + 1], buf[i * 8 + 2], buf[i * 8 + 3], \
46 buf[i * 8 + 4], buf[i * 8 + 5], buf[i * 8 + 6], buf[i * 8 + 7]); \
47 } \
48 switch (len % 8) { \
49 case 1: \
50 Debug(dump_tag, "%02x", buf[i * 8 + 0]); \
51 break; \
52 case 2: \
53 Debug(dump_tag, "%02x %02x", buf[i * 8 + 0], buf[i * 8 + 1]); \
54 \
55 break; \
56 case 3: \
57 Debug(dump_tag, "%02x %02x %02x", buf[i * 8 + 0], buf[i * 8 + 1], buf[i * 8 + 2]); \
58 \
59 break; \
60 case 4: \
61 Debug(dump_tag, "%02x %02x %02x %02x", buf[i * 8 + 0], buf[i * 8 + 1], buf[i * 8 + 2], buf[i * 8 + 3]); \
62 \
63 break; \
64 case 5: \
65 Debug(dump_tag, "%02x %02x %02x %02x %02x", buf[i * 8 + 0], buf[i * 8 + 1], buf[i * 8 + 2], buf[i * 8 + 3], buf[i * 8 + 4]); \
66 \
67 break; \
68 case 6: \
69 Debug(dump_tag, "%02x %02x %02x %02x %02x %02x", buf[i * 8 + 0], buf[i * 8 + 1], buf[i * 8 + 2], buf[i * 8 + 3], \
70 buf[i * 8 + 4], buf[i * 8 + 5]); \
71 \
72 break; \
73 case 7: \
74 Debug(dump_tag, "%02x %02x %02x %02x %02x %02x %02x", buf[i * 8 + 0], buf[i * 8 + 1], buf[i * 8 + 2], buf[i * 8 + 3], \
75 buf[i * 8 + 4], buf[i * 8 + 5], buf[i * 8 + 6]); \
76 \
77 break; \
78 default: \
79 break; \
80 } \
81 }
82
83 static constexpr int UDP_MAXIMUM_PAYLOAD_SIZE = 65527;
84
QUICHandshake(QUICVersion version,QUICConnection * qc,QUICHandshakeProtocol * hsp)85 QUICHandshake::QUICHandshake(QUICVersion version, QUICConnection *qc, QUICHandshakeProtocol *hsp)
86 : QUICHandshake(version, qc, hsp, {}, false)
87 {
88 }
89
QUICHandshake(QUICVersion version,QUICConnection * qc,QUICHandshakeProtocol * hsp,QUICStatelessResetToken token,bool stateless_retry)90 QUICHandshake::QUICHandshake(QUICVersion version, QUICConnection *qc, QUICHandshakeProtocol *hsp, QUICStatelessResetToken token,
91 bool stateless_retry)
92 : _qc(qc),
93 _hs_protocol(hsp),
94 _version_negotiator(new QUICVersionNegotiator()),
95 _reset_token(token),
96 _stateless_retry(stateless_retry)
97 {
98 this->_hs_protocol->initialize_key_materials(this->_qc->original_connection_id(), version);
99
100 if (this->_qc->direction() == NET_VCONNECTION_OUT) {
101 this->_client_initial = true;
102 }
103 }
104
~QUICHandshake()105 QUICHandshake::~QUICHandshake()
106 {
107 delete this->_hs_protocol;
108 }
109
110 QUICConnectionErrorUPtr
start(const QUICTPConfig & tp_config,QUICPacketFactory * packet_factory,bool vn_exercise_enabled)111 QUICHandshake::start(const QUICTPConfig &tp_config, QUICPacketFactory *packet_factory, bool vn_exercise_enabled)
112 {
113 QUICVersion initial_version = QUIC_SUPPORTED_VERSIONS[0];
114 if (vn_exercise_enabled) {
115 initial_version = QUIC_EXERCISE_VERSION1;
116 }
117
118 this->_load_local_client_transport_parameters(tp_config);
119 packet_factory->set_version(initial_version);
120
121 return nullptr;
122 }
123
124 QUICConnectionErrorUPtr
start(const QUICTPConfig & tp_config,const QUICInitialPacketR & initial_packet,QUICPacketFactory * packet_factory,const QUICPreferredAddress * pref_addr)125 QUICHandshake::start(const QUICTPConfig &tp_config, const QUICInitialPacketR &initial_packet, QUICPacketFactory *packet_factory,
126 const QUICPreferredAddress *pref_addr)
127 {
128 // Negotiate version
129 if (this->_version_negotiator->status() == QUICVersionNegotiationStatus::NOT_NEGOTIATED) {
130 if (initial_packet.type() != QUICPacketType::INITIAL) {
131 return std::make_unique<QUICConnectionError>(QUICTransErrorCode::PROTOCOL_VIOLATION);
132 }
133 if (initial_packet.version()) {
134 if (this->_version_negotiator->negotiate(initial_packet) == QUICVersionNegotiationStatus::NEGOTIATED) {
135 QUICHSDebug("Version negotiation succeeded: %x", initial_packet.version());
136 this->_load_local_server_transport_parameters(tp_config, pref_addr);
137 packet_factory->set_version(this->_version_negotiator->negotiated_version());
138 } else {
139 ink_assert(!"Unsupported version initial packet should be dropped QUICPacketHandler");
140 }
141 } else {
142 return std::make_unique<QUICConnectionError>(QUICTransErrorCode::PROTOCOL_VIOLATION);
143 }
144 this->_initial_source_cid_received = initial_packet.source_cid();
145 }
146 return nullptr;
147 }
148
149 QUICConnectionErrorUPtr
negotiate_version(const QUICVersionNegotiationPacketR & vn,QUICPacketFactory * packet_factory)150 QUICHandshake::negotiate_version(const QUICVersionNegotiationPacketR &vn, QUICPacketFactory *packet_factory)
151 {
152 // Client side only
153 ink_assert(this->_qc->direction() == NET_VCONNECTION_OUT);
154
155 // If already negotiated, just ignore it
156 if (this->_version_negotiator->status() == QUICVersionNegotiationStatus::NEGOTIATED ||
157 this->_version_negotiator->status() == QUICVersionNegotiationStatus::VALIDATED) {
158 QUICHSDebug("Ignore Version Negotiation packet");
159 return nullptr;
160 }
161
162 if (vn.version() != 0x00) {
163 QUICHSDebug("Version field must be 0x00000000");
164 return std::make_unique<QUICConnectionError>(QUICTransErrorCode::PROTOCOL_VIOLATION);
165 }
166
167 if (this->_version_negotiator->negotiate(vn) == QUICVersionNegotiationStatus::NEGOTIATED) {
168 QUICVersion version = this->_version_negotiator->negotiated_version();
169 QUICHSDebug("Version negotiation succeeded: 0x%x", version);
170 packet_factory->set_version(version);
171 } else {
172 QUICHSDebug("Version negotiation failed");
173 return std::make_unique<QUICConnectionError>(QUICTransErrorCode::PROTOCOL_VIOLATION);
174 }
175
176 return nullptr;
177 }
178
179 bool
is_version_negotiated() const180 QUICHandshake::is_version_negotiated() const
181 {
182 return (this->_version_negotiator->status() == QUICVersionNegotiationStatus::NEGOTIATED ||
183 this->_version_negotiator->status() == QUICVersionNegotiationStatus::VALIDATED);
184 }
185
186 bool
is_completed() const187 QUICHandshake::is_completed() const
188 {
189 return this->_hs_protocol->is_handshake_finished();
190 }
191
192 bool
is_confirmed() const193 QUICHandshake::is_confirmed() const
194 {
195 if (this->_qc->direction() == NET_VCONNECTION_IN) {
196 return this->is_completed();
197 } else {
198 return this->_is_handshake_done_received;
199 }
200 }
201
202 bool
is_stateless_retry_enabled() const203 QUICHandshake::is_stateless_retry_enabled() const
204 {
205 return this->_stateless_retry;
206 }
207
208 bool
has_remote_tp() const209 QUICHandshake::has_remote_tp() const
210 {
211 return this->_remote_transport_parameters != nullptr;
212 }
213
214 QUICVersion
negotiated_version() const215 QUICHandshake::negotiated_version() const
216 {
217 return this->_version_negotiator->negotiated_version();
218 }
219
220 // Similar to SSLNetVConnection::getSSLCipherSuite()
221 const char *
negotiated_cipher_suite() const222 QUICHandshake::negotiated_cipher_suite() const
223 {
224 return this->_hs_protocol->negotiated_cipher_suite();
225 }
226
227 void
negotiated_application_name(const uint8_t ** name,unsigned int * len) const228 QUICHandshake::negotiated_application_name(const uint8_t **name, unsigned int *len) const
229 {
230 this->_hs_protocol->negotiated_application_name(name, len);
231 }
232
233 bool
check_remote_transport_parameters()234 QUICHandshake::check_remote_transport_parameters()
235 {
236 auto tp = this->_hs_protocol->remote_transport_parameters();
237
238 if (tp == nullptr) {
239 // nothing to check
240 return true;
241 }
242
243 if (std::dynamic_pointer_cast<const QUICTransportParametersInClientHello>(tp)) {
244 return this->_check_remote_transport_parameters(std::static_pointer_cast<const QUICTransportParametersInClientHello>(tp));
245 } else {
246 return this->_check_remote_transport_parameters(
247 std::static_pointer_cast<const QUICTransportParametersInEncryptedExtensions>(tp));
248 }
249 }
250
251 bool
_check_remote_transport_parameters(std::shared_ptr<const QUICTransportParametersInClientHello> tp)252 QUICHandshake::_check_remote_transport_parameters(std::shared_ptr<const QUICTransportParametersInClientHello> tp)
253 {
254 // An endpoint MUST treat receipt of duplicate transport parameters as a connection error of type TRANSPORT_PARAMETER_ERROR.
255 if (!tp->is_valid()) {
256 QUICHSDebug("Transport parameter is not valid");
257 this->_abort_handshake(QUICTransErrorCode::TRANSPORT_PARAMETER_ERROR);
258 return false;
259 }
260
261 // Check if CIDs in TP match with the ones in packets
262 if (this->negotiated_version() == QUIC_SUPPORTED_VERSIONS[0]) { // draft-28
263 uint16_t cid_buf_len;
264 const uint8_t *cid_buf = tp->getAsBytes(QUICTransportParameterId::INITIAL_SOURCE_CONNECTION_ID, cid_buf_len);
265 QUICConnectionId cid_in_tp(cid_buf, cid_buf_len);
266 if (cid_in_tp != this->_initial_source_cid_received) {
267 this->_abort_handshake(QUICTransErrorCode::PROTOCOL_VIOLATION);
268 return false;
269 }
270 }
271
272 this->_remote_transport_parameters = tp;
273
274 return true;
275 }
276
277 bool
_check_remote_transport_parameters(std::shared_ptr<const QUICTransportParametersInEncryptedExtensions> tp)278 QUICHandshake::_check_remote_transport_parameters(std::shared_ptr<const QUICTransportParametersInEncryptedExtensions> tp)
279 {
280 // An endpoint MUST treat receipt of duplicate transport parameters as a connection error of type TRANSPORT_PARAMETER_ERROR.
281 if (!tp->is_valid()) {
282 QUICHSDebug("Transport parameter is not valid");
283 this->_abort_handshake(QUICTransErrorCode::TRANSPORT_PARAMETER_ERROR);
284 return false;
285 }
286
287 // Check if CIDs in TP match with the ones in packets
288 if (this->negotiated_version() == QUIC_SUPPORTED_VERSIONS[0]) { // draft-28
289 uint16_t cid_buf_len;
290 const uint8_t *cid_buf = tp->getAsBytes(QUICTransportParameterId::INITIAL_SOURCE_CONNECTION_ID, cid_buf_len);
291 QUICConnectionId cid_in_tp(cid_buf, cid_buf_len);
292 if (cid_in_tp != this->_initial_source_cid_received) {
293 this->_abort_handshake(QUICTransErrorCode::PROTOCOL_VIOLATION);
294 return false;
295 }
296
297 if (!this->_retry_source_cid_received.is_zero()) {
298 cid_buf = tp->getAsBytes(QUICTransportParameterId::RETRY_SOURCE_CONNECTION_ID, cid_buf_len);
299 QUICConnectionId cid_in_tp(cid_buf, cid_buf_len);
300 if (cid_in_tp != this->_retry_source_cid_received) {
301 this->_abort_handshake(QUICTransErrorCode::PROTOCOL_VIOLATION);
302 return false;
303 }
304 }
305 }
306
307 this->_remote_transport_parameters = tp;
308
309 return true;
310 }
311
312 std::shared_ptr<const QUICTransportParameters>
local_transport_parameters()313 QUICHandshake::local_transport_parameters()
314 {
315 return this->_local_transport_parameters;
316 }
317
318 std::shared_ptr<const QUICTransportParameters>
remote_transport_parameters()319 QUICHandshake::remote_transport_parameters()
320 {
321 return this->_remote_transport_parameters;
322 }
323
324 /**
325 * reset states for starting over
326 */
327 void
reset()328 QUICHandshake::reset()
329 {
330 this->_client_initial = true;
331 this->_hs_protocol->reset();
332
333 for (auto level : QUIC_ENCRYPTION_LEVELS) {
334 int index = static_cast<int>(level);
335 QUICCryptoStream *stream = &this->_crypto_streams[index];
336 stream->reset_send_offset();
337 stream->reset_recv_offset();
338 }
339 }
340
341 void
update(const QUICInitialPacketR & packet)342 QUICHandshake::update(const QUICInitialPacketR &packet)
343 {
344 this->_initial_source_cid_received = packet.source_cid();
345 }
346
347 void
update(const QUICRetryPacketR & packet)348 QUICHandshake::update(const QUICRetryPacketR &packet)
349 {
350 this->_retry_source_cid_received = packet.source_cid();
351 }
352
353 std::vector<QUICFrameType>
interests()354 QUICHandshake::interests()
355 {
356 return {
357 QUICFrameType::CRYPTO,
358 QUICFrameType::HANDSHAKE_DONE,
359 };
360 }
361
362 QUICConnectionErrorUPtr
handle_frame(QUICEncryptionLevel level,const QUICFrame & frame)363 QUICHandshake::handle_frame(QUICEncryptionLevel level, const QUICFrame &frame)
364 {
365 QUICConnectionErrorUPtr error = nullptr;
366 switch (frame.type()) {
367 case QUICFrameType::CRYPTO:
368 error = this->_crypto_streams[static_cast<int>(level)].recv(static_cast<const QUICCryptoFrame &>(frame));
369 if (error == nullptr) {
370 error = this->do_handshake();
371 }
372 break;
373 case QUICFrameType::HANDSHAKE_DONE:
374 if (this->_qc->direction() == NET_VCONNECTION_IN) {
375 error = std::make_unique<QUICConnectionError>(QUICTransErrorCode::PROTOCOL_VIOLATION);
376 } else {
377 this->_is_handshake_done_received = true;
378 }
379 break;
380 default:
381 QUICHSDebug("Unexpected frame type: %02x", static_cast<unsigned int>(frame.type()));
382 ink_assert(false);
383 break;
384 }
385
386 return error;
387 }
388
389 bool
will_generate_frame(QUICEncryptionLevel level,size_t current_packet_size,bool ack_eliciting,uint32_t seq_num)390 QUICHandshake::will_generate_frame(QUICEncryptionLevel level, size_t current_packet_size, bool ack_eliciting, uint32_t seq_num)
391 {
392 if (!this->_is_level_matched(level)) {
393 return false;
394 }
395
396 return (this->_qc->direction() == NET_VCONNECTION_IN && !this->_is_handshake_done_sent) ||
397 this->_crypto_streams[static_cast<int>(level)].will_generate_frame(level, current_packet_size, ack_eliciting, seq_num);
398 }
399
400 QUICFrame *
generate_frame(uint8_t * buf,QUICEncryptionLevel level,uint64_t connection_credit,uint16_t maximum_frame_size,size_t current_packet_size,uint32_t seq_num)401 QUICHandshake::generate_frame(uint8_t *buf, QUICEncryptionLevel level, uint64_t connection_credit, uint16_t maximum_frame_size,
402 size_t current_packet_size, uint32_t seq_num)
403 {
404 QUICFrame *frame = nullptr;
405
406 if (this->_is_level_matched(level)) {
407 // CRYPTO
408 frame = this->_crypto_streams[static_cast<int>(level)].generate_frame(buf, level, connection_credit, maximum_frame_size,
409 current_packet_size, seq_num);
410 if (frame) {
411 return frame;
412 }
413 }
414
415 if (level == QUICEncryptionLevel::ONE_RTT) {
416 // HANDSHAKE_DONE
417 if (!this->_is_handshake_done_sent && this->is_completed()) {
418 frame = QUICFrameFactory::create_handshake_done_frame(buf, this->_issue_frame_id(), this);
419 }
420 if (frame) {
421 this->_is_handshake_done_sent = true;
422 return frame;
423 }
424 }
425
426 return frame;
427 }
428
429 void
_load_local_server_transport_parameters(const QUICTPConfig & tp_config,const QUICPreferredAddress * pref_addr)430 QUICHandshake::_load_local_server_transport_parameters(const QUICTPConfig &tp_config, const QUICPreferredAddress *pref_addr)
431 {
432 QUICTransportParametersInEncryptedExtensions *tp = new QUICTransportParametersInEncryptedExtensions();
433
434 // MUSTs
435 tp->set(QUICTransportParameterId::MAX_IDLE_TIMEOUT, static_cast<uint16_t>(tp_config.no_activity_timeout()));
436 if (this->_stateless_retry) {
437 tp->set(QUICTransportParameterId::ORIGINAL_DESTINATION_CONNECTION_ID, this->_qc->first_connection_id(),
438 this->_qc->first_connection_id().length());
439 tp->set(QUICTransportParameterId::RETRY_SOURCE_CONNECTION_ID, this->_qc->retry_source_connection_id(),
440 this->_qc->retry_source_connection_id().length());
441 } else {
442 if (this->negotiated_version() == QUIC_SUPPORTED_VERSIONS[0]) { // draft-28
443 tp->set(QUICTransportParameterId::ORIGINAL_DESTINATION_CONNECTION_ID, this->_qc->original_connection_id(),
444 this->_qc->original_connection_id().length());
445 }
446 }
447 if (this->negotiated_version() == QUIC_SUPPORTED_VERSIONS[0]) { // draft-28
448 tp->set(QUICTransportParameterId::INITIAL_SOURCE_CONNECTION_ID, this->_qc->initial_source_connection_id(),
449 this->_qc->initial_source_connection_id().length());
450 }
451
452 // MAYs
453 if (tp_config.initial_max_data() != 0) {
454 tp->set(QUICTransportParameterId::INITIAL_MAX_DATA, tp_config.initial_max_data());
455 }
456 if (tp_config.initial_max_streams_bidi() != 0) {
457 tp->set(QUICTransportParameterId::INITIAL_MAX_STREAMS_BIDI, tp_config.initial_max_streams_bidi());
458 }
459 if (tp_config.initial_max_streams_uni() != 0) {
460 tp->set(QUICTransportParameterId::INITIAL_MAX_STREAMS_UNI, tp_config.initial_max_streams_uni());
461 }
462 if (tp_config.initial_max_stream_data_bidi_local() != 0) {
463 tp->set(QUICTransportParameterId::INITIAL_MAX_STREAM_DATA_BIDI_LOCAL, tp_config.initial_max_stream_data_bidi_local());
464 }
465 if (tp_config.initial_max_stream_data_bidi_remote() != 0) {
466 tp->set(QUICTransportParameterId::INITIAL_MAX_STREAM_DATA_BIDI_REMOTE, tp_config.initial_max_stream_data_bidi_remote());
467 }
468 if (tp_config.initial_max_stream_data_uni() != 0) {
469 tp->set(QUICTransportParameterId::INITIAL_MAX_STREAM_DATA_UNI, tp_config.initial_max_stream_data_uni());
470 }
471 if (tp_config.disable_active_migration()) {
472 tp->set(QUICTransportParameterId::DISABLE_ACTIVE_MIGRATION, nullptr, 0);
473 }
474 if (pref_addr != nullptr) {
475 uint8_t pref_addr_buf[QUICPreferredAddress::MAX_LEN];
476 uint16_t len;
477 pref_addr->store(pref_addr_buf, len);
478 tp->set(QUICTransportParameterId::PREFERRED_ADDRESS, pref_addr_buf, len);
479 }
480 if (tp_config.active_cid_limit() != 0) {
481 tp->set(QUICTransportParameterId::ACTIVE_CONNECTION_ID_LIMIT, tp_config.active_cid_limit());
482 }
483
484 // MAYs (server)
485 tp->set(QUICTransportParameterId::STATELESS_RESET_TOKEN, this->_reset_token.buf(), QUICStatelessResetToken::LEN);
486 tp->set(QUICTransportParameterId::ACK_DELAY_EXPONENT, tp_config.ack_delay_exponent());
487
488 // Additional parameters
489 for (auto &¶m : tp_config.additional_tp()) {
490 tp->set(param.first, param.second.first, param.second.second);
491 }
492
493 // Additional parameters
494 for (auto &¶m : tp_config.additional_tp()) {
495 tp->set(param.first, param.second.first, param.second.second);
496 }
497
498 this->_local_transport_parameters = std::shared_ptr<QUICTransportParameters>(tp);
499 this->_hs_protocol->set_local_transport_parameters(this->_local_transport_parameters);
500 }
501
502 void
_load_local_client_transport_parameters(const QUICTPConfig & tp_config)503 QUICHandshake::_load_local_client_transport_parameters(const QUICTPConfig &tp_config)
504 {
505 QUICTransportParametersInClientHello *tp = new QUICTransportParametersInClientHello();
506
507 // MUSTs
508 tp->set(QUICTransportParameterId::MAX_IDLE_TIMEOUT, static_cast<uint16_t>(tp_config.no_activity_timeout()));
509 tp->set(QUICTransportParameterId::INITIAL_SOURCE_CONNECTION_ID, this->_qc->initial_source_connection_id(),
510 this->_qc->initial_source_connection_id().length());
511
512 // MAYs
513 if (tp_config.initial_max_data() != 0) {
514 tp->set(QUICTransportParameterId::INITIAL_MAX_DATA, tp_config.initial_max_data());
515 }
516 if (tp_config.initial_max_streams_bidi() != 0) {
517 tp->set(QUICTransportParameterId::INITIAL_MAX_STREAMS_BIDI, tp_config.initial_max_streams_bidi());
518 }
519 if (tp_config.initial_max_streams_uni() != 0) {
520 tp->set(QUICTransportParameterId::INITIAL_MAX_STREAMS_UNI, tp_config.initial_max_streams_uni());
521 }
522 if (tp_config.initial_max_stream_data_bidi_local() != 0) {
523 tp->set(QUICTransportParameterId::INITIAL_MAX_STREAM_DATA_BIDI_LOCAL, tp_config.initial_max_stream_data_bidi_local());
524 }
525 if (tp_config.initial_max_stream_data_bidi_remote() != 0) {
526 tp->set(QUICTransportParameterId::INITIAL_MAX_STREAM_DATA_BIDI_REMOTE, tp_config.initial_max_stream_data_bidi_remote());
527 }
528 if (tp_config.initial_max_stream_data_uni() != 0) {
529 tp->set(QUICTransportParameterId::INITIAL_MAX_STREAM_DATA_UNI, tp_config.initial_max_stream_data_uni());
530 }
531 tp->set(QUICTransportParameterId::ACK_DELAY_EXPONENT, tp_config.ack_delay_exponent());
532 if (tp_config.active_cid_limit() != 0) {
533 tp->set(QUICTransportParameterId::ACTIVE_CONNECTION_ID_LIMIT, tp_config.active_cid_limit());
534 }
535
536 // Additional parameters
537 for (auto &¶m : tp_config.additional_tp()) {
538 tp->set(param.first, param.second.first, param.second.second);
539 }
540
541 this->_local_transport_parameters = std::shared_ptr<QUICTransportParameters>(tp);
542 this->_hs_protocol->set_local_transport_parameters(std::unique_ptr<QUICTransportParameters>(tp));
543 }
544
545 QUICConnectionErrorUPtr
do_handshake()546 QUICHandshake::do_handshake()
547 {
548 QUICConnectionErrorUPtr error = nullptr;
549
550 QUICHandshakeMsgs in;
551 uint8_t in_buf[UDP_MAXIMUM_PAYLOAD_SIZE] = {0};
552 in.buf = in_buf;
553 in.max_buf_len = UDP_MAXIMUM_PAYLOAD_SIZE;
554
555 if (this->_client_initial) {
556 this->_client_initial = false;
557 } else {
558 for (auto level : QUIC_ENCRYPTION_LEVELS) {
559 int index = static_cast<int>(level);
560 QUICCryptoStream *stream = &this->_crypto_streams[index];
561 int64_t bytes_avail = stream->read_avail();
562 // TODO: check size
563 if (bytes_avail > 0) {
564 stream->read(in.buf + in.offsets[index], bytes_avail);
565 }
566 in.offsets[index + 1] = in.offsets[index] + bytes_avail;
567 }
568 }
569
570 QUICHandshakeMsgs *out = nullptr;
571 int result = this->_hs_protocol->handshake(&out, &in);
572 if (this->_remote_transport_parameters == nullptr) {
573 if (!this->check_remote_transport_parameters()) {
574 result = 0;
575 }
576 }
577
578 if (result == 1) {
579 if (out) {
580 for (auto level : QUIC_ENCRYPTION_LEVELS) {
581 int index = static_cast<int>(level);
582 QUICCryptoStream *stream = &this->_crypto_streams[index];
583 size_t len = out->offsets[index + 1] - out->offsets[index];
584 // TODO: check size
585 if (len > 0) {
586 stream->write(out->buf + out->offsets[index], len);
587 }
588 }
589 }
590 } else {
591 this->_hs_protocol->abort_handshake();
592 if (this->_hs_protocol->has_crypto_error()) {
593 error = std::make_unique<QUICConnectionError>(QUICErrorClass::TRANSPORT, this->_hs_protocol->crypto_error());
594 } else {
595 error = std::make_unique<QUICConnectionError>(QUICErrorClass::TRANSPORT,
596 static_cast<uint16_t>(QUICTransErrorCode::PROTOCOL_VIOLATION));
597 }
598 }
599
600 return error;
601 }
602
603 void
_abort_handshake(QUICTransErrorCode code)604 QUICHandshake::_abort_handshake(QUICTransErrorCode code)
605 {
606 QUICHSDebug("Abort Handshake");
607
608 this->_hs_protocol->abort_handshake();
609
610 this->_qc->close_quic_connection(QUICConnectionErrorUPtr(new QUICConnectionError(code)));
611 }
612
613 /*
614 No limit of encryption level.
615 ```
616 std::array<QUICEncryptionLevel, 4> _encryption_level_filter = {
617 QUICEncryptionLevel::INITIAL,
618 QUICEncryptionLevel::ZERO_RTT,
619 QUICEncryptionLevel::HANDSHAKE,
620 QUICEncryptionLevel::ONE_RTT,
621 };
622 ```
623 */
624 bool
_is_level_matched(QUICEncryptionLevel level)625 QUICHandshake::_is_level_matched(QUICEncryptionLevel level)
626 {
627 return true;
628 }
629
630 void
_on_frame_lost(QUICFrameInformationUPtr & info)631 QUICHandshake::_on_frame_lost(QUICFrameInformationUPtr &info)
632 {
633 ink_assert(info->type == QUICFrameType::HANDSHAKE_DONE);
634 this->_is_handshake_done_sent = false;
635 }
636