Merge branch 'master' of git://git.denx.de/u-boot

Signed-off-by: Stefano Babic <sbabic@denx.de>
This commit is contained in:
Stefano Babic 2020-01-20 15:35:43 +01:00
commit 0e78c9181c
42 changed files with 1361 additions and 262 deletions

View File

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

View File

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

View File

@ -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;
#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
#if defined(CONFIG_ARCH_LS2080A) || defined(CONFIG_ARCH_LS1088A)
gd->arch.sdhc_clk = sys_info.freq_cga_m2;
#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;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

167
common/image-cipher.c Normal file
View File

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

View File

@ -947,6 +947,31 @@ int fit_image_get_data_size(const void *fit, int noffset, int *data_size)
return 0;
}
/**
* 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
@ -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);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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(&regs->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(&regs->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(&regs->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;

View File

@ -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(&regs->sysctl);
if (enable)
value |= SYSCTL_CKEN;
else
value &= ~SYSCTL_CKEN;
esdhc_write32(&regs->sysctl, value);
time_out = 20;
value = PRSSTAT_SDSTB;
while (!(esdhc_read32(&regs->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(&regs->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

View File

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

View File

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

View File

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

View File

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

View File

@ -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", \

View File

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

44
include/u-boot/aes.h Normal file
View File

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

View File

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

View File

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

111
lib/aes.c
View File

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

5
lib/aes/Makefile Normal file
View File

@ -0,0 +1,5 @@
# SPDX-License-Identifier: GPL-2.0+
#
# Copyright (c) 2019, Softathome
obj-$(CONFIG_$(SPL_)FIT_CIPHER) += aes-decrypt.o

41
lib/aes/aes-decrypt.c Normal file
View File

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

136
lib/aes/aes-encrypt.c Normal file
View File

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

View File

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

View File

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

166
test/lib/test_aes.c Normal file
View File

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

View File

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

View File

@ -58,6 +58,14 @@ static int fit_add_file_data(struct image_tool_params *params, size_t size_inc,
ret = fit_set_timestamp(ptr, 0, time);
}
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,
@ -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));
@ -681,6 +746,14 @@ static int fit_handle_file(struct image_tool_params *params)
if (ret)
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;
}

View File

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