1
//! Implementations of Writeable and Readable for several items that
2
//! we use in Tor.
3
//!
4
//! These don't need to be in a separate module, but for convenience
5
//! this is where I'm putting them.
6

            
7
use super::*;
8

            
9
// ----------------------------------------------------------------------
10

            
11
/// `Vec<u8>` is the main type that implements [`Writer`].
12
impl Writer for Vec<u8> {
13
457692
    fn write_all(&mut self, bytes: &[u8]) {
14
457692
        self.extend_from_slice(bytes);
15
457692
    }
16
327078
    fn write_u8(&mut self, byte: u8) {
17
327078
        // specialize for performance
18
327078
        self.push(byte);
19
327078
    }
20
252
    fn write_zeros(&mut self, n: usize) {
21
252
        // specialize for performance
22
252
        let new_len = self.len().saturating_add(n);
23
252
        self.resize(new_len, 0);
24
252
    }
25
}
26

            
27
impl Writer for bytes::BytesMut {
28
2740
    fn write_all(&mut self, bytes: &[u8]) {
29
2740
        self.extend_from_slice(bytes);
30
2740
    }
31
}
32

            
33
// ----------------------------------------------------------------------
34

            
35
impl Writeable for [u8] {
36
1034
    fn write_onto<B: Writer + ?Sized>(&self, b: &mut B) -> EncodeResult<()> {
37
1034
        b.write_all(self);
38
1034
        Ok(())
39
1034
    }
40
}
41

            
42
impl Writeable for Vec<u8> {
43
61356
    fn write_onto<B: Writer + ?Sized>(&self, b: &mut B) -> EncodeResult<()> {
44
61356
        b.write_all(&self[..]);
45
61356
        Ok(())
46
61356
    }
47
}
48

            
49
// We also need to implement our traits for an older version (0.14) of
50
// generic_array, since that's what the digest crate uses (as of digest 0.10.)
51
impl<N> Readable for digest::generic_array::GenericArray<u8, N>
52
where
53
    N: digest::generic_array::ArrayLength<u8>,
54
{
55
32
    fn take_from(b: &mut Reader<'_>) -> Result<Self> {
56
32
        // safety -- "take" returns the requested bytes or error.
57
32
        Ok(Self::clone_from_slice(b.take(N::to_usize())?))
58
32
    }
59
}
60

            
61
impl<N> Writeable for digest::generic_array::GenericArray<u8, N>
62
where
63
    N: digest::generic_array::ArrayLength<u8>,
