1
//! Encoding and decoding for relay messages related to onion services.
2

            
3
use self::ext::{decl_extension_group, ExtGroup, ExtList};
4

            
5
use super::msg::{self, Body};
6
use caret::caret_int;
7
use derive_deftly::Deftly;
8
use tor_bytes::{EncodeError, EncodeResult, Error as BytesError, Result};
9
use tor_bytes::{Readable, Reader, Writeable, Writer};
10
use tor_hscrypto::RendCookie;
11
use tor_llcrypto::pk::rsa::RsaIdentity;
12
use tor_memquota::derive_deftly_template_HasMemoryCost;
13

            
14
pub mod est_intro;
15
mod ext;
16
pub mod intro_payload;
17
pub mod pow;
18

            
19
pub use ext::UnrecognizedExt;
20

            
21
caret_int! {
22
    /// The type of the introduction point auth key
23
    #[derive(Deftly)]
24
    #[derive_deftly(HasMemoryCost)]
25
    pub struct AuthKeyType(u8) {
26
        /// Ed25519; SHA3-256
27
        ED25519_SHA3_256 = 2,
28
    }
29
}
30

            
31
/// A message sent from client to rendezvous point.
32
#[derive(Debug, Clone, Deftly)]
33
#[derive_deftly(HasMemoryCost)]
34
pub struct EstablishRendezvous {
35
    /// A rendezvous cookie is an arbitrary 20-byte value,
36
    /// chosen randomly by the client.
37
    cookie: RendCookie,
38
}
39
impl EstablishRendezvous {
40
    /// Construct a new establish rendezvous cell.
41
49
    pub fn new(cookie: RendCookie) -> Self {
42
49
        Self { cookie }
43
49
    }
44
}
45
impl msg::Body for EstablishRendezvous {
46
147
    fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
47
147
        let cookie = r.extract()?;
48
98
        r.take_rest();
49
98
        Ok(Self { cookie })
50
147
    }
51
6
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
52
6
        w.write(&self.cookie)
53
6
    }
54
}
55

            
56
#[derive(Debug, Clone, Deftly)]
57
#[derive_deftly(HasMemoryCost)]
58
/// A message sent from client to introduction point.
59
pub struct Introduce1(Introduce);
60

            
61
impl msg::Body for Introduce1 {
62
147
    fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
63
147
        let (intro, _) = Introduce::decode_from_reader(r)?;
64
98
        Ok(Self(intro))
65
147
    }
66
6
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
67
6
        self.0.encode_onto(w)
68
6
    }
69
}
70

            
71
impl Introduce1 {
72
    /// All arguments constructor
73
49
    pub fn new(auth_key_type: AuthKeyType, auth_key: Vec<u8>, encrypted: Vec<u8>) -> Self {
74
49
        Self(Introduce::new(auth_key_type, auth_key, encrypted))
75
49
    }
76
}
77

            
78
#[derive(Debug, Clone, Deftly)]
79
#[derive_deftly(HasMemoryCost)]
80
/// A message sent from introduction point to hidden service host.
81
pub struct Introduce2 {
82
    /// A copy of the encoded header that we'll use to finish the hs_ntor handshake.
83
    encoded_header: Vec<u8>,
84
    /// The decoded message itself.
85
    msg: Introduce,
86
}
87

            
88
impl msg::Body for Introduce2 {
89
    fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
90
        let (msg, header) = Introduce::decode_from_reader(r)?;
91
        let encoded_header = header.to_vec();
92

            
93
        Ok(Self {
94
            encoded_header,
95
            msg,
96
        })
97
    }
98
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
99
        self.msg.encode_onto(w)
100
    }
