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))

Reply via email to