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.
5 #include "net/quic/crypto/cert_compressor.h"
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"
12 using base::StringPiece
;
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,
150 // CertEntry represents a certificate in compressed form. Each entry is one of
151 // the three types enumerated in |Type|.
155 // Type 0 is reserved to mean "end of list" in the wire format.
157 // COMPRESSED means that the certificate is included in the trailing zlib
160 // CACHED means that the certificate is already known to the peer and will
161 // be replaced by its 64-bit hash (in |hash|).
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|.
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());
185 const bool cached_valid
=
186 client_cached_cert_hashes
.size() % sizeof(uint64
) == 0 &&
187 !client_cached_cert_hashes
.empty();
189 for (vector
<string
>::const_iterator i
= certs
.begin();
190 i
!= certs
.end(); ++i
) {
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
)) {
201 memcpy(&cached_hash
, client_cached_cert_hashes
.data() + i
,
203 if (hash
!= cached_hash
) {
207 entry
.type
= CertEntry::CACHED
;
209 entries
.push_back(entry
);
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
);
226 entry
.type
= CertEntry::COMPRESSED
;
227 entries
.push_back(entry
);
233 // CertEntriesSize returns the size, in bytes, of the serialised form of
235 size_t CertEntriesSize(const vector
<CertEntry
>& entries
) {
236 size_t entries_size
= 0;
238 for (vector
<CertEntry
>::const_iterator i
= entries
.begin();
239 i
!= entries
.end(); ++i
) {
242 case CertEntry::COMPRESSED
:
244 case CertEntry::CACHED
:
245 entries_size
+= sizeof(uint64
);
247 case CertEntry::COMMON
:
248 entries_size
+= sizeof(uint64
) + sizeof(uint32
);
253 entries_size
++; // for end marker
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
) {
265 case CertEntry::COMPRESSED
:
267 case CertEntry::CACHED
:
268 memcpy(out
, &i
->hash
, sizeof(i
->hash
));
269 out
+= sizeof(uint64
);
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
);
281 *out
++ = 0; // end marker
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
) {
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();
300 // At the end of the dictionary is a block of common certificate substrings.
301 zlib_dict_size
+= sizeof(kCommonCertSubstrings
);
303 zlib_dict
.reserve(zlib_dict_size
);
305 for (size_t i
= certs
.size() - 1; i
< certs
.size(); i
--) {
306 if (entries
[i
].type
!= CertEntry::COMPRESSED
) {
307 zlib_dict
+= certs
[i
];
311 zlib_dict
+= string(reinterpret_cast<const char*>(kCommonCertSubstrings
),
312 sizeof(kCommonCertSubstrings
));
314 DCHECK_EQ(zlib_dict
.size(), zlib_dict_size
);
319 // HashCerts returns the FNV-1a hashes of |certs|.
320 vector
<uint64
> HashCerts(const vector
<string
>& certs
) {
322 ret
.reserve(certs
.size());
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()));
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
;
344 out_entries
->clear();
352 const uint8 type_byte
= in
[0];
355 if (type_byte
== 0) {
359 entry
.type
= static_cast<CertEntry::Type
>(type_byte
);
361 switch (entry
.type
) {
362 case CertEntry::COMPRESSED
:
363 out_certs
->push_back(string());
365 case CertEntry::CACHED
: {
366 if (in
.size() < sizeof(uint64
)) {
369 memcpy(&entry
.hash
, in
.data(), sizeof(uint64
));
370 in
.remove_prefix(sizeof(uint64
));
372 if (cached_hashes
.size() != cached_certs
.size()) {
373 cached_hashes
= HashCerts(cached_certs
);
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
]);
388 case CertEntry::COMMON
: {
392 if (in
.size() < sizeof(uint64
) + sizeof(uint32
)) {
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
));
400 StringPiece cert
= common_sets
->GetCert(entry
.set_hash
, entry
.index
);
404 out_certs
->push_back(cert
.as_string());
410 out_entries
->push_back(entry
);
417 // ScopedZLib deals with the automatic destruction of a zlib context.
425 explicit ScopedZLib(Type type
) : z_(NULL
), type_(type
) {}
427 void reset(z_stream
* z
) {
442 if (type_
== DEFLATE
) {
454 } // anonymous namespace
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());
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();
473 size_t compressed_size
= 0;
475 ScopedZLib
scoped_z(ScopedZLib::DEFLATE
);
477 if (uncompressed_size
> 0) {
478 memset(&z
, 0, sizeof(z
));
479 int rv
= deflateInit(&z
, Z_DEFAULT_COMPRESSION
);
486 string zlib_dict
= ZlibDictForEntries(entries
, certs
);
488 rv
= deflateSetDictionary(&z
, reinterpret_cast<const uint8
*>(&zlib_dict
[0]),
495 compressed_size
= deflateBound(&z
, uncompressed_size
);
498 const size_t entries_size
= CertEntriesSize(entries
);
501 result
.resize(entries_size
+ (uncompressed_size
> 0 ? 4 : 0) +
504 uint8
* j
= reinterpret_cast<uint8
*>(&result
[0]);
505 SerializeCertEntries(j
, entries
);
508 if (uncompressed_size
== 0) {
512 uint32 uncompressed_size_32
= uncompressed_size
;
513 memcpy(j
, &uncompressed_size_32
, sizeof(uint32
));
519 z
.avail_out
= compressed_size
;
521 for (size_t i
= 0; i
< certs
.size(); i
++) {
522 if (entries
[i
].type
!= CertEntry::COMPRESSED
) {
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
);
531 DCHECK_EQ(0u, z
.avail_in
);
532 if (rv
!= Z_OK
|| z
.avail_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
);
541 DCHECK_EQ(0u, z
.avail_in
);
542 if (rv
!= Z_OK
|| z
.avail_in
) {
548 rv
= deflate(&z
, Z_FINISH
);
549 DCHECK_EQ(Z_STREAM_END
, rv
);
550 if (rv
!= Z_STREAM_END
) {
554 result
.resize(result
.size() - z
.avail_out
);
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
)) {
567 DCHECK_EQ(entries
.size(), out_certs
->size());
569 scoped_ptr
<uint8
[]> uncompressed_data
;
570 StringPiece uncompressed
;
573 if (in
.size() < sizeof(uint32
)) {
577 uint32 uncompressed_size
;
578 memcpy(&uncompressed_size
, in
.data(), sizeof(uncompressed_size
));
579 in
.remove_prefix(sizeof(uint32
));
581 if (uncompressed_size
> 128 * 1024) {
585 uncompressed_data
.reset(new uint8
[uncompressed_size
]);
587 ScopedZLib
scoped_z(ScopedZLib::INFLATE
);
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();
595 if (Z_OK
!= inflateInit(&z
)) {
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())) {
607 rv
= inflate(&z
, Z_FINISH
);
610 if (Z_STREAM_END
!= rv
|| z
.avail_out
> 0 || z
.avail_in
> 0) {
614 uncompressed
= StringPiece(reinterpret_cast<char*>(uncompressed_data
.get()),
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
)) {
625 memcpy(&cert_len
, uncompressed
.data(), sizeof(cert_len
));
626 uncompressed
.remove_prefix(sizeof(uint32
));
627 if (uncompressed
.size() < cert_len
) {
630 (*out_certs
)[i
] = uncompressed
.substr(0, cert_len
).as_string();
631 uncompressed
.remove_prefix(cert_len
);
633 case CertEntry::CACHED
:
634 case CertEntry::COMMON
:
639 if (!uncompressed
.empty()) {