[U-Boot] [PATCH v2] crypto/fsl: fix BLOB encapsulation and decapsulation

From: Clemens Gruber clemens.gruber@pqgruber.com
The blob_encap and blob_decap functions were not flushing the dcache before passing data to CAAM/DMA and not invalidating the dcache when getting data back. Therefore, blob encapsulation and decapsulation failed with errors like the following due to data cache incoherency: "40000006: DECO: desc idx 0: Invalid KEY command"
To ensure coherency, we allocate aligned memory to store the data passed to/from CAAM and flush/invalidate the memory regions. Blobs can now be encapsulated and decapsulated with the blob cmd as well as from board code by calling blob_encap and blob_decap directly.
Tested on an i.MX6Q board.
Signed-off-by: Clemens Gruber clemens.gruber@pqgruber.com [fabio: Make BLOB_SIZE() macro available for other archs] Signed-off-by: Fabio Estevam fabio.estevam@nxp.com Tested-by: Breno Lima breno.lima@nxp.com --- Changes since v1: - Make BLOB_SIZE() macro available for other archs
drivers/crypto/fsl/fsl_blob.c | 99 ++++++++++++++++++++++++++++++++++++------- include/fsl_sec.h | 4 +- 2 files changed, 85 insertions(+), 18 deletions(-)
diff --git a/drivers/crypto/fsl/fsl_blob.c b/drivers/crypto/fsl/fsl_blob.c index 38c6f94..65ce21f 100644 --- a/drivers/crypto/fsl/fsl_blob.c +++ b/drivers/crypto/fsl/fsl_blob.c @@ -7,6 +7,7 @@
#include <common.h> #include <malloc.h> +#include <memalign.h> #include <fsl_sec.h> #include <linux/errno.h> #include "jobdesc.h" @@ -15,56 +16,122 @@
int blob_decap(u8 *key_mod, u8 *src, u8 *dst, u32 len) { - int ret, i = 0; + ALLOC_CACHE_ALIGN_BUFFER(u8, aligned_key_mod, 16); + u8 *aligned_src, *aligned_dst; + int ret, size, i = 0; u32 *desc;
printf("\nDecapsulating blob to get data\n"); - 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 -1; + return -ENOMEM; }
- inline_cnstr_jobdesc_blob_decap(desc, key_mod, src, dst, len); + aligned_src = malloc_cache_aligned(BLOB_SIZE(len)); + aligned_dst = malloc_cache_aligned(len); + if (!aligned_src || !aligned_dst) { + debug("Not enough memory for blob allocations\n"); + return -ENOMEM; + } + + memcpy(aligned_key_mod, key_mod, 16); + size = ALIGN(16, ARCH_DMA_MINALIGN); + flush_dcache_range((unsigned long)aligned_key_mod, + (unsigned long)aligned_key_mod + size); + + memcpy(aligned_src, src, BLOB_SIZE(len)); + size = ALIGN(BLOB_SIZE(len), ARCH_DMA_MINALIGN); + flush_dcache_range((unsigned long)aligned_src, + (unsigned long)aligned_src + size); + + inline_cnstr_jobdesc_blob_decap(desc, aligned_key_mod, aligned_src, + aligned_dst, len);
debug("Descriptor dump:\n"); for (i = 0; i < 14; i++) debug("Word[%d]: %08x\n", i, *(desc + i)); + + 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);
- if (ret) - printf("Error in Decapsulation %d\n", ret); - else - printf("Decapsulation Success\n"); + if (ret) { + printf("Error in blob decapsulation: %d\n", ret); + } else { + size = ALIGN(len, ARCH_DMA_MINALIGN); + invalidate_dcache_range((unsigned long)aligned_dst, + (unsigned long)aligned_dst + size); + memcpy(dst, aligned_dst, len); + + puts("Blob decapsulation successful.\n"); + }
+ free(aligned_dst); + free(aligned_src); free(desc); return ret; }
int blob_encap(u8 *key_mod, u8 *src, u8 *dst, u32 len) { - int ret, i = 0; + ALLOC_CACHE_ALIGN_BUFFER(u8, aligned_key_mod, 16); + u8 *aligned_src, *aligned_dst; + int ret, size, i = 0; u32 *desc;
printf("\nEncapsulating data to form blob\n"); - 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 -1; + return -ENOMEM; }
- inline_cnstr_jobdesc_blob_encap(desc, key_mod, src, dst, len); + aligned_src = malloc_cache_aligned(len); + aligned_dst = malloc_cache_aligned(BLOB_SIZE(len)); + if (!aligned_src || !aligned_dst) { + debug("Not enough memory for blob allocations\n"); + return -ENOMEM; + } + + memcpy(aligned_key_mod, key_mod, 16); + size = ALIGN(16, ARCH_DMA_MINALIGN); + flush_dcache_range((unsigned long)aligned_key_mod, + (unsigned long)aligned_key_mod + size); + + memcpy(aligned_src, src, len); + size = ALIGN(len, ARCH_DMA_MINALIGN); + flush_dcache_range((unsigned long)aligned_src, + (unsigned long)aligned_src + size); + + inline_cnstr_jobdesc_blob_encap(desc, aligned_key_mod, aligned_src, + aligned_dst, len);
debug("Descriptor dump:\n"); for (i = 0; i < 14; i++) debug("Word[%d]: %08x\n", i, *(desc + i)); + + 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);
- if (ret) - printf("Error in Encapsulation %d\n", ret); - else - printf("Encapsulation Success\n"); + if (ret) { + printf("Error in blob encapsulation: %d\n", ret); + } else { + size = ALIGN(BLOB_SIZE(len), ARCH_DMA_MINALIGN); + invalidate_dcache_range((unsigned long)aligned_dst, + (unsigned long)aligned_dst + size); + memcpy(dst, aligned_dst, BLOB_SIZE(len)); + + puts("Blob encapsulation successful.\n"); + }
+ free(aligned_dst); + free(aligned_src); free(desc); return ret; } diff --git a/include/fsl_sec.h b/include/fsl_sec.h index 61c671d..e4332d3 100644 --- a/include/fsl_sec.h +++ b/include/fsl_sec.h @@ -215,6 +215,8 @@ struct sg_entry { #define SG_ENTRY_OFFSET_SHIFT 0 };
+#define BLOB_SIZE(x) (x + 32 + 16) /* Blob buffer size */ + #if defined(CONFIG_MX6) || defined(CONFIG_MX7) /* Job Ring Base Address */ #define JR_BASE_ADDR(x) (CONFIG_SYS_FSL_SEC_ADDR + 0x1000 * (x + 1)) @@ -274,8 +276,6 @@ struct sg_entry { #define PERM 0x0000B008 /* Clear on release, lock SMAP * lock SMAG group 1 Blob */
-#define BLOB_SIZE(x) (x + 32 + 16) /* Blob buffer size */ - /* HAB WRAPPED KEY header */ #define WRP_HDR_SIZE 0x08 #define HDR_TAG 0x81

On 01/04/2018 01:57 PM, Fabio Estevam wrote:
From: Clemens Gruber clemens.gruber@pqgruber.com
The blob_encap and blob_decap functions were not flushing the dcache before passing data to CAAM/DMA and not invalidating the dcache when getting data back. Therefore, blob encapsulation and decapsulation failed with errors like the following due to data cache incoherency: "40000006: DECO: desc idx 0: Invalid KEY command"
To ensure coherency, we allocate aligned memory to store the data passed to/from CAAM and flush/invalidate the memory regions. Blobs can now be encapsulated and decapsulated with the blob cmd as well as from board code by calling blob_encap and blob_decap directly.
Tested on an i.MX6Q board.
Signed-off-by: Clemens Gruber clemens.gruber@pqgruber.com [fabio: Make BLOB_SIZE() macro available for other archs] Signed-off-by: Fabio Estevam fabio.estevam@nxp.com Tested-by: Breno Lima breno.lima@nxp.com
Changes since v1:
- Make BLOB_SIZE() macro available for other archs
Applied to fsl-qoriq master, awaiting upstream. Thanks.
York

Hi Clemens, York, Fabio,
-----Original Message----- From: U-Boot [mailto:u-boot-bounces@lists.denx.de] On Behalf Of Fabio Estevam Sent: Friday, January 05, 2018 3:27 AM To: York Sun york.sun@nxp.com Cc: Breno Matheus Lima breno.lima@nxp.com; u-boot@lists.denx.de; clemens.gruber@pqgruber.com; Fabio Estevam fabio.estevam@nxp.com Subject: [U-Boot] [PATCH v2] crypto/fsl: fix BLOB encapsulation and decapsulation
<snip>
int blob_decap(u8 *key_mod, u8 *src, u8 *dst, u32 len) {
- int ret, i = 0;
ALLOC_CACHE_ALIGN_BUFFER(u8, aligned_key_mod, 16);
u8 *aligned_src, *aligned_dst;
int ret, size, i = 0; u32 *desc;
printf("\nDecapsulating blob to get data\n");
- 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 -1;
}return -ENOMEM;
- inline_cnstr_jobdesc_blob_decap(desc, key_mod, src, dst, len);
- aligned_src = malloc_cache_aligned(BLOB_SIZE(len));
- aligned_dst = malloc_cache_aligned(len);
Please don't use malloc here as these blob_encap and blob_decap commands are used to blobify or deblobify images of maximum sizes upto 32 MB.
But u-boot malloc pool is of size:
/* Size of malloc() pool */ #define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + 2048 * 1024)
So please remove malloc from this patch for source and destination images as it will fail for larger images.
- if (!aligned_src || !aligned_dst) {
debug("Not enough memory for blob allocations\n");
return -ENOMEM;
- }
- memcpy(aligned_key_mod, key_mod, 16);
- size = ALIGN(16, ARCH_DMA_MINALIGN);
- flush_dcache_range((unsigned long)aligned_key_mod,
(unsigned long)aligned_key_mod + size);
- memcpy(aligned_src, src, BLOB_SIZE(len));
- size = ALIGN(BLOB_SIZE(len), ARCH_DMA_MINALIGN);
- flush_dcache_range((unsigned long)aligned_src,
(unsigned long)aligned_src + size);
- inline_cnstr_jobdesc_blob_decap(desc, aligned_key_mod,
aligned_src,
aligned_dst, len);
debug("Descriptor dump:\n"); for (i = 0; i < 14; i++) debug("Word[%d]: %08x\n", i, *(desc + i));
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);
- if (ret)
printf("Error in Decapsulation %d\n", ret);
- else
printf("Decapsulation Success\n");
if (ret) {
printf("Error in blob decapsulation: %d\n", ret);
} else {
size = ALIGN(len, ARCH_DMA_MINALIGN);
invalidate_dcache_range((unsigned long)aligned_dst,
(unsigned long)aligned_dst + size);
memcpy(dst, aligned_dst, len);
puts("Blob decapsulation successful.\n");
}
free(aligned_dst);
free(aligned_src); free(desc); return ret;
}
int blob_encap(u8 *key_mod, u8 *src, u8 *dst, u32 len) {
- int ret, i = 0;
ALLOC_CACHE_ALIGN_BUFFER(u8, aligned_key_mod, 16);
u8 *aligned_src, *aligned_dst;
int ret, size, i = 0; u32 *desc;
printf("\nEncapsulating data to form blob\n");
- 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 -1;
}return -ENOMEM;
- inline_cnstr_jobdesc_blob_encap(desc, key_mod, src, dst, len);
- aligned_src = malloc_cache_aligned(len);
- aligned_dst = malloc_cache_aligned(BLOB_SIZE(len));
Same here as above. Please remove malloc from this patch.
- if (!aligned_src || !aligned_dst) {
debug("Not enough memory for blob allocations\n");
return -ENOMEM;
- }
-Sumit

