| 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" |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 96 const der::Input& alg2_tlv = cert.tbs().signature_algorithm_tlv; | 96 const der::Input& alg2_tlv = cert.tbs().signature_algorithm_tlv; |
| 97 | 97 |
| 98 // Ensure that the two DER-encoded signature algorithms are byte-for-byte | 98 // Ensure that the two DER-encoded signature algorithms are byte-for-byte |
| 99 // equal, but make a compatibility concession for RSA with SHA1. | 99 // equal, but make a compatibility concession for RSA with SHA1. |
| 100 return alg1_tlv == alg2_tlv || (IsRsaWithSha1SignatureAlgorithm(alg1_tlv) && | 100 return alg1_tlv == alg2_tlv || (IsRsaWithSha1SignatureAlgorithm(alg1_tlv) && |
| 101 IsRsaWithSha1SignatureAlgorithm(alg2_tlv)); | 101 IsRsaWithSha1SignatureAlgorithm(alg2_tlv)); |
| 102 } | 102 } |
| 103 | 103 |
| 104 // This function corresponds to RFC 5280 section 6.1.3's "Basic Certificate | 104 // This function corresponds to RFC 5280 section 6.1.3's "Basic Certificate |
| 105 // Processing" procedure. | 105 // Processing" procedure. |
| 106 // | |
| 107 // |skip_issuer_checks| controls whether the function will skip: | |
| 108 // - Checking that |cert|'s signature using |working_spki| | |
| 109 // - Checkinging that |cert|'s issuer matches |working_normalized_issuer_name| | |
| 110 // This should be set to true only when verifying a trusted root certificate. | |
| 111 WARN_UNUSED_RESULT bool BasicCertificateProcessing( | 106 WARN_UNUSED_RESULT bool BasicCertificateProcessing( |
| 112 const ParsedCertificate& cert, | 107 const ParsedCertificate& cert, |
| 113 bool is_target_cert, | 108 bool is_target_cert, |
| 114 bool skip_issuer_checks, | |
| 115 const SignaturePolicy* signature_policy, | 109 const SignaturePolicy* signature_policy, |
| 116 const der::GeneralizedTime& time, | 110 const der::GeneralizedTime& time, |
| 117 const der::Input& working_spki, | 111 const der::Input& working_spki, |
| 118 const der::Input& working_normalized_issuer_name, | 112 const der::Input& working_normalized_issuer_name, |
| 119 const std::vector<const NameConstraints*>& name_constraints_list) { | 113 const std::vector<const NameConstraints*>& name_constraints_list) { |
| 120 // Check that the signature algorithms in Certificate vs TBSCertificate | 114 // Check that the signature algorithms in Certificate vs TBSCertificate |
| 121 // match. This isn't part of RFC 5280 section 6.1.3, but is mandated by | 115 // match. This isn't part of RFC 5280 section 6.1.3, but is mandated by |
| 122 // sections 4.1.1.2 and 4.1.2.3. | 116 // sections 4.1.1.2 and 4.1.2.3. |
| 123 if (!VerifySignatureAlgorithmsMatch(cert)) | 117 if (!VerifySignatureAlgorithmsMatch(cert)) |
| 124 return false; | 118 return false; |
| 125 | 119 |
| 126 // Verify the digital signature using the previous certificate's key (RFC | 120 // Verify the digital signature using the previous certificate's key (RFC |
| 127 // 5280 section 6.1.3 step a.1). | 121 // 5280 section 6.1.3 step a.1). |
| 128 if (!skip_issuer_checks) { | 122 if (!cert.has_valid_supported_signature_algorithm() || |
| 129 if (!cert.has_valid_supported_signature_algorithm() || | 123 !VerifySignedData(cert.signature_algorithm(), cert.tbs_certificate_tlv(), |
| 130 !VerifySignedData(cert.signature_algorithm(), | 124 cert.signature_value(), working_spki, |
| 131 cert.tbs_certificate_tlv(), cert.signature_value(), | 125 signature_policy)) { |
| 132 working_spki, signature_policy)) { | 126 return false; |
| 133 return false; | |
| 134 } | |
| 135 } | 127 } |
| 136 | 128 |
| 137 // Check the time range for the certificate's validity, ensuring it is valid | 129 // Check the time range for the certificate's validity, ensuring it is valid |
| 138 // at |time|. | 130 // at |time|. |
| 139 // (RFC 5280 section 6.1.3 step a.2) | 131 // (RFC 5280 section 6.1.3 step a.2) |
| 140 if (!VerifyTimeValidity(cert, time)) | 132 if (!VerifyTimeValidity(cert, time)) |
| 141 return false; | 133 return false; |
| 142 | 134 |
| 143 // TODO(eroman): Check revocation (RFC 5280 section 6.1.3 step a.3) | 135 // TODO(eroman): Check revocation (RFC 5280 section 6.1.3 step a.3) |
| 144 | 136 |
| 145 // Verify the certificate's issuer name matches the issuing certificate's | 137 // Verify the certificate's issuer name matches the issuing certificate's |
| 146 // subject name. (RFC 5280 section 6.1.3 step a.4) | 138 // subject name. (RFC 5280 section 6.1.3 step a.4) |
| 147 if (!skip_issuer_checks) { | 139 if (cert.normalized_issuer() != working_normalized_issuer_name) |
| 148 if (cert.normalized_issuer() != working_normalized_issuer_name) | 140 return false; |
| 149 return false; | |
| 150 } | |
| 151 | 141 |
| 152 // Name constraints (RFC 5280 section 6.1.3 step b & c) | 142 // Name constraints (RFC 5280 section 6.1.3 step b & c) |
| 153 // If certificate i is self-issued and it is not the final certificate in the | 143 // If certificate i is self-issued and it is not the final certificate in the |
| 154 // path, skip this step for certificate i. | 144 // path, skip this step for certificate i. |
| 155 if (!name_constraints_list.empty() && | 145 if (!name_constraints_list.empty() && |
| 156 (!IsSelfIssued(cert) || is_target_cert)) { | 146 (!IsSelfIssued(cert) || is_target_cert)) { |
| 157 for (const NameConstraints* nc : name_constraints_list) { | 147 for (const NameConstraints* nc : name_constraints_list) { |
| 158 if (!nc->IsPermittedCert(cert.normalized_subject(), | 148 if (!nc->IsPermittedCert(cert.normalized_subject(), |
| 159 cert.subject_alt_names())) { | 149 cert.subject_alt_names())) { |
| 160 return false; | 150 return false; |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 330 if (!VerifyTargetCertHasConsistentCaBits(cert)) | 320 if (!VerifyTargetCertHasConsistentCaBits(cert)) |
| 331 return false; | 321 return false; |
| 332 | 322 |
| 333 return true; | 323 return true; |
| 334 } | 324 } |
| 335 | 325 |
| 336 } // namespace | 326 } // namespace |
| 337 | 327 |
| 338 // This implementation is structured to mimic the description of certificate | 328 // This implementation is structured to mimic the description of certificate |
| 339 // path verification given by RFC 5280 section 6.1. | 329 // path verification given by RFC 5280 section 6.1. |
| 340 // | 330 bool VerifyCertificateChain(const ParsedCertificateList& certs, |
| 341 // Unlike RFC 5280, the trust anchor is specified as the root certificate in | 331 const TrustAnchor* trust_anchor, |
| 342 // the chain. This root certificate is assumed to be trusted, and neither its | 332 const SignaturePolicy* signature_policy, |
| 343 // signature nor issuer name are verified. (It needn't be self-signed). | 333 const der::GeneralizedTime& time) { |
| 344 bool VerifyCertificateChainAssumingTrustedRoot( | |
| 345 const ParsedCertificateList& certs, | |
| 346 // The trust store is only used for assertions. | |
| 347 const TrustStore& trust_store, | |
| 348 const SignaturePolicy* signature_policy, | |
| 349 const der::GeneralizedTime& time) { | |
| 350 // An empty chain is necessarily invalid. | 334 // An empty chain is necessarily invalid. |
| 351 if (certs.empty()) | 335 if (certs.empty()) |
| 352 return false; | 336 return false; |
| 353 | 337 |
| 354 // IMPORTANT: the assumption being made is that the root certificate in | 338 // TODO(crbug.com/635200): Support anchor constraints. |
| 355 // the given path is the trust anchor (and has already been verified as | |
| 356 // such). | |
| 357 DCHECK(trust_store.IsTrustedCertificate(certs.back().get())); | |
| 358 | 339 |
| 359 // Will contain a NameConstraints for each previous cert in the chain which | 340 // Will contain a NameConstraints for each previous cert in the chain which |
| 360 // had nameConstraints. This corresponds to the permitted_subtrees and | 341 // had nameConstraints. This corresponds to the permitted_subtrees and |
| 361 // excluded_subtrees state variables from RFC 5280. | 342 // excluded_subtrees state variables from RFC 5280. |
| 362 std::vector<const NameConstraints*> name_constraints_list; | 343 std::vector<const NameConstraints*> name_constraints_list; |
| 363 | 344 |
| 364 // |working_spki| is an amalgamation of 3 separate variables from RFC 5280: | 345 // |working_spki| is an amalgamation of 3 separate variables from RFC 5280: |
| 365 // * working_public_key | 346 // * working_public_key |
| 366 // * working_public_key_algorithm | 347 // * working_public_key_algorithm |
| 367 // * working_public_key_parameters | 348 // * working_public_key_parameters |
| 368 // | 349 // |
| 369 // They are combined for simplicity since the signature verification takes an | 350 // They are combined for simplicity since the signature verification takes an |
| 370 // SPKI, and the parameter inheritence is not applicable for the supported | 351 // SPKI, and the parameter inheritence is not applicable for the supported |
| 371 // key types. | 352 // key types. |
| 372 // | 353 // |
| 373 // An approximate explanation of |working_spki| is this description from RFC | 354 // An approximate explanation of |working_spki| is this description from RFC |
| 374 // 5280 section 6.1.2: | 355 // 5280 section 6.1.2: |
| 375 // | 356 // |
| 376 // working_public_key: the public key used to verify the | 357 // working_public_key: the public key used to verify the |
| 377 // signature of a certificate. | 358 // signature of a certificate. |
| 378 der::Input working_spki; | 359 der::Input working_spki = trust_anchor->spki(); |
| 379 | 360 |
| 380 // |working_normalized_issuer_name| is the normalized value of the | 361 // |working_normalized_issuer_name| is the normalized value of the |
| 381 // working_issuer_name variable in RFC 5280 section 6.1.2: | 362 // working_issuer_name variable in RFC 5280 section 6.1.2: |
| 382 // | 363 // |
| 383 // working_issuer_name: the issuer distinguished name expected | 364 // working_issuer_name: the issuer distinguished name expected |
| 384 // in the next certificate in the chain. | 365 // in the next certificate in the chain. |
| 385 der::Input working_normalized_issuer_name; | 366 der::Input working_normalized_issuer_name = |
| 367 trust_anchor->normalized_subject(); |
| 386 | 368 |
| 387 // |max_path_length| corresponds with the same named variable in RFC 5280 | 369 // |max_path_length| corresponds with the same named variable in RFC 5280 |
| 388 // section 6.1.2: | 370 // section 6.1.2: |
| 389 // | 371 // |
| 390 // max_path_length: this integer is initialized to n, is | 372 // max_path_length: this integer is initialized to n, is |
| 391 // decremented for each non-self-issued certificate in the path, | 373 // decremented for each non-self-issued certificate in the path, |
| 392 // and may be reduced to the value in the path length constraint | 374 // and may be reduced to the value in the path length constraint |
| 393 // field within the basic constraints extension of a CA | 375 // field within the basic constraints extension of a CA |
| 394 // certificate. | 376 // certificate. |
| 395 size_t max_path_length = certs.size(); | 377 size_t max_path_length = certs.size(); |
| 396 | 378 |
| 397 // Iterate over all the certificates in the reverse direction: starting from | 379 // Iterate over all the certificates in the reverse direction: starting from |
| 398 // the trust anchor and progressing towards the target certificate. | 380 // the certificate signed by trust anchor and progressing towards the target |
| 381 // certificate. |
| 399 // | 382 // |
| 400 // Note that |i| uses 0-based indexing whereas in RFC 5280 it is 1-based. | 383 // Note that |i| uses 0-based indexing whereas in RFC 5280 it is 1-based. |
| 401 // | 384 // |
| 402 // * i=0 : Trust anchor. | 385 // * i=0 : Certificated signed by trust anchor. |
| 403 // * i=N-1 : Target certificate. | 386 // * i=N-1 : Target certificate. |
| 404 for (size_t i = 0; i < certs.size(); ++i) { | 387 for (size_t i = 0; i < certs.size(); ++i) { |
| 405 const size_t index_into_certs = certs.size() - i - 1; | 388 const size_t index_into_certs = certs.size() - i - 1; |
| 406 | 389 |
| 407 // |is_target_cert| is true if the current certificate is the target | 390 // |is_target_cert| is true if the current certificate is the target |
| 408 // certificate being verified. The target certificate isn't necessarily an | 391 // certificate being verified. The target certificate isn't necessarily an |
| 409 // end-entity certificate. | 392 // end-entity certificate. |
| 410 const bool is_target_cert = index_into_certs == 0; | 393 const bool is_target_cert = index_into_certs == 0; |
| 411 | 394 |
| 412 // |is_trust_anchor| is true if the current certificate is the trust | |
| 413 // anchor. This certificate is implicitly trusted. | |
| 414 const bool is_trust_anchor = i == 0; | |
| 415 | |
| 416 const ParsedCertificate& cert = *certs[index_into_certs]; | 395 const ParsedCertificate& cert = *certs[index_into_certs]; |
| 417 | 396 |
| 418 // Per RFC 5280 section 6.1: | 397 // Per RFC 5280 section 6.1: |
| 419 // * Do basic processing for each certificate | 398 // * Do basic processing for each certificate |
| 420 // * If it is the last certificate in the path (target certificate) | 399 // * If it is the last certificate in the path (target certificate) |
| 421 // - Then run "Wrap up" | 400 // - Then run "Wrap up" |
| 422 // - Otherwise run "Prepare for Next cert" | 401 // - Otherwise run "Prepare for Next cert" |
| 423 if (!BasicCertificateProcessing(cert, is_target_cert, is_trust_anchor, | 402 if (!BasicCertificateProcessing( |
| 424 signature_policy, time, working_spki, | 403 cert, is_target_cert, signature_policy, time, working_spki, |
| 425 working_normalized_issuer_name, | 404 working_normalized_issuer_name, name_constraints_list)) { |
| 426 name_constraints_list)) { | |
| 427 return false; | 405 return false; |
| 428 } | 406 } |
| 429 if (!is_target_cert) { | 407 if (!is_target_cert) { |
| 430 if (!PrepareForNextCertificate(cert, &max_path_length, &working_spki, | 408 if (!PrepareForNextCertificate(cert, &max_path_length, &working_spki, |
| 431 &working_normalized_issuer_name, | 409 &working_normalized_issuer_name, |
| 432 &name_constraints_list)) { | 410 &name_constraints_list)) { |
| 433 return false; | 411 return false; |
| 434 } | 412 } |
| 435 } else { | 413 } else { |
| 436 if (!WrapUp(cert)) | 414 if (!WrapUp(cert)) |
| 437 return false; | 415 return false; |
| 438 } | 416 } |
| 439 } | 417 } |
| 440 | 418 |
| 441 // TODO(eroman): RFC 5280 forbids duplicate certificates per section 6.1: | 419 // TODO(eroman): RFC 5280 forbids duplicate certificates per section 6.1: |
| 442 // | 420 // |
| 443 // A certificate MUST NOT appear more than once in a prospective | 421 // A certificate MUST NOT appear more than once in a prospective |
| 444 // certification path. | 422 // certification path. |
| 445 | 423 |
| 446 return true; | 424 return true; |
| 447 } | 425 } |
| 448 | 426 |
| 449 } // namespace net | 427 } // namespace net |
| OLD | NEW |