Skip to main content

crypto_common/
lib.rs

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
10/// Hazardous materials.
11pub mod hazmat;
12
13/// Secure random generation.
14#[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
34/// Block on which [`BlockSizeUser`] implementors operate.
35pub type Block<B> = Array<u8, <B as BlockSizeUser>::BlockSize>;
36
37/// Parallel blocks on which [`ParBlocksSizeUser`] implementors operate.
38pub type ParBlocks<T> = Array<Block<T>, <T as ParBlocksSizeUser>::ParBlocksSize>;
39
40/// Output array of [`OutputSizeUser`] implementors.
41pub type Output<T> = Array<u8, OutputSize<T>>;
42
43/// Alias for the output size of [`OutputSizeUser`] implementors.
44pub type OutputSize<T> = <T as OutputSizeUser>::OutputSize;
45
46/// Key used by [`KeySizeUser`] implementors.
47pub type Key<B> = Array<u8, <B as KeySizeUser>::KeySize>;
48
49/// Initialization vector (nonce) used by [`IvSizeUser`] implementors.
50pub type Iv<B> = Array<u8, <B as IvSizeUser>::IvSize>;
51
52/// Alias for `AddBlockSize<A, B> = Sum<T, B::BlockSize>`
53pub type AddBlockSize<T, B> = Sum<T, <B as BlockSizeUser>::BlockSize>;
54
55/// Alias for `SubBlockSize<A, B> = Diff<T, B::BlockSize>`
56pub type SubBlockSize<T, B> = Diff<T, <B as BlockSizeUser>::BlockSize>;
57
58/// Types which process data in blocks.
59pub trait BlockSizeUser {
60    /// Size of the block in bytes.
61    type BlockSize: ArraySize;
62
63    /// Return block size in bytes.
64    #[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
79/// Types which can process blocks in parallel.
80pub trait ParBlocksSizeUser: BlockSizeUser {
81    /// Number of blocks which can be processed in parallel.
82    type ParBlocksSize: ArraySize;
83}
84
85/// Types which return data with the given size.
86pub trait OutputSizeUser {
87    /// Size of the output in bytes.
88    type OutputSize: ArraySize;
89
90    /// Return output size in bytes.
91    #[inline(always)]
92    #[must_use]
93    fn output_size() -> usize {
94        Self::OutputSize::USIZE
95    }
96}
97
98/// Types which use key for initialization.
99///
100/// Generally it's used indirectly via [`KeyInit`] or [`KeyIvInit`].
101pub trait KeySizeUser {
102    /// Key size in bytes.
103    type KeySize: ArraySize;
104
105    /// Return key size in bytes.
106    #[inline(always)]
107    #[must_use]
108    fn key_size() -> usize {
109        Self::KeySize::USIZE
110    }
111}
112
113/// Types which use initialization vector (nonce) for initialization.
114///
115/// Generally it's used indirectly via [`KeyIvInit`] or [`InnerIvInit`].
116pub trait IvSizeUser {
117    /// Initialization vector size in bytes.
118    type IvSize: ArraySize;
119
120    /// Return IV size in bytes.
121    #[inline(always)]
122    #[must_use]
123    fn iv_size() -> usize {
124        Self::IvSize::USIZE
125    }
126}
127
128/// Types which use another type for initialization.
129///
130/// Generally it's used indirectly via [`InnerInit`] or [`InnerIvInit`].
131pub trait InnerUser {
132    /// Inner type.
133    type Inner;
134}
135
136/// Resettable types.
137pub trait Reset {
138    /// Reset state to its initial value.
139    fn reset(&mut self);
140}
141
142/// Trait which stores algorithm name constant, used in `Debug` implementations.
143pub trait AlgorithmName {
144    /// Write algorithm name into `f`.
145    ///
146    /// # Errors
147    /// `fmt::Result` is only intended for cases where an error occurs writing to the underlying
148    /// I/O stream.
149    fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result;
150}
151
152/// Serialize a key to a byte array.
153pub trait KeyExport: KeySizeUser {
154    /// Serialize this key as a byte array.
155    fn to_bytes(&self) -> Key<Self>;
156}
157
158/// Types which can be initialized from a key.
159pub trait KeyInit: KeySizeUser + Sized {
160    /// Create new value from fixed size key.
161    fn new(key: &Key<Self>) -> Self;
162
163    /// Create new value from variable size key.
164    ///
165    /// # Errors
166    /// Returns [`InvalidLength`] in the event the length of the provided slice is not equal to
167    /// `<Self as KeySizeUser>::KeySize::USIZE`.
168    #[inline]
169    fn new_from_slice(key: &[u8]) -> Result<Self, InvalidLength> {
170        <&Key<Self>>::try_from(key)
171            .map(Self::new)
172            .map_err(|_| InvalidLength)
173    }
174
175    /// DEPRECATED: generate random key using the provided [`CryptoRng`].
176    ///
177    /// Instead, you can now use the [`Generate`] trait directly with the [`Key`] type:
178    ///
179    /// ```ignore
180    /// let key = Key::generate_from_rng(rng);
181    /// ```
182    #[deprecated(
183        since = "0.2.0",
184        note = "use the `Generate` trait impl on `Key` instead"
185    )]
186    #[cfg(feature = "rand_core")]
187    fn generate_key<R: CryptoRng>(rng: &mut R) -> Key<Self> {
188        Key::<Self>::generate_from_rng(rng)
189    }
190}
191
192/// Types which can be initialized from a key and initialization vector (nonce).
193pub trait KeyIvInit: KeySizeUser + IvSizeUser + Sized {
194    /// Create new value from fixed length key and nonce.
195    fn new(key: &Key<Self>, iv: &Iv<Self>) -> Self;
196
197    /// Create new value from variable length key and nonce.
198    ///
199    /// # Errors
200    /// Returns [`InvalidLength`] in the event that `key` and/or `iv` are not the expected length.
201    #[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: generate random key using the provided [`CryptoRng`].
209    ///
210    /// Instead, you can now use the [`Generate`] trait directly with the [`Key`] type:
211    ///
212    /// ```ignore
213    /// let key = Key::generate_from_rng(rng);
214    /// ```
215    #[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: generate random IV using the provided [`CryptoRng`].
225    ///
226    /// Instead, you can now use the [`Generate`] trait directly with the [`Iv`] type:
227    ///
228    /// ```ignore
229    /// let iv = Iv::generate_from_rng(rng);
230    /// ```
231    #[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: generate random key and IV using the provided [`CryptoRng`].
241    ///
242    /// Instead, you can now use the [`Generate`] trait directly with the [`Key`] and [`Iv`] types:
243    ///
244    /// ```ignore
245    /// let key = Key::generate_from_rng(rng);
246    /// let iv = Iv::generate_from_rng(rng);
247    /// ```
248    #[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
260/// Types which can be fallibly initialized from a key.
261pub trait TryKeyInit: KeySizeUser + Sized {
262    /// Create new value from a fixed-size key.
263    ///
264    /// # Errors
265    /// If the key is considered invalid according to rules specific to the implementing type.
266    fn new(key: &Key<Self>) -> Result<Self, InvalidKey>;
267
268    /// Create new value from a variable size key.
269    ///
270    /// # Errors
271    /// If the key is considered invalid according to rules specific to the implementing type.
272    #[inline]
273    fn new_from_slice(key: &[u8]) -> Result<Self, InvalidKey> {
274        <&Key<Self>>::try_from(key)
275            .map_err(|_| InvalidKey)
276            .and_then(Self::new)
277    }
278}
279
280/// Types which can be initialized from another type (usually block ciphers).
281///
282/// Usually used for initializing types from block ciphers.
283pub trait InnerInit: InnerUser + Sized {
284    /// Initialize value from the `inner`.
285    fn inner_init(inner: Self::Inner) -> Self;
286}
287
288/// Types which can be initialized from another type and additional initialization
289/// vector/nonce.
290///
291/// Usually used for initializing types from block ciphers.
292pub trait InnerIvInit: InnerUser + IvSizeUser + Sized {
293    /// Initialize value using `inner` and `iv` array.
294    fn inner_iv_init(inner: Self::Inner, iv: &Iv<Self>) -> Self;
295
296    /// Initialize value using `inner` and `iv` slice.
297    ///
298    /// # Errors
299    /// Returns [`InvalidLength`]  in the event that `iv` is not the expected length.
300    #[inline]
301    fn inner_iv_slice_init(inner: Self::Inner, iv: &[u8]) -> Result<Self, InvalidLength> {
302        let iv = <&Iv<Self>>::try_from(iv).map_err(|_| InvalidLength)?;
303        Ok(Self::inner_iv_init(inner, iv))
304    }
305}
306
307/// Trait for loading current IV state.
308pub trait IvState: IvSizeUser {
309    /// Returns current IV state.
310    fn iv_state(&self) -> Iv<Self>;
311}
312
313impl<T> KeySizeUser for T
314where
315    T: InnerUser,
316    T::Inner: KeySizeUser,
317{
318    type KeySize = <T::Inner as KeySizeUser>::KeySize;
319}
320
321impl<T> KeyIvInit for T
322where
323    T: InnerIvInit,
324    T::Inner: KeyInit,
325{
326    #[inline]
327    fn new(key: &Key<Self>, iv: &Iv<Self>) -> Self {
328        Self::inner_iv_init(T::Inner::new(key), iv)
329    }
330
331    #[inline]
332    fn new_from_slices(key: &[u8], iv: &[u8]) -> Result<Self, InvalidLength> {
333        T::Inner::new_from_slice(key).and_then(|i| T::inner_iv_slice_init(i, iv))
334    }
335}
336
337impl<T> KeyInit for T
338where
339    T: InnerInit,
340    T::Inner: KeyInit,
341{
342    #[inline]
343    fn new(key: &Key<Self>) -> Self {
344        Self::inner_init(T::Inner::new(key))
345    }
346
347    #[inline]
348    fn new_from_slice(key: &[u8]) -> Result<Self, InvalidLength> {
349        T::Inner::new_from_slice(key)
350            .map_err(|_| InvalidLength)
351            .map(Self::inner_init)
352    }
353}
354
355/// Error type for [`TryKeyInit`] for cases where the provided bytes do not correspond to a
356/// valid key.
357#[derive(Copy, Clone, Eq, PartialEq, Debug)]
358pub struct InvalidKey;
359
360impl fmt::Display for InvalidKey {
361    #[inline]
362    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
363        f.write_str("InvalidKey")
364    }
365}
366
367impl core::error::Error for InvalidKey {}
368
369/// The error type returned when key and/or IV used in the [`KeyInit`],
370/// [`KeyIvInit`], and [`InnerIvInit`] slice-based methods had
371/// an invalid length.
372#[derive(Copy, Clone, Eq, PartialEq, Debug)]
373pub struct InvalidLength;
374
375impl fmt::Display for InvalidLength {
376    #[inline]
377    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
378        f.write_str("Invalid Length")
379    }
380}
381
382impl core::error::Error for InvalidLength {}