From f90fb50a4a6fa5e0fcd45ef7037101db1089d22d Mon Sep 17 00:00:00 2001
From: Nikos Mavrogiannopoulos <nmav@gnutls.org>
Date: Sun, 11 Dec 2011 13:44:22 +0100
Subject: [PATCH 168/291] cryptodev: Added

---
 .../staging/crypto/cryptodev/crypto/cryptodev.h    | 10 ++++++++
 .../staging/crypto/cryptodev/examples/aes-gcm.c    |  5 +++-
 .../staging/crypto/cryptodev/examples/aes-sha1.c   |  5 +++-
 drivers/staging/crypto/cryptodev/examples/aes.c    |  7 +++++-
 drivers/staging/crypto/cryptodev/examples/sha.c    |  5 +++-
 drivers/staging/crypto/cryptodev/ioctl.c           | 27 +++++++++++++++-------
 6 files changed, 47 insertions(+), 12 deletions(-)

diff --git a/drivers/staging/crypto/cryptodev/crypto/cryptodev.h b/drivers/staging/crypto/cryptodev/crypto/cryptodev.h
index c3de78a15134..ebd61690a2c3 100644
--- a/drivers/staging/crypto/cryptodev/crypto/cryptodev.h
+++ b/drivers/staging/crypto/cryptodev/crypto/cryptodev.h
@@ -99,8 +99,18 @@ struct session_info_op {
 	} cipher_info, hash_info;
 
 	__u16	alignmask;	/* alignment constraints */
+	__u32   flags;          /* SIOP_FLAGS_* */
 };
 
+/* If this flag is set then this algorithm uses
+ * a driver only available in kernel (software drivers,
+ * or drivers based on instruction sets do not set this flag).
+ *
+ * If multiple algorithms are involved (as in AEAD case), then
+ * if one of them is kernel-driver-only this flag will be set.
+ */
+#define SIOP_FLAG_KERNEL_DRIVER_ONLY 1
+
 #define	COP_ENCRYPT	0
 #define COP_DECRYPT	1
 
diff --git a/drivers/staging/crypto/cryptodev/examples/aes-gcm.c b/drivers/staging/crypto/cryptodev/examples/aes-gcm.c
index be327a228894..6791f4eb13b0 100644
--- a/drivers/staging/crypto/cryptodev/examples/aes-gcm.c
+++ b/drivers/staging/crypto/cryptodev/examples/aes-gcm.c
@@ -35,8 +35,11 @@ int aes_gcm_ctx_init(struct cryptodev_ctx* ctx, int cfd, const uint8_t *key, uns
 		perror("ioctl(CIOCGSESSINFO)");
 		return -1;
 	}
