1 //! Resource Tagged Attestations. 2 //! 3 //! Resource Tagged Attestations attaching signed attestations of ownership of 4 //! resources referred to by a document. This is currently an IETF draft, 5 //! see [draft-michaelson-rpki-rta] for details. 6 //! 7 //! Current limitations: 8 //! 9 //! * Resources are read in a rather relaxed way: they can be unordered and 10 //! overlapping. This happens even if the strict flag is set. 11 //! 12 //! draft-michaelson-rpki-rta: https://tools.ietf.org/html/draft-michaelson-rpki-rta 13 14 use std::ops; 15 use bcder::{decode, encode}; 16 use bcder::{Captured, Mode, OctetString, Tag}; 17 use bcder::encode::{PrimitiveContent, Values}; 18 use bcder::string::OctetStringSource; 19 use bcder::xerr; 20 use bytes::Bytes; 21 use super::oid; 22 use super::cert::{Cert, Overclaim, ResourceCert}; 23 use super::crl::Crl; 24 use super::crypto:: { 25 Digest, DigestAlgorithm, KeyIdentifier, Signature, SignatureAlgorithm, 26 Signer, SigningError 27 }; 28 use super::resources::{ 29 AddressFamily, AsBlock, AsBlocks, AsBlocksBuilder, IpBlock, IpBlocks, 30 IpBlocksBuilder, 31 }; 32 use super::sigobj::{MessageDigest, SignedAttrs}; 33 use super::tal::Tal; 34 use super::x509::{Time, ValidationError}; 35 36 37 //------------ Rta ----------------------------------------------------------- 38 39 #[derive(Clone, Debug)] 40 pub struct Rta { 41 signed: MultiSignedObject, 42 content: ResourceTaggedAttestation, 43 } 44 45 impl Rta { content(&self) -> &ResourceTaggedAttestation46 pub fn content(&self) -> &ResourceTaggedAttestation { 47 &self.content 48 } 49 decode<S: decode::Source>( source: S, strict: bool ) -> Result<Self, S::Err>50 pub fn decode<S: decode::Source>( 51 source: S, strict: bool 52 ) -> Result<Self, S::Err> { 53 let signed = MultiSignedObject::decode(source, strict)?; 54 let content = signed.decode_content(|cons| { 55 ResourceTaggedAttestation::take_from(cons) 56 })?; 57 Ok(Rta { signed, content }) 58 } 59 60 /// Returns a value encoder for a reference to a ROA. encode_ref(&self) -> impl encode::Values + '_61 pub fn encode_ref(&self) -> impl encode::Values + '_ { 62 self.signed.encode_ref() 63 } 64 65 /// Returns a DER encoded Captured for this ROA. to_captured(&self) -> Captured66 pub fn to_captured(&self) -> Captured { 67 self.encode_ref().to_captured(Mode::Der) 68 } 69 } 70 71 72 //--- Deref and AsRef 73 74 impl ops::Deref for Rta { 75 type Target = ResourceTaggedAttestation; 76 deref(&self) -> &Self::Target77 fn deref(&self) -> &Self::Target { 78 self.content() 79 } 80 } 81 82 impl AsRef<ResourceTaggedAttestation> for Rta { as_ref(&self) -> &ResourceTaggedAttestation83 fn as_ref(&self) -> &ResourceTaggedAttestation { 84 self.content() 85 } 86 } 87 88 89 //------------ ResourceTaggedAttestation ------------------------------------- 90 91 #[derive(Clone, Debug)] 92 pub struct ResourceTaggedAttestation { 93 subject_keys: Vec<KeyIdentifier>, 94 95 /// AS Resources 96 as_resources: AsBlocks, 97 98 /// IP Resources for the IPv4 address family. 99 v4_resources: IpBlocks, 100 101 /// IP Resources for the IPv6 address family. 102 v6_resources: IpBlocks, 103 104 digest_algorithm: DigestAlgorithm, 105 106 message_digest: MessageDigest, 107 } 108 109 impl ResourceTaggedAttestation { subject_keys(&self) -> &[KeyIdentifier]110 pub fn subject_keys(&self) -> &[KeyIdentifier] { 111 &self.subject_keys 112 } 113 as_resources(&self) -> &AsBlocks114 pub fn as_resources(&self) -> &AsBlocks { 115 &self.as_resources 116 } 117 v4_resources(&self) -> &IpBlocks118 pub fn v4_resources(&self) -> &IpBlocks { 119 &self.v4_resources 120 } 121 v6_resources(&self) -> &IpBlocks122 pub fn v6_resources(&self) -> &IpBlocks { 123 &self.v6_resources 124 } 125 digest_algorithm(&self) -> DigestAlgorithm126 pub fn digest_algorithm(&self) -> DigestAlgorithm { 127 self.digest_algorithm 128 } 129 message_digest(&self) -> &MessageDigest130 pub fn message_digest(&self) -> &MessageDigest { 131 &self.message_digest 132 } 133 } 134 135 impl ResourceTaggedAttestation { take_from<S: decode::Source>( cons: &mut decode::Constructed<S> ) -> Result<Self, S::Err>136 fn take_from<S: decode::Source>( 137 cons: &mut decode::Constructed<S> 138 ) -> Result<Self, S::Err> { 139 cons.take_sequence(|cons| { 140 cons.take_opt_constructed_if(Tag::CTX_0, |c| c.skip_u8_if(0))?; 141 let subject_keys = Self::take_subject_keys_from(cons)?; 142 let (v4res, v6res, asres) = Self::take_resources_from(cons)?; 143 let alg = DigestAlgorithm::take_from(cons)?; 144 let digest = OctetString::take_from(cons)?; 145 Ok(ResourceTaggedAttestation { 146 subject_keys, 147 v4_resources: v4res, 148 v6_resources: v6res, 149 as_resources: asres, 150 digest_algorithm: alg, 151 message_digest: digest.into(), 152 }) 153 }) 154 } 155 take_subject_keys_from<S: decode::Source>( cons: &mut decode::Constructed<S> ) -> Result<Vec<KeyIdentifier>, S::Err>156 fn take_subject_keys_from<S: decode::Source>( 157 cons: &mut decode::Constructed<S> 158 ) -> Result<Vec<KeyIdentifier>, S::Err> { 159 cons.take_set(|cons| { 160 let mut res = Vec::new(); 161 while let Some(id) = KeyIdentifier::take_opt_from(cons)? { 162 res.push(id) 163 } 164 Ok(res) 165 }) 166 } 167 take_resources_from<S: decode::Source>( cons: &mut decode::Constructed<S> ) -> Result<(IpBlocks, IpBlocks, AsBlocks), S::Err>168 fn take_resources_from<S: decode::Source>( 169 cons: &mut decode::Constructed<S> 170 ) -> Result<(IpBlocks, IpBlocks, AsBlocks), S::Err> { 171 cons.take_sequence(|cons| { 172 let asres = cons.take_opt_constructed_if(Tag::CTX_0, |cons| { 173 AsBlocks::take_from(cons) 174 })?; 175 176 let mut v4 = None; 177 let mut v6 = None; 178 cons.take_opt_constructed_if(Tag::CTX_1, |cons| { 179 cons.take_sequence(|cons| { 180 while let Some(()) = cons.take_opt_sequence(|cons| { 181 match AddressFamily::take_from(cons)? { 182 AddressFamily::Ipv4 => { 183 if v4.is_some() { 184 xerr!(return Err(decode::Malformed.into())); 185 } 186 v4 = Some(IpBlocks::take_from_with_family( 187 cons, AddressFamily::Ipv4 188 )?); 189 } 190 AddressFamily::Ipv6 => { 191 if v6.is_some() { 192 xerr!(return Err(decode::Malformed.into())); 193 } 194 v6 = Some(IpBlocks::take_from_with_family( 195 cons, AddressFamily::Ipv6 196 )?); 197 } 198 } 199 Ok(()) 200 })? { } 201 Ok(()) 202 }) 203 })?; 204 205 if asres.is_none() && v4.is_none() && v6.is_none() { 206 xerr!(return Err(decode::Malformed.into())); 207 } 208 Ok(( 209 v4.unwrap_or_default(), 210 v6.unwrap_or_default(), 211 asres.unwrap_or_default(), 212 )) 213 }) 214 } 215 encode_ref(&self) -> impl encode::Values + '_216 pub fn encode_ref(&self) -> impl encode::Values + '_ { 217 encode::sequence(( 218 // version is DEFAULT 219 encode::set( 220 encode::iter(self.subject_keys.iter().map(|item| { 221 item.encode_ref() 222 })) 223 ), 224 encode::sequence(( 225 self.encode_as_resources(), 226 self.encode_ip_resources(), 227 )), 228 self.digest_algorithm.encode(), 229 self.message_digest.encode_ref() 230 )) 231 } 232 encode_as_resources(&self) -> impl encode::Values + '_233 fn encode_as_resources(&self) -> impl encode::Values + '_ { 234 if self.as_resources.is_empty() { 235 None 236 } 237 else { 238 Some(encode::sequence_as(Tag::CTX_0, 239 encode::sequence( 240 self.as_resources.encode_ref() 241 ) 242 )) 243 } 244 } 245 encode_ip_resources(&self) -> impl encode::Values + '_246 fn encode_ip_resources(&self) -> impl encode::Values + '_ { 247 if self.v4_resources.is_empty() && self.v6_resources.is_empty() { 248 return None 249 } 250 Some(encode::sequence_as(Tag::CTX_1, 251 encode::sequence(( 252 self.v4_resources.encode_family(AddressFamily::Ipv4), 253 self.v6_resources.encode_family(AddressFamily::Ipv6), 254 )) 255 )) 256 } 257 to_bytes(&self) -> Bytes258 fn to_bytes(&self) -> Bytes { 259 self.encode_ref().to_captured(Mode::Der).into_bytes() 260 } 261 } 262 263 264 //------------ MultiSignedObject --------------------------------------------- 265 266 /// The flavour of a signed object used for RTAs. 267 #[derive(Clone, Debug)] 268 pub struct MultiSignedObject { 269 digest_algorithm: DigestAlgorithm, 270 content: OctetString, 271 certificates: Vec<Cert>, 272 crls: Vec<Crl>, 273 signer_infos: Vec<SignerInfo>, 274 } 275 276 impl MultiSignedObject { 277 /// Returns a reference to the object’s content. content(&self) -> &OctetString278 pub fn content(&self) -> &OctetString { 279 &self.content 280 } 281 282 /// Decodes the object’s content. decode_content<F, T>(&self, op: F) -> Result<T, decode::Error> where F: FnOnce(&mut decode::Constructed<OctetStringSource>) -> Result<T, decode::Error>283 pub fn decode_content<F, T>(&self, op: F) -> Result<T, decode::Error> 284 where F: FnOnce(&mut decode::Constructed<OctetStringSource>) 285 -> Result<T, decode::Error> { 286 Mode::Der.decode(self.content.to_source(), op) 287 } 288 } 289 290 impl MultiSignedObject { decode<S: decode::Source>( source: S, strict: bool ) -> Result<Self, S::Err>291 pub fn decode<S: decode::Source>( 292 source: S, strict: bool 293 ) -> Result<Self, S::Err> { 294 Mode::Der.decode(source, |cons| Self::take_from(cons, strict)) 295 } 296 take_from<S: decode::Source>( cons: &mut decode::Constructed<S>, strict: bool ) -> Result<Self, S::Err>297 pub fn take_from<S: decode::Source>( 298 cons: &mut decode::Constructed<S>, strict: bool 299 ) -> Result<Self, S::Err> { 300 cons.take_sequence(|cons| { 301 oid::SIGNED_DATA.skip_if(cons)?; // contentType 302 cons.take_constructed_if(Tag::CTX_0, |cons| { // content 303 cons.take_sequence(|cons| { // SignedData 304 cons.skip_u8_if(3)?; // version -- must be 3 305 let digest_algorithm = 306 DigestAlgorithm::take_set_from(cons)?; 307 let content = cons.take_sequence(|cons| { 308 // encapContentInfo 309 oid::CT_RESOURCE_TAGGED_ATTESTATION.skip_if(cons)?; 310 cons.take_constructed_if( 311 Tag::CTX_0, 312 OctetString::take_from 313 ) 314 })?; 315 let certificates = Self::take_certificates(cons, strict)?; 316 let crls = Self::take_crls(cons, strict)?; 317 let signer_infos = Self::take_signer_infos(cons, strict)?; 318 319 Ok(MultiSignedObject { 320 digest_algorithm, 321 content, 322 certificates, 323 crls, 324 signer_infos, 325 }) 326 }) 327 }) 328 }) 329 } 330 take_certificates<S: decode::Source>( cons: &mut decode::Constructed<S>, _strict: bool ) -> Result<Vec<Cert>, S::Err>331 fn take_certificates<S: decode::Source>( 332 cons: &mut decode::Constructed<S>, _strict: bool 333 ) -> Result<Vec<Cert>, S::Err> { 334 cons.take_constructed_if(Tag::CTX_0, |cons| { 335 let mut certificates = Vec::new(); 336 while let Some(cert) = Cert::take_opt_from(cons)? { 337 certificates.push(cert); 338 } 339 Ok(certificates) 340 }) 341 } 342 take_crls<S: decode::Source>( cons: &mut decode::Constructed<S>, _strict: bool ) -> Result<Vec<Crl>, S::Err>343 fn take_crls<S: decode::Source>( 344 cons: &mut decode::Constructed<S>, _strict: bool 345 ) -> Result<Vec<Crl>, S::Err> { 346 cons.take_opt_constructed_if(Tag::CTX_1, |cons| { 347 let mut crls = Vec::new(); 348 while let Some(crl) = Crl::take_opt_from(cons)? { 349 crls.push(crl); 350 } 351 Ok(crls) 352 }).map(|item| item.unwrap_or_default()) 353 } 354 take_signer_infos<S: decode::Source>( cons: &mut decode::Constructed<S>, _strict: bool ) -> Result<Vec<SignerInfo>, S::Err>355 fn take_signer_infos<S: decode::Source>( 356 cons: &mut decode::Constructed<S>, _strict: bool 357 ) -> Result<Vec<SignerInfo>, S::Err> { 358 cons.take_set(|cons| { 359 let mut infos = Vec::new(); 360 while let Some(info) = SignerInfo::take_opt_from(cons)? { 361 infos.push(info); 362 } 363 Ok(infos) 364 }) 365 } 366 367 /// Returns a value encoder for a reference to a signed object. encode_ref(&self) -> impl encode::Values + '_368 pub fn encode_ref(&self) -> impl encode::Values + '_ { 369 encode::sequence(( 370 oid::SIGNED_DATA.encode(), // contentType 371 encode::sequence_as(Tag::CTX_0, // content 372 encode::sequence(( 373 3u8.encode(), // version 374 self.digest_algorithm.encode_set(), // digestAlgorithms 375 encode::sequence(( // encapContentInfo 376 oid::CT_RESOURCE_TAGGED_ATTESTATION.encode(), 377 encode::sequence_as(Tag::CTX_0, 378 self.content.encode_ref() 379 ), 380 )), 381 encode::sequence_as(Tag::CTX_0, // certificates 382 encode::iter(self.certificates.iter().map(|item| { 383 item.encode_ref() 384 })) 385 ), 386 if self.crls.is_empty() { 387 None 388 } 389 else { 390 Some(encode::sequence_as(Tag::CTX_1, // crls 391 encode::iter(self.crls.iter().map(|item| { 392 item.encode_ref() 393 })) 394 )) 395 }, 396 encode::set( 397 encode::iter(self.signer_infos.iter().map(|item| { 398 item.encode_ref() 399 })) 400 ) 401 )), 402 ) 403 )) 404 } 405 } 406 407 408 //------------ SignerInfo ---------------------------------------------------- 409 410 /// A single SignerInfo of a signed object. 411 #[derive(Clone, Debug)] 412 pub struct SignerInfo { 413 sid: KeyIdentifier, 414 digest_algorithm: DigestAlgorithm, 415 signed_attrs: SignedAttrs, 416 signature: Signature, 417 418 //--- SignedAttributes 419 // 420 message_digest: MessageDigest, 421 signing_time: Option<Time>, 422 binary_signing_time: Option<u64>, 423 } 424 425 impl SignerInfo { 426 /// Returns the signing time if available. signing_time(&self) -> Option<Time>427 pub fn signing_time(&self) -> Option<Time> { 428 self.signing_time 429 } 430 431 /// Returns the binary signing time if available. binary_signing_time(&self) -> Option<u64>432 pub fn binary_signing_time(&self) -> Option<u64> { 433 self.binary_signing_time 434 } 435 take_opt_from<S: decode::Source>( cons: &mut decode::Constructed<S>, ) -> Result<Option<Self>, S::Err>436 pub fn take_opt_from<S: decode::Source>( 437 cons: &mut decode::Constructed<S>, 438 ) -> Result<Option<Self>, S::Err> { 439 cons.take_opt_sequence(|cons| { 440 cons.skip_u8_if(3)?; 441 let sid = cons.take_value_if( 442 Tag::CTX_0, |content| { 443 KeyIdentifier::from_content(content) 444 } 445 )?; 446 let alg = DigestAlgorithm::take_from(cons)?; 447 let attrs = SignedAttrs::take_from(cons)?; 448 if attrs.2 != oid::CT_RESOURCE_TAGGED_ATTESTATION { 449 return Err(decode::Malformed.into()) 450 } 451 let signature = Signature::new( 452 SignatureAlgorithm::cms_take_from(cons)?, 453 OctetString::take_from(cons)?.into_bytes() 454 ); 455 // no unsignedAttributes 456 Ok(SignerInfo { 457 sid, 458 digest_algorithm: alg, 459 signed_attrs: attrs.0, 460 signature, 461 message_digest: attrs.1, 462 signing_time: attrs.3, 463 binary_signing_time: attrs.4 464 }) 465 }) 466 } 467 encode_ref(&self) -> impl encode::Values + '_468 pub fn encode_ref(&self) -> impl encode::Values + '_ { 469 encode::sequence(( 470 3u8.encode(), // version 471 self.sid.encode_ref_as(Tag::CTX_0), 472 self.digest_algorithm.encode(), // digestAlgorithm 473 self.signed_attrs.encode_ref(), // signedAttrs 474 self.signature.algorithm().cms_encode(), 475 // signatureAlgorithm 476 OctetString::encode_slice( // signature 477 self.signature.value().as_ref() 478 ), 479 // unsignedAttrs omitted 480 )) 481 } 482 } 483 484 485 //------------ Validation ---------------------------------------------------- 486 487 #[derive(Clone, Debug)] 488 pub struct Validation<'a> { 489 /// The RTA object we are validating. 490 rta: &'a Rta, 491 492 /// The validation chains we need to validate. 493 chains: Vec<Chain<'a>>, 494 495 /// Are we doing strict validation? 496 strict: bool, 497 498 /// What time is it, Geoff Peterson? 499 now: Time, 500 } 501 502 impl<'a> Validation<'a> { new( rta: &'a Rta, strict: bool ) -> Result<Self, ValidationError>503 pub fn new( 504 rta: &'a Rta, strict: bool 505 ) -> Result<Self, ValidationError> { 506 Self::new_at(rta, strict, Time::now()) 507 } 508 new_at( rta: &'a Rta, strict: bool, now: Time, ) -> Result<Self, ValidationError>509 pub fn new_at( 510 rta: &'a Rta, strict: bool, now: Time, 511 ) -> Result<Self, ValidationError> { 512 // Get a vec with options of refs to the CRLs. Whenever we used a CRL 513 // in a CA, we take it out. Thus, at the end we need to have all 514 // `None` in the vec. 515 let mut crls: Vec<_> = rta.signed.crls.iter().map(Some).collect(); 516 517 // Ditto for the subject keys included with the content. 518 let mut keys: Vec<_> = rta.content.subject_keys.iter().map(|key| { 519 Some(*key) 520 }).collect(); 521 522 // Calculate the digest of the content. 523 let digest = { 524 let mut context = rta.signed.digest_algorithm.start(); 525 rta.signed.content.iter().for_each(|x| context.update(x)); 526 context.finish() 527 }; 528 529 // Process all certificates. CA certificates go into the CA vec and 530 // EE certificates go into a temporary option-vec which we use when 531 // creating chains from signer-infos later. 532 let mut cas = Vec::new(); 533 let mut ees = Vec::new(); 534 for cert in &rta.signed.certificates { 535 if cert.basic_ca().is_none() { 536 cert.inspect_detached_ee_at(strict, now)?; 537 ees.push(Some(cert)); 538 } 539 else { 540 cas.push(Ca::new(cert, &mut crls, strict, now)?); 541 } 542 } 543 544 let mut chains = Vec::new(); 545 for info in &rta.signed.signer_infos { 546 chains.push( 547 Chain::new(info, &digest, &mut keys, &mut ees)? 548 ) 549 } 550 551 // All subject keys need to have been used. 552 if keys.iter().any(|item| item.is_some()) { 553 xerr!(return Err(ValidationError)) 554 } 555 556 // All CRLs need to have been used. 557 if crls.iter().any(|item| item.is_some()) { 558 xerr!(return Err(ValidationError)) 559 } 560 561 // All EE certificates have to have been used. 562 if ees.iter().any(|item| item.is_some()) { 563 xerr!(return Err(ValidationError)) 564 } 565 566 // Create the object and advance the chains using the CA certificates 567 // we have. 568 let mut res = Validation { rta, chains, strict, now }; 569 res.advance_chains(&mut cas)?; 570 571 // All the CA certificates have to have been used. 572 if cas.iter().any(|item| !item.used) { 573 xerr!(return Err(ValidationError)) 574 } 575 576 // Hurray! 577 Ok(res) 578 } 579 advance_chains( &mut self, cas: &mut [Ca<'a>] ) -> Result<(), ValidationError>580 fn advance_chains( 581 &mut self, cas: &mut [Ca<'a>] 582 ) -> Result<(), ValidationError> { 583 for chain in &mut self.chains { 584 chain.advance(cas, self.strict)?; 585 } 586 Ok(()) 587 } 588 supply_tal(&mut self, tal: &Tal) -> Result<bool, ValidationError>589 pub fn supply_tal(&mut self, tal: &Tal) -> Result<bool, ValidationError> { 590 let mut done = true; 591 for chain in &mut self.chains { 592 if !chain.supply_tal(tal, self.strict, self.now)? { 593 done = false 594 } 595 } 596 Ok(done) 597 } 598 supply_ca( &mut self, ca: &ResourceCert ) -> Result<bool, ValidationError>599 pub fn supply_ca( 600 &mut self, ca: &ResourceCert 601 ) -> Result<bool, ValidationError> { 602 let mut done = true; 603 for chain in &mut self.chains { 604 if !chain.supply_ca(ca, self.strict, self.now)? { 605 done = false 606 } 607 } 608 Ok(done) 609 } 610 finalize( self ) -> Result<&'a ResourceTaggedAttestation, ValidationError>611 pub fn finalize( 612 self 613 ) -> Result<&'a ResourceTaggedAttestation, ValidationError> { 614 let mut asn = AsBlocksBuilder::new(); 615 let mut v4 = IpBlocksBuilder::new(); 616 let mut v6 = IpBlocksBuilder::new(); 617 618 for chain in &self.chains { 619 chain.finalize(&mut asn, &mut v4, &mut v6)?; 620 } 621 622 let asn = asn.finalize(); 623 let v4 = v4.finalize(); 624 let v6 = v6.finalize(); 625 626 if asn != self.rta.content.as_resources 627 || v4 != self.rta.content.v4_resources 628 || v6 != self.rta.content.v6_resources 629 { 630 return Err(ValidationError) 631 } 632 633 Ok(self.rta) 634 } 635 } 636 637 638 //------------ Ca ------------------------------------------------------------ 639 640 #[derive(Clone, Debug)] 641 struct Ca<'a> { 642 cert: &'a Cert, 643 crl: &'a Crl, 644 used: bool, 645 } 646 647 impl<'a> Ca<'a> { new( cert: &'a Cert, crls: &mut [Option<&'a Crl>], strict: bool, now: Time, ) -> Result<Self, ValidationError>648 fn new( 649 cert: &'a Cert, 650 crls: &mut [Option<&'a Crl>], 651 strict: bool, now: Time, 652 ) -> Result<Self, ValidationError> { 653 cert.inspect_ca_at(strict, now)?; 654 Ok(Ca { 655 cert, 656 crl: Self::find_crl(cert, crls)?, 657 used: false 658 }) 659 } 660 find_crl<'c>( cert: &Cert, crls: &mut [Option<&'c Crl>] ) -> Result<&'c Crl, ValidationError>661 fn find_crl<'c>( 662 cert: &Cert, crls: &mut [Option<&'c Crl>] 663 ) -> Result<&'c Crl, ValidationError> { 664 for crl in crls { 665 match crl.as_ref() { 666 Some(crl) => { 667 if *crl.authority_key_identifier() 668 != cert.subject_key_identifier() 669 { 670 continue 671 } 672 if crl.validate(cert.subject_public_key_info()).is_err() { 673 continue 674 } 675 } 676 None => continue 677 } 678 return Ok(crl.take().unwrap()) 679 } 680 Err(ValidationError) 681 } 682 } 683 684 685 //------------ Chain --------------------------------------------------------- 686 687 #[derive(Clone, Debug)] 688 struct Chain<'a> { 689 /// The topmost certificate of the path. 690 cert: &'a Cert, 691 692 /// The resources of the topmost cert. 693 cert_resources: CertResources, 694 695 /// The resources of the entire path. 696 chain_resources: CertResources, 697 698 /// Has the chain been validated? 699 validated: bool, 700 } 701 702 impl<'a> Chain<'a> { 703 //--- new and helpers 704 new( info: &SignerInfo, digest: &Digest, keys: &mut [Option<KeyIdentifier>], ees: &mut [Option<&'a Cert>], ) -> Result<Self, ValidationError>705 fn new( 706 info: &SignerInfo, 707 digest: &Digest, 708 keys: &mut [Option<KeyIdentifier>], 709 ees: &mut [Option<&'a Cert>], 710 ) -> Result<Self, ValidationError> { 711 // Find and removed sid in keys. 712 match keys.iter_mut().find(|item| **item == Some(info.sid)) { 713 Some(item) => *item = None, 714 None => xerr!(return Err(ValidationError)) 715 } 716 717 // Verify the message digest attribute 718 if digest.as_ref() != info.message_digest.as_ref() { 719 return xerr!(Err(ValidationError)) 720 } 721 722 // Find th EE cert that signed this signer info. 723 let ee = Self::find_cert(info, ees)?; 724 725 let resources = CertResources::new(ee); 726 Ok(Chain { 727 cert: ee, 728 cert_resources: resources.clone(), 729 chain_resources: resources, 730 validated: false 731 }) 732 } 733 find_cert( info: &SignerInfo, ees: &mut [Option<&'a Cert>] ) -> Result<&'a Cert, ValidationError>734 fn find_cert( 735 info: &SignerInfo, 736 ees: &mut [Option<&'a Cert>] 737 ) -> Result<&'a Cert, ValidationError> { 738 let msg = info.signed_attrs.encode_verify(); 739 for item in ees { 740 if let Some(cert) = *item { 741 if cert.subject_key_identifier() != info.sid { 742 continue 743 } 744 if cert.subject_public_key_info().verify( 745 &msg, 746 &info.signature 747 ).is_err() { 748 continue 749 } 750 *item = None; 751 return Ok(cert) 752 } 753 754 } 755 xerr!(Err(ValidationError)) 756 } 757 758 //--- advance and helpers 759 advance( &mut self, cas: &mut [Ca<'a>], strict: bool, ) -> Result<(), ValidationError>760 fn advance( 761 &mut self, 762 cas: &mut [Ca<'a>], 763 strict: bool, 764 ) -> Result<(), ValidationError> { 765 while let Some(ca) = self.find_ca(cas, strict)? { 766 self.apply_ca(ca)?; 767 ca.used = true; 768 } 769 Ok(()) 770 } 771 find_ca<'c>( &self, cas: &'c mut [Ca<'a>], strict: bool, ) -> Result<Option<&'c mut Ca<'a>>, ValidationError>772 fn find_ca<'c>( 773 &self, 774 cas: &'c mut [Ca<'a>], 775 strict: bool, 776 ) -> Result<Option<&'c mut Ca<'a>>, ValidationError> { 777 // If we don’t have an authority key identifier on the cert, it is 778 // self-signed and we are done. If we do have one and it is the same 779 // as the subject key identifier, it is self-signed, too. 780 let aki = match self.cert.authority_key_identifier() { 781 Some(aki) if aki == self.cert.subject_key_identifier() => { 782 return Ok(None) 783 } 784 Some(aki) => aki, 785 None => return Ok(None) 786 }; 787 788 let mut found = false; 789 for ca in cas { 790 if ca.cert.subject_key_identifier() != aki { 791 continue 792 } 793 found = true; 794 if self.cert.verify_signature(ca.cert, strict).is_err() { 795 continue 796 } 797 return Ok(Some(ca)) 798 } 799 if found { 800 xerr!(Err(ValidationError)) 801 } 802 else { 803 Ok(None) 804 } 805 } 806 apply_ca(&mut self, ca: &Ca<'a>) -> Result<(), ValidationError>807 fn apply_ca(&mut self, ca: &Ca<'a>) -> Result<(), ValidationError> { 808 // Check that our cert hasn’t been revoked. 809 if ca.crl.contains(self.cert.serial_number()) { 810 xerr!(return Err(ValidationError)) 811 } 812 813 // Check if the CA allows us to have our resources. 814 self.verify_resources(ca)?; 815 816 // Now update self to reflect the new head of chain cert. 817 self.update_head(ca); 818 819 Ok(()) 820 } 821 verify_resources(&self, ca: &Ca) -> Result<(), ValidationError>822 fn verify_resources(&self, ca: &Ca) -> Result<(), ValidationError> { 823 // If our cert is of the resource trimming kind, we don’t actually 824 // need to check but rather have to trim resources later on. 825 if self.cert.overclaim() == Overclaim::Trim { 826 return Ok(()) 827 } 828 829 // If we have a certain resource, it needs to be covered by the CA. 830 // If the CA has that resource as inherited, that qualifies as valid, 831 // too. 832 if let Some(blocks) = self.cert_resources.as_resources.as_ref() { 833 blocks.verify_covered(ca.cert.as_resources())? 834 } 835 if let Some(blocks) = self.cert_resources.v4_resources.as_ref() { 836 blocks.verify_covered(ca.cert.v4_resources())? 837 } 838 if let Some(blocks) = self.cert_resources.v6_resources.as_ref() { 839 blocks.verify_covered(ca.cert.v6_resources())? 840 } 841 842 Ok(()) 843 } 844 update_head(&mut self, ca: &Ca<'a>)845 fn update_head(&mut self, ca: &Ca<'a>) { 846 // Let’s get the CA’s resources so we can play with them. 847 let ca_resources = CertResources::new(ca.cert); 848 849 // If our current head has a resource trimming certificate, we first 850 // need to trim back the chain resources to whatever the CA allows. 851 if self.cert.overclaim() == Overclaim::Trim { 852 self.chain_resources.trim_to(&ca_resources); 853 } 854 855 // Next we update remaining inherited chain resources to what the CA 856 // has (unless it is inherited, too). 857 self.chain_resources.replace_inherited(&ca_resources); 858 859 // Now we can update the head resources and certificate, leaving 860 // inherited resources in the CA untouched. 861 self.cert_resources.update_head(ca_resources); 862 self.cert = ca.cert; 863 } 864 865 866 //--- supply_tal and supply_ca 867 supply_tal( &mut self, tal: &Tal, strict: bool, now: Time ) -> Result<bool, ValidationError>868 fn supply_tal( 869 &mut self, tal: &Tal, strict: bool, now: Time 870 ) -> Result<bool, ValidationError> { 871 if self.validated { 872 return Ok(true) 873 } 874 875 // If we have a self-signed certificate, it is a TA certificate and 876 // we don’t need to bother checking. 877 if self.cert.is_self_signed() { 878 return Ok(false) 879 } 880 881 // Let’s see if the key matches. 882 if self.cert.subject_public_key_info() != tal.key_info() { 883 return Ok(false) 884 } 885 886 // Finally, let’s see if we have a proper TA certificate. We only do 887 // this now so we don’t check over and over again. We also will never 888 // check a certificate that doesn’t have a matching TAL which will 889 // safe a little extra time. 890 self.cert.inspect_ta_at(strict, now)?; 891 self.cert.verify_ta_ref(strict)?; 892 893 self.validated = true; 894 Ok(true) 895 } 896 supply_ca( &mut self, ca: &ResourceCert, strict: bool, now: Time ) -> Result<bool, ValidationError>897 fn supply_ca( 898 &mut self, ca: &ResourceCert, strict: bool, now: Time 899 ) -> Result<bool, ValidationError> { 900 if self.validated { 901 return Ok(true) 902 } 903 904 // Quick check first: If we don’t have an AKI, we are our own CA and 905 // don’t need to continue here. 906 if self.cert.authority_key_identifier().is_none() { 907 return Ok(false) 908 } 909 910 // Now check properly if `ca` should be our CA and return if it isn’t. 911 // 912 // If it isn’t not all is lost. There may just be a key identifier 913 // collision or something. Unlikely but hey. 914 if self.cert.verify_issuer_claim(ca, strict).is_err() 915 || self.cert.verify_signature(ca, strict).is_err() 916 { 917 return Ok(false) 918 } 919 920 // Now let’s see if our certificate is a proper CA or EE certificate. 921 // 922 // basic_ca must be present (and true) for CA certs and not present 923 // for EE certs, so we can use that. If it has the wrong value, the 924 // cert is broken, so the check will fail and all is good. 925 // 926 // We will error out here if the cert is broken because, well, the 927 // cert is broken. 928 if self.cert.basic_ca().is_some() { 929 self.cert.inspect_ca_at(strict, now)?; 930 } 931 else { 932 self.cert.inspect_detached_ee_at(strict, now)?; 933 } 934 935 // Finally, resources. If they don’t check out, we can error out ... 936 // I think. 937 // 938 // Remember that our cert may be of the resource trimming kind, 939 // though. 940 if self.cert.overclaim() == Overclaim::Trim { 941 self.chain_resources.trim_to_issuer(ca); 942 } 943 else { 944 self.cert_resources.verify_issuer(ca)?; 945 } 946 947 // If we still have inherited resources left, replace them with the 948 // CA cert. 949 self.chain_resources.replace_inherited_from_issuer(ca); 950 951 self.validated = true; 952 Ok(true) 953 } 954 955 //--- finalize 956 finalize( &self, asn: &mut AsBlocksBuilder, v4: &mut IpBlocksBuilder, v6: &mut IpBlocksBuilder ) -> Result<(), ValidationError>957 fn finalize( 958 &self, 959 asn: &mut AsBlocksBuilder, 960 v4: &mut IpBlocksBuilder, 961 v6: &mut IpBlocksBuilder 962 ) -> Result<(), ValidationError> { 963 if !self.validated { 964 return Err(ValidationError) 965 } 966 967 // Add all our resources to the collection of resources. 968 // 969 // We can’t really have inherited resources left (if the top was a TA 970 // certificate, we should have rejected it already in this case and 971 // otherwise we checked it against a resource CA cert from outside 972 // which always has all resources) resources left, so let’s unwrap 973 // here to indicate a programming error. 974 asn.extend(self.chain_resources.as_resources.as_ref().unwrap().iter()); 975 v4.extend(self.chain_resources.v4_resources.as_ref().unwrap().iter()); 976 v6.extend(self.chain_resources.v6_resources.as_ref().unwrap().iter()); 977 978 Ok(()) 979 } 980 } 981 982 983 //------------ CertResources ------------------------------------------------- 984 985 #[derive(Clone, Debug)] 986 struct CertResources { 987 /// The AS resources. 988 /// 989 /// A value of `None` means the resources are inherited from the CA. 990 as_resources: Option<AsBlocks>, 991 992 /// The IPv4 resources. 993 /// 994 /// A value of `None` means the resources are inherited from the CA. 995 v4_resources: Option<IpBlocks>, 996 997 /// The IPv6 resources. 998 /// 999 /// A value of `None` means the resources are inherited from the CA. 1000 v6_resources: Option<IpBlocks>, 1001 } 1002 1003 impl CertResources { new(cert: &Cert) -> Self1004 fn new(cert: &Cert) -> Self { 1005 CertResources { 1006 as_resources: cert.as_resources().to_blocks().ok(), 1007 v4_resources: cert.v4_resources().to_blocks().ok(), 1008 v6_resources: cert.v6_resources().to_blocks().ok(), 1009 } 1010 } 1011 trim_to(&mut self, ca: &CertResources)1012 fn trim_to(&mut self, ca: &CertResources) { 1013 if let (Some(my), Some(them)) = ( 1014 self.as_resources.as_mut(), ca.as_resources.as_ref() 1015 ) { 1016 my.intersection_assign(them) 1017 } 1018 if let (Some(my), Some(them)) = ( 1019 self.v4_resources.as_mut(), ca.v4_resources.as_ref() 1020 ) { 1021 my.intersection_assign(them) 1022 } 1023 if let (Some(my), Some(them)) = ( 1024 self.v6_resources.as_mut(), ca.v6_resources.as_ref() 1025 ) { 1026 my.intersection_assign(them) 1027 } 1028 } 1029 trim_to_issuer(&mut self, issuer: &ResourceCert)1030 fn trim_to_issuer(&mut self, issuer: &ResourceCert) { 1031 if let Some(res) = self.as_resources.as_mut() { 1032 res.intersection_assign(issuer.as_resources()) 1033 } 1034 if let Some(res) = self.v4_resources.as_mut() { 1035 res.intersection_assign(issuer.v4_resources()) 1036 } 1037 if let Some(res) = self.v6_resources.as_mut() { 1038 res.intersection_assign(issuer.v6_resources()) 1039 } 1040 } 1041 verify_issuer( &self, issuer: &ResourceCert ) -> Result<(), ValidationError>1042 fn verify_issuer( 1043 &self, issuer: &ResourceCert 1044 ) -> Result<(), ValidationError> { 1045 if let Some(res) = self.as_resources.as_ref() { 1046 if !issuer.as_resources().contains(res) { 1047 return Err(ValidationError) 1048 } 1049 } 1050 if let Some(res) = self.v4_resources.as_ref() { 1051 if !issuer.v4_resources().contains(res) { 1052 return Err(ValidationError) 1053 } 1054 } 1055 if let Some(res) = self.v6_resources.as_ref() { 1056 if !issuer.v6_resources().contains(res) { 1057 return Err(ValidationError) 1058 } 1059 } 1060 Ok(()) 1061 } 1062 replace_inherited(&mut self, ca: &CertResources)1063 fn replace_inherited(&mut self, ca: &CertResources) { 1064 if self.as_resources.is_none() { 1065 self.as_resources = ca.as_resources.clone() 1066 } 1067 if self.v4_resources.is_none() { 1068 self.v4_resources = ca.v4_resources.clone() 1069 } 1070 if self.v6_resources.is_none() { 1071 self.v6_resources = ca.v6_resources.clone() 1072 } 1073 } 1074 replace_inherited_from_issuer(&mut self, ca: &ResourceCert)1075 fn replace_inherited_from_issuer(&mut self, ca: &ResourceCert) { 1076 if self.as_resources.is_none() { 1077 self.as_resources = Some(ca.as_resources().clone()) 1078 } 1079 if self.v4_resources.is_none() { 1080 self.v4_resources = Some(ca.v4_resources().clone()) 1081 } 1082 if self.v6_resources.is_none() { 1083 self.v6_resources = Some(ca.v6_resources().clone()) 1084 } 1085 } 1086 update_head(&mut self, ca: CertResources)1087 fn update_head(&mut self, ca: CertResources) { 1088 if let Some(res) = ca.as_resources { 1089 self.as_resources = Some(res) 1090 } 1091 if let Some(res) = ca.v4_resources { 1092 self.v4_resources = Some(res) 1093 } 1094 if let Some(res) = ca.v6_resources { 1095 self.v6_resources = Some(res) 1096 } 1097 } 1098 } 1099 1100 1101 //------------ AttestationBuilder -------------------------------------------- 1102 1103 pub struct AttestationBuilder { 1104 keys: Vec<KeyIdentifier>, 1105 as_resources: AsBlocksBuilder, 1106 v4_resources: IpBlocksBuilder, 1107 v6_resources: IpBlocksBuilder, 1108 digest_algorithm: DigestAlgorithm, 1109 message_digest: MessageDigest, 1110 } 1111 1112 impl AttestationBuilder { new( digest_algorithm: DigestAlgorithm, message_digest: MessageDigest ) -> Self1113 pub fn new( 1114 digest_algorithm: DigestAlgorithm, 1115 message_digest: MessageDigest 1116 ) -> Self { 1117 AttestationBuilder { 1118 keys: Vec::new(), 1119 as_resources: AsBlocksBuilder::new(), 1120 v4_resources: IpBlocksBuilder::new(), 1121 v6_resources: IpBlocksBuilder::new(), 1122 digest_algorithm, message_digest 1123 } 1124 } 1125 push_key(&mut self, key: KeyIdentifier)1126 pub fn push_key(&mut self, key: KeyIdentifier) { 1127 self.keys.push(key) 1128 } 1129 keys(&self) -> &[KeyIdentifier]1130 pub fn keys(&self) -> &[KeyIdentifier] { 1131 &self.keys 1132 } 1133 keys_mut(&mut self) -> &mut Vec<KeyIdentifier>1134 pub fn keys_mut(&mut self) -> &mut Vec<KeyIdentifier> { 1135 &mut self.keys 1136 } 1137 push_as(&mut self, block: impl Into<AsBlock>)1138 pub fn push_as(&mut self, block: impl Into<AsBlock>) { 1139 self.as_resources.push(block) 1140 } 1141 as_resources(&self) -> &AsBlocksBuilder1142 pub fn as_resources(&self) -> &AsBlocksBuilder { 1143 &self.as_resources 1144 } 1145 as_resources_mut(&mut self) -> &mut AsBlocksBuilder1146 pub fn as_resources_mut(&mut self) -> &mut AsBlocksBuilder { 1147 &mut self.as_resources 1148 } 1149 push_v4(&mut self, block: impl Into<IpBlock>)1150 pub fn push_v4(&mut self, block: impl Into<IpBlock>) { 1151 self.v4_resources.push(block) 1152 } 1153 v4_resources(&self) -> &IpBlocksBuilder1154 pub fn v4_resources(&self) -> &IpBlocksBuilder { 1155 &self.v4_resources 1156 } 1157 v4_resources_mut(&mut self) ->&mut IpBlocksBuilder1158 pub fn v4_resources_mut(&mut self) ->&mut IpBlocksBuilder { 1159 &mut self.v4_resources 1160 } 1161 push_v6(&mut self, block: impl Into<IpBlock>)1162 pub fn push_v6(&mut self, block: impl Into<IpBlock>) { 1163 self.v6_resources.push(block) 1164 } 1165 v6_resources(&self) -> &IpBlocksBuilder1166 pub fn v6_resources(&self) -> &IpBlocksBuilder { 1167 &self.v6_resources 1168 } 1169 v6_resources_mut(&mut self) -> &mut IpBlocksBuilder1170 pub fn v6_resources_mut(&mut self) -> &mut IpBlocksBuilder { 1171 &mut self.v6_resources 1172 } 1173 into_attestation(self) -> ResourceTaggedAttestation1174 pub fn into_attestation(self) -> ResourceTaggedAttestation { 1175 ResourceTaggedAttestation { 1176 subject_keys: self.keys, 1177 as_resources: self.as_resources.finalize(), 1178 v4_resources: self.v4_resources.finalize(), 1179 v6_resources: self.v6_resources.finalize(), 1180 digest_algorithm: self.digest_algorithm, 1181 message_digest: self.message_digest, 1182 } 1183 } 1184 into_rta_builder(self) -> RtaBuilder1185 pub fn into_rta_builder(self) -> RtaBuilder { 1186 RtaBuilder::from_attestation(self.into_attestation()) 1187 } 1188 } 1189 1190 1191 //------------ RtaBuilder ---------------------------------------------------- 1192 1193 pub struct RtaBuilder { 1194 digest_algorithm: DigestAlgorithm, 1195 encoded_content: Bytes, 1196 content: ResourceTaggedAttestation, 1197 certificates: Vec<Cert>, 1198 crls: Vec<Crl>, 1199 signer_infos: Vec<SignerInfo>, 1200 } 1201 1202 impl RtaBuilder { from_attestation(content: ResourceTaggedAttestation) -> Self1203 pub fn from_attestation(content: ResourceTaggedAttestation) -> Self { 1204 RtaBuilder { 1205 digest_algorithm: DigestAlgorithm::default(), 1206 encoded_content: content.to_bytes(), 1207 content, 1208 certificates: Vec::new(), 1209 crls: Vec::new(), 1210 signer_infos: Vec::new() 1211 } 1212 } 1213 from_rta(rta: Rta) -> Self1214 pub fn from_rta(rta: Rta) -> Self { 1215 RtaBuilder { 1216 digest_algorithm: DigestAlgorithm::default(), 1217 encoded_content: rta.signed.content.to_bytes(), 1218 content: rta.content, 1219 certificates: rta.signed.certificates, 1220 crls: rta.signed.crls, 1221 signer_infos: rta.signed.signer_infos, 1222 } 1223 } 1224 content(&self) -> &ResourceTaggedAttestation1225 pub fn content(&self) -> &ResourceTaggedAttestation { 1226 &self.content 1227 } 1228 push_cert(&mut self, cert: Cert)1229 pub fn push_cert(&mut self, cert: Cert) { 1230 self.certificates.push(cert) 1231 } 1232 certificates(&self) -> &[Cert]1233 pub fn certificates(&self) -> &[Cert] { 1234 &self.certificates 1235 } 1236 certificates_mut(&mut self) -> &mut Vec<Cert>1237 pub fn certificates_mut(&mut self) -> &mut Vec<Cert> { 1238 &mut self.certificates 1239 } 1240 push_crl(&mut self, crl: Crl)1241 pub fn push_crl(&mut self, crl: Crl) { 1242 self.crls.push(crl) 1243 } 1244 crls(&self) -> &[Crl]1245 pub fn crls(&self) -> &[Crl] { 1246 &self.crls 1247 } 1248 crls_mut(&mut self) -> &mut Vec<Crl>1249 pub fn crls_mut(&mut self) -> &mut Vec<Crl> { 1250 &mut self.crls 1251 } 1252 sign<S: Signer>( &mut self, signer: &S, key: &S::KeyId, signing_time: Option<Time>, binary_signing_time: Option<u64>, ) -> Result<(), SigningError<S::Error>>1253 pub fn sign<S: Signer>( 1254 &mut self, 1255 signer: &S, 1256 key: &S::KeyId, 1257 signing_time: Option<Time>, 1258 binary_signing_time: Option<u64>, 1259 ) -> Result<(), SigningError<S::Error>> { 1260 // Produce the content digest 1261 let message_digest = self.digest_algorithm.digest( 1262 &self.encoded_content 1263 ).into(); 1264 1265 // Produce signed attributes. 1266 let signed_attrs = SignedAttrs::new( 1267 &oid::CT_RESOURCE_TAGGED_ATTESTATION, 1268 &message_digest, 1269 signing_time, 1270 binary_signing_time 1271 ); 1272 1273 // Sign those attributes 1274 let signature = signer.sign( 1275 key, SignatureAlgorithm::default(), 1276 &signed_attrs.encode_verify() 1277 )?; 1278 1279 self.signer_infos.push(SignerInfo { 1280 sid: KeyIdentifier::from_public_key(&signer.get_key_info(key)?), 1281 digest_algorithm: self.digest_algorithm, 1282 signed_attrs, 1283 signature, 1284 message_digest, 1285 signing_time, 1286 binary_signing_time 1287 }); 1288 Ok(()) 1289 } 1290 signer_infos(&self) -> &[SignerInfo]1291 pub fn signer_infos(&self) -> &[SignerInfo] { 1292 &self.signer_infos 1293 } 1294 signer_infos_mut(&mut self) -> &mut Vec<SignerInfo>1295 pub fn signer_infos_mut(&mut self) -> &mut Vec<SignerInfo> { 1296 &mut self.signer_infos 1297 } 1298 finalize(self) -> Rta1299 pub fn finalize(self) -> Rta { 1300 Rta { 1301 signed: MultiSignedObject { 1302 digest_algorithm: self.digest_algorithm, 1303 content: OctetString::new(self.encoded_content), 1304 certificates: self.certificates, 1305 crls: self.crls, 1306 signer_infos: self.signer_infos, 1307 }, 1308 content: self.content, 1309 } 1310 } 1311 } 1312 1313