1
//! Facilities to construct AuthCert objects.
2
//!
3
//! (These are only for testing right now, since we don't yet
4
//! support signing or encoding.)
5
#![allow(deprecated)]
6

            
7
use super::{AuthCert, AuthCertVersion, CrossCert, CrossCertObject};
8

            
9
use crate::{BuildError as Error, BuildResult};
10
use std::net::SocketAddrV4;
11
use std::ops::Range;
12
use std::time::SystemTime;
13
use tor_llcrypto::pk::rsa;
14

            
15
/// A builder object used to construct an authority certificate.
16
///
17
/// Create one of these with the [`AuthCert::builder`] method.
18
///
19
/// This facility is only enabled when the crate is built with
20
/// the `build_docs` feature.
21
#[deprecated = "use AuthCertConstructor instead"]
22
#[cfg_attr(docsrs, doc(cfg(feature = "build_docs")))]
23
pub struct AuthCertBuilder {
24
    /// See [`AuthCert::dir_address`]
25
    address: Option<SocketAddrV4>,
26
    /// See [`AuthCert::dir_identity_key`]
27
    identity_key: Option<rsa::PublicKey>,
28
    /// See [`AuthCert::signing_key`]
29
    signing_key: Option<rsa::PublicKey>,
30
    /// See [`AuthCert::published`]
31
    published: Option<SystemTime>,
32
    /// See [`AuthCert::expires`]
33
    expires: Option<SystemTime>,
34
}
35

            
36
impl AuthCertBuilder {
37
    /// Make a new AuthCertBuilder
38
10
    pub(crate) fn new() -> Self {
39
10
        AuthCertBuilder {
40
10
            address: None,
41
10
            identity_key: None,
42
10
            signing_key: None,
43
10
            published: None,
44
10
            expires: None,
45
10
        }
46
10
    }
47

            
48
    /// Set the IPv4 address for this authority.
49
    ///
50
    /// This field is optional.
51
2
    pub fn address(&mut self, address: SocketAddrV4) -> &mut Self {
52
2
        self.address = Some(address);
53
2
        self
54
2
    }
55

            
56
    /// Set the identity key for this authority.
57
    ///
58
    /// This field is required.
59
8
    pub fn identity_key(&mut self, key: rsa::PublicKey) -> &mut Self {
60
8
        self.identity_key = Some(key);
61
8
        self
62
8
    }
63

            
64
    /// Set the identity key for this certificate.
65
    ///
66
    /// This field is required.
67
8
    pub fn signing_key(&mut self, key: rsa::PublicKey) -> &mut Self {
68
8
        self.signing_key = Some(key);
69
8
        self
70
8
    }
71

            
72
    /// Set the lifespan for this certificate.
73
    ///
74
    /// These fields are required.
75
8
    pub fn lifespan(&mut self, lifespan: Range<SystemTime>) -> &mut Self {
76
8
        self.published = Some(lifespan.start);
77
8
        self.expires = Some(lifespan.end);
78
8
        self
79
8
    }
80

            
81
    /// Try to construct an [`AuthCert`] from this builder.
82
    ///
83
    /// This function can fail if any of the builder's fields are
84
    /// missing or ill-formed.
85
    ///
86
    /// # Danger
87
    ///
88
    /// This function is dangerous because it can be used to construct a
89
    /// certificate where no certificate actually exists: The identity key
90
    /// here has not, in fact, attested to the signing key.
91
    ///
92
    /// You should only use this function for testing.
93
10
    pub fn dangerous_testing_cert(&self) -> BuildResult<AuthCert> {
94
10
        let dir_key_published = self
95
10
            .published
96
10
            .ok_or(Error::CannotBuild("Missing published time"))?
97
8
            .into();
98
8
        let dir_key_expires = self
99
8
            .expires
100
8
            .ok_or(Error::CannotBuild("Missing expiration time"))?
101
8
            .into();
102
8
        if dir_key_expires < dir_key_published {
103
2
            return Err(Error::CannotBuild("Expires before published time."));
104
6
        }
105
6
        let dir_identity_key = self
106
6
            .identity_key
107
6
            .as_ref()
108
6
            .ok_or(Error::CannotBuild("Missing identity key."))?
109
4
            .clone();
110
4
        let dir_signing_key = self
111
4
            .signing_key
112
4
            .as_ref()
113
4
            .ok_or(Error::CannotBuild("Missing signing key."))?
114
2
            .clone();
115

            
116
2
        let id_fingerprint = dir_identity_key.to_rsa_identity();
117

            
118
        // This is a nonsense value, but the tests don't look at it.
119
2
        let dir_key_crosscert = CrossCert {
120
2
            signature: CrossCertObject(vec![]),
121
2
        };
122

            
123
2
        Ok(AuthCert {
124
2
            dir_address: self.address,
125
2
            dir_identity_key,
126
2
            dir_signing_key,
127
2
            dir_key_published,
128
2
            dir_key_expires,
129
2
            fingerprint: crate::types::Fingerprint(id_fingerprint),
130
2
            dir_key_certificate_version: AuthCertVersion::V3,
131
2
            dir_key_crosscert,
132
2
            __non_exhaustive: (),
133
2
        })
134
10
    }
135
}
136

            
137
#[cfg(test)]
138
mod test {
139
    // @@ begin test lint list maintained by maint/add_warning @@
140
    #![allow(clippy::bool_assert_comparison)]
141
    #![allow(clippy::clone_on_copy)]
142
    #![allow(clippy::dbg_macro)]
143
    #![allow(clippy::mixed_attributes_style)]
144
    #![allow(clippy::print_stderr)]
145
    #![allow(clippy::print_stdout)]
146
    #![allow(clippy::single_char_pattern)]
147
    #![allow(clippy::unwrap_used)]
148
    #![allow(clippy::unchecked_time_subtraction)]
149
    #![allow(clippy::useless_vec)]
150
    #![allow(clippy::needless_pass_by_value)]
151
    //! <!-- @@ end test lint list maintained by maint/add_warning @@ -->
152
    use super::*;
153
    use hex_literal::hex;
154
    use std::time::Duration;
155

            
156
    fn rsa1() -> rsa::PublicKey {
157
        let der = hex!(
158
            "30818902818100d527b6c63d6e81d39c328a94ce157dccdc044eb1ad8c210c9c9e22487b4cfade6d4041bd10469a657e3d82bc00cf62ac3b6a99247e573b54c10c47f5dc849b0accda031eca6f6e5dc85677f76dec49ff24d2fcb2b5887fb125aa204744119bb6417f45ee696f8dfc1c2fc21b2bae8e9e37a19dc2518a2c24e7d8fd7fac0f46950203010001"
159
        );
160
        rsa::PublicKey::from_der(&der).unwrap()
161
    }
162

            
163
    fn rsa2() -> rsa::PublicKey {
164
        let der = hex!(
165
            "3082010a0282010100d4e420607eddac8264d888cf89a7af78e619db21db5a4671497797614826316f13e2136fd65ed12bbebb724aa6c214d9ceb30a28053778c3da25b87cdb24a246ba427726e17c60b507ed26d8c6377aa14f611dc12f7a7e67ada07fd04e42225a0b84331e347373590f41410c11853e42ee9a34e95a7715edddb651b063e12bf3a58b8c5dce5efd2681d1d4a6ba02def665eb2ba64520577f4d659849858a10f9303fbd934be8a1a461dbe5d7bf0c12c2a3281c63dcdd28f77f5516046253cf7f7a907c15ed2f7baf0aac4c9be3092ec173e15881aebc5d53b5c73dbc545684165510926d8ca202f2e06faaf0da35950c162bf36a2868006837b8b39b61c5b2b10203010001"
166
        );
167
        rsa::PublicKey::from_der(&der).unwrap()
168
    }
169

            
170
    #[test]
171
    fn simple_cert() {
172
        let now = SystemTime::now();
173
        let one_hour = Duration::new(3600, 0);
174
        let later = now + one_hour * 2;
175
        let addr = "192.0.0.1:9090".parse().unwrap();
176
        let cert = AuthCert::builder()
177
            .identity_key(rsa2())
178
            .signing_key(rsa1())
179
            .address(addr)
180
            .lifespan(now..later)
181
            .dangerous_testing_cert()
182
            .unwrap();
183

            
184
        assert_eq!(cert.key_ids().id_fingerprint, rsa2().to_rsa_identity());
185
        assert_eq!(cert.key_ids().sk_fingerprint, rsa1().to_rsa_identity());
186
        assert_eq!(cert.published(), now);
187
        assert_eq!(cert.expires(), later);
188
    }
189

            
190
    #[test]
191
    fn failing_cert() {
192
        let now = SystemTime::now();
193
        let one_hour = Duration::new(3600, 0);
194
        let later = now + one_hour * 2;
195

            
196
        {
197
            let c = AuthCert::builder()
198
                .identity_key(rsa1())
199
                .lifespan(now..later)
200
                .dangerous_testing_cert();
201
            assert!(c.is_err()); // no signing key.
202
        }
203

            
204
        {
205
            let c = AuthCert::builder()
206
                .signing_key(rsa1())
207
                .lifespan(now..later)
208
                .dangerous_testing_cert();
209
            assert!(c.is_err()); // no identity key.
210
        }
211

            
212
        {
213
            let c = AuthCert::builder()
214
                .signing_key(rsa1())
215
                .identity_key(rsa2())
216
                .dangerous_testing_cert();
217
            assert!(c.is_err()); // no lifespan.
218
        }
219

            
220
        {
221
            let c = AuthCert::builder()
222
                .signing_key(rsa1())
223
                .identity_key(rsa2())
224
                .lifespan(later..now)
225
                .dangerous_testing_cert();
226
            assert!(c.is_err()); // bad lifespan.
227
        }
228
    }
229
}