sha3_kmac/
mac.rs

1use core::{error, fmt};
2
3use generic_array::{typenum::Unsigned, ArrayLength, GenericArray};
4use sha3::{
5    digest::{
6        core_api::{Block, CoreProxy, UpdateCore},
7        crypto_common::{AlgorithmName, BlockSizeUser},
8        ExtendableOutput, Update, XofReader,
9    },
10    CShake128, CShake256,
11};
12use sha3_utils::{bytepad_blocks, encode_string, right_encode, right_encode_bytes};
13
14/// Returned when the key is too small.
15#[derive(Copy, Clone, Debug, Eq, PartialEq)]
16pub struct InvalidLength;
17
18impl fmt::Display for InvalidLength {
19    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
20        write!(f, "invalid length")
21    }
22}
23
24impl error::Error for InvalidLength {}
25
26/// A message authentication code.
27pub type Mac<N> = GenericArray<u8, N>;
28
29macro_rules! impl_kmac {
30    ($alg:literal, $name:ident, $cshake:ty, $security:literal) => {
31        #[doc = "`"]
32        #[doc = $alg]
33        #[doc = "`."]
34        #[derive(Clone, Debug)]
35        pub struct $name {
36            cshake: $cshake,
37        }
38
39        impl $name {
40            /// The minimum allowed size, in bytes, of a key.
41            pub const MIN_KEY_SIZE: usize = $security / 8;
42
43            /// Crates a new KMAC instance with key `k` and
44            /// customization string `s`.
45            ///
46            /// - `k` must be at least
47            ///   [`MIN_KEY_SIZE`][Self::MIN_KEY_SIZE].
48            /// - `s` can be any length, including the empty
49            ///   string.
50            pub fn new(k: &[u8], s: &[u8]) -> Result<Self, InvalidLength> {
51                if k.len() < Self::MIN_KEY_SIZE {
52                    return Err(InvalidLength);
53                }
54
55                let mut core = <$cshake as CoreProxy>::Core::new_with_function_name(b"KMAC", s);
56
57                // NB: This is the same thing as
58                //     const RATE: usize = <$cshake as BlockSizeUser>::BlockSize::USIZE;
59                //     for s in &bytepad::<RATE>(encode_string(k)) {
60                //         cshake.update(s);
61                //     }
62                // but avoids a panicking branch.
63                const BLOCK_SIZE: usize = <$cshake as BlockSizeUser>::BlockSize::USIZE;
64                let (head, mid, tail) = bytepad_blocks::<BLOCK_SIZE>(encode_string(k));
65                core.update_blocks(&[*Block::<$cshake>::from_slice(&head)]);
66                if !mid.is_empty() {
67                    core.update_blocks(
68                        // SAFETY: `[u8; BLOCK_SIZE]` and
69                        // `Block<$cshake>` has the same layout in
70                        // memory.
71                        unsafe { &*(mid as *const [[u8; BLOCK_SIZE]] as *const [Block<$cshake>]) },
72                    );
73                }
74                if let Some(tail) = tail {
75                    core.update_blocks(&[*Block::<$cshake>::from_slice(&tail)]);
76                }
77
78                let cshake = <$cshake>::from_core(core);
79
80                Ok(Self { cshake })
81            }
82
83            /// Writes `data` to the running MAC state.
84            #[inline]
85            pub fn update(&mut self, data: &[u8]) {
86                self.cshake.update(data);
87            }
88
89            /// Returns a fixed-size output.
90            pub fn finalize_into(mut self, out: &mut [u8]) {
91                self.cshake.update(right_encode_bytes(out.len()).as_bytes());
92                self.cshake.finalize_xof().read(out)
93            }
94
95            /// Returns a fixed-size MAC.
96            pub fn finalize<N: ArrayLength>(self) -> Mac<N> {
97                let mut out = Mac::default();
98                self.finalize_into(&mut out);
99                out
100            }
101        }
102
103        impl AlgorithmName for $name {
104            fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
105                write!(f, $alg)
106            }
107        }
108
109        impl Update for $name {
110            #[inline]
111            fn update(&mut self, data: &[u8]) {
112                self.update(data);
113            }
114        }
115    };
116}
117impl_kmac!("KMAC128", Kmac128, CShake128, 128);
118impl_kmac!("KMAC256", Kmac256, CShake256, 256);
119
120macro_rules! impl_kmac_xof {
121    ($alg:literal, $name:ident, $cshake:ty, $security:literal) => {
122        #[doc = "`"]
123        #[doc = $alg]
124        #[doc = "`."]
125        #[derive(Clone, Debug)]
126        pub struct $name {
127            cshake: $cshake,
128        }
129
130        impl $name {
131            /// The minimum allowed size, in bytes, of a key.
132            pub const MIN_KEY_SIZE: usize = $security / 8;
133
134            /// Crates a new KMACXOF instance with the key `k`
135            /// and customization string `s`.
136            ///
137            /// - `k` must be at least
138            ///   [`MIN_KEY_SIZE`][Self::MIN_KEY_SIZE].
139            /// - `s` can be any length, including the empty
140            ///   string.
141            pub fn new(k: &[u8], s: &[u8]) -> Result<Self, InvalidLength> {
142                if k.len() < Self::MIN_KEY_SIZE {
143                    return Err(InvalidLength);
144                }
145
146                let mut core = <$cshake as CoreProxy>::Core::new_with_function_name(b"KMAC", s);
147
148                // NB: This is the same thing as
149                //     const RATE: usize = <$cshake as BlockSizeUser>::BlockSize::USIZE;
150                //     for s in &bytepad::<RATE>(encode_string(k)) {
151                //         cshake.update(s);
152                //     }
153                // but avoids a panicking branch.
154                const BLOCK_SIZE: usize = <$cshake as BlockSizeUser>::BlockSize::USIZE;
155                let (head, mid, tail) = bytepad_blocks::<BLOCK_SIZE>(encode_string(k));
156                core.update_blocks(&[*Block::<$cshake>::from_slice(&head)]);
157                if !mid.is_empty() {
158                    core.update_blocks(
159                        // SAFETY: `[u8; BLOCK_SIZE]` and
160                        // `Block<$cshake>` has the same layout in
161                        // memory.
162                        unsafe { &*(mid as *const [[u8; BLOCK_SIZE]] as *const [Block<$cshake>]) },
163                    );
164                }
165                if let Some(tail) = tail {
166                    core.update_blocks(&[*Block::<$cshake>::from_slice(&tail)]);
167                }
168
169                let cshake = <$cshake>::from_core(core);
170
171                Ok(Self { cshake })
172            }
173
174            /// Writes `data` to the running MAC state.
175            #[inline]
176            pub fn update(&mut self, data: &[u8]) {
177                self.cshake.update(data);
178            }
179
180            /// Returns a fixed-size output.
181            pub fn finalize_xof(mut self) -> <$cshake as ExtendableOutput>::Reader {
182                self.cshake.update(right_encode(0).as_bytes());
183                self.cshake.finalize_xof()
184            }
185        }
186
187        impl AlgorithmName for $name {
188            fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
189                write!(f, $alg)
190            }
191        }
192
193        impl ExtendableOutput for $name {
194            type Reader = <$cshake as ExtendableOutput>::Reader;
195
196            #[inline]
197            fn finalize_xof(self) -> Self::Reader {
198                self.finalize_xof()
199            }
200        }
201
202        impl Update for $name {
203            #[inline]
204            fn update(&mut self, data: &[u8]) {
205                self.update(data);
206            }
207        }
208    };
209}
210impl_kmac_xof!("KMACXOF128", KmacXof128, CShake128, 128);
211impl_kmac_xof!("KMACXOF256", KmacXof256, CShake256, 256);
212
213#[cfg(test)]
214#[allow(clippy::type_complexity, reason = "Tests")]
215mod tests {
216    use generic_array::typenum::{U32, U64};
217
218    use super::*;
219
220    // https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/KMAC_samples.pdf
221    #[test]
222    fn test_kmac128() {
223        let vectors: &[(&[u8], &[u8], &[u8], &[u8])] = &[
224            (
225                &[
226                    0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C,
227                    0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
228                    0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
229                ],
230                &[0x00, 0x01, 0x02, 0x03],
231                &[],
232                &[
233                    0xE5, 0x78, 0x0B, 0x0D, 0x3E, 0xA6, 0xF7, 0xD3, 0xA4, 0x29, 0xC5, 0x70, 0x6A,
234                    0xA4, 0x3A, 0x00, 0xFA, 0xDB, 0xD7, 0xD4, 0x96, 0x28, 0x83, 0x9E, 0x31, 0x87,
235                    0x24, 0x3F, 0x45, 0x6E, 0xE1, 0x4E,
236                ],
237            ),
238            (
239                &[
240                    0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C,
241                    0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
242                    0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
243                ],
244                &[0x00, 0x01, 0x02, 0x03],
245                b"My Tagged Application",
246                &[
247                    0x3B, 0x1F, 0xBA, 0x96, 0x3C, 0xD8, 0xB0, 0xB5, 0x9E, 0x8C, 0x1A, 0x6D, 0x71,
248                    0x88, 0x8B, 0x71, 0x43, 0x65, 0x1A, 0xF8, 0xBA, 0x0A, 0x70, 0x70, 0xC0, 0x97,
249                    0x9E, 0x28, 0x11, 0x32, 0x4A, 0xA5,
250                ],
251            ),
252        ];
253        for (i, &(k, data, s, want)) in vectors.iter().enumerate() {
254            let mut m = Kmac128::new(k, s).unwrap();
255            m.update(data);
256            let got = m.finalize::<U32>();
257            let want = Mac::<U32>::from_slice(want);
258            assert_eq!(&got, want, "#{i}");
259        }
260    }
261
262    // https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/KMAC_samples.pdf
263    #[test]
264    fn test_kmac256() {
265        let vectors: &[(&[u8], &[u8], &[u8], &[u8])] = &[
266            (
267                &[
268                    0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C,
269                    0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
270                    0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
271                ],
272                &[0x00, 0x01, 0x02, 0x03],
273                b"My Tagged Application",
274                &[
275                    0x20, 0xC5, 0x70, 0xC3, 0x13, 0x46, 0xF7, 0x03, 0xC9, 0xAC, 0x36, 0xC6, 0x1C,
276                    0x03, 0xCB, 0x64, 0xC3, 0x97, 0x0D, 0x0C, 0xFC, 0x78, 0x7E, 0x9B, 0x79, 0x59,
277                    0x9D, 0x27, 0x3A, 0x68, 0xD2, 0xF7, 0xF6, 0x9D, 0x4C, 0xC3, 0xDE, 0x9D, 0x10,
278                    0x4A, 0x35, 0x16, 0x89, 0xF2, 0x7C, 0xF6, 0xF5, 0x95, 0x1F, 0x01, 0x03, 0xF3,
279                    0x3F, 0x4F, 0x24, 0x87, 0x10, 0x24, 0xD9, 0xC2, 0x77, 0x73, 0xA8, 0xDD,
280                ],
281            ),
282            (
283                &[
284                    0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C,
285                    0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
286                    0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
287                ],
288                &[
289                    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
290                    0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
291                    0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,
292                    0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33,
293                    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40,
294                    0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D,
295                    0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A,
296                    0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
297                    0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74,
298                    0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, 0x80, 0x81,
299                    0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E,
300                    0x8F, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B,
301                    0x9C, 0x9D, 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8,
302                    0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5,
303                    0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xC0, 0xC1, 0xC2,
304                    0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
305                ],
306                &[],
307                &[
308                    0x75, 0x35, 0x8C, 0xF3, 0x9E, 0x41, 0x49, 0x4E, 0x94, 0x97, 0x07, 0x92, 0x7C,
309                    0xEE, 0x0A, 0xF2, 0x0A, 0x3F, 0xF5, 0x53, 0x90, 0x4C, 0x86, 0xB0, 0x8F, 0x21,
310                    0xCC, 0x41, 0x4B, 0xCF, 0xD6, 0x91, 0x58, 0x9D, 0x27, 0xCF, 0x5E, 0x15, 0x36,
311                    0x9C, 0xBB, 0xFF, 0x8B, 0x9A, 0x4C, 0x2E, 0xB1, 0x78, 0x00, 0x85, 0x5D, 0x02,
312                    0x35, 0xFF, 0x63, 0x5D, 0xA8, 0x25, 0x33, 0xEC, 0x6B, 0x75, 0x9B, 0x69,
313                ],
314            ),
315            (
316                &[
317                    0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C,
318                    0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
319                    0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
320                ],
321                &[
322                    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
323                    0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
324                    0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,
325                    0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33,
326                    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40,
327                    0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D,
328                    0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A,
329                    0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
330                    0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74,
331                    0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, 0x80, 0x81,
332                    0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E,
333                    0x8F, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B,
334                    0x9C, 0x9D, 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8,
335                    0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5,
336                    0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xC0, 0xC1, 0xC2,
337                    0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
338                ],
339                b"My Tagged Application",
340                &[
341                    0xB5, 0x86, 0x18, 0xF7, 0x1F, 0x92, 0xE1, 0xD5, 0x6C, 0x1B, 0x8C, 0x55, 0xDD,
342                    0xD7, 0xCD, 0x18, 0x8B, 0x97, 0xB4, 0xCA, 0x4D, 0x99, 0x83, 0x1E, 0xB2, 0x69,
343                    0x9A, 0x83, 0x7D, 0xA2, 0xE4, 0xD9, 0x70, 0xFB, 0xAC, 0xFD, 0xE5, 0x00, 0x33,
344                    0xAE, 0xA5, 0x85, 0xF1, 0xA2, 0x70, 0x85, 0x10, 0xC3, 0x2D, 0x07, 0x88, 0x08,
345                    0x01, 0xBD, 0x18, 0x28, 0x98, 0xFE, 0x47, 0x68, 0x76, 0xFC, 0x89, 0x65,
346                ],
347            ),
348        ];
349        for (i, &(k, data, s, want)) in vectors.iter().enumerate() {
350            let mut m = Kmac256::new(k, s).unwrap();
351            m.update(data);
352            let got = m.finalize::<U64>();
353            let want = Mac::<U64>::from_slice(want);
354            assert_eq!(&got, want, "#{i}");
355        }
356    }
357
358    // https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/KMACXOF_samples.pdf
359    #[test]
360    fn test_kmacxof128() {
361        let vectors: &[(&[u8], &[u8], &[u8], &[u8])] = &[
362            (
363                &[
364                    0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C,
365                    0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
366                    0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
367                ],
368                &[0x00, 0x01, 0x02, 0x03],
369                &[],
370                &[
371                    0xCD, 0x83, 0x74, 0x0B, 0xBD, 0x92, 0xCC, 0xC8, 0xCF, 0x03, 0x2B, 0x14, 0x81,
372                    0xA0, 0xF4, 0x46, 0x0E, 0x7C, 0xA9, 0xDD, 0x12, 0xB0, 0x8A, 0x0C, 0x40, 0x31,
373                    0x17, 0x8B, 0xAC, 0xD6, 0xEC, 0x35,
374                ],
375            ),
376            (
377                &[
378                    0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C,
379                    0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
380                    0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
381                ],
382                &[0x00, 0x01, 0x02, 0x03],
383                b"My Tagged Application",
384                &[
385                    0x31, 0xA4, 0x45, 0x27, 0xB4, 0xED, 0x9F, 0x5C, 0x61, 0x01, 0xD1, 0x1D, 0xE6,
386                    0xD2, 0x6F, 0x06, 0x20, 0xAA, 0x5C, 0x34, 0x1D, 0xEF, 0x41, 0x29, 0x96, 0x57,
387                    0xFE, 0x9D, 0xF1, 0xA3, 0xB1, 0x6C,
388                ],
389            ),
390        ];
391        for (i, &(k, data, s, want)) in vectors.iter().enumerate() {
392            let mut m = KmacXof128::new(k, s).unwrap();
393            m.update(data);
394            let got = m.finalize_xof().read_boxed(32);
395            assert_eq!(&*got, want, "#{i}");
396        }
397    }
398
399    // https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/KMACXOF_samples.pdf
400    #[test]
401    fn test_kmacxof256() {
402        let vectors: &[(&[u8], &[u8], &[u8], &[u8])] = &[
403            (
404                &[
405                    0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C,
406                    0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
407                    0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
408                ],
409                &[0x00, 0x01, 0x02, 0x03],
410                b"My Tagged Application",
411                &[
412                    0x17, 0x55, 0x13, 0x3F, 0x15, 0x34, 0x75, 0x2A, 0xAD, 0x07, 0x48, 0xF2, 0xC7,
413                    0x06, 0xFB, 0x5C, 0x78, 0x45, 0x12, 0xCA, 0xB8, 0x35, 0xCD, 0x15, 0x67, 0x6B,
414                    0x16, 0xC0, 0xC6, 0x64, 0x7F, 0xA9, 0x6F, 0xAA, 0x7A, 0xF6, 0x34, 0xA0, 0xBF,
415                    0x8F, 0xF6, 0xDF, 0x39, 0x37, 0x4F, 0xA0, 0x0F, 0xAD, 0x9A, 0x39, 0xE3, 0x22,
416                    0xA7, 0xC9, 0x20, 0x65, 0xA6, 0x4E, 0xB1, 0xFB, 0x08, 0x01, 0xEB, 0x2B,
417                ],
418            ),
419            (
420                &[
421                    0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C,
422                    0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
423                    0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
424                ],
425                &[
426                    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
427                    0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
428                    0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,
429                    0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33,
430                    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40,
431                    0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D,
432                    0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A,
433                    0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
434                    0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74,
435                    0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, 0x80, 0x81,
436                    0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E,
437                    0x8F, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B,
438                    0x9C, 0x9D, 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8,
439                    0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5,
440                    0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xC0, 0xC1, 0xC2,
441                    0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
442                ],
443                &[],
444                &[
445                    0xFF, 0x7B, 0x17, 0x1F, 0x1E, 0x8A, 0x2B, 0x24, 0x68, 0x3E, 0xED, 0x37, 0x83,
446                    0x0E, 0xE7, 0x97, 0x53, 0x8B, 0xA8, 0xDC, 0x56, 0x3F, 0x6D, 0xA1, 0xE6, 0x67,
447                    0x39, 0x1A, 0x75, 0xED, 0xC0, 0x2C, 0xA6, 0x33, 0x07, 0x9F, 0x81, 0xCE, 0x12,
448                    0xA2, 0x5F, 0x45, 0x61, 0x5E, 0xC8, 0x99, 0x72, 0x03, 0x1D, 0x18, 0x33, 0x73,
449                    0x31, 0xD2, 0x4C, 0xEB, 0x8F, 0x8C, 0xA8, 0xE6, 0xA1, 0x9F, 0xD9, 0x8B,
450                ],
451            ),
452            (
453                &[
454                    0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C,
455                    0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
456                    0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
457                ],
458                &[
459                    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
460                    0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
461                    0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,
462                    0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33,
463                    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40,
464                    0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D,
465                    0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A,
466                    0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
467                    0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74,
468                    0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, 0x80, 0x81,
469                    0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E,
470                    0x8F, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B,
471                    0x9C, 0x9D, 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8,
472                    0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5,
473                    0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xC0, 0xC1, 0xC2,
474                    0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
475                ],
476                b"My Tagged Application",
477                &[
478                    0xD5, 0xBE, 0x73, 0x1C, 0x95, 0x4E, 0xD7, 0x73, 0x28, 0x46, 0xBB, 0x59, 0xDB,
479                    0xE3, 0xA8, 0xE3, 0x0F, 0x83, 0xE7, 0x7A, 0x4B, 0xFF, 0x44, 0x59, 0xF2, 0xF1,
480                    0xC2, 0xB4, 0xEC, 0xEB, 0xB8, 0xCE, 0x67, 0xBA, 0x01, 0xC6, 0x2E, 0x8A, 0xB8,
481                    0x57, 0x8D, 0x2D, 0x49, 0x9B, 0xD1, 0xBB, 0x27, 0x67, 0x68, 0x78, 0x11, 0x90,
482                    0x02, 0x0A, 0x30, 0x6A, 0x97, 0xDE, 0x28, 0x1D, 0xCC, 0x30, 0x30, 0x5D,
483                ],
484            ),
485        ];
486        for (i, &(k, data, s, want)) in vectors.iter().enumerate() {
487            let mut m = KmacXof256::new(k, s).unwrap();
488            m.update(data);
489            let got = m.finalize_xof().read_boxed(64);
490            assert_eq!(&*got, want, "#{i}");
491        }
492    }
493}