@@ -7,23 +7,22 @@ use der::{asn1::BitString, referenced::OwnedToRef, Encode};
77use signature:: { rand_core:: CryptoRngCore , Keypair , RandomizedSigner , Signer } ;
88use spki:: {
99 AlgorithmIdentifier , DynSignatureAlgorithmIdentifier , EncodePublicKey , ObjectIdentifier ,
10- SignatureBitStringEncoding , SubjectPublicKeyInfoOwned , SubjectPublicKeyInfoRef ,
10+ SignatureBitStringEncoding , SubjectPublicKeyInfoOwned ,
1111} ;
1212
1313use crate :: {
1414 certificate:: { Certificate , TbsCertificate , Version } ,
15- ext:: {
16- pkix:: {
17- AuthorityKeyIdentifier , BasicConstraints , KeyUsage , KeyUsages , SubjectKeyIdentifier ,
18- } ,
19- AsExtension , Extension , Extensions ,
20- } ,
15+ ext:: { AsExtension , Extensions } ,
2116 name:: Name ,
2217 request:: { attributes:: AsAttribute , CertReq , CertReqInfo , ExtensionReq } ,
2318 serial_number:: SerialNumber ,
2419 time:: Validity ,
2520} ;
2621
22+ pub mod profile;
23+
24+ use self :: profile:: Profile ;
25+
2726const NULL_OID : ObjectIdentifier = ObjectIdentifier :: new_unwrap ( "0.0.0" ) ;
2827
2928/// Error type
@@ -74,156 +73,12 @@ impl From<signature::Error> for Error {
7473/// Result type
7574pub type Result < T > = core:: result:: Result < T , Error > ;
7675
77- /// The type of certificate to build
78- #[ derive( Clone , Debug , Eq , PartialEq ) ]
79- pub enum Profile {
80- /// Build a root CA certificate
81- Root ,
82- /// Build an intermediate sub CA certificate
83- SubCA {
84- /// issuer Name,
85- /// represents the name signing the certificate
86- issuer : Name ,
87- /// pathLenConstraint INTEGER (0..MAX) OPTIONAL
88- /// BasicConstraints as defined in [RFC 5280 Section 4.2.1.9].
89- path_len_constraint : Option < u8 > ,
90- } ,
91- /// Build an end certificate
92- Leaf {
93- /// issuer Name,
94- /// represents the name signing the certificate
95- issuer : Name ,
96- /// should the key agreement flag of KeyUsage be enabled
97- enable_key_agreement : bool ,
98- /// should the key encipherment flag of KeyUsage be enabled
99- enable_key_encipherment : bool ,
100- /// should the subject key identifier extension be included
101- ///
102- /// From [RFC 5280 Section 4.2.1.2]:
103- /// For end entity certificates, subject key identifiers SHOULD be
104- /// derived from the public key. Two common methods for generating key
105- /// identifiers from the public key are identified above.
106- #[ cfg( feature = "hazmat" ) ]
107- include_subject_key_identifier : bool ,
108- } ,
109- #[ cfg( feature = "hazmat" ) ]
110- /// Opt-out of the default extensions
111- Manual {
112- /// issuer Name,
113- /// represents the name signing the certificate
114- /// A `None` will make it a self-signed certificate
115- issuer : Option < Name > ,
116- } ,
117- }
118-
119- impl Profile {
120- fn get_issuer ( & self , subject : & Name ) -> Name {
121- match self {
122- Profile :: Root => subject. clone ( ) ,
123- Profile :: SubCA { issuer, .. } => issuer. clone ( ) ,
124- Profile :: Leaf { issuer, .. } => issuer. clone ( ) ,
125- #[ cfg( feature = "hazmat" ) ]
126- Profile :: Manual { issuer, .. } => issuer. as_ref ( ) . unwrap_or ( subject) . clone ( ) ,
127- }
128- }
129-
130- fn build_extensions (
131- & self ,
132- spk : SubjectPublicKeyInfoRef < ' _ > ,
133- issuer_spk : SubjectPublicKeyInfoRef < ' _ > ,
134- tbs : & TbsCertificate ,
135- ) -> Result < vec:: Vec < Extension > > {
136- #[ cfg( feature = "hazmat" ) ]
137- // User opted out of default extensions set.
138- if let Profile :: Manual { .. } = self {
139- return Ok ( vec:: Vec :: default ( ) ) ;
140- }
141-
142- let mut extensions: vec:: Vec < Extension > = vec:: Vec :: new ( ) ;
143-
144- match self {
145- #[ cfg( feature = "hazmat" ) ]
146- Profile :: Leaf {
147- include_subject_key_identifier : false ,
148- ..
149- } => { }
150- _ => extensions. push (
151- SubjectKeyIdentifier :: try_from ( spk) ?. to_extension ( & tbs. subject , & extensions) ?,
152- ) ,
153- }
154-
155- // Build Authority Key Identifier
156- match self {
157- Profile :: Root => { }
158- _ => {
159- extensions. push (
160- AuthorityKeyIdentifier :: try_from ( issuer_spk. clone ( ) ) ?
161- . to_extension ( & tbs. subject , & extensions) ?,
162- ) ;
163- }
164- }
165-
166- // Build Basic Contraints extensions
167- extensions. push ( match self {
168- Profile :: Root => BasicConstraints {
169- ca : true ,
170- path_len_constraint : None ,
171- }
172- . to_extension ( & tbs. subject , & extensions) ?,
173- Profile :: SubCA {
174- path_len_constraint,
175- ..
176- } => BasicConstraints {
177- ca : true ,
178- path_len_constraint : * path_len_constraint,
179- }
180- . to_extension ( & tbs. subject , & extensions) ?,
181- Profile :: Leaf { .. } => BasicConstraints {
182- ca : false ,
183- path_len_constraint : None ,
184- }
185- . to_extension ( & tbs. subject , & extensions) ?,
186- #[ cfg( feature = "hazmat" ) ]
187- Profile :: Manual { .. } => unreachable ! ( ) ,
188- } ) ;
189-
190- // Build Key Usage extension
191- match self {
192- Profile :: Root | Profile :: SubCA { .. } => {
193- extensions. push (
194- KeyUsage ( KeyUsages :: KeyCertSign | KeyUsages :: CRLSign )
195- . to_extension ( & tbs. subject , & extensions) ?,
196- ) ;
197- }
198- Profile :: Leaf {
199- enable_key_agreement,
200- enable_key_encipherment,
201- ..
202- } => {
203- let mut key_usage = KeyUsages :: DigitalSignature | KeyUsages :: NonRepudiation ;
204- if * enable_key_encipherment {
205- key_usage |= KeyUsages :: KeyEncipherment ;
206- }
207- if * enable_key_agreement {
208- key_usage |= KeyUsages :: KeyAgreement ;
209- }
210-
211- extensions. push ( KeyUsage ( key_usage) . to_extension ( & tbs. subject , & extensions) ?) ;
212- }
213- #[ cfg( feature = "hazmat" ) ]
214- Profile :: Manual { .. } => unreachable ! ( ) ,
215- }
216-
217- Ok ( extensions)
218- }
219- }
220-
22176/// X509 Certificate builder
22277///
22378/// ```
22479/// use der::Decode;
22580/// use x509_cert::spki::SubjectPublicKeyInfoOwned;
226- /// use x509_cert::builder::{CertificateBuilder, Profile, Builder };
81+ /// use x509_cert::builder::{CertificateBuilder, Builder, profile };
22782/// use x509_cert::name::Name;
22883/// use x509_cert::serial_number::SerialNumber;
22984/// use x509_cert::time::Validity;
@@ -237,14 +92,14 @@ impl Profile {
23792/// # use der::referenced::RefToOwned;
23893/// # fn rsa_signer() -> SigningKey<Sha256> {
23994/// # let private_key = rsa::RsaPrivateKey::from_pkcs1_der(RSA_2048_PRIV_DER).unwrap();
240- /// # let signing_key = SigningKey::<Sha256>::new_with_prefix (private_key);
95+ /// # let signing_key = SigningKey::<Sha256>::new (private_key);
24196/// # signing_key
24297/// # }
24398///
24499/// let serial_number = SerialNumber::from(42u32);
245100/// let validity = Validity::from_now(Duration::new(5, 0)).unwrap();
246- /// let profile = Profile::Root;
247101/// let subject = Name::from_str("CN=World domination corporation,O=World domination Inc,C=US").unwrap();
102+ /// let profile = profile::cabf::Root::new(false,subject).expect("Create root profile");
248103///
249104/// let pub_key = SubjectPublicKeyInfoOwned::try_from(RSA_2048_DER).expect("get rsa pub key");
250105///
@@ -253,33 +108,35 @@ impl Profile {
253108/// profile,
254109/// serial_number,
255110/// validity,
256- /// subject,
257111/// pub_key,
258112/// )
259113/// .expect("Create certificate builder");
260114///
261115/// let cert = builder.build(&signer).expect("Create certificate");
262116/// ```
263- pub struct CertificateBuilder {
117+ pub struct CertificateBuilder < P > {
264118 tbs : TbsCertificate ,
265119 extensions : Extensions ,
266- profile : Profile ,
120+ profile : P ,
267121}
268122
269- impl CertificateBuilder {
123+ impl < P > CertificateBuilder < P >
124+ where
125+ P : Profile ,
126+ {
270127 /// Creates a new certificate builder
271128 pub fn new (
272- profile : Profile ,
129+ profile : P ,
273130 serial_number : SerialNumber ,
274131 mut validity : Validity ,
275- subject : Name ,
276132 subject_public_key_info : SubjectPublicKeyInfoOwned ,
277133 ) -> Result < Self > {
278134 let signature_alg = AlgorithmIdentifier {
279135 oid : NULL_OID ,
280136 parameters : None ,
281137 } ;
282138
139+ let subject = profile. get_subject ( ) ;
283140 let issuer = profile. get_issuer ( & subject) ;
284141
285142 validity. not_before . rfc5280_adjust_utc_time ( ) ?;
@@ -455,7 +312,10 @@ pub trait Builder: Sized {
455312 }
456313}
457314
458- impl Builder for CertificateBuilder {
315+ impl < P > Builder for CertificateBuilder < P >
316+ where
317+ P : Profile ,
318+ {
459319 type Output = Certificate ;
460320
461321 fn finalize < S > ( & mut self , cert_signer : & S ) -> Result < vec:: Vec < u8 > >
0 commit comments