aes_impl.c revision 1.6 1 /* $NetBSD: aes_impl.c,v 1.6 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_impl.c,v 1.6 2020/07/25 22:27:53 riastradh Exp $");
31
32 #include <sys/types.h>
33 #include <sys/kernel.h>
34 #include <sys/module.h>
35 #include <sys/once.h>
36 #include <sys/sysctl.h>
37 #include <sys/systm.h>
38
39 #include <crypto/aes/aes.h>
40 #include <crypto/aes/aes_cbc.h>
41 #include <crypto/aes/aes_bear.h> /* default implementation */
42 #include <crypto/aes/aes_impl.h>
43 #include <crypto/aes/aes_xts.h>
44
45 static int aes_selftest_stdkeysched(void);
46
47 static const struct aes_impl *aes_md_impl __read_mostly;
48 static const struct aes_impl *aes_impl __read_mostly;
49
50 static int
51 sysctl_hw_aes_impl(SYSCTLFN_ARGS)
52 {
53 struct sysctlnode node;
54
55 KASSERTMSG(aes_impl != NULL,
56 "sysctl ran before AES implementation was selected");
57
58 node = *rnode;
59 node.sysctl_data = __UNCONST(aes_impl->ai_name);
60 node.sysctl_size = strlen(aes_impl->ai_name) + 1;
61 return sysctl_lookup(SYSCTLFN_CALL(&node));
62 }
63
64 SYSCTL_SETUP(sysctl_hw_aes_setup, "sysctl hw.aes_impl setup")
65 {
66
67 sysctl_createv(clog, 0, NULL, NULL,
68 CTLFLAG_PERMANENT|CTLFLAG_READONLY, CTLTYPE_STRING, "aes_impl",
69 SYSCTL_DESCR("Selected AES implementation"),
70 sysctl_hw_aes_impl, 0, NULL, 0,
71 CTL_HW, CTL_CREATE, CTL_EOL);
72 }
73
74 /*
75 * The timing of AES implementation selection is finicky:
76 *
77 * 1. It has to be done _after_ cpu_attach for implementations,
78 * such as AES-NI, that rely on fpu initialization done by
79 * fpu_attach.
80 *
81 * 2. It has to be done _before_ the cgd self-tests or anything
82 * else that might call AES.
83 *
84 * For the moment, doing it in module init works. However, if a
85 * driver-class module depended on the aes module, that would break.
86 */
87
88 static int
89 aes_select(void)
90 {
91
92 KASSERT(aes_impl == NULL);
93
94 if (aes_selftest_stdkeysched())
95 panic("AES is busted");
96
97 if (aes_md_impl) {
98 if (aes_selftest(aes_md_impl))
99 aprint_error("aes: self-test failed: %s\n",
100 aes_md_impl->ai_name);
101 else
102 aes_impl = aes_md_impl;
103 }
104 if (aes_impl == NULL) {
105 if (aes_selftest(&aes_bear_impl))
106 aprint_error("aes: self-test failed: %s\n",
107 aes_bear_impl.ai_name);
108 else
109 aes_impl = &aes_bear_impl;
110 }
111 if (aes_impl == NULL)
112 panic("AES self-tests failed");
113
114 aprint_normal("aes: %s\n", aes_impl->ai_name);
115 return 0;
116 }
117
118 MODULE(MODULE_CLASS_MISC, aes, NULL);
119
120 static int
121 aes_modcmd(modcmd_t cmd, void *opaque)
122 {
123
124 switch (cmd) {
125 case MODULE_CMD_INIT:
126 return aes_select();
127 case MODULE_CMD_FINI:
128 return 0;
129 default:
130 return ENOTTY;
131 }
132 }
133
134 static void
135 aes_guarantee_selected(void)
136 {
137 #if 0
138 static once_t once;
139 int error;
140
141 error = RUN_ONCE(&once, aes_select);
142 KASSERT(error == 0);
143 #endif
144 }
145
146 void
147 aes_md_init(const struct aes_impl *impl)
148 {
149
150 KASSERT(cold);
151 KASSERTMSG(aes_impl == NULL,
152 "AES implementation `%s' already chosen, can't offer `%s'",
153 aes_impl->ai_name, impl->ai_name);
154 KASSERTMSG(aes_md_impl == NULL,
155 "AES implementation `%s' already offered, can't offer `%s'",
156 aes_md_impl->ai_name, impl->ai_name);
157
158 aes_md_impl = impl;
159 }
160
161 static void
162 aes_setenckey(struct aesenc *enc, const uint8_t key[static 16],
163 uint32_t nrounds)
164 {
165
166 aes_guarantee_selected();
167 aes_impl->ai_setenckey(enc, key, nrounds);
168 }
169
170 uint32_t
171 aes_setenckey128(struct aesenc *enc, const uint8_t key[static 16])
172 {
173 uint32_t nrounds = AES_128_NROUNDS;
174
175 aes_setenckey(enc, key, nrounds);
176 return nrounds;
177 }
178
179 uint32_t
180 aes_setenckey192(struct aesenc *enc, const uint8_t key[static 24])
181 {
182 uint32_t nrounds = AES_192_NROUNDS;
183
184 aes_setenckey(enc, key, nrounds);
185 return nrounds;
186 }
187
188 uint32_t
189 aes_setenckey256(struct aesenc *enc, const uint8_t key[static 32])
190 {
191 uint32_t nrounds = AES_256_NROUNDS;
192
193 aes_setenckey(enc, key, nrounds);
194 return nrounds;
195 }
196
197 static void
198 aes_setdeckey(struct aesdec *dec, const uint8_t key[static 16],
199 uint32_t nrounds)
200 {
201
202 aes_guarantee_selected();
203 aes_impl->ai_setdeckey(dec, key, nrounds);
204 }
205
206 uint32_t
207 aes_setdeckey128(struct aesdec *dec, const uint8_t key[static 16])
208 {
209 uint32_t nrounds = AES_128_NROUNDS;
210
211 aes_setdeckey(dec, key, nrounds);
212 return nrounds;
213 }
214
215 uint32_t
216 aes_setdeckey192(struct aesdec *dec, const uint8_t key[static 24])
217 {
218 uint32_t nrounds = AES_192_NROUNDS;
219
220 aes_setdeckey(dec, key, nrounds);
221 return nrounds;
222 }
223
224 uint32_t
225 aes_setdeckey256(struct aesdec *dec, const uint8_t key[static 32])
226 {
227 uint32_t nrounds = AES_256_NROUNDS;
228
229 aes_setdeckey(dec, key, nrounds);
230 return nrounds;
231 }
232
233 void
234 aes_enc(const struct aesenc *enc, const uint8_t in[static 16],
235 uint8_t out[static 16], uint32_t nrounds)
236 {
237
238 aes_guarantee_selected();
239 aes_impl->ai_enc(enc, in, out, nrounds);
240 }
241
242 void
243 aes_dec(const struct aesdec *dec, const uint8_t in[static 16],
244 uint8_t out[static 16], uint32_t nrounds)
245 {
246
247 aes_guarantee_selected();
248 aes_impl->ai_dec(dec, in, out, nrounds);
249 }
250
251 void
252 aes_cbc_enc(struct aesenc *enc, const uint8_t in[static 16],
253 uint8_t out[static 16], size_t nbytes, uint8_t iv[static 16],
254 uint32_t nrounds)
255 {
256
257 aes_guarantee_selected();
258 aes_impl->ai_cbc_enc(enc, in, out, nbytes, iv, nrounds);
259 }
260
261 void
262 aes_cbc_dec(struct aesdec *dec, const uint8_t in[static 16],
263 uint8_t out[static 16], size_t nbytes, uint8_t iv[static 16],
264 uint32_t nrounds)
265 {
266
267 aes_guarantee_selected();
268 aes_impl->ai_cbc_dec(dec, in, out, nbytes, iv, nrounds);
269 }
270
271 void
272 aes_xts_enc(struct aesenc *enc, const uint8_t in[static 16],
273 uint8_t out[static 16], size_t nbytes, uint8_t tweak[static 16],
274 uint32_t nrounds)
275 {
276
277 aes_guarantee_selected();
278 aes_impl->ai_xts_enc(enc, in, out, nbytes, tweak, nrounds);
279 }
280
281 void
282 aes_xts_dec(struct aesdec *dec, const uint8_t in[static 16],
283 uint8_t out[static 16], size_t nbytes, uint8_t tweak[static 16],
284 uint32_t nrounds)
285 {
286
287 aes_guarantee_selected();
288 aes_impl->ai_xts_dec(dec, in, out, nbytes, tweak, nrounds);
289 }
290
291 static void
292 xor16(uint8_t *x, const uint8_t *a, const uint8_t *b)
293 {
294
295 le32enc(x + 4*0, le32dec(a + 4*0) ^ le32dec(b + 4*0));
296 le32enc(x + 4*1, le32dec(a + 4*1) ^ le32dec(b + 4*1));
297 le32enc(x + 4*2, le32dec(a + 4*2) ^ le32dec(b + 4*2));
298 le32enc(x + 4*3, le32dec(a + 4*3) ^ le32dec(b + 4*3));
299 }
300
301 void
302 aes_cbcmac_update1(const struct aesenc *enc, const uint8_t in[static 16],
303 size_t nbytes, uint8_t auth[static 16], uint32_t nrounds)
304 {
305
306 KASSERT(nbytes);
307 KASSERT(nbytes % 16 == 0);
308
309 aes_guarantee_selected();
310 if (aes_impl->ai_cbcmac_update1) {
311 aes_impl->ai_cbcmac_update1(enc, in, nbytes, auth, nrounds);
312 return;
313 }
314
315 for (; nbytes; in += 16, nbytes -= 16) {
316 xor16(auth, auth, in);
317 aes_enc(enc, auth, auth, nrounds);
318 }
319 }
320
321 void
322 aes_ccm_enc1(const struct aesenc *enc, const uint8_t in[static 16],
323 uint8_t out[static 16], size_t nbytes, uint8_t authctr[static 32],
324 uint32_t nrounds)
325 {
326 uint8_t *auth = authctr;
327 uint8_t *ctr = authctr + 16;
328
329 KASSERT(nbytes);
330 KASSERT(nbytes % 16 == 0);
331
332 aes_guarantee_selected();
333 if (aes_impl->ai_ccm_enc1) {
334 aes_impl->ai_ccm_enc1(enc, in, out, nbytes, auth, nrounds);
335 return;
336 }
337
338 for (; nbytes; in += 16, out += 16, nbytes -= 16) {
339 xor16(auth, auth, in);
340 aes_enc(enc, auth, auth, nrounds);
341
342 be32enc(ctr + 12, 1 + be32dec(ctr + 12));
343 aes_enc(enc, ctr, out, nrounds);
344 xor16(out, out, in);
345 }
346 }
347
348 void
349 aes_ccm_dec1(const struct aesenc *enc, const uint8_t in[static 16],
350 uint8_t out[static 16], size_t nbytes, uint8_t authctr[static 32],
351 uint32_t nrounds)
352 {
353 uint8_t *auth = authctr;
354 uint8_t *ctr = authctr + 16;
355
356 KASSERT(nbytes);
357 KASSERT(nbytes % 16 == 0);
358
359 aes_guarantee_selected();
360 if (aes_impl->ai_ccm_dec1) {
361 aes_impl->ai_ccm_dec1(enc, in, out, nbytes, auth, nrounds);
362 return;
363 }
364
365 for (; nbytes >= 16; in += 16, out += 16, nbytes -= 16) {
366 be32enc(ctr + 12, 1 + be32dec(ctr + 12));
367 aes_enc(enc, ctr, out, nrounds);
368 xor16(out, out, in);
369
370 xor16(auth, auth, out);
371 aes_enc(enc, auth, auth, nrounds);
372 }
373 }
374
375 /*
376 * Known-answer self-tests for the standard key schedule.
377 */
378 static int
379 aes_selftest_stdkeysched(void)
380 {
381 static const uint8_t key[32] = {
382 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
383 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
384 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
385 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,
386 };
387 static const uint32_t rk128enc[] = {
388 0x03020100, 0x07060504, 0x0b0a0908, 0x0f0e0d0c,
389 0xfd74aad6, 0xfa72afd2, 0xf178a6da, 0xfe76abd6,
390 0x0bcf92b6, 0xf1bd3d64, 0x00c59bbe, 0xfeb33068,
391 0x4e74ffb6, 0xbfc9c2d2, 0xbf0c596c, 0x41bf6904,
392 0xbcf7f747, 0x033e3595, 0xbc326cf9, 0xfd8d05fd,
393 0xe8a3aa3c, 0xeb9d9fa9, 0x57aff350, 0xaa22f6ad,
394 0x7d0f395e, 0x9692a6f7, 0xc13d55a7, 0x6b1fa30a,
395 0x1a70f914, 0x8ce25fe3, 0x4ddf0a44, 0x26c0a94e,
396 0x35874347, 0xb9651ca4, 0xf4ba16e0, 0xd27abfae,
397 0xd1329954, 0x685785f0, 0x9ced9310, 0x4e972cbe,
398 0x7f1d1113, 0x174a94e3, 0x8ba707f3, 0xc5302b4d,
399 };
400 static const uint32_t rk192enc[] = {
401 0x03020100, 0x07060504, 0x0b0a0908, 0x0f0e0d0c,
402 0x13121110, 0x17161514, 0xf9f24658, 0xfef4435c,
403 0xf5fe4a54, 0xfaf04758, 0xe9e25648, 0xfef4435c,
404 0xb349f940, 0x4dbdba1c, 0xb843f048, 0x42b3b710,
405 0xab51e158, 0x55a5a204, 0x41b5ff7e, 0x0c084562,
406 0xb44bb52a, 0xf6f8023a, 0x5da9e362, 0x080c4166,
407 0x728501f5, 0x7e8d4497, 0xcac6f1bd, 0x3c3ef387,
408 0x619710e5, 0x699b5183, 0x9e7c1534, 0xe0f151a3,
409 0x2a37a01e, 0x16095399, 0x779e437c, 0x1e0512ff,
410 0x880e7edd, 0x68ff2f7e, 0x42c88f60, 0x54c1dcf9,
411 0x235f9f85, 0x3d5a8d7a, 0x5229c0c0, 0x3ad6efbe,
412 0x781e60de, 0x2cdfbc27, 0x0f8023a2, 0x32daaed8,
413 0x330a97a4, 0x09dc781a, 0x71c218c4, 0x5d1da4e3,
414 };
415 static const uint32_t rk256enc[] = {
416 0x03020100, 0x07060504, 0x0b0a0908, 0x0f0e0d0c,
417 0x13121110, 0x17161514, 0x1b1a1918, 0x1f1e1d1c,
418 0x9fc273a5, 0x98c476a1, 0x93ce7fa9, 0x9cc072a5,
419 0xcda85116, 0xdabe4402, 0xc1a45d1a, 0xdeba4006,
420 0xf0df87ae, 0x681bf10f, 0xfbd58ea6, 0x6715fc03,
421 0x48f1e16d, 0x924fa56f, 0x53ebf875, 0x8d51b873,
422 0x7f8256c6, 0x1799a7c9, 0xec4c296f, 0x8b59d56c,
423 0x753ae23d, 0xe7754752, 0xb49ebf27, 0x39cf0754,
424 0x5f90dc0b, 0x48097bc2, 0xa44552ad, 0x2f1c87c1,
425 0x60a6f545, 0x87d3b217, 0x334d0d30, 0x0a820a64,
426 0x1cf7cf7c, 0x54feb4be, 0xf0bbe613, 0xdfa761d2,
427 0xfefa1af0, 0x7929a8e7, 0x4a64a5d7, 0x40e6afb3,
428 0x71fe4125, 0x2500f59b, 0xd5bb1388, 0x0a1c725a,
429 0x99665a4e, 0xe04ff2a9, 0xaa2b577e, 0xeacdf8cd,
430 0xcc79fc24, 0xe97909bf, 0x3cc21a37, 0x36de686d,
431 };
432 static const uint32_t rk128dec[] = {
433 0x7f1d1113, 0x174a94e3, 0x8ba707f3, 0xc5302b4d,
434 0xbe29aa13, 0xf6af8f9c, 0x80f570f7, 0x03bff700,
435 0x63a46213, 0x4886258f, 0x765aff6b, 0x834a87f7,
436 0x74fc828d, 0x2b22479c, 0x3edcdae4, 0xf510789c,
437 0x8d09e372, 0x5fdec511, 0x15fe9d78, 0xcbcca278,
438 0x2710c42e, 0xd2d72663, 0x4a205869, 0xde323f00,
439 0x04f5a2a8, 0xf5c7e24d, 0x98f77e0a, 0x94126769,
440 0x91e3c6c7, 0xf13240e5, 0x6d309c47, 0x0ce51963,
441 0x9902dba0, 0x60d18622, 0x9c02dca2, 0x61d58524,
442 0xf0df568c, 0xf9d35d82, 0xfcd35a80, 0xfdd75986,
443 0x03020100, 0x07060504, 0x0b0a0908, 0x0f0e0d0c,
444 };
445 static const uint32_t rk192dec[] = {
446 0x330a97a4, 0x09dc781a, 0x71c218c4, 0x5d1da4e3,
447 0x0dbdbed6, 0x49ea09c2, 0x8073b04d, 0xb91b023e,
448 0xc999b98f, 0x3968b273, 0x9dd8f9c7, 0x728cc685,
449 0xc16e7df7, 0xef543f42, 0x7f317853, 0x4457b714,
450 0x90654711, 0x3b66cf47, 0x8dce0e9b, 0xf0f10bfc,
451 0xb6a8c1dc, 0x7d3f0567, 0x4a195ccc, 0x2e3a42b5,
452 0xabb0dec6, 0x64231e79, 0xbe5f05a4, 0xab038856,
453 0xda7c1bdd, 0x155c8df2, 0x1dab498a, 0xcb97c4bb,
454 0x08f7c478, 0xd63c8d31, 0x01b75596, 0xcf93c0bf,
455 0x10efdc60, 0xce249529, 0x15efdb62, 0xcf20962f,
456 0xdbcb4e4b, 0xdacf4d4d, 0xc7d75257, 0xdecb4949,
457 0x1d181f1a, 0x191c1b1e, 0xd7c74247, 0xdecb4949,
458 0x03020100, 0x07060504, 0x0b0a0908, 0x0f0e0d0c,
459 };
460 static const uint32_t rk256dec[] = {
461 0xcc79fc24, 0xe97909bf, 0x3cc21a37, 0x36de686d,
462 0xffd1f134, 0x2faacebf, 0x5fe2e9fc, 0x6e015825,
463 0xeb48165e, 0x0a354c38, 0x46b77175, 0x84e680dc,
464 0x8005a3c8, 0xd07b3f8b, 0x70482743, 0x31e3b1d9,
465 0x138e70b5, 0xe17d5a66, 0x4c823d4d, 0xc251f1a9,
466 0xa37bda74, 0x507e9c43, 0xa03318c8, 0x41ab969a,
467 0x1597a63c, 0xf2f32ad3, 0xadff672b, 0x8ed3cce4,
468 0xf3c45ff8, 0xf3054637, 0xf04d848b, 0xe1988e52,
469 0x9a4069de, 0xe7648cef, 0x5f0c4df8, 0x232cabcf,
470 0x1658d5ae, 0x00c119cf, 0x0348c2bc, 0x11d50ad9,
471 0xbd68c615, 0x7d24e531, 0xb868c117, 0x7c20e637,
472 0x0f85d77f, 0x1699cc61, 0x0389db73, 0x129dc865,
473 0xc940282a, 0xc04c2324, 0xc54c2426, 0xc4482720,
474 0x1d181f1a, 0x191c1b1e, 0x15101712, 0x11141316,
475 0x03020100, 0x07060504, 0x0b0a0908, 0x0f0e0d0c,
476 };
477 static const struct {
478 unsigned len;
479 unsigned nr;
480 const uint32_t *enc, *dec;
481 } C[] = {
482 { 16, AES_128_NROUNDS, rk128enc, rk128dec },
483 { 24, AES_192_NROUNDS, rk192enc, rk192dec },
484 { 32, AES_256_NROUNDS, rk256enc, rk256dec },
485 };
486 uint32_t rk[60];
487 unsigned i;
488
489 for (i = 0; i < __arraycount(C); i++) {
490 if (br_aes_ct_keysched_stdenc(rk, key, C[i].len) != C[i].nr)
491 return -1;
492 if (memcmp(rk, C[i].enc, 4*(C[i].nr + 1)))
493 return -1;
494 if (br_aes_ct_keysched_stddec(rk, key, C[i].len) != C[i].nr)
495 return -1;
496 if (memcmp(rk, C[i].dec, 4*(C[i].nr + 1)))
497 return -1;
498 }
499
500 return 0;
501 }
502