Ryan Hamilton | 56b10c5d | 2018-05-11 13:40:16 | [diff] [blame] | 1 | // Copyright (c) 2013 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 | |
Ryan Hamilton | 7582d265 | 2018-08-01 22:35:32 | [diff] [blame] | 5 | #include "net/quic/mock_crypto_client_stream.h" |
Ryan Hamilton | 56b10c5d | 2018-05-11 13:40:16 | [diff] [blame] | 6 | |
Ryan Hamilton | 7582d265 | 2018-08-01 22:35:32 | [diff] [blame] | 7 | #include "net/quic/mock_decrypter.h" |
| 8 | #include "net/quic/mock_encrypter.h" |
Victor Vasiliev | 6bb59d2 | 2019-03-08 21:34:51 | [diff] [blame] | 9 | #include "net/third_party/quiche/src/quic/core/crypto/null_decrypter.h" |
| 10 | #include "net/third_party/quiche/src/quic/core/crypto/null_encrypter.h" |
| 11 | #include "net/third_party/quiche/src/quic/core/crypto/quic_decrypter.h" |
| 12 | #include "net/third_party/quiche/src/quic/core/crypto/quic_encrypter.h" |
| 13 | #include "net/third_party/quiche/src/quic/core/http/quic_spdy_client_session_base.h" |
| 14 | #include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h" |
| 15 | #include "net/third_party/quiche/src/quic/test_tools/quic_config_peer.h" |
Ryan Hamilton | 56b10c5d | 2018-05-11 13:40:16 | [diff] [blame] | 16 | #include "testing/gtest/include/gtest/gtest.h" |
| 17 | |
Ryan Hamilton | 9835e66 | 2018-08-02 05:36:27 | [diff] [blame] | 18 | using quic::CLIENT; |
| 19 | using quic::ConnectionCloseBehavior; |
| 20 | using quic::CryptoHandshakeMessage; |
| 21 | using quic::CryptoMessageParser; |
| 22 | using quic::ENCRYPTION_FORWARD_SECURE; |
Michael Warres | 167db3e | 2019-03-01 21:38:03 | [diff] [blame] | 23 | using quic::ENCRYPTION_ZERO_RTT; |
Ryan Hamilton | 9835e66 | 2018-08-02 05:36:27 | [diff] [blame] | 24 | using quic::kAESG; |
| 25 | using quic::kC255; |
| 26 | using quic::kDefaultMaxStreamsPerConnection; |
| 27 | using quic::kMaximumIdleTimeoutSecs; |
| 28 | using quic::kQBIC; |
| 29 | using quic::NullDecrypter; |
| 30 | using quic::NullEncrypter; |
| 31 | using quic::PACKET_8BYTE_CONNECTION_ID; |
| 32 | using quic::Perspective; |
| 33 | using quic::ProofVerifyContext; |
| 34 | using quic::QUIC_CRYPTO_MESSAGE_AFTER_HANDSHAKE_COMPLETE; |
| 35 | using quic::QUIC_NO_ERROR; |
| 36 | using quic::QUIC_PROOF_INVALID; |
| 37 | using quic::QuicConfig; |
| 38 | using quic::QuicCryptoClientConfig; |
| 39 | using quic::QuicCryptoNegotiatedParameters; |
| 40 | using quic::QuicErrorCode; |
| 41 | using quic::QuicMakeUnique; |
| 42 | using quic::QuicServerId; |
| 43 | using quic::QuicSession; |
| 44 | using quic::QuicSpdyClientSessionBase; |
Zhongyi Shi | 87965942 | 2018-08-02 17:58:25 | [diff] [blame] | 45 | using quic::QuicStringPiece; |
Ryan Hamilton | 9835e66 | 2018-08-02 05:36:27 | [diff] [blame] | 46 | using quic::QuicTagVector; |
| 47 | using quic::QuicTime; |
Victor Vasiliev | 076657c | 2019-03-12 02:46:43 | [diff] [blame] | 48 | using std::string; |
Ryan Hamilton | 9835e66 | 2018-08-02 05:36:27 | [diff] [blame] | 49 | |
| 50 | namespace net { |
Ryan Hamilton | 56b10c5d | 2018-05-11 13:40:16 | [diff] [blame] | 51 | |
| 52 | MockCryptoClientStream::MockCryptoClientStream( |
| 53 | const QuicServerId& server_id, |
| 54 | QuicSpdyClientSessionBase* session, |
Ryan Hamilton | f044c1b | 2018-07-24 00:00:14 | [diff] [blame] | 55 | std::unique_ptr<ProofVerifyContext> verify_context, |
Ryan Hamilton | 56b10c5d | 2018-05-11 13:40:16 | [diff] [blame] | 56 | const QuicConfig& config, |
| 57 | QuicCryptoClientConfig* crypto_config, |
| 58 | HandshakeMode handshake_mode, |
Ryan Hamilton | 8d9ee76e | 2018-05-29 23:52:52 | [diff] [blame] | 59 | const net::ProofVerifyDetailsChromium* proof_verify_details, |
Ryan Hamilton | 56b10c5d | 2018-05-11 13:40:16 | [diff] [blame] | 60 | bool use_mock_crypter) |
| 61 | : QuicCryptoClientStream(server_id, |
| 62 | session, |
Ryan Hamilton | f044c1b | 2018-07-24 00:00:14 | [diff] [blame] | 63 | std::move(verify_context), |
Ryan Hamilton | 56b10c5d | 2018-05-11 13:40:16 | [diff] [blame] | 64 | crypto_config, |
| 65 | session), |
| 66 | QuicCryptoHandshaker(this, session), |
| 67 | handshake_mode_(handshake_mode), |
| 68 | encryption_established_(false), |
| 69 | handshake_confirmed_(false), |
| 70 | crypto_negotiated_params_(new QuicCryptoNegotiatedParameters), |
| 71 | use_mock_crypter_(use_mock_crypter), |
| 72 | server_id_(server_id), |
| 73 | proof_verify_details_(proof_verify_details), |
| 74 | config_(config) { |
| 75 | crypto_framer_.set_visitor(this); |
| 76 | } |
| 77 | |
| 78 | MockCryptoClientStream::~MockCryptoClientStream() {} |
| 79 | |
| 80 | void MockCryptoClientStream::OnHandshakeMessage( |
| 81 | const CryptoHandshakeMessage& message) { |
| 82 | CloseConnectionWithDetails(QUIC_CRYPTO_MESSAGE_AFTER_HANDSHAKE_COMPLETE, |
| 83 | "Forced mock failure"); |
| 84 | } |
| 85 | |
| 86 | bool MockCryptoClientStream::CryptoConnect() { |
| 87 | if (proof_verify_details_) { |
| 88 | if (!proof_verify_details_->cert_verify_result.verified_cert |
| 89 | ->VerifyNameMatch(server_id_.host())) { |
| 90 | handshake_confirmed_ = false; |
| 91 | encryption_established_ = false; |
| 92 | session()->connection()->CloseConnection( |
| 93 | QUIC_PROOF_INVALID, "proof invalid", |
| 94 | ConnectionCloseBehavior::SILENT_CLOSE); |
| 95 | return false; |
| 96 | } |
| 97 | } |
| 98 | |
| 99 | switch (handshake_mode_) { |
| 100 | case ZERO_RTT: { |
| 101 | encryption_established_ = true; |
| 102 | handshake_confirmed_ = false; |
| 103 | crypto_negotiated_params_->key_exchange = kC255; |
| 104 | crypto_negotiated_params_->aead = kAESG; |
| 105 | if (proof_verify_details_) { |
| 106 | reinterpret_cast<QuicSpdyClientSessionBase*>(session()) |
| 107 | ->OnProofVerifyDetailsAvailable(*proof_verify_details_); |
| 108 | } |
| 109 | if (use_mock_crypter_) { |
Zhongyi Shi | 2d8d8c2 | 2019-04-13 00:06:17 | [diff] [blame] | 110 | if (session()->connection()->version().KnowsWhichDecrypterToUse()) { |
| 111 | session()->connection()->InstallDecrypter( |
| 112 | ENCRYPTION_ZERO_RTT, |
| 113 | QuicMakeUnique<MockDecrypter>(Perspective::IS_CLIENT)); |
| 114 | } else { |
| 115 | session()->connection()->SetDecrypter( |
| 116 | ENCRYPTION_ZERO_RTT, |
| 117 | QuicMakeUnique<MockDecrypter>(Perspective::IS_CLIENT)); |
| 118 | } |
Ryan Hamilton | 56b10c5d | 2018-05-11 13:40:16 | [diff] [blame] | 119 | session()->connection()->SetEncrypter( |
Michael Warres | 167db3e | 2019-03-01 21:38:03 | [diff] [blame] | 120 | ENCRYPTION_ZERO_RTT, |
Ryan Hamilton | 56b10c5d | 2018-05-11 13:40:16 | [diff] [blame] | 121 | QuicMakeUnique<MockEncrypter>(Perspective::IS_CLIENT)); |
| 122 | } else { |
Zhongyi Shi | 2d8d8c2 | 2019-04-13 00:06:17 | [diff] [blame] | 123 | if (session()->connection()->version().KnowsWhichDecrypterToUse()) { |
| 124 | session()->connection()->InstallDecrypter( |
| 125 | ENCRYPTION_ZERO_RTT, |
| 126 | QuicMakeUnique<NullDecrypter>(Perspective::IS_CLIENT)); |
| 127 | } else { |
| 128 | session()->connection()->SetDecrypter( |
| 129 | ENCRYPTION_ZERO_RTT, |
| 130 | QuicMakeUnique<NullDecrypter>(Perspective::IS_CLIENT)); |
| 131 | } |
Ryan Hamilton | 56b10c5d | 2018-05-11 13:40:16 | [diff] [blame] | 132 | session()->connection()->SetEncrypter( |
Michael Warres | 167db3e | 2019-03-01 21:38:03 | [diff] [blame] | 133 | ENCRYPTION_ZERO_RTT, |
Ryan Hamilton | 56b10c5d | 2018-05-11 13:40:16 | [diff] [blame] | 134 | QuicMakeUnique<NullEncrypter>(Perspective::IS_CLIENT)); |
| 135 | } |
Michael Warres | 167db3e | 2019-03-01 21:38:03 | [diff] [blame] | 136 | session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_ZERO_RTT); |
Ryan Hamilton | 05c0f59 | 2019-08-21 19:53:16 | [diff] [blame] | 137 | session()->OnCryptoHandshakeEvent(QuicSession::ENCRYPTION_ESTABLISHED); |
Ryan Hamilton | 56b10c5d | 2018-05-11 13:40:16 | [diff] [blame] | 138 | break; |
| 139 | } |
| 140 | |
| 141 | case CONFIRM_HANDSHAKE: { |
| 142 | encryption_established_ = true; |
| 143 | handshake_confirmed_ = true; |
| 144 | crypto_negotiated_params_->key_exchange = kC255; |
| 145 | crypto_negotiated_params_->aead = kAESG; |
| 146 | if (proof_verify_details_) { |
| 147 | reinterpret_cast<QuicSpdyClientSessionBase*>(session()) |
| 148 | ->OnProofVerifyDetailsAvailable(*proof_verify_details_); |
| 149 | } |
| 150 | SetConfigNegotiated(); |
| 151 | if (use_mock_crypter_) { |
Zhongyi Shi | 2d8d8c2 | 2019-04-13 00:06:17 | [diff] [blame] | 152 | if (session()->connection()->version().KnowsWhichDecrypterToUse()) { |
| 153 | session()->connection()->InstallDecrypter( |
| 154 | ENCRYPTION_FORWARD_SECURE, |
| 155 | QuicMakeUnique<MockDecrypter>(Perspective::IS_CLIENT)); |
| 156 | } else { |
| 157 | session()->connection()->SetDecrypter( |
| 158 | ENCRYPTION_FORWARD_SECURE, |
| 159 | QuicMakeUnique<MockDecrypter>(Perspective::IS_CLIENT)); |
| 160 | } |
Ryan Hamilton | 56b10c5d | 2018-05-11 13:40:16 | [diff] [blame] | 161 | session()->connection()->SetEncrypter( |
| 162 | ENCRYPTION_FORWARD_SECURE, |
| 163 | QuicMakeUnique<MockEncrypter>(Perspective::IS_CLIENT)); |
| 164 | } else { |
Zhongyi Shi | 2d8d8c2 | 2019-04-13 00:06:17 | [diff] [blame] | 165 | if (session()->connection()->version().KnowsWhichDecrypterToUse()) { |
| 166 | session()->connection()->InstallDecrypter( |
| 167 | ENCRYPTION_FORWARD_SECURE, |
| 168 | QuicMakeUnique<NullDecrypter>(Perspective::IS_CLIENT)); |
| 169 | } else { |
| 170 | session()->connection()->SetDecrypter( |
| 171 | ENCRYPTION_FORWARD_SECURE, |
| 172 | QuicMakeUnique<NullDecrypter>(Perspective::IS_CLIENT)); |
| 173 | } |
Ryan Hamilton | 56b10c5d | 2018-05-11 13:40:16 | [diff] [blame] | 174 | session()->connection()->SetEncrypter( |
| 175 | ENCRYPTION_FORWARD_SECURE, |
| 176 | QuicMakeUnique<NullEncrypter>(Perspective::IS_CLIENT)); |
| 177 | } |
| 178 | session()->connection()->SetDefaultEncryptionLevel( |
| 179 | ENCRYPTION_FORWARD_SECURE); |
| 180 | session()->OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED); |
Fan Yang | 928cb04 | 2019-08-26 21:53:37 | [diff] [blame] | 181 | session()->connection()->OnHandshakeComplete(); |
Ryan Hamilton | 56b10c5d | 2018-05-11 13:40:16 | [diff] [blame] | 182 | break; |
| 183 | } |
| 184 | |
| 185 | case COLD_START: { |
| 186 | handshake_confirmed_ = false; |
| 187 | encryption_established_ = false; |
| 188 | break; |
| 189 | } |
| 190 | |
Zhongyi Shi | 87965942 | 2018-08-02 17:58:25 | [diff] [blame] | 191 | case COLD_START_WITH_CHLO_SENT: { |
| 192 | handshake_confirmed_ = false; |
| 193 | encryption_established_ = false; |
Zhongyi Shi | 5068bb0 | 2018-08-03 02:44:09 | [diff] [blame] | 194 | SendHandshakeMessage(GetDummyCHLOMessage()); |
Ryan Hamilton | 56b10c5d | 2018-05-11 13:40:16 | [diff] [blame] | 195 | break; |
| 196 | } |
| 197 | } |
| 198 | |
| 199 | return session()->connection()->connected(); |
| 200 | } |
| 201 | |
| 202 | bool MockCryptoClientStream::encryption_established() const { |
| 203 | return encryption_established_; |
| 204 | } |
| 205 | |
| 206 | bool MockCryptoClientStream::handshake_confirmed() const { |
| 207 | return handshake_confirmed_; |
| 208 | } |
| 209 | |
| 210 | const QuicCryptoNegotiatedParameters& |
| 211 | MockCryptoClientStream::crypto_negotiated_params() const { |
| 212 | return *crypto_negotiated_params_; |
| 213 | } |
| 214 | |
| 215 | CryptoMessageParser* MockCryptoClientStream::crypto_message_parser() { |
| 216 | return &crypto_framer_; |
| 217 | } |
| 218 | |
| 219 | void MockCryptoClientStream::SendOnCryptoHandshakeEvent( |
| 220 | QuicSession::CryptoHandshakeEvent event) { |
| 221 | encryption_established_ = true; |
| 222 | if (event == QuicSession::HANDSHAKE_CONFIRMED) { |
| 223 | handshake_confirmed_ = true; |
| 224 | SetConfigNegotiated(); |
| 225 | if (use_mock_crypter_) { |
Zhongyi Shi | 2d8d8c2 | 2019-04-13 00:06:17 | [diff] [blame] | 226 | if (session()->connection()->version().KnowsWhichDecrypterToUse()) { |
| 227 | session()->connection()->InstallDecrypter( |
| 228 | ENCRYPTION_FORWARD_SECURE, |
| 229 | QuicMakeUnique<MockDecrypter>(Perspective::IS_CLIENT)); |
| 230 | } else { |
| 231 | session()->connection()->SetDecrypter( |
| 232 | ENCRYPTION_FORWARD_SECURE, |
| 233 | QuicMakeUnique<MockDecrypter>(Perspective::IS_CLIENT)); |
| 234 | } |
Ryan Hamilton | 56b10c5d | 2018-05-11 13:40:16 | [diff] [blame] | 235 | session()->connection()->SetEncrypter( |
| 236 | ENCRYPTION_FORWARD_SECURE, |
| 237 | QuicMakeUnique<MockEncrypter>(Perspective::IS_CLIENT)); |
| 238 | } else { |
Zhongyi Shi | 2d8d8c2 | 2019-04-13 00:06:17 | [diff] [blame] | 239 | if (session()->connection()->version().KnowsWhichDecrypterToUse()) { |
| 240 | session()->connection()->InstallDecrypter( |
| 241 | ENCRYPTION_FORWARD_SECURE, |
| 242 | QuicMakeUnique<NullDecrypter>(Perspective::IS_CLIENT)); |
| 243 | } else { |
| 244 | session()->connection()->SetDecrypter( |
| 245 | ENCRYPTION_FORWARD_SECURE, |
| 246 | QuicMakeUnique<NullDecrypter>(Perspective::IS_CLIENT)); |
| 247 | } |
Ryan Hamilton | 56b10c5d | 2018-05-11 13:40:16 | [diff] [blame] | 248 | session()->connection()->SetEncrypter( |
| 249 | ENCRYPTION_FORWARD_SECURE, |
| 250 | QuicMakeUnique<NullEncrypter>(Perspective::IS_CLIENT)); |
| 251 | } |
| 252 | session()->connection()->SetDefaultEncryptionLevel( |
| 253 | ENCRYPTION_FORWARD_SECURE); |
| 254 | } |
| 255 | session()->OnCryptoHandshakeEvent(event); |
| 256 | } |
| 257 | |
Zhongyi Shi | 87965942 | 2018-08-02 17:58:25 | [diff] [blame] | 258 | // static |
| 259 | CryptoHandshakeMessage MockCryptoClientStream::GetDummyCHLOMessage() { |
| 260 | CryptoHandshakeMessage message; |
| 261 | message.set_tag(quic::kCHLO); |
| 262 | return message; |
| 263 | } |
| 264 | |
Ryan Hamilton | 56b10c5d | 2018-05-11 13:40:16 | [diff] [blame] | 265 | void MockCryptoClientStream::SetConfigNegotiated() { |
| 266 | ASSERT_FALSE(session()->config()->negotiated()); |
| 267 | QuicTagVector cgst; |
| 268 | // TODO(rtenneti): Enable the following code after BBR code is checked in. |
| 269 | #if 0 |
| 270 | cgst.push_back(kTBBR); |
| 271 | #endif |
| 272 | cgst.push_back(kQBIC); |
| 273 | QuicConfig config(config_); |
| 274 | config.SetIdleNetworkTimeout( |
| 275 | QuicTime::Delta::FromSeconds(2 * kMaximumIdleTimeoutSecs), |
| 276 | QuicTime::Delta::FromSeconds(kMaximumIdleTimeoutSecs)); |
Ryan Hamilton | 56b10c5d | 2018-05-11 13:40:16 | [diff] [blame] | 277 | config.SetBytesForConnectionIdToSend(PACKET_8BYTE_CONNECTION_ID); |
Ryan Hamilton | 4aeec56 | 2019-05-17 21:22:52 | [diff] [blame] | 278 | config.SetMaxIncomingBidirectionalStreamsToSend( |
| 279 | kDefaultMaxStreamsPerConnection / 2); |
| 280 | config.SetMaxIncomingUnidirectionalStreamsToSend( |
| 281 | kDefaultMaxStreamsPerConnection / 2); |
Ryan Hamilton | 56b10c5d | 2018-05-11 13:40:16 | [diff] [blame] | 282 | |
| 283 | CryptoHandshakeMessage msg; |
Ryan Hamilton | 4aeec56 | 2019-05-17 21:22:52 | [diff] [blame] | 284 | config.ToHandshakeMessage( |
| 285 | &msg, session()->connection()->version().transport_version); |
Victor Vasiliev | 076657c | 2019-03-12 02:46:43 | [diff] [blame] | 286 | std::string error_details; |
Ryan Hamilton | 56b10c5d | 2018-05-11 13:40:16 | [diff] [blame] | 287 | const QuicErrorCode error = |
| 288 | session()->config()->ProcessPeerHello(msg, CLIENT, &error_details); |
| 289 | ASSERT_EQ(QUIC_NO_ERROR, error); |
| 290 | ASSERT_TRUE(session()->config()->negotiated()); |
| 291 | session()->OnConfigNegotiated(); |
| 292 | } |
| 293 | |
Ryan Hamilton | 9835e66 | 2018-08-02 05:36:27 | [diff] [blame] | 294 | } // namespace net |