OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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 "net/quic/core/crypto/cert_compressor.h" | 5 #include "net/quic/core/crypto/cert_compressor.h" |
6 | 6 |
7 #include <cstdint> | 7 #include <cstdint> |
8 #include <memory> | 8 #include <memory> |
9 | 9 |
10 #include "net/quic/core/quic_utils.h" | 10 #include "net/quic/core/quic_utils.h" |
11 #include "third_party/zlib/zlib.h" | 11 #include "third_party/zlib/zlib.h" |
12 | 12 |
13 using base::StringPiece; | |
14 using std::string; | 13 using std::string; |
15 | 14 |
16 namespace net { | 15 namespace net { |
17 | 16 |
18 namespace { | 17 namespace { |
19 | 18 |
20 // kCommonCertSubstrings contains ~1500 bytes of common certificate substrings | 19 // kCommonCertSubstrings contains ~1500 bytes of common certificate substrings |
21 // in order to help zlib. This was generated via a fairly dumb algorithm from | 20 // in order to help zlib. This was generated via a fairly dumb algorithm from |
22 // the Alexa Top 5000 set - we could probably do better. | 21 // the Alexa Top 5000 set - we could probably do better. |
23 static const unsigned char kCommonCertSubstrings[] = { | 22 static const unsigned char kCommonCertSubstrings[] = { |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
169 uint64_t hash; | 168 uint64_t hash; |
170 uint64_t set_hash; | 169 uint64_t set_hash; |
171 uint32_t index; | 170 uint32_t index; |
172 }; | 171 }; |
173 | 172 |
174 // MatchCerts returns a vector of CertEntries describing how to most | 173 // MatchCerts returns a vector of CertEntries describing how to most |
175 // efficiently represent |certs| to a peer who has the common sets identified | 174 // efficiently represent |certs| to a peer who has the common sets identified |
176 // by |client_common_set_hashes| and who has cached the certificates with the | 175 // by |client_common_set_hashes| and who has cached the certificates with the |
177 // 64-bit, FNV-1a hashes in |client_cached_cert_hashes|. | 176 // 64-bit, FNV-1a hashes in |client_cached_cert_hashes|. |
178 std::vector<CertEntry> MatchCerts(const std::vector<string>& certs, | 177 std::vector<CertEntry> MatchCerts(const std::vector<string>& certs, |
179 StringPiece client_common_set_hashes, | 178 QuicStringPiece client_common_set_hashes, |
180 StringPiece client_cached_cert_hashes, | 179 QuicStringPiece client_cached_cert_hashes, |
181 const CommonCertSets* common_sets) { | 180 const CommonCertSets* common_sets) { |
182 std::vector<CertEntry> entries; | 181 std::vector<CertEntry> entries; |
183 entries.reserve(certs.size()); | 182 entries.reserve(certs.size()); |
184 | 183 |
185 const bool cached_valid = | 184 const bool cached_valid = |
186 client_cached_cert_hashes.size() % sizeof(uint64_t) == 0 && | 185 client_cached_cert_hashes.size() % sizeof(uint64_t) == 0 && |
187 !client_cached_cert_hashes.empty(); | 186 !client_cached_cert_hashes.empty(); |
188 | 187 |
189 for (std::vector<string>::const_iterator i = certs.begin(); i != certs.end(); | 188 for (std::vector<string>::const_iterator i = certs.begin(); i != certs.end(); |
190 ++i) { | 189 ++i) { |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
327 ret.push_back(QuicUtils::FNV1a_64_Hash(*i)); | 326 ret.push_back(QuicUtils::FNV1a_64_Hash(*i)); |
328 } | 327 } |
329 | 328 |
330 return ret; | 329 return ret; |
331 } | 330 } |
332 | 331 |
333 // ParseEntries parses the serialised form of a vector of CertEntries from | 332 // ParseEntries parses the serialised form of a vector of CertEntries from |
334 // |in_out| and writes them to |out_entries|. CACHED and COMMON entries are | 333 // |in_out| and writes them to |out_entries|. CACHED and COMMON entries are |
335 // resolved using |cached_certs| and |common_sets| and written to |out_certs|. | 334 // resolved using |cached_certs| and |common_sets| and written to |out_certs|. |
336 // |in_out| is updated to contain the trailing data. | 335 // |in_out| is updated to contain the trailing data. |
337 bool ParseEntries(StringPiece* in_out, | 336 bool ParseEntries(QuicStringPiece* in_out, |
338 const std::vector<string>& cached_certs, | 337 const std::vector<string>& cached_certs, |
339 const CommonCertSets* common_sets, | 338 const CommonCertSets* common_sets, |
340 std::vector<CertEntry>* out_entries, | 339 std::vector<CertEntry>* out_entries, |
341 std::vector<string>* out_certs) { | 340 std::vector<string>* out_certs) { |
342 StringPiece in = *in_out; | 341 QuicStringPiece in = *in_out; |
343 std::vector<uint64_t> cached_hashes; | 342 std::vector<uint64_t> cached_hashes; |
344 | 343 |
345 out_entries->clear(); | 344 out_entries->clear(); |
346 out_certs->clear(); | 345 out_certs->clear(); |
347 | 346 |
348 for (;;) { | 347 for (;;) { |
349 if (in.empty()) { | 348 if (in.empty()) { |
350 return false; | 349 return false; |
351 } | 350 } |
352 CertEntry entry; | 351 CertEntry entry; |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
391 return false; | 390 return false; |
392 } | 391 } |
393 if (in.size() < sizeof(uint64_t) + sizeof(uint32_t)) { | 392 if (in.size() < sizeof(uint64_t) + sizeof(uint32_t)) { |
394 return false; | 393 return false; |
395 } | 394 } |
396 memcpy(&entry.set_hash, in.data(), sizeof(uint64_t)); | 395 memcpy(&entry.set_hash, in.data(), sizeof(uint64_t)); |
397 in.remove_prefix(sizeof(uint64_t)); | 396 in.remove_prefix(sizeof(uint64_t)); |
398 memcpy(&entry.index, in.data(), sizeof(uint32_t)); | 397 memcpy(&entry.index, in.data(), sizeof(uint32_t)); |
399 in.remove_prefix(sizeof(uint32_t)); | 398 in.remove_prefix(sizeof(uint32_t)); |
400 | 399 |
401 StringPiece cert = common_sets->GetCert(entry.set_hash, entry.index); | 400 QuicStringPiece cert = |
| 401 common_sets->GetCert(entry.set_hash, entry.index); |
402 if (cert.empty()) { | 402 if (cert.empty()) { |
403 return false; | 403 return false; |
404 } | 404 } |
405 out_certs->push_back(cert.as_string()); | 405 out_certs->push_back(cert.as_string()); |
406 break; | 406 break; |
407 } | 407 } |
408 default: | 408 default: |
409 return false; | 409 return false; |
410 } | 410 } |
411 out_entries->push_back(entry); | 411 out_entries->push_back(entry); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
447 } | 447 } |
448 | 448 |
449 z_stream* z_; | 449 z_stream* z_; |
450 const Type type_; | 450 const Type type_; |
451 }; | 451 }; |
452 | 452 |
453 } // anonymous namespace | 453 } // anonymous namespace |
454 | 454 |
455 // static | 455 // static |
456 string CertCompressor::CompressChain(const std::vector<string>& certs, | 456 string CertCompressor::CompressChain(const std::vector<string>& certs, |
457 StringPiece client_common_set_hashes, | 457 QuicStringPiece client_common_set_hashes, |
458 StringPiece client_cached_cert_hashes, | 458 QuicStringPiece client_cached_cert_hashes, |
459 const CommonCertSets* common_sets) { | 459 const CommonCertSets* common_sets) { |
460 const std::vector<CertEntry> entries = MatchCerts( | 460 const std::vector<CertEntry> entries = MatchCerts( |
461 certs, client_common_set_hashes, client_cached_cert_hashes, common_sets); | 461 certs, client_common_set_hashes, client_cached_cert_hashes, common_sets); |
462 DCHECK_EQ(entries.size(), certs.size()); | 462 DCHECK_EQ(entries.size(), certs.size()); |
463 | 463 |
464 size_t uncompressed_size = 0; | 464 size_t uncompressed_size = 0; |
465 for (size_t i = 0; i < entries.size(); i++) { | 465 for (size_t i = 0; i < entries.size(); i++) { |
466 if (entries[i].type == CertEntry::COMPRESSED) { | 466 if (entries[i].type == CertEntry::COMPRESSED) { |
467 uncompressed_size += 4 /* uint32_t length */ + certs[i].size(); | 467 uncompressed_size += 4 /* uint32_t length */ + certs[i].size(); |
468 } | 468 } |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
547 DCHECK_EQ(Z_STREAM_END, rv); | 547 DCHECK_EQ(Z_STREAM_END, rv); |
548 if (rv != Z_STREAM_END) { | 548 if (rv != Z_STREAM_END) { |
549 return ""; | 549 return ""; |
550 } | 550 } |
551 | 551 |
552 result.resize(result.size() - z.avail_out); | 552 result.resize(result.size() - z.avail_out); |
553 return result; | 553 return result; |
554 } | 554 } |
555 | 555 |
556 // static | 556 // static |
557 bool CertCompressor::DecompressChain(StringPiece in, | 557 bool CertCompressor::DecompressChain(QuicStringPiece in, |
558 const std::vector<string>& cached_certs, | 558 const std::vector<string>& cached_certs, |
559 const CommonCertSets* common_sets, | 559 const CommonCertSets* common_sets, |
560 std::vector<string>* out_certs) { | 560 std::vector<string>* out_certs) { |
561 std::vector<CertEntry> entries; | 561 std::vector<CertEntry> entries; |
562 if (!ParseEntries(&in, cached_certs, common_sets, &entries, out_certs)) { | 562 if (!ParseEntries(&in, cached_certs, common_sets, &entries, out_certs)) { |
563 return false; | 563 return false; |
564 } | 564 } |
565 DCHECK_EQ(entries.size(), out_certs->size()); | 565 DCHECK_EQ(entries.size(), out_certs->size()); |
566 | 566 |
567 std::unique_ptr<uint8_t[]> uncompressed_data; | 567 std::unique_ptr<uint8_t[]> uncompressed_data; |
568 StringPiece uncompressed; | 568 QuicStringPiece uncompressed; |
569 | 569 |
570 if (!in.empty()) { | 570 if (!in.empty()) { |
571 if (in.size() < sizeof(uint32_t)) { | 571 if (in.size() < sizeof(uint32_t)) { |
572 return false; | 572 return false; |
573 } | 573 } |
574 | 574 |
575 uint32_t uncompressed_size; | 575 uint32_t uncompressed_size; |
576 memcpy(&uncompressed_size, in.data(), sizeof(uncompressed_size)); | 576 memcpy(&uncompressed_size, in.data(), sizeof(uncompressed_size)); |
577 in.remove_prefix(sizeof(uint32_t)); | 577 in.remove_prefix(sizeof(uint32_t)); |
578 | 578 |
(...skipping 24 matching lines...) Expand all Loading... |
603 if (Z_OK != inflateSetDictionary(&z, dict, zlib_dict.size())) { | 603 if (Z_OK != inflateSetDictionary(&z, dict, zlib_dict.size())) { |
604 return false; | 604 return false; |
605 } | 605 } |
606 rv = inflate(&z, Z_FINISH); | 606 rv = inflate(&z, Z_FINISH); |
607 } | 607 } |
608 | 608 |
609 if (Z_STREAM_END != rv || z.avail_out > 0 || z.avail_in > 0) { | 609 if (Z_STREAM_END != rv || z.avail_out > 0 || z.avail_in > 0) { |
610 return false; | 610 return false; |
611 } | 611 } |
612 | 612 |
613 uncompressed = StringPiece(reinterpret_cast<char*>(uncompressed_data.get()), | 613 uncompressed = QuicStringPiece( |
614 uncompressed_size); | 614 reinterpret_cast<char*>(uncompressed_data.get()), uncompressed_size); |
615 } | 615 } |
616 | 616 |
617 for (size_t i = 0; i < entries.size(); i++) { | 617 for (size_t i = 0; i < entries.size(); i++) { |
618 switch (entries[i].type) { | 618 switch (entries[i].type) { |
619 case CertEntry::COMPRESSED: | 619 case CertEntry::COMPRESSED: |
620 if (uncompressed.size() < sizeof(uint32_t)) { | 620 if (uncompressed.size() < sizeof(uint32_t)) { |
621 return false; | 621 return false; |
622 } | 622 } |
623 uint32_t cert_len; | 623 uint32_t cert_len; |
624 memcpy(&cert_len, uncompressed.data(), sizeof(cert_len)); | 624 memcpy(&cert_len, uncompressed.data(), sizeof(cert_len)); |
(...skipping 11 matching lines...) Expand all Loading... |
636 } | 636 } |
637 | 637 |
638 if (!uncompressed.empty()) { | 638 if (!uncompressed.empty()) { |
639 return false; | 639 return false; |
640 } | 640 } |
641 | 641 |
642 return true; | 642 return true; |
643 } | 643 } |
644 | 644 |
645 } // namespace net | 645 } // namespace net |
OLD | NEW |