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

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

Issue 18836: Work around our not caching the intermediate CA... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 10 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 | Annotate | Revision Log
« no previous file with comments | « net/base/x509_certificate_unittest.cc ('k') | net/http/http_cache.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) 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 "base/histogram.h"
8 #include "base/logging.h" 7 #include "base/logging.h"
9 #include "base/pickle.h" 8 #include "base/pickle.h"
10 #include "base/string_tokenizer.h" 9 #include "base/string_tokenizer.h"
11 #include "base/string_util.h" 10 #include "base/string_util.h"
12 #include "net/base/cert_status_flags.h" 11 #include "net/base/cert_status_flags.h"
13 #include "net/base/ev_root_ca_metadata.h" 12 #include "net/base/ev_root_ca_metadata.h"
14 #include "net/base/scoped_cert_chain_context.h" 13 #include "net/base/scoped_cert_chain_context.h"
15 14
16 #pragma comment(lib, "crypt32.lib") 15 #pragma comment(lib, "crypt32.lib")
17 16
18 using base::Time; 17 using base::Time;
19 18
20 namespace net { 19 namespace net {
21 20
22 namespace { 21 namespace {
23 22
24 // Calculates the SHA-1 fingerprint of the certificate. Returns an empty
25 // (all zero) fingerprint on failure.
26 X509Certificate::Fingerprint CalculateFingerprint(PCCERT_CONTEXT cert) {
27 DCHECK(NULL != cert->pbCertEncoded);
28 DCHECK(0 != cert->cbCertEncoded);
29
30 BOOL rv;
31 X509Certificate::Fingerprint sha1;
32 DWORD sha1_size = sizeof(sha1.data);
33 rv = CryptHashCertificate(NULL, CALG_SHA1, 0, cert->pbCertEncoded,
34 cert->cbCertEncoded, sha1.data, &sha1_size);
35 DCHECK(rv && sha1_size == sizeof(sha1.data));
36 if (!rv)
37 memset(sha1.data, 0, sizeof(sha1.data));
38 return sha1;
39 }
40
41 // Wrappers of malloc and free for CRYPT_DECODE_PARA, which requires the 23 // Wrappers of malloc and free for CRYPT_DECODE_PARA, which requires the
42 // WINAPI calling convention. 24 // WINAPI calling convention.
43 void* WINAPI MyCryptAlloc(size_t size) { 25 void* WINAPI MyCryptAlloc(size_t size) {
44 return malloc(size); 26 return malloc(size);
45 } 27 }
46 28
47 void WINAPI MyCryptFree(void* p) { 29 void WINAPI MyCryptFree(void* p) {
48 free(p); 30 free(p);
49 } 31 }
50 32
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after
248 valid_start_ = Time::FromFileTime(cert_handle_->pCertInfo->NotBefore); 230 valid_start_ = Time::FromFileTime(cert_handle_->pCertInfo->NotBefore);
249 valid_expiry_ = Time::FromFileTime(cert_handle_->pCertInfo->NotAfter); 231 valid_expiry_ = Time::FromFileTime(cert_handle_->pCertInfo->NotAfter);
250 232
251 fingerprint_ = CalculateFingerprint(cert_handle_); 233 fingerprint_ = CalculateFingerprint(cert_handle_);
252 234
253 // Store the certificate in the cache in case we need it later. 235 // Store the certificate in the cache in case we need it later.
254 X509Certificate::Cache::GetInstance()->Insert(this); 236 X509Certificate::Cache::GetInstance()->Insert(this);
255 } 237 }
256 238
257 // static 239 // static
258 X509Certificate* X509Certificate::CreateFromHandle(OSCertHandle cert_handle) {
259 DCHECK(cert_handle);
260
261 // Check if we already have this certificate in memory.
262 X509Certificate::Cache* cache = X509Certificate::Cache::GetInstance();
263 X509Certificate* cert = cache->Find(CalculateFingerprint(cert_handle));
264 if (cert) {
265 // We've found a certificate with the same fingerprint in our cache. We own
266 // the |cert_handle|, which makes it our job to free it.
267 CertFreeCertificateContext(cert_handle);
268 DHISTOGRAM_COUNTS(L"X509CertificateReuseCount", 1);
269 return cert;
270 }
271 // Otherwise, allocate a new object.
272 return new X509Certificate(cert_handle);
273 }
274
275 // static
276 X509Certificate* X509Certificate::CreateFromBytes(const char* data,
277 int length) {
278 OSCertHandle cert_handle = NULL;
279 if (!CertAddEncodedCertificateToStore(
280 NULL, // the cert won't be persisted in any cert store
281 X509_ASN_ENCODING,
282 reinterpret_cast<const BYTE*>(data), length,
283 CERT_STORE_ADD_USE_EXISTING,
284 &cert_handle))
285 return NULL;
286
287 return CreateFromHandle(cert_handle);
288 }
289
290 // static
291 X509Certificate* X509Certificate::CreateFromPickle(const Pickle& pickle, 240 X509Certificate* X509Certificate::CreateFromPickle(const Pickle& pickle,
292 void** pickle_iter) { 241 void** pickle_iter) {
293 const char* data; 242 const char* data;
294 int length; 243 int length;
295 if (!pickle.ReadData(pickle_iter, &data, &length)) 244 if (!pickle.ReadData(pickle_iter, &data, &length))
296 return NULL; 245 return NULL;
297 246
298 OSCertHandle cert_handle = NULL; 247 OSCertHandle cert_handle = NULL;
299 if (!CertAddSerializedElementToStore( 248 if (!CertAddSerializedElementToStore(
300 NULL, // the cert won't be persisted in any cert store 249 NULL, // the cert won't be persisted in any cert store
301 reinterpret_cast<const BYTE*>(data), length, 250 reinterpret_cast<const BYTE*>(data), length,
302 CERT_STORE_ADD_USE_EXISTING, 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, 251 CERT_STORE_ADD_USE_EXISTING, 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG,
303 NULL, reinterpret_cast<const void **>(&cert_handle))) 252 NULL, reinterpret_cast<const void **>(&cert_handle)))
304 return NULL; 253 return NULL;
305 254
306 return CreateFromHandle(cert_handle); 255 return CreateFromHandle(cert_handle, SOURCE_LONE_CERT_IMPORT);
307 }
308
309 X509Certificate::X509Certificate(OSCertHandle cert_handle)
310 : cert_handle_(cert_handle) {
311 Initialize();
312 }
313
314 X509Certificate::X509Certificate(std::string subject, std::string issuer,
315 Time start_date, Time expiration_date)
316 : subject_(subject),
317 issuer_(issuer),
318 valid_start_(start_date),
319 valid_expiry_(expiration_date),
320 cert_handle_(NULL) {
321 memset(fingerprint_.data, 0, sizeof(fingerprint_.data));
322 } 256 }
323 257
324 void X509Certificate::Persist(Pickle* pickle) { 258 void X509Certificate::Persist(Pickle* pickle) {
325 DWORD length; 259 DWORD length;
326 if (!CertSerializeCertificateStoreElement(cert_handle_, 0, 260 if (!CertSerializeCertificateStoreElement(cert_handle_, 0,
327 NULL, &length)) { 261 NULL, &length)) {
328 NOTREACHED(); 262 NOTREACHED();
329 return; 263 return;
330 } 264 }
331 BYTE* data = reinterpret_cast<BYTE*>(pickle->BeginWriteData(length)); 265 BYTE* data = reinterpret_cast<BYTE*>(pickle->BeginWriteData(length));
332 if (!CertSerializeCertificateStoreElement(cert_handle_, 0, 266 if (!CertSerializeCertificateStoreElement(cert_handle_, 0,
333 data, &length)) { 267 data, &length)) {
334 NOTREACHED(); 268 NOTREACHED();
335 length = 0; 269 length = 0;
336 } 270 }
337 pickle->TrimWriteData(length); 271 pickle->TrimWriteData(length);
338 } 272 }
339 273
340 X509Certificate::~X509Certificate() {
341 // We might not be in the cache, but it is safe to remove ourselves anyway.
342 X509Certificate::Cache::GetInstance()->Remove(this);
343 if (cert_handle_)
344 CertFreeCertificateContext(cert_handle_);
345 }
346
347 void X509Certificate::GetDNSNames(std::vector<std::string>* dns_names) const { 274 void X509Certificate::GetDNSNames(std::vector<std::string>* dns_names) const {
348 dns_names->clear(); 275 dns_names->clear();
349 scoped_ptr_malloc<CERT_ALT_NAME_INFO> alt_name_info; 276 scoped_ptr_malloc<CERT_ALT_NAME_INFO> alt_name_info;
350 GetCertSubjectAltName(cert_handle_, &alt_name_info); 277 GetCertSubjectAltName(cert_handle_, &alt_name_info);
351 CERT_ALT_NAME_INFO* alt_name = alt_name_info.get(); 278 CERT_ALT_NAME_INFO* alt_name = alt_name_info.get();
352 if (alt_name) { 279 if (alt_name) {
353 int num_entries = alt_name->cAltEntry; 280 int num_entries = alt_name->cAltEntry;
354 for (int i = 0; i < num_entries; i++) { 281 for (int i = 0; i < num_entries; i++) {
355 // dNSName is an ASN.1 IA5String representing a string of ASCII 282 // dNSName is an ASN.1 IA5String representing a string of ASCII
356 // characters, so we can use WideToASCII here. 283 // characters, so we can use WideToASCII here.
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
399 // Check the end certificate simple chain (chain_context->rgpChain[0]). 326 // Check the end certificate simple chain (chain_context->rgpChain[0]).
400 // If the end certificate's certificatePolicies extension contains the 327 // If the end certificate's certificatePolicies extension contains the
401 // EV policy OID of the root CA, return true. 328 // EV policy OID of the root CA, return true.
402 PCERT_CHAIN_ELEMENT* element = chain_context->rgpChain[0]->rgpElement; 329 PCERT_CHAIN_ELEMENT* element = chain_context->rgpChain[0]->rgpElement;
403 int num_elements = chain_context->rgpChain[0]->cElement; 330 int num_elements = chain_context->rgpChain[0]->cElement;
404 if (num_elements < 2) 331 if (num_elements < 2)
405 return false; 332 return false;
406 333
407 // Look up the EV policy OID of the root CA. 334 // Look up the EV policy OID of the root CA.
408 PCCERT_CONTEXT root_cert = element[num_elements - 1]->pCertContext; 335 PCCERT_CONTEXT root_cert = element[num_elements - 1]->pCertContext;
409 X509Certificate::Fingerprint fingerprint = CalculateFingerprint(root_cert); 336 Fingerprint fingerprint = CalculateFingerprint(root_cert);
410 std::string ev_policy_oid; 337 std::string ev_policy_oid;
411 if (!metadata->GetPolicyOID(fingerprint, &ev_policy_oid)) 338 if (!metadata->GetPolicyOID(fingerprint, &ev_policy_oid))
412 return false; 339 return false;
413 DCHECK(!ev_policy_oid.empty()); 340 DCHECK(!ev_policy_oid.empty());
414 341
415 // Get the certificatePolicies extension of the end certificate. 342 // Get the certificatePolicies extension of the end certificate.
416 PCCERT_CONTEXT end_cert = element[0]->pCertContext; 343 PCCERT_CONTEXT end_cert = element[0]->pCertContext;
417 scoped_ptr_malloc<CERT_POLICIES_INFO> policies_info; 344 scoped_ptr_malloc<CERT_POLICIES_INFO> policies_info;
418 GetCertPoliciesInfo(end_cert, &policies_info); 345 GetCertPoliciesInfo(end_cert, &policies_info);
419 if (!policies_info.get()) 346 if (!policies_info.get())
420 return false; 347 return false;
421 348
422 return ContainsPolicy(policies_info.get(), ev_policy_oid.c_str()); 349 return ContainsPolicy(policies_info.get(), ev_policy_oid.c_str());
423 } 350 }
424 351
352 // static
353 X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes(
354 const char* data, int length) {
355 OSCertHandle cert_handle = NULL;
356 if (!CertAddEncodedCertificateToStore(
357 NULL, // the cert won't be persisted in any cert store
358 X509_ASN_ENCODING,
359 reinterpret_cast<const BYTE*>(data), length,
360 CERT_STORE_ADD_USE_EXISTING,
361 &cert_handle))
362 return NULL;
363
364 return cert_handle;
365 }
366
367 // static
368 void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) {
369 CertFreeCertificateContext(cert_handle);
370 }
371
372 // static
373 X509Certificate::Fingerprint X509Certificate::CalculateFingerprint(
374 OSCertHandle cert) {
375 DCHECK(NULL != cert->pbCertEncoded);
376 DCHECK(0 != cert->cbCertEncoded);
377
378 BOOL rv;
379 Fingerprint sha1;
380 DWORD sha1_size = sizeof(sha1.data);
381 rv = CryptHashCertificate(NULL, CALG_SHA1, 0, cert->pbCertEncoded,
382 cert->cbCertEncoded, sha1.data, &sha1_size);
383 DCHECK(rv && sha1_size == sizeof(sha1.data));
384 if (!rv)
385 memset(sha1.data, 0, sizeof(sha1.data));
386 return sha1;
387 }
388
425 } // namespace net 389 } // namespace net
426 390
OLDNEW
« no previous file with comments | « net/base/x509_certificate_unittest.cc ('k') | net/http/http_cache.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698