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 "net/cert/cert_verify_proc.h" | |
6 | |
7 #include <vector> | |
8 | |
9 #include "base/callback_helpers.h" | |
10 #include "base/files/file_path.h" | |
11 #include "base/files/file_util.h" | |
12 #include "base/logging.h" | |
13 #include "base/sha1.h" | |
14 #include "base/strings/string_number_conversions.h" | |
15 #include "crypto/sha2.h" | |
16 #include "net/base/net_errors.h" | |
17 #include "net/base/test_data_directory.h" | |
18 #include "net/cert/asn1_util.h" | |
19 #include "net/cert/cert_status_flags.h" | |
20 #include "net/cert/cert_verifier.h" | |
21 #include "net/cert/cert_verify_result.h" | |
22 #include "net/cert/crl_set.h" | |
23 #include "net/cert/crl_set_storage.h" | |
24 #include "net/cert/test_root_certs.h" | |
25 #include "net/cert/x509_certificate.h" | |
26 #include "net/test/cert_test_util.h" | |
27 #include "net/test/test_certificate_data.h" | |
28 #include "testing/gtest/include/gtest/gtest.h" | |
29 | |
30 #if defined(OS_WIN) | |
31 #include "base/win/windows_version.h" | |
32 #elif defined(OS_ANDROID) | |
33 #include "base/android/build_info.h" | |
34 #endif | |
35 | |
36 using base::HexEncode; | |
37 | |
38 namespace net { | |
39 | |
40 namespace { | |
41 | |
42 // A certificate for www.paypal.com with a NULL byte in the common name. | |
43 // From http://www.gossamer-threads.com/lists/fulldisc/full-disclosure/70363 | |
44 unsigned char paypal_null_fingerprint[] = { | |
45 0x4c, 0x88, 0x9e, 0x28, 0xd7, 0x7a, 0x44, 0x1e, 0x13, 0xf2, 0x6a, 0xba, | |
46 0x1f, 0xe8, 0x1b, 0xd6, 0xab, 0x7b, 0xe8, 0xd7 | |
47 }; | |
48 | |
49 // Mock CertVerifyProc that will set |verify_result->is_issued_by_known_root| | |
50 // for all certificates that are Verified. | |
51 class WellKnownCaCertVerifyProc : public CertVerifyProc { | |
52 public: | |
53 // Initialize a CertVerifyProc that will set | |
54 // |verify_result->is_issued_by_known_root| to |is_well_known|. | |
55 explicit WellKnownCaCertVerifyProc(bool is_well_known) | |
56 : is_well_known_(is_well_known) {} | |
57 | |
58 // CertVerifyProc implementation: | |
59 bool SupportsAdditionalTrustAnchors() const override { return false; } | |
60 | |
61 protected: | |
62 ~WellKnownCaCertVerifyProc() override {} | |
63 | |
64 private: | |
65 int VerifyInternal(X509Certificate* cert, | |
66 const std::string& hostname, | |
67 int flags, | |
68 CRLSet* crl_set, | |
69 const CertificateList& additional_trust_anchors, | |
70 CertVerifyResult* verify_result) override; | |
71 | |
72 const bool is_well_known_; | |
73 | |
74 DISALLOW_COPY_AND_ASSIGN(WellKnownCaCertVerifyProc); | |
75 }; | |
76 | |
77 int WellKnownCaCertVerifyProc::VerifyInternal( | |
78 X509Certificate* cert, | |
79 const std::string& hostname, | |
80 int flags, | |
81 CRLSet* crl_set, | |
82 const CertificateList& additional_trust_anchors, | |
83 CertVerifyResult* verify_result) { | |
84 verify_result->is_issued_by_known_root = is_well_known_; | |
85 return OK; | |
86 } | |
87 | |
88 bool SupportsReturningVerifiedChain() { | |
89 #if defined(OS_ANDROID) | |
90 // Before API level 17, Android does not expose the APIs necessary to get at | |
91 // the verified certificate chain. | |
92 if (base::android::BuildInfo::GetInstance()->sdk_int() < 17) | |
93 return false; | |
94 #endif | |
95 return true; | |
96 } | |
97 | |
98 bool SupportsDetectingKnownRoots() { | |
99 #if defined(OS_ANDROID) | |
100 // Before API level 17, Android does not expose the APIs necessary to get at | |
101 // the verified certificate chain and detect known roots. | |
102 if (base::android::BuildInfo::GetInstance()->sdk_int() < 17) | |
103 return false; | |
104 #endif | |
105 return true; | |
106 } | |
107 | |
108 } // namespace | |
109 | |
110 class CertVerifyProcTest : public testing::Test { | |
111 public: | |
112 CertVerifyProcTest() | |
113 : verify_proc_(CertVerifyProc::CreateDefault()) { | |
114 } | |
115 ~CertVerifyProcTest() override {} | |
116 | |
117 protected: | |
118 bool SupportsAdditionalTrustAnchors() { | |
119 return verify_proc_->SupportsAdditionalTrustAnchors(); | |
120 } | |
121 | |
122 int Verify(X509Certificate* cert, | |
123 const std::string& hostname, | |
124 int flags, | |
125 CRLSet* crl_set, | |
126 const CertificateList& additional_trust_anchors, | |
127 CertVerifyResult* verify_result) { | |
128 return verify_proc_->Verify(cert, hostname, flags, crl_set, | |
129 additional_trust_anchors, verify_result); | |
130 } | |
131 | |
132 const CertificateList empty_cert_list_; | |
133 scoped_refptr<CertVerifyProc> verify_proc_; | |
134 }; | |
135 | |
136 TEST_F(CertVerifyProcTest, DISABLED_WithoutRevocationChecking) { | |
137 // Check that verification without revocation checking works. | |
138 CertificateList certs = CreateCertificateListFromFile( | |
139 GetTestCertsDirectory(), | |
140 "googlenew.chain.pem", | |
141 X509Certificate::FORMAT_PEM_CERT_SEQUENCE); | |
142 | |
143 X509Certificate::OSCertHandles intermediates; | |
144 intermediates.push_back(certs[1]->os_cert_handle()); | |
145 | |
146 scoped_refptr<X509Certificate> google_full_chain = | |
147 X509Certificate::CreateFromHandle(certs[0]->os_cert_handle(), | |
148 intermediates); | |
149 | |
150 CertVerifyResult verify_result; | |
151 EXPECT_EQ(OK, | |
152 Verify(google_full_chain.get(), | |
153 "www.google.com", | |
154 0 /* flags */, | |
155 NULL, | |
156 empty_cert_list_, | |
157 &verify_result)); | |
158 } | |
159 | |
160 #if defined(OS_ANDROID) || defined(USE_OPENSSL_CERTS) | |
161 // TODO(jnd): http://crbug.com/117478 - EV verification is not yet supported. | |
162 #define MAYBE_EVVerification DISABLED_EVVerification | |
163 #else | |
164 #define MAYBE_EVVerification EVVerification | |
165 #endif | |
166 TEST_F(CertVerifyProcTest, MAYBE_EVVerification) { | |
167 CertificateList certs = CreateCertificateListFromFile( | |
168 GetTestCertsDirectory(), | |
169 "comodo.chain.pem", | |
170 X509Certificate::FORMAT_PEM_CERT_SEQUENCE); | |
171 ASSERT_EQ(3U, certs.size()); | |
172 | |
173 X509Certificate::OSCertHandles intermediates; | |
174 intermediates.push_back(certs[1]->os_cert_handle()); | |
175 intermediates.push_back(certs[2]->os_cert_handle()); | |
176 | |
177 scoped_refptr<X509Certificate> comodo_chain = | |
178 X509Certificate::CreateFromHandle(certs[0]->os_cert_handle(), | |
179 intermediates); | |
180 | |
181 scoped_refptr<CRLSet> crl_set(CRLSet::ForTesting(false, NULL, "")); | |
182 CertVerifyResult verify_result; | |
183 int flags = CertVerifier::VERIFY_EV_CERT; | |
184 int error = Verify(comodo_chain.get(), | |
185 "comodo.com", | |
186 flags, | |
187 crl_set.get(), | |
188 empty_cert_list_, | |
189 &verify_result); | |
190 EXPECT_EQ(OK, error); | |
191 EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_IS_EV); | |
192 } | |
193 | |
194 TEST_F(CertVerifyProcTest, PaypalNullCertParsing) { | |
195 scoped_refptr<X509Certificate> paypal_null_cert( | |
196 X509Certificate::CreateFromBytes( | |
197 reinterpret_cast<const char*>(paypal_null_der), | |
198 sizeof(paypal_null_der))); | |
199 | |
200 ASSERT_NE(static_cast<X509Certificate*>(NULL), paypal_null_cert.get()); | |
201 | |
202 const SHA1HashValue& fingerprint = | |
203 paypal_null_cert->fingerprint(); | |
204 for (size_t i = 0; i < 20; ++i) | |
205 EXPECT_EQ(paypal_null_fingerprint[i], fingerprint.data[i]); | |
206 | |
207 int flags = 0; | |
208 CertVerifyResult verify_result; | |
209 int error = Verify(paypal_null_cert.get(), | |
210 "www.paypal.com", | |
211 flags, | |
212 NULL, | |
213 empty_cert_list_, | |
214 &verify_result); | |
215 #if defined(USE_NSS) || defined(OS_IOS) || defined(OS_ANDROID) | |
216 EXPECT_EQ(ERR_CERT_COMMON_NAME_INVALID, error); | |
217 #else | |
218 // TOOD(bulach): investigate why macosx and win aren't returning | |
219 // ERR_CERT_INVALID or ERR_CERT_COMMON_NAME_INVALID. | |
220 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, error); | |
221 #endif | |
222 // Either the system crypto library should correctly report a certificate | |
223 // name mismatch, or our certificate blacklist should cause us to report an | |
224 // invalid certificate. | |
225 #if defined(USE_NSS) || defined(OS_WIN) || defined(OS_IOS) | |
226 EXPECT_TRUE(verify_result.cert_status & | |
227 (CERT_STATUS_COMMON_NAME_INVALID | CERT_STATUS_INVALID)); | |
228 #endif | |
229 } | |
230 | |
231 // A regression test for http://crbug.com/31497. | |
232 #if defined(OS_ANDROID) | |
233 // Disabled on Android, as the Android verification libraries require an | |
234 // explicit policy to be specified, even when anyPolicy is permitted. | |
235 #define MAYBE_IntermediateCARequireExplicitPolicy \ | |
236 DISABLED_IntermediateCARequireExplicitPolicy | |
237 #else | |
238 #define MAYBE_IntermediateCARequireExplicitPolicy \ | |
239 IntermediateCARequireExplicitPolicy | |
240 #endif | |
241 TEST_F(CertVerifyProcTest, MAYBE_IntermediateCARequireExplicitPolicy) { | |
242 base::FilePath certs_dir = GetTestCertsDirectory(); | |
243 | |
244 CertificateList certs = CreateCertificateListFromFile( | |
245 certs_dir, "explicit-policy-chain.pem", | |
246 X509Certificate::FORMAT_AUTO); | |
247 ASSERT_EQ(3U, certs.size()); | |
248 | |
249 X509Certificate::OSCertHandles intermediates; | |
250 intermediates.push_back(certs[1]->os_cert_handle()); | |
251 | |
252 scoped_refptr<X509Certificate> cert = | |
253 X509Certificate::CreateFromHandle(certs[0]->os_cert_handle(), | |
254 intermediates); | |
255 ASSERT_TRUE(cert.get()); | |
256 | |
257 ScopedTestRoot scoped_root(certs[2].get()); | |
258 | |
259 int flags = 0; | |
260 CertVerifyResult verify_result; | |
261 int error = Verify(cert.get(), | |
262 "policy_test.example", | |
263 flags, | |
264 NULL, | |
265 empty_cert_list_, | |
266 &verify_result); | |
267 EXPECT_EQ(OK, error); | |
268 EXPECT_EQ(0u, verify_result.cert_status); | |
269 } | |
270 | |
271 // Test for bug 58437. | |
272 // This certificate will expire on 2011-12-21. The test will still | |
273 // pass if error == ERR_CERT_DATE_INVALID. | |
274 // This test is DISABLED because it appears that we cannot do | |
275 // certificate revocation checking when running all of the net unit tests. | |
276 // This test passes when run individually, but when run with all of the net | |
277 // unit tests, the call to PKIXVerifyCert returns the NSS error -8180, which is | |
278 // SEC_ERROR_REVOKED_CERTIFICATE. This indicates a lack of revocation | |
279 // status, i.e. that the revocation check is failing for some reason. | |
280 TEST_F(CertVerifyProcTest, DISABLED_GlobalSignR3EVTest) { | |
281 base::FilePath certs_dir = GetTestCertsDirectory(); | |
282 | |
283 scoped_refptr<X509Certificate> server_cert = | |
284 ImportCertFromFile(certs_dir, "2029_globalsign_com_cert.pem"); | |
285 ASSERT_NE(static_cast<X509Certificate*>(NULL), server_cert.get()); | |
286 | |
287 scoped_refptr<X509Certificate> intermediate_cert = | |
288 ImportCertFromFile(certs_dir, "globalsign_ev_sha256_ca_cert.pem"); | |
289 ASSERT_NE(static_cast<X509Certificate*>(NULL), intermediate_cert.get()); | |
290 | |
291 X509Certificate::OSCertHandles intermediates; | |
292 intermediates.push_back(intermediate_cert->os_cert_handle()); | |
293 scoped_refptr<X509Certificate> cert_chain = | |
294 X509Certificate::CreateFromHandle(server_cert->os_cert_handle(), | |
295 intermediates); | |
296 | |
297 CertVerifyResult verify_result; | |
298 int flags = CertVerifier::VERIFY_REV_CHECKING_ENABLED | | |
299 CertVerifier::VERIFY_EV_CERT; | |
300 int error = Verify(cert_chain.get(), | |
301 "2029.globalsign.com", | |
302 flags, | |
303 NULL, | |
304 empty_cert_list_, | |
305 &verify_result); | |
306 if (error == OK) | |
307 EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_IS_EV); | |
308 else | |
309 EXPECT_EQ(ERR_CERT_DATE_INVALID, error); | |
310 } | |
311 | |
312 // Test that verifying an ECDSA certificate doesn't crash on XP. (See | |
313 // crbug.com/144466). | |
314 TEST_F(CertVerifyProcTest, ECDSA_RSA) { | |
315 base::FilePath certs_dir = GetTestCertsDirectory(); | |
316 | |
317 scoped_refptr<X509Certificate> cert = | |
318 ImportCertFromFile(certs_dir, | |
319 "prime256v1-ecdsa-ee-by-1024-rsa-intermediate.pem"); | |
320 | |
321 CertVerifyResult verify_result; | |
322 Verify(cert.get(), "127.0.0.1", 0, NULL, empty_cert_list_, &verify_result); | |
323 | |
324 // We don't check verify_result because the certificate is signed by an | |
325 // unknown CA and will be considered invalid on XP because of the ECDSA | |
326 // public key. | |
327 } | |
328 | |
329 // Currently, only RSA and DSA keys are checked for weakness, and our example | |
330 // weak size is 768. These could change in the future. | |
331 // | |
332 // Note that this means there may be false negatives: keys for other | |
333 // algorithms and which are weak will pass this test. | |
334 static bool IsWeakKeyType(const std::string& key_type) { | |
335 size_t pos = key_type.find("-"); | |
336 std::string size = key_type.substr(0, pos); | |
337 std::string type = key_type.substr(pos + 1); | |
338 | |
339 if (type == "rsa" || type == "dsa") | |
340 return size == "768"; | |
341 | |
342 return false; | |
343 } | |
344 | |
345 TEST_F(CertVerifyProcTest, RejectWeakKeys) { | |
346 base::FilePath certs_dir = GetTestCertsDirectory(); | |
347 typedef std::vector<std::string> Strings; | |
348 Strings key_types; | |
349 | |
350 // generate-weak-test-chains.sh currently has: | |
351 // key_types="768-rsa 1024-rsa 2048-rsa prime256v1-ecdsa" | |
352 // We must use the same key types here. The filenames generated look like: | |
353 // 2048-rsa-ee-by-768-rsa-intermediate.pem | |
354 key_types.push_back("768-rsa"); | |
355 key_types.push_back("1024-rsa"); | |
356 key_types.push_back("2048-rsa"); | |
357 | |
358 bool use_ecdsa = true; | |
359 #if defined(OS_WIN) | |
360 use_ecdsa = base::win::GetVersion() > base::win::VERSION_XP; | |
361 #endif | |
362 | |
363 if (use_ecdsa) | |
364 key_types.push_back("prime256v1-ecdsa"); | |
365 | |
366 // Add the root that signed the intermediates for this test. | |
367 scoped_refptr<X509Certificate> root_cert = | |
368 ImportCertFromFile(certs_dir, "2048-rsa-root.pem"); | |
369 ASSERT_NE(static_cast<X509Certificate*>(NULL), root_cert.get()); | |
370 ScopedTestRoot scoped_root(root_cert.get()); | |
371 | |
372 // Now test each chain. | |
373 for (Strings::const_iterator ee_type = key_types.begin(); | |
374 ee_type != key_types.end(); ++ee_type) { | |
375 for (Strings::const_iterator signer_type = key_types.begin(); | |
376 signer_type != key_types.end(); ++signer_type) { | |
377 std::string basename = *ee_type + "-ee-by-" + *signer_type + | |
378 "-intermediate.pem"; | |
379 SCOPED_TRACE(basename); | |
380 scoped_refptr<X509Certificate> ee_cert = | |
381 ImportCertFromFile(certs_dir, basename); | |
382 ASSERT_NE(static_cast<X509Certificate*>(NULL), ee_cert.get()); | |
383 | |
384 basename = *signer_type + "-intermediate.pem"; | |
385 scoped_refptr<X509Certificate> intermediate = | |
386 ImportCertFromFile(certs_dir, basename); | |
387 ASSERT_NE(static_cast<X509Certificate*>(NULL), intermediate.get()); | |
388 | |
389 X509Certificate::OSCertHandles intermediates; | |
390 intermediates.push_back(intermediate->os_cert_handle()); | |
391 scoped_refptr<X509Certificate> cert_chain = | |
392 X509Certificate::CreateFromHandle(ee_cert->os_cert_handle(), | |
393 intermediates); | |
394 | |
395 CertVerifyResult verify_result; | |
396 int error = Verify(cert_chain.get(), | |
397 "127.0.0.1", | |
398 0, | |
399 NULL, | |
400 empty_cert_list_, | |
401 &verify_result); | |
402 | |
403 if (IsWeakKeyType(*ee_type) || IsWeakKeyType(*signer_type)) { | |
404 EXPECT_NE(OK, error); | |
405 EXPECT_EQ(CERT_STATUS_WEAK_KEY, | |
406 verify_result.cert_status & CERT_STATUS_WEAK_KEY); | |
407 EXPECT_NE(CERT_STATUS_INVALID, | |
408 verify_result.cert_status & CERT_STATUS_INVALID); | |
409 } else { | |
410 EXPECT_EQ(OK, error); | |
411 EXPECT_EQ(0U, verify_result.cert_status & CERT_STATUS_WEAK_KEY); | |
412 } | |
413 } | |
414 } | |
415 } | |
416 | |
417 // Regression test for http://crbug.com/108514. | |
418 #if defined(OS_MACOSX) && !defined(OS_IOS) | |
419 // Disabled on OS X - Security.framework doesn't ignore superflous certificates | |
420 // provided by servers. See CertVerifyProcTest.CybertrustGTERoot for further | |
421 // details. | |
422 #define MAYBE_ExtraneousMD5RootCert DISABLED_ExtraneousMD5RootCert | |
423 #else | |
424 #define MAYBE_ExtraneousMD5RootCert ExtraneousMD5RootCert | |
425 #endif | |
426 TEST_F(CertVerifyProcTest, MAYBE_ExtraneousMD5RootCert) { | |
427 if (!SupportsReturningVerifiedChain()) { | |
428 LOG(INFO) << "Skipping this test in this platform."; | |
429 return; | |
430 } | |
431 | |
432 base::FilePath certs_dir = GetTestCertsDirectory(); | |
433 | |
434 scoped_refptr<X509Certificate> server_cert = | |
435 ImportCertFromFile(certs_dir, "cross-signed-leaf.pem"); | |
436 ASSERT_NE(static_cast<X509Certificate*>(NULL), server_cert.get()); | |
437 | |
438 scoped_refptr<X509Certificate> extra_cert = | |
439 ImportCertFromFile(certs_dir, "cross-signed-root-md5.pem"); | |
440 ASSERT_NE(static_cast<X509Certificate*>(NULL), extra_cert.get()); | |
441 | |
442 scoped_refptr<X509Certificate> root_cert = | |
443 ImportCertFromFile(certs_dir, "cross-signed-root-sha1.pem"); | |
444 ASSERT_NE(static_cast<X509Certificate*>(NULL), root_cert.get()); | |
445 | |
446 ScopedTestRoot scoped_root(root_cert.get()); | |
447 | |
448 X509Certificate::OSCertHandles intermediates; | |
449 intermediates.push_back(extra_cert->os_cert_handle()); | |
450 scoped_refptr<X509Certificate> cert_chain = | |
451 X509Certificate::CreateFromHandle(server_cert->os_cert_handle(), | |
452 intermediates); | |
453 | |
454 CertVerifyResult verify_result; | |
455 int flags = 0; | |
456 int error = Verify(cert_chain.get(), | |
457 "127.0.0.1", | |
458 flags, | |
459 NULL, | |
460 empty_cert_list_, | |
461 &verify_result); | |
462 EXPECT_EQ(OK, error); | |
463 | |
464 // The extra MD5 root should be discarded | |
465 ASSERT_TRUE(verify_result.verified_cert.get()); | |
466 ASSERT_EQ(1u, | |
467 verify_result.verified_cert->GetIntermediateCertificates().size()); | |
468 EXPECT_TRUE(X509Certificate::IsSameOSCert( | |
469 verify_result.verified_cert->GetIntermediateCertificates().front(), | |
470 root_cert->os_cert_handle())); | |
471 | |
472 EXPECT_FALSE(verify_result.has_md5); | |
473 } | |
474 | |
475 // Test for bug 94673. | |
476 TEST_F(CertVerifyProcTest, GoogleDigiNotarTest) { | |
477 base::FilePath certs_dir = GetTestCertsDirectory(); | |
478 | |
479 scoped_refptr<X509Certificate> server_cert = | |
480 ImportCertFromFile(certs_dir, "google_diginotar.pem"); | |
481 ASSERT_NE(static_cast<X509Certificate*>(NULL), server_cert.get()); | |
482 | |
483 scoped_refptr<X509Certificate> intermediate_cert = | |
484 ImportCertFromFile(certs_dir, "diginotar_public_ca_2025.pem"); | |
485 ASSERT_NE(static_cast<X509Certificate*>(NULL), intermediate_cert.get()); | |
486 | |
487 X509Certificate::OSCertHandles intermediates; | |
488 intermediates.push_back(intermediate_cert->os_cert_handle()); | |
489 scoped_refptr<X509Certificate> cert_chain = | |
490 X509Certificate::CreateFromHandle(server_cert->os_cert_handle(), | |
491 intermediates); | |
492 | |
493 CertVerifyResult verify_result; | |
494 int flags = CertVerifier::VERIFY_REV_CHECKING_ENABLED; | |
495 int error = Verify(cert_chain.get(), | |
496 "mail.google.com", | |
497 flags, | |
498 NULL, | |
499 empty_cert_list_, | |
500 &verify_result); | |
501 EXPECT_NE(OK, error); | |
502 | |
503 // Now turn off revocation checking. Certificate verification should still | |
504 // fail. | |
505 flags = 0; | |
506 error = Verify(cert_chain.get(), | |
507 "mail.google.com", | |
508 flags, | |
509 NULL, | |
510 empty_cert_list_, | |
511 &verify_result); | |
512 EXPECT_NE(OK, error); | |
513 } | |
514 | |
515 TEST_F(CertVerifyProcTest, DigiNotarCerts) { | |
516 static const char* const kDigiNotarFilenames[] = { | |
517 "diginotar_root_ca.pem", | |
518 "diginotar_cyber_ca.pem", | |
519 "diginotar_services_1024_ca.pem", | |
520 "diginotar_pkioverheid.pem", | |
521 "diginotar_pkioverheid_g2.pem", | |
522 NULL, | |
523 }; | |
524 | |
525 base::FilePath certs_dir = GetTestCertsDirectory(); | |
526 | |
527 for (size_t i = 0; kDigiNotarFilenames[i]; i++) { | |
528 scoped_refptr<X509Certificate> diginotar_cert = | |
529 ImportCertFromFile(certs_dir, kDigiNotarFilenames[i]); | |
530 std::string der_bytes; | |
531 ASSERT_TRUE(X509Certificate::GetDEREncoded( | |
532 diginotar_cert->os_cert_handle(), &der_bytes)); | |
533 | |
534 base::StringPiece spki; | |
535 ASSERT_TRUE(asn1::ExtractSPKIFromDERCert(der_bytes, &spki)); | |
536 | |
537 std::string spki_sha1 = base::SHA1HashString(spki.as_string()); | |
538 | |
539 HashValueVector public_keys; | |
540 HashValue hash(HASH_VALUE_SHA1); | |
541 ASSERT_EQ(hash.size(), spki_sha1.size()); | |
542 memcpy(hash.data(), spki_sha1.data(), spki_sha1.size()); | |
543 public_keys.push_back(hash); | |
544 | |
545 EXPECT_TRUE(CertVerifyProc::IsPublicKeyBlacklisted(public_keys)) << | |
546 "Public key not blocked for " << kDigiNotarFilenames[i]; | |
547 } | |
548 } | |
549 | |
550 TEST_F(CertVerifyProcTest, NameConstraintsOk) { | |
551 CertificateList ca_cert_list = | |
552 CreateCertificateListFromFile(GetTestCertsDirectory(), | |
553 "root_ca_cert.pem", | |
554 X509Certificate::FORMAT_AUTO); | |
555 ASSERT_EQ(1U, ca_cert_list.size()); | |
556 ScopedTestRoot test_root(ca_cert_list[0].get()); | |
557 | |
558 CertificateList cert_list = CreateCertificateListFromFile( | |
559 GetTestCertsDirectory(), "name_constraint_good.pem", | |
560 X509Certificate::FORMAT_AUTO); | |
561 ASSERT_EQ(1U, cert_list.size()); | |
562 | |
563 X509Certificate::OSCertHandles intermediates; | |
564 scoped_refptr<X509Certificate> leaf = | |
565 X509Certificate::CreateFromHandle(cert_list[0]->os_cert_handle(), | |
566 intermediates); | |
567 | |
568 int flags = 0; | |
569 CertVerifyResult verify_result; | |
570 int error = Verify(leaf.get(), | |
571 "test.example.com", | |
572 flags, | |
573 NULL, | |
574 empty_cert_list_, | |
575 &verify_result); | |
576 EXPECT_EQ(OK, error); | |
577 EXPECT_EQ(0U, verify_result.cert_status); | |
578 } | |
579 | |
580 TEST_F(CertVerifyProcTest, NameConstraintsFailure) { | |
581 if (!SupportsReturningVerifiedChain()) { | |
582 LOG(INFO) << "Skipping this test in this platform."; | |
583 return; | |
584 } | |
585 | |
586 CertificateList ca_cert_list = | |
587 CreateCertificateListFromFile(GetTestCertsDirectory(), | |
588 "root_ca_cert.pem", | |
589 X509Certificate::FORMAT_AUTO); | |
590 ASSERT_EQ(1U, ca_cert_list.size()); | |
591 ScopedTestRoot test_root(ca_cert_list[0].get()); | |
592 | |
593 CertificateList cert_list = CreateCertificateListFromFile( | |
594 GetTestCertsDirectory(), "name_constraint_bad.pem", | |
595 X509Certificate::FORMAT_AUTO); | |
596 ASSERT_EQ(1U, cert_list.size()); | |
597 | |
598 X509Certificate::OSCertHandles intermediates; | |
599 scoped_refptr<X509Certificate> leaf = | |
600 X509Certificate::CreateFromHandle(cert_list[0]->os_cert_handle(), | |
601 intermediates); | |
602 | |
603 int flags = 0; | |
604 CertVerifyResult verify_result; | |
605 int error = Verify(leaf.get(), | |
606 "test.example.com", | |
607 flags, | |
608 NULL, | |
609 empty_cert_list_, | |
610 &verify_result); | |
611 EXPECT_EQ(ERR_CERT_NAME_CONSTRAINT_VIOLATION, error); | |
612 EXPECT_EQ(CERT_STATUS_NAME_CONSTRAINT_VIOLATION, | |
613 verify_result.cert_status & CERT_STATUS_NAME_CONSTRAINT_VIOLATION); | |
614 } | |
615 | |
616 TEST_F(CertVerifyProcTest, TestHasTooLongValidity) { | |
617 struct { | |
618 const char* const file; | |
619 bool is_valid_too_long; | |
620 } tests[] = { | |
621 {"twitter-chain.pem", false}, | |
622 {"start_after_expiry.pem", true}, | |
623 {"pre_br_validity_ok.pem", false}, | |
624 {"pre_br_validity_bad_121.pem", true}, | |
625 {"pre_br_validity_bad_2020.pem", true}, | |
626 {"10_year_validity.pem", false}, | |
627 {"11_year_validity.pem", true}, | |
628 {"39_months_after_2015_04.pem", false}, | |
629 {"40_months_after_2015_04.pem", true}, | |
630 {"60_months_after_2012_07.pem", false}, | |
631 {"61_months_after_2012_07.pem", true}, | |
632 }; | |
633 | |
634 base::FilePath certs_dir = GetTestCertsDirectory(); | |
635 | |
636 for (size_t i = 0; i < arraysize(tests); ++i) { | |
637 scoped_refptr<X509Certificate> certificate = | |
638 ImportCertFromFile(certs_dir, tests[i].file); | |
639 SCOPED_TRACE(tests[i].file); | |
640 ASSERT_TRUE(certificate); | |
641 EXPECT_EQ(tests[i].is_valid_too_long, | |
642 CertVerifyProc::HasTooLongValidity(*certificate)); | |
643 } | |
644 } | |
645 | |
646 TEST_F(CertVerifyProcTest, TestKnownRoot) { | |
647 if (!SupportsDetectingKnownRoots()) { | |
648 LOG(INFO) << "Skipping this test on this platform."; | |
649 return; | |
650 } | |
651 | |
652 base::FilePath certs_dir = GetTestCertsDirectory(); | |
653 CertificateList certs = CreateCertificateListFromFile( | |
654 certs_dir, "twitter-chain.pem", X509Certificate::FORMAT_AUTO); | |
655 ASSERT_EQ(3U, certs.size()); | |
656 | |
657 X509Certificate::OSCertHandles intermediates; | |
658 intermediates.push_back(certs[1]->os_cert_handle()); | |
659 | |
660 scoped_refptr<X509Certificate> cert_chain = | |
661 X509Certificate::CreateFromHandle(certs[0]->os_cert_handle(), | |
662 intermediates); | |
663 | |
664 int flags = 0; | |
665 CertVerifyResult verify_result; | |
666 // This will blow up, May 9th, 2016. Sorry! Please disable and file a bug | |
667 // against agl. See also PublicKeyHashes. | |
668 int error = Verify(cert_chain.get(), "twitter.com", flags, NULL, | |
669 empty_cert_list_, &verify_result); | |
670 EXPECT_EQ(OK, error); | |
671 EXPECT_TRUE(verify_result.is_issued_by_known_root); | |
672 } | |
673 | |
674 TEST_F(CertVerifyProcTest, PublicKeyHashes) { | |
675 if (!SupportsReturningVerifiedChain()) { | |
676 LOG(INFO) << "Skipping this test in this platform."; | |
677 return; | |
678 } | |
679 | |
680 base::FilePath certs_dir = GetTestCertsDirectory(); | |
681 CertificateList certs = CreateCertificateListFromFile( | |
682 certs_dir, "twitter-chain.pem", X509Certificate::FORMAT_AUTO); | |
683 ASSERT_EQ(3U, certs.size()); | |
684 | |
685 X509Certificate::OSCertHandles intermediates; | |
686 intermediates.push_back(certs[1]->os_cert_handle()); | |
687 | |
688 scoped_refptr<X509Certificate> cert_chain = | |
689 X509Certificate::CreateFromHandle(certs[0]->os_cert_handle(), | |
690 intermediates); | |
691 int flags = 0; | |
692 CertVerifyResult verify_result; | |
693 | |
694 // This will blow up, May 9th, 2016. Sorry! Please disable and file a bug | |
695 // against agl. See also TestKnownRoot. | |
696 int error = Verify(cert_chain.get(), "twitter.com", flags, NULL, | |
697 empty_cert_list_, &verify_result); | |
698 EXPECT_EQ(OK, error); | |
699 ASSERT_LE(3U, verify_result.public_key_hashes.size()); | |
700 | |
701 HashValueVector sha1_hashes; | |
702 for (size_t i = 0; i < verify_result.public_key_hashes.size(); ++i) { | |
703 if (verify_result.public_key_hashes[i].tag != HASH_VALUE_SHA1) | |
704 continue; | |
705 sha1_hashes.push_back(verify_result.public_key_hashes[i]); | |
706 } | |
707 ASSERT_LE(3u, sha1_hashes.size()); | |
708 | |
709 for (size_t i = 0; i < 3; ++i) { | |
710 EXPECT_EQ(HexEncode(kTwitterSPKIs[i], base::kSHA1Length), | |
711 HexEncode(sha1_hashes[i].data(), base::kSHA1Length)); | |
712 } | |
713 | |
714 HashValueVector sha256_hashes; | |
715 for (size_t i = 0; i < verify_result.public_key_hashes.size(); ++i) { | |
716 if (verify_result.public_key_hashes[i].tag != HASH_VALUE_SHA256) | |
717 continue; | |
718 sha256_hashes.push_back(verify_result.public_key_hashes[i]); | |
719 } | |
720 ASSERT_LE(3u, sha256_hashes.size()); | |
721 | |
722 for (size_t i = 0; i < 3; ++i) { | |
723 EXPECT_EQ(HexEncode(kTwitterSPKIsSHA256[i], crypto::kSHA256Length), | |
724 HexEncode(sha256_hashes[i].data(), crypto::kSHA256Length)); | |
725 } | |
726 } | |
727 | |
728 // A regression test for http://crbug.com/70293. | |
729 // The Key Usage extension in this RSA SSL server certificate does not have | |
730 // the keyEncipherment bit. | |
731 TEST_F(CertVerifyProcTest, InvalidKeyUsage) { | |
732 base::FilePath certs_dir = GetTestCertsDirectory(); | |
733 | |
734 scoped_refptr<X509Certificate> server_cert = | |
735 ImportCertFromFile(certs_dir, "invalid_key_usage_cert.der"); | |
736 ASSERT_NE(static_cast<X509Certificate*>(NULL), server_cert.get()); | |
737 | |
738 int flags = 0; | |
739 CertVerifyResult verify_result; | |
740 int error = Verify(server_cert.get(), | |
741 "jira.aquameta.com", | |
742 flags, | |
743 NULL, | |
744 empty_cert_list_, | |
745 &verify_result); | |
746 #if defined(USE_OPENSSL_CERTS) && !defined(OS_ANDROID) | |
747 // This certificate has two errors: "invalid key usage" and "untrusted CA". | |
748 // However, OpenSSL returns only one (the latter), and we can't detect | |
749 // the other errors. | |
750 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, error); | |
751 #else | |
752 EXPECT_EQ(ERR_CERT_INVALID, error); | |
753 EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_INVALID); | |
754 #endif | |
755 // TODO(wtc): fix http://crbug.com/75520 to get all the certificate errors | |
756 // from NSS. | |
757 #if !defined(USE_NSS) && !defined(OS_IOS) && !defined(OS_ANDROID) | |
758 // The certificate is issued by an unknown CA. | |
759 EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_AUTHORITY_INVALID); | |
760 #endif | |
761 } | |
762 | |
763 // Basic test for returning the chain in CertVerifyResult. Note that the | |
764 // returned chain may just be a reflection of the originally supplied chain; | |
765 // that is, if any errors occur, the default chain returned is an exact copy | |
766 // of the certificate to be verified. The remaining VerifyReturn* tests are | |
767 // used to ensure that the actual, verified chain is being returned by | |
768 // Verify(). | |
769 TEST_F(CertVerifyProcTest, VerifyReturnChainBasic) { | |
770 if (!SupportsReturningVerifiedChain()) { | |
771 LOG(INFO) << "Skipping this test in this platform."; | |
772 return; | |
773 } | |
774 | |
775 base::FilePath certs_dir = GetTestCertsDirectory(); | |
776 CertificateList certs = CreateCertificateListFromFile( | |
777 certs_dir, "x509_verify_results.chain.pem", | |
778 X509Certificate::FORMAT_AUTO); | |
779 ASSERT_EQ(3U, certs.size()); | |
780 | |
781 X509Certificate::OSCertHandles intermediates; | |
782 intermediates.push_back(certs[1]->os_cert_handle()); | |
783 intermediates.push_back(certs[2]->os_cert_handle()); | |
784 | |
785 ScopedTestRoot scoped_root(certs[2].get()); | |
786 | |
787 scoped_refptr<X509Certificate> google_full_chain = | |
788 X509Certificate::CreateFromHandle(certs[0]->os_cert_handle(), | |
789 intermediates); | |
790 ASSERT_NE(static_cast<X509Certificate*>(NULL), google_full_chain.get()); | |
791 ASSERT_EQ(2U, google_full_chain->GetIntermediateCertificates().size()); | |
792 | |
793 CertVerifyResult verify_result; | |
794 EXPECT_EQ(static_cast<X509Certificate*>(NULL), | |
795 verify_result.verified_cert.get()); | |
796 int error = Verify(google_full_chain.get(), | |
797 "127.0.0.1", | |
798 0, | |
799 NULL, | |
800 empty_cert_list_, | |
801 &verify_result); | |
802 EXPECT_EQ(OK, error); | |
803 ASSERT_NE(static_cast<X509Certificate*>(NULL), | |
804 verify_result.verified_cert.get()); | |
805 | |
806 EXPECT_NE(google_full_chain, verify_result.verified_cert); | |
807 EXPECT_TRUE(X509Certificate::IsSameOSCert( | |
808 google_full_chain->os_cert_handle(), | |
809 verify_result.verified_cert->os_cert_handle())); | |
810 const X509Certificate::OSCertHandles& return_intermediates = | |
811 verify_result.verified_cert->GetIntermediateCertificates(); | |
812 ASSERT_EQ(2U, return_intermediates.size()); | |
813 EXPECT_TRUE(X509Certificate::IsSameOSCert(return_intermediates[0], | |
814 certs[1]->os_cert_handle())); | |
815 EXPECT_TRUE(X509Certificate::IsSameOSCert(return_intermediates[1], | |
816 certs[2]->os_cert_handle())); | |
817 } | |
818 | |
819 // Test that certificates issued for 'intranet' names (that is, containing no | |
820 // known public registry controlled domain information) issued by well-known | |
821 // CAs are flagged appropriately, while certificates that are issued by | |
822 // internal CAs are not flagged. | |
823 TEST_F(CertVerifyProcTest, IntranetHostsRejected) { | |
824 if (!SupportsDetectingKnownRoots()) { | |
825 LOG(INFO) << "Skipping this test in this platform."; | |
826 return; | |
827 } | |
828 | |
829 CertificateList cert_list = CreateCertificateListFromFile( | |
830 GetTestCertsDirectory(), "reject_intranet_hosts.pem", | |
831 X509Certificate::FORMAT_AUTO); | |
832 ASSERT_EQ(1U, cert_list.size()); | |
833 scoped_refptr<X509Certificate> cert(cert_list[0]); | |
834 | |
835 CertVerifyResult verify_result; | |
836 int error = 0; | |
837 | |
838 // Intranet names for public CAs should be flagged: | |
839 verify_proc_ = new WellKnownCaCertVerifyProc(true); | |
840 error = | |
841 Verify(cert.get(), "intranet", 0, NULL, empty_cert_list_, &verify_result); | |
842 EXPECT_EQ(OK, error); | |
843 EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_NON_UNIQUE_NAME); | |
844 | |
845 // However, if the CA is not well known, these should not be flagged: | |
846 verify_proc_ = new WellKnownCaCertVerifyProc(false); | |
847 error = | |
848 Verify(cert.get(), "intranet", 0, NULL, empty_cert_list_, &verify_result); | |
849 EXPECT_EQ(OK, error); | |
850 EXPECT_FALSE(verify_result.cert_status & CERT_STATUS_NON_UNIQUE_NAME); | |
851 } | |
852 | |
853 // Test that the certificate returned in CertVerifyResult is able to reorder | |
854 // certificates that are not ordered from end-entity to root. While this is | |
855 // a protocol violation if sent during a TLS handshake, if multiple sources | |
856 // of intermediate certificates are combined, it's possible that order may | |
857 // not be maintained. | |
858 TEST_F(CertVerifyProcTest, VerifyReturnChainProperlyOrdered) { | |
859 if (!SupportsReturningVerifiedChain()) { | |
860 LOG(INFO) << "Skipping this test in this platform."; | |
861 return; | |
862 } | |
863 | |
864 base::FilePath certs_dir = GetTestCertsDirectory(); | |
865 CertificateList certs = CreateCertificateListFromFile( | |
866 certs_dir, "x509_verify_results.chain.pem", | |
867 X509Certificate::FORMAT_AUTO); | |
868 ASSERT_EQ(3U, certs.size()); | |
869 | |
870 // Construct the chain out of order. | |
871 X509Certificate::OSCertHandles intermediates; | |
872 intermediates.push_back(certs[2]->os_cert_handle()); | |
873 intermediates.push_back(certs[1]->os_cert_handle()); | |
874 | |
875 ScopedTestRoot scoped_root(certs[2].get()); | |
876 | |
877 scoped_refptr<X509Certificate> google_full_chain = | |
878 X509Certificate::CreateFromHandle(certs[0]->os_cert_handle(), | |
879 intermediates); | |
880 ASSERT_NE(static_cast<X509Certificate*>(NULL), google_full_chain.get()); | |
881 ASSERT_EQ(2U, google_full_chain->GetIntermediateCertificates().size()); | |
882 | |
883 CertVerifyResult verify_result; | |
884 EXPECT_EQ(static_cast<X509Certificate*>(NULL), | |
885 verify_result.verified_cert.get()); | |
886 int error = Verify(google_full_chain.get(), | |
887 "127.0.0.1", | |
888 0, | |
889 NULL, | |
890 empty_cert_list_, | |
891 &verify_result); | |
892 EXPECT_EQ(OK, error); | |
893 ASSERT_NE(static_cast<X509Certificate*>(NULL), | |
894 verify_result.verified_cert.get()); | |
895 | |
896 EXPECT_NE(google_full_chain, verify_result.verified_cert); | |
897 EXPECT_TRUE(X509Certificate::IsSameOSCert( | |
898 google_full_chain->os_cert_handle(), | |
899 verify_result.verified_cert->os_cert_handle())); | |
900 const X509Certificate::OSCertHandles& return_intermediates = | |
901 verify_result.verified_cert->GetIntermediateCertificates(); | |
902 ASSERT_EQ(2U, return_intermediates.size()); | |
903 EXPECT_TRUE(X509Certificate::IsSameOSCert(return_intermediates[0], | |
904 certs[1]->os_cert_handle())); | |
905 EXPECT_TRUE(X509Certificate::IsSameOSCert(return_intermediates[1], | |
906 certs[2]->os_cert_handle())); | |
907 } | |
908 | |
909 // Test that Verify() filters out certificates which are not related to | |
910 // or part of the certificate chain being verified. | |
911 TEST_F(CertVerifyProcTest, VerifyReturnChainFiltersUnrelatedCerts) { | |
912 if (!SupportsReturningVerifiedChain()) { | |
913 LOG(INFO) << "Skipping this test in this platform."; | |
914 return; | |
915 } | |
916 | |
917 base::FilePath certs_dir = GetTestCertsDirectory(); | |
918 CertificateList certs = CreateCertificateListFromFile( | |
919 certs_dir, "x509_verify_results.chain.pem", | |
920 X509Certificate::FORMAT_AUTO); | |
921 ASSERT_EQ(3U, certs.size()); | |
922 ScopedTestRoot scoped_root(certs[2].get()); | |
923 | |
924 scoped_refptr<X509Certificate> unrelated_certificate = | |
925 ImportCertFromFile(certs_dir, "duplicate_cn_1.pem"); | |
926 scoped_refptr<X509Certificate> unrelated_certificate2 = | |
927 ImportCertFromFile(certs_dir, "aia-cert.pem"); | |
928 ASSERT_NE(static_cast<X509Certificate*>(NULL), unrelated_certificate.get()); | |
929 ASSERT_NE(static_cast<X509Certificate*>(NULL), unrelated_certificate2.get()); | |
930 | |
931 // Interject unrelated certificates into the list of intermediates. | |
932 X509Certificate::OSCertHandles intermediates; | |
933 intermediates.push_back(unrelated_certificate->os_cert_handle()); | |
934 intermediates.push_back(certs[1]->os_cert_handle()); | |
935 intermediates.push_back(unrelated_certificate2->os_cert_handle()); | |
936 intermediates.push_back(certs[2]->os_cert_handle()); | |
937 | |
938 scoped_refptr<X509Certificate> google_full_chain = | |
939 X509Certificate::CreateFromHandle(certs[0]->os_cert_handle(), | |
940 intermediates); | |
941 ASSERT_NE(static_cast<X509Certificate*>(NULL), google_full_chain.get()); | |
942 ASSERT_EQ(4U, google_full_chain->GetIntermediateCertificates().size()); | |
943 | |
944 CertVerifyResult verify_result; | |
945 EXPECT_EQ(static_cast<X509Certificate*>(NULL), | |
946 verify_result.verified_cert.get()); | |
947 int error = Verify(google_full_chain.get(), | |
948 "127.0.0.1", | |
949 0, | |
950 NULL, | |
951 empty_cert_list_, | |
952 &verify_result); | |
953 EXPECT_EQ(OK, error); | |
954 ASSERT_NE(static_cast<X509Certificate*>(NULL), | |
955 verify_result.verified_cert.get()); | |
956 | |
957 EXPECT_NE(google_full_chain, verify_result.verified_cert); | |
958 EXPECT_TRUE(X509Certificate::IsSameOSCert( | |
959 google_full_chain->os_cert_handle(), | |
960 verify_result.verified_cert->os_cert_handle())); | |
961 const X509Certificate::OSCertHandles& return_intermediates = | |
962 verify_result.verified_cert->GetIntermediateCertificates(); | |
963 ASSERT_EQ(2U, return_intermediates.size()); | |
964 EXPECT_TRUE(X509Certificate::IsSameOSCert(return_intermediates[0], | |
965 certs[1]->os_cert_handle())); | |
966 EXPECT_TRUE(X509Certificate::IsSameOSCert(return_intermediates[1], | |
967 certs[2]->os_cert_handle())); | |
968 } | |
969 | |
970 TEST_F(CertVerifyProcTest, AdditionalTrustAnchors) { | |
971 if (!SupportsAdditionalTrustAnchors()) { | |
972 LOG(INFO) << "Skipping this test in this platform."; | |
973 return; | |
974 } | |
975 | |
976 // |ca_cert| is the issuer of |cert|. | |
977 CertificateList ca_cert_list = CreateCertificateListFromFile( | |
978 GetTestCertsDirectory(), "root_ca_cert.pem", | |
979 X509Certificate::FORMAT_AUTO); | |
980 ASSERT_EQ(1U, ca_cert_list.size()); | |
981 scoped_refptr<X509Certificate> ca_cert(ca_cert_list[0]); | |
982 | |
983 CertificateList cert_list = CreateCertificateListFromFile( | |
984 GetTestCertsDirectory(), "ok_cert.pem", | |
985 X509Certificate::FORMAT_AUTO); | |
986 ASSERT_EQ(1U, cert_list.size()); | |
987 scoped_refptr<X509Certificate> cert(cert_list[0]); | |
988 | |
989 // Verification of |cert| fails when |ca_cert| is not in the trust anchors | |
990 // list. | |
991 int flags = 0; | |
992 CertVerifyResult verify_result; | |
993 int error = Verify( | |
994 cert.get(), "127.0.0.1", flags, NULL, empty_cert_list_, &verify_result); | |
995 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, error); | |
996 EXPECT_EQ(CERT_STATUS_AUTHORITY_INVALID, verify_result.cert_status); | |
997 EXPECT_FALSE(verify_result.is_issued_by_additional_trust_anchor); | |
998 | |
999 // Now add the |ca_cert| to the |trust_anchors|, and verification should pass. | |
1000 CertificateList trust_anchors; | |
1001 trust_anchors.push_back(ca_cert); | |
1002 error = Verify( | |
1003 cert.get(), "127.0.0.1", flags, NULL, trust_anchors, &verify_result); | |
1004 EXPECT_EQ(OK, error); | |
1005 EXPECT_EQ(0U, verify_result.cert_status); | |
1006 EXPECT_TRUE(verify_result.is_issued_by_additional_trust_anchor); | |
1007 | |
1008 // Clearing the |trust_anchors| makes verification fail again (the cache | |
1009 // should be skipped). | |
1010 error = Verify( | |
1011 cert.get(), "127.0.0.1", flags, NULL, empty_cert_list_, &verify_result); | |
1012 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, error); | |
1013 EXPECT_EQ(CERT_STATUS_AUTHORITY_INVALID, verify_result.cert_status); | |
1014 EXPECT_FALSE(verify_result.is_issued_by_additional_trust_anchor); | |
1015 } | |
1016 | |
1017 // Tests that certificates issued by user-supplied roots are not flagged as | |
1018 // issued by a known root. This should pass whether or not the platform supports | |
1019 // detecting known roots. | |
1020 TEST_F(CertVerifyProcTest, IsIssuedByKnownRootIgnoresTestRoots) { | |
1021 // Load root_ca_cert.pem into the test root store. | |
1022 TestRootCerts* root_certs = TestRootCerts::GetInstance(); | |
1023 root_certs->AddFromFile( | |
1024 GetTestCertsDirectory().AppendASCII("root_ca_cert.pem")); | |
1025 | |
1026 CertificateList cert_list = CreateCertificateListFromFile( | |
1027 GetTestCertsDirectory(), "ok_cert.pem", | |
1028 X509Certificate::FORMAT_AUTO); | |
1029 ASSERT_EQ(1U, cert_list.size()); | |
1030 scoped_refptr<X509Certificate> cert(cert_list[0]); | |
1031 | |
1032 // Verification should pass. | |
1033 int flags = 0; | |
1034 CertVerifyResult verify_result; | |
1035 int error = Verify( | |
1036 cert.get(), "127.0.0.1", flags, NULL, empty_cert_list_, &verify_result); | |
1037 EXPECT_EQ(OK, error); | |
1038 EXPECT_EQ(0U, verify_result.cert_status); | |
1039 // But should not be marked as a known root. | |
1040 EXPECT_FALSE(verify_result.is_issued_by_known_root); | |
1041 | |
1042 root_certs->Clear(); | |
1043 EXPECT_TRUE(root_certs->IsEmpty()); | |
1044 } | |
1045 | |
1046 #if defined(OS_MACOSX) && !defined(OS_IOS) | |
1047 // Tests that, on OS X, issues with a cross-certified Baltimore CyberTrust | |
1048 // Root can be successfully worked around once Apple completes removing the | |
1049 // older GTE CyberTrust Root from its trusted root store. | |
1050 // | |
1051 // The issue is caused by servers supplying the cross-certified intermediate | |
1052 // (necessary for certain mobile platforms), which OS X does not recognize | |
1053 // as already existing within its trust store. | |
1054 TEST_F(CertVerifyProcTest, CybertrustGTERoot) { | |
1055 CertificateList certs = CreateCertificateListFromFile( | |
1056 GetTestCertsDirectory(), | |
1057 "cybertrust_omniroot_chain.pem", | |
1058 X509Certificate::FORMAT_PEM_CERT_SEQUENCE); | |
1059 ASSERT_EQ(2U, certs.size()); | |
1060 | |
1061 X509Certificate::OSCertHandles intermediates; | |
1062 intermediates.push_back(certs[1]->os_cert_handle()); | |
1063 | |
1064 scoped_refptr<X509Certificate> cybertrust_basic = | |
1065 X509Certificate::CreateFromHandle(certs[0]->os_cert_handle(), | |
1066 intermediates); | |
1067 ASSERT_TRUE(cybertrust_basic.get()); | |
1068 | |
1069 scoped_refptr<X509Certificate> baltimore_root = | |
1070 ImportCertFromFile(GetTestCertsDirectory(), | |
1071 "cybertrust_baltimore_root.pem"); | |
1072 ASSERT_TRUE(baltimore_root.get()); | |
1073 | |
1074 ScopedTestRoot scoped_root(baltimore_root.get()); | |
1075 | |
1076 // Ensure that ONLY the Baltimore CyberTrust Root is trusted. This | |
1077 // simulates Keychain removing support for the GTE CyberTrust Root. | |
1078 TestRootCerts::GetInstance()->SetAllowSystemTrust(false); | |
1079 base::ScopedClosureRunner reset_system_trust( | |
1080 base::Bind(&TestRootCerts::SetAllowSystemTrust, | |
1081 base::Unretained(TestRootCerts::GetInstance()), | |
1082 true)); | |
1083 | |
1084 // First, make sure a simple certificate chain from | |
1085 // EE -> Public SureServer SV -> Baltimore CyberTrust | |
1086 // works. Only the first two certificates are included in the chain. | |
1087 int flags = 0; | |
1088 CertVerifyResult verify_result; | |
1089 int error = Verify(cybertrust_basic.get(), | |
1090 "cacert.omniroot.com", | |
1091 flags, | |
1092 NULL, | |
1093 empty_cert_list_, | |
1094 &verify_result); | |
1095 EXPECT_EQ(OK, error); | |
1096 EXPECT_EQ(CERT_STATUS_SHA1_SIGNATURE_PRESENT, verify_result.cert_status); | |
1097 | |
1098 // Attempt to verify with the first known cross-certified intermediate | |
1099 // provided. | |
1100 scoped_refptr<X509Certificate> baltimore_intermediate_1 = | |
1101 ImportCertFromFile(GetTestCertsDirectory(), | |
1102 "cybertrust_baltimore_cross_certified_1.pem"); | |
1103 ASSERT_TRUE(baltimore_intermediate_1.get()); | |
1104 | |
1105 X509Certificate::OSCertHandles intermediate_chain_1 = | |
1106 cybertrust_basic->GetIntermediateCertificates(); | |
1107 intermediate_chain_1.push_back(baltimore_intermediate_1->os_cert_handle()); | |
1108 | |
1109 scoped_refptr<X509Certificate> baltimore_chain_1 = | |
1110 X509Certificate::CreateFromHandle(cybertrust_basic->os_cert_handle(), | |
1111 intermediate_chain_1); | |
1112 error = Verify(baltimore_chain_1.get(), | |
1113 "cacert.omniroot.com", | |
1114 flags, | |
1115 NULL, | |
1116 empty_cert_list_, | |
1117 &verify_result); | |
1118 EXPECT_EQ(OK, error); | |
1119 EXPECT_EQ(CERT_STATUS_SHA1_SIGNATURE_PRESENT, verify_result.cert_status); | |
1120 | |
1121 // Attempt to verify with the second known cross-certified intermediate | |
1122 // provided. | |
1123 scoped_refptr<X509Certificate> baltimore_intermediate_2 = | |
1124 ImportCertFromFile(GetTestCertsDirectory(), | |
1125 "cybertrust_baltimore_cross_certified_2.pem"); | |
1126 ASSERT_TRUE(baltimore_intermediate_2.get()); | |
1127 | |
1128 X509Certificate::OSCertHandles intermediate_chain_2 = | |
1129 cybertrust_basic->GetIntermediateCertificates(); | |
1130 intermediate_chain_2.push_back(baltimore_intermediate_2->os_cert_handle()); | |
1131 | |
1132 scoped_refptr<X509Certificate> baltimore_chain_2 = | |
1133 X509Certificate::CreateFromHandle(cybertrust_basic->os_cert_handle(), | |
1134 intermediate_chain_2); | |
1135 error = Verify(baltimore_chain_2.get(), | |
1136 "cacert.omniroot.com", | |
1137 flags, | |
1138 NULL, | |
1139 empty_cert_list_, | |
1140 &verify_result); | |
1141 EXPECT_EQ(OK, error); | |
1142 EXPECT_EQ(CERT_STATUS_SHA1_SIGNATURE_PRESENT, verify_result.cert_status); | |
1143 | |
1144 // Attempt to verify when both a cross-certified intermediate AND | |
1145 // the legacy GTE root are provided. | |
1146 scoped_refptr<X509Certificate> cybertrust_root = | |
1147 ImportCertFromFile(GetTestCertsDirectory(), | |
1148 "cybertrust_gte_root.pem"); | |
1149 ASSERT_TRUE(cybertrust_root.get()); | |
1150 | |
1151 intermediate_chain_2.push_back(cybertrust_root->os_cert_handle()); | |
1152 scoped_refptr<X509Certificate> baltimore_chain_with_root = | |
1153 X509Certificate::CreateFromHandle(cybertrust_basic->os_cert_handle(), | |
1154 intermediate_chain_2); | |
1155 error = Verify(baltimore_chain_with_root.get(), | |
1156 "cacert.omniroot.com", | |
1157 flags, | |
1158 NULL, | |
1159 empty_cert_list_, | |
1160 &verify_result); | |
1161 EXPECT_EQ(OK, error); | |
1162 EXPECT_EQ(CERT_STATUS_SHA1_SIGNATURE_PRESENT, verify_result.cert_status); | |
1163 | |
1164 TestRootCerts::GetInstance()->Clear(); | |
1165 EXPECT_TRUE(TestRootCerts::GetInstance()->IsEmpty()); | |
1166 } | |
1167 #endif | |
1168 | |
1169 #if defined(USE_NSS) || defined(OS_IOS) || defined(OS_WIN) || defined(OS_MACOSX) | |
1170 // Test that CRLSets are effective in making a certificate appear to be | |
1171 // revoked. | |
1172 TEST_F(CertVerifyProcTest, CRLSet) { | |
1173 CertificateList ca_cert_list = | |
1174 CreateCertificateListFromFile(GetTestCertsDirectory(), | |
1175 "root_ca_cert.pem", | |
1176 X509Certificate::FORMAT_AUTO); | |
1177 ASSERT_EQ(1U, ca_cert_list.size()); | |
1178 ScopedTestRoot test_root(ca_cert_list[0].get()); | |
1179 | |
1180 CertificateList cert_list = CreateCertificateListFromFile( | |
1181 GetTestCertsDirectory(), "ok_cert.pem", X509Certificate::FORMAT_AUTO); | |
1182 ASSERT_EQ(1U, cert_list.size()); | |
1183 scoped_refptr<X509Certificate> cert(cert_list[0]); | |
1184 | |
1185 int flags = 0; | |
1186 CertVerifyResult verify_result; | |
1187 int error = Verify( | |
1188 cert.get(), "127.0.0.1", flags, NULL, empty_cert_list_, &verify_result); | |
1189 EXPECT_EQ(OK, error); | |
1190 EXPECT_EQ(0U, verify_result.cert_status); | |
1191 | |
1192 scoped_refptr<CRLSet> crl_set; | |
1193 std::string crl_set_bytes; | |
1194 | |
1195 // First test blocking by SPKI. | |
1196 EXPECT_TRUE(base::ReadFileToString( | |
1197 GetTestCertsDirectory().AppendASCII("crlset_by_leaf_spki.raw"), | |
1198 &crl_set_bytes)); | |
1199 ASSERT_TRUE(CRLSetStorage::Parse(crl_set_bytes, &crl_set)); | |
1200 | |
1201 error = Verify(cert.get(), | |
1202 "127.0.0.1", | |
1203 flags, | |
1204 crl_set.get(), | |
1205 empty_cert_list_, | |
1206 &verify_result); | |
1207 EXPECT_EQ(ERR_CERT_REVOKED, error); | |
1208 | |
1209 // Second, test revocation by serial number of a cert directly under the | |
1210 // root. | |
1211 crl_set_bytes.clear(); | |
1212 EXPECT_TRUE(base::ReadFileToString( | |
1213 GetTestCertsDirectory().AppendASCII("crlset_by_root_serial.raw"), | |
1214 &crl_set_bytes)); | |
1215 ASSERT_TRUE(CRLSetStorage::Parse(crl_set_bytes, &crl_set)); | |
1216 | |
1217 error = Verify(cert.get(), | |
1218 "127.0.0.1", | |
1219 flags, | |
1220 crl_set.get(), | |
1221 empty_cert_list_, | |
1222 &verify_result); | |
1223 EXPECT_EQ(ERR_CERT_REVOKED, error); | |
1224 } | |
1225 | |
1226 TEST_F(CertVerifyProcTest, CRLSetLeafSerial) { | |
1227 CertificateList ca_cert_list = | |
1228 CreateCertificateListFromFile(GetTestCertsDirectory(), | |
1229 "quic_root.crt", | |
1230 X509Certificate::FORMAT_AUTO); | |
1231 ASSERT_EQ(1U, ca_cert_list.size()); | |
1232 ScopedTestRoot test_root(ca_cert_list[0].get()); | |
1233 | |
1234 CertificateList intermediate_cert_list = | |
1235 CreateCertificateListFromFile(GetTestCertsDirectory(), | |
1236 "quic_intermediate.crt", | |
1237 X509Certificate::FORMAT_AUTO); | |
1238 ASSERT_EQ(1U, intermediate_cert_list.size()); | |
1239 X509Certificate::OSCertHandles intermediates; | |
1240 intermediates.push_back(intermediate_cert_list[0]->os_cert_handle()); | |
1241 | |
1242 CertificateList cert_list = CreateCertificateListFromFile( | |
1243 GetTestCertsDirectory(), "quic_test.example.com.crt", | |
1244 X509Certificate::FORMAT_AUTO); | |
1245 ASSERT_EQ(1U, cert_list.size()); | |
1246 | |
1247 scoped_refptr<X509Certificate> leaf = | |
1248 X509Certificate::CreateFromHandle(cert_list[0]->os_cert_handle(), | |
1249 intermediates); | |
1250 | |
1251 int flags = 0; | |
1252 CertVerifyResult verify_result; | |
1253 int error = Verify(leaf.get(), | |
1254 "test.example.com", | |
1255 flags, | |
1256 NULL, | |
1257 empty_cert_list_, | |
1258 &verify_result); | |
1259 EXPECT_EQ(OK, error); | |
1260 EXPECT_EQ(CERT_STATUS_SHA1_SIGNATURE_PRESENT, verify_result.cert_status); | |
1261 | |
1262 // Test revocation by serial number of a certificate not under the root. | |
1263 scoped_refptr<CRLSet> crl_set; | |
1264 std::string crl_set_bytes; | |
1265 ASSERT_TRUE(base::ReadFileToString( | |
1266 GetTestCertsDirectory().AppendASCII("crlset_by_intermediate_serial.raw"), | |
1267 &crl_set_bytes)); | |
1268 ASSERT_TRUE(CRLSetStorage::Parse(crl_set_bytes, &crl_set)); | |
1269 | |
1270 error = Verify(leaf.get(), | |
1271 "test.example.com", | |
1272 flags, | |
1273 crl_set.get(), | |
1274 empty_cert_list_, | |
1275 &verify_result); | |
1276 EXPECT_EQ(ERR_CERT_REVOKED, error); | |
1277 } | |
1278 #endif | |
1279 | |
1280 enum ExpectedAlgorithms { | |
1281 EXPECT_MD2 = 1 << 0, | |
1282 EXPECT_MD4 = 1 << 1, | |
1283 EXPECT_MD5 = 1 << 2, | |
1284 EXPECT_SHA1 = 1 << 3 | |
1285 }; | |
1286 | |
1287 struct WeakDigestTestData { | |
1288 const char* root_cert_filename; | |
1289 const char* intermediate_cert_filename; | |
1290 const char* ee_cert_filename; | |
1291 int expected_algorithms; | |
1292 }; | |
1293 | |
1294 // GTest 'magic' pretty-printer, so that if/when a test fails, it knows how | |
1295 // to output the parameter that was passed. Without this, it will simply | |
1296 // attempt to print out the first twenty bytes of the object, which depending | |
1297 // on platform and alignment, may result in an invalid read. | |
1298 void PrintTo(const WeakDigestTestData& data, std::ostream* os) { | |
1299 *os << "root: " | |
1300 << (data.root_cert_filename ? data.root_cert_filename : "none") | |
1301 << "; intermediate: " << data.intermediate_cert_filename | |
1302 << "; end-entity: " << data.ee_cert_filename; | |
1303 } | |
1304 | |
1305 class CertVerifyProcWeakDigestTest | |
1306 : public CertVerifyProcTest, | |
1307 public testing::WithParamInterface<WeakDigestTestData> { | |
1308 public: | |
1309 CertVerifyProcWeakDigestTest() {} | |
1310 virtual ~CertVerifyProcWeakDigestTest() {} | |
1311 }; | |
1312 | |
1313 TEST_P(CertVerifyProcWeakDigestTest, Verify) { | |
1314 WeakDigestTestData data = GetParam(); | |
1315 base::FilePath certs_dir = GetTestCertsDirectory(); | |
1316 | |
1317 ScopedTestRoot test_root; | |
1318 if (data.root_cert_filename) { | |
1319 scoped_refptr<X509Certificate> root_cert = | |
1320 ImportCertFromFile(certs_dir, data.root_cert_filename); | |
1321 ASSERT_NE(static_cast<X509Certificate*>(NULL), root_cert.get()); | |
1322 test_root.Reset(root_cert.get()); | |
1323 } | |
1324 | |
1325 scoped_refptr<X509Certificate> intermediate_cert = | |
1326 ImportCertFromFile(certs_dir, data.intermediate_cert_filename); | |
1327 ASSERT_NE(static_cast<X509Certificate*>(NULL), intermediate_cert.get()); | |
1328 scoped_refptr<X509Certificate> ee_cert = | |
1329 ImportCertFromFile(certs_dir, data.ee_cert_filename); | |
1330 ASSERT_NE(static_cast<X509Certificate*>(NULL), ee_cert.get()); | |
1331 | |
1332 X509Certificate::OSCertHandles intermediates; | |
1333 intermediates.push_back(intermediate_cert->os_cert_handle()); | |
1334 | |
1335 scoped_refptr<X509Certificate> ee_chain = | |
1336 X509Certificate::CreateFromHandle(ee_cert->os_cert_handle(), | |
1337 intermediates); | |
1338 ASSERT_NE(static_cast<X509Certificate*>(NULL), ee_chain.get()); | |
1339 | |
1340 int flags = 0; | |
1341 CertVerifyResult verify_result; | |
1342 int rv = Verify(ee_chain.get(), | |
1343 "127.0.0.1", | |
1344 flags, | |
1345 NULL, | |
1346 empty_cert_list_, | |
1347 &verify_result); | |
1348 EXPECT_EQ(!!(data.expected_algorithms & EXPECT_MD2), verify_result.has_md2); | |
1349 EXPECT_EQ(!!(data.expected_algorithms & EXPECT_MD4), verify_result.has_md4); | |
1350 EXPECT_EQ(!!(data.expected_algorithms & EXPECT_MD5), verify_result.has_md5); | |
1351 EXPECT_EQ(!!(data.expected_algorithms & EXPECT_SHA1), verify_result.has_sha1); | |
1352 | |
1353 EXPECT_FALSE(verify_result.is_issued_by_additional_trust_anchor); | |
1354 | |
1355 // Ensure that MD4 and MD2 are tagged as invalid. | |
1356 if (data.expected_algorithms & (EXPECT_MD2 | EXPECT_MD4)) { | |
1357 EXPECT_EQ(CERT_STATUS_INVALID, | |
1358 verify_result.cert_status & CERT_STATUS_INVALID); | |
1359 } | |
1360 | |
1361 // Ensure that MD5 is flagged as weak. | |
1362 if (data.expected_algorithms & EXPECT_MD5) { | |
1363 EXPECT_EQ( | |
1364 CERT_STATUS_WEAK_SIGNATURE_ALGORITHM, | |
1365 verify_result.cert_status & CERT_STATUS_WEAK_SIGNATURE_ALGORITHM); | |
1366 } | |
1367 | |
1368 // If a root cert is present, then check that the chain was rejected if any | |
1369 // weak algorithms are present. This is only checked when a root cert is | |
1370 // present because the error reported for incomplete chains with weak | |
1371 // algorithms depends on which implementation was used to validate (NSS, | |
1372 // OpenSSL, CryptoAPI, Security.framework) and upon which weak algorithm | |
1373 // present (MD2, MD4, MD5). | |
1374 if (data.root_cert_filename) { | |
1375 if (data.expected_algorithms & (EXPECT_MD2 | EXPECT_MD4)) { | |
1376 EXPECT_EQ(ERR_CERT_INVALID, rv); | |
1377 } else if (data.expected_algorithms & EXPECT_MD5) { | |
1378 EXPECT_EQ(ERR_CERT_WEAK_SIGNATURE_ALGORITHM, rv); | |
1379 } else { | |
1380 EXPECT_EQ(OK, rv); | |
1381 } | |
1382 } | |
1383 } | |
1384 | |
1385 // Unlike TEST/TEST_F, which are macros that expand to further macros, | |
1386 // INSTANTIATE_TEST_CASE_P is a macro that expands directly to code that | |
1387 // stringizes the arguments. As a result, macros passed as parameters (such as | |
1388 // prefix or test_case_name) will not be expanded by the preprocessor. To work | |
1389 // around this, indirect the macro for INSTANTIATE_TEST_CASE_P, so that the | |
1390 // pre-processor will expand macros such as MAYBE_test_name before | |
1391 // instantiating the test. | |
1392 #define WRAPPED_INSTANTIATE_TEST_CASE_P(prefix, test_case_name, generator) \ | |
1393 INSTANTIATE_TEST_CASE_P(prefix, test_case_name, generator) | |
1394 | |
1395 // The signature algorithm of the root CA should not matter. | |
1396 const WeakDigestTestData kVerifyRootCATestData[] = { | |
1397 { "weak_digest_md5_root.pem", "weak_digest_sha1_intermediate.pem", | |
1398 "weak_digest_sha1_ee.pem", EXPECT_SHA1 }, | |
1399 #if defined(USE_OPENSSL_CERTS) || defined(OS_WIN) | |
1400 // MD4 is not supported by OS X / NSS | |
1401 { "weak_digest_md4_root.pem", "weak_digest_sha1_intermediate.pem", | |
1402 "weak_digest_sha1_ee.pem", EXPECT_SHA1 }, | |
1403 #endif | |
1404 { "weak_digest_md2_root.pem", "weak_digest_sha1_intermediate.pem", | |
1405 "weak_digest_sha1_ee.pem", EXPECT_SHA1 }, | |
1406 }; | |
1407 INSTANTIATE_TEST_CASE_P(VerifyRoot, CertVerifyProcWeakDigestTest, | |
1408 testing::ValuesIn(kVerifyRootCATestData)); | |
1409 | |
1410 // The signature algorithm of intermediates should be properly detected. | |
1411 const WeakDigestTestData kVerifyIntermediateCATestData[] = { | |
1412 { "weak_digest_sha1_root.pem", "weak_digest_md5_intermediate.pem", | |
1413 "weak_digest_sha1_ee.pem", EXPECT_MD5 | EXPECT_SHA1 }, | |
1414 #if defined(USE_OPENSSL_CERTS) || defined(OS_WIN) | |
1415 // MD4 is not supported by OS X / NSS | |
1416 { "weak_digest_sha1_root.pem", "weak_digest_md4_intermediate.pem", | |
1417 "weak_digest_sha1_ee.pem", EXPECT_MD4 | EXPECT_SHA1 }, | |
1418 #endif | |
1419 { "weak_digest_sha1_root.pem", "weak_digest_md2_intermediate.pem", | |
1420 "weak_digest_sha1_ee.pem", EXPECT_MD2 | EXPECT_SHA1 }, | |
1421 }; | |
1422 // Disabled on NSS - MD4 is not supported, and MD2 and MD5 are disabled. | |
1423 #if defined(USE_NSS) || defined(OS_IOS) | |
1424 #define MAYBE_VerifyIntermediate DISABLED_VerifyIntermediate | |
1425 #else | |
1426 #define MAYBE_VerifyIntermediate VerifyIntermediate | |
1427 #endif | |
1428 WRAPPED_INSTANTIATE_TEST_CASE_P( | |
1429 MAYBE_VerifyIntermediate, | |
1430 CertVerifyProcWeakDigestTest, | |
1431 testing::ValuesIn(kVerifyIntermediateCATestData)); | |
1432 | |
1433 // The signature algorithm of end-entity should be properly detected. | |
1434 const WeakDigestTestData kVerifyEndEntityTestData[] = { | |
1435 { "weak_digest_sha1_root.pem", "weak_digest_sha1_intermediate.pem", | |
1436 "weak_digest_md5_ee.pem", EXPECT_MD5 | EXPECT_SHA1 }, | |
1437 #if defined(USE_OPENSSL_CERTS) || defined(OS_WIN) | |
1438 // MD4 is not supported by OS X / NSS | |
1439 { "weak_digest_sha1_root.pem", "weak_digest_sha1_intermediate.pem", | |
1440 "weak_digest_md4_ee.pem", EXPECT_MD4 | EXPECT_SHA1 }, | |
1441 #endif | |
1442 { "weak_digest_sha1_root.pem", "weak_digest_sha1_intermediate.pem", | |
1443 "weak_digest_md2_ee.pem", EXPECT_MD2 | EXPECT_SHA1 }, | |
1444 }; | |
1445 // Disabled on NSS - NSS caches chains/signatures in such a way that cannot | |
1446 // be cleared until NSS is cleanly shutdown, which is not presently supported | |
1447 // in Chromium. | |
1448 #if defined(USE_NSS) || defined(OS_IOS) | |
1449 #define MAYBE_VerifyEndEntity DISABLED_VerifyEndEntity | |
1450 #else | |
1451 #define MAYBE_VerifyEndEntity VerifyEndEntity | |
1452 #endif | |
1453 WRAPPED_INSTANTIATE_TEST_CASE_P(MAYBE_VerifyEndEntity, | |
1454 CertVerifyProcWeakDigestTest, | |
1455 testing::ValuesIn(kVerifyEndEntityTestData)); | |
1456 | |
1457 // Incomplete chains should still report the status of the intermediate. | |
1458 const WeakDigestTestData kVerifyIncompleteIntermediateTestData[] = { | |
1459 { NULL, "weak_digest_md5_intermediate.pem", "weak_digest_sha1_ee.pem", | |
1460 EXPECT_MD5 | EXPECT_SHA1 }, | |
1461 #if defined(USE_OPENSSL_CERTS) || defined(OS_WIN) | |
1462 // MD4 is not supported by OS X / NSS | |
1463 { NULL, "weak_digest_md4_intermediate.pem", "weak_digest_sha1_ee.pem", | |
1464 EXPECT_MD4 | EXPECT_SHA1 }, | |
1465 #endif | |
1466 { NULL, "weak_digest_md2_intermediate.pem", "weak_digest_sha1_ee.pem", | |
1467 EXPECT_MD2 | EXPECT_SHA1 }, | |
1468 }; | |
1469 // Disabled on NSS - libpkix does not return constructed chains on error, | |
1470 // preventing us from detecting/inspecting the verified chain. | |
1471 #if defined(USE_NSS) || defined(OS_IOS) | |
1472 #define MAYBE_VerifyIncompleteIntermediate \ | |
1473 DISABLED_VerifyIncompleteIntermediate | |
1474 #else | |
1475 #define MAYBE_VerifyIncompleteIntermediate VerifyIncompleteIntermediate | |
1476 #endif | |
1477 WRAPPED_INSTANTIATE_TEST_CASE_P( | |
1478 MAYBE_VerifyIncompleteIntermediate, | |
1479 CertVerifyProcWeakDigestTest, | |
1480 testing::ValuesIn(kVerifyIncompleteIntermediateTestData)); | |
1481 | |
1482 // Incomplete chains should still report the status of the end-entity. | |
1483 const WeakDigestTestData kVerifyIncompleteEETestData[] = { | |
1484 { NULL, "weak_digest_sha1_intermediate.pem", "weak_digest_md5_ee.pem", | |
1485 EXPECT_MD5 | EXPECT_SHA1 }, | |
1486 #if defined(USE_OPENSSL_CERTS) || defined(OS_WIN) | |
1487 // MD4 is not supported by OS X / NSS | |
1488 { NULL, "weak_digest_sha1_intermediate.pem", "weak_digest_md4_ee.pem", | |
1489 EXPECT_MD4 | EXPECT_SHA1 }, | |
1490 #endif | |
1491 { NULL, "weak_digest_sha1_intermediate.pem", "weak_digest_md2_ee.pem", | |
1492 EXPECT_MD2 | EXPECT_SHA1 }, | |
1493 }; | |
1494 // Disabled on NSS - libpkix does not return constructed chains on error, | |
1495 // preventing us from detecting/inspecting the verified chain. | |
1496 #if defined(USE_NSS) || defined(OS_IOS) | |
1497 #define MAYBE_VerifyIncompleteEndEntity DISABLED_VerifyIncompleteEndEntity | |
1498 #else | |
1499 #define MAYBE_VerifyIncompleteEndEntity VerifyIncompleteEndEntity | |
1500 #endif | |
1501 WRAPPED_INSTANTIATE_TEST_CASE_P( | |
1502 MAYBE_VerifyIncompleteEndEntity, | |
1503 CertVerifyProcWeakDigestTest, | |
1504 testing::ValuesIn(kVerifyIncompleteEETestData)); | |
1505 | |
1506 // Differing algorithms between the intermediate and the EE should still be | |
1507 // reported. | |
1508 const WeakDigestTestData kVerifyMixedTestData[] = { | |
1509 { "weak_digest_sha1_root.pem", "weak_digest_md5_intermediate.pem", | |
1510 "weak_digest_md2_ee.pem", EXPECT_MD2 | EXPECT_MD5 }, | |
1511 { "weak_digest_sha1_root.pem", "weak_digest_md2_intermediate.pem", | |
1512 "weak_digest_md5_ee.pem", EXPECT_MD2 | EXPECT_MD5 }, | |
1513 #if defined(USE_OPENSSL_CERTS) || defined(OS_WIN) | |
1514 // MD4 is not supported by OS X / NSS | |
1515 { "weak_digest_sha1_root.pem", "weak_digest_md4_intermediate.pem", | |
1516 "weak_digest_md2_ee.pem", EXPECT_MD2 | EXPECT_MD4 }, | |
1517 #endif | |
1518 }; | |
1519 // NSS does not support MD4 and does not enable MD2 by default, making all | |
1520 // permutations invalid. | |
1521 #if defined(USE_NSS) || defined(OS_IOS) | |
1522 #define MAYBE_VerifyMixed DISABLED_VerifyMixed | |
1523 #else | |
1524 #define MAYBE_VerifyMixed VerifyMixed | |
1525 #endif | |
1526 WRAPPED_INSTANTIATE_TEST_CASE_P( | |
1527 MAYBE_VerifyMixed, | |
1528 CertVerifyProcWeakDigestTest, | |
1529 testing::ValuesIn(kVerifyMixedTestData)); | |
1530 | |
1531 // For the list of valid hostnames, see | |
1532 // net/cert/data/ssl/certificates/subjectAltName_sanity_check.pem | |
1533 static const struct CertVerifyProcNameData { | |
1534 const char* hostname; | |
1535 bool valid; // Whether or not |hostname| matches a subjectAltName. | |
1536 } kVerifyNameData[] = { | |
1537 { "127.0.0.1", false }, // Don't match the common name | |
1538 { "127.0.0.2", true }, // Matches the iPAddress SAN (IPv4) | |
1539 { "FE80:0:0:0:0:0:0:1", true }, // Matches the iPAddress SAN (IPv6) | |
1540 { "[FE80:0:0:0:0:0:0:1]", false }, // Should not match the iPAddress SAN | |
1541 { "FE80::1", true }, // Compressed form matches the iPAddress SAN (IPv6) | |
1542 { "::127.0.0.2", false }, // IPv6 mapped form should NOT match iPAddress SAN | |
1543 { "test.example", true }, // Matches the dNSName SAN | |
1544 { "test.example.", true }, // Matches the dNSName SAN (trailing . ignored) | |
1545 { "www.test.example", false }, // Should not match the dNSName SAN | |
1546 { "test..example", false }, // Should not match the dNSName SAN | |
1547 { "test.example..", false }, // Should not match the dNSName SAN | |
1548 { ".test.example.", false }, // Should not match the dNSName SAN | |
1549 { ".test.example", false }, // Should not match the dNSName SAN | |
1550 }; | |
1551 | |
1552 // GTest 'magic' pretty-printer, so that if/when a test fails, it knows how | |
1553 // to output the parameter that was passed. Without this, it will simply | |
1554 // attempt to print out the first twenty bytes of the object, which depending | |
1555 // on platform and alignment, may result in an invalid read. | |
1556 void PrintTo(const CertVerifyProcNameData& data, std::ostream* os) { | |
1557 *os << "Hostname: " << data.hostname << "; valid=" << data.valid; | |
1558 } | |
1559 | |
1560 class CertVerifyProcNameTest | |
1561 : public CertVerifyProcTest, | |
1562 public testing::WithParamInterface<CertVerifyProcNameData> { | |
1563 public: | |
1564 CertVerifyProcNameTest() {} | |
1565 virtual ~CertVerifyProcNameTest() {} | |
1566 }; | |
1567 | |
1568 TEST_P(CertVerifyProcNameTest, VerifyCertName) { | |
1569 CertVerifyProcNameData data = GetParam(); | |
1570 | |
1571 CertificateList cert_list = CreateCertificateListFromFile( | |
1572 GetTestCertsDirectory(), "subjectAltName_sanity_check.pem", | |
1573 X509Certificate::FORMAT_AUTO); | |
1574 ASSERT_EQ(1U, cert_list.size()); | |
1575 scoped_refptr<X509Certificate> cert(cert_list[0]); | |
1576 | |
1577 ScopedTestRoot scoped_root(cert.get()); | |
1578 | |
1579 CertVerifyResult verify_result; | |
1580 int error = Verify(cert.get(), data.hostname, 0, NULL, empty_cert_list_, | |
1581 &verify_result); | |
1582 if (data.valid) { | |
1583 EXPECT_EQ(OK, error); | |
1584 EXPECT_FALSE(verify_result.cert_status & CERT_STATUS_COMMON_NAME_INVALID); | |
1585 } else { | |
1586 EXPECT_EQ(ERR_CERT_COMMON_NAME_INVALID, error); | |
1587 EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_COMMON_NAME_INVALID); | |
1588 } | |
1589 } | |
1590 | |
1591 WRAPPED_INSTANTIATE_TEST_CASE_P( | |
1592 VerifyName, | |
1593 CertVerifyProcNameTest, | |
1594 testing::ValuesIn(kVerifyNameData)); | |
1595 | |
1596 } // namespace net | |
OLD | NEW |