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