Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 <CoreServices/CoreServices.h> | 8 #include <CoreServices/CoreServices.h> |
| 9 #include <Security/Security.h> | 9 #include <Security/Security.h> |
| 10 #include <time.h> | 10 #include <time.h> |
| 11 | 11 |
| 12 #include <vector> | 12 #include <vector> |
| 13 | 13 |
| 14 #include "base/lazy_instance.h" | 14 #include "base/lazy_instance.h" |
| 15 #include "base/logging.h" | 15 #include "base/logging.h" |
| 16 #include "base/mac/mac_logging.h" | |
| 16 #include "base/mac/scoped_cftyperef.h" | 17 #include "base/mac/scoped_cftyperef.h" |
| 17 #include "base/memory/singleton.h" | 18 #include "base/memory/singleton.h" |
| 18 #include "base/pickle.h" | 19 #include "base/pickle.h" |
| 19 #include "base/sha1.h" | 20 #include "base/sha1.h" |
| 20 #include "base/sys_string_conversions.h" | 21 #include "base/sys_string_conversions.h" |
| 21 #include "crypto/cssm_init.h" | 22 #include "crypto/cssm_init.h" |
| 22 #include "crypto/nss_util.h" | 23 #include "crypto/nss_util.h" |
| 23 #include "crypto/rsa_private_key.h" | 24 #include "crypto/rsa_private_key.h" |
| 24 #include "crypto/sha2.h" | 25 #include "crypto/sha2.h" |
| 25 #include "net/base/asn1_util.h" | 26 #include "net/base/asn1_util.h" |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 46 switch (status) { | 47 switch (status) { |
| 47 case noErr: | 48 case noErr: |
| 48 return OK; | 49 return OK; |
| 49 case errSecNotAvailable: | 50 case errSecNotAvailable: |
| 50 case errSecNoCertificateModule: | 51 case errSecNoCertificateModule: |
| 51 case errSecNoPolicyModule: | 52 case errSecNoPolicyModule: |
| 52 return ERR_NOT_IMPLEMENTED; | 53 return ERR_NOT_IMPLEMENTED; |
| 53 case errSecAuthFailed: | 54 case errSecAuthFailed: |
| 54 return ERR_ACCESS_DENIED; | 55 return ERR_ACCESS_DENIED; |
| 55 default: { | 56 default: { |
| 56 base::mac::ScopedCFTypeRef<CFStringRef> error_string( | 57 OSSTATUS_LOG(ERROR, status) << "Unknown error mapped to ERR_FAILED"; |
| 57 SecCopyErrorMessageString(status, NULL)); | |
| 58 LOG(ERROR) << "Unknown error " << status | |
| 59 << " (" << base::SysCFStringRefToUTF8(error_string) << ")" | |
| 60 << " mapped to ERR_FAILED"; | |
| 61 return ERR_FAILED; | 58 return ERR_FAILED; |
| 62 } | 59 } |
| 63 } | 60 } |
| 64 } | 61 } |
| 65 | 62 |
| 66 CertStatus CertStatusFromOSStatus(OSStatus status) { | 63 CertStatus CertStatusFromOSStatus(OSStatus status) { |
| 67 switch (status) { | 64 switch (status) { |
| 68 case noErr: | 65 case noErr: |
| 69 return 0; | 66 return 0; |
| 70 | 67 |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 114 return CERT_STATUS_UNABLE_TO_CHECK_REVOCATION; | 111 return CERT_STATUS_UNABLE_TO_CHECK_REVOCATION; |
| 115 | 112 |
| 116 case CSSMERR_APPLETP_CRL_BAD_URI: | 113 case CSSMERR_APPLETP_CRL_BAD_URI: |
| 117 case CSSMERR_APPLETP_IDP_FAIL: | 114 case CSSMERR_APPLETP_IDP_FAIL: |
| 118 return CERT_STATUS_INVALID; | 115 return CERT_STATUS_INVALID; |
| 119 | 116 |
| 120 default: { | 117 default: { |
| 121 // Failure was due to something Chromium doesn't define a | 118 // Failure was due to something Chromium doesn't define a |
| 122 // specific status for (such as basic constraints violation, or | 119 // specific status for (such as basic constraints violation, or |
| 123 // unknown critical extension) | 120 // unknown critical extension) |
| 124 base::mac::ScopedCFTypeRef<CFStringRef> error_string( | 121 OSSTATUS_LOG(WARNING, status) |
| 125 SecCopyErrorMessageString(status, NULL)); | 122 << "Unknown error mapped to CERT_STATUS_INVALID"; |
| 126 LOG(WARNING) << "Unknown error " << status | |
| 127 << " (" << base::SysCFStringRefToUTF8(error_string) << ")" | |
| 128 << " mapped to CERT_STATUS_INVALID"; | |
| 129 return CERT_STATUS_INVALID; | 123 return CERT_STATUS_INVALID; |
| 130 } | 124 } |
| 131 } | 125 } |
| 132 } | 126 } |
| 133 | 127 |
| 134 // Wrapper for a CSSM_DATA_PTR that was obtained via one of the CSSM field | 128 // Wrapper for a CSSM_DATA_PTR that was obtained via one of the CSSM field |
| 135 // accessors (such as CSSM_CL_CertGet[First/Next]Value or | 129 // accessors (such as CSSM_CL_CertGet[First/Next]Value or |
| 136 // CSSM_CL_CertGet[First/Next]CachedValue). | 130 // CSSM_CL_CertGet[First/Next]CachedValue). |
| 137 class CSSMFieldValue { | 131 class CSSMFieldValue { |
| 138 public: | 132 public: |
| (...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 529 X509Certificate::OSCertHandles* output) { | 523 X509Certificate::OSCertHandles* output) { |
| 530 SecExternalFormat input_format = format; | 524 SecExternalFormat input_format = format; |
| 531 ScopedCFTypeRef<CFDataRef> local_data(CFDataCreateWithBytesNoCopy( | 525 ScopedCFTypeRef<CFDataRef> local_data(CFDataCreateWithBytesNoCopy( |
| 532 kCFAllocatorDefault, reinterpret_cast<const UInt8*>(data), length, | 526 kCFAllocatorDefault, reinterpret_cast<const UInt8*>(data), length, |
| 533 kCFAllocatorNull)); | 527 kCFAllocatorNull)); |
| 534 | 528 |
| 535 CFArrayRef items = NULL; | 529 CFArrayRef items = NULL; |
| 536 OSStatus status = SecKeychainItemImport(local_data, NULL, &input_format, | 530 OSStatus status = SecKeychainItemImport(local_data, NULL, &input_format, |
| 537 NULL, 0, NULL, NULL, &items); | 531 NULL, 0, NULL, NULL, &items); |
| 538 if (status) { | 532 if (status) { |
| 539 DLOG(WARNING) << status << " Unable to import items from data of length " | 533 OSSTATUS_DLOG(WARNING, status) |
| 540 << length; | 534 << "Unable to import items from data of length " << length; |
| 541 return; | 535 return; |
| 542 } | 536 } |
| 543 | 537 |
| 544 ScopedCFTypeRef<CFArrayRef> scoped_items(items); | 538 ScopedCFTypeRef<CFArrayRef> scoped_items(items); |
| 545 CFTypeID cert_type_id = SecCertificateGetTypeID(); | 539 CFTypeID cert_type_id = SecCertificateGetTypeID(); |
| 546 | 540 |
| 547 for (CFIndex i = 0; i < CFArrayGetCount(items); ++i) { | 541 for (CFIndex i = 0; i < CFArrayGetCount(items); ++i) { |
| 548 SecKeychainItemRef item = reinterpret_cast<SecKeychainItemRef>( | 542 SecKeychainItemRef item = reinterpret_cast<SecKeychainItemRef>( |
| 549 const_cast<void*>(CFArrayGetValueAtIndex(items, i))); | 543 const_cast<void*>(CFArrayGetValueAtIndex(items, i))); |
| 550 | 544 |
| (...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 779 // static | 773 // static |
| 780 X509Certificate* X509Certificate::CreateSelfSigned( | 774 X509Certificate* X509Certificate::CreateSelfSigned( |
| 781 crypto::RSAPrivateKey* key, | 775 crypto::RSAPrivateKey* key, |
| 782 const std::string& subject, | 776 const std::string& subject, |
| 783 uint32 serial_number, | 777 uint32 serial_number, |
| 784 base::TimeDelta valid_duration) { | 778 base::TimeDelta valid_duration) { |
| 785 DCHECK(key); | 779 DCHECK(key); |
| 786 DCHECK(!subject.empty()); | 780 DCHECK(!subject.empty()); |
| 787 | 781 |
| 788 if (valid_duration.InSeconds() > kuint32max) { | 782 if (valid_duration.InSeconds() > kuint32max) { |
| 789 LOG(ERROR) << "valid_duration too big" << valid_duration.InSeconds(); | 783 LOG(ERROR) << "valid_duration too big " << valid_duration.InSeconds(); |
| 790 valid_duration = base::TimeDelta::FromSeconds(kuint32max); | 784 valid_duration = base::TimeDelta::FromSeconds(kuint32max); |
| 791 } | 785 } |
| 792 | 786 |
| 793 // There is a comment in | 787 // There is a comment in |
| 794 // http://www.opensource.apple.com/source/security_certtool/security_certtool- 31828/src/CertTool.cpp | 788 // http://www.opensource.apple.com/source/security_certtool/security_certtool- 31828/src/CertTool.cpp |
| 795 // that serial_numbers being passed into CSSM_TP_SubmitCredRequest can't have | 789 // that serial_numbers being passed into CSSM_TP_SubmitCredRequest can't have |
| 796 // their high bit set. We will continue though and mask it out below. | 790 // their high bit set. We will continue though and mask it out below. |
| 797 if (serial_number & 0x80000000) | 791 if (serial_number & 0x80000000) |
| 798 LOG(ERROR) << "serial_number has high bit set " << serial_number; | 792 LOG(ERROR) << "serial_number has high bit set " << serial_number; |
| 799 | 793 |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 899 } | 893 } |
| 900 | 894 |
| 901 CSSM_ENCODED_CERT* encCert = | 895 CSSM_ENCODED_CERT* encCert = |
| 902 reinterpret_cast<CSSM_ENCODED_CERT*>(resultSet->Results); | 896 reinterpret_cast<CSSM_ENCODED_CERT*>(resultSet->Results); |
| 903 base::mac::ScopedCFTypeRef<SecCertificateRef> scoped_cert; | 897 base::mac::ScopedCFTypeRef<SecCertificateRef> scoped_cert; |
| 904 SecCertificateRef certificate_ref = NULL; | 898 SecCertificateRef certificate_ref = NULL; |
| 905 OSStatus os_status = | 899 OSStatus os_status = |
| 906 SecCertificateCreateFromData(&encCert->CertBlob, encCert->CertType, | 900 SecCertificateCreateFromData(&encCert->CertBlob, encCert->CertType, |
| 907 encCert->CertEncoding, &certificate_ref); | 901 encCert->CertEncoding, &certificate_ref); |
| 908 if (os_status != 0) { | 902 if (os_status != 0) { |
| 909 DLOG(ERROR) << "SecCertificateCreateFromData failed: " << os_status; | 903 OSSTATUS_DLOG(ERROR, os_status) << "SecCertificateCreateFromData failed"; |
| 910 return NULL; | 904 return NULL; |
| 911 } | 905 } |
| 912 scoped_cert.reset(certificate_ref); | 906 scoped_cert.reset(certificate_ref); |
| 913 | 907 |
| 914 return CreateFromHandle(scoped_cert, X509Certificate::OSCertHandles()); | 908 return CreateFromHandle(scoped_cert, X509Certificate::OSCertHandles()); |
| 915 } | 909 } |
| 916 | 910 |
| 917 void X509Certificate::GetSubjectAltName( | 911 void X509Certificate::GetSubjectAltName( |
| 918 std::vector<std::string>* dns_names, | 912 std::vector<std::string>* dns_names, |
| 919 std::vector<std::string>* ip_addrs) const { | 913 std::vector<std::string>* ip_addrs) const { |
| (...skipping 404 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1324 if (!ExtendedKeyUsageAllows(ext_key_usage, &CSSMOID_ClientAuth)) | 1318 if (!ExtendedKeyUsageAllows(ext_key_usage, &CSSMOID_ClientAuth)) |
| 1325 return false; | 1319 return false; |
| 1326 } | 1320 } |
| 1327 return true; | 1321 return true; |
| 1328 } | 1322 } |
| 1329 | 1323 |
| 1330 bool X509Certificate::IsIssuedBy( | 1324 bool X509Certificate::IsIssuedBy( |
| 1331 const std::vector<CertPrincipal>& valid_issuers) { | 1325 const std::vector<CertPrincipal>& valid_issuers) { |
| 1332 // Get the cert's issuer chain. | 1326 // Get the cert's issuer chain. |
| 1333 CFArrayRef cert_chain = NULL; | 1327 CFArrayRef cert_chain = NULL; |
| 1334 OSStatus result; | 1328 OSStatus result = CopyCertChain(os_cert_handle(), &cert_chain); |
| 1335 result = CopyCertChain(os_cert_handle(), &cert_chain); | |
| 1336 if (result) | 1329 if (result) |
| 1337 return false; | 1330 return false; |
| 1338 ScopedCFTypeRef<CFArrayRef> scoped_cert_chain(cert_chain); | 1331 ScopedCFTypeRef<CFArrayRef> scoped_cert_chain(cert_chain); |
| 1339 | 1332 |
| 1340 // Check all the certs in the chain for a match. | 1333 // Check all the certs in the chain for a match. |
| 1341 int n = CFArrayGetCount(cert_chain); | 1334 int n = CFArrayGetCount(cert_chain); |
| 1342 for (int i = 0; i < n; ++i) { | 1335 for (int i = 0; i < n; ++i) { |
| 1343 SecCertificateRef cert_handle = reinterpret_cast<SecCertificateRef>( | 1336 SecCertificateRef cert_handle = reinterpret_cast<SecCertificateRef>( |
| 1344 const_cast<void*>(CFArrayGetValueAtIndex(cert_chain, i))); | 1337 const_cast<void*>(CFArrayGetValueAtIndex(cert_chain, i))); |
| 1345 scoped_refptr<X509Certificate> cert(X509Certificate::CreateFromHandle( | 1338 scoped_refptr<X509Certificate> cert(X509Certificate::CreateFromHandle( |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1495 // The cert passes, so add it to the vector. | 1488 // The cert passes, so add it to the vector. |
| 1496 // If it's the preferred identity, add it at the start (so it'll be | 1489 // If it's the preferred identity, add it at the start (so it'll be |
| 1497 // selected by default in the UI.) | 1490 // selected by default in the UI.) |
| 1498 if (is_preferred) | 1491 if (is_preferred) |
| 1499 certs->insert(certs->begin(), cert); | 1492 certs->insert(certs->begin(), cert); |
| 1500 else | 1493 else |
| 1501 certs->push_back(cert); | 1494 certs->push_back(cert); |
| 1502 } | 1495 } |
| 1503 | 1496 |
| 1504 if (err != errSecItemNotFound) { | 1497 if (err != errSecItemNotFound) { |
| 1505 LOG(ERROR) << "SecIdentitySearch error " << err; | 1498 OSSTATUS_LOG(ERROR, err) << "SecIdentitySearch error "; |
|
wtc
2012/01/28 00:06:26
Nit: the space at the end of the string isn't need
| |
| 1506 return false; | 1499 return false; |
| 1507 } | 1500 } |
| 1508 return true; | 1501 return true; |
| 1509 } | 1502 } |
| 1510 | 1503 |
| 1511 CFArrayRef X509Certificate::CreateClientCertificateChain() const { | 1504 CFArrayRef X509Certificate::CreateClientCertificateChain() const { |
| 1512 // Initialize the result array with just the IdentityRef of the receiver: | 1505 // Initialize the result array with just the IdentityRef of the receiver: |
| 1513 OSStatus result; | |
| 1514 SecIdentityRef identity; | 1506 SecIdentityRef identity; |
| 1515 result = SecIdentityCreateWithCertificate(NULL, cert_handle_, &identity); | 1507 OSStatus result = |
| 1508 SecIdentityCreateWithCertificate(NULL, cert_handle_, &identity); | |
| 1516 if (result) { | 1509 if (result) { |
| 1517 LOG(ERROR) << "SecIdentityCreateWithCertificate error " << result; | 1510 OSSTATUS_LOG(ERROR, result) << "SecIdentityCreateWithCertificate error"; |
| 1518 return NULL; | 1511 return NULL; |
| 1519 } | 1512 } |
| 1520 ScopedCFTypeRef<CFMutableArrayRef> chain( | 1513 ScopedCFTypeRef<CFMutableArrayRef> chain( |
| 1521 CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks)); | 1514 CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks)); |
| 1522 CFArrayAppendValue(chain, identity); | 1515 CFArrayAppendValue(chain, identity); |
| 1523 | 1516 |
| 1524 CFArrayRef cert_chain = NULL; | 1517 CFArrayRef cert_chain = NULL; |
| 1525 result = CopyCertChain(cert_handle_, &cert_chain); | 1518 result = CopyCertChain(cert_handle_, &cert_chain); |
| 1526 ScopedCFTypeRef<CFArrayRef> scoped_cert_chain(cert_chain); | 1519 ScopedCFTypeRef<CFArrayRef> scoped_cert_chain(cert_chain); |
| 1527 if (result) { | 1520 if (result) { |
| 1528 LOG(ERROR) << "CreateIdentityCertificateChain error " << result; | 1521 OSSTATUS_LOG(ERROR, result) << "CreateIdentityCertificateChain error"; |
| 1529 return chain.release(); | 1522 return chain.release(); |
| 1530 } | 1523 } |
| 1531 | 1524 |
| 1532 // Append the intermediate certs from SecTrust to the result array: | 1525 // Append the intermediate certs from SecTrust to the result array: |
| 1533 if (cert_chain) { | 1526 if (cert_chain) { |
| 1534 int chain_count = CFArrayGetCount(cert_chain); | 1527 int chain_count = CFArrayGetCount(cert_chain); |
| 1535 if (chain_count > 1) { | 1528 if (chain_count > 1) { |
| 1536 CFArrayAppendArray(chain, | 1529 CFArrayAppendArray(chain, |
| 1537 cert_chain, | 1530 cert_chain, |
| 1538 CFRangeMake(1, chain_count - 1)); | 1531 CFRangeMake(1, chain_count - 1)); |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1619 *type = kPublicKeyTypeDH; | 1612 *type = kPublicKeyTypeDH; |
| 1620 break; | 1613 break; |
| 1621 default: | 1614 default: |
| 1622 *type = kPublicKeyTypeUnknown; | 1615 *type = kPublicKeyTypeUnknown; |
| 1623 *size_bits = 0; | 1616 *size_bits = 0; |
| 1624 break; | 1617 break; |
| 1625 } | 1618 } |
| 1626 } | 1619 } |
| 1627 | 1620 |
| 1628 } // namespace net | 1621 } // namespace net |
| OLD | NEW |