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