summaryrefslogtreecommitdiffstats
path: root/drivers/crypto/picoxcell_crypto.c
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2015-06-11 05:28:34 +0200
committerHerbert Xu <herbert@gondor.apana.org.au>2015-06-12 16:45:09 +0200
commit81781e681551ed3f56c9202e9adc7ef941cba654 (patch)
tree9f9577f0edb591a80e6d5c39b23061839f5dca30 /drivers/crypto/picoxcell_crypto.c
parentcrypto: picoxcell - Make use of sg_nents_for_len (diff)
downloadlinux-81781e681551ed3f56c9202e9adc7ef941cba654.tar.xz
linux-81781e681551ed3f56c9202e9adc7ef941cba654.zip
crypto: picoxcell - Clamp AEAD SG list by input length
Currently the driver assumes that the SG list contains exactly the number of bytes required. This assumption is incorrect. Up until now this has been harmless. However with the new AEAD interface this now breaks as the AD SG list contains more bytes than just the AD. This patch fixes this by always clamping the AD SG list by the specified AD length. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'drivers/crypto/picoxcell_crypto.c')
-rw-r--r--drivers/crypto/picoxcell_crypto.c14
1 files changed, 11 insertions, 3 deletions
diff --git a/drivers/crypto/picoxcell_crypto.c b/drivers/crypto/picoxcell_crypto.c
index 9eb27c71cedf..c2fd860745ad 100644
--- a/drivers/crypto/picoxcell_crypto.c
+++ b/drivers/crypto/picoxcell_crypto.c
@@ -318,6 +318,7 @@ static int spacc_aead_make_ddts(struct spacc_req *req, u8 *giv)
struct spacc_ddt *src_ddt, *dst_ddt;
unsigned ivsize = crypto_aead_ivsize(crypto_aead_reqtfm(areq));
unsigned nents = sg_count(areq->src, areq->cryptlen);
+ unsigned total;
dma_addr_t iv_addr;
struct scatterlist *cur;
int i, dst_ents, src_ents, assoc_ents;
@@ -361,11 +362,18 @@ static int spacc_aead_make_ddts(struct spacc_req *req, u8 *giv)
* Map the associated data. For decryption we don't copy the
* associated data.
*/
+ total = areq->assoclen;
for_each_sg(areq->assoc, cur, assoc_ents, i) {
- ddt_set(src_ddt++, sg_dma_address(cur), sg_dma_len(cur));
+ unsigned len = sg_dma_len(cur);
+
+ if (len > total)
+ len = total;
+
+ total -= len;
+
+ ddt_set(src_ddt++, sg_dma_address(cur), len);
if (req->is_encrypt)
- ddt_set(dst_ddt++, sg_dma_address(cur),
- sg_dma_len(cur));
+ ddt_set(dst_ddt++, sg_dma_address(cur), len);
}
ddt_set(src_ddt++, iv_addr, ivsize);