diff options
-rw-r--r-- | net/base/crl_filter.cc | 878 | ||||
-rw-r--r-- | net/base/crl_filter.h | 114 | ||||
-rw-r--r-- | net/base/crl_filter_unittest.cc | 216 | ||||
-rw-r--r-- | net/base/crl_set.cc | 442 | ||||
-rw-r--r-- | net/base/crl_set.h | 97 | ||||
-rw-r--r-- | net/base/crl_set_unittest.cc | 271 | ||||
-rw-r--r-- | net/net.gyp | 6 |
7 files changed, 813 insertions, 1211 deletions
diff --git a/net/base/crl_filter.cc b/net/base/crl_filter.cc deleted file mode 100644 index d438cc7..0000000 --- a/net/base/crl_filter.cc +++ /dev/null @@ -1,878 +0,0 @@ -// Copyright (c) 2011 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 "base/base64.h" -#include "base/json/json_reader.h" -#include "base/logging.h" -#include "base/stl_util.h" -#include "base/values.h" -#include "crypto/sha2.h" -#include "net/base/crl_filter.h" - -#if defined(USE_SYSTEM_ZLIB) -#include <zlib.h> -#else -#include "third_party/zlib/zlib.h" -#endif - -namespace net { - -// Decompress zlib decompressed |in| into |out|. |out_len| is the number of -// bytes at |out| and must be exactly equal to the size of the decompressed -// data. |dict| optionally contains a pre-shared dictionary. -static bool DecompressZlib(char* out, int out_len, base::StringPiece in, - base::StringPiece dict) { - z_stream z; - memset(&z, 0, sizeof(z)); - - z.next_in = reinterpret_cast<Bytef*>(const_cast<char*>(in.data())); - z.avail_in = in.size(); - z.next_out = reinterpret_cast<Bytef*>(out); - z.avail_out = out_len; - - if (inflateInit(&z) != Z_OK) - return false; - bool ret = false; - int r = inflate(&z, Z_FINISH); - if (r == Z_NEED_DICT) { - r = inflateSetDictionary(&z, reinterpret_cast<const Bytef*>(dict.data()), - dict.size()); - if (r != Z_OK) - goto err; - r = inflate(&z, Z_FINISH); - } - if (r != Z_STREAM_END) - goto err; - if (z.avail_in || z.avail_out) - goto err; - ret = true; - - err: - inflateEnd(&z); - return ret; -} - -/* A RangeDecoder is a type of entropy coder. It is superior to a Huffman - * encoder because symbols can use fractions of bits. - * - * Conceptually a number range is split into regions with one region for each - * symbol. The size of the region is proportional to the probability of the - * symbol: - * - * +-----+ <- 2**32 - 1 - * | | - * | B | - * | | - * +-----+ <- 2**30 - * | A | - * +-----+ <- 0 - * - * Here, symbol B is 3 times more probable than A. - * - * This pattern is recursive: it repeats inside each region: - * - * +-----+ /+-----+ - * | | / | | - * | B | / | B | - * | | / | | - * +-----+/ +-----+ - * | A | | A | - * +-----+-----+-----+ - * - * In this implementation, the probabilities are fixed and so are the same at - * every level. - * - * A range coder encodes a series of symbols by specifing a fraction along the - * number space such that it hits the correct symbols in order. You have to - * know how many symbols to expect from a range coder because it obviously - * produces an infinite series of symbols from any input value. - * - * In order to make the implementation fast on a computer, a high and low point - * are maintained that cover the current valid span of the number space. - * Whenever the span is small enough to that the most significant 8 bits of the - * high and low values are equal, a byte is produced and the current span is - * expanded by a factor of 256. - * - * A decoder reads these bytes and decodes symbols as required. For example, - * say that it reads the first byte as 0x80. It knows that the maximum value of - * the final span is 0x80fffffff... and the minimum value is 0x8000000... - * That's sufficient to figure out that the first symbol is a B. - * - * In the following, we keep track of these values: - * high_, low_: the high and low values of the current span. This is needed - * to mirror the state of the encoder so that span expansions occur at - * the same point. - * - * vhigh_, vlow_: the high and low values of the possible final span. - * vbits_: the number of bits of |vhigh_| and |vlow_| that are from data. - * (The rest of those values is filled with 0xff or 0x00, respectively.) - */ -class RangeDecoder { - public: - // in: the input bytes - // spans: the probabilities of the symbols. The sum of these values must - // equal 2**32 - 1. - RangeDecoder(base::StringPiece in, const std::vector<uint32>& spans) - : in_(in), - spans_(spans), - high_(-1), - vhigh_(-1), - low_(0), - vlow_(0), - vbits_(0) { - } - - bool Decode(unsigned* out_symbol) { - // high_ and low_ mirror the state of the encoder so, when they agree on - // the first byte, we have to perform span expansion. - while ((high_ >> 24) == (low_ >> 24)) { - vhigh_ <<= 8; - vhigh_ |= 0xff; - vlow_ <<= 8; - vbits_ -= 8; - - high_ <<= 8; - high_ |= 0xff; - low_ <<= 8; - } - - // r is the range of the current span, used as a scaling factor. - uint64 r = high_ - low_; - - // We consider each symbol in turn and decide if the final span is such - // that it must be the next symbol. - for (size_t i = 0; i < spans_.size(); i++) { - const uint32 span = spans_[i]; - const uint32 scaled = (r * span) >> 32; - - // Since our knowledge of the final span is incremental, |vhigh_| and - // |vlow_| might be sufficiently far apart that we can't determine the - // next symbol. In this case we have to read more data. - while (vhigh_ > (low_ + scaled) && vlow_ <= (low_ + scaled)) { - // We need more information to disambiguate this. Note that 32-bits of - // information is always sufficient to disambiguate. - uint32 b = 0; - if (!in_.empty()) - b = static_cast<uint8>(in_[0]); - in_.remove_prefix(1); - vhigh_ &= ~(static_cast<uint32>(0xff) << (24 - vbits_)); - vhigh_ |= b << (24 - vbits_); - vlow_ |= b << (24 - vbits_); - vbits_ += 8; - } - - // This symbol covers all the possible values for the final span, so this - // must be the next symbol. - if (vhigh_ <= (low_ + scaled)) { - high_ = low_ + scaled; - *out_symbol = i; - return true; - } - - low_ += scaled + 1; - } - - // Since the sum of |spans_| equals 2**32-1, one of the symbols must cover - // the current span. - NOTREACHED(); - return false; - } - - private: - base::StringPiece in_; - const std::vector<uint32> spans_; - - uint32 high_, vhigh_, low_, vlow_; - unsigned vbits_; - - DISALLOW_COPY_AND_ASSIGN(RangeDecoder); -}; - -// A GolombCompressedSet is built from a set of random hash values where each -// value is less than a pre-agreed limit. Since the hash values are uniform, -// their differences are geometrically distributed and golomb encoding is the -// optimal encoding for geometrically distributed values. -// -// Thus the set [1, 10, 15] is turned into delta values ([1, 9, 5]) and each -// delta value is Golomb encoded to make a GCS. -// -// Golomb encoding of a value, v, requires knowledge of the geometric -// parameter, M, and consists of (q, r) where v = qM + r. q is unary encoded -// and r is binary encoded. In this code M is fixed at 1024. -// -// A couple of implementation tricks are used to speed things up: -// -// First, the bits are consumed in blocks of 32 and are little endian encoded, -// thus saving a endianness conversion on most systems. Also, the bits inside -// each word are ordered such that the first bit is the least-significant bit -// and the unary encoding is terminated with a 1 rather than the usual 0. -// This allows us to use a DeBruijn sequence to do unary decoding. -class GolombCompressedSet { - public: - class iterator { - public: - iterator(base::StringPiece data, unsigned num_values) - : full_data_(data), - num_values_(num_values) { - Reset(); - } - - void Reset() { - data_ = full_data_; - pending_ = 0; - bits_pending_ = 0; - current_ = 0; - } - - bool Next(uint64* out) { - unsigned q, r; - if (!ReadUnary(&q)) - return false; - if (!ReadBinary10(&r)) - return false; - - uint64 step = static_cast<uint64>(q) << 10; - step |= r; - current_ += step; - *out = current_; - return true; - } - - bool NextDelta(unsigned* out_delta) { - unsigned q, r; - if (!ReadUnary(&q)) - return false; - if (!ReadBinary10(&r)) - return false; - - *out_delta = static_cast<unsigned>(q) << 10; - *out_delta |= r; - return true; - } - - bool Contains(uint64 v) { - Reset(); - - uint64 value; - for (unsigned i = 0; i < num_values_; i++) { - if (!Next(&value)) - return false; - if (value == v) - return true; - if (value > v) - return false; - } - - return false; - } - - private: - bool ReadUnary(unsigned* out) { - *out = 0; - - uint32 w; - if (!CurrentWord(&w)) - return false; - - while (w == 0) { - *out += 32; - if (!CurrentWord(&w)) - return false; - } - - // A DeBruijn sequence contains all possible subsequences. kDeBruijn is an - // example of a 32-bit word that contains all possible 5-bit subsequences. - // When decoding Golomb values, we quickly need to find the number of - // consequtive zero bits. (w&-w) results in a word with only the - // least-significant true bit set. Since this work has only a single bit - // set, its value is a power of two and multiplying by it is the same as a - // left shift by the position of that bit. - // - // Thus we multiply (i.e. left-shift) by the DeBruijn value and check the - // top 5 bits. Since each 5-bit subsequence in kDeBruijn is unique, we can - // determine by how many bits it has been shifted with a lookup table. - static const uint32 kDeBruijn = 0x077CB531; - static const uint8 kDeBruijnLookup[32] = { - 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, - 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9, - }; - - MSVC_SUPPRESS_WARNING(4146); - uint8 r = kDeBruijnLookup[((w & -w) * kDeBruijn) >> 27]; - *out += r; - pending_ >>= r + 1; - bits_pending_ -= r + 1; - return true; - } - - bool ReadBinary10(unsigned* out) { - uint32 w; - if (!CurrentWord(&w)) - return false; - *out = w & 0x3ff; - pending_ >>= 10; - bits_pending_ -= 10; - return true; - } - - bool CurrentWord(uint32* out) { - if (bits_pending_ < 32) { - if (!ReadWord() && bits_pending_ == 0) - return false; - } - *out = static_cast<uint32>(pending_); - return true; - } - - bool ReadWord() { - DCHECK_LE(bits_pending_, 32u); - - if (data_.size() < 4) - return false; - uint32 w; - memcpy(&w, data_.data(), 4); - data_.remove_prefix(4); - - uint64 w64 = w; - w64 <<= bits_pending_; - pending_ |= w64; - bits_pending_ += 32; - return true; - } - - base::StringPiece full_data_; - base::StringPiece data_; - const unsigned num_values_; - uint64 pending_; - unsigned bits_pending_; - uint32 current_; - }; - - GolombCompressedSet(base::StringPiece data, - unsigned num_values) - : full_data_(data), - num_values_(num_values) { - } - - iterator begin() const { - return iterator(full_data_, num_values_); - } - - private: - base::StringPiece full_data_; - const unsigned num_values_; - - DISALLOW_COPY_AND_ASSIGN(GolombCompressedSet); -}; - -// BitWriter buffers a number of bits in a format that matches -// GolombCompressedSet's expectations: the bits are packed least-significant -// first in little-endian, 32-bit words. -class BitWriter { - public: - BitWriter() - : buf_(NULL), - buf_len_(0), - buf_used_(0), - current_(0), - num_bits_(0) { - } - - ~BitWriter() { - free(buf_); - buf_ = NULL; - } - - void WriteBit(bool b) { - current_ >>= 1; - if (b) - current_ |= 0x80000000u; - num_bits_++; - - if (num_bits_ == sizeof(current_) * 8) - Flush(); - } - - // WriteGolomb10 outputs v using Golomb encoding with a geometric parameter - // of 1024. - void WriteGolomb10(unsigned v) { - const unsigned q = v >> 10; - unsigned r = v & 0x3ff; - - for (unsigned i = 0; i < q; i++) - WriteBit(false); - WriteBit(true); - for (unsigned i = 0; i < 10; i++) { - WriteBit((r & 1) == 1); - r >>= 1; - } - } - - void Flush() { - if (num_bits_ > 0) - current_ >>= 32 - num_bits_; - - if (buf_len_ < buf_used_ + sizeof(current_)) { - if (buf_) { - buf_len_ += sizeof(current_); - buf_len_ *= 2; - buf_ = reinterpret_cast<uint8*>(realloc(buf_, buf_len_)); - } else { - buf_len_ = 1024; - buf_ = reinterpret_cast<uint8*>(malloc(buf_len_)); - } - } - // assumes little endian - memcpy(buf_ + buf_used_, ¤t_, sizeof(current_)); - buf_used_ += sizeof(current_); - - current_ = 0; - num_bits_ = 0; - } - - std::string as_string() { - Flush(); - return std::string(reinterpret_cast<char*>(buf_), buf_used_); - } - - private: - uint8* buf_; - size_t buf_len_; - size_t buf_used_; - uint32 current_; - unsigned num_bits_; - - DISALLOW_COPY_AND_ASSIGN(BitWriter); -}; - -CRLFilter::CRLFilter() - : not_before_(0), - not_after_(0), - max_range_(0), - sequence_(0), - num_entries_(0) { -} - -CRLFilter::~CRLFilter() { -} - -// CRL filter format: -// -// uint16le description_len -// byte[description_len] description_bytes -// byte[] compressed_header -// byte[] gcs_bytes -// -// description_bytes consists of a JSON dictionary with the following keys: -// Version (int): currently 0 -// Contents (string): "CRLFilter" or "CRLFilterDelta" (magic value) -// DeltaFrom (int); if this is a delta filter (see below), then this contains -// the sequence number of the reference filter. -// HeaderZLength (int): the number of bytes of compressed header. -// HeaderLength (int): the number of bytes of header after decompression. -// RangeLength (int): if this is a delta filter then this is the number of -// bytes of range coded data. -// -// The uncompressed header is also a JSON dictionary with the following keys: -// Sequence (int): the sequence number of this filter. -// Version (int): currently 0. -// NotBefore (int, epoch seconds): the filter is not valid before this time. -// NotAfter (int, epoch seconds): the filter is not valid after this time. -// MaxRange (int): the limit of the GCS encoded values -// NumEntries (int): the number of GCS entries -// -// CRLsIncluded (array): the covered CRLs. Each element in the array is a -// dictionary with the following keys: -// -// URL (string): the URL of the CRL -// ParentSPKISHA256 (string): base64 encoded, SHA256 hash of the CRL -// signer's SPKI. -// -// A delta CRL filter is similar to a CRL filter: -// -// uint16le description_len -// byte[description_len] description_bytes -// byte[] delta_compressed_header -// uint32le[3] range_probabilities -// byte[] range_bytes -// byte[] gcs_bytes -// -// A delta CRL filter applies to a specific CRL filter as given in the -// description's "DeltaFrom" value. The compressed header is compressed with -// the header bytes of the base CRL filter given as a zlib preshared -// dictionary. -// -// range_probabilities contains the probabilies of the three encoded symbols. -// The sum of these values must be 0xffffffff. Next are the range encoded -// bytes, the length of which is given in "RangeLength". There's one symbol for -// each GCS value in the final filter. (This number is given in the -// "NumEntries" value of the header.). Each symbol is either SAME (0), INSERT -// (1) or DELETE (2). SAME values are copied into the new filter, INSERTed -// values are given as a delta from the last value, GCS encoded in |gcs_bytes|. -// DELETEed values are omitted from the final filter. - -// ReadDescription reads the description (including length prefix) from |data| -// and updates |data| to remove the description on return. Caller takes -// ownership of the returned pointer. -static DictionaryValue* ReadDescription(base::StringPiece* data) { - if (data->size() < 2) - return NULL; - uint16 description_len; - memcpy(&description_len, data->data(), 2); // assumes little-endian. - data->remove_prefix(2); - - if (data->size() < description_len) - return NULL; - - const base::StringPiece description_bytes(data->data(), description_len); - data->remove_prefix(description_len); - - scoped_ptr<Value> description(base::JSONReader::Read( - description_bytes.as_string(), true /* allow trailing comma */)); - if (description.get() == NULL) - return NULL; - - if (!description->IsType(Value::TYPE_DICTIONARY)) - return NULL; - return reinterpret_cast<DictionaryValue*>(description.release()); -} - -// CRLFilterFromHeader constructs a CRLFilter from the bytes of a header -// structures. The header is JSON. See above for details of the keys. -// -// static -CRLFilter* CRLFilter::CRLFilterFromHeader(base::StringPiece header_bytes) { - scoped_ptr<Value> header(base::JSONReader::Read( - header_bytes.as_string(), - true /* allow trailing comma */)); - if (header.get() == NULL) - return NULL; - - if (!header->IsType(Value::TYPE_DICTIONARY)) - return NULL; - DictionaryValue* header_dict = - reinterpret_cast<DictionaryValue*>(header.get()); - int version; - if (!header_dict->GetInteger("Version", &version) || - version != 0) { - return NULL; - } - - double not_before, not_after, max_range, num_entries; - if (!header_dict->GetDouble("NotBefore", ¬_before) || - !header_dict->GetDouble("NotAfter", ¬_after) || - !header_dict->GetDouble("NumEntries", &num_entries) || - !header_dict->GetDouble("MaxRange", &max_range)) { - return NULL; - } - - if (not_before <= 0 || not_after <= 0 || max_range <= 0 || num_entries <= 0) - return NULL; - - int sequence; - if (!header_dict->GetInteger("Sequence", &sequence) || - sequence <= 0) { - // Sequence is assumed to be zero if omitted. - sequence = 0; - } - - scoped_ptr<CRLFilter> crl_filter(new CRLFilter); - crl_filter->sequence_ = sequence; - crl_filter->not_before_ = not_before; - crl_filter->not_after_ = not_after; - crl_filter->max_range_ = max_range; - crl_filter->num_entries_ = num_entries; - crl_filter->header_bytes_ = header_bytes.as_string(); - - ListValue* crls_included; - if (!header_dict->GetList("CRLsIncluded", &crls_included)) - return NULL; - - for (size_t i = 0; i < crls_included->GetSize(); i++) { - DictionaryValue* included_crl_dict; - if (!crls_included->GetDictionary(i, &included_crl_dict)) - return NULL; - std::string url, parent_spki_sha256_b64; - if (!included_crl_dict->GetString("URL", &url) || - !included_crl_dict->GetString("ParentSPKISHA256", - &parent_spki_sha256_b64)) { - return NULL; - } - - std::string parent_spki_sha256; - if (!base::Base64Decode(parent_spki_sha256_b64, - &parent_spki_sha256)) { - return NULL; - } - crl_filter->crls_included_.insert( - std::make_pair<std::string, std::string>( - url, - parent_spki_sha256)); - } - - return crl_filter.release(); -} - -// kMaxHeaderLengthBytes contains the sanity limit of the size of a CRL -// filter's decompressed header. -static const int kMaxHeaderLengthBytes = 1024 * 1024; - -// static -bool CRLFilter::Parse(base::StringPiece data, - scoped_refptr<CRLFilter>* out_crl_filter) { - // Other parts of Chrome assume that we're little endian, so we don't lose - // anything by doing this. -#if defined(__BYTE_ORDER) - // Linux check - COMPILE_ASSERT(__BYTE_ORDER == __LITTLE_ENDIAN, - datapack_assumes_little_endian); -#elif defined(__BIG_ENDIAN__) - // Mac check - #error DataPack assumes little endian -#endif - - scoped_ptr<DictionaryValue> description_dict( - ReadDescription(&data)); - if (!description_dict.get()) - return false; - - std::string contents; - if (!description_dict->GetString("Contents", &contents)) - return false; - if (contents != "CRLFilter") - return false; - - int version; - if (!description_dict->GetInteger("Version", &version) || - version != 0) { - return false; - } - - int compressed_header_len; - if (!description_dict->GetInteger("HeaderZLength", &compressed_header_len)) - return false; - - if (compressed_header_len <= 0 || - data.size() < static_cast<unsigned>(compressed_header_len)) { - return false; - } - const base::StringPiece compressed_header(data.data(), compressed_header_len); - data.remove_prefix(compressed_header_len); - - int header_len; - if (!description_dict->GetInteger("HeaderLength", &header_len)) - return false; - if (header_len < 0 || header_len > kMaxHeaderLengthBytes) { - NOTREACHED(); - return false; - } - - scoped_array<char> header_bytes(new char[header_len]); - base::StringPiece no_dict; - if (!DecompressZlib(header_bytes.get(), header_len, compressed_header, - no_dict)) { - return false; - } - - scoped_refptr<CRLFilter> crl_filter(CRLFilterFromHeader( - base::StringPiece(header_bytes.get(), header_len))); - - if (!crl_filter.get()) - return false; - - // The remainder is the Golomb Compressed Set. - crl_filter->gcs_bytes_ = data.as_string(); - crl_filter->gcs_.reset(new GolombCompressedSet(crl_filter->gcs_bytes_, - crl_filter->num_entries_)); - *out_crl_filter = crl_filter; - return true; -} - -bool CRLFilter::ApplyDelta(base::StringPiece data, - scoped_refptr<CRLFilter>* out_crl_filter) { - scoped_ptr<DictionaryValue> description_dict( - ReadDescription(&data)); - if (!description_dict.get()) - return false; - - int compressed_header_len, header_len, delta_from, version, range_length; - std::string contents; - if (!description_dict->GetInteger("HeaderZLength", &compressed_header_len) || - !description_dict->GetInteger("HeaderLength", &header_len) || - !description_dict->GetInteger("RangeLength", &range_length) || - !description_dict->GetInteger("DeltaFrom", &delta_from) || - !description_dict->GetInteger("Version", &version) || - !description_dict->GetString("Contents", &contents)) { - return false; - } - - if (version != 0 || contents != "CRLFilterDelta") - return false; - - if (delta_from < 0 || static_cast<unsigned>(delta_from) != sequence_) - return false; - - if (compressed_header_len <= 0 || - data.size() < static_cast<unsigned>(compressed_header_len) || - header_len < 0 || - header_len > kMaxHeaderLengthBytes) { - return false; - } - - const base::StringPiece compressed_header(data.data(), compressed_header_len); - data.remove_prefix(compressed_header_len); - - scoped_array<char> header_bytes(new char[header_len]); - if (!DecompressZlib(header_bytes.get(), header_len, compressed_header, - header_bytes_)) { - return false; - } - - scoped_refptr<CRLFilter> crl_filter(CRLFilterFromHeader( - base::StringPiece(header_bytes.get(), header_len))); - - if (!crl_filter.get()) - return false; - - // Next are the three span values. - static const unsigned kNumSpanValues = 3; - static const size_t kNumSpanBytes = kNumSpanValues * sizeof(uint32); - if (data.size() < kNumSpanBytes) - return false; - - std::vector<uint32> spans(kNumSpanBytes); - memcpy(&spans[0], data.data(), kNumSpanBytes); - data.remove_prefix(kNumSpanBytes); - - if (data.size() < static_cast<unsigned>(range_length)) - return false; - RangeDecoder decoder(data.substr(0, range_length), spans); - data.remove_prefix(range_length); - - GolombCompressedSet gcs(data, 0 /* no values; we don't know that yet. */); - GolombCompressedSet::iterator gcs_deltas(gcs.begin()); - GolombCompressedSet::iterator gcs_prev(gcs_->begin()); - BitWriter bitwriter; - - uint64 last = 0, v; - for (unsigned i = 0; i < crl_filter->num_entries_;) { - unsigned symbol, delta; - if (!decoder.Decode(&symbol)) - return false; - if (symbol == SYMBOL_SAME) { - if (!gcs_prev.Next(&v)) - return false; - bitwriter.WriteGolomb10(v - last); - last = v; - i++; - } else if (symbol == SYMBOL_INSERT) { - if (!gcs_deltas.NextDelta(&delta)) - return false; - bitwriter.WriteGolomb10(delta); - last += delta; - i++; - } else if (symbol == SYMBOL_DELETE) { - if (!gcs_prev.Next(&v)) - return false; - } else { - NOTREACHED(); - return false; - } - } - - crl_filter->gcs_bytes_ = bitwriter.as_string(); - crl_filter->gcs_.reset(new GolombCompressedSet(crl_filter->gcs_bytes_, - crl_filter->num_entries_)); - *out_crl_filter = crl_filter; - return true; -} - -bool CRLFilter::CRLIsCovered( - const std::vector<base::StringPiece>& crl_urls, - const std::string& parent_spki_sha256) { - for (std::vector<base::StringPiece>::const_iterator - i = crl_urls.begin(); i != crl_urls.end(); i++) { - if (ContainsKey(crls_included_, std::make_pair<std::string, std::string>( - i->as_string(), parent_spki_sha256))) { - return true; - } - } - return false; -} - -// FNV1a64 computes the FNV1a 64-bit hash of the concatenation of |a| and -// |b|. -static uint64 FNV1a64(const std::string& a, const std::string& b) { - uint64 x = 14695981039346656037ull; - static const uint64 p = 1099511628211ull; - for (size_t i = 0; i < a.size(); i++) { - x ^= static_cast<uint8>(a[i]); - x *= p; - } - for (size_t i = 0; i < b.size(); i++) { - x ^= static_cast<uint8>(b[i]); - x *= p; - } - return x; -} - -CRLFilter::Result CRLFilter::CheckCertificate( - base::StringPiece cert_spki, - const std::string& serial_number, - const std::vector<base::StringPiece>& crl_urls, - base::StringPiece parent_spki) { - const std::string parent_spki_sha256 = - crypto::SHA256HashString(parent_spki.as_string()); - - if (!CRLIsCovered(crl_urls, parent_spki_sha256)) - return UNKNOWN; - - uint64 h = FNV1a64(serial_number, parent_spki_sha256); - h %= max_range_; - - GolombCompressedSet::iterator it(gcs_->begin()); - if (it.Contains(h)) - return PROBABLY_REVOKED; - return NOT_REVOKED; -} - -int64 CRLFilter::not_before() const { - return not_before_; -} - -int64 CRLFilter::not_after() const { - return not_after_; -} - -uint64 CRLFilter::max_range() const { - return max_range_; -} - -unsigned CRLFilter::num_entries() const { - return num_entries_; -} - -std::vector<uint64> CRLFilter::DebugValues() { - std::vector<uint64> ret; - uint64 v; - - GolombCompressedSet::iterator it(gcs_->begin()); - - for (unsigned i = 0; i < num_entries_; i++) { - if (!it.Next(&v)) { - ret.clear(); - break; - } - ret.push_back(v); - } - return ret; -} - -std::string CRLFilter::SHA256() const { - std::string s = header_bytes_; - s += gcs_bytes_; - return crypto::SHA256HashString(s); -} - -} // namespace net diff --git a/net/base/crl_filter.h b/net/base/crl_filter.h deleted file mode 100644 index 0ba4abb..0000000 --- a/net/base/crl_filter.h +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright (c) 2011 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_BASE_CRL_FILTER_H_ -#define NET_BASE_CRL_FILTER_H_ -#pragma once - -#include <set> -#include <string> -#include <utility> -#include <vector> - -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "base/string_piece.h" -#include "base/synchronization/lock.h" -#include "net/base/net_export.h" - -namespace net { - -class GolombCompressedSet; - -// A CRLFilter is a probabilistic data structure for eliminating certificate -// revocation checks. A CRL filter contains information about some number of -// globally well known CRLs. Those CRLs are said to be `covered' by the filter. -// -// If a certificate specifies a CRL that is covered then the CRLFilter can give -// a firm "not revoked" answer or a probabilistic "revoked" answer. -// Additionally, a CRLFilter can contain a list of blocked public keys and, in -// that case, it can give a firm "revoked" answer. -class NET_EXPORT_PRIVATE CRLFilter : public base::RefCounted<CRLFilter> { - public: - enum Result { - REVOKED, // the certificate should be rejected. - PROBABLY_REVOKED, // the certificate should be checked. - NOT_REVOKED, // the certificate is acceptable. - UNKNOWN, // no information available. - }; - - ~CRLFilter(); - - static bool Parse(base::StringPiece data, - scoped_refptr<CRLFilter>* out_crl_filter); - - // CheckCertificate returns the information contained in the filter for a - // given certificate: - // cert_spki: the SubjectPublicKeyInfo for the certificate - // serial_number: the serial number of the certificate - // crl_urls: the URLs for the CRL for the certificate - // parent_spki: the SubjectPublicKeyInfo of the CRL signer - // - // This does not check that the CRLFilter is timely. See |not_before| and - // |not_after|. - Result CheckCertificate( - base::StringPiece cert_spki, - const std::string& serial_number, - const std::vector<base::StringPiece>& crl_urls, - base::StringPiece parent_spki); - - // ApplyDelta returns a new CRLFilter in |out_crl_filter| that is the result - // of updating the current filter with the delta information in - // |delta_bytes|. - bool ApplyDelta(base::StringPiece delta_bytes, - scoped_refptr<CRLFilter>* out_crl_filter); - - // not_before and not_after return the validity timespan of this filter. - // |CheckCertificate| does not check the current time so it's up to the - // caller to ensure that the CRLFilter is timely. - int64 not_before() const; - int64 not_after() const; - - // DebugValues return all GCS values, in order. This should only be used - // for testing. - std::vector<uint64> DebugValues(); - // num_entries returns the number of GCS values in the filter. This should - // only be used for testing. - unsigned num_entries() const; - // max_range returns size of the hash range. This should only be used for - // testing. - uint64 max_range() const; - // SHA256 returns a hash over the header and GCS bytes of the filter. This - // should only be used for testing. - std::string SHA256() const; - - private: - CRLFilter(); - - // These are the range coder symbols used in delta updates. - enum { - SYMBOL_SAME = 0, - SYMBOL_INSERT = 1, - SYMBOL_DELETE = 2, - }; - - static CRLFilter* CRLFilterFromHeader(base::StringPiece header); - bool CRLIsCovered(const std::vector<base::StringPiece>& crl_urls, - const std::string& parent_spki_sha256); - - int64 not_before_, not_after_; - uint64 max_range_; - unsigned sequence_; - unsigned num_entries_; - - std::string header_bytes_; - - std::set<std::pair<std::string, std::string> > crls_included_; - std::string gcs_bytes_; - scoped_ptr<GolombCompressedSet> gcs_; -}; - -} // namespace net - -#endif // NET_BASE_CRL_FILTER_H_ diff --git a/net/base/crl_filter_unittest.cc b/net/base/crl_filter_unittest.cc deleted file mode 100644 index 69bd524..0000000 --- a/net/base/crl_filter_unittest.cc +++ /dev/null @@ -1,216 +0,0 @@ -// Copyright (c) 2011 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/base/crl_filter.h" -#include "testing/gtest/include/gtest/gtest.h" - -// These data blocks were generated using a lot of code that is still in -// development. For now, if you need to update them, you have to contact agl. -static const uint8 kTestFilter[] = { - 0xab, 0x00, 0x7b, 0x22, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x3a, - 0x30, 0x2c, 0x22, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a, - 0x22, 0x43, 0x52, 0x4c, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x22, 0x2c, 0x22, - 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x22, 0x3a, 0x30, 0x2c, 0x22, - 0x44, 0x65, 0x6c, 0x74, 0x61, 0x46, 0x72, 0x6f, 0x6d, 0x22, 0x3a, 0x30, 0x2c, - 0x22, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5a, 0x4c, 0x65, 0x6e, 0x67, 0x74, - 0x68, 0x22, 0x3a, 0x32, 0x31, 0x38, 0x2c, 0x22, 0x48, 0x65, 0x61, 0x64, 0x65, - 0x72, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x32, 0x35, 0x39, 0x2c, - 0x22, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x75, 0x62, 0x6c, 0x69, - 0x63, 0x4b, 0x65, 0x79, 0x22, 0x3a, 0x22, 0x22, 0x2c, 0x22, 0x53, 0x69, 0x67, - 0x6e, 0x69, 0x6e, 0x67, 0x4b, 0x65, 0x79, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x22, 0x3a, 0x22, 0x22, 0x2c, 0x22, 0x50, 0x61, 0x79, 0x6c, - 0x6f, 0x61, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, - 0x3a, 0x22, 0x22, 0x7d, 0x78, 0x9c, 0x74, 0xcd, 0x4d, 0x4f, 0x83, 0x30, 0x18, - 0x07, 0xf0, 0xef, 0xf2, 0x5c, 0x25, 0xbc, 0xb8, 0x82, 0x4b, 0x13, 0x0f, 0x38, - 0x8d, 0x36, 0x63, 0xca, 0x98, 0x2c, 0x26, 0xc6, 0x03, 0x76, 0x0f, 0xac, 0x91, - 0xb5, 0x5a, 0x9e, 0xca, 0xc8, 0xb2, 0xef, 0x2e, 0x18, 0xaf, 0x5e, 0x7f, 0xf9, - 0xbf, 0x9c, 0x60, 0x8b, 0xb6, 0x53, 0x46, 0x03, 0x0f, 0x3d, 0x78, 0x34, 0x74, - 0x83, 0xb5, 0xb1, 0x08, 0x3c, 0x9a, 0x85, 0xec, 0x2a, 0x8a, 0x58, 0xcc, 0x7e, - 0x39, 0xad, 0x09, 0xed, 0x9f, 0xc6, 0x2c, 0x99, 0x74, 0x55, 0x1d, 0x8b, 0x4a, - 0x37, 0x63, 0x96, 0x25, 0xe1, 0x7c, 0x6a, 0xbb, 0xc3, 0x9d, 0x26, 0xab, 0xb0, - 0x1b, 0x29, 0xf6, 0x60, 0x51, 0x64, 0x9d, 0xd0, 0xb2, 0x75, 0x3b, 0xdc, 0x01, - 0x7f, 0x3d, 0x41, 0x59, 0x64, 0xc0, 0x61, 0x4f, 0xf4, 0xc9, 0x83, 0xa0, 0xef, - 0x7b, 0xbf, 0xe9, 0xa8, 0x22, 0x25, 0x7d, 0x69, 0x0e, 0xc1, 0xbd, 0x31, 0x4d, - 0x8b, 0x42, 0x8f, 0x3f, 0x1a, 0x29, 0x75, 0xb4, 0x37, 0x56, 0xd1, 0xf0, 0x9f, - 0xfb, 0xd2, 0xb6, 0xe0, 0x41, 0x5e, 0x59, 0xd4, 0xb4, 0xc9, 0x97, 0x62, 0xf3, - 0x90, 0x5e, 0xc6, 0xc9, 0xb8, 0x4f, 0xb6, 0x2d, 0x57, 0x5f, 0xce, 0x6d, 0x03, - 0xb6, 0xb8, 0xcd, 0x96, 0xb3, 0xe7, 0xf0, 0xa2, 0xfe, 0x78, 0xc9, 0xc5, 0xb1, - 0x57, 0xdf, 0x03, 0xca, 0xc1, 0x3e, 0x89, 0x01, 0xd7, 0xc5, 0xfc, 0x7d, 0x5d, - 0x5e, 0xc3, 0xf9, 0xed, 0xfc, 0x13, 0x00, 0x00, 0xff, 0xff, 0x8a, 0x9f, 0x55, - 0x48, 0x43, 0x5d, 0x4a, 0xac, 0xae, 0xd7, 0x88, 0xc4, 0xf7, 0x6e, 0xdc, 0x7c, - 0x6b, 0x74, 0xd2, 0x1a, 0x22, 0xbf, 0x5b, 0x2e, 0x9f, 0xbd, 0xee, 0x09, 0xe7, - 0x87, 0x16, 0x17, 0xa2, 0x6b, 0xf1, 0x37, 0x04, 0x61, 0x83, 0xd5, 0xc4, 0x79, - 0xa4, 0x35, 0xc3, 0xb1, 0x2b, 0x58, 0x9f, 0xc7, 0x0c, 0x2a, 0x7e, 0xf8, 0xd2, - 0x28, 0x46, 0xb4, 0x4f, 0x99, 0xea, 0xd8, 0x3d, 0x18, 0xd2, 0x69, 0x5a, 0x64, - 0x3f, 0x00, 0x00, 0x00, -}; - -static const unsigned kTestFilterExpectedNumValues = 45; -static const uint32 kTestFilterExpectedValues[kTestFilterExpectedNumValues] = { - 673, 838, 1182, 1673, 1743, 2707, 3185, 4066, - 6481, 6946, 8662, 8934, 10437, 11178, 13945, 14692, - 15223, 15728, 19590, 19656, 20086, 21102, 22159, 23615, - 27924, 28748, 29405, 29815, 33754, 34276, 34526, 34725, - 35046, 35550, 38925, 39006, 39279, 39916, 41272, 41670, - 41793, 44130, 44341, 44619, 45896, -}; - -// kGIASPKI is the DER encoded SubjectPublicKeyInfo of the GIA certificate. -static const uint8 kGIASPKI[] = { - 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, - 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, - 0x81, 0x81, 0x00, 0xc9, 0xed, 0xb7, 0xa4, 0x8b, 0x9c, 0x57, 0xe7, 0x84, 0x3e, - 0x40, 0x7d, 0x84, 0xf4, 0x8f, 0xd1, 0x71, 0x63, 0x53, 0x99, 0xe7, 0x79, 0x74, - 0x14, 0xaf, 0x44, 0x99, 0x33, 0x20, 0x92, 0x8d, 0x7b, 0xe5, 0x28, 0x0c, 0xba, - 0xad, 0x6c, 0x49, 0x7e, 0x83, 0x5f, 0x34, 0x59, 0x4e, 0x0a, 0x7a, 0x30, 0xcd, - 0xd0, 0xd7, 0xc4, 0x57, 0x45, 0xed, 0xd5, 0xaa, 0xd6, 0x73, 0x26, 0xce, 0xad, - 0x32, 0x13, 0xb8, 0xd7, 0x0f, 0x1d, 0x3b, 0xdf, 0xdd, 0xdc, 0x08, 0x36, 0xa8, - 0x6f, 0x51, 0x44, 0x9b, 0xca, 0xd6, 0x20, 0x52, 0x73, 0xb7, 0x26, 0x87, 0x35, - 0x6a, 0xdb, 0xa9, 0xe5, 0xd4, 0x59, 0xa5, 0x2b, 0xfc, 0x67, 0x19, 0x39, 0xfa, - 0x93, 0x18, 0x18, 0x6c, 0xde, 0xdd, 0x25, 0x8a, 0x0e, 0x33, 0x14, 0x47, 0xc2, - 0xef, 0x01, 0x50, 0x79, 0xe4, 0xfd, 0x69, 0xd1, 0xa7, 0xc0, 0xac, 0xe2, 0x57, - 0x6f, 0x02, 0x03, 0x01, 0x00, 0x01, -}; - -static const uint8 kDeltaTestFilter1[] = { - 0xae, 0x00, 0x7b, 0x22, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x3a, - 0x30, 0x2c, 0x22, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a, - 0x22, 0x43, 0x52, 0x4c, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x22, 0x2c, 0x22, - 0x44, 0x65, 0x6c, 0x74, 0x61, 0x46, 0x72, 0x6f, 0x6d, 0x22, 0x3a, 0x30, 0x2c, - 0x22, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5a, 0x4c, 0x65, 0x6e, 0x67, 0x74, - 0x68, 0x22, 0x3a, 0x32, 0x30, 0x32, 0x2c, 0x22, 0x48, 0x65, 0x61, 0x64, 0x65, - 0x72, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x32, 0x31, 0x37, 0x2c, - 0x22, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, - 0x3a, 0x30, 0x2c, 0x22, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x75, - 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x22, 0x3a, 0x22, 0x22, 0x2c, 0x22, - 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x4b, 0x65, 0x79, 0x53, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0x3a, 0x22, 0x22, 0x2c, 0x22, 0x50, - 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x22, 0x3a, 0x22, 0x22, 0x7d, 0x78, 0x9c, 0x24, 0xcb, 0xdf, 0x4a, - 0xc3, 0x30, 0x14, 0xc7, 0xf1, 0x77, 0x39, 0xd7, 0x95, 0xe4, 0x64, 0xac, 0xd5, - 0x82, 0x17, 0x5b, 0x11, 0x8c, 0xd6, 0x52, 0x1b, 0x36, 0x64, 0xe2, 0x45, 0xe8, - 0xce, 0xea, 0xb0, 0x26, 0x36, 0x7f, 0xec, 0x64, 0xcc, 0x67, 0xb7, 0x9b, 0x77, - 0x87, 0xcf, 0xf9, 0xfe, 0x8e, 0xa0, 0x68, 0x88, 0x64, 0x5a, 0x82, 0x9c, 0x27, - 0xb0, 0x26, 0xe7, 0xf7, 0xd6, 0x5c, 0xee, 0xca, 0x86, 0x25, 0xed, 0xac, 0x9b, - 0x3e, 0x38, 0xe3, 0x29, 0x66, 0xd9, 0x8d, 0xc0, 0x0b, 0x2f, 0x76, 0x81, 0xdc, - 0xbf, 0x0a, 0x81, 0x78, 0xd6, 0x27, 0x7d, 0x68, 0xb4, 0xe9, 0xa6, 0x76, 0x8e, - 0xe2, 0x3c, 0x8e, 0x9f, 0x77, 0x26, 0xb8, 0x3d, 0xf9, 0x49, 0x12, 0x28, 0x9a, - 0xd2, 0x4b, 0xd3, 0xf6, 0x71, 0x4b, 0x5b, 0xc8, 0x5f, 0x8f, 0xb0, 0x6a, 0x4a, - 0xc8, 0xe1, 0x3d, 0x84, 0xaf, 0x9c, 0xb1, 0x71, 0x1c, 0xd9, 0xaf, 0xee, 0x7a, - 0xd6, 0xba, 0xfe, 0x0a, 0x21, 0x81, 0x5a, 0x3b, 0x32, 0x41, 0xd5, 0x8f, 0x52, - 0xdd, 0x2f, 0xc4, 0x3c, 0x9d, 0xd2, 0x4d, 0x31, 0xeb, 0x5a, 0x5b, 0xae, 0xb3, - 0x87, 0x4a, 0xf2, 0x58, 0xf9, 0x1f, 0xfe, 0xb2, 0x19, 0xae, 0xd5, 0xe1, 0x3b, - 0x43, 0xa9, 0x86, 0xc1, 0x15, 0x69, 0x64, 0xcf, 0xcb, 0x7a, 0xa5, 0x3f, 0xec, - 0x2d, 0x9c, 0xde, 0x4e, 0x7f, 0x01, 0x00, 0x00, 0xff, 0xff, 0xc1, 0xf9, 0x42, - 0x93, 0x32, 0x3b, 0x84, 0x52, 0x5d, 0xa6, 0x01, 0x00, -}; - -static const uint8 kDeltaTestFilter2[] = { - 0xb2, 0x00, 0x7b, 0x22, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x3a, - 0x30, 0x2c, 0x22, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a, - 0x22, 0x43, 0x52, 0x4c, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x44, 0x65, 0x6c, - 0x74, 0x61, 0x22, 0x2c, 0x22, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x46, 0x72, 0x6f, - 0x6d, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5a, - 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x34, 0x30, 0x2c, 0x22, 0x48, - 0x65, 0x61, 0x64, 0x65, 0x72, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, - 0x32, 0x31, 0x37, 0x2c, 0x22, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x4c, 0x65, 0x6e, - 0x67, 0x74, 0x68, 0x22, 0x3a, 0x32, 0x2c, 0x22, 0x53, 0x69, 0x67, 0x6e, 0x69, - 0x6e, 0x67, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x22, 0x3a, - 0x22, 0x22, 0x2c, 0x22, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x4b, 0x65, - 0x79, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0x3a, 0x22, - 0x22, 0x2c, 0x22, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0x3a, 0x22, 0x22, 0x7d, 0x78, 0xf9, - 0xc1, 0xf9, 0x42, 0x93, 0xaa, 0x56, 0x22, 0xda, 0x63, 0x16, 0x06, 0x40, 0x80, - 0xe9, 0x31, 0x63, 0x23, 0x90, 0x28, 0x3e, 0x8f, 0x99, 0x91, 0xe4, 0x31, 0x23, - 0xea, 0x78, 0x0c, 0x10, 0x00, 0x00, 0xff, 0xff, 0xb6, 0xa2, 0x42, 0x83, 0x91, - 0x24, 0x49, 0x92, 0x48, 0x92, 0x24, 0x49, 0x26, 0x49, 0x92, 0x24, 0xd4, 0xb5, - 0xad, 0xcf, 0x00, 0x00, -}; - -// kRevokedCertSerialNumber is the serial number of a certificate that is -// listed in the GIA CRL. -static const uint8 kRevokedCertSerialNumber[] = { - 0x36, 0xa0, 0x42, 0xb4, 0x00, 0x03, 0x00, 0x00, 0x27, 0x86, -}; - -static const uint8 kDeltaResultSHA256[] = { - 0x7d, 0x00, 0xea, 0x3e, 0x58, 0xb6, 0xda, 0x16, 0x6f, 0x3c, 0xae, 0xe1, 0xa3, - 0x26, 0x39, 0x5b, 0x5c, 0xa5, 0x2f, 0x41, 0xde, 0xd7, 0x81, 0xd6, 0xa4, 0x4c, - 0x1d, 0x4b, 0xdc, 0x57, 0x62, 0x6f, -}; - -TEST(CRLFilterTest, Parse) { - base::StringPiece s(reinterpret_cast<const char*>(kTestFilter), - sizeof(kTestFilter)); - scoped_refptr<net::CRLFilter> filter; - EXPECT_TRUE(net::CRLFilter::Parse(s, &filter)); - ASSERT_TRUE(filter.get() != NULL); - - EXPECT_EQ(filter->num_entries(), kTestFilterExpectedNumValues); - EXPECT_EQ(filter->max_range(), kTestFilterExpectedNumValues << 10); - - std::vector<uint64> values(filter->DebugValues()); - ASSERT_EQ(values.size(), kTestFilterExpectedNumValues); - - for (unsigned i = 0; i < kTestFilterExpectedNumValues; i++) { - EXPECT_EQ(kTestFilterExpectedValues[i], values[i]); - } -} - -TEST(CRLFilterTest, DeltaUpdates) { - base::StringPiece s(reinterpret_cast<const char *>(kDeltaTestFilter1), - sizeof(kDeltaTestFilter1)); - scoped_refptr<net::CRLFilter> filter; - EXPECT_TRUE(net::CRLFilter::Parse(s, &filter)); - ASSERT_TRUE(filter.get() != NULL); - - base::StringPiece delta_bytes( - reinterpret_cast<const char*>(kDeltaTestFilter2), - sizeof(kDeltaTestFilter2)); - scoped_refptr<net::CRLFilter> delta; - EXPECT_TRUE(filter->ApplyDelta(delta_bytes, &delta)); - ASSERT_TRUE(delta.get() != NULL); - - ASSERT_TRUE(delta->SHA256() == - std::string(reinterpret_cast<const char *>(kDeltaResultSHA256), - sizeof(kDeltaResultSHA256))); -} - -TEST(CRLFilterTest, Entries) { - base::StringPiece s(reinterpret_cast<const char*>(kTestFilter), - sizeof(kTestFilter)); - scoped_refptr<net::CRLFilter> filter; - EXPECT_TRUE(net::CRLFilter::Parse(s, &filter)); - ASSERT_TRUE(filter.get() != NULL); - - base::StringPiece cert_spki; - std::string serial_number = "1"; // not a real serial number. - std::vector<base::StringPiece> crl_urls; - static const char kFakeCRLURL[] = "http://example.com/crl"; - crl_urls.push_back(base::StringPiece(kFakeCRLURL, sizeof(kFakeCRLURL))); - base::StringPiece parent_spki; - - ASSERT_EQ(net::CRLFilter::UNKNOWN, - filter->CheckCertificate(cert_spki, serial_number, crl_urls, - parent_spki)); - - crl_urls.clear(); - static const char kGIACRLURL[] = - "http://www.gstatic.com/GoogleInternetAuthority/" - "GoogleInternetAuthority.crl"; - crl_urls.push_back(kGIACRLURL); - - parent_spki = base::StringPiece(reinterpret_cast<const char*>(kGIASPKI), - sizeof(kGIASPKI)); - ASSERT_EQ(net::CRLFilter::NOT_REVOKED, - filter->CheckCertificate(cert_spki, serial_number, crl_urls, - parent_spki)); - - serial_number = - std::string(reinterpret_cast<const char*>(kRevokedCertSerialNumber), - sizeof(kRevokedCertSerialNumber)); - ASSERT_EQ(net::CRLFilter::PROBABLY_REVOKED, - filter->CheckCertificate(cert_spki, serial_number, crl_urls, - parent_spki)); -} diff --git a/net/base/crl_set.cc b/net/base/crl_set.cc new file mode 100644 index 0000000..c0543bf --- /dev/null +++ b/net/base/crl_set.cc @@ -0,0 +1,442 @@ +// Copyright (c) 2011 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 "base/base64.h" +#include "base/json/json_reader.h" +#include "base/logging.h" +#include "base/stl_util.h" +#include "base/values.h" +#include "crypto/sha2.h" +#include "net/base/crl_set.h" + +#if defined(USE_SYSTEM_ZLIB) +#include <zlib.h> +#else +#include "third_party/zlib/zlib.h" +#endif + +namespace net { + +// Decompress zlib decompressed |in| into |out|. |out_len| is the number of +// bytes at |out| and must be exactly equal to the size of the decompressed +// data. +static bool DecompressZlib(uint8* out, int out_len, base::StringPiece in) { + z_stream z; + memset(&z, 0, sizeof(z)); + + z.next_in = reinterpret_cast<Bytef*>(const_cast<char*>(in.data())); + z.avail_in = in.size(); + z.next_out = reinterpret_cast<Bytef*>(out); + z.avail_out = out_len; + + if (inflateInit(&z) != Z_OK) + return false; + bool ret = false; + int r = inflate(&z, Z_FINISH); + if (r != Z_STREAM_END) + goto err; + if (z.avail_in || z.avail_out) + goto err; + ret = true; + + err: + inflateEnd(&z); + return ret; +} + +CRLSet::CRLSet() + : sequence_(0) { +} + +CRLSet::~CRLSet() { +} + +// CRLSet format: +// +// uint16le header_len +// byte[header_len] header_bytes +// repeated { +// byte[32] parent_spki_sha256 +// uint32le num_serials +// [num_serials] { +// uint8 serial_length; +// byte[serial_length] serial; +// } +// +// header_bytes consists of a JSON dictionary with the following keys: +// Version (int): currently 0 +// ContentType (string): "CRLSet" or "CRLSetDelta" (magic value) +// DeltaFrom (int): if this is a delta update (see below), then this contains +// the sequence number of the base CRLSet. +// NextUpdate (int64, epoch seconds): the time at which an update is +// availible. +// WindowSecs (int64, seconds): the span of time to spread fetches over. +// Sequence (int32): the monotonic sequence number of this CRL set. +// +// A delta CRLSet is similar to a CRLSet: +// +// struct CompressedChanges { +// uint32le uncompressed_size +// uint32le compressed_size +// byte[compressed_size] zlib_data +// } +// +// uint16le header_len +// byte[header_len] header_bytes +// CompressedChanges crl_changes +// [crl_changes.uncompressed_size] { +// switch (crl_changes[i]) { +// case 0: +// // CRL is the same +// case 1: +// // New CRL inserted +// // See CRL structure from the non-delta format +// case 2: +// // CRL deleted +// case 3: +// // CRL changed +// CompressedChanges serials_changes +// [serials_changes.uncompressed_size] { +// switch (serials_changes[i]) { +// case 0: +// // the serial is the same +// case 1: +// // serial inserted +// uint8 serial_length +// byte[serial_length] serial +// case 2: +// // serial deleted +// } +// } +// } +// } +// +// A delta CRLSet applies to a specific CRL set as given in the +// header's "DeltaFrom" value. The delta describes the changes to each CRL +// in turn with a zlib compressed array of options: either the CRL is the case, +// a new CRL is inserted, the CRL is deleted or the CRL is updated. In the same +// of an update, the serials in the CRL are considered in the same fashion +// except there is no delta update of a serial number: they are either +// inserted, deleted or left the same. + +// ReadHeader reads the header (including length prefix) from |data| and +// updates |data| to remove the header on return. Caller takes ownership of the +// returned pointer. +static DictionaryValue* ReadHeader(base::StringPiece* data) { + if (data->size() < 2) + return NULL; + uint16 header_len; + memcpy(&header_len, data->data(), 2); // assumes little-endian. + data->remove_prefix(2); + + if (data->size() < header_len) + return NULL; + + const base::StringPiece header_bytes(data->data(), header_len); + data->remove_prefix(header_len); + + scoped_ptr<Value> header(base::JSONReader::Read( + header_bytes.as_string(), true /* allow trailing comma */)); + if (header.get() == NULL) + return NULL; + + if (!header->IsType(Value::TYPE_DICTIONARY)) + return NULL; + return reinterpret_cast<DictionaryValue*>(header.release()); +} + +// kCurrentFileVersion is the version of the CRLSet file format that we +// currently implement. +static const int kCurrentFileVersion = 0; + +static bool ReadCRL(base::StringPiece* data, std::string* out_parent_spki_hash, + std::vector<std::string>* out_serials) { + if (data->size() < crypto::SHA256_LENGTH) + return false; + *out_parent_spki_hash = std::string(data->data(), crypto::SHA256_LENGTH); + data->remove_prefix(crypto::SHA256_LENGTH); + + if (data->size() < sizeof(uint32)) + return false; + uint32 num_serials; + memcpy(&num_serials, data->data(), sizeof(uint32)); // assumes little endian + data->remove_prefix(sizeof(uint32)); + + for (uint32 i = 0; i < num_serials; i++) { + uint8 serial_length; + if (data->size() < sizeof(uint8)) + return false; + memcpy(&serial_length, data->data(), sizeof(uint8)); + data->remove_prefix(sizeof(uint8)); + + if (data->size() < serial_length) + return false; + std::string serial(data->data(), serial_length); + data->remove_prefix(serial_length); + out_serials->push_back(serial); + } + + return true; +} + +// static +bool CRLSet::Parse(base::StringPiece data, scoped_refptr<CRLSet>* out_crl_set) { + // Other parts of Chrome assume that we're little endian, so we don't lose + // anything by doing this. +#if defined(__BYTE_ORDER) + // Linux check + COMPILE_ASSERT(__BYTE_ORDER == __LITTLE_ENDIAN, assumes_little_endian); +#elif defined(__BIG_ENDIAN__) + // Mac check + #error assumes little endian +#endif + + scoped_ptr<DictionaryValue> header_dict(ReadHeader(&data)); + if (!header_dict.get()) + return false; + + std::string contents; + if (!header_dict->GetString("ContentType", &contents)) + return false; + if (contents != "CRLSet") + return false; + + int version; + if (!header_dict->GetInteger("Version", &version) || + version != kCurrentFileVersion) { + return false; + } + + double next_update, window_secs; + int sequence; + if (!header_dict->GetDouble("NextUpdate", &next_update) || + !header_dict->GetDouble("WindowSecs", &window_secs) || + !header_dict->GetInteger("Sequence", &sequence)) { + return false; + } + + scoped_refptr<CRLSet> crl_set(new CRLSet); + crl_set->next_update_ = base::Time::FromDoubleT(next_update); + crl_set->update_window_ = + base::TimeDelta::FromSeconds(static_cast<int64>(window_secs)); + crl_set->sequence_ = static_cast<uint32>(sequence); + + for (size_t crl_index = 0; !data.empty(); crl_index++) { + std::string parent_spki_sha256; + std::vector<std::string> serials; + if (!ReadCRL(&data, &parent_spki_sha256, &serials)) + return false; + + crl_set->crls_.push_back(std::make_pair(parent_spki_sha256, serials)); + crl_set->crls_index_by_issuer_[parent_spki_sha256] = crl_index; + } + + *out_crl_set = crl_set; + return true; +} + +// kMaxUncompressedChangesLength is the largest changes array that we'll +// accept. This bounds the number of CRLs in the CRLSet as well as the number +// of serial numbers in a given CRL. +static const unsigned kMaxUncompressedChangesLength = 1024 * 1024; + +static bool ReadChanges(base::StringPiece* data, + std::vector<uint8>* out_changes) { + uint32 uncompressed_size, compressed_size; + if (data->size() < 2 * sizeof(uint32)) + return false; + // assumes little endian. + memcpy(&uncompressed_size, data->data(), sizeof(uint32)); + data->remove_prefix(4); + memcpy(&compressed_size, data->data(), sizeof(uint32)); + data->remove_prefix(4); + + if (uncompressed_size > kMaxUncompressedChangesLength) + return false; + if (data->size() < compressed_size) + return false; + + out_changes->clear(); + if (uncompressed_size == 0) + return true; + + out_changes->resize(uncompressed_size); + base::StringPiece compressed(data->data(), compressed_size); + data->remove_prefix(compressed_size); + return DecompressZlib(&(*out_changes)[0], uncompressed_size, compressed); +} + +// These are the range coder symbols used in delta updates. +enum { + SYMBOL_SAME = 0, + SYMBOL_INSERT = 1, + SYMBOL_DELETE = 2, + SYMBOL_CHANGED = 3, +}; + +bool ReadDeltaCRL(base::StringPiece* data, + const std::vector<std::string>& old_serials, + std::vector<std::string>* out_serials) { + std::vector<uint8> changes; + if (!ReadChanges(data, &changes)) + return false; + + size_t i = 0; + for (std::vector<uint8>::const_iterator k = changes.begin(); + k != changes.end(); ++k) { + if (*k == SYMBOL_SAME) { + if (i >= old_serials.size()) + return false; + out_serials->push_back(old_serials[i]); + i++; + } else if (*k == SYMBOL_INSERT) { + uint8 serial_length; + if (data->size() < sizeof(uint8)) + return false; + memcpy(&serial_length, data->data(), sizeof(uint8)); + data->remove_prefix(sizeof(uint8)); + + if (data->size() < serial_length) + return false; + const std::string serial(data->data(), serial_length); + data->remove_prefix(serial_length); + + out_serials->push_back(serial); + } else if (*k == SYMBOL_DELETE) { + if (i >= old_serials.size()) + return false; + i++; + } else { + NOTREACHED(); + return false; + } + } + + if (i != old_serials.size()) + return false; + return true; +} + +bool CRLSet::ApplyDelta(base::StringPiece data, + scoped_refptr<CRLSet>* out_crl_set) { + scoped_ptr<DictionaryValue> header_dict(ReadHeader(&data)); + if (!header_dict.get()) + return false; + + std::string contents; + if (!header_dict->GetString("ContentType", &contents)) + return false; + if (contents != "CRLSetDelta") + return false; + + int version; + if (!header_dict->GetInteger("Version", &version) || + version != kCurrentFileVersion) { + return false; + } + + double next_update, update_window; + int sequence, delta_from; + if (!header_dict->GetDouble("NextUpdate", &next_update) || + !header_dict->GetDouble("WindowSecs", &update_window) || + !header_dict->GetInteger("Sequence", &sequence) || + !header_dict->GetInteger("DeltaFrom", &delta_from) || + delta_from < 0 || + static_cast<uint32>(delta_from) != sequence_) { + return false; + } + + scoped_refptr<CRLSet> crl_set(new CRLSet); + crl_set->next_update_ = base::Time::FromDoubleT(next_update); + crl_set->update_window_ = + base::TimeDelta::FromSeconds(static_cast<int64>(update_window)); + crl_set->sequence_ = static_cast<uint32>(sequence); + + std::vector<uint8> crl_changes; + + if (!ReadChanges(&data, &crl_changes)) + return false; + + size_t i = 0, j = 0; + for (std::vector<uint8>::const_iterator k = crl_changes.begin(); + k != crl_changes.end(); ++k) { + if (*k == SYMBOL_SAME) { + if (i >= crls_.size()) + return false; + crl_set->crls_.push_back(crls_[i]); + crl_set->crls_index_by_issuer_[crls_[i].first] = j; + i++; + j++; + } else if (*k == SYMBOL_INSERT) { + std::string parent_spki_hash; + std::vector<std::string> serials; + if (!ReadCRL(&data, &parent_spki_hash, &serials)) + return false; + crl_set->crls_.push_back(std::make_pair(parent_spki_hash, serials)); + crl_set->crls_index_by_issuer_[parent_spki_hash] = j; + j++; + } else if (*k == SYMBOL_DELETE) { + if (i >= crls_.size()) + return false; + i++; + } else if (*k == SYMBOL_CHANGED) { + if (i >= crls_.size()) + return false; + std::vector<std::string> serials; + if (!ReadDeltaCRL(&data, crls_[i].second, &serials)) + return false; + crl_set->crls_.push_back(std::make_pair(crls_[i].first, serials)); + crl_set->crls_index_by_issuer_[crls_[i].first] = j; + i++; + j++; + } else { + NOTREACHED(); + return false; + } + } + + if (!data.empty()) + return false; + if (i != crls_.size()) + return false; + + *out_crl_set = crl_set; + return true; +} + +CRLSet::Result CRLSet::CheckCertificate( + const base::StringPiece& serial_number, + const base::StringPiece& parent_spki) const { + std::map<std::string, size_t>::const_iterator i = + crls_index_by_issuer_.find(parent_spki.as_string()); + if (i == crls_index_by_issuer_.end()) + return UNKNOWN; + const std::vector<std::string>& serials = crls_[i->second].second; + + for (std::vector<std::string>::const_iterator i = serials.begin(); + i != serials.end(); ++i) { + if (*i == serial_number.as_string()) + return REVOKED; + } + + return GOOD; +} + +base::Time CRLSet::next_update() const { + return next_update_; +} + +base::TimeDelta CRLSet::update_window() const { + return update_window_; +} + +uint32 CRLSet::sequence() const { + return sequence_; +} + +const CRLSet::CRLList& CRLSet::crls() const { + return crls_; +} + +} // namespace net diff --git a/net/base/crl_set.h b/net/base/crl_set.h new file mode 100644 index 0000000..99a39c6 --- /dev/null +++ b/net/base/crl_set.h @@ -0,0 +1,97 @@ +// Copyright (c) 2011 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_BASE_CRL_SET_H_ +#define NET_BASE_CRL_SET_H_ +#pragma once + +#include <map> +#include <string> +#include <utility> +#include <vector> + +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "base/string_piece.h" +#include "base/time.h" +#include "net/base/net_export.h" + +namespace net { + +// A CRLSet is a structure that lists the serial numbers of revoked +// certificates from a number of issuers where issuers are identified by the +// SHA256 of their SubjectPublicKeyInfo. +class NET_EXPORT_PRIVATE CRLSet : public base::RefCounted<CRLSet> { + public: + enum Result { + REVOKED, // the certificate should be rejected. + UNKNOWN, // there was an error in processing. + GOOD, // the certificate is not listed. + }; + + ~CRLSet(); + + // Parse parses the bytes in |data| and, on success, puts a new CRLSet in + // |out_crl_set| and returns true. + static bool Parse(base::StringPiece data, + scoped_refptr<CRLSet>* out_crl_set); + + // CheckCertificate returns the information contained in the set for a given + // certificate: + // serial_number: the serial number of the certificate + // issuer_spki_hash: the SubjectPublicKeyInfo of the CRL signer + // + // This does not check that the CRLSet is timely. See |next_update|. + Result CheckCertificate( + const base::StringPiece& serial_number, + const base::StringPiece& issuer_spki_hash) const; + + // ApplyDelta returns a new CRLSet in |out_crl_set| that is the result of + // updating the current CRL set with the delta information in |delta_bytes|. + bool ApplyDelta(base::StringPiece delta_bytes, + scoped_refptr<CRLSet>* out_crl_set); + + // next_update returns the time at which a new CRLSet may be availible. + base::Time next_update() const; + + // update_window returns the number of seconds in the update window. Once the + // |next_update| time has occured, the client should schedule a fetch, + // uniformly at random, within |update_window|. This aims to smooth the load + // on the server. + base::TimeDelta update_window() const; + + // sequence returns the sequence number of this CRL set. CRL sets generated + // by the same source are given strictly monotonically increasing sequence + // numbers. + uint32 sequence() const; + + // CRLList contains a list of (issuer SPKI hash, revoked serial numbers) + // pairs. + typedef std::vector< std::pair<std::string, std::vector<std::string> > > + CRLList; + + // crls returns the internal state of this CRLSet. It should only be used in + // testing. + const CRLList& crls() const; + + private: + CRLSet(); + + static CRLSet* CRLSetFromHeader(base::StringPiece header); + + base::Time next_update_; + base::TimeDelta update_window_; + uint32 sequence_; + + CRLList crls_; + // crls_index_by_issuer_ maps from issuer SPKI hashes to the index in |crls_| + // where the information for that issuer can be found. We have both |crls_| + // and |crls_index_by_issuer_| because, when applying a delta update, we need + // to identify a CRL by index. + std::map<std::string, size_t> crls_index_by_issuer_; +}; + +} // namespace net + +#endif // NET_BASE_CRL_SET_H_ diff --git a/net/base/crl_set_unittest.cc b/net/base/crl_set_unittest.cc new file mode 100644 index 0000000..cb5365a --- /dev/null +++ b/net/base/crl_set_unittest.cc @@ -0,0 +1,271 @@ +// Copyright (c) 2011 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/base/crl_set.h" +#include "testing/gtest/include/gtest/gtest.h" + +// These data blocks were generated using a lot of code that is still in +// development. For now, if you need to update them, you have to contact agl. +static const uint8 kGIACRLSet[] = { + 0xbe, 0x00, 0x7b, 0x22, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x3a, + 0x30, 0x2c, 0x22, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, + 0x65, 0x22, 0x3a, 0x22, 0x43, 0x52, 0x4c, 0x53, 0x65, 0x74, 0x22, 0x2c, 0x22, + 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x22, 0x3a, 0x30, 0x2c, 0x22, + 0x4e, 0x65, 0x78, 0x74, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x22, 0x3a, 0x31, + 0x33, 0x31, 0x31, 0x31, 0x32, 0x34, 0x36, 0x35, 0x34, 0x2c, 0x22, 0x57, 0x69, + 0x6e, 0x64, 0x6f, 0x77, 0x53, 0x65, 0x63, 0x73, 0x22, 0x3a, 0x34, 0x33, 0x32, + 0x30, 0x30, 0x2c, 0x22, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x46, 0x72, 0x6f, 0x6d, + 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x4e, 0x75, 0x6d, 0x50, 0x61, 0x72, 0x65, 0x6e, + 0x74, 0x73, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, + 0x67, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x22, 0x3a, 0x22, + 0x22, 0x2c, 0x22, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x4b, 0x65, 0x79, + 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0x3a, 0x22, 0x22, + 0x2c, 0x22, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x69, 0x67, 0x6e, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0x3a, 0x22, 0x22, 0x7d, 0xb6, 0xb9, 0x54, + 0x32, 0xab, 0xae, 0x57, 0xfe, 0x02, 0x0c, 0xb2, 0xb7, 0x4f, 0x4f, 0x9f, 0x91, + 0x73, 0xc8, 0xc7, 0x08, 0xaf, 0xc9, 0xe7, 0x32, 0xac, 0xe2, 0x32, 0x79, 0x04, + 0x7c, 0x6d, 0x05, 0x0d, 0x00, 0x00, 0x00, 0x0a, 0x10, 0x0d, 0x7f, 0x30, 0x00, + 0x03, 0x00, 0x00, 0x23, 0xb0, 0x0a, 0x10, 0x0e, 0x37, 0x06, 0x00, 0x03, 0x00, + 0x00, 0x23, 0xb1, 0x0a, 0x16, 0x25, 0x42, 0x54, 0x00, 0x03, 0x00, 0x00, 0x14, + 0x51, 0x0a, 0x16, 0x69, 0xd1, 0xd7, 0x00, 0x03, 0x00, 0x00, 0x14, 0x52, 0x0a, + 0x16, 0x70, 0x8c, 0x22, 0x00, 0x03, 0x00, 0x00, 0x14, 0x53, 0x0a, 0x16, 0x71, + 0x31, 0x2c, 0x00, 0x03, 0x00, 0x00, 0x14, 0x54, 0x0a, 0x16, 0x7d, 0x75, 0x9d, + 0x00, 0x03, 0x00, 0x00, 0x14, 0x55, 0x0a, 0x1f, 0xee, 0xf9, 0x49, 0x00, 0x03, + 0x00, 0x00, 0x23, 0xae, 0x0a, 0x1f, 0xfc, 0xd1, 0x89, 0x00, 0x03, 0x00, 0x00, + 0x23, 0xaf, 0x0a, 0x61, 0xdd, 0xc7, 0x48, 0x00, 0x03, 0x00, 0x00, 0x18, 0x0e, + 0x0a, 0x61, 0xe6, 0x12, 0x64, 0x00, 0x03, 0x00, 0x00, 0x18, 0x0f, 0x0a, 0x61, + 0xe9, 0x46, 0x56, 0x00, 0x03, 0x00, 0x00, 0x18, 0x10, 0x0a, 0x64, 0x63, 0x49, + 0xd2, 0x00, 0x03, 0x00, 0x00, 0x1d, 0x77, +}; + +static const uint8 kNoopDeltaCRL[] = { + 0xc3, 0x00, 0x7b, 0x22, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x3a, + 0x30, 0x2c, 0x22, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, + 0x65, 0x22, 0x3a, 0x22, 0x43, 0x52, 0x4c, 0x53, 0x65, 0x74, 0x44, 0x65, 0x6c, + 0x74, 0x61, 0x22, 0x2c, 0x22, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, + 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x4e, 0x65, 0x78, 0x74, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x22, 0x3a, 0x31, 0x33, 0x31, 0x31, 0x31, 0x32, 0x33, 0x37, 0x39, + 0x33, 0x2c, 0x22, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x53, 0x65, 0x63, 0x73, + 0x22, 0x3a, 0x34, 0x33, 0x32, 0x30, 0x30, 0x2c, 0x22, 0x44, 0x65, 0x6c, 0x74, + 0x61, 0x46, 0x72, 0x6f, 0x6d, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x4e, 0x75, 0x6d, + 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x53, + 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, + 0x65, 0x79, 0x22, 0x3a, 0x22, 0x22, 0x2c, 0x22, 0x53, 0x69, 0x67, 0x6e, 0x69, + 0x6e, 0x67, 0x4b, 0x65, 0x79, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x22, 0x3a, 0x22, 0x22, 0x2c, 0x22, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, + 0x64, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0x3a, 0x22, + 0x22, 0x7d, 0x01, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x78, 0x9c, 0x62, + 0x00, 0x04, 0x00, 0x00, 0xff, 0xff, 0x00, 0x01, 0x00, 0x01, +}; + +static const uint8 kAddCRLDelta[] = { + 0xc3, 0x00, 0x7b, 0x22, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x3a, + 0x30, 0x2c, 0x22, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, + 0x65, 0x22, 0x3a, 0x22, 0x43, 0x52, 0x4c, 0x53, 0x65, 0x74, 0x44, 0x65, 0x6c, + 0x74, 0x61, 0x22, 0x2c, 0x22, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, + 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x4e, 0x65, 0x78, 0x74, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x22, 0x3a, 0x31, 0x33, 0x31, 0x31, 0x31, 0x32, 0x35, 0x39, 0x34, + 0x38, 0x2c, 0x22, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x53, 0x65, 0x63, 0x73, + 0x22, 0x3a, 0x34, 0x33, 0x32, 0x30, 0x30, 0x2c, 0x22, 0x44, 0x65, 0x6c, 0x74, + 0x61, 0x46, 0x72, 0x6f, 0x6d, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x4e, 0x75, 0x6d, + 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a, 0x32, 0x2c, 0x22, 0x53, + 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, + 0x65, 0x79, 0x22, 0x3a, 0x22, 0x22, 0x2c, 0x22, 0x53, 0x69, 0x67, 0x6e, 0x69, + 0x6e, 0x67, 0x4b, 0x65, 0x79, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x22, 0x3a, 0x22, 0x22, 0x2c, 0x22, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, + 0x64, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0x3a, 0x22, + 0x22, 0x7d, 0x02, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x78, 0x9c, 0x62, + 0x60, 0x04, 0x04, 0x00, 0x00, 0xff, 0xff, 0x00, 0x03, 0x00, 0x02, 0xe4, 0x2f, + 0x24, 0xbd, 0x4d, 0x37, 0xf4, 0xaa, 0x2e, 0x56, 0xb9, 0x79, 0xd8, 0x3d, 0x1e, + 0x65, 0x21, 0x9f, 0xe0, 0xe9, 0xe3, 0xa3, 0x82, 0xa1, 0xb3, 0xcb, 0x66, 0xc9, + 0x39, 0x55, 0xde, 0x75, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x02, 0x01, 0x03, 0x01, + 0x04, 0x01, 0x05, 0x01, 0x06, 0x01, 0x07, 0x01, 0x08, 0x01, 0x09, 0x01, 0x2f, + 0x01, 0x30, 0x01, 0x31, 0x01, 0x32, +}; + +static const uint8 kRemoveCRLDelta[] = { + 0xc3, 0x00, 0x7b, 0x22, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x3a, + 0x30, 0x2c, 0x22, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, + 0x65, 0x22, 0x3a, 0x22, 0x43, 0x52, 0x4c, 0x53, 0x65, 0x74, 0x44, 0x65, 0x6c, + 0x74, 0x61, 0x22, 0x2c, 0x22, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, + 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x4e, 0x65, 0x78, 0x74, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x22, 0x3a, 0x31, 0x33, 0x31, 0x31, 0x31, 0x32, 0x36, 0x31, 0x31, + 0x36, 0x2c, 0x22, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x53, 0x65, 0x63, 0x73, + 0x22, 0x3a, 0x34, 0x33, 0x32, 0x30, 0x30, 0x2c, 0x22, 0x44, 0x65, 0x6c, 0x74, + 0x61, 0x46, 0x72, 0x6f, 0x6d, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x4e, 0x75, 0x6d, + 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x53, + 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, + 0x65, 0x79, 0x22, 0x3a, 0x22, 0x22, 0x2c, 0x22, 0x53, 0x69, 0x67, 0x6e, 0x69, + 0x6e, 0x67, 0x4b, 0x65, 0x79, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x22, 0x3a, 0x22, 0x22, 0x2c, 0x22, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, + 0x64, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0x3a, 0x22, + 0x22, 0x7d, 0x02, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x78, 0x9c, 0x62, + 0x60, 0x02, 0x04, 0x00, 0x00, 0xff, 0xff, 0x00, 0x04, 0x00, 0x03, +}; + +static const uint8 kUpdateSerialsDelta[] = { + 0xc3, 0x00, 0x7b, 0x22, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x3a, + 0x30, 0x2c, 0x22, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, + 0x65, 0x22, 0x3a, 0x22, 0x43, 0x52, 0x4c, 0x53, 0x65, 0x74, 0x44, 0x65, 0x6c, + 0x74, 0x61, 0x22, 0x2c, 0x22, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, + 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x4e, 0x65, 0x78, 0x74, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x22, 0x3a, 0x31, 0x33, 0x31, 0x31, 0x31, 0x32, 0x36, 0x34, 0x36, + 0x31, 0x2c, 0x22, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x53, 0x65, 0x63, 0x73, + 0x22, 0x3a, 0x34, 0x33, 0x32, 0x30, 0x30, 0x2c, 0x22, 0x44, 0x65, 0x6c, 0x74, + 0x61, 0x46, 0x72, 0x6f, 0x6d, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x4e, 0x75, 0x6d, + 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x53, + 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, + 0x65, 0x79, 0x22, 0x3a, 0x22, 0x22, 0x2c, 0x22, 0x53, 0x69, 0x67, 0x6e, 0x69, + 0x6e, 0x67, 0x4b, 0x65, 0x79, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x22, 0x3a, 0x22, 0x22, 0x2c, 0x22, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, + 0x64, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0x3a, 0x22, + 0x22, 0x7d, 0x01, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x78, 0x9c, 0x62, + 0x06, 0x04, 0x00, 0x00, 0xff, 0xff, 0x00, 0x04, 0x00, 0x04, 0x2d, 0x00, 0x00, + 0x00, 0x15, 0x00, 0x00, 0x00, 0x78, 0x9c, 0x62, 0x80, 0x00, 0x46, 0x2c, 0x00, + 0x45, 0x14, 0xac, 0x08, 0x10, 0x00, 0x00, 0xff, 0xff, 0x02, 0xe1, 0x00, 0x21, + 0x0a, 0x10, 0x0d, 0x7f, 0x30, 0x00, 0x03, 0x00, 0x00, 0x23, 0xb0, 0x0a, 0x10, + 0x0d, 0x7f, 0x30, 0x00, 0x03, 0x00, 0x00, 0x23, 0xb0, 0x0a, 0x10, 0x0d, 0x7f, + 0x30, 0x00, 0x03, 0x00, 0x00, 0x23, 0xb0, 0x0a, 0x10, 0x0d, 0x7f, 0x30, 0x00, + 0x03, 0x00, 0x00, 0x23, 0xb0, 0x0a, 0x10, 0x0d, 0x7f, 0x30, 0x00, 0x03, 0x00, + 0x00, 0x23, 0xb0, 0x0a, 0x10, 0x0d, 0x7f, 0x30, 0x00, 0x03, 0x00, 0x00, 0x23, + 0xb0, 0x0a, 0x10, 0x0d, 0x7f, 0x30, 0x00, 0x03, 0x00, 0x00, 0x23, 0xb0, 0x0a, + 0x10, 0x0d, 0x7f, 0x30, 0x00, 0x03, 0x00, 0x00, 0x23, 0xb0, 0x0a, 0x10, 0x0d, + 0x7f, 0x30, 0x00, 0x03, 0x00, 0x00, 0x23, 0xb0, 0x0a, 0x10, 0x0d, 0x7f, 0x30, + 0x00, 0x03, 0x00, 0x00, 0x23, 0xb0, 0x0a, 0x10, 0x0d, 0x7f, 0x30, 0x00, 0x03, + 0x00, 0x00, 0x23, 0xb0, 0x0a, 0x10, 0x0d, 0x7f, 0x30, 0x00, 0x03, 0x00, 0x00, + 0x23, 0xb0, 0x0a, 0x10, 0x0d, 0x7f, 0x30, 0x00, 0x03, 0x00, 0x00, 0x23, 0xb0, + 0x0a, 0x10, 0x0d, 0x7f, 0x30, 0x00, 0x03, 0x00, 0x00, 0x23, 0xb0, 0x0a, 0x10, + 0x0d, 0x7f, 0x30, 0x00, 0x03, 0x00, 0x00, 0x23, 0xb0, 0x0a, 0x10, 0x0d, 0x7f, + 0x30, 0x00, 0x03, 0x00, 0x00, 0x23, 0xb0, 0x0a, 0x10, 0x0d, 0x7f, 0x30, 0x00, + 0x03, 0x00, 0x00, 0x23, 0xb0, 0x0a, 0x10, 0x0d, 0x7f, 0x30, 0x00, 0x03, 0x00, + 0x00, 0x23, 0xb0, 0x0a, 0x10, 0x0d, 0x7f, 0x30, 0x00, 0x03, 0x00, 0x00, 0x23, + 0xb0, 0x0a, 0x10, 0x0d, 0x7f, 0x30, 0x00, 0x03, 0x00, 0x00, 0x23, 0xb0, 0x0a, + 0x10, 0x0d, 0x7f, 0x30, 0x00, 0x03, 0x00, 0x00, 0x23, 0xb0, 0x0a, 0x10, 0x0d, + 0x7f, 0x30, 0x00, 0x03, 0x00, 0x00, 0x23, 0xb0, 0x0a, 0x10, 0x0d, 0x7f, 0x30, + 0x00, 0x03, 0x00, 0x00, 0x23, 0xb0, 0x0a, 0x10, 0x0d, 0x7f, 0x30, 0x00, 0x03, + 0x00, 0x00, 0x23, 0xb0, 0x0a, 0x10, 0x0d, 0x7f, 0x30, 0x00, 0x03, 0x00, 0x00, + 0x23, 0xb0, 0x0a, 0x10, 0x0d, 0x7f, 0x30, 0x00, 0x03, 0x00, 0x00, 0x23, 0xb0, + 0x0a, 0x10, 0x0d, 0x7f, 0x30, 0x00, 0x03, 0x00, 0x00, 0x23, 0xb0, 0x0a, 0x10, + 0x0d, 0x7f, 0x30, 0x00, 0x03, 0x00, 0x00, 0x23, 0xb0, 0x0a, 0x10, 0x0d, 0x7f, + 0x30, 0x00, 0x03, 0x00, 0x00, 0x23, 0xb0, 0x0a, 0x10, 0x0d, 0x7f, 0x30, 0x00, + 0x03, 0x00, 0x00, 0x23, 0xb0, 0x0a, 0x10, 0x0d, 0x7f, 0x30, 0x00, 0x03, 0x00, + 0x00, 0x23, 0xb0, 0x0a, 0x10, 0x0d, 0x7f, 0x30, 0x00, 0x03, 0x00, 0x00, 0x23, + 0xb0, +}; + +// kGIASPKISHA256 is the SHA256 digest the Google Internet Authority's +// SubjectPublicKeyInfo. +static const uint8 kGIASPKISHA256[32] = { + 0xb6, 0xb9, 0x54, 0x32, 0xab, 0xae, 0x57, 0xfe, 0x02, 0x0c, 0xb2, 0xb7, 0x4f, + 0x4f, 0x9f, 0x91, 0x73, 0xc8, 0xc7, 0x08, 0xaf, 0xc9, 0xe7, 0x32, 0xac, 0xe2, + 0x32, 0x79, 0x04, 0x7c, 0x6d, 0x05, +}; + +TEST(CRLSetTest, Parse) { + base::StringPiece s(reinterpret_cast<const char*>(kGIACRLSet), + sizeof(kGIACRLSet)); + scoped_refptr<net::CRLSet> set; + EXPECT_TRUE(net::CRLSet::Parse(s, &set)); + ASSERT_TRUE(set.get() != NULL); + + const net::CRLSet::CRLList& crls = set->crls(); + ASSERT_EQ(1u, crls.size()); + const std::vector<std::string>& serials = crls[0].second; + static const unsigned kExpectedNumSerials = 13; + ASSERT_EQ(kExpectedNumSerials, serials.size()); + EXPECT_EQ(std::string("\x10\x0D\x7F\x30\x00\x03\x00\x00\x23\xB0", 10), + serials[0]); + EXPECT_EQ(std::string("\x64\x63\x49\xD2\x00\x03\x00\x00\x1D\x77", 10), + serials[kExpectedNumSerials - 1]); + + const std::string gia_spki_hash( + reinterpret_cast<const char*>(kGIASPKISHA256), + sizeof(kGIASPKISHA256)); + EXPECT_EQ(net::CRLSet::REVOKED, set->CheckCertificate( + std::string("\x16\x7D\x75\x9D\x00\x03\x00\x00\x14\x55", 10), + gia_spki_hash)); + EXPECT_EQ(net::CRLSet::GOOD, set->CheckCertificate( + std::string("\x47\x54\x3E\x79\x00\x03\x00\x00\x14\xF5", 10), + gia_spki_hash)); +} + +TEST(CRLSetTest, NoOpDeltaUpdate) { + base::StringPiece s(reinterpret_cast<const char*>(kGIACRLSet), + sizeof(kGIACRLSet)); + scoped_refptr<net::CRLSet> set; + EXPECT_TRUE(net::CRLSet::Parse(s, &set)); + ASSERT_TRUE(set.get() != NULL); + + scoped_refptr<net::CRLSet> delta_set; + base::StringPiece delta(reinterpret_cast<const char*>(kNoopDeltaCRL), + sizeof(kNoopDeltaCRL)); + EXPECT_TRUE(set->ApplyDelta(delta, &delta_set)); + ASSERT_TRUE(delta_set.get() != NULL); +} + +TEST(CRLSetTest, AddCRLDelta) { + base::StringPiece s(reinterpret_cast<const char*>(kGIACRLSet), + sizeof(kGIACRLSet)); + scoped_refptr<net::CRLSet> set; + EXPECT_TRUE(net::CRLSet::Parse(s, &set)); + ASSERT_TRUE(set.get() != NULL); + + scoped_refptr<net::CRLSet> delta_set; + base::StringPiece delta(reinterpret_cast<const char*>(kAddCRLDelta), + sizeof(kAddCRLDelta)); + EXPECT_TRUE(set->ApplyDelta(delta, &delta_set)); + ASSERT_TRUE(delta_set.get() != NULL); + + const net::CRLSet::CRLList& crls = delta_set->crls(); + ASSERT_EQ(2u, crls.size()); + const std::vector<std::string>& serials = crls[1].second; + ASSERT_EQ(12u, serials.size()); + EXPECT_EQ(std::string("\x02", 1), serials[0]); + EXPECT_EQ(std::string("\x03", 1), serials[1]); + EXPECT_EQ(std::string("\x04", 1), serials[2]); +} + +TEST(CRLSetTest, AddRemoveCRLDelta) { + base::StringPiece s(reinterpret_cast<const char*>(kGIACRLSet), + sizeof(kGIACRLSet)); + scoped_refptr<net::CRLSet> set; + EXPECT_TRUE(net::CRLSet::Parse(s, &set)); + ASSERT_TRUE(set.get() != NULL); + + scoped_refptr<net::CRLSet> delta_set; + base::StringPiece delta(reinterpret_cast<const char*>(kAddCRLDelta), + sizeof(kAddCRLDelta)); + EXPECT_TRUE(set->ApplyDelta(delta, &delta_set)); + ASSERT_TRUE(delta_set.get() != NULL); + + scoped_refptr<net::CRLSet> delta2_set; + base::StringPiece delta2(reinterpret_cast<const char*>(kRemoveCRLDelta), + sizeof(kRemoveCRLDelta)); + EXPECT_TRUE(delta_set->ApplyDelta(delta2, &delta2_set)); + ASSERT_TRUE(delta2_set.get() != NULL); + + const net::CRLSet::CRLList& crls = delta2_set->crls(); + ASSERT_EQ(1u, crls.size()); + const std::vector<std::string>& serials = crls[0].second; + ASSERT_EQ(13u, serials.size()); +} + +TEST(CRLSetTest, UpdateSerialsDelta) { + base::StringPiece s(reinterpret_cast<const char*>(kGIACRLSet), + sizeof(kGIACRLSet)); + scoped_refptr<net::CRLSet> set; + EXPECT_TRUE(net::CRLSet::Parse(s, &set)); + ASSERT_TRUE(set.get() != NULL); + + scoped_refptr<net::CRLSet> delta_set; + base::StringPiece delta(reinterpret_cast<const char*>(kUpdateSerialsDelta), + sizeof(kUpdateSerialsDelta)); + EXPECT_TRUE(set->ApplyDelta(delta, &delta_set)); + ASSERT_TRUE(delta_set.get() != NULL); + + const net::CRLSet::CRLList& crls = delta_set->crls(); + ASSERT_EQ(1u, crls.size()); + const std::vector<std::string>& serials = crls[0].second; + EXPECT_EQ(45u, serials.size()); +} diff --git a/net/net.gyp b/net/net.gyp index 12bb890..fb55d21 100644 --- a/net/net.gyp +++ b/net/net.gyp @@ -62,8 +62,8 @@ 'base/cookie_options.h', 'base/cookie_store.cc', 'base/cookie_store.h', - 'base/crl_filter.cc', - 'base/crl_filter.h', + 'base/crl_set.cc', + 'base/crl_set.h', 'base/crypto_module.h', 'base/crypto_module_nss.cc', 'base/crypto_module_openssl.cc', @@ -891,7 +891,7 @@ 'base/cert_database_nss_unittest.cc', 'base/cert_verifier_unittest.cc', 'base/cookie_monster_unittest.cc', - 'base/crl_filter_unittest.cc', + 'base/crl_set_unittest.cc', 'base/data_url_unittest.cc', 'base/default_origin_bound_cert_store_unittest.cc', 'base/directory_lister_unittest.cc', |