Re: [PATCH v5 3/8] crypto: AF_ALG: add AEAD support

2014-12-25 Thread Stephan Mueller
Am Mittwoch, 24. Dezember 2014, 09:54:33 schrieb Stephan Mueller:

Hi Stephan,

 Am Mittwoch, 24. Dezember 2014, 07:24:01 schrieb Herbert Xu:
 
 Hi Herbert,
 
  On Tue, Dec 23, 2014 at 03:52:27PM +0100, Stephan Mueller wrote:
   Am Dienstag, 23. Dezember 2014, 22:56:26 schrieb Herbert Xu:
In fact AEAD is rather awkward because you need to do everything
in one go.  Perhaps we could adapt our kernel interface to allow
partial AEAD operations?
   
   I am not sure what you are referring to. The invocation does not need to
   be in one go. You can have arbitrary number of sendmsg calls. But all
   input data needs to be supplied before you call recvmsg.
  
  What I mean is that unlike skcipher we cannot precede until we
  have the complete input.  So you cannot begin recvmsg until all
  input has been sent.
 
 That is right, but isn't that the nature of AEAD ciphers in general? Even if
 you are in the kernel, you need to have all scatter lists together for one
 invocation of the AEAD cipher.
 
 In case of a threaded application, the recvmsg does not start until all data
 is in, marked with the missing MSG_MORE -- see aead_readable.
 
 All we can do is allow the user to use multiple system calls to collect all
 data before the AEAD operation takes place.
 
 Or do you see another way on how to invoke the AEAD operation in a different
 manner?
 
 The only item that I see that could be made better is the output side:
 currently the code allows only one and exactly one iovec to point to the
 output buffer. I would like to allow multiple iovec buffers that are filled
 with the output of one invocation of the AEAD operation. However, to avoid
 making a kernel-internal scratch buffer, I would need to somehow link the
 kernel-internal scatter lists with the iovec buffers. That only works when
 walking the iovec lists first and call af_alg_make_sg with every iovec entry
 and create the kernel-internal scatterlist representation. That is followed
 by the AEAD operation on the scatterlist.
 
 If we agree on walking the iovec list first, then the question arises how
 many iovec list entries we allow at max. Is 16 entries a sensible value?

I would be now ready with a new release of the AEAD and RNG interface patches 
against the current code base (including the iov_iter update). Though, I would 
like to get your answer regarding your concerns.

Thanks.

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


Re: [PATCH v5 3/8] crypto: AF_ALG: add AEAD support

2014-12-25 Thread Herbert Xu
On Wed, Dec 24, 2014 at 09:54:33AM +0100, Stephan Mueller wrote:
 
 That is right, but isn't that the nature of AEAD ciphers in general? Even if 
 you are in the kernel, you need to have all scatter lists together for one 
 invocation of the AEAD cipher.

It's actually only the nature of certain algorithms like CCM which
requires the total length to start the operation.  Most AEAD
algorithms can be implemented in a way that allows piecemeal
operation.  However, as the only users of AEAD is IPsec, it's
probably not worth adding more complexity for now.

So let's proceed with your current solution.

Thanks,
-- 
Email: Herbert Xu herb...@gondor.apana.org.au
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
--
To unsubscribe from this list: send the line unsubscribe linux-crypto in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v5 3/8] crypto: AF_ALG: add AEAD support

2014-12-23 Thread Stephan Mueller
Am Montag, 22. Dezember 2014, 22:23:41 schrieb Herbert Xu:

Hi Herbert,

 On Sun, Dec 07, 2014 at 11:22:30PM +0100, Stephan Mueller wrote:
  +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 ? : as ));
 
 Is this supposed to be
 
   return (ctx-used = (ctx-aead_assoclen + (ctx-enc ?: as)));

