⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 safe.c

📁 linux下基于加密芯片的加密设备
💻 C
📖 第 1 页 / 共 4 页
字号:
		sc->sc_front = sc->sc_ring;	/* XXX honor batching */	safe_feed(sc, re);	spin_unlock_irqrestore(&sc->sc_ringmtx, flags);	return (0);errout:	if (re->re_src.map != re->re_dst.map)		pci_unmap_iov(sc, &re->re_dst);	if (re->re_src.map)		pci_unmap_iov(sc, &re->re_src);	spin_unlock_irqrestore(&sc->sc_ringmtx, flags);	if (err != ERESTART) {		crp->crp_etype = err;		crypto_done(crp);	} else {		sc->sc_needwakeup |= CRYPTO_SYMQ;	}	return (err);}static voidsafe_callback(struct safe_softc *sc, struct safe_ringentry *re){	struct cryptop *crp = (struct cryptop *)re->re_crp;	struct cryptodesc *crd;	DPRINTF("%s()\n", __FUNCTION__);	safestats.st_opackets++;	safestats.st_obytes += re->re_dst.mapsize;	if (re->re_desc.d_csr & SAFE_PE_CSR_STATUS) {		printk("safe: csr 0x%x cmd0 0x%x cmd1 0x%x\n",			re->re_desc.d_csr,			re->re_sa.sa_cmd0, re->re_sa.sa_cmd1);		safestats.st_peoperr++;		crp->crp_etype = EIO;		/* something more meaningful? */	}	if (re->re_dst.map != NULL && re->re_dst.map != re->re_src.map)		pci_unmap_iov(sc, &re->re_dst);	pci_unmap_iov(sc, &re->re_src);#if 0	/* 	 * If result was written to a differet mbuf chain, swap	 * it in as the return value and reclaim the original.	 */	if ((crp->crp_flags & CRYPTO_F_IMBUF) && re->re_src_m != re->re_dst_m) {		printk("safe: no CRYPTO_F_IMBUF support");		return;	}#endif	if (re->re_flags & SAFE_QFLAGS_COPYOUTIV) {		/* copy out IV for future use */		for (crd = crp->crp_desc; crd; crd = crd->crd_next) {			int ivsize;			if (crd->crd_alg == CRYPTO_DES_CBC ||			    crd->crd_alg == CRYPTO_3DES_CBC) {				ivsize = 2*sizeof(u_int32_t);			} else if (crd->crd_alg == CRYPTO_AES_CBC) {				ivsize = 4*sizeof(u_int32_t);			} else				continue;			if (crp->crp_flags & CRYPTO_F_IMBUF) {				printk("safe: no CRYPTO_F_IMBUF support");			} else if (crp->crp_flags & CRYPTO_F_IOV) {				int i;				cuio_copydata((struct uio *)crp->crp_buf,					crd->crd_skip + crd->crd_len - ivsize,					ivsize,					(caddr_t)sc->sc_sessions[re->re_sesn].ses_iv);				for (i = 0;						i < ivsize/sizeof(sc->sc_sessions[re->re_sesn].ses_iv[0]);						i++)					sc->sc_sessions[re->re_sesn].ses_iv[i] =						cpu_to_le32(sc->sc_sessions[re->re_sesn].ses_iv[i]);			}			break;		}	}	if (re->re_flags & SAFE_QFLAGS_COPYOUTICV) {		/* copy out ICV result */		for (crd = crp->crp_desc; crd; crd = crd->crd_next) {			if (!(crd->crd_alg == CRYPTO_MD5_HMAC ||			    crd->crd_alg == CRYPTO_SHA1_HMAC ||			    crd->crd_alg == CRYPTO_NULL_HMAC))				continue;			if (crd->crd_alg == CRYPTO_SHA1_HMAC) {				/*				 * SHA-1 ICV's are byte-swapped; fix 'em up				 * before copy them to their destination.				 */				bswap32(re->re_sastate.sa_saved_indigest[0]);				bswap32(re->re_sastate.sa_saved_indigest[1]);				bswap32(re->re_sastate.sa_saved_indigest[2]);			}			if (crp->crp_flags & CRYPTO_F_IMBUF) {				printk("safe: no CRYPTO_F_IMBUF support");			} else if (crp->crp_flags & CRYPTO_F_IOV && crp->crp_mac) {				bcopy((caddr_t)re->re_sastate.sa_saved_indigest,					crp->crp_mac, 12);			}			break;		}	}	crypto_done(crp);}#ifndef SAFE_NO_RNG#define	SAFE_RNG_MAXWAIT	1000static voidsafe_rng_init(struct safe_softc *sc){	u_int32_t w, v;	int i;	DPRINTF("%s()\n", __FUNCTION__);	WRITE_REG(sc, SAFE_RNG_CTRL, 0);	/* use default value according to the manual */	WRITE_REG(sc, SAFE_RNG_CNFG, 0x834);	/* magic from SafeNet */	WRITE_REG(sc, SAFE_RNG_ALM_CNT, 0);	/*	 * There is a bug in rev 1.0 of the 1140 that when the RNG	 * is brought out of reset the ready status flag does not	 * work until the RNG has finished its internal initialization.	 *	 * So in order to determine the device is through its	 * initialization we must read the data register, using the	 * status reg in the read in case it is initialized.  Then read	 * the data register until it changes from the first read.	 * Once it changes read the data register until it changes	 * again.  At this time the RNG is considered initialized. 	 * This could take between 750ms - 1000ms in time.	 */	i = 0;	w = READ_REG(sc, SAFE_RNG_OUT);	do {		v = READ_REG(sc, SAFE_RNG_OUT);		if (v != w) {			w = v;			break;		}		DELAY(10);	} while (++i < SAFE_RNG_MAXWAIT);	/* Wait Until data changes again */	i = 0;	do {		v = READ_REG(sc, SAFE_RNG_OUT);		if (v != w)			break;		DELAY(10);	} while (++i < SAFE_RNG_MAXWAIT);}static __inline voidsafe_rng_disable_short_cycle(struct safe_softc *sc){	DPRINTF("%s()\n", __FUNCTION__);	WRITE_REG(sc, SAFE_RNG_CTRL,		READ_REG(sc, SAFE_RNG_CTRL) &~ SAFE_RNG_CTRL_SHORTEN);}static __inline voidsafe_rng_enable_short_cycle(struct safe_softc *sc){	DPRINTF("%s()\n", __FUNCTION__);	WRITE_REG(sc, SAFE_RNG_CTRL, 		READ_REG(sc, SAFE_RNG_CTRL) | SAFE_RNG_CTRL_SHORTEN);}static __inline u_int32_tsafe_rng_read(struct safe_softc *sc){	int i;	DPRINTF("%s()\n", __FUNCTION__);	i = 0;	while (READ_REG(sc, SAFE_RNG_STAT) != 0 && ++i < SAFE_RNG_MAXWAIT)		;	return READ_REG(sc, SAFE_RNG_OUT);}static voidsafe_rng(unsigned long arg){	struct safe_softc *sc = (struct safe_softc *) arg;	u_int32_t buf[SAFE_RNG_MAXBUFSIZ];	/* NB: maybe move to softc */	u_int maxwords;	int i;	DPRINTF("%s()\n", __FUNCTION__);	safestats.st_rng++;	/*	 * Fetch the next block of data.	 */	maxwords = safe_rngbufsize;	if (maxwords > SAFE_RNG_MAXBUFSIZ)		maxwords = SAFE_RNG_MAXBUFSIZ;retry:	for (i = 0; i < maxwords; i++)		buf[i] = safe_rng_read(sc);	/*	 * Check the comparator alarm count and reset the h/w if	 * it exceeds our threshold.  This guards against the	 * hardware oscillators resonating with external signals.	 */	if (READ_REG(sc, SAFE_RNG_ALM_CNT) > safe_rngmaxalarm) {		u_int32_t freq_inc, w;		DPRINTF("%s: alarm count %u exceeds threshold %u\n", __func__,			(unsigned)READ_REG(sc, SAFE_RNG_ALM_CNT), safe_rngmaxalarm);		safestats.st_rngalarm++;		safe_rng_enable_short_cycle(sc);		freq_inc = 18;		for (i = 0; i < 64; i++) {			w = READ_REG(sc, SAFE_RNG_CNFG);			freq_inc = ((w + freq_inc) & 0x3fL);			w = ((w & ~0x3fL) | freq_inc);			WRITE_REG(sc, SAFE_RNG_CNFG, w);			WRITE_REG(sc, SAFE_RNG_ALM_CNT, 0);			(void) safe_rng_read(sc);			DELAY(25);			if (READ_REG(sc, SAFE_RNG_ALM_CNT) == 0) {				safe_rng_disable_short_cycle(sc);				goto retry;			}			freq_inc = 1;		}		safe_rng_disable_short_cycle(sc);	} else		WRITE_REG(sc, SAFE_RNG_ALM_CNT, 0);	mod_timer(&sc->sc_rngto,			jiffies + (safe_rnginterval ? safe_rnginterval : 1) * HZ);}#endif /* SAFE_NO_RNG *//* * Resets the board.  Values in the regesters are left as is * from the reset (i.e. initial values are assigned elsewhere). */static voidsafe_reset_board(struct safe_softc *sc){	u_int32_t v;	/*	 * Reset the device.  The manual says no delay	 * is needed between marking and clearing reset.	 */	DPRINTF("%s()\n", __FUNCTION__);	v = READ_REG(sc, SAFE_PE_DMACFG) &~		(SAFE_PE_DMACFG_PERESET | SAFE_PE_DMACFG_PDRRESET |		 SAFE_PE_DMACFG_SGRESET);	WRITE_REG(sc, SAFE_PE_DMACFG, v				    | SAFE_PE_DMACFG_PERESET				    | SAFE_PE_DMACFG_PDRRESET				    | SAFE_PE_DMACFG_SGRESET);	WRITE_REG(sc, SAFE_PE_DMACFG, v);}/* * Initialize registers we need to touch only once. */static voidsafe_init_board(struct safe_softc *sc){	u_int32_t v, dwords;	DPRINTF("%s()\n", __FUNCTION__);	v = READ_REG(sc, SAFE_PE_DMACFG);	v &=~ (   SAFE_PE_DMACFG_PEMODE			| SAFE_PE_DMACFG_FSENA		/* failsafe enable */			| SAFE_PE_DMACFG_GPRPCI		/* gather ring on PCI */			| SAFE_PE_DMACFG_SPRPCI		/* scatter ring on PCI */			| SAFE_PE_DMACFG_ESDESC		/* endian-swap descriptors */			| SAFE_PE_DMACFG_ESPDESC	/* endian-swap part. desc's */			| SAFE_PE_DMACFG_ESSA		/* endian-swap SA's */			| SAFE_PE_DMACFG_ESPACKET	/* swap the packet data */		  );	v |= SAFE_PE_DMACFG_FSENA		/* failsafe enable */	  |  SAFE_PE_DMACFG_GPRPCI		/* gather ring on PCI */	  |  SAFE_PE_DMACFG_SPRPCI		/* scatter ring on PCI */	  |  SAFE_PE_DMACFG_ESDESC		/* endian-swap descriptors */	  |  SAFE_PE_DMACFG_ESPDESC		/* endian-swap part. desc's */	  |  SAFE_PE_DMACFG_ESSA		/* endian-swap SA's */#if 0	  |  SAFE_PE_DMACFG_ESPACKET    /* swap the packet data */#endif	  ;	WRITE_REG(sc, SAFE_PE_DMACFG, v);#ifdef __BIG_ENDIAN	/* tell the safenet that we are 4321 and not 1234 */	WRITE_REG(sc, SAFE_ENDIAN, 0xe4e41b1b);#endif	if (sc->sc_chiprev == SAFE_REV(1,0)) {		/*		 * Avoid large PCI DMA transfers.  Rev 1.0 has a bug where		 * "target mode transfers" done while the chip is DMA'ing		 * >1020 bytes cause the hardware to lockup.  To avoid this		 * we reduce the max PCI transfer size and use small source		 * particle descriptors (<= 256 bytes).		 */		WRITE_REG(sc, SAFE_DMA_CFG, 256);		printk("safe: Reduce max DMA size to %u words for rev %u.%u WAR\n",			(unsigned) ((READ_REG(sc, SAFE_DMA_CFG)>>2) & 0xff),			(unsigned) SAFE_REV_MAJ(sc->sc_chiprev),			(unsigned) SAFE_REV_MIN(sc->sc_chiprev));	}	/* NB: operands+results are overlaid */	WRITE_REG(sc, SAFE_PE_PDRBASE, sc->sc_ring_dma);	WRITE_REG(sc, SAFE_PE_RDRBASE, sc->sc_ring_dma);	/*	 * Configure ring entry size and number of items in the ring.	 */	KASSERT((sizeof(struct safe_ringentry) % sizeof(u_int32_t)) == 0,		("PE ring entry not 32-bit aligned!"));	dwords = sizeof(struct safe_ringentry) / sizeof(u_int32_t);	WRITE_REG(sc, SAFE_PE_RINGCFG,		(dwords << SAFE_PE_RINGCFG_OFFSET_S) | SAFE_MAX_NQUEUE);	WRITE_REG(sc, SAFE_PE_RINGPOLL, 0);	/* disable polling */	WRITE_REG(sc, SAFE_PE_GRNGBASE, sc->sc_sp_dma);	WRITE_REG(sc, SAFE_PE_SRNGBASE, sc->sc_dp_dma);	WRITE_REG(sc, SAFE_PE_PARTSIZE,		(SAFE_TOTAL_DPART<<16) | SAFE_TOTAL_SPART);	/*	 * NB: destination particles are fixed size.  We use	 *     an mbuf cluster and require all results go to	 *     clusters or smaller.	 */	WRITE_REG(sc, SAFE_PE_PARTCFG, SAFE_MAX_DSIZE);	/* it's now safe to enable PE mode, do it */	WRITE_REG(sc, SAFE_PE_DMACFG, v | SAFE_PE_DMACFG_PEMODE);	/*	 * Configure hardware to use level-triggered interrupts and	 * to interrupt after each descriptor is processed.	 */	WRITE_REG(sc, SAFE_HI_CFG, SAFE_HI_CFG_LEVEL);	WRITE_REG(sc, SAFE_HI_DESC_CNT, 1);	WRITE_REG(sc, SAFE_HI_MASK, SAFE_INT_PE_DDONE | SAFE_INT_PE_ERROR);}/* * Clean up after a chip crash. * It is assumed that the caller in splimp() */static voidsafe_cleanchip(struct safe_softc *sc){	DPRINTF("%s()\n", __FUNCTION__);	if (sc->sc_nqchip != 0) {		struct safe_ringentry *re = sc->sc_back;		while (re != sc->sc_front) {			if (re->re_desc.d_csr != 0)				safe_free_entry(sc, re);			if (++re == sc->sc_ringtop)				re = sc->sc_ring;		}		sc->sc_back = re;		sc->sc_nqchip = 0;	}}/* * free a safe_q * It is assumed that the caller is within splimp(). */static intsafe_free_entry(struct safe_softc *sc, struct safe_ringentry *re){	struct cryptop *crp;	DPRINTF("%s()\n", __FUNCTION__);#ifdef NOTYET	/*	 * Free header MCR	 */	if ((re->re_dst_m != NULL) && (re->re_src_m != re->re_dst_m))		m_freem(re->re_dst_m);#endif	crp = (struct cryptop *)re->re_crp;		re->re_desc.d_csr = 0;		crp->crp_etype = EFAULT;	crypto_done(crp);	return(0);}/* * Routine to reset the chip and clean up. * It is assumed that the caller is in splimp() */static voidsafe_totalreset(struct safe_softc *sc){	DPRINTF("%s()\n", __FUNCTION__);	safe_reset_board(sc);	safe_init_board(sc);	safe_cleanchip(sc);}/* * Is the operand suitable aligned for direct DMA.  Each * segment must be aligned on a 32-bit boundary and all * but the last segment must be a multiple of 4 bytes. */static intsafe_dmamap_aligned(const struct safe_operand *op){	int i;	DPRINTF("%s()\n", __FUNCTION__);	for (i = 0; i < op->nsegs; i++) {		if (op->segs[i].ds_addr & 3)			return (0);		if (i != (op->nsegs - 1) && (op->segs[i].ds_len & 3))			return (0);	}	return (1);}/* * Is the operand suitable for direct DMA as the destination * of an operation.  The hardware requires that each ``particle''

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -