wolf_crypto/chacha/
key.rs

1use crate::sealed::Sealed;
2use zeroize::Zeroize;
3use core::fmt;
4
5/// Abstracts over different key types used in [`ChaCha20`].
6///
7/// [`ChaCha20`]: crate::chacha::ChaCha20
8pub trait GenericKey : Sealed {
9    /// Returns a slice of the key data
10    fn slice(&self) -> &[u8];
11    /// Returns the size of the key in bytes
12    fn size(&self) -> u32;
13}
14
15macro_rules! basic_key_api {
16    ($ident:ident $($lt:lifetime)?) => {
17        #[allow(clippy::len_without_is_empty)] // when is a key empty?
18        impl $(<$lt>)? $ident $(<$lt>)? {
19            /// Creates a new 128-bit key
20            #[inline]
21            pub const fn new_128(key: $(&$lt)? [u8; 16]) -> Self {
22                Self::B128(key)
23            }
24            /// Creates a new 256-bit key
25            #[inline]
26            pub const fn new_256(key: $(&$lt)? [u8; 32]) -> Self {
27                Self::B256(key)
28            }
29
30            /// Returns the length of the key in bytes
31            #[inline]
32            pub const fn len(&self) -> u32 {
33                match self {
34                    Self::B256(_) => 32,
35                    Self::B128(_) => 16
36                }
37            }
38
39            #[doc = " Returns a friendly identifier for the key."]
40            #[doc = ""]
41            #[doc = " # Returns"]
42            #[doc = ""]
43            #[doc = concat!(" - `256` bit key: `\"", stringify!($ident), "::256\"`")]
44            #[doc = concat!(" - `128` bit key: `\"", stringify!($ident), "::128\"`")]
45            pub const fn ident(&self) -> &'static str {
46                match self {
47                    Self::B256(_) => concat!(stringify!($ident), "::256"),
48                    Self::B128(_) => concat!(stringify!($ident), "::128"),
49                }
50            }
51
52            /// Returns a slice of the key data
53            #[inline]
54            pub const fn as_slice(&self) -> &[u8] {
55                match self {
56                    Self::B256(array) => array.as_slice(),
57                    Self::B128(array) => array.as_slice()
58                }
59            }
60        }
61
62        impl $(<$lt>)? fmt::Debug for $ident $(<$lt>)? {
63            #[doc = "This writes the following to the `Formatter` (depending on the variant): "]
64            #[doc = ""]
65            #[doc = concat!(" - `256` bit key: `\"", stringify!($ident), "::256\"`")]
66            #[doc = concat!(" - `128` bit key: `\"", stringify!($ident), "::128\"`")]
67            #[inline]
68            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
69                f.write_str(self.ident())
70            }
71        }
72
73        impl $(<$lt>)? fmt::Display for $ident $(<$lt>)? {
74            #[doc = "This writes the following to the `Formatter` (depending on the variant): "]
75            #[doc = ""]
76            #[doc = concat!(" - `256` bit key: `\"", stringify!($ident), "::256\"`")]
77            #[doc = concat!(" - `128` bit key: `\"", stringify!($ident), "::128\"`")]
78            #[inline]
79            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
80                f.write_str(self.ident())
81            }
82        }
83
84        impl $(<$lt>)? Sealed for $ident $(<$lt>)? {}
85
86        impl $(<$lt>)? GenericKey for $ident $(<$lt>)? {
87            #[inline]
88            fn slice(&self) -> &[u8] {
89                self.as_slice()
90            }
91            #[inline]
92            fn size(&self) -> u32 {
93                self.len()
94            }
95        }
96    };
97}
98
99/// Represents either a 128-bit or 256-bit [`ChaCha20`] key.
100///
101/// [`ChaCha20`]: crate::chacha::ChaCha20
102#[must_use]
103pub enum Key {
104    /// 128-bit key.
105    B128([u8; 16]),
106    /// 256-bit key.
107    B256([u8; 32])
108}
109
110basic_key_api! { Key }
111
112arb_key! {
113    enum Key {
114        B128([u8; 16]),
115        B256([u8; 32])
116    }
117}
118
119impl Key {
120    /// Returns a mutable slice of the key data
121    #[inline]
122    pub fn as_mut_slice(&mut self) -> &mut [u8] {
123        match self {
124            Self::B256(array) => array.as_mut_slice(),
125            Self::B128(array) => array.as_mut_slice()
126        }
127    }
128
129    /// Creates a [`KeyRef`] referencing the underlying key material.
130    #[inline]
131    pub const fn as_ref(&self) -> KeyRef {
132        match self {
133            Self::B128(raw) => KeyRef::B128(raw),
134            Self::B256(raw) => KeyRef::B256(raw)
135        }
136    }
137}
138
139impl Zeroize for Key {
140    #[inline]
141    fn zeroize(&mut self) {
142        self.as_mut_slice().zeroize();
143    }
144}
145
146impl Drop for Key {
147    /// Automatically zeroes the key when it's dropped.
148    #[inline]
149    fn drop(&mut self) {
150        self.zeroize();
151    }
152}
153
154impl From<[u8; 16]> for Key {
155    /// Convert a 16 byte array to a 128-bit [`Key`] for [`ChaCha20`].
156    ///
157    /// [`ChaCha20`]: crate::chacha::ChaCha20
158    #[inline]
159    fn from(value: [u8; 16]) -> Self {
160        Self::B128(value)
161    }
162}
163
164impl From<[u8; 32]> for Key {
165    /// Convert a 32 byte array to a 256-bit [`Key`] for [`ChaCha20`].
166    ///
167    /// [`ChaCha20`]: crate::chacha::ChaCha20
168    #[inline]
169    fn from(value: [u8; 32]) -> Self {
170        Self::B256(value)
171    }
172}
173
174/// Represents either a 128-bit or 256-bit [`ChaCha20`] key.
175///
176/// [`ChaCha20`]: crate::chacha::ChaCha20
177#[must_use]
178pub enum KeyRef<'r> {
179    /// 128-bit key.
180    B128(&'r [u8; 16]),
181    /// 256-bit key.
182    B256(&'r [u8; 32])
183}
184
185impl<'r> KeyRef<'r> {
186    /// Copies the underlying key material into a new [`Key`] instance.
187    #[inline]
188    pub const fn copy(&self) -> Key {
189        match *self {
190            Self::B128(raw) => Key::B128(*raw),
191            Self::B256(raw) => Key::B256(*raw)
192        }
193    }
194}
195
196basic_key_api! { KeyRef 'r }
197
198impl<'r> From<&'r [u8; 16]> for KeyRef<'r> {
199    /// Convert a reference to a 16 byte array to a 128-bit [`KeyRef`] for [`ChaCha20`].
200    ///
201    /// [`ChaCha20`]: crate::chacha::ChaCha20
202    #[inline]
203    fn from(value: &'r [u8; 16]) -> Self {
204        Self::B128(value)
205    }
206}
207
208impl<'r> From<&'r [u8; 32]> for KeyRef<'r> {
209    /// Convert a reference to a 32 byte array to a 256-bit [`KeyRef`] for [`ChaCha20`].
210    ///
211    /// [`ChaCha20`]: crate::chacha::ChaCha20
212    #[inline]
213    fn from(value: &'r [u8; 32]) -> Self {
214        Self::B256(value)
215    }
216}
217
218impl<'kr> Sealed for &'kr [u8; 16] {}
219
220impl<'kr> GenericKey for &'kr [u8; 16] {
221    #[inline]
222    fn slice(&self) -> &[u8] {
223        self.as_slice()
224    }
225    #[inline]
226    fn size(&self) -> u32 {
227        16
228    }
229}
230
231impl<'kr> Sealed for &'kr [u8; 32] {}
232impl<'kr> GenericKey for &'kr [u8; 32] {
233    #[inline]
234    fn slice(&self) -> &[u8] {
235        self.as_slice()
236    }
237    #[inline]
238    fn size(&self) -> u32 {
239        32
240    }
241}
242