[PATCH 75/133] [Jaunty SRU] ARM.imx51 Freescale:ENGR00112200 Add cryptodev device

Brad Figg brad.figg at canonical.com
Thu Jul 9 16:49:05 UTC 2009


From: Michal Ludvig <mludvig at suse.cz>

Linux driver for /dev/crypto (aka CryptoDev)
See http://www.logix.cz/michal/devel/cryptodev for details.

Signed-off-by: Michal Ludvig <mludvig at suse.cz>
Signed-off-by: Rob Herring <r.herring at freescale.com>
Signed-off-by: Brad Figg <brad.figg at canonical.com>
---
 crypto/Kconfig            |    8 +
 crypto/Makefile           |    2 +
 crypto/cryptodev.c        |  558 +++++++++++++++++++++++++++++++++++++++++++++
 include/linux/Kbuild      |    1 +
 include/linux/cryptodev.h |   82 +++++++
 5 files changed, 651 insertions(+), 0 deletions(-)
 create mode 100644 crypto/cryptodev.c
 create mode 100644 include/linux/cryptodev.h

diff --git a/crypto/Kconfig b/crypto/Kconfig
index dc20a34..57a9f38 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -132,6 +132,14 @@ config CRYPTO_TEST
 	help
 	  Quick & dirty crypto test module.
 
+config CRYPTO_CRYPTODEV
+	tristate "Cryptodev (/dev/crypto) interface"
+	depends on CRYPTO
+	select CRYPTO_ALGAPI
+	help
+	  Device /dev/crypto gives userspace programs access to
+	  kernel crypto algorithms.
+
 comment "Authenticated Encryption with Associated Data"
 
 config CRYPTO_CCM
diff --git a/crypto/Makefile b/crypto/Makefile
index cd4a4ed..0558609 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -78,6 +78,8 @@ obj-$(CONFIG_CRYPTO_RNG2) += krng.o
 obj-$(CONFIG_CRYPTO_ANSI_CPRNG) += ansi_cprng.o
 obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o
 
+obj-$(CONFIG_CRYPTO_CRYPTODEV) += cryptodev.o
+
 #
 # generic algorithms and the async_tx api
 #
