@@ -533,6 +533,25 @@ impl CertificateParams {
533
533
pub fn serialize_request (
534
534
& self ,
535
535
subject_key : & KeyPair ,
536
+ ) -> Result < CertificateSigningRequest , Error > {
537
+ self . serialize_request_with_attributes ( subject_key, Vec :: new ( ) )
538
+ }
539
+
540
+ /// Generate and serialize a certificate signing request (CSR) with custom PKCS #10 attributes.
541
+ /// as defined in [RFC 2986].
542
+ ///
543
+ /// The constructed CSR will contain attributes based on the certificate parameters,
544
+ /// and include the subject public key information from `subject_key`. Additionally,
545
+ /// the CSR will be self-signed using the subject key.
546
+ ///
547
+ /// Note that subsequent invocations of `serialize_request_with_attributes()` will not produce the exact
548
+ /// same output.
549
+ ///
550
+ /// [RFC 2986]: <https://datatracker.ietf.org/doc/html/rfc2986#section-4>
551
+ pub fn serialize_request_with_attributes (
552
+ & self ,
553
+ subject_key : & KeyPair ,
554
+ attrs : Vec < Attribute > ,
536
555
) -> Result < CertificateSigningRequest , Error > {
537
556
// No .. pattern, we use this to ensure every field is used
538
557
#[ deny( unused) ]
@@ -582,11 +601,9 @@ impl CertificateParams {
582
601
let der = subject_key. sign_der ( |writer| {
583
602
// Write version
584
603
writer. next ( ) . write_u8 ( 0 ) ;
585
- // Write subject name
586
604
write_distinguished_name ( writer. next ( ) , distinguished_name) ;
587
- // Write subjectPublicKeyInfo
588
605
serialize_public_key_der ( subject_key, writer. next ( ) ) ;
589
- // Write extensions
606
+
590
607
// According to the spec in RFC 2986, even if attributes are empty we need the empty attribute tag
591
608
writer
592
609
. next ( )
@@ -596,6 +613,13 @@ impl CertificateParams {
596
613
if write_extension_request {
597
614
self . write_extension_request_attribute ( writer. next ( ) ) ;
598
615
}
616
+
617
+ for Attribute { oid, values } in attrs {
618
+ writer. next ( ) . write_sequence ( |writer| {
619
+ writer. next ( ) . write_oid ( & ObjectIdentifier :: from_slice ( & oid) ) ;
620
+ writer. next ( ) . write_der ( & values) ;
621
+ } ) ;
622
+ }
599
623
} ) ;
600
624
} ) ;
601
625
@@ -846,6 +870,25 @@ fn write_general_subtrees(writer: DERWriter, tag: u64, general_subtrees: &[Gener
846
870
} ) ;
847
871
}
848
872
873
+ /// A PKCS #10 CSR attribute, as defined in [RFC 5280] and constrained
874
+ /// by [RFC 2986].
875
+ ///
876
+ /// [RFC 5280]: <https://datatracker.ietf.org/doc/html/rfc5280#appendix-A.1>
877
+ /// [RFC 2986]: <https://datatracker.ietf.org/doc/html/rfc2986#section-4>
878
+ #[ derive( Debug , PartialEq , Eq , Hash , Clone ) ]
879
+ pub struct Attribute {
880
+ /// `AttributeType` of the `Attribute`, defined as an `OBJECT IDENTIFIER`.
881
+ pub oid : & ' static [ u64 ] ,
882
+ /// DER-encoded values of the `Attribute`, defined by [RFC 2986] as:
883
+ ///
884
+ /// ```text
885
+ /// SET SIZE(1..MAX) OF ATTRIBUTE.&Type({IOSet}{@type})
886
+ /// ```
887
+ ///
888
+ /// [RFC 2986]: https://datatracker.ietf.org/doc/html/rfc2986#section-4
889
+ pub values : Vec < u8 > ,
890
+ }
891
+
849
892
/// A custom extension of a certificate, as specified in
850
893
/// [RFC 5280](https://tools.ietf.org/html/rfc5280#section-4.2)
851
894
#[ derive( Debug , PartialEq , Eq , Hash , Clone ) ]
0 commit comments