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

            
6
use super::{AuthCert, AuthCertKeyIds};
7

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

            
14
/// A builder object used to construct an authority certificate.
15
///
16
/// Create one of these with the [`AuthCert::builder`] method.
17
///
18
/// This facility is only enabled when the crate is built with
19
/// the `build_docs` feature.
20
pub struct AuthCertBuilder {
21
    /// See [`AuthCert::address`]
22
    address: Option<SocketAddrV4>,
23
    /// See [`AuthCert::identity_key`]
24
    identity_key: Option<rsa::PublicKey>,
25
    /// See [`AuthCert::signing_key`]
26
    signing_key: Option<rsa::PublicKey>,
27
    /// See [`AuthCert::published`]
28
    published: Option<SystemTime>,
29
    /// See [`AuthCert::expires`]
30
    expires: Option<SystemTime>,
31
}
32

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

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

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

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

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

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

            
111
1
        let id_fingerprint = identity_key.to_rsa_identity();
112
1
        let sk_fingerprint = signing_key.to_rsa_identity();
113
1

            
114
1
        let key_ids = AuthCertKeyIds {
115
1
            id_fingerprint,
116
1
            sk_fingerprint,
117
1
        };
118
1

            
119
1
        Ok(AuthCert {
120
1
            address: self.address,
121
1
            identity_key,
122
1
            signing_key,
123
1
            published,
124
1
            expires,
125
1
            key_ids,
126
1
        })
127
5
    }
128
}
129

            
130
#[cfg(test)]
131
mod test {
132
    #![allow(clippy::unwrap_used)]
133
    use super::*;
134
    use hex_literal::hex;
135
    use std::time::Duration;
136

            
137
    fn rsa1() -> rsa::PublicKey {
138
        let der = hex!("30818902818100d527b6c63d6e81d39c328a94ce157dccdc044eb1ad8c210c9c9e22487b4cfade6d4041bd10469a657e3d82bc00cf62ac3b6a99247e573b54c10c47f5dc849b0accda031eca6f6e5dc85677f76dec49ff24d2fcb2b5887fb125aa204744119bb6417f45ee696f8dfc1c2fc21b2bae8e9e37a19dc2518a2c24e7d8fd7fac0f46950203010001");
139
        rsa::PublicKey::from_der(&der).unwrap()
140
    }
141

            
142
    fn rsa2() -> rsa::PublicKey {
143
        let der = hex!("3082010a0282010100d4e420607eddac8264d888cf89a7af78e619db21db5a4671497797614826316f13e2136fd65ed12bbebb724aa6c214d9ceb30a28053778c3da25b87cdb24a246ba427726e17c60b507ed26d8c6377aa14f611dc12f7a7e67ada07fd04e42225a0b84331e347373590f41410c11853e42ee9a34e95a7715edddb651b063e12bf3a58b8c5dce5efd2681d1d4a6ba02def665eb2ba64520577f4d659849858a10f9303fbd934be8a1a461dbe5d7bf0c12c2a3281c63dcdd28f77f5516046253cf7f7a907c15ed2f7baf0aac4c9be3092ec173e15881aebc5d53b5c73dbc545684165510926d8ca202f2e06faaf0da35950c162bf36a2868006837b8b39b61c5b2b10203010001");
144
        rsa::PublicKey::from_der(&der).unwrap()
145
    }
146

            
147
    #[test]
148
    fn simple_cert() {
149
        let now = SystemTime::now();
150
        let one_hour = Duration::new(3600, 0);
151
        let later = now + one_hour * 2;
152
        let addr = "192.0.0.1:9090".parse().unwrap();
153
        let cert = AuthCert::builder()
154
            .identity_key(rsa2())
155
            .signing_key(rsa1())
156
            .address(addr)
157
            .lifespan(now..later)
158
            .dangerous_testing_cert()
159
            .unwrap();
160

            
161
        assert_eq!(cert.key_ids().id_fingerprint, rsa2().to_rsa_identity());
162
        assert_eq!(cert.key_ids().sk_fingerprint, rsa1().to_rsa_identity());
163
        assert_eq!(cert.published(), now);
164
        assert_eq!(cert.expires(), later);
165
    }
166

            
167
    #[test]
168
    fn failing_cert() {
169
        let now = SystemTime::now();
170
        let one_hour = Duration::new(3600, 0);
171
        let later = now + one_hour * 2;
172

            
173
        {
174
            let c = AuthCert::builder()
175
                .identity_key(rsa1())
176
                .lifespan(now..later)
177
                .dangerous_testing_cert();
178
            assert!(c.is_err()); // no signing key.
179
        }
180

            
181
        {
182
            let c = AuthCert::builder()
183
                .signing_key(rsa1())
184
                .lifespan(now..later)
185
                .dangerous_testing_cert();
186
            assert!(c.is_err()); // no identity key.
187
        }
188

            
189
        {
190
            let c = AuthCert::builder()
191
                .signing_key(rsa1())
192
                .identity_key(rsa2())
193
                .dangerous_testing_cert();
194
            assert!(c.is_err()); // no lifespan.
195
        }
196

            
197
        {
198
            let c = AuthCert::builder()
199
                .signing_key(rsa1())
200
                .identity_key(rsa2())
201
                .lifespan(later..now)
202
                .dangerous_testing_cert();
203
            assert!(c.is_err()); // bad lifespan.
204
        }
205
    }
206
}