blob: 205ffe6e153339c88dba7a91171982262d053e86 [file] [log] [blame]
// Copyright (c) 2012 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/quic/core/quic_crypto_client_handshaker.h"
#include "net/third_party/quic/core/proto/crypto_server_config.pb.h"
#include "net/third_party/quic/core/tls_client_handshaker.h"
#include "net/third_party/quic/core/tls_server_handshaker.h"
#include "net/third_party/quic/test_tools/quic_test_utils.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace quic {
namespace {
using ::testing::Test;
class TestProofHandler : public QuicCryptoClientStream::ProofHandler {
public:
~TestProofHandler() override {}
void OnProofValid(
const QuicCryptoClientConfig::CachedState& cached) override {}
void OnProofVerifyDetailsAvailable(
const ProofVerifyDetails& verify_details) override {}
};
class InsecureProofVerifier : public ProofVerifier {
public:
InsecureProofVerifier() {}
~InsecureProofVerifier() override {}
// ProofVerifier override.
QuicAsyncStatus VerifyProof(
const QuicString& hostname,
const uint16_t port,
const QuicString& server_config,
QuicTransportVersion transport_version,
QuicStringPiece chlo_hash,
const std::vector<QuicString>& certs,
const QuicString& cert_sct,
const QuicString& signature,
const ProofVerifyContext* context,
QuicString* error_details,
std::unique_ptr<ProofVerifyDetails>* verify_details,
std::unique_ptr<ProofVerifierCallback> callback) override {
return QUIC_SUCCESS;
}
QuicAsyncStatus VerifyCertChain(
const QuicString& hostname,
const std::vector<QuicString>& certs,
const ProofVerifyContext* context,
QuicString* error_details,
std::unique_ptr<ProofVerifyDetails>* details,
std::unique_ptr<ProofVerifierCallback> callback) override {
return QUIC_SUCCESS;
}
std::unique_ptr<ProofVerifyContext> CreateDefaultContext() override {
return nullptr;
}
};
class DummyProofSource : public ProofSource {
public:
DummyProofSource() {}
~DummyProofSource() override {}
// ProofSource override.
void GetProof(const QuicSocketAddress& server_address,
const QuicString& hostname,
const QuicString& server_config,
QuicTransportVersion transport_version,
QuicStringPiece chlo_hash,
std::unique_ptr<Callback> callback) override {
QuicReferenceCountedPointer<ProofSource::Chain> chain =
GetCertChain(server_address, hostname);
QuicCryptoProof proof;
proof.signature = "Dummy signature";
proof.leaf_cert_scts = "Dummy timestamp";
callback->Run(true, chain, proof, nullptr /* details */);
}
QuicReferenceCountedPointer<Chain> GetCertChain(
const QuicSocketAddress& server_address,
const QuicString& hostname) override {
std::vector<QuicString> certs;
certs.push_back("Dummy cert");
return QuicReferenceCountedPointer<ProofSource::Chain>(
new ProofSource::Chain(certs));
}
void ComputeTlsSignature(
const QuicSocketAddress& server_address,
const QuicString& hostname,
uint16_t signature_algorithm,
QuicStringPiece in,
std::unique_ptr<SignatureCallback> callback) override {
callback->Run(true, "Dummy signature");
}
};
class Handshaker : public QuicCryptoClientHandshaker {
public:
Handshaker(const QuicServerId& server_id,
QuicCryptoClientStream* stream,
QuicSession* session,
std::unique_ptr<ProofVerifyContext> verify_context,
QuicCryptoClientConfig* crypto_config,
QuicCryptoClientStream::ProofHandler* proof_handler)
: QuicCryptoClientHandshaker(server_id,
stream,
session,
std::move(verify_context),
crypto_config,
proof_handler) {}
void DoSendCHLOTest(QuicCryptoClientConfig::CachedState* cached) {
QuicCryptoClientHandshaker::DoSendCHLO(cached);
}
};
class QuicCryptoClientHandshakerTest : public Test {
protected:
QuicCryptoClientHandshakerTest()
: proof_handler_(),
helper_(),
alarm_factory_(),
server_id_("host", 123),
connection_(new test::MockQuicConnection(&helper_,
&alarm_factory_,
Perspective::IS_CLIENT)),
session_(connection_, false),
crypto_client_config_(QuicMakeUnique<InsecureProofVerifier>(),
quic::TlsClientHandshaker::CreateSslCtx()),
client_stream_(new QuicCryptoClientStream(server_id_,
&session_,
nullptr,
&crypto_client_config_,
&proof_handler_)),
handshaker_(server_id_,
client_stream_,
&session_,
nullptr,
&crypto_client_config_,
&proof_handler_),
state_() {
// Session takes the ownership of the client stream! (but handshaker also
// takes a reference to it, but doesn't take the ownership).
session_.SetCryptoStream(client_stream_);
session_.Initialize();
}
void InitializeServerParametersToEnableFullHello() {
QuicCryptoServerConfig::ConfigOptions options;
std::unique_ptr<QuicServerConfigProtobuf> config =
QuicCryptoServerConfig::GenerateConfig(helper_.GetRandomGenerator(),
helper_.GetClock(), options);
state_.Initialize(
config->config(), "sourcetoken", std::vector<QuicString>{"Dummy cert"},
"", "chlo_hash", "signature", helper_.GetClock()->WallNow(),
helper_.GetClock()->WallNow().Add(QuicTime::Delta::FromSeconds(30)));
state_.SetProofValid();
}
TestProofHandler proof_handler_;
test::MockQuicConnectionHelper helper_;
test::MockAlarmFactory alarm_factory_;
QuicServerId server_id_;
// Session takes the ownership of the connection.
test::MockQuicConnection* connection_;
test::MockQuicSession session_;
QuicCryptoClientConfig crypto_client_config_;
QuicCryptoClientStream* client_stream_;
Handshaker handshaker_;
QuicCryptoClientConfig::CachedState state_;
};
TEST_F(QuicCryptoClientHandshakerTest, TestSendFullPaddingInInchoateHello) {
handshaker_.DoSendCHLOTest(&state_);
EXPECT_TRUE(connection_->fully_pad_during_crypto_handshake());
}
TEST_F(QuicCryptoClientHandshakerTest, TestDisabledPaddingInInchoateHello) {
crypto_client_config_.set_pad_inchoate_hello(false);
handshaker_.DoSendCHLOTest(&state_);
EXPECT_FALSE(connection_->fully_pad_during_crypto_handshake());
}
TEST_F(QuicCryptoClientHandshakerTest,
TestPaddingInFullHelloEvenIfInchoateDisabled) {
// Disable inchoate, but full hello should still be padded.
crypto_client_config_.set_pad_inchoate_hello(false);
InitializeServerParametersToEnableFullHello();
handshaker_.DoSendCHLOTest(&state_);
EXPECT_TRUE(connection_->fully_pad_during_crypto_handshake());
}
TEST_F(QuicCryptoClientHandshakerTest, TestNoPaddingInFullHelloWhenDisabled) {
crypto_client_config_.set_pad_full_hello(false);
InitializeServerParametersToEnableFullHello();
handshaker_.DoSendCHLOTest(&state_);
EXPECT_FALSE(connection_->fully_pad_during_crypto_handshake());
}
} // namespace
} // namespace quic