101
}
102

            
103
impl Introduce2 {
104
    /// All arguments constructor.
105
    ///
106
    /// This is only useful for testing, since in reality the only time this
107
    /// message type is created is when an introduction point is forwarding an
108
    /// INTRODUCE1 message.
109
    #[cfg(test)] // Don't expose this generally without dealing somehow with the `expect` below
110
    pub fn new(auth_key_type: AuthKeyType, auth_key: Vec<u8>, encrypted: Vec<u8>) -> Self {
111
        let msg = Introduce::new(auth_key_type, auth_key, encrypted);
112
        let mut encoded_header = Vec::new();
113
        msg.header
114
            .write_onto(&mut encoded_header)
115
            .expect("Generated a header that we could not encode");
116
        Self {
117
            encoded_header,
118
            msg,
119
        }
120
    }
121

            
122
    /// Return the bytes used to transmit `header`.
123
    ///
124
    /// (This data is used as part of the handshake.)
125
    pub fn encoded_header(&self) -> &[u8] {
126
        &self.encoded_header[..]
127
    }
128
    /// Return the parsed header of this message.
129
    pub fn header(&self) -> &IntroduceHeader {
130
        &self.msg.header
131
    }
132
    /// Return the encrypted body of this message.
133
    ///
134
    /// (This body is decrypted as part of the handshake.)
135
    pub fn encrypted_body(&self) -> &[u8] {
136
        &self.msg.encrypted[..]
137
    }
138
}
139

            
140
caret_int! {
141
    /// The recognized extension types for an `Introduce1` or `Introduce2 message.
142
    #[derive(Ord,PartialOrd)]
143
    pub struct IntroduceExtType(u8) {
144
    }
145
}
146

            
147
decl_extension_group! {
148
    /// An extension to an IntroEstablished message.
149
    ///
150
    /// (Currently, no extensions of this type are recognized)
151
    #[derive(Debug,Clone,Deftly)]
152
    #[derive_deftly(HasMemoryCost)]
153
    enum IntroduceExt [ IntroduceExtType ] {
154
    }
155
}
156

            
157
/// The unencrypted header portion of an `Introduce1` or `Introduce2` message.
158
///
159
/// This is a separate type because the `hs_ntor` handshake requires access to the
160
/// encoded format of the header, only.
161
#[derive(Debug, Clone, Deftly)]
162
#[derive_deftly(HasMemoryCost)]
163
pub struct IntroduceHeader {
164
    /// Introduction point auth key type and the type of
165
    /// the MAC used in `handshake_auth`.
166
    auth_key_type: AuthKeyType,
167
    /// The public introduction point auth key.
168
    auth_key: Vec<u8>,
169
    /// A list of extensions
170
    extensions: ExtList<IntroduceExt>,
171
}
172

            
173
impl tor_bytes::Readable for IntroduceHeader {
174
147
    fn take_from(r: &mut Reader<'_>) -> Result<Self> {
175
147
        let legacy_key_id: RsaIdentity = r.extract()?;
176
147
        if !legacy_key_id.is_zero() {
177
49
            return Err(BytesError::InvalidMessage(
178
49
                "legacy key id in Introduce1.".into(),
179
49
            ));
180
98
        }
181
98
        let auth_key_type = r.take_u8()?.into();
182
98
        let auth_key_len = r.take_u16()?;
183
98
        let auth_key = r.take(auth_key_len as usize)?.into();
184
98
        let extensions = r.extract()?;
185
98
        Ok(Self {
186
98
            auth_key_type,
187
98
            auth_key,
188
98
            extensions,
189
98
        })
190
147
    }
191
}
192

            
193
impl tor_bytes::Writeable for IntroduceHeader {
194
6
    fn write_onto<W: Writer + ?Sized>(&self, w: &mut W) -> EncodeResult<()> {
195
6
        w.write_all(&[0_u8; 20]);
196
6
        w.write_u8(self.auth_key_type.get());
197
6
        w.write_u16(u16::try_from(self.auth_key.len()).map_err(|_| EncodeError::BadLengthValue)?);
198
6
        w.write_all(&self.auth_key[..]);
199
6
        w.write(&self.extensions)?;
200
6
        Ok(())
201
6
    }
202
}
203

            
204
#[derive(Debug, Clone, Deftly)]
205
#[derive_deftly(HasMemoryCost)]
206
/// A message body shared by Introduce1 and Introduce2
207
struct Introduce {
208
    /// The unencrypted header portion of the message.
209
    header: IntroduceHeader,
210
    /// Up to end of relay payload.
211
    encrypted: Vec<u8>,
212
}
213

            
214
impl Introduce {
215
    /// All arguments constructor
216
49
    fn new(auth_key_type: AuthKeyType, auth_key: Vec<u8>, encrypted: Vec<u8>) -> Self {
217
49
        Self {
218
49
            header: IntroduceHeader {
219
49
                auth_key_type,
220
49
                auth_key,
221
49
                extensions: Default::default(),
222
49
            },
223
49
            encrypted,
224
49
        }
225
49
    }
226
    /// Decode an Introduce message body from the given reader.
227
    ///
228
    /// Return the Introduce message body itself, and the text of the body's header.
229
147
    fn decode_from_reader<'a>(r: &mut Reader<'a>) -> Result<(Self, &'a [u8])> {
230
147
        let header_start = r.cursor();
231
147
        let header = r.extract()?;
232
98
        let header_end = r.cursor();
233
98
        let encrypted = r.take_rest().into();
234
98
        Ok((
235
98
            Self { header, encrypted },
236
98
            r.range(header_start, header_end),
237
98
        ))
238
147
    }
239
    /// Encode an Introduce message body onto the given writer
