Module Name: src
Committed By: riastradh
Date: Sun May 17 00:52:31 UTC 2020
Modified Files:
src/sys/dev/pci: hifn7751.c hifn7751var.h
Log Message:
Merge updates from OpenBSD's hifn(4) crypto decelerator driver.
Highlights:
- Apply a ten-year-old fix to the driver's misuse of previously
exposed ciphertext as IV for the next ciphertext with CBC.
(Someone^TM should make sure there are no other drivers still doing
this...)
- Various zeroing of buffers.
- Various minor cosmetic changes.
To generate a diff of this commit:
cvs rdiff -u -r1.69 -r1.70 src/sys/dev/pci/hifn7751.c
cvs rdiff -u -r1.14 -r1.15 src/sys/dev/pci/hifn7751var.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/dev/pci/hifn7751.c
diff -u src/sys/dev/pci/hifn7751.c:1.69 src/sys/dev/pci/hifn7751.c:1.70
--- src/sys/dev/pci/hifn7751.c:1.69 Sun May 17 00:50:24 2020
+++ src/sys/dev/pci/hifn7751.c Sun May 17 00:52:31 2020
@@ -1,6 +1,5 @@
-/* $NetBSD: hifn7751.c,v 1.69 2020/05/17 00:50:24 riastradh Exp $ */
-/* $FreeBSD: hifn7751.c,v 1.5.2.7 2003/10/08 23:52:00 sam Exp $ */
-/* $OpenBSD: hifn7751.c,v 1.140 2003/08/01 17:55:54 deraadt Exp $ */
+/* $NetBSD: hifn7751.c,v 1.70 2020/05/17 00:52:31 riastradh Exp $ */
+/* $OpenBSD: hifn7751.c,v 1.179 2020/01/11 21:34:03 cheloha Exp $ */
/*
* Invertex AEON / Hifn 7751 driver
@@ -44,11 +43,11 @@
*/
/*
- * Driver for various Hifn pre-HIPP encryption processors.
+ * Driver for various Hifn encryption processors.
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: hifn7751.c,v 1.69 2020/05/17 00:50:24 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: hifn7751.c,v 1.70 2020/05/17 00:52:31 riastradh Exp $");
#include <sys/param.h>
#include <sys/cprng.h>
@@ -179,7 +178,6 @@ static const struct hifn_product {
"Hifn 7956",
},
-
{ 0, 0,
0,
NULL
@@ -810,7 +808,7 @@ static struct pci2id {
}, {
/*
* Other vendors share this PCI ID as well, such as
- * http://www.powercrypt.com, and obviously they also
+ * powercrypt, and obviously they also
* use the same key.
*/
PCI_VENDOR_HIFN,
@@ -831,7 +829,7 @@ hifn_enable_crypto(struct hifn_softc *sc
uint32_t dmacfg, ramcfg, encl, addr, i;
const char *offtbl = NULL;
- for (i = 0; i < sizeof(pci2id)/sizeof(pci2id[0]); i++) {
+ for (i = 0; i < __arraycount(pci2id); i++) {
if (pci2id[i].pci_vendor == PCI_VENDOR(pciid) &&
pci2id[i].pci_prod == PCI_PRODUCT(pciid)) {
offtbl = pci2id[i].card_id;
@@ -1229,7 +1227,6 @@ hifn_writeramaddr(struct hifn_softc *sc,
printf("%s: writeramaddr -- "
"result[%d](addr %d) still valid\n",
device_xname(sc->sc_dv), resi, addr);
- r = -1;
return (-1);
} else
r = 0;
@@ -1375,7 +1372,7 @@ hifn_write_command(struct hifn_command *
base_cmd->total_dest_count = htole16(dlen & HIFN_BASE_CMD_LENMASK_LO);
dlen >>= 16;
slen >>= 16;
- base_cmd->session_num = htole16(cmd->session_num |
+ base_cmd->session_num = htole16(
((slen << HIFN_BASE_CMD_SRCLEN_S) & HIFN_BASE_CMD_SRCLEN_M) |
((dlen << HIFN_BASE_CMD_DSTLEN_S) & HIFN_BASE_CMD_DSTLEN_M));
buf_pos += sizeof(struct hifn_base_command);
@@ -2045,9 +2042,8 @@ hifn_newsession(void *arg, uint32_t *sid
return retval;
mutex_spin_enter(&sc->sc_mtx);
-
for (i = 0; i < sc->sc_maxses; i++)
- if (sc->sc_sessions[i].hs_state == HS_STATE_FREE)
+ if (isclr(sc->sc_sessions, i))
break;
if (i == sc->sc_maxses) {
retval = ENOMEM;
@@ -2068,10 +2064,6 @@ hifn_newsession(void *arg, uint32_t *sid
case CRYPTO_DES_CBC:
case CRYPTO_3DES_CBC:
case CRYPTO_AES_CBC:
- cprng_fast(sc->sc_sessions[i].hs_iv,
- c->cri_alg == CRYPTO_AES_CBC ?
- HIFN_AES_IV_LENGTH : HIFN_IV_LENGTH);
- /*FALLTHROUGH*/
case CRYPTO_ARC4:
if (cry) {
goto out;
@@ -2103,7 +2095,7 @@ hifn_newsession(void *arg, uint32_t *sid
}
*sidp = HIFN_SID(device_unit(sc->sc_dv), i);
- sc->sc_sessions[i].hs_state = HS_STATE_USED;
+ setbit(sc->sc_sessions, i);
retval = 0;
out:
@@ -2133,8 +2125,7 @@ hifn_freesession(void *arg, uint64_t tid
mutex_spin_exit(&sc->sc_mtx);
return (EINVAL);
}
-
- memset(&sc->sc_sessions[session], 0, sizeof(sc->sc_sessions[session]));
+ clrbit(sc->sc_sessions, session);
mutex_spin_exit(&sc->sc_mtx);
return (0);
}
@@ -2144,7 +2135,7 @@ hifn_process(void *arg, struct cryptop *
{
struct hifn_softc *sc = arg;
struct hifn_command *cmd = NULL;
- int session, err, ivlen;
+ int session, err = 0, ivlen;
struct cryptodesc *crd1, *crd2, *maccrd, *enccrd;
if (crp == NULL || crp->crp_callback == NULL) {
@@ -2154,14 +2145,12 @@ hifn_process(void *arg, struct cryptop *
mutex_spin_enter(&sc->sc_mtx);
session = HIFN_SESSION(crp->crp_sid);
-
- if (sc == NULL || session >= sc->sc_maxses) {
+ if (session >= sc->sc_maxses) {
err = EINVAL;
goto errout;
}
- cmd = (struct hifn_command *)malloc(sizeof(struct hifn_command),
- M_DEVBUF, M_NOWAIT|M_ZERO);
+ cmd = malloc(sizeof(*cmd), M_DEVBUF, M_NOWAIT | M_ZERO);
if (cmd == NULL) {
hifnstats.hst_nomem++;
err = ENOMEM;
@@ -2203,7 +2192,7 @@ hifn_process(void *arg, struct cryptop *
enccrd = crd1;
#ifdef CRYPTO_LZS_COMP
} else if (crd1->crd_alg == CRYPTO_LZS_COMP) {
- return (hifn_compression(sc, crp, cmd));
+ return (hifn_compression(sc, crp, cmd));
#endif
} else {
err = EINVAL;
@@ -2248,10 +2237,6 @@ hifn_process(void *arg, struct cryptop *
switch (enccrd->crd_alg) {
case CRYPTO_ARC4:
cmd->cry_masks |= HIFN_CRYPT_CMD_ALG_RC4;
- if ((enccrd->crd_flags & CRD_F_ENCRYPT)
- != sc->sc_sessions[session].hs_prev_op)
- sc->sc_sessions[session].hs_state =
- HS_STATE_USED;
break;
case CRYPTO_DES_CBC:
cmd->cry_masks |= HIFN_CRYPT_CMD_ALG_DES |
@@ -2279,8 +2264,7 @@ hifn_process(void *arg, struct cryptop *
if (enccrd->crd_flags & CRD_F_IV_EXPLICIT)
memcpy(cmd->iv, enccrd->crd_iv, ivlen);
else
- bcopy(sc->sc_sessions[session].hs_iv,
- cmd->iv, ivlen);
+ cprng_fast(cmd->iv, ivlen);
if ((enccrd->crd_flags & CRD_F_IV_PRESENT)
== 0) {
@@ -2301,12 +2285,14 @@ hifn_process(void *arg, struct cryptop *
enccrd->crd_inject, ivlen, cmd->iv);
else if (crp->crp_flags & CRYPTO_F_IOV)
cuio_copydata(cmd->srcu.src_io,
- enccrd->crd_inject, ivlen, cmd->iv);
+ enccrd->crd_inject,
+ ivlen, cmd->iv);
}
}
cmd->ck = enccrd->crd_key;
cmd->cklen = enccrd->crd_klen >> 3;
+ cmd->cry_masks |= HIFN_CRYPT_CMD_NEW_KEY;
/*
* Need to specify the size for the AES key in the masks.
@@ -2328,9 +2314,6 @@ hifn_process(void *arg, struct cryptop *
goto errout;
}
}
-
- if (sc->sc_sessions[session].hs_state == HS_STATE_USED)
- cmd->cry_masks |= HIFN_CRYPT_CMD_NEW_KEY;
}
if (maccrd) {
@@ -2360,9 +2343,8 @@ hifn_process(void *arg, struct cryptop *
break;
}
- if ((maccrd->crd_alg == CRYPTO_SHA1_HMAC_96 ||
- maccrd->crd_alg == CRYPTO_MD5_HMAC_96) &&
- sc->sc_sessions[session].hs_state == HS_STATE_USED) {
+ if (maccrd->crd_alg == CRYPTO_SHA1_HMAC_96 ||
+ maccrd->crd_alg == CRYPTO_MD5_HMAC_96) {
cmd->mac_masks |= HIFN_MAC_CMD_NEW_KEY;
memcpy(cmd->mac, maccrd->crd_key, maccrd->crd_klen >> 3);
memset(cmd->mac + (maccrd->crd_klen >> 3), 0,
@@ -2376,12 +2358,6 @@ hifn_process(void *arg, struct cryptop *
err = hifn_crypto(sc, cmd, crp, hint);
if (err == 0) {
- if (enccrd)
- sc->sc_sessions[session].hs_prev_op =
- enccrd->crd_flags & CRD_F_ENCRYPT;
- if (sc->sc_sessions[session].hs_state == HS_STATE_USED)
- sc->sc_sessions[session].hs_state = HS_STATE_KEY;
- mutex_spin_exit(&sc->sc_mtx);
return 0;
} else if (err == ERESTART) {
/*
@@ -2400,8 +2376,10 @@ hifn_process(void *arg, struct cryptop *
}
errout:
- if (cmd != NULL)
+ if (cmd != NULL) {
+ explicit_memset(cmd, 0, sizeof(*cmd));
free(cmd, M_DEVBUF);
+ }
if (err == EINVAL)
hifnstats.hst_invalid++;
else
@@ -2465,6 +2443,7 @@ hifn_abort(struct hifn_softc *sc)
bus_dmamap_unload(sc->sc_dmat, cmd->src_map);
bus_dmamap_destroy(sc->sc_dmat, cmd->src_map);
+ explicit_memset(cmd, 0, sizeof(*cmd));
free(cmd, M_DEVBUF);
if (crp->crp_etype != EAGAIN)
crypto_done(crp);
@@ -2476,11 +2455,6 @@ hifn_abort(struct hifn_softc *sc)
}
dma->resk = i; dma->resu = u;
- /* Force upload of key next time */
- for (i = 0; i < sc->sc_maxses; i++)
- if (sc->sc_sessions[i].hs_state == HS_STATE_KEY)
- sc->sc_sessions[i].hs_state = HS_STATE_USED;
-
hifn_reset_board(sc, 1);
hifn_init_dma(sc);
hifn_init_pci_registers(sc);
@@ -2493,7 +2467,7 @@ hifn_callback(struct hifn_softc *sc, str
struct cryptop *crp = cmd->crp;
struct cryptodesc *crd;
struct mbuf *m;
- int totlen, i, u, ivlen;
+ int totlen, i, u;
if (cmd->src_map == cmd->dst_map)
bus_dmamap_sync(sc->sc_dmat, cmd->src_map,
@@ -2527,11 +2501,11 @@ hifn_callback(struct hifn_softc *sc, str
if (crp->crp_flags & CRYPTO_F_IMBUF)
m_copyback((struct mbuf *)crp->crp_buf,
cmd->src_map->dm_mapsize - cmd->sloplen,
- cmd->sloplen, (void *)&dma->slop[cmd->slopidx]);
+ cmd->sloplen, &dma->slop[cmd->slopidx]);
else if (crp->crp_flags & CRYPTO_F_IOV)
cuio_copyback((struct uio *)crp->crp_buf,
cmd->src_map->dm_mapsize - cmd->sloplen,
- cmd->sloplen, (void *)&dma->slop[cmd->slopidx]);
+ cmd->sloplen, &dma->slop[cmd->slopidx]);
}
i = dma->dstk; u = dma->dstu;
@@ -2555,31 +2529,6 @@ hifn_callback(struct hifn_softc *sc, str
hifnstats.hst_obytes += cmd->dst_map->dm_mapsize;
- if ((cmd->base_masks & (HIFN_BASE_CMD_CRYPT | HIFN_BASE_CMD_DECODE)) ==
- HIFN_BASE_CMD_CRYPT) {
- for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
- if (crd->crd_alg != CRYPTO_DES_CBC &&
- crd->crd_alg != CRYPTO_3DES_CBC &&
- crd->crd_alg != CRYPTO_AES_CBC)
- continue;
- ivlen = ((crd->crd_alg == CRYPTO_AES_CBC) ?
- HIFN_AES_IV_LENGTH : HIFN_IV_LENGTH);
- if (crp->crp_flags & CRYPTO_F_IMBUF)
- m_copydata((struct mbuf *)crp->crp_buf,
- crd->crd_skip + crd->crd_len - ivlen,
- ivlen,
- cmd->softc->sc_sessions[cmd->session_num].hs_iv);
- else if (crp->crp_flags & CRYPTO_F_IOV) {
- cuio_copydata((struct uio *)crp->crp_buf,
- crd->crd_skip + crd->crd_len - ivlen,
- ivlen,
- cmd->softc->sc_sessions[cmd->session_num].hs_iv);
- }
- /* XXX We do not handle contig data */
- break;
- }
- }
-
if (cmd->base_masks & HIFN_BASE_CMD_MAC) {
uint8_t *macbuf;
@@ -2616,6 +2565,7 @@ hifn_callback(struct hifn_softc *sc, str
}
bus_dmamap_unload(sc->sc_dmat, cmd->src_map);
bus_dmamap_destroy(sc->sc_dmat, cmd->src_map);
+ explicit_memset(cmd, 0, sizeof(*cmd));
free(cmd, M_DEVBUF);
crypto_done(crp);
}
@@ -2740,6 +2690,7 @@ fail:
bus_dmamap_unload(sc->sc_dmat, cmd->src_map);
bus_dmamap_destroy(sc->sc_dmat, cmd->src_map);
}
+ explicit_memset(cmd, 0, sizeof(*cmd));
free(cmd, M_DEVBUF);
if (err == EINVAL)
hifnstats.hst_invalid++;
@@ -2789,14 +2740,13 @@ hifn_compress_enter(struct hifn_softc *s
}
/*
- * We don't worry about missing an interrupt (which a "command wait"
- * interrupt salvages us from), unless there is more than one command
- * in the queue.
+ * Always enable the command wait interrupt. We are obviously
+ * missing an interrupt or two somewhere. Enabling the command wait
+ * interrupt will guarantee we get called periodically until all
+ * of the queues are drained and thus work around this.
*/
- if (dma->cmdu > 1) {
- sc->sc_dmaier |= HIFN_DMAIER_C_WAIT;
- WRITE_REG_1(sc, HIFN_1_DMA_IER, sc->sc_dmaier);
- }
+ sc->sc_dmaier |= HIFN_DMAIER_C_WAIT;
+ WRITE_REG_1(sc, HIFN_1_DMA_IER, sc->sc_dmaier);
hifnstats.hst_ipackets++;
hifnstats.hst_ibytes += cmd->src_map->dm_mapsize;
@@ -2953,6 +2903,7 @@ hifn_callback_comp(struct hifn_softc *sc
}
m_freem(cmd->srcu.src_m);
+ explicit_memset(cmd, 0, sizeof(*cmd));
free(cmd, M_DEVBUF);
crp->crp_etype = 0;
crypto_done(crp);
@@ -2969,8 +2920,8 @@ out:
bus_dmamap_unload(sc->sc_dmat, cmd->src_map);
bus_dmamap_destroy(sc->sc_dmat, cmd->src_map);
}
- if (cmd->dstu.dst_m != NULL)
- m_freem(cmd->dstu.dst_m);
+ m_freem(cmd->dstu.dst_m);
+ explicit_memset(cmd, 0, sizeof(*cmd));
free(cmd, M_DEVBUF);
crp->crp_etype = err;
crypto_done(crp);
@@ -2995,7 +2946,7 @@ hifn_mkmbuf_chain(int totlen, struct mbu
m_copy_pkthdr(m0, mtemplate);
MCLGET(m0, M_DONTWAIT);
if (!(m0->m_flags & M_EXT)) {
- m_freem(m0);
+ m_freem(m0);
return (NULL);
}
len = MCLBYTES;
@@ -3012,7 +2963,7 @@ hifn_mkmbuf_chain(int totlen, struct mbu
}
MCLGET(m, M_DONTWAIT);
if (!(m->m_flags & M_EXT)) {
- m_freem(m);
+ m_free(m);
m_freem(m0);
return (NULL);
}
Index: src/sys/dev/pci/hifn7751var.h
diff -u src/sys/dev/pci/hifn7751var.h:1.14 src/sys/dev/pci/hifn7751var.h:1.15
--- src/sys/dev/pci/hifn7751var.h:1.14 Sun May 17 00:51:27 2020
+++ src/sys/dev/pci/hifn7751var.h Sun May 17 00:52:31 2020
@@ -1,5 +1,5 @@
-/* $NetBSD: hifn7751var.h,v 1.14 2020/05/17 00:51:27 riastradh Exp $ */
-/* $OpenBSD: hifn7751var.h,v 1.48 2003/02/24 20:36:02 jason Exp $ */
+/* $NetBSD: hifn7751var.h,v 1.15 2020/05/17 00:52:31 riastradh Exp $ */
+/* $OpenBSD: hifn7751var.h,v 1.54 2020/01/11 21:34:04 cheloha Exp $ */
/*
* Invertex AEON / Hifn 7751 driver
@@ -62,8 +62,8 @@
#define HIFN_3DES_KEY_LENGTH 24
#define HIFN_MAX_CRYPT_KEY_LENGTH HIFN_3DES_KEY_LENGTH
#define HIFN_IV_LENGTH 8
-#define HIFN_AES_IV_LENGTH 16
-#define HIFN_MAX_IV_LENGTH HIFN_AES_IV_LENGTH
+#define HIFN_AES_IV_LENGTH 16
+#define HIFN_MAX_IV_LENGTH HIFN_AES_IV_LENGTH
/*
* Length values for authentication
@@ -105,17 +105,6 @@ struct hifn_dma {
int cmdk, srck, dstk, resk;
};
-struct hifn_session {
- int hs_state;
- int hs_prev_op; /* XXX collapse into hs_flags? */
- u_int8_t hs_iv[HIFN_MAX_IV_LENGTH];
-};
-
-/* We use a state machine on sessions */
-#define HS_STATE_FREE 0 /* unused session entry */
-#define HS_STATE_USED 1 /* allocated, but key not on card */
-#define HS_STATE_KEY 2 /* allocated and key is on card */
-
#define HIFN_RING_SYNC(sc, r, i, f) \
bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_dmamap, \
offsetof(struct hifn_dma, r[i]), sizeof(struct hifn_desc), (f))
@@ -155,23 +144,20 @@ struct hifn_softc {
int sc_dmansegs;
int32_t sc_cid;
int sc_maxses;
+ int sc_nsessions;
int sc_ramsize;
int sc_flags;
-#define HIFN_HAS_RNG 0x01
-#define HIFN_HAS_PUBLIC 0x02
-#define HIFN_HAS_AES 0x04 /* includes AES support */
-#define HIFN_IS_7811 0x08 /* Hifn 7811 part */
-#define HIFN_IS_7956 0x10 /* Hifn 7956/7955 don't have SDRAM */
-#define HIFN_NO_BURSTWRITE 0x20
-#define HIFN_HAS_LEDS 0x40
-
-#define HIFN_RNG_BITSPER 17 /* From Hifn 6500 paper: 0.06 bits
- of entropy per RNG register bit
- worst-case */
+#define HIFN_HAS_RNG 0x01 /* includes random number generator */
+#define HIFN_HAS_PUBLIC 0x02 /* includes public key support */
+#define HIFN_IS_7811 0x04 /* Hifn 7811 part */
+#define HIFN_NO_BURSTWRITE 0x08 /* can't handle PCI burst writes */
+#define HIFN_HAS_LEDS 0x10 /* Has LEDs to blink */
+#define HIFN_HAS_AES 0x20 /* includes AES support */
+#define HIFN_IS_7956 0x40 /* Hifn 7955/7956 part */
struct callout sc_rngto; /* rng timeout */
struct callout sc_tickto; /* led-clear timeout */
- krndsource_t sc_rnd_source;
+ krndsource_t sc_rnd_source;
int sc_rnghz;
int sc_rng_need; /* how many bytes wanted */
int sc_c_busy; /* command ring busy */
@@ -180,9 +166,7 @@ struct hifn_softc {
int sc_r_busy; /* result ring busy */
int sc_active; /* for initial countdown */
int sc_needwakeup; /* ops q'd wating on resources */
- int sc_curbatch; /* # ops submitted w/o int */
- int sc_suspended;
- struct hifn_session sc_sessions[2048];
+ uint8_t sc_sessions[2048/NBBY];
pci_chipset_tag_t sc_pci_pc;
pcitag_t sc_pci_tag;
bus_size_t sc_waw_lastreg;
@@ -190,6 +174,10 @@ struct hifn_softc {
kmutex_t sc_mtx;
};
+#define HIFN_RNG_BITSPER 17 /* From Hifn 6500 paper: 0.06 bits
+ of entropy per RNG register bit
+ worst-case */
+
#define WRITE_REG_0(sc,reg,val) hifn_write_4((sc), 0, (reg), (val))
#define WRITE_REG_1(sc,reg,val) hifn_write_4((sc), 1, (reg), (val))
#define READ_REG_0(sc,reg) hifn_read_4((sc), 0, (reg))