crypto_common/
lib.rs

1//! Common cryptographic traits.
2
3#![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
26/// Block on which [`BlockSizeUser`] implementors operate.
27pub type Block<B> = GenericArray<u8, <B as BlockSizeUser>::BlockSize>;
28
29/// Parallel blocks on which [`ParBlocksSizeUser`] implementors operate.
30pub type ParBlocks<T> = GenericArray<Block<T>, <T as ParBlocksSizeUser>::ParBlocksSize>;
31
32/// Output array of [`OutputSizeUser`] implementors.
33pub type Output<T> = GenericArray<u8, <T as OutputSizeUser>::OutputSize>;
34
35/// Key used by [`KeySizeUser`] implementors.
36pub type Key<B> = GenericArray<u8, <B as KeySizeUser>::KeySize>;
37
38/// Initialization vector (nonce) used by [`IvSizeUser`] implementors.
39pub type Iv<B> = GenericArray<u8, <B as IvSizeUser>::IvSize>;
40
41/// Types which process data in blocks.
42pub trait BlockSizeUser {
43    /// Size of the block in bytes.
44    type BlockSize: ArrayLength<u8> + 'static;
45
46    /// Return block size in bytes.
47    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
60/// Types which can process blocks in parallel.
61pub trait ParBlocksSizeUser: BlockSizeUser {
62    /// Number of blocks which can be processed in parallel.
63    type ParBlocksSize: ArrayLength<Block<Self>>;
64}
65
66/// Types which return data with the given size.
67pub trait OutputSizeUser {
68    /// Size of the output in bytes.
69    type OutputSize: ArrayLength<u8> + 'static;
70
71    /// Return output size in bytes.
72    fn output_size() -> usize {
73        Self::OutputSize::USIZE
74    }
75}
76
77/// Types which use key for initialization.
78///
79/// Generally it's used indirectly via [`KeyInit`] or [`KeyIvInit`].
80pub trait KeySizeUser {
81    /// Key size in bytes.
82    type KeySize: ArrayLength<u8> + 'static;
83
84    /// Return key size in bytes.
85    fn key_size() -> usize {
86        Self::KeySize::USIZE
87    }
88}
89
90/// Types which use initialization vector (nonce) for initialization.
91///
92/// Generally it's used indirectly via [`KeyIvInit`] or [`InnerIvInit`].
93pub trait IvSizeUser {
94    /// Initialization vector size in bytes.
95    type IvSize: ArrayLength<u8> + 'static;
96
97    /// Return IV size in bytes.
98    fn iv_size() -> usize {
99        Self::IvSize::USIZE
100    }
101}
102
103/// Types which use another type for initialization.
104///
105/// Generally it's used indirectly via [`InnerInit`] or [`InnerIvInit`].
106pub trait InnerUser {
107    /// Inner type.
108    type Inner;
109}
110
111/// Resettable types.
112pub trait Reset {
113    /// Reset state to its initial value.
114    fn reset(&mut self);
115}
116
117/// Trait which stores algorithm name constant, used in `Debug` implementations.
118pub trait AlgorithmName {
119    /// Write algorithm name into `f`.
120    fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result;
121}
122
123/// Types which can be initialized from key.
124pub trait KeyInit: KeySizeUser + Sized {
125    /// Create new value from fixed size key.
126    fn new(key: &Key<Self>) -> Self;
127
128    /// Create new value from variable size key.
129    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    /// Generate random key using the provided [`CryptoRng`].
138    #[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
148/// Types which can be initialized from key and initialization vector (nonce).
149pub trait KeyIvInit: KeySizeUser + IvSizeUser + Sized {
150    /// Create new value from fixed length key and nonce.
151    fn new(key: &Key<Self>, iv: &Iv<Self>) -> Self;
152
153    /// Create new value from variable length key and nonce.
154    #[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    /// Generate random key using the provided [`CryptoRng`].
169    #[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    /// Generate random IV using the provided [`CryptoRng`].
179    #[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    /// Generate random key and nonce using the provided [`CryptoRng`].
189    #[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
197/// Types which can be initialized from another type (usually block ciphers).
198///
199/// Usually used for initializing types from block ciphers.
200pub trait InnerInit: InnerUser + Sized {
201    /// Initialize value from the `inner`.
202    fn inner_init(inner: Self::Inner) -> Self;
203}
204
205/// Types which can be initialized from another type and additional initialization
206/// vector/nonce.
207///
208/// Usually used for initializing types from block ciphers.
209pub trait InnerIvInit: InnerUser + IvSizeUser + Sized {
210    /// Initialize value using `inner` and `iv` array.
211    fn inner_iv_init(inner: Self::Inner, iv: &Iv<Self>) -> Self;
212
213    /// Initialize value using `inner` and `iv` slice.
214    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    /// Generate random IV using the provided [`CryptoRng`].
223    #[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// Unfortunately this blanket impl is impossible without mutually
276// exclusive traits, see: https://github.com/rust-lang/rfcs/issues/1053
277// or at the very least without: https://github.com/rust-lang/rust/issues/20400
278/*
279impl<T> KeyIvInit for T
280where
281    T: InnerInit,
282    T::Inner: KeyIvInit,
283{
284    #[inline]
285    fn new(key: &Key<Self>, iv: &Iv<Self>) -> Self {
286        Self::inner_init(T::Inner::new(key, iv))
287    }
288
289    #[inline]
290    fn new_from_slices(key: &[u8], iv: &[u8]) -> Result<Self, InvalidLength> {
291        T::Inner::new_from_slice(key)
292            .map_err(|_| InvalidLength)
293            .map(Self::inner_init)
294    }
295}
296*/
297
298/// The error type returned when key and/or IV used in the [`KeyInit`],
299/// [`KeyIvInit`], and [`InnerIvInit`] slice-based methods had
300/// an invalid length.
301#[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 {}