All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v8 0/6] crypto: algif - add akcipher
@ 2016-06-23 22:55 Tadeusz Struk
  2016-06-23 22:55 ` [PATCH v8 2/6] crypto: AF_ALG -- add setpubkey setsockopt call Tadeusz Struk
                   ` (4 more replies)
  0 siblings, 5 replies; 20+ messages in thread
From: Tadeusz Struk @ 2016-06-23 22:55 UTC (permalink / raw)
  To: dhowells
  Cc: herbert, tadeusz.struk, smueller, linux-api, marcel,
	mathew.j.martineau, linux-kernel, keyrings, linux-crypto, dwmw2,
	davem

First four patches are a resend algif_akcipher from
Stephan Mueller, with minor changes after rebase on top of 4.7-rc1.

The next three patches add support for keys stored in system
keyring subsystem.

First patch adds algif_akcipher nokey hadlers.

Second patch adds generic sign, verify, encrypt, decrypt accessors
functions to the asymmetric key type. These will be defined by
asymmetric subtypes, similarly to how public_key currently defines
the verify_signature function.

Third patch adds support for ALG_SET_KEY_ID and ALG_SET_PUBKEY_ID
commands to AF_ALG and setkeyid operation to the af_alg_type struct.
If the keyid is used then the afalg layer acquires the key for the
keyring subsystem and uses the new asymmetric accessor functions
instead of akcipher api. The asymmetric subtypes can use akcipher
api internally.

Patches are generate against:
http://git.kernel.org/cgit/linux/kernel/git/dhowells/linux-fs.git/log/?h=keys-next

v8 hanges:
- copy the result to user for verify after the signature_verify
  operation. Before only the return code was checked, but not the
  actual data. Reported by Mat Martineau
- remove the constrain on the output buffer size as requested by
  Mat Martineau
- ifx uninitialize variable issue, reported by Mat Martineau

v7 changes:
- update to reflect changes in kernel_pkey_params struct

v6 changes:
- rabased on top of
http://git.kernel.org/cgit/linux/kernel/git/dhowells/linux-fs.git/log/?h=keys-asym-keyctl

v5 changes:
- drop public key changes and use new version provided by David

v4 changes:
- don't use internal public_key struct in af_alg.
- add generic accessor functions to asymmetric key type, which take
  the generic struct key type and resolve the specific subtype internally

v3 changes:
- include Stephan's patches (rebased on 4.6-rc1)
- add algif_akcipher nokey hadlers
- add public_key info struct to public_key and helper query functions
- add a check if a key is a software accessible key on af_alg, and
  return -ENOKEY if it isn't

v2 changes:
- pass the original skcipher request in ablkcipher.base.data instead of
  casting it back from the ablkcipher request.
- rename _req to base_req
- dropped 3/3

---

Stephan Mueller (4):
      crypto: AF_ALG -- add sign/verify API
      crypto: AF_ALG -- add setpubkey setsockopt call
      crypto: AF_ALG -- add asymmetric cipher interface
      crypto: algif_akcipher - enable compilation

Tadeusz Struk (2):
      crypto: algif_akcipher - add ops_nokey
      crypto: AF_ALG - add support for key_id


 crypto/Kconfig              |    9 
 crypto/Makefile             |    1 
 crypto/af_alg.c             |   28 +
 crypto/algif_akcipher.c     |  878 +++++++++++++++++++++++++++++++++++++++++++
 include/crypto/if_alg.h     |    2 
 include/uapi/linux/if_alg.h |    5 
 6 files changed, 918 insertions(+), 5 deletions(-)
 create mode 100644 crypto/algif_akcipher.c

--
TS

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH v8 1/6] crypto: AF_ALG -- add sign/verify API
  2016-06-23 22:55 [PATCH v8 0/6] crypto: algif - add akcipher Tadeusz Struk
@ 2016-06-23 22:55     ` Tadeusz Struk
  2016-06-23 22:55 ` [PATCH v8 3/6] crypto: AF_ALG -- add asymmetric cipher interface Tadeusz Struk
                       ` (3 subsequent siblings)
  4 siblings, 0 replies; 20+ messages in thread
From: Tadeusz Struk @ 2016-06-23 22:55 UTC (permalink / raw)
  To: dhowells-H+wXaHxf7aLQT0dZR+AlfA
  Cc: herbert-lOAM2aK0SrRLBo1qDEOMRrpzq4S04n8Q,
	tadeusz.struk-ral2JQCrhuEAvxtiuMwx3w,
	smueller-T9tCv8IpfcWELgA04lAiVw,
	linux-api-u79uwXL29TY76Z2rM5mHXA, marcel-kz+m5ild9QBg9hUCZPvPmw,
	mathew.j.martineau-VuQAYsv1563Yd54FQh9/CA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	keyrings-u79uwXL29TY76Z2rM5mHXA,
	linux-crypto-u79uwXL29TY76Z2rM5mHXA,
	dwmw2-wEGCiKHe2LqWVfeAwA7xHQ, davem-fT/PcQaiUtIeIZ0/mPfg9Q

From: Stephan Mueller <smueller-T9tCv8IpfcWELgA04lAiVw@public.gmane.org>

Add the flags for handling signature generation and signature
verification.

Also, the patch adds the interface for setting a public key.

Signed-off-by: Stephan Mueller <smueller-T9tCv8IpfcWELgA04lAiVw@public.gmane.org>
Signed-off-by: Tadeusz Struk <tadeusz.struk-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---
 include/uapi/linux/if_alg.h |    3 +++
 1 file changed, 3 insertions(+)

diff --git a/include/uapi/linux/if_alg.h b/include/uapi/linux/if_alg.h
index f2acd2f..02e6162 100644
--- a/include/uapi/linux/if_alg.h
+++ b/include/uapi/linux/if_alg.h
@@ -34,9 +34,12 @@ struct af_alg_iv {
 #define ALG_SET_OP			3
 #define ALG_SET_AEAD_ASSOCLEN		4
 #define ALG_SET_AEAD_AUTHSIZE		5
+#define ALG_SET_PUBKEY			6
 
 /* Operations */
 #define ALG_OP_DECRYPT			0
 #define ALG_OP_ENCRYPT			1
+#define ALG_OP_SIGN			2
+#define ALG_OP_VERIFY			3
 
 #endif	/* _LINUX_IF_ALG_H */

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v8 1/6] crypto: AF_ALG -- add sign/verify API
@ 2016-06-23 22:55     ` Tadeusz Struk
  0 siblings, 0 replies; 20+ messages in thread
From: Tadeusz Struk @ 2016-06-23 22:55 UTC (permalink / raw)
  To: dhowells
  Cc: herbert, tadeusz.struk, smueller, linux-api, marcel,
	mathew.j.martineau, linux-kernel, keyrings, linux-crypto, dwmw2,
	davem

From: Stephan Mueller <smueller@chronox.de>

Add the flags for handling signature generation and signature
verification.

Also, the patch adds the interface for setting a public key.

Signed-off-by: Stephan Mueller <smueller@chronox.de>
Signed-off-by: Tadeusz Struk <tadeusz.struk@intel.com>
---
 include/uapi/linux/if_alg.h |    3 +++
 1 file changed, 3 insertions(+)

diff --git a/include/uapi/linux/if_alg.h b/include/uapi/linux/if_alg.h
index f2acd2f..02e6162 100644
--- a/include/uapi/linux/if_alg.h
+++ b/include/uapi/linux/if_alg.h
@@ -34,9 +34,12 @@ struct af_alg_iv {
 #define ALG_SET_OP			3
 #define ALG_SET_AEAD_ASSOCLEN		4
 #define ALG_SET_AEAD_AUTHSIZE		5
+#define ALG_SET_PUBKEY			6
 
 /* Operations */
 #define ALG_OP_DECRYPT			0
 #define ALG_OP_ENCRYPT			1
+#define ALG_OP_SIGN			2
+#define ALG_OP_VERIFY			3
 
 #endif	/* _LINUX_IF_ALG_H */

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v8 2/6] crypto: AF_ALG -- add setpubkey setsockopt call
  2016-06-23 22:55 [PATCH v8 0/6] crypto: algif - add akcipher Tadeusz Struk
@ 2016-06-23 22:55 ` Tadeusz Struk
  2016-06-23 22:55 ` [PATCH v8 3/6] crypto: AF_ALG -- add asymmetric cipher interface Tadeusz Struk
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 20+ messages in thread
From: Tadeusz Struk @ 2016-06-23 22:55 UTC (permalink / raw)
  To: dhowells
  Cc: herbert, tadeusz.struk, smueller, linux-api, marcel,
	mathew.j.martineau, linux-kernel, keyrings, linux-crypto, dwmw2,
	davem

From: Stephan Mueller <smueller@chronox.de>

For supporting asymmetric ciphers, user space must be able to set the
public key. The patch adds a new setsockopt call for setting the public
key.

Signed-off-by: Stephan Mueller <smueller@chronox.de>
Signed-off-by: Tadeusz Struk <tadeusz.struk@intel.com>
---
 crypto/af_alg.c         |   18 +++++++++++++-----
 include/crypto/if_alg.h |    1 +
 2 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/crypto/af_alg.c b/crypto/af_alg.c
