blob: 8933e51532d1a66de3d97b45feef37b906ae9f17 [file] [log] [blame]
[email protected]c244c5a12013-05-07 20:55:041// 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
rch16c74d1d2016-04-22 06:14:075#include <memory>
6
[email protected]2662ed562013-07-03 10:27:467#include "base/files/file_path.h"
Keishi Hattori0e45c022021-11-27 09:25:528#include "base/memory/raw_ptr.h"
rtenneti7dac4be2014-12-15 21:10:019#include "net/base/ip_endpoint.h"
[email protected]2662ed562013-07-03 10:27:4610#include "net/base/net_errors.h"
11#include "net/base/test_completion_callback.h"
[email protected]a69af0522013-07-12 19:23:4712#include "net/cert/cert_status_flags.h"
13#include "net/cert/cert_verify_result.h"
[email protected]2662ed562013-07-03 10:27:4614#include "net/cert/x509_certificate.h"
[email protected]2662ed562013-07-03 10:27:4615#include "net/test/cert_test_util.h"
rsleevia69c79a2016-06-22 03:28:4316#include "net/test/test_data_directory.h"
Ryan Hamiltonea4fa192022-04-12 18:30:4917#include "net/third_party/quiche/src/quiche/quic/core/crypto/proof_source.h"
18#include "net/third_party/quiche/src/quiche/quic/core/crypto/proof_verifier.h"
19#include "net/third_party/quiche/src/quiche/quic/test_tools/crypto_test_utils.h"
[email protected]c244c5a12013-05-07 20:55:0420#include "testing/gtest/include/gtest/gtest.h"
Nick Harperb42e4e7d2017-08-31 00:18:1121#include "third_party/boringssl/src/include/openssl/ssl.h"
[email protected]c244c5a12013-05-07 20:55:0422
23using std::string;
[email protected]c244c5a12013-05-07 20:55:0424
Tsuyoshi Horo4f516be2022-06-14 11:53:1325namespace net::test {
[email protected]6a731c92014-03-22 00:43:2426namespace {
[email protected]c244c5a12013-05-07 20:55:0427
Ryan Hamilton8d9ee76e2018-05-29 23:52:5228// TestProofVerifierCallback is a simple callback for a quic::ProofVerifier that
[email protected]72e65992013-07-30 17:16:1429// signals a TestCompletionCallback when called and stores the results from the
Ryan Hamilton8d9ee76e2018-05-29 23:52:5230// quic::ProofVerifier in pointers passed to the constructor.
31class TestProofVerifierCallback : public quic::ProofVerifierCallback {
[email protected]72e65992013-07-30 17:16:1432 public:
33 TestProofVerifierCallback(TestCompletionCallback* comp_callback,
34 bool* ok,
[email protected]b9475b582014-03-20 20:04:3335 string* error_details)
rjshaded5ced072015-12-18 19:26:0236 : comp_callback_(comp_callback), ok_(ok), error_details_(error_details) {}
[email protected]72e65992013-07-30 17:16:1437
dchengb03027d2014-10-21 12:00:2038 void Run(bool ok,
39 const string& error_details,
Ryan Hamilton8d9ee76e2018-05-29 23:52:5240 std::unique_ptr<quic::ProofVerifyDetails>* details) override {
[email protected]72e65992013-07-30 17:16:1441 *ok_ = ok;
42 *error_details_ = error_details;
43
44 comp_callback_->callback().Run(0);
45 }
46
47 private:
Keishi Hattori0e45c022021-11-27 09:25:5248 const raw_ptr<TestCompletionCallback> comp_callback_;
49 const raw_ptr<bool> ok_;
50 const raw_ptr<string> error_details_;
[email protected]72e65992013-07-30 17:16:1451};
52
53// RunVerification runs |verifier->VerifyProof| and asserts that the result
54// matches |expected_ok|.
Ryan Hamilton8d9ee76e2018-05-29 23:52:5255void RunVerification(quic::ProofVerifier* verifier,
[email protected]6a731c92014-03-22 00:43:2456 const string& hostname,
elawrence954bb5472016-04-04 22:03:1157 const uint16_t port,
[email protected]6a731c92014-03-22 00:43:2458 const string& server_config,
Ryan Hamilton8d9ee76e2018-05-29 23:52:5259 quic::QuicTransportVersion quic_version,
Victor Vasiliev47ecb6a2020-10-14 17:22:1060 absl::string_view chlo_hash,
rch872e00e2016-12-02 02:48:1861 const std::vector<string>& certs,
[email protected]6a731c92014-03-22 00:43:2462 const string& proof,
63 bool expected_ok) {
Ryan Hamilton8d9ee76e2018-05-29 23:52:5264 std::unique_ptr<quic::ProofVerifyDetails> details;
[email protected]72e65992013-07-30 17:16:1465 TestCompletionCallback comp_callback;
66 bool ok;
[email protected]b9475b582014-03-20 20:04:3367 string error_details;
Ryan Hamilton8d9ee76e2018-05-29 23:52:5268 std::unique_ptr<quic::ProofVerifyContext> verify_context(
69 quic::test::crypto_test_utils::ProofVerifyContextForTesting());
Tsuyoshi Horof8861cb2022-07-05 23:50:2070 auto callback = std::make_unique<TestProofVerifierCallback>(
71 &comp_callback, &ok, &error_details);
[email protected]72e65992013-07-30 17:16:1472
Ryan Hamilton8d9ee76e2018-05-29 23:52:5273 quic::QuicAsyncStatus status = verifier->VerifyProof(
elawrence954bb5472016-04-04 22:03:1174 hostname, port, server_config, quic_version, chlo_hash, certs, "", proof,
ckrasic6567aa52016-07-08 09:24:3575 verify_context.get(), &error_details, &details, std::move(callback));
[email protected]72e65992013-07-30 17:16:1476
77 switch (status) {
Ryan Hamilton8d9ee76e2018-05-29 23:52:5278 case quic::QUIC_FAILURE:
[email protected]72e65992013-07-30 17:16:1479 ASSERT_FALSE(expected_ok);
80 ASSERT_NE("", error_details);
81 return;
Ryan Hamilton8d9ee76e2018-05-29 23:52:5282 case quic::QUIC_SUCCESS:
[email protected]72e65992013-07-30 17:16:1483 ASSERT_TRUE(expected_ok);
84 ASSERT_EQ("", error_details);
85 return;
Ryan Hamilton8d9ee76e2018-05-29 23:52:5286 case quic::QUIC_PENDING:
[email protected]72e65992013-07-30 17:16:1487 comp_callback.WaitForResult();
88 ASSERT_EQ(expected_ok, ok);
89 break;
90 }
91}
92
Ryan Hamilton8d9ee76e2018-05-29 23:52:5293class TestCallback : public quic::ProofSource::Callback {
ckrasic6567aa52016-07-08 09:24:3594 public:
Ryan Hamilton8d9ee76e2018-05-29 23:52:5295 explicit TestCallback(
96 bool* called,
97 bool* ok,
Victor Vasiliev5b04a6b2022-03-15 14:24:2598 quiche::QuicheReferenceCountedPointer<quic::ProofSource::Chain>* chain,
Ryan Hamilton8d9ee76e2018-05-29 23:52:5299 quic::QuicCryptoProof* proof)
mpw94250b82016-11-19 18:13:30100 : called_(called), ok_(ok), chain_(chain), proof_(proof) {}
ckrasic6567aa52016-07-08 09:24:35101
Ryan Hamilton8d9ee76e2018-05-29 23:52:52102 void Run(
103 bool ok,
Victor Vasiliev5b04a6b2022-03-15 14:24:25104 const quiche::QuicheReferenceCountedPointer<quic::ProofSource::Chain>&
105 chain,
Ryan Hamilton8d9ee76e2018-05-29 23:52:52106 const quic::QuicCryptoProof& proof,
107 std::unique_ptr<quic::ProofSource::Details> /* details */) override {
ckrasic6567aa52016-07-08 09:24:35108 *ok_ = ok;
109 *chain_ = chain;
mpw94250b82016-11-19 18:13:30110 *proof_ = proof;
ckrasic6567aa52016-07-08 09:24:35111 *called_ = true;
112 }
113
114 private:
Keishi Hattori0e45c022021-11-27 09:25:52115 raw_ptr<bool> called_;
116 raw_ptr<bool> ok_;
Victor Vasiliev5b04a6b2022-03-15 14:24:25117 raw_ptr<quiche::QuicheReferenceCountedPointer<quic::ProofSource::Chain>>
118 chain_;
Keishi Hattori0e45c022021-11-27 09:25:52119 raw_ptr<quic::QuicCryptoProof> proof_;
ckrasic6567aa52016-07-08 09:24:35120};
121
Renjie Tang1085bf52019-11-20 00:10:53122class ProofTest : public ::testing::TestWithParam<quic::ParsedQuicVersion> {};
rch28f6469d2016-03-13 21:13:08123
[email protected]6a731c92014-03-22 00:43:24124} // namespace
125
Renjie Tang1085bf52019-11-20 00:10:53126INSTANTIATE_TEST_SUITE_P(QuicTransportVersion,
127 ProofTest,
128 ::testing::ValuesIn(quic::AllSupportedVersions()),
129 ::testing::PrintToStringParamName());
rch28f6469d2016-03-13 21:13:08130
David Benjaminb28c476f2018-12-15 04:47:15131TEST_P(ProofTest, Verify) {
Ryan Hamilton8d9ee76e2018-05-29 23:52:52132 std::unique_ptr<quic::ProofSource> source(
133 quic::test::crypto_test_utils::ProofSourceForTesting());
134 std::unique_ptr<quic::ProofVerifier> verifier(
135 quic::test::crypto_test_utils::ProofVerifierForTesting());
[email protected]6a731c92014-03-22 00:43:24136
137 const string server_config = "server config bytes";
138 const string hostname = "test.example.com";
elawrence954bb5472016-04-04 22:03:11139 const uint16_t port = 8443;
rch28f6469d2016-03-13 21:13:08140 const string first_chlo_hash = "first chlo hash bytes";
141 const string second_chlo_hash = "first chlo hash bytes";
Renjie Tang1085bf52019-11-20 00:10:53142 const quic::QuicTransportVersion quic_version = GetParam().transport_version;
elawrence954bb5472016-04-04 22:03:11143
fayangf5f4cd512017-02-07 16:57:11144 bool called = false;
145 bool first_called = false;
146 bool ok, first_ok;
Victor Vasiliev5b04a6b2022-03-15 14:24:25147 quiche::QuicheReferenceCountedPointer<quic::ProofSource::Chain> chain;
148 quiche::QuicheReferenceCountedPointer<quic::ProofSource::Chain> first_chain;
mpw94250b82016-11-19 18:13:30149 string error_details;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52150 quic::QuicCryptoProof proof, first_proof;
151 quic::QuicSocketAddress server_addr;
Zhongyi Shi43a8f2242020-05-04 23:34:31152 quic::QuicSocketAddress client_addr;
[email protected]6a731c92014-03-22 00:43:24153
Tsuyoshi Horof8861cb2022-07-05 23:50:20154 auto cb = std::make_unique<TestCallback>(&called, &ok, &chain, &proof);
155 auto first_cb = std::make_unique<TestCallback>(&first_called, &first_ok,
156 &first_chain, &first_proof);
fayangf5f4cd512017-02-07 16:57:11157
158 // GetProof here expects the async method to invoke the callback
159 // synchronously.
Zhongyi Shi43a8f2242020-05-04 23:34:31160 source->GetProof(server_addr, client_addr, hostname, server_config,
161 quic_version, first_chlo_hash, std::move(first_cb));
162 source->GetProof(server_addr, client_addr, hostname, server_config,
163 quic_version, second_chlo_hash, std::move(cb));
fayangf5f4cd512017-02-07 16:57:11164 ASSERT_TRUE(called);
165 ASSERT_TRUE(first_called);
166 ASSERT_TRUE(ok);
167 ASSERT_TRUE(first_ok);
[email protected]6a731c92014-03-22 00:43:24168
169 // Check that the proof source is caching correctly:
fayanga64c1a92016-02-13 01:55:58170 ASSERT_EQ(first_chain->certs, chain->certs);
mpw94250b82016-11-19 18:13:30171 ASSERT_NE(proof.signature, first_proof.signature);
172 ASSERT_EQ(first_proof.leaf_cert_scts, proof.leaf_cert_scts);
[email protected]6a731c92014-03-22 00:43:24173
elawrence954bb5472016-04-04 22:03:11174 RunVerification(verifier.get(), hostname, port, server_config, quic_version,
mpw94250b82016-11-19 18:13:30175 first_chlo_hash, chain->certs, proof.signature, true);
[email protected]6a731c92014-03-22 00:43:24176
elawrence954bb5472016-04-04 22:03:11177 RunVerification(verifier.get(), "foo.com", port, server_config, quic_version,
mpw94250b82016-11-19 18:13:30178 first_chlo_hash, chain->certs, proof.signature, false);
[email protected]6a731c92014-03-22 00:43:24179
elawrence954bb5472016-04-04 22:03:11180 RunVerification(verifier.get(), server_config.substr(1, string::npos), port,
rch28f6469d2016-03-13 21:13:08181 server_config, quic_version, first_chlo_hash, chain->certs,
mpw94250b82016-11-19 18:13:30182 proof.signature, false);
[email protected]6a731c92014-03-22 00:43:24183
mpw94250b82016-11-19 18:13:30184 const string corrupt_signature = "1" + proof.signature;
elawrence954bb5472016-04-04 22:03:11185 RunVerification(verifier.get(), hostname, port, server_config, quic_version,
rch28f6469d2016-03-13 21:13:08186 first_chlo_hash, chain->certs, corrupt_signature, false);
[email protected]6a731c92014-03-22 00:43:24187
rch872e00e2016-12-02 02:48:18188 std::vector<string> wrong_certs;
fayanga64c1a92016-02-13 01:55:58189 for (size_t i = 1; i < chain->certs.size(); i++) {
190 wrong_certs.push_back(chain->certs[i]);
[email protected]6a731c92014-03-22 00:43:24191 }
elawrence954bb5472016-04-04 22:03:11192
193 RunVerification(verifier.get(), "foo.com", port, server_config, quic_version,
rch28f6469d2016-03-13 21:13:08194 first_chlo_hash, wrong_certs, corrupt_signature, false);
[email protected]6a731c92014-03-22 00:43:24195}
196
Nick Harperb42e4e7d2017-08-31 00:18:11197namespace {
Nick Harperb00c90892017-08-31 04:08:09198
Ryan Hamilton8d9ee76e2018-05-29 23:52:52199class TestingSignatureCallback : public quic::ProofSource::SignatureCallback {
Nick Harperb42e4e7d2017-08-31 00:18:11200 public:
201 TestingSignatureCallback(bool* ok_out, std::string* signature_out)
202 : ok_out_(ok_out), signature_out_(signature_out) {}
203
Fan Yang7abc6bd2020-03-27 17:58:18204 void Run(bool ok,
205 std::string signature,
206 std::unique_ptr<quic::ProofSource::Details> /*details*/) override {
Nick Harperb42e4e7d2017-08-31 00:18:11207 *ok_out_ = ok;
208 *signature_out_ = std::move(signature);
209 }
210
211 private:
Keishi Hattori0e45c022021-11-27 09:25:52212 raw_ptr<bool> ok_out_;
213 raw_ptr<std::string> signature_out_;
Nick Harperb42e4e7d2017-08-31 00:18:11214};
215
216} // namespace
217
218TEST_P(ProofTest, TlsSignature) {
Ryan Hamilton8d9ee76e2018-05-29 23:52:52219 std::unique_ptr<quic::ProofSource> source(
220 quic::test::crypto_test_utils::ProofSourceForTesting());
Nick Harperb42e4e7d2017-08-31 00:18:11221
Ryan Hamilton8d9ee76e2018-05-29 23:52:52222 quic::QuicSocketAddress server_address;
Nick Harperb42e4e7d2017-08-31 00:18:11223 const string hostname = "test.example.com";
224
Zhongyi Shi43a8f2242020-05-04 23:34:31225 quic::QuicSocketAddress client_address;
226
David Schinazif492e4318a2021-09-09 16:41:19227 bool cert_matched_sni;
Victor Vasiliev5b04a6b2022-03-15 14:24:25228 quiche::QuicheReferenceCountedPointer<quic::ProofSource::Chain> chain =
David Schinazif492e4318a2021-09-09 16:41:19229 source->GetCertChain(server_address, client_address, hostname,
230 &cert_matched_sni);
Nick Harperb42e4e7d2017-08-31 00:18:11231 ASSERT_GT(chain->certs.size(), 0ul);
232
233 // Generate a value to be signed similar to the example in TLS 1.3 section
234 // 4.4.3. The value to be signed starts with octed 0x20 repeated 64 times,
235 // followed by the context string, followed by a single 0 byte, followed by
236 // the transcript hash. Since there's no TLS stack here, we're using 32 bytes
237 // of 01 as the transcript hash.
238 string to_be_signed(64, ' ');
239 to_be_signed.append("TLS 1.3, server CertificateVerify");
240 to_be_signed.append(1, '\0');
241 to_be_signed.append(32, 1);
242
243 string sig;
244 bool success;
245 std::unique_ptr<TestingSignatureCallback> callback =
Victor Vasiliev7da08172019-10-14 06:04:25246 std::make_unique<TestingSignatureCallback>(&success, &sig);
Zhongyi Shi43a8f2242020-05-04 23:34:31247 source->ComputeTlsSignature(server_address, client_address, hostname,
248 SSL_SIGN_RSA_PSS_SHA256, to_be_signed,
249 std::move(callback));
Nick Harperb42e4e7d2017-08-31 00:18:11250 EXPECT_TRUE(success);
251
252 // Verify that the signature from ComputeTlsSignature can be verified with the
253 // leaf cert from GetCertChain.
254 const uint8_t* data;
255 const uint8_t* orig_data;
256 orig_data = data = reinterpret_cast<const uint8_t*>(chain->certs[0].data());
257 bssl::UniquePtr<X509> leaf(d2i_X509(nullptr, &data, chain->certs[0].size()));
258 ASSERT_NE(leaf.get(), nullptr);
259 EXPECT_EQ(data - orig_data, static_cast<ptrdiff_t>(chain->certs[0].size()));
260 bssl::UniquePtr<EVP_PKEY> pkey(X509_get_pubkey(leaf.get()));
261 bssl::ScopedEVP_MD_CTX md_ctx;
262 EVP_PKEY_CTX* ctx;
263 ASSERT_EQ(EVP_DigestVerifyInit(md_ctx.get(), &ctx, EVP_sha256(), nullptr,
264 pkey.get()),
265 1);
266 ASSERT_EQ(EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PSS_PADDING), 1);
267 ASSERT_EQ(EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, -1), 1);
268 ASSERT_EQ(EVP_DigestVerifyUpdate(md_ctx.get(), to_be_signed.data(),
269 to_be_signed.size()),
270 1);
271 EXPECT_EQ(EVP_DigestVerifyFinal(md_ctx.get(),
272 reinterpret_cast<const uint8_t*>(sig.data()),
273 sig.size()),
274 1);
275}
276
rch28f6469d2016-03-13 21:13:08277TEST_P(ProofTest, UseAfterFree) {
Ryan Hamilton8d9ee76e2018-05-29 23:52:52278 std::unique_ptr<quic::ProofSource> source(
279 quic::test::crypto_test_utils::ProofSourceForTesting());
fayanga64c1a92016-02-13 01:55:58280
281 const string server_config = "server config bytes";
282 const string hostname = "test.example.com";
rch28f6469d2016-03-13 21:13:08283 const string chlo_hash = "proof nonce bytes";
fayangf5f4cd512017-02-07 16:57:11284 bool called = false;
285 bool ok;
Victor Vasiliev5b04a6b2022-03-15 14:24:25286 quiche::QuicheReferenceCountedPointer<quic::ProofSource::Chain> chain;
mpw94250b82016-11-19 18:13:30287 string error_details;
Ryan Hamilton8d9ee76e2018-05-29 23:52:52288 quic::QuicCryptoProof proof;
289 quic::QuicSocketAddress server_addr;
Zhongyi Shi43a8f2242020-05-04 23:34:31290 quic::QuicSocketAddress client_addr;
Tsuyoshi Horof8861cb2022-07-05 23:50:20291 auto cb = std::make_unique<TestCallback>(&called, &ok, &chain, &proof);
fayanga64c1a92016-02-13 01:55:58292
fayangf5f4cd512017-02-07 16:57:11293 // GetProof here expects the async method to invoke the callback
294 // synchronously.
Zhongyi Shi43a8f2242020-05-04 23:34:31295 source->GetProof(server_addr, client_addr, hostname, server_config,
Renjie Tang1085bf52019-11-20 00:10:53296 GetParam().transport_version, chlo_hash, std::move(cb));
fayangf5f4cd512017-02-07 16:57:11297 ASSERT_TRUE(called);
298 ASSERT_TRUE(ok);
fayanga64c1a92016-02-13 01:55:58299
300 // Make sure we can safely access results after deleting where they came from.
301 EXPECT_FALSE(chain->HasOneRef());
fayang199cfb02016-07-13 03:56:39302 source = nullptr;
fayanga64c1a92016-02-13 01:55:58303 EXPECT_TRUE(chain->HasOneRef());
304
305 EXPECT_FALSE(chain->certs.empty());
306 for (const string& cert : chain->certs) {
307 EXPECT_FALSE(cert.empty());
308 }
309}
310
Tsuyoshi Horo4f516be2022-06-14 11:53:13311} // namespace net::test