240
6
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
241
6
        w.write(&self.header)?;
242
6
        w.write_all(&self.encrypted[..]);
243
6
        Ok(())
244
6
    }
245
}
246

            
247
/// A message sent from an onion service to a rendezvous point, telling it to
248
/// make a connection to the client.
249
#[derive(Debug, Clone, Deftly)]
250
#[derive_deftly(HasMemoryCost)]
251
pub struct Rendezvous1 {
252
    /// The cookie originally sent by the client in its ESTABLISH_REND message.
253
    cookie: RendCookie,
254
    /// The message to send the client.
255
    handshake_info: Vec<u8>,
256
}
257

            
258
impl Body for Rendezvous1 {
259
49
    fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
260
49
        let cookie = r.extract()?;
261
49
        let handshake_info = r.take_rest().into();
262
49
        Ok(Self {
263
49
            cookie,
264
49
            handshake_info,
265
49
        })
266
49
    }
267

            
268
4
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
269
4
        w.write(&self.cookie)?;
270
4
        w.write_all(&self.handshake_info[..]);
271
4
        Ok(())
272
4
    }
273
}
274

            
275
impl Rendezvous1 {
276
    /// Create a new Rendezvous1 message, to handshake with a client identified
277
    /// by a given RendCookie, and send it a given message.
278
2
    pub fn new(cookie: RendCookie, handshake_info: impl Into<Vec<u8>>) -> Self {
279
2
        Self {
280
2
            cookie,
281
2
            handshake_info: handshake_info.into(),
282
2
        }
283
2
    }
284
}
285

            
286
/// A message sent from the rendezvous point to the client, telling it about the
287
/// onion service's message.
288
#[derive(Debug, Clone, Deftly)]
289
#[derive_deftly(HasMemoryCost)]
290
pub struct Rendezvous2 {
291
    /// The handshake message from the onion service.
292
    handshake_info: Vec<u8>,
293
}
294

            
295
impl Rendezvous2 {
296
    /// Construct a new Rendezvous2 cell containing a given handshake message.
297
    pub fn new(handshake_info: impl Into<Vec<u8>>) -> Self {
298
        Self {
299
            handshake_info: handshake_info.into(),
300
        }
301
    }
302

            
303
    /// Return the body of this Rendezvous2 cell. (That is, the handshake
304
    /// message from the onion service.)
305
    pub fn handshake_info(&self) -> &[u8] {
306
        &self.handshake_info
307
    }
308
}
309

            
310
impl From<Rendezvous1> for Rendezvous2 {
311
49
    fn from(value: Rendezvous1) -> Self {
312
49
        Self {
313
49
            handshake_info: value.handshake_info,
314
49
        }
315
49
    }
316
}
317

            
318
impl Body for Rendezvous2 {
319
49
    fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
320
49
        let handshake_info = r.take_rest().into();
321
49
        Ok(Self { handshake_info })
322
49
    }
323

            
324
4
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
325
4
        w.write_all(&self.handshake_info[..]);
326
4
        Ok(())
327
4
    }
328
}
329

            
330
caret_int! {
331
    /// The recognized extension types for an `IntroEstablished` message.
332
    #[derive(Ord, PartialOrd)]
333
    pub struct IntroEstablishedExtType(u8) {
334
    }
335
}
336

            
337
decl_extension_group! {
338
    /// An extension to an IntroEstablished message.
339
    ///
340
    /// (Currently, no extensions of this type are recognized)
341
    #[derive(Debug,Clone,Deftly)]
342
    #[derive_deftly(HasMemoryCost)]
343
    #[non_exhaustive]
344
    pub enum IntroEstablishedExt [ IntroEstablishedExtType ] {
345
    }
346
}
347

            
348
/// Reply sent from the introduction point to the onion service, telling it that
349
/// an introduction point is now established.
350
#[derive(Debug, Clone, Default, Deftly)]
351
#[derive_deftly(HasMemoryCost)]
352
pub struct IntroEstablished {
353
    /// The extensions included in this cell.
354
    extensions: ExtList<IntroEstablishedExt>,
355
}
356

            
357
impl IntroEstablished {
358
    /// Create a new IntroEstablished message.
359
49
    pub fn new() -> Self {
360
49
        Self::default()
361
49
    }
362

            
363
    /// Return an iterator over the extensions declared in this message.
364
    pub fn iter_extensions(&self) -> impl Iterator<Item = &IntroEstablishedExt> {
365
        self.extensions.iter()
366
    }
367
}
368

            
369
impl Body for IntroEstablished {
370
49
    fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
371
49
        let extensions = r.extract()?;
372
49
        Ok(Self { extensions })
373
49
    }
