crypto: atmel-sha - fix race in atmel_sha_final()
authorCyrille Pitchen <cyrille.pitchen@atmel.com>
Mon, 8 Feb 2016 15:26:49 +0000 (16:26 +0100)
committerHerbert Xu <herbert@gondor.apana.org.au>
Tue, 16 Feb 2016 20:07:43 +0000 (04:07 +0800)
When (!ctx->bufcnt && !(ctx->flags & SHA_FLAGS_PAD)), the former source
code used to set the SHA_FLAGS_BUSY without checking whether this flag was
already set. If so, the hardware is already processing another hash
request so the processing of the req argument of atmel_sha_final() should
be delayed by queueing this request, the same way as done for the
(ctx->bufcnt != 0) case.

Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
drivers/crypto/atmel-sha.c

index e4757f8957ae436cd3cc4f7b54c5492d14663fce..7b93586154a788a6d81905d216313ca1d1d9d03c 100644 (file)
@@ -979,37 +979,17 @@ static int atmel_sha_update(struct ahash_request *req)
 static int atmel_sha_final(struct ahash_request *req)
 {
        struct atmel_sha_reqctx *ctx = ahash_request_ctx(req);
-       struct atmel_sha_ctx *tctx = crypto_tfm_ctx(req->base.tfm);
-       struct atmel_sha_dev *dd = tctx->dd;
-
-       int err = 0;
 
        ctx->flags |= SHA_FLAGS_FINUP;
 
        if (ctx->flags & SHA_FLAGS_ERROR)
                return 0; /* uncompleted hash is not needed */
 
-       if (ctx->bufcnt) {
-               return atmel_sha_enqueue(req, SHA_OP_FINAL);
-       } else if (!(ctx->flags & SHA_FLAGS_PAD)) { /* add padding */
-               err = atmel_sha_hw_init(dd);
-               if (err)
-                       goto err1;
-
-               dd->req = req;
-               dd->flags |= SHA_FLAGS_BUSY;
-               err = atmel_sha_final_req(dd);
-       } else {
+       if (ctx->flags & SHA_FLAGS_PAD)
                /* copy ready hash (+ finalize hmac) */
                return atmel_sha_finish(req);
-       }
-
-err1:
-       if (err != -EINPROGRESS)
-               /* done_task will not finish it, so do it here */
-               atmel_sha_finish_req(req, err);
 
-       return err;
+       return atmel_sha_enqueue(req, SHA_OP_FINAL);
 }
 
 static int atmel_sha_finup(struct ahash_request *req)