blob: a38cb820bcdd0e38ff23ef14b67fe691057f62f1 [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// Copyright (c) 2012 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_crypto_stream.h"
6
vasilvv872e7a32019-03-12 16:42:44 -07007#include <string>
8
QUICHE teama6ef0a62019-03-07 20:34:33 -05009#include "net/third_party/quiche/src/quic/core/crypto/crypto_handshake.h"
10#include "net/third_party/quiche/src/quic/core/crypto/crypto_utils.h"
11#include "net/third_party/quiche/src/quic/core/quic_connection.h"
12#include "net/third_party/quiche/src/quic/core/quic_session.h"
13#include "net/third_party/quiche/src/quic/core/quic_utils.h"
14#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
15#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
16#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050017#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
18
19namespace quic {
20
21#define ENDPOINT \
22 (session()->perspective() == Perspective::IS_SERVER ? "Server: " \
23 : "Client:" \
24 " ")
25
26QuicCryptoStream::QuicCryptoStream(QuicSession* session)
nharper46833c32019-05-15 21:33:05 -070027 : QuicStream(QuicVersionUsesCryptoFrames(
28 session->connection()->transport_version())
29 ? QuicUtils::GetInvalidStreamId(
30 session->connection()->transport_version())
31 : QuicUtils::GetCryptoStreamId(
32 session->connection()->transport_version()),
QUICHE teama6ef0a62019-03-07 20:34:33 -050033 session,
34 /*is_static=*/true,
nharperd5c4a932019-05-13 13:58:49 -070035 QuicVersionUsesCryptoFrames(
36 session->connection()->transport_version())
37 ? CRYPTO
38 : BIDIRECTIONAL),
QUICHE team6987b4a2019-03-15 16:23:04 -070039 substreams_{{this, ENCRYPTION_INITIAL},
QUICHE team88ea0082019-03-15 10:05:26 -070040 {this, ENCRYPTION_HANDSHAKE},
QUICHE teama6ef0a62019-03-07 20:34:33 -050041 {this, ENCRYPTION_ZERO_RTT},
42 {this, ENCRYPTION_FORWARD_SECURE}} {
43 // The crypto stream is exempt from connection level flow control.
44 DisableConnectionFlowControlForThisStream();
45}
46
47QuicCryptoStream::~QuicCryptoStream() {}
48
49// static
50QuicByteCount QuicCryptoStream::CryptoMessageFramingOverhead(
51 QuicTransportVersion version,
52 QuicConnectionId connection_id) {
53 DCHECK(QuicUtils::IsConnectionIdValidForVersion(connection_id, version));
54 return QuicPacketCreator::StreamFramePacketOverhead(
55 version, static_cast<QuicConnectionIdLength>(connection_id.length()),
56 PACKET_0BYTE_CONNECTION_ID,
57 /*include_version=*/true,
58 /*include_diversification_nonce=*/true,
fayangd4291e42019-05-30 10:31:21 -070059 VersionHasIetfInvariantHeader(version) ? PACKET_4BYTE_PACKET_NUMBER
60 : PACKET_1BYTE_PACKET_NUMBER,
QUICHE teama6ef0a62019-03-07 20:34:33 -050061 VARIABLE_LENGTH_INTEGER_LENGTH_1, VARIABLE_LENGTH_INTEGER_LENGTH_2,
62 /*offset=*/0);
63}
64
65void QuicCryptoStream::OnCryptoFrame(const QuicCryptoFrame& frame) {
QUICHE teamea740082019-03-11 17:58:43 -070066 QUIC_BUG_IF(!QuicVersionUsesCryptoFrames(
67 session()->connection()->transport_version()))
QUICHE teama6ef0a62019-03-07 20:34:33 -050068 << "Versions less than 47 shouldn't receive CRYPTO frames";
69 EncryptionLevel level = session()->connection()->last_decrypted_level();
70 substreams_[level].sequencer.OnCryptoFrame(frame);
71}
72
73void QuicCryptoStream::OnStreamFrame(const QuicStreamFrame& frame) {
QUICHE teamea740082019-03-11 17:58:43 -070074 if (QuicVersionUsesCryptoFrames(
75 session()->connection()->transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -050076 QUIC_PEER_BUG
77 << "Crypto data received in stream frame instead of crypto frame";
78 CloseConnectionWithDetails(QUIC_INVALID_STREAM_DATA,
79 "Unexpected stream frame");
80 }
81 QuicStream::OnStreamFrame(frame);
82}
83
84void QuicCryptoStream::OnDataAvailable() {
85 EncryptionLevel level = session()->connection()->last_decrypted_level();
QUICHE teamea740082019-03-11 17:58:43 -070086 if (!QuicVersionUsesCryptoFrames(
87 session()->connection()->transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -050088 // Versions less than 47 only support QUIC crypto, which ignores the
89 // EncryptionLevel passed into CryptoMessageParser::ProcessInput (and
90 // OnDataAvailableInSequencer).
91 OnDataAvailableInSequencer(sequencer(), level);
92 return;
93 }
94 OnDataAvailableInSequencer(&substreams_[level].sequencer, level);
95}
96
97void QuicCryptoStream::OnDataAvailableInSequencer(
98 QuicStreamSequencer* sequencer,
99 EncryptionLevel level) {
100 struct iovec iov;
101 while (sequencer->GetReadableRegion(&iov)) {
102 QuicStringPiece data(static_cast<char*>(iov.iov_base), iov.iov_len);
103 if (!crypto_message_parser()->ProcessInput(data, level)) {
104 CloseConnectionWithDetails(crypto_message_parser()->error(),
105 crypto_message_parser()->error_detail());
106 return;
107 }
108 sequencer->MarkConsumed(iov.iov_len);
109 if (handshake_confirmed() &&
110 crypto_message_parser()->InputBytesRemaining() == 0) {
111 // If the handshake is complete and the current message has been fully
112 // processed then no more handshake messages are likely to arrive soon
113 // so release the memory in the stream sequencer.
114 sequencer->ReleaseBufferIfEmpty();
115 }
116 }
117}
118
119bool QuicCryptoStream::ExportKeyingMaterial(QuicStringPiece label,
120 QuicStringPiece context,
121 size_t result_len,
vasilvvc48c8712019-03-11 13:38:16 -0700122 std::string* result) const {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500123 if (!handshake_confirmed()) {
124 QUIC_DLOG(ERROR) << "ExportKeyingMaterial was called before forward-secure"
125 << "encryption was established.";
126 return false;
127 }
128 return CryptoUtils::ExportKeyingMaterial(
129 crypto_negotiated_params().subkey_secret, label, context, result_len,
130 result);
131}
132
133void QuicCryptoStream::WriteCryptoData(EncryptionLevel level,
134 QuicStringPiece data) {
QUICHE teamea740082019-03-11 17:58:43 -0700135 if (!QuicVersionUsesCryptoFrames(
136 session()->connection()->transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500137 // The QUIC crypto handshake takes care of setting the appropriate
138 // encryption level before writing data. Since that is the only handshake
139 // supported in versions less than 47, |level| can be ignored here.
140 WriteOrBufferData(data, /* fin */ false, /* ack_listener */ nullptr);
141 return;
142 }
143 if (data.empty()) {
144 QUIC_BUG << "Empty crypto data being written";
145 return;
146 }
147 // Append |data| to the send buffer for this encryption level.
148 struct iovec iov(QuicUtils::MakeIovec(data));
149 QuicStreamSendBuffer* send_buffer = &substreams_[level].send_buffer;
150 QuicStreamOffset offset = send_buffer->stream_offset();
151 send_buffer->SaveStreamData(&iov, /*iov_count=*/1, /*iov_offset=*/0,
152 data.length());
153 if (kMaxStreamLength - offset < data.length()) {
154 QUIC_BUG << "Writing too much crypto handshake data";
155 // TODO(nharper): Switch this to an IETF QUIC error code, possibly
156 // INTERNAL_ERROR?
157 CloseConnectionWithDetails(QUIC_STREAM_LENGTH_OVERFLOW,
158 "Writing too much crypto handshake data");
159 }
160
161 EncryptionLevel current_level = session()->connection()->encryption_level();
162 session()->connection()->SetDefaultEncryptionLevel(level);
163 size_t bytes_consumed =
164 session()->connection()->SendCryptoData(level, data.length(), offset);
165 session()->connection()->SetDefaultEncryptionLevel(current_level);
nharper46833c32019-05-15 21:33:05 -0700166 // Since CRYPTO frames aren't flow controlled, SendCryptoData should have sent
167 // all data we asked it to send.
168 DCHECK_EQ(bytes_consumed, data.length());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500169
170 send_buffer->OnStreamDataConsumed(bytes_consumed);
171}
172
173void QuicCryptoStream::OnSuccessfulVersionNegotiation(
174 const ParsedQuicVersion& version) {}
175
176bool QuicCryptoStream::OnCryptoFrameAcked(const QuicCryptoFrame& frame,
177 QuicTime::Delta ack_delay_time) {
178 QuicByteCount newly_acked_length = 0;
179 if (!substreams_[frame.level].send_buffer.OnStreamDataAcked(
180 frame.offset, frame.data_length, &newly_acked_length)) {
181 CloseConnectionWithDetails(QUIC_INTERNAL_ERROR,
182 "Trying to ack unsent crypto data.");
183 return false;
184 }
185 return newly_acked_length > 0;
186}
187
188void QuicCryptoStream::NeuterUnencryptedStreamData() {
QUICHE teamea740082019-03-11 17:58:43 -0700189 if (!QuicVersionUsesCryptoFrames(
190 session()->connection()->transport_version())) {
QUICHE team6987b4a2019-03-15 16:23:04 -0700191 for (const auto& interval : bytes_consumed_[ENCRYPTION_INITIAL]) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500192 QuicByteCount newly_acked_length = 0;
193 send_buffer().OnStreamDataAcked(
194 interval.min(), interval.max() - interval.min(), &newly_acked_length);
195 }
196 return;
197 }
QUICHE team6987b4a2019-03-15 16:23:04 -0700198 QuicStreamSendBuffer* send_buffer =
199 &substreams_[ENCRYPTION_INITIAL].send_buffer;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500200 // TODO(nharper): Consider adding a Clear() method to QuicStreamSendBuffer to
201 // replace the following code.
202 QuicIntervalSet<QuicStreamOffset> to_ack = send_buffer->bytes_acked();
203 to_ack.Complement(0, send_buffer->stream_offset());
204 for (const auto& interval : to_ack) {
205 QuicByteCount newly_acked_length = 0;
206 send_buffer->OnStreamDataAcked(
207 interval.min(), interval.max() - interval.min(), &newly_acked_length);
208 }
209}
210
211void QuicCryptoStream::OnStreamDataConsumed(size_t bytes_consumed) {
QUICHE teamea740082019-03-11 17:58:43 -0700212 if (QuicVersionUsesCryptoFrames(
213 session()->connection()->transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500214 QUIC_BUG << "Stream data consumed when CRYPTO frames should be in use";
215 }
216 if (bytes_consumed > 0) {
217 bytes_consumed_[session()->connection()->encryption_level()].Add(
218 stream_bytes_written(), stream_bytes_written() + bytes_consumed);
219 }
220 QuicStream::OnStreamDataConsumed(bytes_consumed);
221}
222
nharper46833c32019-05-15 21:33:05 -0700223bool QuicCryptoStream::HasPendingCryptoRetransmission() const {
QUICHE teamea740082019-03-11 17:58:43 -0700224 if (!QuicVersionUsesCryptoFrames(
225 session()->connection()->transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500226 return false;
227 }
228 for (EncryptionLevel level :
QUICHE team6987b4a2019-03-15 16:23:04 -0700229 {ENCRYPTION_INITIAL, ENCRYPTION_ZERO_RTT, ENCRYPTION_FORWARD_SECURE}) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500230 if (substreams_[level].send_buffer.HasPendingRetransmission()) {
231 return true;
232 }
233 }
234 return false;
235}
236
237void QuicCryptoStream::WritePendingCryptoRetransmission() {
QUICHE teamea740082019-03-11 17:58:43 -0700238 QUIC_BUG_IF(!QuicVersionUsesCryptoFrames(
239 session()->connection()->transport_version()))
QUICHE teama6ef0a62019-03-07 20:34:33 -0500240 << "Versions less than 47 don't write CRYPTO frames";
241 EncryptionLevel current_encryption_level =
242 session()->connection()->encryption_level();
243 for (EncryptionLevel level :
QUICHE team6987b4a2019-03-15 16:23:04 -0700244 {ENCRYPTION_INITIAL, ENCRYPTION_ZERO_RTT, ENCRYPTION_FORWARD_SECURE}) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500245 QuicStreamSendBuffer* send_buffer = &substreams_[level].send_buffer;
246 session()->connection()->SetDefaultEncryptionLevel(level);
247 while (send_buffer->HasPendingRetransmission()) {
248 auto pending = send_buffer->NextPendingRetransmission();
249 size_t bytes_consumed = session()->connection()->SendCryptoData(
250 level, pending.length, pending.offset);
251 send_buffer->OnStreamDataRetransmitted(pending.offset, bytes_consumed);
252 }
253 }
254 session()->connection()->SetDefaultEncryptionLevel(current_encryption_level);
255}
256
257void QuicCryptoStream::WritePendingRetransmission() {
258 while (HasPendingRetransmission()) {
259 StreamPendingRetransmission pending =
260 send_buffer().NextPendingRetransmission();
261 QuicIntervalSet<QuicStreamOffset> retransmission(
262 pending.offset, pending.offset + pending.length);
QUICHE team6987b4a2019-03-15 16:23:04 -0700263 EncryptionLevel retransmission_encryption_level = ENCRYPTION_INITIAL;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500264 // Determine the encryption level to write the retransmission
265 // at. The retransmission should be written at the same encryption level
266 // as the original transmission.
267 for (size_t i = 0; i < NUM_ENCRYPTION_LEVELS; ++i) {
268 if (retransmission.Intersects(bytes_consumed_[i])) {
269 retransmission_encryption_level = static_cast<EncryptionLevel>(i);
270 retransmission.Intersection(bytes_consumed_[i]);
271 break;
272 }
273 }
274 pending.offset = retransmission.begin()->min();
275 pending.length =
276 retransmission.begin()->max() - retransmission.begin()->min();
277 EncryptionLevel current_encryption_level =
278 session()->connection()->encryption_level();
279 // Set appropriate encryption level.
280 session()->connection()->SetDefaultEncryptionLevel(
281 retransmission_encryption_level);
282 QuicConsumedData consumed = session()->WritevData(
283 this, id(), pending.length, pending.offset, NO_FIN);
284 QUIC_DVLOG(1) << ENDPOINT << "stream " << id()
285 << " tries to retransmit stream data [" << pending.offset
286 << ", " << pending.offset + pending.length
287 << ") with encryption level: "
288 << retransmission_encryption_level
289 << ", consumed: " << consumed;
290 OnStreamFrameRetransmitted(pending.offset, consumed.bytes_consumed,
291 consumed.fin_consumed);
292 // Restore encryption level.
293 session()->connection()->SetDefaultEncryptionLevel(
294 current_encryption_level);
295 if (consumed.bytes_consumed < pending.length) {
296 // The connection is write blocked.
297 break;
298 }
299 }
300}
301
302bool QuicCryptoStream::RetransmitStreamData(QuicStreamOffset offset,
303 QuicByteCount data_length,
304 bool /*fin*/) {
305 QuicIntervalSet<QuicStreamOffset> retransmission(offset,
306 offset + data_length);
307 // Determine the encryption level to send data. This only needs to be once as
308 // [offset, offset + data_length) is guaranteed to be in the same packet.
QUICHE team6987b4a2019-03-15 16:23:04 -0700309 EncryptionLevel send_encryption_level = ENCRYPTION_INITIAL;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500310 for (size_t i = 0; i < NUM_ENCRYPTION_LEVELS; ++i) {
311 if (retransmission.Intersects(bytes_consumed_[i])) {
312 send_encryption_level = static_cast<EncryptionLevel>(i);
313 break;
314 }
315 }
316 retransmission.Difference(bytes_acked());
317 EncryptionLevel current_encryption_level =
318 session()->connection()->encryption_level();
319 for (const auto& interval : retransmission) {
320 QuicStreamOffset retransmission_offset = interval.min();
321 QuicByteCount retransmission_length = interval.max() - interval.min();
322 // Set appropriate encryption level.
323 session()->connection()->SetDefaultEncryptionLevel(send_encryption_level);
324 QuicConsumedData consumed = session()->WritevData(
325 this, id(), retransmission_length, retransmission_offset, NO_FIN);
326 QUIC_DVLOG(1) << ENDPOINT << "stream " << id()
327 << " is forced to retransmit stream data ["
328 << retransmission_offset << ", "
329 << retransmission_offset + retransmission_length
330 << "), with encryption level: " << send_encryption_level
331 << ", consumed: " << consumed;
332 OnStreamFrameRetransmitted(retransmission_offset, consumed.bytes_consumed,
333 consumed.fin_consumed);
334 // Restore encryption level.
335 session()->connection()->SetDefaultEncryptionLevel(
336 current_encryption_level);
337 if (consumed.bytes_consumed < retransmission_length) {
338 // The connection is write blocked.
339 return false;
340 }
341 }
342
343 return true;
344}
345
346uint64_t QuicCryptoStream::crypto_bytes_read() const {
QUICHE teamea740082019-03-11 17:58:43 -0700347 if (!QuicVersionUsesCryptoFrames(
348 session()->connection()->transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500349 return stream_bytes_read();
350 }
QUICHE team6987b4a2019-03-15 16:23:04 -0700351 return substreams_[ENCRYPTION_INITIAL].sequencer.NumBytesConsumed() +
QUICHE teama6ef0a62019-03-07 20:34:33 -0500352 substreams_[ENCRYPTION_ZERO_RTT].sequencer.NumBytesConsumed() +
353 substreams_[ENCRYPTION_FORWARD_SECURE].sequencer.NumBytesConsumed();
354}
355
356uint64_t QuicCryptoStream::BytesReadOnLevel(EncryptionLevel level) const {
357 return substreams_[level].sequencer.NumBytesConsumed();
358}
359
360bool QuicCryptoStream::WriteCryptoFrame(EncryptionLevel level,
361 QuicStreamOffset offset,
362 QuicByteCount data_length,
363 QuicDataWriter* writer) {
QUICHE teamea740082019-03-11 17:58:43 -0700364 QUIC_BUG_IF(!QuicVersionUsesCryptoFrames(
365 session()->connection()->transport_version()))
QUICHE teama6ef0a62019-03-07 20:34:33 -0500366 << "Versions less than 47 don't write CRYPTO frames (2)";
367 return substreams_[level].send_buffer.WriteStreamData(offset, data_length,
368 writer);
369}
370
371void QuicCryptoStream::OnCryptoFrameLost(QuicCryptoFrame* crypto_frame) {
QUICHE teamea740082019-03-11 17:58:43 -0700372 QUIC_BUG_IF(!QuicVersionUsesCryptoFrames(
373 session()->connection()->transport_version()))
QUICHE teama6ef0a62019-03-07 20:34:33 -0500374 << "Versions less than 47 don't lose CRYPTO frames";
375 substreams_[crypto_frame->level].send_buffer.OnStreamDataLost(
376 crypto_frame->offset, crypto_frame->data_length);
377}
378
379void QuicCryptoStream::RetransmitData(QuicCryptoFrame* crypto_frame) {
QUICHE teamea740082019-03-11 17:58:43 -0700380 QUIC_BUG_IF(!QuicVersionUsesCryptoFrames(
381 session()->connection()->transport_version()))
QUICHE teama6ef0a62019-03-07 20:34:33 -0500382 << "Versions less than 47 don't retransmit CRYPTO frames";
383 QuicIntervalSet<QuicStreamOffset> retransmission(
384 crypto_frame->offset, crypto_frame->offset + crypto_frame->data_length);
385 QuicStreamSendBuffer* send_buffer =
386 &substreams_[crypto_frame->level].send_buffer;
387 retransmission.Difference(send_buffer->bytes_acked());
388 if (retransmission.Empty()) {
389 return;
390 }
391 EncryptionLevel current_encryption_level =
392 session()->connection()->encryption_level();
393 for (const auto& interval : retransmission) {
394 size_t retransmission_offset = interval.min();
395 size_t retransmission_length = interval.max() - interval.min();
396 session()->connection()->SetDefaultEncryptionLevel(crypto_frame->level);
397 size_t bytes_consumed = session()->connection()->SendCryptoData(
398 crypto_frame->level, retransmission_length, retransmission_offset);
399 send_buffer->OnStreamDataRetransmitted(retransmission_offset,
400 bytes_consumed);
401 }
402 session()->connection()->SetDefaultEncryptionLevel(current_encryption_level);
403}
404
405bool QuicCryptoStream::IsFrameOutstanding(EncryptionLevel level,
406 size_t offset,
407 size_t length) const {
QUICHE teamea740082019-03-11 17:58:43 -0700408 if (!QuicVersionUsesCryptoFrames(
409 session()->connection()->transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500410 // This only happens if a client was originally configured for a version
411 // greater than 45, but received a version negotiation packet and is
412 // attempting to retransmit for a version less than 47. Outside of tests,
413 // this is a misconfiguration of the client, and this connection will be
414 // doomed. Return false here to avoid trying to retransmit CRYPTO frames on
415 // the wrong transport version.
416 return false;
417 }
418 return substreams_[level].send_buffer.IsStreamDataOutstanding(offset, length);
419}
420
421bool QuicCryptoStream::IsWaitingForAcks() const {
QUICHE teamea740082019-03-11 17:58:43 -0700422 if (!QuicVersionUsesCryptoFrames(
423 session()->connection()->transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500424 return QuicStream::IsWaitingForAcks();
425 }
426 for (EncryptionLevel level :
QUICHE team6987b4a2019-03-15 16:23:04 -0700427 {ENCRYPTION_INITIAL, ENCRYPTION_ZERO_RTT, ENCRYPTION_FORWARD_SECURE}) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500428 if (substreams_[level].send_buffer.stream_bytes_outstanding()) {
429 return true;
430 }
431 }
432 return false;
433}
434
435QuicCryptoStream::CryptoSubstream::CryptoSubstream(
436 QuicCryptoStream* crypto_stream,
437 EncryptionLevel)
438 : sequencer(crypto_stream),
439 send_buffer(crypto_stream->session()
440 ->connection()
441 ->helper()
442 ->GetStreamSendBufferAllocator()) {}
443
444#undef ENDPOINT // undef for jumbo builds
445} // namespace quic