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

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

Issue 2245643004: Support trust anchor constraints, by specifying them as a certificate. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: update gypi Created 4 years, 4 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/name_constraints.h" 10 #include "net/cert/internal/name_constraints.h"
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
159 } 159 }
160 160
161 // This function corresponds to RFC 5280 section 6.1.4's "Preparation for 161 // 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. 162 // Certificate i+1" procedure. |cert| is expected to be an intermediate.
163 WARN_UNUSED_RESULT bool PrepareForNextCertificate( 163 WARN_UNUSED_RESULT bool PrepareForNextCertificate(
164 const ParsedCertificate& cert, 164 const ParsedCertificate& cert,
165 size_t* max_path_length_ptr, 165 size_t* max_path_length_ptr,
166 der::Input* working_spki, 166 der::Input* working_spki,
167 der::Input* working_normalized_issuer_name, 167 der::Input* working_normalized_issuer_name,
168 std::vector<const NameConstraints*>* name_constraints_list) { 168 std::vector<const NameConstraints*>* name_constraints_list) {
169 // TODO(eroman): Steps a-b are omitted, as policy constraints are not yet 169 // TODO(crbug.com/634456): Steps a-b are omitted, as policy mappings are not
170 // implemented. 170 // yet implemented.
171 171
172 // From RFC 5280 section 6.1.4 step c: 172 // From RFC 5280 section 6.1.4 step c:
173 // 173 //
174 // Assign the certificate subject name to working_normalized_issuer_name. 174 // Assign the certificate subject name to working_normalized_issuer_name.
175 *working_normalized_issuer_name = cert.normalized_subject(); 175 *working_normalized_issuer_name = cert.normalized_subject();
176 176
177 // From RFC 5280 section 6.1.4 step d: 177 // From RFC 5280 section 6.1.4 step d:
178 // 178 //
179 // Assign the certificate subjectPublicKey to working_public_key. 179 // Assign the certificate subjectPublicKey to working_public_key.
180 *working_spki = cert.tbs().spki_tlv; 180 *working_spki = cert.tbs().spki_tlv;
181 181
182 // Note that steps e and f are omitted as they are handled by 182 // Note that steps e and f are omitted as they are handled by
183 // the assignment to |working_spki| above. See the definition 183 // the assignment to |working_spki| above. See the definition
184 // of |working_spki|. 184 // of |working_spki|.
185 185
186 // From RFC 5280 section 6.1.4 step g: 186 // From RFC 5280 section 6.1.4 step g:
187 if (cert.has_name_constraints()) 187 if (cert.has_name_constraints())
188 name_constraints_list->push_back(&cert.name_constraints()); 188 name_constraints_list->push_back(&cert.name_constraints());
189 189
190 // TODO(eroman): Steps h-j are omitted as policy constraints are not yet 190 // TODO(eroman): Steps h-j are omitted as policy
191 // implemented. 191 // constraints/mappings/inhibitAnyPolicy are not yet implemented.
192 192
193 // From RFC 5280 section 6.1.4 step k: 193 // From RFC 5280 section 6.1.4 step k:
194 // 194 //
195 // If certificate i is a version 3 certificate, verify that the 195 // If certificate i is a version 3 certificate, verify that the
196 // basicConstraints extension is present and that cA is set to 196 // basicConstraints extension is present and that cA is set to
197 // TRUE. (If certificate i is a version 1 or version 2 197 // TRUE. (If certificate i is a version 1 or version 2
198 // certificate, then the application MUST either verify that 198 // certificate, then the application MUST either verify that
199 // certificate i is a CA certificate through out-of-band means 199 // certificate i is a CA certificate through out-of-band means
200 // or reject the certificate. Conforming implementations may 200 // or reject the certificate. Conforming implementations may
201 // choose to reject all version 1 and version 2 intermediate 201 // choose to reject all version 1 and version 2 intermediate
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
287 (!cert.has_key_usage() || 287 (!cert.has_key_usage() ||
288 cert.key_usage().AssertsBit(KEY_USAGE_BIT_KEY_CERT_SIGN)); 288 cert.key_usage().AssertsBit(KEY_USAGE_BIT_KEY_CERT_SIGN));
289 } 289 }
290 290
291 return true; 291 return true;
292 } 292 }
293 293
294 // This function corresponds with RFC 5280 section 6.1.5's "Wrap-Up Procedure". 294 // 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). 295 // It does processing for the final certificate (the target cert).
296 WARN_UNUSED_RESULT bool WrapUp(const ParsedCertificate& cert) { 296 WARN_UNUSED_RESULT bool WrapUp(const ParsedCertificate& cert) {
297 // TODO(eroman): Steps a-b are omitted as policy constraints are not yet 297 // TODO(crbug.com/634452): Steps a-b are omitted as policy constraints are not
298 // implemented. 298 // yet implemented.
299 299
300 // Note step c-e are omitted the verification function does 300 // Note step c-e are omitted the verification function does
301 // not output the working public key. 301 // not output the working public key.
302 302
303 // From RFC 5280 section 6.1.5 step f: 303 // From RFC 5280 section 6.1.5 step f:
304 // 304 //
305 // Recognize and process any other critical extension present in 305 // Recognize and process any other critical extension present in
306 // the certificate n. Process any other recognized non-critical 306 // the certificate n. Process any other recognized non-critical
307 // extension present in certificate n that is relevant to path 307 // extension present in certificate n that is relevant to path
308 // processing. 308 // processing.
309 // 309 //
310 // Note that this is duplicated by PrepareForNextCertificate() so as to 310 // Note that this is duplicated by PrepareForNextCertificate() so as to
311 // directly match the procedures in RFC 5280's section 6.1. 311 // directly match the procedures in RFC 5280's section 6.1.
312 if (!VerifyNoUnconsumedCriticalExtensions(cert)) 312 if (!VerifyNoUnconsumedCriticalExtensions(cert))
313 return false; 313 return false;
314 314
315 // TODO(eroman): Step g is omitted, as policy constraints are not yet 315 // TODO(eroman): Step g is omitted, as policy constraints are not yet
316 // implemented. 316 // implemented.
317 317
318 // The following check is NOT part of RFC 5280 6.1.5's "Wrap-Up Procedure", 318 // 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. 319 // however is implied by RFC 5280 section 4.2.1.9.
320 if (!VerifyTargetCertHasConsistentCaBits(cert)) 320 if (!VerifyTargetCertHasConsistentCaBits(cert))
321 return false; 321 return false;
322 322
323 return true; 323 return true;
324 } 324 }
325 325
326 // Initializes the path validation algorithm given anchor constraints. This
327 // follows the description in RFC 5937
328 WARN_UNUSED_RESULT bool ProcessTrustAnchorConstraints(
329 const TrustAnchor& trust_anchor,
330 size_t* max_path_length_ptr,
331 std::vector<const NameConstraints*>* name_constraints_list) {
332 // In RFC 5937 the enforcement of anchor constraints is governed by the input
333 // enforceTrustAnchorConstraints to path validation. In our implementation
334 // this is always on, and enforcement is controlled solely by whether or not
335 // the trust anchor specified constraints.
336 if (!trust_anchor.enforces_constraints())
337 return true;
338
339 // Anchor constraints are encoded via the attached certificate.
340 const ParsedCertificate& cert = *trust_anchor.cert();
341
342 // The following enforcements follow from RFC 5937 (primarily section 3.2):
343
344 // Initialize name constraints initial-permitted/excluded-subtrees.
345 if (cert.has_name_constraints())
346 name_constraints_list->push_back(&cert.name_constraints());
347
348 // TODO(eroman): Initialize user-initial-policy-set based on anchor
349 // constraints.
350
351 // TODO(eroman): Initialize inhibit any policy based on anchor constraints.
352
353 // TODO(eroman): Initialize require explicit policy based on anchor
354 // constraints.
355
356 // TODO(eroman): Initialize inhibit policy mapping based on anchor
357 // constraints.
358
359 // From RFC 5937 section 3.2:
360 //
361 // If a basic constraints extension is associated with the trust
362 // anchor and contains a pathLenConstraint value, set the
363 // max_path_length state variable equal to the pathLenConstraint
364 // value from the basic constraints extension.
365 //
366 // NOTE: RFC 5937 does not say to enforce the CA=true part of basic
367 // constraints.
368 if (cert.has_basic_constraints() && cert.basic_constraints().has_path_len)
369 *max_path_length_ptr = cert.basic_constraints().path_len;
370
371 // From RFC 5937 section 2:
372 //
373 // Extensions may be marked critical or not critical. When trust anchor
374 // constraints are enforced, clients MUST reject certification paths
375 // containing a trust anchor with unrecognized critical extensions.
376 if (!VerifyNoUnconsumedCriticalExtensions(cert))
377 return false;
378
379 return true;
380 }
381
326 } // namespace 382 } // namespace
327 383
328 // This implementation is structured to mimic the description of certificate 384 // This implementation is structured to mimic the description of certificate
329 // path verification given by RFC 5280 section 6.1. 385 // path verification given by RFC 5280 section 6.1.
330 bool VerifyCertificateChain(const ParsedCertificateList& certs, 386 bool VerifyCertificateChain(const ParsedCertificateList& certs,
331 const TrustAnchor* trust_anchor, 387 const TrustAnchor* trust_anchor,
332 const SignaturePolicy* signature_policy, 388 const SignaturePolicy* signature_policy,
333 const der::GeneralizedTime& time) { 389 const der::GeneralizedTime& time) {
334 // An empty chain is necessarily invalid. 390 // An empty chain is necessarily invalid.
335 if (certs.empty()) 391 if (certs.empty())
336 return false; 392 return false;
337 393
338 // TODO(crbug.com/635200): Support anchor constraints.
339
340 // Will contain a NameConstraints for each previous cert in the chain which 394 // Will contain a NameConstraints for each previous cert in the chain which
341 // had nameConstraints. This corresponds to the permitted_subtrees and 395 // had nameConstraints. This corresponds to the permitted_subtrees and
342 // excluded_subtrees state variables from RFC 5280. 396 // excluded_subtrees state variables from RFC 5280.
343 std::vector<const NameConstraints*> name_constraints_list; 397 std::vector<const NameConstraints*> name_constraints_list;
344 398
345 // |working_spki| is an amalgamation of 3 separate variables from RFC 5280: 399 // |working_spki| is an amalgamation of 3 separate variables from RFC 5280:
346 // * working_public_key 400 // * working_public_key
347 // * working_public_key_algorithm 401 // * working_public_key_algorithm
348 // * working_public_key_parameters 402 // * working_public_key_parameters
349 // 403 //
(...skipping 19 matching lines...) Expand all
369 // |max_path_length| corresponds with the same named variable in RFC 5280 423 // |max_path_length| corresponds with the same named variable in RFC 5280
370 // section 6.1.2: 424 // section 6.1.2:
371 // 425 //
372 // max_path_length: this integer is initialized to n, is 426 // max_path_length: this integer is initialized to n, is
373 // decremented for each non-self-issued certificate in the path, 427 // decremented for each non-self-issued certificate in the path,
374 // and may be reduced to the value in the path length constraint 428 // and may be reduced to the value in the path length constraint
375 // field within the basic constraints extension of a CA 429 // field within the basic constraints extension of a CA
376 // certificate. 430 // certificate.
377 size_t max_path_length = certs.size(); 431 size_t max_path_length = certs.size();
378 432
433 // Apply any trust anchor constraints per RFC 5937.
434 if (!ProcessTrustAnchorConstraints(*trust_anchor, &max_path_length,
435 &name_constraints_list)) {
436 return false;
437 }
438
379 // Iterate over all the certificates in the reverse direction: starting from 439 // Iterate over all the certificates in the reverse direction: starting from
380 // the certificate signed by trust anchor and progressing towards the target 440 // the certificate signed by trust anchor and progressing towards the target
381 // certificate. 441 // certificate.
382 // 442 //
383 // Note that |i| uses 0-based indexing whereas in RFC 5280 it is 1-based. 443 // Note that |i| uses 0-based indexing whereas in RFC 5280 it is 1-based.
384 // 444 //
385 // * i=0 : Certificated signed by trust anchor. 445 // * i=0 : Certificated signed by trust anchor.
386 // * i=N-1 : Target certificate. 446 // * i=N-1 : Target certificate.
387 for (size_t i = 0; i < certs.size(); ++i) { 447 for (size_t i = 0; i < certs.size(); ++i) {
388 const size_t index_into_certs = certs.size() - i - 1; 448 const size_t index_into_certs = certs.size() - i - 1;
(...skipping 29 matching lines...) Expand all
418 478
419 // TODO(eroman): RFC 5280 forbids duplicate certificates per section 6.1: 479 // TODO(eroman): RFC 5280 forbids duplicate certificates per section 6.1:
420 // 480 //
421 // A certificate MUST NOT appear more than once in a prospective 481 // A certificate MUST NOT appear more than once in a prospective
422 // certification path. 482 // certification path.
423 483
424 return true; 484 return true;
425 } 485 }
426 486
427 } // namespace net 487 } // namespace net
OLDNEW
« no previous file with comments | « net/cert/internal/trust_store.cc ('k') | net/cert/internal/verify_certificate_chain_typed_unittest.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698