certs.rs
1 //! Helpers for encoding certificate material. 2 3 use crate::{CertType, ErasedKey, InvalidCertError, KeyUnknownCert, Result}; 4 use tor_cert::{Ed25519Cert, EncodedEd25519Cert, SigCheckedCert, UncheckedCert}; 5 use tor_llcrypto::pk::ed25519::{self, Ed25519Identity}; 6 7 use std::{result::Result as StdResult, time::SystemTime}; 8 9 /// A key certificate. 10 #[derive(Clone, Debug)] 11 #[non_exhaustive] 12 pub enum CertData { 13 /// A tor-specific ed25519 cert. 14 TorEd25519Cert(EncodedEd25519Cert), 15 } 16 17 impl CertData { 18 /// Convert the cert material into a known cert type, 19 /// and return the type-erased value. 20 /// 21 /// The caller is expected to downcast the value returned to the correct concrete type. 22 #[allow(clippy::unnecessary_wraps)] 23 pub(crate) fn into_erased(self) -> Result<ErasedKey> { 24 match self { 25 Self::TorEd25519Cert(cert) => Ok(Box::new(cert)), 26 } 27 } 28 29 /// Get the [`CertType`] of this cert. 30 pub(crate) fn cert_type(&self) -> CertType { 31 match self { 32 CertData::TorEd25519Cert(_) => CertType::Ed25519TorCert, 33 } 34 } 35 } 36 37 // TODO: maybe all of this belongs in tor-cert? 38 // 39 // The types defined here are all wrappers over various tor-cert types 40 // plus the raw certificate representation (needed to reconstruct 41 // the `EncodedEd25519Cert` without having to encode + sign the certificate) 42 43 /// A parsed `EncodedEd25519Cert`. 44 #[derive(Debug, Clone, derive_more::AsRef)] 45 pub struct ParsedEd25519Cert { 46 /// The parsed cert. 47 #[as_ref] 48 parsed_cert: KeyUnknownCert, 49 /// The raw, unparsed cert. 50 raw: Vec<u8>, 51 } 52 53 impl ParsedEd25519Cert { 54 /// Parse the byte representation of the specified cert. 55 pub fn decode(raw: Vec<u8>) -> StdResult<Self, tor_bytes::Error> { 56 let parsed_cert = Ed25519Cert::decode(&raw)?; 57 Ok(Self { parsed_cert, raw }) 58 } 59 60 /// Declare that this should be a certificate signed with a given key. 61 /// 62 /// See [`KeyUnknownCert::should_be_signed_with`]. 63 pub fn should_be_signed_with( 64 self, 65 pkey: &ed25519::Ed25519Identity, 66 ) -> StdResult<UncheckedEd25519Cert, tor_cert::CertError> { 67 let Self { parsed_cert, raw } = self; 68 69 let cert = parsed_cert.should_be_signed_with(pkey)?; 70 71 Ok(UncheckedEd25519Cert { cert, raw }) 72 } 73 } 74 75 /// A parsed `EncodedEd25519Cert`. 76 pub struct UncheckedEd25519Cert { 77 /// The parsed, unchecked cert. 78 cert: UncheckedCert, 79 /// The raw, unparsed cert. 80 raw: Vec<u8>, 81 } 82 83 impl tor_checkable::SelfSigned<SigCheckedEd25519Cert> for UncheckedEd25519Cert { 84 type Error = tor_cert::CertError; 85 86 fn is_well_signed(&self) -> StdResult<(), tor_cert::CertError> { 87 self.cert.is_well_signed() 88 } 89 90 fn dangerously_assume_wellsigned(self) -> SigCheckedEd25519Cert { 91 let Self { cert, raw } = self; 92 93 let cert = cert.dangerously_assume_wellsigned(); 94 SigCheckedEd25519Cert { cert, raw } 95 } 96 } 97 98 /// A signature-checked `EncodedEd25519Cert`. 99 pub struct SigCheckedEd25519Cert { 100 /// The parsed, checked cert. 101 cert: SigCheckedCert, 102 /// The raw, unparsed cert. 103 raw: Vec<u8>, 104 } 105 106 impl tor_checkable::Timebound<ValidatedEd25519Cert> for SigCheckedEd25519Cert { 107 type Error = tor_checkable::TimeValidityError; 108 109 fn is_valid_at(&self, t: &SystemTime) -> StdResult<(), Self::Error> { 110 self.cert.is_valid_at(t) 111 } 112 113 fn dangerously_assume_timely(self) -> ValidatedEd25519Cert { 114 let Self { cert, raw } = self; 115 116 let cert = cert.dangerously_assume_timely(); 117 ValidatedEd25519Cert { cert, raw } 118 } 119 } 120 121 /// A well-signed and timely `EncodedEd25519Cert`. 122 #[derive(Debug, Clone, derive_more::AsRef)] 123 pub struct ValidatedEd25519Cert { 124 /// The parsed, validated cert. 125 #[as_ref] 126 cert: Ed25519Cert, 127 /// The raw, unparsed cert. 128 raw: Vec<u8>, 129 } 130 131 impl ValidatedEd25519Cert { 132 /// Return the subject key of this certificate. 133 pub fn subject_key(&self) -> StdResult<&Ed25519Identity, InvalidCertError> { 134 match self.cert.subject_key() { 135 tor_cert::CertifiedKey::Ed25519(ed25519_identity) => Ok(ed25519_identity), 136 _ => Err(InvalidCertError::InvalidSubjectKeyAlgorithm), 137 } 138 } 139 140 /// Return the encoded representation of this cert as a `EncodedEd25519Cert`. 141 pub fn into_encoded(self) -> EncodedEd25519Cert { 142 EncodedEd25519Cert::dangerously_from_bytes(&self.raw) 143 } 144 }