askar_crypto/buffer/
secret.rs

1use alloc::{boxed::Box, string::String, vec::Vec};
2use core::{
3    fmt::{self, Debug, Formatter},
4    hash, mem,
5    ops::{Deref, Range},
6};
7
8use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
9use subtle::{Choice, ConstantTimeEq};
10use zeroize::Zeroize;
11
12use super::{string::MaybeStr, HexRepr, ResizeBuffer, WriteBuffer};
13use crate::error::Error;
14
15/// A heap-allocated, zeroized byte buffer
16#[derive(Clone, Default, Zeroize)]
17pub struct SecretBytes(Vec<u8>);
18
19impl SecretBytes {
20    /// Create a new buffer using an initializer for the data
21    pub fn new_with(len: usize, f: impl FnOnce(&mut [u8])) -> Self {
22        let mut slf = Self::with_capacity(len);
23        slf.0.resize(len, 0u8);
24        f(slf.0.as_mut());
25        slf
26    }
27
28    /// Create a new, empty buffer with an initial capacity
29    #[inline]
30    pub fn with_capacity(max_len: usize) -> Self {
31        Self(Vec::with_capacity(max_len))
32    }
33
34    /// Create a new buffer from a slice
35    #[inline]
36    pub fn from_slice(data: &[u8]) -> Self {
37        let mut v = Vec::with_capacity(data.len());
38        v.extend_from_slice(data);
39        Self(v)
40    }
41
42    /// Create a new buffer from a slice, with extra space reserved
43    #[inline]
44    pub fn from_slice_reserve(data: &[u8], reserve: usize) -> Self {
45        let mut v = Vec::with_capacity(data.len() + reserve);
46        v.extend_from_slice(data);
47        Self(v)
48    }
49
50    /// Accessor for the current capacity of the buffer
51    #[inline]
52    pub fn capacity(&self) -> usize {
53        self.0.capacity()
54    }
55
56    /// Accessor for the length of the buffer contents
57    #[inline]
58    pub fn len(&self) -> usize {
59        self.0.len()
60    }
61
62    /// Determine if the buffer has zero length
63    #[inline]
64    pub fn is_empty(&self) -> bool {
65        self.0.is_empty()
66    }
67
68    /// Try to convert the buffer value to a string reference
69    pub fn as_opt_str(&self) -> Option<&str> {
70        core::str::from_utf8(self.0.as_slice()).ok()
71    }
72
73    /// Ensure that data can be appended to the buffer without resizing
74    pub fn ensure_capacity(&mut self, min_cap: usize) {
75        let cap = self.0.capacity();
76        if cap == 0 {
77            self.0.reserve(min_cap);
78        } else if cap > 0 && min_cap >= cap {
79            // allocate a new buffer and copy the secure data over
80            let new_cap = min_cap.max(cap * 2).max(32);
81            let mut buf = Self::with_capacity(new_cap);
82            buf.0.extend_from_slice(&self.0[..]);
83            mem::swap(&mut buf, self);
84            // old buf zeroized on drop
85        }
86    }
87
88    /// Extend the buffer from a byte slice
89    #[inline]
90    pub fn extend_from_slice(&mut self, data: &[u8]) {
91        self.reserve(data.len());
92        self.0.extend_from_slice(data);
93    }
94
95    /// Truncate and zeroize the buffer
96    #[inline]
97    pub fn clear(&mut self) {
98        self.0.zeroize();
99        self.0.truncate(0);
100    }
101
102    /// Reserve extra space in the buffer
103    #[inline]
104    pub fn reserve(&mut self, extra: usize) {
105        self.ensure_capacity(self.len() + extra)
106    }
107
108    /// Shrink the buffer capacity to match the length
109    pub fn shrink_to_fit(&mut self) {
110        let len = self.0.len();
111        if self.0.capacity() > len {
112            // copy to a smaller buffer (capacity is not tracked for boxed slice)
113            // and proceed with the normal zeroize on drop
114            let mut buf = Self::with_capacity(len);
115            buf.0.extend_from_slice(&self.0[..]);
116            mem::swap(&mut buf, self);
117            // old buf zeroized on drop
118        }
119    }
120
121    /// Convert this buffer into a boxed slice
122    pub fn into_boxed_slice(mut self) -> Box<[u8]> {
123        self.shrink_to_fit();
124        self.into_vec().into_boxed_slice()
125    }
126
127    /// Unwrap this buffer into a Vec<u8>
128    #[inline]
129    pub fn into_vec(mut self) -> Vec<u8> {
130        // FIXME zeroize extra capacity in case it was used previously?
131        let mut v = Vec::new(); // note: no heap allocation for empty vec
132        mem::swap(&mut v, &mut self.0);
133        v
134    }
135
136    #[cfg(feature = "crypto_box")]
137    pub(crate) fn as_vec_mut(&mut self) -> &mut Vec<u8> {
138        &mut self.0
139    }
140
141    pub(crate) fn splice(
142        &mut self,
143        range: Range<usize>,
144        iter: impl ExactSizeIterator<Item = u8>,
145    ) -> Result<(), Error> {
146        assert!(range.end >= range.start);
147        let rem_len = range.len();
148        let ins_len = iter.len();
149        if ins_len > rem_len {
150            self.reserve(ins_len - rem_len);
151        }
152        self.0.splice(range, iter);
153        Ok(())
154    }
155
156    /// Get a hex formatter for the secret data
157    pub fn as_hex(&self) -> HexRepr<&[u8]> {
158        HexRepr(self.0.as_ref())
159    }
160}
161
162impl Debug for SecretBytes {
163    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
164        if cfg!(test) {
165            f.debug_tuple("Secret")
166                .field(&MaybeStr(self.0.as_slice()))
167                .finish()
168        } else {
169            f.write_str("<secret>")
170        }
171    }
172}
173
174impl AsRef<[u8]> for SecretBytes {
175    fn as_ref(&self) -> &[u8] {
176        self.0.as_slice()
177    }
178}
179
180impl AsMut<[u8]> for SecretBytes {
181    fn as_mut(&mut self) -> &mut [u8] {
182        self.0.as_mut_slice()
183    }
184}
185
186impl Deref for SecretBytes {
187    type Target = [u8];
188
189    fn deref(&self) -> &Self::Target {
190        self.0.as_slice()
191    }
192}
193
194impl Drop for SecretBytes {
195    fn drop(&mut self) {
196        self.zeroize();
197    }
198}
199
200impl ConstantTimeEq for SecretBytes {
201    fn ct_eq(&self, other: &Self) -> Choice {
202        ConstantTimeEq::ct_eq(self.0.as_slice(), other.0.as_slice())
203    }
204}
205
206impl PartialEq for SecretBytes {
207    #[inline]
208    fn eq(&self, other: &Self) -> bool {
209        self.ct_eq(other).into()
210    }
211}
212impl Eq for SecretBytes {}
213
214impl hash::Hash for SecretBytes {
215    fn hash<H: hash::Hasher>(&self, state: &mut H) {
216        self.0.hash(state);
217    }
218}
219
220impl From<&[u8]> for SecretBytes {
221    fn from(inner: &[u8]) -> Self {
222        Self(inner.to_vec())
223    }
224}
225
226impl From<&str> for SecretBytes {
227    fn from(inner: &str) -> Self {
228        Self(inner.as_bytes().to_vec())
229    }
230}
231
232impl From<String> for SecretBytes {
233    fn from(inner: String) -> Self {
234        Self(inner.into_bytes())
235    }
236}
237
238impl From<Box<[u8]>> for SecretBytes {
239    fn from(inner: Box<[u8]>) -> Self {
240        Self(inner.into())
241    }
242}
243
244impl From<Vec<u8>> for SecretBytes {
245    fn from(inner: Vec<u8>) -> Self {
246        Self(inner)
247    }
248}
249
250impl PartialEq<&[u8]> for SecretBytes {
251    fn eq(&self, other: &&[u8]) -> bool {
252        self.0.eq(other)
253    }
254}
255
256impl PartialEq<Vec<u8>> for SecretBytes {
257    fn eq(&self, other: &Vec<u8>) -> bool {
258        self.0.eq(other)
259    }
260}
261
262impl WriteBuffer for SecretBytes {
263    fn buffer_write(&mut self, data: &[u8]) -> Result<(), Error> {
264        self.extend_from_slice(data);
265        Ok(())
266    }
267}
268
269impl ResizeBuffer for SecretBytes {
270    fn buffer_insert(&mut self, pos: usize, data: &[u8]) -> Result<(), Error> {
271        self.splice(pos..pos, data.iter().cloned())
272    }
273
274    fn buffer_remove(&mut self, range: Range<usize>) -> Result<(), Error> {
275        self.0.drain(range);
276        Ok(())
277    }
278
279    fn buffer_resize(&mut self, len: usize) -> Result<(), Error> {
280        self.ensure_capacity(len);
281        self.0.resize(len, 0u8);
282        Ok(())
283    }
284}
285
286impl Serialize for SecretBytes {
287    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
288    where
289        S: Serializer,
290    {
291        serializer.serialize_bytes(self.as_ref())
292    }
293}
294
295impl<'de> Deserialize<'de> for SecretBytes {
296    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
297    where
298        D: Deserializer<'de>,
299    {
300        deserializer.deserialize_bytes(SecVisitor)
301    }
302}
303
304struct SecVisitor;
305
306impl de::Visitor<'_> for SecVisitor {
307    type Value = SecretBytes;
308
309    fn expecting(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
310        formatter.write_str("bytes")
311    }
312
313    fn visit_bytes<E>(self, value: &[u8]) -> Result<Self::Value, E>
314    where
315        E: de::Error,
316    {
317        Ok(SecretBytes::from_slice(value))
318    }
319}
320
321#[cfg(test)]
322mod tests {
323    use super::super::tests::{test_resize_buffer, test_write_buffer};
324    use super::*;
325
326    #[test]
327    fn write_buffer_secret() {
328        test_write_buffer(SecretBytes::with_capacity(10));
329    }
330
331    #[test]
332    fn resize_buffer_secret() {
333        test_resize_buffer(SecretBytes::with_capacity(10));
334    }
335}