| From 29b37f42127f7da511560a40ea74f5047da40c13 Mon Sep 17 00:00:00 2001 |
| From: Herbert Xu <herbert@gondor.apana.org.au> |
| Date: Tue, 13 Jan 2009 11:26:18 +1100 |
| Subject: crypto: authenc - Fix zero-length IV crash |
| |
| From: Herbert Xu <herbert@gondor.apana.org.au> |
| |
| commit 29b37f42127f7da511560a40ea74f5047da40c13 upstream. |
| |
| As it is if an algorithm with a zero-length IV is used (e.g., |
| NULL encryption) with authenc, authenc may generate an SG entry |
| of length zero, which will trigger a BUG check in the hash layer. |
| |
| This patch fixes it by skipping the IV SG generation if the IV |
| size is zero. |
| |
| Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| |
| --- |
| crypto/authenc.c | 24 +++++++++++++++--------- |
| 1 file changed, 15 insertions(+), 9 deletions(-) |
| |
| --- a/crypto/authenc.c |
| +++ b/crypto/authenc.c |
| @@ -157,16 +157,19 @@ static int crypto_authenc_genicv(struct |
| dstp = sg_page(dst); |
| vdst = PageHighMem(dstp) ? NULL : page_address(dstp) + dst->offset; |
| |
| - sg_init_table(cipher, 2); |
| - sg_set_buf(cipher, iv, ivsize); |
| - authenc_chain(cipher, dst, vdst == iv + ivsize); |
| + if (ivsize) { |
| + sg_init_table(cipher, 2); |
| + sg_set_buf(cipher, iv, ivsize); |
| + authenc_chain(cipher, dst, vdst == iv + ivsize); |
| + dst = cipher; |
| + } |
| |
| cryptlen = req->cryptlen + ivsize; |
| - hash = crypto_authenc_hash(req, flags, cipher, cryptlen); |
| + hash = crypto_authenc_hash(req, flags, dst, cryptlen); |
| if (IS_ERR(hash)) |
| return PTR_ERR(hash); |
| |
| - scatterwalk_map_and_copy(hash, cipher, cryptlen, |
| + scatterwalk_map_and_copy(hash, dst, cryptlen, |
| crypto_aead_authsize(authenc), 1); |
| return 0; |
| } |
| @@ -284,11 +287,14 @@ static int crypto_authenc_iverify(struct |
| srcp = sg_page(src); |
| vsrc = PageHighMem(srcp) ? NULL : page_address(srcp) + src->offset; |
| |
| - sg_init_table(cipher, 2); |
| - sg_set_buf(cipher, iv, ivsize); |
| - authenc_chain(cipher, src, vsrc == iv + ivsize); |
| + if (ivsize) { |
| + sg_init_table(cipher, 2); |
| + sg_set_buf(cipher, iv, ivsize); |
| + authenc_chain(cipher, src, vsrc == iv + ivsize); |
| + src = cipher; |
| + } |
| |
| - return crypto_authenc_verify(req, cipher, cryptlen + ivsize); |
| + return crypto_authenc_verify(req, src, cryptlen + ivsize); |
| } |
| |
| static int crypto_authenc_decrypt(struct aead_request *req) |