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}