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

Side by Side Diff: net/extras/cert/cert_verifier_cache_persister.cc

Issue 2021433004: Cert - protobufs to serialize and deserialize CertVerifierCache. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@Add_support_for_walking_1999733002
Patch Set: Added histogram for cache size Created 4 years, 6 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
OLDNEW
(Empty)
1 // Copyright (c) 2016 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/extras/cert/cert_verifier_cache_persister.h"
6
7 #include "base/logging.h"
8 #include "base/metrics/histogram_macros.h"
9 #include "base/pickle.h"
10 #include "base/strings/string_piece.h"
11 #include "base/time/time.h"
12 #include "net/base/hash_value.h"
13 #include "net/cert/caching_cert_verifier.h"
14 #include "net/cert/cert_type.h"
15 #include "net/cert/cert_verify_result.h"
16 #include "net/cert/x509_cert_types.h"
17 #include "net/cert/x509_certificate.h"
18 #include "net/extras/cert/proto/cert_verification.pb.h"
19
20 namespace net {
21
22 namespace {
23
24 bool SerializeCertHandle(
25 const X509Certificate::OSCertHandle& cert_handle,
26 CertVerifierCachePersister::CertVector* serialized_certs,
27 size_t* cert_number) {
28 std::string encoded;
29 if (!X509Certificate::GetDEREncoded(cert_handle, &encoded)) {
30 DCHECK(false);
31 return false;
32 }
33 const auto& it =
34 std::find(serialized_certs->begin(), serialized_certs->end(), encoded);
Ryan Sleevi 2016/05/30 18:37:18 EFFICIENCY: These |encoded| strings are going to b
ramant (doing other things) 2016/06/01 16:29:21 Done.
35 if (it != serialized_certs->end()) {
36 *cert_number =
37 static_cast<size_t>(std::distance(serialized_certs->begin(), it));
38 } else {
39 serialized_certs->push_back(encoded);
40 *cert_number = serialized_certs->size() - 1;
41 }
42 return true;
43 }
44
45 // Update |proto_certificate| with certificate number and updates
46 // |serialized_certs|
47 // with DER-encoded representation of certificate if the certicate is not in
48 // |serialized_certs|. Returns true if data is serialized correctly.
49 bool SerializeCertificate(
50 const scoped_refptr<X509Certificate>& certificate,
51 CertVerifierCachePersister::CertVector* serialized_certs,
52 CertVerificationCertificate* proto_certificate) {
53 size_t cert_number = 0;
54 if (!SerializeCertHandle(certificate->os_cert_handle(), serialized_certs,
55 &cert_number)) {
56 DCHECK(false);
57 return false;
58 }
59 proto_certificate->add_cert_numbers(cert_number);
60 const X509Certificate::X509Certificate::OSCertHandles& intermediate_ca_certs =
61 certificate->GetIntermediateCertificates();
62 for (size_t i = 0; i < intermediate_ca_certs.size(); ++i) {
63 if (!SerializeCertHandle(intermediate_ca_certs[i], serialized_certs,
64 &cert_number)) {
65 DCHECK(false);
66 return false;
67 }
68 proto_certificate->add_cert_numbers(cert_number);
69 }
70 return true;
71 }
72
73 // Returns deserialized certificate with the deserialized data from
74 // |proto_certificate|.
75 scoped_refptr<X509Certificate> DeserializeCertificate(
76 const CertVerificationCertificate& proto_certificate,
77 const CertVerifierCachePersister::CertVector& deserialized_der_certs) {
78 std::vector<base::StringPiece> der_cert_pieces(
79 proto_certificate.cert_numbers_size());
80 for (int i = 0; i < proto_certificate.cert_numbers_size(); i++) {
81 size_t cert_number = proto_certificate.cert_numbers(i);
82 CHECK_LT(cert_number, deserialized_der_certs.size());
83 der_cert_pieces[i] = base::StringPiece(deserialized_der_certs[cert_number]);
84 }
85 return X509Certificate::CreateFromDERCertChain(der_cert_pieces);
86 }
87
88 // Update |proto_request_param| with RequestParams data from |params|.
89 bool SerializeRequestParams(
90 const CertVerifier::RequestParams& params,
91 CertVerifierCachePersister::CertVector* serialized_certs,
92 CertVerificationRequestParams* proto_request_param) {
93 CertVerificationCertificate* proto_certificate =
94 proto_request_param->mutable_certificate();
95 if (!SerializeCertificate(params.certificate(), serialized_certs,
96 proto_certificate)) {
97 DCHECK(false);
98 return false;
99 }
100 proto_request_param->set_hostname(params.hostname());
101 proto_request_param->set_flags(params.flags());
102 proto_request_param->set_ocsp_response(params.ocsp_response());
103 for (const scoped_refptr<X509Certificate>& cert :
104 params.additional_trust_anchors()) {
105 proto_certificate = proto_request_param->add_additional_trust_anchors();
106 if (!SerializeCertificate(cert, serialized_certs, proto_certificate)) {
107 DCHECK(false);
108 return false;
109 }
110 }
111 return true;
112 }
113
114 // Update |proto_cached_result| with CachedResult data from |cache_iterator|.
115 // |serialized_certs| contains a list of unique DER-encoded representation of
116 // certificates.
117 bool SerializeCachedResult(
118 CachingCertVerifier::Iterator& cache_iterator,
119 CertVerifierCachePersister::CertVector* serialized_certs,
120 CertVerificationCachedResult* proto_cached_result) {
121 proto_cached_result->set_error(cache_iterator.error());
122
123 // Serialize CertVerifyResult.
124 const CertVerifyResult& result = cache_iterator.verify_result();
125
126 CertVerificationResult* proto_result = proto_cached_result->mutable_result();
127 CertVerificationCertificate* proto_certificate =
128 proto_result->mutable_verified_cert();
129 if (!SerializeCertificate(result.verified_cert, serialized_certs,
130 proto_certificate)) {
131 DCHECK(false);
132 return false;
133 }
134 proto_result->set_cert_status(result.cert_status);
135 proto_result->set_has_md2(result.has_md2);
136 proto_result->set_has_md4(result.has_md4);
137 proto_result->set_has_md5(result.has_md5);
138 proto_result->set_has_sha1(result.has_sha1);
139 proto_result->set_has_sha1_leaf(result.has_sha1_leaf);
140 for (const HashValue& value : result.public_key_hashes)
141 proto_result->add_public_key_hashes(value.ToString());
142 proto_result->set_is_issued_by_known_root(result.is_issued_by_known_root);
143 proto_result->set_is_issued_by_additional_trust_anchor(
144 result.is_issued_by_additional_trust_anchor);
145 proto_result->set_common_name_fallback_used(result.common_name_fallback_used);
146 return true;
147 }
148
149 // Update |error| and |result| with deserialized CachedResult data from
150 // |proto_cached_result|. Returns true if it is deserialized correctly.
151 bool DeserializeCachedResult(
152 const CertVerificationCachedResult& proto_cached_result,
153 const CertVerifierCachePersister::CertVector& deserialized_der_certs,
154 int* error,
155 CertVerifyResult* result) {
156 if (!proto_cached_result.has_error() || !proto_cached_result.has_result()) {
157 DCHECK(false);
158 return false;
159 }
160
161 const CertVerificationResult& proto_result = proto_cached_result.result();
162 if (!proto_result.has_verified_cert() || !proto_result.has_cert_status()) {
163 DCHECK(false);
164 return false;
165 }
166
167 *error = proto_cached_result.error();
168
169 result->verified_cert = DeserializeCertificate(proto_result.verified_cert(),
170 deserialized_der_certs);
171 if (!result->verified_cert.get()) {
172 DCHECK(false);
173 return false;
174 }
175
176 for (int i = 0; i < proto_result.public_key_hashes_size(); ++i) {
177 const ::std::string& public_key_hash = proto_result.public_key_hashes(i);
178 HashValue hash;
179 if (!hash.FromString(public_key_hash)) {
180 DCHECK(false);
181 return false;
182 }
183 result->public_key_hashes.push_back(hash);
184 }
185 result->cert_status = proto_result.cert_status();
186 result->has_md2 = proto_result.has_md2();
187 result->has_md4 = proto_result.has_md4();
188 result->has_md5 = proto_result.has_md5();
189 result->has_sha1 = proto_result.has_sha1();
190 result->has_sha1_leaf = proto_result.has_sha1_leaf();
191 result->is_issued_by_known_root = proto_result.is_issued_by_known_root();
192 result->is_issued_by_additional_trust_anchor =
193 proto_result.is_issued_by_additional_trust_anchor();
194 result->common_name_fallback_used = proto_result.common_name_fallback_used();
195 return true;
196 }
197
198 // Update |proto_cache_validity_period| with ValidityPeriod data from
199 // |cache_iterator|.
200 void SerializeValidityPeriod(
201 CachingCertVerifier::Iterator& cache_iterator,
202 CertVerificationCacheValidityPeriod* proto_cache_validity_period) {
203 proto_cache_validity_period->set_verification_time(
204 cache_iterator.verification_time().ToInternalValue());
205 proto_cache_validity_period->set_expiration_time(
206 cache_iterator.expiration_time().ToInternalValue());
207 }
208
209 } // namespace
210
211 CertVerifierCachePersister::CertVerifierCachePersister(
212 CachingCertVerifier* verifier)
213 : verifier_(verifier) {}
214
215 CertVerifierCachePersister::~CertVerifierCachePersister() {}
216
217 void CertVerifierCachePersister::SerializeCache(std::string* data) {
218 base::TimeTicks start_time(base::TimeTicks::Now());
219 CertVerificationCache proto_cert_cache;
220 CertVector serialized_certs;
221
222 CachingCertVerifier::Iterator cache_iterator(*verifier_);
223 for (; cache_iterator.HasNext(); cache_iterator.Advance()) {
224 CertVerificationCacheEntry* proto_cache_entry =
225 proto_cert_cache.add_cache_entry();
226
227 CertVerificationRequestParams* proto_request_param =
228 proto_cache_entry->mutable_request_params();
229 if (!SerializeRequestParams(cache_iterator.params(), &serialized_certs,
230 proto_request_param)) {
231 DCHECK(false);
232 continue;
233 }
234
235 CertVerificationCachedResult* proto_cached_result =
236 proto_cache_entry->mutable_cached_result();
237 if (!SerializeCachedResult(cache_iterator, &serialized_certs,
238 proto_cached_result)) {
239 DCHECK(false);
240 continue;
241 }
242
243 CertVerificationCacheValidityPeriod* proto_cache_validity_period =
244 proto_cache_entry->mutable_cache_validity_period();
245 SerializeValidityPeriod(cache_iterator, proto_cache_validity_period);
246 }
247 for (const std::string& cert : serialized_certs)
248 proto_cert_cache.add_certs(cert);
249
250 proto_cert_cache.SerializeToString(data);
251 UMA_HISTOGRAM_TIMES("Net.CertVerifierCachePersister.SerializeTime",
252 base::TimeTicks::Now() - start_time);
253 }
254
255 bool CertVerifierCachePersister::LoadCache(const std::string& data) {
256 base::TimeTicks load_cache_start_time = base::TimeTicks::Now();
257 CertVector deserialized_der_certs;
258 CertVerificationCache proto;
259
260 if (!proto.ParseFromString(data) || proto.certs_size() == 0u ||
261 proto.cache_entry_size() == 0u) {
262 return false;
263 }
264
265 for (int i = 0; i < proto.certs_size(); ++i)
266 deserialized_der_certs.push_back(proto.certs(i));
267
268 bool detected_corrupted_data = false;
269 for (int i = 0; i < proto.cache_entry_size(); ++i) {
270 const CertVerificationCacheEntry& cache_entry = proto.cache_entry(i);
271 if (!cache_entry.has_request_params() ||
272 !cache_entry.has_cache_validity_period() ||
273 !cache_entry.has_cached_result()) {
274 detected_corrupted_data = true;
275 continue;
276 }
277
278 const CertVerificationRequestParams& proto_request_params =
279 cache_entry.request_params();
280
281 if (!proto_request_params.has_certificate() ||
282 !proto_request_params.has_hostname() ||
283 proto_request_params.hostname().empty() ||
284 !proto_request_params.has_flags() ||
285 !proto_request_params.has_ocsp_response()) {
286 detected_corrupted_data = true;
287 continue;
288 }
289
290 scoped_refptr<X509Certificate> certificate = DeserializeCertificate(
291 proto_request_params.certificate(), deserialized_der_certs);
292 if (!certificate.get()) {
293 detected_corrupted_data = true;
294 continue;
295 }
296
297 std::string hostname(proto_request_params.hostname());
298 int flags = proto_request_params.flags();
299 std::string ocsp_response(proto_request_params.ocsp_response());
300 CertificateList additional_trust_anchors;
301 for (int i = 0; i < proto_request_params.additional_trust_anchors_size();
302 ++i) {
303 const CertVerificationCertificate& proto_certificate =
304 proto_request_params.additional_trust_anchors(i);
305 scoped_refptr<X509Certificate> cert =
306 DeserializeCertificate(proto_certificate, deserialized_der_certs);
307 if (cert.get())
308 additional_trust_anchors.push_back(cert);
309 }
310
311 CertVerifier::RequestParams params(certificate, hostname, flags,
312 ocsp_response, additional_trust_anchors);
313
314 const CertVerificationCacheValidityPeriod& proto_cache_validity_period =
315 cache_entry.cache_validity_period();
316 if (!proto_cache_validity_period.has_verification_time() ||
317 !proto_cache_validity_period.has_expiration_time()) {
318 detected_corrupted_data = true;
319 continue;
320 }
321 base::Time verification_time = base::Time::FromInternalValue(
322 proto_cache_validity_period.verification_time());
323
324 const CertVerificationCachedResult& proto_cached_result =
325 cache_entry.cached_result();
326 CertVerifyResult result;
327 int error;
328 if (!DeserializeCachedResult(proto_cached_result, deserialized_der_certs,
329 &error, &result)) {
330 detected_corrupted_data = true;
331 continue;
332 }
333
334 if (!verifier_->AddEntry(params, error, result, verification_time)) {
335 detected_corrupted_data = true;
336 continue;
337 }
338 }
339 UMA_HISTOGRAM_COUNTS("Net.CertVerifierCachePersister.LoadCacheSize",
340 proto.cache_entry_size());
341 UMA_HISTOGRAM_TIMES("Net.CertVerifierCachePersister.LoadCacheTime",
342 base::TimeTicks::Now() - load_cache_start_time);
343 return !detected_corrupted_data;
344 }
345
346 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698