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|.
MatchCerts(const vector<string> & certs,StringPiece client_common_set_hashes,StringPiece client_cached_cert_hashes,const CommonCertSets * common_sets)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|.
CertEntriesSize(const vector<CertEntry> & 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.
SerializeCertEntries(uint8 * out,const vector<CertEntry> & entries)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.
ZlibDictForEntries(const vector<CertEntry> & entries,const vector<string> & certs)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|.
HashCerts(const vector<string> & 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.
ParseEntries(StringPiece * in_out,const vector<string> & cached_certs,const CommonCertSets * common_sets,vector<CertEntry> * out_entries,vector<string> * out_certs)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
ScopedZLib(Type type)425 explicit ScopedZLib(Type type) : z_(NULL), type_(type) {}
426
reset(z_stream * z)427 void reset(z_stream* z) {
428 Clear();
429 z_ = z;
430 }
431
~ScopedZLib()432 ~ScopedZLib() {
433 Clear();
434 }
435
436 private:
Clear()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
CompressChain(const vector<string> & certs,StringPiece client_common_set_hashes,StringPiece client_cached_cert_hashes,const CommonCertSets * common_sets)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
DecompressChain(StringPiece in,const vector<string> & cached_certs,const CommonCertSets * common_sets,vector<string> * out_certs)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