374

            
375
4
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
376
4
        w.write(&self.extensions)?;
377
4
        Ok(())
378
4
    }
379
}
380

            
381
caret_int! {
382
    /// A status code returned in response to an INTRODUCE1 message.
383
    #[derive(Deftly)]
384
    #[derive_deftly(HasMemoryCost)]
385
    pub struct IntroduceAckStatus(u16) {
386
        /// The message was relayed successfully.
387
        SUCCESS = 0x0000,
388
        /// The introduction point does not have a live circuit from the
389
        /// identified service.
390
        NOT_RECOGNIZED = 0x0001,
391
        /// There was a failure while parsing the INTRODUCE1 message.
392
        BAD_MESSAGE_FORMAT = 0x0002,
393
        /// The introduction point was unable to deliver the message to the service.
394
        CANT_RELAY = 0x0003,
395
    }
396
}
397
caret_int! {
398
    /// The recognized extension types for an `IntroEstablished` message.
399
    #[derive(Ord, PartialOrd, Deftly)]
400
    #[derive_deftly(HasMemoryCost)]
401
    pub struct IntroduceAckExtType(u8) {
402
    }
403
}
404
decl_extension_group! {
405
    /// An extension to an IntroduceAct message.
406
    ///
407
    /// (Currently, no extensions of this type are recognized.)
408
    #[derive(Debug,Clone,Deftly)]
409
    #[derive_deftly(HasMemoryCost)]
410
    enum IntroduceAckExt [ IntroduceAckExtType ] {
411
    }
412
}
413

            
414
/// A reply from the introduction point to the client, telling it that its
415
/// introduce1 was received.
416
#[derive(Clone, Debug, Deftly)]
417
#[derive_deftly(HasMemoryCost)]
418
pub struct IntroduceAck {
419
    /// The status reported for the Introduce1 message.
420
    status_code: IntroduceAckStatus,
421
    /// The extensions on this message.
422
    extensions: ExtList<IntroduceAckExt>,
423
}
424
impl IntroduceAck {
425
    /// Create a new IntroduceAck message with a provided status code.
426
49
    pub fn new(status_code: IntroduceAckStatus) -> Self {
427
49
        Self {
428
49
            status_code,
429
49
            extensions: Default::default(),
430
49
        }
431
49
    }
432

            
433
    /// Return the status code from this message.
434
    pub fn status(&self) -> IntroduceAckStatus {
435
        self.status_code
436
    }
437

            
438
    /// Checks whether the introduction was a success
439
    ///
440
    /// If introduction was forwarded successfully,
441
    /// returns an `Ok<IntroduceAck>`, whose `.status()` can safely be ignored.
442
    /// (The extension list may still be of interest.)
443
    ///
444
    /// Otherwise, returns `Err<IntroduceAckStatus>`,
445
    /// which is suitable for error reporting purposes.
446
    pub fn success(self) -> std::result::Result<IntroduceAck, IntroduceAckStatus> {
447
        if self.status() == IntroduceAckStatus::SUCCESS {
448
            Ok(self)
449
        } else {
450
            Err(self.status())
451
        }
452
    }
453
}
454

            
455
impl Body for IntroduceAck {
456
49
    fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
457
49
        let status_code = r.take_u16()?.into();
458
49
        let extensions = r.extract()?;
459
49
        Ok(IntroduceAck {
460
49
            status_code,
461
49
            extensions,
462
49
        })
463
49
    }
464

            
465
4
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
466
4
        w.write_u16(self.status_code.into());
467
4
        w.write(&self.extensions)?;
468
4
        Ok(())
469
4
    }
470
}
471

            
472
/// When to maybe retry introduction to the *same service* at the *same introduction point*.
473
///
474
/// (Using this on `IntroduceAckStatus::SUCCESS` is a mistake;
475
/// if you do that you'll not get a meaningful retry time, but it won't panic.)
476
impl tor_error::HasRetryTime for IntroduceAckStatus {
477
    fn retry_time(&self) -> tor_error::RetryTime {
478
        use tor_error::RetryTime as RT;
479
        use IntroduceAckStatus as S;
480
        match *self {
481
            S::SUCCESS => RT::Never, // this is a bug
482
            S::NOT_RECOGNIZED => RT::AfterWaiting,
483
            S::BAD_MESSAGE_FORMAT => RT::Never,
484
            S::CANT_RELAY => RT::AfterWaiting,
485
            _ => RT::AfterWaiting, // who knows?
486
        }
487
    }
488
}
489

            
490
super::msg::empty_body! {
491
    /// Acknowledges an EstablishRendezvous message.
492
    pub struct RendezvousEstablished {}
493
}