diff --git a/crypto/cryptodev.c b/crypto/cryptodev.c
new file mode 100644
index 0000000..5b8d00b
--- /dev/null
+++ b/crypto/cryptodev.c
@@ -0,0 +1,558 @@
+/*
+ * Driver for /dev/crypto device (aka CryptoDev)
+ *
+ * Copyright (c) 2004 Michal Ludvig <mludvig at suse.cz>, SuSE Labs
+ *
+ * Device /dev/crypto provides an interface for
+ * accessing kernel CryptoAPI algorithms (ciphers,
+ * hashes) from userspace programs.
+ *
+ * /dev/crypto interface was originally introduced in
+ * OpenBSD and this module attempts to keep the API,
+ * although a bit extended.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/file.h>
+#include <linux/miscdevice.h>
+#include <linux/crypto.h>
+#include <linux/mm.h>
+#include <linux/highmem.h>
+#include <linux/random.h>
+#include <linux/cryptodev.h>
+#include <asm/uaccess.h>
+#include <asm/ioctl.h>
+#include <linux/scatterlist.h>
+
+MODULE_AUTHOR("Michal Ludvig <mludvig at suse.cz>");
+MODULE_DESCRIPTION("CryptoDev driver");
+MODULE_LICENSE("Dual BSD/GPL");
+
+/* ====== Compile-time config ====== */
+
+#define CRYPTODEV_STATS
+
+/* ====== Module parameters ====== */
+
+static int verbosity = 0;
+module_param(verbosity, int, 0644);
+MODULE_PARM_DESC(verbosity, "0: normal, 1: verbose, 2: debug");
+
+#ifdef CRYPTODEV_STATS
+static int enable_stats = 0;
+module_param(enable_stats, int, 0644);
+MODULE_PARM_DESC(enable_stats, "collect statictics about cryptodev usage");
+#endif
+
+/* ====== Debug helpers ====== */
+
+#define PFX "cryptodev: "
+#define dprintk(level,severity,format,a...)			\
+	do { 							\
+		if (level <= verbosity)				\
+			printk(severity PFX "%s[%u]: " format,	\
+			       current->comm, current->pid,	\
+			       ##a);				\
+	} while (0)
+
+/* ====== CryptoAPI ====== */
+
+struct csession {
+	struct list_head entry;
+	struct semaphore sem;
+	struct crypto_blkcipher *tfm;
+	uint32_t sid;
+#ifdef CRYPTODEV_STATS
+#if ! ((COP_ENCRYPT < 2) && (COP_DECRYPT < 2))
+#error Struct csession.stat uses COP_{ENCRYPT,DECRYPT} as indices. Do something!
+#endif
+	unsigned long long stat[2];
+	size_t stat_max_size, stat_count;
+#endif
+};
+
+struct fcrypt {
+	struct list_head list;
+	struct semaphore sem;
+};
+
+/* Prepare session for future use. */
+static int
+crypto_create_session(struct fcrypt *fcr, struct session_op *sop)
+{
+	struct csession	*ses_new, *ses_ptr;
+	struct crypto_blkcipher *tfm;
+	int ret = 0;
+	char alg_name[MAX_ALG_NAME_LEN+1];
+	char alg_full_name[MAX_ALG_NAME_LEN+1];
+	const char *mode;
+	u8 *keyp;
+
+	/* Does the request make sense? */
+	if (!sop->cipher == !sop->mac) {
+		dprintk(1, KERN_DEBUG, "Both 'cipher' and 'mac' set or unset.\n");
+		return -EINVAL;
+	}
+
+	/* Copy-in the algorithm name if necessary. */
+	if (!sop->alg_namelen) {
+		/* Hmm, compatibility with OpenBSD CRYPTO_* constants...
+		   Should we support it? */
+		dprintk(2, KERN_DEBUG, "OpenBSD constants are not (yet?) supported.\n");
+		return -EINVAL;
+	}
+
+	if(sop->alg_namelen > MAX_ALG_NAME_LEN) {
+		dprintk(1, KERN_DEBUG, "Algorithm name too long (%zu > %u)\n",
+		       sop->alg_namelen, MAX_ALG_NAME_LEN);
+		return -EINVAL;
+	}
+
+	copy_from_user(alg_name, sop->alg_name, sop->alg_namelen);
+	alg_name[sop->alg_namelen] = '\0';
+
+	if(!sop->cipher) {
+		dprintk(2, KERN_DEBUG, "Hashes are not yet supported.\n");
+		return -EINVAL;
+	}
+
+	switch (sop->cipher & CRYPTO_FLAG_MASK) {
+		case CRYPTO_FLAG_ECB: mode = "ebc"; break;
+		case CRYPTO_FLAG_CBC: mode = "cbc"; break;
+		case CRYPTO_FLAG_CFB: mode = "cfb"; break;
+		case CRYPTO_FLAG_CTR: mode = "ctr"; break;
+#if 0
+		/* These modes are not yet supported. */
+		case CRYPTO_FLAG_OFB:	mode = "ofb"; break;
+#endif
+		default: return -EINVAL;
+	}
+	snprintf(alg_full_name, sizeof(alg_full_name) - 1, "%s(%s)", mode, alg_name);
+
+	/* Set-up crypto transform. */
+	tfm = crypto_alloc_blkcipher(alg_full_name, 0, 0);
+	if (!tfm) {
+		dprintk(1, KERN_DEBUG, "Failed to load transform for %s %s\n",
+		       alg_name, mode);
+		return -EINVAL;
+	}
+
+#if 0
+	/* Was correct key length supplied? */
+	if ((sop->keylen < crypto_tfm_alg_min_keysize(tfm)) ||
+	    (sop->keylen > crypto_tfm_alg_max_keysize(tfm))) {
+		dprintk(1, KERN_DEBUG,
+			"Wrong keylen '%zu' for algorithm '%s'. Use %u to %u.\n",
+		       sop->keylen, alg_name, crypto_tfm_alg_min_keysize(tfm),
+		       crypto_tfm_alg_max_keysize(tfm));
+		crypto_free_blkcipher(tfm);
+		return -EINVAL;
+	}
+#endif
+
+	/* Copy the key from user and set to TFM. */
+	keyp = kmalloc(sop->keylen, GFP_KERNEL);
+	if (keyp == NULL) {
+		dprintk(1, KERN_ERR,
+			"Unable to allocate key buffer.\n");
+		crypto_free_blkcipher(tfm);
+		return -ENOMEM;
+	}
+	copy_from_user(keyp, sop->key, sop->keylen);
+	ret = crypto_blkcipher_setkey(tfm, keyp, sop->keylen);
+	kfree(keyp);
+	if (ret) {
+		dprintk(2, KERN_DEBUG,
+			"Setting key failed for %s-%zu-%s: flags=0x%X\n",
+			alg_name, sop->keylen*8, mode, crypto_blkcipher_tfm(tfm)->crt_flags);
+		dprintk(2, KERN_DEBUG,
+			"(see CRYPTO_TFM_RES_* in <linux/crypto.h> for details)\n");
+		crypto_free_blkcipher(tfm);
+		return -EINVAL;
+	}
+
+	/* Create a session and put it to the list. */
+	ses_new = kmalloc(sizeof(*ses_new), GFP_KERNEL);
+	if(!ses_new)
+		return -ENOMEM;
+
+	memset(ses_new, 0, sizeof(*ses_new));
+	get_random_bytes(&ses_new->sid, sizeof(ses_new->sid));
+	ses_new->tfm = tfm;
+	init_MUTEX(&ses_new->sem);
+
+	down(&fcr->sem);
+restart:
+	list_for_each_entry(ses_ptr, &fcr->list, entry) {
+		/* Check for duplicate SID */
+		if (unlikely(ses_new->sid == ses_ptr->sid)) {
+			get_random_bytes(&ses_new->sid, sizeof(ses_new->sid));
+			/* Unless we have a broken RNG this
+			   shouldn't loop forever... ;-) */
+			goto restart;
+		}
+	}
+
+	list_add(&ses_new->entry, &fcr->list);
+	up(&fcr->sem);
+
+	dprintk(2, KERN_DEBUG, "Added session 0x%08X (%s-%zu-%s)\n",
+		ses_new->sid, alg_name, sop->keylen*8, mode);
+
+	/* Fill in some values for the user. */
+	sop->ses = ses_new->sid;
+	sop->blocksize = crypto_blkcipher_blocksize(tfm);
+
+	return 0;
+}
+
+/* Everything that needs to be done when remowing a session. */
+static inline void
+crypto_destroy_session(struct csession *ses_ptr)
+{
+	if(down_trylock(&ses_ptr->sem)) {
+		dprintk(2, KERN_DEBUG, "Waiting for semaphore of sid=0x%08X\n",
+			ses_ptr->sid);
+		down(&ses_ptr->sem);
+	}
+	dprintk(2, KERN_DEBUG, "Removed session 0x%08X\n", ses_ptr->sid);
+#if defined(CRYPTODEV_STATS)
+	if(enable_stats)
+		dprintk(2, KERN_DEBUG,
+			"Usage in Bytes: enc=%llu, dec=%llu, max=%zu, avg=%lu, cnt=%zu\n",
+			ses_ptr->stat[COP_ENCRYPT], ses_ptr->stat[COP_DECRYPT],
+			ses_ptr->stat_max_size, ses_ptr->stat_count > 0
+				? ((unsigned long)(ses_ptr->stat[COP_ENCRYPT]+
+						   ses_ptr->stat[COP_DECRYPT]) /
+				   ses_ptr->stat_count) : 0,
+			ses_ptr->stat_count);
+#endif
+	crypto_free_blkcipher(ses_ptr->tfm);
+	ses_ptr->tfm = NULL;
+	up(&ses_ptr->sem);
+	kfree(ses_ptr);
+}
+
+/* Look up a session by ID and remove. */
+static int
+crypto_finish_session(struct fcrypt *fcr, uint32_t sid)
+{
+	struct csession *tmp, *ses_ptr;
+	struct list_head *head;
+	int ret = 0;
+
+	down(&fcr->sem);
+	head = &fcr->list;
+	list_for_each_entry_safe(ses_ptr, tmp, head, entry) {
+		if(ses_ptr->sid == sid) {
+			list_del(&ses_ptr->entry);
+			crypto_destroy_session(ses_ptr);
+			break;
+		}
+	}
+
+	if (!ses_ptr) {
+		dprintk(1, KERN_ERR, "Session with sid=0x%08X not found!\n", sid);
+		ret = -ENOENT;
+	}
+	up(&fcr->sem);
+
+	return ret;
+}
+
+/* Remove all sessions when closing the file */
+static int
+crypto_finish_all_sessions(struct fcrypt *fcr)
+{
+	struct csession *tmp, *ses_ptr;
+
+	down(&fcr->sem);
+	list_for_each_entry_safe(ses_ptr, tmp, &fcr->list, entry) {
+		list_del(&ses_ptr->entry);
+		crypto_destroy_session(ses_ptr);
+	}
+	up(&fcr->sem);
+
+	return 0;
+}
+
+/* Look up session by session ID. The returned session is locked. */
+static struct csession *
+crypto_get_session_by_sid(struct fcrypt *fcr, uint32_t sid)
+{
+	struct csession *ses_ptr;
+
+	down(&fcr->sem);
+	list_for_each_entry(ses_ptr, &fcr->list, entry) {
+		if(ses_ptr->sid == sid) {
+			down(&ses_ptr->sem);
+			break;
+		}
+	}
+	up(&fcr->sem);
+
+	return ses_ptr;
+}
+
+/* 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;
+	char __user *src, __user *dst;
+	struct scatterlist sg;
+	struct csession *ses_ptr;
+	unsigned int ivsize;
+	size_t nbytes, bufsize;
+	int ret = 0;
+	struct blkcipher_desc desc;
+
+	nbytes = cop->len;
+
+	if (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, cop->ses);
+	if (!ses_ptr) {
+		dprintk(1, KERN_ERR, "invalid session ID=0x%08X\n", cop->ses);
+		return -EINVAL;
+	}
+
+	if (nbytes % crypto_blkcipher_blocksize(ses_ptr->tfm)) {
+		dprintk(1, KERN_ERR,
+			"data size (%zu) isn't a multiple of block size (%u)\n",
+			nbytes, crypto_blkcipher_blocksize(ses_ptr->tfm));
+		ret = -EINVAL;
+		goto out_unlock;
+	}
+
+	bufsize = PAGE_SIZE < nbytes ? PAGE_SIZE : nbytes;
+	data = (char*)__get_free_page(GFP_KERNEL);
+
+	if (unlikely(!data)) {
+		ret = -ENOMEM;
+		goto out_unlock;
+	}
+
+	ivsize = crypto_blkcipher_ivsize(ses_ptr->tfm);
+
+	ivp = kmalloc(ivsize, GFP_KERNEL);
+	if (unlikely(!ivp)) {
+		free_page((unsigned long)data);
+		ret = -ENOMEM;
+		goto out_unlock;
+	}
+
+	if (cop->iv) {
+		copy_from_user(ivp, cop->iv, ivsize);
+		crypto_blkcipher_set_iv(ses_ptr->tfm, ivp, ivsize);
+	}
+
+	src = cop->src;
+	dst = cop->dst;
+
+	desc.tfm = ses_ptr->tfm;
+	desc.info = NULL;
+	desc.flags = 0;
+
+	while (nbytes > 0) {
+		size_t current_len = nbytes > bufsize ? bufsize : nbytes;
+
+		copy_from_user(data, src, current_len);
+
+		sg_set_buf(&sg, data, current_len);
+
+		if (cop->op == COP_DECRYPT)
+			ret = crypto_blkcipher_decrypt(&desc, &sg, &sg, current_len);
+		else
+			ret = crypto_blkcipher_encrypt(&desc, &sg, &sg, current_len);
+
+		if (unlikely(ret)) {
+			dprintk(0, KERN_ERR, "CryptoAPI failure: flags=0x%x\n",
+				crypto_blkcipher_tfm(ses_ptr->tfm)->crt_flags);
+			goto out;
+		}
+
+		copy_to_user(dst, data, current_len);
+
+		nbytes -= current_len;
+		src += 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[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);
+
+	kfree(ivp);
+
+out_unlock:
+	up(&ses_ptr->sem);
+
+	return ret;
+}
+
+/* ====== /dev/crypto ====== */
+
+static int
+cryptodev_open(struct inode *inode, struct file *filp)
+{
+	struct fcrypt *fcr;
+
+	fcr = kmalloc(sizeof(*fcr), GFP_KERNEL);
+	if(!fcr)
+		return -ENOMEM;
+
+	memset(fcr, 0, sizeof(*fcr));
+	init_MUTEX(&fcr->sem);
+	INIT_LIST_HEAD(&fcr->list);
+	filp->private_data = fcr;
+
+	return 0;
+}
+
+static int
+cryptodev_release(struct inode *inode, struct file *filp)
+{
+	struct fcrypt *fcr = filp->private_data;
+
+	if(fcr) {
+		crypto_finish_all_sessions(fcr);
+		kfree(fcr);
+		filp->private_data = NULL;
+	}
+	return 0;
+}
+
+static int
+clonefd(struct file *filp)
+{
+	int fd;
+
+	fd = get_unused_fd();
+	if (fd >= 0) {
+		get_file(filp);
+		fd_install(fd, filp);
+	}
+
+	return fd;
+}
+
+static int
+cryptodev_ioctl(struct inode *inode, struct file *filp,
+		unsigned int cmd, unsigned long arg)
+{
+	struct session_op sop;
+	struct crypt_op cop;
+	struct fcrypt *fcr = filp->private_data;
+	uint32_t ses;
+	int ret, fd;
+
+	if (!fcr)
+		BUG();
+
+	switch (cmd) {
+		case CRIOGET:
+			fd = clonefd(filp);
+			put_user(fd, (int*)arg);
+			return 0;
+
+		case CIOCGSESSION:
+			copy_from_user(&sop, (void*)arg, sizeof(sop));
+			ret = crypto_create_session(fcr, &sop);
+			if (ret)
+				return ret;
+			copy_to_user((void*)arg, &sop, sizeof(sop));
+			return 0;
+
+		case CIOCFSESSION:
+			get_user(ses, (uint32_t*)arg);
+			ret = crypto_finish_session(fcr, ses);
+			return ret;
+
+		case CIOCCRYPT:
+			copy_from_user(&cop, (void*)arg, sizeof(cop));
+			ret = crypto_run(fcr, &cop);
+			copy_to_user((void*)arg, &cop, sizeof(cop));
+			return ret;
+
+		default:
+			return -EINVAL;
+	}
+}
+
+struct file_operations cryptodev_fops = {
+	.owner = THIS_MODULE,
+	.open = cryptodev_open,
+	.release = cryptodev_release,
+	.ioctl = cryptodev_ioctl,
+};
+
+struct miscdevice cryptodev = {
+	.minor = CRYPTODEV_MINOR,
+	.name = "crypto",
+	.fops = &cryptodev_fops,
+};
+
+static int
+cryptodev_register(void)
+{
+	int rc;
+
+	rc = misc_register (&cryptodev);
+	if (rc) {
+		printk(KERN_ERR PFX "registeration of /dev/crypto failed\n");
+		return rc;
+	}
+
+	return 0;
+}
+
+static void
+cryptodev_deregister(void)
+{
+	misc_deregister(&cryptodev);
+}
+
+/* ====== Module init/exit ====== */
+
+int __init
+init_cryptodev(void)
+{
+	int rc;
+
+	rc = cryptodev_register();
+	if (rc)
+		return rc;
+
+	printk(KERN_INFO PFX "driver loaded.\n");
+
+	return 0;
+}
+
+void __exit
+exit_cryptodev(void)
+{
+	cryptodev_deregister();
+	printk(KERN_INFO PFX "driver unloaded.\n");
+}
+
+module_init(init_cryptodev);
+module_exit(exit_cryptodev);
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index d066bbc..d9af0ab 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -51,6 +51,7 @@ header-y += comstats.h
 header-y += const.h
 header-y += cgroupstats.h
 header-y += cramfs_fs.h
+header-y += cryptodev.h
 header-y += cycx_cfm.h
 header-y += dlmconstants.h
 header-y += dlm_device.h
diff --git a/include/linux/cryptodev.h b/include/linux/cryptodev.h
new file mode 100644
index 0000000..0f8f670
--- /dev/null
+++ b/include/linux/cryptodev.h
@@ -0,0 +1,82 @@
+/*
+ * Driver for /dev/crypto device (aka CryptoDev)
+ *
+ * Copyright (c) 2004 Michal Ludvig <mludvig at suse.cz>, SuSE Labs
+ *
+ * Structures and ioctl command names were taken from
+ * OpenBSD to preserve compatibility with their API.
+ *
+ */
+
+#ifndef _CRYPTODEV_H
+#define _CRYPTODEV_H
+
+#ifndef __KERNEL__
+#include <inttypes.h>
+#endif
+
+#define	CRYPTODEV_MINOR	MISC_DYNAMIC_MINOR
+
+#define CRYPTO_FLAG_ECB		0x0000
+#define CRYPTO_FLAG_CBC		0x0001
+#define CRYPTO_FLAG_CFB		0x0002
+#define CRYPTO_FLAG_OFB		0x0003
+#define CRYPTO_FLAG_CTR		0x0004
+#define CRYPTO_FLAG_HMAC	0x0010
+#define CRYPTO_FLAG_MASK	0x00FF
+
+#define	CRYPTO_CIPHER_NAME	0x0100
+#define	CRYPTO_CIPHER_NAME_CBC	(CRYPTO_CIPHER_NAME | CRYPTO_FLAG_CBC)
+#define	CRYPTO_HASH_NAME	0x0200
+#define	CRYPTO_HASH_NAME_HMAC	(CRYPTO_HASH_NAME | CRYPTO_FLAG_HMAC)
+
+/* ioctl parameter to create a session */
+struct session_op {
+	unsigned int	cipher;		/* e.g. CRYPTO_DES_CBC */
+	unsigned int	mac;		/* e.g. CRYPTO_MD5_HMAC */
+	char		*alg_name;	/* set cipher=CRYPTO_CIPHER_NAME
+					   or  mac=CRYPTO_HASH_NAME */
+	#define	MAX_ALG_NAME_LEN 128
+	size_t		alg_namelen;
+
+	size_t		keylen;		/* cipher key */
+	char		*key;
+	int		mackeylen;	/* mac key */
+	char		*mackey;
+
+	/* Return values */
+	unsigned int	blocksize;	/* selected algorithm's block size */
+	uint32_t	ses;		/* session ID */
+};
+
+/* ioctl parameter to request a crypt/decrypt operation against a session  */
+struct crypt_op {
+	uint32_t	ses;		/* from session_op->ses */
+	#define COP_DECRYPT	0
+	#define COP_ENCRYPT	1
+	uint32_t	op;		/* ie. COP_ENCRYPT */
+	uint32_t	flags;		/* unused */
+
+	size_t		len;
+	char		*src, *dst;
+	char		*mac;
+	char		*iv;
+};
+
+/* clone original filedescriptor */
+#define CRIOGET         _IOWR('c', 100, uint32_t)
+
+/* create crypto session */
+#define CIOCGSESSION    _IOWR('c', 101, struct session_op)
+
+/* finish crypto session */
+#define CIOCFSESSION    _IOW('c', 102, uint32_t)
+
+/* request encryption/decryptions of a given buffer */
+#define CIOCCRYPT       _IOWR('c', 103, struct crypt_op)
+
+/* ioctl()s for asym-crypto. Not yet supported. */
+#define CIOCKEY         _IOWR('c', 104, void *)
+#define CIOCASYMFEAT    _IOR('c', 105, uint32_t)
+
+#endif /* _CRYPTODEV_H */
-- 
1.6.0.4





More information about the kernel-team mailing list