| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/base64.h" | 5 #include "base/base64.h" |
| 6 #include "base/format_macros.h" | 6 #include "base/format_macros.h" |
| 7 #include "base/json/json_reader.h" | 7 #include "base/json/json_reader.h" |
| 8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "base/stl_util.h" | 9 #include "base/stl_util.h" |
| 10 #include "base/strings/string_util.h" | 10 #include "base/strings/string_util.h" |
| (...skipping 21 matching lines...) Expand all Loading... |
| 32 if (inflateInit(&z) != Z_OK) | 32 if (inflateInit(&z) != Z_OK) |
| 33 return false; | 33 return false; |
| 34 bool ret = false; | 34 bool ret = false; |
| 35 int r = inflate(&z, Z_FINISH); | 35 int r = inflate(&z, Z_FINISH); |
| 36 if (r != Z_STREAM_END) | 36 if (r != Z_STREAM_END) |
| 37 goto err; | 37 goto err; |
| 38 if (z.avail_in || z.avail_out) | 38 if (z.avail_in || z.avail_out) |
| 39 goto err; | 39 goto err; |
| 40 ret = true; | 40 ret = true; |
| 41 | 41 |
| 42 err: | 42 err: |
| 43 inflateEnd(&z); | 43 inflateEnd(&z); |
| 44 return ret; | 44 return ret; |
| 45 } | 45 } |
| 46 | 46 |
| 47 CRLSet::CRLSet() | 47 CRLSet::CRLSet() : sequence_(0), not_after_(0) { |
| 48 : sequence_(0), | |
| 49 not_after_(0) { | |
| 50 } | 48 } |
| 51 | 49 |
| 52 CRLSet::~CRLSet() { | 50 CRLSet::~CRLSet() { |
| 53 } | 51 } |
| 54 | 52 |
| 55 // CRLSet format: | 53 // CRLSet format: |
| 56 // | 54 // |
| 57 // uint16le header_len | 55 // uint16le header_len |
| 58 // byte[header_len] header_bytes | 56 // byte[header_len] header_bytes |
| 59 // repeated { | 57 // repeated { |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 126 uint16 header_len; | 124 uint16 header_len; |
| 127 memcpy(&header_len, data->data(), 2); // assumes little-endian. | 125 memcpy(&header_len, data->data(), 2); // assumes little-endian. |
| 128 data->remove_prefix(2); | 126 data->remove_prefix(2); |
| 129 | 127 |
| 130 if (data->size() < header_len) | 128 if (data->size() < header_len) |
| 131 return NULL; | 129 return NULL; |
| 132 | 130 |
| 133 const base::StringPiece header_bytes(data->data(), header_len); | 131 const base::StringPiece header_bytes(data->data(), header_len); |
| 134 data->remove_prefix(header_len); | 132 data->remove_prefix(header_len); |
| 135 | 133 |
| 136 scoped_ptr<base::Value> header(base::JSONReader::Read( | 134 scoped_ptr<base::Value> header( |
| 137 header_bytes, base::JSON_ALLOW_TRAILING_COMMAS)); | 135 base::JSONReader::Read(header_bytes, base::JSON_ALLOW_TRAILING_COMMAS)); |
| 138 if (header.get() == NULL) | 136 if (header.get() == NULL) |
| 139 return NULL; | 137 return NULL; |
| 140 | 138 |
| 141 if (!header->IsType(base::Value::TYPE_DICTIONARY)) | 139 if (!header->IsType(base::Value::TYPE_DICTIONARY)) |
| 142 return NULL; | 140 return NULL; |
| 143 return reinterpret_cast<base::DictionaryValue*>(header.release()); | 141 return reinterpret_cast<base::DictionaryValue*>(header.release()); |
| 144 } | 142 } |
| 145 | 143 |
| 146 // kCurrentFileVersion is the version of the CRLSet file format that we | 144 // kCurrentFileVersion is the version of the CRLSet file format that we |
| 147 // currently implement. | 145 // currently implement. |
| 148 static const int kCurrentFileVersion = 0; | 146 static const int kCurrentFileVersion = 0; |
| 149 | 147 |
| 150 static bool ReadCRL(base::StringPiece* data, std::string* out_parent_spki_hash, | 148 static bool ReadCRL(base::StringPiece* data, |
| 149 std::string* out_parent_spki_hash, |
| 151 std::vector<std::string>* out_serials) { | 150 std::vector<std::string>* out_serials) { |
| 152 if (data->size() < crypto::kSHA256Length) | 151 if (data->size() < crypto::kSHA256Length) |
| 153 return false; | 152 return false; |
| 154 *out_parent_spki_hash = std::string(data->data(), crypto::kSHA256Length); | 153 *out_parent_spki_hash = std::string(data->data(), crypto::kSHA256Length); |
| 155 data->remove_prefix(crypto::kSHA256Length); | 154 data->remove_prefix(crypto::kSHA256Length); |
| 156 | 155 |
| 157 if (data->size() < sizeof(uint32)) | 156 if (data->size() < sizeof(uint32)) |
| 158 return false; | 157 return false; |
| 159 uint32 num_serials; | 158 uint32 num_serials; |
| 160 memcpy(&num_serials, data->data(), sizeof(uint32)); // assumes little endian | 159 memcpy(&num_serials, data->data(), sizeof(uint32)); // assumes little endian |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 193 if (!base::Base64Decode(spki_sha256_base64, &spki_sha256)) | 192 if (!base::Base64Decode(spki_sha256_base64, &spki_sha256)) |
| 194 return false; | 193 return false; |
| 195 blocked_spkis_.push_back(spki_sha256); | 194 blocked_spkis_.push_back(spki_sha256); |
| 196 } | 195 } |
| 197 | 196 |
| 198 return true; | 197 return true; |
| 199 } | 198 } |
| 200 | 199 |
| 201 // static | 200 // static |
| 202 bool CRLSet::Parse(base::StringPiece data, scoped_refptr<CRLSet>* out_crl_set) { | 201 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 | 202 // Other parts of Chrome assume that we're little endian, so we don't lose |
| 204 // anything by doing this. | 203 // anything by doing this. |
| 205 #if defined(__BYTE_ORDER) | 204 #if defined(__BYTE_ORDER) |
| 206 // Linux check | 205 // Linux check |
| 207 COMPILE_ASSERT(__BYTE_ORDER == __LITTLE_ENDIAN, assumes_little_endian); | 206 COMPILE_ASSERT(__BYTE_ORDER == __LITTLE_ENDIAN, assumes_little_endian); |
| 208 #elif defined(__BIG_ENDIAN__) | 207 #elif defined(__BIG_ENDIAN__) |
| 209 // Mac check | 208 // Mac check |
| 210 #error assumes little endian | 209 #error assumes little endian |
| 211 #endif | 210 #endif |
| 212 | 211 |
| 213 scoped_ptr<base::DictionaryValue> header_dict(ReadHeader(&data)); | 212 scoped_ptr<base::DictionaryValue> header_dict(ReadHeader(&data)); |
| 214 if (!header_dict.get()) | 213 if (!header_dict.get()) |
| 215 return false; | 214 return false; |
| 216 | 215 |
| 217 std::string contents; | 216 std::string contents; |
| 218 if (!header_dict->GetString("ContentType", &contents)) | 217 if (!header_dict->GetString("ContentType", &contents)) |
| 219 return false; | 218 return false; |
| 220 if (contents != "CRLSet") | 219 if (contents != "CRLSet") |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 300 | 299 |
| 301 bool ReadDeltaCRL(base::StringPiece* data, | 300 bool ReadDeltaCRL(base::StringPiece* data, |
| 302 const std::vector<std::string>& old_serials, | 301 const std::vector<std::string>& old_serials, |
| 303 std::vector<std::string>* out_serials) { | 302 std::vector<std::string>* out_serials) { |
| 304 std::vector<uint8> changes; | 303 std::vector<uint8> changes; |
| 305 if (!ReadChanges(data, &changes)) | 304 if (!ReadChanges(data, &changes)) |
| 306 return false; | 305 return false; |
| 307 | 306 |
| 308 size_t i = 0; | 307 size_t i = 0; |
| 309 for (std::vector<uint8>::const_iterator k = changes.begin(); | 308 for (std::vector<uint8>::const_iterator k = changes.begin(); |
| 310 k != changes.end(); ++k) { | 309 k != changes.end(); |
| 310 ++k) { |
| 311 if (*k == SYMBOL_SAME) { | 311 if (*k == SYMBOL_SAME) { |
| 312 if (i >= old_serials.size()) | 312 if (i >= old_serials.size()) |
| 313 return false; | 313 return false; |
| 314 out_serials->push_back(old_serials[i]); | 314 out_serials->push_back(old_serials[i]); |
| 315 i++; | 315 i++; |
| 316 } else if (*k == SYMBOL_INSERT) { | 316 } else if (*k == SYMBOL_INSERT) { |
| 317 uint8 serial_length; | 317 uint8 serial_length; |
| 318 if (data->size() < sizeof(uint8)) | 318 if (data->size() < sizeof(uint8)) |
| 319 return false; | 319 return false; |
| 320 memcpy(&serial_length, data->data(), sizeof(uint8)); | 320 memcpy(&serial_length, data->data(), sizeof(uint8)); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 355 return false; | 355 return false; |
| 356 | 356 |
| 357 int version; | 357 int version; |
| 358 if (!header_dict->GetInteger("Version", &version) || | 358 if (!header_dict->GetInteger("Version", &version) || |
| 359 version != kCurrentFileVersion) { | 359 version != kCurrentFileVersion) { |
| 360 return false; | 360 return false; |
| 361 } | 361 } |
| 362 | 362 |
| 363 int sequence, delta_from; | 363 int sequence, delta_from; |
| 364 if (!header_dict->GetInteger("Sequence", &sequence) || | 364 if (!header_dict->GetInteger("Sequence", &sequence) || |
| 365 !header_dict->GetInteger("DeltaFrom", &delta_from) || | 365 !header_dict->GetInteger("DeltaFrom", &delta_from) || delta_from < 0 || |
| 366 delta_from < 0 || | |
| 367 static_cast<uint32>(delta_from) != sequence_) { | 366 static_cast<uint32>(delta_from) != sequence_) { |
| 368 return false; | 367 return false; |
| 369 } | 368 } |
| 370 | 369 |
| 371 double not_after; | 370 double not_after; |
| 372 if (!header_dict->GetDouble("NotAfter", ¬_after)) { | 371 if (!header_dict->GetDouble("NotAfter", ¬_after)) { |
| 373 // NotAfter is optional for now. | 372 // NotAfter is optional for now. |
| 374 not_after = 0; | 373 not_after = 0; |
| 375 } | 374 } |
| 376 if (not_after < 0) | 375 if (not_after < 0) |
| 377 return false; | 376 return false; |
| 378 | 377 |
| 379 scoped_refptr<CRLSet> crl_set(new CRLSet); | 378 scoped_refptr<CRLSet> crl_set(new CRLSet); |
| 380 crl_set->sequence_ = static_cast<uint32>(sequence); | 379 crl_set->sequence_ = static_cast<uint32>(sequence); |
| 381 crl_set->not_after_ = static_cast<uint64>(not_after); | 380 crl_set->not_after_ = static_cast<uint64>(not_after); |
| 382 | 381 |
| 383 if (!crl_set->CopyBlockedSPKIsFromHeader(header_dict.get())) | 382 if (!crl_set->CopyBlockedSPKIsFromHeader(header_dict.get())) |
| 384 return false; | 383 return false; |
| 385 | 384 |
| 386 std::vector<uint8> crl_changes; | 385 std::vector<uint8> crl_changes; |
| 387 | 386 |
| 388 if (!ReadChanges(&data, &crl_changes)) | 387 if (!ReadChanges(&data, &crl_changes)) |
| 389 return false; | 388 return false; |
| 390 | 389 |
| 391 size_t i = 0, j = 0; | 390 size_t i = 0, j = 0; |
| 392 for (std::vector<uint8>::const_iterator k = crl_changes.begin(); | 391 for (std::vector<uint8>::const_iterator k = crl_changes.begin(); |
| 393 k != crl_changes.end(); ++k) { | 392 k != crl_changes.end(); |
| 393 ++k) { |
| 394 if (*k == SYMBOL_SAME) { | 394 if (*k == SYMBOL_SAME) { |
| 395 if (i >= crls_.size()) | 395 if (i >= crls_.size()) |
| 396 return false; | 396 return false; |
| 397 crl_set->crls_.push_back(crls_[i]); | 397 crl_set->crls_.push_back(crls_[i]); |
| 398 crl_set->crls_index_by_issuer_[crls_[i].first] = j; | 398 crl_set->crls_index_by_issuer_[crls_[i].first] = j; |
| 399 i++; | 399 i++; |
| 400 j++; | 400 j++; |
| 401 } else if (*k == SYMBOL_INSERT) { | 401 } else if (*k == SYMBOL_INSERT) { |
| 402 std::string parent_spki_hash; | 402 std::string parent_spki_hash; |
| 403 std::vector<std::string> serials; | 403 std::vector<std::string> serials; |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 464 "\"Version\":0," | 464 "\"Version\":0," |
| 465 "\"ContentType\":\"CRLSet\"," | 465 "\"ContentType\":\"CRLSet\"," |
| 466 "\"Sequence\":%u," | 466 "\"Sequence\":%u," |
| 467 "\"DeltaFrom\":0," | 467 "\"DeltaFrom\":0," |
| 468 "\"NumParents\":%u," | 468 "\"NumParents\":%u," |
| 469 "\"BlockedSPKIs\":[", | 469 "\"BlockedSPKIs\":[", |
| 470 static_cast<unsigned>(sequence_), | 470 static_cast<unsigned>(sequence_), |
| 471 static_cast<unsigned>(crls_.size())); | 471 static_cast<unsigned>(crls_.size())); |
| 472 | 472 |
| 473 for (std::vector<std::string>::const_iterator i = blocked_spkis_.begin(); | 473 for (std::vector<std::string>::const_iterator i = blocked_spkis_.begin(); |
| 474 i != blocked_spkis_.end(); ++i) { | 474 i != blocked_spkis_.end(); |
| 475 ++i) { |
| 475 std::string spki_hash_base64; | 476 std::string spki_hash_base64; |
| 476 base::Base64Encode(*i, &spki_hash_base64); | 477 base::Base64Encode(*i, &spki_hash_base64); |
| 477 | 478 |
| 478 if (i != blocked_spkis_.begin()) | 479 if (i != blocked_spkis_.begin()) |
| 479 header += ","; | 480 header += ","; |
| 480 header += "\"" + spki_hash_base64 + "\""; | 481 header += "\"" + spki_hash_base64 + "\""; |
| 481 } | 482 } |
| 482 header += "]"; | 483 header += "]"; |
| 483 if (not_after_ != 0) | 484 if (not_after_ != 0) |
| 484 header += base::StringPrintf(",\"NotAfter\":%" PRIu64, not_after_); | 485 header += base::StringPrintf(",\"NotAfter\":%" PRIu64, not_after_); |
| 485 header += "}"; | 486 header += "}"; |
| 486 | 487 |
| 487 size_t len = 2 /* header len */ + header.size(); | 488 size_t len = 2 /* header len */ + header.size(); |
| 488 | 489 |
| 489 for (CRLList::const_iterator i = crls_.begin(); i != crls_.end(); ++i) { | 490 for (CRLList::const_iterator i = crls_.begin(); i != crls_.end(); ++i) { |
| 490 len += i->first.size() + 4 /* num serials */; | 491 len += i->first.size() + 4 /* num serials */; |
| 491 for (std::vector<std::string>::const_iterator j = i->second.begin(); | 492 for (std::vector<std::string>::const_iterator j = i->second.begin(); |
| 492 j != i->second.end(); ++j) { | 493 j != i->second.end(); |
| 494 ++j) { |
| 493 len += 1 /* serial length */ + j->size(); | 495 len += 1 /* serial length */ + j->size(); |
| 494 } | 496 } |
| 495 } | 497 } |
| 496 | 498 |
| 497 std::string ret; | 499 std::string ret; |
| 498 char* out = WriteInto(&ret, len + 1 /* to include final NUL */); | 500 char* out = WriteInto(&ret, len + 1 /* to include final NUL */); |
| 499 size_t off = 0; | 501 size_t off = 0; |
| 500 out[off++] = header.size(); | 502 out[off++] = header.size(); |
| 501 out[off++] = header.size() >> 8; | 503 out[off++] = header.size() >> 8; |
| 502 memcpy(out + off, header.data(), header.size()); | 504 memcpy(out + off, header.data(), header.size()); |
| 503 off += header.size(); | 505 off += header.size(); |
| 504 | 506 |
| 505 for (CRLList::const_iterator i = crls_.begin(); i != crls_.end(); ++i) { | 507 for (CRLList::const_iterator i = crls_.begin(); i != crls_.end(); ++i) { |
| 506 memcpy(out + off, i->first.data(), i->first.size()); | 508 memcpy(out + off, i->first.data(), i->first.size()); |
| 507 off += i->first.size(); | 509 off += i->first.size(); |
| 508 const uint32 num_serials = i->second.size(); | 510 const uint32 num_serials = i->second.size(); |
| 509 memcpy(out + off, &num_serials, sizeof(num_serials)); | 511 memcpy(out + off, &num_serials, sizeof(num_serials)); |
| 510 off += sizeof(num_serials); | 512 off += sizeof(num_serials); |
| 511 | 513 |
| 512 for (std::vector<std::string>::const_iterator j = i->second.begin(); | 514 for (std::vector<std::string>::const_iterator j = i->second.begin(); |
| 513 j != i->second.end(); ++j) { | 515 j != i->second.end(); |
| 516 ++j) { |
| 514 out[off++] = j->size(); | 517 out[off++] = j->size(); |
| 515 memcpy(out + off, j->data(), j->size()); | 518 memcpy(out + off, j->data(), j->size()); |
| 516 off += j->size(); | 519 off += j->size(); |
| 517 } | 520 } |
| 518 } | 521 } |
| 519 | 522 |
| 520 CHECK_EQ(off, len); | 523 CHECK_EQ(off, len); |
| 521 return ret; | 524 return ret; |
| 522 } | 525 } |
| 523 | 526 |
| 524 CRLSet::Result CRLSet::CheckSPKI(const base::StringPiece& spki_hash) const { | 527 CRLSet::Result CRLSet::CheckSPKI(const base::StringPiece& spki_hash) const { |
| 525 for (std::vector<std::string>::const_iterator i = blocked_spkis_.begin(); | 528 for (std::vector<std::string>::const_iterator i = blocked_spkis_.begin(); |
| 526 i != blocked_spkis_.end(); ++i) { | 529 i != blocked_spkis_.end(); |
| 530 ++i) { |
| 527 if (spki_hash.size() == i->size() && | 531 if (spki_hash.size() == i->size() && |
| 528 memcmp(spki_hash.data(), i->data(), i->size()) == 0) { | 532 memcmp(spki_hash.data(), i->data(), i->size()) == 0) { |
| 529 return REVOKED; | 533 return REVOKED; |
| 530 } | 534 } |
| 531 } | 535 } |
| 532 | 536 |
| 533 return GOOD; | 537 return GOOD; |
| 534 } | 538 } |
| 535 | 539 |
| 536 CRLSet::Result CRLSet::CheckSerial( | 540 CRLSet::Result CRLSet::CheckSerial( |
| (...skipping 11 matching lines...) Expand all Loading... |
| 548 while (serial.size() > 1 && serial[0] == 0x00) | 552 while (serial.size() > 1 && serial[0] == 0x00) |
| 549 serial.remove_prefix(1); | 553 serial.remove_prefix(1); |
| 550 | 554 |
| 551 std::map<std::string, size_t>::const_iterator i = | 555 std::map<std::string, size_t>::const_iterator i = |
| 552 crls_index_by_issuer_.find(issuer_spki_hash.as_string()); | 556 crls_index_by_issuer_.find(issuer_spki_hash.as_string()); |
| 553 if (i == crls_index_by_issuer_.end()) | 557 if (i == crls_index_by_issuer_.end()) |
| 554 return UNKNOWN; | 558 return UNKNOWN; |
| 555 const std::vector<std::string>& serials = crls_[i->second].second; | 559 const std::vector<std::string>& serials = crls_[i->second].second; |
| 556 | 560 |
| 557 for (std::vector<std::string>::const_iterator i = serials.begin(); | 561 for (std::vector<std::string>::const_iterator i = serials.begin(); |
| 558 i != serials.end(); ++i) { | 562 i != serials.end(); |
| 563 ++i) { |
| 559 if (base::StringPiece(*i) == serial) | 564 if (base::StringPiece(*i) == serial) |
| 560 return REVOKED; | 565 return REVOKED; |
| 561 } | 566 } |
| 562 | 567 |
| 563 return GOOD; | 568 return GOOD; |
| 564 } | 569 } |
| 565 | 570 |
| 566 bool CRLSet::IsExpired() const { | 571 bool CRLSet::IsExpired() const { |
| 567 if (not_after_ == 0) | 572 if (not_after_ == 0) |
| 568 return false; | 573 return false; |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 602 crl_set->crls_index_by_issuer_[spki] = 0; | 607 crl_set->crls_index_by_issuer_[spki] = 0; |
| 603 } | 608 } |
| 604 | 609 |
| 605 if (!serial_number.empty()) | 610 if (!serial_number.empty()) |
| 606 crl_set->crls_[0].second.push_back(serial_number); | 611 crl_set->crls_[0].second.push_back(serial_number); |
| 607 | 612 |
| 608 return crl_set; | 613 return crl_set; |
| 609 } | 614 } |
| 610 | 615 |
| 611 } // namespace net | 616 } // namespace net |
| OLD | NEW |