| 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 "base/memory/ptr_util.h" | 10 #include "base/memory/ptr_util.h" |
| 11 #include "net/cert/internal/cert_error_params.h" | 11 #include "net/cert/internal/cert_error_params.h" |
| 12 #include "net/cert/internal/cert_error_scoper.h" | |
| 13 #include "net/cert/internal/cert_errors.h" | 12 #include "net/cert/internal/cert_errors.h" |
| 14 #include "net/cert/internal/name_constraints.h" | 13 #include "net/cert/internal/name_constraints.h" |
| 15 #include "net/cert/internal/parse_certificate.h" | 14 #include "net/cert/internal/parse_certificate.h" |
| 16 #include "net/cert/internal/signature_algorithm.h" | 15 #include "net/cert/internal/signature_algorithm.h" |
| 17 #include "net/cert/internal/signature_policy.h" | 16 #include "net/cert/internal/signature_policy.h" |
| 18 #include "net/cert/internal/trust_store.h" | 17 #include "net/cert/internal/trust_store.h" |
| 19 #include "net/cert/internal/verify_signed_data.h" | 18 #include "net/cert/internal/verify_signed_data.h" |
| 20 #include "net/der/input.h" | 19 #include "net/der/input.h" |
| 21 #include "net/der/parser.h" | 20 #include "net/der/parser.h" |
| 22 | 21 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 50 "Does not have Basic Constraints"); | 49 "Does not have Basic Constraints"); |
| 51 DEFINE_CERT_ERROR_ID(kNotPermittedByNameConstraints, | 50 DEFINE_CERT_ERROR_ID(kNotPermittedByNameConstraints, |
| 52 "Not permitted by name constraints"); | 51 "Not permitted by name constraints"); |
| 53 DEFINE_CERT_ERROR_ID(kSubjectDoesNotMatchIssuer, | 52 DEFINE_CERT_ERROR_ID(kSubjectDoesNotMatchIssuer, |
| 54 "subject does not match issuer"); | 53 "subject does not match issuer"); |
| 55 DEFINE_CERT_ERROR_ID(kVerifySignedDataFailed, "VerifySignedData failed"); | 54 DEFINE_CERT_ERROR_ID(kVerifySignedDataFailed, "VerifySignedData failed"); |
| 56 DEFINE_CERT_ERROR_ID(kSignatureAlgorithmsDifferentEncoding, | 55 DEFINE_CERT_ERROR_ID(kSignatureAlgorithmsDifferentEncoding, |
| 57 "Certificate.signatureAlgorithm is encoded differently " | 56 "Certificate.signatureAlgorithm is encoded differently " |
| 58 "than TBSCertificate.signature"); | 57 "than TBSCertificate.signature"); |
| 59 | 58 |
| 60 DEFINE_CERT_ERROR_ID(kContextTrustAnchor, "Processing Trust Anchor"); | 59 // Adds errors to |errors| if the certificate contains unconsumed _critical_ |
| 61 DEFINE_CERT_ERROR_ID(kContextCertificate, "Processing Certificate"); | |
| 62 | |
| 63 // This class changes the error scope to indicate which certificate in the | |
| 64 // chain is currently being processed. | |
| 65 class CertErrorScoperForCert : public CertErrorScoper { | |
| 66 public: | |
| 67 CertErrorScoperForCert(CertErrors* parent_errors, size_t index) | |
| 68 : CertErrorScoper(parent_errors), index_(index) {} | |
| 69 | |
| 70 std::unique_ptr<CertErrorNode> BuildRootNode() override { | |
| 71 return base::MakeUnique<CertErrorNode>( | |
| 72 CertErrorNodeType::TYPE_CONTEXT, kContextCertificate, | |
| 73 CreateCertErrorParams1SizeT("index", index_)); | |
| 74 } | |
| 75 | |
| 76 private: | |
| 77 size_t index_; | |
| 78 | |
| 79 DISALLOW_COPY_AND_ASSIGN(CertErrorScoperForCert); | |
| 80 }; | |
| 81 | |
| 82 // Returns true if the certificate does not contain any unconsumed _critical_ | |
| 83 // extensions. | 60 // extensions. |
| 84 WARN_UNUSED_RESULT bool VerifyNoUnconsumedCriticalExtensions( | 61 void VerifyNoUnconsumedCriticalExtensions(const ParsedCertificate& cert, |
| 85 const ParsedCertificate& cert, | 62 CertErrors* errors) { |
| 86 CertErrors* errors) { | |
| 87 bool has_unconsumed_critical_extensions = false; | |
| 88 | |
| 89 for (const auto& entry : cert.unparsed_extensions()) { | 63 for (const auto& entry : cert.unparsed_extensions()) { |
| 90 if (entry.second.critical) { | 64 if (entry.second.critical) { |
| 91 has_unconsumed_critical_extensions = true; | |
| 92 errors->AddError(kUnconsumedCriticalExtension, | 65 errors->AddError(kUnconsumedCriticalExtension, |
| 93 CreateCertErrorParams2Der("oid", entry.second.oid, | 66 CreateCertErrorParams2Der("oid", entry.second.oid, |
| 94 "value", entry.second.value)); | 67 "value", entry.second.value)); |
| 95 } | 68 } |
| 96 } | 69 } |
| 97 | |
| 98 return !has_unconsumed_critical_extensions; | |
| 99 } | 70 } |
| 100 | 71 |
| 101 // Returns true if |cert| was self-issued. The definition of self-issuance | 72 // Returns true if |cert| was self-issued. The definition of self-issuance |
| 102 // comes from RFC 5280 section 6.1: | 73 // comes from RFC 5280 section 6.1: |
| 103 // | 74 // |
| 104 // A certificate is self-issued if the same DN appears in the subject | 75 // A certificate is self-issued if the same DN appears in the subject |
| 105 // and issuer fields (the two DNs are the same if they match according | 76 // and issuer fields (the two DNs are the same if they match according |
| 106 // to the rules specified in Section 7.1). In general, the issuer and | 77 // to the rules specified in Section 7.1). In general, the issuer and |
| 107 // subject of the certificates that make up a path are different for | 78 // subject of the certificates that make up a path are different for |
| 108 // each certificate. However, a CA may issue a certificate to itself to | 79 // each certificate. However, a CA may issue a certificate to itself to |
| 109 // support key rollover or changes in certificate policies. These | 80 // support key rollover or changes in certificate policies. These |
| 110 // self-issued certificates are not counted when evaluating path length | 81 // self-issued certificates are not counted when evaluating path length |
| 111 // or name constraints. | 82 // or name constraints. |
| 112 WARN_UNUSED_RESULT bool IsSelfIssued(const ParsedCertificate& cert) { | 83 WARN_UNUSED_RESULT bool IsSelfIssued(const ParsedCertificate& cert) { |
| 113 return cert.normalized_subject() == cert.normalized_issuer(); | 84 return cert.normalized_subject() == cert.normalized_issuer(); |
| 114 } | 85 } |
| 115 | 86 |
| 116 // Returns true if |cert| is valid at time |time|. | 87 // Adds errors to |errors| if |cert| is not valid at time |time|. |
| 117 // | 88 // |
| 118 // The certificate's validity requirements are described by RFC 5280 section | 89 // The certificate's validity requirements are described by RFC 5280 section |
| 119 // 4.1.2.5: | 90 // 4.1.2.5: |
| 120 // | 91 // |
| 121 // The validity period for a certificate is the period of time from | 92 // The validity period for a certificate is the period of time from |
| 122 // notBefore through notAfter, inclusive. | 93 // notBefore through notAfter, inclusive. |
| 123 WARN_UNUSED_RESULT bool VerifyTimeValidity(const ParsedCertificate& cert, | 94 void VerifyTimeValidity(const ParsedCertificate& cert, |
| 124 const der::GeneralizedTime time, | 95 const der::GeneralizedTime time, |
| 125 CertErrors* errors) { | 96 CertErrors* errors) { |
| 126 if (time < cert.tbs().validity_not_before) { | 97 if (time < cert.tbs().validity_not_before) |
| 127 errors->AddError(kValidityFailedNotBefore); | 98 errors->AddError(kValidityFailedNotBefore); |
| 128 return false; | |
| 129 } | |
| 130 | 99 |
| 131 if (cert.tbs().validity_not_after < time) { | 100 if (cert.tbs().validity_not_after < time) |
| 132 errors->AddError(kValidityFailedNotAfter); | 101 errors->AddError(kValidityFailedNotAfter); |
| 133 return false; | |
| 134 } | |
| 135 | |
| 136 return true; | |
| 137 } | 102 } |
| 138 | 103 |
| 139 // Returns true if |cert| has internally consistent signature algorithms. | 104 // Adds errors to |errors| if |cert| has internally inconsistent signature |
| 105 // algorithms. |
| 140 // | 106 // |
| 141 // X.509 certificates contain two different signature algorithms: | 107 // X.509 certificates contain two different signature algorithms: |
| 142 // (1) The signatureAlgorithm field of Certificate | 108 // (1) The signatureAlgorithm field of Certificate |
| 143 // (2) The signature field of TBSCertificate | 109 // (2) The signature field of TBSCertificate |
| 144 // | 110 // |
| 145 // According to RFC 5280 section 4.1.1.2 and 4.1.2.3 these two fields must be | 111 // According to RFC 5280 section 4.1.1.2 and 4.1.2.3 these two fields must be |
| 146 // equal: | 112 // equal: |
| 147 // | 113 // |
| 148 // This field MUST contain the same algorithm identifier as the | 114 // This field MUST contain the same algorithm identifier as the |
| 149 // signature field in the sequence tbsCertificate (Section 4.1.2.3). | 115 // signature field in the sequence tbsCertificate (Section 4.1.2.3). |
| 150 // | 116 // |
| 151 // The spec is not explicit about what "the same algorithm identifier" means. | 117 // The spec is not explicit about what "the same algorithm identifier" means. |
| 152 // Our interpretation is that the two DER-encoded fields must be byte-for-byte | 118 // Our interpretation is that the two DER-encoded fields must be byte-for-byte |
| 153 // identical. | 119 // identical. |
| 154 // | 120 // |
| 155 // In practice however there are certificates which use different encodings for | 121 // In practice however there are certificates which use different encodings for |
| 156 // specifying RSA with SHA1 (different OIDs). This is special-cased for | 122 // specifying RSA with SHA1 (different OIDs). This is special-cased for |
| 157 // compatibility sake. | 123 // compatibility sake. |
| 158 WARN_UNUSED_RESULT bool VerifySignatureAlgorithmsMatch( | 124 void VerifySignatureAlgorithmsMatch(const ParsedCertificate& cert, |
| 159 const ParsedCertificate& cert, | 125 CertErrors* errors) { |
| 160 CertErrors* errors) { | |
| 161 const der::Input& alg1_tlv = cert.signature_algorithm_tlv(); | 126 const der::Input& alg1_tlv = cert.signature_algorithm_tlv(); |
| 162 const der::Input& alg2_tlv = cert.tbs().signature_algorithm_tlv; | 127 const der::Input& alg2_tlv = cert.tbs().signature_algorithm_tlv; |
| 163 | 128 |
| 164 // Ensure that the two DER-encoded signature algorithms are byte-for-byte | 129 // Ensure that the two DER-encoded signature algorithms are byte-for-byte |
| 165 // equal. | 130 // equal. |
| 166 if (alg1_tlv == alg2_tlv) | 131 if (alg1_tlv == alg2_tlv) |
| 167 return true; | 132 return; |
| 168 | 133 |
| 169 // But make a compatibility concession if alternate encodings are used | 134 // But make a compatibility concession if alternate encodings are used |
| 170 // TODO(eroman): Turn this warning into an error. | 135 // TODO(eroman): Turn this warning into an error. |
| 171 // TODO(eroman): Add a unit-test that exercises this case. | 136 // TODO(eroman): Add a unit-test that exercises this case. |
| 172 if (SignatureAlgorithm::IsEquivalent(alg1_tlv, alg2_tlv)) { | 137 if (SignatureAlgorithm::IsEquivalent(alg1_tlv, alg2_tlv)) { |
| 173 errors->AddWarning( | 138 errors->AddWarning( |
| 174 kSignatureAlgorithmsDifferentEncoding, | 139 kSignatureAlgorithmsDifferentEncoding, |
| 175 CreateCertErrorParams2Der("Certificate.algorithm", alg1_tlv, | 140 CreateCertErrorParams2Der("Certificate.algorithm", alg1_tlv, |
| 176 "TBSCertificate.signature", alg2_tlv)); | 141 "TBSCertificate.signature", alg2_tlv)); |
| 177 return true; | 142 return; |
| 178 } | 143 } |
| 179 | 144 |
| 180 errors->AddError( | 145 errors->AddError( |
| 181 kSignatureAlgorithmMismatch, | 146 kSignatureAlgorithmMismatch, |
| 182 CreateCertErrorParams2Der("Certificate.algorithm", alg1_tlv, | 147 CreateCertErrorParams2Der("Certificate.algorithm", alg1_tlv, |
| 183 "TBSCertificate.signature", alg2_tlv)); | 148 "TBSCertificate.signature", alg2_tlv)); |
| 184 | |
| 185 return false; | |
| 186 } | 149 } |
| 187 | 150 |
| 188 // This function corresponds to RFC 5280 section 6.1.3's "Basic Certificate | 151 // This function corresponds to RFC 5280 section 6.1.3's "Basic Certificate |
| 189 // Processing" procedure. | 152 // Processing" procedure. |
| 190 WARN_UNUSED_RESULT bool BasicCertificateProcessing( | 153 void BasicCertificateProcessing( |
| 191 const ParsedCertificate& cert, | 154 const ParsedCertificate& cert, |
| 192 bool is_target_cert, | 155 bool is_target_cert, |
| 193 const SignaturePolicy* signature_policy, | 156 const SignaturePolicy* signature_policy, |
| 194 const der::GeneralizedTime& time, | 157 const der::GeneralizedTime& time, |
| 195 const der::Input& working_spki, | 158 const der::Input& working_spki, |
| 196 const der::Input& working_normalized_issuer_name, | 159 const der::Input& working_normalized_issuer_name, |
| 197 const std::vector<const NameConstraints*>& name_constraints_list, | 160 const std::vector<const NameConstraints*>& name_constraints_list, |
| 198 CertErrors* errors) { | 161 CertErrors* errors) { |
| 199 // Check that the signature algorithms in Certificate vs TBSCertificate | 162 // Check that the signature algorithms in Certificate vs TBSCertificate |
| 200 // match. This isn't part of RFC 5280 section 6.1.3, but is mandated by | 163 // match. This isn't part of RFC 5280 section 6.1.3, but is mandated by |
| 201 // sections 4.1.1.2 and 4.1.2.3. | 164 // sections 4.1.1.2 and 4.1.2.3. |
| 202 if (!VerifySignatureAlgorithmsMatch(cert, errors)) | 165 VerifySignatureAlgorithmsMatch(cert, errors); |
| 203 return false; | |
| 204 | 166 |
| 205 // Verify the digital signature using the previous certificate's key (RFC | 167 // Verify the digital signature using the previous certificate's key (RFC |
| 206 // 5280 section 6.1.3 step a.1). | 168 // 5280 section 6.1.3 step a.1). |
| 207 if (!cert.has_valid_supported_signature_algorithm()) { | 169 if (!cert.has_valid_supported_signature_algorithm()) { |
| 208 errors->AddError( | 170 errors->AddError( |
| 209 kInvalidOrUnsupportedSignatureAlgorithm, | 171 kInvalidOrUnsupportedSignatureAlgorithm, |
| 210 CreateCertErrorParams1Der("algorithm", cert.signature_algorithm_tlv())); | 172 CreateCertErrorParams1Der("algorithm", cert.signature_algorithm_tlv())); |
| 211 return false; | 173 } else { |
| 212 } | 174 if (!VerifySignedData(cert.signature_algorithm(), |
| 213 | 175 cert.tbs_certificate_tlv(), cert.signature_value(), |
| 214 if (!VerifySignedData(cert.signature_algorithm(), cert.tbs_certificate_tlv(), | 176 working_spki, signature_policy, errors)) { |
| 215 cert.signature_value(), working_spki, signature_policy, | 177 errors->AddError(kVerifySignedDataFailed); |
| 216 errors)) { | 178 } |
| 217 errors->AddError(kVerifySignedDataFailed); | |
| 218 return false; | |
| 219 } | 179 } |
| 220 | 180 |
| 221 // Check the time range for the certificate's validity, ensuring it is valid | 181 // Check the time range for the certificate's validity, ensuring it is valid |
| 222 // at |time|. | 182 // at |time|. |
| 223 // (RFC 5280 section 6.1.3 step a.2) | 183 // (RFC 5280 section 6.1.3 step a.2) |
| 224 if (!VerifyTimeValidity(cert, time, errors)) | 184 VerifyTimeValidity(cert, time, errors); |
| 225 return false; | |
| 226 | 185 |
| 227 // TODO(eroman): Check revocation (RFC 5280 section 6.1.3 step a.3) | 186 // TODO(eroman): Check revocation (RFC 5280 section 6.1.3 step a.3) |
| 228 | 187 |
| 229 // Verify the certificate's issuer name matches the issuing certificate's | 188 // Verify the certificate's issuer name matches the issuing certificate's |
| 230 // subject name. (RFC 5280 section 6.1.3 step a.4) | 189 // subject name. (RFC 5280 section 6.1.3 step a.4) |
| 231 if (cert.normalized_issuer() != working_normalized_issuer_name) { | 190 if (cert.normalized_issuer() != working_normalized_issuer_name) |
| 232 errors->AddError(kSubjectDoesNotMatchIssuer); | 191 errors->AddError(kSubjectDoesNotMatchIssuer); |
| 233 return false; | |
| 234 } | |
| 235 | 192 |
| 236 // Name constraints (RFC 5280 section 6.1.3 step b & c) | 193 // Name constraints (RFC 5280 section 6.1.3 step b & c) |
| 237 // If certificate i is self-issued and it is not the final certificate in the | 194 // If certificate i is self-issued and it is not the final certificate in the |
| 238 // path, skip this step for certificate i. | 195 // path, skip this step for certificate i. |
| 239 if (!name_constraints_list.empty() && | 196 if (!name_constraints_list.empty() && |
| 240 (!IsSelfIssued(cert) || is_target_cert)) { | 197 (!IsSelfIssued(cert) || is_target_cert)) { |
| 241 for (const NameConstraints* nc : name_constraints_list) { | 198 for (const NameConstraints* nc : name_constraints_list) { |
| 242 if (!nc->IsPermittedCert(cert.normalized_subject(), | 199 if (!nc->IsPermittedCert(cert.normalized_subject(), |
| 243 cert.subject_alt_names())) { | 200 cert.subject_alt_names())) { |
| 244 errors->AddError(kNotPermittedByNameConstraints); | 201 errors->AddError(kNotPermittedByNameConstraints); |
| 245 return false; | |
| 246 } | 202 } |
| 247 } | 203 } |
| 248 } | 204 } |
| 249 | 205 |
| 250 // TODO(eroman): Steps d-f are omitted, as policy constraints are not yet | 206 // TODO(eroman): Steps d-f are omitted, as policy constraints are not yet |
| 251 // implemented. | 207 // implemented. |
| 252 | |
| 253 return true; | |
| 254 } | 208 } |
| 255 | 209 |
| 256 // This function corresponds to RFC 5280 section 6.1.4's "Preparation for | 210 // This function corresponds to RFC 5280 section 6.1.4's "Preparation for |
| 257 // Certificate i+1" procedure. |cert| is expected to be an intermediate. | 211 // Certificate i+1" procedure. |cert| is expected to be an intermediate. |
| 258 WARN_UNUSED_RESULT bool PrepareForNextCertificate( | 212 void PrepareForNextCertificate( |
| 259 const ParsedCertificate& cert, | 213 const ParsedCertificate& cert, |
| 260 size_t* max_path_length_ptr, | 214 size_t* max_path_length_ptr, |
| 261 der::Input* working_spki, | 215 der::Input* working_spki, |
| 262 der::Input* working_normalized_issuer_name, | 216 der::Input* working_normalized_issuer_name, |
| 263 std::vector<const NameConstraints*>* name_constraints_list, | 217 std::vector<const NameConstraints*>* name_constraints_list, |
| 264 CertErrors* errors) { | 218 CertErrors* errors) { |
| 265 // TODO(crbug.com/634456): Steps a-b are omitted, as policy mappings are not | 219 // TODO(crbug.com/634456): Steps a-b are omitted, as policy mappings are not |
| 266 // yet implemented. | 220 // yet implemented. |
| 267 | 221 |
| 268 // From RFC 5280 section 6.1.4 step c: | 222 // From RFC 5280 section 6.1.4 step c: |
| (...skipping 25 matching lines...) Expand all Loading... |
| 294 // certificate, then the application MUST either verify that | 248 // certificate, then the application MUST either verify that |
| 295 // certificate i is a CA certificate through out-of-band means | 249 // certificate i is a CA certificate through out-of-band means |
| 296 // or reject the certificate. Conforming implementations may | 250 // or reject the certificate. Conforming implementations may |
| 297 // choose to reject all version 1 and version 2 intermediate | 251 // choose to reject all version 1 and version 2 intermediate |
| 298 // certificates.) | 252 // certificates.) |
| 299 // | 253 // |
| 300 // This code implicitly rejects non version 3 intermediates, since they | 254 // This code implicitly rejects non version 3 intermediates, since they |
| 301 // can't contain a BasicConstraints extension. | 255 // can't contain a BasicConstraints extension. |
| 302 if (!cert.has_basic_constraints()) { | 256 if (!cert.has_basic_constraints()) { |
| 303 errors->AddError(kMissingBasicConstraints); | 257 errors->AddError(kMissingBasicConstraints); |
| 304 return false; | 258 } else if (!cert.basic_constraints().is_ca) { |
| 305 } | |
| 306 | |
| 307 if (!cert.basic_constraints().is_ca) { | |
| 308 errors->AddError(kBasicConstraintsIndicatesNotCa); | 259 errors->AddError(kBasicConstraintsIndicatesNotCa); |
| 309 return false; | |
| 310 } | 260 } |
| 311 | 261 |
| 312 // From RFC 5280 section 6.1.4 step l: | 262 // From RFC 5280 section 6.1.4 step l: |
| 313 // | 263 // |
| 314 // If the certificate was not self-issued, verify that | 264 // If the certificate was not self-issued, verify that |
| 315 // max_path_length is greater than zero and decrement | 265 // max_path_length is greater than zero and decrement |
| 316 // max_path_length by 1. | 266 // max_path_length by 1. |
| 317 if (!IsSelfIssued(cert)) { | 267 if (!IsSelfIssued(cert)) { |
| 318 if (*max_path_length_ptr == 0) { | 268 if (*max_path_length_ptr == 0) { |
| 319 errors->AddError(kMaxPathLengthViolated); | 269 errors->AddError(kMaxPathLengthViolated); |
| 320 return false; | 270 } else { |
| 271 --(*max_path_length_ptr); |
| 321 } | 272 } |
| 322 --(*max_path_length_ptr); | |
| 323 } | 273 } |
| 324 | 274 |
| 325 // From RFC 5280 section 6.1.4 step m: | 275 // From RFC 5280 section 6.1.4 step m: |
| 326 // | 276 // |
| 327 // If pathLenConstraint is present in the certificate and is | 277 // If pathLenConstraint is present in the certificate and is |
| 328 // less than max_path_length, set max_path_length to the value | 278 // less than max_path_length, set max_path_length to the value |
| 329 // of pathLenConstraint. | 279 // of pathLenConstraint. |
| 330 if (cert.basic_constraints().has_path_len && | 280 if (cert.has_basic_constraints() && cert.basic_constraints().has_path_len && |
| 331 cert.basic_constraints().path_len < *max_path_length_ptr) { | 281 cert.basic_constraints().path_len < *max_path_length_ptr) { |
| 332 *max_path_length_ptr = cert.basic_constraints().path_len; | 282 *max_path_length_ptr = cert.basic_constraints().path_len; |
| 333 } | 283 } |
| 334 | 284 |
| 335 // From RFC 5280 section 6.1.4 step n: | 285 // From RFC 5280 section 6.1.4 step n: |
| 336 // | 286 // |
| 337 // If a key usage extension is present, verify that the | 287 // If a key usage extension is present, verify that the |
| 338 // keyCertSign bit is set. | 288 // keyCertSign bit is set. |
| 339 if (cert.has_key_usage() && | 289 if (cert.has_key_usage() && |
| 340 !cert.key_usage().AssertsBit(KEY_USAGE_BIT_KEY_CERT_SIGN)) { | 290 !cert.key_usage().AssertsBit(KEY_USAGE_BIT_KEY_CERT_SIGN)) { |
| 341 errors->AddError(kKeyCertSignBitNotSet); | 291 errors->AddError(kKeyCertSignBitNotSet); |
| 342 return false; | |
| 343 } | 292 } |
| 344 | 293 |
| 345 // From RFC 5280 section 6.1.4 step o: | 294 // From RFC 5280 section 6.1.4 step o: |
| 346 // | 295 // |
| 347 // Recognize and process any other critical extension present in | 296 // Recognize and process any other critical extension present in |
| 348 // the certificate. Process any other recognized non-critical | 297 // the certificate. Process any other recognized non-critical |
| 349 // extension present in the certificate that is relevant to path | 298 // extension present in the certificate that is relevant to path |
| 350 // processing. | 299 // processing. |
| 351 if (!VerifyNoUnconsumedCriticalExtensions(cert, errors)) | 300 VerifyNoUnconsumedCriticalExtensions(cert, errors); |
| 352 return false; | |
| 353 | |
| 354 return true; | |
| 355 } | 301 } |
| 356 | 302 |
| 357 // Checks that if the target certificate has properties that only a CA should | 303 // Checks that if the target certificate has properties that only a CA should |
| 358 // have (keyCertSign, CA=true, pathLenConstraint), then its other properties | 304 // have (keyCertSign, CA=true, pathLenConstraint), then its other properties |
| 359 // are consistent with being a CA. | 305 // are consistent with being a CA. If it does, adds errors to |errors|. |
| 360 // | 306 // |
| 361 // This follows from some requirements in RFC 5280 section 4.2.1.9. In | 307 // This follows from some requirements in RFC 5280 section 4.2.1.9. In |
| 362 // particular: | 308 // particular: |
| 363 // | 309 // |
| 364 // CAs MUST NOT include the pathLenConstraint field unless the cA | 310 // CAs MUST NOT include the pathLenConstraint field unless the cA |
| 365 // boolean is asserted and the key usage extension asserts the | 311 // boolean is asserted and the key usage extension asserts the |
| 366 // keyCertSign bit. | 312 // keyCertSign bit. |
| 367 // | 313 // |
| 368 // And: | 314 // And: |
| 369 // | 315 // |
| 370 // If the cA boolean is not asserted, then the keyCertSign bit in the key | 316 // If the cA boolean is not asserted, then the keyCertSign bit in the key |
| 371 // usage extension MUST NOT be asserted. | 317 // usage extension MUST NOT be asserted. |
| 372 // | 318 // |
| 373 // TODO(eroman): Strictly speaking the first requirement is on CAs and not the | 319 // TODO(eroman): Strictly speaking the first requirement is on CAs and not the |
| 374 // certificate client, so could be skipped. | 320 // certificate client, so could be skipped. |
| 375 // | 321 // |
| 376 // TODO(eroman): I don't believe Firefox enforces the keyCertSign restriction | 322 // TODO(eroman): I don't believe Firefox enforces the keyCertSign restriction |
| 377 // for compatibility reasons. Investigate if we need to similarly relax this | 323 // for compatibility reasons. Investigate if we need to similarly relax this |
| 378 // constraint. | 324 // constraint. |
| 379 WARN_UNUSED_RESULT bool VerifyTargetCertHasConsistentCaBits( | 325 void VerifyTargetCertHasConsistentCaBits(const ParsedCertificate& cert, |
| 380 const ParsedCertificate& cert, | 326 CertErrors* errors) { |
| 381 CertErrors* errors) { | |
| 382 // Check if the certificate contains any property specific to CAs. | 327 // Check if the certificate contains any property specific to CAs. |
| 383 bool has_ca_property = | 328 bool has_ca_property = |
| 384 (cert.has_basic_constraints() && | 329 (cert.has_basic_constraints() && |
| 385 (cert.basic_constraints().is_ca || | 330 (cert.basic_constraints().is_ca || |
| 386 cert.basic_constraints().has_path_len)) || | 331 cert.basic_constraints().has_path_len)) || |
| 387 (cert.has_key_usage() && | 332 (cert.has_key_usage() && |
| 388 cert.key_usage().AssertsBit(KEY_USAGE_BIT_KEY_CERT_SIGN)); | 333 cert.key_usage().AssertsBit(KEY_USAGE_BIT_KEY_CERT_SIGN)); |
| 389 | 334 |
| 390 // If it "looks" like a CA because it has a CA-only property, then check that | 335 // If it "looks" like a CA because it has a CA-only property, then check that |
| 391 // it sets ALL the properties expected of a CA. | 336 // it sets ALL the properties expected of a CA. |
| 392 if (has_ca_property) { | 337 if (has_ca_property) { |
| 393 bool success = cert.has_basic_constraints() && | 338 bool success = cert.has_basic_constraints() && |
| 394 cert.basic_constraints().is_ca && | 339 cert.basic_constraints().is_ca && |
| 395 (!cert.has_key_usage() || | 340 (!cert.has_key_usage() || |
| 396 cert.key_usage().AssertsBit(KEY_USAGE_BIT_KEY_CERT_SIGN)); | 341 cert.key_usage().AssertsBit(KEY_USAGE_BIT_KEY_CERT_SIGN)); |
| 397 if (!success) { | 342 if (!success) { |
| 398 // TODO(eroman): Add DER for basic constraints and key usage. | 343 // TODO(eroman): Add DER for basic constraints and key usage. |
| 399 errors->AddError(kTargetCertInconsistentCaBits); | 344 errors->AddError(kTargetCertInconsistentCaBits); |
| 400 } | 345 } |
| 401 | |
| 402 return success; | |
| 403 } | 346 } |
| 404 | |
| 405 return true; | |
| 406 } | 347 } |
| 407 | 348 |
| 408 // This function corresponds with RFC 5280 section 6.1.5's "Wrap-Up Procedure". | 349 // This function corresponds with RFC 5280 section 6.1.5's "Wrap-Up Procedure". |
| 409 // It does processing for the final certificate (the target cert). | 350 // It does processing for the final certificate (the target cert). |
| 410 WARN_UNUSED_RESULT bool WrapUp(const ParsedCertificate& cert, | 351 void WrapUp(const ParsedCertificate& cert, CertErrors* errors) { |
| 411 CertErrors* errors) { | |
| 412 // TODO(crbug.com/634452): Steps a-b are omitted as policy constraints are not | 352 // TODO(crbug.com/634452): Steps a-b are omitted as policy constraints are not |
| 413 // yet implemented. | 353 // yet implemented. |
| 414 | 354 |
| 415 // Note step c-e are omitted the verification function does | 355 // Note step c-e are omitted the verification function does |
| 416 // not output the working public key. | 356 // not output the working public key. |
| 417 | 357 |
| 418 // From RFC 5280 section 6.1.5 step f: | 358 // From RFC 5280 section 6.1.5 step f: |
| 419 // | 359 // |
| 420 // Recognize and process any other critical extension present in | 360 // Recognize and process any other critical extension present in |
| 421 // the certificate n. Process any other recognized non-critical | 361 // the certificate n. Process any other recognized non-critical |
| 422 // extension present in certificate n that is relevant to path | 362 // extension present in certificate n that is relevant to path |
| 423 // processing. | 363 // processing. |
| 424 // | 364 // |
| 425 // Note that this is duplicated by PrepareForNextCertificate() so as to | 365 // Note that this is duplicated by PrepareForNextCertificate() so as to |
| 426 // directly match the procedures in RFC 5280's section 6.1. | 366 // directly match the procedures in RFC 5280's section 6.1. |
| 427 if (!VerifyNoUnconsumedCriticalExtensions(cert, errors)) | 367 VerifyNoUnconsumedCriticalExtensions(cert, errors); |
| 428 return false; | |
| 429 | 368 |
| 430 // TODO(eroman): Step g is omitted, as policy constraints are not yet | 369 // TODO(eroman): Step g is omitted, as policy constraints are not yet |
| 431 // implemented. | 370 // implemented. |
| 432 | 371 |
| 433 // The following check is NOT part of RFC 5280 6.1.5's "Wrap-Up Procedure", | 372 // The following check is NOT part of RFC 5280 6.1.5's "Wrap-Up Procedure", |
| 434 // however is implied by RFC 5280 section 4.2.1.9. | 373 // however is implied by RFC 5280 section 4.2.1.9. |
| 435 if (!VerifyTargetCertHasConsistentCaBits(cert, errors)) | 374 VerifyTargetCertHasConsistentCaBits(cert, errors); |
| 436 return false; | |
| 437 | |
| 438 return true; | |
| 439 } | 375 } |
| 440 | 376 |
| 441 // Initializes the path validation algorithm given anchor constraints. This | 377 // Initializes the path validation algorithm given anchor constraints. This |
| 442 // follows the description in RFC 5937 | 378 // follows the description in RFC 5937 |
| 443 WARN_UNUSED_RESULT bool ProcessTrustAnchorConstraints( | 379 void ProcessTrustAnchorConstraints( |
| 444 const TrustAnchor& trust_anchor, | 380 const TrustAnchor& trust_anchor, |
| 445 size_t* max_path_length_ptr, | 381 size_t* max_path_length_ptr, |
| 446 std::vector<const NameConstraints*>* name_constraints_list, | 382 std::vector<const NameConstraints*>* name_constraints_list, |
| 447 CertErrors* errors) { | 383 CertErrors* errors) { |
| 448 // Set the trust anchor as the current context for any subsequent errors. | |
| 449 CertErrorScoperNoParams error_context(errors, kContextTrustAnchor); | |
| 450 | |
| 451 // In RFC 5937 the enforcement of anchor constraints is governed by the input | 384 // In RFC 5937 the enforcement of anchor constraints is governed by the input |
| 452 // enforceTrustAnchorConstraints to path validation. In our implementation | 385 // enforceTrustAnchorConstraints to path validation. In our implementation |
| 453 // this is always on, and enforcement is controlled solely by whether or not | 386 // this is always on, and enforcement is controlled solely by whether or not |
| 454 // the trust anchor specified constraints. | 387 // the trust anchor specified constraints. |
| 455 if (!trust_anchor.enforces_constraints()) | 388 if (!trust_anchor.enforces_constraints()) |
| 456 return true; | 389 return; |
| 457 | 390 |
| 458 // Anchor constraints are encoded via the attached certificate. | 391 // Anchor constraints are encoded via the attached certificate. |
| 459 const ParsedCertificate& cert = *trust_anchor.cert(); | 392 const ParsedCertificate& cert = *trust_anchor.cert(); |
| 460 | 393 |
| 461 // The following enforcements follow from RFC 5937 (primarily section 3.2): | 394 // The following enforcements follow from RFC 5937 (primarily section 3.2): |
| 462 | 395 |
| 463 // Initialize name constraints initial-permitted/excluded-subtrees. | 396 // Initialize name constraints initial-permitted/excluded-subtrees. |
| 464 if (cert.has_name_constraints()) | 397 if (cert.has_name_constraints()) |
| 465 name_constraints_list->push_back(&cert.name_constraints()); | 398 name_constraints_list->push_back(&cert.name_constraints()); |
| 466 | 399 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 485 // NOTE: RFC 5937 does not say to enforce the CA=true part of basic | 418 // NOTE: RFC 5937 does not say to enforce the CA=true part of basic |
| 486 // constraints. | 419 // constraints. |
| 487 if (cert.has_basic_constraints() && cert.basic_constraints().has_path_len) | 420 if (cert.has_basic_constraints() && cert.basic_constraints().has_path_len) |
| 488 *max_path_length_ptr = cert.basic_constraints().path_len; | 421 *max_path_length_ptr = cert.basic_constraints().path_len; |
| 489 | 422 |
| 490 // From RFC 5937 section 2: | 423 // From RFC 5937 section 2: |
| 491 // | 424 // |
| 492 // Extensions may be marked critical or not critical. When trust anchor | 425 // Extensions may be marked critical or not critical. When trust anchor |
| 493 // constraints are enforced, clients MUST reject certification paths | 426 // constraints are enforced, clients MUST reject certification paths |
| 494 // containing a trust anchor with unrecognized critical extensions. | 427 // containing a trust anchor with unrecognized critical extensions. |
| 495 if (!VerifyNoUnconsumedCriticalExtensions(cert, errors)) | 428 VerifyNoUnconsumedCriticalExtensions(cert, errors); |
| 496 return false; | |
| 497 | |
| 498 return true; | |
| 499 } | 429 } |
| 500 | 430 |
| 501 } // namespace | |
| 502 | |
| 503 // This implementation is structured to mimic the description of certificate | 431 // This implementation is structured to mimic the description of certificate |
| 504 // path verification given by RFC 5280 section 6.1. | 432 // path verification given by RFC 5280 section 6.1. |
| 505 bool VerifyCertificateChain(const ParsedCertificateList& certs, | 433 void VerifyCertificateChainNoReturnValue( |
| 506 const TrustAnchor* trust_anchor, | 434 const ParsedCertificateList& certs, |
| 507 const SignaturePolicy* signature_policy, | 435 const TrustAnchor* trust_anchor, |
| 508 const der::GeneralizedTime& time, | 436 const SignaturePolicy* signature_policy, |
| 509 CertErrors* errors) { | 437 const der::GeneralizedTime& time, |
| 438 CertPathErrors* errors) { |
| 510 DCHECK(trust_anchor); | 439 DCHECK(trust_anchor); |
| 511 DCHECK(signature_policy); | 440 DCHECK(signature_policy); |
| 512 DCHECK(errors); | 441 DCHECK(errors); |
| 513 | 442 |
| 514 // An empty chain is necessarily invalid. | 443 // An empty chain is necessarily invalid. |
| 515 if (certs.empty()) { | 444 if (certs.empty()) { |
| 516 errors->AddError(kChainIsEmpty); | 445 errors->GetOtherErrors()->AddError(kChainIsEmpty); |
| 517 return false; | 446 return; |
| 518 } | 447 } |
| 519 | 448 |
| 520 // Will contain a NameConstraints for each previous cert in the chain which | 449 // Will contain a NameConstraints for each previous cert in the chain which |
| 521 // had nameConstraints. This corresponds to the permitted_subtrees and | 450 // had nameConstraints. This corresponds to the permitted_subtrees and |
| 522 // excluded_subtrees state variables from RFC 5280. | 451 // excluded_subtrees state variables from RFC 5280. |
| 523 std::vector<const NameConstraints*> name_constraints_list; | 452 std::vector<const NameConstraints*> name_constraints_list; |
| 524 | 453 |
| 525 // |working_spki| is an amalgamation of 3 separate variables from RFC 5280: | 454 // |working_spki| is an amalgamation of 3 separate variables from RFC 5280: |
| 526 // * working_public_key | 455 // * working_public_key |
| 527 // * working_public_key_algorithm | 456 // * working_public_key_algorithm |
| (...skipping 22 matching lines...) Expand all Loading... |
| 550 // section 6.1.2: | 479 // section 6.1.2: |
| 551 // | 480 // |
| 552 // max_path_length: this integer is initialized to n, is | 481 // max_path_length: this integer is initialized to n, is |
| 553 // decremented for each non-self-issued certificate in the path, | 482 // decremented for each non-self-issued certificate in the path, |
| 554 // and may be reduced to the value in the path length constraint | 483 // and may be reduced to the value in the path length constraint |
| 555 // field within the basic constraints extension of a CA | 484 // field within the basic constraints extension of a CA |
| 556 // certificate. | 485 // certificate. |
| 557 size_t max_path_length = certs.size(); | 486 size_t max_path_length = certs.size(); |
| 558 | 487 |
| 559 // Apply any trust anchor constraints per RFC 5937. | 488 // Apply any trust anchor constraints per RFC 5937. |
| 560 if (!ProcessTrustAnchorConstraints(*trust_anchor, &max_path_length, | 489 // |
| 561 &name_constraints_list, errors)) { | 490 // TODO(eroman): Errors on the trust anchor are put into a certificate bucket |
| 562 return false; | 491 // GetErrorsForCert(certs.size()). This is a bit magical, and |
| 563 } | 492 // has some integration issues. |
| 493 ProcessTrustAnchorConstraints(*trust_anchor, &max_path_length, |
| 494 &name_constraints_list, |
| 495 errors->GetErrorsForCert(certs.size())); |
| 564 | 496 |
| 565 // Iterate over all the certificates in the reverse direction: starting from | 497 // Iterate over all the certificates in the reverse direction: starting from |
| 566 // the certificate signed by trust anchor and progressing towards the target | 498 // the certificate signed by trust anchor and progressing towards the target |
| 567 // certificate. | 499 // certificate. |
| 568 // | 500 // |
| 569 // Note that |i| uses 0-based indexing whereas in RFC 5280 it is 1-based. | 501 // Note that |i| uses 0-based indexing whereas in RFC 5280 it is 1-based. |
| 570 // | 502 // |
| 571 // * i=0 : Certificated signed by trust anchor. | 503 // * i=0 : Certificated signed by trust anchor. |
| 572 // * i=N-1 : Target certificate. | 504 // * i=N-1 : Target certificate. |
| 573 for (size_t i = 0; i < certs.size(); ++i) { | 505 for (size_t i = 0; i < certs.size(); ++i) { |
| 574 const size_t index_into_certs = certs.size() - i - 1; | 506 const size_t index_into_certs = certs.size() - i - 1; |
| 575 | 507 |
| 576 // |is_target_cert| is true if the current certificate is the target | 508 // |is_target_cert| is true if the current certificate is the target |
| 577 // certificate being verified. The target certificate isn't necessarily an | 509 // certificate being verified. The target certificate isn't necessarily an |
| 578 // end-entity certificate. | 510 // end-entity certificate. |
| 579 const bool is_target_cert = index_into_certs == 0; | 511 const bool is_target_cert = index_into_certs == 0; |
| 580 | 512 |
| 581 const ParsedCertificate& cert = *certs[index_into_certs]; | 513 const ParsedCertificate& cert = *certs[index_into_certs]; |
| 582 | 514 |
| 583 // Set the current certificate as the context for any subsequent errors. | 515 // Output errors for the current certificate into an error bucket that is |
| 584 CertErrorScoperForCert error_context(errors, i); | 516 // associated with that certificate. |
| 517 CertErrors* cert_errors = errors->GetErrorsForCert(index_into_certs); |
| 585 | 518 |
| 586 // Per RFC 5280 section 6.1: | 519 // Per RFC 5280 section 6.1: |
| 587 // * Do basic processing for each certificate | 520 // * Do basic processing for each certificate |
| 588 // * If it is the last certificate in the path (target certificate) | 521 // * If it is the last certificate in the path (target certificate) |
| 589 // - Then run "Wrap up" | 522 // - Then run "Wrap up" |
| 590 // - Otherwise run "Prepare for Next cert" | 523 // - Otherwise run "Prepare for Next cert" |
| 591 if (!BasicCertificateProcessing( | 524 BasicCertificateProcessing(cert, is_target_cert, signature_policy, time, |
| 592 cert, is_target_cert, signature_policy, time, working_spki, | 525 working_spki, working_normalized_issuer_name, |
| 593 working_normalized_issuer_name, name_constraints_list, errors)) { | 526 name_constraints_list, cert_errors); |
| 594 return false; | |
| 595 } | |
| 596 if (!is_target_cert) { | 527 if (!is_target_cert) { |
| 597 if (!PrepareForNextCertificate(cert, &max_path_length, &working_spki, | 528 PrepareForNextCertificate(cert, &max_path_length, &working_spki, |
| 598 &working_normalized_issuer_name, | 529 &working_normalized_issuer_name, |
| 599 &name_constraints_list, errors)) { | 530 &name_constraints_list, cert_errors); |
| 600 return false; | |
| 601 } | |
| 602 } else { | 531 } else { |
| 603 if (!WrapUp(cert, errors)) | 532 WrapUp(cert, cert_errors); |
| 604 return false; | |
| 605 } | 533 } |
| 606 } | 534 } |
| 607 | 535 |
| 608 // TODO(eroman): RFC 5280 forbids duplicate certificates per section 6.1: | 536 // TODO(eroman): RFC 5280 forbids duplicate certificates per section 6.1: |
| 609 // | 537 // |
| 610 // A certificate MUST NOT appear more than once in a prospective | 538 // A certificate MUST NOT appear more than once in a prospective |
| 611 // certification path. | 539 // certification path. |
| 540 } |
| 612 | 541 |
| 613 return true; | 542 } // namespace |
| 543 |
| 544 bool VerifyCertificateChain(const ParsedCertificateList& certs, |
| 545 const TrustAnchor* trust_anchor, |
| 546 const SignaturePolicy* signature_policy, |
| 547 const der::GeneralizedTime& time, |
| 548 CertPathErrors* errors) { |
| 549 // TODO(eroman): This function requires that |errors| is empty upon entry, |
| 550 // which is not part of the API contract. |
| 551 DCHECK(!errors->ContainsHighSeverityErrors()); |
| 552 VerifyCertificateChainNoReturnValue(certs, trust_anchor, signature_policy, |
| 553 time, errors); |
| 554 return !errors->ContainsHighSeverityErrors(); |
| 614 } | 555 } |
| 615 | 556 |
| 616 } // namespace net | 557 } // namespace net |
| OLD | NEW |