wolf_crypto/mac/poly1305/
key.rs

1//! Key management for the `Poly1305` MAC.
2//!
3//! This defines the key structures, traits, and associated functionalities required
4//! for securely managing and utilizing cryptographic keys.
5//!
6//! # Key Structures
7//!
8//! - `Key`: Represents a 32-byte secret key used for MAC computations.
9//! - `KeyRef`: A reference to a `Key`, allowing for efficient key handling without ownership.
10//!
11//! # Traits
12//!
13//! - `GenericKey`: A sealed trait for generic key types, providing a method to access the key's
14//!   byte pointer.
15
16use core::array::TryFromSliceError;
17use zeroize::Zeroize;
18use crate::sealed::Sealed;
19
20/// The size of the Poly1305 key in bytes.
21pub const KEY_SIZE: usize = KEY_SIZE_U32 as usize;
22
23/// The size of the Poly1305 key as a `u32`.
24pub const KEY_SIZE_U32: u32 = 32;
25
26
27/// A sealed trait for generic key types used in Poly1305.
28///
29/// This trait is sealed and cannot be implemented outside of this crate.
30pub trait GenericKey : Sealed {
31    #[doc(hidden)]
32    fn ptr(&self) -> *const u8;
33}
34
35/// Represents a 32-byte secret key for `Poly1305` and `ChaCha20Poly1305`.
36///
37/// This struct ensures that the key material is securely managed and zeroed from memory when
38/// dropped.
39#[repr(transparent)]
40#[derive(Clone)]
41pub struct Key {
42    inner: [u8; KEY_SIZE]
43}
44
45arb_key! { struct Key::new([u8; 32]) }
46
47impl Key {
48    /// Creates a new `Key` from a 32-byte array.
49    ///
50    /// # Arguments
51    ///
52    /// * `inner` - A 32-byte array containing the key material.
53    ///
54    /// # Example
55    ///
56    /// ```rust
57    /// use wolf_crypto::mac::poly1305::Key;
58    ///
59    /// let key = Key::new([0u8; 32]);
60    /// # drop(key);
61    /// ```
62    pub const fn new(inner: [u8; KEY_SIZE]) -> Self {
63        Self { inner }
64    }
65
66    /// Returns a reference to the key as a `KeyRef`.
67    ///
68    /// # Returns
69    ///
70    /// * `KeyRef` - A reference to the key material.
71    ///
72    /// # Example
73    ///
74    /// ```rust
75    /// use wolf_crypto::mac::poly1305::{Key, KeyRef};
76    ///
77    /// let key = Key::new([0u8; 32]);
78    /// let key_ref: KeyRef = key.as_ref();
79    /// # drop(key_ref); drop(key);
80    /// ```
81    pub const fn as_ref(&self) -> KeyRef {
82        KeyRef::new(&self.inner)
83    }
84}
85
86impl Zeroize for Key {
87    /// Zeroes the key material in memory.
88    ///
89    /// This method securely erases the key from memory to prevent leakage.
90    #[inline]
91    fn zeroize(&mut self) {
92        self.inner.zeroize();
93    }
94}
95
96opaque_dbg! { Key }
97impl Sealed for Key {}
98impl GenericKey for Key {
99    #[doc(hidden)]
100    #[inline]
101    fn ptr(&self) -> *const u8 {
102        self.inner.as_ptr()
103    }
104}
105
106impl From<[u8; KEY_SIZE]> for Key {
107    /// Converts a 32-byte array into a `Key`.
108    ///
109    /// # Arguments
110    ///
111    /// * `value` - A 32-byte array containing the key material.
112    ///
113    /// # Example
114    ///
115    /// ```rust
116    /// use wolf_crypto::mac::poly1305::Key;
117    ///
118    /// let key_bytes = [1u8; 32];
119    /// let key: Key = key_bytes.into();
120    /// # drop(key);
121    /// ```
122    #[inline]
123    fn from(value: [u8; KEY_SIZE]) -> Self {
124        Self::new(value, )
125    }
126}
127
128impl Drop for Key {
129    /// Drops the `Key`, ensuring that the key material is zeroed from memory.
130    #[inline]
131    fn drop(&mut self) {
132        self.zeroize();
133    }
134}
135
136/// A reference to a [`Key`], allowing for efficient key handling without ownership.
137#[repr(transparent)]
138pub struct KeyRef<'r> {
139    inner: &'r [u8; KEY_SIZE]
140}
141
142impl<'r> KeyRef<'r> {
143    /// Creates a new `KeyRef` from a reference to a 32-byte array.
144    ///
145    /// # Arguments
146    ///
147    /// * `inner` - A reference to a 32-byte array containing the key material.
148    ///
149    /// # Example
150    ///
151    /// ```rust
152    /// use wolf_crypto::mac::poly1305::{Key, KeyRef};
153    ///
154    /// let key_bytes = [2u8; 32];
155    /// let key = Key::new(key_bytes,);
156    /// let key_ref: KeyRef = key.as_ref();
157    /// # drop(key_ref); drop(key);
158    /// ```
159    pub const fn new(inner: &'r [u8; KEY_SIZE]) -> Self {
160        Self { inner }
161    }
162
163    /// Creates a copy of the key as a [`Key`].
164    ///
165    /// # Returns
166    ///
167    /// A new [`Key`] instance containing the same key material.
168    ///
169    /// # Example
170    ///
171    /// ```rust
172    /// use wolf_crypto::mac::poly1305::{Key, KeyRef};
173    ///
174    /// let key_ref: KeyRef = (&[7u8; 32]).into();
175    /// let owned_key = key_ref.copy();
176    /// # drop(key_ref); drop(owned_key);
177    /// ```
178    pub const fn copy(&self) -> Key {
179        Key::new(*self.inner, )
180    }
181}
182
183opaque_dbg! { KeyRef<'r> }
184
185impl<'r> Sealed for KeyRef<'r> {}
186impl<'r> GenericKey for KeyRef<'r> {
187    #[doc(hidden)]
188    #[inline]
189    fn ptr(&self) -> *const u8 {
190        self.inner.as_ptr()
191    }
192}
193
194impl<'r> From<&'r [u8; KEY_SIZE]> for KeyRef<'r> {
195    /// Converts a reference to a 32-byte array into a `KeyRef`.
196    ///
197    /// # Arguments
198    ///
199    /// * `value` - A reference to a 32-byte array containing the key material.
200    ///
201    /// # Example
202    ///
203    /// ```rust
204    /// use wolf_crypto::mac::poly1305::{Key, KeyRef};
205    ///
206    /// let key_ref = KeyRef::from(&[2u8; 32]);
207    /// # drop(key_ref);
208    /// ```
209    #[inline]
210    fn from(value: &'r [u8; KEY_SIZE]) -> Self {
211        Self::new(value)
212    }
213}
214
215impl<'r> TryFrom<&'r [u8]> for KeyRef<'r> {
216    type Error = TryFromSliceError;
217
218    /// Attempts to convert a slice of bytes into a `KeyRef`.
219    ///
220    /// # Arguments
221    ///
222    /// * `value` - A slice of bytes to convert.
223    ///
224    /// # Errors
225    ///
226    /// Returns `TryFromSliceError` if the slice length is not exactly 32 bytes.
227    ///
228    /// # Example
229    ///
230    /// ```rust
231    /// use wolf_crypto::mac::poly1305::KeyRef;
232    ///
233    /// let key_slice = &[5u8; 32];
234    /// let key_ref = KeyRef::try_from(key_slice).unwrap();
235    /// ```
236    #[inline]
237    fn try_from(value: &'r [u8]) -> Result<Self, Self::Error> {
238        value.try_into().map(Self::new)
239    }
240}