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