Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(10)

Side by Side Diff: net/quic/crypto/cert_compressor.cc

Issue 2193073003: Move shared files in net/quic/ into net/quic/core/ (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: io_thread_unittest.cc Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/quic/crypto/cert_compressor.h ('k') | net/quic/crypto/cert_compressor_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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 <cstdint>
8 #include <memory>
9
10 #include "base/logging.h"
11 #include "net/quic/quic_utils.h"
12 #include "third_party/zlib/zlib.h"
13
14 using base::StringPiece;
15 using std::string;
16 using std::vector;
17
18 namespace net {
19
20 namespace {
21
22 // kCommonCertSubstrings contains ~1500 bytes of common certificate substrings
23 // in order to help zlib. This was generated via a fairly dumb algorithm from
24 // the Alexa Top 5000 set - we could probably do better.
25 static const unsigned char kCommonCertSubstrings[] = {
26 0x04, 0x02, 0x30, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04,
27 0x16, 0x30, 0x14, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03,
28 0x01, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x30,
29 0x5f, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x04, 0x01,
30 0x06, 0x06, 0x0b, 0x60, 0x86, 0x48, 0x01, 0x86, 0xfd, 0x6d, 0x01, 0x07,
31 0x17, 0x01, 0x30, 0x33, 0x20, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65,
32 0x64, 0x20, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e,
33 0x20, 0x53, 0x20, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x64, 0x31, 0x34,
34 0x20, 0x53, 0x53, 0x4c, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31,
35 0x32, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x53, 0x65, 0x72,
36 0x76, 0x65, 0x72, 0x20, 0x43, 0x41, 0x30, 0x2d, 0x61, 0x69, 0x61, 0x2e,
37 0x76, 0x65, 0x72, 0x69, 0x73, 0x69, 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d,
38 0x2f, 0x45, 0x2d, 0x63, 0x72, 0x6c, 0x2e, 0x76, 0x65, 0x72, 0x69, 0x73,
39 0x69, 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x45, 0x2e, 0x63, 0x65,
40 0x72, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
41 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x4a, 0x2e, 0x63,
42 0x6f, 0x6d, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73,
43 0x2f, 0x63, 0x70, 0x73, 0x20, 0x28, 0x63, 0x29, 0x30, 0x30, 0x09, 0x06,
44 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1d, 0x30, 0x0d,
45 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05,
46 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x7b, 0x30, 0x1d, 0x06, 0x03, 0x55,
47 0x1d, 0x0e, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
48 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01,
49 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xd2,
50 0x6f, 0x64, 0x6f, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x43, 0x2e,
51 0x63, 0x72, 0x6c, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16,
52 0x04, 0x14, 0xb4, 0x2e, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x73, 0x69,
53 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x72, 0x30, 0x0b, 0x06, 0x03,
54 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x01, 0x30, 0x0d, 0x06, 0x09,
55 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30,
56 0x81, 0xca, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
57 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x08,
58 0x13, 0x07, 0x41, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x61, 0x31, 0x13, 0x30,
59 0x11, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0a, 0x53, 0x63, 0x6f, 0x74,
60 0x74, 0x73, 0x64, 0x61, 0x6c, 0x65, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03,
61 0x55, 0x04, 0x0a, 0x13, 0x11, 0x47, 0x6f, 0x44, 0x61, 0x64, 0x64, 0x79,
62 0x2e, 0x63, 0x6f, 0x6d, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x33,
63 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2a, 0x68, 0x74, 0x74,
64 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63,
65 0x61, 0x74, 0x65, 0x73, 0x2e, 0x67, 0x6f, 0x64, 0x61, 0x64, 0x64, 0x79,
66 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74,
67 0x6f, 0x72, 0x79, 0x31, 0x30, 0x30, 0x2e, 0x06, 0x03, 0x55, 0x04, 0x03,
68 0x13, 0x27, 0x47, 0x6f, 0x20, 0x44, 0x61, 0x64, 0x64, 0x79, 0x20, 0x53,
69 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66,
70 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68,
71 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55,
72 0x04, 0x05, 0x13, 0x08, 0x30, 0x37, 0x39, 0x36, 0x39, 0x32, 0x38, 0x37,
73 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x31, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d,
74 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x0c,
75 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, 0x30, 0x00,
76 0x30, 0x1d, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
77 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55,
78 0x1d, 0x25, 0x04, 0x16, 0x30, 0x14, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05,
79 0x05, 0x07, 0x03, 0x01, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
80 0x03, 0x02, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff,
81 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x33, 0x06, 0x03, 0x55, 0x1d,
82 0x1f, 0x04, 0x2c, 0x30, 0x2a, 0x30, 0x28, 0xa0, 0x26, 0xa0, 0x24, 0x86,
83 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, 0x2e,
84 0x67, 0x6f, 0x64, 0x61, 0x64, 0x64, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
85 0x67, 0x64, 0x73, 0x31, 0x2d, 0x32, 0x30, 0x2a, 0x30, 0x28, 0x06, 0x08,
86 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, 0x16, 0x1c, 0x68, 0x74,
87 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x76, 0x65,
88 0x72, 0x69, 0x73, 0x69, 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63,
89 0x70, 0x73, 0x30, 0x34, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17,
90 0x0d, 0x31, 0x33, 0x30, 0x35, 0x30, 0x39, 0x06, 0x08, 0x2b, 0x06, 0x01,
91 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x2d, 0x68, 0x74, 0x74, 0x70, 0x3a,
92 0x2f, 0x2f, 0x73, 0x30, 0x39, 0x30, 0x37, 0x06, 0x08, 0x2b, 0x06, 0x01,
93 0x05, 0x05, 0x07, 0x02, 0x30, 0x44, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04,
94 0x3d, 0x30, 0x3b, 0x30, 0x39, 0x06, 0x0b, 0x60, 0x86, 0x48, 0x01, 0x86,
95 0xf8, 0x45, 0x01, 0x07, 0x17, 0x06, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
96 0x55, 0x04, 0x06, 0x13, 0x02, 0x47, 0x42, 0x31, 0x1b, 0x53, 0x31, 0x17,
97 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, 0x56, 0x65, 0x72,
98 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31,
99 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x16, 0x56, 0x65,
100 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74,
101 0x20, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x31, 0x3b, 0x30, 0x39,
102 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x32, 0x54, 0x65, 0x72, 0x6d, 0x73,
103 0x20, 0x6f, 0x66, 0x20, 0x75, 0x73, 0x65, 0x20, 0x61, 0x74, 0x20, 0x68,
104 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x76,
105 0x65, 0x72, 0x69, 0x73, 0x69, 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
106 0x72, 0x70, 0x61, 0x20, 0x28, 0x63, 0x29, 0x30, 0x31, 0x10, 0x30, 0x0e,
107 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x53, 0x31, 0x13, 0x30, 0x11,
108 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0a, 0x47, 0x31, 0x13, 0x30, 0x11,
109 0x06, 0x0b, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x3c, 0x02, 0x01,
110 0x03, 0x13, 0x02, 0x55, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04,
111 0x03, 0x14, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
112 0x31, 0x1d, 0x30, 0x1b, 0x06, 0x03, 0x55, 0x04, 0x0f, 0x13, 0x14, 0x50,
113 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x20, 0x4f, 0x72, 0x67, 0x61, 0x6e,
114 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x12, 0x31, 0x21, 0x30,
115 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x18, 0x44, 0x6f, 0x6d, 0x61,
116 0x69, 0x6e, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x20, 0x56,
117 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x64, 0x31, 0x14, 0x31, 0x31,
118 0x30, 0x2f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x28, 0x53, 0x65, 0x65,
119 0x20, 0x77, 0x77, 0x77, 0x2e, 0x72, 0x3a, 0x2f, 0x2f, 0x73, 0x65, 0x63,
120 0x75, 0x72, 0x65, 0x2e, 0x67, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x53,
121 0x69, 0x67, 0x6e, 0x31, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x41,
122 0x2e, 0x63, 0x72, 0x6c, 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e,
123 0x20, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x33, 0x20, 0x45, 0x63, 0x72,
124 0x6c, 0x2e, 0x67, 0x65, 0x6f, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x63,
125 0x6f, 0x6d, 0x2f, 0x63, 0x72, 0x6c, 0x73, 0x2f, 0x73, 0x64, 0x31, 0x1a,
126 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x68, 0x74, 0x74, 0x70, 0x3a,
127 0x2f, 0x2f, 0x45, 0x56, 0x49, 0x6e, 0x74, 0x6c, 0x2d, 0x63, 0x63, 0x72,
128 0x74, 0x2e, 0x67, 0x77, 0x77, 0x77, 0x2e, 0x67, 0x69, 0x63, 0x65, 0x72,
129 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x31, 0x6f, 0x63, 0x73, 0x70, 0x2e,
130 0x76, 0x65, 0x72, 0x69, 0x73, 0x69, 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d,
131 0x30, 0x39, 0x72, 0x61, 0x70, 0x69, 0x64, 0x73, 0x73, 0x6c, 0x2e, 0x63,
132 0x6f, 0x73, 0x2e, 0x67, 0x6f, 0x64, 0x61, 0x64, 0x64, 0x79, 0x2e, 0x63,
133 0x6f, 0x6d, 0x2f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72,
134 0x79, 0x2f, 0x30, 0x81, 0x80, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05,
135 0x07, 0x01, 0x01, 0x04, 0x74, 0x30, 0x72, 0x30, 0x24, 0x06, 0x08, 0x2b,
136 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x18, 0x68, 0x74, 0x74,
137 0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x2e, 0x67, 0x6f, 0x64,
138 0x61, 0x64, 0x64, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x30, 0x4a, 0x06,
139 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x3e, 0x68,
140 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66,
141 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x2e, 0x67, 0x6f, 0x64, 0x61, 0x64,
142 0x64, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x72, 0x65, 0x70, 0x6f, 0x73,
143 0x69, 0x74, 0x6f, 0x72, 0x79, 0x2f, 0x67, 0x64, 0x5f, 0x69, 0x6e, 0x74,
144 0x65, 0x72, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x2e, 0x63, 0x72,
145 0x74, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16,
146 0x80, 0x14, 0xfd, 0xac, 0x61, 0x32, 0x93, 0x6c, 0x45, 0xd6, 0xe2, 0xee,
147 0x85, 0x5f, 0x9a, 0xba, 0xe7, 0x76, 0x99, 0x68, 0xcc, 0xe7, 0x30, 0x27,
148 0x86, 0x29, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x86, 0x30,
149 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x73,
150 };
151
152 // CertEntry represents a certificate in compressed form. Each entry is one of
153 // the three types enumerated in |Type|.
154 struct CertEntry {
155 public:
156 enum Type {
157 // Type 0 is reserved to mean "end of list" in the wire format.
158
159 // COMPRESSED means that the certificate is included in the trailing zlib
160 // data.
161 COMPRESSED = 1,
162 // CACHED means that the certificate is already known to the peer and will
163 // be replaced by its 64-bit hash (in |hash|).
164 CACHED = 2,
165 // COMMON means that the certificate is in a common certificate set known
166 // to the peer with hash |set_hash| and certificate index |index|.
167 COMMON = 3,
168 };
169
170 Type type;
171 uint64_t hash;
172 uint64_t set_hash;
173 uint32_t index;
174 };
175
176 // MatchCerts returns a vector of CertEntries describing how to most
177 // efficiently represent |certs| to a peer who has the common sets identified
178 // by |client_common_set_hashes| and who has cached the certificates with the
179 // 64-bit, FNV-1a hashes in |client_cached_cert_hashes|.
180 vector<CertEntry> MatchCerts(const vector<string>& certs,
181 StringPiece client_common_set_hashes,
182 StringPiece client_cached_cert_hashes,
183 const CommonCertSets* common_sets) {
184 vector<CertEntry> entries;
185 entries.reserve(certs.size());
186
187 const bool cached_valid =
188 client_cached_cert_hashes.size() % sizeof(uint64_t) == 0 &&
189 !client_cached_cert_hashes.empty();
190
191 for (vector<string>::const_iterator i = certs.begin(); i != certs.end();
192 ++i) {
193 CertEntry entry;
194
195 if (cached_valid) {
196 bool cached = false;
197
198 uint64_t hash = QuicUtils::FNV1a_64_Hash(i->data(), i->size());
199 // This assumes that the machine is little-endian.
200 for (size_t j = 0; j < client_cached_cert_hashes.size();
201 j += sizeof(uint64_t)) {
202 uint64_t cached_hash;
203 memcpy(&cached_hash, client_cached_cert_hashes.data() + j,
204 sizeof(uint64_t));
205 if (hash != cached_hash) {
206 continue;
207 }
208
209 entry.type = CertEntry::CACHED;
210 entry.hash = hash;
211 entries.push_back(entry);
212 cached = true;
213 break;
214 }
215
216 if (cached) {
217 continue;
218 }
219 }
220
221 if (common_sets &&
222 common_sets->MatchCert(*i, client_common_set_hashes, &entry.set_hash,
223 &entry.index)) {
224 entry.type = CertEntry::COMMON;
225 entries.push_back(entry);
226 continue;
227 }
228
229 entry.type = CertEntry::COMPRESSED;
230 entries.push_back(entry);
231 }
232
233 return entries;
234 }
235
236 // CertEntriesSize returns the size, in bytes, of the serialised form of
237 // |entries|.
238 size_t CertEntriesSize(const vector<CertEntry>& entries) {
239 size_t entries_size = 0;
240
241 for (vector<CertEntry>::const_iterator i = entries.begin();
242 i != entries.end(); ++i) {
243 entries_size++;
244 switch (i->type) {
245 case CertEntry::COMPRESSED:
246 break;
247 case CertEntry::CACHED:
248 entries_size += sizeof(uint64_t);
249 break;
250 case CertEntry::COMMON:
251 entries_size += sizeof(uint64_t) + sizeof(uint32_t);
252 break;
253 }
254 }
255
256 entries_size++; // for end marker
257
258 return entries_size;
259 }
260
261 // SerializeCertEntries serialises |entries| to |out|, which must have enough
262 // space to contain them.
263 void SerializeCertEntries(uint8_t* out, const vector<CertEntry>& entries) {
264 for (vector<CertEntry>::const_iterator i = entries.begin();
265 i != entries.end(); ++i) {
266 *out++ = static_cast<uint8_t>(i->type);
267 switch (i->type) {
268 case CertEntry::COMPRESSED:
269 break;
270 case CertEntry::CACHED:
271 memcpy(out, &i->hash, sizeof(i->hash));
272 out += sizeof(uint64_t);
273 break;
274 case CertEntry::COMMON:
275 // Assumes a little-endian machine.
276 memcpy(out, &i->set_hash, sizeof(i->set_hash));
277 out += sizeof(i->set_hash);
278 memcpy(out, &i->index, sizeof(uint32_t));
279 out += sizeof(uint32_t);
280 break;
281 }
282 }
283
284 *out++ = 0; // end marker
285 }
286
287 // ZlibDictForEntries returns a string that contains the zlib pre-shared
288 // dictionary to use in order to decompress a zlib block following |entries|.
289 // |certs| is one-to-one with |entries| and contains the certificates for those
290 // entries that are CACHED or COMMON.
291 string ZlibDictForEntries(const vector<CertEntry>& entries,
292 const vector<string>& certs) {
293 string zlib_dict;
294
295 // The dictionary starts with the common and cached certs in reverse order.
296 size_t zlib_dict_size = 0;
297 for (size_t i = certs.size() - 1; i < certs.size(); i--) {
298 if (entries[i].type != CertEntry::COMPRESSED) {
299 zlib_dict_size += certs[i].size();
300 }
301 }
302
303 // At the end of the dictionary is a block of common certificate substrings.
304 zlib_dict_size += sizeof(kCommonCertSubstrings);
305
306 zlib_dict.reserve(zlib_dict_size);
307
308 for (size_t i = certs.size() - 1; i < certs.size(); i--) {
309 if (entries[i].type != CertEntry::COMPRESSED) {
310 zlib_dict += certs[i];
311 }
312 }
313
314 zlib_dict += string(reinterpret_cast<const char*>(kCommonCertSubstrings),
315 sizeof(kCommonCertSubstrings));
316
317 DCHECK_EQ(zlib_dict.size(), zlib_dict_size);
318
319 return zlib_dict;
320 }
321
322 // HashCerts returns the FNV-1a hashes of |certs|.
323 vector<uint64_t> HashCerts(const vector<string>& certs) {
324 vector<uint64_t> ret;
325 ret.reserve(certs.size());
326
327 for (vector<string>::const_iterator i = certs.begin(); i != certs.end();
328 ++i) {
329 ret.push_back(QuicUtils::FNV1a_64_Hash(i->data(), i->size()));
330 }
331
332 return ret;
333 }
334
335 // ParseEntries parses the serialised form of a vector of CertEntries from
336 // |in_out| and writes them to |out_entries|. CACHED and COMMON entries are
337 // resolved using |cached_certs| and |common_sets| and written to |out_certs|.
338 // |in_out| is updated to contain the trailing data.
339 bool ParseEntries(StringPiece* in_out,
340 const vector<string>& cached_certs,
341 const CommonCertSets* common_sets,
342 vector<CertEntry>* out_entries,
343 vector<string>* out_certs) {
344 StringPiece in = *in_out;
345 vector<uint64_t> cached_hashes;
346
347 out_entries->clear();
348 out_certs->clear();
349
350 for (;;) {
351 if (in.empty()) {
352 return false;
353 }
354 CertEntry entry;
355 const uint8_t type_byte = in[0];
356 in.remove_prefix(1);
357
358 if (type_byte == 0) {
359 break;
360 }
361
362 entry.type = static_cast<CertEntry::Type>(type_byte);
363
364 switch (entry.type) {
365 case CertEntry::COMPRESSED:
366 out_certs->push_back(string());
367 break;
368 case CertEntry::CACHED: {
369 if (in.size() < sizeof(uint64_t)) {
370 return false;
371 }
372 memcpy(&entry.hash, in.data(), sizeof(uint64_t));
373 in.remove_prefix(sizeof(uint64_t));
374
375 if (cached_hashes.size() != cached_certs.size()) {
376 cached_hashes = HashCerts(cached_certs);
377 }
378 bool found = false;
379 for (size_t i = 0; i < cached_hashes.size(); i++) {
380 if (cached_hashes[i] == entry.hash) {
381 out_certs->push_back(cached_certs[i]);
382 found = true;
383 break;
384 }
385 }
386 if (!found) {
387 return false;
388 }
389 break;
390 }
391 case CertEntry::COMMON: {
392 if (!common_sets) {
393 return false;
394 }
395 if (in.size() < sizeof(uint64_t) + sizeof(uint32_t)) {
396 return false;
397 }
398 memcpy(&entry.set_hash, in.data(), sizeof(uint64_t));
399 in.remove_prefix(sizeof(uint64_t));
400 memcpy(&entry.index, in.data(), sizeof(uint32_t));
401 in.remove_prefix(sizeof(uint32_t));
402
403 StringPiece cert = common_sets->GetCert(entry.set_hash, entry.index);
404 if (cert.empty()) {
405 return false;
406 }
407 out_certs->push_back(cert.as_string());
408 break;
409 }
410 default:
411 return false;
412 }
413 out_entries->push_back(entry);
414 }
415
416 *in_out = in;
417 return true;
418 }
419
420 // ScopedZLib deals with the automatic destruction of a zlib context.
421 class ScopedZLib {
422 public:
423 enum Type {
424 INFLATE,
425 DEFLATE,
426 };
427
428 explicit ScopedZLib(Type type) : z_(nullptr), type_(type) {}
429
430 void reset(z_stream* z) {
431 Clear();
432 z_ = z;
433 }
434
435 ~ScopedZLib() { Clear(); }
436
437 private:
438 void Clear() {
439 if (!z_) {
440 return;
441 }
442
443 if (type_ == DEFLATE) {
444 deflateEnd(z_);
445 } else {
446 inflateEnd(z_);
447 }
448 z_ = nullptr;
449 }
450
451 z_stream* z_;
452 const Type type_;
453 };
454
455 } // anonymous namespace
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_t 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(
489 &z, reinterpret_cast<const uint8_t*>(&zlib_dict[0]), 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_t* j = reinterpret_cast<uint8_t*>(&result[0]);
505 SerializeCertEntries(j, entries);
506 j += entries_size;
507
508 if (uncompressed_size == 0) {
509 return result;
510 }
511
512 uint32_t uncompressed_size_32 = uncompressed_size;
513 memcpy(j, &uncompressed_size_32, sizeof(uint32_t));
514 j += sizeof(uint32_t);
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_t length32 = certs[i].size();
527 z.next_in = reinterpret_cast<uint8_t*>(&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_t*>(reinterpret_cast<const uint8_t*>(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 std::unique_ptr<uint8_t[]> uncompressed_data;
570 StringPiece uncompressed;
571
572 if (!in.empty()) {
573 if (in.size() < sizeof(uint32_t)) {
574 return false;
575 }
576
577 uint32_t uncompressed_size;
578 memcpy(&uncompressed_size, in.data(), sizeof(uncompressed_size));
579 in.remove_prefix(sizeof(uint32_t));
580
581 if (uncompressed_size > 128 * 1024) {
582 return false;
583 }
584
585 uncompressed_data.reset(new uint8_t[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 =
593 const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(in.data()));
594 z.avail_in = in.size();
595
596 if (Z_OK != inflateInit(&z)) {
597 return false;
598 }
599 scoped_z.reset(&z);
600
601 int rv = inflate(&z, Z_FINISH);
602 if (rv == Z_NEED_DICT) {
603 string zlib_dict = ZlibDictForEntries(entries, *out_certs);
604 const uint8_t* dict = reinterpret_cast<const uint8_t*>(zlib_dict.data());
605 if (Z_OK != inflateSetDictionary(&z, dict, zlib_dict.size())) {
606 return false;
607 }
608 rv = inflate(&z, Z_FINISH);
609 }
610
611 if (Z_STREAM_END != rv || z.avail_out > 0 || z.avail_in > 0) {
612 return false;
613 }
614
615 uncompressed = StringPiece(reinterpret_cast<char*>(uncompressed_data.get()),
616 uncompressed_size);
617 }
618
619 for (size_t i = 0; i < entries.size(); i++) {
620 switch (entries[i].type) {
621 case CertEntry::COMPRESSED:
622 if (uncompressed.size() < sizeof(uint32_t)) {
623 return false;
624 }
625 uint32_t cert_len;
626 memcpy(&cert_len, uncompressed.data(), sizeof(cert_len));
627 uncompressed.remove_prefix(sizeof(uint32_t));
628 if (uncompressed.size() < cert_len) {
629 return false;
630 }
631 (*out_certs)[i] = uncompressed.substr(0, cert_len).as_string();
632 uncompressed.remove_prefix(cert_len);
633 break;
634 case CertEntry::CACHED:
635 case CertEntry::COMMON:
636 break;
637 }
638 }
639
640 if (!uncompressed.empty()) {
641 return false;
642 }
643
644 return true;
645 }
646
647 } // namespace net
OLDNEW
« no previous file with comments | « net/quic/crypto/cert_compressor.h ('k') | net/quic/crypto/cert_compressor_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698