| // Copyright 2020 The Chromium Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #include "net/third_party/quiche/src/quic/core/crypto/proof_source_x509.h" | |
| #include <memory> | |
| #include "absl/strings/string_view.h" | |
| #include "third_party/boringssl/src/include/openssl/ssl.h" | |
| #include "net/third_party/quiche/src/quic/core/crypto/certificate_view.h" | |
| #include "net/third_party/quiche/src/quic/core/crypto/proof_source.h" | |
| #include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h" | |
| #include "net/third_party/quiche/src/quic/platform/api/quic_ip_address.h" | |
| #include "net/third_party/quiche/src/quic/platform/api/quic_reference_counted.h" | |
| #include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h" | |
| #include "net/third_party/quiche/src/quic/platform/api/quic_test.h" | |
| #include "net/third_party/quiche/src/quic/test_tools/test_certificates.h" | |
| namespace quic { | |
| namespace test { | |
| namespace { | |
| QuicReferenceCountedPointer<ProofSource::Chain> MakeChain( | |
| absl::string_view cert) { | |
| return QuicReferenceCountedPointer<ProofSource::Chain>( | |
| new ProofSource::Chain(std::vector<std::string>{std::string(cert)})); | |
| } | |
| class ProofSourceX509Test : public QuicTest { | |
| public: | |
| ProofSourceX509Test() | |
| : test_chain_(MakeChain(kTestCertificate)), | |
| wildcard_chain_(MakeChain(kWildcardCertificate)), | |
| test_key_( | |
| CertificatePrivateKey::LoadFromDer(kTestCertificatePrivateKey)), | |
| wildcard_key_(CertificatePrivateKey::LoadFromDer( | |
| kWildcardCertificatePrivateKey)) { | |
| CHECK(test_key_ != nullptr); | |
| CHECK(wildcard_key_ != nullptr); | |
| } | |
| protected: | |
| QuicReferenceCountedPointer<ProofSource::Chain> test_chain_, wildcard_chain_; | |
| std::unique_ptr<CertificatePrivateKey> test_key_, wildcard_key_; | |
| }; | |
| TEST_F(ProofSourceX509Test, AddCertificates) { | |
| std::unique_ptr<ProofSourceX509> proof_source = | |
| ProofSourceX509::Create(test_chain_, std::move(*test_key_)); | |
| ASSERT_TRUE(proof_source != nullptr); | |
| EXPECT_TRUE(proof_source->AddCertificateChain(wildcard_chain_, | |
| std::move(*wildcard_key_))); | |
| } | |
| TEST_F(ProofSourceX509Test, AddCertificateKeyMismatch) { | |
| std::unique_ptr<ProofSourceX509> proof_source = | |
| ProofSourceX509::Create(test_chain_, std::move(*test_key_)); | |
| ASSERT_TRUE(proof_source != nullptr); | |
| test_key_ = CertificatePrivateKey::LoadFromDer(kTestCertificatePrivateKey); | |
| bool result; | |
| EXPECT_QUIC_BUG(result = proof_source->AddCertificateChain( | |
| wildcard_chain_, std::move(*test_key_)), | |
| "Private key does not match"); | |
| } | |
| TEST_F(ProofSourceX509Test, CertificateSelection) { | |
| std::unique_ptr<ProofSourceX509> proof_source = | |
| ProofSourceX509::Create(test_chain_, std::move(*test_key_)); | |
| ASSERT_TRUE(proof_source != nullptr); | |
| ASSERT_TRUE(proof_source->AddCertificateChain(wildcard_chain_, | |
| std::move(*wildcard_key_))); | |
| // Default certificate. | |
| EXPECT_EQ(proof_source | |
| ->GetCertChain(QuicSocketAddress(), QuicSocketAddress(), | |
| "unknown.test") | |
| ->certs[0], | |
| kTestCertificate); | |
| // mail.example.org is explicitly a SubjectAltName in kTestCertificate. | |
| EXPECT_EQ(proof_source | |
| ->GetCertChain(QuicSocketAddress(), QuicSocketAddress(), | |
| "mail.example.org") | |
| ->certs[0], | |
| kTestCertificate); | |
| // www.foo.test is in kWildcardCertificate. | |
| EXPECT_EQ(proof_source | |
| ->GetCertChain(QuicSocketAddress(), QuicSocketAddress(), | |
| "www.foo.test") | |
| ->certs[0], | |
| kWildcardCertificate); | |
| // *.wildcard.test is in kWildcardCertificate. | |
| EXPECT_EQ(proof_source | |
| ->GetCertChain(QuicSocketAddress(), QuicSocketAddress(), | |
| "www.wildcard.test") | |
| ->certs[0], | |
| kWildcardCertificate); | |
| EXPECT_EQ(proof_source | |
| ->GetCertChain(QuicSocketAddress(), QuicSocketAddress(), | |
| "etc.wildcard.test") | |
| ->certs[0], | |
| kWildcardCertificate); | |
| // wildcard.test itself is not in kWildcardCertificate. | |
| EXPECT_EQ(proof_source | |
| ->GetCertChain(QuicSocketAddress(), QuicSocketAddress(), | |
| "wildcard.test") | |
| ->certs[0], | |
| kTestCertificate); | |
| } | |
| TEST_F(ProofSourceX509Test, TlsSignature) { | |
| class Callback : public ProofSource::SignatureCallback { | |
| public: | |
| void Run(bool ok, | |
| std::string signature, | |
| std::unique_ptr<ProofSource::Details> /*details*/) override { | |
| ASSERT_TRUE(ok); | |
| std::unique_ptr<CertificateView> view = | |
| CertificateView::ParseSingleCertificate(kTestCertificate); | |
| EXPECT_TRUE(view->VerifySignature("Test data", signature, | |
| SSL_SIGN_RSA_PSS_RSAE_SHA256)); | |
| } | |
| }; | |
| std::unique_ptr<ProofSourceX509> proof_source = | |
| ProofSourceX509::Create(test_chain_, std::move(*test_key_)); | |
| ASSERT_TRUE(proof_source != nullptr); | |
| proof_source->ComputeTlsSignature(QuicSocketAddress(), QuicSocketAddress(), | |
| "example.com", SSL_SIGN_RSA_PSS_RSAE_SHA256, | |
| "Test data", std::make_unique<Callback>()); | |
| } | |
| } // namespace | |
| } // namespace test | |
| } // namespace quic |