291 lines
6.5 KiB
Diff
291 lines
6.5 KiB
Diff
From: Hector Palacios <hector.palacios@digi.com>
|
|
Date: Fri, 17 Jul 2020 07:08:50 +0200
|
|
Subject: [PATCH] tools: env: implement support for environment encryption by
|
|
CAAM
|
|
|
|
Use the md5sum of HWID words (on the device tree) as key modifier.
|
|
|
|
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>
|
|
|
|
https://jira.digi.com/browse/DEL-7185
|
|
https://jira.digi.com/browse/DEL-2836
|
|
---
|
|
tools/env/Makefile | 2 +-
|
|
tools/env/caam_keyblob.h | 45 +++++++++++++
|
|
tools/env/fw_env.c | 141 +++++++++++++++++++++++++++++++++++++++
|
|
3 files changed, 187 insertions(+), 1 deletion(-)
|
|
create mode 100644 tools/env/caam_keyblob.h
|
|
|
|
diff --git a/tools/env/Makefile b/tools/env/Makefile
|
|
index b627796e949e..fc7c44baa2b7 100644
|
|
--- a/tools/env/Makefile
|
|
+++ b/tools/env/Makefile
|
|
@@ -24,7 +24,7 @@ hostprogs-y := fw_printenv
|
|
|
|
lib-y += fw_env.o \
|
|
crc32.o ctype.o linux_string.o \
|
|
- env_attr.o env_flags.o
|
|
+ env_attr.o env_flags.o ../../lib/md5.o
|
|
|
|
fw_printenv-objs := fw_env_main.o $(lib-y)
|
|
|
|
diff --git a/tools/env/caam_keyblob.h b/tools/env/caam_keyblob.h
|
|
new file mode 100644
|
|
index 000000000000..1cdf3946c1ba
|
|
--- /dev/null
|
|
+++ b/tools/env/caam_keyblob.h
|
|
@@ -0,0 +1,45 @@
|
|
+/*
|
|
+ * CAAM public-level include definitions for the key blob
|
|
+ *
|
|
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
|
|
+ */
|
|
+
|
|
+#ifndef CAAM_KEYBLOB_H
|
|
+#define CAAM_KEYBLOB_H
|
|
+
|
|
+
|
|
+#include <linux/ioctl.h>
|
|
+#include <linux/types.h>
|
|
+
|
|
+struct caam_kb_data {
|
|
+ char *rawkey;
|
|
+ size_t rawkey_len;
|
|
+ char *keyblob;
|
|
+ size_t keyblob_len;
|
|
+ char *keymod;
|
|
+ size_t keymod_len;
|
|
+};
|
|
+
|
|
+
|
|
+#define CAAM_KB_MAGIC 'I'
|
|
+
|
|
+/**
|
|
+ * DOC: CAAM_KB_ENCRYPT - generate a key blob from raw key
|
|
+ *
|
|
+ * Takes an caam_kb_data struct and returns it with the key blob
|
|
+ */
|
|
+#define CAAM_KB_ENCRYPT _IOWR(CAAM_KB_MAGIC, 0, \
|
|
+ struct caam_kb_data)
|
|
+
|
|
+/**
|
|
+ * DOC: CAAM_KB_DECRYPT - get keys from a key blob
|
|
+ *
|
|
+ * Takes an caam_kb_data struct and returns it with the raw key.
|
|
+ */
|
|
+#define CAAM_KB_DECRYPT _IOWR(CAAM_KB_MAGIC, 1, struct caam_kb_data)
|
|
+
|
|
+#ifndef GENMEM_KEYMOD_LEN
|
|
+#define GENMEM_KEYMOD_LEN 16
|
|
+#endif
|
|
+
|
|
+#endif /* CAAM_KEYBLOB_H */
|
|
diff --git a/tools/env/fw_env.c b/tools/env/fw_env.c
|
|
index a5d75958e1b6..228d11c070e6 100644
|
|
--- a/tools/env/fw_env.c
|
|
+++ b/tools/env/fw_env.c
|
|
@@ -24,6 +24,7 @@
|
|
#include <sys/types.h>
|
|
#include <sys/ioctl.h>
|
|
#include <sys/stat.h>
|
|
+#include <u-boot/md5.h>
|
|
#include <unistd.h>
|
|
#include <dirent.h>
|
|
|
|
@@ -37,9 +38,17 @@
|
|
|
|
#include <mtd/ubi-user.h>
|
|
|
|
+#include "caam_keyblob.h"
|
|
#include "fw_env_private.h"
|
|
#include "fw_env.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"
|
|
+
|
|
struct env_opts default_opts = {
|
|
#ifdef CONFIG_FILE
|
|
.config_file = CONFIG_FILE
|
|
@@ -117,6 +126,7 @@ static struct environment environment = {
|
|
};
|
|
|
|
static int have_redund_env;
|
|
+static int caam_encryption_flag;
|
|
|
|
static unsigned char active_flag = 1;
|
|
/* obsolete_flag must be 0 to efficiently set it on NOR flash without erasing */
|
|
@@ -442,6 +452,106 @@ char *fw_getdefenv(char *name)
|
|
return NULL;
|
|
}
|
|
|
|
+static void check_caam_encryption(void)
|
|
+{
|
|
+ const char *dt_prop = "/proc/device-tree/digi,uboot-env,encrypted";
|
|
+
|
|
+ if (access(dt_prop, F_OK) != -1)
|
|
+ caam_encryption_flag = 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];
|
|
+ const 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, const int enc)
|
|
+{
|
|
+ struct caam_kb_data enc_data;
|
|
+ int fd;
|
|
+ int ret = 0;
|
|
+ const int len = usable_envsize;
|
|
+ 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, len);
|
|
+
|
|
+out:
|
|
+ close(fd);
|
|
+free:
|
|
+ free(buffer);
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
/*
|
|
* Print the current definition of one, or more, or all
|
|
* environment variables
|
|
@@ -505,9 +615,20 @@ int fw_printenv(int argc, char *argv[], int value_only, struct env_opts *opts)
|
|
|
|
int fw_env_flush(struct env_opts *opts)
|
|
{
|
|
+ int ret;
|
|
+
|
|
if (!opts)
|
|
opts = &default_opts;
|
|
|
|
+ if (caam_encryption_flag) {
|
|
+ ret = env_caam_crypt(environment.data, 1);
|
|
+ if (ret) {
|
|
+ fprintf(stderr,
|
|
+ "Error: can't encrypt env for flash\n");
|
|
+ return ret;
|
|
+ }
|
|
+ }
|
|
+
|
|
/*
|
|
* Update CRC
|
|
*/
|
|
@@ -1396,6 +1517,8 @@ int fw_env_open(struct env_opts *opts)
|
|
struct env_image_single *single;
|
|
struct env_image_redundant *redundant;
|
|
|
|
+ check_caam_encryption();
|
|
+
|
|
if (!opts)
|
|
opts = &default_opts;
|
|
|
|
@@ -1434,6 +1557,15 @@ int fw_env_open(struct env_opts *opts)
|
|
|
|
crc0 = crc32(0, (uint8_t *)environment.data, ENV_SIZE);
|
|
|
|
+ if (caam_encryption_flag) {
|
|
+ ret = env_caam_crypt(environment.data, 0);
|
|
+ if (ret) {
|
|
+ fprintf(stderr,
|
|
+ "Error: can't decrypt environment\n");
|
|
+ return ret;
|
|
+ }
|
|
+ }
|
|
+
|
|
crc0_ok = (crc0 == *environment.crc);
|
|
if (!have_redund_env) {
|
|
if (!crc0_ok) {
|
|
@@ -1491,6 +1623,15 @@ int fw_env_open(struct env_opts *opts)
|
|
|
|
crc1 = crc32(0, (uint8_t *)redundant->data, ENV_SIZE);
|
|
|
|
+ if (caam_encryption_flag) {
|
|
+ ret = env_caam_crypt(redundant->data, 0);
|
|
+ if (ret) {
|
|
+ fprintf(stderr,
|
|
+ "Error: can't decrypt environment\n");
|
|
+ return ret;
|
|
+ }
|
|
+ }
|
|
+
|
|
crc1_ok = (crc1 == redundant->crc);
|
|
flag1 = redundant->flags;
|