-	printf("requested cipher CRYPTO_AES_GCM, got %s with driver %s\n",
+	printf("Got %s with driver %s\n",
 			siop.cipher_info.cra_name, siop.cipher_info.cra_driver_name);
+	if (!(siop.flags & SIOP_FLAG_KERNEL_DRIVER_ONLY)) {
+		printf("Note: This is not an accelerated cipher\n");
+	}
 	/*printf("Alignmask is %x\n", (unsigned int)siop.alignmask); */
 	ctx->alignmask = siop.alignmask;
 #endif
diff --git a/drivers/staging/crypto/cryptodev/examples/aes-sha1.c b/drivers/staging/crypto/cryptodev/examples/aes-sha1.c
index 8235918763dc..e93e3c4461b2 100644
--- a/drivers/staging/crypto/cryptodev/examples/aes-sha1.c
+++ b/drivers/staging/crypto/cryptodev/examples/aes-sha1.c
@@ -45,8 +45,11 @@ int aes_sha1_ctx_init(struct cryptodev_ctx* ctx, int cfd,
 		perror("ioctl(CIOCGSESSINFO)");
 		return -1;
 	}
-	printf("requested cipher CRYPTO_AES_GCM, got %s with driver %s\n",
+	printf("Got %s with driver %s\n",
 			siop.cipher_info.cra_name, siop.cipher_info.cra_driver_name);
+	if (!(siop.flags & SIOP_FLAG_KERNEL_DRIVER_ONLY)) {
+		printf("Note: This is not an accelerated cipher\n");
+	}
 	/*printf("Alignmask is %x\n", (unsigned int)siop.alignmask); */
 	ctx->alignmask = siop.alignmask;
 #endif
diff --git a/drivers/staging/crypto/cryptodev/examples/aes.c b/drivers/staging/crypto/cryptodev/examples/aes.c
index 0f154d8fc97f..02f7613b6c19 100644
--- a/drivers/staging/crypto/cryptodev/examples/aes.c
+++ b/drivers/staging/crypto/cryptodev/examples/aes.c
@@ -33,13 +33,18 @@ int aes_ctx_init(struct cryptodev_ctx* ctx, int cfd, const uint8_t *key, unsigne
 	}
 
 #ifdef CIOCGSESSINFO
+	memset(&siop, 0, sizeof(siop));
+
 	siop.ses = ctx->sess.ses;
 	if (ioctl(ctx->cfd, CIOCGSESSINFO, &siop)) {
 		perror("ioctl(CIOCGSESSINFO)");
 		return -1;
 	}
-	printf("requested cipher CRYPTO_AES_CBC, got %s with driver %s\n",
+	printf("Got %s with driver %s\n",
 			siop.cipher_info.cra_name, siop.cipher_info.cra_driver_name);
+	if (!(siop.flags & SIOP_FLAG_KERNEL_DRIVER_ONLY)) {
+		printf("Note: This is not an accelerated cipher\n");
+	}
 	/*printf("Alignmask is %x\n", (unsigned int)siop.alignmask); */
 	ctx->alignmask = siop.alignmask;
 #endif
diff --git a/drivers/staging/crypto/cryptodev/examples/sha.c b/drivers/staging/crypto/cryptodev/examples/sha.c
index 065f54d7c25b..4f45a6b01a50 100644
--- a/drivers/staging/crypto/cryptodev/examples/sha.c
+++ b/drivers/staging/crypto/cryptodev/examples/sha.c
@@ -39,8 +39,11 @@ int sha_ctx_init(struct cryptodev_ctx* ctx, int cfd, const uint8_t *key, unsigne
 		perror("ioctl(CIOCGSESSINFO)");
 		return -1;
 	}
-	printf("requested SHA, got %s with driver %s\n",
+	printf("Got %s with driver %s\n",
 			siop.hash_info.cra_name, siop.hash_info.cra_driver_name);
+	if (!(siop.flags & SIOP_FLAG_KERNEL_DRIVER_ONLY)) {
+		printf("Note: This is not an accelerated cipher\n");
+	}
 	/*printf("Alignmask is %x\n", (unsigned int)siop.alignmask);*/
 	ctx->alignmask = siop.alignmask;
 #endif
diff --git a/drivers/staging/crypto/cryptodev/ioctl.c b/drivers/staging/crypto/cryptodev/ioctl.c
index 5b8169dea106..4330bceee7e6 100644
--- a/drivers/staging/crypto/cryptodev/ioctl.c
+++ b/drivers/staging/crypto/cryptodev/ioctl.c
@@ -696,6 +696,7 @@ static inline void tfm_info_to_alg_info(struct alg_info *dst, struct crypto_tfm
 static int get_session_info(struct fcrypt *fcr, struct session_info_op *siop)
 {
 	struct csession *ses_ptr;
+	struct crypto_tfm *tfm;
 
 	/* this also enters ses_ptr->sem */
 	ses_ptr = crypto_get_session_by_sid(fcr, siop->ses);
@@ -703,18 +704,28 @@ static int get_session_info(struct fcrypt *fcr, struct session_info_op *siop)
 		dprintk(1, KERN_ERR, "invalid session ID=0x%08X\n", siop->ses);
 		return -EINVAL;
 	}
+	
+	siop->flags = 0;
 
 	if (ses_ptr->cdata.init) {
-		if (ses_ptr->cdata.aead == 0) 
-			tfm_info_to_alg_info(&siop->cipher_info,
-				crypto_ablkcipher_tfm(ses_ptr->cdata.async.s));
-		else
-			tfm_info_to_alg_info(&siop->cipher_info,
-				crypto_aead_tfm(ses_ptr->cdata.async.as));
+		if (ses_ptr->cdata.aead == 0) {
+			tfm = crypto_ablkcipher_tfm(ses_ptr->cdata.async.s);
+		} else {
+			tfm = crypto_aead_tfm(ses_ptr->cdata.async.as);
+		}
+		tfm_info_to_alg_info(&siop->cipher_info, tfm);
+#ifdef CRYPTO_ALG_KERN_DRIVER_ONLY
+		if (tfm->__crt_alg->cra_flags & CRYPTO_ALG_KERN_DRIVER_ONLY)
+			siop->flags |= SIOP_FLAG_KERNEL_DRIVER_ONLY;
+#endif
 	}
 	if (ses_ptr->hdata.init) {
-		tfm_info_to_alg_info(&siop->hash_info,
-				crypto_ahash_tfm(ses_ptr->hdata.async.s));
+		tfm = crypto_ahash_tfm(ses_ptr->hdata.async.s);
+		tfm_info_to_alg_info(&siop->hash_info, tfm);
+#ifdef CRYPTO_ALG_KERN_DRIVER_ONLY
+		if (tfm->__crt_alg->cra_flags & CRYPTO_ALG_KERN_DRIVER_ONLY)
+			siop->flags |= SIOP_FLAG_KERNEL_DRIVER_ONLY;
+#endif
 	}
 
 	siop->alignmask = ses_ptr->alignmask;
-- 
2.1.0

