@@ -26,9 +26,9 @@ use rcgen::{
2626#[ cfg( feature = "alloc" ) ]
2727use webpki:: OwnedCertRevocationList ;
2828use webpki:: {
29- BorrowedCertRevocationList , CertRevocationList , ExtendedKeyUsage , PathBuilder ,
30- RevocationCheckDepth , RevocationOptions , RevocationOptionsBuilder , UnknownStatusPolicy ,
31- anchor_from_trusted_cert,
29+ BorrowedCertRevocationList , CertRevocationList , ExpirationPolicy , ExtendedKeyUsage ,
30+ PathBuilder , RevocationCheckDepth , RevocationOptions , RevocationOptionsBuilder ,
31+ UnknownStatusPolicy , anchor_from_trusted_cert,
3232} ;
3333use x509_parser:: oid_registry;
3434
@@ -990,7 +990,7 @@ fn ee_revoked_expired_crl() {
990990 . unwrap ( )
991991 . with_depth ( RevocationCheckDepth :: EndEntity )
992992 . with_status_policy ( UnknownStatusPolicy :: Allow )
993- . with_expiration_policy ( webpki :: ExpirationPolicy :: Enforce )
993+ . with_expiration_policy ( ExpirationPolicy :: Enforce )
994994 . build ( ) ;
995995
996996 assert ! ( matches!(
@@ -1004,6 +1004,180 @@ fn ee_revoked_expired_crl() {
10041004 ) ) ;
10051005}
10061006
1007+ #[ test]
1008+ fn expired_crl_does_not_shadow_current_crl_when_enforcing_expiration ( ) {
1009+ let chain = CertChain :: no_key_usages ( "expired_first_enforce" ) ;
1010+ let expired_not_revoked = chain. int_a . generate_crl_with_updates_and_number (
1011+ SerialNumber :: from ( 0xFFFF ) ,
1012+ None ,
1013+ 0x1FED_F00D - 120 ,
1014+ 0x1FED_F00D - 60 ,
1015+ 1 ,
1016+ ) ;
1017+ let current_not_revoked = chain. int_a . generate_crl_with_updates_and_number (
1018+ SerialNumber :: from ( 0xFFFF ) ,
1019+ None ,
1020+ 0x1FED_F00D - 60 ,
1021+ 0x1FED_F00D + 60 ,
1022+ 2 ,
1023+ ) ;
1024+
1025+ let expired_not_revoked = CertRevocationList :: Borrowed (
1026+ BorrowedCertRevocationList :: from_der ( & expired_not_revoked) . unwrap ( ) ,
1027+ ) ;
1028+ let current_not_revoked = CertRevocationList :: Borrowed (
1029+ BorrowedCertRevocationList :: from_der ( & current_not_revoked) . unwrap ( ) ,
1030+ ) ;
1031+ let crls = & [ & expired_not_revoked, & current_not_revoked] ;
1032+
1033+ let revocation = RevocationOptionsBuilder :: new ( crls)
1034+ . unwrap ( )
1035+ . with_depth ( RevocationCheckDepth :: EndEntity )
1036+ . with_status_policy ( UnknownStatusPolicy :: Allow )
1037+ . with_expiration_policy ( ExpirationPolicy :: Enforce )
1038+ . build ( ) ;
1039+
1040+ assert_eq ! (
1041+ check_cert(
1042+ chain. ee_cert. der( ) ,
1043+ & chain. intermediates( ) ,
1044+ chain. root. der( ) ,
1045+ Some ( revocation) ,
1046+ ) ,
1047+ Ok ( ( ) )
1048+ ) ;
1049+ }
1050+
1051+ #[ test]
1052+ fn expired_crl_does_not_shadow_newer_revocation_when_ignoring_expiration ( ) {
1053+ let chain = CertChain :: no_key_usages ( "expired_first_ignore" ) ;
1054+ let expired_not_revoked = chain. int_a . generate_crl_with_updates_and_number (
1055+ SerialNumber :: from ( 0xFFFF ) ,
1056+ None ,
1057+ 0x1FED_F00D - 120 ,
1058+ 0x1FED_F00D - 60 ,
1059+ 1 ,
1060+ ) ;
1061+ let current_revoked = chain. int_a . generate_crl_with_updates_and_number (
1062+ chain. ee_serial . clone ( ) ,
1063+ None ,
1064+ 0x1FED_F00D - 60 ,
1065+ 0x1FED_F00D + 60 ,
1066+ 2 ,
1067+ ) ;
1068+
1069+ let expired_not_revoked = CertRevocationList :: Borrowed (
1070+ BorrowedCertRevocationList :: from_der ( & expired_not_revoked) . unwrap ( ) ,
1071+ ) ;
1072+ let current_revoked = CertRevocationList :: Borrowed (
1073+ BorrowedCertRevocationList :: from_der ( & current_revoked) . unwrap ( ) ,
1074+ ) ;
1075+ let crls = & [ & expired_not_revoked, & current_revoked] ;
1076+
1077+ let revocation = RevocationOptionsBuilder :: new ( crls)
1078+ . unwrap ( )
1079+ . with_depth ( RevocationCheckDepth :: EndEntity )
1080+ . with_status_policy ( UnknownStatusPolicy :: Allow )
1081+ . with_expiration_policy ( ExpirationPolicy :: Ignore )
1082+ . build ( ) ;
1083+
1084+ assert_eq ! (
1085+ check_cert(
1086+ chain. ee_cert. der( ) ,
1087+ & chain. intermediates( ) ,
1088+ chain. root. der( ) ,
1089+ Some ( revocation) ,
1090+ ) ,
1091+ Err ( webpki:: Error :: CertRevoked )
1092+ ) ;
1093+ }
1094+
1095+ #[ test]
1096+ fn crl_number_in_other_partition_does_not_shadow_revoked_partition ( ) {
1097+ let chain = CertChain :: with_crl_dps ( "partitioned_crl_order" , vec ! [ MATCHING_URI . to_string( ) ] ) ;
1098+ let other_partition_not_revoked = chain. int_a . generate_crl_with_updates_and_number (
1099+ SerialNumber :: from ( 0xFFFF ) ,
1100+ Some ( idp ( NON_MATCHING_URI ) ) ,
1101+ NOT_BEFORE_SECS ,
1102+ NOT_AFTER_SECS ,
1103+ 100 ,
1104+ ) ;
1105+ let revoked_partition = chain. int_a . generate_crl_with_updates_and_number (
1106+ chain. ee_serial . clone ( ) ,
1107+ Some ( idp ( MATCHING_URI ) ) ,
1108+ NOT_BEFORE_SECS ,
1109+ NOT_AFTER_SECS ,
1110+ 1 ,
1111+ ) ;
1112+
1113+ let other_partition_not_revoked = CertRevocationList :: Borrowed (
1114+ BorrowedCertRevocationList :: from_der ( & other_partition_not_revoked) . unwrap ( ) ,
1115+ ) ;
1116+ let revoked_partition = CertRevocationList :: Borrowed (
1117+ BorrowedCertRevocationList :: from_der ( & revoked_partition) . unwrap ( ) ,
1118+ ) ;
1119+ let crls = & [ & other_partition_not_revoked, & revoked_partition] ;
1120+
1121+ let revocation = RevocationOptionsBuilder :: new ( crls)
1122+ . unwrap ( )
1123+ . with_depth ( RevocationCheckDepth :: EndEntity )
1124+ . with_status_policy ( UnknownStatusPolicy :: Allow )
1125+ . build ( ) ;
1126+
1127+ assert_eq ! (
1128+ check_cert(
1129+ chain. ee_cert. der( ) ,
1130+ & chain. intermediates( ) ,
1131+ chain. root. der( ) ,
1132+ Some ( revocation) ,
1133+ ) ,
1134+ Err ( webpki:: Error :: CertRevoked )
1135+ ) ;
1136+ }
1137+
1138+ #[ test]
1139+ fn crl_number_order_uses_integer_value_not_lexicographic_bytes ( ) {
1140+ let chain = CertChain :: no_key_usages ( "crl_number_order" ) ;
1141+ let crl_255_not_revoked = chain. int_a . generate_crl_with_updates_and_number (
1142+ SerialNumber :: from ( 0xFFFF ) ,
1143+ None ,
1144+ NOT_BEFORE_SECS ,
1145+ NOT_AFTER_SECS ,
1146+ 0xFF ,
1147+ ) ;
1148+ let crl_256_revoked = chain. int_a . generate_crl_with_updates_and_number (
1149+ chain. ee_serial . clone ( ) ,
1150+ None ,
1151+ NOT_BEFORE_SECS ,
1152+ NOT_AFTER_SECS ,
1153+ 0x0100 ,
1154+ ) ;
1155+
1156+ let crl_255_not_revoked = CertRevocationList :: Borrowed (
1157+ BorrowedCertRevocationList :: from_der ( & crl_255_not_revoked) . unwrap ( ) ,
1158+ ) ;
1159+ let crl_256_revoked = CertRevocationList :: Borrowed (
1160+ BorrowedCertRevocationList :: from_der ( & crl_256_revoked) . unwrap ( ) ,
1161+ ) ;
1162+ let crls = & [ & crl_255_not_revoked, & crl_256_revoked] ;
1163+
1164+ let revocation = RevocationOptionsBuilder :: new ( crls)
1165+ . unwrap ( )
1166+ . with_depth ( RevocationCheckDepth :: EndEntity )
1167+ . with_status_policy ( UnknownStatusPolicy :: Allow )
1168+ . build ( ) ;
1169+
1170+ assert_eq ! (
1171+ check_cert(
1172+ chain. ee_cert. der( ) ,
1173+ & chain. intermediates( ) ,
1174+ chain. root. der( ) ,
1175+ Some ( revocation) ,
1176+ ) ,
1177+ Err ( webpki:: Error :: CertRevoked )
1178+ ) ;
1179+ }
1180+
10071181// Cert has two normal DPs; first doesn't match IDP, second does.
10081182// Proves the outer cert_dp loop continues to the next DP when URIs don't match.
10091183#[ test]
@@ -1312,6 +1486,26 @@ impl Intermediate {
13121486 . into ( )
13131487 }
13141488
1489+ fn generate_crl_with_updates_and_number (
1490+ & self ,
1491+ serial : SerialNumber ,
1492+ issuing_dp : Option < CrlIssuingDistributionPoint > ,
1493+ this_update_secs : u64 ,
1494+ next_update_secs : u64 ,
1495+ crl_number : u64 ,
1496+ ) -> CertificateRevocationListDer < ' static > {
1497+ crl_params_with_updates_and_number (
1498+ serial,
1499+ issuing_dp,
1500+ this_update_secs,
1501+ next_update_secs,
1502+ crl_number,
1503+ )
1504+ . signed_by ( & self . issuer )
1505+ . unwrap ( )
1506+ . into ( )
1507+ }
1508+
13151509 fn generate_crl_with_crl_sign (
13161510 & self ,
13171511 serial : SerialNumber ,
@@ -1336,12 +1530,27 @@ fn crl_params(
13361530 serial_number : SerialNumber ,
13371531 issuing_distribution_point : Option < CrlIssuingDistributionPoint > ,
13381532 not_after_secs : Option < u64 > ,
1533+ ) -> CertificateRevocationListParams {
1534+ crl_params_with_updates_and_number (
1535+ serial_number,
1536+ issuing_distribution_point,
1537+ NOT_BEFORE_SECS ,
1538+ not_after_secs. unwrap_or ( NOT_AFTER_SECS ) ,
1539+ 1234 ,
1540+ )
1541+ }
1542+
1543+ fn crl_params_with_updates_and_number (
1544+ serial_number : SerialNumber ,
1545+ issuing_distribution_point : Option < CrlIssuingDistributionPoint > ,
1546+ this_update_secs : u64 ,
1547+ next_update_secs : u64 ,
1548+ crl_number : u64 ,
13391549) -> CertificateRevocationListParams {
13401550 CertificateRevocationListParams {
1341- this_update : date_time_ymd ( 1970 , 1 , 1 ) + Duration :: from_secs ( NOT_BEFORE_SECS ) ,
1342- next_update : date_time_ymd ( 1970 , 1 , 1 )
1343- + Duration :: from_secs ( not_after_secs. unwrap_or ( NOT_AFTER_SECS ) ) ,
1344- crl_number : SerialNumber :: from ( 1234 ) ,
1551+ this_update : date_time_ymd ( 1970 , 1 , 1 ) + Duration :: from_secs ( this_update_secs) ,
1552+ next_update : date_time_ymd ( 1970 , 1 , 1 ) + Duration :: from_secs ( next_update_secs) ,
1553+ crl_number : SerialNumber :: from ( crl_number) ,
13451554 issuing_distribution_point,
13461555 key_identifier_method : KeyIdMethod :: Sha256 ,
13471556 revoked_certs : vec ! [ RevokedCertParams {
@@ -1516,9 +1725,13 @@ fn build_crl_dps_extension(dps: &[Vec<u8>]) -> Vec<u8> {
15161725}
15171726
15181727fn matching_idp ( ) -> CrlIssuingDistributionPoint {
1728+ idp ( MATCHING_URI )
1729+ }
1730+
1731+ fn idp ( uri : & str ) -> CrlIssuingDistributionPoint {
15191732 CrlIssuingDistributionPoint {
15201733 distribution_point : CrlDistributionPoint {
1521- uris : vec ! [ MATCHING_URI . to_string( ) ] ,
1734+ uris : vec ! [ uri . to_string( ) ] ,
15221735 } ,
15231736 scope : None ,
15241737 }
0 commit comments