PERFORCE change 1199894 for review

John-Mark Gurney jmg at FreeBSD.org
Mon Sep 8 04:54:24 UTC 2014


http://p4web.freebsd.org/@@1199894?ac=10

Change 1199894 by jmg at jmg_carbon2 on 2014/09/05 18:57:07

	       convert everything down to an iov and operate on that...
	
	       This imports the latest iov code from OpenBSD which includes a
	       bug fix if the number of iov's is more than one...  This also
	       includes a minor optimizations by using two iv buffers and
	       switching between the two instead of always copying...
	
	add ivsize for handling here so we don't copy too much data,
	which might not exist...

Affected files ...

.. //depot/projects/opencrypto/sys/opencrypto/criov.c#3 edit
.. //depot/projects/opencrypto/sys/opencrypto/cryptodev.h#8 edit
.. //depot/projects/opencrypto/sys/opencrypto/cryptosoft.c#10 edit
.. //depot/projects/opencrypto/sys/opencrypto/xform.c#8 edit
.. //depot/projects/opencrypto/sys/opencrypto/xform.h#7 edit

Differences ...

==== //depot/projects/opencrypto/sys/opencrypto/criov.c#3 (text+ko) ====

@@ -99,35 +99,31 @@
 }
 
 /*
- * Return a pointer to iov/offset of location in iovec list.
+ * Return the index and offset of location in iovec list.
  */
