]> git.hungrycats.org Git - linux/commitdiff
crypto: caam - properly set IV after {en,de}crypt
authorDavid Gstir <david@sigma-star.at>
Wed, 28 Jun 2017 13:27:10 +0000 (15:27 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 21 Jul 2017 05:00:14 +0000 (07:00 +0200)
commit 854b06f768794cd664886ec3ba3a5b1c58d42167 upstream.

Certain cipher modes like CTS expect the IV (req->info) of
ablkcipher_request (or equivalently req->iv of skcipher_request) to
contain the last ciphertext block when the {en,de}crypt operation is done.
This is currently not the case for the CAAM driver which in turn breaks
e.g. cts(cbc(aes)) when the CAAM driver is enabled.

This patch fixes the CAAM driver to properly set the IV after the
{en,de}crypt operation of ablkcipher finishes.

This issue was revealed by the changes in the SW CTS mode in commit
0605c41cc53ca ("crypto: cts - Convert to skcipher")

Signed-off-by: David Gstir <david@sigma-star.at>
Reviewed-by: Horia Geantă <horia.geanta@nxp.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/crypto/caam/caamalg.c

index b4e3f4ef5c0530534239edb1e3acaed05eaafcf8..20772c8abf481faa83fe73f84cea5f4f7df35738 100644 (file)
@@ -881,10 +881,10 @@ static void ablkcipher_encrypt_done(struct device *jrdev, u32 *desc, u32 err,
 {
        struct ablkcipher_request *req = context;
        struct ablkcipher_edesc *edesc;
-#ifdef DEBUG
        struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req);
        int ivsize = crypto_ablkcipher_ivsize(ablkcipher);
 
+#ifdef DEBUG
        dev_err(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err);
 #endif
 
@@ -903,6 +903,14 @@ static void ablkcipher_encrypt_done(struct device *jrdev, u32 *desc, u32 err,
 #endif
 
        ablkcipher_unmap(jrdev, edesc, req);
+
+       /*
+        * The crypto API expects us to set the IV (req->info) to the last
+        * ciphertext block. This is used e.g. by the CTS mode.
+        */
+       scatterwalk_map_and_copy(req->info, req->dst, req->nbytes - ivsize,
+                                ivsize, 0);
+
        kfree(edesc);
 
        ablkcipher_request_complete(req, err);
@@ -913,10 +921,10 @@ static void ablkcipher_decrypt_done(struct device *jrdev, u32 *desc, u32 err,
 {
        struct ablkcipher_request *req = context;
        struct ablkcipher_edesc *edesc;
-#ifdef DEBUG
        struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req);
        int ivsize = crypto_ablkcipher_ivsize(ablkcipher);
 
+#ifdef DEBUG
        dev_err(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err);
 #endif
 
@@ -934,6 +942,14 @@ static void ablkcipher_decrypt_done(struct device *jrdev, u32 *desc, u32 err,
 #endif
 
        ablkcipher_unmap(jrdev, edesc, req);
+
+       /*
+        * The crypto API expects us to set the IV (req->info) to the last
+        * ciphertext block.
+        */
+       scatterwalk_map_and_copy(req->info, req->src, req->nbytes - ivsize,
+                                ivsize, 0);
+
        kfree(edesc);
 
        ablkcipher_request_complete(req, err);