]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
arm: socfpga: soc64: Support Vendor Authorized Boot (VAB)
authorSiew Chin Lim <elly.siew.chin.lim@intel.com>
Mon, 1 Mar 2021 12:04:11 +0000 (20:04 +0800)
committerLey Foon Tan <ley.foon.tan@intel.com>
Mon, 8 Mar 2021 02:59:10 +0000 (10:59 +0800)
Vendor Authorized Boot is a security feature for authenticating
the images such as U-Boot, ARM trusted Firmware, Linux kernel,
device tree blob and etc loaded from FIT. After those images are
loaded from FIT, the VAB certificate and signature block appended
at the end of each image are sent to Secure Device Manager (SDM)
for authentication. U-Boot will validate the SHA384 of the image
against the SHA384 hash stored in the VAB certificate before
sending the image to SDM for authentication.

Signed-off-by: Siew Chin Lim <elly.siew.chin.lim@intel.com>
Reviewed-by: Ley Foon Tan <ley.foon.tan@intel.com>
arch/arm/mach-socfpga/Kconfig
arch/arm/mach-socfpga/Makefile
arch/arm/mach-socfpga/board.c
arch/arm/mach-socfpga/include/mach/mailbox_s10.h
arch/arm/mach-socfpga/include/mach/secure_vab.h [new file with mode: 0644]
arch/arm/mach-socfpga/secure_vab.c [new file with mode: 0644]
common/Kconfig.boot

index 9b1abdaabdfd339e070646fbf71f879ff71c5b01..0c35406232871d8b13874466a32a0ba227aee3fb 100644 (file)
@@ -6,6 +6,21 @@ config ERR_PTR_OFFSET
 config NR_DRAM_BANKS
        default 1
 
+config SOCFPGA_SECURE_VAB_AUTH
+       bool "Enable boot image authentication with Secure Device Manager"
+       depends on TARGET_SOCFPGA_AGILEX
+       select FIT_IMAGE_POST_PROCESS
+       select SHA384
+       select SHA512_ALGO
+       select SPL_FIT_IMAGE_POST_PROCESS
+       help
+        All images loaded from FIT will be authenticated by Secure Device
+        Manager.
+
+config SOCFPGA_SECURE_VAB_AUTH_ALLOW_NON_FIT_IMAGE
+       bool "Allow non-FIT VAB signed images"
+       depends on SOCFPGA_SECURE_VAB_AUTH
+
 config SPL_SIZE_LIMIT
        default 0x10000 if TARGET_SOCFPGA_GEN5
 
index 82b681d870fb216bc32f6a271c6fa2bb10a1800f..1f1e21766d1db399b9176bafa457a43318bb2957 100644 (file)
@@ -4,6 +4,7 @@
 # Wolfgang Denk, DENX Software Engineering, wd@denx.de.
 #
 # Copyright (C) 2012-2017 Altera Corporation <www.altera.com>
+# Copyright (C) 2017-2020 Intel Corporation <www.intel.com>
 
 obj-y  += board.o
 obj-y  += clock_manager.o
@@ -47,6 +48,7 @@ obj-y += mailbox_s10.o
 obj-y  += misc_s10.o
 obj-y  += mmu-arm64_s10.o
 obj-y  += reset_manager_s10.o
+obj-$(CONFIG_SOCFPGA_SECURE_VAB_AUTH)  += secure_vab.o
 obj-y  += system_manager_s10.o
 obj-y  += timer_s10.o
 obj-y  += wrap_pinmux_config_s10.o
index 2a6af9d1f8aeffe4662beafdb040061ec93547fd..81aa07c9025774e90e13eb07c54695682ba159e6 100644 (file)
@@ -6,14 +6,17 @@
  */
 
 #include <common.h>
-#include <errno.h>
-#include <fdtdec.h>
-#include <init.h>
-#include <asm/arch/reset_manager.h>
 #include <asm/arch/clock_manager.h>
 #include <asm/arch/misc.h>
+#include <asm/arch/reset_manager.h>
+#include <asm/arch/secure_vab.h>
 #include <asm/global_data.h>
 #include <asm/io.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <hang.h>
+#include <image.h>
+#include <init.h>
 #include <log.h>
 #include <usb.h>
 #include <usb/dwc2_udc.h>
@@ -98,3 +101,37 @@ __weak int board_fit_config_name_match(const char *name)
        return 0;
 }
 #endif
