linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Miloslav Trmač" <mitr@redhat.com>
To: Herbert Xu <herbert@gondor.hengli.com.au>
Cc: linux-crypto@vger.kernel.org,
	"Nikos Mavrogiannopoulos" <n.mavrogiannopoulos@gmail.com>,
	"Neil Horman" <nhorman@redhat.com>,
	linux-kernel@vger.kernel.org, "Miloslav Trmač" <mitr@redhat.com>
Subject: [PATCH 18/19] Add ioctl handlers
Date: Fri, 20 Aug 2010 10:46:02 +0200	[thread overview]
Message-ID: <1282293963-27807-20-git-send-email-mitr@redhat.com> (raw)
In-Reply-To: <1282293963-27807-1-git-send-email-mitr@redhat.com>

Add ioctl and compat_ioctl handling.  This is the only file that
directly accesses structured data from userspace (other files may access
unformated data such as cipher input or multiple-precision integers).

Also add the last operation, ncr_master_key_set.
---
 crypto/userspace/ncr.c |  405 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 405 insertions(+), 0 deletions(-)

diff --git a/crypto/userspace/ncr.c b/crypto/userspace/ncr.c
index 9fb56ad..ee812ab 100644
--- a/crypto/userspace/ncr.c
+++ b/crypto/userspace/ncr.c
@@ -44,6 +44,411 @@
  */
 struct key_item_st master_key;
 
