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, missing_debug_implementations)]
11
12pub mod hazmat;
14
15#[cfg(feature = "rand_core")]
17mod generate;
18
19pub use hybrid_array as array;
20pub use hybrid_array::typenum;
21
22#[cfg(feature = "getrandom")]
23pub use getrandom;
24#[cfg(feature = "rand_core")]
25pub use {generate::Generate, rand_core};
26
27use core::fmt;
28use hybrid_array::{
29 Array, ArraySize,
30 typenum::{Diff, Sum, Unsigned},
31};
32
33#[cfg(feature = "rand_core")]
34use rand_core::CryptoRng;
35
36pub type Block<B> = Array<u8, <B as BlockSizeUser>::BlockSize>;
38
39pub type ParBlocks<T> = Array<Block<T>, <T as ParBlocksSizeUser>::ParBlocksSize>;
41
42pub type Output<T> = Array<u8, OutputSize<T>>;
44
45pub type OutputSize<T> = <T as OutputSizeUser>::OutputSize;
47
48pub type Key<B> = Array<u8, <B as KeySizeUser>::KeySize>;
50
51pub type Iv<B> = Array<u8, <B as IvSizeUser>::IvSize>;
53
54pub type AddBlockSize<T, B> = Sum<T, <B as BlockSizeUser>::BlockSize>;
56
57pub type SubBlockSize<T, B> = Diff<T, <B as BlockSizeUser>::BlockSize>;
59
60pub trait BlockSizeUser {
62 type BlockSize: BlockSizes;
64
65 #[inline(always)]
67 fn block_size() -> usize {
68 Self::BlockSize::USIZE
69 }
70}
71
72impl<T: BlockSizeUser> BlockSizeUser for &T {
73 type BlockSize = T::BlockSize;
74}
75
76impl<T: BlockSizeUser> BlockSizeUser for &mut T {
77 type BlockSize = T::BlockSize;
78}
79
80pub trait BlockSizes: ArraySize + sealed::BlockSizes {}
82
83impl<T: ArraySize + sealed::BlockSizes> BlockSizes for T {}
84
85mod sealed {
86 use crate::typenum::{IsLess, NonZero, True, U256, Unsigned};
87
88 pub trait BlockSizes {}
89
90 impl<T: Unsigned> BlockSizes for T where Self: IsLess<U256, Output = True> + NonZero {}
91}
92
93pub trait ParBlocksSizeUser: BlockSizeUser {
95 type ParBlocksSize: ArraySize;
97}
98
99pub trait OutputSizeUser {
101 type OutputSize: ArraySize;
103
104 #[inline(always)]
106 fn output_size() -> usize {
107 Self::OutputSize::USIZE
108 }
109}
110
111pub trait KeySizeUser {
115 type KeySize: ArraySize;
117
118 #[inline(always)]
120 fn key_size() -> usize {
121 Self::KeySize::USIZE
122 }
123}
124
125pub trait IvSizeUser {
129 type IvSize: ArraySize;
131
132 #[inline(always)]
134 fn iv_size() -> usize {
135 Self::IvSize::USIZE
136 }
137}
138
139pub trait InnerUser {
143 type Inner;
145}
146
147pub trait Reset {
149 fn reset(&mut self);
151}
152
153pub trait AlgorithmName {
155 fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result;
157}
158
159pub trait KeyExport: KeySizeUser {
161 fn to_bytes(&self) -> Key<Self>;
163}
164
165pub trait KeyInit: KeySizeUser + Sized {
167 fn new(key: &Key<Self>) -> Self;
169
170 #[inline]
172 fn new_from_slice(key: &[u8]) -> Result<Self, InvalidLength> {
173 <&Key<Self>>::try_from(key)
174 .map(Self::new)
175 .map_err(|_| InvalidLength)
176 }
177
178 #[deprecated(
186 since = "0.2.0",
187 note = "use the `Generate` trait impl on `Key` instead"
188 )]
189 #[cfg(feature = "rand_core")]
190 fn generate_key<R: CryptoRng>(rng: &mut R) -> Key<Self> {
191 Key::<Self>::generate_from_rng(rng)
192 }
193}
194
195pub trait KeyIvInit: KeySizeUser + IvSizeUser + Sized {
197 fn new(key: &Key<Self>, iv: &Iv<Self>) -> Self;
199
200 #[inline]
202 fn new_from_slices(key: &[u8], iv: &[u8]) -> Result<Self, InvalidLength> {
203 let key = <&Key<Self>>::try_from(key).map_err(|_| InvalidLength)?;
204 let iv = <&Iv<Self>>::try_from(iv).map_err(|_| InvalidLength)?;
205 Ok(Self::new(key, iv))
206 }
207
208 #[deprecated(
216 since = "0.2.0",
217 note = "use the `Generate` trait impl on `Key` instead"
218 )]
219 #[cfg(feature = "rand_core")]
220 fn generate_key<R: CryptoRng>(rng: &mut R) -> Key<Self> {
221 Key::<Self>::generate_from_rng(rng)
222 }
223
224 #[deprecated(
232 since = "0.2.0",
233 note = "use the `Generate` trait impl on `Iv` instead"
234 )]
235 #[cfg(feature = "rand_core")]
236 fn generate_iv<R: CryptoRng>(rng: &mut R) -> Iv<Self> {
237 Iv::<Self>::generate_from_rng(rng)
238 }
239
240 #[deprecated(
249 since = "0.2.0",
250 note = "use the `Generate` trait impls on `Key` and `Iv` instead"
251 )]
252 #[cfg(feature = "rand_core")]
253 fn generate_key_iv<R: CryptoRng>(rng: &mut R) -> (Key<Self>, Iv<Self>) {
254 let key = Key::<Self>::generate_from_rng(rng);
255 let iv = Iv::<Self>::generate_from_rng(rng);
256 (key, iv)
257 }
258}
259
260pub trait TryKeyInit: KeySizeUser + Sized {
262 fn new(key: &Key<Self>) -> Result<Self, InvalidKey>;
267
268 #[inline]
274 fn new_from_slice(key: &[u8]) -> Result<Self, InvalidKey> {
275 <&Key<Self>>::try_from(key)
276 .map_err(|_| InvalidKey)
277 .and_then(Self::new)
278 }
279}
280
281pub trait InnerInit: InnerUser + Sized {
285 fn inner_init(inner: Self::Inner) -> Self;
287}
288
289pub trait InnerIvInit: InnerUser + IvSizeUser + Sized {
294 fn inner_iv_init(inner: Self::Inner, iv: &Iv<Self>) -> Self;
296
297 #[inline]
299 fn inner_iv_slice_init(inner: Self::Inner, iv: &[u8]) -> Result<Self, InvalidLength> {
300 let iv = <&Iv<Self>>::try_from(iv).map_err(|_| InvalidLength)?;
301 Ok(Self::inner_iv_init(inner, iv))
302 }
303}
304
305pub trait IvState: IvSizeUser {
307 fn iv_state(&self) -> Iv<Self>;
309}
310
311impl<T> KeySizeUser for T
312where
313 T: InnerUser,
314 T::Inner: KeySizeUser,
315{
316 type KeySize = <T::Inner as KeySizeUser>::KeySize;
317}
318
319impl<T> KeyIvInit for T
320where
321 T: InnerIvInit,
322 T::Inner: KeyInit,
323{
324 #[inline]
325 fn new(key: &Key<Self>, iv: &Iv<Self>) -> Self {
326 Self::inner_iv_init(T::Inner::new(key), iv)
327 }
328
329 #[inline]
330 fn new_from_slices(key: &[u8], iv: &[u8]) -> Result<Self, InvalidLength> {
331 T::Inner::new_from_slice(key).and_then(|i| T::inner_iv_slice_init(i, iv))
332 }
333}
334
335impl<T> KeyInit for T
336where
337 T: InnerInit,
338 T::Inner: KeyInit,
339{
340 #[inline]
341 fn new(key: &Key<Self>) -> Self {
342 Self::inner_init(T::Inner::new(key))
343 }
344
345 #[inline]
346 fn new_from_slice(key: &[u8]) -> Result<Self, InvalidLength> {
347 T::Inner::new_from_slice(key)
348 .map_err(|_| InvalidLength)
349 .map(Self::inner_init)
350 }
351}
352
353#[derive(Copy, Clone, Eq, PartialEq, Debug)]
379pub struct InvalidKey;
380
381impl fmt::Display for InvalidKey {
382 #[inline]
383 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
384 f.write_str("InvalidKey")
385 }
386}
387
388impl core::error::Error for InvalidKey {}
389
390#[derive(Copy, Clone, Eq, PartialEq, Debug)]
394pub struct InvalidLength;
395
396impl fmt::Display for InvalidLength {
397 #[inline]
398 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
399 f.write_str("Invalid Length")
400 }
401}
402
403impl core::error::Error for InvalidLength {}