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

Unified Diff: net/cert/internal/verify_certificate_chain.cc

Issue 1976433002: Add new ParsedCertificate class, move TrustStore to own file. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@cert-parsing-remove-old-parsedcertificate
Patch Set: . Created 4 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 side-by-side diff with in-line comments
Download patch
Index: net/cert/internal/verify_certificate_chain.cc
diff --git a/net/cert/internal/verify_certificate_chain.cc b/net/cert/internal/verify_certificate_chain.cc
index edfbfcb570000276124f3c18e31e51cff7a5bb82..09f6a6b23912b119a2f1b3e4b0e5074ff339ba32 100644
--- a/net/cert/internal/verify_certificate_chain.cc
+++ b/net/cert/internal/verify_certificate_chain.cc
@@ -9,9 +9,10 @@
#include "base/logging.h"
#include "net/cert/internal/name_constraints.h"
#include "net/cert/internal/parse_certificate.h"
+#include "net/cert/internal/parsed_certificate.h"
#include "net/cert/internal/signature_algorithm.h"
#include "net/cert/internal/signature_policy.h"
-#include "net/cert/internal/verify_name_match.h"
+#include "net/cert/internal/trust_store.h"
#include "net/cert/internal/verify_signed_data.h"
#include "net/der/input.h"
#include "net/der/parser.h"
@@ -20,172 +21,17 @@ namespace net {
namespace {
-// Map from OID to ParsedExtension.
-using ExtensionsMap = std::map<der::Input, ParsedExtension>;
-
-// Describes all parsed properties of a certificate that are relevant for
-// certificate verification.
-struct FullyParsedCert {
- der::Input tbs_certificate_tlv;
- der::Input signature_algorithm_tlv;
- der::BitString signature_value;
- ParsedTbsCertificate tbs;
-
- std::unique_ptr<SignatureAlgorithm> signature_algorithm;
-
- // Standard extensions that were parsed.
- bool has_basic_constraints = false;
- ParsedBasicConstraints basic_constraints;
-
- bool has_key_usage = false;
- der::BitString key_usage;
-
- std::unique_ptr<GeneralNames> subject_alt_names;
-
- bool has_name_constraints = false;
- ParsedExtension name_constraints_extension;
-
- // The remaining extensions (excludes the standard ones above).
- ExtensionsMap unconsumed_extensions;
-};
-
-// Removes the extension with OID |oid| from |unconsumed_extensions| and fills
-// |extension| with the matching extension value. If there was no extension
-// matching |oid| then returns |false|.
-WARN_UNUSED_RESULT bool ConsumeExtension(const der::Input& oid,
- ExtensionsMap* unconsumed_extensions,
- ParsedExtension* extension) {
- auto it = unconsumed_extensions->find(oid);
- if (it == unconsumed_extensions->end())
- return false;
-
- *extension = it->second;
- unconsumed_extensions->erase(it);
- return true;
-}
-
// Returns true if the certificate does not contain any unconsumed _critical_
// extensions.
WARN_UNUSED_RESULT bool VerifyNoUnconsumedCriticalExtensions(
- const FullyParsedCert& cert) {
- for (const auto& entry : cert.unconsumed_extensions) {
+ const ParsedCertificate& cert) {
+ for (const auto& entry : cert.unconsumed_extensions()) {
if (entry.second.critical)
return false;
}
return true;
}
-WARN_UNUSED_RESULT bool GetSequenceValue(const der::Input& tlv,
- der::Input* value) {
- der::Parser parser(tlv);
- return parser.ReadTag(der::kSequence, value) && !parser.HasMore();
-}
-
-// Parses an X.509 Certificate fully (including the TBSCertificate and
-// standard extensions), saving all the properties to |out_|.
-WARN_UNUSED_RESULT bool FullyParseCertificate(const der::Input& cert_tlv,
- FullyParsedCert* out) {
- // Parse the outer Certificate.
- if (!ParseCertificate(cert_tlv, &out->tbs_certificate_tlv,
- &out->signature_algorithm_tlv, &out->signature_value))
- return false;
-
- // Parse the signature algorithm contained in the Certificate (there is
- // another one in the TBSCertificate, which is checked later by
- // VerifySignatureAlgorithmsMatch)
- out->signature_algorithm =
- SignatureAlgorithm::CreateFromDer(out->signature_algorithm_tlv);
- if (!out->signature_algorithm)
- return false;
-
- // Parse the TBSCertificate.
- if (!ParseTbsCertificate(out->tbs_certificate_tlv, &out->tbs))
- return false;
-
- // Reset state relating to extensions (which may not get overwritten). This is
- // just a precaution, since in practice |out| will already be default
- // initialize.
- out->has_basic_constraints = false;
- out->has_key_usage = false;
- out->unconsumed_extensions.clear();
- out->subject_alt_names.reset();
- out->has_name_constraints = false;
-
- // Parse the standard X.509 extensions and remove them from
- // |unconsumed_extensions|.
- if (out->tbs.has_extensions) {
- // ParseExtensions() ensures there are no duplicates, and maps the (unique)
- // OID to the extension value.
- if (!ParseExtensions(out->tbs.extensions_tlv, &out->unconsumed_extensions))
- return false;
-
- ParsedExtension extension;
-
- // Basic constraints.
- if (ConsumeExtension(BasicConstraintsOid(), &out->unconsumed_extensions,
- &extension)) {
- out->has_basic_constraints = true;
- if (!ParseBasicConstraints(extension.value, &out->basic_constraints))
- return false;
- }
-
- // KeyUsage.
- if (ConsumeExtension(KeyUsageOid(), &out->unconsumed_extensions,
- &extension)) {
- out->has_key_usage = true;
- if (!ParseKeyUsage(extension.value, &out->key_usage))
- return false;
- }
-
- // Subject alternative name.
- if (ConsumeExtension(SubjectAltNameOid(), &out->unconsumed_extensions,
- &extension)) {
- // RFC 5280 section 4.2.1.6:
- // SubjectAltName ::= GeneralNames
- out->subject_alt_names = GeneralNames::CreateFromDer(extension.value);
- if (!out->subject_alt_names)
- return false;
- // RFC 5280 section 4.1.2.6:
- // If subject naming information is present only in the subjectAltName
- // extension (e.g., a key bound only to an email address or URI), then the
- // subject name MUST be an empty sequence and the subjectAltName extension
- // MUST be critical.
- if (!extension.critical) {
- der::Input subject_value;
- if (!GetSequenceValue(out->tbs.subject_tlv, &subject_value))
- return false;
- if (subject_value.Length() == 0)
- return false;
- }
- }
-
- // Name constraints.
- if (ConsumeExtension(NameConstraintsOid(), &out->unconsumed_extensions,
- &out->name_constraints_extension)) {
- out->has_name_constraints = true;
- }
- }
-
- return true;
-}
-
-// Returns true if |name1_tlv| matches |name2_tlv|. The two inputs must be
-// tag-length-value for RFC 5280's Name.
-WARN_UNUSED_RESULT bool NameMatches(const der::Input& name1_tlv,
- const der::Input& name2_tlv) {
- der::Input name1_value;
- der::Input name2_value;
-
- // Assume that the Name is an RDNSequence. VerifyNameMatch() expects the
- // value from a SEQUENCE, so strip off the tag.
- if (!GetSequenceValue(name1_tlv, &name1_value) ||
- !GetSequenceValue(name2_tlv, &name2_value)) {
- return false;
- }
-
- return VerifyNameMatch(name1_value, name2_value);
-}
-
// Returns true if |cert| was self-issued. The definition of self-issuance
// comes from RFC 5280 section 6.1:
//
@@ -197,8 +43,8 @@ WARN_UNUSED_RESULT bool NameMatches(const der::Input& name1_tlv,
// support key rollover or changes in certificate policies. These
// self-issued certificates are not counted when evaluating path length
// or name constraints.
-WARN_UNUSED_RESULT bool IsSelfIssued(const FullyParsedCert& cert) {
- return NameMatches(cert.tbs.subject_tlv, cert.tbs.issuer_tlv);
+WARN_UNUSED_RESULT bool IsSelfIssued(const ParsedCertificate& cert) {
+ return cert.normalized_subject() == cert.normalized_issuer();
eroman 2016/05/12 18:12:30 yay!
}
// Returns true if |cert| is valid at time |time|.
@@ -208,10 +54,10 @@ WARN_UNUSED_RESULT bool IsSelfIssued(const FullyParsedCert& cert) {
//
// The validity period for a certificate is the period of time from
// notBefore through notAfter, inclusive.
-WARN_UNUSED_RESULT bool VerifyTimeValidity(const FullyParsedCert& cert,
+WARN_UNUSED_RESULT bool VerifyTimeValidity(const ParsedCertificate& cert,
const der::GeneralizedTime time) {
- return !(time < cert.tbs.validity_not_before) &&
- !(cert.tbs.validity_not_after < time);
+ return !(time < cert.parsed_tbs().validity_not_before) &&
eroman 2016/05/12 18:12:30 maybe we can call the function just cert.tbs() (
mattm 2016/05/13 02:17:37 Done.
+ !(cert.parsed_tbs().validity_not_after < time);
}
// Returns true if |signature_algorithm_tlv| is a valid algorithm encoding for
@@ -246,9 +92,9 @@ WARN_UNUSED_RESULT bool IsRsaWithSha1SignatureAlgorithm(
// specifying RSA with SHA1 (different OIDs). This is special-cased for
// compatibility sake.
WARN_UNUSED_RESULT bool VerifySignatureAlgorithmsMatch(
- const FullyParsedCert& cert) {
- const der::Input& alg1_tlv = cert.signature_algorithm_tlv;
- const der::Input& alg2_tlv = cert.tbs.signature_algorithm_tlv;
+ const ParsedCertificate& cert) {
+ const der::Input& alg1_tlv = cert.signature_algorithm_tlv();
+ const der::Input& alg2_tlv = cert.parsed_tbs().signature_algorithm_tlv;
// Ensure that the two DER-encoded signature algorithms are byte-for-byte
// equal, but make a compatibility concession for RSA with SHA1.
@@ -261,18 +107,17 @@ WARN_UNUSED_RESULT bool VerifySignatureAlgorithmsMatch(
//
// |skip_issuer_checks| controls whether the function will skip:
// - Checking that |cert|'s signature using |working_spki|
-// - Checkinging that |cert|'s issuer matches |working_issuer_name|
+// - Checkinging that |cert|'s issuer matches |working_normalized_issuer_name|
// This should be set to true only when verifying a trusted root certificate.
WARN_UNUSED_RESULT bool BasicCertificateProcessing(
- const FullyParsedCert& cert,
+ const ParsedCertificate& cert,
bool is_target_cert,
bool skip_issuer_checks,
const SignaturePolicy* signature_policy,
const der::GeneralizedTime& time,
const der::Input& working_spki,
- const der::Input& working_issuer_name,
- const std::vector<std::unique_ptr<NameConstraints>>&
- name_constraints_list) {
+ const der::Input& working_normalized_issuer_name,
+ const std::vector<const NameConstraints*>& name_constraints_list) {
// Check that the signature algorithms in Certificate vs TBSCertificate
// match. This isn't part of RFC 5280 section 6.1.3, but is mandated by
// sections 4.1.1.2 and 4.1.2.3.
@@ -282,9 +127,10 @@ WARN_UNUSED_RESULT bool BasicCertificateProcessing(
// Verify the digital signature using the previous certificate's key (RFC
// 5280 section 6.1.3 step a.1).
if (!skip_issuer_checks) {
- if (!VerifySignedData(*cert.signature_algorithm, cert.tbs_certificate_tlv,
- cert.signature_value, working_spki,
- signature_policy)) {
+ if (!cert.has_supported_signature_algorithm() ||
+ !VerifySignedData(cert.signature_algorithm(),
+ cert.tbs_certificate_tlv(), cert.signature_value(),
+ working_spki, signature_policy)) {
return false;
}
}
@@ -300,7 +146,7 @@ WARN_UNUSED_RESULT bool BasicCertificateProcessing(
// Verify the certificate's issuer name matches the issuing certificate's
// subject name. (RFC 5280 section 6.1.3 step a.4)
if (!skip_issuer_checks) {
- if (!NameMatches(cert.tbs.issuer_tlv, working_issuer_name))
+ if (der::Input(&cert.normalized_issuer()) != working_normalized_issuer_name)
return false;
}
@@ -309,11 +155,9 @@ WARN_UNUSED_RESULT bool BasicCertificateProcessing(
// path, skip this step for certificate i.
if (!name_constraints_list.empty() &&
(!IsSelfIssued(cert) || is_target_cert)) {
- der::Input subject_value;
- if (!GetSequenceValue(cert.tbs.subject_tlv, &subject_value))
- return false;
- for (const auto& nc : name_constraints_list) {
- if (!nc->IsPermittedCert(subject_value, cert.subject_alt_names.get()))
+ for (const NameConstraints* nc : name_constraints_list) {
+ if (!nc->IsPermittedCert(der::Input(&cert.normalized_subject()),
+ cert.subject_alt_names()))
return false;
}
}
@@ -327,38 +171,31 @@ WARN_UNUSED_RESULT bool BasicCertificateProcessing(
// This function corresponds to RFC 5280 section 6.1.4's "Preparation for
// Certificate i+1" procedure. |cert| is expected to be an intermediary.
WARN_UNUSED_RESULT bool PrepareForNextCertificate(
- const FullyParsedCert& cert,
+ const ParsedCertificate& cert,
size_t* max_path_length_ptr,
der::Input* working_spki,
- der::Input* working_issuer_name,
- std::vector<std::unique_ptr<NameConstraints>>* name_constraints_list) {
+ der::Input* working_normalized_issuer_name,
+ std::vector<const NameConstraints*>* name_constraints_list) {
// TODO(eroman): Steps a-b are omitted, as policy constraints are not yet
// implemented.
// From RFC 5280 section 6.1.4 step c:
//
- // Assign the certificate subject name to working_issuer_name.
- *working_issuer_name = cert.tbs.subject_tlv;
+ // Assign the certificate subject name to working_normalized_issuer_name.
+ *working_normalized_issuer_name = der::Input(&cert.normalized_subject());
// From RFC 5280 section 6.1.4 step d:
//
// Assign the certificate subjectPublicKey to working_public_key.
- *working_spki = cert.tbs.spki_tlv;
+ *working_spki = cert.parsed_tbs().spki_tlv;
// Note that steps e and f are omitted as they are handled by
// the assignment to |working_spki| above. See the definition
// of |working_spki|.
// From RFC 5280 section 6.1.4 step g:
- if (cert.has_name_constraints) {
- std::unique_ptr<NameConstraints> name_constraints(
- NameConstraints::CreateFromDer(
- cert.name_constraints_extension.value,
- cert.name_constraints_extension.critical));
- if (!name_constraints)
- return false;
- name_constraints_list->push_back(std::move(name_constraints));
- }
+ if (cert.has_name_constraints())
+ name_constraints_list->push_back(&cert.name_constraints());
// TODO(eroman): Steps h-j are omitted as policy constraints are not yet
// implemented.
@@ -376,7 +213,7 @@ WARN_UNUSED_RESULT bool PrepareForNextCertificate(
//
// This code implicitly rejects non version 3 intermediaries, since they
// can't contain a BasicConstraints extension.
- if (!cert.has_basic_constraints || !cert.basic_constraints.is_ca)
+ if (!cert.has_basic_constraints() || !cert.basic_constraints().is_ca)
return false;
// From RFC 5280 section 6.1.4 step l:
@@ -395,17 +232,17 @@ WARN_UNUSED_RESULT bool PrepareForNextCertificate(
// If pathLenConstraint is present in the certificate and is
// less than max_path_length, set max_path_length to the value
// of pathLenConstraint.
- if (cert.basic_constraints.has_path_len &&
- cert.basic_constraints.path_len < *max_path_length_ptr) {
- *max_path_length_ptr = cert.basic_constraints.path_len;
+ if (cert.basic_constraints().has_path_len &&
+ cert.basic_constraints().path_len < *max_path_length_ptr) {
+ *max_path_length_ptr = cert.basic_constraints().path_len;
}
// From RFC 5280 section 6.1.4 step n:
//
// If a key usage extension is present, verify that the
// keyCertSign bit is set.
- if (cert.has_key_usage &&
- !cert.key_usage.AssertsBit(KEY_USAGE_BIT_KEY_CERT_SIGN)) {
+ if (cert.has_key_usage() &&
+ !cert.key_usage().AssertsBit(KEY_USAGE_BIT_KEY_CERT_SIGN)) {
return false;
}
@@ -444,20 +281,21 @@ WARN_UNUSED_RESULT bool PrepareForNextCertificate(
// for compatibility reasons. Investigate if we need to similarly relax this
// constraint.
WARN_UNUSED_RESULT bool VerifyTargetCertHasConsistentCaBits(
- const FullyParsedCert& cert) {
+ const ParsedCertificate& cert) {
// Check if the certificate contains any property specific to CAs.
bool has_ca_property =
- (cert.has_basic_constraints &&
- (cert.basic_constraints.is_ca || cert.basic_constraints.has_path_len)) ||
- (cert.has_key_usage &&
- cert.key_usage.AssertsBit(KEY_USAGE_BIT_KEY_CERT_SIGN));
+ (cert.has_basic_constraints() &&
+ (cert.basic_constraints().is_ca ||
+ cert.basic_constraints().has_path_len)) ||
+ (cert.has_key_usage() &&
+ cert.key_usage().AssertsBit(KEY_USAGE_BIT_KEY_CERT_SIGN));
// If it "looks" like a CA because it has a CA-only property, then check that
// it sets ALL the properties expected of a CA.
if (has_ca_property) {
- return cert.has_basic_constraints && cert.basic_constraints.is_ca &&
- (!cert.has_key_usage ||
- cert.key_usage.AssertsBit(KEY_USAGE_BIT_KEY_CERT_SIGN));
+ return cert.has_basic_constraints() && cert.basic_constraints().is_ca &&
+ (!cert.has_key_usage() ||
+ cert.key_usage().AssertsBit(KEY_USAGE_BIT_KEY_CERT_SIGN));
}
return true;
@@ -465,7 +303,7 @@ WARN_UNUSED_RESULT bool VerifyTargetCertHasConsistentCaBits(
// This function corresponds with RFC 5280 section 6.1.5's "Wrap-Up Procedure".
// It does processing for the final certificate (the target cert).
-WARN_UNUSED_RESULT bool WrapUp(const FullyParsedCert& cert) {
+WARN_UNUSED_RESULT bool WrapUp(const ParsedCertificate& cert) {
// TODO(eroman): Steps a-b are omitted as policy constraints are not yet
// implemented.
@@ -497,102 +335,6 @@ WARN_UNUSED_RESULT bool WrapUp(const FullyParsedCert& cert) {
} // namespace
-TrustAnchor::TrustAnchor() {}
-TrustAnchor::~TrustAnchor() {}
-
-std::unique_ptr<TrustAnchor> TrustAnchor::CreateFromCertificateData(
- const uint8_t* data,
- size_t length,
- DataSource source) {
- std::unique_ptr<TrustAnchor> result(new TrustAnchor);
-
- switch (source) {
- case DataSource::INTERNAL_COPY:
- result->cert_data_.assign(data, data + length);
- result->cert_ =
- der::Input(result->cert_data_.data(), result->cert_data_.size());
- break;
- case DataSource::EXTERNAL_REFERENCE:
- result->cert_ = der::Input(data, length);
- break;
- }
-
- // Parse the certificate to get its name.
- der::Input tbs_certificate_tlv;
- der::Input signature_algorithm_tlv;
- der::BitString signature_value;
- if (!ParseCertificate(result->cert(), &tbs_certificate_tlv,
- &signature_algorithm_tlv, &signature_value))
- return nullptr;
-
- ParsedTbsCertificate tbs;
- if (!ParseTbsCertificate(tbs_certificate_tlv, &tbs))
- return nullptr;
-
- result->name_ = tbs.subject_tlv;
-
- // TODO(eroman): If adding a self-signed certificate, check that its
- // signature is correct? This check will not otherwise be done during
- // verification.
-
- return result;
-}
-
-bool TrustAnchor::MatchesName(const der::Input& name) const {
- return NameMatches(name, name_);
-}
-
-TrustStore::TrustStore() {}
-TrustStore::~TrustStore() {}
-
-void TrustStore::Clear() {
- anchors_.clear();
-}
-
-bool TrustStore::AddTrustedCertificate(const uint8_t* data, size_t length) {
- return AddTrustedCertificate(data, length,
- TrustAnchor::DataSource::INTERNAL_COPY);
-}
-
-bool TrustStore::AddTrustedCertificate(const base::StringPiece& data) {
- return AddTrustedCertificate(reinterpret_cast<const uint8_t*>(data.data()),
- data.size());
-}
-
-bool TrustStore::AddTrustedCertificateWithoutCopying(const uint8_t* data,
- size_t length) {
- return AddTrustedCertificate(data, length,
- TrustAnchor::DataSource::EXTERNAL_REFERENCE);
-}
-
-const TrustAnchor* TrustStore::FindTrustAnchorByName(
- const der::Input& name) const {
- for (const auto& anchor : anchors_) {
- if (anchor->MatchesName(name)) {
- return anchor.get();
- }
- }
- return nullptr;
-}
-
-bool TrustStore::IsTrustedCertificate(const der::Input& cert_der) const {
- for (const auto& anchor : anchors_) {
- if (anchor->cert() == cert_der)
- return true;
- }
- return false;
-}
-
-bool TrustStore::AddTrustedCertificate(const uint8_t* data,
- size_t length,
- TrustAnchor::DataSource source) {
- auto anchor = TrustAnchor::CreateFromCertificateData(data, length, source);
- if (!anchor)
- return false;
- anchors_.push_back(std::move(anchor));
- return true;
-}
-
// TODO(eroman): Move this into existing anonymous namespace.
namespace {
@@ -603,24 +345,24 @@ namespace {
// the chain. This root certificate is assumed to be trusted, and neither its
// signature nor issuer name are verified. (It needn't be self-signed).
bool VerifyCertificateChainAssumingTrustedRoot(
- const std::vector<der::Input>& certs_der,
+ const std::vector<scoped_refptr<ParsedCertificate>>& certs,
// The trust store is only used for assertions.
const TrustStore& trust_store,
const SignaturePolicy* signature_policy,
const der::GeneralizedTime& time) {
// An empty chain is necessarily invalid.
- if (certs_der.empty())
+ if (certs.empty())
return false;
// IMPORTANT: the assumption being made is that the root certificate in
// the given path is the trust anchor (and has already been verified as
// such).
- DCHECK(trust_store.IsTrustedCertificate(certs_der.back()));
+ DCHECK(trust_store.IsTrustedCertificate(certs.back().get()));
// Will contain a NameConstraints for each previous cert in the chain which
// had nameConstraints. This corresponds to the permitted_subtrees and
// excluded_subtrees state variables from RFC 5280.
- std::vector<std::unique_ptr<NameConstraints>> name_constraints_list;
+ std::vector<const NameConstraints*> name_constraints_list;
// |working_spki| is an amalgamation of 3 separate variables from RFC 5280:
// * working_public_key
@@ -638,12 +380,12 @@ bool VerifyCertificateChainAssumingTrustedRoot(
// signature of a certificate.
der::Input working_spki;
- // |working_issuer_name| corresponds with the same named variable in RFC 5280
- // section 6.1.2:
+ // |working_normalized_issuer_name| is the normalized value of the
+ // working_issuer_name variable in RFC 5280 section 6.1.2:
eroman 2016/05/12 18:12:30 thanks for updating the comments throughout!
//
// working_issuer_name: the issuer distinguished name expected
// in the next certificate in the chain.
- der::Input working_issuer_name;
+ der::Input working_normalized_issuer_name;
// |max_path_length| corresponds with the same named variable in RFC 5280
// section 6.1.2:
@@ -653,7 +395,7 @@ bool VerifyCertificateChainAssumingTrustedRoot(
// and may be reduced to the value in the path length constraint
// field within the basic constraints extension of a CA
// certificate.
- size_t max_path_length = certs_der.size();
+ size_t max_path_length = certs.size();
// Iterate over all the certificates in the reverse direction: starting from
// the trust anchor and progressing towards the target certificate.
@@ -662,37 +404,34 @@ bool VerifyCertificateChainAssumingTrustedRoot(
//
// * i=0 : Trust anchor.
// * i=N-1 : Target certificate.
- for (size_t i = 0; i < certs_der.size(); ++i) {
- const size_t index_into_certs_der = certs_der.size() - i - 1;
+ for (size_t i = 0; i < certs.size(); ++i) {
+ const size_t index_into_certs = certs.size() - i - 1;
// |is_target_cert| is true if the current certificate is the target
// certificate being verified. The target certificate isn't necessarily an
// end-entity certificate.
- const bool is_target_cert = index_into_certs_der == 0;
+ const bool is_target_cert = index_into_certs == 0;
// |is_trust_anchor| is true if the current certificate is the trust
// anchor. This certificate is implicitly trusted.
const bool is_trust_anchor = i == 0;
- // Parse the current certificate into |cert|.
- FullyParsedCert cert;
- const der::Input& cert_der = certs_der[index_into_certs_der];
- if (!FullyParseCertificate(cert_der, &cert))
- return false;
+ const ParsedCertificate& cert = *certs[index_into_certs];
// Per RFC 5280 section 6.1:
// * Do basic processing for each certificate
// * If it is the last certificate in the path (target certificate)
// - Then run "Wrap up"
// - Otherwise run "Prepare for Next cert"
- if (!BasicCertificateProcessing(
- cert, is_target_cert, is_trust_anchor, signature_policy, time,
- working_spki, working_issuer_name, name_constraints_list)) {
+ if (!BasicCertificateProcessing(cert, is_target_cert, is_trust_anchor,
+ signature_policy, time, working_spki,
+ working_normalized_issuer_name,
+ name_constraints_list)) {
return false;
}
if (!is_target_cert) {
if (!PrepareForNextCertificate(cert, &max_path_length, &working_spki,
- &working_issuer_name,
+ &working_normalized_issuer_name,
&name_constraints_list)) {
return false;
}
@@ -717,56 +456,45 @@ bool VerifyCertificateChainAssumingTrustedRoot(
// Beyond this no other verification is done on the chain. The caller is
// responsible for verifying the subsequent chain's correctness.
WARN_UNUSED_RESULT bool BuildSimplePathToTrustAnchor(
- const std::vector<der::Input>& certs_der,
const TrustStore& trust_store,
- std::vector<der::Input>* certs_der_trusted_root) {
- // Copy the input chain.
- *certs_der_trusted_root = certs_der;
-
- if (certs_der.empty())
+ std::vector<scoped_refptr<ParsedCertificate>>* certs) {
+ if (certs->empty())
return false;
// Check if the current root certificate is trusted. If it is then no
// extra work is needed.
- if (trust_store.IsTrustedCertificate(certs_der_trusted_root->back()))
+ if (trust_store.IsTrustedCertificate(certs->back().get()))
return true;
- // Otherwise if it is not trusted, check whether its issuer is trusted. If
- // so, make *that* trusted certificate the root. If the issuer is not in
- // the trust store then give up and fail (this is not full path building).
- der::Input tbs_certificate_tlv;
- der::Input signature_algorithm_tlv;
- der::BitString signature_value;
- ParsedTbsCertificate tbs;
- if (!ParseCertificate(certs_der.back(), &tbs_certificate_tlv,
- &signature_algorithm_tlv, &signature_value) ||
- !ParseTbsCertificate(tbs_certificate_tlv, &tbs)) {
- return false;
- }
-
- auto trust_anchor = trust_store.FindTrustAnchorByName(tbs.issuer_tlv);
- if (!trust_anchor)
+ std::vector<scoped_refptr<ParsedCertificate>> trust_anchors;
+ trust_store.FindTrustAnchorsByNormalizedName(
+ certs->back()->normalized_issuer(), &trust_anchors);
+ if (trust_anchors.empty())
return false;
- certs_der_trusted_root->push_back(trust_anchor->cert());
+ certs->push_back(std::move(trust_anchors[0]));
return true;
}
} // namespace
-bool VerifyCertificateChain(const std::vector<der::Input>& certs_der,
- const TrustStore& trust_store,
- const SignaturePolicy* signature_policy,
- const der::GeneralizedTime& time) {
+bool VerifyCertificateChain(
+ const std::vector<scoped_refptr<ParsedCertificate>>& cert_chain,
+ const TrustStore& trust_store,
+ const SignaturePolicy* signature_policy,
+ const der::GeneralizedTime& time) {
+ if (cert_chain.empty())
+ return false;
+
+ std::vector<scoped_refptr<ParsedCertificate>> full_chain = cert_chain;
+
// Modify the certificate chain so that its root is a trusted certificate.
- std::vector<der::Input> certs_der_trusted_root;
- if (!BuildSimplePathToTrustAnchor(certs_der, trust_store,
- &certs_der_trusted_root)) {
+ if (!BuildSimplePathToTrustAnchor(trust_store, &full_chain)) {
return false;
}
// Verify the chain.
- return VerifyCertificateChainAssumingTrustedRoot(
- certs_der_trusted_root, trust_store, signature_policy, time);
+ return VerifyCertificateChainAssumingTrustedRoot(full_chain, trust_store,
+ signature_policy, time);
}
} // namespace net

Powered by Google App Engine
This is Rietveld 408576698