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

Side by Side Diff: net/cert/internal/verify_certificate_chain.cc

Issue 2759023002: Improvements to the net/cert/internal error handling. (Closed)
Patch Set: fix comment Created 3 years, 9 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 unified diff | Download patch
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « net/cert/internal/verify_certificate_chain.h ('k') | net/cert/internal/verify_certificate_chain_pkits_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698