| 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 "base/base_paths.h" | 7 #include "base/base_paths.h" |
| 8 #include "base/files/file_util.h" | 8 #include "base/files/file_util.h" |
| 9 #include "base/files/scoped_temp_dir.h" | 9 #include "base/files/scoped_temp_dir.h" |
| 10 #include "base/path_service.h" | 10 #include "base/path_service.h" |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 120 ASSERT_TRUE(ReadTestCert("multi-root-A-by-B.pem", &a_by_b)); | 120 ASSERT_TRUE(ReadTestCert("multi-root-A-by-B.pem", &a_by_b)); |
| 121 ASSERT_TRUE(ReadTestCert("multi-root-B-by-C.pem", &b_by_c)); | 121 ASSERT_TRUE(ReadTestCert("multi-root-B-by-C.pem", &b_by_c)); |
| 122 ASSERT_TRUE(ReadTestCert("multi-root-B-by-F.pem", &b_by_f)); | 122 ASSERT_TRUE(ReadTestCert("multi-root-B-by-F.pem", &b_by_f)); |
| 123 ASSERT_TRUE(ReadTestCert("multi-root-C-by-D.pem", &c_by_d)); | 123 ASSERT_TRUE(ReadTestCert("multi-root-C-by-D.pem", &c_by_d)); |
| 124 ASSERT_TRUE(ReadTestCert("multi-root-C-by-E.pem", &c_by_e)); | 124 ASSERT_TRUE(ReadTestCert("multi-root-C-by-E.pem", &c_by_e)); |
| 125 ASSERT_TRUE(ReadTestCert("multi-root-F-by-E.pem", &f_by_e)); | 125 ASSERT_TRUE(ReadTestCert("multi-root-F-by-E.pem", &f_by_e)); |
| 126 ASSERT_TRUE(ReadTestCert("multi-root-D-by-D.pem", &d_by_d)); | 126 ASSERT_TRUE(ReadTestCert("multi-root-D-by-D.pem", &d_by_d)); |
| 127 ASSERT_TRUE(ReadTestCert("multi-root-E-by-E.pem", &e_by_e)); | 127 ASSERT_TRUE(ReadTestCert("multi-root-E-by-E.pem", &e_by_e)); |
| 128 | 128 |
| 129 base::ScopedCFTypeRef<CFDataRef> normalized_name_b = | 129 base::ScopedCFTypeRef<CFDataRef> normalized_name_b = |
| 130 TrustStoreMac::GetMacNormalizedIssuer(a_by_b); | 130 TrustStoreMac::GetMacNormalizedIssuer(a_by_b.get()); |
| 131 ASSERT_TRUE(normalized_name_b); | 131 ASSERT_TRUE(normalized_name_b); |
| 132 base::ScopedCFTypeRef<CFDataRef> normalized_name_c = | 132 base::ScopedCFTypeRef<CFDataRef> normalized_name_c = |
| 133 TrustStoreMac::GetMacNormalizedIssuer(b_by_c); | 133 TrustStoreMac::GetMacNormalizedIssuer(b_by_c.get()); |
| 134 ASSERT_TRUE(normalized_name_c); | 134 ASSERT_TRUE(normalized_name_c); |
| 135 base::ScopedCFTypeRef<CFDataRef> normalized_name_f = | 135 base::ScopedCFTypeRef<CFDataRef> normalized_name_f = |
| 136 TrustStoreMac::GetMacNormalizedIssuer(b_by_f); | 136 TrustStoreMac::GetMacNormalizedIssuer(b_by_f.get()); |
| 137 ASSERT_TRUE(normalized_name_f); | 137 ASSERT_TRUE(normalized_name_f); |
| 138 base::ScopedCFTypeRef<CFDataRef> normalized_name_d = | 138 base::ScopedCFTypeRef<CFDataRef> normalized_name_d = |
| 139 TrustStoreMac::GetMacNormalizedIssuer(c_by_d); | 139 TrustStoreMac::GetMacNormalizedIssuer(c_by_d.get()); |
| 140 ASSERT_TRUE(normalized_name_d); | 140 ASSERT_TRUE(normalized_name_d); |
| 141 base::ScopedCFTypeRef<CFDataRef> normalized_name_e = | 141 base::ScopedCFTypeRef<CFDataRef> normalized_name_e = |
| 142 TrustStoreMac::GetMacNormalizedIssuer(f_by_e); | 142 TrustStoreMac::GetMacNormalizedIssuer(f_by_e.get()); |
| 143 ASSERT_TRUE(normalized_name_e); | 143 ASSERT_TRUE(normalized_name_e); |
| 144 | 144 |
| 145 // Test that the matching keychain items are found, even though they aren't | 145 // Test that the matching keychain items are found, even though they aren't |
| 146 // trusted. | 146 // trusted. |
| 147 // TODO(eroman): These tests could be using TrustStore::SyncGetIssuersOf(). |
| 147 { | 148 { |
| 148 base::ScopedCFTypeRef<CFArrayRef> scoped_matching_items = | 149 base::ScopedCFTypeRef<CFArrayRef> scoped_matching_items = |
| 149 TrustStoreMac::FindMatchingCertificatesForMacNormalizedSubject( | 150 TrustStoreMac::FindMatchingCertificatesForMacNormalizedSubject( |
| 150 normalized_name_b.get()); | 151 normalized_name_b.get()); |
| 151 | 152 |
| 152 EXPECT_THAT(SecCertificateArrayAsDER(scoped_matching_items), | 153 EXPECT_THAT(SecCertificateArrayAsDER(scoped_matching_items), |
| 153 UnorderedElementsAreArray( | 154 UnorderedElementsAreArray( |
| 154 ParsedCertificateListAsDER({b_by_c, b_by_f}))); | 155 ParsedCertificateListAsDER({b_by_c, b_by_f}))); |
| 155 } | 156 } |
| 156 | 157 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 183 | 184 |
| 184 { | 185 { |
| 185 base::ScopedCFTypeRef<CFArrayRef> scoped_matching_items = | 186 base::ScopedCFTypeRef<CFArrayRef> scoped_matching_items = |
| 186 TrustStoreMac::FindMatchingCertificatesForMacNormalizedSubject( | 187 TrustStoreMac::FindMatchingCertificatesForMacNormalizedSubject( |
| 187 normalized_name_e.get()); | 188 normalized_name_e.get()); |
| 188 EXPECT_THAT( | 189 EXPECT_THAT( |
| 189 SecCertificateArrayAsDER(scoped_matching_items), | 190 SecCertificateArrayAsDER(scoped_matching_items), |
| 190 UnorderedElementsAreArray(ParsedCertificateListAsDER({e_by_e}))); | 191 UnorderedElementsAreArray(ParsedCertificateListAsDER({e_by_e}))); |
| 191 } | 192 } |
| 192 | 193 |
| 193 // None of the certs should return any matching TrustAnchors, since the test | 194 // Verify that none of the added certificates are considered trusted (since |
| 194 // certs in the keychain aren't trusted (unless someone manually added and | 195 // the test certs in the keychain aren't trusted, unless someone manually |
| 195 // trusted the test certs on the machine the test is being run on). | 196 // added and trusted the test certs on the machine the test is being run on). |
| 196 for (const auto& cert : | 197 for (const auto& cert : |
| 197 {a_by_b, b_by_c, b_by_f, c_by_d, c_by_e, f_by_e, d_by_d, e_by_e}) { | 198 {a_by_b, b_by_c, b_by_f, c_by_d, c_by_e, f_by_e, d_by_d, e_by_e}) { |
| 198 TrustAnchors matching_anchors; | 199 CertificateTrust trust = CertificateTrust::ForTrustAnchor(); |
| 199 trust_store.FindTrustAnchorsForCert(cert, &matching_anchors); | 200 trust_store.GetTrust(cert.get(), &trust); |
| 200 EXPECT_EQ(0u, matching_anchors.size()); | 201 EXPECT_EQ(CertificateTrustType::UNSPECIFIED, trust.type); |
| 201 } | 202 } |
| 202 } | 203 } |
| 203 | 204 |
| 204 // Test against all the certificates in the default keychains. Confirms that | 205 // Test against all the certificates in the default keychains. Confirms that |
| 205 // the computed trust value matches that of SecTrustEvaluate. | 206 // the computed trust value matches that of SecTrustEvaluate. |
| 206 TEST(TrustStoreMacTest, SystemCerts) { | 207 TEST(TrustStoreMacTest, SystemCerts) { |
| 207 // Get the list of all certificates in the user & system keychains. | 208 // Get the list of all certificates in the user & system keychains. |
| 208 // This may include both trusted and untrusted certificates. | 209 // This may include both trusted and untrusted certificates. |
| 209 // | 210 // |
| 210 // The output contains zero or more repetitions of: | 211 // The output contains zero or more repetitions of: |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 255 ParseCertificateOptions options; | 256 ParseCertificateOptions options; |
| 256 // For https://crt.sh/?q=D3EEFBCBBCF49867838626E23BB59CA01E305DB7: | 257 // For https://crt.sh/?q=D3EEFBCBBCF49867838626E23BB59CA01E305DB7: |
| 257 options.allow_invalid_serial_numbers = true; | 258 options.allow_invalid_serial_numbers = true; |
| 258 scoped_refptr<ParsedCertificate> cert = ParsedCertificate::Create( | 259 scoped_refptr<ParsedCertificate> cert = ParsedCertificate::Create( |
| 259 x509_util::CreateCryptoBuffer(cert_der), options, &errors); | 260 x509_util::CreateCryptoBuffer(cert_der), options, &errors); |
| 260 if (!cert) { | 261 if (!cert) { |
| 261 LOG(WARNING) << "ParseCertificate::Create " << hash_text << " failed:\n" | 262 LOG(WARNING) << "ParseCertificate::Create " << hash_text << " failed:\n" |
| 262 << errors.ToDebugString(); | 263 << errors.ToDebugString(); |
| 263 continue; | 264 continue; |
| 264 } | 265 } |
| 266 // Check if this cert is considered a trust anchor by TrustStoreMac. |
| 267 CertificateTrust cert_trust; |
| 268 trust_store.GetTrust(cert, &cert_trust); |
| 269 bool is_trust_anchor = cert_trust.IsTrustAnchor(); |
| 265 | 270 |
| 271 // Check if this cert is considered a trust anchor by the OS. |
| 266 base::ScopedCFTypeRef<SecCertificateRef> cert_handle( | 272 base::ScopedCFTypeRef<SecCertificateRef> cert_handle( |
| 267 x509_util::CreateSecCertificateFromBytes(cert->der_cert().UnsafeData(), | 273 x509_util::CreateSecCertificateFromBytes(cert->der_cert().UnsafeData(), |
| 268 cert->der_cert().Length())); | 274 cert->der_cert().Length())); |
| 269 if (!cert_handle) { | 275 if (!cert_handle) { |
| 270 ADD_FAILURE() << "CreateOSCertHandleFromBytes " << hash_text; | 276 ADD_FAILURE() << "CreateOSCertHandleFromBytes " << hash_text; |
| 271 continue; | 277 continue; |
| 272 } | 278 } |
| 273 base::ScopedCFTypeRef<CFDataRef> mac_normalized_subject; | |
| 274 { | |
| 275 base::AutoLock lock(crypto::GetMacSecurityServicesLock()); | |
| 276 mac_normalized_subject.reset( | |
| 277 SecCertificateCopyNormalizedSubjectContent(cert_handle, nullptr)); | |
| 278 } | |
| 279 if (!mac_normalized_subject) { | |
| 280 ADD_FAILURE() << "SecCertificateCopyNormalizedSubjectContent " | |
| 281 << hash_text; | |
| 282 continue; | |
| 283 } | |
| 284 | |
| 285 // Check if this cert is considered a trust anchor by TrustStoreMac. | |
| 286 TrustAnchors trust_anchors; | |
| 287 trust_store.FindTrustAnchorsByMacNormalizedSubject(mac_normalized_subject, | |
| 288 &trust_anchors); | |
| 289 bool is_trust_anchor = false; | |
| 290 for (const auto& anchor : trust_anchors) { | |
| 291 ASSERT_TRUE(anchor->cert()); | |
| 292 if (anchor->cert()->der_cert() == cert->der_cert()) | |
| 293 is_trust_anchor = true; | |
| 294 } | |
| 295 | |
| 296 // Check if this cert is considered a trust anchor by the OS. | |
| 297 base::ScopedCFTypeRef<SecTrustRef> trust; | 279 base::ScopedCFTypeRef<SecTrustRef> trust; |
| 298 { | 280 { |
| 299 base::AutoLock lock(crypto::GetMacSecurityServicesLock()); | 281 base::AutoLock lock(crypto::GetMacSecurityServicesLock()); |
| 300 ASSERT_EQ(noErr, | 282 ASSERT_EQ(noErr, |
| 301 SecTrustCreateWithCertificates(cert_handle, sec_policy, | 283 SecTrustCreateWithCertificates(cert_handle, sec_policy, |
| 302 trust.InitializeInto())); | 284 trust.InitializeInto())); |
| 303 ASSERT_EQ(noErr, | 285 ASSERT_EQ(noErr, |
| 304 SecTrustSetOptions( | 286 SecTrustSetOptions( |
| 305 trust, | 287 trust, |
| 306 kSecTrustOptionLeafIsCA | kSecTrustOptionAllowExpiredRoot)); | 288 kSecTrustOptionLeafIsCA | kSecTrustOptionAllowExpiredRoot)); |
| 307 | 289 |
| 308 SecTrustResultType trust_result; | 290 SecTrustResultType trust_result; |
| 309 ASSERT_EQ(noErr, SecTrustEvaluate(trust, &trust_result)); | 291 ASSERT_EQ(noErr, SecTrustEvaluate(trust, &trust_result)); |
| 310 bool expected_trust_anchor = | 292 bool expected_trust_anchor = |
| 311 ((trust_result == kSecTrustResultProceed) || | 293 ((trust_result == kSecTrustResultProceed) || |
| 312 (trust_result == kSecTrustResultUnspecified)) && | 294 (trust_result == kSecTrustResultUnspecified)) && |
| 313 (SecTrustGetCertificateCount(trust) == 1); | 295 (SecTrustGetCertificateCount(trust) == 1); |
| 314 EXPECT_EQ(expected_trust_anchor, is_trust_anchor); | 296 EXPECT_EQ(expected_trust_anchor, is_trust_anchor); |
| 315 } | 297 } |
| 316 } | 298 } |
| 317 } | 299 } |
| 318 | 300 |
| 319 } // namespace net | 301 } // namespace net |
| OLD | NEW |