Commit 86ef1dfc authored by Tudor Ambarus's avatar Tudor Ambarus Committed by Herbert Xu

crypto: atmel-aes - Fix IV handling when req->nbytes < ivsize

commit 394a9e04 ("crypto: cfb - add missing 'chunksize' property")
adds a test vector where the input length is smaller than the IV length
(the second test vector). This revealed a NULL pointer dereference in
the atmel-aes driver, that is caused by passing an incorrect offset in
scatterwalk_map_and_copy() when atmel_aes_complete() is called.

Do not save the IV in req->info of ablkcipher_request (or equivalently
req->iv of skcipher_request) when req->nbytes < ivsize, because the IV
will not be further used.

While touching the code, modify the type of ivsize from int to
unsigned int, to comply with the return type of
crypto_ablkcipher_ivsize().

Fixes: 91308019 ("crypto: atmel-aes - properly set IV after {en,de}crypt")
Cc: <stable@vger.kernel.org>
Signed-off-by: default avatarTudor Ambarus <tudor.ambarus@microchip.com>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent 83053677
......@@ -490,36 +490,41 @@ static inline bool atmel_aes_is_encrypt(const struct atmel_aes_dev *dd)
static void atmel_aes_authenc_complete(struct atmel_aes_dev *dd, int err);
#endif
static inline int atmel_aes_complete(struct atmel_aes_dev *dd, int err)
static void atmel_aes_set_iv_as_last_ciphertext_block(struct atmel_aes_dev *dd)
{
#ifdef CONFIG_CRYPTO_DEV_ATMEL_AUTHENC
if (dd->ctx->is_aead)
atmel_aes_authenc_complete(dd, err);
#endif
clk_disable(dd->iclk);
dd->flags &= ~AES_FLAGS_BUSY;
if (!dd->ctx->is_aead) {
struct ablkcipher_request *req =
ablkcipher_request_cast(dd->areq);
struct ablkcipher_request *req = ablkcipher_request_cast(dd->areq);
struct atmel_aes_reqctx *rctx = ablkcipher_request_ctx(req);
struct crypto_ablkcipher *ablkcipher =
crypto_ablkcipher_reqtfm(req);
int ivsize = crypto_ablkcipher_ivsize(ablkcipher);
struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req);
unsigned int ivsize = crypto_ablkcipher_ivsize(ablkcipher);
if (req->nbytes < ivsize)
return;
if (rctx->mode & AES_FLAGS_ENCRYPT) {
scatterwalk_map_and_copy(req->info, req->dst,
req->nbytes - ivsize, ivsize, 0);
} else {
if (req->src == req->dst) {
if (req->src == req->dst)
memcpy(req->info, rctx->lastc, ivsize);
} else {
else
scatterwalk_map_and_copy(req->info, req->src,
req->nbytes - ivsize, ivsize, 0);
}
}
req->nbytes - ivsize,
ivsize, 0);
}
}
static inline int atmel_aes_complete(struct atmel_aes_dev *dd, int err)
{
#ifdef CONFIG_CRYPTO_DEV_ATMEL_AUTHENC
if (dd->ctx->is_aead)
atmel_aes_authenc_complete(dd, err);
#endif
clk_disable(dd->iclk);
dd->flags &= ~AES_FLAGS_BUSY;
if (!dd->ctx->is_aead)
atmel_aes_set_iv_as_last_ciphertext_block(dd);
if (dd->is_async)
dd->areq->complete(dd->areq, err);
......@@ -1125,10 +1130,12 @@ static int atmel_aes_crypt(struct ablkcipher_request *req, unsigned long mode)
rctx->mode = mode;
if (!(mode & AES_FLAGS_ENCRYPT) && (req->src == req->dst)) {
int ivsize = crypto_ablkcipher_ivsize(ablkcipher);
unsigned int ivsize = crypto_ablkcipher_ivsize(ablkcipher);
if (req->nbytes >= ivsize)
scatterwalk_map_and_copy(rctx->lastc, req->src,
(req->nbytes - ivsize), ivsize, 0);
req->nbytes - ivsize,
ivsize, 0);
}
return atmel_aes_handle_queue(dd, &req->base);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment