| 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" | |
| 12 #include "base/logging.h" | 11 #include "base/logging.h" |
| 13 #include "base/pickle.h" | 12 #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 |
| 375 } // namespace | 413 } // namespace |
| 376 | 414 |
| 377 void X509Certificate::Initialize() { | 415 void X509Certificate::Initialize() { |
| 378 const CSSM_X509_NAME* name; | 416 const CSSM_X509_NAME* name; |
| 379 OSStatus status = SecCertificateGetSubject(cert_handle_, &name); | 417 OSStatus status = SecCertificateGetSubject(cert_handle_, &name); |
| 380 if (!status) { | 418 if (!status) { |
| 381 subject_.Parse(name); | 419 subject_.Parse(name); |
| 382 } | 420 } |
| 383 status = SecCertificateGetIssuer(cert_handle_, &name); | 421 status = SecCertificateGetIssuer(cert_handle_, &name); |
| 384 if (!status) { | 422 if (!status) { |
| (...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 662 // static | 700 // static |
| 663 X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes( | 701 X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes( |
| 664 const char* data, int length) { | 702 const char* data, int length) { |
| 665 CSSM_DATA cert_data; | 703 CSSM_DATA cert_data; |
| 666 cert_data.Data = const_cast<uint8*>(reinterpret_cast<const uint8*>(data)); | 704 cert_data.Data = const_cast<uint8*>(reinterpret_cast<const uint8*>(data)); |
| 667 cert_data.Length = length; | 705 cert_data.Length = length; |
| 668 | 706 |
| 669 OSCertHandle cert_handle = NULL; | 707 OSCertHandle cert_handle = NULL; |
| 670 OSStatus status = SecCertificateCreateFromData(&cert_data, | 708 OSStatus status = SecCertificateCreateFromData(&cert_data, |
| 671 CSSM_CERT_X_509v3, | 709 CSSM_CERT_X_509v3, |
| 672 CSSM_CERT_ENCODING_BER, | 710 CSSM_CERT_ENCODING_DER, |
| 673 &cert_handle); | 711 &cert_handle); |
| 674 if (status) | 712 if (status) |
| 675 return NULL; | 713 return NULL; |
| 676 | 714 |
| 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 // 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 |
| 677 return cert_handle; | 730 return cert_handle; |
| 678 } | 731 } |
| 679 | 732 |
| 680 // static | 733 // static |
| 734 X509Certificate::OSCertHandles X509Certificate::CreateOSCertHandlesFromBytes( |
| 735 const char* data, int length, Format format) { |
| 736 OSCertHandles results; |
| 737 |
| 738 switch (format) { |
| 739 case FORMAT_SINGLE_CERTIFICATE: { |
| 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 |
| 681 X509Certificate::OSCertHandle X509Certificate::DupOSCertHandle( | 757 X509Certificate::OSCertHandle X509Certificate::DupOSCertHandle( |
| 682 OSCertHandle handle) { | 758 OSCertHandle handle) { |
| 683 if (!handle) | 759 if (!handle) |
| 684 return NULL; | 760 return NULL; |
| 685 return reinterpret_cast<OSCertHandle>(const_cast<void*>(CFRetain(handle))); | 761 return reinterpret_cast<OSCertHandle>(const_cast<void*>(CFRetain(handle))); |
| 686 } | 762 } |
| 687 | 763 |
| 688 // static | 764 // static |
| 689 void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) { | 765 void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) { |
| 690 CFRelease(cert_handle); | 766 CFRelease(cert_handle); |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 893 } | 969 } |
| 894 CFRelease(cert_chain); | 970 CFRelease(cert_chain); |
| 895 } | 971 } |
| 896 exit: | 972 exit: |
| 897 if (result) | 973 if (result) |
| 898 LOG(ERROR) << "CreateIdentityCertificateChain error " << result; | 974 LOG(ERROR) << "CreateIdentityCertificateChain error " << result; |
| 899 return chain.release(); | 975 return chain.release(); |
| 900 } | 976 } |
| 901 | 977 |
| 902 } // namespace net | 978 } // namespace net |
| OLD | NEW |