-struct iovec *
+int
 cuio_getptr(struct uio *uio, int loc, int *off)
 {
-	struct iovec *iov = uio->uio_iov;
-	int iol = uio->uio_iovcnt;
+	int ind, len;
 
-	while (loc >= 0) {
-		/* Normal end of search */
-		if (loc < iov->iov_len) {
+	ind = 0;
+	while (loc >= 0 && ind < uio->uio_iovcnt) {
+		len = uio->uio_iov[ind].iov_len;
+		if (len > loc) {
 	    		*off = loc;
-	    		return (iov);
+	    		return (ind);
 		}
+		loc -= len;
+		ind++;
+	}
 
-		loc -= iov->iov_len;
-		if (iol == 0) {
-			if (loc == 0) {
-				/* Point at the end of valid data */
-				*off = iov->iov_len;
-				return (iov);
-			} else
-				return (NULL);
-		} else {
-			iov++, iol--;
-		}
-    	}
+	if (ind > 0 && loc == 0) {
+		ind--;
+		*off = uio->uio_iov[ind].iov_len;
+		return (ind);
+	}
 
-	return (NULL);
+	return (-1);
 }
 
 /*
@@ -159,13 +155,6 @@
 }
 
 void
-buf_copyback(caddr_t buf, int off, int size, caddr_t in)
-{
-
-	bcopy(in, buf + off, size);
-}
-
-void
 crypto_copyback(int flags, caddr_t buf, int off, int size, caddr_t in)
 {
 
@@ -205,7 +194,7 @@
 }
 
 void
-crypto_mbuftoiovec(struct mbuf *mbuf, struct iovec **iovptr, int *cnt,
+crypto_mbuftoiov(struct mbuf *mbuf, struct iovec **iovptr, int *cnt,
     int *allocated)
 {
 	struct iovec *iov;
@@ -226,7 +215,8 @@
 			mtmp = m;
 			while ((mtmp = mtmp->m_next) != NULL)
 				j++;
-			iov = malloc(sizeof *iov * (i + j), M_TEMP, M_WAITOK);
+			iov = malloc(sizeof *iov * (i + j), M_CRYPTO_DATA,
+			    M_WAITOK);
 			*allocated = 1;
 			*cnt = i + j;
 			memcpy(iov, *iovptr, sizeof *iov * i);

==== //depot/projects/opencrypto/sys/opencrypto/cryptodev.h#8 (text+ko) ====

@@ -459,13 +459,13 @@
 struct uio;
 extern	void cuio_copydata(struct uio* uio, int off, int len, caddr_t cp);
 extern	void cuio_copyback(struct uio* uio, int off, int len, caddr_t cp);
-extern	struct iovec *cuio_getptr(struct uio *uio, int loc, int *off);
+extern	int cuio_getptr(struct uio *uio, int loc, int *off);
 extern	int cuio_apply(struct uio *uio, int off, int len,
 	    int (*f)(void *, void *, u_int), void *arg);
 
-extern	void buf_copyback(caddr_t buf, int off, int len, caddr_t in);
-
-extern	void crypto_mbuftoiovec(struct mbuf *mbuf, struct iovec **iovptr,
+struct mbuf;
+struct iovec;
+extern	void crypto_mbuftoiov(struct mbuf *mbuf, struct iovec **iovptr,
 	    int *cnt, int *allocated);
 
 extern	void crypto_copyback(int flags, caddr_t buf, int off, int size,

==== //depot/projects/opencrypto/sys/opencrypto/cryptosoft.c#10 (text+ko) ====

@@ -76,111 +76,6 @@
 static	int swcr_freesession(device_t dev, u_int64_t tid);
 static	int swcr_freesession_locked(device_t dev, u_int64_t tid);
 
-typedef void (*copybackfun_t)(void *, int, int, caddr_t);
-
-struct blkdata {
-	void	(*fun)(caddr_t, u_int8_t *);
-	caddr_t	arg;
-	uint8_t	blk[EALG_MAX_BLOCK_LEN];
-	int	blksize;
-	int	blkoff;
-	int	cnt;
-	void	(*copyback)(void *, int, int, caddr_t);
-	void	*copybackarg;
-};
-
-struct cbcdata {
-	struct blkdata	bd;
-	void		(*fun)(caddr_t, u_int8_t *);
-	caddr_t		arg;
-	uint8_t		iv[EALG_MAX_BLOCK_LEN];
-};
-
-static int
-blkdata(void *arg, void *dataarg, u_int len)
-{
-	uint8_t *data;
-	struct blkdata *bd;
-	int blksize;
-	int cnt;
-
-	data = (uint8_t *)dataarg;
-	bd = (struct blkdata *)arg;
-	blksize = bd->blksize;
-
-	/* process remaining from before */
-	if (bd->cnt) {
-		cnt = MIN(blksize - bd->cnt, len);
-		memcpy(&bd->blk[bd->cnt], data, cnt);
-		bd->cnt += cnt;
-
-		if (bd->cnt == blksize) {
-			bd->fun(bd->arg, bd->blk);
-			bd->copyback(bd->copybackarg, bd->blkoff, blksize,
-			    bd->blk);
-			bd->blkoff += blksize;
-			bd->cnt = 0;
-		} else
-			return 0;
-
-		len -= cnt;
-		data += cnt;
-	}
-
-	while (len >= blksize) {
-		bd->fun(bd->arg, data);
-
-		len -= blksize;
-		data += blksize;
-		bd->blkoff += blksize;
-	}
-
-	/* keep the remaining around for the next call */
-	if (len) {
-		bd->cnt = len;
-		memcpy(bd->blk, data, len);
-	}
-
-	return 0;
-}
-
-static void
-cbcencdata(caddr_t arg, uint8_t *in)
-{
-	struct cbcdata *cd;
-	int i;
-
-        cd = (struct cbcdata *)arg;
-
-	for (i = 0; i < cd->bd.blksize; i++) {
-		in[i] ^= cd->iv[i];
-	}
-
-	cd->fun(cd->arg, in);
-
-	bcopy(in, cd->iv, cd->bd.blksize);
-}
-
-static void
-cbcdecdata(caddr_t arg, uint8_t *in)
-{
-	uint8_t		oiv[EALG_MAX_BLOCK_LEN];
-	struct cbcdata *cd;
-	int i;
-
-        cd = (struct cbcdata *)arg;
-
-	bcopy(in, oiv, cd->bd.blksize);
-
-	cd->fun(cd->arg, in);
-
-	for (i = 0; i < cd->bd.blksize; i++) {
-		in[i] ^= cd->iv[i];
-	}
-
-	bcopy(oiv, cd->iv, cd->bd.blksize);
-}
-
 /*
  * Apply a symmetric encryption/decryption algorithm.
  */
