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