1use zeroize::Zeroize;
3use core::convert::TryFrom;
4use crate::can_cast_u32;
5use core::fmt;
6
7pub trait IvSize : crate::sealed::Sealed {
11 fn size() -> usize;
13
14 #[cfg_attr(not(debug_assertions), inline(always))]
20 fn size_32() -> u32 {
21 debug_assert!(can_cast_u32(Self::size()), "IvSize `size` is too large.");
22 Self::size() as u32
23 }
24}
25
26macro_rules! make_iv_size {
27 ($ident:ident = $size:literal) => {
28 #[doc = concat!("Represents a `", stringify!($size), "` byte IV size.")]
29 pub struct $ident;
30
31 impl $ident {
32 #[doc = concat!(
33 "The size of the IV as a u32 constant (`", stringify!($size), "`)"
34 )]
35 pub const SIZE_U32: u32 = $size;
36 #[doc = concat!(
37 "The size of the IV as a usize constant (`", stringify!($size), "`)"
38 )]
39 pub const SIZE: usize = $size;
40 }
41
42 impl $crate::sealed::Sealed for $ident {}
43
44 impl $crate::buf::IvSize for $ident {
45 #[doc = concat!("Returns the size of the IV in bytes. (`", stringify!($size), "`)")]
46 #[inline]
47 fn size() -> usize {
48 Self::SIZE
49 }
50
51 #[doc = concat!("Returns the size of the IV in bytes. (`", stringify!($size), "`)")]
52 #[inline]
53 fn size_32() -> u32 {
54 Self::SIZE_U32
55 }
56 }
57 };
58}
59
60make_iv_size! { U16 = 16 }
61make_iv_size! { U12 = 12 }
62
63pub trait GenericIv {
65 type Size : IvSize;
67
68 fn as_slice(&self) -> &[u8];
70}
71
72#[derive(Debug)]
74pub struct InvalidSize;
75
76impl fmt::Display for InvalidSize {
77 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
78 f.write_str("InvalidSize")
79 }
80}
81
82std! {
83 impl std::error::Error for InvalidSize {}
84}
85
86macro_rules! def_nonce {
87 ($ident:ident, $size:ident) => {
88 #[doc = concat!("Represents an IV / Nonce with the size: [`", stringify!($size), "`].")]
89 #[doc = ""]
90 #[doc = concat!("[`", stringify!($size), "`]: crate::buf::", stringify!($size))]
91 #[repr(transparent)]
92 #[cfg_attr(test, derive(Debug))]
93 pub struct $ident {
94 inner: [u8; $size::SIZE]
95 }
96
97 impl $ident {
98 pub const SIZE: $size = $size;
100
101 #[doc = "Creates a new nonce / IV"]
102 pub const fn new(inner: [u8; $size::SIZE]) -> Self {
103 Self { inner }
104 }
105
106 #[inline]
108 pub const fn slice(&self) -> &[u8] {
109 self.inner.as_slice()
110 }
111
112 #[inline]
114 pub fn zero(&mut self) {
115 self.inner.as_mut_slice().zeroize();
116 }
117 #[inline]
122 #[must_use]
123 pub const fn copy(&self) -> Self {
124 Self::new(self.inner)
125 }
126 }
127
128 impl GenericIv for $ident {
129 type Size = $size;
130
131 #[inline]
132 fn as_slice(&self) -> &[u8] {
133 self.inner.as_slice()
134 }
135 }
136
137 impl From<[u8; $size::SIZE]> for $ident {
138 fn from(value: [u8; $size::SIZE]) -> Self {
139 Self::new(value)
140 }
141 }
142
143 impl<'s> From<&'s [u8; $size::SIZE]> for $ident {
144 fn from(value: &'s [u8; $size::SIZE]) -> Self {
145 Self::new(*value)
146 }
147 }
148
149 impl<'s> TryFrom<&'s [u8]> for $ident {
152 type Error = InvalidSize;
153
154 fn try_from(value: &'s [u8]) -> Result<Self, Self::Error> {
155 match value.try_into() {
156 Ok(res) => Ok(Self::new(res)),
157 Err(_) => Err(InvalidSize)
158 }
159 }
160 }
161
162 #[cfg(test)]
163 impl proptest::arbitrary::Arbitrary for $ident {
164 type Parameters = ();
165
166 fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
167 use proptest::strategy::Strategy as _;
168 proptest::arbitrary::any::<[u8; $size::SIZE]>().prop_map($ident::new).boxed()
169 }
170
171 type Strategy = proptest::prelude::BoxedStrategy<Self>;
172 }
173 };
174}
175
176def_nonce!(Nonce, U12);
177def_nonce!(Nonce16, U16);
178def_nonce!(Iv, U16);
179
180impl<'r> GenericIv for &'r [u8; 12] {
181 type Size = U12;
182
183 #[inline]
184 fn as_slice(&self) -> &[u8] {
185 *self
186 }
187}
188
189impl GenericIv for [u8; 12] {
190 type Size = U12;
191
192 #[inline]
193 fn as_slice(&self) -> &[u8] {
194 self
195 }
196}
197
198impl<'r> GenericIv for &'r [u8; 16] {
199 type Size = U16;
200
201 #[inline]
202 fn as_slice(&self) -> &[u8] {
203 *self
204 }
205}
206
207impl GenericIv for [u8; 16] {
208 type Size = U16;
209
210 #[inline]
211 fn as_slice(&self) -> &[u8] {
212 self
213 }
214}
215
216pub trait ByteArray {
218 type Target;
220
221 fn capacity(&self) -> usize;
223
224 fn slice(&self) -> &[u8];
226 fn mut_slice(&mut self) -> &mut [u8];
228
229 #[inline]
231 fn zero(&mut self) {
232 self.mut_slice().zeroize();
233 }
234}
235
236impl<const N: usize> ByteArray for [u8; N] {
237 type Target = Self;
238
239 #[inline]
240 fn capacity(&self) -> usize {
241 N
242 }
243
244 #[inline]
245 fn slice(&self) -> &[u8] {
246 self.as_slice()
247 }
248 #[inline]
249 fn mut_slice(&mut self) -> &mut [u8] {
250 self.as_mut_slice()
251 }
252}
253
254#[cfg(feature = "alloc")]
255impl ByteArray for Vec<u8> {
256 type Target = Self;
257
258 #[inline]
259 fn capacity(&self) -> usize {
260 self.len()
261 }
262
263 #[inline]
264 fn slice(&self) -> &[u8] {
265 self.as_slice()
266 }
267 #[inline]
268 fn mut_slice(&mut self) -> &mut [u8] {
269 self.as_mut_slice()
270 }
271}