1
//! Implementation for parsing and encoding relay cells
2

            
3
use std::num::NonZeroU16;
4

            
5
use crate::chancell::{BoxedCellBody, CELL_DATA_LEN};
6
use derive_deftly::Deftly;
7
use smallvec::{SmallVec, smallvec};
8
use tor_bytes::{EncodeError, EncodeResult, Error, Result};
9
use tor_bytes::{Reader, Writer};
10
use tor_error::internal;
11
use tor_memquota::derive_deftly_template_HasMemoryCost;
12

            
13
use caret::caret_int;
14
use rand::{CryptoRng, Rng};
15

            
16
#[cfg(feature = "conflux")]
17
pub mod conflux;
18
pub mod extend;
19
mod extlist;
20
pub mod flow_ctrl;
21
#[cfg(feature = "hs")]
22
pub mod hs;
23
pub mod msg;
24
#[cfg(feature = "experimental-udp")]
25
pub mod udp;
26

            
27
caret_int! {
28
    /// A command that identifies the type of a relay cell
29
    #[derive(Deftly)]
30
    #[derive_deftly(HasMemoryCost)]
31
    pub struct RelayCmd(u8) {
32
        /// Start a new stream
33
        BEGIN = 1,
34
        /// Data on a stream
35
        DATA = 2,
36
        /// Close a stream
37
        END = 3,
38
        /// Acknowledge a BEGIN; stream is open
39
        CONNECTED = 4,
40
        /// Used for flow control
41
        SENDME = 5,
42
        /// Extend a circuit to a new hop; deprecated
43
        EXTEND = 6,
44
        /// Reply to EXTEND handshake; deprecated
45
        EXTENDED = 7,
46
        /// Partially close a circuit
47
        TRUNCATE = 8,
48
        /// Circuit has been partially closed
49
        TRUNCATED = 9,
50
        /// Padding cell
51
        DROP = 10,
52
        /// Start a DNS lookup
53
        RESOLVE = 11,
54
        /// Reply to a DNS lookup
55
        RESOLVED = 12,
56
        /// Start a directory stream
57
        BEGIN_DIR = 13,
58
        /// Extend a circuit to a new hop
59
        EXTEND2 = 14,
60
        /// Reply to an EXTEND2 cell.
61
        EXTENDED2 = 15,
62

            
63
        /// NOTE: UDP command are reserved but only used with experimental-udp feature
64

            
65
        /// UDP: Start of a stream
66
        CONNECT_UDP = 16,
67
        /// UDP: Acknowledge a CONNECT_UDP. Stream is open.
68
        CONNECTED_UDP = 17,
69
        /// UDP: Data on a UDP stream.
70
        DATAGRAM = 18,
71

            
72
        /// CONFLUX: Link circuits together at the receiving endpoint.
73
        CONFLUX_LINK = 19,
74
        /// CONFLUX: Confirm that the circuits were linked.
75
        CONFLUX_LINKED = 20,
76
        /// CONFLUX: Acknowledge the linkage of the circuits, for RTT measurement.
77
        CONFLUX_LINKED_ACK = 21,
78
        /// CONFLUX: Switch to another leg in an already linked circuit construction.
79
        CONFLUX_SWITCH = 22,
80

            
81
        /// HS: establish an introduction point.
82
        ESTABLISH_INTRO = 32,
83
        /// HS: establish a rendezvous point.
84
        ESTABLISH_RENDEZVOUS = 33,
85
        /// HS: send introduction (client to introduction point)
86
        INTRODUCE1 = 34,
87
        /// HS: send introduction (introduction point to service)
88
        INTRODUCE2 = 35,
89
        /// HS: connect rendezvous point (service to rendezvous point)
90
        RENDEZVOUS1 = 36,
91
        /// HS: connect rendezvous point (rendezvous point to client)
92
        RENDEZVOUS2 = 37,
93
        /// HS: Response to ESTABLISH_INTRO
94
        INTRO_ESTABLISHED = 38,
95
        /// HS: Response to ESTABLISH_RENDEZVOUS
96
        RENDEZVOUS_ESTABLISHED = 39,
97
        /// HS: Response to INTRODUCE1 from introduction point to client
98
        INTRODUCE_ACK = 40,
99

            
100
        /// Padding: declare what kind of padding we want
101
        PADDING_NEGOTIATE = 41,
102
        /// Padding: reply to a PADDING_NEGOTIATE
103
        PADDING_NEGOTIATED = 42,
104

            
105
        /// Flow control: rate update (transmit off)
106
        XOFF = 43,
107
        /// Flow control: rate update (transmit on with rate limit)
108
        XON = 44,
109
    }
110
}
111

            
112
/// Possible requirements on stream IDs for a relay command.
113
enum StreamIdReq {
114
    /// Can only be used with a stream ID of 0
115
    WantNone,
116
    /// Can only be used with a stream ID that isn't 0
117
    WantSome,
118
    /// Can be used with any stream ID.
119
    ///
120
    /// This result is impossible with `RelayCellFormat::V1`.
121
    Any,
122
    /// Unrecognized; might be used with a stream ID or without.
123
    Unrecognized,
124
}
125

            
126
impl RelayCmd {
127
    /// Check whether this command requires a certain kind of
128
    /// StreamId in the provided `format`, and return a corresponding StreamIdReq.
129
    ///
130
    /// If `format` is None, return a result that is correct for _any_ version.
131
15008
    fn expects_streamid(self, format: Option<RelayCellFormat>) -> StreamIdReq {
132
15008
        match self {
133
            RelayCmd::BEGIN
134
            | RelayCmd::DATA
135
            | RelayCmd::END
136
            | RelayCmd::CONNECTED
137
            | RelayCmd::RESOLVE
138
            | RelayCmd::RESOLVED
139
            | RelayCmd::BEGIN_DIR
140
            | RelayCmd::XOFF
141
7672
            | RelayCmd::XON => StreamIdReq::WantSome,
142
            // NOTE: Even when a RelayCmd is not implemented (like these UDP-based commands),
143
            // we need to implement expects_streamid() unconditionally.
144
            // Otherwise we leak more information than necessary
145
            // when parsing RelayCellFormat::V1 cells.
146
            RelayCmd::CONNECT_UDP | RelayCmd::CONNECTED_UDP | RelayCmd::DATAGRAM => {
147
                StreamIdReq::WantSome
148
            }
149
            RelayCmd::EXTEND
150
            | RelayCmd::EXTENDED
151
            | RelayCmd::TRUNCATE
152
            | RelayCmd::TRUNCATED
153
            | RelayCmd::DROP
154
            | RelayCmd::EXTEND2
155
            | RelayCmd::EXTENDED2
156
            | RelayCmd::CONFLUX_LINK
157
            | RelayCmd::CONFLUX_LINKED
158
            | RelayCmd::CONFLUX_LINKED_ACK
159
            | RelayCmd::CONFLUX_SWITCH
160
            | RelayCmd::ESTABLISH_INTRO
161
            | RelayCmd::ESTABLISH_RENDEZVOUS
162
            | RelayCmd::INTRODUCE1
163
            | RelayCmd::INTRODUCE2
164
            | RelayCmd::RENDEZVOUS1
165
            | RelayCmd::RENDEZVOUS2
166
            | RelayCmd::INTRO_ESTABLISHED
167
            | RelayCmd::RENDEZVOUS_ESTABLISHED
168
5656
            | RelayCmd::INTRODUCE_ACK => StreamIdReq::WantNone,
169
280
            RelayCmd::SENDME => match format {
170
                // There are no stream-level SENDMES in V1, since CC is mandatory.
171
                // Further, the 'Any' result is not possible with V1, since
172
                // we need be able to decide whether a stream ID is present
173
                // from the value of the command.
174
280
                Some(RelayCellFormat::V1) => StreamIdReq::WantNone,
175
                // In V0, CC is not mandatory, so stream-level SENDMES are possible.
176
                Some(RelayCellFormat::V0) => StreamIdReq::Any,
177
                // When we're checking for general compatibility, we need to allow V0 or V1.
178
1344
                None => StreamIdReq::Any,
179
            },
180
56
            _ => StreamIdReq::Unrecognized,
181
        }
182
15008
    }
183
    /// Return true if this command is one that accepts the particular
184
    /// stream ID `id`.
185
    ///
186
    /// Note that this method does not consider the [`RelayCellFormat`] in use:
187
    /// it will return "true" for _any_ stream ID if the command is `SENDME`,
188
    /// and if the command is unrecognized.
189
13888
    pub fn accepts_streamid_val(self, id: Option<StreamId>) -> bool {
190
13888
        match self.expects_streamid(None) {
191
5376
            StreamIdReq::WantNone => id.is_none(),
192
7168
            StreamIdReq::WantSome => id.is_some(),
193
1344
            StreamIdReq::Any => true,
194
            StreamIdReq::Unrecognized => true,
195
        }
196
13888
    }
197
}
198

            
199
/// Identify a single stream on a circuit.
200
///
201
/// These identifiers are local to each hop on a circuit.
202
/// This can't be zero; if you need something that can be zero in the protocol,
203
/// use `Option<StreamId>`.
204
#[derive(Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Debug, Hash, Deftly)]
205
#[derive_deftly(HasMemoryCost)]
206
pub struct StreamId(NonZeroU16);
207

            
208
impl From<NonZeroU16> for StreamId {
209
45304
    fn from(id: NonZeroU16) -> Self {
210
45304
        Self(id)
211
45304
    }
212
}
213

            
214
impl From<StreamId> for NonZeroU16 {
215
14288
    fn from(id: StreamId) -> NonZeroU16 {
216
14288
        id.0
217
14288
    }
218
}
219

            
220
impl From<StreamId> for u16 {
221
112
    fn from(id: StreamId) -> u16 {
222
112
        id.0.get()
223
112
    }
224
}
225

            
226
impl std::fmt::Display for StreamId {
227
1848
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
228
1848
        self.0.fmt(f)
229
1848
    }
