Merge 4.14.105 into android-4.14-p
[GitHub/moto-9609/android_kernel_motorola_exynos9610.git] / crypto / skcipher.c
index d5692e35fab1f069376f7c54358ff5e5f0cb352e..e319421a32e7de4fabadddf116f64eeea790a113 100644 (file)
@@ -95,7 +95,7 @@ static inline u8 *skcipher_get_spot(u8 *start, unsigned int len)
        return max(start, end_page);
 }
 
-static int skcipher_done_slow(struct skcipher_walk *walk, unsigned int bsize)
+static void skcipher_done_slow(struct skcipher_walk *walk, unsigned int bsize)
 {
        u8 *addr;
 
@@ -103,23 +103,24 @@ static int skcipher_done_slow(struct skcipher_walk *walk, unsigned int bsize)
        addr = skcipher_get_spot(addr, bsize);
        scatterwalk_copychunks(addr, &walk->out, bsize,
                               (walk->flags & SKCIPHER_WALK_PHYS) ? 2 : 1);
-       return 0;
 }
 
 int skcipher_walk_done(struct skcipher_walk *walk, int err)
 {
-       unsigned int n = walk->nbytes - err;
-       unsigned int nbytes;
+       unsigned int n; /* bytes processed */
+       bool more;
+
+       if (unlikely(err < 0))
+               goto finish;
 
-       nbytes = walk->total - n;
+       n = walk->nbytes - err;
+       walk->total -= n;
+       more = (walk->total != 0);
 
-       if (unlikely(err < 0)) {
-               nbytes = 0;
-               n = 0;
-       } else if (likely(!(walk->flags & (SKCIPHER_WALK_PHYS |
-                                          SKCIPHER_WALK_SLOW |
-                                          SKCIPHER_WALK_COPY |
-                                          SKCIPHER_WALK_DIFF)))) {
+       if (likely(!(walk->flags & (SKCIPHER_WALK_PHYS |
+                                   SKCIPHER_WALK_SLOW |
+                                   SKCIPHER_WALK_COPY |
+                                   SKCIPHER_WALK_DIFF)))) {
 unmap_src:
                skcipher_unmap_src(walk);
        } else if (walk->flags & SKCIPHER_WALK_DIFF) {
@@ -131,28 +132,28 @@ unmap_src:
                skcipher_unmap_dst(walk);
        } else if (unlikely(walk->flags & SKCIPHER_WALK_SLOW)) {
                if (WARN_ON(err)) {
+                       /* unexpected case; didn't process all bytes */
                        err = -EINVAL;
-                       nbytes = 0;
-               } else
-                       n = skcipher_done_slow(walk, n);
+                       goto finish;
+               }
+               skcipher_done_slow(walk, n);
+               goto already_advanced;
        }
 
-       if (err > 0)
-               err = 0;
-
-       walk->total = nbytes;
-       walk->nbytes = nbytes;
-
        scatterwalk_advance(&walk->in, n);
        scatterwalk_advance(&walk->out, n);
-       scatterwalk_done(&walk->in, 0, nbytes);
-       scatterwalk_done(&walk->out, 1, nbytes);
+already_advanced:
+       scatterwalk_done(&walk->in, 0, more);
+       scatterwalk_done(&walk->out, 1, more);
 
-       if (nbytes) {
+       if (more) {
                crypto_yield(walk->flags & SKCIPHER_WALK_SLEEP ?
                             CRYPTO_TFM_REQ_MAY_SLEEP : 0);
                return skcipher_walk_next(walk);
        }
+       err = 0;
+finish:
+       walk->nbytes = 0;
 
        /* Short-circuit for the common/fast path. */
        if (!((unsigned long)walk->buffer | (unsigned long)walk->page))
@@ -399,7 +400,7 @@ static int skcipher_copy_iv(struct skcipher_walk *walk)
        unsigned size;
        u8 *iv;
 
-       aligned_bs = ALIGN(bs, alignmask);
+       aligned_bs = ALIGN(bs, alignmask + 1);
 
        /* Minimum size to align buffer by alignmask. */
        size = alignmask & ~a;
@@ -449,6 +450,8 @@ static int skcipher_walk_skcipher(struct skcipher_walk *walk,
 
        walk->total = req->cryptlen;
        walk->nbytes = 0;
+       walk->iv = req->iv;
+       walk->oiv = req->iv;
 
        if (unlikely(!walk->total))
                return 0;
@@ -456,9 +459,6 @@ static int skcipher_walk_skcipher(struct skcipher_walk *walk,
        scatterwalk_start(&walk->in, req->src);
        scatterwalk_start(&walk->out, req->dst);
 
-       walk->iv = req->iv;
-       walk->oiv = req->iv;
-
        walk->flags &= ~SKCIPHER_WALK_SLEEP;
        walk->flags |= req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ?
                       SKCIPHER_WALK_SLEEP : 0;
@@ -510,6 +510,8 @@ static int skcipher_walk_aead_common(struct skcipher_walk *walk,
        int err;
 
        walk->nbytes = 0;
+       walk->iv = req->iv;
+       walk->oiv = req->iv;
 
        if (unlikely(!walk->total))
                return 0;
@@ -522,8 +524,8 @@ static int skcipher_walk_aead_common(struct skcipher_walk *walk,
        scatterwalk_copychunks(NULL, &walk->in, req->assoclen, 2);
        scatterwalk_copychunks(NULL, &walk->out, req->assoclen, 2);
 
-       walk->iv = req->iv;
-       walk->oiv = req->iv;
+       scatterwalk_done(&walk->in, 0, walk->total);
+       scatterwalk_done(&walk->out, 0, walk->total);
 
        if (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP)
                walk->flags |= SKCIPHER_WALK_SLEEP;