blob: f72e2f5e957043fe89261ebd6d9a338b077094d8 [file] [log] [blame]
// 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 "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 "quic/core/crypto/certificate_view.h"
#include "quic/core/crypto/proof_source.h"
#include "quic/platform/api/quic_expect_bug.h"
#include "quic/platform/api/quic_ip_address.h"
#include "quic/platform/api/quic_reference_counted.h"
#include "quic/platform/api/quic_socket_address.h"
#include "quic/platform/api/quic_test.h"
#include "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