tor_key_forge/
certs.rs

1//! Helpers for encoding certificate material.
2
3use crate::{CertType, ErasedKey, InvalidCertError, KeyUnknownCert, Result};
4use tor_cert::{Ed25519Cert, EncodedEd25519Cert, SigCheckedCert, UncheckedCert};
5use tor_llcrypto::pk::ed25519::{self, Ed25519Identity};
6
7use std::{result::Result as StdResult, time::SystemTime};
8
9/// A key certificate.
10#[derive(Clone, Debug)]
11#[non_exhaustive]
12pub enum CertData {
13    /// A tor-specific ed25519 cert.
14    TorEd25519Cert(EncodedEd25519Cert),
15}
16
17impl 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)]
45pub struct ParsedEd25519Cert {
46    /// The parsed cert.
47    #[as_ref]
48    parsed_cert: KeyUnknownCert,
49    /// The raw, unparsed cert.
50    raw: Vec<u8>,
51}
52
53impl 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`.
76pub struct UncheckedEd25519Cert {
77    /// The parsed, unchecked cert.
78    cert: UncheckedCert,
79    /// The raw, unparsed cert.
80    raw: Vec<u8>,
81}
82
83impl 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`.
99pub struct SigCheckedEd25519Cert {
100    /// The parsed, checked cert.
101    cert: SigCheckedCert,
102    /// The raw, unparsed cert.
103    raw: Vec<u8>,
104}
105
106impl 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)]
123pub struct ValidatedEd25519Cert {
124    /// The parsed, validated cert.
125    #[as_ref]
126    cert: Ed25519Cert,
127    /// The raw, unparsed cert.
128    raw: Vec<u8>,
129}
130
131impl 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}