230
}
231

            
232
impl StreamId {
233
    /// Creates a `StreamId` for non-zero `stream_id`.
234
    ///
235
    /// Returns `None` when `stream_id` is zero. Messages with a zero/None stream ID
236
    /// apply to the circuit as a whole instead of a particular stream.
237
146160
    pub fn new(stream_id: u16) -> Option<Self> {
238
146160
        NonZeroU16::new(stream_id).map(Self)
239
146160
    }
240

            
241
    /// Convenience function to convert to a `u16`; `None` is mapped to 0.
242
144088
    pub fn get_or_zero(stream_id: Option<Self>) -> u16 {
243
144088
        match stream_id {
244
130256
            Some(stream_id) => stream_id.0.get(),
245
13832
            None => 0,
246
        }
247
144088
    }
248
}
249

            
250
/// Specifies which encoding version of RelayCell to use.
251
#[non_exhaustive]
252
#[derive(Copy, Clone, Debug)]
253
pub enum RelayCellFormat {
254
    /// This is the "legacy" pre-prop340 format. No packing or fragmentation.
255
    V0,
256
    /// A "transitional" format for use with Counter Galois Onion encryption.
257
    ///
258
    /// It provides a 16-byte tag field, and a simplified layout for the rest of
259
    /// the cell.
260
    V1,
261
}
262

            
263
/// Internal decoder state.
264
#[derive(Clone, Debug)]
265
enum RelayCellDecoderInternal {
266
    /// Internal state for `RelayCellFormat::V0`
267
    V0,
268
    /// Internal state for `RelayCellFormat::V1`
269
    V1,
270
}
271

            
272
// TODO prop340: We should also fuzz RelayCellDecoder, but not in this fuzzer.
273

            
274
/// Decodes a stream of relay cell bodies into `UnparsedRelayMsg`s.
275
#[derive(Clone, Debug)]
276
pub struct RelayCellDecoder {
277
    /// Internal representation.
278
    internal: RelayCellDecoderInternal,
279
}
280

            
281
impl RelayCellDecoder {
282
    /// Returns a new `Decoder`, handling a stream of relay cells
283
    /// of the given `version`.
284
145432
    pub fn new(version: RelayCellFormat) -> Self {
285
145432
        match version {
286
144760
            RelayCellFormat::V0 => Self {
287
144760
                internal: RelayCellDecoderInternal::V0,
288
144760
            },
289
672
            RelayCellFormat::V1 => Self {
290
672
                internal: RelayCellDecoderInternal::V1,
291
672
            },
292
        }
293
145432
    }
294
    /// Parse a RELAY or RELAY_EARLY cell body.
295
    ///
296
    /// Requires that the cryptographic checks on the message have already been
297
    /// performed
298
130872
    pub fn decode(&mut self, cell: BoxedCellBody) -> Result<RelayCellDecoderResult> {
299
130872
        let msg_internal = match &self.internal {
300
130200
            RelayCellDecoderInternal::V0 => UnparsedRelayMsgInternal::V0(cell),
301
672
            RelayCellDecoderInternal::V1 => UnparsedRelayMsgInternal::V1(cell),
302
        };
303
        Ok(RelayCellDecoderResult {
304
130872
            msgs: smallvec![UnparsedRelayMsg {
305
                internal: msg_internal
306
            }],
307
130872
            incomplete: None,
308
        })
309
130872
    }
310
    /// Returns the `IncompleteRelayMsgInfo` describing the partial
311
    /// (fragmented) relay message at the end of the so-far-processed relay cell
312
    /// stream.
313
    pub fn incomplete_info(&self) -> Option<IncompleteRelayMsgInfo> {
314
        match &self.internal {
315
            // V0 and V1 don't support fragmentation, so there is never a pending fragment.
316
            RelayCellDecoderInternal::V0 | RelayCellDecoderInternal::V1 => None,
317
        }
318
    }
319
}
320

            
321
/// Result of calling `RelayCellDecoder::decode`.
322
#[derive(Debug)]
323
pub struct RelayCellDecoderResult {
324
    /// Complete messages obtained by decoding the cell. i.e. messages
325
    /// that were completely contained within the cell, or for which the cell
326
    /// contained the final fragment.
327
    msgs: SmallVec<[UnparsedRelayMsg; 1]>,
328
    /// Description of the partial message at the end of the cell, if any.
329
    incomplete: Option<IncompleteRelayMsgInfo>,
330
}
331

            
332
impl RelayCellDecoderResult {
333
    /// Returns a non-empty iterator over commands in relay messages that the
334
    /// cell producing this result contained *any* part of. i.e. this includes
335
    /// the command of "head", "middle", and/or "tail" message fragments that
336
    /// were in the cell.
337
13664
    pub fn cmds(&self) -> impl Iterator<Item = RelayCmd> + '_ {
338
13908
        let complete_msg_cmds = self.msgs.iter().map(|m| m.cmd());
339
13664
        let partial_msg_cmd = self.incomplete.as_ref().map(|c| c.cmd());
340
13664
        complete_msg_cmds.chain(partial_msg_cmd)
341
13664
    }
