@@ -41,6 +41,8 @@ use std::net::IpAddr;
4141use std:: net:: { Ipv4Addr , Ipv6Addr } ;
4242use std:: ops:: Deref ;
4343
44+ #[ cfg( feature = "x509-parser" ) ]
45+ use pki_types:: CertificateDer ;
4446use time:: { OffsetDateTime , Time } ;
4547use yasna:: models:: ObjectIdentifier ;
4648use yasna:: models:: { GeneralizedTime , UTCTime } ;
@@ -165,6 +167,56 @@ impl<'a, S: SigningKey> Issuer<'a, S> {
165167 }
166168 }
167169
170+ /// Parses an existing ca certificate from the ASCII PEM format.
171+ ///
172+ /// See [`from_ca_cert_der`](Self::from_ca_cert_der) for more details.
173+ #[ cfg( all( feature = "pem" , feature = "x509-parser" ) ) ]
174+ pub fn from_ca_cert_pem ( pem_str : & str , signing_key : S ) -> Result < Self , Error > {
175+ let certificate = pem:: parse ( pem_str) . map_err ( |_| Error :: CouldNotParseCertificate ) ?;
176+ Self :: from_ca_cert_der ( & certificate. contents ( ) . into ( ) , signing_key)
177+ }
178+
179+ /// Parses an existing ca certificate from the DER format.
180+ ///
181+ /// This function is only of use if you have an existing CA certificate
182+ /// you would like to use to sign a certificate generated by `rcgen`.
183+ /// By providing the constructed [`CertificateParams`] and the [`SigningKey`]
184+ /// associated with your existing `ca_cert` you can use [`CertificateParams::signed_by()`]
185+ /// or [`crate::CertificateSigningRequestParams::signed_by()`] to issue new certificates
186+ /// using the CA cert.
187+ ///
188+ /// In general this function only extracts the information needed for signing.
189+ /// Other attributes of the [`Certificate`] may be left as defaults.
190+ ///
191+ /// This function assumes the provided certificate is a CA. It will not check
192+ /// for the presence of the `BasicConstraints` extension, or perform any other
193+ /// validation.
194+ ///
195+ /// [`rustls_pemfile::certs()`] is often used to obtain a [`CertificateDer`] from PEM input.
196+ /// If you already have a byte slice containing DER, it can trivially be converted into
197+ /// [`CertificateDer`] using the [`Into`] trait.
198+ ///
199+ /// [`rustls_pemfile::certs()`]: https://docs.rs/rustls-pemfile/latest/rustls_pemfile/fn.certs.html
200+ #[ cfg( feature = "x509-parser" ) ]
201+ pub fn from_ca_cert_der ( ca_cert : & CertificateDer < ' _ > , signing_key : S ) -> Result < Self , Error > {
202+ let ( _remainder, x509) = x509_parser:: parse_x509_certificate ( ca_cert)
203+ . map_err ( |_| Error :: CouldNotParseCertificate ) ?;
204+
205+ Ok ( Self {
206+ key_usages : Cow :: Owned ( KeyUsagePurpose :: from_x509 ( & x509) ?) ,
207+ key_identifier_method : Cow :: Owned ( KeyIdMethod :: from_x509 ( & x509) ?) ,
208+ distinguished_name : Cow :: Owned ( DistinguishedName :: from_name (
209+ & x509. tbs_certificate . subject ,
210+ ) ?) ,
211+ signing_key : MaybeOwned :: Owned ( signing_key) ,
212+ } )
213+ }
214+
215+ /// Allowed key usages for this issuer.
216+ pub fn key_usages ( & self ) -> & [ KeyUsagePurpose ] {
217+ & self . key_usages
218+ }
219+
168220 /// Yield a reference to the signing key.
169221 pub fn key ( & self ) -> & S {
170222 & self . signing_key
0 commit comments