/ crates / tor-key-forge / src / certs.rs
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  }