index f5e18c2..24dc082 100644
--- a/crypto/af_alg.c
+++ b/crypto/af_alg.c
@@ -202,13 +202,17 @@ unlock:
 }
 
 static int alg_setkey(struct sock *sk, char __user *ukey,
-		      unsigned int keylen)
+		      unsigned int keylen,
+		      int (*setkey)(void *private, const u8 *key,
+				    unsigned int keylen))
 {
 	struct alg_sock *ask = alg_sk(sk);
-	const struct af_alg_type *type = ask->type;
 	u8 *key;
 	int err;
 
+	if (!setkey)
+		return -ENOPROTOOPT;
+
 	key = sock_kmalloc(sk, keylen, GFP_KERNEL);
 	if (!key)
 		return -ENOMEM;
@@ -217,7 +221,7 @@ static int alg_setkey(struct sock *sk, char __user *ukey,
 	if (copy_from_user(key, ukey, keylen))
 		goto out;
 
-	err = type->setkey(ask->private, key, keylen);
+	err = setkey(ask->private, key, keylen);
 
 out:
 	sock_kzfree_s(sk, key, keylen);
@@ -247,10 +251,14 @@ static int alg_setsockopt(struct socket *sock, int level, int optname,
 	case ALG_SET_KEY:
 		if (sock->state == SS_CONNECTED)
 			goto unlock;
-		if (!type->setkey)
+
+		err = alg_setkey(sk, optval, optlen, type->setkey);
+		break;
+	case ALG_SET_PUBKEY:
+		if (sock->state == SS_CONNECTED)
 			goto unlock;
 
-		err = alg_setkey(sk, optval, optlen);
+		err = alg_setkey(sk, optval, optlen, type->setpubkey);
 		break;
 	case ALG_SET_AEAD_AUTHSIZE:
 		if (sock->state == SS_CONNECTED)
diff --git a/include/crypto/if_alg.h b/include/crypto/if_alg.h
index a2bfd78..6c3e6e7 100644
--- a/include/crypto/if_alg.h
+++ b/include/crypto/if_alg.h
@@ -52,6 +52,7 @@ struct af_alg_type {
 	void *(*bind)(const char *name, u32 type, u32 mask);
 	void (*release)(void *private);
 	int (*setkey)(void *private, const u8 *key, unsigned int keylen);
+	int (*setpubkey)(void *private, const u8 *key, unsigned int keylen);
 	int (*accept)(void *private, struct sock *sk);
 	int (*accept_nokey)(void *private, struct sock *sk);
 	int (*setauthsize)(void *private, unsigned int authsize);

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v8 3/6] crypto: AF_ALG -- add asymmetric cipher interface
  2016-06-23 22:55 [PATCH v8 0/6] crypto: algif - add akcipher Tadeusz Struk
  2016-06-23 22:55 ` [PATCH v8 2/6] crypto: AF_ALG -- add setpubkey setsockopt call Tadeusz Struk
@ 2016-06-23 22:55 ` Tadeusz Struk
  2016-06-23 22:55 ` [PATCH v8 4/6] crypto: algif_akcipher - enable compilation Tadeusz Struk
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 20+ messages in thread
From: Tadeusz Struk @ 2016-06-23 22:55 UTC (permalink / raw)
  To: dhowells
  Cc: herbert, tadeusz.struk, smueller, linux-api, marcel,
	mathew.j.martineau, linux-kernel, keyrings, linux-crypto, dwmw2,
	davem

From: Stephan Mueller <smueller@chronox.de>

This patch adds the user space interface for asymmetric ciphers. The
interface allows the use of sendmsg as well as vmsplice to provide data.

This version has been rebased on top of 4.7 and a few chackpatch issues
have been fixed. This version also removes the constrain on the output
buffer size.

Signed-off-by: Stephan Mueller <smueller@chronox.de>
Signed-off-by: Tadeusz Struk <tadeusz.struk@intel.com>
---
 crypto/algif_akcipher.c |  531 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 531 insertions(+)
 create mode 100644 crypto/algif_akcipher.c

diff --git a/crypto/algif_akcipher.c b/crypto/algif_akcipher.c
new file mode 100644
index 0000000..8dd6354
--- /dev/null
+++ b/crypto/algif_akcipher.c
@@ -0,0 +1,531 @@
+/*
+ * algif_akcipher: User-space interface for asymmetric cipher algorithms
+ *
+ * Copyright (C) 2015, Stephan Mueller <smueller@chronox.de>
+ *
+ * This file provides the user-space API for asymmetric ciphers.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+
+#include <crypto/akcipher.h>
+#include <crypto/scatterwalk.h>
+#include <crypto/if_alg.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/net.h>
+#include <net/sock.h>
+
+struct akcipher_sg_list {
+	unsigned int cur;
+	struct scatterlist sg[ALG_MAX_PAGES];
+};
+
+struct akcipher_ctx {
+	struct akcipher_sg_list tsgl;
+	struct af_alg_sgl rsgl[ALG_MAX_PAGES];
+
+	struct af_alg_completion completion;
+
+	unsigned long used;
+
+	unsigned int len;
+	bool more;
+	bool merge;
+	int op;
+
+	struct akcipher_request req;
+};
+
+static inline int akcipher_sndbuf(struct sock *sk)
+{
+	struct alg_sock *ask = alg_sk(sk);
+	struct akcipher_ctx *ctx = ask->private;
+
+	return max_t(int, max_t(int, sk->sk_sndbuf & PAGE_MASK, PAGE_SIZE) -
+			  ctx->used, 0);
+}
+
+static inline bool akcipher_writable(struct sock *sk)
+{
+	return akcipher_sndbuf(sk) >= PAGE_SIZE;
+}
+
+static void akcipher_put_sgl(struct sock *sk)
+{
+	struct alg_sock *ask = alg_sk(sk);
+	struct akcipher_ctx *ctx = ask->private;
+	struct akcipher_sg_list *sgl = &ctx->tsgl;
+	struct scatterlist *sg = sgl->sg;
+	unsigned int i;
+
+	for (i = 0; i < sgl->cur; i++) {
+		if (!sg_page(sg + i))
+			continue;
+
+		put_page(sg_page(sg + i));
+		sg_assign_page(sg + i, NULL);
+	}
+	sg_init_table(sg, ALG_MAX_PAGES);
+	sgl->cur = 0;
+	ctx->used = 0;
+	ctx->more = 0;
+	ctx->merge = 0;
+}
+
+static void akcipher_wmem_wakeup(struct sock *sk)
+{
+	struct socket_wq *wq;
+
+	if (!akcipher_writable(sk))
+		return;
+
+	rcu_read_lock();
+	wq = rcu_dereference(sk->sk_wq);
+	if (wq_has_sleeper(&wq->wait))
+		wake_up_interruptible_sync_poll(&wq->wait, POLLIN |
+							   POLLRDNORM |
+							   POLLRDBAND);
+	sk_wake_async(sk, SOCK_WAKE_WAITD, POLL_IN);
+	rcu_read_unlock();
+}
+
+static int akcipher_wait_for_data(struct sock *sk, unsigned int flags)
+{
+	struct alg_sock *ask = alg_sk(sk);
+	struct akcipher_ctx *ctx = ask->private;
+	long timeout;
+	DEFINE_WAIT(wait);
+	int err = -ERESTARTSYS;
+
+	if (flags & MSG_DONTWAIT)
+		return -EAGAIN;
+
+	set_bit(SOCKWQ_ASYNC_WAITDATA, &sk->sk_socket->flags);
+
+	for (;;) {
+		if (signal_pending(current))
+			break;
+		prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
+		timeout = MAX_SCHEDULE_TIMEOUT;
+		if (sk_wait_event(sk, &timeout, !ctx->more)) {
+			err = 0;
+			break;
+		}
+	}
+	finish_wait(sk_sleep(sk), &wait);
+
+	clear_bit(SOCKWQ_ASYNC_WAITDATA, &sk->sk_socket->flags);
+
+	return err;
+}
+
+static void akcipher_data_wakeup(struct sock *sk)
+{
+	struct alg_sock *ask = alg_sk(sk);
+	struct akcipher_ctx *ctx = ask->private;
+	struct socket_wq *wq;
+
+	if (ctx->more)
+		return;
+	if (!ctx->used)
+		return;
+
+	rcu_read_lock();
+	wq = rcu_dereference(sk->sk_wq);
+	if (wq_has_sleeper(&wq->wait))
+		wake_up_interruptible_sync_poll(&wq->wait, POLLOUT |
+							   POLLRDNORM |
+							   POLLRDBAND);
+	sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT);
+	rcu_read_unlock();
+}
+
+static int akcipher_sendmsg(struct socket *sock, struct msghdr *msg,
+			    size_t size)
+{
+	struct sock *sk = sock->sk;
+	struct alg_sock *ask = alg_sk(sk);
+	struct akcipher_ctx *ctx = ask->private;
+	struct akcipher_sg_list *sgl = &ctx->tsgl;
+	struct af_alg_control con = {};
+	long copied = 0;
+	int op = 0;
+	bool init = 0;
+	int err = -EINVAL;
+
+	if (msg->msg_controllen) {
+		err = af_alg_cmsg_send(msg, &con);
+		if (err)
+			return err;
+
+		init = 1;
+		switch (con.op) {
+		case ALG_OP_VERIFY:
+		case ALG_OP_SIGN:
+		case ALG_OP_ENCRYPT:
+		case ALG_OP_DECRYPT:
+			op = con.op;
+			break;
+		default:
+			return -EINVAL;
+		}
+	}
+
+	lock_sock(sk);
+	if (!ctx->more && ctx->used)
+		goto unlock;
+
+	if (init)
+		ctx->op = op;
+
+	while (size) {
+		unsigned long len = size;
+		struct scatterlist *sg = NULL;
+
+		/* use the existing memory in an allocated page */
+		if (ctx->merge) {
+			sg = sgl->sg + sgl->cur - 1;
+			len = min_t(unsigned long, len,
+				    PAGE_SIZE - sg->offset - sg->length);
+			err = memcpy_from_msg(page_address(sg_page(sg)) +
+					      sg->offset + sg->length,
+					      msg, len);
+			if (err)
+				goto unlock;
+
+			sg->length += len;
+			ctx->merge = (sg->offset + sg->length) &
+				     (PAGE_SIZE - 1);
+
+			ctx->used += len;
+			copied += len;
+			size -= len;
+			continue;
+		}
+
+		if (!akcipher_writable(sk)) {
+			/* user space sent too much data */
+			akcipher_put_sgl(sk);
+			err = -EMSGSIZE;
+			goto unlock;
+		}
+
+		/* allocate a new page */
+		len = min_t(unsigned long, size, akcipher_sndbuf(sk));
+		while (len) {
+			int plen = 0;
+
+			if (sgl->cur >= ALG_MAX_PAGES) {
+				akcipher_put_sgl(sk);
+				err = -E2BIG;
+				goto unlock;
+			}
+
+			sg = sgl->sg + sgl->cur;
+			plen = min_t(int, len, PAGE_SIZE);
+
+			sg_assign_page(sg, alloc_page(GFP_KERNEL));
+			if (!sg_page(sg)) {
+				err = -ENOMEM;
+				goto unlock;
+			}
+
+			err = memcpy_from_msg(page_address(sg_page(sg)),
+					      msg, plen);
+			if (err) {
+				__free_page(sg_page(sg));
+				sg_assign_page(sg, NULL);
+				goto unlock;
+			}
+
+			sg->offset = 0;
+			sg->length = plen;
+			len -= plen;
+			ctx->used += plen;
+			copied += plen;
+			sgl->cur++;
+			size -= plen;
+			ctx->merge = plen & (PAGE_SIZE - 1);
+		}
+	}
+
+	err = 0;
+
+	ctx->more = msg->msg_flags & MSG_MORE;
+
+unlock:
+	akcipher_data_wakeup(sk);
+	release_sock(sk);
+
+	return err ?: copied;
+}
+
+static ssize_t akcipher_sendpage(struct socket *sock, struct page *page,
+				 int offset, size_t size, int flags)
+{
+	struct sock *sk = sock->sk;
+	struct alg_sock *ask = alg_sk(sk);
+	struct akcipher_ctx *ctx = ask->private;
+	struct akcipher_sg_list *sgl = &ctx->tsgl;
+	int err = 0;
+
+	if (flags & MSG_SENDPAGE_NOTLAST)
+		flags |= MSG_MORE;
+
+	if (sgl->cur >= ALG_MAX_PAGES)
+		return -E2BIG;
+
+	lock_sock(sk);
+	if (!ctx->more && ctx->used)
+		goto unlock;
+
+	if (!size)
+		goto done;
+
+	if (!akcipher_writable(sk)) {
+		/* user space sent too much data */
+		akcipher_put_sgl(sk);
+		err = -EMSGSIZE;
+		goto unlock;
+	}
+
+	ctx->merge = 0;
+
+	get_page(page);
+	sg_set_page(sgl->sg + sgl->cur, page, size, offset);
+	sgl->cur++;
+	ctx->used += size;
+
+done:
+	ctx->more = flags & MSG_MORE;
+unlock:
+	akcipher_data_wakeup(sk);
+	release_sock(sk);
+
+	return err ? err : size;
+}
+
+static int akcipher_recvmsg(struct socket *sock, struct msghdr *msg,
+			    size_t ignored, int flags)
+{
+	struct sock *sk = sock->sk;
+	struct alg_sock *ask = alg_sk(sk);
+	struct akcipher_ctx *ctx = ask->private;
+	struct akcipher_sg_list *sgl = &ctx->tsgl;
+	unsigned int i = 0;
+	int err;
+	unsigned long used = 0;
+	size_t usedpages = 0;
+	unsigned int cnt = 0;
+
+	/* Limit number of IOV blocks to be accessed below */
+	if (msg->msg_iter.nr_segs > ALG_MAX_PAGES)
+		return -ENOMSG;
+
+	lock_sock(sk);
+
+	if (ctx->more) {
+		err = akcipher_wait_for_data(sk, flags);
+		if (err)
+			goto unlock;
+	}
+
+	used = ctx->used;
+
+	/* convert iovecs of output buffers into scatterlists */
+	while (iov_iter_count(&msg->msg_iter)) {
+		/* make one iovec available as scatterlist */
+		err = af_alg_make_sg(&ctx->rsgl[cnt], &msg->msg_iter,
+				     iov_iter_count(&msg->msg_iter));
+		if (err < 0)
+			goto unlock;
+		usedpages += err;
+		/* chain the new scatterlist with previous one */
+		if (cnt)
+			af_alg_link_sg(&ctx->rsgl[cnt - 1], &ctx->rsgl[cnt]);
+
+		iov_iter_advance(&msg->msg_iter, err);
+		cnt++;
+	}
+
+	sg_mark_end(sgl->sg + sgl->cur - 1);
+
+	akcipher_request_set_crypt(&ctx->req, sgl->sg, ctx->rsgl[0].sg, used,
+				   usedpages);
+	switch (ctx->op) {
+	case ALG_OP_VERIFY:
+		err = crypto_akcipher_verify(&ctx->req);
+		break;
+	case ALG_OP_SIGN:
+		err = crypto_akcipher_sign(&ctx->req);
+		break;
+	case ALG_OP_ENCRYPT:
+		err = crypto_akcipher_encrypt(&ctx->req);
+		break;
+	case ALG_OP_DECRYPT:
+		err = crypto_akcipher_decrypt(&ctx->req);
+		break;
+	default:
+		err = -EFAULT;
+		goto unlock;
+	}
+
+	err = af_alg_wait_for_completion(err, &ctx->completion);
+
+	if (err) {
+		/* EBADMSG implies a valid cipher operation took place */
+		if (err == -EBADMSG)
+			akcipher_put_sgl(sk);
+		goto unlock;
+	}
+
+	akcipher_put_sgl(sk);
+
+unlock:
+	for (i = 0; i < cnt; i++)
+		af_alg_free_sg(&ctx->rsgl[i]);
+
+	akcipher_wmem_wakeup(sk);
+	release_sock(sk);
+
+	return err ? err : ctx->req.dst_len;
+}
+
+static unsigned int akcipher_poll(struct file *file, struct socket *sock,
+				  poll_table *wait)
+{
+	struct sock *sk = sock->sk;
+	struct alg_sock *ask = alg_sk(sk);
+	struct akcipher_ctx *ctx = ask->private;
+	unsigned int mask = 0;
+
+	sock_poll_wait(file, sk_sleep(sk), wait);
+
+	if (!ctx->more)
+		mask |= POLLIN | POLLRDNORM;
+
+	if (akcipher_writable(sk))
+		mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
+
+	return mask;
+}
+
+static struct proto_ops algif_akcipher_ops = {
+	.family		=	PF_ALG,
+
+	.connect	=	sock_no_connect,
+	.socketpair	=	sock_no_socketpair,
+	.getname	=	sock_no_getname,
+	.ioctl		=	sock_no_ioctl,
+	.listen		=	sock_no_listen,
+	.shutdown	=	sock_no_shutdown,
+	.getsockopt	=	sock_no_getsockopt,
+	.mmap		=	sock_no_mmap,
+	.bind		=	sock_no_bind,
+	.accept		=	sock_no_accept,
+	.setsockopt	=	sock_no_setsockopt,
+
+	.release	=	af_alg_release,
+	.sendmsg	=	akcipher_sendmsg,
+	.sendpage	=	akcipher_sendpage,
+	.recvmsg	=	akcipher_recvmsg,
+	.poll		=	akcipher_poll,
+};
+
+static void *akcipher_bind(const char *name, u32 type, u32 mask)
+{
+	return crypto_alloc_akcipher(name, type, mask);
+}
+
+static void akcipher_release(void *private)
+{
+	crypto_free_akcipher(private);
+}
+
+static int akcipher_setprivkey(void *private, const u8 *key,
+			       unsigned int keylen)
+{
+	return crypto_akcipher_set_priv_key(private, key, keylen);
+}
+
+static int akcipher_setpubkey(void *private, const u8 *key, unsigned int keylen)
+{
+	return crypto_akcipher_set_pub_key(private, key, keylen);
+}
+
+static void akcipher_sock_destruct(struct sock *sk)
+{
+	struct alg_sock *ask = alg_sk(sk);
+	struct akcipher_ctx *ctx = ask->private;
+
+	akcipher_put_sgl(sk);
+	sock_kfree_s(sk, ctx, ctx->len);
+	af_alg_release_parent(sk);
+}
+
+static int akcipher_accept_parent(void *private, struct sock *sk)
+{
+	struct akcipher_ctx *ctx;
+	struct alg_sock *ask = alg_sk(sk);
+	unsigned int len = sizeof(*ctx) + crypto_akcipher_reqsize(private);
+
+	ctx = sock_kmalloc(sk, len, GFP_KERNEL);
+	if (!ctx)
+		return -ENOMEM;
+	memset(ctx, 0, len);
+
+	ctx->len = len;
+	ctx->used = 0;
+	ctx->more = 0;
+	ctx->merge = 0;
+	ctx->op = 0;
+	ctx->tsgl.cur = 0;
+	af_alg_init_completion(&ctx->completion);
+	sg_init_table(ctx->tsgl.sg, ALG_MAX_PAGES);
+
+	ask->private = ctx;
+
+	akcipher_request_set_tfm(&ctx->req, private);
+	akcipher_request_set_callback(&ctx->req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+				      af_alg_complete, &ctx->completion);
+
+	sk->sk_destruct = akcipher_sock_destruct;
+
+	return 0;
+}
+
+static const struct af_alg_type algif_type_akcipher = {
+	.bind		=	akcipher_bind,
+	.release	=	akcipher_release,
+	.setkey		=	akcipher_setprivkey,
+	.setpubkey	=	akcipher_setpubkey,
+	.accept		=	akcipher_accept_parent,
+	.ops		=	&algif_akcipher_ops,
+	.name		=	"akcipher",
+	.owner		=	THIS_MODULE
+};
+
+static int __init algif_akcipher_init(void)
+{
+	return af_alg_register_type(&algif_type_akcipher);
+}
+
+static void __exit algif_akcipher_exit(void)
+{
+	int err = af_alg_unregister_type(&algif_type_akcipher);
+
+	WARN_ON(err);
+}
+
+module_init(algif_akcipher_init);
+module_exit(algif_akcipher_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>");
+MODULE_DESCRIPTION("Asymmetric kernel crypto API user space interface");

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v8 4/6] crypto: algif_akcipher - enable compilation
  2016-06-23 22:55 [PATCH v8 0/6] crypto: algif - add akcipher Tadeusz Struk
  2016-06-23 22:55 ` [PATCH v8 2/6] crypto: AF_ALG -- add setpubkey setsockopt call Tadeusz Struk
  2016-06-23 22:55 ` [PATCH v8 3/6] crypto: AF_ALG -- add asymmetric cipher interface Tadeusz Struk
@ 2016-06-23 22:55 ` Tadeusz Struk
       [not found] ` <146672252642.23101.15972023870303797249.stgit-mEAvsCHCuLl9qtVHHdszJa2pdiUAq4bhAL8bYrjMMd8@public.gmane.org>
  2016-06-23 22:55 ` [PATCH v8 6/6] crypto: AF_ALG - add support for key_id Tadeusz Struk
  4 siblings, 0 replies; 20+ messages in thread
From: Tadeusz Struk @ 2016-06-23 22:55 UTC (permalink / raw)
  To: dhowells
  Cc: herbert, tadeusz.struk, smueller, linux-api, marcel,
	mathew.j.martineau, linux-kernel, keyrings, linux-crypto, dwmw2,
	davem

From: Stephan Mueller <smueller@chronox.de>

Add the Makefile and Kconfig updates to allow algif_akcipher to be
compiled.

Signed-off-by: Stephan Mueller <smueller@chronox.de>
Signed-off-by: Tadeusz Struk <tadeusz.struk@intel.com>
---
 crypto/Kconfig  |    9 +++++++++
 crypto/Makefile |    1 +
 2 files changed, 10 insertions(+)

diff --git a/crypto/Kconfig b/crypto/Kconfig
index 1d33beb..3c6113e 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -1627,6 +1627,15 @@ config CRYPTO_USER_API_AEAD
 	  This option enables the user-spaces interface for AEAD
 	  cipher algorithms.
 
+config CRYPTO_USER_API_AKCIPHER
+	tristate "User-space interface for asymmetric key cipher algorithms"
+	depends on NET
+	select CRYPTO_AKCIPHER2
+	select CRYPTO_USER_API
+	help
+	  This option enables the user-spaces interface for asymmetric
+	  key cipher algorithms.
+
 config CRYPTO_HASH_INFO
 	bool
 
diff --git a/crypto/Makefile b/crypto/Makefile
index 4f4ef7e..c51ac16 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -121,6 +121,7 @@ obj-$(CONFIG_CRYPTO_USER_API_HASH) += algif_hash.o
 obj-$(CONFIG_CRYPTO_USER_API_SKCIPHER) += algif_skcipher.o
 obj-$(CONFIG_CRYPTO_USER_API_RNG) += algif_rng.o
 obj-$(CONFIG_CRYPTO_USER_API_AEAD) += algif_aead.o
+obj-$(CONFIG_CRYPTO_USER_API_AKCIPHER) += algif_akcipher.o
 
 #
 # generic algorithms and the async_tx api

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v8 5/6] crypto: algif_akcipher - add ops_nokey
  2016-06-23 22:55 [PATCH v8 0/6] crypto: algif - add akcipher Tadeusz Struk
@ 2016-06-23 22:55     ` Tadeusz Struk
  2016-06-23 22:55 ` [PATCH v8 3/6] crypto: AF_ALG -- add asymmetric cipher interface Tadeusz Struk
                       ` (3 subsequent siblings)
  4 siblings, 0 replies; 20+ messages in thread
From: Tadeusz Struk @ 2016-06-23 22:55 UTC (permalink / raw)
  To: dhowells-H+wXaHxf7aLQT0dZR+AlfA
  Cc: herbert-lOAM2aK0SrRLBo1qDEOMRrpzq4S04n8Q,
	tadeusz.struk-ral2JQCrhuEAvxtiuMwx3w,
	smueller-T9tCv8IpfcWELgA04lAiVw,
	linux-api-u79uwXL29TY76Z2rM5mHXA, marcel-kz+m5ild9QBg9hUCZPvPmw,
	mathew.j.martineau-VuQAYsv1563Yd54FQh9/CA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	keyrings-u79uwXL29TY76Z2rM5mHXA,
	linux-crypto-u79uwXL29TY76Z2rM5mHXA,
	dwmw2-wEGCiKHe2LqWVfeAwA7xHQ, davem-fT/PcQaiUtIeIZ0/mPfg9Q

Similar to algif_skcipher and algif_hash, algif_akcipher needs
to prevent user space from using the interface in an improper way.
This patch adds nokey ops handlers, which do just that.

Signed-off-by: Tadeusz Struk <tadeusz.struk-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---
 crypto/algif_akcipher.c |  159 +++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 152 insertions(+), 7 deletions(-)

diff --git a/crypto/algif_akcipher.c b/crypto/algif_akcipher.c
index 8dd6354..2b8d37e 100644
--- a/crypto/algif_akcipher.c
+++ b/crypto/algif_akcipher.c
@@ -27,6 +27,11 @@ struct akcipher_sg_list {
 	struct scatterlist sg[ALG_MAX_PAGES];
 };
 
+struct akcipher_tfm {
+	struct crypto_akcipher *akcipher;
+	bool has_key;
+};
+
 struct akcipher_ctx {
 	struct akcipher_sg_list tsgl;
 	struct af_alg_sgl rsgl[ALG_MAX_PAGES];
@@ -439,25 +444,151 @@ static struct proto_ops algif_akcipher_ops = {
 	.poll		=	akcipher_poll,
 };
 
+static int akcipher_check_key(struct socket *sock)
+{
+	int err = 0;
+	struct sock *psk;
+	struct alg_sock *pask;
+	struct akcipher_tfm *tfm;
+	struct sock *sk = sock->sk;
+	struct alg_sock *ask = alg_sk(sk);
+
+	lock_sock(sk);
+	if (ask->refcnt)
+		goto unlock_child;
+
+	psk = ask->parent;
+	pask = alg_sk(ask->parent);
+	tfm = pask->private;
+
+	err = -ENOKEY;
+	lock_sock_nested(psk, SINGLE_DEPTH_NESTING);
+	if (!tfm->has_key)
+		goto unlock;
+
+	if (!pask->refcnt++)
+		sock_hold(psk);
+
+	ask->refcnt = 1;
+	sock_put(psk);
+
+	err = 0;
+
+unlock:
+	release_sock(psk);
+unlock_child:
+	release_sock(sk);
+
+	return err;
+}
+
+static int akcipher_sendmsg_nokey(struct socket *sock, struct msghdr *msg,
+				  size_t size)
+{
+	int err;
+
+	err = akcipher_check_key(sock);
+	if (err)
+		return err;
+
+	return akcipher_sendmsg(sock, msg, size);
+}
+
+static ssize_t akcipher_sendpage_nokey(struct socket *sock, struct page *page,
+				       int offset, size_t size, int flags)
+{
+	int err;
+
+	err = akcipher_check_key(sock);
+	if (err)
+		return err;
+
+	return akcipher_sendpage(sock, page, offset, size, flags);
+}
+
+static int akcipher_recvmsg_nokey(struct socket *sock, struct msghdr *msg,
+				  size_t ignored, int flags)
+{
+	int err;
+
+	err = akcipher_check_key(sock);
+	if (err)
+		return err;
+
+	return akcipher_recvmsg(sock, msg, ignored, flags);
+}
+
+static struct proto_ops algif_akcipher_ops_nokey = {
+	.family		=	PF_ALG,
+
+	.connect	=	sock_no_connect,
+	.socketpair	=	sock_no_socketpair,
+	.getname	=	sock_no_getname,
+	.ioctl		=	sock_no_ioctl,
+	.listen		=	sock_no_listen,
+	.shutdown	=	sock_no_shutdown,
+	.getsockopt	=	sock_no_getsockopt,
+	.mmap		=	sock_no_mmap,
+	.bind		=	sock_no_bind,
+	.accept		=	sock_no_accept,
+	.setsockopt	=	sock_no_setsockopt,
+
+	.release	=	af_alg_release,
+	.sendmsg	=	akcipher_sendmsg_nokey,
+	.sendpage	=	akcipher_sendpage_nokey,
+	.recvmsg	=	akcipher_recvmsg_nokey,
+	.poll		=	akcipher_poll,
+};
+
 static void *akcipher_bind(const char *name, u32 type, u32 mask)
 {
-	return crypto_alloc_akcipher(name, type, mask);
+	struct akcipher_tfm *tfm;
+	struct crypto_akcipher *akcipher;
+
+	tfm = kzalloc(sizeof(*tfm), GFP_KERNEL);
+	if (!tfm)
+		return ERR_PTR(-ENOMEM);
+
+	akcipher = crypto_alloc_akcipher(name, type, mask);
+	if (IS_ERR(akcipher)) {
+		kfree(tfm);
+		return ERR_CAST(akcipher);
+	}
+
+	tfm->akcipher = akcipher;
+	return tfm;
 }
 
 static void akcipher_release(void *private)
 {
-	crypto_free_akcipher(private);
+	struct akcipher_tfm *tfm = private;
+	struct crypto_akcipher *akcipher = tfm->akcipher;
+
+	crypto_free_akcipher(akcipher);
+	kfree(tfm);
 }
 
 static int akcipher_setprivkey(void *private, const u8 *key,
 			       unsigned int keylen)
 {
-	return crypto_akcipher_set_priv_key(private, key, keylen);
+	struct akcipher_tfm *tfm = private;
+	struct crypto_akcipher *akcipher = tfm->akcipher;
+	int err;
+
+	err = crypto_akcipher_set_priv_key(akcipher, key, keylen);
+	tfm->has_key = !err;
+	return err;
 }
 
 static int akcipher_setpubkey(void *private, const u8 *key, unsigned int keylen)
 {
-	return crypto_akcipher_set_pub_key(private, key, keylen);
+	struct akcipher_tfm *tfm = private;
+	struct crypto_akcipher *akcipher = tfm->akcipher;
+	int err;
+
+	err = crypto_akcipher_set_pub_key(akcipher, key, keylen);
+	tfm->has_key = !err;
+	return err;
 }
 
 static void akcipher_sock_destruct(struct sock *sk)
@@ -470,11 +601,13 @@ static void akcipher_sock_destruct(struct sock *sk)
 	af_alg_release_parent(sk);
 }
 
-static int akcipher_accept_parent(void *private, struct sock *sk)
+static int akcipher_accept_parent_nokey(void *private, struct sock *sk)
 {
 	struct akcipher_ctx *ctx;
 	struct alg_sock *ask = alg_sk(sk);
-	unsigned int len = sizeof(*ctx) + crypto_akcipher_reqsize(private);
+	struct akcipher_tfm *tfm = private;
+	struct crypto_akcipher *akcipher = tfm->akcipher;
+	unsigned int len = sizeof(*ctx) + crypto_akcipher_reqsize(akcipher);
 
 	ctx = sock_kmalloc(sk, len, GFP_KERNEL);
 	if (!ctx)
@@ -492,7 +625,7 @@ static int akcipher_accept_parent(void *private, struct sock *sk)
 
 	ask->private = ctx;
 
-	akcipher_request_set_tfm(&ctx->req, private);
+	akcipher_request_set_tfm(&ctx->req, akcipher);
 	akcipher_request_set_callback(&ctx->req, CRYPTO_TFM_REQ_MAY_BACKLOG,
 				      af_alg_complete, &ctx->completion);
 
@@ -501,13 +634,25 @@ static int akcipher_accept_parent(void *private, struct sock *sk)
 	return 0;
 }
 
+static int akcipher_accept_parent(void *private, struct sock *sk)
+{
+	struct akcipher_tfm *tfm = private;
+
+	if (!tfm->has_key)
+		return -ENOKEY;
+
+	return akcipher_accept_parent_nokey(private, sk);
+}
+
 static const struct af_alg_type algif_type_akcipher = {
 	.bind		=	akcipher_bind,
 	.release	=	akcipher_release,
 	.setkey		=	akcipher_setprivkey,
 	.setpubkey	=	akcipher_setpubkey,
 	.accept		=	akcipher_accept_parent,
+	.accept_nokey	=	akcipher_accept_parent_nokey,
 	.ops		=	&algif_akcipher_ops,
+	.ops_nokey	=	&algif_akcipher_ops_nokey,
 	.name		=	"akcipher",
 	.owner		=	THIS_MODULE
 };

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v8 5/6] crypto: algif_akcipher - add ops_nokey
@ 2016-06-23 22:55     ` Tadeusz Struk
  0 siblings, 0 replies; 20+ messages in thread
From: Tadeusz Struk @ 2016-06-23 22:55 UTC (permalink / raw)
  To: dhowells
  Cc: herbert, tadeusz.struk, smueller, linux-api, marcel,
	mathew.j.martineau, linux-kernel, keyrings, linux-crypto, dwmw2,
	davem

Similar to algif_skcipher and algif_hash, algif_akcipher needs
to prevent user space from using the interface in an improper way.
This patch adds nokey ops handlers, which do just that.

Signed-off-by: Tadeusz Struk <tadeusz.struk@intel.com>
---
 crypto/algif_akcipher.c |  159 +++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 152 insertions(+), 7 deletions(-)

diff --git a/crypto/algif_akcipher.c b/crypto/algif_akcipher.c
index 8dd6354..2b8d37e 100644
--- a/crypto/algif_akcipher.c
+++ b/crypto/algif_akcipher.c
@@ -27,6 +27,11 @@ struct akcipher_sg_list {
 	struct scatterlist sg[ALG_MAX_PAGES];
 };
 
+struct akcipher_tfm {
+	struct crypto_akcipher *akcipher;
+	bool has_key;
+};
+
 struct akcipher_ctx {
 	struct akcipher_sg_list tsgl;
 	struct af_alg_sgl rsgl[ALG_MAX_PAGES];
@@ -439,25 +444,151 @@ static struct proto_ops algif_akcipher_ops = {
 	.poll		=	akcipher_poll,
 };
 
+static int akcipher_check_key(struct socket *sock)
+{
+	int err = 0;
+	struct sock *psk;
+	struct alg_sock *pask;
+	struct akcipher_tfm *tfm;
+	struct sock *sk = sock->sk;
+	struct alg_sock *ask = alg_sk(sk);
+
+	lock_sock(sk);
+	if (ask->refcnt)
+		goto unlock_child;
+
+	psk = ask->parent;
+	pask = alg_sk(ask->parent);
+	tfm = pask->private;
+
+	err = -ENOKEY;
+	lock_sock_nested(psk, SINGLE_DEPTH_NESTING);
+	if (!tfm->has_key)
+		goto unlock;
+
+	if (!pask->refcnt++)
+		sock_hold(psk);
+
+	ask->refcnt = 1;
+	sock_put(psk);
+
+	err = 0;
+
+unlock:
+	release_sock(psk);
+unlock_child:
+	release_sock(sk);
+
+	return err;
+}
+
+static int akcipher_sendmsg_nokey(struct socket *sock, struct msghdr *msg,
+				  size_t size)
+{
+	int err;
+
+	err = akcipher_check_key(sock);
+	if (err)
+		return err;
+
+	return akcipher_sendmsg(sock, msg, size);
+}
+
+static ssize_t akcipher_sendpage_nokey(struct socket *sock, struct page *page,
+				       int offset, size_t size, int flags)
+{
+	int err;
+
+	err = akcipher_check_key(sock);
+	if (err)
+		return err;
+
+	return akcipher_sendpage(sock, page, offset, size, flags);
+}
+
+static int akcipher_recvmsg_nokey(struct socket *sock, struct msghdr *msg,
+				  size_t ignored, int flags)
+{
+	int err;
+
+	err = akcipher_check_key(sock);
+	if (err)
+		return err;
+
+	return akcipher_recvmsg(sock, msg, ignored, flags);
+}
+
+static struct proto_ops algif_akcipher_ops_nokey = {
+	.family		=	PF_ALG,
+
+	.connect	=	sock_no_connect,
+	.socketpair	=	sock_no_socketpair,
+	.getname	=	sock_no_getname,
+	.ioctl		=	sock_no_ioctl,
+	.listen		=	sock_no_listen,
+	.shutdown	=	sock_no_shutdown,
+	.getsockopt	=	sock_no_getsockopt,
+	.mmap		=	sock_no_mmap,
+	.bind		=	sock_no_bind,
+	.accept		=	sock_no_accept,
+	.setsockopt	=	sock_no_setsockopt,
+
+	.release	=	af_alg_release,
+	.sendmsg	=	akcipher_sendmsg_nokey,
+	.sendpage	=	akcipher_sendpage_nokey,
+	.recvmsg	=	akcipher_recvmsg_nokey,
+	.poll		=	akcipher_poll,
+};
+
 static void *akcipher_bind(const char *name, u32 type, u32 mask)
 {
-	return crypto_alloc_akcipher(name, type, mask);
+	struct akcipher_tfm *tfm;
+	struct crypto_akcipher *akcipher;
+
+	tfm = kzalloc(sizeof(*tfm), GFP_KERNEL);
+	if (!tfm)
+		return ERR_PTR(-ENOMEM);
+
+	akcipher = crypto_alloc_akcipher(name, type, mask);
+	if (IS_ERR(akcipher)) {
+		kfree(tfm);
+		return ERR_CAST(akcipher);
+	}
+
+	tfm->akcipher = akcipher;
+	return tfm;
 }
 
 static void akcipher_release(void *private)
 {
-	crypto_free_akcipher(private);
+	struct akcipher_tfm *tfm = private;
+	struct crypto_akcipher *akcipher = tfm->akcipher;
+
+	crypto_free_akcipher(akcipher);
+	kfree(tfm);
 }
 
 static int akcipher_setprivkey(void *private, const u8 *key,
 			       unsigned int keylen)
 {
-	return crypto_akcipher_set_priv_key(private, key, keylen);
+	struct akcipher_tfm *tfm = private;
+	struct crypto_akcipher *akcipher = tfm->akcipher;
+	int err;
+
+	err = crypto_akcipher_set_priv_key(akcipher, key, keylen);
+	tfm->has_key = !err;
+	return err;
 }
 
 static int akcipher_setpubkey(void *private, const u8 *key, unsigned int keylen)
 {
-	return crypto_akcipher_set_pub_key(private, key, keylen);
+	struct akcipher_tfm *tfm = private;
+	struct crypto_akcipher *akcipher = tfm->akcipher;
+	int err;
+
+	err = crypto_akcipher_set_pub_key(akcipher, key, keylen);
+	tfm->has_key = !err;
+	return err;
 }
 
 static void akcipher_sock_destruct(struct sock *sk)
@@ -470,11 +601,13 @@ static void akcipher_sock_destruct(struct sock *sk)
 	af_alg_release_parent(sk);
 }
 
-static int akcipher_accept_parent(void *private, struct sock *sk)
+static int akcipher_accept_parent_nokey(void *private, struct sock *sk)
 {
 	struct akcipher_ctx *ctx;
 	struct alg_sock *ask = alg_sk(sk);
-	unsigned int len = sizeof(*ctx) + crypto_akcipher_reqsize(private);
+	struct akcipher_tfm *tfm = private;
+	struct crypto_akcipher *akcipher = tfm->akcipher;
+	unsigned int len = sizeof(*ctx) + crypto_akcipher_reqsize(akcipher);
 
 	ctx = sock_kmalloc(sk, len, GFP_KERNEL);
 	if (!ctx)
@@ -492,7 +625,7 @@ static int akcipher_accept_parent(void *private, struct sock *sk)
 
 	ask->private = ctx;
 
-	akcipher_request_set_tfm(&ctx->req, private);
+	akcipher_request_set_tfm(&ctx->req, akcipher);
 	akcipher_request_set_callback(&ctx->req, CRYPTO_TFM_REQ_MAY_BACKLOG,
 				      af_alg_complete, &ctx->completion);
 
@@ -501,13 +634,25 @@ static int akcipher_accept_parent(void *private, struct sock *sk)
 	return 0;
 }
 
+static int akcipher_accept_parent(void *private, struct sock *sk)
+{
+	struct akcipher_tfm *tfm = private;
+
+	if (!tfm->has_key)
+		return -ENOKEY;
+
+	return akcipher_accept_parent_nokey(private, sk);
+}
+
 static const struct af_alg_type algif_type_akcipher = {
 	.bind		=	akcipher_bind,
 	.release	=	akcipher_release,
 	.setkey		=	akcipher_setprivkey,
 	.setpubkey	=	akcipher_setpubkey,
 	.accept		=	akcipher_accept_parent,
+	.accept_nokey	=	akcipher_accept_parent_nokey,
 	.ops		=	&algif_akcipher_ops,
+	.ops_nokey	=	&algif_akcipher_ops_nokey,
 	.name		=	"akcipher",
 	.owner		=	THIS_MODULE
 };

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v8 6/6] crypto: AF_ALG - add support for key_id
  2016-06-23 22:55 [PATCH v8 0/6] crypto: algif - add akcipher Tadeusz Struk
                   ` (3 preceding siblings ...)
       [not found] ` <146672252642.23101.15972023870303797249.stgit-mEAvsCHCuLl9qtVHHdszJa2pdiUAq4bhAL8bYrjMMd8@public.gmane.org>
@ 2016-06-23 22:55 ` Tadeusz Struk
       [not found]   ` <146672255872.23101.10938182451423661314.stgit-mEAvsCHCuLl9qtVHHdszJa2pdiUAq4bhAL8bYrjMMd8@public.gmane.org>
  2016-06-29 18:43   ` Mat Martineau
  4 siblings, 2 replies; 20+ messages in thread
From: Tadeusz Struk @ 2016-06-23 22:55 UTC (permalink / raw)
  To: dhowells
  Cc: herbert, tadeusz.struk, smueller, linux-api, marcel,
	mathew.j.martineau, linux-kernel, keyrings, linux-crypto, dwmw2,
	davem

This patch adds support for asymmetric key type to AF_ALG.
It will work as follows: A new PF_ALG socket options are
added on top of existing ALG_SET_KEY and ALG_SET_PUBKEY, namely
ALG_SET_KEY_ID and ALG_SET_PUBKEY_ID for setting public and
private keys respectively. When these new options will be used
the user, instead of providing the key material, will provide a
key id and the key itself will be obtained from kernel keyring
subsystem. The user will use the standard tools (keyctl tool
or the keyctl syscall) for key instantiation and to obtain the
key id. The key id can also be obtained by reading the
/proc/keys file.

When a key corresponding to the given keyid is found, it is stored
in the socket context and subsequent crypto operation invoked by the
user will use the new asymmetric accessor functions instead of akcipher
api. The asymmetric subtype can internally use akcipher api or
invoke operations defined by a given subtype, depending on the
key type.

Signed-off-by: Tadeusz Struk <tadeusz.struk@intel.com>
---
 crypto/af_alg.c             |   10 ++
 crypto/algif_akcipher.c     |  212 ++++++++++++++++++++++++++++++++++++++++++-
 include/crypto/if_alg.h     |    1 
 include/uapi/linux/if_alg.h |    2 
 4 files changed, 220 insertions(+), 5 deletions(-)

diff --git a/crypto/af_alg.c b/crypto/af_alg.c
index 24dc082..59c8244 100644
--- a/crypto/af_alg.c
+++ b/crypto/af_alg.c
@@ -260,6 +260,16 @@ static int alg_setsockopt(struct socket *sock, int level, int optname,
 
 		err = alg_setkey(sk, optval, optlen, type->setpubkey);
 		break;
+
+	case ALG_SET_KEY_ID:
+	case ALG_SET_PUBKEY_ID:
+		/* ALG_SET_KEY_ID is only for akcipher */
+		if (!strcmp(type->name, "akcipher") ||
+		    sock->state == SS_CONNECTED)
+			goto unlock;
+
+		err = alg_setkey(sk, optval, optlen, type->setkeyid);
+		break;
 	case ALG_SET_AEAD_AUTHSIZE:
 		if (sock->state == SS_CONNECTED)
 			goto unlock;
diff --git a/crypto/algif_akcipher.c b/crypto/algif_akcipher.c
index 2b8d37e..106f715 100644
--- a/crypto/algif_akcipher.c
+++ b/crypto/algif_akcipher.c
@@ -14,6 +14,8 @@
 #include <crypto/akcipher.h>
 #include <crypto/scatterwalk.h>
 #include <crypto/if_alg.h>
+#include <crypto/public_key.h>
+#include <keys/asymmetric-type.h>
 #include <linux/init.h>
 #include <linux/list.h>
 #include <linux/kernel.h>
@@ -29,6 +31,7 @@ struct akcipher_sg_list {
 
 struct akcipher_tfm {
 	struct crypto_akcipher *akcipher;
+	char keyid[12];
 	bool has_key;
 };
 
@@ -37,6 +40,7 @@ struct akcipher_ctx {
 	struct af_alg_sgl rsgl[ALG_MAX_PAGES];
 
 	struct af_alg_completion completion;
+	struct key *key;
 
 	unsigned long used;
 
@@ -317,6 +321,158 @@ unlock:
 	return err ? err : size;
 }
 
+static int asym_key_encrypt(const struct key *key, struct akcipher_request *req)
+{
+	struct kernel_pkey_params params = {0};
+	char *src = NULL, *dst = NULL, *in, *out;
+	int ret;
+
+	if (!sg_is_last(req->src)) {
+		src = kmalloc(req->src_len, GFP_KERNEL);
+		if (!src)
+			return -ENOMEM;
+		scatterwalk_map_and_copy(src, req->src, 0, req->src_len, 0);
+		in = src;
+	} else {
+		in = sg_virt(req->src);
+	}
+	if (!sg_is_last(req->dst)) {
+		dst = kmalloc(req->dst_len, GFP_KERNEL);
+		if (!dst) {
+			kfree(src);
+			return -ENOMEM;
+		}
+		out = dst;
+	} else {
+		out = sg_virt(req->dst);
+	}
+	params.key = (struct key *)key;
+	params.in_len = req->src_len;
+	params.out_len = req->dst_len;
+	ret = encrypt_blob(&params, in, out);
+	if (ret)
+		goto free;
+
+	if (dst)
+		scatterwalk_map_and_copy(dst, req->dst, 0, req->dst_len, 1);
+free:
+	kfree(src);
+	kfree(dst);
+	return ret;
+}
+
+static int asym_key_decrypt(const struct key *key, struct akcipher_request *req)
+{
+	struct kernel_pkey_params params = {0};
+	char *src = NULL, *dst = NULL, *in, *out;
+	int ret;
+
+	if (!sg_is_last(req->src)) {
+		src = kmalloc(req->src_len, GFP_KERNEL);
+		if (!src)
+			return -ENOMEM;
+		scatterwalk_map_and_copy(src, req->src, 0, req->src_len, 0);
+		in = src;
+	} else {
+		in = sg_virt(req->src);
+	}
+	if (!sg_is_last(req->dst)) {
+		dst = kmalloc(req->dst_len, GFP_KERNEL);
+		if (!dst) {
+			kfree(src);
+			return -ENOMEM;
+		}
+		out = dst;
+	} else {
+		out = sg_virt(req->dst);
+	}
+	params.key = (struct key *)key;
+	params.in_len = req->src_len;
+	params.out_len = req->dst_len;
+	ret = decrypt_blob(&params, in, out);
+	if (ret)
+		goto free;
+
+	if (dst)
+		scatterwalk_map_and_copy(dst, req->dst, 0, req->dst_len, 1);
+free:
+	kfree(src);
+	kfree(dst);
+	return ret;
+}
+
+static int asym_key_sign(const struct key *key, struct akcipher_request *req)
+{
+	struct kernel_pkey_params params = {0};
+	char *src = NULL, *dst = NULL, *in, *out;
+	int ret;
+
+	if (!sg_is_last(req->src)) {
+		src = kmalloc(req->src_len, GFP_KERNEL);
+		if (!src)
+			return -ENOMEM;
+		scatterwalk_map_and_copy(src, req->src, 0, req->src_len, 0);
+		in = src;
+	} else {
+		in = sg_virt(req->src);
+	}
+	if (!sg_is_last(req->dst)) {
+		dst = kmalloc(req->dst_len, GFP_KERNEL);
+		if (!dst) {
+			kfree(src);
+			return -ENOMEM;
+		}
+		out = dst;
+	} else {
+		out = sg_virt(req->dst);
+	}
+	params.key = (struct key *)key;
+	params.in_len = req->src_len;
+	params.out_len = req->dst_len;
+	ret = create_signature(&params, in, out);
+	if (ret)
+		goto free;
+
+	if (dst)
+		scatterwalk_map_and_copy(dst, req->dst, 0, req->dst_len, 1);
+free:
+	kfree(src);
+	kfree(dst);
+	return ret;
+}
+
+static int asym_key_verify(const struct key *key, struct akcipher_request *req)
+{
+	struct public_key_signature sig;
+	char *src = NULL, *in, digest[20];
+	int ret;
+
+	if (!sg_is_last(req->src)) {
+		src = kmalloc(req->src_len, GFP_KERNEL);
+		if (!src)
+			return -ENOMEM;
+		scatterwalk_map_and_copy(src, req->src, 0, req->src_len, 0);
+		in = src;
+	} else {
+		in = sg_virt(req->src);
+	}
+	sig.pkey_algo = "rsa";
+	sig.encoding = "pkcs1";
+	/* Need to find a way to pass the hash param */
+	sig.hash_algo = "sha1";
+	sig.digest_size = sizeof(digest);
+	sig.digest = digest;
+	sig.s_size = req->src_len;
+	sig.s = src;
+	ret = verify_signature(key, &sig);
+	if (!ret) {
+		req->dst_len = sizeof(digest);
+		scatterwalk_map_and_copy(digest, req->dst, 0, req->dst_len, 1);
+	}
+	kfree(src);
+	return ret;
+}
+
 static int akcipher_recvmsg(struct socket *sock, struct msghdr *msg,
 			    size_t ignored, int flags)
 {
@@ -366,16 +522,28 @@ static int akcipher_recvmsg(struct socket *sock, struct msghdr *msg,
 				   usedpages);
 	switch (ctx->op) {
 	case ALG_OP_VERIFY:
-		err = crypto_akcipher_verify(&ctx->req);
+		if (ctx->key)
+			err = asym_key_verify(ctx->key, &ctx->req);
+		else
+			err = crypto_akcipher_verify(&ctx->req);
 		break;
 	case ALG_OP_SIGN:
-		err = crypto_akcipher_sign(&ctx->req);
+		if (ctx->key)
+			err = asym_key_sign(ctx->key, &ctx->req);
+		else
+			err = crypto_akcipher_sign(&ctx->req);
 		break;
 	case ALG_OP_ENCRYPT:
-		err = crypto_akcipher_encrypt(&ctx->req);
+		if (ctx->key)
+			err = asym_key_encrypt(ctx->key, &ctx->req);
+		else
+			err = crypto_akcipher_encrypt(&ctx->req);
 		break;
 	case ALG_OP_DECRYPT:
-		err = crypto_akcipher_decrypt(&ctx->req);
+		if (ctx->key)
+			err = asym_key_decrypt(ctx->key, &ctx->req);
+		else
+			err = crypto_akcipher_decrypt(&ctx->req);
 		break;
 	default:
 		err = -EFAULT;
@@ -568,6 +736,27 @@ static void akcipher_release(void *private)
 	kfree(tfm);
 }
 
+static int akcipher_setkeyid(void *private, const u8 *key, unsigned int keylen)
+{
+	struct akcipher_tfm *tfm = private;
+	struct key *akey;
+	u32 keyid = *((u32 *)key);
+	int err = -ENOKEY;
+
+	/* Store the key id and verify that a key with the given id is present.
+	 * The actual key will be acquired in the accept_parent function
+	 */
+	sprintf(tfm->keyid, "id:%08x", keyid);
+	akey = request_key(&key_type_asymmetric, tfm->keyid, NULL);
+	if (IS_ERR(key))
+		goto out;
+
+	tfm->has_key = true;
+	key_put(akey);
+out:
+	return err;
+}
+
 static int akcipher_setprivkey(void *private, const u8 *key,
 			       unsigned int keylen)
 {
@@ -599,6 +788,8 @@ static void akcipher_sock_destruct(struct sock *sk)
 	akcipher_put_sgl(sk);
 	sock_kfree_s(sk, ctx, ctx->len);
 	af_alg_release_parent(sk);
+	if (ctx->key)
+		key_put(ctx->key);
 }
 
 static int akcipher_accept_parent_nokey(void *private, struct sock *sk)
@@ -607,6 +798,7 @@ static int akcipher_accept_parent_nokey(void *private, struct sock *sk)
 	struct alg_sock *ask = alg_sk(sk);
 	struct akcipher_tfm *tfm = private;
 	struct crypto_akcipher *akcipher = tfm->akcipher;
+	struct key *key;
 	unsigned int len = sizeof(*ctx) + crypto_akcipher_reqsize(akcipher);
 
 	ctx = sock_kmalloc(sk, len, GFP_KERNEL);
@@ -623,11 +815,20 @@ static int akcipher_accept_parent_nokey(void *private, struct sock *sk)
 	af_alg_init_completion(&ctx->completion);
 	sg_init_table(ctx->tsgl.sg, ALG_MAX_PAGES);
 
-	ask->private = ctx;
+	if (strlen(tfm->keyid)) {
+		key = request_key(&key_type_asymmetric, tfm->keyid, NULL);
+		if (IS_ERR(key)) {
+			sock_kfree_s(sk, ctx, len);
+			return -ENOKEY;
+		}
 
+		ctx->key = key;
+		memset(tfm->keyid, '\0', sizeof(tfm->keyid));
+	}
 	akcipher_request_set_tfm(&ctx->req, akcipher);
 	akcipher_request_set_callback(&ctx->req, CRYPTO_TFM_REQ_MAY_BACKLOG,
 				      af_alg_complete, &ctx->completion);
+	ask->private = ctx;
 
 	sk->sk_destruct = akcipher_sock_destruct;
 
@@ -649,6 +850,7 @@ static const struct af_alg_type algif_type_akcipher = {
 	.release	=	akcipher_release,
 	.setkey		=	akcipher_setprivkey,
 	.setpubkey	=	akcipher_setpubkey,
+	.setkeyid	=	akcipher_setkeyid,
 	.accept		=	akcipher_accept_parent,
 	.accept_nokey	=	akcipher_accept_parent_nokey,
 	.ops		=	&algif_akcipher_ops,
diff --git a/include/crypto/if_alg.h b/include/crypto/if_alg.h
index 6c3e6e7..09c99ab 100644
--- a/include/crypto/if_alg.h
+++ b/include/crypto/if_alg.h
@@ -53,6 +53,7 @@ struct af_alg_type {
 	void (*release)(void *private);
 	int (*setkey)(void *private, const u8 *key, unsigned int keylen);
 	int (*setpubkey)(void *private, const u8 *key, unsigned int keylen);
+	int (*setkeyid)(void *private, const u8 *key, unsigned int keylen);
 	int (*accept)(void *private, struct sock *sk);
 	int (*accept_nokey)(void *private, struct sock *sk);
 	int (*setauthsize)(void *private, unsigned int authsize);
diff --git a/include/uapi/linux/if_alg.h b/include/uapi/linux/if_alg.h
index 02e6162..0379766 100644
--- a/include/uapi/linux/if_alg.h
+++ b/include/uapi/linux/if_alg.h
@@ -35,6 +35,8 @@ struct af_alg_iv {
 #define ALG_SET_AEAD_ASSOCLEN		4
 #define ALG_SET_AEAD_AUTHSIZE		5
 #define ALG_SET_PUBKEY			6
+#define ALG_SET_PUBKEY_ID		7
+#define ALG_SET_KEY_ID			8
 
 /* Operations */
 #define ALG_OP_DECRYPT			0

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [PATCH v8 6/6] crypto: AF_ALG - add support for key_id
  2016-06-23 22:55 ` [PATCH v8 6/6] crypto: AF_ALG - add support for key_id Tadeusz Struk
       [not found]   ` <146672255872.23101.10938182451423661314.stgit-mEAvsCHCuLl9qtVHHdszJa2pdiUAq4bhAL8bYrjMMd8@public.gmane.org>
@ 2016-06-24  1:01       ` kbuild test robot
  1 sibling, 0 replies; 20+ messages in thread
From: kbuild test robot @ 2016-06-24  1:01 UTC (permalink / raw)
  To: Tadeusz Struk
  Cc: kbuild-all-JC7UmRfGjtg, dhowells-H+wXaHxf7aLQT0dZR+AlfA,
	herbert-lOAM2aK0SrRLBo1qDEOMRrpzq4S04n8Q,
	tadeusz.struk-ral2JQCrhuEAvxtiuMwx3w,
	smueller-T9tCv8IpfcWELgA04lAiVw,
	linux-api-u79uwXL29TY76Z2rM5mHXA, marcel-kz+m5ild9QBg9hUCZPvPmw,
	mathew.j.martineau-VuQAYsv1563Yd54FQh9/CA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	keyrings-u79uwXL29TY76Z2rM5mHXA,
	linux-crypto-u79uwXL29TY76Z2rM5mHXA,
	dwmw2-wEGCiKHe2LqWVfeAwA7xHQ, davem-fT/PcQaiUtIeIZ0/mPfg9Q

[-- Attachment #1: Type: text/plain, Size: 8253 bytes --]

Hi,

[auto build test ERROR on cryptodev/master]
[also build test ERROR on v4.7-rc4 next-20160623]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Tadeusz-Struk/crypto-algif-add-akcipher/20160624-065803
base:   https://git.kernel.org/pub/scm/linux/kernel/git/herbert/cryptodev-2.6.git master
config: x86_64-allmodconfig (attached as .config)
compiler: gcc-6 (Debian 6.1.1-1) 6.1.1 20160430
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All error/warnings (new ones prefixed by >>):

   crypto/algif_akcipher.c: In function 'asym_key_encrypt':
>> crypto/algif_akcipher.c:326:9: error: variable 'params' has initializer but incomplete type
     struct kernel_pkey_params params = {0};
            ^~~~~~~~~~~~~~~~~~
>> crypto/algif_akcipher.c:326:38: warning: excess elements in struct initializer
     struct kernel_pkey_params params = {0};
                                         ^
   crypto/algif_akcipher.c:326:38: note: (near initialization for 'params')
>> crypto/algif_akcipher.c:326:28: error: storage size of 'params' isn't known
     struct kernel_pkey_params params = {0};
                               ^~~~~~
>> crypto/algif_akcipher.c:352:8: error: implicit declaration of function 'encrypt_blob' [-Werror=implicit-function-declaration]
     ret = encrypt_blob(&params, in, out);
           ^~~~~~~~~~~~
>> crypto/algif_akcipher.c:326:28: warning: unused variable 'params' [-Wunused-variable]
     struct kernel_pkey_params params = {0};
                               ^~~~~~
   crypto/algif_akcipher.c: In function 'asym_key_decrypt':
   crypto/algif_akcipher.c:366:9: error: variable 'params' has initializer but incomplete type
     struct kernel_pkey_params params = {0};
            ^~~~~~~~~~~~~~~~~~
   crypto/algif_akcipher.c:366:38: warning: excess elements in struct initializer
     struct kernel_pkey_params params = {0};
                                         ^
   crypto/algif_akcipher.c:366:38: note: (near initialization for 'params')
   crypto/algif_akcipher.c:366:28: error: storage size of 'params' isn't known
     struct kernel_pkey_params params = {0};
                               ^~~~~~
>> crypto/algif_akcipher.c:392:8: error: implicit declaration of function 'decrypt_blob' [-Werror=implicit-function-declaration]
     ret = decrypt_blob(&params, in, out);
           ^~~~~~~~~~~~
   crypto/algif_akcipher.c:366:28: warning: unused variable 'params' [-Wunused-variable]
     struct kernel_pkey_params params = {0};
                               ^~~~~~
   crypto/algif_akcipher.c: In function 'asym_key_sign':
   crypto/algif_akcipher.c:406:9: error: variable 'params' has initializer but incomplete type
     struct kernel_pkey_params params = {0};
            ^~~~~~~~~~~~~~~~~~
   crypto/algif_akcipher.c:406:38: warning: excess elements in struct initializer
     struct kernel_pkey_params params = {0};
                                         ^
   crypto/algif_akcipher.c:406:38: note: (near initialization for 'params')
   crypto/algif_akcipher.c:406:28: error: storage size of 'params' isn't known
     struct kernel_pkey_params params = {0};
                               ^~~~~~
>> crypto/algif_akcipher.c:432:8: error: implicit declaration of function 'create_signature' [-Werror=implicit-function-declaration]
     ret = create_signature(&params, in, out);
           ^~~~~~~~~~~~~~~~
   crypto/algif_akcipher.c:406:28: warning: unused variable 'params' [-Wunused-variable]
     struct kernel_pkey_params params = {0};
                               ^~~~~~
   crypto/algif_akcipher.c: In function 'asym_key_verify':
>> crypto/algif_akcipher.c:460:5: error: 'struct public_key_signature' has no member named 'encoding'
     sig.encoding = "pkcs1";
        ^
   cc1: some warnings being treated as errors

vim +/params +326 crypto/algif_akcipher.c

   320	
   321		return err ? err : size;
   322	}
   323	
   324	static int asym_key_encrypt(const struct key *key, struct akcipher_request *req)
   325	{
 > 326		struct kernel_pkey_params params = {0};
   327		char *src = NULL, *dst = NULL, *in, *out;
   328		int ret;
   329	
   330		if (!sg_is_last(req->src)) {
   331			src = kmalloc(req->src_len, GFP_KERNEL);
   332			if (!src)
   333				return -ENOMEM;
   334			scatterwalk_map_and_copy(src, req->src, 0, req->src_len, 0);
   335			in = src;
   336		} else {
   337			in = sg_virt(req->src);
   338		}
   339		if (!sg_is_last(req->dst)) {
   340			dst = kmalloc(req->dst_len, GFP_KERNEL);
   341			if (!dst) {
   342				kfree(src);
   343				return -ENOMEM;
   344			}
   345			out = dst;
   346		} else {
   347			out = sg_virt(req->dst);
   348		}
   349		params.key = (struct key *)key;
   350		params.in_len = req->src_len;
   351		params.out_len = req->dst_len;
 > 352		ret = encrypt_blob(&params, in, out);
   353		if (ret)
   354			goto free;
   355	
   356		if (dst)
   357			scatterwalk_map_and_copy(dst, req->dst, 0, req->dst_len, 1);
   358	free:
   359		kfree(src);
   360		kfree(dst);
   361		return ret;
   362	}
   363	
   364	static int asym_key_decrypt(const struct key *key, struct akcipher_request *req)
   365	{
 > 366		struct kernel_pkey_params params = {0};
   367		char *src = NULL, *dst = NULL, *in, *out;
   368		int ret;
   369	
   370		if (!sg_is_last(req->src)) {
   371			src = kmalloc(req->src_len, GFP_KERNEL);
   372			if (!src)
   373				return -ENOMEM;
   374			scatterwalk_map_and_copy(src, req->src, 0, req->src_len, 0);
   375			in = src;
   376		} else {
   377			in = sg_virt(req->src);
   378		}
   379		if (!sg_is_last(req->dst)) {
   380			dst = kmalloc(req->dst_len, GFP_KERNEL);
   381			if (!dst) {
   382				kfree(src);
   383				return -ENOMEM;
   384			}
   385			out = dst;
   386		} else {
   387			out = sg_virt(req->dst);
   388		}
   389		params.key = (struct key *)key;
   390		params.in_len = req->src_len;
   391		params.out_len = req->dst_len;
 > 392		ret = decrypt_blob(&params, in, out);
   393		if (ret)
   394			goto free;
   395	
   396		if (dst)
   397			scatterwalk_map_and_copy(dst, req->dst, 0, req->dst_len, 1);
   398	free:
   399		kfree(src);
   400		kfree(dst);
   401		return ret;
   402	}
   403	
   404	static int asym_key_sign(const struct key *key, struct akcipher_request *req)
   405	{
 > 406		struct kernel_pkey_params params = {0};
   407		char *src = NULL, *dst = NULL, *in, *out;
   408		int ret;
   409	
   410		if (!sg_is_last(req->src)) {
   411			src = kmalloc(req->src_len, GFP_KERNEL);
   412			if (!src)
   413				return -ENOMEM;
   414			scatterwalk_map_and_copy(src, req->src, 0, req->src_len, 0);
   415			in = src;
   416		} else {
   417			in = sg_virt(req->src);
   418		}
   419		if (!sg_is_last(req->dst)) {
   420			dst = kmalloc(req->dst_len, GFP_KERNEL);
   421			if (!dst) {
   422				kfree(src);
   423				return -ENOMEM;
   424			}
   425			out = dst;
   426		} else {
   427			out = sg_virt(req->dst);
   428		}
   429		params.key = (struct key *)key;
   430		params.in_len = req->src_len;
   431		params.out_len = req->dst_len;
 > 432		ret = create_signature(&params, in, out);
   433		if (ret)
   434			goto free;
   435	
   436		if (dst)
   437			scatterwalk_map_and_copy(dst, req->dst, 0, req->dst_len, 1);
   438	free:
   439		kfree(src);
   440		kfree(dst);
   441		return ret;
   442	}
   443	
   444	static int asym_key_verify(const struct key *key, struct akcipher_request *req)
   445	{
   446		struct public_key_signature sig;
   447		char *src = NULL, *in, digest[20];
   448		int ret;
   449	
   450		if (!sg_is_last(req->src)) {
   451			src = kmalloc(req->src_len, GFP_KERNEL);
   452			if (!src)
   453				return -ENOMEM;
   454			scatterwalk_map_and_copy(src, req->src, 0, req->src_len, 0);
   455			in = src;
   456		} else {
   457			in = sg_virt(req->src);
   458		}
   459		sig.pkey_algo = "rsa";
 > 460		sig.encoding = "pkcs1";
   461		/* Need to find a way to pass the hash param */
   462		sig.hash_algo = "sha1";
   463		sig.digest_size = sizeof(digest);

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 54789 bytes --]

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v8 6/6] crypto: AF_ALG - add support for key_id
@ 2016-06-24  1:01       ` kbuild test robot
  0 siblings, 0 replies; 20+ messages in thread
From: kbuild test robot @ 2016-06-24  1:01 UTC (permalink / raw)
  To: Tadeusz Struk
  Cc: kbuild-all, dhowells, herbert, tadeusz.struk, smueller,
	linux-api, marcel, mathew.j.martineau, linux-kernel, keyrings,
	linux-crypto, dwmw2, davem

[-- Attachment #1: Type: text/plain, Size: 8253 bytes --]

Hi,

[auto build test ERROR on cryptodev/master]
[also build test ERROR on v4.7-rc4 next-20160623]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Tadeusz-Struk/crypto-algif-add-akcipher/20160624-065803
base:   https://git.kernel.org/pub/scm/linux/kernel/git/herbert/cryptodev-2.6.git master
config: x86_64-allmodconfig (attached as .config)
compiler: gcc-6 (Debian 6.1.1-1) 6.1.1 20160430
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All error/warnings (new ones prefixed by >>):

   crypto/algif_akcipher.c: In function 'asym_key_encrypt':
>> crypto/algif_akcipher.c:326:9: error: variable 'params' has initializer but incomplete type
     struct kernel_pkey_params params = {0};
            ^~~~~~~~~~~~~~~~~~
>> crypto/algif_akcipher.c:326:38: warning: excess elements in struct initializer
     struct kernel_pkey_params params = {0};
                                         ^
   crypto/algif_akcipher.c:326:38: note: (near initialization for 'params')
>> crypto/algif_akcipher.c:326:28: error: storage size of 'params' isn't known
     struct kernel_pkey_params params = {0};
                               ^~~~~~
>> crypto/algif_akcipher.c:352:8: error: implicit declaration of function 'encrypt_blob' [-Werror=implicit-function-declaration]
     ret = encrypt_blob(&params, in, out);
           ^~~~~~~~~~~~
>> crypto/algif_akcipher.c:326:28: warning: unused variable 'params' [-Wunused-variable]
     struct kernel_pkey_params params = {0};
                               ^~~~~~
   crypto/algif_akcipher.c: In function 'asym_key_decrypt':
   crypto/algif_akcipher.c:366:9: error: variable 'params' has initializer but incomplete type
     struct kernel_pkey_params params = {0};
            ^~~~~~~~~~~~~~~~~~
   crypto/algif_akcipher.c:366:38: warning: excess elements in struct initializer
     struct kernel_pkey_params params = {0};
                                         ^
   crypto/algif_akcipher.c:366:38: note: (near initialization for 'params')
   crypto/algif_akcipher.c:366:28: error: storage size of 'params' isn't known
     struct kernel_pkey_params params = {0};
                               ^~~~~~
>> crypto/algif_akcipher.c:392:8: error: implicit declaration of function 'decrypt_blob' [-Werror=implicit-function-declaration]
     ret = decrypt_blob(&params, in, out);
           ^~~~~~~~~~~~
   crypto/algif_akcipher.c:366:28: warning: unused variable 'params' [-Wunused-variable]
     struct kernel_pkey_params params = {0};
                               ^~~~~~
   crypto/algif_akcipher.c: In function 'asym_key_sign':
   crypto/algif_akcipher.c:406:9: error: variable 'params' has initializer but incomplete type
     struct kernel_pkey_params params = {0};
            ^~~~~~~~~~~~~~~~~~
   crypto/algif_akcipher.c:406:38: warning: excess elements in struct initializer
     struct kernel_pkey_params params = {0};
                                         ^
   crypto/algif_akcipher.c:406:38: note: (near initialization for 'params')
   crypto/algif_akcipher.c:406:28: error: storage size of 'params' isn't known
     struct kernel_pkey_params params = {0};
                               ^~~~~~
>> crypto/algif_akcipher.c:432:8: error: implicit declaration of function 'create_signature' [-Werror=implicit-function-declaration]
     ret = create_signature(&params, in, out);
           ^~~~~~~~~~~~~~~~
   crypto/algif_akcipher.c:406:28: warning: unused variable 'params' [-Wunused-variable]
     struct kernel_pkey_params params = {0};
                               ^~~~~~
   crypto/algif_akcipher.c: In function 'asym_key_verify':
>> crypto/algif_akcipher.c:460:5: error: 'struct public_key_signature' has no member named 'encoding'
     sig.encoding = "pkcs1";
        ^
   cc1: some warnings being treated as errors

vim +/params +326 crypto/algif_akcipher.c

   320	
   321		return err ? err : size;
   322	}
   323	
   324	static int asym_key_encrypt(const struct key *key, struct akcipher_request *req)
   325	{
 > 326		struct kernel_pkey_params params = {0};
   327		char *src = NULL, *dst = NULL, *in, *out;
   328		int ret;
   329	
   330		if (!sg_is_last(req->src)) {
   331			src = kmalloc(req->src_len, GFP_KERNEL);
   332			if (!src)
   333				return -ENOMEM;
   334			scatterwalk_map_and_copy(src, req->src, 0, req->src_len, 0);
   335			in = src;
   336		} else {
   337			in = sg_virt(req->src);
   338		}
   339		if (!sg_is_last(req->dst)) {
   340			dst = kmalloc(req->dst_len, GFP_KERNEL);
   341			if (!dst) {
   342				kfree(src);
   343				return -ENOMEM;
   344			}
   345			out = dst;
   346		} else {
   347			out = sg_virt(req->dst);
   348		}
   349		params.key = (struct key *)key;
   350		params.in_len = req->src_len;
   351		params.out_len = req->dst_len;
 > 352		ret = encrypt_blob(&params, in, out);
   353		if (ret)
   354			goto free;
   355	
   356		if (dst)
   357			scatterwalk_map_and_copy(dst, req->dst, 0, req->dst_len, 1);
   358	free:
   359		kfree(src);
   360		kfree(dst);
   361		return ret;
   362	}
   363	
   364	static int asym_key_decrypt(const struct key *key, struct akcipher_request *req)
   365	{
 > 366		struct kernel_pkey_params params = {0};
   367		char *src = NULL, *dst = NULL, *in, *out;
   368		int ret;
   369	
   370		if (!sg_is_last(req->src)) {
   371			src = kmalloc(req->src_len, GFP_KERNEL);
   372			if (!src)
   373				return -ENOMEM;
   374			scatterwalk_map_and_copy(src, req->src, 0, req->src_len, 0);
   375			in = src;
   376		} else {
   377			in = sg_virt(req->src);
   378		}
   379		if (!sg_is_last(req->dst)) {
   380			dst = kmalloc(req->dst_len, GFP_KERNEL);
   381			if (!dst) {
   382				kfree(src);
   383				return -ENOMEM;
   384			}
   385			out = dst;
   386		} else {
   387			out = sg_virt(req->dst);
   388		}
   389		params.key = (struct key *)key;
   390		params.in_len = req->src_len;
   391		params.out_len = req->dst_len;
 > 392		ret = decrypt_blob(&params, in, out);
   393		if (ret)
   394			goto free;
   395	
   396		if (dst)
   397			scatterwalk_map_and_copy(dst, req->dst, 0, req->dst_len, 1);
   398	free:
   399		kfree(src);
   400		kfree(dst);
   401		return ret;
   402	}
   403	
   404	static int asym_key_sign(const struct key *key, struct akcipher_request *req)
   405	{
 > 406		struct kernel_pkey_params params = {0};
   407		char *src = NULL, *dst = NULL, *in, *out;
   408		int ret;
   409	
   410		if (!sg_is_last(req->src)) {
   411			src = kmalloc(req->src_len, GFP_KERNEL);
   412			if (!src)
   413				return -ENOMEM;
   414			scatterwalk_map_and_copy(src, req->src, 0, req->src_len, 0);
   415			in = src;
   416		} else {
   417			in = sg_virt(req->src);
   418		}
   419		if (!sg_is_last(req->dst)) {
   420			dst = kmalloc(req->dst_len, GFP_KERNEL);
   421			if (!dst) {
   422				kfree(src);
   423				return -ENOMEM;
   424			}
   425			out = dst;
   426		} else {
   427			out = sg_virt(req->dst);
   428		}
   429		params.key = (struct key *)key;
   430		params.in_len = req->src_len;
   431		params.out_len = req->dst_len;
 > 432		ret = create_signature(&params, in, out);
   433		if (ret)
   434			goto free;
   435	
   436		if (dst)
   437			scatterwalk_map_and_copy(dst, req->dst, 0, req->dst_len, 1);
   438	free:
   439		kfree(src);
   440		kfree(dst);
   441		return ret;
   442	}
   443	
   444	static int asym_key_verify(const struct key *key, struct akcipher_request *req)
   445	{
   446		struct public_key_signature sig;
   447		char *src = NULL, *in, digest[20];
   448		int ret;
   449	
   450		if (!sg_is_last(req->src)) {
   451			src = kmalloc(req->src_len, GFP_KERNEL);
   452			if (!src)
   453				return -ENOMEM;
   454			scatterwalk_map_and_copy(src, req->src, 0, req->src_len, 0);
   455			in = src;
   456		} else {
   457			in = sg_virt(req->src);
   458		}
   459		sig.pkey_algo = "rsa";
 > 460		sig.encoding = "pkcs1";
   461		/* Need to find a way to pass the hash param */
   462		sig.hash_algo = "sha1";
   463		sig.digest_size = sizeof(digest);

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 54789 bytes --]

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v8 6/6] crypto: AF_ALG - add support for key_id
@ 2016-06-24  1:01       ` kbuild test robot
  0 siblings, 0 replies; 20+ messages in thread
