powerpc/mpc85xx: SECURE BOOT- Enable chain of trust in SPL
authorSumit Garg <sumit.garg@nxp.com>
Thu, 14 Jul 2016 16:27:51 +0000 (12:27 -0400)
committerYork Sun <york.sun@nxp.com>
Thu, 21 Jul 2016 18:09:23 +0000 (11:09 -0700)
As part of Chain of Trust for Secure boot, the SPL U-Boot will validate
the next level U-boot image. Add a new function spl_validate_uboot to
perform the validation.

Enable hardware crypto operations in SPL using SEC block.
In case of Secure Boot, PAMU is not bypassed. For allowing SEC block
access to CPC configured as SRAM, configure PAMU.

Reviewed-by: Ruchika Gupta <ruchika.gupta@nxp.com>
Signed-off-by: Aneesh Bansal <aneesh.bansal@nxp.com>
Signed-off-by: Sumit Garg <sumit.garg@nxp.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Reviewed-by: York Sun <york.sun@nxp.com>
arch/powerpc/cpu/mpc8xxx/fsl_pamu.c
arch/powerpc/cpu/mpc8xxx/pamu_table.c
arch/powerpc/include/asm/fsl_secure_boot.h
board/freescale/common/fsl_chain_of_trust.c
drivers/crypto/fsl/jr.c
drivers/mtd/nand/fsl_ifc_spl.c
include/fsl_validate.h

index 9421f1ebf6f312c081cb9f295e33fc5c4b1707ca..ede8e662104e890ec03bfa14724ed3dca38a096d 100644 (file)
@@ -239,15 +239,23 @@ int pamu_init(void)
        spaact_size = sizeof(struct paace) * NUM_SPAACT_ENTRIES;
 
        /* Allocate space for Primary PAACT Table */
+#if (defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_PPAACT_ADDR))
+       ppaact = (void *)CONFIG_SPL_PPAACT_ADDR;
+#else
        ppaact = memalign(PAMU_TABLE_ALIGNMENT, ppaact_size);
        if (!ppaact)
                return -1;
+#endif
        memset(ppaact, 0, ppaact_size);
 
        /* Allocate space for Secondary PAACT Table */
+#if (defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_SPAACT_ADDR))
+       sec = (void *)CONFIG_SPL_SPAACT_ADDR;
+#else
        sec = memalign(PAMU_TABLE_ALIGNMENT, spaact_size);
        if (!sec)
                return -1;
+#endif
        memset(sec, 0, spaact_size);
 
        ppaact_phys = virt_to_phys((void *)ppaact);
index 26c5ea4fd7a9fd13a73e54aa0f7dbd1d630092b0..a8e6f5177713ea31489703e026f70f0e879272fd 100644 (file)
@@ -28,6 +28,14 @@ void construct_pamu_addr_table(struct pamu_addr_tbl *tbl, int *num_entries)
 
        i++;
 #endif
+#if (defined(CONFIG_SPL_BUILD) && (CONFIG_SYS_INIT_L3_VADDR))
+       tbl->start_addr[i] =
+               (uint64_t)virt_to_phys((void *)CONFIG_SYS_INIT_L3_VADDR);
+       tbl->size[i] = 256 * 1024; /* 256K CPC flash */
+       tbl->end_addr[i] = tbl->start_addr[i] +  tbl->size[i] - 1;
+
+       i++;
+#endif
        debug("PAMU address\t\t\tsize\n");
        for (j = 0; j < i ; j++)
                debug("%llx \t\t\t%llx\n",  tbl->start_addr[j],  tbl->size[j]);
index 826f9c960e956aec2a630b73bee8aa160450dae4..9420021d640778ef81e995dc64455a555c3ca8ce 100644 (file)
 
 #ifdef CONFIG_CHAIN_OF_TRUST
 
