Tom Rini 10 роки тому
батько
коміт
0f507779ca
62 змінених файлів з 1573 додано та 399 видалено
  1. 1 0
      README
  2. 2 70
      arch/arm/cpu/tegra20-common/crypto.c
  3. 1 1
      arch/sparc/cpu/leon2/config.mk
  4. 1 1
      arch/sparc/cpu/leon3/config.mk
  5. 1 0
      common/Makefile
  6. 89 0
      common/cmd_aes.c
  7. 41 1
      common/cmd_fdt.c
  8. 79 0
      common/env_common.c
  9. 6 11
      common/env_dataflash.c
  10. 3 9
      common/env_eeprom.c
  11. 3 9
      common/env_fat.c
  12. 6 15
      common/env_flash.c
  13. 2 10
      common/env_mmc.c
  14. 4 9
      common/env_nand.c
  15. 3 9
      common/env_nvram.c
  16. 4 9
      common/env_onenand.c
  17. 7 17
      common/env_sf.c
  18. 8 19
      common/env_ubi.c
  19. 105 11
      common/hash.c
  20. 5 0
      common/image-fit.c
  21. 63 0
      common/image-sig.c
  22. 19 1
      doc/uImage.FIT/signature.txt
  23. 39 10
      include/aes.h
  24. 0 2
      include/configs/gr_cpci_ax2000.h
  25. 0 2
      include/configs/gr_ep2s60.h
  26. 0 2
      include/configs/gr_xc3s_1500.h
  27. 0 2
      include/configs/grsim.h
  28. 0 2
      include/configs/grsim_leon2.h
  29. 14 1
      include/environment.h
  30. 5 0
      include/fdt_support.h
  31. 48 0
      include/hash.h
  32. 36 2
      include/image.h
  33. 24 0
      include/rsa-checksum.h
  34. 24 0
      include/rsa.h
  35. 84 0
      lib/aes.c
  36. 20 0
      lib/fdtdec.c
  37. 1 1
      lib/rsa/Makefile
  38. 163 0
      lib/rsa/rsa-checksum.c
  39. 6 4
      lib/rsa/rsa-sign.c
  40. 37 70
      lib/rsa/rsa-verify.c
  41. 3 2
      lib/sha256.c
  42. 0 0
      test/vboot/sign-configs-sha1.its
  43. 45 0
      test/vboot/sign-configs-sha256.its
  44. 0 0
      test/vboot/sign-images-sha1.its
  45. 42 0
      test/vboot/sign-images-sha256.its
  46. 58 28
      test/vboot/vboot_test.sh
  47. 2 0
      tools/.gitignore
  48. 14 2
      tools/Makefile
  49. 1 1
      tools/env/Makefile
  50. 127 2
      tools/env/fw_env.c
  51. 12 5
      tools/env/fw_env_main.c
  52. 2 0
      tools/fdt_host.h
  53. 1 0
      tools/fdtdec.c
  54. 85 0
      tools/fit_check_sign.c
  55. 86 0
      tools/fit_common.c
  56. 22 0
      tools/fit_common.h
  57. 4 58
      tools/fit_image.c
  58. 96 0
      tools/fit_info.c
  59. 16 1
      tools/image-host.c
  60. 1 0
      tools/rsa-checksum.c
  61. 1 0
      tools/rsa-verify.c
  62. 1 0
      tools/sha256.c

+ 1 - 0
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

+ 2 - 70
arch/arm/cpu/tegra20-common/crypto.c

@@ -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");
 	}
 

+ 1 - 1
arch/sparc/cpu/leon2/config.mk

@@ -7,4 +7,4 @@
 
 PLATFORM_RELFLAGS += -fPIC
 
-PLATFORM_CPPFLAGS += -DCONFIG_LEON
+PLATFORM_CPPFLAGS += -DCONFIG_LEON -DCONFIG_LEON2

