tor_netdoc/parse2/poc/
authcert.rs1use super::*;
4
5use crate::types;
6
7type DirKeyCertificateHash = [u8; 20];
11
12#[derive(Clone, Debug, Deftly)]
16#[derive_deftly(NetdocParseable, NetdocSigned)]
17#[non_exhaustive]
18pub struct DirAuthKeyCert {
19 pub dir_key_certificate_version: (NdaDirKeyCertificateVersion,),
21
22 #[deftly(netdoc(keyword = "fingerprint"))]
24 pub h_kp_auth_id_rsa: (types::Fingerprint,),
25
26 #[deftly(netdoc(keyword = "dir-identity-key"))]
28 pub kp_auth_id_rsa: pk::rsa::PublicKey,
29
30 pub dir_key_published: (NdaSystemTimeDeprecatedSyntax,),
32
33 pub dir_key_expires: (NdaSystemTimeDeprecatedSyntax,),
35
36 #[deftly(netdoc(keyword = "dir-signing-key"))]
38 pub kp_auth_sign_rsa: pk::rsa::PublicKey,
39
40 pub dir_key_crosscert: DirAuthCrossCert,
42}
43
44#[derive(Clone, Debug, Deftly)]
46#[derive_deftly(NetdocParseable)]
47#[deftly(netdoc(signatures))]
48#[non_exhaustive]
49pub struct DirAuthKeyCertSignatures {
50 pub dir_key_certification: DirAuthCertRsaSignature,
52}
53
54#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, strum::EnumString)]
56#[non_exhaustive]
57pub enum NdaDirKeyCertificateVersion {
58 #[strum(serialize = "3")]
60 V3,
61}
62
63#[derive(Deftly)]
69#[derive_deftly(ItemValueParseable)]
70#[deftly(netdoc(no_extra_args))]
71#[derive(Debug, Clone, Hash, Eq, PartialEq)]
72#[non_exhaustive]
73pub struct DirAuthCertRsaSignature {
74 #[deftly(netdoc(object(label = "SIGNATURE")))]
76 pub signature: Vec<u8>,
77
78 #[deftly(netdoc(sig_hash = "whole_keyword_line_sha1"))]
80 pub hash: DirKeyCertificateHash,
81}
82
83impl DirAuthKeyCertSigned {
84 pub fn verify_selfcert(self, now: SystemTime) -> Result<DirAuthKeyCert, VF> {
90 let hash = self.signatures.dir_key_certification.hash;
92
93 let validity = *self.body.dir_key_published.0..=*self.body.dir_key_expires.0;
94 check_validity_time(now, validity)?;
95 self.body
96 .kp_auth_id_rsa
97 .verify(&hash, &self.signatures.dir_key_certification.signature)?;
98
99 if *self.body.h_kp_auth_id_rsa.0 != self.body.kp_auth_id_rsa.to_rsa_identity() {
101 return Err(VF::Inconsistent);
102 }
103
104 let h_kp_auth_id_rsa: DirKeyCertificateHash =
106 tor_llcrypto::d::Sha1::digest(self.body.kp_auth_id_rsa.to_der()).into();
107 self.body
109 .kp_auth_sign_rsa
110 .verify(&h_kp_auth_id_rsa, &self.body.dir_key_crosscert.signature)?;
111
112 Ok(self.body)
113 }
114}
115
116#[derive(Debug, Clone, Hash, Eq, PartialEq, derive_more::Deref)]
120#[non_exhaustive]
121pub struct DirAuthCrossCert {
122 pub signature: Vec<u8>,
124}
125
126impl ItemValueParseable for DirAuthCrossCert {
127 fn from_unparsed(mut item: UnparsedItem<'_>) -> Result<Self, ErrorProblem> {
128 item.args_mut().reject_extra_args()?;
129
130 let object = item.object().ok_or(EP::MissingObject)?;
131 match object.label() {
132 "SIGNATURE" | "ID SIGNATURE" => Ok(()),
133 _other => Err(EP::ObjectIncorrectLabel),
134 }?;
135 let signature = object.decode_data()?;
136 Ok(DirAuthCrossCert { signature })
137 }
138}