@@ -163,6 +163,10 @@ const OID_CRL_REASONS :&[u64] = &[2, 5, 29, 21];
163
163
// https://www.rfc-editor.org/rfc/rfc5280#section-5.3.2
164
164
const OID_CRL_INVALIDITY_DATE : & [ u64 ] = & [ 2 , 5 , 29 , 24 ] ;
165
165
166
+ // id-ce-issuingDistributionPoint
167
+ // https://datatracker.ietf.org/doc/html/rfc5280#section-5.2.5
168
+ const OID_CRL_ISSUING_DISTRIBUTION_POINT : & [ u64 ] = & [ 2 , 5 , 29 , 28 ] ;
169
+
166
170
#[ cfg( feature = "pem" ) ]
167
171
const ENCODE_CONFIG : pem:: EncodeConfig = match cfg ! ( target_family = "windows" ) {
168
172
true => pem:: EncodeConfig { line_ending : pem:: LineEnding :: CRLF } ,
@@ -680,6 +684,7 @@ impl CertificateSigningRequest {
680
684
/// this_update: date_time_ymd(2023, 06, 17),
681
685
/// next_update: date_time_ymd(2024, 06, 17),
682
686
/// crl_number: SerialNumber::from(1234),
687
+ /// issuing_distribution_point: None,
683
688
/// revoked_certs: vec![revoked_cert],
684
689
/// alg: &PKCS_ECDSA_P256_SHA256,
685
690
/// key_identifier_method: KeyIdMethod::Sha256,
@@ -1247,7 +1252,10 @@ impl CertificateParams {
1247
1252
write_x509_extension ( writer. next ( ) , OID_CRL_DISTRIBUTION_POINTS , false , |writer| {
1248
1253
writer. write_sequence ( |writer| {
1249
1254
for distribution_point in & self . crl_distribution_points {
1250
- write_crl_distribution_point ( writer. next ( ) , distribution_point) ;
1255
+ // DistributionPoint SEQUENCE
1256
+ writer. next ( ) . write_sequence ( |writer| {
1257
+ write_crl_distribution_point_name ( writer. next ( ) , & distribution_point. uris ) ;
1258
+ } ) ;
1251
1259
}
1252
1260
} )
1253
1261
} ) ;
@@ -1404,7 +1412,8 @@ impl NameConstraints {
1404
1412
}
1405
1413
1406
1414
/// A certificate revocation list (CRL) distribution point, to be included in a certificate's
1407
- /// [distribution points extension](https://www.rfc-editor.org/rfc/rfc5280#section-4.2.1.13).
1415
+ /// [distribution points extension](https://www.rfc-editor.org/rfc/rfc5280#section-4.2.1.13),
1416
+ /// or a CRL's [issuing distribution point extension](https://datatracker.ietf.org/doc/html/rfc5280#section-5.2.5).
1408
1417
#[ derive( Debug , PartialEq , Eq , Clone ) ]
1409
1418
pub struct CrlDistributionPoint {
1410
1419
/// One or more URI distribution point names, indicating a place the current CRL can
@@ -1567,6 +1576,11 @@ pub struct CertificateRevocationListParams {
1567
1576
pub next_update : OffsetDateTime ,
1568
1577
/// A monotonically increasing sequence number for a given CRL scope and issuer.
1569
1578
pub crl_number : SerialNumber ,
1579
+ /// An optional CRL extension identifying the CRL distribution point and scope for a
1580
+ /// particular CRL as described in RFC 5280 Section 5.2.5[^1].
1581
+ ///
1582
+ /// [^1]: <https://datatracker.ietf.org/doc/html/rfc5280#section-5.2.5>
1583
+ pub issuing_distribution_point : Option < CrlIssuingDistributionPoint > ,
1570
1584
/// A list of zero or more parameters describing revoked certificates included in the CRL.
1571
1585
pub revoked_certs : Vec < RevokedCertParams > ,
1572
1586
/// Signature algorithm to use when signing the serialized CRL.
@@ -1664,6 +1678,13 @@ impl CertificateRevocationListParams {
1664
1678
write_x509_extension ( writer. next ( ) , OID_CRL_NUMBER , false , |writer| {
1665
1679
writer. write_bigint_bytes ( self . crl_number . as_ref ( ) , true ) ;
1666
1680
} ) ;
1681
+
1682
+ // Write issuing distribution point.
1683
+ if let Some ( issuing_distribution_point) = & self . issuing_distribution_point {
1684
+ write_x509_extension ( writer. next ( ) , OID_CRL_ISSUING_DISTRIBUTION_POINT , true , |writer| {
1685
+ issuing_distribution_point. write_der ( writer) ;
1686
+ } ) ;
1687
+ }
1667
1688
} ) ;
1668
1689
} ) ;
1669
1690
@@ -1672,6 +1693,54 @@ impl CertificateRevocationListParams {
1672
1693
}
1673
1694
}
1674
1695
1696
+ /// A certificate revocation list (CRL) issuing distribution point, to be included in a CRL's
1697
+ /// [issuing distribution point extension](https://datatracker.ietf.org/doc/html/rfc5280#section-5.2.5).
1698
+ pub struct CrlIssuingDistributionPoint {
1699
+ /// The CRL's distribution point, containing a sequence of URIs the CRL can be retrieved from.
1700
+ pub distribution_point : CrlDistributionPoint ,
1701
+ /// An optional description of the CRL's scope. If omitted, the CRL may contain
1702
+ /// both user certs and CA certs.
1703
+ pub scope : Option < CrlScope > ,
1704
+ }
1705
+
1706
+ impl CrlIssuingDistributionPoint {
1707
+ fn write_der ( & self , writer : DERWriter ) {
1708
+ // IssuingDistributionPoint SEQUENCE
1709
+ writer. write_sequence ( |writer| {
1710
+ // distributionPoint [0] DistributionPointName OPTIONAL
1711
+ write_crl_distribution_point_name ( writer. next ( ) , & self . distribution_point . uris ) ;
1712
+
1713
+ // -- at most one of onlyContainsUserCerts, onlyContainsCACerts,
1714
+ // -- and onlyContainsAttributeCerts may be set to TRUE.
1715
+ if let Some ( scope) = self . scope {
1716
+ match scope {
1717
+ // onlyContainsUserCerts [1] BOOLEAN DEFAULT FALSE,
1718
+ CrlScope :: UserCertsOnly => {
1719
+ writer. next ( ) . write_tagged_implicit ( Tag :: context ( 1 ) , |writer| {
1720
+ writer. write_bool ( true ) ;
1721
+ } ) ;
1722
+ }
1723
+ // onlyContainsCACerts [2] BOOLEAN DEFAULT FALSE,
1724
+ CrlScope :: CaCertsOnly => {
1725
+ writer. next ( ) . write_tagged_implicit ( Tag :: context ( 2 ) , |writer| {
1726
+ writer. write_bool ( true ) ;
1727
+ } ) ;
1728
+ }
1729
+ }
1730
+ }
1731
+ } ) ;
1732
+ }
1733
+ }
1734
+
1735
+ /// Describes the scope of a CRL for an issuing distribution point extension.
1736
+ #[ derive( Debug , Clone , Copy , Eq , PartialEq ) ]
1737
+ pub enum CrlScope {
1738
+ /// The CRL contains only end-entity user certificates.
1739
+ UserCertsOnly ,
1740
+ /// The CRL contains only CA certificates.
1741
+ CaCertsOnly ,
1742
+ }
1743
+
1675
1744
/// Parameters used for describing a revoked certificate included in a [`CertificateRevocationList`].
1676
1745
pub struct RevokedCertParams {
1677
1746
/// Serial number identifying the revoked certificate.
@@ -1828,24 +1897,21 @@ fn write_general_subtrees(writer :DERWriter, tag :u64, general_subtrees :&[Gener
1828
1897
} ) ;
1829
1898
}
1830
1899
1831
- fn write_crl_distribution_point ( writer : DERWriter , dp : & CrlDistributionPoint ) {
1832
- // DistributionPoint SEQUENCE
1833
- writer. write_sequence ( |writer| {
1834
- // distributionPoint DistributionPointName
1835
- writer. next ( ) . write_tagged_implicit ( Tag :: context ( 0 ) , |writer| {
1836
- writer. write_sequence ( |writer| {
1837
- // fullName GeneralNames
1838
- writer. next ( ) . write_tagged_implicit ( Tag :: context ( 0 ) , | writer| {
1839
- // GeneralNames
1840
- writer. write_sequence ( |writer| {
1841
- for uri in dp. uris . iter ( ) {
1842
- // uniformResourceIdentifier [6] IA5String,
1843
- writer. next ( ) . write_tagged_implicit ( Tag :: context ( 6 ) , |writer| {
1844
- writer. write_ia5_string ( uri)
1845
- } ) ;
1846
- }
1847
- } )
1848
- } ) ;
1900
+ fn write_crl_distribution_point_name < ' a > ( writer : DERWriter , uris : impl IntoIterator < Item = & ' a String > ) {
1901
+ // distributionPoint DistributionPointName
1902
+ writer. write_tagged_implicit ( Tag :: context ( 0 ) , |writer| {
1903
+ writer. write_sequence ( |writer| {
1904
+ // fullName GeneralNames
1905
+ writer. next ( ) . write_tagged_implicit ( Tag :: context ( 0 ) , | writer| {
1906
+ // GeneralNames
1907
+ writer. write_sequence ( |writer| {
1908
+ for uri in uris. into_iter ( ) {
1909
+ // uniformResourceIdentifier [6] IA5String,
1910
+ writer. next ( ) . write_tagged_implicit ( Tag :: context ( 6 ) , |writer| {
1911
+ writer. write_ia5_string ( uri)
1912
+ } ) ;
1913
+ }
1914
+ } )
1849
1915
} ) ;
1850
1916
} ) ;
1851
1917
} ) ;
0 commit comments