/rust/registry/src/index.crates.io-1949cf8c6b5b557f/cipher-0.3.0/src/stream.rs
Line | Count | Source |
1 | | //! Traits which define functionality of stream ciphers. |
2 | | //! |
3 | | //! See [RustCrypto/stream-ciphers](https://github.com/RustCrypto/stream-ciphers) |
4 | | //! for ciphers implementation. |
5 | | |
6 | | use crate::errors::{LoopError, OverflowError}; |
7 | | use core::convert::{TryFrom, TryInto}; |
8 | | |
9 | | /// Synchronous stream cipher core trait. |
10 | | pub trait StreamCipher { |
11 | | /// Apply keystream to the data. |
12 | | /// |
13 | | /// It will XOR generated keystream with the data, which can be both |
14 | | /// encryption and decryption. |
15 | | /// |
16 | | /// # Panics |
17 | | /// If end of the keystream will be reached with the given data length, |
18 | | /// method will panic without modifying the provided `data`. |
19 | | #[inline] |
20 | 3.59k | fn apply_keystream(&mut self, data: &mut [u8]) { |
21 | 3.59k | self.try_apply_keystream(data).unwrap(); |
22 | 3.59k | } |
23 | | |
24 | | /// Apply keystream to the data, but return an error if end of a keystream |
25 | | /// will be reached. |
26 | | /// |
27 | | /// If end of the keystream will be achieved with the given data length, |
28 | | /// method will return `Err(LoopError)` without modifying provided `data`. |
29 | | fn try_apply_keystream(&mut self, data: &mut [u8]) -> Result<(), LoopError>; |
30 | | } |
31 | | |
32 | | /// Trait for seekable stream ciphers. |
33 | | /// |
34 | | /// Methods of this trait are generic over the [`SeekNum`] trait, which is |
35 | | /// implemented for primitive numeric types, i.e.: `i/u8`, `i/u16`, `i/u32`, |
36 | | /// `i/u64`, `i/u128`, and `i/usize`. |
37 | | pub trait StreamCipherSeek { |
38 | | /// Try to get current keystream position |
39 | | /// |
40 | | /// Returns [`LoopError`] if position can not be represented by type `T` |
41 | | fn try_current_pos<T: SeekNum>(&self) -> Result<T, OverflowError>; |
42 | | |
43 | | /// Try to seek to the given position |
44 | | /// |
45 | | /// Returns [`LoopError`] if provided position value is bigger than |
46 | | /// keystream length. |
47 | | fn try_seek<T: SeekNum>(&mut self, pos: T) -> Result<(), LoopError>; |
48 | | |
49 | | /// Get current keystream position |
50 | | /// |
51 | | /// # Panics |
52 | | /// If position can not be represented by type `T` |
53 | | fn current_pos<T: SeekNum>(&self) -> T { |
54 | | self.try_current_pos().unwrap() |
55 | | } |
56 | | |
57 | | /// Seek to the given position |
58 | | /// |
59 | | /// # Panics |
60 | | /// If provided position value is bigger than keystream leangth |
61 | | fn seek<T: SeekNum>(&mut self, pos: T) { |
62 | | self.try_seek(pos).unwrap() |
63 | | } |
64 | | } |
65 | | |
66 | | /// Asynchronous stream cipher core trait. |
67 | | pub trait AsyncStreamCipher { |
68 | | /// Encrypt data in place. |
69 | | fn encrypt(&mut self, data: &mut [u8]); |
70 | | |
71 | | /// Decrypt data in place. |
72 | | fn decrypt(&mut self, data: &mut [u8]); |
73 | | } |
74 | | |
75 | | impl<C: StreamCipher> StreamCipher for &mut C { |
76 | | #[inline] |
77 | | fn apply_keystream(&mut self, data: &mut [u8]) { |
78 | | C::apply_keystream(self, data); |
79 | | } |
80 | | |
81 | | #[inline] |
82 | | fn try_apply_keystream(&mut self, data: &mut [u8]) -> Result<(), LoopError> { |
83 | | C::try_apply_keystream(self, data) |
84 | | } |
85 | | } |
86 | | |
87 | | /// Trait implemented for numeric types which can be used with the |
88 | | /// [`StreamCipherSeek`] trait. |
89 | | /// |
90 | | /// This trait is implemented for primitive numeric types, i.e. `i/u8`, |
91 | | /// `u16`, `u32`, `u64`, `u128`, `usize`, and `i32`. It is not intended |
92 | | /// to be implemented in third-party crates. |
93 | | #[rustfmt::skip] |
94 | | pub trait SeekNum: |
95 | | Sized |
96 | | + TryInto<u8> + TryFrom<u8> + TryInto<i8> + TryFrom<i8> |
97 | | + TryInto<u16> + TryFrom<u16> + TryInto<i16> + TryFrom<i16> |
98 | | + TryInto<u32> + TryFrom<u32> + TryInto<i32> + TryFrom<i32> |
99 | | + TryInto<u64> + TryFrom<u64> + TryInto<i64> + TryFrom<i64> |
100 | | + TryInto<u128> + TryFrom<u128> + TryInto<i128> + TryFrom<i128> |
101 | | + TryInto<usize> + TryFrom<usize> + TryInto<isize> + TryFrom<isize> |
102 | | { |
103 | | /// Try to get position for block number `block`, byte position inside |
104 | | /// block `byte`, and block size `bs`. |
105 | | fn from_block_byte<T: SeekNum>(block: T, byte: u8, bs: u8) -> Result<Self, OverflowError>; |
106 | | |
107 | | /// Try to get block number and bytes position for given block size `bs`. |
108 | | fn to_block_byte<T: SeekNum>(self, bs: u8) -> Result<(T, u8), OverflowError>; |
109 | | } |
110 | | |
111 | | macro_rules! impl_seek_num { |
112 | | {$($t:ty )*} => { |
113 | | $( |
114 | | impl SeekNum for $t { |
115 | | fn from_block_byte<T: TryInto<Self>>(block: T, byte: u8, bs: u8) -> Result<Self, OverflowError> { |
116 | | debug_assert!(byte < bs); |
117 | | let block = block.try_into().map_err(|_| OverflowError)?; |
118 | | let pos = block.checked_mul(bs as Self).ok_or(OverflowError)? + (byte as Self); |
119 | | Ok(pos) |
120 | | } |
121 | | |
122 | | fn to_block_byte<T: TryFrom<Self>>(self, bs: u8) -> Result<(T, u8), OverflowError> { |
123 | | let bs = bs as Self; |
124 | | let byte = self % bs; |
125 | | let block = T::try_from(self/bs).map_err(|_| OverflowError)?; |
126 | | Ok((block, byte as u8)) |
127 | | } |
128 | | } |
129 | | )* |
130 | | }; |
131 | | } |
132 | | |
133 | | impl_seek_num! { u8 u16 u32 u64 u128 usize i32 } |