Home | History | Annotate | Line # | Download | only in aes
aes_selftest.c revision 1.1
      1 /*	$NetBSD: aes_selftest.c,v 1.1 2020/06/29 23:27:52 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.1 2020/06/29 23:27:52 riastradh Exp $");
     31 
     32 #include <sys/types.h>
     33 #include <sys/systm.h>
     34 
     35 #include <lib/libkern/libkern.h>
     36 
     37 #include <crypto/aes/aes.h>
     38 
     39 static const unsigned aes_keybytes[] __unused = { 16, 24, 32 };
     40 static const unsigned aes_keybits[] __unused = { 128, 192, 256 };
     41 static const unsigned aes_nrounds[] = { 10, 12, 14 };
     42 
     43 #define	aes_selftest_fail(impl, actual, expected, nbytes, fmt, args...)	      \
     44 ({									      \
     45 	printf("%s "fmt": self-test failed\n", (impl)->ai_name, ##args);      \
     46 	hexdump(printf, "was", (actual), (nbytes));			      \
     47 	hexdump(printf, "expected", (expected), (nbytes));		      \
     48 	-1;								      \
     49 })
     50 
     51 static int
     52 aes_selftest_encdec(const struct aes_impl *impl)
     53 {
     54 	/*
     55 	 * head -c 16 < /dev/zero | openssl enc -aes-{128,192,256}-ecb
     56 	 *     -nopad -K 000102030405060708090a0b0c0d... | hexdump -C
     57 	 */
     58 	static const uint8_t expected[3][16] = {
     59 		[0] = {
     60 			0xc6,0xa1,0x3b,0x37,0x87,0x8f,0x5b,0x82,
     61 			0x6f,0x4f,0x81,0x62,0xa1,0xc8,0xd8,0x79,
     62 		},
     63 		[1] = {
     64 			0x91,0x62,0x51,0x82,0x1c,0x73,0xa5,0x22,
     65 			0xc3,0x96,0xd6,0x27,0x38,0x01,0x96,0x07,
     66 		},
     67 		[2] = {
     68 			0xf2,0x90,0x00,0xb6,0x2a,0x49,0x9f,0xd0,
     69 			0xa9,0xf3,0x9a,0x6a,0xdd,0x2e,0x77,0x80,
     70 		},
     71 	};
     72 	struct aesenc enc;
     73 	struct aesdec dec;
     74 	uint8_t key[32];
     75 	uint8_t in[16];
     76 	uint8_t outbuf[18] = { [0] = 0x1a, [17] = 0x1a }, *out = outbuf + 1;
     77 	unsigned i;
     78 
     79 	for (i = 0; i < 32; i++)
     80 		key[i] = i;
     81 	for (i = 0; i < 16; i++)
     82 		in[i] = 0;
     83 
     84 	for (i = 0; i < 3; i++) {
     85 		impl->ai_setenckey(&enc, key, aes_nrounds[i]);
     86 		impl->ai_setdeckey(&dec, key, aes_nrounds[i]);
     87 		impl->ai_enc(&enc, in, out, aes_nrounds[i]);
     88 		if (memcmp(out, expected[i], 16))
     89 			return aes_selftest_fail(impl, out, expected[i], 16,
     90 			    "AES-%u enc", aes_keybits[i]);
     91 		impl->ai_dec(&dec, out, out, aes_nrounds[i]);
     92 		if (memcmp(out, in, 16))
     93 			return aes_selftest_fail(impl, out, in, 16,
     94 			    "AES-%u dec", aes_keybits[i]);
     95 	}
     96 
     97 	if (outbuf[0] != 0x1a)
     98 		return aes_selftest_fail(impl, outbuf,
     99 		    (const uint8_t[1]){0x1a}, 1,
    100 		    "AES overrun preceding");
    101 	if (outbuf[17] != 0x1a)
    102 		return aes_selftest_fail(impl, outbuf + 17,
    103 		    (const uint8_t[1]){0x1a}, 1,
    104 		    "AES overrun folllowing");
    105 
    106 	/* Success!  */
    107 	return 0;
    108 }
    109 
    110 static int
    111 aes_selftest_encdec_cbc(const struct aes_impl *impl)
    112 {
    113 	static const uint8_t expected[3][144] = {
    114 		[0] = {
    115 			0xfe,0xf1,0xa8,0xb6,0x25,0xf0,0xc4,0x3a,
    116 			0x71,0x08,0xb6,0x23,0xa6,0xfb,0x90,0xca,
    117 			0x9e,0x64,0x6d,0x95,0xb5,0xf5,0x41,0x24,
    118 			0xd2,0xe6,0x60,0xda,0x6c,0x69,0xc4,0xa0,
    119 			0x4d,0xaa,0x94,0xf6,0x66,0x1e,0xaa,0x85,
    120 			0x68,0xc5,0x6b,0x2e,0x77,0x7a,0x68,0xff,
    121 			0x45,0x15,0x45,0xc5,0x9c,0xbb,0x3a,0x23,
    122 			0x08,0x3a,0x06,0xdd,0xc0,0x52,0xd2,0xb7,
    123 			0x47,0xaa,0x1c,0xc7,0xb5,0xa9,0x7d,0x04,
    124 			0x60,0x67,0x78,0xf6,0xb9,0xba,0x26,0x84,
    125 			0x45,0x72,0x44,0xed,0xa3,0xd3,0xa0,0x3f,
    126 			0x19,0xee,0x3f,0x94,0x59,0x52,0x4b,0x13,
    127 			0xfd,0x81,0xcc,0xf9,0xf2,0x29,0xd7,0xec,
    128 			0xde,0x03,0x56,0x01,0x4a,0x19,0x86,0xc0,
    129 			0x87,0xce,0xe1,0xcc,0x13,0xf1,0x2e,0xda,
    130 			0x3f,0xfe,0xa4,0x64,0xe7,0x48,0xb4,0x7b,
    131 			0x73,0x62,0x5a,0x80,0x5e,0x01,0x20,0xa5,
    132 			0x0a,0xd7,0x98,0xa7,0xd9,0x8b,0xff,0xc2,
    133 		},
    134 		[1] = {
    135 			0xa6,0x87,0xf0,0x92,0x68,0xc8,0xd6,0x42,
    136 			0xa8,0x83,0x1c,0x92,0x65,0x8c,0xd9,0xfe,
    137 			0x0b,0x1a,0xc6,0x96,0x27,0x44,0xd4,0x14,
    138 			0xfc,0xe7,0x85,0xb2,0x71,0xc7,0x11,0x39,
    139 			0xed,0x36,0xd3,0x5c,0xa7,0xf7,0x3d,0xc9,
    140 			0xa2,0x54,0x8b,0xb4,0xfa,0xe8,0x21,0xf9,
    141 			0xfd,0x6a,0x42,0x85,0xde,0x66,0xd4,0xc0,
    142 			0xa7,0xd3,0x5b,0xe1,0xe6,0xac,0xea,0xf9,
    143 			0xa3,0x15,0x68,0xf4,0x66,0x4c,0x23,0x75,
    144 			0x58,0xba,0x7f,0xca,0xbf,0x40,0x56,0x79,
    145 			0x2f,0xbf,0xdf,0x5f,0x56,0xcb,0xa0,0xe4,
    146 			0x22,0x65,0x6a,0x8f,0x4f,0xff,0x11,0x6b,
    147 			0x57,0xeb,0x45,0xeb,0x9d,0x7f,0xfe,0x9c,
    148 			0x8b,0x30,0xa8,0xb0,0x7e,0x27,0xf8,0xbc,
    149 			0x1f,0xf8,0x15,0x34,0x36,0x4f,0x46,0x73,
    150 			0x81,0x90,0x4b,0x4b,0x46,0x4d,0x01,0x45,
    151 			0xa1,0xc3,0x0b,0xa8,0x5a,0xab,0xc1,0x88,
    152 			0x66,0xc8,0x1a,0x94,0x17,0x64,0x6f,0xf4,
    153 		},
    154 		[2] = {
    155 			0x22,0x4c,0x27,0xf4,0xba,0x37,0x8b,0x27,
    156 			0xd3,0xd6,0x88,0x8a,0xdc,0xed,0x64,0x42,
    157 			0x19,0x60,0x31,0x09,0xf3,0x72,0xd2,0xc2,
    158 			0xd3,0xe3,0xff,0xce,0xc5,0x03,0x9f,0xce,
    159 			0x99,0x49,0x8a,0xf2,0xe1,0xba,0xe2,0xa8,
    160 			0xd7,0x32,0x07,0x2d,0xb0,0xb3,0xbc,0x67,
    161 			0x32,0x9a,0x3e,0x7d,0x16,0x23,0xe7,0x24,
    162 			0x84,0xe1,0x15,0x03,0x9c,0xa2,0x7a,0x95,
    163 			0x34,0xa8,0x04,0x4e,0x79,0x31,0x50,0x26,
    164 			0x76,0xd1,0x10,0xce,0xec,0x13,0xf7,0xfb,
    165 			0x94,0x6b,0x76,0x50,0x5f,0xb2,0x3e,0x7c,
    166 			0xbe,0x97,0xe7,0x13,0x06,0x9e,0x2d,0xc4,
    167 			0x46,0x65,0xa7,0x69,0x37,0x07,0x25,0x37,
    168 			0xe5,0x48,0x51,0xa8,0x58,0xe8,0x4d,0x7c,
    169 			0xb5,0xbe,0x25,0x13,0xbc,0x11,0xc2,0xde,
    170 			0xdb,0x00,0xef,0x1c,0x1d,0xeb,0xe3,0x49,
    171 			0x1c,0xc0,0x78,0x29,0x76,0xc0,0xde,0x3a,
    172 			0x0e,0x96,0x8f,0xea,0xd7,0x42,0x4e,0xb4,
    173 		},
    174 	};
    175 	struct aesenc enc;
    176 	struct aesdec dec;
    177 	uint8_t key[32];
    178 	uint8_t in[144];
    179 	uint8_t outbuf[146] = { [0] = 0x1a, [145] = 0x1a }, *out = outbuf + 1;
    180 	uint8_t iv0[16], iv[16];
    181 	unsigned i;
    182 
    183 	for (i = 0; i < 32; i++)
    184 		key[i] = i;
    185 	for (i = 0; i < 16; i++)
    186 		iv0[i] = 0x20 ^ i;
    187 	for (i = 0; i < 144; i++)
    188 		in[i] = 0x80 ^ i;
    189 
    190 	for (i = 0; i < 3; i++) {
    191 		impl->ai_setenckey(&enc, key, aes_nrounds[i]);
    192 		impl->ai_setdeckey(&dec, key, aes_nrounds[i]);
    193 
    194 		/* Try one swell foop.  */
    195 		memcpy(iv, iv0, 16);
    196 		impl->ai_cbc_enc(&enc, in, out, 144, iv, aes_nrounds[i]);
    197 		if (memcmp(out, expected[i], 144))
    198 			return aes_selftest_fail(impl, out, expected[i], 144,
    199 			    "AES-%u-CBC enc", aes_keybits[i]);
    200 
    201 		memcpy(iv, iv0, 16);
    202 		impl->ai_cbc_dec(&dec, out, out, 144, iv, aes_nrounds[i]);
    203 		if (memcmp(out, in, 144))
    204 			return aes_selftest_fail(impl, out, in, 144,
    205 			    "AES-%u-CBC dec", aes_keybits[i]);
    206 
    207 		/* Try incrementally, with IV update.  */
    208 		memcpy(iv, iv0, 16);
    209 		impl->ai_cbc_enc(&enc, in, out, 16, iv, aes_nrounds[i]);
    210 		impl->ai_cbc_enc(&enc, in + 16, out + 16, 128, iv,
    211 		    aes_nrounds[i]);
    212 		if (memcmp(out, expected[i], 144))
    213 			return aes_selftest_fail(impl, out, expected[i], 144,
    214 			    "AES-%u-CBC enc incremental", aes_keybits[i]);
    215 
    216 		memcpy(iv, iv0, 16);
    217 		impl->ai_cbc_dec(&dec, out, out, 128, iv, aes_nrounds[i]);
    218 		impl->ai_cbc_dec(&dec, out + 128, out + 128, 16, iv,
    219 		    aes_nrounds[i]);
    220 		if (memcmp(out, in, 144))
    221 			return aes_selftest_fail(impl, out, in, 144,
    222 			    "AES-%u-CBC dec incremental", aes_keybits[i]);
    223 	}
    224 
    225 	if (outbuf[0] != 0x1a)
    226 		return aes_selftest_fail(impl, outbuf,
    227 		    (const uint8_t[1]){0x1a}, 1,
    228 		    "AES-CBC overrun preceding");
    229 	if (outbuf[145] != 0x1a)
    230 		return aes_selftest_fail(impl, outbuf + 145,
    231 		    (const uint8_t[1]){0x1a}, 1,
    232 		    "AES-CBC overrun following");
    233 
    234 	/* Success!  */
    235 	return 0;
    236 }
    237 
    238 static int
    239 aes_selftest_encdec_xts(const struct aes_impl *impl)
    240 {
    241 	uint64_t blkno[3] = { 0, 1, 0xff };
    242 	static const uint8_t expected[3][144] = {
    243 		[0] = {
    244 			/* IEEE P1619-D16, XTS-AES-128, Vector 4, truncated */
    245 			0x27,0xa7,0x47,0x9b,0xef,0xa1,0xd4,0x76,
    246 			0x48,0x9f,0x30,0x8c,0xd4,0xcf,0xa6,0xe2,
    247 			0xa9,0x6e,0x4b,0xbe,0x32,0x08,0xff,0x25,
    248 			0x28,0x7d,0xd3,0x81,0x96,0x16,0xe8,0x9c,
    249 			0xc7,0x8c,0xf7,0xf5,0xe5,0x43,0x44,0x5f,
    250 			0x83,0x33,0xd8,0xfa,0x7f,0x56,0x00,0x00,
    251 			0x05,0x27,0x9f,0xa5,0xd8,0xb5,0xe4,0xad,
    252 			0x40,0xe7,0x36,0xdd,0xb4,0xd3,0x54,0x12,
    253 			0x32,0x80,0x63,0xfd,0x2a,0xab,0x53,0xe5,
    254 			0xea,0x1e,0x0a,0x9f,0x33,0x25,0x00,0xa5,
    255 			0xdf,0x94,0x87,0xd0,0x7a,0x5c,0x92,0xcc,
    256 			0x51,0x2c,0x88,0x66,0xc7,0xe8,0x60,0xce,
    257 			0x93,0xfd,0xf1,0x66,0xa2,0x49,0x12,0xb4,
    258 			0x22,0x97,0x61,0x46,0xae,0x20,0xce,0x84,
    259 			0x6b,0xb7,0xdc,0x9b,0xa9,0x4a,0x76,0x7a,
    260 			0xae,0xf2,0x0c,0x0d,0x61,0xad,0x02,0x65,
    261 			0x5e,0xa9,0x2d,0xc4,0xc4,0xe4,0x1a,0x89,
    262 			0x52,0xc6,0x51,0xd3,0x31,0x74,0xbe,0x51,
    263 		},
    264 		[1] = {
    265 		},
    266 		[2] = {
    267 			/* IEEE P1619-D16, XTS-AES-256, Vector 10, truncated */
    268 			0x1c,0x3b,0x3a,0x10,0x2f,0x77,0x03,0x86,
    269 			0xe4,0x83,0x6c,0x99,0xe3,0x70,0xcf,0x9b,
    270 			0xea,0x00,0x80,0x3f,0x5e,0x48,0x23,0x57,
    271 			0xa4,0xae,0x12,0xd4,0x14,0xa3,0xe6,0x3b,
    272 			0x5d,0x31,0xe2,0x76,0xf8,0xfe,0x4a,0x8d,
    273 			0x66,0xb3,0x17,0xf9,0xac,0x68,0x3f,0x44,
    274 			0x68,0x0a,0x86,0xac,0x35,0xad,0xfc,0x33,
    275 			0x45,0xbe,0xfe,0xcb,0x4b,0xb1,0x88,0xfd,
    276 			0x57,0x76,0x92,0x6c,0x49,0xa3,0x09,0x5e,
    277 			0xb1,0x08,0xfd,0x10,0x98,0xba,0xec,0x70,
    278 			0xaa,0xa6,0x69,0x99,0xa7,0x2a,0x82,0xf2,
    279 			0x7d,0x84,0x8b,0x21,0xd4,0xa7,0x41,0xb0,
    280 			0xc5,0xcd,0x4d,0x5f,0xff,0x9d,0xac,0x89,
    281 			0xae,0xba,0x12,0x29,0x61,0xd0,0x3a,0x75,
    282 			0x71,0x23,0xe9,0x87,0x0f,0x8a,0xcf,0x10,
    283 			0x00,0x02,0x08,0x87,0x89,0x14,0x29,0xca,
    284 			0x2a,0x3e,0x7a,0x7d,0x7d,0xf7,0xb1,0x03,
    285 			0x55,0x16,0x5c,0x8b,0x9a,0x6d,0x0a,0x7d,
    286 		},
    287 	};
    288 	static const uint8_t key1[32] = {
    289 		0x27,0x18,0x28,0x18,0x28,0x45,0x90,0x45,
    290 		0x23,0x53,0x60,0x28,0x74,0x71,0x35,0x26,
    291 		0x62,0x49,0x77,0x57,0x24,0x70,0x93,0x69,
    292 		0x99,0x59,0x57,0x49,0x66,0x96,0x76,0x27,
    293 	};
    294 	static const uint8_t key2[32] = {
    295 		0x31,0x41,0x59,0x26,0x53,0x58,0x97,0x93,
    296 		0x23,0x84,0x62,0x64,0x33,0x83,0x27,0x95,
    297 		0x02,0x88,0x41,0x97,0x16,0x93,0x99,0x37,
    298 		0x51,0x05,0x82,0x09,0x74,0x94,0x45,0x92,
    299 	};
    300 	struct aesenc enc;
    301 	struct aesdec dec;
    302 	uint8_t in[144];
    303 	uint8_t outbuf[146] = { [0] = 0x1a, [145] = 0x1a }, *out = outbuf + 1;
    304 	uint8_t blkno_buf[16];
    305 	uint8_t iv0[16], iv[16];
    306 	unsigned i;
    307 
    308 	for (i = 0; i < 144; i++)
    309 		in[i] = i;
    310 
    311 	for (i = 0; i < 3; i++) {
    312 		if (i == 1)	/* XXX missing AES-192 test vector */
    313 			continue;
    314 
    315 		/* Format the data unit sequence number.  */
    316 		memset(blkno_buf, 0, sizeof blkno_buf);
    317 		le64enc(blkno_buf, blkno[i]);
    318 
    319 		/* Generate the tweak.  */
    320 		impl->ai_setenckey(&enc, key2, aes_nrounds[i]);
    321 		impl->ai_enc(&enc, blkno_buf, iv0, aes_nrounds[i]);
    322 
    323 		/* Load the data encryption key.  */
    324 		impl->ai_setenckey(&enc, key1, aes_nrounds[i]);
    325 		impl->ai_setdeckey(&dec, key1, aes_nrounds[i]);
    326 
    327 		/* Try one swell foop.  */
    328 		memcpy(iv, iv0, 16);
    329 		impl->ai_xts_enc(&enc, in, out, 144, iv, aes_nrounds[i]);
    330 		if (memcmp(out, expected[i], 144))
    331 			return aes_selftest_fail(impl, out, expected[i], 144,
    332 			    "AES-%u-XTS enc", aes_keybits[i]);
    333 
    334 		memcpy(iv, iv0, 16);
    335 		impl->ai_xts_dec(&dec, out, out, 144, iv, aes_nrounds[i]);
    336 		if (memcmp(out, in, 144))
    337 			return aes_selftest_fail(impl, out, in, 144,
    338 			    "AES-%u-XTS dec", aes_keybits[i]);
    339 
    340 		/* Try incrementally, with IV update.  */
    341 		memcpy(iv, iv0, 16);
    342 		impl->ai_xts_enc(&enc, in, out, 16, iv, aes_nrounds[i]);
    343 		impl->ai_xts_enc(&enc, in + 16, out + 16, 128, iv,
    344 		    aes_nrounds[i]);
    345 		if (memcmp(out, expected[i], 144))
    346 			return aes_selftest_fail(impl, out, expected[i], 144,
    347 			    "AES-%u-XTS enc incremental", aes_keybits[i]);
    348 
    349 		memcpy(iv, iv0, 16);
    350 		impl->ai_xts_dec(&dec, out, out, 128, iv, aes_nrounds[i]);
    351 		impl->ai_xts_dec(&dec, out + 128, out + 128, 16, iv,
    352 		    aes_nrounds[i]);
    353 		if (memcmp(out, in, 144))
    354 			return aes_selftest_fail(impl, out, in, 144,
    355 			    "AES-%u-XTS dec incremental", aes_keybits[i]);
    356 	}
    357 
    358 	if (outbuf[0] != 0x1a)
    359 		return aes_selftest_fail(impl, outbuf,
    360 		    (const uint8_t[1]){0x1a}, 1,
    361 		    "AES-XTS overrun preceding");
    362 	if (outbuf[145] != 0x1a)
    363 		return aes_selftest_fail(impl, outbuf + 145,
    364 		    (const uint8_t[1]){0x1a}, 1,
    365 		    "AES-XTS overrun following");
    366 
    367 	/* Success!  */
    368 	return 0;
    369 }
    370 
    371 int
    372 aes_selftest(const struct aes_impl *impl)
    373 {
    374 	int result = 0;
    375 
    376 	if (impl->ai_probe())
    377 		return -1;
    378 
    379 	if (aes_selftest_encdec(impl))
    380 		result = -1;
    381 	if (aes_selftest_encdec_cbc(impl))
    382 		result = -1;
    383 	if (aes_selftest_encdec_xts(impl))
    384 		result = -1;
    385 
    386 	return result;
    387 }
    388