diff options
author | David S. Miller <davem@davemloft.net> | 2016-12-10 16:21:55 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-12-10 16:21:55 -0500 |
commit | 821781a9f40673c2aa0f29d9d8226ec320dff20c (patch) | |
tree | c9d5cb8a184fff84a9d841d8cb5da4b26be5c551 /crypto/algif_aead.c | |
parent | 3174fed9820edc95cff74ad0934c3240c7fb5115 (diff) | |
parent | 045169816b31b10faed984b01c390db1b32ee4c1 (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.c | 59 |
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 | ||
87 | static void aead_reset_ctx(struct aead_ctx *ctx) | 91 | static 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, |