summaryrefslogtreecommitdiffstats
path: root/crypto/algif_aead.c
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2015-05-27 05:24:41 -0400
committerHerbert Xu <herbert@gondor.apana.org.au>2015-05-27 23:23:21 -0400
commit19fa77522e45e384be0f0f93b10c928763460ae3 (patch)
tree55c94d34e0e61b480801a0eb7c41d9764c6b9245 /crypto/algif_aead.c
parenta3f2185a29df084611641e964aa93d1a6ee2212c (diff)
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.c66
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)
72{ 72{
73 unsigned as = crypto_aead_authsize(crypto_aead_reqtfm(&ctx->aead_req)); 73 unsigned as = crypto_aead_authsize(crypto_aead_reqtfm(&ctx->aead_req));
74 74
75 return (ctx->used >= (ctx->aead_assoclen + (ctx->enc ? 0 : as))); 75 return ctx->used >= ctx->aead_assoclen + as;
76} 76}
77 77
78static void aead_put_sgl(struct sock *sk) 78static void aead_put_sgl(struct sock *sk)
@@ -353,12 +353,8 @@ static int aead_recvmsg(struct socket *sock, struct msghdr *msg, size_t ignored,
353 struct sock *sk = sock->sk; 353 struct sock *sk = sock->sk;
354 struct alg_sock *ask = alg_sk(sk); 354 struct alg_sock *ask = alg_sk(sk);
355 struct aead_ctx *ctx = ask->private; 355 struct aead_ctx *ctx = ask->private;
356 unsigned bs = crypto_aead_blocksize(crypto_aead_reqtfm(&ctx->aead_req));
357 unsigned as = crypto_aead_authsize(crypto_aead_reqtfm(&ctx->aead_req)); 356 unsigned as = crypto_aead_authsize(crypto_aead_reqtfm(&ctx->aead_req));
358 struct aead_sg_list *sgl = &ctx->tsgl; 357 struct aead_sg_list *sgl = &ctx->tsgl;
359 struct scatterlist *sg = NULL;
360 struct scatterlist assoc[ALG_MAX_PAGES];
361 size_t assoclen = 0;
362 unsigned int i = 0; 358 unsigned int i = 0;
363 int err = -EINVAL; 359 int err = -EINVAL;
364 unsigned long used = 0; 360 unsigned long used = 0;
@@ -407,23 +403,13 @@ static int aead_recvmsg(struct socket *sock, struct msghdr *msg, size_t ignored,
407 if (!aead_sufficient_data(ctx)) 403 if (!aead_sufficient_data(ctx))
408 goto unlock; 404 goto unlock;
409 405
406 outlen = used;
407
410 /* 408 /*
411 * The cipher operation input data is reduced by the associated data 409 * The cipher operation input data is reduced by the associated data
412 * length as this data is processed separately later on. 410 * length as this data is processed separately later on.
413 */ 411 */
414 used -= ctx->aead_assoclen; 412 used -= ctx->aead_assoclen + (ctx->enc ? as : 0);
415
416 if (ctx->enc) {
417 /* round up output buffer to multiple of block size */
418 outlen = ((used + bs - 1) / bs * bs);
419 /* add the size needed for the auth tag to be created */
420 outlen += as;
421 } else {
422 /* output data size is input without the authentication tag */
423 outlen = used - as;
424 /* round up output buffer to multiple of block size */
425 outlen = ((outlen + bs - 1) / bs * bs);
426 }
427 413
428 /* convert iovecs of output buffers into scatterlists */ 414 /* convert iovecs of output buffers into scatterlists */
429 while (iov_iter_count(&msg->msg_iter)) { 415 while (iov_iter_count(&msg->msg_iter)) {
@@ -452,47 +438,11 @@ static int aead_recvmsg(struct socket *sock, struct msghdr *msg, size_t ignored,
452 if (usedpages < outlen) 438 if (usedpages < outlen)
453 goto unlock; 439 goto unlock;
454 440
455 sg_init_table(assoc, ALG_MAX_PAGES); 441 sg_mark_end(sgl->sg + sgl->cur - 1);
456 assoclen = ctx->aead_assoclen;
457 /*
458 * Split scatterlist into two: first part becomes AD, second part
459 * is plaintext / ciphertext. The first part is assigned to assoc
460 * scatterlist. When this loop finishes, sg points to the start of the
461 * plaintext / ciphertext.
462 */
463 for (i = 0; i < ctx->tsgl.cur; i++) {
464 sg = sgl->sg + i;
465 if (sg->length <= assoclen) {
466 /* AD is larger than one page */
467 sg_set_page(assoc + i, sg_page(sg),
468 sg->length, sg->offset);
469 assoclen -= sg->length;
470 if (i >= ctx->tsgl.cur)
471 goto unlock;
472 } else if (!assoclen) {
473 /* current page is to start of plaintext / ciphertext */
474 if (i)
475 /* AD terminates at page boundary */
476 sg_mark_end(assoc + i - 1);
477 else
478 /* AD size is zero */
479 sg_mark_end(assoc);
480 break;
481 } else {
482 /* AD does not terminate at page boundary */
483 sg_set_page(assoc + i, sg_page(sg),
484 assoclen, sg->offset);
485 sg_mark_end(assoc + i);
486 /* plaintext / ciphertext starts after AD */
487 sg->length -= assoclen;
488 sg->offset += assoclen;
489 break;
490 }
491 }
492 442
493 aead_request_set_assoc(&ctx->aead_req, assoc, ctx->aead_assoclen); 443 aead_request_set_crypt(&ctx->aead_req, sgl->sg, ctx->rsgl[0].sg,
494 aead_request_set_crypt(&ctx->aead_req, sg, ctx->rsgl[0].sg, used, 444 used, ctx->iv);
495 ctx->iv); 445 aead_request_set_ad(&ctx->aead_req, ctx->aead_assoclen);
496 446
497 err = af_alg_wait_for_completion(ctx->enc ? 447 err = af_alg_wait_for_completion(ctx->enc ?
498 crypto_aead_encrypt(&ctx->aead_req) : 448 crypto_aead_encrypt(&ctx->aead_req) :