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
12using base::StringPiece;
13using std::string;
14using std::vector;
15
16namespace net {
17
18namespace {
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.
23static 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|.
152struct 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|.
178vector<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|.
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