Module Name: src Committed By: riastradh Date: Mon Jun 29 23:36:59 UTC 2020
Modified Files: src/sys/crypto/aes: aes_bear.h aes_ct.c aes_ct_dec.c aes_impl.c Log Message: Provide the standard AES key schedule. Different AES implementations prefer different variations on it, but some of them -- notably VIA -- require the standard key schedule to be available and don't provide hardware support for computing it themselves. So adapt BearSSL's logic to generate the standard key schedule (and decryption keys, with InvMixColumns), rather than the bitsliced key schedule that BearSSL uses natively. To generate a diff of this commit: cvs rdiff -u -r1.1 -r1.2 src/sys/crypto/aes/aes_bear.h \ src/sys/crypto/aes/aes_ct.c src/sys/crypto/aes/aes_ct_dec.c \ src/sys/crypto/aes/aes_impl.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/crypto/aes/aes_bear.h diff -u src/sys/crypto/aes/aes_bear.h:1.1 src/sys/crypto/aes/aes_bear.h:1.2 --- src/sys/crypto/aes/aes_bear.h:1.1 Mon Jun 29 23:27:52 2020 +++ src/sys/crypto/aes/aes_bear.h Mon Jun 29 23:36:59 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: aes_bear.h,v 1.1 2020/06/29 23:27:52 riastradh Exp $ */ +/* $NetBSD: aes_bear.h,v 1.2 2020/06/29 23:36:59 riastradh Exp $ */ /*- * Copyright (c) 2020 The NetBSD Foundation, Inc. @@ -45,6 +45,12 @@ void br_aes_ct_skey_expand(uint32_t *, u void br_aes_ct_bitslice_encrypt(unsigned, const uint32_t *, uint32_t *); void br_aes_ct_bitslice_decrypt(unsigned, const uint32_t *, uint32_t *); +/* NetBSD additions */ + +void br_aes_ct_inv_mix_columns(uint32_t *); +u_int br_aes_ct_keysched_stdenc(uint32_t *, const void *, size_t); +u_int br_aes_ct_keysched_stddec(uint32_t *, const void *, size_t); + extern struct aes_impl aes_bear_impl; #endif /* _CRYPTO_AES_AES_BEAR_H */ Index: src/sys/crypto/aes/aes_ct.c diff -u src/sys/crypto/aes/aes_ct.c:1.1 src/sys/crypto/aes/aes_ct.c:1.2 --- src/sys/crypto/aes/aes_ct.c:1.1 Mon Jun 29 23:27:52 2020 +++ src/sys/crypto/aes/aes_ct.c Mon Jun 29 23:36:59 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: aes_ct.c,v 1.1 2020/06/29 23:27:52 riastradh Exp $ */ +/* $NetBSD: aes_ct.c,v 1.2 2020/06/29 23:36:59 riastradh Exp $ */ /* * Copyright (c) 2016 Thomas Pornin <por...@bolet.org> @@ -25,10 +25,12 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(1, "$NetBSD: aes_ct.c,v 1.1 2020/06/29 23:27:52 riastradh Exp $"); +__KERNEL_RCSID(1, "$NetBSD: aes_ct.c,v 1.2 2020/06/29 23:36:59 riastradh Exp $"); #include <sys/types.h> +#include <lib/libkern/libkern.h> + #include <crypto/aes/aes_bear.h> /* see inner.h */ @@ -333,3 +335,92 @@ br_aes_ct_skey_expand(uint32_t *skey, skey[v + 1] = y | (y >> 1); } } + +/* NetBSD additions, for computing the standard AES key schedule */ + +unsigned +br_aes_ct_keysched_stdenc(uint32_t *skey, const void *key, size_t key_len) +{ + unsigned num_rounds; + int i, j, k, nk, nkf; + uint32_t tmp; + + switch (key_len) { + case 16: + num_rounds = 10; + break; + case 24: + num_rounds = 12; + break; + case 32: + num_rounds = 14; + break; + default: + /* abort(); */ + return 0; + } + nk = (int)(key_len >> 2); + nkf = (int)((num_rounds + 1) << 2); + tmp = 0; + for (i = 0; i < nk; i ++) { + tmp = br_dec32le((const unsigned char *)key + (i << 2)); + skey[i] = tmp; + } + for (i = nk, j = 0, k = 0; i < nkf; i ++) { + if (j == 0) { + tmp = (tmp << 24) | (tmp >> 8); + tmp = sub_word(tmp) ^ Rcon[k]; + } else if (nk > 6 && j == 4) { + tmp = sub_word(tmp); + } + tmp ^= skey[i - nk]; + skey[i] = tmp; + if (++ j == nk) { + j = 0; + k ++; + } + } + return num_rounds; +} + +unsigned +br_aes_ct_keysched_stddec(uint32_t *skey, const void *key, size_t key_len) +{ + uint32_t tkey[60]; + uint32_t q[8]; + unsigned num_rounds; + unsigned i; + + num_rounds = br_aes_ct_keysched_stdenc(skey, key, key_len); + if (num_rounds == 0) + return 0; + + tkey[0] = skey[4*num_rounds + 0]; + tkey[1] = skey[4*num_rounds + 1]; + tkey[2] = skey[4*num_rounds + 2]; + tkey[3] = skey[4*num_rounds + 3]; + for (i = 1; i < num_rounds; i++) { + q[2*0] = skey[4*i + 0]; + q[2*1] = skey[4*i + 1]; + q[2*2] = skey[4*i + 2]; + q[2*3] = skey[4*i + 3]; + q[1] = q[3] = q[5] = q[7] = 0; + + br_aes_ct_ortho(q); + br_aes_ct_inv_mix_columns(q); + br_aes_ct_ortho(q); + + tkey[4*(num_rounds - i) + 0] = q[2*0]; + tkey[4*(num_rounds - i) + 1] = q[2*1]; + tkey[4*(num_rounds - i) + 2] = q[2*2]; + tkey[4*(num_rounds - i) + 3] = q[2*3]; + } + tkey[4*num_rounds + 0] = skey[0]; + tkey[4*num_rounds + 1] = skey[1]; + tkey[4*num_rounds + 2] = skey[2]; + tkey[4*num_rounds + 3] = skey[3]; + + memcpy(skey, tkey, 4*(num_rounds + 1)*sizeof(uint32_t)); + explicit_memset(tkey, 0, 4*(num_rounds + 1)*sizeof(uint32_t)); + return num_rounds; +} Index: src/sys/crypto/aes/aes_ct_dec.c diff -u src/sys/crypto/aes/aes_ct_dec.c:1.1 src/sys/crypto/aes/aes_ct_dec.c:1.2 --- src/sys/crypto/aes/aes_ct_dec.c:1.1 Mon Jun 29 23:27:52 2020 +++ src/sys/crypto/aes/aes_ct_dec.c Mon Jun 29 23:36:59 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: aes_ct_dec.c,v 1.1 2020/06/29 23:27:52 riastradh Exp $ */ +/* $NetBSD: aes_ct_dec.c,v 1.2 2020/06/29 23:36:59 riastradh Exp $ */ /* * Copyright (c) 2016 Thomas Pornin <por...@bolet.org> @@ -25,7 +25,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(1, "$NetBSD: aes_ct_dec.c,v 1.1 2020/06/29 23:27:52 riastradh Exp $"); +__KERNEL_RCSID(1, "$NetBSD: aes_ct_dec.c,v 1.2 2020/06/29 23:36:59 riastradh Exp $"); #include <sys/types.h> @@ -175,3 +175,11 @@ br_aes_ct_bitslice_decrypt(unsigned num_ br_aes_ct_bitslice_invSbox(q); add_round_key(q, skey); } + +/* NetBSD addition, for generating compatible decryption keys */ +void +br_aes_ct_inv_mix_columns(uint32_t *q) +{ + + inv_mix_columns(q); +} Index: src/sys/crypto/aes/aes_impl.c diff -u src/sys/crypto/aes/aes_impl.c:1.1 src/sys/crypto/aes/aes_impl.c:1.2 --- src/sys/crypto/aes/aes_impl.c:1.1 Mon Jun 29 23:27:52 2020 +++ src/sys/crypto/aes/aes_impl.c Mon Jun 29 23:36:59 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: aes_impl.c,v 1.1 2020/06/29 23:27:52 riastradh Exp $ */ +/* $NetBSD: aes_impl.c,v 1.2 2020/06/29 23:36:59 riastradh Exp $ */ /*- * Copyright (c) 2020 The NetBSD Foundation, Inc. @@ -27,7 +27,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(1, "$NetBSD: aes_impl.c,v 1.1 2020/06/29 23:27:52 riastradh Exp $"); +__KERNEL_RCSID(1, "$NetBSD: aes_impl.c,v 1.2 2020/06/29 23:36:59 riastradh Exp $"); #include <sys/types.h> #include <sys/kernel.h> @@ -38,6 +38,8 @@ __KERNEL_RCSID(1, "$NetBSD: aes_impl.c,v #include <crypto/aes/aes.h> #include <crypto/aes/aes_bear.h> /* default implementation */ +static int aes_selftest_stdkeysched(void); + static const struct aes_impl *aes_md_impl __read_mostly; static const struct aes_impl *aes_impl __read_mostly; @@ -61,6 +63,9 @@ aes_select(void) KASSERT(aes_impl == NULL); + if (aes_selftest_stdkeysched()) + panic("AES is busted"); + if (aes_md_impl) { if (aes_selftest(aes_md_impl)) aprint_error("aes: self-test failed: %s\n", @@ -254,3 +259,131 @@ aes_xts_dec(struct aesdec *dec, const ui aes_guarantee_selected(); aes_impl->ai_xts_dec(dec, in, out, nbytes, tweak, nrounds); } + +/* + * Known-answer self-tests for the standard key schedule. + */ +static int +aes_selftest_stdkeysched(void) +{ + static const uint8_t key[32] = { + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f, + 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, + 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f, + }; + static const uint32_t rk128enc[] = { + 0x03020100, 0x07060504, 0x0b0a0908, 0x0f0e0d0c, + 0xfd74aad6, 0xfa72afd2, 0xf178a6da, 0xfe76abd6, + 0x0bcf92b6, 0xf1bd3d64, 0x00c59bbe, 0xfeb33068, + 0x4e74ffb6, 0xbfc9c2d2, 0xbf0c596c, 0x41bf6904, + 0xbcf7f747, 0x033e3595, 0xbc326cf9, 0xfd8d05fd, + 0xe8a3aa3c, 0xeb9d9fa9, 0x57aff350, 0xaa22f6ad, + 0x7d0f395e, 0x9692a6f7, 0xc13d55a7, 0x6b1fa30a, + 0x1a70f914, 0x8ce25fe3, 0x4ddf0a44, 0x26c0a94e, + 0x35874347, 0xb9651ca4, 0xf4ba16e0, 0xd27abfae, + 0xd1329954, 0x685785f0, 0x9ced9310, 0x4e972cbe, + 0x7f1d1113, 0x174a94e3, 0x8ba707f3, 0xc5302b4d, + }; + static const uint32_t rk192enc[] = { + 0x03020100, 0x07060504, 0x0b0a0908, 0x0f0e0d0c, + 0x13121110, 0x17161514, 0xf9f24658, 0xfef4435c, + 0xf5fe4a54, 0xfaf04758, 0xe9e25648, 0xfef4435c, + 0xb349f940, 0x4dbdba1c, 0xb843f048, 0x42b3b710, + 0xab51e158, 0x55a5a204, 0x41b5ff7e, 0x0c084562, + 0xb44bb52a, 0xf6f8023a, 0x5da9e362, 0x080c4166, + 0x728501f5, 0x7e8d4497, 0xcac6f1bd, 0x3c3ef387, + 0x619710e5, 0x699b5183, 0x9e7c1534, 0xe0f151a3, + 0x2a37a01e, 0x16095399, 0x779e437c, 0x1e0512ff, + 0x880e7edd, 0x68ff2f7e, 0x42c88f60, 0x54c1dcf9, + 0x235f9f85, 0x3d5a8d7a, 0x5229c0c0, 0x3ad6efbe, + 0x781e60de, 0x2cdfbc27, 0x0f8023a2, 0x32daaed8, + 0x330a97a4, 0x09dc781a, 0x71c218c4, 0x5d1da4e3, + }; + static const uint32_t rk256enc[] = { + 0x03020100, 0x07060504, 0x0b0a0908, 0x0f0e0d0c, + 0x13121110, 0x17161514, 0x1b1a1918, 0x1f1e1d1c, + 0x9fc273a5, 0x98c476a1, 0x93ce7fa9, 0x9cc072a5, + 0xcda85116, 0xdabe4402, 0xc1a45d1a, 0xdeba4006, + 0xf0df87ae, 0x681bf10f, 0xfbd58ea6, 0x6715fc03, + 0x48f1e16d, 0x924fa56f, 0x53ebf875, 0x8d51b873, + 0x7f8256c6, 0x1799a7c9, 0xec4c296f, 0x8b59d56c, + 0x753ae23d, 0xe7754752, 0xb49ebf27, 0x39cf0754, + 0x5f90dc0b, 0x48097bc2, 0xa44552ad, 0x2f1c87c1, + 0x60a6f545, 0x87d3b217, 0x334d0d30, 0x0a820a64, + 0x1cf7cf7c, 0x54feb4be, 0xf0bbe613, 0xdfa761d2, + 0xfefa1af0, 0x7929a8e7, 0x4a64a5d7, 0x40e6afb3, + 0x71fe4125, 0x2500f59b, 0xd5bb1388, 0x0a1c725a, + 0x99665a4e, 0xe04ff2a9, 0xaa2b577e, 0xeacdf8cd, + 0xcc79fc24, 0xe97909bf, 0x3cc21a37, 0x36de686d, + }; + static const uint32_t rk128dec[] = { + 0x7f1d1113, 0x174a94e3, 0x8ba707f3, 0xc5302b4d, + 0xbe29aa13, 0xf6af8f9c, 0x80f570f7, 0x03bff700, + 0x63a46213, 0x4886258f, 0x765aff6b, 0x834a87f7, + 0x74fc828d, 0x2b22479c, 0x3edcdae4, 0xf510789c, + 0x8d09e372, 0x5fdec511, 0x15fe9d78, 0xcbcca278, + 0x2710c42e, 0xd2d72663, 0x4a205869, 0xde323f00, + 0x04f5a2a8, 0xf5c7e24d, 0x98f77e0a, 0x94126769, + 0x91e3c6c7, 0xf13240e5, 0x6d309c47, 0x0ce51963, + 0x9902dba0, 0x60d18622, 0x9c02dca2, 0x61d58524, + 0xf0df568c, 0xf9d35d82, 0xfcd35a80, 0xfdd75986, + 0x03020100, 0x07060504, 0x0b0a0908, 0x0f0e0d0c, + }; + static const uint32_t rk192dec[] = { + 0x330a97a4, 0x09dc781a, 0x71c218c4, 0x5d1da4e3, + 0x0dbdbed6, 0x49ea09c2, 0x8073b04d, 0xb91b023e, + 0xc999b98f, 0x3968b273, 0x9dd8f9c7, 0x728cc685, + 0xc16e7df7, 0xef543f42, 0x7f317853, 0x4457b714, + 0x90654711, 0x3b66cf47, 0x8dce0e9b, 0xf0f10bfc, + 0xb6a8c1dc, 0x7d3f0567, 0x4a195ccc, 0x2e3a42b5, + 0xabb0dec6, 0x64231e79, 0xbe5f05a4, 0xab038856, + 0xda7c1bdd, 0x155c8df2, 0x1dab498a, 0xcb97c4bb, + 0x08f7c478, 0xd63c8d31, 0x01b75596, 0xcf93c0bf, + 0x10efdc60, 0xce249529, 0x15efdb62, 0xcf20962f, + 0xdbcb4e4b, 0xdacf4d4d, 0xc7d75257, 0xdecb4949, + 0x1d181f1a, 0x191c1b1e, 0xd7c74247, 0xdecb4949, + 0x03020100, 0x07060504, 0x0b0a0908, 0x0f0e0d0c, + }; + static const uint32_t rk256dec[] = { + 0xcc79fc24, 0xe97909bf, 0x3cc21a37, 0x36de686d, + 0xffd1f134, 0x2faacebf, 0x5fe2e9fc, 0x6e015825, + 0xeb48165e, 0x0a354c38, 0x46b77175, 0x84e680dc, + 0x8005a3c8, 0xd07b3f8b, 0x70482743, 0x31e3b1d9, + 0x138e70b5, 0xe17d5a66, 0x4c823d4d, 0xc251f1a9, + 0xa37bda74, 0x507e9c43, 0xa03318c8, 0x41ab969a, + 0x1597a63c, 0xf2f32ad3, 0xadff672b, 0x8ed3cce4, + 0xf3c45ff8, 0xf3054637, 0xf04d848b, 0xe1988e52, + 0x9a4069de, 0xe7648cef, 0x5f0c4df8, 0x232cabcf, + 0x1658d5ae, 0x00c119cf, 0x0348c2bc, 0x11d50ad9, + 0xbd68c615, 0x7d24e531, 0xb868c117, 0x7c20e637, + 0x0f85d77f, 0x1699cc61, 0x0389db73, 0x129dc865, + 0xc940282a, 0xc04c2324, 0xc54c2426, 0xc4482720, + 0x1d181f1a, 0x191c1b1e, 0x15101712, 0x11141316, + 0x03020100, 0x07060504, 0x0b0a0908, 0x0f0e0d0c, + }; + static const struct { + unsigned len; + unsigned nr; + const uint32_t *enc, *dec; + } C[] = { + { 16, AES_128_NROUNDS, rk128enc, rk128dec }, + { 24, AES_192_NROUNDS, rk192enc, rk192dec }, + { 32, AES_256_NROUNDS, rk256enc, rk256dec }, + }; + uint32_t rk[60]; + unsigned i; + + for (i = 0; i < __arraycount(C); i++) { + if (br_aes_ct_keysched_stdenc(rk, key, C[i].len) != C[i].nr) + return -1; + if (memcmp(rk, C[i].enc, 4*(C[i].nr + 1))) + return -1; + if (br_aes_ct_keysched_stddec(rk, key, C[i].len) != C[i].nr) + return -1; + if (memcmp(rk, C[i].dec, 4*(C[i].nr + 1))) + return -1; + } + + return 0; +}