From: kbuild test robot @ 2016-06-24  1:01 UTC (permalink / raw)
  Cc: kbuild-all-JC7UmRfGjtg, dhowells-H+wXaHxf7aLQT0dZR+AlfA,
	herbert-lOAM2aK0SrRLBo1qDEOMRrpzq4S04n8Q,
	tadeusz.struk-ral2JQCrhuEAvxtiuMwx3w,
	smueller-T9tCv8IpfcWELgA04lAiVw,
	linux-api-u79uwXL29TY76Z2rM5mHXA, marcel-kz+m5ild9QBg9hUCZPvPmw,
	mathew.j.martineau-VuQAYsv1563Yd54FQh9/CA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	keyrings-u79uwXL29TY76Z2rM5mHXA,
	linux-crypto-u79uwXL29TY76Z2rM5mHXA,
	dwmw2-wEGCiKHe2LqWVfeAwA7xHQ, davem-fT/PcQaiUtIeIZ0/mPfg9Q

[-- Attachment #1: Type: text/plain, Size: 8253 bytes --]

Hi,

[auto build test ERROR on cryptodev/master]
[also build test ERROR on v4.7-rc4 next-20160623]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Tadeusz-Struk/crypto-algif-add-akcipher/20160624-065803
base:   https://git.kernel.org/pub/scm/linux/kernel/git/herbert/cryptodev-2.6.git master
config: x86_64-allmodconfig (attached as .config)
compiler: gcc-6 (Debian 6.1.1-1) 6.1.1 20160430
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All error/warnings (new ones prefixed by >>):

   crypto/algif_akcipher.c: In function 'asym_key_encrypt':
>> crypto/algif_akcipher.c:326:9: error: variable 'params' has initializer but incomplete type
     struct kernel_pkey_params params = {0};
            ^~~~~~~~~~~~~~~~~~
>> crypto/algif_akcipher.c:326:38: warning: excess elements in struct initializer
     struct kernel_pkey_params params = {0};
                                         ^
   crypto/algif_akcipher.c:326:38: note: (near initialization for 'params')
>> crypto/algif_akcipher.c:326:28: error: storage size of 'params' isn't known
     struct kernel_pkey_params params = {0};
                               ^~~~~~
>> crypto/algif_akcipher.c:352:8: error: implicit declaration of function 'encrypt_blob' [-Werror=implicit-function-declaration]
     ret = encrypt_blob(&params, in, out);
           ^~~~~~~~~~~~
>> crypto/algif_akcipher.c:326:28: warning: unused variable 'params' [-Wunused-variable]
     struct kernel_pkey_params params = {0};
                               ^~~~~~
   crypto/algif_akcipher.c: In function 'asym_key_decrypt':
   crypto/algif_akcipher.c:366:9: error: variable 'params' has initializer but incomplete type
     struct kernel_pkey_params params = {0};
            ^~~~~~~~~~~~~~~~~~
   crypto/algif_akcipher.c:366:38: warning: excess elements in struct initializer
     struct kernel_pkey_params params = {0};
                                         ^
   crypto/algif_akcipher.c:366:38: note: (near initialization for 'params')
   crypto/algif_akcipher.c:366:28: error: storage size of 'params' isn't known
     struct kernel_pkey_params params = {0};
                               ^~~~~~
>> crypto/algif_akcipher.c:392:8: error: implicit declaration of function 'decrypt_blob' [-Werror=implicit-function-declaration]
     ret = decrypt_blob(&params, in, out);
           ^~~~~~~~~~~~
   crypto/algif_akcipher.c:366:28: warning: unused variable 'params' [-Wunused-variable]
     struct kernel_pkey_params params = {0};
                               ^~~~~~
   crypto/algif_akcipher.c: In function 'asym_key_sign':
   crypto/algif_akcipher.c:406:9: error: variable 'params' has initializer but incomplete type
     struct kernel_pkey_params params = {0};
            ^~~~~~~~~~~~~~~~~~
   crypto/algif_akcipher.c:406:38: warning: excess elements in struct initializer
     struct kernel_pkey_params params = {0};
                                         ^
   crypto/algif_akcipher.c:406:38: note: (near initialization for 'params')
   crypto/algif_akcipher.c:406:28: error: storage size of 'params' isn't known
     struct kernel_pkey_params params = {0};
                               ^~~~~~
>> crypto/algif_akcipher.c:432:8: error: implicit declaration of function 'create_signature' [-Werror=implicit-function-declaration]
     ret = create_signature(&params, in, out);
           ^~~~~~~~~~~~~~~~
   crypto/algif_akcipher.c:406:28: warning: unused variable 'params' [-Wunused-variable]
     struct kernel_pkey_params params = {0};
                               ^~~~~~
   crypto/algif_akcipher.c: In function 'asym_key_verify':
>> crypto/algif_akcipher.c:460:5: error: 'struct public_key_signature' has no member named 'encoding'
     sig.encoding = "pkcs1";
        ^
   cc1: some warnings being treated as errors

vim +/params +326 crypto/algif_akcipher.c

   320	
   321		return err ? err : size;
   322	}
   323	
   324	static int asym_key_encrypt(const struct key *key, struct akcipher_request *req)
   325	{
 > 326		struct kernel_pkey_params params = {0};
   327		char *src = NULL, *dst = NULL, *in, *out;
   328		int ret;
   329	
   330		if (!sg_is_last(req->src)) {
   331			src = kmalloc(req->src_len, GFP_KERNEL);
   332			if (!src)
   333				return -ENOMEM;
   334			scatterwalk_map_and_copy(src, req->src, 0, req->src_len, 0);
   335			in = src;
   336		} else {
   337			in = sg_virt(req->src);
   338		}
   339		if (!sg_is_last(req->dst)) {
   340			dst = kmalloc(req->dst_len, GFP_KERNEL);
   341			if (!dst) {
   342				kfree(src);
   343				return -ENOMEM;
   344			}
   345			out = dst;
   346		} else {
   347			out = sg_virt(req->dst);
   348		}
   349		params.key = (struct key *)key;
   350		params.in_len = req->src_len;
   351		params.out_len = req->dst_len;
 > 352		ret = encrypt_blob(&params, in, out);
   353		if (ret)
   354			goto free;
   355	
   356		if (dst)
   357			scatterwalk_map_and_copy(dst, req->dst, 0, req->dst_len, 1);
   358	free:
   359		kfree(src);
   360		kfree(dst);
   361		return ret;
   362	}
   363	
   364	static int asym_key_decrypt(const struct key *key, struct akcipher_request *req)
   365	{
 > 366		struct kernel_pkey_params params = {0};
   367		char *src = NULL, *dst = NULL, *in, *out;
   368		int ret;
   369	
   370		if (!sg_is_last(req->src)) {
   371			src = kmalloc(req->src_len, GFP_KERNEL);
   372			if (!src)
   373				return -ENOMEM;
   374			scatterwalk_map_and_copy(src, req->src, 0, req->src_len, 0);
   375			in = src;
   376		} else {
   377			in = sg_virt(req->src);
   378		}
   379		if (!sg_is_last(req->dst)) {
   380			dst = kmalloc(req->dst_len, GFP_KERNEL);
   381			if (!dst) {
   382				kfree(src);
   383				return -ENOMEM;
   384			}
   385			out = dst;
   386		} else {
   387			out = sg_virt(req->dst);
   388		}
   389		params.key = (struct key *)key;
   390		params.in_len = req->src_len;
   391		params.out_len = req->dst_len;
 > 392		ret = decrypt_blob(&params, in, out);
   393		if (ret)
   394			goto free;
   395	
   396		if (dst)
   397			scatterwalk_map_and_copy(dst, req->dst, 0, req->dst_len, 1);
   398	free:
   399		kfree(src);
   400		kfree(dst);
   401		return ret;
   402	}
   403	
   404	static int asym_key_sign(const struct key *key, struct akcipher_request *req)
   405	{
 > 406		struct kernel_pkey_params params = {0};
   407		char *src = NULL, *dst = NULL, *in, *out;
   408		int ret;
   409	
   410		if (!sg_is_last(req->src)) {
   411			src = kmalloc(req->src_len, GFP_KERNEL);
   412			if (!src)
   413				return -ENOMEM;
   414			scatterwalk_map_and_copy(src, req->src, 0, req->src_len, 0);
   415			in = src;
   416		} else {
   417			in = sg_virt(req->src);
   418		}
   419		if (!sg_is_last(req->dst)) {
   420			dst = kmalloc(req->dst_len, GFP_KERNEL);
   421			if (!dst) {
   422				kfree(src);
   423				return -ENOMEM;
   424			}
   425			out = dst;
   426		} else {
   427			out = sg_virt(req->dst);
   428		}
   429		params.key = (struct key *)key;
   430		params.in_len = req->src_len;
   431		params.out_len = req->dst_len;
 > 432		ret = create_signature(&params, in, out);
   433		if (ret)
   434			goto free;
   435	
   436		if (dst)
   437			scatterwalk_map_and_copy(dst, req->dst, 0, req->dst_len, 1);
   438	free:
   439		kfree(src);
   440		kfree(dst);
   441		return ret;
   442	}
   443	
   444	static int asym_key_verify(const struct key *key, struct akcipher_request *req)
   445	{
   446		struct public_key_signature sig;
   447		char *src = NULL, *in, digest[20];
   448		int ret;
   449	
   450		if (!sg_is_last(req->src)) {
   451			src = kmalloc(req->src_len, GFP_KERNEL);
   452			if (!src)
   453				return -ENOMEM;
   454			scatterwalk_map_and_copy(src, req->src, 0, req->src_len, 0);
   455			in = src;
   456		} else {
   457			in = sg_virt(req->src);
   458		}
   459		sig.pkey_algo = "rsa";
 > 460		sig.encoding = "pkcs1";
   461		/* Need to find a way to pass the hash param */
   462		sig.hash_algo = "sha1";
   463		sig.digest_size = sizeof(digest);

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 54789 bytes --]

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v8 0/6] crypto: algif - add akcipher
  2016-06-23 22:55 [PATCH v8 0/6] crypto: algif - add akcipher Tadeusz Struk
