[-stable] crypto: ccm - deal with CTR ciphers that honour iv_out

Message ID 1485636005-5192-1-git-send-email-ard.biesheuvel@linaro.org
State New
Headers show

Commit Message

Ard Biesheuvel Jan. 28, 2017, 8:40 p.m.
The skcipher API mandates that chaining modes involving IVs calculate
an outgoing IV value that is suitable for encrypting additional blocks
of data. This means the CCM driver cannot assume that req->iv points to
the original IV value when it calls crypto_ccm_auth. So pass a copy to
the skcipher instead.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>

---
 crypto/ccm.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

-- 
2.7.4

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

Comments

Ard Biesheuvel Feb. 1, 2017, 8:08 p.m. | #1
On 28 January 2017 at 20:40, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
> The skcipher API mandates that chaining modes involving IVs calculate

> an outgoing IV value that is suitable for encrypting additional blocks

> of data. This means the CCM driver cannot assume that req->iv points to

> the original IV value when it calls crypto_ccm_auth. So pass a copy to

> the skcipher instead.

>

> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>

> ---

>  crypto/ccm.c | 3 ++-

>  1 file changed, 2 insertions(+), 1 deletion(-)

>

> diff --git a/crypto/ccm.c b/crypto/ccm.c

> index b388ac6edfb9..8976ef9bc2e7 100644

> --- a/crypto/ccm.c

> +++ b/crypto/ccm.c

> @@ -362,7 +362,7 @@ static int crypto_ccm_decrypt(struct aead_request *req)

>         unsigned int cryptlen = req->cryptlen;

>         u8 *authtag = pctx->auth_tag;

>         u8 *odata = pctx->odata;

> -       u8 *iv = req->iv;

> +       u8 iv[16];

>         int err;

>

>         cryptlen -= authsize;

> @@ -378,6 +378,7 @@ static int crypto_ccm_decrypt(struct aead_request *req)

>         if (req->src != req->dst)

>                 dst = pctx->dst;

>

> +       memcpy(iv, req->iv, sizeof(iv));

>         skcipher_request_set_tfm(skreq, ctx->ctr);

>         skcipher_request_set_callback(skreq, pctx->flags,

>                                       crypto_ccm_decrypt_done, req);

> --

> 2.7.4

>


Herbert,

Could you please forward this patch to Linus as well? I noticed that the patch

crypto: arm64/aes-blk - honour iv_out requirement in CBC and CTR modes

is now in mainline, which means CCM is now broken on arm64, given that
the iv_out requirement for CTR apparently isn't honored by *any*
implementation, and CCM wrongly assumes that req->iv retains its value
across the call into the CTR skcipher

Thanks,
Ard.
Herbert Xu Feb. 2, 2017, 5:13 a.m. | #2
On Wed, Feb 01, 2017 at 08:08:09PM +0000, Ard Biesheuvel wrote:
>

> Could you please forward this patch to Linus as well? I noticed that the patch


Sure, I will do that.

> crypto: arm64/aes-blk - honour iv_out requirement in CBC and CTR modes

> 

> is now in mainline, which means CCM is now broken on arm64, given that

> the iv_out requirement for CTR apparently isn't honored by *any*

> implementation, and CCM wrongly assumes that req->iv retains its value

> across the call into the CTR skcipher


Hmm, I wonder why we don't see this breakage with the generic
CTR as it seems to do exactly the same thing.

Cheers,
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
Ard Biesheuvel Feb. 2, 2017, 8:01 a.m. | #3
On 2 February 2017 at 05:13, Herbert Xu <herbert@gondor.apana.org.au> wrote:
> On Wed, Feb 01, 2017 at 08:08:09PM +0000, Ard Biesheuvel wrote:

>>

>> Could you please forward this patch to Linus as well? I noticed that the patch

>

> Sure, I will do that.

>

>> crypto: arm64/aes-blk - honour iv_out requirement in CBC and CTR modes

>>

>> is now in mainline, which means CCM is now broken on arm64, given that

>> the iv_out requirement for CTR apparently isn't honored by *any*

>> implementation, and CCM wrongly assumes that req->iv retains its value

>> across the call into the CTR skcipher

>

> Hmm, I wonder why we don't see this breakage with the generic

> CTR as it seems to do exactly the same thing.

>


You are right: due to its construction, the CCM mode does not care
about the incremented counter because it clears the counter part of
the IV before encrypting the MAC. So this is caused by an optimization
in my code rather than the CCM code being incorrect.
Herbert Xu Feb. 2, 2017, 9:53 a.m. | #4
On Thu, Feb 02, 2017 at 08:01:47AM +0000, Ard Biesheuvel wrote:
>

> You are right: due to its construction, the CCM mode does not care

> about the incremented counter because it clears the counter part of

> the IV before encrypting the MAC. So this is caused by an optimization

> in my code rather than the CCM code being incorrect.


OK so you will send me an update for the ARM64 code, right?

Thanks,
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
Ard Biesheuvel Feb. 2, 2017, 11:39 a.m. | #5
On 2 February 2017 at 09:53, Herbert Xu <herbert@gondor.apana.org.au> wrote:
> On Thu, Feb 02, 2017 at 08:01:47AM +0000, Ard Biesheuvel wrote:

>>

>> You are right: due to its construction, the CCM mode does not care

>> about the incremented counter because it clears the counter part of

>> the IV before encrypting the MAC. So this is caused by an optimization

>> in my code rather than the CCM code being incorrect.

>

> OK so you will send me an update for the ARM64 code, right?

>


Yes, on their way

Thanks,
Ard.

Patch hide | download patch | download mbox

diff --git a/crypto/ccm.c b/crypto/ccm.c
index b388ac6edfb9..8976ef9bc2e7 100644
--- a/crypto/ccm.c
+++ b/crypto/ccm.c
@@ -362,7 +362,7 @@  static int crypto_ccm_decrypt(struct aead_request *req)
 	unsigned int cryptlen = req->cryptlen;
 	u8 *authtag = pctx->auth_tag;
 	u8 *odata = pctx->odata;
-	u8 *iv = req->iv;
+	u8 iv[16];
 	int err;
 
 	cryptlen -= authsize;
@@ -378,6 +378,7 @@  static int crypto_ccm_decrypt(struct aead_request *req)
 	if (req->src != req->dst)
 		dst = pctx->dst;
 
+	memcpy(iv, req->iv, sizeof(iv));
 	skcipher_request_set_tfm(skreq, ctx->ctr);
 	skcipher_request_set_callback(skreq, pctx->flags,
 				      crypto_ccm_decrypt_done, req);