diff mbox series

[U-Boot] crypto/fsl: Fix HW accelerated hash commands

Message ID 1516190625-3653-1-git-send-email-breno.lima@nxp.com
State Accepted
Commit d7af2baa49c60c097d77986f49d7c2db06080c8e
Delegated to: York Sun
Headers show
Series [U-Boot] crypto/fsl: Fix HW accelerated hash commands | expand

Commit Message

Breno Matheus Lima Jan. 17, 2018, 12:03 p.m. UTC
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 <agust@denx.de>
Signed-off-by: Breno Lima <breno.lima@nxp.com>
---
 common/hash.c                 |  7 ++++++-
 drivers/crypto/fsl/fsl_hash.c | 20 +++++++++++++++++++-
 2 files changed, 25 insertions(+), 2 deletions(-)

Comments

York Sun Jan. 24, 2018, 7:13 p.m. UTC | #1
On 01/17/2018 04:02 AM, Breno Lima wrote:
> 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 <agust@denx.de>
> Signed-off-by: Breno Lima <breno.lima@nxp.com>
> ---

Applied to fsl-qoriq master. Thanks.

York
diff mbox series

Patch

diff --git a/common/hash.c b/common/hash.c
index cf4d70f..69d53ed 100644
--- a/common/hash.c
+++ b/common/hash.c
@@ -390,7 +390,7 @@  int hash_command(const char *algo_name, int flags, cmd_tbl_t *cmdtp, int flag,
 
 	if (multi_hash()) {
 		struct hash_algo *algo;
-		uint8_t output[HASH_MAX_DIGEST_SIZE];
+		u8 *output;
 		uint8_t vsum[HASH_MAX_DIGEST_SIZE];
 		void *buf;
 
@@ -405,6 +405,9 @@  int hash_command(const char *algo_name, int flags, cmd_tbl_t *cmdtp, int flag,
 			return 1;
 		}
 
+		output = memalign(ARCH_DMA_MINALIGN,
+				  sizeof(uint32_t) * HASH_MAX_DIGEST_SIZE);
+
 		buf = map_sysmem(addr, len);
 		algo->hash_func_ws(buf, len, output, algo->chunk_size);
 		unmap_sysmem(buf);
@@ -440,6 +443,8 @@  int hash_command(const char *algo_name, int flags, cmd_tbl_t *cmdtp, int flag,
 				store_result(algo, output, *argv,
 					flags & HASH_FLAG_ENV);
 			}
+		unmap_sysmem(output);
+
 		}
 
 	/* Horrible code size hack for boards that just want crc32 */
diff --git a/drivers/crypto/fsl/fsl_hash.c b/drivers/crypto/fsl/fsl_hash.c
index a63eba3..9373a39 100644
--- a/drivers/crypto/fsl/fsl_hash.c
+++ b/drivers/crypto/fsl/fsl_hash.c
@@ -7,6 +7,7 @@ 
 
 #include <common.h>
 #include <malloc.h>
+#include <memalign.h>
 #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;
 }