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 |