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

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

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

Powered by Google App Engine
This is Rietveld 408576698