@@ -472,6 +472,17 @@ impl<'a, B: CryptoOps> Policy<'a, B> {
472
472
}
473
473
}
474
474
475
+ /// Checks whether the given "leaf" certificate is compatible with this policy.
476
+ ///
477
+ /// A "leaf" certificate is just the certificate in the leaf position during
478
+ /// path validation, whether it be a CA or EE. As such, `permits_leaf`
479
+ /// is logically equivalent to `permits_ee(leaf) || permits_ca(leaf)`.
480
+ pub ( crate ) fn permits_leaf ( & self , leaf : & Certificate ) -> Result < ( ) , PolicyError > {
481
+ // NOTE: Perform `permits_ee` first, since 99% of path validations should have
482
+ // an EE certificate in the leaf position.
483
+ self . permits_ee ( leaf) . or_else ( |_| self . permits_ca ( leaf) )
484
+ }
485
+
475
486
/// Checks whether the given CA certificate is compatible with this policy.
476
487
pub ( crate ) fn permits_ca ( & self , cert : & Certificate ) -> Result < ( ) , PolicyError > {
477
488
self . permits_basic ( cert) ?;
@@ -571,7 +582,20 @@ impl<'a, B: CryptoOps> Policy<'a, B> {
571
582
572
583
let extensions = cert. extensions ( ) ?;
573
584
574
- // 4.1.2.6 / 4.2.1.6: Subject / Subject Alternative Name
585
+ // 5280 4.2.1.3: Key Usage
586
+ // It isn't stated explicitly, but an EE is defined to be not a CA,
587
+ // so it MUST NOT assert keyCertSign.
588
+ if let Some ( key_usage) = extensions. get_extension ( & KEY_USAGE_OID ) {
589
+ let key_usage: KeyUsage = key_usage. value ( ) ?;
590
+
591
+ if key_usage. key_cert_sign ( ) {
592
+ return Err ( PolicyError :: Other (
593
+ "EE is marked as a CA certificate (keyUsage.keyCertSign)" ,
594
+ ) ) ;
595
+ }
596
+ }
597
+
598
+ // 5280 4.1.2.6 / 4.2.1.6: Subject / Subject Alternative Name
575
599
// EE certificates MAY have their subject in either the subject or subjectAltName.
576
600
// If the subject is empty, then the subjectAltName MUST be marked critical.
577
601
if cert. subject ( ) . is_empty ( ) {
@@ -595,6 +619,19 @@ impl<'a, B: CryptoOps> Policy<'a, B> {
595
619
// 5280 4.2.1.5: Policy Mappings
596
620
// The RFC is not clear on whether these may appear in EE certificates.
597
621
622
+ // 5280 4.2.1.9: Basic Constraints
623
+ // We refute `KeyUsage.keyCertSign` above, so `BasicConstraints.cA` MUST NOT
624
+ // be asserted.
625
+ if let Some ( basic_constraints) = extensions. get_extension ( & BASIC_CONSTRAINTS_OID ) {
626
+ let basic_constraints: BasicConstraints = basic_constraints. value ( ) ?;
627
+
628
+ if basic_constraints. ca {
629
+ return Err ( PolicyError :: Other (
630
+ "EE is marked as a CA certificate (basicConstraints.cA)" ,
631
+ ) ) ;
632
+ }
633
+ }
634
+
598
635
// 5280 4.2.1.10: Name Constraints
599
636
// NameConstraints MUST NOT appear in EE certificates.
600
637
0 commit comments