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
|
#endif
|
||||||
diff --git a/src/uboot_env.c b/src/uboot_env.c
|
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
|
--- a/src/uboot_env.c
|
||||||
+++ b/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);
|
free(ctx);
|
||||||
}
|
}
|
||||||
|
|
@ -27,10 +27,10 @@ Signed-off-by: Gabriel Valcazar <gabriel.valcazar@digi.com>
|
||||||
2 files changed, 90 insertions(+), 2 deletions(-)
|
2 files changed, 90 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
diff --git a/src/uboot_env.c b/src/uboot_env.c
|
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
|
--- a/src/uboot_env.c
|
||||||
+++ b/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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -104,7 +104,7 @@ index b7ad4c4..924a6cf 100644
|
||||||
static bool check_compatible_devices(struct uboot_ctx *ctx)
|
static bool check_compatible_devices(struct uboot_ctx *ctx)
|
||||||
{
|
{
|
||||||
if (!ctx->redundant)
|
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;
|
return false;
|
||||||
if (ctx->envdevs[0].envsize != ctx->envdevs[1].envsize)
|
if (ctx->envdevs[0].envsize != ctx->envdevs[1].envsize)
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -117,7 +117,7 @@ index b7ad4c4..924a6cf 100644
|
||||||
|
|
||||||
return true;
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -126,7 +126,7 @@ index b7ad4c4..924a6cf 100644
|
||||||
{
|
{
|
||||||
size_t count;
|
size_t count;
|
||||||
size_t blocksize;
|
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);
|
ret = read(dev->fd, data, dev->envsize);
|
||||||
break;
|
break;
|
||||||
case MTD_NANDFLASH:
|
case MTD_NANDFLASH:
|
||||||
|
|
@ -144,7 +144,7 @@ index b7ad4c4..924a6cf 100644
|
||||||
if (dev->offset)
|
if (dev->offset)
|
||||||
if (lseek(dev->fd, dev->offset, SEEK_SET) < 0) {
|
if (lseek(dev->fd, dev->offset, SEEK_SET) < 0) {
|
||||||
ret = -EIO;
|
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);
|
ret = fileread(dev, data);
|
||||||
break;
|
break;
|
||||||
case DEVICE_MTD:
|
case DEVICE_MTD:
|
||||||
|
|
@ -154,13 +154,13 @@ index b7ad4c4..924a6cf 100644
|
||||||
case DEVICE_UBI:
|
case DEVICE_UBI:
|
||||||
ret = ubiread(dev, data);
|
ret = ubiread(dev, data);
|
||||||
diff --git a/src/uboot_private.h b/src/uboot_private.h
|
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
|
--- a/src/uboot_private.h
|
||||||
+++ b/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;
|
bool redundant;
|
||||||
/** true if the environment is encrypted */
|
|
||||||
bool encrypted;
|
|
||||||
+ /** true if the environment is dynamic */
|
+ /** true if the environment is dynamic */
|
||||||
+ bool dynamic_env;
|
+ bool dynamic_env;
|
||||||
/** set to valid after a successful load */
|
/** set to valid after a successful load */
|
||||||
|
|
@ -169,6 +169,6 @@ index ee2d305..84bd1bc 100644
|
||||||
size_t size;
|
size_t size;
|
||||||
+ /** top limit of the dynamic environment */
|
+ /** top limit of the dynamic environment */
|
||||||
+ loff_t top_limit;
|
+ loff_t top_limit;
|
||||||
/** usable environment size */
|
|
||||||
unsigned int usable_size;
|
|
||||||
/** devices where environment is stored */
|
/** 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: Gonzalo Ruiz <Gonzalo.Ruiz@digi.com>
|
||||||
Signed-off-by: Hector Palacios <hector.palacios@digi.com>
|
Signed-off-by: Hector Palacios <hector.palacios@digi.com>
|
||||||
Signed-off-by: Gabriel Valcazar <gabriel.valcazar@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/CMakeLists.txt | 4 +
|
||||||
src/caam_keyblob.h | 42 +++++++
|
src/caam_keyblob.h | 42 +++++++
|
||||||
src/md5.c | 275 ++++++++++++++++++++++++++++++++++++++++++++
|
src/crypt.c | 179 +++++++++++++++++++++++++++++
|
||||||
src/md5.h | 24 ++++
|
src/crypt.h | 10 ++
|
||||||
src/uboot_env.c | 131 +++++++++++++++++++++
|
src/md5.c | 275 +++++++++++++++++++++++++++++++++++++++++++++
|
||||||
src/uboot_private.h | 4 +
|
src/md5.h | 24 ++++
|
||||||
6 files changed, 478 insertions(+)
|
src/uboot_env.c | 18 +++
|
||||||
|
7 files changed, 552 insertions(+)
|
||||||
create mode 100644 src/caam_keyblob.h
|
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.c
|
||||||
create mode 100644 src/md5.h
|
create mode 100644 src/md5.h
|
||||||
|
|
||||||
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
|
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
|
||||||
index ababe0f..fb1efa2 100644
|
index ababe0f..638f1c1 100644
|
||||||
--- a/src/CMakeLists.txt
|
--- a/src/CMakeLists.txt
|
||||||
+++ b/src/CMakeLists.txt
|
+++ b/src/CMakeLists.txt
|
||||||
@@ -4,6 +4,8 @@
|
@@ -4,6 +4,10 @@
|
||||||
cmake_minimum_required (VERSION 2.6)
|
cmake_minimum_required (VERSION 2.6)
|
||||||
# Sources and private headers
|
# Sources and private headers
|
||||||
SET(libubootenv_SOURCES
|
SET(libubootenv_SOURCES
|
||||||
|
+ crypt.c
|
||||||
|
+ crypt.h
|
||||||
+ md5.c
|
+ md5.c
|
||||||
+ md5.h
|
+ md5.h
|
||||||
uboot_env.c
|
uboot_env.c
|
||||||
|
|
@ -88,6 +125,207 @@ index 0000000..e313e87
|
||||||
+#endif
|
+#endif
|
||||||
+
|
+
|
||||||
+#endif /* CAAM_KEYBLOB_H */
|
+#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
|
diff --git a/src/md5.c b/src/md5.c
|
||||||
new file mode 100644
|
new file mode 100644
|
||||||
index 0000000..47ae8bf
|
index 0000000..47ae8bf
|
||||||
|
|
@ -400,146 +638,26 @@ index 0000000..02a9a9d
|
||||||
+
|
+
|
||||||
+#endif /* _MD5_H */
|
+#endif /* _MD5_H */
|
||||||
diff --git a/src/uboot_env.c b/src/uboot_env.c
|
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
|
--- a/src/uboot_env.c
|
||||||
+++ b/src/uboot_env.c
|
+++ b/src/uboot_env.c
|
||||||
@@ -34,11 +34,21 @@
|
@@ -37,6 +37,7 @@
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <zlib.h>
|
|
||||||
#include <yaml.h>
|
|
||||||
+#include <arpa/inet.h>
|
|
||||||
#include <mtd/mtd-user.h>
|
#include <mtd/mtd-user.h>
|
||||||
#include <mtd/ubi-user.h>
|
#include <mtd/ubi-user.h>
|
||||||
|
|
||||||
+#include "caam_keyblob.h"
|
+#include "crypt.h"
|
||||||
+#include "md5.h"
|
|
||||||
#include "uboot_private.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 UBI_MAX_VOLUME 128
|
||||||
|
@@ -1187,6 +1188,15 @@ int libuboot_env_store(struct uboot_ctx *ctx)
|
||||||
#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)
|
|
||||||
((struct uboot_env_redund *)image)->flags = flags;
|
((struct uboot_env_redund *)image)->flags = flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
+ if (ctx->encrypted) {
|
+ if (is_env_encrypted()) {
|
||||||
+ ret = env_caam_crypt(data, ctx->usable_size, 1);
|
+ size_t usable_envsize = ctx->size - offsetdata;
|
||||||
|
+ ret = env_crypt(data, usable_envsize, 1);
|
||||||
+ if (ret) {
|
+ if (ret) {
|
||||||
+ fprintf(stderr,
|
+ fprintf(stderr, "Error: can't encrypt env for flash\n");
|
||||||
+ "Error: can't encrypt env for flash\n");
|
|
||||||
+ return ret;
|
+ return ret;
|
||||||
+ }
|
+ }
|
||||||
+ }
|
+ }
|
||||||
|
|
@ -547,56 +665,18 @@ index ae85c7e..750b736 100644
|
||||||
*(uint32_t *)image = crc32(0, (uint8_t *)data, ctx->size - offsetdata);
|
*(uint32_t *)image = crc32(0, (uint8_t *)data, ctx->size - offsetdata);
|
||||||
|
|
||||||
copy = ctx->redundant ? (ctx->current ? 0 : 1) : 0;
|
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);
|
crc = *(uint32_t *)(buf[i] + offsetcrc);
|
||||||
dev->crc = crc32(0, (uint8_t *)data, usable_envsize);
|
dev->crc = crc32(0, (uint8_t *)data, usable_envsize);
|
||||||
+ if (ctx->encrypted) {
|
+ if (is_env_encrypted()) {
|
||||||
+ ret = env_caam_crypt((char *)data, ctx->usable_size, 0);
|
+ ret = env_crypt(data, usable_envsize, 0);
|
||||||
+ if (ret) {
|
+ if (ret) {
|
||||||
+ fprintf(stderr, "Error: can't decrypt environment\n");
|
+ fprintf(stderr,
|
||||||
|
+ "Error: can't decrypt environment\n");
|
||||||
+ return ret;
|
+ return ret;
|
||||||
+ }
|
+ }
|
||||||
+ }
|
+ }
|
||||||
crcenv[i] = dev->crc == crc;
|
crcenv[i] = dev->crc == crc;
|
||||||
if (ctx->redundant)
|
if (ctx->redundant)
|
||||||
dev->flags = *(uint8_t *)(buf[i] + offsetflags);
|
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_default', \
|
||||||
'ubi/fw_env.config', d)}"
|
'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 += " \
|
SRC_URI += " \
|
||||||
file://${FW_CONFIG_FILE} \
|
file://${FW_CONFIG_FILE} \
|
||||||
file://0001-Implement-support-for-environment-encryption-by-CAAM.patch \
|
file://0001-Implement-U-Boot-environment-access-functions.patch \
|
||||||
file://0002-Implement-U-Boot-environment-access-functions.patch \
|
file://0002-tools-env-add-support-to-set-dynamic-location-of-env.patch \
|
||||||
file://0003-tools-env-add-support-to-set-dynamic-location-of-env.patch \
|
file://0003-Implement-support-for-environment-encryption-by-CAAM.patch \
|
||||||
file://0004-fall-back-to-read-HWID-from-nvmem-device-if-not-avai.patch \
|
${@bb.utils.contains('MACHINE_FEATURES', 'optee', '${OPTEE_PATCHES}', '', d)} \
|
||||||
file://0005-Implement-support-for-environment-encryption-for-CCM.patch \
|
|
||||||
"
|
"
|
||||||
|
|
||||||
do_install:append() {
|
do_install:append() {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue