From 48ef0908b81cc6b92ec8b157bb78ce2c4eddd7c7 Mon Sep 17 00:00:00 2001 From: Lars Persson Date: Wed, 23 Jan 2019 12:59:44 +0100 Subject: crypto: axis - support variable AEAD tag length The implementation assumed that the client always wants the whole 16 byte AES-GCM tag. Now we respect the requested authentication tag size fetched using crypto_aead_authsize(). Signed-off-by: Lars Persson Signed-off-by: Herbert Xu --- drivers/crypto/axis/artpec6_crypto.c | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) (limited to 'drivers/crypto') diff --git a/drivers/crypto/axis/artpec6_crypto.c b/drivers/crypto/axis/artpec6_crypto.c index e8a57b9e1c7a..5089ad2c49f9 100644 --- a/drivers/crypto/axis/artpec6_crypto.c +++ b/drivers/crypto/axis/artpec6_crypto.c @@ -1907,7 +1907,7 @@ static int artpec6_crypto_prepare_aead(struct aead_request *areq) /* For the decryption, cryptlen includes the tag. */ input_length = areq->cryptlen; if (req_ctx->decrypt) - input_length -= AES_BLOCK_SIZE; + input_length -= crypto_aead_authsize(cipher); /* Prepare the context buffer */ req_ctx->hw_ctx.aad_length_bits = @@ -1972,7 +1972,7 @@ static int artpec6_crypto_prepare_aead(struct aead_request *areq) size_t output_len = areq->cryptlen; if (req_ctx->decrypt) - output_len -= AES_BLOCK_SIZE; + output_len -= crypto_aead_authsize(cipher); artpec6_crypto_walk_init(&walk, areq->dst); @@ -2001,19 +2001,32 @@ static int artpec6_crypto_prepare_aead(struct aead_request *areq) * the output ciphertext. For decryption it is put in a context * buffer for later compare against the input tag. */ - count = AES_BLOCK_SIZE; if (req_ctx->decrypt) { ret = artpec6_crypto_setup_in_descr(common, - req_ctx->decryption_tag, count, false); + req_ctx->decryption_tag, AES_BLOCK_SIZE, false); if (ret) return ret; } else { + /* For encryption the requested tag size may be smaller + * than the hardware's generated tag. + */ + size_t authsize = crypto_aead_authsize(cipher); + ret = artpec6_crypto_setup_sg_descrs_in(common, &walk, - count); + authsize); if (ret) return ret; + + if (authsize < AES_BLOCK_SIZE) { + count = AES_BLOCK_SIZE - authsize; + ret = artpec6_crypto_setup_in_descr(common, + ac->pad_buffer, + count, false); + if (ret) + return ret; + } } } @@ -2174,27 +2187,29 @@ static void artpec6_crypto_complete_aead(struct crypto_async_request *req) /* Verify GCM hashtag. */ struct aead_request *areq = container_of(req, struct aead_request, base); + struct crypto_aead *aead = crypto_aead_reqtfm(areq); struct artpec6_crypto_aead_req_ctx *req_ctx = aead_request_ctx(areq); if (req_ctx->decrypt) { u8 input_tag[AES_BLOCK_SIZE]; + unsigned int authsize = crypto_aead_authsize(aead); sg_pcopy_to_buffer(areq->src, sg_nents(areq->src), input_tag, - AES_BLOCK_SIZE, + authsize, areq->assoclen + areq->cryptlen - - AES_BLOCK_SIZE); + authsize); if (memcmp(req_ctx->decryption_tag, input_tag, - AES_BLOCK_SIZE)) { + authsize)) { pr_debug("***EBADMSG:\n"); print_hex_dump_debug("ref:", DUMP_PREFIX_ADDRESS, 32, 1, - input_tag, AES_BLOCK_SIZE, true); + input_tag, authsize, true); print_hex_dump_debug("out:", DUMP_PREFIX_ADDRESS, 32, 1, req_ctx->decryption_tag, - AES_BLOCK_SIZE, true); + authsize, true); result = -EBADMSG; } -- cgit v1.2.3