Skip to main content

over_there/core/transport/wire/input/
mod.rs

1pub mod decoder;
2
3use crate::core::transport::crypto::{AssociatedData, CryptError, Decrypter, Nonce};
4use crate::core::transport::{auth::Verifier, wire::packet::Packet};
5use decoder::Decoder;
6use derive_more::{Display, Error};
7use std::time::Duration;
8
9#[derive(Debug, Display, Error)]
10pub enum InputProcessorError {
11    EncodePacket(serde_cbor::Error),
12    UnableToVerifySignature,
13    InvalidPacketSignature,
14    DecodeData(decoder::DecoderError),
15    DecryptData(CryptError),
16}
17
18#[derive(Debug, Clone)]
19pub struct InputProcessor<V, D>
20where
21    V: Verifier,
22    D: Decrypter,
23{
24    decoder: Decoder,
25    verifier: V,
26    decrypter: D,
27}
28
29impl<V, D> InputProcessor<V, D>
30where
31    V: Verifier,
32    D: Decrypter,
33{
34    pub fn new(packet_ttl: Duration, verifier: V, decrypter: D) -> Self {
35        let decoder = Decoder::new(packet_ttl);
36        Self {
37            decoder,
38            verifier,
39            decrypter,
40        }
41    }
42
43    pub fn process(
44        &mut self,
45        data: &[u8],
46    ) -> Result<Option<Vec<u8>>, InputProcessorError> {
47        if data.is_empty() {
48            return Ok(None);
49        }
50
51        // Process the data as a packet
52        let p = Packet::from_slice(data)
53            .map_err(InputProcessorError::EncodePacket)?;
54
55        // Verify the packet's signature, skipping any form of assembly if
56        // it is not a legit packet
57        if !verify_packet(&self.verifier, &p)? {
58            return Err(InputProcessorError::InvalidPacketSignature);
59        }
60
61        let group_id = p.id();
62        let nonce = p.nonce().cloned();
63
64        // Ensure that packet groups are still valid
65        self.decoder.remove_expired();
66
67        // Add the packet, see if we are ready to decode the data, and do so
68        let do_decode = add_packet_and_verify(&mut self.decoder, p)?;
69        if do_decode {
70            // Gather the complete data
71            let data = decode_and_decrypt(
72                group_id,
73                &self.decoder,
74                &self.decrypter,
75                nonce,
76            )?;
77
78            // Remove the underlying group as we no longer need to keep it
79            self.decoder.remove_group(group_id);
80
81            Ok(Some(data))
82        } else {
83            Ok(None)
84        }
85    }
86}
87
88fn verify_packet<V>(
89    verifier: &V,
90    packet: &Packet,
91) -> Result<bool, InputProcessorError>
92where
93    V: Verifier,
94{
95    let signature = packet.signature();
96    let content = packet
97        .content_for_signature()
98        .map_err(|_| InputProcessorError::UnableToVerifySignature)?;
99    Ok(verifier.verify(&content, signature))
100}
101
102/// Adds the packet to our internal cache and checks to see if we
103/// are ready to decode the packet
104fn add_packet_and_verify(
105    decoder: &mut Decoder,
106    packet: Packet,
107) -> Result<bool, InputProcessorError> {
108    let id = packet.id();
109
110    // Bubble up the error; we don't care about the success
111    decoder
112        .add_packet(packet)
113        .map_err(InputProcessorError::DecodeData)?;
114
115    Ok(decoder.verify(id))
116}
117
118/// Decodes the complete data held by the decoder and decrypts it
119/// using the internal bicrypter
120fn decode_and_decrypt<D>(
121    group_id: u32,
122    decoder: &Decoder,
123    decrypter: &D,
124    nonce: Option<Nonce>,
125) -> Result<Vec<u8>, InputProcessorError>
126where
127    D: Decrypter,
128{
129    // Decode our data, which could be encrypted
130    let data = decoder
131        .decode(group_id)
132        .map_err(InputProcessorError::DecodeData)?;
133
134    // Decrypt our collective data
135    let data = decrypter
136        .decrypt(&data, &AssociatedData::from(nonce))
137        .map_err(InputProcessorError::DecryptData)?;
138
139    Ok(data)
140}
141
142#[cfg(test)]
143mod tests {
144    use super::*;
145    use crate::core::transport::auth::NoopAuthenticator;
146    use crate::core::transport::crypto::NoopBicrypter;
147    use crate::core::transport::wire::{
148        output::encoder::{EncodeArgs, Encoder},
149        packet::{PacketEncryption, PacketType},
150    };
151    use std::time::Duration;
152
153    fn new_processor() -> InputProcessor<NoopAuthenticator, NoopBicrypter> {
154        InputProcessor::new(
155            Duration::from_secs(1),
156            NoopAuthenticator,
157            NoopBicrypter,
158        )
159    }
160
161    #[test]
162    fn input_processor_process_should_fail_if_unable_to_convert_bytes_to_packet(
163    ) {
164        let mut processor = new_processor();
165
166        match processor.process(&[0; 5]) {
167            Err(InputProcessorError::EncodePacket(_)) => (),
168            Err(x) => panic!("Unexpected error: {:?}", x),
169            Ok(x) => panic!("Unexpected result: {:?}", x),
170        }
171    }
172
173    #[test]
174    fn input_processor_process_should_fail_if_unable_to_add_packet_to_decoder()
175    {
176        let mut processor = new_processor();
177        let id = 0;
178        let encryption = PacketEncryption::None;
179        let data = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
180        let signer = NoopAuthenticator;
181        let mut encoder = Encoder::default();
182
183        // Calculate a packet size where the final packet can only
184        // fit a single byte of data to ensure that we get at least
185        // one additional packet
186        let max_packet_size = encoder
187            .estimate_packet_size(
188                /* data size */ 1,
189                PacketType::Final { encryption },
190                &signer,
191            )
192            .unwrap();
193
194        // Make several packets so that we don't send a single and last
195        // packet, which would remove itself from the cache and allow
196        // us to re-add a packet with the same id & index
197        let p = &encoder
198            .encode(EncodeArgs {
199                id,
200                encryption,
201                data: &data,
202                max_packet_size,
203                signer: &signer,
204            })
205            .unwrap()[0];
206        let data = p.to_vec().unwrap();
207        assert_eq!(
208            processor.process(&data).is_ok(),
209            true,
210            "Failed to receive first packet!"
211        );
212
213        // Add the same packet more than once, which should
214        // trigger the decoder to fail
215        match processor.process(&data) {
216            Err(InputProcessorError::DecodeData(_)) => (),
217            Err(x) => panic!("Unexpected error: {:?}", x),
218            Ok(x) => panic!("Unexpected result: {:?}", x),
219        }
220    }
221
222    #[test]
223    fn input_processor_process_should_return_none_if_zero_bytes_received() {
224        let mut processor = new_processor();
225
226        match processor.process(&[0; 0]) {
227            Ok(None) => (),
228            Ok(Some(x)) => panic!("Unexpected result: {:?}", x),
229            Err(x) => panic!("Unexpected error: {:?}", x),
230        }
231    }
232
233    #[test]
234    fn input_processor_process_should_return_none_if_received_packet_does_not_complete_data(
235    ) {
236        let mut processor = new_processor();
237
238        let id = 0;
239        let encryption = PacketEncryption::None;
240        let data = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
241        let signer = NoopAuthenticator;
242        let mut encoder = Encoder::default();
243
244        // Calculate a packet size where the final packet can only
245        // fit a single byte of data to ensure that we get at least
246        // one additional packet
247        let max_packet_size = encoder
248            .estimate_packet_size(
249                /* data size */ 1,
250                PacketType::Final { encryption },
251                &signer,
252            )
253            .unwrap();
254
255        // Make several packets so that we don't send a single and last
256        // packet, which would result in a complete message
257        let p = &encoder
258            .encode(EncodeArgs {
259                id,
260                encryption,
261                data: &data,
262                max_packet_size,
263                signer: &NoopAuthenticator,
264            })
265            .unwrap()[0];
266        let data = p.to_vec().unwrap();
267        match processor.process(&data) {
268            Ok(None) => (),
269            Ok(Some(x)) => panic!("Unexpected result: {:?}", x),
270            Err(x) => panic!("Unexpected error: {:?}", x),
271        }
272    }
273
274    #[test]
275    fn input_processor_process_should_return_some_data_if_received_packet_does_complete_data(
276    ) {
277        let mut processor = new_processor();
278        let data = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
279
280        // Make one large packet so we can complete a message
281        let p = &Encoder::default()
282            .encode(EncodeArgs {
283                id: 0,
284                encryption: PacketEncryption::None,
285                data: &data,
286                max_packet_size: 100,
287                signer: &NoopAuthenticator,
288            })
289            .unwrap()[0];
290        let pdata = p.to_vec().unwrap();
291        match processor.process(&pdata) {
292            Ok(Some(input_processor_process_data)) => {
293                assert_eq!(
294                    input_processor_process_data, data,
295                    "Received unexpected data: {:?}",
296                    input_processor_process_data
297                );
298            }
299            Ok(None) => panic!("Unexpectedly received no data"),
300            Err(x) => panic!("Unexpected error: {:?}", x),
301        }
302    }
303
304    #[test]
305    fn input_processor_process_should_remove_expired_packet_groups() {
306        // Create a custom context whose packet groups within its decoder
307        // will expire immediately
308        let mut processor = InputProcessor::new(
309            Duration::new(0, 0),
310            NoopAuthenticator,
311            NoopBicrypter,
312        );
313        let data = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
314        let mut encoder = Encoder::default();
315
316        // Make many small packets
317        let packets = &mut Encoder::default()
318            .encode(EncodeArgs {
319                id: 0,
320                encryption: PacketEncryption::None,
321                data: &data,
322                max_packet_size: encoder
323                    .estimate_packet_size(
324                        /* data size for final packet */ 1,
325                        PacketType::NotFinal,
326                        &NoopAuthenticator,
327                    )
328                    .unwrap()
329                    + data.len(),
330                signer: &NoopAuthenticator,
331            })
332            .unwrap();
333        assert!(packets.len() > 1, "Did not produce many small packets");
334
335        for p in packets.iter() {
336            let pdata = p.to_vec().unwrap();
337            assert!(
338                processor.process(&pdata).unwrap().is_none(),
339                "Unexpectedly got result from process with ttl of zero"
340            );
341        }
342    }
343
344    #[test]
345    fn input_processor_process_should_remove_the_decoder_packet_group_if_does_complete_data(
346    ) {
347        let mut processor = new_processor();
348        let data = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
349
350        // Make one large packet so we can complete a message
351        let p = &Encoder::default()
352            .encode(EncodeArgs {
353                id: 0,
354                encryption: PacketEncryption::None,
355                data: &data,
356                max_packet_size: 100,
357                signer: &NoopAuthenticator,
358            })
359            .unwrap()[0];
360        let pdata = p.to_vec().unwrap();
361        processor.process(&pdata).unwrap();
362
363        assert_eq!(processor.decoder.len(), 0);
364    }
365
366    #[cfg(test)]
367    mod crypt {
368        use super::*;
369        use crate::core::transport::crypto::{CryptError, Decrypter, Encrypter};
370
371        #[derive(Clone)]
372        struct BadDecrypter;
373        impl Decrypter for BadDecrypter {
374            fn decrypt(
375                &self,
376                _: &[u8],
377                _: &AssociatedData,
378            ) -> Result<Vec<u8>, CryptError> {
379                Err(CryptError::DecryptFailed(From::from("Some error")))
380            }
381        }
382        impl Encrypter for BadDecrypter {
383            fn encrypt(
384                &self,
385                _: &[u8],
386                _: &AssociatedData,
387            ) -> Result<Vec<u8>, CryptError> {
388                Err(CryptError::EncryptFailed(From::from("Some error")))
389            }
390
391            fn new_encrypt_associated_data(
392                &self,
393            ) -> crate::core::transport::crypto::AssociatedData {
394                crate::core::transport::crypto::AssociatedData::None
395            }
396        }
397
398        fn new_processor() -> InputProcessor<NoopAuthenticator, BadDecrypter> {
399            InputProcessor::new(
400                Duration::from_secs(1),
401                NoopAuthenticator,
402                BadDecrypter,
403            )
404        }
405
406        #[test]
407        fn input_processor_process_should_fail_if_unable_to_decrypt_data() {
408            let mut processor = new_processor();
409
410            let id = 0;
411            let encryption = PacketEncryption::None;
412            let data = vec![1, 2, 3];
413            let signer = NoopAuthenticator;
414            let mut encoder = Encoder::default();
415
416            // Calculate a packet size where the final packet can only
417            // fit a single byte of data to ensure that we get at least
418            // one additional packet
419            let max_packet_size = encoder
420                .estimate_packet_size(
421                    /* data size */ 1,
422                    PacketType::Final { encryption },
423                    &signer,
424                )
425                .unwrap();
426
427            // Make a new packet per element in data
428            let packets = encoder
429                .encode(EncodeArgs {
430                    id,
431                    encryption,
432                    data: &data.clone(),
433                    max_packet_size,
434                    signer: &NoopAuthenticator,
435                })
436                .unwrap();
437
438            // First N-1 packets should succeed
439            for p in packets[..packets.len() - 1].iter() {
440                let pdata = p.to_vec().unwrap();
441                assert_eq!(
442                    processor.process(&pdata).is_ok(),
443                    true,
444                    "Unexpectedly failed to receive packet"
445                );
446            }
447
448            // Final packet should trigger decrypting and it should fail
449            let final_packet = packets.last().unwrap();
450            let pdata = final_packet.to_vec().unwrap();
451            match processor.process(&pdata) {
452                Err(super::InputProcessorError::DecryptData(_)) => (),
453                Err(x) => panic!("Unexpected error: {:?}", x),
454                Ok(x) => panic!("Unexpected result: {:?}", x),
455            }
456        }
457    }
458}