1 //! Resource certificates.
2 //!
3 //! The certificates used in RPKI are called _resource certificates._ They
4 //! are defined in [RFC 6487] as a profile on regular Internet PKI
5 //! certificates defined in [RFC 5280]. While they use the format defined
6 //! for X.509 certificates, the allowed values for various fields are limited
7 //! making the overall structure more simple and predictable.
8 //!
9 //! This module implements raw resource certificates in the type [`Cert`] and
10 //! validated certificates in the type [`ResourceCert`]. The latter type is
11 //! used for issuer certificates when validating other certificates.
12 //!
13 //! In addition, there are several types for the components of a certificate.
14 //!
15 //! [`Cert`]: struct.Cert.html
16 //! [`ResourceCert`]: struct.ResourceCert.html
17 //! [RFC 5280]: https://tools.ietf.org/html/rfc5280
18 //! [RFC 6487]: https://tools.ietf.org/html/rfc5487
19
20 use std::{borrow, ops};
21 use std::iter::FromIterator;
22 use std::sync::Arc;
23 use bcder::{decode, encode};
24 use bcder::xerr;
25 use bcder::encode::PrimitiveContent;
26 use bcder::{
27 BitString, Captured, ConstOid, Ia5String, Mode, OctetString, Oid, Tag
28 };
29 use bytes::Bytes;
30 use crate::uri;
31 use super::crypto::{
32 KeyIdentifier, PublicKey, SignatureAlgorithm, Signer, SigningError
33 };
34 use super::oid;
35 use super::resources::{
36 AsBlock, AsBlocks, AsBlocksBuilder, AsResources, AsResourcesBuilder,
37 IpBlock, IpBlocks, IpBlocksBuilder, IpResources, IpResourcesBuilder
38 };
39 use super::tal::TalInfo;
40 use super::x509::{
41 Name, SignedData, Serial, Time, Validity, ValidationError,
42 encode_extension, update_first, update_once
43 };
44
45
46 //------------ Cert ----------------------------------------------------------
47
48 /// A raw resource certificate.
49 ///
50 /// A value of this type represents a resource certificate. It can be one of
51 /// three different variants.
52 ///
53 /// A _CA certificate_ appears in its own file in the repository. Its main
54 /// use is to sign other certificates.
55 ///
56 /// An _EE certificate_ is used to sign other objects in the repository, such
57 /// as manifests or ROAs and is included in the file of these objects. In
58 /// RPKI, EE certificates are used only once. Whenever a new object is
59 /// created, a new EE certificate is created, signed by its CA, used to sign
60 /// the object, and then the private key is thrown away.
61 ///
62 /// Finally, _TA certificates_ are the installed trust anchors. These are
63 /// self-signed.
64 ///
65 /// If a certificate is stored in a file, you can use the [`decode`] function
66 /// to parse the entire file. If the certificate is part of some other
67 /// structure, the [`take_from`] and [`from_constructed`] functions can be
68 /// used during parsing of that structure.
69 ///
70 /// Once parsing succeeded, the three methods [`validate_ca`],
71 /// [`validate_ee`], and [`validate_ta`] can be used to validate the
72 /// certificate and turn it into a [`ResourceCert`] so it can be used for
73 /// further processing. In addition, various methods exist to access
74 /// information contained in the certificate.
75 ///
76 /// [`ResourceCert`]: struct.ResourceCert.html
77 /// [`decode`]: #method.decode
78 /// [`take_from`]: #method.take_from
79 /// [`from_constructed`]: #method.from_constructed
80 /// [`validate_ca`]: #method.validate_ca
81 /// [`validate_ee`]: #method.validate_ee
82 /// [`validate_ta`]: #method.validate_ta
83 #[derive(Clone, Debug)]
84 pub struct Cert {
85 /// The outer structure of the certificate.
86 signed_data: SignedData,
87
88 /// The actual data of the certificate.
89 tbs: TbsCert,
90 }
91
92
93 /// # Decoding and Encoding
94 ///
95 impl Cert {
96 /// Decodes a source as a certificate.
decode<S: decode::Source>(source: S) -> Result<Self, S::Err>97 pub fn decode<S: decode::Source>(source: S) -> Result<Self, S::Err> {
98 Mode::Der.decode(source, Self::take_from)
99 }
100
101 /// Takes an encoded certificate from the beginning of a value.
102 ///
103 /// This function assumes that the certificate is encoded in the next
104 /// constructed value in `cons` tagged as a sequence.
take_from<S: decode::Source>( cons: &mut decode::Constructed<S> ) -> Result<Self, S::Err>105 pub fn take_from<S: decode::Source>(
106 cons: &mut decode::Constructed<S>
107 ) -> Result<Self, S::Err> {
108 cons.take_sequence(Self::from_constructed)
109 }
110
111 /// Takes an optional certificate from the beginning of a value.
take_opt_from<S: decode::Source>( cons: &mut decode::Constructed<S> ) -> Result<Option<Self>, S::Err>112 pub fn take_opt_from<S: decode::Source>(
113 cons: &mut decode::Constructed<S>
114 ) -> Result<Option<Self>, S::Err> {
115 cons.take_opt_sequence(Self::from_constructed)
116 }
117
118 /// Parses the content of a Certificate sequence.
from_constructed<S: decode::Source>( cons: &mut decode::Constructed<S> ) -> Result<Self, S::Err>119 pub fn from_constructed<S: decode::Source>(
120 cons: &mut decode::Constructed<S>
121 ) -> Result<Self, S::Err> {
122 let signed_data = SignedData::from_constructed(cons)?;
123 let tbs = signed_data.data().clone().decode(
124 TbsCert::from_constructed
125 )?;
126 Ok(Self { signed_data, tbs })
127 }
128
129 /// Returns a value encoder for a reference to the certificate.
encode_ref(&self) -> impl encode::Values + '_130 pub fn encode_ref(&self) -> impl encode::Values + '_ {
131 self.signed_data.encode_ref()
132 }
133
134 /// Returns a captured encoding of the certificate.
to_captured(&self) -> Captured135 pub fn to_captured(&self) -> Captured {
136 Captured::from_values(Mode::Der, self.encode_ref())
137 }
138 }
139
140
141 /// # Validation
142 ///
143 /// When validating a certificate, two properties are checked: whether the
144 /// certificate’s structure and content comply with the specification for
145 /// resource certificates laid out in [RFC 6487] and whether the certificate
146 /// has been correctly issued by its CA.
147 ///
148 /// In some cases it is useful to perform these two steps separately.
149 /// Therefore, methods are available both for each step and for doing both
150 /// steps at once. Since we need to name these consistently, we devised the
151 /// following convention:
152 ///
153 /// The first step that validates compliance with the specification is called
154 /// _inspection._ Methods are available to inspect different kinds of
155 /// certificates. They all have the verb _inspect_ in their name. Only the
156 /// certificate itself is necessary to perform inspection.
157 ///
158 /// The second step checking whether the certificate was correctly issued is
159 /// called _verification._ Methods are available to verify different kinds of
160 /// certificates. They all have the verb _verify_ in their name and, in
161 /// most cases, require access to the issuer certificate.
162 ///
163 /// In addition, methods are available to perform both steps at once for
164 /// different kinds of certificates. These all have _validate_ in their name.
165 impl Cert {
166 //--- Validation
167
168 /// Validates the certificate as a trust anchor.
169 ///
170 /// This validates that the certificate “is a current, self-signed RPKI
171 /// CA certificate that conforms to the profile as specified in
172 /// RFC6487” (RFC7730, section 3, step 2).
validate_ta( self, tal: Arc<TalInfo>, strict: bool ) -> Result<ResourceCert, ValidationError>173 pub fn validate_ta(
174 self,
175 tal: Arc<TalInfo>,
176 strict: bool
177 ) -> Result<ResourceCert, ValidationError> {
178 self.validate_ta_at(tal, strict, Time::now())
179 }
180
validate_ta_at( self, tal: Arc<TalInfo>, strict: bool, now: Time, ) -> Result<ResourceCert, ValidationError>181 pub fn validate_ta_at(
182 self,
183 tal: Arc<TalInfo>,
184 strict: bool,
185 now: Time,
186 ) -> Result<ResourceCert, ValidationError> {
187 self.inspect_ta_at(strict, now)?;
188 self.verify_ta(tal, strict)
189 }
190
191 /// Validates the certificate as a CA certificate.
192 ///
193 /// For validation to succeed, the certificate needs to have been signed
194 /// by the provided `issuer` certificate.
195 ///
196 /// Note that this does _not_ check the CRL.
validate_ca( self, issuer: &ResourceCert, strict: bool ) -> Result<ResourceCert, ValidationError>197 pub fn validate_ca(
198 self,
199 issuer: &ResourceCert,
200 strict: bool
201 ) -> Result<ResourceCert, ValidationError> {
202 self.validate_ca_at(issuer, strict, Time::now())
203 }
204
validate_ca_at( self, issuer: &ResourceCert, strict: bool, now: Time, ) -> Result<ResourceCert, ValidationError>205 pub fn validate_ca_at(
206 self,
207 issuer: &ResourceCert,
208 strict: bool,
209 now: Time,
210 ) -> Result<ResourceCert, ValidationError> {
211 self.inspect_ca_at(strict, now)?;
212 self.verify_ca(issuer, strict)
213 }
214
215 /// Validates the certificate as an EE RPKI-internal certificate.
216 ///
217 /// For validation to succeed, the certificate needs to have been signed
218 /// by the provided `issuer` certificate.
219 ///
220 /// Note that this does _not_ check the CRL.
221 ///
222 /// Note further that this method should not be used for router
223 /// certificates. Use `validate_router` for that.
validate_ee( self, issuer: &ResourceCert, strict: bool ) -> Result<ResourceCert, ValidationError>224 pub fn validate_ee(
225 self,
226 issuer: &ResourceCert,
227 strict: bool
228 ) -> Result<ResourceCert, ValidationError> {
229 self.validate_ee_at(issuer, strict, Time::now())
230 }
231
validate_ee_at( self, issuer: &ResourceCert, strict: bool, now: Time, ) -> Result<ResourceCert, ValidationError>232 pub fn validate_ee_at(
233 self,
234 issuer: &ResourceCert,
235 strict: bool,
236 now: Time,
237 ) -> Result<ResourceCert, ValidationError> {
238 self.inspect_ee_at(strict, now)?;
239 self.verify_ee(issuer, strict)
240 }
241
validate_detached_ee( self, issuer: &ResourceCert, strict: bool ) -> Result<ResourceCert, ValidationError>242 pub fn validate_detached_ee(
243 self,
244 issuer: &ResourceCert,
245 strict: bool
246 ) -> Result<ResourceCert, ValidationError> {
247 self.validate_detached_ee_at(issuer, strict, Time::now())
248 }
249
validate_detached_ee_at( self, issuer: &ResourceCert, strict: bool, now: Time, ) -> Result<ResourceCert, ValidationError>250 pub fn validate_detached_ee_at(
251 self,
252 issuer: &ResourceCert,
253 strict: bool,
254 now: Time,
255 ) -> Result<ResourceCert, ValidationError> {
256 self.inspect_detached_ee_at(strict, now)?;
257 self.verify_ee(issuer, strict)
258 }
259
validate_router( &self, issuer: &ResourceCert, strict: bool ) -> Result<(), ValidationError>260 pub fn validate_router(
261 &self,
262 issuer: &ResourceCert,
263 strict: bool
264 ) -> Result<(), ValidationError> {
265 self.validate_router_at(issuer, strict, Time::now())
266 }
267
validate_router_at( &self, issuer: &ResourceCert, strict: bool, now: Time, ) -> Result<(), ValidationError>268 pub fn validate_router_at(
269 &self,
270 issuer: &ResourceCert,
271 strict: bool,
272 now: Time,
273 ) -> Result<(), ValidationError> {
274 self.inspect_router_at(strict, now)?;
275 self.verify_router(issuer, strict)
276 }
277
278
279 //--- Inspection
280
inspect_ta(&self, strict: bool) -> Result<(), ValidationError>281 pub fn inspect_ta(&self, strict: bool) -> Result<(), ValidationError> {
282 self.inspect_ta_at(strict, Time::now())
283 }
284
inspect_ta_at( &self, strict: bool, now: Time ) -> Result<(), ValidationError>285 pub fn inspect_ta_at(
286 &self,
287 strict: bool,
288 now: Time
289 ) -> Result<(), ValidationError> {
290 self.inspect_basics(strict, now)?;
291 self.inspect_ca_basics(strict)?;
292
293 // 4.8.3. Authority Key Identifier. May be present, if so, must be
294 // equal to the subject key identifier.
295 if let Some(ref aki) = self.authority_key_identifier {
296 if *aki != self.subject_key_identifier {
297 return Err(ValidationError);
298 }
299 }
300
301 // 4.8.6. CRL Distribution Points. There mustn’t be one.
302 if self.crl_uri.is_some() {
303 return Err(ValidationError)
304 }
305
306 // 4.8.7. Authority Information Access. Must not be present.
307 if self.ca_issuer.is_some() {
308 return Err(ValidationError)
309 }
310
311 // 4.8.10. IP Resources.
312 // 4.8.11. AS Resources.
313 //
314 // Are checked as part of verification.
315
316 Ok(())
317 }
318
inspect_ca(&self, strict: bool) -> Result<(), ValidationError>319 pub fn inspect_ca(&self, strict: bool) -> Result<(), ValidationError> {
320 self.inspect_ca_at(strict, Time::now())
321 }
322
inspect_ca_at( &self, strict: bool, now: Time ) -> Result<(), ValidationError>323 pub fn inspect_ca_at(
324 &self, strict: bool, now: Time
325 ) -> Result<(), ValidationError> {
326 self.inspect_basics(strict, now)?;
327 self.inspect_ca_basics(strict)?;
328 self.inspect_issued(strict)
329 }
330
inspect_ee(&self, strict: bool) -> Result<(), ValidationError>331 pub fn inspect_ee(&self, strict: bool) -> Result<(), ValidationError> {
332 self.inspect_ee_at(strict, Time::now())
333 }
334
inspect_ee_at( &self, strict: bool, now: Time ) -> Result<(), ValidationError>335 pub fn inspect_ee_at(
336 &self, strict: bool, now: Time
337 ) -> Result<(), ValidationError> {
338 self.inspect_basics(strict, now)?;
339 self.inspect_issued(strict)?;
340
341 // 4.8.1. Basic Constraints: Must not be present.
342 if self.basic_ca.is_some(){
343 xerr!(return Err(ValidationError))
344 }
345
346 // 4.8.4. Key Usage. Bits for CA or not CA have been checked during
347 // parsing already.
348 if self.key_usage != KeyUsage::Ee {
349 xerr!(return Err(ValidationError))
350 }
351
352 // 4.8.8. Subject Information Access. We need the signed object
353 // but not the other ones.
354 if self.ca_repository.is_some() || self.rpki_manifest.is_some()
355 || self.signed_object.is_none()
356 {
357 xerr!(return Err(ValidationError))
358 }
359
360 Ok(())
361 }
362
inspect_detached_ee( &self, strict: bool ) -> Result<(), ValidationError>363 pub fn inspect_detached_ee(
364 &self, strict: bool
365 ) -> Result<(), ValidationError> {
366 self.inspect_detached_ee_at(strict, Time::now())
367 }
368
inspect_detached_ee_at( &self, strict: bool, now: Time ) -> Result<(), ValidationError>369 pub fn inspect_detached_ee_at(
370 &self, strict: bool, now: Time
371 ) -> Result<(), ValidationError> {
372 self.inspect_basics(strict, now)?;
373 self.inspect_issued(strict)?;
374
375 // 4.8.1. Basic Constraints: Must not be present.
376 if self.basic_ca.is_some(){
377 xerr!(return Err(ValidationError))
378 }
379
380 // 4.8.4. Key Usage. Bits for CA or not CA have been checked during
381 // parsing already.
382 if self.key_usage != KeyUsage::Ee {
383 xerr!(return Err(ValidationError))
384 }
385
386 // 4.8.8. Subject Information Access. We allow the signed object one
387 // but not the other ones.
388 if self.ca_repository.is_some() || self.rpki_manifest.is_some() {
389 xerr!(return Err(ValidationError))
390 }
391
392 Ok(())
393 }
394
inspect_router( &self, strict: bool ) -> Result<(), ValidationError>395 pub fn inspect_router(
396 &self, strict: bool
397 ) -> Result<(), ValidationError> {
398 self.inspect_router_at(strict, Time::now())
399 }
400
inspect_router_at( &self, strict: bool, now: Time ) -> Result<(), ValidationError>401 pub fn inspect_router_at(
402 &self, strict: bool, now: Time
403 ) -> Result<(), ValidationError> {
404 // 4.2 Serial Number: must be unique over the CA. We cannot check
405 // here, and -- XXX --- probably don’t care?
406
407 // 4.3 Signature Algorithm: limited to those in RFC 6485. Already
408 // checked in parsing.
409 //
410 // However, RFC 5280 demands that the two mentions of the signature
411 // algorithm are the same. So we do that here.
412 if self.signature != self.signed_data.signature().algorithm() {
413 return Err(ValidationError)
414 }
415
416 // 4.4 Issuer: must have certain format.
417 Name::validate_rpki(&self.issuer, strict)?;
418
419 // 4.5 Subject: same as 4.4.
420 Name::validate_router(&self.subject, strict)?;
421
422 // 4.6 Validity. Check according to RFC 5280.
423 self.validity.validate_at(now)?;
424
425 // 4.7 Subject Public Key Info: limited algorithms.
426 if !self.subject_public_key_info().allow_router_cert() {
427 xerr!(return Err(ValidationError))
428 }
429
430 // 4.8.1. Basic Constraints. Must not be present.
431 if self.basic_ca.is_some(){
432 xerr!(return Err(ValidationError))
433 }
434
435 // 4.8.2. Subject Key Identifier. Must be the SHA-1 hash of the octets
436 // of the subjectPublicKey.
437 if self.subject_key_identifier() !=
438 self.subject_public_key_info().key_identifier() {
439 return Err(ValidationError)
440 }
441
442 // 4.8.3. Authority Key Identifier. Will be checked during
443 // verification later.
444
445 // 4.8.4. Key Usage. Must be EE.
446 if self.key_usage != KeyUsage::Ee {
447 xerr!(return Err(ValidationError))
448 }
449
450 // 4.8.5. Extended Key Usage.
451 //
452 // Must be present and contain at least the kp-bgpsec-router OID.
453 self.inspect_router_eku(strict)?;
454
455 // 4.8.6. CRL Distribution Points. There must be one.
456 if self.crl_uri().is_none() {
457 return Err(ValidationError)
458 }
459
460 // 4.8.7. Authority Information Access. Differs between TA and other
461 // certificates.
462
463 // 4.8.8. Subject Information Access. There must be none.
464 if self.ca_repository().is_some() || self.rpki_manifest().is_some()
465 || self.signed_object().is_some() || self.rpki_notify().is_some()
466 {
467 return Err(ValidationError)
468 }
469
470 // 4.8.9. Certificate Policies. XXX I think this can be ignored.
471 // At least for now.
472
473 // 4.8.10. IP Resources. Must not be present.
474 if self.v4_resources().is_present() || self.v6_resources().is_present()
475 {
476 return Err(ValidationError)
477 }
478
479 // 4.8.11. AS Resources. Differs between trust anchor and issued
480 // certificates.
481 if !self.as_resources().is_present()
482 || self.as_resources().is_inherited()
483 {
484 return Err(ValidationError)
485 }
486
487 Ok(())
488 }
489
490 //--- Verification
491
verify_ta( self, tal: Arc<TalInfo>, _strict: bool ) -> Result<ResourceCert, ValidationError>492 pub fn verify_ta(
493 self, tal: Arc<TalInfo>, _strict: bool
494 ) -> Result<ResourceCert, ValidationError> {
495 // 4.8.10. IP Resources. If present, mustn’t be "inherit".
496 let v4_resources = IpBlocks::from_resources(
497 self.v4_resources.clone()
498 )?;
499 let v6_resources = IpBlocks::from_resources(
500 self.v6_resources.clone()
501 )?;
502
503 // 4.8.11. AS Resources. If present, mustn’t be "inherit". That
504 // IP resources (logical) or AS resources are present has already
505 // been checked during parsing.
506 let as_resources = AsBlocks::from_resources(
507 self.as_resources.clone()
508 )?;
509
510 self.signed_data.verify_signature(
511 &self.subject_public_key_info
512 )?;
513
514 Ok(ResourceCert {
515 cert: self,
516 v4_resources,
517 v6_resources,
518 as_resources,
519 tal
520 })
521 }
522
verify_ta_ref( &self, _strict: bool ) -> Result<(), ValidationError>523 pub fn verify_ta_ref(
524 &self, _strict: bool
525 ) -> Result<(), ValidationError> {
526 // 4.8.10. IP Resources. If present, mustn’t be "inherit".
527 if self.v4_resources.is_inherited() {
528 return Err(ValidationError)
529 }
530 if self.v6_resources.is_inherited() {
531 return Err(ValidationError)
532 }
533
534 // 4.8.11. AS Resources. If present, mustn’t be "inherit".
535 if self.as_resources.is_inherited() {
536 return Err(ValidationError)
537 }
538
539 self.signed_data.verify_signature(
540 &self.subject_public_key_info
541 )?;
542
543 Ok(())
544 }
545
verify_ca( self, issuer: &ResourceCert, strict: bool ) -> Result<ResourceCert, ValidationError>546 pub fn verify_ca(
547 self, issuer: &ResourceCert, strict: bool
548 ) -> Result<ResourceCert, ValidationError> {
549 self.verify_issuer_claim(issuer, strict)?;
550 self.verify_signature(issuer, strict)?;
551 self.verify_resources(issuer, strict)
552 }
553
verify_ee( self, issuer: &ResourceCert, strict: bool ) -> Result<ResourceCert, ValidationError>554 pub fn verify_ee(
555 self, issuer: &ResourceCert, strict: bool
556 ) -> Result<ResourceCert, ValidationError> {
557 self.verify_issuer_claim(issuer, strict)?;
558 self.verify_signature(issuer, strict)?;
559 self.verify_resources(issuer, strict)
560 }
561
verify_router( &self, issuer: &ResourceCert, strict: bool ) -> Result<(), ValidationError>562 pub fn verify_router(
563 &self, issuer: &ResourceCert, strict: bool
564 ) -> Result<(), ValidationError> {
565 self.verify_issuer_claim(issuer, strict)?;
566 self.verify_signature(issuer, strict)?;
567 self.verify_as_resources(issuer, strict)
568 }
569
570
571 //--- Validation Components
572
573 /// Inspects basic compliance with section 4 of RFC 6487.
inspect_basics( &self, strict: bool, now: Time ) -> Result<(), ValidationError>574 fn inspect_basics(
575 &self,
576 strict: bool,
577 now: Time
578 ) -> Result<(), ValidationError> {
579 // The following lists all such constraints in the RFC, noting those
580 // that we cannot check here.
581
582 // 4.2 Serial Number: must be unique over the CA. We cannot check
583 // here, and -- XXX --- probably don’t care?
584
585 // 4.3 Signature Algorithm: limited to those in RFC 6485. Already
586 // checked in parsing.
587 //
588 // However, RFC 5280 demands that the two mentions of the signature
589 // algorithm are the same. So we do that here.
590 if self.signature != self.signed_data.signature().algorithm() {
591 return Err(ValidationError)
592 }
593
594 // 4.4 Issuer: must have certain format.
595 Name::validate_rpki(&self.issuer, strict)?;
596
597 // 4.5 Subject: same as 4.4.
598 Name::validate_rpki(&self.subject, strict)?;
599
600 // 4.6 Validity. Check according to RFC 5280.
601 self.validity.validate_at(now)?;
602
603 // 4.7 Subject Public Key Info: limited algorithms.
604 if !self.subject_public_key_info().allow_rpki_cert() {
605 xerr!(return Err(ValidationError))
606 }
607
608 // 4.8.1. Basic Constraints. Differing requirements for CA and EE
609 // certificates.
610
611 // 4.8.2. Subject Key Identifier. Must be the SHA-1 hash of the octets
612 // of the subjectPublicKey.
613 if self.subject_key_identifier() !=
614 self.subject_public_key_info().key_identifier() {
615 return Err(ValidationError)
616 }
617
618 // 4.8.3. Authority Key Identifier. Differing requirements of TA and
619 // other certificates.
620
621 // 4.8.4. Key Usage. Differs between CA and EE certificates.
622
623 // 4.8.5. Extended Key Usage. Must not be present for the kind of
624 // certificates we use here.
625 if self.extended_key_usage().is_some() {
626 return Err(ValidationError)
627 }
628
629 // 4.8.6. CRL Distribution Points. Differs between TA and other
630 // certificates.
631
632 // 4.8.7. Authority Information Access. Differs between TA and other
633 // certificates.
634
635 // 4.8.8. Subject Information Access. Differs between CA and EE
636 // certificates.
637
638 // 4.8.9. Certificate Policies. XXX I think this can be ignored.
639 // At least for now.
640
641 // 4.8.10. IP Resources. Differs between trust anchor and issued
642 // certificates.
643
644 // 4.8.11. AS Resources. Differs between trust anchor and issued
645 // certificates.
646
647 Ok(())
648 }
649
inspect_issued(&self, _strict: bool) -> Result<(), ValidationError>650 fn inspect_issued(&self, _strict: bool) -> Result<(), ValidationError> {
651 // 4.8.6. CRL Distribution Points. There must be one.
652 if self.crl_uri().is_none() {
653 return Err(ValidationError)
654 }
655
656 Ok(())
657 }
658
659 /// Validates that the certificate is a valid CA certificate.
660 ///
661 /// Checks the parts that are common in normal and trust anchor CA
662 /// certificates.
inspect_ca_basics( &self, _strict: bool ) -> Result<(), ValidationError>663 fn inspect_ca_basics(
664 &self,
665 _strict: bool
666 ) -> Result<(), ValidationError> {
667 // 4.8.1. Basic Constraints: For a CA it must be present (RFC6487)
668 // und the “cA” flag must be set (RFC5280).
669 if self.basic_ca() != Some(true) {
670 return Err(ValidationError)
671 }
672
673 // 4.8.4. Key Usage. Bits for CA or not CA have been checked during
674 // parsing already.
675 if self.key_usage() != KeyUsage::Ca {
676 return Err(ValidationError)
677 }
678
679 // 4.8.8. Subject Information Access.
680 if self.ca_repository().is_none() || self.rpki_manifest().is_none()
681 || self.signed_object().is_some()
682 {
683 return Err(ValidationError)
684 }
685
686 Ok(())
687 }
688
689 /// Inspects a router certificate’s extended key usage.
inspect_router_eku( &self, _strict: bool ) -> Result<(), ValidationError>690 fn inspect_router_eku(
691 &self, _strict: bool
692 ) -> Result<(), ValidationError> {
693 match self.extended_key_usage() {
694 Some(captured) => {
695 // We already know that the content is a sequence of OIDs
696 // (that has been tested in take_extended_key_usage). So we
697 // can return successfully as soon as we find our OID.
698 let mut captured = captured.clone();
699 while let Some(oid) = captured.decode_partial(|cons| {
700 Oid::take_opt_from(cons)
701 })? {
702 if oid == oid::KP_BGPSEC_ROUTER {
703 return Ok(())
704 }
705 }
706 Err(ValidationError)
707 }
708 None => Err(ValidationError)
709 }
710 }
711
712 /// Verifies that the certificate claims to have been issued by `issuer`.
713 ///
714 /// This is only the first part of verification. You _must_ call
715 /// `verified_signature`, too.
verify_issuer_claim( &self, issuer: &ResourceCert, _strict: bool, ) -> Result<(), ValidationError>716 pub fn verify_issuer_claim(
717 &self,
718 issuer: &ResourceCert,
719 _strict: bool,
720 ) -> Result<(), ValidationError> {
721 // 4.8.3. Authority Key Identifier. Must be present and match the
722 // subject key ID of `issuer`.
723 if self.authority_key_identifier()
724 != Some(issuer.cert.subject_key_identifier())
725 {
726 return Err(ValidationError)
727 }
728
729 // 4.8.7. Authority Information Access. Must be present and contain
730 // the URI of the issuer certificate. Since we do top-down validation,
731 // we don’t really need that URI so – XXX – leave it unchecked for
732 // now.
733 if self.ca_issuer().is_none() {
734 return Err(ValidationError);
735 }
736
737 Ok(())
738 }
739
740 /// Validates the certificate’s signature.
verify_signature( &self, issuer: &Cert, _strict: bool ) -> Result<(), ValidationError>741 pub fn verify_signature(
742 &self,
743 issuer: &Cert,
744 _strict: bool
745 ) -> Result<(), ValidationError> {
746 self.signed_data.verify_signature(
747 issuer.subject_public_key_info()
748 )
749 }
750
751 /// Validates and extracts the IP and AS resources.
752 ///
753 /// Upon success, this converts the certificate into a `ResourceCert`.
verify_resources( self, issuer: &ResourceCert, _strict: bool ) -> Result<ResourceCert, ValidationError>754 fn verify_resources(
755 self,
756 issuer: &ResourceCert,
757 _strict: bool
758 ) -> Result<ResourceCert, ValidationError> {
759 Ok(ResourceCert {
760 // 4.8.10. IP Resources. If present, must be encompassed by or
761 // trimmed down to the issuer certificate.
762 v4_resources: issuer.v4_resources.validate_issued(
763 self.v4_resources(), self.overclaim
764 )?,
765 v6_resources: issuer.v6_resources.validate_issued(
766 self.v6_resources(), self.overclaim
767 )?,
768 // 4.8.11. AS Resources. If present, must be encompassed by or
769 // trimmed down to the issuer.
770 as_resources: issuer.as_resources.validate_issued(
771 self.as_resources(), self.overclaim()
772 )?,
773 cert: self,
774 tal: issuer.tal.clone(),
775 })
776 }
777
778 /// Validates the AS resources for router certificates.
verify_as_resources( &self, issuer: &ResourceCert, _strict: bool ) -> Result<(), ValidationError>779 fn verify_as_resources(
780 &self,
781 issuer: &ResourceCert,
782 _strict: bool
783 ) -> Result<(), ValidationError> {
784 let _ = issuer.as_resources.validate_issued(
785 self.as_resources(), self.overclaim()
786 )?;
787 Ok(())
788 }
789 }
790
791
792 //--- Deref, AsRef, and Borrow
793
794 impl ops::Deref for Cert {
795 type Target = TbsCert;
796
deref(&self) -> &Self::Target797 fn deref(&self) -> &Self::Target {
798 &self.tbs
799 }
800 }
801
802 impl AsRef<Cert> for Cert {
as_ref(&self) -> &Self803 fn as_ref(&self) -> &Self {
804 self
805 }
806 }
807
808 impl AsRef<TbsCert> for Cert {
as_ref(&self) -> &TbsCert809 fn as_ref(&self) -> &TbsCert {
810 &self.tbs
811 }
812 }
813
814 impl borrow::Borrow<TbsCert> for Cert {
borrow(&self) -> &TbsCert815 fn borrow(&self) -> &TbsCert {
816 &self.tbs
817 }
818 }
819
820
821 //--- Deserialize and Serialize
822
823 #[cfg(feature = "serde")]
824 impl serde::Serialize for Cert {
serialize<S: serde::Serializer>( &self, serializer: S ) -> Result<S::Ok, S::Error>825 fn serialize<S: serde::Serializer>(
826 &self, serializer: S
827 ) -> Result<S::Ok, S::Error> {
828 let bytes = self.to_captured().into_bytes();
829 let b64 = base64::encode(&bytes);
830 b64.serialize(serializer)
831 }
832 }
833
834 #[cfg(feature = "serde")]
835 impl<'de> serde::Deserialize<'de> for Cert {
deserialize<D: serde::Deserializer<'de>>( deserializer: D ) -> Result<Self, D::Error>836 fn deserialize<D: serde::Deserializer<'de>>(
837 deserializer: D
838 ) -> Result<Self, D::Error> {
839 use serde::de;
840
841 let string = String::deserialize(deserializer)?;
842 let decoded = base64::decode(&string).map_err(de::Error::custom)?;
843 let bytes = Bytes::from(decoded);
844 Cert::decode(bytes).map_err(de::Error::custom)
845 }
846 }
847
848
849 //------------ TbsCert -------------------------------------------------------
850
851 /// The data of a resource certificate.
852 #[derive(Clone, Debug)]
853 pub struct TbsCert {
854 /// The serial number.
855 serial_number: Serial,
856
857 /// The algorithm used for signing the certificate.
858 signature: SignatureAlgorithm,
859
860 /// The name of the issuer.
861 ///
862 /// It isn’t really relevant in RPKI.
863 issuer: Name,
864
865 /// The validity of the certificate.
866 validity: Validity,
867
868 /// The name of the subject of this certificate.
869 ///
870 /// This isn’t really relevant in RPKI.
871 subject: Name,
872
873 /// Information about the public key of this certificate.
874 subject_public_key_info: PublicKey,
875
876 /// Basic Constraints extension.
877 ///
878 /// The field indicates whether the extension is present and, if so,
879 /// whether the "cA" boolean is set. See 4.8.1. of RFC 6487.
880 basic_ca: Option<bool>,
881
882 /// Subject Key Identifier extension.
883 subject_key_identifier: KeyIdentifier,
884
885 /// Authority Key Identifier extension.
886 authority_key_identifier: Option<KeyIdentifier>,
887
888 /// Key Usage.
889 ///
890 key_usage: KeyUsage,
891
892 /// Extended Key Usage.
893 ///
894 /// The value is the content of the DER-encoded sequence of object
895 /// identifiers.
896 extended_key_usage: Option<Captured>,
897
898 // The following fields are lists of URIs. Each has to have at least one
899 // rsync or HTTPS URI but may contain more. We only support those primary
900 // URIs for now, so we don’t keep the full list but only the one URI we
901 // need.
902
903 /// CRL Distribution Points.
904 crl_uri: Option<uri::Rsync>,
905
906 /// Authority Information Access of type `id-ad-caIssuer`.
907 ca_issuer: Option<uri::Rsync>,
908
909 /// Subject Information Access of type `id-ad-caRepository`
910 ca_repository: Option<uri::Rsync>,
911
912 /// Subject Information Access of type `id-ad-rpkiManifest`
913 rpki_manifest: Option<uri::Rsync>,
914
915 /// Subject Information Access of type `id-ad-signedObject`
916 signed_object: Option<uri::Rsync>,
917
918 /// Subject Information Access of type `id-ad-rpkiNotify`
919 rpki_notify: Option<uri::Https>,
920
921 /// Certificate Policies
922 ///
923 /// Must be present and critical. RFC 6484 demands there to be a single
924 /// policy with a specific OID and no parameters. RFC 8630 adds a second
925 /// OID for a different way of handling overclaim of resources.
926 ///
927 /// We reflect this choice of policy with an overclaim mode.
928 overclaim: Overclaim,
929
930 /// IP Resources for the IPv4 address family.
931 v4_resources: IpResources,
932
933 /// IP Resources for the IPv6 address family.
934 v6_resources: IpResources,
935
936 /// AS Resources
937 as_resources: AsResources,
938 }
939
940
941 /// # Creation and Conversion
942 ///
943 impl TbsCert {
944 /// Creates a new value from the necessary data.
945 #[allow(clippy::too_many_arguments)]
new( serial_number: Serial, issuer: Name, validity: Validity, subject: Option<Name>, subject_public_key_info: PublicKey, key_usage: KeyUsage, overclaim: Overclaim, ) -> Self946 pub fn new(
947 serial_number: Serial,
948 issuer: Name,
949 validity: Validity,
950 subject: Option<Name>,
951 subject_public_key_info: PublicKey,
952 key_usage: KeyUsage,
953 overclaim: Overclaim,
954 ) -> Self {
955 Self {
956 serial_number,
957 signature: SignatureAlgorithm::default(),
958 issuer,
959 validity,
960 subject: {
961 subject.unwrap_or_else(||
962 subject_public_key_info.to_subject_name()
963 )
964 },
965 subject_key_identifier: {
966 KeyIdentifier::from_public_key(&subject_public_key_info)
967 },
968 subject_public_key_info,
969 basic_ca: None,
970 authority_key_identifier: None,
971 key_usage,
972 extended_key_usage: None,
973 crl_uri: None,
974 ca_issuer: None,
975 ca_repository: None,
976 rpki_manifest: None,
977 signed_object: None,
978 rpki_notify: None,
979 overclaim,
980 v4_resources: IpResources::missing(),
981 v6_resources: IpResources::missing(),
982 as_resources: AsResources::missing(),
983 }
984 }
985
986 /// Converts the value into a signed certificate.
into_cert<S: Signer>( self, signer: &S, key: &S::KeyId, ) -> Result<Cert, SigningError<S::Error>>987 pub fn into_cert<S: Signer>(
988 self,
989 signer: &S,
990 key: &S::KeyId,
991 ) -> Result<Cert, SigningError<S::Error>> {
992 let data = Captured::from_values(Mode::Der, self.encode_ref());
993 let signature = signer.sign(key, self.signature, &data)?;
994 Ok(Cert {
995 signed_data: SignedData::new(data, signature),
996 tbs: self
997 })
998 }
999 }
1000
1001
1002 /// # Data Access
1003 ///
1004 impl TbsCert {
1005 /// Returns the serial number of the certificate.
serial_number(&self) -> Serial1006 pub fn serial_number(&self) -> Serial {
1007 self.serial_number
1008 }
1009
1010 /// Set the serial number of the certificate.
set_serial_number<S: Into<Serial>>(&mut self, serial: S)1011 pub fn set_serial_number<S: Into<Serial>>(&mut self, serial: S) {
1012 self.serial_number = serial.into()
1013 }
1014
1015 /// Returns a reference to the issuer.
issuer(&self) -> &Name1016 pub fn issuer(&self) -> &Name {
1017 &self.issuer
1018 }
1019
1020 /// Sets the issuer.
set_issuer(&mut self, name: Name)1021 pub fn set_issuer(&mut self, name: Name) {
1022 self.issuer = name
1023 }
1024
1025 /// Returns a reference to the validity.
validity(&self) -> Validity1026 pub fn validity(&self) -> Validity {
1027 self.validity
1028 }
1029
1030 /// Sets the validity.
set_validity(&mut self, validity: Validity)1031 pub fn set_validity(&mut self, validity: Validity) {
1032 self.validity = validity
1033 }
1034
1035 /// Returns a reference to the subject.
subject(&self) -> &Name1036 pub fn subject(&self) -> &Name {
1037 &self.subject
1038 }
1039
1040 /// Sets the subject.
set_subject(&mut self, subject: Name)1041 pub fn set_subject(&mut self, subject: Name) {
1042 self.subject = subject
1043 }
1044
1045 /// Returns a reference to the public key.
subject_public_key_info(&self) -> &PublicKey1046 pub fn subject_public_key_info(&self) -> &PublicKey {
1047 &self.subject_public_key_info
1048 }
1049
1050 /// Sets the public key.
1051 ///
1052 /// This sets both the value of the `subject_public_key_info` field to
1053 /// the public key itself as well as the `subject_public_key_identifier`
1054 /// to the identifier of that key.
set_subject_public_key(&mut self, key: PublicKey)1055 pub fn set_subject_public_key(&mut self, key: PublicKey) {
1056 self.subject_key_identifier = KeyIdentifier::from_public_key(&key);
1057 self.subject_public_key_info = key;
1058 }
1059
1060 /// Returns the cA field of the basic constraints extension if present.
basic_ca(&self) -> Option<bool>1061 pub fn basic_ca(&self) -> Option<bool> {
1062 self.basic_ca
1063 }
1064
1065 /// Sets the basic constraints extension.
1066 ///
1067 /// If `value` is `None`, the extension will be absent. If it is some
1068 /// value, the boolean is the value of the `cA` field of the extension.
set_basic_ca(&mut self, value: Option<bool>)1069 pub fn set_basic_ca(&mut self, value: Option<bool>) {
1070 self.basic_ca = value
1071 }
1072
1073 /// Returns a reference to the subject key identifier.
1074 ///
1075 /// There is no method to set this extension as this happens automatically
1076 /// when the subject public key is set via [`set_subject_public_key`].
1077 ///
1078 /// [`set_subject_public_key`]: #method.set_subject_public_key
subject_key_identifier(&self) -> KeyIdentifier1079 pub fn subject_key_identifier(&self) -> KeyIdentifier {
1080 self.subject_key_identifier
1081 }
1082
1083 /// Returns a reference to the authority key identifier if present.
authority_key_identifier(&self) -> Option<KeyIdentifier>1084 pub fn authority_key_identifier(&self) -> Option<KeyIdentifier> {
1085 self.authority_key_identifier
1086 }
1087
1088 /// Sets the authority key identifier extension.
set_authority_key_identifier( &mut self, id: Option<KeyIdentifier> )1089 pub fn set_authority_key_identifier(
1090 &mut self,
1091 id: Option<KeyIdentifier>
1092 ) {
1093 self.authority_key_identifier = id
1094 }
1095
1096 /// Returns the key usage of the certificate.
key_usage(&self) -> KeyUsage1097 pub fn key_usage(&self) -> KeyUsage {
1098 self.key_usage
1099 }
1100
1101 /// Sets the key usage of the certificate.
set_key_usage(&mut self, key_usage: KeyUsage)1102 pub fn set_key_usage(&mut self, key_usage: KeyUsage) {
1103 self.key_usage = key_usage
1104 }
1105
1106 /// Returns a reference to the extended key usage if present.
1107 ///
1108 /// Since this field isn’t allowed in any certificate used for RPKI
1109 /// objects directly, we do not currently support setting this field.
extended_key_usage(&self) -> Option<&Captured>1110 pub fn extended_key_usage(&self) -> Option<&Captured> {
1111 self.extended_key_usage.as_ref()
1112 }
1113
1114 /// Returns a reference to the certificate’s CRL distribution point.
crl_uri(&self) -> Option<&uri::Rsync>1115 pub fn crl_uri(&self) -> Option<&uri::Rsync> {
1116 self.crl_uri.as_ref()
1117 }
1118
1119 /// Sets the CRL distribution point.
set_crl_uri(&mut self, uri: Option<uri::Rsync>)1120 pub fn set_crl_uri(&mut self, uri: Option<uri::Rsync>) {
1121 self.crl_uri = uri
1122 }
1123
1124 /// Returns a reference to *caIssuer* AIA rsync URI if present.
ca_issuer(&self) -> Option<&uri::Rsync>1125 pub fn ca_issuer(&self) -> Option<&uri::Rsync> {
1126 self.ca_issuer.as_ref()
1127 }
1128
1129 /// Sets the *caIssuer* AIA rsync URI.
set_ca_issuer(&mut self, uri: Option<uri::Rsync>)1130 pub fn set_ca_issuer(&mut self, uri: Option<uri::Rsync>) {
1131 self.ca_issuer= uri
1132 }
1133
1134 /// Returns a reference to the *caRepository* SIA rsync URI if present.
ca_repository(&self) -> Option<&uri::Rsync>1135 pub fn ca_repository(&self) -> Option<&uri::Rsync> {
1136 self.ca_repository.as_ref()
1137 }
1138
1139 /// Sets the *caRepository* SIA rsync URI.
set_ca_repository(&mut self, uri: Option<uri::Rsync>)1140 pub fn set_ca_repository(&mut self, uri: Option<uri::Rsync>) {
1141 self.ca_repository = uri
1142 }
1143
1144 /// Returns a reference to the *rpkiManifest* SIA rsync URI if present.
rpki_manifest(&self) -> Option<&uri::Rsync>1145 pub fn rpki_manifest(&self) -> Option<&uri::Rsync> {
1146 self.rpki_manifest.as_ref()
1147 }
1148
1149 /// Sets the *rpkiManifest* SIA rsync URI.
set_rpki_manifest(&mut self, uri: Option<uri::Rsync>)1150 pub fn set_rpki_manifest(&mut self, uri: Option<uri::Rsync>) {
1151 self.rpki_manifest = uri
1152 }
1153
1154 /// Returns a reference to the *signedObject* SIA rsync URI if present.
signed_object(&self) -> Option<&uri::Rsync>1155 pub fn signed_object(&self) -> Option<&uri::Rsync> {
1156 self.signed_object.as_ref()
1157 }
1158
1159 /// Sets the *signedObject* SIA rsync URI.
set_signed_object(&mut self, uri: Option<uri::Rsync>)1160 pub fn set_signed_object(&mut self, uri: Option<uri::Rsync>) {
1161 self.signed_object = uri
1162 }
1163
1164 /// Returns a reference to the *rpkiNotify* SIA HTTPS URI if present.
rpki_notify(&self) -> Option<&uri::Https>1165 pub fn rpki_notify(&self) -> Option<&uri::Https> {
1166 self.rpki_notify.as_ref()
1167 }
1168
1169 /// Sets the *rpkiNotify* SIA HTTPS URI.
set_rpki_notify(&mut self, uri: Option<uri::Https>)1170 pub fn set_rpki_notify(&mut self, uri: Option<uri::Https>) {
1171 self.rpki_notify = uri
1172 }
1173
1174 /// Returns the overclaim mode of the certificate.
overclaim(&self) -> Overclaim1175 pub fn overclaim(&self) -> Overclaim {
1176 self.overclaim
1177 }
1178
1179 /// Sets the overclaim mode of the certificate.
set_overclaim(&mut self, overclaim: Overclaim)1180 pub fn set_overclaim(&mut self, overclaim: Overclaim) {
1181 self.overclaim = overclaim
1182 }
1183
1184 /// Returns a reference to the IPv4 address resources if present.
v4_resources(&self) -> &IpResources1185 pub fn v4_resources(&self) -> &IpResources {
1186 &self.v4_resources
1187 }
1188
1189 /// Set the IPv4 address resources.
set_v4_resources(&mut self, resources: IpResources)1190 pub fn set_v4_resources(&mut self, resources: IpResources) {
1191 self.v4_resources = resources
1192 }
1193
1194 /// Sets the IPv4 address resources to inherit.
set_v4_resources_inherit(&mut self)1195 pub fn set_v4_resources_inherit(&mut self) {
1196 self.set_v4_resources(IpResources::inherit())
1197 }
1198
1199 /// Builds the blocks IPv4 address resources.
build_v4_resource_blocks<F>(&mut self, op: F) where F: FnOnce(&mut IpBlocksBuilder)1200 pub fn build_v4_resource_blocks<F>(&mut self, op: F)
1201 where F: FnOnce(&mut IpBlocksBuilder) {
1202 let mut builder = IpResourcesBuilder::new();
1203 builder.blocks(op);
1204 self.set_v4_resources(builder.finalize())
1205 }
1206
1207 /// Builds the IPv4 address resources from an iterator over blocks.
v4_resources_from_iter<I>(&mut self, iter: I) where I: IntoIterator<Item=IpBlock>1208 pub fn v4_resources_from_iter<I>(&mut self, iter: I)
1209 where I: IntoIterator<Item=IpBlock> {
1210 self.v4_resources = IpResources::blocks(IpBlocks::from_iter(iter))
1211 }
1212
1213 /// Returns a reference to the IPv6 address resources if present.
v6_resources(&self) -> &IpResources1214 pub fn v6_resources(&self) -> &IpResources {
1215 &self.v6_resources
1216 }
1217
1218 /// Set the IPv6 address resources.
set_v6_resources(&mut self, resources: IpResources)1219 pub fn set_v6_resources(&mut self, resources: IpResources) {
1220 self.v6_resources = resources
1221 }
1222
1223 /// Sets the IPv6 address resources to inherit.
set_v6_resources_inherit(&mut self)1224 pub fn set_v6_resources_inherit(&mut self) {
1225 self.set_v6_resources(IpResources::inherit())
1226 }
1227
1228 /// Builds the blocks IPv6 address resources.
build_v6_resource_blocks<F>(&mut self, op: F) where F: FnOnce(&mut IpBlocksBuilder)1229 pub fn build_v6_resource_blocks<F>(&mut self, op: F)
1230 where F: FnOnce(&mut IpBlocksBuilder) {
1231 let mut builder = IpResourcesBuilder::new();
1232 builder.blocks(op);
1233 self.set_v6_resources(builder.finalize())
1234 }
1235
1236 /// Builds the IPv6 address resources from an iterator over blocks
v6_resources_from_iter<I>(&mut self, iter: I) where I: IntoIterator<Item=IpBlock>1237 pub fn v6_resources_from_iter<I>(&mut self, iter: I)
1238 where I: IntoIterator<Item=IpBlock> {
1239 self.v6_resources = IpResources::blocks(IpBlocks::from_iter(iter))
1240 }
1241
1242 /// Returns whether the certificate has any IP resources at all.
has_ip_resources(&self) -> bool1243 pub fn has_ip_resources(&self) -> bool {
1244 self.v4_resources.is_present() || self.v6_resources().is_present()
1245 }
1246
1247 /// Returns a reference to the AS resources.
as_resources(&self) -> &AsResources1248 pub fn as_resources(&self) -> &AsResources {
1249 &self.as_resources
1250 }
1251
1252 /// Set the AS resources.
set_as_resources(&mut self, resources: AsResources)1253 pub fn set_as_resources(&mut self, resources: AsResources) {
1254 self.as_resources = resources
1255 }
1256
1257 /// Sets the AS resources to inherit.
set_as_resources_inherit(&mut self)1258 pub fn set_as_resources_inherit(&mut self) {
1259 self.set_as_resources(AsResources::inherit())
1260 }
1261
1262 /// Builds the blocks AS resources.
build_as_resource_blocks<F>(&mut self, op: F) where F: FnOnce(&mut AsBlocksBuilder)1263 pub fn build_as_resource_blocks<F>(&mut self, op: F)
1264 where F: FnOnce(&mut AsBlocksBuilder) {
1265 let mut builder = AsResourcesBuilder::new();
1266 builder.blocks(op);
1267 self.set_as_resources(builder.finalize())
1268 }
1269
1270 /// Builds the AS resources from an iterator over blocks.
as_resources_from_iter<I>(&mut self, iter: I) where I: IntoIterator<Item = AsBlock>1271 pub fn as_resources_from_iter<I>(&mut self, iter: I)
1272 where I: IntoIterator<Item = AsBlock> {
1273 self.as_resources = AsResources::blocks(AsBlocks::from_iter(iter))
1274 }
1275
1276 /// Returns whether this is a CA certificate if validation succeeds.
is_ca(&self) -> bool1277 pub fn is_ca(&self) -> bool {
1278 self.basic_ca.unwrap_or(false)
1279 }
1280
1281 /// Returns whether this is a self-signed certificate if valid.
is_self_signed(&self) -> bool1282 pub fn is_self_signed(&self) -> bool {
1283 match self.authority_key_identifier {
1284 Some(aki) => aki == self.subject_key_identifier,
1285 None => true
1286 }
1287 }
1288 }
1289
1290
1291 /// # Decoding and Encoding
1292 ///
1293 impl TbsCert {
1294 /// Parses the content of a Certificate sequence.
from_constructed<S: decode::Source>( cons: &mut decode::Constructed<S> ) -> Result<Self, S::Err>1295 pub fn from_constructed<S: decode::Source>(
1296 cons: &mut decode::Constructed<S>
1297 ) -> Result<Self, S::Err> {
1298 cons.take_sequence(|cons| {
1299 // version [0] EXPLICIT Version DEFAULT v1.
1300 // -- we need extensions so apparently, we want v3 which,
1301 // confusingly, is 2.
1302 cons.take_constructed_if(Tag::CTX_0, |c| c.skip_u8_if(2))?;
1303
1304 let serial_number = Serial::take_from(cons)?;
1305 let signature = SignatureAlgorithm::x509_take_from(cons)?;
1306 let issuer = Name::take_from(cons)?;
1307 let validity = Validity::take_from(cons)?;
1308 let subject = Name::take_from(cons)?;
1309 let subject_public_key_info = PublicKey::take_from(cons)?;
1310
1311
1312 // issuerUniqueID and subjectUniqueID must not be present in
1313 // resource certificates. So extension is next.
1314
1315 let mut basic_ca = None;
1316 let mut subject_key_id = None;
1317 let mut authority_key_id = None;
1318 let mut key_usage = None;
1319 let mut extended_key_usage = None;
1320 let mut crl_uri = None;
1321 let mut ca_issuer = None;
1322 let mut sia = None;
1323 let mut overclaim = None;
1324 let mut ip_resources = None;
1325 let mut ip_overclaim = None;
1326 let mut as_resources = None;
1327 let mut as_overclaim = None;
1328
1329 cons.take_constructed_if(Tag::CTX_3, |c| c.take_sequence(|cons| {
1330 while let Some(()) = cons.take_opt_sequence(|cons| {
1331 let id = Oid::take_from(cons)?;
1332 let critical = cons.take_opt_bool()?.unwrap_or(false);
1333 let value = OctetString::take_from(cons)?;
1334 Mode::Der.decode(value.to_source(), |content| {
1335 if id == oid::CE_BASIC_CONSTRAINTS {
1336 Self::take_basic_constraints(
1337 content, &mut basic_ca
1338 )
1339 } else if id == oid::CE_SUBJECT_KEY_IDENTIFIER {
1340 Self::take_subject_key_identifier(
1341 content, &mut subject_key_id
1342 )
1343 } else if id == oid::CE_AUTHORITY_KEY_IDENTIFIER {
1344 Self::take_authority_key_identifier(
1345 content, &mut authority_key_id
1346 )
1347 } else if id == oid::CE_KEY_USAGE {
1348 Self::take_key_usage(
1349 content, &mut key_usage
1350 )
1351 } else if id == oid::CE_EXTENDED_KEY_USAGE {
1352 Self::take_extended_key_usage(
1353 content, &mut extended_key_usage
1354 )
1355 } else if id == oid::CE_CRL_DISTRIBUTION_POINTS {
1356 Self::take_crl_distribution_points(
1357 content, &mut crl_uri
1358 )
1359 } else if id == oid::PE_AUTHORITY_INFO_ACCESS {
1360 Self::take_authority_info_access(
1361 content, &mut ca_issuer
1362 )
1363 } else if id == oid::PE_SUBJECT_INFO_ACCESS {
1364 Self::take_subject_info_access(
1365 content, &mut sia
1366 )
1367 } else if id == oid::CE_CERTIFICATE_POLICIES {
1368 Self::take_certificate_policies(
1369 content, &mut overclaim
1370 )
1371 } else if let Some(m) = Overclaim::from_ip_res(&id) {
1372 ip_overclaim = Some(m);
1373 Self::take_ip_resources(content, &mut ip_resources)
1374 } else if let Some(m) = Overclaim::from_as_res(&id) {
1375 as_overclaim = Some(m);
1376 Self::take_as_resources(content, &mut as_resources)
1377 } else if critical {
1378 xerr!(Err(decode::Malformed))
1379 } else {
1380 // RFC 5280 says we can ignore non-critical
1381 // extensions we don’t know of. RFC 6487
1382 // agrees. So let’s do that.
1383 Ok(())
1384 }
1385 })?;
1386 Ok(())
1387 })? { }
1388 Ok(())
1389 }))?;
1390
1391 if ip_resources.is_none() && as_resources.is_none() {
1392 xerr!(return Err(decode::Malformed.into()))
1393 }
1394 if ip_resources.is_some() && ip_overclaim != overclaim {
1395 xerr!(return Err(decode::Malformed.into()))
1396 }
1397 if as_resources.is_some() && as_overclaim != overclaim {
1398 xerr!(return Err(decode::Malformed.into()))
1399 }
1400 let (v4_resources, v6_resources) = match ip_resources {
1401 Some(res) => res,
1402 None => (None, None)
1403 };
1404 let (ca_repository, rpki_manifest, signed_object, rpki_notify) = {
1405 match sia {
1406 Some(sia) => (
1407 sia.ca_repository, sia.rpki_manifest,
1408 sia.signed_object, sia.rpki_notify
1409 ),
1410 None => (None, None, None, None)
1411 }
1412 };
1413
1414 Ok(Self {
1415 serial_number,
1416 signature,
1417 issuer,
1418 validity,
1419 subject,
1420 subject_public_key_info,
1421 basic_ca,
1422 subject_key_identifier:
1423 subject_key_id.ok_or(decode::Malformed)?,
1424 authority_key_identifier: authority_key_id,
1425 key_usage: key_usage.ok_or(decode::Malformed)?,
1426 extended_key_usage,
1427 crl_uri,
1428 ca_issuer,
1429 ca_repository,
1430 rpki_manifest,
1431 signed_object,
1432 rpki_notify,
1433 overclaim: overclaim.ok_or(decode::Malformed)?,
1434 v4_resources: v4_resources.unwrap_or_else(
1435 IpResources::missing
1436 ),
1437 v6_resources: v6_resources.unwrap_or_else(
1438 IpResources::missing
1439 ),
1440 as_resources: as_resources.unwrap_or_else(
1441 AsResources::missing
1442 ),
1443 })
1444 })
1445 }
1446
1447 /// Parses the Basic Constraints extension.
1448 ///
1449 /// ```text
1450 /// BasicConstraints ::= SEQUENCE {
1451 /// cA BOOLEAN DEFAULT FALSE,
1452 /// pathLenConstraint INTEGER (0..MAX) OPTIONAL
1453 /// }
1454 /// ```
1455 ///
1456 /// For resource certificates, the extension must be critical. It must be
1457 /// present for CA certificates and must not be present for EE
1458 /// certificates. RFC 6487 says that the issued decides whether the cA
1459 /// boolean is to be set or not, but for all CA certificates it must be
1460 /// set (required indirectly by requiring the keyCertSign bit set in
1461 /// the key usage extension) so really it must always be true if the
1462 /// extension is present.
1463 ///
1464 /// The pathLenConstraint field must not be present.
take_basic_constraints<S: decode::Source>( cons: &mut decode::Constructed<S>, basic_ca: &mut Option<bool>, ) -> Result<(), S::Err>1465 pub(crate) fn take_basic_constraints<S: decode::Source>(
1466 cons: &mut decode::Constructed<S>,
1467 basic_ca: &mut Option<bool>,
1468 ) -> Result<(), S::Err> {
1469 update_once(basic_ca, || {
1470 cons.take_sequence(|cons| cons.take_opt_bool())
1471 .map(|ca| ca.unwrap_or(false))
1472 })
1473 }
1474
1475 /// Parses the Subject Key Identifier extension.
1476 ///
1477 /// ```text
1478 /// SubjectKeyIdentifier ::= KeyIdentifier
1479 /// ```
1480 ///
1481 /// The extension must be present and contain the 160 bit SHA-1 hash of
1482 /// the value of the DER-encoded bit string of the subject public key.
1483 ///
1484 /// Conforming CAs MUST mark this extension as non-critical.
take_subject_key_identifier<S: decode::Source>( cons: &mut decode::Constructed<S>, subject_key_id: &mut Option<KeyIdentifier>, ) -> Result<(), S::Err>1485 fn take_subject_key_identifier<S: decode::Source>(
1486 cons: &mut decode::Constructed<S>,
1487 subject_key_id: &mut Option<KeyIdentifier>,
1488 ) -> Result<(), S::Err> {
1489 update_once(subject_key_id, || KeyIdentifier::take_from(cons))
1490 }
1491
1492 /// Parses the Authority Key Identifier extension.
1493 ///
1494 /// ```text
1495 /// AuthorityKeyIdentifier ::= SEQUENCE {
1496 /// keyIdentifier [0] KeyIdentifier OPTIONAL,
1497 /// authorityCertIssuer [1] GeneralNames OPTIONAL,
1498 /// authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL }
1499 /// ```
1500 ///
1501 /// Must be present except in self-signed CA certificates where it is
1502 /// optional. The keyIdentifier field must be present, the other must not
1503 /// be.
take_authority_key_identifier<S: decode::Source>( cons: &mut decode::Constructed<S>, authority_key_id: &mut Option<KeyIdentifier>, ) -> Result<(), S::Err>1504 fn take_authority_key_identifier<S: decode::Source>(
1505 cons: &mut decode::Constructed<S>,
1506 authority_key_id: &mut Option<KeyIdentifier>,
1507 ) -> Result<(), S::Err> {
1508 update_once(authority_key_id, || {
1509 cons.take_sequence(|cons| {
1510 cons.take_value_if(Tag::CTX_0, KeyIdentifier::from_content)
1511 })
1512 })
1513 }
1514
1515 /// Parses the Key Usage extension.
1516 ///
1517 /// ```text
1518 /// KeyUsage ::= BIT STRING {
1519 /// digitalSignature (0),
1520 /// nonRepudiation (1), -- recent editions of X.509 have
1521 /// -- renamed this bit to contentCommitment
1522 /// keyEncipherment (2),
1523 /// dataEncipherment (3),
1524 /// keyAgreement (4),
1525 /// keyCertSign (5),
1526 /// cRLSign (6),
1527 /// encipherOnly (7),
1528 /// decipherOnly (8) }
1529 ///
1530 /// Must be present. In CA certificates, keyCertSign and
1531 /// CRLSign must be set, in EE certificates, digitalSignatures must be
1532 /// set.
take_key_usage<S: decode::Source>( cons: &mut decode::Constructed<S>, key_usage: &mut Option<KeyUsage> ) -> Result<(), S::Err>1533 pub(crate) fn take_key_usage<S: decode::Source>(
1534 cons: &mut decode::Constructed<S>,
1535 key_usage: &mut Option<KeyUsage>
1536 ) -> Result<(), S::Err> {
1537 update_once(key_usage, || {
1538 let bits = BitString::take_from(cons)?;
1539 if bits.bit(5) && bits.bit(6) {
1540 Ok(KeyUsage::Ca)
1541 }
1542 else if bits.bit(0) {
1543 Ok(KeyUsage::Ee)
1544 }
1545 else {
1546 Err(decode::Malformed.into())
1547 }
1548 })
1549 }
1550
1551 /// Parses the Extended Key Usage extension.
1552 ///
1553 /// ```text
1554 /// ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
1555 /// KeyPurposeId ::= OBJECT IDENTIFIER
1556 /// ```
1557 ///
1558 /// May only be present in EE certificates issued to devices.
take_extended_key_usage<S: decode::Source>( cons: &mut decode::Constructed<S>, extended_key_usage: &mut Option<Captured> ) -> Result<(), S::Err>1559 pub(crate) fn take_extended_key_usage<S: decode::Source>(
1560 cons: &mut decode::Constructed<S>,
1561 extended_key_usage: &mut Option<Captured>
1562 ) -> Result<(), S::Err> {
1563 update_once(extended_key_usage, || {
1564 let res = cons.take_sequence(|c| c.capture_all())?;
1565 res.clone().decode(|cons| {
1566 Oid::skip_in(cons)?;
1567 while Oid::skip_opt_in(cons)?.is_some() { }
1568 Ok(res)
1569 }).map_err(Into::into)
1570 })
1571 }
1572
1573 /// Parses the CRL Distribution Points extension.
1574 ///
1575 /// ```text
1576 /// CRLDistributionPoints ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint
1577 ///
1578 /// DistributionPoint ::= SEQUENCE {
1579 /// distributionPoint [0] DistributionPointName OPTIONAL,
1580 /// reasons [1] ReasonFlags OPTIONAL,
1581 /// cRLIssuer [2] GeneralNames OPTIONAL }
1582 ///
1583 /// DistributionPointName ::= CHOICE {
1584 /// fullName [0] GeneralNames,
1585 /// nameRelativeToCRLIssuer [1] RelativeDistinguishedName }
1586 /// ```
1587 ///
1588 /// Must be present except in self-signed certificates.
1589 ///
1590 /// It must contain exactly one Distribution Point. Only its
1591 /// distributionPoint field must be present and it must contain
1592 /// the fullName choice which can be one or more uniformResourceIdentifier
1593 /// choices.
take_crl_distribution_points<S: decode::Source>( cons: &mut decode::Constructed<S>, crl_uri: &mut Option<uri::Rsync> ) -> Result<(), S::Err>1594 fn take_crl_distribution_points<S: decode::Source>(
1595 cons: &mut decode::Constructed<S>,
1596 crl_uri: &mut Option<uri::Rsync>
1597 ) -> Result<(), S::Err> {
1598 update_once(crl_uri, || {
1599 // CRLDistributionPoints
1600 cons.take_sequence(|cons| {
1601 // DistributionPoint
1602 cons.take_sequence(|cons| {
1603 // distributionPoint
1604 cons.take_constructed_if(Tag::CTX_0, |cons| {
1605 // fullName
1606 cons.take_constructed_if(Tag::CTX_0, |cons| {
1607 // GeneralNames content
1608 take_general_names_content(
1609 cons, uri::Rsync::from_bytes
1610 )
1611 })
1612 })
1613 })
1614 })
1615 })
1616 }
1617
1618 /// Parses the Authority Information Access extension.
1619 ///
1620 /// ```text
1621 /// AuthorityInfoAccessSyntax ::=
1622 /// SEQUENCE SIZE (1..MAX) OF AccessDescription
1623 ///
1624 /// AccessDescription ::= SEQUENCE {
1625 /// accessMethod OBJECT IDENTIFIER,
1626 /// accessLocation GeneralName }
1627 /// ```
1628 ///
1629 /// Must be present except in self-signed certificates. Must contain
1630 /// exactly one entry with accessMethod id-ad-caIssuers and URIs in the
1631 /// generalName. There must be one rsync URI, there may be more. We only
1632 /// support the one, though, so we’ll ignore the rest.
take_authority_info_access<S: decode::Source>( cons: &mut decode::Constructed<S>, ca_issuer: &mut Option<uri::Rsync> ) -> Result<(), S::Err>1633 fn take_authority_info_access<S: decode::Source>(
1634 cons: &mut decode::Constructed<S>,
1635 ca_issuer: &mut Option<uri::Rsync>
1636 ) -> Result<(), S::Err> {
1637 update_once(ca_issuer, || {
1638 cons.take_sequence(|cons| {
1639 cons.take_sequence(|cons| {
1640 oid::AD_CA_ISSUERS.skip_if(cons)?;
1641 take_general_names_content(cons, uri::Rsync::from_bytes)
1642 })
1643 })
1644 })
1645 }
1646
1647 /// Parses the Subject Information Access extension.
1648 ///
1649 /// ```text
1650 /// SubjectInfoAccessSyntax ::=
1651 /// SEQUENCE SIZE (1..MAX) OF AccessDescription
1652 ///
1653 /// AccessDescription ::= SEQUENCE {
1654 /// accessMethod OBJECT IDENTIFIER,
1655 /// accessLocation GeneralName }
1656 /// ```
1657 ///
1658 /// Must be present.
1659 ///
1660 /// For CA certificates, there must be two AccessDescriptions, one with
1661 /// id-ad-caRepository and one with id-ad-rpkiManifest, both with rsync
1662 /// URIs. Additional id-ad-rpkiManifest descriptions may be present with
1663 /// additional access mechanisms for the manifest.
1664 ///
1665 /// Additionally, an id-ad-rpkiNotify may be present with a HTTPS URI.
1666 ///
1667 /// For EE certificates, there must at least one AccessDescription value
1668 /// with an id-ad-signedObject access method.
1669 ///
1670 /// Since we don’t necessarily know what kind of certificate we have yet,
1671 /// we may accept the wrong kind here. This needs to be checked later.
take_subject_info_access<S: decode::Source>( cons: &mut decode::Constructed<S>, sia: &mut Option<Sia>, ) -> Result<(), S::Err>1672 pub(crate) fn take_subject_info_access<S: decode::Source>(
1673 cons: &mut decode::Constructed<S>,
1674 sia: &mut Option<Sia>,
1675 ) -> Result<(), S::Err> {
1676 update_once(sia, || {
1677 let mut sia = Sia::default();
1678 let mut others_seen = false;
1679 cons.take_sequence(|cons| {
1680 while let Some(()) = cons.take_opt_sequence(|cons| {
1681 let oid = Oid::take_from(cons)?;
1682 if oid == oid::AD_CA_REPOSITORY {
1683 update_first(&mut sia.ca_repository, || {
1684 take_general_name(
1685 cons, uri::Rsync::from_bytes
1686 )
1687 })
1688 }
1689 else if oid == oid::AD_RPKI_MANIFEST {
1690 update_first(&mut sia.rpki_manifest, || {
1691 take_general_name(
1692 cons, uri::Rsync::from_bytes
1693 )
1694 })
1695 }
1696 else if oid == oid::AD_SIGNED_OBJECT {
1697 update_first(&mut sia.signed_object, || {
1698 take_general_name(
1699 cons, uri::Rsync::from_bytes
1700 )
1701 })
1702 }
1703 else if oid == oid::AD_RPKI_NOTIFY {
1704 update_first(&mut sia.rpki_notify, || {
1705 take_general_name(
1706 cons, uri::Https::from_bytes
1707 )
1708 })
1709 }
1710 else {
1711 others_seen = true;
1712 // XXX Presumably it is fine to just skip over these
1713 // things. Since this is DER, it can’t be tricked
1714 // into reading forever.
1715 cons.skip_all()
1716 }
1717 })? { }
1718 Ok(())
1719 })?;
1720 Ok(sia)
1721 })
1722 }
1723
1724 /// Parses the Certificate Policies extension.
1725 ///
1726 /// ```text
1727 /// certificatePolicies ::= SEQUENCE SIZE (1..MAX) OF PolicyInformation
1728 ///
1729 /// PolicyInformation ::= SEQUENCE {
1730 /// policyIdentifier CertPolicyId,
1731 /// policyQualifiers SEQUENCE SIZE (1..MAX) OF
1732 /// PolicyQualifierInfo OPTIONAL }
1733 ///
1734 /// CertPolicyId ::= OBJECT IDENTIFIER
1735 ///
1736 /// [...]
1737 /// ```
1738 ///
1739 /// Must be present. There are two policyIdentifiers for resource
1740 /// certificates. They define how we deal with overclaim of resources.
1741 /// The policyQualifiers are not interesting for us.
take_certificate_policies<S: decode::Source>( cons: &mut decode::Constructed<S>, overclaim: &mut Option<Overclaim>, ) -> Result<(), S::Err>1742 fn take_certificate_policies<S: decode::Source>(
1743 cons: &mut decode::Constructed<S>,
1744 overclaim: &mut Option<Overclaim>,
1745 ) -> Result<(), S::Err> {
1746 update_once(overclaim, || {
1747 cons.take_sequence(|cons| {
1748 cons.take_sequence(|cons| {
1749 let res = Overclaim::from_policy(&Oid::take_from(cons)?)?;
1750 // policyQualifiers. This is a sequence of sequences with
1751 // stuff we don’t really care about. Let’s skip all the
1752 // rest.
1753 cons.skip_all()?;
1754 Ok(res)
1755 })
1756 })
1757 })
1758 }
1759
1760 /// Parses the IP Resources extension.
take_ip_resources<S: decode::Source>( cons: &mut decode::Constructed<S>, ip_resources: &mut Option<(Option<IpResources>, Option<IpResources>)> ) -> Result<(), S::Err>1761 fn take_ip_resources<S: decode::Source>(
1762 cons: &mut decode::Constructed<S>,
1763 ip_resources: &mut Option<(Option<IpResources>, Option<IpResources>)>
1764 ) -> Result<(), S::Err> {
1765 update_once(ip_resources, || IpResources::take_families_from(cons))
1766 }
1767
1768 /// Parses the AS Resources extension.
take_as_resources<S: decode::Source>( cons: &mut decode::Constructed<S>, as_resources: &mut Option<AsResources> ) -> Result<(), S::Err>1769 fn take_as_resources<S: decode::Source>(
1770 cons: &mut decode::Constructed<S>,
1771 as_resources: &mut Option<AsResources>
1772 ) -> Result<(), S::Err> {
1773 update_once(as_resources, || {
1774 AsResources::take_from(cons)
1775 })
1776 }
1777
1778 /// Returns an encoder for the value.
encode_ref(&self) -> impl encode::Values + '_1779 pub fn encode_ref(&self) -> impl encode::Values + '_ {
1780 encode::sequence((
1781 encode::sequence_as(Tag::CTX_0, 2.encode()), // version
1782 self.serial_number.encode(),
1783 self.signature.x509_encode(),
1784 self.issuer.encode_ref(),
1785 self.validity.encode(),
1786 self.subject.encode_ref(),
1787 self.subject_public_key_info.encode_ref(),
1788 // no issuerUniqueID
1789 // no subjectUniqueID
1790 // extensions
1791 encode::sequence_as(Tag::CTX_3, encode::sequence((
1792 // Basic Constraints
1793 self.basic_ca.map(|ca| {
1794 encode_extension(
1795 &oid::CE_BASIC_CONSTRAINTS, true,
1796 encode::sequence(
1797 if ca {
1798 Some(ca.encode())
1799 }
1800 else {
1801 None
1802 }
1803 )
1804 )
1805 }),
1806
1807 // Subject Key Identifier
1808 encode_extension(
1809 &oid::CE_SUBJECT_KEY_IDENTIFIER, false,
1810 self.subject_key_identifier.encode_ref(),
1811 ),
1812
1813 // Authority Key Identifier
1814 self.authority_key_identifier.as_ref().map(|id| {
1815 encode_extension(
1816 &oid::CE_AUTHORITY_KEY_IDENTIFIER, false,
1817 encode::sequence(id.encode_ref_as(Tag::CTX_0))
1818 )
1819 }),
1820
1821 // Key Usage
1822 encode_extension(
1823 &oid::CE_KEY_USAGE, true,
1824 self.key_usage.encode()
1825 ),
1826
1827 // Extended Key Usage
1828 self.extended_key_usage.as_ref().map(|captured| {
1829 encode_extension(
1830 &oid::CE_EXTENDED_KEY_USAGE, false,
1831 encode::sequence(captured)
1832 )
1833 }),
1834
1835 // CRL Distribution Points
1836 self.crl_uri.as_ref().map(|uri| {
1837 encode_extension(
1838 &oid::CE_CRL_DISTRIBUTION_POINTS, false,
1839 encode::sequence( // CRLDistributionPoints
1840 encode::sequence( // DistributionPoint
1841 encode::sequence_as(Tag::CTX_0, // distrib.Pt.
1842 encode::sequence_as(Tag::CTX_0, // fullName
1843 uri.encode_general_name()
1844 )
1845 )
1846 )
1847 )
1848 )
1849 }),
1850
1851 // Authority Information Access
1852 self.ca_issuer.as_ref().map(|uri| {
1853 encode_extension(
1854 &oid::PE_AUTHORITY_INFO_ACCESS, false,
1855 encode::sequence(
1856 encode::sequence((
1857 oid::AD_CA_ISSUERS.encode(),
1858 uri.encode_general_name()
1859 ))
1860 )
1861 )
1862 }),
1863
1864 // Subject Information Access
1865 encode_extension(
1866 &oid::PE_SUBJECT_INFO_ACCESS, false,
1867 encode::sequence((
1868 self.ca_repository.as_ref().map(|uri| {
1869 encode::sequence((
1870 oid::AD_CA_REPOSITORY.encode(),
1871 uri.encode_general_name()
1872 ))
1873 }),
1874 self.rpki_manifest.as_ref().map(|uri| {
1875 encode::sequence((
1876 oid::AD_RPKI_MANIFEST.encode(),
1877 uri.encode_general_name()
1878 ))
1879 }),
1880 self.signed_object.as_ref().map(|uri| {
1881 encode::sequence((
1882 oid::AD_SIGNED_OBJECT.encode(),
1883 uri.encode_general_name()
1884 ))
1885 }),
1886 self.rpki_notify.as_ref().map(|uri| {
1887 encode::sequence((
1888 oid::AD_RPKI_NOTIFY.encode(),
1889 uri.encode_general_name()
1890 ))
1891 })
1892 ))
1893 ),
1894
1895 // Certificate Policies
1896 encode_extension(
1897 &oid::CE_CERTIFICATE_POLICIES, true,
1898 encode::sequence(
1899 encode::sequence(
1900 self.overclaim.policy_id().encode()
1901 // policyQualifiers sequence is optional
1902 )
1903 )
1904 ),
1905
1906 // IP Resources
1907 IpResources::encode_extension(
1908 self.overclaim(),
1909 self.v4_resources(),
1910 self.v6_resources()
1911 ),
1912
1913 // AS Resources
1914 self.as_resources.encode_extension(self.overclaim)
1915 )))
1916 ))
1917 }
1918 }
1919
1920
1921 //------------ Helpers for Decoding and Encoding -----------------------------
1922
1923 /// Parses a URI from the content of a GeneralNames sequence.
1924 ///
1925 /// ```text
1926 /// GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
1927 ///
1928 /// GeneralName ::= CHOICE {
1929 /// ...
1930 /// uniformResourceIdentifier [6] IA5String,
1931 /// ... }
1932 /// ```
1933 ///
1934 /// Takes the first name for which the closure returns successfully. Ignores
1935 /// values where the closure produces an error. If there is more than one case
1936 /// where the closure returns successfully, that’s an error, too.
take_general_names_content<S: decode::Source, F, T, E>( cons: &mut decode::Constructed<S>, mut op: F ) -> Result<T, S::Err> where F: FnMut(Bytes) -> Result<T, E>1937 fn take_general_names_content<S: decode::Source, F, T, E>(
1938 cons: &mut decode::Constructed<S>,
1939 mut op: F
1940 ) -> Result<T, S::Err>
1941 where F: FnMut(Bytes) -> Result<T, E> {
1942 let mut res = None;
1943 while let Some(()) = cons.take_opt_value_if(Tag::CTX_6, |content| {
1944 let uri = Ia5String::from_content(content)?;
1945 if let Ok(uri) = op(uri.into_bytes()) {
1946 if res.is_some() {
1947 xerr!(return Err(decode::Malformed.into()))
1948 }
1949 res = Some(uri)
1950 }
1951 Ok(())
1952 })? {}
1953 match res {
1954 Some(res) => Ok(res),
1955 None => xerr!(Err(decode::Malformed.into()))
1956 }
1957 }
1958
take_general_name<S: decode::Source, F, T, E>( cons: &mut decode::Constructed<S>, mut op: F ) -> Result<Option<T>, S::Err> where F: FnMut(Bytes) -> Result<T, E>1959 fn take_general_name<S: decode::Source, F, T, E>(
1960 cons: &mut decode::Constructed<S>,
1961 mut op: F
1962 ) -> Result<Option<T>, S::Err>
1963 where F: FnMut(Bytes) -> Result<T, E> {
1964 cons.take_value_if(Tag::CTX_6, |content| {
1965 Ia5String::from_content(content).map(|uri| {
1966 op(uri.into_bytes()).ok()
1967 })
1968 })
1969 }
1970
1971 /// Internal helper type for parsing Subject Information Access.
1972 #[derive(Clone, Debug, Default)]
1973 pub(crate) struct Sia {
1974 ca_repository: Option<uri::Rsync>,
1975 rpki_manifest: Option<uri::Rsync>,
1976 signed_object: Option<uri::Rsync>,
1977 rpki_notify: Option<uri::Https>,
1978 }
1979
1980 impl Sia {
ca_repository(&self) -> Option<&uri::Rsync>1981 pub(crate) fn ca_repository(&self) -> Option<&uri::Rsync> {
1982 self.ca_repository.as_ref()
1983 }
rpki_manifest(&self) -> Option<&uri::Rsync>1984 pub(crate) fn rpki_manifest(&self) -> Option<&uri::Rsync> {
1985 self.rpki_manifest.as_ref()
1986 }
rpki_notify(&self) -> Option<&uri::Https>1987 pub(crate) fn rpki_notify(&self) -> Option<&uri::Https> {
1988 self.rpki_notify.as_ref()
1989 }
1990 }
1991
1992
1993 //------------ CertBuilder ---------------------------------------------------
1994
1995 #[derive(Clone, Debug)]
1996 pub struct CertBuilder {
1997 // The following lists how all the parts to go into the final certificate
1998 // are to be generated. It also mentions all the parts that don’t need to
1999 // be stored in the builder.
2000
2001 //--- Certificate
2002 //
2003 // tbsCertificate: see below,
2004 // signatureAlgorithm and signature: generated when signing the final
2005 // certificate
2006
2007 //--- TBSCertificate
2008
2009 // Version.
2010 //
2011 // This is always present and v3, which really is 2.
2012
2013 /// Serial number.
2014 ///
2015 /// This is required for all certificates. The standard demands twenty
2016 /// digits, u128 gives us 38, so this should be fine.
2017 serial_number: u128,
2018
2019 /// Signature.
2020 ///
2021 /// This is the signature algorithm and must be identical to the one used
2022 /// on the outer value. Thus, it needs to be set when constructing the
2023 /// certificate for signing.
2024
2025 /// Issuer.
2026 ///
2027 /// This needs to be identical to the subject of the issuing certificate.
2028 /// It needs to be presented when creating the builder.
2029 issuer: Name,
2030
2031 /// Validity.
2032 ///
2033 /// This needs to be present for all certificates.
2034 validity: Validity,
2035
2036 /// Subject.
2037 ///
2038 /// This needs to be present for all certifications. In RPKI, we commonly
2039 /// derive the name from the public key of the certificate, so this is an
2040 /// option. If it is not set explicitly, we derive the name.
2041 subject: Option<Name>, // XXX NameBuilder?
2042
2043 /// Subject Public Key Info
2044 ///
2045 /// This is required for all certificates. However, because we sometimes
2046 /// use one-off certificates that only receive their key info very late
2047 /// in the process, we won’t store the key info but take it as an
2048 /// argument for encoding.
2049
2050 // Issuer Unique ID, Subject Unique ID
2051 //
2052 // These must not be present.
2053
2054 //--- Extensions
2055
2056 /// Basic Constraints
2057 ///
2058 /// Needs to be present and critical and the cA boolean set to true for
2059 /// a CA and TA certificate. We simply remember whether we are making a
2060 /// CA certificate here.
2061 ca: bool,
2062
2063 // Subject Key Identifier
2064 //
2065 // Must be present and non-critical. It is the SHA1 of the BIT STRING
2066 // of the Subject Public Key, so we take it from
2067 // subject_public_key_info.
2068
2069 /// Authority Key Identifier
2070 ///
2071 /// Must be present except in trust-anchor certificates and non-critical.
2072 /// It must contain the subject key identifier of issuing certificate.
2073 authority_key_identifier: Option<OctetString>,
2074
2075 // Key Usage.
2076 //
2077 // Must be present and critical. For CA certificates, keyCertSign and
2078 // CRLSign are set, for EE certificates, digitalSignature bit is set.
2079
2080 // Extended Key Usage
2081 //
2082 // This is only allowed in router keys. For now, we will not support
2083 // this.
2084
2085 /// CRL Distribution Points
2086 ///
2087 /// Must be present and non-critical except in self-signed certificates.
2088 /// For RPKI it is very restricted and boils down to a list of URIs. Most
2089 /// likely, it will be exactly one. So for now, we allow at most one.
2090 crl_distribution: Option<uri::Rsync>,
2091
2092 /// Authority Information Access
2093 ///
2094 /// Except for self-signed certificates, must be present and non-critical.
2095 /// There must be one rsync URI as a id-ad-caIssuer. Additional URIs may
2096 /// be present, but we don’t support that as of now.
2097 authority_info_access: Option<uri::Rsync>,
2098
2099 // Subject Information Access
2100 //
2101 // Must be present and non-critical. There are essentially three
2102 // access methods that may be present. id-ad-rpkiManifest points to the
2103 // manifest of a CA, id-ad-signedObject points to the signed object of
2104 // an EE certificate. id-ad-rpkiNotify points to the RRDP notification
2105 // file of a CA. We only support one of each and simply add whatever is
2106 // there.
2107
2108 /// Subject Information Access of type `id-ad-caRepository`
2109 ca_repository: Option<uri::Rsync>,
2110
2111 /// Subject Information Access of type `id-ad-rpkiManifest`
2112 rpki_manifest: Option<uri::Rsync>,
2113
2114 /// Subject Information Access of type `id-ad-signedObject`
2115 signed_object: Option<uri::Rsync>,
2116
2117 /// Subject Information Access of type `id-ad-rpkiNotify`
2118 rpki_notify: Option<uri::Https>,
2119
2120 /// Certificate Policies
2121 ///
2122 /// This is chosen via the value of the overclaim mode,
2123 overclaim: Overclaim,
2124
2125 /// IPv4 Resources
2126 ///
2127 /// One of the resources must be present. The IPv4 resources are part of
2128 /// the IP resources which, if present, it must be critical.
2129 v4_resources: IpResourcesBuilder,
2130
2131 /// IPv6 Resources
2132 ///
2133 /// One of the resources must be present. The IPv4 resources are part of
2134 /// the IP resources which, if present, it must be critical.
2135 v6_resources: IpResourcesBuilder,
2136
2137 /// AS Resources
2138 ///
2139 /// If present, it must be critical. One of the resources must be
2140 /// present.
2141 as_resources: AsResourcesBuilder,
2142 }
2143
2144 impl CertBuilder {
new( serial_number: u128, issuer: Name, validity: Validity, ca: bool ) -> Self2145 pub fn new(
2146 serial_number: u128,
2147 issuer: Name,
2148 validity: Validity,
2149 ca: bool
2150 ) -> Self {
2151 CertBuilder {
2152 serial_number,
2153 issuer,
2154 validity,
2155 subject: None,
2156 ca,
2157 authority_key_identifier: None,
2158 crl_distribution: None,
2159 authority_info_access: None,
2160 ca_repository: None,
2161 rpki_manifest: None,
2162 signed_object: None,
2163 rpki_notify: None,
2164 overclaim: Overclaim::Refuse,
2165 v4_resources: IpResourcesBuilder::new(),
2166 v6_resources: IpResourcesBuilder::new(),
2167 as_resources: AsResourcesBuilder::new(),
2168 }
2169 }
2170
subject(&mut self, name: Name) -> &mut Self2171 pub fn subject(&mut self, name: Name) -> &mut Self {
2172 self.subject = Some(name);
2173 self
2174 }
2175
authority_key_identifier( &mut self, id: OctetString ) -> &mut Self2176 pub fn authority_key_identifier(
2177 &mut self, id: OctetString
2178 ) -> &mut Self {
2179 self.authority_key_identifier = Some(id);
2180 self
2181 }
2182
crl_distribution(&mut self, uri: uri::Rsync) -> &mut Self2183 pub fn crl_distribution(&mut self, uri: uri::Rsync) -> &mut Self {
2184 self.crl_distribution = Some(uri);
2185 self
2186 }
2187
authority_info_access(&mut self, uri: uri::Rsync) -> &mut Self2188 pub fn authority_info_access(&mut self, uri: uri::Rsync) -> &mut Self {
2189 self.authority_info_access = Some(uri);
2190 self
2191 }
2192
ca_repository(&mut self, uri: uri::Rsync) -> &mut Self2193 pub fn ca_repository(&mut self, uri: uri::Rsync) -> &mut Self {
2194 self.ca_repository = Some(uri);
2195 self
2196 }
2197
rpki_manifest(&mut self, uri: uri::Rsync) -> &mut Self2198 pub fn rpki_manifest(&mut self, uri: uri::Rsync) -> &mut Self {
2199 self.rpki_manifest = Some(uri);
2200 self
2201 }
2202
signed_object(&mut self, uri: uri::Rsync) -> &mut Self2203 pub fn signed_object(&mut self, uri: uri::Rsync) -> &mut Self {
2204 self.signed_object = Some(uri);
2205 self
2206 }
2207
rpki_notify(&mut self, uri: uri::Https) -> &mut Self2208 pub fn rpki_notify(&mut self, uri: uri::Https) -> &mut Self {
2209 self.rpki_notify = Some(uri);
2210 self
2211 }
2212
overclaim(&mut self, overclaim: Overclaim) -> &mut Self2213 pub fn overclaim(&mut self, overclaim: Overclaim) -> &mut Self {
2214 self.overclaim = overclaim;
2215 self
2216 }
2217
inherit_v4(&mut self) -> &mut Self2218 pub fn inherit_v4(&mut self) -> &mut Self {
2219 self.v4_resources.inherit();
2220 self
2221 }
2222
inherit_v6(&mut self) -> &mut Self2223 pub fn inherit_v6(&mut self) -> &mut Self {
2224 self.v6_resources.inherit();
2225 self
2226 }
2227
inherit_as(&mut self) -> &mut Self2228 pub fn inherit_as(&mut self) -> &mut Self {
2229 self.as_resources.inherit();
2230 self
2231 }
2232
v4_blocks<F>(&mut self, build: F) -> &mut Self where F: FnOnce(&mut IpBlocksBuilder)2233 pub fn v4_blocks<F>(&mut self, build: F) -> &mut Self
2234 where F: FnOnce(&mut IpBlocksBuilder) {
2235 self.v4_resources.blocks(build);
2236 self
2237 }
2238
v6_blocks<F>(&mut self, build: F) -> &mut Self where F: FnOnce(&mut IpBlocksBuilder)2239 pub fn v6_blocks<F>(&mut self, build: F) -> &mut Self
2240 where F: FnOnce(&mut IpBlocksBuilder) {
2241 self.v6_resources.blocks(build);
2242 self
2243 }
2244
as_blocks<F>(&mut self, build: F) -> &mut Self where F: FnOnce(&mut AsBlocksBuilder)2245 pub fn as_blocks<F>(&mut self, build: F) -> &mut Self
2246 where F: FnOnce(&mut AsBlocksBuilder) {
2247 self.as_resources.blocks(build);
2248 self
2249 }
2250
2251 /// Finalizes the certificate and returns an encoder for it.
encode<S: Signer>( self, signer: &S, key: &S::KeyId, alg: SignatureAlgorithm, public_key: &PublicKey, ) -> Result<impl encode::Values, SigningError<S::Error>>2252 pub fn encode<S: Signer>(
2253 self,
2254 signer: &S,
2255 key: &S::KeyId,
2256 alg: SignatureAlgorithm,
2257 public_key: &PublicKey,
2258 ) -> Result<impl encode::Values, SigningError<S::Error>> {
2259 let tbs_cert = self.encode_tbs_cert(alg, public_key);
2260 let (alg, signature) = signer.sign(key, alg, &tbs_cert)?.unwrap();
2261 Ok(encode::sequence((
2262 tbs_cert,
2263 alg.x509_encode(),
2264 BitString::new(0, signature).encode()
2265 )))
2266 }
2267
encode_tbs_cert( mut self, alg: SignatureAlgorithm, public_key: &PublicKey, ) -> Captured2268 fn encode_tbs_cert(
2269 mut self,
2270 alg: SignatureAlgorithm,
2271 public_key: &PublicKey,
2272 ) -> Captured {
2273 if self.subject.is_none() {
2274 self.subject = Some(Name::from_pub_key(public_key))
2275 }
2276 Captured::from_values(Mode::Der, encode::sequence((
2277 encode::sequence_as(Tag::CTX_0, 2.encode()), // version
2278 self.serial_number.encode(),
2279 alg.x509_encode(),
2280 self.issuer.encode_ref(),
2281 self.validity.encode(),
2282 match self.subject.as_ref() {
2283 Some(subject) => encode::Choice2::One(subject.encode_ref()),
2284 None => {
2285 encode::Choice2::Two(
2286 public_key.encode_subject_name()
2287 )
2288 }
2289 },
2290 public_key.encode_ref(),
2291 // no issuerUniqueID, no subjectUniqueID
2292 encode::sequence_as(Tag::CTX_3, encode::sequence((
2293 // Basic Constraints
2294 if self.ca {
2295 Some(Self::extension(
2296 &oid::CE_BASIC_CONSTRAINTS, true,
2297 encode::sequence(true.encode())
2298 ))
2299 }
2300 else { None },
2301
2302 // Subject Key Identifier
2303 Self::extension(
2304 &oid::CE_SUBJECT_KEY_IDENTIFIER, false,
2305 OctetString::encode_slice(
2306 public_key.key_identifier()
2307 )
2308 ),
2309
2310 // Authority Key Identifier
2311 self.authority_key_identifier.as_ref().map(|id| {
2312 Self::extension(
2313 &oid::CE_AUTHORITY_KEY_IDENTIFIER, false,
2314 encode::sequence(id.encode_ref_as(Tag::CTX_0))
2315 )
2316 }),
2317
2318 // Key Usage
2319 Self::extension(
2320 &oid::CE_KEY_USAGE, true,
2321 if self.ca {
2322 // Bits 5 and 6 must be set.
2323 b"\x01\x06".encode_as(Tag::BIT_STRING)
2324 }
2325 else {
2326 // Bit 0 must be set.
2327 b"\x07\x80".encode_as(Tag::BIT_STRING)
2328 }
2329 ),
2330
2331 // Extended Key Usage: currently not supported.
2332
2333 // CRL Distribution Points
2334 self.crl_distribution.as_ref().map(|uri| {
2335 Self::extension(
2336 &oid::CE_CRL_DISTRIBUTION_POINTS, false,
2337 encode::sequence( // CRLDistributionPoints
2338 encode::sequence( // DistributionPoint
2339 encode::sequence_as(Tag::CTX_0, // distrib.Pt.
2340 encode::sequence_as(Tag::CTX_0, // fullName
2341 encode::sequence( // GeneralNames
2342 uri.encode_general_name()
2343 )
2344 )
2345 )
2346 )
2347 )
2348 )
2349 }),
2350
2351 // Authority Information Access
2352 self.authority_info_access.as_ref().map(|uri| {
2353 Self::extension(
2354 &oid::PE_AUTHORITY_INFO_ACCESS, false,
2355 encode::sequence(
2356 encode::sequence((
2357 oid::AD_CA_ISSUERS.encode(),
2358 uri.encode_general_name()
2359 ))
2360 )
2361 )
2362 }),
2363
2364 // Subject Information Access
2365 Self::extension(
2366 &oid::PE_SUBJECT_INFO_ACCESS, false,
2367 encode::sequence((
2368 self.ca_repository.as_ref().map(|uri| {
2369 encode::sequence((
2370 oid::AD_CA_REPOSITORY.encode(),
2371 uri.encode_general_name()
2372 ))
2373 }),
2374 self.rpki_manifest.as_ref().map(|uri| {
2375 encode::sequence((
2376 oid::AD_RPKI_MANIFEST.encode(),
2377 uri.encode_general_name()
2378 ))
2379 }),
2380 self.signed_object.as_ref().map(|uri| {
2381 encode::sequence((
2382 oid::AD_SIGNED_OBJECT.encode(),
2383 uri.encode_general_name()
2384 ))
2385 }),
2386 self.rpki_notify.as_ref().map(|uri| {
2387 encode::sequence((
2388 oid::AD_RPKI_NOTIFY.encode(),
2389 uri.encode_general_name()
2390 ))
2391 })
2392 ))
2393 ),
2394
2395 // Certificate Policies
2396 Self::extension(
2397 &oid::CE_CERTIFICATE_POLICIES, true,
2398 encode::sequence(
2399 encode::sequence(
2400 oid::CP_IPADDR_ASNUMBER.encode()
2401 )
2402 )
2403 ),
2404
2405 // IP Resources
2406 IpResources::encode_extension(
2407 self.overclaim,
2408 &self.v4_resources.finalize(),
2409 &self.v6_resources.finalize()
2410 ),
2411
2412 // AS Resources
2413 self.as_resources.finalize().encode_extension(
2414 self.overclaim
2415 ),
2416 )))
2417 )))
2418 }
2419
extension<V: encode::Values>( oid: &'static ConstOid, critical: bool, content: V ) -> impl encode::Values2420 pub(crate) fn extension<V: encode::Values>(
2421 oid: &'static ConstOid,
2422 critical: bool,
2423 content: V
2424 ) -> impl encode::Values {
2425 encode::sequence((
2426 oid.encode(),
2427 critical.encode(),
2428 OctetString::encode_wrapped(Mode::Der, content)
2429 ))
2430 }
2431 }
2432
2433
2434 //------------ ResourceCert --------------------------------------------------
2435
2436 /// A validated resource certificate.
2437 ///
2438 /// This differs from a normal [`Cert`] in that its IP and AS resources are
2439 /// resolved into concrete values.
2440 #[derive(Clone, Debug)]
2441 pub struct ResourceCert {
2442 /// The underlying resource certificate.
2443 cert: Cert,
2444
2445 /// The resolved IPv4 resources.
2446 v4_resources: IpBlocks,
2447
2448 /// The resolved IPv6 resources.
2449 v6_resources: IpBlocks,
2450
2451 /// The resolved AS resources.
2452 as_resources: AsBlocks,
2453
2454 /// The TAL this is based on.
2455 tal: Arc<TalInfo>,
2456 }
2457
2458 impl ResourceCert {
2459 /// Returns a reference to the underlying certificate.
as_cert(&self) -> &Cert2460 pub fn as_cert(&self) -> &Cert {
2461 &self.cert
2462 }
2463
2464 /// Returns a reference to the IPv4 resources of this certificate.
v4_resources(&self) -> &IpBlocks2465 pub fn v4_resources(&self) -> &IpBlocks {
2466 &self.v4_resources
2467 }
2468
2469 /// Returns a reference to the IPv6 resources of this certificate.
v6_resources(&self) -> &IpBlocks2470 pub fn v6_resources(&self) -> &IpBlocks {
2471 &self.v6_resources
2472 }
2473
2474 /// Returns a reference to the AS resources of this certificate.
as_resources(&self) -> &AsBlocks2475 pub fn as_resources(&self) -> &AsBlocks {
2476 &self.as_resources
2477 }
2478
2479 /// Returns information about the TAL this certificate is based on.
tal(&self) -> &Arc<TalInfo>2480 pub fn tal(&self) -> &Arc<TalInfo> {
2481 &self.tal
2482 }
2483
2484 /// Converts the certificate into its TAL info.
into_tal(self) -> Arc<TalInfo>2485 pub fn into_tal(self) -> Arc<TalInfo> {
2486 self.tal
2487 }
2488 }
2489
2490
2491 //--- Deref and AsRef
2492
2493 impl ops::Deref for ResourceCert {
2494 type Target = Cert;
2495
deref(&self) -> &Cert2496 fn deref(&self) -> &Cert {
2497 self.as_cert()
2498 }
2499 }
2500
2501 impl AsRef<Cert> for ResourceCert {
as_ref(&self) -> &Cert2502 fn as_ref(&self) -> &Cert {
2503 self.as_cert()
2504 }
2505 }
2506
2507 impl AsRef<TbsCert> for ResourceCert {
as_ref(&self) -> &TbsCert2508 fn as_ref(&self) -> &TbsCert {
2509 self.as_cert().as_ref()
2510 }
2511 }
2512
2513
2514 //------------ KeyUsage ------------------------------------------------------
2515
2516 /// The allowed key usages of a resource certificate.
2517 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
2518 pub enum KeyUsage {
2519 /// A CA certificate.
2520 Ca,
2521
2522 /// An end-entity certificate.
2523 Ee,
2524 }
2525
2526 impl KeyUsage {
2527 /// Returns a value encoder for the key usage.
encode(self) -> impl encode::Values2528 pub fn encode(self) -> impl encode::Values {
2529 let s = match self {
2530 KeyUsage::Ca => b"\x01\x06", // Bits 5 and 6
2531 KeyUsage::Ee => b"\x07\x80", // Bit 0
2532 };
2533 s.encode_as(Tag::BIT_STRING)
2534 }
2535 }
2536
2537
2538 //------------ Overclaim -----------------------------------------------------
2539
2540 /// The overclaim mode for resource validation.
2541 ///
2542 /// In the original RPKI specification, a certificate becomes valid if it
2543 /// claims more resources than its issuer, a condition known as
2544 /// ‘overclaiming’. [RFC 8360] proposed an alternative approach where in this
2545 /// case the resources of the certificate are simply trimmed back to what the
2546 /// issuer certificate allows. This makes handling cases where a CA loses some
2547 /// resources easier.
2548 ///
2549 /// A certificate can choose to use the old or new method by using different
2550 /// OIDs for the certificate policy and the resource extensions.
2551 ///
2552 /// This type specifies which mode a certificate uses.
2553 ///
2554 /// [RFC 8380]: https://tools.ietf.org/html/rfc8360
2555 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
2556 pub enum Overclaim {
2557 /// A certificate becomes invalid if it overclaims resources.
2558 Refuse,
2559
2560 /// Overclaimed resources are trimmed to the by encompassed by the issuer.
2561 Trim,
2562 }
2563
2564 impl Overclaim {
from_policy(oid: &Oid) -> Result<Self, decode::Error>2565 fn from_policy(oid: &Oid) -> Result<Self, decode::Error> {
2566 if oid == &oid::CP_IPADDR_ASNUMBER {
2567 Ok(Overclaim::Refuse)
2568 }
2569 else if oid == &oid::CP_IPADDR_ASNUMBER_V2 {
2570 Ok(Overclaim::Trim)
2571 }
2572 else {
2573 xerr!(Err(decode::Malformed))
2574 }
2575 }
2576
from_ip_res(oid: &Oid) -> Option<Self>2577 fn from_ip_res(oid: &Oid) -> Option<Self> {
2578 if oid == &oid::PE_IP_ADDR_BLOCK {
2579 Some(Overclaim::Refuse)
2580 }
2581 else if oid == &oid::PE_IP_ADDR_BLOCK_V2 {
2582 Some(Overclaim::Trim)
2583 }
2584 else {
2585 None
2586 }
2587 }
2588
from_as_res(oid: &Oid) -> Option<Self>2589 fn from_as_res(oid: &Oid) -> Option<Self> {
2590 if oid == &oid::PE_AUTONOMOUS_SYS_IDS {
2591 Some(Overclaim::Refuse)
2592 }
2593 else if oid == &oid::PE_AUTONOMOUS_SYS_IDS_V2 {
2594 Some(Overclaim::Trim)
2595 }
2596 else {
2597 None
2598 }
2599 }
2600
policy_id(self) -> &'static ConstOid2601 pub fn policy_id(self) -> &'static ConstOid {
2602 match self {
2603 Overclaim::Refuse => &oid::CP_IPADDR_ASNUMBER,
2604 Overclaim::Trim => &oid::CP_IPADDR_ASNUMBER_V2
2605 }
2606 }
2607
ip_res_id(self) -> &'static ConstOid2608 pub fn ip_res_id(self) -> &'static ConstOid {
2609 match self {
2610 Overclaim::Refuse => &oid::PE_IP_ADDR_BLOCK,
2611 Overclaim::Trim => &oid::PE_IP_ADDR_BLOCK_V2
2612 }
2613 }
2614
as_res_id(self) -> &'static ConstOid2615 pub fn as_res_id(self) -> &'static ConstOid {
2616 match self {
2617 Overclaim::Refuse => &oid::PE_AUTONOMOUS_SYS_IDS,
2618 Overclaim::Trim => &oid::PE_AUTONOMOUS_SYS_IDS_V2
2619 }
2620 }
2621 }
2622
2623
2624 //============ Tests =========================================================
2625
2626 #[cfg(test)]
2627 mod test {
2628 use super::*;
2629
2630 #[test]
decode_and_inspect_certs()2631 fn decode_and_inspect_certs() {
2632 Cert::decode(
2633 include_bytes!("../../test-data/ta.cer").as_ref()
2634 ).unwrap().inspect_ta_at(
2635 true, Time::utc(2020, 11, 1, 12, 0, 0)
2636 ).unwrap();
2637 Cert::decode(
2638 include_bytes!("../../test-data/ca1.cer").as_ref()
2639 ).unwrap().inspect_ca_at(
2640 true, Time::utc(2020, 5, 1, 12, 0, 0)
2641 ).unwrap();
2642 Cert::decode(
2643 include_bytes!("../../test-data/router.cer").as_ref()
2644 ).unwrap().inspect_router_at(
2645 true, Time::utc(2020, 11, 1, 12, 0, 0)
2646 ).unwrap();
2647 }
2648
2649 /// Tests that inconsistent algorithm encoding fail validation.
2650 ///
2651 /// Specifically, tests that a certificate with different encoding of
2652 /// the signature algorithm parameters (NULL value v. not present) in
2653 /// the outer certificate structure and inside the TbsCertificate will
2654 /// be rejected during the inspection step.
2655 #[test]
signature_algorithm_mismatch()2656 fn signature_algorithm_mismatch() {
2657 let roa = crate::repository::roa::Roa::decode(
2658 include_bytes!(
2659 "../../test-data/example-ripe.roa"
2660 ).as_ref(),
2661 false
2662 ).unwrap();
2663 assert!(
2664 roa.cert().inspect_ee_at(
2665 true, Time::utc(2020, 5, 1, 0, 0, 0)
2666 ).is_ok()
2667 );
2668
2669 let mft = crate::repository::manifest::Manifest::decode(
2670 include_bytes!(
2671 "../../test-data/signature-alg-mismatch.mft"
2672 ).as_ref(),
2673 false
2674 ).unwrap();
2675 assert!(
2676 mft.cert().inspect_ee_at(
2677 true, Time::utc(2020, 5, 1, 0, 0, 0)
2678 ).is_err()
2679 );
2680 }
2681
2682 #[test]
2683 #[cfg(feature = "serde")]
serde_cert()2684 fn serde_cert() {
2685 let der = include_bytes!("../../test-data/ta.cer");
2686 let cert = Cert::decode(Bytes::from_static(der)).unwrap();
2687
2688 let serialize = serde_json::to_string(&cert).unwrap();
2689 let des_cert: Cert = serde_json::from_str(&serialize).unwrap();
2690
2691 assert_eq!(cert.to_captured().into_bytes(), des_cert.to_captured().into_bytes());
2692
2693 }
2694 }
2695
2696 #[cfg(all(test, feature="softkeys"))]
2697 mod signer_test {
2698 use std::str::FromStr;
2699 use crate::repository::cert::Cert;
2700 use crate::repository::crypto::PublicKeyFormat;
2701 use crate::repository::crypto::softsigner::OpenSslSigner;
2702 use crate::repository::resources::{AsId, Prefix};
2703 use crate::repository::tal::TalInfo;
2704 use super::*;
2705
2706
2707 #[test]
build_ta_cert()2708 fn build_ta_cert() {
2709 let signer = OpenSslSigner::new();
2710 let key = signer.create_key(PublicKeyFormat::Rsa).unwrap();
2711 let pubkey = signer.get_key_info(&key).unwrap();
2712 let uri = uri::Rsync::from_str("rsync://example.com/m/p").unwrap();
2713 let mut cert = TbsCert::new(
2714 12u64.into(), pubkey.to_subject_name(),
2715 Validity::from_secs(86400), None, pubkey, KeyUsage::Ca,
2716 Overclaim::Trim
2717 );
2718 cert.set_basic_ca(Some(true));
2719 cert.set_ca_repository(Some(uri.clone()));
2720 cert.set_rpki_manifest(Some(uri));
2721 cert.build_v4_resource_blocks(|b| b.push(Prefix::new(0, 0)));
2722 cert.build_v6_resource_blocks(|b| b.push(Prefix::new(0, 0)));
2723 cert.build_as_resource_blocks(|b| b.push((AsId::MIN, AsId::MAX)));
2724 let cert = cert.into_cert(&signer, &key).unwrap().to_captured();
2725 let cert = Cert::decode(cert.as_slice()).unwrap();
2726 let talinfo = TalInfo::from_name("foo".into()).into_arc();
2727 cert.validate_ta(talinfo, true).unwrap();
2728 }
2729 }
2730
2731
2732