@@ -15,9 +15,10 @@ use crate::{
1515 pkix:: {
1616 AuthorityKeyIdentifier , BasicConstraints , KeyUsage , KeyUsages , SubjectKeyIdentifier ,
1717 } ,
18- AsExtension , Extension ,
18+ AsExtension , Extension , Extensions ,
1919 } ,
2020 name:: Name ,
21+ request:: { CertReq , CertReqInfo , ExtensionReq } ,
2122 serial_number:: SerialNumber ,
2223 time:: Validity ,
2324} ;
@@ -142,15 +143,19 @@ impl Profile {
142143 include_subject_key_identifier : false ,
143144 ..
144145 } => { }
145- _ => extensions. push ( SubjectKeyIdentifier :: try_from ( spk) ?. to_extension ( tbs) ?) ,
146+ _ => extensions. push (
147+ SubjectKeyIdentifier :: try_from ( spk) ?. to_extension ( & tbs. subject , & extensions) ?,
148+ ) ,
146149 }
147150
148151 // Build Authority Key Identifier
149152 match self {
150153 Profile :: Root => { }
151154 _ => {
152- extensions
153- . push ( AuthorityKeyIdentifier :: try_from ( issuer_spk. clone ( ) ) ?. to_extension ( tbs) ?) ;
155+ extensions. push (
156+ AuthorityKeyIdentifier :: try_from ( issuer_spk. clone ( ) ) ?
157+ . to_extension ( & tbs. subject , & extensions) ?,
158+ ) ;
154159 }
155160 }
156161
@@ -160,29 +165,31 @@ impl Profile {
160165 ca : true ,
161166 path_len_constraint : None ,
162167 }
163- . to_extension ( tbs) ?,
168+ . to_extension ( & tbs. subject , & extensions ) ?,
164169 Profile :: SubCA {
165170 path_len_constraint,
166171 ..
167172 } => BasicConstraints {
168173 ca : true ,
169174 path_len_constraint : * path_len_constraint,
170175 }
171- . to_extension ( tbs) ?,
176+ . to_extension ( & tbs. subject , & extensions ) ?,
172177 Profile :: Leaf { .. } => BasicConstraints {
173178 ca : false ,
174179 path_len_constraint : None ,
175180 }
176- . to_extension ( tbs) ?,
181+ . to_extension ( & tbs. subject , & extensions ) ?,
177182 #[ cfg( feature = "hazmat" ) ]
178183 Profile :: Manual { .. } => unreachable ! ( ) ,
179184 } ) ;
180185
181186 // Build Key Usage extension
182187 match self {
183188 Profile :: Root | Profile :: SubCA { .. } => {
184- extensions
185- . push ( KeyUsage ( KeyUsages :: KeyCertSign | KeyUsages :: CRLSign ) . to_extension ( tbs) ?) ;
189+ extensions. push (
190+ KeyUsage ( KeyUsages :: KeyCertSign | KeyUsages :: CRLSign )
191+ . to_extension ( & tbs. subject , & extensions) ?,
192+ ) ;
186193 }
187194 Profile :: Leaf {
188195 enable_key_agreement,
@@ -197,7 +204,7 @@ impl Profile {
197204 key_usage |= KeyUsages :: KeyAgreement ;
198205 }
199206
200- extensions. push ( KeyUsage ( key_usage) . to_extension ( tbs) ?) ;
207+ extensions. push ( KeyUsage ( key_usage) . to_extension ( & tbs. subject , & extensions ) ?) ;
201208 }
202209 #[ cfg( feature = "hazmat" ) ]
203210 Profile :: Manual { .. } => unreachable ! ( ) ,
@@ -250,6 +257,7 @@ impl Profile {
250257/// ```
251258pub struct CertificateBuilder < ' s , S > {
252259 tbs : TbsCertificate ,
260+ extensions : Extensions ,
253261 signer : & ' s S ,
254262}
255263
@@ -302,30 +310,26 @@ where
302310 signer_pub. owned_to_ref ( ) ,
303311 & tbs,
304312 ) ?;
305- if !extensions . is_empty ( ) {
306- tbs. extensions = Some ( extensions ) ;
307- }
308-
309- Ok ( Self { tbs , signer } )
313+ Ok ( Self {
314+ tbs,
315+ extensions ,
316+ signer ,
317+ } )
310318 }
311319
312320 /// Add an extension to this certificate
313321 pub fn add_extension < E : AsExtension > ( & mut self , extension : & E ) -> Result < ( ) > {
314- if self . tbs . version == Version :: V3 {
315- let ext = extension. to_extension ( & self . tbs ) ?;
316-
317- if let Some ( extensions) = self . tbs . extensions . as_mut ( ) {
318- extensions. push ( ext) ;
319- } else {
320- let extensions = vec ! [ ext] ;
321- self . tbs . extensions = Some ( extensions) ;
322- }
323- }
322+ let ext = extension. to_extension ( & self . tbs . subject , & self . extensions ) ?;
323+ self . extensions . push ( ext) ;
324324
325325 Ok ( ( ) )
326326 }
327327
328328 fn finalize ( & mut self ) {
329+ if !self . extensions . is_empty ( ) {
330+ self . tbs . extensions = Some ( self . extensions . clone ( ) ) ;
331+ }
332+
329333 if self . tbs . extensions . is_none ( ) {
330334 if self . tbs . issuer_unique_id . is_some ( ) || self . tbs . subject_unique_id . is_some ( ) {
331335 self . tbs . version = Version :: V2 ;
@@ -375,3 +379,95 @@ where
375379 Ok ( cert)
376380 }
377381}
382+
383+ pub struct RequestBuilder < ' s , S > {
384+ info : CertReqInfo ,
385+ extension_req : ExtensionReq ,
386+ signer : & ' s S ,
387+ }
388+
389+ impl < ' s , S > RequestBuilder < ' s , S >
390+ where
391+ S : Keypair + DynSignatureAlgorithmIdentifier ,
392+ S :: VerifyingKey : EncodePublicKey ,
393+ {
394+ /// Creates a new certificate request builder
395+ pub fn new ( subject : Name , signer : & ' s S ) -> Result < Self > {
396+ let version = Default :: default ( ) ;
397+ let verifying_key = signer. verifying_key ( ) ;
398+ let public_key = verifying_key
399+ . to_public_key_der ( ) ?
400+ . decode_msg :: < SubjectPublicKeyInfoOwned > ( ) ?;
401+ let attributes = Default :: default ( ) ;
402+ let extension_req = Default :: default ( ) ;
403+
404+ Ok ( Self {
405+ info : CertReqInfo {
406+ version,
407+ subject,
408+ public_key,
409+ attributes,
410+ } ,
411+ extension_req,
412+ signer,
413+ } )
414+ }
415+
416+ /// Add an extension to this certificate request
417+ pub fn add_extension < E : AsExtension > ( & mut self , extension : & E ) -> Result < ( ) > {
418+ let ext = extension. to_extension ( & self . info . subject , & self . extension_req . 0 ) ?;
419+
420+ self . extension_req . 0 . push ( ext) ;
421+
422+ Ok ( ( ) )
423+ }
424+
425+ fn finalize ( & mut self ) -> Result < ( ) > {
426+ self . info
427+ . attributes
428+ . add ( self . extension_req . clone ( ) . try_into ( ) ?) ;
429+ Ok ( ( ) )
430+ }
431+
432+ /// Run the certificate through the signer and build the end certificate.
433+ pub fn build < Signature > ( mut self ) -> Result < CertReq >
434+ where
435+ S : Signer < Signature > ,
436+ Signature : SignatureEncoding ,
437+ {
438+ self . finalize ( ) ;
439+
440+ let algorithm = self . signer . signature_algorithm_identifier ( ) ?;
441+ let signature = self . signer . try_sign ( & self . info . to_der ( ) ?) ?;
442+ let signature = BitString :: from_bytes ( signature. to_bytes ( ) . as_ref ( ) ) ?;
443+
444+ let req = CertReq {
445+ info : self . info ,
446+ algorithm,
447+ signature,
448+ } ;
449+
450+ Ok ( req)
451+ }
452+
453+ /// Run the certificate through the signer and build the end certificate.
454+ pub fn build_with_rng < Signature > ( mut self , rng : & mut impl CryptoRngCore ) -> Result < CertReq >
455+ where
456+ S : RandomizedSigner < Signature > ,
457+ Signature : SignatureEncoding ,
458+ {
459+ self . finalize ( ) ;
460+
461+ let algorithm = self . signer . signature_algorithm_identifier ( ) ?;
462+ let signature = self . signer . try_sign_with_rng ( rng, & self . info . to_der ( ) ?) ?;
463+ let signature = BitString :: from_bytes ( signature. to_bytes ( ) . as_ref ( ) ) ?;
464+
465+ let req = CertReq {
466+ info : self . info ,
467+ algorithm,
468+ signature,
469+ } ;
470+
471+ Ok ( req)
472+ }
473+ }
0 commit comments