| 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 |