diff options
author | Utkarsh Gupta <utkarsh.gupta@nxp.com> | 2017-11-17 19:20:33 -0600 |
---|---|---|
committer | Utkarsh Gupta <utkarsh.gupta@nxp.com> | 2017-11-17 19:20:33 -0600 |
commit | 1167e4dae890dd74f2f181c5b01bf8f5c5ba4977 (patch) | |
tree | 6ddac3c4c388ab5f8967787029db9c221a19c9c2 | |
parent | 345bcc28e52eff7a8cee7fee787db9453bcd457f (diff) |
MLK-16703: HAB : Check if CSF is valid before authenticating image
For proper authentication users must check if the CSF is valid. This patch
calls the csf_is_valid function prior to authenticating the image to parse
the CSF and returns a failure if an invalid command is found as shown below.
Authenticate image from DDR location 0x12000000...
Check CSF for Write Data command before authenticating image
Error - WRITE Data command found
Authenticate zImage Fail, Please check
Signed-off-by: Utkarsh Gupta <utkarsh.gupta@nxp.com>
-rw-r--r-- | arch/arm/imx-common/hab.c | 92 | ||||
-rw-r--r-- | arch/arm/include/asm/imx-common/hab.h | 24 |
2 files changed, 116 insertions, 0 deletions
diff --git a/arch/arm/imx-common/hab.c b/arch/arm/imx-common/hab.c index babf09be76..0747e499b1 100644 --- a/arch/arm/imx-common/hab.c +++ b/arch/arm/imx-common/hab.c @@ -506,6 +506,92 @@ static bool is_hab_enabled(void) return (reg & IS_HAB_ENABLED_BIT) == IS_HAB_ENABLED_BIT; } +/* + * Check whether addr lies between start and end and is within + * the length of the image + */ +static inline int chk_bounds(const uint8_t *addr, size_t bytes, + const uint8_t *start, const uint8_t *end) +{ + return (addr && (addr >= start) && (addr <= end) && + ((size_t)((end + 1) - addr) >= bytes)) + ? 1 : 0; +} + +/* Get Length of each command in CSF */ +static inline int get_csf_cmd_hdr_len(const uint8_t *csf_hdr) +{ + if (*csf_hdr == HAB_CMD_HDR) + return sizeof(struct hab_hdr); + + return HAB_HDR_LEN(*(const struct hab_hdr *)csf_hdr); +} + +/* + * Check if CSF has Write data command + * + * If WRITE DATA command exists, then return failure + */ +static int csf_is_valid(int ivt_offset, ulong start_addr, size_t bytes) +{ + size_t offset = 0; + size_t cmd_hdr_len = 0; + size_t csf_hdr_len = 0; + + const struct hab_ivt *ivt_initial = NULL; + const uint8_t *csf_hdr = NULL; + const uint8_t *end = NULL; + const uint8_t *start = (const uint8_t *)start_addr; + + ivt_initial = (const struct hab_ivt *)(start + ivt_offset); + + if (bytes != 0) + end = start + bytes - 1; + else + end = start; + + /* Check that the CSF lies within the image bounds */ + if ((start == 0) || (ivt_initial == NULL) || + (ivt_initial->csf == 0) || + !chk_bounds((const uint8_t *)ivt_initial->csf, + HAB_HDR_LEN(*(const struct hab_hdr *)ivt_initial->csf), + start, end)) { + puts("Error - CSF lies outside the image bounds\n"); + return 0; + } + + csf_hdr = (const uint8_t *)ivt_initial->csf; + + if (*csf_hdr == HAB_CMD_HDR) { + csf_hdr_len = HAB_HDR_LEN(*(const struct hab_hdr *)csf_hdr); + } else { + puts("Error - CSF header command not found\n"); + return 0; + } + + /* Check for Write data command in CSF */ + do { + switch (csf_hdr[offset]) { + case (HAB_CMD_WRT_DAT): + puts("Error - WRITE Data command found\n"); + return 0; + default: + break; + } + + cmd_hdr_len = get_csf_cmd_hdr_len(&csf_hdr[offset]); + if (!cmd_hdr_len) { + puts("Error - Invalid command length\n"); + return 0; + } + offset += cmd_hdr_len; + + } while (offset < csf_hdr_len); + + /* Write Data command not found */ + return 1; +} + uint32_t authenticate_image(uint32_t ddr_start, uint32_t image_size) { ulong load_addr = 0; @@ -527,6 +613,12 @@ uint32_t authenticate_image(uint32_t ddr_start, uint32_t image_size) start = ddr_start; bytes = ivt_offset + IVT_SIZE + CSF_PAD_SIZE; + + puts("Check CSF for Write Data command before "); + puts("authenticating image\n"); + if (!csf_is_valid(ivt_offset, start, bytes)) + return result; + #ifdef DEBUG printf("\nivt_offset = 0x%x, ivt addr = 0x%x\n", ivt_offset, ddr_start + ivt_offset); diff --git a/arch/arm/include/asm/imx-common/hab.h b/arch/arm/include/asm/imx-common/hab.h index 808dd9ed9d..3b1b3767f3 100644 --- a/arch/arm/include/asm/imx-common/hab.h +++ b/arch/arm/include/asm/imx-common/hab.h @@ -90,6 +90,23 @@ struct imx_sec_config_fuse_t { int word; }; +struct __packed hab_hdr { + uint8_t tag; /* Tag field */ + uint8_t len[2]; /* Length field in bytes (big-endian) */ + uint8_t par; /* Parameters field */ +}; + +struct hab_ivt { + struct hab_hdr hdr; + uint32_t entry; + uint32_t reserved1; + uint32_t dcd; + uint32_t boot_data; + uint32_t self; + uint32_t csf; + uint32_t reserved2; +}; + #if defined(CONFIG_SECURE_BOOT) extern struct imx_sec_config_fuse_t const imx_sec_config_fuse; #endif @@ -150,6 +167,13 @@ typedef void hapi_clock_init_t(void); #define HAB_CID_ROM 0 /**< ROM Caller ID */ #define HAB_CID_UBOOT 1 /**< UBOOT Caller ID*/ +#define HAB_CMD_HDR 0xD4 /* CSF Header */ +#define HAB_CMD_WRT_DAT 0xCC /* Write Data */ + +#define HAB_HDR_LEN(hdr) \ + ((size_t)(((const struct hab_hdr *)&(hdr))->len[0] << 8) \ + + (size_t)((const struct hab_hdr *)&(hdr))->len[1]) + /* ----------- end of HAB API updates ------------*/ uint32_t authenticate_image(uint32_t ddr_start, uint32_t image_size); |