15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/quic/crypto/cert_compressor.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/quic/quic_utils.h"
10cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "third_party/zlib/zlib.h"
11cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::StringPiece;
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using std::string;
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using std::vector;
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// kCommonCertSubstrings contains ~1500 bytes of common certificate substrings
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in order to help zlib. This was generated via a fairly dumb algorithm from
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the Alexa Top 5000 set - we could probably do better.
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const unsigned char kCommonCertSubstrings[] = {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x04, 0x02, 0x30, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04,
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x16, 0x30, 0x14, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03,
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x01, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x30,
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x5f, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x04, 0x01,
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x06, 0x06, 0x0b, 0x60, 0x86, 0x48, 0x01, 0x86, 0xfd, 0x6d, 0x01, 0x07,
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x17, 0x01, 0x30, 0x33, 0x20, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65,
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x64, 0x20, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e,
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x20, 0x53, 0x20, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x64, 0x31, 0x34,
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x20, 0x53, 0x53, 0x4c, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31,
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x32, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x53, 0x65, 0x72,
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x76, 0x65, 0x72, 0x20, 0x43, 0x41, 0x30, 0x2d, 0x61, 0x69, 0x61, 0x2e,
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x76, 0x65, 0x72, 0x69, 0x73, 0x69, 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d,
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x2f, 0x45, 0x2d, 0x63, 0x72, 0x6c, 0x2e, 0x76, 0x65, 0x72, 0x69, 0x73,
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x69, 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x45, 0x2e, 0x63, 0x65,
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x72, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x4a, 0x2e, 0x63,
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x6f, 0x6d, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73,
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x2f, 0x63, 0x70, 0x73, 0x20, 0x28, 0x63, 0x29, 0x30, 0x30, 0x09, 0x06,
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1d, 0x30, 0x0d,
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05,
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x7b, 0x30, 0x1d, 0x06, 0x03, 0x55,
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x1d, 0x0e, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01,
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xd2,
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x6f, 0x64, 0x6f, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x43, 0x2e,
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x63, 0x72, 0x6c, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16,
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x04, 0x14, 0xb4, 0x2e, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x73, 0x69,
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x72, 0x30, 0x0b, 0x06, 0x03,
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x01, 0x30, 0x0d, 0x06, 0x09,
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30,
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x81, 0xca, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x08,
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x13, 0x07, 0x41, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x61, 0x31, 0x13, 0x30,
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x11, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0a, 0x53, 0x63, 0x6f, 0x74,
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x74, 0x73, 0x64, 0x61, 0x6c, 0x65, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03,
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x55, 0x04, 0x0a, 0x13, 0x11, 0x47, 0x6f, 0x44, 0x61, 0x64, 0x64, 0x79,
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x2e, 0x63, 0x6f, 0x6d, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x33,
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2a, 0x68, 0x74, 0x74,
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63,
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x61, 0x74, 0x65, 0x73, 0x2e, 0x67, 0x6f, 0x64, 0x61, 0x64, 0x64, 0x79,
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74,
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x6f, 0x72, 0x79, 0x31, 0x30, 0x30, 0x2e, 0x06, 0x03, 0x55, 0x04, 0x03,
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x13, 0x27, 0x47, 0x6f, 0x20, 0x44, 0x61, 0x64, 0x64, 0x79, 0x20, 0x53,
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66,
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68,
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55,
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x04, 0x05, 0x13, 0x08, 0x30, 0x37, 0x39, 0x36, 0x39, 0x32, 0x38, 0x37,
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x30, 0x1e, 0x17, 0x0d, 0x31, 0x31, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d,
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x0c,
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, 0x30, 0x00,
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x30, 0x1d, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55,
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  0x1d, 0x25, 0x04, 0x16, 0x30, 0x14, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05,
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x05, 0x07, 0x03, 0x01, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x03, 0x02, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff,
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x33, 0x06, 0x03, 0x55, 0x1d,
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x1f, 0x04, 0x2c, 0x30, 0x2a, 0x30, 0x28, 0xa0, 0x26, 0xa0, 0x24, 0x86,
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, 0x2e,
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x67, 0x6f, 0x64, 0x61, 0x64, 0x64, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x67, 0x64, 0x73, 0x31, 0x2d, 0x32, 0x30, 0x2a, 0x30, 0x28, 0x06, 0x08,
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, 0x16, 0x1c, 0x68, 0x74,
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x76, 0x65,
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x72, 0x69, 0x73, 0x69, 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63,
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x70, 0x73, 0x30, 0x34, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17,
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x0d, 0x31, 0x33, 0x30, 0x35, 0x30, 0x39, 0x06, 0x08, 0x2b, 0x06, 0x01,
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x2d, 0x68, 0x74, 0x74, 0x70, 0x3a,
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x2f, 0x2f, 0x73, 0x30, 0x39, 0x30, 0x37, 0x06, 0x08, 0x2b, 0x06, 0x01,
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x05, 0x05, 0x07, 0x02, 0x30, 0x44, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04,
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x3d, 0x30, 0x3b, 0x30, 0x39, 0x06, 0x0b, 0x60, 0x86, 0x48, 0x01, 0x86,
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  0xf8, 0x45, 0x01, 0x07, 0x17, 0x06, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x55, 0x04, 0x06, 0x13, 0x02, 0x47, 0x42, 0x31, 0x1b, 0x53, 0x31, 0x17,
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, 0x56, 0x65, 0x72,
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31,
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x16, 0x56, 0x65,
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74,
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x20, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x31, 0x3b, 0x30, 0x39,
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x32, 0x54, 0x65, 0x72, 0x6d, 0x73,
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x20, 0x6f, 0x66, 0x20, 0x75, 0x73, 0x65, 0x20, 0x61, 0x74, 0x20, 0x68,
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x76,
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x65, 0x72, 0x69, 0x73, 0x69, 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x72, 0x70, 0x61, 0x20, 0x28, 0x63, 0x29, 0x30, 0x31, 0x10, 0x30, 0x0e,
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x53, 0x31, 0x13, 0x30, 0x11,
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0a, 0x47, 0x31, 0x13, 0x30, 0x11,
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x06, 0x0b, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x3c, 0x02, 0x01,
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x03, 0x13, 0x02, 0x55, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04,
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x03, 0x14, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x31, 0x1d, 0x30, 0x1b, 0x06, 0x03, 0x55, 0x04, 0x0f, 0x13, 0x14, 0x50,
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x20, 0x4f, 0x72, 0x67, 0x61, 0x6e,
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x12, 0x31, 0x21, 0x30,
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x1f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x18, 0x44, 0x6f, 0x6d, 0x61,
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x69, 0x6e, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x20, 0x56,
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x64, 0x31, 0x14, 0x31, 0x31,
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x30, 0x2f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x28, 0x53, 0x65, 0x65,
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x20, 0x77, 0x77, 0x77, 0x2e, 0x72, 0x3a, 0x2f, 0x2f, 0x73, 0x65, 0x63,
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x75, 0x72, 0x65, 0x2e, 0x67, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x53,
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x69, 0x67, 0x6e, 0x31, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x41,
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x2e, 0x63, 0x72, 0x6c, 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e,
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x20, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x33, 0x20, 0x45, 0x63, 0x72,
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x6c, 0x2e, 0x67, 0x65, 0x6f, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x63,
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x6f, 0x6d, 0x2f, 0x63, 0x72, 0x6c, 0x73, 0x2f, 0x73, 0x64, 0x31, 0x1a,
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x68, 0x74, 0x74, 0x70, 0x3a,
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x2f, 0x2f, 0x45, 0x56, 0x49, 0x6e, 0x74, 0x6c, 0x2d, 0x63, 0x63, 0x72,
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x74, 0x2e, 0x67, 0x77, 0x77, 0x77, 0x2e, 0x67, 0x69, 0x63, 0x65, 0x72,
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x31, 0x6f, 0x63, 0x73, 0x70, 0x2e,
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x76, 0x65, 0x72, 0x69, 0x73, 0x69, 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d,
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x30, 0x39, 0x72, 0x61, 0x70, 0x69, 0x64, 0x73, 0x73, 0x6c, 0x2e, 0x63,
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x6f, 0x73, 0x2e, 0x67, 0x6f, 0x64, 0x61, 0x64, 0x64, 0x79, 0x2e, 0x63,
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x6f, 0x6d, 0x2f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72,
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x79, 0x2f, 0x30, 0x81, 0x80, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05,
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x07, 0x01, 0x01, 0x04, 0x74, 0x30, 0x72, 0x30, 0x24, 0x06, 0x08, 0x2b,
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x18, 0x68, 0x74, 0x74,
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x2e, 0x67, 0x6f, 0x64,
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x61, 0x64, 0x64, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x30, 0x4a, 0x06,
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x3e, 0x68,
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66,
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x2e, 0x67, 0x6f, 0x64, 0x61, 0x64,
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x64, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x72, 0x65, 0x70, 0x6f, 0x73,
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x69, 0x74, 0x6f, 0x72, 0x79, 0x2f, 0x67, 0x64, 0x5f, 0x69, 0x6e, 0x74,
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x65, 0x72, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x2e, 0x63, 0x72,
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x74, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16,
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x80, 0x14, 0xfd, 0xac, 0x61, 0x32, 0x93, 0x6c, 0x45, 0xd6, 0xe2, 0xee,
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x85, 0x5f, 0x9a, 0xba, 0xe7, 0x76, 0x99, 0x68, 0xcc, 0xe7, 0x30, 0x27,
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x86, 0x29, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x86, 0x30,
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x73,
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1495e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)
1505e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)// CertEntry represents a certificate in compressed form. Each entry is one of
1515e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)// the three types enumerated in |Type|.
1525e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)struct CertEntry {
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enum Type {
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Type 0 is reserved to mean "end of list" in the wire format.
1563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // COMPRESSED means that the certificate is included in the trailing zlib
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // data.
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    COMPRESSED = 1,
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // CACHED means that the certificate is already known to the peer and will
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // be replaced by its 64-bit hash (in |hash|).
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CACHED = 2,
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // COMMON means that the certificate is in a common certificate set known
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // to the peer with hash |set_hash| and certificate index |index|.
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    COMMON = 3,
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Type type;
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint64 hash;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint64 set_hash;
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 index;
172ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch};
173ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
174ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// MatchCerts returns a vector of CertEntries describing how to most
175ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// efficiently represent |certs| to a peer who has the common sets identified
176ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// by |client_common_set_hashes| and who has cached the certificates with the
177ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// 64-bit, FNV-1a hashes in |client_cached_cert_hashes|.
178ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvector<CertEntry> MatchCerts(const vector<string>& certs,
179ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                             StringPiece client_common_set_hashes,
180ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                             StringPiece client_cached_cert_hashes,
181ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                             const CommonCertSets* common_sets) {
1825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  vector<CertEntry> entries;
1835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  entries.reserve(certs.size());
1845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const bool cached_valid =
1865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      client_cached_cert_hashes.size() % sizeof(uint64) == 0 &&
1875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      !client_cached_cert_hashes.empty();
1885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  for (vector<string>::const_iterator i = certs.begin();
1905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)       i != certs.end(); ++i) {
1915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    CertEntry entry;
1925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (cached_valid) {
1945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      bool cached = false;
1955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      uint64 hash = QuicUtils::FNV1a_64_Hash(i->data(), i->size());
1975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      // This assumes that the machine is little-endian.
198      for (size_t i = 0; i < client_cached_cert_hashes.size();
199           i += sizeof(uint64)) {
200        uint64 cached_hash;
201        memcpy(&cached_hash, client_cached_cert_hashes.data() + i,
202               sizeof(uint64));
203        if (hash != cached_hash) {
204          continue;
205        }
206
207        entry.type = CertEntry::CACHED;
208        entry.hash = hash;
209        entries.push_back(entry);
210        cached = true;
211        break;
212      }
213
214      if (cached) {
215        continue;
216      }
217    }
218
219    if (common_sets && common_sets->MatchCert(*i, client_common_set_hashes,
220                                              &entry.set_hash, &entry.index)) {
221      entry.type = CertEntry::COMMON;
222      entries.push_back(entry);
223      continue;
224    }
225
226    entry.type = CertEntry::COMPRESSED;
227    entries.push_back(entry);
228  }
229
230  return entries;
231}
232
233// CertEntriesSize returns the size, in bytes, of the serialised form of
234// |entries|.
235size_t CertEntriesSize(const vector<CertEntry>& entries) {
236  size_t entries_size = 0;
237
238  for (vector<CertEntry>::const_iterator i = entries.begin();
239       i != entries.end(); ++i) {
240    entries_size++;
241    switch (i->type) {
242      case CertEntry::COMPRESSED:
243        break;
244      case CertEntry::CACHED:
245        entries_size += sizeof(uint64);
246        break;
247      case CertEntry::COMMON:
248        entries_size += sizeof(uint64) + sizeof(uint32);
249        break;
250    }
251  }
252
253  entries_size++;  // for end marker
254
255  return entries_size;
256}
257
258// SerializeCertEntries serialises |entries| to |out|, which must have enough
259// space to contain them.
260void SerializeCertEntries(uint8* out, const vector<CertEntry>& entries) {
261  for (vector<CertEntry>::const_iterator i = entries.begin();
262       i != entries.end(); ++i) {
263    *out++ = i->type;
264    switch (i->type) {
265      case CertEntry::COMPRESSED:
266        break;
267      case CertEntry::CACHED:
268        memcpy(out, &i->hash, sizeof(i->hash));
269        out += sizeof(uint64);
270        break;
271      case CertEntry::COMMON:
272        // Assumes a little-endian machine.
273        memcpy(out, &i->set_hash, sizeof(i->set_hash));
274        out += sizeof(i->set_hash);
275        memcpy(out, &i->index, sizeof(uint32));
276        out += sizeof(uint32);
277        break;
278    }
279  }
280
281  *out++ = 0;  // end marker
282}
283
284// ZlibDictForEntries returns a string that contains the zlib pre-shared
285// dictionary to use in order to decompress a zlib block following |entries|.
286// |certs| is one-to-one with |entries| and contains the certificates for those
287// entries that are CACHED or COMMON.
288string ZlibDictForEntries(const vector<CertEntry>& entries,
289                          const vector<string>& certs) {
290  string zlib_dict;
291
292  // The dictionary starts with the common and cached certs in reverse order.
293  size_t zlib_dict_size = 0;
294  for (size_t i = certs.size() - 1; i < certs.size(); i--) {
295    if (entries[i].type != CertEntry::COMPRESSED) {
296      zlib_dict_size += certs[i].size();
297    }
298  }
299
300  // At the end of the dictionary is a block of common certificate substrings.
301  zlib_dict_size += sizeof(kCommonCertSubstrings);
302
303  zlib_dict.reserve(zlib_dict_size);
304
305  for (size_t i = certs.size() - 1; i < certs.size(); i--) {
306    if (entries[i].type != CertEntry::COMPRESSED) {
307      zlib_dict += certs[i];
308    }
309  }
310
311  zlib_dict += string(reinterpret_cast<const char*>(kCommonCertSubstrings),
312                      sizeof(kCommonCertSubstrings));
313
314  DCHECK_EQ(zlib_dict.size(), zlib_dict_size);
315
316  return zlib_dict;
317}
318
319// HashCerts returns the FNV-1a hashes of |certs|.
320vector<uint64> HashCerts(const vector<string>& certs) {
321  vector<uint64> ret;
322  ret.reserve(certs.size());
323
324  for (vector<string>::const_iterator i = certs.begin();
325       i != certs.end(); ++i) {
326    ret.push_back(QuicUtils::FNV1a_64_Hash(i->data(), i->size()));
327  }
328
329  return ret;
330}
331
332// ParseEntries parses the serialised form of a vector of CertEntries from
333// |in_out| and writes them to |out_entries|. CACHED and COMMON entries are
334// resolved using |cached_certs| and |common_sets| and written to |out_certs|.
335// |in_out| is updated to contain the trailing data.
336bool ParseEntries(StringPiece* in_out,
337                  const vector<string>& cached_certs,
338                  const CommonCertSets* common_sets,
339                  vector<CertEntry>* out_entries,
340                  vector<string>* out_certs) {
341  StringPiece in = *in_out;
342  vector<uint64> cached_hashes;
343
344  out_entries->clear();
345  out_certs->clear();
346
347  for (;;) {
348    if (in.empty()) {
349      return false;
350    }
351    CertEntry entry;
352    const uint8 type_byte = in[0];
353    in.remove_prefix(1);
354
355    if (type_byte == 0) {
356      break;
357    }
358
359    entry.type = static_cast<CertEntry::Type>(type_byte);
360
361    switch (entry.type) {
362      case CertEntry::COMPRESSED:
363        out_certs->push_back(string());
364        break;
365      case CertEntry::CACHED: {
366        if (in.size() < sizeof(uint64)) {
367          return false;
368        }
369        memcpy(&entry.hash, in.data(), sizeof(uint64));
370        in.remove_prefix(sizeof(uint64));
371
372        if (cached_hashes.size() != cached_certs.size()) {
373          cached_hashes = HashCerts(cached_certs);
374        }
375        bool found = false;
376        for (size_t i = 0; i < cached_hashes.size(); i++) {
377          if (cached_hashes[i] == entry.hash) {
378            out_certs->push_back(cached_certs[i]);
379            found = true;
380            break;
381          }
382        }
383        if (!found) {
384          return false;
385        }
386        break;
387      }
388      case CertEntry::COMMON: {
389        if (!common_sets) {
390          return false;
391        }
392        if (in.size() < sizeof(uint64) + sizeof(uint32)) {
393          return false;
394        }
395        memcpy(&entry.set_hash, in.data(), sizeof(uint64));
396        in.remove_prefix(sizeof(uint64));
397        memcpy(&entry.index, in.data(), sizeof(uint32));
398        in.remove_prefix(sizeof(uint32));
399
400        StringPiece cert = common_sets->GetCert(entry.set_hash, entry.index);
401        if (cert.empty()) {
402          return false;
403        }
404        out_certs->push_back(cert.as_string());
405        break;
406      }
407      default:
408        return false;
409    }
410    out_entries->push_back(entry);
411  }
412
413  *in_out = in;
414  return true;
415}
416
417// ScopedZLib deals with the automatic destruction of a zlib context.
418class ScopedZLib {
419 public:
420  enum Type {
421    INFLATE,
422    DEFLATE,
423  };
424
425  explicit ScopedZLib(Type type) : z_(NULL), type_(type) {}
426
427  void reset(z_stream* z) {
428    Clear();
429    z_ = z;
430  }
431
432  ~ScopedZLib() {
433    Clear();
434  }
435
436 private:
437  void Clear() {
438    if (!z_) {
439      return;
440    }
441
442    if (type_ == DEFLATE) {
443      deflateEnd(z_);
444    } else {
445      inflateEnd(z_);
446    }
447    z_ = NULL;
448  }
449
450  z_stream* z_;
451  const Type type_;
452};
453
454}  // anonymous namespace
455
456
457// static
458string CertCompressor::CompressChain(const vector<string>& certs,
459                                     StringPiece client_common_set_hashes,
460                                     StringPiece client_cached_cert_hashes,
461                                     const CommonCertSets* common_sets) {
462  const vector<CertEntry> entries = MatchCerts(
463      certs, client_common_set_hashes, client_cached_cert_hashes, common_sets);
464  DCHECK_EQ(entries.size(), certs.size());
465
466  size_t uncompressed_size = 0;
467  for (size_t i = 0; i < entries.size(); i++) {
468    if (entries[i].type == CertEntry::COMPRESSED) {
469      uncompressed_size += 4 /* uint32 length */ + certs[i].size();
470    }
471  }
472
473  size_t compressed_size = 0;
474  z_stream z;
475  ScopedZLib scoped_z(ScopedZLib::DEFLATE);
476
477  if (uncompressed_size > 0) {
478    memset(&z, 0, sizeof(z));
479    int rv = deflateInit(&z, Z_DEFAULT_COMPRESSION);
480    DCHECK_EQ(Z_OK, rv);
481    if (rv != Z_OK) {
482      return "";
483    }
484    scoped_z.reset(&z);
485
486    string zlib_dict = ZlibDictForEntries(entries, certs);
487
488    rv = deflateSetDictionary(&z, reinterpret_cast<const uint8*>(&zlib_dict[0]),
489                              zlib_dict.size());
490    DCHECK_EQ(Z_OK, rv);
491    if (rv != Z_OK) {
492      return "";
493    }
494
495    compressed_size = deflateBound(&z, uncompressed_size);
496  }
497
498  const size_t entries_size = CertEntriesSize(entries);
499
500  string result;
501  result.resize(entries_size + (uncompressed_size > 0 ? 4 : 0) +
502                compressed_size);
503
504  uint8* j = reinterpret_cast<uint8*>(&result[0]);
505  SerializeCertEntries(j, entries);
506  j += entries_size;
507
508  if (uncompressed_size == 0) {
509    return result;
510  }
511
512  uint32 uncompressed_size_32 = uncompressed_size;
513  memcpy(j, &uncompressed_size_32, sizeof(uint32));
514  j += sizeof(uint32);
515
516  int rv;
517
518  z.next_out = j;
519  z.avail_out = compressed_size;
520
521  for (size_t i = 0; i < certs.size(); i++) {
522    if (entries[i].type != CertEntry::COMPRESSED) {
523      continue;
524    }
525
526    uint32 length32 = certs[i].size();
527    z.next_in = reinterpret_cast<uint8*>(&length32);
528    z.avail_in = sizeof(length32);
529    rv = deflate(&z, Z_NO_FLUSH);
530    DCHECK_EQ(Z_OK, rv);
531    DCHECK_EQ(0u, z.avail_in);
532    if (rv != Z_OK || z.avail_in) {
533      return "";
534    }
535
536    z.next_in =
537        const_cast<uint8*>(reinterpret_cast<const uint8*>(certs[i].data()));
538    z.avail_in = certs[i].size();
539    rv = deflate(&z, Z_NO_FLUSH);
540    DCHECK_EQ(Z_OK, rv);
541    DCHECK_EQ(0u, z.avail_in);
542    if (rv != Z_OK || z.avail_in) {
543      return "";
544    }
545  }
546
547  z.avail_in = 0;
548  rv = deflate(&z, Z_FINISH);
549  DCHECK_EQ(Z_STREAM_END, rv);
550  if (rv != Z_STREAM_END) {
551    return "";
552  }
553
554  result.resize(result.size() - z.avail_out);
555  return result;
556}
557
558// static
559bool CertCompressor::DecompressChain(StringPiece in,
560                                     const vector<string>& cached_certs,
561                                     const CommonCertSets* common_sets,
562                                     vector<string>* out_certs) {
563  vector<CertEntry> entries;
564  if (!ParseEntries(&in, cached_certs, common_sets, &entries, out_certs)) {
565    return false;
566  }
567  DCHECK_EQ(entries.size(), out_certs->size());
568
569  scoped_ptr<uint8[]> uncompressed_data;
570  StringPiece uncompressed;
571
572  if (!in.empty()) {
573    if (in.size() < sizeof(uint32)) {
574      return false;
575    }
576
577    uint32 uncompressed_size;
578    memcpy(&uncompressed_size, in.data(), sizeof(uncompressed_size));
579    in.remove_prefix(sizeof(uint32));
580
581    if (uncompressed_size > 128 * 1024) {
582      return false;
583    }
584
585    uncompressed_data.reset(new uint8[uncompressed_size]);
586    z_stream z;
587    ScopedZLib scoped_z(ScopedZLib::INFLATE);
588
589    memset(&z, 0, sizeof(z));
590    z.next_out = uncompressed_data.get();
591    z.avail_out = uncompressed_size;
592    z.next_in = const_cast<uint8*>(reinterpret_cast<const uint8*>(in.data()));
593    z.avail_in = in.size();
594
595    if (Z_OK != inflateInit(&z)) {
596      return false;
597    }
598    scoped_z.reset(&z);
599
600    int rv = inflate(&z, Z_FINISH);
601    if (rv == Z_NEED_DICT) {
602      string zlib_dict = ZlibDictForEntries(entries, *out_certs);
603      const uint8* dict = reinterpret_cast<const uint8*>(zlib_dict.data());
604      if (Z_OK != inflateSetDictionary(&z, dict, zlib_dict.size())) {
605        return false;
606      }
607      rv = inflate(&z, Z_FINISH);
608    }
609
610    if (Z_STREAM_END != rv || z.avail_out > 0 || z.avail_in > 0) {
611      return false;
612    }
613
614    uncompressed = StringPiece(reinterpret_cast<char*>(uncompressed_data.get()),
615                               uncompressed_size);
616  }
617
618  for (size_t i = 0; i < entries.size(); i++) {
619    switch (entries[i].type) {
620      case CertEntry::COMPRESSED:
621        if (uncompressed.size() < sizeof(uint32)) {
622          return false;
623        }
624        uint32 cert_len;
625        memcpy(&cert_len, uncompressed.data(), sizeof(cert_len));
626        uncompressed.remove_prefix(sizeof(uint32));
627        if (uncompressed.size() < cert_len) {
628          return false;
629        }
630        (*out_certs)[i] = uncompressed.substr(0, cert_len).as_string();
631        uncompressed.remove_prefix(cert_len);
632        break;
633      case CertEntry::CACHED:
634      case CertEntry::COMMON:
635        break;
636    }
637  }
638
639  if (!uncompressed.empty()) {
640    return false;
641  }
642
643  return true;
644}
645
646}  // namespace net
647