meta-digi/meta-digi-arm/recipes-bsp/u-boot/u-boot-fw-utils/0001-tools-env-implement-su...

294 lines
6.5 KiB
Diff

From: "Diaz de Grenu, Jose" <Jose.DiazdeGrenu@digi.com>
Date: Tue, 23 Aug 2016 13:05:05 +0200
Subject: [PATCH] tools: env: implement support for environment encryption by
CAAM
https://jira.digi.com/browse/DEL-2836
Signed-off-by: Diaz de Grenu, Jose <Jose.DiazdeGrenu@digi.com>
---
configs/sandbox_defconfig | 1 +
tools/env/Makefile | 2 +-
tools/env/caam_keyblob.h | 45 +++++++++++++++
tools/env/fw_env.c | 138 ++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 185 insertions(+), 1 deletion(-)
create mode 100644 tools/env/caam_keyblob.h
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 02534bfea761..5a690c1cc623 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -90,3 +90,4 @@ CONFIG_UNIT_TEST=y
CONFIG_UT_TIME=y
CONFIG_UT_DM=y
CONFIG_UT_ENV=y
+CONFIG_MD5=y
diff --git a/tools/env/Makefile b/tools/env/Makefile
index 38ad118d032f..fa2a564bb357 100644
--- a/tools/env/Makefile
+++ b/tools/env/Makefile
@@ -25,7 +25,7 @@ hostprogs-y := fw_printenv
lib-y += fw_env.o \
crc32.o ctype.o linux_string.o \
- env_attr.o env_flags.o aes.o
+ env_attr.o env_flags.o aes.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 b2f62827d918..46c619b211b5 100644
--- a/tools/env/fw_env.c
+++ b/tools/env/fw_env.c
@@ -22,6 +22,7 @@
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
+#include <u-boot/md5.h>
#include <unistd.h>
#ifdef MTD_OLD
@@ -32,12 +33,21 @@
# include <mtd/mtd-user.h>
#endif
+#include "caam_keyblob.h"
#include "fw_env.h"
struct common_args common_args;
struct printenv_args printenv_args;
struct setenv_args setenv_args;
+/*
+ * 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 ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
#define WHITESPACE(c) ((c == '\t') || (c == ' '))
@@ -109,6 +119,8 @@ static struct environment environment = {
static int env_aes_cbc_crypt(char *data, const int enc);
+static int caam_encryption_flag;
+
static int HaveRedundEnv = 0;
static unsigned char active_flag = 1;
@@ -234,6 +246,103 @@ int parse_aes_key(char *key, uint8_t *bin_key)
return 0;
}
+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;
+}
+
+static int env_caam_get_keymod(unsigned char output[16])
+{
+ int i;
+ int len;
+ int fd;
+ char buff[32];
+ uint32_t ocotp_hwid[2];
+ const char *ocotp_hwid_file[2] = {
+ "/sys/fsl_otp/HW_OCOTP_MAC0",
+ "/sys/fsl_otp/HW_OCOTP_MAC1"
+ };
+
+ for (i = 0; i < ARRAY_SIZE(ocotp_hwid); i++) {
+ fd = open(ocotp_hwid_file[i], O_RDONLY);
+ if (fd < 0)
+ return fd;
+ len = read(fd, buff, sizeof(buff));
+ if (len < 0) {
+ close(fd);
+ return -1;
+ }
+ /* drop last character (new line) */
+ buff[len - 1] = '\0';
+ ocotp_hwid[i] = strtoul(buff, NULL, 0);
+ close(fd);
+ }
+
+ md5((unsigned char *)(&ocotp_hwid), sizeof(ocotp_hwid), 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 = getenvsize();
+ 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
@@ -311,6 +420,15 @@ int fw_env_close(void)
}
}
+ 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
*/
@@ -1154,6 +1272,8 @@ int fw_env_open(void)
struct env_image_single *single;
struct env_image_redundant *redundant;
+ check_caam_encryption();
+
if (parse_config ()) /* should fill envdevices */
return -1;
@@ -1192,6 +1312,15 @@ int fw_env_open(void)
return ret;
}
+ 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 (!HaveRedundEnv) {
if (!crc0_ok) {
@@ -1249,6 +1378,15 @@ int fw_env_open(void)
return ret;
}
+ 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;