Commit 87bf0f71 authored by Dmitry Lomov's avatar Dmitry Lomov

Revert "Certificate Transparency: Code for unpacking EV cert hashes whitelist"

This reverts commit 743f614e.
It breaks X509CertificateTest.SHA256FingerprintsCorrectly on Vista.

BUG=339128
TBR=eranm@chromium.org
NOTRY=true

Review URL: https://codereview.chromium.org/542673002

Cr-Commit-Position: refs/heads/master@{#293300}
parent f8d6f659
// Copyright 2014 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/cert/ct_ev_whitelist.h"
#include <set>
#include "base/big_endian.h"
#include "base/file_util.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
namespace net {
namespace ct {
namespace {
base::LazyInstance<std::set<std::string> >::Leaky g_current_ev_whitelist =
LAZY_INSTANCE_INITIALIZER;
const uint8 kCertHashLengthBits = 64; // 8 bytes
const uint64 kGolombMParameterBits = 47; // 2^47
} // namespace
namespace internal {
BitStreamReader::BitStreamReader(const char* source, size_t length)
: source_(source), length_(length), current_byte_(0), current_bit_(7) {
}
bool BitStreamReader::ReadUnaryEncoding(uint64* out) {
uint64 res = 0;
if (BitsLeft() == 0)
return false;
while ((BitsLeft() > 0) && ReadBit())
res++;
*out = res;
return true;
}
bool BitStreamReader::ReadBits(uint8 num_bits, uint64* out) {
if (num_bits > 64)
return false;
if (BitsLeft() < num_bits)
return false;
uint64 res = 0;
for (uint8 i = 0; i < num_bits; ++i)
res |= (static_cast<uint64>(ReadBit()) << (num_bits - (i + 1)));
*out = res;
return true;
}
uint64 BitStreamReader::BitsLeft() const {
if (current_byte_ == length_)
return 0;
return (length_ - (current_byte_ + 1)) * 8 + current_bit_ + 1;
}
uint8 BitStreamReader::ReadBit() {
DCHECK_GT(BitsLeft(), 0u);
DCHECK(current_bit_ < 8 && current_bit_ >= 0);
uint8 res = (source_[current_byte_] & (1 << current_bit_)) >> current_bit_;
current_bit_--;
if (current_bit_ < 0) {
current_byte_++;
current_bit_ = 7;
}
return res;
}
bool UncompressEVWhitelist(const std::string& compressed_whitelist,
std::set<std::string>* uncompressed_list) {
BitStreamReader reader(compressed_whitelist.data(),
compressed_whitelist.size());
std::set<std::string> result;
VLOG(1) << "Uncompressing EV whitelist of size "
<< compressed_whitelist.size();
uint64 curr_hash(0);
if (!reader.ReadBits(kCertHashLengthBits, &curr_hash)) {
VLOG(1) << "Failed reading first hash.";
return false;
}
char hash_bytes[8];
base::WriteBigEndian(hash_bytes, curr_hash);
result.insert(std::string(hash_bytes, 8));
static const uint64 M = static_cast<uint64>(1) << kGolombMParameterBits;
while (reader.BitsLeft() > kGolombMParameterBits) {
uint64 read_prefix = 0;
if (!reader.ReadUnaryEncoding(&read_prefix)) {
VLOG(1) << "Failed reading unary-encoded prefix.";
return false;
}
uint64 r = 0;
if (!reader.ReadBits(kGolombMParameterBits, &r)) {
VLOG(1) << "Failed reading " << kGolombMParameterBits << " bits.";
return false;
}
uint64 curr_diff = read_prefix * M + r;
curr_hash += curr_diff;
base::WriteBigEndian(hash_bytes, curr_hash);
result.insert(std::string(hash_bytes, 8));
}
uncompressed_list->swap(result);
return true;
}
void SetEVWhitelistData(std::set<std::string>& ev_whitelist) {
g_current_ev_whitelist.Get().swap(ev_whitelist);
}
} // namespace internal
void SetEVWhitelistFromFile(const base::FilePath& compressed_whitelist_file) {
VLOG(1) << "Setting EV whitelist from file: "
<< compressed_whitelist_file.value();
std::string compressed_list;
if (!base::ReadFileToString(compressed_whitelist_file, &compressed_list)) {
VLOG(1) << "Failed reading from " << compressed_whitelist_file.value();
return;
}
std::set<std::string> uncompressed_list;
if (!internal::UncompressEVWhitelist(compressed_list, &uncompressed_list)) {
VLOG(1) << "Failed uncompressing.";
return;
}
VLOG(1) << "Uncompressing succeeded, hashes: " << uncompressed_list.size();
internal::SetEVWhitelistData(uncompressed_list);
}
bool IsCertificateHashInWhitelist(const std::string& certificate_hash) {
const std::set<std::string>& current_ev_whitelist =
g_current_ev_whitelist.Get();
return current_ev_whitelist.find(certificate_hash) !=
current_ev_whitelist.end();
}
bool HasValidEVWhitelist() {
return !g_current_ev_whitelist.Get().empty();
}
} // namespace ct
} // namespace net
// Copyright 2014 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.
#ifndef NET_CERT_CT_EV_WHITELIST_H_
#define NET_CERT_CT_EV_WHITELIST_H_
#include <set>
#include <string>
#include "base/files/file_path.h"
#include "net/base/net_export.h"
namespace net {
namespace ct {
namespace internal {
// Abstraction over a stream of bits, to be read independently
// of the bytes they're packed into. Bits are read MSB-first from the stream.
// It is limited to 64-bit reads and is inefficient as a design choice - Since
// it is used infrequently to unpack the Golomb-coded EV certificate hashes
// whitelist in a blocking thread.
//
// This class is declared here so it can be tested.
class NET_EXPORT_PRIVATE BitStreamReader {
public:
BitStreamReader(const char* source, size_t length);
// Reads unary-encoded number into |out|. Returns true if
// there was at least one bit to read, false otherwise.
bool ReadUnaryEncoding(uint64* out);
// Reads |num_bits| (up to 64) into |out|. |out| is filled from the MSB to the
// LSB. If |num_bits| is less than 64, the most significant |64 - num_bits|
// bits are unused and left as zeros. Returns true if the stream had the
// requested |num_bits|, false otherwise.
bool ReadBits(uint8 num_bits, uint64* out);
// Returns the number of bits left in the stream.
uint64 BitsLeft() const;
private:
// Reads a single bit. Within a byte, the bits are read from the MSB to the
// LSB.
uint8 ReadBit();
const char* const source_;
const size_t length_;
// Index of the byte currently being read from.
uint64 current_byte_;
// Index of the last bit read within |current_byte_|. Since bits are read
// from the MSB to the LSB, this value is initialized to 7 and decremented
// after each read.
int8 current_bit_;
};
// Given a Golomb-coded list of hashes in |compressed_whitelist|, unpack into
// |uncompressed_list|. Returns true if the format of the compressed whitelist
// is valid, false otherwise.
NET_EXPORT_PRIVATE bool UncompressEVWhitelist(
const std::string& compressed_whitelist,
std::set<std::string>* uncompressed_list);
// Sets the given |ev_whitelist| into the global context.
// Note that |ev_whitelist| will contain the old EV whitelist data after this
// call as the implementation is using set::swap() to efficiently switch the
// sets.
NET_EXPORT_PRIVATE void SetEVWhitelistData(std::set<std::string>& ev_whitelist);
} // namespace internal
// Sets the global EV certificate hashes whitelist from
// |compressed_whitelist_file| in the global context, after uncompressing it.
// If the data in |compressed_whitelist_file| is not a valid compressed
// whitelist, does nothing.
NET_EXPORT void SetEVWhitelistFromFile(
const base::FilePath& compressed_whitelist_file);
// Returns true if the |certificate_hash| appears in the EV certificate hashes
// whitelist.
NET_EXPORT bool IsCertificateHashInWhitelist(
const std::string& certificate_hash);
// Returns true if the global EV certificate hashes whitelist is non-empty,
// false otherwise.
NET_EXPORT bool HasValidEVWhitelist();
} // namespace ct
} // namespace net
#endif // NET_CERT_CT_EV_WHITELIST_H_
// Copyright 2014 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/cert/ct_ev_whitelist.h"
#include <string>
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
namespace ct {
namespace internal {
const uint8 kSomeData[] = {0xd5, 0xe2, 0xaf, 0xe5, 0xbb, 0x10, 0x7c, 0xd1};
TEST(BitStreamReaderTest, CanReadSingleByte) {
BitStreamReader reader(reinterpret_cast<const char*>(kSomeData), 1);
uint64 v(0);
EXPECT_EQ(8u, reader.BitsLeft());
EXPECT_TRUE(reader.ReadBits(8, &v));
EXPECT_EQ(UINT64_C(0xd5), v);
EXPECT_FALSE(reader.ReadBits(1, &v));
EXPECT_EQ(0u, reader.BitsLeft());
}
TEST(BitStreamReaderTest, CanReadSingleBits) {
const uint64 expected_bits[] = {1, 1, 0, 1, 0, 1, 0, 1,
1, 1, 1, 0, 0, 0, 1, 0};
BitStreamReader reader(reinterpret_cast<const char*>(kSomeData), 2);
EXPECT_EQ(16u, reader.BitsLeft());
uint64 v(0);
for (int i = 0; i < 16; ++i) {
EXPECT_TRUE(reader.ReadBits(1, &v));
EXPECT_EQ(expected_bits[i], v);
}
EXPECT_EQ(0u, reader.BitsLeft());
}
TEST(BitStreamReaderTest, CanReadBitGroups) {
BitStreamReader reader(reinterpret_cast<const char*>(kSomeData), 3);
EXPECT_EQ(24u, reader.BitsLeft());
uint64 v(0);
uint64 res(0);
EXPECT_TRUE(reader.ReadBits(5, &v));
res |= v << 19;
EXPECT_EQ(19u, reader.BitsLeft());
EXPECT_TRUE(reader.ReadBits(13, &v));
res |= v << 6;
EXPECT_EQ(6u, reader.BitsLeft());
EXPECT_TRUE(reader.ReadBits(6, &v));
res |= v;
EXPECT_EQ(UINT64_C(0xd5e2af), res);
EXPECT_FALSE(reader.ReadBits(1, &v));
}
TEST(BitStreamReaderTest, CanRead64Bit) {
BitStreamReader reader(reinterpret_cast<const char*>(kSomeData), 8);
EXPECT_EQ(64u, reader.BitsLeft());
uint64 v(0);
EXPECT_TRUE(reader.ReadBits(64, &v));
EXPECT_EQ(UINT64_C(0xd5e2afe5bb107cd1), v);
}
TEST(BitStreamReaderTest, CanReadUnaryEncodedNumbers) {
BitStreamReader reader(reinterpret_cast<const char*>(kSomeData), 3);
const uint64 expected_values[] = {2, 1, 1, 4, 0, 0, 1, 1, 1, 4};
uint64 v(0);
for (int i = 0; i < 10; ++i) {
EXPECT_TRUE(reader.ReadUnaryEncoding(&v));
EXPECT_EQ(expected_values[i], v) << "Values differ at position " << i;
}
}
} // namespace internal
namespace {
const uint8 kFirstHashRaw[] = {0x00, 0x00, 0x03, 0xd7, 0xfc, 0x18, 0x02, 0xcb};
std::string GetFirstHash() {
return std::string(reinterpret_cast<const char*>(kFirstHashRaw), 8);
}
// Second hash: Diff from first hash is > 2^47
const uint8 kSecondHashRaw[] = {0x00, 0x01, 0x05, 0xd2, 0x58, 0x47, 0xa7, 0xbf};
std::string GetSecondHash() {
return std::string(reinterpret_cast<const char*>(kSecondHashRaw), 8);
}
// Third hash: Diff from 2nd hash is < 2^47
const uint8 kThirdHashRaw[] = {0x00, 0x01, 0x48, 0x45, 0x8c, 0x53, 0x03, 0x94};
std::string GetThirdHash() {
return std::string(reinterpret_cast<const char*>(kThirdHashRaw), 8);
}
const uint8 kWhitelistData[] = {
0x00, 0x00, 0x03, 0xd7, 0xfc, 0x18, 0x02, 0xcb, // First hash
0xc0, 0x7e, 0x97, 0x0b, 0xe9, 0x3d, 0x10, 0x9c,
0xcd, 0x02, 0xd6, 0xf5, 0x40,
};
} // namespace
TEST(CTEVWhitelistTest, UncompressFailsForTooShortList) {
// This list does not contain enough bytes even for the first hash.
std::set<std::string> res;
EXPECT_FALSE(internal::UncompressEVWhitelist(
std::string(reinterpret_cast<const char*>(kWhitelistData), 7), &res));
}
TEST(CTEVWhitelistTest, UncompressFailsForTruncatedList) {
// This list is missing bits for the second part of the diff.
std::set<std::string> res;
EXPECT_FALSE(internal::UncompressEVWhitelist(
std::string(reinterpret_cast<const char*>(kWhitelistData), 14), &res));
}
TEST(CTEVWhitelistTest, UncompressesWhitelistCorrectly) {
std::set<std::string> res;
ASSERT_TRUE(internal::UncompressEVWhitelist(
std::string(reinterpret_cast<const char*>(kWhitelistData),
arraysize(kWhitelistData)),
&res));
// Ensure first hash is found
EXPECT_TRUE(res.find(GetFirstHash()) != res.end());
// Ensure second hash is found
EXPECT_TRUE(res.find(GetSecondHash()) != res.end());
// Ensure last hash is found
EXPECT_TRUE(res.find(GetThirdHash()) != res.end());
// Ensure that there are exactly 3 hashes.
EXPECT_EQ(3u, res.size());
}
TEST(CTEVWhitelistTest, CanFindHashInSetList) {
std::set<std::string> whitelist_data;
whitelist_data.insert(GetFirstHash());
internal::SetEVWhitelistData(whitelist_data);
EXPECT_TRUE(IsCertificateHashInWhitelist(GetFirstHash()));
}
TEST(CTEVWhitelistTest, CannotFindOldHashAfterSetList) {
std::set<std::string> whitelist_data;
whitelist_data.insert(GetFirstHash());
internal::SetEVWhitelistData(whitelist_data);
EXPECT_TRUE(IsCertificateHashInWhitelist(GetFirstHash()));
std::set<std::string> new_whitelist_data;
new_whitelist_data.insert(GetSecondHash());
internal::SetEVWhitelistData(new_whitelist_data);
EXPECT_TRUE(IsCertificateHashInWhitelist(GetSecondHash()));
EXPECT_FALSE(IsCertificateHashInWhitelist(GetFirstHash()));
}
TEST(CTEVWhitelistTest, CorrectlyIdentifiesWhitelistIsInvalid) {
std::set<std::string> whitelist_data;
internal::SetEVWhitelistData(whitelist_data);
EXPECT_FALSE(HasValidEVWhitelist());
}
TEST(CTEVWhitelistTest, CorrectlyIdentifiesWhitelistIsValid) {
std::set<std::string> whitelist_data;
whitelist_data.insert(GetFirstHash());
internal::SetEVWhitelistData(whitelist_data);
EXPECT_TRUE(HasValidEVWhitelist());
}
} // namespace ct
} // namespace net
......@@ -395,10 +395,6 @@ class NET_EXPORT X509Certificate
// the same.
static SHA1HashValue CalculateFingerprint(OSCertHandle cert_handle);
// Calculates the SHA-256 fingerprint of the certificate. Returns an empty
// (all zero) fingerprint on failure.
static SHA256HashValue CalculateFingerprint256(OSCertHandle cert_handle);
// Calculates the SHA-1 fingerprint of the intermediate CA certificates.
// Returns an empty (all zero) fingerprint on failure.
//
......
......@@ -183,22 +183,6 @@ SHA1HashValue X509Certificate::CalculateFingerprint(
return sha1;
}
// static
SHA256HashValue X509Certificate::CalculateFingerprint256(OSCertHandle cert) {
SHA256HashValue sha256;
memset(sha256.data, 0, sizeof(sha256.data));
ScopedCFTypeRef<CFDataRef> cert_data(SecCertificateCopyData(cert));
if (!cert_data)
return sha256;
DCHECK(CFDataGetBytePtr(cert_data));
DCHECK_NE(0, CFDataGetLength(cert_data));
CC_SHA256(
CFDataGetBytePtr(cert_data), CFDataGetLength(cert_data), sha256.data);
return sha256;
}
// static
SHA1HashValue X509Certificate::CalculateCAFingerprint(
const OSCertHandles& intermediates) {
......
......@@ -373,24 +373,6 @@ SHA1HashValue X509Certificate::CalculateFingerprint(
return sha1;
}
// static
SHA256HashValue X509Certificate::CalculateFingerprint256(OSCertHandle cert) {
SHA256HashValue sha256;
memset(sha256.data, 0, sizeof(sha256.data));
CSSM_DATA cert_data;
OSStatus status = SecCertificateGetData(cert, &cert_data);
if (status)
return sha256;
DCHECK(cert_data.Data);
DCHECK_NE(cert_data.Length, 0U);
CC_SHA256(cert_data.Data, cert_data.Length, sha256.data);
return sha256;
}
// static
SHA1HashValue X509Certificate::CalculateCAFingerprint(
const OSCertHandles& intermediates) {
......
......@@ -224,21 +224,6 @@ SHA1HashValue X509Certificate::CalculateFingerprint(
return sha1;
}
// static
SHA256HashValue X509Certificate::CalculateFingerprint256(OSCertHandle cert) {
SHA256HashValue sha256;
memset(sha256.data, 0, sizeof(sha256.data));
DCHECK(NULL != cert->derCert.data);
DCHECK_NE(0U, cert->derCert.len);
SECStatus rv = HASH_HashBuf(
HASH_AlgSHA256, sha256.data, cert->derCert.data, cert->derCert.len);
DCHECK_EQ(SECSuccess, rv);
return sha256;
}
// static
SHA1HashValue X509Certificate::CalculateCAFingerprint(
const OSCertHandles& intermediates) {
......
......@@ -293,16 +293,6 @@ SHA1HashValue X509Certificate::CalculateFingerprint(OSCertHandle cert) {
return sha1;
}
// static
SHA256HashValue X509Certificate::CalculateFingerprint256(OSCertHandle cert) {
SHA256HashValue sha256;
unsigned int sha256_size = static_cast<unsigned int>(sizeof(sha256.data));
int ret = X509_digest(cert, EVP_sha256(), sha256.data, &sha256_size);
CHECK(ret);
CHECK_EQ(sha256_size, sizeof(sha256.data));
return sha256;
}
// static
SHA1HashValue X509Certificate::CalculateCAFingerprint(
const OSCertHandles& intermediates) {
......
......@@ -323,22 +323,6 @@ TEST(X509CertificateTest, SerialNumbers) {
paypal_null_serial, sizeof(paypal_null_serial)) == 0);
}
TEST(X509CertificateTest, SHA256FingerprintsCorrectly) {
scoped_refptr<X509Certificate> google_cert(X509Certificate::CreateFromBytes(
reinterpret_cast<const char*>(google_der), sizeof(google_der)));
static const uint8 google_sha256_fingerprint[32] = {
0x21, 0xaf, 0x58, 0x74, 0xea, 0x6b, 0xad, 0xbd, 0xe4, 0xb3, 0xb1,
0xaa, 0x53, 0x32, 0x80, 0x8f, 0xbf, 0x8a, 0x24, 0x7d, 0x98, 0xec,
0x7f, 0x77, 0x49, 0x38, 0x42, 0x81, 0x26, 0x7f, 0xed, 0x38};
SHA256HashValue fingerprint =
X509Certificate::CalculateFingerprint256(google_cert->os_cert_handle());
for (size_t i = 0; i < 32; ++i)
EXPECT_EQ(google_sha256_fingerprint[i], fingerprint.data[i]);
}
TEST(X509CertificateTest, CAFingerprints) {
base::FilePath certs_dir = GetTestCertsDirectory();
......
......@@ -313,27 +313,6 @@ SHA1HashValue X509Certificate::CalculateFingerprint(
return sha1;
}
// static
SHA256HashValue X509Certificate::CalculateFingerprint256(OSCertHandle cert) {
DCHECK(NULL != cert->pbCertEncoded);
DCHECK_NE(static_cast<DWORD>(0), cert->cbCertEncoded);
BOOL rv;
SHA256HashValue sha256;
DWORD sha256_size = sizeof(sha256.data);
rv = CryptHashCertificate(NULL,
CALG_SHA_256,
0,
cert->pbCertEncoded,
cert->cbCertEncoded,
sha256.data,
&sha256_size);
DCHECK(rv && sha256_size == sizeof(sha256.data));
if (!rv)
memset(sha256.data, 0, sizeof(sha256.data));
return sha256;
}
// TODO(wtc): This function is implemented with NSS low-level hash
// functions to ensure it is fast. Reimplement this function with
// CryptoAPI. May need to cache the HCRYPTPROV to reduce the overhead.
......
......@@ -304,8 +304,6 @@
'cert/cert_verify_proc_win.h',
'cert/crl_set_storage.cc',
'cert/crl_set_storage.h',
'cert/ct_ev_whitelist.cc',
'cert/ct_ev_whitelist.h',
'cert/ct_known_logs.cc',
'cert/ct_known_logs.h',
'cert/ct_known_logs_static.h',
......@@ -1285,7 +1283,6 @@
'base/url_util_unittest.cc',
'cert/cert_verify_proc_unittest.cc',
'cert/crl_set_unittest.cc',
'cert/ct_ev_whitelist_unittest.cc',
'cert/ct_log_response_parser_unittest.cc',
'cert/ct_log_verifier_unittest.cc',
'cert/ct_objects_extractor_unittest.cc',
......
......@@ -93,7 +93,6 @@
#include "net/cert/asn1_util.h"
#include "net/cert/cert_status_flags.h"
#include "net/cert/cert_verifier.h"
#include "net/cert/ct_ev_whitelist.h"
#include "net/cert/ct_objects_extractor.h"
#include "net/cert/ct_verifier.h"
#include "net/cert/ct_verify_result.h"
......@@ -3427,17 +3426,6 @@ int SSLClientSocketNSS::DoVerifyCertComplete(int result) {
result = ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN;
}
if (server_cert_verify_result_.cert_status & CERT_STATUS_IS_EV &&
ct::HasValidEVWhitelist()) {
const SHA256HashValue fingerprint(X509Certificate::CalculateFingerprint256(
server_cert_verify_result_.verified_cert->os_cert_handle()));
UMA_HISTOGRAM_BOOLEAN(
"Net.SSL_EVCertificateInWhitelist",
ct::IsCertificateHashInWhitelist(
std::string(reinterpret_cast<const char*>(fingerprint.data), 8)));
}
if (result == OK) {
// Only check Certificate Transparency if there were no other errors with
// the connection.
......
......@@ -14188,7 +14188,7 @@ Therefore, the affected-histogram name has to have at least one dot in it.
</histogram>
<histogram name="Net.CertificateTransparency.MainFrameValidSCTCount">
<owner>eranm@chromium.org</owner>
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
Number of valid Signed Certificate Timestamps (SCTs) present for the
main-frame resource. Emitted every time a main-frame resource is fetched.
......@@ -14196,7 +14196,7 @@ Therefore, the affected-histogram name has to have at least one dot in it.
</histogram>
<histogram name="Net.CertificateTransparency.SCTOrigin" enum="SCTOrigin">
<owner>eranm@chromium.org</owner>
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
The origin breakdown of Signed Certificate Timestamps (SCTs). Emitted once
for every SCT when first validated, which means 0 or more times during every
......@@ -14205,7 +14205,7 @@ Therefore, the affected-histogram name has to have at least one dot in it.
</histogram>
<histogram name="Net.CertificateTransparency.SCTsPerConnection">
<owner>eranm@chromium.org</owner>
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
The number of Signed Certificate Timestamps (SCTs) that were available for
each SSL connection, including SCTs embedded in the certificate. This metric
......@@ -14215,7 +14215,7 @@ Therefore, the affected-histogram name has to have at least one dot in it.
</histogram>
<histogram name="Net.CertificateTransparency.SCTStatus" enum="SCTVerifyStatus">
<owner>eranm@chromium.org</owner>
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
Breakdown of Signed Certificate Timestamps (SCTs) validation status. Emitted
once for every SCT when first validated, which means 0 or more times during
......@@ -17359,16 +17359,6 @@ Therefore, the affected-histogram name has to have at least one dot in it.
</summary>
</histogram>
<histogram name="Net.SSL_EVCertificateInWhitelist" enum="Boolean">
<owner>eranm@chromium.org</owner>
<owner>rsleevi@chromium.org</owner>
<summary>
Whether an EV certificate is present in the Certificate Transparency
whitelist. Emitted once for every EV certificate encountered (during SSL
connection establishment), but only if the client has a valid whitelist.
</summary>
</histogram>
<histogram name="Net.SSLCertBlacklisted">
<owner>agl@chromium.org</owner>
<summary>
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