Hi,

I am currently working on a driver for our crypto HW and the initial
aim was to offload IPSec (ESP for now) to HW. I did this by
registering the cipher and hash algorithms (both asynchronous)
separately (AES-CBC, HMAC-SHA1 only for now) and let the API handle
the request using the AUTHENC interface.

The problem seems to be after the asynchronous hash request is
completed, the length of the ABLKCIPHER decrypt request is not
calculated correctly in "authenc_verify_ahash_update_done()" and
"authenc_verify_ahash_done()". The length should be subtracted by
"authsize" as done in "crypto_authenc_decrypt()".

The following patch (applied against 2.6.34) should fix it. I hope I
didn't miss anything.

Thanks,
Shikhar

--------
diff -pu linux-2.6.34/crypto/authenc.c linux-2.6.34_mod/crypto/authenc.c

--- linux-2.6.34/crypto/authenc.c       2010-05-16 23:17:36.000000000 +0200
+++ linux-2.6.34_mod/crypto/authenc.c   2010-05-19 14:32:51.000000000 +0200
@@ -181,6 +181,7 @@ static void authenc_verify_ahash_update_
        struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
        struct authenc_request_ctx *areq_ctx = aead_request_ctx(req);
        struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff);
+       unsigned int cryptlen = req->cryptlen;

        if (err)
                goto out;
@@ -196,6 +197,7 @@ static void authenc_verify_ahash_update_
                goto out;

        authsize = crypto_aead_authsize(authenc);
+       cryptlen -= authsize;
        ihash = ahreq->result + authsize;
        scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen,
                                 authsize, 0);
@@ -209,7 +211,7 @@ static void authenc_verify_ahash_update_
        ablkcipher_request_set_callback(abreq, aead_request_flags(req),
                                        req->base.complete, req->base.data);
        ablkcipher_request_set_crypt(abreq, req->src, req->dst,
-                                    req->cryptlen, req->iv);
+                                    cryptlen, req->iv);

        err = crypto_ablkcipher_decrypt(abreq);

@@ -228,11 +230,13 @@ static void authenc_verify_ahash_done(st
        struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
        struct authenc_request_ctx *areq_ctx = aead_request_ctx(req);
        struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff);
+       unsigned int cryptlen = req->cryptlen;

        if (err)
                goto out;

        authsize = crypto_aead_authsize(authenc);
+       cryptlen -= authsize;
        ihash = ahreq->result + authsize;
        scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen,
                                 authsize, 0);
@@ -246,7 +250,7 @@ static void authenc_verify_ahash_done(st
        ablkcipher_request_set_callback(abreq, aead_request_flags(req),
                                        req->base.complete, req->base.data);
        ablkcipher_request_set_crypt(abreq, req->src, req->dst,
-                                    req->cryptlen, req->iv);
+                                    cryptlen, req->iv);

        err = crypto_ablkcipher_decrypt(abreq);

--- linux-2.6.34/crypto/authenc.c       2010-05-16 23:17:36.000000000 +0200
+++ linux-2.6.34_mod/crypto/authenc.c   2010-05-19 14:32:51.000000000 +0200
@@ -181,6 +181,7 @@ static void authenc_verify_ahash_update_
        struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
        struct authenc_request_ctx *areq_ctx = aead_request_ctx(req);
        struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff);
+       unsigned int cryptlen = req->cryptlen;

        if (err)
                goto out;
@@ -196,6 +197,7 @@ static void authenc_verify_ahash_update_
                goto out;

        authsize = crypto_aead_authsize(authenc);
+       cryptlen -= authsize;
        ihash = ahreq->result + authsize;
        scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen,
                                 authsize, 0);
@@ -209,7 +211,7 @@ static void authenc_verify_ahash_update_
        ablkcipher_request_set_callback(abreq, aead_request_flags(req),
                                        req->base.complete, req->base.data);
        ablkcipher_request_set_crypt(abreq, req->src, req->dst,
-                                    req->cryptlen, req->iv);
+                                    cryptlen, req->iv);

        err = crypto_ablkcipher_decrypt(abreq);

@@ -228,11 +230,13 @@ static void authenc_verify_ahash_done(st
        struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
        struct authenc_request_ctx *areq_ctx = aead_request_ctx(req);
        struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff);
+       unsigned int cryptlen = req->cryptlen;

        if (err)
                goto out;

        authsize = crypto_aead_authsize(authenc);
+       cryptlen -= authsize;
        ihash = ahreq->result + authsize;
        scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen,
                                 authsize, 0);
@@ -246,7 +250,7 @@ static void authenc_verify_ahash_done(st
        ablkcipher_request_set_callback(abreq, aead_request_flags(req),
                                        req->base.complete, req->base.data);
        ablkcipher_request_set_crypt(abreq, req->src, req->dst,
-                                    req->cryptlen, req->iv);
+                                    cryptlen, req->iv);

        err = crypto_ablkcipher_decrypt(abreq);

 --------
--
To unsubscribe from this list: send the line "unsubscribe linux-crypto" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to