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" |
Ryan Hamilton | 56b10c5d | 2018-05-11 13:40:16 | [diff] [blame] | 9 | #include "net/third_party/quic/core/crypto/null_decrypter.h" |
| 10 | #include "net/third_party/quic/core/crypto/null_encrypter.h" |
| 11 | #include "net/third_party/quic/core/crypto/quic_decrypter.h" |
| 12 | #include "net/third_party/quic/core/crypto/quic_encrypter.h" |
Victor Vasiliev | c5b409c2 | 2018-07-24 12:23:46 | [diff] [blame] | 13 | #include "net/third_party/quic/core/http/quic_spdy_client_session_base.h" |
Ryan Hamilton | 56b10c5d | 2018-05-11 13:40:16 | [diff] [blame] | 14 | #include "net/third_party/quic/platform/api/quic_ptr_util.h" |
Ryan Hamilton | 56b10c5d | 2018-05-11 13:40:16 | [diff] [blame] | 15 | #include "net/third_party/quic/test_tools/quic_config_peer.h" |
| 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; |
| 23 | using quic::ENCRYPTION_INITIAL; |
| 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; |
| 45 | using quic::QuicString; |
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; |
| 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_) { |
| 110 | session()->connection()->SetDecrypter( |
| 111 | ENCRYPTION_INITIAL, |
| 112 | QuicMakeUnique<MockDecrypter>(Perspective::IS_CLIENT)); |
| 113 | session()->connection()->SetEncrypter( |
| 114 | ENCRYPTION_INITIAL, |
| 115 | QuicMakeUnique<MockEncrypter>(Perspective::IS_CLIENT)); |
| 116 | } else { |
| 117 | session()->connection()->SetDecrypter( |
| 118 | ENCRYPTION_INITIAL, |
| 119 | QuicMakeUnique<NullDecrypter>(Perspective::IS_CLIENT)); |
| 120 | session()->connection()->SetEncrypter( |
| 121 | ENCRYPTION_INITIAL, |
| 122 | QuicMakeUnique<NullEncrypter>(Perspective::IS_CLIENT)); |
| 123 | } |
| 124 | session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_INITIAL); |
| 125 | session()->OnCryptoHandshakeEvent( |
| 126 | QuicSession::ENCRYPTION_FIRST_ESTABLISHED); |
| 127 | break; |
| 128 | } |
| 129 | |
| 130 | case CONFIRM_HANDSHAKE: { |
| 131 | encryption_established_ = true; |
| 132 | handshake_confirmed_ = true; |
| 133 | crypto_negotiated_params_->key_exchange = kC255; |
| 134 | crypto_negotiated_params_->aead = kAESG; |
| 135 | if (proof_verify_details_) { |
| 136 | reinterpret_cast<QuicSpdyClientSessionBase*>(session()) |
| 137 | ->OnProofVerifyDetailsAvailable(*proof_verify_details_); |
| 138 | } |
| 139 | SetConfigNegotiated(); |
| 140 | if (use_mock_crypter_) { |
| 141 | session()->connection()->SetDecrypter( |
| 142 | ENCRYPTION_FORWARD_SECURE, |
| 143 | QuicMakeUnique<MockDecrypter>(Perspective::IS_CLIENT)); |
| 144 | session()->connection()->SetEncrypter( |
| 145 | ENCRYPTION_FORWARD_SECURE, |
| 146 | QuicMakeUnique<MockEncrypter>(Perspective::IS_CLIENT)); |
| 147 | } else { |
| 148 | session()->connection()->SetDecrypter( |
| 149 | ENCRYPTION_FORWARD_SECURE, |
| 150 | QuicMakeUnique<NullDecrypter>(Perspective::IS_CLIENT)); |
| 151 | session()->connection()->SetEncrypter( |
| 152 | ENCRYPTION_FORWARD_SECURE, |
| 153 | QuicMakeUnique<NullEncrypter>(Perspective::IS_CLIENT)); |
| 154 | } |
| 155 | session()->connection()->SetDefaultEncryptionLevel( |
| 156 | ENCRYPTION_FORWARD_SECURE); |
| 157 | session()->OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED); |
| 158 | break; |
| 159 | } |
| 160 | |
| 161 | case COLD_START: { |
| 162 | handshake_confirmed_ = false; |
| 163 | encryption_established_ = false; |
| 164 | break; |
| 165 | } |
| 166 | |
Zhongyi Shi | 87965942 | 2018-08-02 17:58:25 | [diff] [blame] | 167 | case COLD_START_WITH_CHLO_SENT: { |
| 168 | handshake_confirmed_ = false; |
| 169 | encryption_established_ = false; |
Zhongyi Shi | 5068bb0 | 2018-08-03 02:44:09 | [diff] [blame^] | 170 | SendHandshakeMessage(GetDummyCHLOMessage()); |
Ryan Hamilton | 56b10c5d | 2018-05-11 13:40:16 | [diff] [blame] | 171 | break; |
| 172 | } |
| 173 | } |
| 174 | |
| 175 | return session()->connection()->connected(); |
| 176 | } |
| 177 | |
| 178 | bool MockCryptoClientStream::encryption_established() const { |
| 179 | return encryption_established_; |
| 180 | } |
| 181 | |
| 182 | bool MockCryptoClientStream::handshake_confirmed() const { |
| 183 | return handshake_confirmed_; |
| 184 | } |
| 185 | |
| 186 | const QuicCryptoNegotiatedParameters& |
| 187 | MockCryptoClientStream::crypto_negotiated_params() const { |
| 188 | return *crypto_negotiated_params_; |
| 189 | } |
| 190 | |
| 191 | CryptoMessageParser* MockCryptoClientStream::crypto_message_parser() { |
| 192 | return &crypto_framer_; |
| 193 | } |
| 194 | |
| 195 | void MockCryptoClientStream::SendOnCryptoHandshakeEvent( |
| 196 | QuicSession::CryptoHandshakeEvent event) { |
| 197 | encryption_established_ = true; |
| 198 | if (event == QuicSession::HANDSHAKE_CONFIRMED) { |
| 199 | handshake_confirmed_ = true; |
| 200 | SetConfigNegotiated(); |
| 201 | if (use_mock_crypter_) { |
| 202 | session()->connection()->SetDecrypter( |
| 203 | ENCRYPTION_FORWARD_SECURE, |
| 204 | QuicMakeUnique<MockDecrypter>(Perspective::IS_CLIENT)); |
| 205 | session()->connection()->SetEncrypter( |
| 206 | ENCRYPTION_FORWARD_SECURE, |
| 207 | QuicMakeUnique<MockEncrypter>(Perspective::IS_CLIENT)); |
| 208 | } else { |
| 209 | session()->connection()->SetDecrypter( |
| 210 | ENCRYPTION_FORWARD_SECURE, |
| 211 | QuicMakeUnique<NullDecrypter>(Perspective::IS_CLIENT)); |
| 212 | session()->connection()->SetEncrypter( |
| 213 | ENCRYPTION_FORWARD_SECURE, |
| 214 | QuicMakeUnique<NullEncrypter>(Perspective::IS_CLIENT)); |
| 215 | } |
| 216 | session()->connection()->SetDefaultEncryptionLevel( |
| 217 | ENCRYPTION_FORWARD_SECURE); |
| 218 | } |
| 219 | session()->OnCryptoHandshakeEvent(event); |
| 220 | } |
| 221 | |
Zhongyi Shi | 87965942 | 2018-08-02 17:58:25 | [diff] [blame] | 222 | // static |
| 223 | CryptoHandshakeMessage MockCryptoClientStream::GetDummyCHLOMessage() { |
| 224 | CryptoHandshakeMessage message; |
| 225 | message.set_tag(quic::kCHLO); |
| 226 | return message; |
| 227 | } |
| 228 | |
Ryan Hamilton | 56b10c5d | 2018-05-11 13:40:16 | [diff] [blame] | 229 | void MockCryptoClientStream::SetConfigNegotiated() { |
| 230 | ASSERT_FALSE(session()->config()->negotiated()); |
| 231 | QuicTagVector cgst; |
| 232 | // TODO(rtenneti): Enable the following code after BBR code is checked in. |
| 233 | #if 0 |
| 234 | cgst.push_back(kTBBR); |
| 235 | #endif |
| 236 | cgst.push_back(kQBIC); |
| 237 | QuicConfig config(config_); |
| 238 | config.SetIdleNetworkTimeout( |
| 239 | QuicTime::Delta::FromSeconds(2 * kMaximumIdleTimeoutSecs), |
| 240 | QuicTime::Delta::FromSeconds(kMaximumIdleTimeoutSecs)); |
Ryan Hamilton | 56b10c5d | 2018-05-11 13:40:16 | [diff] [blame] | 241 | config.SetBytesForConnectionIdToSend(PACKET_8BYTE_CONNECTION_ID); |
| 242 | config.SetMaxIncomingDynamicStreamsToSend(kDefaultMaxStreamsPerConnection / |
| 243 | 2); |
| 244 | |
| 245 | CryptoHandshakeMessage msg; |
| 246 | config.ToHandshakeMessage(&msg); |
Ryan Hamilton | ccfa84a | 2018-07-24 00:38:08 | [diff] [blame] | 247 | QuicString error_details; |
Ryan Hamilton | 56b10c5d | 2018-05-11 13:40:16 | [diff] [blame] | 248 | const QuicErrorCode error = |
| 249 | session()->config()->ProcessPeerHello(msg, CLIENT, &error_details); |
| 250 | ASSERT_EQ(QUIC_NO_ERROR, error); |
| 251 | ASSERT_TRUE(session()->config()->negotiated()); |
| 252 | session()->OnConfigNegotiated(); |
| 253 | } |
| 254 | |
Ryan Hamilton | 9835e66 | 2018-08-02 05:36:27 | [diff] [blame] | 255 | } // namespace net |