Merge branch 'next'
This commit is contained in:
commit
0f507779ca
1
README
1
README
@ -912,6 +912,7 @@ The following options need to be configured:
|
||||
The default command configuration includes all commands
|
||||
except those marked below with a "*".
|
||||
|
||||
CONFIG_CMD_AES AES 128 CBC encrypt/decrypt
|
||||
CONFIG_CMD_ASKENV * ask for env variable
|
||||
CONFIG_CMD_BDI bdinfo
|
||||
CONFIG_CMD_BEDBUG * Include BedBug Debugger
|
||||
|
@ -19,74 +19,6 @@ enum security_op {
|
||||
SECURITY_ENCRYPT = 1 << 1, /* Encrypt the data */
|
||||
};
|
||||
|
||||
static void debug_print_vector(char *name, u32 num_bytes, u8 *data)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
debug("%s [%d] @0x%08x", name, num_bytes, (u32)data);
|
||||
for (i = 0; i < num_bytes; i++) {
|
||||
if (i % 16 == 0)
|
||||
debug(" = ");
|
||||
debug("%02x", data[i]);
|
||||
if ((i+1) % 16 != 0)
|
||||
debug(" ");
|
||||
}
|
||||
debug("\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply chain data to the destination using EOR
|
||||
*
|
||||
* Each array is of length AES_AES_KEY_LENGTH.
|
||||
*
|
||||
* \param cbc_chain_data Chain data
|
||||
* \param src Source data
|
||||
* \param dst Destination data, which is modified here
|
||||
*/
|
||||
static void apply_cbc_chain_data(u8 *cbc_chain_data, u8 *src, u8 *dst)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
*dst++ = *src++ ^ *cbc_chain_data++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypt some data with AES.
|
||||
*
|
||||
* \param key_schedule Expanded key to use
|
||||
* \param src Source data to encrypt
|
||||
* \param dst Destination buffer
|
||||
* \param num_aes_blocks Number of AES blocks to encrypt
|
||||
*/
|
||||
static void encrypt_object(u8 *key_schedule, u8 *src, u8 *dst,
|
||||
u32 num_aes_blocks)
|
||||
{
|
||||
u8 tmp_data[AES_KEY_LENGTH];
|
||||
u8 *cbc_chain_data;
|
||||
u32 i;
|
||||
|
||||
cbc_chain_data = zero_key; /* Convenient array of 0's for IV */
|
||||
|
||||
for (i = 0; i < num_aes_blocks; i++) {
|
||||
debug("encrypt_object: block %d of %d\n", i, num_aes_blocks);
|
||||
debug_print_vector("AES Src", AES_KEY_LENGTH, src);
|
||||
|
||||
/* Apply the chain data */
|
||||
apply_cbc_chain_data(cbc_chain_data, src, tmp_data);
|
||||
debug_print_vector("AES Xor", AES_KEY_LENGTH, tmp_data);
|
||||
|
||||
/* encrypt the AES block */
|
||||
aes_encrypt(tmp_data, key_schedule, dst);
|
||||
debug_print_vector("AES Dst", AES_KEY_LENGTH, dst);
|
||||
|
||||
/* Update pointers for next loop. */
|
||||
cbc_chain_data = dst;
|
||||
src += AES_KEY_LENGTH;
|
||||
dst += AES_KEY_LENGTH;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shift a vector left by one bit
|
||||
*
|
||||
@ -129,7 +61,7 @@ static void sign_object(u8 *key, u8 *key_schedule, u8 *src, u8 *dst,
|
||||
for (i = 0; i < AES_KEY_LENGTH; i++)
|
||||
tmp_data[i] = 0;
|
||||
|
||||
encrypt_object(key_schedule, tmp_data, left, 1);
|
||||
aes_cbc_encrypt_blocks(key_schedule, tmp_data, left, 1);
|
||||
debug_print_vector("AES(key, nonce)", AES_KEY_LENGTH, left);
|
||||
|
||||
left_shift_vector(left, k1, sizeof(left));
|
||||
@ -193,7 +125,7 @@ static int encrypt_and_sign(u8 *key, enum security_op oper, u8 *src,
|
||||
if (oper & SECURITY_ENCRYPT) {
|
||||
/* Perform this in place, resulting in src being encrypted. */
|
||||
debug("encrypt_and_sign: begin encryption\n");
|
||||
encrypt_object(key_schedule, src, src, num_aes_blocks);
|
||||
aes_cbc_encrypt_blocks(key_schedule, src, src, num_aes_blocks);
|
||||
debug("encrypt_and_sign: end encryption\n");
|
||||
}
|
||||
|
||||
|
@ -7,4 +7,4 @@
|
||||
|
||||
PLATFORM_RELFLAGS += -fPIC
|
||||
|
||||
PLATFORM_CPPFLAGS += -DCONFIG_LEON
|
||||
PLATFORM_CPPFLAGS += -DCONFIG_LEON -DCONFIG_LEON2
|
||||
|
@ -7,4 +7,4 @@
|
||||
|
||||
PLATFORM_RELFLAGS += -fPIC
|
||||
|
||||
PLATFORM_CPPFLAGS += -DCONFIG_LEON
|
||||
PLATFORM_CPPFLAGS += -DCONFIG_LEON -DCONFIG_LEON3
|
||||
|
@ -48,6 +48,7 @@ obj-$(CONFIG_ENV_IS_IN_UBI) += env_ubi.o
|
||||
obj-$(CONFIG_ENV_IS_NOWHERE) += env_nowhere.o
|
||||
|
||||
# command
|
||||
obj-$(CONFIG_CMD_AES) += cmd_aes.o
|
||||
obj-$(CONFIG_CMD_AMBAPP) += cmd_ambapp.o
|
||||
obj-$(CONFIG_SOURCE) += cmd_source.o
|
||||
obj-$(CONFIG_CMD_SOURCE) += cmd_source.o
|
||||
|
89
common/cmd_aes.c
Normal file
89
common/cmd_aes.c
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Marek Vasut <marex@denx.de>
|
||||
*
|
||||
* Command for en/de-crypting block of memory with AES-128-CBC cipher.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <environment.h>
|
||||
#include <aes.h>
|
||||
#include <malloc.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <linux/compiler.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
/**
|
||||
* do_aes() - Handle the "aes" command-line command
|
||||
* @cmdtp: Command data struct pointer
|
||||
* @flag: Command flag
|
||||
* @argc: Command-line argument count
|
||||
* @argv: Array of command-line arguments
|
||||
*
|
||||
* Returns zero on success, CMD_RET_USAGE in case of misuse and negative
|
||||
* on error.
|
||||
*/
|
||||
static int do_aes(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
|
||||
{
|
||||
uint32_t key_addr, src_addr, dst_addr, len;
|
||||
uint8_t *key_ptr, *src_ptr, *dst_ptr;
|
||||
uint8_t key_exp[AES_EXPAND_KEY_LENGTH];
|
||||
uint32_t aes_blocks;
|
||||
int enc;
|
||||
|
||||
if (argc != 6)
|
||||
return CMD_RET_USAGE;
|
||||
|
||||
if (!strncmp(argv[1], "enc", 3))
|
||||
enc = 1;
|
||||
else if (!strncmp(argv[1], "dec", 3))
|
||||
enc = 0;
|
||||
else
|
||||
return CMD_RET_USAGE;
|
||||
|
||||
key_addr = simple_strtoul(argv[2], NULL, 16);
|
||||
src_addr = simple_strtoul(argv[3], NULL, 16);
|
||||
dst_addr = simple_strtoul(argv[4], NULL, 16);
|
||||
len = simple_strtoul(argv[5], NULL, 16);
|
||||
|
||||
key_ptr = (uint8_t *)key_addr;
|
||||
src_ptr = (uint8_t *)src_addr;
|
||||
dst_ptr = (uint8_t *)dst_addr;
|
||||
|
||||
/* First we expand the key. */
|
||||
aes_expand_key(key_ptr, 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, src_ptr, dst_ptr, aes_blocks);
|
||||
else
|
||||
aes_cbc_decrypt_blocks(key_exp, src_ptr, dst_ptr, aes_blocks);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***************************************************/
|
||||
#ifdef CONFIG_SYS_LONGHELP
|
||||
static char aes_help_text[] =
|
||||
"enc key src dst len - Encrypt block of data $len bytes long\n"
|
||||
" at address $src using a key at address\n"
|
||||
" $key and store the result at address\n"
|
||||
" $dst. The $len size must be multiple of\n"
|
||||
" 16 bytes and $key must be 16 bytes long.\n"
|
||||
"aes dec key src dst len - Decrypt block of data $len bytes long\n"
|
||||
" at address $src using a key at address\n"
|
||||
" $key and store the result at address\n"
|
||||
" $dst. The $len size must be multiple of\n"
|
||||
" 16 bytes and $key must be 16 bytes long.";
|
||||
#endif
|
||||
|
||||
U_BOOT_CMD(
|
||||
aes, 6, 1, do_aes,
|
||||
"AES 128 CBC encryption",
|
||||
aes_help_text
|
||||
);
|
@ -570,7 +570,7 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
ft_board_setup(working_fdt, gd->bd);
|
||||
#endif
|
||||
/* Create a chosen node */
|
||||
else if (argv[1][0] == 'c') {
|
||||
else if (strncmp(argv[1], "cho", 3) == 0) {
|
||||
unsigned long initrd_start = 0, initrd_end = 0;
|
||||
|
||||
if ((argc != 2) && (argc != 4))
|
||||
@ -583,6 +583,41 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
|
||||
fdt_chosen(working_fdt, 1);
|
||||
fdt_initrd(working_fdt, initrd_start, initrd_end, 1);
|
||||
|
||||
#if defined(CONFIG_FIT_SIGNATURE)
|
||||
} else if (strncmp(argv[1], "che", 3) == 0) {
|
||||
int cfg_noffset;
|
||||
int ret;
|
||||
unsigned long addr;
|
||||
struct fdt_header *blob;
|
||||
|
||||
if (!working_fdt)
|
||||
return CMD_RET_FAILURE;
|
||||
|
||||
if (argc > 2) {
|
||||
addr = simple_strtoul(argv[2], NULL, 16);
|
||||
blob = map_sysmem(addr, 0);
|
||||
} else {
|
||||
blob = (struct fdt_header *)gd->fdt_blob;
|
||||
}
|
||||
if (!fdt_valid(&blob))
|
||||
return 1;
|
||||
|
||||
gd->fdt_blob = blob;
|
||||
cfg_noffset = fit_conf_get_node(working_fdt, NULL);
|
||||
if (!cfg_noffset) {
|
||||
printf("Could not find configuration node: %s\n",
|
||||
fdt_strerror(cfg_noffset));
|
||||
return CMD_RET_FAILURE;
|
||||
}
|
||||
|
||||
ret = fit_config_verify(working_fdt, cfg_noffset);
|
||||
if (ret == 1)
|
||||
return CMD_RET_SUCCESS;
|
||||
else
|
||||
return CMD_RET_FAILURE;
|
||||
#endif
|
||||
|
||||
}
|
||||
/* resize the fdt */
|
||||
else if (strncmp(argv[1], "re", 2) == 0) {
|
||||
@ -992,6 +1027,11 @@ static char fdt_help_text[] =
|
||||
"fdt rsvmem delete <index> - Delete a mem reserves\n"
|
||||
"fdt chosen [<start> <end>] - Add/update the /chosen branch in the tree\n"
|
||||
" <start>/<end> - initrd start/end addr\n"
|
||||
#if defined(CONFIG_FIT_SIGNATURE)
|
||||
"fdt checksign [<addr>] - check FIT signature\n"
|
||||
" <start> - addr of key blob\n"
|
||||
" default gd->fdt_blob\n"
|
||||
#endif
|
||||
"NOTE: Dereference aliases by omiting the leading '/', "
|
||||
"e.g. fdt print ethernet0.";
|
||||
#endif
|
||||
|
@ -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;
|
||||
@ -172,6 +227,30 @@ 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;
|
||||
int ret;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
void env_relocate(void)
|
||||
{
|
||||
#if defined(CONFIG_NEEDS_MANUAL_RELOC)
|
||||
|
@ -56,17 +56,12 @@ void env_relocate_spec(void)
|
||||
|
||||
int saveenv(void)
|
||||
{
|
||||
env_t env_new;
|
||||
ssize_t len;
|
||||
char *res;
|
||||
env_t env_new;
|
||||
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;
|
||||
}
|
||||
env_new.crc = crc32(0, env_new.data, ENV_SIZE);
|
||||
ret = env_export(&env_new);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return write_dataflash(CONFIG_ENV_ADDR,
|
||||
(unsigned long)&env_new,
|
||||
|
@ -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) {
|
||||
|
@ -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",
|
||||
|
@ -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))
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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",
|
||||
|
116
common/hash.c
116
common/hash.c
@ -12,6 +12,7 @@
|
||||
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <malloc.h>
|
||||
#include <hw_sha.h>
|
||||
#include <hash.h>
|
||||
#include <sha1.h>
|
||||
@ -19,6 +20,88 @@
|
||||
#include <asm/io.h>
|
||||
#include <asm/errno.h>
|
||||
|
||||
#ifdef CONFIG_CMD_SHA1SUM
|
||||
static int hash_init_sha1(struct hash_algo *algo, void **ctxp)
|
||||
{
|
||||
sha1_context *ctx = malloc(sizeof(sha1_context));
|
||||
sha1_starts(ctx);
|
||||
*ctxp = ctx;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hash_update_sha1(struct hash_algo *algo, void *ctx, const void *buf,
|
||||
unsigned int size, int is_last)
|
||||
{
|
||||
sha1_update((sha1_context *)ctx, buf, size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hash_finish_sha1(struct hash_algo *algo, void *ctx, void *dest_buf,
|
||||
int size)
|
||||
{
|
||||
if (size < algo->digest_size)
|
||||
return -1;
|
||||
|
||||
sha1_finish((sha1_context *)ctx, dest_buf);
|
||||
free(ctx);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SHA256
|
||||
static int hash_init_sha256(struct hash_algo *algo, void **ctxp)
|
||||
{
|
||||
sha256_context *ctx = malloc(sizeof(sha256_context));
|
||||
sha256_starts(ctx);
|
||||
*ctxp = ctx;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hash_update_sha256(struct hash_algo *algo, void *ctx,
|
||||
const void *buf, unsigned int size, int is_last)
|
||||
{
|
||||
sha256_update((sha256_context *)ctx, buf, size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hash_finish_sha256(struct hash_algo *algo, void *ctx, void
|
||||
*dest_buf, int size)
|
||||
{
|
||||
if (size < algo->digest_size)
|
||||
return -1;
|
||||
|
||||
sha256_finish((sha256_context *)ctx, dest_buf);
|
||||
free(ctx);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int hash_init_crc32(struct hash_algo *algo, void **ctxp)
|
||||
{
|
||||
uint32_t *ctx = malloc(sizeof(uint32_t));
|
||||
*ctx = 0;
|
||||
*ctxp = ctx;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hash_update_crc32(struct hash_algo *algo, void *ctx,
|
||||
const void *buf, unsigned int size, int is_last)
|
||||
{
|
||||
*((uint32_t *)ctx) = crc32(*((uint32_t *)ctx), buf, size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hash_finish_crc32(struct hash_algo *algo, void *ctx, void *dest_buf,
|
||||
int size)
|
||||
{
|
||||
if (size < algo->digest_size)
|
||||
return -1;
|
||||
|
||||
*((uint32_t *)dest_buf) = *((uint32_t *)ctx);
|
||||
free(ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* These are the hash algorithms we support. Chips which support accelerated
|
||||
* crypto could perhaps add named version of these algorithms here. Note that
|
||||
@ -53,6 +136,9 @@ static struct hash_algo hash_algo[] = {
|
||||
SHA1_SUM_LEN,
|
||||
sha1_csum_wd,
|
||||
CHUNKSZ_SHA1,
|
||||
hash_init_sha1,
|
||||
hash_update_sha1,
|
||||
hash_finish_sha1,
|
||||
},
|
||||
#define MULTI_HASH
|
||||
#endif
|
||||
@ -62,6 +148,9 @@ static struct hash_algo hash_algo[] = {
|
||||
SHA256_SUM_LEN,
|
||||
sha256_csum_wd,
|
||||
CHUNKSZ_SHA256,
|
||||
hash_init_sha256,
|
||||
hash_update_sha256,
|
||||
hash_finish_sha256,
|
||||
},
|
||||
#define MULTI_HASH
|
||||
#endif
|
||||
@ -70,6 +159,9 @@ static struct hash_algo hash_algo[] = {
|
||||
4,
|
||||
crc32_wd_buf,
|
||||
CHUNKSZ_CRC32,
|
||||
hash_init_crc32,
|
||||
hash_update_crc32,
|
||||
hash_finish_crc32,
|
||||
},
|
||||
};
|
||||
|
||||
@ -204,16 +296,19 @@ static int parse_verify_sum(struct hash_algo *algo, char *verify_str, u8 *vsum,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct hash_algo *find_hash_algo(const char *name)
|
||||
int hash_lookup_algo(const char *algo_name, struct hash_algo **algop)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(hash_algo); i++) {
|
||||
if (!strcmp(name, hash_algo[i].name))
|
||||
return &hash_algo[i];
|
||||
if (!strcmp(algo_name, hash_algo[i].name)) {
|
||||
*algop = &hash_algo[i];
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
debug("Unknown hash algorithm '%s'\n", algo_name);
|
||||
return -EPROTONOSUPPORT;
|
||||
}
|
||||
|
||||
static void show_hash(struct hash_algo *algo, ulong addr, ulong len,
|
||||
@ -230,12 +325,12 @@ int hash_block(const char *algo_name, const void *data, unsigned int len,
|
||||
uint8_t *output, int *output_size)
|
||||
{
|
||||
struct hash_algo *algo;
|
||||
int ret;
|
||||
|
||||
ret = hash_lookup_algo(algo_name, &algo);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
algo = find_hash_algo(algo_name);
|
||||
if (!algo) {
|
||||
debug("Unknown hash algorithm '%s'\n", algo_name);
|
||||
return -EPROTONOSUPPORT;
|
||||
}
|
||||
if (output_size && *output_size < algo->digest_size) {
|
||||
debug("Output buffer size %d too small (need %d bytes)",
|
||||
*output_size, algo->digest_size);
|
||||
@ -265,8 +360,7 @@ int hash_command(const char *algo_name, int flags, cmd_tbl_t *cmdtp, int flag,
|
||||
u8 vsum[HASH_MAX_DIGEST_SIZE];
|
||||
void *buf;
|
||||
|
||||
algo = find_hash_algo(algo_name);
|
||||
if (!algo) {
|
||||
if (hash_lookup_algo(algo_name, &algo)) {
|
||||
printf("Unknown hash algorithm '%s'\n", algo_name);
|
||||
return CMD_RET_USAGE;
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
#include <bootstage.h>
|
||||
#include <sha1.h>
|
||||
#include <sha256.h>
|
||||
#include <u-boot/crc.h>
|
||||
#include <u-boot/md5.h>
|
||||
|
||||
@ -882,6 +883,10 @@ int calculate_hash(const void *data, int data_len, const char *algo,
|
||||
sha1_csum_wd((unsigned char *)data, data_len,
|
||||
(unsigned char *)value, CHUNKSZ_SHA1);
|
||||
*value_len = 20;
|
||||
} else if (IMAGE_ENABLE_SHA256 && strcmp(algo, "sha256") == 0) {
|
||||
sha256_csum_wd((unsigned char *)data, data_len,
|
||||
(unsigned char *)value, CHUNKSZ_SHA256);
|
||||
*value_len = SHA256_SUM_LEN;
|
||||
} else if (IMAGE_ENABLE_MD5 && strcmp(algo, "md5") == 0) {
|
||||
md5_wd((unsigned char *)data, data_len, value, CHUNKSZ_MD5);
|
||||
*value_len = 16;
|
||||
|
@ -14,16 +14,79 @@ DECLARE_GLOBAL_DATA_PTR;
|
||||
#endif /* !USE_HOSTCC*/
|
||||
#include <image.h>
|
||||
#include <rsa.h>
|
||||
#include <rsa-checksum.h>
|
||||
|
||||
#define IMAGE_MAX_HASHED_NODES 100
|
||||
|
||||
#ifdef USE_HOSTCC
|
||||
void *host_blob;
|
||||
void image_set_host_blob(void *blob)
|
||||
{
|
||||
host_blob = blob;
|
||||
}
|
||||
void *image_get_host_blob(void)
|
||||
{
|
||||
return host_blob;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct checksum_algo checksum_algos[] = {
|
||||
{
|
||||
"sha1",
|
||||
SHA1_SUM_LEN,
|
||||
RSA2048_BYTES,
|
||||
#if IMAGE_ENABLE_SIGN
|
||||
EVP_sha1,
|
||||
#endif
|
||||
sha1_calculate,
|
||||
padding_sha1_rsa2048,
|
||||
},
|
||||
{
|
||||
"sha256",
|
||||
SHA256_SUM_LEN,
|
||||
RSA2048_BYTES,
|
||||
#if IMAGE_ENABLE_SIGN
|
||||
EVP_sha256,
|
||||
#endif
|
||||
sha256_calculate,
|
||||
padding_sha256_rsa2048,
|
||||
},
|
||||
{
|
||||
"sha256",
|
||||
SHA256_SUM_LEN,
|
||||
RSA4096_BYTES,
|
||||
#if IMAGE_ENABLE_SIGN
|
||||
EVP_sha256,
|
||||
#endif
|
||||
sha256_calculate,
|
||||
padding_sha256_rsa4096,
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
struct image_sig_algo image_sig_algos[] = {
|
||||
{
|
||||
"sha1,rsa2048",
|
||||
rsa_sign,
|
||||
rsa_add_verify_data,
|
||||
rsa_verify,
|
||||
&checksum_algos[0],
|
||||
},
|
||||
{
|
||||
"sha256,rsa2048",
|
||||
rsa_sign,
|
||||
rsa_add_verify_data,
|
||||
rsa_verify,
|
||||
&checksum_algos[1],
|
||||
},
|
||||
{
|
||||
"sha256,rsa4096",
|
||||
rsa_sign,
|
||||
rsa_add_verify_data,
|
||||
rsa_verify,
|
||||
&checksum_algos[2],
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
struct image_sig_algo *image_get_sig_algo(const char *name)
|
||||
|
@ -346,7 +346,9 @@ Simple Verified Boot Test
|
||||
|
||||
Please see doc/uImage.FIT/verified-boot.txt for more information
|
||||
|
||||
/home/hs/ids/u-boot/sandbox/tools/mkimage -D -I dts -O dtb -p 2000
|
||||
Build keys
|
||||
do sha1 test
|
||||
Build FIT with signed images
|
||||
Test Verified Boot Run: unsigned signatures:: OK
|
||||
Sign images
|
||||
@ -355,10 +357,26 @@ Build FIT with signed configuration
|
||||
Test Verified Boot Run: unsigned config: OK
|
||||
Sign images
|
||||
Test Verified Boot Run: signed config: OK
|
||||
check signed config on the host
|
||||
OK
|
||||
Test Verified Boot Run: signed config: OK
|
||||
Test Verified Boot Run: signed config with bad hash: OK
|
||||
do sha256 test
|
||||
Build FIT with signed images
|
||||
Test Verified Boot Run: unsigned signatures:: OK
|
||||
Sign images
|
||||
Test Verified Boot Run: signed images: OK
|
||||
Build FIT with signed configuration
|
||||
Test Verified Boot Run: unsigned config: OK
|
||||
Sign images
|
||||
Test Verified Boot Run: signed config: OK
|
||||
check signed config on the host
|
||||
OK
|
||||
Test Verified Boot Run: signed config: OK
|
||||
Test Verified Boot Run: signed config with bad hash: OK
|
||||
|
||||
Test passed
|
||||
|
||||
|
||||
Future Work
|
||||
-----------
|
||||
- Roll-back protection using a TPM is done using the tpm command. This can
|
||||
|
@ -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
|
||||
*
|
||||
@ -25,30 +32,52 @@ enum {
|
||||
};
|
||||
|
||||
/**
|
||||
* aes_expand_key() - Expand the AES key
|
||||
*
|
||||
* Expand a key into a key schedule, which is then used for the other
|
||||
* operations.
|
||||
*
|
||||
* \param key Key, of length AES_KEY_LENGTH bytes
|
||||
* \param expkey Buffer to place expanded key, AES_EXPAND_KEY_LENGTH
|
||||
* @key Key, of length AES_KEY_LENGTH bytes
|
||||
* @expkey Buffer to place expanded key, AES_EXPAND_KEY_LENGTH
|
||||
*/
|
||||
void aes_expand_key(u8 *key, u8 *expkey);
|
||||
|
||||
/**
|
||||
* Encrypt a single block of data
|
||||
* aes_encrypt() - Encrypt single block of data with AES 128
|
||||
*
|
||||
* in Input data
|
||||
* expkey Expanded key to use for encryption (from aes_expand_key())
|
||||
* out Output data
|
||||
* @in Input data
|
||||
* @expkey Expanded key to use for encryption (from aes_expand_key())
|
||||
* @out Output data
|
||||
*/
|
||||
void aes_encrypt(u8 *in, u8 *expkey, u8 *out);
|
||||
|
||||
/**
|
||||
* Decrypt a single block of data
|
||||
* aes_decrypt() - Decrypt single block of data with AES 128
|
||||
*
|
||||
* in Input data
|
||||
* expkey Expanded key to use for decryption (from aes_expand_key())
|
||||
* out Output data
|
||||
* @in Input data
|
||||
* @expkey Expanded key to use for decryption (from aes_expand_key())
|
||||
* @out Output data
|
||||
*/
|
||||
void aes_decrypt(u8 *in, u8 *expkey, u8 *out);
|
||||
|
||||
/**
|
||||
* aes_cbc_encrypt_blocks() - Encrypt multiple blocks of data with AES CBC.
|
||||
*
|
||||
* @key_exp Expanded key to use
|
||||
* @src Source data to encrypt
|
||||
* @dst Destination buffer
|
||||
* @num_aes_blocks Number of AES blocks to encrypt
|
||||
*/
|
||||
void aes_cbc_encrypt_blocks(u8 *key_exp, u8 *src, u8 *dst, u32 num_aes_blocks);
|
||||
|
||||
/**
|
||||
* Decrypt multiple blocks of data with AES CBC.
|
||||
*
|
||||
* @key_exp Expanded key to use
|
||||
* @src Source data to decrypt
|
||||
* @dst Destination buffer
|
||||
* @num_aes_blocks Number of AES blocks to decrypt
|
||||
*/
|
||||
void aes_cbc_decrypt_blocks(u8 *key_exp, u8 *src, u8 *dst, u32 num_aes_blocks);
|
||||
|
||||
#endif /* _AES_REF_H_ */
|
||||
|
@ -19,8 +19,6 @@
|
||||
* (easy to change)
|
||||
*/
|
||||
|
||||
#define CONFIG_LEON3 /* This is an LEON3 CPU */
|
||||
#define CONFIG_LEON 1 /* This is an LEON CPU */
|
||||
#define CONFIG_CPCI_AX2000 1 /* ... on GR-CPCI-AX2000 board */
|
||||
|
||||
#define CONFIG_LEON_RAM_SRAM 1
|
||||
|
@ -20,8 +20,6 @@
|
||||
* (easy to change)
|
||||
*/
|
||||
|
||||
#define CONFIG_LEON3 /* This is an LEON3 CPU */
|
||||
#define CONFIG_LEON 1 /* This is an LEON CPU */
|
||||
/* Altera NIOS Development board, Stratix II board */
|
||||
#define CONFIG_GR_EP2S60 1
|
||||
|
||||
|
@ -18,8 +18,6 @@
|
||||
* (easy to change)
|
||||
*/
|
||||
|
||||
#define CONFIG_LEON3 /* This is an LEON3 CPU */
|
||||
#define CONFIG_LEON 1 /* This is an LEON CPU */
|
||||
#define CONFIG_GRXC3S1500 1 /* ... on GR-XC3S-1500 board */
|
||||
|
||||
/* CPU / AMBA BUS configuration */
|
||||
|
@ -24,8 +24,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#define CONFIG_LEON3 /* This is an LEON3 CPU */
|
||||
#define CONFIG_LEON 1 /* This is an LEON CPU */
|
||||
#define CONFIG_GRSIM 0 /* ... not running on GRSIM */
|
||||
#define CONFIG_TSIM 1 /* ... running on TSIM */
|
||||
|
||||
|
@ -23,8 +23,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#define CONFIG_LEON2 /* This is an LEON2 CPU */
|
||||
#define CONFIG_LEON 1 /* This is an LEON CPU */
|
||||
#define CONFIG_GRSIM 0 /* ... not running on GRSIM */
|
||||
#define CONFIG_TSIM 1 /* ... running on TSIM */
|
||||
|
||||
|
@ -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;
|
||||
@ -201,6 +211,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_ */
|
||||
|
@ -115,4 +115,9 @@ static inline int fdt_status_disabled_by_alias(void *fdt, const char* alias)
|
||||
}
|
||||
|
||||
#endif /* ifdef CONFIG_OF_LIBFDT */
|
||||
|
||||
#ifdef USE_HOSTCC
|
||||
int fdtdec_get_int(const void *blob, int node, const char *prop_name,
|
||||
int default_val);
|
||||
#endif
|
||||
#endif /* ifndef __FDT_SUPPORT_H */
|
||||
|
@ -27,6 +27,42 @@ struct hash_algo {
|
||||
void (*hash_func_ws)(const unsigned char *input, unsigned int ilen,
|
||||
unsigned char *output, unsigned int chunk_sz);
|
||||
int chunk_size; /* Watchdog chunk size */
|
||||
/*
|
||||
* hash_init: Create the context for progressive hashing
|
||||
*
|
||||
* @algo: Pointer to the hash_algo struct
|
||||
* @ctxp: Pointer to the pointer of the context for hashing
|
||||
* @return 0 if ok, -1 on error
|
||||
*/
|
||||
int (*hash_init)(struct hash_algo *algo, void **ctxp);
|
||||
/*
|
||||
* hash_update: Perform hashing on the given buffer
|
||||
*
|
||||
* The context is freed by this function if an error occurs.
|
||||
*
|
||||
* @algo: Pointer to the hash_algo struct
|
||||
* @ctx: Pointer to the context for hashing
|
||||
* @buf: Pointer to the buffer being hashed
|
||||
* @size: Size of the buffer being hashed
|
||||
* @is_last: 1 if this is the last update; 0 otherwise
|
||||
* @return 0 if ok, -1 on error
|
||||
*/
|
||||
int (*hash_update)(struct hash_algo *algo, void *ctx, const void *buf,
|
||||
unsigned int size, int is_last);
|
||||
/*
|
||||
* hash_finish: Write the hash result to the given buffer
|
||||
*
|
||||
* The context is freed by this function.
|
||||
*
|
||||
* @algo: Pointer to the hash_algo struct
|
||||
* @ctx: Pointer to the context for hashing
|
||||
* @dest_buf: Pointer to the buffer for the result
|
||||
* @size: Size of the buffer for the result
|
||||
* @return 0 if ok, -ENOSPC if size of the result buffer is too small
|
||||
* or -1 on other errors
|
||||
*/
|
||||
int (*hash_finish)(struct hash_algo *algo, void *ctx, void *dest_buf,
|
||||
int size);
|
||||
};
|
||||
|
||||
/*
|
||||
@ -77,4 +113,16 @@ int hash_command(const char *algo_name, int flags, cmd_tbl_t *cmdtp, int flag,
|
||||
int hash_block(const char *algo_name, const void *data, unsigned int len,
|
||||
uint8_t *output, int *output_size);
|
||||
|
||||
/**
|
||||
* hash_lookup_algo() - Look up the hash_algo struct for an algorithm
|
||||
*
|
||||
* The function returns the pointer to the struct or -EPROTONOSUPPORT if the
|
||||
* algorithm is not available.
|
||||
*
|
||||
* @algo_name: Hash algorithm to look up
|
||||
* @algop: Pointer to the hash_algo struct if found
|
||||
*
|
||||
* @return 0 if ok, -EPROTONOSUPPORT for an unknown algorithm.
|
||||
*/
|
||||
int hash_lookup_algo(const char *algo_name, struct hash_algo **algop);
|
||||
#endif
|
||||
|
@ -57,13 +57,18 @@ struct lmb;
|
||||
# ifdef CONFIG_SPL_SHA1_SUPPORT
|
||||
# define IMAGE_ENABLE_SHA1 1
|
||||
# endif
|
||||
# ifdef CONFIG_SPL_SHA256_SUPPORT
|
||||
# define IMAGE_ENABLE_SHA256 1
|
||||
# endif
|
||||
# else
|
||||
# define CONFIG_CRC32 /* FIT images need CRC32 support */
|
||||
# define CONFIG_MD5 /* and MD5 */
|
||||
# define CONFIG_SHA1 /* and SHA1 */
|
||||
# define CONFIG_SHA256 /* and SHA256 */
|
||||
# define IMAGE_ENABLE_CRC32 1
|
||||
# define IMAGE_ENABLE_MD5 1
|
||||
# define IMAGE_ENABLE_SHA1 1
|
||||
# define IMAGE_ENABLE_SHA256 1
|
||||
# endif
|
||||
|
||||
#ifndef IMAGE_ENABLE_CRC32
|
||||
@ -78,6 +83,10 @@ struct lmb;
|
||||
#define IMAGE_ENABLE_SHA1 0
|
||||
#endif
|
||||
|
||||
#ifndef IMAGE_ENABLE_SHA256
|
||||
#define IMAGE_ENABLE_SHA256 0
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_FIT */
|
||||
|
||||
#ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
|
||||
@ -823,7 +832,8 @@ int calculate_hash(const void *data, int data_len, const char *algo,
|
||||
#if defined(CONFIG_FIT_SIGNATURE)
|
||||
# ifdef USE_HOSTCC
|
||||
# define IMAGE_ENABLE_SIGN 1
|
||||
# define IMAGE_ENABLE_VERIFY 0
|
||||
# define IMAGE_ENABLE_VERIFY 1
|
||||
# include <openssl/evp.h>
|
||||
#else
|
||||
# define IMAGE_ENABLE_SIGN 0
|
||||
# define IMAGE_ENABLE_VERIFY 1
|
||||
@ -834,7 +844,9 @@ int calculate_hash(const void *data, int data_len, const char *algo,
|
||||
#endif
|
||||
|
||||
#ifdef USE_HOSTCC
|
||||
# define gd_fdt_blob() NULL
|
||||
void *image_get_host_blob(void);
|
||||
void image_set_host_blob(void *host_blob);
|
||||
# define gd_fdt_blob() image_get_host_blob()
|
||||
#else
|
||||
# define gd_fdt_blob() (gd->fdt_blob)
|
||||
#endif
|
||||
@ -863,6 +875,21 @@ struct image_region {
|
||||
int size;
|
||||
};
|
||||
|
||||
#if IMAGE_ENABLE_VERIFY
|
||||
# include <rsa-checksum.h>
|
||||
#endif
|
||||
struct checksum_algo {
|
||||
const char *name;
|
||||
const int checksum_len;
|
||||
const int pad_len;
|
||||
#if IMAGE_ENABLE_SIGN
|
||||
const EVP_MD *(*calculate_sign)(void);
|
||||
#endif
|
||||
void (*calculate)(const struct image_region region[],
|
||||
int region_count, uint8_t *checksum);
|
||||
const uint8_t *rsa_padding;
|
||||
};
|
||||
|
||||
struct image_sig_algo {
|
||||
const char *name; /* Name of algorithm */
|
||||
|
||||
@ -913,6 +940,9 @@ struct image_sig_algo {
|
||||
int (*verify)(struct image_sign_info *info,
|
||||
const struct image_region region[], int region_count,
|
||||
uint8_t *sig, uint sig_len);
|
||||
|
||||
/* pointer to checksum algorithm */
|
||||
struct checksum_algo *checksum;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -978,7 +1008,11 @@ struct image_region *fit_region_make_list(const void *fit,
|
||||
|
||||
static inline int fit_image_check_target_arch(const void *fdt, int node)
|
||||
{
|
||||
#ifndef USE_HOSTCC
|
||||
return fit_image_check_arch(fdt, node, IH_ARCH_DEFAULT);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CONFIG_FIT_VERBOSE
|
||||
|
24
include/rsa-checksum.h
Normal file
24
include/rsa-checksum.h
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (c) 2013, Andreas Oetken.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef _RSA_CHECKSUM_H
|
||||
#define _RSA_CHECKSUM_H
|
||||
|
||||
#include <errno.h>
|
||||
#include <image.h>
|
||||
#include <sha1.h>
|
||||
#include <sha256.h>
|
||||
|
||||
extern const uint8_t padding_sha256_rsa4096[];
|
||||
extern const uint8_t padding_sha256_rsa2048[];
|
||||
extern const uint8_t padding_sha1_rsa2048[];
|
||||
|
||||
void sha256_calculate(const struct image_region region[], int region_count,
|
||||
uint8_t *checksum);
|
||||
void sha1_calculate(const struct image_region region[], int region_count,
|
||||
uint8_t *checksum);
|
||||
|
||||
#endif
|
@ -15,6 +15,20 @@
|
||||
#include <errno.h>
|
||||
#include <image.h>
|
||||
|
||||
/**
|
||||
* struct rsa_public_key - holder for a public key
|
||||
*
|
||||
* An RSA public key consists of a modulus (typically called N), the inverse
|
||||
* and R^2, where R is 2^(# key bits).
|
||||
*/
|
||||
|
||||
struct rsa_public_key {
|
||||
uint len; /* len of modulus[] in number of uint32_t */
|
||||
uint32_t n0inv; /* -1 / modulus[0] mod 2^32 */
|
||||
uint32_t *modulus; /* modulus as little endian array */
|
||||
uint32_t *rr; /* R^2 as little endian array */
|
||||
};
|
||||
|
||||
#if IMAGE_ENABLE_SIGN
|
||||
/**
|
||||
* sign() - calculate and return signature for given input data
|
||||
@ -89,4 +103,14 @@ static inline int rsa_verify(struct image_sign_info *info,
|
||||
}
|
||||
#endif
|
||||
|
||||
#define RSA2048_BYTES (2048 / 8)
|
||||
#define RSA4096_BYTES (4096 / 8)
|
||||
|
||||
/* This is the minimum/maximum key size we support, in bits */
|
||||
#define RSA_MIN_KEY_BITS 2048
|
||||
#define RSA_MAX_KEY_BITS 4096
|
||||
|
||||
/* This is the maximum signature length that we support, in bits */
|
||||
#define RSA_MAX_SIG_BITS 4096
|
||||
|
||||
#endif
|
||||
|
84
lib/aes.c
84
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 */
|
||||
@ -580,3 +584,83 @@ void aes_decrypt(u8 *in, u8 *expkey, u8 *out)
|
||||
|
||||
memcpy(out, state, sizeof(state));
|
||||
}
|
||||
|
||||
static void debug_print_vector(char *name, u32 num_bytes, u8 *data)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("%s [%d] @0x%08x", name, num_bytes, (u32)data);
|
||||
print_buffer(0, data, 1, num_bytes, 16);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply chain data to the destination using EOR
|
||||
*
|
||||
* Each array is of length AES_KEY_LENGTH.
|
||||
*
|
||||
* @cbc_chain_data Chain data
|
||||
* @src Source data
|
||||
* @dst Destination data, which is modified here
|
||||
*/
|
||||
static void apply_cbc_chain_data(u8 *cbc_chain_data, u8 *src, u8 *dst)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < AES_KEY_LENGTH; i++)
|
||||
*dst++ = *src++ ^ *cbc_chain_data++;
|
||||
}
|
||||
|
||||
void aes_cbc_encrypt_blocks(u8 *key_exp, u8 *src, u8 *dst, u32 num_aes_blocks)
|
||||
{
|
||||
u8 zero_key[AES_KEY_LENGTH] = { 0 };
|
||||
u8 tmp_data[AES_KEY_LENGTH];
|
||||
/* Convenient array of 0's for IV */
|
||||
u8 *cbc_chain_data = zero_key;
|
||||
u32 i;
|
||||
|
||||
for (i = 0; i < num_aes_blocks; i++) {
|
||||
debug("encrypt_object: block %d of %d\n", i, num_aes_blocks);
|
||||
debug_print_vector("AES Src", AES_KEY_LENGTH, src);
|
||||
|
||||
/* Apply the chain data */
|
||||
apply_cbc_chain_data(cbc_chain_data, src, tmp_data);
|
||||
debug_print_vector("AES Xor", AES_KEY_LENGTH, tmp_data);
|
||||
|
||||
/* Encrypt the AES block */
|
||||
aes_encrypt(tmp_data, key_exp, dst);
|
||||
debug_print_vector("AES Dst", AES_KEY_LENGTH, dst);
|
||||
|
||||
/* Update pointers for next loop. */
|
||||
cbc_chain_data = dst;
|
||||
src += AES_KEY_LENGTH;
|
||||
dst += AES_KEY_LENGTH;
|
||||
}
|
||||
}
|
||||
|
||||
void aes_cbc_decrypt_blocks(u8 *key_exp, u8 *src, u8 *dst, u32 num_aes_blocks)
|
||||
{
|
||||
u8 tmp_data[AES_KEY_LENGTH], tmp_block[AES_KEY_LENGTH];
|
||||
/* Convenient array of 0's for IV */
|
||||
u8 cbc_chain_data[AES_KEY_LENGTH] = { 0 };
|
||||
u32 i;
|
||||
|
||||
for (i = 0; i < num_aes_blocks; i++) {
|
||||
debug("encrypt_object: block %d of %d\n", i, num_aes_blocks);
|
||||
debug_print_vector("AES Src", AES_KEY_LENGTH, src);
|
||||
|
||||
memcpy(tmp_block, src, AES_KEY_LENGTH);
|
||||
|
||||
/* Decrypt the AES block */
|
||||
aes_decrypt(src, key_exp, tmp_data);
|
||||
debug_print_vector("AES Xor", AES_KEY_LENGTH, tmp_data);
|
||||
|
||||
/* Apply the chain data */
|
||||
apply_cbc_chain_data(cbc_chain_data, tmp_data, dst);
|
||||
debug_print_vector("AES Dst", AES_KEY_LENGTH, dst);
|
||||
|
||||
/* Update pointers for next loop. */
|
||||
memcpy(cbc_chain_data, tmp_block, AES_KEY_LENGTH);
|
||||
src += AES_KEY_LENGTH;
|
||||
dst += AES_KEY_LENGTH;
|
||||
}
|
||||
}
|
||||
|
20
lib/fdtdec.c
20
lib/fdtdec.c
@ -3,6 +3,7 @@
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef USE_HOSTCC
|
||||
#include <common.h>
|
||||
#include <serial.h>
|
||||
#include <libfdt.h>
|
||||
@ -645,3 +646,22 @@ int fdtdec_read_fmap_entry(const void *blob, int node, const char *name,
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#include "libfdt.h"
|
||||
#include "fdt_support.h"
|
||||
|
||||
int fdtdec_get_int(const void *blob, int node, const char *prop_name,
|
||||
int default_val)
|
||||
{
|
||||
const int *cell;
|
||||
int len;
|
||||
|
||||
cell = fdt_getprop_w((void *)blob, node, prop_name, &len);
|
||||
if (cell && len >= sizeof(int)) {
|
||||
int val = fdt32_to_cpu(cell[0]);
|
||||
|
||||
return val;
|
||||
}
|
||||
return default_val;
|
||||
}
|
||||
#endif
|
||||
|
@ -7,4 +7,4 @@
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
|
||||
obj-$(CONFIG_FIT_SIGNATURE) += rsa-verify.o
|
||||
obj-$(CONFIG_FIT_SIGNATURE) += rsa-verify.o rsa-checksum.o
|
||||
|
163
lib/rsa/rsa-checksum.c
Normal file
163
lib/rsa/rsa-checksum.c
Normal file
@ -0,0 +1,163 @@
|
||||
/*
|
||||
* Copyright (c) 2013, Andreas Oetken.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef USE_HOSTCC
|
||||
#include <common.h>
|
||||
#include <fdtdec.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <asm/errno.h>
|
||||
#include <asm/unaligned.h>
|
||||
#else
|
||||
#include "fdt_host.h"
|
||||
#endif
|
||||
#include <rsa.h>
|
||||
#include <sha1.h>
|
||||
#include <sha256.h>
|
||||
|
||||
/* PKCS 1.5 paddings as described in the RSA PKCS#1 v2.1 standard. */
|
||||
|
||||
const uint8_t padding_sha256_rsa2048[RSA2048_BYTES - SHA256_SUM_LEN] = {
|
||||
0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x30, 0x31, 0x30,
|
||||
0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05,
|
||||
0x00, 0x04, 0x20
|
||||
};
|
||||
|
||||
const uint8_t padding_sha1_rsa2048[RSA2048_BYTES - SHA1_SUM_LEN] = {
|
||||
0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0x00, 0x30, 0x21, 0x30,
|
||||
0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a,
|
||||
0x05, 0x00, 0x04, 0x14
|
||||
};
|
||||
|
||||
const uint8_t padding_sha256_rsa4096[RSA4096_BYTES - SHA256_SUM_LEN] = {
|
||||
0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0x00, 0x30, 0x31, 0x30,
|
||||
0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65,
|
||||
0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20
|
||||
};
|
||||
|
||||
void sha1_calculate(const struct image_region region[], int region_count,
|
||||
uint8_t *checksum)
|
||||
{
|
||||
sha1_context ctx;
|
||||
uint32_t i;
|
||||
i = 0;
|
||||
|
||||
sha1_starts(&ctx);
|
||||
for (i = 0; i < region_count; i++)
|
||||
sha1_update(&ctx, region[i].data, region[i].size);
|
||||
sha1_finish(&ctx, checksum);
|
||||
}
|
||||
|
||||
void sha256_calculate(const struct image_region region[], int region_count,
|
||||
uint8_t *checksum)
|
||||
{
|
||||
sha256_context ctx;
|
||||
uint32_t i;
|
||||
i = 0;
|
||||
|
||||
sha256_starts(&ctx);
|
||||
for (i = 0; i < region_count; i++)
|
||||
sha256_update(&ctx, region[i].data, region[i].size);
|
||||
sha256_finish(&ctx, checksum);
|
||||
}
|
@ -159,8 +159,9 @@ static void rsa_remove(void)
|
||||
EVP_cleanup();
|
||||
}
|
||||
|
||||
static int rsa_sign_with_key(RSA *rsa, const struct image_region region[],
|
||||
int region_count, uint8_t **sigp, uint *sig_size)
|
||||
static int rsa_sign_with_key(RSA *rsa, struct checksum_algo *checksum_algo,
|
||||
const struct image_region region[], int region_count,
|
||||
uint8_t **sigp, uint *sig_size)
|
||||
{
|
||||
EVP_PKEY *key;
|
||||
EVP_MD_CTX *context;
|
||||
@ -192,7 +193,7 @@ static int rsa_sign_with_key(RSA *rsa, const struct image_region region[],
|
||||
goto err_create;
|
||||
}
|
||||
EVP_MD_CTX_init(context);
|
||||
if (!EVP_SignInit(context, EVP_sha1())) {
|
||||
if (!EVP_SignInit(context, checksum_algo->calculate_sign())) {
|
||||
ret = rsa_err("Signer setup failed");
|
||||
goto err_sign;
|
||||
}
|
||||
@ -242,7 +243,8 @@ int rsa_sign(struct image_sign_info *info,
|
||||
ret = rsa_get_priv_key(info->keydir, info->keyname, &rsa);
|
||||
if (ret)
|
||||
goto err_priv;
|
||||
ret = rsa_sign_with_key(rsa, region, region_count, sigp, sig_len);
|
||||
ret = rsa_sign_with_key(rsa, info->algo->checksum, region,
|
||||
region_count, sigp, sig_len);
|
||||
if (ret)
|
||||
goto err_sign;
|
||||
|
||||
|
@ -4,70 +4,27 @@
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef USE_HOSTCC
|
||||
#include <common.h>
|
||||
#include <fdtdec.h>
|
||||
#include <rsa.h>
|
||||
#include <sha1.h>
|
||||
#include <asm/types.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <asm/errno.h>
|
||||
#include <asm/types.h>
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
/**
|
||||
* struct rsa_public_key - holder for a public key
|
||||
*
|
||||
* An RSA public key consists of a modulus (typically called N), the inverse
|
||||
* and R^2, where R is 2^(# key bits).
|
||||
*/
|
||||
struct rsa_public_key {
|
||||
uint len; /* Length of modulus[] in number of uint32_t */
|
||||
uint32_t n0inv; /* -1 / modulus[0] mod 2^32 */
|
||||
uint32_t *modulus; /* modulus as little endian array */
|
||||
uint32_t *rr; /* R^2 as little endian array */
|
||||
};
|
||||
#else
|
||||
#include "fdt_host.h"
|
||||
#include "mkimage.h"
|
||||
#include <fdt_support.h>
|
||||
#endif
|
||||
#include <rsa.h>
|
||||
#include <sha1.h>
|
||||
#include <sha256.h>
|
||||
|
||||
#define UINT64_MULT32(v, multby) (((uint64_t)(v)) * ((uint32_t)(multby)))
|
||||
|
||||
#define RSA2048_BYTES (2048 / 8)
|
||||
|
||||
/* This is the minimum/maximum key size we support, in bits */
|
||||
#define RSA_MIN_KEY_BITS 2048
|
||||
#define RSA_MAX_KEY_BITS 2048
|
||||
|
||||
/* This is the maximum signature length that we support, in bits */
|
||||
#define RSA_MAX_SIG_BITS 2048
|
||||
|
||||
static const uint8_t padding_sha1_rsa2048[RSA2048_BYTES - SHA1_SUM_LEN] = {
|
||||
0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0x00, 0x30, 0x21, 0x30,
|
||||
0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a,
|
||||
0x05, 0x00, 0x04, 0x14
|
||||
};
|
||||
#define get_unaligned_be32(a) fdt32_to_cpu(*(uint32_t *)a)
|
||||
#define put_unaligned_be32(a, b) (*(uint32_t *)(b) = cpu_to_fdt32(a))
|
||||
|
||||
/**
|
||||
* subtract_modulus() - subtract modulus from the given value
|
||||
@ -204,18 +161,18 @@ static int pow_mod(const struct rsa_public_key *key, uint32_t *inout)
|
||||
/* Convert to bigendian byte array */
|
||||
for (i = key->len - 1, ptr = inout; (int)i >= 0; i--, ptr++)
|
||||
put_unaligned_be32(result[i], ptr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rsa_verify_key(const struct rsa_public_key *key, const uint8_t *sig,
|
||||
const uint32_t sig_len, const uint8_t *hash)
|
||||
const uint32_t sig_len, const uint8_t *hash,
|
||||
struct checksum_algo *algo)
|
||||
{
|
||||
const uint8_t *padding;
|
||||
int pad_len;
|
||||
int ret;
|
||||
|
||||
if (!key || !sig || !hash)
|
||||
if (!key || !sig || !hash || !algo)
|
||||
return -EIO;
|
||||
|
||||
if (sig_len != (key->len * sizeof(uint32_t))) {
|
||||
@ -223,6 +180,8 @@ static int rsa_verify_key(const struct rsa_public_key *key, const uint8_t *sig,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
debug("Checksum algorithm: %s", algo->name);
|
||||
|
||||
/* Sanity check for stack size */
|
||||
if (sig_len > RSA_MAX_SIG_BITS / 8) {
|
||||
debug("Signature length %u exceeds maximum %d\n", sig_len,
|
||||
@ -238,9 +197,8 @@ static int rsa_verify_key(const struct rsa_public_key *key, const uint8_t *sig,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Determine padding to use depending on the signature type. */
|
||||
padding = padding_sha1_rsa2048;
|
||||
pad_len = RSA2048_BYTES - SHA1_SUM_LEN;
|
||||
padding = algo->rsa_padding;
|
||||
pad_len = algo->pad_len - algo->checksum_len;
|
||||
|
||||
/* Check pkcs1.5 padding bytes. */
|
||||
if (memcmp(buf, padding, pad_len)) {
|
||||
@ -309,7 +267,7 @@ static int rsa_verify_with_keynode(struct image_sign_info *info,
|
||||
}
|
||||
|
||||
debug("key length %d\n", key.len);
|
||||
ret = rsa_verify_key(&key, sig, sig_len, hash);
|
||||
ret = rsa_verify_key(&key, sig, sig_len, hash, info->algo->checksum);
|
||||
if (ret) {
|
||||
printf("%s: RSA failed to verify: %d\n", __func__, ret);
|
||||
return ret;
|
||||
@ -323,12 +281,23 @@ int rsa_verify(struct image_sign_info *info,
|
||||
uint8_t *sig, uint sig_len)
|
||||
{
|
||||
const void *blob = info->fdt_blob;
|
||||
uint8_t hash[SHA1_SUM_LEN];
|
||||
/* Reserve memory for maximum checksum-length */
|
||||
uint8_t hash[info->algo->checksum->pad_len];
|
||||
int ndepth, noffset;
|
||||
int sig_node, node;
|
||||
char name[100];
|
||||
sha1_context ctx;
|
||||
int ret, i;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Verify that the checksum-length does not exceed the
|
||||
* rsa-signature-length
|
||||
*/
|
||||
if (info->algo->checksum->checksum_len >
|
||||
info->algo->checksum->pad_len) {
|
||||
debug("%s: invlaid checksum-algorithm %s for %s\n",
|
||||
__func__, info->algo->checksum->name, info->algo->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sig_node = fdt_subnode_offset(blob, 0, FIT_SIG_NODENAME);
|
||||
if (sig_node < 0) {
|
||||
@ -336,10 +305,8 @@ int rsa_verify(struct image_sign_info *info,
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
sha1_starts(&ctx);
|
||||
for (i = 0; i < region_count; i++)
|
||||
sha1_update(&ctx, region[i].data, region[i].size);
|
||||
sha1_finish(&ctx, hash);
|
||||
/* Calculate checksum with checksum-algorithm */
|
||||
info->algo->checksum->calculate(region, region_count, hash);
|
||||
|
||||
/* See if we must use a particular key */
|
||||
if (info->required_keynode != -1) {
|
||||
|
@ -258,14 +258,15 @@ void sha256_csum_wd(const unsigned char *input, unsigned int ilen,
|
||||
{
|
||||
sha256_context ctx;
|
||||
#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
|
||||
unsigned char *end, *curr;
|
||||
const unsigned char *end;
|
||||
unsigned char *curr;
|
||||
int chunk;
|
||||
#endif
|
||||
|
||||
sha256_starts(&ctx);
|
||||
|
||||
#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
|
||||
curr = input;
|
||||
curr = (unsigned char *)input;
|
||||
end = input + ilen;
|
||||
while (curr < end) {
|
||||
chunk = end - curr;
|
||||
|
45
test/vboot/sign-configs-sha256.its
Normal file
45
test/vboot/sign-configs-sha256.its
Normal file
@ -0,0 +1,45 @@
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
description = "Chrome OS kernel image with one or more FDT blobs";
|
||||
#address-cells = <1>;
|
||||
|
||||
images {
|
||||
kernel@1 {
|
||||
data = /incbin/("test-kernel.bin");
|
||||
type = "kernel_noload";
|
||||
arch = "sandbox";
|
||||
os = "linux";
|
||||
compression = "none";
|
||||
load = <0x4>;
|
||||
entry = <0x8>;
|
||||
kernel-version = <1>;
|
||||
hash@1 {
|
||||
algo = "sha256";
|
||||
};
|
||||
};
|
||||
fdt@1 {
|
||||
description = "snow";
|
||||
data = /incbin/("sandbox-kernel.dtb");
|
||||
type = "flat_dt";
|
||||
arch = "sandbox";
|
||||
compression = "none";
|
||||
fdt-version = <1>;
|
||||
hash@1 {
|
||||
algo = "sha256";
|
||||
};
|
||||
};
|
||||
};
|
||||
configurations {
|
||||
default = "conf@1";
|
||||
conf@1 {
|
||||
kernel = "kernel@1";
|
||||
fdt = "fdt@1";
|
||||
signature@1 {
|
||||
algo = "sha256,rsa2048";
|
||||
key-name-hint = "dev";
|
||||
sign-images = "fdt", "kernel";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
42
test/vboot/sign-images-sha256.its
Normal file
42
test/vboot/sign-images-sha256.its
Normal file
@ -0,0 +1,42 @@
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
description = "Chrome OS kernel image with one or more FDT blobs";
|
||||
#address-cells = <1>;
|
||||
|
||||
images {
|
||||
kernel@1 {
|
||||
data = /incbin/("test-kernel.bin");
|
||||
type = "kernel_noload";
|
||||
arch = "sandbox";
|
||||
os = "linux";
|
||||
compression = "none";
|
||||
load = <0x4>;
|
||||
entry = <0x8>;
|
||||
kernel-version = <1>;
|
||||
signature@1 {
|
||||
algo = "sha256,rsa2048";
|
||||
key-name-hint = "dev";
|
||||
};
|
||||
};
|
||||
fdt@1 {
|
||||
description = "snow";
|
||||
data = /incbin/("sandbox-kernel.dtb");
|
||||
type = "flat_dt";
|
||||
arch = "sandbox";
|
||||
compression = "none";
|
||||
fdt-version = <1>;
|
||||
signature@1 {
|
||||
algo = "sha256,rsa2048";
|
||||
key-name-hint = "dev";
|
||||
};
|
||||
};
|
||||
};
|
||||
configurations {
|
||||
default = "conf@1";
|
||||
conf@1 {
|
||||
kernel = "kernel@1";
|
||||
fdt = "fdt@1";
|
||||
};
|
||||
};
|
||||
};
|
@ -47,6 +47,7 @@ O=$(readlink -f ${O})
|
||||
dtc="-I dts -O dtb -p 2000"
|
||||
uboot="${O}/u-boot"
|
||||
mkimage="${O}/tools/mkimage"
|
||||
fit_check_sign="${O}/tools/fit_check_sign"
|
||||
keys="${dir}/dev-keys"
|
||||
echo ${mkimage} -D "${dtc}"
|
||||
|
||||
@ -61,47 +62,76 @@ openssl req -batch -new -x509 -key ${keys}/dev.key -out ${keys}/dev.crt
|
||||
|
||||
pushd ${dir} >/dev/null
|
||||
|
||||
# Compile our device tree files for kernel and U-Boot (CONFIG_OF_CONTROL)
|
||||
dtc -p 0x1000 sandbox-kernel.dts -O dtb -o sandbox-kernel.dtb
|
||||
dtc -p 0x1000 sandbox-u-boot.dts -O dtb -o sandbox-u-boot.dtb
|
||||
function do_test {
|
||||
echo do $sha test
|
||||
# Compile our device tree files for kernel and U-Boot
|
||||
dtc -p 0x1000 sandbox-kernel.dts -O dtb -o sandbox-kernel.dtb
|
||||
dtc -p 0x1000 sandbox-u-boot.dts -O dtb -o sandbox-u-boot.dtb
|
||||
|
||||
# Create a number kernel image with zeroes
|
||||
head -c 5000 /dev/zero >test-kernel.bin
|
||||
# Create a number kernel image with zeroes
|
||||
head -c 5000 /dev/zero >test-kernel.bin
|
||||
|
||||
# Build the FIT, but don't sign anything yet
|
||||
echo Build FIT with signed images
|
||||
${mkimage} -D "${dtc}" -f sign-images.its test.fit >${tmp}
|
||||
# Build the FIT, but don't sign anything yet
|
||||
echo Build FIT with signed images
|
||||
${mkimage} -D "${dtc}" -f sign-images-$sha.its test.fit >${tmp}
|
||||
|
||||
run_uboot "unsigned signatures:" "dev-"
|
||||
run_uboot "unsigned signatures:" "dev-"
|
||||
|
||||
# Sign images with our dev keys
|
||||
echo Sign images
|
||||
${mkimage} -D "${dtc}" -F -k dev-keys -K sandbox-u-boot.dtb -r test.fit >${tmp}
|
||||
# Sign images with our dev keys
|
||||
echo Sign images
|
||||
${mkimage} -D "${dtc}" -F -k dev-keys -K sandbox-u-boot.dtb \
|
||||
-r test.fit >${tmp}
|
||||
|
||||
run_uboot "signed images" "dev+"
|
||||
run_uboot "signed images" "dev+"
|
||||
|
||||
|
||||
# Create a fresh .dtb without the public keys
|
||||
dtc -p 0x1000 sandbox-u-boot.dts -O dtb -o sandbox-u-boot.dtb
|
||||
# Create a fresh .dtb without the public keys
|
||||
dtc -p 0x1000 sandbox-u-boot.dts -O dtb -o sandbox-u-boot.dtb
|
||||
|
||||
echo Build FIT with signed configuration
|
||||
${mkimage} -D "${dtc}" -f sign-configs.its test.fit >${tmp}
|
||||
echo Build FIT with signed configuration
|
||||
${mkimage} -D "${dtc}" -f sign-configs-$sha.its test.fit >${tmp}
|
||||
|
||||
run_uboot "unsigned config" "sha1+ OK"
|
||||
run_uboot "unsigned config" $sha"+ OK"
|
||||
|
||||
# Sign images with our dev keys
|
||||
echo Sign images
|
||||
${mkimage} -D "${dtc}" -F -k dev-keys -K sandbox-u-boot.dtb -r test.fit >${tmp}
|
||||
# Sign images with our dev keys
|
||||
echo Sign images
|
||||
${mkimage} -D "${dtc}" -F -k dev-keys -K sandbox-u-boot.dtb \
|
||||
-r test.fit >${tmp}
|
||||
|
||||
run_uboot "signed config" "dev+"
|
||||
run_uboot "signed config" "dev+"
|
||||
|
||||
# Increment the first byte of the signature, which should cause failure
|
||||
sig=$(fdtget -t bx test.fit /configurations/conf@1/signature@1 value)
|
||||
newbyte=$(printf %x $((0x${sig:0:2} + 1)))
|
||||
sig="${newbyte} ${sig:2}"
|
||||
fdtput -t bx test.fit /configurations/conf@1/signature@1 value ${sig}
|
||||
echo check signed config on the host
|
||||
if ! ${fit_check_sign} -f test.fit -k sandbox-u-boot.dtb >${tmp}; then
|
||||
echo
|
||||
echo "Verified boot key check on host failed, output follows:"
|
||||
cat ${tmp}
|
||||
false
|
||||
else
|
||||
if ! grep -q "dev+" ${tmp}; then
|
||||
echo
|
||||
echo "Verified boot key check failed, output follows:"
|
||||
cat ${tmp}
|
||||
false
|
||||
else
|
||||
echo "OK"
|
||||
fi
|
||||
fi
|
||||
|
||||
run_uboot "signed config with bad hash" "Bad Data Hash"
|
||||
run_uboot "signed config" "dev+"
|
||||
|
||||
# Increment the first byte of the signature, which should cause failure
|
||||
sig=$(fdtget -t bx test.fit /configurations/conf@1/signature@1 value)
|
||||
newbyte=$(printf %x $((0x${sig:0:2} + 1)))
|
||||
sig="${newbyte} ${sig:2}"
|
||||
fdtput -t bx test.fit /configurations/conf@1/signature@1 value ${sig}
|
||||
|
||||
run_uboot "signed config with bad hash" "Bad Data Hash"
|
||||
}
|
||||
|
||||
sha=sha1
|
||||
do_test
|
||||
sha=sha256
|
||||
do_test
|
||||
|
||||
popd >/dev/null
|
||||
|
||||
|
2
tools/.gitignore
vendored
2
tools/.gitignore
vendored
@ -1,5 +1,7 @@
|
||||
/bmp_logo
|
||||
/envcrc
|
||||
/fit_check_sign
|
||||
/fit_info
|
||||
/gen_eth_addr
|
||||
/img2srec
|
||||
/kwboot
|
||||
|
@ -40,7 +40,6 @@ CONFIG_BUILD_ENVCRC ?= $(ENVCRC-y)
|
||||
|
||||
# TODO: CONFIG_CMD_LICENSE does not work
|
||||
hostprogs-$(CONFIG_CMD_LICENSE) += bin2header$(SFX)
|
||||
|
||||
hostprogs-$(CONFIG_LCD_LOGO) += bmp_logo$(SFX)
|
||||
hostprogs-$(CONFIG_VIDEO_LOGO) += bmp_logo$(SFX)
|
||||
HOSTCFLAGS_bmp_logo$(SFX).o := -pedantic
|
||||
@ -61,17 +60,22 @@ hostprogs-y += mkenvimage$(SFX)
|
||||
mkenvimage$(SFX)-objs := crc32.o mkenvimage.o os_support.o
|
||||
|
||||
hostprogs-y += dumpimage$(SFX) mkimage$(SFX)
|
||||
ifdef CONFIG_FIT_SIGNATURE
|
||||
hostprogs-y += fit_info$(SFX) fit_check_sign$(SFX)
|
||||
endif
|
||||
|
||||
FIT_SIG_OBJS-$(CONFIG_FIT_SIGNATURE) := image-sig.o
|
||||
# Flattened device tree objects
|
||||
LIBFDT_OBJS := fdt.o fdt_ro.o fdt_rw.o fdt_strerror.o fdt_wip.o
|
||||
RSA_OBJS-$(CONFIG_FIT_SIGNATURE) := rsa-sign.o
|
||||
RSA_OBJS-$(CONFIG_FIT_SIGNATURE) := rsa-sign.o rsa-verify.o rsa-checksum.o
|
||||
|
||||
# common objs for dumpimage and mkimage
|
||||
dumpimage-mkimage-objs := aisimage.o \
|
||||
$(FIT_SIG_OBJS-y) \
|
||||
crc32.o \
|
||||
default_image.o \
|
||||
fdtdec.o \
|
||||
fit_common.o \
|
||||
fit_image.o \
|
||||
image-fit.o \
|
||||
image-host.o \
|
||||
@ -85,12 +89,15 @@ dumpimage-mkimage-objs := aisimage.o \
|
||||
os_support.o \
|
||||
pblimage.o \
|
||||
sha1.o \
|
||||
sha256.o \
|
||||
ublimage.o \
|
||||
$(LIBFDT_OBJS) \
|
||||
$(RSA_OBJS-y)
|
||||
|
||||
dumpimage$(SFX)-objs := $(dumpimage-mkimage-objs) dumpimage.o
|
||||
mkimage$(SFX)-objs := $(dumpimage-mkimage-objs) mkimage.o
|
||||
fit_info$(SFX)-objs := $(dumpimage-mkimage-objs) fit_info.o
|
||||
fit_check_sign$(SFX)-objs := $(dumpimage-mkimage-objs) fit_check_sign.o
|
||||
|
||||
# TODO(sjg@chromium.org): Is this correct on Mac OS?
|
||||
|
||||
@ -98,6 +105,8 @@ mkimage$(SFX)-objs := $(dumpimage-mkimage-objs) mkimage.o
|
||||
ifneq ($(CONFIG_MX23)$(CONFIG_MX28),)
|
||||
HOSTLOADLIBES_dumpimage$(SFX) := -lssl -lcrypto
|
||||
HOSTLOADLIBES_mkimage$(SFX) := -lssl -lcrypto
|
||||
HOSTLOADLIBES_fit_info$(SFX) := -lssl -lcrypto
|
||||
HOSTLOADLIBES_fit_check_sign$(SFX) := -lssl -lcrypto
|
||||
# Add CONFIG_MXS into host CFLAGS, so we can check whether or not register
|
||||
# the mxsimage support within tools/mxsimage.c .
|
||||
HOSTCFLAGS_mxsimage.o += -DCONFIG_MXS
|
||||
@ -106,6 +115,8 @@ endif
|
||||
ifdef CONFIG_FIT_SIGNATURE
|
||||
HOSTLOADLIBES_dumpimage$(SFX) := -lssl -lcrypto
|
||||
HOSTLOADLIBES_mkimage$(SFX) := -lssl -lcrypto
|
||||
HOSTLOADLIBES_fit_info$(SFX) := -lssl -lcrypto
|
||||
HOSTLOADLIBES_fit_check_sign$(SFX) := -lssl -lcrypto
|
||||
|
||||
# This affects include/image.h, but including the board config file
|
||||
# is tricky, so manually define this options here.
|
||||
@ -137,6 +148,7 @@ hostprogs-$(CONFIG_STATIC_RELA) += relocate-rela$(SFX)
|
||||
HOSTCFLAGS_crc32.o := -pedantic
|
||||
HOSTCFLAGS_md5.o := -pedantic
|
||||
HOSTCFLAGS_sha1.o := -pedantic
|
||||
HOSTCFLAGS_sha256.o := -pedantic
|
||||
|
||||
# Don't build by default
|
||||
#hostprogs-$(CONFIG_PPC) += mpc86x_clk$(SFX)
|
||||
|
2
tools/env/Makefile
vendored
2
tools/env/Makefile
vendored
@ -25,7 +25,7 @@ hostprogs-y := fw_printenv_unstripped
|
||||
|
||||
fw_printenv_unstripped-objs := fw_env.o fw_env_main.o \
|
||||
crc32.o ctype.o linux_string.o \
|
||||
env_attr.o env_flags.o
|
||||
env_attr.o env_flags.o aes.o
|
||||
|
||||
quiet_cmd_strip = STRIP $@
|
||||
cmd_strip = $(STRIP) -o $@ $<
|
||||
|
129
tools/env/fw_env.c
vendored
129
tools/env/fw_env.c
vendored
@ -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;
|
||||
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;
|
||||
|
||||
|
17
tools/env/fw_env_main.c
vendored
17
tools/env/fw_env_main.c
vendored
@ -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;
|
||||
|
@ -11,4 +11,6 @@
|
||||
#include "../include/libfdt.h"
|
||||
#include "../include/fdt_support.h"
|
||||
|
||||
int fit_check_sign(const void *working_fdt, const void *key);
|
||||
|
||||
#endif /* __FDT_HOST_H__ */
|
||||
|
1
tools/fdtdec.c
Normal file
1
tools/fdtdec.c
Normal file
@ -0,0 +1 @@
|
||||
#include "../lib/fdtdec.c"
|
85
tools/fit_check_sign.c
Normal file
85
tools/fit_check_sign.c
Normal file
@ -0,0 +1,85 @@
|
||||
/*
|
||||
* (C) Copyright 2014
|
||||
* DENX Software Engineering
|
||||
* Heiko Schocher <hs@denx.de>
|
||||
*
|
||||
* Based on:
|
||||
* (C) Copyright 2008 Semihalf
|
||||
*
|
||||
* (C) Copyright 2000-2004
|
||||
* DENX Software Engineering
|
||||
* Wolfgang Denk, wd@denx.de
|
||||
*
|
||||
* Updated-by: Prafulla Wadaskar <prafulla@marvell.com>
|
||||
* FIT image specific code abstracted from mkimage.c
|
||||
* some functions added to address abstraction
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include "mkimage.h"
|
||||
#include "fit_common.h"
|
||||
#include <image.h>
|
||||
#include <u-boot/crc.h>
|
||||
|
||||
void usage(char *cmdname)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s -f fit file -k key file\n"
|
||||
" -f ==> set fit file which should be checked'\n"
|
||||
" -k ==> set key file which contains the key'\n",
|
||||
cmdname);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int ffd = -1;
|
||||
int kfd = -1;
|
||||
struct stat fsbuf;
|
||||
struct stat ksbuf;
|
||||
void *fit_blob;
|
||||
char *fdtfile = NULL;
|
||||
char *keyfile = NULL;
|
||||
char cmdname[50];
|
||||
int ret;
|
||||
void *key_blob;
|
||||
int c;
|
||||
|
||||
strcpy(cmdname, *argv);
|
||||
while ((c = getopt(argc, argv, "f:k:")) != -1)
|
||||
switch (c) {
|
||||
case 'f':
|
||||
fdtfile = optarg;
|
||||
break;
|
||||
case 'k':
|
||||
keyfile = optarg;
|
||||
break;
|
||||
default:
|
||||
usage(cmdname);
|
||||
break;
|
||||
}
|
||||
|
||||
ffd = mmap_fdt(cmdname, fdtfile, &fit_blob, &fsbuf, 0);
|
||||
if (ffd < 0)
|
||||
return EXIT_FAILURE;
|
||||
kfd = mmap_fdt(cmdname, keyfile, &key_blob, &ksbuf, 0);
|
||||
if (ffd < 0)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
image_set_host_blob(key_blob);
|
||||
ret = fit_check_sign(fit_blob, key_blob);
|
||||
|
||||
if (ret)
|
||||
ret = EXIT_SUCCESS;
|
||||
else
|
||||
ret = EXIT_FAILURE;
|
||||
|
||||
(void) munmap((void *)fit_blob, fsbuf.st_size);
|
||||
(void) munmap((void *)key_blob, ksbuf.st_size);
|
||||
|
||||
close(ffd);
|
||||
close(kfd);
|
||||
exit(ret);
|
||||
}
|
86
tools/fit_common.c
Normal file
86
tools/fit_common.c
Normal file
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* (C) Copyright 2014
|
||||
* DENX Software Engineering
|
||||
* Heiko Schocher <hs@denx.de>
|
||||
*
|
||||
* (C) Copyright 2008 Semihalf
|
||||
*
|
||||
* (C) Copyright 2000-2004
|
||||
* DENX Software Engineering
|
||||
* Wolfgang Denk, wd@denx.de
|
||||
*
|
||||
* Updated-by: Prafulla Wadaskar <prafulla@marvell.com>
|
||||
* FIT image specific code abstracted from mkimage.c
|
||||
* some functions added to address abstraction
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include "imagetool.h"
|
||||
#include "mkimage.h"
|
||||
#include "fit_common.h"
|
||||
#include <image.h>
|
||||
#include <u-boot/crc.h>
|
||||
|
||||
int fit_verify_header(unsigned char *ptr, int image_size,
|
||||
struct image_tool_params *params)
|
||||
{
|
||||
return fdt_check_header(ptr);
|
||||
}
|
||||
|
||||
int fit_check_image_types(uint8_t type)
|
||||
{
|
||||
if (type == IH_TYPE_FLATDT)
|
||||
return EXIT_SUCCESS;
|
||||
else
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
int mmap_fdt(char *cmdname, const char *fname, void **blobp,
|
||||
struct stat *sbuf, int useunlink)
|
||||
{
|
||||
void *ptr;
|
||||
int fd;
|
||||
|
||||
/* Load FIT blob into memory (we need to write hashes/signatures) */
|
||||
fd = open(fname, O_RDWR | O_BINARY);
|
||||
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "%s: Can't open %s: %s\n",
|
||||
cmdname, fname, strerror(errno));
|
||||
if (useunlink)
|
||||
unlink(fname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (fstat(fd, sbuf) < 0) {
|
||||
fprintf(stderr, "%s: Can't stat %s: %s\n",
|
||||
cmdname, fname, strerror(errno));
|
||||
if (useunlink)
|
||||
unlink(fname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
ptr = mmap(0, sbuf->st_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
if ((ptr == MAP_FAILED) || (errno != 0)) {
|
||||
fprintf(stderr, "%s: Can't read %s: %s\n",
|
||||
cmdname, fname, strerror(errno));
|
||||
if (useunlink)
|
||||
unlink(fname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* check if ptr has a valid blob */
|
||||
if (fdt_check_header(ptr)) {
|
||||
fprintf(stderr, "%s: Invalid FIT blob\n", cmdname);
|
||||
if (useunlink)
|
||||
unlink(fname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*blobp = ptr;
|
||||
return fd;
|
||||
}
|
22
tools/fit_common.h
Normal file
22
tools/fit_common.h
Normal file
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* (C) Copyright 2014
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef _FIT_COMMON_H_
|
||||
#define _FIT_COMMON_H_
|
||||
|
||||
#include "imagetool.h"
|
||||
#include "mkimage.h"
|
||||
#include <image.h>
|
||||
|
||||
int fit_verify_header(unsigned char *ptr, int image_size,
|
||||
struct image_tool_params *params);
|
||||
|
||||
int fit_check_image_types(uint8_t type);
|
||||
|
||||
int mmap_fdt(char *cmdname, const char *fname, void **blobp,
|
||||
struct stat *sbuf, int useunlink);
|
||||
|
||||
#endif /* _FIT_COMMON_H_ */
|
@ -15,68 +15,13 @@
|
||||
*/
|
||||
|
||||
#include "imagetool.h"
|
||||
#include "fit_common.h"
|
||||
#include "mkimage.h"
|
||||
#include <image.h>
|
||||
#include <u-boot/crc.h>
|
||||
|
||||
static image_header_t header;
|
||||
|
||||
static int fit_verify_header (unsigned char *ptr, int image_size,
|
||||
struct image_tool_params *params)
|
||||
{
|
||||
return fdt_check_header(ptr);
|
||||
}
|
||||
|
||||
static int fit_check_image_types (uint8_t type)
|
||||
{
|
||||
if (type == IH_TYPE_FLATDT)
|
||||
return EXIT_SUCCESS;
|
||||
else
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
int mmap_fdt(struct image_tool_params *params, const char *fname, void **blobp,
|
||||
struct stat *sbuf)
|
||||
{
|
||||
void *ptr;
|
||||
int fd;
|
||||
|
||||
/* Load FIT blob into memory (we need to write hashes/signatures) */
|
||||
fd = open(fname, O_RDWR | O_BINARY);
|
||||
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "%s: Can't open %s: %s\n",
|
||||
params->cmdname, fname, strerror(errno));
|
||||
unlink(fname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (fstat(fd, sbuf) < 0) {
|
||||
fprintf(stderr, "%s: Can't stat %s: %s\n",
|
||||
params->cmdname, fname, strerror(errno));
|
||||
unlink(fname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ptr = mmap(0, sbuf->st_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
if (ptr == MAP_FAILED) {
|
||||
fprintf(stderr, "%s: Can't read %s: %s\n",
|
||||
params->cmdname, fname, strerror(errno));
|
||||
unlink(fname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* check if ptr has a valid blob */
|
||||
if (fdt_check_header(ptr)) {
|
||||
fprintf(stderr, "%s: Invalid FIT blob\n", params->cmdname);
|
||||
unlink(fname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*blobp = ptr;
|
||||
return fd;
|
||||
}
|
||||
|
||||
/**
|
||||
* fit_handle_file - main FIT file processing function
|
||||
*
|
||||
@ -129,13 +74,14 @@ static int fit_handle_file(struct image_tool_params *params)
|
||||
}
|
||||
|
||||
if (params->keydest) {
|
||||
destfd = mmap_fdt(params, params->keydest, &dest_blob, &sbuf);
|
||||
destfd = mmap_fdt(params->cmdname, params->keydest,
|
||||
&dest_blob, &sbuf, 1);
|
||||
if (destfd < 0)
|
||||
goto err_keydest;
|
||||
destfd_size = sbuf.st_size;
|
||||
}
|
||||
|
||||
tfd = mmap_fdt(params, tmpfile, &ptr, &sbuf);
|
||||
tfd = mmap_fdt(params->cmdname, tmpfile, &ptr, &sbuf, 1);
|
||||
if (tfd < 0)
|
||||
goto err_mmap;
|
||||
|
||||
|
96
tools/fit_info.c
Normal file
96
tools/fit_info.c
Normal file
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* (C) Copyright 2014
|
||||
* DENX Software Engineering
|
||||
* Heiko Schocher <hs@denx.de>
|
||||
*
|
||||
* fit_info: print the offset and the len of a property from
|
||||
* node in a fit file.
|
||||
*
|
||||
* Based on:
|
||||
* (C) Copyright 2008 Semihalf
|
||||
*
|
||||
* (C) Copyright 2000-2004
|
||||
* DENX Software Engineering
|
||||
* Wolfgang Denk, wd@denx.de
|
||||
*
|
||||
* Updated-by: Prafulla Wadaskar <prafulla@marvell.com>
|
||||
* FIT image specific code abstracted from mkimage.c
|
||||
* some functions added to address abstraction
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include "mkimage.h"
|
||||
#include "fit_common.h"
|
||||
#include <image.h>
|
||||
#include <u-boot/crc.h>
|
||||
|
||||
void usage(char *cmdname)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s -f fit file -n node -p property\n"
|
||||
" -f ==> set fit file which is used'\n"
|
||||
" -n ==> set node name'\n"
|
||||
" -p ==> set property name'\n",
|
||||
cmdname);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int ffd = -1;
|
||||
struct stat fsbuf;
|
||||
void *fit_blob;
|
||||
int len;
|
||||
int nodeoffset; /* node offset from libfdt */
|
||||
const void *nodep; /* property node pointer */
|
||||
char *fdtfile = NULL;
|
||||
char *nodename = NULL;
|
||||
char *propertyname = NULL;
|
||||
char cmdname[50];
|
||||
int c;
|
||||
|
||||
strcpy(cmdname, *argv);
|
||||
while ((c = getopt(argc, argv, "f:n:p:")) != -1)
|
||||
switch (c) {
|
||||
case 'f':
|
||||
fdtfile = optarg;
|
||||
break;
|
||||
case 'n':
|
||||
nodename = optarg;
|
||||
break;
|
||||
case 'p':
|
||||
propertyname = optarg;
|
||||
break;
|
||||
default:
|
||||
usage(cmdname);
|
||||
break;
|
||||
}
|
||||
|
||||
ffd = mmap_fdt(cmdname, fdtfile, &fit_blob, &fsbuf, 0);
|
||||
|
||||
if (ffd < 0) {
|
||||
printf("Could not open %s\n", fdtfile);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
nodeoffset = fdt_path_offset(fit_blob, nodename);
|
||||
if (nodeoffset < 0) {
|
||||
printf("%s not found.", nodename);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
nodep = fdt_getprop(fit_blob, nodeoffset, propertyname, &len);
|
||||
if (len == 0) {
|
||||
printf("len == 0 %s\n", propertyname);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
printf("NAME: %s\n", fit_get_name(fit_blob, nodeoffset, NULL));
|
||||
printf("LEN: %d\n", len);
|
||||
printf("OFF: %d\n", (int)(nodep - fit_blob));
|
||||
(void) munmap((void *)fit_blob, fsbuf.st_size);
|
||||
|
||||
close(ffd);
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
@ -403,7 +403,7 @@ static int fit_config_get_hash_list(void *fit, int conf_noffset,
|
||||
goto err_mem;
|
||||
|
||||
/* Get a list of images that we intend to sign */
|
||||
prop = fit_config_get_image_list(fit, conf_noffset, &len,
|
||||
prop = fit_config_get_image_list(fit, sig_offset, &len,
|
||||
&allow_missing);
|
||||
if (!prop)
|
||||
return 0;
|
||||
@ -695,3 +695,18 @@ int fit_add_verification_data(const char *keydir, void *keydest, void *fit,
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_FIT_SIGNATURE
|
||||
int fit_check_sign(const void *working_fdt, const void *key)
|
||||
{
|
||||
int cfg_noffset;
|
||||
int ret;
|
||||
|
||||
cfg_noffset = fit_conf_get_node(working_fdt, NULL);
|
||||
if (!cfg_noffset)
|
||||
return -1;
|
||||
|
||||
ret = fit_config_verify(working_fdt, cfg_noffset);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
1
tools/rsa-checksum.c
Normal file
1
tools/rsa-checksum.c
Normal file
@ -0,0 +1 @@
|
||||
#include "../lib/rsa/rsa-checksum.c"
|
1
tools/rsa-verify.c
Normal file
1
tools/rsa-verify.c
Normal file
@ -0,0 +1 @@
|
||||
#include "../lib/rsa/rsa-verify.c"
|
1
tools/sha256.c
Normal file
1
tools/sha256.c
Normal file
@ -0,0 +1 @@
|
||||
#include "../lib/sha256.c"
|
Loading…
Reference in New Issue
Block a user