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
48
    pub fn decode(raw: Vec<u8>) -> StdResult<Self, tor_bytes::Error> {
56
48
        let parsed_cert = Ed25519Cert::decode(&raw)?;
57
48
        Ok(Self { parsed_cert, raw })
58
48
    }
59

            
60
    /// Declare that this should be a certificate signed with a given key.
61
    ///
62
    /// See [`KeyUnknownCert::should_be_signed_with`].
63
48
    pub fn should_be_signed_with(
64
48
        self,
65
48
        pkey: &ed25519::Ed25519Identity,
66
48
    ) -> StdResult<UncheckedEd25519Cert, tor_cert::CertError> {
67
48
        let Self { parsed_cert, raw } = self;
68

            
69
48
        let cert = parsed_cert.should_be_signed_with(pkey)?;
70

            
71
48
        Ok(UncheckedEd25519Cert { cert, raw })
72
48
    }
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
48
    fn dangerously_assume_wellsigned(self) -> SigCheckedEd25519Cert {
91
48
        let Self { cert, raw } = self;
92
48

            
93
48
        let cert = cert.dangerously_assume_wellsigned();
94
48
        SigCheckedEd25519Cert { cert, raw }
95
48
    }
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
48
    fn dangerously_assume_timely(self) -> ValidatedEd25519Cert {
114
48
        let Self { cert, raw } = self;
115
48

            
116
48
        let cert = cert.dangerously_assume_timely();
117
48
        ValidatedEd25519Cert { cert, raw }
118
48
    }
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
48
    pub fn subject_key(&self) -> StdResult<&Ed25519Identity, InvalidCertError> {
134
48
        match self.cert.subject_key() {
135
48
            tor_cert::CertifiedKey::Ed25519(ed25519_identity) => Ok(ed25519_identity),
136
            _ => Err(InvalidCertError::InvalidSubjectKeyAlgorithm),
137
        }
138
48
    }
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
}