X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=board%2Ffreescale%2Fcommon%2Ffsl_validate.c;h=3424d49208fe2f1c6c3ddc386ebab0bff070aced;hb=6cc04547cb3bbd3a3d78947f200acbae19e3c67f;hp=5283648a4d090df468b3487603ce542a109aa396;hpb=62f3aaf89d01bdc9ff0e67d92f3bf085143edf8c;p=platform%2Fkernel%2Fu-boot.git diff --git a/board/freescale/common/fsl_validate.c b/board/freescale/common/fsl_validate.c index 5283648..3424d49 100644 --- a/board/freescale/common/fsl_validate.c +++ b/board/freescale/common/fsl_validate.c @@ -1,29 +1,39 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright 2015 Freescale Semiconductor, Inc. - * - * SPDX-License-Identifier: GPL-2.0+ + * Copyright 2021-2022 NXP */ #include +#include #include #include #include #include #include +#include #include -#include #include #include #include -#ifndef CONFIG_MPC85xx +#ifdef CONFIG_ARCH_LS1021A #include #endif +#include #define SHA256_BITS 256 #define SHA256_BYTES (256/8) #define SHA256_NIBBLES (256/4) #define NUM_HEX_CHARS (sizeof(ulong) * 2) +#define CHECK_KEY_LEN(key_len) (((key_len) == 2 * KEY_SIZE_BYTES / 4) || \ + ((key_len) == 2 * KEY_SIZE_BYTES / 2) || \ + ((key_len) == 2 * KEY_SIZE_BYTES)) +#if defined(CONFIG_FSL_ISBC_KEY_EXT) +/* Global data structure */ +static struct fsl_secboot_glb glb; +#endif + /* This array contains DER value for SHA-256 */ static const u8 hash_identifier[] = { 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, @@ -31,7 +41,13 @@ static const u8 hash_identifier[] = { 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, }; static u8 hash_val[SHA256_BYTES]; + +#ifdef CONFIG_ESBC_HDR_LS +/* New Barker Code for LS ESBC Header */ +static const u8 barker_code[ESBC_BARKER_LEN] = { 0x12, 0x19, 0x20, 0x01 }; +#else static const u8 barker_code[ESBC_BARKER_LEN] = { 0x68, 0x39, 0x27, 0x81 }; +#endif void branch_to_self(void) __attribute__ ((noreturn)); @@ -50,7 +66,7 @@ self: #if defined(CONFIG_FSL_ISBC_KEY_EXT) static u32 check_ie(struct fsl_secboot_img_priv *img) { - if (img->hdr.ie_flag) + if (img->hdr.ie_flag & IE_FLAG_MASK) return 1; return 0; @@ -63,12 +79,14 @@ static u32 check_ie(struct fsl_secboot_img_priv *img) * address */ #if defined(CONFIG_MPC85xx) -int get_csf_base_addr(ulong *csf_addr, ulong *flash_base_addr) +#include + +int get_csf_base_addr(u32 *csf_addr, u32 *flash_base_addr) { - struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); + struct ccsr_gur __iomem *gur = (void *)(CFG_SYS_MPC85xx_GUTS_ADDR); u32 csf_hdr_addr = in_be32(&gur->scratchrw[0]); u32 csf_flash_offset = csf_hdr_addr & ~(CONFIG_SYS_PBI_FLASH_BASE); - ulong flash_addr, addr; + u32 flash_addr, addr; int found = 0; int i = 0; @@ -76,7 +94,7 @@ int get_csf_base_addr(ulong *csf_addr, ulong *flash_base_addr) flash_addr = flash_info[i].start[0]; addr = flash_info[i].start[0] + csf_flash_offset; if (memcmp((u8 *)addr, barker_code, ESBC_BARKER_LEN) == 0) { - debug("Barker found on addr %lx\n", addr); + debug("Barker found on addr %x\n", addr); found = 1; break; } @@ -94,12 +112,13 @@ int get_csf_base_addr(ulong *csf_addr, ulong *flash_base_addr) /* For platforms like LS1020, correct flash address is present in * the header. So the function reqturns flash base address as 0 */ -int get_csf_base_addr(ulong *csf_addr, ulong *flash_base_addr) +int get_csf_base_addr(u32 *csf_addr, u32 *flash_base_addr) { - struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); + struct ccsr_gur __iomem *gur = (void *)(CFG_SYS_FSL_GUTS_ADDR); u32 csf_hdr_addr = in_be32(&gur->scratchrw[0]); - if (memcmp((u8 *)csf_hdr_addr, barker_code, ESBC_BARKER_LEN)) + if (memcmp((u8 *)(uintptr_t)csf_hdr_addr, + barker_code, ESBC_BARKER_LEN)) return -1; *csf_addr = csf_hdr_addr; @@ -108,16 +127,30 @@ int get_csf_base_addr(ulong *csf_addr, ulong *flash_base_addr) } #endif -static int get_ie_info_addr(ulong *ie_addr) +#if defined(CONFIG_ESBC_HDR_LS) +static int get_ie_info_addr(uintptr_t *ie_addr) +{ + struct ccsr_gur __iomem *gur = (void *)(CFG_SYS_FSL_GUTS_ADDR); + /* For LS-CH3, the address of IE Table is + * stated in Scratch13 and scratch14 of DCFG. + * Bootrom validates this table while validating uboot. + * DCFG is LE*/ + *ie_addr = in_le32(&gur->scratchrw[SCRATCH_IE_HIGH_ADR - 1]); + *ie_addr = *ie_addr << 32; + *ie_addr |= in_le32(&gur->scratchrw[SCRATCH_IE_LOW_ADR - 1]); + return 0; +} +#else /* CONFIG_ESBC_HDR_LS */ +static int get_ie_info_addr(uintptr_t *ie_addr) { struct fsl_secboot_img_hdr *hdr; struct fsl_secboot_sg_table *sg_tbl; - ulong flash_base_addr, csf_addr; + u32 flash_base_addr, csf_addr; if (get_csf_base_addr(&csf_addr, &flash_base_addr)) return -1; - hdr = (struct fsl_secboot_img_hdr *)csf_addr; + hdr = (struct fsl_secboot_img_hdr *)(uintptr_t)csf_addr; /* For SoC's with Trust Architecture v1 with corenet bus * the sg table field in CSF header has absolute address @@ -127,35 +160,44 @@ static int get_ie_info_addr(ulong *ie_addr) */ #if defined(CONFIG_FSL_TRUST_ARCH_v1) && defined(CONFIG_FSL_CORENET) sg_tbl = (struct fsl_secboot_sg_table *) - (((ulong)hdr->psgtable & ~(CONFIG_SYS_PBI_FLASH_BASE)) + + (((u32)hdr->psgtable & ~(CONFIG_SYS_PBI_FLASH_BASE)) + flash_base_addr); #else - sg_tbl = (struct fsl_secboot_sg_table *)(csf_addr + - (ulong)hdr->psgtable); + sg_tbl = (struct fsl_secboot_sg_table *)(uintptr_t)(csf_addr + + (u32)hdr->psgtable); #endif /* IE Key Table is the first entry in the SG Table */ #if defined(CONFIG_MPC85xx) - *ie_addr = (sg_tbl->src_addr & ~(CONFIG_SYS_PBI_FLASH_BASE)) + - flash_base_addr; + *ie_addr = (uintptr_t)((sg_tbl->src_addr & + ~(CONFIG_SYS_PBI_FLASH_BASE)) + + flash_base_addr); #else - *ie_addr = sg_tbl->src_addr; + *ie_addr = (uintptr_t)sg_tbl->src_addr; #endif debug("IE Table address is %lx\n", *ie_addr); return 0; } - +#endif /* CONFIG_ESBC_HDR_LS */ #endif #ifdef CONFIG_KEY_REVOCATION /* This function checks srk_table_flag in header and set/reset srk_flag.*/ static u32 check_srk(struct fsl_secboot_img_priv *img) { +#ifdef CONFIG_ESBC_HDR_LS + /* In LS, No SRK Flag as SRK is always present if IE not present*/ +#if defined(CONFIG_FSL_ISBC_KEY_EXT) + return !check_ie(img); +#endif + return 1; +#else if (img->hdr.len_kr.srk_table_flag & SRK_FLAG) return 1; return 0; +#endif } /* This function returns ospr's key_revoc values.*/ @@ -178,20 +220,114 @@ static u32 is_key_revoked(u32 keynum, u32 rev_flag) return 0; } -/* It validates srk_table key lengths.*/ -static u32 validate_srk_tbl(struct srk_table *tbl, u32 num_entries) +/* It read validates srk_table key lengths.*/ +static u32 read_validate_srk_tbl(struct fsl_secboot_img_priv *img) { int i = 0; - for (i = 0; i < num_entries; i++) { - if (!((tbl[i].key_len == 2 * KEY_SIZE_BYTES/4) || - (tbl[i].key_len == 2 * KEY_SIZE_BYTES/2) || - (tbl[i].key_len == 2 * KEY_SIZE_BYTES))) + u32 ret, key_num, key_revoc_flag, size; + struct fsl_secboot_img_hdr *hdr = &img->hdr; + void *esbc = (u8 *)(uintptr_t)img->ehdrloc; + + if ((hdr->len_kr.num_srk == 0) || + (hdr->len_kr.num_srk > MAX_KEY_ENTRIES)) + return ERROR_ESBC_CLIENT_HEADER_INVALID_SRK_NUM_ENTRY; + + key_num = hdr->len_kr.srk_sel; + if (key_num == 0 || key_num > hdr->len_kr.num_srk) + return ERROR_ESBC_CLIENT_HEADER_INVALID_KEY_NUM; + + /* Get revoc key from sfp */ + key_revoc_flag = get_key_revoc(); + ret = is_key_revoked(key_num, key_revoc_flag); + if (ret) + return ERROR_ESBC_CLIENT_HEADER_KEY_REVOKED; + + size = hdr->len_kr.num_srk * sizeof(struct srk_table); + + memcpy(&img->srk_tbl, esbc + hdr->srk_tbl_off, size); + + for (i = 0; i < hdr->len_kr.num_srk; i++) { + if (!CHECK_KEY_LEN(img->srk_tbl[i].key_len)) return ERROR_ESBC_CLIENT_HEADER_INV_SRK_ENTRY_KEYLEN; } + + img->key_len = img->srk_tbl[key_num - 1].key_len; + + memcpy(&img->img_key, &(img->srk_tbl[key_num - 1].pkey), + img->key_len); + return 0; } #endif +#ifndef CONFIG_ESBC_HDR_LS +static u32 read_validate_single_key(struct fsl_secboot_img_priv *img) +{ + struct fsl_secboot_img_hdr *hdr = &img->hdr; + void *esbc = (u8 *)(uintptr_t)img->ehdrloc; + + /* check key length */ + if (!CHECK_KEY_LEN(hdr->key_len)) + return ERROR_ESBC_CLIENT_HEADER_KEY_LEN; + + memcpy(&img->img_key, esbc + hdr->pkey, hdr->key_len); + + img->key_len = hdr->key_len; + + return 0; +} +#endif /* CONFIG_ESBC_HDR_LS */ + +#if defined(CONFIG_FSL_ISBC_KEY_EXT) + +static void install_ie_tbl(uintptr_t ie_tbl_addr, + struct fsl_secboot_img_priv *img) +{ + /* Copy IE tbl to Global Data */ + memcpy(&glb.ie_tbl, (u8 *)ie_tbl_addr, sizeof(struct ie_key_info)); + img->ie_addr = (uintptr_t)&glb.ie_tbl; + glb.ie_addr = img->ie_addr; +} + +static u32 read_validate_ie_tbl(struct fsl_secboot_img_priv *img) +{ + struct fsl_secboot_img_hdr *hdr = &img->hdr; + u32 ie_key_len, ie_revoc_flag, ie_num; + struct ie_key_info *ie_info; + + if (!img->ie_addr) { + if (get_ie_info_addr(&img->ie_addr)) + return ERROR_IE_TABLE_NOT_FOUND; + else + install_ie_tbl(img->ie_addr, img); + } + + ie_info = (struct ie_key_info *)(uintptr_t)img->ie_addr; + if (ie_info->num_keys == 0 || ie_info->num_keys > 32) + return ERROR_ESBC_CLIENT_HEADER_INVALID_IE_NUM_ENTRY; + + ie_num = hdr->ie_key_sel; + if (ie_num == 0 || ie_num > ie_info->num_keys) + return ERROR_ESBC_CLIENT_HEADER_INVALID_IE_KEY_NUM; + + ie_revoc_flag = ie_info->key_revok; + if ((u32)(1 << (ie_num - 1)) & ie_revoc_flag) + return ERROR_ESBC_CLIENT_HEADER_IE_KEY_REVOKED; + + ie_key_len = ie_info->ie_key_tbl[ie_num - 1].key_len; + + if (!CHECK_KEY_LEN(ie_key_len)) + return ERROR_ESBC_CLIENT_HEADER_INV_IE_ENTRY_KEYLEN; + + memcpy(&img->img_key, &(ie_info->ie_key_tbl[ie_num - 1].pkey), + ie_key_len); + + img->key_len = ie_key_len; + return 0; +} +#endif + + /* This function return length of public key.*/ static inline u32 get_key_len(struct fsl_secboot_img_priv *img) { @@ -206,30 +342,20 @@ static inline u32 get_key_len(struct fsl_secboot_img_priv *img) */ static void fsl_secboot_header_verification_failure(void) { - struct ccsr_sec_mon_regs *sec_mon_regs = (void *) - (CONFIG_SYS_SEC_MON_ADDR); struct ccsr_sfp_regs *sfp_regs = (void *)(CONFIG_SYS_SFP_ADDR); - u32 sts = sec_mon_in32(&sec_mon_regs->hp_stat); /* 29th bit of OSPR is ITS */ u32 its = sfp_in32(&sfp_regs->ospr) >> 2; - /* - * Read the SEC_MON status register - * Read SSM_ST field - */ - sts = sec_mon_in32(&sec_mon_regs->hp_stat); - if ((sts & HPSR_SSM_ST_MASK) == HPSR_SSM_ST_TRUST) { - if (its == 1) - change_sec_mon_state(HPSR_SSM_ST_TRUST, - HPSR_SSM_ST_SOFT_FAIL); - else - change_sec_mon_state(HPSR_SSM_ST_TRUST, - HPSR_SSM_ST_NON_SECURE); - } + if (its == 1) + set_sec_mon_state(HPSR_SSM_ST_SOFT_FAIL); + else + set_sec_mon_state(HPSR_SSM_ST_NON_SECURE); printf("Generating reset request\n"); do_reset(NULL, 0, 0, NULL); + /* If reset doesn't coocur, halt execution */ + do_esbc_halt(NULL, 0, 0, NULL); } /* @@ -241,29 +367,20 @@ static void fsl_secboot_header_verification_failure(void) */ static void fsl_secboot_image_verification_failure(void) { - struct ccsr_sec_mon_regs *sec_mon_regs = (void *) - (CONFIG_SYS_SEC_MON_ADDR); struct ccsr_sfp_regs *sfp_regs = (void *)(CONFIG_SYS_SFP_ADDR); - u32 sts = sec_mon_in32(&sec_mon_regs->hp_stat); - u32 its = sfp_in32(&sfp_regs->ospr) & ITS_MASK >> ITS_BIT; + u32 its = (sfp_in32(&sfp_regs->ospr) & ITS_MASK) >> ITS_BIT; - /* - * Read the SEC_MON status register - * Read SSM_ST field - */ - sts = sec_mon_in32(&sec_mon_regs->hp_stat); - if ((sts & HPSR_SSM_ST_MASK) == HPSR_SSM_ST_TRUST) { - if (its == 1) { - change_sec_mon_state(HPSR_SSM_ST_TRUST, - HPSR_SSM_ST_SOFT_FAIL); - - printf("Generating reset request\n"); - do_reset(NULL, 0, 0, NULL); - } else { - change_sec_mon_state(HPSR_SSM_ST_TRUST, - HPSR_SSM_ST_NON_SECURE); - } + if (its == 1) { + set_sec_mon_state(HPSR_SSM_ST_SOFT_FAIL); + + printf("Generating reset request\n"); + do_reset(NULL, 0, 0, NULL); + /* If reset doesn't coocur, halt execution */ + do_esbc_halt(NULL, 0, 0, NULL); + + } else { + set_sec_mon_state(HPSR_SSM_ST_NON_SECURE); } } @@ -280,6 +397,7 @@ static void fsl_secboot_bootscript_parse_failure(void) */ void fsl_secboot_handle_error(int error) { +#ifndef CONFIG_SPL_BUILD const struct fsl_secboot_errcode *e; for (e = fsl_secboot_errcodes; e->errcode != ERROR_ESBC_CLIENT_MAX; @@ -287,6 +405,16 @@ void fsl_secboot_handle_error(int error) if (e->errcode == error) printf("ERROR :: %x :: %s\n", error, e->name); } +#else + printf("ERROR :: %x\n", error); +#endif + + /* If Boot Mode is secure, transition the SNVS state and issue + * reset based on type of failure and ITS setting. + * If Boot mode is non-secure, return from this function. + */ + if (fsl_check_boot_mode_secure() == 0) + return; switch (error) { case ERROR_ESBC_CLIENT_HEADER_BARKER: @@ -299,6 +427,7 @@ void fsl_secboot_handle_error(int error) case ERROR_ESBC_CLIENT_HEADER_SIG_KEY_MOD: case ERROR_ESBC_CLIENT_HEADER_SG_ESBC_EP: case ERROR_ESBC_CLIENT_HEADER_SG_ENTIRES_BAD: + case ERROR_KEY_TABLE_NOT_FOUND: #ifdef CONFIG_KEY_REVOCATION case ERROR_ESBC_CLIENT_HEADER_KEY_REVOKED: case ERROR_ESBC_CLIENT_HEADER_INVALID_SRK_NUM_ENTRY: @@ -374,13 +503,12 @@ static int calc_img_key_hash(struct fsl_secboot_img_priv *img) ret = algo->hash_init(algo, &ctx); if (ret) return ret; - /* Update hash for ESBC key */ #ifdef CONFIG_KEY_REVOCATION if (check_srk(img)) { ret = algo->hash_update(algo, ctx, - (u8 *)(img->ehdrloc + img->hdr.srk_tbl_off), - img->hdr.len_kr.num_srk * sizeof(struct srk_table), 1); + (u8 *)(uintptr_t)(img->ehdrloc + img->hdr.srk_tbl_off), + img->hdr.len_kr.num_srk * sizeof(struct srk_table), 1); srk = 1; } #endif @@ -389,12 +517,12 @@ static int calc_img_key_hash(struct fsl_secboot_img_priv *img) img->img_key, img->key_len, 1); if (ret) return ret; - /* Copy hash at destination buffer */ ret = algo->hash_finish(algo, ctx, hash_val, algo->digest_size); - if (ret) + if (ret) { + free(ctx); return ret; - + } for (i = 0; i < SHA256_BYTES; i++) img->img_key_hash[i] = hash_val[i]; @@ -438,8 +566,8 @@ static int calc_esbchdr_esbc_hash(struct fsl_secboot_img_priv *img) #ifdef CONFIG_KEY_REVOCATION if (check_srk(img)) { ret = algo->hash_update(algo, ctx, - (u8 *)(img->ehdrloc + img->hdr.srk_tbl_off), - img->hdr.len_kr.num_srk * sizeof(struct srk_table), 0); + (u8 *)(uintptr_t)(img->ehdrloc + img->hdr.srk_tbl_off), + img->hdr.len_kr.num_srk * sizeof(struct srk_table), 0); key_hash = 1; } #endif @@ -447,23 +575,32 @@ static int calc_esbchdr_esbc_hash(struct fsl_secboot_img_priv *img) if (!key_hash && check_ie(img)) key_hash = 1; #endif - if (!key_hash) +#ifndef CONFIG_ESBC_HDR_LS +/* No single key support in LS ESBC header */ + if (!key_hash) { ret = algo->hash_update(algo, ctx, img->img_key, img->hdr.key_len, 0); + key_hash = 1; + } +#endif if (ret) return ret; - + if (!key_hash) { + free(ctx); + return ERROR_KEY_TABLE_NOT_FOUND; + } /* Update hash for actual Image */ ret = algo->hash_update(algo, ctx, - (u8 *)img->hdr.pimg, img->hdr.img_size, 1); + (u8 *)(*(img->img_addr_ptr)), img->img_size, 1); if (ret) return ret; /* Copy hash at destination buffer */ ret = algo->hash_finish(algo, ctx, hash_val, algo->digest_size); - if (ret) + if (ret) { + free(ctx); return ret; - + } return 0; } @@ -531,109 +668,62 @@ static void construct_img_encoded_hash_second(struct fsl_secboot_img_priv *img) */ static int read_validate_esbc_client_header(struct fsl_secboot_img_priv *img) { - char buf[20]; struct fsl_secboot_img_hdr *hdr = &img->hdr; - void *esbc = (u8 *)img->ehdrloc; + void *esbc = (u8 *)(uintptr_t)img->ehdrloc; u8 *k, *s; -#ifdef CONFIG_KEY_REVOCATION - u32 ret; - u32 key_num, key_revoc_flag, size; -#endif -#if defined(CONFIG_FSL_ISBC_KEY_EXT) - struct ie_key_info *ie_info; - u32 ie_num, ie_revoc_flag, ie_key_len; -#endif + u32 ret = 0; + int key_found = 0; /* check barker code */ if (memcmp(hdr->barker, barker_code, ESBC_BARKER_LEN)) return ERROR_ESBC_CLIENT_HEADER_BARKER; - sprintf(buf, "%p", hdr->pimg); - setenv("img_addr", buf); + /* If Image Address is not passed as argument to function, + * then Address and Size must be read from the Header. + */ + if (*(img->img_addr_ptr) == 0) { + #ifdef CONFIG_ESBC_ADDR_64BIT + *(img->img_addr_ptr) = hdr->pimg64; + #else + *(img->img_addr_ptr) = hdr->pimg; + #endif + } if (!hdr->img_size) return ERROR_ESBC_CLIENT_HEADER_IMG_SIZE; + img->img_size = hdr->img_size; + /* Key checking*/ #ifdef CONFIG_KEY_REVOCATION if (check_srk(img)) { - if ((hdr->len_kr.num_srk == 0) || - (hdr->len_kr.num_srk > MAX_KEY_ENTRIES)) - return ERROR_ESBC_CLIENT_HEADER_INVALID_SRK_NUM_ENTRY; - - key_num = hdr->len_kr.srk_sel; - if (key_num == 0 || key_num > hdr->len_kr.num_srk) - return ERROR_ESBC_CLIENT_HEADER_INVALID_KEY_NUM; - - /* Get revoc key from sfp */ - key_revoc_flag = get_key_revoc(); - ret = is_key_revoked(key_num, key_revoc_flag); - if (ret) - return ERROR_ESBC_CLIENT_HEADER_KEY_REVOKED; - - size = hdr->len_kr.num_srk * sizeof(struct srk_table); - - memcpy(&img->srk_tbl, esbc + hdr->srk_tbl_off, size); - - ret = validate_srk_tbl(img->srk_tbl, hdr->len_kr.num_srk); - + ret = read_validate_srk_tbl(img); if (ret != 0) return ret; - - img->key_len = img->srk_tbl[key_num - 1].key_len; - - memcpy(&img->img_key, &(img->srk_tbl[key_num - 1].pkey), - img->key_len); - key_found = 1; } #endif #if defined(CONFIG_FSL_ISBC_KEY_EXT) if (!key_found && check_ie(img)) { - if (get_ie_info_addr(&img->ie_addr)) - return ERROR_IE_TABLE_NOT_FOUND; - ie_info = (struct ie_key_info *)img->ie_addr; - if (ie_info->num_keys == 0 || ie_info->num_keys > 32) - return ERROR_ESBC_CLIENT_HEADER_INVALID_IE_NUM_ENTRY; - - ie_num = hdr->ie_key_sel; - if (ie_num == 0 || ie_num > ie_info->num_keys) - return ERROR_ESBC_CLIENT_HEADER_INVALID_IE_KEY_NUM; - - ie_revoc_flag = ie_info->key_revok; - if ((u32)(1 << (ie_num - 1)) & ie_revoc_flag) - return ERROR_ESBC_CLIENT_HEADER_IE_KEY_REVOKED; - - ie_key_len = ie_info->ie_key_tbl[ie_num - 1].key_len; - - if (!((ie_key_len == 2 * KEY_SIZE_BYTES / 4) || - (ie_key_len == 2 * KEY_SIZE_BYTES / 2) || - (ie_key_len == 2 * KEY_SIZE_BYTES))) - return ERROR_ESBC_CLIENT_HEADER_INV_IE_ENTRY_KEYLEN; - - memcpy(&img->img_key, &(ie_info->ie_key_tbl[ie_num - 1].pkey), - ie_key_len); - - img->key_len = ie_key_len; + ret = read_validate_ie_tbl(img); + if (ret != 0) + return ret; key_found = 1; } #endif - +#ifndef CONFIG_ESBC_HDR_LS +/* Single Key Feature not available in LS ESBC Header */ if (key_found == 0) { - /* check key length */ - if (!((hdr->key_len == 2 * KEY_SIZE_BYTES / 4) || - (hdr->key_len == 2 * KEY_SIZE_BYTES / 2) || - (hdr->key_len == 2 * KEY_SIZE_BYTES))) - return ERROR_ESBC_CLIENT_HEADER_KEY_LEN; - - memcpy(&img->img_key, esbc + hdr->pkey, hdr->key_len); - - img->key_len = hdr->key_len; - + ret = read_validate_single_key(img); + if (ret != 0) + return ret; key_found = 1; } +#endif + if (!key_found) + return ERROR_KEY_TABLE_NOT_FOUND; /* check signaure */ if (get_key_len(img) == 2 * hdr->sign_len) { @@ -647,10 +737,12 @@ static int read_validate_esbc_client_header(struct fsl_secboot_img_priv *img) } memcpy(&img->img_sign, esbc + hdr->psign, hdr->sign_len); - +/* No SG support in LS-CH3 */ +#ifndef CONFIG_ESBC_HDR_LS /* No SG support */ if (hdr->sg_flag) return ERROR_ESBC_CLIENT_HEADER_SG; +#endif /* modulus most significant bit should be set */ k = (u8 *)&img->img_key; @@ -679,7 +771,7 @@ static inline int str2longbe(const char *p, ulong *num) if (!p) { return 0; } else { - tmp = simple_strtoul(p, &endptr, 16); + tmp = hextoul(p, &endptr); if (sizeof(ulong) == 4) *num = cpu_to_be32(tmp); else @@ -688,27 +780,108 @@ static inline int str2longbe(const char *p, ulong *num) return *p != '\0' && *endptr == '\0'; } +/* Function to calculate the ESBC Image Hash + * and hash from Digital signature. + * The Two hash's are compared to yield the + * result of signature validation. + */ +static int calculate_cmp_img_sig(struct fsl_secboot_img_priv *img) +{ + int ret; + uint32_t key_len; + struct key_prop prop; +#if !defined(USE_HOSTCC) + struct udevice *mod_exp_dev; +#endif + ret = calc_esbchdr_esbc_hash(img); + if (ret) + return ret; -int fsl_secboot_validate(cmd_tbl_t *cmdtp, int flag, int argc, - char * const argv[]) + /* Construct encoded hash EM' wrt PKCSv1.5 */ + construct_img_encoded_hash_second(img); + + /* Fill prop structure for public key */ + memset(&prop, 0, sizeof(struct key_prop)); + key_len = get_key_len(img) / 2; + prop.modulus = img->img_key; + prop.public_exponent = img->img_key + key_len; + prop.num_bits = key_len * 8; + prop.exp_len = key_len; + +#if defined(CONFIG_SPL_BUILD) + ret = device_bind_driver(NULL, "fsl_rsa_mod_exp", "fsl_rsa_mod_exp", NULL); + if (ret) { + printf("Couldn't bind fsl_rsa_mod_exp driver (%d)\n", ret); + return -EINVAL; + } +#endif + ret = uclass_get_device(UCLASS_MOD_EXP, 0, &mod_exp_dev); + if (ret) { + printf("RSA: Can't find Modular Exp implementation\n"); + return -EINVAL; + } + + ret = rsa_mod_exp(mod_exp_dev, img->img_sign, img->hdr.sign_len, + &prop, img->img_encoded_hash); + if (ret) + return ret; + + /* + * compare the encoded messages EM' and EM wrt RSA PKCSv1.5 + * memcmp returns zero on success + * memcmp returns non-zero on failure + */ + ret = memcmp(&img->img_encoded_hash_second, &img->img_encoded_hash, + img->hdr.sign_len); + + if (ret) + return ERROR_ESBC_CLIENT_HASH_COMPARE_EM; + + return 0; +} +/* Function to initialize img priv and global data structure + */ +static int secboot_init(struct fsl_secboot_img_priv **img_ptr) +{ + *img_ptr = malloc(sizeof(struct fsl_secboot_img_priv)); + + struct fsl_secboot_img_priv *img = *img_ptr; + + if (!img) + return -ENOMEM; + memset(img, 0, sizeof(struct fsl_secboot_img_priv)); + +#if defined(CONFIG_FSL_ISBC_KEY_EXT) + if (glb.ie_addr) + img->ie_addr = glb.ie_addr; +#endif + return 0; +} + + +/* haddr - Address of the header of image to be validated. + * arg_hash_str - Option hash string. If provided, this + * overrides the key hash in the SFP fuses. + * img_addr_ptr - Optional pointer to address of image to be validated. + * If non zero addr, this overrides the addr of image in header, + * otherwise updated to image addr in header. + * Acts as both input and output of function. + * This pointer shouldn't be NULL. + */ +int fsl_secboot_validate(uintptr_t haddr, char *arg_hash_str, + uintptr_t *img_addr_ptr) { struct ccsr_sfp_regs *sfp_regs = (void *)(CONFIG_SYS_SFP_ADDR); ulong hash[SHA256_BYTES/sizeof(ulong)]; char hash_str[NUM_HEX_CHARS + 1]; - ulong addr = simple_strtoul(argv[1], NULL, 16); struct fsl_secboot_img_priv *img; struct fsl_secboot_img_hdr *hdr; void *esbc; int ret, i, hash_cmd = 0; u32 srk_hash[8]; - uint32_t key_len; - struct key_prop prop; -#if !defined(USE_HOSTCC) - struct udevice *mod_exp_dev; -#endif - if (argc == 3) { - char *cp = argv[2]; + if (strlen(arg_hash_str) != 0) { + const char *cp = arg_hash_str; int i = 0; if (*cp == '0' && *(cp + 1) == 'x') @@ -721,7 +894,7 @@ int fsl_secboot_validate(cmd_tbl_t *cmdtp, int flag, int argc, */ if (strlen(cp) != SHA256_NIBBLES) { printf("%s is not a 256 bits hex string as expected\n", - argv[2]); + arg_hash_str); return -1; } @@ -731,7 +904,7 @@ int fsl_secboot_validate(cmd_tbl_t *cmdtp, int flag, int argc, hash_str[NUM_HEX_CHARS] = '\0'; if (!str2longbe(hash_str, &hash[i])) { printf("%s is not a 256 bits hex string ", - argv[2]); + arg_hash_str); return -1; } } @@ -739,15 +912,14 @@ int fsl_secboot_validate(cmd_tbl_t *cmdtp, int flag, int argc, hash_cmd = 1; } - img = malloc(sizeof(struct fsl_secboot_img_priv)); - - if (!img) - return -1; - - memset(img, 0, sizeof(struct fsl_secboot_img_priv)); + ret = secboot_init(&img); + if (ret) + goto exit; + /* Update the information in Private Struct */ hdr = &img->hdr; - img->ehdrloc = addr; + img->ehdrloc = haddr; + img->img_addr_ptr = img_addr_ptr; esbc = (u8 *)img->ehdrloc; memcpy(hdr, esbc, sizeof(struct fsl_secboot_img_hdr)); @@ -790,51 +962,14 @@ int fsl_secboot_validate(cmd_tbl_t *cmdtp, int flag, int argc, goto exit; } - ret = calc_esbchdr_esbc_hash(img); - if (ret) { - fsl_secblk_handle_error(ret); - goto exit; - } - - /* Construct encoded hash EM' wrt PKCSv1.5 */ - construct_img_encoded_hash_second(img); - - /* Fill prop structure for public key */ - memset(&prop, 0, sizeof(struct key_prop)); - key_len = get_key_len(img) / 2; - prop.modulus = img->img_key; - prop.public_exponent = img->img_key + key_len; - prop.num_bits = key_len * 8; - prop.exp_len = key_len; - - ret = uclass_get_device(UCLASS_MOD_EXP, 0, &mod_exp_dev); - if (ret) { - printf("RSA: Can't find Modular Exp implementation\n"); - return -EINVAL; - } - - ret = rsa_mod_exp(mod_exp_dev, img->img_sign, img->hdr.sign_len, - &prop, img->img_encoded_hash); - if (ret) { - fsl_secblk_handle_error(ret); - goto exit; - } - - /* - * compare the encoded messages EM' and EM wrt RSA PKCSv1.5 - * memcmp returns zero on success - * memcmp returns non-zero on failure - */ - ret = memcmp(&img->img_encoded_hash_second, &img->img_encoded_hash, - img->hdr.sign_len); - + ret = calculate_cmp_img_sig(img); if (ret) { - fsl_secboot_handle_error(ERROR_ESBC_CLIENT_HASH_COMPARE_EM); + fsl_secboot_handle_error(ret); goto exit; } - printf("esbc_validate command successful\n"); - exit: - return 0; + /* Free Img as it was malloc'ed*/ + free(img); + return ret; }