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/string_util.h" | 10 #include "base/string_util.h" |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
116 // header's "DeltaFrom" value. The delta describes the changes to each CRL | 116 // header's "DeltaFrom" value. The delta describes the changes to each CRL |
117 // in turn with a zlib compressed array of options: either the CRL is the same, | 117 // in turn with a zlib compressed array of options: either the CRL is the same, |
118 // a new CRL is inserted, the CRL is deleted or the CRL is updated. In the case | 118 // a new CRL is inserted, the CRL is deleted or the CRL is updated. In the case |
119 // of an update, the serials in the CRL are considered in the same fashion | 119 // of an update, the serials in the CRL are considered in the same fashion |
120 // except there is no delta update of a serial number: they are either | 120 // except there is no delta update of a serial number: they are either |
121 // inserted, deleted or left the same. | 121 // inserted, deleted or left the same. |
122 | 122 |
123 // ReadHeader reads the header (including length prefix) from |data| and | 123 // ReadHeader reads the header (including length prefix) from |data| and |
124 // updates |data| to remove the header on return. Caller takes ownership of the | 124 // updates |data| to remove the header on return. Caller takes ownership of the |
125 // returned pointer. | 125 // returned pointer. |
126 static DictionaryValue* ReadHeader(base::StringPiece* data) { | 126 static base::DictionaryValue* ReadHeader(base::StringPiece* data) { |
127 if (data->size() < 2) | 127 if (data->size() < 2) |
128 return NULL; | 128 return NULL; |
129 uint16 header_len; | 129 uint16 header_len; |
130 memcpy(&header_len, data->data(), 2); // assumes little-endian. | 130 memcpy(&header_len, data->data(), 2); // assumes little-endian. |
131 data->remove_prefix(2); | 131 data->remove_prefix(2); |
132 | 132 |
133 if (data->size() < header_len) | 133 if (data->size() < header_len) |
134 return NULL; | 134 return NULL; |
135 | 135 |
136 const base::StringPiece header_bytes(data->data(), header_len); | 136 const base::StringPiece header_bytes(data->data(), header_len); |
137 data->remove_prefix(header_len); | 137 data->remove_prefix(header_len); |
138 | 138 |
139 scoped_ptr<Value> header(base::JSONReader::Read( | 139 scoped_ptr<Value> header(base::JSONReader::Read( |
140 header_bytes.as_string(), true /* allow trailing comma */)); | 140 header_bytes.as_string(), true /* allow trailing comma */)); |
141 if (header.get() == NULL) | 141 if (header.get() == NULL) |
142 return NULL; | 142 return NULL; |
143 | 143 |
144 if (!header->IsType(Value::TYPE_DICTIONARY)) | 144 if (!header->IsType(Value::TYPE_DICTIONARY)) |
145 return NULL; | 145 return NULL; |
146 return reinterpret_cast<DictionaryValue*>(header.release()); | 146 return reinterpret_cast<base::DictionaryValue*>(header.release()); |
147 } | 147 } |
148 | 148 |
149 // kCurrentFileVersion is the version of the CRLSet file format that we | 149 // kCurrentFileVersion is the version of the CRLSet file format that we |
150 // currently implement. | 150 // currently implement. |
151 static const int kCurrentFileVersion = 0; | 151 static const int kCurrentFileVersion = 0; |
152 | 152 |
153 static bool ReadCRL(base::StringPiece* data, std::string* out_parent_spki_hash, | 153 static bool ReadCRL(base::StringPiece* data, std::string* out_parent_spki_hash, |
154 std::vector<std::string>* out_serials) { | 154 std::vector<std::string>* out_serials) { |
155 if (data->size() < crypto::kSHA256Length) | 155 if (data->size() < crypto::kSHA256Length) |
156 return false; | 156 return false; |
157 *out_parent_spki_hash = std::string(data->data(), crypto::kSHA256Length); | 157 *out_parent_spki_hash = std::string(data->data(), crypto::kSHA256Length); |
158 data->remove_prefix(crypto::kSHA256Length); | 158 data->remove_prefix(crypto::kSHA256Length); |
159 | 159 |
160 if (data->size() < sizeof(uint32)) | 160 if (data->size() < sizeof(uint32)) |
161 return false; | 161 return false; |
162 uint32 num_serials; | 162 uint32 num_serials; |
163 memcpy(&num_serials, data->data(), sizeof(uint32)); // assumes little endian | 163 memcpy(&num_serials, data->data(), sizeof(uint32)); // assumes little endian |
164 data->remove_prefix(sizeof(uint32)); | 164 data->remove_prefix(sizeof(uint32)); |
165 | 165 |
166 for (uint32 i = 0; i < num_serials; i++) { | 166 for (uint32 i = 0; i < num_serials; ++i) { |
167 uint8 serial_length; | 167 uint8 serial_length; |
168 if (data->size() < sizeof(uint8)) | 168 if (data->size() < sizeof(uint8)) |
169 return false; | 169 return false; |
170 memcpy(&serial_length, data->data(), sizeof(uint8)); | 170 memcpy(&serial_length, data->data(), sizeof(uint8)); |
171 data->remove_prefix(sizeof(uint8)); | 171 data->remove_prefix(sizeof(uint8)); |
172 | 172 |
173 if (data->size() < serial_length) | 173 if (data->size() < serial_length) |
174 return false; | 174 return false; |
175 std::string serial(data->data(), serial_length); | 175 std::string serial(data->data(), serial_length); |
176 data->remove_prefix(serial_length); | 176 data->remove_prefix(serial_length); |
177 out_serials->push_back(serial); | 177 out_serials->push_back(serial); |
178 } | 178 } |
179 | 179 |
180 return true; | 180 return true; |
181 } | 181 } |
182 | 182 |
| 183 bool CRLSet::CopyBlockedSPKIsFromHeader(base::DictionaryValue* header_dict) { |
| 184 ListValue* blocked_spkis_list = NULL; |
| 185 if (!header_dict->GetList("BlockedSPKIs", &blocked_spkis_list)) { |
| 186 // BlockedSPKIs is optional, so it's fine if we don't find it. |
| 187 return true; |
| 188 } |
| 189 |
| 190 blocked_spkis_.clear(); |
| 191 |
| 192 for (size_t i = 0; i < blocked_spkis_list->GetSize(); ++i) { |
| 193 std::string spki_sha256_base64, spki_sha256; |
| 194 if (!blocked_spkis_list->GetString(i, &spki_sha256_base64)) |
| 195 return false; |
| 196 if (!base::Base64Decode(spki_sha256_base64, &spki_sha256)) |
| 197 return false; |
| 198 blocked_spkis_.push_back(spki_sha256); |
| 199 } |
| 200 |
| 201 return true; |
| 202 } |
| 203 |
183 // static | 204 // static |
184 bool CRLSet::Parse(base::StringPiece data, scoped_refptr<CRLSet>* out_crl_set) { | 205 bool CRLSet::Parse(base::StringPiece data, scoped_refptr<CRLSet>* out_crl_set) { |
185 // Other parts of Chrome assume that we're little endian, so we don't lose | 206 // Other parts of Chrome assume that we're little endian, so we don't lose |
186 // anything by doing this. | 207 // anything by doing this. |
187 #if defined(__BYTE_ORDER) | 208 #if defined(__BYTE_ORDER) |
188 // Linux check | 209 // Linux check |
189 COMPILE_ASSERT(__BYTE_ORDER == __LITTLE_ENDIAN, assumes_little_endian); | 210 COMPILE_ASSERT(__BYTE_ORDER == __LITTLE_ENDIAN, assumes_little_endian); |
190 #elif defined(__BIG_ENDIAN__) | 211 #elif defined(__BIG_ENDIAN__) |
191 // Mac check | 212 // Mac check |
192 #error assumes little endian | 213 #error assumes little endian |
193 #endif | 214 #endif |
194 | 215 |
195 scoped_ptr<DictionaryValue> header_dict(ReadHeader(&data)); | 216 scoped_ptr<base::DictionaryValue> header_dict(ReadHeader(&data)); |
196 if (!header_dict.get()) | 217 if (!header_dict.get()) |
197 return false; | 218 return false; |
198 | 219 |
199 std::string contents; | 220 std::string contents; |
200 if (!header_dict->GetString("ContentType", &contents)) | 221 if (!header_dict->GetString("ContentType", &contents)) |
201 return false; | 222 return false; |
202 if (contents != "CRLSet") | 223 if (contents != "CRLSet") |
203 return false; | 224 return false; |
204 | 225 |
205 int version; | 226 int version; |
(...skipping 12 matching lines...) Expand all Loading... |
218 for (size_t crl_index = 0; !data.empty(); crl_index++) { | 239 for (size_t crl_index = 0; !data.empty(); crl_index++) { |
219 std::string parent_spki_sha256; | 240 std::string parent_spki_sha256; |
220 std::vector<std::string> serials; | 241 std::vector<std::string> serials; |
221 if (!ReadCRL(&data, &parent_spki_sha256, &serials)) | 242 if (!ReadCRL(&data, &parent_spki_sha256, &serials)) |
222 return false; | 243 return false; |
223 | 244 |
224 crl_set->crls_.push_back(std::make_pair(parent_spki_sha256, serials)); | 245 crl_set->crls_.push_back(std::make_pair(parent_spki_sha256, serials)); |
225 crl_set->crls_index_by_issuer_[parent_spki_sha256] = crl_index; | 246 crl_set->crls_index_by_issuer_[parent_spki_sha256] = crl_index; |
226 } | 247 } |
227 | 248 |
| 249 if (!crl_set->CopyBlockedSPKIsFromHeader(header_dict.get())) |
| 250 return false; |
| 251 |
228 *out_crl_set = crl_set; | 252 *out_crl_set = crl_set; |
229 return true; | 253 return true; |
230 } | 254 } |
231 | 255 |
232 // kMaxUncompressedChangesLength is the largest changes array that we'll | 256 // kMaxUncompressedChangesLength is the largest changes array that we'll |
233 // accept. This bounds the number of CRLs in the CRLSet as well as the number | 257 // accept. This bounds the number of CRLs in the CRLSet as well as the number |
234 // of serial numbers in a given CRL. | 258 // of serial numbers in a given CRL. |
235 static const unsigned kMaxUncompressedChangesLength = 1024 * 1024; | 259 static const unsigned kMaxUncompressedChangesLength = 1024 * 1024; |
236 | 260 |
237 static bool ReadChanges(base::StringPiece* data, | 261 static bool ReadChanges(base::StringPiece* data, |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
307 } | 331 } |
308 | 332 |
309 if (i != old_serials.size()) | 333 if (i != old_serials.size()) |
310 return false; | 334 return false; |
311 return true; | 335 return true; |
312 } | 336 } |
313 | 337 |
314 bool CRLSet::ApplyDelta(const base::StringPiece& in_data, | 338 bool CRLSet::ApplyDelta(const base::StringPiece& in_data, |
315 scoped_refptr<CRLSet>* out_crl_set) { | 339 scoped_refptr<CRLSet>* out_crl_set) { |
316 base::StringPiece data(in_data); | 340 base::StringPiece data(in_data); |
317 scoped_ptr<DictionaryValue> header_dict(ReadHeader(&data)); | 341 scoped_ptr<base::DictionaryValue> header_dict(ReadHeader(&data)); |
318 if (!header_dict.get()) | 342 if (!header_dict.get()) |
319 return false; | 343 return false; |
320 | 344 |
321 std::string contents; | 345 std::string contents; |
322 if (!header_dict->GetString("ContentType", &contents)) | 346 if (!header_dict->GetString("ContentType", &contents)) |
323 return false; | 347 return false; |
324 if (contents != "CRLSetDelta") | 348 if (contents != "CRLSetDelta") |
325 return false; | 349 return false; |
326 | 350 |
327 int version; | 351 int version; |
328 if (!header_dict->GetInteger("Version", &version) || | 352 if (!header_dict->GetInteger("Version", &version) || |
329 version != kCurrentFileVersion) { | 353 version != kCurrentFileVersion) { |
330 return false; | 354 return false; |
331 } | 355 } |
332 | 356 |
333 int sequence, delta_from; | 357 int sequence, delta_from; |
334 if (!header_dict->GetInteger("Sequence", &sequence) || | 358 if (!header_dict->GetInteger("Sequence", &sequence) || |
335 !header_dict->GetInteger("DeltaFrom", &delta_from) || | 359 !header_dict->GetInteger("DeltaFrom", &delta_from) || |
336 delta_from < 0 || | 360 delta_from < 0 || |
337 static_cast<uint32>(delta_from) != sequence_) { | 361 static_cast<uint32>(delta_from) != sequence_) { |
338 return false; | 362 return false; |
339 } | 363 } |
340 | 364 |
341 scoped_refptr<CRLSet> crl_set(new CRLSet); | 365 scoped_refptr<CRLSet> crl_set(new CRLSet); |
342 crl_set->sequence_ = static_cast<uint32>(sequence); | 366 crl_set->sequence_ = static_cast<uint32>(sequence); |
343 | 367 |
| 368 if (!crl_set->CopyBlockedSPKIsFromHeader(header_dict.get())) |
| 369 return false; |
| 370 |
344 std::vector<uint8> crl_changes; | 371 std::vector<uint8> crl_changes; |
345 | 372 |
346 if (!ReadChanges(&data, &crl_changes)) | 373 if (!ReadChanges(&data, &crl_changes)) |
347 return false; | 374 return false; |
348 | 375 |
349 size_t i = 0, j = 0; | 376 size_t i = 0, j = 0; |
350 for (std::vector<uint8>::const_iterator k = crl_changes.begin(); | 377 for (std::vector<uint8>::const_iterator k = crl_changes.begin(); |
351 k != crl_changes.end(); ++k) { | 378 k != crl_changes.end(); ++k) { |
352 if (*k == SYMBOL_SAME) { | 379 if (*k == SYMBOL_SAME) { |
353 if (i >= crls_.size()) | 380 if (i >= crls_.size()) |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
390 return false; | 417 return false; |
391 | 418 |
392 *out_crl_set = crl_set; | 419 *out_crl_set = crl_set; |
393 return true; | 420 return true; |
394 } | 421 } |
395 | 422 |
396 // static | 423 // static |
397 bool CRLSet::GetIsDeltaUpdate(const base::StringPiece& in_data, | 424 bool CRLSet::GetIsDeltaUpdate(const base::StringPiece& in_data, |
398 bool *is_delta) { | 425 bool *is_delta) { |
399 base::StringPiece data(in_data); | 426 base::StringPiece data(in_data); |
400 scoped_ptr<DictionaryValue> header_dict(ReadHeader(&data)); | 427 scoped_ptr<base::DictionaryValue> header_dict(ReadHeader(&data)); |
401 if (!header_dict.get()) | 428 if (!header_dict.get()) |
402 return false; | 429 return false; |
403 | 430 |
404 std::string contents; | 431 std::string contents; |
405 if (!header_dict->GetString("ContentType", &contents)) | 432 if (!header_dict->GetString("ContentType", &contents)) |
406 return false; | 433 return false; |
407 | 434 |
408 if (contents == "CRLSet") { | 435 if (contents == "CRLSet") { |
409 *is_delta = false; | 436 *is_delta = false; |
410 } else if (contents == "CRLSetDelta") { | 437 } else if (contents == "CRLSetDelta") { |
411 *is_delta = true; | 438 *is_delta = true; |
412 } else { | 439 } else { |
413 return false; | 440 return false; |
414 } | 441 } |
415 | 442 |
416 return true; | 443 return true; |
417 } | 444 } |
418 | 445 |
419 std::string CRLSet::Serialize() const { | 446 std::string CRLSet::Serialize() const { |
420 std::string header = StringPrintf( | 447 std::string header = StringPrintf( |
421 "{" | 448 "{" |
422 "\"Version\":0," | 449 "\"Version\":0," |
423 "\"ContentType\":\"CRLSet\"," | 450 "\"ContentType\":\"CRLSet\"," |
424 "\"Sequence\":%u," | 451 "\"Sequence\":%u," |
425 "\"DeltaFrom\":0," | 452 "\"DeltaFrom\":0," |
426 "\"NumParents\":%u" | 453 "\"NumParents\":%u," |
427 "}", | 454 "\"BlockedSPKIs\":[", |
428 static_cast<unsigned>(sequence_), | 455 static_cast<unsigned>(sequence_), |
429 static_cast<unsigned>(crls_.size())); | 456 static_cast<unsigned>(crls_.size())); |
430 | 457 |
| 458 for (std::vector<std::string>::const_iterator i = blocked_spkis_.begin(); |
| 459 i != blocked_spkis_.end(); ++i) { |
| 460 std::string spki_hash_base64; |
| 461 base::Base64Encode(*i, &spki_hash_base64); |
| 462 |
| 463 if (i != blocked_spkis_.begin()) |
| 464 header += ","; |
| 465 header += "\"" + spki_hash_base64 + "\""; |
| 466 } |
| 467 header += "]}"; |
| 468 |
431 size_t len = 2 /* header len */ + header.size(); | 469 size_t len = 2 /* header len */ + header.size(); |
432 | 470 |
433 for (CRLList::const_iterator i = crls_.begin(); i != crls_.end(); ++i) { | 471 for (CRLList::const_iterator i = crls_.begin(); i != crls_.end(); ++i) { |
434 len += i->first.size() + 4 /* num serials */; | 472 len += i->first.size() + 4 /* num serials */; |
435 for (std::vector<std::string>::const_iterator j = i->second.begin(); | 473 for (std::vector<std::string>::const_iterator j = i->second.begin(); |
436 j != i->second.end(); j++) { | 474 j != i->second.end(); ++j) { |
437 len += 1 /* serial length */ + j->size(); | 475 len += 1 /* serial length */ + j->size(); |
438 } | 476 } |
439 } | 477 } |
440 | 478 |
441 std::string ret; | 479 std::string ret; |
442 char* out = WriteInto(&ret, len + 1 /* to include final NUL */); | 480 char* out = WriteInto(&ret, len + 1 /* to include final NUL */); |
443 size_t off = 0; | 481 size_t off = 0; |
444 out[off++] = header.size(); | 482 out[off++] = header.size(); |
445 out[off++] = header.size() >> 8; | 483 out[off++] = header.size() >> 8; |
446 memcpy(out + off, header.data(), header.size()); | 484 memcpy(out + off, header.data(), header.size()); |
447 off += header.size(); | 485 off += header.size(); |
448 | 486 |
449 for (CRLList::const_iterator i = crls_.begin(); i != crls_.end(); ++i) { | 487 for (CRLList::const_iterator i = crls_.begin(); i != crls_.end(); ++i) { |
450 memcpy(out + off, i->first.data(), i->first.size()); | 488 memcpy(out + off, i->first.data(), i->first.size()); |
451 off += i->first.size(); | 489 off += i->first.size(); |
452 const uint32 num_serials = i->second.size(); | 490 const uint32 num_serials = i->second.size(); |
453 memcpy(out + off, &num_serials, sizeof(num_serials)); | 491 memcpy(out + off, &num_serials, sizeof(num_serials)); |
454 off += sizeof(num_serials); | 492 off += sizeof(num_serials); |
455 | 493 |
456 for (std::vector<std::string>::const_iterator j = i->second.begin(); | 494 for (std::vector<std::string>::const_iterator j = i->second.begin(); |
457 j != i->second.end(); j++) { | 495 j != i->second.end(); ++j) { |
458 out[off++] = j->size(); | 496 out[off++] = j->size(); |
459 memcpy(out + off, j->data(), j->size()); | 497 memcpy(out + off, j->data(), j->size()); |
460 off += j->size(); | 498 off += j->size(); |
461 } | 499 } |
462 } | 500 } |
463 | 501 |
464 CHECK_EQ(off, len); | 502 CHECK_EQ(off, len); |
465 return ret; | 503 return ret; |
466 } | 504 } |
467 | 505 |
468 CRLSet::Result CRLSet::CheckCertificate( | 506 CRLSet::Result CRLSet::CheckSPKI(const base::StringPiece& spki_hash) const { |
| 507 for (std::vector<std::string>::const_iterator i = blocked_spkis_.begin(); |
| 508 i != blocked_spkis_.end(); ++i) { |
| 509 if (spki_hash.size() == i->size() && |
| 510 memcmp(spki_hash.data(), i->data(), i->size()) == 0) { |
| 511 return REVOKED; |
| 512 } |
| 513 } |
| 514 |
| 515 return GOOD; |
| 516 } |
| 517 |
| 518 CRLSet::Result CRLSet::CheckSerial( |
469 const base::StringPiece& serial_number, | 519 const base::StringPiece& serial_number, |
470 const base::StringPiece& parent_spki) const { | 520 const base::StringPiece& issuer_spki_hash) const { |
471 base::StringPiece serial(serial_number); | 521 base::StringPiece serial(serial_number); |
472 | 522 |
473 if (!serial.empty() && (serial[0] & 0x80) != 0) { | 523 if (!serial.empty() && (serial[0] & 0x80) != 0) { |
474 // This serial number is negative but the process which generates CRL sets | 524 // This serial number is negative but the process which generates CRL sets |
475 // will reject any certificates with negative serial numbers as invalid. | 525 // will reject any certificates with negative serial numbers as invalid. |
476 return UNKNOWN; | 526 return UNKNOWN; |
477 } | 527 } |
478 | 528 |
479 // Remove any leading zero bytes. | 529 // Remove any leading zero bytes. |
480 while (serial.size() > 1 && serial[0] == 0x00) | 530 while (serial.size() > 1 && serial[0] == 0x00) |
481 serial.remove_prefix(1); | 531 serial.remove_prefix(1); |
482 | 532 |
483 std::map<std::string, size_t>::const_iterator i = | 533 std::map<std::string, size_t>::const_iterator i = |
484 crls_index_by_issuer_.find(parent_spki.as_string()); | 534 crls_index_by_issuer_.find(issuer_spki_hash.as_string()); |
485 if (i == crls_index_by_issuer_.end()) | 535 if (i == crls_index_by_issuer_.end()) |
486 return UNKNOWN; | 536 return UNKNOWN; |
487 const std::vector<std::string>& serials = crls_[i->second].second; | 537 const std::vector<std::string>& serials = crls_[i->second].second; |
488 | 538 |
489 for (std::vector<std::string>::const_iterator i = serials.begin(); | 539 for (std::vector<std::string>::const_iterator i = serials.begin(); |
490 i != serials.end(); ++i) { | 540 i != serials.end(); ++i) { |
491 if (base::StringPiece(*i) == serial) | 541 if (base::StringPiece(*i) == serial) |
492 return REVOKED; | 542 return REVOKED; |
493 } | 543 } |
494 | 544 |
495 return GOOD; | 545 return GOOD; |
496 } | 546 } |
497 | 547 |
498 uint32 CRLSet::sequence() const { | 548 uint32 CRLSet::sequence() const { |
499 return sequence_; | 549 return sequence_; |
500 } | 550 } |
501 | 551 |
502 const CRLSet::CRLList& CRLSet::crls() const { | 552 const CRLSet::CRLList& CRLSet::crls() const { |
503 return crls_; | 553 return crls_; |
504 } | 554 } |
505 | 555 |
506 } // namespace net | 556 } // namespace net |
OLD | NEW |