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: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: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: ::Inner| T::inner_iv_slice_init(inner: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(data:"Invalid Length")
307 }
308}
309
310#[cfg(feature = "std")]
311impl std::error::Error for InvalidLength {}
312