1 //! Signed objects. 2 // 3 // See RFC 6488 and RFC 5652. 4 5 use std::{cmp, io}; 6 use bcder::{decode, encode}; 7 use bcder::{Captured, Mode, OctetString, Oid, Tag, xerr}; 8 use bcder::encode::PrimitiveContent; 9 use bcder::string::OctetStringSource; 10 use bytes::Bytes; 11 use crate::uri; 12 use super::oid; 13 use super::cert::{Cert, KeyUsage, Overclaim, ResourceCert, TbsCert}; 14 use super::crypto::{ 15 Digest, DigestAlgorithm, KeyIdentifier, Signature, SignatureAlgorithm, 16 Signer, SigningError 17 }; 18 use super::resources::{ 19 AsBlocksBuilder, AsResources, AsResourcesBuilder, IpBlocksBuilder, 20 IpResources, IpResourcesBuilder 21 }; 22 use super::x509::{Name, Serial, Time, ValidationError, Validity, update_once}; 23 24 25 //------------ SignedObject -------------------------------------------------- 26 27 /// A signed object. 28 #[derive(Clone, Debug)] 29 pub struct SignedObject { 30 //--- From SignedData 31 // 32 digest_algorithm: DigestAlgorithm, 33 content_type: Oid<Bytes>, 34 content: OctetString, 35 cert: Cert, 36 37 //--- From SignerInfo 38 // 39 sid: KeyIdentifier, 40 signed_attrs: SignedAttrs, 41 signature: Signature, 42 43 //--- SignedAttributes 44 // 45 message_digest: MessageDigest, 46 signing_time: Option<Time>, 47 binary_signing_time: Option<u64>, 48 } 49 50 /// # Data Access 51 /// 52 impl SignedObject { 53 /// Returns a reference to the object’s content type. content_type(&self) -> &Oid<Bytes>54 pub fn content_type(&self) -> &Oid<Bytes> { 55 &self.content_type 56 } 57 58 /// Returns a reference to the object’s content. content(&self) -> &OctetString59 pub fn content(&self) -> &OctetString { 60 &self.content 61 } 62 63 /// 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>64 pub fn decode_content<F, T>(&self, op: F) -> Result<T, decode::Error> 65 where F: FnOnce(&mut decode::Constructed<OctetStringSource>) 66 -> Result<T, decode::Error> { 67 // XXX Let’s see if using DER here at least holds. 68 Mode::Der.decode(self.content.to_source(), op) 69 } 70 71 /// Returns a reference to the certificate the object is signed with. cert(&self) -> &Cert72 pub fn cert(&self) -> &Cert { 73 &self.cert 74 } 75 } 76 77 /// # Decoding, Validation, and Encoding 78 /// 79 impl SignedObject { 80 /// Decodes a signed object from the given source. decode<S: decode::Source>( source: S, strict: bool ) -> Result<Self, S::Err>81 pub fn decode<S: decode::Source>( 82 source: S, 83 strict: bool 84 ) -> Result<Self, S::Err> { 85 if strict { Mode::Der } 86 else { Mode::Ber } 87 .decode(source, Self::take_from) 88 } 89 90 /// Takes a signed object from an encoded constructed value. take_from<S: decode::Source>( cons: &mut decode::Constructed<S> ) -> Result<Self, S::Err>91 pub fn take_from<S: decode::Source>( 92 cons: &mut decode::Constructed<S> 93 ) -> Result<Self, S::Err> { 94 cons.take_sequence(|cons| { // ContentInfo 95 oid::SIGNED_DATA.skip_if(cons)?; // contentType 96 cons.take_constructed_if(Tag::CTX_0, |cons| { // content 97 cons.take_sequence(|cons| { // SignedData 98 cons.skip_u8_if(3)?; // version -- must be 3 99 let digest_algorithm = 100 DigestAlgorithm::take_set_from(cons)?; 101 let (content_type, content) = { 102 cons.take_sequence(|cons| { // encapContentInfo 103 Ok(( 104 Oid::take_from(cons)?, 105 cons.take_constructed_if( 106 Tag::CTX_0, 107 OctetString::take_from 108 )? 109 )) 110 })? 111 }; 112 let cert = cons.take_constructed_if( // certificates 113 Tag::CTX_0, 114 Cert::take_from 115 )?; 116 // no crls 117 let (sid, attrs, signature) = { // signerInfos 118 cons.take_set(|cons| { 119 cons.take_sequence(|cons| { 120 cons.skip_u8_if(3)?; 121 let sid = cons.take_value_if( 122 Tag::CTX_0, |content| { 123 KeyIdentifier::from_content(content) 124 } 125 )?; 126 let alg = DigestAlgorithm::take_from(cons)?; 127 if alg != digest_algorithm { 128 return Err(decode::Malformed.into()) 129 } 130 let attrs = SignedAttrs::take_from(cons)?; 131 if attrs.2 != content_type { 132 return Err(decode::Malformed.into()) 133 } 134 let signature = Signature::new( 135 SignatureAlgorithm::cms_take_from(cons)?, 136 OctetString::take_from(cons)?.into_bytes() 137 ); 138 // no unsignedAttributes 139 Ok((sid, attrs, signature)) 140 }) 141 })? 142 }; 143 Ok(Self { 144 digest_algorithm, 145 content_type, 146 content, 147 cert, 148 sid, 149 signed_attrs: attrs.0, 150 signature, 151 message_digest: attrs.1, 152 signing_time: attrs.3, 153 binary_signing_time: attrs.4 154 }) 155 }) 156 }) 157 }) 158 } 159 process<F>( self, issuer: &ResourceCert, strict: bool, check_crl: F ) -> Result<(ResourceCert, Bytes), ValidationError> where F: FnOnce(&Cert) -> Result<(), ValidationError>160 pub fn process<F>( 161 self, 162 issuer: &ResourceCert, 163 strict: bool, 164 check_crl: F 165 ) -> Result<(ResourceCert, Bytes), ValidationError> 166 where F: FnOnce(&Cert) -> Result<(), ValidationError> { 167 let res = self.content.clone(); 168 let cert = self.validate(issuer, strict)?; 169 check_crl(cert.as_ref())?; 170 Ok((cert, res.into_bytes())) 171 } 172 173 /// Validates the signed object. 174 /// 175 /// Upon success, the method returns the validated EE certificate of the 176 /// object. validate( self, issuer: &ResourceCert, strict: bool, ) -> Result<ResourceCert, ValidationError>177 pub fn validate( 178 self, 179 issuer: &ResourceCert, 180 strict: bool, 181 ) -> Result<ResourceCert, ValidationError> { 182 self.validate_at(issuer, strict, Time::now()) 183 } 184 185 /// Validates the signed object at he given time. validate_at( self, issuer: &ResourceCert, strict: bool, now: Time, ) -> Result<ResourceCert, ValidationError>186 pub fn validate_at( 187 self, 188 issuer: &ResourceCert, 189 strict: bool, 190 now: Time, 191 ) -> Result<ResourceCert, ValidationError> { 192 self.verify_compliance(strict)?; 193 self.verify_signature(strict)?; 194 self.cert.validate_ee_at(issuer, strict, now) 195 } 196 197 /// Validates that the signed object complies with the specification. 198 /// 199 /// This is item 1 of [RFC 6488]`s section 3. verify_compliance( &self, _strict: bool ) -> Result<(), ValidationError>200 fn verify_compliance( 201 &self, 202 _strict: bool 203 ) -> Result<(), ValidationError> { 204 // Sub-items a, b, d, e, f, g, h, i, j, k, l have been validated while 205 // parsing. This leaves these: 206 // 207 // c. cert is an EE cert with the SubjectKeyIdentifer matching 208 // the sid field of the SignerInfo. 209 if self.sid != self.cert.subject_key_identifier() { 210 return Err(ValidationError) 211 } 212 Ok(()) 213 } 214 215 /// Verifies the signature of the object against contained certificate. 216 /// 217 /// This is item 2 of [RFC 6488]’s section 3. verify_signature(&self, _strict: bool) -> Result<(), ValidationError>218 fn verify_signature(&self, _strict: bool) -> Result<(), ValidationError> { 219 let digest = { 220 let mut context = self.digest_algorithm.start(); 221 self.content.iter().for_each(|x| context.update(x)); 222 context.finish() 223 }; 224 if digest.as_ref() != self.message_digest.as_ref() { 225 return Err(ValidationError) 226 } 227 let msg = self.signed_attrs.encode_verify(); 228 self.cert.subject_public_key_info().verify( 229 &msg, 230 &self.signature 231 ).map_err(Into::into) 232 } 233 234 /// Returns a value encoder for a reference to a signed object. encode_ref(&self) -> impl encode::Values + '_235 pub fn encode_ref(&self) -> impl encode::Values + '_ { 236 encode::sequence(( 237 oid::SIGNED_DATA.encode(), // contentType 238 encode::sequence_as(Tag::CTX_0, // content 239 encode::sequence(( 240 3u8.encode(), // version 241 self.digest_algorithm.encode_set(), // digestAlgorithms 242 encode::sequence(( // encapContentInfo 243 self.content_type.encode_ref(), 244 encode::sequence_as(Tag::CTX_0, 245 self.content.encode_ref() 246 ), 247 )), 248 encode::sequence_as(Tag::CTX_0, // certificates 249 self.cert.encode_ref(), 250 ), 251 // crl -- omitted 252 encode::set( // signerInfo 253 encode::sequence(( // SignerInfo 254 3u8.encode(), // version 255 self.sid.encode_ref_as(Tag::CTX_0), 256 self.digest_algorithm.encode(), // digestAlgorithm 257 self.signed_attrs.encode_ref(), // signedAttrs 258 self.signature.algorithm().cms_encode(), 259 // signatureAlgorithm 260 OctetString::encode_slice( // signature 261 self.signature.value().as_ref() 262 ), 263 // unsignedAttrs omitted 264 )) 265 ) 266 )) 267 ) 268 )) 269 } 270 } 271 272 273 //------------ SignedAttrs --------------------------------------------------- 274 275 /// A private helper type that contains the raw signed attributes content. 276 /// 277 /// These attributes, in their DER encoded form, are what the signature is 278 /// calculated over. Annoyingly, the encoding uses the signed attribute set 279 /// with a tag for SET OF, not \[0\] as it would be found in the actual data. 280 /// 281 /// Technically, signed objects need to be DER encoded, anyway, so we would 282 /// not need to re-encode the signed attributes other than sticking the SET OF 283 /// tag and length in front of them. While we do allow BER encoded objects in 284 /// relaxed mode, those that we have encountered have their signed attributes 285 /// in DER encoding still, so we don’t re-encode. 286 /// 287 /// A `SignedAttrs` value contains the captured content of the signed 288 /// attributes set. That is, it does not contain the tag and length values of 289 /// the outer set object, only two to four sequences of the actual 290 /// attributes. 291 /// 292 /// In order to make sticking tag and length in front of the value easier, we 293 /// allow a maximum length of the s content of 65536 octets. 294 #[derive(Clone, Debug)] 295 pub struct SignedAttrs(Captured); 296 297 impl SignedAttrs { new( content_type: &Oid<impl AsRef<[u8]>>, digest: &MessageDigest, signing_time: Option<Time>, binary_signing_time: Option<u64>, ) -> Self298 pub(crate) fn new( 299 content_type: &Oid<impl AsRef<[u8]>>, 300 digest: &MessageDigest, 301 signing_time: Option<Time>, 302 binary_signing_time: Option<u64>, 303 ) -> Self { 304 // In DER encoding, the values of SET OFs is ordered via the octet 305 // string of their DER encoding. Given that all our values are 306 // SEQUENCEs, their first octet will always be 30. So we only have to 307 // compare the length octets. Unfortunately, two of the values are 308 // variable length, so we need to get creative. 309 310 let mut content_type = Some(encode::sequence(( 311 oid::CONTENT_TYPE.encode(), 312 encode::set( 313 content_type.encode_ref(), 314 ) 315 ))); 316 let mut signing_time = signing_time.map(|time| { 317 encode::sequence(( 318 oid::SIGNING_TIME.encode(), 319 encode::set( 320 time.encode_varied(), 321 ) 322 )) 323 }); 324 let mut message_digest = Some(encode::sequence(( 325 oid::MESSAGE_DIGEST.encode(), 326 encode::set( 327 digest.encode_ref(), 328 ) 329 ))); 330 let mut binary_signing_time = binary_signing_time.map(|time| { 331 encode::sequence(( 332 oid::AA_BINARY_SIGNING_TIME.encode(), 333 encode::set( 334 time.encode() 335 ) 336 )) 337 }); 338 339 let mut len = [ 340 (0, StartOfValue::new(&content_type)), 341 (1, StartOfValue::new(&signing_time)), 342 (2, StartOfValue::new(&message_digest)), 343 (3, StartOfValue::new(&binary_signing_time)), 344 ]; 345 len.sort_by_key(|&(_, len)| len.unwrap()); 346 347 let mut res = Captured::builder(Mode::Der); 348 for &(idx, _) in &len { 349 match idx { 350 0 => { 351 if let Some(val) = content_type.take() { 352 res.extend(val) 353 } 354 } 355 1 => { 356 if let Some(val) = signing_time.take() { 357 res.extend(val) 358 } 359 } 360 2 => { 361 if let Some(val) = message_digest.take() { 362 res.extend(val) 363 } 364 } 365 3 => { 366 if let Some(val) = binary_signing_time.take() { 367 res.extend(val) 368 } 369 } 370 _ => unreachable!() 371 } 372 } 373 374 SignedAttrs(res.freeze()) 375 } 376 377 /// Takes the signed attributes from the beginning of a constructed value. 378 /// 379 /// Returns the raw signed attrs, the message digest, the content type 380 /// object identifier, and the two optional signing times. 381 /// 382 /// If strict is true, any unknown signed attributes are rejected, if 383 /// strict is false they will be ignored. 384 #[allow(clippy::type_complexity)] take_from_with_mode<S: decode::Source>( cons: &mut decode::Constructed<S>, strict: bool ) -> Result< (Self, MessageDigest, Oid<Bytes>, Option<Time>, Option<u64>), S::Err >385 fn take_from_with_mode<S: decode::Source>( 386 cons: &mut decode::Constructed<S>, 387 strict: bool 388 ) -> Result< 389 (Self, MessageDigest, Oid<Bytes>, Option<Time>, Option<u64>), 390 S::Err 391 > { 392 let mut message_digest = None; 393 let mut content_type = None; 394 let mut signing_time = None; 395 let mut binary_signing_time = None; 396 let raw = cons.take_constructed_if(Tag::CTX_0, |cons| { 397 cons.capture(|cons| { 398 while let Some(()) = cons.take_opt_sequence(|cons| { 399 let oid = Oid::take_from(cons)?; 400 if oid == oid::CONTENT_TYPE { 401 Self::take_content_type(cons, &mut content_type) 402 } 403 else if oid == oid::MESSAGE_DIGEST { 404 Self::take_message_digest(cons, &mut message_digest) 405 } 406 else if oid == oid::SIGNING_TIME { 407 Self::take_signing_time(cons, &mut signing_time) 408 } 409 else if oid == oid::AA_BINARY_SIGNING_TIME { 410 Self::take_bin_signing_time( 411 cons, 412 &mut binary_signing_time 413 ) 414 } 415 else if !strict { 416 cons.skip_all() 417 } else { 418 xerr!(Err(decode::Malformed.into())) 419 } 420 })? { } 421 Ok(()) 422 }) 423 })?; 424 if raw.len() > 0xFFFF { 425 return Err(decode::Unimplemented.into()) 426 } 427 let message_digest = match message_digest { 428 Some(some) => MessageDigest(some.into_bytes()), 429 None => return Err(decode::Malformed.into()) 430 }; 431 let content_type = match content_type { 432 Some(some) => some, 433 None => return Err(decode::Malformed.into()) 434 }; 435 Ok(( 436 Self(raw), message_digest, content_type, signing_time, 437 binary_signing_time 438 )) 439 } 440 441 442 443 /// Takes the signed attributes from the beginning of a constructed value. 444 /// 445 /// Returns the raw signed attrs, the message digest, the content type 446 /// object identifier, and the two optional signing times. 447 #[allow(clippy::type_complexity)] take_from<S: decode::Source>( cons: &mut decode::Constructed<S> ) -> Result< (Self, MessageDigest, Oid<Bytes>, Option<Time>, Option<u64>), S::Err >448 pub fn take_from<S: decode::Source>( 449 cons: &mut decode::Constructed<S> 450 ) -> Result< 451 (Self, MessageDigest, Oid<Bytes>, Option<Time>, Option<u64>), 452 S::Err 453 > { 454 Self::take_from_with_mode(cons, true) 455 } 456 457 /// Takes the signed attributes from the beginning of a constructed value. 458 /// 459 /// Note this function should be used for parsing CMS used in RFC6492 and 460 /// RFC8181 messages only, as it will ignore any unknown signed attributes. 461 /// Unfortunately the profile for the Certificates and CMS used is not 462 /// well-defined in these RFCs. So, in this case, we should be more 463 /// accepting. 464 /// 465 /// Returns the raw signed attrs, the message digest, the content type 466 /// object identifier, and the two optional signing times. 467 #[allow(clippy::type_complexity)] take_from_signed_message<S: decode::Source>( cons: &mut decode::Constructed<S> ) -> Result< (Self, MessageDigest, Oid<Bytes>, Option<Time>, Option<u64>), S::Err >468 pub fn take_from_signed_message<S: decode::Source>( 469 cons: &mut decode::Constructed<S> 470 ) -> Result< 471 (Self, MessageDigest, Oid<Bytes>, Option<Time>, Option<u64>), 472 S::Err 473 > { 474 Self::take_from_with_mode(cons, false) 475 } 476 477 /// Parses the Content Type attribute. 478 /// 479 /// This attribute is defined in section 11.1. of RFC 5652. The attribute 480 /// value is a SET of exactly one OBJECT IDENTIFIER. take_content_type<S: decode::Source>( cons: &mut decode::Constructed<S>, content_type: &mut Option<Oid<Bytes>> ) -> Result<(), S::Err>481 fn take_content_type<S: decode::Source>( 482 cons: &mut decode::Constructed<S>, 483 content_type: &mut Option<Oid<Bytes>> 484 ) -> Result<(), S::Err> { 485 update_once(content_type, || { 486 cons.take_set(|cons| Oid::take_from(cons)) 487 }) 488 } 489 take_message_digest<S: decode::Source>( cons: &mut decode::Constructed<S>, message_digest: &mut Option<OctetString> ) -> Result<(), S::Err>490 fn take_message_digest<S: decode::Source>( 491 cons: &mut decode::Constructed<S>, 492 message_digest: &mut Option<OctetString> 493 ) -> Result<(), S::Err> { 494 update_once(message_digest, || { 495 cons.take_set(|cons| OctetString::take_from(cons)) 496 }) 497 } 498 take_signing_time<S: decode::Source>( cons: &mut decode::Constructed<S>, signing_time: &mut Option<Time> ) -> Result<(), S::Err>499 fn take_signing_time<S: decode::Source>( 500 cons: &mut decode::Constructed<S>, 501 signing_time: &mut Option<Time> 502 ) -> Result<(), S::Err> { 503 update_once(signing_time, || { 504 cons.take_set(Time::take_from) 505 }) 506 } 507 take_bin_signing_time<S: decode::Source>( cons: &mut decode::Constructed<S>, bin_signing_time: &mut Option<u64> ) -> Result<(), S::Err>508 fn take_bin_signing_time<S: decode::Source>( 509 cons: &mut decode::Constructed<S>, 510 bin_signing_time: &mut Option<u64> 511 ) -> Result<(), S::Err> { 512 update_once(bin_signing_time, || { 513 cons.take_set(|cons| cons.take_u64()) 514 }) 515 } 516 encode_ref(&self) -> impl encode::Values + '_517 pub fn encode_ref(&self) -> impl encode::Values + '_ { 518 encode::sequence_as(Tag::CTX_0, &self.0) 519 } 520 521 /// Creates the message for verification. encode_verify(&self) -> Vec<u8>522 pub fn encode_verify(&self) -> Vec<u8> { 523 let len = self.0.len(); 524 let mut res = Vec::with_capacity(len + 4); 525 res.push(0x31); // SET 526 if len < 128 { 527 res.push(len as u8) 528 } 529 else if len < 0x10000 { 530 res.push(2); 531 res.push((len >> 8) as u8); 532 res.push(len as u8); 533 } 534 else { 535 panic!("overly long signed attrs"); 536 } 537 res.extend_from_slice(self.0.as_ref()); 538 res 539 } 540 } 541 542 impl AsRef<[u8]> for SignedAttrs { as_ref(&self) -> &[u8]543 fn as_ref(&self) -> &[u8] { 544 self.0.as_ref() 545 } 546 } 547 548 549 //------------ MessageDigest ------------------------------------------------- 550 551 /// A private helper type that contains the message digest attribute. 552 #[derive(Clone, Debug)] 553 pub struct MessageDigest(Bytes); 554 555 impl MessageDigest { encode_ref(&self) -> impl encode::Values + '_556 pub fn encode_ref(&self) -> impl encode::Values + '_ { 557 OctetString::encode_slice(self.0.as_ref()) 558 } 559 } 560 561 impl From<OctetString> for MessageDigest { from(src: OctetString) -> Self562 fn from(src: OctetString) -> Self { 563 MessageDigest(src.into_bytes()) 564 } 565 } 566 567 impl From<Digest> for MessageDigest { from(digest: Digest) -> Self568 fn from(digest: Digest) -> Self { 569 MessageDigest(Bytes::copy_from_slice(digest.as_ref())) 570 } 571 } 572 573 impl AsRef<[u8]> for MessageDigest { as_ref(&self) -> &[u8]574 fn as_ref(&self) -> &[u8] { 575 self.0.as_ref() 576 } 577 } 578 579 580 //------------ SignedObjectBuilder ------------------------------------------- 581 582 #[derive(Clone, Debug)] 583 pub struct SignedObjectBuilder { 584 /// The digest algorithm to be used for the message digest attribute. 585 /// 586 /// By default, this will be the default algorithm. 587 digest_algorithm: DigestAlgorithm, 588 589 /// The serial number of the EE certificate. 590 /// 591 /// Must be provided. 592 serial_number: Serial, 593 594 /// The validity of the EE certificate. 595 /// 596 /// Must be provided. 597 validity: Validity, 598 599 /// The issuer name of the EE certificate. 600 /// 601 /// If this is `None` (the default), it will be generated from the key 602 /// identifier of the EE certificate’s key. 603 issuer: Option<Name>, 604 605 /// The subject name of the EE certificate. 606 /// 607 /// If this is `None` (the default), it will be generated from the key 608 /// identifier of the EE certificate’s key. 609 subject: Option<Name>, 610 611 /// The URI of CRL for the EE certificate. 612 /// 613 /// Must be provided. 614 crl_uri: uri::Rsync, 615 616 /// The URI of the CA certificate issuing the EE certificate. 617 /// 618 /// Must be provided. 619 ca_issuer: uri::Rsync, 620 621 /// The URI of the signed object itself. 622 /// 623 /// Must be provided. 624 signed_object: uri::Rsync, 625 626 /// The IPv4 resources of the EE certificate. 627 /// 628 /// Defaults to not having any. 629 v4_resources: IpResources, 630 631 /// The IPv6 resources of the EE certificate. 632 /// 633 /// Defaults to not having any. 634 v6_resources: IpResources, 635 636 /// The AS resources of the EE certificate. 637 /// 638 /// Defaults to not having any. 639 as_resources: AsResources, 640 641 /// The signing time attribute of the signed object. 642 /// 643 /// This is optional and by default omitted. 644 signing_time: Option<Time>, 645 646 /// The binary signing time attribute of the signed object. 647 /// 648 /// This is optional and by default omitted. 649 binary_signing_time: Option<u64>, 650 } 651 652 impl SignedObjectBuilder { new( serial_number: Serial, validity: Validity, crl_uri: uri::Rsync, ca_issuer: uri::Rsync, signed_object: uri::Rsync ) -> Self653 pub fn new( 654 serial_number: Serial, 655 validity: Validity, 656 crl_uri: uri::Rsync, 657 ca_issuer: uri::Rsync, 658 signed_object: uri::Rsync 659 ) -> Self { 660 Self { 661 digest_algorithm: DigestAlgorithm::default(), 662 serial_number, 663 validity, 664 issuer: None, 665 subject: None, 666 crl_uri, 667 ca_issuer, 668 signed_object, 669 v4_resources: IpResources::missing(), 670 v6_resources: IpResources::missing(), 671 as_resources: AsResources::missing(), 672 signing_time: None, 673 binary_signing_time: None, 674 } 675 } 676 digest_algorithm(&self) -> DigestAlgorithm677 pub fn digest_algorithm(&self) -> DigestAlgorithm { 678 self.digest_algorithm 679 } 680 set_digest_algorithm(&mut self, algorithm: DigestAlgorithm)681 pub fn set_digest_algorithm(&mut self, algorithm: DigestAlgorithm) { 682 self.digest_algorithm = algorithm 683 } 684 serial_number(&self) -> Serial685 pub fn serial_number(&self) -> Serial { 686 self.serial_number 687 } 688 set_serial_number(&mut self, serial: Serial)689 pub fn set_serial_number(&mut self, serial: Serial) { 690 self.serial_number = serial 691 } 692 validity(&self) -> Validity693 pub fn validity(&self) -> Validity { 694 self.validity 695 } 696 set_validity(&mut self, validity: Validity)697 pub fn set_validity(&mut self, validity: Validity) { 698 self.validity = validity 699 } 700 issuer(&self) -> Option<&Name>701 pub fn issuer(&self) -> Option<&Name> { 702 self.issuer.as_ref() 703 } 704 set_issuer(&mut self, name: Option<Name>)705 pub fn set_issuer(&mut self, name: Option<Name>) { 706 self.issuer = name 707 } 708 subject(&self) -> Option<&Name>709 pub fn subject(&self) -> Option<&Name> { 710 self.subject.as_ref() 711 } 712 set_subject(&mut self, name: Option<Name>)713 pub fn set_subject(&mut self, name: Option<Name>) { 714 self.subject = name 715 } 716 crl_uri(&self) -> &uri::Rsync717 pub fn crl_uri(&self) -> &uri::Rsync { 718 &self.crl_uri 719 } 720 set_crl_uri(&mut self, uri: uri::Rsync)721 pub fn set_crl_uri(&mut self, uri: uri::Rsync) { 722 self.crl_uri = uri 723 } 724 ca_issuer(&self) -> &uri::Rsync725 pub fn ca_issuer(&self) -> &uri::Rsync { 726 &self.ca_issuer 727 } 728 set_ca_issuer(&mut self, uri: uri::Rsync)729 pub fn set_ca_issuer(&mut self, uri: uri::Rsync) { 730 self.ca_issuer = uri 731 } 732 signed_object(&self) -> &uri::Rsync733 pub fn signed_object(&self) -> &uri::Rsync { 734 &self.signed_object 735 } 736 set_signed_object(&mut self, uri: uri::Rsync)737 pub fn set_signed_object(&mut self, uri: uri::Rsync) { 738 self.signed_object = uri 739 } 740 741 /// Returns a reference to the IPv4 address resources if present. v4_resources(&self) -> &IpResources742 pub fn v4_resources(&self) -> &IpResources { 743 &self.v4_resources 744 } 745 746 /// Set the IPv4 address resources. set_v4_resources(&mut self, resources: IpResources)747 pub fn set_v4_resources(&mut self, resources: IpResources) { 748 self.v4_resources = resources 749 } 750 751 /// Sets the IPv4 address resources to inherit. set_v4_resources_inherit(&mut self)752 pub fn set_v4_resources_inherit(&mut self) { 753 self.set_v4_resources(IpResources::inherit()) 754 } 755 756 /// Builds the blocks IPv4 address resources. build_v4_resource_blocks<F>(&mut self, op: F) where F: FnOnce(&mut IpBlocksBuilder)757 pub fn build_v4_resource_blocks<F>(&mut self, op: F) 758 where F: FnOnce(&mut IpBlocksBuilder) { 759 let mut builder = IpResourcesBuilder::new(); 760 builder.blocks(op); 761 self.set_v4_resources(builder.finalize()) 762 } 763 764 /// Returns a reference to the IPv6 address resources if present. v6_resources(&self) -> &IpResources765 pub fn v6_resources(&self) -> &IpResources { 766 &self.v6_resources 767 } 768 769 /// Set the IPv6 address resources. set_v6_resources(&mut self, resources: IpResources)770 pub fn set_v6_resources(&mut self, resources: IpResources) { 771 self.v6_resources = resources 772 } 773 774 /// Sets the IPv6 address resources to inherit. set_v6_resources_inherit(&mut self)775 pub fn set_v6_resources_inherit(&mut self) { 776 self.set_v6_resources(IpResources::inherit()) 777 } 778 779 /// Builds the blocks IPv6 address resources. build_v6_resource_blocks<F>(&mut self, op: F) where F: FnOnce(&mut IpBlocksBuilder)780 pub fn build_v6_resource_blocks<F>(&mut self, op: F) 781 where F: FnOnce(&mut IpBlocksBuilder) { 782 let mut builder = IpResourcesBuilder::new(); 783 builder.blocks(op); 784 self.set_v6_resources(builder.finalize()) 785 } 786 787 /// Returns whether the certificate has any IP resources at all. has_ip_resources(&self) -> bool788 pub fn has_ip_resources(&self) -> bool { 789 self.v4_resources.is_present() || self.v6_resources().is_present() 790 } 791 792 /// Returns a reference to the AS resources if present. as_resources(&self) -> &AsResources793 pub fn as_resources(&self) -> &AsResources { 794 &self.as_resources 795 } 796 797 /// Set the AS resources. set_as_resources(&mut self, resources: AsResources)798 pub fn set_as_resources(&mut self, resources: AsResources) { 799 self.as_resources = resources 800 } 801 802 /// Sets the AS resources to inherit. set_as_resources_inherit(&mut self)803 pub fn set_as_resources_inherit(&mut self) { 804 self.set_as_resources(AsResources::inherit()) 805 } 806 807 /// Builds the blocks AS resources. build_as_resource_blocks<F>(&mut self, op: F) where F: FnOnce(&mut AsBlocksBuilder)808 pub fn build_as_resource_blocks<F>(&mut self, op: F) 809 where F: FnOnce(&mut AsBlocksBuilder) { 810 let mut builder = AsResourcesBuilder::new(); 811 builder.blocks(op); 812 self.set_as_resources(builder.finalize()) 813 } 814 815 /// Returns the signing time attribute. signing_time(&self) -> Option<Time>816 pub fn signing_time(&self) -> Option<Time> { 817 self.signing_time 818 } 819 820 /// Sets the signing time attribute. set_signing_time(&mut self, signing_time: Option<Time>)821 pub fn set_signing_time(&mut self, signing_time: Option<Time>) { 822 self.signing_time = signing_time 823 } 824 825 /// Returns the binary signing time attribute. binary_signing_time(&self) -> Option<u64>826 pub fn binary_signing_time(&self) -> Option<u64> { 827 self.binary_signing_time 828 } 829 830 /// Sets the binary signing time attribute. set_binary_signing_time(&mut self, time: Option<u64>)831 pub fn set_binary_signing_time(&mut self, time: Option<u64>) { 832 self.binary_signing_time = time 833 } 834 finalize<S: Signer>( self, content_type: Oid<Bytes>, content: Bytes, signer: &S, issuer_key: &S::KeyId, ) -> Result<SignedObject, SigningError<S::Error>>835 pub fn finalize<S: Signer>( 836 self, 837 content_type: Oid<Bytes>, 838 content: Bytes, 839 signer: &S, 840 issuer_key: &S::KeyId, 841 ) -> Result<SignedObject, SigningError<S::Error>> { 842 let issuer_pub = signer.get_key_info(issuer_key)?; 843 844 // Produce signed attributes. 845 let message_digest = self.digest_algorithm.digest(&content).into(); 846 let signed_attrs = SignedAttrs::new( 847 &content_type, 848 &message_digest, 849 self.signing_time, 850 self.binary_signing_time 851 ); 852 853 // Sign signed attributes with a one-off key. 854 let (signature, key_info) = signer.sign_one_off( 855 SignatureAlgorithm::default(), &signed_attrs.encode_verify() 856 )?; 857 let sid = KeyIdentifier::from_public_key(&key_info); 858 859 // Make the certificate. 860 let mut cert = TbsCert::new( 861 self.serial_number, 862 self.issuer.unwrap_or_else(|| issuer_pub.to_subject_name()), 863 self.validity, 864 self.subject, 865 key_info, 866 KeyUsage::Ee, 867 Overclaim::Refuse, 868 ); 869 cert.set_authority_key_identifier(Some(issuer_pub.key_identifier())); 870 cert.set_crl_uri(Some(self.crl_uri)); 871 cert.set_ca_issuer(Some(self.ca_issuer)); 872 cert.set_signed_object(Some(self.signed_object)); 873 cert.set_v4_resources(self.v4_resources); 874 cert.set_v6_resources(self.v6_resources); 875 cert.set_as_resources(self.as_resources); 876 let cert = cert.into_cert(signer, issuer_key)?; 877 878 Ok(SignedObject { 879 digest_algorithm: self.digest_algorithm, 880 content_type, 881 content: OctetString::new(content), 882 cert, 883 sid, 884 signed_attrs, 885 signature, 886 message_digest, 887 signing_time: self.signing_time, 888 binary_signing_time: self.binary_signing_time, 889 }) 890 } 891 } 892 893 894 //------------ StartOfValue -------------------------------------------------- 895 896 /// Helper type for ordering signed attributes. 897 /// 898 /// It keeps the first eight octets of a value which should be enough to 899 /// cover the length. 900 #[derive(Clone, Copy, Debug)] 901 struct StartOfValue { 902 res: [u8; 8], 903 pos: usize, 904 } 905 906 impl StartOfValue { new<V: encode::Values>(values: &V) -> Self907 fn new<V: encode::Values>(values: &V) -> Self { 908 let mut res = StartOfValue { 909 res: [0; 8], 910 pos: 0 911 }; 912 values.write_encoded(Mode::Der, &mut res).unwrap(); 913 res 914 } 915 unwrap(self) -> [u8; 8]916 fn unwrap(self) -> [u8; 8] { 917 self.res 918 } 919 } 920 921 impl io::Write for StartOfValue { write(&mut self, buf: &[u8]) -> Result<usize, io::Error>922 fn write(&mut self, buf: &[u8]) -> Result<usize, io::Error> { 923 let slice = &mut self.res[self.pos..]; 924 let len = cmp::min(slice.len(), buf.len()); 925 slice[..len].copy_from_slice(&buf[..len]); 926 self.pos += len; 927 Ok(buf.len()) 928 } 929 flush(&mut self) -> Result<(), io::Error>930 fn flush(&mut self) -> Result<(), io::Error> { 931 Ok(()) 932 } 933 } 934 935 936 //============ Tests ========================================================= 937 938 #[cfg(test)] 939 mod test { 940 use crate::repository::tal::TalInfo; 941 use super::*; 942 943 #[test] decode()944 fn decode() { 945 let talinfo = TalInfo::from_name("foo".into()).into_arc(); 946 let at = Time::utc(2019, 5, 1, 0, 0, 0); 947 let issuer = Cert::decode( 948 include_bytes!("../../test-data/ta.cer").as_ref() 949 ).unwrap(); 950 let issuer = issuer.validate_ta_at(talinfo, false, at).unwrap(); 951 let obj = SignedObject::decode( 952 include_bytes!("../../test-data/ta.mft").as_ref(), 953 false 954 ).unwrap(); 955 obj.validate_at(&issuer, false, at).unwrap(); 956 let obj = SignedObject::decode( 957 include_bytes!("../../test-data/ca1.mft").as_ref(), 958 false 959 ).unwrap(); 960 assert!(obj.validate_at(&issuer, false, at).is_err()); 961 } 962 } 963 964 #[cfg(all(test, feature="softkeys"))] 965 mod signer_test { 966 use std::str::FromStr; 967 use bcder::Oid; 968 use bcder::encode::Values; 969 use crate::uri; 970 use crate::repository::crypto::PublicKeyFormat; 971 use crate::repository::crypto::softsigner::OpenSslSigner; 972 use crate::repository::resources::{AsId, Prefix}; 973 use crate::repository::tal::TalInfo; 974 use super::*; 975 976 #[test] encode_signed_object()977 fn encode_signed_object() { 978 let mut signer = OpenSslSigner::new(); 979 let key = signer.create_key(PublicKeyFormat::Rsa).unwrap(); 980 let pubkey = signer.get_key_info(&key).unwrap(); 981 let uri = uri::Rsync::from_str("rsync://example.com/m/p").unwrap(); 982 983 let mut cert = TbsCert::new( 984 12u64.into(), pubkey.to_subject_name(), 985 Validity::from_secs(86400), None, pubkey, KeyUsage::Ca, 986 Overclaim::Trim 987 ); 988 cert.set_basic_ca(Some(true)); 989 cert.set_ca_repository(Some(uri.clone())); 990 cert.set_rpki_manifest(Some(uri.clone())); 991 cert.build_v4_resource_blocks(|b| b.push(Prefix::new(0, 0))); 992 cert.build_v6_resource_blocks(|b| b.push(Prefix::new(0, 0))); 993 cert.build_as_resource_blocks(|b| b.push((AsId::MIN, AsId::MAX))); 994 let cert = cert.into_cert(&signer, &key).unwrap(); 995 996 let mut sigobj = SignedObjectBuilder::new( 997 12u64.into(), Validity::from_secs(86400), uri.clone(), 998 uri.clone(), uri.clone() 999 ); 1000 sigobj.set_v4_resources_inherit(); 1001 let sigobj = sigobj.finalize( 1002 Oid(oid::SIGNED_DATA.0.into()), 1003 Bytes::from(b"1234".as_ref()), 1004 &signer, 1005 &key, 1006 ).unwrap(); 1007 let sigobj = sigobj.encode_ref().to_captured(Mode::Der); 1008 1009 let sigobj = SignedObject::decode(sigobj.as_slice(), true).unwrap(); 1010 let cert = cert.validate_ta( 1011 TalInfo::from_name("foo".into()).into_arc(), true 1012 ).unwrap(); 1013 sigobj.validate(&cert, true).unwrap(); 1014 } 1015 } 1016 1017 1018 //============ Specification Documentation =================================== 1019 1020 /// Signed Objects Specification. 1021 /// 1022 /// This is a documentation-only module. It summarizes the specification for 1023 /// signed objects, how they are to be parsed and constructed. 1024 /// 1025 /// Signed objects are CMS signed objects that have been severly limited in 1026 /// the options of the various fields. They are specified in [RFC 6488] while 1027 /// CMS is specified in [RFC 5652]. 1028 /// 1029 /// A signed object is a CMS object with a single signed data object in it. 1030 /// 1031 /// A CMS object is: 1032 /// 1033 /// ```txt 1034 /// ContentInfo ::= SEQUENCE { 1035 /// contentType ContentType, 1036 /// content [0] EXPLICIT ANY DEFINED BY contentType } 1037 /// ``` 1038 /// 1039 /// For a signed object, the _contentType_ must be `oid::SIGNED_DATA` and the 1040 /// _content_ a _SignedData_ object (however, note the `[0] EXPLICIT` there) 1041 /// as follows: 1042 /// 1043 /// ```txt 1044 /// SignedData ::= SEQUENCE { 1045 /// version CMSVersion, 1046 /// digestAlgorithms DigestAlgorithmIdentifiers, 1047 /// encapContentInfo EncapsulatedContentInfo, 1048 /// certificates [0] IMPLICIT CertificateSet OPTIONAL, 1049 /// crls [1] IMPLICIT RevocationInfoChoices OPTIONAL, 1050 /// signerInfos SignerInfos } 1051 /// 1052 /// EncapsulatedContentInfo ::= SEQUENCE { 1053 /// eContentType ContentType, 1054 /// eContent [0] EXPLICIT OCTET STRING OPTIONAL } 1055 /// 1056 /// CertificateSet ::= SET OF CertificateChoices 1057 /// 1058 /// CertificateChoices ::= CHOICE { 1059 /// certificate Certificate, 1060 /// extendedCertificate [0] IMPLICIT ExtendedCertificate, -- Obsolete 1061 /// v1AttrCert [1] IMPLICIT AttributeCertificateV1,-- Obsolete 1062 /// v2AttrCert [2] IMPLICIT AttributeCertificateV2, 1063 /// other [3] IMPLICIT OtherCertificateFormat } 1064 /// ``` 1065 /// 1066 /// Limitations imposed by [RFC 6488] are as follows: 1067 /// 1068 /// * The _version_ must be 3. 1069 /// * The _digestAlgorithms_ set must be exactly one algorithm chosen from 1070 /// those defined in [RFC 7935]. The [`DigestAlgorithm`] type implements 1071 /// both the _DigestAlgorithmIdentifier_ and _DigestAlgorithmIndentifiers_ 1072 /// definitions (the latter via `take_set_from` and `encode_set`). 1073 /// * The _eContentType_ field of _encapContentInfo_ defines the type of an 1074 /// object. Check the specific signed objects for their matching object ID. 1075 /// * The _eContent_ field of _encapContentInfo_ must be present and contain 1076 /// the actual content of the signed object. 1077 /// * There must be exactly one certificate in the `certificates` set. It must 1078 /// be of the _certificate_ choice (that’s not exactly in RFC 6488, but it 1079 /// is the only logical choice for ‘the RPKI end-entity (EE) certificate 1080 /// needed to validate this signed object’), which in practice means it is 1081 /// just one [`Cert`]. 1082 /// * The _crls_ field must be omitted. 1083 /// 1084 /// The _SignerInfos_ structure: 1085 /// 1086 /// ```txt 1087 /// 1088 /// SignerInfos ::= SET OF SignerInfo 1089 /// 1090 /// SignerInfo ::= SEQUENCE { 1091 /// version CMSVersion, 1092 /// sid SignerIdentifier, 1093 /// digestAlgorithm DigestAlgorithmIdentifier, 1094 /// signedAttrs [0] IMPLICIT SignedAttributes OPTIONAL, 1095 /// signatureAlgorithm SignatureAlgorithmIdentifier, 1096 /// signature SignatureValue, 1097 /// unsignedAttrs [1] IMPLICIT UnsignedAttributes OPTIONAL } 1098 /// 1099 /// SignerIdentifier ::= CHOICE { 1100 /// issuerAndSerialNumber IssuerAndSerialNumber, 1101 /// subjectKeyIdentifier [0] EXPLICIT SubjectKeyIdentifier } 1102 /// 1103 /// SubjectKeyIdentifier ::= OCTET STRING 1104 /// 1105 /// SignatureValue ::= OCTET STRING 1106 /// ``` 1107 /// 1108 /// Limitations are as follows: 1109 /// 1110 /// * There must be exactly one _SignerInfo_ present. 1111 /// * The _version_ must be 3. 1112 /// * The _sid_ must be identical to the value of the Subject Key Identifier 1113 /// extension of the included certificate. I.e., it must be the second 1114 /// choice. 1115 /// * The _digestAlgorithm_ must be the same as the only value in the outer 1116 /// _digestAlgorthm_ field. 1117 /// * The _signedAttrs_ field must be present. See below. 1118 /// * For the content of the _signature_ field, see below. 1119 /// * The _unsignedAttrs_ field must be omitted. 1120 /// 1121 /// Finally, _SignedAttributes_ is a sequence of attributes keyed by an OID. 1122 /// RPKI has two mandatory and two optional attributes. Definition for all 1123 /// of these is the following: 1124 /// 1125 /// ```text 1126 /// SignedAttributes ::= SET SIZE (1..MAX) OF Attribute 1127 /// 1128 /// Attribute ::= SEQUENCE { 1129 /// attrType OBJECT IDENTIFIER, 1130 /// attrValues SET OF AttributeValue } 1131 /// 1132 /// ContentType ::= OBJECT IDENTIFIER 1133 /// 1134 /// MessageDigest ::= OCTET STRING 1135 /// 1136 /// SigningTime ::= Time 1137 /// 1138 /// Time ::= CHOICE { 1139 /// utcTime UTCTime, 1140 /// generalizedTime GeneralizedTime } 1141 /// 1142 /// BinarySigningTime ::= BinaryTime 1143 /// 1144 /// BinaryTime ::= INTEGER (0..MAX) 1145 /// ``` 1146 /// 1147 /// The two mandatory attributes are _ContentType_ and _MessageDigest_. The 1148 /// content type attribute must be the same as the _eContentType_ field of 1149 /// the _encapContentInfo_. The message digest attribute contains the digest 1150 /// value of the (actual) content. 1151 /// 1152 /// The _SigningTime_ and _BinarySigningTime_ attributes are optional. Their 1153 /// presence is not considered when validating a signed object. 1154 /// 1155 /// No other attribute may be present. 1156 /// 1157 /// For the object identifiers of the attributes, see the [`oid`] module. 1158 /// 1159 /// The _signature_ field of the signed object contains a signature over the 1160 /// DER encoding of the _signedAttrs_ field. When calculating the signature, 1161 /// the normal tag for the SET is used instead of the implicit `[0]`. 1162 /// 1163 /// [RFC 5652]: https://tools.ietf.org/html/rfc5652 1164 /// [RFC 6488]: https://tools.ietf.org/html/rfc6488 1165 /// [RFC 7935]: https://tools.ietf.org/html/rfc7935 1166 /// [`Cert`]: ../../cert/struct.Cert.html 1167 /// [`DigestAlgorithm`]: ../../crypto/keys/struct.DigestAlgorithm.html 1168 /// [`oid`]: ../../oid/index.html 1169 pub mod spec { } 1170 1171 1172