Thanks, will be fixed in the next iteration
 
  +static int aead_recvmsg(struct kiocb *unused, struct socket *sock,
  +   struct msghdr *msg, size_t ignored, int flags)
  +{
 
 ...
 
  +   err = -ENOMEM;
  +   if (!aead_sufficient_data(ctx))
  +   goto unlock;
 
 You should just block if there is insufficient input.
 
I do not concur here due to the following:

- the check aead_readable() immediately before this check implements the 
blocking if we do not have sufficient data *and* more data is to be expected

- this very check for aead_sufficient_data() comes into play if the caller 
does not have more data (i.e. ctx-more is zero). In this case, more data is 
not to be expected and we cannot wait as this would be a deadlock in user 
space.

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


Re: [PATCH v5 3/8] crypto: AF_ALG: add AEAD support

2014-12-23 Thread Stephan Mueller
Am Dienstag, 23. Dezember 2014, 22:56:26 schrieb Herbert Xu:

Hi Herbert,

 On Tue, Dec 23, 2014 at 09:14:43AM +0100, Stephan Mueller wrote:
  - the check aead_readable() immediately before this check implements the
  blocking if we do not have sufficient data *and* more data is to be
  expected
 Good point.
 
 In fact AEAD is rather awkward because you need to do everything
 in one go.  Perhaps we could adapt our kernel interface to allow
 partial AEAD operations?


I am not sure what you are referring to. The invocation does not need to be in 
one go. You can have arbitrary number of sendmsg calls. But all input data 
needs to be supplied before you call recvmsg.

Please see my test code that implements the following call sequence using the 
libkcapi wrapper API calls where I dissect the data to be sent to the kernel 
for testing purposes:

if (cavs_test-enc) {
/* send assoc with init call */
ret = kcapi_aead_stream_init_enc(handle, iov, 1);
if (0  ret) {
printf(Initialization of cipher buffer failed\n);
goto out;
}
/* send plaintext with last call */
iov.iov_base = cavs_test-pt;
iov.iov_len = cavs_test-ptlen;
ret = kcapi_aead_stream_update_last(handle, iov, 1);
if (0  ret) {
printf(Sending last update buffer failed\n);
goto out;
}
ret = kcapi_aead_stream_op(handle, outiov, 1);
} else {
/* send assoc with init call */
ret = kcapi_aead_stream_init_dec(handle, iov, 1);
if (0  ret) {
printf(Initialization of cipher buffer failed\n);
goto out;
}
/* send plaintext with intermediary call */
iov.iov_base = cavs_test-ct;
iov.iov_len = cavs_test-ctlen;
ret = kcapi_aead_stream_update(handle, iov, 1);
if (0  ret) {
printf(Sending update buffer failed\n);
goto out;
}
/* send tag with last send call */
iov.iov_base = cavs_test-tag;
iov.iov_len = cavs_test-taglen;
ret = kcapi_aead_stream_update_last(handle, iov, 1);
if (0  ret) {
printf(Sending last update buffer failed\n);
goto out;
}
ret = kcapi_aead_stream_op(handle, outiov, 1);
}

Every call to kcapi_aead_stream_init_dec / kcapi_aead_stream_update / 
kcapi_aead_stream_update_last invokes one sendmsg syscall.

In essence, kcapi_aead_stream_update can be invoked with every byte you want 
to add to the message stream. This stream API of libkcapi is logially 
equivalent to the init/update/final of message digests.
 
 I want to be very careful before we pin down our user-space
 interface since that's something that we cannot easily change
 while the kernel interface can be modified at any time.

I am fully with you and try to patiently present solutions.
 
 Thanks,


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


Re: [PATCH v5 3/8] crypto: AF_ALG: add AEAD support

2014-12-23 Thread Herbert Xu
On Tue, Dec 23, 2014 at 03:52:27PM +0100, Stephan Mueller wrote:
 Am Dienstag, 23. Dezember 2014, 22:56:26 schrieb Herbert Xu:

  In fact AEAD is rather awkward because you need to do everything
  in one go.  Perhaps we could adapt our kernel interface to allow
  partial AEAD operations?
 
 
 I am not sure what you are referring to. The invocation does not need to be 
 in 
 one go. You can have arbitrary number of sendmsg calls. But all input data 
 needs to be supplied before you call recvmsg.

What I mean is that unlike skcipher we cannot precede until we
have the complete input.  So you cannot begin recvmsg until all
input has been sent.

Cheers,
-- 
Email: Herbert Xu herb...@gondor.apana.org.au
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
--
To unsubscribe from this list: send the line unsubscribe linux-crypto in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v5 3/8] crypto: AF_ALG: add AEAD support

2014-12-22 Thread Herbert Xu
On Sun, Dec 07, 2014 at 11:22:30PM +0100, Stephan Mueller wrote:

 +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 ? : as ));

Is this supposed to be

return (ctx-used = (ctx-aead_assoclen + (ctx-enc ?: as)));

 +static int aead_recvmsg(struct kiocb *unused, struct socket *sock,
 + struct msghdr *msg, size_t ignored, int flags)
 +{

...

 + err = -ENOMEM;
 + if (!aead_sufficient_data(ctx))
 + goto unlock;

You should just block if there is insufficient input.

Cheers,
-- 
Email: Herbert Xu herb...@gondor.apana.org.au
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
--
To unsubscribe from this list: send the line unsubscribe linux-crypto in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v5 3/8] crypto: AF_ALG: add AEAD support

2014-12-07 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 | 650 
 1 file changed, 650 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..97d6a0e
--- /dev/null
+++ b/crypto/algif_aead.c
@@ -0,0 +1,650 @@
+/*
+ * algif_aeadr: 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;
+   struct af_alg_sgl rsgl;
+
+   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 ? : as ));
+}
+static inline bool aead_readable(struct aead_ctx *ctx)
+{
+   /*
+* Ensure that assoc data is present, the plaintext / ciphertext
+* is non-zero and that the authentication tag is also present
+* in case of a decryption operation.
+*
+* Also, wait until all data is received before processing.
+*/
+   return (aead_sufficient_data(ctx)  !ctx-more);
+}
+
+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 int aead_wait_for_wmem(struct sock *sk, unsigned flags)
+{
+   long timeout;
+   DEFINE_WAIT(wait);
+   int err = -ERESTARTSYS;
+
+   if (flags  MSG_DONTWAIT)
+   return -EAGAIN;
+
+   set_bit(SOCK_ASYNC_NOSPACE, 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, aead_writable(sk))) {
+   err = 0;
+   break;
+   }
+   }
+   finish_wait(sk_sleep(sk), wait);
+
+   return err;
+}
+
+static void aead_wmem_wakeup(struct sock *sk)
+{
+   struct socket_wq *wq;
+
+   if (!aead_writable(sk))
+   return;
+
+   rcu_read_lock();
+