Hi Sumit, Fabio, York,
On Fri, Jan 05, 2018 at 06:47:36AM +0000, Sumit Garg wrote:
Hi Clemens, York, Fabio,
-----Original Message----- From: U-Boot [mailto:u-boot-bounces@lists.denx.de] On Behalf Of Fabio Estevam Sent: Friday, January 05, 2018 3:27 AM To: York Sun york.sun@nxp.com Cc: Breno Matheus Lima breno.lima@nxp.com; u-boot@lists.denx.de; clemens.gruber@pqgruber.com; Fabio Estevam fabio.estevam@nxp.com Subject: [U-Boot] [PATCH v2] crypto/fsl: fix BLOB encapsulation and decapsulation
<snip>
int blob_decap(u8 *key_mod, u8 *src, u8 *dst, u32 len) {
- int ret, i = 0;
ALLOC_CACHE_ALIGN_BUFFER(u8, aligned_key_mod, 16);
u8 *aligned_src, *aligned_dst;
int ret, size, i = 0; u32 *desc;
printf("\nDecapsulating blob to get data\n");
- 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 -1;
}return -ENOMEM;
- inline_cnstr_jobdesc_blob_decap(desc, key_mod, src, dst, len);
- aligned_src = malloc_cache_aligned(BLOB_SIZE(len));
- aligned_dst = malloc_cache_aligned(len);
Please don't use malloc here as these blob_encap and blob_decap commands are used to blobify or deblobify images of maximum sizes upto 32 MB.
But u-boot malloc pool is of size:
/* Size of malloc() pool */ #define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + 2048 * 1024)
So please remove malloc from this patch for source and destination images as it will fail for larger images.
I could use ALLOC_CACHE_ALIGN_BUFFER to store the aligned_src and _dst buffers on the stack instead of the malloc pool.
Or would you rather remove the copying and require the caller of blob_encap/_decap to pass correctly aligned addresses?
York: Should I send a v3 or a fixup patch ontop of v2.
Thanks, Clemens