+#ifdef CONFIG_SPL_BUILD
+#define CONFIG_SPL_DM                  1
+#define CONFIG_SPL_CRYPTO_SUPPORT
+#define CONFIG_SPL_HASH_SUPPORT
+#define CONFIG_SPL_RSA
+#define CONFIG_SPL_DRIVERS_MISC_SUPPORT
+/*
+ * PPAACT and SPAACT table for PAMU must be placed on DDR after DDR init
+ * due to space crunch on CPC and thus malloc will not work.
+ */
+#define CONFIG_SPL_PPAACT_ADDR         0x2e000000
+#define CONFIG_SPL_SPAACT_ADDR         0x2f000000
+#define CONFIG_SPL_JR0_LIODN_S         454
+#define CONFIG_SPL_JR0_LIODN_NS                458
+/*
+ * Define the key hash for U-Boot here if public/private key pair used to
+ * sign U-boot are different from the SRK hash put in the fuse
+ * Example of defining KEY_HASH is
+ * #define CONFIG_SPL_UBOOT_KEY_HASH \
+ *      "41066b564c6ffcef40ccbc1e0a5d0d519604000c785d97bbefd25e4d288d1c8b"
+ * else leave it defined as NULL
+ */
+
+#define CONFIG_SPL_UBOOT_KEY_HASH      NULL
+#endif /* ifdef CONFIG_SPL_BUILD */
+
 #define CONFIG_CMD_ESBC_VALIDATE
 #define CONFIG_CMD_BLOB
 #define CONFIG_FSL_SEC_MON
 #define CONFIG_FSL_CAAM
 #endif
 
-/* fsl_setenv_chain_of_trust() must be called from
+#ifndef CONFIG_SPL_BUILD
+/*
+ * fsl_setenv_chain_of_trust() must be called from
  * board_late_init()
  */
 #ifndef CONFIG_BOARD_LATE_INIT
 #endif /* #ifdef CONFIG_BOOTSCRIPT_COPY_RAM */
 
 #include <config_fsl_chain_trust.h>
+#endif /* #ifndef CONFIG_SPL_BUILD */
 #endif /* #ifdef CONFIG_CHAIN_OF_TRUST */
 #endif
index ecfcc8253a88b5a5700678cbbedeb83c26bbdc4b..290536db154d3539dcf947e9bcdbaa4273e44ecd 100644 (file)
@@ -6,7 +6,17 @@
 
 #include <common.h>
 #include <fsl_validate.h>
+#include <fsl_secboot_err.h>
 #include <fsl_sfp.h>
+#include <dm/root.h>
+
+#ifdef CONFIG_ADDR_MAP
+#include <asm/mmu.h>
+#endif
+
+#ifdef CONFIG_FSL_CORENET
+#include <asm/fsl_pamu.h>
+#endif
 
 #ifdef CONFIG_LS102XA
 #include <asm/arch/immap_ls102xa.h>
@@ -52,6 +62,7 @@ int fsl_check_boot_mode_secure(void)
        return 0;
 }
 
+#ifndef CONFIG_SPL_BUILD
 int fsl_setenv_chain_of_trust(void)
 {
        /* Check Boot Mode
@@ -68,3 +79,48 @@ int fsl_setenv_chain_of_trust(void)
        setenv("bootcmd", CONFIG_CHAIN_BOOT_CMD);
        return 0;
 }
+#endif
+
+#ifdef CONFIG_SPL_BUILD
+void spl_validate_uboot(uint32_t hdr_addr, uintptr_t img_addr)
+{
+       int res;
+
+       /*
+        * Check Boot Mode
+        * If Boot Mode is Non-Secure, skip validation
+        */
+       if (fsl_check_boot_mode_secure() == 0)
+               return;
+
+       printf("SPL: Validating U-Boot image\n");
+
+#ifdef CONFIG_ADDR_MAP
+       init_addr_map();
+#endif
+
+#ifdef CONFIG_FSL_CORENET
+       if (pamu_init() < 0)
+               fsl_secboot_handle_error(ERROR_ESBC_PAMU_INIT);
+#endif
+
+#ifdef CONFIG_FSL_CAAM
+       if (sec_init() < 0)
+               fsl_secboot_handle_error(ERROR_ESBC_SEC_INIT);
+#endif
+
+/*
+ * dm_init_and_scan() is called as part of common SPL framework, so no
+ * need to call it again but in case of powerpc platforms which currently
+ * do not use common SPL framework, so need to call this function here.
+ */
+#if defined(CONFIG_SPL_DM) && (!defined(CONFIG_SPL_FRAMEWORK))
+       dm_init_and_scan(false);
+#endif
+       res = fsl_secboot_validate(hdr_addr, CONFIG_SPL_UBOOT_KEY_HASH,
+                                  &img_addr);
+
+       if (res == 0)
+               printf("SPL: Validation of U-boot successful\n");
+}
+#endif /* ifdef CONFIG_SPL_BUILD */
index 510fa4e37601cb72ec552def4fff963c23891115..4a8cc3295a4a4eb116a2fbddc5c9ba5543aea115 100644 (file)
@@ -599,9 +599,26 @@ int sec_init_idx(uint8_t sec_idx)
        sec_out32(&sec->mcfgr, mcr);
 
 #ifdef CONFIG_FSL_CORENET
