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 |