@ 2016-06-24  6:07     ` Stephan Mueller
  2016-06-23 22:55 ` [PATCH v8 3/6] crypto: AF_ALG -- add asymmetric cipher interface Tadeusz Struk
                       ` (3 subsequent siblings)
  4 siblings, 0 replies; 20+ messages in thread
From: Stephan Mueller @ 2016-06-24  6:07 UTC (permalink / raw)
  To: Tadeusz Struk
  Cc: dhowells-H+wXaHxf7aLQT0dZR+AlfA,
	herbert-lOAM2aK0SrRLBo1qDEOMRrpzq4S04n8Q,
	linux-api-u79uwXL29TY76Z2rM5mHXA, marcel-kz+m5ild9QBg9hUCZPvPmw,
	mathew.j.martineau-VuQAYsv1563Yd54FQh9/CA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	keyrings-u79uwXL29TY76Z2rM5mHXA,
	linux-crypto-u79uwXL29TY76Z2rM5mHXA,
	dwmw2-wEGCiKHe2LqWVfeAwA7xHQ, davem-fT/PcQaiUtIeIZ0/mPfg9Q

Am Donnerstag, 23. Juni 2016, 15:55:26 schrieb Tadeusz Struk:

Hi Tadeusz,

> First four patches are a resend algif_akcipher from
> Stephan Mueller, with minor changes after rebase on top of 4.7-rc1.

The first four patches:

Acked-by: Stephan Mueller <smueller-T9tCv8IpfcWELgA04lAiVw@public.gmane.org>


Ciao
Stephan

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v8 0/6] crypto: algif - add akcipher
@ 2016-06-24  6:07     ` Stephan Mueller
  0 siblings, 0 replies; 20+ messages in thread
