diff --git a/commons/src/remote/builder.rs b/commons/src/remote/builder.rs index 78ae4bfd..ac0b3d9d 100644 --- a/commons/src/remote/builder.rs +++ b/commons/src/remote/builder.rs @@ -1,20 +1,20 @@ //! Support for building RPKI Certificates and Objects +use std::fmt; use bcder::encode::{Constructed, PrimitiveContent, Values}; use bcder::{decode, encode}; use bcder::{BitString, Mode, OctetString, Oid, Tag}; use bytes::Bytes; use chrono::Utc; -use rpki::cert::ext::{AuthorityKeyIdentifier, CrlNumber, Extensions, KeyIdentifier}; -use rpki::crl::Crl; +use rpki::cert::ext::{CrlNumber, Extensions, KeyIdentifier}; use rpki::crypto::signer::KeyError; use rpki::crypto::{ DigestAlgorithm, PublicKey, Signature, SignatureAlgorithm, Signer, SigningError, }; use rpki::oid; use rpki::x509::{Name, Time, Validity}; -use std::fmt; use crate::remote::id::{IdCert, IdExtensions}; +use crate::remote::sigmsg::SigMsgCrl; //------------ TbsCertificate ------------------------------------------------ @@ -225,7 +225,7 @@ pub struct SignedMessageBuilder { content: OctetString, signer_info: SignedSignerInfo, ee_cert: IdCert, - crl: Crl, + crl: SigMsgCrl, } impl SignedMessageBuilder { @@ -240,7 +240,7 @@ impl SignedMessageBuilder { let ee_cert = IdCertBuilder::new_ee_cert(issuing_key, signer_info.one_off_key(), signer)?; - let crl = CrlBuilder::create(issuing_key, signer)?; + let crl = SigMsgCrlBuilder::create(issuing_key, signer)?; Ok(SignedMessageBuilder { content, @@ -470,29 +470,22 @@ impl SignerInfoBuilder { //------------ CrlBuilder ---------------------------------------------------- -pub struct CrlBuilder; +pub struct SigMsgCrlBuilder; -impl CrlBuilder { - /// Creates a CRL for use with protocol messages. I.e. it revokes nothing, - /// because smart people use single use keys for EE certs, and it's valid - /// for, like, forever -- cause really this thing is useless. Still it is - /// mandatory, so make one (1) and re-use it. - /// - /// This will all be changed in future when we implement generating CRLs - /// for the RPKI CA. - pub fn create(issuing_key: &S::KeyId, signer: &S) -> Result> { +impl SigMsgCrlBuilder { + /// Creates a CRL for use with protocol messages. This revokes nothing, + /// because we use single use keys for EE certs. + pub fn create( + issuing_key: &S::KeyId, + signer: &S, + ) -> Result> { let pub_key = signer.get_key_info(issuing_key)?; let name = Name::from_pub_key(&pub_key); - let now = Time::new(Utc::now()); - let eternity = Time::new(Utc::now() + ::chrono::Duration::weeks(52000)); + let just_now = Time::new(Utc::now()) - ::chrono::Duration::minutes(5); + let in_a_bit = Time::new(Utc::now() + ::chrono::Duration::minutes(5)); let crl_number = CrlNumber::new(1); - let aki = AuthorityKeyIdentifier::new(&pub_key); - - let extensions = Constructed::new( - Tag::CTX_0, - encode::sequence((aki.encode(), crl_number.encode())), - ); + let extensions = Constructed::new(Tag::CTX_0, encode::sequence(crl_number.encode())); let crl_data = encode::sequence(( ( @@ -501,8 +494,8 @@ impl CrlBuilder { name.encode_ref(), ), ( - now.encode(), - eternity.encode(), + just_now.encode(), + in_a_bit.encode(), // Real revocations go here extensions, ), @@ -526,7 +519,7 @@ impl CrlBuilder { signature.encode(), )); - let crl = Crl::decode(crl_obj.to_captured(Mode::Der).as_ref())?; + let crl = SigMsgCrl::decode(crl_obj.to_captured(Mode::Der).as_ref())?; Ok(crl) } @@ -602,7 +595,7 @@ pub mod tests { let key_id = s.create_key(&PublicKeyAlgorithm::RsaEncryption).unwrap(); let key_info = s.get_key_info(&key_id).unwrap(); - let crl = CrlBuilder::create(&key_id, &mut s).unwrap(); + let crl = SigMsgCrlBuilder::create(&key_id, &mut s).unwrap(); crl.validate(&key_info).unwrap(); }) } diff --git a/commons/src/remote/sigmsg.rs b/commons/src/remote/sigmsg.rs index 8ebd3bea..9c0dd91f 100644 --- a/commons/src/remote/sigmsg.rs +++ b/commons/src/remote/sigmsg.rs @@ -3,14 +3,14 @@ use bytes::Bytes; -use bcder::decode; use bcder::string::OctetString; +use bcder::{decode, encode, Captured}; use bcder::{Mode, Oid, Tag}; -use rpki::crypto::{DigestAlgorithm, KeyIdentifier, Signature, SignatureAlgorithm}; +use rpki::crypto::{DigestAlgorithm, KeyIdentifier, PublicKey, Signature, SignatureAlgorithm}; use rpki::oid; use rpki::sigobj::{MessageDigest, SignedAttrs}; -use rpki::x509::{Time, ValidationError}; +use rpki::x509::{SignedData, Time, ValidationError}; use crate::remote::id::IdCert; @@ -29,6 +29,7 @@ pub struct SignedMessage { content_type: Oid, content: OctetString, id_cert: IdCert, + crl: SigMsgCrl, //--- From SignerInfo // @@ -83,7 +84,7 @@ impl SignedMessage { let id_cert = Self::take_certificates(cons)?; - let _whatever = Self::drop_crls(cons); + let crl = Self::take_crl(cons)?; let (sid, attrs, signature) = { // signerInfos @@ -116,6 +117,7 @@ impl SignedMessage { content_type, content, id_cert, + crl, sid, signed_attrs: attrs.0, @@ -144,18 +146,13 @@ impl SignedMessage { }) } - // Drop the CRLs, if present. + // Take the CRL, if present. // - // The ones from DRL don't seem to parse, and their value is - // is very limited. - // - // These CRLs only really protect if an operator use multi-use - // keys for their EE certificates and is given some frequently - // re-signed CRL by the CA cert for inclusion.. then if the EE - // key is stolen you get a bit of protection. - // - fn drop_crls(cons: &mut decode::Constructed) -> Result<(), S::Err> { - cons.take_constructed_if(Tag::CTX_1, |cons| cons.skip_all()) + // In theory there could be multiple CRLs, one for each CA certificate included in signing + // this object. However, nobody seems to do this, and it's rather poorly defined how (and why) + // this would be done. So.. just expecting 1 CRL here. + fn take_crl(cons: &mut decode::Constructed) -> Result { + cons.take_constructed_if(Tag::CTX_1, |cons| SigMsgCrl::take_from(cons)) } } @@ -197,6 +194,54 @@ impl SignedMessage { } } +//------------ SigMsgCrl ----------------------------------------------------- + +/// An RPKI certificate revocation list used in RFC6492 and RFC8181 protocol signed +/// messages. +#[derive(Clone, Debug)] +pub struct SigMsgCrl { + /// The outer structure of the CRL. + signed_data: SignedData, +} + +/// # Decode, Validate, and Encode +/// +impl SigMsgCrl { + /// Parses a source as a certificate revocation list. + pub fn decode(source: S) -> Result { + Mode::Der.decode(source, Self::take_from) + } + + /// Takes an encoded CRL from the beginning of a constructed value. + pub fn take_from(cons: &mut decode::Constructed) -> Result { + cons.take_sequence(Self::from_constructed) + } + + /// Parses the content of a certificate revocation list. + pub fn from_constructed( + cons: &mut decode::Constructed, + ) -> Result { + let signed_data = SignedData::from_constructed(cons)?; + Ok(Self { signed_data }) + } + + /// Validates the certificate revocation list. + /// + /// The list’s signature is validated against the provided public key. + pub fn validate(&self, public_key: &PublicKey) -> Result<(), ValidationError> { + self.signed_data.verify_signature(public_key) + } + + pub fn encode_ref<'a>(&'a self) -> impl encode::Values + 'a { + self.signed_data.encode_ref() + } + + /// Returns a captured encoding of the CRL. + pub fn to_captured(&self) -> Captured { + Captured::from_values(Mode::Der, self.encode_ref()) + } +} + //------------ Tests --------------------------------------------------------- #[cfg(test)]