Commit 44f63222 authored by Nick Harper's avatar Nick Harper Committed by Commit Bot

Reject empty signatures in ProofVerifierChromium::VerifyProof

QuicCryptoClientHandshaker checks that signatures aren't empty, so we
should never hit this case in production. In case something goes wrong
at the upper layer, it's nice to have a belt-and-suspenders approach and
since an empty signature is obviously wrong, it should be rejected.

Change-Id: Id704bb9b469b6bc831f0a629be1824461617d883
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2243835Reviewed-by: default avatarDavid Schinazi <dschinazi@chromium.org>
Commit-Queue: David Schinazi <dschinazi@chromium.org>
Auto-Submit: Nick Harper <nharper@chromium.org>
Cr-Commit-Position: refs/heads/master@{#778043}
parent 3f56e464
...@@ -243,8 +243,8 @@ quic::QuicAsyncStatus ProofVerifierChromium::Job::VerifyProof( ...@@ -243,8 +243,8 @@ quic::QuicAsyncStatus ProofVerifierChromium::Job::VerifyProof(
// We call VerifySignature first to avoid copying of server_config and // We call VerifySignature first to avoid copying of server_config and
// signature. // signature.
if (!signature.empty() && !VerifySignature(server_config, quic_version, if (!VerifySignature(server_config, quic_version, chlo_hash, signature,
chlo_hash, signature, certs[0])) { certs[0])) {
*error_details = "Failed to verify signature of server config"; *error_details = "Failed to verify signature of server config";
DLOG(WARNING) << *error_details; DLOG(WARNING) << *error_details;
verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID; verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID;
...@@ -560,6 +560,11 @@ bool ProofVerifierChromium::Job::VerifySignature( ...@@ -560,6 +560,11 @@ bool ProofVerifierChromium::Job::VerifySignature(
return false; return false;
} }
if (signature.empty()) {
DLOG(WARNING) << "Signature is empty, thus cannot possibly be valid";
return false;
}
crypto::SignatureVerifier verifier; crypto::SignatureVerifier verifier;
if (!x509_util::SignatureVerifierInitWithCertificate( if (!x509_util::SignatureVerifierInitWithCertificate(
&verifier, algorithm, base::as_bytes(base::make_span(signature)), &verifier, algorithm, base::as_bytes(base::make_span(signature)),
......
...@@ -105,10 +105,12 @@ class DummyProofVerifierCallback : public quic::ProofVerifierCallback { ...@@ -105,10 +105,12 @@ class DummyProofVerifierCallback : public quic::ProofVerifierCallback {
}; };
const char kTestHostname[] = "test.example.com"; const char kTestHostname[] = "test.example.com";
const char kTestChloHash[] = "CHLO hash";
const char kTestEmptySCT[] = "";
const uint16_t kTestPort = 8443; const uint16_t kTestPort = 8443;
const char kTestConfig[] = "server config bytes"; const char kTestConfig[] = "server config bytes";
const char kTestChloHash[] = "CHLO hash";
const char kTestEmptySCT[] = "";
const char kTestEmptySignature[] = "";
const char kLogDescription[] = "somelog"; const char kLogDescription[] = "somelog";
// This test exercises code that does not depend on the QUIC version in use // This test exercises code that does not depend on the QUIC version in use
...@@ -258,7 +260,7 @@ TEST_F(ProofVerifierChromiumTest, ValidSCTList) { ...@@ -258,7 +260,7 @@ TEST_F(ProofVerifierChromiumTest, ValidSCTList) {
new DummyProofVerifierCallback); new DummyProofVerifierCallback);
quic::QuicAsyncStatus status = proof_verifier.VerifyProof( quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
kTestHostname, kTestPort, kTestConfig, kTestTransportVersion, kTestHostname, kTestPort, kTestConfig, kTestTransportVersion,
kTestChloHash, certs_, ct::GetSCTListForTesting(), kTestEmptySCT, kTestChloHash, certs_, ct::GetSCTListForTesting(), kTestEmptySignature,
verify_context_.get(), &error_details_, &details_, std::move(callback)); verify_context_.get(), &error_details_, &details_, std::move(callback));
ASSERT_EQ(quic::QUIC_FAILURE, status); ASSERT_EQ(quic::QUIC_FAILURE, status);
CheckSCT(/*sct_expected_ok=*/true); CheckSCT(/*sct_expected_ok=*/true);
...@@ -278,8 +280,9 @@ TEST_F(ProofVerifierChromiumTest, InvalidSCTList) { ...@@ -278,8 +280,9 @@ TEST_F(ProofVerifierChromiumTest, InvalidSCTList) {
new DummyProofVerifierCallback); new DummyProofVerifierCallback);
quic::QuicAsyncStatus status = proof_verifier.VerifyProof( quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
kTestHostname, kTestPort, kTestConfig, kTestTransportVersion, kTestHostname, kTestPort, kTestConfig, kTestTransportVersion,
kTestChloHash, certs_, ct::GetSCTListWithInvalidSCT(), kTestEmptySCT, kTestChloHash, certs_, ct::GetSCTListWithInvalidSCT(),
verify_context_.get(), &error_details_, &details_, std::move(callback)); kTestEmptySignature, verify_context_.get(), &error_details_, &details_,
std::move(callback));
ASSERT_EQ(quic::QUIC_FAILURE, status); ASSERT_EQ(quic::QUIC_FAILURE, status);
CheckSCT(/*sct_expected_ok=*/false); CheckSCT(/*sct_expected_ok=*/false);
} }
...@@ -296,8 +299,8 @@ TEST_F(ProofVerifierChromiumTest, FailsIfSignatureFails) { ...@@ -296,8 +299,8 @@ TEST_F(ProofVerifierChromiumTest, FailsIfSignatureFails) {
new DummyProofVerifierCallback); new DummyProofVerifierCallback);
quic::QuicAsyncStatus status = proof_verifier.VerifyProof( quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
kTestHostname, kTestPort, kTestConfig, kTestTransportVersion, kTestHostname, kTestPort, kTestConfig, kTestTransportVersion,
kTestChloHash, certs_, kTestEmptySCT, kTestConfig, verify_context_.get(), kTestChloHash, certs_, kTestEmptySCT, kTestEmptySignature,
&error_details_, &details_, std::move(callback)); verify_context_.get(), &error_details_, &details_, std::move(callback));
ASSERT_EQ(quic::QUIC_FAILURE, status); ASSERT_EQ(quic::QUIC_FAILURE, status);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment