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