+static struct mutex lists_ida_mutex;
+static DEFINE_IDA(lists_ida);
+
+struct ncr_lists *ncr_init_lists(void)
+{
+	struct ncr_lists *lst;
+
+	lst = kmalloc(sizeof(*lst), GFP_KERNEL);
+	if(!lst) {
+		err();
+		return NULL;
+	}
+
+	memset(lst, 0, sizeof(*lst));
+
+	mutex_init(&lists_ida_mutex);
+	mutex_lock(&lists_ida_mutex);
+	/* ida_pre_get() should preallocate enough, and, due to lists_ida_mutex,
+	   nobody else can use the preallocated data.  Therefore the loop
+	   recommended in idr_get_new() documentation is not necessary. */
+	if (ida_pre_get(&lists_ida, GFP_KERNEL) == 0 ||
+	    ida_get_new(&lists_ida, &lst->id) != 0) {
+		mutex_unlock(&lists_ida_mutex);
+		kfree(lst);
+		return NULL;
+	}
+	mutex_unlock(&lists_ida_mutex);
+
+	mutex_init(&lst->key_idr_mutex);
+	idr_init(&lst->key_idr);
+
+	mutex_init(&lst->session_idr_mutex);
+	idr_init(&lst->session_idr);
+
+	return lst;
+}
+
+void ncr_deinit_lists(struct ncr_lists *lst)
+{
+	if(lst) {
+		ncr_key_list_deinit(lst);
+		ncr_sessions_list_deinit(lst);
+
+		mutex_lock(&lists_ida_mutex);
+		ida_remove(&lists_ida, lst->id);
+		mutex_unlock(&lists_ida_mutex);
+
+		kfree(lst);
+	}
+}
+
+void ncr_master_key_reset(void)
+{
+	memset(&master_key, 0, sizeof(master_key));
+}
+
+static int ncr_master_key_set(const struct ncr_master_key_set *st,
+			      struct nlattr *tb[])
+{
+struct audit_buffer *ab;
+int ret;
+
+	/* This will also cause auditing of the syscall, including information
+	   about the process, and success/failure indication.  Note that on
+	   error the AUDIT_CRYPTO_STORAGE_KEY record will be empty. */
+	ab = audit_log_start(current->audit_context, GFP_KERNEL,
+			     AUDIT_CRYPTO_STORAGE_KEY);
+
+	if (current_euid() != 0 && !capable(CAP_SYS_ADMIN)) {
+		err();
+		ret = -EPERM;
+		goto end;
+	}
+
+	if (st->key_size > sizeof(master_key.key.secret.data)) {
+		err();
+		ret = -EINVAL;
+		goto end;
+	}
+
+	if (st->key_size != 16 && st->key_size != 24 && st->key_size != 32) {
+		dprintk(0, KERN_DEBUG, "Master key size must be 16,24 or 32.\n");
+		ret = -EINVAL;
+		goto end;
+	}
+
+	if (master_key.type != NCR_KEY_TYPE_INVALID) {
+		dprintk(0, KERN_DEBUG, "Master key was previously initialized.\n");
+	}
+
+	if (unlikely(copy_from_user(master_key.key.secret.data, st->key,
+				    st->key_size))) {
+		err();
+		ret = -EFAULT;
+		goto end;
+	}
+
+	dprintk(0, KERN_INFO, "Initializing master key.\n");
+	/* Not much we can reveal... */
+	audit_log_format(ab, "key_size=%u", (unsigned)st->key_size);
+
+	master_key.type = NCR_KEY_TYPE_SECRET;
+	master_key.key.secret.size = st->key_size;
+
+	ret = 0;
+
+end:
+	audit_log_end(ab);
+
+	return ret;
+}
+
+int
+ncr_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg_)
+{
+	void __user *arg = (void __user *)arg_;
+	struct nlattr *tb[NCR_ATTR_MAX + 1];
+	void *attr_buf;
+	int ret;
+
+	if (unlikely(!lst))
+		BUG();
+
+	switch (cmd) {
+#define CASE_(LABEL, STRUCT, FUNCTION, ARGS)				\
+	case (LABEL): {							\
+		struct STRUCT data;					\
+									\
+		attr_buf = NCR_GET_INPUT_ARGS_NO_OUTPUT(&data, tb, arg); \
+		if (IS_ERR(attr_buf)) {					\
+			err();						\
+			return PTR_ERR(attr_buf);			\
+		}							\
+		ret = (FUNCTION)ARGS;					\
+		break;							\
+	}
+#define CASE_NO_OUTPUT(LABEL, STRUCT, FUNCTION)				\
+		CASE_(LABEL, STRUCT, FUNCTION, (lst, &data, tb))
+#define CASE_NO_OUTPUT_COMPAT(LABEL, STRUCT, FUNCTION)			\
+		CASE_(LABEL, STRUCT, FUNCTION, (lst, &data, tb, 0))
+
+	case NCRIO_KEY_INIT:
+		return ncr_key_init(lst);
+	CASE_NO_OUTPUT(NCRIO_KEY_GENERATE, ncr_key_generate, ncr_key_generate);
+	CASE_NO_OUTPUT(NCRIO_KEY_GENERATE_PAIR, ncr_key_generate_pair,
+		       ncr_key_generate_pair);
+	CASE_NO_OUTPUT(NCRIO_KEY_DERIVE, ncr_key_derive, ncr_key_derive);
+	case NCRIO_KEY_GET_INFO: {
+		struct ncr_key_get_info data;
+		struct ncr_out out;
+
+		attr_buf = NCR_GET_INPUT_ARGS(&data, tb, arg);
+		if (IS_ERR(attr_buf)) {
+			err();
+			return PTR_ERR(attr_buf);
+		}
+		ret = NCR_OUT_INIT(&out, &data, arg);
+		if (ret != 0) {
+			err();
+			break;
+		}
+		ret = ncr_key_get_info(lst, &out, &data, tb);
+		ncr_out_free(&out);
+		break;
+	}
+	CASE_NO_OUTPUT(NCRIO_KEY_EXPORT, ncr_key_export, ncr_key_export);
+	CASE_NO_OUTPUT(NCRIO_KEY_IMPORT, ncr_key_import, ncr_key_import);
+	case NCRIO_KEY_DEINIT: {
+		ncr_key_t key;
+
+		ret = get_user(key, (const ncr_key_t __user *)arg);
+		if (unlikely(ret)) {
+			err();
+			return ret;
+		}
+		return ncr_key_deinit(lst, key);
+	}
+	CASE_NO_OUTPUT(NCRIO_KEY_WRAP, ncr_key_wrap, ncr_key_wrap);
+	CASE_NO_OUTPUT(NCRIO_KEY_UNWRAP, ncr_key_unwrap, ncr_key_unwrap);
+	CASE_NO_OUTPUT(NCRIO_KEY_STORAGE_WRAP, ncr_key_storage_wrap,
+		       ncr_key_storage_wrap);
+	CASE_NO_OUTPUT(NCRIO_KEY_STORAGE_UNWRAP, ncr_key_storage_unwrap,
+		       ncr_key_storage_unwrap);
+	CASE_NO_OUTPUT(NCRIO_SESSION_INIT, ncr_session_init, ncr_session_init);
+	CASE_NO_OUTPUT_COMPAT(NCRIO_SESSION_UPDATE, ncr_session_update,
+			      ncr_session_update);
+	CASE_NO_OUTPUT_COMPAT(NCRIO_SESSION_FINAL, ncr_session_final,
+			      ncr_session_final);
+	CASE_NO_OUTPUT_COMPAT(NCRIO_SESSION_ONCE, ncr_session_once,
+			      ncr_session_once);
+	CASE_(NCRIO_MASTER_KEY_SET, ncr_master_key_set, ncr_master_key_set,
+	      (&data, tb));
+	default:
+		return -EINVAL;
+#undef CASE_
+#undef CASE_NO_OUTPUT
+#undef CASE_NO_OUTPUT_COMPAT
+	}
+	kfree(attr_buf);
+	return ret;
+}
+
+#ifdef CONFIG_COMPAT
+struct compat_ncr_key_export {
+	__u32 input_size, output_size;
+	ncr_key_t key;
+	compat_uptr_t buffer;
+	compat_int_t buffer_size;
+	__NL_ATTRIBUTES;
+};
+#define COMPAT_NCRIO_KEY_EXPORT _IOWR('c', 209, struct compat_ncr_key_export)
+
+static void convert_ncr_key_export(struct ncr_key_export *new,
+				   const struct compat_ncr_key_export *old)
+{
+	new->key = old->key;
+	new->buffer = compat_ptr(old->buffer);
+	new->buffer_size = old->buffer_size;
+}
+
+struct compat_ncr_key_import {
+	__u32 input_size, output_size;
+	ncr_key_t key;
+	compat_uptr_t data;
+	__u32 data_size;
+	__NL_ATTRIBUTES;
+};
+#define COMPAT_NCRIO_KEY_IMPORT _IOWR('c', 210, struct compat_ncr_key_import)
+
+static void convert_ncr_key_import(struct ncr_key_import *new,
+				   const struct compat_ncr_key_import *old)
+{
+	new->key = old->key;
+	new->data = compat_ptr(old->data);
+	new->data_size = old->data_size;
+}
+
+struct compat_ncr_key_wrap {
+	__u32 input_size, output_size;
+	ncr_key_t wrapping_key;
+	ncr_key_t source_key;
+	compat_uptr_t buffer;
+	compat_int_t buffer_size;
+	__NL_ATTRIBUTES;
+};
+#define COMPAT_NCRIO_KEY_WRAP _IOWR('c', 250, struct compat_ncr_key_wrap)
+
+static void convert_ncr_key_wrap(struct ncr_key_wrap *new,
+				 const struct compat_ncr_key_wrap *old)
+{
+	new->wrapping_key = old->wrapping_key;
+	new->source_key = old->source_key;
+	new->buffer = compat_ptr(old->buffer);
+	new->buffer_size = old->buffer_size;
+}
+
+struct compat_ncr_key_unwrap {
+	__u32 input_size, output_size;
+	ncr_key_t wrapping_key;
+	ncr_key_t dest_key;
+	compat_uptr_t data;
+	__u32 data_size;
+	__NL_ATTRIBUTES;
+};
+#define COMPAT_NCRIO_KEY_UNWRAP _IOWR('c', 251, struct compat_ncr_key_unwrap)
+
+static void convert_ncr_key_unwrap(struct ncr_key_unwrap *new,
+				   const struct compat_ncr_key_unwrap *old)
+{
+	new->wrapping_key = old->wrapping_key;
+	new->dest_key = old->dest_key;
+	new->data = compat_ptr(old->data);
+	new->data_size = old->data_size;
+}
+
+struct compat_ncr_key_storage_wrap {
+	__u32 input_size, output_size;
+	ncr_key_t key;
+	compat_uptr_t buffer;
+	compat_int_t buffer_size;
+	__NL_ATTRIBUTES;
+};
+#define COMPAT_NCRIO_KEY_STORAGE_WRAP				\
+	_IOWR('c', 261, struct compat_ncr_key_storage_wrap)
+
+static void convert_ncr_key_storage_wrap(struct ncr_key_storage_wrap *new,
+					 const struct compat_ncr_key_storage_wrap *old)
+{
+	new->key = old->key;
+	new->buffer = compat_ptr(old->buffer);
+	new->buffer_size = old->buffer_size;
+}
+
+struct compat_ncr_key_storage_unwrap {
+	__u32 input_size, output_size;
+	ncr_key_t key;
+	compat_uptr_t data;
+	__u32 data_size;
+	__NL_ATTRIBUTES;
+};
+#define COMPAT_NCRIO_KEY_STORAGE_UNWRAP				\
+	_IOWR('c', 262, struct compat_ncr_key_storage_wrap)
+
+static void convert_ncr_key_storage_unwrap(struct ncr_key_storage_unwrap *new,
+					   const struct compat_ncr_key_storage_unwrap *old)
+{
+	new->key = old->key;
+	new->data = compat_ptr(old->data);
+	new->data_size = old->data_size;
+}
+
+struct compat_ncr_master_key_set {
+	__u32 input_size, output_size;
+	compat_uptr_t key;
+	__u32 key_size;
+	__NL_ATTRIBUTES;
+};
+#define COMPAT_NCRIO_MASTER_KEY_SET				\
+	_IOWR('c', 260, struct compat_ncr_master_key_set)
+
+static void convert_ncr_master_key_set(struct ncr_master_key_set *new,
+				       const struct compat_ncr_master_key_set *old)
+{
+	new->key = compat_ptr(old->key);
+	new->key_size = old->key_size;
+}
+
+long
+ncr_compat_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg_)
+{
+	void __user *arg = (void __user *)arg_;
+	struct nlattr *tb[NCR_ATTR_MAX + 1];
+	void *attr_buf;
+	int ret;
+
+	if (unlikely(!lst))
+		BUG();
+
+	switch (cmd) {
+	case NCRIO_KEY_INIT:
+	case NCRIO_KEY_GENERATE:
+	case NCRIO_KEY_GENERATE_PAIR:
+	case NCRIO_KEY_DERIVE:
+	case NCRIO_KEY_GET_INFO:
+	case NCRIO_KEY_DEINIT:
+	case NCRIO_SESSION_INIT:
+		return ncr_ioctl(lst, cmd, arg_);
+
+#define CASE_(LABEL, STRUCT, FUNCTION, ARGS)				\
+	case (LABEL): {							\
+		struct compat_##STRUCT old;				\
+		struct STRUCT new;					\
+									\
+		attr_buf = NCR_GET_INPUT_ARGS_NO_OUTPUT(&old, tb, arg);	\
+		if (IS_ERR(attr_buf)) {					\
+			err();						\
+			return PTR_ERR(attr_buf);			\
+		}							\
+		convert_##STRUCT(&new, &old);				\
+		ret = (FUNCTION)ARGS;					\
+		break;							\
+	}
+#define CASE_NO_OUTPUT(LABEL, STRUCT, FUNCTION)			\
+		CASE_(LABEL, STRUCT, FUNCTION, (lst, &new, tb))
+
+#define CASE_COMPAT_ONLY(LABEL, STRUCT, FUNCTION)			\
+	case (LABEL): {							\
+		struct STRUCT data;					\
+									\
+		attr_buf = NCR_GET_INPUT_ARGS_NO_OUTPUT(&data, tb, arg); \
+		if (IS_ERR(attr_buf)) {					\
+			err();						\
+			return PTR_ERR(attr_buf);			\
+		}							\
+		ret = (FUNCTION)(lst, &data, tb, 1);			\
+		break;							\
+	}
+
+	CASE_NO_OUTPUT(COMPAT_NCRIO_KEY_EXPORT, ncr_key_export, ncr_key_export);
+	CASE_NO_OUTPUT(COMPAT_NCRIO_KEY_IMPORT, ncr_key_import, ncr_key_import);
+	CASE_NO_OUTPUT(COMPAT_NCRIO_KEY_WRAP, ncr_key_wrap, ncr_key_wrap);
+	CASE_NO_OUTPUT(COMPAT_NCRIO_KEY_UNWRAP, ncr_key_unwrap, ncr_key_unwrap);
+	CASE_NO_OUTPUT(COMPAT_NCRIO_KEY_STORAGE_WRAP, ncr_key_storage_wrap,
+		       ncr_key_storage_wrap);
+	CASE_NO_OUTPUT(COMPAT_NCRIO_KEY_STORAGE_UNWRAP, ncr_key_storage_unwrap,
+		       ncr_key_storage_unwrap);
+	CASE_COMPAT_ONLY(NCRIO_SESSION_UPDATE, ncr_session_update,
+			 ncr_session_update);
+	CASE_COMPAT_ONLY(NCRIO_SESSION_FINAL, ncr_session_final,
+			 ncr_session_final);
+	CASE_COMPAT_ONLY(NCRIO_SESSION_ONCE, ncr_session_once,
+			 ncr_session_once);
+	CASE_(COMPAT_NCRIO_MASTER_KEY_SET, ncr_master_key_set,
+	      ncr_master_key_set, (&new, tb));
+	default:
+		return -EINVAL;
+#undef CASE_
+#undef CASE_NO_OUTPUT
+#undef CASE_COMPAT_ONLY
+	}
+	kfree(attr_buf);
+	return ret;
+}
+#endif
+
 int ncr_session_input_data_from_nla(struct ncr_session_input_data *dest,
 				    const struct nlattr *nla, int compat)
 {
-- 
1.7.2.1


  parent reply	other threads:[~2010-08-20  8:47 UTC|newest]

Thread overview: 45+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-08-20  8:45 [PATCH 00/19] RFC, v2: "New" /dev/crypto user-space interface Miloslav Trmač
2010-08-20  8:45 ` [PATCH 01/19] User-space API definition Miloslav Trmač
2010-08-20 12:48   ` Stefan Richter
2010-08-21  7:35     ` Nikos Mavrogiannopoulos
2010-08-21  9:11     ` Miloslav Trmac
2010-08-20 17:12   ` Randy Dunlap
2010-08-21 13:09   ` Kyle Moffett
2010-08-21 14:54     ` Nikos Mavrogiannopoulos
2010-08-22 10:22     ` David Howells
2010-09-03  9:18   ` Herbert Xu
2010-09-03  9:34     ` Nikos Mavrogiannopoulos
2010-09-03 15:20     ` Nikos Mavrogiannopoulos
2010-08-20  8:45 ` [PATCH 02/19] Add CRYPTO_USERSPACE config option Miloslav Trmač
2010-08-20  8:45 ` [PATCH 03/19] Add libtommath headers Miloslav Trmač
2010-08-20  8:45 ` [PATCH 04/19] Add libtomcrypt headers Miloslav Trmač
2010-08-20  8:45 ` [PATCH 05/19] Add internal /dev/crypto implementation headers Miloslav Trmač
2010-08-20  8:45 ` [PATCH 06/19] Add ioctl() argument and attribute handling utils Miloslav Trmač
2010-08-20 12:59   ` Stefan Richter
2010-08-21  2:15     ` Miloslav Trmac
2010-08-21  7:15       ` Stefan Richter
2010-08-20  8:45 ` [PATCH 07/19] Add crypto API utilities Miloslav Trmač
2010-08-20  8:45 ` [PATCH 08/19] Add per-process and per-user limits Miloslav Trmač
2010-08-20  8:45 ` [PATCH 09/19] Add libtommath implementation Miloslav Trmač
2010-08-20  8:45 ` [PATCH 10/19] Add libtomcrypt implementation Miloslav Trmač
2010-08-20  8:45 ` [PATCH 10/19] Add libtommath implementation Miloslav Trmač
2010-08-20  8:45 ` [PATCH 11/19] Add algorithm properties table Miloslav Trmač
2010-08-20  8:45 ` [PATCH 12/19] Add DH implementation and pubkey abstraction layer Miloslav Trmač
2010-08-20  8:45 ` [PATCH 13/19] Add /dev/crypto auditing infrastructure Miloslav Trmač
2010-08-20  8:45 ` [PATCH 14/19] Add most operations on key objects Miloslav Trmač
2010-08-20  8:45 ` [PATCH 15/19] Add key wrapping operations Miloslav Trmač
2010-08-20  8:46 ` [PATCH 16/19] Add helpers for zero-copy userspace access Miloslav Trmač
2010-08-20  8:46 ` [PATCH 17/19] Add session operations Miloslav Trmač
2010-08-20  8:46 ` Miloslav Trmač [this message]
2010-08-20  8:46 ` [PATCH 19/19] Finally, add the /dev/crypto device Miloslav Trmač
2010-08-20 13:56 ` [PATCH 00/19] RFC, v2: "New" /dev/crypto user-space interface Ted Ts'o
2010-08-20 17:03   ` Nikos Mavrogiannopoulos
2010-08-20 23:48     ` Ted Ts'o
2010-08-23  6:39       ` Tomas Mraz
2010-08-21 17:08 ` Arnd Bergmann
2010-08-22  7:52   ` Nikos Mavrogiannopoulos
2010-08-23  8:09     ` Arnd Bergmann
2010-08-23  9:34       ` Nikos Mavrogiannopoulos
2010-08-25  6:20 ` Pavel Machek
2010-08-25  6:44   ` Tomas Mraz
2010-08-25 15:28   ` Miloslav Trmac

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1282293963-27807-20-git-send-email-mitr@redhat.com \
    --to=mitr@redhat.com \
    --cc=herbert@gondor.hengli.com.au \
    --cc=linux-crypto@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=n.mavrogiannopoulos@gmail.com \
    --cc=nhorman@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).