@@ -188,14 +83,21 @@
 swcr_encdec(struct cryptodesc *crd, struct swcr_data *sw, caddr_t buf,
     int flags)
 {
-	struct cbcdata cd;
-	struct blkdata bd;
-	unsigned char iv[EALG_MAX_BLOCK_LEN];
+	unsigned char iv[EALG_MAX_BLOCK_LEN], blk[EALG_MAX_BLOCK_LEN], *idat;
+	unsigned char *ivp, *nivp, iv2[EALG_MAX_BLOCK_LEN];
 	struct enc_xform *exf;
-	int blks;
+	int i, j, k, blks, ind, count, ivlen;
+	struct uio *uio, uiolcl;
+	struct iovec iovlcl[4];
+	struct iovec *iov;
+	int iovcnt, iovalloc;
+	int error;
+
+	error = 0;
 
 	exf = sw->sw_exf;
 	blks = exf->blocksize;
+	ivlen = exf->ivsize;
 
 	/* Check for non-padded data */
 	if (crd->crd_len % blks)
@@ -209,21 +111,21 @@
 	if (crd->crd_flags & CRD_F_ENCRYPT) {
 		/* IV explicitly provided ? */
 		if (crd->crd_flags & CRD_F_IV_EXPLICIT)
-			bcopy(crd->crd_iv, iv, blks);
+			bcopy(crd->crd_iv, iv, ivlen);
 		else
-			arc4rand(iv, blks, 0);
+			arc4rand(iv, ivlen, 0);
 
 		/* Do we need to write the IV */
 		if (!(crd->crd_flags & CRD_F_IV_PRESENT))
-			crypto_copyback(flags, buf, crd->crd_inject, blks, iv);
+			crypto_copyback(flags, buf, crd->crd_inject, ivlen, iv);
 
 	} else {	/* Decryption */
 		/* IV explicitly provided ? */
 		if (crd->crd_flags & CRD_F_IV_EXPLICIT)
-			bcopy(crd->crd_iv, iv, blks);
+			bcopy(crd->crd_iv, iv, ivlen);
 		else {
 			/* Get IV off buf */
-			crypto_copydata(flags, buf, crd->crd_inject, blks, iv);
+			crypto_copydata(flags, buf, crd->crd_inject, ivlen, iv);
 		}
 	}
 
@@ -239,20 +141,23 @@
 			return (error);
 	}
 
-	bd = (struct blkdata){};
-	bd.fun = (crd->crd_flags & CRD_F_ENCRYPT) ? exf->encrypt :
-	    exf->decrypt;
-	bd.arg = sw->sw_kschedule;
-	bd.blksize = blks;
-	bd.blkoff = crd->crd_skip;
-        if ((flags & CRYPTO_F_IMBUF) != 0)
-                bd.copyback = (copybackfun_t)m_copyback;
-        else if ((flags & CRYPTO_F_IOV) != 0)
-		bd.copyback = (copybackfun_t)cuio_copyback;
-        else
-		bd.copyback = (copybackfun_t)buf_copyback;
-
-	bd.copybackarg = buf;
+	iov = iovlcl;
+	iovcnt = nitems(iovlcl);
+	iovalloc = 0;
+	uio = &uiolcl;
+	if ((flags & CRYPTO_F_IMBUF) != 0) {
+		crypto_mbuftoiov((struct mbuf *)buf, &iov, &iovcnt,
+		    &iovalloc);
+		uio->uio_iov = iov;
+		uio->uio_iovcnt = iovcnt;
+	} else if ((flags & CRYPTO_F_IOV) != 0)
+		uio = (struct uio *)buf;
+	else {
+		iov[0].iov_base = buf;
+		iov[0].iov_len = crd->crd_skip + crd->crd_len;
+		uio->uio_iov = iov;
+		uio->uio_iovcnt = 1;
+	}
 
 	if (exf->reinit) {
 		/*
@@ -260,24 +165,151 @@
 		 * handling themselves.
 		 */
 		exf->reinit(sw->sw_kschedule, iv);
+	}
+
+	count = crd->crd_skip;
+	ind = cuio_getptr(uio, count, &k);
+	if (ind == -1) {
+		error = EINVAL;
+		goto out;
+	}
+
+	i = crd->crd_len;
+
+	while (i > 0) {
+		/*
+		 * If there's insufficient data at the end of
+		 * an iovec, we have to do some copying.
+		 */
+		if (uio->uio_iov[ind].iov_len < k + blks &&
+		    uio->uio_iov[ind].iov_len != k) {
+			cuio_copydata(uio, count, blks, blk);
+
+			/* Actual encryption/decryption */
+			if (exf->reinit) {
+				if (crd->crd_flags & CRD_F_ENCRYPT) {
+					exf->encrypt(sw->sw_kschedule,
+					    blk);
+				} else {
+					exf->decrypt(sw->sw_kschedule,
+					    blk);
+				}
+			} else if (crd->crd_flags & CRD_F_ENCRYPT) {
+				/* XOR with previous block */
+				for (j = 0; j < blks; j++)
+					blk[j] ^= ivp[j];
+
+				exf->encrypt(sw->sw_kschedule, blk);
+
+				/*
+				 * Keep encrypted block for XOR'ing
+				 * with next block
+				 */
+				bcopy(blk, iv, blks);
+				ivp = iv;
+			} else {	/* decrypt */
+				/*	
+				 * Keep encrypted block for XOR'ing
+				 * with next block
+				 */
+				nivp = (ivp == iv) ? iv2 : iv;
+				bcopy(blk, nivp, blks);
+
+				exf->decrypt(sw->sw_kschedule, blk);
+
+				/* XOR with previous block */
+				for (j = 0; j < blks; j++)
+					blk[j] ^= ivp[j];
+
+				ivp = nivp;
+			}
+
+			/* Copy back decrypted block */
+			cuio_copyback(uio, count, blks, blk);
+
+			count += blks;
+
+			/* Advance pointer */
+			ind = cuio_getptr(uio, count, &k);
+			if (ind == -1) {
+				error = EINVAL;
+				goto out;
+			}
+
+			i -= blks;
+
+			/* Could be done... */
+			if (i == 0)
+				break;
+		}
+
+		/*
+		 * Warning: idat may point to garbage here, but
+		 * we only use it in the while() loop, only if
+		 * there are indeed enough data.
+		 */
+		idat = (char *)uio->uio_iov[ind].iov_base + k;
 
-		crypto_apply(flags, buf, crd->crd_skip, crd->crd_len, blkdata,
-		    &bd);
-	} else {
-		cd.bd = bd;
+		while (uio->uio_iov[ind].iov_len >= k + blks && i > 0) {
+			if (exf->reinit) {
+				if (crd->crd_flags & CRD_F_ENCRYPT) {
+					exf->encrypt(sw->sw_kschedule,
+					    idat);
+				} else {
+					exf->decrypt(sw->sw_kschedule,
+					    idat);
+				}
+			} else if (crd->crd_flags & CRD_F_ENCRYPT) {
+				/* XOR with previous block/IV */
+				for (j = 0; j < blks; j++)
+					idat[j] ^= ivp[j];
+
+				exf->encrypt(sw->sw_kschedule, idat);
+				ivp = idat;
+			} else {	/* decrypt */
+				/*
+				 * Keep encrypted block to be used
+				 * in next block's processing.
+				 */
+				nivp = (ivp == iv) ? iv2 : iv;
+				bcopy(idat, nivp, blks);
+
+				exf->decrypt(sw->sw_kschedule, idat);
+
+				/* XOR with previous block/IV */
+				for (j = 0; j < blks; j++)
+					idat[j] ^= ivp[j];
 
-		cd.fun = bd.fun;
-		cd.arg = bd.arg;
+				ivp = nivp;
+			}
 
-		cd.bd.fun = (crd->crd_flags & CRD_F_ENCRYPT) ? cbcencdata :
-		    cbcdecdata;
-		cd.bd.arg = (caddr_t)&cd;
+			idat += blks;
+			count += blks;
+			k += blks;
+			i -= blks;
+		}
 
-		crypto_apply(flags, buf, crd->crd_skip, crd->crd_len, blkdata,
-		    &cd);
+		/*
+		 * Advance to the next iov if the end of the current iov
+		 * is aligned with the end of a cipher block.
+		 * Note that the code is equivalent to calling:
+		 *      ind = cuio_getptr(uio, count, &k);
+		 */
+		if (i > 0 && k == uio->uio_iov[ind].iov_len) {
+			k = 0;
+			ind++;
+			if (ind >= uio->uio_iovcnt) {
+				error = EINVAL;
+				goto out;
+			}
+		}
 	}
 
