diff options
author | Cyrille Pitchen <cyrille.pitchen@atmel.com> | 2016-02-08 10:26:49 -0500 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2016-02-16 15:07:43 -0500 |
commit | ad84112a1135bda928806fcbb98680847ab81436 (patch) | |
tree | b48ec319f8958b3ea67c01879bd8afb47071ba7c | |
parent | 9c4274d90d2923dda7435073de6494f0250ccb5a (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.c | 24 |
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) | |||
979 | static int atmel_sha_final(struct ahash_request *req) | 979 | static 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 | |||
1007 | err1: | ||
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 | ||
1015 | static int atmel_sha_finup(struct ahash_request *req) | 995 | static int atmel_sha_finup(struct ahash_request *req) |