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

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

Issue 14651009: Land Recent QUIC changes (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix integer constant is too large for 'unsigned long' type Created 7 years, 7 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 | Annotate | Revision Log
« 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 "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.
22 static unsigned char kCommonCertSubstrings[] = {
23 0x04, 0x02, 0x30, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04,
24 0x16, 0x30, 0x14, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03,
25 0x01, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x30,
26 0x5f, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x04, 0x01,
27 0x06, 0x06, 0x0b, 0x60, 0x86, 0x48, 0x01, 0x86, 0xfd, 0x6d, 0x01, 0x07,
28 0x17, 0x01, 0x30, 0x33, 0x20, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65,
29 0x64, 0x20, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e,
30 0x20, 0x53, 0x20, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x64, 0x31, 0x34,
31 0x20, 0x53, 0x53, 0x4c, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31,
32 0x32, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x53, 0x65, 0x72,
33 0x76, 0x65, 0x72, 0x20, 0x43, 0x41, 0x30, 0x2d, 0x61, 0x69, 0x61, 0x2e,
34 0x76, 0x65, 0x72, 0x69, 0x73, 0x69, 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d,
35 0x2f, 0x45, 0x2d, 0x63, 0x72, 0x6c, 0x2e, 0x76, 0x65, 0x72, 0x69, 0x73,
36 0x69, 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x45, 0x2e, 0x63, 0x65,
37 0x72, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
38 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x4a, 0x2e, 0x63,
39 0x6f, 0x6d, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73,
40 0x2f, 0x63, 0x70, 0x73, 0x20, 0x28, 0x63, 0x29, 0x30, 0x30, 0x09, 0x06,
41 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1d, 0x30, 0x0d,
42 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05,
43 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x7b, 0x30, 0x1d, 0x06, 0x03, 0x55,
44 0x1d, 0x0e, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
45 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01,
46 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xd2,
47 0x6f, 0x64, 0x6f, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x43, 0x2e,
48 0x63, 0x72, 0x6c, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16,
49 0x04, 0x14, 0xb4, 0x2e, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x73, 0x69,
50 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x72, 0x30, 0x0b, 0x06, 0x03,
51 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x01, 0x30, 0x0d, 0x06, 0x09,
52 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30,
53 0x81, 0xca, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
54 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x08,
55 0x13, 0x07, 0x41, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x61, 0x31, 0x13, 0x30,
56 0x11, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0a, 0x53, 0x63, 0x6f, 0x74,
57 0x74, 0x73, 0x64, 0x61, 0x6c, 0x65, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03,
58 0x55, 0x04, 0x0a, 0x13, 0x11, 0x47, 0x6f, 0x44, 0x61, 0x64, 0x64, 0x79,
59 0x2e, 0x63, 0x6f, 0x6d, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x33,
60 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2a, 0x68, 0x74, 0x74,
61 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63,
62 0x61, 0x74, 0x65, 0x73, 0x2e, 0x67, 0x6f, 0x64, 0x61, 0x64, 0x64, 0x79,
63 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74,
64 0x6f, 0x72, 0x79, 0x31, 0x30, 0x30, 0x2e, 0x06, 0x03, 0x55, 0x04, 0x03,
65 0x13, 0x27, 0x47, 0x6f, 0x20, 0x44, 0x61, 0x64, 0x64, 0x79, 0x20, 0x53,
66 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66,
67 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68,
68 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55,
69 0x04, 0x05, 0x13, 0x08, 0x30, 0x37, 0x39, 0x36, 0x39, 0x32, 0x38, 0x37,
70 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x31, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d,
71 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x0c,
72 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, 0x30, 0x00,
73 0x30, 0x1d, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
74 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55,
75 0x1d, 0x25, 0x04, 0x16, 0x30, 0x14, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05,
76 0x05, 0x07, 0x03, 0x01, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
77 0x03, 0x02, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff,
78 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x33, 0x06, 0x03, 0x55, 0x1d,
79 0x1f, 0x04, 0x2c, 0x30, 0x2a, 0x30, 0x28, 0xa0, 0x26, 0xa0, 0x24, 0x86,
80 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, 0x2e,
81 0x67, 0x6f, 0x64, 0x61, 0x64, 0x64, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
82 0x67, 0x64, 0x73, 0x31, 0x2d, 0x32, 0x30, 0x2a, 0x30, 0x28, 0x06, 0x08,
83 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, 0x16, 0x1c, 0x68, 0x74,
84 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x76, 0x65,
85 0x72, 0x69, 0x73, 0x69, 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63,
86 0x70, 0x73, 0x30, 0x34, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17,
87 0x0d, 0x31, 0x33, 0x30, 0x35, 0x30, 0x39, 0x06, 0x08, 0x2b, 0x06, 0x01,
88 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x2d, 0x68, 0x74, 0x74, 0x70, 0x3a,
89 0x2f, 0x2f, 0x73, 0x30, 0x39, 0x30, 0x37, 0x06, 0x08, 0x2b, 0x06, 0x01,
90 0x05, 0x05, 0x07, 0x02, 0x30, 0x44, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04,
91 0x3d, 0x30, 0x3b, 0x30, 0x39, 0x06, 0x0b, 0x60, 0x86, 0x48, 0x01, 0x86,
92 0xf8, 0x45, 0x01, 0x07, 0x17, 0x06, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
93 0x55, 0x04, 0x06, 0x13, 0x02, 0x47, 0x42, 0x31, 0x1b, 0x53, 0x31, 0x17,
94 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, 0x56, 0x65, 0x72,
95 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31,
96 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x16, 0x56, 0x65,
97 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74,
98 0x20, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x31, 0x3b, 0x30, 0x39,
99 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x32, 0x54, 0x65, 0x72, 0x6d, 0x73,
100 0x20, 0x6f, 0x66, 0x20, 0x75, 0x73, 0x65, 0x20, 0x61, 0x74, 0x20, 0x68,
101 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x76,
102 0x65, 0x72, 0x69, 0x73, 0x69, 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
103 0x72, 0x70, 0x61, 0x20, 0x28, 0x63, 0x29, 0x30, 0x31, 0x10, 0x30, 0x0e,
104 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x53, 0x31, 0x13, 0x30, 0x11,
105 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0a, 0x47, 0x31, 0x13, 0x30, 0x11,
106 0x06, 0x0b, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x3c, 0x02, 0x01,
107 0x03, 0x13, 0x02, 0x55, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04,
108 0x03, 0x14, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
109 0x31, 0x1d, 0x30, 0x1b, 0x06, 0x03, 0x55, 0x04, 0x0f, 0x13, 0x14, 0x50,
110 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x20, 0x4f, 0x72, 0x67, 0x61, 0x6e,
111 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x12, 0x31, 0x21, 0x30,
112 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x18, 0x44, 0x6f, 0x6d, 0x61,
113 0x69, 0x6e, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x20, 0x56,
114 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x64, 0x31, 0x14, 0x31, 0x31,
115 0x30, 0x2f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x28, 0x53, 0x65, 0x65,
116 0x20, 0x77, 0x77, 0x77, 0x2e, 0x72, 0x3a, 0x2f, 0x2f, 0x73, 0x65, 0x63,
117 0x75, 0x72, 0x65, 0x2e, 0x67, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x53,
118 0x69, 0x67, 0x6e, 0x31, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x41,
119 0x2e, 0x63, 0x72, 0x6c, 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e,
120 0x20, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x33, 0x20, 0x45, 0x63, 0x72,
121 0x6c, 0x2e, 0x67, 0x65, 0x6f, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x63,
122 0x6f, 0x6d, 0x2f, 0x63, 0x72, 0x6c, 0x73, 0x2f, 0x73, 0x64, 0x31, 0x1a,
123 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x68, 0x74, 0x74, 0x70, 0x3a,
124 0x2f, 0x2f, 0x45, 0x56, 0x49, 0x6e, 0x74, 0x6c, 0x2d, 0x63, 0x63, 0x72,
125 0x74, 0x2e, 0x67, 0x77, 0x77, 0x77, 0x2e, 0x67, 0x69, 0x63, 0x65, 0x72,
126 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x31, 0x6f, 0x63, 0x73, 0x70, 0x2e,
127 0x76, 0x65, 0x72, 0x69, 0x73, 0x69, 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d,
128 0x30, 0x39, 0x72, 0x61, 0x70, 0x69, 0x64, 0x73, 0x73, 0x6c, 0x2e, 0x63,
129 0x6f, 0x73, 0x2e, 0x67, 0x6f, 0x64, 0x61, 0x64, 0x64, 0x79, 0x2e, 0x63,
130 0x6f, 0x6d, 0x2f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72,
131 0x79, 0x2f, 0x30, 0x81, 0x80, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05,
132 0x07, 0x01, 0x01, 0x04, 0x74, 0x30, 0x72, 0x30, 0x24, 0x06, 0x08, 0x2b,
133 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x18, 0x68, 0x74, 0x74,
134 0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x2e, 0x67, 0x6f, 0x64,
135 0x61, 0x64, 0x64, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x30, 0x4a, 0x06,
136 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x3e, 0x68,
137 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66,
138 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x2e, 0x67, 0x6f, 0x64, 0x61, 0x64,
139 0x64, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x72, 0x65, 0x70, 0x6f, 0x73,
140 0x69, 0x74, 0x6f, 0x72, 0x79, 0x2f, 0x67, 0x64, 0x5f, 0x69, 0x6e, 0x74,
141 0x65, 0x72, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x2e, 0x63, 0x72,
142 0x74, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16,
143 0x80, 0x14, 0xfd, 0xac, 0x61, 0x32, 0x93, 0x6c, 0x45, 0xd6, 0xe2, 0xee,
144 0x85, 0x5f, 0x9a, 0xba, 0xe7, 0x76, 0x99, 0x68, 0xcc, 0xe7, 0x30, 0x27,
145 0x86, 0x29, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x86, 0x30,
146 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x73,
147 };
148
149 // CertEntry represents a certificate in compressed form. Each entry is one of
150 // the three types enumerated in |Type|.
151 struct CertEntry {
152 public:
153 enum Type {
154 // COMPRESSED means that the certificate is included in the trailing zlib
155 // data.
156 COMPRESSED = 1,
157 // CACHED means that the certificate is already known to the peer and will
158 // be replaced by its 64-bit hash (in |hash|).
159 CACHED = 2,
160 // COMMON means that the certificate is in a common certificate set known
161 // to the peer with hash |set_hash| and index |index|.
162 COMMON = 3,
163 };
164
165 Type type;
166 uint64 hash;
167 uint64 set_hash;
168 uint32 index;
169 };
170
171 // MatchCerts returns a vector of CertEntries describing how to most
172 // efficiently represent |certs| to a peer who has the common sets identified
173 // by |client_common_set_hashes| and who has cached the certificates with the
174 // 64-bit, FNV-1a hashes in |client_cached|.
175 vector<CertEntry> MatchCerts(const vector<string>& certs,
176 StringPiece client_common_set_hashes,
177 StringPiece client_cached,
178 CommonCertSet* common_set) {
179 vector<CertEntry> entries;
180 entries.reserve(certs.size());
181
182 const bool cached_valid = client_cached.size() % sizeof(uint64) == 0 &&
183 !client_cached.empty();
184
185 for (vector<string>::const_iterator i = certs.begin();
186 i != certs.end(); ++i) {
187 CertEntry entry;
188
189 if (cached_valid) {
190 bool cached = false;
191
192 uint64 hash = QuicUtils::FNV1a_64_Hash(i->data(), i->size());
193 // This assumes that the machine is little-endian.
194 for (size_t i = 0; i < client_cached.size(); i += sizeof(uint64)) {
195 uint64 cached_hash;
196 memcpy(&cached_hash, client_cached.data() + i, sizeof(uint64));
197 if (hash != cached_hash) {
198 continue;
199 }
200
201 entry.type = CertEntry::CACHED;
202 entry.hash = hash;
203 entries.push_back(entry);
204 cached = true;
205 break;
206 }
207
208 if (cached) {
209 continue;
210 }
211 }
212
213 if (common_set &&
214 common_set->MatchCert(*i, client_common_set_hashes, &entry.set_hash,
215 &entry.index)) {
216 entry.type = CertEntry::COMMON;
217 entries.push_back(entry);
218 continue;
219 }
220
221 entry.type = CertEntry::COMPRESSED;
222 entries.push_back(entry);
223 }
224
225 return entries;
226 }
227
228 // CertEntriesSize returns the size, in bytes, of the serialised form of
229 // |entries|.
230 size_t CertEntriesSize(const vector<CertEntry>& entries) {
231 size_t entries_size = 0;
232
233 for (vector<CertEntry>::const_iterator i = entries.begin();
234 i != entries.end(); ++i) {
235 switch (i->type) {
236 case CertEntry::COMPRESSED:
237 entries_size++;
238 break;
239 case CertEntry::CACHED:
240 entries_size += 1 + sizeof(uint64);
241 break;
242 case CertEntry::COMMON:
243 entries_size += 1 + sizeof(uint64) + sizeof(uint32);
244 break;
245 }
246 }
247
248 entries_size++; // for end marker
249
250 return entries_size;
251 }
252
253 // SerializeCertEntries serialises |entries| to |out|, which must have enough
254 // space to contain them.
255 void SerializeCertEntries(uint8* out, const vector<CertEntry>& entries) {
256 for (vector<CertEntry>::const_iterator i = entries.begin();
257 i != entries.end(); ++i) {
258 *out++ = i->type;
259 switch (i->type) {
260 case CertEntry::COMPRESSED:
261 break;
262 case CertEntry::CACHED:
263 memcpy(out, &i->hash, sizeof(i->hash));
264 out += sizeof(uint64);
265 break;
266 case CertEntry::COMMON:
267 // Assumes a little-endian machine.
268 memcpy(out, &i->set_hash, sizeof(i->set_hash));
269 out += sizeof(i->set_hash);
270 memcpy(out, &i->index, sizeof(uint32));
271 out += sizeof(uint32);
272 break;
273 }
274 }
275
276 *out++ = 0; // end marker
277 }
278
279 // ZlibDictForEntries returns a string that contains the zlib pre-shared
280 // dictionary to use in order to decompress a zlib block following |entries|.
281 // |certs| is one-to-one with |entries| and contains the certificates for those
282 // entries that are CACHED or COMMON.
283 string ZlibDictForEntries(const vector<CertEntry>& entries,
284 const vector<string>& certs) {
285 string zlib_dict;
286
287 // The dictionary starts with the common and cached certs in reverse order.
288 size_t zlib_dict_size = 0;
289 for (size_t i = certs.size() - 1; i < certs.size(); i--) {
290 if (entries[i].type != CertEntry::COMPRESSED) {
291 zlib_dict_size += certs[i].size();
292 }
293 }
294
295 // At the end of the dictionary is a block of common certificate substrings.
296 zlib_dict_size += sizeof(kCommonCertSubstrings);
297
298 zlib_dict.reserve(zlib_dict_size);
299
300 for (size_t i = certs.size() - 1; i < certs.size(); i--) {
301 if (entries[i].type != CertEntry::COMPRESSED) {
302 zlib_dict += certs[i];
303 }
304 }
305
306 zlib_dict += string(reinterpret_cast<const char*>(kCommonCertSubstrings),
307 sizeof(kCommonCertSubstrings));
308
309 DCHECK_EQ(zlib_dict.size(), zlib_dict_size);
310
311 return zlib_dict;
312 }
313
314 // HashCerts returns the FNV-1a hashes of |certs|.
315 vector<uint64> HashCerts(const vector<string>& certs) {
316 vector<uint64> ret;
317
318 for (vector<string>::const_iterator i = certs.begin();
319 i != certs.end(); ++i) {
320 ret.push_back(QuicUtils::FNV1a_64_Hash(i->data(), i->size()));
321 }
322
323 return ret;
324 }
325
326 // ParseEntries parses the serialised form of a vector of CertEntries from
327 // |in_out| and writes them to |out_entries|. CACHED and COMMON entries are
328 // resolved using |cached_certs| and |common_set| and written to |out_certs|.
329 // |in_out| is updated to contain the trailing data.
330 bool ParseEntries(StringPiece* in_out,
331 const vector<string>& cached_certs,
332 CommonCertSet* common_set,
333 vector<CertEntry>* out_entries,
334 vector<string>* out_certs) {
335 StringPiece in = *in_out;
336 vector<uint64> cached_hashes;
337
338 out_entries->clear();
339 out_certs->clear();
340
341 for (;;) {
342 if (in.empty()) {
343 return false;
344 }
345 CertEntry entry;
346 const uint8 type_byte = in[0];
347 in.remove_prefix(1);
348
349 if (type_byte == 0) {
350 break;
351 }
352
353 entry.type = static_cast<CertEntry::Type>(type_byte);
354
355 switch (entry.type) {
356 case CertEntry::COMPRESSED:
357 out_certs->push_back(string());
358 break;
359 case CertEntry::CACHED: {
360 if (in.size() < sizeof(uint64)) {
361 return false;
362 }
363 memcpy(&entry.hash, in.data(), sizeof(uint64));
364 in.remove_prefix(sizeof(uint64));
365
366 if (cached_hashes.size() != cached_certs.size()) {
367 cached_hashes = HashCerts(cached_certs);
368 }
369 bool found = false;
370 for (size_t i = 0; i < cached_hashes.size(); i++) {
371 if (cached_hashes[i] == entry.hash) {
372 out_certs->push_back(cached_certs[i]);
373 found = true;
374 break;
375 }
376 }
377 if (!found) {
378 return false;
379 }
380 break;
381 }
382 case CertEntry::COMMON: {
383 if (!common_set) {
384 return false;
385 }
386 if (in.size() < sizeof(uint64)) {
387 return false;
388 }
389 memcpy(&entry.set_hash, in.data(), sizeof(uint64));
390 in.remove_prefix(sizeof(uint64));
391
392 if (in.size() < sizeof(uint32)) {
393 return false;
394 }
395 memcpy(&entry.index, in.data(), sizeof(uint32));
396 in.remove_prefix(sizeof(uint32));
397
398 StringPiece cert = common_set->GetCert(entry.set_hash, entry.index);
399 if (cert.empty()) {
400 return false;
401 }
402 out_certs->push_back(cert.as_string());
403 break;
404 }
405 default:
406 return false;
407 }
408 out_entries->push_back(entry);
409 }
410
411 *in_out = in;
412 return true;
413 }
414
415 class ScopedZLib {
416 public:
417 enum Type {
418 INFLATE,
419 DEFLATE,
420 };
421
422 explicit ScopedZLib(Type type)
423 : z_(NULL),
424 type_(type) {
425 }
426
427 void reset(z_stream* z) {
428 z_ = z;
429 }
430
431 ~ScopedZLib() {
432 if (z_) {
433 if (type_ == DEFLATE) {
434 deflateEnd(z_);
435 } else {
436 inflateEnd(z_);
437 }
438 z_ = NULL;
439 }
440 }
441
442 private:
443 z_stream* z_;
444 const Type type_;
445 };
446
447 } // anonymous namespace
448
449
450 // static
451 string CertCompressor::CompressChain(const vector<string>& certs,
452 StringPiece client_common_set_hashes,
453 StringPiece client_cached,
454 CommonCertSet* common_set) {
455 const vector<CertEntry> entries = MatchCerts(
456 certs, client_common_set_hashes, client_cached, common_set);
457 DCHECK_EQ(entries.size(), certs.size());
458
459 size_t uncompressed_size = 0;
460 for (size_t i = 0; i < entries.size(); i++) {
461 if (entries[i].type == CertEntry::COMPRESSED) {
462 uncompressed_size += 4 /* uint32 length */ + certs[i].size();
463 }
464 }
465
466 size_t compressed_size = 0;
467 z_stream z;
468 ScopedZLib scoped_z(ScopedZLib::DEFLATE);
469
470 if (uncompressed_size > 0) {
471 memset(&z, 0, sizeof(z));
472 int rv = deflateInit(&z, Z_DEFAULT_COMPRESSION);
473 DCHECK_EQ(Z_OK, rv);
474 if (rv != Z_OK) {
475 return "";
476 }
477 scoped_z.reset(&z);
478
479 string zlib_dict = ZlibDictForEntries(entries, certs);
480
481 rv = deflateSetDictionary(&z, reinterpret_cast<const uint8*>(&zlib_dict[0]),
482 zlib_dict.size());
483 DCHECK_EQ(Z_OK, rv);
484 if (rv != Z_OK) {
485 return "";
486 }
487
488 compressed_size = deflateBound(&z, uncompressed_size);
489 }
490
491 const size_t entries_size = CertEntriesSize(entries);
492
493 string result;
494 result.resize(entries_size + (uncompressed_size > 0 ? 4 : 0) +
495 compressed_size);
496
497 uint8* j = reinterpret_cast<uint8*>(&result[0]);
498 SerializeCertEntries(j, entries);
499 j += entries_size;
500
501 if (uncompressed_size == 0) {
502 return result;
503 }
504
505 uint32 uncompressed_size_32 = uncompressed_size;
506 memcpy(j, &uncompressed_size_32, sizeof(uint32));
507 j += sizeof(uint32);
508
509 int rv;
510
511 z.next_out = j;
512 z.avail_out = compressed_size;
513
514 for (size_t i = 0; i < certs.size(); i++) {
515 if (entries[i].type != CertEntry::COMPRESSED) {
516 continue;
517 }
518
519 uint32 length = certs[i].size();
520 z.next_in = reinterpret_cast<uint8*>(&length);
521 z.avail_in = sizeof(length);
522 rv = deflate(&z, Z_NO_FLUSH);
523 DCHECK_EQ(Z_OK, rv);
524 DCHECK_EQ(0u, z.avail_in);
525 if (rv != Z_OK || z.avail_in) {
526 return "";
527 }
528
529 z.next_in =
530 const_cast<uint8*>(reinterpret_cast<const uint8*>(certs[i].data()));
531 z.avail_in = certs[i].size();
532 rv = deflate(&z, Z_NO_FLUSH);
533 DCHECK_EQ(Z_OK, rv);
534 DCHECK_EQ(0u, z.avail_in);
535 if (rv != Z_OK || z.avail_in) {
536 return "";
537 }
538 }
539
540 z.avail_in = 0;
541 rv = deflate(&z, Z_FINISH);
542 DCHECK_EQ(Z_STREAM_END, rv);
543 if (rv != Z_STREAM_END) {
544 return "";
545 }
546
547 result.resize(result.size() - z.avail_out);
548 return result;
549 }
550
551 // static
552 bool CertCompressor::DecompressChain(StringPiece in,
553 const vector<string>& cached_certs,
554 CommonCertSet* common_set,
555 vector<string>* out_certs) {
556 vector<CertEntry> entries;
557 if (!ParseEntries(&in, cached_certs, common_set, &entries, out_certs)) {
558 return false;
559 }
560 DCHECK_EQ(entries.size(), out_certs->size());
561
562 scoped_ptr<uint8[]> uncompressed_data;
563 StringPiece uncompressed;
564
565 if (!in.empty()) {
566 if (in.size() < sizeof(uint32)) {
567 return false;
568 }
569
570 uint32 uncompressed_size;
571 memcpy(&uncompressed_size, in.data(), sizeof(uncompressed_size));
572 in.remove_prefix(sizeof(uint32));
573
574 if (uncompressed_size > 128 * 1024) {
575 return false;
576 }
577
578 uncompressed_data.reset(new uint8[uncompressed_size]);
579 z_stream z;
580 ScopedZLib scoped_z(ScopedZLib::INFLATE);
581
582 memset(&z, 0, sizeof(z));
583 z.next_out = uncompressed_data.get();
584 z.avail_out = uncompressed_size;
585 z.next_in = const_cast<uint8*>(reinterpret_cast<const uint8*>(in.data()));
586 z.avail_in = in.size();
587
588 if (Z_OK != inflateInit(&z)) {
589 return false;
590 }
591 scoped_z.reset(&z);
592
593 int rv = inflate(&z, Z_FINISH);
594 if (rv == Z_NEED_DICT) {
595 string zlib_dict = ZlibDictForEntries(entries, *out_certs);
596 const uint8* dict = reinterpret_cast<const uint8*>(zlib_dict.data());
597 if (Z_OK != inflateSetDictionary(&z, dict, zlib_dict.size())) {
598 return false;
599 }
600 rv = inflate(&z, Z_FINISH);
601 }
602
603 if (Z_STREAM_END != rv ||
604 z.avail_out > 0 ||
605 z.avail_in > 0) {
606 return false;
607 }
608
609 uncompressed = StringPiece(reinterpret_cast<char*>(uncompressed_data.get()),
610 uncompressed_size);
611 }
612
613 for (size_t i = 0; i < entries.size(); i++) {
614 switch (entries[i].type) {
615 case CertEntry::COMPRESSED:
616 if (uncompressed.size() < sizeof(uint32)) {
617 return false;
618 }
619 uint32 cert_len;
620 memcpy(&cert_len, uncompressed.data(), sizeof(cert_len));
621 uncompressed.remove_prefix(sizeof(uint32));
622 if (uncompressed.size() < cert_len) {
623 return false;
624 }
625 (*out_certs)[i] = uncompressed.substr(0, cert_len).as_string();
626 uncompressed.remove_prefix(cert_len);
627 break;
628 case CertEntry::CACHED:
629 case CertEntry::COMMON:
630 break;
631 }
632 }
633
634 if (!uncompressed.empty()) {
635 return false;
636 }
637
638 return true;
639 }
640
641 } // 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