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/cert/x509_util_mac.h" | 5 #include "net/cert/x509_util_mac.h" |
6 | 6 |
| 7 #include <CommonCrypto/CommonDigest.h> |
| 8 |
7 #include "base/logging.h" | 9 #include "base/logging.h" |
8 #include "base/mac/mac_util.h" | 10 #include "base/mac/mac_util.h" |
9 #include "base/mac/scoped_cftyperef.h" | |
10 #include "base/strings/sys_string_conversions.h" | 11 #include "base/strings/sys_string_conversions.h" |
| 12 #include "net/cert/x509_certificate.h" |
11 #include "third_party/apple_apsl/cssmapplePriv.h" | 13 #include "third_party/apple_apsl/cssmapplePriv.h" |
| 14 #include "third_party/boringssl/src/include/openssl/pool.h" |
12 | 15 |
13 namespace net { | 16 namespace net { |
14 | 17 |
15 // CSSM functions are deprecated as of OSX 10.7, but have no replacement. | 18 // CSSM functions are deprecated as of OSX 10.7, but have no replacement. |
16 // https://bugs.chromium.org/p/chromium/issues/detail?id=590914#c1 | 19 // https://bugs.chromium.org/p/chromium/issues/detail?id=590914#c1 |
17 #pragma clang diagnostic push | 20 #pragma clang diagnostic push |
18 #pragma clang diagnostic ignored "-Wdeprecated-declarations" | 21 #pragma clang diagnostic ignored "-Wdeprecated-declarations" |
19 | 22 |
20 namespace x509_util { | 23 namespace x509_util { |
21 | 24 |
(...skipping 23 matching lines...) Expand all Loading... |
45 if (err) { | 48 if (err) { |
46 CFRelease(*policy); | 49 CFRelease(*policy); |
47 return err; | 50 return err; |
48 } | 51 } |
49 } | 52 } |
50 return noErr; | 53 return noErr; |
51 } | 54 } |
52 | 55 |
53 } // namespace | 56 } // namespace |
54 | 57 |
| 58 bool IsValidSecCertificate(SecCertificateRef cert_handle) { |
| 59 const CSSM_X509_NAME* sanity_check = NULL; |
| 60 OSStatus status = SecCertificateGetSubject(cert_handle, &sanity_check); |
| 61 return status == noErr && sanity_check; |
| 62 } |
| 63 |
| 64 base::ScopedCFTypeRef<SecCertificateRef> CreateSecCertificateFromBytes( |
| 65 const uint8_t* data, |
| 66 size_t length) { |
| 67 CSSM_DATA cert_data; |
| 68 cert_data.Data = const_cast<uint8_t*>(data); |
| 69 cert_data.Length = length; |
| 70 |
| 71 base::ScopedCFTypeRef<SecCertificateRef> cert_handle; |
| 72 OSStatus status = SecCertificateCreateFromData(&cert_data, CSSM_CERT_X_509v3, |
| 73 CSSM_CERT_ENCODING_DER, |
| 74 cert_handle.InitializeInto()); |
| 75 if (status != noErr) |
| 76 return base::ScopedCFTypeRef<SecCertificateRef>(); |
| 77 if (!IsValidSecCertificate(cert_handle.get())) |
| 78 return base::ScopedCFTypeRef<SecCertificateRef>(); |
| 79 return cert_handle; |
| 80 } |
| 81 |
| 82 base::ScopedCFTypeRef<SecCertificateRef> |
| 83 CreateSecCertificateFromX509Certificate(const X509Certificate* cert) { |
| 84 #if BUILDFLAG(USE_BYTE_CERTS) |
| 85 return CreateSecCertificateFromBytes( |
| 86 CRYPTO_BUFFER_data(cert->os_cert_handle()), |
| 87 CRYPTO_BUFFER_len(cert->os_cert_handle())); |
| 88 #else |
| 89 return base::ScopedCFTypeRef<SecCertificateRef>( |
| 90 reinterpret_cast<SecCertificateRef>( |
| 91 const_cast<void*>(CFRetain(cert->os_cert_handle())))); |
| 92 #endif |
| 93 } |
| 94 |
| 95 base::ScopedCFTypeRef<CFMutableArrayRef> |
| 96 CreateSecCertificateArrayForX509Certificate(X509Certificate* cert) { |
| 97 base::ScopedCFTypeRef<CFMutableArrayRef> cert_list( |
| 98 CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks)); |
| 99 if (!cert_list) |
| 100 return base::ScopedCFTypeRef<CFMutableArrayRef>(); |
| 101 #if BUILDFLAG(USE_BYTE_CERTS) |
| 102 std::string bytes; |
| 103 base::ScopedCFTypeRef<SecCertificateRef> sec_cert( |
| 104 CreateSecCertificateFromBytes(CRYPTO_BUFFER_data(cert->os_cert_handle()), |
| 105 CRYPTO_BUFFER_len(cert->os_cert_handle()))); |
| 106 if (!sec_cert) |
| 107 return base::ScopedCFTypeRef<CFMutableArrayRef>(); |
| 108 CFArrayAppendValue(cert_list, sec_cert); |
| 109 for (X509Certificate::OSCertHandle intermediate : |
| 110 cert->GetIntermediateCertificates()) { |
| 111 base::ScopedCFTypeRef<SecCertificateRef> sec_cert( |
| 112 CreateSecCertificateFromBytes(CRYPTO_BUFFER_data(intermediate), |
| 113 CRYPTO_BUFFER_len(intermediate))); |
| 114 CFArrayAppendValue(cert_list, sec_cert); |
| 115 } |
| 116 #else |
| 117 X509Certificate::OSCertHandles intermediate_ca_certs = |
| 118 cert->GetIntermediateCertificates(); |
| 119 CFArrayAppendValue(cert_list, cert->os_cert_handle()); |
| 120 for (size_t i = 0; i < intermediate_ca_certs.size(); ++i) |
| 121 CFArrayAppendValue(cert_list, intermediate_ca_certs[i]); |
| 122 #endif |
| 123 return cert_list; |
| 124 } |
| 125 |
| 126 scoped_refptr<X509Certificate> CreateX509CertificateFromSecCertificate( |
| 127 SecCertificateRef sec_cert, |
| 128 const std::vector<SecCertificateRef>& sec_chain) { |
| 129 #if BUILDFLAG(USE_BYTE_CERTS) |
| 130 CSSM_DATA der_data; |
| 131 if (!sec_cert || SecCertificateGetData(sec_cert, &der_data) != noErr) |
| 132 return nullptr; |
| 133 bssl::UniquePtr<CRYPTO_BUFFER> cert_handle( |
| 134 X509Certificate::CreateOSCertHandleFromBytes( |
| 135 reinterpret_cast<const char*>(der_data.Data), der_data.Length)); |
| 136 if (!cert_handle) |
| 137 return nullptr; |
| 138 std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> intermediates; |
| 139 X509Certificate::OSCertHandles intermediates_raw; |
| 140 for (const SecCertificateRef& sec_intermediate : sec_chain) { |
| 141 if (!sec_intermediate || |
| 142 SecCertificateGetData(sec_intermediate, &der_data) != noErr) { |
| 143 return nullptr; |
| 144 } |
| 145 bssl::UniquePtr<CRYPTO_BUFFER> intermediate_cert_handle( |
| 146 X509Certificate::CreateOSCertHandleFromBytes( |
| 147 reinterpret_cast<const char*>(der_data.Data), der_data.Length)); |
| 148 if (!intermediate_cert_handle) |
| 149 return nullptr; |
| 150 intermediates_raw.push_back(intermediate_cert_handle.get()); |
| 151 intermediates.push_back(std::move(intermediate_cert_handle)); |
| 152 } |
| 153 scoped_refptr<X509Certificate> result( |
| 154 X509Certificate::CreateFromHandle(cert_handle.get(), intermediates_raw)); |
| 155 return result; |
| 156 #else |
| 157 return X509Certificate::CreateFromHandle(sec_cert, sec_chain); |
| 158 #endif |
| 159 } |
| 160 |
| 161 bool IsSelfSigned(SecCertificateRef cert_handle) { |
| 162 CSSMCachedCertificate cached_cert; |
| 163 OSStatus status = cached_cert.Init(cert_handle); |
| 164 if (status != noErr) |
| 165 return false; |
| 166 |
| 167 CSSMFieldValue subject; |
| 168 status = cached_cert.GetField(&CSSMOID_X509V1SubjectNameStd, &subject); |
| 169 if (status != CSSM_OK || !subject.field()) |
| 170 return false; |
| 171 |
| 172 CSSMFieldValue issuer; |
| 173 status = cached_cert.GetField(&CSSMOID_X509V1IssuerNameStd, &issuer); |
| 174 if (status != CSSM_OK || !issuer.field()) |
| 175 return false; |
| 176 |
| 177 if (subject.field()->Length != issuer.field()->Length || |
| 178 memcmp(subject.field()->Data, issuer.field()->Data, |
| 179 issuer.field()->Length) != 0) { |
| 180 return false; |
| 181 } |
| 182 |
| 183 CSSM_CL_HANDLE cl_handle = CSSM_INVALID_HANDLE; |
| 184 status = SecCertificateGetCLHandle(cert_handle, &cl_handle); |
| 185 if (status) |
| 186 return false; |
| 187 CSSM_DATA cert_data; |
| 188 status = SecCertificateGetData(cert_handle, &cert_data); |
| 189 if (status) |
| 190 return false; |
| 191 |
| 192 if (CSSM_CL_CertVerify(cl_handle, 0, &cert_data, &cert_data, NULL, 0)) |
| 193 return false; |
| 194 return true; |
| 195 } |
| 196 |
| 197 SHA256HashValue CalculateFingerprint256(SecCertificateRef cert) { |
| 198 SHA256HashValue sha256; |
| 199 memset(sha256.data, 0, sizeof(sha256.data)); |
| 200 |
| 201 CSSM_DATA cert_data; |
| 202 OSStatus status = SecCertificateGetData(cert, &cert_data); |
| 203 if (status) |
| 204 return sha256; |
| 205 |
| 206 DCHECK(cert_data.Data); |
| 207 DCHECK_NE(cert_data.Length, 0U); |
| 208 |
| 209 CC_SHA256(cert_data.Data, cert_data.Length, sha256.data); |
| 210 |
| 211 return sha256; |
| 212 } |
55 | 213 |
56 OSStatus CreateSSLClientPolicy(SecPolicyRef* policy) { | 214 OSStatus CreateSSLClientPolicy(SecPolicyRef* policy) { |
57 *policy = SecPolicyCreateSSL(false /* server */, nullptr); | 215 *policy = SecPolicyCreateSSL(false /* server */, nullptr); |
58 return *policy ? noErr : errSecNoPolicyModule; | 216 return *policy ? noErr : errSecNoPolicyModule; |
59 } | 217 } |
60 | 218 |
61 OSStatus CreateSSLServerPolicy(const std::string& hostname, | 219 OSStatus CreateSSLServerPolicy(const std::string& hostname, |
62 SecPolicyRef* policy) { | 220 SecPolicyRef* policy) { |
63 base::ScopedCFTypeRef<CFStringRef> hostname_cfstring; | 221 base::ScopedCFTypeRef<CFStringRef> hostname_cfstring; |
64 if (!hostname.empty()) { | 222 if (!hostname.empty()) { |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
252 CSSM_CL_CertAbortQuery(cl_handle_, results_handle); | 410 CSSM_CL_CertAbortQuery(cl_handle_, results_handle); |
253 field->Reset(cl_handle_, oid, field_ptr); | 411 field->Reset(cl_handle_, oid, field_ptr); |
254 return CSSM_OK; | 412 return CSSM_OK; |
255 } | 413 } |
256 | 414 |
257 } // namespace x509_util | 415 } // namespace x509_util |
258 | 416 |
259 #pragma clang diagnostic pop // "-Wdeprecated-declarations" | 417 #pragma clang diagnostic pop // "-Wdeprecated-declarations" |
260 | 418 |
261 } // namespace net | 419 } // namespace net |
OLD | NEW |