147151e4bSgaurav rana /*
247151e4bSgaurav rana * Copyright 2015 Freescale Semiconductor, Inc.
347151e4bSgaurav rana *
447151e4bSgaurav rana * SPDX-License-Identifier: GPL-2.0+
547151e4bSgaurav rana */
647151e4bSgaurav rana
747151e4bSgaurav rana #include <common.h>
8*9d922450SSimon Glass #include <dm.h>
947151e4bSgaurav rana #include <fsl_validate.h>
1047151e4bSgaurav rana #include <fsl_secboot_err.h>
1147151e4bSgaurav rana #include <fsl_sfp.h>
1247151e4bSgaurav rana #include <fsl_sec.h>
1347151e4bSgaurav rana #include <command.h>
1447151e4bSgaurav rana #include <malloc.h>
1547151e4bSgaurav rana #include <u-boot/rsa-mod-exp.h>
1647151e4bSgaurav rana #include <hash.h>
1747151e4bSgaurav rana #include <fsl_secboot_err.h>
1873fb5838SYork Sun #ifdef CONFIG_ARCH_LS1021A
1947151e4bSgaurav rana #include <asm/arch/immap_ls102xa.h>
2047151e4bSgaurav rana #endif
2147151e4bSgaurav rana
2247151e4bSgaurav rana #define SHA256_BITS 256
2347151e4bSgaurav rana #define SHA256_BYTES (256/8)
2447151e4bSgaurav rana #define SHA256_NIBBLES (256/4)
2547151e4bSgaurav rana #define NUM_HEX_CHARS (sizeof(ulong) * 2)
2647151e4bSgaurav rana
2794ba5e41SAneesh Bansal #define CHECK_KEY_LEN(key_len) (((key_len) == 2 * KEY_SIZE_BYTES / 4) || \
2894ba5e41SAneesh Bansal ((key_len) == 2 * KEY_SIZE_BYTES / 2) || \
2994ba5e41SAneesh Bansal ((key_len) == 2 * KEY_SIZE_BYTES))
30ac55dadbSUdit Agarwal #if defined(CONFIG_FSL_ISBC_KEY_EXT)
31ac55dadbSUdit Agarwal /* Global data structure */
32ac55dadbSUdit Agarwal static struct fsl_secboot_glb glb;
33ac55dadbSUdit Agarwal #endif
3494ba5e41SAneesh Bansal
3547151e4bSgaurav rana /* This array contains DER value for SHA-256 */
3647151e4bSgaurav rana static const u8 hash_identifier[] = { 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60,
3747151e4bSgaurav rana 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00,
3847151e4bSgaurav rana 0x04, 0x20
3947151e4bSgaurav rana };
4047151e4bSgaurav rana
4147151e4bSgaurav rana static u8 hash_val[SHA256_BYTES];
42fd6dbc98SSaksham Jain
43fd6dbc98SSaksham Jain #ifdef CONFIG_ESBC_HDR_LS
44fd6dbc98SSaksham Jain /* New Barker Code for LS ESBC Header */
45fd6dbc98SSaksham Jain static const u8 barker_code[ESBC_BARKER_LEN] = { 0x12, 0x19, 0x20, 0x01 };
46fd6dbc98SSaksham Jain #else
4747151e4bSgaurav rana static const u8 barker_code[ESBC_BARKER_LEN] = { 0x68, 0x39, 0x27, 0x81 };
48fd6dbc98SSaksham Jain #endif
4947151e4bSgaurav rana
5047151e4bSgaurav rana void branch_to_self(void) __attribute__ ((noreturn));
5147151e4bSgaurav rana
5247151e4bSgaurav rana /*
5347151e4bSgaurav rana * This function will put core in infinite loop.
5447151e4bSgaurav rana * This will be called when the ESBC can not proceed further due
5547151e4bSgaurav rana * to some unknown errors.
5647151e4bSgaurav rana */
branch_to_self(void)5747151e4bSgaurav rana void branch_to_self(void)
5847151e4bSgaurav rana {
5947151e4bSgaurav rana printf("Core is in infinite loop due to errors.\n");
6047151e4bSgaurav rana self:
6147151e4bSgaurav rana goto self;
6247151e4bSgaurav rana }
6347151e4bSgaurav rana
6447151e4bSgaurav rana #if defined(CONFIG_FSL_ISBC_KEY_EXT)
check_ie(struct fsl_secboot_img_priv * img)6547151e4bSgaurav rana static u32 check_ie(struct fsl_secboot_img_priv *img)
6647151e4bSgaurav rana {
67ac55dadbSUdit Agarwal if (img->hdr.ie_flag & IE_FLAG_MASK)
6847151e4bSgaurav rana return 1;
6947151e4bSgaurav rana
7047151e4bSgaurav rana return 0;
7147151e4bSgaurav rana }
7247151e4bSgaurav rana
7347151e4bSgaurav rana /* This function returns the CSF Header Address of uboot
7447151e4bSgaurav rana * For MPC85xx based platforms, the LAW mapping for NOR
7547151e4bSgaurav rana * flash changes in uboot code. Hence the offset needs
7647151e4bSgaurav rana * to be calculated and added to the new NOR flash base
7747151e4bSgaurav rana * address
7847151e4bSgaurav rana */
7947151e4bSgaurav rana #if defined(CONFIG_MPC85xx)
get_csf_base_addr(u32 * csf_addr,u32 * flash_base_addr)807bcb0eb2SAneesh Bansal int get_csf_base_addr(u32 *csf_addr, u32 *flash_base_addr)
8147151e4bSgaurav rana {
8247151e4bSgaurav rana struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
8347151e4bSgaurav rana u32 csf_hdr_addr = in_be32(&gur->scratchrw[0]);
8447151e4bSgaurav rana u32 csf_flash_offset = csf_hdr_addr & ~(CONFIG_SYS_PBI_FLASH_BASE);
857bcb0eb2SAneesh Bansal u32 flash_addr, addr;
8647151e4bSgaurav rana int found = 0;
8747151e4bSgaurav rana int i = 0;
8847151e4bSgaurav rana
8947151e4bSgaurav rana for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++) {
9047151e4bSgaurav rana flash_addr = flash_info[i].start[0];
9147151e4bSgaurav rana addr = flash_info[i].start[0] + csf_flash_offset;
9247151e4bSgaurav rana if (memcmp((u8 *)addr, barker_code, ESBC_BARKER_LEN) == 0) {
937bcb0eb2SAneesh Bansal debug("Barker found on addr %x\n", addr);
9447151e4bSgaurav rana found = 1;
9547151e4bSgaurav rana break;
9647151e4bSgaurav rana }
9747151e4bSgaurav rana }
9847151e4bSgaurav rana
9947151e4bSgaurav rana if (!found)
10047151e4bSgaurav rana return -1;
10147151e4bSgaurav rana
10247151e4bSgaurav rana *csf_addr = addr;
10347151e4bSgaurav rana *flash_base_addr = flash_addr;
10447151e4bSgaurav rana
10547151e4bSgaurav rana return 0;
10647151e4bSgaurav rana }
10747151e4bSgaurav rana #else
10847151e4bSgaurav rana /* For platforms like LS1020, correct flash address is present in
10947151e4bSgaurav rana * the header. So the function reqturns flash base address as 0
11047151e4bSgaurav rana */
get_csf_base_addr(u32 * csf_addr,u32 * flash_base_addr)1117bcb0eb2SAneesh Bansal int get_csf_base_addr(u32 *csf_addr, u32 *flash_base_addr)
11247151e4bSgaurav rana {
11347151e4bSgaurav rana struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
11447151e4bSgaurav rana u32 csf_hdr_addr = in_be32(&gur->scratchrw[0]);
11547151e4bSgaurav rana
1169711f528SAneesh Bansal if (memcmp((u8 *)(uintptr_t)csf_hdr_addr,
1179711f528SAneesh Bansal barker_code, ESBC_BARKER_LEN))
11847151e4bSgaurav rana return -1;
11947151e4bSgaurav rana
12047151e4bSgaurav rana *csf_addr = csf_hdr_addr;
12147151e4bSgaurav rana *flash_base_addr = 0;
12247151e4bSgaurav rana return 0;
12347151e4bSgaurav rana }
12447151e4bSgaurav rana #endif
12547151e4bSgaurav rana
126ac55dadbSUdit Agarwal #if defined(CONFIG_ESBC_HDR_LS)
get_ie_info_addr(uintptr_t * ie_addr)127ac55dadbSUdit Agarwal static int get_ie_info_addr(uintptr_t *ie_addr)
128ac55dadbSUdit Agarwal {
129ac55dadbSUdit Agarwal struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
130ac55dadbSUdit Agarwal /* For LS-CH3, the address of IE Table is
131ac55dadbSUdit Agarwal * stated in Scratch13 and scratch14 of DCFG.
132ac55dadbSUdit Agarwal * Bootrom validates this table while validating uboot.
133ac55dadbSUdit Agarwal * DCFG is LE*/
134ac55dadbSUdit Agarwal *ie_addr = in_le32(&gur->scratchrw[SCRATCH_IE_HIGH_ADR - 1]);
135ac55dadbSUdit Agarwal *ie_addr = *ie_addr << 32;
136ac55dadbSUdit Agarwal *ie_addr |= in_le32(&gur->scratchrw[SCRATCH_IE_LOW_ADR - 1]);
137ac55dadbSUdit Agarwal return 0;
138ac55dadbSUdit Agarwal }
139ac55dadbSUdit Agarwal #else /* CONFIG_ESBC_HDR_LS */
get_ie_info_addr(uintptr_t * ie_addr)140ac55dadbSUdit Agarwal static int get_ie_info_addr(uintptr_t *ie_addr)
14147151e4bSgaurav rana {
14247151e4bSgaurav rana struct fsl_secboot_img_hdr *hdr;
14347151e4bSgaurav rana struct fsl_secboot_sg_table *sg_tbl;
1447bcb0eb2SAneesh Bansal u32 flash_base_addr, csf_addr;
14547151e4bSgaurav rana
14647151e4bSgaurav rana if (get_csf_base_addr(&csf_addr, &flash_base_addr))
14747151e4bSgaurav rana return -1;
14847151e4bSgaurav rana
1499711f528SAneesh Bansal hdr = (struct fsl_secboot_img_hdr *)(uintptr_t)csf_addr;
15047151e4bSgaurav rana
15147151e4bSgaurav rana /* For SoC's with Trust Architecture v1 with corenet bus
15247151e4bSgaurav rana * the sg table field in CSF header has absolute address
15347151e4bSgaurav rana * for sg table in memory. In other Trust Architecture,
15447151e4bSgaurav rana * this field specifies the offset of sg table from the
15547151e4bSgaurav rana * base address of CSF Header
15647151e4bSgaurav rana */
15747151e4bSgaurav rana #if defined(CONFIG_FSL_TRUST_ARCH_v1) && defined(CONFIG_FSL_CORENET)
15847151e4bSgaurav rana sg_tbl = (struct fsl_secboot_sg_table *)
1597bcb0eb2SAneesh Bansal (((u32)hdr->psgtable & ~(CONFIG_SYS_PBI_FLASH_BASE)) +
16047151e4bSgaurav rana flash_base_addr);
16147151e4bSgaurav rana #else
1629711f528SAneesh Bansal sg_tbl = (struct fsl_secboot_sg_table *)(uintptr_t)(csf_addr +
1637bcb0eb2SAneesh Bansal (u32)hdr->psgtable);
16447151e4bSgaurav rana #endif
16547151e4bSgaurav rana
16647151e4bSgaurav rana /* IE Key Table is the first entry in the SG Table */
16747151e4bSgaurav rana #if defined(CONFIG_MPC85xx)
168ac55dadbSUdit Agarwal *ie_addr = (uintptr_t)((sg_tbl->src_addr &
169ac55dadbSUdit Agarwal ~(CONFIG_SYS_PBI_FLASH_BASE)) +
170ac55dadbSUdit Agarwal flash_base_addr);
17147151e4bSgaurav rana #else
172ac55dadbSUdit Agarwal *ie_addr = (uintptr_t)sg_tbl->src_addr;
17347151e4bSgaurav rana #endif
17447151e4bSgaurav rana
175ac55dadbSUdit Agarwal debug("IE Table address is %lx\n", *ie_addr);
17647151e4bSgaurav rana return 0;
17747151e4bSgaurav rana }
178ac55dadbSUdit Agarwal #endif /* CONFIG_ESBC_HDR_LS */
17947151e4bSgaurav rana #endif
18047151e4bSgaurav rana
18147151e4bSgaurav rana #ifdef CONFIG_KEY_REVOCATION
18247151e4bSgaurav rana /* This function checks srk_table_flag in header and set/reset srk_flag.*/
check_srk(struct fsl_secboot_img_priv * img)18347151e4bSgaurav rana static u32 check_srk(struct fsl_secboot_img_priv *img)
18447151e4bSgaurav rana {
185fd6dbc98SSaksham Jain #ifdef CONFIG_ESBC_HDR_LS
186ac55dadbSUdit Agarwal /* In LS, No SRK Flag as SRK is always present if IE not present*/
187ac55dadbSUdit Agarwal #if defined(CONFIG_FSL_ISBC_KEY_EXT)
188ac55dadbSUdit Agarwal return !check_ie(img);
189ac55dadbSUdit Agarwal #endif
190fd6dbc98SSaksham Jain return 1;
191fd6dbc98SSaksham Jain #else
19247151e4bSgaurav rana if (img->hdr.len_kr.srk_table_flag & SRK_FLAG)
19347151e4bSgaurav rana return 1;
19447151e4bSgaurav rana
19547151e4bSgaurav rana return 0;
196fd6dbc98SSaksham Jain #endif
19747151e4bSgaurav rana }
19847151e4bSgaurav rana
19947151e4bSgaurav rana /* This function returns ospr's key_revoc values.*/
get_key_revoc(void)20047151e4bSgaurav rana static u32 get_key_revoc(void)
20147151e4bSgaurav rana {
20247151e4bSgaurav rana struct ccsr_sfp_regs *sfp_regs = (void *)(CONFIG_SYS_SFP_ADDR);
20347151e4bSgaurav rana return (sfp_in32(&sfp_regs->ospr) & OSPR_KEY_REVOC_MASK) >>
20447151e4bSgaurav rana OSPR_KEY_REVOC_SHIFT;
20547151e4bSgaurav rana }
20647151e4bSgaurav rana
20747151e4bSgaurav rana /* This function checks if selected key is revoked or not.*/
is_key_revoked(u32 keynum,u32 rev_flag)20847151e4bSgaurav rana static u32 is_key_revoked(u32 keynum, u32 rev_flag)
20947151e4bSgaurav rana {
21047151e4bSgaurav rana if (keynum == UNREVOCABLE_KEY)
21147151e4bSgaurav rana return 0;
21247151e4bSgaurav rana
21347151e4bSgaurav rana if ((u32)(1 << (ALIGN_REVOC_KEY - keynum)) & rev_flag)
21447151e4bSgaurav rana return 1;
21547151e4bSgaurav rana
21647151e4bSgaurav rana return 0;
21747151e4bSgaurav rana }
21847151e4bSgaurav rana
21994ba5e41SAneesh Bansal /* It read validates srk_table key lengths.*/
read_validate_srk_tbl(struct fsl_secboot_img_priv * img)22094ba5e41SAneesh Bansal static u32 read_validate_srk_tbl(struct fsl_secboot_img_priv *img)
22147151e4bSgaurav rana {
22247151e4bSgaurav rana int i = 0;
22394ba5e41SAneesh Bansal u32 ret, key_num, key_revoc_flag, size;
22494ba5e41SAneesh Bansal struct fsl_secboot_img_hdr *hdr = &img->hdr;
22594ba5e41SAneesh Bansal void *esbc = (u8 *)(uintptr_t)img->ehdrloc;
22694ba5e41SAneesh Bansal
22794ba5e41SAneesh Bansal if ((hdr->len_kr.num_srk == 0) ||
22894ba5e41SAneesh Bansal (hdr->len_kr.num_srk > MAX_KEY_ENTRIES))
22994ba5e41SAneesh Bansal return ERROR_ESBC_CLIENT_HEADER_INVALID_SRK_NUM_ENTRY;
23094ba5e41SAneesh Bansal
23194ba5e41SAneesh Bansal key_num = hdr->len_kr.srk_sel;
23294ba5e41SAneesh Bansal if (key_num == 0 || key_num > hdr->len_kr.num_srk)
23394ba5e41SAneesh Bansal return ERROR_ESBC_CLIENT_HEADER_INVALID_KEY_NUM;
23494ba5e41SAneesh Bansal
23594ba5e41SAneesh Bansal /* Get revoc key from sfp */
23694ba5e41SAneesh Bansal key_revoc_flag = get_key_revoc();
23794ba5e41SAneesh Bansal ret = is_key_revoked(key_num, key_revoc_flag);
23894ba5e41SAneesh Bansal if (ret)
23994ba5e41SAneesh Bansal return ERROR_ESBC_CLIENT_HEADER_KEY_REVOKED;
24094ba5e41SAneesh Bansal
24194ba5e41SAneesh Bansal size = hdr->len_kr.num_srk * sizeof(struct srk_table);
24294ba5e41SAneesh Bansal
24394ba5e41SAneesh Bansal memcpy(&img->srk_tbl, esbc + hdr->srk_tbl_off, size);
24494ba5e41SAneesh Bansal
24594ba5e41SAneesh Bansal for (i = 0; i < hdr->len_kr.num_srk; i++) {
24694ba5e41SAneesh Bansal if (!CHECK_KEY_LEN(img->srk_tbl[i].key_len))
24747151e4bSgaurav rana return ERROR_ESBC_CLIENT_HEADER_INV_SRK_ENTRY_KEYLEN;
24847151e4bSgaurav rana }
24994ba5e41SAneesh Bansal
25094ba5e41SAneesh Bansal img->key_len = img->srk_tbl[key_num - 1].key_len;
25194ba5e41SAneesh Bansal
25294ba5e41SAneesh Bansal memcpy(&img->img_key, &(img->srk_tbl[key_num - 1].pkey),
25394ba5e41SAneesh Bansal img->key_len);
25494ba5e41SAneesh Bansal
25547151e4bSgaurav rana return 0;
25647151e4bSgaurav rana }
25747151e4bSgaurav rana #endif
25847151e4bSgaurav rana
259fd6dbc98SSaksham Jain #ifndef CONFIG_ESBC_HDR_LS
read_validate_single_key(struct fsl_secboot_img_priv * img)26094ba5e41SAneesh Bansal static u32 read_validate_single_key(struct fsl_secboot_img_priv *img)
26194ba5e41SAneesh Bansal {
26294ba5e41SAneesh Bansal struct fsl_secboot_img_hdr *hdr = &img->hdr;
26394ba5e41SAneesh Bansal void *esbc = (u8 *)(uintptr_t)img->ehdrloc;
26494ba5e41SAneesh Bansal
26594ba5e41SAneesh Bansal /* check key length */
26694ba5e41SAneesh Bansal if (!CHECK_KEY_LEN(hdr->key_len))
26794ba5e41SAneesh Bansal return ERROR_ESBC_CLIENT_HEADER_KEY_LEN;
26894ba5e41SAneesh Bansal
26994ba5e41SAneesh Bansal memcpy(&img->img_key, esbc + hdr->pkey, hdr->key_len);
27094ba5e41SAneesh Bansal
27194ba5e41SAneesh Bansal img->key_len = hdr->key_len;
27294ba5e41SAneesh Bansal
27394ba5e41SAneesh Bansal return 0;
27494ba5e41SAneesh Bansal }
275fd6dbc98SSaksham Jain #endif /* CONFIG_ESBC_HDR_LS */
27694ba5e41SAneesh Bansal
27794ba5e41SAneesh Bansal #if defined(CONFIG_FSL_ISBC_KEY_EXT)
278ac55dadbSUdit Agarwal
install_ie_tbl(uintptr_t ie_tbl_addr,struct fsl_secboot_img_priv * img)279ac55dadbSUdit Agarwal static void install_ie_tbl(uintptr_t ie_tbl_addr,
280ac55dadbSUdit Agarwal struct fsl_secboot_img_priv *img)
281ac55dadbSUdit Agarwal {
282ac55dadbSUdit Agarwal /* Copy IE tbl to Global Data */
283ac55dadbSUdit Agarwal memcpy(&glb.ie_tbl, (u8 *)ie_tbl_addr, sizeof(struct ie_key_info));
284ac55dadbSUdit Agarwal img->ie_addr = (uintptr_t)&glb.ie_tbl;
285ac55dadbSUdit Agarwal glb.ie_addr = img->ie_addr;
286ac55dadbSUdit Agarwal }
287ac55dadbSUdit Agarwal
read_validate_ie_tbl(struct fsl_secboot_img_priv * img)28894ba5e41SAneesh Bansal static u32 read_validate_ie_tbl(struct fsl_secboot_img_priv *img)
28994ba5e41SAneesh Bansal {
29094ba5e41SAneesh Bansal struct fsl_secboot_img_hdr *hdr = &img->hdr;
29194ba5e41SAneesh Bansal u32 ie_key_len, ie_revoc_flag, ie_num;
29294ba5e41SAneesh Bansal struct ie_key_info *ie_info;
29394ba5e41SAneesh Bansal
294ac55dadbSUdit Agarwal if (!img->ie_addr) {
29594ba5e41SAneesh Bansal if (get_ie_info_addr(&img->ie_addr))
29694ba5e41SAneesh Bansal return ERROR_IE_TABLE_NOT_FOUND;
297ac55dadbSUdit Agarwal else
298ac55dadbSUdit Agarwal install_ie_tbl(img->ie_addr, img);
299ac55dadbSUdit Agarwal }
300ac55dadbSUdit Agarwal
30194ba5e41SAneesh Bansal ie_info = (struct ie_key_info *)(uintptr_t)img->ie_addr;
30294ba5e41SAneesh Bansal if (ie_info->num_keys == 0 || ie_info->num_keys > 32)
30394ba5e41SAneesh Bansal return ERROR_ESBC_CLIENT_HEADER_INVALID_IE_NUM_ENTRY;
30494ba5e41SAneesh Bansal
30594ba5e41SAneesh Bansal ie_num = hdr->ie_key_sel;
30694ba5e41SAneesh Bansal if (ie_num == 0 || ie_num > ie_info->num_keys)
30794ba5e41SAneesh Bansal return ERROR_ESBC_CLIENT_HEADER_INVALID_IE_KEY_NUM;
30894ba5e41SAneesh Bansal
30994ba5e41SAneesh Bansal ie_revoc_flag = ie_info->key_revok;
31094ba5e41SAneesh Bansal if ((u32)(1 << (ie_num - 1)) & ie_revoc_flag)
31194ba5e41SAneesh Bansal return ERROR_ESBC_CLIENT_HEADER_IE_KEY_REVOKED;
31294ba5e41SAneesh Bansal
31394ba5e41SAneesh Bansal ie_key_len = ie_info->ie_key_tbl[ie_num - 1].key_len;
31494ba5e41SAneesh Bansal
31594ba5e41SAneesh Bansal if (!CHECK_KEY_LEN(ie_key_len))
31694ba5e41SAneesh Bansal return ERROR_ESBC_CLIENT_HEADER_INV_IE_ENTRY_KEYLEN;
31794ba5e41SAneesh Bansal
31894ba5e41SAneesh Bansal memcpy(&img->img_key, &(ie_info->ie_key_tbl[ie_num - 1].pkey),
31994ba5e41SAneesh Bansal ie_key_len);
32094ba5e41SAneesh Bansal
32194ba5e41SAneesh Bansal img->key_len = ie_key_len;
32294ba5e41SAneesh Bansal return 0;
32394ba5e41SAneesh Bansal }
32494ba5e41SAneesh Bansal #endif
32594ba5e41SAneesh Bansal
32694ba5e41SAneesh Bansal
32747151e4bSgaurav rana /* This function return length of public key.*/
get_key_len(struct fsl_secboot_img_priv * img)32847151e4bSgaurav rana static inline u32 get_key_len(struct fsl_secboot_img_priv *img)
32947151e4bSgaurav rana {
33047151e4bSgaurav rana return img->key_len;
33147151e4bSgaurav rana }
33247151e4bSgaurav rana
33347151e4bSgaurav rana /*
33447151e4bSgaurav rana * Handles the ESBC uboot client header verification failure.
33547151e4bSgaurav rana * This function handles all the errors which might occur in the
33647151e4bSgaurav rana * parsing and checking of ESBC uboot client header. It will also
33747151e4bSgaurav rana * set the error bits in the SEC_MON.
33847151e4bSgaurav rana */
fsl_secboot_header_verification_failure(void)33947151e4bSgaurav rana static void fsl_secboot_header_verification_failure(void)
34047151e4bSgaurav rana {
34147151e4bSgaurav rana struct ccsr_sfp_regs *sfp_regs = (void *)(CONFIG_SYS_SFP_ADDR);
34247151e4bSgaurav rana
34347151e4bSgaurav rana /* 29th bit of OSPR is ITS */
34447151e4bSgaurav rana u32 its = sfp_in32(&sfp_regs->ospr) >> 2;
34547151e4bSgaurav rana
34647151e4bSgaurav rana if (its == 1)
347b259732dSSumit Garg set_sec_mon_state(HPSR_SSM_ST_SOFT_FAIL);
34847151e4bSgaurav rana else
349b259732dSSumit Garg set_sec_mon_state(HPSR_SSM_ST_NON_SECURE);
35047151e4bSgaurav rana
35147151e4bSgaurav rana printf("Generating reset request\n");
35247151e4bSgaurav rana do_reset(NULL, 0, 0, NULL);
353c4666cf6SSaksham Jain /* If reset doesn't coocur, halt execution */
354c4666cf6SSaksham Jain do_esbc_halt(NULL, 0, 0, NULL);
35547151e4bSgaurav rana }
35647151e4bSgaurav rana
35747151e4bSgaurav rana /*
35847151e4bSgaurav rana * Handles the ESBC uboot client image verification failure.
35947151e4bSgaurav rana * This function handles all the errors which might occur in the
36047151e4bSgaurav rana * public key hash comparison and signature verification of
36147151e4bSgaurav rana * ESBC uboot client image. It will also
36247151e4bSgaurav rana * set the error bits in the SEC_MON.
36347151e4bSgaurav rana */
fsl_secboot_image_verification_failure(void)36447151e4bSgaurav rana static void fsl_secboot_image_verification_failure(void)
36547151e4bSgaurav rana {
36647151e4bSgaurav rana struct ccsr_sfp_regs *sfp_regs = (void *)(CONFIG_SYS_SFP_ADDR);
36747151e4bSgaurav rana
3686ec9aef2SAneesh Bansal u32 its = (sfp_in32(&sfp_regs->ospr) & ITS_MASK) >> ITS_BIT;
36947151e4bSgaurav rana
37047151e4bSgaurav rana if (its == 1) {
371b259732dSSumit Garg set_sec_mon_state(HPSR_SSM_ST_SOFT_FAIL);
37247151e4bSgaurav rana
37347151e4bSgaurav rana printf("Generating reset request\n");
37447151e4bSgaurav rana do_reset(NULL, 0, 0, NULL);
375c4666cf6SSaksham Jain /* If reset doesn't coocur, halt execution */
376c4666cf6SSaksham Jain do_esbc_halt(NULL, 0, 0, NULL);
377c4666cf6SSaksham Jain
37847151e4bSgaurav rana } else {
379b259732dSSumit Garg set_sec_mon_state(HPSR_SSM_ST_NON_SECURE);
38047151e4bSgaurav rana }
38147151e4bSgaurav rana }
38247151e4bSgaurav rana
fsl_secboot_bootscript_parse_failure(void)38347151e4bSgaurav rana static void fsl_secboot_bootscript_parse_failure(void)
38447151e4bSgaurav rana {
38547151e4bSgaurav rana fsl_secboot_header_verification_failure();
38647151e4bSgaurav rana }
38747151e4bSgaurav rana
38847151e4bSgaurav rana /*
38947151e4bSgaurav rana * Handles the errors in esbc boot.
39047151e4bSgaurav rana * This function handles all the errors which might occur in the
39147151e4bSgaurav rana * esbc boot phase. It will call the appropriate api to log the
39247151e4bSgaurav rana * errors and set the error bits in the SEC_MON.
39347151e4bSgaurav rana */
fsl_secboot_handle_error(int error)39447151e4bSgaurav rana void fsl_secboot_handle_error(int error)
39547151e4bSgaurav rana {
39670f9661cSRuchika Gupta #ifndef CONFIG_SPL_BUILD
39747151e4bSgaurav rana const struct fsl_secboot_errcode *e;
39847151e4bSgaurav rana
39947151e4bSgaurav rana for (e = fsl_secboot_errcodes; e->errcode != ERROR_ESBC_CLIENT_MAX;
40047151e4bSgaurav rana e++) {
40147151e4bSgaurav rana if (e->errcode == error)
40247151e4bSgaurav rana printf("ERROR :: %x :: %s\n", error, e->name);
40347151e4bSgaurav rana }
40470f9661cSRuchika Gupta #else
40570f9661cSRuchika Gupta printf("ERROR :: %x\n", error);
40670f9661cSRuchika Gupta #endif
40747151e4bSgaurav rana
408856b2846SAneesh Bansal /* If Boot Mode is secure, transition the SNVS state and issue
409856b2846SAneesh Bansal * reset based on type of failure and ITS setting.
410856b2846SAneesh Bansal * If Boot mode is non-secure, return from this function.
411856b2846SAneesh Bansal */
412856b2846SAneesh Bansal if (fsl_check_boot_mode_secure() == 0)
413856b2846SAneesh Bansal return;
414856b2846SAneesh Bansal
41547151e4bSgaurav rana switch (error) {
41647151e4bSgaurav rana case ERROR_ESBC_CLIENT_HEADER_BARKER:
41747151e4bSgaurav rana case ERROR_ESBC_CLIENT_HEADER_IMG_SIZE:
41847151e4bSgaurav rana case ERROR_ESBC_CLIENT_HEADER_KEY_LEN:
41947151e4bSgaurav rana case ERROR_ESBC_CLIENT_HEADER_SIG_LEN:
42047151e4bSgaurav rana case ERROR_ESBC_CLIENT_HEADER_KEY_LEN_NOT_TWICE_SIG_LEN:
42147151e4bSgaurav rana case ERROR_ESBC_CLIENT_HEADER_KEY_MOD_1:
42247151e4bSgaurav rana case ERROR_ESBC_CLIENT_HEADER_KEY_MOD_2:
42347151e4bSgaurav rana case ERROR_ESBC_CLIENT_HEADER_SIG_KEY_MOD:
42447151e4bSgaurav rana case ERROR_ESBC_CLIENT_HEADER_SG_ESBC_EP:
42547151e4bSgaurav rana case ERROR_ESBC_CLIENT_HEADER_SG_ENTIRES_BAD:
426fd6dbc98SSaksham Jain case ERROR_KEY_TABLE_NOT_FOUND:
42747151e4bSgaurav rana #ifdef CONFIG_KEY_REVOCATION
42847151e4bSgaurav rana case ERROR_ESBC_CLIENT_HEADER_KEY_REVOKED:
42947151e4bSgaurav rana case ERROR_ESBC_CLIENT_HEADER_INVALID_SRK_NUM_ENTRY:
43047151e4bSgaurav rana case ERROR_ESBC_CLIENT_HEADER_INVALID_KEY_NUM:
43147151e4bSgaurav rana case ERROR_ESBC_CLIENT_HEADER_INV_SRK_ENTRY_KEYLEN:
43247151e4bSgaurav rana #endif
43347151e4bSgaurav rana #if defined(CONFIG_FSL_ISBC_KEY_EXT)
43447151e4bSgaurav rana /*@fallthrough@*/
43547151e4bSgaurav rana case ERROR_ESBC_CLIENT_HEADER_IE_KEY_REVOKED:
43647151e4bSgaurav rana case ERROR_ESBC_CLIENT_HEADER_INVALID_IE_NUM_ENTRY:
43747151e4bSgaurav rana case ERROR_ESBC_CLIENT_HEADER_INVALID_IE_KEY_NUM:
43847151e4bSgaurav rana case ERROR_ESBC_CLIENT_HEADER_INV_IE_ENTRY_KEYLEN:
43947151e4bSgaurav rana case ERROR_IE_TABLE_NOT_FOUND:
44047151e4bSgaurav rana #endif
44147151e4bSgaurav rana fsl_secboot_header_verification_failure();
44247151e4bSgaurav rana break;
44347151e4bSgaurav rana case ERROR_ESBC_SEC_RESET:
44447151e4bSgaurav rana case ERROR_ESBC_SEC_DEQ:
44547151e4bSgaurav rana case ERROR_ESBC_SEC_ENQ:
44647151e4bSgaurav rana case ERROR_ESBC_SEC_DEQ_TO:
44747151e4bSgaurav rana case ERROR_ESBC_SEC_JOBQ_STATUS:
44847151e4bSgaurav rana case ERROR_ESBC_CLIENT_HASH_COMPARE_KEY:
44947151e4bSgaurav rana case ERROR_ESBC_CLIENT_HASH_COMPARE_EM:
45047151e4bSgaurav rana fsl_secboot_image_verification_failure();
45147151e4bSgaurav rana break;
45247151e4bSgaurav rana case ERROR_ESBC_MISSING_BOOTM:
45347151e4bSgaurav rana fsl_secboot_bootscript_parse_failure();
45447151e4bSgaurav rana break;
45547151e4bSgaurav rana case ERROR_ESBC_WRONG_CMD:
45647151e4bSgaurav rana default:
45747151e4bSgaurav rana branch_to_self();
45847151e4bSgaurav rana break;
45947151e4bSgaurav rana }
46047151e4bSgaurav rana }
46147151e4bSgaurav rana
fsl_secblk_handle_error(int error)46247151e4bSgaurav rana static void fsl_secblk_handle_error(int error)
46347151e4bSgaurav rana {
46447151e4bSgaurav rana switch (error) {
46547151e4bSgaurav rana case ERROR_ESBC_SEC_ENQ:
46647151e4bSgaurav rana fsl_secboot_handle_error(ERROR_ESBC_SEC_ENQ);
46747151e4bSgaurav rana break;
46847151e4bSgaurav rana case ERROR_ESBC_SEC_DEQ:
46947151e4bSgaurav rana fsl_secboot_handle_error(ERROR_ESBC_SEC_DEQ);
47047151e4bSgaurav rana break;
47147151e4bSgaurav rana case ERROR_ESBC_SEC_DEQ_TO:
47247151e4bSgaurav rana fsl_secboot_handle_error(ERROR_ESBC_SEC_DEQ_TO);
47347151e4bSgaurav rana break;
47447151e4bSgaurav rana default:
47547151e4bSgaurav rana printf("Job Queue Output status %x\n", error);
47647151e4bSgaurav rana fsl_secboot_handle_error(ERROR_ESBC_SEC_JOBQ_STATUS);
47747151e4bSgaurav rana break;
47847151e4bSgaurav rana }
47947151e4bSgaurav rana }
48047151e4bSgaurav rana
48147151e4bSgaurav rana /*
48247151e4bSgaurav rana * Calculate hash of key obtained via offset present in ESBC uboot
48347151e4bSgaurav rana * client hdr. This function calculates the hash of key which is obtained
48447151e4bSgaurav rana * through offset present in ESBC uboot client header.
48547151e4bSgaurav rana */
calc_img_key_hash(struct fsl_secboot_img_priv * img)48647151e4bSgaurav rana static int calc_img_key_hash(struct fsl_secboot_img_priv *img)
48747151e4bSgaurav rana {
48847151e4bSgaurav rana struct hash_algo *algo;
48947151e4bSgaurav rana void *ctx;
49047151e4bSgaurav rana int i, srk = 0;
49147151e4bSgaurav rana int ret = 0;
49247151e4bSgaurav rana const char *algo_name = "sha256";
49347151e4bSgaurav rana
49447151e4bSgaurav rana /* Calculate hash of the esbc key */
49547151e4bSgaurav rana ret = hash_progressive_lookup_algo(algo_name, &algo);
49647151e4bSgaurav rana if (ret)
49747151e4bSgaurav rana return ret;
49847151e4bSgaurav rana
49947151e4bSgaurav rana ret = algo->hash_init(algo, &ctx);
50047151e4bSgaurav rana if (ret)
50147151e4bSgaurav rana return ret;
50247151e4bSgaurav rana
50347151e4bSgaurav rana /* Update hash for ESBC key */
50447151e4bSgaurav rana #ifdef CONFIG_KEY_REVOCATION
50547151e4bSgaurav rana if (check_srk(img)) {
50647151e4bSgaurav rana ret = algo->hash_update(algo, ctx,
5079711f528SAneesh Bansal (u8 *)(uintptr_t)(img->ehdrloc + img->hdr.srk_tbl_off),
50847151e4bSgaurav rana img->hdr.len_kr.num_srk * sizeof(struct srk_table), 1);
50947151e4bSgaurav rana srk = 1;
51047151e4bSgaurav rana }
51147151e4bSgaurav rana #endif
51247151e4bSgaurav rana if (!srk)
51347151e4bSgaurav rana ret = algo->hash_update(algo, ctx,
51447151e4bSgaurav rana img->img_key, img->key_len, 1);
51547151e4bSgaurav rana if (ret)
51647151e4bSgaurav rana return ret;
51747151e4bSgaurav rana
51847151e4bSgaurav rana /* Copy hash at destination buffer */
51947151e4bSgaurav rana ret = algo->hash_finish(algo, ctx, hash_val, algo->digest_size);
52047151e4bSgaurav rana if (ret)
52147151e4bSgaurav rana return ret;
52247151e4bSgaurav rana
52347151e4bSgaurav rana for (i = 0; i < SHA256_BYTES; i++)
52447151e4bSgaurav rana img->img_key_hash[i] = hash_val[i];
52547151e4bSgaurav rana
52647151e4bSgaurav rana return 0;
52747151e4bSgaurav rana }
52847151e4bSgaurav rana
52947151e4bSgaurav rana /*
53047151e4bSgaurav rana * Calculate hash of ESBC hdr and ESBC. This function calculates the
53147151e4bSgaurav rana * single hash of ESBC header and ESBC image. If SG flag is on, all
53247151e4bSgaurav rana * SG entries are also hashed alongwith the complete SG table.
53347151e4bSgaurav rana */
calc_esbchdr_esbc_hash(struct fsl_secboot_img_priv * img)53447151e4bSgaurav rana static int calc_esbchdr_esbc_hash(struct fsl_secboot_img_priv *img)
53547151e4bSgaurav rana {
53647151e4bSgaurav rana struct hash_algo *algo;
53747151e4bSgaurav rana void *ctx;
53847151e4bSgaurav rana int ret = 0;
53947151e4bSgaurav rana int key_hash = 0;
54047151e4bSgaurav rana const char *algo_name = "sha256";
54147151e4bSgaurav rana
54247151e4bSgaurav rana /* Calculate the hash of the ESBC */
54347151e4bSgaurav rana ret = hash_progressive_lookup_algo(algo_name, &algo);
54447151e4bSgaurav rana if (ret)
54547151e4bSgaurav rana return ret;
54647151e4bSgaurav rana
54747151e4bSgaurav rana ret = algo->hash_init(algo, &ctx);
54847151e4bSgaurav rana /* Copy hash at destination buffer */
54947151e4bSgaurav rana if (ret)
55047151e4bSgaurav rana return ret;
55147151e4bSgaurav rana
55247151e4bSgaurav rana /* Update hash for CSF Header */
55347151e4bSgaurav rana ret = algo->hash_update(algo, ctx,
55447151e4bSgaurav rana (u8 *)&img->hdr, sizeof(struct fsl_secboot_img_hdr), 0);
55547151e4bSgaurav rana if (ret)
55647151e4bSgaurav rana return ret;
55747151e4bSgaurav rana
55847151e4bSgaurav rana /* Update the hash with that of srk table if srk flag is 1
55947151e4bSgaurav rana * If IE Table is selected, key is not added in the hash
56047151e4bSgaurav rana * If neither srk table nor IE key table available, add key
56147151e4bSgaurav rana * from header in the hash calculation
56247151e4bSgaurav rana */
56347151e4bSgaurav rana #ifdef CONFIG_KEY_REVOCATION
56447151e4bSgaurav rana if (check_srk(img)) {
56547151e4bSgaurav rana ret = algo->hash_update(algo, ctx,
5669711f528SAneesh Bansal (u8 *)(uintptr_t)(img->ehdrloc + img->hdr.srk_tbl_off),
56747151e4bSgaurav rana img->hdr.len_kr.num_srk * sizeof(struct srk_table), 0);
56847151e4bSgaurav rana key_hash = 1;
56947151e4bSgaurav rana }
57047151e4bSgaurav rana #endif
57147151e4bSgaurav rana #if defined(CONFIG_FSL_ISBC_KEY_EXT)
57247151e4bSgaurav rana if (!key_hash && check_ie(img))
57347151e4bSgaurav rana key_hash = 1;
57447151e4bSgaurav rana #endif
575fd6dbc98SSaksham Jain #ifndef CONFIG_ESBC_HDR_LS
576fd6dbc98SSaksham Jain /* No single key support in LS ESBC header */
577fd6dbc98SSaksham Jain if (!key_hash) {
57847151e4bSgaurav rana ret = algo->hash_update(algo, ctx,
57947151e4bSgaurav rana img->img_key, img->hdr.key_len, 0);
580fd6dbc98SSaksham Jain key_hash = 1;
581fd6dbc98SSaksham Jain }
582fd6dbc98SSaksham Jain #endif
58347151e4bSgaurav rana if (ret)
58447151e4bSgaurav rana return ret;
585fd6dbc98SSaksham Jain if (!key_hash)
586fd6dbc98SSaksham Jain return ERROR_KEY_TABLE_NOT_FOUND;
58747151e4bSgaurav rana
58847151e4bSgaurav rana /* Update hash for actual Image */
58947151e4bSgaurav rana ret = algo->hash_update(algo, ctx,
59085bb3896SSaksham Jain (u8 *)(*(img->img_addr_ptr)), img->img_size, 1);
59147151e4bSgaurav rana if (ret)
59247151e4bSgaurav rana return ret;
59347151e4bSgaurav rana
59447151e4bSgaurav rana /* Copy hash at destination buffer */
59547151e4bSgaurav rana ret = algo->hash_finish(algo, ctx, hash_val, algo->digest_size);
59647151e4bSgaurav rana if (ret)
59747151e4bSgaurav rana return ret;
59847151e4bSgaurav rana
59947151e4bSgaurav rana return 0;
60047151e4bSgaurav rana }
60147151e4bSgaurav rana
60247151e4bSgaurav rana /*
60347151e4bSgaurav rana * Construct encoded hash EM' wrt PKCSv1.5. This function calculates the
60447151e4bSgaurav rana * pointers for padding, DER value and hash. And finally, constructs EM'
60547151e4bSgaurav rana * which includes hash of complete CSF header and ESBC image. If SG flag
60647151e4bSgaurav rana * is on, hash of SG table and entries is also included.
60747151e4bSgaurav rana */
construct_img_encoded_hash_second(struct fsl_secboot_img_priv * img)60847151e4bSgaurav rana static void construct_img_encoded_hash_second(struct fsl_secboot_img_priv *img)
60947151e4bSgaurav rana {
61047151e4bSgaurav rana /*
61147151e4bSgaurav rana * RSA PKCSv1.5 encoding format for encoded message is below
61247151e4bSgaurav rana * EM = 0x0 || 0x1 || PS || 0x0 || DER || Hash
61347151e4bSgaurav rana * PS is Padding String
61447151e4bSgaurav rana * DER is DER value for SHA-256
61547151e4bSgaurav rana * Hash is SHA-256 hash
61647151e4bSgaurav rana * *********************************************************
61747151e4bSgaurav rana * representative points to first byte of EM initially and is
61847151e4bSgaurav rana * filled with 0x0
61947151e4bSgaurav rana * representative is incremented by 1 and second byte is filled
62047151e4bSgaurav rana * with 0x1
62147151e4bSgaurav rana * padding points to third byte of EM
62247151e4bSgaurav rana * digest points to full length of EM - 32 bytes
62347151e4bSgaurav rana * hash_id (DER value) points to 19 bytes before pDigest
62447151e4bSgaurav rana * separator is one byte which separates padding and DER
62547151e4bSgaurav rana */
62647151e4bSgaurav rana
62747151e4bSgaurav rana size_t len;
62847151e4bSgaurav rana u8 *representative;
62947151e4bSgaurav rana u8 *padding, *digest;
63047151e4bSgaurav rana u8 *hash_id, *separator;
63147151e4bSgaurav rana int i;
63247151e4bSgaurav rana
63347151e4bSgaurav rana len = (get_key_len(img) / 2) - 1;
63447151e4bSgaurav rana representative = img->img_encoded_hash_second;
63547151e4bSgaurav rana representative[0] = 0;
63647151e4bSgaurav rana representative[1] = 1; /* block type 1 */
63747151e4bSgaurav rana
63847151e4bSgaurav rana padding = &representative[2];
63947151e4bSgaurav rana digest = &representative[1] + len - 32;
64047151e4bSgaurav rana hash_id = digest - sizeof(hash_identifier);
64147151e4bSgaurav rana separator = hash_id - 1;
64247151e4bSgaurav rana
64347151e4bSgaurav rana /* fill padding area pointed by padding with 0xff */
64447151e4bSgaurav rana memset(padding, 0xff, separator - padding);
64547151e4bSgaurav rana
64647151e4bSgaurav rana /* fill byte pointed by separator */
64747151e4bSgaurav rana *separator = 0;
64847151e4bSgaurav rana
64947151e4bSgaurav rana /* fill SHA-256 DER value pointed by HashId */
65047151e4bSgaurav rana memcpy(hash_id, hash_identifier, sizeof(hash_identifier));
65147151e4bSgaurav rana
65247151e4bSgaurav rana /* fill hash pointed by Digest */
65347151e4bSgaurav rana for (i = 0; i < SHA256_BYTES; i++)
65447151e4bSgaurav rana digest[i] = hash_val[i];
65547151e4bSgaurav rana }
65647151e4bSgaurav rana
65747151e4bSgaurav rana /*
65847151e4bSgaurav rana * Reads and validates the ESBC client header.
65947151e4bSgaurav rana * This function reads key and signature from the ESBC client header.
66047151e4bSgaurav rana * If Scatter/Gather flag is on, lengths and offsets of images
66147151e4bSgaurav rana * present as SG entries are also read. This function also checks
66247151e4bSgaurav rana * whether the header is valid or not.
66347151e4bSgaurav rana */
read_validate_esbc_client_header(struct fsl_secboot_img_priv * img)66447151e4bSgaurav rana static int read_validate_esbc_client_header(struct fsl_secboot_img_priv *img)
66547151e4bSgaurav rana {
66647151e4bSgaurav rana struct fsl_secboot_img_hdr *hdr = &img->hdr;
6679711f528SAneesh Bansal void *esbc = (u8 *)(uintptr_t)img->ehdrloc;
66847151e4bSgaurav rana u8 *k, *s;
66994ba5e41SAneesh Bansal u32 ret = 0;
67094ba5e41SAneesh Bansal
67147151e4bSgaurav rana int key_found = 0;
67247151e4bSgaurav rana
67347151e4bSgaurav rana /* check barker code */
67447151e4bSgaurav rana if (memcmp(hdr->barker, barker_code, ESBC_BARKER_LEN))
67547151e4bSgaurav rana return ERROR_ESBC_CLIENT_HEADER_BARKER;
67647151e4bSgaurav rana
677b055a0fdSAneesh Bansal /* If Image Address is not passed as argument to function,
678b055a0fdSAneesh Bansal * then Address and Size must be read from the Header.
679b055a0fdSAneesh Bansal */
68085bb3896SSaksham Jain if (*(img->img_addr_ptr) == 0) {
6819711f528SAneesh Bansal #ifdef CONFIG_ESBC_ADDR_64BIT
68285bb3896SSaksham Jain *(img->img_addr_ptr) = hdr->pimg64;
6839711f528SAneesh Bansal #else
68485bb3896SSaksham Jain *(img->img_addr_ptr) = hdr->pimg;
6859711f528SAneesh Bansal #endif
686b055a0fdSAneesh Bansal }
687b055a0fdSAneesh Bansal
68847151e4bSgaurav rana if (!hdr->img_size)
68947151e4bSgaurav rana return ERROR_ESBC_CLIENT_HEADER_IMG_SIZE;
69047151e4bSgaurav rana
691b055a0fdSAneesh Bansal img->img_size = hdr->img_size;
692b055a0fdSAneesh Bansal
69347151e4bSgaurav rana /* Key checking*/
69447151e4bSgaurav rana #ifdef CONFIG_KEY_REVOCATION
69547151e4bSgaurav rana if (check_srk(img)) {
69694ba5e41SAneesh Bansal ret = read_validate_srk_tbl(img);
69747151e4bSgaurav rana if (ret != 0)
69847151e4bSgaurav rana return ret;
69947151e4bSgaurav rana key_found = 1;
70047151e4bSgaurav rana }
70147151e4bSgaurav rana #endif
70247151e4bSgaurav rana
70347151e4bSgaurav rana #if defined(CONFIG_FSL_ISBC_KEY_EXT)
70447151e4bSgaurav rana if (!key_found && check_ie(img)) {
70594ba5e41SAneesh Bansal ret = read_validate_ie_tbl(img);
70694ba5e41SAneesh Bansal if (ret != 0)
70794ba5e41SAneesh Bansal return ret;
70847151e4bSgaurav rana key_found = 1;
70947151e4bSgaurav rana }
71047151e4bSgaurav rana #endif
711fd6dbc98SSaksham Jain #ifndef CONFIG_ESBC_HDR_LS
712fd6dbc98SSaksham Jain /* Single Key Feature not available in LS ESBC Header */
71347151e4bSgaurav rana if (key_found == 0) {
71494ba5e41SAneesh Bansal ret = read_validate_single_key(img);
71594ba5e41SAneesh Bansal if (ret != 0)
71694ba5e41SAneesh Bansal return ret;
71747151e4bSgaurav rana key_found = 1;
71847151e4bSgaurav rana }
719fd6dbc98SSaksham Jain #endif
720fd6dbc98SSaksham Jain if (!key_found)
721fd6dbc98SSaksham Jain return ERROR_KEY_TABLE_NOT_FOUND;
72247151e4bSgaurav rana
72347151e4bSgaurav rana /* check signaure */
72447151e4bSgaurav rana if (get_key_len(img) == 2 * hdr->sign_len) {
72547151e4bSgaurav rana /* check signature length */
72647151e4bSgaurav rana if (!((hdr->sign_len == KEY_SIZE_BYTES / 4) ||
72747151e4bSgaurav rana (hdr->sign_len == KEY_SIZE_BYTES / 2) ||
72847151e4bSgaurav rana (hdr->sign_len == KEY_SIZE_BYTES)))
72947151e4bSgaurav rana return ERROR_ESBC_CLIENT_HEADER_SIG_LEN;
73047151e4bSgaurav rana } else {
73147151e4bSgaurav rana return ERROR_ESBC_CLIENT_HEADER_KEY_LEN_NOT_TWICE_SIG_LEN;
73247151e4bSgaurav rana }
73347151e4bSgaurav rana
73447151e4bSgaurav rana memcpy(&img->img_sign, esbc + hdr->psign, hdr->sign_len);
735fd6dbc98SSaksham Jain /* No SG support in LS-CH3 */
736fd6dbc98SSaksham Jain #ifndef CONFIG_ESBC_HDR_LS
73747151e4bSgaurav rana /* No SG support */
73847151e4bSgaurav rana if (hdr->sg_flag)
73947151e4bSgaurav rana return ERROR_ESBC_CLIENT_HEADER_SG;
740fd6dbc98SSaksham Jain #endif
74147151e4bSgaurav rana
74247151e4bSgaurav rana /* modulus most significant bit should be set */
74347151e4bSgaurav rana k = (u8 *)&img->img_key;
74447151e4bSgaurav rana
74547151e4bSgaurav rana if ((k[0] & 0x80) == 0)
74647151e4bSgaurav rana return ERROR_ESBC_CLIENT_HEADER_KEY_MOD_1;
74747151e4bSgaurav rana
74847151e4bSgaurav rana /* modulus value should be odd */
74947151e4bSgaurav rana if ((k[get_key_len(img) / 2 - 1] & 0x1) == 0)
75047151e4bSgaurav rana return ERROR_ESBC_CLIENT_HEADER_KEY_MOD_2;
75147151e4bSgaurav rana
75247151e4bSgaurav rana /* Check signature value < modulus value */
75347151e4bSgaurav rana s = (u8 *)&img->img_sign;
75447151e4bSgaurav rana
75547151e4bSgaurav rana if (!(memcmp(s, k, hdr->sign_len) < 0))
75647151e4bSgaurav rana return ERROR_ESBC_CLIENT_HEADER_SIG_KEY_MOD;
75747151e4bSgaurav rana
75847151e4bSgaurav rana return ESBC_VALID_HDR;
75947151e4bSgaurav rana }
76047151e4bSgaurav rana
str2longbe(const char * p,ulong * num)76147151e4bSgaurav rana static inline int str2longbe(const char *p, ulong *num)
76247151e4bSgaurav rana {
76347151e4bSgaurav rana char *endptr;
76447151e4bSgaurav rana ulong tmp;
76547151e4bSgaurav rana
76647151e4bSgaurav rana if (!p) {
76747151e4bSgaurav rana return 0;
76847151e4bSgaurav rana } else {
76947151e4bSgaurav rana tmp = simple_strtoul(p, &endptr, 16);
77047151e4bSgaurav rana if (sizeof(ulong) == 4)
77147151e4bSgaurav rana *num = cpu_to_be32(tmp);
77247151e4bSgaurav rana else
77347151e4bSgaurav rana *num = cpu_to_be64(tmp);
77447151e4bSgaurav rana }
77547151e4bSgaurav rana
77647151e4bSgaurav rana return *p != '\0' && *endptr == '\0';
77747151e4bSgaurav rana }
7786629261dSAneesh Bansal /* Function to calculate the ESBC Image Hash
7796629261dSAneesh Bansal * and hash from Digital signature.
7806629261dSAneesh Bansal * The Two hash's are compared to yield the
7816629261dSAneesh Bansal * result of signature validation.
7826629261dSAneesh Bansal */
calculate_cmp_img_sig(struct fsl_secboot_img_priv * img)7836629261dSAneesh Bansal static int calculate_cmp_img_sig(struct fsl_secboot_img_priv *img)
7846629261dSAneesh Bansal {
7856629261dSAneesh Bansal int ret;
7866629261dSAneesh Bansal uint32_t key_len;
7876629261dSAneesh Bansal struct key_prop prop;
7886629261dSAneesh Bansal #if !defined(USE_HOSTCC)
7896629261dSAneesh Bansal struct udevice *mod_exp_dev;
7906629261dSAneesh Bansal #endif
7916629261dSAneesh Bansal ret = calc_esbchdr_esbc_hash(img);
7926629261dSAneesh Bansal if (ret)
7936629261dSAneesh Bansal return ret;
7946629261dSAneesh Bansal
7956629261dSAneesh Bansal /* Construct encoded hash EM' wrt PKCSv1.5 */
7966629261dSAneesh Bansal construct_img_encoded_hash_second(img);
7976629261dSAneesh Bansal
7986629261dSAneesh Bansal /* Fill prop structure for public key */
7996629261dSAneesh Bansal memset(&prop, 0, sizeof(struct key_prop));
8006629261dSAneesh Bansal key_len = get_key_len(img) / 2;
8016629261dSAneesh Bansal prop.modulus = img->img_key;
8026629261dSAneesh Bansal prop.public_exponent = img->img_key + key_len;
8036629261dSAneesh Bansal prop.num_bits = key_len * 8;
8046629261dSAneesh Bansal prop.exp_len = key_len;
8056629261dSAneesh Bansal
8066629261dSAneesh Bansal ret = uclass_get_device(UCLASS_MOD_EXP, 0, &mod_exp_dev);
8076629261dSAneesh Bansal if (ret) {
8086629261dSAneesh Bansal printf("RSA: Can't find Modular Exp implementation\n");
8096629261dSAneesh Bansal return -EINVAL;
8106629261dSAneesh Bansal }
8116629261dSAneesh Bansal
8126629261dSAneesh Bansal ret = rsa_mod_exp(mod_exp_dev, img->img_sign, img->hdr.sign_len,
8136629261dSAneesh Bansal &prop, img->img_encoded_hash);
8146629261dSAneesh Bansal if (ret)
8156629261dSAneesh Bansal return ret;
8166629261dSAneesh Bansal
8176629261dSAneesh Bansal /*
8186629261dSAneesh Bansal * compare the encoded messages EM' and EM wrt RSA PKCSv1.5
8196629261dSAneesh Bansal * memcmp returns zero on success
8206629261dSAneesh Bansal * memcmp returns non-zero on failure
8216629261dSAneesh Bansal */
8226629261dSAneesh Bansal ret = memcmp(&img->img_encoded_hash_second, &img->img_encoded_hash,
8236629261dSAneesh Bansal img->hdr.sign_len);
8246629261dSAneesh Bansal
8256629261dSAneesh Bansal if (ret)
8266629261dSAneesh Bansal return ERROR_ESBC_CLIENT_HASH_COMPARE_EM;
8276629261dSAneesh Bansal
8286629261dSAneesh Bansal return 0;
8296629261dSAneesh Bansal }
830ac55dadbSUdit Agarwal /* Function to initialize img priv and global data structure
831ac55dadbSUdit Agarwal */
secboot_init(struct fsl_secboot_img_priv ** img_ptr)832ac55dadbSUdit Agarwal static int secboot_init(struct fsl_secboot_img_priv **img_ptr)
833ac55dadbSUdit Agarwal {
834ac55dadbSUdit Agarwal *img_ptr = malloc(sizeof(struct fsl_secboot_img_priv));
835ac55dadbSUdit Agarwal
836ac55dadbSUdit Agarwal struct fsl_secboot_img_priv *img = *img_ptr;
837ac55dadbSUdit Agarwal
838ac55dadbSUdit Agarwal if (!img)
839ac55dadbSUdit Agarwal return -ENOMEM;
840ac55dadbSUdit Agarwal memset(img, 0, sizeof(struct fsl_secboot_img_priv));
841ac55dadbSUdit Agarwal
842ac55dadbSUdit Agarwal #if defined(CONFIG_FSL_ISBC_KEY_EXT)
843ac55dadbSUdit Agarwal if (glb.ie_addr)
844ac55dadbSUdit Agarwal img->ie_addr = glb.ie_addr;
845ac55dadbSUdit Agarwal #endif
846ac55dadbSUdit Agarwal return 0;
847ac55dadbSUdit Agarwal }
848ac55dadbSUdit Agarwal
849ac55dadbSUdit Agarwal
85085bb3896SSaksham Jain /* haddr - Address of the header of image to be validated.
85185bb3896SSaksham Jain * arg_hash_str - Option hash string. If provided, this
8521cc0a9f4SRobert P. J. Day * overrides the key hash in the SFP fuses.
85385bb3896SSaksham Jain * img_addr_ptr - Optional pointer to address of image to be validated.
8541cc0a9f4SRobert P. J. Day * If non zero addr, this overrides the addr of image in header,
85585bb3896SSaksham Jain * otherwise updated to image addr in header.
85685bb3896SSaksham Jain * Acts as both input and output of function.
85785bb3896SSaksham Jain * This pointer shouldn't be NULL.
85885bb3896SSaksham Jain */
fsl_secboot_validate(uintptr_t haddr,char * arg_hash_str,uintptr_t * img_addr_ptr)859b055a0fdSAneesh Bansal int fsl_secboot_validate(uintptr_t haddr, char *arg_hash_str,
86085bb3896SSaksham Jain uintptr_t *img_addr_ptr)
86147151e4bSgaurav rana {
86247151e4bSgaurav rana struct ccsr_sfp_regs *sfp_regs = (void *)(CONFIG_SYS_SFP_ADDR);
86347151e4bSgaurav rana ulong hash[SHA256_BYTES/sizeof(ulong)];
86447151e4bSgaurav rana char hash_str[NUM_HEX_CHARS + 1];
86547151e4bSgaurav rana struct fsl_secboot_img_priv *img;
86647151e4bSgaurav rana struct fsl_secboot_img_hdr *hdr;
86747151e4bSgaurav rana void *esbc;
86847151e4bSgaurav rana int ret, i, hash_cmd = 0;
86947151e4bSgaurav rana u32 srk_hash[8];
87047151e4bSgaurav rana
871bc71f926SAneesh Bansal if (arg_hash_str != NULL) {
872bc71f926SAneesh Bansal const char *cp = arg_hash_str;
87347151e4bSgaurav rana int i = 0;
87447151e4bSgaurav rana
87547151e4bSgaurav rana if (*cp == '0' && *(cp + 1) == 'x')
87647151e4bSgaurav rana cp += 2;
87747151e4bSgaurav rana
87847151e4bSgaurav rana /* The input string expected is in hex, where
87947151e4bSgaurav rana * each 4 bits would be represented by a hex
88047151e4bSgaurav rana * sha256 hash is 256 bits long, which would mean
88147151e4bSgaurav rana * num of characters = 256 / 4
88247151e4bSgaurav rana */
88347151e4bSgaurav rana if (strlen(cp) != SHA256_NIBBLES) {
88447151e4bSgaurav rana printf("%s is not a 256 bits hex string as expected\n",
885bc71f926SAneesh Bansal arg_hash_str);
88647151e4bSgaurav rana return -1;
88747151e4bSgaurav rana }
88847151e4bSgaurav rana
88947151e4bSgaurav rana for (i = 0; i < sizeof(hash)/sizeof(ulong); i++) {
89047151e4bSgaurav rana strncpy(hash_str, cp + (i * NUM_HEX_CHARS),
89147151e4bSgaurav rana NUM_HEX_CHARS);
89247151e4bSgaurav rana hash_str[NUM_HEX_CHARS] = '\0';
89347151e4bSgaurav rana if (!str2longbe(hash_str, &hash[i])) {
89447151e4bSgaurav rana printf("%s is not a 256 bits hex string ",
895bc71f926SAneesh Bansal arg_hash_str);
89647151e4bSgaurav rana return -1;
89747151e4bSgaurav rana }
89847151e4bSgaurav rana }
89947151e4bSgaurav rana
90047151e4bSgaurav rana hash_cmd = 1;
90147151e4bSgaurav rana }
90247151e4bSgaurav rana
903ac55dadbSUdit Agarwal ret = secboot_init(&img);
904ac55dadbSUdit Agarwal if (ret)
905ac55dadbSUdit Agarwal goto exit;
90647151e4bSgaurav rana
907b055a0fdSAneesh Bansal /* Update the information in Private Struct */
90847151e4bSgaurav rana hdr = &img->hdr;
909bc71f926SAneesh Bansal img->ehdrloc = haddr;
91085bb3896SSaksham Jain img->img_addr_ptr = img_addr_ptr;
911b055a0fdSAneesh Bansal esbc = (u8 *)img->ehdrloc;
91247151e4bSgaurav rana
91347151e4bSgaurav rana memcpy(hdr, esbc, sizeof(struct fsl_secboot_img_hdr));
91447151e4bSgaurav rana
91547151e4bSgaurav rana /* read and validate esbc header */
91647151e4bSgaurav rana ret = read_validate_esbc_client_header(img);
91747151e4bSgaurav rana
91847151e4bSgaurav rana if (ret != ESBC_VALID_HDR) {
91947151e4bSgaurav rana fsl_secboot_handle_error(ret);
92047151e4bSgaurav rana goto exit;
92147151e4bSgaurav rana }
92247151e4bSgaurav rana
92347151e4bSgaurav rana /* SRKH present in SFP */
92447151e4bSgaurav rana for (i = 0; i < NUM_SRKH_REGS; i++)
92547151e4bSgaurav rana srk_hash[i] = srk_in32(&sfp_regs->srk_hash[i]);
92647151e4bSgaurav rana
92747151e4bSgaurav rana /*
92847151e4bSgaurav rana * Calculate hash of key obtained via offset present in
92947151e4bSgaurav rana * ESBC uboot client hdr
93047151e4bSgaurav rana */
93147151e4bSgaurav rana ret = calc_img_key_hash(img);
93247151e4bSgaurav rana if (ret) {
93347151e4bSgaurav rana fsl_secblk_handle_error(ret);
93447151e4bSgaurav rana goto exit;
93547151e4bSgaurav rana }
93647151e4bSgaurav rana
93747151e4bSgaurav rana /* Compare hash obtained above with SRK hash present in SFP */
93847151e4bSgaurav rana if (hash_cmd)
93947151e4bSgaurav rana ret = memcmp(&hash, &img->img_key_hash, SHA256_BYTES);
94047151e4bSgaurav rana else
94147151e4bSgaurav rana ret = memcmp(srk_hash, img->img_key_hash, SHA256_BYTES);
94247151e4bSgaurav rana
94347151e4bSgaurav rana #if defined(CONFIG_FSL_ISBC_KEY_EXT)
94447151e4bSgaurav rana if (!hash_cmd && check_ie(img))
94547151e4bSgaurav rana ret = 0;
94647151e4bSgaurav rana #endif
94747151e4bSgaurav rana
94847151e4bSgaurav rana if (ret != 0) {
94947151e4bSgaurav rana fsl_secboot_handle_error(ERROR_ESBC_CLIENT_HASH_COMPARE_KEY);
95047151e4bSgaurav rana goto exit;
95147151e4bSgaurav rana }
95247151e4bSgaurav rana
9536629261dSAneesh Bansal ret = calculate_cmp_img_sig(img);
95447151e4bSgaurav rana if (ret) {
9556629261dSAneesh Bansal fsl_secboot_handle_error(ret);
95647151e4bSgaurav rana goto exit;
95747151e4bSgaurav rana }
95847151e4bSgaurav rana
95947151e4bSgaurav rana exit:
960ac55dadbSUdit Agarwal /* Free Img as it was malloc'ed*/
961ac55dadbSUdit Agarwal free(img);
962bc71f926SAneesh Bansal return ret;
96347151e4bSgaurav rana }
964