mirror of
https://github.com/torvalds/linux.git
synced 2026-04-18 06:44:00 -04:00
crypto: authencesn - Do not place hiseq at end of dst for out-of-place decryption
When decrypting data that is not in-place (src != dst), there is
no need to save the high-order sequence bits in dst as it could
simply be re-copied from the source.
However, the data to be hashed need to be rearranged accordingly.
Reported-by: Taeyang Lee <0wn@theori.io>
Fixes: 104880a6b4 ("crypto: authencesn - Convert to new AEAD interface")
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Thanks,
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
This commit is contained in:
@@ -207,6 +207,7 @@ static int crypto_authenc_esn_decrypt_tail(struct aead_request *req,
|
|||||||
u8 *ohash = areq_ctx->tail;
|
u8 *ohash = areq_ctx->tail;
|
||||||
unsigned int cryptlen = req->cryptlen - authsize;
|
unsigned int cryptlen = req->cryptlen - authsize;
|
||||||
unsigned int assoclen = req->assoclen;
|
unsigned int assoclen = req->assoclen;
|
||||||
|
struct scatterlist *src = req->src;
|
||||||
struct scatterlist *dst = req->dst;
|
struct scatterlist *dst = req->dst;
|
||||||
u8 *ihash = ohash + crypto_ahash_digestsize(auth);
|
u8 *ihash = ohash + crypto_ahash_digestsize(auth);
|
||||||
u32 tmp[2];
|
u32 tmp[2];
|
||||||
@@ -214,23 +215,27 @@ static int crypto_authenc_esn_decrypt_tail(struct aead_request *req,
|
|||||||
if (!authsize)
|
if (!authsize)
|
||||||
goto decrypt;
|
goto decrypt;
|
||||||
|
|
||||||
/* Move high-order bits of sequence number back. */
|
if (src == dst) {
|
||||||
scatterwalk_map_and_copy(tmp, dst, 4, 4, 0);
|
/* Move high-order bits of sequence number back. */
|
||||||
scatterwalk_map_and_copy(tmp + 1, dst, assoclen + cryptlen, 4, 0);
|
scatterwalk_map_and_copy(tmp, dst, 4, 4, 0);
|
||||||
scatterwalk_map_and_copy(tmp, dst, 0, 8, 1);
|
scatterwalk_map_and_copy(tmp + 1, dst, assoclen + cryptlen, 4, 0);
|
||||||
|
scatterwalk_map_and_copy(tmp, dst, 0, 8, 1);
|
||||||
|
} else
|
||||||
|
memcpy_sglist(dst, src, assoclen);
|
||||||
|
|
||||||
if (crypto_memneq(ihash, ohash, authsize))
|
if (crypto_memneq(ihash, ohash, authsize))
|
||||||
return -EBADMSG;
|
return -EBADMSG;
|
||||||
|
|
||||||
decrypt:
|
decrypt:
|
||||||
|
|
||||||
sg_init_table(areq_ctx->dst, 2);
|
if (src != dst)
|
||||||
|
src = scatterwalk_ffwd(areq_ctx->src, src, assoclen);
|
||||||
dst = scatterwalk_ffwd(areq_ctx->dst, dst, assoclen);
|
dst = scatterwalk_ffwd(areq_ctx->dst, dst, assoclen);
|
||||||
|
|
||||||
skcipher_request_set_tfm(skreq, ctx->enc);
|
skcipher_request_set_tfm(skreq, ctx->enc);
|
||||||
skcipher_request_set_callback(skreq, flags,
|
skcipher_request_set_callback(skreq, flags,
|
||||||
req->base.complete, req->base.data);
|
req->base.complete, req->base.data);
|
||||||
skcipher_request_set_crypt(skreq, dst, dst, cryptlen, req->iv);
|
skcipher_request_set_crypt(skreq, src, dst, cryptlen, req->iv);
|
||||||
|
|
||||||
return crypto_skcipher_decrypt(skreq);
|
return crypto_skcipher_decrypt(skreq);
|
||||||
}
|
}
|
||||||
@@ -255,6 +260,7 @@ static int crypto_authenc_esn_decrypt(struct aead_request *req)
|
|||||||
unsigned int assoclen = req->assoclen;
|
unsigned int assoclen = req->assoclen;
|
||||||
unsigned int cryptlen = req->cryptlen;
|
unsigned int cryptlen = req->cryptlen;
|
||||||
u8 *ihash = ohash + crypto_ahash_digestsize(auth);
|
u8 *ihash = ohash + crypto_ahash_digestsize(auth);
|
||||||
|
struct scatterlist *src = req->src;
|
||||||
struct scatterlist *dst = req->dst;
|
struct scatterlist *dst = req->dst;
|
||||||
u32 tmp[2];
|
u32 tmp[2];
|
||||||
int err;
|
int err;
|
||||||
@@ -262,24 +268,28 @@ static int crypto_authenc_esn_decrypt(struct aead_request *req)
|
|||||||
if (assoclen < 8)
|
if (assoclen < 8)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
cryptlen -= authsize;
|
|
||||||
|
|
||||||
if (req->src != dst)
|
|
||||||
memcpy_sglist(dst, req->src, assoclen + cryptlen);
|
|
||||||
|
|
||||||
scatterwalk_map_and_copy(ihash, req->src, assoclen + cryptlen,
|
|
||||||
authsize, 0);
|
|
||||||
|
|
||||||
if (!authsize)
|
if (!authsize)
|
||||||
goto tail;
|
goto tail;
|
||||||
|
|
||||||
/* Move high-order bits of sequence number to the end. */
|
cryptlen -= authsize;
|
||||||
scatterwalk_map_and_copy(tmp, dst, 0, 8, 0);
|
scatterwalk_map_and_copy(ihash, req->src, assoclen + cryptlen,
|
||||||
scatterwalk_map_and_copy(tmp, dst, 4, 4, 1);
|
authsize, 0);
|
||||||
scatterwalk_map_and_copy(tmp + 1, dst, assoclen + cryptlen, 4, 1);
|
|
||||||
|
|
||||||
sg_init_table(areq_ctx->dst, 2);
|
/* Move high-order bits of sequence number to the end. */
|
||||||
dst = scatterwalk_ffwd(areq_ctx->dst, dst, 4);
|
scatterwalk_map_and_copy(tmp, src, 0, 8, 0);
|
||||||
|
if (src == dst) {
|
||||||
|
scatterwalk_map_and_copy(tmp, dst, 4, 4, 1);
|
||||||
|
scatterwalk_map_and_copy(tmp + 1, dst, assoclen + cryptlen, 4, 1);
|
||||||
|
dst = scatterwalk_ffwd(areq_ctx->dst, dst, 4);
|
||||||
|
} else {
|
||||||
|
scatterwalk_map_and_copy(tmp, dst, 0, 4, 1);
|
||||||
|
scatterwalk_map_and_copy(tmp + 1, dst, assoclen + cryptlen - 4, 4, 1);
|
||||||
|
|
||||||
|
src = scatterwalk_ffwd(areq_ctx->src, src, 8);
|
||||||
|
dst = scatterwalk_ffwd(areq_ctx->dst, dst, 4);
|
||||||
|
memcpy_sglist(dst, src, assoclen + cryptlen - 8);
|
||||||
|
dst = req->dst;
|
||||||
|
}
|
||||||
|
|
||||||
ahash_request_set_tfm(ahreq, auth);
|
ahash_request_set_tfm(ahreq, auth);
|
||||||
ahash_request_set_crypt(ahreq, dst, ohash, assoclen + cryptlen);
|
ahash_request_set_crypt(ahreq, dst, ohash, assoclen + cryptlen);
|
||||||
|
|||||||
Reference in New Issue
Block a user