Chromium Code Reviews| 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 7bd928bc0c6696adb18ae4606e0dc7668cb3f0cc..4060bf0c12c50c0aac2dd137019bb1306890b80d 100644 |
| --- a/net/cert/internal/verify_certificate_chain.cc |
| +++ b/net/cert/internal/verify_certificate_chain.cc |
| @@ -166,8 +166,8 @@ WARN_UNUSED_RESULT bool PrepareForNextCertificate( |
| der::Input* working_spki, |
| 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. |
| + // TODO(crbug.com/634456): Steps a-b are omitted, as policy mappings are not |
| + // yet implemented. |
| // From RFC 5280 section 6.1.4 step c: |
| // |
| @@ -187,8 +187,8 @@ WARN_UNUSED_RESULT bool PrepareForNextCertificate( |
| 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. |
| + // TODO(eroman): Steps h-j are omitted as policy |
| + // constraints/mappings/inhibitAnyPolicy are not yet implemented. |
| // From RFC 5280 section 6.1.4 step k: |
| // |
| @@ -294,8 +294,8 @@ 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 ParsedCertificate& cert) { |
| - // TODO(eroman): Steps a-b are omitted as policy constraints are not yet |
| - // implemented. |
| + // TODO(crbug.com/634452): Steps a-b are omitted as policy constraints are not |
| + // yet implemented. |
| // Note step c-e are omitted the verification function does |
| // not output the working public key. |
| @@ -323,6 +323,62 @@ WARN_UNUSED_RESULT bool WrapUp(const ParsedCertificate& cert) { |
| return true; |
| } |
| +// Initializes the path validation algorithm given anchor constraints. This |
| +// follows the description in RFC 5937 |
| +WARN_UNUSED_RESULT bool ProcessTrustAnchorConstraints( |
| + const TrustAnchor& trust_anchor, |
| + size_t* max_path_length_ptr, |
| + std::vector<const NameConstraints*>* name_constraints_list) { |
| + // In RFC 5937 the enforcement of anchor constraints is governed by the input |
| + // enforceTrustAnchorConstraints to path validation. In our implementation |
| + // this is always on, and enforcement is controlled solely by whether or not |
| + // the trust anchor specified constraints. |
| + if (!trust_anchor.enforces_constraints()) |
| + return true; |
| + |
| + // Anchor constraints are encoded via the attached certificate. |
| + const ParsedCertificate& cert = *trust_anchor.cert(); |
| + |
| + // The following enforcements follow from RFC 5937 (primarily section 3.2): |
| + |
| + // Initialize name constraints initial-permitted/excluded-subtrees. |
| + if (cert.has_name_constraints()) |
| + name_constraints_list->push_back(&cert.name_constraints()); |
|
eroman
2016/08/16 00:03:01
I don't yet have a test for this -- will probably
|
| + |
| + // TODO(eroman): Initialize user-initial-policy-set based on anchor |
| + // constraints. |
| + |
| + // TODO(eroman): Initialize inhibit any policy based on anchor constraints. |
| + |
| + // TODO(eroman): Initialize require explicit policy based on anchor |
| + // constraints. |
| + |
| + // TODO(eroman): Initialize inhibit policy mapping based on anchor |
| + // constraints. |
| + |
| + // From RFC 5937 section 3.2: |
| + // |
| + // If a basic constraints extension is associated with the trust |
| + // anchor and contains a pathLenConstraint value, set the |
| + // max_path_length state variable equal to the pathLenConstraint |
| + // value from the basic constraints extension. |
| + // |
| + // NOTE: RFC 5937 does not say to enforce the CA=true part of basic |
| + // constraints. |
| + if (cert.has_basic_constraints() && cert.basic_constraints().has_path_len) |
| + *max_path_length_ptr = cert.basic_constraints().path_len; |
| + |
| + // From RFC 5937 section 2: |
| + // |
| + // Extensions may be marked critical or not critical. When trust anchor |
| + // constraints are enforced, clients MUST reject certification paths |
| + // containing a trust anchor with unrecognized critical extensions. |
| + if (!VerifyNoUnconsumedCriticalExtensions(cert)) |
| + return false; |
| + |
| + return true; |
| +} |
| + |
| } // namespace |
| // This implementation is structured to mimic the description of certificate |
| @@ -335,8 +391,6 @@ bool VerifyCertificateChain(const ParsedCertificateList& certs, |
| if (certs.empty()) |
| return false; |
| - // TODO(crbug.com/635200): Support anchor constraints. |
| - |
| // 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. |
| @@ -376,6 +430,12 @@ bool VerifyCertificateChain(const ParsedCertificateList& certs, |
| // certificate. |
| size_t max_path_length = certs.size(); |
| + // Apply any trust anchor constraints per RFC 5937. |
| + if (!ProcessTrustAnchorConstraints(*trust_anchor, &max_path_length, |
| + &name_constraints_list)) { |
| + return false; |
| + } |
| + |
| // Iterate over all the certificates in the reverse direction: starting from |
| // the certificate signed by trust anchor and progressing towards the target |
| // certificate. |