1 // Copyright (c) 2012 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
5 #include "quiche/quic/core/quic_crypto_client_handshaker.h"
6
7 #include <utility>
8
9 #include "absl/strings/string_view.h"
10 #include "quiche/quic/core/proto/crypto_server_config_proto.h"
11 #include "quiche/quic/platform/api/quic_test.h"
12 #include "quiche/quic/test_tools/quic_test_utils.h"
13
14 namespace quic::test {
15 namespace {
16
17 class TestProofHandler : public QuicCryptoClientStream::ProofHandler {
18 public:
~TestProofHandler()19 ~TestProofHandler() override {}
OnProofValid(const QuicCryptoClientConfig::CachedState &)20 void OnProofValid(
21 const QuicCryptoClientConfig::CachedState& /*cached*/) override {}
OnProofVerifyDetailsAvailable(const ProofVerifyDetails &)22 void OnProofVerifyDetailsAvailable(
23 const ProofVerifyDetails& /*verify_details*/) override {}
24 };
25
26 class InsecureProofVerifier : public ProofVerifier {
27 public:
InsecureProofVerifier()28 InsecureProofVerifier() {}
~InsecureProofVerifier()29 ~InsecureProofVerifier() override {}
30
31 // ProofVerifier override.
VerifyProof(const std::string &,const uint16_t,const std::string &,QuicTransportVersion,absl::string_view,const std::vector<std::string> &,const std::string &,const std::string &,const ProofVerifyContext *,std::string *,std::unique_ptr<ProofVerifyDetails> *,std::unique_ptr<ProofVerifierCallback>)32 QuicAsyncStatus VerifyProof(
33 const std::string& /*hostname*/, const uint16_t /*port*/,
34 const std::string& /*server_config*/,
35 QuicTransportVersion /*transport_version*/,
36 absl::string_view /*chlo_hash*/,
37 const std::vector<std::string>& /*certs*/,
38 const std::string& /*cert_sct*/, const std::string& /*signature*/,
39 const ProofVerifyContext* /*context*/, std::string* /*error_details*/,
40 std::unique_ptr<ProofVerifyDetails>* /*verify_details*/,
41 std::unique_ptr<ProofVerifierCallback> /*callback*/) override {
42 return QUIC_SUCCESS;
43 }
44
VerifyCertChain(const std::string &,const uint16_t,const std::vector<std::string> &,const std::string &,const std::string &,const ProofVerifyContext *,std::string *,std::unique_ptr<ProofVerifyDetails> *,uint8_t *,std::unique_ptr<ProofVerifierCallback>)45 QuicAsyncStatus VerifyCertChain(
46 const std::string& /*hostname*/, const uint16_t /*port*/,
47 const std::vector<std::string>& /*certs*/,
48 const std::string& /*ocsp_response*/, const std::string& /*cert_sct*/,
49 const ProofVerifyContext* /*context*/, std::string* /*error_details*/,
50 std::unique_ptr<ProofVerifyDetails>* /*details*/, uint8_t* /*out_alert*/,
51 std::unique_ptr<ProofVerifierCallback> /*callback*/) override {
52 return QUIC_SUCCESS;
53 }
54
CreateDefaultContext()55 std::unique_ptr<ProofVerifyContext> CreateDefaultContext() override {
56 return nullptr;
57 }
58 };
59
60 class DummyProofSource : public ProofSource {
61 public:
DummyProofSource()62 DummyProofSource() {}
~DummyProofSource()63 ~DummyProofSource() override {}
64
65 // ProofSource override.
GetProof(const QuicSocketAddress & server_address,const QuicSocketAddress & client_address,const std::string & hostname,const std::string &,QuicTransportVersion,absl::string_view,std::unique_ptr<Callback> callback)66 void GetProof(const QuicSocketAddress& server_address,
67 const QuicSocketAddress& client_address,
68 const std::string& hostname,
69 const std::string& /*server_config*/,
70 QuicTransportVersion /*transport_version*/,
71 absl::string_view /*chlo_hash*/,
72 std::unique_ptr<Callback> callback) override {
73 bool cert_matched_sni;
74 quiche::QuicheReferenceCountedPointer<ProofSource::Chain> chain =
75 GetCertChain(server_address, client_address, hostname,
76 &cert_matched_sni);
77 QuicCryptoProof proof;
78 proof.signature = "Dummy signature";
79 proof.leaf_cert_scts = "Dummy timestamp";
80 proof.cert_matched_sni = cert_matched_sni;
81 callback->Run(true, chain, proof, /*details=*/nullptr);
82 }
83
GetCertChain(const QuicSocketAddress &,const QuicSocketAddress &,const std::string &,bool *)84 quiche::QuicheReferenceCountedPointer<Chain> GetCertChain(
85 const QuicSocketAddress& /*server_address*/,
86 const QuicSocketAddress& /*client_address*/,
87 const std::string& /*hostname*/, bool* /*cert_matched_sni*/) override {
88 std::vector<std::string> certs;
89 certs.push_back("Dummy cert");
90 return quiche::QuicheReferenceCountedPointer<ProofSource::Chain>(
91 new ProofSource::Chain(certs));
92 }
93
ComputeTlsSignature(const QuicSocketAddress &,const QuicSocketAddress &,const std::string &,uint16_t,absl::string_view,std::unique_ptr<SignatureCallback> callback)94 void ComputeTlsSignature(
95 const QuicSocketAddress& /*server_address*/,
96 const QuicSocketAddress& /*client_address*/,
97 const std::string& /*hostname*/, uint16_t /*signature_algorit*/,
98 absl::string_view /*in*/,
99 std::unique_ptr<SignatureCallback> callback) override {
100 callback->Run(true, "Dummy signature", /*details=*/nullptr);
101 }
102
SupportedTlsSignatureAlgorithms() const103 absl::InlinedVector<uint16_t, 8> SupportedTlsSignatureAlgorithms()
104 const override {
105 return {};
106 }
107
GetTicketCrypter()108 TicketCrypter* GetTicketCrypter() override { return nullptr; }
109 };
110
111 class Handshaker : public QuicCryptoClientHandshaker {
112 public:
Handshaker(const QuicServerId & server_id,QuicCryptoClientStream * stream,QuicSession * session,std::unique_ptr<ProofVerifyContext> verify_context,QuicCryptoClientConfig * crypto_config,QuicCryptoClientStream::ProofHandler * proof_handler)113 Handshaker(const QuicServerId& server_id, QuicCryptoClientStream* stream,
114 QuicSession* session,
115 std::unique_ptr<ProofVerifyContext> verify_context,
116 QuicCryptoClientConfig* crypto_config,
117 QuicCryptoClientStream::ProofHandler* proof_handler)
118 : QuicCryptoClientHandshaker(server_id, stream, session,
119 std::move(verify_context), crypto_config,
120 proof_handler) {}
121
DoSendCHLOTest(QuicCryptoClientConfig::CachedState * cached)122 void DoSendCHLOTest(QuicCryptoClientConfig::CachedState* cached) {
123 QuicCryptoClientHandshaker::DoSendCHLO(cached);
124 }
125 };
126
127 class QuicCryptoClientHandshakerTest
128 : public QuicTestWithParam<ParsedQuicVersion> {
129 protected:
QuicCryptoClientHandshakerTest()130 QuicCryptoClientHandshakerTest()
131 : version_(GetParam()),
132 proof_handler_(),
133 helper_(),
134 alarm_factory_(),
135 server_id_("host", 123),
136 connection_(new test::MockQuicConnection(
137 &helper_, &alarm_factory_, Perspective::IS_CLIENT, {version_})),
138 session_(connection_, false),
139 crypto_client_config_(std::make_unique<InsecureProofVerifier>()),
140 client_stream_(
141 new QuicCryptoClientStream(server_id_, &session_, nullptr,
142 &crypto_client_config_, &proof_handler_,
143 /*has_application_state = */ false)),
144 handshaker_(server_id_, client_stream_, &session_, nullptr,
145 &crypto_client_config_, &proof_handler_),
146 state_() {
147 // Session takes the ownership of the client stream! (but handshaker also
148 // takes a reference to it, but doesn't take the ownership).
149 session_.SetCryptoStream(client_stream_);
150 session_.Initialize();
151 }
152
InitializeServerParametersToEnableFullHello()153 void InitializeServerParametersToEnableFullHello() {
154 QuicCryptoServerConfig::ConfigOptions options;
155 QuicServerConfigProtobuf config = QuicCryptoServerConfig::GenerateConfig(
156 helper_.GetRandomGenerator(), helper_.GetClock(), options);
157 state_.Initialize(
158 config.config(), "sourcetoken", std::vector<std::string>{"Dummy cert"},
159 "", "chlo_hash", "signature", helper_.GetClock()->WallNow(),
160 helper_.GetClock()->WallNow().Add(QuicTime::Delta::FromSeconds(30)));
161
162 state_.SetProofValid();
163 }
164
165 ParsedQuicVersion version_;
166 TestProofHandler proof_handler_;
167 test::MockQuicConnectionHelper helper_;
168 test::MockAlarmFactory alarm_factory_;
169 QuicServerId server_id_;
170 // Session takes the ownership of the connection.
171 test::MockQuicConnection* connection_;
172 test::MockQuicSession session_;
173 QuicCryptoClientConfig crypto_client_config_;
174 QuicCryptoClientStream* client_stream_;
175 Handshaker handshaker_;
176 QuicCryptoClientConfig::CachedState state_;
177 };
178
179 INSTANTIATE_TEST_SUITE_P(
180 QuicCryptoClientHandshakerTests, QuicCryptoClientHandshakerTest,
181 ::testing::ValuesIn(AllSupportedVersionsWithQuicCrypto()),
182 ::testing::PrintToStringParamName());
183
TEST_P(QuicCryptoClientHandshakerTest,TestSendFullPaddingInInchoateHello)184 TEST_P(QuicCryptoClientHandshakerTest, TestSendFullPaddingInInchoateHello) {
185 handshaker_.DoSendCHLOTest(&state_);
186
187 EXPECT_TRUE(connection_->fully_pad_during_crypto_handshake());
188 }
189
TEST_P(QuicCryptoClientHandshakerTest,TestDisabledPaddingInInchoateHello)190 TEST_P(QuicCryptoClientHandshakerTest, TestDisabledPaddingInInchoateHello) {
191 crypto_client_config_.set_pad_inchoate_hello(false);
192 handshaker_.DoSendCHLOTest(&state_);
193 EXPECT_FALSE(connection_->fully_pad_during_crypto_handshake());
194 }
195
TEST_P(QuicCryptoClientHandshakerTest,TestPaddingInFullHelloEvenIfInchoateDisabled)196 TEST_P(QuicCryptoClientHandshakerTest,
197 TestPaddingInFullHelloEvenIfInchoateDisabled) {
198 // Disable inchoate, but full hello should still be padded.
199 crypto_client_config_.set_pad_inchoate_hello(false);
200
201 InitializeServerParametersToEnableFullHello();
202
203 handshaker_.DoSendCHLOTest(&state_);
204 EXPECT_TRUE(connection_->fully_pad_during_crypto_handshake());
205 }
206
TEST_P(QuicCryptoClientHandshakerTest,TestNoPaddingInFullHelloWhenDisabled)207 TEST_P(QuicCryptoClientHandshakerTest, TestNoPaddingInFullHelloWhenDisabled) {
208 crypto_client_config_.set_pad_full_hello(false);
209
210 InitializeServerParametersToEnableFullHello();
211
212 handshaker_.DoSendCHLOTest(&state_);
213 EXPECT_FALSE(connection_->fully_pad_during_crypto_handshake());
214 }
215
216 } // namespace
217 } // namespace quic::test
218