From 8a3e2ffecabd2d344a13102f0f8b8478b3b75476 Mon Sep 17 00:00:00 2001
From: Nikos Mavrogiannopoulos <nmav@gnutls.org>
Date: Fri, 4 Dec 2009 01:34:03 +0200
Subject: [PATCH 007/291] cryptodev: Revert is a cryptodev release that intends
 to be fully compatible with OpenBSD and FreeBSD APIs.

This reverts commit 30181c1a49a63fddc97dd10dbac1b49568aede1f.

Conflicts:

	cryptodev.c
---
 drivers/staging/crypto/cryptodev/cryptodev.c | 188 +++++++++++----------------
 drivers/staging/crypto/cryptodev/cryptodev.h |  29 +----
 2 files changed, 77 insertions(+), 140 deletions(-)

diff --git a/drivers/staging/crypto/cryptodev/cryptodev.c b/drivers/staging/crypto/cryptodev/cryptodev.c
index 53808043bb10..17a470800a2e 100644
--- a/drivers/staging/crypto/cryptodev/cryptodev.c
+++ b/drivers/staging/crypto/cryptodev/cryptodev.c
@@ -401,7 +401,10 @@ crypto_get_session_by_sid(struct fcrypt *fcr, uint32_t sid)
 	return ses_ptr;
 }
 
-static int crypto_runv(struct fcrypt *fcr, struct crypt_opv *copv)
+/* This is the main crypto function - feed it with plaintext 
+   and get a ciphertext (or vice versa :-) */
+static int
+crypto_run(struct fcrypt *fcr, struct crypt_op *cop)
 {
 	char *data, ivp[EALG_MAX_BLOCK_LEN];
 	char __user *src, __user *dst;
@@ -411,7 +414,6 @@ static int crypto_runv(struct fcrypt *fcr, struct crypt_opv *copv)
 	size_t nbytes, bufsize;
 	int ret = 0;
 	uint8_t hash_output[HASH_MAX_LEN];
-	int blocksize=1, i;
 	struct blkcipher_desc bdesc = {
         .flags = CRYPTO_TFM_REQ_MAY_SLEEP,
 	};
@@ -420,27 +422,29 @@ static int crypto_runv(struct fcrypt *fcr, struct crypt_opv *copv)
 	};
 
 
