aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/crypto/omap-sham.c
diff options
context:
space:
mode:
authorDmitry Kasatkin <dmitry.kasatkin@nokia.com>2011-04-20 06:34:58 -0400
committerHerbert Xu <herbert@gondor.apana.org.au>2011-04-26 02:45:38 -0400
commitbf362759034cf208966dff262c7d740a6b1b3edd (patch)
tree60e3eb51fbc11e1c15a7b25c79ba8a6dd9db9f8a /drivers/crypto/omap-sham.c
parent528d26f57acd112fef78cd455db78e69a1ac39fd (diff)
crypto: omap-sham - hmac calculation bug fix for sha1 base hash
This patch fixes 2 hmac inter-dependent bugs. 1. "omap-sham: hash-in-progress is stored in hw format" commit introduced optimization where temporary hash had been stored in OMAP specific format (big endian). For SHA1 it is different to real hash format, which is little endian. Final HMAC value was calculated using incorrect hash. Because CONFIG_CRYPTO_MANAGER_TESTS was disabled this error remained unnoticed. After enabling this option, bug has been found. 2. HMAC was calculated using temporrary hash value. For a single-request updates, temporary hash was the final one and HMAC result was correct. But in fact only the final hash had to be used. All crypto tests for HMAC produces only single request and could not catch the problem. This problem is fixed here. Signed-off-by: Dmitry Kasatkin <dmitry.kasatkin@nokia.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'drivers/crypto/omap-sham.c')
-rw-r--r--drivers/crypto/omap-sham.c71
1 files changed, 31 insertions, 40 deletions
diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c
index f5c01dc363d4..ba8f1ea84c5e 100644
--- a/drivers/crypto/omap-sham.c
+++ b/drivers/crypto/omap-sham.c
@@ -78,7 +78,6 @@
78#define FLAGS_SHA1 0x0010 78#define FLAGS_SHA1 0x0010
79#define FLAGS_DMA_ACTIVE 0x0020 79#define FLAGS_DMA_ACTIVE 0x0020
80#define FLAGS_OUTPUT_READY 0x0040 80#define FLAGS_OUTPUT_READY 0x0040
81#define FLAGS_CLEAN 0x0080
82#define FLAGS_INIT 0x0100 81#define FLAGS_INIT 0x0100
83#define FLAGS_CPU 0x0200 82#define FLAGS_CPU 0x0200
84#define FLAGS_HMAC 0x0400 83#define FLAGS_HMAC 0x0400
@@ -511,26 +510,6 @@ static int omap_sham_update_dma_stop(struct omap_sham_dev *dd)
511 return 0; 510 return 0;
512} 511}
513 512
514static void omap_sham_cleanup(struct ahash_request *req)
515{
516 struct omap_sham_reqctx *ctx = ahash_request_ctx(req);
517 struct omap_sham_dev *dd = ctx->dd;
518 unsigned long flags;
519
520 spin_lock_irqsave(&dd->lock, flags);
521 if (ctx->flags & FLAGS_CLEAN) {
522 spin_unlock_irqrestore(&dd->lock, flags);
523 return;
524 }
525 ctx->flags |= FLAGS_CLEAN;
526 spin_unlock_irqrestore(&dd->lock, flags);
527
528 if (ctx->digcnt)
529 omap_sham_copy_ready_hash(req);
530
531 dev_dbg(dd->dev, "digcnt: %d, bufcnt: %d\n", ctx->digcnt, ctx->bufcnt);
532}
533
534static int omap_sham_init(struct ahash_request *req) 513static int omap_sham_init(struct ahash_request *req)
535{ 514{
536 struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 515 struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
@@ -618,9 +597,8 @@ static int omap_sham_final_req(struct omap_sham_dev *dd)
618 return err; 597 return err;
619} 598}
620 599
621static int omap_sham_finish_req_hmac(struct ahash_request *req) 600static int omap_sham_finish_hmac(struct ahash_request *req)
622{ 601{
623 struct omap_sham_reqctx *ctx = ahash_request_ctx(req);
624 struct omap_sham_ctx *tctx = crypto_tfm_ctx(req->base.tfm); 602 struct omap_sham_ctx *tctx = crypto_tfm_ctx(req->base.tfm);
625 struct omap_sham_hmac_ctx *bctx = tctx->base; 603 struct omap_sham_hmac_ctx *bctx = tctx->base;
626 int bs = crypto_shash_blocksize(bctx->shash); 604 int bs = crypto_shash_blocksize(bctx->shash);
@@ -635,7 +613,24 @@ static int omap_sham_finish_req_hmac(struct ahash_request *req)
635 613
636 return crypto_shash_init(&desc.shash) ?: 614 return crypto_shash_init(&desc.shash) ?:
637 crypto_shash_update(&desc.shash, bctx->opad, bs) ?: 615 crypto_shash_update(&desc.shash, bctx->opad, bs) ?:
638 crypto_shash_finup(&desc.shash, ctx->digest, ds, ctx->digest); 616 crypto_shash_finup(&desc.shash, req->result, ds, req->result);
617}
618
619static int omap_sham_finish(struct ahash_request *req)
620{
621 struct omap_sham_reqctx *ctx = ahash_request_ctx(req);
622 struct omap_sham_dev *dd = ctx->dd;
623 int err = 0;
624
625 if (ctx->digcnt) {
626 omap_sham_copy_ready_hash(req);
627 if (ctx->flags & FLAGS_HMAC)
628 err = omap_sham_finish_hmac(req);
629 }
630
631 dev_dbg(dd->dev, "digcnt: %d, bufcnt: %d\n", ctx->digcnt, ctx->bufcnt);
632
633 return err;
639} 634}
640 635
641static void omap_sham_finish_req(struct ahash_request *req, int err) 636static void omap_sham_finish_req(struct ahash_request *req, int err)
@@ -645,15 +640,12 @@ static void omap_sham_finish_req(struct ahash_request *req, int err)
645 640
646 if (!err) { 641 if (!err) {
647 omap_sham_copy_hash(ctx->dd->req, 1); 642 omap_sham_copy_hash(ctx->dd->req, 1);
648 if (ctx->flags & FLAGS_HMAC) 643 if (ctx->flags & FLAGS_FINAL)
649 err = omap_sham_finish_req_hmac(req); 644 err = omap_sham_finish(req);
650 } else { 645 } else {
651 ctx->flags |= FLAGS_ERROR; 646 ctx->flags |= FLAGS_ERROR;
652 } 647 }
653 648
654 if ((ctx->flags & FLAGS_FINAL) || err)
655 omap_sham_cleanup(req);
656
657 clk_disable(dd->iclk); 649 clk_disable(dd->iclk);
658 dd->flags &= ~FLAGS_BUSY; 650 dd->flags &= ~FLAGS_BUSY;
659 651
@@ -809,22 +801,21 @@ static int omap_sham_final_shash(struct ahash_request *req)
809static int omap_sham_final(struct ahash_request *req) 801static int omap_sham_final(struct ahash_request *req)
810{ 802{
811 struct omap_sham_reqctx *ctx = ahash_request_ctx(req); 803 struct omap_sham_reqctx *ctx = ahash_request_ctx(req);
812 int err = 0;
813 804
814 ctx->flags |= FLAGS_FINUP; 805 ctx->flags |= FLAGS_FINUP;
815 806
816 if (!(ctx->flags & FLAGS_ERROR)) { 807 if (ctx->flags & FLAGS_ERROR)
817 /* OMAP HW accel works only with buffers >= 9 */ 808 return 0; /* uncompleted hash is not needed */
818 /* HMAC is always >= 9 because of ipad */
819 if ((ctx->digcnt + ctx->bufcnt) < 9)
820 err = omap_sham_final_shash(req);
821 else if (ctx->bufcnt)
822 return omap_sham_enqueue(req, OP_FINAL);
823 }
824 809
825 omap_sham_cleanup(req); 810 /* OMAP HW accel works only with buffers >= 9 */
811 /* HMAC is always >= 9 because ipad == block size */
812 if ((ctx->digcnt + ctx->bufcnt) < 9)
813 return omap_sham_final_shash(req);
814 else if (ctx->bufcnt)
815 return omap_sham_enqueue(req, OP_FINAL);
826 816
827 return err; 817 /* copy ready hash (+ finalize hmac) */
818 return omap_sham_finish(req);
828} 819}
829 820
830static int omap_sham_finup(struct ahash_request *req) 821static int omap_sham_finup(struct ahash_request *req)