summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGaurav Jain <gaurav.jain@nxp.com>2021-07-26 19:29:36 +0530
committerYe Li <ye.li@nxp.com>2022-04-06 18:04:50 +0800
commit12f90b0849f680a0825d48086db1f025dc858bfc (patch)
tree7eb34b2915025563660b56873363890fbb09f1fc
parentcfe483a6c6219f1327fe31220e7c854ebc11e837 (diff)
LFU-192-6 Uboot: Add command to provision encryption key
command actions: generate the MPPubK and generate PKEK as hash(MPPUBK). read the encrypted key from RAM and decrypt using PKEK. encapsulate the key in black blob and add 20 bytes TAG to black blob. Tested on: IMX8MM IMX8MN Signed-off-by: Gaurav Jain <gaurav.jain@nxp.com> Reviewed-by: Horia Geantă <horia.geanta@nxp.com> Reviewed-by: Ye Li <ye.li@nxp.com> (cherry picked from commit 2ad52ac95ffb991d7efb61084b690c02176ce499)
-rw-r--r--arch/arm/mach-imx/Kconfig11
-rw-r--r--arch/arm/mach-imx/Makefile1
-rw-r--r--arch/arm/mach-imx/cmd_prov_key.c166
-rw-r--r--drivers/crypto/fsl/Makefile1
-rw-r--r--include/fsl_sec.h9
5 files changed, 188 insertions, 0 deletions
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 5e6376851c2..f4fd8af3b50 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -76,6 +76,7 @@ config IMX_HAB
depends on ARCH_MX7 || ARCH_MX6 || ARCH_MX5 || ARCH_IMX8M || ARCH_MX7ULP
select FSL_CAAM if HAS_CAAM
imply CMD_DEKBLOB if HAS_CAAM
+ imply CMD_PROVISION_KEY if HAS_CAAM
help
This option enables the support for secure boot (HAB).
See doc/imx/habv4/* for more details.
@@ -257,3 +258,13 @@ config IMX_TRUSTY_OS
bool "Support Trusty OS related feature"
depends on ARCH_MX6 || ARCH_MX7 || ARCH_IMX8 || ARCH_IMX8M
select SYS_ARM_CACHE_WRITEALLOC
+
+config CMD_PROVISION_KEY
+ bool "Support to provision a encrypted key as black blob"
+ depends on IMX8MM || IMX8MN
+ select IMX_CAAM_MFG_PROT
+ help
+ reads manufacturing protection public key(MPPUBK).
+ derive PKEK = sha256(MPPUBK).
+ read encrypted key and decrypt it using PKEK.
+ generate black blob of decrypted key, add 20 bytes TAG to black blob.
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index 2bb58d334d6..526650e3de9 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -12,6 +12,7 @@ endif
ifeq ($(SOC),$(filter $(SOC),imx8m))
ifneq ($(CONFIG_SPL_BUILD),y)
obj-$(CONFIG_IMX_BOOTAUX) += imx_bootaux.o
+obj-$(CONFIG_CMD_PROVISION_KEY) += cmd_prov_key.o
endif
obj-y += mmc_env.o
obj-$(CONFIG_FEC_MXC) += mac.o
diff --git a/arch/arm/mach-imx/cmd_prov_key.c b/arch/arm/mach-imx/cmd_prov_key.c
new file mode 100644
index 00000000000..b09e275d237
--- /dev/null
+++ b/arch/arm/mach-imx/cmd_prov_key.c
@@ -0,0 +1,166 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * @file - cmd_prov_key.c
+ * @brief - NXP command support
+ * Command for provisioning encrypted key as black blob,
+ *
+ * Copyright 2021 NXP
+ *
+ */
+
+/*
+ *Concepts:
+ *
+ * - black key: secure encrypted key that can only be used by the CAAM HW
+ * module on the device generating this key.
+ * - black blob: black blob is an encapsulation of black data (key) that can
+ * only be decapsulated by the initiator device. The
+ * decapsulation will result in a new black data readable only
+ * by the CAAM HW.
+ *
+ *
+ *Generation of the key black blob:
+ *
+ * 1) Compile the bootloader with configuration:
+ * CONFIG_IMX_HAB
+ * CONFIG_FSL_CAAM
+ * CONFIG_IMX_CAAM_MFG_PROT
+ * CONFIG_CMD_PROVISION_KEY
+ * 2) Boot the bootloader on the board
+ * 3) Bootloader will generate the MPPubK
+ * 4) PKEK = hash(MPPUBK)
+ * 5) Read the encrypted key from RAM
+ * 6) Decrypt using PKEK
+ * 7) Encapsulate the decrypted key in black blob
+ * 8) Add the 20 bytes TAG to black blob
+ * 9) Copy the black blob in a binary file.
+ * The file must have a size of 112 bytes (0x70 bytes).
+ */
+
+#include <common.h>
+#include <cpu_func.h>
+#include <command.h>
+#include <malloc.h>
+#include <memalign.h>
+#include <asm/byteorder.h>
+#include <linux/compiler.h>
+#include <fsl_sec.h>
+#include <hash.h>
+#include <u-boot/sha256.h>
+#include <asm/arch/clock.h>
+
+/* Key modifier for CAAM blobs, used as a revision number */
+static const char caam_key_modifier[16] = {
+ 'C', 'A', 'A', 'M', '_', 'K', 'E', 'Y',
+ '_', 'T', 'Y', 'P', 'E', '_', 'V', '1',
+};
+
+/**
+ * do_export_key_blob() - Handle the "export_key_blob" command-line command
+ * @cmdtp: Command data struct pointer
+ * @flag: Command flag
+ * @argc: Command-line argument count
+ * @argv: Array of command-line arguments
+ *
+ * Returns zero on success, CMD_RET_USAGE in case of misuse and negative
+ * on error.
+ */
+static int do_export_key_blob(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ ulong src_addr, dst_addr;
+ uint8_t *src_ptr, *dst_ptr;
+ uint8_t *mppubk = NULL, *pkek = NULL, *black_key = NULL;
+ size_t key_len = AES256_KEY_SZ, pkek_len = SHA256_SUM_LEN;
+ size_t blob_len, blob_max_len;
+ int size, ret = 0;
+
+ ALLOC_CACHE_ALIGN_BUFFER(uint8_t, km_ptr, 16);
+
+ if (argc != 3)
+ return CMD_RET_USAGE;
+
+ /* generate mppubk */
+ mppubk = malloc_cache_aligned(FSL_CAAM_MP_PUBK_BYTES);
+ if (!mppubk) {
+ printf("Failed to allocate mem for mppubk\n");
+ return -ENOMEM;
+ }
+
+ ret = gen_mppubk(mppubk);
+ if (ret) {
+ printf("Failed to generate MPPubK\n");
+ goto free_m;
+ }
+
+ /* Derive PKEK = SHA256(MPPUBK) */
+ pkek = malloc_cache_aligned(pkek_len);
+ if (!pkek) {
+ printf("Failed to allocate memory for pkek\n");
+ ret = -ENOMEM;
+ goto free_m;
+ }
+
+ ret = hash_block("sha256", mppubk, FSL_CAAM_MP_PUBK_BYTES, pkek, (int *)&pkek_len);
+ if (ret)
+ goto free_pkek;
+
+ /* use pkek to decrypt src_addr which has enc key*/
+ src_addr = simple_strtoul(argv[1], NULL, 16);
+ src_ptr = (uint8_t *)(uintptr_t)src_addr;
+
+ black_key = malloc_cache_aligned(key_len);
+ if (!black_key) {
+ printf("Failed to allocate memory for black_key\n");
+ ret = -ENOMEM;
+ goto free_pkek;
+ }
+
+ ret = aesecb_decrypt(pkek, pkek_len, src_ptr, black_key, key_len);
+ if (ret)
+ goto free_blk_key;
+
+ /* create key black blob */
+ dst_addr = simple_strtoul(argv[2], NULL, 16);
+ dst_ptr = (uint8_t *)(uintptr_t)dst_addr;
+
+ /* copy key modifier, must be same as used in kernel */
+ memcpy(km_ptr, caam_key_modifier, 16);
+
+ ret = blob_encap((uint8_t *)km_ptr, black_key, dst_ptr, key_len, 1);
+ if (ret)
+ goto free_blk_key;
+
+ /* Tag the black blob so it can be passed to kernel */
+ blob_len = BLOB_SIZE(key_len) + CCM_OVERHEAD;
+ blob_max_len = MAX_BLOB_SIZE;
+ ret = tag_black_obj(dst_ptr, blob_len, key_len, blob_max_len);
+ if (ret)
+ printf("Failed to tag black blob: %d\n", ret);
+
+free_blk_key:
+ free(black_key);
+free_pkek:
+ memset(pkek, 0, pkek_len);
+ size = ALIGN(pkek_len, ARCH_DMA_MINALIGN);
+ flush_dcache_range((unsigned long)pkek, (unsigned long)pkek + size);
+ free(pkek);
+free_m:
+ memset(mppubk, 0, FSL_CAAM_MP_PUBK_BYTES);
+ size = ALIGN(FSL_CAAM_MP_PUBK_BYTES, ARCH_DMA_MINALIGN);
+ flush_dcache_range((unsigned long)mppubk, (unsigned long)mppubk + size);
+ free(mppubk);
+
+ return ret;
+}
+
+/***************************************************/
+
+U_BOOT_CMD(
+ export_key_blob, 3, 0, do_export_key_blob,
+ "Provision encrypted key as black blob.",
+ "src_addr dst_addr \n\n"
+ " - src_addr: source addr which has encrypted key(32 byte) to provision.\n"
+ " must be 64 byte aligned.\n"
+ " - dst_addr: destination addr which will have key black blob(112 byte).\n"
+ " must be 64 byte aligned.\n"
+);
diff --git a/drivers/crypto/fsl/Makefile b/drivers/crypto/fsl/Makefile
index 3d846748016..926300e2abc 100644
--- a/drivers/crypto/fsl/Makefile
+++ b/drivers/crypto/fsl/Makefile
@@ -9,3 +9,4 @@ obj-$(CONFIG_RSA_FREESCALE_EXP) += fsl_rsa.o
obj-$(CONFIG_FSL_CAAM_RNG) += rng.o
obj-$(CONFIG_IMX_CAAM_MFG_PROT) += fsl_mfgprot.o
obj-$(CONFIG_RNG_SELF_TEST) += rng_self_test.o
+obj-$(CONFIG_CMD_PROVISION_KEY) += fsl_aes.o tag_object.o
diff --git a/include/fsl_sec.h b/include/fsl_sec.h
index e0aed957794..f9e0d2e322e 100644
--- a/include/fsl_sec.h
+++ b/include/fsl_sec.h
@@ -28,7 +28,16 @@
#error Neither CONFIG_SYS_FSL_SEC_LE nor CONFIG_SYS_FSL_SEC_BE is defined
#endif
+#define BLOB_OVERHEAD (32 + 16)
#define BLOB_SIZE(x) ((x) + 32 + 16) /* Blob buffer size */
+#define AES256_KEY_SZ 32
+
+#define NONCE_SIZE 6
+#define ICV_SIZE 6
+#define CCM_OVERHEAD (NONCE_SIZE + ICV_SIZE)
+#define TAG_SIZE 20
+#define MAX_BLOB_SIZE (AES256_KEY_SZ + CCM_OVERHEAD +\
+ BLOB_OVERHEAD + TAG_SIZE)
/* Security Engine Block (MS = Most Sig., LS = Least Sig.) */
#if CONFIG_SYS_FSL_SEC_COMPAT >= 4