Skip to main content

tor_key_forge/
certs.rs

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