From 67c44a00b8dbfeb5966b12af4b132dd67b7ee5d2 Mon Sep 17 00:00:00 2001
From: Phil Sutter <phil.sutter@viprinet.com>
Date: Fri, 17 Dec 2010 18:52:32 +0100
Subject: [PATCH 121/291] cryptodev: CIOCGSESSINFO:

For now, the only information returned are the verbose names of the
requested cipher and hash algos along with their driver names.

Signed-off-by: Nikos Mavrogiannopoulos <nmav@gnutls.org>
---
 drivers/staging/crypto/cryptodev/cryptodev.h      | 14 ++++++++
 drivers/staging/crypto/cryptodev/cryptodev_main.c | 42 +++++++++++++++++++++++
 2 files changed, 56 insertions(+)

diff --git a/drivers/staging/crypto/cryptodev/cryptodev.h b/drivers/staging/crypto/cryptodev/cryptodev.h
index f367262be652..d7343ba88062 100644
--- a/drivers/staging/crypto/cryptodev/cryptodev.h
+++ b/drivers/staging/crypto/cryptodev/cryptodev.h
@@ -68,6 +68,9 @@ enum cryptodev_crypto_op_t {
 /* Values for hashes/MAC */
 #define AALG_MAX_RESULT_LEN		64
 
+/* maximum length of verbose alg names (depends on CRYPTO_MAX_ALG_NAME) */
+#define CRYPTODEV_MAX_ALG_NAME		64
+
 /* input of CIOCGSESSION */
 struct session_op {
 	/* Specify either cipher or mac
@@ -85,6 +88,16 @@ struct session_op {
 	__u16	alignmask;	/* alignment constraints */
 };
 
+struct session_info_op {
+	__u32 ses;		/* session identifier */
+
+	/* verbose names for the requested ciphers */
+	struct alg_info {
+		char cra_name[CRYPTODEV_MAX_ALG_NAME];
+		char cra_driver_name[CRYPTODEV_MAX_ALG_NAME];
+	} cipher_info, hash_info;
+};
+
 #define	COP_ENCRYPT	0
 #define COP_DECRYPT	1
 
@@ -162,6 +175,7 @@ enum cryptodev_crk_op_t {
 #define CIOCCRYPT       _IOWR('c', 104, struct crypt_op)
 #define CIOCKEY         _IOWR('c', 105, struct crypt_kop)
 #define CIOCASYMFEAT    _IOR('c', 106, __u32)
+#define CIOCGSESSINFO	_IOWR('c', 107, struct session_info_op)
 
 /* to indicate that CRIOGET is not required in linux
  */
diff --git a/drivers/staging/crypto/cryptodev/cryptodev_main.c b/drivers/staging/crypto/cryptodev/cryptodev_main.c
index e869557461ad..750e2824f472 100644
--- a/drivers/staging/crypto/cryptodev/cryptodev_main.c
+++ b/drivers/staging/crypto/cryptodev/cryptodev_main.c
@@ -32,6 +32,7 @@
  *
  */
 
+#include <crypto/hash.h>
 #include <linux/crypto.h>
 #include <linux/mm.h>
 #include <linux/highmem.h>
@@ -1006,6 +1007,38 @@ static int kcop_from_user(struct kernel_crypt_op *kcop,
 	return fill_kcop_from_cop(kcop, fcr);
 }
 
+static inline void tfm_info_to_alg_info(struct alg_info *dst, struct crypto_tfm *tfm)
+{
+	snprintf(dst->cra_name, CRYPTODEV_MAX_ALG_NAME,
+			"%s", crypto_tfm_alg_name(tfm));
+	snprintf(dst->cra_driver_name, CRYPTODEV_MAX_ALG_NAME,
+			"%s", crypto_tfm_alg_driver_name(tfm));
+}
+
+static int get_session_info(struct fcrypt *fcr, struct session_info_op *siop)
+{
+	struct csession *ses_ptr;
+
+	/* this also enters ses_ptr->sem */
+	ses_ptr = crypto_get_session_by_sid(fcr, siop->ses);
+	if (unlikely(!ses_ptr)) {
+		dprintk(1, KERN_ERR, "invalid session ID=0x%08X\n", siop->ses);
+		return -EINVAL;
+	}
+
+	if (ses_ptr->cdata.init) {
+		tfm_info_to_alg_info(&siop->cipher_info,
+				crypto_ablkcipher_tfm(ses_ptr->cdata.async.s));
+	}
+	if (ses_ptr->hdata.init) {
+		tfm_info_to_alg_info(&siop->hash_info,
+				crypto_ahash_tfm(ses_ptr->hdata.async.s));
+	}
+
+	mutex_unlock(&ses_ptr->sem);
+	return 0;
+}
+
 static long
 cryptodev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg_)
 {
@@ -1015,6 +1048,7 @@ cryptodev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg_)
 	struct kernel_crypt_op kcop;
 	struct crypt_priv *pcr = filp->private_data;
 	struct fcrypt *fcr;
+	struct session_info_op siop;
 	uint32_t ses;
 	int ret, fd;
 
@@ -1053,6 +1087,14 @@ cryptodev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg_)
 			return ret;
 		ret = crypto_finish_session(fcr, ses);
 		return ret;
+	case CIOCGSESSINFO:
+		if (unlikely(copy_from_user(&siop, arg, sizeof(siop))))
+			return -EFAULT;
+
+		ret = get_session_info(fcr, &siop);
+		if (unlikely(ret))
+			return ret;
+		return copy_to_user(arg, &siop, sizeof(siop));
 	case CIOCCRYPT:
 		if (unlikely(ret = kcop_from_user(&kcop, fcr, arg)))
 			return ret;
-- 
2.1.0

