1
//! Helpers for encoding certificate material.
2

            
3
use crate::{CertType, InvalidCertError, KeyUnknownCert};
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
    /// Get the [`CertType`] of this cert.
19
2088
    pub(crate) fn cert_type(&self) -> CertType {
20
2088
        match self {
21
2088
            CertData::TorEd25519Cert(_) => CertType::Ed25519TorCert,
22
        }
23
2088
    }
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)]
34
pub struct ParsedEd25519Cert {
35
    /// The parsed cert.
36
    #[as_ref]
37
    parsed_cert: KeyUnknownCert,
38
    /// The raw, unparsed cert.
39
    raw: Vec<u8>,
40
}
41

            
42
impl ParsedEd25519Cert {
43
    /// Parse the byte representation of the specified cert.
44
174
    pub fn decode(raw: Vec<u8>) -> StdResult<Self, tor_bytes::Error> {
45
174
        let parsed_cert = Ed25519Cert::decode(&raw)?;
46
174
        Ok(Self { parsed_cert, raw })
47
174
    }
48

            
49
    /// Declare that this should be a certificate signed with a given key.
50
    ///
51
    /// See [`KeyUnknownCert::should_be_signed_with`].
52
174
    pub fn should_be_signed_with(
53
174
        self,
54
174
        pkey: &ed25519::Ed25519Identity,
55
174
    ) -> StdResult<UncheckedEd25519Cert, tor_cert::CertError> {
56
174
        let Self { parsed_cert, raw } = self;
57

            
58
174
        let cert = parsed_cert.should_be_signed_with(pkey)?;
59

            
60
174
        Ok(UncheckedEd25519Cert { cert, raw })
61
174
    }
62
}
63

            
64
/// A parsed `EncodedEd25519Cert`.
65
pub struct UncheckedEd25519Cert {
66
    /// The parsed, unchecked cert.
67
    cert: UncheckedCert,
68
    /// The raw, unparsed cert.
69
    raw: Vec<u8>,
70
}
71

            
72
impl tor_checkable::SelfSigned<SigCheckedEd25519Cert> for UncheckedEd25519Cert {
73
    type Error = tor_cert::CertError;
74

            
75
116
    fn is_well_signed(&self) -> StdResult<(), tor_cert::CertError> {
76
116
        self.cert.is_well_signed()
77
116
    }
78

            
79
174
    fn dangerously_assume_wellsigned(self) -> SigCheckedEd25519Cert {
80
174
        let Self { cert, raw } = self;
81

            
82
174
        let cert = cert.dangerously_assume_wellsigned();
83
174
        SigCheckedEd25519Cert { cert, raw }
84
174
    }
85
}
86

            
87
/// A signature-checked `EncodedEd25519Cert`.
88
pub struct SigCheckedEd25519Cert {
89
    /// The parsed, checked cert.
90
    cert: SigCheckedCert,
91
    /// The raw, unparsed cert.
92
    raw: Vec<u8>,
93
}
94

            
95
impl tor_checkable::Timebound<ValidatedEd25519Cert> for SigCheckedEd25519Cert {
96
    type Error = tor_checkable::TimeValidityError;
97

            
98
116
    fn is_valid_at(&self, t: &SystemTime) -> StdResult<(), Self::Error> {
99
116
        self.cert.is_valid_at(t)
100
116
    }
101

            
102
174
    fn dangerously_assume_timely(self) -> ValidatedEd25519Cert {
103
174
        let Self { cert, raw } = self;
104

            
105
174
        let cert = cert.dangerously_assume_timely();
106
174
        ValidatedEd25519Cert { cert, raw }
107
174
    }
108
}
109

            
110
/// A well-signed and timely `EncodedEd25519Cert`.
111
#[derive(Debug, Clone, derive_more::AsRef)]
112
pub struct ValidatedEd25519Cert {
113
    /// The parsed, validated cert.
114
    #[as_ref]
115
    cert: Ed25519Cert,
116
    /// The raw, unparsed cert.
117
    raw: Vec<u8>,
118
}
119

            
120
impl ValidatedEd25519Cert {
121
    /// Return the subject key of this certificate.
122
174
    pub fn subject_key(&self) -> StdResult<&Ed25519Identity, InvalidCertError> {
123
174
        match self.cert.subject_key() {
124
174
            tor_cert::CertifiedKey::Ed25519(ed25519_identity) => Ok(ed25519_identity),
125
            _ => Err(InvalidCertError::InvalidSubjectKeyAlgorithm),
126
        }
127
174
    }
128

            
129
    /// Return the encoded representation of this cert as a `EncodedEd25519Cert`.
130
116
    pub fn into_encoded(self) -> EncodedEd25519Cert {
131
116
        EncodedEd25519Cert::dangerously_from_bytes(&self.raw)
132
116
    }
133
}