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;
+}

Reply via email to