+ 1 - 1
arch/sparc/cpu/leon3/config.mk

@@ -7,4 +7,4 @@
 
 PLATFORM_RELFLAGS += -fPIC
 
-PLATFORM_CPPFLAGS += -DCONFIG_LEON
+PLATFORM_CPPFLAGS += -DCONFIG_LEON -DCONFIG_LEON3

+ 1 - 0
common/Makefile

@@ -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 - 0
common/cmd_aes.c

@@ -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
+);

+ 41 - 1
common/cmd_fdt.c

@@ -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

+ 79 - 0
common/env_common.c

@@ -140,6 +140,52 @@ int set_default_vars(int nvars, char * const vars[])
 				H_NOCLEAR | H_INTERACTIVE, nvars, vars);
 }
 
+#ifdef CONFIG_ENV_AES
+#include <aes.h>
+/**
+ * env_aes_cbc_get_key() - Get AES-128-CBC key for the environment
+ *
+ * This function shall return 16-byte array containing AES-128 key used
+ * to encrypt and decrypt the environment. This function must be overriden
+ * by the implementer as otherwise the environment encryption will not
+ * work.
+ */
+__weak uint8_t *env_aes_cbc_get_key(void)
+{
+	return NULL;
+}
+
+static int env_aes_cbc_crypt(env_t *env, const int enc)
+{
+	unsigned char *data = env->data;
+	uint8_t *key;
+	uint8_t key_exp[AES_EXPAND_KEY_LENGTH];
+	uint32_t aes_blocks;
+
+	key = env_aes_cbc_get_key();
+	if (!key)
+		return -EINVAL;
+
+	/* First we expand the key. */
+	aes_expand_key(key, key_exp);
+
+	/* Calculate the number of AES blocks to encrypt. */
+	aes_blocks = ENV_SIZE / AES_KEY_LENGTH;
+
+	if (enc)
+		aes_cbc_encrypt_blocks(key_exp, data, data, aes_blocks);
+	else
+		aes_cbc_decrypt_blocks(key_exp, data, data, aes_blocks);
+
+	return 0;
+}
+#else
+static inline int env_aes_cbc_crypt(env_t *env, const int enc)
+{
+	return 0;
+}
+#endif
+
 /*
  * Check if CRC is valid and (if yes) import the environment.
  * Note that "buf" may or may not be aligned.
@@ -147,6 +193,7 @@ int set_default_vars(int nvars, char * const vars[])
 int env_import(const char *buf, int check)
 {
 	env_t *ep = (env_t *)buf;
+	int ret;
 
 	if (check) {
 		uint32_t crc;
@@ -159,6 +206,14 @@ int env_import(const char *buf, int check)
 		}
 	}
 
+	/* Decrypt the env if desired. */
+	ret = env_aes_cbc_crypt(ep, 0);
+	if (ret) {
+		error("Failed to decrypt env!\n");
+		set_default_env("!import failed");
+		return ret;
+	}
+
 	if (himport_r(&env_htab, (char *)ep->data, ENV_SIZE, '\0', 0,
 			0, NULL)) {
 		gd->flags |= GD_FLG_ENV_READY;
@@ -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)

+ 6 - 11
common/env_dataflash.c

