- add sources.
[platform/framework/web/crosswalk.git] / src / net / quic / crypto / cert_compressor.cc
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|.
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|.
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.
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.
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|.
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.
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
425   explicit ScopedZLib(Type type) : z_(NULL), type_(type) {}
426
427   void reset(z_stream* z) {
428     Clear();
429     z_ = z;
430   }
431
432   ~ScopedZLib() {
433     Clear();
434   }
435
436  private:
437   void Clear() {
438     if (!z_) {
439       return;
440     }
441
442     if (type_ == DEFLATE) {
443       deflateEnd(z_);
444     } else {
445       inflateEnd(z_);
446     }
447     z_ = NULL;
448   }
449
450   z_stream* z_;
451   const Type type_;
452 };
453
454 }  // anonymous namespace
455
456
457 // static
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
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