From d7af2baa49c60c097d77986f49d7c2db06080c8e Mon Sep 17 00:00:00 2001 From: Breno Lima Date: Wed, 17 Jan 2018 10:03:45 -0200 Subject: crypto/fsl: Fix HW accelerated hash commands The hash command function were not flushing the dcache before passing data to CAAM/DMA and not invalidating the dcache when getting data back. Due the data cache incoherency, HW accelerated hash commands used to fail with CAAM errors like "Invalid KEY Command". Check if pbuf and pout buffers are properly aligned to the cache line size and flush/invalidate the memory regions to address this issue. This solution is based in a previous work from Clemens Gruber in commit 598e9dccc75d ("crypto/fsl: fix BLOB encapsulation and decapsulation") Reported-by: Anatolij Gustschin Signed-off-by: Breno Lima Reviewed-by: York Sun --- drivers/crypto/fsl/fsl_hash.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) (limited to 'drivers/crypto') diff --git a/drivers/crypto/fsl/fsl_hash.c b/drivers/crypto/fsl/fsl_hash.c index a63eba389d..9373a39931 100644 --- a/drivers/crypto/fsl/fsl_hash.c +++ b/drivers/crypto/fsl/fsl_hash.c @@ -7,6 +7,7 @@ #include #include +#include #include "jobdesc.h" #include "desc.h" #include "jr.h" @@ -163,20 +164,37 @@ int caam_hash(const unsigned char *pbuf, unsigned int buf_len, { int ret = 0; uint32_t *desc; + unsigned int size; - desc = malloc(sizeof(int) * MAX_CAAM_DESCSIZE); + desc = malloc_cache_aligned(sizeof(int) * MAX_CAAM_DESCSIZE); if (!desc) { debug("Not enough memory for descriptor allocation\n"); return -ENOMEM; } + if (!IS_ALIGNED((uintptr_t)pbuf, ARCH_DMA_MINALIGN) || + !IS_ALIGNED((uintptr_t)pout, ARCH_DMA_MINALIGN)) { + puts("Error: Address arguments are not aligned\n"); + return -EINVAL; + } + + size = ALIGN(buf_len, ARCH_DMA_MINALIGN); + flush_dcache_range((unsigned long)pbuf, (unsigned long)pbuf + size); + inline_cnstr_jobdesc_hash(desc, pbuf, buf_len, pout, driver_hash[algo].alg_type, driver_hash[algo].digestsize, 0); + size = ALIGN(sizeof(int) * MAX_CAAM_DESCSIZE, ARCH_DMA_MINALIGN); + flush_dcache_range((unsigned long)desc, (unsigned long)desc + size); + ret = run_descriptor_jr(desc); + size = ALIGN(driver_hash[algo].digestsize, ARCH_DMA_MINALIGN); + invalidate_dcache_range((unsigned long)pout, + (unsigned long)pout + size); + free(desc); return ret; } -- cgit