@@ -56,17 +56,12 @@ void env_relocate_spec(void)
 
 int saveenv(void)
 {
-	env_t	env_new;
-	ssize_t	len;
-	char	*res;
-
-	res = (char *)&env_new.data;
-	len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
-	if (len < 0) {
-		error("Cannot export environment: errno = %d\n", errno);
-		return 1;
-	}
-	env_new.crc = crc32(0, env_new.data, ENV_SIZE);
+	env_t env_new;
+	int ret;
+
+	ret = env_export(&env_new);
+	if (ret)
+		return ret;
 
 	return write_dataflash(CONFIG_ENV_ADDR,
 				(unsigned long)&env_new,

+ 3 - 9
common/env_eeprom.c

@@ -98,8 +98,6 @@ void env_relocate_spec(void)
 int saveenv(void)
 {
 	env_t	env_new;
-	ssize_t	len;
-	char	*res;
 	int	rc;
 	unsigned int off	= CONFIG_ENV_OFFSET;
 #ifdef CONFIG_ENV_OFFSET_REDUND
@@ -109,13 +107,9 @@ int saveenv(void)
 
 	BUG_ON(env_ptr != NULL);
 
-	res = (char *)&env_new.data;
-	len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
-	if (len < 0) {
-		error("Cannot export environment: errno = %d\n", errno);
-		return 1;
-	}
-	env_new.crc = crc32(0, env_new.data, ENV_SIZE);
+	rc = env_export(&env_new);
+	if (rc)
+		return rc;
 
 #ifdef CONFIG_ENV_OFFSET_REDUND
 	if (gd->env_valid == 1) {

+ 3 - 9
common/env_fat.c

@@ -37,19 +37,14 @@ int env_init(void)
 int saveenv(void)
 {
 	env_t	env_new;
-	ssize_t	len;
-	char	*res;
 	block_dev_desc_t *dev_desc = NULL;
 	int dev = FAT_ENV_DEVICE;
 	int part = FAT_ENV_PART;
 	int err;
 
-	res = (char *)&env_new.data;
-	len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
-	if (len < 0) {
-		error("Cannot export environment: errno = %d\n", errno);
-		return 1;
-	}
+	err = env_export(&env_new);
+	if (err)
+		return err;
 
 #ifdef CONFIG_MMC
 	if (strcmp(FAT_ENV_INTERFACE, "mmc") == 0) {
@@ -79,7 +74,6 @@ int saveenv(void)
 		return 1;
 	}
 
-	env_new.crc = crc32(0, env_new.data, ENV_SIZE);
 	err = file_fat_write(FAT_ENV_FILE, (void *)&env_new, sizeof(env_t));
 	if (err == -1) {
 		printf("\n** Unable to write \"%s\" from %s%d:%d **\n",

+ 6 - 15
common/env_flash.c

@@ -106,8 +106,7 @@ int env_init(void)
 int saveenv(void)
 {
 	env_t	env_new;
-	ssize_t	len;
-	char	*res, *saved_data = NULL;
+	char	*saved_data = NULL;
 	char	flag = OBSOLETE_FLAG, new_flag = ACTIVE_FLAG;
 	int	rc = 1;
 #if CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE
@@ -125,13 +124,9 @@ int saveenv(void)
 	if (flash_sect_protect(0, (ulong)flash_addr_new, end_addr_new))
 		goto done;
 
-	res = (char *)&env_new.data;
-	len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
-	if (len < 0) {
-		error("Cannot export environment: errno = %d\n", errno);
-		goto done;
-	}
-	env_new.crc	= crc32(0, env_new.data, ENV_SIZE);
+	rc = env_export(&env_new);
+	if (rc)
+		return rc;
 	env_new.flags	= new_flag;
 
 #if CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE
@@ -258,13 +253,9 @@ int saveenv(void)
 	if (flash_sect_protect(0, (long)flash_addr, end_addr))
 		goto done;
 
-	res = (char *)&env_new.data;
-	len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
-	if (len < 0) {
-		error("Cannot export environment: errno = %d\n", errno);
+	rc = env_export(&env_new);
+	if (rc)
 		goto done;
-	}
-	env_new.crc = crc32(0, env_new.data, ENV_SIZE);
 
 	puts("Erasing Flash...");
 	if (flash_sect_erase((long)flash_addr, end_addr))

+ 2 - 10
common/env_mmc.c

@@ -118,8 +118,6 @@ static unsigned char env_flags;
 int saveenv(void)
 {
 	ALLOC_CACHE_ALIGN_BUFFER(env_t, env_new, 1);
-	ssize_t	len;
-	char	*res;
 	struct mmc *mmc = find_mmc_device(CONFIG_SYS_MMC_ENV_DEV);
 	u32	offset;
 	int	ret, copy = 0;
@@ -127,15 +125,9 @@ int saveenv(void)
 	if (init_mmc_for_env(mmc))
 		return 1;
 
-	res = (char *)&env_new->data;
-	len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
-	if (len < 0) {
-		error("Cannot export environment: errno = %d\n", errno);
-		ret = 1;
+	ret = env_export(env_new);
+	if (ret)
 		goto fini;
-	}
-
-	env_new->crc = crc32(0, &env_new->data[0], ENV_SIZE);
 
 #ifdef CONFIG_ENV_OFFSET_REDUND
 	env_new->flags	= ++env_flags; /* increase the serial */

+ 4 - 9
common/env_nand.c

@@ -181,8 +181,6 @@ int saveenv(void)
 {
 	int	ret = 0;
 	ALLOC_CACHE_ALIGN_BUFFER(env_t, env_new, 1);
-	ssize_t	len;
-	char	*res;
 	int	env_idx = 0;
 	static const struct env_location location[] = {
 		{
@@ -207,13 +205,10 @@ int saveenv(void)
 	if (CONFIG_ENV_RANGE < CONFIG_ENV_SIZE)
 		return 1;
 
-	res = (char *)&env_new->data;
-	len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
-	if (len < 0) {
-		error("Cannot export environment: errno = %d\n", errno);
-		return 1;
-	}
-	env_new->crc   = crc32(0, env_new->data, ENV_SIZE);
+	ret = env_export(env_new);
+	if (ret)
+		return ret;
+
 #ifdef CONFIG_ENV_OFFSET_REDUND
 	env_new->flags = ++env_flags; /* increase the serial */
 	env_idx = (gd->env_valid == 1);

+ 3 - 9
common/env_nvram.c

@@ -69,17 +69,11 @@ void env_relocate_spec(void)
 int saveenv(void)
 {
 	env_t	env_new;
-	ssize_t	len;
-	char	*res;
 	int	rcode = 0;
 
-	res = (char *)&env_new.data;
-	len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
-	if (len < 0) {
-		error("Cannot export environment: errno = %d\n", errno);
-		return 1;
-	}
-	env_new.crc = crc32(0, env_new.data, ENV_SIZE);
+	rcode = env_export(&env_new);
+	if (rcode)
+		return rcode;
 
 #ifdef CONFIG_SYS_NVRAM_ACCESS_ROUTINE
 	nvram_write(CONFIG_ENV_ADDR, &env_new, CONFIG_ENV_SIZE);

+ 4 - 9
common/env_onenand.c

@@ -66,8 +66,7 @@ void env_relocate_spec(void)
 int saveenv(void)
 {
 	env_t	env_new;
-	ssize_t	len;
-	char	*res;
+	int ret;
 	struct mtd_info *mtd = &onenand_mtd;
 #ifdef CONFIG_ENV_ADDR_FLEX
 	struct onenand_chip *this = &onenand_chip;
@@ -78,13 +77,9 @@ int saveenv(void)
 		.callback	= NULL,
 	};
 
-	res = (char *)&env_new.data;
-	len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
-	if (len < 0) {
-		error("Cannot export environment: errno = %d\n", errno);
-		return 1;
-	}
-	env_new.crc = crc32(0, env_new.data, ENV_SIZE);
+	ret = env_export(&env_new);
+	if (ret)
+		return ret;
 
 	instr.len = CONFIG_ENV_SIZE;
 #ifdef CONFIG_ENV_ADDR_FLEX

+ 7 - 17
common/env_sf.c

@@ -47,8 +47,7 @@ static struct spi_flash *env_flash;
 int saveenv(void)
 {
 	env_t	env_new;
-	ssize_t	len;
-	char	*res, *saved_buffer = NULL, flag = OBSOLETE_FLAG;
+	char	*saved_buffer = NULL, flag = OBSOLETE_FLAG;
 	u32	saved_size, saved_offset, sector = 1;
 	int	ret;
 
@@ -62,13 +61,9 @@ int saveenv(void)
 		}
 	}
 
-	res = (char *)&env_new.data;
-	len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
-	if (len < 0) {
-		error("Cannot export environment: errno = %d\n", errno);
-		return 1;
-	}
-	env_new.crc	= crc32(0, env_new.data, ENV_SIZE);
+	ret = env_export(&env_new);
+	if (ret)
+		return ret;
 	env_new.flags	= ACTIVE_FLAG;
 
 	if (gd->env_valid == 1) {
@@ -225,10 +220,9 @@ out:
 int saveenv(void)
 {
 	u32	saved_size, saved_offset, sector = 1;
-	char	*res, *saved_buffer = NULL;
+	char	*saved_buffer = NULL;
 	int	ret = 1;
 	env_t	env_new;
-	ssize_t	len;
 
 	if (!env_flash) {
 		env_flash = spi_flash_probe(CONFIG_ENV_SPI_BUS,
@@ -260,13 +254,9 @@ int saveenv(void)
 			sector++;
 	}
 
-	res = (char *)&env_new.data;
-	len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
-	if (len < 0) {
-		error("Cannot export environment: errno = %d\n", errno);
+	ret = env_export(&env_new);
+	if (ret)
 		goto done;
-	}
-	env_new.crc = crc32(0, env_new.data, ENV_SIZE);
 
 	puts("Erasing SPI flash...");
 	ret = spi_flash_erase(env_flash, CONFIG_ENV_OFFSET,

+ 8 - 19
common/env_ubi.c

@@ -37,15 +37,11 @@ static unsigned char env_flags;
 int saveenv(void)
 {
 	ALLOC_CACHE_ALIGN_BUFFER(env_t, env_new, 1);
-	ssize_t	len;
-	char *res;
+	int ret;
 
-	res = (char *)&env_new->data;
-	len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
-	if (len < 0) {
-		error("Cannot export environment: errno = %d\n", errno);
-		return 1;
-	}
+	ret = env_export(env_new);
+	if (ret)
+		return ret;
 
 	if (ubi_part(CONFIG_ENV_UBI_PART, NULL)) {
 		printf("\n** Cannot find mtd partition \"%s\"\n",
@@ -53,7 +49,6 @@ int saveenv(void)
 		return 1;
 	}
 
-	env_new->crc = crc32(0, env_new->data, ENV_SIZE);
 	env_new->flags = ++env_flags; /* increase the serial */
 
 	if (gd->env_valid == 1) {
@@ -86,15 +81,11 @@ int saveenv(void)
 int saveenv(void)
 {
 	ALLOC_CACHE_ALIGN_BUFFER(env_t, env_new, 1);
-	ssize_t	len;
-	char *res;
+	int ret;
 
-	res = (char *)&env_new->data;
-	len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
-	if (len < 0) {
-		error("Cannot export environment: errno = %d\n", errno);
-		return 1;
-	}
+	ret = env_export(env_new);
+	if (ret)
+		return ret;
 
 	if (ubi_part(CONFIG_ENV_UBI_PART, NULL)) {
 		printf("\n** Cannot find mtd partition \"%s\"\n",
@@ -102,8 +93,6 @@ int saveenv(void)
 		return 1;
 	}
 
-	env_new->crc = crc32(0, env_new->data, ENV_SIZE);
-
 	if (ubi_volume_write(CONFIG_ENV_UBI_VOLUME, (void *)env_new,
 			     CONFIG_ENV_SIZE)) {
 		printf("\n** Unable to write env to %s:%s **\n",

+ 105 - 11
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;
 		}

+ 5 - 0
common/image-fit.c

@@ -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;

+ 63 - 0
common/image-sig.c

@@ -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)

+ 19 - 1
doc/uImage.FIT/signature.txt

@@ -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

+ 39 - 10
include/aes.h

@@ -8,6 +8,13 @@
 #ifndef _AES_REF_H_
 #define _AES_REF_H_
 
+#ifdef USE_HOSTCC
+/* Define compat stuff for use in fw_* tools. */
+typedef unsigned char u8;
+typedef unsigned int u32;
+#define debug(...) do {} while (0)
+#endif
+
 /*
  * AES encryption library, with small code size, supporting only 128-bit AES
  *
@@ -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_ */

+ 0 - 2
include/configs/gr_cpci_ax2000.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

+ 0 - 2
include/configs/gr_ep2s60.h

@@ -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
 

+ 0 - 2
include/configs/gr_xc3s_1500.h

@@ -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 */

+ 0 - 2
include/configs/grsim.h

@@ -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 */
 

+ 0 - 2
include/configs/grsim_leon2.h

@@ -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 */
 

+ 14 - 1
include/environment.h

@@ -146,7 +146,12 @@ extern unsigned long nand_env_oob_offset;
 extern char *env_name_spec;
 #endif
 
+#ifdef CONFIG_ENV_AES
+/* Make sure the payload is multiple of AES block size */
+#define ENV_SIZE ((CONFIG_ENV_SIZE - ENV_HEADER_SIZE) & ~(16 - 1))
+#else
 #define ENV_SIZE (CONFIG_ENV_SIZE - ENV_HEADER_SIZE)
+#endif
 
 typedef struct environment_s {
 	uint32_t	crc;		/* CRC32 over data bytes	*/
@@ -154,7 +159,12 @@ typedef struct environment_s {
 	unsigned char	flags;		/* active/obsolete flags	*/
 #endif
 	unsigned char	data[ENV_SIZE]; /* Environment data		*/
-} env_t;
+} env_t
+#ifdef CONFIG_ENV_AES
+/* Make sure the env is aligned to block size. */
+__attribute__((aligned(16)))
+#endif
+;
 
 #ifdef ENV_IS_EMBEDDED
 extern env_t environment;
@@ -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_ */

+ 5 - 0
include/fdt_support.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 */

+ 48 - 0
include/hash.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

+ 36 - 2
include/image.h

@@ -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 - 0
include/rsa-checksum.h

@@ -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

+ 24 - 0
include/rsa.h

@@ -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 - 0
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 - 0
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

+ 1 - 1
lib/rsa/Makefile

@@ -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 - 0
lib/rsa/rsa-checksum.c

@@ -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);
+}

+ 6 - 4
lib/rsa/rsa-sign.c

@@ -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;
 

+ 37 - 70
lib/rsa/rsa-verify.c

@@ -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) {

+ 3 - 2
lib/sha256.c

@@ -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;

+ 0 - 0
test/vboot/sign-configs.its → test/vboot/sign-configs-sha1.its


+ 45 - 0
test/vboot/sign-configs-sha256.its

@@ -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";
+			};
+		};
+	};
+};

+ 0 - 0
test/vboot/sign-images.its → test/vboot/sign-images-sha1.its


+ 42 - 0
test/vboot/sign-images-sha256.its

@@ -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";
+		};
+	};
+};

+ 58 - 28
test/vboot/vboot_test.sh

@@ -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" "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"
+}
 
-run_uboot "signed config with bad hash" "Bad Data Hash"
+sha=sha1
+do_test
+sha=sha256
+do_test
 
 popd >/dev/null
 

+ 2 - 0
tools/.gitignore

@@ -1,5 +1,7 @@
 /bmp_logo
 /envcrc
+/fit_check_sign
+/fit_info
 /gen_eth_addr
 /img2srec
 /kwboot

+ 14 - 2
tools/Makefile

@@ -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)

+ 1 - 1
tools/env/Makefile

@@ -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 $@ $<

+ 127 - 2
tools/env/fw_env.c

@@ -31,6 +31,10 @@
 
 #include "fw_env.h"
 
+#include <aes.h>
+
+#define DIV_ROUND_UP(n, d)	(((n) + (d) - 1) / (d))
+
 #define WHITESPACE(c) ((c == '\t') || (c == ' '))
 
 #define min(x, y) ({				\
@@ -98,6 +102,11 @@ static struct environment environment = {
 	.flag_scheme = FLAG_NONE,
 };
 
+/* Is AES encryption used? */
+static int aes_flag;
+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;
 

+ 12 - 5
tools/env/fw_env_main.c

@@ -9,18 +9,22 @@
  * Command line user interface to firmware (=U-Boot) environment.
  *
  * Implements:
- *	fw_printenv [[ -n name ] | [ name ... ]]
+ *	fw_printenv [ -a key ] [[ -n name ] | [ name ... ]]
  *              - prints the value of a single environment variable
  *                "name", the ``name=value'' pairs of one or more
  *                environment variables "name", or the whole
  *                environment if no names are specified.
- *	fw_setenv name [ value ... ]
+ *	fw_setenv [ -a key ] name [ value ... ]
  *		- If a name without any values is given, the variable
  *		  with this name is deleted from the environment;
  *		  otherwise, all "value" arguments are concatenated,
  *		  separated by single blank characters, and the
  *		  resulting string is assigned to the environment
  *		  variable "name"
+ *
+ * If '-a key' is specified, the env block is encrypted with AES 128 CBC.
+ * The 'key' argument is in the format of 32 hexadecimal numbers (16 bytes
+ * of AES key), eg. '-a aabbccddeeff00112233445566778899'.
  */
 
 #include <fcntl.h>
@@ -46,8 +50,8 @@ void usage(void)
 
 	fprintf(stderr, "fw_printenv/fw_setenv, "
 		"a command line interface to U-Boot environment\n\n"
-		"usage:\tfw_printenv [-n] [variable name]\n"
-		"\tfw_setenv [variable name] [variable value]\n"
+		"usage:\tfw_printenv [-a key] [-n] [variable name]\n"
+		"\tfw_setenv [-a key] [variable name] [variable value]\n"
 		"\tfw_setenv -s [ file ]\n"
 		"\tfw_setenv -s - < [ file ]\n\n"
 		"The file passed as argument contains only pairs "
@@ -94,9 +98,12 @@ int main(int argc, char *argv[])
 		cmdname = p + 1;
 	}
 
-	while ((c = getopt_long (argc, argv, "ns:h",
+	while ((c = getopt_long (argc, argv, "a:ns:h",
 		long_options, NULL)) != EOF) {
 		switch (c) {
+		case 'a':
+			/* AES key, handled later */
+			break;
 		case 'n':
 			/* handled in fw_printenv */
 			break;

+ 2 - 0
tools/fdt_host.h

@@ -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 - 0
tools/fdtdec.c

@@ -0,0 +1 @@
+#include "../lib/fdtdec.c"

+ 85 - 0
tools/fit_check_sign.c

@@ -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 - 0
tools/fit_common.c

@@ -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 - 0
tools/fit_common.h

@@ -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_ */

+ 4 - 58
tools/fit_image.c

@@ -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 - 0
tools/fit_info.c

@@ -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);
+}

+ 16 - 1
tools/image-host.c

@@ -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 - 0
tools/rsa-checksum.c

@@ -0,0 +1 @@
+#include "../lib/rsa/rsa-checksum.c"

+ 1 - 0
tools/rsa-verify.c

@@ -0,0 +1 @@
+#include "../lib/rsa/rsa-verify.c"

+ 1 - 0
tools/sha256.c

@@ -0,0 +1 @@
+#include "../lib/sha256.c"