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 {}