crypto: caam - Clamp AEAD SG list by input length
authorHerbert Xu <herbert@gondor.apana.org.au>
Mon, 8 Jun 2015 08:38:24 +0000 (16:38 +0800)
committerHerbert Xu <herbert@gondor.apana.org.au>
Tue, 9 Jun 2015 14:25:58 +0000 (22:25 +0800)
Currently caam 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>
drivers/crypto/caam/caamalg.c
drivers/crypto/caam/sg_sw_sec4.h

index 3d850ab47c2865a10e457b2f5827a69c31a7ffd2..3c37fe63e5985995cb30d3828fab43f0222d0f45 100644 (file)
@@ -2713,10 +2713,8 @@ static struct aead_edesc *aead_edesc_alloc(struct aead_request *req,
        sec4_sg_index = 0;
        if (!all_contig) {
                if (!is_gcm) {
-                       sg_to_sec4_sg(req->assoc,
-                                     assoc_nents,
-                                     edesc->sec4_sg +
-                                     sec4_sg_index, 0);
+                       sg_to_sec4_sg_len(req->assoc, req->assoclen,
+                                         edesc->sec4_sg + sec4_sg_index);
                        sec4_sg_index += assoc_nents;
                }
 
@@ -2725,10 +2723,8 @@ static struct aead_edesc *aead_edesc_alloc(struct aead_request *req,
                sec4_sg_index += 1;
 
                if (is_gcm) {
-                       sg_to_sec4_sg(req->assoc,
-                                     assoc_nents,
-                                     edesc->sec4_sg +
-                                     sec4_sg_index, 0);
+                       sg_to_sec4_sg_len(req->assoc, req->assoclen,
+                                         edesc->sec4_sg + sec4_sg_index);
                        sec4_sg_index += assoc_nents;
                }
 
@@ -2953,8 +2949,8 @@ static struct aead_edesc *aead_giv_edesc_alloc(struct aead_givcrypt_request
        sec4_sg_index = 0;
        if (!(contig & GIV_SRC_CONTIG)) {
                if (!is_gcm) {
-                       sg_to_sec4_sg(req->assoc, assoc_nents,
-                                     edesc->sec4_sg + sec4_sg_index, 0);
+                       sg_to_sec4_sg_len(req->assoc, req->assoclen,
+                                         edesc->sec4_sg + sec4_sg_index);
                        sec4_sg_index += assoc_nents;
                }
 
@@ -2963,8 +2959,8 @@ static struct aead_edesc *aead_giv_edesc_alloc(struct aead_givcrypt_request
                sec4_sg_index += 1;
 
                if (is_gcm) {
-                       sg_to_sec4_sg(req->assoc, assoc_nents,
-                                     edesc->sec4_sg + sec4_sg_index, 0);
+                       sg_to_sec4_sg_len(req->assoc, req->assoclen,
+                                         edesc->sec4_sg + sec4_sg_index);
                        sec4_sg_index += assoc_nents;
                }
 
index 3b918218aa4c56436e378f595f45d2f2cc067e1a..efbc1db8da5307c532d0f3a48df94245afb70b2f 100644 (file)
@@ -55,6 +55,21 @@ static inline void sg_to_sec4_sg_last(struct scatterlist *sg, int sg_count,
        sec4_sg_ptr->len |= SEC4_SG_LEN_FIN;
 }
 
+static inline struct sec4_sg_entry *sg_to_sec4_sg_len(
+       struct scatterlist *sg, unsigned int total,
+       struct sec4_sg_entry *sec4_sg_ptr)
+{
+       do {
+               unsigned int len = min(sg_dma_len(sg), total);
+
+               dma_to_sec4_sg_one(sec4_sg_ptr, sg_dma_address(sg), len, 0);
+               sec4_sg_ptr++;
+               sg = sg_next(sg);
+               total -= len;
+       } while (total);
+       return sec4_sg_ptr - 1;
+}
+
 /* count number of elements in scatterlist */
 static inline int __sg_count(struct scatterlist *sg_list, int nbytes,
                             bool *chained)