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, strum::Display)]
56#[non_exhaustive]
57pub enum NdaDirKeyCertificateVersion {
58 #[strum(serialize = "3")]
60 V3,
61}
62
63impl NormalItemArgument for NdaDirKeyCertificateVersion {}
64
65#[derive(Deftly)]
71#[derive_deftly(ItemValueParseable)]
72#[deftly(netdoc(no_extra_args))]
73#[derive(Debug, Clone, Hash, Eq, PartialEq)]
74#[non_exhaustive]
75pub struct DirAuthCertRsaSignature {
76 #[deftly(netdoc(object(label = "SIGNATURE"), with = "crate::parse2::raw_data_object"))]
78 pub signature: Vec<u8>,
79
80 #[deftly(netdoc(sig_hash = "whole_keyword_line_sha1"))]
82 pub hash: DirKeyCertificateHash,
83}
84
85impl DirAuthKeyCertSigned {
86 pub fn verify_selfcert(self, now: SystemTime) -> Result<DirAuthKeyCert, VF> {
92 let hash = self.signatures.dir_key_certification.hash;
94
95 let validity = *self.body.dir_key_published.0..=*self.body.dir_key_expires.0;
96 check_validity_time(now, validity)?;
97 self.body
98 .kp_auth_id_rsa
99 .verify(&hash, &self.signatures.dir_key_certification.signature)?;
100
101 if *self.body.h_kp_auth_id_rsa.0 != self.body.kp_auth_id_rsa.to_rsa_identity() {
103 return Err(VF::Inconsistent);
104 }
105
106 let h_kp_auth_id_rsa: DirKeyCertificateHash =
108 tor_llcrypto::d::Sha1::digest(self.body.kp_auth_id_rsa.to_der()).into();
109 self.body
111 .kp_auth_sign_rsa
112 .verify(&h_kp_auth_id_rsa, &self.body.dir_key_crosscert.signature)?;
113
114 Ok(self.body)
115 }
116}
117
118#[derive(Debug, Clone, Hash, Eq, PartialEq, derive_more::Deref)]
122#[non_exhaustive]
123pub struct DirAuthCrossCert {
124 pub signature: Vec<u8>,
126}
127
128impl ItemValueParseable for DirAuthCrossCert {
129 fn from_unparsed(mut item: UnparsedItem<'_>) -> Result<Self, ErrorProblem> {
130 item.args_mut().reject_extra_args()?;
131
132 let object = item.object().ok_or(EP::MissingObject)?;
133 match object.label() {
134 "SIGNATURE" | "ID SIGNATURE" => Ok(()),
135 _other => Err(EP::ObjectIncorrectLabel),
136 }?;
137 let signature = object.decode_data()?;
138 Ok(DirAuthCrossCert { signature })
139 }
140}