diff options
author | Herbert Xu <herbert@gondor.apana.org.au> | 2009-01-13 11:26:18 +1100 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2009-01-15 15:33:49 +1100 |
commit | 29b37f42127f7da511560a40ea74f5047da40c13 (patch) | |
tree | fa6cbeb329cc0d564511a3bd6f4d7172d468494b /crypto/authenc.c | |
parent | 5393f780277165f282a37ed82dd878159ec9dad5 (diff) | |
download | lwn-29b37f42127f7da511560a40ea74f5047da40c13.tar.gz lwn-29b37f42127f7da511560a40ea74f5047da40c13.zip |
crypto: authenc - Fix zero-length IV crash
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>
Diffstat (limited to 'crypto/authenc.c')
-rw-r--r-- | crypto/authenc.c | 24 |
1 files changed, 15 insertions, 9 deletions
diff --git a/crypto/authenc.c b/crypto/authenc.c index 40b6e9ec9e3a..5793b64c81a8 100644 --- a/crypto/authenc.c +++ b/crypto/authenc.c @@ -158,16 +158,19 @@ static int crypto_authenc_genicv(struct aead_request *req, u8 *iv, 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; } @@ -285,11 +288,14 @@ static int crypto_authenc_iverify(struct aead_request *req, u8 *iv, 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) |