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