342
    /// Converts `self` to an iterator over the complete messages, and metadata
343
    /// about the trailing incomplete message (as for `Self::incomplete_info`),
344
    /// if any.
345
130872
    pub fn into_parts(
346
130872
        self,
347
130872
    ) -> (
348
130872
        impl Iterator<Item = UnparsedRelayMsg>,
349
130872
        Option<IncompleteRelayMsgInfo>,
350
130872
    ) {
351
130872
        (self.msgs.into_iter(), self.incomplete)
352
130872
    }
353
    /// Returns the `IncompleteRelayMsgInfo` describing the incomplete
354
    /// relay message that this cell contained a fragment of, if any.
355
    ///
356
    /// Note that:
357
    /// * This does not describe a fragment that includes the end of the relay
358
    ///   message, since the message is then complete.
359
    /// * This *does* include a fragment that continues, but does not complete,
360
    ///   a message started in an earlier relay cell.
361
    /// * There is at most one such incomplete relay message, since no current
362
    ///   relay cell format supports starting a new message before completing the
363
    ///   previous one.
364
    pub fn incomplete_info(&self) -> Option<IncompleteRelayMsgInfo> {
365
        self.incomplete.clone()
366
    }
367

            
368
    /// Return true if this consists of nothing but padding.
369
13664
    pub fn is_padding(&self) -> bool {
370
        // If all the messages we have are padding...
371
13908
        self.msgs.iter().all(|m| m.cmd() == RelayCmd::DROP) &&
372
            // ... and any pending incomplete message is either absent or is padding...
373
            self.incomplete
374
                .as_ref()
375
                .is_none_or(|incomplete| incomplete.cmd() == RelayCmd::DROP)
376
        // ... then this is padding.
377
13664
    }
