Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/base/x509_certificate.h" | 5 #include "net/base/x509_certificate.h" |
| 6 | 6 |
| 7 // Work around https://bugzilla.mozilla.org/show_bug.cgi?id=455424 | 7 // Work around https://bugzilla.mozilla.org/show_bug.cgi?id=455424 |
| 8 // until NSS 3.12.2 comes out and we update to it. | 8 // until NSS 3.12.2 comes out and we update to it. |
| 9 #define Lock FOO_NSS_Lock | 9 #define Lock FOO_NSS_Lock |
| 10 #include <cert.h> | 10 #include <cert.h> |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 93 } | 93 } |
| 94 } | 94 } |
| 95 } | 95 } |
| 96 | 96 |
| 97 private: | 97 private: |
| 98 CERTValOutParam* cvout_; | 98 CERTValOutParam* cvout_; |
| 99 | 99 |
| 100 DISALLOW_COPY_AND_ASSIGN(ScopedCERTValOutParam); | 100 DISALLOW_COPY_AND_ASSIGN(ScopedCERTValOutParam); |
| 101 }; | 101 }; |
| 102 | 102 |
| 103 class ScopedCERTCertificatePolicies { | |
|
wtc
2009/08/13 00:35:33
Nit: move this up, under ScopedCERTCertList, becau
| |
| 104 public: | |
| 105 explicit ScopedCERTCertificatePolicies(CERTCertificatePolicies* policies) | |
| 106 : policies_(policies) {} | |
| 107 | |
| 108 ~ScopedCERTCertificatePolicies() { | |
| 109 if (policies_) | |
| 110 CERT_DestroyCertificatePoliciesExtension(policies_); | |
| 111 } | |
| 112 | |
| 113 private: | |
| 114 CERTCertificatePolicies* policies_; | |
| 115 | |
| 116 DISALLOW_COPY_AND_ASSIGN(ScopedCERTCertificatePolicies); | |
| 117 }; | |
| 118 | |
| 119 | |
| 103 // Map PORT_GetError() return values to our network error codes. | 120 // Map PORT_GetError() return values to our network error codes. |
| 104 int MapSecurityError(int err) { | 121 int MapSecurityError(int err) { |
| 105 switch (err) { | 122 switch (err) { |
| 106 case SEC_ERROR_INVALID_TIME: | 123 case SEC_ERROR_INVALID_TIME: |
| 107 case SEC_ERROR_EXPIRED_CERTIFICATE: | 124 case SEC_ERROR_EXPIRED_CERTIFICATE: |
| 108 return ERR_CERT_DATE_INVALID; | 125 return ERR_CERT_DATE_INVALID; |
| 109 case SEC_ERROR_UNKNOWN_ISSUER: | 126 case SEC_ERROR_UNKNOWN_ISSUER: |
| 110 case SEC_ERROR_UNTRUSTED_ISSUER: | 127 case SEC_ERROR_UNTRUSTED_ISSUER: |
| 111 case SEC_ERROR_CA_CERT_INVALID: | 128 case SEC_ERROR_CA_CERT_INVALID: |
| 112 case SEC_ERROR_UNTRUSTED_CERT: | 129 case SEC_ERROR_UNTRUSTED_CERT: |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 324 // If policy_oids is not NULL and num_policy_oids is positive, policies | 341 // If policy_oids is not NULL and num_policy_oids is positive, policies |
| 325 // are also checked. | 342 // are also checked. |
| 326 // Caller must initialize cvout before calling this function. | 343 // Caller must initialize cvout before calling this function. |
| 327 SECStatus PKIXVerifyCert(X509Certificate::OSCertHandle cert_handle, | 344 SECStatus PKIXVerifyCert(X509Certificate::OSCertHandle cert_handle, |
| 328 const SECOidTag* policy_oids, | 345 const SECOidTag* policy_oids, |
| 329 int num_policy_oids, | 346 int num_policy_oids, |
| 330 CERTValOutParam* cvout) { | 347 CERTValOutParam* cvout) { |
| 331 PRUint64 revocation_method_flags = | 348 PRUint64 revocation_method_flags = |
| 332 CERT_REV_M_TEST_USING_THIS_METHOD | | 349 CERT_REV_M_TEST_USING_THIS_METHOD | |
| 333 CERT_REV_M_ALLOW_NETWORK_FETCHING | | 350 CERT_REV_M_ALLOW_NETWORK_FETCHING | |
| 334 CERT_REV_M_ALLOW_IMPLICIT_DEFAULT_SOURCE | | 351 CERT_REV_M_IGNORE_IMPLICIT_DEFAULT_SOURCE | |
| 335 CERT_REV_M_STOP_TESTING_ON_FRESH_INFO; | 352 CERT_REV_M_STOP_TESTING_ON_FRESH_INFO | |
| 353 CERT_REV_M_IGNORE_MISSING_FRESH_INFO; | |
|
wtc
2009/08/13 01:20:58
Nit: please list CERT_REV_M_IGNORE_MISSING_FRESH_I
| |
| 336 PRUint64 revocation_method_independent_flags = | 354 PRUint64 revocation_method_independent_flags = |
| 337 CERT_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST; | 355 CERT_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST; |
| 338 if (policy_oids && num_policy_oids > 0) { | 356 if (policy_oids && num_policy_oids > 0) { |
|
wtc
2009/08/13 00:35:33
Alexei, I had to add this if statement so that we'
| |
| 339 // EV verification requires revocation checking. Consider the certificate | 357 // EV verification requires revocation checking. Consider the certificate |
| 340 // revoked if we don't have revocation info. | 358 // revoked if we don't have revocation info. |
| 341 // TODO(wtc): Add a bool parameter to expressly specify we're doing EV | 359 // TODO(wtc): Add a bool parameter to expressly specify we're doing EV |
| 342 // verification or we want strict revocation flags. | 360 // verification or we want strict revocation flags. |
| 343 revocation_method_flags |= CERT_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE; | 361 revocation_method_flags |= CERT_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE; |
| 344 revocation_method_independent_flags |= | 362 revocation_method_independent_flags |= |
| 345 CERT_REV_MI_REQUIRE_SOME_FRESH_INFO_AVAILABLE; | 363 CERT_REV_MI_REQUIRE_SOME_FRESH_INFO_AVAILABLE; |
| 346 } else { | 364 } else { |
| 347 revocation_method_flags |= CERT_REV_M_SKIP_TEST_ON_MISSING_SOURCE; | 365 revocation_method_flags |= CERT_REV_M_SKIP_TEST_ON_MISSING_SOURCE; |
| 348 revocation_method_independent_flags |= | 366 revocation_method_independent_flags |= |
| 349 CERT_REV_MI_NO_OVERALL_INFO_REQUIREMENT; | 367 CERT_REV_MI_NO_OVERALL_INFO_REQUIREMENT; |
| 350 } | 368 } |
| 351 PRUint64 method_flags[2]; | 369 PRUint64 method_flags[2]; |
| 352 method_flags[cert_revocation_method_crl] = revocation_method_flags; | 370 method_flags[cert_revocation_method_crl] = revocation_method_flags; |
| 353 method_flags[cert_revocation_method_ocsp] = revocation_method_flags; | 371 method_flags[cert_revocation_method_ocsp] = revocation_method_flags; |
| 354 | 372 |
| 355 // TODO(ukai): need to find out if we need to call OCSP-related NSS functions, | 373 // TODO(ukai): need to find out if we need to call OCSP-related NSS functions, |
|
wtc
2009/08/13 00:35:33
Please remove this TODO comment. Alexei told me t
| |
| 356 // CERT_EnableOCSPChecking, CERT_DisableOCSPDefaultResponder and | 374 // CERT_EnableOCSPChecking, CERT_DisableOCSPDefaultResponder and |
| 357 // CERT_SetOCSPFailureMode. | 375 // CERT_SetOCSPFailureMode. |
| 358 CERTRevocationMethodIndex preferred_revocation_methods[1]; | 376 CERTRevocationMethodIndex preferred_revocation_methods[1]; |
| 359 preferred_revocation_methods[0] = cert_revocation_method_ocsp; | 377 preferred_revocation_methods[0] = cert_revocation_method_ocsp; |
| 360 | 378 |
| 361 CERTRevocationFlags revocation_flags; | 379 CERTRevocationFlags revocation_flags; |
| 362 revocation_flags.leafTests.number_of_defined_methods = | 380 revocation_flags.leafTests.number_of_defined_methods = |
| 363 arraysize(method_flags); | 381 arraysize(method_flags); |
| 364 revocation_flags.leafTests.cert_rev_flags_per_method = method_flags; | 382 revocation_flags.leafTests.cert_rev_flags_per_method = method_flags; |
| 365 revocation_flags.leafTests.number_of_preferred_methods = | 383 revocation_flags.leafTests.number_of_preferred_methods = |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 405 if (rv != SECSuccess) { | 423 if (rv != SECSuccess) { |
| 406 LOG(ERROR) << "Cert has no policies extension."; | 424 LOG(ERROR) << "Cert has no policies extension."; |
| 407 return false; | 425 return false; |
| 408 } | 426 } |
| 409 CERTCertificatePolicies* policies = | 427 CERTCertificatePolicies* policies = |
| 410 CERT_DecodeCertificatePoliciesExtension(&policy_ext); | 428 CERT_DecodeCertificatePoliciesExtension(&policy_ext); |
| 411 if (!policies) { | 429 if (!policies) { |
| 412 LOG(ERROR) << "Failed to decode certificate policy."; | 430 LOG(ERROR) << "Failed to decode certificate policy."; |
| 413 return false; | 431 return false; |
| 414 } | 432 } |
| 433 ScopedCERTCertificatePolicies scoped_policies(policies); | |
|
alv
2009/08/12 18:40:42
It will work, but it is too fancy and increases si
wtc
2009/08/13 00:38:22
I, a C programmer, agree with the "too fancy" opin
| |
| 415 CERTPolicyInfo** policy_infos = policies->policyInfos; | 434 CERTPolicyInfo** policy_infos = policies->policyInfos; |
| 416 while (*policy_infos != NULL) { | 435 while (*policy_infos != NULL) { |
| 417 CERTPolicyInfo* policy_info = *policy_infos++; | 436 CERTPolicyInfo* policy_info = *policy_infos++; |
| 418 SECOidTag oid_tag = policy_info->oid; | 437 SECOidTag oid_tag = policy_info->oid; |
| 419 if (oid_tag == SEC_OID_UNKNOWN) | 438 if (oid_tag == SEC_OID_UNKNOWN) |
| 420 continue; | 439 continue; |
| 421 if (oid_tag == ev_policy_tag) | 440 if (oid_tag == ev_policy_tag) |
| 422 return true; | 441 return true; |
| 423 } | 442 } |
| 424 LOG(ERROR) << "No EV Policy Tag"; | 443 LOG(ERROR) << "No EV Policy Tag"; |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 515 if (IsCertStatusError(verify_result->cert_status)) | 534 if (IsCertStatusError(verify_result->cert_status)) |
| 516 return MapCertStatusToNetError(verify_result->cert_status); | 535 return MapCertStatusToNetError(verify_result->cert_status); |
| 517 | 536 |
| 518 if ((flags & VERIFY_EV_CERT) && VerifyEV()) | 537 if ((flags & VERIFY_EV_CERT) && VerifyEV()) |
| 519 verify_result->cert_status |= CERT_STATUS_IS_EV; | 538 verify_result->cert_status |= CERT_STATUS_IS_EV; |
| 520 return OK; | 539 return OK; |
| 521 } | 540 } |
| 522 | 541 |
| 523 // Studied Mozilla's code (esp. security/manager/ssl/src/nsIdentityChecking.cpp | 542 // Studied Mozilla's code (esp. security/manager/ssl/src/nsIdentityChecking.cpp |
| 524 // and nsNSSCertHelper.cpp) to learn how to verify EV certificate. | 543 // and nsNSSCertHelper.cpp) to learn how to verify EV certificate. |
| 525 // TODO(wtc): We may be able to request cert_po_policyOID and just | 544 // TODO(wtc): Possible optimization is that we get the trust anchor from |
| 526 // check if any of the returned policies is the EV policy of the trust anchor. | |
| 527 // Another possible optimization is that we get the trust anchor from | |
| 528 // the first PKIXVerifyCert call. We look up the EV policy for the trust | 545 // the first PKIXVerifyCert call. We look up the EV policy for the trust |
| 529 // anchor. If the trust anchor has no EV policy, we know the cert isn't EV. | 546 // anchor. If the trust anchor has no EV policy, we know the cert isn't EV. |
| 530 // Otherwise, we pass just that EV policy (as opposed to all the EV policies) | 547 // Otherwise, we pass just that EV policy (as opposed to all the EV policies) |
| 531 // to the second PKIXVerifyCert call. | 548 // to the second PKIXVerifyCert call. |
| 532 bool X509Certificate::VerifyEV() const { | 549 bool X509Certificate::VerifyEV() const { |
| 533 net::EVRootCAMetadata* metadata = net::EVRootCAMetadata::GetInstance(); | 550 net::EVRootCAMetadata* metadata = net::EVRootCAMetadata::GetInstance(); |
| 534 | 551 |
| 535 CERTValOutParam cvout[3]; | 552 CERTValOutParam cvout[3]; |
| 536 int cvout_index = 0; | 553 int cvout_index = 0; |
| 537 cvout[cvout_index].type = cert_po_trustAnchor; | 554 cvout[cvout_index].type = cert_po_trustAnchor; |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 591 DCHECK(0 != cert->derCert.len); | 608 DCHECK(0 != cert->derCert.len); |
| 592 | 609 |
| 593 SECStatus rv = HASH_HashBuf(HASH_AlgSHA1, sha1.data, | 610 SECStatus rv = HASH_HashBuf(HASH_AlgSHA1, sha1.data, |
| 594 cert->derCert.data, cert->derCert.len); | 611 cert->derCert.data, cert->derCert.len); |
| 595 DCHECK(rv == SECSuccess); | 612 DCHECK(rv == SECSuccess); |
| 596 | 613 |
| 597 return sha1; | 614 return sha1; |
| 598 } | 615 } |
| 599 | 616 |
| 600 } // namespace net | 617 } // namespace net |
| OLD | NEW |