Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev Fix encblkno8 legacy support. Add a test vector whi...
details: https://anonhg.NetBSD.org/src/rev/c69687d00382
branches: trunk
changeset: 972933:c69687d00382
user: riastradh <riastradh%NetBSD.org@localhost>
date: Sat Jun 13 22:17:03 2020 +0000
description:
Fix encblkno8 legacy support. Add a test vector while here.
What a crock!
This is deliberately _not_ neatly abstracted because the whole
configurable `iv method' mechanism is a mistake and should never be
used for anything new.
diffstat:
sys/dev/cgd.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---
1 files changed, 82 insertions(+), 5 deletions(-)
diffs (168 lines):
diff -r 4510a1dfcbd8 -r c69687d00382 sys/dev/cgd.c
--- a/sys/dev/cgd.c Sat Jun 13 22:15:57 2020 +0000
+++ b/sys/dev/cgd.c Sat Jun 13 22:17:03 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: cgd.c,v 1.133 2020/06/13 22:15:57 riastradh Exp $ */
+/* $NetBSD: cgd.c,v 1.134 2020/06/13 22:17:03 riastradh Exp $ */
/*-
* Copyright (c) 2002 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: cgd.c,v 1.133 2020/06/13 22:15:57 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cgd.c,v 1.134 2020/06/13 22:17:03 riastradh Exp $");
#include <sys/types.h>
#include <sys/param.h>
@@ -64,6 +64,7 @@
struct selftest_params {
const char *alg;
+ int encblkno8;
int blocksize; /* number of bytes */
int secsize;
daddr_t blkno;
@@ -292,6 +293,18 @@
0xb8, 0xbf, 0x69, 0x17, 0x20, 0x0a, 0xf7, 0xda,
};
+static const uint8_t selftest_aes_cbc_encblkno8_zero64[64];
+static const uint8_t selftest_aes_cbc_encblkno8_ctxt[64] = {
+ 0xa2, 0x06, 0x26, 0x26, 0xac, 0xdc, 0xe7, 0xcf,
+ 0x47, 0x68, 0x24, 0x0e, 0xfa, 0x40, 0x44, 0x83,
+ 0x07, 0xe1, 0xf4, 0x5d, 0x53, 0x47, 0xa0, 0xfe,
+ 0xc0, 0x6e, 0x4e, 0xf8, 0x9d, 0x98, 0x63, 0xb8,
+ 0x2c, 0x27, 0xfa, 0x3a, 0xd5, 0x40, 0xda, 0xdb,
+ 0xe6, 0xc3, 0xe4, 0xfb, 0x85, 0x53, 0xfb, 0x78,
+ 0x5d, 0xbd, 0x8f, 0x4c, 0x1a, 0x04, 0x9c, 0x88,
+ 0x85, 0xec, 0x3c, 0x56, 0x46, 0x1a, 0x6e, 0xf5,
+};
+
const struct selftest_params selftests[] = {
{
.alg = "aes-xts",
@@ -359,6 +372,18 @@
.ptxt = selftest_bf_cbc_ptxt,
.ctxt = selftest_bf_cbc_ctxt,
},
+ {
+ .alg = "aes-cbc",
+ .encblkno8 = 1,
+ .blocksize = 16,
+ .secsize = 512,
+ .blkno = 0,
+ .keylen = 128,
+ .txtlen = sizeof(selftest_aes_cbc_encblkno8_zero64),
+ .key = selftest_aes_cbc_encblkno8_zero64,
+ .ptxt = selftest_aes_cbc_encblkno8_zero64,
+ .ctxt = selftest_aes_cbc_encblkno8_ctxt,
+ },
};
static int cgd_match(device_t, cfdata_t, void *);
@@ -1264,6 +1289,25 @@
sc->sc_cdata.cf_blocksize = ci->ci_blocksize;
sc->sc_cdata.cf_mode = encblkno[i].v;
+
+ /*
+ * Print a warning if the user selected the legacy encblkno8
+ * mistake, and reject it altogether for ciphers that it
+ * doesn't apply to.
+ */
+ if (encblkno[i].v != CGD_CIPHER_CBC_ENCBLKNO1) {
+ if (strcmp(sc->sc_cfuncs->cf_name, "aes-cbc") &&
+ strcmp(sc->sc_cfuncs->cf_name, "3des-cbc") &&
+ strcmp(sc->sc_cfuncs->cf_name, "bf-cbc")) {
+ log(LOG_WARNING, "cgd: %s only makes sense for cbc,"
+ " not for %s; ignoring\n",
+ encblkno[i].n, sc->sc_cfuncs->cf_name);
+ sc->sc_cdata.cf_mode = CGD_CIPHER_CBC_ENCBLKNO1;
+ } else {
+ log(LOG_WARNING, "cgd: enabling legacy encblkno8\n");
+ }
+ }
+
sc->sc_cdata.cf_keylen = ci->ci_keylen;
sc->sc_cdata.cf_priv = sc->sc_cfuncs->cf_init(ci->ci_keylen, inbuf,
&sc->sc_cdata.cf_blocksize);
@@ -1547,6 +1591,9 @@
DPRINTF_FOLLOW(("cgd_cipher() dir=%d\n", dir));
+ if (sc->sc_cdata.cf_mode == CGD_CIPHER_CBC_ENCBLKNO8)
+ blocksize /= 8;
+
KASSERT(len % blocksize == 0);
/* ensure that sizeof(daddr_t) <= blocksize (for encblkno IVing) */
KASSERT(sizeof(daddr_t) <= blocksize);
@@ -1560,6 +1607,32 @@
IFDEBUG(CGDB_CRYPTO, hexprint("step 1: blkno_buf",
blkno_buf, blocksize));
+ /*
+ * Handle bollocksed up encblkno8 mistake. We used to
+ * compute the encryption of a zero block with blkno as
+ * the CBC IV -- except in an early mistake arising
+ * from bit/byte confusion, we actually computed the
+ * encryption of the last of _eight_ zero blocks under
+ * CBC as the CBC IV.
+ *
+ * Encrypting the block number is handled inside the
+ * cipher dispatch now (even though in practice, both
+ * CBC and XTS will do the same thing), so we have to
+ * simulate the block number that would yield the same
+ * result. So we encrypt _six_ zero blocks -- the
+ * first one and the last one are handled inside the
+ * cipher dispatch.
+ */
+ if (sc->sc_cdata.cf_mode == CGD_CIPHER_CBC_ENCBLKNO8) {
+ static const uint8_t zero[CGD_MAXBLOCKSIZE];
+ uint8_t iv[CGD_MAXBLOCKSIZE];
+
+ memcpy(iv, blkno_buf, blocksize);
+ cipher(sc->sc_cdata.cf_priv, blkno_buf, zero,
+ 6*blocksize, iv, CGD_CIPHER_ENCRYPT);
+ memmove(blkno_buf, blkno_buf + 5*blocksize, blocksize);
+ }
+
cipher(sc->sc_cdata.cf_priv, dst, src, todo, blkno_buf, dir);
dst += todo;
@@ -1589,11 +1662,13 @@
for (size_t i = 0; i < __arraycount(selftests); i++) {
const char *alg = selftests[i].alg;
+ int encblkno8 = selftests[i].encblkno8;
const uint8_t *key = selftests[i].key;
int keylen = selftests[i].keylen;
int txtlen = selftests[i].txtlen;
- aprint_verbose("cgd: self-test %s-%d\n", alg, keylen);
+ aprint_verbose("cgd: self-test %s-%d%s\n", alg, keylen,
+ encblkno8 ? " (encblkno8)" : "");
memset(&sc, 0, sizeof(sc));
@@ -1602,7 +1677,8 @@
panic("%s not implemented", alg);
sc.sc_cdata.cf_blocksize = 8 * selftests[i].blocksize;
- sc.sc_cdata.cf_mode = CGD_CIPHER_CBC_ENCBLKNO1;
+ sc.sc_cdata.cf_mode = encblkno8 ? CGD_CIPHER_CBC_ENCBLKNO8 :
+ CGD_CIPHER_CBC_ENCBLKNO1;
sc.sc_cdata.cf_keylen = keylen;
sc.sc_cdata.cf_priv = sc.sc_cfuncs->cf_init(keylen,
@@ -1612,7 +1688,8 @@
if (sc.sc_cdata.cf_blocksize > CGD_MAXBLOCKSIZE)
panic("bad block size %zu", sc.sc_cdata.cf_blocksize);
- sc.sc_cdata.cf_blocksize /= 8;
+ if (!encblkno8)
+ sc.sc_cdata.cf_blocksize /= 8;
buf = kmem_alloc(txtlen, KM_SLEEP);
memcpy(buf, selftests[i].ptxt, txtlen);
Home |
Main Index |
Thread Index |
Old Index