378
}
379

            
380
/// Information about a relay message for which we don't yet have the complete body.
381
#[derive(Clone, Debug)]
382
pub struct IncompleteRelayMsgInfo {
383
    /// The message's command.
384
    cmd: RelayCmd,
385
    /// The message's stream ID, if any.
386
    stream_id: Option<StreamId>,
387
    /// The total number of bytes in the body of the message.
388
    total_msg_len: usize,
389
    /// The number of bytes of the body of the message that we've decoded so
390
    /// far.
391
    num_bytes_present: usize,
392
}
393

            
394
impl IncompleteRelayMsgInfo {
395
    /// Returns the message's command.
396
    pub fn cmd(&self) -> RelayCmd {
397
        self.cmd
398
    }
399
    /// Returns the message's `StreamId`, if any.
400
    pub fn stream_id(&self) -> Option<StreamId> {
401
        self.stream_id
402
    }
403
    /// Returns the total size of the complete message body.
404
    pub fn total_msg_len(&self) -> usize {
405
        self.total_msg_len
406
    }
407
    /// Returns the number of bytes of the message body that we have so far.
408
    pub fn num_bytes_present(&self) -> usize {
409
        self.num_bytes_present
410
    }
411
    /// Returns the number of bytes of the message body that we still need.
412
    pub fn num_bytes_missing(&self) -> usize {
413
        self.total_msg_len - self.num_bytes_present
414
    }
415
}
416

            
417
/// Internal representation of an `UnparsedRelayMsg`.
418
#[derive(Clone, Debug, Deftly)]
419
#[derive_deftly(HasMemoryCost)]
420
enum UnparsedRelayMsgInternal {
421
    /// For `RelayCellFormat::V0` we can avoid copying data around by just
422
    /// storing the original cell body here.
423
    // NOTE: we could also have a separate command and stream ID field here, but
424
    // we expect to be working with a TON of these, so we will be mildly
425
    // over-optimized and just peek into the body.
426
    //
427
    // It *is* a bit ugly to have to encode so much knowledge about the format in
428
    // different functions here, but that information shouldn't leak out of this module.
429
    V0(BoxedCellBody),
430

            
431
    /// For `V1` we can also avoid copies, since there is still exactly one
432
    /// relay message per cell.
433
    V1(BoxedCellBody),
434
}
435

            
436
/// An enveloped relay message that has not yet been fully parsed, but where we
437
/// have access to the command, stream ID, and payload data length for dispatching
438
/// and congestion control purposes.
439
#[derive(Clone, Debug, Deftly)]
440
#[derive_deftly(HasMemoryCost)]
441
pub struct UnparsedRelayMsg {
442
    /// The internal representation.
443
    internal: UnparsedRelayMsgInternal,
444
}
445

            
446
/// Const helper to find the min between three u16 values.
447
const fn min(a: u16, b: u16, c: u16) -> u16 {
448
    const fn min_2(a: u16, b: u16) -> u16 {
449
        if a < b { a } else { b }
450
    }
451
    min_2(a, min_2(b, c))
452
}
453

            
454
/// Const helper to find the max between three u16 values.
455
const fn max(a: u16, b: u16, c: u16) -> u16 {
456
    const fn max_2(a: u16, b: u16) -> u16 {
457
        if a > b { a } else { b }
458
    }
459
    max_2(a, max_2(b, c))
460
}
461

            
462
/// Position of the stream ID within the V0 cell body.
463
const STREAM_ID_OFFSET_V0: usize = 3;
464

            
465
/// Position of the stream ID within the V1 cell body, if it is present.
466
const STREAM_ID_OFFSET_V1: usize = 16 + 1 + 2; // tag, command, length.
467

            
468
/// Position of the payload data length within the V0 cell body.
469
const LENGTH_OFFSET_V0: usize = 1 + 2 + 2 + 4; // command, recognized, stream_id, digest.
470

            
471
/// Position of the payload data length within the V1 cell body.
472
const LENGTH_OFFSET_V1: usize = 16 + 1; // tag, command.
473

            
474
/// Position of the payload data within the V0 cell body.
475
const PAYLOAD_OFFSET_V0: usize = LENGTH_OFFSET_V0 + 2; // (everything before length), length.
476

            
477
/// Position of the payload data within the V1 cell body, when not including a stream ID.
478
const PAYLOAD_OFFSET_V1_WITHOUT_STREAM_ID: usize = LENGTH_OFFSET_V1 + 2; // (everything before length), length.
479

            
480
/// Position of the payload data within the V1 cell body, when including a stream ID.
481
const PAYLOAD_OFFSET_V1_WITH_STREAM_ID: usize = LENGTH_OFFSET_V1 + 2 + 2; // (everything before length), length, stream_id.
482

            
483
/// Max amount of payload data that can be stored in a V0 cell body.
484
const PAYLOAD_MAX_SIZE_V0: u16 = BODY_MAX_LEN_V0 - (PAYLOAD_OFFSET_V0 as u16);
485

            
486
/// Max amount of payload data that can be stored in a V1 cell body, when not including a stream ID.
487
const PAYLOAD_MAX_SIZE_V1_WITHOUT_STREAM_ID: u16 =
488
    BODY_MAX_LEN_V1 - (PAYLOAD_OFFSET_V1_WITHOUT_STREAM_ID as u16);
