| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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 <map> | 7 #include <map> |
| 8 | 8 |
| 9 #include "base/lazy_instance.h" | 9 #include "base/lazy_instance.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| (...skipping 23 matching lines...) Expand all Loading... |
| 34 const X509Certificate::Format kFormatDecodePriority[] = { | 34 const X509Certificate::Format kFormatDecodePriority[] = { |
| 35 X509Certificate::FORMAT_SINGLE_CERTIFICATE, | 35 X509Certificate::FORMAT_SINGLE_CERTIFICATE, |
| 36 X509Certificate::FORMAT_PKCS7 | 36 X509Certificate::FORMAT_PKCS7 |
| 37 }; | 37 }; |
| 38 | 38 |
| 39 // The PEM block header used for DER certificates | 39 // The PEM block header used for DER certificates |
| 40 const char kCertificateHeader[] = "CERTIFICATE"; | 40 const char kCertificateHeader[] = "CERTIFICATE"; |
| 41 // The PEM block header used for PKCS#7 data | 41 // The PEM block header used for PKCS#7 data |
| 42 const char kPKCS7Header[] = "PKCS7"; | 42 const char kPKCS7Header[] = "PKCS7"; |
| 43 | 43 |
| 44 // A thread-safe cache for X509Certificate objects. | 44 // A thread-safe cache for OS certificate handles. |
| 45 // | 45 // |
| 46 // The cache does not hold a reference to the certificate objects. The objects | 46 // Within each of the supported underlying crypto libraries, a certificate |
| 47 // must |Remove| themselves from the cache upon destruction (or else the cache | 47 // handle is represented as a ref-counted object that contains the parsed |
| 48 // will be holding dead pointers to the objects). | 48 // data for the certificate. In addition, the underlying OS handle may also |
| 49 // TODO(rsleevi): There exists a chance of a use-after-free, due to a race | 49 // contain a copy of the original ASN.1 DER used to constructed the handle. |
| 50 // between Find() and Remove(). See http://crbug.com/49377 | 50 // |
| 51 // In order to reduce the memory usage when multiple SSL connections exist, |
| 52 // with each connection storing the server's identity certificate plus any |
| 53 // intermediates supplied, the certificate handles are cached. Any two |
| 54 // X509Certificates that were created from the same ASN.1 DER data, |
| 55 // regardless of where that data came from, will share the same underlying |
| 56 // OS certificate handle. |
| 51 class X509CertificateCache { | 57 class X509CertificateCache { |
| 52 public: | 58 public: |
| 53 void Insert(X509Certificate* cert); | 59 // Performs a compare-and-swap like operation. If an OS certificate handle |
| 54 void Remove(X509Certificate* cert); | 60 // for the same certificate data as |*cert_handle| already exists in the |
| 55 X509Certificate* Find(const SHA1Fingerprint& fingerprint); | 61 // cache, the original |*cert_handle| will be freed, and |cert_handle| |
| 62 // will be updated to point to the existing cached certificate, after |
| 63 // adding to the reference count. If an equivalent OS certificate handle |
| 64 // is not found, |*cert_handle| will be added to the cache and its |
| 65 // reference count increased, while otherwise remaining unmodified and |
| 66 // pointing to the caller's original certificate. |
| 67 void InsertOrUpdate(X509Certificate::OSCertHandle* cert_handle); |
| 68 |
| 69 // Decrements the reference count for |cert_handle|, and if it is the last |
| 70 // reference held in the cache, frees the underlying OS certificate |
| 71 // handle. InsertOrUpdate() must have been called prior to Remove() for |
| 72 // the |cert_handle|. |
| 73 void Remove(X509Certificate::OSCertHandle cert_handle); |
| 56 | 74 |
| 57 private: | 75 private: |
| 58 typedef std::map<SHA1Fingerprint, X509Certificate*, SHA1FingerprintLessThan> | 76 // A single entry in the cache. Certificates will be keyed by their SHA1 |
| 59 CertMap; | 77 // fingerprints, but will not be considered equivalent unless the entire |
| 78 // certificate data matches. |
| 79 struct Entry { |
| 80 Entry() : cert_handle(NULL), ref_count(0) {} |
| 81 X509Certificate::OSCertHandle cert_handle; |
| 82 |
| 83 // Increased by each call to InsertOrUpdate(), and balanced by each call |
| 84 // to Remove(). When it equals 0, all references have been released, so |
| 85 // the cache entry will be removed and the OS certificate released. |
| 86 size_t ref_count; |
| 87 }; |
| 88 typedef std::map<SHA1Fingerprint, Entry, SHA1FingerprintLessThan> CertMap; |
| 60 | 89 |
| 61 // Obtain an instance of X509CertificateCache via a LazyInstance. | 90 // Obtain an instance of X509CertificateCache via a LazyInstance. |
| 62 X509CertificateCache() {} | 91 X509CertificateCache() {} |
| 63 ~X509CertificateCache() {} | 92 ~X509CertificateCache() {} |
| 64 friend struct base::DefaultLazyInstanceTraits<X509CertificateCache>; | 93 friend struct base::DefaultLazyInstanceTraits<X509CertificateCache>; |
| 65 | 94 |
| 66 // You must acquire this lock before using any private data of this object. | 95 // You must acquire this lock before using any private data of this |
| 67 // You must not block while holding this lock. | 96 // object. You must not block while holding this lock. |
| 68 Lock lock_; | 97 Lock lock_; |
| 69 | 98 |
| 70 // The certificate cache. You must acquire |lock_| before using |cache_|. | 99 // The certificate cache. You must acquire |lock_| before using |cache_|. |
| 71 CertMap cache_; | 100 CertMap cache_; |
| 72 | 101 |
| 73 DISALLOW_COPY_AND_ASSIGN(X509CertificateCache); | 102 DISALLOW_COPY_AND_ASSIGN(X509CertificateCache); |
| 74 }; | 103 }; |
| 75 | 104 |
| 76 base::LazyInstance<X509CertificateCache, | 105 base::LazyInstance<X509CertificateCache, |
| 77 base::LeakyLazyInstanceTraits<X509CertificateCache> > | 106 base::LeakyLazyInstanceTraits<X509CertificateCache> > |
| 78 g_x509_certificate_cache(base::LINKER_INITIALIZED); | 107 g_x509_certificate_cache(base::LINKER_INITIALIZED); |
| 79 | 108 |
| 80 // Insert |cert| into the cache. The cache does NOT AddRef |cert|. | 109 void X509CertificateCache::InsertOrUpdate( |
| 81 // Any existing certificate with the same fingerprint will be replaced. | 110 X509Certificate::OSCertHandle* cert_handle) { |
| 82 void X509CertificateCache::Insert(X509Certificate* cert) { | 111 DCHECK(cert_handle); |
| 112 SHA1Fingerprint fingerprint = |
| 113 X509Certificate::CalculateFingerprint(*cert_handle); |
| 114 DCHECK(!IsNullFingerprint(fingerprint)) << |
| 115 "Only insert certs with real fingerprints."; |
| 116 |
| 117 AutoLock lock(lock_); |
| 118 CertMap::iterator pos(cache_.find(fingerprint)); |
| 119 if (pos == cache_.end()) { |
| 120 // Cached entry not found. Initialize a new entry. |*cert_handle| is |
| 121 // guaranteed to have at least one OS reference (the caller's), which |
| 122 // will be incremented, along with cache_entry.ref_count, below. |
| 123 Entry cache_entry; |
| 124 cache_entry.cert_handle = *cert_handle; |
| 125 cache_entry.ref_count = 0; |
| 126 CertMap::value_type cache_value(fingerprint, cache_entry); |
| 127 pos = cache_.insert(cache_value).first; |
| 128 } else { |
| 129 bool is_same_cert = |
| 130 X509Certificate::IsSameOSCert(*cert_handle, pos->second.cert_handle); |
| 131 if (!is_same_cert) { |
| 132 // Two certificates don't match, likely due to a SHA1 hash collision. |
| 133 // Given the low probability, the simplest solution is to not cache |
| 134 // the certificate, which should not affect performance too |
| 135 // negatively. |
| 136 return; |
| 137 } |
| 138 // Release the caller's reference to |*cert_handle|, as it will be |
| 139 // replaced by the cached handle just found. |
| 140 X509Certificate::FreeOSCertHandle(*cert_handle); |
| 141 DHISTOGRAM_COUNTS("X509CertificateReuseCount", 1); |
| 142 } |
| 143 |
| 144 ++pos->second.ref_count; |
| 145 *cert_handle = X509Certificate::DupOSCertHandle(pos->second.cert_handle); |
| 146 } |
| 147 |
| 148 void X509CertificateCache::Remove(X509Certificate::OSCertHandle cert_handle) { |
| 149 SHA1Fingerprint fingerprint = |
| 150 X509Certificate::CalculateFingerprint(cert_handle); |
| 83 AutoLock lock(lock_); | 151 AutoLock lock(lock_); |
| 84 | 152 |
| 85 DCHECK(!IsNullFingerprint(cert->fingerprint())) << | 153 CertMap::iterator pos(cache_.find(fingerprint)); |
| 86 "Only insert certs with real fingerprints."; | 154 if (pos == cache_.end()) |
| 87 cache_[cert->fingerprint()] = cert; | 155 return; // A cache collision where the winning cert was already freed. |
| 88 }; | |
| 89 | 156 |
| 90 // Remove |cert| from the cache. The cache does not assume that |cert| is | 157 bool is_same_cert = X509Certificate::IsSameOSCert(cert_handle, |
| 91 // already in the cache. | 158 pos->second.cert_handle); |
| 92 void X509CertificateCache::Remove(X509Certificate* cert) { | 159 DCHECK(is_same_cert) << "Hash collision between different certificates"; |
| 93 AutoLock lock(lock_); | 160 if (!is_same_cert) |
| 161 return; // A cache collision where the winning cert is still around. |
| 94 | 162 |
| 95 CertMap::iterator pos(cache_.find(cert->fingerprint())); | 163 if (--pos->second.ref_count == 0) { |
| 96 if (pos == cache_.end()) | 164 // The last reference to |cert_handle| has been removed, so release the |
| 97 return; // It is not an error to remove a cert that is not in the cache. | 165 // underlying OS handle and remove from the cache. The caller still |
| 98 cache_.erase(pos); | 166 // holds a reference to the underlying OS handle and still bears |
| 99 }; | 167 // responsibility for freeing it. |
| 100 | 168 X509Certificate::FreeOSCertHandle(pos->second.cert_handle); |
| 101 // Find a certificate in the cache with the given fingerprint. If one does | 169 cache_.erase(pos); |
| 102 // not exist, this method returns NULL. | 170 } |
| 103 X509Certificate* X509CertificateCache::Find( | 171 } |
| 104 const SHA1Fingerprint& fingerprint) { | |
| 105 AutoLock lock(lock_); | |
| 106 | |
| 107 CertMap::iterator pos(cache_.find(fingerprint)); | |
| 108 if (pos == cache_.end()) | |
| 109 return NULL; | |
| 110 | |
| 111 return pos->second; | |
| 112 }; | |
| 113 | 172 |
| 114 } // namespace | 173 } // namespace |
| 115 | 174 |
| 116 bool X509Certificate::LessThan::operator()(X509Certificate* lhs, | 175 bool X509Certificate::LessThan::operator()(X509Certificate* lhs, |
| 117 X509Certificate* rhs) const { | 176 X509Certificate* rhs) const { |
| 118 if (lhs == rhs) | 177 if (lhs == rhs) |
| 119 return false; | 178 return false; |
| 120 | 179 |
| 121 SHA1FingerprintLessThan fingerprint_functor; | 180 SHA1FingerprintLessThan fingerprint_functor; |
| 122 return fingerprint_functor(lhs->fingerprint_, rhs->fingerprint_); | 181 return fingerprint_functor(lhs->fingerprint_, rhs->fingerprint_); |
| 123 } | 182 } |
| 124 | 183 |
| 125 // static | 184 // static |
| 126 X509Certificate* X509Certificate::CreateFromHandle( | 185 X509Certificate* X509Certificate::CreateFromHandle( |
| 127 OSCertHandle cert_handle, | 186 OSCertHandle cert_handle, |
| 128 Source source, | |
| 129 const OSCertHandles& intermediates) { | 187 const OSCertHandles& intermediates) { |
| 130 DCHECK(cert_handle); | 188 DCHECK(cert_handle); |
| 131 DCHECK(source != SOURCE_UNUSED); | 189 X509Certificate* cert = new X509Certificate(cert_handle, intermediates); |
| 132 | |
| 133 // Check if we already have this certificate in memory. | |
| 134 X509CertificateCache* cache = g_x509_certificate_cache.Pointer(); | |
| 135 X509Certificate* cached_cert = | |
| 136 cache->Find(CalculateFingerprint(cert_handle)); | |
| 137 if (cached_cert) { | |
| 138 DCHECK(cached_cert->source_ != SOURCE_UNUSED); | |
| 139 if (cached_cert->source_ > source || | |
| 140 (cached_cert->source_ == source && | |
| 141 cached_cert->HasIntermediateCertificates(intermediates))) { | |
| 142 // Return the certificate with the same fingerprint from our cache. | |
| 143 DHISTOGRAM_COUNTS("X509CertificateReuseCount", 1); | |
| 144 return cached_cert; | |
| 145 } | |
| 146 // Else the new cert is better and will replace the old one in the cache. | |
| 147 } | |
| 148 | |
| 149 // Otherwise, allocate and cache a new object. | |
| 150 X509Certificate* cert = new X509Certificate(cert_handle, source, | |
| 151 intermediates); | |
| 152 cache->Insert(cert); | |
| 153 return cert; | 190 return cert; |
| 154 } | 191 } |
| 155 | 192 |
| 156 #if defined(OS_WIN) | 193 #if defined(OS_WIN) |
| 157 static X509Certificate::OSCertHandle CreateOSCert(base::StringPiece der_cert) { | 194 static X509Certificate::OSCertHandle CreateOSCert(base::StringPiece der_cert) { |
| 158 X509Certificate::OSCertHandle cert_handle = NULL; | 195 X509Certificate::OSCertHandle cert_handle = NULL; |
| 159 BOOL ok = CertAddEncodedCertificateToStore( | 196 BOOL ok = CertAddEncodedCertificateToStore( |
| 160 X509Certificate::cert_store(), X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, | 197 X509Certificate::cert_store(), X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, |
| 161 reinterpret_cast<const BYTE*>(der_cert.data()), der_cert.size(), | 198 reinterpret_cast<const BYTE*>(der_cert.data()), der_cert.size(), |
| 162 CERT_STORE_ADD_USE_EXISTING, &cert_handle); | 199 CERT_STORE_ADD_USE_EXISTING, &cert_handle); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 177 | 214 |
| 178 X509Certificate::OSCertHandles intermediate_ca_certs; | 215 X509Certificate::OSCertHandles intermediate_ca_certs; |
| 179 for (size_t i = 1; i < der_certs.size(); i++) { | 216 for (size_t i = 1; i < der_certs.size(); i++) { |
| 180 OSCertHandle handle = CreateOSCert(der_certs[i]); | 217 OSCertHandle handle = CreateOSCert(der_certs[i]); |
| 181 DCHECK(handle); | 218 DCHECK(handle); |
| 182 intermediate_ca_certs.push_back(handle); | 219 intermediate_ca_certs.push_back(handle); |
| 183 } | 220 } |
| 184 | 221 |
| 185 OSCertHandle handle = CreateOSCert(der_certs[0]); | 222 OSCertHandle handle = CreateOSCert(der_certs[0]); |
| 186 DCHECK(handle); | 223 DCHECK(handle); |
| 187 X509Certificate* cert = | 224 X509Certificate* cert = CreateFromHandle(handle, intermediate_ca_certs); |
| 188 CreateFromHandle(handle, SOURCE_FROM_NETWORK, intermediate_ca_certs); | |
| 189 FreeOSCertHandle(handle); | 225 FreeOSCertHandle(handle); |
| 190 for (size_t i = 0; i < intermediate_ca_certs.size(); i++) | 226 for (size_t i = 0; i < intermediate_ca_certs.size(); i++) |
| 191 FreeOSCertHandle(intermediate_ca_certs[i]); | 227 FreeOSCertHandle(intermediate_ca_certs[i]); |
| 192 | 228 |
| 193 return cert; | 229 return cert; |
| 194 } | 230 } |
| 195 | 231 |
| 196 // static | 232 // static |
| 197 X509Certificate* X509Certificate::CreateFromBytes(const char* data, | 233 X509Certificate* X509Certificate::CreateFromBytes(const char* data, |
| 198 int length) { | 234 int length) { |
| 199 OSCertHandle cert_handle = CreateOSCertHandleFromBytes(data, length); | 235 OSCertHandle cert_handle = CreateOSCertHandleFromBytes(data, length); |
| 200 if (!cert_handle) | 236 if (!cert_handle) |
| 201 return NULL; | 237 return NULL; |
| 202 | 238 |
| 203 X509Certificate* cert = CreateFromHandle(cert_handle, | 239 X509Certificate* cert = CreateFromHandle(cert_handle, OSCertHandles()); |
| 204 SOURCE_LONE_CERT_IMPORT, | |
| 205 OSCertHandles()); | |
| 206 FreeOSCertHandle(cert_handle); | 240 FreeOSCertHandle(cert_handle); |
| 207 return cert; | 241 return cert; |
| 208 } | 242 } |
| 209 | 243 |
| 210 // static | 244 // static |
| 211 X509Certificate* X509Certificate::CreateFromPickle(const Pickle& pickle, | 245 X509Certificate* X509Certificate::CreateFromPickle(const Pickle& pickle, |
| 212 void** pickle_iter, | 246 void** pickle_iter, |
| 213 PickleType type) { | 247 PickleType type) { |
| 214 OSCertHandle cert_handle = ReadCertHandleFromPickle(pickle, pickle_iter); | 248 OSCertHandle cert_handle = ReadCertHandleFromPickle(pickle, pickle_iter); |
| 215 OSCertHandles intermediates; | 249 OSCertHandles intermediates; |
| (...skipping 24 matching lines...) Expand all Loading... |
| 240 if (!ok) { | 274 if (!ok) { |
| 241 FreeOSCertHandle(cert_handle); | 275 FreeOSCertHandle(cert_handle); |
| 242 for (size_t i = 0; i < intermediates.size(); ++i) | 276 for (size_t i = 0; i < intermediates.size(); ++i) |
| 243 FreeOSCertHandle(intermediates[i]); | 277 FreeOSCertHandle(intermediates[i]); |
| 244 return NULL; | 278 return NULL; |
| 245 } | 279 } |
| 246 } | 280 } |
| 247 | 281 |
| 248 if (!cert_handle) | 282 if (!cert_handle) |
| 249 return NULL; | 283 return NULL; |
| 250 X509Certificate* cert = CreateFromHandle(cert_handle, SOURCE_FROM_CACHE, | 284 X509Certificate* cert = CreateFromHandle(cert_handle, intermediates); |
| 251 intermediates); | |
| 252 FreeOSCertHandle(cert_handle); | 285 FreeOSCertHandle(cert_handle); |
| 253 for (size_t i = 0; i < intermediates.size(); ++i) | 286 for (size_t i = 0; i < intermediates.size(); ++i) |
| 254 FreeOSCertHandle(intermediates[i]); | 287 FreeOSCertHandle(intermediates[i]); |
| 255 | 288 |
| 256 return cert; | 289 return cert; |
| 257 } | 290 } |
| 258 | 291 |
| 259 // static | 292 // static |
| 260 CertificateList X509Certificate::CreateCertificateListFromBytes( | 293 CertificateList X509Certificate::CreateCertificateListFromBytes( |
| 261 const char* data, int length, int format) { | 294 const char* data, int length, int format) { |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 318 kFormatDecodePriority[i]); | 351 kFormatDecodePriority[i]); |
| 319 } | 352 } |
| 320 | 353 |
| 321 CertificateList results; | 354 CertificateList results; |
| 322 // No certificates parsed. | 355 // No certificates parsed. |
| 323 if (certificates.empty()) | 356 if (certificates.empty()) |
| 324 return results; | 357 return results; |
| 325 | 358 |
| 326 for (OSCertHandles::iterator it = certificates.begin(); | 359 for (OSCertHandles::iterator it = certificates.begin(); |
| 327 it != certificates.end(); ++it) { | 360 it != certificates.end(); ++it) { |
| 328 X509Certificate* result = CreateFromHandle(*it, SOURCE_LONE_CERT_IMPORT, | 361 X509Certificate* result = CreateFromHandle(*it, OSCertHandles()); |
| 329 OSCertHandles()); | |
| 330 results.push_back(scoped_refptr<X509Certificate>(result)); | 362 results.push_back(scoped_refptr<X509Certificate>(result)); |
| 331 FreeOSCertHandle(*it); | 363 FreeOSCertHandle(*it); |
| 332 } | 364 } |
| 333 | 365 |
| 334 return results; | 366 return results; |
| 335 } | 367 } |
| 336 | 368 |
| 337 X509Certificate::X509Certificate(OSCertHandle cert_handle, | 369 X509Certificate::X509Certificate(OSCertHandle cert_handle, |
| 338 Source source, | |
| 339 const OSCertHandles& intermediates) | 370 const OSCertHandles& intermediates) |
| 340 : cert_handle_(DupOSCertHandle(cert_handle)), | 371 : cert_handle_(DupOSCertHandle(cert_handle)) { |
| 341 source_(source) { | 372 X509CertificateCache* cache = g_x509_certificate_cache.Pointer(); |
| 342 // Copy/retain the intermediate cert handles. | 373 cache->InsertOrUpdate(&cert_handle_); |
| 343 for (size_t i = 0; i < intermediates.size(); ++i) | 374 for (size_t i = 0; i < intermediates.size(); ++i) { |
| 344 intermediate_ca_certs_.push_back(DupOSCertHandle(intermediates[i])); | 375 // Duplicate the incoming certificate, as the caller retains ownership |
| 376 // of |intermediates|. |
| 377 OSCertHandle intermediate = DupOSCertHandle(intermediates[i]); |
| 378 // Update the cache, which will assume ownership of the duplicated |
| 379 // handle and return a suitable equivalent, potentially from the cache. |
| 380 cache->InsertOrUpdate(&intermediate); |
| 381 intermediate_ca_certs_.push_back(intermediate); |
| 382 } |
| 345 // Platform-specific initialization. | 383 // Platform-specific initialization. |
| 346 Initialize(); | 384 Initialize(); |
| 347 } | 385 } |
| 348 | 386 |
| 349 X509Certificate::X509Certificate(const std::string& subject, | 387 X509Certificate::X509Certificate(const std::string& subject, |
| 350 const std::string& issuer, | 388 const std::string& issuer, |
| 351 base::Time start_date, | 389 base::Time start_date, |
| 352 base::Time expiration_date) | 390 base::Time expiration_date) |
| 353 : subject_(subject), | 391 : subject_(subject), |
| 354 issuer_(issuer), | 392 issuer_(issuer), |
| 355 valid_start_(start_date), | 393 valid_start_(start_date), |
| 356 valid_expiry_(expiration_date), | 394 valid_expiry_(expiration_date), |
| 357 cert_handle_(NULL), | 395 cert_handle_(NULL) { |
| 358 source_(SOURCE_UNUSED) { | |
| 359 memset(fingerprint_.data, 0, sizeof(fingerprint_.data)); | 396 memset(fingerprint_.data, 0, sizeof(fingerprint_.data)); |
| 360 } | 397 } |
| 361 | 398 |
| 362 X509Certificate::~X509Certificate() { | 399 X509Certificate::~X509Certificate() { |
| 363 // We might not be in the cache, but it is safe to remove ourselves anyway. | 400 X509CertificateCache* cache = g_x509_certificate_cache.Pointer(); |
| 364 g_x509_certificate_cache.Get().Remove(this); | 401 if (cert_handle_) { |
| 365 if (cert_handle_) | 402 cache->Remove(cert_handle_); |
| 366 FreeOSCertHandle(cert_handle_); | 403 FreeOSCertHandle(cert_handle_); |
| 367 for (size_t i = 0; i < intermediate_ca_certs_.size(); ++i) | 404 } |
| 405 for (size_t i = 0; i < intermediate_ca_certs_.size(); ++i) { |
| 406 cache->Remove(intermediate_ca_certs_[i]); |
| 368 FreeOSCertHandle(intermediate_ca_certs_[i]); | 407 FreeOSCertHandle(intermediate_ca_certs_[i]); |
| 408 } |
| 369 } | 409 } |
| 370 | 410 |
| 371 void X509Certificate::Persist(Pickle* pickle) { | 411 void X509Certificate::Persist(Pickle* pickle) { |
| 372 DCHECK(cert_handle_); | 412 DCHECK(cert_handle_); |
| 373 if (!WriteCertHandleToPickle(cert_handle_, pickle)) { | 413 if (!WriteCertHandleToPickle(cert_handle_, pickle)) { |
| 374 NOTREACHED(); | 414 NOTREACHED(); |
| 375 return; | 415 return; |
| 376 } | 416 } |
| 377 | 417 |
| 378 if (!pickle->WriteSize(intermediate_ca_certs_.size())) { | 418 if (!pickle->WriteSize(intermediate_ca_certs_.size())) { |
| (...skipping 27 matching lines...) Expand all Loading... |
| 406 | 446 |
| 407 bool X509Certificate::HasIntermediateCertificates(const OSCertHandles& certs) { | 447 bool X509Certificate::HasIntermediateCertificates(const OSCertHandles& certs) { |
| 408 for (size_t i = 0; i < certs.size(); ++i) { | 448 for (size_t i = 0; i < certs.size(); ++i) { |
| 409 if (!HasIntermediateCertificate(certs[i])) | 449 if (!HasIntermediateCertificate(certs[i])) |
| 410 return false; | 450 return false; |
| 411 } | 451 } |
| 412 return true; | 452 return true; |
| 413 } | 453 } |
| 414 | 454 |
| 415 } // namespace net | 455 } // namespace net |
| OLD | NEW |