blob: 35efa9f2e950bb115bd5a376b5e3cc07f3136686 [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// Copyright (c) 2017 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
vasilvv872e7a32019-03-12 16:42:44 -07005#include <string>
6
nharper6ebe83b2019-06-13 17:43:52 -07007#include "net/third_party/quiche/src/quic/core/crypto/tls_client_connection.h"
8#include "net/third_party/quiche/src/quic/core/crypto/tls_server_connection.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -05009#include "net/third_party/quiche/src/quic/core/quic_utils.h"
10#include "net/third_party/quiche/src/quic/core/tls_client_handshaker.h"
11#include "net/third_party/quiche/src/quic/core/tls_server_handshaker.h"
12#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
13#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050014#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
15#include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
16#include "net/third_party/quiche/src/quic/test_tools/fake_proof_source.h"
17#include "net/third_party/quiche/src/quic/test_tools/mock_quic_session_visitor.h"
18#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
19
20namespace quic {
21namespace test {
22namespace {
23
24using ::testing::_;
25
26class FakeProofVerifier : public ProofVerifier {
27 public:
28 FakeProofVerifier()
29 : verifier_(crypto_test_utils::ProofVerifierForTesting()) {}
30
31 QuicAsyncStatus VerifyProof(
vasilvvc48c8712019-03-11 13:38:16 -070032 const std::string& hostname,
QUICHE teama6ef0a62019-03-07 20:34:33 -050033 const uint16_t port,
vasilvvc48c8712019-03-11 13:38:16 -070034 const std::string& server_config,
QUICHE teama6ef0a62019-03-07 20:34:33 -050035 QuicTransportVersion quic_version,
36 QuicStringPiece chlo_hash,
vasilvvc48c8712019-03-11 13:38:16 -070037 const std::vector<std::string>& certs,
38 const std::string& cert_sct,
39 const std::string& signature,
QUICHE teama6ef0a62019-03-07 20:34:33 -050040 const ProofVerifyContext* context,
vasilvvc48c8712019-03-11 13:38:16 -070041 std::string* error_details,
QUICHE teama6ef0a62019-03-07 20:34:33 -050042 std::unique_ptr<ProofVerifyDetails>* details,
43 std::unique_ptr<ProofVerifierCallback> callback) override {
44 return verifier_->VerifyProof(
45 hostname, port, server_config, quic_version, chlo_hash, certs, cert_sct,
46 signature, context, error_details, details, std::move(callback));
47 }
48
49 QuicAsyncStatus VerifyCertChain(
vasilvvc48c8712019-03-11 13:38:16 -070050 const std::string& hostname,
51 const std::vector<std::string>& certs,
QUICHE team38c190b2019-05-08 09:12:01 -070052 const std::string& ocsp_response,
53 const std::string& cert_sct,
QUICHE teama6ef0a62019-03-07 20:34:33 -050054 const ProofVerifyContext* context,
vasilvvc48c8712019-03-11 13:38:16 -070055 std::string* error_details,
QUICHE teama6ef0a62019-03-07 20:34:33 -050056 std::unique_ptr<ProofVerifyDetails>* details,
57 std::unique_ptr<ProofVerifierCallback> callback) override {
58 if (!active_) {
QUICHE team38c190b2019-05-08 09:12:01 -070059 return verifier_->VerifyCertChain(hostname, certs, ocsp_response,
60 cert_sct, context, error_details,
QUICHE teama6ef0a62019-03-07 20:34:33 -050061 details, std::move(callback));
62 }
63 pending_ops_.push_back(QuicMakeUnique<VerifyChainPendingOp>(
QUICHE team38c190b2019-05-08 09:12:01 -070064 hostname, certs, ocsp_response, cert_sct, context, error_details,
65 details, std::move(callback), verifier_.get()));
QUICHE teama6ef0a62019-03-07 20:34:33 -050066 return QUIC_PENDING;
67 }
68
69 std::unique_ptr<ProofVerifyContext> CreateDefaultContext() override {
70 return nullptr;
71 }
72
73 void Activate() { active_ = true; }
74
75 size_t NumPendingCallbacks() const { return pending_ops_.size(); }
76
77 void InvokePendingCallback(size_t n) {
78 CHECK(NumPendingCallbacks() > n);
79 pending_ops_[n]->Run();
80 auto it = pending_ops_.begin() + n;
81 pending_ops_.erase(it);
82 }
83
84 private:
85 // Implementation of ProofVerifierCallback that fails if the callback is ever
86 // run.
87 class FailingProofVerifierCallback : public ProofVerifierCallback {
88 public:
dschinazi17d42422019-06-18 16:35:07 -070089 void Run(bool /*ok*/,
90 const std::string& /*error_details*/,
91 std::unique_ptr<ProofVerifyDetails>* /*details*/) override {
QUICHE teama6ef0a62019-03-07 20:34:33 -050092 FAIL();
93 }
94 };
95
96 class VerifyChainPendingOp {
97 public:
vasilvvc48c8712019-03-11 13:38:16 -070098 VerifyChainPendingOp(const std::string& hostname,
99 const std::vector<std::string>& certs,
QUICHE team38c190b2019-05-08 09:12:01 -0700100 const std::string& ocsp_response,
101 const std::string& cert_sct,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500102 const ProofVerifyContext* context,
vasilvvc48c8712019-03-11 13:38:16 -0700103 std::string* error_details,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500104 std::unique_ptr<ProofVerifyDetails>* details,
105 std::unique_ptr<ProofVerifierCallback> callback,
106 ProofVerifier* delegate)
107 : hostname_(hostname),
108 certs_(certs),
QUICHE team38c190b2019-05-08 09:12:01 -0700109 ocsp_response_(ocsp_response),
110 cert_sct_(cert_sct),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500111 context_(context),
112 error_details_(error_details),
113 details_(details),
114 callback_(std::move(callback)),
115 delegate_(delegate) {}
116
117 void Run() {
118 // FakeProofVerifier depends on crypto_test_utils::ProofVerifierForTesting
119 // running synchronously. It passes a FailingProofVerifierCallback and
120 // runs the original callback after asserting that the verification ran
121 // synchronously.
122 QuicAsyncStatus status = delegate_->VerifyCertChain(
QUICHE team38c190b2019-05-08 09:12:01 -0700123 hostname_, certs_, ocsp_response_, cert_sct_, context_,
124 error_details_, details_,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500125 QuicMakeUnique<FailingProofVerifierCallback>());
126 ASSERT_NE(status, QUIC_PENDING);
127 callback_->Run(status == QUIC_SUCCESS, *error_details_, details_);
128 }
129
130 private:
vasilvvc48c8712019-03-11 13:38:16 -0700131 std::string hostname_;
132 std::vector<std::string> certs_;
QUICHE team38c190b2019-05-08 09:12:01 -0700133 std::string ocsp_response_;
134 std::string cert_sct_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500135 const ProofVerifyContext* context_;
vasilvvc48c8712019-03-11 13:38:16 -0700136 std::string* error_details_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500137 std::unique_ptr<ProofVerifyDetails>* details_;
138 std::unique_ptr<ProofVerifierCallback> callback_;
139 ProofVerifier* delegate_;
140 };
141
142 std::unique_ptr<ProofVerifier> verifier_;
143 bool active_ = false;
144 std::vector<std::unique_ptr<VerifyChainPendingOp>> pending_ops_;
145};
146
147class TestQuicCryptoStream : public QuicCryptoStream {
148 public:
149 explicit TestQuicCryptoStream(QuicSession* session)
150 : QuicCryptoStream(session) {}
151
152 ~TestQuicCryptoStream() override = default;
153
154 virtual TlsHandshaker* handshaker() const = 0;
155
156 bool encryption_established() const override {
157 return handshaker()->encryption_established();
158 }
159
160 bool handshake_confirmed() const override {
161 return handshaker()->handshake_confirmed();
162 }
163
164 const QuicCryptoNegotiatedParameters& crypto_negotiated_params()
165 const override {
166 return handshaker()->crypto_negotiated_params();
167 }
168
169 CryptoMessageParser* crypto_message_parser() override {
170 return handshaker()->crypto_message_parser();
171 }
172
173 void WriteCryptoData(EncryptionLevel level, QuicStringPiece data) override {
vasilvvc48c8712019-03-11 13:38:16 -0700174 pending_writes_.push_back(std::make_pair(std::string(data), level));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500175 }
176
vasilvvc48c8712019-03-11 13:38:16 -0700177 const std::vector<std::pair<std::string, EncryptionLevel>>& pending_writes() {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500178 return pending_writes_;
179 }
180
181 // Sends the pending frames to |stream| and clears the array of pending
182 // writes.
183 void SendCryptoMessagesToPeer(QuicCryptoStream* stream) {
184 QUIC_LOG(INFO) << "Sending " << pending_writes_.size() << " frames";
185 // This is a minimal re-implementation of QuicCryptoStream::OnDataAvailable.
186 // It doesn't work to call QuicStream::OnStreamFrame because
187 // QuicCryptoStream::OnDataAvailable currently (as an implementation detail)
188 // relies on the QuicConnection to know the EncryptionLevel to pass into
189 // CryptoMessageParser::ProcessInput. Since the crypto messages in this test
190 // never reach the framer or connection and never get encrypted/decrypted,
191 // QuicCryptoStream::OnDataAvailable isn't able to call ProcessInput with
192 // the correct EncryptionLevel. Instead, that can be short-circuited by
193 // directly calling ProcessInput here.
194 for (size_t i = 0; i < pending_writes_.size(); ++i) {
195 if (!stream->crypto_message_parser()->ProcessInput(
196 pending_writes_[i].first, pending_writes_[i].second)) {
197 CloseConnectionWithDetails(
198 stream->crypto_message_parser()->error(),
199 stream->crypto_message_parser()->error_detail());
200 break;
201 }
202 }
203 pending_writes_.clear();
204 }
205
206 private:
vasilvvc48c8712019-03-11 13:38:16 -0700207 std::vector<std::pair<std::string, EncryptionLevel>> pending_writes_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500208};
209
210class TestQuicCryptoClientStream : public TestQuicCryptoStream {
211 public:
212 explicit TestQuicCryptoClientStream(QuicSession* session)
213 : TestQuicCryptoStream(session),
214 proof_verifier_(new FakeProofVerifier),
nharper6ebe83b2019-06-13 17:43:52 -0700215 ssl_ctx_(TlsClientConnection::CreateSslCtx()),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500216 handshaker_(new TlsClientHandshaker(
217 this,
218 session,
219 QuicServerId("test.example.com", 443, false),
220 proof_verifier_.get(),
221 ssl_ctx_.get(),
222 crypto_test_utils::ProofVerifyContextForTesting(),
223 "quic-tester")) {}
224
225 ~TestQuicCryptoClientStream() override = default;
226
227 TlsHandshaker* handshaker() const override { return handshaker_.get(); }
228
229 bool CryptoConnect() { return handshaker_->CryptoConnect(); }
230
231 FakeProofVerifier* GetFakeProofVerifier() const {
232 return proof_verifier_.get();
233 }
234
235 private:
236 std::unique_ptr<FakeProofVerifier> proof_verifier_;
237 bssl::UniquePtr<SSL_CTX> ssl_ctx_;
238 std::unique_ptr<TlsClientHandshaker> handshaker_;
239};
240
241class TestQuicCryptoServerStream : public TestQuicCryptoStream {
242 public:
243 TestQuicCryptoServerStream(QuicSession* session,
244 FakeProofSource* proof_source)
245 : TestQuicCryptoStream(session),
246 proof_source_(proof_source),
nharper6ebe83b2019-06-13 17:43:52 -0700247 ssl_ctx_(TlsServerConnection::CreateSslCtx()),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500248 handshaker_(new TlsServerHandshaker(this,
249 session,
250 ssl_ctx_.get(),
251 proof_source_)) {}
252
253 ~TestQuicCryptoServerStream() override = default;
254
255 void CancelOutstandingCallbacks() {
256 handshaker_->CancelOutstandingCallbacks();
257 }
258
259 TlsHandshaker* handshaker() const override { return handshaker_.get(); }
260
261 FakeProofSource* GetFakeProofSource() const { return proof_source_; }
262
263 private:
264 FakeProofSource* proof_source_;
265 bssl::UniquePtr<SSL_CTX> ssl_ctx_;
266 std::unique_ptr<TlsServerHandshaker> handshaker_;
267};
268
269void ExchangeHandshakeMessages(TestQuicCryptoStream* client,
270 TestQuicCryptoStream* server) {
271 while (!client->pending_writes().empty() ||
272 !server->pending_writes().empty()) {
273 client->SendCryptoMessagesToPeer(server);
274 server->SendCryptoMessagesToPeer(client);
275 }
276}
277
278class TlsHandshakerTest : public QuicTest {
279 public:
280 TlsHandshakerTest()
nharper107ba5f2019-07-02 21:33:39 -0700281 : client_conn_(new MockQuicConnection(
282 &conn_helper_,
283 &alarm_factory_,
284 Perspective::IS_CLIENT,
285 {ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_99)})),
286 server_conn_(new MockQuicConnection(
287 &conn_helper_,
288 &alarm_factory_,
289 Perspective::IS_SERVER,
290 {ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_99)})),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500291 client_session_(client_conn_, /*create_mock_crypto_stream=*/false),
292 server_session_(server_conn_, /*create_mock_crypto_stream=*/false) {
nharper107ba5f2019-07-02 21:33:39 -0700293 SetQuicFlag(FLAGS_quic_supports_tls_handshake, true);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500294 client_stream_ = new TestQuicCryptoClientStream(&client_session_);
295 client_session_.SetCryptoStream(client_stream_);
296 server_stream_ =
297 new TestQuicCryptoServerStream(&server_session_, &proof_source_);
298 server_session_.SetCryptoStream(server_stream_);
299 client_session_.Initialize();
300 server_session_.Initialize();
301 EXPECT_FALSE(client_stream_->encryption_established());
302 EXPECT_FALSE(client_stream_->handshake_confirmed());
303 EXPECT_FALSE(server_stream_->encryption_established());
304 EXPECT_FALSE(server_stream_->handshake_confirmed());
305 }
306
307 MockQuicConnectionHelper conn_helper_;
308 MockAlarmFactory alarm_factory_;
309 MockQuicConnection* client_conn_;
310 MockQuicConnection* server_conn_;
311 MockQuicSession client_session_;
312 MockQuicSession server_session_;
313
314 FakeProofSource proof_source_;
315 TestQuicCryptoClientStream* client_stream_;
316 TestQuicCryptoServerStream* server_stream_;
317};
318
319TEST_F(TlsHandshakerTest, CryptoHandshake) {
320 EXPECT_CALL(*client_conn_, CloseConnection(_, _, _)).Times(0);
321 EXPECT_CALL(*server_conn_, CloseConnection(_, _, _)).Times(0);
nharper8a72e4f2019-08-13 19:17:08 -0700322 EXPECT_CALL(client_session_,
renjietangea71d6f2019-08-19 12:22:28 -0700323 OnCryptoHandshakeEvent(QuicSession::ENCRYPTION_ESTABLISHED));
nharper8a72e4f2019-08-13 19:17:08 -0700324 EXPECT_CALL(client_session_,
325 OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED));
326 EXPECT_CALL(server_session_,
327 OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500328 client_stream_->CryptoConnect();
329 ExchangeHandshakeMessages(client_stream_, server_stream_);
330
331 EXPECT_TRUE(client_stream_->handshake_confirmed());
332 EXPECT_TRUE(client_stream_->encryption_established());
333 EXPECT_TRUE(server_stream_->handshake_confirmed());
334 EXPECT_TRUE(server_stream_->encryption_established());
335}
336
337TEST_F(TlsHandshakerTest, HandshakeWithAsyncProofSource) {
338 EXPECT_CALL(*client_conn_, CloseConnection(_, _, _)).Times(0);
339 EXPECT_CALL(*server_conn_, CloseConnection(_, _, _)).Times(0);
340 // Enable FakeProofSource to capture call to ComputeTlsSignature and run it
341 // asynchronously.
342 FakeProofSource* proof_source = server_stream_->GetFakeProofSource();
343 proof_source->Activate();
344
345 // Start handshake.
346 client_stream_->CryptoConnect();
347 ExchangeHandshakeMessages(client_stream_, server_stream_);
348
349 ASSERT_EQ(proof_source->NumPendingCallbacks(), 1);
350 proof_source->InvokePendingCallback(0);
351
352 ExchangeHandshakeMessages(client_stream_, server_stream_);
353
354 EXPECT_TRUE(client_stream_->handshake_confirmed());
355 EXPECT_TRUE(client_stream_->encryption_established());
356 EXPECT_TRUE(server_stream_->handshake_confirmed());
357 EXPECT_TRUE(server_stream_->encryption_established());
358}
359
360TEST_F(TlsHandshakerTest, CancelPendingProofSource) {
361 EXPECT_CALL(*client_conn_, CloseConnection(_, _, _)).Times(0);
362 EXPECT_CALL(*server_conn_, CloseConnection(_, _, _)).Times(0);
363 // Enable FakeProofSource to capture call to ComputeTlsSignature and run it
364 // asynchronously.
365 FakeProofSource* proof_source = server_stream_->GetFakeProofSource();
366 proof_source->Activate();
367
368 // Start handshake.
369 client_stream_->CryptoConnect();
370 ExchangeHandshakeMessages(client_stream_, server_stream_);
371
372 ASSERT_EQ(proof_source->NumPendingCallbacks(), 1);
373 server_stream_ = nullptr;
374
375 proof_source->InvokePendingCallback(0);
376}
377
378TEST_F(TlsHandshakerTest, HandshakeWithAsyncProofVerifier) {
379 EXPECT_CALL(*client_conn_, CloseConnection(_, _, _)).Times(0);
380 EXPECT_CALL(*server_conn_, CloseConnection(_, _, _)).Times(0);
381 // Enable FakeProofVerifier to capture call to VerifyCertChain and run it
382 // asynchronously.
383 FakeProofVerifier* proof_verifier = client_stream_->GetFakeProofVerifier();
384 proof_verifier->Activate();
385
386 // Start handshake.
387 client_stream_->CryptoConnect();
388 ExchangeHandshakeMessages(client_stream_, server_stream_);
389
390 ASSERT_EQ(proof_verifier->NumPendingCallbacks(), 1u);
391 proof_verifier->InvokePendingCallback(0);
392
393 ExchangeHandshakeMessages(client_stream_, server_stream_);
394
395 EXPECT_TRUE(client_stream_->handshake_confirmed());
396 EXPECT_TRUE(client_stream_->encryption_established());
397 EXPECT_TRUE(server_stream_->handshake_confirmed());
398 EXPECT_TRUE(server_stream_->encryption_established());
399}
400
401TEST_F(TlsHandshakerTest, ClientConnectionClosedOnTlsError) {
402 // Have client send ClientHello.
403 client_stream_->CryptoConnect();
404 EXPECT_CALL(*client_conn_, CloseConnection(QUIC_HANDSHAKE_FAILED, _, _));
405
406 // Send a zero-length ServerHello from server to client.
407 char bogus_handshake_message[] = {
408 // Handshake struct (RFC 8446 appendix B.3)
409 2, // HandshakeType server_hello
410 0, 0, 0, // uint24 length
411 };
412 server_stream_->WriteCryptoData(
QUICHE team6987b4a2019-03-15 16:23:04 -0700413 ENCRYPTION_INITIAL,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500414 QuicStringPiece(bogus_handshake_message,
415 QUIC_ARRAYSIZE(bogus_handshake_message)));
416 server_stream_->SendCryptoMessagesToPeer(client_stream_);
417
418 EXPECT_FALSE(client_stream_->handshake_confirmed());
419}
420
421TEST_F(TlsHandshakerTest, ServerConnectionClosedOnTlsError) {
422 EXPECT_CALL(*server_conn_, CloseConnection(QUIC_HANDSHAKE_FAILED, _, _));
423
424 // Send a zero-length ClientHello from client to server.
425 char bogus_handshake_message[] = {
426 // Handshake struct (RFC 8446 appendix B.3)
427 1, // HandshakeType client_hello
428 0, 0, 0, // uint24 length
429 };
430 client_stream_->WriteCryptoData(
QUICHE team6987b4a2019-03-15 16:23:04 -0700431 ENCRYPTION_INITIAL,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500432 QuicStringPiece(bogus_handshake_message,
433 QUIC_ARRAYSIZE(bogus_handshake_message)));
434 client_stream_->SendCryptoMessagesToPeer(server_stream_);
435
436 EXPECT_FALSE(server_stream_->handshake_confirmed());
437}
438
dschinazi91453642019-08-01 11:12:15 -0700439TEST_F(TlsHandshakerTest, ClientNotSendingALPN) {
440 static std::string kTestClientNoAlpn = "";
441 quic_alpn_override_on_client_for_tests = &kTestClientNoAlpn;
442 EXPECT_CALL(*client_conn_, CloseConnection(QUIC_HANDSHAKE_FAILED,
443 "Server did not select ALPN", _));
444 EXPECT_CALL(*server_conn_,
445 CloseConnection(QUIC_HANDSHAKE_FAILED,
446 "Server did not receive a known ALPN", _));
447 client_stream_->CryptoConnect();
448 ExchangeHandshakeMessages(client_stream_, server_stream_);
449
450 EXPECT_FALSE(client_stream_->handshake_confirmed());
451 EXPECT_FALSE(client_stream_->encryption_established());
452 EXPECT_FALSE(server_stream_->handshake_confirmed());
453 EXPECT_FALSE(server_stream_->encryption_established());
454 quic_alpn_override_on_client_for_tests = nullptr;
455}
456
457TEST_F(TlsHandshakerTest, ClientSendingBadALPN) {
458 static std::string kTestBadClientAlpn = "bad-client-alpn";
459 quic_alpn_override_on_client_for_tests = &kTestBadClientAlpn;
460 EXPECT_CALL(*client_conn_, CloseConnection(QUIC_HANDSHAKE_FAILED,
461 "Server did not select ALPN", _));
462 EXPECT_CALL(*server_conn_,
463 CloseConnection(QUIC_HANDSHAKE_FAILED,
464 "Server did not receive a known ALPN", _));
465 client_stream_->CryptoConnect();
466 ExchangeHandshakeMessages(client_stream_, server_stream_);
467
468 EXPECT_FALSE(client_stream_->handshake_confirmed());
469 EXPECT_FALSE(client_stream_->encryption_established());
470 EXPECT_FALSE(server_stream_->handshake_confirmed());
471 EXPECT_FALSE(server_stream_->encryption_established());
472 quic_alpn_override_on_client_for_tests = nullptr;
473}
474
QUICHE teama6ef0a62019-03-07 20:34:33 -0500475} // namespace
476} // namespace test
477} // namespace quic