From: Stephan Mueller @ 2016-06-24  6:07 UTC (permalink / raw)
  To: Tadeusz Struk
  Cc: dhowells, herbert, linux-api, marcel, mathew.j.martineau,
	linux-kernel, keyrings, linux-crypto, dwmw2, davem

Am Donnerstag, 23. Juni 2016, 15:55:26 schrieb Tadeusz Struk:

Hi Tadeusz,

> First four patches are a resend algif_akcipher from
> Stephan Mueller, with minor changes after rebase on top of 4.7-rc1.

The first four patches:

Acked-by: Stephan Mueller <smueller@chronox.de>


Ciao
Stephan

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v8 6/6] crypto: AF_ALG - add support for key_id
  2016-06-23 22:55 ` [PATCH v8 6/6] crypto: AF_ALG - add support for key_id Tadeusz Struk
       [not found]   ` <146672255872.23101.10938182451423661314.stgit-mEAvsCHCuLl9qtVHHdszJa2pdiUAq4bhAL8bYrjMMd8@public.gmane.org>
@ 2016-06-29 18:43   ` Mat Martineau
  2016-07-05 20:27     ` Tadeusz Struk
  1 sibling, 1 reply; 20+ messages in thread
From: Mat Martineau @ 2016-06-29 18:43 UTC (permalink / raw)
  To: Tadeusz Struk
  Cc: dhowells, herbert, smueller, linux-api, marcel,
	mathew.j.martineau, linux-kernel, keyrings, linux-crypto, dwmw2,
	davem


