Re: [PATCH v13 1/2] crypto: AF_ALG: add AEAD support

2015-06-11 Thread Stephan Mueller
Am Thursday 11 June 2015, 15:59:29 schrieb Tadeusz Struk:

Hi Tadeusz,

>Hi Stephan,
>
>On 02/28/2015 11:50 AM, Stephan Mueller wrote:
>> +err = af_alg_wait_for_completion(ctx->enc ?
>> + crypto_aead_encrypt(>aead_req) :
>> + crypto_aead_decrypt(>aead_req),
>> + >completion);
>> +
>> +if (err) {
>> +/* EBADMSG implies a valid cipher operation took place */
>> +if (err == -EBADMSG)
>> +aead_put_sgl(sk);
>> +goto unlock;
>
>Shouldn't we free the TX sgl regardless of the error was?
>Or do we expect that the user will try to read again and it will be Ok the
>second time? Hope you still remember :)

It is the latter: as the crypto was not completed properly, leave the data in 
memory. This may allow a user to send more data if he needs to for completing 
the AEAD operation.

Ciao
Stephan
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v13 1/2] crypto: AF_ALG: add AEAD support

2015-06-11 Thread Tadeusz Struk
Hi Stephan,
On 02/28/2015 11:50 AM, Stephan Mueller wrote:
> + err = af_alg_wait_for_completion(ctx->enc ?
> +  crypto_aead_encrypt(>aead_req) :
> +  crypto_aead_decrypt(>aead_req),
> +  >completion);
> +
> + if (err) {
> + /* EBADMSG implies a valid cipher operation took place */
> + if (err == -EBADMSG)
> + aead_put_sgl(sk);
> + goto unlock;

Shouldn't we free the TX sgl regardless of the error was?
Or do we expect that the user will try to read again and it will be Ok the 
second time?
Hope you still remember :)

> + }
> +
> + aead_put_sgl(sk);
> +
> + err = 0;
> +
> +unlock:
> + for (i = 0; i < cnt; i++)
> + af_alg_free_sg(>rsgl[i]);
> +
> + aead_wmem_wakeup(sk);
> + release_sock(sk);
> +
> + return err ? err : outlen;
> +}

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v13 1/2] crypto: AF_ALG: add AEAD support

2015-06-11 Thread Tadeusz Struk
Hi Stephan,
On 02/28/2015 11:50 AM, Stephan Mueller wrote:
 + err = af_alg_wait_for_completion(ctx-enc ?
 +  crypto_aead_encrypt(ctx-aead_req) :
 +  crypto_aead_decrypt(ctx-aead_req),
 +  ctx-completion);
 +
 + if (err) {
 + /* EBADMSG implies a valid cipher operation took place */
 + if (err == -EBADMSG)
 + aead_put_sgl(sk);
 + goto unlock;

Shouldn't we free the TX sgl regardless of the error was?
Or do we expect that the user will try to read again and it will be Ok the 
second time?
Hope you still remember :)

 + }
 +
 + aead_put_sgl(sk);
 +
 + err = 0;
 +
 +unlock:
 + for (i = 0; i  cnt; i++)
 + af_alg_free_sg(ctx-rsgl[i]);
 +
 + aead_wmem_wakeup(sk);
 + release_sock(sk);
 +
 + return err ? err : outlen;
 +}

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v13 1/2] crypto: AF_ALG: add AEAD support

2015-06-11 Thread Stephan Mueller
Am Thursday 11 June 2015, 15:59:29 schrieb Tadeusz Struk:

Hi Tadeusz,

Hi Stephan,

On 02/28/2015 11:50 AM, Stephan Mueller wrote:
 +err = af_alg_wait_for_completion(ctx-enc ?
 + crypto_aead_encrypt(ctx-aead_req) :
 + crypto_aead_decrypt(ctx-aead_req),
 + ctx-completion);
 +
 +if (err) {
 +/* EBADMSG implies a valid cipher operation took place */
 +if (err == -EBADMSG)
 +aead_put_sgl(sk);
 +goto unlock;

Shouldn't we free the TX sgl regardless of the error was?
Or do we expect that the user will try to read again and it will be Ok the
second time? Hope you still remember :)

It is the latter: as the crypto was not completed properly, leave the data in 
memory. This may allow a user to send more data if he needs to for completing 
the AEAD operation.

Ciao
Stephan
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v13 1/2] crypto: AF_ALG: add AEAD support

2015-02-28 Thread Stephan Mueller
This patch adds the AEAD support for AF_ALG.

The implementation is based on algif_skcipher, but contains heavy
modifications to streamline the interface for AEAD uses.

To use AEAD, the user space consumer has to use the salg_type named
"aead".