489

            
490
/// Max amount of payload data that can be stored in a V1 cell body, when including a stream ID.
491
const PAYLOAD_MAX_SIZE_V1_WITH_STREAM_ID: u16 =
492
    BODY_MAX_LEN_V1 - (PAYLOAD_OFFSET_V1_WITH_STREAM_ID as u16);
493

            
494
/// The maximum length of a V0 cell message body.
495
const BODY_MAX_LEN_V0: u16 = 509;
496

            
497
/// The maximum length of a V1 cell message body.
498
const BODY_MAX_LEN_V1: u16 = 509;
499

            
500
/// The maximum amount of payload data that can fit within all cell body types.
501
pub const PAYLOAD_MAX_SIZE_ALL: u16 = min(
502
    PAYLOAD_MAX_SIZE_V0,
503
    PAYLOAD_MAX_SIZE_V1_WITH_STREAM_ID,
504
    PAYLOAD_MAX_SIZE_V1_WITHOUT_STREAM_ID,
505
);
506

            
507
/// The maximum amount of payload data that can fit within any cell body type.
508
pub const PAYLOAD_MAX_SIZE_ANY: u16 = max(
509
    PAYLOAD_MAX_SIZE_V0,
510
    PAYLOAD_MAX_SIZE_V1_WITH_STREAM_ID,
511
    PAYLOAD_MAX_SIZE_V1_WITHOUT_STREAM_ID,
512
);
513

            
514
impl UnparsedRelayMsg {
515
    /// Wrap a BoxedCellBody as an UnparsedRelayMsg.
516
    ///
517
    /// Fails if the body doesn't correspond to exactly one relay message, but
518
    /// doesn't parse the message itself.
519
    ///
520
    /// Non-test code should generally use `RelayCellDecoder` instead.
521
    // Ideally we'd make this `#[cfg(test)]`, but then we wouldn't be able
522
    // to use it in integration tests.
523
    // https://github.com/rust-lang/rust/issues/84629
524
117208
    pub fn from_singleton_body(version: RelayCellFormat, body: BoxedCellBody) -> Result<Self> {
525
117208
        let mut decoder = RelayCellDecoder::new(version);
526
117208
        let res = decoder.decode(body)?;
527
117208
        let (mut msgs, incomplete) = res.into_parts();
528
117208
        let Some(msg) = msgs.next() else {
529
            // There was no complete message in the cell.
530
            return Err(Error::MissingData);
531
        };
532
117208
        if incomplete.is_some() {
533
            // There was an incomplete message at the end of the cell.
534
            return Err(Error::ExtraneousBytes);
535
117208
        }
536
117208
        if msgs.next().is_some() {
537
            // There was more than one message in the cell.
538
            return Err(Error::ExtraneousBytes);
539
117208
        }
540
117208
        Ok(msg)
541
117208
    }
542

            
543
    /// Return the command for this cell.
544
115640
    pub fn cmd(&self) -> RelayCmd {
545
115640
        match &self.internal {
546
114744
            UnparsedRelayMsgInternal::V0(body) => {
547
                /// Position of the command within the v0 cell body.
548
                const CMD_OFFSET: usize = 0;
549
114744
                body[CMD_OFFSET].into()
550
            }
551
896
            UnparsedRelayMsgInternal::V1(body) => {
552
                /// Position of the command within the v1 body.
553
                const CMD_OFFSET: usize = 16;
554
896
                body[CMD_OFFSET].into()
555
            }
556
        }
557
115640
    }
558
    /// Return the stream ID for the stream that this msg corresponds to, if any.
559
14000
    pub fn stream_id(&self) -> Option<StreamId> {
560
14000
        match &self.internal {
561
13776
            UnparsedRelayMsgInternal::V0(body) => StreamId::new(u16::from_be_bytes(
562
13776
                body[STREAM_ID_OFFSET_V0..STREAM_ID_OFFSET_V0 + 2]
563
13776
                    .try_into()
564
13776
                    .expect("two-byte slice was not two bytes long!?"),
565
            )),
566
224
            UnparsedRelayMsgInternal::V1(body) => {
567
224
                match self.cmd().expects_streamid(Some(RelayCellFormat::V1)) {
568
112
                    StreamIdReq::WantNone => None,
569
                    StreamIdReq::Unrecognized | StreamIdReq::Any => None,
570
112
                    StreamIdReq::WantSome => StreamId::new(u16::from_be_bytes(
571
112
                        body[STREAM_ID_OFFSET_V1..STREAM_ID_OFFSET_V1 + 2]
572
112
                            .try_into()
573
112
                            .expect("two-byte slice was not two bytes long!?"),
574
                    )),
575
                }
576
            }
577
        }
578
14000
    }
579
    /// Return the "length" field of a data cell, or 0 if not a data cell.
580
    ///
581
    /// This is the size of the cell data (the "data" field), not the size of the cell.
582
    ///
583
    /// If the field value is invalid (for example >509 for V0 cells), an error will be returned.
584
11872
    pub fn data_len(&self) -> Result<u16> {
585
11872
        if self.cmd() != RelayCmd::DATA {
586
6608
            return Ok(0);
587
5264
        }
588

            
589
5264
        let bytes: [u8; 2] = match &self.internal {
590
5096
            UnparsedRelayMsgInternal::V0(body) => &body[LENGTH_OFFSET_V0..LENGTH_OFFSET_V0 + 2],
591
168
            UnparsedRelayMsgInternal::V1(body) => &body[LENGTH_OFFSET_V1..LENGTH_OFFSET_V1 + 2],
592
        }
593
5264
        .try_into()
594
5264
        .expect("two-byte slice was not two bytes long!?");
595

            
596
5264
        let len = u16::from_be_bytes(bytes);
597

            
598
5264
        let max = match &self.internal {
599
5096
            UnparsedRelayMsgInternal::V0(_body) => BODY_MAX_LEN_V0,
600
168
            UnparsedRelayMsgInternal::V1(_body) => BODY_MAX_LEN_V1,
601
        };
602

            
603
5264
        if len > max {
604
            // TODO: This error value isn't quite right as it has the error message "object length
605
            // too large to represent as usize", which isn't what we're checking here.
606
            // But it wouldn't make sense to add a different but similar variant to `Error`.
607
112
            return Err(Error::BadLengthValue);
608
5152
        }
609

            
610
5152
        Ok(len)
611
11872
    }
612
    /// Decode this unparsed cell into a given cell type.
613
4592
    pub fn decode<M: RelayMsg>(self) -> Result<RelayMsgOuter<M>> {
614
4592
        match self.internal {
615
4572
            UnparsedRelayMsgInternal::V0(body) => {
616
4572
                let mut reader = Reader::from_slice(body.as_ref());
617
4572
                RelayMsgOuter::decode_v0_from_reader(&mut reader)
618
            }
619
20
            UnparsedRelayMsgInternal::V1(body) => {
620
20
                let mut reader = Reader::from_slice(body.as_ref());
621
20
                RelayMsgOuter::decode_v1_from_reader(&mut reader)
622
            }
623
        }
624
4592
    }
625
}
626

            
627
/// A decoded and parsed relay message of unrestricted type,
628
/// with an accompanying optional Stream ID.
629
pub type AnyRelayMsgOuter = RelayMsgOuter<msg::AnyRelayMsg>;
630

            
631
/// A deprecated name for AnyRelayMsgOuter.
632
#[deprecated(note = "Use AnyRelayMsgOuter instead.")]
633
pub type AnyRelayCell = AnyRelayMsgOuter;
634

            
635
/// Trait implemented by anything that can serve as a relay message.
636
///
637
/// Typically, this will be [`RelayMsg`] (to represent an unrestricted relay
638
/// message), or a restricted subset of `RelayMsg`.
639
pub trait RelayMsg {
640
    /// Return the stream command associated with this message.
641
    fn cmd(&self) -> RelayCmd;
642
    /// Encode the body of this message, not including command or length
643
    fn encode_onto<W: tor_bytes::Writer + ?Sized>(self, w: &mut W) -> tor_bytes::EncodeResult<()>;
644
    /// Extract the body of a message with command `cmd` from reader `r`.
645
    fn decode_from_reader(cmd: RelayCmd, r: &mut Reader<'_>) -> Result<Self>
646
    where
647
        Self: Sized;
648
}
649

            
650
/// A decoded and parsed relay message, along with an optional Stream ID.
651
///
652
/// This type represents a message that can be sent along a
653
/// circuit, along with the ID for an associated stream that the
654
/// message is meant for.
655
///
656
/// NOTE: This name is a placeholder; we intend to replace it once we have
657
/// standardized our vocabulary in this area.
658
#[derive(Debug)]
659
pub struct RelayMsgOuter<M> {
660
    /// The stream ID for the stream that this cell corresponds to.
661
    streamid: Option<StreamId>,
662
    /// The relay message for this cell.
663
    msg: M,
664
}
665

            
666
/// A deprecated name for RelayMsgOuter.
667
#[deprecated(note = "Use RelayMsgOuter instead.")]
668
pub type RelayCell<M> = RelayMsgOuter<M>;
669

            
670
impl<M: RelayMsg> RelayMsgOuter<M> {
671
    /// Construct a new relay cell.
672
5150
    pub fn new(streamid: Option<StreamId>, msg: M) -> Self {
673
5150
        RelayMsgOuter { streamid, msg }
674
5150
    }
675
    /// Consume this cell and return its components.
676
4058
    pub fn into_streamid_and_msg(self) -> (Option<StreamId>, M) {
677
4058
        (self.streamid, self.msg)
678
4058
    }
679
    /// Return the command for this cell.
680
15068
    pub fn cmd(&self) -> RelayCmd {
681
15068
        self.msg.cmd()
682
15068
    }
683
    /// Return the stream ID for the stream that this cell corresponds to.
684
4612
    pub fn stream_id(&self) -> Option<StreamId> {
685
4612
        self.streamid
686
4612
    }
687
    /// Return the underlying message for this cell.
688
4186
    pub fn msg(&self) -> &M {
689
4186
        &self.msg
690
4186
    }
691
    /// Consume this cell and return the underlying message.
692
428
    pub fn into_msg(self) -> M {
693
428
        self.msg
694
428
    }
695
    /// Consume this relay message and encode it as a 509-byte padded cell
696
    /// body.
697
    //
698
    // TODO prop340: This API won't work for packed or fragmented messages.
699
5154
    pub fn encode<R: Rng + CryptoRng>(
700
5154
        self,
701
5154
        format: RelayCellFormat,
702
5154
        rng: &mut R,
703
5154
    ) -> crate::Result<BoxedCellBody> {
704
        /// We skip this much space before adding any random padding to the
705
        /// end of the cell
706
        const MIN_SPACE_BEFORE_PADDING: usize = 4;
707

            
708
5154
        let (mut body, enc_len) = match format {
709
5142
            RelayCellFormat::V0 => self.encode_to_cell_v0()?,
710
12
            RelayCellFormat::V1 => self.encode_to_cell_v1()?,
711
        };
712
5154
        debug_assert!(enc_len <= CELL_DATA_LEN);
713
5154
        if enc_len < CELL_DATA_LEN - MIN_SPACE_BEFORE_PADDING {
714
1014
            rng.fill_bytes(&mut body[enc_len + MIN_SPACE_BEFORE_PADDING..]);
715
4156
        }
716

            
717
5154
        Ok(body)
718
5154
    }
719

            
720
    /// Consume a relay cell and return its contents, encoded for use
721
    /// in a RELAY or RELAY_EARLY cell.
722
5142
    fn encode_to_cell_v0(self) -> EncodeResult<(BoxedCellBody, usize)> {
723
        // NOTE: This implementation is a bit optimized, since it happens to
724
        // literally every relay cell that we produce.
725

            
726
        // TODO -NM: Add a specialized implementation for making a DATA cell from
727
        // a body?
728

            
729
        /// The position of the length field within a relay cell.
730
        const LEN_POS: usize = 9;
731
        /// The position of the body a relay cell.
732
        const BODY_POS: usize = 11;
733

            
734
5142
        let body = BodyWrapper(Box::new([0_u8; BODY_MAX_LEN_V0 as usize]));
735

            
736
5142
        let mut w = crate::slicewriter::SliceWriter::new(body);
737
5142
        w.write_u8(self.msg.cmd().into());
738
5142
        w.write_u16(0); // "Recognized"
739
5142
        w.assert_offset_is(STREAM_ID_OFFSET_V0);
740
5142
        w.write_u16(StreamId::get_or_zero(self.streamid));
741
5142
        w.write_u32(0); // Digest
742
        // (It would be simpler to use NestedWriter at this point, but it uses an internal Vec that we are trying to avoid.)
743
5142
        w.assert_offset_is(LEN_POS);
744
5142
        w.write_u16(0); // Length.
745
5142
        w.assert_offset_is(BODY_POS);
746
5142
        self.msg.encode_onto(&mut w)?; // body
747
5142
        let (mut body, written) = w.try_unwrap().map_err(|_| {
748
            EncodeError::Bug(internal!(
749
                "Encoding of relay message was too long to fit into a cell!"
750
            ))
751
        })?;
752
5142
        let payload_len = written - BODY_POS;
753
5142
        debug_assert!(payload_len < u16::MAX as usize);
754
5142
        *(<&mut [u8; 2]>::try_from(&mut body.0[LEN_POS..LEN_POS + 2])
755
5142
            .expect("Two-byte slice was not two bytes long!?")) =
756
5142
            (payload_len as u16).to_be_bytes();
757
5142
        Ok((body.0, written))
758
5142
    }
759

            
760
    /// Consume a relay cell and return its contents, encoded for use
761
    /// in a RELAY or RELAY_EARLY cell.
762
12
    fn encode_to_cell_v1(self) -> EncodeResult<(BoxedCellBody, usize)> {
763
        // NOTE: This implementation is a bit optimized, since it happens to
764
        // literally every relay cell that we produce.
765
        // TODO -NM: Add a specialized implementation for making a DATA cell from
766
        // a body?
767

            
768
        /// Position of the length field within the cell.
769
        const LEN_POS_V1: usize = 16 + 1; // Skipping tag, command.
770

            
771
12
        let cmd = self.msg.cmd();
772
12
        let body = BodyWrapper(Box::new([0_u8; BODY_MAX_LEN_V1 as usize]));
773
12
        let mut w = crate::slicewriter::SliceWriter::new(body);
774
12
        w.advance(16); // Tag: 16 bytes
775
12
        w.write_u8(cmd.get()); // Command: 1 byte.
776
12
        w.assert_offset_is(LEN_POS_V1);
777
12
        w.advance(2); //  Length: 2 bytes.
778
12
        let mut body_pos = 16 + 1 + 2;
779
        match (
780
12
            cmd.expects_streamid(Some(RelayCellFormat::V1)),
781
12
            self.streamid,
782
        ) {
783
8
            (StreamIdReq::WantNone, None) => {}
784
4
            (StreamIdReq::WantSome, Some(id)) => {
785
4
                w.write_u16(id.into());
786
4
                body_pos += 2;
787
4
            }
788
            (_, id) => {
789
                return Err(EncodeError::Bug(internal!(
790
                    "Tried to encode invalid stream ID {id:?} for {cmd}"
791
                )));
792
            }
793
        }
794
12
        w.assert_offset_is(body_pos);
795

            
796
12
        self.msg.encode_onto(&mut w)?; // body
797
12
        let (mut body, written) = w.try_unwrap().map_err(|_| {
798
            EncodeError::Bug(internal!(
799
                "Encoding of relay message was too long to fit into a cell!"
800
            ))
801
        })?;
802
12
        let payload_len = written - body_pos;
803
12
        debug_assert!(payload_len < u16::MAX as usize);
804
12
        *(<&mut [u8; 2]>::try_from(&mut body.0[LEN_POS_V1..LEN_POS_V1 + 2])
805
12
            .expect("Two-byte slice was not two bytes long!?")) =
806
12
            (payload_len as u16).to_be_bytes();
807
12
        Ok((body.0, written))
808
12
    }
809

            
810
    /// Parse a RELAY or RELAY_EARLY cell body into a RelayMsgOuter.
811
    /// Requires that the cryptographic checks on the message have already been
812
    /// performed
813
    ///
814
    /// Fails if the cell doesn't contain exactly one message.
815
    ///
816
    /// Non-test code should generally use `RelayCellDecoder` instead.
817
    // Ideally we'd make this `#[cfg(test)]`, but then we wouldn't be able
818
    // to use it in integration tests.
819
    // https://github.com/rust-lang/rust/issues/84629
820
    #[allow(clippy::needless_pass_by_value)] // TODO this will go away soon.
821
4100
    pub fn decode_singleton(version: RelayCellFormat, body: BoxedCellBody) -> Result<Self> {
822
4100
        let unparsed_msg = UnparsedRelayMsg::from_singleton_body(version, body)?;
823
4100
        unparsed_msg.decode()
824
4100
    }
825
    /// Parse a `RelayCellFormat::V0` RELAY or RELAY_EARLY cell body into a
826
    /// RelayMsgOuter from a reader.
827
    ///
828
    /// Requires that the cryptographic checks on the message have already been
829
    /// performed
830
4572
    fn decode_v0_from_reader(r: &mut Reader<'_>) -> Result<Self> {
831
4572
        let cmd = r.take_u8()?.into();
832
4572
        r.advance(2)?; // "recognized"
833
4572
        let streamid = StreamId::new(r.take_u16()?);
834
4572
        r.advance(4)?; // digest
835
4572
        let len = r.take_u16()? as usize;
836
4572
        if r.remaining() < len {
837
2
            return Err(Error::InvalidMessage(
838
2
                "Insufficient data in relay cell".into(),
839
2
            ));
840
4570
        }
841
4570
        r.truncate(len);
842
4570
        let msg = M::decode_from_reader(cmd, r)?;
843
4558
        Ok(Self { streamid, msg })
844
4572
    }
845

            
846
    /// Parse a `RelayCellFormat::V1` RELAY or RELAY_EARLY cell body into a
847
    /// RelayMsgOuter from a reader.
848
    ///
849
    /// Requires that the cryptographic checks on the message have already been
850
    /// performed.
851
20
    fn decode_v1_from_reader(r: &mut Reader<'_>) -> Result<Self> {
852
20
        r.advance(16)?; // Tag
853
20
        let cmd: RelayCmd = r.take_u8()?.into();
854
20
        let len = r.take_u16()?.into();
855
20
        let streamid = match cmd.expects_streamid(Some(RelayCellFormat::V1)) {
856
            // If no stream ID is expected, then the body begins immediately.
857
8
            StreamIdReq::WantNone => None,
858
            // In this case, a stream ID _is_ expected.
859
            //
860
            // (If it happens to be zero, we will reject the message,
861
            // since zero is never a stream ID.)
862
10
            StreamIdReq::WantSome => Some(StreamId::new(r.take_u16()?).ok_or_else(|| {
863
2
                Error::InvalidMessage(
864
2
                    format!("Zero-valued stream ID with relay command {cmd}").into(),
865
2
                )
866
2
            })?),
867
            // We treat an unrecognized command as having no stream ID.
868
            //
869
            // (Note: This command is truly unrecognized, and not one that we could parse
870
            // differently under other circumstances.)
871
            //
872
            // Note that this enables a destructive fingerprinting opportunity,
873
            // where an attacker can learn whether we have a version of Arti that recognizes this
874
            // command, at the expense of our killing this circuit immediately if they are wrong.
875
            // This is not a very bad attack.
876
            //
877
            // Note that StreamIdReq::Any should be impossible here, since we're using the V1
878
            // format.
879
            StreamIdReq::Unrecognized | StreamIdReq::Any => {
880
2
                return Err(Error::InvalidMessage(
881
2
                    format!("Unrecognized relay command {cmd}").into(),
882
2
                ));
883
            }
884
        };
885
16
        if r.remaining() < len {
886
            //
887
2
            return Err(Error::InvalidMessage(
888
2
                "Insufficient data in relay cell".into(),
889
2
            ));
890
14
        }
891
14
        r.truncate(len);
892
14
        let msg = M::decode_from_reader(cmd, r)?;
893
14
        Ok(Self { streamid, msg })
894
20
    }
895
}
896

            
897
/// Wrap a BoxedCellBody and implement AsMut<[u8]>, so we can use it with `SliceWriter`.
898
struct BodyWrapper(BoxedCellBody);
899
impl AsMut<[u8]> for BodyWrapper {
900
1840160
    fn as_mut(&mut self) -> &mut [u8] {
901
1840160
        self.0.as_mut()
902
1840160
    }
903
}