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

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

Issue 2668005: Bring the handling of <keygen> and support for the application/x-x509-user-ce... (Closed) Base URL: http://src.chromium.org/svn/trunk/src/
Patch Set: Whitespace/style Created 10 years, 6 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.cc ('k') | net/base/x509_certificate_nss.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 <CommonCrypto/CommonDigest.h> 7 #include <CommonCrypto/CommonDigest.h>
8 #include <Security/Security.h> 8 #include <Security/Security.h>
9 #include <time.h> 9 #include <time.h>
10 10
11 #include "base/file_path.h"
12 #include "base/file_util.h"
11 #include "base/scoped_cftyperef.h" 13 #include "base/scoped_cftyperef.h"
12 #include "base/logging.h" 14 #include "base/logging.h"
13 #include "base/pickle.h" 15 #include "base/pickle.h"
14 #include "base/sys_string_conversions.h" 16 #include "base/sys_string_conversions.h"
15 #include "net/base/cert_status_flags.h" 17 #include "net/base/cert_status_flags.h"
16 #include "net/base/cert_verify_result.h" 18 #include "net/base/cert_verify_result.h"
17 #include "net/base/net_errors.h" 19 #include "net/base/net_errors.h"
18 20
19 using base::Time; 21 using base::Time;
20 22
(...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after
351 353
352 // Evaluate trust, which creates the cert chain. 354 // Evaluate trust, which creates the cert chain.
353 SecTrustResultType status; 355 SecTrustResultType status;
354 CSSM_TP_APPLE_EVIDENCE_INFO* status_chain; 356 CSSM_TP_APPLE_EVIDENCE_INFO* status_chain;
355 result = SecTrustEvaluate(trust, &status); 357 result = SecTrustEvaluate(trust, &status);
356 if (result) 358 if (result)
357 return result; 359 return result;
358 return SecTrustGetResult(trust, &status, out_cert_chain, &status_chain); 360 return SecTrustGetResult(trust, &status, out_cert_chain, &status_chain);
359 } 361 }
360 362
363 void AddCertificatesFromData(const char* data, size_t length,
364 SecExternalFormat format,
365 X509Certificate::OSCertHandles* output) {
366 // In order to use SecKeychainItemImport successfully, a destination
367 // keychain must be specified to receive the created objects. Further,
368 // the created objects remain valid only for as long as the keychain does.
369 // In order to match the handling on Windows/NSS, which has the handles
370 // valid for an arbitrary length of time, a temporary keychain is created,
371 // the certificates are imported into it, and then free-standing
372 // certificates are created from the DER representation of the original
373 // keychain item.
374 FilePath temp_file;
375 if (!file_util::CreateTemporaryFile(&temp_file))
376 return;
377
378 SecExternalFormat input_format = format;
379 scoped_cftyperef<CFDataRef> local_data(CFDataCreateWithBytesNoCopy(
380 kCFAllocatorDefault, reinterpret_cast<const UInt8*>(data),
381 length, kCFAllocatorDefault);
382
383 scoped_cftyperef<SecKeychainRef> temp_keychain;
384 SecKeychainRef keychain = NULL;
385 OSStatus rv = SecKeychainCreate(temp_file.value().c_str(), 0, NULL, FALSE,
386 NULL, &keychain);
387 if (rv != noErr) {
388 DLOG(WARNING) << rv << " Unable to create temporary keychain at "
389 << temp_file.value();
390 return;
391 }
392
393 temp_keychain.reset(keychain);
394 keychain = NULL;
395
396 CFArrayRef items = NULL;
397 rv = SecKeychainItemImport(local_data, NULL, &input_format, NULL,
398 0, NULL, NULL, temp_keychain, &items);
399 if (rv != noErr) {
400 scoped_cftyperef<CFArrayRef> scoped_items(items);
401 CFTypeID certTypeID = SecCertificateGetTypeID();
402
403 for (CFIndex i = 0; i < CFArrayGetCount(items); ++i) {
404 SecKeychainItemRef item = CFArrayGetValueAtIndex(items, i);
405
406 // While inputFormat implies only certificates will be imported, if/when
407 // other formats (eg: PKCS#12) are supported, this may also include
408 // private keys or other items types, so filter appropriately.
409 if (CFGetTypeID(item) == certTypeID) {
410 // Create a freestanding SecCertificateRef from the keychain item.
411 // Unfortunately, this invokes a double-parse of the DER data, which
412 // is less than optimally efficient.
413 scoped_cftyperef<CFDataRef> scoped_cert_data =
414 SecCertificateCopyData(reinterpret_cast<SecCertificateRef>(item));
415 if (scoped_cert_data == NULL)
416 continue;
417
418 SecCertificateRef cert = SecCertificateCreateWithData(NULL,
419 scoped_cert_data);
420 if (cert == NULL)
421 continue;
422
423 output->push_back(cert);
424 }
425 } else {
426 DLOG(WARNING) << rv << " Unable to import items from data of length "
427 << length;
428 }
429
430 rv = SecKeychainDelete(temp_keychain);
431 if (rv != noErr) {
432 DLOG(WARNING) << rv << " Unable to remove temporary keychain at "
433 << temp_file.value();
434 }
435 }
436
361 } // namespace 437 } // namespace
362 438
363 void X509Certificate::Initialize() { 439 void X509Certificate::Initialize() {
364 const CSSM_X509_NAME* name; 440 const CSSM_X509_NAME* name;
365 OSStatus status = SecCertificateGetSubject(cert_handle_, &name); 441 OSStatus status = SecCertificateGetSubject(cert_handle_, &name);
366 if (!status) { 442 if (!status) {
367 subject_.Parse(name); 443 subject_.Parse(name);
368 } 444 }
369 status = SecCertificateGetIssuer(cert_handle_, &name); 445 status = SecCertificateGetIssuer(cert_handle_, &name);
370 if (!status) { 446 if (!status) {
371 issuer_.Parse(name); 447 issuer_.Parse(name);
372 } 448 }
373 449
374 GetCertDateForOID(cert_handle_, CSSMOID_X509V1ValidityNotBefore, 450 GetCertDateForOID(cert_handle_, CSSMOID_X509V1ValidityNotBefore,
375 &valid_start_); 451 &valid_start_);
376 GetCertDateForOID(cert_handle_, CSSMOID_X509V1ValidityNotAfter, 452 GetCertDateForOID(cert_handle_, CSSMOID_X509V1ValidityNotAfter,
377 &valid_expiry_); 453 &valid_expiry_);
378 454
379 fingerprint_ = CalculateFingerprint(cert_handle_); 455 fingerprint_ = CalculateFingerprint(cert_handle_);
380 } 456 }
381 457
382 // static 458 // static
383 X509Certificate* X509Certificate::CreateFromPickle(const Pickle& pickle, 459 X509Certificate* X509Certificate::CreateFromPickle(const Pickle& pickle,
384 void** pickle_iter) { 460 void** pickle_iter) {
385 const char* data; 461 const char* data;
386 int length; 462 int length;
387 if (!pickle.ReadData(pickle_iter, &data, &length)) 463 if (!pickle.ReadData(pickle_iter, &data, &length))
388 return NULL; 464 return NULL;
389 465
390 return CreateFromBytes(data, length); 466 return CreateFromBytes(data, length, X509Certificate::FORMAT_DER);
391 } 467 }
392 468
393 void X509Certificate::Persist(Pickle* pickle) { 469 void X509Certificate::Persist(Pickle* pickle) {
394 CSSM_DATA cert_data; 470 CSSM_DATA cert_data;
395 OSStatus status = SecCertificateGetData(cert_handle_, &cert_data); 471 OSStatus status = SecCertificateGetData(cert_handle_, &cert_data);
396 if (status) { 472 if (status) {
397 NOTREACHED(); 473 NOTREACHED();
398 return; 474 return;
399 } 475 }
400 476
(...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after
640 bool X509Certificate::VerifyEV() const { 716 bool X509Certificate::VerifyEV() const {
641 // We don't call this private method, but we do need to implement it because 717 // We don't call this private method, but we do need to implement it because
642 // it's defined in x509_certificate.h. We perform EV checking in the 718 // it's defined in x509_certificate.h. We perform EV checking in the
643 // Verify() above. 719 // Verify() above.
644 NOTREACHED(); 720 NOTREACHED();
645 return false; 721 return false;
646 } 722 }
647 723
648 // static 724 // static
649 X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes( 725 X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes(
650 const char* data, int length) { 726 const char* data, size_t length) {
651 CSSM_DATA cert_data; 727 CSSM_DATA cert_data;
652 cert_data.Data = const_cast<uint8*>(reinterpret_cast<const uint8*>(data)); 728 cert_data.Data = const_cast<uint8*>(reinterpret_cast<const uint8*>(data));
653 cert_data.Length = length; 729 cert_data.Length = length;
654 730
655 OSCertHandle cert_handle = NULL; 731 OSCertHandle cert_handle = NULL;
656 OSStatus status = SecCertificateCreateFromData(&cert_data, 732 OSStatus status = SecCertificateCreateFromData(&cert_data,
657 CSSM_CERT_X_509v3, 733 CSSM_CERT_X_509v3,
658 CSSM_CERT_ENCODING_BER, 734 CSSM_CERT_ENCODING_BER,
659 &cert_handle); 735 &cert_handle);
660 if (status) 736 if (status)
661 return NULL; 737 return NULL;
662 738
663 return cert_handle; 739 return cert_handle;
664 } 740 }
665 741
666 // static 742 // static
743 X509Certificate::OSCertHandles X509Certificate::CreateOSCertHandlesFromBytes(
744 const char* data, size_t length, CertificateFormat format) {
745 OSCertHandles results;
746
747 switch (format) {
748 case FORMAT_DER:
749 {
750 OSCertHandle handle = CreateOSCertHandleFromBytes(data, length);
751 if (handle)
752 results.push_back(handle);
753 }
754 break;
755 case FORMAT_PKCS7:
756 AddCertificatesFromData(data, length, kSecFormatPKCS7, &results);
757 break;
758 case FORMAT_LEGACY_NETSCAPE:
759 AddCertificatesFromData(data, length, kSecFormatNetscapeCertSequence,
760 &results);
761 break;
762 default:
763 NOTREACHED() << "Certificate format " << format << " unimplemented";
764 break;
765 }
766
767 return results;
768 }
769
770 // static
667 X509Certificate::OSCertHandle X509Certificate::DupOSCertHandle( 771 X509Certificate::OSCertHandle X509Certificate::DupOSCertHandle(
668 OSCertHandle handle) { 772 OSCertHandle handle) {
669 if (!handle) 773 if (!handle)
670 return NULL; 774 return NULL;
671 return reinterpret_cast<OSCertHandle>(const_cast<void*>(CFRetain(handle))); 775 return reinterpret_cast<OSCertHandle>(const_cast<void*>(CFRetain(handle)));
672 } 776 }
673 777
674 // static 778 // static
675 void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) { 779 void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) {
676 CFRelease(cert_handle); 780 CFRelease(cert_handle);
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
756 NULL, 860 NULL,
757 CSSM_APPLE_TP_SSL_CLIENT 861 CSSM_APPLE_TP_SSL_CLIENT
758 }; 862 };
759 return CreatePolicy(&CSSMOID_APPLE_TP_SSL, 863 return CreatePolicy(&CSSMOID_APPLE_TP_SSL,
760 &tp_ssl_options, 864 &tp_ssl_options,
761 sizeof(tp_ssl_options), 865 sizeof(tp_ssl_options),
762 out_policy); 866 out_policy);
763 } 867 }
764 868
765 // static 869 // static
766 bool X509Certificate::GetSSLClientCertificates ( 870 bool X509Certificate::GetSSLClientCertificates(
767 const std::string& server_domain, 871 const std::string& server_domain,
768 const std::vector<Principal>& valid_issuers, 872 const std::vector<Principal>& valid_issuers,
769 std::vector<scoped_refptr<X509Certificate> >* certs) { 873 std::vector<scoped_refptr<X509Certificate> >* certs) {
770 scoped_cftyperef<SecIdentityRef> preferred_identity; 874 scoped_cftyperef<SecIdentityRef> preferred_identity;
771 if (!server_domain.empty()) { 875 if (!server_domain.empty()) {
772 // See if there's an identity preference for this domain: 876 // See if there's an identity preference for this domain:
773 scoped_cftyperef<CFStringRef> domain_str( 877 scoped_cftyperef<CFStringRef> domain_str(
774 base::SysUTF8ToCFStringRef("https://" + server_domain)); 878 base::SysUTF8ToCFStringRef("https://" + server_domain));
775 SecIdentityRef identity = NULL; 879 SecIdentityRef identity = NULL;
776 if (SecIdentityCopyPreference(domain_str, 880 if (SecIdentityCopyPreference(domain_str,
777 0, 881 0,
778 NULL, // validIssuers argument is ignored :( 882 NULL, // validIssuers argument is ignored :(
779 &identity) == noErr) 883 &identity) == noErr)
780 preferred_identity.reset(identity); 884 preferred_identity.reset(identity);
781 } 885 }
782 886
783 // Now enumerate the identities in the available keychains. 887 // Now enumerate the identities in the available keychains.
784 SecIdentitySearchRef search = nil; 888 SecIdentitySearchRef search = nil;
785 OSStatus err = SecIdentitySearchCreate(NULL, CSSM_KEYUSE_SIGN, &search); 889 OSStatus err = SecIdentitySearchCreate(NULL, CSSM_KEYUSE_SIGN, &search);
786 scoped_cftyperef<SecIdentitySearchRef> scoped_search(search); 890 scoped_cftyperef<SecIdentitySearchRef> scoped_search(search);
787 while (!err) { 891 while (!err) {
788 SecIdentityRef identity = NULL; 892 SecIdentityRef identity = NULL;
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
860 // Append the intermediate certs from SecTrust to the result array: 964 // Append the intermediate certs from SecTrust to the result array:
861 if (cert_chain) { 965 if (cert_chain) {
862 int chain_count = CFArrayGetCount(cert_chain); 966 int chain_count = CFArrayGetCount(cert_chain);
863 if (chain_count > 1) { 967 if (chain_count > 1) {
864 CFArrayAppendArray(chain, 968 CFArrayAppendArray(chain,
865 cert_chain, 969 cert_chain,
866 CFRangeMake(1, chain_count - 1)); 970 CFRangeMake(1, chain_count - 1));
867 } 971 }
868 CFRelease(cert_chain); 972 CFRelease(cert_chain);
869 } 973 }
870 exit: 974 exit:
871 if (result) 975 if (result)
872 LOG(ERROR) << "CreateIdentityCertificateChain error " << result; 976 LOG(ERROR) << "CreateIdentityCertificateChain error " << result;
873 return chain.release(); 977 return chain.release();
874 } 978 }
875 979
876 } // namespace net 980 } // namespace net
OLDNEW
« no previous file with comments | « net/base/x509_certificate.cc ('k') | net/base/x509_certificate_nss.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698