Commit d7af2baa49c60c097d77986f49d7c2db06080c8e

Authored by Breno Lima
Committed by York Sun
1 parent 6d48d1c4b4

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 <agust@denx.de>
Signed-off-by: Breno Lima <breno.lima@nxp.com>
Reviewed-by: York Sun <york.sun@nxp.com>

Showing 2 changed files with 25 additions and 2 deletions Side-by-side Diff

... ... @@ -390,7 +390,7 @@
390 390  
391 391 if (multi_hash()) {
392 392 struct hash_algo *algo;
393   - uint8_t output[HASH_MAX_DIGEST_SIZE];
  393 + u8 *output;
394 394 uint8_t vsum[HASH_MAX_DIGEST_SIZE];
395 395 void *buf;
396 396  
... ... @@ -405,6 +405,9 @@
405 405 return 1;
406 406 }
407 407  
  408 + output = memalign(ARCH_DMA_MINALIGN,
  409 + sizeof(uint32_t) * HASH_MAX_DIGEST_SIZE);
  410 +
408 411 buf = map_sysmem(addr, len);
409 412 algo->hash_func_ws(buf, len, output, algo->chunk_size);
410 413 unmap_sysmem(buf);
... ... @@ -440,6 +443,8 @@
440 443 store_result(algo, output, *argv,
441 444 flags & HASH_FLAG_ENV);
442 445 }
  446 + unmap_sysmem(output);
  447 +
443 448 }
444 449  
445 450 /* Horrible code size hack for boards that just want crc32 */
drivers/crypto/fsl/fsl_hash.c
... ... @@ -7,6 +7,7 @@
7 7  
8 8 #include <common.h>
9 9 #include <malloc.h>
  10 +#include <memalign.h>
10 11 #include "jobdesc.h"
11 12 #include "desc.h"
12 13 #include "jr.h"
13 14  
14 15  
15 16  
16 17  
... ... @@ -163,19 +164,36 @@
163 164 {
164 165 int ret = 0;
165 166 uint32_t *desc;
  167 + unsigned int size;
166 168  
167   - desc = malloc(sizeof(int) * MAX_CAAM_DESCSIZE);
  169 + desc = malloc_cache_aligned(sizeof(int) * MAX_CAAM_DESCSIZE);
168 170 if (!desc) {
169 171 debug("Not enough memory for descriptor allocation\n");
170 172 return -ENOMEM;
171 173 }
172 174  
  175 + if (!IS_ALIGNED((uintptr_t)pbuf, ARCH_DMA_MINALIGN) ||
  176 + !IS_ALIGNED((uintptr_t)pout, ARCH_DMA_MINALIGN)) {
  177 + puts("Error: Address arguments are not aligned\n");
  178 + return -EINVAL;
  179 + }
  180 +
  181 + size = ALIGN(buf_len, ARCH_DMA_MINALIGN);
  182 + flush_dcache_range((unsigned long)pbuf, (unsigned long)pbuf + size);
  183 +
173 184 inline_cnstr_jobdesc_hash(desc, pbuf, buf_len, pout,
174 185 driver_hash[algo].alg_type,
175 186 driver_hash[algo].digestsize,
176 187 0);
177 188  
  189 + size = ALIGN(sizeof(int) * MAX_CAAM_DESCSIZE, ARCH_DMA_MINALIGN);
  190 + flush_dcache_range((unsigned long)desc, (unsigned long)desc + size);
  191 +
178 192 ret = run_descriptor_jr(desc);
  193 +
  194 + size = ALIGN(driver_hash[algo].digestsize, ARCH_DMA_MINALIGN);
  195 + invalidate_dcache_range((unsigned long)pout,
  196 + (unsigned long)pout + size);
179 197  
180 198 free(desc);
181 199 return ret;