Tadeusz,

On Thu, 23 Jun 2016, Tadeusz Struk wrote:

> This patch adds support for asymmetric key type to AF_ALG.
> It will work as follows: A new PF_ALG socket options are
> added on top of existing ALG_SET_KEY and ALG_SET_PUBKEY, namely
> ALG_SET_KEY_ID and ALG_SET_PUBKEY_ID for setting public and
> private keys respectively. When these new options will be used
> the user, instead of providing the key material, will provide a
> key id and the key itself will be obtained from kernel keyring
> subsystem. The user will use the standard tools (keyctl tool
> or the keyctl syscall) for key instantiation and to obtain the
> key id. The key id can also be obtained by reading the
> /proc/keys file.
>
> When a key corresponding to the given keyid is found, it is stored
> in the socket context and subsequent crypto operation invoked by the
> user will use the new asymmetric accessor functions instead of akcipher
> api. The asymmetric subtype can internally use akcipher api or
> invoke operations defined by a given subtype, depending on the
> key type.
>
> Signed-off-by: Tadeusz Struk <tadeusz.struk@intel.com>
> ---
> crypto/af_alg.c             |   10 ++
> crypto/algif_akcipher.c     |  212 ++++++++++++++++++++++++++++++++++++++++++-
> include/crypto/if_alg.h     |    1
> include/uapi/linux/if_alg.h |    2
> 4 files changed, 220 insertions(+), 5 deletions(-)
>
> diff --git a/crypto/algif_akcipher.c b/crypto/algif_akcipher.c
> index 2b8d37e..106f715 100644
> --- a/crypto/algif_akcipher.c
> +++ b/crypto/algif_akcipher.c
> +static int asym_key_verify(const struct key *key, struct akcipher_request *req)
> +{
> +	struct public_key_signature sig;
> +	char *src = NULL, *in, digest[20];
> +	int ret;
> +
> +	if (!sg_is_last(req->src)) {
> +		src = kmalloc(req->src_len, GFP_KERNEL);
> +		if (!src)
> +			return -ENOMEM;
> +		scatterwalk_map_and_copy(src, req->src, 0, req->src_len, 0);
> +		in = src;
> +	} else {
> +		in = sg_virt(req->src);
> +	}
> +	sig.pkey_algo = "rsa";
> +	sig.encoding = "pkcs1";
> +	/* Need to find a way to pass the hash param */

Comment still needed?

> +	sig.hash_algo = "sha1";
> +	sig.digest_size = sizeof(digest);
> +	sig.digest = digest;
> +	sig.s_size = req->src_len;
> +	sig.s = src;
> +	ret = verify_signature(key, &sig);
> +	if (!ret) {
> +		req->dst_len = sizeof(digest);

I think you fixed the BUG_ON() problem but there's still an issue with the 
handling of the digest. Check the use of sig->digest in 
public_key_verify_signature(), it's an input not an output. Right now it 
looks like 20 uninitialized bytes are compared with the computed digest 
within verify_signature, and then the unintialized bytes are copied to 
req->dst here.

With some modifications to public_key_verify_signature you could get the 
digest you need, but I'm not sure if verification with a hardware key 
(like a key in a TPM) can or can not provide the digest needed. Maybe this 
is why the verify_signature hook in struct asymmetric_key_subtype is 
optional.

> +		scatterwalk_map_and_copy(digest, req->dst, 0, req->dst_len, 1);
> +	}
> +	kfree(src);
> +	return ret;
> +}
> +

