mls_spec/
sensitive_bytes.rs

1use crate::macros::ref_forward_tls_impl;
2
3/// Container that ser/deserializes to TLS Variable-Length bytes
4/// and implements zeroizing & constant-time equality checks
5#[derive(Clone, Default, Ord, PartialOrd, zeroize::Zeroize, zeroize::ZeroizeOnDrop)]
6#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
7#[repr(transparent)]
8pub struct SensitiveBytes(Vec<u8>);
9
10impl SensitiveBytes {
11    pub fn as_slice(&self) -> &[u8] {
12        self.0.as_slice()
13    }
14
15    pub fn ct_eq_slice(&self, slice: impl AsRef<[u8]>) -> bool {
16        use subtle::ConstantTimeEq as _;
17        self.0.ct_eq(slice.as_ref()).into()
18    }
19
20    pub fn clear(&mut self) {
21        use zeroize::Zeroize as _;
22        self.0.zeroize();
23        self.0.clear();
24    }
25}
26
27impl std::hash::Hash for SensitiveBytes {
28    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
29        self.0.hash(state);
30    }
31}
32
33#[cfg(not(feature = "hazmat"))]
34impl std::fmt::Debug for SensitiveBytes {
35    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
36        write!(f, "[REDACTED]")
37    }
38}
39
40#[cfg(not(feature = "hazmat"))]
41impl std::fmt::Display for SensitiveBytes {
42    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
43        write!(f, "[REDACTED]")
44    }
45}
46
47#[cfg(feature = "hazmat")]
48impl std::fmt::Debug for SensitiveBytes {
49    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
50        write!(f, "{:?}", &self.0)
51    }
52}
53
54#[cfg(feature = "hazmat")]
55impl std::fmt::Display for SensitiveBytes {
56    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
57        write!(f, "{}", &hex::encode(self.0.as_slice()))
58    }
59}
60
61impl tls_codec::Size for SensitiveBytes {
62    fn tls_serialized_len(&self) -> usize {
63        crate::tlspl::bytes::tls_serialized_len(&self.0)
64    }
65}
66
67impl tls_codec::Serialize for SensitiveBytes {
68    fn tls_serialize<W: std::io::Write>(&self, writer: &mut W) -> Result<usize, tls_codec::Error> {
69        crate::tlspl::bytes::tls_serialize(&self.0, writer)
70    }
71}
72
73impl tls_codec::Deserialize for SensitiveBytes {
74    fn tls_deserialize<R: std::io::Read>(bytes: &mut R) -> Result<Self, tls_codec::Error>
75    where
76        Self: Sized,
77    {
78        Ok(Self(crate::tlspl::bytes::tls_deserialize(bytes)?))
79    }
80}
81
82ref_forward_tls_impl!(SensitiveBytes);
83
84impl From<Vec<u8>> for SensitiveBytes {
85    fn from(value: Vec<u8>) -> Self {
86        Self(value)
87    }
88}
89
90impl From<SensitiveBytes> for Vec<u8> {
91    fn from(val: SensitiveBytes) -> Self {
92        val.0.clone()
93    }
94}
95
96impl PartialEq for SensitiveBytes {
97    fn eq(&self, other: &Self) -> bool {
98        use subtle::ConstantTimeEq as _;
99        self.0.ct_eq(&other.0).into()
100    }
101}
102
103impl Eq for SensitiveBytes {}
104
105impl std::ops::Deref for SensitiveBytes {
106    type Target = [u8];
107    fn deref(&self) -> &Self::Target {
108        self.0.as_slice()
109    }
110}
111
112impl std::ops::DerefMut for SensitiveBytes {
113    fn deref_mut(&mut self) -> &mut Self::Target {
114        self.0.as_mut_slice()
115    }
116}