These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / crypto / algif_aead.c
index 69abada..6d4d456 100644 (file)
@@ -13,6 +13,7 @@
  * any later version.
  */
 
+#include <crypto/aead.h>
 #include <crypto/scatterwalk.h>
 #include <crypto/if_alg.h>
 #include <linux/init.h>
@@ -71,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)
@@ -89,6 +90,7 @@ static void aead_put_sgl(struct sock *sk)
                put_page(sg_page(sg + i));
                sg_assign_page(sg + i, NULL);
        }
+       sg_init_table(sg, ALG_MAX_PAGES);
        sgl->cur = 0;
        ctx->used = 0;
        ctx->more = 0;
@@ -123,7 +125,7 @@ static int aead_wait_for_data(struct sock *sk, unsigned flags)
        if (flags & MSG_DONTWAIT)
                return -EAGAIN;
 
-       set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
+       sk_set_bit(SOCKWQ_ASYNC_WAITDATA, sk);
 
        for (;;) {
                if (signal_pending(current))
@@ -137,7 +139,7 @@ static int aead_wait_for_data(struct sock *sk, unsigned flags)
        }
        finish_wait(sk_sleep(sk), &wait);
 
-       clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
+       sk_clear_bit(SOCKWQ_ASYNC_WAITDATA, sk);
 
        return err;
 }
@@ -352,12 +354,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;
@@ -406,23 +404,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)) {
@@ -451,47 +439,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) :