[U-Boot] [PATCH 1/3] env: Add env_export() wrapper

Implement env_export() wrapper, so that all implementers of saveenv() don't have to call hexport_r(), crc32() etc. sequence . This trims down a bit of code duplication.
Signed-off-by: Marek Vasut marex@denx.de --- common/env_common.c | 17 +++++++++++++++++ common/env_dataflash.c | 17 ++++++----------- common/env_eeprom.c | 12 +++--------- common/env_fat.c | 12 +++--------- common/env_flash.c | 21 ++++++--------------- common/env_mmc.c | 12 ++---------- common/env_nand.c | 13 ++++--------- common/env_nvram.c | 12 +++--------- common/env_onenand.c | 13 ++++--------- common/env_sf.c | 24 +++++++----------------- common/env_ubi.c | 27 ++++++++------------------- include/environment.h | 3 +++ 12 files changed, 66 insertions(+), 117 deletions(-)
diff --git a/common/env_common.c b/common/env_common.c index c0bfc2f..fe35ff4 100644 --- a/common/env_common.c +++ b/common/env_common.c @@ -172,6 +172,23 @@ int env_import(const char *buf, int check) return 0; }
+/* Emport the environment and generate CRC for it. */ +int env_export(env_t *env_out) +{ + char *res; + ssize_t len; + + res = (char *)env_out->data; + len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL); + if (len < 0) { + error("Cannot export environment: errno = %d\n", errno); + return 1; + } + env_out->crc = crc32(0, env_out->data, ENV_SIZE); + + return 0; +} + void env_relocate(void) { #if defined(CONFIG_NEEDS_MANUAL_RELOC) diff --git a/common/env_dataflash.c b/common/env_dataflash.c index b53b87e..034e323 100644 --- a/common/env_dataflash.c +++ b/common/env_dataflash.c @@ -56,17 +56,12 @@ void env_relocate_spec(void)
int saveenv(void) { - env_t env_new; - ssize_t len; - char *res; - - res = (char *)&env_new.data; - len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL); - if (len < 0) { - error("Cannot export environment: errno = %d\n", errno); - return 1; - } - env_new.crc = crc32(0, env_new.data, ENV_SIZE); + env_t env_new; + int ret; + + ret = env_export(&env_new); + if (ret) + return ret;
return write_dataflash(CONFIG_ENV_ADDR, (unsigned long)&env_new, diff --git a/common/env_eeprom.c b/common/env_eeprom.c index 0db2bb6..490ac73 100644 --- a/common/env_eeprom.c +++ b/common/env_eeprom.c @@ -98,8 +98,6 @@ void env_relocate_spec(void) int saveenv(void) { env_t env_new; - ssize_t len; - char *res; int rc; unsigned int off = CONFIG_ENV_OFFSET; #ifdef CONFIG_ENV_OFFSET_REDUND @@ -109,13 +107,9 @@ int saveenv(void)
BUG_ON(env_ptr != NULL);
- res = (char *)&env_new.data; - len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL); - if (len < 0) { - error("Cannot export environment: errno = %d\n", errno); - return 1; - } - env_new.crc = crc32(0, env_new.data, ENV_SIZE); + rc = env_export(&env_new); + if (rc) + return rc;
#ifdef CONFIG_ENV_OFFSET_REDUND if (gd->env_valid == 1) { diff --git a/common/env_fat.c b/common/env_fat.c index 708fd13..aad0487 100644 --- a/common/env_fat.c +++ b/common/env_fat.c @@ -37,19 +37,14 @@ int env_init(void) int saveenv(void) { env_t env_new; - ssize_t len; - char *res; block_dev_desc_t *dev_desc = NULL; int dev = FAT_ENV_DEVICE; int part = FAT_ENV_PART; int err;
- res = (char *)&env_new.data; - len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL); - if (len < 0) { - error("Cannot export environment: errno = %d\n", errno); - return 1; - } + err = env_export(&env_new); + if (err) + return err;
#ifdef CONFIG_MMC if (strcmp(FAT_ENV_INTERFACE, "mmc") == 0) { @@ -79,7 +74,6 @@ int saveenv(void) return 1; }
- env_new.crc = crc32(0, env_new.data, ENV_SIZE); err = file_fat_write(FAT_ENV_FILE, (void *)&env_new, sizeof(env_t)); if (err == -1) { printf("\n** Unable to write "%s" from %s%d:%d **\n", diff --git a/common/env_flash.c b/common/env_flash.c index 7d5a4cf..b3ad908 100644 --- a/common/env_flash.c +++ b/common/env_flash.c @@ -106,8 +106,7 @@ int env_init(void) int saveenv(void) { env_t env_new; - ssize_t len; - char *res, *saved_data = NULL; + char *saved_data = NULL; char flag = OBSOLETE_FLAG, new_flag = ACTIVE_FLAG; int rc = 1; #if CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE @@ -125,13 +124,9 @@ int saveenv(void) if (flash_sect_protect(0, (ulong)flash_addr_new, end_addr_new)) goto done;
- res = (char *)&env_new.data; - len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL); - if (len < 0) { - error("Cannot export environment: errno = %d\n", errno); - goto done; - } - env_new.crc = crc32(0, env_new.data, ENV_SIZE); + rc = env_export(&env_new); + if (rc) + return rc; env_new.flags = new_flag;
#if CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE @@ -258,13 +253,9 @@ int saveenv(void) if (flash_sect_protect(0, (long)flash_addr, end_addr)) goto done;
- res = (char *)&env_new.data; - len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL); - if (len < 0) { - error("Cannot export environment: errno = %d\n", errno); + rc = env_export(&env_new); + if (rc) goto done; - } - env_new.crc = crc32(0, env_new.data, ENV_SIZE);
puts("Erasing Flash..."); if (flash_sect_erase((long)flash_addr, end_addr)) diff --git a/common/env_mmc.c b/common/env_mmc.c index 045428c..c99fc75 100644 --- a/common/env_mmc.c +++ b/common/env_mmc.c @@ -118,8 +118,6 @@ static unsigned char env_flags; int saveenv(void) { ALLOC_CACHE_ALIGN_BUFFER(env_t, env_new, 1); - ssize_t len; - char *res; struct mmc *mmc = find_mmc_device(CONFIG_SYS_MMC_ENV_DEV); u32 offset; int ret, copy = 0; @@ -127,15 +125,9 @@ int saveenv(void) if (init_mmc_for_env(mmc)) return 1;
- res = (char *)&env_new->data; - len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL); - if (len < 0) { - error("Cannot export environment: errno = %d\n", errno); - ret = 1; + ret = env_export(env_new); + if (ret) goto fini; - } - - env_new->crc = crc32(0, &env_new->data[0], ENV_SIZE);
#ifdef CONFIG_ENV_OFFSET_REDUND env_new->flags = ++env_flags; /* increase the serial */ diff --git a/common/env_nand.c b/common/env_nand.c index 695a9ee..b94545d 100644 --- a/common/env_nand.c +++ b/common/env_nand.c @@ -181,8 +181,6 @@ int saveenv(void) { int ret = 0; ALLOC_CACHE_ALIGN_BUFFER(env_t, env_new, 1); - ssize_t len; - char *res; int env_idx = 0; static const struct env_location location[] = { { @@ -207,13 +205,10 @@ int saveenv(void) if (CONFIG_ENV_RANGE < CONFIG_ENV_SIZE) return 1;
- res = (char *)&env_new->data; - len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL); - if (len < 0) { - error("Cannot export environment: errno = %d\n", errno); - return 1; - } - env_new->crc = crc32(0, env_new->data, ENV_SIZE); + ret = env_export(&env_new); + if (ret) + return ret; + #ifdef CONFIG_ENV_OFFSET_REDUND env_new->flags = ++env_flags; /* increase the serial */ env_idx = (gd->env_valid == 1); diff --git a/common/env_nvram.c b/common/env_nvram.c index 0866cde..524f07d 100644 --- a/common/env_nvram.c +++ b/common/env_nvram.c @@ -69,17 +69,11 @@ void env_relocate_spec(void) int saveenv(void) { env_t env_new; - ssize_t len; - char *res; int rcode = 0;
- res = (char *)&env_new.data; - len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL); - if (len < 0) { - error("Cannot export environment: errno = %d\n", errno); - return 1; - } - env_new.crc = crc32(0, env_new.data, ENV_SIZE); + rcode = env_export(&env_new); + if (rcode) + return rcode;
#ifdef CONFIG_SYS_NVRAM_ACCESS_ROUTINE nvram_write(CONFIG_ENV_ADDR, &env_new, CONFIG_ENV_SIZE); diff --git a/common/env_onenand.c b/common/env_onenand.c index 4b44632..cc3d670 100644 --- a/common/env_onenand.c +++ b/common/env_onenand.c @@ -66,8 +66,7 @@ void env_relocate_spec(void) int saveenv(void) { env_t env_new; - ssize_t len; - char *res; + int ret; struct mtd_info *mtd = &onenand_mtd; #ifdef CONFIG_ENV_ADDR_FLEX struct onenand_chip *this = &onenand_chip; @@ -78,13 +77,9 @@ int saveenv(void) .callback = NULL, };
- res = (char *)&env_new.data; - len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL); - if (len < 0) { - error("Cannot export environment: errno = %d\n", errno); - return 1; - } - env_new.crc = crc32(0, env_new.data, ENV_SIZE); + ret = env_export(&env_new); + if (ret) + return ret;
instr.len = CONFIG_ENV_SIZE; #ifdef CONFIG_ENV_ADDR_FLEX diff --git a/common/env_sf.c b/common/env_sf.c index 9f806fb..3395684 100644 --- a/common/env_sf.c +++ b/common/env_sf.c @@ -47,8 +47,7 @@ static struct spi_flash *env_flash; int saveenv(void) { env_t env_new; - ssize_t len; - char *res, *saved_buffer = NULL, flag = OBSOLETE_FLAG; + char *saved_buffer = NULL, flag = OBSOLETE_FLAG; u32 saved_size, saved_offset, sector = 1; int ret;
@@ -62,13 +61,9 @@ int saveenv(void) } }
- res = (char *)&env_new.data; - len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL); - if (len < 0) { - error("Cannot export environment: errno = %d\n", errno); - return 1; - } - env_new.crc = crc32(0, env_new.data, ENV_SIZE); + ret = env_export(&env_new); + if (ret) + return ret; env_new.flags = ACTIVE_FLAG;
if (gd->env_valid == 1) { @@ -225,10 +220,9 @@ out: int saveenv(void) { u32 saved_size, saved_offset, sector = 1; - char *res, *saved_buffer = NULL; + char *saved_buffer = NULL; int ret = 1; env_t env_new; - ssize_t len;
if (!env_flash) { env_flash = spi_flash_probe(CONFIG_ENV_SPI_BUS, @@ -260,13 +254,9 @@ int saveenv(void) sector++; }
- res = (char *)&env_new.data; - len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL); - if (len < 0) { - error("Cannot export environment: errno = %d\n", errno); + ret = env_export(&env_new); + if (ret) goto done; - } - env_new.crc = crc32(0, env_new.data, ENV_SIZE);
puts("Erasing SPI flash..."); ret = spi_flash_erase(env_flash, CONFIG_ENV_OFFSET, diff --git a/common/env_ubi.c b/common/env_ubi.c index c0828a4..77bbfa6 100644 --- a/common/env_ubi.c +++ b/common/env_ubi.c @@ -37,15 +37,11 @@ static unsigned char env_flags; int saveenv(void) { ALLOC_CACHE_ALIGN_BUFFER(env_t, env_new, 1); - ssize_t len; - char *res; + int ret;
- res = (char *)&env_new->data; - len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL); - if (len < 0) { - error("Cannot export environment: errno = %d\n", errno); - return 1; - } + ret = env_export(env_new); + if (ret) + return ret;
if (ubi_part(CONFIG_ENV_UBI_PART, NULL)) { printf("\n** Cannot find mtd partition "%s"\n", @@ -53,7 +49,6 @@ int saveenv(void) return 1; }
- env_new->crc = crc32(0, env_new->data, ENV_SIZE); env_new->flags = ++env_flags; /* increase the serial */
if (gd->env_valid == 1) { @@ -86,15 +81,11 @@ int saveenv(void) int saveenv(void) { ALLOC_CACHE_ALIGN_BUFFER(env_t, env_new, 1); - ssize_t len; - char *res; + int ret;
- res = (char *)&env_new->data; - len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL); - if (len < 0) { - error("Cannot export environment: errno = %d\n", errno); - return 1; - } + ret = env_export(env_new); + if (ret) + return ret;
if (ubi_part(CONFIG_ENV_UBI_PART, NULL)) { printf("\n** Cannot find mtd partition "%s"\n", @@ -102,8 +93,6 @@ int saveenv(void) return 1; }
- env_new->crc = crc32(0, env_new->data, ENV_SIZE); - if (ubi_volume_write(CONFIG_ENV_UBI_VOLUME, (void *)env_new, CONFIG_ENV_SIZE)) { printf("\n** Unable to write env to %s:%s **\n", diff --git a/include/environment.h b/include/environment.h index 46a3554..f797595 100644 --- a/include/environment.h +++ b/include/environment.h @@ -201,6 +201,9 @@ int set_default_vars(int nvars, char * const vars[]); /* Import from binary representation into hash table */ int env_import(const char *buf, int check);
+/* Export from hash table into binary representation */ +int env_export(env_t *env_out); + #endif /* DO_DEPS_ONLY */
#endif /* _ENVIRONMENT_H_ */

Add function which allows encrypting the whole environment block with AES-128-CBC. The key for the environment is retrieved by env_aes_cbc_get_key() function, which must be implemented on a per-board basis.
Signed-off-by: Marek Vasut marex@denx.de --- common/env_common.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++ include/environment.h | 12 +++++++++- 2 files changed, 73 insertions(+), 1 deletion(-)
diff --git a/common/env_common.c b/common/env_common.c index fe35ff4..cd7b4cd 100644 --- a/common/env_common.c +++ b/common/env_common.c @@ -140,6 +140,52 @@ int set_default_vars(int nvars, char * const vars[]) H_NOCLEAR | H_INTERACTIVE, nvars, vars); }
+#ifdef CONFIG_ENV_AES +#include <aes.h> +/** + * env_aes_cbc_get_key() - Get AES-128-CBC key for the environment + * + * This function shall return 16-byte array containing AES-128 key used + * to encrypt and decrypt the environment. This function must be overriden + * by the implementer as otherwise the environment encryption will not + * work. + */ +__weak uint8_t *env_aes_cbc_get_key(void) +{ + return NULL; +} + +static int env_aes_cbc_crypt(env_t *env, const int enc) +{ + unsigned char *data = env->data; + uint8_t *key; + uint8_t key_exp[AES_EXPAND_KEY_LENGTH]; + uint32_t aes_blocks; + + key = env_aes_cbc_get_key(); + if (!key) + return -EINVAL; + + /* First we expand the key. */ + aes_expand_key(key, key_exp); + + /* Calculate the number of AES blocks to encrypt. */ + aes_blocks = ENV_SIZE / AES_KEY_LENGTH; + + if (enc) + aes_cbc_encrypt_blocks(key_exp, data, data, aes_blocks); + else + aes_cbc_decrypt_blocks(key_exp, data, data, aes_blocks); + + return 0; +} +#else +static inline int env_aes_cbc_crypt(env_t *env, const int enc) +{ + return 0; +} +#endif + /* * Check if CRC is valid and (if yes) import the environment. * Note that "buf" may or may not be aligned. @@ -147,6 +193,7 @@ int set_default_vars(int nvars, char * const vars[]) int env_import(const char *buf, int check) { env_t *ep = (env_t *)buf; + int ret;
if (check) { uint32_t crc; @@ -159,6 +206,14 @@ int env_import(const char *buf, int check) } }
+ /* Decrypt the env if desired. */ + ret = env_aes_cbc_crypt(ep, 0); + if (ret) { + error("Failed to decrypt env!\n"); + set_default_env("!import failed"); + return ret; + } + if (himport_r(&env_htab, (char *)ep->data, ENV_SIZE, '\0', 0, 0, NULL)) { gd->flags |= GD_FLG_ENV_READY; @@ -177,6 +232,7 @@ int env_export(env_t *env_out) { char *res; ssize_t len; + int ret;
res = (char *)env_out->data; len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL); @@ -184,6 +240,12 @@ int env_export(env_t *env_out) error("Cannot export environment: errno = %d\n", errno); return 1; } + + /* Encrypt the env if desired. */ + ret = env_aes_cbc_crypt(env_out, 1); + if (ret) + return ret; + env_out->crc = crc32(0, env_out->data, ENV_SIZE);
return 0; diff --git a/include/environment.h b/include/environment.h index f797595..08679ae 100644 --- a/include/environment.h +++ b/include/environment.h @@ -146,7 +146,12 @@ extern unsigned long nand_env_oob_offset; extern char *env_name_spec; #endif
+#ifdef CONFIG_ENV_AES +/* Make sure the payload is multiple of AES block size */ +#define ENV_SIZE ((CONFIG_ENV_SIZE - ENV_HEADER_SIZE) & ~(16 - 1)) +#else #define ENV_SIZE (CONFIG_ENV_SIZE - ENV_HEADER_SIZE) +#endif
typedef struct environment_s { uint32_t crc; /* CRC32 over data bytes */ @@ -154,7 +159,12 @@ typedef struct environment_s { unsigned char flags; /* active/obsolete flags */ #endif unsigned char data[ENV_SIZE]; /* Environment data */ -} env_t; +} env_t +#ifdef CONFIG_ENV_AES +/* Make sure the env is aligned to block size. */ +__attribute__((aligned(16))) +#endif +;
#ifdef ENV_IS_EMBEDDED extern env_t environment;

Implement support for encrypting/decrypting the environment block into the tools/env/fw_* tools. The cipher used is AES 128 CBC and the implementation depends solely on components internal to U-Boot.
To allow building against the internal AES library, the library did need minor adjustments to not include U-Boot's headers which are not wanted to be included and define missing types.
Signed-off-by: Marek Vasut marex@denx.de --- include/aes.h | 7 +++ lib/aes.c | 4 ++ tools/env/Makefile | 1 + tools/env/fw_env.c | 129 +++++++++++++++++++++++++++++++++++++++++++++++- tools/env/fw_env_main.c | 17 +++++-- 5 files changed, 151 insertions(+), 7 deletions(-)
diff --git a/include/aes.h b/include/aes.h index 4897e6f..891d833 100644 --- a/include/aes.h +++ b/include/aes.h @@ -8,6 +8,13 @@ #ifndef _AES_REF_H_ #define _AES_REF_H_
+#ifdef USE_HOSTCC +/* Define compat stuff for use in fw_* tools. */ +typedef unsigned char u8; +typedef unsigned int u32; +#define debug(...) do {} while(0) +#endif + /* * AES encryption library, with small code size, supporting only 128-bit AES * diff --git a/lib/aes.c b/lib/aes.c index 8b23e10..aec2afa 100644 --- a/lib/aes.c +++ b/lib/aes.c @@ -22,7 +22,11 @@ * REDISTRIBUTION OF THIS SOFTWARE. */
+#ifndef USE_HOSTCC #include <common.h> +#else +#include <string.h> +#endif #include "aes.h"
/* forward s-box */ diff --git a/tools/env/Makefile b/tools/env/Makefile index 27892f7..ae19200 100644 --- a/tools/env/Makefile +++ b/tools/env/Makefile @@ -10,6 +10,7 @@ include $(TOPDIR)/config.mk HOSTSRCS := $(SRCTREE)/lib/crc32.c fw_env.c fw_env_main.c HOSTSRCS += $(SRCTREE)/lib/ctype.c $(SRCTREE)/lib/linux_string.c HOSTSRCS += $(SRCTREE)/common/env_attr.c $(SRCTREE)/common/env_flags.c +HOSTSRCS += $(SRCTREE)/lib/aes.c HEADERS := fw_env.h $(OBJTREE)/include/config.h
# Compile for a hosted environment on the target diff --git a/tools/env/fw_env.c b/tools/env/fw_env.c index 577ce2d..807ec1b 100644 --- a/tools/env/fw_env.c +++ b/tools/env/fw_env.c @@ -31,6 +31,10 @@
#include "fw_env.h"
+#include <aes.h> + +#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) + #define WHITESPACE(c) ((c == '\t') || (c == ' '))
#define min(x, y) ({ \ @@ -98,6 +102,11 @@ static struct environment environment = { .flag_scheme = FLAG_NONE, };
+/* Is AES encryption used? */ +static int aes_flag = 0; +static uint8_t aes_key[AES_KEY_LENGTH] = {0}; +static int env_aes_cbc_crypt(char *data, const int enc); + static int HaveRedundEnv = 0;
static unsigned char active_flag = 1; @@ -120,6 +129,10 @@ static inline ulong getenvsize (void)
if (HaveRedundEnv) rc -= sizeof (char); + + if (aes_flag) + rc &= ~(AES_KEY_LENGTH - 1); + return rc; }
@@ -191,6 +204,36 @@ char *fw_getdefenv(char *name) return NULL; }
+static int parse_aes_key(char *key) +{ + char tmp[5] = { '0', 'x', 0, 0, 0 }; + unsigned long ul; + int i; + + if (strnlen(key, 64) != 32) { + fprintf (stderr, "## Error: " + "`-a' option requires 16-byte AES key\n"); + return -1; + } + + for (i = 0; i < 16; i++) { + tmp[2] = key[0]; + tmp[3] = key[1]; + errno = 0; + ul = strtoul(tmp, NULL, 16); + if (errno) { + fprintf (stderr, "## Error: " + "`-a' option requires valid AES key\n"); + return -1; + } + aes_key[i] = ul & 0xff; + key += 2; + } + aes_flag = 1; + + return 0; +} + /* * Print the current definition of one, or more, or all * environment variables @@ -201,6 +244,19 @@ int fw_printenv (int argc, char *argv[]) int i, n_flag; int rc = 0;
+ if (argc >= 2 && strcmp (argv[1], "-a") == 0) { + if (argc < 3) { + fprintf (stderr, "## Error: " + "`-a' option requires AES key\n"); + return -1; + } + rc = parse_aes_key(argv[2]); + if (rc) + return rc; + argv += 2; + argc -= 2; + } + if (fw_env_open()) return -1;
@@ -266,6 +322,16 @@ int fw_printenv (int argc, char *argv[])
int fw_env_close(void) { + int ret; + if (aes_flag) { + ret = env_aes_cbc_crypt(environment.data, 1); + if (ret) { + fprintf(stderr, + "Error: can't encrypt env for flash\n"); + return ret; + } + } + /* * Update CRC */ @@ -413,7 +479,7 @@ int fw_env_write(char *name, char *value) */ int fw_setenv(int argc, char *argv[]) { - int i; + int i, rc; size_t len; char *name; char *value = NULL; @@ -423,6 +489,24 @@ int fw_setenv(int argc, char *argv[]) return -1; }
+ if (strcmp (argv[1], "-a") == 0) { + if (argc < 3) { + fprintf (stderr, "## Error: " + "`-a' option requires AES key\n"); + return -1; + } + rc = parse_aes_key(argv[2]); + if (rc) + return rc; + argv += 2; + argc -= 2; + } + + if (argc < 2) { + errno = EINVAL; + return -1; + } + if (fw_env_open()) { fprintf(stderr, "Error: environment not initialized\n"); return -1; @@ -900,6 +984,28 @@ static int flash_flag_obsolete (int dev, int fd, off_t offset) return rc; }
+/* Encrypt or decrypt the environment before writing or reading it. */ +static int env_aes_cbc_crypt(char *payload, const int enc) +{ + uint8_t *data = (uint8_t *)payload; + const int len = getenvsize(); + uint8_t key_exp[AES_EXPAND_KEY_LENGTH]; + uint32_t aes_blocks; + + /* First we expand the key. */ + aes_expand_key(aes_key, key_exp); + + /* Calculate the number of AES blocks to encrypt. */ + aes_blocks = DIV_ROUND_UP(len, AES_KEY_LENGTH); + + if (enc) + aes_cbc_encrypt_blocks(key_exp, data, data, aes_blocks); + else + aes_cbc_decrypt_blocks(key_exp, data, data, aes_blocks); + + return 0; +} + static int flash_write (int fd_current, int fd_target, int dev_target) { int rc; @@ -923,6 +1029,7 @@ static int flash_write (int fd_current, int fd_target, int dev_target) fprintf(stderr, "Writing new environment at 0x%lx on %s\n", DEVOFFSET (dev_target), DEVNAME (dev_target)); #endif + rc = flash_write_buf(dev_target, fd_target, environment.image, CUR_ENVSIZE, DEVOFFSET(dev_target), DEVTYPE(dev_target)); @@ -981,8 +1088,10 @@ static int flash_read (int fd)
rc = flash_read_buf(dev_current, fd, environment.image, CUR_ENVSIZE, DEVOFFSET (dev_current), mtdinfo.type); + if (rc != CUR_ENVSIZE) + return -1;
- return (rc != CUR_ENVSIZE) ? -1 : 0; + return 0; }
static int flash_io (int mode) @@ -1075,6 +1184,8 @@ int fw_env_open(void) unsigned char flag1; void *addr1;
+ int ret; + struct env_image_single *single; struct env_image_redundant *redundant;
@@ -1109,6 +1220,13 @@ int fw_env_open(void) return -1;
crc0 = crc32 (0, (uint8_t *) environment.data, ENV_SIZE); + + if (aes_flag) { + ret = env_aes_cbc_crypt(environment.data, 0); + if (ret) + return ret; + } + crc0_ok = (crc0 == *environment.crc); if (!HaveRedundEnv) { if (!crc0_ok) { @@ -1159,6 +1277,13 @@ int fw_env_open(void) }
crc1 = crc32 (0, (uint8_t *) redundant->data, ENV_SIZE); + + if (aes_flag) { + ret = env_aes_cbc_crypt(redundant->data, 0); + if (ret) + return ret; + } + crc1_ok = (crc1 == redundant->crc); flag1 = redundant->flags;
diff --git a/tools/env/fw_env_main.c b/tools/env/fw_env_main.c index 2b85d78..ce50d58 100644 --- a/tools/env/fw_env_main.c +++ b/tools/env/fw_env_main.c @@ -9,18 +9,22 @@ * Command line user interface to firmware (=U-Boot) environment. * * Implements: - * fw_printenv [[ -n name ] | [ name ... ]] + * fw_printenv [ -a key ] [[ -n name ] | [ name ... ]] * - prints the value of a single environment variable * "name", the ``name=value'' pairs of one or more * environment variables "name", or the whole * environment if no names are specified. - * fw_setenv name [ value ... ] + * fw_setenv [ -a key ] name [ value ... ] * - If a name without any values is given, the variable * with this name is deleted from the environment; * otherwise, all "value" arguments are concatenated, * separated by single blank characters, and the * resulting string is assigned to the environment * variable "name" + * + * If '-a key' is specified, the env block is encrypted with AES 128 CBC. + * The 'key' argument is in the format of 32 hexadecimal numbers (16 bytes + * of AES key), eg. '-a aabbccddeeff00112233445566778899'. */
#include <fcntl.h> @@ -46,8 +50,8 @@ void usage(void)
fprintf(stderr, "fw_printenv/fw_setenv, " "a command line interface to U-Boot environment\n\n" - "usage:\tfw_printenv [-n] [variable name]\n" - "\tfw_setenv [variable name] [variable value]\n" + "usage:\tfw_printenv [-a key] [-n] [variable name]\n" + "\tfw_setenv [-a key] [variable name] [variable value]\n" "\tfw_setenv -s [ file ]\n" "\tfw_setenv -s - < [ file ]\n\n" "The file passed as argument contains only pairs " @@ -94,9 +98,12 @@ int main(int argc, char *argv[]) cmdname = p + 1; }
- while ((c = getopt_long (argc, argv, "ns:h", + while ((c = getopt_long (argc, argv, "a:ns:h", long_options, NULL)) != EOF) { switch (c) { + case 'a': + /* AES key, handled later */ + break; case 'n': /* handled in fw_printenv */ break;

Dear Marek Vasut,
In message 1391658352-24754-3-git-send-email-marex@denx.de you wrote:
Implement support for encrypting/decrypting the environment block into the tools/env/fw_* tools. The cipher used is AES 128 CBC and the implementation depends solely on components internal to U-Boot.
...
+#ifdef USE_HOSTCC +/* Define compat stuff for use in fw_* tools. */ +typedef unsigned char u8; +typedef unsigned int u32; +#define debug(...) do {} while(0)
If we need this for the host environment, then you should provide a useful implementation (output to STDERR).
Also, this is causing checkpatch warnings: space required before the open parenthesis '('
--- a/tools/env/fw_env.c +++ b/tools/env/fw_env.c
...
+#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
Checkpatch says: space required after that ',' (ctx:VxV)
+static int aes_flag = 0;
ERROR: do not initialise statics to 0 or NULL
fprintf (stderr, "## Error: "
"`-a' option requires valid AES key\n");
WARNING: space prohibited between function name and open parenthesis '('
More checkpatch issues suppressed. Please fix all of these!
Best regards,
Wolfgang Denk

On Thursday, February 06, 2014 at 01:16:31 PM, Wolfgang Denk wrote:
[...]
All input considered, thanks! I have but a quick question -- why does the fw_* tools source look _so_ bad ? Don't you think it needs quite some cleanup ? What do you think please?
Best regards, Marek Vasut

Dear Marek,
In message 201402062041.23537.marex@denx.de you wrote:
[...]
All input considered, thanks! I have but a quick question -- why does the fw_* tools source look _so_ bad ? ...
Because it was written more than a decade ago, when rules were not as strict yet, and personal preferences took hold?
... Don't you think it needs quite some cleanup ? What
do you think please?
Cleanup patches are always welcome...
Best regards,
Wolfgang Denk
participants (2)
-
Marek Vasut
-
Wolfgang Denk