Home | History | Annotate | Download | only in crypto
      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
      3 // found in the LICENSE file.
      4 
      5 #include "net/quic/crypto/cert_compressor.h"
      6 
      7 #include "base/logging.h"
      8 #include "base/memory/scoped_ptr.h"
      9 #include "net/quic/quic_utils.h"
     10 #include "third_party/zlib/zlib.h"
     11 
     12 using base::StringPiece;
     13 using std::string;
     14 using std::vector;
     15 
     16 namespace net {
     17 
     18 namespace {
     19 
     20 // kCommonCertSubstrings contains ~1500 bytes of common certificate substrings
     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.
     23 static const unsigned char kCommonCertSubstrings[] = {
     24   0x04, 0x02, 0x30, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04,
     25   0x16, 0x30, 0x14, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03,
     26   0x01, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x30,
     27   0x5f, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x04, 0x01,
     28   0x06, 0x06, 0x0b, 0x60, 0x86, 0x48, 0x01, 0x86, 0xfd, 0x6d, 0x01, 0x07,
     29   0x17, 0x01, 0x30, 0x33, 0x20, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65,
     30   0x64, 0x20, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e,
     31   0x20, 0x53, 0x20, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x64, 0x31, 0x34,
     32   0x20, 0x53, 0x53, 0x4c, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31,
     33   0x32, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x53, 0x65, 0x72,
     34   0x76, 0x65, 0x72, 0x20, 0x43, 0x41, 0x30, 0x2d, 0x61, 0x69, 0x61, 0x2e,
     35   0x76, 0x65, 0x72, 0x69, 0x73, 0x69, 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d,
     36   0x2f, 0x45, 0x2d, 0x63, 0x72, 0x6c, 0x2e, 0x76, 0x65, 0x72, 0x69, 0x73,
     37   0x69, 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x45, 0x2e, 0x63, 0x65,
     38   0x72, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
     39   0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x4a, 0x2e, 0x63,
     40   0x6f, 0x6d, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73,
     41   0x2f, 0x63, 0x70, 0x73, 0x20, 0x28, 0x63, 0x29, 0x30, 0x30, 0x09, 0x06,
     42   0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1d, 0x30, 0x0d,
     43   0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05,
     44   0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x7b, 0x30, 0x1d, 0x06, 0x03, 0x55,
     45   0x1d, 0x0e, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
     46   0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01,
     47   0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xd2,
     48   0x6f, 0x64, 0x6f, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x43, 0x2e,
     49   0x63, 0x72, 0x6c, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16,
     50   0x04, 0x14, 0xb4, 0x2e, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x73, 0x69,
     51   0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x72, 0x30, 0x0b, 0x06, 0x03,
     52   0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x01, 0x30, 0x0d, 0x06, 0x09,
     53   0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30,
     54   0x81, 0xca, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
     55   0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x08,
     56   0x13, 0x07, 0x41, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x61, 0x31, 0x13, 0x30,
     57   0x11, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0a, 0x53, 0x63, 0x6f, 0x74,
     58   0x74, 0x73, 0x64, 0x61, 0x6c, 0x65, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03,
     59   0x55, 0x04, 0x0a, 0x13, 0x11, 0x47, 0x6f, 0x44, 0x61, 0x64, 0x64, 0x79,
     60   0x2e, 0x63, 0x6f, 0x6d, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x33,
     61   0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2a, 0x68, 0x74, 0x74,
     62   0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63,
     63   0x61, 0x74, 0x65, 0x73, 0x2e, 0x67, 0x6f, 0x64, 0x61, 0x64, 0x64, 0x79,
     64   0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74,
     65   0x6f, 0x72, 0x79, 0x31, 0x30, 0x30, 0x2e, 0x06, 0x03, 0x55, 0x04, 0x03,
     66   0x13, 0x27, 0x47, 0x6f, 0x20, 0x44, 0x61, 0x64, 0x64, 0x79, 0x20, 0x53,
     67   0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66,
     68   0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68,
     69   0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55,
     70   0x04, 0x05, 0x13, 0x08, 0x30, 0x37, 0x39, 0x36, 0x39, 0x32, 0x38, 0x37,
     71   0x30, 0x1e, 0x17, 0x0d, 0x31, 0x31, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d,
     72   0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x0c,
     73   0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, 0x30, 0x00,
     74   0x30, 0x1d, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
     75   0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55,
     76   0x1d, 0x25, 0x04, 0x16, 0x30, 0x14, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05,
     77   0x05, 0x07, 0x03, 0x01, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
     78   0x03, 0x02, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff,
     79   0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x33, 0x06, 0x03, 0x55, 0x1d,
     80   0x1f, 0x04, 0x2c, 0x30, 0x2a, 0x30, 0x28, 0xa0, 0x26, 0xa0, 0x24, 0x86,
     81   0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, 0x2e,
     82   0x67, 0x6f, 0x64, 0x61, 0x64, 0x64, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
     83   0x67, 0x64, 0x73, 0x31, 0x2d, 0x32, 0x30, 0x2a, 0x30, 0x28, 0x06, 0x08,
     84   0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, 0x16, 0x1c, 0x68, 0x74,
     85   0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x76, 0x65,
     86   0x72, 0x69, 0x73, 0x69, 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63,
     87   0x70, 0x73, 0x30, 0x34, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17,
     88   0x0d, 0x31, 0x33, 0x30, 0x35, 0x30, 0x39, 0x06, 0x08, 0x2b, 0x06, 0x01,
     89   0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x2d, 0x68, 0x74, 0x74, 0x70, 0x3a,
     90   0x2f, 0x2f, 0x73, 0x30, 0x39, 0x30, 0x37, 0x06, 0x08, 0x2b, 0x06, 0x01,
     91   0x05, 0x05, 0x07, 0x02, 0x30, 0x44, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04,
     92   0x3d, 0x30, 0x3b, 0x30, 0x39, 0x06, 0x0b, 0x60, 0x86, 0x48, 0x01, 0x86,
     93   0xf8, 0x45, 0x01, 0x07, 0x17, 0x06, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
     94   0x55, 0x04, 0x06, 0x13, 0x02, 0x47, 0x42, 0x31, 0x1b, 0x53, 0x31, 0x17,
     95   0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, 0x56, 0x65, 0x72,
     96   0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31,
     97   0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x16, 0x56, 0x65,
     98   0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74,
     99   0x20, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x31, 0x3b, 0x30, 0x39,
    100   0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x32, 0x54, 0x65, 0x72, 0x6d, 0x73,
    101   0x20, 0x6f, 0x66, 0x20, 0x75, 0x73, 0x65, 0x20, 0x61, 0x74, 0x20, 0x68,
    102   0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x76,
    103   0x65, 0x72, 0x69, 0x73, 0x69, 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
    104   0x72, 0x70, 0x61, 0x20, 0x28, 0x63, 0x29, 0x30, 0x31, 0x10, 0x30, 0x0e,
    105   0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x53, 0x31, 0x13, 0x30, 0x11,
    106   0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0a, 0x47, 0x31, 0x13, 0x30, 0x11,
    107   0x06, 0x0b, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x3c, 0x02, 0x01,
    108   0x03, 0x13, 0x02, 0x55, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04,
    109   0x03, 0x14, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
    110   0x31, 0x1d, 0x30, 0x1b, 0x06, 0x03, 0x55, 0x04, 0x0f, 0x13, 0x14, 0x50,
    111   0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x20, 0x4f, 0x72, 0x67, 0x61, 0x6e,
    112   0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x12, 0x31, 0x21, 0x30,
    113   0x1f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x18, 0x44, 0x6f, 0x6d, 0x61,
    114   0x69, 0x6e, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x20, 0x56,
    115   0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x64, 0x31, 0x14, 0x31, 0x31,
    116   0x30, 0x2f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x28, 0x53, 0x65, 0x65,
    117   0x20, 0x77, 0x77, 0x77, 0x2e, 0x72, 0x3a, 0x2f, 0x2f, 0x73, 0x65, 0x63,
    118   0x75, 0x72, 0x65, 0x2e, 0x67, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x53,
    119   0x69, 0x67, 0x6e, 0x31, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x41,
    120   0x2e, 0x63, 0x72, 0x6c, 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e,
    121   0x20, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x33, 0x20, 0x45, 0x63, 0x72,
    122   0x6c, 0x2e, 0x67, 0x65, 0x6f, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x63,
    123   0x6f, 0x6d, 0x2f, 0x63, 0x72, 0x6c, 0x73, 0x2f, 0x73, 0x64, 0x31, 0x1a,
    124   0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x68, 0x74, 0x74, 0x70, 0x3a,
    125   0x2f, 0x2f, 0x45, 0x56, 0x49, 0x6e, 0x74, 0x6c, 0x2d, 0x63, 0x63, 0x72,
    126   0x74, 0x2e, 0x67, 0x77, 0x77, 0x77, 0x2e, 0x67, 0x69, 0x63, 0x65, 0x72,
    127   0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x31, 0x6f, 0x63, 0x73, 0x70, 0x2e,
    128   0x76, 0x65, 0x72, 0x69, 0x73, 0x69, 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d,
    129   0x30, 0x39, 0x72, 0x61, 0x70, 0x69, 0x64, 0x73, 0x73, 0x6c, 0x2e, 0x63,
    130   0x6f, 0x73, 0x2e, 0x67, 0x6f, 0x64, 0x61, 0x64, 0x64, 0x79, 0x2e, 0x63,
    131   0x6f, 0x6d, 0x2f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72,
    132   0x79, 0x2f, 0x30, 0x81, 0x80, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05,
    133   0x07, 0x01, 0x01, 0x04, 0x74, 0x30, 0x72, 0x30, 0x24, 0x06, 0x08, 0x2b,
    134   0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x18, 0x68, 0x74, 0x74,
    135   0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x2e, 0x67, 0x6f, 0x64,
    136   0x61, 0x64, 0x64, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x30, 0x4a, 0x06,
    137   0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x3e, 0x68,
    138   0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66,
    139   0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x2e, 0x67, 0x6f, 0x64, 0x61, 0x64,
    140   0x64, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x72, 0x65, 0x70, 0x6f, 0x73,
    141   0x69, 0x74, 0x6f, 0x72, 0x79, 0x2f, 0x67, 0x64, 0x5f, 0x69, 0x6e, 0x74,
    142   0x65, 0x72, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x2e, 0x63, 0x72,
    143   0x74, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16,
    144   0x80, 0x14, 0xfd, 0xac, 0x61, 0x32, 0x93, 0x6c, 0x45, 0xd6, 0xe2, 0xee,
    145   0x85, 0x5f, 0x9a, 0xba, 0xe7, 0x76, 0x99, 0x68, 0xcc, 0xe7, 0x30, 0x27,
    146   0x86, 0x29, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x86, 0x30,
    147   0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x73,
    148 };
    149 
    150 // CertEntry represents a certificate in compressed form. Each entry is one of
    151 // the three types enumerated in |Type|.
    152 struct CertEntry {
    153  public:
    154   enum Type {
    155     // Type 0 is reserved to mean "end of list" in the wire format.
    156 
    157     // COMPRESSED means that the certificate is included in the trailing zlib
    158     // data.
    159     COMPRESSED = 1,
    160     // CACHED means that the certificate is already known to the peer and will
    161     // be replaced by its 64-bit hash (in |hash|).
    162     CACHED = 2,
    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|.
    165     COMMON = 3,
    166   };
    167 
    168   Type type;
    169   uint64 hash;
    170   uint64 set_hash;
    171   uint32 index;
    172 };
    173 
    174 // MatchCerts returns a vector of CertEntries describing how to most
    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
    177 // 64-bit, FNV-1a hashes in |client_cached_cert_hashes|.
    178 vector<CertEntry> MatchCerts(const vector<string>& certs,
    179                              StringPiece client_common_set_hashes,
    180                              StringPiece client_cached_cert_hashes,
    181                              const CommonCertSets* common_sets) {
    182   vector<CertEntry> entries;
    183   entries.reserve(certs.size());
    184 
    185   const bool cached_valid =
    186       client_cached_cert_hashes.size() % sizeof(uint64) == 0 &&
    187       !client_cached_cert_hashes.empty();
    188 
    189   for (vector<string>::const_iterator i = certs.begin();
    190        i != certs.end(); ++i) {
    191     CertEntry entry;
    192 
    193     if (cached_valid) {
    194       bool cached = false;
    195 
    196       uint64 hash = QuicUtils::FNV1a_64_Hash(i->data(), i->size());
    197       // 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|.
    235 size_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.
    260 void 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.
    288 string 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|.
    320 vector<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.
    336 bool 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.
    418 class 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
    458 string 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
    559 bool 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