tor_protover/named.rs
1//! Define protocol versions by name.
2//!
3//! Protocol versions obsolete at the time of this writing (Mar 2025)
4//! are not included.
5//!
6//! For more details about specific versions,
7//! see the [relevant section of the spec][spec].
8//!
9//! [spec]: https://spec.torproject.org/tor-spec/subprotocol-versioning.html
10
11use super::{NamedSubver, ProtoKind};
12use paste::paste;
13
14/// Helper: define a set of named aliases for specific subprotocol versions
15macro_rules! def_named {
16 { $( $protocol:ident {
17 $(
18 $(#[$meta:meta])*
19 $subver:ident = $num:expr;
20 )*
21 })*
22 } => {paste!{
23 $($(
24 $(#[$meta])*
25 pub const [<$protocol:upper _ $subver>] : NamedSubver = NamedSubver::new(ProtoKind::$protocol, $num);
26 )*)*
27 }}
28}
29
30def_named! {
31
32 Link {
33 /// Obsolete version 1 link protocol.
34 ///
35 /// This protocol used RSA-based TLS certificate chains with specific properties.
36 V1 = 1;
37 /// Obsolete version 2 link protocol.
38 ///
39 /// This protocol used TLS renegotiation.
40 V2 = 2;
41 /// Version 3 link protocol.
42 ///
43 /// This protocol uses a single server certificate in TLS,
44 /// and then exchanges additional certificates and authentication
45 /// within the protocol.
46 V3 = 3;
47 /// Version 4 link protocol.
48 ///
49 /// This protocol extends the version 3 link protocol
50 /// by changing the length of Circuit IDs from 2 bytes to 4 bytes.
51 V4 = 4;
52 /// Version 5 link protocol.
53 ///
54 /// This protocol extends the version 4 link protocol
55 /// by adding support for link padding.
56 V5 = 5;
57 }
58
59 LinkAuth {
60 /// TLS authentication based on signing key-exported material with an Ed25519 key.
61 ///
62 /// ([Specification](https://spec.torproject.org/tor-spec/negotiating-channels.html#Ed25519-SHA256-RFC5705))
63 ED25519_SHA256_EXPORTER = 3;
64 }
65
66 Relay {
67 /// Support for ntor key exchange, CREATE2, CREATED2, EXTEND2, EXTENDED2.
68 NTOR = 2;
69
70 /// Support for extending over IPv6 properly using EXTEND2 messages.
71 EXTEND_IPv6 = 3;
72
73 /// Support for ntor v3 key exchange, including "extra data" in circuit handshakes
74 /// in the format described in
75 /// [the "ntor-v3" handshake](https://spec.torproject.org/tor-spec/create-created-cells.md#ntor-v3).
76 NTORV3 = 4;
77
78 /// Support for the ntorv3 [protocol request extension][prop346].
79 ///
80 /// (Reserved.)
81 ///
82 /// [prop346]: https://spec.torproject.org/proposals/346-protovers-again.html
83 NEGOTIATE_SUBPROTO = 5;
84
85 /// Support for counter galois onion relay encryption.
86 ///
87 /// (Reserved.)
88 ///
89 /// [prop359]: https://spec.torproject.org/proposals/359-cgo-redux.html
90 CRYPT_CGO = 6;
91 }
92
93 HSIntro {
94 /// Version 3 hidden service introduction point support.
95 V3 = 4;
96
97 /// Support for rate-limiting anti-DOS extensions in the`ESTABLISH_INTRO` message.
98 RATELIM = 5;
99 }
100
101 HSRend {
102 /// Support for RENDEZVOUS2 messages of arbitrary length.
103 V3 = 2;
104 }
105
106 HSDir {
107 /// Support for version 3 hidden service descriptors,
108 /// including blinded keys.
109 V3 = 2;
110 }
111
112 DirCache {
113 /// Support for consensus diffs.
114 CONSDIFF = 2;
115 }
116
117 Desc {
118 /// Support for signing with ed25519 keys,
119 /// and cross-signing with onion keys.
120 CROSSSIGN = 2;
121
122 /// Support for parsing relay descriptors without TAP onion-keys (`KP_onion_tap`),
123 /// and generating them without TAP onion keys when `publish-dummy-tap-key` is 0.
124 NO_TAP = 3;
125
126 /// Support for understanding and building paths according to
127 /// the "happy families" design.
128 FAMILY_IDS = 4;
129 }
130
131 Microdesc {
132 /// Support for generating and parsing microdescriptors with Ed25159 identities
133 /// (`KP_relayid_ed`)
134 ED25519_KEY = 2;
135
136 /// Support for parsing microdescriptors without TAP keys (`KP_onion_tap``).
137 NO_TAP = 3;
138 }
139
140 Cons {
141 /// Support for consensus method 21, which moved ed25519 identity keys (`KP_relayid_ed`)
142 /// to microdescriptors.
143 ED25519_MDS = 2;
144 }
145
146 Padding {
147 /// Support for padding machines to hide HS circuit setup patterns.
148 MACHINES_CIRC_SETUP = 2;
149 }
150
151 FlowCtrl {
152 /// Support for authenticated circuit-level SENDME messages.
153 AUTH_SENDME = 1;
154
155 /// Support for congestion control.
156 CC = 2;
157 }
158
159 Conflux {
160 /// Support for the core conflux protocol.
161 BASE = 1;
162 }
163
164}
165
166/// Define a restricted set of subprotocol versions.
167///
168/// This supports a set of named subprotocols as defined in [`tor_protover::named`](crate::named).
169///
170/// This is useful when you want to restrict what subprotocol versions are allowed,
171/// and also want to be able to exhaustively handle each subprotocol version.
172/// If you don't care about (or don't want) the exhaustive property,
173/// you might be better off defining a wrapper around [`Protocols`]($crate::Protocols) instead.
174///
175/// Example:
176///
177/// ```
178/// tor_protover::subprotocol_restricted_set! {
179/// #[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
180/// pub(crate) struct SupportedSubprotocols {
181/// RELAY_CRYPT_CGO,
182/// RELAY_NTORV3,
183/// }
184/// }
185/// ```
186///
187/// generates a struct of the form:
188///
189/// ```
190/// #[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
191/// pub(crate) struct SupportedSubprotocols {
192/// pub(crate) relay_crypt_cgo: bool,
193/// pub(crate) relay_ntorv3: bool,
194/// }
195/// ```
196#[macro_export]
197macro_rules! subprotocol_restricted_set {
198 {
199 $(#[$meta:meta])*
200 $v:vis struct $name:ident {
201 $(
202 $(#[$field_meta:meta])*
203 $field:ident
204 ),* $(,)?
205 }
206 } => {
207 $crate::macro_export::paste::paste!{
208 // We don't make this `non_exhaustive` because the goal of this type is to support
209 // exhaustively handling all elements.
210 $(#[$meta])*
211 $v struct $name {
212 $(
213 $(#[$field_meta])*
214 #[doc = concat!(
215 "The [`", stringify!($field), "`](",
216 stringify!($crate), "::named::", stringify!($field),
217 ") subprotocol version."
218 )]
219 $v [<$field:lower>]: bool,
220 )*
221 }
222
223 impl $name {
224 /// All subprotocol versions that are supported by this set.
225 $v const ALL: Self = Self {$(
226 [<$field:lower>]: true,
227 )*};
228 }
229
230 impl From<$name> for $crate::Protocols {
231 fn from(set: $name) -> Self {
232 Self::from_iter(
233 [$(set.[<$field:lower>].then_some($crate::named::$field)),*]
234 .into_iter()
235 .filter_map(|x| x)
236 )
237 }
238 }
239 }
240 };
241}
242
243#[cfg(test)]
244mod test {
245 // @@ begin test lint list maintained by maint/add_warning @@
246 #![allow(clippy::bool_assert_comparison)]
247 #![allow(clippy::clone_on_copy)]
248 #![allow(clippy::dbg_macro)]
249 #![allow(clippy::mixed_attributes_style)]
250 #![allow(clippy::print_stderr)]
251 #![allow(clippy::print_stdout)]
252 #![allow(clippy::single_char_pattern)]
253 #![allow(clippy::unwrap_used)]
254 #![allow(clippy::unchecked_time_subtraction)]
255 #![allow(clippy::useless_vec)]
256 #![allow(clippy::needless_pass_by_value)]
257 #![allow(clippy::string_slice)] // See arti#2571
258 //! <!-- @@ end test lint list maintained by maint/add_warning @@ -->
259
260 use crate::Protocols;
261
262 subprotocol_restricted_set! {
263 #[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
264 struct SupportedSubprotocols {
265 RELAY_CRYPT_CGO,
266 RELAY_NTORV3,
267 }
268 }
269
270 #[test]
271 fn restricted_set_constants() {
272 assert_eq!(
273 SupportedSubprotocols::ALL,
274 SupportedSubprotocols {
275 relay_crypt_cgo: true,
276 relay_ntorv3: true,
277 },
278 );
279 }
280
281 #[test]
282 fn restricted_set() {
283 let protocols: Protocols = "Relay=4".parse().unwrap();
284
285 assert_eq!(
286 Protocols::from(SupportedSubprotocols {
287 relay_crypt_cgo: false,
288 relay_ntorv3: true,
289 }),
290 protocols,
291 );
292 }
293}