+#ifdef CONFIG_SPL_BUILD
+       /*
+        * For SPL Build, Set the Liodns in SEC JR0 for
+        * creating PAMU entries corresponding to these.
+        * For normal build, these are set in set_liodns().
+        */
+       liodn_ns = CONFIG_SPL_JR0_LIODN_NS & JRNSLIODN_MASK;
+       liodn_s = CONFIG_SPL_JR0_LIODN_S & JRSLIODN_MASK;
+
+       liodnr = sec_in32(&sec->jrliodnr[0].ls) &
+                ~(JRNSLIODN_MASK | JRSLIODN_MASK);
+       liodnr = liodnr |
+                (liodn_ns << JRNSLIODN_SHIFT) |
+                (liodn_s << JRSLIODN_SHIFT);
+       sec_out32(&sec->jrliodnr[0].ls, liodnr);
+#else
        liodnr = sec_in32(&sec->jrliodnr[0].ls);
        liodn_ns = (liodnr & JRNSLIODN_MASK) >> JRNSLIODN_SHIFT;
        liodn_s = (liodnr & JRSLIODN_MASK) >> JRSLIODN_SHIFT;
+#endif
 #endif
 
        ret = jr_init(sec_idx);
index cbeb74a5bb8e777a041925185c226977f97835e4..4e49a4e15465a762b1d08bd5f8ebe579954b9973 100644 (file)
@@ -11,6 +11,9 @@
 #include <asm/io.h>
 #include <fsl_ifc.h>
 #include <linux/mtd/nand.h>
+#ifdef CONFIG_CHAIN_OF_TRUST
+#include <fsl_validate.h>
+#endif
 
 static inline int is_blank(uchar *addr, int page_size)
 {
@@ -268,6 +271,27 @@ void nand_boot(void)
         */
        flush_cache(CONFIG_SYS_NAND_U_BOOT_DST, CONFIG_SYS_NAND_U_BOOT_SIZE);
 #endif
+
+#ifdef CONFIG_CHAIN_OF_TRUST
+       /*
+        * U-Boot header is appended at end of U-boot image, so
+        * calculate U-boot header address using U-boot header size.
+        */
+#define CONFIG_U_BOOT_HDR_ADDR \
+               ((CONFIG_SYS_NAND_U_BOOT_START + \
+                 CONFIG_SYS_NAND_U_BOOT_SIZE) - \
+                CONFIG_U_BOOT_HDR_SIZE)
+       spl_validate_uboot(CONFIG_U_BOOT_HDR_ADDR,
+                          CONFIG_SYS_NAND_U_BOOT_START);
+       /*
+        * In case of failure in validation, spl_validate_uboot would
+        * not return back in case of Production environment with ITS=1.
+        * Thus U-Boot will not start.
+        * In Development environment (ITS=0 and SB_EN=1), the function
+        * may return back in case of non-fatal failures.
+        */
+#endif
+
        uboot = (void *)CONFIG_SYS_NAND_U_BOOT_START;
        uboot();
 }
index a71e1ce2b0e1c8dc486e83f216772ab6b2a822b2..c350938d1ffc92142f7dfeba5616b7dbf694e55b 100644 (file)
@@ -254,4 +254,11 @@ int fsl_secboot_blob_decap(cmd_tbl_t *cmdtp, int flag, int argc,
 
 int fsl_check_boot_mode_secure(void);
 int fsl_setenv_chain_of_trust(void);
+
+/*
+ * This function is used to validate the main U-boot binary from
+ * SPL just before passing control to it using QorIQ Trust
+ * Architecture header (appended to U-boot image).
+ */
+void spl_validate_uboot(uint32_t hdr_addr, uintptr_t img_addr);
 #endif