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