diff options
author | Corentin Labbe <clabbe@baylibre.com> | 2021-05-05 20:26:09 +0000 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2021-07-14 16:56:03 +0200 |
commit | 8c8c11b4df706307248d0ab637f2601b2520edc0 (patch) | |
tree | 44424dc72f491d1b537d7d1b00d8fcc7660a308f /drivers/crypto | |
parent | f00454ac40f87fda875252d1b22e0876512d4414 (diff) | |
download | linux-rt-8c8c11b4df706307248d0ab637f2601b2520edc0.tar.gz |
crypto: ixp4xx - update IV after requests
[ Upstream commit e8acf011f2e7e21a7e2fae47cbaa06598e533d40 ]
Crypto selftests fail on ixp4xx since it do not update IV after skcipher
requests.
Fixes: 81bef0150074 ("crypto: ixp4xx - Hardware crypto support for IXP4xx CPUs")
Signed-off-by: Corentin Labbe <clabbe@baylibre.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'drivers/crypto')
-rw-r--r-- | drivers/crypto/ixp4xx_crypto.c | 22 |
1 files changed, 22 insertions, 0 deletions
diff --git a/drivers/crypto/ixp4xx_crypto.c b/drivers/crypto/ixp4xx_crypto.c index cbb1fda299a8..5e474a7a1912 100644 --- a/drivers/crypto/ixp4xx_crypto.c +++ b/drivers/crypto/ixp4xx_crypto.c @@ -149,6 +149,8 @@ struct crypt_ctl { struct ablk_ctx { struct buffer_desc *src; struct buffer_desc *dst; + u8 iv[MAX_IVLEN]; + bool encrypt; }; struct aead_ctx { @@ -381,6 +383,20 @@ static void one_packet(dma_addr_t phys) case CTL_FLAG_PERFORM_ABLK: { struct skcipher_request *req = crypt->data.ablk_req; struct ablk_ctx *req_ctx = skcipher_request_ctx(req); + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + unsigned int ivsize = crypto_skcipher_ivsize(tfm); + unsigned int offset; + + if (ivsize > 0) { + offset = req->cryptlen - ivsize; + if (req_ctx->encrypt) { + scatterwalk_map_and_copy(req->iv, req->dst, + offset, ivsize, 0); + } else { + memcpy(req->iv, req_ctx->iv, ivsize); + memzero_explicit(req_ctx->iv, ivsize); + } + } if (req_ctx->dst) { free_buf_chain(dev, req_ctx->dst, crypt->dst_buf); @@ -876,6 +892,7 @@ static int ablk_perform(struct skcipher_request *req, int encrypt) struct ablk_ctx *req_ctx = skcipher_request_ctx(req); struct buffer_desc src_hook; struct device *dev = &pdev->dev; + unsigned int offset; gfp_t flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL : GFP_ATOMIC; @@ -885,6 +902,7 @@ static int ablk_perform(struct skcipher_request *req, int encrypt) return -EAGAIN; dir = encrypt ? &ctx->encrypt : &ctx->decrypt; + req_ctx->encrypt = encrypt; crypt = get_crypt_desc(); if (!crypt) @@ -900,6 +918,10 @@ static int ablk_perform(struct skcipher_request *req, int encrypt) BUG_ON(ivsize && !req->iv); memcpy(crypt->iv, req->iv, ivsize); + if (ivsize > 0 && !encrypt) { + offset = req->cryptlen - ivsize; + scatterwalk_map_and_copy(req_ctx->iv, req->src, offset, ivsize, 0); + } if (req->src != req->dst) { struct buffer_desc dst_hook; crypt->mode |= NPE_OP_NOT_IN_PLACE; |