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