@@ -28,15 +28,15 @@ use crate::{public_values_eq, signed_data, subject_name};
28
28
29
29
// Use `'a` for lifetimes that we don't care about, `'p` for lifetimes that become a part of
30
30
// the `VerifiedPath`.
31
- pub ( crate ) struct ChainOptions < ' a , ' p > {
32
- pub ( crate ) eku : KeyUsage ,
31
+ pub ( crate ) struct ChainOptions < ' a , ' p , V > {
32
+ pub ( crate ) eku : V ,
33
33
pub ( crate ) supported_sig_algs : & ' a [ & ' a dyn SignatureVerificationAlgorithm ] ,
34
34
pub ( crate ) trust_anchors : & ' p [ TrustAnchor < ' p > ] ,
35
35
pub ( crate ) intermediate_certs : & ' p [ CertificateDer < ' p > ] ,
36
36
pub ( crate ) revocation : Option < RevocationOptions < ' a > > ,
37
37
}
38
38
39
- impl < ' a , ' p : ' a > ChainOptions < ' a , ' p > {
39
+ impl < ' a , ' p : ' a , V : ExtendedKeyUsageValidator > ChainOptions < ' a , ' p , V > {
40
40
pub ( crate ) fn build_chain (
41
41
& self ,
42
42
end_entity : & ' p EndEntityCert < ' p > ,
@@ -60,7 +60,7 @@ impl<'a, 'p: 'a> ChainOptions<'a, 'p> {
60
60
) -> Result < & ' p TrustAnchor < ' p > , ControlFlow < Error , Error > > {
61
61
let role = path. node ( ) . role ( ) ;
62
62
63
- check_issuer_independent_properties ( path. head ( ) , time, role, sub_ca_count, self . eku ) ?;
63
+ check_issuer_independent_properties ( path. head ( ) , time, role, sub_ca_count, & self . eku ) ?;
64
64
65
65
// TODO: HPKP checks.
66
66
@@ -349,7 +349,7 @@ fn check_issuer_independent_properties(
349
349
time : UnixTime ,
350
350
role : Role ,
351
351
sub_ca_count : usize ,
352
- eku : KeyUsage ,
352
+ eku : & impl ExtendedKeyUsageValidator ,
353
353
) -> Result < ( ) , Error > {
354
354
// TODO: check_distrust(trust_anchor_subject, trust_anchor_spki)?;
355
355
// TODO: Check signature algorithm like mozilla::pkix.
@@ -368,8 +368,8 @@ fn check_issuer_independent_properties(
368
368
check_basic_constraints ( value, role, sub_ca_count)
369
369
} ) ?;
370
370
untrusted:: read_all_optional ( cert. eku , Error :: BadDer , |value| match value {
371
- Some ( input) => eku. check ( KeyPurposeIdIter { input } ) ,
372
- None => eku. check ( KeyPurposeIdIter {
371
+ Some ( input) => eku. validate ( KeyPurposeIdIter { input } ) ,
372
+ None => eku. validate ( KeyPurposeIdIter {
373
373
input : & mut untrusted:: Reader :: new ( untrusted:: Input :: from ( & [ ] ) ) ,
374
374
} ) ,
375
375
} ) ?;
@@ -531,11 +531,27 @@ impl KeyUsage {
531
531
}
532
532
}
533
533
534
+ /// Yield the OID values of the required extended key usage.
535
+ pub fn oid_values ( & self ) -> impl Iterator < Item = usize > + ' _ {
536
+ OidDecoder :: new (
537
+ match & self . inner {
538
+ ExtendedKeyUsage :: Required ( eku) => eku,
539
+ ExtendedKeyUsage :: RequiredIfPresent ( eku) => eku,
540
+ }
541
+ . oid_value
542
+ . as_slice_less_safe ( ) ,
543
+ )
544
+ }
545
+
546
+ /// Human-readable representation of the server authentication OID.
547
+ pub const SERVER_AUTH_REPR : & [ usize ] = & [ 1 , 3 , 6 , 1 , 5 , 5 , 7 , 3 , 1 ] ;
548
+ /// Human-readable representation of the client authentication OID.
549
+ pub const CLIENT_AUTH_REPR : & [ usize ] = & [ 1 , 3 , 6 , 1 , 5 , 5 , 7 , 3 , 2 ] ;
550
+ }
551
+
552
+ impl ExtendedKeyUsageValidator for KeyUsage {
534
553
// https://tools.ietf.org/html/rfc5280#section-4.2.1.12
535
- fn check < ' a > (
536
- & self ,
537
- iter : impl Iterator < Item = Result < KeyPurposeId < ' a > , Error > > ,
538
- ) -> Result < ( ) , Error > {
554
+ fn validate ( & self , iter : KeyPurposeIdIter < ' _ , ' _ > ) -> Result < ( ) , Error > {
539
555
let mut empty = true ;
540
556
#[ cfg( feature = "alloc" ) ]
541
557
let mut present = Vec :: new ( ) ;
@@ -556,30 +572,30 @@ impl KeyUsage {
556
572
_ => Err ( Error :: RequiredEkuNotFoundContext (
557
573
RequiredEkuNotFoundContext {
558
574
#[ cfg( feature = "alloc" ) ]
559
- required : KeyUsage { inner : self . inner } ,
575
+ required : Self { inner : self . inner } ,
560
576
#[ cfg( feature = "alloc" ) ]
561
577
present,
562
578
} ,
563
579
) ) ,
564
580
}
565
581
}
582
+ }
566
583
567
- /// Yield the OID values of the required extended key usage.
568
- pub fn oid_values ( & self ) -> impl Iterator < Item = usize > + ' _ {
569
- OidDecoder :: new (
570
- match & self . inner {
571
- ExtendedKeyUsage :: Required ( eku) => eku,
572
- ExtendedKeyUsage :: RequiredIfPresent ( eku) => eku,
573
- }
574
- . oid_value
575
- . as_slice_less_safe ( ) ,
576
- )
584
+ impl < V : ExtendedKeyUsageValidator > ExtendedKeyUsageValidator for & V {
585
+ fn validate ( & self , iter : KeyPurposeIdIter < ' _ , ' _ > ) -> Result < ( ) , Error > {
586
+ ( * self ) . validate ( iter)
577
587
}
588
+ }
578
589
579
- /// Human-readable representation of the server authentication OID.
580
- pub const SERVER_AUTH_REPR : & [ usize ] = & [ 1 , 3 , 6 , 1 , 5 , 5 , 7 , 3 , 1 ] ;
581
- /// Human-readable representation of the client authentication OID.
582
- pub const CLIENT_AUTH_REPR : & [ usize ] = & [ 1 , 3 , 6 , 1 , 5 , 5 , 7 , 3 , 2 ] ;
590
+ /// A trait for validating the Extended Key Usage (EKU) extensions of a certificate.
591
+ pub trait ExtendedKeyUsageValidator {
592
+ /// Validate the EKU values in a certificate.
593
+ ///
594
+ /// `iter` yields the EKU OIDs in the certificate, or an error if the EKU extension
595
+ /// is malformed. `validate()` should yield `Ok(())` if the EKU values match the
596
+ /// required policy, or an `Error` if they do not. Ideally the `Error` should be
597
+ /// `Error::RequiredEkuNotFoundContext` if the policy is not met.
598
+ fn validate ( & self , iter : KeyPurposeIdIter < ' _ , ' _ > ) -> Result < ( ) , Error > ;
583
599
}
584
600
585
601
/// Extended Key Usage (EKU) of a certificate.
@@ -601,7 +617,7 @@ impl ExtendedKeyUsage {
601
617
}
602
618
}
603
619
604
- struct KeyPurposeIdIter < ' a , ' r > {
620
+ pub struct KeyPurposeIdIter < ' a , ' r > {
605
621
input : & ' r mut untrusted:: Reader < ' a > ,
606
622
}
607
623
@@ -625,15 +641,15 @@ impl Drop for KeyPurposeIdIter<'_, '_> {
625
641
626
642
/// An OID value indicating an Extended Key Usage (EKU) key purpose.
627
643
#[ derive( Clone , Copy ) ]
628
- struct KeyPurposeId < ' a > {
644
+ pub struct KeyPurposeId < ' a > {
629
645
oid_value : untrusted:: Input < ' a > ,
630
646
}
631
647
632
648
impl < ' a > KeyPurposeId < ' a > {
633
649
/// Construct a new [`KeyPurposeId`].
634
650
///
635
651
/// `oid` is the OBJECT IDENTIFIER in bytes.
636
- const fn new ( oid : & ' a [ u8 ] ) -> Self {
652
+ pub const fn new ( oid : & ' a [ u8 ] ) -> Self {
637
653
Self {
638
654
oid_value : untrusted:: Input :: from ( oid) ,
639
655
}
@@ -903,7 +919,7 @@ mod tests {
903
919
#[ test]
904
920
fn eku_fail_empty ( ) {
905
921
let err = KeyUsage :: required ( EKU_SERVER_AUTH )
906
- . check ( KeyPurposeIdIter {
922
+ . validate ( KeyPurposeIdIter {
907
923
input : & mut untrusted:: Reader :: new ( untrusted:: Input :: from ( & [ ] ) ) ,
908
924
} )
909
925
. unwrap_err ( ) ;
0 commit comments