blob: 8e8b9004b2c236e8fa7a09de6c9b310b0041c46a [file] [log] [blame]
Bence Békybac04052022-04-07 15:44:29 -04001// Copyright (c) 2018 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "quiche/quic/core/crypto/transport_parameters.h"
6
7#include <cstdint>
8#include <cstring>
9#include <forward_list>
10#include <memory>
11#include <utility>
12
13#include "absl/strings/escaping.h"
14#include "absl/strings/str_cat.h"
15#include "absl/strings/string_view.h"
vasilvvdaa2fda2022-04-11 14:08:36 -070016#include "openssl/digest.h"
17#include "openssl/sha.h"
Bence Békybac04052022-04-07 15:44:29 -040018#include "quiche/quic/core/quic_connection_id.h"
19#include "quiche/quic/core/quic_data_reader.h"
20#include "quiche/quic/core/quic_data_writer.h"
21#include "quiche/quic/core/quic_types.h"
22#include "quiche/quic/core/quic_utils.h"
23#include "quiche/quic/core/quic_versions.h"
24#include "quiche/quic/platform/api/quic_bug_tracker.h"
25#include "quiche/quic/platform/api/quic_flag_utils.h"
26#include "quiche/quic/platform/api/quic_ip_address.h"
27
28namespace quic {
29
30// Values of the TransportParameterId enum as defined in the
31// "Transport Parameter Encoding" section of draft-ietf-quic-transport.
32// When parameters are encoded, one of these enum values is used to indicate
33// which parameter is encoded. The supported draft version is noted in
34// transport_parameters.h.
35enum TransportParameters::TransportParameterId : uint64_t {
36 kOriginalDestinationConnectionId = 0,
37 kMaxIdleTimeout = 1,
38 kStatelessResetToken = 2,
39 kMaxPacketSize = 3,
40 kInitialMaxData = 4,
41 kInitialMaxStreamDataBidiLocal = 5,
42 kInitialMaxStreamDataBidiRemote = 6,
43 kInitialMaxStreamDataUni = 7,
44 kInitialMaxStreamsBidi = 8,
45 kInitialMaxStreamsUni = 9,
46 kAckDelayExponent = 0xa,
47 kMaxAckDelay = 0xb,
48 kDisableActiveMigration = 0xc,
49 kPreferredAddress = 0xd,
50 kActiveConnectionIdLimit = 0xe,
51 kInitialSourceConnectionId = 0xf,
52 kRetrySourceConnectionId = 0x10,
53
54 kMaxDatagramFrameSize = 0x20,
55
56 kInitialRoundTripTime = 0x3127,
57 kGoogleConnectionOptions = 0x3128,
58 // 0x3129 was used to convey the user agent string.
59 // 0x312A was used only in T050 to indicate support for HANDSHAKE_DONE.
60 // 0x312B was used to indicate that QUIC+TLS key updates were not supported.
61 // 0x4751 was used for non-standard Google-specific parameters encoded as a
62 // Google QUIC_CRYPTO CHLO, it has been replaced by individual parameters.
63 kGoogleQuicVersion =
64 0x4752, // Used to transmit version and supported_versions.
65
66 kMinAckDelay = 0xDE1A, // draft-iyengar-quic-delayed-ack.
67 kVersionInformation = 0xFF73DB, // draft-ietf-quic-version-negotiation.
68};
69
70namespace {
71
72// The following constants define minimum and maximum allowed values for some of
73// the parameters. These come from the "Transport Parameter Definitions"
74// section of draft-ietf-quic-transport.
75constexpr uint64_t kMinMaxPacketSizeTransportParam = 1200;
76constexpr uint64_t kMaxAckDelayExponentTransportParam = 20;
77constexpr uint64_t kDefaultAckDelayExponentTransportParam = 3;
78constexpr uint64_t kMaxMaxAckDelayTransportParam = 16383;
79constexpr uint64_t kDefaultMaxAckDelayTransportParam = 25;
80constexpr uint64_t kMinActiveConnectionIdLimitTransportParam = 2;
81constexpr uint64_t kDefaultActiveConnectionIdLimitTransportParam = 2;
82
83std::string TransportParameterIdToString(
84 TransportParameters::TransportParameterId param_id) {
85 switch (param_id) {
86 case TransportParameters::kOriginalDestinationConnectionId:
87 return "original_destination_connection_id";
88 case TransportParameters::kMaxIdleTimeout:
89 return "max_idle_timeout";
90 case TransportParameters::kStatelessResetToken:
91 return "stateless_reset_token";
92 case TransportParameters::kMaxPacketSize:
93 return "max_udp_payload_size";
94 case TransportParameters::kInitialMaxData:
95 return "initial_max_data";
96 case TransportParameters::kInitialMaxStreamDataBidiLocal:
97 return "initial_max_stream_data_bidi_local";
98 case TransportParameters::kInitialMaxStreamDataBidiRemote:
99 return "initial_max_stream_data_bidi_remote";
100 case TransportParameters::kInitialMaxStreamDataUni:
101 return "initial_max_stream_data_uni";
102 case TransportParameters::kInitialMaxStreamsBidi:
103 return "initial_max_streams_bidi";
104 case TransportParameters::kInitialMaxStreamsUni:
105 return "initial_max_streams_uni";
106 case TransportParameters::kAckDelayExponent:
107 return "ack_delay_exponent";
108 case TransportParameters::kMaxAckDelay:
109 return "max_ack_delay";
110 case TransportParameters::kDisableActiveMigration:
111 return "disable_active_migration";
112 case TransportParameters::kPreferredAddress:
113 return "preferred_address";
114 case TransportParameters::kActiveConnectionIdLimit:
115 return "active_connection_id_limit";
116 case TransportParameters::kInitialSourceConnectionId:
117 return "initial_source_connection_id";
118 case TransportParameters::kRetrySourceConnectionId:
119 return "retry_source_connection_id";
120 case TransportParameters::kMaxDatagramFrameSize:
121 return "max_datagram_frame_size";
122 case TransportParameters::kInitialRoundTripTime:
123 return "initial_round_trip_time";
124 case TransportParameters::kGoogleConnectionOptions:
125 return "google_connection_options";
126 case TransportParameters::kGoogleQuicVersion:
127 return "google-version";
128 case TransportParameters::kMinAckDelay:
129 return "min_ack_delay_us";
130 case TransportParameters::kVersionInformation:
131 return "version_information";
132 }
133 return absl::StrCat("Unknown(", param_id, ")");
134}
135
136bool TransportParameterIdIsKnown(
137 TransportParameters::TransportParameterId param_id) {
138 switch (param_id) {
139 case TransportParameters::kOriginalDestinationConnectionId:
140 case TransportParameters::kMaxIdleTimeout:
141 case TransportParameters::kStatelessResetToken:
142 case TransportParameters::kMaxPacketSize:
143 case TransportParameters::kInitialMaxData:
144 case TransportParameters::kInitialMaxStreamDataBidiLocal:
145 case TransportParameters::kInitialMaxStreamDataBidiRemote:
146 case TransportParameters::kInitialMaxStreamDataUni:
147 case TransportParameters::kInitialMaxStreamsBidi:
148 case TransportParameters::kInitialMaxStreamsUni:
149 case TransportParameters::kAckDelayExponent:
150 case TransportParameters::kMaxAckDelay:
151 case TransportParameters::kDisableActiveMigration:
152 case TransportParameters::kPreferredAddress:
153 case TransportParameters::kActiveConnectionIdLimit:
154 case TransportParameters::kInitialSourceConnectionId:
155 case TransportParameters::kRetrySourceConnectionId:
156 case TransportParameters::kMaxDatagramFrameSize:
157 case TransportParameters::kInitialRoundTripTime:
158 case TransportParameters::kGoogleConnectionOptions:
159 case TransportParameters::kGoogleQuicVersion:
160 case TransportParameters::kMinAckDelay:
161 case TransportParameters::kVersionInformation:
162 return true;
163 }
164 return false;
165}
166
167} // namespace
168
169TransportParameters::IntegerParameter::IntegerParameter(
170 TransportParameters::TransportParameterId param_id,
171 uint64_t default_value,
172 uint64_t min_value,
173 uint64_t max_value)
174 : param_id_(param_id),
175 value_(default_value),
176 default_value_(default_value),
177 min_value_(min_value),
178 max_value_(max_value),
179 has_been_read_(false) {
180 QUICHE_DCHECK_LE(min_value, default_value);
181 QUICHE_DCHECK_LE(default_value, max_value);
182 QUICHE_DCHECK_LE(max_value, kVarInt62MaxValue);
183}
184
185TransportParameters::IntegerParameter::IntegerParameter(
186 TransportParameters::TransportParameterId param_id)
187 : TransportParameters::IntegerParameter::IntegerParameter(
188 param_id,
189 0,
190 0,
191 kVarInt62MaxValue) {}
192
193void TransportParameters::IntegerParameter::set_value(uint64_t value) {
194 value_ = value;
195}
196
197uint64_t TransportParameters::IntegerParameter::value() const {
198 return value_;
199}
200
201bool TransportParameters::IntegerParameter::IsValid() const {
202 return min_value_ <= value_ && value_ <= max_value_;
203}
204
205bool TransportParameters::IntegerParameter::Write(
206 QuicDataWriter* writer) const {
207 QUICHE_DCHECK(IsValid());
208 if (value_ == default_value_) {
209 // Do not write if the value is default.
210 return true;
211 }
212 if (!writer->WriteVarInt62(param_id_)) {
213 QUIC_BUG(quic_bug_10743_1) << "Failed to write param_id for " << *this;
214 return false;
215 }
216 const QuicVariableLengthIntegerLength value_length =
217 QuicDataWriter::GetVarInt62Len(value_);
218 if (!writer->WriteVarInt62(value_length)) {
219 QUIC_BUG(quic_bug_10743_2) << "Failed to write value_length for " << *this;
220 return false;
221 }
222 if (!writer->WriteVarInt62(value_, value_length)) {
223 QUIC_BUG(quic_bug_10743_3) << "Failed to write value for " << *this;
224 return false;
225 }
226 return true;
227}
228
229bool TransportParameters::IntegerParameter::Read(QuicDataReader* reader,
230 std::string* error_details) {
231 if (has_been_read_) {
232 *error_details =
233 "Received a second " + TransportParameterIdToString(param_id_);
234 return false;
235 }
236 has_been_read_ = true;
237
238 if (!reader->ReadVarInt62(&value_)) {
239 *error_details =
240 "Failed to parse value for " + TransportParameterIdToString(param_id_);
241 return false;
242 }
243 if (!reader->IsDoneReading()) {
244 *error_details =
245 absl::StrCat("Received unexpected ", reader->BytesRemaining(),
246 " bytes after parsing ", this->ToString(false));
247 return false;
248 }
249 return true;
250}
251
252std::string TransportParameters::IntegerParameter::ToString(
253 bool for_use_in_list) const {
254 if (for_use_in_list && value_ == default_value_) {
255 return "";
256 }
257 std::string rv = for_use_in_list ? " " : "";
258 absl::StrAppend(&rv, TransportParameterIdToString(param_id_), " ", value_);
259 if (!IsValid()) {
260 rv += " (Invalid)";
261 }
262 return rv;
263}
264
265std::ostream& operator<<(std::ostream& os,
266 const TransportParameters::IntegerParameter& param) {
267 os << param.ToString(/*for_use_in_list=*/false);
268 return os;
269}
270
271TransportParameters::PreferredAddress::PreferredAddress()
272 : ipv4_socket_address(QuicIpAddress::Any4(), 0),
273 ipv6_socket_address(QuicIpAddress::Any6(), 0),
274 connection_id(EmptyQuicConnectionId()),
275 stateless_reset_token(kStatelessResetTokenLength, 0) {}
276
277TransportParameters::PreferredAddress::~PreferredAddress() {}
278
279bool TransportParameters::PreferredAddress::operator==(
280 const PreferredAddress& rhs) const {
281 return ipv4_socket_address == rhs.ipv4_socket_address &&
282 ipv6_socket_address == rhs.ipv6_socket_address &&
283 connection_id == rhs.connection_id &&
284 stateless_reset_token == rhs.stateless_reset_token;
285}
286
287bool TransportParameters::PreferredAddress::operator!=(
288 const PreferredAddress& rhs) const {
289 return !(*this == rhs);
290}
291
292std::ostream& operator<<(
293 std::ostream& os,
294 const TransportParameters::PreferredAddress& preferred_address) {
295 os << preferred_address.ToString();
296 return os;
297}
298
299std::string TransportParameters::PreferredAddress::ToString() const {
300 return "[" + ipv4_socket_address.ToString() + " " +
301 ipv6_socket_address.ToString() + " connection_id " +
302 connection_id.ToString() + " stateless_reset_token " +
303 absl::BytesToHexString(absl::string_view(
304 reinterpret_cast<const char*>(stateless_reset_token.data()),
305 stateless_reset_token.size())) +
306 "]";
307}
308
309TransportParameters::LegacyVersionInformation::LegacyVersionInformation()
310 : version(0) {}
311
312bool TransportParameters::LegacyVersionInformation::operator==(
313 const LegacyVersionInformation& rhs) const {
314 return version == rhs.version && supported_versions == rhs.supported_versions;
315}
316
317bool TransportParameters::LegacyVersionInformation::operator!=(
318 const LegacyVersionInformation& rhs) const {
319 return !(*this == rhs);
320}
321
322std::string TransportParameters::LegacyVersionInformation::ToString() const {
323 std::string rv =
324 absl::StrCat("legacy[version ", QuicVersionLabelToString(version));
325 if (!supported_versions.empty()) {
326 absl::StrAppend(&rv,
327 " supported_versions " +
328 QuicVersionLabelVectorToString(supported_versions));
329 }
330 absl::StrAppend(&rv, "]");
331 return rv;
332}
333
334std::ostream& operator<<(std::ostream& os,
335 const TransportParameters::LegacyVersionInformation&
336 legacy_version_information) {
337 os << legacy_version_information.ToString();
338 return os;
339}
340
341TransportParameters::VersionInformation::VersionInformation()
342 : chosen_version(0) {}
343
344bool TransportParameters::VersionInformation::operator==(
345 const VersionInformation& rhs) const {
346 return chosen_version == rhs.chosen_version &&
347 other_versions == rhs.other_versions;
348}
349
350bool TransportParameters::VersionInformation::operator!=(
351 const VersionInformation& rhs) const {
352 return !(*this == rhs);
353}
354
355std::string TransportParameters::VersionInformation::ToString() const {
356 std::string rv = absl::StrCat("[chosen_version ",
357 QuicVersionLabelToString(chosen_version));
358 if (!other_versions.empty()) {
359 absl::StrAppend(&rv, " other_versions " +
360 QuicVersionLabelVectorToString(other_versions));
361 }
362 absl::StrAppend(&rv, "]");
363 return rv;
364}
365
366std::ostream& operator<<(
367 std::ostream& os,
368 const TransportParameters::VersionInformation& version_information) {
369 os << version_information.ToString();
370 return os;
371}
372
373std::ostream& operator<<(std::ostream& os, const TransportParameters& params) {
374 os << params.ToString();
375 return os;
376}
377
378std::string TransportParameters::ToString() const {
379 std::string rv = "[";
380 if (perspective == Perspective::IS_SERVER) {
381 rv += "Server";
382 } else {
383 rv += "Client";
384 }
385 if (legacy_version_information.has_value()) {
386 rv += " " + legacy_version_information.value().ToString();
387 }
388 if (version_information.has_value()) {
389 rv += " " + version_information.value().ToString();
390 }
391 if (original_destination_connection_id.has_value()) {
392 rv += " " + TransportParameterIdToString(kOriginalDestinationConnectionId) +
393 " " + original_destination_connection_id.value().ToString();
394 }
395 rv += max_idle_timeout_ms.ToString(/*for_use_in_list=*/true);
396 if (!stateless_reset_token.empty()) {
397 rv += " " + TransportParameterIdToString(kStatelessResetToken) + " " +
398 absl::BytesToHexString(absl::string_view(
399 reinterpret_cast<const char*>(stateless_reset_token.data()),
400 stateless_reset_token.size()));
401 }
402 rv += max_udp_payload_size.ToString(/*for_use_in_list=*/true);
403 rv += initial_max_data.ToString(/*for_use_in_list=*/true);
404 rv += initial_max_stream_data_bidi_local.ToString(/*for_use_in_list=*/true);
405 rv += initial_max_stream_data_bidi_remote.ToString(/*for_use_in_list=*/true);
406 rv += initial_max_stream_data_uni.ToString(/*for_use_in_list=*/true);
407 rv += initial_max_streams_bidi.ToString(/*for_use_in_list=*/true);
408 rv += initial_max_streams_uni.ToString(/*for_use_in_list=*/true);
409 rv += ack_delay_exponent.ToString(/*for_use_in_list=*/true);
410 rv += max_ack_delay.ToString(/*for_use_in_list=*/true);
411 rv += min_ack_delay_us.ToString(/*for_use_in_list=*/true);
412 if (disable_active_migration) {
413 rv += " " + TransportParameterIdToString(kDisableActiveMigration);
414 }
415 if (preferred_address) {
416 rv += " " + TransportParameterIdToString(kPreferredAddress) + " " +
417 preferred_address->ToString();
418 }
419 rv += active_connection_id_limit.ToString(/*for_use_in_list=*/true);
420 if (initial_source_connection_id.has_value()) {
421 rv += " " + TransportParameterIdToString(kInitialSourceConnectionId) + " " +
422 initial_source_connection_id.value().ToString();
423 }
424 if (retry_source_connection_id.has_value()) {
425 rv += " " + TransportParameterIdToString(kRetrySourceConnectionId) + " " +
426 retry_source_connection_id.value().ToString();
427 }
428 rv += max_datagram_frame_size.ToString(/*for_use_in_list=*/true);
429 rv += initial_round_trip_time_us.ToString(/*for_use_in_list=*/true);
430 if (google_connection_options.has_value()) {
431 rv += " " + TransportParameterIdToString(kGoogleConnectionOptions) + " ";
432 bool first = true;
433 for (const QuicTag& connection_option : google_connection_options.value()) {
434 if (first) {
435 first = false;
436 } else {
437 rv += ",";
438 }
439 rv += QuicTagToString(connection_option);
440 }
441 }
442 for (const auto& kv : custom_parameters) {
443 absl::StrAppend(&rv, " 0x", absl::Hex(static_cast<uint32_t>(kv.first)),
444 "=");
445 static constexpr size_t kMaxPrintableLength = 32;
446 if (kv.second.length() <= kMaxPrintableLength) {
447 rv += absl::BytesToHexString(kv.second);
448 } else {
449 absl::string_view truncated(kv.second.data(), kMaxPrintableLength);
450 rv += absl::StrCat(absl::BytesToHexString(truncated), "...(length ",
451 kv.second.length(), ")");
452 }
453 }
454 rv += "]";
455 return rv;
456}
457
458TransportParameters::TransportParameters()
459 : max_idle_timeout_ms(kMaxIdleTimeout),
460 max_udp_payload_size(kMaxPacketSize, kDefaultMaxPacketSizeTransportParam,
461 kMinMaxPacketSizeTransportParam, kVarInt62MaxValue),
462 initial_max_data(kInitialMaxData),
463 initial_max_stream_data_bidi_local(kInitialMaxStreamDataBidiLocal),
464 initial_max_stream_data_bidi_remote(kInitialMaxStreamDataBidiRemote),
465 initial_max_stream_data_uni(kInitialMaxStreamDataUni),
466 initial_max_streams_bidi(kInitialMaxStreamsBidi),
467 initial_max_streams_uni(kInitialMaxStreamsUni),
468 ack_delay_exponent(kAckDelayExponent,
469 kDefaultAckDelayExponentTransportParam, 0,
470 kMaxAckDelayExponentTransportParam),
471 max_ack_delay(kMaxAckDelay, kDefaultMaxAckDelayTransportParam, 0,
472 kMaxMaxAckDelayTransportParam),
473 min_ack_delay_us(kMinAckDelay, 0, 0,
474 kMaxMaxAckDelayTransportParam * kNumMicrosPerMilli),
475 disable_active_migration(false),
476 active_connection_id_limit(kActiveConnectionIdLimit,
477 kDefaultActiveConnectionIdLimitTransportParam,
478 kMinActiveConnectionIdLimitTransportParam,
479 kVarInt62MaxValue),
480 max_datagram_frame_size(kMaxDatagramFrameSize),
481 initial_round_trip_time_us(kInitialRoundTripTime)
482// Important note: any new transport parameters must be added
483// to TransportParameters::AreValid, SerializeTransportParameters and
484// ParseTransportParameters, TransportParameters's custom copy constructor, the
485// operator==, and TransportParametersTest.Comparator.
486{}
487
488TransportParameters::TransportParameters(const TransportParameters& other)
489 : perspective(other.perspective),
490 legacy_version_information(other.legacy_version_information),
491 version_information(other.version_information),
492 original_destination_connection_id(
493 other.original_destination_connection_id),
494 max_idle_timeout_ms(other.max_idle_timeout_ms),
495 stateless_reset_token(other.stateless_reset_token),
496 max_udp_payload_size(other.max_udp_payload_size),
497 initial_max_data(other.initial_max_data),
498 initial_max_stream_data_bidi_local(
499 other.initial_max_stream_data_bidi_local),
500 initial_max_stream_data_bidi_remote(
501 other.initial_max_stream_data_bidi_remote),
502 initial_max_stream_data_uni(other.initial_max_stream_data_uni),
503 initial_max_streams_bidi(other.initial_max_streams_bidi),
504 initial_max_streams_uni(other.initial_max_streams_uni),
505 ack_delay_exponent(other.ack_delay_exponent),
506 max_ack_delay(other.max_ack_delay),
507 min_ack_delay_us(other.min_ack_delay_us),
508 disable_active_migration(other.disable_active_migration),
509 active_connection_id_limit(other.active_connection_id_limit),
510 initial_source_connection_id(other.initial_source_connection_id),
511 retry_source_connection_id(other.retry_source_connection_id),
512 max_datagram_frame_size(other.max_datagram_frame_size),
513 initial_round_trip_time_us(other.initial_round_trip_time_us),
514 google_connection_options(other.google_connection_options),
515 custom_parameters(other.custom_parameters) {
516 if (other.preferred_address) {
517 preferred_address = std::make_unique<TransportParameters::PreferredAddress>(
518 *other.preferred_address);
519 }
520}
521
522bool TransportParameters::operator==(const TransportParameters& rhs) const {
523 if (!(perspective == rhs.perspective &&
524 legacy_version_information == rhs.legacy_version_information &&
525 version_information == rhs.version_information &&
526 original_destination_connection_id ==
527 rhs.original_destination_connection_id &&
528 max_idle_timeout_ms.value() == rhs.max_idle_timeout_ms.value() &&
529 stateless_reset_token == rhs.stateless_reset_token &&
530 max_udp_payload_size.value() == rhs.max_udp_payload_size.value() &&
531 initial_max_data.value() == rhs.initial_max_data.value() &&
532 initial_max_stream_data_bidi_local.value() ==
533 rhs.initial_max_stream_data_bidi_local.value() &&
534 initial_max_stream_data_bidi_remote.value() ==
535 rhs.initial_max_stream_data_bidi_remote.value() &&
536 initial_max_stream_data_uni.value() ==
537 rhs.initial_max_stream_data_uni.value() &&
538 initial_max_streams_bidi.value() ==
539 rhs.initial_max_streams_bidi.value() &&
540 initial_max_streams_uni.value() ==
541 rhs.initial_max_streams_uni.value() &&
542 ack_delay_exponent.value() == rhs.ack_delay_exponent.value() &&
543 max_ack_delay.value() == rhs.max_ack_delay.value() &&
544 min_ack_delay_us.value() == rhs.min_ack_delay_us.value() &&
545 disable_active_migration == rhs.disable_active_migration &&
546 active_connection_id_limit.value() ==
547 rhs.active_connection_id_limit.value() &&
548 initial_source_connection_id == rhs.initial_source_connection_id &&
549 retry_source_connection_id == rhs.retry_source_connection_id &&
550 max_datagram_frame_size.value() ==
551 rhs.max_datagram_frame_size.value() &&
552 initial_round_trip_time_us.value() ==
553 rhs.initial_round_trip_time_us.value() &&
554 google_connection_options == rhs.google_connection_options &&
555 custom_parameters == rhs.custom_parameters)) {
556 return false;
557 }
558
559 if ((!preferred_address && rhs.preferred_address) ||
560 (preferred_address && !rhs.preferred_address)) {
561 return false;
562 }
563 if (preferred_address && rhs.preferred_address &&
564 *preferred_address != *rhs.preferred_address) {
565 return false;
566 }
567
568 return true;
569}
570
571bool TransportParameters::operator!=(const TransportParameters& rhs) const {
572 return !(*this == rhs);
573}
574
575bool TransportParameters::AreValid(std::string* error_details) const {
576 QUICHE_DCHECK(perspective == Perspective::IS_CLIENT ||
577 perspective == Perspective::IS_SERVER);
578 if (perspective == Perspective::IS_CLIENT && !stateless_reset_token.empty()) {
579 *error_details = "Client cannot send stateless reset token";
580 return false;
581 }
582 if (perspective == Perspective::IS_CLIENT &&
583 original_destination_connection_id.has_value()) {
584 *error_details = "Client cannot send original_destination_connection_id";
585 return false;
586 }
587 if (!stateless_reset_token.empty() &&
588 stateless_reset_token.size() != kStatelessResetTokenLength) {
589 *error_details = absl::StrCat("Stateless reset token has bad length ",
590 stateless_reset_token.size());
591 return false;
592 }
593 if (perspective == Perspective::IS_CLIENT && preferred_address) {
594 *error_details = "Client cannot send preferred address";
595 return false;
596 }
597 if (preferred_address && preferred_address->stateless_reset_token.size() !=
598 kStatelessResetTokenLength) {
599 *error_details =
600 absl::StrCat("Preferred address stateless reset token has bad length ",
601 preferred_address->stateless_reset_token.size());
602 return false;
603 }
604 if (preferred_address &&
605 (!preferred_address->ipv4_socket_address.host().IsIPv4() ||
606 !preferred_address->ipv6_socket_address.host().IsIPv6())) {
607 QUIC_BUG(quic_bug_10743_4) << "Preferred address family failure";
608 *error_details = "Internal preferred address family failure";
609 return false;
610 }
611 if (perspective == Perspective::IS_CLIENT &&
612 retry_source_connection_id.has_value()) {
613 *error_details = "Client cannot send retry_source_connection_id";
614 return false;
615 }
616 for (const auto& kv : custom_parameters) {
617 if (TransportParameterIdIsKnown(kv.first)) {
618 *error_details = absl::StrCat("Using custom_parameters with known ID ",
619 TransportParameterIdToString(kv.first),
620 " is not allowed");
621 return false;
622 }
623 }
624 if (perspective == Perspective::IS_SERVER &&
625 initial_round_trip_time_us.value() > 0) {
626 *error_details = "Server cannot send initial round trip time";
627 return false;
628 }
629 if (version_information.has_value()) {
630 const QuicVersionLabel& chosen_version =
631 version_information.value().chosen_version;
632 const QuicVersionLabelVector& other_versions =
633 version_information.value().other_versions;
634 if (chosen_version == 0) {
635 *error_details = "Invalid chosen version";
636 return false;
637 }
638 if (perspective == Perspective::IS_CLIENT &&
639 std::find(other_versions.begin(), other_versions.end(),
640 chosen_version) == other_versions.end()) {
641 // When sent by the client, chosen_version needs to be present in
642 // other_versions because other_versions lists the compatible versions and
643 // the chosen version is part of that list. When sent by the server,
644 // other_version contains the list of fully-deployed versions which is
645 // generally equal to the list of supported versions but can slightly
646 // differ during removal of versions across a server fleet. See
647 // draft-ietf-quic-version-negotiation for details.
648 *error_details = "Client chosen version not in other versions";
649 return false;
650 }
651 }
652 const bool ok =
653 max_idle_timeout_ms.IsValid() && max_udp_payload_size.IsValid() &&
654 initial_max_data.IsValid() &&
655 initial_max_stream_data_bidi_local.IsValid() &&
656 initial_max_stream_data_bidi_remote.IsValid() &&
657 initial_max_stream_data_uni.IsValid() &&
658 initial_max_streams_bidi.IsValid() && initial_max_streams_uni.IsValid() &&
659 ack_delay_exponent.IsValid() && max_ack_delay.IsValid() &&
660 min_ack_delay_us.IsValid() && active_connection_id_limit.IsValid() &&
661 max_datagram_frame_size.IsValid() && initial_round_trip_time_us.IsValid();
662 if (!ok) {
663 *error_details = "Invalid transport parameters " + this->ToString();
664 }
665 return ok;
666}
667
668TransportParameters::~TransportParameters() = default;
669
670bool SerializeTransportParameters(ParsedQuicVersion /*version*/,
671 const TransportParameters& in,
672 std::vector<uint8_t>* out) {
673 std::string error_details;
674 if (!in.AreValid(&error_details)) {
675 QUIC_BUG(invalid transport parameters)
676 << "Not serializing invalid transport parameters: " << error_details;
677 return false;
678 }
679 if (!in.legacy_version_information.has_value() ||
680 in.legacy_version_information.value().version == 0 ||
681 (in.perspective == Perspective::IS_SERVER &&
682 in.legacy_version_information.value().supported_versions.empty())) {
683 QUIC_BUG(missing versions) << "Refusing to serialize without versions";
684 return false;
685 }
686 TransportParameters::ParameterMap custom_parameters = in.custom_parameters;
687 for (const auto& kv : custom_parameters) {
688 if (kv.first % 31 == 27) {
689 // See the "Reserved Transport Parameters" section of RFC 9000.
690 QUIC_BUG(custom_parameters with GREASE)
691 << "Serializing custom_parameters with GREASE ID " << kv.first
692 << " is not allowed";
693 return false;
694 }
695 }
696
697 // Maximum length of the GREASE transport parameter (see below).
698 static constexpr size_t kMaxGreaseLength = 16;
699
700 // Empirically transport parameters generally fit within 128 bytes, but we
701 // need to allocate the size up front. Integer transport parameters
702 // have a maximum encoded length of 24 bytes (3 variable length integers),
703 // other transport parameters have a length of 16 + the maximum value length.
704 static constexpr size_t kTypeAndValueLength = 2 * sizeof(uint64_t);
705 static constexpr size_t kIntegerParameterLength =
706 kTypeAndValueLength + sizeof(uint64_t);
707 static constexpr size_t kStatelessResetParameterLength =
708 kTypeAndValueLength + 16 /* stateless reset token length */;
709 static constexpr size_t kConnectionIdParameterLength =
710 kTypeAndValueLength + 255 /* maximum connection ID length */;
711 static constexpr size_t kPreferredAddressParameterLength =
712 kTypeAndValueLength + 4 /*IPv4 address */ + 2 /* IPv4 port */ +
713 16 /* IPv6 address */ + 1 /* Connection ID length */ +
714 255 /* maximum connection ID length */ + 16 /* stateless reset token */;
715 static constexpr size_t kKnownTransportParamLength =
716 kConnectionIdParameterLength + // original_destination_connection_id
717 kIntegerParameterLength + // max_idle_timeout
718 kStatelessResetParameterLength + // stateless_reset_token
719 kIntegerParameterLength + // max_udp_payload_size
720 kIntegerParameterLength + // initial_max_data
721 kIntegerParameterLength + // initial_max_stream_data_bidi_local
722 kIntegerParameterLength + // initial_max_stream_data_bidi_remote
723 kIntegerParameterLength + // initial_max_stream_data_uni
724 kIntegerParameterLength + // initial_max_streams_bidi
725 kIntegerParameterLength + // initial_max_streams_uni
726 kIntegerParameterLength + // ack_delay_exponent
727 kIntegerParameterLength + // max_ack_delay
728 kIntegerParameterLength + // min_ack_delay_us
729 kTypeAndValueLength + // disable_active_migration
730 kPreferredAddressParameterLength + // preferred_address
731 kIntegerParameterLength + // active_connection_id_limit
732 kConnectionIdParameterLength + // initial_source_connection_id
733 kConnectionIdParameterLength + // retry_source_connection_id
734 kIntegerParameterLength + // max_datagram_frame_size
735 kIntegerParameterLength + // initial_round_trip_time_us
736 kTypeAndValueLength + // google_connection_options
737 kTypeAndValueLength; // google-version
738
739 std::vector<TransportParameters::TransportParameterId> parameter_ids = {
740 TransportParameters::kOriginalDestinationConnectionId,
741 TransportParameters::kMaxIdleTimeout,
742 TransportParameters::kStatelessResetToken,
743 TransportParameters::kMaxPacketSize,
744 TransportParameters::kInitialMaxData,
745 TransportParameters::kInitialMaxStreamDataBidiLocal,
746 TransportParameters::kInitialMaxStreamDataBidiRemote,
747 TransportParameters::kInitialMaxStreamDataUni,
748 TransportParameters::kInitialMaxStreamsBidi,
749 TransportParameters::kInitialMaxStreamsUni,
750 TransportParameters::kAckDelayExponent,
751 TransportParameters::kMaxAckDelay,
752 TransportParameters::kMinAckDelay,
753 TransportParameters::kActiveConnectionIdLimit,
754 TransportParameters::kMaxDatagramFrameSize,
755 TransportParameters::kInitialRoundTripTime,
756 TransportParameters::kDisableActiveMigration,
757 TransportParameters::kPreferredAddress,
758 TransportParameters::kInitialSourceConnectionId,
759 TransportParameters::kRetrySourceConnectionId,
760 TransportParameters::kGoogleConnectionOptions,
761 TransportParameters::kGoogleQuicVersion,
762 TransportParameters::kVersionInformation,
763 };
764
765 size_t max_transport_param_length = kKnownTransportParamLength;
766 // google_connection_options.
767 if (in.google_connection_options.has_value()) {
768 max_transport_param_length +=
769 in.google_connection_options.value().size() * sizeof(QuicTag);
770 }
771 // Google-specific version extension.
772 if (in.legacy_version_information.has_value()) {
773 max_transport_param_length +=
774 sizeof(in.legacy_version_information.value().version) +
775 1 /* versions length */ +
776 in.legacy_version_information.value().supported_versions.size() *
777 sizeof(QuicVersionLabel);
778 }
779 // version_information.
780 if (in.version_information.has_value()) {
781 max_transport_param_length +=
782 sizeof(in.version_information.value().chosen_version) +
783 // Add one for the added GREASE version.
784 (in.version_information.value().other_versions.size() + 1) *
785 sizeof(QuicVersionLabel);
786 }
787
788 // Add a random GREASE transport parameter, as defined in the
789 // "Reserved Transport Parameters" section of RFC 9000.
790 // This forces receivers to support unexpected input.
791 QuicRandom* random = QuicRandom::GetInstance();
792 // Transport parameter identifiers are 62 bits long so we need to
793 // ensure that the output of the computation below fits in 62 bits.
794 uint64_t grease_id64 = random->RandUint64() % ((1ULL << 62) - 31);
795 // Make sure grease_id % 31 == 27. Note that this is not uniformely
796 // distributed but is acceptable since no security depends on this
797 // randomness.
798 grease_id64 = (grease_id64 / 31) * 31 + 27;
799 TransportParameters::TransportParameterId grease_id =
800 static_cast<TransportParameters::TransportParameterId>(grease_id64);
801 const size_t grease_length = random->RandUint64() % kMaxGreaseLength;
802 QUICHE_DCHECK_GE(kMaxGreaseLength, grease_length);
803 char grease_contents[kMaxGreaseLength];
804 random->RandBytes(grease_contents, grease_length);
805 custom_parameters[grease_id] = std::string(grease_contents, grease_length);
806
807 // Custom parameters.
808 for (const auto& kv : custom_parameters) {
809 max_transport_param_length += kTypeAndValueLength + kv.second.length();
810 parameter_ids.push_back(kv.first);
811 }
812
813 // Randomize order of sent transport parameters by walking the array
814 // backwards and swapping each element with a random earlier one.
815 for (size_t i = parameter_ids.size() - 1; i > 0; i--) {
816 std::swap(parameter_ids[i],
817 parameter_ids[random->InsecureRandUint64() % (i + 1)]);
818 }
819
820 out->resize(max_transport_param_length);
821 QuicDataWriter writer(out->size(), reinterpret_cast<char*>(out->data()));
822
823 for (TransportParameters::TransportParameterId parameter_id : parameter_ids) {
824 switch (parameter_id) {
825 // original_destination_connection_id
826 case TransportParameters::kOriginalDestinationConnectionId: {
827 if (in.original_destination_connection_id.has_value()) {
828 QUICHE_DCHECK_EQ(Perspective::IS_SERVER, in.perspective);
829 QuicConnectionId original_destination_connection_id =
830 in.original_destination_connection_id.value();
831 if (!writer.WriteVarInt62(
832 TransportParameters::kOriginalDestinationConnectionId) ||
833 !writer.WriteStringPieceVarInt62(absl::string_view(
834 original_destination_connection_id.data(),
835 original_destination_connection_id.length()))) {
836 QUIC_BUG(Failed to write original_destination_connection_id)
837 << "Failed to write original_destination_connection_id "
838 << original_destination_connection_id << " for " << in;
839 return false;
840 }
841 }
842 } break;
843 // max_idle_timeout
844 case TransportParameters::kMaxIdleTimeout: {
845 if (!in.max_idle_timeout_ms.Write(&writer)) {
846 QUIC_BUG(Failed to write idle_timeout)
847 << "Failed to write idle_timeout for " << in;
848 return false;
849 }
850 } break;
851 // stateless_reset_token
852 case TransportParameters::kStatelessResetToken: {
853 if (!in.stateless_reset_token.empty()) {
854 QUICHE_DCHECK_EQ(kStatelessResetTokenLength,
855 in.stateless_reset_token.size());
856 QUICHE_DCHECK_EQ(Perspective::IS_SERVER, in.perspective);
857 if (!writer.WriteVarInt62(
858 TransportParameters::kStatelessResetToken) ||
859 !writer.WriteStringPieceVarInt62(
860 absl::string_view(reinterpret_cast<const char*>(
861 in.stateless_reset_token.data()),
862 in.stateless_reset_token.size()))) {
863 QUIC_BUG(Failed to write stateless_reset_token)
864 << "Failed to write stateless_reset_token of length "
865 << in.stateless_reset_token.size() << " for " << in;
866 return false;
867 }
868 }
869 } break;
870 // max_udp_payload_size
871 case TransportParameters::kMaxPacketSize: {
872 if (!in.max_udp_payload_size.Write(&writer)) {
873 QUIC_BUG(Failed to write max_udp_payload_size)
874 << "Failed to write max_udp_payload_size for " << in;
875 return false;
876 }
877 } break;
878 // initial_max_data
879 case TransportParameters::kInitialMaxData: {
880 if (!in.initial_max_data.Write(&writer)) {
881 QUIC_BUG(Failed to write initial_max_data)
882 << "Failed to write initial_max_data for " << in;
883 return false;
884 }
885 } break;
886 // initial_max_stream_data_bidi_local
887 case TransportParameters::kInitialMaxStreamDataBidiLocal: {
888 if (!in.initial_max_stream_data_bidi_local.Write(&writer)) {
889 QUIC_BUG(Failed to write initial_max_stream_data_bidi_local)
890 << "Failed to write initial_max_stream_data_bidi_local for "
891 << in;
892 return false;
893 }
894 } break;
895 // initial_max_stream_data_bidi_remote
896 case TransportParameters::kInitialMaxStreamDataBidiRemote: {
897 if (!in.initial_max_stream_data_bidi_remote.Write(&writer)) {
898 QUIC_BUG(Failed to write initial_max_stream_data_bidi_remote)
899 << "Failed to write initial_max_stream_data_bidi_remote for "
900 << in;
901 return false;
902 }
903 } break;
904 // initial_max_stream_data_uni
905 case TransportParameters::kInitialMaxStreamDataUni: {
906 if (!in.initial_max_stream_data_uni.Write(&writer)) {
907 QUIC_BUG(Failed to write initial_max_stream_data_uni)
908 << "Failed to write initial_max_stream_data_uni for " << in;
909 return false;
910 }
911 } break;
912 // initial_max_streams_bidi
913 case TransportParameters::kInitialMaxStreamsBidi: {
914 if (!in.initial_max_streams_bidi.Write(&writer)) {
915 QUIC_BUG(Failed to write initial_max_streams_bidi)
916 << "Failed to write initial_max_streams_bidi for " << in;
917 return false;
918 }
919 } break;
920 // initial_max_streams_uni
921 case TransportParameters::kInitialMaxStreamsUni: {
922 if (!in.initial_max_streams_uni.Write(&writer)) {
923 QUIC_BUG(Failed to write initial_max_streams_uni)
924 << "Failed to write initial_max_streams_uni for " << in;
925 return false;
926 }
927 } break;
928 // ack_delay_exponent
929 case TransportParameters::kAckDelayExponent: {
930 if (!in.ack_delay_exponent.Write(&writer)) {
931 QUIC_BUG(Failed to write ack_delay_exponent)
932 << "Failed to write ack_delay_exponent for " << in;
933 return false;
934 }
935 } break;
936 // max_ack_delay
937 case TransportParameters::kMaxAckDelay: {
938 if (!in.max_ack_delay.Write(&writer)) {
939 QUIC_BUG(Failed to write max_ack_delay)
940 << "Failed to write max_ack_delay for " << in;
941 return false;
942 }
943 } break;
944 // min_ack_delay_us
945 case TransportParameters::kMinAckDelay: {
946 if (!in.min_ack_delay_us.Write(&writer)) {
947 QUIC_BUG(Failed to write min_ack_delay_us)
948 << "Failed to write min_ack_delay_us for " << in;
949 return false;
950 }
951 } break;
952 // active_connection_id_limit
953 case TransportParameters::kActiveConnectionIdLimit: {
954 if (!in.active_connection_id_limit.Write(&writer)) {
955 QUIC_BUG(Failed to write active_connection_id_limit)
956 << "Failed to write active_connection_id_limit for " << in;
957 return false;
958 }
959 } break;
960 // max_datagram_frame_size
961 case TransportParameters::kMaxDatagramFrameSize: {
962 if (!in.max_datagram_frame_size.Write(&writer)) {
963 QUIC_BUG(Failed to write max_datagram_frame_size)
964 << "Failed to write max_datagram_frame_size for " << in;
965 return false;
966 }
967 } break;
968 // initial_round_trip_time_us
969 case TransportParameters::kInitialRoundTripTime: {
970 if (!in.initial_round_trip_time_us.Write(&writer)) {
971 QUIC_BUG(Failed to write initial_round_trip_time_us)
972 << "Failed to write initial_round_trip_time_us for " << in;
973 return false;
974 }
975 } break;
976 // disable_active_migration
977 case TransportParameters::kDisableActiveMigration: {
978 if (in.disable_active_migration) {
979 if (!writer.WriteVarInt62(
980 TransportParameters::kDisableActiveMigration) ||
981 !writer.WriteVarInt62(/* transport parameter length */ 0)) {
982 QUIC_BUG(Failed to write disable_active_migration)
983 << "Failed to write disable_active_migration for " << in;
984 return false;
985 }
986 }
987 } break;
988 // preferred_address
989 case TransportParameters::kPreferredAddress: {
990 if (in.preferred_address) {
991 std::string v4_address_bytes =
992 in.preferred_address->ipv4_socket_address.host().ToPackedString();
993 std::string v6_address_bytes =
994 in.preferred_address->ipv6_socket_address.host().ToPackedString();
995 if (v4_address_bytes.length() != 4 ||
996 v6_address_bytes.length() != 16 ||
997 in.preferred_address->stateless_reset_token.size() !=
998 kStatelessResetTokenLength) {
999 QUIC_BUG(quic_bug_10743_12)
1000 << "Bad lengths " << *in.preferred_address;
1001 return false;
1002 }
1003 const uint64_t preferred_address_length =
1004 v4_address_bytes.length() + /* IPv4 port */ sizeof(uint16_t) +
1005 v6_address_bytes.length() + /* IPv6 port */ sizeof(uint16_t) +
1006 /* connection ID length byte */ sizeof(uint8_t) +
1007 in.preferred_address->connection_id.length() +
1008 in.preferred_address->stateless_reset_token.size();
1009 if (!writer.WriteVarInt62(TransportParameters::kPreferredAddress) ||
1010 !writer.WriteVarInt62(
1011 /* transport parameter length */ preferred_address_length) ||
1012 !writer.WriteStringPiece(v4_address_bytes) ||
1013 !writer.WriteUInt16(
1014 in.preferred_address->ipv4_socket_address.port()) ||
1015 !writer.WriteStringPiece(v6_address_bytes) ||
1016 !writer.WriteUInt16(
1017 in.preferred_address->ipv6_socket_address.port()) ||
1018 !writer.WriteUInt8(
1019 in.preferred_address->connection_id.length()) ||
1020 !writer.WriteBytes(
1021 in.preferred_address->connection_id.data(),
1022 in.preferred_address->connection_id.length()) ||
1023 !writer.WriteBytes(
1024 in.preferred_address->stateless_reset_token.data(),
1025 in.preferred_address->stateless_reset_token.size())) {
1026 QUIC_BUG(Failed to write preferred_address)
1027 << "Failed to write preferred_address for " << in;
1028 return false;
1029 }
1030 }
1031 } break;
1032 // initial_source_connection_id
1033 case TransportParameters::kInitialSourceConnectionId: {
1034 if (in.initial_source_connection_id.has_value()) {
1035 QuicConnectionId initial_source_connection_id =
1036 in.initial_source_connection_id.value();
1037 if (!writer.WriteVarInt62(
1038 TransportParameters::kInitialSourceConnectionId) ||
1039 !writer.WriteStringPieceVarInt62(
1040 absl::string_view(initial_source_connection_id.data(),
1041 initial_source_connection_id.length()))) {
1042 QUIC_BUG(Failed to write initial_source_connection_id)
1043 << "Failed to write initial_source_connection_id "
1044 << initial_source_connection_id << " for " << in;
1045 return false;
1046 }
1047 }
1048 } break;
1049 // retry_source_connection_id
1050 case TransportParameters::kRetrySourceConnectionId: {
1051 if (in.retry_source_connection_id.has_value()) {
1052 QUICHE_DCHECK_EQ(Perspective::IS_SERVER, in.perspective);
1053 QuicConnectionId retry_source_connection_id =
1054 in.retry_source_connection_id.value();
1055 if (!writer.WriteVarInt62(
1056 TransportParameters::kRetrySourceConnectionId) ||
1057 !writer.WriteStringPieceVarInt62(
1058 absl::string_view(retry_source_connection_id.data(),
1059 retry_source_connection_id.length()))) {
1060 QUIC_BUG(Failed to write retry_source_connection_id)
1061 << "Failed to write retry_source_connection_id "
1062 << retry_source_connection_id << " for " << in;
1063 return false;
1064 }
1065 }
1066 } break;
1067 // Google-specific connection options.
1068 case TransportParameters::kGoogleConnectionOptions: {
1069 if (in.google_connection_options.has_value()) {
1070 static_assert(
1071 sizeof(in.google_connection_options.value().front()) == 4,
1072 "bad size");
1073 uint64_t connection_options_length =
1074 in.google_connection_options.value().size() * 4;
1075 if (!writer.WriteVarInt62(
1076 TransportParameters::kGoogleConnectionOptions) ||
1077 !writer.WriteVarInt62(
1078 /* transport parameter length */ connection_options_length)) {
1079 QUIC_BUG(Failed to write google_connection_options)
1080 << "Failed to write google_connection_options of length "
1081 << connection_options_length << " for " << in;
1082 return false;
1083 }
1084 for (const QuicTag& connection_option :
1085 in.google_connection_options.value()) {
1086 if (!writer.WriteTag(connection_option)) {
1087 QUIC_BUG(Failed to write google_connection_option)
1088 << "Failed to write google_connection_option "
1089 << QuicTagToString(connection_option) << " for " << in;
1090 return false;
1091 }
1092 }
1093 }
1094 } break;
1095 // Google-specific version extension.
1096 case TransportParameters::kGoogleQuicVersion: {
1097 if (!in.legacy_version_information.has_value()) {
1098 break;
1099 }
1100 static_assert(sizeof(QuicVersionLabel) == sizeof(uint32_t),
1101 "bad length");
1102 uint64_t google_version_length =
1103 sizeof(in.legacy_version_information.value().version);
1104 if (in.perspective == Perspective::IS_SERVER) {
1105 google_version_length +=
1106 /* versions length */ sizeof(uint8_t) +
1107 sizeof(QuicVersionLabel) * in.legacy_version_information.value()
1108 .supported_versions.size();
1109 }
1110 if (!writer.WriteVarInt62(TransportParameters::kGoogleQuicVersion) ||
1111 !writer.WriteVarInt62(
1112 /* transport parameter length */ google_version_length) ||
1113 !writer.WriteUInt32(
1114 in.legacy_version_information.value().version)) {
1115 QUIC_BUG(Failed to write Google version extension)
1116 << "Failed to write Google version extension for " << in;
1117 return false;
1118 }
1119 if (in.perspective == Perspective::IS_SERVER) {
1120 if (!writer.WriteUInt8(sizeof(QuicVersionLabel) *
1121 in.legacy_version_information.value()
1122 .supported_versions.size())) {
1123 QUIC_BUG(Failed to write versions length)
1124 << "Failed to write versions length for " << in;
1125 return false;
1126 }
1127 for (QuicVersionLabel version_label :
1128 in.legacy_version_information.value().supported_versions) {
1129 if (!writer.WriteUInt32(version_label)) {
1130 QUIC_BUG(Failed to write supported version)
1131 << "Failed to write supported version for " << in;
1132 return false;
1133 }
1134 }
1135 }
1136 } break;
1137 // version_information.
1138 case TransportParameters::kVersionInformation: {
1139 if (!in.version_information.has_value()) {
1140 break;
1141 }
1142 static_assert(sizeof(QuicVersionLabel) == sizeof(uint32_t),
1143 "bad length");
1144 QuicVersionLabelVector other_versions =
1145 in.version_information.value().other_versions;
1146 // Insert one GREASE version at a random index.
1147 const size_t grease_index =
1148 random->InsecureRandUint64() % (other_versions.size() + 1);
1149 other_versions.insert(
1150 other_versions.begin() + grease_index,
1151 CreateQuicVersionLabel(QuicVersionReservedForNegotiation()));
1152 const uint64_t version_information_length =
1153 sizeof(in.version_information.value().chosen_version) +
1154 sizeof(QuicVersionLabel) * other_versions.size();
1155 if (!writer.WriteVarInt62(TransportParameters::kVersionInformation) ||
1156 !writer.WriteVarInt62(
1157 /* transport parameter length */ version_information_length) ||
1158 !writer.WriteUInt32(
1159 in.version_information.value().chosen_version)) {
1160 QUIC_BUG(Failed to write chosen version)
1161 << "Failed to write chosen version for " << in;
1162 return false;
1163 }
1164 for (QuicVersionLabel version_label : other_versions) {
1165 if (!writer.WriteUInt32(version_label)) {
1166 QUIC_BUG(Failed to write other version)
1167 << "Failed to write other version for " << in;
1168 return false;
1169 }
1170 }
1171 } break;
1172 // Custom parameters and GREASE.
1173 default: {
1174 auto it = custom_parameters.find(parameter_id);
1175 if (it == custom_parameters.end()) {
1176 QUIC_BUG(Unknown parameter) << "Unknown parameter " << parameter_id;
1177 return false;
1178 }
1179 if (!writer.WriteVarInt62(parameter_id) ||
1180 !writer.WriteStringPieceVarInt62(it->second)) {
1181 QUIC_BUG(Failed to write custom parameter)
1182 << "Failed to write custom parameter " << parameter_id;
1183 return false;
1184 }
1185 } break;
1186 }
1187 }
1188
1189 out->resize(writer.length());
1190
1191 QUIC_DLOG(INFO) << "Serialized " << in << " as " << writer.length()
1192 << " bytes";
1193
1194 return true;
1195}
1196
1197bool ParseTransportParameters(ParsedQuicVersion version,
1198 Perspective perspective,
1199 const uint8_t* in,
1200 size_t in_len,
1201 TransportParameters* out,
1202 std::string* error_details) {
1203 out->perspective = perspective;
1204 QuicDataReader reader(reinterpret_cast<const char*>(in), in_len);
1205
1206 while (!reader.IsDoneReading()) {
1207 uint64_t param_id64;
1208 if (!reader.ReadVarInt62(&param_id64)) {
1209 *error_details = "Failed to parse transport parameter ID";
1210 return false;
1211 }
1212 TransportParameters::TransportParameterId param_id =
1213 static_cast<TransportParameters::TransportParameterId>(param_id64);
1214 absl::string_view value;
1215 if (!reader.ReadStringPieceVarInt62(&value)) {
1216 *error_details =
1217 "Failed to read length and value of transport parameter " +
1218 TransportParameterIdToString(param_id);
1219 return false;
1220 }
1221 QuicDataReader value_reader(value);
1222 bool parse_success = true;
1223 switch (param_id) {
1224 case TransportParameters::kOriginalDestinationConnectionId: {
1225 if (out->original_destination_connection_id.has_value()) {
1226 *error_details =
1227 "Received a second original_destination_connection_id";
1228 return false;
1229 }
1230 const size_t connection_id_length = value_reader.BytesRemaining();
1231 if (!QuicUtils::IsConnectionIdLengthValidForVersion(
1232 connection_id_length, version.transport_version)) {
1233 *error_details = absl::StrCat(
1234 "Received original_destination_connection_id of invalid length ",
1235 connection_id_length);
1236 return false;
1237 }
1238 QuicConnectionId original_destination_connection_id;
1239 if (!value_reader.ReadConnectionId(&original_destination_connection_id,
1240 connection_id_length)) {
1241 *error_details = "Failed to read original_destination_connection_id";
1242 return false;
1243 }
1244 out->original_destination_connection_id =
1245 original_destination_connection_id;
1246 } break;
1247 case TransportParameters::kMaxIdleTimeout:
1248 parse_success =
1249 out->max_idle_timeout_ms.Read(&value_reader, error_details);
1250 break;
1251 case TransportParameters::kStatelessResetToken: {
1252 if (!out->stateless_reset_token.empty()) {
1253 *error_details = "Received a second stateless_reset_token";
1254 return false;
1255 }
1256 absl::string_view stateless_reset_token =
1257 value_reader.ReadRemainingPayload();
1258 if (stateless_reset_token.length() != kStatelessResetTokenLength) {
1259 *error_details =
1260 absl::StrCat("Received stateless_reset_token of invalid length ",
1261 stateless_reset_token.length());
1262 return false;
1263 }
1264 out->stateless_reset_token.assign(
1265 stateless_reset_token.data(),
1266 stateless_reset_token.data() + stateless_reset_token.length());
1267 } break;
1268 case TransportParameters::kMaxPacketSize:
1269 parse_success =
1270 out->max_udp_payload_size.Read(&value_reader, error_details);
1271 break;
1272 case TransportParameters::kInitialMaxData:
1273 parse_success =
1274 out->initial_max_data.Read(&value_reader, error_details);
1275 break;
1276 case TransportParameters::kInitialMaxStreamDataBidiLocal:
1277 parse_success = out->initial_max_stream_data_bidi_local.Read(
1278 &value_reader, error_details);
1279 break;
1280 case TransportParameters::kInitialMaxStreamDataBidiRemote:
1281 parse_success = out->initial_max_stream_data_bidi_remote.Read(
1282 &value_reader, error_details);
1283 break;
1284 case TransportParameters::kInitialMaxStreamDataUni:
1285 parse_success =
1286 out->initial_max_stream_data_uni.Read(&value_reader, error_details);
1287 break;
1288 case TransportParameters::kInitialMaxStreamsBidi:
1289 parse_success =
1290 out->initial_max_streams_bidi.Read(&value_reader, error_details);
1291 break;
1292 case TransportParameters::kInitialMaxStreamsUni:
1293 parse_success =
1294 out->initial_max_streams_uni.Read(&value_reader, error_details);
1295 break;
1296 case TransportParameters::kAckDelayExponent:
1297 parse_success =
1298 out->ack_delay_exponent.Read(&value_reader, error_details);
1299 break;
1300 case TransportParameters::kMaxAckDelay:
1301 parse_success = out->max_ack_delay.Read(&value_reader, error_details);
1302 break;
1303 case TransportParameters::kDisableActiveMigration:
1304 if (out->disable_active_migration) {
1305 *error_details = "Received a second disable_active_migration";
1306 return false;
1307 }
1308 out->disable_active_migration = true;
1309 break;
1310 case TransportParameters::kPreferredAddress: {
1311 TransportParameters::PreferredAddress preferred_address;
1312 uint16_t ipv4_port, ipv6_port;
1313 in_addr ipv4_address;
1314 in6_addr ipv6_address;
1315 preferred_address.stateless_reset_token.resize(
1316 kStatelessResetTokenLength);
1317 if (!value_reader.ReadBytes(&ipv4_address, sizeof(ipv4_address)) ||
1318 !value_reader.ReadUInt16(&ipv4_port) ||
1319 !value_reader.ReadBytes(&ipv6_address, sizeof(ipv6_address)) ||
1320 !value_reader.ReadUInt16(&ipv6_port) ||
1321 !value_reader.ReadLengthPrefixedConnectionId(
1322 &preferred_address.connection_id) ||
1323 !value_reader.ReadBytes(&preferred_address.stateless_reset_token[0],
1324 kStatelessResetTokenLength)) {
1325 *error_details = "Failed to read preferred_address";
1326 return false;
1327 }
1328 preferred_address.ipv4_socket_address =
1329 QuicSocketAddress(QuicIpAddress(ipv4_address), ipv4_port);
1330 preferred_address.ipv6_socket_address =
1331 QuicSocketAddress(QuicIpAddress(ipv6_address), ipv6_port);
1332 if (!preferred_address.ipv4_socket_address.host().IsIPv4() ||
1333 !preferred_address.ipv6_socket_address.host().IsIPv6()) {
1334 *error_details = "Received preferred_address of bad families " +
1335 preferred_address.ToString();
1336 return false;
1337 }
1338 if (!QuicUtils::IsConnectionIdValidForVersion(
1339 preferred_address.connection_id, version.transport_version)) {
1340 *error_details = "Received invalid preferred_address connection ID " +
1341 preferred_address.ToString();
1342 return false;
1343 }
1344 out->preferred_address =
1345 std::make_unique<TransportParameters::PreferredAddress>(
1346 preferred_address);
1347 } break;
1348 case TransportParameters::kActiveConnectionIdLimit:
1349 parse_success =
1350 out->active_connection_id_limit.Read(&value_reader, error_details);
1351 break;
1352 case TransportParameters::kInitialSourceConnectionId: {
1353 if (out->initial_source_connection_id.has_value()) {
1354 *error_details = "Received a second initial_source_connection_id";
1355 return false;
1356 }
1357 const size_t connection_id_length = value_reader.BytesRemaining();
1358 if (!QuicUtils::IsConnectionIdLengthValidForVersion(
1359 connection_id_length, version.transport_version)) {
1360 *error_details = absl::StrCat(
1361 "Received initial_source_connection_id of invalid length ",
1362 connection_id_length);
1363 return false;
1364 }
1365 QuicConnectionId initial_source_connection_id;
1366 if (!value_reader.ReadConnectionId(&initial_source_connection_id,
1367 connection_id_length)) {
1368 *error_details = "Failed to read initial_source_connection_id";
1369 return false;
1370 }
1371 out->initial_source_connection_id = initial_source_connection_id;
1372 } break;
1373 case TransportParameters::kRetrySourceConnectionId: {
1374 if (out->retry_source_connection_id.has_value()) {
1375 *error_details = "Received a second retry_source_connection_id";
1376 return false;
1377 }
1378 const size_t connection_id_length = value_reader.BytesRemaining();
1379 if (!QuicUtils::IsConnectionIdLengthValidForVersion(
1380 connection_id_length, version.transport_version)) {
1381 *error_details = absl::StrCat(
1382 "Received retry_source_connection_id of invalid length ",
1383 connection_id_length);
1384 return false;
1385 }
1386 QuicConnectionId retry_source_connection_id;
1387 if (!value_reader.ReadConnectionId(&retry_source_connection_id,
1388 connection_id_length)) {
1389 *error_details = "Failed to read retry_source_connection_id";
1390 return false;
1391 }
1392 out->retry_source_connection_id = retry_source_connection_id;
1393 } break;
1394 case TransportParameters::kMaxDatagramFrameSize:
1395 parse_success =
1396 out->max_datagram_frame_size.Read(&value_reader, error_details);
1397 break;
1398 case TransportParameters::kInitialRoundTripTime:
1399 parse_success =
1400 out->initial_round_trip_time_us.Read(&value_reader, error_details);
1401 break;
1402 case TransportParameters::kGoogleConnectionOptions: {
1403 if (out->google_connection_options.has_value()) {
1404 *error_details = "Received a second google_connection_options";
1405 return false;
1406 }
1407 out->google_connection_options = QuicTagVector{};
1408 while (!value_reader.IsDoneReading()) {
1409 QuicTag connection_option;
1410 if (!value_reader.ReadTag(&connection_option)) {
1411 *error_details = "Failed to read a google_connection_options";
1412 return false;
1413 }
1414 out->google_connection_options.value().push_back(connection_option);
1415 }
1416 } break;
1417 case TransportParameters::kGoogleQuicVersion: {
1418 if (!out->legacy_version_information.has_value()) {
1419 out->legacy_version_information =
1420 TransportParameters::LegacyVersionInformation();
1421 }
1422 if (!value_reader.ReadUInt32(
1423 &out->legacy_version_information.value().version)) {
1424 *error_details = "Failed to read Google version extension version";
1425 return false;
1426 }
1427 if (perspective == Perspective::IS_SERVER) {
1428 uint8_t versions_length;
1429 if (!value_reader.ReadUInt8(&versions_length)) {
1430 *error_details = "Failed to parse Google supported versions length";
1431 return false;
1432 }
1433 const uint8_t num_versions = versions_length / sizeof(uint32_t);
1434 for (uint8_t i = 0; i < num_versions; ++i) {
1435 QuicVersionLabel version;
1436 if (!value_reader.ReadUInt32(&version)) {
1437 *error_details = "Failed to parse Google supported version";
1438 return false;
1439 }
1440 out->legacy_version_information.value()
1441 .supported_versions.push_back(version);
1442 }
1443 }
1444 } break;
1445 case TransportParameters::kVersionInformation: {
1446 if (out->version_information.has_value()) {
1447 *error_details = "Received a second version_information";
1448 return false;
1449 }
1450 out->version_information = TransportParameters::VersionInformation();
1451 if (!value_reader.ReadUInt32(
1452 &out->version_information.value().chosen_version)) {
1453 *error_details = "Failed to read chosen version";
1454 return false;
1455 }
1456 while (!value_reader.IsDoneReading()) {
1457 QuicVersionLabel other_version;
1458 if (!value_reader.ReadUInt32(&other_version)) {
1459 *error_details = "Failed to parse other version";
1460 return false;
1461 }
1462 out->version_information.value().other_versions.push_back(
1463 other_version);
1464 }
1465 } break;
1466 case TransportParameters::kMinAckDelay:
1467 parse_success =
1468 out->min_ack_delay_us.Read(&value_reader, error_details);
1469 break;
1470 default:
1471 if (out->custom_parameters.find(param_id) !=
1472 out->custom_parameters.end()) {
1473 *error_details = "Received a second unknown parameter" +
1474 TransportParameterIdToString(param_id);
1475 return false;
1476 }
1477 out->custom_parameters[param_id] =
1478 std::string(value_reader.ReadRemainingPayload());
1479 break;
1480 }
1481 if (!parse_success) {
1482 QUICHE_DCHECK(!error_details->empty());
1483 return false;
1484 }
1485 if (!value_reader.IsDoneReading()) {
1486 *error_details = absl::StrCat(
1487 "Received unexpected ", value_reader.BytesRemaining(),
1488 " bytes after parsing ", TransportParameterIdToString(param_id));
1489 return false;
1490 }
1491 }
1492
1493 if (!out->AreValid(error_details)) {
1494 QUICHE_DCHECK(!error_details->empty());
1495 return false;
1496 }
1497
1498 QUIC_DLOG(INFO) << "Parsed transport parameters " << *out << " from "
1499 << in_len << " bytes";
1500
1501 return true;
1502}
1503
1504namespace {
1505
1506bool DigestUpdateIntegerParam(
1507 EVP_MD_CTX* hash_ctx,
1508 const TransportParameters::IntegerParameter& param) {
1509 uint64_t value = param.value();
1510 return EVP_DigestUpdate(hash_ctx, &value, sizeof(value));
1511}
1512
1513} // namespace
1514
1515bool SerializeTransportParametersForTicket(
1516 const TransportParameters& in,
1517 const std::vector<uint8_t>& application_data,
1518 std::vector<uint8_t>* out) {
1519 std::string error_details;
1520 if (!in.AreValid(&error_details)) {
1521 QUIC_BUG(quic_bug_10743_26)
1522 << "Not serializing invalid transport parameters: " << error_details;
1523 return false;
1524 }
1525
1526 out->resize(SHA256_DIGEST_LENGTH + 1);
1527 const uint8_t serialization_version = 0;
1528 (*out)[0] = serialization_version;
1529
1530 bssl::ScopedEVP_MD_CTX hash_ctx;
1531 // Write application data:
1532 uint64_t app_data_len = application_data.size();
1533 const uint64_t parameter_version = 0;
1534 // The format of the input to the hash function is as follows:
1535 // - The application data, prefixed with a 64-bit length field.
1536 // - Transport parameters:
1537 // - A 64-bit version field indicating which version of encoding is used
1538 // for transport parameters.
1539 // - A list of 64-bit integers representing the relevant parameters.
1540 //
1541 // When changing which parameters are included, additional parameters can be
1542 // added to the end of the list without changing the version field. New
1543 // parameters that are variable length must be length prefixed. If
1544 // parameters are removed from the list, the version field must be
1545 // incremented.
1546 //
1547 // Integers happen to be written in host byte order, not network byte order.
1548 if (!EVP_DigestInit(hash_ctx.get(), EVP_sha256()) ||
1549 !EVP_DigestUpdate(hash_ctx.get(), &app_data_len, sizeof(app_data_len)) ||
1550 !EVP_DigestUpdate(hash_ctx.get(), application_data.data(),
1551 application_data.size()) ||
1552 !EVP_DigestUpdate(hash_ctx.get(), &parameter_version,
1553 sizeof(parameter_version))) {
1554 QUIC_BUG(quic_bug_10743_27)
1555 << "Unexpected failure of EVP_Digest functions when hashing "
1556 "Transport Parameters for ticket";
1557 return false;
1558 }
1559
1560 // Write transport parameters specified by draft-ietf-quic-transport-28,
1561 // section 7.4.1, that are remembered for 0-RTT.
1562 if (!DigestUpdateIntegerParam(hash_ctx.get(), in.initial_max_data) ||
1563 !DigestUpdateIntegerParam(hash_ctx.get(),
1564 in.initial_max_stream_data_bidi_local) ||
1565 !DigestUpdateIntegerParam(hash_ctx.get(),
1566 in.initial_max_stream_data_bidi_remote) ||
1567 !DigestUpdateIntegerParam(hash_ctx.get(),
1568 in.initial_max_stream_data_uni) ||
1569 !DigestUpdateIntegerParam(hash_ctx.get(), in.initial_max_streams_bidi) ||
1570 !DigestUpdateIntegerParam(hash_ctx.get(), in.initial_max_streams_uni) ||
1571 !DigestUpdateIntegerParam(hash_ctx.get(),
1572 in.active_connection_id_limit)) {
1573 QUIC_BUG(quic_bug_10743_28)
1574 << "Unexpected failure of EVP_Digest functions when hashing "
1575 "Transport Parameters for ticket";
1576 return false;
1577 }
1578 uint8_t disable_active_migration = in.disable_active_migration ? 1 : 0;
1579 if (!EVP_DigestUpdate(hash_ctx.get(), &disable_active_migration,
1580 sizeof(disable_active_migration)) ||
1581 !EVP_DigestFinal(hash_ctx.get(), out->data() + 1, nullptr)) {
1582 QUIC_BUG(quic_bug_10743_29)
1583 << "Unexpected failure of EVP_Digest functions when hashing "
1584 "Transport Parameters for ticket";
1585 return false;
1586 }
1587 return true;
1588}
1589
1590} // namespace quic