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

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: Rebase before commit 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
« no previous file with comments | « net/base/x509_certificate.h ('k') | net/base/x509_certificate_mac.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 <algorithm> 9 #include <algorithm>
10 #include <map> 10 #include <map>
11 #include <string> 11 #include <string>
12 #include <vector> 12 #include <vector>
13 13
14 #include "base/lazy_instance.h" 14 #include "base/lazy_instance.h"
15 #include "base/logging.h" 15 #include "base/logging.h"
16 #include "base/memory/singleton.h" 16 #include "base/memory/singleton.h"
17 #include "base/metrics/histogram.h" 17 #include "base/metrics/histogram.h"
18 #include "base/pickle.h" 18 #include "base/pickle.h"
19 #include "base/sha1.h" 19 #include "base/sha1.h"
20 #include "base/string_piece.h" 20 #include "base/string_piece.h"
21 #include "base/string_util.h" 21 #include "base/string_util.h"
22 #include "base/synchronization/lock.h"
22 #include "base/time.h" 23 #include "base/time.h"
23 #include "googleurl/src/url_canon_ip.h" 24 #include "googleurl/src/url_canon_ip.h"
24 #include "net/base/cert_status_flags.h" 25 #include "net/base/cert_status_flags.h"
25 #include "net/base/cert_verify_result.h" 26 #include "net/base/cert_verify_result.h"
26 #include "net/base/net_errors.h" 27 #include "net/base/net_errors.h"
27 #include "net/base/net_util.h" 28 #include "net/base/net_util.h"
28 #include "net/base/pem_tokenizer.h" 29 #include "net/base/pem_tokenizer.h"
29 30
30 namespace net { 31 namespace net {
31 32
(...skipping 14 matching lines...) Expand all
46 const X509Certificate::Format kFormatDecodePriority[] = { 47 const X509Certificate::Format kFormatDecodePriority[] = {
47 X509Certificate::FORMAT_SINGLE_CERTIFICATE, 48 X509Certificate::FORMAT_SINGLE_CERTIFICATE,
48 X509Certificate::FORMAT_PKCS7 49 X509Certificate::FORMAT_PKCS7
49 }; 50 };
50 51
51 // The PEM block header used for DER certificates 52 // The PEM block header used for DER certificates
52 const char kCertificateHeader[] = "CERTIFICATE"; 53 const char kCertificateHeader[] = "CERTIFICATE";
53 // The PEM block header used for PKCS#7 data 54 // The PEM block header used for PKCS#7 data
54 const char kPKCS7Header[] = "PKCS7"; 55 const char kPKCS7Header[] = "PKCS7";
55 56
56 // A thread-safe cache for X509Certificate objects. 57 // A thread-safe cache for OS certificate handles.
57 // 58 //
58 // The cache does not hold a reference to the certificate objects. The objects 59 // Within each of the supported underlying crypto libraries, a certificate
59 // must |Remove| themselves from the cache upon destruction (or else the cache 60 // handle is represented as a ref-counted object that contains the parsed
60 // will be holding dead pointers to the objects). 61 // data for the certificate. In addition, the underlying OS handle may also
61 // TODO(rsleevi): There exists a chance of a use-after-free, due to a race 62 // contain a copy of the original ASN.1 DER used to constructed the handle.
62 // between Find() and Remove(). See http://crbug.com/49377 63 //
64 // In order to reduce the memory usage when multiple SSL connections exist,
65 // with each connection storing the server's identity certificate plus any
66 // intermediates supplied, the certificate handles are cached. Any two
67 // X509Certificates that were created from the same ASN.1 DER data,
68 // regardless of where that data came from, will share the same underlying
69 // OS certificate handle.
63 class X509CertificateCache { 70 class X509CertificateCache {
64 public: 71 public:
65 void Insert(X509Certificate* cert); 72 // Performs a compare-and-swap like operation. If an OS certificate handle
66 void Remove(X509Certificate* cert); 73 // for the same certificate data as |*cert_handle| already exists in the
67 X509Certificate* Find(const SHA1Fingerprint& fingerprint); 74 // cache, the original |*cert_handle| will be freed and |cert_handle|
75 // will be updated to point to a duplicated reference to the existing cached
76 // certificate, with the caller taking ownership of this duplicated handle.
77 // If an equivalent OS certificate handle is not found, a duplicated
78 // reference to |*cert_handle| will be added to the cache. In either case,
79 // upon return, the caller fully owns |*cert_handle| and is responsible for
80 // calling FreeOSCertHandle(), after first calling Remove().
81 void InsertOrUpdate(X509Certificate::OSCertHandle* cert_handle);
82
83 // Decrements the cache reference count for |cert_handle|, a handle that was
84 // previously obtained by calling InsertOrUpdate(). If this is the last
85 // cached reference held, this will remove the handle from the cache. The
86 // caller retains ownership of |cert_handle| and remains responsible for
87 // calling FreeOSCertHandle() to release the underlying OS certificate
88 void Remove(X509Certificate::OSCertHandle cert_handle);
68 89
69 private: 90 private:
70 typedef std::map<SHA1Fingerprint, X509Certificate*, SHA1FingerprintLessThan> 91 // A single entry in the cache. Certificates will be keyed by their SHA1
71 CertMap; 92 // fingerprints, but will not be considered equivalent unless the entire
93 // certificate data matches.
94 struct Entry {
95 Entry() : cert_handle(NULL), ref_count(0) {}
96
97 X509Certificate::OSCertHandle cert_handle;
98
99 // Increased by each call to InsertOrUpdate(), and balanced by each call
100 // to Remove(). When it equals 0, all references created by
101 // InsertOrUpdate() have been released, so the cache entry will be removed
102 // the cached OS certificate handle will be freed.
103 int ref_count;
104 };
105 typedef std::map<SHA1Fingerprint, Entry, SHA1FingerprintLessThan> CertMap;
72 106
73 // Obtain an instance of X509CertificateCache via a LazyInstance. 107 // Obtain an instance of X509CertificateCache via a LazyInstance.
74 X509CertificateCache() {} 108 X509CertificateCache() {}
75 ~X509CertificateCache() {} 109 ~X509CertificateCache() {}
76 friend struct base::DefaultLazyInstanceTraits<X509CertificateCache>; 110 friend struct base::DefaultLazyInstanceTraits<X509CertificateCache>;
77 111
78 // You must acquire this lock before using any private data of this object. 112 // You must acquire this lock before using any private data of this object
79 // You must not block while holding this lock. 113 // You must not block while holding this lock.
80 base::Lock lock_; 114 base::Lock lock_;
81 115
82 // The certificate cache. You must acquire |lock_| before using |cache_|. 116 // The certificate cache. You must acquire |lock_| before using |cache_|.
83 CertMap cache_; 117 CertMap cache_;
84 118
85 DISALLOW_COPY_AND_ASSIGN(X509CertificateCache); 119 DISALLOW_COPY_AND_ASSIGN(X509CertificateCache);
86 }; 120 };
87 121
88 base::LazyInstance<X509CertificateCache, 122 base::LazyInstance<X509CertificateCache,
89 base::LeakyLazyInstanceTraits<X509CertificateCache> > 123 base::LeakyLazyInstanceTraits<X509CertificateCache> >
90 g_x509_certificate_cache(base::LINKER_INITIALIZED); 124 g_x509_certificate_cache(base::LINKER_INITIALIZED);
91 125
92 // Insert |cert| into the cache. The cache does NOT AddRef |cert|. 126 void X509CertificateCache::InsertOrUpdate(
93 // Any existing certificate with the same fingerprint will be replaced. 127 X509Certificate::OSCertHandle* cert_handle) {
94 void X509CertificateCache::Insert(X509Certificate* cert) { 128 DCHECK(cert_handle);
129 SHA1Fingerprint fingerprint =
130 X509Certificate::CalculateFingerprint(*cert_handle);
131
132 X509Certificate::OSCertHandle old_handle = NULL;
133 {
134 base::AutoLock lock(lock_);
135 CertMap::iterator pos = cache_.find(fingerprint);
136 if (pos == cache_.end()) {
137 // A cached entry was not found, so initialize a new entry. The entry
138 // assumes ownership of the current |*cert_handle|.
139 Entry cache_entry;
140 cache_entry.cert_handle = *cert_handle;
141 cache_entry.ref_count = 0;
142 CertMap::value_type cache_value(fingerprint, cache_entry);
143 pos = cache_.insert(cache_value).first;
144 } else {
145 bool is_same_cert =
146 X509Certificate::IsSameOSCert(*cert_handle, pos->second.cert_handle);
147 if (!is_same_cert) {
148 // Two certificates don't match, due to a SHA1 hash collision. Given
149 // the low probability, the simplest solution is to not cache the
150 // certificate, which should not affect performance too negatively.
151 return;
152 }
153 // A cached entry was found and will be used instead of the caller's
154 // handle. Ensure the caller's original handle will be freed, since
155 // ownership is assumed.
156 old_handle = *cert_handle;
157 }
158 // Whether an existing cached handle or a new handle, increment the
159 // cache's reference count and return a handle that the caller can own.
160 ++pos->second.ref_count;
161 *cert_handle = X509Certificate::DupOSCertHandle(pos->second.cert_handle);
162 }
163 // If the caller's handle was replaced with a cached handle, free the
164 // original handle now. This is done outside of the lock because
165 // |old_handle| may be the only handle for this particular certificate, so
166 // freeing it may be complex or resource-intensive and does not need to
167 // be guarded by the lock.
168 if (old_handle) {
169 X509Certificate::FreeOSCertHandle(old_handle);
170 DHISTOGRAM_COUNTS("X509CertificateReuseCount", 1);
171 }
172 }
173
174 void X509CertificateCache::Remove(X509Certificate::OSCertHandle cert_handle) {
175 SHA1Fingerprint fingerprint =
176 X509Certificate::CalculateFingerprint(cert_handle);
95 base::AutoLock lock(lock_); 177 base::AutoLock lock(lock_);
96 178
97 DCHECK(!IsNullFingerprint(cert->fingerprint())) << 179 CertMap::iterator pos = cache_.find(fingerprint);
98 "Only insert certs with real fingerprints."; 180 if (pos == cache_.end())
99 cache_[cert->fingerprint()] = cert; 181 return; // A hash collision where the winning cert was already freed.
100 };
101 182
102 // Remove |cert| from the cache. The cache does not assume that |cert| is 183 bool is_same_cert = X509Certificate::IsSameOSCert(cert_handle,
103 // already in the cache. 184 pos->second.cert_handle);
104 void X509CertificateCache::Remove(X509Certificate* cert) { 185 if (!is_same_cert)
105 base::AutoLock lock(lock_); 186 return; // A hash collision where the winning cert is still around.
106 187
107 CertMap::iterator pos(cache_.find(cert->fingerprint())); 188 if (--pos->second.ref_count == 0) {
108 if (pos == cache_.end()) 189 // The last reference to |cert_handle| has been removed, so release the
109 return; // It is not an error to remove a cert that is not in the cache. 190 // Entry's OS handle and remove the Entry. The caller still holds a
110 cache_.erase(pos); 191 // reference to |cert_handle| and is responsible for freeing it.
111 }; 192 X509Certificate::FreeOSCertHandle(pos->second.cert_handle);
112 193 cache_.erase(pos);
113 // Find a certificate in the cache with the given fingerprint. If one does 194 }
114 // not exist, this method returns NULL. 195 }
115 X509Certificate* X509CertificateCache::Find(
116 const SHA1Fingerprint& fingerprint) {
117 base::AutoLock lock(lock_);
118
119 CertMap::iterator pos(cache_.find(fingerprint));
120 if (pos == cache_.end())
121 return NULL;
122
123 return pos->second;
124 };
125 196
126 // CompareSHA1Hashes is a helper function for using bsearch() with an array of 197 // CompareSHA1Hashes is a helper function for using bsearch() with an array of
127 // SHA1 hashes. 198 // SHA1 hashes.
128 int CompareSHA1Hashes(const void* a, const void* b) { 199 int CompareSHA1Hashes(const void* a, const void* b) {
129 return memcmp(a, b, base::SHA1_LENGTH); 200 return memcmp(a, b, base::SHA1_LENGTH);
130 } 201 }
131 202
132 // Utility to split |src| on the first occurrence of |c|, if any. |right| will 203 // Utility to split |src| on the first occurrence of |c|, if any. |right| will
133 // either be empty if |c| was not found, or will contain the remainder of the 204 // either be empty if |c| was not found, or will contain the remainder of the
134 // string including the split character itself. 205 // string including the split character itself.
(...skipping 23 matching lines...) Expand all
158 } 229 }
159 230
160 X509Certificate::X509Certificate(const std::string& subject, 231 X509Certificate::X509Certificate(const std::string& subject,
161 const std::string& issuer, 232 const std::string& issuer,
162 base::Time start_date, 233 base::Time start_date,
163 base::Time expiration_date) 234 base::Time expiration_date)
164 : subject_(subject), 235 : subject_(subject),
165 issuer_(issuer), 236 issuer_(issuer),
166 valid_start_(start_date), 237 valid_start_(start_date),
167 valid_expiry_(expiration_date), 238 valid_expiry_(expiration_date),
168 cert_handle_(NULL), 239 cert_handle_(NULL) {
169 source_(SOURCE_UNUSED) {
170 memset(fingerprint_.data, 0, sizeof(fingerprint_.data)); 240 memset(fingerprint_.data, 0, sizeof(fingerprint_.data));
171 } 241 }
172 242
173 // static 243 // static
174 X509Certificate* X509Certificate::CreateFromHandle( 244 X509Certificate* X509Certificate::CreateFromHandle(
175 OSCertHandle cert_handle, 245 OSCertHandle cert_handle,
176 Source source,
177 const OSCertHandles& intermediates) { 246 const OSCertHandles& intermediates) {
178 DCHECK(cert_handle); 247 DCHECK(cert_handle);
179 DCHECK_NE(source, SOURCE_UNUSED); 248 return new X509Certificate(cert_handle, intermediates);
180
181 // Check if we already have this certificate in memory.
182 X509CertificateCache* cache = g_x509_certificate_cache.Pointer();
183 X509Certificate* cached_cert =
184 cache->Find(CalculateFingerprint(cert_handle));
185 if (cached_cert) {
186 DCHECK_NE(cached_cert->source_, SOURCE_UNUSED);
187 if (cached_cert->source_ > source ||
188 (cached_cert->source_ == source &&
189 cached_cert->HasIntermediateCertificates(intermediates))) {
190 // Return the certificate with the same fingerprint from our cache.
191 DHISTOGRAM_COUNTS("X509CertificateReuseCount", 1);
192 return cached_cert;
193 }
194 // Else the new cert is better and will replace the old one in the cache.
195 }
196
197 // Otherwise, allocate and cache a new object.
198 X509Certificate* cert = new X509Certificate(cert_handle, source,
199 intermediates);
200 cache->Insert(cert);
201 return cert;
202 } 249 }
203 250
204 #if defined(OS_WIN)
205 static X509Certificate::OSCertHandle CreateOSCert(base::StringPiece der_cert) {
206 X509Certificate::OSCertHandle cert_handle = NULL;
207 BOOL ok = CertAddEncodedCertificateToStore(
208 X509Certificate::cert_store(), X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
209 reinterpret_cast<const BYTE*>(der_cert.data()), der_cert.size(),
210 CERT_STORE_ADD_USE_EXISTING, &cert_handle);
211 return ok ? cert_handle : NULL;
212 }
213 #else
214 static X509Certificate::OSCertHandle CreateOSCert(base::StringPiece der_cert) { 251 static X509Certificate::OSCertHandle CreateOSCert(base::StringPiece der_cert) {
215 return X509Certificate::CreateOSCertHandleFromBytes( 252 return X509Certificate::CreateOSCertHandleFromBytes(
216 const_cast<char*>(der_cert.data()), der_cert.size()); 253 const_cast<char*>(der_cert.data()), der_cert.size());
217 } 254 }
218 #endif
219 255
220 // static 256 // static
221 X509Certificate* X509Certificate::CreateFromDERCertChain( 257 X509Certificate* X509Certificate::CreateFromDERCertChain(
222 const std::vector<base::StringPiece>& der_certs) { 258 const std::vector<base::StringPiece>& der_certs) {
223 if (der_certs.empty()) 259 if (der_certs.empty())
224 return NULL; 260 return NULL;
225 261
226 X509Certificate::OSCertHandles intermediate_ca_certs; 262 X509Certificate::OSCertHandles intermediate_ca_certs;
227 for (size_t i = 1; i < der_certs.size(); i++) { 263 for (size_t i = 1; i < der_certs.size(); i++) {
228 OSCertHandle handle = CreateOSCert(der_certs[i]); 264 OSCertHandle handle = CreateOSCert(der_certs[i]);
229 DCHECK(handle); 265 DCHECK(handle);
230 intermediate_ca_certs.push_back(handle); 266 intermediate_ca_certs.push_back(handle);
231 } 267 }
232 268
233 OSCertHandle handle = CreateOSCert(der_certs[0]); 269 OSCertHandle handle = CreateOSCert(der_certs[0]);
234 DCHECK(handle); 270 DCHECK(handle);
235 X509Certificate* cert = 271 X509Certificate* cert = CreateFromHandle(handle, intermediate_ca_certs);
236 CreateFromHandle(handle, SOURCE_FROM_NETWORK, intermediate_ca_certs);
237 FreeOSCertHandle(handle); 272 FreeOSCertHandle(handle);
238 for (size_t i = 0; i < intermediate_ca_certs.size(); i++) 273 for (size_t i = 0; i < intermediate_ca_certs.size(); i++)
239 FreeOSCertHandle(intermediate_ca_certs[i]); 274 FreeOSCertHandle(intermediate_ca_certs[i]);
240 275
241 return cert; 276 return cert;
242 } 277 }
243 278
244 // static 279 // static
245 X509Certificate* X509Certificate::CreateFromBytes(const char* data, 280 X509Certificate* X509Certificate::CreateFromBytes(const char* data,
246 int length) { 281 int length) {
247 OSCertHandle cert_handle = CreateOSCertHandleFromBytes(data, length); 282 OSCertHandle cert_handle = CreateOSCertHandleFromBytes(data, length);
248 if (!cert_handle) 283 if (!cert_handle)
249 return NULL; 284 return NULL;
250 285
251 X509Certificate* cert = CreateFromHandle(cert_handle, 286 X509Certificate* cert = CreateFromHandle(cert_handle, OSCertHandles());
252 SOURCE_LONE_CERT_IMPORT,
253 OSCertHandles());
254 FreeOSCertHandle(cert_handle); 287 FreeOSCertHandle(cert_handle);
255 return cert; 288 return cert;
256 } 289 }
257 290
258 // static 291 // static
259 X509Certificate* X509Certificate::CreateFromPickle(const Pickle& pickle, 292 X509Certificate* X509Certificate::CreateFromPickle(const Pickle& pickle,
260 void** pickle_iter, 293 void** pickle_iter,
261 PickleType type) { 294 PickleType type) {
262 OSCertHandle cert_handle = ReadOSCertHandleFromPickle(pickle, pickle_iter); 295 OSCertHandle cert_handle = ReadOSCertHandleFromPickle(pickle, pickle_iter);
263 if (!cert_handle) 296 if (!cert_handle)
(...skipping 11 matching lines...) Expand all
275 OSCertHandle intermediate = ReadOSCertHandleFromPickle(pickle, 308 OSCertHandle intermediate = ReadOSCertHandleFromPickle(pickle,
276 pickle_iter); 309 pickle_iter);
277 if (!intermediate) 310 if (!intermediate)
278 break; 311 break;
279 intermediates.push_back(intermediate); 312 intermediates.push_back(intermediate);
280 } 313 }
281 } 314 }
282 315
283 X509Certificate* cert = NULL; 316 X509Certificate* cert = NULL;
284 if (intermediates.size() == num_intermediates) 317 if (intermediates.size() == num_intermediates)
285 cert = CreateFromHandle(cert_handle, SOURCE_FROM_CACHE, intermediates); 318 cert = CreateFromHandle(cert_handle, intermediates);
286 FreeOSCertHandle(cert_handle); 319 FreeOSCertHandle(cert_handle);
287 for (size_t i = 0; i < intermediates.size(); ++i) 320 for (size_t i = 0; i < intermediates.size(); ++i)
288 FreeOSCertHandle(intermediates[i]); 321 FreeOSCertHandle(intermediates[i]);
289 322
290 return cert; 323 return cert;
291 } 324 }
292 325
293 // static 326 // static
294 CertificateList X509Certificate::CreateCertificateListFromBytes( 327 CertificateList X509Certificate::CreateCertificateListFromBytes(
295 const char* data, int length, int format) { 328 const char* data, int length, int format) {
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
352 kFormatDecodePriority[i]); 385 kFormatDecodePriority[i]);
353 } 386 }
354 387
355 CertificateList results; 388 CertificateList results;
356 // No certificates parsed. 389 // No certificates parsed.
357 if (certificates.empty()) 390 if (certificates.empty())
358 return results; 391 return results;
359 392
360 for (OSCertHandles::iterator it = certificates.begin(); 393 for (OSCertHandles::iterator it = certificates.begin();
361 it != certificates.end(); ++it) { 394 it != certificates.end(); ++it) {
362 X509Certificate* result = CreateFromHandle(*it, SOURCE_LONE_CERT_IMPORT, 395 X509Certificate* result = CreateFromHandle(*it, OSCertHandles());
363 OSCertHandles());
364 results.push_back(scoped_refptr<X509Certificate>(result)); 396 results.push_back(scoped_refptr<X509Certificate>(result));
365 FreeOSCertHandle(*it); 397 FreeOSCertHandle(*it);
366 } 398 }
367 399
368 return results; 400 return results;
369 } 401 }
370 402
371 void X509Certificate::Persist(Pickle* pickle) { 403 void X509Certificate::Persist(Pickle* pickle) {
372 DCHECK(cert_handle_); 404 DCHECK(cert_handle_);
373 if (!WriteOSCertHandleToPickle(cert_handle_, pickle)) { 405 if (!WriteOSCertHandleToPickle(cert_handle_, pickle)) {
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
547 bool X509Certificate::VerifyNameMatch(const std::string& hostname) const { 579 bool X509Certificate::VerifyNameMatch(const std::string& hostname) const {
548 // TODO(joth): Define a cross platform version of ParseSubjectAltName and use 580 // TODO(joth): Define a cross platform version of ParseSubjectAltName and use
549 // that to retrieve dns names and ip addresses, independent of common name. 581 // that to retrieve dns names and ip addresses, independent of common name.
550 std::vector<std::string> dns_names, ip_addrs; 582 std::vector<std::string> dns_names, ip_addrs;
551 GetDNSNames(&dns_names); 583 GetDNSNames(&dns_names);
552 return VerifyHostname(hostname, subject_.common_name, dns_names, ip_addrs); 584 return VerifyHostname(hostname, subject_.common_name, dns_names, ip_addrs);
553 } 585 }
554 #endif 586 #endif
555 587
556 X509Certificate::X509Certificate(OSCertHandle cert_handle, 588 X509Certificate::X509Certificate(OSCertHandle cert_handle,
557 Source source,
558 const OSCertHandles& intermediates) 589 const OSCertHandles& intermediates)
559 : cert_handle_(DupOSCertHandle(cert_handle)), 590 : cert_handle_(DupOSCertHandle(cert_handle)) {
560 source_(source) { 591 X509CertificateCache* cache = g_x509_certificate_cache.Pointer();
561 // Copy/retain the intermediate cert handles. 592 cache->InsertOrUpdate(&cert_handle_);
562 for (size_t i = 0; i < intermediates.size(); ++i) 593 for (size_t i = 0; i < intermediates.size(); ++i) {
563 intermediate_ca_certs_.push_back(DupOSCertHandle(intermediates[i])); 594 // Duplicate the incoming certificate, as the caller retains ownership
595 // of |intermediates|.
596 OSCertHandle intermediate = DupOSCertHandle(intermediates[i]);
597 // Update the cache, which will assume ownership of the duplicated
598 // handle and return a suitable equivalent, potentially from the cache.
599 cache->InsertOrUpdate(&intermediate);
600 intermediate_ca_certs_.push_back(intermediate);
601 }
564 // Platform-specific initialization. 602 // Platform-specific initialization.
565 Initialize(); 603 Initialize();
566 } 604 }
567 605
568 X509Certificate::~X509Certificate() { 606 X509Certificate::~X509Certificate() {
569 // We might not be in the cache, but it is safe to remove ourselves anyway. 607 // We might not be in the cache, but it is safe to remove ourselves anyway.
570 g_x509_certificate_cache.Get().Remove(this); 608 X509CertificateCache* cache = g_x509_certificate_cache.Pointer();
571 if (cert_handle_) 609 if (cert_handle_) {
610 cache->Remove(cert_handle_);
572 FreeOSCertHandle(cert_handle_); 611 FreeOSCertHandle(cert_handle_);
573 for (size_t i = 0; i < intermediate_ca_certs_.size(); ++i) 612 }
613 for (size_t i = 0; i < intermediate_ca_certs_.size(); ++i) {
614 cache->Remove(intermediate_ca_certs_[i]);
574 FreeOSCertHandle(intermediate_ca_certs_[i]); 615 FreeOSCertHandle(intermediate_ca_certs_[i]);
616 }
575 } 617 }
576 618
577 bool X509Certificate::IsBlacklisted() const { 619 bool X509Certificate::IsBlacklisted() const {
578 static const unsigned kNumSerials = 10; 620 static const unsigned kNumSerials = 10;
579 static const unsigned kSerialBytes = 16; 621 static const unsigned kSerialBytes = 16;
580 static const uint8 kSerials[kNumSerials][kSerialBytes] = { 622 static const uint8 kSerials[kNumSerials][kSerialBytes] = {
581 // Not a real certificate. For testing only. 623 // Not a real certificate. For testing only.
582 {0x07,0x7a,0x59,0xbc,0xd5,0x34,0x59,0x60,0x1c,0xa6,0x90,0x72,0x67,0xa6,0xdd, 0x1c}, 624 {0x07,0x7a,0x59,0xbc,0xd5,0x34,0x59,0x60,0x1c,0xa6,0x90,0x72,0x67,0xa6,0xdd, 0x1c},
583 625
584 // The next nine certificates all expire on Fri Mar 14 23:59:59 2014. 626 // 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
632 bool X509Certificate::IsSHA1HashInSortedArray(const SHA1Fingerprint& hash, 674 bool X509Certificate::IsSHA1HashInSortedArray(const SHA1Fingerprint& hash,
633 const uint8* array, 675 const uint8* array,
634 size_t array_byte_len) { 676 size_t array_byte_len) {
635 DCHECK_EQ(0u, array_byte_len % base::SHA1_LENGTH); 677 DCHECK_EQ(0u, array_byte_len % base::SHA1_LENGTH);
636 const unsigned arraylen = array_byte_len / base::SHA1_LENGTH; 678 const unsigned arraylen = array_byte_len / base::SHA1_LENGTH;
637 return NULL != bsearch(hash.data, array, arraylen, base::SHA1_LENGTH, 679 return NULL != bsearch(hash.data, array, arraylen, base::SHA1_LENGTH,
638 CompareSHA1Hashes); 680 CompareSHA1Hashes);
639 } 681 }
640 682
641 } // namespace net 683 } // namespace net
OLDNEW
« no previous file with comments | « net/base/x509_certificate.h ('k') | net/base/x509_certificate_mac.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698