Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(156)

Side by Side Diff: net/cert/cert_verify_proc_nss.cc

Issue 266243004: Clang format slam. Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/cert/cert_verify_proc_nss.h" 5 #include "net/cert/cert_verify_proc_nss.h"
6 6
7 #include <string> 7 #include <string>
8 #include <vector> 8 #include <vector>
9 9
10 #include <cert.h> 10 #include <cert.h>
(...skipping 25 matching lines...) Expand all
36 namespace net { 36 namespace net {
37 37
38 namespace { 38 namespace {
39 39
40 typedef scoped_ptr< 40 typedef scoped_ptr<
41 CERTCertificatePolicies, 41 CERTCertificatePolicies,
42 crypto::NSSDestroyer<CERTCertificatePolicies, 42 crypto::NSSDestroyer<CERTCertificatePolicies,
43 CERT_DestroyCertificatePoliciesExtension> > 43 CERT_DestroyCertificatePoliciesExtension> >
44 ScopedCERTCertificatePolicies; 44 ScopedCERTCertificatePolicies;
45 45
46 typedef scoped_ptr< 46 typedef scoped_ptr<CERTCertList,
47 CERTCertList, 47 crypto::NSSDestroyer<CERTCertList, CERT_DestroyCertList> >
48 crypto::NSSDestroyer<CERTCertList, CERT_DestroyCertList> >
49 ScopedCERTCertList; 48 ScopedCERTCertList;
50 49
51 // ScopedCERTValOutParam manages destruction of values in the CERTValOutParam 50 // ScopedCERTValOutParam manages destruction of values in the CERTValOutParam
52 // array that cvout points to. cvout must be initialized as passed to 51 // array that cvout points to. cvout must be initialized as passed to
53 // CERT_PKIXVerifyCert, so that the array must be terminated with 52 // CERT_PKIXVerifyCert, so that the array must be terminated with
54 // cert_po_end type. 53 // cert_po_end type.
55 // When it goes out of scope, it destroys values of cert_po_trustAnchor 54 // When it goes out of scope, it destroys values of cert_po_trustAnchor
56 // and cert_po_certList types, but doesn't release the array itself. 55 // and cert_po_certList types, but doesn't release the array itself.
57 class ScopedCERTValOutParam { 56 class ScopedCERTValOutParam {
58 public: 57 public:
59 explicit ScopedCERTValOutParam(CERTValOutParam* cvout) : cvout_(cvout) {} 58 explicit ScopedCERTValOutParam(CERTValOutParam* cvout) : cvout_(cvout) {}
60 59
61 ~ScopedCERTValOutParam() { 60 ~ScopedCERTValOutParam() { Clear(); }
62 Clear();
63 }
64 61
65 // Free the internal resources, but do not release the array itself. 62 // Free the internal resources, but do not release the array itself.
66 void Clear() { 63 void Clear() {
67 if (cvout_ == NULL) 64 if (cvout_ == NULL)
68 return; 65 return;
69 for (CERTValOutParam *p = cvout_; p->type != cert_po_end; p++) { 66 for (CERTValOutParam* p = cvout_; p->type != cert_po_end; p++) {
70 switch (p->type) { 67 switch (p->type) {
71 case cert_po_trustAnchor: 68 case cert_po_trustAnchor:
72 if (p->value.pointer.cert) { 69 if (p->value.pointer.cert) {
73 CERT_DestroyCertificate(p->value.pointer.cert); 70 CERT_DestroyCertificate(p->value.pointer.cert);
74 p->value.pointer.cert = NULL; 71 p->value.pointer.cert = NULL;
75 } 72 }
76 break; 73 break;
77 case cert_po_certList: 74 case cert_po_certList:
78 if (p->value.pointer.chain) { 75 if (p->value.pointer.chain) {
79 CERT_DestroyCertList(p->value.pointer.chain); 76 CERT_DestroyCertList(p->value.pointer.chain);
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
220 } 217 }
221 218
222 // IsKnownRoot returns true if the given certificate is one that we believe 219 // IsKnownRoot returns true if the given certificate is one that we believe
223 // is a standard (as opposed to user-installed) root. 220 // is a standard (as opposed to user-installed) root.
224 bool IsKnownRoot(CERTCertificate* root) { 221 bool IsKnownRoot(CERTCertificate* root) {
225 if (!root || !root->slot) 222 if (!root || !root->slot)
226 return false; 223 return false;
227 224
228 // This magic name is taken from 225 // This magic name is taken from
229 // http://bonsai.mozilla.org/cvsblame.cgi?file=mozilla/security/nss/lib/ckfw/b uiltins/constants.c&rev=1.13&mark=86,89#79 226 // http://bonsai.mozilla.org/cvsblame.cgi?file=mozilla/security/nss/lib/ckfw/b uiltins/constants.c&rev=1.13&mark=86,89#79
230 return 0 == strcmp(PK11_GetSlotName(root->slot), 227 return 0 == strcmp(PK11_GetSlotName(root->slot), "NSS Builtin Objects");
231 "NSS Builtin Objects");
232 } 228 }
233 229
234 // Returns true if the given certificate is one of the additional trust anchors. 230 // Returns true if the given certificate is one of the additional trust anchors.
235 bool IsAdditionalTrustAnchor(CERTCertList* additional_trust_anchors, 231 bool IsAdditionalTrustAnchor(CERTCertList* additional_trust_anchors,
236 CERTCertificate* root) { 232 CERTCertificate* root) {
237 if (!additional_trust_anchors || !root) 233 if (!additional_trust_anchors || !root)
238 return false; 234 return false;
239 for (CERTCertListNode* node = CERT_LIST_HEAD(additional_trust_anchors); 235 for (CERTCertListNode* node = CERT_LIST_HEAD(additional_trust_anchors);
240 !CERT_LIST_END(node, additional_trust_anchors); 236 !CERT_LIST_END(node, additional_trust_anchors);
241 node = CERT_LIST_NEXT(node)) { 237 node = CERT_LIST_NEXT(node)) {
(...skipping 30 matching lines...) Expand all
272 } 268 }
273 if (root) 269 if (root)
274 certs.push_back(root); 270 certs.push_back(root);
275 271
276 bool covered = true; 272 bool covered = true;
277 273
278 // We iterate from the root certificate down to the leaf, keeping track of 274 // We iterate from the root certificate down to the leaf, keeping track of
279 // the issuer's SPKI at each step. 275 // the issuer's SPKI at each step.
280 std::string issuer_spki_hash; 276 std::string issuer_spki_hash;
281 for (std::vector<CERTCertificate*>::reverse_iterator i = certs.rbegin(); 277 for (std::vector<CERTCertificate*>::reverse_iterator i = certs.rbegin();
282 i != certs.rend(); ++i) { 278 i != certs.rend();
279 ++i) {
283 CERTCertificate* cert = *i; 280 CERTCertificate* cert = *i;
284 281
285 base::StringPiece der(reinterpret_cast<char*>(cert->derCert.data), 282 base::StringPiece der(reinterpret_cast<char*>(cert->derCert.data),
286 cert->derCert.len); 283 cert->derCert.len);
287 284
288 base::StringPiece spki; 285 base::StringPiece spki;
289 if (!asn1::ExtractSPKIFromDERCert(der, &spki)) { 286 if (!asn1::ExtractSPKIFromDERCert(der, &spki)) {
290 NOTREACHED(); 287 NOTREACHED();
291 covered = false; 288 covered = false;
292 continue; 289 continue;
293 } 290 }
294 const std::string spki_hash = crypto::SHA256HashString(spki); 291 const std::string spki_hash = crypto::SHA256HashString(spki);
295 292
296 base::StringPiece serial_number = base::StringPiece( 293 base::StringPiece serial_number =
297 reinterpret_cast<char*>(cert->serialNumber.data), 294 base::StringPiece(reinterpret_cast<char*>(cert->serialNumber.data),
298 cert->serialNumber.len); 295 cert->serialNumber.len);
299 296
300 CRLSet::Result result = crl_set->CheckSPKI(spki_hash); 297 CRLSet::Result result = crl_set->CheckSPKI(spki_hash);
301 298
302 if (result != CRLSet::REVOKED && !issuer_spki_hash.empty()) 299 if (result != CRLSet::REVOKED && !issuer_spki_hash.empty())
303 result = crl_set->CheckSerial(serial_number, issuer_spki_hash); 300 result = crl_set->CheckSerial(serial_number, issuer_spki_hash);
304 301
305 issuer_spki_hash = spki_hash; 302 issuer_spki_hash = spki_hash;
306 303
307 switch (result) { 304 switch (result) {
308 case CRLSet::REVOKED: 305 case CRLSet::REVOKED:
309 return kCRLSetRevoked; 306 return kCRLSetRevoked;
310 case CRLSet::UNKNOWN: 307 case CRLSet::UNKNOWN:
311 covered = false; 308 covered = false;
312 continue; 309 continue;
313 case CRLSet::GOOD: 310 case CRLSet::GOOD:
314 continue; 311 continue;
315 default: 312 default:
316 NOTREACHED(); 313 NOTREACHED();
317 covered = false; 314 covered = false;
318 continue; 315 continue;
319 } 316 }
320 } 317 }
321 318
322 if (!covered || crl_set->IsExpired()) 319 if (!covered || crl_set->IsExpired())
323 return kCRLSetUnknown; 320 return kCRLSetUnknown;
324 return kCRLSetOk; 321 return kCRLSetOk;
325 } 322 }
326 323
327 // Forward declarations. 324 // Forward declarations.
328 SECStatus RetryPKIXVerifyCertWithWorkarounds( 325 SECStatus RetryPKIXVerifyCertWithWorkarounds(CERTCertificate* cert_handle,
329 CERTCertificate* cert_handle, int num_policy_oids, 326 int num_policy_oids,
330 bool cert_io_enabled, std::vector<CERTValInParam>* cvin, 327 bool cert_io_enabled,
331 CERTValOutParam* cvout); 328 std::vector<CERTValInParam>* cvin,
329 CERTValOutParam* cvout);
332 SECOidTag GetFirstCertPolicy(CERTCertificate* cert_handle); 330 SECOidTag GetFirstCertPolicy(CERTCertificate* cert_handle);
333 331
334 // Call CERT_PKIXVerifyCert for the cert_handle. 332 // Call CERT_PKIXVerifyCert for the cert_handle.
335 // Verification results are stored in an array of CERTValOutParam. 333 // Verification results are stored in an array of CERTValOutParam.
336 // If |hard_fail| is true, and no policy_oids are supplied (eg: EV is NOT being 334 // If |hard_fail| is true, and no policy_oids are supplied (eg: EV is NOT being
337 // checked), then the failure to obtain valid CRL/OCSP information for all 335 // checked), then the failure to obtain valid CRL/OCSP information for all
338 // certificates that contain CRL/OCSP URLs will cause the certificate to be 336 // certificates that contain CRL/OCSP URLs will cause the certificate to be
339 // treated as if it was revoked. Since failures may be caused by transient 337 // treated as if it was revoked. Since failures may be caused by transient
340 // network failures or by malicious attackers, in general, hard_fail should be 338 // network failures or by malicious attackers, in general, hard_fail should be
341 // false. 339 // false.
342 // If policy_oids is not NULL and num_policy_oids is positive, policies 340 // If policy_oids is not NULL and num_policy_oids is positive, policies
343 // are also checked. 341 // are also checked.
344 // additional_trust_anchors is an optional list of certificates that can be 342 // additional_trust_anchors is an optional list of certificates that can be
345 // trusted as anchors when building a certificate chain. 343 // trusted as anchors when building a certificate chain.
346 // Caller must initialize cvout before calling this function. 344 // Caller must initialize cvout before calling this function.
347 SECStatus PKIXVerifyCert(CERTCertificate* cert_handle, 345 SECStatus PKIXVerifyCert(CERTCertificate* cert_handle,
348 bool check_revocation, 346 bool check_revocation,
349 bool hard_fail, 347 bool hard_fail,
350 bool cert_io_enabled, 348 bool cert_io_enabled,
351 const SECOidTag* policy_oids, 349 const SECOidTag* policy_oids,
352 int num_policy_oids, 350 int num_policy_oids,
353 CERTCertList* additional_trust_anchors, 351 CERTCertList* additional_trust_anchors,
354 CERTChainVerifyCallback* chain_verify_callback, 352 CERTChainVerifyCallback* chain_verify_callback,
355 CERTValOutParam* cvout) { 353 CERTValOutParam* cvout) {
356 bool use_crl = check_revocation; 354 bool use_crl = check_revocation;
357 bool use_ocsp = check_revocation; 355 bool use_ocsp = check_revocation;
358 356
359 PRUint64 revocation_method_flags = 357 PRUint64 revocation_method_flags = CERT_REV_M_DO_NOT_TEST_USING_THIS_METHOD |
360 CERT_REV_M_DO_NOT_TEST_USING_THIS_METHOD | 358 CERT_REV_M_ALLOW_NETWORK_FETCHING |
361 CERT_REV_M_ALLOW_NETWORK_FETCHING | 359 CERT_REV_M_IGNORE_IMPLICIT_DEFAULT_SOURCE |
362 CERT_REV_M_IGNORE_IMPLICIT_DEFAULT_SOURCE | 360 CERT_REV_M_IGNORE_MISSING_FRESH_INFO |
363 CERT_REV_M_IGNORE_MISSING_FRESH_INFO | 361 CERT_REV_M_STOP_TESTING_ON_FRESH_INFO;
364 CERT_REV_M_STOP_TESTING_ON_FRESH_INFO;
365 PRUint64 revocation_method_independent_flags = 362 PRUint64 revocation_method_independent_flags =
366 CERT_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST; 363 CERT_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST;
367 if (check_revocation && policy_oids && num_policy_oids > 0) { 364 if (check_revocation && policy_oids && num_policy_oids > 0) {
368 // EV verification requires revocation checking. Consider the certificate 365 // EV verification requires revocation checking. Consider the certificate
369 // revoked if we don't have revocation info. 366 // revoked if we don't have revocation info.
370 // TODO(wtc): Add a bool parameter to expressly specify we're doing EV 367 // TODO(wtc): Add a bool parameter to expressly specify we're doing EV
371 // verification or we want strict revocation flags. 368 // verification or we want strict revocation flags.
372 revocation_method_flags |= CERT_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE; 369 revocation_method_flags |= CERT_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE;
373 revocation_method_independent_flags |= 370 revocation_method_independent_flags |=
374 CERT_REV_MI_REQUIRE_SOME_FRESH_INFO_AVAILABLE; 371 CERT_REV_MI_REQUIRE_SOME_FRESH_INFO_AVAILABLE;
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
413 410
414 revocation_flags.chainTests.number_of_defined_methods = 411 revocation_flags.chainTests.number_of_defined_methods =
415 arraysize(method_flags); 412 arraysize(method_flags);
416 revocation_flags.chainTests.cert_rev_flags_per_method = method_flags; 413 revocation_flags.chainTests.cert_rev_flags_per_method = method_flags;
417 revocation_flags.chainTests.number_of_preferred_methods = 414 revocation_flags.chainTests.number_of_preferred_methods =
418 arraysize(preferred_revocation_methods); 415 arraysize(preferred_revocation_methods);
419 revocation_flags.chainTests.preferred_methods = preferred_revocation_methods; 416 revocation_flags.chainTests.preferred_methods = preferred_revocation_methods;
420 revocation_flags.chainTests.cert_rev_method_independent_flags = 417 revocation_flags.chainTests.cert_rev_method_independent_flags =
421 revocation_method_independent_flags; 418 revocation_method_independent_flags;
422 419
423
424 std::vector<CERTValInParam> cvin; 420 std::vector<CERTValInParam> cvin;
425 cvin.reserve(7); 421 cvin.reserve(7);
426 CERTValInParam in_param; 422 CERTValInParam in_param;
427 in_param.type = cert_pi_revocationFlags; 423 in_param.type = cert_pi_revocationFlags;
428 in_param.value.pointer.revocation = &revocation_flags; 424 in_param.value.pointer.revocation = &revocation_flags;
429 cvin.push_back(in_param); 425 cvin.push_back(in_param);
430 if (policy_oids && num_policy_oids > 0) { 426 if (policy_oids && num_policy_oids > 0) {
431 in_param.type = cert_pi_policyOID; 427 in_param.type = cert_pi_policyOID;
432 in_param.value.arraySize = num_policy_oids; 428 in_param.value.arraySize = num_policy_oids;
433 in_param.value.array.oids = policy_oids; 429 in_param.value.array.oids = policy_oids;
434 cvin.push_back(in_param); 430 cvin.push_back(in_param);
435 } 431 }
436 if (additional_trust_anchors) { 432 if (additional_trust_anchors) {
437 in_param.type = cert_pi_trustAnchors; 433 in_param.type = cert_pi_trustAnchors;
438 in_param.value.pointer.chain = additional_trust_anchors; 434 in_param.value.pointer.chain = additional_trust_anchors;
439 cvin.push_back(in_param); 435 cvin.push_back(in_param);
440 in_param.type = cert_pi_useOnlyTrustAnchors; 436 in_param.type = cert_pi_useOnlyTrustAnchors;
441 in_param.value.scalar.b = PR_FALSE; 437 in_param.value.scalar.b = PR_FALSE;
442 cvin.push_back(in_param); 438 cvin.push_back(in_param);
443 } 439 }
444 if (chain_verify_callback) { 440 if (chain_verify_callback) {
445 in_param.type = cert_pi_chainVerifyCallback; 441 in_param.type = cert_pi_chainVerifyCallback;
446 in_param.value.pointer.chainVerifyCallback = chain_verify_callback; 442 in_param.value.pointer.chainVerifyCallback = chain_verify_callback;
447 cvin.push_back(in_param); 443 cvin.push_back(in_param);
448 } 444 }
449 in_param.type = cert_pi_end; 445 in_param.type = cert_pi_end;
450 cvin.push_back(in_param); 446 cvin.push_back(in_param);
451 447
452 SECStatus rv = CERT_PKIXVerifyCert(cert_handle, certificateUsageSSLServer, 448 SECStatus rv = CERT_PKIXVerifyCert(
453 &cvin[0], cvout, NULL); 449 cert_handle, certificateUsageSSLServer, &cvin[0], cvout, NULL);
454 if (rv != SECSuccess) { 450 if (rv != SECSuccess) {
455 rv = RetryPKIXVerifyCertWithWorkarounds(cert_handle, num_policy_oids, 451 rv = RetryPKIXVerifyCertWithWorkarounds(
456 cert_io_enabled, &cvin, cvout); 452 cert_handle, num_policy_oids, cert_io_enabled, &cvin, cvout);
457 } 453 }
458 return rv; 454 return rv;
459 } 455 }
460 456
461 // PKIXVerifyCert calls this function to work around some bugs in 457 // PKIXVerifyCert calls this function to work around some bugs in
462 // CERT_PKIXVerifyCert. All the arguments of this function are either the 458 // CERT_PKIXVerifyCert. All the arguments of this function are either the
463 // arguments or local variables of PKIXVerifyCert. 459 // arguments or local variables of PKIXVerifyCert.
464 SECStatus RetryPKIXVerifyCertWithWorkarounds( 460 SECStatus RetryPKIXVerifyCertWithWorkarounds(CERTCertificate* cert_handle,
465 CERTCertificate* cert_handle, int num_policy_oids, 461 int num_policy_oids,
466 bool cert_io_enabled, std::vector<CERTValInParam>* cvin, 462 bool cert_io_enabled,
467 CERTValOutParam* cvout) { 463 std::vector<CERTValInParam>* cvin,
464 CERTValOutParam* cvout) {
468 // We call this function when the first CERT_PKIXVerifyCert call in 465 // We call this function when the first CERT_PKIXVerifyCert call in
469 // PKIXVerifyCert failed, so we initialize |rv| to SECFailure. 466 // PKIXVerifyCert failed, so we initialize |rv| to SECFailure.
470 SECStatus rv = SECFailure; 467 SECStatus rv = SECFailure;
471 int nss_error = PORT_GetError(); 468 int nss_error = PORT_GetError();
472 CERTValInParam in_param; 469 CERTValInParam in_param;
473 470
474 // If we get SEC_ERROR_UNKNOWN_ISSUER, we may be missing an intermediate 471 // If we get SEC_ERROR_UNKNOWN_ISSUER, we may be missing an intermediate
475 // CA certificate, so we retry with cert_pi_useAIACertFetch. 472 // CA certificate, so we retry with cert_pi_useAIACertFetch.
476 // cert_pi_useAIACertFetch has several bugs in its error handling and 473 // cert_pi_useAIACertFetch has several bugs in its error handling and
477 // error reporting (NSS bug 528743), so we don't use it by default. 474 // error reporting (NSS bug 528743), so we don't use it by default.
478 // Note: When building a certificate chain, CERT_PKIXVerifyCert may 475 // Note: When building a certificate chain, CERT_PKIXVerifyCert may
479 // incorrectly pick a CA certificate with the same subject name as the 476 // incorrectly pick a CA certificate with the same subject name as the
480 // missing intermediate CA certificate, and fail with the 477 // missing intermediate CA certificate, and fail with the
481 // SEC_ERROR_BAD_SIGNATURE error (NSS bug 524013), so we also retry with 478 // SEC_ERROR_BAD_SIGNATURE error (NSS bug 524013), so we also retry with
482 // cert_pi_useAIACertFetch on SEC_ERROR_BAD_SIGNATURE. 479 // cert_pi_useAIACertFetch on SEC_ERROR_BAD_SIGNATURE.
483 if (cert_io_enabled && 480 if (cert_io_enabled && (nss_error == SEC_ERROR_UNKNOWN_ISSUER ||
484 (nss_error == SEC_ERROR_UNKNOWN_ISSUER || 481 nss_error == SEC_ERROR_BAD_SIGNATURE)) {
485 nss_error == SEC_ERROR_BAD_SIGNATURE)) { 482 DCHECK_EQ(cvin->back().type, cert_pi_end);
486 DCHECK_EQ(cvin->back().type, cert_pi_end);
487 cvin->pop_back(); 483 cvin->pop_back();
488 in_param.type = cert_pi_useAIACertFetch; 484 in_param.type = cert_pi_useAIACertFetch;
489 in_param.value.scalar.b = PR_TRUE; 485 in_param.value.scalar.b = PR_TRUE;
490 cvin->push_back(in_param); 486 cvin->push_back(in_param);
491 in_param.type = cert_pi_end; 487 in_param.type = cert_pi_end;
492 cvin->push_back(in_param); 488 cvin->push_back(in_param);
493 rv = CERT_PKIXVerifyCert(cert_handle, certificateUsageSSLServer, 489 rv = CERT_PKIXVerifyCert(
494 &(*cvin)[0], cvout, NULL); 490 cert_handle, certificateUsageSSLServer, &(*cvin)[0], cvout, NULL);
495 if (rv == SECSuccess) 491 if (rv == SECSuccess)
496 return rv; 492 return rv;
497 int new_nss_error = PORT_GetError(); 493 int new_nss_error = PORT_GetError();
498 if (new_nss_error == SEC_ERROR_INVALID_ARGS || 494 if (new_nss_error == SEC_ERROR_INVALID_ARGS ||
499 new_nss_error == SEC_ERROR_UNKNOWN_AIA_LOCATION_TYPE || 495 new_nss_error == SEC_ERROR_UNKNOWN_AIA_LOCATION_TYPE ||
500 new_nss_error == SEC_ERROR_BAD_INFO_ACCESS_LOCATION || 496 new_nss_error == SEC_ERROR_BAD_INFO_ACCESS_LOCATION ||
501 new_nss_error == SEC_ERROR_BAD_HTTP_RESPONSE || 497 new_nss_error == SEC_ERROR_BAD_HTTP_RESPONSE ||
502 new_nss_error == SEC_ERROR_BAD_LDAP_RESPONSE || 498 new_nss_error == SEC_ERROR_BAD_LDAP_RESPONSE ||
503 !IS_SEC_ERROR(new_nss_error)) { 499 !IS_SEC_ERROR(new_nss_error)) {
504 // Use the original error code because of cert_pi_useAIACertFetch's 500 // Use the original error code because of cert_pi_useAIACertFetch's
505 // bad error reporting. 501 // bad error reporting.
506 PORT_SetError(nss_error); 502 PORT_SetError(nss_error);
507 return rv; 503 return rv;
508 } 504 }
509 nss_error = new_nss_error; 505 nss_error = new_nss_error;
510 } 506 }
511 507
512 // If an intermediate CA certificate has requireExplicitPolicy in its 508 // If an intermediate CA certificate has requireExplicitPolicy in its
513 // policyConstraints extension, CERT_PKIXVerifyCert fails with 509 // policyConstraints extension, CERT_PKIXVerifyCert fails with
514 // SEC_ERROR_POLICY_VALIDATION_FAILED because we didn't specify any 510 // SEC_ERROR_POLICY_VALIDATION_FAILED because we didn't specify any
515 // certificate policy (NSS bug 552775). So we retry with the certificate 511 // certificate policy (NSS bug 552775). So we retry with the certificate
516 // policy found in the server certificate. 512 // policy found in the server certificate.
517 if (nss_error == SEC_ERROR_POLICY_VALIDATION_FAILED && 513 if (nss_error == SEC_ERROR_POLICY_VALIDATION_FAILED && num_policy_oids == 0) {
518 num_policy_oids == 0) {
519 SECOidTag policy = GetFirstCertPolicy(cert_handle); 514 SECOidTag policy = GetFirstCertPolicy(cert_handle);
520 if (policy != SEC_OID_UNKNOWN) { 515 if (policy != SEC_OID_UNKNOWN) {
521 DCHECK_EQ(cvin->back().type, cert_pi_end); 516 DCHECK_EQ(cvin->back().type, cert_pi_end);
522 cvin->pop_back(); 517 cvin->pop_back();
523 in_param.type = cert_pi_policyOID; 518 in_param.type = cert_pi_policyOID;
524 in_param.value.arraySize = 1; 519 in_param.value.arraySize = 1;
525 in_param.value.array.oids = &policy; 520 in_param.value.array.oids = &policy;
526 cvin->push_back(in_param); 521 cvin->push_back(in_param);
527 in_param.type = cert_pi_end; 522 in_param.type = cert_pi_end;
528 cvin->push_back(in_param); 523 cvin->push_back(in_param);
529 rv = CERT_PKIXVerifyCert(cert_handle, certificateUsageSSLServer, 524 rv = CERT_PKIXVerifyCert(
530 &(*cvin)[0], cvout, NULL); 525 cert_handle, certificateUsageSSLServer, &(*cvin)[0], cvout, NULL);
531 if (rv != SECSuccess) { 526 if (rv != SECSuccess) {
532 // Use the original error code. 527 // Use the original error code.
533 PORT_SetError(nss_error); 528 PORT_SetError(nss_error);
534 } 529 }
535 } 530 }
536 } 531 }
537 532
538 return rv; 533 return rv;
539 } 534 }
540 535
541 // Decodes the certificatePolicies extension of the certificate. Returns 536 // Decodes the certificatePolicies extension of the certificate. Returns
542 // NULL if the certificate doesn't have the extension or the extension can't 537 // NULL if the certificate doesn't have the extension or the extension can't
543 // be decoded. The returned value must be freed with a 538 // be decoded. The returned value must be freed with a
544 // CERT_DestroyCertificatePoliciesExtension call. 539 // CERT_DestroyCertificatePoliciesExtension call.
545 CERTCertificatePolicies* DecodeCertPolicies( 540 CERTCertificatePolicies* DecodeCertPolicies(CERTCertificate* cert_handle) {
546 CERTCertificate* cert_handle) {
547 SECItem policy_ext; 541 SECItem policy_ext;
548 SECStatus rv = CERT_FindCertExtension(cert_handle, 542 SECStatus rv = CERT_FindCertExtension(
549 SEC_OID_X509_CERTIFICATE_POLICIES, 543 cert_handle, SEC_OID_X509_CERTIFICATE_POLICIES, &policy_ext);
550 &policy_ext);
551 if (rv != SECSuccess) 544 if (rv != SECSuccess)
552 return NULL; 545 return NULL;
553 CERTCertificatePolicies* policies = 546 CERTCertificatePolicies* policies =
554 CERT_DecodeCertificatePoliciesExtension(&policy_ext); 547 CERT_DecodeCertificatePoliciesExtension(&policy_ext);
555 SECITEM_FreeItem(&policy_ext, PR_FALSE); 548 SECITEM_FreeItem(&policy_ext, PR_FALSE);
556 return policies; 549 return policies;
557 } 550 }
558 551
559 // Returns the OID tag for the first certificate policy in the certificate's 552 // Returns the OID tag for the first certificate policy in the certificate's
560 // certificatePolicies extension. Returns SEC_OID_UNKNOWN if the certificate 553 // certificatePolicies extension. Returns SEC_OID_UNKNOWN if the certificate
(...skipping 22 matching lines...) Expand all
583 od.mechanism = CKM_INVALID_MECHANISM; 576 od.mechanism = CKM_INVALID_MECHANISM;
584 od.supportedExtension = INVALID_CERT_EXTENSION; 577 od.supportedExtension = INVALID_CERT_EXTENSION;
585 return SECOID_AddEntry(&od); 578 return SECOID_AddEntry(&od);
586 } 579 }
587 580
588 HashValue CertPublicKeyHashSHA1(CERTCertificate* cert) { 581 HashValue CertPublicKeyHashSHA1(CERTCertificate* cert) {
589 HashValue hash(HASH_VALUE_SHA1); 582 HashValue hash(HASH_VALUE_SHA1);
590 #if defined(OS_IOS) 583 #if defined(OS_IOS)
591 CC_SHA1(cert->derPublicKey.data, cert->derPublicKey.len, hash.data()); 584 CC_SHA1(cert->derPublicKey.data, cert->derPublicKey.len, hash.data());
592 #else 585 #else
593 SECStatus rv = HASH_HashBuf(HASH_AlgSHA1, hash.data(), 586 SECStatus rv = HASH_HashBuf(HASH_AlgSHA1,
594 cert->derPublicKey.data, cert->derPublicKey.len); 587 hash.data(),
588 cert->derPublicKey.data,
589 cert->derPublicKey.len);
595 DCHECK_EQ(SECSuccess, rv); 590 DCHECK_EQ(SECSuccess, rv);
596 #endif 591 #endif
597 return hash; 592 return hash;
598 } 593 }
599 594
600 HashValue CertPublicKeyHashSHA256(CERTCertificate* cert) { 595 HashValue CertPublicKeyHashSHA256(CERTCertificate* cert) {
601 HashValue hash(HASH_VALUE_SHA256); 596 HashValue hash(HASH_VALUE_SHA256);
602 #if defined(OS_IOS) 597 #if defined(OS_IOS)
603 CC_SHA256(cert->derPublicKey.data, cert->derPublicKey.len, hash.data()); 598 CC_SHA256(cert->derPublicKey.data, cert->derPublicKey.len, hash.data());
604 #else 599 #else
605 SECStatus rv = HASH_HashBuf(HASH_AlgSHA256, hash.data(), 600 SECStatus rv = HASH_HashBuf(HASH_AlgSHA256,
606 cert->derPublicKey.data, cert->derPublicKey.len); 601 hash.data(),
602 cert->derPublicKey.data,
603 cert->derPublicKey.len);
607 DCHECK_EQ(rv, SECSuccess); 604 DCHECK_EQ(rv, SECSuccess);
608 #endif 605 #endif
609 return hash; 606 return hash;
610 } 607 }
611 608
612 void AppendPublicKeyHashes(CERTCertList* cert_list, 609 void AppendPublicKeyHashes(CERTCertList* cert_list,
613 CERTCertificate* root_cert, 610 CERTCertificate* root_cert,
614 HashValueVector* hashes) { 611 HashValueVector* hashes) {
615 for (CERTCertListNode* node = CERT_LIST_HEAD(cert_list); 612 for (CERTCertListNode* node = CERT_LIST_HEAD(cert_list);
616 !CERT_LIST_END(node, cert_list); 613 !CERT_LIST_END(node, cert_list);
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
674 cvout[cvout_index].value.pointer.chain = NULL; 671 cvout[cvout_index].value.pointer.chain = NULL;
675 int cvout_cert_list_index = cvout_index; 672 int cvout_cert_list_index = cvout_index;
676 cvout_index++; 673 cvout_index++;
677 cvout[cvout_index].type = cert_po_trustAnchor; 674 cvout[cvout_index].type = cert_po_trustAnchor;
678 cvout[cvout_index].value.pointer.cert = NULL; 675 cvout[cvout_index].value.pointer.cert = NULL;
679 int cvout_trust_anchor_index = cvout_index; 676 int cvout_trust_anchor_index = cvout_index;
680 cvout_index++; 677 cvout_index++;
681 cvout[cvout_index].type = cert_po_end; 678 cvout[cvout_index].type = cert_po_end;
682 ScopedCERTValOutParam scoped_cvout(cvout); 679 ScopedCERTValOutParam scoped_cvout(cvout);
683 680
684 SECStatus status = PKIXVerifyCert( 681 SECStatus status =
685 cert_handle, 682 PKIXVerifyCert(cert_handle,
686 rev_checking_enabled, 683 rev_checking_enabled,
687 true, /* hard fail is implied in EV. */ 684 true, /* hard fail is implied in EV. */
688 flags & CertVerifier::VERIFY_CERT_IO_ENABLED, 685 flags & CertVerifier::VERIFY_CERT_IO_ENABLED,
689 &ev_policy_oid, 686 &ev_policy_oid,
690 1, 687 1,
691 additional_trust_anchors, 688 additional_trust_anchors,
692 chain_verify_callback, 689 chain_verify_callback,
693 cvout); 690 cvout);
694 if (status != SECSuccess) 691 if (status != SECSuccess)
695 return false; 692 return false;
696 693
697 CERTCertificate* root_ca = 694 CERTCertificate* root_ca = cvout[cvout_trust_anchor_index].value.pointer.cert;
698 cvout[cvout_trust_anchor_index].value.pointer.cert;
699 if (root_ca == NULL) 695 if (root_ca == NULL)
700 return false; 696 return false;
701 697
702 // This second PKIXVerifyCert call could have found a different certification 698 // This second PKIXVerifyCert call could have found a different certification
703 // path and one or more of the certificates on this new path, that weren't on 699 // path and one or more of the certificates on this new path, that weren't on
704 // the old path, might have been revoked. 700 // the old path, might have been revoked.
705 if (crl_set) { 701 if (crl_set) {
706 CRLSetResult crl_set_result = CheckRevocationWithCRLSet( 702 CRLSetResult crl_set_result = CheckRevocationWithCRLSet(
707 cvout[cvout_cert_list_index].value.pointer.chain, 703 cvout[cvout_cert_list_index].value.pointer.chain,
708 cvout[cvout_trust_anchor_index].value.pointer.cert, 704 cvout[cvout_trust_anchor_index].value.pointer.cert,
709 crl_set); 705 crl_set);
710 if (crl_set_result == kCRLSetRevoked) 706 if (crl_set_result == kCRLSetRevoked)
711 return false; 707 return false;
712 } 708 }
713 709
714 #if defined(OS_IOS) 710 #if defined(OS_IOS)
715 SHA1HashValue fingerprint = x509_util_ios::CalculateFingerprintNSS(root_ca); 711 SHA1HashValue fingerprint = x509_util_ios::CalculateFingerprintNSS(root_ca);
716 #else 712 #else
717 SHA1HashValue fingerprint = 713 SHA1HashValue fingerprint = X509Certificate::CalculateFingerprint(root_ca);
718 X509Certificate::CalculateFingerprint(root_ca);
719 #endif 714 #endif
720 return metadata->HasEVPolicyOID(fingerprint, ev_policy_oid); 715 return metadata->HasEVPolicyOID(fingerprint, ev_policy_oid);
721 } 716 }
722 717
723 CERTCertList* CertificateListToCERTCertList(const CertificateList& list) { 718 CERTCertList* CertificateListToCERTCertList(const CertificateList& list) {
724 CERTCertList* result = CERT_NewCertList(); 719 CERTCertList* result = CERT_NewCertList();
725 for (size_t i = 0; i < list.size(); ++i) { 720 for (size_t i = 0; i < list.size(); ++i) {
726 #if defined(OS_IOS) 721 #if defined(OS_IOS)
727 // X509Certificate::os_cert_handle() on iOS is a SecCertificateRef; convert 722 // X509Certificate::os_cert_handle() on iOS is a SecCertificateRef; convert
728 // it to an NSS CERTCertificate. 723 // it to an NSS CERTCertificate.
729 CERTCertificate* cert = x509_util_ios::CreateNSSCertHandleFromOSHandle( 724 CERTCertificate* cert = x509_util_ios::CreateNSSCertHandleFromOSHandle(
730 list[i]->os_cert_handle()); 725 list[i]->os_cert_handle());
731 #else 726 #else
732 CERTCertificate* cert = list[i]->os_cert_handle(); 727 CERTCertificate* cert = list[i]->os_cert_handle();
733 #endif 728 #endif
734 CERT_AddCertToListTail(result, CERT_DupCertificate(cert)); 729 CERT_AddCertToListTail(result, CERT_DupCertificate(cert));
735 } 730 }
736 return result; 731 return result;
737 } 732 }
738 733
739 } // namespace 734 } // namespace
740 735
741 CertVerifyProcNSS::CertVerifyProcNSS() {} 736 CertVerifyProcNSS::CertVerifyProcNSS() {
737 }
742 738
743 CertVerifyProcNSS::~CertVerifyProcNSS() {} 739 CertVerifyProcNSS::~CertVerifyProcNSS() {
740 }
744 741
745 bool CertVerifyProcNSS::SupportsAdditionalTrustAnchors() const { 742 bool CertVerifyProcNSS::SupportsAdditionalTrustAnchors() const {
746 return true; 743 return true;
747 } 744 }
748 745
749 int CertVerifyProcNSS::VerifyInternalImpl( 746 int CertVerifyProcNSS::VerifyInternalImpl(
750 X509Certificate* cert, 747 X509Certificate* cert,
751 const std::string& hostname, 748 const std::string& hostname,
752 int flags, 749 int flags,
753 CRLSet* crl_set, 750 CRLSet* crl_set,
754 const CertificateList& additional_trust_anchors, 751 const CertificateList& additional_trust_anchors,
755 CERTChainVerifyCallback* chain_verify_callback, 752 CERTChainVerifyCallback* chain_verify_callback,
756 CertVerifyResult* verify_result) { 753 CertVerifyResult* verify_result) {
757 #if defined(OS_IOS) 754 #if defined(OS_IOS)
758 // For iOS, the entire chain must be loaded into NSS's in-memory certificate 755 // For iOS, the entire chain must be loaded into NSS's in-memory certificate
759 // store. 756 // store.
760 x509_util_ios::NSSCertChain scoped_chain(cert); 757 x509_util_ios::NSSCertChain scoped_chain(cert);
761 CERTCertificate* cert_handle = scoped_chain.cert_handle(); 758 CERTCertificate* cert_handle = scoped_chain.cert_handle();
762 #else 759 #else
763 CERTCertificate* cert_handle = cert->os_cert_handle(); 760 CERTCertificate* cert_handle = cert->os_cert_handle();
764 #endif // defined(OS_IOS) 761 #endif // defined(OS_IOS)
765 762
766 if (!cert->VerifyNameMatch(hostname, 763 if (!cert->VerifyNameMatch(hostname,
767 &verify_result->common_name_fallback_used)) { 764 &verify_result->common_name_fallback_used)) {
768 verify_result->cert_status |= CERT_STATUS_COMMON_NAME_INVALID; 765 verify_result->cert_status |= CERT_STATUS_COMMON_NAME_INVALID;
769 } 766 }
770 767
771 // Make sure that the cert is valid now. 768 // Make sure that the cert is valid now.
772 SECCertTimeValidity validity = CERT_CheckCertValidTimes( 769 SECCertTimeValidity validity =
773 cert_handle, PR_Now(), PR_TRUE); 770 CERT_CheckCertValidTimes(cert_handle, PR_Now(), PR_TRUE);
774 if (validity != secCertTimeValid) 771 if (validity != secCertTimeValid)
775 verify_result->cert_status |= CERT_STATUS_DATE_INVALID; 772 verify_result->cert_status |= CERT_STATUS_DATE_INVALID;
776 773
777 CERTValOutParam cvout[3]; 774 CERTValOutParam cvout[3];
778 int cvout_index = 0; 775 int cvout_index = 0;
779 cvout[cvout_index].type = cert_po_certList; 776 cvout[cvout_index].type = cert_po_certList;
780 cvout[cvout_index].value.pointer.chain = NULL; 777 cvout[cvout_index].value.pointer.chain = NULL;
781 int cvout_cert_list_index = cvout_index; 778 int cvout_cert_list_index = cvout_index;
782 cvout_index++; 779 cvout_index++;
783 cvout[cvout_index].type = cert_po_trustAnchor; 780 cvout[cvout_index].type = cert_po_trustAnchor;
784 cvout[cvout_index].value.pointer.cert = NULL; 781 cvout[cvout_index].value.pointer.cert = NULL;
785 int cvout_trust_anchor_index = cvout_index; 782 int cvout_trust_anchor_index = cvout_index;
786 cvout_index++; 783 cvout_index++;
787 cvout[cvout_index].type = cert_po_end; 784 cvout[cvout_index].type = cert_po_end;
788 ScopedCERTValOutParam scoped_cvout(cvout); 785 ScopedCERTValOutParam scoped_cvout(cvout);
789 786
790 EVRootCAMetadata* metadata = EVRootCAMetadata::GetInstance(); 787 EVRootCAMetadata* metadata = EVRootCAMetadata::GetInstance();
791 SECOidTag ev_policy_oid = SEC_OID_UNKNOWN; 788 SECOidTag ev_policy_oid = SEC_OID_UNKNOWN;
792 bool is_ev_candidate = 789 bool is_ev_candidate = (flags & CertVerifier::VERIFY_EV_CERT) &&
793 (flags & CertVerifier::VERIFY_EV_CERT) && 790 IsEVCandidate(metadata, cert_handle, &ev_policy_oid);
794 IsEVCandidate(metadata, cert_handle, &ev_policy_oid);
795 bool cert_io_enabled = flags & CertVerifier::VERIFY_CERT_IO_ENABLED; 791 bool cert_io_enabled = flags & CertVerifier::VERIFY_CERT_IO_ENABLED;
796 bool check_revocation = 792 bool check_revocation =
797 cert_io_enabled && 793 cert_io_enabled && (flags & CertVerifier::VERIFY_REV_CHECKING_ENABLED);
798 (flags & CertVerifier::VERIFY_REV_CHECKING_ENABLED);
799 if (check_revocation) 794 if (check_revocation)
800 verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED; 795 verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED;
801 796
802 ScopedCERTCertList trust_anchors; 797 ScopedCERTCertList trust_anchors;
803 if (!additional_trust_anchors.empty()) { 798 if (!additional_trust_anchors.empty()) {
804 trust_anchors.reset( 799 trust_anchors.reset(
805 CertificateListToCERTCertList(additional_trust_anchors)); 800 CertificateListToCERTCertList(additional_trust_anchors));
806 } 801 }
807 802
808 SECStatus status = PKIXVerifyCert(cert_handle, 803 SECStatus status = PKIXVerifyCert(cert_handle,
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
879 } 874 }
880 // |err| is not a certificate error. 875 // |err| is not a certificate error.
881 return MapSecurityError(err); 876 return MapSecurityError(err);
882 } 877 }
883 878
884 if (IsCertStatusError(verify_result->cert_status)) 879 if (IsCertStatusError(verify_result->cert_status))
885 return MapCertStatusToNetError(verify_result->cert_status); 880 return MapCertStatusToNetError(verify_result->cert_status);
886 881
887 if ((flags & CertVerifier::VERIFY_EV_CERT) && is_ev_candidate) { 882 if ((flags & CertVerifier::VERIFY_EV_CERT) && is_ev_candidate) {
888 check_revocation |= 883 check_revocation |=
889 crl_set_result != kCRLSetOk && 884 crl_set_result != kCRLSetOk && cert_io_enabled &&
890 cert_io_enabled &&
891 (flags & CertVerifier::VERIFY_REV_CHECKING_ENABLED_EV_ONLY); 885 (flags & CertVerifier::VERIFY_REV_CHECKING_ENABLED_EV_ONLY);
892 if (check_revocation) 886 if (check_revocation)
893 verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED; 887 verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED;
894 888
895 if (VerifyEV(cert_handle, 889 if (VerifyEV(cert_handle,
896 flags, 890 flags,
897 crl_set, 891 crl_set,
898 check_revocation, 892 check_revocation,
899 metadata, 893 metadata,
900 ev_policy_oid, 894 ev_policy_oid,
(...skipping 16 matching lines...) Expand all
917 return VerifyInternalImpl(cert, 911 return VerifyInternalImpl(cert,
918 hostname, 912 hostname,
919 flags, 913 flags,
920 crl_set, 914 crl_set,
921 additional_trust_anchors, 915 additional_trust_anchors,
922 NULL, // chain_verify_callback 916 NULL, // chain_verify_callback
923 verify_result); 917 verify_result);
924 } 918 }
925 919
926 } // namespace net 920 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698