imx: ele_ahab: Add HUK derivation support

Add a new ahab_derive command that derives the hardware unique key (HUK)
into a 16 or 32 bytes key and stores it at the given address.

Signed-off-by: Mathieu Othacehe <othacehe@gnu.org>
Reviewed-by: Ye Li <ye.li@nxp.com>
This commit is contained in:
Mathieu Othacehe
2024-08-26 12:07:07 +02:00
committed by Fabio Estevam
parent e83ced1a24
commit ef53c77595
3 changed files with 110 additions and 0 deletions

View File

@@ -26,6 +26,7 @@
#define ELE_GET_EVENTS_REQ (0xA2) #define ELE_GET_EVENTS_REQ (0xA2)
#define ELE_COMMIT_REQ (0xA8) #define ELE_COMMIT_REQ (0xA8)
#define ELE_START_RNG (0xA3) #define ELE_START_RNG (0xA3)
#define ELE_CMD_DERIVE_KEY (0xA9)
#define ELE_GENERATE_DEK_BLOB (0xAF) #define ELE_GENERATE_DEK_BLOB (0xAF)
#define ELE_ENABLE_PATCH_REQ (0xC3) #define ELE_ENABLE_PATCH_REQ (0xC3)
#define ELE_RELEASE_RDC_REQ (0xC4) #define ELE_RELEASE_RDC_REQ (0xC4)
@@ -143,6 +144,7 @@ int ele_read_common_fuse(u16 fuse_id, u32 *fuse_words, u32 fuse_num, u32 *respon
int ele_release_caam(u32 core_did, u32 *response); int ele_release_caam(u32 core_did, u32 *response);
int ele_get_fw_version(u32 *fw_version, u32 *sha1, u32 *response); int ele_get_fw_version(u32 *fw_version, u32 *sha1, u32 *response);
int ele_get_events(u32 *events, u32 *events_cnt, u32 *response); int ele_get_events(u32 *events, u32 *events_cnt, u32 *response);
int ele_derive_huk(u8 *key, size_t key_size, u8 *ctx, size_t seed_size);
int ele_commit(u16 fuse_id, u32 *response, u32 *info_type); int ele_commit(u16 fuse_id, u32 *response, u32 *info_type);
int ele_generate_dek_blob(u32 key_id, u32 src_paddr, u32 dst_paddr, u32 max_output_size); int ele_generate_dek_blob(u32 key_id, u32 src_paddr, u32 dst_paddr, u32 max_output_size);
int ele_dump_buffer(u32 *buffer, u32 buffer_length); int ele_dump_buffer(u32 *buffer, u32 buffer_length);

View File

@@ -624,6 +624,31 @@ static int do_ahab_return_lifecycle(struct cmd_tbl *cmdtp, int flag, int argc, c
return CMD_RET_SUCCESS; return CMD_RET_SUCCESS;
} }
static int do_ahab_derive(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
{
ulong key;
size_t key_size;
char seed[] = "_ELE_AHAB_SEED_";
if (argc != 3)
return CMD_RET_USAGE;
key = hextoul(argv[1], NULL);
key_size = simple_strtoul(argv[2], NULL, 10);
if (key_size != 16 && key_size != 32) {
printf("key size can only be 16 or 32\n");
return CMD_RET_FAILURE;
}
if (ele_derive_huk((u8 *)key, key_size, seed, sizeof(seed))) {
printf("Error in AHAB derive\n");
return CMD_RET_FAILURE;
}
return CMD_RET_SUCCESS;
}
static int do_ahab_commit(struct cmd_tbl *cmdtp, int flag, int argc, static int do_ahab_commit(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[]) char *const argv[])
{ {
@@ -680,6 +705,12 @@ U_BOOT_CMD(ahab_return_lifecycle, CONFIG_SYS_MAXARGS, 1, do_ahab_return_lifecycl
"addr - Return lifecycle message block signed by OEM SRK\n" "addr - Return lifecycle message block signed by OEM SRK\n"
); );
U_BOOT_CMD(ahab_derive, CONFIG_SYS_MAXARGS, 3, do_ahab_derive,
"Derive the hardware unique key",
"addr [16|32]\n"
"Store at addr the derivation of the HUK on 16 or 32 bytes.\n"
);
U_BOOT_CMD(ahab_commit, CONFIG_SYS_MAXARGS, 1, do_ahab_commit, U_BOOT_CMD(ahab_commit, CONFIG_SYS_MAXARGS, 1, do_ahab_commit,
"commit into the fuses any new SRK revocation and FW version information\n" "commit into the fuses any new SRK revocation and FW version information\n"
"that have been found into the NXP (ELE FW) and OEM containers", "that have been found into the NXP (ELE FW) and OEM containers",

View File

@@ -1,11 +1,13 @@
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: GPL-2.0
/* /*
* Copyright 2020, 2023 NXP * Copyright 2020, 2023 NXP
* Copyright 2024 Mathieu Othacehe <othacehe@gnu.org>
* *
*/ */
#include <hang.h> #include <hang.h>
#include <malloc.h> #include <malloc.h>
#include <memalign.h>
#include <asm/io.h> #include <asm/io.h>
#include <dm.h> #include <dm.h>
#include <asm/mach-imx/ele_api.h> #include <asm/mach-imx/ele_api.h>
@@ -527,6 +529,81 @@ int ele_start_rng(void)
return ret; return ret;
} }
int ele_derive_huk(u8 *key, size_t key_size, u8 *seed, size_t seed_size)
{
struct udevice *dev = gd->arch.ele_dev;
struct ele_msg msg;
int msg_size = sizeof(struct ele_msg);
u8 *seed_aligned, *key_aligned;
int ret, size;
if (!dev) {
printf("ele dev is not initialized\n");
return -ENODEV;
}
if (key_size != 16 && key_size != 32) {
printf("key size can only be 16 or 32\n");
return -EINVAL;
}
if (seed_size >= (1U << 16) - 1) {
printf("seed size is too large\n");
return -EINVAL;
}
seed_aligned = memalign(ARCH_DMA_MINALIGN, seed_size);
if (!seed_aligned) {
printf("failed to alloc memory\n");
return -EINVAL;
}
memcpy(seed_aligned, seed, seed_size);
key_aligned = memalign(ARCH_DMA_MINALIGN, key_size);
if (!key_aligned) {
printf("failed to alloc memory\n");
ret = -EINVAL;
goto ret_seed;
}
size = ALIGN(seed_size, ARCH_DMA_MINALIGN);
flush_dcache_range((ulong)seed_aligned,
(ulong)seed_aligned + size);
size = ALIGN(key_size, ARCH_DMA_MINALIGN);
invalidate_dcache_range((ulong)key_aligned,
(ulong)key_aligned + size);
msg.version = ELE_VERSION;
msg.tag = ELE_CMD_TAG;
msg.size = 7;
msg.command = ELE_CMD_DERIVE_KEY;
msg.data[0] = upper_32_bits((ulong)key_aligned);
msg.data[1] = lower_32_bits((ulong)key_aligned);
msg.data[2] = upper_32_bits((ulong)seed_aligned);
msg.data[3] = lower_32_bits((ulong)seed_aligned);
msg.data[4] = seed_size << 16 | key_size;
msg.data[5] = compute_crc(&msg);
ret = misc_call(dev, false, &msg, msg_size, &msg, msg_size);
if (ret) {
printf("Error: %s: ret %d, response 0x%x\n",
__func__, ret, msg.data[0]);
goto ret_key;
}
invalidate_dcache_range((ulong)key_aligned,
(ulong)key_aligned + size);
memcpy(key, key_aligned, key_size);
ret_key:
free(key_aligned);
ret_seed:
free(seed_aligned);
return ret;
}
int ele_commit(u16 fuse_id, u32 *response, u32 *info_type) int ele_commit(u16 fuse_id, u32 *response, u32 *info_type)
{ {
struct udevice *dev = gd->arch.ele_dev; struct udevice *dev = gd->arch.ele_dev;