libubootenv: rework patchset with Digi-specific functionality
* Move Digi code out of the upstream files to minimize conflicts in version migrations. * Remove all the TEE client copied code and use the libteeclient library. * Some fixes in the Optee-based environment encryption * Some simplifications in CAAM-based environment encryption. https://onedigi.atlassian.net/browse/DUB-1079 Signed-off-by: Javier Viguera <javier.viguera@digi.com>
This commit is contained in:
parent
a288a03ef5
commit
720c5f7218
|
|
@ -52,10 +52,10 @@ index 3ed3244..e83b3a5 100644
|
|||
}
|
||||
#endif
|
||||
diff --git a/src/uboot_env.c b/src/uboot_env.c
|
||||
index 750b736..b7ad4c4 100644
|
||||
index ae85c7e..358dfbb 100644
|
||||
--- a/src/uboot_env.c
|
||||
+++ b/src/uboot_env.c
|
||||
@@ -2234,3 +2234,99 @@ void libuboot_exit(struct uboot_ctx *ctx)
|
||||
@@ -2103,3 +2103,99 @@ void libuboot_exit(struct uboot_ctx *ctx)
|
||||
|
||||
free(ctx);
|
||||
}
|
||||
|
|
@ -27,10 +27,10 @@ Signed-off-by: Gabriel Valcazar <gabriel.valcazar@digi.com>
|
|||
2 files changed, 90 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/uboot_env.c b/src/uboot_env.c
|
||||
index b7ad4c4..924a6cf 100644
|
||||
index 358dfbb..c1f334e 100644
|
||||
--- a/src/uboot_env.c
|
||||
+++ b/src/uboot_env.c
|
||||
@@ -591,6 +591,73 @@ static int check_env_device(struct uboot_flash_env *dev)
|
||||
@@ -581,6 +581,73 @@ static int check_env_device(struct uboot_flash_env *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -104,7 +104,7 @@ index b7ad4c4..924a6cf 100644
|
|||
static bool check_compatible_devices(struct uboot_ctx *ctx)
|
||||
{
|
||||
if (!ctx->redundant)
|
||||
@@ -602,6 +669,12 @@ static bool check_compatible_devices(struct uboot_ctx *ctx)
|
||||
@@ -592,6 +659,12 @@ static bool check_compatible_devices(struct uboot_ctx *ctx)
|
||||
return false;
|
||||
if (ctx->envdevs[0].envsize != ctx->envdevs[1].envsize)
|
||||
return false;
|
||||
|
|
@ -117,7 +117,7 @@ index b7ad4c4..924a6cf 100644
|
|||
|
||||
return true;
|
||||
}
|
||||
@@ -648,7 +721,7 @@ static int fileread(struct uboot_flash_env *dev, void *data)
|
||||
@@ -638,7 +711,7 @@ static int fileread(struct uboot_flash_env *dev, void *data)
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -126,7 +126,7 @@ index b7ad4c4..924a6cf 100644
|
|||
{
|
||||
size_t count;
|
||||
size_t blocksize;
|
||||
@@ -667,6 +740,17 @@ static int mtdread(struct uboot_flash_env *dev, void *data)
|
||||
@@ -657,6 +730,17 @@ static int mtdread(struct uboot_flash_env *dev, void *data)
|
||||
ret = read(dev->fd, data, dev->envsize);
|
||||
break;
|
||||
case MTD_NANDFLASH:
|
||||
|
|
@ -144,7 +144,7 @@ index b7ad4c4..924a6cf 100644
|
|||
if (dev->offset)
|
||||
if (lseek(dev->fd, dev->offset, SEEK_SET) < 0) {
|
||||
ret = -EIO;
|
||||
@@ -742,7 +826,7 @@ static int devread(struct uboot_ctx *ctx, unsigned int copy, void *data)
|
||||
@@ -732,7 +816,7 @@ static int devread(struct uboot_ctx *ctx, unsigned int copy, void *data)
|
||||
ret = fileread(dev, data);
|
||||
break;
|
||||
case DEVICE_MTD:
|
||||
|
|
@ -154,13 +154,13 @@ index b7ad4c4..924a6cf 100644
|
|||
case DEVICE_UBI:
|
||||
ret = ubiread(dev, data);
|
||||
diff --git a/src/uboot_private.h b/src/uboot_private.h
|
||||
index ee2d305..84bd1bc 100644
|
||||
index 40e5446..c8fecc4 100644
|
||||
--- a/src/uboot_private.h
|
||||
+++ b/src/uboot_private.h
|
||||
@@ -116,10 +116,14 @@ struct uboot_ctx {
|
||||
@@ -114,10 +114,14 @@ LIST_HEAD(vars, var_entry);
|
||||
struct uboot_ctx {
|
||||
/** true if the environment is redundant */
|
||||
bool redundant;
|
||||
/** true if the environment is encrypted */
|
||||
bool encrypted;
|
||||
+ /** true if the environment is dynamic */
|
||||
+ bool dynamic_env;
|
||||
/** set to valid after a successful load */
|
||||
|
|
@ -169,6 +169,6 @@ index ee2d305..84bd1bc 100644
|
|||
size_t size;
|
||||
+ /** top limit of the dynamic environment */
|
||||
+ loff_t top_limit;
|
||||
/** usable environment size */
|
||||
unsigned int usable_size;
|
||||
/** devices where environment is stored */
|
||||
struct uboot_flash_env envdevs[2];
|
||||
/** Set which device contains the current(last valid) environment */
|
||||
|
|
@ -15,26 +15,63 @@ Signed-off-by: Diaz de Grenu, Jose <Jose.DiazdeGrenu@digi.com>
|
|||
Signed-off-by: Gonzalo Ruiz <Gonzalo.Ruiz@digi.com>
|
||||
Signed-off-by: Hector Palacios <hector.palacios@digi.com>
|
||||
Signed-off-by: Gabriel Valcazar <gabriel.valcazar@digi.com>
|
||||
|
||||
# This is the commit message #2:
|
||||
|
||||
fall back to read HWID from nvmem device if not available on DT
|
||||
|
||||
Old U-Boot versions don't populate the HWID on the device tree. This may
|
||||
be used as a key modifier for TrustFence encryption and, if not available
|
||||
on the DT, newer firmware may be unable to unencrypt the U-Boot
|
||||
environment.
|
||||
|
||||
This patch implements a fall-back function to query the HWID directly from
|
||||
the nvmem device node if it cannot locate it at the DT.
|
||||
This is only implemented for ccimx6 family, which may be in the case of
|
||||
having an old U-Boot.
|
||||
|
||||
https://onedigi.atlassian.net/browse/DEL-8444
|
||||
|
||||
Signed-off-by: Hector Palacios <hector.palacios@digi.com>
|
||||
|
||||
# This is the commit message #3:
|
||||
|
||||
ubootenv: generalize env encryption code
|
||||
|
||||
Generalize the code to make room for Optee-based encryption.
|
||||
* Move the code to the crypt.c/h files to minimize changes on the upstream
|
||||
uboot_env.c file.
|
||||
* Rename env_caam_get_keymod to env_get_keymod as this function is not
|
||||
CAAM-specific.
|
||||
* Create a public env_crypt function that will select the proper (CAAM,
|
||||
Optee) implementation.
|
||||
|
||||
Signed-off-by: Javier Viguera <javier.viguera@digi.com>
|
||||
---
|
||||
src/CMakeLists.txt | 2 +
|
||||
src/caam_keyblob.h | 42 +++++++
|
||||
src/md5.c | 275 ++++++++++++++++++++++++++++++++++++++++++++
|
||||
src/md5.h | 24 ++++
|
||||
src/uboot_env.c | 131 +++++++++++++++++++++
|
||||
src/uboot_private.h | 4 +
|
||||
6 files changed, 478 insertions(+)
|
||||
src/CMakeLists.txt | 4 +
|
||||
src/caam_keyblob.h | 42 +++++++
|
||||
src/crypt.c | 179 +++++++++++++++++++++++++++++
|
||||
src/crypt.h | 10 ++
|
||||
src/md5.c | 275 +++++++++++++++++++++++++++++++++++++++++++++
|
||||
src/md5.h | 24 ++++
|
||||
src/uboot_env.c | 18 +++
|
||||
7 files changed, 552 insertions(+)
|
||||
create mode 100644 src/caam_keyblob.h
|
||||
create mode 100644 src/crypt.c
|
||||
create mode 100644 src/crypt.h
|
||||
create mode 100644 src/md5.c
|
||||
create mode 100644 src/md5.h
|
||||
|
||||
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
|
||||
index ababe0f..fb1efa2 100644
|
||||
index ababe0f..638f1c1 100644
|
||||
--- a/src/CMakeLists.txt
|
||||
+++ b/src/CMakeLists.txt
|
||||
@@ -4,6 +4,8 @@
|
||||
@@ -4,6 +4,10 @@
|
||||
cmake_minimum_required (VERSION 2.6)
|
||||
# Sources and private headers
|
||||
SET(libubootenv_SOURCES
|
||||
+ crypt.c
|
||||
+ crypt.h
|
||||
+ md5.c
|
||||
+ md5.h
|
||||
uboot_env.c
|
||||
|
|
@ -88,6 +125,207 @@ index 0000000..e313e87
|
|||
+#endif
|
||||
+
|
||||
+#endif /* CAAM_KEYBLOB_H */
|
||||
diff --git a/src/crypt.c b/src/crypt.c
|
||||
new file mode 100644
|
||||
index 0000000..213cffd
|
||||
--- /dev/null
|
||||
+++ b/src/crypt.c
|
||||
@@ -0,0 +1,179 @@
|
||||
+/*
|
||||
+ * Copyright 2024 Digi International Inc
|
||||
+ *
|
||||
+ * SPDX-License-Identifier: GPL-2.0+
|
||||
+ */
|
||||
+
|
||||
+#include <arpa/inet.h>
|
||||
+#include <fcntl.h>
|
||||
+#include <stdbool.h>
|
||||
+#include <stdio.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <string.h>
|
||||
+#include <sys/ioctl.h>
|
||||
+#include <sys/stat.h>
|
||||
+#include <unistd.h>
|
||||
+
|
||||
+#include "caam_keyblob.h"
|
||||
+#include "md5.h"
|
||||
+
|
||||
+/*
|
||||
+ * The BLOB includes a random AES-256 key (32 bytes) and a
|
||||
+ * Message Authentication Code (MAC) (16 bytes)
|
||||
+ */
|
||||
+#define BLOB_OVERHEAD 48
|
||||
+#define CAAM_KEY_DEV "/dev/caam_kb"
|
||||
+#define MAX_HWID_WORDS 4
|
||||
+
|
||||
+/* Function that checks if machine is compatible (on the DT) */
|
||||
+static bool machine_is_compatible(char *machine)
|
||||
+{
|
||||
+ int fd, nchars, len = 0;
|
||||
+ int ret = false;
|
||||
+ char str[256];
|
||||
+ char *p = str;
|
||||
+
|
||||
+ fd = open("/proc/device-tree/compatible", O_RDONLY);
|
||||
+ if (fd < 0)
|
||||
+ return false;
|
||||
+
|
||||
+ nchars = read(fd, str, 255);
|
||||
+ while (len < nchars) {
|
||||
+ if (!strcmp(p, machine)) {
|
||||
+ ret = true;
|
||||
+ break;
|
||||
+ }
|
||||
+ len += strlen(p) + 1;
|
||||
+ p += strlen(p) + 1;
|
||||
+ }
|
||||
+ close(fd);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int env_get_keymod(unsigned char output[16])
|
||||
+{
|
||||
+ int i;
|
||||
+ int len;
|
||||
+ int fd;
|
||||
+ uint32_t ocotp_hwid[MAX_HWID_WORDS];
|
||||
+ char dt_prop[32];
|
||||
+ char buf[sizeof(uint32_t)];
|
||||
+
|
||||
+ for (i = 0; i < MAX_HWID_WORDS; i++) {
|
||||
+ sprintf(dt_prop, "/proc/device-tree/digi,hwid_%d", i);
|
||||
+ if (access(dt_prop, F_OK) != -1) {
|
||||
+ fd = open(dt_prop, O_RDONLY);
|
||||
+ if (fd < 0)
|
||||
+ return fd;
|
||||
+ len = read(fd, buf, sizeof(uint32_t));
|
||||
+ if (len < 0) {
|
||||
+ close(fd);
|
||||
+ return -1;
|
||||
+ }
|
||||
+ ocotp_hwid[i] = ntohl(*(uint32_t *) buf);
|
||||
+ close(fd);
|
||||
+ } else if (machine_is_compatible("digi,ccimx6ul") ||
|
||||
+ machine_is_compatible("digi,ccimx6")) {
|
||||
+ /*
|
||||
+ * If HWID not available on the DT (old U-Boot version),
|
||||
+ * fall back to read it directly from the nvmem device.
|
||||
+ */
|
||||
+ int hwid_offset = 136; /* (Bank * 8 + Word) * 4 */
|
||||
+
|
||||
+ /* HWID for CC6 family only has two words */
|
||||
+ if (i == 2)
|
||||
+ break;
|
||||
+
|
||||
+ fd = open("/sys/bus/nvmem/devices/imx-ocotp0/nvmem",
|
||||
+ O_RDONLY);
|
||||
+ if (fd < 0)
|
||||
+ return fd;
|
||||
+ len = lseek(fd, hwid_offset + i * 4, SEEK_SET);
|
||||
+
|
||||
+ len = read(fd, buf, sizeof(unsigned int));
|
||||
+ if (len < 0) {
|
||||
+ close(fd);
|
||||
+ return -1;
|
||||
+ }
|
||||
+ ocotp_hwid[i] = *(unsigned int *)buf;
|
||||
+ close(fd);
|
||||
+ } else {
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* Calculate md5sum on the raw HWID array */
|
||||
+ md5((unsigned char *)(&ocotp_hwid), sizeof(uint32_t) * i, output);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int env_caam_crypt(char *data, unsigned int size, const int enc)
|
||||
+{
|
||||
+ struct caam_kb_data enc_data;
|
||||
+ int fd;
|
||||
+ int ret = 0;
|
||||
+ const int len = size;
|
||||
+ int ioctl_mode;
|
||||
+ char *buffer;
|
||||
+ unsigned char key_modifier[16];
|
||||
+
|
||||
+ ret = env_get_keymod(key_modifier);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ enc_data.keymod = (char *)key_modifier;
|
||||
+ enc_data.keymod_len = sizeof(key_modifier);
|
||||
+
|
||||
+ enc_data.keyblob_len = len;
|
||||
+ enc_data.rawkey_len = len - BLOB_OVERHEAD;
|
||||
+
|
||||
+ buffer = malloc(len);
|
||||
+ if (!buffer) {
|
||||
+ printf("Could not allocate memory\n");
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ if (enc) {
|
||||
+ enc_data.rawkey = data;
|
||||
+ ioctl_mode = CAAM_KB_ENCRYPT;
|
||||
+ enc_data.keyblob = buffer;
|
||||
+ } else {
|
||||
+ enc_data.keyblob = data;
|
||||
+ ioctl_mode = CAAM_KB_DECRYPT;
|
||||
+ enc_data.rawkey = buffer;
|
||||
+ }
|
||||
+
|
||||
+ if ((fd = open(CAAM_KEY_DEV, O_RDWR)) < 0) {
|
||||
+ ret = fd;
|
||||
+ goto free;
|
||||
+ }
|
||||
+
|
||||
+ ret = ioctl(fd, ioctl_mode, &enc_data);
|
||||
+ if (ret) {
|
||||
+ printf("CAAM_KEY_DEV ioctl failed: %d\n", ret);
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ memcpy(data, buffer, enc ? len : len - BLOB_OVERHEAD);
|
||||
+
|
||||
+out:
|
||||
+ close(fd);
|
||||
+free:
|
||||
+ free(buffer);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+int env_crypt(char *data, unsigned int size, const int enc)
|
||||
+{
|
||||
+ return env_caam_crypt(data, size, enc);
|
||||
+}
|
||||
+
|
||||
+int is_env_encrypted(void)
|
||||
+{
|
||||
+ const char *dt_prop = "/proc/device-tree/digi,uboot-env,encrypted";
|
||||
+
|
||||
+ return access(dt_prop, F_OK) != -1;
|
||||
+}
|
||||
diff --git a/src/crypt.h b/src/crypt.h
|
||||
new file mode 100644
|
||||
index 0000000..8d85c7f
|
||||
--- /dev/null
|
||||
+++ b/src/crypt.h
|
||||
@@ -0,0 +1,10 @@
|
||||
+/*
|
||||
+ * Copyright 2024 Digi International Inc
|
||||
+ *
|
||||
+ * SPDX-License-Identifier: GPL-2.0+
|
||||
+ */
|
||||
+
|
||||
+#pragma once
|
||||
+
|
||||
+int env_crypt(char *data, unsigned int size, const int enc);
|
||||
+int is_env_encrypted(void);
|
||||
diff --git a/src/md5.c b/src/md5.c
|
||||
new file mode 100644
|
||||
index 0000000..47ae8bf
|
||||
|
|
@ -400,146 +638,26 @@ index 0000000..02a9a9d
|
|||
+
|
||||
+#endif /* _MD5_H */
|
||||
diff --git a/src/uboot_env.c b/src/uboot_env.c
|
||||
index ae85c7e..750b736 100644
|
||||
index c1f334e..30ef835 100644
|
||||
--- a/src/uboot_env.c
|
||||
+++ b/src/uboot_env.c
|
||||
@@ -34,11 +34,21 @@
|
||||
#include <sys/ioctl.h>
|
||||
#include <zlib.h>
|
||||
#include <yaml.h>
|
||||
+#include <arpa/inet.h>
|
||||
@@ -37,6 +37,7 @@
|
||||
#include <mtd/mtd-user.h>
|
||||
#include <mtd/ubi-user.h>
|
||||
|
||||
+#include "caam_keyblob.h"
|
||||
+#include "md5.h"
|
||||
+#include "crypt.h"
|
||||
#include "uboot_private.h"
|
||||
|
||||
+/*
|
||||
+ * The BLOB includes a random AES-256 key (32 bytes) and a
|
||||
+ * Message Authentication Code (MAC) (16 bytes)
|
||||
+ */
|
||||
+#define BLOB_OVERHEAD 48
|
||||
+#define CAAM_KEY_DEV "/dev/caam_kb"
|
||||
+
|
||||
#define UBI_MAX_VOLUME 128
|
||||
|
||||
#define DEVICE_MTD_NAME "/dev/mtd"
|
||||
@@ -1028,6 +1038,105 @@ const struct uboot_version_info *libuboot_version_info(void)
|
||||
return &libinfo;
|
||||
}
|
||||
|
||||
+static int is_env_encrypted(void)
|
||||
+{
|
||||
+ const char *dt_prop = "/proc/device-tree/digi,uboot-env,encrypted";
|
||||
+
|
||||
+ return access(dt_prop, F_OK) != -1;
|
||||
+}
|
||||
+
|
||||
+#define MAX_HWID_WORDS 4
|
||||
+static int env_caam_get_keymod(unsigned char output[16])
|
||||
+{
|
||||
+ int i;
|
||||
+ int len;
|
||||
+ int fd;
|
||||
+ uint32_t ocotp_hwid[MAX_HWID_WORDS];
|
||||
+ char dt_prop[32];
|
||||
+
|
||||
+ for (i = 0; i < MAX_HWID_WORDS; i++) {
|
||||
+ sprintf(dt_prop, "/proc/device-tree/digi,hwid_%d", i);
|
||||
+ if (access(dt_prop, F_OK) != -1) {
|
||||
+ char buf[sizeof(uint32_t)];
|
||||
+
|
||||
+ fd = open(dt_prop, O_RDONLY);
|
||||
+ if (fd < 0)
|
||||
+ return fd;
|
||||
+ len = read(fd, buf, sizeof(uint32_t));
|
||||
+ if (len < 0) {
|
||||
+ close(fd);
|
||||
+ return -1;
|
||||
+ }
|
||||
+ ocotp_hwid[i] = ntohl(*(uint32_t *)buf);
|
||||
+ close(fd);
|
||||
+ } else {
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* Calculate md5sum on the raw HWID array */
|
||||
+ md5((unsigned char *)(&ocotp_hwid), sizeof(uint32_t) * i, output);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int env_caam_crypt(char *data, unsigned int size, const int enc)
|
||||
+{
|
||||
+ struct caam_kb_data enc_data;
|
||||
+ int fd;
|
||||
+ int ret = 0;
|
||||
+ const int len = size;
|
||||
+ int ioctl_mode;
|
||||
+ char *buffer;
|
||||
+ unsigned char key_modifier[16];
|
||||
+
|
||||
+ ret = env_caam_get_keymod(key_modifier);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ enc_data.keymod = (char *)key_modifier;
|
||||
+ enc_data.keymod_len = sizeof(key_modifier);
|
||||
+
|
||||
+ enc_data.keyblob_len = len;
|
||||
+ enc_data.rawkey_len = len - BLOB_OVERHEAD;
|
||||
+
|
||||
+ buffer = malloc(len);
|
||||
+ if (!buffer) {
|
||||
+ printf("Could not allocate memory\n");
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ if (enc) {
|
||||
+ enc_data.rawkey = data;
|
||||
+ ioctl_mode = CAAM_KB_ENCRYPT;
|
||||
+ enc_data.keyblob = buffer;
|
||||
+ } else {
|
||||
+ enc_data.keyblob = data;
|
||||
+ ioctl_mode = CAAM_KB_DECRYPT;
|
||||
+ enc_data.rawkey = buffer;
|
||||
+ }
|
||||
+
|
||||
+ if ((fd = open(CAAM_KEY_DEV, O_RDWR)) < 0) {
|
||||
+ ret = fd;
|
||||
+ goto free;
|
||||
+ }
|
||||
+
|
||||
+ ret = ioctl(fd, ioctl_mode, &enc_data);
|
||||
+ if (ret) {
|
||||
+ printf("CAAM_KEY_DEV ioctl failed: %d\n", ret);
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ memcpy(data, buffer, enc ? len : len - BLOB_OVERHEAD);
|
||||
+
|
||||
+out:
|
||||
+ close(fd);
|
||||
+free:
|
||||
+ free(buffer);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
int libuboot_env_store(struct uboot_ctx *ctx)
|
||||
{
|
||||
struct var_entry *entry;
|
||||
@@ -1103,6 +1212,15 @@ int libuboot_env_store(struct uboot_ctx *ctx)
|
||||
@@ -1187,6 +1188,15 @@ int libuboot_env_store(struct uboot_ctx *ctx)
|
||||
((struct uboot_env_redund *)image)->flags = flags;
|
||||
}
|
||||
|
||||
+ if (ctx->encrypted) {
|
||||
+ ret = env_caam_crypt(data, ctx->usable_size, 1);
|
||||
+ if (is_env_encrypted()) {
|
||||
+ size_t usable_envsize = ctx->size - offsetdata;
|
||||
+ ret = env_crypt(data, usable_envsize, 1);
|
||||
+ if (ret) {
|
||||
+ fprintf(stderr,
|
||||
+ "Error: can't encrypt env for flash\n");
|
||||
+ fprintf(stderr, "Error: can't encrypt env for flash\n");
|
||||
+ return ret;
|
||||
+ }
|
||||
+ }
|
||||
|
|
@ -547,56 +665,18 @@ index ae85c7e..750b736 100644
|
|||
*(uint32_t *)image = crc32(0, (uint8_t *)data, ctx->size - offsetdata);
|
||||
|
||||
copy = ctx->redundant ? (ctx->current ? 0 : 1) : 0;
|
||||
@@ -1167,6 +1285,13 @@ static int libuboot_load(struct uboot_ctx *ctx)
|
||||
@@ -1251,6 +1261,14 @@ static int libuboot_load(struct uboot_ctx *ctx)
|
||||
}
|
||||
crc = *(uint32_t *)(buf[i] + offsetcrc);
|
||||
dev->crc = crc32(0, (uint8_t *)data, usable_envsize);
|
||||
+ if (ctx->encrypted) {
|
||||
+ ret = env_caam_crypt((char *)data, ctx->usable_size, 0);
|
||||
+ if (is_env_encrypted()) {
|
||||
+ ret = env_crypt(data, usable_envsize, 0);
|
||||
+ if (ret) {
|
||||
+ fprintf(stderr, "Error: can't decrypt environment\n");
|
||||
+ fprintf(stderr,
|
||||
+ "Error: can't decrypt environment\n");
|
||||
+ return ret;
|
||||
+ }
|
||||
+ }
|
||||
crcenv[i] = dev->crc == crc;
|
||||
if (ctx->redundant)
|
||||
dev->flags = *(uint8_t *)(buf[i] + offsetflags);
|
||||
@@ -1773,6 +1898,11 @@ int libuboot_read_config_ext(struct uboot_ctx **ctxlist, const char *config)
|
||||
break;
|
||||
}
|
||||
}
|
||||
+
|
||||
+ ctx->usable_size = ctx->size - sizeof(uint32_t);
|
||||
+ if (ctx->redundant)
|
||||
+ ctx->usable_size -= sizeof(char);
|
||||
+
|
||||
if (ndev == 0)
|
||||
retval = -EINVAL;
|
||||
|
||||
@@ -2042,6 +2172,7 @@ int libuboot_initialize(struct uboot_ctx **out,
|
||||
return -ENOMEM;
|
||||
|
||||
ctx->valid = false;
|
||||
+ ctx->encrypted = is_env_encrypted();
|
||||
ret = libuboot_configure(ctx, envdevs);
|
||||
|
||||
if (ret < 0) {
|
||||
diff --git a/src/uboot_private.h b/src/uboot_private.h
|
||||
index 40e5446..ee2d305 100644
|
||||
--- a/src/uboot_private.h
|
||||
+++ b/src/uboot_private.h
|
||||
@@ -114,10 +114,14 @@ LIST_HEAD(vars, var_entry);
|
||||
struct uboot_ctx {
|
||||
/** true if the environment is redundant */
|
||||
bool redundant;
|
||||
+ /** true if the environment is encrypted */
|
||||
+ bool encrypted;
|
||||
/** set to valid after a successful load */
|
||||
bool valid;
|
||||
/** size of the environment */
|
||||
size_t size;
|
||||
+ /** usable environment size */
|
||||
+ unsigned int usable_size;
|
||||
/** devices where environment is stored */
|
||||
struct uboot_flash_env envdevs[2];
|
||||
/** Set which device contains the current(last valid) environment */
|
||||
|
|
@ -0,0 +1,259 @@
|
|||
From: Mike Engel <Mike.Engel@digi.com>
|
||||
Date: Fri, 26 May 2023 11:21:43 +0200
|
||||
Subject: [PATCH] Implement support for environment encryption using Optee
|
||||
|
||||
Co-authored-by: Javier Viguera <javier.viguera@digi.com>
|
||||
Signed-off-by: Mike Engel <Mike.Engel@digi.com>
|
||||
Signed-off-by: Javier Viguera <javier.viguera@digi.com>
|
||||
---
|
||||
src/CMakeLists.txt | 3 +
|
||||
src/crypt.c | 10 ++-
|
||||
src/crypt_optee.c | 172 +++++++++++++++++++++++++++++++++++++++++++++
|
||||
src/crypt_optee.h | 10 +++
|
||||
4 files changed, 194 insertions(+), 1 deletion(-)
|
||||
create mode 100644 src/crypt_optee.c
|
||||
create mode 100644 src/crypt_optee.h
|
||||
|
||||
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
|
||||
index 638f1c1..f218b35 100644
|
||||
--- a/src/CMakeLists.txt
|
||||
+++ b/src/CMakeLists.txt
|
||||
@@ -6,6 +6,8 @@ cmake_minimum_required (VERSION 2.6)
|
||||
SET(libubootenv_SOURCES
|
||||
crypt.c
|
||||
crypt.h
|
||||
+ crypt_optee.c
|
||||
+ crypt_optee.h
|
||||
md5.c
|
||||
md5.h
|
||||
uboot_env.c
|
||||
@@ -26,6 +28,7 @@ ADD_LIBRARY(ubootenv_static STATIC ${libubootenv_SOURCES} ${include_HEADERS})
|
||||
SET_TARGET_PROPERTIES(ubootenv_static PROPERTIES OUTPUT_NAME ubootenv)
|
||||
add_executable(fw_printenv fw_printenv.c)
|
||||
target_link_libraries(ubootenv z yaml)
|
||||
+target_link_libraries(ubootenv teec)
|
||||
target_link_libraries(fw_printenv ubootenv)
|
||||
add_custom_target(fw_setenv ALL ${CMAKE_COMMAND} -E create_symlink fw_printenv fw_setenv)
|
||||
|
||||
diff --git a/src/crypt.c b/src/crypt.c
|
||||
index 213cffd..e3f9a5d 100644
|
||||
--- a/src/crypt.c
|
||||
+++ b/src/crypt.c
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <unistd.h>
|
||||
|
||||
#include "caam_keyblob.h"
|
||||
+#include "crypt_optee.h"
|
||||
#include "md5.h"
|
||||
|
||||
/*
|
||||
@@ -168,7 +169,14 @@ free:
|
||||
|
||||
int env_crypt(char *data, unsigned int size, const int enc)
|
||||
{
|
||||
- return env_caam_crypt(data, size, enc);
|
||||
+ if (is_env_optee_encrypted()) {
|
||||
+ unsigned char key_modifier[16];
|
||||
+ if (env_get_keymod(key_modifier))
|
||||
+ return -1;
|
||||
+ return env_optee_crypt((char *)key_modifier, data, size, enc);
|
||||
+ } else {
|
||||
+ return env_caam_crypt(data, size, enc);
|
||||
+ }
|
||||
}
|
||||
|
||||
int is_env_encrypted(void)
|
||||
diff --git a/src/crypt_optee.c b/src/crypt_optee.c
|
||||
new file mode 100644
|
||||
index 0000000..fc74141
|
||||
--- /dev/null
|
||||
+++ b/src/crypt_optee.c
|
||||
@@ -0,0 +1,172 @@
|
||||
+/*
|
||||
+ * Copyright 2024 Digi International Inc
|
||||
+ *
|
||||
+ * SPDX-License-Identifier: GPL-2.0+
|
||||
+ */
|
||||
+
|
||||
+#include <arpa/inet.h>
|
||||
+#include <errno.h>
|
||||
+#include <stdio.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <string.h>
|
||||
+#include <tee_client_api.h>
|
||||
+#include <unistd.h>
|
||||
+
|
||||
+#define AES_BLOCK_LENGTH 16
|
||||
+
|
||||
+/* From TA's public header (aes_ta.h) */
|
||||
+#define TA_AES_UUID \
|
||||
+ { 0xc2fad363, 0x5d9f, 0x4fc4, \
|
||||
+ { 0xa4, 0x17, 0x55, 0x58, 0x41, 0xe0, 0x57, 0x45 } }
|
||||
+#define TA_AES_ALGO_ECB 0
|
||||
+#define TA_AES_ALGO_CBC 1
|
||||
+#define TA_AES_ALGO_CTR 2
|
||||
+#define TA_AES_SIZE_128BIT (128 / 8)
|
||||
+#define TA_AES_SIZE_256BIT (256 / 8)
|
||||
+#define TA_AES_MODE_DECODE 0
|
||||
+#define TA_AES_MODE_ENCODE 1
|
||||
+#define TA_AES_CMD_PREPARE 0
|
||||
+#define TA_AES_CMD_SET_KEY 1
|
||||
+#define TA_AES_CMD_SET_IV 2
|
||||
+#define TA_AES_CMD_CIPHER 3
|
||||
+
|
||||
+struct tee_ctx {
|
||||
+ TEEC_Context ctx;
|
||||
+ TEEC_Session sess;
|
||||
+};
|
||||
+
|
||||
+static void prepare_tee_session(struct tee_ctx *ctx)
|
||||
+{
|
||||
+ TEEC_Result ret;
|
||||
+ uint32_t origin;
|
||||
+ TEEC_UUID uuid = TA_AES_UUID;
|
||||
+
|
||||
+ ret = TEEC_InitializeContext(NULL, &ctx->ctx);
|
||||
+ if (ret != TEEC_SUCCESS)
|
||||
+ printf("TEEC_InitializeContext failed with code 0x%x", ret);
|
||||
+
|
||||
+ /* Open a session with the TA */
|
||||
+ ret = TEEC_OpenSession(&ctx->ctx, &ctx->sess, &uuid,
|
||||
+ TEEC_LOGIN_PUBLIC, NULL, NULL, &origin);
|
||||
+ if (ret != TEEC_SUCCESS)
|
||||
+ printf("TEEC_Opensession failed with code 0x%x origin 0x%x",
|
||||
+ ret, origin);
|
||||
+
|
||||
+}
|
||||
+
|
||||
+static void terminate_tee_session(struct tee_ctx *ctx)
|
||||
+{
|
||||
+ TEEC_CloseSession(&ctx->sess);
|
||||
+ TEEC_FinalizeContext(&ctx->ctx);
|
||||
+}
|
||||
+
|
||||
+static void prepare_aes(struct tee_ctx *ctx, int encode)
|
||||
+{
|
||||
+ TEEC_Operation op;
|
||||
+ uint32_t origin;
|
||||
+ TEEC_Result res;
|
||||
+
|
||||
+ memset(&op, 0, sizeof(op));
|
||||
+ op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT,
|
||||
+ TEEC_VALUE_INPUT,
|
||||
+ TEEC_VALUE_INPUT, TEEC_NONE);
|
||||
+
|
||||
+ op.params[0].value.a = TA_AES_ALGO_CTR;
|
||||
+ op.params[1].value.a = TA_AES_SIZE_256BIT;
|
||||
+ op.params[2].value.a = encode ? TA_AES_MODE_ENCODE : TA_AES_MODE_DECODE;
|
||||
+
|
||||
+ res = TEEC_InvokeCommand(&ctx->sess, TA_AES_CMD_PREPARE, &op, &origin);
|
||||
+ if (res != TEEC_SUCCESS)
|
||||
+ printf("TEEC_InvokeCommand(PREPARE) failed 0x%x origin 0x%x",
|
||||
+ res, origin);
|
||||
+}
|
||||
+
|
||||
+static void set_key(struct tee_ctx *ctx, size_t key_sz)
|
||||
+{
|
||||
+ TEEC_Operation op;
|
||||
+ uint32_t origin;
|
||||
+ TEEC_Result res;
|
||||
+
|
||||
+ memset(&op, 0, sizeof(op));
|
||||
+
|
||||
+ op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT,
|
||||
+ TEEC_NONE, TEEC_NONE, TEEC_NONE);
|
||||
+
|
||||
+ op.params[0].value.a = key_sz;
|
||||
+
|
||||
+ res = TEEC_InvokeCommand(&ctx->sess, TA_AES_CMD_SET_KEY, &op, &origin);
|
||||
+ if (res != TEEC_SUCCESS)
|
||||
+ printf("TEEC_InvokeCommand(SET_KEY) failed 0x%x origin 0x%x",
|
||||
+ res, origin);
|
||||
+}
|
||||
+
|
||||
+static void set_iv(struct tee_ctx *ctx, char *iv, size_t iv_sz)
|
||||
+{
|
||||
+ TEEC_Operation op;
|
||||
+ uint32_t origin;
|
||||
+ TEEC_Result res;
|
||||
+
|
||||
+ memset(&op, 0, sizeof(op));
|
||||
+ op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT,
|
||||
+ TEEC_NONE, TEEC_NONE, TEEC_NONE);
|
||||
+ op.params[0].tmpref.buffer = iv;
|
||||
+ op.params[0].tmpref.size = iv_sz;
|
||||
+
|
||||
+ res = TEEC_InvokeCommand(&ctx->sess, TA_AES_CMD_SET_IV, &op, &origin);
|
||||
+ if (res != TEEC_SUCCESS)
|
||||
+ printf("TEEC_InvokeCommand(SET_IV) failed 0x%x origin 0x%x",
|
||||
+ res, origin);
|
||||
+}
|
||||
+
|
||||
+static void cipher_buffer(struct tee_ctx *ctx, char *in, char *out, size_t sz)
|
||||
+{
|
||||
+ TEEC_Operation op;
|
||||
+ uint32_t origin;
|
||||
+ TEEC_Result res;
|
||||
+
|
||||
+ memset(&op, 0, sizeof(op));
|
||||
+ op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT,
|
||||
+ TEEC_MEMREF_TEMP_OUTPUT,
|
||||
+ TEEC_NONE, TEEC_NONE);
|
||||
+ op.params[0].tmpref.buffer = in;
|
||||
+ op.params[0].tmpref.size = sz;
|
||||
+ op.params[1].tmpref.buffer = out;
|
||||
+ op.params[1].tmpref.size = sz;
|
||||
+
|
||||
+ res = TEEC_InvokeCommand(&ctx->sess, TA_AES_CMD_CIPHER, &op, &origin);
|
||||
+ if (res != TEEC_SUCCESS)
|
||||
+ printf("TEEC_InvokeCommand(CIPHER) failed 0x%x origin 0x%x",
|
||||
+ res, origin);
|
||||
+}
|
||||
+
|
||||
+int env_optee_crypt(char *keymod, char *data, unsigned int size, const int enc)
|
||||
+{
|
||||
+ struct tee_ctx tee;
|
||||
+ char *cryptdata;
|
||||
+ int ret = 0;
|
||||
+
|
||||
+ prepare_tee_session(&tee);
|
||||
+ prepare_aes(&tee, enc);
|
||||
+ set_key(&tee, TA_AES_SIZE_256BIT);
|
||||
+ set_iv(&tee, keymod, AES_BLOCK_LENGTH);
|
||||
+ cryptdata = calloc(1, size);
|
||||
+ if (cryptdata) {
|
||||
+ cipher_buffer(&tee, data, cryptdata, size);
|
||||
+ memcpy(data, cryptdata, size);
|
||||
+ free(cryptdata);
|
||||
+ } else {
|
||||
+ printf("%s: can't allocate memory\n", __func__);
|
||||
+ ret = -ENOMEM;
|
||||
+ }
|
||||
+ terminate_tee_session(&tee);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+int is_env_optee_encrypted(void)
|
||||
+{
|
||||
+ const char *dt_prop =
|
||||
+ "/proc/device-tree/digi,uboot-env,encrypted-optee";
|
||||
+
|
||||
+ return access(dt_prop, F_OK) != -1;
|
||||
+}
|
||||
diff --git a/src/crypt_optee.h b/src/crypt_optee.h
|
||||
new file mode 100644
|
||||
index 0000000..e0c77a7
|
||||
--- /dev/null
|
||||
+++ b/src/crypt_optee.h
|
||||
@@ -0,0 +1,10 @@
|
||||
+/*
|
||||
+ * Copyright 2024 Digi International Inc
|
||||
+ *
|
||||
+ * SPDX-License-Identifier: GPL-2.0+
|
||||
+ */
|
||||
+
|
||||
+#pragma once
|
||||
+
|
||||
+int env_optee_crypt(char *keymod, char *data, unsigned int size, const int enc);
|
||||
+int is_env_optee_encrypted(void);
|
||||
|
|
@ -1,105 +0,0 @@
|
|||
From: Hector Palacios <hector.palacios@digi.com>
|
||||
Date: Mon, 3 Apr 2023 18:21:07 +0200
|
||||
Subject: [PATCH] fall back to read HWID from nvmem device if not available on
|
||||
DT
|
||||
|
||||
Old U-Boot versions don't populate the HWID on the device tree. This may
|
||||
be used as a key modifier for TrustFence encryption and, if not available
|
||||
on the DT, newer firmware may be unable to unencrypt the U-Boot
|
||||
environment.
|
||||
|
||||
This patch implements a fall-back function to query the HWID directly from
|
||||
the nvmem device node if it cannot locate it at the DT.
|
||||
This is only implemented for ccimx6 family, which may be in the case of
|
||||
having an old U-Boot.
|
||||
|
||||
Signed-off-by: Hector Palacios <hector.palacios@digi.com>
|
||||
|
||||
https://onedigi.atlassian.net/browse/DEL-8444
|
||||
---
|
||||
src/uboot_env.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++--
|
||||
1 file changed, 52 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/uboot_env.c b/src/uboot_env.c
|
||||
index 924a6cf..d507cac 100644
|
||||
--- a/src/uboot_env.c
|
||||
+++ b/src/uboot_env.c
|
||||
@@ -1129,6 +1129,32 @@ static int is_env_encrypted(void)
|
||||
return access(dt_prop, F_OK) != -1;
|
||||
}
|
||||
|
||||
+/* Function that checks if machine is compatible (on the DT) */
|
||||
+static bool machine_is_compatible(char *machine)
|
||||
+{
|
||||
+ int fd, nchars, len = 0;
|
||||
+ int ret = false;
|
||||
+ char str[256];
|
||||
+ char *p = str;
|
||||
+
|
||||
+ fd = open("/proc/device-tree/compatible", O_RDONLY);
|
||||
+ if (fd < 0)
|
||||
+ return false;
|
||||
+
|
||||
+ nchars = read(fd, str, 255);
|
||||
+ while (len < nchars) {
|
||||
+ if (!strcmp(p, machine)) {
|
||||
+ ret = true;
|
||||
+ break;
|
||||
+ }
|
||||
+ len += strlen(p) + 1;
|
||||
+ p += strlen(p) + 1;
|
||||
+ }
|
||||
+
|
||||
+ close(fd);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
#define MAX_HWID_WORDS 4
|
||||
static int env_caam_get_keymod(unsigned char output[16])
|
||||
{
|
||||
@@ -1137,12 +1163,11 @@ static int env_caam_get_keymod(unsigned char output[16])
|
||||
int fd;
|
||||
uint32_t ocotp_hwid[MAX_HWID_WORDS];
|
||||
char dt_prop[32];
|
||||
+ char buf[sizeof(uint32_t)];
|
||||
|
||||
for (i = 0; i < MAX_HWID_WORDS; i++) {
|
||||
sprintf(dt_prop, "/proc/device-tree/digi,hwid_%d", i);
|
||||
if (access(dt_prop, F_OK) != -1) {
|
||||
- char buf[sizeof(uint32_t)];
|
||||
-
|
||||
fd = open(dt_prop, O_RDONLY);
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
@@ -1153,6 +1178,31 @@ static int env_caam_get_keymod(unsigned char output[16])
|
||||
}
|
||||
ocotp_hwid[i] = ntohl(*(uint32_t *)buf);
|
||||
close(fd);
|
||||
+ } else if (machine_is_compatible("digi,ccimx6ul") ||
|
||||
+ machine_is_compatible("digi,ccimx6")) {
|
||||
+ /*
|
||||
+ * If HWID not available on the DT (old U-Boot version),
|
||||
+ * fall back to read it directly from the nvmem device.
|
||||
+ */
|
||||
+ int hwid_offset = 136; /* (Bank * 8 + Word) * 4 */
|
||||
+
|
||||
+ /* HWID for CC6 family only has two words */
|
||||
+ if (i == 2)
|
||||
+ break;
|
||||
+
|
||||
+ fd = open("/sys/bus/nvmem/devices/imx-ocotp0/nvmem",
|
||||
+ O_RDONLY);
|
||||
+ if (fd < 0)
|
||||
+ return fd;
|
||||
+ len = lseek(fd, hwid_offset + i * 4, SEEK_SET);
|
||||
+
|
||||
+ len = read(fd, buf, sizeof(unsigned int));
|
||||
+ if (len < 0) {
|
||||
+ close(fd);
|
||||
+ return -1;
|
||||
+ }
|
||||
+ ocotp_hwid[i] = *(unsigned int *)buf;
|
||||
+ close(fd);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -15,13 +15,18 @@ FW_CONFIG_FILE:ccmp1 = "${@bb.utils.contains('IMAGE_FEATURES', 'read-only-rootfs
|
|||
'ubi/fw_env.config_default', \
|
||||
'ubi/fw_env.config', d)}"
|
||||
|
||||
DEPENDS += "${@oe.utils.conditional('OPTEE_PATCHES', '', '', 'optee-client', d)}"
|
||||
|
||||
OPTEE_PATCHES = ""
|
||||
OPTEE_PATCHES:ccimx93 = "file://0004-Implement-support-for-environment-encryption-using-O.patch"
|
||||
OPTEE_PATCHES:ccmp1 = "file://0004-Implement-support-for-environment-encryption-using-O.patch"
|
||||
|
||||
SRC_URI += " \
|
||||
file://${FW_CONFIG_FILE} \
|
||||
file://0001-Implement-support-for-environment-encryption-by-CAAM.patch \
|
||||
file://0002-Implement-U-Boot-environment-access-functions.patch \
|
||||
file://0003-tools-env-add-support-to-set-dynamic-location-of-env.patch \
|
||||
file://0004-fall-back-to-read-HWID-from-nvmem-device-if-not-avai.patch \
|
||||
file://0005-Implement-support-for-environment-encryption-for-CCM.patch \
|
||||
file://0001-Implement-U-Boot-environment-access-functions.patch \
|
||||
file://0002-tools-env-add-support-to-set-dynamic-location-of-env.patch \
|
||||
file://0003-Implement-support-for-environment-encryption-by-CAAM.patch \
|
||||
${@bb.utils.contains('MACHINE_FEATURES', 'optee', '${OPTEE_PATCHES}', '', d)} \
|
||||
"
|
||||
|
||||
do_install:append() {
|
||||
|
|
|
|||
Loading…
Reference in New Issue