summaryrefslogtreecommitdiff
path: root/arch/arm/mach-imx/hab.c
diff options
context:
space:
mode:
authorUtkarsh Gupta <utkarsh.gupta@nxp.com>2018-02-20 01:19:24 +0000
committerStefano Babic <sbabic@denx.de>2018-02-22 14:35:42 +0100
commited286bc80e9d237dd1732ced037427e7d9a277a0 (patch)
tree733d66e1d419d0c16cc4f65c676f1d6634391a09 /arch/arm/mach-imx/hab.c
parent8c4037a09a5c2f15aae4c79860a31c8045bd4ee8 (diff)
imx: hab: Check if CSF is valid before authenticating image
For proper authentication the HAB code must check if the CSF is valid. Users must call the csf_is_valid() function to parse the CSF prior to authenticating any additional images. The function will return a failure if any of the following invalid conditions are met: - CSF pointer is NULL - CSF Header does not exist - CSF does not lie within the image bounds - CSF command length zero Signed-off-by: Utkarsh Gupta <utkarsh.gupta@nxp.com> Signed-off-by: Breno Lima <breno.lima@nxp.com> Reviewed-by: Fabio Estevam <fabio.estevam@nxp.com>
Diffstat (limited to 'arch/arm/mach-imx/hab.c')
-rw-r--r--arch/arm/mach-imx/hab.c81
1 files changed, 81 insertions, 0 deletions
diff --git a/arch/arm/mach-imx/hab.c b/arch/arm/mach-imx/hab.c
index ba6b31d490..7f66965af5 100644
--- a/arch/arm/mach-imx/hab.c
+++ b/arch/arm/mach-imx/hab.c
@@ -453,6 +453,83 @@ U_BOOT_CMD(
#endif /* !defined(CONFIG_SPL_BUILD) */
+/* Get CSF Header length */
+static int get_hab_hdr_len(struct hab_hdr *hdr)
+{
+ return (size_t)((hdr->len[0] << 8) + (hdr->len[1]));
+}
+
+/* Check whether addr lies between start and
+ * end and is within the length of the image
+ */
+static int chk_bounds(u8 *addr, size_t bytes, u8 *start, u8 *end)
+{
+ size_t csf_size = (size_t)((end + 1) - addr);
+
+ return (addr && (addr >= start) && (addr <= end) &&
+ (csf_size >= bytes));
+}
+
+/* Get Length of each command in CSF */
+static int get_csf_cmd_hdr_len(u8 *csf_hdr)
+{
+ if (*csf_hdr == HAB_CMD_HDR)
+ return sizeof(struct hab_hdr);
+
+ return get_hab_hdr_len((struct hab_hdr *)csf_hdr);
+}
+
+/* Check if CSF is valid */
+static bool csf_is_valid(struct ivt *ivt, ulong start_addr, size_t bytes)
+{
+ u8 *start = (u8 *)start_addr;
+ u8 *csf_hdr;
+ u8 *end;
+
+ size_t csf_hdr_len;
+ size_t cmd_hdr_len;
+ size_t offset = 0;
+
+ if (bytes != 0)
+ end = start + bytes - 1;
+ else
+ end = start;
+
+ /* Verify if CSF pointer content is zero */
+ if (!ivt->csf) {
+ puts("Error: CSF pointer is NULL\n");
+ return false;
+ }
+
+ csf_hdr = (u8 *)ivt->csf;
+
+ /* Verify if CSF Header exist */
+ if (*csf_hdr != HAB_CMD_HDR) {
+ puts("Error: CSF header command not found\n");
+ return false;
+ }
+
+ csf_hdr_len = get_hab_hdr_len((struct hab_hdr *)csf_hdr);
+
+ /* Check if the CSF lies within the image bounds */
+ if (!chk_bounds(csf_hdr, csf_hdr_len, start, end)) {
+ puts("Error: CSF lies outside the image bounds\n");
+ return false;
+ }
+
+ do {
+ cmd_hdr_len = get_csf_cmd_hdr_len(&csf_hdr[offset]);
+ if (!cmd_hdr_len) {
+ puts("Error: Invalid command length\n");
+ return false;
+ }
+ offset += cmd_hdr_len;
+
+ } while (offset < csf_hdr_len);
+
+ return true;
+}
+
bool imx_hab_is_enabled(void)
{
struct imx_sec_config_fuse_t *fuse =
@@ -525,6 +602,10 @@ int imx_hab_authenticate_image(uint32_t ddr_start, uint32_t image_size,
start = ddr_start;
bytes = image_size;
+ /* Verify CSF */
+ if (!csf_is_valid(ivt, start, bytes))
+ goto hab_authentication_exit;
+
if (hab_rvt_entry() != HAB_SUCCESS) {
puts("hab entry function fail\n");
goto hab_exit_failure_print_status;