-	if (unlikely(copv->op != COP_ENCRYPT && copv->op != COP_DECRYPT)) {
-		dprintk(1, KERN_DEBUG, "invalid operation op=%u\n", copv->op);
+	if (unlikely(cop->op != COP_ENCRYPT && cop->op != COP_DECRYPT)) {
+		dprintk(1, KERN_DEBUG, "invalid operation op=%u\n", cop->op);
 		return -EINVAL;
 	}
 
-	ses_ptr = crypto_get_session_by_sid(fcr, copv->ses);
+	ses_ptr = crypto_get_session_by_sid(fcr, cop->ses);
 	if (!ses_ptr) {
-		dprintk(1, KERN_ERR, "invalid session ID=0x%08X\n", copv->ses);
+		dprintk(1, KERN_ERR, "invalid session ID=0x%08X\n", cop->ses);
 		return -EINVAL;
 	}
 
+	nbytes = cop->len;
 	data = (char*)__get_free_page(GFP_KERNEL);
 
 	if (unlikely(!data)) {
 		ret = -ENOMEM;
 		goto out_unlock;
 	}
+	bufsize = PAGE_SIZE < nbytes ? PAGE_SIZE : nbytes;
 
+	nbytes = cop->len;
 	bdesc.tfm = ses_ptr->tfm;
 	hdesc.tfm = ses_ptr->hash_tfm;
-
 	if (hdesc.tfm) {
 		ret = crypto_hash_init(&hdesc);
 		if (unlikely(ret)) {
@@ -450,97 +454,81 @@ static int crypto_runv(struct fcrypt *fcr, struct crypt_opv *copv)
 		}
 	}
 
-	if (ses_ptr->tfm) {
-		blocksize = crypto_blkcipher_blocksize(ses_ptr->tfm);
-		ivsize = crypto_blkcipher_ivsize(ses_ptr->tfm);
-
-		if (copv->iv) {
-			copy_from_user(ivp, copv->iv, ivsize);
-			crypto_blkcipher_set_iv(ses_ptr->tfm, ivp, ivsize);
-		}
-	}
-
-	dst = copv->dst;
+	if (bdesc.tfm) {
+		int blocksize = crypto_blkcipher_blocksize(bdesc.tfm);
 
-	for (i=0;i<copv->iovec_cnt;i++) {
-		nbytes = copv->iovec[i].len;
-
-		if (unlikely(bdesc.tfm && (copv->iovec[i].op_flags & IOP_CIPHER) && (nbytes % blocksize))) {
+		if (unlikely(nbytes % blocksize)) {
 			dprintk(1, KERN_ERR,
 				"data size (%zu) isn't a multiple of block size (%u)\n",
-				nbytes, crypto_blkcipher_blocksize(ses_ptr->tfm));
+				nbytes, blocksize);
 			ret = -EINVAL;
 			goto out_unlock;
 		}
 
-		bufsize = PAGE_SIZE < nbytes ? PAGE_SIZE : nbytes;
+		ivsize = crypto_blkcipher_ivsize(bdesc.tfm);
 
-		src = copv->iovec[i].src;
+		if (cop->iv) {
+			copy_from_user(ivp, cop->iv, ivsize);
+			crypto_blkcipher_set_iv(bdesc.tfm, ivp, ivsize);
+		}
+	}
 
-		while(nbytes > 0) {
-			size_t current_len = nbytes > bufsize ? bufsize : nbytes;
+	src = cop->src;
+	dst = cop->dst;
 
-			copy_from_user(data, src, current_len);
 
-			sg_set_buf(&sg, data, current_len);
+	while(nbytes > 0) {
+		size_t current_len = nbytes > bufsize ? bufsize : nbytes;
 
-			/* Always hash before encryption and after decryption. Maybe
-			 * we should introduce a flag to switch... TBD later on.
-			 */
-			if (copv->op == COP_ENCRYPT) {
-				if (hdesc.tfm && (copv->iovec[i].op_flags & IOP_HASH)) {
-					ret = crypto_hash_update(&hdesc, &sg, current_len);
-					if (unlikely(ret)) {
-						dprintk(0, KERN_ERR, "CryptoAPI failure: %d\n",ret);
-						goto out;
-					}
-				}
-				if (bdesc.tfm && (copv->iovec[i].op_flags & IOP_CIPHER)) {
-					ret = crypto_blkcipher_encrypt(&bdesc, &sg, &sg, current_len);
-
-					if (unlikely(ret)) {
-						dprintk(0, KERN_ERR, "CryptoAPI failure: %d\n",ret);
-						goto out;
-					}
-					copy_to_user(dst, data, current_len);
-					dst += current_len;
-				}
-			} else {
-				if (bdesc.tfm && (copv->iovec[i].op_flags & IOP_CIPHER)) {
-					ret = crypto_blkcipher_decrypt(&bdesc, &sg, &sg, current_len);
+		copy_from_user(data, src, current_len);
 
-					if (unlikely(ret)) {
-						dprintk(0, KERN_ERR, "CryptoAPI failure: %d\n",ret);
-						goto out;
-					}
-					copy_to_user(dst, data, current_len);
-					dst += current_len;
+		sg_set_buf(&sg, data, current_len);
 
+		/* Always hash before encryption and after decryption. Maybe
+		 * we should introduce a flag to switch... TBD later on.
+		 */
+		if (cop->op == COP_ENCRYPT) {
+			if (hdesc.tfm) {
+				ret = crypto_hash_update(&hdesc, &sg, current_len);
+				if (unlikely(ret)) {
+					dprintk(0, KERN_ERR, "CryptoAPI failure: %d\n",ret);
+					goto out;
 				}
+			}
+			if (bdesc.tfm) {
+				ret = crypto_blkcipher_encrypt(&bdesc, &sg, &sg, current_len);
 
-				if (hdesc.tfm && (copv->iovec[i].op_flags & IOP_HASH)) {
-					ret = crypto_hash_update(&hdesc, &sg, current_len);
-					if (unlikely(ret)) {
-						dprintk(0, KERN_ERR, "CryptoAPI failure: %d\n",ret);
-						goto out;
-					}
+				if (unlikely(ret)) {
+					dprintk(0, KERN_ERR, "CryptoAPI failure: %d\n",ret);
+					goto out;
 				}
+				copy_to_user(dst, data, current_len);
+				dst += current_len;
 			}
+		} else {
+			if (bdesc.tfm) {
+				ret = crypto_blkcipher_decrypt(&bdesc, &sg, &sg, current_len);
 
-			nbytes -= current_len;
-			src += current_len;
-		}
+				if (unlikely(ret)) {
+					dprintk(0, KERN_ERR, "CryptoAPI failure: %d\n",ret);
+					goto out;
+				}
+				copy_to_user(dst, data, current_len);
+				dst += current_len;
 
-#if defined(CRYPTODEV_STATS)
-	if (enable_stats) {
-		/* this is safe - we check cop->op at the function entry */
-		ses_ptr->stat[copv->op] += copv->iovec[i].len;
-		if (ses_ptr->stat_max_size < copv->iovec[i].len)
-			ses_ptr->stat_max_size = copv->iovec[i].len;
-		ses_ptr->stat_count++;
-	}
-#endif
+			}
 
+			if (hdesc.tfm) {
+				ret = crypto_hash_update(&hdesc, &sg, current_len);
+				if (unlikely(ret)) {
+					dprintk(0, KERN_ERR, "CryptoAPI failure: %d\n",ret);
+					goto out;
+				}
+			}
+		}
+
+		nbytes -= current_len;
+		src += current_len;
 	}
 	
 	if (hdesc.tfm) {
@@ -550,8 +538,18 @@ static int crypto_runv(struct fcrypt *fcr, struct crypt_opv *copv)
 			goto out;
 		}
 
-		copy_to_user(copv->mac, hash_output, crypto_hash_digestsize(ses_ptr->hash_tfm));
+		copy_to_user(cop->mac, hash_output, crypto_hash_digestsize(ses_ptr->hash_tfm));
+	}
+
+#if defined(CRYPTODEV_STATS)
+	if (enable_stats) {
+		/* this is safe - we check cop->op at the function entry */
+		ses_ptr->stat[cop->op] += cop->len;
+		if (ses_ptr->stat_max_size < cop->len)
+			ses_ptr->stat_max_size = cop->len;
+		ses_ptr->stat_count++;
 	}
+#endif
 
 out:
 	free_page((unsigned long)data);
@@ -562,33 +560,6 @@ out_unlock:
 	return ret;
 }
 
-/* This is the main crypto function - feed it with plaintext 
-   and get a ciphertext (or vice versa :-) */
-static int crypto_run(struct fcrypt *fcr, struct crypt_op *cop)
-{
-	struct crypt_opv copv;
-	struct crypt_iovec iovec;
-	
-	iovec.src = cop->src;
-	iovec.len = cop->len;
-	iovec.op_flags = IOP_CIPHER|IOP_HASH;
-	
-	copv.op = cop->op;
-	copv.ses = cop->ses;
-	copv.flags = cop->flags;
-	copv.iovec = &iovec;
-	copv.iovec_cnt = 1;
-
-	copv.dst = cop->dst;
-	copv.mac = cop->mac;
-	copv.iv = cop->iv;
-	
-	return crypto_runv(fcr, &copv);
-	
-}
-
-
-
 /* ====== /dev/crypto ====== */
 
 static int
@@ -644,7 +615,6 @@ cryptodev_ioctl(struct inode *inode, struct file *filp,
 	int __user *p = (void __user *)arg;
 	struct session_op sop;
 	struct crypt_op cop;
-	struct crypt_opv copv;
 	struct fcrypt *fcr = filp->private_data;
 	uint32_t ses;
 	int ret, fd;
@@ -680,12 +650,6 @@ cryptodev_ioctl(struct inode *inode, struct file *filp,
 			copy_to_user((void*)arg, &cop, sizeof(cop));
 			return ret;
 
-		case CIOCCRYPTV:
-			copy_from_user(&cop, (void*)arg, sizeof(copv));
-			ret = crypto_runv(fcr, &copv);
-			copy_to_user((void*)arg, &copv, sizeof(copv));
-			return ret;
-
 		default:
 			return -EINVAL;
 	}
diff --git a/drivers/staging/crypto/cryptodev/cryptodev.h b/drivers/staging/crypto/cryptodev/cryptodev.h
index 55c3279143a7..fcdd00628843 100644
--- a/drivers/staging/crypto/cryptodev/cryptodev.h
+++ b/drivers/staging/crypto/cryptodev/cryptodev.h
@@ -75,7 +75,7 @@ struct crypt_op {
 	uint32_t	ses;		/* from session_op->ses */
 	#define COP_DECRYPT	0
 	#define COP_ENCRYPT	1
-	uint16_t	op;		/* ie. COP_ENCRYPT */
+	uint32_t	op;		/* ie. COP_ENCRYPT */
 	uint32_t	flags;		/* unused */
 
 	size_t		len;
@@ -84,30 +84,6 @@ struct crypt_op {
 	void		*iv;
 };
 
-struct crypt_iovec {
-#define IOP_CIPHER 1
-#define IOP_HASH 2
-	uint16_t	op_flags;		/* ie. IOP_CIPHER|IOP_HASH */
-	void		*src;
-	size_t		len;
-};
-
-/* ioctl parameter to request a crypt/decrypt operation against a session  */
-struct crypt_opv {
-	uint32_t	ses;		/* from session_op->ses */
-	#define COP_DECRYPT	0
-	#define COP_ENCRYPT	1
-	uint16_t	op;		/* ie. COP_ENCRYPT */
-	uint32_t	flags;		/* unused */
-
-	struct crypt_iovec* iovec;
-	uint16_t iovec_cnt;
-	
-	void		*dst;
-	void		*mac;
-	void		*iv;
-};
-
 /* clone original filedescriptor */
 #define CRIOGET         _IOWR('c', 101, uint32_t)
 
@@ -124,9 +100,6 @@ struct crypt_opv {
 #define CIOCKEY         _IOWR('c', 105, void *)
 #define CIOCASYMFEAT    _IOR('c', 106, uint32_t)
 
-/* request encryption/decryptions of a given buffer vector */
-#define CIOCCRYPTV       _IOWR('c', 107, struct crypt_opv)
-
 #endif /* _CRYPTODEV_H */
 
 /* unused structures */
-- 
2.1.0

