Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src-draft/trunk]: src/sys Rework AES in kernel to finally address CVE-2005-1...
details: https://anonhg.NetBSD.org/src-all/rev/36e8546bbfd3
branches: trunk
changeset: 934933:36e8546bbfd3
user: Taylor R Campbell <riastradh%NetBSD.org@localhost>
date: Fri Jun 12 05:16:46 2020 +0000
description:
Rework AES in kernel to finally address CVE-2005-1797.
1. Rip out old variable-time reference implementation.
2. Replace it by BearSSL's constant-time 32-bit logic.
=> Obtained from commit dda1f8a0c46e15b4a235163470ff700b2f13dcc5.
=> We could conditionally adopt the 64-bit logic too, which would
likely give a modest performance boost on 64-bit platforms
without AES-NI, but that's a bit more trouble.
3. Select the AES implementation at boot-time; allow an MD override.
=> Use self-tests to verify basic correctness at boot.
=> The implementation selection policy is rather rudimentary at
the moment but it is isolated to one place so it's easy to
change later on.
This (a) plugs a host of timing attacks on, e.g., cgd, and (b) paves
the way to take advantage of CPU support for AES -- both things we
should've done a decade ago. Downside: Computing AES takes 2-3x the
CPU time. But that's what hardware support will be coming for.
Rudimentary measurement of performance impact done by:
mount -t tmpfs tmpfs /tmp
dd if=/dev/zero of=/tmp/disk bs=1m count=512
vnconfig -cv vnd0 /tmp/disk
cgdconfig -s cgd0 /dev/vnd0 aes-cbc 256 < /dev/zero
dd if=/dev/rcgd0d of=/dev/null bs=64k
dd if=/dev/zero of=/dev/rcgd0d bs=64k
The AES-CBC encryption performance impact is closer to 3x because it
is inherently sequential; the AES-CBC decryption impact is closer to
2x because the bitsliced AES logic can process two blocks at once.
diffstat:
sys/conf/files | 2 +-
sys/crypto/aes/aes.h | 101 ++
sys/crypto/aes/aes_bear.c | 617 ++++++++++++++++
sys/crypto/aes/aes_bear.h | 50 +
sys/crypto/aes/aes_ct.c | 335 ++++++++
sys/crypto/aes/aes_ct_dec.c | 177 ++++
sys/crypto/aes/aes_ct_enc.c | 119 +++
sys/crypto/aes/aes_impl.c | 256 ++++++
sys/crypto/aes/aes_rijndael.c | 306 +++++++
sys/crypto/aes/aes_selftest.c | 387 ++++++++++
sys/crypto/aes/files.aes | 12 +
sys/crypto/rijndael/files.rijndael | 7 -
sys/crypto/rijndael/rijndael-alg-fst.c | 1225 --------------------------------
sys/crypto/rijndael/rijndael-api-fst.c | 430 -----------
sys/crypto/rijndael/rijndael.c | 57 -
sys/crypto/rijndael/rijndael_local.h | 7 -
sys/rump/kern/lib/libcrypto/Makefile | 14 +-
17 files changed, 2371 insertions(+), 1731 deletions(-)
diffs (truncated from 4195 to 300 lines):
diff -r 782f3535bc9e -r 36e8546bbfd3 sys/conf/files
--- a/sys/conf/files Sun Jun 14 15:58:39 2020 +0000
+++ b/sys/conf/files Fri Jun 12 05:16:46 2020 +0000
@@ -200,10 +200,10 @@
# use it.
# Individual crypto transforms
+include "crypto/aes/files.aes"
include "crypto/des/files.des"
include "crypto/blowfish/files.blowfish"
include "crypto/cast128/files.cast128"
-include "crypto/rijndael/files.rijndael"
include "crypto/skipjack/files.skipjack"
include "crypto/camellia/files.camellia"
# General-purpose crypto processing framework.
diff -r 782f3535bc9e -r 36e8546bbfd3 sys/crypto/aes/aes.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/crypto/aes/aes.h Fri Jun 12 05:16:46 2020 +0000
@@ -0,0 +1,101 @@
+/* $NetBSD$ */
+
+/*-
+ * Copyright (c) 2020 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _CRYPTO_AES_AES_H
+#define _CRYPTO_AES_AES_H
+
+#include <sys/types.h>
+#include <sys/cdefs.h>
+
+/*
+ * struct aes
+ *
+ * Expanded round keys.
+ */
+struct aes {
+ uint32_t aes_rk[60];
+} __aligned(16);
+
+#define AES_128_NROUNDS 10
+#define AES_192_NROUNDS 12
+#define AES_256_NROUNDS 14
+
+struct aesenc {
+ struct aes aese_aes;
+};
+
+struct aesdec {
+ struct aes aesd_aes;
+};
+
+struct aes_impl {
+ const char *ai_name;
+ int (*ai_probe)(void);
+ void (*ai_setenckey)(struct aesenc *, const uint8_t *, uint32_t);
+ void (*ai_setdeckey)(struct aesdec *, const uint8_t *, uint32_t);
+ void (*ai_enc)(const struct aesenc *, const uint8_t[static 16],
+ uint8_t[static 16], uint32_t);
+ void (*ai_dec)(const struct aesdec *, const uint8_t[static 16],
+ uint8_t[static 16], uint32_t);
+ void (*ai_cbc_enc)(const struct aesenc *, const uint8_t[static 16],
+ uint8_t[static 16], size_t, uint8_t[static 16], uint32_t);
+ void (*ai_cbc_dec)(const struct aesdec *, const uint8_t[static 16],
+ uint8_t[static 16], size_t, uint8_t[static 16], uint32_t);
+ void (*ai_xts_enc)(const struct aesenc *, const uint8_t[static 16],
+ uint8_t[static 16], size_t, uint8_t[static 16], uint32_t);
+ void (*ai_xts_dec)(const struct aesdec *, const uint8_t[static 16],
+ uint8_t[static 16], size_t, uint8_t[static 16], uint32_t);
+};
+
+int aes_selftest(const struct aes_impl *);
+
+uint32_t aes_setenckey128(struct aesenc *, const uint8_t[static 16]);
+uint32_t aes_setenckey192(struct aesenc *, const uint8_t[static 24]);
+uint32_t aes_setenckey256(struct aesenc *, const uint8_t[static 32]);
+uint32_t aes_setdeckey128(struct aesdec *, const uint8_t[static 16]);
+uint32_t aes_setdeckey192(struct aesdec *, const uint8_t[static 24]);
+uint32_t aes_setdeckey256(struct aesdec *, const uint8_t[static 32]);
+
+void aes_enc(const struct aesenc *, const uint8_t[static 16],
+ uint8_t[static 16], uint32_t);
+void aes_dec(const struct aesdec *, const uint8_t[static 16],
+ uint8_t[static 16], uint32_t);
+
+void aes_cbc_enc(struct aesenc *, const uint8_t[static 16],
+ uint8_t[static 16], size_t, uint8_t[static 16], uint32_t);
+void aes_cbc_dec(struct aesdec *, const uint8_t[static 16],
+ uint8_t[static 16], size_t, uint8_t[static 16], uint32_t);
+
+void aes_xts_enc(struct aesenc *, const uint8_t[static 16],
+ uint8_t[static 16], size_t, uint8_t[static 16], uint32_t);
+void aes_xts_dec(struct aesdec *, const uint8_t[static 16],
+ uint8_t[static 16], size_t, uint8_t[static 16], uint32_t);
+
+void aes_md_init(const struct aes_impl *);
+
+#endif /* _CRYPTO_AES_AES_H */
diff -r 782f3535bc9e -r 36e8546bbfd3 sys/crypto/aes/aes_bear.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/crypto/aes/aes_bear.c Fri Jun 12 05:16:46 2020 +0000
@@ -0,0 +1,617 @@
+/* $NetBSD$ */
+
+/*-
+ * Copyright (c) 2020 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(1, "$NetBSD$");
+
+#include <sys/types.h>
+#include <sys/endian.h>
+#include <sys/systm.h>
+
+#include <crypto/aes/aes.h>
+#include <crypto/aes/aes_bear.h>
+
+static void
+aesbear_setkey(uint32_t rk[static 60], const void *key, uint32_t nrounds)
+{
+ size_t key_len;
+
+ switch (nrounds) {
+ case 10:
+ key_len = 16;
+ break;
+ case 12:
+ key_len = 24;
+ break;
+ case 14:
+ key_len = 32;
+ break;
+ default:
+ panic("invalid AES nrounds: %u", nrounds);
+ }
+
+ br_aes_ct_keysched(rk, key, key_len);
+}
+
+static void
+aesbear_setenckey(struct aesenc *enc, const uint8_t *key, uint32_t nrounds)
+{
+
+ aesbear_setkey(enc->aese_aes.aes_rk, key, nrounds);
+}
+
+static void
+aesbear_setdeckey(struct aesdec *dec, const uint8_t *key, uint32_t nrounds)
+{
+
+ /*
+ * BearSSL computes InvMixColumns on the fly -- no need for
+ * distinct decryption round keys.
+ */
+ aesbear_setkey(dec->aesd_aes.aes_rk, key, nrounds);
+}
+
+static void
+aesbear_enc(const struct aesenc *enc, const uint8_t in[static 16],
+ uint8_t out[static 16], uint32_t nrounds)
+{
+ uint32_t sk_exp[120];
+ uint32_t q[8];
+
+ /* Expand round keys for bitslicing. */
+ br_aes_ct_skey_expand(sk_exp, nrounds, enc->aese_aes.aes_rk);
+
+ /* Load input block interleaved with garbage block. */
+ q[2*0] = le32dec(in + 4*0);
+ q[2*1] = le32dec(in + 4*1);
+ q[2*2] = le32dec(in + 4*2);
+ q[2*3] = le32dec(in + 4*3);
+ q[1] = q[3] = q[5] = q[7] = 0;
+
+ /* Transform to bitslice, decrypt, transform from bitslice. */
+ br_aes_ct_ortho(q);
+ br_aes_ct_bitslice_encrypt(nrounds, sk_exp, q);
+ br_aes_ct_ortho(q);
+
+ /* Store output block. */
+ le32enc(out + 4*0, q[2*0]);
+ le32enc(out + 4*1, q[2*1]);
+ le32enc(out + 4*2, q[2*2]);
+ le32enc(out + 4*3, q[2*3]);
+
+ /* Paranoia: Zero temporary buffers. */
+ explicit_memset(sk_exp, 0, sizeof sk_exp);
+ explicit_memset(q, 0, sizeof q);
+}
+
+static void
+aesbear_dec(const struct aesdec *dec, const uint8_t in[static 16],
+ uint8_t out[static 16], uint32_t nrounds)
+{
+ uint32_t sk_exp[120];
+ uint32_t q[8];
+
+ /* Expand round keys for bitslicing. */
+ br_aes_ct_skey_expand(sk_exp, nrounds, dec->aesd_aes.aes_rk);
+
+ /* Load input block interleaved with garbage. */
+ q[2*0] = le32dec(in + 4*0);
+ q[2*1] = le32dec(in + 4*1);
+ q[2*2] = le32dec(in + 4*2);
+ q[2*3] = le32dec(in + 4*3);
+ q[1] = q[3] = q[5] = q[7] = 0;
+
+ /* Transform to bitslice, decrypt, transform from bitslice. */
+ br_aes_ct_ortho(q);
+ br_aes_ct_bitslice_decrypt(nrounds, sk_exp, q);
+ br_aes_ct_ortho(q);
+
+ /* Store output block. */
+ le32enc(out + 4*0, q[2*0]);
+ le32enc(out + 4*1, q[2*1]);
+ le32enc(out + 4*2, q[2*2]);
+ le32enc(out + 4*3, q[2*3]);
+
+ /* Paranoia: Zero temporary buffers. */
+ explicit_memset(sk_exp, 0, sizeof sk_exp);
+ explicit_memset(q, 0, sizeof q);
+}
+
+static void
+aesbear_cbc_enc(const struct aesenc *enc, const uint8_t in[static 16],
+ uint8_t out[static 16], size_t nbytes, uint8_t iv[static 16],
+ uint32_t nrounds)
+{
+ uint32_t sk_exp[120];
+ uint32_t q[8];
+ uint32_t cv0, cv1, cv2, cv3;
+
+ KASSERT(nbytes % 16 == 0);
+
+ /* Skip if there's nothing to do. */
+ if (nbytes == 0)
+ return;
+
+ /* Expand round keys for bitslicing. */
+ br_aes_ct_skey_expand(sk_exp, nrounds, enc->aese_aes.aes_rk);
+
+ /* Initialize garbage block. */
+ q[1] = q[3] = q[5] = q[7] = 0;
+
+ /* Load IV. */
+ cv0 = le32dec(iv + 4*0);
+ cv1 = le32dec(iv + 4*1);
+ cv2 = le32dec(iv + 4*2);
+ cv3 = le32dec(iv + 4*3);
+
+ for (; nbytes; nbytes -= 16, in += 16, out += 16) {
+ /* Load input block and apply CV. */
+ q[2*0] = cv0 ^ le32dec(in + 4*0);
+ q[2*1] = cv1 ^ le32dec(in + 4*1);
+ q[2*2] = cv2 ^ le32dec(in + 4*2);
Home |
Main Index |
Thread Index |
Old Index