Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(395)

Side by Side Diff: net/quic/crypto/cert_compressor.cc

Issue 14816006: Land Recent QUIC changes (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Added missing NET_PRIVATE_EXPORT to QuicWallTime Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/quic/crypto/cert_compressor.h ('k') | net/quic/crypto/cert_compressor_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/crypto/cert_compressor.h" 5 #include "net/quic/crypto/cert_compressor.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "base/memory/scoped_ptr.h" 8 #include "base/memory/scoped_ptr.h"
9 #include "net/quic/quic_utils.h" 9 #include "net/quic/quic_utils.h"
10 #include "third_party/zlib/zlib.h" 10 #include "third_party/zlib/zlib.h"
11 11
12 using base::StringPiece; 12 using base::StringPiece;
13 using std::string; 13 using std::string;
14 using std::vector; 14 using std::vector;
15 15
16 namespace net { 16 namespace net {
17 17
18 namespace { 18 namespace {
19 19
20 // kCommonCertSubstrings contains ~1500 bytes of common certificate substrings 20 // kCommonCertSubstrings contains ~1500 bytes of common certificate substrings
21 // in order to help zlib. 21 // 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.
22 static unsigned char kCommonCertSubstrings[] = { 23 static unsigned char kCommonCertSubstrings[] = {
23 0x04, 0x02, 0x30, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 24 0x04, 0x02, 0x30, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04,
24 0x16, 0x30, 0x14, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 25 0x16, 0x30, 0x14, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03,
25 0x01, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x30, 26 0x01, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x30,
26 0x5f, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x04, 0x01, 27 0x5f, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x04, 0x01,
27 0x06, 0x06, 0x0b, 0x60, 0x86, 0x48, 0x01, 0x86, 0xfd, 0x6d, 0x01, 0x07, 28 0x06, 0x06, 0x0b, 0x60, 0x86, 0x48, 0x01, 0x86, 0xfd, 0x6d, 0x01, 0x07,
28 0x17, 0x01, 0x30, 0x33, 0x20, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 29 0x17, 0x01, 0x30, 0x33, 0x20, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65,
29 0x64, 0x20, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 30 0x64, 0x20, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e,
30 0x20, 0x53, 0x20, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x64, 0x31, 0x34, 31 0x20, 0x53, 0x20, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x64, 0x31, 0x34,
31 0x20, 0x53, 0x53, 0x4c, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, 32 0x20, 0x53, 0x53, 0x4c, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31,
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
151 struct CertEntry { 152 struct CertEntry {
152 public: 153 public:
153 enum Type { 154 enum Type {
154 // COMPRESSED means that the certificate is included in the trailing zlib 155 // COMPRESSED means that the certificate is included in the trailing zlib
155 // data. 156 // data.
156 COMPRESSED = 1, 157 COMPRESSED = 1,
157 // CACHED means that the certificate is already known to the peer and will 158 // CACHED means that the certificate is already known to the peer and will
158 // be replaced by its 64-bit hash (in |hash|). 159 // be replaced by its 64-bit hash (in |hash|).
159 CACHED = 2, 160 CACHED = 2,
160 // COMMON means that the certificate is in a common certificate set known 161 // COMMON means that the certificate is in a common certificate set known
161 // to the peer with hash |set_hash| and index |index|. 162 // to the peer with hash |set_hash| and certificate index |index|.
162 COMMON = 3, 163 COMMON = 3,
163 }; 164 };
164 165
165 Type type; 166 Type type;
166 uint64 hash; 167 uint64 hash;
167 uint64 set_hash; 168 uint64 set_hash;
168 uint32 index; 169 uint32 index;
169 }; 170 };
170 171
171 // MatchCerts returns a vector of CertEntries describing how to most 172 // MatchCerts returns a vector of CertEntries describing how to most
172 // efficiently represent |certs| to a peer who has the common sets identified 173 // efficiently represent |certs| to a peer who has the common sets identified
173 // by |client_common_set_hashes| and who has cached the certificates with the 174 // by |client_common_set_hashes| and who has cached the certificates with the
174 // 64-bit, FNV-1a hashes in |client_cached|. 175 // 64-bit, FNV-1a hashes in |client_cached_cert_hashes|.
175 vector<CertEntry> MatchCerts(const vector<string>& certs, 176 vector<CertEntry> MatchCerts(const vector<string>& certs,
176 StringPiece client_common_set_hashes, 177 StringPiece client_common_set_hashes,
177 StringPiece client_cached, 178 StringPiece client_cached_cert_hashes,
178 CommonCertSet* common_set) { 179 const CommonCertSets* common_set) {
179 vector<CertEntry> entries; 180 vector<CertEntry> entries;
180 entries.reserve(certs.size()); 181 entries.reserve(certs.size());
181 182
182 const bool cached_valid = client_cached.size() % sizeof(uint64) == 0 && 183 const bool cached_valid =
183 !client_cached.empty(); 184 client_cached_cert_hashes.size() % sizeof(uint64) == 0 &&
185 !client_cached_cert_hashes.empty();
184 186
185 for (vector<string>::const_iterator i = certs.begin(); 187 for (vector<string>::const_iterator i = certs.begin();
186 i != certs.end(); ++i) { 188 i != certs.end(); ++i) {
187 CertEntry entry; 189 CertEntry entry;
188 190
189 if (cached_valid) { 191 if (cached_valid) {
190 bool cached = false; 192 bool cached = false;
191 193
192 uint64 hash = QuicUtils::FNV1a_64_Hash(i->data(), i->size()); 194 uint64 hash = QuicUtils::FNV1a_64_Hash(i->data(), i->size());
193 // This assumes that the machine is little-endian. 195 // This assumes that the machine is little-endian.
194 for (size_t i = 0; i < client_cached.size(); i += sizeof(uint64)) { 196 for (size_t i = 0; i < client_cached_cert_hashes.size();
197 i += sizeof(uint64)) {
195 uint64 cached_hash; 198 uint64 cached_hash;
196 memcpy(&cached_hash, client_cached.data() + i, sizeof(uint64)); 199 memcpy(&cached_hash, client_cached_cert_hashes.data() + i,
200 sizeof(uint64));
197 if (hash != cached_hash) { 201 if (hash != cached_hash) {
198 continue; 202 continue;
199 } 203 }
200 204
201 entry.type = CertEntry::CACHED; 205 entry.type = CertEntry::CACHED;
202 entry.hash = hash; 206 entry.hash = hash;
203 entries.push_back(entry); 207 entries.push_back(entry);
204 cached = true; 208 cached = true;
205 break; 209 break;
206 } 210 }
207 211
208 if (cached) { 212 if (cached) {
209 continue; 213 continue;
210 } 214 }
211 } 215 }
212 216
213 if (common_set && 217 if (common_set && common_set->MatchCert(*i, client_common_set_hashes,
214 common_set->MatchCert(*i, client_common_set_hashes, &entry.set_hash, 218 &entry.set_hash, &entry.index)) {
215 &entry.index)) {
216 entry.type = CertEntry::COMMON; 219 entry.type = CertEntry::COMMON;
217 entries.push_back(entry); 220 entries.push_back(entry);
218 continue; 221 continue;
219 } 222 }
220 223
221 entry.type = CertEntry::COMPRESSED; 224 entry.type = CertEntry::COMPRESSED;
222 entries.push_back(entry); 225 entries.push_back(entry);
223 } 226 }
224 227
225 return entries; 228 return entries;
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
322 325
323 return ret; 326 return ret;
324 } 327 }
325 328
326 // ParseEntries parses the serialised form of a vector of CertEntries from 329 // ParseEntries parses the serialised form of a vector of CertEntries from
327 // |in_out| and writes them to |out_entries|. CACHED and COMMON entries are 330 // |in_out| and writes them to |out_entries|. CACHED and COMMON entries are
328 // resolved using |cached_certs| and |common_set| and written to |out_certs|. 331 // resolved using |cached_certs| and |common_set| and written to |out_certs|.
329 // |in_out| is updated to contain the trailing data. 332 // |in_out| is updated to contain the trailing data.
330 bool ParseEntries(StringPiece* in_out, 333 bool ParseEntries(StringPiece* in_out,
331 const vector<string>& cached_certs, 334 const vector<string>& cached_certs,
332 CommonCertSet* common_set, 335 const CommonCertSets* common_set,
333 vector<CertEntry>* out_entries, 336 vector<CertEntry>* out_entries,
334 vector<string>* out_certs) { 337 vector<string>* out_certs) {
335 StringPiece in = *in_out; 338 StringPiece in = *in_out;
336 vector<uint64> cached_hashes; 339 vector<uint64> cached_hashes;
337 340
338 out_entries->clear(); 341 out_entries->clear();
339 out_certs->clear(); 342 out_certs->clear();
340 343
341 for (;;) { 344 for (;;) {
342 if (in.empty()) { 345 if (in.empty()) {
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
412 return true; 415 return true;
413 } 416 }
414 417
415 class ScopedZLib { 418 class ScopedZLib {
416 public: 419 public:
417 enum Type { 420 enum Type {
418 INFLATE, 421 INFLATE,
419 DEFLATE, 422 DEFLATE,
420 }; 423 };
421 424
422 explicit ScopedZLib(Type type) 425 explicit ScopedZLib(Type type) : z_(NULL), type_(type) {}
423 : z_(NULL),
424 type_(type) {
425 }
426 426
427 void reset(z_stream* z) { 427 void reset(z_stream* z) { z_ = z; }
428 z_ = z;
429 }
430 428
431 ~ScopedZLib() { 429 ~ScopedZLib() {
432 if (z_) { 430 if (z_) {
433 if (type_ == DEFLATE) { 431 if (type_ == DEFLATE) {
434 deflateEnd(z_); 432 deflateEnd(z_);
435 } else { 433 } else {
436 inflateEnd(z_); 434 inflateEnd(z_);
437 } 435 }
438 z_ = NULL; 436 z_ = NULL;
439 } 437 }
440 } 438 }
441 439
442 private: 440 private:
443 z_stream* z_; 441 z_stream* z_;
444 const Type type_; 442 const Type type_;
445 }; 443 };
446 444
447 } // anonymous namespace 445 } // anonymous namespace
448 446
449 447
450 // static 448 // static
451 string CertCompressor::CompressChain(const vector<string>& certs, 449 string CertCompressor::CompressChain(const vector<string>& certs,
452 StringPiece client_common_set_hashes, 450 StringPiece client_common_set_hashes,
453 StringPiece client_cached, 451 StringPiece client_cached_cert_hashes,
454 CommonCertSet* common_set) { 452 const CommonCertSets* common_set) {
455 const vector<CertEntry> entries = MatchCerts( 453 const vector<CertEntry> entries = MatchCerts(
456 certs, client_common_set_hashes, client_cached, common_set); 454 certs, client_common_set_hashes, client_cached_cert_hashes, common_set);
457 DCHECK_EQ(entries.size(), certs.size()); 455 DCHECK_EQ(entries.size(), certs.size());
458 456
459 size_t uncompressed_size = 0; 457 size_t uncompressed_size = 0;
460 for (size_t i = 0; i < entries.size(); i++) { 458 for (size_t i = 0; i < entries.size(); i++) {
461 if (entries[i].type == CertEntry::COMPRESSED) { 459 if (entries[i].type == CertEntry::COMPRESSED) {
462 uncompressed_size += 4 /* uint32 length */ + certs[i].size(); 460 uncompressed_size += 4 /* uint32 length */ + certs[i].size();
463 } 461 }
464 } 462 }
465 463
466 size_t compressed_size = 0; 464 size_t compressed_size = 0;
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
544 return ""; 542 return "";
545 } 543 }
546 544
547 result.resize(result.size() - z.avail_out); 545 result.resize(result.size() - z.avail_out);
548 return result; 546 return result;
549 } 547 }
550 548
551 // static 549 // static
552 bool CertCompressor::DecompressChain(StringPiece in, 550 bool CertCompressor::DecompressChain(StringPiece in,
553 const vector<string>& cached_certs, 551 const vector<string>& cached_certs,
554 CommonCertSet* common_set, 552 const CommonCertSets* common_set,
555 vector<string>* out_certs) { 553 vector<string>* out_certs) {
556 vector<CertEntry> entries; 554 vector<CertEntry> entries;
557 if (!ParseEntries(&in, cached_certs, common_set, &entries, out_certs)) { 555 if (!ParseEntries(&in, cached_certs, common_set, &entries, out_certs)) {
558 return false; 556 return false;
559 } 557 }
560 DCHECK_EQ(entries.size(), out_certs->size()); 558 DCHECK_EQ(entries.size(), out_certs->size());
561 559
562 scoped_ptr<uint8[]> uncompressed_data; 560 scoped_ptr<uint8[]> uncompressed_data;
563 StringPiece uncompressed; 561 StringPiece uncompressed;
564 562
(...skipping 28 matching lines...) Expand all
593 int rv = inflate(&z, Z_FINISH); 591 int rv = inflate(&z, Z_FINISH);
594 if (rv == Z_NEED_DICT) { 592 if (rv == Z_NEED_DICT) {
595 string zlib_dict = ZlibDictForEntries(entries, *out_certs); 593 string zlib_dict = ZlibDictForEntries(entries, *out_certs);
596 const uint8* dict = reinterpret_cast<const uint8*>(zlib_dict.data()); 594 const uint8* dict = reinterpret_cast<const uint8*>(zlib_dict.data());
597 if (Z_OK != inflateSetDictionary(&z, dict, zlib_dict.size())) { 595 if (Z_OK != inflateSetDictionary(&z, dict, zlib_dict.size())) {
598 return false; 596 return false;
599 } 597 }
600 rv = inflate(&z, Z_FINISH); 598 rv = inflate(&z, Z_FINISH);
601 } 599 }
602 600
603 if (Z_STREAM_END != rv || 601 if (Z_STREAM_END != rv || z.avail_out > 0 || z.avail_in > 0) {
604 z.avail_out > 0 ||
605 z.avail_in > 0) {
606 return false; 602 return false;
607 } 603 }
608 604
609 uncompressed = StringPiece(reinterpret_cast<char*>(uncompressed_data.get()), 605 uncompressed = StringPiece(reinterpret_cast<char*>(uncompressed_data.get()),
610 uncompressed_size); 606 uncompressed_size);
611 } 607 }
612 608
613 for (size_t i = 0; i < entries.size(); i++) { 609 for (size_t i = 0; i < entries.size(); i++) {
614 switch (entries[i].type) { 610 switch (entries[i].type) {
615 case CertEntry::COMPRESSED: 611 case CertEntry::COMPRESSED:
(...skipping 16 matching lines...) Expand all
632 } 628 }
633 629
634 if (!uncompressed.empty()) { 630 if (!uncompressed.empty()) {
635 return false; 631 return false;
636 } 632 }
637 633
638 return true; 634 return true;
639 } 635 }
640 636
641 } // namespace net 637 } // namespace net
OLDNEW
« no previous file with comments | « net/quic/crypto/cert_compressor.h ('k') | net/quic/crypto/cert_compressor_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698