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/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" |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
159 COMPRESSED = 1, | 159 COMPRESSED = 1, |
160 // CACHED means that the certificate is already known to the peer and will | 160 // CACHED means that the certificate is already known to the peer and will |
161 // be replaced by its 64-bit hash (in |hash|). | 161 // be replaced by its 64-bit hash (in |hash|). |
162 CACHED = 2, | 162 CACHED = 2, |
163 // COMMON means that the certificate is in a common certificate set known | 163 // COMMON means that the certificate is in a common certificate set known |
164 // to the peer with hash |set_hash| and certificate index |index|. | 164 // to the peer with hash |set_hash| and certificate index |index|. |
165 COMMON = 3, | 165 COMMON = 3, |
166 }; | 166 }; |
167 | 167 |
168 Type type; | 168 Type type; |
169 uint64 hash; | 169 uint64_t hash; |
170 uint64 set_hash; | 170 uint64_t set_hash; |
171 uint32 index; | 171 uint32_t index; |
172 }; | 172 }; |
173 | 173 |
174 // MatchCerts returns a vector of CertEntries describing how to most | 174 // MatchCerts returns a vector of CertEntries describing how to most |
175 // efficiently represent |certs| to a peer who has the common sets identified | 175 // 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 | 176 // by |client_common_set_hashes| and who has cached the certificates with the |
177 // 64-bit, FNV-1a hashes in |client_cached_cert_hashes|. | 177 // 64-bit, FNV-1a hashes in |client_cached_cert_hashes|. |
178 vector<CertEntry> MatchCerts(const vector<string>& certs, | 178 vector<CertEntry> MatchCerts(const vector<string>& certs, |
179 StringPiece client_common_set_hashes, | 179 StringPiece client_common_set_hashes, |
180 StringPiece client_cached_cert_hashes, | 180 StringPiece client_cached_cert_hashes, |
181 const CommonCertSets* common_sets) { | 181 const CommonCertSets* common_sets) { |
182 vector<CertEntry> entries; | 182 vector<CertEntry> entries; |
183 entries.reserve(certs.size()); | 183 entries.reserve(certs.size()); |
184 | 184 |
185 const bool cached_valid = | 185 const bool cached_valid = |
186 client_cached_cert_hashes.size() % sizeof(uint64) == 0 && | 186 client_cached_cert_hashes.size() % sizeof(uint64_t) == 0 && |
187 !client_cached_cert_hashes.empty(); | 187 !client_cached_cert_hashes.empty(); |
188 | 188 |
189 for (vector<string>::const_iterator i = certs.begin(); i != certs.end(); | 189 for (vector<string>::const_iterator i = certs.begin(); i != certs.end(); |
190 ++i) { | 190 ++i) { |
191 CertEntry entry; | 191 CertEntry entry; |
192 | 192 |
193 if (cached_valid) { | 193 if (cached_valid) { |
194 bool cached = false; | 194 bool cached = false; |
195 | 195 |
196 uint64 hash = QuicUtils::FNV1a_64_Hash(i->data(), i->size()); | 196 uint64_t hash = QuicUtils::FNV1a_64_Hash(i->data(), i->size()); |
197 // This assumes that the machine is little-endian. | 197 // This assumes that the machine is little-endian. |
198 for (size_t j = 0; j < client_cached_cert_hashes.size(); | 198 for (size_t j = 0; j < client_cached_cert_hashes.size(); |
199 j += sizeof(uint64)) { | 199 j += sizeof(uint64_t)) { |
200 uint64 cached_hash; | 200 uint64_t cached_hash; |
201 memcpy(&cached_hash, client_cached_cert_hashes.data() + j, | 201 memcpy(&cached_hash, client_cached_cert_hashes.data() + j, |
202 sizeof(uint64)); | 202 sizeof(uint64_t)); |
203 if (hash != cached_hash) { | 203 if (hash != cached_hash) { |
204 continue; | 204 continue; |
205 } | 205 } |
206 | 206 |
207 entry.type = CertEntry::CACHED; | 207 entry.type = CertEntry::CACHED; |
208 entry.hash = hash; | 208 entry.hash = hash; |
209 entries.push_back(entry); | 209 entries.push_back(entry); |
210 cached = true; | 210 cached = true; |
211 break; | 211 break; |
212 } | 212 } |
(...skipping 23 matching lines...) Expand all Loading... |
236 size_t CertEntriesSize(const vector<CertEntry>& entries) { | 236 size_t CertEntriesSize(const vector<CertEntry>& entries) { |
237 size_t entries_size = 0; | 237 size_t entries_size = 0; |
238 | 238 |
239 for (vector<CertEntry>::const_iterator i = entries.begin(); | 239 for (vector<CertEntry>::const_iterator i = entries.begin(); |
240 i != entries.end(); ++i) { | 240 i != entries.end(); ++i) { |
241 entries_size++; | 241 entries_size++; |
242 switch (i->type) { | 242 switch (i->type) { |
243 case CertEntry::COMPRESSED: | 243 case CertEntry::COMPRESSED: |
244 break; | 244 break; |
245 case CertEntry::CACHED: | 245 case CertEntry::CACHED: |
246 entries_size += sizeof(uint64); | 246 entries_size += sizeof(uint64_t); |
247 break; | 247 break; |
248 case CertEntry::COMMON: | 248 case CertEntry::COMMON: |
249 entries_size += sizeof(uint64) + sizeof(uint32); | 249 entries_size += sizeof(uint64_t) + sizeof(uint32_t); |
250 break; | 250 break; |
251 } | 251 } |
252 } | 252 } |
253 | 253 |
254 entries_size++; // for end marker | 254 entries_size++; // for end marker |
255 | 255 |
256 return entries_size; | 256 return entries_size; |
257 } | 257 } |
258 | 258 |
259 // SerializeCertEntries serialises |entries| to |out|, which must have enough | 259 // SerializeCertEntries serialises |entries| to |out|, which must have enough |
260 // space to contain them. | 260 // space to contain them. |
261 void SerializeCertEntries(uint8* out, const vector<CertEntry>& entries) { | 261 void SerializeCertEntries(uint8_t* out, const vector<CertEntry>& entries) { |
262 for (vector<CertEntry>::const_iterator i = entries.begin(); | 262 for (vector<CertEntry>::const_iterator i = entries.begin(); |
263 i != entries.end(); ++i) { | 263 i != entries.end(); ++i) { |
264 *out++ = static_cast<uint8>(i->type); | 264 *out++ = static_cast<uint8_t>(i->type); |
265 switch (i->type) { | 265 switch (i->type) { |
266 case CertEntry::COMPRESSED: | 266 case CertEntry::COMPRESSED: |
267 break; | 267 break; |
268 case CertEntry::CACHED: | 268 case CertEntry::CACHED: |
269 memcpy(out, &i->hash, sizeof(i->hash)); | 269 memcpy(out, &i->hash, sizeof(i->hash)); |
270 out += sizeof(uint64); | 270 out += sizeof(uint64_t); |
271 break; | 271 break; |
272 case CertEntry::COMMON: | 272 case CertEntry::COMMON: |
273 // Assumes a little-endian machine. | 273 // Assumes a little-endian machine. |
274 memcpy(out, &i->set_hash, sizeof(i->set_hash)); | 274 memcpy(out, &i->set_hash, sizeof(i->set_hash)); |
275 out += sizeof(i->set_hash); | 275 out += sizeof(i->set_hash); |
276 memcpy(out, &i->index, sizeof(uint32)); | 276 memcpy(out, &i->index, sizeof(uint32_t)); |
277 out += sizeof(uint32); | 277 out += sizeof(uint32_t); |
278 break; | 278 break; |
279 } | 279 } |
280 } | 280 } |
281 | 281 |
282 *out++ = 0; // end marker | 282 *out++ = 0; // end marker |
283 } | 283 } |
284 | 284 |
285 // ZlibDictForEntries returns a string that contains the zlib pre-shared | 285 // ZlibDictForEntries returns a string that contains the zlib pre-shared |
286 // dictionary to use in order to decompress a zlib block following |entries|. | 286 // dictionary to use in order to decompress a zlib block following |entries|. |
287 // |certs| is one-to-one with |entries| and contains the certificates for those | 287 // |certs| is one-to-one with |entries| and contains the certificates for those |
(...skipping 23 matching lines...) Expand all Loading... |
311 | 311 |
312 zlib_dict += string(reinterpret_cast<const char*>(kCommonCertSubstrings), | 312 zlib_dict += string(reinterpret_cast<const char*>(kCommonCertSubstrings), |
313 sizeof(kCommonCertSubstrings)); | 313 sizeof(kCommonCertSubstrings)); |
314 | 314 |
315 DCHECK_EQ(zlib_dict.size(), zlib_dict_size); | 315 DCHECK_EQ(zlib_dict.size(), zlib_dict_size); |
316 | 316 |
317 return zlib_dict; | 317 return zlib_dict; |
318 } | 318 } |
319 | 319 |
320 // HashCerts returns the FNV-1a hashes of |certs|. | 320 // HashCerts returns the FNV-1a hashes of |certs|. |
321 vector<uint64> HashCerts(const vector<string>& certs) { | 321 vector<uint64_t> HashCerts(const vector<string>& certs) { |
322 vector<uint64> ret; | 322 vector<uint64_t> ret; |
323 ret.reserve(certs.size()); | 323 ret.reserve(certs.size()); |
324 | 324 |
325 for (vector<string>::const_iterator i = certs.begin(); i != certs.end(); | 325 for (vector<string>::const_iterator i = certs.begin(); i != certs.end(); |
326 ++i) { | 326 ++i) { |
327 ret.push_back(QuicUtils::FNV1a_64_Hash(i->data(), i->size())); | 327 ret.push_back(QuicUtils::FNV1a_64_Hash(i->data(), i->size())); |
328 } | 328 } |
329 | 329 |
330 return ret; | 330 return ret; |
331 } | 331 } |
332 | 332 |
333 // ParseEntries parses the serialised form of a vector of CertEntries from | 333 // 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 | 334 // |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|. | 335 // resolved using |cached_certs| and |common_sets| and written to |out_certs|. |
336 // |in_out| is updated to contain the trailing data. | 336 // |in_out| is updated to contain the trailing data. |
337 bool ParseEntries(StringPiece* in_out, | 337 bool ParseEntries(StringPiece* in_out, |
338 const vector<string>& cached_certs, | 338 const vector<string>& cached_certs, |
339 const CommonCertSets* common_sets, | 339 const CommonCertSets* common_sets, |
340 vector<CertEntry>* out_entries, | 340 vector<CertEntry>* out_entries, |
341 vector<string>* out_certs) { | 341 vector<string>* out_certs) { |
342 StringPiece in = *in_out; | 342 StringPiece in = *in_out; |
343 vector<uint64> cached_hashes; | 343 vector<uint64_t> cached_hashes; |
344 | 344 |
345 out_entries->clear(); | 345 out_entries->clear(); |
346 out_certs->clear(); | 346 out_certs->clear(); |
347 | 347 |
348 for (;;) { | 348 for (;;) { |
349 if (in.empty()) { | 349 if (in.empty()) { |
350 return false; | 350 return false; |
351 } | 351 } |
352 CertEntry entry; | 352 CertEntry entry; |
353 const uint8 type_byte = in[0]; | 353 const uint8_t type_byte = in[0]; |
354 in.remove_prefix(1); | 354 in.remove_prefix(1); |
355 | 355 |
356 if (type_byte == 0) { | 356 if (type_byte == 0) { |
357 break; | 357 break; |
358 } | 358 } |
359 | 359 |
360 entry.type = static_cast<CertEntry::Type>(type_byte); | 360 entry.type = static_cast<CertEntry::Type>(type_byte); |
361 | 361 |
362 switch (entry.type) { | 362 switch (entry.type) { |
363 case CertEntry::COMPRESSED: | 363 case CertEntry::COMPRESSED: |
364 out_certs->push_back(string()); | 364 out_certs->push_back(string()); |
365 break; | 365 break; |
366 case CertEntry::CACHED: { | 366 case CertEntry::CACHED: { |
367 if (in.size() < sizeof(uint64)) { | 367 if (in.size() < sizeof(uint64_t)) { |
368 return false; | 368 return false; |
369 } | 369 } |
370 memcpy(&entry.hash, in.data(), sizeof(uint64)); | 370 memcpy(&entry.hash, in.data(), sizeof(uint64_t)); |
371 in.remove_prefix(sizeof(uint64)); | 371 in.remove_prefix(sizeof(uint64_t)); |
372 | 372 |
373 if (cached_hashes.size() != cached_certs.size()) { | 373 if (cached_hashes.size() != cached_certs.size()) { |
374 cached_hashes = HashCerts(cached_certs); | 374 cached_hashes = HashCerts(cached_certs); |
375 } | 375 } |
376 bool found = false; | 376 bool found = false; |
377 for (size_t i = 0; i < cached_hashes.size(); i++) { | 377 for (size_t i = 0; i < cached_hashes.size(); i++) { |
378 if (cached_hashes[i] == entry.hash) { | 378 if (cached_hashes[i] == entry.hash) { |
379 out_certs->push_back(cached_certs[i]); | 379 out_certs->push_back(cached_certs[i]); |
380 found = true; | 380 found = true; |
381 break; | 381 break; |
382 } | 382 } |
383 } | 383 } |
384 if (!found) { | 384 if (!found) { |
385 return false; | 385 return false; |
386 } | 386 } |
387 break; | 387 break; |
388 } | 388 } |
389 case CertEntry::COMMON: { | 389 case CertEntry::COMMON: { |
390 if (!common_sets) { | 390 if (!common_sets) { |
391 return false; | 391 return false; |
392 } | 392 } |
393 if (in.size() < sizeof(uint64) + sizeof(uint32)) { | 393 if (in.size() < sizeof(uint64_t) + sizeof(uint32_t)) { |
394 return false; | 394 return false; |
395 } | 395 } |
396 memcpy(&entry.set_hash, in.data(), sizeof(uint64)); | 396 memcpy(&entry.set_hash, in.data(), sizeof(uint64_t)); |
397 in.remove_prefix(sizeof(uint64)); | 397 in.remove_prefix(sizeof(uint64_t)); |
398 memcpy(&entry.index, in.data(), sizeof(uint32)); | 398 memcpy(&entry.index, in.data(), sizeof(uint32_t)); |
399 in.remove_prefix(sizeof(uint32)); | 399 in.remove_prefix(sizeof(uint32_t)); |
400 | 400 |
401 StringPiece cert = common_sets->GetCert(entry.set_hash, entry.index); | 401 StringPiece cert = 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; |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
457 StringPiece client_common_set_hashes, | 457 StringPiece client_common_set_hashes, |
458 StringPiece client_cached_cert_hashes, | 458 StringPiece client_cached_cert_hashes, |
459 const CommonCertSets* common_sets) { | 459 const CommonCertSets* common_sets) { |
460 const vector<CertEntry> entries = MatchCerts( | 460 const 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 length */ + certs[i].size(); | 467 uncompressed_size += 4 /* uint32_t length */ + certs[i].size(); |
468 } | 468 } |
469 } | 469 } |
470 | 470 |
471 size_t compressed_size = 0; | 471 size_t compressed_size = 0; |
472 z_stream z; | 472 z_stream z; |
473 ScopedZLib scoped_z(ScopedZLib::DEFLATE); | 473 ScopedZLib scoped_z(ScopedZLib::DEFLATE); |
474 | 474 |
475 if (uncompressed_size > 0) { | 475 if (uncompressed_size > 0) { |
476 memset(&z, 0, sizeof(z)); | 476 memset(&z, 0, sizeof(z)); |
477 int rv = deflateInit(&z, Z_DEFAULT_COMPRESSION); | 477 int rv = deflateInit(&z, Z_DEFAULT_COMPRESSION); |
478 DCHECK_EQ(Z_OK, rv); | 478 DCHECK_EQ(Z_OK, rv); |
479 if (rv != Z_OK) { | 479 if (rv != Z_OK) { |
480 return ""; | 480 return ""; |
481 } | 481 } |
482 scoped_z.reset(&z); | 482 scoped_z.reset(&z); |
483 | 483 |
484 string zlib_dict = ZlibDictForEntries(entries, certs); | 484 string zlib_dict = ZlibDictForEntries(entries, certs); |
485 | 485 |
486 rv = deflateSetDictionary(&z, reinterpret_cast<const uint8*>(&zlib_dict[0]), | 486 rv = deflateSetDictionary( |
487 zlib_dict.size()); | 487 &z, reinterpret_cast<const uint8_t*>(&zlib_dict[0]), zlib_dict.size()); |
488 DCHECK_EQ(Z_OK, rv); | 488 DCHECK_EQ(Z_OK, rv); |
489 if (rv != Z_OK) { | 489 if (rv != Z_OK) { |
490 return ""; | 490 return ""; |
491 } | 491 } |
492 | 492 |
493 compressed_size = deflateBound(&z, uncompressed_size); | 493 compressed_size = deflateBound(&z, uncompressed_size); |
494 } | 494 } |
495 | 495 |
496 const size_t entries_size = CertEntriesSize(entries); | 496 const size_t entries_size = CertEntriesSize(entries); |
497 | 497 |
498 string result; | 498 string result; |
499 result.resize(entries_size + (uncompressed_size > 0 ? 4 : 0) + | 499 result.resize(entries_size + (uncompressed_size > 0 ? 4 : 0) + |
500 compressed_size); | 500 compressed_size); |
501 | 501 |
502 uint8* j = reinterpret_cast<uint8*>(&result[0]); | 502 uint8_t* j = reinterpret_cast<uint8_t*>(&result[0]); |
503 SerializeCertEntries(j, entries); | 503 SerializeCertEntries(j, entries); |
504 j += entries_size; | 504 j += entries_size; |
505 | 505 |
506 if (uncompressed_size == 0) { | 506 if (uncompressed_size == 0) { |
507 return result; | 507 return result; |
508 } | 508 } |
509 | 509 |
510 uint32 uncompressed_size_32 = uncompressed_size; | 510 uint32_t uncompressed_size_32 = uncompressed_size; |
511 memcpy(j, &uncompressed_size_32, sizeof(uint32)); | 511 memcpy(j, &uncompressed_size_32, sizeof(uint32_t)); |
512 j += sizeof(uint32); | 512 j += sizeof(uint32_t); |
513 | 513 |
514 int rv; | 514 int rv; |
515 | 515 |
516 z.next_out = j; | 516 z.next_out = j; |
517 z.avail_out = compressed_size; | 517 z.avail_out = compressed_size; |
518 | 518 |
519 for (size_t i = 0; i < certs.size(); i++) { | 519 for (size_t i = 0; i < certs.size(); i++) { |
520 if (entries[i].type != CertEntry::COMPRESSED) { | 520 if (entries[i].type != CertEntry::COMPRESSED) { |
521 continue; | 521 continue; |
522 } | 522 } |
523 | 523 |
524 uint32 length32 = certs[i].size(); | 524 uint32_t length32 = certs[i].size(); |
525 z.next_in = reinterpret_cast<uint8*>(&length32); | 525 z.next_in = reinterpret_cast<uint8_t*>(&length32); |
526 z.avail_in = sizeof(length32); | 526 z.avail_in = sizeof(length32); |
527 rv = deflate(&z, Z_NO_FLUSH); | 527 rv = deflate(&z, Z_NO_FLUSH); |
528 DCHECK_EQ(Z_OK, rv); | 528 DCHECK_EQ(Z_OK, rv); |
529 DCHECK_EQ(0u, z.avail_in); | 529 DCHECK_EQ(0u, z.avail_in); |
530 if (rv != Z_OK || z.avail_in) { | 530 if (rv != Z_OK || z.avail_in) { |
531 return ""; | 531 return ""; |
532 } | 532 } |
533 | 533 |
534 z.next_in = | 534 z.next_in = |
535 const_cast<uint8*>(reinterpret_cast<const uint8*>(certs[i].data())); | 535 const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(certs[i].data())); |
536 z.avail_in = certs[i].size(); | 536 z.avail_in = certs[i].size(); |
537 rv = deflate(&z, Z_NO_FLUSH); | 537 rv = deflate(&z, Z_NO_FLUSH); |
538 DCHECK_EQ(Z_OK, rv); | 538 DCHECK_EQ(Z_OK, rv); |
539 DCHECK_EQ(0u, z.avail_in); | 539 DCHECK_EQ(0u, z.avail_in); |
540 if (rv != Z_OK || z.avail_in) { | 540 if (rv != Z_OK || z.avail_in) { |
541 return ""; | 541 return ""; |
542 } | 542 } |
543 } | 543 } |
544 | 544 |
545 z.avail_in = 0; | 545 z.avail_in = 0; |
(...skipping 11 matching lines...) Expand all Loading... |
557 bool CertCompressor::DecompressChain(StringPiece in, | 557 bool CertCompressor::DecompressChain(StringPiece in, |
558 const vector<string>& cached_certs, | 558 const vector<string>& cached_certs, |
559 const CommonCertSets* common_sets, | 559 const CommonCertSets* common_sets, |
560 vector<string>* out_certs) { | 560 vector<string>* out_certs) { |
561 vector<CertEntry> entries; | 561 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 scoped_ptr<uint8[]> uncompressed_data; | 567 scoped_ptr<uint8_t[]> uncompressed_data; |
568 StringPiece uncompressed; | 568 StringPiece uncompressed; |
569 | 569 |
570 if (!in.empty()) { | 570 if (!in.empty()) { |
571 if (in.size() < sizeof(uint32)) { | 571 if (in.size() < sizeof(uint32_t)) { |
572 return false; | 572 return false; |
573 } | 573 } |
574 | 574 |
575 uint32 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)); | 577 in.remove_prefix(sizeof(uint32_t)); |
578 | 578 |
579 if (uncompressed_size > 128 * 1024) { | 579 if (uncompressed_size > 128 * 1024) { |
580 return false; | 580 return false; |
581 } | 581 } |
582 | 582 |
583 uncompressed_data.reset(new uint8[uncompressed_size]); | 583 uncompressed_data.reset(new uint8_t[uncompressed_size]); |
584 z_stream z; | 584 z_stream z; |
585 ScopedZLib scoped_z(ScopedZLib::INFLATE); | 585 ScopedZLib scoped_z(ScopedZLib::INFLATE); |
586 | 586 |
587 memset(&z, 0, sizeof(z)); | 587 memset(&z, 0, sizeof(z)); |
588 z.next_out = uncompressed_data.get(); | 588 z.next_out = uncompressed_data.get(); |
589 z.avail_out = uncompressed_size; | 589 z.avail_out = uncompressed_size; |
590 z.next_in = const_cast<uint8*>(reinterpret_cast<const uint8*>(in.data())); | 590 z.next_in = |
| 591 const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(in.data())); |
591 z.avail_in = in.size(); | 592 z.avail_in = in.size(); |
592 | 593 |
593 if (Z_OK != inflateInit(&z)) { | 594 if (Z_OK != inflateInit(&z)) { |
594 return false; | 595 return false; |
595 } | 596 } |
596 scoped_z.reset(&z); | 597 scoped_z.reset(&z); |
597 | 598 |
598 int rv = inflate(&z, Z_FINISH); | 599 int rv = inflate(&z, Z_FINISH); |
599 if (rv == Z_NEED_DICT) { | 600 if (rv == Z_NEED_DICT) { |
600 string zlib_dict = ZlibDictForEntries(entries, *out_certs); | 601 string zlib_dict = ZlibDictForEntries(entries, *out_certs); |
601 const uint8* dict = reinterpret_cast<const uint8*>(zlib_dict.data()); | 602 const uint8_t* dict = reinterpret_cast<const uint8_t*>(zlib_dict.data()); |
602 if (Z_OK != inflateSetDictionary(&z, dict, zlib_dict.size())) { | 603 if (Z_OK != inflateSetDictionary(&z, dict, zlib_dict.size())) { |
603 return false; | 604 return false; |
604 } | 605 } |
605 rv = inflate(&z, Z_FINISH); | 606 rv = inflate(&z, Z_FINISH); |
606 } | 607 } |
607 | 608 |
608 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) { |
609 return false; | 610 return false; |
610 } | 611 } |
611 | 612 |
612 uncompressed = StringPiece(reinterpret_cast<char*>(uncompressed_data.get()), | 613 uncompressed = StringPiece(reinterpret_cast<char*>(uncompressed_data.get()), |
613 uncompressed_size); | 614 uncompressed_size); |
614 } | 615 } |
615 | 616 |
616 for (size_t i = 0; i < entries.size(); i++) { | 617 for (size_t i = 0; i < entries.size(); i++) { |
617 switch (entries[i].type) { | 618 switch (entries[i].type) { |
618 case CertEntry::COMPRESSED: | 619 case CertEntry::COMPRESSED: |
619 if (uncompressed.size() < sizeof(uint32)) { | 620 if (uncompressed.size() < sizeof(uint32_t)) { |
620 return false; | 621 return false; |
621 } | 622 } |
622 uint32 cert_len; | 623 uint32_t cert_len; |
623 memcpy(&cert_len, uncompressed.data(), sizeof(cert_len)); | 624 memcpy(&cert_len, uncompressed.data(), sizeof(cert_len)); |
624 uncompressed.remove_prefix(sizeof(uint32)); | 625 uncompressed.remove_prefix(sizeof(uint32_t)); |
625 if (uncompressed.size() < cert_len) { | 626 if (uncompressed.size() < cert_len) { |
626 return false; | 627 return false; |
627 } | 628 } |
628 (*out_certs)[i] = uncompressed.substr(0, cert_len).as_string(); | 629 (*out_certs)[i] = uncompressed.substr(0, cert_len).as_string(); |
629 uncompressed.remove_prefix(cert_len); | 630 uncompressed.remove_prefix(cert_len); |
630 break; | 631 break; |
631 case CertEntry::CACHED: | 632 case CertEntry::CACHED: |
632 case CertEntry::COMMON: | 633 case CertEntry::COMMON: |
633 break; | 634 break; |
634 } | 635 } |
635 } | 636 } |
636 | 637 |
637 if (!uncompressed.empty()) { | 638 if (!uncompressed.empty()) { |
638 return false; | 639 return false; |
639 } | 640 } |
640 | 641 |
641 return true; | 642 return true; |
642 } | 643 } |
643 | 644 |
644 } // namespace net | 645 } // namespace net |
OLD | NEW |