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->ToString();
388 }
389 if (version_information.has_value()) {
390 rv += " " + version_information->ToString();
391 }
392 if (original_destination_connection_id.has_value()) {
393 rv += " " + TransportParameterIdToString(kOriginalDestinationConnectionId) +
394 " " + original_destination_connection_id->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->ToString();
424 }
425 if (retry_source_connection_id.has_value()) {
426 rv += " " + TransportParameterIdToString(kRetrySourceConnectionId) + " " +
427 retry_source_connection_id->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->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) {
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->chosen_version;
646 const QuicVersionLabelVector& other_versions =
647 version_information->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->version == 0 ||
694 (in.perspective == Perspective::IS_SERVER &&
695 in.legacy_version_information->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->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->version) +
790 1 /* versions length */ +
791 in.legacy_version_information->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->chosen_version) +
798 // Add one for the added GREASE version.
799 (in.version_information->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->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;
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(*in.google_handshake_message)) {
993 QUIC_BUG(Failed to write google_handshake_message)
994 << "Failed to write google_handshake_message: "
995 << *in.google_handshake_message << " for " << in;
996 return false;
997 }
998 }
999 } break;
1000 // initial_round_trip_time_us
1001 case TransportParameters::kInitialRoundTripTime: {
1002 if (!in.initial_round_trip_time_us.Write(&writer)) {
1003 QUIC_BUG(Failed to write initial_round_trip_time_us)
1004 << "Failed to write initial_round_trip_time_us for " << in;
1005 return false;
1006 }
1007 } break;
1008 // disable_active_migration
1009 case TransportParameters::kDisableActiveMigration: {
1010 if (in.disable_active_migration) {
1011 if (!writer.WriteVarInt62(
1012 TransportParameters::kDisableActiveMigration) ||
1013 !writer.WriteVarInt62(/* transport parameter length */ 0)) {
1014 QUIC_BUG(Failed to write disable_active_migration)
1015 << "Failed to write disable_active_migration for " << in;
1016 return false;
1017 }
1018 }
1019 } break;
1020 // preferred_address
1021 case TransportParameters::kPreferredAddress: {
1022 if (in.preferred_address) {
1023 std::string v4_address_bytes =
1024 in.preferred_address->ipv4_socket_address.host().ToPackedString();
1025 std::string v6_address_bytes =
1026 in.preferred_address->ipv6_socket_address.host().ToPackedString();
1027 if (v4_address_bytes.length() != 4 ||
1028 v6_address_bytes.length() != 16 ||
1029 in.preferred_address->stateless_reset_token.size() !=
1030 kStatelessResetTokenLength) {
1031 QUIC_BUG(quic_bug_10743_12)
1032 << "Bad lengths " << *in.preferred_address;
1033 return false;
1034 }
1035 const uint64_t preferred_address_length =
1036 v4_address_bytes.length() + /* IPv4 port */ sizeof(uint16_t) +
1037 v6_address_bytes.length() + /* IPv6 port */ sizeof(uint16_t) +
1038 /* connection ID length byte */ sizeof(uint8_t) +
1039 in.preferred_address->connection_id.length() +
1040 in.preferred_address->stateless_reset_token.size();
1041 if (!writer.WriteVarInt62(TransportParameters::kPreferredAddress) ||
1042 !writer.WriteVarInt62(
1043 /* transport parameter length */ preferred_address_length) ||
1044 !writer.WriteStringPiece(v4_address_bytes) ||
1045 !writer.WriteUInt16(
1046 in.preferred_address->ipv4_socket_address.port()) ||
1047 !writer.WriteStringPiece(v6_address_bytes) ||
1048 !writer.WriteUInt16(
1049 in.preferred_address->ipv6_socket_address.port()) ||
1050 !writer.WriteUInt8(
1051 in.preferred_address->connection_id.length()) ||
1052 !writer.WriteBytes(
1053 in.preferred_address->connection_id.data(),
1054 in.preferred_address->connection_id.length()) ||
1055 !writer.WriteBytes(
1056 in.preferred_address->stateless_reset_token.data(),
1057 in.preferred_address->stateless_reset_token.size())) {
1058 QUIC_BUG(Failed to write preferred_address)
1059 << "Failed to write preferred_address for " << in;
1060 return false;
1061 }
1062 }
1063 } break;
1064 // initial_source_connection_id
1065 case TransportParameters::kInitialSourceConnectionId: {
1066 if (in.initial_source_connection_id.has_value()) {
1067 QuicConnectionId initial_source_connection_id =
1068 *in.initial_source_connection_id;
1069 if (!writer.WriteVarInt62(
1070 TransportParameters::kInitialSourceConnectionId) ||
1071 !writer.WriteStringPieceVarInt62(
1072 absl::string_view(initial_source_connection_id.data(),
1073 initial_source_connection_id.length()))) {
1074 QUIC_BUG(Failed to write initial_source_connection_id)
1075 << "Failed to write initial_source_connection_id "
1076 << initial_source_connection_id << " for " << in;
1077 return false;
1078 }
1079 }
1080 } break;
1081 // retry_source_connection_id
1082 case TransportParameters::kRetrySourceConnectionId: {
1083 if (in.retry_source_connection_id.has_value()) {
1084 QUICHE_DCHECK_EQ(Perspective::IS_SERVER, in.perspective);
1085 QuicConnectionId retry_source_connection_id =
1086 *in.retry_source_connection_id;
1087 if (!writer.WriteVarInt62(
1088 TransportParameters::kRetrySourceConnectionId) ||
1089 !writer.WriteStringPieceVarInt62(
1090 absl::string_view(retry_source_connection_id.data(),
1091 retry_source_connection_id.length()))) {
1092 QUIC_BUG(Failed to write retry_source_connection_id)
1093 << "Failed to write retry_source_connection_id "
1094 << retry_source_connection_id << " for " << in;
1095 return false;
1096 }
1097 }
1098 } break;
1099 // Google-specific connection options.
1100 case TransportParameters::kGoogleConnectionOptions: {
1101 if (in.google_connection_options.has_value()) {
1102 static_assert(sizeof(in.google_connection_options->front()) == 4,
1103 "bad size");
1104 uint64_t connection_options_length =
1105 in.google_connection_options->size() * 4;
1106 if (!writer.WriteVarInt62(
1107 TransportParameters::kGoogleConnectionOptions) ||
1108 !writer.WriteVarInt62(
1109 /* transport parameter length */ connection_options_length)) {
1110 QUIC_BUG(Failed to write google_connection_options)
1111 << "Failed to write google_connection_options of length "
1112 << connection_options_length << " for " << in;
1113 return false;
1114 }
1115 for (const QuicTag& connection_option :
1116 *in.google_connection_options) {
1117 if (!writer.WriteTag(connection_option)) {
1118 QUIC_BUG(Failed to write google_connection_option)
1119 << "Failed to write google_connection_option "
1120 << QuicTagToString(connection_option) << " for " << in;
1121 return false;
1122 }
1123 }
1124 }
1125 } break;
1126 // Google-specific version extension.
1127 case TransportParameters::kGoogleQuicVersion: {
1128 if (!in.legacy_version_information.has_value()) {
1129 break;
1130 }
1131 static_assert(sizeof(QuicVersionLabel) == sizeof(uint32_t),
1132 "bad length");
1133 uint64_t google_version_length =
1134 sizeof(in.legacy_version_information->version);
1135 if (in.perspective == Perspective::IS_SERVER) {
1136 google_version_length +=
1137 /* versions length */ sizeof(uint8_t) +
1138 sizeof(QuicVersionLabel) *
1139 in.legacy_version_information->supported_versions.size();
1140 }
1141 if (!writer.WriteVarInt62(TransportParameters::kGoogleQuicVersion) ||
1142 !writer.WriteVarInt62(
1143 /* transport parameter length */ google_version_length) ||
1144 !writer.WriteUInt32(in.legacy_version_information->version)) {
1145 QUIC_BUG(Failed to write Google version extension)
1146 << "Failed to write Google version extension for " << in;
1147 return false;
1148 }
1149 if (in.perspective == Perspective::IS_SERVER) {
1150 if (!writer.WriteUInt8(
1151 sizeof(QuicVersionLabel) *
1152 in.legacy_version_information->supported_versions.size())) {
1153 QUIC_BUG(Failed to write versions length)
1154 << "Failed to write versions length for " << in;
1155 return false;
1156 }
1157 for (QuicVersionLabel version_label :
1158 in.legacy_version_information->supported_versions) {
1159 if (!writer.WriteUInt32(version_label)) {
1160 QUIC_BUG(Failed to write supported version)
1161 << "Failed to write supported version for " << in;
1162 return false;
1163 }
1164 }
1165 }
1166 } break;
1167 // version_information.
1168 case TransportParameters::kVersionInformation: {
1169 if (!in.version_information.has_value()) {
1170 break;
1171 }
1172 static_assert(sizeof(QuicVersionLabel) == sizeof(uint32_t),
1173 "bad length");
1174 QuicVersionLabelVector other_versions =
1175 in.version_information->other_versions;
1176 // Insert one GREASE version at a random index.
1177 const size_t grease_index =
1178 random->InsecureRandUint64() % (other_versions.size() + 1);
1179 other_versions.insert(
1180 other_versions.begin() + grease_index,
1181 CreateQuicVersionLabel(QuicVersionReservedForNegotiation()));
1182 const uint64_t version_information_length =
1183 sizeof(in.version_information->chosen_version) +
1184 sizeof(QuicVersionLabel) * other_versions.size();
1185 if (!writer.WriteVarInt62(TransportParameters::kVersionInformation) ||
1186 !writer.WriteVarInt62(
1187 /* transport parameter length */ version_information_length) ||
1188 !writer.WriteUInt32(in.version_information->chosen_version)) {
1189 QUIC_BUG(Failed to write chosen version)
1190 << "Failed to write chosen version for " << in;
1191 return false;
1192 }
1193 for (QuicVersionLabel version_label : other_versions) {
1194 if (!writer.WriteUInt32(version_label)) {
1195 QUIC_BUG(Failed to write other version)
1196 << "Failed to write other version for " << in;
1197 return false;
1198 }
1199 }
1200 } break;
1201 // Custom parameters and GREASE.
1202 default: {
1203 auto it = custom_parameters.find(parameter_id);
1204 if (it == custom_parameters.end()) {
1205 QUIC_BUG(Unknown parameter) << "Unknown parameter " << parameter_id;
1206 return false;
1207 }
1208 if (!writer.WriteVarInt62(parameter_id) ||
1209 !writer.WriteStringPieceVarInt62(it->second)) {
1210 QUIC_BUG(Failed to write custom parameter)
1211 << "Failed to write custom parameter " << parameter_id;
1212 return false;
1213 }
1214 } break;
1215 }
1216 }
1217
1218 out->resize(writer.length());
1219
1220 QUIC_DLOG(INFO) << "Serialized " << in << " as " << writer.length()
1221 << " bytes";
1222
1223 return true;
1224 }
1225
ParseTransportParameters(ParsedQuicVersion version,Perspective perspective,const uint8_t * in,size_t in_len,TransportParameters * out,std::string * error_details)1226 bool ParseTransportParameters(ParsedQuicVersion version,
1227 Perspective perspective, const uint8_t* in,
1228 size_t in_len, TransportParameters* out,
1229 std::string* error_details) {
1230 out->perspective = perspective;
1231 QuicDataReader reader(reinterpret_cast<const char*>(in), in_len);
1232
1233 while (!reader.IsDoneReading()) {
1234 uint64_t param_id64;
1235 if (!reader.ReadVarInt62(¶m_id64)) {
1236 *error_details = "Failed to parse transport parameter ID";
1237 return false;
1238 }
1239 TransportParameters::TransportParameterId param_id =
1240 static_cast<TransportParameters::TransportParameterId>(param_id64);
1241 absl::string_view value;
1242 if (!reader.ReadStringPieceVarInt62(&value)) {
1243 *error_details =
1244 "Failed to read length and value of transport parameter " +
1245 TransportParameterIdToString(param_id);
1246 return false;
1247 }
1248 QuicDataReader value_reader(value);
1249 bool parse_success = true;
1250 switch (param_id) {
1251 case TransportParameters::kOriginalDestinationConnectionId: {
1252 if (out->original_destination_connection_id.has_value()) {
1253 *error_details =
1254 "Received a second original_destination_connection_id";
1255 return false;
1256 }
1257 const size_t connection_id_length = value_reader.BytesRemaining();
1258 if (!QuicUtils::IsConnectionIdLengthValidForVersion(
1259 connection_id_length, version.transport_version)) {
1260 *error_details = absl::StrCat(
1261 "Received original_destination_connection_id of invalid length ",
1262 connection_id_length);
1263 return false;
1264 }
1265 QuicConnectionId original_destination_connection_id;
1266 if (!value_reader.ReadConnectionId(&original_destination_connection_id,
1267 connection_id_length)) {
1268 *error_details = "Failed to read original_destination_connection_id";
1269 return false;
1270 }
1271 out->original_destination_connection_id =
1272 original_destination_connection_id;
1273 } break;
1274 case TransportParameters::kMaxIdleTimeout:
1275 parse_success =
1276 out->max_idle_timeout_ms.Read(&value_reader, error_details);
1277 break;
1278 case TransportParameters::kStatelessResetToken: {
1279 if (!out->stateless_reset_token.empty()) {
1280 *error_details = "Received a second stateless_reset_token";
1281 return false;
1282 }
1283 absl::string_view stateless_reset_token =
1284 value_reader.ReadRemainingPayload();
1285 if (stateless_reset_token.length() != kStatelessResetTokenLength) {
1286 *error_details =
1287 absl::StrCat("Received stateless_reset_token of invalid length ",
1288 stateless_reset_token.length());
1289 return false;
1290 }
1291 out->stateless_reset_token.assign(
1292 stateless_reset_token.data(),
1293 stateless_reset_token.data() + stateless_reset_token.length());
1294 } break;
1295 case TransportParameters::kMaxPacketSize:
1296 parse_success =
1297 out->max_udp_payload_size.Read(&value_reader, error_details);
1298 break;
1299 case TransportParameters::kInitialMaxData:
1300 parse_success =
1301 out->initial_max_data.Read(&value_reader, error_details);
1302 break;
1303 case TransportParameters::kInitialMaxStreamDataBidiLocal:
1304 parse_success = out->initial_max_stream_data_bidi_local.Read(
1305 &value_reader, error_details);
1306 break;
1307 case TransportParameters::kInitialMaxStreamDataBidiRemote:
1308 parse_success = out->initial_max_stream_data_bidi_remote.Read(
1309 &value_reader, error_details);
1310 break;
1311 case TransportParameters::kInitialMaxStreamDataUni:
1312 parse_success =
1313 out->initial_max_stream_data_uni.Read(&value_reader, error_details);
1314 break;
1315 case TransportParameters::kInitialMaxStreamsBidi:
1316 parse_success =
1317 out->initial_max_streams_bidi.Read(&value_reader, error_details);
1318 break;
1319 case TransportParameters::kInitialMaxStreamsUni:
1320 parse_success =
1321 out->initial_max_streams_uni.Read(&value_reader, error_details);
1322 break;
1323 case TransportParameters::kAckDelayExponent:
1324 parse_success =
1325 out->ack_delay_exponent.Read(&value_reader, error_details);
1326 break;
1327 case TransportParameters::kMaxAckDelay:
1328 parse_success = out->max_ack_delay.Read(&value_reader, error_details);
1329 break;
1330 case TransportParameters::kDisableActiveMigration:
1331 if (out->disable_active_migration) {
1332 *error_details = "Received a second disable_active_migration";
1333 return false;
1334 }
1335 out->disable_active_migration = true;
1336 break;
1337 case TransportParameters::kPreferredAddress: {
1338 TransportParameters::PreferredAddress preferred_address;
1339 uint16_t ipv4_port, ipv6_port;
1340 in_addr ipv4_address;
1341 in6_addr ipv6_address;
1342 preferred_address.stateless_reset_token.resize(
1343 kStatelessResetTokenLength);
1344 if (!value_reader.ReadBytes(&ipv4_address, sizeof(ipv4_address)) ||
1345 !value_reader.ReadUInt16(&ipv4_port) ||
1346 !value_reader.ReadBytes(&ipv6_address, sizeof(ipv6_address)) ||
1347 !value_reader.ReadUInt16(&ipv6_port) ||
1348 !value_reader.ReadLengthPrefixedConnectionId(
1349 &preferred_address.connection_id) ||
1350 !value_reader.ReadBytes(&preferred_address.stateless_reset_token[0],
1351 kStatelessResetTokenLength)) {
1352 *error_details = "Failed to read preferred_address";
1353 return false;
1354 }
1355 preferred_address.ipv4_socket_address =
1356 QuicSocketAddress(QuicIpAddress(ipv4_address), ipv4_port);
1357 preferred_address.ipv6_socket_address =
1358 QuicSocketAddress(QuicIpAddress(ipv6_address), ipv6_port);
1359 if (!preferred_address.ipv4_socket_address.host().IsIPv4() ||
1360 !preferred_address.ipv6_socket_address.host().IsIPv6()) {
1361 *error_details = "Received preferred_address of bad families " +
1362 preferred_address.ToString();
1363 return false;
1364 }
1365 if (!QuicUtils::IsConnectionIdValidForVersion(
1366 preferred_address.connection_id, version.transport_version)) {
1367 *error_details = "Received invalid preferred_address connection ID " +
1368 preferred_address.ToString();
1369 return false;
1370 }
1371 out->preferred_address =
1372 std::make_unique<TransportParameters::PreferredAddress>(
1373 preferred_address);
1374 } break;
1375 case TransportParameters::kActiveConnectionIdLimit:
1376 parse_success =
1377 out->active_connection_id_limit.Read(&value_reader, error_details);
1378 break;
1379 case TransportParameters::kInitialSourceConnectionId: {
1380 if (out->initial_source_connection_id.has_value()) {
1381 *error_details = "Received a second initial_source_connection_id";
1382 return false;
1383 }
1384 const size_t connection_id_length = value_reader.BytesRemaining();
1385 if (!QuicUtils::IsConnectionIdLengthValidForVersion(
1386 connection_id_length, version.transport_version)) {
1387 *error_details = absl::StrCat(
1388 "Received initial_source_connection_id of invalid length ",
1389 connection_id_length);
1390 return false;
1391 }
1392 QuicConnectionId initial_source_connection_id;
1393 if (!value_reader.ReadConnectionId(&initial_source_connection_id,
1394 connection_id_length)) {
1395 *error_details = "Failed to read initial_source_connection_id";
1396 return false;
1397 }
1398 out->initial_source_connection_id = initial_source_connection_id;
1399 } break;
1400 case TransportParameters::kRetrySourceConnectionId: {
1401 if (out->retry_source_connection_id.has_value()) {
1402 *error_details = "Received a second retry_source_connection_id";
1403 return false;
1404 }
1405 const size_t connection_id_length = value_reader.BytesRemaining();
1406 if (!QuicUtils::IsConnectionIdLengthValidForVersion(
1407 connection_id_length, version.transport_version)) {
1408 *error_details = absl::StrCat(
1409 "Received retry_source_connection_id of invalid length ",
1410 connection_id_length);
1411 return false;
1412 }
1413 QuicConnectionId retry_source_connection_id;
1414 if (!value_reader.ReadConnectionId(&retry_source_connection_id,
1415 connection_id_length)) {
1416 *error_details = "Failed to read retry_source_connection_id";
1417 return false;
1418 }
1419 out->retry_source_connection_id = retry_source_connection_id;
1420 } break;
1421 case TransportParameters::kMaxDatagramFrameSize:
1422 parse_success =
1423 out->max_datagram_frame_size.Read(&value_reader, error_details);
1424 break;
1425 case TransportParameters::kGoogleHandshakeMessage:
1426 if (out->google_handshake_message.has_value()) {
1427 *error_details = "Received a second google_handshake_message";
1428 return false;
1429 }
1430 out->google_handshake_message =
1431 std::string(value_reader.ReadRemainingPayload());
1432 break;
1433 case TransportParameters::kInitialRoundTripTime:
1434 parse_success =
1435 out->initial_round_trip_time_us.Read(&value_reader, error_details);
1436 break;
1437 case TransportParameters::kGoogleConnectionOptions: {
1438 if (out->google_connection_options.has_value()) {
1439 *error_details = "Received a second google_connection_options";
1440 return false;
1441 }
1442 out->google_connection_options = QuicTagVector{};
1443 while (!value_reader.IsDoneReading()) {
1444 QuicTag connection_option;
1445 if (!value_reader.ReadTag(&connection_option)) {
1446 *error_details = "Failed to read a google_connection_options";
1447 return false;
1448 }
1449 out->google_connection_options->push_back(connection_option);
1450 }
1451 } break;
1452 case TransportParameters::kGoogleQuicVersion: {
1453 if (!out->legacy_version_information.has_value()) {
1454 out->legacy_version_information =
1455 TransportParameters::LegacyVersionInformation();
1456 }
1457 if (!value_reader.ReadUInt32(
1458 &out->legacy_version_information->version)) {
1459 *error_details = "Failed to read Google version extension version";
1460 return false;
1461 }
1462 if (perspective == Perspective::IS_SERVER) {
1463 uint8_t versions_length;
1464 if (!value_reader.ReadUInt8(&versions_length)) {
1465 *error_details = "Failed to parse Google supported versions length";
1466 return false;
1467 }
1468 const uint8_t num_versions = versions_length / sizeof(uint32_t);
1469 for (uint8_t i = 0; i < num_versions; ++i) {
1470 QuicVersionLabel parsed_version;
1471 if (!value_reader.ReadUInt32(&parsed_version)) {
1472 *error_details = "Failed to parse Google supported version";
1473 return false;
1474 }
1475 out->legacy_version_information->supported_versions.push_back(
1476 parsed_version);
1477 }
1478 }
1479 } break;
1480 case TransportParameters::kVersionInformation: {
1481 if (out->version_information.has_value()) {
1482 *error_details = "Received a second version_information";
1483 return false;
1484 }
1485 out->version_information = TransportParameters::VersionInformation();
1486 if (!value_reader.ReadUInt32(
1487 &out->version_information->chosen_version)) {
1488 *error_details = "Failed to read chosen version";
1489 return false;
1490 }
1491 while (!value_reader.IsDoneReading()) {
1492 QuicVersionLabel other_version;
1493 if (!value_reader.ReadUInt32(&other_version)) {
1494 *error_details = "Failed to parse other version";
1495 return false;
1496 }
1497 out->version_information->other_versions.push_back(other_version);
1498 }
1499 } break;
1500 case TransportParameters::kMinAckDelay:
1501 parse_success =
1502 out->min_ack_delay_us.Read(&value_reader, error_details);
1503 break;
1504 default:
1505 if (out->custom_parameters.find(param_id) !=
1506 out->custom_parameters.end()) {
1507 *error_details = "Received a second unknown parameter" +
1508 TransportParameterIdToString(param_id);
1509 return false;
1510 }
1511 out->custom_parameters[param_id] =
1512 std::string(value_reader.ReadRemainingPayload());
1513 break;
1514 }
1515 if (!parse_success) {
1516 QUICHE_DCHECK(!error_details->empty());
1517 return false;
1518 }
1519 if (!value_reader.IsDoneReading()) {
1520 *error_details = absl::StrCat(
1521 "Received unexpected ", value_reader.BytesRemaining(),
1522 " bytes after parsing ", TransportParameterIdToString(param_id));
1523 return false;
1524 }
1525 }
1526
1527 if (!out->AreValid(error_details)) {
1528 QUICHE_DCHECK(!error_details->empty());
1529 return false;
1530 }
1531
1532 QUIC_DLOG(INFO) << "Parsed transport parameters " << *out << " from "
1533 << in_len << " bytes";
1534
1535 return true;
1536 }
1537
1538 namespace {
1539
DigestUpdateIntegerParam(EVP_MD_CTX * hash_ctx,const TransportParameters::IntegerParameter & param)1540 bool DigestUpdateIntegerParam(
1541 EVP_MD_CTX* hash_ctx, const TransportParameters::IntegerParameter& param) {
1542 uint64_t value = param.value();
1543 return EVP_DigestUpdate(hash_ctx, &value, sizeof(value));
1544 }
1545
1546 } // namespace
1547
SerializeTransportParametersForTicket(const TransportParameters & in,const std::vector<uint8_t> & application_data,std::vector<uint8_t> * out)1548 bool SerializeTransportParametersForTicket(
1549 const TransportParameters& in, const std::vector<uint8_t>& application_data,
1550 std::vector<uint8_t>* out) {
1551 std::string error_details;
1552 if (!in.AreValid(&error_details)) {
1553 QUIC_BUG(quic_bug_10743_26)
1554 << "Not serializing invalid transport parameters: " << error_details;
1555 return false;
1556 }
1557
1558 out->resize(SHA256_DIGEST_LENGTH + 1);
1559 const uint8_t serialization_version = 0;
1560 (*out)[0] = serialization_version;
1561
1562 bssl::ScopedEVP_MD_CTX hash_ctx;
1563 // Write application data:
1564 uint64_t app_data_len = application_data.size();
1565 const uint64_t parameter_version = 0;
1566 // The format of the input to the hash function is as follows:
1567 // - The application data, prefixed with a 64-bit length field.
1568 // - Transport parameters:
1569 // - A 64-bit version field indicating which version of encoding is used
1570 // for transport parameters.
1571 // - A list of 64-bit integers representing the relevant parameters.
1572 //
1573 // When changing which parameters are included, additional parameters can be
1574 // added to the end of the list without changing the version field. New
1575 // parameters that are variable length must be length prefixed. If
1576 // parameters are removed from the list, the version field must be
1577 // incremented.
1578 //
1579 // Integers happen to be written in host byte order, not network byte order.
1580 if (!EVP_DigestInit(hash_ctx.get(), EVP_sha256()) ||
1581 !EVP_DigestUpdate(hash_ctx.get(), &app_data_len, sizeof(app_data_len)) ||
1582 !EVP_DigestUpdate(hash_ctx.get(), application_data.data(),
1583 application_data.size()) ||
1584 !EVP_DigestUpdate(hash_ctx.get(), ¶meter_version,
1585 sizeof(parameter_version))) {
1586 QUIC_BUG(quic_bug_10743_27)
1587 << "Unexpected failure of EVP_Digest functions when hashing "
1588 "Transport Parameters for ticket";
1589 return false;
1590 }
1591
1592 // Write transport parameters specified by draft-ietf-quic-transport-28,
1593 // section 7.4.1, that are remembered for 0-RTT.
1594 if (!DigestUpdateIntegerParam(hash_ctx.get(), in.initial_max_data) ||
1595 !DigestUpdateIntegerParam(hash_ctx.get(),
1596 in.initial_max_stream_data_bidi_local) ||
1597 !DigestUpdateIntegerParam(hash_ctx.get(),
1598 in.initial_max_stream_data_bidi_remote) ||
1599 !DigestUpdateIntegerParam(hash_ctx.get(),
1600 in.initial_max_stream_data_uni) ||
1601 !DigestUpdateIntegerParam(hash_ctx.get(), in.initial_max_streams_bidi) ||
1602 !DigestUpdateIntegerParam(hash_ctx.get(), in.initial_max_streams_uni) ||
1603 !DigestUpdateIntegerParam(hash_ctx.get(),
1604 in.active_connection_id_limit)) {
1605 QUIC_BUG(quic_bug_10743_28)
1606 << "Unexpected failure of EVP_Digest functions when hashing "
1607 "Transport Parameters for ticket";
1608 return false;
1609 }
1610 uint8_t disable_active_migration = in.disable_active_migration ? 1 : 0;
1611 if (!EVP_DigestUpdate(hash_ctx.get(), &disable_active_migration,
1612 sizeof(disable_active_migration)) ||
1613 !EVP_DigestFinal(hash_ctx.get(), out->data() + 1, nullptr)) {
1614 QUIC_BUG(quic_bug_10743_29)
1615 << "Unexpected failure of EVP_Digest functions when hashing "
1616 "Transport Parameters for ticket";
1617 return false;
1618 }
1619 return true;
1620 }
1621
DegreaseTransportParameters(TransportParameters & parameters)1622 void DegreaseTransportParameters(TransportParameters& parameters) {
1623 // Strip GREASE from custom parameters.
1624 for (auto it = parameters.custom_parameters.begin();
1625 it != parameters.custom_parameters.end();
1626 /**/) {
1627 // See the "Reserved Transport Parameters" section of RFC 9000.
1628 if (it->first % 31 == 27) {
1629 parameters.custom_parameters.erase(it++);
1630 } else {
1631 ++it;
1632 }
1633 }
1634
1635 // Strip GREASE from versions.
1636 if (parameters.version_information.has_value()) {
1637 QuicVersionLabelVector clean_versions;
1638 for (QuicVersionLabel version :
1639 parameters.version_information->other_versions) {
1640 // See the "Versions" section of RFC 9000.
1641 if ((version & kReservedVersionMask) != kReservedVersionBits) {
1642 clean_versions.push_back(version);
1643 }
1644 }
1645
1646 parameters.version_information->other_versions = std::move(clean_versions);
1647 }
1648 }
1649
1650 } // namespace quic
1651