Home | History | Annotate | Line # | Download | only in aes
aes_selftest.c revision 1.4
      1 /*	$NetBSD: aes_selftest.c,v 1.4 2020/07/25 22:27:53 riastradh 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.4 2020/07/25 22:27:53 riastradh 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 
     45 static void
     46 hexdump(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 
     71 static const unsigned aes_keybytes[] __unused = { 16, 24, 32 };
     72 static const unsigned aes_keybits[] __unused = { 128, 192, 256 };
     73 static 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 
     83 static int
     84 aes_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 folllowing");
    137 
    138 	/* Success!  */
    139 	return 0;
    140 }
    141 
    142 static int
    143 aes_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;
    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 		memcpy(iv, iv0, 16);
    241 		impl->ai_cbc_enc(&enc, in, out, 16, iv, aes_nrounds[i]);
    242 		impl->ai_cbc_enc(&enc, in + 16, out + 16, 128, iv,
    243 		    aes_nrounds[i]);
    244 		if (memcmp(out, expected[i], 144))
    245 			return aes_selftest_fail(impl, out, expected[i], 144,
    246 			    "AES-%u-CBC enc incremental", aes_keybits[i]);
    247 
    248 		memcpy(iv, iv0, 16);
    249 		impl->ai_cbc_dec(&dec, out, out, 128, iv, aes_nrounds[i]);
    250 		impl->ai_cbc_dec(&dec, out + 128, out + 128, 16, iv,
    251 		    aes_nrounds[i]);
    252 		if (memcmp(out, in, 144))
    253 			return aes_selftest_fail(impl, out, in, 144,
    254 			    "AES-%u-CBC dec incremental", aes_keybits[i]);
    255 	}
    256 
    257 	if (outbuf[0] != 0x1a)
    258 		return aes_selftest_fail(impl, outbuf,
    259 		    (const uint8_t[1]){0x1a}, 1,
    260 		    "AES-CBC overrun preceding");
    261 	if (outbuf[145] != 0x1a)
    262 		return aes_selftest_fail(impl, outbuf + 145,
    263 		    (const uint8_t[1]){0x1a}, 1,
    264 		    "AES-CBC overrun following");
    265 
    266 	/* Success!  */
    267 	return 0;
    268 }
    269 
    270 static int
    271 aes_selftest_encdec_xts(const struct aes_impl *impl)
    272 {
    273 	uint64_t blkno[3] = { 0, 1, 0xff };
    274 	static const uint8_t expected[3][144] = {
    275 		[0] = {
    276 			/* IEEE P1619-D16, XTS-AES-128, Vector 4, truncated */
    277 			0x27,0xa7,0x47,0x9b,0xef,0xa1,0xd4,0x76,
    278 			0x48,0x9f,0x30,0x8c,0xd4,0xcf,0xa6,0xe2,
    279 			0xa9,0x6e,0x4b,0xbe,0x32,0x08,0xff,0x25,
    280 			0x28,0x7d,0xd3,0x81,0x96,0x16,0xe8,0x9c,
    281 			0xc7,0x8c,0xf7,0xf5,0xe5,0x43,0x44,0x5f,
    282 			0x83,0x33,0xd8,0xfa,0x7f,0x56,0x00,0x00,
    283 			0x05,0x27,0x9f,0xa5,0xd8,0xb5,0xe4,0xad,
    284 			0x40,0xe7,0x36,0xdd,0xb4,0xd3,0x54,0x12,
    285 			0x32,0x80,0x63,0xfd,0x2a,0xab,0x53,0xe5,
    286 			0xea,0x1e,0x0a,0x9f,0x33,0x25,0x00,0xa5,
    287 			0xdf,0x94,0x87,0xd0,0x7a,0x5c,0x92,0xcc,
    288 			0x51,0x2c,0x88,0x66,0xc7,0xe8,0x60,0xce,
    289 			0x93,0xfd,0xf1,0x66,0xa2,0x49,0x12,0xb4,
    290 			0x22,0x97,0x61,0x46,0xae,0x20,0xce,0x84,
    291 			0x6b,0xb7,0xdc,0x9b,0xa9,0x4a,0x76,0x7a,
    292 			0xae,0xf2,0x0c,0x0d,0x61,0xad,0x02,0x65,
    293 			0x5e,0xa9,0x2d,0xc4,0xc4,0xe4,0x1a,0x89,
    294 			0x52,0xc6,0x51,0xd3,0x31,0x74,0xbe,0x51,
    295 		},
    296 		[1] = {
    297 		},
    298 		[2] = {
    299 			/* IEEE P1619-D16, XTS-AES-256, Vector 10, truncated */
    300 			0x1c,0x3b,0x3a,0x10,0x2f,0x77,0x03,0x86,
    301 			0xe4,0x83,0x6c,0x99,0xe3,0x70,0xcf,0x9b,
    302 			0xea,0x00,0x80,0x3f,0x5e,0x48,0x23,0x57,
    303 			0xa4,0xae,0x12,0xd4,0x14,0xa3,0xe6,0x3b,
    304 			0x5d,0x31,0xe2,0x76,0xf8,0xfe,0x4a,0x8d,
    305 			0x66,0xb3,0x17,0xf9,0xac,0x68,0x3f,0x44,
    306 			0x68,0x0a,0x86,0xac,0x35,0xad,0xfc,0x33,
    307 			0x45,0xbe,0xfe,0xcb,0x4b,0xb1,0x88,0xfd,
    308 			0x57,0x76,0x92,0x6c,0x49,0xa3,0x09,0x5e,
    309 			0xb1,0x08,0xfd,0x10,0x98,0xba,0xec,0x70,
    310 			0xaa,0xa6,0x69,0x99,0xa7,0x2a,0x82,0xf2,
    311 			0x7d,0x84,0x8b,0x21,0xd4,0xa7,0x41,0xb0,
    312 			0xc5,0xcd,0x4d,0x5f,0xff,0x9d,0xac,0x89,
    313 			0xae,0xba,0x12,0x29,0x61,0xd0,0x3a,0x75,
    314 			0x71,0x23,0xe9,0x87,0x0f,0x8a,0xcf,0x10,
    315 			0x00,0x02,0x08,0x87,0x89,0x14,0x29,0xca,
    316 			0x2a,0x3e,0x7a,0x7d,0x7d,0xf7,0xb1,0x03,
    317 			0x55,0x16,0x5c,0x8b,0x9a,0x6d,0x0a,0x7d,
    318 		},
    319 	};
    320 	static const uint8_t key1[32] = {
    321 		0x27,0x18,0x28,0x18,0x28,0x45,0x90,0x45,
    322 		0x23,0x53,0x60,0x28,0x74,0x71,0x35,0x26,
    323 		0x62,0x49,0x77,0x57,0x24,0x70,0x93,0x69,
    324 		0x99,0x59,0x57,0x49,0x66,0x96,0x76,0x27,
    325 	};
    326 	static const uint8_t key2[32] = {
    327 		0x31,0x41,0x59,0x26,0x53,0x58,0x97,0x93,
    328 		0x23,0x84,0x62,0x64,0x33,0x83,0x27,0x95,
    329 		0x02,0x88,0x41,0x97,0x16,0x93,0x99,0x37,
    330 		0x51,0x05,0x82,0x09,0x74,0x94,0x45,0x92,
    331 	};
    332 	struct aesenc enc;
    333 	struct aesdec dec;
    334 	uint8_t in[144];
    335 	uint8_t outbuf[146] = { [0] = 0x1a, [145] = 0x1a }, *out = outbuf + 1;
    336 	uint8_t blkno_buf[16];
    337 	uint8_t iv0[16], iv[16];
    338 	unsigned i;
    339 
    340 	for (i = 0; i < 144; i++)
    341 		in[i] = i;
    342 
    343 	for (i = 0; i < 3; i++) {
    344 		if (i == 1)	/* XXX missing AES-192 test vector */
    345 			continue;
    346 
    347 		/* Format the data unit sequence number.  */
    348 		memset(blkno_buf, 0, sizeof blkno_buf);
    349 		le64enc(blkno_buf, blkno[i]);
    350 
    351 		/* Generate the tweak.  */
    352 		impl->ai_setenckey(&enc, key2, aes_nrounds[i]);
    353 		impl->ai_enc(&enc, blkno_buf, iv0, aes_nrounds[i]);
    354 
    355 		/* Load the data encryption key.  */
    356 		impl->ai_setenckey(&enc, key1, aes_nrounds[i]);
    357 		impl->ai_setdeckey(&dec, key1, aes_nrounds[i]);
    358 
    359 		/* Try one swell foop.  */
    360 		memcpy(iv, iv0, 16);
    361 		impl->ai_xts_enc(&enc, in, out, 144, iv, aes_nrounds[i]);
    362 		if (memcmp(out, expected[i], 144))
    363 			return aes_selftest_fail(impl, out, expected[i], 144,
    364 			    "AES-%u-XTS enc", aes_keybits[i]);
    365 
    366 		memcpy(iv, iv0, 16);
    367 		impl->ai_xts_dec(&dec, out, out, 144, iv, aes_nrounds[i]);
    368 		if (memcmp(out, in, 144))
    369 			return aes_selftest_fail(impl, out, in, 144,
    370 			    "AES-%u-XTS dec", aes_keybits[i]);
    371 
    372 		/* Try incrementally, with IV update.  */
    373 		memcpy(iv, iv0, 16);
    374 		impl->ai_xts_enc(&enc, in, out, 16, iv, aes_nrounds[i]);
    375 		impl->ai_xts_enc(&enc, in + 16, out + 16, 128, iv,
    376 		    aes_nrounds[i]);
    377 		if (memcmp(out, expected[i], 144))
    378 			return aes_selftest_fail(impl, out, expected[i], 144,
    379 			    "AES-%u-XTS enc incremental", aes_keybits[i]);
    380 
    381 		memcpy(iv, iv0, 16);
    382 		impl->ai_xts_dec(&dec, out, out, 128, iv, aes_nrounds[i]);
    383 		impl->ai_xts_dec(&dec, out + 128, out + 128, 16, iv,
    384 		    aes_nrounds[i]);
    385 		if (memcmp(out, in, 144))
    386 			return aes_selftest_fail(impl, out, in, 144,
    387 			    "AES-%u-XTS dec incremental", aes_keybits[i]);
    388 	}
    389 
    390 	if (outbuf[0] != 0x1a)
    391 		return aes_selftest_fail(impl, outbuf,
    392 		    (const uint8_t[1]){0x1a}, 1,
    393 		    "AES-XTS overrun preceding");
    394 	if (outbuf[145] != 0x1a)
    395 		return aes_selftest_fail(impl, outbuf + 145,
    396 		    (const uint8_t[1]){0x1a}, 1,
    397 		    "AES-XTS overrun following");
    398 
    399 	/* Success!  */
    400 	return 0;
    401 }
    402 
    403 static int
    404 aes_selftest_cbcmac(const struct aes_impl *impl)
    405 {
    406 	static const uint8_t m[48] = {
    407 		0x00,0x01,0x02,0x03, 0x04,0x05,0x06,0x07,
    408 		0x08,0x09,0x0a,0x0b, 0x0c,0x0d,0x0e,0x0f,
    409 		0x10,0x11,0x12,0x13, 0x14,0x15,0x16,0x17,
    410 		0x18,0x19,0x1a,0x1b, 0x1c,0x1d,0x1e,0x1f,
    411 		0x20,0x21,0x22,0x23, 0x24,0x25,0x26,0x27,
    412 		0x28,0x29,0x2a,0x2b, 0x2c,0x2d,0x2e,0x2f,
    413 	};
    414 	static uint8_t auth16[16] = {
    415 		0x7a,0xca,0x0f,0xd9, 0xbc,0xd6,0xec,0x7c,
    416 		0x9f,0x97,0x46,0x66, 0x16,0xe6,0xa2,0x82,
    417 	};
    418 	static uint8_t auth48[16] = {
    419 		0x26,0x9a,0xe5,0xfc, 0x8c,0x53,0x0f,0xf7,
    420 		0x6b,0xd9,0xec,0x05, 0x40,0xf7,0x35,0x13,
    421 	};
    422 	static const uint8_t key[16];
    423 	struct aesenc enc;
    424 	uint8_t auth[16];
    425 	const unsigned nr = AES_128_NROUNDS;
    426 
    427 	if (impl->ai_cbcmac_update1 == NULL)
    428 		return 0;
    429 
    430 	memset(auth, 0, sizeof auth);
    431 
    432 	impl->ai_setenckey(&enc, key, nr);
    433 	impl->ai_cbcmac_update1(&enc, m, 16, auth, nr);
    434 	if (memcmp(auth, auth16, 16))
    435 		return aes_selftest_fail(impl, auth, auth16, 16,
    436 		    "AES-128 CBC-MAC (16)");
    437 	impl->ai_cbcmac_update1(&enc, m + 16, 32, auth, nr);
    438 	if (memcmp(auth, auth48, 16))
    439 		return aes_selftest_fail(impl, auth, auth48, 16,
    440 		    "AES-128 CBC-MAC (48)");
    441 
    442 	return 0;
    443 }
    444 
    445 static int
    446 aes_selftest_ccm(const struct aes_impl *impl)
    447 {
    448 	static const uint8_t ptxt[48] = {
    449 		0x00,0x01,0x02,0x03, 0x04,0x05,0x06,0x07,
    450 		0x08,0x09,0x0a,0x0b, 0x0c,0x0d,0x0e,0x0f,
    451 		0x10,0x11,0x12,0x13, 0x14,0x15,0x16,0x17,
    452 		0x18,0x19,0x1a,0x1b, 0x1c,0x1d,0x1e,0x1f,
    453 		0x20,0x21,0x22,0x23, 0x24,0x25,0x26,0x27,
    454 		0x28,0x29,0x2a,0x2b, 0x2c,0x2d,0x2e,0x2f,
    455 	};
    456 	static uint8_t ctr0[16] = {
    457 		/* L - 1, #octets in counter */
    458 		[0] = 0x01,
    459 		/* nonce */
    460 		[1] = 0,1,2,3,4,5,6,7,8,9,10,11,12,
    461 		[14] = 0,
    462 		[15] = 254,
    463 	};
    464 	static uint8_t authctr16[32] = {
    465 		/* authentication tag */
    466 		0x7a,0xca,0x0f,0xd9, 0xbc,0xd6,0xec,0x7c,
    467 		0x9f,0x97,0x46,0x66, 0x16,0xe6,0xa2,0x82,
    468 
    469 		/* L - 1, #octets in counter */
    470 		[16 + 0] = 0x01,
    471 		/* nonce */
    472 		[16 + 1] = 0,1,2,3,4,5,6,7,8,9,10,11,12,
    473 		[16 + 14] = 0,
    474 		[16 + 15] = 255,
    475 	};
    476 	static uint8_t authctr48[32] = {
    477 		/* authentication tag */
    478 		0x26,0x9a,0xe5,0xfc, 0x8c,0x53,0x0f,0xf7,
    479 		0x6b,0xd9,0xec,0x05, 0x40,0xf7,0x35,0x13,
    480 
    481 		/* L - 1, #octets in counter */
    482 		[16 + 0] = 0x01,
    483 		/* nonce */
    484 		[16 + 1] = 0,1,2,3,4,5,6,7,8,9,10,11,12,
    485 		[16 + 14] = 1,
    486 		[16 + 15] = 1,
    487 	};
    488 	static uint8_t ctxt[48] = {
    489 		0xa4,0x35,0x07,0x5c, 0xdf,0x2d,0x67,0xd3,
    490 		0xbf,0x1f,0x36,0x93, 0xe4,0x43,0xcb,0x1e,
    491 		0xa0,0x82,0x9c,0x2a, 0x0b,0x66,0x46,0x05,
    492 		0x80,0x17,0x71,0xa1, 0x7b,0x09,0xa7,0xd5,
    493 		0x91,0x0b,0xb3,0x96, 0xd1,0x5e,0x29,0x3e,
    494 		0x74,0x94,0x74,0x6d, 0x6b,0x25,0x43,0x8c,
    495 	};
    496 	static const uint8_t key[16];
    497 	struct aesenc enc;
    498 	uint8_t authctr[32];
    499 	uint8_t buf[48];
    500 	const unsigned nr = AES_128_NROUNDS;
    501 	int result = 0;
    502 
    503 	if (impl->ai_ccm_enc1 == NULL)
    504 		return 0;
    505 
    506 	impl->ai_setenckey(&enc, key, nr);
    507 
    508 	memset(authctr, 0, 16);
    509 	memcpy(authctr + 16, ctr0, 16);
    510 
    511 	impl->ai_ccm_enc1(&enc, ptxt, buf, 16, authctr, nr);
    512 	if (memcmp(authctr, authctr16, 32))
    513 		result |= aes_selftest_fail(impl, authctr, authctr16, 32,
    514 		    "AES-128 CCM encrypt auth/ctr (16)");
    515 	impl->ai_ccm_enc1(&enc, ptxt + 16, buf + 16, 32, authctr, nr);
    516 	if (memcmp(authctr, authctr48, 32))
    517 		result |= aes_selftest_fail(impl, authctr, authctr48, 32,
    518 		    "AES-128 CCM encrypt auth/ctr (48)");
    519 
    520 	if (memcmp(buf, ctxt, 32))
    521 		result |= aes_selftest_fail(impl, buf, ctxt, 48,
    522 		    "AES-128 CCM ciphertext");
    523 
    524 	if (impl->ai_ccm_dec1 == NULL)
    525 		return result;
    526 
    527 	memset(authctr, 0, 16);
    528 	memcpy(authctr + 16, ctr0, 16);
    529 
    530 	impl->ai_ccm_dec1(&enc, ctxt, buf, 16, authctr, nr);
    531 	if (memcmp(authctr, authctr16, 32))
    532 		result |= aes_selftest_fail(impl, authctr, authctr16, 32,
    533 		    "AES-128 CCM decrypt auth/ctr (16)");
    534 	impl->ai_ccm_dec1(&enc, ctxt + 16, buf + 16, 32, authctr, nr);
    535 	if (memcmp(authctr, authctr48, 32))
    536 		result |= aes_selftest_fail(impl, authctr, authctr48, 32,
    537 		    "AES-128 CCM decrypt auth/ctr (48)");
    538 
    539 	if (memcmp(buf, ptxt, 32))
    540 		result |= aes_selftest_fail(impl, buf, ptxt, 48,
    541 		    "AES-128 CCM plaintext");
    542 
    543 	return result;
    544 }
    545 
    546 int
    547 aes_selftest(const struct aes_impl *impl)
    548 {
    549 	int result = 0;
    550 
    551 	if (impl->ai_probe())
    552 		return -1;
    553 
    554 	if (aes_selftest_encdec(impl))
    555 		result = -1;
    556 	if (aes_selftest_encdec_cbc(impl))
    557 		result = -1;
    558 	if (aes_selftest_encdec_xts(impl))
    559 		result = -1;
    560 	if (aes_selftest_cbcmac(impl))
    561 		result = -1;
    562 	if (aes_selftest_ccm(impl))
    563 		result = -1;
    564 
    565 	return result;
    566 }
    567