--
Mat Martineau
Intel OTC

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v8 6/6] crypto: AF_ALG - add support for key_id
  2016-06-29 18:43   ` Mat Martineau
@ 2016-07-05 20:27     ` Tadeusz Struk
  2016-07-06 19:38       ` Mat Martineau
  0 siblings, 1 reply; 20+ messages in thread
From: Tadeusz Struk @ 2016-07-05 20:27 UTC (permalink / raw)
  To: Mat Martineau
  Cc: dhowells, herbert, smueller, linux-api, marcel, linux-kernel,
	keyrings, linux-crypto, dwmw2, davem

Hi Mat,
On 06/29/2016 11:43 AM, Mat Martineau wrote:
>> +    ret = verify_signature(key, &sig);
>> +    if (!ret) {
>> +        req->dst_len = sizeof(digest);
> 
> I think you fixed the BUG_ON() problem but there's still an issue with
> the handling of the digest. Check the use of sig->digest in
> public_key_verify_signature(), it's an input not an output. Right now it
> looks like 20 uninitialized bytes are compared with the computed digest
> within verify_signature, and then the unintialized bytes are copied to
> req->dst here.
> 
> With some modifications to public_key_verify_signature you could get the
> digest you need, but I'm not sure if verification with a hardware key
> (like a key in a TPM) can or can not provide the digest needed. Maybe
> this is why the verify_signature hook in struct asymmetric_key_subtype
> is optional.
> 
>> +        scatterwalk_map_and_copy(digest, req->dst, 0, req->dst_len, 1);
>> +    } 

So it looks like the only thing that we need to return to the user in
this case is the return code. Do you agree?
Thanks,
-- 
TS

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v8 6/6] crypto: AF_ALG - add support for key_id
  2016-07-05 20:27     ` Tadeusz Struk
