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    html_root_url = "https://docs.rs/crypto-common/0.1.3"
9)]
10#![forbid(unsafe_code)]
11#![warn(missing_docs, rust_2018_idioms)]
12
13#[cfg(feature = "std")]
14extern crate std;
15
16#[cfg(feature = "rand_core")]
17pub use rand_core;
18
19pub use generic_array;
20pub use generic_array::typenum;
21
22use core::fmt;
23use generic_array::{typenum::Unsigned, ArrayLength, GenericArray};
24#[cfg(feature = "rand_core")]
25use rand_core::{CryptoRng, RngCore};
26
27/// Block on which [`BlockSizeUser`] implementors operate.
28pub type Block<B> = GenericArray<u8, <B as BlockSizeUser>::BlockSize>;
29/// Output array of [`OutputSizeUser`] implementors.
30pub type Output<T> = GenericArray<u8, <T as OutputSizeUser>::OutputSize>;
31/// Key used by [`KeySizeUser`] implementors.
32pub type Key<B> = GenericArray<u8, <B as KeySizeUser>::KeySize>;
33/// Initialization vector (nonce) used by [`IvSizeUser`] implementors.
34pub type Iv<B> = GenericArray<u8, <B as IvSizeUser>::IvSize>;
35
36/// Types which process data in blocks.
37pub trait BlockSizeUser {
38    /// Size of the block in bytes.
39    type BlockSize: ArrayLength<u8> + 'static;
40
41    /// Return block size in bytes.
42    fn block_size() -> usize {
43        Self::BlockSize::USIZE
44    }
45}
46
47impl<T: BlockSizeUser> BlockSizeUser for &T {
48    type BlockSize = T::BlockSize;
49}
50
51impl<T: BlockSizeUser> BlockSizeUser for &mut T {
52    type BlockSize = T::BlockSize;
53}
54
55/// Types which return data with the given size.
56pub trait OutputSizeUser {
57    /// Size of the output in bytes.
58    type OutputSize: ArrayLength<u8> + 'static;
59
60    /// Return output size in bytes.
61    fn output_size() -> usize {
62        Self::OutputSize::USIZE
63    }
64}
65
66/// Types which use key for initialization.
67///
68/// Generally it's used indirectly via [`KeyInit`] or [`KeyIvInit`].
69pub trait KeySizeUser {
70    /// Key size in bytes.
71    type KeySize: ArrayLength<u8> + 'static;
72
73    /// Return key size in bytes.
74    fn key_size() -> usize {
75        Self::KeySize::USIZE
76    }
77}
78
79/// Types which use initialization vector (nonce) for initialization.
80///
81/// Generally it's used indirectly via [`KeyIvInit`] or [`InnerIvInit`].
82pub trait IvSizeUser {
83    /// Initialization vector size in bytes.
84    type IvSize: ArrayLength<u8> + 'static;
85
86    /// Return IV size in bytes.
87    fn iv_size() -> usize {
88        Self::IvSize::USIZE
89    }
90}
91
92/// Types which use another type for initialization.
93///
94/// Generally it's used indirectly via [`InnerInit`] or [`InnerIvInit`].
95pub trait InnerUser {
96    /// Inner type.
97    type Inner;
98}
99
100/// Resettable types.
101pub trait Reset {
102    /// Reset state to its initial value.
103    fn reset(&mut self);
104}
105
106/// Trait which stores algorithm name constant, used in `Debug` implementations.
107pub trait AlgorithmName {
108    /// Write algorithm name into `f`.
109    fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result;
110}
111
112/// Types which can be initialized from key.
113pub trait KeyInit: KeySizeUser + Sized {
114    /// Create new value from fixed size key.
115    fn new(key: &Key<Self>) -> Self;
116
117    /// Create new value from variable size key.
118    fn new_from_slice(key: &[u8]) -> Result<Self, InvalidLength> {
119        if key.len() != Self::KeySize::to_usize() {
120            Err(InvalidLength)
121        } else {
122            Ok(Self::new(Key::<Self>::from_slice(key)))
123        }
124    }
125
126    /// Generate random key using the provided [`CryptoRng`].
127    #[cfg(feature = "rand_core")]
128    #[cfg_attr(docsrs, doc(cfg(feature = "rand_core")))]
129    #[inline]
130    fn generate_key(mut rng: impl CryptoRng + RngCore) -> Key<Self> {
131        let mut key = Key::<Self>::default();
132        rng.fill_bytes(&mut key);
133        key
134    }
135}
136
137/// Types which can be initialized from key and initialization vector (nonce).
138pub trait KeyIvInit: KeySizeUser + IvSizeUser + Sized {
139    /// Create new value from fixed length key and nonce.
140    fn new(key: &Key<Self>, iv: &Iv<Self>) -> Self;
141
142    /// Create new value from variable length key and nonce.
143    #[inline]
144    fn new_from_slices(key: &[u8], iv: &[u8]) -> Result<Self, InvalidLength> {
145        let key_len = Self::KeySize::USIZE;
146        let iv_len = Self::IvSize::USIZE;
147        if key.len() != key_len || iv.len() != iv_len {
148            Err(InvalidLength)
149        } else {
150            Ok(Self::new(
151                Key::<Self>::from_slice(key),
152                Iv::<Self>::from_slice(iv),
153            ))
154        }
155    }
156
157    /// Generate random key using the provided [`CryptoRng`].
158    #[cfg(feature = "rand_core")]
159    #[cfg_attr(docsrs, doc(cfg(feature = "rand_core")))]
160    #[inline]
161    fn generate_key(mut rng: impl CryptoRng + RngCore) -> Key<Self> {
162        let mut key = Key::<Self>::default();
163        rng.fill_bytes(&mut key);
164        key
165    }
166
167    /// Generate random IV using the provided [`CryptoRng`].
168    #[cfg(feature = "rand_core")]
169    #[cfg_attr(docsrs, doc(cfg(feature = "rand_core")))]
170    #[inline]
171    fn generate_iv(mut rng: impl CryptoRng + RngCore) -> Iv<Self> {
172        let mut iv = Iv::<Self>::default();
173        rng.fill_bytes(&mut iv);
174        iv
175    }
176
177    /// Generate random key and nonce using the provided [`CryptoRng`].
178    #[cfg(feature = "rand_core")]
179    #[cfg_attr(docsrs, doc(cfg(feature = "rand_core")))]
180    #[inline]
181    fn generate_key_iv(mut rng: impl CryptoRng + RngCore) -> (Key<Self>, Iv<Self>) {
182        (Self::generate_key(&mut rng), Self::generate_iv(&mut rng))
183    }
184}
185
186/// Types which can be initialized from another type (usually block ciphers).
187///
188/// Usually used for initializing types from block ciphers.
189pub trait InnerInit: InnerUser + Sized {
190    /// Initialize value from the `inner`.
191    fn inner_init(inner: Self::Inner) -> Self;
192}
193
194/// Types which can be initialized from another type and additional initialization
195/// vector/nonce.
196///
197/// Usually used for initializing types from block ciphers.
198pub trait InnerIvInit: InnerUser + IvSizeUser + Sized {
199    /// Initialize value using `inner` and `iv` array.
200    fn inner_iv_init(inner: Self::Inner, iv: &Iv<Self>) -> Self;
201
202    /// Initialize value using `inner` and `iv` slice.
203    fn inner_iv_slice_init(inner: Self::Inner, iv: &[u8]) -> Result<Self, InvalidLength> {
204        if iv.len() != Self::IvSize::to_usize() {
205            Err(InvalidLength)
206        } else {
207            Ok(Self::inner_iv_init(inner, Iv::<Self>::from_slice(iv)))
208        }
209    }
210
211    /// Generate random IV using the provided [`CryptoRng`].
212    #[cfg(feature = "rand_core")]
213    #[cfg_attr(docsrs, doc(cfg(feature = "rand_core")))]
214    #[inline]
215    fn generate_iv(mut rng: impl CryptoRng + RngCore) -> Iv<Self> {
216        let mut iv = Iv::<Self>::default();
217        rng.fill_bytes(&mut iv);
218        iv
219    }
220}
221
222impl<T> KeySizeUser for T
223where
224    T: InnerUser,
225    T::Inner: KeySizeUser,
226{
227    type KeySize = <T::Inner as KeySizeUser>::KeySize;
228}
229
230impl<T> KeyIvInit for T
231where
232    T: InnerIvInit,
233    T::Inner: KeyInit,
234{
235    #[inline]
236    fn new(key: &Key<Self>, iv: &Iv<Self>) -> Self {
237        Self::inner_iv_init(T::Inner::new(key), iv)
238    }
239
240    #[inline]
241    fn new_from_slices(key: &[u8], iv: &[u8]) -> Result<Self, InvalidLength> {
242        T::Inner::new_from_slice(key).and_then(|i| T::inner_iv_slice_init(i, iv))
243    }
244}
245
246impl<T> KeyInit for T
247where
248    T: InnerInit,
249    T::Inner: KeyInit,
250{
251    #[inline]
252    fn new(key: &Key<Self>) -> Self {
253        Self::inner_init(T::Inner::new(key))
254    }
255
256    #[inline]
257    fn new_from_slice(key: &[u8]) -> Result<Self, InvalidLength> {
258        T::Inner::new_from_slice(key)
259            .map_err(|_| InvalidLength)
260            .map(Self::inner_init)
261    }
262}
263
264// Unfortunately this blanket impl is impossible without mutually
265// exclusive traits, see: https://github.com/rust-lang/rfcs/issues/1053
266// or at the very least without: https://github.com/rust-lang/rust/issues/20400
267/*
268impl<T> KeyIvInit for T
269where
270    T: InnerInit,
271    T::Inner: KeyIvInit,
272{
273    #[inline]
274    fn new(key: &Key<Self>, iv: &Iv<Self>) -> Self {
275        Self::inner_init(T::Inner::new(key, iv))
276    }
277
278    #[inline]
279    fn new_from_slices(key: &[u8], iv: &[u8]) -> Result<Self, InvalidLength> {
280        T::Inner::new_from_slice(key)
281            .map_err(|_| InvalidLength)
282            .map(Self::inner_init)
283    }
284}
285*/
286
287/// The error type returned when key and/or IV used in the [`KeyInit`],
288/// [`KeyIvInit`], and [`InnerIvInit`] slice-based methods had
289/// an invalid length.
290#[derive(Copy, Clone, Eq, PartialEq, Debug)]
291pub struct InvalidLength;
292
293impl fmt::Display for InvalidLength {
294    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
295        f.write_str("Invalid Length")
296    }
297}
298
299#[cfg(feature = "std")]
300impl std::error::Error for InvalidLength {}