+
+#if IS_ENABLED(CONFIG_FIT_IMAGE_POST_PROCESS)
+void board_fit_image_post_process(void **p_image, size_t *p_size)
+{
+       if (IS_ENABLED(CONFIG_SOCFPGA_SECURE_VAB_AUTH)) {
+               if (socfpga_vendor_authentication(p_image, p_size))
+                       hang();
+       }
+}
+#endif
+
+#if !IS_ENABLED(CONFIG_SPL_BUILD) && IS_ENABLED(CONFIG_FIT)
+void board_prep_linux(bootm_headers_t *images)
+{
+       if (!IS_ENABLED(CONFIG_SECURE_VAB_AUTH_ALLOW_NON_FIT_IMAGE)) {
+               /*
+                * Ensure the OS is always booted from FIT and with
+                * VAB signed certificate
+                */
+               if (!images->fit_uname_cfg) {
+                       printf("Please use FIT with VAB signed images!\n");
+                       hang();
+               }
+
+               env_set_hex("fdt_addr", (ulong)images->ft_addr);
+               debug("images->ft_addr = 0x%08lx\n", (ulong)images->ft_addr);
+       }
+
+       if (IS_ENABLED(CONFIG_CADENCE_QSPI)) {
+               if (env_get("linux_qspi_enable"))
+                       run_command(env_get("linux_qspi_enable"), 0);
+       }
+}
+#endif
index 4d783119ea783085ce798ffcef5162d3e44daae0..fbaf11597ed66bbdb7dbd296a2c759a58894014f 100644 (file)
@@ -118,6 +118,7 @@ enum ALT_SDM_MBOX_RESP_CODE {
 #define MBOX_RECONFIG_MSEL     7
 #define MBOX_RECONFIG_DATA     8
 #define MBOX_RECONFIG_STATUS   9
+#define MBOX_VAB_SRC_CERT              11
 #define MBOX_QSPI_OPEN         50
 #define MBOX_QSPI_CLOSE                51
 #define MBOX_QSPI_DIRECT       59
diff --git a/arch/arm/mach-socfpga/include/mach/secure_vab.h b/arch/arm/mach-socfpga/include/mach/secure_vab.h
new file mode 100644 (file)
index 0000000..4258858
--- /dev/null
@@ -0,0 +1,63 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright (C) 2020 Intel Corporation <www.intel.com>
+ *
+ */
+
+#ifndef        _SECURE_VAB_H_
+#define        _SECURE_VAB_H_
+
+#include <linux/sizes.h>
+#include <linux/stddef.h>
+#include <u-boot/sha512.h>
+
+#define VAB_DATA_SZ                    64
+
+#define SDM_CERT_MAGIC_NUM             0x25D04E7F
+#define FCS_HPS_VAB_MAGIC_NUM          0xD0564142
+
+#define MAX_CERT_SIZE                  (SZ_4K)
+
+/*
+ * struct fcs_hps_vab_certificate_data
+ * @vab_cert_magic_num: VAB Certificate Magic Word (0xD0564142)
+ * @flags: TBD
+ * @fcs_data: Data words being certificate signed.
+ * @cert_sign_keychain: Certificate Signing Keychain
+ */
+struct fcs_hps_vab_certificate_data {
+       u32 vab_cert_magic_num;         /* offset 0x10 */
+       u32 flags;
+       u8 rsvd0_1[8];
+       u8 fcs_sha384[SHA384_SUM_LEN];  /* offset 0x20 */
+};
+
+/*
+ * struct fcs_hps_vab_certificate_header
+ * @cert_magic_num: Certificate Magic Word (0x25D04E7F)
+ * @cert_data_sz: size of this certificate header (0x80)
+ *     Includes magic number all the way to the certificate
+ *      signing keychain (excludes cert. signing keychain)
+ * @cert_ver: Certificate Version
+ * @cert_type: Certificate Type
+ * @data: VAB HPS Image Certificate data
+ */
+struct fcs_hps_vab_certificate_header {
+       u32 cert_magic_num;             /* offset 0 */
+       u32 cert_data_sz;
+       u32 cert_ver;
+       u32 cert_type;
+       struct fcs_hps_vab_certificate_data d;  /* offset 0x10 */
+       /* keychain starts at offset 0x50 */
+};
+
+#define VAB_CERT_HEADER_SIZE   sizeof(struct fcs_hps_vab_certificate_header)
+#define VAB_CERT_MAGIC_OFFSET  offsetof \
+                               (struct fcs_hps_vab_certificate_header, d)
+#define VAB_CERT_FIT_SHA384_OFFSET     offsetof \
+                                       (struct fcs_hps_vab_certificate_data, \
+                                        fcs_sha384[0])
+
+int socfpga_vendor_authentication(void **p_image, size_t *p_size);
+
+#endif /* _SECURE_VAB_H_ */
diff --git a/arch/arm/mach-socfpga/secure_vab.c b/arch/arm/mach-socfpga/secure_vab.c
new file mode 100644 (file)
index 0000000..e2db588
--- /dev/null
@@ -0,0 +1,186 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020 Intel Corporation <www.intel.com>
+ *
+ */
+
+#include <asm/arch/mailbox_s10.h>
+#include <asm/arch/secure_vab.h>
+#include <asm/arch/smc_api.h>
+#include <asm/unaligned.h>
+#include <common.h>
+#include <exports.h>
+#include <linux/errno.h>
+#include <linux/intel-smc.h>
+#include <log.h>
+
+#define CHUNKSZ_PER_WD_RESET           (256 * SZ_1K)
+
+/*
+ * Read the length of the VAB certificate from the end of image
+ * and calculate the actual image size (excluding the VAB certificate).
+ */
+static size_t get_img_size(u8 *img_buf, size_t img_buf_sz)
+{
+       u8 *img_buf_end = img_buf + img_buf_sz;
+       u32 cert_sz = get_unaligned_le32(img_buf_end - sizeof(u32));
+       u8 *p = img_buf_end - cert_sz - sizeof(u32);
+
+       /* Ensure p is pointing within the img_buf */
+       if (p < img_buf || p > (img_buf_end - VAB_CERT_HEADER_SIZE))
+               return 0;
+
+       if (get_unaligned_le32(p) == SDM_CERT_MAGIC_NUM)
+               return (size_t)(p - img_buf);
+
+       return 0;
+}
+
+/*
+ * Vendor Authorized Boot (VAB) is a security feature for authenticating
+ * the images such as U-Boot, ARM trusted Firmware, Linux kernel,
+ * device tree blob and etc loaded from FIT. User can also trigger
+ * the VAB authentication from U-Boot command.
+ *
+ * This function extracts the VAB certificate and signature block
+ * appended at the end of the image, then send to Secure Device Manager
+ * (SDM) for authentication. This function will validate the SHA384
+ * of the image against the SHA384 hash stored in the VAB certificate
+ * before sending the VAB certificate to SDM for authentication.
+ *
+ * RETURN
+ * 0 if authentication success or
+ *   if authentication is not required and bypassed on a non-secure device
+ * negative error code if authentication fail
+ */
+int socfpga_vendor_authentication(void **p_image, size_t *p_size)
+{
+       int retry_count = 20;
+       u8 hash384[SHA384_SUM_LEN];
+       u64 img_addr, mbox_data_addr;
+       size_t img_sz, mbox_data_sz;
+       u8 *cert_hash_ptr, *mbox_relocate_data_addr;
+       u32 resp = 0, resp_len = 1;
+       int ret;
+
+       img_addr = (uintptr_t)*p_image;
+
+       debug("Authenticating image at address 0x%016llx (%ld bytes)\n",
+             img_addr, *p_size);
+
+       img_sz = get_img_size((u8 *)img_addr, *p_size);
+       debug("img_sz = %ld\n", img_sz);
+
+       if (!img_sz) {
+               puts("VAB certificate not found in image!\n");
+               return -ENOKEY;
+       }
+
+       if (!IS_ALIGNED(img_sz, sizeof(u32))) {
+               printf("Image size (%ld bytes) not aliged to 4 bytes!\n",
+                      img_sz);
+               return -EBFONT;
+       }
+
+       /* Generate HASH384 from the image */
+       sha384_csum_wd((u8 *)img_addr, img_sz, hash384, CHUNKSZ_PER_WD_RESET);
+
+       cert_hash_ptr = (u8 *)(img_addr + img_sz + VAB_CERT_MAGIC_OFFSET +
+                              VAB_CERT_FIT_SHA384_OFFSET);
+
+       /*
+        * Compare the SHA384 found in certificate against the SHA384
+        * calculated from image
+        */
+       if (memcmp(hash384, cert_hash_ptr, SHA384_SUM_LEN)) {
+               puts("SHA384 not match!\n");
+               return -EKEYREJECTED;
+       }
+
+       mbox_data_addr = img_addr + img_sz - sizeof(u32);
+       /* Size in word (32bits) */
+       mbox_data_sz = (ALIGN(*p_size - img_sz, sizeof(u32))) >> 2;
+
+       debug("mbox_data_addr = 0x%016llx\n", mbox_data_addr);
+       debug("mbox_data_sz = %ld words\n", mbox_data_sz);
+
+       /*
+        * Relocate certificate to first memory block before trigger SMC call
+        * to send mailbox command because ATF only able to access first
+        * memory block.
+        */
+       mbox_relocate_data_addr = (u8 *)malloc(mbox_data_sz * sizeof(u32));
+       if (!mbox_relocate_data_addr) {
+               puts("Out of memory for VAB certificate relocation!\n");
+               return -ENOMEM;
+       }
+
+       memcpy(mbox_relocate_data_addr, (u8 *)mbox_data_addr, mbox_data_sz * sizeof(u32));
+       *(u32 *)mbox_relocate_data_addr = 0;
+
+       debug("mbox_relocate_data_addr = 0x%p\n", mbox_relocate_data_addr);
+
+       do {
+               if (!IS_ENABLED(CONFIG_SPL_BUILD) && IS_ENABLED(CONFIG_SPL_ATF)) {
+                       /* Invoke SMC call to ATF to send the VAB certificate to SDM */
+                       ret  = smc_send_mailbox(MBOX_VAB_SRC_CERT, mbox_data_sz,
+                                               (u32 *)mbox_relocate_data_addr, 0, &resp_len,
+                                               &resp);
+               } else {
+                       /* Send the VAB certficate to SDM for authentication */
+                       ret = mbox_send_cmd(MBOX_ID_UBOOT, MBOX_VAB_SRC_CERT,
+                                           MBOX_CMD_DIRECT, mbox_data_sz,
+                                           (u32 *)mbox_relocate_data_addr, 0, &resp_len,
+                                           &resp);
+               }
+               /* If SDM is not available, just delay 50ms and retry again */
+               if (ret == MBOX_RESP_DEVICE_BUSY)
+                       mdelay(50);
+               else
+                       break;
+       } while (--retry_count);
+
+       /* Free the relocate certificate memory space */
+       free(mbox_relocate_data_addr);
+
+       /* Exclude the size of the VAB certificate from image size */
+       *p_size = img_sz;
+
+       debug("ret = 0x%08x, resp = 0x%08x, resp_len = %d\n", ret, resp,
+             resp_len);
+
+       if (ret) {
+               /*
+                * Unsupported mailbox command or device not in the
+                * owned/secure state
+                */
+               if (ret == MBOX_RESP_NOT_ALLOWED_UNDER_SECURITY_SETTINGS) {
+                       /* SDM bypass authentication */
+                       printf("%s 0x%016llx (%ld bytes)\n",
+                              "Image Authentication bypassed at address",
+                              img_addr, img_sz);
+                       return 0;
+               }
+               puts("VAB certificate authentication failed in SDM");
+               if (ret == MBOX_RESP_DEVICE_BUSY) {
+                       puts(" (SDM busy timeout)\n");
+                       return -ETIMEDOUT;
+               } else if (ret == MBOX_RESP_UNKNOWN) {
+                       puts(" (Not supported)\n");
+                       return -ESRCH;
+               }
+               puts("\n");
+               return -EKEYREJECTED;
+       } else {
+               /* If Certificate Process Status has error */
+               if (resp) {
+                       puts("VAB certificate process failed\n");
+                       return -ENOEXEC;
+               }
+       }
+
+       printf("%s 0x%016llx (%ld bytes)\n",
+              "Image Authentication passed at address", img_addr, img_sz);
+
+       return 0;
+}
index e650c605d1d216cbf8d93292782c82bdd65a5382..9c335f4f8cea65a529bfe02b346e4cd177018b5b 100644 (file)
@@ -138,7 +138,7 @@ config FIT_BEST_MATCH
 
 config FIT_IMAGE_POST_PROCESS
        bool "Enable post-processing of FIT artifacts after loading by U-Boot"
-       depends on TI_SECURE_DEVICE
+       depends on TI_SECURE_DEVICE || SOCFPGA_SECURE_VAB_AUTH
        help
          Allows doing any sort of manipulation to blobs after they got extracted
          from FIT images like stripping off headers or modifying the size of the