aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCyrille Pitchen <cyrille.pitchen@atmel.com>2016-02-08 10:26:49 -0500
committerHerbert Xu <herbert@gondor.apana.org.au>2016-02-16 15:07:43 -0500
commitad84112a1135bda928806fcbb98680847ab81436 (patch)
treeb48ec319f8958b3ea67c01879bd8afb47071ba7c
parent9c4274d90d2923dda7435073de6494f0250ccb5a (diff)
crypto: atmel-sha - fix race in atmel_sha_final()
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>
-rw-r--r--drivers/crypto/atmel-sha.c24
1 files changed, 2 insertions, 22 deletions
diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c
index e4757f8957ae..7b93586154a7 100644
--- a/drivers/crypto/atmel-sha.c
+++ b/drivers/crypto/atmel-sha.c
@@ -979,37 +979,17 @@ static int atmel_sha_update(struct ahash_request *req)
979static int atmel_sha_final(struct ahash_request *req) 979static int atmel_sha_final(struct ahash_request *req)
980{ 980{
981 struct atmel_sha_reqctx *ctx = ahash_request_ctx(req); 981 struct atmel_sha_reqctx *ctx = ahash_request_ctx(req);
982 struct atmel_sha_ctx *tctx = crypto_tfm_ctx(req->base.tfm);
983 struct atmel_sha_dev *dd = tctx->dd;
984
985 int err = 0;
986 982
987 ctx->flags |= SHA_FLAGS_FINUP; 983 ctx->flags |= SHA_FLAGS_FINUP;
988 984
989 if (ctx->flags & SHA_FLAGS_ERROR) 985 if (ctx->flags & SHA_FLAGS_ERROR)
990 return 0; /* uncompleted hash is not needed */ 986 return 0; /* uncompleted hash is not needed */
991 987
992 if (ctx->bufcnt) { 988 if (ctx->flags & SHA_FLAGS_PAD)
993 return atmel_sha_enqueue(req, SHA_OP_FINAL);
994 } else if (!(ctx->flags & SHA_FLAGS_PAD)) { /* add padding */
995 err = atmel_sha_hw_init(dd);
996 if (err)
997 goto err1;
998
999 dd->req = req;
1000 dd->flags |= SHA_FLAGS_BUSY;
1001 err = atmel_sha_final_req(dd);
1002 } else {
1003 /* copy ready hash (+ finalize hmac) */ 989 /* copy ready hash (+ finalize hmac) */
1004 return atmel_sha_finish(req); 990 return atmel_sha_finish(req);
1005 }
1006
1007err1:
1008 if (err != -EINPROGRESS)
1009 /* done_task will not finish it, so do it here */
1010 atmel_sha_finish_req(req, err);
1011 991
1012 return err; 992 return atmel_sha_enqueue(req, SHA_OP_FINAL);
1013} 993}
1014 994
1015static int atmel_sha_finup(struct ahash_request *req) 995static int atmel_sha_finup(struct ahash_request *req)