Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "base/file_path.h" | |
| 6 #include "base/string_number_conversions.h" | |
| 7 #include "base/sha1.h" | |
| 8 #include "net/base/cert_status_flags.h" | |
| 9 #include "net/base/cert_test_util.h" | |
| 10 #include "net/base/cert_verify_proc_mac.h" | |
| 11 #include "net/base/cert_verify_proc_nss.h" | |
| 12 #include "net/base/cert_verify_proc_openssl.h" | |
| 13 #include "net/base/cert_verify_proc_win.h" | |
| 14 #include "net/base/cert_verify_result.h" | |
| 15 #include "net/base/crl_set.h" | |
| 16 #include "net/base/multi_threaded_cert_verifier.h" | |
| 17 #include "net/base/net_errors.h" | |
| 18 #include "net/base/test_certificate_data.h" | |
| 19 #include "net/base/test_root_certs.h" | |
| 20 #include "net/base/x509_certificate.h" | |
| 21 #include "testing/gtest/include/gtest/gtest.h" | |
| 22 | |
| 23 #if defined(OS_WIN) | |
| 24 #include "base/win/windows_version.h" | |
| 25 #elif defined(OS_MACOSX) | |
| 26 #include "base/mac/mac_util.h" | |
| 27 #endif | |
| 28 | |
| 29 using base::HexEncode; | |
| 30 | |
| 31 namespace net { | |
| 32 | |
| 33 namespace { | |
| 34 | |
| 35 // A certificate for www.paypal.com with a NULL byte in the common name. | |
| 36 // From http://www.gossamer-threads.com/lists/fulldisc/full-disclosure/70363 | |
| 37 unsigned char paypal_null_fingerprint[] = { | |
| 38 0x4c, 0x88, 0x9e, 0x28, 0xd7, 0x7a, 0x44, 0x1e, 0x13, 0xf2, 0x6a, 0xba, | |
| 39 0x1f, 0xe8, 0x1b, 0xd6, 0xab, 0x7b, 0xe8, 0xd7 | |
| 40 }; | |
| 41 | |
| 42 MultiThreadedCertVerifier::VerifyProc* GetSystemVerifier() { | |
|
wtc
2012/03/06 23:26:54
I saw this function in your other CL. Perhaps thi
Ryan Sleevi
2012/03/10 03:30:56
This has now been addressed by SystemCertVerifyPro
| |
| 43 #if defined(USE_NSS) | |
| 44 return new CertVerifyProcNSS; | |
| 45 #elif defined(USE_OPENSSL) | |
| 46 return new CertVerifyProcOpenSSL; | |
| 47 #elif defined(OS_MACOSX) | |
| 48 return new CertVerifyProcMac; | |
| 49 #elif defined(OS_WIN) | |
| 50 return new CertVerifyProcWin; | |
| 51 #else | |
| 52 return NULL; | |
| 53 #endif | |
| 54 } | |
| 55 | |
| 56 } // namespace | |
| 57 | |
| 58 class CertVerifyProcTest : public testing::Test { | |
| 59 public: | |
| 60 CertVerifyProcTest() : verify_proc_(GetSystemVerifier()) {} | |
| 61 virtual ~CertVerifyProcTest() {} | |
| 62 | |
| 63 protected: | |
| 64 int Verify(X509Certificate* cert, | |
| 65 const std::string& hostname, | |
| 66 int flags, | |
| 67 CRLSet* crl_set, | |
| 68 CertVerifyResult* verify_result) { | |
| 69 return verify_proc_->Verify(cert, hostname, flags, crl_set, | |
| 70 verify_result); | |
| 71 } | |
| 72 | |
| 73 private: | |
| 74 scoped_refptr<MultiThreadedCertVerifier::VerifyProc> verify_proc_; | |
| 75 }; | |
| 76 | |
| 77 | |
| 78 TEST_F(CertVerifyProcTest, WithoutRevocationChecking) { | |
| 79 // Check that verification without revocation checking works. | |
| 80 CertificateList certs = CreateCertificateListFromFile( | |
| 81 GetTestCertsDirectory(), | |
| 82 "googlenew.chain.pem", | |
| 83 X509Certificate::FORMAT_PEM_CERT_SEQUENCE); | |
| 84 | |
| 85 X509Certificate::OSCertHandles intermediates; | |
| 86 intermediates.push_back(certs[1]->os_cert_handle()); | |
| 87 | |
| 88 scoped_refptr<X509Certificate> google_full_chain = | |
| 89 X509Certificate::CreateFromHandle(certs[0]->os_cert_handle(), | |
| 90 intermediates); | |
| 91 | |
| 92 CertVerifyResult verify_result; | |
| 93 EXPECT_EQ(OK, Verify(google_full_chain, "www.google.com", 0 /* flags */, | |
| 94 NULL, &verify_result)); | |
| 95 } | |
| 96 | |
| 97 TEST_F(CertVerifyProcTest, PaypalNullCertParsing) { | |
| 98 scoped_refptr<X509Certificate> paypal_null_cert( | |
| 99 X509Certificate::CreateFromBytes( | |
| 100 reinterpret_cast<const char*>(paypal_null_der), | |
| 101 sizeof(paypal_null_der))); | |
| 102 | |
| 103 ASSERT_NE(static_cast<X509Certificate*>(NULL), paypal_null_cert); | |
| 104 | |
| 105 const SHA1Fingerprint& fingerprint = | |
| 106 paypal_null_cert->fingerprint(); | |
| 107 for (size_t i = 0; i < 20; ++i) | |
| 108 EXPECT_EQ(paypal_null_fingerprint[i], fingerprint.data[i]); | |
| 109 | |
| 110 int flags = 0; | |
| 111 CertVerifyResult verify_result; | |
| 112 int error = Verify(paypal_null_cert, "www.paypal.com", flags, NULL, | |
| 113 &verify_result); | |
| 114 #if defined(USE_OPENSSL) || defined(OS_MACOSX) || defined(OS_WIN) | |
| 115 // TOOD(bulach): investigate why macosx and win aren't returning | |
| 116 // ERR_CERT_INVALID or ERR_CERT_COMMON_NAME_INVALID. | |
| 117 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, error); | |
| 118 #else | |
| 119 EXPECT_EQ(ERR_CERT_COMMON_NAME_INVALID, error); | |
| 120 #endif | |
| 121 // Either the system crypto library should correctly report a certificate | |
| 122 // name mismatch, or our certificate blacklist should cause us to report an | |
| 123 // invalid certificate. | |
| 124 #if !defined(OS_MACOSX) && !defined(USE_OPENSSL) | |
| 125 EXPECT_TRUE(verify_result.cert_status & | |
| 126 (CERT_STATUS_COMMON_NAME_INVALID | CERT_STATUS_INVALID)); | |
| 127 #endif | |
| 128 } | |
| 129 | |
| 130 // A regression test for http://crbug.com/31497. | |
| 131 // This certificate will expire on 2012-04-08. The test will still | |
| 132 // pass if error == ERR_CERT_DATE_INVALID. TODO(wtc): generate test | |
| 133 // certificates for this unit test. http://crbug.com/111742 | |
| 134 TEST_F(CertVerifyProcTest, IntermediateCARequireExplicitPolicy) { | |
| 135 FilePath certs_dir = GetTestCertsDirectory(); | |
| 136 | |
| 137 scoped_refptr<X509Certificate> server_cert = | |
| 138 ImportCertFromFile(certs_dir, "www_us_army_mil_cert.der"); | |
| 139 ASSERT_NE(static_cast<X509Certificate*>(NULL), server_cert); | |
| 140 | |
| 141 // The intermediate CA certificate's policyConstraints extension has a | |
| 142 // requireExplicitPolicy field with SkipCerts=0. | |
| 143 scoped_refptr<X509Certificate> intermediate_cert = | |
| 144 ImportCertFromFile(certs_dir, "dod_ca_17_cert.der"); | |
| 145 ASSERT_NE(static_cast<X509Certificate*>(NULL), intermediate_cert); | |
| 146 | |
| 147 FilePath root_cert_path = certs_dir.AppendASCII("dod_root_ca_2_cert.der"); | |
| 148 TestRootCerts* root_certs = TestRootCerts::GetInstance(); | |
| 149 ASSERT_TRUE(root_certs->AddFromFile(root_cert_path)); | |
| 150 | |
| 151 X509Certificate::OSCertHandles intermediates; | |
| 152 intermediates.push_back(intermediate_cert->os_cert_handle()); | |
| 153 scoped_refptr<X509Certificate> cert_chain = | |
| 154 X509Certificate::CreateFromHandle(server_cert->os_cert_handle(), | |
| 155 intermediates); | |
| 156 | |
| 157 int flags = 0; | |
| 158 CertVerifyResult verify_result; | |
| 159 int error = Verify(cert_chain, "www.us.army.mil", flags, NULL, | |
| 160 &verify_result); | |
| 161 if (error == OK) { | |
| 162 EXPECT_EQ(0U, verify_result.cert_status); | |
| 163 } else { | |
| 164 EXPECT_EQ(ERR_CERT_DATE_INVALID, error); | |
| 165 EXPECT_EQ(CERT_STATUS_DATE_INVALID, verify_result.cert_status); | |
| 166 } | |
| 167 root_certs->Clear(); | |
| 168 } | |
| 169 | |
| 170 // Test for bug 58437. | |
| 171 // This certificate will expire on 2011-12-21. The test will still | |
| 172 // pass if error == ERR_CERT_DATE_INVALID. | |
| 173 // This test is DISABLED because it appears that we cannot do | |
| 174 // certificate revocation checking when running all of the net unit tests. | |
| 175 // This test passes when run individually, but when run with all of the net | |
| 176 // unit tests, the call to PKIXVerifyCert returns the NSS error -8180, which is | |
| 177 // SEC_ERROR_REVOKED_CERTIFICATE. This indicates a lack of revocation | |
| 178 // status, i.e. that the revocation check is failing for some reason. | |
| 179 TEST_F(CertVerifyProcTest, DISABLED_GlobalSignR3EVTest) { | |
| 180 FilePath certs_dir = GetTestCertsDirectory(); | |
| 181 | |
| 182 scoped_refptr<X509Certificate> server_cert = | |
| 183 ImportCertFromFile(certs_dir, "2029_globalsign_com_cert.pem"); | |
| 184 ASSERT_NE(static_cast<X509Certificate*>(NULL), server_cert); | |
| 185 | |
| 186 scoped_refptr<X509Certificate> intermediate_cert = | |
| 187 ImportCertFromFile(certs_dir, "globalsign_ev_sha256_ca_cert.pem"); | |
| 188 ASSERT_NE(static_cast<X509Certificate*>(NULL), intermediate_cert); | |
| 189 | |
| 190 X509Certificate::OSCertHandles intermediates; | |
| 191 intermediates.push_back(intermediate_cert->os_cert_handle()); | |
| 192 scoped_refptr<X509Certificate> cert_chain = | |
| 193 X509Certificate::CreateFromHandle(server_cert->os_cert_handle(), | |
| 194 intermediates); | |
| 195 | |
| 196 CertVerifyResult verify_result; | |
| 197 int flags = X509Certificate::VERIFY_REV_CHECKING_ENABLED | | |
| 198 X509Certificate::VERIFY_EV_CERT; | |
| 199 int error = Verify(cert_chain, "2029.globalsign.com", flags, NULL, | |
| 200 &verify_result); | |
| 201 if (error == OK) | |
| 202 EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_IS_EV); | |
| 203 else | |
| 204 EXPECT_EQ(ERR_CERT_DATE_INVALID, error); | |
| 205 } | |
| 206 | |
| 207 // Currently, only RSA and DSA keys are checked for weakness, and our example | |
| 208 // weak size is 768. These could change in the future. | |
| 209 // | |
| 210 // Note that this means there may be false negatives: keys for other | |
| 211 // algorithms and which are weak will pass this test. | |
| 212 static bool IsWeakKeyType(const std::string& key_type) { | |
| 213 size_t pos = key_type.find("-"); | |
| 214 std::string size = key_type.substr(0, pos); | |
| 215 std::string type = key_type.substr(pos + 1); | |
| 216 | |
| 217 if (type == "rsa" || type == "dsa") | |
| 218 return size == "768"; | |
| 219 | |
| 220 return false; | |
| 221 } | |
| 222 | |
| 223 TEST_F(CertVerifyProcTest, RejectWeakKeys) { | |
| 224 FilePath certs_dir = GetTestCertsDirectory(); | |
| 225 typedef std::vector<std::string> Strings; | |
| 226 Strings key_types; | |
| 227 | |
| 228 // generate-weak-test-chains.sh currently has: | |
| 229 // key_types="768-rsa 1024-rsa 2048-rsa prime256v1-ecdsa" | |
| 230 // We must use the same key types here. The filenames generated look like: | |
| 231 // 2048-rsa-ee-by-768-rsa-intermediate.pem | |
| 232 key_types.push_back("768-rsa"); | |
| 233 key_types.push_back("1024-rsa"); | |
| 234 key_types.push_back("2048-rsa"); | |
| 235 | |
| 236 bool use_ecdsa = true; | |
| 237 #if defined(OS_WIN) | |
| 238 use_ecdsa = base::win::GetVersion() > base::win::VERSION_XP; | |
| 239 #elif defined(OS_MACOSX) | |
| 240 use_ecdsa = base::mac::IsOSSnowLeopardOrLater(); | |
| 241 #endif | |
| 242 | |
| 243 if (use_ecdsa) | |
| 244 key_types.push_back("prime256v1-ecdsa"); | |
| 245 | |
| 246 // Add the root that signed the intermediates for this test. | |
| 247 scoped_refptr<X509Certificate> root_cert = | |
| 248 ImportCertFromFile(certs_dir, "2048-rsa-root.pem"); | |
| 249 ASSERT_NE(static_cast<X509Certificate*>(NULL), root_cert); | |
| 250 TestRootCerts::GetInstance()->Add(root_cert.get()); | |
| 251 | |
| 252 // Now test each chain. | |
| 253 for (Strings::const_iterator ee_type = key_types.begin(); | |
| 254 ee_type != key_types.end(); ++ee_type) { | |
| 255 for (Strings::const_iterator signer_type = key_types.begin(); | |
| 256 signer_type != key_types.end(); ++signer_type) { | |
| 257 std::string basename = *ee_type + "-ee-by-" + *signer_type + | |
| 258 "-intermediate.pem"; | |
| 259 SCOPED_TRACE(basename); | |
| 260 scoped_refptr<X509Certificate> ee_cert = | |
| 261 ImportCertFromFile(certs_dir, basename); | |
| 262 ASSERT_NE(static_cast<X509Certificate*>(NULL), ee_cert); | |
| 263 | |
| 264 basename = *signer_type + "-intermediate.pem"; | |
| 265 scoped_refptr<X509Certificate> intermediate = | |
| 266 ImportCertFromFile(certs_dir, basename); | |
| 267 ASSERT_NE(static_cast<X509Certificate*>(NULL), intermediate); | |
| 268 | |
| 269 X509Certificate::OSCertHandles intermediates; | |
| 270 intermediates.push_back(intermediate->os_cert_handle()); | |
| 271 scoped_refptr<X509Certificate> cert_chain = | |
| 272 X509Certificate::CreateFromHandle(ee_cert->os_cert_handle(), | |
| 273 intermediates); | |
| 274 | |
| 275 CertVerifyResult verify_result; | |
| 276 int error = Verify(cert_chain, "127.0.0.1", 0, NULL, &verify_result); | |
| 277 | |
| 278 if (IsWeakKeyType(*ee_type) || IsWeakKeyType(*signer_type)) { | |
| 279 EXPECT_NE(OK, error); | |
| 280 EXPECT_EQ(CERT_STATUS_WEAK_KEY, | |
| 281 verify_result.cert_status & CERT_STATUS_WEAK_KEY); | |
| 282 } else { | |
| 283 EXPECT_EQ(OK, error); | |
| 284 EXPECT_EQ(0U, verify_result.cert_status & CERT_STATUS_WEAK_KEY); | |
| 285 } | |
| 286 } | |
| 287 } | |
| 288 | |
| 289 TestRootCerts::GetInstance()->Clear(); | |
| 290 } | |
| 291 | |
| 292 // Test for bug 108514. | |
| 293 // The certificate will expire on 2012-07-20. The test will still | |
| 294 // pass if error == ERR_CERT_DATE_INVALID. TODO(rsleevi): generate test | |
| 295 // certificates for this unit test. http://crbug.com/111730 | |
| 296 TEST_F(CertVerifyProcTest, ExtraneousMD5RootCert) { | |
| 297 FilePath certs_dir = GetTestCertsDirectory(); | |
| 298 | |
| 299 scoped_refptr<X509Certificate> server_cert = | |
| 300 ImportCertFromFile(certs_dir, "images_etrade_wallst_com.pem"); | |
| 301 ASSERT_NE(static_cast<X509Certificate*>(NULL), server_cert); | |
| 302 | |
| 303 scoped_refptr<X509Certificate> intermediate_cert = | |
| 304 ImportCertFromFile(certs_dir, "globalsign_orgv1_ca.pem"); | |
| 305 ASSERT_NE(static_cast<X509Certificate*>(NULL), intermediate_cert); | |
| 306 | |
| 307 scoped_refptr<X509Certificate> md5_root_cert = | |
| 308 ImportCertFromFile(certs_dir, "globalsign_root_ca_md5.pem"); | |
| 309 ASSERT_NE(static_cast<X509Certificate*>(NULL), md5_root_cert); | |
| 310 | |
| 311 X509Certificate::OSCertHandles intermediates; | |
| 312 intermediates.push_back(intermediate_cert->os_cert_handle()); | |
| 313 intermediates.push_back(md5_root_cert->os_cert_handle()); | |
| 314 scoped_refptr<X509Certificate> cert_chain = | |
| 315 X509Certificate::CreateFromHandle(server_cert->os_cert_handle(), | |
| 316 intermediates); | |
| 317 | |
| 318 CertVerifyResult verify_result; | |
| 319 int flags = 0; | |
| 320 int error = Verify(cert_chain, "images.etrade.wallst.com", flags, NULL, | |
| 321 &verify_result); | |
| 322 if (error != OK) | |
| 323 EXPECT_EQ(ERR_CERT_DATE_INVALID, error); | |
| 324 | |
| 325 EXPECT_FALSE(verify_result.has_md5); | |
| 326 EXPECT_FALSE(verify_result.has_md5_ca); | |
| 327 } | |
| 328 | |
| 329 // Test for bug 94673. | |
| 330 TEST_F(CertVerifyProcTest, GoogleDigiNotarTest) { | |
| 331 FilePath certs_dir = GetTestCertsDirectory(); | |
| 332 | |
| 333 scoped_refptr<X509Certificate> server_cert = | |
| 334 ImportCertFromFile(certs_dir, "google_diginotar.pem"); | |
| 335 ASSERT_NE(static_cast<X509Certificate*>(NULL), server_cert); | |
| 336 | |
| 337 scoped_refptr<X509Certificate> intermediate_cert = | |
| 338 ImportCertFromFile(certs_dir, "diginotar_public_ca_2025.pem"); | |
| 339 ASSERT_NE(static_cast<X509Certificate*>(NULL), intermediate_cert); | |
| 340 | |
| 341 X509Certificate::OSCertHandles intermediates; | |
| 342 intermediates.push_back(intermediate_cert->os_cert_handle()); | |
| 343 scoped_refptr<X509Certificate> cert_chain = | |
| 344 X509Certificate::CreateFromHandle(server_cert->os_cert_handle(), | |
| 345 intermediates); | |
| 346 | |
| 347 CertVerifyResult verify_result; | |
| 348 int flags = X509Certificate::VERIFY_REV_CHECKING_ENABLED; | |
| 349 int error = Verify(cert_chain, "mail.google.com", flags, NULL, | |
| 350 &verify_result); | |
| 351 EXPECT_NE(OK, error); | |
| 352 | |
| 353 // Now turn off revocation checking. Certificate verification should still | |
| 354 // fail. | |
| 355 flags = 0; | |
| 356 error = Verify(cert_chain, "mail.google.com", flags, NULL, &verify_result); | |
| 357 EXPECT_NE(OK, error); | |
| 358 } | |
| 359 | |
| 360 // Bug 111893: This test needs a new certificate. | |
| 361 TEST_F(CertVerifyProcTest, DISABLED_TestKnownRoot) { | |
| 362 FilePath certs_dir = GetTestCertsDirectory(); | |
| 363 scoped_refptr<X509Certificate> cert = | |
| 364 ImportCertFromFile(certs_dir, "nist.der"); | |
| 365 ASSERT_NE(static_cast<X509Certificate*>(NULL), cert); | |
| 366 | |
| 367 // This intermediate is only needed for old Linux machines. Modern NSS | |
| 368 // includes it as a root already. | |
| 369 scoped_refptr<X509Certificate> intermediate_cert = | |
| 370 ImportCertFromFile(certs_dir, "nist_intermediate.der"); | |
| 371 ASSERT_NE(static_cast<X509Certificate*>(NULL), intermediate_cert); | |
| 372 | |
| 373 X509Certificate::OSCertHandles intermediates; | |
| 374 intermediates.push_back(intermediate_cert->os_cert_handle()); | |
| 375 scoped_refptr<X509Certificate> cert_chain = | |
| 376 X509Certificate::CreateFromHandle(cert->os_cert_handle(), | |
| 377 intermediates); | |
| 378 | |
| 379 int flags = 0; | |
| 380 CertVerifyResult verify_result; | |
| 381 // This is going to blow up in Feb 2012. Sorry! Disable and file a bug | |
| 382 // against agl. Also see PublicKeyHashes in this file. | |
| 383 int error = Verify(cert_chain, "www.nist.gov", flags, NULL, &verify_result); | |
| 384 EXPECT_EQ(OK, error); | |
| 385 EXPECT_EQ(0U, verify_result.cert_status); | |
| 386 EXPECT_TRUE(verify_result.is_issued_by_known_root); | |
| 387 } | |
| 388 | |
| 389 // Bug 111893: This test needs a new certificate. | |
| 390 TEST_F(CertVerifyProcTest, DISABLED_PublicKeyHashes) { | |
| 391 FilePath certs_dir = GetTestCertsDirectory(); | |
| 392 // This is going to blow up in Feb 2012. Sorry! Disable and file a bug | |
| 393 // against agl. Also see TestKnownRoot in this file. | |
| 394 scoped_refptr<X509Certificate> cert = | |
| 395 ImportCertFromFile(certs_dir, "nist.der"); | |
| 396 ASSERT_NE(static_cast<X509Certificate*>(NULL), cert); | |
| 397 | |
| 398 // This intermediate is only needed for old Linux machines. Modern NSS | |
| 399 // includes it as a root already. | |
| 400 scoped_refptr<X509Certificate> intermediate_cert = | |
| 401 ImportCertFromFile(certs_dir, "nist_intermediate.der"); | |
| 402 ASSERT_NE(static_cast<X509Certificate*>(NULL), intermediate_cert); | |
| 403 | |
| 404 TestRootCerts::GetInstance()->Add(intermediate_cert.get()); | |
| 405 | |
| 406 X509Certificate::OSCertHandles intermediates; | |
| 407 intermediates.push_back(intermediate_cert->os_cert_handle()); | |
| 408 scoped_refptr<X509Certificate> cert_chain = | |
| 409 X509Certificate::CreateFromHandle(cert->os_cert_handle(), | |
| 410 intermediates); | |
| 411 | |
| 412 int flags = 0; | |
| 413 CertVerifyResult verify_result; | |
| 414 | |
| 415 int error = Verify(cert_chain, "www.nist.gov", flags, NULL, &verify_result); | |
| 416 EXPECT_EQ(OK, error); | |
| 417 EXPECT_EQ(0U, verify_result.cert_status); | |
| 418 ASSERT_LE(2u, verify_result.public_key_hashes.size()); | |
| 419 EXPECT_EQ(HexEncode(nistSPKIHash, base::kSHA1Length), | |
| 420 HexEncode(verify_result.public_key_hashes[0].data, base::kSHA1Length)); | |
| 421 EXPECT_EQ("83244223D6CBF0A26FC7DE27CEBCA4BDA32612AD", | |
| 422 HexEncode(verify_result.public_key_hashes[1].data, base::kSHA1Length)); | |
| 423 | |
| 424 TestRootCerts::GetInstance()->Clear(); | |
| 425 } | |
| 426 | |
| 427 // A regression test for http://crbug.com/70293. | |
| 428 // The Key Usage extension in this RSA SSL server certificate does not have | |
| 429 // the keyEncipherment bit. | |
| 430 TEST_F(CertVerifyProcTest, InvalidKeyUsage) { | |
| 431 FilePath certs_dir = GetTestCertsDirectory(); | |
| 432 | |
| 433 scoped_refptr<X509Certificate> server_cert = | |
| 434 ImportCertFromFile(certs_dir, "invalid_key_usage_cert.der"); | |
| 435 ASSERT_NE(static_cast<X509Certificate*>(NULL), server_cert); | |
| 436 | |
| 437 int flags = 0; | |
| 438 CertVerifyResult verify_result; | |
| 439 int error = Verify(server_cert, "jira.aquameta.com", flags, NULL, | |
| 440 &verify_result); | |
| 441 #if defined(USE_OPENSSL) | |
| 442 // This certificate has two errors: "invalid key usage" and "untrusted CA". | |
| 443 // However, OpenSSL returns only one (the latter), and we can't detect | |
| 444 // the other errors. | |
| 445 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, error); | |
| 446 #else | |
| 447 EXPECT_EQ(ERR_CERT_INVALID, error); | |
| 448 EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_INVALID); | |
| 449 #endif | |
| 450 // TODO(wtc): fix http://crbug.com/75520 to get all the certificate errors | |
| 451 // from NSS. | |
| 452 #if !defined(USE_NSS) | |
| 453 // The certificate is issued by an unknown CA. | |
| 454 EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_AUTHORITY_INVALID); | |
| 455 #endif | |
| 456 } | |
| 457 | |
| 458 // Basic test for returning the chain in CertVerifyResult. Note that the | |
| 459 // returned chain may just be a reflection of the originally supplied chain; | |
| 460 // that is, if any errors occur, the default chain returned is an exact copy | |
| 461 // of the certificate to be verified. The remaining VerifyReturn* tests are | |
| 462 // used to ensure that the actual, verified chain is being returned by | |
| 463 // Verify(). | |
| 464 TEST_F(CertVerifyProcTest, VerifyReturnChainBasic) { | |
| 465 FilePath certs_dir = GetTestCertsDirectory(); | |
| 466 CertificateList certs = CreateCertificateListFromFile( | |
| 467 certs_dir, "x509_verify_results.chain.pem", | |
| 468 X509Certificate::FORMAT_AUTO); | |
| 469 ASSERT_EQ(3U, certs.size()); | |
| 470 | |
| 471 X509Certificate::OSCertHandles intermediates; | |
| 472 intermediates.push_back(certs[1]->os_cert_handle()); | |
| 473 intermediates.push_back(certs[2]->os_cert_handle()); | |
| 474 | |
| 475 TestRootCerts::GetInstance()->Add(certs[2]); | |
| 476 | |
| 477 scoped_refptr<X509Certificate> google_full_chain = | |
| 478 X509Certificate::CreateFromHandle(certs[0]->os_cert_handle(), | |
| 479 intermediates); | |
| 480 ASSERT_NE(static_cast<X509Certificate*>(NULL), google_full_chain); | |
| 481 ASSERT_EQ(2U, google_full_chain->GetIntermediateCertificates().size()); | |
| 482 | |
| 483 CertVerifyResult verify_result; | |
| 484 EXPECT_EQ(static_cast<X509Certificate*>(NULL), verify_result.verified_cert); | |
| 485 int error = Verify(google_full_chain, "127.0.0.1", 0, NULL, &verify_result); | |
| 486 EXPECT_EQ(OK, error); | |
| 487 ASSERT_NE(static_cast<X509Certificate*>(NULL), verify_result.verified_cert); | |
| 488 | |
| 489 EXPECT_NE(google_full_chain, verify_result.verified_cert); | |
| 490 EXPECT_TRUE(X509Certificate::IsSameOSCert( | |
| 491 google_full_chain->os_cert_handle(), | |
| 492 verify_result.verified_cert->os_cert_handle())); | |
| 493 const X509Certificate::OSCertHandles& return_intermediates = | |
| 494 verify_result.verified_cert->GetIntermediateCertificates(); | |
| 495 ASSERT_EQ(2U, return_intermediates.size()); | |
| 496 EXPECT_TRUE(X509Certificate::IsSameOSCert(return_intermediates[0], | |
| 497 certs[1]->os_cert_handle())); | |
| 498 EXPECT_TRUE(X509Certificate::IsSameOSCert(return_intermediates[1], | |
| 499 certs[2]->os_cert_handle())); | |
| 500 | |
| 501 TestRootCerts::GetInstance()->Clear(); | |
| 502 } | |
| 503 | |
| 504 // Test that the certificate returned in CertVerifyResult is able to reorder | |
| 505 // certificates that are not ordered from end-entity to root. While this is | |
| 506 // a protocol violation if sent during a TLS handshake, if multiple sources | |
| 507 // of intermediate certificates are combined, it's possible that order may | |
| 508 // not be maintained. | |
| 509 TEST_F(CertVerifyProcTest, VerifyReturnChainProperlyOrdered) { | |
| 510 FilePath certs_dir = GetTestCertsDirectory(); | |
| 511 CertificateList certs = CreateCertificateListFromFile( | |
| 512 certs_dir, "x509_verify_results.chain.pem", | |
| 513 X509Certificate::FORMAT_AUTO); | |
| 514 ASSERT_EQ(3U, certs.size()); | |
| 515 | |
| 516 // Construct the chain out of order. | |
| 517 X509Certificate::OSCertHandles intermediates; | |
| 518 intermediates.push_back(certs[2]->os_cert_handle()); | |
| 519 intermediates.push_back(certs[1]->os_cert_handle()); | |
| 520 | |
| 521 TestRootCerts::GetInstance()->Add(certs[2]); | |
| 522 | |
| 523 scoped_refptr<X509Certificate> google_full_chain = | |
| 524 X509Certificate::CreateFromHandle(certs[0]->os_cert_handle(), | |
| 525 intermediates); | |
| 526 ASSERT_NE(static_cast<X509Certificate*>(NULL), google_full_chain); | |
| 527 ASSERT_EQ(2U, google_full_chain->GetIntermediateCertificates().size()); | |
| 528 | |
| 529 CertVerifyResult verify_result; | |
| 530 EXPECT_EQ(static_cast<X509Certificate*>(NULL), verify_result.verified_cert); | |
| 531 int error = Verify(google_full_chain, "127.0.0.1", 0, NULL, &verify_result); | |
| 532 EXPECT_EQ(OK, error); | |
| 533 ASSERT_NE(static_cast<X509Certificate*>(NULL), verify_result.verified_cert); | |
| 534 | |
| 535 EXPECT_NE(google_full_chain, verify_result.verified_cert); | |
| 536 EXPECT_TRUE(X509Certificate::IsSameOSCert( | |
| 537 google_full_chain->os_cert_handle(), | |
| 538 verify_result.verified_cert->os_cert_handle())); | |
| 539 const X509Certificate::OSCertHandles& return_intermediates = | |
| 540 verify_result.verified_cert->GetIntermediateCertificates(); | |
| 541 ASSERT_EQ(2U, return_intermediates.size()); | |
| 542 EXPECT_TRUE(X509Certificate::IsSameOSCert(return_intermediates[0], | |
| 543 certs[1]->os_cert_handle())); | |
| 544 EXPECT_TRUE(X509Certificate::IsSameOSCert(return_intermediates[1], | |
| 545 certs[2]->os_cert_handle())); | |
| 546 | |
| 547 TestRootCerts::GetInstance()->Clear(); | |
| 548 } | |
| 549 | |
| 550 // Test that Verify() filters out certificates which are not related to | |
| 551 // or part of the certificate chain being verified. | |
| 552 TEST_F(CertVerifyProcTest, VerifyReturnChainFiltersUnrelatedCerts) { | |
| 553 FilePath certs_dir = GetTestCertsDirectory(); | |
| 554 CertificateList certs = CreateCertificateListFromFile( | |
| 555 certs_dir, "x509_verify_results.chain.pem", | |
| 556 X509Certificate::FORMAT_AUTO); | |
| 557 ASSERT_EQ(3U, certs.size()); | |
| 558 TestRootCerts::GetInstance()->Add(certs[2]); | |
| 559 | |
| 560 scoped_refptr<X509Certificate> unrelated_dod_certificate = | |
| 561 ImportCertFromFile(certs_dir, "dod_ca_17_cert.der"); | |
| 562 scoped_refptr<X509Certificate> unrelated_dod_certificate2 = | |
| 563 ImportCertFromFile(certs_dir, "dod_root_ca_2_cert.der"); | |
| 564 ASSERT_NE(static_cast<X509Certificate*>(NULL), unrelated_dod_certificate); | |
| 565 ASSERT_NE(static_cast<X509Certificate*>(NULL), unrelated_dod_certificate2); | |
| 566 | |
| 567 // Interject unrelated certificates into the list of intermediates. | |
| 568 X509Certificate::OSCertHandles intermediates; | |
| 569 intermediates.push_back(unrelated_dod_certificate->os_cert_handle()); | |
| 570 intermediates.push_back(certs[1]->os_cert_handle()); | |
| 571 intermediates.push_back(unrelated_dod_certificate2->os_cert_handle()); | |
| 572 intermediates.push_back(certs[2]->os_cert_handle()); | |
| 573 | |
| 574 scoped_refptr<X509Certificate> google_full_chain = | |
| 575 X509Certificate::CreateFromHandle(certs[0]->os_cert_handle(), | |
| 576 intermediates); | |
| 577 ASSERT_NE(static_cast<X509Certificate*>(NULL), google_full_chain); | |
| 578 ASSERT_EQ(4U, google_full_chain->GetIntermediateCertificates().size()); | |
| 579 | |
| 580 CertVerifyResult verify_result; | |
| 581 EXPECT_EQ(static_cast<X509Certificate*>(NULL), verify_result.verified_cert); | |
| 582 int error = Verify(google_full_chain, "127.0.0.1", 0, NULL, &verify_result); | |
| 583 EXPECT_EQ(OK, error); | |
| 584 ASSERT_NE(static_cast<X509Certificate*>(NULL), verify_result.verified_cert); | |
| 585 | |
| 586 EXPECT_NE(google_full_chain, verify_result.verified_cert); | |
| 587 EXPECT_TRUE(X509Certificate::IsSameOSCert( | |
| 588 google_full_chain->os_cert_handle(), | |
| 589 verify_result.verified_cert->os_cert_handle())); | |
| 590 const X509Certificate::OSCertHandles& return_intermediates = | |
| 591 verify_result.verified_cert->GetIntermediateCertificates(); | |
| 592 ASSERT_EQ(2U, return_intermediates.size()); | |
| 593 EXPECT_TRUE(X509Certificate::IsSameOSCert(return_intermediates[0], | |
| 594 certs[1]->os_cert_handle())); | |
| 595 EXPECT_TRUE(X509Certificate::IsSameOSCert(return_intermediates[1], | |
| 596 certs[2]->os_cert_handle())); | |
| 597 TestRootCerts::GetInstance()->Clear(); | |
| 598 } | |
| 599 | |
| 600 #if defined(USE_NSS) || defined(OS_WIN) || defined(OS_MACOSX) | |
| 601 static const uint8 kCRLSetThawteSPKIBlocked[] = { | |
| 602 0x8e, 0x00, 0x7b, 0x22, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x3a, | |
| 603 0x30, 0x2c, 0x22, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, | |
| 604 0x65, 0x22, 0x3a, 0x22, 0x43, 0x52, 0x4c, 0x53, 0x65, 0x74, 0x22, 0x2c, 0x22, | |
| 605 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x22, 0x3a, 0x30, 0x2c, 0x22, | |
| 606 0x44, 0x65, 0x6c, 0x74, 0x61, 0x46, 0x72, 0x6f, 0x6d, 0x22, 0x3a, 0x30, 0x2c, | |
| 607 0x22, 0x4e, 0x75, 0x6d, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a, | |
| 608 0x30, 0x2c, 0x22, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x53, 0x50, 0x4b, | |
| 609 0x49, 0x73, 0x22, 0x3a, 0x5b, 0x22, 0x36, 0x58, 0x36, 0x4d, 0x78, 0x52, 0x37, | |
| 610 0x58, 0x70, 0x4d, 0x51, 0x4b, 0x78, 0x49, 0x41, 0x39, 0x50, 0x6a, 0x36, 0x37, | |
| 611 0x36, 0x38, 0x76, 0x74, 0x55, 0x6b, 0x6b, 0x7a, 0x48, 0x79, 0x7a, 0x41, 0x6f, | |
| 612 0x6d, 0x6f, 0x4f, 0x68, 0x4b, 0x55, 0x6e, 0x7a, 0x73, 0x55, 0x3d, 0x22, 0x5d, | |
| 613 0x7d, | |
| 614 }; | |
| 615 | |
| 616 static const uint8 kCRLSetThawteSerialBlocked[] = { | |
| 617 0x60, 0x00, 0x7b, 0x22, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x3a, | |
| 618 0x30, 0x2c, 0x22, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, | |
| 619 0x65, 0x22, 0x3a, 0x22, 0x43, 0x52, 0x4c, 0x53, 0x65, 0x74, 0x22, 0x2c, 0x22, | |
| 620 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x22, 0x3a, 0x30, 0x2c, 0x22, | |
| 621 0x44, 0x65, 0x6c, 0x74, 0x61, 0x46, 0x72, 0x6f, 0x6d, 0x22, 0x3a, 0x30, 0x2c, | |
| 622 0x22, 0x4e, 0x75, 0x6d, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a, | |
| 623 0x31, 0x2c, 0x22, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x53, 0x50, 0x4b, | |
| 624 0x49, 0x73, 0x22, 0x3a, 0x5b, 0x5d, 0x7d, 0xb1, 0x12, 0x41, 0x42, 0xa5, 0xa1, | |
| 625 0xa5, 0xa2, 0x88, 0x19, 0xc7, 0x35, 0x34, 0x0e, 0xff, 0x8c, 0x9e, 0x2f, 0x81, | |
| 626 0x68, 0xfe, 0xe3, 0xba, 0x18, 0x7f, 0x25, 0x3b, 0xc1, 0xa3, 0x92, 0xd7, 0xe2, | |
| 627 // Note that this is actually blocking two serial numbers because on XP and | |
| 628 // Vista, CryptoAPI finds a different Thawte certificate. | |
| 629 0x02, 0x00, 0x00, 0x00, | |
| 630 0x04, 0x30, 0x00, 0x00, 0x02, | |
| 631 0x04, 0x30, 0x00, 0x00, 0x06, | |
| 632 }; | |
| 633 | |
| 634 static const uint8 kCRLSetGoogleSerialBlocked[] = { | |
| 635 0x60, 0x00, 0x7b, 0x22, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x3a, | |
| 636 0x30, 0x2c, 0x22, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, | |
| 637 0x65, 0x22, 0x3a, 0x22, 0x43, 0x52, 0x4c, 0x53, 0x65, 0x74, 0x22, 0x2c, 0x22, | |
| 638 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x22, 0x3a, 0x30, 0x2c, 0x22, | |
| 639 0x44, 0x65, 0x6c, 0x74, 0x61, 0x46, 0x72, 0x6f, 0x6d, 0x22, 0x3a, 0x30, 0x2c, | |
| 640 0x22, 0x4e, 0x75, 0x6d, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a, | |
| 641 0x31, 0x2c, 0x22, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x53, 0x50, 0x4b, | |
| 642 0x49, 0x73, 0x22, 0x3a, 0x5b, 0x5d, 0x7d, 0xe9, 0x7e, 0x8c, 0xc5, 0x1e, 0xd7, | |
| 643 0xa4, 0xc4, 0x0a, 0xc4, 0x80, 0x3d, 0x3e, 0x3e, 0xbb, 0xeb, 0xcb, 0xed, 0x52, | |
| 644 0x49, 0x33, 0x1f, 0x2c, 0xc0, 0xa2, 0x6a, 0x0e, 0x84, 0xa5, 0x27, 0xce, 0xc5, | |
| 645 0x01, 0x00, 0x00, 0x00, 0x10, 0x4f, 0x9d, 0x96, 0xd9, 0x66, 0xb0, 0x99, 0x2b, | |
| 646 0x54, 0xc2, 0x95, 0x7c, 0xb4, 0x15, 0x7d, 0x4d, | |
| 647 }; | |
| 648 | |
| 649 // Test that CRLSets are effective in making a certificate appear to be | |
| 650 // revoked. | |
| 651 TEST_F(CertVerifyProcTest, CRLSet) { | |
| 652 CertificateList certs = CreateCertificateListFromFile( | |
| 653 GetTestCertsDirectory(), | |
| 654 "googlenew.chain.pem", | |
| 655 X509Certificate::FORMAT_PEM_CERT_SEQUENCE); | |
| 656 | |
| 657 X509Certificate::OSCertHandles intermediates; | |
| 658 intermediates.push_back(certs[1]->os_cert_handle()); | |
| 659 | |
| 660 scoped_refptr<X509Certificate> google_full_chain = | |
| 661 X509Certificate::CreateFromHandle(certs[0]->os_cert_handle(), | |
| 662 intermediates); | |
| 663 | |
| 664 CertVerifyResult verify_result; | |
| 665 int error = Verify(google_full_chain, "www.google.com", 0, NULL, | |
| 666 &verify_result); | |
| 667 EXPECT_EQ(OK, error); | |
| 668 | |
| 669 // First test blocking by SPKI. | |
| 670 base::StringPiece crl_set_bytes( | |
| 671 reinterpret_cast<const char*>(kCRLSetThawteSPKIBlocked), | |
| 672 sizeof(kCRLSetThawteSPKIBlocked)); | |
| 673 scoped_refptr<CRLSet> crl_set; | |
| 674 ASSERT_TRUE(CRLSet::Parse(crl_set_bytes, &crl_set)); | |
| 675 | |
| 676 error = Verify(google_full_chain, "www.google.com", 0, crl_set.get(), | |
| 677 &verify_result); | |
| 678 EXPECT_EQ(ERR_CERT_REVOKED, error); | |
| 679 | |
| 680 // Second, test revocation by serial number of a cert directly under the | |
| 681 // root. | |
| 682 crl_set_bytes = base::StringPiece( | |
| 683 reinterpret_cast<const char*>(kCRLSetThawteSerialBlocked), | |
| 684 sizeof(kCRLSetThawteSerialBlocked)); | |
| 685 ASSERT_TRUE(CRLSet::Parse(crl_set_bytes, &crl_set)); | |
| 686 | |
| 687 error = Verify(google_full_chain, "www.google.com", 0, crl_set.get(), | |
| 688 &verify_result); | |
| 689 EXPECT_EQ(ERR_CERT_REVOKED, error); | |
| 690 | |
| 691 // Lastly, test revocation by serial number of a certificate not under the | |
| 692 // root. | |
| 693 crl_set_bytes = base::StringPiece( | |
| 694 reinterpret_cast<const char*>(kCRLSetGoogleSerialBlocked), | |
| 695 sizeof(kCRLSetGoogleSerialBlocked)); | |
| 696 ASSERT_TRUE(CRLSet::Parse(crl_set_bytes, &crl_set)); | |
| 697 | |
| 698 error = Verify(google_full_chain, "www.google.com", 0, crl_set.get(), | |
| 699 &verify_result); | |
| 700 EXPECT_EQ(ERR_CERT_REVOKED, error); | |
| 701 } | |
| 702 #endif | |
| 703 | |
| 704 struct WeakDigestTestData { | |
| 705 const char* root_cert_filename; | |
| 706 const char* intermediate_cert_filename; | |
| 707 const char* ee_cert_filename; | |
| 708 bool expected_has_md5; | |
| 709 bool expected_has_md4; | |
| 710 bool expected_has_md2; | |
| 711 bool expected_has_md5_ca; | |
| 712 bool expected_has_md2_ca; | |
| 713 }; | |
| 714 | |
| 715 // GTest 'magic' pretty-printer, so that if/when a test fails, it knows how | |
| 716 // to output the parameter that was passed. Without this, it will simply | |
| 717 // attempt to print out the first twenty bytes of the object, which depending | |
| 718 // on platform and alignment, may result in an invalid read. | |
| 719 void PrintTo(const WeakDigestTestData& data, std::ostream* os) { | |
| 720 *os << "root: " | |
| 721 << (data.root_cert_filename ? data.root_cert_filename : "none") | |
| 722 << "; intermediate: " << data.intermediate_cert_filename | |
| 723 << "; end-entity: " << data.ee_cert_filename; | |
| 724 } | |
| 725 | |
| 726 class CertVerifyProcWeakDigestTest | |
| 727 : public CertVerifyProcTest, | |
| 728 public testing::WithParamInterface<WeakDigestTestData> { | |
| 729 public: | |
| 730 CertVerifyProcWeakDigestTest() {} | |
| 731 | |
| 732 virtual void TearDown() { | |
| 733 TestRootCerts::GetInstance()->Clear(); | |
| 734 } | |
| 735 }; | |
| 736 | |
| 737 TEST_P(CertVerifyProcWeakDigestTest, Verify) { | |
| 738 WeakDigestTestData data = GetParam(); | |
| 739 FilePath certs_dir = GetTestCertsDirectory(); | |
| 740 | |
| 741 if (data.root_cert_filename) { | |
| 742 scoped_refptr<X509Certificate> root_cert = | |
| 743 ImportCertFromFile(certs_dir, data.root_cert_filename); | |
| 744 ASSERT_NE(static_cast<X509Certificate*>(NULL), root_cert); | |
| 745 TestRootCerts::GetInstance()->Add(root_cert.get()); | |
| 746 } | |
| 747 | |
| 748 scoped_refptr<X509Certificate> intermediate_cert = | |
| 749 ImportCertFromFile(certs_dir, data.intermediate_cert_filename); | |
| 750 ASSERT_NE(static_cast<X509Certificate*>(NULL), intermediate_cert); | |
| 751 scoped_refptr<X509Certificate> ee_cert = | |
| 752 ImportCertFromFile(certs_dir, data.ee_cert_filename); | |
| 753 ASSERT_NE(static_cast<X509Certificate*>(NULL), ee_cert); | |
| 754 | |
| 755 X509Certificate::OSCertHandles intermediates; | |
| 756 intermediates.push_back(intermediate_cert->os_cert_handle()); | |
| 757 | |
| 758 scoped_refptr<X509Certificate> ee_chain = | |
| 759 X509Certificate::CreateFromHandle(ee_cert->os_cert_handle(), | |
| 760 intermediates); | |
| 761 ASSERT_NE(static_cast<X509Certificate*>(NULL), ee_chain); | |
| 762 | |
| 763 int flags = 0; | |
| 764 CertVerifyResult verify_result; | |
| 765 int rv = Verify(ee_chain, "127.0.0.1", flags, NULL, &verify_result); | |
| 766 EXPECT_EQ(data.expected_has_md5, verify_result.has_md5); | |
| 767 EXPECT_EQ(data.expected_has_md4, verify_result.has_md4); | |
| 768 EXPECT_EQ(data.expected_has_md2, verify_result.has_md2); | |
| 769 EXPECT_EQ(data.expected_has_md5_ca, verify_result.has_md5_ca); | |
| 770 EXPECT_EQ(data.expected_has_md2_ca, verify_result.has_md2_ca); | |
| 771 | |
| 772 // Ensure that MD4 and MD2 are tagged as invalid. | |
| 773 if (data.expected_has_md4 || data.expected_has_md2) { | |
| 774 EXPECT_EQ(CERT_STATUS_INVALID, | |
| 775 verify_result.cert_status & CERT_STATUS_INVALID); | |
| 776 } | |
| 777 | |
| 778 // Ensure that MD5 is flagged as weak. | |
| 779 if (data.expected_has_md5) { | |
| 780 EXPECT_EQ( | |
| 781 CERT_STATUS_WEAK_SIGNATURE_ALGORITHM, | |
| 782 verify_result.cert_status & CERT_STATUS_WEAK_SIGNATURE_ALGORITHM); | |
| 783 } | |
| 784 | |
| 785 // If a root cert is present, then check that the chain was rejected if any | |
| 786 // weak algorithms are present. This is only checked when a root cert is | |
| 787 // present because the error reported for incomplete chains with weak | |
| 788 // algorithms depends on which implementation was used to validate (NSS, | |
| 789 // OpenSSL, CryptoAPI, Security.framework) and upon which weak algorithm | |
| 790 // present (MD2, MD4, MD5). | |
| 791 if (data.root_cert_filename) { | |
| 792 if (data.expected_has_md4 || data.expected_has_md2) { | |
| 793 EXPECT_EQ(ERR_CERT_INVALID, rv); | |
| 794 } else if (data.expected_has_md5) { | |
| 795 EXPECT_EQ(ERR_CERT_WEAK_SIGNATURE_ALGORITHM, rv); | |
| 796 } else { | |
| 797 EXPECT_EQ(OK, rv); | |
| 798 } | |
| 799 } | |
| 800 } | |
| 801 | |
| 802 // Unlike TEST/TEST_F, which are macros that expand to further macros, | |
| 803 // INSTANTIATE_TEST_CASE_P is a macro that expands directly to code that | |
| 804 // stringizes the arguments. As a result, macros passed as parameters (such as | |
| 805 // prefix or test_case_name) will not be expanded by the preprocessor. To work | |
| 806 // around this, indirect the macro for INSTANTIATE_TEST_CASE_P, so that the | |
| 807 // pre-processor will expand macros such as MAYBE_test_name before | |
| 808 // instantiating the test. | |
| 809 #define WRAPPED_INSTANTIATE_TEST_CASE_P(prefix, test_case_name, generator) \ | |
| 810 INSTANTIATE_TEST_CASE_P(prefix, test_case_name, generator) | |
| 811 | |
| 812 // The signature algorithm of the root CA should not matter. | |
| 813 const WeakDigestTestData kVerifyRootCATestData[] = { | |
| 814 { "weak_digest_md5_root.pem", "weak_digest_sha1_intermediate.pem", | |
| 815 "weak_digest_sha1_ee.pem", false, false, false, false, false }, | |
| 816 #if !defined(OS_MACOSX) // MD4 is not supported. | |
| 817 { "weak_digest_md4_root.pem", "weak_digest_sha1_intermediate.pem", | |
| 818 "weak_digest_sha1_ee.pem", false, false, false, false, false }, | |
| 819 #endif | |
| 820 { "weak_digest_md2_root.pem", "weak_digest_sha1_intermediate.pem", | |
| 821 "weak_digest_sha1_ee.pem", false, false, false, false, false }, | |
| 822 }; | |
| 823 INSTANTIATE_TEST_CASE_P(VerifyRoot, CertVerifyProcWeakDigestTest, | |
| 824 testing::ValuesIn(kVerifyRootCATestData)); | |
| 825 | |
| 826 // The signature algorithm of intermediates should be properly detected. | |
| 827 const WeakDigestTestData kVerifyIntermediateCATestData[] = { | |
| 828 { "weak_digest_sha1_root.pem", "weak_digest_md5_intermediate.pem", | |
| 829 "weak_digest_sha1_ee.pem", true, false, false, true, false }, | |
| 830 #if !defined(USE_NSS) && !defined(OS_MACOSX) // MD4 is not supported. | |
| 831 { "weak_digest_sha1_root.pem", "weak_digest_md4_intermediate.pem", | |
| 832 "weak_digest_sha1_ee.pem", false, true, false, false, false }, | |
| 833 #endif | |
| 834 #if !defined(USE_NSS) // MD2 is disabled by default. | |
| 835 { "weak_digest_sha1_root.pem", "weak_digest_md2_intermediate.pem", | |
| 836 "weak_digest_sha1_ee.pem", false, false, true, false, true }, | |
| 837 #endif | |
| 838 }; | |
| 839 INSTANTIATE_TEST_CASE_P(VerifyIntermediate, CertVerifyProcWeakDigestTest, | |
| 840 testing::ValuesIn(kVerifyIntermediateCATestData)); | |
| 841 | |
| 842 // The signature algorithm of end-entity should be properly detected. | |
| 843 const WeakDigestTestData kVerifyEndEntityTestData[] = { | |
| 844 { "weak_digest_sha1_root.pem", "weak_digest_sha1_intermediate.pem", | |
| 845 "weak_digest_md5_ee.pem", true, false, false, false, false }, | |
| 846 #if !defined(USE_NSS) && !defined(OS_MACOSX) // MD4 is not supported. | |
| 847 { "weak_digest_sha1_root.pem", "weak_digest_sha1_intermediate.pem", | |
| 848 "weak_digest_md4_ee.pem", false, true, false, false, false }, | |
| 849 #endif | |
| 850 #if !defined(USE_NSS) // MD2 is disabled by default. | |
| 851 { "weak_digest_sha1_root.pem", "weak_digest_sha1_intermediate.pem", | |
| 852 "weak_digest_md2_ee.pem", false, false, true, false, false }, | |
| 853 #endif | |
| 854 }; | |
| 855 // Disabled on NSS - NSS caches chains/signatures in such a way that cannot | |
| 856 // be cleared until NSS is cleanly shutdown, which is not presently supported | |
| 857 // in Chromium. | |
| 858 #if defined(USE_NSS) | |
| 859 #define MAYBE_VerifyEndEntity DISABLED_VerifyEndEntity | |
| 860 #else | |
| 861 #define MAYBE_VerifyEndEntity VerifyEndEntity | |
| 862 #endif | |
| 863 WRAPPED_INSTANTIATE_TEST_CASE_P(MAYBE_VerifyEndEntity, | |
| 864 CertVerifyProcWeakDigestTest, | |
| 865 testing::ValuesIn(kVerifyEndEntityTestData)); | |
| 866 | |
| 867 // Incomplete chains should still report the status of the intermediate. | |
| 868 const WeakDigestTestData kVerifyIncompleteIntermediateTestData[] = { | |
| 869 { NULL, "weak_digest_md5_intermediate.pem", "weak_digest_sha1_ee.pem", | |
| 870 true, false, false, true, false }, | |
| 871 #if !defined(OS_MACOSX) // MD4 is not supported. | |
| 872 { NULL, "weak_digest_md4_intermediate.pem", "weak_digest_sha1_ee.pem", | |
| 873 false, true, false, false, false }, | |
| 874 #endif | |
| 875 { NULL, "weak_digest_md2_intermediate.pem", "weak_digest_sha1_ee.pem", | |
| 876 false, false, true, false, true }, | |
| 877 }; | |
| 878 // Disabled on NSS - libpkix does not return constructed chains on error, | |
| 879 // preventing us from detecting/inspecting the verified chain. | |
| 880 #if defined(USE_NSS) | |
| 881 #define MAYBE_VerifyIncompleteIntermediate \ | |
| 882 DISABLED_VerifyIncompleteIntermediate | |
| 883 #else | |
| 884 #define MAYBE_VerifyIncompleteIntermediate VerifyIncompleteIntermediate | |
| 885 #endif | |
| 886 WRAPPED_INSTANTIATE_TEST_CASE_P( | |
| 887 MAYBE_VerifyIncompleteIntermediate, | |
| 888 CertVerifyProcWeakDigestTest, | |
| 889 testing::ValuesIn(kVerifyIncompleteIntermediateTestData)); | |
| 890 | |
| 891 // Incomplete chains should still report the status of the end-entity. | |
| 892 const WeakDigestTestData kVerifyIncompleteEETestData[] = { | |
| 893 { NULL, "weak_digest_sha1_intermediate.pem", "weak_digest_md5_ee.pem", | |
| 894 true, false, false, false, false }, | |
| 895 #if !defined(OS_MACOSX) // MD4 is not supported. | |
| 896 { NULL, "weak_digest_sha1_intermediate.pem", "weak_digest_md4_ee.pem", | |
| 897 false, true, false, false, false }, | |
| 898 #endif | |
| 899 { NULL, "weak_digest_sha1_intermediate.pem", "weak_digest_md2_ee.pem", | |
| 900 false, false, true, false, false }, | |
| 901 }; | |
| 902 // Disabled on NSS - libpkix does not return constructed chains on error, | |
| 903 // preventing us from detecting/inspecting the verified chain. | |
| 904 #if defined(USE_NSS) | |
| 905 #define MAYBE_VerifyIncompleteEndEntity DISABLED_VerifyIncompleteEndEntity | |
| 906 #else | |
| 907 #define MAYBE_VerifyIncompleteEndEntity VerifyIncompleteEndEntity | |
| 908 #endif | |
| 909 WRAPPED_INSTANTIATE_TEST_CASE_P( | |
| 910 MAYBE_VerifyIncompleteEndEntity, | |
| 911 CertVerifyProcWeakDigestTest, | |
| 912 testing::ValuesIn(kVerifyIncompleteEETestData)); | |
| 913 | |
| 914 // Differing algorithms between the intermediate and the EE should still be | |
| 915 // reported. | |
| 916 const WeakDigestTestData kVerifyMixedTestData[] = { | |
| 917 { "weak_digest_sha1_root.pem", "weak_digest_md5_intermediate.pem", | |
| 918 "weak_digest_md2_ee.pem", true, false, true, true, false }, | |
| 919 { "weak_digest_sha1_root.pem", "weak_digest_md2_intermediate.pem", | |
| 920 "weak_digest_md5_ee.pem", true, false, true, false, true }, | |
| 921 #if !defined(OS_MACOSX) // MD4 is not supported. | |
| 922 { "weak_digest_sha1_root.pem", "weak_digest_md4_intermediate.pem", | |
| 923 "weak_digest_md2_ee.pem", false, true, true, false, false }, | |
| 924 #endif | |
| 925 }; | |
| 926 // NSS does not support MD4 and does not enable MD2 by default, making all | |
| 927 // permutations invalid. | |
| 928 #if defined(USE_NSS) | |
| 929 #define MAYBE_VerifyMixed DISABLED_VerifyMixed | |
| 930 #else | |
| 931 #define MAYBE_VerifyMixed VerifyMixed | |
| 932 #endif | |
| 933 WRAPPED_INSTANTIATE_TEST_CASE_P( | |
| 934 MAYBE_VerifyMixed, | |
| 935 CertVerifyProcWeakDigestTest, | |
| 936 testing::ValuesIn(kVerifyMixedTestData)); | |
| 937 | |
| 938 } // namespace net | |
| OLD | NEW |