From cb253df5c86722a6dea6abd467c87dd760aaaff0 Mon Sep 17 00:00:00 2001
From: Nikos Mavrogiannopoulos <nmav@gnutls.org>
Date: Tue, 6 Jul 2010 13:24:09 +0200
Subject: [PATCH 071/291] cryptodev: Internal

---
 .../staging/crypto/cryptodev/cryptodev_cipher.c    | 35 +++---------------
 drivers/staging/crypto/cryptodev/cryptodev_int.h   |  6 +--
 drivers/staging/crypto/cryptodev/cryptodev_main.c  | 43 ++++++++++++++++++++--
 3 files changed, 49 insertions(+), 35 deletions(-)

diff --git a/drivers/staging/crypto/cryptodev/cryptodev_cipher.c b/drivers/staging/crypto/cryptodev/cryptodev_cipher.c
index 2f52f46793bc..5462f032a6eb 100644
--- a/drivers/staging/crypto/cryptodev/cryptodev_cipher.c
+++ b/drivers/staging/crypto/cryptodev/cryptodev_cipher.c
@@ -48,9 +48,9 @@ static void cryptodev_complete(struct crypto_async_request *req, int err)
 	complete(&res->completion);
 }
 
-int cryptodev_cipher_init(struct cipher_data* out, const char* alg_name, uint8_t __user * key, size_t keylen)
+int cryptodev_cipher_init(struct cipher_data* out, const char* alg_name, uint8_t * keyp, size_t keylen)
 {
-	uint8_t keyp[CRYPTO_CIPHER_MAX_KEY_LEN];
+	
 	struct ablkcipher_alg* alg;
 	int ret;
 
@@ -58,17 +58,6 @@ int cryptodev_cipher_init(struct cipher_data* out, const char* alg_name, uint8_t
 
 	out->init = 1;
 
-	if (unlikely(keylen > CRYPTO_CIPHER_MAX_KEY_LEN)) {
-		dprintk(1,KERN_DEBUG,"Setting key failed for %s-%zu.\n",
-			alg_name, keylen*8);
-		return -EINVAL;
-	}
-	/* Copy the key from user and set to TFM. */
-	if (unlikely(copy_from_user(keyp, key, keylen))) {
-		dprintk(1, KERN_DEBUG, "copy_from_user() failed for key\n");
-		return -EINVAL;
-	}
-
 	out->async.s = crypto_alloc_ablkcipher(alg_name, 0, 0);
 	if (unlikely(IS_ERR(out->async.s))) {
 		dprintk(1,KERN_DEBUG,"%s: Failed to load cipher %s\n", __func__,
@@ -138,9 +127,9 @@ void cryptodev_cipher_deinit(struct cipher_data* cdata)
 	cdata->init = 0;
 }
 
-int cryptodev_cipher_set_iv(struct cipher_data* cdata, void __user* iv, size_t iv_size)
+void cryptodev_cipher_set_iv(struct cipher_data* cdata, void __user* iv, size_t iv_size)
 {
-	return copy_from_user(cdata->async.iv, iv, min(iv_size,sizeof(cdata->async.iv)));
+	memcpy(cdata->async.iv, iv, min(iv_size,sizeof(cdata->async.iv)) );
 }
 
 static inline int waitfor (struct cryptodev_result* cr, ssize_t ret)
@@ -196,23 +185,12 @@ ssize_t cryptodev_cipher_decrypt( struct cipher_data* cdata, struct scatterlist
 
 /* Hash functions */
 
-int cryptodev_hash_init( struct hash_data* hdata, const char* alg_name, int hmac_mode, void __user* mackey, size_t mackeylen)
+int cryptodev_hash_init( struct hash_data* hdata, const char* alg_name, int hmac_mode, void * mackey, size_t mackeylen)
 {
 int ret;
-uint8_t hkeyp[CRYPTO_HMAC_MAX_KEY_LEN];
 
 	hdata->init = 1;
 
-	if (unlikely(mackeylen > CRYPTO_HMAC_MAX_KEY_LEN)) {
-		dprintk(1,KERN_DEBUG,"Setting hmac key failed for %s-%zu.\n",
-			alg_name, mackeylen*8);
-		return -EINVAL;
-	}
-	if (unlikely(copy_from_user(hkeyp, mackey, mackeylen))) {
-		dprintk(1, KERN_DEBUG, "copy_from_user() failed for mackey\n");
-		return -EINVAL;
-	}
-
 	hdata->async.s = crypto_alloc_ahash(alg_name, 0, 0);
 	if (unlikely(IS_ERR(hdata->async.s))) {
 		dprintk(1,KERN_DEBUG,"%s: Failed to load transform for %s\n", __func__,
@@ -222,8 +200,7 @@ uint8_t hkeyp[CRYPTO_HMAC_MAX_KEY_LEN];
 
 	/* Copy the key from user and set to TFM. */
 	if (hmac_mode != 0) {
-
-		ret = crypto_ahash_setkey(hdata->async.s, hkeyp, mackeylen);
+		ret = crypto_ahash_setkey(hdata->async.s, mackey, mackeylen);
 		if (unlikely(ret)) {
 			dprintk(1,KERN_DEBUG,"Setting hmac key failed for %s-%zu.\n",
 				alg_name, mackeylen*8);
diff --git a/drivers/staging/crypto/cryptodev/cryptodev_int.h b/drivers/staging/crypto/cryptodev/cryptodev_int.h
index 0b82017f2b39..bc3b586a233a 100644
--- a/drivers/staging/crypto/cryptodev/cryptodev_int.h
+++ b/drivers/staging/crypto/cryptodev/cryptodev_int.h
@@ -37,11 +37,11 @@ struct cipher_data
 	} async;
 };
 
-int cryptodev_cipher_init(struct cipher_data* out, const char* alg_name, __user uint8_t * key, size_t keylen);
+int cryptodev_cipher_init(struct cipher_data* out, const char* alg_name, uint8_t * key, size_t keylen);
 void cryptodev_cipher_deinit(struct cipher_data* cdata);
 ssize_t cryptodev_cipher_decrypt( struct cipher_data* cdata, struct scatterlist *sg1, struct scatterlist *sg2, size_t len);
 ssize_t cryptodev_cipher_encrypt( struct cipher_data* cdata, struct scatterlist *sg1, struct scatterlist *sg2, size_t len);
-int cryptodev_cipher_set_iv(struct cipher_data* cdata, void* iv, size_t iv_size);
+void cryptodev_cipher_set_iv(struct cipher_data* cdata, void* iv, size_t iv_size);
 
 /* hash stuff */
 struct hash_data
@@ -59,7 +59,7 @@ int cryptodev_hash_final( struct hash_data* hdata, void* output);
 ssize_t cryptodev_hash_update( struct hash_data* hdata, struct scatterlist *sg, size_t len);
 int cryptodev_hash_reset( struct hash_data* hdata);
 void cryptodev_hash_deinit(struct hash_data* hdata);
-int cryptodev_hash_init( struct hash_data* hdata, const char* alg_name, int hmac_mode, __user void* mackey, size_t mackeylen);
+int cryptodev_hash_init( struct hash_data* hdata, const char* alg_name, int hmac_mode, void* mackey, size_t mackeylen);
 
 /* compatibility stuff */
 #ifdef CONFIG_COMPAT
diff --git a/drivers/staging/crypto/cryptodev/cryptodev_main.c b/drivers/staging/crypto/cryptodev/cryptodev_main.c
index 0da458253680..df0a8ba34c6c 100644
--- a/drivers/staging/crypto/cryptodev/cryptodev_main.c
+++ b/drivers/staging/crypto/cryptodev/cryptodev_main.c
@@ -200,7 +200,22 @@ crypto_create_session(struct fcrypt *fcr, struct session_op *sop)
 
 	/* Set-up crypto transform. */
 	if (alg_name) {
-		ret = cryptodev_cipher_init(&ses_new->cdata, alg_name, sop->key, sop->keylen);
+		uint8_t keyp[CRYPTO_CIPHER_MAX_KEY_LEN];
+
+		if (unlikely(sop->keylen > CRYPTO_CIPHER_MAX_KEY_LEN)) {
+			dprintk(1,KERN_DEBUG,"Setting key failed for %s-%zu.\n",
+				alg_name, (size_t)sop->keylen*8);
+			ret = -EINVAL;
+			goto error_cipher;
+		}
+
+		ret = copy_from_user(keyp, sop->key, sop->keylen);
+		if (unlikely(ret)) {
+			goto error_cipher;
+		}
+
+		ret = cryptodev_cipher_init(&ses_new->cdata, alg_name, keyp, sop->keylen);
+
 		if (ret < 0) {
 			dprintk(1,KERN_DEBUG,"%s: Failed to load cipher for %s\n", __func__,
 				   alg_name);
@@ -210,7 +225,21 @@ crypto_create_session(struct fcrypt *fcr, struct session_op *sop)
 	}
 
 	if (hash_name) {
-		ret = cryptodev_hash_init(&ses_new->hdata, hash_name, hmac_mode, sop->mackey, sop->mackeylen);
+		uint8_t keyp[CRYPTO_HMAC_MAX_KEY_LEN];
+
+		if (unlikely(sop->mackeylen > CRYPTO_HMAC_MAX_KEY_LEN)) {
+			dprintk(1,KERN_DEBUG,"Setting key failed for %s-%zu.\n",
+				alg_name, (size_t)sop->mackeylen*8);
+			ret = -EINVAL;
+			goto error_hash;
+		}
+		
+		ret = copy_from_user(keyp, sop->mackey, sop->mackeylen);
+		if (unlikely(ret)) {
+			goto error_hash;
+		}
+
+		ret = cryptodev_hash_init(&ses_new->hdata, hash_name, hmac_mode, keyp, sop->mackeylen);
 		if (ret != 0) {
 			dprintk(1,KERN_DEBUG,"%s: Failed to load hash for %s\n", __func__,
 				   hash_name);
@@ -603,7 +632,15 @@ static int crypto_run(struct fcrypt *fcr, struct crypt_op *cop)
 		}
 
 		if (cop->iv) {
-			cryptodev_cipher_set_iv(&ses_ptr->cdata, cop->iv, ses_ptr->cdata.ivsize);
+			uint8_t iv[EALG_MAX_BLOCK_LEN];
+			
+			ret = copy_from_user(iv, cop->iv, min( (int)sizeof(iv), (ses_ptr->cdata.ivsize)));
+			dprintk(1, KERN_ERR, "error copying IV\n");
+			if (unlikely(ret)) {
+				goto out_unlock;
+			}
+
+			cryptodev_cipher_set_iv(&ses_ptr->cdata, iv, ses_ptr->cdata.ivsize);
 		}
 	}
 
-- 
2.1.0

