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