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 |