diff options
author | Herbert Xu <herbert@gondor.apana.org.au> | 2015-05-27 17:24:41 +0800 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2015-05-28 11:23:21 +0800 |
commit | 19fa77522e45e384be0f0f93b10c928763460ae3 (patch) | |
tree | 55c94d34e0e61b480801a0eb7c41d9764c6b9245 /crypto/algif_aead.c | |
parent | a3f2185a29df084611641e964aa93d1a6ee2212c (diff) | |
download | lwn-19fa77522e45e384be0f0f93b10c928763460ae3.tar.gz lwn-19fa77522e45e384be0f0f93b10c928763460ae3.zip |
crypto: algif_aead - Switch to new AEAD interface
This patch makes use of the new AEAD interface which uses a single
SG list instead of separate lists for the AD and plain text.
Note that the user-space interface now requires both input and
output to be of the same length, and both must include space for
the AD as well as the authentication tag.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'crypto/algif_aead.c')
-rw-r--r-- | crypto/algif_aead.c | 66 |
1 files changed, 8 insertions, 58 deletions
diff --git a/crypto/algif_aead.c b/crypto/algif_aead.c index a55e4e6fa3d8..38a6cab7aeca 100644 --- a/crypto/algif_aead.c +++ b/crypto/algif_aead.c @@ -72,7 +72,7 @@ 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))); + return ctx->used >= ctx->aead_assoclen + as; } static void aead_put_sgl(struct sock *sk) @@ -353,12 +353,8 @@ static int aead_recvmsg(struct socket *sock, struct msghdr *msg, size_t ignored, struct sock *sk = sock->sk; struct alg_sock *ask = alg_sk(sk); struct aead_ctx *ctx = ask->private; - unsigned bs = crypto_aead_blocksize(crypto_aead_reqtfm(&ctx->aead_req)); unsigned as = crypto_aead_authsize(crypto_aead_reqtfm(&ctx->aead_req)); struct aead_sg_list *sgl = &ctx->tsgl; - struct scatterlist *sg = NULL; - struct scatterlist assoc[ALG_MAX_PAGES]; - size_t assoclen = 0; unsigned int i = 0; int err = -EINVAL; unsigned long used = 0; @@ -407,23 +403,13 @@ static int aead_recvmsg(struct socket *sock, struct msghdr *msg, size_t ignored, if (!aead_sufficient_data(ctx)) goto unlock; + outlen = used; + /* * The cipher operation input data is reduced by the associated data * length as this data is processed separately later on. */ - used -= ctx->aead_assoclen; - - if (ctx->enc) { - /* round up output buffer to multiple of block size */ - outlen = ((used + bs - 1) / bs * bs); - /* add the size needed for the auth tag to be created */ - outlen += as; - } else { - /* output data size is input without the authentication tag */ - outlen = used - as; - /* round up output buffer to multiple of block size */ - outlen = ((outlen + bs - 1) / bs * bs); - } + used -= ctx->aead_assoclen + (ctx->enc ? as : 0); /* convert iovecs of output buffers into scatterlists */ while (iov_iter_count(&msg->msg_iter)) { @@ -452,47 +438,11 @@ static int aead_recvmsg(struct socket *sock, struct msghdr *msg, size_t ignored, if (usedpages < outlen) goto unlock; - sg_init_table(assoc, ALG_MAX_PAGES); - assoclen = ctx->aead_assoclen; - /* - * Split scatterlist into two: first part becomes AD, second part - * is plaintext / ciphertext. The first part is assigned to assoc - * scatterlist. When this loop finishes, sg points to the start of the - * plaintext / ciphertext. - */ - for (i = 0; i < ctx->tsgl.cur; i++) { - sg = sgl->sg + i; - if (sg->length <= assoclen) { - /* AD is larger than one page */ - sg_set_page(assoc + i, sg_page(sg), - sg->length, sg->offset); - assoclen -= sg->length; - if (i >= ctx->tsgl.cur) - goto unlock; - } else if (!assoclen) { - /* current page is to start of plaintext / ciphertext */ - if (i) - /* AD terminates at page boundary */ - sg_mark_end(assoc + i - 1); - else - /* AD size is zero */ - sg_mark_end(assoc); - break; - } else { - /* AD does not terminate at page boundary */ - sg_set_page(assoc + i, sg_page(sg), - assoclen, sg->offset); - sg_mark_end(assoc + i); - /* plaintext / ciphertext starts after AD */ - sg->length -= assoclen; - sg->offset += assoclen; - break; - } - } + sg_mark_end(sgl->sg + sgl->cur - 1); - aead_request_set_assoc(&ctx->aead_req, assoc, ctx->aead_assoclen); - aead_request_set_crypt(&ctx->aead_req, sg, ctx->rsgl[0].sg, used, - ctx->iv); + aead_request_set_crypt(&ctx->aead_req, sgl->sg, ctx->rsgl[0].sg, + used, ctx->iv); + aead_request_set_ad(&ctx->aead_req, ctx->aead_assoclen); err = af_alg_wait_for_completion(ctx->enc ? crypto_aead_encrypt(&ctx->aead_req) : |