1#![no_std]
4#![cfg_attr(docsrs, feature(doc_cfg))]
5#![doc(
6    html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg",
7    html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg"
8)]
9#![forbid(unsafe_code)]
10#![warn(missing_docs, rust_2018_idioms)]
11
12#[cfg(feature = "std")]
13extern crate std;
14
15#[cfg(feature = "rand_core")]
16pub use rand_core;
17
18pub use generic_array;
19pub use generic_array::typenum;
20
21use core::fmt;
22use generic_array::{typenum::Unsigned, ArrayLength, GenericArray};
23#[cfg(feature = "rand_core")]
24use rand_core::{CryptoRng, RngCore};
25
26pub type Block<B> = GenericArray<u8, <B as BlockSizeUser>::BlockSize>;
28
29pub type ParBlocks<T> = GenericArray<Block<T>, <T as ParBlocksSizeUser>::ParBlocksSize>;
31
32pub type Output<T> = GenericArray<u8, <T as OutputSizeUser>::OutputSize>;
34
35pub type Key<B> = GenericArray<u8, <B as KeySizeUser>::KeySize>;
37
38pub type Iv<B> = GenericArray<u8, <B as IvSizeUser>::IvSize>;
40
41pub trait BlockSizeUser {
43    type BlockSize: ArrayLength<u8> + 'static;
45
46    fn block_size() -> usize {
48        Self::BlockSize::USIZE
49    }
50}
51
52impl<T: BlockSizeUser> BlockSizeUser for &T {
53    type BlockSize = T::BlockSize;
54}
55
56impl<T: BlockSizeUser> BlockSizeUser for &mut T {
57    type BlockSize = T::BlockSize;
58}
59
60pub trait ParBlocksSizeUser: BlockSizeUser {
62    type ParBlocksSize: ArrayLength<Block<Self>>;
64}
65
66pub trait OutputSizeUser {
68    type OutputSize: ArrayLength<u8> + 'static;
70
71    fn output_size() -> usize {
73        Self::OutputSize::USIZE
74    }
75}
76
77pub trait KeySizeUser {
81    type KeySize: ArrayLength<u8> + 'static;
83
84    fn key_size() -> usize {
86        Self::KeySize::USIZE
87    }
88}
89
90pub trait IvSizeUser {
94    type IvSize: ArrayLength<u8> + 'static;
96
97    fn iv_size() -> usize {
99        Self::IvSize::USIZE
100    }
101}
102
103pub trait InnerUser {
107    type Inner;
109}
110
111pub trait Reset {
113    fn reset(&mut self);
115}
116
117pub trait AlgorithmName {
119    fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result;
121}
122
123pub trait KeyInit: KeySizeUser + Sized {
125    fn new(key: &Key<Self>) -> Self;
127
128    fn new_from_slice(key: &[u8]) -> Result<Self, InvalidLength> {
130        if key.len() != Self::KeySize::to_usize() {
131            Err(InvalidLength)
132        } else {
133            Ok(Self::new(Key::<Self>::from_slice(key)))
134        }
135    }
136
137    #[cfg(feature = "rand_core")]
139    #[cfg_attr(docsrs, doc(cfg(feature = "rand_core")))]
140    #[inline]
141    fn generate_key(mut rng: impl CryptoRng + RngCore) -> Key<Self> {
142        let mut key = Key::<Self>::default();
143        rng.fill_bytes(&mut key);
144        key
145    }
146}
147
148pub trait KeyIvInit: KeySizeUser + IvSizeUser + Sized {
150    fn new(key: &Key<Self>, iv: &Iv<Self>) -> Self;
152
153    #[inline]
155    fn new_from_slices(key: &[u8], iv: &[u8]) -> Result<Self, InvalidLength> {
156        let key_len = Self::KeySize::USIZE;
157        let iv_len = Self::IvSize::USIZE;
158        if key.len() != key_len || iv.len() != iv_len {
159            Err(InvalidLength)
160        } else {
161            Ok(Self::new(
162                Key::<Self>::from_slice(key),
163                Iv::<Self>::from_slice(iv),
164            ))
165        }
166    }
167
168    #[cfg(feature = "rand_core")]
170    #[cfg_attr(docsrs, doc(cfg(feature = "rand_core")))]
171    #[inline]
172    fn generate_key(mut rng: impl CryptoRng + RngCore) -> Key<Self> {
173        let mut key = Key::<Self>::default();
174        rng.fill_bytes(&mut key);
175        key
176    }
177
178    #[cfg(feature = "rand_core")]
180    #[cfg_attr(docsrs, doc(cfg(feature = "rand_core")))]
181    #[inline]
182    fn generate_iv(mut rng: impl CryptoRng + RngCore) -> Iv<Self> {
183        let mut iv = Iv::<Self>::default();
184        rng.fill_bytes(&mut iv);
185        iv
186    }
187
188    #[cfg(feature = "rand_core")]
190    #[cfg_attr(docsrs, doc(cfg(feature = "rand_core")))]
191    #[inline]
192    fn generate_key_iv(mut rng: impl CryptoRng + RngCore) -> (Key<Self>, Iv<Self>) {
193        (Self::generate_key(&mut rng), Self::generate_iv(&mut rng))
194    }
195}
196
197pub trait InnerInit: InnerUser + Sized {
201    fn inner_init(inner: Self::Inner) -> Self;
203}
204
205pub trait InnerIvInit: InnerUser + IvSizeUser + Sized {
210    fn inner_iv_init(inner: Self::Inner, iv: &Iv<Self>) -> Self;
212
213    fn inner_iv_slice_init(inner: Self::Inner, iv: &[u8]) -> Result<Self, InvalidLength> {
215        if iv.len() != Self::IvSize::to_usize() {
216            Err(InvalidLength)
217        } else {
218            Ok(Self::inner_iv_init(inner, Iv::<Self>::from_slice(iv)))
219        }
220    }
221
222    #[cfg(feature = "rand_core")]
224    #[cfg_attr(docsrs, doc(cfg(feature = "rand_core")))]
225    #[inline]
226    fn generate_iv(mut rng: impl CryptoRng + RngCore) -> Iv<Self> {
227        let mut iv = Iv::<Self>::default();
228        rng.fill_bytes(&mut iv);
229        iv
230    }
231}
232
233impl<T> KeySizeUser for T
234where
235    T: InnerUser,
236    T::Inner: KeySizeUser,
237{
238    type KeySize = <T::Inner as KeySizeUser>::KeySize;
239}
240
241impl<T> KeyIvInit for T
242where
243    T: InnerIvInit,
244    T::Inner: KeyInit,
245{
246    #[inline]
247    fn new(key: &Key<Self>, iv: &Iv<Self>) -> Self {
248        Self::inner_iv_init(T::Inner::new(key), iv)
249    }
250
251    #[inline]
252    fn new_from_slices(key: &[u8], iv: &[u8]) -> Result<Self, InvalidLength> {
253        T::Inner::new_from_slice(key).and_then(|i| T::inner_iv_slice_init(i, iv))
254    }
255}
256
257impl<T> KeyInit for T
258where
259    T: InnerInit,
260    T::Inner: KeyInit,
261{
262    #[inline]
263    fn new(key: &Key<Self>) -> Self {
264        Self::inner_init(T::Inner::new(key))
265    }
266
267    #[inline]
268    fn new_from_slice(key: &[u8]) -> Result<Self, InvalidLength> {
269        T::Inner::new_from_slice(key)
270            .map_err(|_| InvalidLength)
271            .map(Self::inner_init)
272    }
273}
274
275#[derive(Copy, Clone, Eq, PartialEq, Debug)]
302pub struct InvalidLength;
303
304impl fmt::Display for InvalidLength {
305    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
306        f.write_str("Invalid Length")
307    }
308}
309
310#[cfg(feature = "std")]
311impl std::error::Error for InvalidLength {}