1 // Copyright (c) 2020 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 "net/third_party/quiche/src/quic/core/quic_legacy_version_encapsulator.h"
6 #include "net/third_party/quiche/src/quic/core/crypto/crypto_handshake_message.h"
7 #include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
8 #include "net/third_party/quiche/src/quic/core/quic_utils.h"
9 #include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
10 #include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
11
12 namespace quic {
13
QuicLegacyVersionEncapsulator(QuicPacketBuffer packet_buffer)14 QuicLegacyVersionEncapsulator::QuicLegacyVersionEncapsulator(
15 QuicPacketBuffer packet_buffer)
16 : packet_buffer_(packet_buffer) {}
17
~QuicLegacyVersionEncapsulator()18 QuicLegacyVersionEncapsulator::~QuicLegacyVersionEncapsulator() {}
19
20 // static
GetMinimumOverhead(absl::string_view sni)21 QuicByteCount QuicLegacyVersionEncapsulator::GetMinimumOverhead(
22 absl::string_view sni) {
23 // The number 52 is the sum of:
24 // - Flags (1 byte)
25 // - Server Connection ID (8 bytes)
26 // - Version (4 bytes)
27 // - Packet Number (1 byte)
28 // - Message Authentication Hash (12 bytes)
29 // - Frame Type (1 byte)
30 // - Stream ID (1 byte)
31 // - ClientHello tag (4 bytes)
32 // - ClientHello num tags (2 bytes)
33 // - Padding (2 bytes)
34 // - SNI tag (4 bytes)
35 // - SNI end offset (4 bytes)
36 // - QLVE tag (4 bytes)
37 // - QLVE end offset (4 bytes)
38 return 52 + sni.length();
39 }
40
GetPacketBuffer()41 QuicPacketBuffer QuicLegacyVersionEncapsulator::GetPacketBuffer() {
42 return packet_buffer_;
43 }
44
OnSerializedPacket(SerializedPacket serialized_packet)45 void QuicLegacyVersionEncapsulator::OnSerializedPacket(
46 SerializedPacket serialized_packet) {
47 if (encrypted_length_ != 0) {
48 unrecoverable_failure_encountered_ = true;
49 QUIC_BUG << "OnSerializedPacket called twice";
50 return;
51 }
52 if (serialized_packet.encrypted_length == 0) {
53 unrecoverable_failure_encountered_ = true;
54 QUIC_BUG << "OnSerializedPacket called with empty packet";
55 return;
56 }
57 encrypted_length_ = serialized_packet.encrypted_length;
58 }
59
OnUnrecoverableError(QuicErrorCode error,const std::string & error_details)60 void QuicLegacyVersionEncapsulator::OnUnrecoverableError(
61 QuicErrorCode error,
62 const std::string& error_details) {
63 unrecoverable_failure_encountered_ = true;
64 QUIC_BUG << "QuicLegacyVersionEncapsulator received error " << error << ": "
65 << error_details;
66 }
67
ShouldGeneratePacket(HasRetransmittableData,IsHandshake)68 bool QuicLegacyVersionEncapsulator::ShouldGeneratePacket(
69 HasRetransmittableData /*retransmittable*/,
70 IsHandshake /*handshake*/) {
71 return true;
72 }
73
74 const QuicFrames
MaybeBundleAckOpportunistically()75 QuicLegacyVersionEncapsulator::MaybeBundleAckOpportunistically() {
76 // We do not want to ever include any ACKs here, return an empty array.
77 return QuicFrames();
78 }
79
GetSerializedPacketFate(bool,EncryptionLevel)80 SerializedPacketFate QuicLegacyVersionEncapsulator::GetSerializedPacketFate(
81 bool /*is_mtu_discovery*/,
82 EncryptionLevel /*encryption_level*/) {
83 return SEND_TO_WRITER;
84 }
85
86 // static
Encapsulate(absl::string_view sni,absl::string_view inner_packet,const QuicConnectionId & server_connection_id,QuicTime creation_time,QuicByteCount outer_max_packet_length,char * out)87 QuicPacketLength QuicLegacyVersionEncapsulator::Encapsulate(
88 absl::string_view sni,
89 absl::string_view inner_packet,
90 const QuicConnectionId& server_connection_id,
91 QuicTime creation_time,
92 QuicByteCount outer_max_packet_length,
93 char* out) {
94 if (outer_max_packet_length > kMaxOutgoingPacketSize) {
95 outer_max_packet_length = kMaxOutgoingPacketSize;
96 }
97 CryptoHandshakeMessage outer_chlo;
98 outer_chlo.set_tag(kCHLO);
99 outer_chlo.SetStringPiece(kSNI, sni);
100 outer_chlo.SetStringPiece(kQLVE, inner_packet);
101 const QuicData& serialized_outer_chlo = outer_chlo.GetSerialized();
102 DCHECK(!LegacyVersionForEncapsulation().UsesCryptoFrames());
103 DCHECK(LegacyVersionForEncapsulation().UsesQuicCrypto());
104 QuicStreamFrame outer_stream_frame(
105 QuicUtils::GetCryptoStreamId(
106 LegacyVersionForEncapsulation().transport_version),
107 /*fin=*/false,
108 /*offset=*/0, serialized_outer_chlo.AsStringPiece());
109 QuicFramer outer_framer(
110 ParsedQuicVersionVector{LegacyVersionForEncapsulation()}, creation_time,
111 Perspective::IS_CLIENT, kQuicDefaultConnectionIdLength);
112 outer_framer.SetInitialObfuscators(server_connection_id);
113 char outer_encrypted_packet[kMaxOutgoingPacketSize];
114 QuicPacketBuffer outer_packet_buffer(outer_encrypted_packet, nullptr);
115 QuicLegacyVersionEncapsulator creator_delegate(outer_packet_buffer);
116 QuicPacketCreator outer_creator(server_connection_id, &outer_framer,
117 &creator_delegate);
118 outer_creator.SetMaxPacketLength(outer_max_packet_length);
119 outer_creator.set_encryption_level(ENCRYPTION_INITIAL);
120 outer_creator.SetTransmissionType(NOT_RETRANSMISSION);
121 if (!outer_creator.AddPaddedSavedFrame(QuicFrame(outer_stream_frame),
122 NOT_RETRANSMISSION)) {
123 QUIC_BUG << "Failed to add Legacy Version Encapsulation stream frame "
124 "(max packet length is "
125 << outer_creator.max_packet_length() << ") " << outer_stream_frame;
126 return 0;
127 }
128 outer_creator.FlushCurrentPacket();
129 const QuicPacketLength encrypted_length = creator_delegate.encrypted_length_;
130 if (creator_delegate.unrecoverable_failure_encountered_ ||
131 encrypted_length == 0) {
132 QUIC_BUG << "Failed to perform Legacy Version Encapsulation of "
133 << inner_packet.length() << " bytes";
134 return 0;
135 }
136 if (encrypted_length > kMaxOutgoingPacketSize) {
137 QUIC_BUG << "Legacy Version Encapsulation outer creator generated a "
138 "packet with unexpected length "
139 << encrypted_length;
140 return 0;
141 }
142
143 QUIC_DLOG(INFO) << "Successfully performed Legacy Version Encapsulation from "
144 << inner_packet.length() << " bytes to " << encrypted_length;
145
146 // Replace our current packet with the encapsulated one.
147 memcpy(out, outer_encrypted_packet, encrypted_length);
148 return encrypted_length;
149 }
150
151 } // namespace quic
152