embedded_chacha/
lib.rs

1#![no_std]
2
3use core::slice;
4
5use chacha20::{
6    ChaCha20,
7    cipher::{KeyIvInit, StreamCipher, StreamCipherSeek, generic_array::GenericArray},
8};
9#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash, Default)]
10pub struct ChaCha<T, C = ChaCha20> {
11    pub wrapped: T,
12    pub read: C,
13    pub write: C,
14}
15impl<T: embedded_io::ErrorType, C> embedded_io::ErrorType for ChaCha<T, C> {
16    type Error = T::Error;
17}
18impl<T: embedded_io::Read, C: StreamCipher> embedded_io::Read for ChaCha<T, C> {
19    fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
20        let a = self.wrapped.read(buf)?;
21        self.read.apply_keystream(&mut buf[..a]);
22        Ok(a)
23    }
24}
25impl<T: embedded_io_async::Read, C: StreamCipher> embedded_io_async::Read for ChaCha<T, C> {
26    async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
27        let a = self.wrapped.read(buf).await?;
28        self.read.apply_keystream(&mut buf[..a]);
29        Ok(a)
30    }
31}
32impl<T: embedded_io::Write, C: StreamCipherSeek + StreamCipher> embedded_io::Write
33    for ChaCha<T, C>
34{
35    fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
36        let mut i = 0;
37        for b in buf.iter() {
38            let mut c = 0u8;
39            let _ = self
40                .write
41                .apply_keystream_b2b(slice::from_ref(b), slice::from_mut(&mut c));
42            let d = self.wrapped.write(slice::from_ref(&c))?;
43            if d == 0 {
44                let cur: usize = self.write.current_pos::<usize>() - 1;
45                self.write.seek(cur);
46                return Ok(i);
47            }
48        }
49        Ok(i)
50    }
51
52    fn flush(&mut self) -> Result<(), Self::Error> {
53        self.wrapped.flush()
54    }
55    fn write_all(&mut self, mut buf: &[u8]) -> Result<(), Self::Error> {
56        for b in buf.iter() {
57            let mut c = 0u8;
58            let _ = self
59                .write
60                .apply_keystream_b2b(slice::from_ref(b), slice::from_mut(&mut c));
61            self.wrapped.write_all(slice::from_ref(&c))?;
62        }
63        Ok(())
64    }
65}
66impl<T: embedded_io_async::Write, C: StreamCipherSeek + StreamCipher> embedded_io_async::Write
67    for ChaCha<T, C>
68{
69    async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
70        let mut i = 0;
71        for b in buf.iter() {
72            let mut c = 0u8;
73            let _ = self
74                .write
75                .apply_keystream_b2b(slice::from_ref(b), slice::from_mut(&mut c));
76            let d = self.wrapped.write(slice::from_ref(&c)).await?;
77            if d == 0 {
78                let cur: usize = self.write.current_pos::<usize>() - 1;
79                self.write.seek(cur);
80                return Ok(i);
81            }
82        }
83        Ok(i)
84    }
85
86    async fn flush(&mut self) -> Result<(), Self::Error> {
87        self.wrapped.flush().await
88    }
89
90    async fn write_all(&mut self, mut buf: &[u8]) -> Result<(), Self::Error> {
91        for b in buf.iter() {
92            let mut c = 0u8;
93            let _ = self
94                .write
95                .apply_keystream_b2b(slice::from_ref(b), slice::from_mut(&mut c));
96            self.wrapped.write_all(slice::from_ref(&c)).await?;
97        }
98        Ok(())
99    }
100}
101impl<T, C: KeyIvInit> ChaCha<T, C> {
102    pub fn new(
103        wrapped: T,
104        key: &GenericArray<u8, C::KeySize>,
105        iv: GenericArray<u8, C::IvSize>,
106    ) -> Self {
107        let mut iv2 = iv.clone();
108        for i in iv2.iter_mut() {
109            *i ^= 0xff;
110        }
111        Self {
112            wrapped,
113            read: C::new(key, &iv),
114            write: C::new(key, &iv2),
115        }
116    }
117}