64
{
65
2
    fn write_onto<B: Writer + ?Sized>(&self, b: &mut B) -> EncodeResult<()> {
66
2
        b.write_all(self.as_slice());
67
2
        Ok(())
68
2
    }
69
}
70

            
71
/*
72
// We could add these as well as our implementations over GenericArray<u8>,
73
// except that we don't actually need them, and Rust doesn't support
74
// specialization.
75

            
76
impl<T, N> Readable for GenericArray<T, N>
77
where
78
    T: Readable + Clone,
79
    N: generic_array::ArrayLength<T>,
80
{
81
    fn take_from(b: &mut Reader<'_>) -> Result<Self> {
82
        let mut v: Vec<T> = Vec::new();
83
        for _ in 0..N::to_usize() {
84
            v.push(T::take_from(b)?);
85
        }
86
        // TODO(nickm) I wish I didn't have to clone this.
87
        Ok(Self::from_slice(v.as_slice()).clone())
88
    }
89
}
90

            
91
impl<T, N> Writeable for GenericArray<T, N>
92
where
93
    T: Writeable,
94
    N: generic_array::ArrayLength<T>,
95
{
96
    fn write_onto<B: Writer + ?Sized>(&self, b: &mut B) {
97
        for item in self {
98
            item.write_onto(b)
99
        }
100
    }
101
}
102
*/
103

            
104
/// Make Readable and Writeable implementations for a provided
105
/// unsigned type, delegating to the `read_uNN` and `write_uNN` functions.
106
macro_rules! impl_u {
107
    ( $t:ty, $wrfn:ident, $rdfn:ident ) => {
108
        impl Writeable for $t {
109
30732
            fn write_onto<B: Writer + ?Sized>(&self, b: &mut B) -> EncodeResult<()> {
110
30732
                b.$wrfn(*self);
111
30732
                Ok(())
112
30732
            }
113
        }
114
        impl Readable for $t {
115
25449
            fn take_from(b: &mut Reader<'_>) -> Result<Self> {
116
25449
                b.$rdfn()
117
25449
            }
118
        }
119
    };
120
}
121

            
122
impl_u!(u8, write_u8, take_u8);
123
impl_u!(u16, write_u16, take_u16);
124
impl_u!(u32, write_u32, take_u32);
125
impl_u!(u64, write_u64, take_u64);
126
impl_u!(u128, write_u128, take_u128);
127

            
128
// ----------------------------------------------------------------------
129

            
130
/// Implement [`Readable`] and [`Writeable`] for IPv4 and IPv6 addresses.
131
///
132
/// These are encoded as a sequence of octets, not as strings.
133
mod net_impls {
134
    use super::*;
135
    use std::net::{Ipv4Addr, Ipv6Addr};
136

            
137
    impl Writeable for Ipv4Addr {
138
15808
        fn write_onto<B: Writer + ?Sized>(&self, b: &mut B) -> EncodeResult<()> {
139
15808
            b.write_all(&self.octets()[..]);
140
15808
            Ok(())
141
15808
        }
142
    }
143

            
144
    impl Readable for Ipv4Addr {
145
7346
        fn take_from(b: &mut Reader<'_>) -> Result<Self> {
146
7346
            Ok(b.take_u32()?.into())
147
7346
        }
148
    }
149

            
150
    impl Writeable for Ipv6Addr {
151
690
        fn write_onto<B: Writer + ?Sized>(&self, b: &mut B) -> EncodeResult<()> {
152
690
            b.write_all(&self.octets()[..]);
153
690
            Ok(())
154
690
        }
155
    }
156
    impl Readable for Ipv6Addr {
157
5170
        fn take_from(b: &mut Reader<'_>) -> Result<Self> {
158
5170
            Ok(b.take_u128()?.into())
159
5170
        }
160
    }
161
}
162

            
163
/// Implement [`Readable`] and [`Writeable`] for Ed25519 types.
164
#[cfg(feature = "tor-llcrypto")]
165
mod ed25519_impls {
166
    use super::*;
167
    use tor_llcrypto::pk::ed25519;
168

            
169
    impl Writeable for ed25519::PublicKey {
170
26
        fn write_onto<B: Writer + ?Sized>(&self, b: &mut B) -> EncodeResult<()> {
171
26
            b.write_all(self.as_bytes());
172
26
            Ok(())
173
26
        }
174
    }
175
    impl Readable for ed25519::PublicKey {
176
6
        fn take_from(b: &mut Reader<'_>) -> Result<Self> {
177
6
            let bytes: [u8; 32] = b.extract()?;
178
4
            Self::from_bytes(&bytes)
179
5
                .map_err(|_| Error::InvalidMessage("Couldn't decode Ed25519 public key".into()))
180
6
        }
181
    }
182

            
183
    impl Writeable for ed25519::Ed25519Identity {
184
2894
        fn write_onto<B: Writer + ?Sized>(&self, b: &mut B) -> EncodeResult<()> {
185
2894
            b.write_all(self.as_bytes());
186
2894
            Ok(())
187
2894
        }
188
    }
189
    impl Readable for ed25519::Ed25519Identity {
190
21888
        fn take_from(b: &mut Reader<'_>) -> Result<Self> {
191
21888
            let bytes: [u8; 32] = b.extract()?;
192
21888
            Ok(Self::new(bytes))
193
21888
        }
194
    }
195
    impl Writeable for ed25519::Signature {
196
23756
        fn write_onto<B: Writer + ?Sized>(&self, b: &mut B) -> EncodeResult<()> {
197
23756
            b.write_all(&self.to_bytes()[..]);
198
23756
            Ok(())
199
23756
        }
200
    }
201
    impl Readable for ed25519::Signature {
202
20802
        fn take_from(b: &mut Reader<'_>) -> Result<Self> {
203
20802
            let bytes: [u8; 64] = b.extract()?;
204
20802
            Ok(Self::from_bytes(&bytes))
205
20802
        }
206
    }
207
}
208

            
209
/// Implement Readable and Writeable for Curve25519 types.
210
#[cfg(feature = "tor-llcrypto")]
211
mod curve25519_impls {
212
    use super::*;
213
    use tor_llcrypto::pk::curve25519::{PublicKey, SharedSecret};
214

            
215
    impl Writeable for PublicKey {
216
1262
        fn write_onto<B: Writer + ?Sized>(&self, b: &mut B) -> EncodeResult<()> {
217
1262
            b.write_all(self.as_bytes());
218
1262
            Ok(())
219
1262
        }
220
    }
221
    impl Readable for PublicKey {
222
5172
        fn take_from(b: &mut Reader<'_>) -> Result<Self> {
223
5172
            let bytes: [u8; 32] = b.extract()?;
224
5172
            Ok(bytes.into())
225
5172
        }
226
    }
227
    impl Writeable for SharedSecret {
228
320
        fn write_onto<B: Writer + ?Sized>(&self, b: &mut B) -> EncodeResult<()> {
229
320
            b.write_all(self.as_bytes());
230
320
            Ok(())
231
320
        }
232
    }
233
}
234

            
235
/// Implement readable and writeable for the RsaIdentity type.
236
#[cfg(feature = "tor-llcrypto")]
237
mod rsa_impls {
238
    use super::*;
239
    use tor_llcrypto::pk::rsa::*;
240

            
241
    impl Writeable for RsaIdentity {
242
4652
        fn write_onto<B: Writer + ?Sized>(&self, b: &mut B) -> EncodeResult<()> {
243
4652
            b.write_all(self.as_bytes());
244
4652
            Ok(())
245
4652
        }
246
    }
247
    impl Readable for RsaIdentity {
248
1256
        fn take_from(b: &mut Reader<'_>) -> Result<Self> {
249
1256
            let m = b.take(RSA_ID_LEN)?;
250
1256
            RsaIdentity::from_bytes(m)
251
1256
                .ok_or_else(|| tor_error::internal!("wrong number of bytes from take").into())
252
1256
        }
253
    }
254
}
255

            
256
/// Implement readable and writeable for the digest::CtOutput type.
257
mod digest_impls {
258
    use super::*;
259
    use digest::{CtOutput, OutputSizeUser};
260
    impl<T: OutputSizeUser> WriteableOnce for CtOutput<T> {
261
74
        fn write_into<B: Writer + ?Sized>(self, b: &mut B) -> EncodeResult<()> {
262
74
            let code = self.into_bytes();
263
74
            b.write_all(&code[..]);
264
74
            Ok(())
265
74
        }
266
    }
267
    impl<T: OutputSizeUser> Readable for CtOutput<T> {
268
30
        fn take_from(b: &mut Reader<'_>) -> Result<Self> {
269
30
            let array = digest::generic_array::GenericArray::take_from(b)?;
270
30
            Ok(CtOutput::new(array))
271
30
        }
272
    }
273
}
274

            
275
/// Implement readable and writeable for u8 arrays.
276
mod u8_array_impls {
277
    use super::*;
278
    impl<const N: usize> Writeable for [u8; N] {
279
1064
        fn write_onto<B: Writer + ?Sized>(&self, b: &mut B) -> EncodeResult<()> {
280
1064
            b.write_all(&self[..]);
281
1064
            Ok(())
282
1064
        }
283
    }
284

            
285
    impl<const N: usize> Readable for [u8; N] {
286
432007
        fn take_from(b: &mut Reader<'_>) -> Result<Self> {
287
432007
            // note: Conceivably this should use MaybeUninit, but let's
288
432007
            // avoid that unless there is some measurable benefit.
289
432007
            let mut array = [0_u8; N];
290
432007
            b.take_into(&mut array[..])?;
291
419084
            Ok(array)
292
432007
        }
293
    }
294
}
295

            
296
/// Implement Readable and Writeable for `CtByteArray`
297
#[cfg(feature = "tor-llcrypto")]
298
mod ctbytearray_impls {
299
    use super::*;
300
    use tor_llcrypto::util::ct::CtByteArray;
301
    impl<const N: usize> Writeable for CtByteArray<N> {
302
26
        fn write_onto<B: Writer + ?Sized>(&self, b: &mut B) -> EncodeResult<()> {
303
26
            b.write_all(&self.as_ref()[..]);
304
26
            Ok(())
305
26
        }
306
    }
307

            
308
    impl<const N: usize> Readable for CtByteArray<N> {
309
501
        fn take_from(b: &mut Reader<'_>) -> Result<Self> {
310
501
            Ok(CtByteArray::from(b.extract::<[u8; N]>()?))
311
501
        }
312
    }
313
}
314

            
315
#[cfg(test)]
316
mod tests {
317
    #![allow(clippy::unwrap_used)]
318
    use crate::{Reader, Writer};
319
    #[cfg(feature = "tor-llcrypto")]
320
    use hex_literal::hex;
321

            
322
    macro_rules! check_encode {
323
        ($e:expr, $e2:expr) => {
324
            let mut w = Vec::new();
325
            w.write(&$e).expect("encoding failed");
326
            assert_eq!(&w[..], &$e2[..]);
327
        };
328
    }
329
    macro_rules! check_decode {
330
        ($t:ty, $e:expr, $e2:expr) => {
331
            let mut b = Reader::from_slice_for_test(&$e[..]);
332
            let obj: $t = b.extract().unwrap();
333
            assert_eq!(obj, $e2);
334
            assert!(b.should_be_exhausted().is_ok());
335
        };
336
    }
337
    macro_rules! check_roundtrip {
338
        ($t:ty, $e:expr, $e2:expr) => {
339
            check_encode!($e, $e2);
340
            check_decode!($t, $e2, $e);
341
        };
342
    }
343
    #[cfg(feature = "tor-llcrypto")]
344
    macro_rules! check_bad {
345
        ($t:ty, $e:expr) => {
346
            let mut b = Reader::from_slice_for_test(&$e[..]);
347
            let len_orig = b.remaining();
348
            let res: Result<$t, _> = b.extract();
349
            assert!(res.is_err());
350
            assert_eq!(b.remaining(), len_orig);
351
        };
352
    }
353
    #[test]
354
    fn vec_u8() {
355
        let v: Vec<u8> = vec![1, 2, 3, 4];
356
        check_encode!(v, b"\x01\x02\x03\x04");
357
    }
358

            
359
    #[test]
360
    fn genarray() {
361
        use digest::generic_array as ga;
362
        let a: ga::GenericArray<u8, ga::typenum::U7> = [4, 5, 6, 7, 8, 9, 10].into();
363
        check_roundtrip!(ga::GenericArray<u8, ga::typenum::U7>,
364
                         a,
365
                         [4, 5, 6, 7, 8, 9, 10]);
366
    }
367

            
368
    #[test]
369
    fn roundtrip_u64() {
370
        check_roundtrip!(u64, 0x4040111_u64, [0, 0, 0, 0, 4, 4, 1, 17]);
371
    }
372

            
373
    #[test]
374
    fn u8_array() {
375
        check_roundtrip!(
376
            [u8; 16],
377
            [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
378
            [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
379
        );
380
    }
381

            
382
    #[test]
383
    fn ipv4addr() {
384
        use std::net::Ipv4Addr;
385
        check_roundtrip!(Ipv4Addr, Ipv4Addr::new(192, 168, 0, 1), [192, 168, 0, 1]);
386
    }
387

            
388
    #[test]
389
    fn ipv6addr() {
390
        use std::net::Ipv6Addr;
391
        check_roundtrip!(
392
            Ipv6Addr,
393
            Ipv6Addr::new(65535, 77, 1, 1, 1, 0, 0, 0),
394
            [255, 255, 0, 77, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0]
395
        );
396
    }
397

            
398
    #[cfg(feature = "tor-llcrypto")]
399
    #[test]
400
    fn ed25519() {
401
        use tor_llcrypto::pk::ed25519;
402
        let b = &hex!(
403
            "68a6cee11d2883661f5876f7aac748992cd140f
404
             cfc36923aa957d04b5f8967ff"
405
        );
406
        check_roundtrip!(
407
            ed25519::PublicKey,
408
            ed25519::PublicKey::from_bytes(b).unwrap(),
409
            b
410
        );
411
        let b = &hex!(
412
            "68a6cee11d2883661f5876f7aac748992cd140f
413
             cfc36923aa957d04b5f8967"
414
        ); // too short
415
        check_bad!(ed25519::PublicKey, b);
416
        let b = &hex!(
417
            "68a6cee11d2883661f5876f7aac748992cd140f
418
             cfc36923aa957d04b5f896700"
419
        ); // not a valid compressed Y
420
        check_bad!(ed25519::PublicKey, b);
421

            
422
        let sig = &hex!(
423
            "b8842c083a56076fc27c8af21211f9fe57d1c32d9d
424
             c804f76a8fa858b9ab43622b9e8335993c422eab15
425
             6ebb5a047033f35256333a47a508b02699314d22550e"
426
        );
427
        check_roundtrip!(ed25519::Signature, ed25519::Signature::from_bytes(sig), sig);
428

            
429
        // Test removed: The ed25519::Signature type is now happy to hold any
430
        // 64-byte sequence.
431
        //
432
        // let sig = &hex!(
433
        //   "b8842c083a56076fc27c8af21211f9fe57d1c32d9d
434
        //     c804f76a8fa858b9ab43622b9e8335993c422eab15
435
        //     6ebb5a047033f35256333a47a508b02699314d2255ff"
436
        // );
437
        // check_bad!(ed25519::Signature, sig);
438
    }
439

            
440
    #[cfg(feature = "tor-llcrypto")]
441
    #[test]
442
    fn curve25519() {
443
        use tor_llcrypto::pk::curve25519;
444
        let b = &hex!("5f6df7a2fe3bcf1c9323e9755250efd79b9db4ed8f3fd21c7515398b6662a365");
445
        let pk: curve25519::PublicKey = (*b).into();
446
        check_roundtrip!(curve25519::PublicKey, pk, b);
447
    }
448

            
449
    #[cfg(feature = "tor-llcrypto")]
450
    #[test]
451
    fn rsa_id() {
452
        use tor_llcrypto::pk::rsa::RsaIdentity;
453
        let b = &hex!("9432D4CEA2621ED09F5A8088BE0E31E0D271435C");
454
        check_roundtrip!(RsaIdentity, RsaIdentity::from_bytes(b).unwrap(), b);
455
    }
456
}