1
//! Helpers for encoding certificate material.
2

            
3
use crate::{CertType, InvalidCertError, KeyUnknownCert};
4
use tor_cert::{Ed25519Cert, EncodedEd25519Cert, SigCheckedCert, UncheckedCert};
5
use tor_checkable::TimeRange;
6
use tor_llcrypto::pk::ed25519::{self, Ed25519Identity};
7

            
8
use std::result::Result as StdResult;
9

            
10
/// A key certificate.
11
#[derive(Clone, Debug)]
12
#[non_exhaustive]
13
pub enum CertData {
14
    /// A tor-specific ed25519 cert.
15
    TorEd25519Cert(EncodedEd25519Cert),
16
}
17

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

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

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

            
59
186
        let cert = parsed_cert.should_be_signed_with(pkey)?;
60

            
61
186
        Ok(UncheckedEd25519Cert { cert, raw })
62
186
    }
63
}
64

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

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

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

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

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

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

            
96
impl tor_checkable::TimeBound for SigCheckedEd25519Cert {
97
    type Inner = ValidatedEd25519Cert;
98

            
99
124
    fn bounds(&self) -> TimeRange {
100
124
        self.cert.bounds()
101
124
    }
102

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

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

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

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

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