From: "Diaz de Grenu, Jose" 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 --- 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 +#include + +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 #include #include +#include #include #ifdef MTD_OLD @@ -32,12 +33,21 @@ # include #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;