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