OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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/internal/verify_certificate_chain.h" | 5 #include "net/cert/internal/verify_certificate_chain.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "net/cert/internal/name_constraints.h" | 10 #include "net/cert/internal/name_constraints.h" |
11 #include "net/cert/internal/parse_certificate.h" | 11 #include "net/cert/internal/parse_certificate.h" |
12 #include "net/cert/internal/parsed_certificate.h" | |
13 #include "net/cert/internal/signature_algorithm.h" | 12 #include "net/cert/internal/signature_algorithm.h" |
14 #include "net/cert/internal/signature_policy.h" | 13 #include "net/cert/internal/signature_policy.h" |
15 #include "net/cert/internal/trust_store.h" | 14 #include "net/cert/internal/trust_store.h" |
16 #include "net/cert/internal/verify_signed_data.h" | 15 #include "net/cert/internal/verify_signed_data.h" |
17 #include "net/der/input.h" | 16 #include "net/der/input.h" |
18 #include "net/der/parser.h" | 17 #include "net/der/parser.h" |
19 | 18 |
20 namespace net { | 19 namespace net { |
21 | 20 |
22 namespace { | 21 namespace { |
(...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
329 // The following check is NOT part of RFC 5280 6.1.5's "Wrap-Up Procedure", | 328 // The following check is NOT part of RFC 5280 6.1.5's "Wrap-Up Procedure", |
330 // however is implied by RFC 5280 section 4.2.1.9. | 329 // however is implied by RFC 5280 section 4.2.1.9. |
331 if (!VerifyTargetCertHasConsistentCaBits(cert)) | 330 if (!VerifyTargetCertHasConsistentCaBits(cert)) |
332 return false; | 331 return false; |
333 | 332 |
334 return true; | 333 return true; |
335 } | 334 } |
336 | 335 |
337 } // namespace | 336 } // namespace |
338 | 337 |
339 // TODO(eroman): Move this into existing anonymous namespace. | |
340 namespace { | |
341 | |
342 // This implementation is structured to mimic the description of certificate | 338 // This implementation is structured to mimic the description of certificate |
343 // path verification given by RFC 5280 section 6.1. | 339 // path verification given by RFC 5280 section 6.1. |
344 // | 340 // |
345 // Unlike RFC 5280, the trust anchor is specified as the root certificate in | 341 // Unlike RFC 5280, the trust anchor is specified as the root certificate in |
346 // the chain. This root certificate is assumed to be trusted, and neither its | 342 // the chain. This root certificate is assumed to be trusted, and neither its |
347 // signature nor issuer name are verified. (It needn't be self-signed). | 343 // signature nor issuer name are verified. (It needn't be self-signed). |
348 bool VerifyCertificateChainAssumingTrustedRoot( | 344 bool VerifyCertificateChainAssumingTrustedRoot( |
349 const std::vector<scoped_refptr<ParsedCertificate>>& certs, | 345 const ParsedCertificateList& certs, |
350 // The trust store is only used for assertions. | 346 // The trust store is only used for assertions. |
351 const TrustStore& trust_store, | 347 const TrustStore& trust_store, |
352 const SignaturePolicy* signature_policy, | 348 const SignaturePolicy* signature_policy, |
353 const der::GeneralizedTime& time) { | 349 const der::GeneralizedTime& time) { |
354 // An empty chain is necessarily invalid. | 350 // An empty chain is necessarily invalid. |
355 if (certs.empty()) | 351 if (certs.empty()) |
356 return false; | 352 return false; |
357 | 353 |
358 // IMPORTANT: the assumption being made is that the root certificate in | 354 // IMPORTANT: the assumption being made is that the root certificate in |
359 // the given path is the trust anchor (and has already been verified as | 355 // the given path is the trust anchor (and has already been verified as |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
443 } | 439 } |
444 | 440 |
445 // TODO(eroman): RFC 5280 forbids duplicate certificates per section 6.1: | 441 // TODO(eroman): RFC 5280 forbids duplicate certificates per section 6.1: |
446 // | 442 // |
447 // A certificate MUST NOT appear more than once in a prospective | 443 // A certificate MUST NOT appear more than once in a prospective |
448 // certification path. | 444 // certification path. |
449 | 445 |
450 return true; | 446 return true; |
451 } | 447 } |
452 | 448 |
453 // TODO(eroman): This function is a temporary hack in the absence of full | |
454 // path building. It may insert 1 certificate at the root of the | |
455 // chain to ensure that the path's root certificate is a trust anchor. | |
456 // | |
457 // Beyond this no other verification is done on the chain. The caller is | |
458 // responsible for verifying the subsequent chain's correctness. | |
459 WARN_UNUSED_RESULT bool BuildSimplePathToTrustAnchor( | |
460 const TrustStore& trust_store, | |
461 std::vector<scoped_refptr<ParsedCertificate>>* certs) { | |
462 if (certs->empty()) | |
463 return false; | |
464 | |
465 // Check if the current root certificate is trusted. If it is then no | |
466 // extra work is needed. | |
467 if (trust_store.IsTrustedCertificate(certs->back().get())) | |
468 return true; | |
469 | |
470 std::vector<scoped_refptr<ParsedCertificate>> trust_anchors; | |
471 trust_store.FindTrustAnchorsByNormalizedName( | |
472 certs->back()->normalized_issuer(), &trust_anchors); | |
473 if (trust_anchors.empty()) | |
474 return false; | |
475 // TODO(mattm): this only tries the first match, even if there are multiple. | |
476 certs->push_back(std::move(trust_anchors[0])); | |
477 return true; | |
478 } | |
479 | |
480 } // namespace | |
481 | |
482 bool VerifyCertificateChain( | |
483 const std::vector<scoped_refptr<ParsedCertificate>>& cert_chain, | |
484 const TrustStore& trust_store, | |
485 const SignaturePolicy* signature_policy, | |
486 const der::GeneralizedTime& time, | |
487 std::vector<scoped_refptr<ParsedCertificate>>* trusted_chain_out) { | |
488 if (cert_chain.empty()) | |
489 return false; | |
490 | |
491 std::vector<scoped_refptr<ParsedCertificate>> full_chain = cert_chain; | |
492 | |
493 // Modify the certificate chain so that its root is a trusted certificate. | |
494 if (!BuildSimplePathToTrustAnchor(trust_store, &full_chain)) | |
495 return false; | |
496 | |
497 // Verify the chain. | |
498 bool success = VerifyCertificateChainAssumingTrustedRoot( | |
499 full_chain, trust_store, signature_policy, time); | |
500 if (success && trusted_chain_out != nullptr) | |
501 *trusted_chain_out = std::move(full_chain); | |
502 return success; | |
503 } | |
504 | |
505 } // namespace net | 449 } // namespace net |
OLD | NEW |