Re: [PATCH v5 3/8] crypto: AF_ALG: add AEAD support
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
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
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
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
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
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
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(); +