All of lore.kernel.org
 help / color / mirror / Atom feed
From: Stefano Babic <sbabic@denx.de>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH v3] imx: Support i.MX6 High Assurance Boot authentication
Date: Fri, 12 Sep 2014 10:46:31 +0200	[thread overview]
Message-ID: <5412B2E7.6080502@denx.de> (raw)
In-Reply-To: <1409793521-11428-1-git-send-email-nitin.garg@freescale.com>

Hi Nitin,

On 04/09/2014 03:18, Nitin Garg wrote:
> When CONFIG_SECURE_BOOT is enabled, the signed images
> like kernel and dtb can be authenticated using iMX6 CAAM.
> The added command hab_auth_img can be used for HAB
> authentication of images. The command takes the image
> DDR location, IVT (Image Vector Table) offset inside
> image as parameters. Detailed info about signing images
> can be found in Freescale AppNote AN4581.
> 
> Signed-off-by: Nitin Garg <nitin.garg@freescale.com>
> 
> ---
> 
> Changes in v3:
> - Remove typecast of get_cpu_rev since its not required
> 
> Changes in v2:
> - Cleaned up clock code as per review comments
> - Removed dead code as per review comments
> - Re-written commit log as per review comments
> 
>  arch/arm/cpu/armv7/mx6/clock.c        |   32 ++++++-
>  arch/arm/cpu/armv7/mx6/hab.c          |  165 ++++++++++++++++++++++++++++++++-
>  arch/arm/cpu/armv7/mx6/soc.c          |   15 +++
>  arch/arm/include/asm/arch-mx6/clock.h |    4 +
>  4 files changed, 214 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm/cpu/armv7/mx6/clock.c b/arch/arm/cpu/armv7/mx6/clock.c
> index 820b8d5..db6a8fc 100644
> --- a/arch/arm/cpu/armv7/mx6/clock.c
> +++ b/arch/arm/cpu/armv7/mx6/clock.c
> @@ -1,5 +1,5 @@
>  /*
> - * Copyright (C) 2010-2011 Freescale Semiconductor, Inc.
> + * Copyright (C) 2010-2014 Freescale Semiconductor, Inc.
>   *
>   * SPDX-License-Identifier:	GPL-2.0+
>   */
> @@ -543,6 +543,36 @@ int enable_pcie_clock(void)
>  			       BM_ANADIG_PLL_ENET_ENABLE_PCIE);
>  }
>  
> +#ifdef CONFIG_SECURE_BOOT
> +void hab_caam_clock_enable(void)
> +{
> +	struct mxc_ccm_reg *const imx_ccm =
> +		(struct mxc_ccm_reg *)CCM_BASE_ADDR;
> +
> +	/*CG4 ~ CG6, enable CAAM clocks*/
> +	setbits_le32(&imx_ccm->CCGR0, MXC_CCM_CCGR0_CAAM_WRAPPER_IPG_MASK |
> +		     MXC_CCM_CCGR0_CAAM_WRAPPER_ACLK_MASK |
> +		     MXC_CCM_CCGR0_CAAM_SECURE_MEM_MASK);
> +
> +	/* Enable EMI slow clk */
> +	setbits_le32(&imx_ccm->CCGR6, MXC_CCM_CCGR6_EMI_SLOW_MASK);
> +}
> +
> +void hab_caam_clock_disable(void)
> +{
> +	struct mxc_ccm_reg *const imx_ccm =
> +		(struct mxc_ccm_reg *)CCM_BASE_ADDR;
> +
> +	/*CG4 ~ CG6, disable CAAM clocks*/
> +	clrbits_le32(&imx_ccm->CCGR0, MXC_CCM_CCGR0_CAAM_WRAPPER_IPG_MASK |
> +		     MXC_CCM_CCGR0_CAAM_WRAPPER_ACLK_MASK |
> +		     MXC_CCM_CCGR0_CAAM_SECURE_MEM_MASK);
> +
> +	/* Disable EMI slow clk */
> +	clrbits_le32(&imx_ccm->CCGR6, MXC_CCM_CCGR6_EMI_SLOW_MASK);
> +}
> +#endif


