diff options
42 files changed, 1361 insertions, 262 deletions
@@ -383,6 +383,14 @@ config FIT_ENABLE_RSASSA_PSS_SUPPORT Enable this to support the pss padding algorithm as described in the rfc8017 (https://tools.ietf.org/html/rfc8017). +config FIT_CIPHER + bool "Enable ciphering data in a FIT uImages" + depends on DM + select AES + help + Enable the feature of data ciphering/unciphering in the tool mkimage + and in the u-boot support of the FIT image. + config FIT_VERBOSE bool "Show verbose messages when FIT images fail" help diff --git a/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch2_speed.c b/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch2_speed.c index 25e9a495f7..fec231857b 100644 --- a/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch2_speed.c +++ b/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch2_speed.c @@ -125,7 +125,6 @@ void get_sys_info(struct sys_info *sys_info) } #endif -#ifdef CONFIG_FSL_ESDHC #define HWA_CGA_M2_CLK_SEL 0x00000007 #define HWA_CGA_M2_CLK_SHIFT 0 #if defined(CONFIG_TARGET_LS1046ARDB) || defined(CONFIG_TARGET_LS1043ARDB) @@ -148,11 +147,10 @@ void get_sys_info(struct sys_info *sys_info) break; #endif default: - printf("Error: Unknown peripheral clock select!\n"); + printf("Error: Unknown cluster group A mux 2 clock select!\n"); break; } #endif -#endif #if defined(CONFIG_FSL_IFC) sys_info->freq_localbus = sys_info->freq_systembus / @@ -179,28 +177,21 @@ unsigned long get_qman_freq(void) int get_clocks(void) { struct sys_info sys_info; - +#ifdef CONFIG_FSL_ESDHC + u32 clock = 0; +#endif get_sys_info(&sys_info); gd->cpu_clk = sys_info.freq_processor[0]; gd->bus_clk = sys_info.freq_systembus / CONFIG_SYS_FSL_PCLK_DIV; gd->mem_clk = sys_info.freq_ddrbus; - #ifdef CONFIG_FSL_ESDHC -#if defined(CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK) -#if defined(CONFIG_TARGET_LS1046ARDB) - gd->arch.sdhc_clk = sys_info.freq_cga_m2 / 2; -#endif -#if defined(CONFIG_TARGET_LS1043ARDB) - gd->arch.sdhc_clk = sys_info.freq_cga_m2; -#endif -#if defined(CONFIG_TARGET_LS1012ARDB) - gd->arch.sdhc_clk = sys_info.freq_systembus; -#endif -#else - gd->arch.sdhc_clk = (sys_info.freq_systembus / - CONFIG_SYS_FSL_PCLK_DIV) / - CONFIG_SYS_FSL_SDHC_CLK_DIV; +#if defined(CONFIG_ARCH_LS1012A) + clock = sys_info.freq_systembus; +#elif defined(CONFIG_ARCH_LS1043A) || defined(CONFIG_ARCH_LS1046A) + clock = sys_info.freq_cga_m2; #endif + gd->arch.sdhc_per_clk = clock / CONFIG_SYS_FSL_SDHC_CLK_DIV; + gd->arch.sdhc_clk = gd->bus_clk / CONFIG_SYS_FSL_SDHC_CLK_DIV; #endif if (gd->cpu_clk != 0) return 0; diff --git a/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch3_speed.c b/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch3_speed.c index 4b047a39c0..bd8b9cbdad 100644 --- a/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch3_speed.c +++ b/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch3_speed.c @@ -160,14 +160,14 @@ void get_sys_info(struct sys_info *sys_info) break; } #endif -#if defined(CONFIG_ARCH_LX2160A) || defined(CONFIG_ARCH_LS2080A) - sys_info->freq_cga_m2 = sys_info->freq_systembus; -#endif } int get_clocks(void) { struct sys_info sys_info; +#ifdef CONFIG_FSL_ESDHC + u32 clock = 0; +#endif get_sys_info(&sys_info); gd->cpu_clk = sys_info.freq_processor[0]; gd->bus_clk = sys_info.freq_systembus / CONFIG_SYS_FSL_PCLK_DIV; @@ -175,18 +175,16 @@ int get_clocks(void) #ifdef CONFIG_SYS_FSL_HAS_DP_DDR gd->arch.mem2_clk = sys_info.freq_ddrbus2; #endif -#if defined(CONFIG_FSL_ESDHC) -#if defined(CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK) -#if defined(CONFIG_ARCH_LS1028A) || defined(CONFIG_ARCH_LX2160A) - gd->arch.sdhc_clk = sys_info.freq_cga_m2 / 2; -#endif -#if defined(CONFIG_ARCH_LS2080A) || defined(CONFIG_ARCH_LS1088A) - gd->arch.sdhc_clk = sys_info.freq_cga_m2; + +#ifdef CONFIG_FSL_ESDHC +#if defined(CONFIG_ARCH_LS1028A) || defined(CONFIG_ARCH_LS1088A) + clock = sys_info.freq_cga_m2; +#elif defined(CONFIG_ARCH_LX2160A) || defined(CONFIG_ARCH_LS2080A) + clock = sys_info.freq_systembus; #endif -#else + gd->arch.sdhc_per_clk = clock / CONFIG_SYS_FSL_SDHC_CLK_DIV; gd->arch.sdhc_clk = gd->bus_clk / CONFIG_SYS_FSL_SDHC_CLK_DIV; #endif -#endif /* defined(CONFIG_FSL_ESDHC) */ if (gd->cpu_clk != 0) return 0; diff --git a/arch/arm/include/asm/global_data.h b/arch/arm/include/asm/global_data.h index 17740147ea..f23b6bfb75 100644 --- a/arch/arm/include/asm/global_data.h +++ b/arch/arm/include/asm/global_data.h @@ -13,6 +13,10 @@ struct arch_global_data { u32 sdhc_clk; #endif +#if defined(CONFIG_FSL_ESDHC) + u32 sdhc_per_clk; +#endif + #if defined(CONFIG_U_QE) u32 qe_clk; u32 brg_clk; diff --git a/arch/arm/mach-tegra/tegra20/crypto.c b/arch/arm/mach-tegra/tegra20/crypto.c index 66fbc3b458..b91191eba3 100644 --- a/arch/arm/mach-tegra/tegra20/crypto.c +++ b/arch/arm/mach-tegra/tegra20/crypto.c @@ -39,34 +39,35 @@ static void left_shift_vector(u8 *in, u8 *out, int size) /** * Sign a block of data, putting the result into dst. * - * \param key Input AES key, length AES_KEY_LENGTH + * \param key Input AES key, length AES128_KEY_LENGTH * \param key_schedule Expanded key to use * \param src Source data of length 'num_aes_blocks' blocks - * \param dst Destination buffer, length AES_KEY_LENGTH + * \param dst Destination buffer, length AES128_KEY_LENGTH * \param num_aes_blocks Number of AES blocks to encrypt */ static void sign_object(u8 *key, u8 *key_schedule, u8 *src, u8 *dst, u32 num_aes_blocks) { - u8 tmp_data[AES_KEY_LENGTH]; - u8 iv[AES_KEY_LENGTH] = {0}; - u8 left[AES_KEY_LENGTH]; - u8 k1[AES_KEY_LENGTH]; + u8 tmp_data[AES128_KEY_LENGTH]; + u8 iv[AES128_KEY_LENGTH] = {0}; + u8 left[AES128_KEY_LENGTH]; + u8 k1[AES128_KEY_LENGTH]; u8 *cbc_chain_data; unsigned i; cbc_chain_data = zero_key; /* Convenient array of 0's for IV */ /* compute K1 constant needed by AES-CMAC calculation */ - for (i = 0; i < AES_KEY_LENGTH; i++) + for (i = 0; i < AES128_KEY_LENGTH; i++) tmp_data[i] = 0; - aes_cbc_encrypt_blocks(key_schedule, iv, tmp_data, left, 1); + aes_cbc_encrypt_blocks(AES128_KEY_LENGTH, key_schedule, iv, + tmp_data, left, 1); left_shift_vector(left, k1, sizeof(left)); if ((left[0] >> 7) != 0) /* get MSB of L */ - k1[AES_KEY_LENGTH-1] ^= AES_CMAC_CONST_RB; + k1[AES128_KEY_LENGTH - 1] ^= AES_CMAC_CONST_RB; /* compute the AES-CMAC value */ for (i = 0; i < num_aes_blocks; i++) { @@ -78,31 +79,32 @@ static void sign_object(u8 *key, u8 *key_schedule, u8 *src, u8 *dst, aes_apply_cbc_chain_data(tmp_data, k1, tmp_data); /* encrypt the AES block */ - aes_encrypt(tmp_data, key_schedule, dst); + aes_encrypt(AES128_KEY_LENGTH, tmp_data, + key_schedule, dst); debug("sign_obj: block %d of %d\n", i, num_aes_blocks); /* Update pointers for next loop. */ cbc_chain_data = dst; - src += AES_KEY_LENGTH; + src += AES128_KEY_LENGTH; } } /** * Encrypt and sign a block of data (depending on security mode). * - * \param key Input AES key, length AES_KEY_LENGTH + * \param key Input AES key, length AES128_KEY_LENGTH * \param oper Security operations mask to perform (enum security_op) * \param src Source data * \param length Size of source data - * \param sig_dst Destination address for signature, AES_KEY_LENGTH bytes + * \param sig_dst Destination address for signature, AES128_KEY_LENGTH bytes */ static int encrypt_and_sign(u8 *key, enum security_op oper, u8 *src, u32 length, u8 *sig_dst) { u32 num_aes_blocks; - u8 key_schedule[AES_EXPAND_KEY_LENGTH]; - u8 iv[AES_KEY_LENGTH] = {0}; + u8 key_schedule[AES128_EXPAND_KEY_LENGTH]; + u8 iv[AES128_KEY_LENGTH] = {0}; debug("encrypt_and_sign: length = %d\n", length); @@ -110,15 +112,16 @@ static int encrypt_and_sign(u8 *key, enum security_op oper, u8 *src, * The only need for a key is for signing/checksum purposes, so * if not encrypting, expand a key of 0s. */ - aes_expand_key(oper & SECURITY_ENCRYPT ? key : zero_key, key_schedule); + aes_expand_key(oper & SECURITY_ENCRYPT ? key : zero_key, + AES128_KEY_LENGTH, key_schedule); - num_aes_blocks = (length + AES_KEY_LENGTH - 1) / AES_KEY_LENGTH; + num_aes_blocks = (length + AES128_KEY_LENGTH - 1) / AES128_KEY_LENGTH; if (oper & SECURITY_ENCRYPT) { /* Perform this in place, resulting in src being encrypted. */ debug("encrypt_and_sign: begin encryption\n"); - aes_cbc_encrypt_blocks(key_schedule, iv, src, src, - num_aes_blocks); + aes_cbc_encrypt_blocks(AES128_KEY_LENGTH, key_schedule, iv, src, + src, num_aes_blocks); debug("encrypt_and_sign: end encryption\n"); } diff --git a/arch/powerpc/cpu/mpc85xx/speed.c b/arch/powerpc/cpu/mpc85xx/speed.c index 15b05fcc51..0c5252edc2 100644 --- a/arch/powerpc/cpu/mpc85xx/speed.c +++ b/arch/powerpc/cpu/mpc85xx/speed.c @@ -69,8 +69,7 @@ void get_sys_info(sys_info_t *sys_info) [14] = 4, /* CC4 PPL / 4 */ }; uint i, freq_c_pll[CONFIG_SYS_FSL_NUM_CC_PLLS]; -#if !defined(CONFIG_FM_PLAT_CLK_DIV) || !defined(CONFIG_PME_PLAT_CLK_DIV) || \ - defined(CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK) +#if !defined(CONFIG_FM_PLAT_CLK_DIV) || !defined(CONFIG_PME_PLAT_CLK_DIV) uint rcw_tmp; #endif uint ratio[CONFIG_SYS_FSL_NUM_CC_PLLS]; @@ -450,48 +449,6 @@ void get_sys_info(sys_info_t *sys_info) #endif #endif -#ifdef CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK -#if defined(CONFIG_ARCH_T2080) -#define ESDHC_CLK_SEL 0x00000007 -#define ESDHC_CLK_SHIFT 0 -#define ESDHC_CLK_RCWSR 15 -#else /* Support T1040 T1024 by now */ -#define ESDHC_CLK_SEL 0xe0000000 -#define ESDHC_CLK_SHIFT 29 -#define ESDHC_CLK_RCWSR 7 -#endif - rcw_tmp = in_be32(&gur->rcwsr[ESDHC_CLK_RCWSR]); - switch ((rcw_tmp & ESDHC_CLK_SEL) >> ESDHC_CLK_SHIFT) { - case 1: - sys_info->freq_sdhc = freq_c_pll[CONFIG_SYS_SDHC_CLK]; - break; - case 2: - sys_info->freq_sdhc = freq_c_pll[CONFIG_SYS_SDHC_CLK] / 2; - break; - case 3: - sys_info->freq_sdhc = freq_c_pll[CONFIG_SYS_SDHC_CLK] / 3; - break; -#if defined(CONFIG_SYS_SDHC_CLK_2_PLL) - case 4: - sys_info->freq_sdhc = freq_c_pll[CONFIG_SYS_SDHC_CLK] / 4; - break; -#if defined(CONFIG_ARCH_T2080) - case 5: - sys_info->freq_sdhc = freq_c_pll[1 - CONFIG_SYS_SDHC_CLK]; - break; -#endif - case 6: - sys_info->freq_sdhc = freq_c_pll[1 - CONFIG_SYS_SDHC_CLK] / 2; - break; - case 7: - sys_info->freq_sdhc = freq_c_pll[1 - CONFIG_SYS_SDHC_CLK] / 3; - break; -#endif - default: - sys_info->freq_sdhc = 0; - printf("Error: Unknown SDHC peripheral clock select!\n"); - } -#endif #else /* CONFIG_SYS_FSL_QORIQ_CHASSIS2 */ for_each_cpu(i, cpu, cpu_numcores(), cpu_mask()) { @@ -673,15 +630,11 @@ int get_clocks (void) gd->arch.i2c2_clk = gd->arch.i2c1_clk; #if defined(CONFIG_FSL_ESDHC) -#ifdef CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK - gd->arch.sdhc_clk = sys_info.freq_sdhc / 2; -#else #if defined(CONFIG_ARCH_MPC8569) || defined(CONFIG_ARCH_P1010) gd->arch.sdhc_clk = gd->bus_clk; #else gd->arch.sdhc_clk = gd->bus_clk / 2; #endif -#endif #endif /* defined(CONFIG_FSL_ESDHC) */ #if defined(CONFIG_CPM2) diff --git a/arch/powerpc/include/asm/config_mpc85xx.h b/arch/powerpc/include/asm/config_mpc85xx.h index 946e74a93b..4ca1e2b325 100644 --- a/arch/powerpc/include/asm/config_mpc85xx.h +++ b/arch/powerpc/include/asm/config_mpc85xx.h @@ -331,9 +331,6 @@ #define CONFIG_SYS_FMAN_V3 #define CONFIG_FM_PLAT_CLK_DIV 1 #define CONFIG_SYS_FM1_CLK CONFIG_FM_PLAT_CLK_DIV -#define CONFIG_SYS_SDHC_CLK 0/* Select SDHC CLK begining from PLL1 - per rcw field value */ -#define CONFIG_SYS_SDHC_CLK_2_PLL /* Select SDHC CLK from 2 PLLs */ #define CONFIG_SYS_FM_MURAM_SIZE 0x30000 #define CONFIG_SYS_FSL_SINGLE_SOURCE_CLK #define CONFIG_SYS_FSL_TBCLK_DIV 16 @@ -362,8 +359,6 @@ #define CONFIG_USB_MAX_CONTROLLER_COUNT 2 #define CONFIG_SYS_FSL_IFC_BANK_COUNT 8 #define CONFIG_SYS_FM1_CLK 0 -#define CONFIG_SYS_SDHC_CLK 0/* Select SDHC CLK begining from PLL1 - per rcw field value */ #define CONFIG_QBMAN_CLK_DIV 1 #define CONFIG_SYS_FM_MURAM_SIZE 0x30000 #define CONFIG_SYS_FSL_SINGLE_SOURCE_CLK @@ -402,9 +397,6 @@ #define CONFIG_PME_PLAT_CLK_DIV 1 #define CONFIG_SYS_PME_CLK CONFIG_PME_PLAT_CLK_DIV #define CONFIG_SYS_FM1_CLK 0 -#define CONFIG_SYS_SDHC_CLK 1/* Select SDHC CLK begining from PLL2 - per rcw field value */ -#define CONFIG_SYS_SDHC_CLK_2_PLL /* Select SDHC CLK from 2 PLLs */ #define CONFIG_SYS_FSL_IFC_BANK_COUNT 8 #define CONFIG_SYS_FMAN_V3 #define CONFIG_SYS_FM_MURAM_SIZE 0x28000 diff --git a/arch/powerpc/include/asm/global_data.h b/arch/powerpc/include/asm/global_data.h index b6e4dd6c80..1620fba014 100644 --- a/arch/powerpc/include/asm/global_data.h +++ b/arch/powerpc/include/asm/global_data.h @@ -14,6 +14,7 @@ struct arch_global_data { #if defined(CONFIG_FSL_ESDHC) u32 sdhc_clk; + u32 sdhc_per_clk; #if defined(CONFIG_FSL_ESDHC_ADAPTER_IDENT) u8 sdhc_adapter; #endif diff --git a/board/solidrun/clearfog/README b/board/solidrun/clearfog/README index 6171ce66f4..9375be8495 100644 --- a/board/solidrun/clearfog/README +++ b/board/solidrun/clearfog/README @@ -20,12 +20,6 @@ of "/dev/sdX" here! Install U-Boot on eMMC: ----------------------- -The ROM loads the bootloader from eMMC first boot partition at offset 0. This -is unlike load from SD card that is at offset 512. As a result, the offset of -the main U-Boot image on the eMMC boot partition changes. Set -CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR to 0x140 for SPL to load U-Boot from -the correct location. - To make SPL load the main U-Boot image from the eMMC boot partition enable eMMC boot acknowledgement and boot partition with the following U-Boot command: @@ -2,7 +2,7 @@ /* * Copyright (C) 2014 Marek Vasut <marex@denx.de> * - * Command for en/de-crypting block of memory with AES-128-CBC cipher. + * Command for en/de-crypting block of memory with AES-[128/192/256]-CBC cipher. */ #include <common.h> @@ -13,6 +13,18 @@ #include <linux/compiler.h> #include <mapmem.h> +u32 aes_get_key_len(char *command) +{ + u32 key_len = AES128_KEY_LENGTH; + + if (!strcmp(command, "aes.192")) + key_len = AES192_KEY_LENGTH; + else if (!strcmp(command, "aes.256")) + key_len = AES256_KEY_LENGTH; + + return key_len; +} + /** * do_aes() - Handle the "aes" command-line command * @cmdtp: Command data struct pointer @@ -27,13 +39,15 @@ static int do_aes(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) { uint32_t key_addr, iv_addr, src_addr, dst_addr, len; uint8_t *key_ptr, *iv_ptr, *src_ptr, *dst_ptr; - uint8_t key_exp[AES_EXPAND_KEY_LENGTH]; - uint32_t aes_blocks; + u8 key_exp[AES256_EXPAND_KEY_LENGTH]; + u32 aes_blocks, key_len; int enc; if (argc != 7) return CMD_RET_USAGE; + key_len = aes_get_key_len(argv[0]); + if (!strncmp(argv[1], "enc", 3)) enc = 1; else if (!strncmp(argv[1], "dec", 3)) @@ -47,23 +61,23 @@ static int do_aes(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) dst_addr = simple_strtoul(argv[5], NULL, 16); len = simple_strtoul(argv[6], NULL, 16); - key_ptr = (uint8_t *)map_sysmem(key_addr, 128 / 8); + key_ptr = (uint8_t *)map_sysmem(key_addr, key_len); iv_ptr = (uint8_t *)map_sysmem(iv_addr, 128 / 8); src_ptr = (uint8_t *)map_sysmem(src_addr, len); dst_ptr = (uint8_t *)map_sysmem(dst_addr, len); /* First we expand the key. */ - aes_expand_key(key_ptr, key_exp); + aes_expand_key(key_ptr, key_len, key_exp); /* Calculate the number of AES blocks to encrypt. */ - aes_blocks = DIV_ROUND_UP(len, AES_KEY_LENGTH); + aes_blocks = DIV_ROUND_UP(len, AES_BLOCK_LENGTH); if (enc) - aes_cbc_encrypt_blocks(key_exp, iv_ptr, src_ptr, dst_ptr, - aes_blocks); + aes_cbc_encrypt_blocks(key_len, key_exp, iv_ptr, src_ptr, + dst_ptr, aes_blocks); else - aes_cbc_decrypt_blocks(key_exp, iv_ptr, src_ptr, dst_ptr, - aes_blocks); + aes_cbc_decrypt_blocks(key_len, key_exp, iv_ptr, src_ptr, + dst_ptr, aes_blocks); unmap_sysmem(key_ptr); unmap_sysmem(iv_ptr); @@ -76,13 +90,13 @@ static int do_aes(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) /***************************************************/ #ifdef CONFIG_SYS_LONGHELP static char aes_help_text[] = - "enc key iv src dst len - Encrypt block of data $len bytes long\n" + "[.128,.192,.256] enc key iv src dst len - Encrypt block of data $len bytes long\n" " at address $src using a key at address\n" " $key with initialization vector at address\n" " $iv. Store the result at address $dst.\n" " The $len size must be multiple of 16 bytes.\n" " The $key and $iv must be 16 bytes long.\n" - "aes dec key iv src dst len - Decrypt block of data $len bytes long\n" + "aes [.128,.192,.256] dec key iv src dst len - Decrypt block of data $len bytes long\n" " at address $src using a key at address\n" " $key with initialization vector at address\n" " $iv. Store the result at address $dst.\n" @@ -92,6 +106,6 @@ static char aes_help_text[] = U_BOOT_CMD( aes, 7, 1, do_aes, - "AES 128 CBC encryption", + "AES 128/192/256 CBC encryption", aes_help_text ); diff --git a/common/Makefile b/common/Makefile index 029cc0f2ce..5f62b8d0b1 100644 --- a/common/Makefile +++ b/common/Makefile @@ -113,6 +113,7 @@ obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += image-fdt.o obj-$(CONFIG_$(SPL_TPL_)FIT) += image-fit.o obj-$(CONFIG_$(SPL_)MULTI_DTB_FIT) += boot_fit.o common_fit.o obj-$(CONFIG_$(SPL_TPL_)FIT_SIGNATURE) += image-sig.o +obj-$(CONFIG_$(SPL_TPL_)FIT_CIPHER) += image-cipher.o obj-$(CONFIG_IO_TRACE) += iotrace.o obj-y += memsize.o obj-y += stdio.o diff --git a/common/image-cipher.c b/common/image-cipher.c new file mode 100644 index 0000000000..cee3b03ee5 --- /dev/null +++ b/common/image-cipher.c @@ -0,0 +1,167 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2019, Softathome + */ + +#ifdef USE_HOSTCC +#include "mkimage.h" +#include <time.h> +#else +#include <common.h> +#include <malloc.h> +DECLARE_GLOBAL_DATA_PTR; +#endif /* !USE_HOSTCC*/ +#include <image.h> +#include <uboot_aes.h> +#include <u-boot/aes.h> + +struct cipher_algo cipher_algos[] = { + { + .name = "aes128", + .key_len = AES128_KEY_LENGTH, + .iv_len = AES_BLOCK_LENGTH, +#if IMAGE_ENABLE_ENCRYPT + .calculate_type = EVP_aes_128_cbc, +#endif + .encrypt = image_aes_encrypt, + .decrypt = image_aes_decrypt, + .add_cipher_data = image_aes_add_cipher_data + }, + { + .name = "aes192", + .key_len = AES192_KEY_LENGTH, + .iv_len = AES_BLOCK_LENGTH, +#if IMAGE_ENABLE_ENCRYPT + .calculate_type = EVP_aes_192_cbc, +#endif + .encrypt = image_aes_encrypt, + .decrypt = image_aes_decrypt, + .add_cipher_data = image_aes_add_cipher_data + }, + { + .name = "aes256", + .key_len = AES256_KEY_LENGTH, + .iv_len = AES_BLOCK_LENGTH, +#if IMAGE_ENABLE_ENCRYPT + .calculate_type = EVP_aes_256_cbc, +#endif + .encrypt = image_aes_encrypt, + .decrypt = image_aes_decrypt, + .add_cipher_data = image_aes_add_cipher_data + } +}; + +struct cipher_algo *image_get_cipher_algo(const char *full_name) +{ + int i; + const char *name; + + for (i = 0; i < ARRAY_SIZE(cipher_algos); i++) { + name = cipher_algos[i].name; + if (!strncmp(name, full_name, strlen(name))) + return &cipher_algos[i]; + } + + return NULL; +} + +static int fit_image_setup_decrypt(struct image_cipher_info *info, + const void *fit, int image_noffset, + int cipher_noffset) +{ + const void *fdt = gd_fdt_blob(); + const char *node_name; + char node_path[128]; + int noffset; + char *algo_name; + int ret; + + node_name = fit_get_name(fit, image_noffset, NULL); + if (!node_name) { + printf("Can't get node name\n"); + return -1; + } + + if (fit_image_cipher_get_algo(fit, cipher_noffset, &algo_name)) { + printf("Can't get algo name for cipher '%s' in image '%s'\n", + node_name, node_name); + return -1; + } + + info->keyname = fdt_getprop(fit, cipher_noffset, "key-name-hint", NULL); + if (!info->keyname) { + printf("Can't get key name\n"); + return -1; + } + + info->ivname = fdt_getprop(fit, cipher_noffset, "iv-name-hint", NULL); + if (!info->ivname) { + printf("Can't get IV name\n"); + return -1; + } + + info->fit = fit; + info->node_noffset = image_noffset; + info->name = algo_name; + info->cipher = image_get_cipher_algo(algo_name); + if (!info->cipher) { + printf("Can't get cipher\n"); + return -1; + } + + ret = fit_image_get_data_size_unciphered(fit, image_noffset, + &info->size_unciphered); + if (ret) { + printf("Can't get size of unciphered data\n"); + return -1; + } + + /* + * Search the cipher node in the u-boot fdt + * the path should be: /cipher/key-<algo>-<key>-<iv> + */ + snprintf(node_path, sizeof(node_path), "/%s/key-%s-%s-%s", + FIT_CIPHER_NODENAME, algo_name, info->keyname, info->ivname); + + noffset = fdt_path_offset(fdt, node_path); + if (noffset < 0) { + printf("Can't found cipher node offset\n"); + return -1; + } + + /* read key */ + info->key = fdt_getprop(fdt, noffset, "key", NULL); + if (!info->key) { + printf("Can't get key in cipher node '%s'\n", node_path); + return -1; + } + + /* read iv */ + info->iv = fdt_getprop(fdt, noffset, "iv", NULL); + if (!info->iv) { + printf("Can't get IV in cipher node '%s'\n", node_path); + return -1; + } + + return 0; +} + +int fit_image_decrypt_data(const void *fit, + int image_noffset, int cipher_noffset, + const void *data_ciphered, size_t size_ciphered, + void **data_unciphered, size_t *size_unciphered) +{ + struct image_cipher_info info; + int ret; + + ret = fit_image_setup_decrypt(&info, fit, image_noffset, + cipher_noffset); + if (ret < 0) + goto out; + + ret = info.cipher->decrypt(&info, data_ciphered, size_ciphered, + data_unciphered, size_unciphered); + + out: + return ret; +} diff --git a/common/image-fit.c b/common/image-fit.c index 231612ff5f..f3bb00c98a 100644 --- a/common/image-fit.c +++ b/common/image-fit.c @@ -948,6 +948,31 @@ int fit_image_get_data_size(const void *fit, int noffset, int *data_size) } /** + * Get 'data-size-unciphered' property from a given image node. + * + * @fit: pointer to the FIT image header + * @noffset: component image node offset + * @data_size: holds the data-size property + * + * returns: + * 0, on success + * -ENOENT if the property could not be found + */ +int fit_image_get_data_size_unciphered(const void *fit, int noffset, + size_t *data_size) +{ + const fdt32_t *val; + + val = fdt_getprop(fit, noffset, "data-size-unciphered", NULL); + if (!val) + return -ENOENT; + + *data_size = (size_t)fdt32_to_cpu(*val); + + return 0; +} + +/** * fit_image_get_data_and_size - get data and its size including * both embedded and external data * @fit: pointer to the FIT format image header @@ -1080,6 +1105,33 @@ static int fit_image_hash_get_ignore(const void *fit, int noffset, int *ignore) return 0; } +/** + * fit_image_cipher_get_algo - get cipher algorithm name + * @fit: pointer to the FIT format image header + * @noffset: cipher node offset + * @algo: double pointer to char, will hold pointer to the algorithm name + * + * fit_image_cipher_get_algo() finds cipher algorithm property in a given + * cipher node. If the property is found its data start address is returned + * to the caller. + * + * returns: + * 0, on success + * -1, on failure + */ +int fit_image_cipher_get_algo(const void *fit, int noffset, char **algo) +{ + int len; + + *algo = (char *)fdt_getprop(fit, noffset, FIT_ALGO_PROP, &len); + if (!*algo) { + fit_get_debug(fit, noffset, FIT_ALGO_PROP, len); + return -1; + } + + return 0; +} + ulong fit_get_end(const void *fit) { return map_to_sysmem((void *)(fit + fdt_totalsize(fit))); @@ -1354,6 +1406,32 @@ int fit_all_image_verify(const void *fit) return 1; } +#ifdef CONFIG_FIT_CIPHER +static int fit_image_uncipher(const void *fit, int image_noffset, + void **data, size_t *size) +{ + int cipher_noffset, ret; + void *dst; + size_t size_dst; + + cipher_noffset = fdt_subnode_offset(fit, image_noffset, + FIT_CIPHER_NODENAME); + if (cipher_noffset < 0) + return 0; + + ret = fit_image_decrypt_data(fit, image_noffset, cipher_noffset, + *data, *size, &dst, &size_dst); + if (ret) + goto out; + + *data = dst; + *size = size_dst; + + out: + return ret; +} +#endif /* CONFIG_FIT_CIPHER */ + /** * fit_image_check_os - check whether image node is of a given os type * @fit: pointer to the FIT format image header @@ -1954,6 +2032,18 @@ int fit_image_load(bootm_headers_t *images, ulong addr, return -ENOENT; } +#ifdef CONFIG_FIT_CIPHER + /* Decrypt data before uncompress/move */ + if (IMAGE_ENABLE_DECRYPT) { + puts(" Decrypting Data ... "); + if (fit_image_uncipher(fit, noffset, &buf, &size)) { + puts("Error\n"); + return -EACCES; + } + puts("OK\n"); + } +#endif + #if !defined(USE_HOSTCC) && defined(CONFIG_FIT_IMAGE_POST_PROCESS) /* perform any post-processing on the image data */ board_fit_image_post_process(&buf, &size); diff --git a/common/spl/Kconfig b/common/spl/Kconfig index c43eed2b2a..76f39dc04f 100644 --- a/common/spl/Kconfig +++ b/common/spl/Kconfig @@ -329,6 +329,18 @@ config SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR Address on the MMC to load U-Boot from, when the MMC is being used in raw mode. Units: MMC sectors (1 sector = 512 bytes). +config SYS_MMCSD_RAW_MODE_U_BOOT_DATA_PART_OFFSET + hex "U-Boot main hardware partition image offset" + depends on SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR + default 0x0 + help + On some platforms SPL location depends on hardware partition. The ROM + code skips the MBR sector when loading SPL from main hardware data + partition. This adds offset to the main U-Boot image. Set this symbol + to the number of skipped sectors. + + If unsure, leave the default. + config SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION bool "MMC Raw mode: by partition" help diff --git a/common/spl/spl_mmc.c b/common/spl/spl_mmc.c index 2ede096e61..3e6a17c110 100644 --- a/common/spl/spl_mmc.c +++ b/common/spl/spl_mmc.c @@ -49,6 +49,16 @@ static ulong h_spl_load_read(struct spl_load_info *load, ulong sector, return blk_dread(mmc_get_blk_desc(mmc), sector, count, buf); } +static __maybe_unused unsigned long spl_mmc_raw_uboot_offset(int part) +{ +#if IS_ENABLED(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR) + if (part == 0) + return CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_DATA_PART_OFFSET; +#endif + + return 0; +} + static __maybe_unused int mmc_load_image_raw_sector(struct spl_image_info *spl_image, struct mmc *mmc, unsigned long sector) @@ -325,7 +335,7 @@ int spl_mmc_load(struct spl_image_info *spl_image, static struct mmc *mmc; u32 boot_mode; int err = 0; - __maybe_unused int part; + __maybe_unused int part = 0; /* Perform peripheral init only once */ if (!mmc) { @@ -391,7 +401,8 @@ int spl_mmc_load(struct spl_image_info *spl_image, return err; #endif #ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR - err = mmc_load_image_raw_sector(spl_image, mmc, raw_sect); + err = mmc_load_image_raw_sector(spl_image, mmc, + raw_sect + spl_mmc_raw_uboot_offset(part)); if (!err) return err; #endif diff --git a/configs/clearfog_defconfig b/configs/clearfog_defconfig index 787c6360a7..b48a4abfcb 100644 --- a/configs/clearfog_defconfig +++ b/configs/clearfog_defconfig @@ -26,7 +26,8 @@ CONFIG_USE_PREBOOT=y CONFIG_SYS_CONSOLE_INFO_QUIET=y # CONFIG_DISPLAY_BOARDINFO is not set CONFIG_DISPLAY_BOARDINFO_LATE=y -CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x141 +CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_DATA_PART_OFFSET=0x1 +CONFIG_SPL_DM_GPIO=y CONFIG_SPL_I2C_SUPPORT=y # CONFIG_CMD_FLASH is not set CONFIG_CMD_GPIO=y diff --git a/configs/ls1028aqds_tfa_SECURE_BOOT_defconfig b/configs/ls1028aqds_tfa_SECURE_BOOT_defconfig index 31e3b5a9b6..c80f8c7699 100644 --- a/configs/ls1028aqds_tfa_SECURE_BOOT_defconfig +++ b/configs/ls1028aqds_tfa_SECURE_BOOT_defconfig @@ -4,7 +4,6 @@ CONFIG_TFABOOT=y CONFIG_SYS_MALLOC_F_LEN=0x6000 CONFIG_NXP_ESBC=y CONFIG_FSPI_AHB_EN_4BYTE=y -CONFIG_SYS_FSL_SDHC_CLK_DIV=1 CONFIG_ENV_SIZE=0x2000 CONFIG_NR_DRAM_BANKS=2 CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT=y diff --git a/configs/ls1028aqds_tfa_defconfig b/configs/ls1028aqds_tfa_defconfig index 72922120e9..b3e3bcfe63 100644 --- a/configs/ls1028aqds_tfa_defconfig +++ b/configs/ls1028aqds_tfa_defconfig @@ -3,7 +3,6 @@ CONFIG_TARGET_LS1028AQDS=y CONFIG_TFABOOT=y CONFIG_SYS_MALLOC_F_LEN=0x6000 CONFIG_FSPI_AHB_EN_4BYTE=y -CONFIG_SYS_FSL_SDHC_CLK_DIV=1 CONFIG_ENV_SIZE=0x2000 CONFIG_ENV_OFFSET=0x500000 CONFIG_NR_DRAM_BANKS=2 diff --git a/configs/ls1028ardb_tfa_SECURE_BOOT_defconfig b/configs/ls1028ardb_tfa_SECURE_BOOT_defconfig index db92204d98..02770b1064 100644 --- a/configs/ls1028ardb_tfa_SECURE_BOOT_defconfig +++ b/configs/ls1028ardb_tfa_SECURE_BOOT_defconfig @@ -4,7 +4,6 @@ CONFIG_TFABOOT=y CONFIG_SYS_MALLOC_F_LEN=0x6000 CONFIG_NXP_ESBC=y CONFIG_FSPI_AHB_EN_4BYTE=y -CONFIG_SYS_FSL_SDHC_CLK_DIV=1 CONFIG_ENV_SIZE=0x2000 CONFIG_NR_DRAM_BANKS=2 CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT=y diff --git a/configs/ls1028ardb_tfa_defconfig b/configs/ls1028ardb_tfa_defconfig index 41fe40a853..6715d310fa 100644 --- a/configs/ls1028ardb_tfa_defconfig +++ b/configs/ls1028ardb_tfa_defconfig @@ -3,7 +3,6 @@ CONFIG_TARGET_LS1028ARDB=y CONFIG_TFABOOT=y CONFIG_SYS_MALLOC_F_LEN=0x6000 CONFIG_FSPI_AHB_EN_4BYTE=y -CONFIG_SYS_FSL_SDHC_CLK_DIV=1 CONFIG_ENV_SIZE=0x2000 CONFIG_ENV_OFFSET=0x500000 CONFIG_NR_DRAM_BANKS=2 diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index 2bc19dd56b..2f0eedc22f 100644 --- a/drivers/mmc/Kconfig +++ b/drivers/mmc/Kconfig @@ -79,7 +79,7 @@ config MMC_QUIRKS help Some cards and hosts may sometimes behave unexpectedly (quirks). This option enable workarounds to handle those quirks. Some of them - are enabled by default, other may require additionnal flags or are + are enabled by default, other may require additional flags or are enabled by the host driver. config MMC_HW_PARTITIONING @@ -711,19 +711,10 @@ endif config FSL_ESDHC bool "Freescale/NXP eSDHC controller support" - select FSL_ESDHC_USE_PERIPHERAL_CLK if MMC_HS200_SUPPORT || MMC_UHS_SUPPORT help This selects support for the eSDHC (Enhanced Secure Digital Host Controller) found on numerous Freescale/NXP SoCs. -config FSL_ESDHC_USE_PERIPHERAL_CLK - bool "enable ESDHC peripheral clock support" - depends on FSL_ESDHC - help - eSDHC supports two reference clocks (platform clock and peripheral clock). - Peripheral clock which could provide higher clock frequency is required to - be used for tuning of SD UHS mode and eMMC HS200/HS400 modes. - config FSL_ESDHC_IMX bool "Freescale/NXP i.MX eSDHC controller support" help diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c index 1e7d606cd8..112f115015 100644 --- a/drivers/mmc/fsl_esdhc.c +++ b/drivers/mmc/fsl_esdhc.c @@ -81,6 +81,7 @@ struct fsl_esdhc_plat { struct fsl_esdhc_priv { struct fsl_esdhc *esdhc_regs; unsigned int sdhc_clk; + bool is_sdhc_per_clk; unsigned int clock; #if !CONFIG_IS_ENABLED(DM_MMC) struct mmc *mmc; @@ -523,7 +524,6 @@ static void set_sysctl(struct fsl_esdhc_priv *priv, struct mmc *mmc, uint clock) esdhc_setbits32(®s->sysctl, SYSCTL_PEREN | SYSCTL_CKEN); } -#ifdef CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK static void esdhc_clock_control(struct fsl_esdhc_priv *priv, bool enable) { struct fsl_esdhc *regs = priv->esdhc_regs; @@ -550,18 +550,18 @@ static void esdhc_clock_control(struct fsl_esdhc_priv *priv, bool enable) mdelay(1); } } -#endif static int esdhc_set_ios_common(struct fsl_esdhc_priv *priv, struct mmc *mmc) { struct fsl_esdhc *regs = priv->esdhc_regs; -#ifdef CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK - /* Select to use peripheral clock */ - esdhc_clock_control(priv, false); - esdhc_setbits32(®s->esdhcctl, ESDHCCTL_PCS); - esdhc_clock_control(priv, true); -#endif + if (priv->is_sdhc_per_clk) { + /* Select to use peripheral clock */ + esdhc_clock_control(priv, false); + esdhc_setbits32(®s->esdhcctl, ESDHCCTL_PCS); + esdhc_clock_control(priv, true); + } + /* Set the clock speed */ if (priv->clock != mmc->clock) set_sysctl(priv, mmc, mmc->clock); @@ -716,17 +716,8 @@ void fdt_fixup_esdhc(void *blob, bd_t *bd) if (esdhc_status_fixup(blob, compat)) return; -#ifdef CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK - do_fixup_by_compat_u32(blob, compat, "peripheral-frequency", - gd->arch.sdhc_clk, 1); -#else do_fixup_by_compat_u32(blob, compat, "clock-frequency", gd->arch.sdhc_clk, 1); -#endif -#ifdef CONFIG_FSL_ESDHC_ADAPTER_IDENT - do_fixup_by_compat_u32(blob, compat, "adapter-type", - (u32)(gd->arch.sdhc_adapter), 1); -#endif } #endif @@ -788,6 +779,8 @@ int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg) priv->esdhc_regs = (struct fsl_esdhc *)(unsigned long)(cfg->esdhc_base); priv->sdhc_clk = cfg->sdhc_clk; + if (gd->arch.sdhc_per_clk) + priv->is_sdhc_per_clk = true; mmc_cfg = &plat->cfg; @@ -826,7 +819,11 @@ int fsl_esdhc_mmc_init(bd_t *bis) cfg = calloc(sizeof(struct fsl_esdhc_cfg), 1); cfg->esdhc_base = CONFIG_SYS_FSL_ESDHC_ADDR; - cfg->sdhc_clk = gd->arch.sdhc_clk; + /* Prefer peripheral clock which provides higher frequency. */ + if (gd->arch.sdhc_per_clk) + cfg->sdhc_clk = gd->arch.sdhc_per_clk; + else + cfg->sdhc_clk = gd->arch.sdhc_clk; return fsl_esdhc_initialize(bis, cfg); } #else /* DM_MMC */ @@ -848,7 +845,13 @@ static int fsl_esdhc_probe(struct udevice *dev) #endif priv->dev = dev; - priv->sdhc_clk = gd->arch.sdhc_clk; + if (gd->arch.sdhc_per_clk) { + priv->sdhc_clk = gd->arch.sdhc_per_clk; + priv->is_sdhc_per_clk = true; + } else { + priv->sdhc_clk = gd->arch.sdhc_clk; + } + if (priv->sdhc_clk <= 0) { dev_err(dev, "Unable to get clk for %s\n", dev->name); return -EINVAL; diff --git a/drivers/mmc/fsl_esdhc_imx.c b/drivers/mmc/fsl_esdhc_imx.c index 96fe01e26d..462ad2878a 100644 --- a/drivers/mmc/fsl_esdhc_imx.c +++ b/drivers/mmc/fsl_esdhc_imx.c @@ -661,35 +661,6 @@ static void set_sysctl(struct fsl_esdhc_priv *priv, struct mmc *mmc, uint clock) priv->clock = clock; } -#ifdef CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK -static void esdhc_clock_control(struct fsl_esdhc_priv *priv, bool enable) -{ - struct fsl_esdhc *regs = priv->esdhc_regs; - u32 value; - u32 time_out; - - value = esdhc_read32(®s->sysctl); - - if (enable) - value |= SYSCTL_CKEN; - else - value &= ~SYSCTL_CKEN; - - esdhc_write32(®s->sysctl, value); - - time_out = 20; - value = PRSSTAT_SDSTB; - while (!(esdhc_read32(®s->prsstat) & value)) { - if (time_out == 0) { - printf("fsl_esdhc: Internal clock never stabilised.\n"); - break; - } - time_out--; - mdelay(1); - } -} -#endif - #ifdef MMC_SUPPORTS_TUNING static int esdhc_change_pinstate(struct udevice *dev) { @@ -961,12 +932,6 @@ static int esdhc_set_ios_common(struct fsl_esdhc_priv *priv, struct mmc *mmc) int ret __maybe_unused; u32 clock; -#ifdef CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK - /* Select to use peripheral clock */ - esdhc_clock_control(priv, false); - esdhc_setbits32(®s->scr, ESDHCCTL_PCS); - esdhc_clock_control(priv, true); -#endif /* Set the clock speed */ clock = mmc->clock; if (clock < mmc->cfg->f_min) @@ -1394,13 +1359,8 @@ void fdt_fixup_esdhc(void *blob, bd_t *bd) if (esdhc_status_fixup(blob, compat)) return; -#ifdef CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK - do_fixup_by_compat_u32(blob, compat, "peripheral-frequency", - gd->arch.sdhc_clk, 1); -#else do_fixup_by_compat_u32(blob, compat, "clock-frequency", gd->arch.sdhc_clk, 1); -#endif } #endif diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index f683b52ead..d43983d4a6 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -1444,6 +1444,20 @@ static int sd_read_ssr(struct mmc *mmc) cmd.cmdarg = mmc->rca << 16; err = mmc_send_cmd(mmc, &cmd, NULL); +#ifdef CONFIG_MMC_QUIRKS + if (err && (mmc->quirks & MMC_QUIRK_RETRY_APP_CMD)) { + int retries = 4; + /* + * It has been seen that APP_CMD may fail on the first + * attempt, let's try a few more times + */ + do { + err = mmc_send_cmd(mmc, &cmd, NULL); + if (!err) + break; + } while (retries--); + } +#endif if (err) return err; @@ -2755,7 +2769,8 @@ int mmc_get_op_cond(struct mmc *mmc) #ifdef CONFIG_MMC_QUIRKS mmc->quirks = MMC_QUIRK_RETRY_SET_BLOCKLEN | - MMC_QUIRK_RETRY_SEND_CID; + MMC_QUIRK_RETRY_SEND_CID | + MMC_QUIRK_RETRY_APP_CMD; #endif err = mmc_power_cycle(mmc); diff --git a/include/configs/T1040QDS.h b/include/configs/T1040QDS.h index b8456984e2..aa2a8b00de 100644 --- a/include/configs/T1040QDS.h +++ b/include/configs/T1040QDS.h @@ -481,7 +481,6 @@ unsigned long get_board_ddr_clk(void); #endif #ifdef CONFIG_MMC -#define CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK #define CONFIG_SYS_FSL_ESDHC_ADDR CONFIG_SYS_MPC85xx_ESDHC_ADDR #define CONFIG_FSL_ESDHC_ADAPTER_IDENT #endif diff --git a/include/configs/T208xQDS.h b/include/configs/T208xQDS.h index 2078b9d369..be5a658d7e 100644 --- a/include/configs/T208xQDS.h +++ b/include/configs/T208xQDS.h @@ -630,7 +630,6 @@ unsigned long get_board_ddr_clk(void); * SDHC */ #ifdef CONFIG_MMC -#define CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK #define CONFIG_SYS_FSL_ESDHC_ADDR CONFIG_SYS_MPC85xx_ESDHC_ADDR #define CONFIG_SYS_FSL_ESDHC_BROKEN_TIMEOUT #define CONFIG_SYS_FSL_MMC_HAS_CAPBLT_VS33 diff --git a/include/e500.h b/include/e500.h index 1acf7784df..255f46bf1e 100644 --- a/include/e500.h +++ b/include/e500.h @@ -18,7 +18,6 @@ typedef struct unsigned long freq_ddrbus; unsigned long freq_localbus; unsigned long freq_qe; - unsigned long freq_sdhc; #ifdef CONFIG_SYS_DPAA_FMAN unsigned long freq_fman[CONFIG_SYS_NUM_FMAN]; #endif diff --git a/include/image.h b/include/image.h index 4a280b78e7..86ebaae4fe 100644 --- a/include/image.h +++ b/include/image.h @@ -930,6 +930,10 @@ int booti_setup(ulong image, ulong *relocated_addr, ulong *size, #define FIT_IGNORE_PROP "uboot-ignore" #define FIT_SIG_NODENAME "signature" +/* cipher node */ +#define FIT_CIPHER_NODENAME "cipher" +#define FIT_ALGO_PROP "algo" + /* image node */ #define FIT_DATA_PROP "data" #define FIT_DATA_POSITION_PROP "data-position" @@ -1019,6 +1023,8 @@ int fit_image_get_data_offset(const void *fit, int noffset, int *data_offset); int fit_image_get_data_position(const void *fit, int noffset, int *data_position); int fit_image_get_data_size(const void *fit, int noffset, int *data_size); +int fit_image_get_data_size_unciphered(const void *fit, int noffset, + size_t *data_size); int fit_image_get_data_and_size(const void *fit, int noffset, const void **data, size_t *size); @@ -1028,6 +1034,10 @@ int fit_image_hash_get_value(const void *fit, int noffset, uint8_t **value, int fit_set_timestamp(void *fit, int noffset, time_t timestamp); +int fit_cipher_data(const char *keydir, void *keydest, void *fit, + const char *comment, int require_keys, + const char *engine_id, const char *cmdname); + /** * fit_add_verification_data() - add verification data to FIT image nodes * @@ -1058,6 +1068,7 @@ int fit_image_verify_with_data(const void *fit, int image_noffset, int fit_image_verify(const void *fit, int noffset); int fit_config_verify(const void *fit, int conf_noffset); int fit_all_image_verify(const void *fit); +int fit_config_decrypt(const void *fit, int conf_noffset); int fit_image_check_os(const void *fit, int noffset, uint8_t os); int fit_image_check_arch(const void *fit, int noffset, uint8_t arch); int fit_image_check_type(const void *fit, int noffset, uint8_t type); @@ -1138,6 +1149,7 @@ struct image_sign_info { const char *require_keys; /* Value for 'required' property */ const char *engine_id; /* Engine to use for signing */ }; + #endif /* Allow struct image_region to always be defined for rsa.h */ /* A part of an image, used for hashing */ @@ -1284,6 +1296,11 @@ int fit_image_verify_required_sigs(const void *fit, int image_noffset, int fit_image_check_sig(const void *fit, int noffset, const void *data, size_t size, int required_keynode, char **err_msgp); +int fit_image_decrypt_data(const void *fit, + int image_noffset, int cipher_noffset, + const void *data, size_t size, + void **data_unciphered, size_t *size_unciphered); + /** * fit_region_make_list() - Make a list of regions to hash * @@ -1310,6 +1327,64 @@ static inline int fit_image_check_target_arch(const void *fdt, int node) #endif } +/* + * At present we only support ciphering on the host, and unciphering on the + * device + */ +#if defined(USE_HOSTCC) +# if defined(CONFIG_FIT_CIPHER) +# define IMAGE_ENABLE_ENCRYPT 1 +# define IMAGE_ENABLE_DECRYPT 1 +# include <openssl/evp.h> +# else +# define IMAGE_ENABLE_ENCRYPT 0 +# define IMAGE_ENABLE_DECRYPT 0 +# endif +#else +# define IMAGE_ENABLE_ENCRYPT 0 +# define IMAGE_ENABLE_DECRYPT CONFIG_IS_ENABLED(FIT_CIPHER) +#endif + +/* Information passed to the ciphering routines */ +struct image_cipher_info { + const char *keydir; /* Directory containing keys */ + const char *keyname; /* Name of key to use */ + const char *ivname; /* Name of IV to use */ + const void *fit; /* Pointer to FIT blob */ + int node_noffset; /* Offset of the cipher node */ + const char *name; /* Algorithm name */ + struct cipher_algo *cipher; /* Cipher algorithm information */ + const void *fdt_blob; /* FDT containing key and IV */ + const void *key; /* Value of the key */ + const void *iv; /* Value of the IV */ + size_t size_unciphered; /* Size of the unciphered data */ +}; + +struct cipher_algo { + const char *name; /* Name of algorithm */ + int key_len; /* Length of the key */ + int iv_len; /* Length of the IV */ + +#if IMAGE_ENABLE_ENCRYPT + const EVP_CIPHER * (*calculate_type)(void); +#endif + + int (*encrypt)(struct image_cipher_info *info, + const unsigned char *data, int data_len, + unsigned char **cipher, int *cipher_len); + + int (*add_cipher_data)(struct image_cipher_info *info, + void *keydest); + + int (*decrypt)(struct image_cipher_info *info, + const void *cipher, size_t cipher_len, + void **data, size_t *data_len); +}; + +int fit_image_cipher_get_algo(const void *fit, int noffset, char **algo); + +struct cipher_algo *image_get_cipher_algo(const char *full_name); + #ifdef CONFIG_FIT_VERBOSE #define fit_unsupported(msg) printf("! %s:%d " \ "FIT images not supported for '%s'\n", \ diff --git a/include/mmc.h b/include/mmc.h index 1a9efe4c38..b5cb514f57 100644 --- a/include/mmc.h +++ b/include/mmc.h @@ -331,6 +331,7 @@ static inline bool mmc_is_tuning_cmd(uint cmdidx) #define MMC_QUIRK_RETRY_SEND_CID BIT(0) #define MMC_QUIRK_RETRY_SET_BLOCKLEN BIT(1) +#define MMC_QUIRK_RETRY_APP_CMD BIT(2) enum mmc_voltage { MMC_SIGNAL_VOLTAGE_000 = 0, diff --git a/include/u-boot/aes.h b/include/u-boot/aes.h new file mode 100644 index 0000000000..32281041de --- /dev/null +++ b/include/u-boot/aes.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2019, Softathome + */ + +#ifndef _AES_H +#define _AES_H + +#include <errno.h> +#include <image.h> + +#if IMAGE_ENABLE_ENCRYPT +int image_aes_encrypt(struct image_cipher_info *info, + const unsigned char *data, int size, + unsigned char **cipher, int *cipher_len); +int image_aes_add_cipher_data(struct image_cipher_info *info, void *keydest); +#else +int image_aes_encrypt(struct image_cipher_info *info, + const unsigned char *data, int size, + unsigned char **cipher, int *cipher_len) +{ + return -ENXIO; +} + +int image_aes_add_cipher_data(struct image_cipher_info *info, void *keydest) +{ + return -ENXIO; +} +#endif /* IMAGE_ENABLE_ENCRYPT */ + +#if IMAGE_ENABLE_DECRYPT +int image_aes_decrypt(struct image_cipher_info *info, + const void *cipher, size_t cipher_len, + void **data, size_t *size); +#else +int image_aes_decrypt(struct image_cipher_info *info, + const void *cipher, size_t cipher_len, + void **data, size_t *size) +{ + return -ENXIO; +} +#endif /* IMAGE_ENABLE_DECRYPT */ + +#endif diff --git a/include/uboot_aes.h b/include/uboot_aes.h index 2fda384e3b..d2583bed99 100644 --- a/include/uboot_aes.h +++ b/include/uboot_aes.h @@ -18,16 +18,24 @@ typedef unsigned int u32; * AES encryption library, with small code size, supporting only 128-bit AES * * AES is a stream cipher which works a block at a time, with each block - * in this case being AES_KEY_LENGTH bytes. + * in this case being AES_BLOCK_LENGTH bytes. */ enum { AES_STATECOLS = 4, /* columns in the state & expanded key */ - AES_KEYCOLS = 4, /* columns in a key */ - AES_ROUNDS = 10, /* rounds in encryption */ - - AES_KEY_LENGTH = 128 / 8, - AES_EXPAND_KEY_LENGTH = 4 * AES_STATECOLS * (AES_ROUNDS + 1), + AES128_KEYCOLS = 4, /* columns in a key for aes128 */ + AES192_KEYCOLS = 6, /* columns in a key for aes128 */ + AES256_KEYCOLS = 8, /* columns in a key for aes128 */ + AES128_ROUNDS = 10, /* rounds in encryption for aes128 */ + AES192_ROUNDS = 12, /* rounds in encryption for aes192 */ + AES256_ROUNDS = 14, /* rounds in encryption for aes256 */ + AES128_KEY_LENGTH = 128 / 8, + AES192_KEY_LENGTH = 192 / 8, + AES256_KEY_LENGTH = 256 / 8, + AES128_EXPAND_KEY_LENGTH = 4 * AES_STATECOLS * (AES128_ROUNDS + 1), + AES192_EXPAND_KEY_LENGTH = 4 * AES_STATECOLS * (AES192_ROUNDS + 1), + AES256_EXPAND_KEY_LENGTH = 4 * AES_STATECOLS * (AES256_ROUNDS + 1), + AES_BLOCK_LENGTH = 128 / 8, }; /** @@ -36,33 +44,36 @@ enum { * Expand a key into a key schedule, which is then used for the other * operations. * - * @key Key, of length AES_KEY_LENGTH bytes + * @key Key + * @key_size Size of the key (in bits) * @expkey Buffer to place expanded key, AES_EXPAND_KEY_LENGTH */ -void aes_expand_key(u8 *key, u8 *expkey); +void aes_expand_key(u8 *key, u32 key_size, u8 *expkey); /** * aes_encrypt() - Encrypt single block of data with AES 128 * + * @key_size Size of the aes key (in bits) * @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); +void aes_encrypt(u32 key_size, u8 *in, u8 *expkey, u8 *out); /** * aes_decrypt() - Decrypt single block of data with AES 128 * + * @key_size Size of the aes key (in bits) * @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); +void aes_decrypt(u32 key_size, u8 *in, u8 *expkey, u8 *out); /** * Apply chain data to the destination using EOR * - * Each array is of length AES_KEY_LENGTH. + * Each array is of length AES_BLOCK_LENGTH. * * @cbc_chain_data Chain data * @src Source data @@ -73,25 +84,27 @@ void aes_apply_cbc_chain_data(u8 *cbc_chain_data, u8 *src, u8 *dst); /** * aes_cbc_encrypt_blocks() - Encrypt multiple blocks of data with AES CBC. * + * @key_size Size of the aes key (in bits) * @key_exp Expanded key to use * @iv Initialization vector * @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 *iv, u8 *src, u8 *dst, +void aes_cbc_encrypt_blocks(u32 key_size, u8 *key_exp, u8 *iv, u8 *src, u8 *dst, u32 num_aes_blocks); /** * Decrypt multiple blocks of data with AES CBC. * + * @key_size Size of the aes key (in bits) * @key_exp Expanded key to use * @iv Initialization vector * @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 *iv, u8 *src, u8 *dst, +void aes_cbc_decrypt_blocks(u32 key_size, u8 *key_exp, u8 *iv, u8 *src, u8 *dst, u32 num_aes_blocks); #endif /* _AES_REF_H_ */ diff --git a/lib/Makefile b/lib/Makefile index 6b7b9ce85c..51eba80b89 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -21,6 +21,7 @@ obj-$(CONFIG_ASN1_DECODER) += asn1_decoder.o obj-y += crypto/ obj-$(CONFIG_AES) += aes.o +obj-$(CONFIG_AES) += aes/ obj-$(CONFIG_$(SPL_TPL_)BINMAN_FDT) += binman.o ifndef API_BUILD @@ -508,50 +508,79 @@ static u8 rcon[11] = { 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 }; +static u32 aes_get_rounds(u32 key_len) +{ + u32 rounds = AES128_ROUNDS; + + if (key_len == AES192_KEY_LENGTH) + rounds = AES192_ROUNDS; + else if (key_len == AES256_KEY_LENGTH) + rounds = AES256_ROUNDS; + + return rounds; +} + +static u32 aes_get_keycols(u32 key_len) +{ + u32 keycols = AES128_KEYCOLS; + + if (key_len == AES192_KEY_LENGTH) + keycols = AES192_KEYCOLS; + else if (key_len == AES256_KEY_LENGTH) + keycols = AES256_KEYCOLS; + + return keycols; +} + /* produce AES_STATECOLS bytes for each round */ -void aes_expand_key(u8 *key, u8 *expkey) +void aes_expand_key(u8 *key, u32 key_len, u8 *expkey) { u8 tmp0, tmp1, tmp2, tmp3, tmp4; - u32 idx; + u32 idx, aes_rounds, aes_keycols; - memcpy(expkey, key, AES_KEYCOLS * 4); + aes_rounds = aes_get_rounds(key_len); + aes_keycols = aes_get_keycols(key_len); - for (idx = AES_KEYCOLS; idx < AES_STATECOLS * (AES_ROUNDS + 1); idx++) { + memcpy(expkey, key, key_len); + + for (idx = aes_keycols; idx < AES_STATECOLS * (aes_rounds + 1); idx++) { tmp0 = expkey[4*idx - 4]; tmp1 = expkey[4*idx - 3]; tmp2 = expkey[4*idx - 2]; tmp3 = expkey[4*idx - 1]; - if (!(idx % AES_KEYCOLS)) { + if (!(idx % aes_keycols)) { tmp4 = tmp3; tmp3 = sbox[tmp0]; - tmp0 = sbox[tmp1] ^ rcon[idx / AES_KEYCOLS]; + tmp0 = sbox[tmp1] ^ rcon[idx / aes_keycols]; tmp1 = sbox[tmp2]; tmp2 = sbox[tmp4]; - } else if ((AES_KEYCOLS > 6) && (idx % AES_KEYCOLS == 4)) { + } else if ((aes_keycols > 6) && (idx % aes_keycols == 4)) { tmp0 = sbox[tmp0]; tmp1 = sbox[tmp1]; tmp2 = sbox[tmp2]; tmp3 = sbox[tmp3]; } - expkey[4*idx+0] = expkey[4*idx - 4*AES_KEYCOLS + 0] ^ tmp0; - expkey[4*idx+1] = expkey[4*idx - 4*AES_KEYCOLS + 1] ^ tmp1; - expkey[4*idx+2] = expkey[4*idx - 4*AES_KEYCOLS + 2] ^ tmp2; - expkey[4*idx+3] = expkey[4*idx - 4*AES_KEYCOLS + 3] ^ tmp3; + expkey[4*idx+0] = expkey[4*idx - 4*aes_keycols + 0] ^ tmp0; + expkey[4*idx+1] = expkey[4*idx - 4*aes_keycols + 1] ^ tmp1; + expkey[4*idx+2] = expkey[4*idx - 4*aes_keycols + 2] ^ tmp2; + expkey[4*idx+3] = expkey[4*idx - 4*aes_keycols + 3] ^ tmp3; } } /* encrypt one 128 bit block */ -void aes_encrypt(u8 *in, u8 *expkey, u8 *out) +void aes_encrypt(u32 key_len, u8 *in, u8 *expkey, u8 *out) { u8 state[AES_STATECOLS * 4]; - u32 round; + u32 round, aes_rounds; + + aes_rounds = aes_get_rounds(key_len); memcpy(state, in, AES_STATECOLS * 4); add_round_key((u32 *)state, (u32 *)expkey); - for (round = 1; round < AES_ROUNDS + 1; round++) { - if (round < AES_ROUNDS) + for (round = 1; round < aes_rounds + 1; round++) { + if (round < aes_rounds) mix_sub_columns(state); else shift_rows(state); @@ -563,18 +592,20 @@ void aes_encrypt(u8 *in, u8 *expkey, u8 *out) memcpy(out, state, sizeof(state)); } -void aes_decrypt(u8 *in, u8 *expkey, u8 *out) +void aes_decrypt(u32 key_len, u8 *in, u8 *expkey, u8 *out) { u8 state[AES_STATECOLS * 4]; - int round; + int round, aes_rounds; + + aes_rounds = aes_get_rounds(key_len); memcpy(state, in, sizeof(state)); add_round_key((u32 *)state, - (u32 *)expkey + AES_ROUNDS * AES_STATECOLS); + (u32 *)expkey + aes_rounds * AES_STATECOLS); inv_shift_rows(state); - for (round = AES_ROUNDS; round--; ) { + for (round = aes_rounds; round--; ) { add_round_key((u32 *)state, (u32 *)expkey + round * AES_STATECOLS); if (round) @@ -596,62 +627,62 @@ void aes_apply_cbc_chain_data(u8 *cbc_chain_data, u8 *src, u8 *dst) { int i; - for (i = 0; i < AES_KEY_LENGTH; i++) + for (i = 0; i < AES_BLOCK_LENGTH; i++) *dst++ = *src++ ^ *cbc_chain_data++; } -void aes_cbc_encrypt_blocks(u8 *key_exp, u8 *iv, u8 *src, u8 *dst, +void aes_cbc_encrypt_blocks(u32 key_len, u8 *key_exp, u8 *iv, u8 *src, u8 *dst, u32 num_aes_blocks) { - u8 tmp_data[AES_KEY_LENGTH]; + u8 tmp_data[AES_BLOCK_LENGTH]; u8 *cbc_chain_data = iv; 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); + debug_print_vector("AES Src", AES_BLOCK_LENGTH, src); /* Apply the chain data */ aes_apply_cbc_chain_data(cbc_chain_data, src, tmp_data); - debug_print_vector("AES Xor", AES_KEY_LENGTH, tmp_data); + debug_print_vector("AES Xor", AES_BLOCK_LENGTH, tmp_data); /* Encrypt the AES block */ - aes_encrypt(tmp_data, key_exp, dst); - debug_print_vector("AES Dst", AES_KEY_LENGTH, dst); + aes_encrypt(key_len, tmp_data, key_exp, dst); + debug_print_vector("AES Dst", AES_BLOCK_LENGTH, dst); /* Update pointers for next loop. */ cbc_chain_data = dst; - src += AES_KEY_LENGTH; - dst += AES_KEY_LENGTH; + src += AES_BLOCK_LENGTH; + dst += AES_BLOCK_LENGTH; } } -void aes_cbc_decrypt_blocks(u8 *key_exp, u8 *iv, u8 *src, u8 *dst, +void aes_cbc_decrypt_blocks(u32 key_len, u8 *key_exp, u8 *iv, u8 *src, u8 *dst, u32 num_aes_blocks) { - u8 tmp_data[AES_KEY_LENGTH], tmp_block[AES_KEY_LENGTH]; + u8 tmp_data[AES_BLOCK_LENGTH], tmp_block[AES_BLOCK_LENGTH]; /* Convenient array of 0's for IV */ - u8 cbc_chain_data[AES_KEY_LENGTH]; + u8 cbc_chain_data[AES_BLOCK_LENGTH]; u32 i; - memcpy(cbc_chain_data, iv, AES_KEY_LENGTH); + memcpy(cbc_chain_data, iv, AES_BLOCK_LENGTH); 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); + debug_print_vector("AES Src", AES_BLOCK_LENGTH, src); - memcpy(tmp_block, src, AES_KEY_LENGTH); + memcpy(tmp_block, src, AES_BLOCK_LENGTH); /* Decrypt the AES block */ - aes_decrypt(src, key_exp, tmp_data); - debug_print_vector("AES Xor", AES_KEY_LENGTH, tmp_data); + aes_decrypt(key_len, src, key_exp, tmp_data); + debug_print_vector("AES Xor", AES_BLOCK_LENGTH, tmp_data); /* Apply the chain data */ aes_apply_cbc_chain_data(cbc_chain_data, tmp_data, dst); - debug_print_vector("AES Dst", AES_KEY_LENGTH, dst); + debug_print_vector("AES Dst", AES_BLOCK_LENGTH, dst); /* Update pointers for next loop. */ - memcpy(cbc_chain_data, tmp_block, AES_KEY_LENGTH); - src += AES_KEY_LENGTH; - dst += AES_KEY_LENGTH; + memcpy(cbc_chain_data, tmp_block, AES_BLOCK_LENGTH); + src += AES_BLOCK_LENGTH; + dst += AES_BLOCK_LENGTH; } } diff --git a/lib/aes/Makefile b/lib/aes/Makefile new file mode 100644 index 0000000000..daed52a713 --- /dev/null +++ b/lib/aes/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (c) 2019, Softathome + +obj-$(CONFIG_$(SPL_)FIT_CIPHER) += aes-decrypt.o diff --git a/lib/aes/aes-decrypt.c b/lib/aes/aes-decrypt.c new file mode 100644 index 0000000000..345029fa78 --- /dev/null +++ b/lib/aes/aes-decrypt.c @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2019, softathome + */ + +#ifndef USE_HOSTCC +#include <common.h> +#include <malloc.h> +#endif +#include <image.h> +#include <uboot_aes.h> + +int image_aes_decrypt(struct image_cipher_info *info, + const void *cipher, size_t cipher_len, + void **data, size_t *size) +{ +#ifndef USE_HOSTCC + unsigned char key_exp[AES256_EXPAND_KEY_LENGTH]; + unsigned int aes_blocks, key_len = info->cipher->key_len; + + *data = malloc(cipher_len); + if (!*data) { + printf("Can't allocate memory to decrypt\n"); + return -ENOMEM; + } + *size = info->size_unciphered; + + memcpy(&key_exp[0], info->key, key_len); + + /* First we expand the key. */ + aes_expand_key((u8 *)info->key, key_len, key_exp); + + /* Calculate the number of AES blocks to encrypt. */ + aes_blocks = DIV_ROUND_UP(cipher_len, AES_BLOCK_LENGTH); + + aes_cbc_decrypt_blocks(key_len, key_exp, (u8 *)info->iv, + (u8 *)cipher, *data, aes_blocks); +#endif + + return 0; +} diff --git a/lib/aes/aes-encrypt.c b/lib/aes/aes-encrypt.c new file mode 100644 index 0000000000..de00a836f6 --- /dev/null +++ b/lib/aes/aes-encrypt.c @@ -0,0 +1,136 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2019,Softathome + */ +#include "mkimage.h" +#include <stdio.h> +#include <string.h> +#include <image.h> +#include <time.h> +#include <openssl/bn.h> +#include <openssl/rsa.h> +#include <openssl/pem.h> +#include <openssl/err.h> +#include <openssl/ssl.h> +#include <openssl/evp.h> +#include <openssl/engine.h> +#include <uboot_aes.h> + +#if OPENSSL_VERSION_NUMBER >= 0x10000000L +#define HAVE_ERR_REMOVE_THREAD_STATE +#endif + +int image_aes_encrypt(struct image_cipher_info *info, + unsigned char *data, int size, + unsigned char **cipher, int *cipher_len) +{ + EVP_CIPHER_CTX *ctx; + unsigned char *buf = NULL; + int buf_len, len, ret = 0; + + /* create and initialise the context */ + ctx = EVP_CIPHER_CTX_new(); + if (!ctx) { + printf("Can't create context\n"); + return -1; + } + + /* allocate a buffer for the result */ + buf = malloc(size + AES_BLOCK_LENGTH); + if (!buf) { + printf("Can't allocate memory to encrypt\n"); + ret = -1; + goto out; + } + + if (EVP_EncryptInit_ex(ctx, info->cipher->calculate_type(), + NULL, info->key, info->iv) != 1) { + printf("Can't init encryption\n"); + ret = -1; + goto out; + } + + if (EVP_EncryptUpdate(ctx, buf, &len, data, size) != 1) { + printf("Can't encrypt data\n"); + ret = -1; + goto out; + } + + buf_len = len; + + if (EVP_EncryptFinal_ex(ctx, buf + len, &len) != 1) { + printf("Can't finalise the encryption\n"); + ret = -1; + goto out; + } + + buf_len += len; + + *cipher = buf; + *cipher_len = buf_len; + + out: + EVP_CIPHER_CTX_free(ctx); + return ret; +} + +int image_aes_add_cipher_data(struct image_cipher_info *info, void *keydest) +{ + int parent, node; + char name[128]; + int ret = 0; + + /* Either create or overwrite the named cipher node */ + parent = fdt_subnode_offset(keydest, 0, FIT_CIPHER_NODENAME); + if (parent == -FDT_ERR_NOTFOUND) { + parent = fdt_add_subnode(keydest, 0, FIT_CIPHER_NODENAME); + if (parent < 0) { + ret = parent; + if (ret != -FDT_ERR_NOSPACE) { + fprintf(stderr, + "Couldn't create cipher node: %s\n", + fdt_strerror(parent)); + } + } + } + if (ret) + goto done; + + /* Either create or overwrite the named key node */ + snprintf(name, sizeof(name), "key-%s-%s-%s", + info->name, info->keyname, info->ivname); + node = fdt_subnode_offset(keydest, parent, name); + if (node == -FDT_ERR_NOTFOUND) { + node = fdt_add_subnode(keydest, parent, name); + if (node < 0) { + ret = node; + if (ret != -FDT_ERR_NOSPACE) { + fprintf(stderr, + "Could not create key subnode: %s\n", + fdt_strerror(node)); + } + } + } else if (node < 0) { + fprintf(stderr, "Cannot select keys parent: %s\n", + fdt_strerror(node)); + ret = node; + } + + if (!ret) + ret = fdt_setprop(keydest, node, "iv", + info->iv, info->cipher->iv_len); + + if (!ret) + ret = fdt_setprop(keydest, node, "key", + info->key, info->cipher->key_len); + + if (!ret) + ret = fdt_setprop_u32(keydest, node, "key-len", + info->cipher->key_len); + +done: + if (ret) + ret = ret == -FDT_ERR_NOSPACE ? -ENOSPC : -EIO; + + return ret; +} diff --git a/scripts/config_whitelist.txt b/scripts/config_whitelist.txt index cd154738a4..95c0ccc9d3 100644 --- a/scripts/config_whitelist.txt +++ b/scripts/config_whitelist.txt @@ -3777,8 +3777,6 @@ CONFIG_SYS_SCRATCH_VA CONFIG_SYS_SCSI_MAX_DEVICE CONFIG_SYS_SCSI_MAX_LUN CONFIG_SYS_SCSI_MAX_SCSI_ID -CONFIG_SYS_SDHC_CLK -CONFIG_SYS_SDHC_CLK_2_PLL CONFIG_SYS_SDIO0 CONFIG_SYS_SDIO0_MAX_CLK CONFIG_SYS_SDIO1 diff --git a/test/lib/Makefile b/test/lib/Makefile index 72d2ec74b5..230068d5a0 100644 --- a/test/lib/Makefile +++ b/test/lib/Makefile @@ -8,3 +8,4 @@ obj-y += lmb.o obj-y += string.o obj-$(CONFIG_ERRNO_STR) += test_errno_str.o obj-$(CONFIG_UT_LIB_ASN1) += asn1.o +obj-$(CONFIG_AES) += test_aes.o diff --git a/test/lib/test_aes.c b/test/lib/test_aes.c new file mode 100644 index 0000000000..b7b4b775df --- /dev/null +++ b/test/lib/test_aes.c @@ -0,0 +1,166 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2019 Philippe Reynes <philippe.reynes@softathome.com> + * + * Unit tests for aes functions + */ + +#include <common.h> +#include <command.h> +#include <hexdump.h> +#include <uboot_aes.h> +#include <test/lib.h> +#include <test/test.h> +#include <test/ut.h> + +#define TEST_AES_ONE_BLOCK 0 +#define TEST_AES_CBC_CHAIN 1 + +struct test_aes_s { + int key_len; + int key_exp_len; + int type; + int num_block; +}; + +static struct test_aes_s test_aes[] = { + { AES128_KEY_LENGTH, AES128_EXPAND_KEY_LENGTH, TEST_AES_ONE_BLOCK, 1 }, + { AES128_KEY_LENGTH, AES128_EXPAND_KEY_LENGTH, TEST_AES_CBC_CHAIN, 16 }, + { AES192_KEY_LENGTH, AES192_EXPAND_KEY_LENGTH, TEST_AES_ONE_BLOCK, 1 }, + { AES192_KEY_LENGTH, AES192_EXPAND_KEY_LENGTH, TEST_AES_CBC_CHAIN, 16 }, + { AES256_KEY_LENGTH, AES256_EXPAND_KEY_LENGTH, TEST_AES_ONE_BLOCK, 1 }, + { AES256_KEY_LENGTH, AES256_EXPAND_KEY_LENGTH, TEST_AES_CBC_CHAIN, 16 }, +}; + +static void rand_buf(u8 *buf, int size) +{ + int i; + + for (i = 0; i < size; i++) + buf[i] = rand() & 0xff; +} + +static int lib_test_aes_one_block(struct unit_test_state *uts, int key_len, + u8 *key_exp, u8 *iv, int num_block, + u8 *nocipher, u8 *ciphered, u8 *uncipher) +{ + aes_encrypt(key_len, nocipher, key_exp, ciphered); + aes_decrypt(key_len, ciphered, key_exp, uncipher); + + ut_asserteq_mem(nocipher, uncipher, AES_BLOCK_LENGTH); + + /* corrupt the expanded key */ + key_exp[0]++; + aes_decrypt(key_len, ciphered, key_exp, uncipher); + ut_assertf(memcmp(nocipher, uncipher, AES_BLOCK_LENGTH), + "nocipher and uncipher should be different\n"); + + return 0; +} + +static int lib_test_aes_cbc_chain(struct unit_test_state *uts, int key_len, + u8 *key_exp, u8 *iv, int num_block, + u8 *nocipher, u8 *ciphered, u8 *uncipher) +{ + aes_cbc_encrypt_blocks(key_len, key_exp, iv, + nocipher, ciphered, num_block); + aes_cbc_decrypt_blocks(key_len, key_exp, iv, + ciphered, uncipher, num_block); + + ut_asserteq_mem(nocipher, uncipher, num_block * AES_BLOCK_LENGTH); + + /* corrupt the expanded key */ + key_exp[0]++; + aes_cbc_decrypt_blocks(key_len, key_exp, iv, + ciphered, uncipher, num_block); + ut_assertf(memcmp(nocipher, uncipher, num_block * AES_BLOCK_LENGTH), + "nocipher and uncipher should be different\n"); + + return 0; +} + +static int _lib_test_aes_run(struct unit_test_state *uts, int key_len, + int key_exp_len, int type, int num_block) +{ + u8 *key, *key_exp, *iv; + u8 *nocipher, *ciphered, *uncipher; + int ret; + + /* Allocate all the buffer */ + key = malloc(key_len); + ut_assertnonnull(key); + key_exp = malloc(key_exp_len); + ut_assertnonnull(key_exp); + iv = malloc(AES_BLOCK_LENGTH); + ut_assertnonnull(iv); + nocipher = malloc(num_block * AES_BLOCK_LENGTH); + ut_assertnonnull(nocipher); + ciphered = malloc((num_block + 1) * AES_BLOCK_LENGTH); + ut_assertnonnull(ciphered); + uncipher = malloc((num_block + 1) * AES_BLOCK_LENGTH); + ut_assertnonnull(uncipher); + + /* Initialize all buffer */ + rand_buf(key, key_len); + rand_buf(iv, AES_BLOCK_LENGTH); + rand_buf(nocipher, num_block * AES_BLOCK_LENGTH); + memset(ciphered, 0, (num_block + 1) * AES_BLOCK_LENGTH); + memset(uncipher, 0, (num_block + 1) * AES_BLOCK_LENGTH); + + /* Expand the key */ + aes_expand_key(key, key_len, key_exp); + + /* Encrypt and decrypt */ + switch (type) { + case TEST_AES_ONE_BLOCK: + ret = lib_test_aes_one_block(uts, key_len, key_exp, iv, + num_block, nocipher, + ciphered, uncipher); + break; + case TEST_AES_CBC_CHAIN: + ret = lib_test_aes_cbc_chain(uts, key_len, key_exp, iv, + num_block, nocipher, + ciphered, uncipher); + break; + default: + printf("%s: unknown type (type=%d)\n", __func__, type); + ret = -1; + }; + + /* Free all the data */ + free(key); + free(key_exp); + free(iv); + free(nocipher); + free(ciphered); + free(uncipher); + + return ret; +} + +static int lib_test_aes_run(struct unit_test_state *uts, + struct test_aes_s *test) +{ + int key_len = test->key_len; + int key_exp_len = test->key_exp_len; + int type = test->type; + int num_block = test->num_block; + + return _lib_test_aes_run(uts, key_len, key_exp_len, + type, num_block); +} + +static int lib_test_aes(struct unit_test_state *uts) +{ + int i, ret = 0; + + for (i = 0; i < ARRAY_SIZE(test_aes); i++) { + ret = lib_test_aes_run(uts, &test_aes[i]); + if (ret) + break; + } + + return ret; +} + +LIB_TEST(lib_test_aes, 0); diff --git a/tools/Makefile b/tools/Makefile index 345bc84e48..99be724b82 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -59,6 +59,7 @@ hostprogs-$(CONFIG_CMD_BOOTEFI_SELFTEST) += file2include FIT_OBJS-$(CONFIG_FIT) := fit_common.o fit_image.o image-host.o common/image-fit.o FIT_SIG_OBJS-$(CONFIG_FIT_SIGNATURE) := common/image-sig.o +FIT_CIPHER_OBJS-$(CONFIG_FIT_CIPHER) := common/image-cipher.o # The following files are synced with upstream DTC. # Use synced versions from scripts/dtc/libfdt/. @@ -75,6 +76,9 @@ RSA_OBJS-$(CONFIG_FIT_SIGNATURE) := $(addprefix lib/rsa/, \ rsa-sign.o rsa-verify.o rsa-checksum.o \ rsa-mod-exp.o) +AES_OBJS-$(CONFIG_FIT_CIPHER) := $(addprefix lib/aes/, \ + aes-encrypt.o aes-decrypt.o) + ROCKCHIP_OBS = lib/rc4.o rkcommon.o rkimage.o rksd.o rkspi.o # common objs for dumpimage and mkimage @@ -82,6 +86,7 @@ dumpimage-mkimage-objs := aisimage.o \ atmelimage.o \ $(FIT_OBJS-y) \ $(FIT_SIG_OBJS-y) \ + $(FIT_CIPHER_OBJS-y) \ common/bootm.o \ lib/crc32.o \ default_image.o \ @@ -116,7 +121,8 @@ dumpimage-mkimage-objs := aisimage.o \ gpimage.o \ gpimage-common.o \ mtk_image.o \ - $(RSA_OBJS-y) + $(RSA_OBJS-y) \ + $(AES_OBJS-y) dumpimage-objs := $(dumpimage-mkimage-objs) dumpimage.o mkimage-objs := $(dumpimage-mkimage-objs) mkimage.o @@ -137,6 +143,12 @@ HOST_EXTRACFLAGS += -DCONFIG_FIT_SIGNATURE HOST_EXTRACFLAGS += -DCONFIG_FIT_SIGNATURE_MAX_SIZE=$(CONFIG_FIT_SIGNATURE_MAX_SIZE) endif +ifdef CONFIG_FIT_CIPHER +# This affects include/image.h, but including the board config file +# is tricky, so manually define this options here. +HOST_EXTRACFLAGS += -DCONFIG_FIT_CIPHER +endif + ifdef CONFIG_SYS_U_BOOT_OFFS HOSTCFLAGS_kwbimage.o += -DCONFIG_SYS_U_BOOT_OFFS=$(CONFIG_SYS_U_BOOT_OFFS) endif diff --git a/tools/fit_image.c b/tools/fit_image.c index 6aa4b1c733..dd61a816c9 100644 --- a/tools/fit_image.c +++ b/tools/fit_image.c @@ -59,6 +59,14 @@ static int fit_add_file_data(struct image_tool_params *params, size_t size_inc, } if (!ret) { + ret = fit_cipher_data(params->keydir, dest_blob, ptr, + params->comment, + params->require_keys, + params->engine_id, + params->cmdname); + } + + if (!ret) { ret = fit_add_verification_data(params->keydir, dest_blob, ptr, params->comment, params->require_keys, @@ -74,7 +82,6 @@ static int fit_add_file_data(struct image_tool_params *params, size_t size_inc, err_keydest: munmap(ptr, sbuf.st_size); close(tfd); - return ret; } @@ -621,6 +628,62 @@ err_no_fd: return ret; } +static int copyfile(const char *src, const char *dst) +{ + int fd_src = -1, fd_dst = -1; + void *buf = NULL; + ssize_t size; + size_t count; + int ret = -1; + + fd_src = open(src, O_RDONLY); + if (fd_src < 0) { + printf("Can't open file %s (%s)\n", src, strerror(errno)); + goto out; + } + + fd_dst = open(dst, O_WRONLY | O_CREAT, 0700); + if (fd_dst < 0) { + printf("Can't open file %s (%s)\n", dst, strerror(errno)); + goto out; + } + + buf = malloc(512); + if (!buf) { + printf("Can't allocate buffer to copy file\n"); + goto out; + } + + while (1) { + size = read(fd_src, buf, 512); + if (size < 0) { + printf("Can't read file %s\n", src); + goto out; + } + if (!size) + break; + + count = size; + size = write(fd_dst, buf, count); + if (size < 0) { + printf("Can't write file %s\n", dst); + goto out; + } + } + + ret = 0; + + out: + if (fd_src >= 0) + close(fd_src); + if (fd_dst >= 0) + close(fd_dst); + if (buf) + free(buf); + + return ret; +} + /** * fit_handle_file - main FIT file processing function * @@ -636,6 +699,7 @@ err_no_fd: static int fit_handle_file(struct image_tool_params *params) { char tmpfile[MKIMAGE_MAX_TMPFILE_LEN]; + char bakfile[MKIMAGE_MAX_TMPFILE_LEN + 4] = {0}; char cmd[MKIMAGE_MAX_DTC_CMDLINE_LEN]; size_t size_inc; int ret; @@ -670,6 +734,7 @@ static int fit_handle_file(struct image_tool_params *params) snprintf(cmd, sizeof(cmd), "cp \"%s\" \"%s\"", params->imagefile, tmpfile); } + if (*cmd && system(cmd) == -1) { fprintf (stderr, "%s: system(%s) failed: %s\n", params->cmdname, cmd, strerror(errno)); @@ -682,6 +747,14 @@ static int fit_handle_file(struct image_tool_params *params) goto err_system; /* + * Copy the tmpfile to bakfile, then in the following loop + * we copy bakfile to tmpfile. So we always start from the + * beginning. + */ + sprintf(bakfile, "%s%s", tmpfile, ".bak"); + rename(tmpfile, bakfile); + + /* * Set hashes for images in the blob. Unfortunately we may need more * space in either FDT, so keep trying until we succeed. * @@ -692,6 +765,11 @@ static int fit_handle_file(struct image_tool_params *params) * steps of this loop is enough to sign with several keys. */ for (size_inc = 0; size_inc < 64 * 1024; size_inc += 1024) { + if (copyfile(bakfile, tmpfile) < 0) { + printf("Can't copy %s to %s\n", bakfile, tmpfile); + ret = -EIO; + break; + } ret = fit_add_file_data(params, size_inc, tmpfile); if (!ret || ret != -ENOSPC) break; @@ -715,13 +793,16 @@ static int fit_handle_file(struct image_tool_params *params) params->cmdname, tmpfile, params->imagefile, strerror (errno)); unlink (tmpfile); + unlink(bakfile); unlink (params->imagefile); return EXIT_FAILURE; } + unlink(bakfile); return EXIT_SUCCESS; err_system: unlink(tmpfile); + unlink(bakfile); return -1; } diff --git a/tools/image-host.c b/tools/image-host.c index 88b329502c..9483561bfa 100644 --- a/tools/image-host.c +++ b/tools/image-host.c @@ -12,6 +12,7 @@ #include <bootm.h> #include <image.h> #include <version.h> +#include <uboot_aes.h> /** * fit_set_hash_value - set hash value in requested has node @@ -268,6 +269,262 @@ static int fit_image_process_sig(const char *keydir, void *keydest, return 0; } +static int fit_image_read_data(char *filename, unsigned char *data, + int expected_size) +{ + struct stat sbuf; + int fd, ret = -1; + ssize_t n; + + /* Open file */ + fd = open(filename, O_RDONLY | O_BINARY); + if (fd < 0) { + printf("Can't open file %s (err=%d => %s)\n", + filename, errno, strerror(errno)); + return -1; + } + + /* Compute file size */ + if (fstat(fd, &sbuf) < 0) { + printf("Can't fstat file %s (err=%d => %s)\n", + filename, errno, strerror(errno)); + goto err; + } + + /* Check file size */ + if (sbuf.st_size != expected_size) { + printf("File %s don't have the expected size (size=%ld, expected=%d)\n", + filename, sbuf.st_size, expected_size); + goto err; + } + + /* Read data */ + n = read(fd, data, sbuf.st_size); + if (n < 0) { + printf("Can't read file %s (err=%d => %s)\n", + filename, errno, strerror(errno)); + goto err; + } + + /* Check that we have read all the file */ + if (n != sbuf.st_size) { + printf("Can't read all file %s (read %ld bytes, expexted %ld)\n", + filename, n, sbuf.st_size); + goto err; + } + + ret = 0; + +err: + close(fd); + return ret; +} + +static int fit_image_setup_cipher(struct image_cipher_info *info, + const char *keydir, void *fit, + const char *image_name, int image_noffset, + const char *node_name, int noffset) +{ + char *algo_name; + char filename[128]; + int ret = -1; + + if (fit_image_cipher_get_algo(fit, noffset, &algo_name)) { + printf("Can't get algo name for cipher '%s' in image '%s'\n", + node_name, image_name); + goto out; + } + + info->keydir = keydir; + + /* Read the key name */ + info->keyname = fdt_getprop(fit, noffset, "key-name-hint", NULL); + if (!info->keyname) { + printf("Can't get key name for cipher '%s' in image '%s'\n", + node_name, image_name); + goto out; + } + + /* Read the IV name */ + info->ivname = fdt_getprop(fit, noffset, "iv-name-hint", NULL); + if (!info->ivname) { + printf("Can't get iv name for cipher '%s' in image '%s'\n", + node_name, image_name); + goto out; + } + + info->fit = fit; + info->node_noffset = noffset; + info->name = algo_name; + + info->cipher = image_get_cipher_algo(algo_name); + if (!info->cipher) { + printf("Can't get algo for cipher '%s'\n", image_name); + goto out; + } + + /* Read the key in the file */ + snprintf(filename, sizeof(filename), "%s/%s%s", + info->keydir, info->keyname, ".bin"); + info->key = malloc(info->cipher->key_len); + if (!info->key) { + printf("Can't allocate memory for key\n"); + ret = -1; + goto out; + } + ret = fit_image_read_data(filename, (unsigned char *)info->key, + info->cipher->key_len); + if (ret < 0) + goto out; + + /* Read the IV in the file */ + snprintf(filename, sizeof(filename), "%s/%s%s", + info->keydir, info->ivname, ".bin"); + info->iv = malloc(info->cipher->iv_len); + if (!info->iv) { + printf("Can't allocate memory for iv\n"); + ret = -1; + goto out; + } + ret = fit_image_read_data(filename, (unsigned char *)info->iv, + info->cipher->iv_len); + + out: + return ret; +} + +int fit_image_write_cipher(void *fit, int image_noffset, int noffset, + const void *data, size_t size, + unsigned char *data_ciphered, int data_ciphered_len) +{ + int ret = -1; + + /* Remove unciphered data */ + ret = fdt_delprop(fit, image_noffset, FIT_DATA_PROP); + if (ret) { + printf("Can't remove data (err = %d)\n", ret); + goto out; + } + + /* Add ciphered data */ + ret = fdt_setprop(fit, image_noffset, FIT_DATA_PROP, + data_ciphered, data_ciphered_len); + if (ret) { + printf("Can't add ciphered data (err = %d)\n", ret); + goto out; + } + + /* add non ciphered data size */ + ret = fdt_setprop_u32(fit, image_noffset, "data-size-unciphered", size); + if (ret) { + printf("Can't add unciphered data size (err = %d)\n", ret); + goto out; + } + + out: + return ret; +} + +static int +fit_image_process_cipher(const char *keydir, void *keydest, void *fit, + const char *image_name, int image_noffset, + const char *node_name, int node_noffset, + const void *data, size_t size, + const char *cmdname) +{ + struct image_cipher_info info; + unsigned char *data_ciphered = NULL; + int data_ciphered_len; + int ret; + + memset(&info, 0, sizeof(info)); + + ret = fit_image_setup_cipher(&info, keydir, fit, image_name, + image_noffset, node_name, node_noffset); + if (ret) + goto out; + + ret = info.cipher->encrypt(&info, data, size, + &data_ciphered, &data_ciphered_len); + if (ret) + goto out; + + /* + * Write the public key into the supplied FDT file; this might fail + * several times, since we try signing with successively increasing + * size values + */ + if (keydest) { + ret = info.cipher->add_cipher_data(&info, keydest); + if (ret) { + printf("Failed to add verification data for cipher '%s' in image '%s'\n", + info.keyname, image_name); + goto out; + } + } + + ret = fit_image_write_cipher(fit, image_noffset, node_noffset, + data, size, + data_ciphered, data_ciphered_len); + + out: + free(data_ciphered); + free((void *)info.key); + free((void *)info.iv); + return ret; +} + +int fit_image_cipher_data(const char *keydir, void *keydest, + void *fit, int image_noffset, const char *comment, + int require_keys, const char *engine_id, + const char *cmdname) +{ + const char *image_name; + const void *data; + size_t size; + int node_noffset; + + /* Get image name */ + image_name = fit_get_name(fit, image_noffset, NULL); + if (!image_name) { + printf("Can't get image name\n"); + return -1; + } + + /* Get image data and data length */ + if (fit_image_get_data(fit, image_noffset, &data, &size)) { + printf("Can't get image data/size\n"); + return -1; + } + + /* Process all hash subnodes of the component image node */ + for (node_noffset = fdt_first_subnode(fit, image_noffset); + node_noffset >= 0; + node_noffset = fdt_next_subnode(fit, node_noffset)) { + const char *node_name; + int ret = 0; + + node_name = fit_get_name(fit, node_noffset, NULL); + if (!node_name) { + printf("Can't get node name\n"); + return -1; + } + + if (IMAGE_ENABLE_ENCRYPT && keydir && + !strncmp(node_name, FIT_CIPHER_NODENAME, + strlen(FIT_CIPHER_NODENAME))) + ret = fit_image_process_cipher(keydir, keydest, + fit, image_name, + image_noffset, + node_name, node_noffset, + data, size, cmdname); + if (ret) + return ret; + } + + return 0; +} + /** * fit_image_add_verification_data() - calculate/set verig. data for image node * @@ -675,6 +932,41 @@ static int fit_config_add_verification_data(const char *keydir, void *keydest, return 0; } +int fit_cipher_data(const char *keydir, void *keydest, void *fit, + const char *comment, int require_keys, + const char *engine_id, const char *cmdname) +{ + int images_noffset; + int noffset; + int ret; + + /* Find images parent node offset */ + images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH); + if (images_noffset < 0) { + printf("Can't find images parent node '%s' (%s)\n", + FIT_IMAGES_PATH, fdt_strerror(images_noffset)); + return images_noffset; + } + + /* Process its subnodes, print out component images details */ + for (noffset = fdt_first_subnode(fit, images_noffset); + noffset >= 0; + noffset = fdt_next_subnode(fit, noffset)) { + /* + * Direct child node of the images parent node, + * i.e. component image node. + */ + ret = fit_image_cipher_data(keydir, keydest, + fit, noffset, comment, + require_keys, engine_id, + cmdname); + if (ret) + return ret; + } + + return 0; +} + int fit_add_verification_data(const char *keydir, void *keydest, void *fit, const char *comment, int require_keys, const char *engine_id, const char *cmdname) |