1/*	$NetBSD: aes_selftest.c,v 1.7 2021/12/05 04:48:35 msaitoh Exp $	*/
2
3/*-
4 * Copyright (c) 2020 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <sys/cdefs.h>
30__KERNEL_RCSID(1, "$NetBSD: aes_selftest.c,v 1.7 2021/12/05 04:48:35 msaitoh Exp $");
31
32#ifdef _KERNEL
33
34#include <sys/types.h>
35#include <sys/systm.h>
36
37#include <lib/libkern/libkern.h>
38
39#else  /* !_KERNEL */
40
41#include <stdint.h>
42#include <stdio.h>
43#include <string.h>
44
45static void
46hexdump(int (*prf)(const char *, ...) __printflike(1,2), const char *prefix,
47    const void *buf, size_t len)
48{
49	const uint8_t *p = buf;
50	size_t i;
51
52	(*prf)("%s (%zu bytes)\n", prefix, len);
53	for (i = 0; i < len; i++) {
54		if (i % 16 == 8)
55			(*prf)("  ");
56		else
57			(*prf)(" ");
58		(*prf)("%02hhx", p[i]);
59		if ((i + 1) % 16 == 0)
60			(*prf)("\n");
61	}
62	if (i % 16)
63		(*prf)("\n");
64}
65
66#endif	/* _KERNEL */
67
68#include <crypto/aes/aes.h>
69#include <crypto/aes/aes_impl.h>
70
71static const unsigned aes_keybytes[] __unused = { 16, 24, 32 };
72static const unsigned aes_keybits[] __unused = { 128, 192, 256 };
73static const unsigned aes_nrounds[] = { 10, 12, 14 };
74
75#define	aes_selftest_fail(impl, actual, expected, nbytes, fmt, args...)	      \
76({									      \
77	printf("%s "fmt": self-test failed\n", (impl)->ai_name, ##args);      \
78	hexdump(printf, "was", (actual), (nbytes));			      \
79	hexdump(printf, "expected", (expected), (nbytes));		      \
80	-1;								      \
81})
82
83static int
84aes_selftest_encdec(const struct aes_impl *impl)
85{
86	/*
87	 * head -c 16 < /dev/zero | openssl enc -aes-{128,192,256}-ecb
88	 *     -nopad -K 000102030405060708090a0b0c0d... | hexdump -C
89	 */
90	static const uint8_t expected[3][16] = {
91		[0] = {
92			0xc6,0xa1,0x3b,0x37,0x87,0x8f,0x5b,0x82,
93			0x6f,0x4f,0x81,0x62,0xa1,0xc8,0xd8,0x79,
94		},
95		[1] = {
96			0x91,0x62,0x51,0x82,0x1c,0x73,0xa5,0x22,
97			0xc3,0x96,0xd6,0x27,0x38,0x01,0x96,0x07,
98		},
99		[2] = {
100			0xf2,0x90,0x00,0xb6,0x2a,0x49,0x9f,0xd0,
101			0xa9,0xf3,0x9a,0x6a,0xdd,0x2e,0x77,0x80,
102		},
103	};
104	struct aesenc enc;
105	struct aesdec dec;
106	uint8_t key[32];
107	uint8_t in[16];
108	uint8_t outbuf[18] = { [0] = 0x1a, [17] = 0x1a }, *out = outbuf + 1;
109	unsigned i;
110
111	for (i = 0; i < 32; i++)
112		key[i] = i;
113	for (i = 0; i < 16; i++)
114		in[i] = 0;
115
116	for (i = 0; i < 3; i++) {
117		impl->ai_setenckey(&enc, key, aes_nrounds[i]);
118		impl->ai_setdeckey(&dec, key, aes_nrounds[i]);
119		impl->ai_enc(&enc, in, out, aes_nrounds[i]);
120		if (memcmp(out, expected[i], 16))
121			return aes_selftest_fail(impl, out, expected[i], 16,
122			    "AES-%u enc", aes_keybits[i]);
123		impl->ai_dec(&dec, out, out, aes_nrounds[i]);
124		if (memcmp(out, in, 16))
125			return aes_selftest_fail(impl, out, in, 16,
126			    "AES-%u dec", aes_keybits[i]);
127	}
128
129	if (outbuf[0] != 0x1a)
130		return aes_selftest_fail(impl, outbuf,
131		    (const uint8_t[1]){0x1a}, 1,
132		    "AES overrun preceding");
133	if (outbuf[17] != 0x1a)
134		return aes_selftest_fail(impl, outbuf + 17,
135		    (const uint8_t[1]){0x1a}, 1,
136		    "AES overrun following");
137
138	/* Success!  */
139	return 0;
140}
141
142static int
143aes_selftest_encdec_cbc(const struct aes_impl *impl)
144{
145	static const uint8_t expected[3][144] = {
146		[0] = {
147			0xfe,0xf1,0xa8,0xb6,0x25,0xf0,0xc4,0x3a,
148			0x71,0x08,0xb6,0x23,0xa6,0xfb,0x90,0xca,
149			0x9e,0x64,0x6d,0x95,0xb5,0xf5,0x41,0x24,
150			0xd2,0xe6,0x60,0xda,0x6c,0x69,0xc4,0xa0,
151			0x4d,0xaa,0x94,0xf6,0x66,0x1e,0xaa,0x85,
152			0x68,0xc5,0x6b,0x2e,0x77,0x7a,0x68,0xff,
153			0x45,0x15,0x45,0xc5,0x9c,0xbb,0x3a,0x23,
154			0x08,0x3a,0x06,0xdd,0xc0,0x52,0xd2,0xb7,
155			0x47,0xaa,0x1c,0xc7,0xb5,0xa9,0x7d,0x04,
156			0x60,0x67,0x78,0xf6,0xb9,0xba,0x26,0x84,
157			0x45,0x72,0x44,0xed,0xa3,0xd3,0xa0,0x3f,
158			0x19,0xee,0x3f,0x94,0x59,0x52,0x4b,0x13,
159			0xfd,0x81,0xcc,0xf9,0xf2,0x29,0xd7,0xec,
160			0xde,0x03,0x56,0x01,0x4a,0x19,0x86,0xc0,
161			0x87,0xce,0xe1,0xcc,0x13,0xf1,0x2e,0xda,
162			0x3f,0xfe,0xa4,0x64,0xe7,0x48,0xb4,0x7b,
163			0x73,0x62,0x5a,0x80,0x5e,0x01,0x20,0xa5,
164			0x0a,0xd7,0x98,0xa7,0xd9,0x8b,0xff,0xc2,
165		},
166		[1] = {
167			0xa6,0x87,0xf0,0x92,0x68,0xc8,0xd6,0x42,
168			0xa8,0x83,0x1c,0x92,0x65,0x8c,0xd9,0xfe,
169			0x0b,0x1a,0xc6,0x96,0x27,0x44,0xd4,0x14,
170			0xfc,0xe7,0x85,0xb2,0x71,0xc7,0x11,0x39,
171			0xed,0x36,0xd3,0x5c,0xa7,0xf7,0x3d,0xc9,
172			0xa2,0x54,0x8b,0xb4,0xfa,0xe8,0x21,0xf9,
173			0xfd,0x6a,0x42,0x85,0xde,0x66,0xd4,0xc0,
174			0xa7,0xd3,0x5b,0xe1,0xe6,0xac,0xea,0xf9,
175			0xa3,0x15,0x68,0xf4,0x66,0x4c,0x23,0x75,
176			0x58,0xba,0x7f,0xca,0xbf,0x40,0x56,0x79,
177			0x2f,0xbf,0xdf,0x5f,0x56,0xcb,0xa0,0xe4,
178			0x22,0x65,0x6a,0x8f,0x4f,0xff,0x11,0x6b,
179			0x57,0xeb,0x45,0xeb,0x9d,0x7f,0xfe,0x9c,
180			0x8b,0x30,0xa8,0xb0,0x7e,0x27,0xf8,0xbc,
181			0x1f,0xf8,0x15,0x34,0x36,0x4f,0x46,0x73,
182			0x81,0x90,0x4b,0x4b,0x46,0x4d,0x01,0x45,
183			0xa1,0xc3,0x0b,0xa8,0x5a,0xab,0xc1,0x88,
184			0x66,0xc8,0x1a,0x94,0x17,0x64,0x6f,0xf4,
185		},
186		[2] = {
187			0x22,0x4c,0x27,0xf4,0xba,0x37,0x8b,0x27,
188			0xd3,0xd6,0x88,0x8a,0xdc,0xed,0x64,0x42,
189			0x19,0x60,0x31,0x09,0xf3,0x72,0xd2,0xc2,
190			0xd3,0xe3,0xff,0xce,0xc5,0x03,0x9f,0xce,
191			0x99,0x49,0x8a,0xf2,0xe1,0xba,0xe2,0xa8,
192			0xd7,0x32,0x07,0x2d,0xb0,0xb3,0xbc,0x67,
193			0x32,0x9a,0x3e,0x7d,0x16,0x23,0xe7,0x24,
194			0x84,0xe1,0x15,0x03,0x9c,0xa2,0x7a,0x95,
195			0x34,0xa8,0x04,0x4e,0x79,0x31,0x50,0x26,
196			0x76,0xd1,0x10,0xce,0xec,0x13,0xf7,0xfb,
197			0x94,0x6b,0x76,0x50,0x5f,0xb2,0x3e,0x7c,
198			0xbe,0x97,0xe7,0x13,0x06,0x9e,0x2d,0xc4,
199			0x46,0x65,0xa7,0x69,0x37,0x07,0x25,0x37,
200			0xe5,0x48,0x51,0xa8,0x58,0xe8,0x4d,0x7c,
201			0xb5,0xbe,0x25,0x13,0xbc,0x11,0xc2,0xde,
202			0xdb,0x00,0xef,0x1c,0x1d,0xeb,0xe3,0x49,
203			0x1c,0xc0,0x78,0x29,0x76,0xc0,0xde,0x3a,
204			0x0e,0x96,0x8f,0xea,0xd7,0x42,0x4e,0xb4,
205		},
206	};
207	struct aesenc enc;
208	struct aesdec dec;
209	uint8_t key[32];
210	uint8_t in[144];
211	uint8_t outbuf[146] = { [0] = 0x1a, [145] = 0x1a }, *out = outbuf + 1;
212	uint8_t iv0[16], iv[16];
213	unsigned i, j;
214
215	for (i = 0; i < 32; i++)
216		key[i] = i;
217	for (i = 0; i < 16; i++)
218		iv0[i] = 0x20 ^ i;
219	for (i = 0; i < 144; i++)
220		in[i] = 0x80 ^ i;
221
222	for (i = 0; i < 3; i++) {
223		impl->ai_setenckey(&enc, key, aes_nrounds[i]);
224		impl->ai_setdeckey(&dec, key, aes_nrounds[i]);
225
226		/* Try one swell foop.  */
227		memcpy(iv, iv0, 16);
228		impl->ai_cbc_enc(&enc, in, out, 144, iv, aes_nrounds[i]);
229		if (memcmp(out, expected[i], 144))
230			return aes_selftest_fail(impl, out, expected[i], 144,
231			    "AES-%u-CBC enc", aes_keybits[i]);
232
233		memcpy(iv, iv0, 16);
234		impl->ai_cbc_dec(&dec, out, out, 144, iv, aes_nrounds[i]);
235		if (memcmp(out, in, 144))
236			return aes_selftest_fail(impl, out, in, 144,
237			    "AES-%u-CBC dec", aes_keybits[i]);
238
239		/* Try incrementally, with IV update.  */
240		for (j = 0; j < 144; j += 16) {
241			memcpy(iv, iv0, 16);
242			impl->ai_cbc_enc(&enc, in, out, j, iv, aes_nrounds[i]);
243			impl->ai_cbc_enc(&enc, in + j, out + j, 144 - j, iv,
244			    aes_nrounds[i]);
245			if (memcmp(out, expected[i], 144))
246				return aes_selftest_fail(impl, out,
247				    expected[i], 144, "AES-%u-CBC enc inc %u",
248				    aes_keybits[i], j);
249
250			memcpy(iv, iv0, 16);
251			impl->ai_cbc_dec(&dec, out, out, j, iv,
252			    aes_nrounds[i]);
253			impl->ai_cbc_dec(&dec, out + j, out + j, 144 - j, iv,
254			    aes_nrounds[i]);
255			if (memcmp(out, in, 144))
256				return aes_selftest_fail(impl, out,
257				    in, 144, "AES-%u-CBC dec inc %u",
258				    aes_keybits[i], j);
259		}
260	}
261
262	if (outbuf[0] != 0x1a)
263		return aes_selftest_fail(impl, outbuf,
264		    (const uint8_t[1]){0x1a}, 1,
265		    "AES-CBC overrun preceding");
266	if (outbuf[145] != 0x1a)
267		return aes_selftest_fail(impl, outbuf + 145,
268		    (const uint8_t[1]){0x1a}, 1,
269		    "AES-CBC overrun following");
270
271	/* Success!  */
272	return 0;
273}
274
275static int
276aes_selftest_encdec_xts(const struct aes_impl *impl)
277{
278	uint64_t blkno[3] = { 0, 1, 0xff };
279	static const uint8_t expected[3][144] = {
280		[0] = {
281			/* IEEE P1619-D16, XTS-AES-128, Vector 4, truncated */
282			0x27,0xa7,0x47,0x9b,0xef,0xa1,0xd4,0x76,
283			0x48,0x9f,0x30,0x8c,0xd4,0xcf,0xa6,0xe2,
284			0xa9,0x6e,0x4b,0xbe,0x32,0x08,0xff,0x25,
285			0x28,0x7d,0xd3,0x81,0x96,0x16,0xe8,0x9c,
286			0xc7,0x8c,0xf7,0xf5,0xe5,0x43,0x44,0x5f,
287			0x83,0x33,0xd8,0xfa,0x7f,0x56,0x00,0x00,
288			0x05,0x27,0x9f,0xa5,0xd8,0xb5,0xe4,0xad,
289			0x40,0xe7,0x36,0xdd,0xb4,0xd3,0x54,0x12,
290			0x32,0x80,0x63,0xfd,0x2a,0xab,0x53,0xe5,
291			0xea,0x1e,0x0a,0x9f,0x33,0x25,0x00,0xa5,
292			0xdf,0x94,0x87,0xd0,0x7a,0x5c,0x92,0xcc,
293			0x51,0x2c,0x88,0x66,0xc7,0xe8,0x60,0xce,
294			0x93,0xfd,0xf1,0x66,0xa2,0x49,0x12,0xb4,
295			0x22,0x97,0x61,0x46,0xae,0x20,0xce,0x84,
296			0x6b,0xb7,0xdc,0x9b,0xa9,0x4a,0x76,0x7a,
297			0xae,0xf2,0x0c,0x0d,0x61,0xad,0x02,0x65,
298			0x5e,0xa9,0x2d,0xc4,0xc4,0xe4,0x1a,0x89,
299			0x52,0xc6,0x51,0xd3,0x31,0x74,0xbe,0x51,
300		},
301		[1] = {
302		},
303		[2] = {
304			/* IEEE P1619-D16, XTS-AES-256, Vector 10, truncated */
305			0x1c,0x3b,0x3a,0x10,0x2f,0x77,0x03,0x86,
306			0xe4,0x83,0x6c,0x99,0xe3,0x70,0xcf,0x9b,
307			0xea,0x00,0x80,0x3f,0x5e,0x48,0x23,0x57,
308			0xa4,0xae,0x12,0xd4,0x14,0xa3,0xe6,0x3b,
309			0x5d,0x31,0xe2,0x76,0xf8,0xfe,0x4a,0x8d,
310			0x66,0xb3,0x17,0xf9,0xac,0x68,0x3f,0x44,
311			0x68,0x0a,0x86,0xac,0x35,0xad,0xfc,0x33,
312			0x45,0xbe,0xfe,0xcb,0x4b,0xb1,0x88,0xfd,
313			0x57,0x76,0x92,0x6c,0x49,0xa3,0x09,0x5e,
314			0xb1,0x08,0xfd,0x10,0x98,0xba,0xec,0x70,
315			0xaa,0xa6,0x69,0x99,0xa7,0x2a,0x82,0xf2,
316			0x7d,0x84,0x8b,0x21,0xd4,0xa7,0x41,0xb0,
317			0xc5,0xcd,0x4d,0x5f,0xff,0x9d,0xac,0x89,
318			0xae,0xba,0x12,0x29,0x61,0xd0,0x3a,0x75,
319			0x71,0x23,0xe9,0x87,0x0f,0x8a,0xcf,0x10,
320			0x00,0x02,0x08,0x87,0x89,0x14,0x29,0xca,
321			0x2a,0x3e,0x7a,0x7d,0x7d,0xf7,0xb1,0x03,
322			0x55,0x16,0x5c,0x8b,0x9a,0x6d,0x0a,0x7d,
323		},
324	};
325	static const uint8_t key1[32] = {
326		0x27,0x18,0x28,0x18,0x28,0x45,0x90,0x45,
327		0x23,0x53,0x60,0x28,0x74,0x71,0x35,0x26,
328		0x62,0x49,0x77,0x57,0x24,0x70,0x93,0x69,
329		0x99,0x59,0x57,0x49,0x66,0x96,0x76,0x27,
330	};
331	static const uint8_t key2[32] = {
332		0x31,0x41,0x59,0x26,0x53,0x58,0x97,0x93,
333		0x23,0x84,0x62,0x64,0x33,0x83,0x27,0x95,
334		0x02,0x88,0x41,0x97,0x16,0x93,0x99,0x37,
335		0x51,0x05,0x82,0x09,0x74,0x94,0x45,0x92,
336	};
337	struct aesenc enc;
338	struct aesdec dec;
339	uint8_t in[144];
340	uint8_t outbuf[146] = { [0] = 0x1a, [145] = 0x1a }, *out = outbuf + 1;
341	uint8_t blkno_buf[16];
342	uint8_t iv0[16], iv[16];
343	unsigned i;
344
345	for (i = 0; i < 144; i++)
346		in[i] = i;
347
348	for (i = 0; i < 3; i++) {
349		if (i == 1)	/* XXX missing AES-192 test vector */
350			continue;
351
352		/* Format the data unit sequence number.  */
353		memset(blkno_buf, 0, sizeof blkno_buf);
354		le64enc(blkno_buf, blkno[i]);
355
356		/* Generate the tweak.  */
357		impl->ai_setenckey(&enc, key2, aes_nrounds[i]);
358		impl->ai_enc(&enc, blkno_buf, iv0, aes_nrounds[i]);
359
360		/* Load the data encryption key.  */
361		impl->ai_setenckey(&enc, key1, aes_nrounds[i]);
362		impl->ai_setdeckey(&dec, key1, aes_nrounds[i]);
363
364		/* Try one swell foop.  */
365		memcpy(iv, iv0, 16);
366		impl->ai_xts_enc(&enc, in, out, 144, iv, aes_nrounds[i]);
367		if (memcmp(out, expected[i], 144))
368			return aes_selftest_fail(impl, out, expected[i], 144,
369			    "AES-%u-XTS enc", aes_keybits[i]);
370
371		memcpy(iv, iv0, 16);
372		impl->ai_xts_dec(&dec, out, out, 144, iv, aes_nrounds[i]);
373		if (memcmp(out, in, 144))
374			return aes_selftest_fail(impl, out, in, 144,
375			    "AES-%u-XTS dec", aes_keybits[i]);
376
377		/* Try incrementally, with IV update.  */
378		memcpy(iv, iv0, 16);
379		impl->ai_xts_enc(&enc, in, out, 16, iv, aes_nrounds[i]);
380		impl->ai_xts_enc(&enc, in + 16, out + 16, 128, iv,
381		    aes_nrounds[i]);
382		if (memcmp(out, expected[i], 144))
383			return aes_selftest_fail(impl, out, expected[i], 144,
384			    "AES-%u-XTS enc incremental", aes_keybits[i]);
385
386		memcpy(iv, iv0, 16);
387		impl->ai_xts_dec(&dec, out, out, 128, iv, aes_nrounds[i]);
388		impl->ai_xts_dec(&dec, out + 128, out + 128, 16, iv,
389		    aes_nrounds[i]);
390		if (memcmp(out, in, 144))
391			return aes_selftest_fail(impl, out, in, 144,
392			    "AES-%u-XTS dec incremental", aes_keybits[i]);
393	}
394
395	if (outbuf[0] != 0x1a)
396		return aes_selftest_fail(impl, outbuf,
397		    (const uint8_t[1]){0x1a}, 1,
398		    "AES-XTS overrun preceding");
399	if (outbuf[145] != 0x1a)
400		return aes_selftest_fail(impl, outbuf + 145,
401		    (const uint8_t[1]){0x1a}, 1,
402		    "AES-XTS overrun following");
403
404	/* Success!  */
405	return 0;
406}
407
408static int
409aes_selftest_cbcmac(const struct aes_impl *impl)
410{
411	static const uint8_t m[48] = {
412		0x00,0x01,0x02,0x03, 0x04,0x05,0x06,0x07,
413		0x08,0x09,0x0a,0x0b, 0x0c,0x0d,0x0e,0x0f,
414		0x10,0x11,0x12,0x13, 0x14,0x15,0x16,0x17,
415		0x18,0x19,0x1a,0x1b, 0x1c,0x1d,0x1e,0x1f,
416		0x20,0x21,0x22,0x23, 0x24,0x25,0x26,0x27,
417		0x28,0x29,0x2a,0x2b, 0x2c,0x2d,0x2e,0x2f,
418	};
419	static uint8_t auth16[16] = {
420		0x7a,0xca,0x0f,0xd9, 0xbc,0xd6,0xec,0x7c,
421		0x9f,0x97,0x46,0x66, 0x16,0xe6,0xa2,0x82,
422	};
423	static uint8_t auth48[16] = {
424		0x26,0x9a,0xe5,0xfc, 0x8c,0x53,0x0f,0xf7,
425		0x6b,0xd9,0xec,0x05, 0x40,0xf7,0x35,0x13,
426	};
427	static const uint8_t key[16];
428	struct aesenc enc;
429	uint8_t auth[16];
430	const unsigned nr = AES_128_NROUNDS;
431
432	memset(auth, 0, sizeof auth);
433
434	impl->ai_setenckey(&enc, key, nr);
435	impl->ai_cbcmac_update1(&enc, m, 16, auth, nr);
436	if (memcmp(auth, auth16, 16))
437		return aes_selftest_fail(impl, auth, auth16, 16,
438		    "AES-128 CBC-MAC (16)");
439	impl->ai_cbcmac_update1(&enc, m + 16, 32, auth, nr);
440	if (memcmp(auth, auth48, 16))
441		return aes_selftest_fail(impl, auth, auth48, 16,
442		    "AES-128 CBC-MAC (48)");
443
444	return 0;
445}
446
447static int
448aes_selftest_ccm(const struct aes_impl *impl)
449{
450	static const uint8_t ptxt[48] = {
451		0x00,0x01,0x02,0x03, 0x04,0x05,0x06,0x07,
452		0x08,0x09,0x0a,0x0b, 0x0c,0x0d,0x0e,0x0f,
453		0x10,0x11,0x12,0x13, 0x14,0x15,0x16,0x17,
454		0x18,0x19,0x1a,0x1b, 0x1c,0x1d,0x1e,0x1f,
455		0x20,0x21,0x22,0x23, 0x24,0x25,0x26,0x27,
456		0x28,0x29,0x2a,0x2b, 0x2c,0x2d,0x2e,0x2f,
457	};
458	static uint8_t ctr0[16] = {
459		/* L - 1, #octets in counter */
460		[0] = 0x01,
461		/* nonce */
462		[1] = 0,1,2,3,4,5,6,7,8,9,10,11,12,
463		[14] = 0,
464		[15] = 254,
465	};
466	static uint8_t authctr16[32] = {
467		/* authentication tag */
468		0x7a,0xca,0x0f,0xd9, 0xbc,0xd6,0xec,0x7c,
469		0x9f,0x97,0x46,0x66, 0x16,0xe6,0xa2,0x82,
470
471		/* L - 1, #octets in counter */
472		[16 + 0] = 0x01,
473		/* nonce */
474		[16 + 1] = 0,1,2,3,4,5,6,7,8,9,10,11,12,
475		[16 + 14] = 0,
476		[16 + 15] = 255,
477	};
478	static uint8_t authctr48[32] = {
479		/* authentication tag */
480		0x26,0x9a,0xe5,0xfc, 0x8c,0x53,0x0f,0xf7,
481		0x6b,0xd9,0xec,0x05, 0x40,0xf7,0x35,0x13,
482
483		/* L - 1, #octets in counter */
484		[16 + 0] = 0x01,
485		/* nonce */
486		[16 + 1] = 0,1,2,3,4,5,6,7,8,9,10,11,12,
487		[16 + 14] = 1,
488		[16 + 15] = 1,
489	};
490	static uint8_t ctxt[48] = {
491		0xa4,0x35,0x07,0x5c, 0xdf,0x2d,0x67,0xd3,
492		0xbf,0x1f,0x36,0x93, 0xe4,0x43,0xcb,0x1e,
493		0xa0,0x82,0x9c,0x2a, 0x0b,0x66,0x46,0x05,
494		0x80,0x17,0x71,0xa1, 0x7b,0x09,0xa7,0xd5,
495		0x91,0x0b,0xb3,0x96, 0xd1,0x5e,0x29,0x3e,
496		0x74,0x94,0x74,0x6d, 0x6b,0x25,0x43,0x8c,
497	};
498	static const uint8_t key[16];
499	struct aesenc enc;
500	uint8_t authctr[32];
501	uint8_t buf[48];
502	const unsigned nr = AES_128_NROUNDS;
503	int result = 0;
504
505	impl->ai_setenckey(&enc, key, nr);
506
507	memset(authctr, 0, 16);
508	memcpy(authctr + 16, ctr0, 16);
509
510	impl->ai_ccm_enc1(&enc, ptxt, buf, 16, authctr, nr);
511	if (memcmp(authctr, authctr16, 32))
512		result |= aes_selftest_fail(impl, authctr, authctr16, 32,
513		    "AES-128 CCM encrypt auth/ctr (16)");
514	impl->ai_ccm_enc1(&enc, ptxt + 16, buf + 16, 32, authctr, nr);
515	if (memcmp(authctr, authctr48, 32))
516		result |= aes_selftest_fail(impl, authctr, authctr48, 32,
517		    "AES-128 CCM encrypt auth/ctr (48)");
518
519	if (memcmp(buf, ctxt, 32))
520		result |= aes_selftest_fail(impl, buf, ctxt, 48,
521		    "AES-128 CCM ciphertext");
522
523	memset(authctr, 0, 16);
524	memcpy(authctr + 16, ctr0, 16);
525
526	impl->ai_ccm_dec1(&enc, ctxt, buf, 16, authctr, nr);
527	if (memcmp(authctr, authctr16, 32))
528		result |= aes_selftest_fail(impl, authctr, authctr16, 32,
529		    "AES-128 CCM decrypt auth/ctr (16)");
530	impl->ai_ccm_dec1(&enc, ctxt + 16, buf + 16, 32, authctr, nr);
531	if (memcmp(authctr, authctr48, 32))
532		result |= aes_selftest_fail(impl, authctr, authctr48, 32,
533		    "AES-128 CCM decrypt auth/ctr (48)");
534
535	if (memcmp(buf, ptxt, 32))
536		result |= aes_selftest_fail(impl, buf, ptxt, 48,
537		    "AES-128 CCM plaintext");
538
539	return result;
540}
541
542int
543aes_selftest(const struct aes_impl *impl)
544{
545	int result = 0;
546
547	if (impl->ai_probe())
548		return -1;
549
550	if (aes_selftest_encdec(impl))
551		result = -1;
552	if (aes_selftest_encdec_cbc(impl))
553		result = -1;
554	if (aes_selftest_encdec_xts(impl))
555		result = -1;
556	if (aes_selftest_cbcmac(impl))
557		result = -1;
558	if (aes_selftest_ccm(impl))
559		result = -1;
560
561	return result;
562}
563