1 //! Support for signing mft, crl, certificates, roas..
2 //! Common objects for TAs and CAs
3 use std::{
4     ops::Deref,
5     sync::{Arc, RwLock},
6     {convert::TryFrom, path::Path},
7 };
8 
9 use bcder::Captured;
10 use bytes::Bytes;
11 
12 use rpki::{
13     repository::{
14         aspa::{Aspa, AspaBuilder},
15         cert::{Cert, KeyUsage, Overclaim, TbsCert},
16         crl::{Crl, CrlEntry, TbsCertList},
17         crypto::{DigestAlgorithm, KeyIdentifier, PublicKey, PublicKeyFormat, Signature, SignatureAlgorithm, Signer},
18         csr::Csr,
19         manifest::{FileAndHash, Manifest, ManifestContent},
20         roa::{Roa, RoaBuilder},
21         rta,
22         sigobj::SignedObjectBuilder,
23         x509::{Name, Serial, Time, Validity},
24     },
25     uri,
26 };
27 
28 #[cfg(feature = "hsm")]
29 use crate::commons::util::dummysigner::DummySigner;
30 
31 use crate::{
32     commons::{
33         api::{IssuedCert, RcvdCert, ReplacedObject, RepoInfo, RequestResourceLimit, ResourceSet},
34         crypto::{self, CryptoResult},
35         error::Error,
36         util::{softsigner::OpenSslSigner, AllowedUri},
37         KrillResult,
38     },
39     daemon::ca::CertifiedKey,
40 };
41 
42 //------------ Signer --------------------------------------------------------
43 
44 #[derive(Clone, Debug)]
45 enum SignerProvider {
46     OpenSsl(OpenSslSigner),
47 
48     #[cfg(feature = "hsm")]
49     #[allow(dead_code)]
50     Dummy(DummySigner),
51 }
52 
53 impl SignerProvider {
create_key(&mut self) -> CryptoResult<KeyIdentifier>54     pub fn create_key(&mut self) -> CryptoResult<KeyIdentifier> {
55         match self {
56             SignerProvider::OpenSsl(signer) => signer.create_key(PublicKeyFormat::Rsa),
57             #[cfg(feature = "hsm")]
58             SignerProvider::Dummy(signer) => signer.create_key(PublicKeyFormat::Rsa),
59         }
60         .map_err(crypto::Error::signer)
61     }
62 
destroy_key(&mut self, key_id: &KeyIdentifier) -> CryptoResult<()>63     pub fn destroy_key(&mut self, key_id: &KeyIdentifier) -> CryptoResult<()> {
64         match self {
65             SignerProvider::OpenSsl(signer) => signer.destroy_key(key_id),
66             #[cfg(feature = "hsm")]
67             SignerProvider::Dummy(signer) => signer.destroy_key(key_id),
68         }
69         .map_err(crypto::Error::key_error)
70     }
71 
get_key_info(&self, key_id: &KeyIdentifier) -> CryptoResult<PublicKey>72     pub fn get_key_info(&self, key_id: &KeyIdentifier) -> CryptoResult<PublicKey> {
73         match self {
74             SignerProvider::OpenSsl(signer) => signer.get_key_info(key_id),
75             #[cfg(feature = "hsm")]
76             SignerProvider::Dummy(signer) => signer.get_key_info(key_id),
77         }
78         .map_err(crypto::Error::key_error)
79     }
80 
random_serial(&self) -> CryptoResult<Serial>81     pub fn random_serial(&self) -> CryptoResult<Serial> {
82         match self {
83             SignerProvider::OpenSsl(signer) => Serial::random(signer.deref()),
84             #[cfg(feature = "hsm")]
85             SignerProvider::Dummy(signer) => Serial::random(signer.deref()),
86         }
87         .map_err(crypto::Error::signer)
88     }
89 
sign<D: AsRef<[u8]> + ?Sized>( &self, key_id: &KeyIdentifier, sig_alg: SignatureAlgorithm, data: &D, ) -> CryptoResult<Signature>90     pub fn sign<D: AsRef<[u8]> + ?Sized>(
91         &self,
92         key_id: &KeyIdentifier,
93         sig_alg: SignatureAlgorithm,
94         data: &D,
95     ) -> CryptoResult<Signature> {
96         match self {
97             SignerProvider::OpenSsl(signer) => signer.sign(key_id, sig_alg, data),
98             #[cfg(feature = "hsm")]
99             SignerProvider::Dummy(signer) => signer.sign(key_id, sig_alg, data),
100         }
101         .map_err(crypto::Error::signing)
102     }
103 
sign_one_off<D: AsRef<[u8]> + ?Sized>( &self, sig_alg: SignatureAlgorithm, data: &D, ) -> CryptoResult<(Signature, PublicKey)>104     pub fn sign_one_off<D: AsRef<[u8]> + ?Sized>(
105         &self,
106         sig_alg: SignatureAlgorithm,
107         data: &D,
108     ) -> CryptoResult<(Signature, PublicKey)> {
109         match self {
110             SignerProvider::OpenSsl(signer) => signer.sign_one_off(sig_alg, data),
111             #[cfg(feature = "hsm")]
112             SignerProvider::Dummy(signer) => signer.sign_one_off(sig_alg, data),
113         }
114         .map_err(crypto::Error::signer)
115     }
116 
sign_csr(&self, base_repo: &RepoInfo, name_space: &str, key: &KeyIdentifier) -> CryptoResult<Csr>117     pub fn sign_csr(&self, base_repo: &RepoInfo, name_space: &str, key: &KeyIdentifier) -> CryptoResult<Csr> {
118         fn func<T>(signer: &T, base_repo: &RepoInfo, name_space: &str, key: &KeyIdentifier) -> CryptoResult<Captured>
119         where
120             T: Signer<KeyId = KeyIdentifier>,
121         {
122             let pub_key = signer.get_key_info(key).map_err(crypto::Error::key_error)?;
123             Csr::construct(
124                 signer.deref(),
125                 key,
126                 &base_repo.ca_repository(name_space).join(&[]).unwrap(), // force trailing slash
127                 &base_repo.rpki_manifest(name_space, &pub_key.key_identifier()),
128                 Some(&base_repo.rpki_notify()),
129             )
130             .map_err(crypto::Error::signing)
131         }
132 
133         let enc = match self {
134             SignerProvider::OpenSsl(signer) => func(signer.deref(), base_repo, name_space, key),
135             #[cfg(feature = "hsm")]
136             SignerProvider::Dummy(signer) => func(signer.deref(), base_repo, name_space, key),
137         }?;
138 
139         Ok(Csr::decode(enc.as_slice())?)
140     }
141 
sign_cert(&self, tbs: TbsCert, key_id: &KeyIdentifier) -> CryptoResult<Cert>142     pub fn sign_cert(&self, tbs: TbsCert, key_id: &KeyIdentifier) -> CryptoResult<Cert> {
143         match self {
144             SignerProvider::OpenSsl(signer) => tbs.into_cert(signer.deref(), key_id),
145             #[cfg(feature = "hsm")]
146             SignerProvider::Dummy(signer) => tbs.into_cert(signer.deref(), key_id),
147         }
148         .map_err(crypto::Error::signing)
149     }
150 
sign_crl(&self, tbs: TbsCertList<Vec<CrlEntry>>, key_id: &KeyIdentifier) -> CryptoResult<Crl>151     pub fn sign_crl(&self, tbs: TbsCertList<Vec<CrlEntry>>, key_id: &KeyIdentifier) -> CryptoResult<Crl> {
152         match self {
153             SignerProvider::OpenSsl(signer) => tbs.into_crl(signer.deref(), key_id),
154             #[cfg(feature = "hsm")]
155             SignerProvider::Dummy(signer) => tbs.into_crl(signer.deref(), key_id),
156         }
157         .map_err(crypto::Error::signing)
158     }
159 
sign_manifest( &self, content: ManifestContent, builder: SignedObjectBuilder, key_id: &KeyIdentifier, ) -> CryptoResult<Manifest>160     pub fn sign_manifest(
161         &self,
162         content: ManifestContent,
163         builder: SignedObjectBuilder,
164         key_id: &KeyIdentifier,
165     ) -> CryptoResult<Manifest> {
166         match self {
167             SignerProvider::OpenSsl(signer) => content.into_manifest(builder, signer.deref(), key_id),
168             #[cfg(feature = "hsm")]
169             SignerProvider::Dummy(signer) => content.into_manifest(builder, signer.deref(), key_id),
170         }
171         .map_err(crypto::Error::signing)
172     }
173 
sign_roa( &self, roa_builder: RoaBuilder, object_builder: SignedObjectBuilder, key_id: &KeyIdentifier, ) -> CryptoResult<Roa>174     pub fn sign_roa(
175         &self,
176         roa_builder: RoaBuilder,
177         object_builder: SignedObjectBuilder,
178         key_id: &KeyIdentifier,
179     ) -> CryptoResult<Roa> {
180         match self {
181             SignerProvider::OpenSsl(signer) => roa_builder.finalize(object_builder, signer.deref(), key_id),
182             #[cfg(feature = "hsm")]
183             SignerProvider::Dummy(signer) => roa_builder.finalize(object_builder, signer.deref(), key_id),
184         }
185         .map_err(crypto::Error::signing)
186     }
187 
sign_aspa( &self, aspa_builder: AspaBuilder, object_builder: SignedObjectBuilder, key_id: &KeyIdentifier, ) -> CryptoResult<Aspa>188     pub fn sign_aspa(
189         &self,
190         aspa_builder: AspaBuilder,
191         object_builder: SignedObjectBuilder,
192         key_id: &KeyIdentifier,
193     ) -> CryptoResult<Aspa> {
194         match self {
195             SignerProvider::OpenSsl(signer) => aspa_builder.finalize(object_builder, signer.deref(), key_id),
196             #[cfg(feature = "hsm")]
197             SignerProvider::Dummy(signer) => aspa_builder.finalize(object_builder, signer.deref(), key_id),
198         }
199         .map_err(crypto::Error::signing)
200     }
201 
sign_rta(&self, rta_builder: &mut rta::RtaBuilder, ee: Cert) -> CryptoResult<()>202     pub fn sign_rta(&self, rta_builder: &mut rta::RtaBuilder, ee: Cert) -> CryptoResult<()> {
203         let key = ee.subject_key_identifier();
204         rta_builder.push_cert(ee);
205 
206         match self {
207             SignerProvider::OpenSsl(signer) => rta_builder.sign(signer.deref(), &key, None, None),
208             #[cfg(feature = "hsm")]
209             SignerProvider::Dummy(signer) => rta_builder.sign(signer.deref(), &key, None, None),
210         }
211         .map_err(crypto::Error::signing)
212     }
213 }
214 
215 #[derive(Clone, Debug)]
216 pub struct KrillSigner {
217     // KrillSigner chooses which signer to use when. The noise of handling the enum based dispatch is handled by the
218     // SignerProvider type defined above, patterned after the existing AuthProvider enum based approach.
219     //
220     // Use Arc references so that we can use refer to the same signer instance more than once if that signer should be
221     // used for multiple purposes, e.g. as both general_signer and one_off_signer in this case.
222     //
223     // Use an RwLock because the Signer trait from the rpki-rs crate uses &mut self for create_key() and destroy_key()
224     // operations. In future we might move the responsibility for locking into the signer so that it can lock only what
225     // actually needs to be locked raet
226 
227     // The general signer is used for all signing operations except one off signing.
228     general_signer: Arc<RwLock<SignerProvider>>,
229 
230     // As the security of a HSM isn't needed for one off keys, and HSMs are slow, by default this should be an instance
231     // of OpenSslSigner. However, if users think the perceived extra security is warranted let them use a different
232     // Signer for one off keys if that's what they want.
233     one_off_signer: Arc<RwLock<SignerProvider>>,
234 }
235 
236 impl KrillSigner {
build(work_dir: &Path) -> KrillResult<Self>237     pub fn build(work_dir: &Path) -> KrillResult<Self> {
238         // The types of signer to initialize, the details needed to initialize them and the intended purpose for each
239         // signer (e.g. signer for past keys, currently used signer, signer to use for a key roll, etc.) should come
240         // from the configuration file. KrillSigner should combine that input its own rules, e.g. to dispatch a signing
241         // request to the correct signer we will need to determine which signer possesses the signing key, and the
242         // signer to use to create a new key depends on whether the key is one-off or not and whether or not it is
243         // being created for a key roll. For now the capability for different signers for different purposes exists but
244         // is not yet used.
245 
246         let openssl_signer = OpenSslSigner::build(work_dir)?;
247         let openssl_signer = Arc::new(RwLock::new(SignerProvider::OpenSsl(openssl_signer)));
248         let general_signer = openssl_signer.clone();
249         let one_off_signer = openssl_signer;
250         Ok(KrillSigner {
251             general_signer,
252             one_off_signer,
253         })
254     }
255 
create_key(&self) -> CryptoResult<KeyIdentifier>256     pub fn create_key(&self) -> CryptoResult<KeyIdentifier> {
257         self.general_signer.write().unwrap().create_key()
258     }
259 
destroy_key(&self, key_id: &KeyIdentifier) -> CryptoResult<()>260     pub fn destroy_key(&self, key_id: &KeyIdentifier) -> CryptoResult<()> {
261         self.general_signer.write().unwrap().destroy_key(key_id)
262     }
263 
get_key_info(&self, key_id: &KeyIdentifier) -> CryptoResult<PublicKey>264     pub fn get_key_info(&self, key_id: &KeyIdentifier) -> CryptoResult<PublicKey> {
265         self.general_signer.read().unwrap().get_key_info(key_id)
266     }
267 
random_serial(&self) -> CryptoResult<Serial>268     pub fn random_serial(&self) -> CryptoResult<Serial> {
269         self.general_signer.read().unwrap().random_serial()
270     }
271 
sign<D: AsRef<[u8]> + ?Sized>(&self, key_id: &KeyIdentifier, data: &D) -> CryptoResult<Signature>272     pub fn sign<D: AsRef<[u8]> + ?Sized>(&self, key_id: &KeyIdentifier, data: &D) -> CryptoResult<Signature> {
273         self.general_signer
274             .read()
275             .unwrap()
276             .sign(key_id, SignatureAlgorithm::default(), data)
277     }
278 
sign_one_off<D: AsRef<[u8]> + ?Sized>(&self, data: &D) -> CryptoResult<(Signature, PublicKey)>279     pub fn sign_one_off<D: AsRef<[u8]> + ?Sized>(&self, data: &D) -> CryptoResult<(Signature, PublicKey)> {
280         self.one_off_signer
281             .read()
282             .unwrap()
283             .sign_one_off(SignatureAlgorithm::default(), data)
284     }
285 
sign_csr(&self, base_repo: &RepoInfo, name_space: &str, key: &KeyIdentifier) -> CryptoResult<Csr>286     pub fn sign_csr(&self, base_repo: &RepoInfo, name_space: &str, key: &KeyIdentifier) -> CryptoResult<Csr> {
287         self.general_signer.read().unwrap().sign_csr(base_repo, name_space, key)
288     }
289 
sign_cert(&self, tbs: TbsCert, key_id: &KeyIdentifier) -> CryptoResult<Cert>290     pub fn sign_cert(&self, tbs: TbsCert, key_id: &KeyIdentifier) -> CryptoResult<Cert> {
291         self.general_signer.read().unwrap().sign_cert(tbs, key_id)
292     }
293 
sign_crl(&self, tbs: TbsCertList<Vec<CrlEntry>>, key_id: &KeyIdentifier) -> CryptoResult<Crl>294     pub fn sign_crl(&self, tbs: TbsCertList<Vec<CrlEntry>>, key_id: &KeyIdentifier) -> CryptoResult<Crl> {
295         self.general_signer.read().unwrap().sign_crl(tbs, key_id)
296     }
297 
sign_manifest( &self, content: ManifestContent, builder: SignedObjectBuilder, key_id: &KeyIdentifier, ) -> CryptoResult<Manifest>298     pub fn sign_manifest(
299         &self,
300         content: ManifestContent,
301         builder: SignedObjectBuilder,
302         key_id: &KeyIdentifier,
303     ) -> CryptoResult<Manifest> {
304         self.general_signer
305             .read()
306             .unwrap()
307             .sign_manifest(content, builder, key_id)
308     }
309 
sign_roa( &self, roa_builder: RoaBuilder, object_builder: SignedObjectBuilder, key_id: &KeyIdentifier, ) -> CryptoResult<Roa>310     pub fn sign_roa(
311         &self,
312         roa_builder: RoaBuilder,
313         object_builder: SignedObjectBuilder,
314         key_id: &KeyIdentifier,
315     ) -> CryptoResult<Roa> {
316         self.general_signer
317             .read()
318             .unwrap()
319             .sign_roa(roa_builder, object_builder, key_id)
320     }
321 
sign_aspa( &self, aspa_builder: AspaBuilder, object_builder: SignedObjectBuilder, key_id: &KeyIdentifier, ) -> CryptoResult<Aspa>322     pub fn sign_aspa(
323         &self,
324         aspa_builder: AspaBuilder,
325         object_builder: SignedObjectBuilder,
326         key_id: &KeyIdentifier,
327     ) -> CryptoResult<Aspa> {
328         self.general_signer
329             .read()
330             .unwrap()
331             .sign_aspa(aspa_builder, object_builder, key_id)
332     }
333 
sign_rta(&self, rta_builder: &mut rta::RtaBuilder, ee: Cert) -> CryptoResult<()>334     pub fn sign_rta(&self, rta_builder: &mut rta::RtaBuilder, ee: Cert) -> CryptoResult<()> {
335         self.general_signer.read().unwrap().sign_rta(rta_builder, ee)
336     }
337 }
338 
339 // //------------ Signer --------------------------------------------------------
340 //
341 // pub trait Signer: crypto::Signer<KeyId = KeyIdentifier> + Clone + Sized + Sync + Send + 'static {}
342 // impl<T: crypto::Signer<KeyId = KeyIdentifier> + Clone + Sized + Sync + Send + 'static> Signer for T {}
343 
344 //------------ CsrInfo -------------------------------------------------------
345 
346 pub type CaRepository = uri::Rsync;
347 pub type RpkiManifest = uri::Rsync;
348 pub type RpkiNotify = uri::Https;
349 
350 pub struct CsrInfo {
351     ca_repository: CaRepository,
352     rpki_manifest: RpkiManifest,
353     rpki_notify: Option<RpkiNotify>,
354     key: PublicKey,
355 }
356 
357 impl CsrInfo {
new( ca_repository: CaRepository, rpki_manifest: RpkiManifest, rpki_notify: Option<RpkiNotify>, key: PublicKey, ) -> Self358     pub fn new(
359         ca_repository: CaRepository,
360         rpki_manifest: RpkiManifest,
361         rpki_notify: Option<RpkiNotify>,
362         key: PublicKey,
363     ) -> Self {
364         CsrInfo {
365             ca_repository,
366             rpki_manifest,
367             rpki_notify,
368             key,
369         }
370     }
371 
global_uris(&self) -> bool372     pub fn global_uris(&self) -> bool {
373         self.ca_repository.seems_global_uri()
374             && self.rpki_manifest.seems_global_uri()
375             && self
376                 .rpki_notify
377                 .as_ref()
378                 .map(|uri| uri.seems_global_uri())
379                 .unwrap_or_else(|| true)
380     }
381 
unpack(self) -> (CaRepository, RpkiManifest, Option<RpkiNotify>, PublicKey)382     pub fn unpack(self) -> (CaRepository, RpkiManifest, Option<RpkiNotify>, PublicKey) {
383         (self.ca_repository, self.rpki_manifest, self.rpki_notify, self.key)
384     }
385 
key_id(&self) -> KeyIdentifier386     pub fn key_id(&self) -> KeyIdentifier {
387         self.key.key_identifier()
388     }
389 }
390 
391 impl TryFrom<&Csr> for CsrInfo {
392     type Error = Error;
393 
try_from(csr: &Csr) -> KrillResult<CsrInfo>394     fn try_from(csr: &Csr) -> KrillResult<CsrInfo> {
395         csr.validate().map_err(|_| Error::invalid_csr("invalid signature"))?;
396         let ca_repository = csr
397             .ca_repository()
398             .cloned()
399             .ok_or_else(|| Error::invalid_csr("missing ca repository"))?;
400         let rpki_manifest = csr
401             .rpki_manifest()
402             .cloned()
403             .ok_or_else(|| Error::invalid_csr("missing rpki manifest"))?;
404         let rpki_notify = csr.rpki_notify().cloned();
405         let key = csr.public_key().clone();
406         Ok(CsrInfo {
407             ca_repository,
408             rpki_manifest,
409             rpki_notify,
410             key,
411         })
412     }
413 }
414 
415 impl From<&Cert> for CsrInfo {
from(issued: &Cert) -> Self416     fn from(issued: &Cert) -> Self {
417         let ca_repository = issued.ca_repository().cloned().unwrap();
418         let rpki_manifest = issued.rpki_manifest().cloned().unwrap();
419         let rpki_notify = issued.rpki_notify().cloned();
420         let key = issued.subject_public_key_info().clone();
421         CsrInfo {
422             ca_repository,
423             rpki_manifest,
424             rpki_notify,
425             key,
426         }
427     }
428 }
429 
430 //------------ CaSignSupport -------------------------------------------------
431 
432 /// Support signing by CAs
433 pub struct SignSupport;
434 
435 impl SignSupport {
436     /// Create an IssuedCert
make_issued_cert( csr: CsrInfo, resources: &ResourceSet, limit: RequestResourceLimit, replaces: Option<ReplacedObject>, signing_key: &CertifiedKey, weeks: i64, signer: &KrillSigner, ) -> KrillResult<IssuedCert>437     pub fn make_issued_cert(
438         csr: CsrInfo,
439         resources: &ResourceSet,
440         limit: RequestResourceLimit,
441         replaces: Option<ReplacedObject>,
442         signing_key: &CertifiedKey,
443         weeks: i64,
444         signer: &KrillSigner,
445     ) -> KrillResult<IssuedCert> {
446         let signing_cert = signing_key.incoming_cert();
447         let resources = resources.apply_limit(&limit)?;
448         if !signing_cert.resources().contains(&resources) {
449             return Err(Error::MissingResources);
450         }
451 
452         let validity = Self::sign_validity_weeks(weeks);
453         let request = CertRequest::Ca(csr, validity);
454 
455         let tbs = Self::make_tbs_cert(&resources, signing_cert, request, signer)?;
456         let cert = signer.sign_cert(tbs, signing_key.key_id())?;
457 
458         let cert_uri = signing_cert.uri_for_object(&cert);
459 
460         Ok(IssuedCert::new(cert_uri, limit, resources, cert, replaces))
461     }
462 
463     /// Create an EE certificate for use in ResourceTaggedAttestations.
464     /// Note that for RPKI signed objects such as ROAs and Manifests, the
465     /// EE certificate is created by the rpki.rs library instead.
make_rta_ee_cert( resources: &ResourceSet, signing_key: &CertifiedKey, validity: Validity, pub_key: PublicKey, signer: &KrillSigner, ) -> KrillResult<Cert>466     pub fn make_rta_ee_cert(
467         resources: &ResourceSet,
468         signing_key: &CertifiedKey,
469         validity: Validity,
470         pub_key: PublicKey,
471         signer: &KrillSigner,
472     ) -> KrillResult<Cert> {
473         let signing_cert = signing_key.incoming_cert();
474         let request = CertRequest::Ee(pub_key, validity);
475         let tbs = Self::make_tbs_cert(resources, signing_cert, request, signer)?;
476 
477         let cert = signer.sign_cert(tbs, signing_key.key_id())?;
478         Ok(cert)
479     }
480 
make_tbs_cert( resources: &ResourceSet, signing_cert: &RcvdCert, request: CertRequest, signer: &KrillSigner, ) -> KrillResult<TbsCert>481     fn make_tbs_cert(
482         resources: &ResourceSet,
483         signing_cert: &RcvdCert,
484         request: CertRequest,
485         signer: &KrillSigner,
486     ) -> KrillResult<TbsCert> {
487         let serial = signer.random_serial()?;
488         let issuer = signing_cert.cert().subject().clone();
489 
490         let validity = match &request {
491             CertRequest::Ca(_, validity) => *validity,
492             CertRequest::Ee(_, validity) => *validity,
493         };
494 
495         let pub_key = match &request {
496             CertRequest::Ca(info, _) => info.key.clone(),
497             CertRequest::Ee(key, _) => key.clone(),
498         };
499 
500         let subject = Some(Name::from_pub_key(&pub_key));
501 
502         let key_usage = match &request {
503             CertRequest::Ca(_, _) => KeyUsage::Ca,
504             CertRequest::Ee(_, _) => KeyUsage::Ee,
505         };
506 
507         let overclaim = Overclaim::Refuse;
508 
509         let mut cert = TbsCert::new(serial, issuer, validity, subject, pub_key, key_usage, overclaim);
510 
511         let asns = resources.to_as_resources();
512         if asns.is_inherited() || !asns.to_blocks().unwrap().is_empty() {
513             cert.set_as_resources(asns);
514         }
515 
516         let ipv4 = resources.to_ip_resources_v4();
517         if ipv4.is_inherited() || !ipv4.to_blocks().unwrap().is_empty() {
518             cert.set_v4_resources(ipv4);
519         }
520 
521         let ipv6 = resources.to_ip_resources_v6();
522         if ipv6.is_inherited() || !ipv6.to_blocks().unwrap().is_empty() {
523             cert.set_v6_resources(ipv6);
524         }
525 
526         cert.set_authority_key_identifier(Some(signing_cert.cert().subject_key_identifier()));
527         cert.set_ca_issuer(Some(signing_cert.uri().clone()));
528         cert.set_crl_uri(Some(signing_cert.crl_uri()));
529 
530         match request {
531             CertRequest::Ca(csr, _) => {
532                 let (ca_repository, rpki_manifest, rpki_notify, _pub_key) = csr.unpack();
533                 cert.set_basic_ca(Some(true));
534                 cert.set_ca_repository(Some(ca_repository));
535                 cert.set_rpki_manifest(Some(rpki_manifest));
536                 cert.set_rpki_notify(rpki_notify);
537             }
538             CertRequest::Ee(_, _) => {
539                 // cert.set_signed_object() ??
540             }
541         }
542 
543         Ok(cert)
544     }
545 
546     /// Returns a validity period from 5 minutes ago (in case of NTP mess-up), to
547     /// X weeks from now.
sign_validity_weeks(weeks: i64) -> Validity548     pub fn sign_validity_weeks(weeks: i64) -> Validity {
549         let from = Time::five_minutes_ago();
550         let until = Time::now() + chrono::Duration::weeks(weeks);
551         Validity::new(from, until)
552     }
553 
sign_validity_days(days: i64) -> Validity554     pub fn sign_validity_days(days: i64) -> Validity {
555         let from = Time::five_minutes_ago();
556         let until = Time::now() + chrono::Duration::days(days);
557         Validity::new(from, until)
558     }
559 }
560 
561 #[allow(clippy::large_enum_variant)]
562 enum CertRequest {
563     Ca(CsrInfo, Validity),
564     Ee(PublicKey, Validity),
565 }
566 
567 trait ManifestEntry {
mft_bytes(&self) -> Bytes568     fn mft_bytes(&self) -> Bytes;
mft_hash(&self) -> Bytes569     fn mft_hash(&self) -> Bytes {
570         let digest = DigestAlgorithm::default().digest(self.mft_bytes().as_ref());
571         Bytes::copy_from_slice(digest.as_ref())
572     }
mft_entry(&self, name: &str) -> FileAndHash<Bytes, Bytes>573     fn mft_entry(&self, name: &str) -> FileAndHash<Bytes, Bytes> {
574         FileAndHash::new(Bytes::copy_from_slice(name.as_bytes()), self.mft_hash())
575     }
576 }
577 
578 impl ManifestEntry for Crl {
mft_bytes(&self) -> Bytes579     fn mft_bytes(&self) -> Bytes {
580         self.to_captured().into_bytes()
581     }
582 }
583