1use tor_bytes::Reader;
7use tor_checkable::{ExternallySigned, timed::TimerangeBound};
8use tor_llcrypto as ll;
9
10use digest::Digest;
11
12#[must_use]
20pub struct RsaCrosscert {
21 subject_key: ll::pk::ed25519::Ed25519Identity,
23 exp_hours: u32,
26 digest: [u8; 32],
28 signature: Vec<u8>,
30}
31
32impl RsaCrosscert {
33 pub fn expiry(&self) -> std::time::SystemTime {
35 let d = std::time::Duration::new(u64::from(self.exp_hours) * 3600, 0);
36 std::time::SystemTime::UNIX_EPOCH + d
37 }
38
39 pub fn digest(&self) -> &[u8; 32] {
41 &self.digest
42 }
43
44 pub fn subject_key_matches(&self, other: &ll::pk::ed25519::Ed25519Identity) -> bool {
46 other == &self.subject_key
47 }
48
49 pub fn decode(bytes: &[u8]) -> tor_bytes::Result<UncheckedRsaCrosscert> {
51 let mut r = Reader::from_slice(bytes);
52 let signed_portion = r.peek(36)?; let subject_key = r.extract()?;
54 let exp_hours = r.take_u32()?;
55 let siglen = r.take_u8()?;
56 let signature = r.take(siglen as usize)?.into();
57
58 let mut d = ll::d::Sha256::new();
59 d.update(&b"Tor TLS RSA/Ed25519 cross-certificate"[..]);
60 d.update(signed_portion);
61 let digest = d.finalize().into();
62
63 let cc = RsaCrosscert {
64 subject_key,
65 exp_hours,
66 digest,
67 signature,
68 };
69
70 Ok(UncheckedRsaCrosscert(cc))
71 }
72}
73
74pub struct UncheckedRsaCrosscert(RsaCrosscert);
76
77impl ExternallySigned<TimerangeBound<RsaCrosscert>> for UncheckedRsaCrosscert {
78 type Key = ll::pk::rsa::PublicKey;
79 type KeyHint = ();
80 type Error = tor_bytes::Error;
81
82 fn key_is_correct(&self, _k: &Self::Key) -> Result<(), Self::KeyHint> {
83 Ok(())
85 }
86
87 fn is_well_signed(&self, k: &Self::Key) -> Result<(), Self::Error> {
88 k.verify(&self.0.digest[..], &self.0.signature[..])
89 .map_err(|_| {
90 tor_bytes::Error::InvalidMessage(
91 "Invalid signature on RSA->Ed identity crosscert".into(),
92 )
93 })?;
94 Ok(())
95 }
96
97 fn dangerously_assume_wellsigned(self) -> TimerangeBound<RsaCrosscert> {
98 let expiration = self.0.expiry();
99 TimerangeBound::new(self.0, ..expiration)
100 }
101}