env: Implement support for encrypting environment
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>
This commit is contained in:
parent
7ce1526ed2
commit
a4223b746d
|
@ -140,6 +140,52 @@ int set_default_vars(int nvars, char * const vars[])
|
||||||
H_NOCLEAR | H_INTERACTIVE, nvars, 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.
|
* Check if CRC is valid and (if yes) import the environment.
|
||||||
* Note that "buf" may or may not be aligned.
|
* 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)
|
int env_import(const char *buf, int check)
|
||||||
{
|
{
|
||||||
env_t *ep = (env_t *)buf;
|
env_t *ep = (env_t *)buf;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (check) {
|
if (check) {
|
||||||
uint32_t crc;
|
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,
|
if (himport_r(&env_htab, (char *)ep->data, ENV_SIZE, '\0', 0,
|
||||||
0, NULL)) {
|
0, NULL)) {
|
||||||
gd->flags |= GD_FLG_ENV_READY;
|
gd->flags |= GD_FLG_ENV_READY;
|
||||||
|
@ -177,6 +232,7 @@ int env_export(env_t *env_out)
|
||||||
{
|
{
|
||||||
char *res;
|
char *res;
|
||||||
ssize_t len;
|
ssize_t len;
|
||||||
|
int ret;
|
||||||
|
|
||||||
res = (char *)env_out->data;
|
res = (char *)env_out->data;
|
||||||
len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
|
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);
|
error("Cannot export environment: errno = %d\n", errno);
|
||||||
return 1;
|
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);
|
env_out->crc = crc32(0, env_out->data, ENV_SIZE);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -146,7 +146,12 @@ extern unsigned long nand_env_oob_offset;
|
||||||
extern char *env_name_spec;
|
extern char *env_name_spec;
|
||||||
#endif
|
#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)
|
#define ENV_SIZE (CONFIG_ENV_SIZE - ENV_HEADER_SIZE)
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct environment_s {
|
typedef struct environment_s {
|
||||||
uint32_t crc; /* CRC32 over data bytes */
|
uint32_t crc; /* CRC32 over data bytes */
|
||||||
|
@ -154,7 +159,12 @@ typedef struct environment_s {
|
||||||
unsigned char flags; /* active/obsolete flags */
|
unsigned char flags; /* active/obsolete flags */
|
||||||
#endif
|
#endif
|
||||||
unsigned char data[ENV_SIZE]; /* Environment data */
|
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
|
#ifdef ENV_IS_EMBEDDED
|
||||||
extern env_t environment;
|
extern env_t environment;
|
||||||
|
|
Loading…
Reference in New Issue