1#![no_std]
2#![cfg_attr(docsrs, feature(doc_cfg))]
3#![doc = include_str!("../README.md")]
4#![doc(
5 html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/8f1a9894/logo.svg",
6 html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/8f1a9894/logo.svg"
7)]
8#![forbid(unsafe_code)]
9
10pub mod hazmat;
12
13#[cfg(feature = "rand_core")]
15mod generate;
16
17pub use hybrid_array as array;
18pub use hybrid_array::typenum;
19
20#[cfg(feature = "getrandom")]
21pub use getrandom;
22#[cfg(feature = "rand_core")]
23pub use {generate::Generate, rand_core};
24
25use core::fmt;
26use hybrid_array::{
27 Array, ArraySize,
28 typenum::{Diff, Sum, Unsigned},
29};
30
31#[cfg(feature = "rand_core")]
32use rand_core::CryptoRng;
33
34pub type Block<B> = Array<u8, <B as BlockSizeUser>::BlockSize>;
36
37pub type ParBlocks<T> = Array<Block<T>, <T as ParBlocksSizeUser>::ParBlocksSize>;
39
40pub type Output<T> = Array<u8, OutputSize<T>>;
42
43pub type OutputSize<T> = <T as OutputSizeUser>::OutputSize;
45
46pub type Key<B> = Array<u8, <B as KeySizeUser>::KeySize>;
48
49pub type Iv<B> = Array<u8, <B as IvSizeUser>::IvSize>;
51
52pub type AddBlockSize<T, B> = Sum<T, <B as BlockSizeUser>::BlockSize>;
54
55pub type SubBlockSize<T, B> = Diff<T, <B as BlockSizeUser>::BlockSize>;
57
58pub trait BlockSizeUser {
60 type BlockSize: BlockSizes;
62
63 #[inline(always)]
65 #[must_use]
66 fn block_size() -> usize {
67 Self::BlockSize::USIZE
68 }
69}
70
71impl<T: BlockSizeUser> BlockSizeUser for &T {
72 type BlockSize = T::BlockSize;
73}
74
75impl<T: BlockSizeUser> BlockSizeUser for &mut T {
76 type BlockSize = T::BlockSize;
77}
78
79pub trait BlockSizes: ArraySize + sealed::BlockSizes {}
81
82impl<T: ArraySize + sealed::BlockSizes> BlockSizes for T {}
83
84mod sealed {
85 use crate::typenum::{IsLess, NonZero, True, U256, Unsigned};
86
87 pub trait BlockSizes {}
88
89 impl<T: Unsigned> BlockSizes for T where Self: IsLess<U256, Output = True> + NonZero {}
90}
91
92pub trait ParBlocksSizeUser: BlockSizeUser {
94 type ParBlocksSize: ArraySize;
96}
97
98pub trait OutputSizeUser {
100 type OutputSize: ArraySize;
102
103 #[inline(always)]
105 #[must_use]
106 fn output_size() -> usize {
107 Self::OutputSize::USIZE
108 }
109}
110
111pub trait KeySizeUser {
115 type KeySize: ArraySize;
117
118 #[inline(always)]
120 #[must_use]
121 fn key_size() -> usize {
122 Self::KeySize::USIZE
123 }
124}
125
126pub trait IvSizeUser {
130 type IvSize: ArraySize;
132
133 #[inline(always)]
135 #[must_use]
136 fn iv_size() -> usize {
137 Self::IvSize::USIZE
138 }
139}
140
141pub trait InnerUser {
145 type Inner;
147}
148
149pub trait Reset {
151 fn reset(&mut self);
153}
154
155pub trait AlgorithmName {
157 fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result;
163}
164
165pub trait KeyExport: KeySizeUser {
167 fn to_bytes(&self) -> Key<Self>;
169}
170
171pub trait KeyInit: KeySizeUser + Sized {
173 fn new(key: &Key<Self>) -> Self;
175
176 #[inline]
182 fn new_from_slice(key: &[u8]) -> Result<Self, InvalidLength> {
183 <&Key<Self>>::try_from(key)
184 .map(Self::new)
185 .map_err(|_| InvalidLength)
186 }
187
188 #[deprecated(
196 since = "0.2.0",
197 note = "use the `Generate` trait impl on `Key` instead"
198 )]
199 #[cfg(feature = "rand_core")]
200 fn generate_key<R: CryptoRng>(rng: &mut R) -> Key<Self> {
201 Key::<Self>::generate_from_rng(rng)
202 }
203}
204
205pub trait KeyIvInit: KeySizeUser + IvSizeUser + Sized {
207 fn new(key: &Key<Self>, iv: &Iv<Self>) -> Self;
209
210 #[inline]
215 fn new_from_slices(key: &[u8], iv: &[u8]) -> Result<Self, InvalidLength> {
216 let key = <&Key<Self>>::try_from(key).map_err(|_| InvalidLength)?;
217 let iv = <&Iv<Self>>::try_from(iv).map_err(|_| InvalidLength)?;
218 Ok(Self::new(key, iv))
219 }
220
221 #[deprecated(
229 since = "0.2.0",
230 note = "use the `Generate` trait impl on `Key` instead"
231 )]
232 #[cfg(feature = "rand_core")]
233 fn generate_key<R: CryptoRng>(rng: &mut R) -> Key<Self> {
234 Key::<Self>::generate_from_rng(rng)
235 }
236
237 #[deprecated(
245 since = "0.2.0",
246 note = "use the `Generate` trait impl on `Iv` instead"
247 )]
248 #[cfg(feature = "rand_core")]
249 fn generate_iv<R: CryptoRng>(rng: &mut R) -> Iv<Self> {
250 Iv::<Self>::generate_from_rng(rng)
251 }
252
253 #[deprecated(
262 since = "0.2.0",
263 note = "use the `Generate` trait impls on `Key` and `Iv` instead"
264 )]
265 #[cfg(feature = "rand_core")]
266 fn generate_key_iv<R: CryptoRng>(rng: &mut R) -> (Key<Self>, Iv<Self>) {
267 let key = Key::<Self>::generate_from_rng(rng);
268 let iv = Iv::<Self>::generate_from_rng(rng);
269 (key, iv)
270 }
271}
272
273pub trait TryKeyInit: KeySizeUser + Sized {
275 fn new(key: &Key<Self>) -> Result<Self, InvalidKey>;
280
281 #[inline]
286 fn new_from_slice(key: &[u8]) -> Result<Self, InvalidKey> {
287 <&Key<Self>>::try_from(key)
288 .map_err(|_| InvalidKey)
289 .and_then(Self::new)
290 }
291}
292
293pub trait InnerInit: InnerUser + Sized {
297 fn inner_init(inner: Self::Inner) -> Self;
299}
300
301pub trait InnerIvInit: InnerUser + IvSizeUser + Sized {
306 fn inner_iv_init(inner: Self::Inner, iv: &Iv<Self>) -> Self;
308
309 #[inline]
314 fn inner_iv_slice_init(inner: Self::Inner, iv: &[u8]) -> Result<Self, InvalidLength> {
315 let iv = <&Iv<Self>>::try_from(iv).map_err(|_| InvalidLength)?;
316 Ok(Self::inner_iv_init(inner, iv))
317 }
318}
319
320pub trait IvState: IvSizeUser {
322 fn iv_state(&self) -> Iv<Self>;
324}
325
326impl<T> KeySizeUser for T
327where
328 T: InnerUser,
329 T::Inner: KeySizeUser,
330{
331 type KeySize = <T::Inner as KeySizeUser>::KeySize;
332}
333
334impl<T> KeyIvInit for T
335where
336 T: InnerIvInit,
337 T::Inner: KeyInit,
338{
339 #[inline]
340 fn new(key: &Key<Self>, iv: &Iv<Self>) -> Self {
341 Self::inner_iv_init(T::Inner::new(key), iv)
342 }
343
344 #[inline]
345 fn new_from_slices(key: &[u8], iv: &[u8]) -> Result<Self, InvalidLength> {
346 T::Inner::new_from_slice(key).and_then(|i| T::inner_iv_slice_init(i, iv))
347 }
348}
349
350impl<T> KeyInit for T
351where
352 T: InnerInit,
353 T::Inner: KeyInit,
354{
355 #[inline]
356 fn new(key: &Key<Self>) -> Self {
357 Self::inner_init(T::Inner::new(key))
358 }
359
360 #[inline]
361 fn new_from_slice(key: &[u8]) -> Result<Self, InvalidLength> {
362 T::Inner::new_from_slice(key)
363 .map_err(|_| InvalidLength)
364 .map(Self::inner_init)
365 }
366}
367
368#[derive(Copy, Clone, Eq, PartialEq, Debug)]
371pub struct InvalidKey;
372
373impl fmt::Display for InvalidKey {
374 #[inline]
375 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
376 f.write_str("InvalidKey")
377 }
378}
379
380impl core::error::Error for InvalidKey {}
381
382#[derive(Copy, Clone, Eq, PartialEq, Debug)]
386pub struct InvalidLength;
387
388impl fmt::Display for InvalidLength {
389 #[inline]
390 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
391 f.write_str("Invalid Length")
392 }
393}
394
395impl core::error::Error for InvalidLength {}