summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/base/crl_filter.cc878
-rw-r--r--net/base/crl_filter.h114
-rw-r--r--net/base/crl_filter_unittest.cc216
-rw-r--r--net/base/crl_set.cc442
-rw-r--r--net/base/crl_set.h97
-rw-r--r--net/base/crl_set_unittest.cc271
-rw-r--r--net/net.gyp6
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_, &current_, 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", &not_before) ||
- !header_dict->GetDouble("NotAfter", &not_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',