blob: 6aa83d2c6a06f3586ec3c46f590408d7c38c1028 [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
QUICHE teama6ef0a62019-03-07 20:34:33 -05007#include "net/third_party/quiche/src/quic/core/quic_utils.h"
8#include "net/third_party/quiche/src/quic/core/tls_client_handshaker.h"
9#include "net/third_party/quiche/src/quic/core/tls_server_handshaker.h"
10#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
11#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050012#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
13#include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
14#include "net/third_party/quiche/src/quic/test_tools/fake_proof_source.h"
15#include "net/third_party/quiche/src/quic/test_tools/mock_quic_session_visitor.h"
16#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
17
18namespace quic {
19namespace test {
20namespace {
21
22using ::testing::_;
23
24class FakeProofVerifier : public ProofVerifier {
25 public:
26 FakeProofVerifier()
27 : verifier_(crypto_test_utils::ProofVerifierForTesting()) {}
28
29 QuicAsyncStatus VerifyProof(
vasilvvc48c8712019-03-11 13:38:16 -070030 const std::string& hostname,
QUICHE teama6ef0a62019-03-07 20:34:33 -050031 const uint16_t port,
vasilvvc48c8712019-03-11 13:38:16 -070032 const std::string& server_config,
QUICHE teama6ef0a62019-03-07 20:34:33 -050033 QuicTransportVersion quic_version,
34 QuicStringPiece chlo_hash,
vasilvvc48c8712019-03-11 13:38:16 -070035 const std::vector<std::string>& certs,
36 const std::string& cert_sct,
37 const std::string& signature,
QUICHE teama6ef0a62019-03-07 20:34:33 -050038 const ProofVerifyContext* context,
vasilvvc48c8712019-03-11 13:38:16 -070039 std::string* error_details,
QUICHE teama6ef0a62019-03-07 20:34:33 -050040 std::unique_ptr<ProofVerifyDetails>* details,
41 std::unique_ptr<ProofVerifierCallback> callback) override {
42 return verifier_->VerifyProof(
43 hostname, port, server_config, quic_version, chlo_hash, certs, cert_sct,
44 signature, context, error_details, details, std::move(callback));
45 }
46
47 QuicAsyncStatus VerifyCertChain(
vasilvvc48c8712019-03-11 13:38:16 -070048 const std::string& hostname,
49 const std::vector<std::string>& certs,
QUICHE teama6ef0a62019-03-07 20:34:33 -050050 const ProofVerifyContext* context,
vasilvvc48c8712019-03-11 13:38:16 -070051 std::string* error_details,
QUICHE teama6ef0a62019-03-07 20:34:33 -050052 std::unique_ptr<ProofVerifyDetails>* details,
53 std::unique_ptr<ProofVerifierCallback> callback) override {
54 if (!active_) {
55 return verifier_->VerifyCertChain(hostname, certs, context, error_details,
56 details, std::move(callback));
57 }
58 pending_ops_.push_back(QuicMakeUnique<VerifyChainPendingOp>(
59 hostname, certs, context, error_details, details, std::move(callback),
60 verifier_.get()));
61 return QUIC_PENDING;
62 }
63
64 std::unique_ptr<ProofVerifyContext> CreateDefaultContext() override {
65 return nullptr;
66 }
67
68 void Activate() { active_ = true; }
69
70 size_t NumPendingCallbacks() const { return pending_ops_.size(); }
71
72 void InvokePendingCallback(size_t n) {
73 CHECK(NumPendingCallbacks() > n);
74 pending_ops_[n]->Run();
75 auto it = pending_ops_.begin() + n;
76 pending_ops_.erase(it);
77 }
78
79 private:
80 // Implementation of ProofVerifierCallback that fails if the callback is ever
81 // run.
82 class FailingProofVerifierCallback : public ProofVerifierCallback {
83 public:
84 void Run(bool ok,
vasilvvc48c8712019-03-11 13:38:16 -070085 const std::string& error_details,
QUICHE teama6ef0a62019-03-07 20:34:33 -050086 std::unique_ptr<ProofVerifyDetails>* details) override {
87 FAIL();
88 }
89 };
90
91 class VerifyChainPendingOp {
92 public:
vasilvvc48c8712019-03-11 13:38:16 -070093 VerifyChainPendingOp(const std::string& hostname,
94 const std::vector<std::string>& certs,
QUICHE teama6ef0a62019-03-07 20:34:33 -050095 const ProofVerifyContext* context,
vasilvvc48c8712019-03-11 13:38:16 -070096 std::string* error_details,
QUICHE teama6ef0a62019-03-07 20:34:33 -050097 std::unique_ptr<ProofVerifyDetails>* details,
98 std::unique_ptr<ProofVerifierCallback> callback,
99 ProofVerifier* delegate)
100 : hostname_(hostname),
101 certs_(certs),
102 context_(context),
103 error_details_(error_details),
104 details_(details),
105 callback_(std::move(callback)),
106 delegate_(delegate) {}
107
108 void Run() {
109 // FakeProofVerifier depends on crypto_test_utils::ProofVerifierForTesting
110 // running synchronously. It passes a FailingProofVerifierCallback and
111 // runs the original callback after asserting that the verification ran
112 // synchronously.
113 QuicAsyncStatus status = delegate_->VerifyCertChain(
114 hostname_, certs_, context_, error_details_, details_,
115 QuicMakeUnique<FailingProofVerifierCallback>());
116 ASSERT_NE(status, QUIC_PENDING);
117 callback_->Run(status == QUIC_SUCCESS, *error_details_, details_);
118 }
119
120 private:
vasilvvc48c8712019-03-11 13:38:16 -0700121 std::string hostname_;
122 std::vector<std::string> certs_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500123 const ProofVerifyContext* context_;
vasilvvc48c8712019-03-11 13:38:16 -0700124 std::string* error_details_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500125 std::unique_ptr<ProofVerifyDetails>* details_;
126 std::unique_ptr<ProofVerifierCallback> callback_;
127 ProofVerifier* delegate_;
128 };
129
130 std::unique_ptr<ProofVerifier> verifier_;
131 bool active_ = false;
132 std::vector<std::unique_ptr<VerifyChainPendingOp>> pending_ops_;
133};
134
135class TestQuicCryptoStream : public QuicCryptoStream {
136 public:
137 explicit TestQuicCryptoStream(QuicSession* session)
138 : QuicCryptoStream(session) {}
139
140 ~TestQuicCryptoStream() override = default;
141
142 virtual TlsHandshaker* handshaker() const = 0;
143
144 bool encryption_established() const override {
145 return handshaker()->encryption_established();
146 }
147
148 bool handshake_confirmed() const override {
149 return handshaker()->handshake_confirmed();
150 }
151
152 const QuicCryptoNegotiatedParameters& crypto_negotiated_params()
153 const override {
154 return handshaker()->crypto_negotiated_params();
155 }
156
157 CryptoMessageParser* crypto_message_parser() override {
158 return handshaker()->crypto_message_parser();
159 }
160
161 void WriteCryptoData(EncryptionLevel level, QuicStringPiece data) override {
vasilvvc48c8712019-03-11 13:38:16 -0700162 pending_writes_.push_back(std::make_pair(std::string(data), level));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500163 }
164
vasilvvc48c8712019-03-11 13:38:16 -0700165 const std::vector<std::pair<std::string, EncryptionLevel>>& pending_writes() {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500166 return pending_writes_;
167 }
168
169 // Sends the pending frames to |stream| and clears the array of pending
170 // writes.
171 void SendCryptoMessagesToPeer(QuicCryptoStream* stream) {
172 QUIC_LOG(INFO) << "Sending " << pending_writes_.size() << " frames";
173 // This is a minimal re-implementation of QuicCryptoStream::OnDataAvailable.
174 // It doesn't work to call QuicStream::OnStreamFrame because
175 // QuicCryptoStream::OnDataAvailable currently (as an implementation detail)
176 // relies on the QuicConnection to know the EncryptionLevel to pass into
177 // CryptoMessageParser::ProcessInput. Since the crypto messages in this test
178 // never reach the framer or connection and never get encrypted/decrypted,
179 // QuicCryptoStream::OnDataAvailable isn't able to call ProcessInput with
180 // the correct EncryptionLevel. Instead, that can be short-circuited by
181 // directly calling ProcessInput here.
182 for (size_t i = 0; i < pending_writes_.size(); ++i) {
183 if (!stream->crypto_message_parser()->ProcessInput(
184 pending_writes_[i].first, pending_writes_[i].second)) {
185 CloseConnectionWithDetails(
186 stream->crypto_message_parser()->error(),
187 stream->crypto_message_parser()->error_detail());
188 break;
189 }
190 }
191 pending_writes_.clear();
192 }
193
194 private:
vasilvvc48c8712019-03-11 13:38:16 -0700195 std::vector<std::pair<std::string, EncryptionLevel>> pending_writes_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500196};
197
198class TestQuicCryptoClientStream : public TestQuicCryptoStream {
199 public:
200 explicit TestQuicCryptoClientStream(QuicSession* session)
201 : TestQuicCryptoStream(session),
202 proof_verifier_(new FakeProofVerifier),
203 ssl_ctx_(TlsClientHandshaker::CreateSslCtx()),
204 handshaker_(new TlsClientHandshaker(
205 this,
206 session,
207 QuicServerId("test.example.com", 443, false),
208 proof_verifier_.get(),
209 ssl_ctx_.get(),
210 crypto_test_utils::ProofVerifyContextForTesting(),
211 "quic-tester")) {}
212
213 ~TestQuicCryptoClientStream() override = default;
214
215 TlsHandshaker* handshaker() const override { return handshaker_.get(); }
216
217 bool CryptoConnect() { return handshaker_->CryptoConnect(); }
218
219 FakeProofVerifier* GetFakeProofVerifier() const {
220 return proof_verifier_.get();
221 }
222
223 private:
224 std::unique_ptr<FakeProofVerifier> proof_verifier_;
225 bssl::UniquePtr<SSL_CTX> ssl_ctx_;
226 std::unique_ptr<TlsClientHandshaker> handshaker_;
227};
228
229class TestQuicCryptoServerStream : public TestQuicCryptoStream {
230 public:
231 TestQuicCryptoServerStream(QuicSession* session,
232 FakeProofSource* proof_source)
233 : TestQuicCryptoStream(session),
234 proof_source_(proof_source),
235 ssl_ctx_(TlsServerHandshaker::CreateSslCtx()),
236 handshaker_(new TlsServerHandshaker(this,
237 session,
238 ssl_ctx_.get(),
239 proof_source_)) {}
240
241 ~TestQuicCryptoServerStream() override = default;
242
243 void CancelOutstandingCallbacks() {
244 handshaker_->CancelOutstandingCallbacks();
245 }
246
247 TlsHandshaker* handshaker() const override { return handshaker_.get(); }
248
249 FakeProofSource* GetFakeProofSource() const { return proof_source_; }
250
251 private:
252 FakeProofSource* proof_source_;
253 bssl::UniquePtr<SSL_CTX> ssl_ctx_;
254 std::unique_ptr<TlsServerHandshaker> handshaker_;
255};
256
257void ExchangeHandshakeMessages(TestQuicCryptoStream* client,
258 TestQuicCryptoStream* server) {
259 while (!client->pending_writes().empty() ||
260 !server->pending_writes().empty()) {
261 client->SendCryptoMessagesToPeer(server);
262 server->SendCryptoMessagesToPeer(client);
263 }
264}
265
266class TlsHandshakerTest : public QuicTest {
267 public:
268 TlsHandshakerTest()
269 : client_conn_(new MockQuicConnection(&conn_helper_,
270 &alarm_factory_,
271 Perspective::IS_CLIENT)),
272 server_conn_(new MockQuicConnection(&conn_helper_,
273 &alarm_factory_,
274 Perspective::IS_SERVER)),
275 client_session_(client_conn_, /*create_mock_crypto_stream=*/false),
276 server_session_(server_conn_, /*create_mock_crypto_stream=*/false) {
277 client_stream_ = new TestQuicCryptoClientStream(&client_session_);
278 client_session_.SetCryptoStream(client_stream_);
279 server_stream_ =
280 new TestQuicCryptoServerStream(&server_session_, &proof_source_);
281 server_session_.SetCryptoStream(server_stream_);
282 client_session_.Initialize();
283 server_session_.Initialize();
284 EXPECT_FALSE(client_stream_->encryption_established());
285 EXPECT_FALSE(client_stream_->handshake_confirmed());
286 EXPECT_FALSE(server_stream_->encryption_established());
287 EXPECT_FALSE(server_stream_->handshake_confirmed());
288 }
289
290 MockQuicConnectionHelper conn_helper_;
291 MockAlarmFactory alarm_factory_;
292 MockQuicConnection* client_conn_;
293 MockQuicConnection* server_conn_;
294 MockQuicSession client_session_;
295 MockQuicSession server_session_;
296
297 FakeProofSource proof_source_;
298 TestQuicCryptoClientStream* client_stream_;
299 TestQuicCryptoServerStream* server_stream_;
300};
301
302TEST_F(TlsHandshakerTest, CryptoHandshake) {
303 EXPECT_CALL(*client_conn_, CloseConnection(_, _, _)).Times(0);
304 EXPECT_CALL(*server_conn_, CloseConnection(_, _, _)).Times(0);
305 client_stream_->CryptoConnect();
306 ExchangeHandshakeMessages(client_stream_, server_stream_);
307
308 EXPECT_TRUE(client_stream_->handshake_confirmed());
309 EXPECT_TRUE(client_stream_->encryption_established());
310 EXPECT_TRUE(server_stream_->handshake_confirmed());
311 EXPECT_TRUE(server_stream_->encryption_established());
312}
313
314TEST_F(TlsHandshakerTest, HandshakeWithAsyncProofSource) {
315 EXPECT_CALL(*client_conn_, CloseConnection(_, _, _)).Times(0);
316 EXPECT_CALL(*server_conn_, CloseConnection(_, _, _)).Times(0);
317 // Enable FakeProofSource to capture call to ComputeTlsSignature and run it
318 // asynchronously.
319 FakeProofSource* proof_source = server_stream_->GetFakeProofSource();
320 proof_source->Activate();
321
322 // Start handshake.
323 client_stream_->CryptoConnect();
324 ExchangeHandshakeMessages(client_stream_, server_stream_);
325
326 ASSERT_EQ(proof_source->NumPendingCallbacks(), 1);
327 proof_source->InvokePendingCallback(0);
328
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, CancelPendingProofSource) {
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 server_stream_ = nullptr;
351
352 proof_source->InvokePendingCallback(0);
353}
354
355TEST_F(TlsHandshakerTest, HandshakeWithAsyncProofVerifier) {
356 EXPECT_CALL(*client_conn_, CloseConnection(_, _, _)).Times(0);
357 EXPECT_CALL(*server_conn_, CloseConnection(_, _, _)).Times(0);
358 // Enable FakeProofVerifier to capture call to VerifyCertChain and run it
359 // asynchronously.
360 FakeProofVerifier* proof_verifier = client_stream_->GetFakeProofVerifier();
361 proof_verifier->Activate();
362
363 // Start handshake.
364 client_stream_->CryptoConnect();
365 ExchangeHandshakeMessages(client_stream_, server_stream_);
366
367 ASSERT_EQ(proof_verifier->NumPendingCallbacks(), 1u);
368 proof_verifier->InvokePendingCallback(0);
369
370 ExchangeHandshakeMessages(client_stream_, server_stream_);
371
372 EXPECT_TRUE(client_stream_->handshake_confirmed());
373 EXPECT_TRUE(client_stream_->encryption_established());
374 EXPECT_TRUE(server_stream_->handshake_confirmed());
375 EXPECT_TRUE(server_stream_->encryption_established());
376}
377
378TEST_F(TlsHandshakerTest, ClientConnectionClosedOnTlsError) {
379 // Have client send ClientHello.
380 client_stream_->CryptoConnect();
381 EXPECT_CALL(*client_conn_, CloseConnection(QUIC_HANDSHAKE_FAILED, _, _));
382
383 // Send a zero-length ServerHello from server to client.
384 char bogus_handshake_message[] = {
385 // Handshake struct (RFC 8446 appendix B.3)
386 2, // HandshakeType server_hello
387 0, 0, 0, // uint24 length
388 };
389 server_stream_->WriteCryptoData(
QUICHE team6987b4a2019-03-15 16:23:04 -0700390 ENCRYPTION_INITIAL,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500391 QuicStringPiece(bogus_handshake_message,
392 QUIC_ARRAYSIZE(bogus_handshake_message)));
393 server_stream_->SendCryptoMessagesToPeer(client_stream_);
394
395 EXPECT_FALSE(client_stream_->handshake_confirmed());
396}
397
398TEST_F(TlsHandshakerTest, ServerConnectionClosedOnTlsError) {
399 EXPECT_CALL(*server_conn_, CloseConnection(QUIC_HANDSHAKE_FAILED, _, _));
400
401 // Send a zero-length ClientHello from client to server.
402 char bogus_handshake_message[] = {
403 // Handshake struct (RFC 8446 appendix B.3)
404 1, // HandshakeType client_hello
405 0, 0, 0, // uint24 length
406 };
407 client_stream_->WriteCryptoData(
QUICHE team6987b4a2019-03-15 16:23:04 -0700408 ENCRYPTION_INITIAL,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500409 QuicStringPiece(bogus_handshake_message,
410 QUIC_ARRAYSIZE(bogus_handshake_message)));
411 client_stream_->SendCryptoMessagesToPeer(server_stream_);
412
413 EXPECT_FALSE(server_stream_->handshake_confirmed());
414}
415
416} // namespace
417} // namespace test
418} // namespace quic