-	return 0;
+out:
+	if (iovalloc)
+		free(iov, M_CRYPTO_DATA);
+
+	return (error);
 }
 
 static void

==== //depot/projects/opencrypto/sys/opencrypto/xform.c#8 (text+ko) ====

@@ -153,7 +153,7 @@
 struct enc_xform enc_xform_null = {
 	CRYPTO_NULL_CBC, "NULL",
 	/* NB: blocksize of 4 is to generate a properly aligned ESP header */
-	NULL_BLOCK_LEN, 0, 256, /* 2048 bits, max key */
+	NULL_BLOCK_LEN, NULL_BLOCK_LEN, 0, 256, /* 2048 bits, max key */
 	null_encrypt,
 	null_decrypt,
 	null_setkey,
@@ -163,7 +163,7 @@
 
 struct enc_xform enc_xform_des = {
 	CRYPTO_DES_CBC, "DES",
-	DES_BLOCK_LEN, 8, 8,
+	DES_BLOCK_LEN, DES_BLOCK_LEN, 8, 8,
 	des1_encrypt,
 	des1_decrypt,
 	des1_setkey,
@@ -173,7 +173,7 @@
 
 struct enc_xform enc_xform_3des = {
 	CRYPTO_3DES_CBC, "3DES",
-	DES3_BLOCK_LEN, 24, 24,
+	DES3_BLOCK_LEN, DES3_BLOCK_LEN, 24, 24,
 	des3_encrypt,
 	des3_decrypt,
 	des3_setkey,
@@ -183,7 +183,7 @@
 
 struct enc_xform enc_xform_blf = {
 	CRYPTO_BLF_CBC, "Blowfish",
-	BLOWFISH_BLOCK_LEN, 5, 56 /* 448 bits, max key */,
+	BLOWFISH_BLOCK_LEN, BLOWFISH_BLOCK_LEN, 5, 56 /* 448 bits, max key */,
 	blf_encrypt,
 	blf_decrypt,
 	blf_setkey,
@@ -193,7 +193,7 @@
 
 struct enc_xform enc_xform_cast5 = {
 	CRYPTO_CAST_CBC, "CAST-128",
-	CAST128_BLOCK_LEN, 5, 16,
+	CAST128_BLOCK_LEN, CAST128_BLOCK_LEN, 5, 16,
 	cast5_encrypt,
 	cast5_decrypt,
 	cast5_setkey,
@@ -203,7 +203,7 @@
 
 struct enc_xform enc_xform_skipjack = {
 	CRYPTO_SKIPJACK_CBC, "Skipjack",
-	SKIPJACK_BLOCK_LEN, 10, 10,
+	SKIPJACK_BLOCK_LEN, SKIPJACK_BLOCK_LEN, 10, 10,
 	skipjack_encrypt,
 	skipjack_decrypt, skipjack_setkey,
 	skipjack_zerokey,
@@ -212,7 +212,7 @@
 
 struct enc_xform enc_xform_rijndael128 = {
 	CRYPTO_RIJNDAEL128_CBC, "Rijndael-128/AES",
-	RIJNDAEL128_BLOCK_LEN, 16, 32,
+	RIJNDAEL128_BLOCK_LEN, RIJNDAEL128_BLOCK_LEN, 16, 32,
 	rijndael128_encrypt,
 	rijndael128_decrypt,
 	rijndael128_setkey,
@@ -222,7 +222,7 @@
 
 struct enc_xform enc_xform_aes_icm = {
 	CRYPTO_AES_ICM, "AES-ICM",
-	RIJNDAEL128_BLOCK_LEN, 16, 32,
+	RIJNDAEL128_BLOCK_LEN, RIJNDAEL128_BLOCK_LEN, 16, 32,
 	aes_icm_crypt,
 	aes_icm_crypt,
 	aes_icm_setkey,
@@ -232,7 +232,7 @@
 
 struct enc_xform enc_xform_aes_nist_gcm = {
 	CRYPTO_AES_NIST_GCM_16, "AES-GCM",
-	1, 16, 32,
+	1, 12, 16, 32,
 	aes_icm_crypt,
 	aes_icm_crypt,
 	aes_icm_setkey,
@@ -242,7 +242,7 @@
 
 struct enc_xform enc_xform_aes_nist_gmac = {
 	CRYPTO_AES_NIST_GMAC, "AES-GMAC",
-	1, 16, 32,
+	1, 12, 16, 32,
 	NULL,
 	NULL,
 	NULL,
@@ -252,7 +252,7 @@
 
 struct enc_xform enc_xform_aes_xts = {
 	CRYPTO_AES_XTS, "AES-XTS",
-	RIJNDAEL128_BLOCK_LEN, 32, 64,
+	RIJNDAEL128_BLOCK_LEN, 8, 32, 64,
 	aes_xts_encrypt,
 	aes_xts_decrypt,
 	aes_xts_setkey,
@@ -262,7 +262,7 @@
 
 struct enc_xform enc_xform_arc4 = {
 	CRYPTO_ARC4, "ARC4",
-	1, 1, 32,
+	1, 1, 1, 32,
 	NULL,
 	NULL,
 	NULL,
@@ -272,7 +272,7 @@
 
 struct enc_xform enc_xform_camellia = {
 	CRYPTO_CAMELLIA_CBC, "Camellia",
-	CAMELLIA_BLOCK_LEN, 8, 32,
+	CAMELLIA_BLOCK_LEN, CAMELLIA_BLOCK_LEN, 8, 32,
 	cml_encrypt,
 	cml_decrypt,
 	cml_setkey,

==== //depot/projects/opencrypto/sys/opencrypto/xform.h#7 (text+ko) ====

@@ -58,6 +58,7 @@
 	int type;
 	char *name;
 	u_int16_t blocksize;
+	u_int16_t ivsize;
 	u_int16_t minkey, maxkey;
 	void (*encrypt) (caddr_t, u_int8_t *);
 	void (*decrypt) (caddr_t, u_int8_t *);


More information about the p4-projects mailing list