@@ -13,9 +13,13 @@ use spki::{
13
13
use crate :: {
14
14
AlgorithmIdentifier , SubjectPublicKeyInfo ,
15
15
certificate:: { Certificate , TbsCertificate , Version } ,
16
- ext:: { AsExtension , Extensions } ,
16
+ crl:: { CertificateList , RevokedCert , TbsCertList } ,
17
+ ext:: {
18
+ AsExtension , Extensions ,
19
+ pkix:: { AuthorityKeyIdentifier , CrlNumber , SubjectKeyIdentifier } ,
20
+ } ,
17
21
serial_number:: SerialNumber ,
18
- time:: Validity ,
22
+ time:: { Time , Validity } ,
19
23
} ;
20
24
21
25
pub mod profile;
@@ -410,3 +414,119 @@ where
410
414
<T as Builder >:: finalize ( self , signer)
411
415
}
412
416
}
417
+
418
+ /// X.509 CRL builder
419
+ pub struct CrlBuilder {
420
+ tbs : TbsCertList ,
421
+ }
422
+
423
+ impl CrlBuilder {
424
+ /// Create a `CrlBuilder` with the given issuer and the given monotonic [`CrlNumber`]
425
+ #[ cfg( feature = "std" ) ]
426
+ pub fn new ( issuer : & Certificate , crl_number : CrlNumber ) -> der:: Result < Self > {
427
+ let this_update = Time :: now ( ) ?;
428
+ Self :: new_with_this_update ( issuer, crl_number, this_update)
429
+ }
430
+
431
+ /// Create a `CrlBuilder` with the given issuer, a given monotonic [`CrlNumber`], and valid
432
+ /// from the given `this_update` start validity date.
433
+ pub fn new_with_this_update (
434
+ issuer : & Certificate ,
435
+ crl_number : CrlNumber ,
436
+ this_update : Time ,
437
+ ) -> der:: Result < Self > {
438
+ // Replaced later when the finalize is called
439
+ let signature_alg = AlgorithmIdentifier {
440
+ oid : NULL_OID ,
441
+ parameters : None ,
442
+ } ;
443
+
444
+ let issuer_name = issuer. tbs_certificate . subject ( ) . clone ( ) ;
445
+
446
+ let mut crl_extensions = Extensions :: new ( ) ;
447
+ crl_extensions. push ( crl_number. to_extension ( & issuer_name, & crl_extensions) ?) ;
448
+ let aki = match issuer
449
+ . tbs_certificate
450
+ . get_extension :: < AuthorityKeyIdentifier > ( ) ?
451
+ {
452
+ Some ( ( _, aki) ) => aki,
453
+ None => {
454
+ let ski = SubjectKeyIdentifier :: try_from (
455
+ issuer
456
+ . tbs_certificate
457
+ . subject_public_key_info ( )
458
+ . owned_to_ref ( ) ,
459
+ ) ?;
460
+ AuthorityKeyIdentifier {
461
+ // KeyIdentifier must be the same as subjectKeyIdentifier
462
+ key_identifier : Some ( ski. 0 . clone ( ) ) ,
463
+ // other fields must not be present.
464
+ ..Default :: default ( )
465
+ }
466
+ }
467
+ } ;
468
+ crl_extensions. push ( aki. to_extension ( & issuer_name, & crl_extensions) ?) ;
469
+
470
+ let tbs = TbsCertList {
471
+ version : Version :: V2 ,
472
+ signature : signature_alg,
473
+ issuer : issuer_name,
474
+ this_update,
475
+ next_update : None ,
476
+ revoked_certificates : None ,
477
+ crl_extensions : Some ( crl_extensions) ,
478
+ } ;
479
+
480
+ Ok ( Self { tbs } )
481
+ }
482
+
483
+ /// Make the CRL valid until the given `next_update`
484
+ pub fn with_next_update ( mut self , next_update : Option < Time > ) -> Self {
485
+ self . tbs . next_update = next_update;
486
+ self
487
+ }
488
+
489
+ /// Add certificates to the revocation list
490
+ pub fn with_certificates < I > ( mut self , revoked : I ) -> Self
491
+ where
492
+ I : Iterator < Item = RevokedCert > ,
493
+ {
494
+ let certificates = self
495
+ . tbs
496
+ . revoked_certificates
497
+ . get_or_insert_with ( vec:: Vec :: new) ;
498
+
499
+ let mut revoked: vec:: Vec < RevokedCert > = revoked. collect ( ) ;
500
+ certificates. append ( & mut revoked) ;
501
+
502
+ self
503
+ }
504
+ }
505
+
506
+ impl Builder for CrlBuilder {
507
+ type Output = CertificateList ;
508
+
509
+ fn finalize < S > ( & mut self , cert_signer : & S ) -> Result < vec:: Vec < u8 > >
510
+ where
511
+ S : Keypair + DynSignatureAlgorithmIdentifier ,
512
+ S :: VerifyingKey : EncodePublicKey ,
513
+ {
514
+ self . tbs . signature = cert_signer. signature_algorithm_identifier ( ) ?;
515
+
516
+ self . tbs . to_der ( ) . map_err ( Error :: from)
517
+ }
518
+
519
+ fn assemble < S > ( self , signature : BitString , _signer : & S ) -> Result < Self :: Output >
520
+ where
521
+ S : Keypair + DynSignatureAlgorithmIdentifier ,
522
+ S :: VerifyingKey : EncodePublicKey ,
523
+ {
524
+ let signature_algorithm = self . tbs . signature . clone ( ) ;
525
+
526
+ Ok ( CertificateList {
527
+ tbs_cert_list : self . tbs ,
528
+ signature_algorithm,
529
+ signature,
530
+ } )
531
+ }
532
+ }
0 commit comments