| 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 <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/scoped_cftyperef.h" |
| 11 #include "base/logging.h" | 12 #include "base/logging.h" |
| 12 #include "base/pickle.h" | 13 #include "base/pickle.h" |
| 13 #include "base/scoped_cftyperef.h" | |
| 14 #include "base/sys_string_conversions.h" | 14 #include "base/sys_string_conversions.h" |
| 15 #include "net/base/cert_status_flags.h" | 15 #include "net/base/cert_status_flags.h" |
| 16 #include "net/base/cert_verify_result.h" | 16 #include "net/base/cert_verify_result.h" |
| 17 #include "net/base/net_errors.h" | 17 #include "net/base/net_errors.h" |
| 18 | 18 |
| 19 using base::Time; | 19 using base::Time; |
| 20 | 20 |
| 21 namespace net { | 21 namespace net { |
| 22 | 22 |
| 23 class MacTrustedCertificates { | 23 class MacTrustedCertificates { |
| (...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 365 const CSSM_OID* purpose) { | 365 const CSSM_OID* purpose) { |
| 366 for (unsigned p = 0; p < usage->numPurposes; ++p) { | 366 for (unsigned p = 0; p < usage->numPurposes; ++p) { |
| 367 if (CSSMOIDEqual(&usage->purposes[p], purpose)) | 367 if (CSSMOIDEqual(&usage->purposes[p], purpose)) |
| 368 return true; | 368 return true; |
| 369 if (CSSMOIDEqual(&usage->purposes[p], &CSSMOID_ExtendedKeyUsageAny)) | 369 if (CSSMOIDEqual(&usage->purposes[p], &CSSMOID_ExtendedKeyUsageAny)) |
| 370 return true; | 370 return true; |
| 371 } | 371 } |
| 372 return false; | 372 return false; |
| 373 } | 373 } |
| 374 | 374 |
| 375 // Parses |data| of length |length|, attempting to decode it as the specified | |
| 376 // |format|. If |data| is in the specified format, any certificates contained | |
| 377 // within are stored into |output|. | |
| 378 void AddCertificatesFromBytes(const char* data, size_t length, | |
| 379 SecExternalFormat format, | |
| 380 X509Certificate::OSCertHandles* output) { | |
| 381 SecExternalFormat input_format = format; | |
| 382 scoped_cftyperef<CFDataRef> local_data(CFDataCreateWithBytesNoCopy( | |
| 383 kCFAllocatorDefault, reinterpret_cast<const UInt8*>(data), | |
| 384 length, kCFAllocatorNull)); | |
| 385 | |
| 386 CFArrayRef items = NULL; | |
| 387 OSStatus status = SecKeychainItemImport(local_data, NULL, &input_format, | |
| 388 NULL, 0, NULL, NULL, &items); | |
| 389 if (status) { | |
| 390 DLOG(WARNING) << status << " Unable to import items from data of length " | |
| 391 << length; | |
| 392 return; | |
| 393 } | |
| 394 | |
| 395 scoped_cftyperef<CFArrayRef> scoped_items(items); | |
| 396 CFTypeID cert_type_id = SecCertificateGetTypeID(); | |
| 397 | |
| 398 for (CFIndex i = 0; i < CFArrayGetCount(items); ++i) { | |
| 399 SecKeychainItemRef item = reinterpret_cast<SecKeychainItemRef>( | |
| 400 const_cast<void*>(CFArrayGetValueAtIndex(items, i))); | |
| 401 | |
| 402 // While inputFormat implies only certificates will be imported, if/when | |
| 403 // other formats (eg: PKCS#12) are supported, this may also include | |
| 404 // private keys or other items types, so filter appropriately. | |
| 405 if (CFGetTypeID(item) == cert_type_id) { | |
| 406 SecCertificateRef cert = reinterpret_cast<SecCertificateRef>(item); | |
| 407 CFRetain(cert); | |
| 408 output->push_back(cert); | |
| 409 } | |
| 410 } | |
| 411 } | |
| 412 | |
| 413 } // namespace | 375 } // namespace |
| 414 | 376 |
| 415 void X509Certificate::Initialize() { | 377 void X509Certificate::Initialize() { |
| 416 const CSSM_X509_NAME* name; | 378 const CSSM_X509_NAME* name; |
| 417 OSStatus status = SecCertificateGetSubject(cert_handle_, &name); | 379 OSStatus status = SecCertificateGetSubject(cert_handle_, &name); |
| 418 if (!status) { | 380 if (!status) { |
| 419 subject_.Parse(name); | 381 subject_.Parse(name); |
| 420 } | 382 } |
| 421 status = SecCertificateGetIssuer(cert_handle_, &name); | 383 status = SecCertificateGetIssuer(cert_handle_, &name); |
| 422 if (!status) { | 384 if (!status) { |
| (...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 700 // static | 662 // static |
| 701 X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes( | 663 X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes( |
| 702 const char* data, int length) { | 664 const char* data, int length) { |
| 703 CSSM_DATA cert_data; | 665 CSSM_DATA cert_data; |
| 704 cert_data.Data = const_cast<uint8*>(reinterpret_cast<const uint8*>(data)); | 666 cert_data.Data = const_cast<uint8*>(reinterpret_cast<const uint8*>(data)); |
| 705 cert_data.Length = length; | 667 cert_data.Length = length; |
| 706 | 668 |
| 707 OSCertHandle cert_handle = NULL; | 669 OSCertHandle cert_handle = NULL; |
| 708 OSStatus status = SecCertificateCreateFromData(&cert_data, | 670 OSStatus status = SecCertificateCreateFromData(&cert_data, |
| 709 CSSM_CERT_X_509v3, | 671 CSSM_CERT_X_509v3, |
| 710 CSSM_CERT_ENCODING_DER, | 672 CSSM_CERT_ENCODING_BER, |
| 711 &cert_handle); | 673 &cert_handle); |
| 712 if (status) | 674 if (status) |
| 713 return NULL; | 675 return NULL; |
| 714 | 676 |
| 715 // SecCertificateCreateFromData() unfortunately will not return any | |
| 716 // errors, as long as simply all pointers are present. The actual decoding | |
| 717 // of the certificate does not happen until an API that requires a CDSA | |
| 718 // handle is called. While SecCertificateGetCLHandle is the most likely | |
| 719 // candidate, as it initializes the parsing, it does not check whether the | |
| 720 // parsing was successful. Instead, SecCertificateGetSubject is used | |
| 721 // (supported since 10.3), as a means to double-check that the parsed | |
| 722 // parsed certificate is valid. | |
| 723 const CSSM_X509_NAME* sanity_check = NULL; | |
| 724 status = SecCertificateGetSubject(cert_handle, &sanity_check); | |
| 725 if (status || !sanity_check) { | |
| 726 CFRelease(cert_handle); | |
| 727 return NULL; | |
| 728 } | |
| 729 | |
| 730 return cert_handle; | 677 return cert_handle; |
| 731 } | 678 } |
| 732 | 679 |
| 733 // static | 680 // static |
| 734 X509Certificate::OSCertHandles X509Certificate::CreateOSCertHandlesFromBytes( | |
| 735 const char* data, int length, Format format) { | |
| 736 OSCertHandles results; | |
| 737 | |
| 738 switch (format) { | |
| 739 case FORMAT_DER: { | |
| 740 OSCertHandle handle = CreateOSCertHandleFromBytes(data, length); | |
| 741 if (handle) | |
| 742 results.push_back(handle); | |
| 743 break; | |
| 744 } | |
| 745 case FORMAT_PKCS7: | |
| 746 AddCertificatesFromBytes(data, length, kSecFormatPKCS7, &results); | |
| 747 break; | |
| 748 default: | |
| 749 NOTREACHED() << "Certificate format " << format << " unimplemented"; | |
| 750 break; | |
| 751 } | |
| 752 | |
| 753 return results; | |
| 754 } | |
| 755 | |
| 756 // static | |
| 757 X509Certificate::OSCertHandle X509Certificate::DupOSCertHandle( | 681 X509Certificate::OSCertHandle X509Certificate::DupOSCertHandle( |
| 758 OSCertHandle handle) { | 682 OSCertHandle handle) { |
| 759 if (!handle) | 683 if (!handle) |
| 760 return NULL; | 684 return NULL; |
| 761 return reinterpret_cast<OSCertHandle>(const_cast<void*>(CFRetain(handle))); | 685 return reinterpret_cast<OSCertHandle>(const_cast<void*>(CFRetain(handle))); |
| 762 } | 686 } |
| 763 | 687 |
| 764 // static | 688 // static |
| 765 void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) { | 689 void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) { |
| 766 CFRelease(cert_handle); | 690 CFRelease(cert_handle); |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 969 } | 893 } |
| 970 CFRelease(cert_chain); | 894 CFRelease(cert_chain); |
| 971 } | 895 } |
| 972 exit: | 896 exit: |
| 973 if (result) | 897 if (result) |
| 974 LOG(ERROR) << "CreateIdentityCertificateChain error " << result; | 898 LOG(ERROR) << "CreateIdentityCertificateChain error " << result; |
| 975 return chain.release(); | 899 return chain.release(); |
| 976 } | 900 } |
| 977 | 901 |
| 978 } // namespace net | 902 } // namespace net |
| OLD | NEW |