The AEAD implementation includes some overhead to calculate the size of
the ciphertext, because the AEAD implementation of the kernel crypto API
makes implied assumption on the location of the authentication tag. When
performing an encryption, the tag will be added to the created
ciphertext (note, the tag is placed adjacent to the ciphertext). For
decryption, the caller must hand in the ciphertext with the tag appended
to the ciphertext. Therefore, the selection of the used memory
needs to add/subtract the tag size from the source/destination buffers
depending on the encryption type. The code is provided with comments
explaining when and how that operation is performed.

A fully working example using all aspects of AEAD is provided at
http://www.chronox.de/libkcapi.html

Signed-off-by: Stephan Mueller 
---
 crypto/algif_aead.c | 666 
 1 file changed, 666 insertions(+)
 create mode 100644 crypto/algif_aead.c

diff --git a/crypto/algif_aead.c b/crypto/algif_aead.c
new file mode 100644
index 000..527d27b
--- /dev/null
+++ b/crypto/algif_aead.c
@@ -0,0 +1,666 @@
+/*
+ * algif_aead: User-space interface for AEAD algorithms
+ *
+ * Copyright (C) 2014, Stephan Mueller 
+ *
+ * This file provides the user-space API for AEAD ciphers.
+ *
+ * This file is derived from algif_skcipher.c.
+ *
+ * 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 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+struct aead_sg_list {
+   unsigned int cur;
+   struct scatterlist sg[ALG_MAX_PAGES];
+};
+
+struct aead_ctx {
+   struct aead_sg_list tsgl;
+   /*
+* RSGL_MAX_ENTRIES is an artificial limit where user space at maximum
+* can cause the kernel to allocate RSGL_MAX_ENTRIES * ALG_MAX_PAGES
+* bytes
+*/
+#define RSGL_MAX_ENTRIES ALG_MAX_PAGES
+   struct af_alg_sgl rsgl[RSGL_MAX_ENTRIES];
+
+   void *iv;
+
+   struct af_alg_completion completion;
+
+   unsigned long used;
+
+   unsigned int len;
+   bool more;
+   bool merge;
+   bool enc;
+
+   size_t aead_assoclen;
+   struct aead_request aead_req;
+};
+
+static inline int aead_sndbuf(struct sock *sk)
+{
+   struct alg_sock *ask = alg_sk(sk);
+   struct aead_ctx *ctx = ask->private;
+
+   return max_t(int, max_t(int, sk->sk_sndbuf & PAGE_MASK, PAGE_SIZE) -
+ ctx->used, 0);
+}
+
+static inline bool aead_writable(struct sock *sk)
+{
+   return PAGE_SIZE <= aead_sndbuf(sk);
+}
+
+static inline bool aead_sufficient_data(struct aead_ctx *ctx)
+{
+   unsigned as = crypto_aead_authsize(crypto_aead_reqtfm(>aead_req));
+
+   return (ctx->used >= (ctx->aead_assoclen + (ctx->enc ? 0 : as)));
+}
+
+static void aead_put_sgl(struct sock *sk)
+{
+   struct alg_sock *ask = alg_sk(sk);
+   struct aead_ctx *ctx = ask->private;
+   struct aead_sg_list *sgl = >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);
+   }
+   sgl->cur = 0;
+   ctx->used = 0;
+   ctx->more = 0;
+   ctx->merge = 0;
+}
+
+static void aead_wmem_wakeup(struct sock *sk)
+{
+   struct socket_wq *wq;
+
+   if (!aead_writable(sk))
+   return;
+
+   rcu_read_lock();
+   wq = rcu_dereference(sk->sk_wq);
+   if (wq_has_sleeper(wq))
+   wake_up_interruptible_sync_poll(>wait, POLLIN |
+  POLLRDNORM |
+  POLLRDBAND);
+   sk_wake_async(sk, SOCK_WAKE_WAITD, POLL_IN);
+   rcu_read_unlock();
+}
+
+static int aead_wait_for_data(struct sock *sk, unsigned flags)
+{
+   struct alg_sock *ask = alg_sk(sk);
+   struct aead_ctx *ctx = ask->private;
+   long timeout;
+   DEFINE_WAIT(wait);
+   int err = -ERESTARTSYS;
+
+   if (flags & MSG_DONTWAIT)
+   return -EAGAIN;
+
+   set_bit(SOCK_ASYNC_WAITDATA, >sk_socket->flags);
+
+   for (;;) {
+   if (signal_pending(current))
+   break;
+   prepare_to_wait(sk_sleep(sk), , TASK_INTERRUPTIBLE);
+   timeout = MAX_SCHEDULE_TIMEOUT;
+   if (sk_wait_event(sk, , !ctx->more)) {
+   

[PATCH v13 1/2] crypto: AF_ALG: add AEAD support

2015-02-28 Thread Stephan Mueller
This patch adds the AEAD support for AF_ALG.

The implementation is based on algif_skcipher, but contains heavy
modifications to streamline the interface for AEAD uses.

To use AEAD, the user space consumer has to use the salg_type named
aead.

The AEAD implementation includes some overhead to calculate the size of
the ciphertext, because the AEAD implementation of the kernel crypto API
makes implied assumption on the location of the authentication tag. When
performing an encryption, the tag will be added to the created
ciphertext (note, the tag is placed adjacent to the ciphertext). For
decryption, the caller must hand in the ciphertext with the tag appended
to the ciphertext. Therefore, the selection of the used memory
needs to add/subtract the tag size from the source/destination buffers
depending on the encryption type. The code is provided with comments
explaining when and how that operation is performed.

A fully working example using all aspects of AEAD is provided at
http://www.chronox.de/libkcapi.html

Signed-off-by: Stephan Mueller smuel...@chronox.de
---
 crypto/algif_aead.c | 666 
 1 file changed, 666 insertions(+)
 create mode 100644 crypto/algif_aead.c

diff --git a/crypto/algif_aead.c b/crypto/algif_aead.c
new file mode 100644
index 000..527d27b
--- /dev/null
+++ b/crypto/algif_aead.c
@@ -0,0 +1,666 @@
+/*
+ * algif_aead: User-space interface for AEAD algorithms
+ *
+ * Copyright (C) 2014, Stephan Mueller smuel...@chronox.de
+ *
+ * This file provides the user-space API for AEAD ciphers.
+ *
+ * This file is derived from algif_skcipher.c.
+ *
+ * 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/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 aead_sg_list {
+   unsigned int cur;
+   struct scatterlist sg[ALG_MAX_PAGES];
+};
+
+struct aead_ctx {
+   struct aead_sg_list tsgl;
+   /*
+* RSGL_MAX_ENTRIES is an artificial limit where user space at maximum
+* can cause the kernel to allocate RSGL_MAX_ENTRIES * ALG_MAX_PAGES
+* bytes
+*/
+#define RSGL_MAX_ENTRIES ALG_MAX_PAGES
+   struct af_alg_sgl rsgl[RSGL_MAX_ENTRIES];
+
+   void *iv;
+
+   struct af_alg_completion completion;
+
+   unsigned long used;
+
+   unsigned int len;
+   bool more;
+   bool merge;
+   bool enc;
+
+   size_t aead_assoclen;
+   struct aead_request aead_req;
+};
+
+static inline int aead_sndbuf(struct sock *sk)
+{
+   struct alg_sock *ask = alg_sk(sk);
+   struct aead_ctx *ctx = ask-private;
+
+   return max_t(int, max_t(int, sk-sk_sndbuf  PAGE_MASK, PAGE_SIZE) -
+ ctx-used, 0);
+}
+
+static inline bool aead_writable(struct sock *sk)
+{
+   return PAGE_SIZE = aead_sndbuf(sk);
+}
+
+static inline bool aead_sufficient_data(struct aead_ctx *ctx)
+{
+   unsigned as = crypto_aead_authsize(crypto_aead_reqtfm(ctx-aead_req));
+
+   return (ctx-used = (ctx-aead_assoclen + (ctx-enc ? 0 : as)));
+}
+
+static void aead_put_sgl(struct sock *sk)
+{
+   struct alg_sock *ask = alg_sk(sk);
+   struct aead_ctx *ctx = ask-private;
+   struct aead_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);
+   }
+   sgl-cur = 0;
+   ctx-used = 0;
+   ctx-more = 0;
+   ctx-merge = 0;
+}
+
+static void aead_wmem_wakeup(struct sock *sk)
+{
+   struct socket_wq *wq;
+
+   if (!aead_writable(sk))
+   return;
+
+   rcu_read_lock();
+   wq = rcu_dereference(sk-sk_wq);
+   if (wq_has_sleeper(wq))
+   wake_up_interruptible_sync_poll(wq-wait, POLLIN |
+  POLLRDNORM |
+  POLLRDBAND);
+   sk_wake_async(sk, SOCK_WAKE_WAITD, POLL_IN);
+   rcu_read_unlock();
+}
+
+static int aead_wait_for_data(struct sock *sk, unsigned flags)
+{
+   struct alg_sock *ask = alg_sk(sk);
+   struct aead_ctx *ctx = ask-private;
+   long timeout;
+   DEFINE_WAIT(wait);
+   int err = -ERESTARTSYS;
+
+   if (flags  MSG_DONTWAIT)
+   return -EAGAIN;
+
+   set_bit(SOCK_ASYNC_WAITDATA, sk-sk_socket-flags);
+
+   for (;;) {
+   if (signal_pending(current))
+   break;
+   prepare_to_wait(sk_sleep(sk), wait,