| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "base/base64.h" | |
| 6 #include "base/format_macros.h" | |
| 7 #include "base/json/json_reader.h" | |
| 8 #include "base/logging.h" | |
| 9 #include "base/stl_util.h" | |
| 10 #include "base/string_util.h" | |
| 11 #include "base/stringprintf.h" | |
| 12 #include "base/time.h" | |
| 13 #include "base/values.h" | |
| 14 #include "crypto/sha2.h" | |
| 15 #include "net/base/crl_set.h" | |
| 16 #include "third_party/zlib/zlib.h" | |
| 17 | |
| 18 namespace net { | |
| 19 | |
| 20 // Decompress zlib decompressed |in| into |out|. |out_len| is the number of | |
| 21 // bytes at |out| and must be exactly equal to the size of the decompressed | |
| 22 // data. | |
| 23 static bool DecompressZlib(uint8* out, int out_len, base::StringPiece in) { | |
| 24 z_stream z; | |
| 25 memset(&z, 0, sizeof(z)); | |
| 26 | |
| 27 z.next_in = reinterpret_cast<Bytef*>(const_cast<char*>(in.data())); | |
| 28 z.avail_in = in.size(); | |
| 29 z.next_out = reinterpret_cast<Bytef*>(out); | |
| 30 z.avail_out = out_len; | |
| 31 | |
| 32 if (inflateInit(&z) != Z_OK) | |
| 33 return false; | |
| 34 bool ret = false; | |
| 35 int r = inflate(&z, Z_FINISH); | |
| 36 if (r != Z_STREAM_END) | |
| 37 goto err; | |
| 38 if (z.avail_in || z.avail_out) | |
| 39 goto err; | |
| 40 ret = true; | |
| 41 | |
| 42 err: | |
| 43 inflateEnd(&z); | |
| 44 return ret; | |
| 45 } | |
| 46 | |
| 47 CRLSet::CRLSet() | |
| 48 : sequence_(0), | |
| 49 not_after_(0) { | |
| 50 } | |
| 51 | |
| 52 CRLSet::~CRLSet() { | |
| 53 } | |
| 54 | |
| 55 // CRLSet format: | |
| 56 // | |
| 57 // uint16le header_len | |
| 58 // byte[header_len] header_bytes | |
| 59 // repeated { | |
| 60 // byte[32] parent_spki_sha256 | |
| 61 // uint32le num_serials | |
| 62 // [num_serials] { | |
| 63 // uint8 serial_length; | |
| 64 // byte[serial_length] serial; | |
| 65 // } | |
| 66 // | |
| 67 // header_bytes consists of a JSON dictionary with the following keys: | |
| 68 // Version (int): currently 0 | |
| 69 // ContentType (string): "CRLSet" or "CRLSetDelta" (magic value) | |
| 70 // DeltaFrom (int32): if this is a delta update (see below), then this | |
| 71 // contains the sequence number of the base CRLSet. | |
| 72 // Sequence (int32): the monotonic sequence number of this CRL set. | |
| 73 // | |
| 74 // A delta CRLSet is similar to a CRLSet: | |
| 75 // | |
| 76 // struct CompressedChanges { | |
| 77 // uint32le uncompressed_size | |
| 78 // uint32le compressed_size | |
| 79 // byte[compressed_size] zlib_data | |
| 80 // } | |
| 81 // | |
| 82 // uint16le header_len | |
| 83 // byte[header_len] header_bytes | |
| 84 // CompressedChanges crl_changes | |
| 85 // [crl_changes.uncompressed_size] { | |
| 86 // switch (crl_changes[i]) { | |
| 87 // case 0: | |
| 88 // // CRL is the same | |
| 89 // case 1: | |
| 90 // // New CRL inserted | |
| 91 // // See CRL structure from the non-delta format | |
| 92 // case 2: | |
| 93 // // CRL deleted | |
| 94 // case 3: | |
| 95 // // CRL changed | |
| 96 // CompressedChanges serials_changes | |
| 97 // [serials_changes.uncompressed_size] { | |
| 98 // switch (serials_changes[i]) { | |
| 99 // case 0: | |
| 100 // // the serial is the same | |
| 101 // case 1: | |
| 102 // // serial inserted | |
| 103 // uint8 serial_length | |
| 104 // byte[serial_length] serial | |
| 105 // case 2: | |
| 106 // // serial deleted | |
| 107 // } | |
| 108 // } | |
| 109 // } | |
| 110 // } | |
| 111 // | |
| 112 // A delta CRLSet applies to a specific CRL set as given in the | |
| 113 // header's "DeltaFrom" value. The delta describes the changes to each CRL | |
| 114 // in turn with a zlib compressed array of options: either the CRL is the same, | |
| 115 // a new CRL is inserted, the CRL is deleted or the CRL is updated. In the case | |
| 116 // of an update, the serials in the CRL are considered in the same fashion | |
| 117 // except there is no delta update of a serial number: they are either | |
| 118 // inserted, deleted or left the same. | |
| 119 | |
| 120 // ReadHeader reads the header (including length prefix) from |data| and | |
| 121 // updates |data| to remove the header on return. Caller takes ownership of the | |
| 122 // returned pointer. | |
| 123 static base::DictionaryValue* ReadHeader(base::StringPiece* data) { | |
| 124 if (data->size() < 2) | |
| 125 return NULL; | |
| 126 uint16 header_len; | |
| 127 memcpy(&header_len, data->data(), 2); // assumes little-endian. | |
| 128 data->remove_prefix(2); | |
| 129 | |
| 130 if (data->size() < header_len) | |
| 131 return NULL; | |
| 132 | |
| 133 const base::StringPiece header_bytes(data->data(), header_len); | |
| 134 data->remove_prefix(header_len); | |
| 135 | |
| 136 scoped_ptr<Value> header(base::JSONReader::Read( | |
| 137 header_bytes, base::JSON_ALLOW_TRAILING_COMMAS)); | |
| 138 if (header.get() == NULL) | |
| 139 return NULL; | |
| 140 | |
| 141 if (!header->IsType(Value::TYPE_DICTIONARY)) | |
| 142 return NULL; | |
| 143 return reinterpret_cast<base::DictionaryValue*>(header.release()); | |
| 144 } | |
| 145 | |
| 146 // kCurrentFileVersion is the version of the CRLSet file format that we | |
| 147 // currently implement. | |
| 148 static const int kCurrentFileVersion = 0; | |
| 149 | |
| 150 static bool ReadCRL(base::StringPiece* data, std::string* out_parent_spki_hash, | |
| 151 std::vector<std::string>* out_serials) { | |
| 152 if (data->size() < crypto::kSHA256Length) | |
| 153 return false; | |
| 154 *out_parent_spki_hash = std::string(data->data(), crypto::kSHA256Length); | |
| 155 data->remove_prefix(crypto::kSHA256Length); | |
| 156 | |
| 157 if (data->size() < sizeof(uint32)) | |
| 158 return false; | |
| 159 uint32 num_serials; | |
| 160 memcpy(&num_serials, data->data(), sizeof(uint32)); // assumes little endian | |
| 161 data->remove_prefix(sizeof(uint32)); | |
| 162 | |
| 163 for (uint32 i = 0; i < num_serials; ++i) { | |
| 164 uint8 serial_length; | |
| 165 if (data->size() < sizeof(uint8)) | |
| 166 return false; | |
| 167 memcpy(&serial_length, data->data(), sizeof(uint8)); | |
| 168 data->remove_prefix(sizeof(uint8)); | |
| 169 | |
| 170 if (data->size() < serial_length) | |
| 171 return false; | |
| 172 std::string serial(data->data(), serial_length); | |
| 173 data->remove_prefix(serial_length); | |
| 174 out_serials->push_back(serial); | |
| 175 } | |
| 176 | |
| 177 return true; | |
| 178 } | |
| 179 | |
| 180 bool CRLSet::CopyBlockedSPKIsFromHeader(base::DictionaryValue* header_dict) { | |
| 181 ListValue* blocked_spkis_list = NULL; | |
| 182 if (!header_dict->GetList("BlockedSPKIs", &blocked_spkis_list)) { | |
| 183 // BlockedSPKIs is optional, so it's fine if we don't find it. | |
| 184 return true; | |
| 185 } | |
| 186 | |
| 187 blocked_spkis_.clear(); | |
| 188 | |
| 189 for (size_t i = 0; i < blocked_spkis_list->GetSize(); ++i) { | |
| 190 std::string spki_sha256_base64, spki_sha256; | |
| 191 if (!blocked_spkis_list->GetString(i, &spki_sha256_base64)) | |
| 192 return false; | |
| 193 if (!base::Base64Decode(spki_sha256_base64, &spki_sha256)) | |
| 194 return false; | |
| 195 blocked_spkis_.push_back(spki_sha256); | |
| 196 } | |
| 197 | |
| 198 return true; | |
| 199 } | |
| 200 | |
| 201 // static | |
| 202 bool CRLSet::Parse(base::StringPiece data, scoped_refptr<CRLSet>* out_crl_set) { | |
| 203 // Other parts of Chrome assume that we're little endian, so we don't lose | |
| 204 // anything by doing this. | |
| 205 #if defined(__BYTE_ORDER) | |
| 206 // Linux check | |
| 207 COMPILE_ASSERT(__BYTE_ORDER == __LITTLE_ENDIAN, assumes_little_endian); | |
| 208 #elif defined(__BIG_ENDIAN__) | |
| 209 // Mac check | |
| 210 #error assumes little endian | |
| 211 #endif | |
| 212 | |
| 213 scoped_ptr<base::DictionaryValue> header_dict(ReadHeader(&data)); | |
| 214 if (!header_dict.get()) | |
| 215 return false; | |
| 216 | |
| 217 std::string contents; | |
| 218 if (!header_dict->GetString("ContentType", &contents)) | |
| 219 return false; | |
| 220 if (contents != "CRLSet") | |
| 221 return false; | |
| 222 | |
| 223 int version; | |
| 224 if (!header_dict->GetInteger("Version", &version) || | |
| 225 version != kCurrentFileVersion) { | |
| 226 return false; | |
| 227 } | |
| 228 | |
| 229 int sequence; | |
| 230 if (!header_dict->GetInteger("Sequence", &sequence)) | |
| 231 return false; | |
| 232 | |
| 233 double not_after; | |
| 234 if (!header_dict->GetDouble("NotAfter", ¬_after)) { | |
| 235 // NotAfter is optional for now. | |
| 236 not_after = 0; | |
| 237 } | |
| 238 if (not_after < 0) | |
| 239 return false; | |
| 240 | |
| 241 scoped_refptr<CRLSet> crl_set(new CRLSet); | |
| 242 crl_set->sequence_ = static_cast<uint32>(sequence); | |
| 243 crl_set->not_after_ = static_cast<uint64>(not_after); | |
| 244 | |
| 245 for (size_t crl_index = 0; !data.empty(); crl_index++) { | |
| 246 std::string parent_spki_sha256; | |
| 247 std::vector<std::string> serials; | |
| 248 if (!ReadCRL(&data, &parent_spki_sha256, &serials)) | |
| 249 return false; | |
| 250 | |
| 251 crl_set->crls_.push_back(std::make_pair(parent_spki_sha256, serials)); | |
| 252 crl_set->crls_index_by_issuer_[parent_spki_sha256] = crl_index; | |
| 253 } | |
| 254 | |
| 255 if (!crl_set->CopyBlockedSPKIsFromHeader(header_dict.get())) | |
| 256 return false; | |
| 257 | |
| 258 *out_crl_set = crl_set; | |
| 259 return true; | |
| 260 } | |
| 261 | |
| 262 // kMaxUncompressedChangesLength is the largest changes array that we'll | |
| 263 // accept. This bounds the number of CRLs in the CRLSet as well as the number | |
| 264 // of serial numbers in a given CRL. | |
| 265 static const unsigned kMaxUncompressedChangesLength = 1024 * 1024; | |
| 266 | |
| 267 static bool ReadChanges(base::StringPiece* data, | |
| 268 std::vector<uint8>* out_changes) { | |
| 269 uint32 uncompressed_size, compressed_size; | |
| 270 if (data->size() < 2 * sizeof(uint32)) | |
| 271 return false; | |
| 272 // assumes little endian. | |
| 273 memcpy(&uncompressed_size, data->data(), sizeof(uint32)); | |
| 274 data->remove_prefix(4); | |
| 275 memcpy(&compressed_size, data->data(), sizeof(uint32)); | |
| 276 data->remove_prefix(4); | |
| 277 | |
| 278 if (uncompressed_size > kMaxUncompressedChangesLength) | |
| 279 return false; | |
| 280 if (data->size() < compressed_size) | |
| 281 return false; | |
| 282 | |
| 283 out_changes->clear(); | |
| 284 if (uncompressed_size == 0) | |
| 285 return true; | |
| 286 | |
| 287 out_changes->resize(uncompressed_size); | |
| 288 base::StringPiece compressed(data->data(), compressed_size); | |
| 289 data->remove_prefix(compressed_size); | |
| 290 return DecompressZlib(&(*out_changes)[0], uncompressed_size, compressed); | |
| 291 } | |
| 292 | |
| 293 // These are the range coder symbols used in delta updates. | |
| 294 enum { | |
| 295 SYMBOL_SAME = 0, | |
| 296 SYMBOL_INSERT = 1, | |
| 297 SYMBOL_DELETE = 2, | |
| 298 SYMBOL_CHANGED = 3, | |
| 299 }; | |
| 300 | |
| 301 bool ReadDeltaCRL(base::StringPiece* data, | |
| 302 const std::vector<std::string>& old_serials, | |
| 303 std::vector<std::string>* out_serials) { | |
| 304 std::vector<uint8> changes; | |
| 305 if (!ReadChanges(data, &changes)) | |
| 306 return false; | |
| 307 | |
| 308 size_t i = 0; | |
| 309 for (std::vector<uint8>::const_iterator k = changes.begin(); | |
| 310 k != changes.end(); ++k) { | |
| 311 if (*k == SYMBOL_SAME) { | |
| 312 if (i >= old_serials.size()) | |
| 313 return false; | |
| 314 out_serials->push_back(old_serials[i]); | |
| 315 i++; | |
| 316 } else if (*k == SYMBOL_INSERT) { | |
| 317 uint8 serial_length; | |
| 318 if (data->size() < sizeof(uint8)) | |
| 319 return false; | |
| 320 memcpy(&serial_length, data->data(), sizeof(uint8)); | |
| 321 data->remove_prefix(sizeof(uint8)); | |
| 322 | |
| 323 if (data->size() < serial_length) | |
| 324 return false; | |
| 325 const std::string serial(data->data(), serial_length); | |
| 326 data->remove_prefix(serial_length); | |
| 327 | |
| 328 out_serials->push_back(serial); | |
| 329 } else if (*k == SYMBOL_DELETE) { | |
| 330 if (i >= old_serials.size()) | |
| 331 return false; | |
| 332 i++; | |
| 333 } else { | |
| 334 NOTREACHED(); | |
| 335 return false; | |
| 336 } | |
| 337 } | |
| 338 | |
| 339 if (i != old_serials.size()) | |
| 340 return false; | |
| 341 return true; | |
| 342 } | |
| 343 | |
| 344 bool CRLSet::ApplyDelta(const base::StringPiece& in_data, | |
| 345 scoped_refptr<CRLSet>* out_crl_set) { | |
| 346 base::StringPiece data(in_data); | |
| 347 scoped_ptr<base::DictionaryValue> header_dict(ReadHeader(&data)); | |
| 348 if (!header_dict.get()) | |
| 349 return false; | |
| 350 | |
| 351 std::string contents; | |
| 352 if (!header_dict->GetString("ContentType", &contents)) | |
| 353 return false; | |
| 354 if (contents != "CRLSetDelta") | |
| 355 return false; | |
| 356 | |
| 357 int version; | |
| 358 if (!header_dict->GetInteger("Version", &version) || | |
| 359 version != kCurrentFileVersion) { | |
| 360 return false; | |
| 361 } | |
| 362 | |
| 363 int sequence, delta_from; | |
| 364 if (!header_dict->GetInteger("Sequence", &sequence) || | |
| 365 !header_dict->GetInteger("DeltaFrom", &delta_from) || | |
| 366 delta_from < 0 || | |
| 367 static_cast<uint32>(delta_from) != sequence_) { | |
| 368 return false; | |
| 369 } | |
| 370 | |
| 371 double not_after; | |
| 372 if (!header_dict->GetDouble("NotAfter", ¬_after)) { | |
| 373 // NotAfter is optional for now. | |
| 374 not_after = 0; | |
| 375 } | |
| 376 if (not_after < 0) | |
| 377 return false; | |
| 378 | |
| 379 scoped_refptr<CRLSet> crl_set(new CRLSet); | |
| 380 crl_set->sequence_ = static_cast<uint32>(sequence); | |
| 381 crl_set->not_after_ = static_cast<uint64>(not_after); | |
| 382 | |
| 383 if (!crl_set->CopyBlockedSPKIsFromHeader(header_dict.get())) | |
| 384 return false; | |
| 385 | |
| 386 std::vector<uint8> crl_changes; | |
| 387 | |
| 388 if (!ReadChanges(&data, &crl_changes)) | |
| 389 return false; | |
| 390 | |
| 391 size_t i = 0, j = 0; | |
| 392 for (std::vector<uint8>::const_iterator k = crl_changes.begin(); | |
| 393 k != crl_changes.end(); ++k) { | |
| 394 if (*k == SYMBOL_SAME) { | |
| 395 if (i >= crls_.size()) | |
| 396 return false; | |
| 397 crl_set->crls_.push_back(crls_[i]); | |
| 398 crl_set->crls_index_by_issuer_[crls_[i].first] = j; | |
| 399 i++; | |
| 400 j++; | |
| 401 } else if (*k == SYMBOL_INSERT) { | |
| 402 std::string parent_spki_hash; | |
| 403 std::vector<std::string> serials; | |
| 404 if (!ReadCRL(&data, &parent_spki_hash, &serials)) | |
| 405 return false; | |
| 406 crl_set->crls_.push_back(std::make_pair(parent_spki_hash, serials)); | |
| 407 crl_set->crls_index_by_issuer_[parent_spki_hash] = j; | |
| 408 j++; | |
| 409 } else if (*k == SYMBOL_DELETE) { | |
| 410 if (i >= crls_.size()) | |
| 411 return false; | |
| 412 i++; | |
| 413 } else if (*k == SYMBOL_CHANGED) { | |
| 414 if (i >= crls_.size()) | |
| 415 return false; | |
| 416 std::vector<std::string> serials; | |
| 417 if (!ReadDeltaCRL(&data, crls_[i].second, &serials)) | |
| 418 return false; | |
| 419 crl_set->crls_.push_back(std::make_pair(crls_[i].first, serials)); | |
| 420 crl_set->crls_index_by_issuer_[crls_[i].first] = j; | |
| 421 i++; | |
| 422 j++; | |
| 423 } else { | |
| 424 NOTREACHED(); | |
| 425 return false; | |
| 426 } | |
| 427 } | |
| 428 | |
| 429 if (!data.empty()) | |
| 430 return false; | |
| 431 if (i != crls_.size()) | |
| 432 return false; | |
| 433 | |
| 434 *out_crl_set = crl_set; | |
| 435 return true; | |
| 436 } | |
| 437 | |
| 438 // static | |
| 439 bool CRLSet::GetIsDeltaUpdate(const base::StringPiece& in_data, | |
| 440 bool* is_delta) { | |
| 441 base::StringPiece data(in_data); | |
| 442 scoped_ptr<base::DictionaryValue> header_dict(ReadHeader(&data)); | |
| 443 if (!header_dict.get()) | |
| 444 return false; | |
| 445 | |
| 446 std::string contents; | |
| 447 if (!header_dict->GetString("ContentType", &contents)) | |
| 448 return false; | |
| 449 | |
| 450 if (contents == "CRLSet") { | |
| 451 *is_delta = false; | |
| 452 } else if (contents == "CRLSetDelta") { | |
| 453 *is_delta = true; | |
| 454 } else { | |
| 455 return false; | |
| 456 } | |
| 457 | |
| 458 return true; | |
| 459 } | |
| 460 | |
| 461 std::string CRLSet::Serialize() const { | |
| 462 std::string header = base::StringPrintf( | |
| 463 "{" | |
| 464 "\"Version\":0," | |
| 465 "\"ContentType\":\"CRLSet\"," | |
| 466 "\"Sequence\":%u," | |
| 467 "\"DeltaFrom\":0," | |
| 468 "\"NumParents\":%u," | |
| 469 "\"BlockedSPKIs\":[", | |
| 470 static_cast<unsigned>(sequence_), | |
| 471 static_cast<unsigned>(crls_.size())); | |
| 472 | |
| 473 for (std::vector<std::string>::const_iterator i = blocked_spkis_.begin(); | |
| 474 i != blocked_spkis_.end(); ++i) { | |
| 475 std::string spki_hash_base64; | |
| 476 base::Base64Encode(*i, &spki_hash_base64); | |
| 477 | |
| 478 if (i != blocked_spkis_.begin()) | |
| 479 header += ","; | |
| 480 header += "\"" + spki_hash_base64 + "\""; | |
| 481 } | |
| 482 header += "]"; | |
| 483 if (not_after_ != 0) | |
| 484 header += base::StringPrintf(",\"NotAfter\":%" PRIu64, not_after_); | |
| 485 header += "}"; | |
| 486 | |
| 487 size_t len = 2 /* header len */ + header.size(); | |
| 488 | |
| 489 for (CRLList::const_iterator i = crls_.begin(); i != crls_.end(); ++i) { | |
| 490 len += i->first.size() + 4 /* num serials */; | |
| 491 for (std::vector<std::string>::const_iterator j = i->second.begin(); | |
| 492 j != i->second.end(); ++j) { | |
| 493 len += 1 /* serial length */ + j->size(); | |
| 494 } | |
| 495 } | |
| 496 | |
| 497 std::string ret; | |
| 498 char* out = WriteInto(&ret, len + 1 /* to include final NUL */); | |
| 499 size_t off = 0; | |
| 500 out[off++] = header.size(); | |
| 501 out[off++] = header.size() >> 8; | |
| 502 memcpy(out + off, header.data(), header.size()); | |
| 503 off += header.size(); | |
| 504 | |
| 505 for (CRLList::const_iterator i = crls_.begin(); i != crls_.end(); ++i) { | |
| 506 memcpy(out + off, i->first.data(), i->first.size()); | |
| 507 off += i->first.size(); | |
| 508 const uint32 num_serials = i->second.size(); | |
| 509 memcpy(out + off, &num_serials, sizeof(num_serials)); | |
| 510 off += sizeof(num_serials); | |
| 511 | |
| 512 for (std::vector<std::string>::const_iterator j = i->second.begin(); | |
| 513 j != i->second.end(); ++j) { | |
| 514 out[off++] = j->size(); | |
| 515 memcpy(out + off, j->data(), j->size()); | |
| 516 off += j->size(); | |
| 517 } | |
| 518 } | |
| 519 | |
| 520 CHECK_EQ(off, len); | |
| 521 return ret; | |
| 522 } | |
| 523 | |
| 524 CRLSet::Result CRLSet::CheckSPKI(const base::StringPiece& spki_hash) const { | |
| 525 for (std::vector<std::string>::const_iterator i = blocked_spkis_.begin(); | |
| 526 i != blocked_spkis_.end(); ++i) { | |
| 527 if (spki_hash.size() == i->size() && | |
| 528 memcmp(spki_hash.data(), i->data(), i->size()) == 0) { | |
| 529 return REVOKED; | |
| 530 } | |
| 531 } | |
| 532 | |
| 533 return GOOD; | |
| 534 } | |
| 535 | |
| 536 CRLSet::Result CRLSet::CheckSerial( | |
| 537 const base::StringPiece& serial_number, | |
| 538 const base::StringPiece& issuer_spki_hash) const { | |
| 539 base::StringPiece serial(serial_number); | |
| 540 | |
| 541 if (!serial.empty() && (serial[0] & 0x80) != 0) { | |
| 542 // This serial number is negative but the process which generates CRL sets | |
| 543 // will reject any certificates with negative serial numbers as invalid. | |
| 544 return UNKNOWN; | |
| 545 } | |
| 546 | |
| 547 // Remove any leading zero bytes. | |
| 548 while (serial.size() > 1 && serial[0] == 0x00) | |
| 549 serial.remove_prefix(1); | |
| 550 | |
| 551 std::map<std::string, size_t>::const_iterator i = | |
| 552 crls_index_by_issuer_.find(issuer_spki_hash.as_string()); | |
| 553 if (i == crls_index_by_issuer_.end()) | |
| 554 return UNKNOWN; | |
| 555 const std::vector<std::string>& serials = crls_[i->second].second; | |
| 556 | |
| 557 for (std::vector<std::string>::const_iterator i = serials.begin(); | |
| 558 i != serials.end(); ++i) { | |
| 559 if (base::StringPiece(*i) == serial) | |
| 560 return REVOKED; | |
| 561 } | |
| 562 | |
| 563 return GOOD; | |
| 564 } | |
| 565 | |
| 566 bool CRLSet::IsExpired() const { | |
| 567 if (not_after_ == 0) | |
| 568 return false; | |
| 569 | |
| 570 uint64 now = base::Time::Now().ToTimeT(); | |
| 571 return now > not_after_; | |
| 572 } | |
| 573 | |
| 574 uint32 CRLSet::sequence() const { | |
| 575 return sequence_; | |
| 576 } | |
| 577 | |
| 578 const CRLSet::CRLList& CRLSet::crls() const { | |
| 579 return crls_; | |
| 580 } | |
| 581 | |
| 582 // static | |
| 583 CRLSet* CRLSet::EmptyCRLSetForTesting() { | |
| 584 return new CRLSet; | |
| 585 } | |
| 586 | |
| 587 CRLSet* CRLSet::ExpiredCRLSetForTesting() { | |
| 588 CRLSet* crl_set = new CRLSet; | |
| 589 crl_set->not_after_ = 1; | |
| 590 return crl_set; | |
| 591 } | |
| 592 | |
| 593 } // namespace net | |
| OLD | NEW |