| OLD | NEW |
| 1 // Copyright (c) 2012 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/cert_verify_proc.h" | 5 #include "net/cert/cert_verify_proc_mac.h" |
| 6 | 6 |
| 7 #include <vector> | |
| 8 | |
| 9 #include "base/callback_helpers.h" | |
| 10 #include "base/files/file_path.h" | 7 #include "base/files/file_path.h" |
| 11 #include "base/files/file_util.h" | 8 #include "base/files/file_util.h" |
| 12 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/mac/mac_util.h" |
| 13 #include "base/macros.h" | 11 #include "base/macros.h" |
| 14 #include "base/sha1.h" | 12 #include "base/memory/ptr_util.h" |
| 15 #include "base/strings/string_number_conversions.h" | |
| 16 #include "base/test/histogram_tester.h" | |
| 17 #include "base/test/scoped_feature_list.h" | |
| 18 #include "build/build_config.h" | |
| 19 #include "crypto/sha2.h" | |
| 20 #include "net/base/net_errors.h" | 13 #include "net/base/net_errors.h" |
| 21 #include "net/cert/asn1_util.h" | |
| 22 #include "net/cert/cert_status_flags.h" | |
| 23 #include "net/cert/cert_verifier.h" | 14 #include "net/cert/cert_verifier.h" |
| 24 #include "net/cert/cert_verify_result.h" | 15 #include "net/cert/cert_verify_result.h" |
| 25 #include "net/cert/crl_set.h" | 16 #include "net/cert/crl_set.h" |
| 26 #include "net/cert/crl_set_storage.h" | 17 #include "net/cert/crl_set_storage.h" |
| 18 #include "net/cert/test_keychain_search_list_mac.h" |
| 27 #include "net/cert/test_root_certs.h" | 19 #include "net/cert/test_root_certs.h" |
| 28 #include "net/cert/x509_certificate.h" | 20 #include "net/cert/x509_certificate.h" |
| 29 #include "net/test/cert_test_util.h" | 21 #include "net/test/cert_test_util.h" |
| 30 #include "net/test/gtest_util.h" | 22 #include "net/test/gtest_util.h" |
| 31 #include "net/test/test_certificate_data.h" | |
| 32 #include "net/test/test_data_directory.h" | |
| 33 #include "testing/gmock/include/gmock/gmock.h" | 23 #include "testing/gmock/include/gmock/gmock.h" |
| 34 #include "testing/gtest/include/gtest/gtest.h" | 24 #include "testing/gtest/include/gtest/gtest.h" |
| 35 | 25 |
| 36 #if defined(OS_ANDROID) | |
| 37 #include "base/android/build_info.h" | |
| 38 #endif | |
| 39 | |
| 40 #if defined(OS_MACOSX) && !defined(OS_IOS) | |
| 41 #include "base/mac/mac_util.h" | |
| 42 #include "net/cert/test_keychain_search_list_mac.h" | |
| 43 #endif | |
| 44 | |
| 45 #if defined(OS_WIN) | |
| 46 #include "base/win/windows_version.h" | |
| 47 #endif | |
| 48 | |
| 49 using net::test::IsError; | 26 using net::test::IsError; |
| 50 using net::test::IsOk; | 27 using net::test::IsOk; |
| 51 | 28 |
| 52 using base::HexEncode; | |
| 53 | |
| 54 namespace net { | 29 namespace net { |
| 55 | 30 |
| 56 namespace { | 31 namespace { |
| 57 | 32 |
| 58 const char kTLSFeatureExtensionHistogram[] = | |
| 59 "Net.Certificate.TLSFeatureExtensionWithPrivateRoot"; | |
| 60 const char kTLSFeatureExtensionOCSPHistogram[] = | |
| 61 "Net.Certificate.TLSFeatureExtensionWithPrivateRootHasOCSP"; | |
| 62 | |
| 63 // Mock CertVerifyProc that sets the CertVerifyResult to a given value for | |
| 64 // all certificates that are Verify()'d | |
| 65 class MockCertVerifyProc : public CertVerifyProc { | |
| 66 public: | |
| 67 explicit MockCertVerifyProc(const CertVerifyResult& result) | |
| 68 : result_(result) {} | |
| 69 // CertVerifyProc implementation: | |
| 70 bool SupportsAdditionalTrustAnchors() const override { return false; } | |
| 71 bool SupportsOCSPStapling() const override { return false; } | |
| 72 | |
| 73 protected: | |
| 74 ~MockCertVerifyProc() override {} | |
| 75 | |
| 76 private: | |
| 77 int VerifyInternal(X509Certificate* cert, | |
| 78 const std::string& hostname, | |
| 79 const std::string& ocsp_response, | |
| 80 int flags, | |
| 81 CRLSet* crl_set, | |
| 82 const CertificateList& additional_trust_anchors, | |
| 83 CertVerifyResult* verify_result) override; | |
| 84 | |
| 85 const CertVerifyResult result_; | |
| 86 | |
| 87 DISALLOW_COPY_AND_ASSIGN(MockCertVerifyProc); | |
| 88 }; | |
| 89 | |
| 90 int MockCertVerifyProc::VerifyInternal( | |
| 91 X509Certificate* cert, | |
| 92 const std::string& hostname, | |
| 93 const std::string& ocsp_response, | |
| 94 int flags, | |
| 95 CRLSet* crl_set, | |
| 96 const CertificateList& additional_trust_anchors, | |
| 97 CertVerifyResult* verify_result) { | |
| 98 *verify_result = result_; | |
| 99 verify_result->verified_cert = cert; | |
| 100 return OK; | |
| 101 } | |
| 102 | |
| 103 // This enum identifies a concrete implemenation of CertVerifyProc. | |
| 104 // | |
| 105 // The type is erased by CertVerifyProc::CreateDefault(), however | |
| 106 // needs to be known for some of the test expectations. | |
| 107 enum CertVerifyProcType { | |
| 108 CERT_VERIFY_PROC_NSS, | |
| 109 CERT_VERIFY_PROC_OPENSSL, | |
| 110 CERT_VERIFY_PROC_ANDROID, | |
| 111 CERT_VERIFY_PROC_IOS, | |
| 112 CERT_VERIFY_PROC_MAC, | |
| 113 CERT_VERIFY_PROC_WIN, | |
| 114 }; | |
| 115 | |
| 116 // Returns the CertVerifyProcType corresponding to what | |
| 117 // CertVerifyProc::CreateDefault() returns. This needs to be kept in sync with | |
| 118 // CreateDefault(). | |
| 119 CertVerifyProcType GetDefaultCertVerifyProcType() { | |
| 120 #if defined(USE_NSS_CERTS) | |
| 121 return CERT_VERIFY_PROC_NSS; | |
| 122 #elif defined(USE_OPENSSL_CERTS) && !defined(OS_ANDROID) | |
| 123 return CERT_VERIFY_PROC_OPENSSL; | |
| 124 #elif defined(OS_ANDROID) | |
| 125 return CERT_VERIFY_PROC_ANDROID; | |
| 126 #elif defined(OS_IOS) | |
| 127 return CERT_VERIFY_PROC_IOS; | |
| 128 #elif defined(OS_MACOSX) | |
| 129 return CERT_VERIFY_PROC_MAC; | |
| 130 #elif defined(OS_WIN) | |
| 131 return CERT_VERIFY_PROC_WIN; | |
| 132 #else | |
| 133 // Will fail to compile. | |
| 134 #endif | |
| 135 } | |
| 136 | |
| 137 // Whether the test is running within the iphone simulator. | |
| 138 const bool kTargetIsIphoneSimulator = | |
| 139 #if TARGET_IPHONE_SIMULATOR | |
| 140 true; | |
| 141 #else | |
| 142 false; | |
| 143 #endif | |
| 144 | |
| 145 // Template helper to load a series of certificate files into a CertificateList. | |
| 146 // Like CertTestUtil's CreateCertificateListFromFile, except it can load a | |
| 147 // series of individual certificates (to make the tests clearer). | |
| 148 template <size_t N> | |
| 149 void LoadCertificateFiles(const char* const (&cert_files)[N], | |
| 150 CertificateList* certs) { | |
| 151 certs->clear(); | |
| 152 for (size_t i = 0; i < N; ++i) { | |
| 153 SCOPED_TRACE(cert_files[i]); | |
| 154 scoped_refptr<X509Certificate> cert = CreateCertificateChainFromFile( | |
| 155 GetTestCertsDirectory(), cert_files[i], X509Certificate::FORMAT_AUTO); | |
| 156 ASSERT_TRUE(cert); | |
| 157 certs->push_back(cert); | |
| 158 } | |
| 159 } | |
| 160 | |
| 161 // Returns a textual description of the CertVerifyProc implementation | |
| 162 // that is being tested, used to give better names to parameterized | |
| 163 // tests. | |
| 164 std::string VerifyProcTypeToName( | |
| 165 const testing::TestParamInfo<CertVerifyProcType>& params) { | |
| 166 switch (params.param) { | |
| 167 case CERT_VERIFY_PROC_NSS: | |
| 168 return "CertVerifyProcNSS"; | |
| 169 case CERT_VERIFY_PROC_OPENSSL: | |
| 170 return "CertVerifyProcOpenSSL"; | |
| 171 case CERT_VERIFY_PROC_ANDROID: | |
| 172 return "CertVerifyProcAndroid"; | |
| 173 case CERT_VERIFY_PROC_IOS: | |
| 174 return "CertVerifyProcIOS"; | |
| 175 case CERT_VERIFY_PROC_MAC: | |
| 176 return "CertVerifyProcMac"; | |
| 177 case CERT_VERIFY_PROC_WIN: | |
| 178 return "CertVerifyProcWin"; | |
| 179 } | |
| 180 | |
| 181 return nullptr; | |
| 182 } | |
| 183 | |
| 184 // The set of all CertVerifyProcTypes that tests should be | |
| 185 // parameterized on. | |
| 186 const std::vector<CertVerifyProcType> kAllCertVerifiers = { | |
| 187 GetDefaultCertVerifyProcType()}; | |
| 188 | |
| 189 } // namespace | |
| 190 | |
| 191 // This fixture is for tests that apply to concrete implementations of | |
| 192 // CertVerifyProc. It will be run for all of the concrete | |
| 193 // CertVerifyProc types. | |
| 194 // | |
| 195 // It is called "Internal" as it tests the internal methods like | |
| 196 // "VerifyInternal()". | |
| 197 class CertVerifyProcInternalTest | |
| 198 : public testing::TestWithParam<CertVerifyProcType> { | |
| 199 protected: | |
| 200 void SetUp() override { | |
| 201 EXPECT_EQ(verify_proc_type(), GetDefaultCertVerifyProcType()); | |
| 202 verify_proc_ = CertVerifyProc::CreateDefault(); | |
| 203 } | |
| 204 | |
| 205 int Verify(X509Certificate* cert, | |
| 206 const std::string& hostname, | |
| 207 int flags, | |
| 208 CRLSet* crl_set, | |
| 209 const CertificateList& additional_trust_anchors, | |
| 210 CertVerifyResult* verify_result) { | |
| 211 return verify_proc_->Verify(cert, hostname, std::string(), flags, crl_set, | |
| 212 additional_trust_anchors, verify_result); | |
| 213 } | |
| 214 | |
| 215 CertVerifyProcType verify_proc_type() const { return GetParam(); } | |
| 216 | |
| 217 bool SupportsAdditionalTrustAnchors() const { | |
| 218 return verify_proc_->SupportsAdditionalTrustAnchors(); | |
| 219 } | |
| 220 | |
| 221 bool SupportsReturningVerifiedChain() const { | |
| 222 #if defined(OS_ANDROID) | |
| 223 // Before API level 17, Android does not expose the APIs necessary to get at | |
| 224 // the verified certificate chain. | |
| 225 if (verify_proc_type() == CERT_VERIFY_PROC_ANDROID && | |
| 226 base::android::BuildInfo::GetInstance()->sdk_int() < 17) | |
| 227 return false; | |
| 228 #endif | |
| 229 return true; | |
| 230 } | |
| 231 | |
| 232 bool SupportsDetectingKnownRoots() const { | |
| 233 #if defined(OS_ANDROID) | |
| 234 // Before API level 17, Android does not expose the APIs necessary to get at | |
| 235 // the verified certificate chain and detect known roots. | |
| 236 if (verify_proc_type() == CERT_VERIFY_PROC_ANDROID) | |
| 237 return base::android::BuildInfo::GetInstance()->sdk_int() >= 17; | |
| 238 #endif | |
| 239 | |
| 240 // iOS does not expose the APIs necessary to get the known system roots. | |
| 241 if (verify_proc_type() == CERT_VERIFY_PROC_IOS) | |
| 242 return false; | |
| 243 | |
| 244 return true; | |
| 245 } | |
| 246 | |
| 247 bool WeakKeysAreInvalid() const { | |
| 248 #if defined(OS_MACOSX) && !defined(OS_IOS) | |
| 249 // Starting with Mac OS 10.12, certs with weak keys are treated as | |
| 250 // (recoverable) invalid certificate errors. | |
| 251 if (verify_proc_type() == CERT_VERIFY_PROC_MAC && | |
| 252 base::mac::IsAtLeastOS10_12()) { | |
| 253 return true; | |
| 254 } | |
| 255 #endif | |
| 256 return false; | |
| 257 } | |
| 258 | |
| 259 bool SupportsCRLSet() const { | |
| 260 return verify_proc_type() == CERT_VERIFY_PROC_NSS || | |
| 261 verify_proc_type() == CERT_VERIFY_PROC_WIN || | |
| 262 verify_proc_type() == CERT_VERIFY_PROC_MAC; | |
| 263 } | |
| 264 | |
| 265 bool SupportsCRLSetsInPathBuilding() const { | |
| 266 return verify_proc_type() == CERT_VERIFY_PROC_WIN || | |
| 267 verify_proc_type() == CERT_VERIFY_PROC_NSS; | |
| 268 } | |
| 269 | |
| 270 CertVerifyProc* verify_proc() const { return verify_proc_.get(); } | |
| 271 | |
| 272 private: | |
| 273 scoped_refptr<CertVerifyProc> verify_proc_; | |
| 274 }; | |
| 275 | |
| 276 INSTANTIATE_TEST_CASE_P(, | |
| 277 CertVerifyProcInternalTest, | |
| 278 testing::ValuesIn(kAllCertVerifiers), | |
| 279 VerifyProcTypeToName); | |
| 280 | |
| 281 // TODO(rsleevi): Reenable this test once comodo.chaim.pem is no longer | |
| 282 // expired, http://crbug.com/502818 | |
| 283 TEST_P(CertVerifyProcInternalTest, DISABLED_EVVerification) { | |
| 284 if (verify_proc_type() == CERT_VERIFY_PROC_ANDROID || | |
| 285 verify_proc_type() == CERT_VERIFY_PROC_OPENSSL) { | |
| 286 // TODO(jnd): http://crbug.com/117478 - EV verification is not yet | |
| 287 // supported. | |
| 288 LOG(INFO) << "Skipping test as EV verification is not yet supported"; | |
| 289 return; | |
| 290 } | |
| 291 | |
| 292 CertificateList certs = | |
| 293 CreateCertificateListFromFile(GetTestCertsDirectory(), "comodo.chain.pem", | |
| 294 X509Certificate::FORMAT_PEM_CERT_SEQUENCE); | |
| 295 ASSERT_EQ(3U, certs.size()); | |
| 296 | |
| 297 X509Certificate::OSCertHandles intermediates; | |
| 298 intermediates.push_back(certs[1]->os_cert_handle()); | |
| 299 intermediates.push_back(certs[2]->os_cert_handle()); | |
| 300 | |
| 301 scoped_refptr<X509Certificate> comodo_chain = | |
| 302 X509Certificate::CreateFromHandle(certs[0]->os_cert_handle(), | |
| 303 intermediates); | |
| 304 | |
| 305 scoped_refptr<CRLSet> crl_set(CRLSet::ForTesting(false, NULL, "")); | |
| 306 CertVerifyResult verify_result; | |
| 307 int flags = CertVerifier::VERIFY_EV_CERT; | |
| 308 int error = Verify(comodo_chain.get(), "comodo.com", flags, crl_set.get(), | |
| 309 CertificateList(), &verify_result); | |
| 310 EXPECT_THAT(error, IsOk()); | |
| 311 EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_IS_EV); | |
| 312 } | |
| 313 | |
| 314 // TODO(crbug.com/605457): the test expectation was incorrect on some | |
| 315 // configurations, so disable the test until it is fixed (better to have | |
| 316 // a bug to track a failing test than a false sense of security due to | |
| 317 // false positive). | |
| 318 TEST_P(CertVerifyProcInternalTest, DISABLED_PaypalNullCertParsing) { | |
| 319 // A certificate for www.paypal.com with a NULL byte in the common name. | |
| 320 // From http://www.gossamer-threads.com/lists/fulldisc/full-disclosure/70363 | |
| 321 SHA256HashValue paypal_null_fingerprint = {{0x00}}; | |
| 322 | |
| 323 scoped_refptr<X509Certificate> paypal_null_cert( | |
| 324 X509Certificate::CreateFromBytes( | |
| 325 reinterpret_cast<const char*>(paypal_null_der), | |
| 326 sizeof(paypal_null_der))); | |
| 327 | |
| 328 ASSERT_NE(static_cast<X509Certificate*>(NULL), paypal_null_cert.get()); | |
| 329 | |
| 330 EXPECT_EQ(paypal_null_fingerprint, X509Certificate::CalculateFingerprint256( | |
| 331 paypal_null_cert->os_cert_handle())); | |
| 332 | |
| 333 int flags = 0; | |
| 334 CertVerifyResult verify_result; | |
| 335 int error = Verify(paypal_null_cert.get(), "www.paypal.com", flags, NULL, | |
| 336 CertificateList(), &verify_result); | |
| 337 | |
| 338 if (verify_proc_type() == CERT_VERIFY_PROC_NSS || | |
| 339 verify_proc_type() == CERT_VERIFY_PROC_ANDROID) { | |
| 340 EXPECT_THAT(error, IsError(ERR_CERT_COMMON_NAME_INVALID)); | |
| 341 } else if (verify_proc_type() == CERT_VERIFY_PROC_IOS && | |
| 342 kTargetIsIphoneSimulator) { | |
| 343 // iOS returns a ERR_CERT_INVALID error on the simulator, while returning | |
| 344 // ERR_CERT_AUTHORITY_INVALID on the real device. | |
| 345 EXPECT_THAT(error, IsError(ERR_CERT_INVALID)); | |
| 346 } else { | |
| 347 // TOOD(bulach): investigate why macosx and win aren't returning | |
| 348 // ERR_CERT_INVALID or ERR_CERT_COMMON_NAME_INVALID. | |
| 349 EXPECT_THAT(error, IsError(ERR_CERT_AUTHORITY_INVALID)); | |
| 350 } | |
| 351 | |
| 352 // Either the system crypto library should correctly report a certificate | |
| 353 // name mismatch, or our certificate blacklist should cause us to report an | |
| 354 // invalid certificate. | |
| 355 if (verify_proc_type() == CERT_VERIFY_PROC_NSS || | |
| 356 verify_proc_type() == CERT_VERIFY_PROC_WIN) { | |
| 357 EXPECT_TRUE(verify_result.cert_status & | |
| 358 (CERT_STATUS_COMMON_NAME_INVALID | CERT_STATUS_INVALID)); | |
| 359 } | |
| 360 | |
| 361 // TODO(crbug.com/649017): What expectations to use for the other verifiers? | |
| 362 } | |
| 363 | |
| 364 // A regression test for http://crbug.com/31497. | |
| 365 TEST_P(CertVerifyProcInternalTest, IntermediateCARequireExplicitPolicy) { | |
| 366 if (verify_proc_type() == CERT_VERIFY_PROC_ANDROID) { | |
| 367 // Disabled on Android, as the Android verification libraries require an | |
| 368 // explicit policy to be specified, even when anyPolicy is permitted. | |
| 369 LOG(INFO) << "Skipping test on Android"; | |
| 370 return; | |
| 371 } | |
| 372 | |
| 373 base::FilePath certs_dir = GetTestCertsDirectory(); | |
| 374 | |
| 375 CertificateList certs = CreateCertificateListFromFile( | |
| 376 certs_dir, "explicit-policy-chain.pem", X509Certificate::FORMAT_AUTO); | |
| 377 ASSERT_EQ(3U, certs.size()); | |
| 378 | |
| 379 X509Certificate::OSCertHandles intermediates; | |
| 380 intermediates.push_back(certs[1]->os_cert_handle()); | |
| 381 | |
| 382 scoped_refptr<X509Certificate> cert = X509Certificate::CreateFromHandle( | |
| 383 certs[0]->os_cert_handle(), intermediates); | |
| 384 ASSERT_TRUE(cert.get()); | |
| 385 | |
| 386 ScopedTestRoot scoped_root(certs[2].get()); | |
| 387 | |
| 388 int flags = 0; | |
| 389 CertVerifyResult verify_result; | |
| 390 int error = Verify(cert.get(), "policy_test.example", flags, NULL, | |
| 391 CertificateList(), &verify_result); | |
| 392 EXPECT_THAT(error, IsOk()); | |
| 393 EXPECT_EQ(0u, verify_result.cert_status); | |
| 394 } | |
| 395 | |
| 396 TEST_P(CertVerifyProcInternalTest, RejectExpiredCert) { | |
| 397 base::FilePath certs_dir = GetTestCertsDirectory(); | |
| 398 | |
| 399 // Load root_ca_cert.pem into the test root store. | |
| 400 ScopedTestRoot test_root( | |
| 401 ImportCertFromFile(certs_dir, "root_ca_cert.pem").get()); | |
| 402 | |
| 403 CertificateList certs = CreateCertificateListFromFile( | |
| 404 certs_dir, "expired_cert.pem", X509Certificate::FORMAT_AUTO); | |
| 405 ASSERT_EQ(1U, certs.size()); | |
| 406 | |
| 407 X509Certificate::OSCertHandles intermediates; | |
| 408 scoped_refptr<X509Certificate> cert = X509Certificate::CreateFromHandle( | |
| 409 certs[0]->os_cert_handle(), intermediates); | |
| 410 | |
| 411 int flags = 0; | |
| 412 CertVerifyResult verify_result; | |
| 413 int error = Verify(cert.get(), "127.0.0.1", flags, NULL, CertificateList(), | |
| 414 &verify_result); | |
| 415 EXPECT_THAT(error, IsError(ERR_CERT_DATE_INVALID)); | |
| 416 EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_DATE_INVALID); | |
| 417 } | |
| 418 | |
| 419 // Currently, only RSA and DSA keys are checked for weakness, and our example | |
| 420 // weak size is 768. These could change in the future. | |
| 421 // | |
| 422 // Note that this means there may be false negatives: keys for other | |
| 423 // algorithms and which are weak will pass this test. | |
| 424 static bool IsWeakKeyType(const std::string& key_type) { | |
| 425 size_t pos = key_type.find("-"); | |
| 426 std::string size = key_type.substr(0, pos); | |
| 427 std::string type = key_type.substr(pos + 1); | |
| 428 | |
| 429 if (type == "rsa" || type == "dsa") | |
| 430 return size == "768"; | |
| 431 | |
| 432 return false; | |
| 433 } | |
| 434 | |
| 435 TEST_P(CertVerifyProcInternalTest, RejectWeakKeys) { | |
| 436 base::FilePath certs_dir = GetTestCertsDirectory(); | |
| 437 typedef std::vector<std::string> Strings; | |
| 438 Strings key_types; | |
| 439 | |
| 440 // generate-weak-test-chains.sh currently has: | |
| 441 // key_types="768-rsa 1024-rsa 2048-rsa prime256v1-ecdsa" | |
| 442 // We must use the same key types here. The filenames generated look like: | |
| 443 // 2048-rsa-ee-by-768-rsa-intermediate.pem | |
| 444 key_types.push_back("768-rsa"); | |
| 445 key_types.push_back("1024-rsa"); | |
| 446 key_types.push_back("2048-rsa"); | |
| 447 key_types.push_back("prime256v1-ecdsa"); | |
| 448 | |
| 449 // Add the root that signed the intermediates for this test. | |
| 450 scoped_refptr<X509Certificate> root_cert = | |
| 451 ImportCertFromFile(certs_dir, "2048-rsa-root.pem"); | |
| 452 ASSERT_NE(static_cast<X509Certificate*>(NULL), root_cert.get()); | |
| 453 ScopedTestRoot scoped_root(root_cert.get()); | |
| 454 | |
| 455 // Now test each chain. | |
| 456 for (Strings::const_iterator ee_type = key_types.begin(); | |
| 457 ee_type != key_types.end(); ++ee_type) { | |
| 458 for (Strings::const_iterator signer_type = key_types.begin(); | |
| 459 signer_type != key_types.end(); ++signer_type) { | |
| 460 std::string basename = | |
| 461 *ee_type + "-ee-by-" + *signer_type + "-intermediate.pem"; | |
| 462 SCOPED_TRACE(basename); | |
| 463 scoped_refptr<X509Certificate> ee_cert = | |
| 464 ImportCertFromFile(certs_dir, basename); | |
| 465 ASSERT_NE(static_cast<X509Certificate*>(NULL), ee_cert.get()); | |
| 466 | |
| 467 basename = *signer_type + "-intermediate.pem"; | |
| 468 scoped_refptr<X509Certificate> intermediate = | |
| 469 ImportCertFromFile(certs_dir, basename); | |
| 470 ASSERT_NE(static_cast<X509Certificate*>(NULL), intermediate.get()); | |
| 471 | |
| 472 X509Certificate::OSCertHandles intermediates; | |
| 473 intermediates.push_back(intermediate->os_cert_handle()); | |
| 474 scoped_refptr<X509Certificate> cert_chain = | |
| 475 X509Certificate::CreateFromHandle(ee_cert->os_cert_handle(), | |
| 476 intermediates); | |
| 477 | |
| 478 CertVerifyResult verify_result; | |
| 479 int error = Verify(cert_chain.get(), "127.0.0.1", 0, NULL, | |
| 480 CertificateList(), &verify_result); | |
| 481 | |
| 482 if (IsWeakKeyType(*ee_type) || IsWeakKeyType(*signer_type)) { | |
| 483 EXPECT_NE(OK, error); | |
| 484 EXPECT_EQ(CERT_STATUS_WEAK_KEY, | |
| 485 verify_result.cert_status & CERT_STATUS_WEAK_KEY); | |
| 486 EXPECT_EQ(WeakKeysAreInvalid() ? CERT_STATUS_INVALID : 0, | |
| 487 verify_result.cert_status & CERT_STATUS_INVALID); | |
| 488 } else { | |
| 489 EXPECT_THAT(error, IsOk()); | |
| 490 EXPECT_EQ(0U, verify_result.cert_status & CERT_STATUS_WEAK_KEY); | |
| 491 } | |
| 492 } | |
| 493 } | |
| 494 } | |
| 495 | |
| 496 // Regression test for http://crbug.com/108514. | |
| 497 TEST_P(CertVerifyProcInternalTest, ExtraneousMD5RootCert) { | |
| 498 if (!SupportsReturningVerifiedChain()) { | |
| 499 LOG(INFO) << "Skipping this test in this platform."; | |
| 500 return; | |
| 501 } | |
| 502 | |
| 503 if (verify_proc_type() == CERT_VERIFY_PROC_MAC) { | |
| 504 // Disabled on OS X - Security.framework doesn't ignore superflous | |
| 505 // certificates provided by servers. | |
| 506 // TODO(eroman): Is this still needed? | |
| 507 LOG(INFO) << "Skipping this test as Security.framework doesn't ignore " | |
| 508 "superflous certificates provided by servers."; | |
| 509 return; | |
| 510 } | |
| 511 | |
| 512 base::FilePath certs_dir = GetTestCertsDirectory(); | |
| 513 | |
| 514 scoped_refptr<X509Certificate> server_cert = | |
| 515 ImportCertFromFile(certs_dir, "cross-signed-leaf.pem"); | |
| 516 ASSERT_NE(static_cast<X509Certificate*>(NULL), server_cert.get()); | |
| 517 | |
| 518 scoped_refptr<X509Certificate> extra_cert = | |
| 519 ImportCertFromFile(certs_dir, "cross-signed-root-md5.pem"); | |
| 520 ASSERT_NE(static_cast<X509Certificate*>(NULL), extra_cert.get()); | |
| 521 | |
| 522 scoped_refptr<X509Certificate> root_cert = | |
| 523 ImportCertFromFile(certs_dir, "cross-signed-root-sha256.pem"); | |
| 524 ASSERT_NE(static_cast<X509Certificate*>(NULL), root_cert.get()); | |
| 525 | |
| 526 ScopedTestRoot scoped_root(root_cert.get()); | |
| 527 | |
| 528 X509Certificate::OSCertHandles intermediates; | |
| 529 intermediates.push_back(extra_cert->os_cert_handle()); | |
| 530 scoped_refptr<X509Certificate> cert_chain = X509Certificate::CreateFromHandle( | |
| 531 server_cert->os_cert_handle(), intermediates); | |
| 532 | |
| 533 CertVerifyResult verify_result; | |
| 534 int flags = 0; | |
| 535 int error = Verify(cert_chain.get(), "127.0.0.1", flags, NULL, | |
| 536 CertificateList(), &verify_result); | |
| 537 EXPECT_THAT(error, IsOk()); | |
| 538 | |
| 539 // The extra MD5 root should be discarded | |
| 540 ASSERT_TRUE(verify_result.verified_cert.get()); | |
| 541 ASSERT_EQ(1u, | |
| 542 verify_result.verified_cert->GetIntermediateCertificates().size()); | |
| 543 EXPECT_TRUE(X509Certificate::IsSameOSCert( | |
| 544 verify_result.verified_cert->GetIntermediateCertificates().front(), | |
| 545 root_cert->os_cert_handle())); | |
| 546 | |
| 547 EXPECT_FALSE(verify_result.has_md5); | |
| 548 } | |
| 549 | |
| 550 // Test for bug 94673. | |
| 551 TEST_P(CertVerifyProcInternalTest, GoogleDigiNotarTest) { | |
| 552 base::FilePath certs_dir = GetTestCertsDirectory(); | |
| 553 | |
| 554 scoped_refptr<X509Certificate> server_cert = | |
| 555 ImportCertFromFile(certs_dir, "google_diginotar.pem"); | |
| 556 ASSERT_NE(static_cast<X509Certificate*>(NULL), server_cert.get()); | |
| 557 | |
| 558 scoped_refptr<X509Certificate> intermediate_cert = | |
| 559 ImportCertFromFile(certs_dir, "diginotar_public_ca_2025.pem"); | |
| 560 ASSERT_NE(static_cast<X509Certificate*>(NULL), intermediate_cert.get()); | |
| 561 | |
| 562 X509Certificate::OSCertHandles intermediates; | |
| 563 intermediates.push_back(intermediate_cert->os_cert_handle()); | |
| 564 scoped_refptr<X509Certificate> cert_chain = X509Certificate::CreateFromHandle( | |
| 565 server_cert->os_cert_handle(), intermediates); | |
| 566 | |
| 567 CertVerifyResult verify_result; | |
| 568 int flags = CertVerifier::VERIFY_REV_CHECKING_ENABLED; | |
| 569 int error = Verify(cert_chain.get(), "mail.google.com", flags, NULL, | |
| 570 CertificateList(), &verify_result); | |
| 571 EXPECT_NE(OK, error); | |
| 572 | |
| 573 // Now turn off revocation checking. Certificate verification should still | |
| 574 // fail. | |
| 575 flags = 0; | |
| 576 error = Verify(cert_chain.get(), "mail.google.com", flags, NULL, | |
| 577 CertificateList(), &verify_result); | |
| 578 EXPECT_NE(OK, error); | |
| 579 } | |
| 580 | |
| 581 // Ensures the CertVerifyProc blacklist remains in sorted order, so that it | |
| 582 // can be binary-searched. | |
| 583 TEST(CertVerifyProcTest, BlacklistIsSorted) { | |
| 584 // Defines kBlacklistedSPKIs. | |
| 585 #include "net/cert/cert_verify_proc_blacklist.inc" | |
| 586 for (size_t i = 0; i < arraysize(kBlacklistedSPKIs) - 1; ++i) { | |
| 587 EXPECT_GT(0, memcmp(kBlacklistedSPKIs[i], kBlacklistedSPKIs[i + 1], | |
| 588 crypto::kSHA256Length)) | |
| 589 << " at index " << i; | |
| 590 } | |
| 591 } | |
| 592 | |
| 593 TEST(CertVerifyProcTest, DigiNotarCerts) { | |
| 594 static const char* const kDigiNotarFilenames[] = { | |
| 595 "diginotar_root_ca.pem", "diginotar_cyber_ca.pem", | |
| 596 "diginotar_services_1024_ca.pem", "diginotar_pkioverheid.pem", | |
| 597 "diginotar_pkioverheid_g2.pem", NULL, | |
| 598 }; | |
| 599 | |
| 600 base::FilePath certs_dir = GetTestCertsDirectory(); | |
| 601 | |
| 602 for (size_t i = 0; kDigiNotarFilenames[i]; i++) { | |
| 603 scoped_refptr<X509Certificate> diginotar_cert = | |
| 604 ImportCertFromFile(certs_dir, kDigiNotarFilenames[i]); | |
| 605 std::string der_bytes; | |
| 606 ASSERT_TRUE(X509Certificate::GetDEREncoded(diginotar_cert->os_cert_handle(), | |
| 607 &der_bytes)); | |
| 608 | |
| 609 base::StringPiece spki; | |
| 610 ASSERT_TRUE(asn1::ExtractSPKIFromDERCert(der_bytes, &spki)); | |
| 611 | |
| 612 std::string spki_sha256 = crypto::SHA256HashString(spki.as_string()); | |
| 613 | |
| 614 HashValueVector public_keys; | |
| 615 HashValue hash(HASH_VALUE_SHA256); | |
| 616 ASSERT_EQ(hash.size(), spki_sha256.size()); | |
| 617 memcpy(hash.data(), spki_sha256.data(), spki_sha256.size()); | |
| 618 public_keys.push_back(hash); | |
| 619 | |
| 620 EXPECT_TRUE(CertVerifyProc::IsPublicKeyBlacklisted(public_keys)) | |
| 621 << "Public key not blocked for " << kDigiNotarFilenames[i]; | |
| 622 } | |
| 623 } | |
| 624 | |
| 625 TEST_P(CertVerifyProcInternalTest, NameConstraintsOk) { | |
| 626 CertificateList ca_cert_list = | |
| 627 CreateCertificateListFromFile(GetTestCertsDirectory(), "root_ca_cert.pem", | |
| 628 X509Certificate::FORMAT_AUTO); | |
| 629 ASSERT_EQ(1U, ca_cert_list.size()); | |
| 630 ScopedTestRoot test_root(ca_cert_list[0].get()); | |
| 631 | |
| 632 CertificateList cert_list = CreateCertificateListFromFile( | |
| 633 GetTestCertsDirectory(), "name_constraint_good.pem", | |
| 634 X509Certificate::FORMAT_AUTO); | |
| 635 ASSERT_EQ(1U, cert_list.size()); | |
| 636 | |
| 637 X509Certificate::OSCertHandles intermediates; | |
| 638 scoped_refptr<X509Certificate> leaf = X509Certificate::CreateFromHandle( | |
| 639 cert_list[0]->os_cert_handle(), intermediates); | |
| 640 | |
| 641 int flags = 0; | |
| 642 CertVerifyResult verify_result; | |
| 643 int error = Verify(leaf.get(), "test.example.com", flags, NULL, | |
| 644 CertificateList(), &verify_result); | |
| 645 EXPECT_THAT(error, IsOk()); | |
| 646 EXPECT_EQ(0U, verify_result.cert_status); | |
| 647 | |
| 648 error = Verify(leaf.get(), "foo.test2.example.com", flags, NULL, | |
| 649 CertificateList(), &verify_result); | |
| 650 EXPECT_THAT(error, IsOk()); | |
| 651 EXPECT_EQ(0U, verify_result.cert_status); | |
| 652 } | |
| 653 | |
| 654 TEST_P(CertVerifyProcInternalTest, NameConstraintsFailure) { | |
| 655 if (!SupportsReturningVerifiedChain()) { | |
| 656 LOG(INFO) << "Skipping this test in this platform."; | |
| 657 return; | |
| 658 } | |
| 659 | |
| 660 CertificateList ca_cert_list = | |
| 661 CreateCertificateListFromFile(GetTestCertsDirectory(), "root_ca_cert.pem", | |
| 662 X509Certificate::FORMAT_AUTO); | |
| 663 ASSERT_EQ(1U, ca_cert_list.size()); | |
| 664 ScopedTestRoot test_root(ca_cert_list[0].get()); | |
| 665 | |
| 666 CertificateList cert_list = CreateCertificateListFromFile( | |
| 667 GetTestCertsDirectory(), "name_constraint_bad.pem", | |
| 668 X509Certificate::FORMAT_AUTO); | |
| 669 ASSERT_EQ(1U, cert_list.size()); | |
| 670 | |
| 671 X509Certificate::OSCertHandles intermediates; | |
| 672 scoped_refptr<X509Certificate> leaf = X509Certificate::CreateFromHandle( | |
| 673 cert_list[0]->os_cert_handle(), intermediates); | |
| 674 | |
| 675 int flags = 0; | |
| 676 CertVerifyResult verify_result; | |
| 677 int error = Verify(leaf.get(), "test.example.com", flags, NULL, | |
| 678 CertificateList(), &verify_result); | |
| 679 EXPECT_THAT(error, IsError(ERR_CERT_NAME_CONSTRAINT_VIOLATION)); | |
| 680 EXPECT_EQ(CERT_STATUS_NAME_CONSTRAINT_VIOLATION, | |
| 681 verify_result.cert_status & CERT_STATUS_NAME_CONSTRAINT_VIOLATION); | |
| 682 } | |
| 683 | |
| 684 TEST(CertVerifyProcTest, TestHasTooLongValidity) { | |
| 685 struct { | |
| 686 const char* const file; | |
| 687 bool is_valid_too_long; | |
| 688 } tests[] = { | |
| 689 {"twitter-chain.pem", false}, | |
| 690 {"start_after_expiry.pem", true}, | |
| 691 {"pre_br_validity_ok.pem", false}, | |
| 692 {"pre_br_validity_bad_121.pem", true}, | |
| 693 {"pre_br_validity_bad_2020.pem", true}, | |
| 694 {"10_year_validity.pem", false}, | |
| 695 {"11_year_validity.pem", true}, | |
| 696 {"39_months_after_2015_04.pem", false}, | |
| 697 {"40_months_after_2015_04.pem", true}, | |
| 698 {"60_months_after_2012_07.pem", false}, | |
| 699 {"61_months_after_2012_07.pem", true}, | |
| 700 }; | |
| 701 | |
| 702 base::FilePath certs_dir = GetTestCertsDirectory(); | |
| 703 | |
| 704 for (size_t i = 0; i < arraysize(tests); ++i) { | |
| 705 scoped_refptr<X509Certificate> certificate = | |
| 706 ImportCertFromFile(certs_dir, tests[i].file); | |
| 707 SCOPED_TRACE(tests[i].file); | |
| 708 ASSERT_TRUE(certificate); | |
| 709 EXPECT_EQ(tests[i].is_valid_too_long, | |
| 710 CertVerifyProc::HasTooLongValidity(*certificate)); | |
| 711 } | |
| 712 } | |
| 713 | |
| 714 // TODO(crbug.com/610546): Fix and re-enable this test. | |
| 715 TEST_P(CertVerifyProcInternalTest, DISABLED_TestKnownRoot) { | |
| 716 if (!SupportsDetectingKnownRoots()) { | |
| 717 LOG(INFO) << "Skipping this test on this platform."; | |
| 718 return; | |
| 719 } | |
| 720 | |
| 721 base::FilePath certs_dir = GetTestCertsDirectory(); | |
| 722 CertificateList certs = CreateCertificateListFromFile( | |
| 723 certs_dir, "twitter-chain.pem", X509Certificate::FORMAT_AUTO); | |
| 724 ASSERT_EQ(3U, certs.size()); | |
| 725 | |
| 726 X509Certificate::OSCertHandles intermediates; | |
| 727 intermediates.push_back(certs[1]->os_cert_handle()); | |
| 728 | |
| 729 scoped_refptr<X509Certificate> cert_chain = X509Certificate::CreateFromHandle( | |
| 730 certs[0]->os_cert_handle(), intermediates); | |
| 731 | |
| 732 int flags = 0; | |
| 733 CertVerifyResult verify_result; | |
| 734 // This will blow up, May 9th, 2016. Sorry! Please disable and file a bug | |
| 735 // against agl. See also PublicKeyHashes. | |
| 736 int error = Verify(cert_chain.get(), "twitter.com", flags, NULL, | |
| 737 CertificateList(), &verify_result); | |
| 738 EXPECT_THAT(error, IsOk()); | |
| 739 EXPECT_TRUE(verify_result.is_issued_by_known_root); | |
| 740 } | |
| 741 | |
| 742 // TODO(crbug.com/610546): Fix and re-enable this test. | |
| 743 TEST_P(CertVerifyProcInternalTest, DISABLED_PublicKeyHashes) { | |
| 744 if (!SupportsReturningVerifiedChain()) { | |
| 745 LOG(INFO) << "Skipping this test in this platform."; | |
| 746 return; | |
| 747 } | |
| 748 | |
| 749 base::FilePath certs_dir = GetTestCertsDirectory(); | |
| 750 CertificateList certs = CreateCertificateListFromFile( | |
| 751 certs_dir, "twitter-chain.pem", X509Certificate::FORMAT_AUTO); | |
| 752 ASSERT_EQ(3U, certs.size()); | |
| 753 | |
| 754 X509Certificate::OSCertHandles intermediates; | |
| 755 intermediates.push_back(certs[1]->os_cert_handle()); | |
| 756 | |
| 757 scoped_refptr<X509Certificate> cert_chain = X509Certificate::CreateFromHandle( | |
| 758 certs[0]->os_cert_handle(), intermediates); | |
| 759 int flags = 0; | |
| 760 CertVerifyResult verify_result; | |
| 761 | |
| 762 // This will blow up, May 9th, 2016. Sorry! Please disable and file a bug | |
| 763 // against agl. See also TestKnownRoot. | |
| 764 int error = Verify(cert_chain.get(), "twitter.com", flags, NULL, | |
| 765 CertificateList(), &verify_result); | |
| 766 EXPECT_THAT(error, IsOk()); | |
| 767 ASSERT_LE(3U, verify_result.public_key_hashes.size()); | |
| 768 | |
| 769 HashValueVector sha1_hashes; | |
| 770 for (size_t i = 0; i < verify_result.public_key_hashes.size(); ++i) { | |
| 771 if (verify_result.public_key_hashes[i].tag != HASH_VALUE_SHA1) | |
| 772 continue; | |
| 773 sha1_hashes.push_back(verify_result.public_key_hashes[i]); | |
| 774 } | |
| 775 ASSERT_LE(3u, sha1_hashes.size()); | |
| 776 | |
| 777 for (size_t i = 0; i < 3; ++i) { | |
| 778 EXPECT_EQ(HexEncode(kTwitterSPKIs[i], base::kSHA1Length), | |
| 779 HexEncode(sha1_hashes[i].data(), base::kSHA1Length)); | |
| 780 } | |
| 781 | |
| 782 HashValueVector sha256_hashes; | |
| 783 for (size_t i = 0; i < verify_result.public_key_hashes.size(); ++i) { | |
| 784 if (verify_result.public_key_hashes[i].tag != HASH_VALUE_SHA256) | |
| 785 continue; | |
| 786 sha256_hashes.push_back(verify_result.public_key_hashes[i]); | |
| 787 } | |
| 788 ASSERT_LE(3u, sha256_hashes.size()); | |
| 789 | |
| 790 for (size_t i = 0; i < 3; ++i) { | |
| 791 EXPECT_EQ(HexEncode(kTwitterSPKIsSHA256[i], crypto::kSHA256Length), | |
| 792 HexEncode(sha256_hashes[i].data(), crypto::kSHA256Length)); | |
| 793 } | |
| 794 } | |
| 795 | |
| 796 // A regression test for http://crbug.com/70293. | |
| 797 // The Key Usage extension in this RSA SSL server certificate does not have | |
| 798 // the keyEncipherment bit. | |
| 799 TEST_P(CertVerifyProcInternalTest, InvalidKeyUsage) { | |
| 800 base::FilePath certs_dir = GetTestCertsDirectory(); | |
| 801 | |
| 802 scoped_refptr<X509Certificate> server_cert = | |
| 803 ImportCertFromFile(certs_dir, "invalid_key_usage_cert.der"); | |
| 804 ASSERT_NE(static_cast<X509Certificate*>(NULL), server_cert.get()); | |
| 805 | |
| 806 int flags = 0; | |
| 807 CertVerifyResult verify_result; | |
| 808 int error = Verify(server_cert.get(), "jira.aquameta.com", flags, NULL, | |
| 809 CertificateList(), &verify_result); | |
| 810 | |
| 811 // TODO(eroman): Change the test data so results are consistent across | |
| 812 // verifiers. | |
| 813 if (verify_proc_type() == CERT_VERIFY_PROC_OPENSSL) { | |
| 814 // This certificate has two errors: "invalid key usage" and "untrusted CA". | |
| 815 // However, OpenSSL returns only one (the latter), and we can't detect | |
| 816 // the other errors. | |
| 817 EXPECT_THAT(error, IsError(ERR_CERT_AUTHORITY_INVALID)); | |
| 818 } else { | |
| 819 EXPECT_THAT(error, IsError(ERR_CERT_INVALID)); | |
| 820 EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_INVALID); | |
| 821 } | |
| 822 // TODO(wtc): fix http://crbug.com/75520 to get all the certificate errors | |
| 823 // from NSS. | |
| 824 if (verify_proc_type() != CERT_VERIFY_PROC_NSS && | |
| 825 verify_proc_type() != CERT_VERIFY_PROC_IOS && | |
| 826 verify_proc_type() != CERT_VERIFY_PROC_ANDROID) { | |
| 827 // The certificate is issued by an unknown CA. | |
| 828 EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_AUTHORITY_INVALID); | |
| 829 } | |
| 830 } | |
| 831 | |
| 832 // Basic test for returning the chain in CertVerifyResult. Note that the | |
| 833 // returned chain may just be a reflection of the originally supplied chain; | |
| 834 // that is, if any errors occur, the default chain returned is an exact copy | |
| 835 // of the certificate to be verified. The remaining VerifyReturn* tests are | |
| 836 // used to ensure that the actual, verified chain is being returned by | |
| 837 // Verify(). | |
| 838 TEST_P(CertVerifyProcInternalTest, VerifyReturnChainBasic) { | |
| 839 if (!SupportsReturningVerifiedChain()) { | |
| 840 LOG(INFO) << "Skipping this test in this platform."; | |
| 841 return; | |
| 842 } | |
| 843 | |
| 844 base::FilePath certs_dir = GetTestCertsDirectory(); | |
| 845 CertificateList certs = CreateCertificateListFromFile( | |
| 846 certs_dir, "x509_verify_results.chain.pem", X509Certificate::FORMAT_AUTO); | |
| 847 ASSERT_EQ(3U, certs.size()); | |
| 848 | |
| 849 X509Certificate::OSCertHandles intermediates; | |
| 850 intermediates.push_back(certs[1]->os_cert_handle()); | |
| 851 intermediates.push_back(certs[2]->os_cert_handle()); | |
| 852 | |
| 853 ScopedTestRoot scoped_root(certs[2].get()); | |
| 854 | |
| 855 scoped_refptr<X509Certificate> google_full_chain = | |
| 856 X509Certificate::CreateFromHandle(certs[0]->os_cert_handle(), | |
| 857 intermediates); | |
| 858 ASSERT_NE(static_cast<X509Certificate*>(NULL), google_full_chain.get()); | |
| 859 ASSERT_EQ(2U, google_full_chain->GetIntermediateCertificates().size()); | |
| 860 | |
| 861 CertVerifyResult verify_result; | |
| 862 EXPECT_EQ(static_cast<X509Certificate*>(NULL), | |
| 863 verify_result.verified_cert.get()); | |
| 864 int error = Verify(google_full_chain.get(), "127.0.0.1", 0, NULL, | |
| 865 CertificateList(), &verify_result); | |
| 866 EXPECT_THAT(error, IsOk()); | |
| 867 ASSERT_NE(static_cast<X509Certificate*>(NULL), | |
| 868 verify_result.verified_cert.get()); | |
| 869 | |
| 870 EXPECT_NE(google_full_chain, verify_result.verified_cert); | |
| 871 EXPECT_TRUE(X509Certificate::IsSameOSCert( | |
| 872 google_full_chain->os_cert_handle(), | |
| 873 verify_result.verified_cert->os_cert_handle())); | |
| 874 const X509Certificate::OSCertHandles& return_intermediates = | |
| 875 verify_result.verified_cert->GetIntermediateCertificates(); | |
| 876 ASSERT_EQ(2U, return_intermediates.size()); | |
| 877 EXPECT_TRUE(X509Certificate::IsSameOSCert(return_intermediates[0], | |
| 878 certs[1]->os_cert_handle())); | |
| 879 EXPECT_TRUE(X509Certificate::IsSameOSCert(return_intermediates[1], | |
| 880 certs[2]->os_cert_handle())); | |
| 881 } | |
| 882 | |
| 883 // Test that certificates issued for 'intranet' names (that is, containing no | |
| 884 // known public registry controlled domain information) issued by well-known | |
| 885 // CAs are flagged appropriately, while certificates that are issued by | |
| 886 // internal CAs are not flagged. | |
| 887 TEST(CertVerifyProcTest, IntranetHostsRejected) { | |
| 888 CertificateList cert_list = CreateCertificateListFromFile( | |
| 889 GetTestCertsDirectory(), "reject_intranet_hosts.pem", | |
| 890 X509Certificate::FORMAT_AUTO); | |
| 891 ASSERT_EQ(1U, cert_list.size()); | |
| 892 scoped_refptr<X509Certificate> cert(cert_list[0]); | |
| 893 | |
| 894 CertVerifyResult verify_result; | |
| 895 int error = 0; | |
| 896 | |
| 897 // Intranet names for public CAs should be flagged: | |
| 898 CertVerifyResult dummy_result; | |
| 899 dummy_result.is_issued_by_known_root = true; | |
| 900 scoped_refptr<CertVerifyProc> verify_proc = | |
| 901 new MockCertVerifyProc(dummy_result); | |
| 902 error = verify_proc->Verify(cert.get(), "intranet", std::string(), 0, NULL, | |
| 903 CertificateList(), &verify_result); | |
| 904 EXPECT_THAT(error, IsOk()); | |
| 905 EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_NON_UNIQUE_NAME); | |
| 906 | |
| 907 // However, if the CA is not well known, these should not be flagged: | |
| 908 dummy_result.Reset(); | |
| 909 dummy_result.is_issued_by_known_root = false; | |
| 910 verify_proc = make_scoped_refptr(new MockCertVerifyProc(dummy_result)); | |
| 911 error = verify_proc->Verify(cert.get(), "intranet", std::string(), 0, NULL, | |
| 912 CertificateList(), &verify_result); | |
| 913 EXPECT_THAT(error, IsOk()); | |
| 914 EXPECT_FALSE(verify_result.cert_status & CERT_STATUS_NON_UNIQUE_NAME); | |
| 915 } | |
| 916 | |
| 917 // While all SHA-1 certificates should be rejected, in the event that there | |
| 918 // emerges some unexpected bug, test that the 'legacy' behaviour works | |
| 919 // correctly - rejecting all SHA-1 certificates from publicly trusted CAs | |
| 920 // that were issued after 1 January 2016, while still allowing those from | |
| 921 // before that date, with SHA-1 in the intermediate, or from an enterprise | |
| 922 // CA. | |
| 923 TEST(CertVerifyProcTest, VerifyRejectsSHA1AfterDeprecationLegacyMode) { | |
| 924 base::test::ScopedFeatureList scoped_feature_list; | |
| 925 scoped_feature_list.InitAndEnableFeature(CertVerifyProc::kSHA1LegacyMode); | |
| 926 | |
| 927 CertVerifyResult dummy_result; | |
| 928 CertVerifyResult verify_result; | |
| 929 int error = 0; | |
| 930 scoped_refptr<X509Certificate> cert; | |
| 931 | |
| 932 // Publicly trusted SHA-1 leaf certificates issued before 1 January 2016 | |
| 933 // are accepted. | |
| 934 verify_result.Reset(); | |
| 935 dummy_result.Reset(); | |
| 936 dummy_result.is_issued_by_known_root = true; | |
| 937 dummy_result.has_sha1 = true; | |
| 938 dummy_result.has_sha1_leaf = true; | |
| 939 scoped_refptr<CertVerifyProc> verify_proc = | |
| 940 new MockCertVerifyProc(dummy_result); | |
| 941 cert = CreateCertificateChainFromFile(GetTestCertsDirectory(), | |
| 942 "sha1_dec_2015.pem", | |
| 943 X509Certificate::FORMAT_AUTO); | |
| 944 ASSERT_TRUE(cert); | |
| 945 error = verify_proc->Verify(cert.get(), "127.0.0.1", std::string(), 0, NULL, | |
| 946 CertificateList(), &verify_result); | |
| 947 EXPECT_THAT(error, IsOk()); | |
| 948 EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_SHA1_SIGNATURE_PRESENT); | |
| 949 | |
| 950 // Publicly trusted SHA-1 leaf certificates issued on/after 1 January 2016 | |
| 951 // are rejected. | |
| 952 verify_result.Reset(); | |
| 953 dummy_result.Reset(); | |
| 954 dummy_result.is_issued_by_known_root = true; | |
| 955 dummy_result.has_sha1 = true; | |
| 956 dummy_result.has_sha1_leaf = true; | |
| 957 verify_proc = make_scoped_refptr(new MockCertVerifyProc(dummy_result)); | |
| 958 cert = CreateCertificateChainFromFile(GetTestCertsDirectory(), | |
| 959 "sha1_jan_2016.pem", | |
| 960 X509Certificate::FORMAT_AUTO); | |
| 961 ASSERT_TRUE(cert); | |
| 962 error = verify_proc->Verify(cert.get(), "127.0.0.1", std::string(), 0, NULL, | |
| 963 CertificateList(), &verify_result); | |
| 964 EXPECT_THAT(error, IsError(ERR_CERT_WEAK_SIGNATURE_ALGORITHM)); | |
| 965 EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_WEAK_SIGNATURE_ALGORITHM); | |
| 966 | |
| 967 // Enterprise issued SHA-1 leaf certificates issued on/after 1 January 2016 | |
| 968 // remain accepted. | |
| 969 verify_result.Reset(); | |
| 970 dummy_result.Reset(); | |
| 971 dummy_result.is_issued_by_known_root = false; | |
| 972 dummy_result.has_sha1 = true; | |
| 973 dummy_result.has_sha1_leaf = true; | |
| 974 verify_proc = make_scoped_refptr(new MockCertVerifyProc(dummy_result)); | |
| 975 cert = CreateCertificateChainFromFile(GetTestCertsDirectory(), | |
| 976 "sha1_jan_2016.pem", | |
| 977 X509Certificate::FORMAT_AUTO); | |
| 978 ASSERT_TRUE(cert); | |
| 979 error = verify_proc->Verify(cert.get(), "127.0.0.1", std::string(), 0, NULL, | |
| 980 CertificateList(), &verify_result); | |
| 981 EXPECT_THAT(error, IsOk()); | |
| 982 EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_SHA1_SIGNATURE_PRESENT); | |
| 983 | |
| 984 // Publicly trusted SHA-1 intermediates issued on/after 1 January 2016 are, | |
| 985 // unfortunately, accepted. This can arise due to OS path building quirks. | |
| 986 verify_result.Reset(); | |
| 987 dummy_result.Reset(); | |
| 988 dummy_result.is_issued_by_known_root = true; | |
| 989 dummy_result.has_sha1 = true; | |
| 990 dummy_result.has_sha1_leaf = false; | |
| 991 verify_proc = make_scoped_refptr(new MockCertVerifyProc(dummy_result)); | |
| 992 cert = CreateCertificateChainFromFile(GetTestCertsDirectory(), | |
| 993 "sha1_jan_2016.pem", | |
| 994 X509Certificate::FORMAT_AUTO); | |
| 995 ASSERT_TRUE(cert); | |
| 996 error = verify_proc->Verify(cert.get(), "127.0.0.1", std::string(), 0, NULL, | |
| 997 CertificateList(), &verify_result); | |
| 998 EXPECT_THAT(error, IsOk()); | |
| 999 EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_SHA1_SIGNATURE_PRESENT); | |
| 1000 } | |
| 1001 | |
| 1002 // Test that the certificate returned in CertVerifyResult is able to reorder | |
| 1003 // certificates that are not ordered from end-entity to root. While this is | |
| 1004 // a protocol violation if sent during a TLS handshake, if multiple sources | |
| 1005 // of intermediate certificates are combined, it's possible that order may | |
| 1006 // not be maintained. | |
| 1007 TEST_P(CertVerifyProcInternalTest, VerifyReturnChainProperlyOrdered) { | |
| 1008 if (!SupportsReturningVerifiedChain()) { | |
| 1009 LOG(INFO) << "Skipping this test in this platform."; | |
| 1010 return; | |
| 1011 } | |
| 1012 | |
| 1013 base::FilePath certs_dir = GetTestCertsDirectory(); | |
| 1014 CertificateList certs = CreateCertificateListFromFile( | |
| 1015 certs_dir, "x509_verify_results.chain.pem", X509Certificate::FORMAT_AUTO); | |
| 1016 ASSERT_EQ(3U, certs.size()); | |
| 1017 | |
| 1018 // Construct the chain out of order. | |
| 1019 X509Certificate::OSCertHandles intermediates; | |
| 1020 intermediates.push_back(certs[2]->os_cert_handle()); | |
| 1021 intermediates.push_back(certs[1]->os_cert_handle()); | |
| 1022 | |
| 1023 ScopedTestRoot scoped_root(certs[2].get()); | |
| 1024 | |
| 1025 scoped_refptr<X509Certificate> google_full_chain = | |
| 1026 X509Certificate::CreateFromHandle(certs[0]->os_cert_handle(), | |
| 1027 intermediates); | |
| 1028 ASSERT_NE(static_cast<X509Certificate*>(NULL), google_full_chain.get()); | |
| 1029 ASSERT_EQ(2U, google_full_chain->GetIntermediateCertificates().size()); | |
| 1030 | |
| 1031 CertVerifyResult verify_result; | |
| 1032 EXPECT_EQ(static_cast<X509Certificate*>(NULL), | |
| 1033 verify_result.verified_cert.get()); | |
| 1034 int error = Verify(google_full_chain.get(), "127.0.0.1", 0, NULL, | |
| 1035 CertificateList(), &verify_result); | |
| 1036 EXPECT_THAT(error, IsOk()); | |
| 1037 ASSERT_NE(static_cast<X509Certificate*>(NULL), | |
| 1038 verify_result.verified_cert.get()); | |
| 1039 | |
| 1040 EXPECT_NE(google_full_chain, verify_result.verified_cert); | |
| 1041 EXPECT_TRUE(X509Certificate::IsSameOSCert( | |
| 1042 google_full_chain->os_cert_handle(), | |
| 1043 verify_result.verified_cert->os_cert_handle())); | |
| 1044 const X509Certificate::OSCertHandles& return_intermediates = | |
| 1045 verify_result.verified_cert->GetIntermediateCertificates(); | |
| 1046 ASSERT_EQ(2U, return_intermediates.size()); | |
| 1047 EXPECT_TRUE(X509Certificate::IsSameOSCert(return_intermediates[0], | |
| 1048 certs[1]->os_cert_handle())); | |
| 1049 EXPECT_TRUE(X509Certificate::IsSameOSCert(return_intermediates[1], | |
| 1050 certs[2]->os_cert_handle())); | |
| 1051 } | |
| 1052 | |
| 1053 // Test that Verify() filters out certificates which are not related to | |
| 1054 // or part of the certificate chain being verified. | |
| 1055 TEST_P(CertVerifyProcInternalTest, VerifyReturnChainFiltersUnrelatedCerts) { | |
| 1056 if (!SupportsReturningVerifiedChain()) { | |
| 1057 LOG(INFO) << "Skipping this test in this platform."; | |
| 1058 return; | |
| 1059 } | |
| 1060 | |
| 1061 base::FilePath certs_dir = GetTestCertsDirectory(); | |
| 1062 CertificateList certs = CreateCertificateListFromFile( | |
| 1063 certs_dir, "x509_verify_results.chain.pem", X509Certificate::FORMAT_AUTO); | |
| 1064 ASSERT_EQ(3U, certs.size()); | |
| 1065 ScopedTestRoot scoped_root(certs[2].get()); | |
| 1066 | |
| 1067 scoped_refptr<X509Certificate> unrelated_certificate = | |
| 1068 ImportCertFromFile(certs_dir, "duplicate_cn_1.pem"); | |
| 1069 scoped_refptr<X509Certificate> unrelated_certificate2 = | |
| 1070 ImportCertFromFile(certs_dir, "aia-cert.pem"); | |
| 1071 ASSERT_NE(static_cast<X509Certificate*>(NULL), unrelated_certificate.get()); | |
| 1072 ASSERT_NE(static_cast<X509Certificate*>(NULL), unrelated_certificate2.get()); | |
| 1073 | |
| 1074 // Interject unrelated certificates into the list of intermediates. | |
| 1075 X509Certificate::OSCertHandles intermediates; | |
| 1076 intermediates.push_back(unrelated_certificate->os_cert_handle()); | |
| 1077 intermediates.push_back(certs[1]->os_cert_handle()); | |
| 1078 intermediates.push_back(unrelated_certificate2->os_cert_handle()); | |
| 1079 intermediates.push_back(certs[2]->os_cert_handle()); | |
| 1080 | |
| 1081 scoped_refptr<X509Certificate> google_full_chain = | |
| 1082 X509Certificate::CreateFromHandle(certs[0]->os_cert_handle(), | |
| 1083 intermediates); | |
| 1084 ASSERT_NE(static_cast<X509Certificate*>(NULL), google_full_chain.get()); | |
| 1085 ASSERT_EQ(4U, google_full_chain->GetIntermediateCertificates().size()); | |
| 1086 | |
| 1087 CertVerifyResult verify_result; | |
| 1088 EXPECT_EQ(static_cast<X509Certificate*>(NULL), | |
| 1089 verify_result.verified_cert.get()); | |
| 1090 int error = Verify(google_full_chain.get(), "127.0.0.1", 0, NULL, | |
| 1091 CertificateList(), &verify_result); | |
| 1092 EXPECT_THAT(error, IsOk()); | |
| 1093 ASSERT_NE(static_cast<X509Certificate*>(NULL), | |
| 1094 verify_result.verified_cert.get()); | |
| 1095 | |
| 1096 EXPECT_NE(google_full_chain, verify_result.verified_cert); | |
| 1097 EXPECT_TRUE(X509Certificate::IsSameOSCert( | |
| 1098 google_full_chain->os_cert_handle(), | |
| 1099 verify_result.verified_cert->os_cert_handle())); | |
| 1100 const X509Certificate::OSCertHandles& return_intermediates = | |
| 1101 verify_result.verified_cert->GetIntermediateCertificates(); | |
| 1102 ASSERT_EQ(2U, return_intermediates.size()); | |
| 1103 EXPECT_TRUE(X509Certificate::IsSameOSCert(return_intermediates[0], | |
| 1104 certs[1]->os_cert_handle())); | |
| 1105 EXPECT_TRUE(X509Certificate::IsSameOSCert(return_intermediates[1], | |
| 1106 certs[2]->os_cert_handle())); | |
| 1107 } | |
| 1108 | |
| 1109 TEST_P(CertVerifyProcInternalTest, AdditionalTrustAnchors) { | |
| 1110 if (!SupportsAdditionalTrustAnchors()) { | |
| 1111 LOG(INFO) << "Skipping this test in this platform."; | |
| 1112 return; | |
| 1113 } | |
| 1114 | |
| 1115 // |ca_cert| is the issuer of |cert|. | |
| 1116 CertificateList ca_cert_list = | |
| 1117 CreateCertificateListFromFile(GetTestCertsDirectory(), "root_ca_cert.pem", | |
| 1118 X509Certificate::FORMAT_AUTO); | |
| 1119 ASSERT_EQ(1U, ca_cert_list.size()); | |
| 1120 scoped_refptr<X509Certificate> ca_cert(ca_cert_list[0]); | |
| 1121 | |
| 1122 CertificateList cert_list = CreateCertificateListFromFile( | |
| 1123 GetTestCertsDirectory(), "ok_cert.pem", X509Certificate::FORMAT_AUTO); | |
| 1124 ASSERT_EQ(1U, cert_list.size()); | |
| 1125 scoped_refptr<X509Certificate> cert(cert_list[0]); | |
| 1126 | |
| 1127 // Verification of |cert| fails when |ca_cert| is not in the trust anchors | |
| 1128 // list. | |
| 1129 int flags = 0; | |
| 1130 CertVerifyResult verify_result; | |
| 1131 int error = Verify(cert.get(), "127.0.0.1", flags, NULL, CertificateList(), | |
| 1132 &verify_result); | |
| 1133 EXPECT_THAT(error, IsError(ERR_CERT_AUTHORITY_INVALID)); | |
| 1134 EXPECT_EQ(CERT_STATUS_AUTHORITY_INVALID, verify_result.cert_status); | |
| 1135 EXPECT_FALSE(verify_result.is_issued_by_additional_trust_anchor); | |
| 1136 | |
| 1137 // Now add the |ca_cert| to the |trust_anchors|, and verification should pass. | |
| 1138 CertificateList trust_anchors; | |
| 1139 trust_anchors.push_back(ca_cert); | |
| 1140 error = Verify(cert.get(), "127.0.0.1", flags, NULL, trust_anchors, | |
| 1141 &verify_result); | |
| 1142 EXPECT_THAT(error, IsOk()); | |
| 1143 EXPECT_EQ(0U, verify_result.cert_status); | |
| 1144 EXPECT_TRUE(verify_result.is_issued_by_additional_trust_anchor); | |
| 1145 | |
| 1146 // Clearing the |trust_anchors| makes verification fail again (the cache | |
| 1147 // should be skipped). | |
| 1148 error = Verify(cert.get(), "127.0.0.1", flags, NULL, CertificateList(), | |
| 1149 &verify_result); | |
| 1150 EXPECT_THAT(error, IsError(ERR_CERT_AUTHORITY_INVALID)); | |
| 1151 EXPECT_EQ(CERT_STATUS_AUTHORITY_INVALID, verify_result.cert_status); | |
| 1152 EXPECT_FALSE(verify_result.is_issued_by_additional_trust_anchor); | |
| 1153 } | |
| 1154 | |
| 1155 // Tests that certificates issued by user-supplied roots are not flagged as | |
| 1156 // issued by a known root. This should pass whether or not the platform supports | |
| 1157 // detecting known roots. | |
| 1158 TEST_P(CertVerifyProcInternalTest, IsIssuedByKnownRootIgnoresTestRoots) { | |
| 1159 // Load root_ca_cert.pem into the test root store. | |
| 1160 ScopedTestRoot test_root( | |
| 1161 ImportCertFromFile(GetTestCertsDirectory(), "root_ca_cert.pem").get()); | |
| 1162 | |
| 1163 scoped_refptr<X509Certificate> cert( | |
| 1164 ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem")); | |
| 1165 | |
| 1166 // Verification should pass. | |
| 1167 int flags = 0; | |
| 1168 CertVerifyResult verify_result; | |
| 1169 int error = Verify(cert.get(), "127.0.0.1", flags, NULL, CertificateList(), | |
| 1170 &verify_result); | |
| 1171 EXPECT_THAT(error, IsOk()); | |
| 1172 EXPECT_EQ(0U, verify_result.cert_status); | |
| 1173 // But should not be marked as a known root. | |
| 1174 EXPECT_FALSE(verify_result.is_issued_by_known_root); | |
| 1175 } | |
| 1176 | |
| 1177 // Test that CRLSets are effective in making a certificate appear to be | |
| 1178 // revoked. | |
| 1179 TEST_P(CertVerifyProcInternalTest, CRLSet) { | |
| 1180 if (!SupportsCRLSet()) { | |
| 1181 LOG(INFO) << "Skipping test as verifier doesn't support CRLSet"; | |
| 1182 return; | |
| 1183 } | |
| 1184 | |
| 1185 CertificateList ca_cert_list = | |
| 1186 CreateCertificateListFromFile(GetTestCertsDirectory(), "root_ca_cert.pem", | |
| 1187 X509Certificate::FORMAT_AUTO); | |
| 1188 ASSERT_EQ(1U, ca_cert_list.size()); | |
| 1189 ScopedTestRoot test_root(ca_cert_list[0].get()); | |
| 1190 | |
| 1191 CertificateList cert_list = CreateCertificateListFromFile( | |
| 1192 GetTestCertsDirectory(), "ok_cert.pem", X509Certificate::FORMAT_AUTO); | |
| 1193 ASSERT_EQ(1U, cert_list.size()); | |
| 1194 scoped_refptr<X509Certificate> cert(cert_list[0]); | |
| 1195 | |
| 1196 int flags = 0; | |
| 1197 CertVerifyResult verify_result; | |
| 1198 int error = Verify(cert.get(), "127.0.0.1", flags, NULL, CertificateList(), | |
| 1199 &verify_result); | |
| 1200 EXPECT_THAT(error, IsOk()); | |
| 1201 EXPECT_EQ(0U, verify_result.cert_status); | |
| 1202 | |
| 1203 scoped_refptr<CRLSet> crl_set; | |
| 1204 std::string crl_set_bytes; | |
| 1205 | |
| 1206 // First test blocking by SPKI. | |
| 1207 EXPECT_TRUE(base::ReadFileToString( | |
| 1208 GetTestCertsDirectory().AppendASCII("crlset_by_leaf_spki.raw"), | |
| 1209 &crl_set_bytes)); | |
| 1210 ASSERT_TRUE(CRLSetStorage::Parse(crl_set_bytes, &crl_set)); | |
| 1211 | |
| 1212 error = Verify(cert.get(), "127.0.0.1", flags, crl_set.get(), | |
| 1213 CertificateList(), &verify_result); | |
| 1214 EXPECT_THAT(error, IsError(ERR_CERT_REVOKED)); | |
| 1215 | |
| 1216 // Second, test revocation by serial number of a cert directly under the | |
| 1217 // root. | |
| 1218 crl_set_bytes.clear(); | |
| 1219 EXPECT_TRUE(base::ReadFileToString( | |
| 1220 GetTestCertsDirectory().AppendASCII("crlset_by_root_serial.raw"), | |
| 1221 &crl_set_bytes)); | |
| 1222 ASSERT_TRUE(CRLSetStorage::Parse(crl_set_bytes, &crl_set)); | |
| 1223 | |
| 1224 error = Verify(cert.get(), "127.0.0.1", flags, crl_set.get(), | |
| 1225 CertificateList(), &verify_result); | |
| 1226 EXPECT_THAT(error, IsError(ERR_CERT_REVOKED)); | |
| 1227 } | |
| 1228 | |
| 1229 TEST_P(CertVerifyProcInternalTest, CRLSetLeafSerial) { | |
| 1230 if (!SupportsCRLSet()) { | |
| 1231 LOG(INFO) << "Skipping test as verifier doesn't support CRLSet"; | |
| 1232 return; | |
| 1233 } | |
| 1234 | |
| 1235 CertificateList ca_cert_list = | |
| 1236 CreateCertificateListFromFile(GetTestCertsDirectory(), "root_ca_cert.pem", | |
| 1237 X509Certificate::FORMAT_AUTO); | |
| 1238 ASSERT_EQ(1U, ca_cert_list.size()); | |
| 1239 ScopedTestRoot test_root(ca_cert_list[0].get()); | |
| 1240 | |
| 1241 CertificateList intermediate_cert_list = CreateCertificateListFromFile( | |
| 1242 GetTestCertsDirectory(), "intermediate_ca_cert.pem", | |
| 1243 X509Certificate::FORMAT_AUTO); | |
| 1244 ASSERT_EQ(1U, intermediate_cert_list.size()); | |
| 1245 X509Certificate::OSCertHandles intermediates; | |
| 1246 intermediates.push_back(intermediate_cert_list[0]->os_cert_handle()); | |
| 1247 | |
| 1248 CertificateList cert_list = CreateCertificateListFromFile( | |
| 1249 GetTestCertsDirectory(), "ok_cert_by_intermediate.pem", | |
| 1250 X509Certificate::FORMAT_AUTO); | |
| 1251 ASSERT_EQ(1U, cert_list.size()); | |
| 1252 | |
| 1253 scoped_refptr<X509Certificate> leaf = X509Certificate::CreateFromHandle( | |
| 1254 cert_list[0]->os_cert_handle(), intermediates); | |
| 1255 ASSERT_TRUE(leaf); | |
| 1256 | |
| 1257 int flags = 0; | |
| 1258 CertVerifyResult verify_result; | |
| 1259 int error = Verify(leaf.get(), "127.0.0.1", flags, NULL, CertificateList(), | |
| 1260 &verify_result); | |
| 1261 EXPECT_THAT(error, IsOk()); | |
| 1262 | |
| 1263 // Test revocation by serial number of a certificate not under the root. | |
| 1264 scoped_refptr<CRLSet> crl_set; | |
| 1265 std::string crl_set_bytes; | |
| 1266 ASSERT_TRUE(base::ReadFileToString( | |
| 1267 GetTestCertsDirectory().AppendASCII("crlset_by_intermediate_serial.raw"), | |
| 1268 &crl_set_bytes)); | |
| 1269 ASSERT_TRUE(CRLSetStorage::Parse(crl_set_bytes, &crl_set)); | |
| 1270 | |
| 1271 error = Verify(leaf.get(), "127.0.0.1", flags, crl_set.get(), | |
| 1272 CertificateList(), &verify_result); | |
| 1273 EXPECT_THAT(error, IsError(ERR_CERT_REVOKED)); | |
| 1274 } | |
| 1275 | |
| 1276 // Tests that CRLSets participate in path building functions, and that as | |
| 1277 // long as a valid path exists within the verification graph, verification | |
| 1278 // succeeds. | |
| 1279 // | |
| 1280 // In this test, there are two roots (D and E), and three possible paths | |
| 1281 // to validate a leaf (A): | |
| 1282 // 1. A(B) -> B(C) -> C(D) -> D(D) | |
| 1283 // 2. A(B) -> B(C) -> C(E) -> E(E) | |
| 1284 // 3. A(B) -> B(F) -> F(E) -> E(E) | |
| 1285 // | |
| 1286 // Each permutation of revocation is tried: | |
| 1287 // 1. Revoking E by SPKI, so that only Path 1 is valid (as E is in Paths 2 & 3) | |
| 1288 // 2. Revoking C(D) and F(E) by serial, so that only Path 2 is valid. | |
| 1289 // 3. Revoking C by SPKI, so that only Path 3 is valid (as C is in Paths 1 & 2) | |
| 1290 TEST_P(CertVerifyProcInternalTest, CRLSetDuringPathBuilding) { | |
| 1291 if (!SupportsCRLSetsInPathBuilding()) { | |
| 1292 LOG(INFO) << "Skipping this test on this platform."; | |
| 1293 return; | |
| 1294 } | |
| 1295 | |
| 1296 const char* const kPath1Files[] = { | |
| 1297 "multi-root-A-by-B.pem", "multi-root-B-by-C.pem", "multi-root-C-by-D.pem", | |
| 1298 "multi-root-D-by-D.pem"}; | |
| 1299 const char* const kPath2Files[] = { | |
| 1300 "multi-root-A-by-B.pem", "multi-root-B-by-C.pem", "multi-root-C-by-E.pem", | |
| 1301 "multi-root-E-by-E.pem"}; | |
| 1302 const char* const kPath3Files[] = { | |
| 1303 "multi-root-A-by-B.pem", "multi-root-B-by-F.pem", "multi-root-F-by-E.pem", | |
| 1304 "multi-root-E-by-E.pem"}; | |
| 1305 | |
| 1306 CertificateList path_1_certs; | |
| 1307 ASSERT_NO_FATAL_FAILURE(LoadCertificateFiles(kPath1Files, &path_1_certs)); | |
| 1308 | |
| 1309 CertificateList path_2_certs; | |
| 1310 ASSERT_NO_FATAL_FAILURE(LoadCertificateFiles(kPath2Files, &path_2_certs)); | |
| 1311 | |
| 1312 CertificateList path_3_certs; | |
| 1313 ASSERT_NO_FATAL_FAILURE(LoadCertificateFiles(kPath3Files, &path_3_certs)); | |
| 1314 | |
| 1315 // Add D and E as trust anchors. | |
| 1316 ScopedTestRoot test_root_D(path_1_certs[3].get()); // D-by-D | |
| 1317 ScopedTestRoot test_root_E(path_2_certs[3].get()); // E-by-E | |
| 1318 | |
| 1319 // Create a chain that contains all the certificate paths possible. | |
| 1320 // CertVerifyProcInternalTest.VerifyReturnChainFiltersUnrelatedCerts already | |
| 1321 // ensures that it's safe to send additional certificates as inputs, and | |
| 1322 // that they're ignored if not necessary. | |
| 1323 // This is to avoid relying on AIA or internal object caches when | |
| 1324 // interacting with the underlying library. | |
| 1325 X509Certificate::OSCertHandles intermediates; | |
| 1326 intermediates.push_back(path_1_certs[1]->os_cert_handle()); // B-by-C | |
| 1327 intermediates.push_back(path_1_certs[2]->os_cert_handle()); // C-by-D | |
| 1328 intermediates.push_back(path_2_certs[2]->os_cert_handle()); // C-by-E | |
| 1329 intermediates.push_back(path_3_certs[1]->os_cert_handle()); // B-by-F | |
| 1330 intermediates.push_back(path_3_certs[2]->os_cert_handle()); // F-by-E | |
| 1331 scoped_refptr<X509Certificate> cert = X509Certificate::CreateFromHandle( | |
| 1332 path_1_certs[0]->os_cert_handle(), intermediates); | |
| 1333 ASSERT_TRUE(cert); | |
| 1334 | |
| 1335 struct TestPermutations { | |
| 1336 const char* crlset; | |
| 1337 bool expect_valid; | |
| 1338 scoped_refptr<X509Certificate> expected_intermediate; | |
| 1339 } kTests[] = { | |
| 1340 {"multi-root-crlset-D-and-E.raw", false, nullptr}, | |
| 1341 {"multi-root-crlset-E.raw", true, path_1_certs[2].get()}, | |
| 1342 {"multi-root-crlset-CD-and-FE.raw", true, path_2_certs[2].get()}, | |
| 1343 {"multi-root-crlset-C.raw", true, path_3_certs[2].get()}, | |
| 1344 {"multi-root-crlset-unrelated.raw", true, nullptr}}; | |
| 1345 | |
| 1346 for (const auto& testcase : kTests) { | |
| 1347 SCOPED_TRACE(testcase.crlset); | |
| 1348 scoped_refptr<CRLSet> crl_set; | |
| 1349 std::string crl_set_bytes; | |
| 1350 EXPECT_TRUE(base::ReadFileToString( | |
| 1351 GetTestCertsDirectory().AppendASCII(testcase.crlset), &crl_set_bytes)); | |
| 1352 ASSERT_TRUE(CRLSetStorage::Parse(crl_set_bytes, &crl_set)); | |
| 1353 | |
| 1354 int flags = 0; | |
| 1355 CertVerifyResult verify_result; | |
| 1356 int error = Verify(cert.get(), "127.0.0.1", flags, crl_set.get(), | |
| 1357 CertificateList(), &verify_result); | |
| 1358 | |
| 1359 if (!testcase.expect_valid) { | |
| 1360 EXPECT_NE(OK, error); | |
| 1361 EXPECT_NE(0U, verify_result.cert_status); | |
| 1362 continue; | |
| 1363 } | |
| 1364 | |
| 1365 ASSERT_THAT(error, IsOk()); | |
| 1366 ASSERT_EQ(0U, verify_result.cert_status); | |
| 1367 ASSERT_TRUE(verify_result.verified_cert.get()); | |
| 1368 | |
| 1369 if (!testcase.expected_intermediate) | |
| 1370 continue; | |
| 1371 | |
| 1372 const X509Certificate::OSCertHandles& verified_intermediates = | |
| 1373 verify_result.verified_cert->GetIntermediateCertificates(); | |
| 1374 ASSERT_EQ(3U, verified_intermediates.size()); | |
| 1375 | |
| 1376 scoped_refptr<X509Certificate> intermediate = | |
| 1377 X509Certificate::CreateFromHandle(verified_intermediates[1], | |
| 1378 X509Certificate::OSCertHandles()); | |
| 1379 ASSERT_TRUE(intermediate); | |
| 1380 | |
| 1381 EXPECT_TRUE(testcase.expected_intermediate->Equals(intermediate.get())) | |
| 1382 << "Expected: " << testcase.expected_intermediate->subject().common_name | |
| 1383 << " issued by " << testcase.expected_intermediate->issuer().common_name | |
| 1384 << "; Got: " << intermediate->subject().common_name << " issued by " | |
| 1385 << intermediate->issuer().common_name; | |
| 1386 } | |
| 1387 } | |
| 1388 | |
| 1389 #if defined(OS_MACOSX) && !defined(OS_IOS) | |
| 1390 // Test that a CRLSet blocking one of the intermediates supplied by the server | 33 // Test that a CRLSet blocking one of the intermediates supplied by the server |
| 1391 // can be worked around by the chopping workaround for path building. (Once the | 34 // can be worked around by the chopping workaround for path building. (Once the |
| 1392 // supplied chain is chopped back to just the target, a better path can be | 35 // supplied chain is chopped back to just the target, a better path can be |
| 1393 // found out-of-band. Normally that would be by AIA fetching, for the purposes | 36 // found out-of-band. Normally that would be by AIA fetching, for the purposes |
| 1394 // of this test the better path is supplied by a test keychain.) | 37 // of this test the better path is supplied by a test keychain.) |
| 1395 // | 38 // |
| 1396 // In this test, there are two possible paths to validate a leaf (A): | 39 // In this test, there are two possible paths to validate a leaf (A): |
| 1397 // 1. A(B) -> B(C) -> C(E) -> E(E) | 40 // 1. A(B) -> B(C) -> C(E) -> E(E) |
| 1398 // 2. A(B) -> B(F) -> F(E) -> E(E) | 41 // 2. A(B) -> B(F) -> F(E) -> E(E) |
| 1399 // | 42 // |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1453 std::string crl_set_bytes; | 96 std::string crl_set_bytes; |
| 1454 // CRL which blocks C by SPKI. | 97 // CRL which blocks C by SPKI. |
| 1455 EXPECT_TRUE(base::ReadFileToString( | 98 EXPECT_TRUE(base::ReadFileToString( |
| 1456 GetTestCertsDirectory().AppendASCII("multi-root-crlset-C.raw"), | 99 GetTestCertsDirectory().AppendASCII("multi-root-crlset-C.raw"), |
| 1457 &crl_set_bytes)); | 100 &crl_set_bytes)); |
| 1458 ASSERT_TRUE(CRLSetStorage::Parse(crl_set_bytes, &crl_set)); | 101 ASSERT_TRUE(CRLSetStorage::Parse(crl_set_bytes, &crl_set)); |
| 1459 | 102 |
| 1460 int flags = 0; | 103 int flags = 0; |
| 1461 CertVerifyResult verify_result; | 104 CertVerifyResult verify_result; |
| 1462 | 105 |
| 1463 scoped_refptr<CertVerifyProc> verify_proc = CertVerifyProc::CreateDefault(); | 106 scoped_refptr<CertVerifyProc> verify_proc = new CertVerifyProcMac; |
| 1464 int error = | 107 int error = |
| 1465 verify_proc->Verify(cert.get(), "127.0.0.1", std::string(), flags, | 108 verify_proc->Verify(cert.get(), "127.0.0.1", std::string(), flags, |
| 1466 crl_set.get(), CertificateList(), &verify_result); | 109 crl_set.get(), CertificateList(), &verify_result); |
| 1467 | 110 |
| 1468 ASSERT_EQ(OK, error); | 111 ASSERT_EQ(OK, error); |
| 1469 ASSERT_EQ(0U, verify_result.cert_status); | 112 ASSERT_EQ(0U, verify_result.cert_status); |
| 1470 ASSERT_TRUE(verify_result.verified_cert.get()); | 113 ASSERT_TRUE(verify_result.verified_cert.get()); |
| 1471 | 114 |
| 1472 const X509Certificate::OSCertHandles& verified_intermediates = | 115 const X509Certificate::OSCertHandles& verified_intermediates = |
| 1473 verify_result.verified_cert->GetIntermediateCertificates(); | 116 verify_result.verified_cert->GetIntermediateCertificates(); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1510 SecKeychainRef keychain; | 153 SecKeychainRef keychain; |
| 1511 OSStatus status = | 154 OSStatus status = |
| 1512 SecKeychainOpen(keychain_path.MaybeAsASCII().c_str(), &keychain); | 155 SecKeychainOpen(keychain_path.MaybeAsASCII().c_str(), &keychain); |
| 1513 ASSERT_EQ(errSecSuccess, status); | 156 ASSERT_EQ(errSecSuccess, status); |
| 1514 ASSERT_TRUE(keychain); | 157 ASSERT_TRUE(keychain); |
| 1515 base::ScopedCFTypeRef<SecKeychainRef> scoped_keychain(keychain); | 158 base::ScopedCFTypeRef<SecKeychainRef> scoped_keychain(keychain); |
| 1516 test_keychain_search_list->AddKeychain(keychain); | 159 test_keychain_search_list->AddKeychain(keychain); |
| 1517 | 160 |
| 1518 int flags = 0; | 161 int flags = 0; |
| 1519 CertVerifyResult verify_result; | 162 CertVerifyResult verify_result; |
| 1520 scoped_refptr<CertVerifyProc> verify_proc = CertVerifyProc::CreateDefault(); | 163 scoped_refptr<CertVerifyProc> verify_proc = new CertVerifyProcMac; |
| 1521 int error = verify_proc->Verify(cert.get(), "www.tripadvisor.com", | 164 int error = verify_proc->Verify(cert.get(), "www.tripadvisor.com", |
| 1522 std::string(), flags, nullptr /* crl_set */, | 165 std::string(), flags, nullptr /* crl_set */, |
| 1523 CertificateList(), &verify_result); | 166 CertificateList(), &verify_result); |
| 1524 | 167 |
| 1525 ASSERT_EQ(OK, error); | 168 ASSERT_EQ(OK, error); |
| 1526 EXPECT_EQ(0U, verify_result.cert_status); | 169 EXPECT_EQ(0U, verify_result.cert_status); |
| 1527 EXPECT_FALSE(verify_result.has_sha1); | 170 EXPECT_FALSE(verify_result.has_sha1); |
| 1528 ASSERT_TRUE(verify_result.verified_cert.get()); | 171 ASSERT_TRUE(verify_result.verified_cert.get()); |
| 1529 | 172 |
| 1530 const X509Certificate::OSCertHandles& verified_intermediates = | 173 const X509Certificate::OSCertHandles& verified_intermediates = |
| 1531 verify_result.verified_cert->GetIntermediateCertificates(); | 174 verify_result.verified_cert->GetIntermediateCertificates(); |
| 1532 ASSERT_EQ(2U, verified_intermediates.size()); | 175 ASSERT_EQ(2U, verified_intermediates.size()); |
| 1533 } | 176 } |
| 1534 | 177 |
| 1535 // Test that the system root certificate keychain is in the expected location | 178 // Test that the system root certificate keychain is in the expected location |
| 1536 // and can be opened. Other tests would fail if this was not true, but this | 179 // and can be opened. Other tests would fail if this was not true, but this |
| 1537 // test makes the reason for the failure obvious. | 180 // test makes the reason for the failure obvious. |
| 1538 TEST(CertVerifyProcMacTest, MacSystemRootCertificateKeychainLocation) { | 181 TEST(CertVerifyProcMacTest, MacSystemRootCertificateKeychainLocation) { |
| 1539 const char* root_keychain_path = | 182 const char* root_keychain_path = |
| 1540 "/System/Library/Keychains/SystemRootCertificates.keychain"; | 183 "/System/Library/Keychains/SystemRootCertificates.keychain"; |
| 1541 ASSERT_TRUE(base::PathExists(base::FilePath(root_keychain_path))); | 184 ASSERT_TRUE(base::PathExists(base::FilePath(root_keychain_path))); |
| 1542 | 185 |
| 1543 SecKeychainRef keychain; | 186 SecKeychainRef keychain; |
| 1544 OSStatus status = SecKeychainOpen(root_keychain_path, &keychain); | 187 OSStatus status = SecKeychainOpen(root_keychain_path, &keychain); |
| 1545 ASSERT_EQ(errSecSuccess, status); | 188 ASSERT_EQ(errSecSuccess, status); |
| 1546 CFRelease(keychain); | 189 CFRelease(keychain); |
| 1547 } | 190 } |
| 1548 #endif // defined(OS_MACOSX) && !defined(OS_IOS) | |
| 1549 | 191 |
| 1550 // TODO(crbug.com/649017): This is not parameterized by the CertVerifyProc | |
| 1551 // because the CertVerifyProc::Verify() does this unconditionally based on the | |
| 1552 // platform. | |
| 1553 bool AreSHA1IntermediatesAllowed() { | |
| 1554 #if defined(OS_WIN) | |
| 1555 // TODO(rsleevi): Remove this once https://crbug.com/588789 is resolved | |
| 1556 // for Windows 7/2008 users. | |
| 1557 // Note: This must be kept in sync with cert_verify_proc.cc | |
| 1558 return base::win::GetVersion() < base::win::VERSION_WIN8; | |
| 1559 #else | |
| 1560 return false; | |
| 1561 #endif | |
| 1562 } | |
| 1563 | |
| 1564 TEST(CertVerifyProcTest, RejectsMD2) { | |
| 1565 scoped_refptr<X509Certificate> cert( | |
| 1566 ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem")); | |
| 1567 ASSERT_TRUE(cert); | |
| 1568 | |
| 1569 CertVerifyResult result; | |
| 1570 result.has_md2 = true; | |
| 1571 scoped_refptr<CertVerifyProc> verify_proc = new MockCertVerifyProc(result); | |
| 1572 | |
| 1573 int flags = 0; | |
| 1574 CertVerifyResult verify_result; | |
| 1575 int error = verify_proc->Verify(cert.get(), "127.0.0.1", std::string(), flags, | |
| 1576 nullptr /* crl_set */, CertificateList(), | |
| 1577 &verify_result); | |
| 1578 EXPECT_THAT(error, IsError(ERR_CERT_INVALID)); | |
| 1579 EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_INVALID); | |
| 1580 } | |
| 1581 | |
| 1582 TEST(CertVerifyProcTest, RejectsMD4) { | |
| 1583 scoped_refptr<X509Certificate> cert( | |
| 1584 ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem")); | |
| 1585 ASSERT_TRUE(cert); | |
| 1586 | |
| 1587 CertVerifyResult result; | |
| 1588 result.has_md4 = true; | |
| 1589 scoped_refptr<CertVerifyProc> verify_proc = new MockCertVerifyProc(result); | |
| 1590 | |
| 1591 int flags = 0; | |
| 1592 CertVerifyResult verify_result; | |
| 1593 int error = verify_proc->Verify(cert.get(), "127.0.0.1", std::string(), flags, | |
| 1594 nullptr /* crl_set */, CertificateList(), | |
| 1595 &verify_result); | |
| 1596 EXPECT_THAT(error, IsError(ERR_CERT_INVALID)); | |
| 1597 EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_INVALID); | |
| 1598 } | |
| 1599 | |
| 1600 TEST(CertVerifyProcTest, RejectsMD5) { | |
| 1601 scoped_refptr<X509Certificate> cert( | |
| 1602 ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem")); | |
| 1603 ASSERT_TRUE(cert); | |
| 1604 | |
| 1605 CertVerifyResult result; | |
| 1606 result.has_md5 = true; | |
| 1607 scoped_refptr<CertVerifyProc> verify_proc = new MockCertVerifyProc(result); | |
| 1608 | |
| 1609 int flags = 0; | |
| 1610 CertVerifyResult verify_result; | |
| 1611 int error = verify_proc->Verify(cert.get(), "127.0.0.1", std::string(), flags, | |
| 1612 nullptr /* crl_set */, CertificateList(), | |
| 1613 &verify_result); | |
| 1614 EXPECT_THAT(error, IsError(ERR_CERT_WEAK_SIGNATURE_ALGORITHM)); | |
| 1615 EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_WEAK_SIGNATURE_ALGORITHM); | |
| 1616 } | |
| 1617 | |
| 1618 TEST(CertVerifyProcTest, RejectsPublicSHA1Leaves) { | |
| 1619 scoped_refptr<X509Certificate> cert( | |
| 1620 ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem")); | |
| 1621 ASSERT_TRUE(cert); | |
| 1622 | |
| 1623 CertVerifyResult result; | |
| 1624 result.has_sha1 = true; | |
| 1625 result.has_sha1_leaf = true; | |
| 1626 result.is_issued_by_known_root = true; | |
| 1627 scoped_refptr<CertVerifyProc> verify_proc = new MockCertVerifyProc(result); | |
| 1628 | |
| 1629 int flags = 0; | |
| 1630 CertVerifyResult verify_result; | |
| 1631 int error = verify_proc->Verify(cert.get(), "127.0.0.1", std::string(), flags, | |
| 1632 nullptr /* crl_set */, CertificateList(), | |
| 1633 &verify_result); | |
| 1634 EXPECT_THAT(error, IsError(ERR_CERT_WEAK_SIGNATURE_ALGORITHM)); | |
| 1635 EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_WEAK_SIGNATURE_ALGORITHM); | |
| 1636 } | |
| 1637 | |
| 1638 TEST(CertVerifyProcTest, RejectsPublicSHA1IntermediatesUnlessAllowed) { | |
| 1639 scoped_refptr<X509Certificate> cert(ImportCertFromFile( | |
| 1640 GetTestCertsDirectory(), "39_months_after_2015_04.pem")); | |
| 1641 ASSERT_TRUE(cert); | |
| 1642 | |
| 1643 CertVerifyResult result; | |
| 1644 result.has_sha1 = true; | |
| 1645 result.has_sha1_leaf = false; | |
| 1646 result.is_issued_by_known_root = true; | |
| 1647 scoped_refptr<CertVerifyProc> verify_proc = new MockCertVerifyProc(result); | |
| 1648 | |
| 1649 int flags = 0; | |
| 1650 CertVerifyResult verify_result; | |
| 1651 int error = verify_proc->Verify(cert.get(), "127.0.0.1", std::string(), flags, | |
| 1652 nullptr /* crl_set */, CertificateList(), | |
| 1653 &verify_result); | |
| 1654 if (AreSHA1IntermediatesAllowed()) { | |
| 1655 EXPECT_THAT(error, IsOk()); | |
| 1656 EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_SHA1_SIGNATURE_PRESENT); | |
| 1657 } else { | |
| 1658 EXPECT_THAT(error, IsError(ERR_CERT_WEAK_SIGNATURE_ALGORITHM)); | |
| 1659 EXPECT_TRUE(verify_result.cert_status & | |
| 1660 CERT_STATUS_WEAK_SIGNATURE_ALGORITHM); | |
| 1661 } | |
| 1662 } | |
| 1663 | |
| 1664 TEST(CertVerifyProcTest, RejectsPrivateSHA1UnlessFlag) { | |
| 1665 scoped_refptr<X509Certificate> cert( | |
| 1666 ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem")); | |
| 1667 ASSERT_TRUE(cert); | |
| 1668 | |
| 1669 CertVerifyResult result; | |
| 1670 result.has_sha1 = true; | |
| 1671 result.has_sha1_leaf = true; | |
| 1672 result.is_issued_by_known_root = false; | |
| 1673 scoped_refptr<CertVerifyProc> verify_proc = new MockCertVerifyProc(result); | |
| 1674 | |
| 1675 // SHA-1 should be rejected by default for private roots... | |
| 1676 int flags = 0; | |
| 1677 CertVerifyResult verify_result; | |
| 1678 int error = verify_proc->Verify(cert.get(), "127.0.0.1", std::string(), flags, | |
| 1679 nullptr /* crl_set */, CertificateList(), | |
| 1680 &verify_result); | |
| 1681 EXPECT_THAT(error, IsError(ERR_CERT_WEAK_SIGNATURE_ALGORITHM)); | |
| 1682 EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_SHA1_SIGNATURE_PRESENT); | |
| 1683 | |
| 1684 // ... unless VERIFY_ENABLE_SHA1_LOCAL_ANCHORS was supplied. | |
| 1685 flags = CertVerifier::VERIFY_ENABLE_SHA1_LOCAL_ANCHORS; | |
| 1686 verify_result.Reset(); | |
| 1687 error = verify_proc->Verify(cert.get(), "127.0.0.1", std::string(), flags, | |
| 1688 nullptr /* crl_set */, CertificateList(), | |
| 1689 &verify_result); | |
| 1690 EXPECT_THAT(error, IsOk()); | |
| 1691 EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_SHA1_SIGNATURE_PRESENT); | |
| 1692 } | |
| 1693 | |
| 1694 enum ExpectedAlgorithms { | |
| 1695 EXPECT_MD2 = 1 << 0, | |
| 1696 EXPECT_MD4 = 1 << 1, | |
| 1697 EXPECT_MD5 = 1 << 2, | |
| 1698 EXPECT_SHA1 = 1 << 3, | |
| 1699 EXPECT_SHA1_LEAF = 1 << 4, | |
| 1700 }; | |
| 1701 | |
| 1702 struct WeakDigestTestData { | |
| 1703 const char* root_cert_filename; | |
| 1704 const char* intermediate_cert_filename; | |
| 1705 const char* ee_cert_filename; | |
| 1706 int expected_algorithms; | |
| 1707 }; | |
| 1708 | |
| 1709 const char* StringOrDefault(const char* str, const char* default_value) { | |
| 1710 if (!str) | |
| 1711 return default_value; | |
| 1712 return str; | |
| 1713 } | |
| 1714 | |
| 1715 // GTest 'magic' pretty-printer, so that if/when a test fails, it knows how | |
| 1716 // to output the parameter that was passed. Without this, it will simply | |
| 1717 // attempt to print out the first twenty bytes of the object, which depending | |
| 1718 // on platform and alignment, may result in an invalid read. | |
| 1719 void PrintTo(const WeakDigestTestData& data, std::ostream* os) { | |
| 1720 *os << "root: " << StringOrDefault(data.root_cert_filename, "none") | |
| 1721 << "; intermediate: " | |
| 1722 << StringOrDefault(data.intermediate_cert_filename, "none") | |
| 1723 << "; end-entity: " << data.ee_cert_filename; | |
| 1724 } | |
| 1725 | |
| 1726 class CertVerifyProcWeakDigestTest | |
| 1727 : public testing::TestWithParam<WeakDigestTestData> { | |
| 1728 public: | |
| 1729 CertVerifyProcWeakDigestTest() {} | |
| 1730 virtual ~CertVerifyProcWeakDigestTest() {} | |
| 1731 }; | |
| 1732 | |
| 1733 // Tests that the CertVerifyProc::Verify() properly surfaces the (weak) hash | |
| 1734 // algorithms used in the chain. | |
| 1735 TEST_P(CertVerifyProcWeakDigestTest, VerifyDetectsAlgorithm) { | |
| 1736 WeakDigestTestData data = GetParam(); | |
| 1737 base::FilePath certs_dir = GetTestCertsDirectory(); | |
| 1738 | |
| 1739 scoped_refptr<X509Certificate> intermediate_cert; | |
| 1740 scoped_refptr<X509Certificate> root_cert; | |
| 1741 | |
| 1742 // Build |intermediates| as the full chain (including trust anchor). | |
| 1743 X509Certificate::OSCertHandles intermediates; | |
| 1744 | |
| 1745 if (data.intermediate_cert_filename) { | |
| 1746 intermediate_cert = | |
| 1747 ImportCertFromFile(certs_dir, data.intermediate_cert_filename); | |
| 1748 ASSERT_TRUE(intermediate_cert); | |
| 1749 intermediates.push_back(intermediate_cert->os_cert_handle()); | |
| 1750 } | |
| 1751 | |
| 1752 if (data.root_cert_filename) { | |
| 1753 root_cert = ImportCertFromFile(certs_dir, data.root_cert_filename); | |
| 1754 ASSERT_TRUE(root_cert); | |
| 1755 intermediates.push_back(root_cert->os_cert_handle()); | |
| 1756 } | |
| 1757 | |
| 1758 scoped_refptr<X509Certificate> ee_cert = | |
| 1759 ImportCertFromFile(certs_dir, data.ee_cert_filename); | |
| 1760 ASSERT_TRUE(ee_cert); | |
| 1761 | |
| 1762 scoped_refptr<X509Certificate> ee_chain = X509Certificate::CreateFromHandle( | |
| 1763 ee_cert->os_cert_handle(), intermediates); | |
| 1764 ASSERT_TRUE(ee_chain); | |
| 1765 | |
| 1766 int flags = 0; | |
| 1767 CertVerifyResult verify_result; | |
| 1768 | |
| 1769 // Use a mock CertVerifyProc that returns success with a verified_cert of | |
| 1770 // |ee_chain|. | |
| 1771 // | |
| 1772 // This is sufficient for the purposes of this test, as the checking for weak | |
| 1773 // hash algorithms is done by CertVerifyProc::Verify(). | |
| 1774 scoped_refptr<CertVerifyProc> proc = | |
| 1775 new MockCertVerifyProc(CertVerifyResult()); | |
| 1776 proc->Verify(ee_chain.get(), "127.0.0.1", std::string(), flags, nullptr, | |
| 1777 CertificateList(), &verify_result); | |
| 1778 EXPECT_EQ(!!(data.expected_algorithms & EXPECT_MD2), verify_result.has_md2); | |
| 1779 EXPECT_EQ(!!(data.expected_algorithms & EXPECT_MD4), verify_result.has_md4); | |
| 1780 EXPECT_EQ(!!(data.expected_algorithms & EXPECT_MD5), verify_result.has_md5); | |
| 1781 EXPECT_EQ(!!(data.expected_algorithms & EXPECT_SHA1), verify_result.has_sha1); | |
| 1782 EXPECT_EQ(!!(data.expected_algorithms & EXPECT_SHA1_LEAF), | |
| 1783 verify_result.has_sha1_leaf); | |
| 1784 } | |
| 1785 | |
| 1786 // The signature algorithm of the root CA should not matter. | |
| 1787 const WeakDigestTestData kVerifyRootCATestData[] = { | |
| 1788 {"weak_digest_md5_root.pem", "weak_digest_sha1_intermediate.pem", | |
| 1789 "weak_digest_sha1_ee.pem", EXPECT_SHA1 | EXPECT_SHA1_LEAF}, | |
| 1790 {"weak_digest_md4_root.pem", "weak_digest_sha1_intermediate.pem", | |
| 1791 "weak_digest_sha1_ee.pem", EXPECT_SHA1 | EXPECT_SHA1_LEAF}, | |
| 1792 {"weak_digest_md2_root.pem", "weak_digest_sha1_intermediate.pem", | |
| 1793 "weak_digest_sha1_ee.pem", EXPECT_SHA1 | EXPECT_SHA1_LEAF}, | |
| 1794 }; | |
| 1795 INSTANTIATE_TEST_CASE_P(VerifyRoot, | |
| 1796 CertVerifyProcWeakDigestTest, | |
| 1797 testing::ValuesIn(kVerifyRootCATestData)); | |
| 1798 | |
| 1799 // The signature algorithm of intermediates should be properly detected. | |
| 1800 const WeakDigestTestData kVerifyIntermediateCATestData[] = { | |
| 1801 {"weak_digest_sha1_root.pem", "weak_digest_md5_intermediate.pem", | |
| 1802 "weak_digest_sha1_ee.pem", EXPECT_MD5 | EXPECT_SHA1 | EXPECT_SHA1_LEAF}, | |
| 1803 {"weak_digest_sha1_root.pem", "weak_digest_md4_intermediate.pem", | |
| 1804 "weak_digest_sha1_ee.pem", EXPECT_MD4 | EXPECT_SHA1 | EXPECT_SHA1_LEAF}, | |
| 1805 {"weak_digest_sha1_root.pem", "weak_digest_md2_intermediate.pem", | |
| 1806 "weak_digest_sha1_ee.pem", EXPECT_MD2 | EXPECT_SHA1 | EXPECT_SHA1_LEAF}, | |
| 1807 }; | |
| 1808 | |
| 1809 INSTANTIATE_TEST_CASE_P(VerifyIntermediate, | |
| 1810 CertVerifyProcWeakDigestTest, | |
| 1811 testing::ValuesIn(kVerifyIntermediateCATestData)); | |
| 1812 | |
| 1813 // The signature algorithm of end-entity should be properly detected. | |
| 1814 const WeakDigestTestData kVerifyEndEntityTestData[] = { | |
| 1815 {"weak_digest_sha1_root.pem", "weak_digest_sha1_intermediate.pem", | |
| 1816 "weak_digest_md5_ee.pem", EXPECT_MD5 | EXPECT_SHA1}, | |
| 1817 {"weak_digest_sha1_root.pem", "weak_digest_sha1_intermediate.pem", | |
| 1818 "weak_digest_md4_ee.pem", EXPECT_MD4 | EXPECT_SHA1}, | |
| 1819 {"weak_digest_sha1_root.pem", "weak_digest_sha1_intermediate.pem", | |
| 1820 "weak_digest_md2_ee.pem", EXPECT_MD2 | EXPECT_SHA1}, | |
| 1821 }; | |
| 1822 | |
| 1823 INSTANTIATE_TEST_CASE_P(VerifyEndEntity, | |
| 1824 CertVerifyProcWeakDigestTest, | |
| 1825 testing::ValuesIn(kVerifyEndEntityTestData)); | |
| 1826 | |
| 1827 // Incomplete chains do not report the status of the intermediate. | |
| 1828 // Note: really each of these tests should also expect the digest algorithm of | |
| 1829 // the intermediate (included as a comment). However CertVerifyProc::Verify() is | |
| 1830 // unable to distinguish that this is an intermediate and not a trust anchor, so | |
| 1831 // this intermediate is treated like a trust anchor. | |
| 1832 const WeakDigestTestData kVerifyIncompleteIntermediateTestData[] = { | |
| 1833 {NULL, "weak_digest_md5_intermediate.pem", "weak_digest_sha1_ee.pem", | |
| 1834 /*EXPECT_MD5 |*/ EXPECT_SHA1 | EXPECT_SHA1_LEAF}, | |
| 1835 {NULL, "weak_digest_md4_intermediate.pem", "weak_digest_sha1_ee.pem", | |
| 1836 /*EXPECT_MD4 |*/ EXPECT_SHA1 | EXPECT_SHA1_LEAF}, | |
| 1837 {NULL, "weak_digest_md2_intermediate.pem", "weak_digest_sha1_ee.pem", | |
| 1838 /*EXPECT_MD2 |*/ EXPECT_SHA1 | EXPECT_SHA1_LEAF}, | |
| 1839 }; | |
| 1840 | |
| 1841 INSTANTIATE_TEST_CASE_P( | |
| 1842 MAYBE_VerifyIncompleteIntermediate, | |
| 1843 CertVerifyProcWeakDigestTest, | |
| 1844 testing::ValuesIn(kVerifyIncompleteIntermediateTestData)); | |
| 1845 | |
| 1846 // Incomplete chains should report the status of the end-entity. | |
| 1847 // Note: really each of these tests should also expect EXPECT_SHA1 (included as | |
| 1848 // a comment). However CertVerifyProc::Verify() is unable to distinguish that | |
| 1849 // this is an intermediate and not a trust anchor, so this intermediate is | |
| 1850 // treated like a trust anchor. | |
| 1851 const WeakDigestTestData kVerifyIncompleteEETestData[] = { | |
| 1852 {NULL, "weak_digest_sha1_intermediate.pem", "weak_digest_md5_ee.pem", | |
| 1853 /*EXPECT_SHA1 |*/ EXPECT_MD5}, | |
| 1854 {NULL, "weak_digest_sha1_intermediate.pem", "weak_digest_md4_ee.pem", | |
| 1855 /*EXPECT_SHA1 |*/ EXPECT_MD4}, | |
| 1856 {NULL, "weak_digest_sha1_intermediate.pem", "weak_digest_md2_ee.pem", | |
| 1857 /*EXPECT_SHA1 |*/ EXPECT_MD2}, | |
| 1858 }; | |
| 1859 | |
| 1860 INSTANTIATE_TEST_CASE_P(VerifyIncompleteEndEntity, | |
| 1861 CertVerifyProcWeakDigestTest, | |
| 1862 testing::ValuesIn(kVerifyIncompleteEETestData)); | |
| 1863 | |
| 1864 // Differing algorithms between the intermediate and the EE should still be | |
| 1865 // reported. | |
| 1866 const WeakDigestTestData kVerifyMixedTestData[] = { | |
| 1867 {"weak_digest_sha1_root.pem", "weak_digest_md5_intermediate.pem", | |
| 1868 "weak_digest_md2_ee.pem", EXPECT_MD2 | EXPECT_MD5}, | |
| 1869 {"weak_digest_sha1_root.pem", "weak_digest_md2_intermediate.pem", | |
| 1870 "weak_digest_md5_ee.pem", EXPECT_MD2 | EXPECT_MD5}, | |
| 1871 {"weak_digest_sha1_root.pem", "weak_digest_md4_intermediate.pem", | |
| 1872 "weak_digest_md2_ee.pem", EXPECT_MD2 | EXPECT_MD4}, | |
| 1873 }; | |
| 1874 | |
| 1875 INSTANTIATE_TEST_CASE_P(VerifyMixed, | |
| 1876 CertVerifyProcWeakDigestTest, | |
| 1877 testing::ValuesIn(kVerifyMixedTestData)); | |
| 1878 | |
| 1879 // The EE is a trusted certificate. Even though it uses weak hashes, these | |
| 1880 // should not be reported. | |
| 1881 const WeakDigestTestData kVerifyTrustedEETestData[] = { | |
| 1882 {NULL, NULL, "weak_digest_md5_ee.pem", 0}, | |
| 1883 {NULL, NULL, "weak_digest_md4_ee.pem", 0}, | |
| 1884 {NULL, NULL, "weak_digest_md2_ee.pem", 0}, | |
| 1885 {NULL, NULL, "weak_digest_sha1_ee.pem", 0}, | |
| 1886 }; | |
| 1887 | |
| 1888 INSTANTIATE_TEST_CASE_P(VerifyTrustedEE, | |
| 1889 CertVerifyProcWeakDigestTest, | |
| 1890 testing::ValuesIn(kVerifyTrustedEETestData)); | |
| 1891 | |
| 1892 // For the list of valid hostnames, see | |
| 1893 // net/cert/data/ssl/certificates/subjectAltName_sanity_check.pem | |
| 1894 struct CertVerifyProcNameData { | |
| 1895 const char* hostname; | |
| 1896 bool valid; // Whether or not |hostname| matches a subjectAltName. | |
| 1897 }; | |
| 1898 | |
| 1899 // Test fixture for verifying certificate names. These tests are run for each | |
| 1900 // of the CertVerify implementations. | |
| 1901 class CertVerifyProcNameTest : public CertVerifyProcInternalTest { | |
| 1902 public: | |
| 1903 CertVerifyProcNameTest() {} | |
| 1904 virtual ~CertVerifyProcNameTest() {} | |
| 1905 | |
| 1906 protected: | |
| 1907 void VerifyCertName(const char* hostname, bool valid) { | |
| 1908 CertificateList cert_list = CreateCertificateListFromFile( | |
| 1909 GetTestCertsDirectory(), "subjectAltName_sanity_check.pem", | |
| 1910 X509Certificate::FORMAT_AUTO); | |
| 1911 ASSERT_EQ(1U, cert_list.size()); | |
| 1912 scoped_refptr<X509Certificate> cert(cert_list[0]); | |
| 1913 | |
| 1914 ScopedTestRoot scoped_root(cert.get()); | |
| 1915 | |
| 1916 CertVerifyResult verify_result; | |
| 1917 int error = Verify(cert.get(), hostname, 0, NULL, CertificateList(), | |
| 1918 &verify_result); | |
| 1919 if (valid) { | |
| 1920 EXPECT_THAT(error, IsOk()); | |
| 1921 EXPECT_FALSE(verify_result.cert_status & CERT_STATUS_COMMON_NAME_INVALID); | |
| 1922 } else { | |
| 1923 EXPECT_THAT(error, IsError(ERR_CERT_COMMON_NAME_INVALID)); | |
| 1924 EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_COMMON_NAME_INVALID); | |
| 1925 } | |
| 1926 } | |
| 1927 }; | |
| 1928 | |
| 1929 // Don't match the common name | |
| 1930 TEST_P(CertVerifyProcNameTest, DontMatchCommonName) { | |
| 1931 VerifyCertName("127.0.0.1", false); | |
| 1932 } | |
| 1933 | |
| 1934 // Matches the iPAddress SAN (IPv4) | |
| 1935 TEST_P(CertVerifyProcNameTest, MatchesIpSanIpv4) { | |
| 1936 VerifyCertName("127.0.0.2", true); | |
| 1937 } | |
| 1938 | |
| 1939 // Matches the iPAddress SAN (IPv6) | |
| 1940 TEST_P(CertVerifyProcNameTest, MatchesIpSanIpv6) { | |
| 1941 VerifyCertName("FE80:0:0:0:0:0:0:1", true); | |
| 1942 } | |
| 1943 | |
| 1944 // Should not match the iPAddress SAN | |
| 1945 TEST_P(CertVerifyProcNameTest, DoesntMatchIpSanIpv6) { | |
| 1946 VerifyCertName("[FE80:0:0:0:0:0:0:1]", false); | |
| 1947 } | |
| 1948 | |
| 1949 // Compressed form matches the iPAddress SAN (IPv6) | |
| 1950 TEST_P(CertVerifyProcNameTest, MatchesIpSanCompressedIpv6) { | |
| 1951 VerifyCertName("FE80::1", true); | |
| 1952 } | |
| 1953 | |
| 1954 // IPv6 mapped form should NOT match iPAddress SAN | |
| 1955 TEST_P(CertVerifyProcNameTest, DoesntMatchIpSanIPv6Mapped) { | |
| 1956 VerifyCertName("::127.0.0.2", false); | |
| 1957 } | |
| 1958 | |
| 1959 // Matches the dNSName SAN | |
| 1960 TEST_P(CertVerifyProcNameTest, MatchesDnsSan) { | |
| 1961 VerifyCertName("test.example", true); | |
| 1962 } | |
| 1963 | |
| 1964 // Matches the dNSName SAN (trailing . ignored) | |
| 1965 TEST_P(CertVerifyProcNameTest, MatchesDnsSanTrailingDot) { | |
| 1966 VerifyCertName("test.example.", true); | |
| 1967 } | |
| 1968 | |
| 1969 // Should not match the dNSName SAN | |
| 1970 TEST_P(CertVerifyProcNameTest, DoesntMatchDnsSan) { | |
| 1971 VerifyCertName("www.test.example", false); | |
| 1972 } | |
| 1973 | |
| 1974 // Should not match the dNSName SAN | |
| 1975 TEST_P(CertVerifyProcNameTest, DoesntMatchDnsSanInvalid) { | |
| 1976 VerifyCertName("test..example", false); | |
| 1977 } | |
| 1978 | |
| 1979 // Should not match the dNSName SAN | |
| 1980 TEST_P(CertVerifyProcNameTest, DoesntMatchDnsSanTwoTrailingDots) { | |
| 1981 VerifyCertName("test.example..", false); | |
| 1982 } | |
| 1983 | |
| 1984 // Should not match the dNSName SAN | |
| 1985 TEST_P(CertVerifyProcNameTest, DoesntMatchDnsSanLeadingAndTrailingDot) { | |
| 1986 VerifyCertName(".test.example.", false); | |
| 1987 } | |
| 1988 | |
| 1989 // Should not match the dNSName SAN | |
| 1990 TEST_P(CertVerifyProcNameTest, DoesntMatchDnsSanTrailingDot) { | |
| 1991 VerifyCertName(".test.example", false); | |
| 1992 } | |
| 1993 | |
| 1994 INSTANTIATE_TEST_CASE_P(VerifyName, | |
| 1995 CertVerifyProcNameTest, | |
| 1996 testing::ValuesIn(kAllCertVerifiers), | |
| 1997 VerifyProcTypeToName); | |
| 1998 | |
| 1999 #if defined(OS_MACOSX) && !defined(OS_IOS) | |
| 2000 // Test that CertVerifyProcMac reacts appropriately when Apple's certificate | 192 // Test that CertVerifyProcMac reacts appropriately when Apple's certificate |
| 2001 // verifier rejects a certificate with a fatal error. This is a regression | 193 // verifier rejects a certificate with a fatal error. This is a regression |
| 2002 // test for https://crbug.com/472291. | 194 // test for https://crbug.com/472291. |
| 2003 // (Since 10.12, this causes a recoverable error instead of a fatal one.) | 195 // (Since 10.12, this causes a recoverable error instead of a fatal one.) |
| 2004 // TODO(mattm): Try to find a different way to cause a fatal error that works | 196 // TODO(mattm): Try to find a different way to cause a fatal error that works |
| 2005 // on 10.12. | 197 // on 10.12. |
| 2006 TEST(CertVerifyProcMacTest, LargeKey) { | 198 TEST(CertVerifyProcMacTest, LargeKey) { |
| 2007 // Load root_ca_cert.pem into the test root store. | 199 // Load root_ca_cert.pem into the test root store. |
| 2008 ScopedTestRoot test_root( | 200 ScopedTestRoot test_root( |
| 2009 ImportCertFromFile(GetTestCertsDirectory(), "root_ca_cert.pem").get()); | 201 ImportCertFromFile(GetTestCertsDirectory(), "root_ca_cert.pem").get()); |
| 2010 | 202 |
| 2011 scoped_refptr<X509Certificate> cert( | 203 scoped_refptr<X509Certificate> cert( |
| 2012 ImportCertFromFile(GetTestCertsDirectory(), "large_key.pem")); | 204 ImportCertFromFile(GetTestCertsDirectory(), "large_key.pem")); |
| 2013 | 205 |
| 2014 // Apple's verifier rejects this certificate as invalid because the | 206 // Apple's verifier rejects this certificate as invalid because the |
| 2015 // RSA key is too large. If a future version of OS X changes this, | 207 // RSA key is too large. If a future version of OS X changes this, |
| 2016 // large_key.pem may need to be regenerated with a larger key. | 208 // large_key.pem may need to be regenerated with a larger key. |
| 2017 int flags = 0; | 209 int flags = 0; |
| 2018 CertVerifyResult verify_result; | 210 CertVerifyResult verify_result; |
| 2019 scoped_refptr<CertVerifyProc> verify_proc = CertVerifyProc::CreateDefault(); | 211 scoped_refptr<CertVerifyProc> verify_proc = new CertVerifyProcMac; |
| 2020 int error = verify_proc->Verify(cert.get(), "127.0.0.1", std::string(), flags, | 212 int error = verify_proc->Verify(cert.get(), "127.0.0.1", std::string(), flags, |
| 2021 NULL, CertificateList(), &verify_result); | 213 NULL, CertificateList(), &verify_result); |
| 2022 EXPECT_THAT(error, IsError(ERR_CERT_INVALID)); | 214 EXPECT_THAT(error, IsError(ERR_CERT_INVALID)); |
| 2023 EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_INVALID); | 215 EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_INVALID); |
| 2024 } | 216 } |
| 2025 #endif // defined(OS_MACOSX) && !defined(OS_IOS) | |
| 2026 | 217 |
| 2027 // Tests that CertVerifyProc records a histogram correctly when a | 218 } // namespace |
| 2028 // certificate chaining to a private root contains the TLS feature | |
| 2029 // extension and does not have a stapled OCSP response. | |
| 2030 TEST(CertVerifyProcTest, HasTLSFeatureExtensionUMA) { | |
| 2031 base::HistogramTester histograms; | |
| 2032 scoped_refptr<X509Certificate> cert( | |
| 2033 ImportCertFromFile(GetTestCertsDirectory(), "tls_feature_extension.pem")); | |
| 2034 ASSERT_TRUE(cert); | |
| 2035 CertVerifyResult result; | |
| 2036 result.is_issued_by_known_root = false; | |
| 2037 scoped_refptr<CertVerifyProc> verify_proc = new MockCertVerifyProc(result); | |
| 2038 | |
| 2039 histograms.ExpectTotalCount(kTLSFeatureExtensionHistogram, 0); | |
| 2040 histograms.ExpectTotalCount(kTLSFeatureExtensionOCSPHistogram, 0); | |
| 2041 | |
| 2042 int flags = 0; | |
| 2043 CertVerifyResult verify_result; | |
| 2044 int error = verify_proc->Verify(cert.get(), "127.0.0.1", std::string(), flags, | |
| 2045 NULL, CertificateList(), &verify_result); | |
| 2046 EXPECT_EQ(OK, error); | |
| 2047 histograms.ExpectTotalCount(kTLSFeatureExtensionHistogram, 1); | |
| 2048 histograms.ExpectBucketCount(kTLSFeatureExtensionHistogram, true, 1); | |
| 2049 histograms.ExpectTotalCount(kTLSFeatureExtensionOCSPHistogram, 1); | |
| 2050 histograms.ExpectBucketCount(kTLSFeatureExtensionOCSPHistogram, false, 1); | |
| 2051 } | |
| 2052 | |
| 2053 // Tests that CertVerifyProc records a histogram correctly when a | |
| 2054 // certificate chaining to a private root contains the TLS feature | |
| 2055 // extension and does have a stapled OCSP response. | |
| 2056 TEST(CertVerifyProcTest, HasTLSFeatureExtensionWithStapleUMA) { | |
| 2057 base::HistogramTester histograms; | |
| 2058 scoped_refptr<X509Certificate> cert( | |
| 2059 ImportCertFromFile(GetTestCertsDirectory(), "tls_feature_extension.pem")); | |
| 2060 ASSERT_TRUE(cert); | |
| 2061 CertVerifyResult result; | |
| 2062 result.is_issued_by_known_root = false; | |
| 2063 scoped_refptr<CertVerifyProc> verify_proc = new MockCertVerifyProc(result); | |
| 2064 | |
| 2065 histograms.ExpectTotalCount(kTLSFeatureExtensionHistogram, 0); | |
| 2066 histograms.ExpectTotalCount(kTLSFeatureExtensionOCSPHistogram, 0); | |
| 2067 | |
| 2068 int flags = 0; | |
| 2069 CertVerifyResult verify_result; | |
| 2070 int error = | |
| 2071 verify_proc->Verify(cert.get(), "127.0.0.1", "dummy response", flags, | |
| 2072 nullptr, CertificateList(), &verify_result); | |
| 2073 EXPECT_EQ(OK, error); | |
| 2074 histograms.ExpectTotalCount(kTLSFeatureExtensionHistogram, 1); | |
| 2075 histograms.ExpectBucketCount(kTLSFeatureExtensionHistogram, true, 1); | |
| 2076 histograms.ExpectTotalCount(kTLSFeatureExtensionOCSPHistogram, 1); | |
| 2077 histograms.ExpectBucketCount(kTLSFeatureExtensionOCSPHistogram, true, 1); | |
| 2078 } | |
| 2079 | |
| 2080 // Tests that CertVerifyProc records a histogram correctly when a | |
| 2081 // certificate chaining to a private root does not contain the TLS feature | |
| 2082 // extension. | |
| 2083 TEST(CertVerifyProcTest, DoesNotHaveTLSFeatureExtensionUMA) { | |
| 2084 base::HistogramTester histograms; | |
| 2085 scoped_refptr<X509Certificate> cert( | |
| 2086 ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem")); | |
| 2087 ASSERT_TRUE(cert); | |
| 2088 CertVerifyResult result; | |
| 2089 result.is_issued_by_known_root = false; | |
| 2090 scoped_refptr<CertVerifyProc> verify_proc = new MockCertVerifyProc(result); | |
| 2091 | |
| 2092 histograms.ExpectTotalCount(kTLSFeatureExtensionHistogram, 0); | |
| 2093 histograms.ExpectTotalCount(kTLSFeatureExtensionOCSPHistogram, 0); | |
| 2094 | |
| 2095 int flags = 0; | |
| 2096 CertVerifyResult verify_result; | |
| 2097 int error = verify_proc->Verify(cert.get(), "127.0.0.1", std::string(), flags, | |
| 2098 NULL, CertificateList(), &verify_result); | |
| 2099 EXPECT_EQ(OK, error); | |
| 2100 histograms.ExpectTotalCount(kTLSFeatureExtensionHistogram, 1); | |
| 2101 histograms.ExpectBucketCount(kTLSFeatureExtensionHistogram, false, 1); | |
| 2102 histograms.ExpectTotalCount(kTLSFeatureExtensionOCSPHistogram, 0); | |
| 2103 } | |
| 2104 | |
| 2105 // Tests that CertVerifyProc does not record a histogram when a | |
| 2106 // certificate contains the TLS feature extension but chains to a public | |
| 2107 // root. | |
| 2108 TEST(CertVerifyProcTest, HasTLSFeatureExtensionWithPublicRootUMA) { | |
| 2109 base::HistogramTester histograms; | |
| 2110 scoped_refptr<X509Certificate> cert( | |
| 2111 ImportCertFromFile(GetTestCertsDirectory(), "tls_feature_extension.pem")); | |
| 2112 ASSERT_TRUE(cert); | |
| 2113 CertVerifyResult result; | |
| 2114 result.is_issued_by_known_root = true; | |
| 2115 scoped_refptr<CertVerifyProc> verify_proc = new MockCertVerifyProc(result); | |
| 2116 | |
| 2117 histograms.ExpectTotalCount(kTLSFeatureExtensionHistogram, 0); | |
| 2118 | |
| 2119 int flags = 0; | |
| 2120 CertVerifyResult verify_result; | |
| 2121 int error = verify_proc->Verify(cert.get(), "127.0.0.1", std::string(), flags, | |
| 2122 NULL, CertificateList(), &verify_result); | |
| 2123 EXPECT_EQ(OK, error); | |
| 2124 histograms.ExpectTotalCount(kTLSFeatureExtensionHistogram, 0); | |
| 2125 histograms.ExpectTotalCount(kTLSFeatureExtensionOCSPHistogram, 0); | |
| 2126 } | |
| 2127 | 219 |
| 2128 } // namespace net | 220 } // namespace net |
| OLD | NEW |