1116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Copyright 2014 The Chromium Authors. All rights reserved.
2116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Use of this source code is governed by a BSD-style license that can be
3116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// found in the LICENSE file.
4116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
5116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "net/cert/crl_set_storage.h"
6116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
7116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/base64.h"
8116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/debug/trace_event.h"
9116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/format_macros.h"
10116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/json/json_reader.h"
11116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/strings/stringprintf.h"
12116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/values.h"
13116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "crypto/sha2.h"
14116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "third_party/zlib/zlib.h"
15116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
16116680a4aac90f2aa7413d9095a592090648e557Ben Murdochnamespace net {
17116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
18116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Decompress zlib decompressed |in| into |out|. |out_len| is the number of
19116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// bytes at |out| and must be exactly equal to the size of the decompressed
20116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// data.
21116680a4aac90f2aa7413d9095a592090648e557Ben Murdochstatic bool DecompressZlib(uint8* out, int out_len, base::StringPiece in) {
22116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  z_stream z;
23116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  memset(&z, 0, sizeof(z));
24116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
25116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  z.next_in = reinterpret_cast<Bytef*>(const_cast<char*>(in.data()));
26116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  z.avail_in = in.size();
27116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  z.next_out = reinterpret_cast<Bytef*>(out);
28116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  z.avail_out = out_len;
29116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
30116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (inflateInit(&z) != Z_OK)
31116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return false;
32116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  bool ret = false;
33116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  int r = inflate(&z, Z_FINISH);
34116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (r != Z_STREAM_END)
35116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    goto err;
36116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (z.avail_in || z.avail_out)
37116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    goto err;
38116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ret = true;
39116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
40116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch err:
41116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  inflateEnd(&z);
42116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return ret;
43116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
44116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
45116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// CRLSet format:
46116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch//
47116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// uint16le header_len
48116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// byte[header_len] header_bytes
49116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// repeated {
50116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch//   byte[32] parent_spki_sha256
51116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch//   uint32le num_serials
52116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch//   [num_serials] {
53116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch//     uint8 serial_length;
54116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch//     byte[serial_length] serial;
55116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch//   }
56116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch//
57116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// header_bytes consists of a JSON dictionary with the following keys:
58116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch//   Version (int): currently 0
59116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch//   ContentType (string): "CRLSet" or "CRLSetDelta" (magic value)
60116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch//   DeltaFrom (int32): if this is a delta update (see below), then this
61116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch//       contains the sequence number of the base CRLSet.
62116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch//   Sequence (int32): the monotonic sequence number of this CRL set.
63116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch//
64116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// A delta CRLSet is similar to a CRLSet:
65116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch//
66116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// struct CompressedChanges {
67116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch//    uint32le uncompressed_size
68116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch//    uint32le compressed_size
69116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch//    byte[compressed_size] zlib_data
70116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// }
71116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch//
72116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// uint16le header_len
73116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// byte[header_len] header_bytes
74116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// CompressedChanges crl_changes
75116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// [crl_changes.uncompressed_size] {
76116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch//   switch (crl_changes[i]) {
77116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch//   case 0:
78116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch//     // CRL is the same
79116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch//   case 1:
80116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch//     // New CRL inserted
81116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch//     // See CRL structure from the non-delta format
82116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch//   case 2:
83116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch//     // CRL deleted
84116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch//   case 3:
85116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch//     // CRL changed
86116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch//     CompressedChanges serials_changes
87116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch//     [serials_changes.uncompressed_size] {
88116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch//       switch (serials_changes[i]) {
89116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch//       case 0:
90116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch//         // the serial is the same
91116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch//       case 1:
92116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch//         // serial inserted
93116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch//         uint8 serial_length
94116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch//         byte[serial_length] serial
95116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch//       case 2:
96116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch//         // serial deleted
97116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch//       }
98116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch//     }
99116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch//   }
100116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// }
101116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch//
102116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// A delta CRLSet applies to a specific CRL set as given in the
103116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// header's "DeltaFrom" value. The delta describes the changes to each CRL
104116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// in turn with a zlib compressed array of options: either the CRL is the same,
105116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// a new CRL is inserted, the CRL is deleted or the CRL is updated. In the case
106116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// of an update, the serials in the CRL are considered in the same fashion
107116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// except there is no delta update of a serial number: they are either
108116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// inserted, deleted or left the same.
109116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
110116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// ReadHeader reads the header (including length prefix) from |data| and
111116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// updates |data| to remove the header on return. Caller takes ownership of the
112116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// returned pointer.
113116680a4aac90f2aa7413d9095a592090648e557Ben Murdochstatic base::DictionaryValue* ReadHeader(base::StringPiece* data) {
114116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (data->size() < 2)
115116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return NULL;
116116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  uint16 header_len;
117116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  memcpy(&header_len, data->data(), 2);  // assumes little-endian.
118116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  data->remove_prefix(2);
119116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
120116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (data->size() < header_len)
121116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return NULL;
122116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
123116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  const base::StringPiece header_bytes(data->data(), header_len);
124116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  data->remove_prefix(header_len);
125116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
126116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_ptr<base::Value> header(base::JSONReader::Read(
127116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      header_bytes, base::JSON_ALLOW_TRAILING_COMMAS));
128116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (header.get() == NULL)
129116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return NULL;
130116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
131116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!header->IsType(base::Value::TYPE_DICTIONARY))
132116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return NULL;
133116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return reinterpret_cast<base::DictionaryValue*>(header.release());
134116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
135116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
136116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// kCurrentFileVersion is the version of the CRLSet file format that we
137116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// currently implement.
138116680a4aac90f2aa7413d9095a592090648e557Ben Murdochstatic const int kCurrentFileVersion = 0;
139116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
140116680a4aac90f2aa7413d9095a592090648e557Ben Murdochstatic bool ReadCRL(base::StringPiece* data, std::string* out_parent_spki_hash,
141116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                    std::vector<std::string>* out_serials) {
142116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (data->size() < crypto::kSHA256Length)
143116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return false;
144116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  out_parent_spki_hash->assign(data->data(), crypto::kSHA256Length);
145116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  data->remove_prefix(crypto::kSHA256Length);
146116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
147116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (data->size() < sizeof(uint32))
148116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return false;
149116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  uint32 num_serials;
150116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  memcpy(&num_serials, data->data(), sizeof(uint32));  // assumes little endian
151116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (num_serials > 32 * 1024 * 1024)  // Sanity check.
152116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return false;
153116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
154116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  out_serials->reserve(num_serials);
155116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  data->remove_prefix(sizeof(uint32));
156116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
157116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  for (uint32 i = 0; i < num_serials; ++i) {
158116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (data->size() < sizeof(uint8))
159116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      return false;
160116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
161116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    uint8 serial_length = data->data()[0];
162116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    data->remove_prefix(sizeof(uint8));
163116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
164116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (data->size() < serial_length)
165116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      return false;
166116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
167116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    out_serials->push_back(std::string());
168116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    out_serials->back().assign(data->data(), serial_length);
169116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    data->remove_prefix(serial_length);
170116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
171116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
172116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return true;
173116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
174116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
175116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// static
176116680a4aac90f2aa7413d9095a592090648e557Ben Murdochbool CRLSetStorage::CopyBlockedSPKIsFromHeader(
177116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    CRLSet* crl_set,
178116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    base::DictionaryValue* header_dict) {
179116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  base::ListValue* blocked_spkis_list = NULL;
180116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!header_dict->GetList("BlockedSPKIs", &blocked_spkis_list)) {
181116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // BlockedSPKIs is optional, so it's fine if we don't find it.
182116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return true;
183116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
184116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
185116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  crl_set->blocked_spkis_.clear();
186116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  crl_set->blocked_spkis_.reserve(blocked_spkis_list->GetSize());
187116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
188116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  std::string spki_sha256_base64;
189116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
190116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  for (size_t i = 0; i < blocked_spkis_list->GetSize(); ++i) {
191116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    spki_sha256_base64.clear();
192116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
193116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (!blocked_spkis_list->GetString(i, &spki_sha256_base64))
194116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      return false;
195116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
196116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    crl_set->blocked_spkis_.push_back(std::string());
197116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (!base::Base64Decode(spki_sha256_base64,
198116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                            &crl_set->blocked_spkis_.back())) {
199116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      crl_set->blocked_spkis_.pop_back();
200116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      return false;
201116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
202116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
203116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
204116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return true;
205116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
206116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
207116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// kMaxUncompressedChangesLength is the largest changes array that we'll
208116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// accept. This bounds the number of CRLs in the CRLSet as well as the number
209116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// of serial numbers in a given CRL.
210116680a4aac90f2aa7413d9095a592090648e557Ben Murdochstatic const unsigned kMaxUncompressedChangesLength = 1024 * 1024;
211116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
212116680a4aac90f2aa7413d9095a592090648e557Ben Murdochstatic bool ReadChanges(base::StringPiece* data,
213116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                        std::vector<uint8>* out_changes) {
214116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  uint32 uncompressed_size, compressed_size;
215116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (data->size() < 2 * sizeof(uint32))
216116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return false;
217116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // assumes little endian.
218116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  memcpy(&uncompressed_size, data->data(), sizeof(uint32));
219116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  data->remove_prefix(4);
220116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  memcpy(&compressed_size, data->data(), sizeof(uint32));
221116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  data->remove_prefix(4);
222116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
223116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (uncompressed_size > kMaxUncompressedChangesLength)
224116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return false;
225116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (data->size() < compressed_size)
226116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return false;
227116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
228116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  out_changes->clear();
229116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (uncompressed_size == 0)
230116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return true;
231116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
232116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  out_changes->resize(uncompressed_size);
233116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  base::StringPiece compressed(data->data(), compressed_size);
234116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  data->remove_prefix(compressed_size);
235116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return DecompressZlib(&(*out_changes)[0], uncompressed_size, compressed);
236116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
237116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
238116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// These are the range coder symbols used in delta updates.
239116680a4aac90f2aa7413d9095a592090648e557Ben Murdochenum {
240116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  SYMBOL_SAME = 0,
241116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  SYMBOL_INSERT = 1,
242116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  SYMBOL_DELETE = 2,
243116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  SYMBOL_CHANGED = 3,
244116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch};
245116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
246116680a4aac90f2aa7413d9095a592090648e557Ben Murdochstatic bool ReadDeltaCRL(base::StringPiece* data,
247116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                         const std::vector<std::string>& old_serials,
248116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                         std::vector<std::string>* out_serials) {
249116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  std::vector<uint8> changes;
250116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!ReadChanges(data, &changes))
251116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return false;
252116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
253116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  size_t i = 0;
254116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  for (std::vector<uint8>::const_iterator k = changes.begin();
255116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch       k != changes.end(); ++k) {
256116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (*k == SYMBOL_SAME) {
257116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      if (i >= old_serials.size())
258116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        return false;
259116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      out_serials->push_back(old_serials[i]);
260116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      i++;
261116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    } else if (*k == SYMBOL_INSERT) {
262116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      uint8 serial_length;
263116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      if (data->size() < sizeof(uint8))
264116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        return false;
265116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      memcpy(&serial_length, data->data(), sizeof(uint8));
266116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      data->remove_prefix(sizeof(uint8));
267116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
268116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      if (data->size() < serial_length)
269116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        return false;
270116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      const std::string serial(data->data(), serial_length);
271116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      data->remove_prefix(serial_length);
272116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
273116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      out_serials->push_back(serial);
274116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    } else if (*k == SYMBOL_DELETE) {
275116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      if (i >= old_serials.size())
276116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        return false;
277116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      i++;
278116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    } else {
279116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      NOTREACHED();
280116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      return false;
281116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
282116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
283116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
284116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (i != old_serials.size())
285116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return false;
286116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return true;
287116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
288116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
289116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// static
290116680a4aac90f2aa7413d9095a592090648e557Ben Murdochbool CRLSetStorage::Parse(base::StringPiece data,
291116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                          scoped_refptr<CRLSet>* out_crl_set) {
292116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  TRACE_EVENT0("CRLSet", "Parse");
293116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Other parts of Chrome assume that we're little endian, so we don't lose
294116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // anything by doing this.
295116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#if defined(__BYTE_ORDER)
296116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Linux check
297116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  COMPILE_ASSERT(__BYTE_ORDER == __LITTLE_ENDIAN, assumes_little_endian);
298116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#elif defined(__BIG_ENDIAN__)
299116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Mac check
300116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  #error assumes little endian
301116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#endif
302116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
303116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_ptr<base::DictionaryValue> header_dict(ReadHeader(&data));
304116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!header_dict.get())
305116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return false;
306116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
307116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  std::string contents;
308116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!header_dict->GetString("ContentType", &contents))
309116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return false;
310116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (contents != "CRLSet")
311116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return false;
312116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
313116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  int version;
314116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!header_dict->GetInteger("Version", &version) ||
315116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      version != kCurrentFileVersion) {
316116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return false;
317116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
318116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
319116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  int sequence;
320116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!header_dict->GetInteger("Sequence", &sequence))
321116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return false;
322116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
323116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  double not_after;
324116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!header_dict->GetDouble("NotAfter", &not_after)) {
325116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // NotAfter is optional for now.
326116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    not_after = 0;
327116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
328116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (not_after < 0)
329116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return false;
330116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
331116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_refptr<CRLSet> crl_set(new CRLSet());
332116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  crl_set->sequence_ = static_cast<uint32>(sequence);
333116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  crl_set->not_after_ = static_cast<uint64>(not_after);
334116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  crl_set->crls_.reserve(64);  // Value observed experimentally.
335116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
336116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  for (size_t crl_index = 0; !data.empty(); crl_index++) {
337116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // Speculatively push back a pair and pass it to ReadCRL() to avoid
338116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // unnecessary copies.
339116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    crl_set->crls_.push_back(
340116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        std::make_pair(std::string(), std::vector<std::string>()));
341116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    std::pair<std::string, std::vector<std::string> >* const back_pair =
342116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        &crl_set->crls_.back();
343116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
344116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (!ReadCRL(&data, &back_pair->first, &back_pair->second)) {
345116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      // Undo the speculative push_back() performed above.
346116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      crl_set->crls_.pop_back();
347116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      return false;
348116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
349116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
350116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    crl_set->crls_index_by_issuer_[back_pair->first] = crl_index;
351116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
352116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
3531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!CopyBlockedSPKIsFromHeader(crl_set.get(), header_dict.get()))
354116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return false;
355116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
356116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  *out_crl_set = crl_set;
357116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return true;
358116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
359116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
360116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// static
361116680a4aac90f2aa7413d9095a592090648e557Ben Murdochbool CRLSetStorage::ApplyDelta(const CRLSet* in_crl_set,
362116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                               const base::StringPiece& delta_bytes,
363116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                               scoped_refptr<CRLSet>* out_crl_set) {
364116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  base::StringPiece data(delta_bytes);
365116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_ptr<base::DictionaryValue> header_dict(ReadHeader(&data));
366116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!header_dict.get())
367116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return false;
368116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
369116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  std::string contents;
370116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!header_dict->GetString("ContentType", &contents))
371116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return false;
372116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (contents != "CRLSetDelta")
373116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return false;
374116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
375116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  int version;
376116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!header_dict->GetInteger("Version", &version) ||
377116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      version != kCurrentFileVersion) {
378116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return false;
379116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
380116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
381116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  int sequence, delta_from;
382116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!header_dict->GetInteger("Sequence", &sequence) ||
383116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      !header_dict->GetInteger("DeltaFrom", &delta_from) ||
384116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      delta_from < 0 ||
385116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      static_cast<uint32>(delta_from) != in_crl_set->sequence_) {
386116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return false;
387116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
388116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
389116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  double not_after;
390116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!header_dict->GetDouble("NotAfter", &not_after)) {
391116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // NotAfter is optional for now.
392116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    not_after = 0;
393116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
394116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (not_after < 0)
395116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return false;
396116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
397116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_refptr<CRLSet> crl_set(new CRLSet);
398116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  crl_set->sequence_ = static_cast<uint32>(sequence);
399116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  crl_set->not_after_ = static_cast<uint64>(not_after);
400116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
4011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!CopyBlockedSPKIsFromHeader(crl_set.get(), header_dict.get()))
402116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return false;
403116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
404116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  std::vector<uint8> crl_changes;
405116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
406116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!ReadChanges(&data, &crl_changes))
407116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return false;
408116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
409116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  size_t i = 0, j = 0;
410116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  for (std::vector<uint8>::const_iterator k = crl_changes.begin();
411116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch       k != crl_changes.end(); ++k) {
412116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (*k == SYMBOL_SAME) {
413116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      if (i >= in_crl_set->crls_.size())
414116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        return false;
415116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      crl_set->crls_.push_back(in_crl_set->crls_[i]);
416116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      crl_set->crls_index_by_issuer_[in_crl_set->crls_[i].first] = j;
417116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      i++;
418116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      j++;
419116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    } else if (*k == SYMBOL_INSERT) {
420116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      std::string parent_spki_hash;
421116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      std::vector<std::string> serials;
422116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      if (!ReadCRL(&data, &parent_spki_hash, &serials))
423116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        return false;
424116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      crl_set->crls_.push_back(std::make_pair(parent_spki_hash, serials));
425116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      crl_set->crls_index_by_issuer_[parent_spki_hash] = j;
426116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      j++;
427116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    } else if (*k == SYMBOL_DELETE) {
428116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      if (i >= in_crl_set->crls_.size())
429116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        return false;
430116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      i++;
431116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    } else if (*k == SYMBOL_CHANGED) {
432116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      if (i >= in_crl_set->crls_.size())
433116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        return false;
434116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      std::vector<std::string> serials;
435116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      if (!ReadDeltaCRL(&data, in_crl_set->crls_[i].second, &serials))
436116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        return false;
437116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      crl_set->crls_.push_back(
438116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          std::make_pair(in_crl_set->crls_[i].first, serials));
439116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      crl_set->crls_index_by_issuer_[in_crl_set->crls_[i].first] = j;
440116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      i++;
441116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      j++;
442116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    } else {
443116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      NOTREACHED();
444116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      return false;
445116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
446116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
447116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
448116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!data.empty())
449116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return false;
450116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (i != in_crl_set->crls_.size())
451116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return false;
452116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
453116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  *out_crl_set = crl_set;
454116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return true;
455116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
456116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
457116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// static
458116680a4aac90f2aa7413d9095a592090648e557Ben Murdochbool CRLSetStorage::GetIsDeltaUpdate(const base::StringPiece& bytes,
459116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                     bool* is_delta) {
460116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  base::StringPiece data(bytes);
461116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_ptr<base::DictionaryValue> header_dict(ReadHeader(&data));
462116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!header_dict.get())
463116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return false;
464116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
465116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  std::string contents;
466116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!header_dict->GetString("ContentType", &contents))
467116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return false;
468116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
469116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (contents == "CRLSet") {
470116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    *is_delta = false;
471116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  } else if (contents == "CRLSetDelta") {
472116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    *is_delta = true;
473116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  } else {
474116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return false;
475116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
476116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
477116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return true;
478116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
479116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
480116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// static
481116680a4aac90f2aa7413d9095a592090648e557Ben Murdochstd::string CRLSetStorage::Serialize(const CRLSet* crl_set) {
482116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  std::string header = base::StringPrintf(
483116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      "{"
484116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      "\"Version\":0,"
485116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      "\"ContentType\":\"CRLSet\","
486116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      "\"Sequence\":%u,"
487116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      "\"DeltaFrom\":0,"
488116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      "\"NumParents\":%u,"
489116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      "\"BlockedSPKIs\":[",
490116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      static_cast<unsigned>(crl_set->sequence_),
491116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      static_cast<unsigned>(crl_set->crls_.size()));
492116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
493116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  for (std::vector<std::string>::const_iterator i =
494116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch           crl_set->blocked_spkis_.begin();
495116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch       i != crl_set->blocked_spkis_.end(); ++i) {
496116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    std::string spki_hash_base64;
497116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    base::Base64Encode(*i, &spki_hash_base64);
498116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
499116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (i != crl_set->blocked_spkis_.begin())
500116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      header += ",";
501116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    header += "\"" + spki_hash_base64 + "\"";
502116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
503116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  header += "]";
504116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (crl_set->not_after_ != 0)
505116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    header += base::StringPrintf(",\"NotAfter\":%" PRIu64, crl_set->not_after_);
506116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  header += "}";
507116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
508116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  size_t len = 2 /* header len */ + header.size();
509116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
510116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  for (CRLSet::CRLList::const_iterator i = crl_set->crls_.begin();
511116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch       i != crl_set->crls_.end(); ++i) {
512116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    len += i->first.size() + 4 /* num serials */;
513116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    for (std::vector<std::string>::const_iterator j = i->second.begin();
514116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch         j != i->second.end(); ++j) {
515116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      len += 1 /* serial length */ + j->size();
516116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
517116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
518116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
519116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  std::string ret;
520116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  char* out = WriteInto(&ret, len + 1 /* to include final NUL */);
521116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  size_t off = 0;
522116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  out[off++] = header.size();
523116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  out[off++] = header.size() >> 8;
524116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  memcpy(out + off, header.data(), header.size());
525116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  off += header.size();
526116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
527116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  for (CRLSet::CRLList::const_iterator i = crl_set->crls_.begin();
528116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch       i != crl_set->crls_.end(); ++i) {
529116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    memcpy(out + off, i->first.data(), i->first.size());
530116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    off += i->first.size();
531116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const uint32 num_serials = i->second.size();
532116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    memcpy(out + off, &num_serials, sizeof(num_serials));
533116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    off += sizeof(num_serials);
534116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
535116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    for (std::vector<std::string>::const_iterator j = i->second.begin();
536116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch         j != i->second.end(); ++j) {
537116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      out[off++] = j->size();
538116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      memcpy(out + off, j->data(), j->size());
539116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      off += j->size();
540116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
541116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
542116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
543116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  CHECK_EQ(off, len);
544116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return ret;
545116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
546116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
547116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}  // namespace net
548