1//! Types to describe information about other downloaded directory
2//! documents, without necessarily having the full document.
3//!
4//! These types are all local within tor-dirmgr. They're used so that
5//! the storage code doesn't need to know about all of the parsed
6//! types from tor-netdoc.
78use digest::Digest;
9use tor_llcrypto as ll;
10use tor_netdoc::doc::{
11 authcert::{AuthCert, AuthCertKeyIds},
12 netstatus::{Lifetime, MdConsensus, UnvalidatedMdConsensus},
13};
1415use std::time::SystemTime;
1617/// Information about a consensus that we have in storage.
18///
19/// This information is ordinarily derived from the consensus, but doesn't
20/// have to be.
21#[derive(Debug, Clone)]
22pub(crate) struct ConsensusMeta {
23/// The time over which the consensus is valid.
24lifetime: Lifetime,
25/// A sha3-256 digest of the signed portion of the consensus: used for
26 /// fetching diffs.
27sha3_256_of_signed: [u8; 32],
28/// A sha3-256 digest of the entirety of the consensus: used for
29 /// naming the file.
30sha3_256_of_whole: [u8; 32],
31}
3233impl ConsensusMeta {
34/// Create a new ConsensusMeta
35pub(crate) fn new(
36 lifetime: Lifetime,
37 sha3_256_of_signed: [u8; 32],
38 sha3_256_of_whole: [u8; 32],
39 ) -> Self {
40 ConsensusMeta {
41 lifetime,
42 sha3_256_of_signed,
43 sha3_256_of_whole,
44 }
45 }
46/// Derive a new ConsensusMeta from an UnvalidatedMdConsensus and the
47 /// text of its signed portion.
48pub(crate) fn from_unvalidated(
49 signed_part: &str,
50 remainder: &str,
51 con: &UnvalidatedMdConsensus,
52 ) -> Self {
53let lifetime = con.peek_lifetime().clone();
54let (sd, wd) = sha3_dual(signed_part, remainder);
55 ConsensusMeta::new(lifetime, sd, wd)
56 }
57/// Derive a new ConsensusMeta from a MdConsensus and the text of its
58 /// signed portion.
59#[allow(unused)]
60pub(crate) fn from_consensus(signed_part: &str, remainder: &str, con: &MdConsensus) -> Self {
61let lifetime = con.lifetime().clone();
62let (sd, wd) = sha3_dual(signed_part, remainder);
63 ConsensusMeta::new(lifetime, sd, wd)
64 }
65/// Return the lifetime of this ConsensusMeta
66pub(crate) fn lifetime(&self) -> &Lifetime {
67&self.lifetime
68 }
69/// Return the sha3-256 of the signed portion of this consensus.
70pub(crate) fn sha3_256_of_signed(&self) -> &[u8; 32] {
71&self.sha3_256_of_signed
72 }
73/// Return the sha3-256 of the entirety of this consensus.
74pub(crate) fn sha3_256_of_whole(&self) -> &[u8; 32] {
75&self.sha3_256_of_whole
76 }
77}
7879/// Compute the sha3-256 digests of signed_part on its own, and of
80/// signed_part concatenated with remainder.
81fn sha3_dual(signed_part: impl AsRef<[u8]>, remainder: impl AsRef<[u8]>) -> ([u8; 32], [u8; 32]) {
82let mut d = ll::d::Sha3_256::new();
83 d.update(signed_part.as_ref());
84let sha3_of_signed = d.clone().finalize().into();
85 d.update(remainder.as_ref());
86let sha3_of_whole = d.finalize().into();
87 (sha3_of_signed, sha3_of_whole)
88}
8990/// Information about an authority certificate that we have in storage.
91///
92/// This information is ordinarily derived from the authority cert, but it
93/// doesn't have to be.
94#[derive(Clone, Debug)]
95pub(crate) struct AuthCertMeta {
96/// Key IDs (identity and signing) for the certificate.
97ids: AuthCertKeyIds,
98/// Time of publication.
99published: SystemTime,
100/// Expiration time.
101expires: SystemTime,
102}
103104impl AuthCertMeta {
105/// Construct a new AuthCertMeta from its components
106pub(crate) fn new(ids: AuthCertKeyIds, published: SystemTime, expires: SystemTime) -> Self {
107 AuthCertMeta {
108 ids,
109 published,
110 expires,
111 }
112 }
113114/// Construct a new AuthCertMeta from a certificate.
115pub(crate) fn from_authcert(cert: &AuthCert) -> Self {
116 AuthCertMeta::new(*cert.key_ids(), cert.published(), cert.expires())
117 }
118119/// Return the key IDs for this certificate
120pub(crate) fn key_ids(&self) -> &AuthCertKeyIds {
121&self.ids
122 }
123/// Return the published time for this certificate
124pub(crate) fn published(&self) -> SystemTime {
125self.published
126 }
127/// Return the expiration time for this certificate
128pub(crate) fn expires(&self) -> SystemTime {
129self.expires
130 }
131}
132133#[cfg(test)]
134mod test {
135// @@ begin test lint list maintained by maint/add_warning @@
136#![allow(clippy::bool_assert_comparison)]
137 #![allow(clippy::clone_on_copy)]
138 #![allow(clippy::dbg_macro)]
139 #![allow(clippy::mixed_attributes_style)]
140 #![allow(clippy::print_stderr)]
141 #![allow(clippy::print_stdout)]
142 #![allow(clippy::single_char_pattern)]
143 #![allow(clippy::unwrap_used)]
144 #![allow(clippy::unchecked_duration_subtraction)]
145 #![allow(clippy::useless_vec)]
146 #![allow(clippy::needless_pass_by_value)]
147//! <!-- @@ end test lint list maintained by maint/add_warning @@ -->
148use super::*;
149150#[test]
151fn t_sha3_dual() {
152let s = b"Loarax ipsum gruvvulus thneed amet, snergelly once-ler lerkim, sed do barbaloot tempor gluppitus ut labore et truffula magna aliqua. Ut enim ad grickle-grass veniam, quis miff-muffered ga-zumpco laboris nisi ut cruffulus ex ea schloppity consequat. Duis aute snarggle in swomeeswans in voluptate axe-hacker esse rippulus crummii eu moof nulla snuvv.";
153154let sha3_of_whole: [u8; 32] = ll::d::Sha3_256::digest(s).into();
155156for idx in 0..s.len() {
157let sha3_of_part: [u8; 32] = ll::d::Sha3_256::digest(&s[..idx]).into();
158let (a, b) = sha3_dual(&s[..idx], &s[idx..]);
159assert_eq!(a, sha3_of_part);
160assert_eq!(b, sha3_of_whole);
161 }
162 }
163}