Generally, we have in clock.c one function per clock, getting as
enable_uart_clkparameter a boolean for enabling/disabling (i.e.
enable_ocotp_clk(), enable_uart_clk(),...)

Please stick with the same rule.

> +
>  unsigned int mxc_get_clock(enum mxc_clock clk)
>  {
>  	switch (clk) {
> diff --git a/arch/arm/cpu/armv7/mx6/hab.c b/arch/arm/cpu/armv7/mx6/hab.c
> index f6810a6..61a94a1 100644
> --- a/arch/arm/cpu/armv7/mx6/hab.c
> +++ b/arch/arm/cpu/armv7/mx6/hab.c
> @@ -1,5 +1,5 @@
>  /*
> - * Copyright (C) 2010-2013 Freescale Semiconductor, Inc.
> + * Copyright (C) 2010-2014 Freescale Semiconductor, Inc.
>   *
>   * SPDX-License-Identifier:    GPL-2.0+
>   */
> @@ -7,8 +7,12 @@
>  #include <common.h>
>  #include <asm/io.h>
>  #include <asm/arch/hab.h>
> +#include <asm/arch/clock.h>
>  #include <asm/arch/sys_proto.h>
>  
> +/* HAB (High Assurance Boot) debug */
> +#undef DEBUG_AUTHENTICATE_IMAGE

This is never defined, you do not need to undefine it.

> +
>  /* -------- start of HAB API updates ------------*/
>  
>  #define hab_rvt_report_event_p					\
> @@ -71,6 +75,41 @@
>  	((hab_rvt_exit_t *)HAB_RVT_EXIT)			\
>  )
>  
> +#define IVT_SIZE		0x20
> +#define ALIGN_SIZE		0x1000
> +#define CSF_PAD_SIZE		0x2000
> +
> +/*
> + * +------------+  0x0 (DDR_UIMAGE_START) -
> + * |   Header   |                          |
> + * +------------+  0x40                    |
> + * |            |                          |
> + * |            |                          |
> + * |            |                          |
> + * |            |                          |
> + * | Image Data |                          |
> + * .            |                          |
> + * .            |                           > Stuff to be authenticated ----+
> + * .            |                          |                                |
> + * |            |                          |                                |
> + * |            |                          |                                |
> + * +------------+                          |                                |
> + * |            |                          |                                |
> + * | Fill Data  |                          |                                |
> + * |            |                          |                                |
> + * +------------+ Align to ALIGN_SIZE      |                                |
> + * |    IVT     |                          |                                |
> + * +------------+ + IVT_SIZE              -                                 |
> + * |            |                                                           |
> + * |  CSF DATA  | <---------------------------------------------------------+
> + * |            |
> + * +------------+
> + * |            |
> + * | Fill Data  |
> + * |            |
> + * +------------+ + CSF_PAD_SIZE
> + */
> +
>  bool is_hab_enabled(void)
>  {
>  	struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
> @@ -144,6 +183,105 @@ int get_hab_status(void)
>  	return 0;
>  }
>  
> +uint32_t authenticate_image(uint32_t ddr_start, uint32_t image_size)
> +{
> +	uint32_t load_addr = 0;
> +	size_t bytes;
> +	ptrdiff_t ivt_offset = 0;
> +	int result = 0;
> +	ulong start;
> +	hab_rvt_authenticate_image_t *hab_rvt_authenticate_image;
> +	hab_rvt_entry_t *hab_rvt_entry;
> +	hab_rvt_exit_t *hab_rvt_exit;
> +
> +	hab_rvt_authenticate_image = hab_rvt_authenticate_image_p;
> +	hab_rvt_entry = hab_rvt_entry_p;
> +	hab_rvt_exit = hab_rvt_exit_p;
> +
> +	if (is_hab_enabled()) {
> +		printf("\nAuthenticate image from DDR location 0x%x...\n",
> +		       ddr_start);
> +
> +		hab_caam_clock_enable();
> +
> +		if (hab_rvt_entry() == HAB_SUCCESS) {
> +			/* If not already aligned, Align to ALIGN_SIZE */
> +			ivt_offset = (image_size + ALIGN_SIZE - 1) &
> +					~(ALIGN_SIZE - 1);
> +
> +			start = ddr_start;
> +			bytes = ivt_offset + IVT_SIZE + CSF_PAD_SIZE;
> +
> +#ifdef DEBUG_AUTHENTICATE_IMAGE


We have already a way for adding debugging. Use debug() instead of
printf(), and you can simply use #ifdef DEBUG for conditional branches.

We decided some times ago to avoid adding any flavour of specific DEBUG_
switches.


> +			printf("\nivt_offset = 0x%x, ivt addr = 0x%x\n",
> +			       ivt_offset, ddr_start + ivt_offset);
> +			printf("Dumping IVT\n");
> +			print_buffer(ddr_start + ivt_offset,
> +				     (void *)(ddr_start + ivt_offset),
> +				     4, 0x8, 0);
> +
> +			printf("Dumping CSF Header\n");
> +			print_buffer(ddr_start + ivt_offset+IVT_SIZE,
> +				     (void *)(ddr_start + ivt_offset+IVT_SIZE),
> +				     4, 0x10, 0);
> +
> +			get_hab_status();
> +
> +			printf("\nCalling authenticate_image in ROM\n");
> +			printf("\tivt_offset = 0x%x\n", ivt_offset);
> +			printf("\tstart = 0x%08lx\n", start);
> +			printf("\tbytes = 0x%x\n", bytes);
> +#endif
> +			/*
> +			 * If the MMU is enabled, we have to notify the ROM
> +			 * code, or it won't flush the caches when needed.
> +			 * This is done, by setting the "pu_irom_mmu_enabled"
> +			 * word to 1. You can find its address by looking in
> +			 * the ROM map. This is critical for
> +			 * authenticate_image(). If MMU is enabled, without
> +			 * setting this but, authentication will fail and may
> +			 * crash.
> +			 */
> +			if (is_cpu_type(MXC_CPU_MX6Q) ||
> +			    is_cpu_type(MXC_CPU_MX6D)) {
> +				/*
> +				 * This won't work on Rev 1.0.0 of i.MX6Q/D,
> +				 * since their ROM doesn't do cache flushes.
> +				 * I don't think any exist, so we ignore them.
> +				 */
> +				writel(1, 0x009024a8);

Can you add defines or (better) structures for this ? Writing in this
way into the hardware is generally not allowed in u-boot.

In the comments you say that it must be checked if MMU is on (generally
on when cache is enabled), but there is no check afterward, only a
different behavior depending on CPU. Does it mean that
pu_irom_mmu_enabled is set independently from MMU status ?

> +			} else if (is_cpu_type(MXC_CPU_MX6DL) ||
> +				   is_cpu_type(MXC_CPU_MX6SOLO)) {
> +				writel(1, 0x00901dd0);
> +			} else if (is_cpu_type(MXC_CPU_MX6SL)) {
> +				writel(1, 0x00900a18);
> +			}
> +
> +			load_addr = (uint32_t)hab_rvt_authenticate_image(
> +					HAB_CID_UBOOT,
> +					ivt_offset, (void **)&start,
> +					(size_t *)&bytes, NULL);
> +			if (hab_rvt_exit() != HAB_SUCCESS) {
> +				printf("hab exit function fail\n");
> +				load_addr = 0;
> +			}
> +		} else {
> +			printf("hab entry function fail\n");

Use puts() instead of printf() when you want to output a constant string.

> +		}
> +
> +		hab_caam_clock_disable();
> +
> +		get_hab_status();
> +	} else {
> +		printf("hab fuse not enabled\n");
> +	}
> +
> +	if ((!is_hab_enabled()) || (load_addr != 0))
> +		result = 1;
> +
> +	return result;
> +}
> +
>  int do_hab_status(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
>  {
>  	if ((argc != 1)) {
> @@ -156,8 +294,33 @@ int do_hab_status(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
>  	return 0;
>  }
>  
> +static int do_authenticate_image(cmd_tbl_t *cmdtp, int flag, int argc,
> +				char * const argv[])
> +{
> +	ulong	addr, ivt_offset;
> +	int	rcode = 0;
> +
> +	if (argc < 3)
> +		return CMD_RET_USAGE;
> +
> +	addr = simple_strtoul(argv[1], NULL, 16);
> +	ivt_offset = simple_strtoul(argv[2], NULL, 16);
> +
> +	rcode = authenticate_image(addr, ivt_offset);
> +
> +	return rcode;
> +}
> +
>  U_BOOT_CMD(
>  		hab_status, CONFIG_SYS_MAXARGS, 1, do_hab_status,
>  		"display HAB status",
>  		""
>  	  );
> +
> +U_BOOT_CMD(
> +		hab_auth_img, 3, 1, do_authenticate_image,
> +		"authenticate image via HAB",
> +		"addr ivt_offset\n"
> +		"addr - image hex address\n"
> +		"ivt_offset - hex offset of IVT in the image"
> +	  );
> diff --git a/arch/arm/cpu/armv7/mx6/soc.c b/arch/arm/cpu/armv7/mx6/soc.c
> index b0c1306..9842efb 100644
> --- a/arch/arm/cpu/armv7/mx6/soc.c
> +++ b/arch/arm/cpu/armv7/mx6/soc.c
> @@ -409,10 +409,25 @@ int board_postclk_init(void)
>  #ifndef CONFIG_SYS_DCACHE_OFF
>  void enable_caches(void)
>  {
> +#if defined(CONFIG_SYS_ARM_CACHE_WRITETHROUGH)
> +	enum dcache_option option = DCACHE_WRITETHROUGH;
> +#else
> +	enum dcache_option option = DCACHE_WRITEBACK;
> +#endif
> +
>  	/* Avoid random hang when download by usb */
>  	invalidate_dcache_all();
> +
>  	/* Enable D-cache. I-cache is already enabled in start.S */
>  	dcache_enable();
> +
> +	/* Enable caching on OCRAM and ROM */
> +	mmu_set_region_dcache_behaviour(ROMCP_ARB_BASE_ADDR,
> +					ROMCP_ARB_END_ADDR,
> +					option);
> +	mmu_set_region_dcache_behaviour(IRAM_BASE_ADDR,
> +					IRAM_SIZE,
> +					option);
>  }
>  #endif
>  
> diff --git a/arch/arm/include/asm/arch-mx6/clock.h b/arch/arm/include/asm/arch-mx6/clock.h
> index 339c789..2482e1a 100644
> --- a/arch/arm/include/asm/arch-mx6/clock.h
> +++ b/arch/arm/include/asm/arch-mx6/clock.h
> @@ -2,6 +2,8 @@
>   * (C) Copyright 2009
>   * Stefano Babic, DENX Software Engineering, sbabic at denx.de.
>   *
> + * (C) Copyright 2014 Freescale Semiconductor, Inc.
> + *
>   * SPDX-License-Identifier:	GPL-2.0+
>   */
>  
> @@ -60,4 +62,6 @@ int enable_i2c_clk(unsigned char enable, unsigned i2c_num);
>  int enable_spi_clk(unsigned char enable, unsigned spi_num);
>  void enable_ipu_clock(void);
>  int enable_fec_anatop_clock(enum enet_freq freq);
> +void hab_caam_clock_enable(void);
> +void hab_caam_clock_disable(void);
>  #endif /* __ASM_ARCH_CLOCK_H */
> 

I have not found enough documentation to verify this: is this code
suitable for MX53, too ? I can see in MX53 manual that a "CAAM" is
available, but nothing more as that.

Best regards,
Stefano Babic

-- 
=====================================================================
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-53 Fax: +49-8142-66989-80 Email: sbabic at denx.de
=====================================================================

  reply	other threads:[~2014-09-12  8:46 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-09-04  1:18 [U-Boot] [PATCH v3] imx: Support i.MX6 High Assurance Boot authentication Nitin Garg
2014-09-12  8:46 ` Stefano Babic [this message]
2014-09-16 18:37   ` Nitin Garg

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=5412B2E7.6080502@denx.de \
    --to=sbabic@denx.de \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.