summaryrefslogtreecommitdiffstats
path: root/crypto/algif_aead.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2016-12-10 16:21:55 -0500
committerDavid S. Miller <davem@davemloft.net>2016-12-10 16:21:55 -0500
commit821781a9f40673c2aa0f29d9d8226ec320dff20c (patch)
treec9d5cb8a184fff84a9d841d8cb5da4b26be5c551 /crypto/algif_aead.c
parent3174fed9820edc95cff74ad0934c3240c7fb5115 (diff)
parent045169816b31b10faed984b01c390db1b32ee4c1 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Diffstat (limited to 'crypto/algif_aead.c')
-rw-r--r--crypto/algif_aead.c59
1 files changed, 37 insertions, 22 deletions
diff --git a/crypto/algif_aead.c b/crypto/algif_aead.c
index 8948392c0525..235f54d4f8a9 100644
--- a/crypto/algif_aead.c
+++ b/crypto/algif_aead.c
@@ -81,7 +81,11 @@ static inline bool aead_sufficient_data(struct aead_ctx *ctx)
81{ 81{
82 unsigned as = crypto_aead_authsize(crypto_aead_reqtfm(&ctx->aead_req)); 82 unsigned as = crypto_aead_authsize(crypto_aead_reqtfm(&ctx->aead_req));
83 83
84 return ctx->used >= ctx->aead_assoclen + as; 84 /*
85 * The minimum amount of memory needed for an AEAD cipher is
86 * the AAD and in case of decryption the tag.
87 */
88 return ctx->used >= ctx->aead_assoclen + (ctx->enc ? 0 : as);
85} 89}
86 90
87static void aead_reset_ctx(struct aead_ctx *ctx) 91static void aead_reset_ctx(struct aead_ctx *ctx)
@@ -415,7 +419,7 @@ static int aead_recvmsg_async(struct socket *sock, struct msghdr *msg,
415 unsigned int i, reqlen = GET_REQ_SIZE(tfm); 419 unsigned int i, reqlen = GET_REQ_SIZE(tfm);
416 int err = -ENOMEM; 420 int err = -ENOMEM;
417 unsigned long used; 421 unsigned long used;
418 size_t outlen; 422 size_t outlen = 0;
419 size_t usedpages = 0; 423 size_t usedpages = 0;
420 424
421 lock_sock(sk); 425 lock_sock(sk);
@@ -425,12 +429,15 @@ static int aead_recvmsg_async(struct socket *sock, struct msghdr *msg,
425 goto unlock; 429 goto unlock;
426 } 430 }
427 431
428 used = ctx->used;
429 outlen = used;
430
431 if (!aead_sufficient_data(ctx)) 432 if (!aead_sufficient_data(ctx))
432 goto unlock; 433 goto unlock;
433 434
435 used = ctx->used;
436 if (ctx->enc)
437 outlen = used + as;
438 else
439 outlen = used - as;
440
434 req = sock_kmalloc(sk, reqlen, GFP_KERNEL); 441 req = sock_kmalloc(sk, reqlen, GFP_KERNEL);
435 if (unlikely(!req)) 442 if (unlikely(!req))
436 goto unlock; 443 goto unlock;
@@ -444,7 +451,7 @@ static int aead_recvmsg_async(struct socket *sock, struct msghdr *msg,
444 aead_request_set_ad(req, ctx->aead_assoclen); 451 aead_request_set_ad(req, ctx->aead_assoclen);
445 aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, 452 aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
446 aead_async_cb, sk); 453 aead_async_cb, sk);
447 used -= ctx->aead_assoclen + (ctx->enc ? as : 0); 454 used -= ctx->aead_assoclen;
448 455
449 /* take over all tx sgls from ctx */ 456 /* take over all tx sgls from ctx */
450 areq->tsgl = sock_kmalloc(sk, sizeof(*areq->tsgl) * sgl->cur, 457 areq->tsgl = sock_kmalloc(sk, sizeof(*areq->tsgl) * sgl->cur,
@@ -460,7 +467,7 @@ static int aead_recvmsg_async(struct socket *sock, struct msghdr *msg,
460 areq->tsgls = sgl->cur; 467 areq->tsgls = sgl->cur;
461 468
462 /* create rx sgls */ 469 /* create rx sgls */
463 while (iov_iter_count(&msg->msg_iter)) { 470 while (outlen > usedpages && iov_iter_count(&msg->msg_iter)) {
464 size_t seglen = min_t(size_t, iov_iter_count(&msg->msg_iter), 471 size_t seglen = min_t(size_t, iov_iter_count(&msg->msg_iter),
465 (outlen - usedpages)); 472 (outlen - usedpages));
466 473
@@ -490,16 +497,14 @@ static int aead_recvmsg_async(struct socket *sock, struct msghdr *msg,
490 497
491 last_rsgl = rsgl; 498 last_rsgl = rsgl;
492 499
493 /* we do not need more iovecs as we have sufficient memory */
494 if (outlen <= usedpages)
495 break;
496
497 iov_iter_advance(&msg->msg_iter, err); 500 iov_iter_advance(&msg->msg_iter, err);
498 } 501 }
499 err = -EINVAL; 502
500 /* ensure output buffer is sufficiently large */ 503 /* ensure output buffer is sufficiently large */
501 if (usedpages < outlen) 504 if (usedpages < outlen) {
502 goto free; 505 err = -EINVAL;
506 goto unlock;
507 }
503 508
504 aead_request_set_crypt(req, areq->tsgl, areq->first_rsgl.sgl.sg, used, 509 aead_request_set_crypt(req, areq->tsgl, areq->first_rsgl.sgl.sg, used,
505 areq->iv); 510 areq->iv);
@@ -570,6 +575,7 @@ static int aead_recvmsg_sync(struct socket *sock, struct msghdr *msg, int flags)
570 goto unlock; 575 goto unlock;
571 } 576 }
572 577
578 /* data length provided by caller via sendmsg/sendpage */
573 used = ctx->used; 579 used = ctx->used;
574 580
575 /* 581 /*
@@ -584,16 +590,27 @@ static int aead_recvmsg_sync(struct socket *sock, struct msghdr *msg, int flags)
584 if (!aead_sufficient_data(ctx)) 590 if (!aead_sufficient_data(ctx))
585 goto unlock; 591 goto unlock;
586 592
587 outlen = used; 593 /*
594 * Calculate the minimum output buffer size holding the result of the
595 * cipher operation. When encrypting data, the receiving buffer is
596 * larger by the tag length compared to the input buffer as the
597 * encryption operation generates the tag. For decryption, the input
598 * buffer provides the tag which is consumed resulting in only the
599 * plaintext without a buffer for the tag returned to the caller.
600 */
601 if (ctx->enc)
602 outlen = used + as;
603 else
604 outlen = used - as;
588 605
589 /* 606 /*
590 * The cipher operation input data is reduced by the associated data 607 * The cipher operation input data is reduced by the associated data
591 * length as this data is processed separately later on. 608 * length as this data is processed separately later on.
592 */ 609 */
593 used -= ctx->aead_assoclen + (ctx->enc ? as : 0); 610 used -= ctx->aead_assoclen;
594 611
595 /* convert iovecs of output buffers into scatterlists */ 612 /* convert iovecs of output buffers into scatterlists */
596 while (iov_iter_count(&msg->msg_iter)) { 613 while (outlen > usedpages && iov_iter_count(&msg->msg_iter)) {
597 size_t seglen = min_t(size_t, iov_iter_count(&msg->msg_iter), 614 size_t seglen = min_t(size_t, iov_iter_count(&msg->msg_iter),
598 (outlen - usedpages)); 615 (outlen - usedpages));
599 616
@@ -620,16 +637,14 @@ static int aead_recvmsg_sync(struct socket *sock, struct msghdr *msg, int flags)
620 637
621 last_rsgl = rsgl; 638 last_rsgl = rsgl;
622 639
623 /* we do not need more iovecs as we have sufficient memory */
624 if (outlen <= usedpages)
625 break;
626 iov_iter_advance(&msg->msg_iter, err); 640 iov_iter_advance(&msg->msg_iter, err);
627 } 641 }
628 642
629 err = -EINVAL;
630 /* ensure output buffer is sufficiently large */ 643 /* ensure output buffer is sufficiently large */
631 if (usedpages < outlen) 644 if (usedpages < outlen) {
645 err = -EINVAL;
632 goto unlock; 646 goto unlock;
647 }
633 648
634 sg_mark_end(sgl->sg + sgl->cur - 1); 649 sg_mark_end(sgl->sg + sgl->cur - 1);
635 aead_request_set_crypt(&ctx->aead_req, sgl->sg, ctx->first_rsgl.sgl.sg, 650 aead_request_set_crypt(&ctx->aead_req, sgl->sg, ctx->first_rsgl.sgl.sg,