OLD | NEW |
1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 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/internal/trust_store_mac.h" | 5 #include "net/cert/internal/trust_store_mac.h" |
6 | 6 |
7 #include <Security/Security.h> | 7 #include <Security/Security.h> |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/mac/foundation_util.h" | 10 #include "base/mac/foundation_util.h" |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
171 trust_settings, is_self_signed, policy_oid); | 171 trust_settings, is_self_signed, policy_oid); |
172 if (trust != TrustStatus::UNSPECIFIED) | 172 if (trust != TrustStatus::UNSPECIFIED) |
173 return trust; | 173 return trust; |
174 } | 174 } |
175 | 175 |
176 // No trust settings, or none of the settings were for the correct policy, or | 176 // No trust settings, or none of the settings were for the correct policy, or |
177 // had the correct trust result. | 177 // had the correct trust result. |
178 return TrustStatus::UNSPECIFIED; | 178 return TrustStatus::UNSPECIFIED; |
179 } | 179 } |
180 | 180 |
181 // Filters an array of SecCertificateRef by trust for |policy_oid|, returning | 181 } // namespace |
182 // the results as TrustAnchors in |out_anchors|. | 182 |
183 void FilterTrustedCertificates(CFArrayRef matching_items, | 183 TrustStoreMac::TrustStoreMac(CFTypeRef policy_oid) |
184 const CFStringRef policy_oid, | 184 : policy_oid_(base::mac::CFCastStrict<CFStringRef>(policy_oid)) { |
185 TrustAnchors* out_anchors) { | 185 DCHECK(policy_oid_); |
| 186 } |
| 187 |
| 188 TrustStoreMac::~TrustStoreMac() = default; |
| 189 |
| 190 void TrustStoreMac::SyncGetIssuersOf(const ParsedCertificate* cert, |
| 191 ParsedCertificateList* issuers) { |
| 192 base::ScopedCFTypeRef<CFDataRef> name_data = GetMacNormalizedIssuer(cert); |
| 193 |
| 194 base::ScopedCFTypeRef<CFArrayRef> matching_items = |
| 195 FindMatchingCertificatesForMacNormalizedSubject(name_data); |
| 196 if (!matching_items) |
| 197 return; |
| 198 |
| 199 // Convert to ParsedCertificate. |
186 for (CFIndex i = 0, item_count = CFArrayGetCount(matching_items); | 200 for (CFIndex i = 0, item_count = CFArrayGetCount(matching_items); |
187 i < item_count; ++i) { | 201 i < item_count; ++i) { |
188 SecCertificateRef match_cert_handle = reinterpret_cast<SecCertificateRef>( | 202 SecCertificateRef match_cert_handle = reinterpret_cast<SecCertificateRef>( |
189 const_cast<void*>(CFArrayGetValueAtIndex(matching_items, i))); | 203 const_cast<void*>(CFArrayGetValueAtIndex(matching_items, i))); |
190 | 204 |
191 if (IsSecCertificateTrustedForPolicy(match_cert_handle, policy_oid) != | |
192 TrustStatus::TRUSTED) | |
193 continue; | |
194 | |
195 base::ScopedCFTypeRef<CFDataRef> der_data( | 205 base::ScopedCFTypeRef<CFDataRef> der_data( |
196 SecCertificateCopyData(match_cert_handle)); | 206 SecCertificateCopyData(match_cert_handle)); |
197 if (!der_data) { | 207 if (!der_data) { |
198 LOG(ERROR) << "SecCertificateCopyData error"; | 208 LOG(ERROR) << "SecCertificateCopyData error"; |
199 continue; | 209 continue; |
200 } | 210 } |
201 | 211 |
202 CertErrors errors; | 212 CertErrors errors; |
203 ParseCertificateOptions options; | 213 ParseCertificateOptions options; |
204 options.allow_invalid_serial_numbers = true; | 214 options.allow_invalid_serial_numbers = true; |
205 scoped_refptr<ParsedCertificate> anchor_cert = ParsedCertificate::Create( | 215 scoped_refptr<ParsedCertificate> anchor_cert = ParsedCertificate::Create( |
206 x509_util::CreateCryptoBuffer(CFDataGetBytePtr(der_data.get()), | 216 x509_util::CreateCryptoBuffer(CFDataGetBytePtr(der_data.get()), |
207 CFDataGetLength(der_data.get())), | 217 CFDataGetLength(der_data.get())), |
208 options, &errors); | 218 options, &errors); |
209 if (!anchor_cert) { | 219 if (!anchor_cert) { |
210 // TODO(crbug.com/634443): return errors better. | 220 // TODO(crbug.com/634443): return errors better. |
211 LOG(ERROR) << "Error parsing issuer certificate:\n" | 221 LOG(ERROR) << "Error parsing issuer certificate:\n" |
212 << errors.ToDebugString(); | 222 << errors.ToDebugString(); |
213 continue; | 223 continue; |
214 } | 224 } |
215 | 225 |
216 out_anchors->push_back(TrustAnchor::CreateFromCertificateNoConstraints( | 226 issuers->push_back(std::move(anchor_cert)); |
217 std::move(anchor_cert))); | |
218 } | 227 } |
219 } | 228 } |
220 | 229 |
221 } // namespace | 230 void TrustStoreMac::GetTrust(const scoped_refptr<ParsedCertificate>& cert, |
| 231 CertificateTrust* trust) const { |
| 232 // TODO(eroman): Inefficient -- path building will convert between |
| 233 // SecCertificateRef and ParsedCertificate representations multiple times |
| 234 // (when getting the issuers, and again here). |
| 235 base::ScopedCFTypeRef<SecCertificateRef> cert_handle = |
| 236 x509_util::CreateSecCertificateFromBytes(cert->der_cert().UnsafeData(), |
| 237 cert->der_cert().Length()); |
222 | 238 |
223 TrustStoreMac::TrustStoreMac(CFTypeRef policy_oid) | 239 TrustStatus trust_status = |
224 : policy_oid_(base::mac::CFCastStrict<CFStringRef>(policy_oid)) { | 240 IsSecCertificateTrustedForPolicy(cert_handle, policy_oid_); |
225 DCHECK(policy_oid_); | 241 switch (trust_status) { |
226 } | 242 case TrustStatus::TRUSTED: |
| 243 *trust = CertificateTrust::ForTrustAnchor(); |
| 244 return; |
| 245 case TrustStatus::DISTRUSTED: |
| 246 *trust = CertificateTrust::ForDistrusted(); |
| 247 return; |
| 248 case TrustStatus::UNSPECIFIED: |
| 249 *trust = CertificateTrust::ForUnspecified(); |
| 250 return; |
| 251 } |
227 | 252 |
228 TrustStoreMac::~TrustStoreMac() = default; | 253 *trust = CertificateTrust::ForUnspecified(); |
229 | 254 return; |
230 void TrustStoreMac::FindTrustAnchorsForCert( | |
231 const scoped_refptr<ParsedCertificate>& cert, | |
232 TrustAnchors* out_anchors) const { | |
233 base::ScopedCFTypeRef<CFDataRef> name_data = GetMacNormalizedIssuer(cert); | |
234 | |
235 FindTrustAnchorsByMacNormalizedSubject(name_data, out_anchors); | |
236 } | 255 } |
237 | 256 |
238 // static | 257 // static |
239 base::ScopedCFTypeRef<CFArrayRef> | 258 base::ScopedCFTypeRef<CFArrayRef> |
240 TrustStoreMac::FindMatchingCertificatesForMacNormalizedSubject( | 259 TrustStoreMac::FindMatchingCertificatesForMacNormalizedSubject( |
241 CFDataRef name_data) { | 260 CFDataRef name_data) { |
242 base::ScopedCFTypeRef<CFArrayRef> matching_items; | 261 base::ScopedCFTypeRef<CFArrayRef> matching_items; |
243 base::ScopedCFTypeRef<CFMutableDictionaryRef> query( | 262 base::ScopedCFTypeRef<CFMutableDictionaryRef> query( |
244 CFDictionaryCreateMutable(nullptr, 0, &kCFTypeDictionaryKeyCallBacks, | 263 CFDictionaryCreateMutable(nullptr, 0, &kCFTypeDictionaryKeyCallBacks, |
245 &kCFTypeDictionaryValueCallBacks)); | 264 &kCFTypeDictionaryValueCallBacks)); |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
308 } | 327 } |
309 if (err) { | 328 if (err) { |
310 OSSTATUS_LOG(ERROR, err) << "SecItemCopyMatching error"; | 329 OSSTATUS_LOG(ERROR, err) << "SecItemCopyMatching error"; |
311 return matching_items; | 330 return matching_items; |
312 } | 331 } |
313 return matching_items; | 332 return matching_items; |
314 } | 333 } |
315 | 334 |
316 // static | 335 // static |
317 base::ScopedCFTypeRef<CFDataRef> TrustStoreMac::GetMacNormalizedIssuer( | 336 base::ScopedCFTypeRef<CFDataRef> TrustStoreMac::GetMacNormalizedIssuer( |
318 const scoped_refptr<ParsedCertificate>& cert) { | 337 const ParsedCertificate* cert) { |
319 base::ScopedCFTypeRef<CFDataRef> name_data; | 338 base::ScopedCFTypeRef<CFDataRef> name_data; |
320 // There does not appear to be any public API to get the normalized version | 339 // There does not appear to be any public API to get the normalized version |
321 // of a Name without creating a SecCertificate. | 340 // of a Name without creating a SecCertificate. |
322 base::ScopedCFTypeRef<SecCertificateRef> cert_handle( | 341 base::ScopedCFTypeRef<SecCertificateRef> cert_handle( |
323 x509_util::CreateSecCertificateFromBytes(cert->der_cert().UnsafeData(), | 342 x509_util::CreateSecCertificateFromBytes(cert->der_cert().UnsafeData(), |
324 cert->der_cert().Length())); | 343 cert->der_cert().Length())); |
325 if (!cert_handle) { | 344 if (!cert_handle) { |
326 LOG(ERROR) << "CreateOSCertHandleFromBytes"; | 345 LOG(ERROR) << "CreateOSCertHandleFromBytes"; |
327 return name_data; | 346 return name_data; |
328 } | 347 } |
329 { | 348 { |
330 base::AutoLock lock(crypto::GetMacSecurityServicesLock()); | 349 base::AutoLock lock(crypto::GetMacSecurityServicesLock()); |
331 name_data.reset( | 350 name_data.reset( |
332 SecCertificateCopyNormalizedIssuerContent(cert_handle, nullptr)); | 351 SecCertificateCopyNormalizedIssuerContent(cert_handle, nullptr)); |
333 } | 352 } |
334 if (!name_data) | 353 if (!name_data) |
335 LOG(ERROR) << "SecCertificateCopyNormalizedIssuerContent"; | 354 LOG(ERROR) << "SecCertificateCopyNormalizedIssuerContent"; |
336 return name_data; | 355 return name_data; |
337 } | 356 } |
338 | 357 |
339 void TrustStoreMac::FindTrustAnchorsByMacNormalizedSubject( | |
340 CFDataRef name_data, | |
341 TrustAnchors* out_anchors) const { | |
342 base::ScopedCFTypeRef<CFArrayRef> scoped_matching_items = | |
343 FindMatchingCertificatesForMacNormalizedSubject(name_data); | |
344 if (!scoped_matching_items) | |
345 return; | |
346 | |
347 FilterTrustedCertificates(scoped_matching_items.get(), policy_oid_, | |
348 out_anchors); | |
349 } | |
350 | |
351 } // namespace net | 358 } // namespace net |
OLD | NEW |