Skip to contentSkip to conversation

crypto/fsl: fix BLOB encapsulation and decapsulation

PATCH New Fabio Estevam 4 participants 6 messages Jan 4, 2018 – Jan 5, 2018 Crypto API

lore
Share & tools
lore
#0 lore raw

PATCH v2 1/1 crypto/fsl: fix BLOB encapsulation and decapsulation

From: Clemens Gruber <[email protected]>

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.

[fabio: Make BLOB_SIZE() macro available for other archs]

---
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(-)
drivers/crypto/fsl/fsl_blob.c +83 -16
index 38c6f94..65ce21f 100644
@@ -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;
 }
include/fsl_sec.h +2 -2
index 61c671d..e4332d3 100644
@@ -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
Signature · 1 line
2.7.4
Applied
#1 lore raw

PATCH v2 1/1 crypto/fsl: fix BLOB encapsulation and decapsulation

Quoted 16 lines · Fabio Estevam

From: Clemens Gruber <[email protected]>

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.

Quoted 8 lines
[fabio: Make BLOB_SIZE() macro available for other archs]

---
Changes since v1:
- Make BLOB_SIZE() macro available for other archs

Applied to fsl-qoriq master, awaiting upstream. Thanks.

York

#2 lore raw

PATCH v2 1/1 crypto/fsl: fix BLOB encapsulation and decapsulation

In reply to Fabio Estevam

Hi Clemens, York, Fabio,

Quoted 10 lines

-----Original Message-----
From: U-Boot [mailto:u-boot-bounces at lists.denx.de] On Behalf Of Fabio Estevam
Sent: Friday, January 05, 2018 3:27 AM
To: York Sun <[email protected]>
Cc: Breno Matheus Lima <[email protected]>; u-boot at lists.denx.de; clemens.gruber at pqgruber.com; Fabio Estevam <[email protected]>
Subject: [U-Boot] [PATCH v2] crypto/fsl: fix BLOB encapsulation and decapsulation

<snip>

Quoted 10 lines

int blob_decap(u8 *key_mod, u8 *src, u8 *dst, u32 len) {

drivers/crypto/fsl/fsl_blob.c +3 -2
-	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);

drivers/crypto/fsl/fsl_blob.c line 32

Quoted 10 lines
drivers/crypto/fsl/fsl_blob.c +4 -2
+	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.

Quoted 60 lines
drivers/crypto/fsl/fsl_blob.c +16 -0
+	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,

drivers/crypto/fsl/fsl_blob.c +3 -0
+					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);

drivers/crypto/fsl/fsl_blob.c +18 -6
+	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);

drivers/crypto/fsl/fsl_blob.c line 93

Quoted 10 lines
drivers/crypto/fsl/fsl_blob.c +4 -2
+	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.

drivers/crypto/fsl/fsl_blob.c line 37

Quoted 5 lines
drivers/crypto/fsl/fsl_blob.c +5 -0
+	if (!aligned_src || !aligned_dst) {
+		debug("Not enough memory for blob allocations\n");
+		return -ENOMEM;
+	}
+

-Sumit

#3 lore raw

PATCH v2 1/1 crypto/fsl: fix BLOB encapsulation and decapsulation

Hi Sumit, Fabio, York,

Quoted 38 lines · Sumit Garg

Hi Clemens, York, Fabio,

Quoted 10 lines

-----Original Message-----
From: U-Boot [mailto:u-boot-bounces at lists.denx.de] On Behalf Of Fabio Estevam
Sent: Friday, January 05, 2018 3:27 AM
To: York Sun <[email protected]>
Cc: Breno Matheus Lima <[email protected]>; u-boot at lists.denx.de; clemens.gruber at pqgruber.com; Fabio Estevam <[email protected]>
Subject: [U-Boot] [PATCH v2] crypto/fsl: fix BLOB encapsulation and decapsulation

<snip>

Quoted 10 lines

int blob_decap(u8 *key_mod, u8 *src, u8 *dst, u32 len) {

drivers/crypto/fsl/fsl_blob.c +3 -2
-	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);

drivers/crypto/fsl/fsl_blob.c line 32

Quoted 10 lines
drivers/crypto/fsl/fsl_blob.c +4 -2
+	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.

Quoted 6 lines

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

#4 lore raw

PATCH v2 1/1 crypto/fsl: fix BLOB encapsulation and decapsulation

Quoted 49 lines

From: Clemens Gruber [mailto:clemens.gruber at pqgruber.com]
Sent: Friday, January 05, 2018 6:32 PM

Hi Sumit, Fabio, York,

Quoted 9 lines · Sumit Garg

Hi Clemens, York, Fabio,

Quoted 7 lines

-----Original Message-----
From: U-Boot [mailto:u-boot-bounces at lists.denx.de] On Behalf Of Fabio Estevam
Sent: Friday, January 05, 2018 3:27 AM
To: York Sun <[email protected]>
Cc: Breno Matheus Lima <[email protected]>; u-boot at lists.denx.de; clemens.gruber at pqgruber.com; Fabio Estevam

<[email protected]>

Quoted 23 lines
Quoted 3 lines

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

<snip>

Quoted 17 lines

int blob_decap(u8 *key_mod, u8 *src, u8 *dst, u32 len) {

drivers/crypto/fsl/fsl_blob.c +5 -3
-	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;
 	}
Quoted 5 lines

drivers/crypto/fsl/fsl_blob.c line 32

Quoted 3 lines
drivers/crypto/fsl/fsl_blob.c +2 -1
-	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.

Quoted 3 lines

But u-boot malloc pool is of size:

Quoted 8 lines
Quoted 4 lines

/* 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).

Quoted 4 lines

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

Quoted 4 lines

York: Should I send a v3 or a fixup patch ontop of v2.

Thanks,
Clemens

#5 lore raw

PATCH v2 1/1 crypto/fsl: fix BLOB encapsulation and decapsulation

In reply to Clemens Gruber

On 01/05/2018 05:02 AM, Clemens Gruber wrote:

<snip>

Quoted 2 lines

York: Should I send a v3 or a fixup patch ontop of v2.

I have reset my git head. Please send v3 patch.

York