From: Clemens Gruber [mailto:clemens.gruber@pqgruber.com] Sent: Friday, January 05, 2018 6:32 PM
Hi Sumit, Fabio, York,
On Fri, Jan 05, 2018 at 06:47:36AM +0000, Sumit Garg wrote:
Hi Clemens, York, Fabio,
-----Original Message----- From: U-Boot [mailto:u-boot-bounces@lists.denx.de] On Behalf Of Fabio Estevam Sent: Friday, January 05, 2018 3:27 AM To: York Sun york.sun@nxp.com Cc: Breno Matheus Lima breno.lima@nxp.com; u-boot@lists.denx.de; clemens.gruber@pqgruber.com; Fabio Estevam
Subject: [U-Boot] [PATCH v2] crypto/fsl: fix BLOB encapsulation and decapsulation
<snip>
int blob_decap(u8 *key_mod, u8 *src, u8 *dst, u32 len) {
- int ret, i = 0;
ALLOC_CACHE_ALIGN_BUFFER(u8, aligned_key_mod, 16);
u8 *aligned_src, *aligned_dst;
int ret, size, i = 0; u32 *desc;
printf("\nDecapsulating blob to get data\n");
- 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 -1;
}return -ENOMEM;
- inline_cnstr_jobdesc_blob_decap(desc, key_mod, src, dst, len);
- aligned_src = malloc_cache_aligned(BLOB_SIZE(len));
- aligned_dst = malloc_cache_aligned(len);
Please don't use malloc here as these blob_encap and blob_decap
commands are used to blobify or deblobify images of maximum sizes upto 32 MB.
But u-boot malloc pool is of size:
/* Size of malloc() pool */ #define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + 2048 * 1024)
So please remove malloc from this patch for source and destination images as
it will fail for larger images.
I could use ALLOC_CACHE_ALIGN_BUFFER to store the aligned_src and _dst buffers on the stack instead of the malloc pool.
I don't think stack is enough to save src and dest images (max. size: approx. 64MB).
Or would you rather remove the copying and require the caller of blob_encap/_decap to pass correctly aligned addresses?
Yes you could put check for input src and dest addresses to be cache aligned and print error to make user aware to pass cache aligned addresses. Also double copying will be much overhead for encap or decap of images (size 32MB).
-Sumit
York: Should I send a v3 or a fixup patch ontop of v2.
Thanks, Clemens
participants (4)
-
Clemens Gruber
-
Fabio Estevam
-
Sumit Garg
-
York Sun