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

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

Issue 1892033002: Cert - protobufs to serialize and deserialize CertVerifierCache. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 8 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/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/time/time.h"
11 #include "net/base/hash_value.h"
12 #include "net/cert/cert_verify_result.h"
13 #include "net/cert/proto/cert_verification.pb.h"
14 #include "net/cert/x509_certificate.h"
15
16 namespace net {
17
18 CertVerifierCachePersister::CertVerifierCachePersister(
19 MultiThreadedCertVerifier* verifier)
20 : verifier_(verifier) {}
21
22 CertVerifierCachePersister::~CertVerifierCachePersister() {}
23
24 void CertVerifierCachePersister::SerializeCache(std::string* data) {
25 base::TimeTicks start_time(base::TimeTicks::Now());
26 CertVerificationCache proto_cert_cache;
27
28 MultiThreadedCertVerifier::CertVerifierCacheIterator cache_iterator(
29 *verifier_);
30 for (; cache_iterator.HasNext(); cache_iterator.Advance()) {
31 CertVerificationCacheEntry* proto_cache_entry =
32 proto_cert_cache.add_cache_entry();
33
34 CertVerificationRequestParams* proto_request_param =
35 proto_cache_entry->mutable_request_params();
36 SerializeRequestParams(cache_iterator, proto_request_param);
37
38 CertVerificationCachedResult* proto_cached_result =
39 proto_cache_entry->mutable_cached_result();
40 SerializeCachedResult(cache_iterator, proto_cached_result);
41
42 CertVerificationCacheValidityPeriod* proto_cache_validity_period =
43 proto_cache_entry->mutable_cache_validity_period();
44 SerializeValidityPeriod(cache_iterator, proto_cache_validity_period);
45 }
46
47 proto_cert_cache.SerializeToString(data);
48 UMA_HISTOGRAM_TIMES("Net.CertVerifierCachePersister.SerializeTime",
49 base::TimeTicks::Now() - start_time);
50 }
51
52 bool CertVerifierCachePersister::LoadCache(const std::string& data) {
53 base::TimeTicks start_time(base::TimeTicks::Now());
54
55 CertVerificationCache proto;
56 if (!proto.ParseFromString(data)) {
57 DVLOG(1) << "Protobug ParseFromString failure";
58 return false;
59 }
60 for (int i = 0; i < proto.cache_entry_size(); ++i) {
61 const CertVerificationCacheEntry& cache_entry = proto.cache_entry(i);
62 if (!cache_entry.has_request_params() ||
63 !cache_entry.has_cache_validity_period() ||
64 !cache_entry.has_cached_result()) {
65 DVLOG(1) << "Invalid CertVerificationCacheEntry";
66 continue;
67 }
68
69 const CertVerificationRequestParams& proto_request_params =
70 cache_entry.request_params();
71 MultiThreadedCertVerifier::RequestParams key;
72 if (!DeserializeRequestParams(proto_request_params, &key))
73 continue;
74
75 MultiThreadedCertVerifier::CacheValidityPeriod expiration(
76 base::Time::Now());
77 const MultiThreadedCertVerifier::CertVerifierCache::value_type*
78 cached_entry = verifier_->cache_.Get(key, expiration);
79 if (cached_entry) {
80 DVLOG(1) << "Already exists in the cache for " << key.hostname;
81 continue;
82 }
83
84 const CertVerificationCacheValidityPeriod& proto_cache_validity_period =
85 cache_entry.cache_validity_period();
86 if (!DeserializeValidityPeriod(proto_cache_validity_period, key.hostname,
87 &expiration)) {
88 continue;
89 }
90
91 const CertVerificationCachedResult& proto_cached_result =
92 cache_entry.cached_result();
93 MultiThreadedCertVerifier::CachedResult cached_result;
94 if (!DeserializeCachedResult(proto_cached_result, key.hostname,
95 &cached_result)) {
96 continue;
97 }
98
99 verifier_->cache_.Put(
100 key, cached_result,
101 MultiThreadedCertVerifier::CacheValidityPeriod(key.start_time),
102 expiration);
103 }
104 UMA_HISTOGRAM_TIMES("Net.CertVerifierCachePersister.LoadCacheTime",
105 base::TimeTicks::Now() - start_time);
106 return true;
107 }
108
109 void CertVerifierCachePersister::SerializeRequestParams(
110 MultiThreadedCertVerifier::CertVerifierCacheIterator& cache_iterator,
111 CertVerificationRequestParams* proto_request_param) {
112 proto_request_param->set_hostname(cache_iterator.hostname());
113 proto_request_param->set_flags(cache_iterator.flags());
114 proto_request_param->set_start_time(
115 cache_iterator.start_time().ToInternalValue());
116 for (const SHA1HashValue& value : cache_iterator.hash_values()) {
117 CertVerificationSHA1HashValue* hash_value =
118 proto_request_param->add_hash_values();
119 hash_value->set_data(value.data, 20);
120 }
121 }
122
123 void CertVerifierCachePersister::SerializeCachedResult(
124 MultiThreadedCertVerifier::CertVerifierCacheIterator& cache_iterator,
125 CertVerificationCachedResult* proto_cached_result) {
126 proto_cached_result->set_error(cache_iterator.error());
127
128 // Serialize CertVerifyResult.
129 CertVerificationResult* proto_result = proto_cached_result->mutable_result();
130 const CertVerifyResult& result = cache_iterator.result();
131
132 // TODO(rtenneti): Don't use picke to persist the certificates. Persist each
133 // unique individual certificate.
134 base::Pickle pickle;
135 result.verified_cert->Persist(&pickle);
136 std::string verified_cert(reinterpret_cast<const char*>(pickle.data()),
137 pickle.size());
138 proto_result->set_verified_cert(verified_cert);
139 proto_result->set_cert_status(result.cert_status);
140 proto_result->set_has_md2(result.has_md2);
141 proto_result->set_has_md4(result.has_md4);
142 proto_result->set_has_md5(result.has_md5);
143 proto_result->set_has_sha1(result.has_sha1);
144 proto_result->set_has_sha1_leaf(result.has_sha1_leaf);
145 for (const HashValue& value : result.public_key_hashes)
146 proto_result->add_public_key_hashes(value.ToString());
147 proto_result->set_is_issued_by_known_root(result.is_issued_by_known_root);
148 proto_result->set_is_issued_by_additional_trust_anchor(
149 result.is_issued_by_additional_trust_anchor);
150 proto_result->set_common_name_fallback_used(result.common_name_fallback_used);
151 }
152
153 void CertVerifierCachePersister::SerializeValidityPeriod(
154 MultiThreadedCertVerifier::CertVerifierCacheIterator& cache_iterator,
155 CertVerificationCacheValidityPeriod* proto_cache_validity_period) {
156 proto_cache_validity_period->set_verification_time(
157 cache_iterator.verification_time().ToInternalValue());
158 proto_cache_validity_period->set_expiration_time(
159 cache_iterator.expiration_time().ToInternalValue());
160 }
161
162 bool CertVerifierCachePersister::DeserializeRequestParams(
163 const CertVerificationRequestParams& proto_request_params,
164 MultiThreadedCertVerifier::RequestParams* request_params) {
165 int hash_values_size = proto_request_params.hash_values_size();
166 if (!proto_request_params.has_hostname() ||
167 proto_request_params.hostname().empty() ||
168 !proto_request_params.has_flags() || hash_values_size <= 0 ||
169 !proto_request_params.has_start_time()) {
170 DVLOG(1) << "Invalid CertVerificationRequestParams";
171 return false;
172 }
173
174 request_params->hostname.assign(proto_request_params.hostname());
175 request_params->flags = proto_request_params.flags();
176 request_params->hash_values.resize(hash_values_size);
177 for (int index = 0; index < hash_values_size; ++index) {
178 const CertVerificationSHA1HashValue& hash_values =
179 proto_request_params.hash_values(index);
180 if (!hash_values.has_data()) {
181 DVLOG(1) << "Invalid CertVerificationSHA1HashValue for "
182 << request_params->hostname;
183 return false;
184 }
185 const std::string& data = hash_values.data();
186 memcpy(request_params->hash_values[index].data, data.data(), data.length());
187 }
188 return true;
189 }
190
191 bool CertVerifierCachePersister::DeserializeValidityPeriod(
192 const CertVerificationCacheValidityPeriod& proto_cache_validity_period,
193 const std::string& hostname,
194 MultiThreadedCertVerifier::CacheValidityPeriod* expiration) {
195 if (!proto_cache_validity_period.has_verification_time() ||
196 !proto_cache_validity_period.has_expiration_time()) {
197 DVLOG(1) << "Invalid CertVerificationCacheValidityPeriod" << hostname;
198 return false;
199 }
200 expiration->verification_time = base::Time::FromInternalValue(
201 proto_cache_validity_period.verification_time());
202 expiration->expiration_time = base::Time::FromInternalValue(
203 proto_cache_validity_period.expiration_time());
204 if (expiration->verification_time > expiration->expiration_time ||
205 expiration->expiration_time < base::Time::Now() ||
206 expiration->verification_time > base::Time::Now()) {
207 DVLOG(1) << "CertVerificationCacheValidityPeriod expired for " << hostname;
208 return false;
209 }
210 return true;
211 }
212
213 bool CertVerifierCachePersister::DeserializeCachedResult(
214 const CertVerificationCachedResult& proto_cached_result,
215 const std::string& hostname,
216 MultiThreadedCertVerifier::CachedResult* cached_result) {
217 if (!proto_cached_result.has_error() || !proto_cached_result.has_result()) {
218 DVLOG(1) << "Invalid CertVerificationCacheEntry";
219 return false;
220 }
221 const CertVerificationResult& proto_result = proto_cached_result.result();
222 if (!proto_result.has_verified_cert() || !proto_result.has_cert_status()) {
223 DVLOG(1) << "Invalid CertVerificationResult for " << hostname;
224 return false;
225 }
226
227 cached_result->error = proto_cached_result.error();
228 const std::string& verified_cert = proto_result.verified_cert();
229 base::Pickle pickle(verified_cert.data(), verified_cert.length());
230 base::PickleIterator iter1(pickle);
231 cached_result->result.verified_cert = X509Certificate::CreateFromPickle(
232 &iter1, X509Certificate::PICKLETYPE_CERTIFICATE_CHAIN_V3);
233 if (cached_result->result.verified_cert.get() == nullptr) {
234 DVLOG(1) << "CertVerificationResult has invalid certificate chain for "
235 << hostname;
236 return false;
237 }
238 for (int i = 0; i < proto_result.public_key_hashes_size(); ++i) {
239 const ::std::string& public_key_hash = proto_result.public_key_hashes(i);
240 HashValue hash;
241 if (!hash.FromString(public_key_hash)) {
242 DVLOG(1) << "CertVerificationResult has invalid public_key_hashes for "
243 << hostname;
244 return false;
245 }
246 cached_result->result.public_key_hashes.push_back(hash);
247 }
248 cached_result->result.cert_status = proto_result.cert_status();
249 cached_result->result.has_md2 = proto_result.has_md2();
250 cached_result->result.has_md4 = proto_result.has_md4();
251 cached_result->result.has_md5 = proto_result.has_md5();
252 cached_result->result.has_sha1 = proto_result.has_sha1();
253 cached_result->result.has_sha1_leaf = proto_result.has_sha1_leaf();
254 cached_result->result.is_issued_by_known_root =
255 proto_result.is_issued_by_known_root();
256 cached_result->result.is_issued_by_additional_trust_anchor =
257 proto_result.is_issued_by_additional_trust_anchor();
258 cached_result->result.common_name_fallback_used =
259 proto_result.common_name_fallback_used();
260 return true;
261 }
262
263 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698