@@ -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 : KeyUsageValidator > 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 KeyUsageValidator ,
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,8 +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 KeyUsageValidator for KeyUsage {
534
553
// https://tools.ietf.org/html/rfc5280#section-4.2.1.12
535
- fn check < ' a > (
554
+ fn validate < ' a > (
536
555
& self ,
537
556
iter : impl Iterator < Item = Result < KeyPurposeId < ' a > , Error > > ,
538
557
) -> Result < ( ) , Error > {
@@ -563,23 +582,29 @@ impl KeyUsage {
563
582
) ) ,
564
583
}
565
584
}
585
+ }
566
586
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
- )
587
+ impl < V : KeyUsageValidator > KeyUsageValidator for & V {
588
+ fn validate < ' a > (
589
+ & self ,
590
+ iter : impl Iterator < Item = Result < KeyPurposeId < ' a > , Error > > ,
591
+ ) -> Result < ( ) , Error > {
592
+ ( * self ) . validate ( iter)
577
593
}
594
+ }
578
595
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 ] ;
596
+ /// A trait for validating the Extended Key Usage (EKU) extensions of a certificate.
597
+ pub trait KeyUsageValidator {
598
+ /// Validate the EKU values in a certificate.
599
+ ///
600
+ /// `iter` yields the EKU OIDs in the certificate, or an error if the EKU extension
601
+ /// is malformed. `validate()` should yield `Ok(())` if the EKU values match the
602
+ /// required policy, or an `Error` if they do not. Ideally the `Error` should be
603
+ /// `Error::RequiredEkuNotFoundContext` if the policy is not met.
604
+ fn validate < ' a > (
605
+ & self ,
606
+ iter : impl Iterator < Item = Result < KeyPurposeId < ' a > , Error > > ,
607
+ ) -> Result < ( ) , Error > ;
583
608
}
584
609
585
610
/// Extended Key Usage (EKU) of a certificate.
@@ -625,15 +650,15 @@ impl Drop for KeyPurposeIdIter<'_, '_> {
625
650
626
651
/// An OID value indicating an Extended Key Usage (EKU) key purpose.
627
652
#[ derive( Clone , Copy ) ]
628
- struct KeyPurposeId < ' a > {
653
+ pub struct KeyPurposeId < ' a > {
629
654
oid_value : untrusted:: Input < ' a > ,
630
655
}
631
656
632
657
impl < ' a > KeyPurposeId < ' a > {
633
658
/// Construct a new [`KeyPurposeId`].
634
659
///
635
660
/// `oid` is the OBJECT IDENTIFIER in bytes.
636
- const fn new ( oid : & ' a [ u8 ] ) -> Self {
661
+ pub const fn new ( oid : & ' a [ u8 ] ) -> Self {
637
662
Self {
638
663
oid_value : untrusted:: Input :: from ( oid) ,
639
664
}
@@ -902,7 +927,7 @@ mod tests {
902
927
#[ test]
903
928
fn eku_fail_empty ( ) {
904
929
let err = KeyUsage :: required ( EKU_SERVER_AUTH )
905
- . check ( KeyPurposeIdIter {
930
+ . validate ( KeyPurposeIdIter {
906
931
input : & mut untrusted:: Reader :: new ( untrusted:: Input :: from ( & [ ] ) ) ,
907
932
} )
908
933
. unwrap_err ( ) ;
0 commit comments