1#![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
27pub type Block<B> = GenericArray<u8, <B as BlockSizeUser>::BlockSize>;
29pub type Output<T> = GenericArray<u8, <T as OutputSizeUser>::OutputSize>;
31pub type Key<B> = GenericArray<u8, <B as KeySizeUser>::KeySize>;
33pub type Iv<B> = GenericArray<u8, <B as IvSizeUser>::IvSize>;
35
36pub trait BlockSizeUser {
38 type BlockSize: ArrayLength<u8> + 'static;
40
41 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
55pub trait OutputSizeUser {
57 type OutputSize: ArrayLength<u8> + 'static;
59
60 fn output_size() -> usize {
62 Self::OutputSize::USIZE
63 }
64}
65
66pub trait KeySizeUser {
70 type KeySize: ArrayLength<u8> + 'static;
72
73 fn key_size() -> usize {
75 Self::KeySize::USIZE
76 }
77}
78
79pub trait IvSizeUser {
83 type IvSize: ArrayLength<u8> + 'static;
85
86 fn iv_size() -> usize {
88 Self::IvSize::USIZE
89 }
90}
91
92pub trait InnerUser {
96 type Inner;
98}
99
100pub trait Reset {
102 fn reset(&mut self);
104}
105
106pub trait AlgorithmName {
108 fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result;
110}
111
112pub trait KeyInit: KeySizeUser + Sized {
114 fn new(key: &Key<Self>) -> Self;
116
117 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 #[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
137pub trait KeyIvInit: KeySizeUser + IvSizeUser + Sized {
139 fn new(key: &Key<Self>, iv: &Iv<Self>) -> Self;
141
142 #[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 #[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 #[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 #[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
186pub trait InnerInit: InnerUser + Sized {
190 fn inner_init(inner: Self::Inner) -> Self;
192}
193
194pub trait InnerIvInit: InnerUser + IvSizeUser + Sized {
199 fn inner_iv_init(inner: Self::Inner, iv: &Iv<Self>) -> Self;
201
202 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 #[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#[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 {}