blob: 11a5728f356b64e9732a329b18bb125f49819c1e [file] [log] [blame]
Bence Békybac04052022-04-07 15:44:29 -04001// 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 "quiche/quic/core/quic_crypto_server_stream.h"
6
7#include <memory>
8#include <string>
9
10#include "absl/base/macros.h"
11#include "absl/strings/string_view.h"
vasilvvdaa2fda2022-04-11 14:08:36 -070012#include "openssl/sha.h"
Bence Békybac04052022-04-07 15:44:29 -040013#include "quiche/quic/platform/api/quic_flag_utils.h"
14#include "quiche/quic/platform/api/quic_testvalue.h"
haoyuewang3d173d52022-04-27 12:20:25 -070015#include "quiche/common/platform/api/quiche_logging.h"
Bence Békybac04052022-04-07 15:44:29 -040016#include "quiche/common/quiche_text_utils.h"
17
18namespace quic {
19
20class QuicCryptoServerStream::ProcessClientHelloCallback
21 : public ProcessClientHelloResultCallback {
22 public:
23 ProcessClientHelloCallback(
24 QuicCryptoServerStream* parent,
25 const quiche::QuicheReferenceCountedPointer<
26 ValidateClientHelloResultCallback::Result>& result)
27 : parent_(parent), result_(result) {}
28
29 void Run(
bnc862751f2022-04-13 08:33:42 -070030 QuicErrorCode error, const std::string& error_details,
Bence Békybac04052022-04-07 15:44:29 -040031 std::unique_ptr<CryptoHandshakeMessage> message,
32 std::unique_ptr<DiversificationNonce> diversification_nonce,
33 std::unique_ptr<ProofSource::Details> proof_source_details) override {
34 if (parent_ == nullptr) {
35 return;
36 }
37
38 parent_->FinishProcessingHandshakeMessageAfterProcessClientHello(
39 *result_, error, error_details, std::move(message),
40 std::move(diversification_nonce), std::move(proof_source_details));
41 }
42
43 void Cancel() { parent_ = nullptr; }
44
45 private:
46 QuicCryptoServerStream* parent_;
47 quiche::QuicheReferenceCountedPointer<
48 ValidateClientHelloResultCallback::Result>
49 result_;
50};
51
52QuicCryptoServerStream::QuicCryptoServerStream(
53 const QuicCryptoServerConfig* crypto_config,
bnc862751f2022-04-13 08:33:42 -070054 QuicCompressedCertsCache* compressed_certs_cache, QuicSession* session,
Bence Békybac04052022-04-07 15:44:29 -040055 QuicCryptoServerStreamBase::Helper* helper)
56 : QuicCryptoServerStreamBase(session),
57 QuicCryptoHandshaker(this, session),
58 session_(session),
59 delegate_(session),
60 crypto_config_(crypto_config),
61 compressed_certs_cache_(compressed_certs_cache),
62 signed_config_(new QuicSignedServerConfig),
63 helper_(helper),
64 num_handshake_messages_(0),
65 num_handshake_messages_with_server_nonces_(0),
66 send_server_config_update_cb_(nullptr),
67 num_server_config_update_messages_sent_(0),
68 zero_rtt_attempted_(false),
69 chlo_packet_size_(0),
70 validate_client_hello_cb_(nullptr),
71 process_client_hello_cb_(nullptr),
72 encryption_established_(false),
73 one_rtt_keys_available_(false),
74 one_rtt_packet_decrypted_(false),
75 crypto_negotiated_params_(new QuicCryptoNegotiatedParameters) {}
76
77QuicCryptoServerStream::~QuicCryptoServerStream() {
78 CancelOutstandingCallbacks();
79}
80
81void QuicCryptoServerStream::CancelOutstandingCallbacks() {
82 // Detach from the validation callback. Calling this multiple times is safe.
83 if (validate_client_hello_cb_ != nullptr) {
84 validate_client_hello_cb_->Cancel();
85 validate_client_hello_cb_ = nullptr;
86 }
87 if (send_server_config_update_cb_ != nullptr) {
88 send_server_config_update_cb_->Cancel();
89 send_server_config_update_cb_ = nullptr;
90 }
91 if (process_client_hello_cb_ != nullptr) {
92 process_client_hello_cb_->Cancel();
93 process_client_hello_cb_ = nullptr;
94 }
95}
96
97void QuicCryptoServerStream::OnHandshakeMessage(
98 const CryptoHandshakeMessage& message) {
99 QuicCryptoHandshaker::OnHandshakeMessage(message);
100 ++num_handshake_messages_;
101 chlo_packet_size_ = session()->connection()->GetCurrentPacket().length();
102
103 // Do not process handshake messages after the handshake is confirmed.
104 if (one_rtt_keys_available_) {
105 OnUnrecoverableError(QUIC_CRYPTO_MESSAGE_AFTER_HANDSHAKE_COMPLETE,
106 "Unexpected handshake message from client");
107 return;
108 }
109
110 if (message.tag() != kCHLO) {
111 OnUnrecoverableError(QUIC_INVALID_CRYPTO_MESSAGE_TYPE,
112 "Handshake packet not CHLO");
113 return;
114 }
115
116 if (validate_client_hello_cb_ != nullptr ||
117 process_client_hello_cb_ != nullptr) {
118 // Already processing some other handshake message. The protocol
119 // does not allow for clients to send multiple handshake messages
120 // before the server has a chance to respond.
121 OnUnrecoverableError(QUIC_CRYPTO_MESSAGE_WHILE_VALIDATING_CLIENT_HELLO,
122 "Unexpected handshake message while processing CHLO");
123 return;
124 }
125
126 chlo_hash_ =
127 CryptoUtils::HashHandshakeMessage(message, Perspective::IS_SERVER);
128
129 std::unique_ptr<ValidateCallback> cb(new ValidateCallback(this));
130 QUICHE_DCHECK(validate_client_hello_cb_ == nullptr);
131 QUICHE_DCHECK(process_client_hello_cb_ == nullptr);
132 validate_client_hello_cb_ = cb.get();
133 crypto_config_->ValidateClientHello(
134 message, GetClientAddress(), session()->connection()->self_address(),
135 transport_version(), session()->connection()->clock(), signed_config_,
136 std::move(cb));
137}
138
139void QuicCryptoServerStream::FinishProcessingHandshakeMessage(
140 quiche::QuicheReferenceCountedPointer<
141 ValidateClientHelloResultCallback::Result>
142 result,
143 std::unique_ptr<ProofSource::Details> details) {
144 // Clear the callback that got us here.
145 QUICHE_DCHECK(validate_client_hello_cb_ != nullptr);
146 QUICHE_DCHECK(process_client_hello_cb_ == nullptr);
147 validate_client_hello_cb_ = nullptr;
148
149 std::unique_ptr<ProcessClientHelloCallback> cb(
150 new ProcessClientHelloCallback(this, result));
151 process_client_hello_cb_ = cb.get();
152 ProcessClientHello(result, std::move(details), std::move(cb));
153}
154
155void QuicCryptoServerStream::
156 FinishProcessingHandshakeMessageAfterProcessClientHello(
157 const ValidateClientHelloResultCallback::Result& result,
bnc862751f2022-04-13 08:33:42 -0700158 QuicErrorCode error, const std::string& error_details,
Bence Békybac04052022-04-07 15:44:29 -0400159 std::unique_ptr<CryptoHandshakeMessage> reply,
160 std::unique_ptr<DiversificationNonce> diversification_nonce,
161 std::unique_ptr<ProofSource::Details> proof_source_details) {
162 // Clear the callback that got us here.
163 QUICHE_DCHECK(process_client_hello_cb_ != nullptr);
164 QUICHE_DCHECK(validate_client_hello_cb_ == nullptr);
165 process_client_hello_cb_ = nullptr;
166 proof_source_details_ = std::move(proof_source_details);
167
168 AdjustTestValue("quic::QuicCryptoServerStream::after_process_client_hello",
169 session());
170
171 if (!session()->connection()->connected()) {
172 QUIC_CODE_COUNT(quic_crypto_disconnected_after_process_client_hello);
173 QUIC_LOG_FIRST_N(INFO, 10)
174 << "After processing CHLO, QUIC connection has been closed with code "
175 << session()->error() << ", details: " << session()->error_details();
176 return;
177 }
178
179 const CryptoHandshakeMessage& message = result.client_hello;
180 if (error != QUIC_NO_ERROR) {
181 OnUnrecoverableError(error, error_details);
182 return;
183 }
184
185 if (reply->tag() != kSHLO) {
186 session()->connection()->set_fully_pad_crypto_handshake_packets(
187 crypto_config_->pad_rej());
188 // Send REJ in plaintext.
189 SendHandshakeMessage(*reply, ENCRYPTION_INITIAL);
190 return;
191 }
192
193 // If we are returning a SHLO then we accepted the handshake. Now
194 // process the negotiated configuration options as part of the
195 // session config.
196 QuicConfig* config = session()->config();
197 OverrideQuicConfigDefaults(config);
198 std::string process_error_details;
199 const QuicErrorCode process_error =
200 config->ProcessPeerHello(message, CLIENT, &process_error_details);
201 if (process_error != QUIC_NO_ERROR) {
202 OnUnrecoverableError(process_error, process_error_details);
203 return;
204 }
205
206 session()->OnConfigNegotiated();
207
208 config->ToHandshakeMessage(reply.get(), session()->transport_version());
209
210 // Receiving a full CHLO implies the client is prepared to decrypt with
211 // the new server write key. We can start to encrypt with the new server
212 // write key.
213 //
214 // NOTE: the SHLO will be encrypted with the new server write key.
215 delegate_->OnNewEncryptionKeyAvailable(
216 ENCRYPTION_ZERO_RTT,
217 std::move(crypto_negotiated_params_->initial_crypters.encrypter));
218 delegate_->OnNewDecryptionKeyAvailable(
219 ENCRYPTION_ZERO_RTT,
220 std::move(crypto_negotiated_params_->initial_crypters.decrypter),
221 /*set_alternative_decrypter=*/false,
222 /*latch_once_used=*/false);
223 delegate_->SetDefaultEncryptionLevel(ENCRYPTION_ZERO_RTT);
224 delegate_->DiscardOldDecryptionKey(ENCRYPTION_INITIAL);
225 session()->connection()->SetDiversificationNonce(*diversification_nonce);
226
227 session()->connection()->set_fully_pad_crypto_handshake_packets(
228 crypto_config_->pad_shlo());
229 // Send SHLO in ENCRYPTION_ZERO_RTT.
230 SendHandshakeMessage(*reply, ENCRYPTION_ZERO_RTT);
231 delegate_->OnNewEncryptionKeyAvailable(
232 ENCRYPTION_FORWARD_SECURE,
233 std::move(crypto_negotiated_params_->forward_secure_crypters.encrypter));
234 delegate_->OnNewDecryptionKeyAvailable(
235 ENCRYPTION_FORWARD_SECURE,
236 std::move(crypto_negotiated_params_->forward_secure_crypters.decrypter),
237 /*set_alternative_decrypter=*/true,
238 /*latch_once_used=*/false);
239 encryption_established_ = true;
240 one_rtt_keys_available_ = true;
241 delegate_->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
242 delegate_->DiscardOldEncryptionKey(ENCRYPTION_INITIAL);
243}
244
245void QuicCryptoServerStream::SendServerConfigUpdate(
246 const CachedNetworkParameters* cached_network_params) {
247 if (!one_rtt_keys_available_) {
248 return;
249 }
250
251 if (send_server_config_update_cb_ != nullptr) {
252 QUIC_DVLOG(1)
253 << "Skipped server config update since one is already in progress";
254 return;
255 }
256
257 std::unique_ptr<SendServerConfigUpdateCallback> cb(
258 new SendServerConfigUpdateCallback(this));
259 send_server_config_update_cb_ = cb.get();
260
261 crypto_config_->BuildServerConfigUpdateMessage(
262 session()->transport_version(), chlo_hash_,
263 previous_source_address_tokens_, session()->connection()->self_address(),
264 GetClientAddress(), session()->connection()->clock(),
265 session()->connection()->random_generator(), compressed_certs_cache_,
266 *crypto_negotiated_params_, cached_network_params, std::move(cb));
267}
268
269QuicCryptoServerStream::SendServerConfigUpdateCallback::
270 SendServerConfigUpdateCallback(QuicCryptoServerStream* parent)
271 : parent_(parent) {}
272
273void QuicCryptoServerStream::SendServerConfigUpdateCallback::Cancel() {
274 parent_ = nullptr;
275}
276
277// From BuildServerConfigUpdateMessageResultCallback
278void QuicCryptoServerStream::SendServerConfigUpdateCallback::Run(
bnc862751f2022-04-13 08:33:42 -0700279 bool ok, const CryptoHandshakeMessage& message) {
Bence Békybac04052022-04-07 15:44:29 -0400280 if (parent_ == nullptr) {
281 return;
282 }
283 parent_->FinishSendServerConfigUpdate(ok, message);
284}
285
286void QuicCryptoServerStream::FinishSendServerConfigUpdate(
bnc862751f2022-04-13 08:33:42 -0700287 bool ok, const CryptoHandshakeMessage& message) {
Bence Békybac04052022-04-07 15:44:29 -0400288 // Clear the callback that got us here.
289 QUICHE_DCHECK(send_server_config_update_cb_ != nullptr);
290 send_server_config_update_cb_ = nullptr;
291
292 if (!ok) {
293 QUIC_DVLOG(1) << "Server: Failed to build server config update (SCUP)!";
294 return;
295 }
296
297 QUIC_DVLOG(1) << "Server: Sending server config update: "
298 << message.DebugString();
299
300 // Send server config update in ENCRYPTION_FORWARD_SECURE.
301 SendHandshakeMessage(message, ENCRYPTION_FORWARD_SECURE);
302
303 ++num_server_config_update_messages_sent_;
304}
305
306bool QuicCryptoServerStream::DisableResumption() {
307 QUICHE_DCHECK(false) << "Not supported for QUIC crypto.";
308 return false;
309}
310
311bool QuicCryptoServerStream::IsZeroRtt() const {
312 return num_handshake_messages_ == 1 &&
313 num_handshake_messages_with_server_nonces_ == 0;
314}
315
316bool QuicCryptoServerStream::IsResumption() const {
317 // QUIC Crypto doesn't have a non-0-RTT resumption mode.
318 return IsZeroRtt();
319}
320
321int QuicCryptoServerStream::NumServerConfigUpdateMessagesSent() const {
322 return num_server_config_update_messages_sent_;
323}
324
325const CachedNetworkParameters*
326QuicCryptoServerStream::PreviousCachedNetworkParams() const {
327 return previous_cached_network_params_.get();
328}
329
330bool QuicCryptoServerStream::ResumptionAttempted() const {
331 return zero_rtt_attempted_;
332}
333
334bool QuicCryptoServerStream::EarlyDataAttempted() const {
335 QUICHE_DCHECK(false) << "Not supported for QUIC crypto.";
336 return zero_rtt_attempted_;
337}
338
339void QuicCryptoServerStream::SetPreviousCachedNetworkParams(
340 CachedNetworkParameters cached_network_params) {
341 previous_cached_network_params_.reset(
342 new CachedNetworkParameters(cached_network_params));
343}
344
345void QuicCryptoServerStream::OnPacketDecrypted(EncryptionLevel level) {
346 if (level == ENCRYPTION_FORWARD_SECURE) {
347 one_rtt_packet_decrypted_ = true;
348 delegate_->NeuterHandshakeData();
349 }
350}
351
bnc862751f2022-04-13 08:33:42 -0700352void QuicCryptoServerStream::OnHandshakeDoneReceived() { QUICHE_DCHECK(false); }
Bence Békybac04052022-04-07 15:44:29 -0400353
354void QuicCryptoServerStream::OnNewTokenReceived(absl::string_view /*token*/) {
355 QUICHE_DCHECK(false);
356}
357
358std::string QuicCryptoServerStream::GetAddressToken(
359 const CachedNetworkParameters* /*cached_network_parameters*/) const {
360 QUICHE_DCHECK(false);
361 return "";
362}
363
364bool QuicCryptoServerStream::ValidateAddressToken(
365 absl::string_view /*token*/) const {
366 QUICHE_DCHECK(false);
367 return false;
368}
369
370bool QuicCryptoServerStream::ShouldSendExpectCTHeader() const {
371 return signed_config_->proof.send_expect_ct_header;
372}
373
374bool QuicCryptoServerStream::DidCertMatchSni() const {
375 return signed_config_->proof.cert_matched_sni;
376}
377
378const ProofSource::Details* QuicCryptoServerStream::ProofSourceDetails() const {
379 return proof_source_details_.get();
380}
381
382bool QuicCryptoServerStream::GetBase64SHA256ClientChannelID(
383 std::string* output) const {
384 if (!encryption_established() ||
385 crypto_negotiated_params_->channel_id.empty()) {
386 return false;
387 }
388
389 const std::string& channel_id(crypto_negotiated_params_->channel_id);
390 uint8_t digest[SHA256_DIGEST_LENGTH];
391 SHA256(reinterpret_cast<const uint8_t*>(channel_id.data()), channel_id.size(),
392 digest);
393
394 quiche::QuicheTextUtils::Base64Encode(digest, ABSL_ARRAYSIZE(digest), output);
395 return true;
396}
397
398ssl_early_data_reason_t QuicCryptoServerStream::EarlyDataReason() const {
399 if (IsZeroRtt()) {
400 return ssl_early_data_accepted;
401 }
402 if (zero_rtt_attempted_) {
403 return ssl_early_data_session_not_resumed;
404 }
405 return ssl_early_data_no_session_offered;
406}
407
408bool QuicCryptoServerStream::encryption_established() const {
409 return encryption_established_;
410}
411
412bool QuicCryptoServerStream::one_rtt_keys_available() const {
413 return one_rtt_keys_available_;
414}
415
416const QuicCryptoNegotiatedParameters&
417QuicCryptoServerStream::crypto_negotiated_params() const {
418 return *crypto_negotiated_params_;
419}
420
421CryptoMessageParser* QuicCryptoServerStream::crypto_message_parser() {
422 return QuicCryptoHandshaker::crypto_message_parser();
423}
424
425HandshakeState QuicCryptoServerStream::GetHandshakeState() const {
426 return one_rtt_packet_decrypted_ ? HANDSHAKE_COMPLETE : HANDSHAKE_START;
427}
428
429void QuicCryptoServerStream::SetServerApplicationStateForResumption(
430 std::unique_ptr<ApplicationState> /*state*/) {
431 // QUIC Crypto doesn't need to remember any application state as part of doing
432 // 0-RTT resumption, so this function is a no-op.
433}
434
435size_t QuicCryptoServerStream::BufferSizeLimitForLevel(
436 EncryptionLevel level) const {
437 return QuicCryptoHandshaker::BufferSizeLimitForLevel(level);
438}
439
440std::unique_ptr<QuicDecrypter>
441QuicCryptoServerStream::AdvanceKeysAndCreateCurrentOneRttDecrypter() {
442 // Key update is only defined in QUIC+TLS.
443 QUICHE_DCHECK(false);
444 return nullptr;
445}
446
447std::unique_ptr<QuicEncrypter>
448QuicCryptoServerStream::CreateCurrentOneRttEncrypter() {
449 // Key update is only defined in QUIC+TLS.
450 QUICHE_DCHECK(false);
451 return nullptr;
452}
453
454void QuicCryptoServerStream::ProcessClientHello(
455 quiche::QuicheReferenceCountedPointer<
456 ValidateClientHelloResultCallback::Result>
457 result,
458 std::unique_ptr<ProofSource::Details> proof_source_details,
459 std::unique_ptr<ProcessClientHelloResultCallback> done_cb) {
460 proof_source_details_ = std::move(proof_source_details);
461 const CryptoHandshakeMessage& message = result->client_hello;
462 std::string error_details;
463 if (!helper_->CanAcceptClientHello(
464 message, GetClientAddress(), session()->connection()->peer_address(),
465 session()->connection()->self_address(), &error_details)) {
466 done_cb->Run(QUIC_HANDSHAKE_FAILED, error_details, nullptr, nullptr,
467 nullptr);
468 return;
469 }
470
471 absl::string_view user_agent_id;
472 message.GetStringPiece(quic::kUAID, &user_agent_id);
473 if (!session()->user_agent_id().has_value() && !user_agent_id.empty()) {
474 session()->SetUserAgentId(std::string(user_agent_id));
475 }
476
477 if (!result->info.server_nonce.empty()) {
478 ++num_handshake_messages_with_server_nonces_;
479 }
480
481 if (num_handshake_messages_ == 1) {
482 // Client attempts zero RTT handshake by sending a non-inchoate CHLO.
483 absl::string_view public_value;
484 zero_rtt_attempted_ = message.GetStringPiece(kPUBS, &public_value);
485 }
486
487 // Store the bandwidth estimate from the client.
488 if (result->cached_network_params.bandwidth_estimate_bytes_per_second() > 0) {
489 previous_cached_network_params_.reset(
490 new CachedNetworkParameters(result->cached_network_params));
491 }
492 previous_source_address_tokens_ = result->info.source_address_tokens;
493
494 QuicConnection* connection = session()->connection();
495 crypto_config_->ProcessClientHello(
496 result, /*reject_only=*/false, connection->connection_id(),
497 connection->self_address(), GetClientAddress(), connection->version(),
498 session()->supported_versions(), connection->clock(),
499 connection->random_generator(), compressed_certs_cache_,
500 crypto_negotiated_params_, signed_config_,
501 QuicCryptoStream::CryptoMessageFramingOverhead(
502 transport_version(), connection->connection_id()),
503 chlo_packet_size_, std::move(done_cb));
504}
505
506void QuicCryptoServerStream::OverrideQuicConfigDefaults(
507 QuicConfig* /*config*/) {}
508
509QuicCryptoServerStream::ValidateCallback::ValidateCallback(
510 QuicCryptoServerStream* parent)
511 : parent_(parent) {}
512
bnc862751f2022-04-13 08:33:42 -0700513void QuicCryptoServerStream::ValidateCallback::Cancel() { parent_ = nullptr; }
Bence Békybac04052022-04-07 15:44:29 -0400514
515void QuicCryptoServerStream::ValidateCallback::Run(
516 quiche::QuicheReferenceCountedPointer<Result> result,
517 std::unique_ptr<ProofSource::Details> details) {
518 if (parent_ != nullptr) {
519 parent_->FinishProcessingHandshakeMessage(std::move(result),
520 std::move(details));
521 }
522}
523
524const QuicSocketAddress QuicCryptoServerStream::GetClientAddress() {
525 return session()->connection()->peer_address();
526}
527
528SSL* QuicCryptoServerStream::GetSsl() const { return nullptr; }
529
haoyuewang3d173d52022-04-27 12:20:25 -0700530bool QuicCryptoServerStream::IsCryptoFrameExpectedForEncryptionLevel(
531 EncryptionLevel /*level*/) const {
532 return true;
533}
534
Bence Békybac04052022-04-07 15:44:29 -0400535} // namespace quic