blob: 84366d32a35f8a7520ce4f41e1402ec812bffe2c [file] [log] [blame]
// Copyright 2016 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 "components/cronet/android/cert/cert_verifier_cache_serializer.h"
#include <memory>
#include <string>
#include "base/android/path_utils.h"
#include "base/files/file_path.h"
#include "base/memory/ref_counted.h"
#include "components/cronet/android/cert/proto/cert_verification.pb.h"
#include "net/base/net_errors.h"
#include "net/base/test_completion_callback.h"
#include "net/cert/caching_cert_verifier.h"
#include "net/cert/cert_verifier.h"
#include "net/cert/cert_verify_result.h"
#include "net/cert/mock_cert_verifier.h"
#include "net/cert/x509_certificate.h"
#include "net/cert/x509_util.h"
#include "net/log/net_log_with_source.h"
#include "net/test/cert_test_util.h"
#include "net/test/test_data_directory.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace cronet {
namespace {
// Helper function that verifies the cerificate with the given |cert_name|
// against the given |hostname| using the given |verifier|. Result from the cert
// verification is ignored.
void VerifyCert(const std::string& cert_name,
const std::string& hostname,
net::CachingCertVerifier* verifier,
net::CertVerifyResult* verify_result) {
// Set up server certs.
scoped_refptr<net::X509Certificate> cert(
net::ImportCertFromFile(net::GetTestCertsDirectory(), cert_name));
ASSERT_TRUE(cert);
net::TestCompletionCallback callback;
std::unique_ptr<net::CertVerifier::Request> request;
ignore_result(callback.GetResult(verifier->Verify(
net::CertVerifier::RequestParams(cert.get(), hostname, 0, std::string(),
net::CertificateList()),
nullptr, verify_result, callback.callback(), &request,
net::NetLogWithSource())));
}
} // namespace
TEST(CertVerifierCacheSerializerTest, RestoreEmptyData) {
// Restoring empty data should fail.
cronet_pb::CertVerificationCache cert_cache;
net::CachingCertVerifier verifier(std::make_unique<net::MockCertVerifier>());
EXPECT_FALSE(DeserializeCertVerifierCache(cert_cache, &verifier));
}
TEST(CertVerifierCacheSerializerTest, SerializeCache) {
net::CertVerifyResult verify_result;
net::CachingCertVerifier verifier(std::make_unique<net::MockCertVerifier>());
ASSERT_NO_FATAL_FAILURE(
VerifyCert("ok_cert.pem", "www.example.com", &verifier, &verify_result));
cronet_pb::CertVerificationCache cert_cache =
SerializeCertVerifierCache(verifier);
// Verify atleast one certificate is serialized.
DCHECK_EQ(1, cert_cache.cert_entry_size());
DCHECK_EQ(1, cert_cache.cache_entry_size());
}
// Create a new Verifier and restoring the data into it should succeed.
TEST(CertVerifierCacheSerializerTest, RestoreMultipleEntriesIntoNewVerifier) {
scoped_refptr<net::X509Certificate> ok_cert(
net::ImportCertFromFile(net::GetTestCertsDirectory(), "ok_cert.pem"));
ASSERT_TRUE(ok_cert);
const scoped_refptr<net::X509Certificate> root_cert =
net::ImportCertFromFile(net::GetTestCertsDirectory(), "root_ca_cert.pem");
ASSERT_TRUE(root_cert);
net::TestCompletionCallback callback;
std::unique_ptr<net::CertVerifier::Request> request;
// Verify www.example.com host's certificate.
std::string example_hostname("www.example.com");
net::CertVerifyResult verifier1_result1;
net::CachingCertVerifier verifier(std::make_unique<net::MockCertVerifier>());
ASSERT_NO_FATAL_FAILURE(VerifyCert("ok_cert.pem", example_hostname, &verifier,
&verifier1_result1));
// Verify www2.example.com host's certificate.
std::string example2_hostname("www2.example.com");
net::CertVerifyResult verifier1_result2;
// Create a certificate that contains both a leaf and an intermediate/root and
// use that certificate for www2.example.com.
std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> chain;
chain.push_back(net::x509_util::DupCryptoBuffer(root_cert->cert_buffer()));
const scoped_refptr<net::X509Certificate> combined_cert =
net::X509Certificate::CreateFromBuffer(
net::x509_util::DupCryptoBuffer(ok_cert->cert_buffer()),
std::move(chain));
ASSERT_TRUE(combined_cert);
ignore_result(callback.GetResult(verifier.Verify(
net::CertVerifier::RequestParams(combined_cert, example2_hostname, 0,
std::string(), net::CertificateList()),
nullptr, &verifier1_result2, callback.callback(), &request,
net::NetLogWithSource())));
cronet_pb::CertVerificationCache cert_cache =
SerializeCertVerifierCache(verifier);
// Verify two certificates are serialized.
DCHECK_EQ(2, cert_cache.cert_entry_size());
DCHECK_EQ(2, cert_cache.cache_entry_size());
net::CachingCertVerifier verifier2(std::make_unique<net::MockCertVerifier>());
// Populate |verifier2|'s cache.
EXPECT_TRUE(DeserializeCertVerifierCache(cert_cache, &verifier2));
// Verify the cert for www.example.com with |verifier2|.
net::CertVerifyResult verifier2_result1;
ASSERT_NO_FATAL_FAILURE(VerifyCert("ok_cert.pem", example_hostname,
&verifier2, &verifier2_result1));
// CertVerifyResult for www.example.com with |verifier2| should match
// what was serialized with |verifier|.
EXPECT_EQ(verifier2_result1, verifier1_result1);
// Verify the cert for www2.example.com with |verifier2|.
net::CertVerifyResult verifier2_result2;
ignore_result(callback.GetResult(verifier2.Verify(
net::CertVerifier::RequestParams(combined_cert, example2_hostname, 0,
std::string(), net::CertificateList()),
nullptr, &verifier2_result2, callback.callback(), &request,
net::NetLogWithSource())));
// CertVerifyResult for www2.example.com with |verifier2| should match
// what was serialized with |verifier|.
EXPECT_EQ(verifier2_result2, verifier1_result2);
}
// A corrupted cert_entry in the serialized data should fail to be deserialized.
// Should not deserialize a corrupted cert_entry.
TEST(CertVerifierCacheSerializerTest, DeserializeCorruptedCerts) {
net::CertVerifyResult verify_result;
net::CachingCertVerifier verifier(std::make_unique<net::MockCertVerifier>());
ASSERT_NO_FATAL_FAILURE(
VerifyCert("ok_cert.pem", "www.example.com", &verifier, &verify_result));
cronet_pb::CertVerificationCache cert_cache =
SerializeCertVerifierCache(verifier);
DCHECK_EQ(1, cert_cache.cert_entry_size());
DCHECK_EQ(1, cert_cache.cache_entry_size());
cert_cache.clear_cert_entry();
net::CachingCertVerifier verifier2(std::make_unique<net::MockCertVerifier>());
EXPECT_FALSE(DeserializeCertVerifierCache(cert_cache, &verifier2));
}
// A corrupted |cache_entry| in the serialized data should fail to be
// deserialized. Should not deserialize a corrupted |cert_entry|.
TEST(CertVerifierCacheSerializerTest, DeserializeCorruptedCacheEntry) {
net::CertVerifyResult verify_result;
net::CachingCertVerifier verifier(std::make_unique<net::MockCertVerifier>());
ASSERT_NO_FATAL_FAILURE(
VerifyCert("ok_cert.pem", "www.example.com", &verifier, &verify_result));
cronet_pb::CertVerificationCache cert_cache =
SerializeCertVerifierCache(verifier);
DCHECK_EQ(1, cert_cache.cert_entry_size());
DCHECK_EQ(1, cert_cache.cache_entry_size());
// Corrupt |cache_entry|.
cert_cache.clear_cache_entry();
net::CachingCertVerifier verifier2(std::make_unique<net::MockCertVerifier>());
EXPECT_FALSE(DeserializeCertVerifierCache(cert_cache, &verifier2));
}
// A corrupted |request_params| in the serialized data should fail to be
// deserialized. Should not deserialize a corrupted |request_params|.
TEST(CertVerifierCacheSerializerTest, DeserializeCorruptedRequestParams) {
net::CertVerifyResult verify_result;
net::CachingCertVerifier verifier(std::make_unique<net::MockCertVerifier>());
ASSERT_NO_FATAL_FAILURE(
VerifyCert("ok_cert.pem", "www.example.com", &verifier, &verify_result));
cronet_pb::CertVerificationCache cert_cache =
SerializeCertVerifierCache(verifier);
DCHECK_EQ(1, cert_cache.cert_entry_size());
DCHECK_EQ(1, cert_cache.cache_entry_size());
for (int i = 0; i < cert_cache.cache_entry_size(); ++i) {
cronet_pb::CertVerificationCacheEntry* cache_entry =
cert_cache.mutable_cache_entry(i);
// Corrupt |request_params|.
cache_entry->clear_request_params();
}
net::CachingCertVerifier verifier2(std::make_unique<net::MockCertVerifier>());
EXPECT_FALSE(DeserializeCertVerifierCache(cert_cache, &verifier2));
}
// A corrupted |certificate| in |request_params| in the serialized data should
// fail to be deserialized. Should not deserialize a corrupted |certificate|.
TEST(CertVerifierCacheSerializerTest, DeserializeRequestParamsNoCertificate) {
net::CertVerifyResult verify_result;
net::CachingCertVerifier verifier(std::make_unique<net::MockCertVerifier>());
ASSERT_NO_FATAL_FAILURE(
VerifyCert("ok_cert.pem", "www.example.com", &verifier, &verify_result));
cronet_pb::CertVerificationCache cert_cache =
SerializeCertVerifierCache(verifier);
DCHECK_EQ(1, cert_cache.cert_entry_size());
DCHECK_EQ(1, cert_cache.cache_entry_size());
for (int i = 0; i < cert_cache.cache_entry_size(); ++i) {
cronet_pb::CertVerificationCacheEntry* cache_entry =
cert_cache.mutable_cache_entry(i);
cronet_pb::CertVerificationRequestParams* request_params =
cache_entry->mutable_request_params();
// Corrupt certificate.
request_params->clear_certificate();
}
net::CachingCertVerifier verifier2(std::make_unique<net::MockCertVerifier>());
EXPECT_FALSE(DeserializeCertVerifierCache(cert_cache, &verifier2));
}
// A corrupted |hostname| in |request_params| in the serialized data should
// fail to be deserialized. Should not deserialize a corrupted |hostname|.
TEST(CertVerifierCacheSerializerTest, DeserializeRequestParamsNoHostname) {
net::CertVerifyResult verify_result;
net::CachingCertVerifier verifier(std::make_unique<net::MockCertVerifier>());
ASSERT_NO_FATAL_FAILURE(
VerifyCert("ok_cert.pem", "www.example.com", &verifier, &verify_result));
cronet_pb::CertVerificationCache cert_cache =
SerializeCertVerifierCache(verifier);
DCHECK_EQ(1, cert_cache.cert_entry_size());
DCHECK_EQ(1, cert_cache.cache_entry_size());
for (int i = 0; i < cert_cache.cache_entry_size(); ++i) {
cronet_pb::CertVerificationCacheEntry* cache_entry =
cert_cache.mutable_cache_entry(i);
cronet_pb::CertVerificationRequestParams* request_params =
cache_entry->mutable_request_params();
// Corrupt hostname.
request_params->clear_hostname();
}
net::CachingCertVerifier verifier2(std::make_unique<net::MockCertVerifier>());
EXPECT_FALSE(DeserializeCertVerifierCache(cert_cache, &verifier2));
}
// An invalid |hostname| in |request_params| in the serialized data should
// fail to be deserialized. Should not deserialize an invalid |hostname|.
TEST(CertVerifierCacheSerializerTest, DeserializeRequestParamsEmptyHostname) {
net::CertVerifyResult verify_result;
net::CachingCertVerifier verifier(std::make_unique<net::MockCertVerifier>());
ASSERT_NO_FATAL_FAILURE(
VerifyCert("ok_cert.pem", "www.example.com", &verifier, &verify_result));
cronet_pb::CertVerificationCache cert_cache =
SerializeCertVerifierCache(verifier);
DCHECK_EQ(1, cert_cache.cert_entry_size());
DCHECK_EQ(1, cert_cache.cache_entry_size());
for (int i = 0; i < cert_cache.cache_entry_size(); ++i) {
cronet_pb::CertVerificationCacheEntry* cache_entry =
cert_cache.mutable_cache_entry(i);
cronet_pb::CertVerificationRequestParams* request_params =
cache_entry->mutable_request_params();
// Set bogus hostname.
request_params->set_hostname("");
}
net::CachingCertVerifier verifier2(std::make_unique<net::MockCertVerifier>());
EXPECT_FALSE(DeserializeCertVerifierCache(cert_cache, &verifier2));
}
// A corrupted |flags| in |request_params| in the serialized data should
// fail to be deserialized. Should not deserialize a corrupted |flags|.
TEST(CertVerifierCacheSerializerTest, DeserializeRequestParamsNoFlags) {
net::CertVerifyResult verify_result;
net::CachingCertVerifier verifier(std::make_unique<net::MockCertVerifier>());
ASSERT_NO_FATAL_FAILURE(
VerifyCert("ok_cert.pem", "www.example.com", &verifier, &verify_result));
cronet_pb::CertVerificationCache cert_cache =
SerializeCertVerifierCache(verifier);
DCHECK_EQ(1, cert_cache.cert_entry_size());
DCHECK_EQ(1, cert_cache.cache_entry_size());
for (int i = 0; i < cert_cache.cache_entry_size(); ++i) {
cronet_pb::CertVerificationCacheEntry* cache_entry =
cert_cache.mutable_cache_entry(i);
cronet_pb::CertVerificationRequestParams* request_params =
cache_entry->mutable_request_params();
// Corrupt flags.
request_params->clear_flags();
}
net::CachingCertVerifier verifier2(std::make_unique<net::MockCertVerifier>());
EXPECT_FALSE(DeserializeCertVerifierCache(cert_cache, &verifier2));
}
// A corrupted |ocsp_response| in |request_params| in the serialized data should
// fail to be deserialized. Should not deserialize a corrupted |ocsp_response|.
TEST(CertVerifierCacheSerializerTest, DeserializeRequestParamsNoOcspResponse) {
net::CertVerifyResult verify_result;
net::CachingCertVerifier verifier(std::make_unique<net::MockCertVerifier>());
ASSERT_NO_FATAL_FAILURE(
VerifyCert("ok_cert.pem", "www.example.com", &verifier, &verify_result));
cronet_pb::CertVerificationCache cert_cache =
SerializeCertVerifierCache(verifier);
DCHECK_EQ(1, cert_cache.cert_entry_size());
DCHECK_EQ(1, cert_cache.cache_entry_size());
for (int i = 0; i < cert_cache.cache_entry_size(); ++i) {
cronet_pb::CertVerificationCacheEntry* cache_entry =
cert_cache.mutable_cache_entry(i);
cronet_pb::CertVerificationRequestParams* request_params =
cache_entry->mutable_request_params();
// Corrupt |ocsp_response|.
request_params->clear_ocsp_response();
}
net::CachingCertVerifier verifier2(std::make_unique<net::MockCertVerifier>());
EXPECT_FALSE(DeserializeCertVerifierCache(cert_cache, &verifier2));
}
// An empty certificate number in |request_params| in the serialized data should
// fail to be deserialized. Should not deserialize an empty certificate number.
TEST(CertVerifierCacheSerializerTest,
DeserializeRequestParamsCertificateNoCertNumbers) {
net::CertVerifyResult verify_result;
net::CachingCertVerifier verifier(std::make_unique<net::MockCertVerifier>());
ASSERT_NO_FATAL_FAILURE(
VerifyCert("ok_cert.pem", "www.example.com", &verifier, &verify_result));
cronet_pb::CertVerificationCache cert_cache =
SerializeCertVerifierCache(verifier);
DCHECK_EQ(1, cert_cache.cert_entry_size());
DCHECK_EQ(1, cert_cache.cache_entry_size());
for (int i = 0; i < cert_cache.cache_entry_size(); ++i) {
cronet_pb::CertVerificationCacheEntry* cache_entry =
cert_cache.mutable_cache_entry(i);
cronet_pb::CertVerificationRequestParams* request_params =
cache_entry->mutable_request_params();
cronet_pb::CertVerificationCertificate* certificate =
request_params->mutable_certificate();
// Corrupt certificate number.
certificate->clear_cert_numbers();
}
net::CachingCertVerifier verifier2(std::make_unique<net::MockCertVerifier>());
EXPECT_FALSE(DeserializeCertVerifierCache(cert_cache, &verifier2));
}
// An invalid certificate number in |request_params| in the serialized data
// should fail to be deserialized. Should not deserialize an invalid certificate
// number.
TEST(CertVerifierCacheSerializerTest,
DeserializeCorruptedRequestParamsCertNumbers) {
net::CertVerifyResult verify_result;
net::CachingCertVerifier verifier(std::make_unique<net::MockCertVerifier>());
ASSERT_NO_FATAL_FAILURE(
VerifyCert("ok_cert.pem", "www.example.com", &verifier, &verify_result));
cronet_pb::CertVerificationCache cert_cache =
SerializeCertVerifierCache(verifier);
DCHECK_EQ(1, cert_cache.cert_entry_size());
DCHECK_EQ(1, cert_cache.cache_entry_size());
for (int i = 0; i < cert_cache.cache_entry_size(); ++i) {
cronet_pb::CertVerificationCacheEntry* cache_entry =
cert_cache.mutable_cache_entry(i);
cronet_pb::CertVerificationRequestParams* request_params =
cache_entry->mutable_request_params();
cronet_pb::CertVerificationCertificate* certificate =
request_params->mutable_certificate();
// Set bogus certificate number.
certificate->set_cert_numbers(0, 100);
}
net::CachingCertVerifier verifier2(std::make_unique<net::MockCertVerifier>());
EXPECT_FALSE(DeserializeCertVerifierCache(cert_cache, &verifier2));
}
// A corrupted certificate number in |additional_trust_anchors| of
// |request_params| in the serialized data should fail to be deserialized.
// Should not deserialize a corrupted certificate number.
TEST(CertVerifierCacheSerializerTest,
DeserializeRequestParamsCertificateNoTrustAnchors) {
net::CertificateList ca_cert_list = net::CreateCertificateListFromFile(
net::GetTestCertsDirectory(), "root_ca_cert.pem",
net::X509Certificate::FORMAT_AUTO);
ASSERT_EQ(1U, ca_cert_list.size());
scoped_refptr<net::X509Certificate> ca_cert(ca_cert_list[0]);
net::CertificateList cert_list = net::CreateCertificateListFromFile(
net::GetTestCertsDirectory(), "ok_cert.pem",
net::X509Certificate::FORMAT_AUTO);
ASSERT_EQ(1U, cert_list.size());
scoped_refptr<net::X509Certificate> cert(cert_list[0]);
// Now add the |ca_cert| to the |trust_anchors|, and verification should pass.
net::CertificateList trust_anchors;
trust_anchors.push_back(ca_cert);
net::CertVerifyResult verify_result;
net::TestCompletionCallback callback;
std::unique_ptr<net::CertVerifier::Request> request;
net::CachingCertVerifier verifier(std::make_unique<net::MockCertVerifier>());
// Verify the |cert| with |trust_anchors|.
ignore_result(callback.GetResult(verifier.Verify(
net::CertVerifier::RequestParams(cert, "www.example.com", 0,
std::string(), trust_anchors),
nullptr, &verify_result, callback.callback(), &request,
net::NetLogWithSource())));
cronet_pb::CertVerificationCache cert_cache =
SerializeCertVerifierCache(verifier);
DCHECK_EQ(2, cert_cache.cert_entry_size());
DCHECK_EQ(1, cert_cache.cache_entry_size());
for (int i = 0; i < cert_cache.cache_entry_size(); ++i) {
cronet_pb::CertVerificationCacheEntry* cache_entry =
cert_cache.mutable_cache_entry(i);
cronet_pb::CertVerificationRequestParams* request_params =
cache_entry->mutable_request_params();
for (int j = 0; j < request_params->additional_trust_anchors_size(); ++j) {
cronet_pb::CertVerificationCertificate* certificate =
request_params->mutable_additional_trust_anchors(j);
// Corrupt the certificate number in |additional_trust_anchors|.
certificate->clear_cert_numbers();
}
}
net::CachingCertVerifier verifier2(std::make_unique<net::MockCertVerifier>());
EXPECT_FALSE(DeserializeCertVerifierCache(cert_cache, &verifier2));
}
// A corrupted |cached_result| in the serialized data should fail to be
// deserialized. Should not deserialize a corrupted |cached_result|.
TEST(CertVerifierCacheSerializerTest, DeserializeCorruptedCachedResult) {
net::CertVerifyResult verify_result;
net::CachingCertVerifier verifier(std::make_unique<net::MockCertVerifier>());
ASSERT_NO_FATAL_FAILURE(
VerifyCert("ok_cert.pem", "www.example.com", &verifier, &verify_result));
cronet_pb::CertVerificationCache cert_cache =
SerializeCertVerifierCache(verifier);
DCHECK_EQ(1, cert_cache.cert_entry_size());
DCHECK_EQ(1, cert_cache.cache_entry_size());
for (int i = 0; i < cert_cache.cache_entry_size(); ++i) {
cronet_pb::CertVerificationCacheEntry* cache_entry =
cert_cache.mutable_cache_entry(i);
// Corrupt the |cached_result|.
cache_entry->clear_cached_result();
}
net::CachingCertVerifier verifier2(std::make_unique<net::MockCertVerifier>());
EXPECT_FALSE(DeserializeCertVerifierCache(cert_cache, &verifier2));
}
// A corrupted |error| in the serialized data should fail to be deserialized.
// Should not deserialize a corrupted |error|.
TEST(CertVerifierCacheSerializerTest, DeserializeCachedResultNoError) {
net::CertVerifyResult verify_result;
net::CachingCertVerifier verifier(std::make_unique<net::MockCertVerifier>());
ASSERT_NO_FATAL_FAILURE(
VerifyCert("ok_cert.pem", "www.example.com", &verifier, &verify_result));
cronet_pb::CertVerificationCache cert_cache =
SerializeCertVerifierCache(verifier);
DCHECK_EQ(1, cert_cache.cert_entry_size());
DCHECK_EQ(1, cert_cache.cache_entry_size());
for (int i = 0; i < cert_cache.cache_entry_size(); ++i) {
cronet_pb::CertVerificationCacheEntry* cache_entry =
cert_cache.mutable_cache_entry(i);
cronet_pb::CertVerificationCachedResult* cached_result =
cache_entry->mutable_cached_result();
// Corrupt |error|.
cached_result->clear_error();
}
net::CachingCertVerifier verifier2(std::make_unique<net::MockCertVerifier>());
EXPECT_FALSE(DeserializeCertVerifierCache(cert_cache, &verifier2));
}
// A corrupted |result| in the serialized data should fail to be deserialized.
// Should not deserialize a corrupted |result|.
TEST(CertVerifierCacheSerializerTest, DeserializeCachedResultNoResult) {
net::CertVerifyResult verify_result;
net::CachingCertVerifier verifier(std::make_unique<net::MockCertVerifier>());
ASSERT_NO_FATAL_FAILURE(
VerifyCert("ok_cert.pem", "www.example.com", &verifier, &verify_result));
cronet_pb::CertVerificationCache cert_cache =
SerializeCertVerifierCache(verifier);
DCHECK_EQ(1, cert_cache.cert_entry_size());
DCHECK_EQ(1, cert_cache.cache_entry_size());
for (int i = 0; i < cert_cache.cache_entry_size(); ++i) {
cronet_pb::CertVerificationCacheEntry* cache_entry =
cert_cache.mutable_cache_entry(i);
cronet_pb::CertVerificationCachedResult* cached_result =
cache_entry->mutable_cached_result();
// Corrupt the |result|.
cached_result->clear_result();
}
net::CachingCertVerifier verifier2(std::make_unique<net::MockCertVerifier>());
EXPECT_FALSE(DeserializeCertVerifierCache(cert_cache, &verifier2));
}
// A corrupted |cert_status| in the serialized data should fail to be
// deserialized. Should not deserialize a corrupted |cert_status|.
TEST(CertVerifierCacheSerializerTest, DeserializeCachedResultNoCertStatus) {
net::CertVerifyResult verify_result;
net::CachingCertVerifier verifier(std::make_unique<net::MockCertVerifier>());
ASSERT_NO_FATAL_FAILURE(
VerifyCert("ok_cert.pem", "www.example.com", &verifier, &verify_result));
cronet_pb::CertVerificationCache cert_cache =
SerializeCertVerifierCache(verifier);
DCHECK_EQ(1, cert_cache.cert_entry_size());
DCHECK_EQ(1, cert_cache.cache_entry_size());
for (int i = 0; i < cert_cache.cache_entry_size(); ++i) {
cronet_pb::CertVerificationCacheEntry* cache_entry =
cert_cache.mutable_cache_entry(i);
cronet_pb::CertVerificationCachedResult* cached_result =
cache_entry->mutable_cached_result();
cronet_pb::CertVerificationResult* result = cached_result->mutable_result();
// Corrupt the |cert_status|.
result->clear_cert_status();
}
net::CachingCertVerifier verifier2(std::make_unique<net::MockCertVerifier>());
EXPECT_FALSE(DeserializeCertVerifierCache(cert_cache, &verifier2));
}
// A corrupted |verification_time| in the serialized data should fail to be
// deserialized. Should not deserialize a corrupted |verification_time|.
TEST(CertVerifierCacheSerializerTest, DeserializeCachedResultNoVerifiedCert) {
net::CertVerifyResult verify_result;
net::CachingCertVerifier verifier(std::make_unique<net::MockCertVerifier>());
ASSERT_NO_FATAL_FAILURE(
VerifyCert("ok_cert.pem", "www.example.com", &verifier, &verify_result));
cronet_pb::CertVerificationCache cert_cache =
SerializeCertVerifierCache(verifier);
DCHECK_EQ(1, cert_cache.cert_entry_size());
DCHECK_EQ(1, cert_cache.cache_entry_size());
for (int i = 0; i < cert_cache.cache_entry_size(); ++i) {
cronet_pb::CertVerificationCacheEntry* cache_entry =
cert_cache.mutable_cache_entry(i);
cronet_pb::CertVerificationCachedResult* cached_result =
cache_entry->mutable_cached_result();
cronet_pb::CertVerificationResult* result = cached_result->mutable_result();
// Corrupt the |verified_cert|.
result->clear_verified_cert();
}
net::CachingCertVerifier verifier2(std::make_unique<net::MockCertVerifier>());
EXPECT_FALSE(DeserializeCertVerifierCache(cert_cache, &verifier2));
}
// A corrupted |verified_cert| in the serialized data should fail to be
// deserialized. Should not deserialize a corrupted |verified_cert|.
TEST(CertVerifierCacheSerializerTest,
DeserializeCachedResultNoVerifiedCertNumber) {
net::CertVerifyResult verify_result;
net::CachingCertVerifier verifier(std::make_unique<net::MockCertVerifier>());
ASSERT_NO_FATAL_FAILURE(
VerifyCert("ok_cert.pem", "www.example.com", &verifier, &verify_result));
cronet_pb::CertVerificationCache cert_cache =
SerializeCertVerifierCache(verifier);
DCHECK_EQ(1, cert_cache.cert_entry_size());
DCHECK_EQ(1, cert_cache.cache_entry_size());
for (int i = 0; i < cert_cache.cache_entry_size(); ++i) {
cronet_pb::CertVerificationCacheEntry* cache_entry =
cert_cache.mutable_cache_entry(i);
cronet_pb::CertVerificationCachedResult* cached_result =
cache_entry->mutable_cached_result();
cronet_pb::CertVerificationResult* result = cached_result->mutable_result();
result->clear_verified_cert();
// Corrupt the verified cert's certificate number.
cronet_pb::CertVerificationCertificate* certificate =
result->mutable_verified_cert();
certificate->clear_cert_numbers();
}
net::CachingCertVerifier verifier2(std::make_unique<net::MockCertVerifier>());
EXPECT_FALSE(DeserializeCertVerifierCache(cert_cache, &verifier2));
}
// An invalid certificate number of |verified_cert| in the serialized data
// should fail to be deserialized. Should not deserialize an invalid certificate
// number.
TEST(CertVerifierCacheSerializerTest,
DeserializeCorruptedCachedResultVerifiedCertNumber) {
net::CertVerifyResult verify_result;
net::CachingCertVerifier verifier(std::make_unique<net::MockCertVerifier>());
ASSERT_NO_FATAL_FAILURE(
VerifyCert("ok_cert.pem", "www.example.com", &verifier, &verify_result));
cronet_pb::CertVerificationCache cert_cache =
SerializeCertVerifierCache(verifier);
DCHECK_EQ(1, cert_cache.cert_entry_size());
DCHECK_EQ(1, cert_cache.cache_entry_size());
for (int i = 0; i < cert_cache.cache_entry_size(); ++i) {
cronet_pb::CertVerificationCacheEntry* cache_entry =
cert_cache.mutable_cache_entry(i);
cronet_pb::CertVerificationCachedResult* cached_result =
cache_entry->mutable_cached_result();
cronet_pb::CertVerificationResult* result = cached_result->mutable_result();
cronet_pb::CertVerificationCertificate* certificate =
result->mutable_verified_cert();
// Set bogus certificate number for |verified_cert|.
certificate->set_cert_numbers(0, 100);
}
net::CachingCertVerifier verifier2(std::make_unique<net::MockCertVerifier>());
EXPECT_FALSE(DeserializeCertVerifierCache(cert_cache, &verifier2));
}
// A corrupted |public_key_hashes| in the serialized data should fail to be
// deserialized. Should not deserialize a corrupted |public_key_hashes|.
TEST(CertVerifierCacheSerializerTest,
DeserializeCorruptedCachedResultPublicKeyHashes) {
net::CertVerifyResult verify_result;
net::CachingCertVerifier verifier(std::make_unique<net::MockCertVerifier>());
ASSERT_NO_FATAL_FAILURE(
VerifyCert("ok_cert.pem", "www.example.com", &verifier, &verify_result));
cronet_pb::CertVerificationCache cert_cache =
SerializeCertVerifierCache(verifier);
DCHECK_EQ(1, cert_cache.cert_entry_size());
DCHECK_EQ(1, cert_cache.cache_entry_size());
for (int i = 0; i < cert_cache.cache_entry_size(); ++i) {
cronet_pb::CertVerificationCacheEntry* cache_entry =
cert_cache.mutable_cache_entry(i);
cronet_pb::CertVerificationCachedResult* cached_result =
cache_entry->mutable_cached_result();
cronet_pb::CertVerificationResult* result = cached_result->mutable_result();
// Set bogus |public_key_hashes|.
result->add_public_key_hashes("");
}
net::CachingCertVerifier verifier2(std::make_unique<net::MockCertVerifier>());
EXPECT_FALSE(DeserializeCertVerifierCache(cert_cache, &verifier2));
}
// A corrupted |verification_time| in the serialized data should fail to be
// deserialized. Should not deserialize a corrupted |verification_time|.
TEST(CertVerifierCacheSerializerTest, DeserializeCorruptedVerificationTime) {
net::CertVerifyResult verify_result;
net::CachingCertVerifier verifier(std::make_unique<net::MockCertVerifier>());
ASSERT_NO_FATAL_FAILURE(
VerifyCert("ok_cert.pem", "www.example.com", &verifier, &verify_result));
cronet_pb::CertVerificationCache cert_cache =
SerializeCertVerifierCache(verifier);
DCHECK_EQ(1, cert_cache.cert_entry_size());
DCHECK_EQ(1, cert_cache.cache_entry_size());
for (int i = 0; i < cert_cache.cache_entry_size(); ++i) {
cronet_pb::CertVerificationCacheEntry* cache_entry =
cert_cache.mutable_cache_entry(i);
// Corrupt |verification_time|.
cache_entry->clear_verification_time();
}
net::CachingCertVerifier verifier2(std::make_unique<net::MockCertVerifier>());
EXPECT_FALSE(DeserializeCertVerifierCache(cert_cache, &verifier2));
}
} // namespace cronet