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

Side by Side Diff: net/base/x509_certificate.cc

Issue 2944008: Refactor X509Certificate caching to cache the OS handle, rather than the X509Certificate (Closed)
Patch Set: Removed unnecessary bits Created 9 years, 5 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
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/base/x509_certificate.h" 5 #include "net/base/x509_certificate.h"
6 6
7 #include <stdlib.h> 7 #include <stdlib.h>
8 8
9 #include <map> 9 #include <map>
10 #include <string> 10 #include <string>
11 #include <vector> 11 #include <vector>
12 12
13 #include "base/lazy_instance.h" 13 #include "base/lazy_instance.h"
14 #include "base/logging.h" 14 #include "base/logging.h"
15 #include "base/memory/singleton.h" 15 #include "base/memory/singleton.h"
16 #include "base/metrics/histogram.h" 16 #include "base/metrics/histogram.h"
17 #include "base/pickle.h" 17 #include "base/pickle.h"
18 #include "base/sha1.h" 18 #include "base/sha1.h"
19 #include "base/string_piece.h" 19 #include "base/string_piece.h"
20 #include "base/string_util.h" 20 #include "base/string_util.h"
21 #include "base/synchronization/lock.h"
21 #include "base/time.h" 22 #include "base/time.h"
22 #include "net/base/cert_status_flags.h" 23 #include "net/base/cert_status_flags.h"
23 #include "net/base/cert_verify_result.h" 24 #include "net/base/cert_verify_result.h"
24 #include "net/base/net_errors.h" 25 #include "net/base/net_errors.h"
25 #include "net/base/pem_tokenizer.h" 26 #include "net/base/pem_tokenizer.h"
26 27
27 namespace net { 28 namespace net {
28 29
29 namespace { 30 namespace {
30 31
(...skipping 12 matching lines...) Expand all
43 const X509Certificate::Format kFormatDecodePriority[] = { 44 const X509Certificate::Format kFormatDecodePriority[] = {
44 X509Certificate::FORMAT_SINGLE_CERTIFICATE, 45 X509Certificate::FORMAT_SINGLE_CERTIFICATE,
45 X509Certificate::FORMAT_PKCS7 46 X509Certificate::FORMAT_PKCS7
46 }; 47 };
47 48
48 // The PEM block header used for DER certificates 49 // The PEM block header used for DER certificates
49 const char kCertificateHeader[] = "CERTIFICATE"; 50 const char kCertificateHeader[] = "CERTIFICATE";
50 // The PEM block header used for PKCS#7 data 51 // The PEM block header used for PKCS#7 data
51 const char kPKCS7Header[] = "PKCS7"; 52 const char kPKCS7Header[] = "PKCS7";
52 53
53 // A thread-safe cache for X509Certificate objects. 54 // A thread-safe cache for OS certificate handles.
54 // 55 //
55 // The cache does not hold a reference to the certificate objects. The objects 56 // Within each of the supported underlying crypto libraries, a certificate
56 // must |Remove| themselves from the cache upon destruction (or else the cache 57 // handle is represented as a ref-counted object that contains the parsed
57 // will be holding dead pointers to the objects). 58 // data for the certificate. In addition, the underlying OS handle may also
58 // TODO(rsleevi): There exists a chance of a use-after-free, due to a race 59 // contain a copy of the original ASN.1 DER used to constructed the handle.
59 // between Find() and Remove(). See http://crbug.com/49377 60 //
61 // In order to reduce the memory usage when multiple SSL connections exist,
62 // with each connection storing the server's identity certificate plus any
63 // intermediates supplied, the certificate handles are cached. Any two
64 // X509Certificates that were created from the same ASN.1 DER data,
65 // regardless of where that data came from, will share the same underlying
66 // OS certificate handle.
60 class X509CertificateCache { 67 class X509CertificateCache {
wtc 2011/07/17 01:55:32 This class should be renamed OSCertHandleCache. Yo
61 public: 68 public:
62 void Insert(X509Certificate* cert); 69 // Performs a compare-and-swap like operation. If an OS certificate handle
63 void Remove(X509Certificate* cert); 70 // for the same certificate data as |*cert_handle| already exists in the
64 X509Certificate* Find(const SHA1Fingerprint& fingerprint); 71 // cache, the original |*cert_handle| will be freed, and |cert_handle|
72 // will be updated to point to the existing cached certificate, after
73 // adding to the reference count. If an equivalent OS certificate handle
74 // is not found, |*cert_handle| will be added to the cache and its
75 // reference count increased, while otherwise remaining unmodified and
76 // pointing to the caller's original certificate.
77 void InsertOrUpdate(X509Certificate::OSCertHandle* cert_handle);
78
79 // Decrements the reference count for |cert_handle|, and if it is the last
80 // reference held in the cache, frees the underlying OS certificate
81 // handle. InsertOrUpdate() must have been called prior to Remove() for
82 // the |cert_handle|.
83 void Remove(X509Certificate::OSCertHandle cert_handle);
65 84
66 private: 85 private:
67 typedef std::map<SHA1Fingerprint, X509Certificate*, SHA1FingerprintLessThan> 86 // A single entry in the cache. Certificates will be keyed by their SHA1
68 CertMap; 87 // fingerprints, but will not be considered equivalent unless the entire
88 // certificate data matches.
89 struct Entry {
90 Entry() : cert_handle(NULL), ref_count(0) {}
wtc 2011/07/17 01:55:32 Add a blank line below.
91 X509Certificate::OSCertHandle cert_handle;
92
93 // Increased by each call to InsertOrUpdate(), and balanced by each call
94 // to Remove(). When it equals 0, all references have been released, so
95 // the cache entry will be removed and the OS certificate released.
96 size_t ref_count;
wtc 2011/07/17 01:55:32 Define ref_count as an 'int'. This is what RefCou
97 };
98 typedef std::map<SHA1Fingerprint, Entry, SHA1FingerprintLessThan> CertMap;
69 99
70 // Obtain an instance of X509CertificateCache via a LazyInstance. 100 // Obtain an instance of X509CertificateCache via a LazyInstance.
71 X509CertificateCache() {} 101 X509CertificateCache() {}
72 ~X509CertificateCache() {} 102 ~X509CertificateCache() {}
73 friend struct base::DefaultLazyInstanceTraits<X509CertificateCache>; 103 friend struct base::DefaultLazyInstanceTraits<X509CertificateCache>;
74 104
75 // You must acquire this lock before using any private data of this object. 105 // You must acquire this lock before using any private data of this
wtc 2011/07/17 01:55:32 It doesn't seem necessary to wrap this line.
76 // You must not block while holding this lock. 106 // object. You must not block while holding this lock.
77 base::Lock lock_; 107 base::Lock lock_;
78 108
79 // The certificate cache. You must acquire |lock_| before using |cache_|. 109 // The certificate cache. You must acquire |lock_| before using |cache_|.
80 CertMap cache_; 110 CertMap cache_;
81 111
82 DISALLOW_COPY_AND_ASSIGN(X509CertificateCache); 112 DISALLOW_COPY_AND_ASSIGN(X509CertificateCache);
83 }; 113 };
84 114
85 base::LazyInstance<X509CertificateCache, 115 base::LazyInstance<X509CertificateCache,
86 base::LeakyLazyInstanceTraits<X509CertificateCache> > 116 base::LeakyLazyInstanceTraits<X509CertificateCache> >
87 g_x509_certificate_cache(base::LINKER_INITIALIZED); 117 g_x509_certificate_cache(base::LINKER_INITIALIZED);
88 118
89 // Insert |cert| into the cache. The cache does NOT AddRef |cert|. 119 void X509CertificateCache::InsertOrUpdate(
90 // Any existing certificate with the same fingerprint will be replaced. 120 X509Certificate::OSCertHandle* cert_handle) {
91 void X509CertificateCache::Insert(X509Certificate* cert) { 121 DCHECK(cert_handle);
122 SHA1Fingerprint fingerprint =
123 X509Certificate::CalculateFingerprint(*cert_handle);
124 DCHECK(!IsNullFingerprint(fingerprint)) <<
125 "Only insert certs with real fingerprints.";
wtc 2011/07/17 01:55:32 Delete this DCHECK. This DCHECK was only meaningf
126
127 X509Certificate::OSCertHandle old_handle = NULL;
128 {
129 base::AutoLock lock(lock_);
130 CertMap::iterator pos = cache_.find(fingerprint);
131 if (pos == cache_.end()) {
132 // Cached entry not found. Initialize a new entry. |*cert_handle| is
133 // guaranteed to have at least one OS reference (the caller's), which
134 // will be incremented, along with cache_entry.ref_count, below.
135 Entry cache_entry;
136 cache_entry.cert_handle = *cert_handle;
137 cache_entry.ref_count = 0;
138 CertMap::value_type cache_value(fingerprint, cache_entry);
139 pos = cache_.insert(cache_value).first;
140 } else {
141 bool is_same_cert =
142 X509Certificate::IsSameOSCert(*cert_handle, pos->second.cert_handle);
143 if (!is_same_cert) {
144 // Two certificates don't match, likely due to a SHA1 hash collision.
wtc 2011/07/17 01:55:32 Remove "likely".
145 // Given the low probability, the simplest solution is to not cache
146 // the certificate, which should not affect performance too
147 // negatively.
148 return;
149 }
150 // A cached entry was found and will be used instead of the caller's
151 // handle. Ensure the caller's original handle will be freed, since
152 // ownership is assumed.
153 old_handle = *cert_handle;
154 DHISTOGRAM_COUNTS("X509CertificateReuseCount", 1);
wtc 2011/07/17 01:55:32 Move this DHISTOGRAM_COUNTS call outside the criti
155 }
156 ++pos->second.ref_count;
157 *cert_handle = X509Certificate::DupOSCertHandle(pos->second.cert_handle);
wtc 2011/07/17 01:55:32 Note how you increment pos->second.ref_count and t
158 }
159 // If the caller's handle was replaced with a cached handle, free the
160 // original handle now. This is done outside of the lock because
161 // |old_handle| may be the only handle for this particular certificate, so
162 // freeing it may be complex or resource-intensive and does not need to
163 // be guarded by the lock.
164 if (old_handle)
165 X509Certificate::FreeOSCertHandle(old_handle);
166 }
167
168 void X509CertificateCache::Remove(X509Certificate::OSCertHandle cert_handle) {
169 SHA1Fingerprint fingerprint =
170 X509Certificate::CalculateFingerprint(cert_handle);
92 base::AutoLock lock(lock_); 171 base::AutoLock lock(lock_);
93 172
94 DCHECK(!IsNullFingerprint(cert->fingerprint())) << 173 CertMap::iterator pos = cache_.find(fingerprint);
95 "Only insert certs with real fingerprints."; 174 if (pos == cache_.end())
96 cache_[cert->fingerprint()] = cert; 175 return; // A cache collision where the winning cert was already freed.
97 };
98 176
99 // Remove |cert| from the cache. The cache does not assume that |cert| is 177 bool is_same_cert = X509Certificate::IsSameOSCert(cert_handle,
100 // already in the cache. 178 pos->second.cert_handle);
101 void X509CertificateCache::Remove(X509Certificate* cert) { 179 if (!is_same_cert)
102 base::AutoLock lock(lock_); 180 return; // A cache collision where the winning cert is still around.
wtc 2011/07/17 01:55:32 In the comments on lines 175 and 180, change "cach
103 181
104 CertMap::iterator pos(cache_.find(cert->fingerprint())); 182 if (--pos->second.ref_count == 0) {
105 if (pos == cache_.end()) 183 // The last reference to |cert_handle| has been removed, so release the
106 return; // It is not an error to remove a cert that is not in the cache. 184 // underlying OS handle and remove from the cache. The caller still
107 cache_.erase(pos); 185 // holds a reference to the underlying OS handle and still bears
108 }; 186 // responsibility for freeing it.
109 187 X509Certificate::FreeOSCertHandle(pos->second.cert_handle);
wtc 2011/07/17 01:55:32 Here, you decrement pos->second.ref_count every ti
Ryan Sleevi 2011/07/17 03:52:22 I don't believe there is a leak, and have made an
110 // Find a certificate in the cache with the given fingerprint. If one does 188 cache_.erase(pos);
111 // not exist, this method returns NULL. 189 }
112 X509Certificate* X509CertificateCache::Find( 190 }
113 const SHA1Fingerprint& fingerprint) {
114 base::AutoLock lock(lock_);
115
116 CertMap::iterator pos(cache_.find(fingerprint));
117 if (pos == cache_.end())
118 return NULL;
119
120 return pos->second;
121 };
122 191
123 // CompareSHA1Hashes is a helper function for using bsearch() with an array of 192 // CompareSHA1Hashes is a helper function for using bsearch() with an array of
124 // SHA1 hashes. 193 // SHA1 hashes.
125 static int CompareSHA1Hashes(const void* a, const void* b) { 194 static int CompareSHA1Hashes(const void* a, const void* b) {
126 return memcmp(a, b, base::SHA1_LENGTH); 195 return memcmp(a, b, base::SHA1_LENGTH);
127 } 196 }
128 197
129 } // namespace 198 } // namespace
130 199
131 bool X509Certificate::LessThan::operator()(X509Certificate* lhs, 200 bool X509Certificate::LessThan::operator()(X509Certificate* lhs,
132 X509Certificate* rhs) const { 201 X509Certificate* rhs) const {
133 if (lhs == rhs) 202 if (lhs == rhs)
134 return false; 203 return false;
135 204
136 SHA1FingerprintLessThan fingerprint_functor; 205 SHA1FingerprintLessThan fingerprint_functor;
137 return fingerprint_functor(lhs->fingerprint_, rhs->fingerprint_); 206 return fingerprint_functor(lhs->fingerprint_, rhs->fingerprint_);
138 } 207 }
139 208
140 X509Certificate::X509Certificate(const std::string& subject, 209 X509Certificate::X509Certificate(const std::string& subject,
141 const std::string& issuer, 210 const std::string& issuer,
142 base::Time start_date, 211 base::Time start_date,
143 base::Time expiration_date) 212 base::Time expiration_date)
144 : subject_(subject), 213 : subject_(subject),
145 issuer_(issuer), 214 issuer_(issuer),
146 valid_start_(start_date), 215 valid_start_(start_date),
147 valid_expiry_(expiration_date), 216 valid_expiry_(expiration_date),
148 cert_handle_(NULL), 217 cert_handle_(NULL) {
149 source_(SOURCE_UNUSED) {
150 memset(fingerprint_.data, 0, sizeof(fingerprint_.data)); 218 memset(fingerprint_.data, 0, sizeof(fingerprint_.data));
151 } 219 }
152 220
153 // static 221 // static
154 X509Certificate* X509Certificate::CreateFromHandle( 222 X509Certificate* X509Certificate::CreateFromHandle(
155 OSCertHandle cert_handle, 223 OSCertHandle cert_handle,
156 Source source,
157 const OSCertHandles& intermediates) { 224 const OSCertHandles& intermediates) {
158 DCHECK(cert_handle); 225 DCHECK(cert_handle);
159 DCHECK_NE(source, SOURCE_UNUSED); 226 X509Certificate* cert = new X509Certificate(cert_handle, intermediates);
wtc 2011/07/17 01:55:32 The local variable 'cert' was necessary in the old
160
161 // Check if we already have this certificate in memory.
162 X509CertificateCache* cache = g_x509_certificate_cache.Pointer();
163 X509Certificate* cached_cert =
164 cache->Find(CalculateFingerprint(cert_handle));
165 if (cached_cert) {
166 DCHECK_NE(cached_cert->source_, SOURCE_UNUSED);
167 if (cached_cert->source_ > source ||
168 (cached_cert->source_ == source &&
169 cached_cert->HasIntermediateCertificates(intermediates))) {
170 // Return the certificate with the same fingerprint from our cache.
171 DHISTOGRAM_COUNTS("X509CertificateReuseCount", 1);
172 return cached_cert;
173 }
174 // Else the new cert is better and will replace the old one in the cache.
175 }
176
177 // Otherwise, allocate and cache a new object.
178 X509Certificate* cert = new X509Certificate(cert_handle, source,
179 intermediates);
180 cache->Insert(cert);
181 return cert; 227 return cert;
182 } 228 }
183 229
184 #if defined(OS_WIN)
185 static X509Certificate::OSCertHandle CreateOSCert(base::StringPiece der_cert) {
186 X509Certificate::OSCertHandle cert_handle = NULL;
187 BOOL ok = CertAddEncodedCertificateToStore(
188 X509Certificate::cert_store(), X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
189 reinterpret_cast<const BYTE*>(der_cert.data()), der_cert.size(),
190 CERT_STORE_ADD_USE_EXISTING, &cert_handle);
191 return ok ? cert_handle : NULL;
wtc 2011/07/16 00:54:54 IMPORTANT: Removing X509Certificate::cert_store()
192 }
193 #else
194 static X509Certificate::OSCertHandle CreateOSCert(base::StringPiece der_cert) { 230 static X509Certificate::OSCertHandle CreateOSCert(base::StringPiece der_cert) {
195 return X509Certificate::CreateOSCertHandleFromBytes( 231 return X509Certificate::CreateOSCertHandleFromBytes(
196 const_cast<char*>(der_cert.data()), der_cert.size()); 232 const_cast<char*>(der_cert.data()), der_cert.size());
197 } 233 }
198 #endif
199 234
200 // static 235 // static
201 X509Certificate* X509Certificate::CreateFromDERCertChain( 236 X509Certificate* X509Certificate::CreateFromDERCertChain(
202 const std::vector<base::StringPiece>& der_certs) { 237 const std::vector<base::StringPiece>& der_certs) {
203 if (der_certs.empty()) 238 if (der_certs.empty())
204 return NULL; 239 return NULL;
205 240
206 X509Certificate::OSCertHandles intermediate_ca_certs; 241 X509Certificate::OSCertHandles intermediate_ca_certs;
207 for (size_t i = 1; i < der_certs.size(); i++) { 242 for (size_t i = 1; i < der_certs.size(); i++) {
208 OSCertHandle handle = CreateOSCert(der_certs[i]); 243 OSCertHandle handle = CreateOSCert(der_certs[i]);
209 DCHECK(handle); 244 DCHECK(handle);
210 intermediate_ca_certs.push_back(handle); 245 intermediate_ca_certs.push_back(handle);
211 } 246 }
212 247
213 OSCertHandle handle = CreateOSCert(der_certs[0]); 248 OSCertHandle handle = CreateOSCert(der_certs[0]);
214 DCHECK(handle); 249 DCHECK(handle);
215 X509Certificate* cert = 250 X509Certificate* cert = CreateFromHandle(handle, intermediate_ca_certs);
216 CreateFromHandle(handle, SOURCE_FROM_NETWORK, intermediate_ca_certs);
217 FreeOSCertHandle(handle); 251 FreeOSCertHandle(handle);
218 for (size_t i = 0; i < intermediate_ca_certs.size(); i++) 252 for (size_t i = 0; i < intermediate_ca_certs.size(); i++)
219 FreeOSCertHandle(intermediate_ca_certs[i]); 253 FreeOSCertHandle(intermediate_ca_certs[i]);
220 254
221 return cert; 255 return cert;
222 } 256 }
223 257
224 // static 258 // static
225 X509Certificate* X509Certificate::CreateFromBytes(const char* data, 259 X509Certificate* X509Certificate::CreateFromBytes(const char* data,
226 int length) { 260 int length) {
227 OSCertHandle cert_handle = CreateOSCertHandleFromBytes(data, length); 261 OSCertHandle cert_handle = CreateOSCertHandleFromBytes(data, length);
228 if (!cert_handle) 262 if (!cert_handle)
229 return NULL; 263 return NULL;
230 264
231 X509Certificate* cert = CreateFromHandle(cert_handle, 265 X509Certificate* cert = CreateFromHandle(cert_handle, OSCertHandles());
232 SOURCE_LONE_CERT_IMPORT,
233 OSCertHandles());
234 FreeOSCertHandle(cert_handle); 266 FreeOSCertHandle(cert_handle);
235 return cert; 267 return cert;
236 } 268 }
237 269
238 // static 270 // static
239 X509Certificate* X509Certificate::CreateFromPickle(const Pickle& pickle, 271 X509Certificate* X509Certificate::CreateFromPickle(const Pickle& pickle,
240 void** pickle_iter, 272 void** pickle_iter,
241 PickleType type) { 273 PickleType type) {
242 OSCertHandle cert_handle = ReadOSCertHandleFromPickle(pickle, pickle_iter); 274 OSCertHandle cert_handle = ReadOSCertHandleFromPickle(pickle, pickle_iter);
243 if (!cert_handle) 275 if (!cert_handle)
(...skipping 11 matching lines...) Expand all
255 OSCertHandle intermediate = ReadOSCertHandleFromPickle(pickle, 287 OSCertHandle intermediate = ReadOSCertHandleFromPickle(pickle,
256 pickle_iter); 288 pickle_iter);
257 if (!intermediate) 289 if (!intermediate)
258 break; 290 break;
259 intermediates.push_back(intermediate); 291 intermediates.push_back(intermediate);
260 } 292 }
261 } 293 }
262 294
263 X509Certificate* cert = NULL; 295 X509Certificate* cert = NULL;
264 if (intermediates.size() == num_intermediates) 296 if (intermediates.size() == num_intermediates)
265 cert = CreateFromHandle(cert_handle, SOURCE_FROM_CACHE, intermediates); 297 cert = CreateFromHandle(cert_handle, intermediates);
266 FreeOSCertHandle(cert_handle); 298 FreeOSCertHandle(cert_handle);
267 for (size_t i = 0; i < intermediates.size(); ++i) 299 for (size_t i = 0; i < intermediates.size(); ++i)
268 FreeOSCertHandle(intermediates[i]); 300 FreeOSCertHandle(intermediates[i]);
269 301
270 return cert; 302 return cert;
271 } 303 }
272 304
273 // static 305 // static
274 CertificateList X509Certificate::CreateCertificateListFromBytes( 306 CertificateList X509Certificate::CreateCertificateListFromBytes(
275 const char* data, int length, int format) { 307 const char* data, int length, int format) {
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
332 kFormatDecodePriority[i]); 364 kFormatDecodePriority[i]);
333 } 365 }
334 366
335 CertificateList results; 367 CertificateList results;
336 // No certificates parsed. 368 // No certificates parsed.
337 if (certificates.empty()) 369 if (certificates.empty())
338 return results; 370 return results;
339 371
340 for (OSCertHandles::iterator it = certificates.begin(); 372 for (OSCertHandles::iterator it = certificates.begin();
341 it != certificates.end(); ++it) { 373 it != certificates.end(); ++it) {
342 X509Certificate* result = CreateFromHandle(*it, SOURCE_LONE_CERT_IMPORT, 374 X509Certificate* result = CreateFromHandle(*it, OSCertHandles());
343 OSCertHandles());
344 results.push_back(scoped_refptr<X509Certificate>(result)); 375 results.push_back(scoped_refptr<X509Certificate>(result));
345 FreeOSCertHandle(*it); 376 FreeOSCertHandle(*it);
346 } 377 }
347 378
348 return results; 379 return results;
349 } 380 }
350 381
351 void X509Certificate::Persist(Pickle* pickle) { 382 void X509Certificate::Persist(Pickle* pickle) {
352 DCHECK(cert_handle_); 383 DCHECK(cert_handle_);
353 if (!WriteOSCertHandleToPickle(cert_handle_, pickle)) { 384 if (!WriteOSCertHandleToPickle(cert_handle_, pickle)) {
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after
524 555
525 #if !defined(USE_NSS) 556 #if !defined(USE_NSS)
526 bool X509Certificate::VerifyNameMatch(const std::string& hostname) const { 557 bool X509Certificate::VerifyNameMatch(const std::string& hostname) const {
527 std::vector<std::string> dns_names; 558 std::vector<std::string> dns_names;
528 GetDNSNames(&dns_names); 559 GetDNSNames(&dns_names);
529 return VerifyHostname(hostname, dns_names); 560 return VerifyHostname(hostname, dns_names);
530 } 561 }
531 #endif 562 #endif
532 563
533 X509Certificate::X509Certificate(OSCertHandle cert_handle, 564 X509Certificate::X509Certificate(OSCertHandle cert_handle,
534 Source source,
535 const OSCertHandles& intermediates) 565 const OSCertHandles& intermediates)
536 : cert_handle_(DupOSCertHandle(cert_handle)), 566 : cert_handle_(DupOSCertHandle(cert_handle)) {
537 source_(source) { 567 X509CertificateCache* cache = g_x509_certificate_cache.Pointer();
538 // Copy/retain the intermediate cert handles. 568 cache->InsertOrUpdate(&cert_handle_);
539 for (size_t i = 0; i < intermediates.size(); ++i) 569 for (size_t i = 0; i < intermediates.size(); ++i) {
540 intermediate_ca_certs_.push_back(DupOSCertHandle(intermediates[i])); 570 // Duplicate the incoming certificate, as the caller retains ownership
571 // of |intermediates|.
572 OSCertHandle intermediate = DupOSCertHandle(intermediates[i]);
573 // Update the cache, which will assume ownership of the duplicated
574 // handle and return a suitable equivalent, potentially from the cache.
575 cache->InsertOrUpdate(&intermediate);
576 intermediate_ca_certs_.push_back(intermediate);
577 }
541 // Platform-specific initialization. 578 // Platform-specific initialization.
542 Initialize(); 579 Initialize();
543 } 580 }
544 581
545 X509Certificate::~X509Certificate() { 582 X509Certificate::~X509Certificate() {
546 // We might not be in the cache, but it is safe to remove ourselves anyway. 583 // We might not be in the cache, but it is safe to remove ourselves anyway.
547 g_x509_certificate_cache.Get().Remove(this); 584 X509CertificateCache* cache = g_x509_certificate_cache.Pointer();
548 if (cert_handle_) 585 if (cert_handle_) {
586 cache->Remove(cert_handle_);
549 FreeOSCertHandle(cert_handle_); 587 FreeOSCertHandle(cert_handle_);
550 for (size_t i = 0; i < intermediate_ca_certs_.size(); ++i) 588 }
589 for (size_t i = 0; i < intermediate_ca_certs_.size(); ++i) {
590 cache->Remove(intermediate_ca_certs_[i]);
551 FreeOSCertHandle(intermediate_ca_certs_[i]); 591 FreeOSCertHandle(intermediate_ca_certs_[i]);
592 }
552 } 593 }
553 594
554 bool X509Certificate::IsBlacklisted() const { 595 bool X509Certificate::IsBlacklisted() const {
555 static const unsigned kNumSerials = 10; 596 static const unsigned kNumSerials = 10;
556 static const unsigned kSerialBytes = 16; 597 static const unsigned kSerialBytes = 16;
557 static const uint8 kSerials[kNumSerials][kSerialBytes] = { 598 static const uint8 kSerials[kNumSerials][kSerialBytes] = {
558 // Not a real certificate. For testing only. 599 // Not a real certificate. For testing only.
559 {0x07,0x7a,0x59,0xbc,0xd5,0x34,0x59,0x60,0x1c,0xa6,0x90,0x72,0x67,0xa6,0xdd, 0x1c}, 600 {0x07,0x7a,0x59,0xbc,0xd5,0x34,0x59,0x60,0x1c,0xa6,0x90,0x72,0x67,0xa6,0xdd, 0x1c},
560 601
561 // The next nine certificates all expire on Fri Mar 14 23:59:59 2014. 602 // The next nine certificates all expire on Fri Mar 14 23:59:59 2014.
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
609 bool X509Certificate::IsSHA1HashInSortedArray(const SHA1Fingerprint& hash, 650 bool X509Certificate::IsSHA1HashInSortedArray(const SHA1Fingerprint& hash,
610 const uint8* array, 651 const uint8* array,
611 size_t array_byte_len) { 652 size_t array_byte_len) {
612 DCHECK_EQ(0u, array_byte_len % base::SHA1_LENGTH); 653 DCHECK_EQ(0u, array_byte_len % base::SHA1_LENGTH);
613 const unsigned arraylen = array_byte_len / base::SHA1_LENGTH; 654 const unsigned arraylen = array_byte_len / base::SHA1_LENGTH;
614 return NULL != bsearch(hash.data, array, arraylen, base::SHA1_LENGTH, 655 return NULL != bsearch(hash.data, array, arraylen, base::SHA1_LENGTH,
615 CompareSHA1Hashes); 656 CompareSHA1Hashes);
616 } 657 }
617 658
618 } // namespace net 659 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698