@ 2016-07-06 19:38       ` Mat Martineau
  2016-07-08 15:21         ` Tadeusz Struk
  0 siblings, 1 reply; 20+ messages in thread
From: Mat Martineau @ 2016-07-06 19:38 UTC (permalink / raw)
  To: Tadeusz Struk
  Cc: Mat Martineau, dhowells, herbert, smueller, linux-api, marcel,
	linux-kernel, keyrings, linux-crypto, dwmw2, davem


On Tue, 5 Jul 2016, Tadeusz Struk wrote:

> Hi Mat,
> On 06/29/2016 11:43 AM, Mat Martineau wrote:
>>> +    ret = verify_signature(key, &sig);
>>> +    if (!ret) {
>>> +        req->dst_len = sizeof(digest);
>>
>> I think you fixed the BUG_ON() problem but there's still an issue with
>> the handling of the digest. Check the use of sig->digest in
>> public_key_verify_signature(), it's an input not an output. Right now it
>> looks like 20 uninitialized bytes are compared with the computed digest
>> within verify_signature, and then the unintialized bytes are copied to
>> req->dst here.
>>
>> With some modifications to public_key_verify_signature you could get the
>> digest you need, but I'm not sure if verification with a hardware key
>> (like a key in a TPM) can or can not provide the digest needed. Maybe
>> this is why the verify_signature hook in struct asymmetric_key_subtype
>> is optional.
>>
>>> +        scatterwalk_map_and_copy(digest, req->dst, 0, req->dst_len, 1);
>>> +    }
>
> So it looks like the only thing that we need to return to the user in
> this case is the return code. Do you agree?

The way verify_signature is implemented today, the only output is the 
return code. For verify, maybe no read is required (just sendmsg() and 
check the return code).

But this isn't the extent of the problem: verify_signature needs both the 
signature to be verified and the expected hash as inputs. How is the 
expected hash provided? Would you include it as a cmsg header?
ALG_OP_VERIFY should have consistent inputs and outputs whether the key 
was set with ALG_SET_KEY_ID or ALG_SET_KEY.


--
Mat Martineau
Intel OTC

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v8 6/6] crypto: AF_ALG - add support for key_id
  2016-07-06 19:38       ` Mat Martineau
@ 2016-07-08 15:21         ` Tadeusz Struk
  2016-07-08 16:38           ` Mat Martineau
  0 siblings, 1 reply; 20+ messages in thread
From: Tadeusz Struk @ 2016-07-08 15:21 UTC (permalink / raw)
  To: Mat Martineau
  Cc: dhowells, herbert, smueller, linux-api, marcel, linux-kernel,
	keyrings, linux-crypto, dwmw2, davem

Hi Mat,
On 07/06/2016 12:38 PM, Mat Martineau wrote:
>> So it looks like the only thing that we need to return to the user in
>> this case is the return code. Do you agree?
> 
> The way verify_signature is implemented today, the only output is the
> return code. For verify, maybe no read is required (just sendmsg() and
> check the return code).
> 
> But this isn't the extent of the problem: verify_signature needs both
> the signature to be verified and the expected hash as inputs. How is the
> expected hash provided? Would you include it as a cmsg header?
> ALG_OP_VERIFY should have consistent inputs and outputs whether the key
> was set with ALG_SET_KEY_ID or ALG_SET_KEY.

The signature of verify_signature() is quite different from the other
new public key handlers, i.e. create_signature(), encrypt_blob(), and
decrypt_blob(). For verify_signature() we need the following parameters:
encrypted src, hash function to use, expected digest.
The expected digest could be optional if we would modify the
verify_signature() to return the decrypted buffer.
I think the best solution for now would be to just return -ENOPROTOOPT
for verify_signature in SET_KEY_ID mode.
All the four operations will be supported in the SET_KEY mode and
all but verify_signature() will be supported in the SET_KEY_ID mode.
This can added later if we will find a way to pass all parameters in a
consistent way. What do you think? If you are ok with that I will send a
new version soon.
Thanks,
-- 
TS

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v8 6/6] crypto: AF_ALG - add support for key_id
  2016-07-08 15:21         ` Tadeusz Struk
@ 2016-07-08 16:38           ` Mat Martineau
  2016-07-08 17:26             ` Tadeusz Struk
  0 siblings, 1 reply; 20+ messages in thread
From: Mat Martineau @ 2016-07-08 16:38 UTC (permalink / raw)
  To: Tadeusz Struk
  Cc: Mat Martineau, dhowells, herbert, smueller, linux-api, marcel,
	linux-kernel, keyrings, linux-crypto, dwmw2, davem


On Fri, 8 Jul 2016, Tadeusz Struk wrote:

> Hi Mat,
> On 07/06/2016 12:38 PM, Mat Martineau wrote:
>>> So it looks like the only thing that we need to return to the user in
>>> this case is the return code. Do you agree?
>>
>> The way verify_signature is implemented today, the only output is the
>> return code. For verify, maybe no read is required (just sendmsg() and
>> check the return code).
>>
>> But this isn't the extent of the problem: verify_signature needs both
>> the signature to be verified and the expected hash as inputs. How is the
>> expected hash provided? Would you include it as a cmsg header?
>> ALG_OP_VERIFY should have consistent inputs and outputs whether the key
>> was set with ALG_SET_KEY_ID or ALG_SET_KEY.
>
> The signature of verify_signature() is quite different from the other
> new public key handlers, i.e. create_signature(), encrypt_blob(), and
> decrypt_blob(). For verify_signature() we need the following parameters:
> encrypted src, hash function to use, expected digest.
> The expected digest could be optional if we would modify the
> verify_signature() to return the decrypted buffer.
> I think the best solution for now would be to just return -ENOPROTOOPT
> for verify_signature in SET_KEY_ID mode.
> All the four operations will be supported in the SET_KEY mode and
> all but verify_signature() will be supported in the SET_KEY_ID mode.
> This can added later if we will find a way to pass all parameters in a
> consistent way. What do you think? If you are ok with that I will send a
> new version soon.

Are the inputs and outputs defined for ALG_OP_VERIFY in SET_KEY mode going 
to work for hardware keys (like TPM) in SET_KEY_ID mode? That's needed if 
the verify SET_KEY_ID mode is to be added later.

--
Mat Martineau
Intel OTC

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v8 6/6] crypto: AF_ALG - add support for key_id
  2016-07-08 16:38           ` Mat Martineau
@ 2016-07-08 17:26             ` Tadeusz Struk
  0 siblings, 0 replies; 20+ messages in thread
From: Tadeusz Struk @ 2016-07-08 17:26 UTC (permalink / raw)
  To: Mat Martineau
  Cc: dhowells, herbert, smueller, linux-api, marcel, linux-kernel,
	keyrings, linux-crypto, dwmw2, davem

On 07/08/2016 09:38 AM, Mat Martineau wrote:
> Are the inputs and outputs defined for ALG_OP_VERIFY in SET_KEY mode
> going to work for hardware keys (like TPM) in SET_KEY_ID mode? That's
> needed if the verify SET_KEY_ID mode is to be added later.

Yes, we will just need to change the verify_signature() in public_key.c
to be consistent with the rest of handlers. What we need really is the
src (encrypted input), key (or key id), and an output buffer where we
can copy the result to.
Thanks,
-- 
TS

^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2016-07-08 17:26 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-06-23 22:55 [PATCH v8 0/6] crypto: algif - add akcipher Tadeusz Struk
2016-06-23 22:55 ` [PATCH v8 2/6] crypto: AF_ALG -- add setpubkey setsockopt call Tadeusz Struk
2016-06-23 22:55 ` [PATCH v8 3/6] crypto: AF_ALG -- add asymmetric cipher interface Tadeusz Struk
2016-06-23 22:55 ` [PATCH v8 4/6] crypto: algif_akcipher - enable compilation Tadeusz Struk
     [not found] ` <146672252642.23101.15972023870303797249.stgit-mEAvsCHCuLl9qtVHHdszJa2pdiUAq4bhAL8bYrjMMd8@public.gmane.org>
2016-06-23 22:55   ` [PATCH v8 1/6] crypto: AF_ALG -- add sign/verify API Tadeusz Struk
2016-06-23 22:55     ` Tadeusz Struk
2016-06-23 22:55   ` [PATCH v8 5/6] crypto: algif_akcipher - add ops_nokey Tadeusz Struk
2016-06-23 22:55     ` Tadeusz Struk
2016-06-24  6:07   ` [PATCH v8 0/6] crypto: algif - add akcipher Stephan Mueller
2016-06-24  6:07     ` Stephan Mueller
2016-06-23 22:55 ` [PATCH v8 6/6] crypto: AF_ALG - add support for key_id Tadeusz Struk
     [not found]   ` <146672255872.23101.10938182451423661314.stgit-mEAvsCHCuLl9qtVHHdszJa2pdiUAq4bhAL8bYrjMMd8@public.gmane.org>
2016-06-24  1:01     ` kbuild test robot
2016-06-24  1:01       ` kbuild test robot
2016-06-24  1:01       ` kbuild test robot
2016-06-29 18:43   ` Mat Martineau
2016-07-05 20:27     ` Tadeusz Struk
2016-07-06 19:38       ` Mat Martineau
2016-07-08 15:21         ` Tadeusz Struk
2016-07-08 16:38           ` Mat Martineau
2016-07-08 17:26             ` Tadeusz Struk

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.