crypto_common/
lib.rs

1//! Common cryptographic traits.
2
3#![no_std]
4#![cfg_attr(docsrs, feature(doc_auto_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
12/// Hazardous materials.
13pub mod hazmat;
14
15#[cfg(feature = "rand_core")]
16pub use rand_core;
17
18pub use hybrid_array as array;
19pub use hybrid_array::typenum;
20
21use core::fmt;
22use hybrid_array::{
23    Array, ArraySize,
24    typenum::{Diff, Sum, Unsigned},
25};
26
27#[cfg(feature = "rand_core")]
28use rand_core::{CryptoRng, TryCryptoRng};
29#[cfg(feature = "os_rng")]
30use rand_core::{OsError, OsRng, TryRngCore};
31
32/// Block on which [`BlockSizeUser`] implementors operate.
33pub type Block<B> = Array<u8, <B as BlockSizeUser>::BlockSize>;
34
35/// Parallel blocks on which [`ParBlocksSizeUser`] implementors operate.
36pub type ParBlocks<T> = Array<Block<T>, <T as ParBlocksSizeUser>::ParBlocksSize>;
37
38/// Output array of [`OutputSizeUser`] implementors.
39pub type Output<T> = Array<u8, OutputSize<T>>;
40
41/// Alias for the output size of [`OutputSizeUser`] implementors.
42pub type OutputSize<T> = <T as OutputSizeUser>::OutputSize;
43
44/// Key used by [`KeySizeUser`] implementors.
45pub type Key<B> = Array<u8, <B as KeySizeUser>::KeySize>;
46
47/// Initialization vector (nonce) used by [`IvSizeUser`] implementors.
48pub type Iv<B> = Array<u8, <B as IvSizeUser>::IvSize>;
49
50/// Alias for `AddBlockSize<A, B> = Sum<T, B::BlockSize>`
51pub type AddBlockSize<T, B> = Sum<T, <B as BlockSizeUser>::BlockSize>;
52
53/// Alias for `SubBlockSize<A, B> = Diff<T, B::BlockSize>`
54pub type SubBlockSize<T, B> = Diff<T, <B as BlockSizeUser>::BlockSize>;
55
56/// Types which process data in blocks.
57pub trait BlockSizeUser {
58    /// Size of the block in bytes.
59    type BlockSize: BlockSizes;
60
61    /// Return block size in bytes.
62    #[inline(always)]
63    fn block_size() -> usize {
64        Self::BlockSize::USIZE
65    }
66}
67
68impl<T: BlockSizeUser> BlockSizeUser for &T {
69    type BlockSize = T::BlockSize;
70}
71
72impl<T: BlockSizeUser> BlockSizeUser for &mut T {
73    type BlockSize = T::BlockSize;
74}
75
76/// Trait implemented for supported block sizes, i.e. for types from `U1` to `U255`.
77pub trait BlockSizes: ArraySize + sealed::BlockSizes {}
78
79impl<T: ArraySize + sealed::BlockSizes> BlockSizes for T {}
80
81mod sealed {
82    use crate::typenum::{IsLess, NonZero, True, U256, Unsigned};
83
84    pub trait BlockSizes {}
85
86    impl<T: Unsigned> BlockSizes for T where Self: IsLess<U256, Output = True> + NonZero {}
87}
88
89/// Types which can process blocks in parallel.
90pub trait ParBlocksSizeUser: BlockSizeUser {
91    /// Number of blocks which can be processed in parallel.
92    type ParBlocksSize: ArraySize;
93}
94
95/// Types which return data with the given size.
96pub trait OutputSizeUser {
97    /// Size of the output in bytes.
98    type OutputSize: ArraySize;
99
100    /// Return output size in bytes.
101    #[inline(always)]
102    fn output_size() -> usize {
103        Self::OutputSize::USIZE
104    }
105}
106
107/// Types which use key for initialization.
108///
109/// Generally it's used indirectly via [`KeyInit`] or [`KeyIvInit`].
110pub trait KeySizeUser {
111    /// Key size in bytes.
112    type KeySize: ArraySize;
113
114    /// Return key size in bytes.
115    #[inline(always)]
116    fn key_size() -> usize {
117        Self::KeySize::USIZE
118    }
119}
120
121/// Types which use initialization vector (nonce) for initialization.
122///
123/// Generally it's used indirectly via [`KeyIvInit`] or [`InnerIvInit`].
124pub trait IvSizeUser {
125    /// Initialization vector size in bytes.
126    type IvSize: ArraySize;
127
128    /// Return IV size in bytes.
129    #[inline(always)]
130    fn iv_size() -> usize {
131        Self::IvSize::USIZE
132    }
133}
134
135/// Types which use another type for initialization.
136///
137/// Generally it's used indirectly via [`InnerInit`] or [`InnerIvInit`].
138pub trait InnerUser {
139    /// Inner type.
140    type Inner;
141}
142
143/// Resettable types.
144pub trait Reset {
145    /// Reset state to its initial value.
146    fn reset(&mut self);
147}
148
149/// Trait which stores algorithm name constant, used in `Debug` implementations.
150pub trait AlgorithmName {
151    /// Write algorithm name into `f`.
152    fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result;
153}
154
155/// Types which can be initialized from key.
156pub trait KeyInit: KeySizeUser + Sized {
157    /// Create new value from fixed size key.
158    fn new(key: &Key<Self>) -> Self;
159
160    /// Check if the key might be considered weak.
161    #[inline]
162    fn weak_key_test(_key: &Key<Self>) -> Result<(), WeakKeyError> {
163        Ok(())
164    }
165
166    /// Create new value from fixed size key after checking it for weakness.
167    #[inline]
168    fn new_checked(key: &Key<Self>) -> Result<Self, WeakKeyError> {
169        Self::weak_key_test(key)?;
170        Ok(Self::new(key))
171    }
172
173    /// Create new value from variable size key.
174    #[inline]
175    fn new_from_slice(key: &[u8]) -> Result<Self, InvalidLength> {
176        <&Key<Self>>::try_from(key)
177            .map(Self::new)
178            .map_err(|_| InvalidLength)
179    }
180
181    /// Generate random key using the operating system's secure RNG.
182    #[cfg(feature = "os_rng")]
183    #[inline]
184    fn generate_key() -> Result<Key<Self>, OsError> {
185        let mut key = Key::<Self>::default();
186        OsRng.try_fill_bytes(&mut key)?;
187        Ok(key)
188    }
189
190    /// Generate random key using the provided [`CryptoRng`].
191    #[cfg(feature = "rand_core")]
192    #[inline]
193    fn generate_key_with_rng<R: CryptoRng + ?Sized>(rng: &mut R) -> Key<Self> {
194        let mut key = Key::<Self>::default();
195        rng.fill_bytes(&mut key);
196        key
197    }
198
199    /// Generate random key using the provided [`TryCryptoRng`].
200    #[cfg(feature = "rand_core")]
201    #[inline]
202    fn try_generate_key_with_rng<R: TryCryptoRng + ?Sized>(
203        rng: &mut R,
204    ) -> Result<Key<Self>, R::Error> {
205        let mut key = Key::<Self>::default();
206        rng.try_fill_bytes(&mut key)?;
207        Ok(key)
208    }
209}
210
211/// Types which can be initialized from key and initialization vector (nonce).
212pub trait KeyIvInit: KeySizeUser + IvSizeUser + Sized {
213    /// Create new value from fixed length key and nonce.
214    fn new(key: &Key<Self>, iv: &Iv<Self>) -> Self;
215
216    /// Check if the key might be considered weak.
217    #[inline]
218    fn weak_key_test(_key: &Key<Self>) -> Result<(), WeakKeyError> {
219        Ok(())
220    }
221
222    /// Create new value from fixed length key and nonce after checking the key for weakness.
223    #[inline]
224    fn new_checked(key: &Key<Self>, iv: &Iv<Self>) -> Result<Self, WeakKeyError> {
225        Self::weak_key_test(key)?;
226        Ok(Self::new(key, iv))
227    }
228
229    /// Create new value from variable length key and nonce.
230    #[inline]
231    fn new_from_slices(key: &[u8], iv: &[u8]) -> Result<Self, InvalidLength> {
232        let key = <&Key<Self>>::try_from(key).map_err(|_| InvalidLength)?;
233        let iv = <&Iv<Self>>::try_from(iv).map_err(|_| InvalidLength)?;
234        Ok(Self::new(key, iv))
235    }
236
237    /// Generate random key using the operating system's secure RNG.
238    #[cfg(feature = "os_rng")]
239    #[inline]
240    fn generate_key() -> Result<Key<Self>, OsError> {
241        let mut key = Key::<Self>::default();
242        OsRng.try_fill_bytes(&mut key)?;
243        Ok(key)
244    }
245
246    /// Generate random key using the provided [`CryptoRng`].
247    #[cfg(feature = "rand_core")]
248    #[inline]
249    fn generate_key_with_rng<R: CryptoRng + ?Sized>(rng: &mut R) -> Key<Self> {
250        let mut key = Key::<Self>::default();
251        rng.fill_bytes(&mut key);
252        key
253    }
254
255    /// Generate random key using the provided [`TryCryptoRng`].
256    #[cfg(feature = "rand_core")]
257    #[inline]
258    fn try_generate_key_with_rng<R: TryCryptoRng + ?Sized>(
259        rng: &mut R,
260    ) -> Result<Key<Self>, R::Error> {
261        let mut key = Key::<Self>::default();
262        rng.try_fill_bytes(&mut key)?;
263        Ok(key)
264    }
265
266    /// Generate random IV using the operating system's secure RNG.
267    #[cfg(feature = "os_rng")]
268    #[inline]
269    fn generate_iv() -> Result<Iv<Self>, OsError> {
270        let mut iv = Iv::<Self>::default();
271        OsRng.try_fill_bytes(&mut iv)?;
272        Ok(iv)
273    }
274
275    /// Generate random IV using the provided [`CryptoRng`].
276    #[cfg(feature = "rand_core")]
277    #[inline]
278    fn generate_iv_with_rng<R: CryptoRng + ?Sized>(rng: &mut R) -> Iv<Self> {
279        let mut iv = Iv::<Self>::default();
280        rng.fill_bytes(&mut iv);
281        iv
282    }
283
284    /// Generate random IV using the provided [`TryCryptoRng`].
285    #[cfg(feature = "rand_core")]
286    #[inline]
287    fn try_generate_iv_with_rng<R: TryCryptoRng + ?Sized>(
288        rng: &mut R,
289    ) -> Result<Iv<Self>, R::Error> {
290        let mut iv = Iv::<Self>::default();
291        rng.try_fill_bytes(&mut iv)?;
292        Ok(iv)
293    }
294
295    /// Generate random key and IV using the operating system's secure RNG.
296    #[cfg(feature = "os_rng")]
297    #[inline]
298    fn generate_key_iv() -> Result<(Key<Self>, Iv<Self>), OsError> {
299        let key = Self::generate_key()?;
300        let iv = Self::generate_iv()?;
301        Ok((key, iv))
302    }
303
304    /// Generate random key and IV using the provided [`CryptoRng`].
305    #[cfg(feature = "rand_core")]
306    #[inline]
307    fn generate_key_iv_with_rng<R: CryptoRng + ?Sized>(rng: &mut R) -> (Key<Self>, Iv<Self>) {
308        let key = Self::generate_key_with_rng(rng);
309        let iv = Self::generate_iv_with_rng(rng);
310        (key, iv)
311    }
312
313    /// Generate random key and IV using the provided [`TryCryptoRng`].
314    #[cfg(feature = "rand_core")]
315    #[inline]
316    fn try_generate_key_iv_with_rng<R: TryCryptoRng + ?Sized>(
317        rng: &mut R,
318    ) -> Result<(Key<Self>, Iv<Self>), R::Error> {
319        let key = Self::try_generate_key_with_rng(rng)?;
320        let iv = Self::try_generate_iv_with_rng(rng)?;
321        Ok((key, iv))
322    }
323}
324
325/// Types which can be initialized from another type (usually block ciphers).
326///
327/// Usually used for initializing types from block ciphers.
328pub trait InnerInit: InnerUser + Sized {
329    /// Initialize value from the `inner`.
330    fn inner_init(inner: Self::Inner) -> Self;
331}
332
333/// Types which can be initialized from another type and additional initialization
334/// vector/nonce.
335///
336/// Usually used for initializing types from block ciphers.
337pub trait InnerIvInit: InnerUser + IvSizeUser + Sized {
338    /// Initialize value using `inner` and `iv` array.
339    fn inner_iv_init(inner: Self::Inner, iv: &Iv<Self>) -> Self;
340
341    /// Initialize value using `inner` and `iv` slice.
342    #[inline]
343    fn inner_iv_slice_init(inner: Self::Inner, iv: &[u8]) -> Result<Self, InvalidLength> {
344        let iv = <&Iv<Self>>::try_from(iv).map_err(|_| InvalidLength)?;
345        Ok(Self::inner_iv_init(inner, iv))
346    }
347
348    /// Generate random IV using the operating system's secure RNG.
349    #[cfg(feature = "os_rng")]
350    #[inline]
351    fn generate_iv() -> Result<Iv<Self>, OsError> {
352        let mut iv = Iv::<Self>::default();
353        OsRng.try_fill_bytes(&mut iv)?;
354        Ok(iv)
355    }
356
357    /// Generate random IV using the provided [`CryptoRng`].
358    #[cfg(feature = "rand_core")]
359    #[inline]
360    fn generate_iv_with_rng<R: CryptoRng + ?Sized>(rng: &mut R) -> Iv<Self> {
361        let mut iv = Iv::<Self>::default();
362        rng.fill_bytes(&mut iv);
363        iv
364    }
365
366    /// Generate random IV using the provided [`TryCryptoRng`].
367    #[cfg(feature = "rand_core")]
368    #[inline]
369    fn try_generate_iv_with_rng<R: TryCryptoRng + ?Sized>(
370        rng: &mut R,
371    ) -> Result<Iv<Self>, R::Error> {
372        let mut iv = Iv::<Self>::default();
373        rng.try_fill_bytes(&mut iv)?;
374        Ok(iv)
375    }
376}
377
378/// Trait for loading current IV state.
379pub trait IvState: IvSizeUser {
380    /// Returns current IV state.
381    fn iv_state(&self) -> Iv<Self>;
382}
383
384impl<T> KeySizeUser for T
385where
386    T: InnerUser,
387    T::Inner: KeySizeUser,
388{
389    type KeySize = <T::Inner as KeySizeUser>::KeySize;
390}
391
392impl<T> KeyIvInit for T
393where
394    T: InnerIvInit,
395    T::Inner: KeyInit,
396{
397    #[inline]
398    fn new(key: &Key<Self>, iv: &Iv<Self>) -> Self {
399        Self::inner_iv_init(T::Inner::new(key), iv)
400    }
401
402    #[inline]
403    fn new_from_slices(key: &[u8], iv: &[u8]) -> Result<Self, InvalidLength> {
404        T::Inner::new_from_slice(key).and_then(|i| T::inner_iv_slice_init(i, iv))
405    }
406
407    #[inline]
408    fn weak_key_test(key: &Key<Self>) -> Result<(), WeakKeyError> {
409        T::Inner::weak_key_test(key)
410    }
411}
412
413impl<T> KeyInit for T
414where
415    T: InnerInit,
416    T::Inner: KeyInit,
417{
418    #[inline]
419    fn new(key: &Key<Self>) -> Self {
420        Self::inner_init(T::Inner::new(key))
421    }
422
423    #[inline]
424    fn new_from_slice(key: &[u8]) -> Result<Self, InvalidLength> {
425        T::Inner::new_from_slice(key)
426            .map_err(|_| InvalidLength)
427            .map(Self::inner_init)
428    }
429
430    #[inline]
431    fn weak_key_test(key: &Key<Self>) -> Result<(), WeakKeyError> {
432        T::Inner::weak_key_test(key)
433    }
434}
435
436// Unfortunately this blanket impl is impossible without mutually
437// exclusive traits, see: https://github.com/rust-lang/rfcs/issues/1053
438// or at the very least without: https://github.com/rust-lang/rust/issues/20400
439/*
440impl<T> KeyIvInit for T
441where
442    T: InnerInit,
443    T::Inner: KeyIvInit,
444{
445    #[inline]
446    fn new(key: &Key<Self>, iv: &Iv<Self>) -> Self {
447        Self::inner_init(T::Inner::new(key, iv))
448    }
449
450    #[inline]
451    fn new_from_slices(key: &[u8], iv: &[u8]) -> Result<Self, InvalidLength> {
452        T::Inner::new_from_slice(key)
453            .map_err(|_| InvalidLength)
454            .map(Self::inner_init)
455    }
456
457    #[inline]
458    fn weak_key_test(key: &Key<Self>) -> Result<(), WeakKeyError> {
459        T::Inner::weak_key_test(key)
460    }
461}
462*/
463
464/// The error type returned when key and/or IV used in the [`KeyInit`],
465/// [`KeyIvInit`], and [`InnerIvInit`] slice-based methods had
466/// an invalid length.
467#[derive(Copy, Clone, Eq, PartialEq, Debug)]
468pub struct InvalidLength;
469
470impl fmt::Display for InvalidLength {
471    #[inline]
472    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
473        f.write_str("Invalid Length")
474    }
475}
476
477impl core::error::Error for InvalidLength {}
478
479/// The error type returned when a key is found to be weak.
480#[derive(Copy, Clone, Eq, PartialEq, Debug)]
481pub struct WeakKeyError;
482
483impl fmt::Display for WeakKeyError {
484    #[inline]
485    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
486        f.write_str("WeakKey")
487    }
488}
489
490impl core::error::Error for WeakKeyError {}