[U-Boot] [PATCH 2/3] env: Implement support for encrypting environment

Marek Vasut marex at denx.de
Thu Feb 6 04:45:51 CET 2014


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 at 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;
-- 
1.8.5.3



More information about the U-Boot mailing list