From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id E6150C00140 for ; Fri, 5 Aug 2022 15:48:44 +0000 (UTC) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 2ADCD8486E; Fri, 5 Aug 2022 17:48:37 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=kernel.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=kernel.org header.i=@kernel.org header.b="DJbjiy4L"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id B6A2F84884; Fri, 5 Aug 2022 17:48:35 +0200 (CEST) Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 92A9984864 for ; Fri, 5 Aug 2022 17:48:32 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=kernel.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=pali@kernel.org Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id F2DB5615F4; Fri, 5 Aug 2022 15:48:30 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 13727C433D7; Fri, 5 Aug 2022 15:48:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1659714510; bh=ywpBjkJ8EERBF+WX+P87+DHEOxVDEtw9xFJH36FsGpU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=DJbjiy4Lw2dsznWgsENNyGz2zs6+xn1stIJKPrM8UyNg70Lyarkcwn+hOU73BGgMG IWbdXK+HCTbqQs9mia98kE1JURKCY6APQjkhlV6iVBnnlXYMeO8FOIOxT/2GtouLyF 5imfDF1saPWS0ZVZF8Y4x0BYrxuvXSmKtj69my/eMKFK1dWf1yCfd4rrXBTU93vmm7 12baY7zVN17kzKw32wMaMYLnOFvI8Pm+KcwTqRMun7h8f1cd09jzJEB45i4Yj+qnUS byVMiYJG0dhMi6zyf4ful3e6RMbeb0/YtxEpIGaVZghZTYhZxjXItR/PQWVp9TAGxk A0u5OCdDM8UKA== Received: by pali.im (Postfix) id BBB03941; Fri, 5 Aug 2022 17:48:27 +0200 (CEST) From: =?UTF-8?q?Pali=20Roh=C3=A1r?= To: Stefan Roese Cc: u-boot@lists.denx.de Subject: [PATCH 2/2] cmd: mvebu/bubt: Check for OTP secure bits and secure boot Date: Fri, 5 Aug 2022 17:48:19 +0200 Message-Id: <20220805154819.4924-2-pali@kernel.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20220805154819.4924-1-pali@kernel.org> References: <20220805154819.4924-1-pali@kernel.org> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.6 at phobos.denx.de X-Virus-Status: Clean For obvious reasons BootROMS rejects unsigned images when secure boot is enabled in OTP secure bits. So check for OPT secure bits and do not allow flashing unsigned images when secure boot is enabled. Additionally Armada 3700 BootROM rejects signed trusted image when secure boot is not enabled in OTP. So add also check for this case. OTP secure bits may have burned also boot device source. Check it also and reject flashing images to target storage which does not match OTP. Signed-off-by: Pali Rohár --- cmd/mvebu/bubt.c | 123 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 114 insertions(+), 9 deletions(-) diff --git a/cmd/mvebu/bubt.c b/cmd/mvebu/bubt.c index 615234e41897..ac98154fb759 100644 --- a/cmd/mvebu/bubt.c +++ b/cmd/mvebu/bubt.c @@ -14,6 +14,8 @@ #include #include #include +#include +#include #include #include @@ -122,6 +124,17 @@ struct a38x_main_hdr_v1 { u8 checksum; /* 0x1F */ }; +/* + * Header for the optional headers, version 1 (Armada 370/XP/375/38x/39x) + */ +struct a38x_opt_hdr_v1 { + u8 headertype; + u8 headersz_msb; + u16 headersz_lsb; + u8 data[0]; +}; +#define A38X_OPT_HDR_V1_SECURE_TYPE 0x1 + struct a38x_boot_mode { unsigned int id; const char *name; @@ -707,6 +720,7 @@ static int check_image_header(void) { u8 checksum; u32 checksum32, exp_checksum32; + u32 offset, size; const struct a38x_main_hdr_v1 *hdr = (struct a38x_main_hdr_v1 *)get_load_addr(); const size_t image_size = a38x_header_size(hdr); @@ -743,7 +757,7 @@ static int check_image_header(void) } checksum32 = image_checksum32((u8 *)hdr + offset, size - 4); - exp_checksum32 = *(u32 *)((u8 *)ptr + offset + size - 4); + exp_checksum32 = *(u32 *)((u8 *)hdr + offset + size - 4); if (checksum32 != exp_checksum32) { printf("Error: Bad A38x image data checksum. 0x%08x != 0x%08x\n", checksum32, exp_checksum32); @@ -753,6 +767,36 @@ static int check_image_header(void) printf("Image checksum...OK!\n"); return 0; } + +static int a38x_image_is_secure(const struct a38x_main_hdr_v1 *hdr) +{ + u32 image_size = a38x_header_size(hdr); + struct a38x_opt_hdr_v1 *ohdr; + u32 ohdr_size; + + if (hdr->version != 1) + return 0; + + if (!hdr->ext) + return 0; + + ohdr = (struct a38x_opt_hdr_v1 *)(hdr + 1); + do { + if (ohdr->headertype == A38X_OPT_HDR_V1_SECURE_TYPE) + return 1; + + ohdr_size = (ohdr->headersz_msb << 16) | le16_to_cpu(ohdr->headersz_lsb); + + if (!*((u8 *)ohdr + ohdr_size - 4)) + break; + + ohdr = (struct a38x_opt_hdr_v1 *)((u8 *)ohdr + ohdr_size); + if ((u8 *)ohdr >= (u8 *)hdr + image_size) + break; + } while (1); + + return 0; +} #else /* Not ARMADA? */ static int check_image_header(void) { @@ -761,20 +805,56 @@ static int check_image_header(void) } #endif +static u64 fuse_read_u64(u32 bank) +{ + u32 val[2]; + int ret; + + ret = fuse_read(bank, 0, &val[0]); + if (ret < 0) + return -1; + + ret = fuse_read(bank, 1, &val[1]); + if (ret < 0) + return -1; + + return ((u64)val[1] << 32) | val[0]; +} + +#if defined(CONFIG_ARMADA_3700) +static inline u8 maj3(u8 val) +{ + /* return majority vote of 3 bits */ + return ((val & 0x7) == 3 || (val & 0x7) > 4) ? 1 : 0; +} +#endif + static int bubt_check_boot_mode(const struct bubt_dev *dst) { #if defined(CONFIG_ARMADA_3700) || defined(CONFIG_ARMADA_32BIT) - int mode; + int mode, secure_mode; #if defined(CONFIG_ARMADA_3700) const struct tim_boot_flash_sign *boot_modes = tim_boot_flash_signs; const struct common_tim_data *hdr = (struct common_tim_data *)get_load_addr(); u32 id = hdr->boot_flash_sign; + int is_secure = hdr->trusted != 0; + u64 otp_secure_bits = fuse_read_u64(1); + int otp_secure_boot = ((maj3(otp_secure_bits >> 0) << 0) | + (maj3(otp_secure_bits >> 4) << 1)) == 2; + unsigned int otp_boot_device = (maj3(otp_secure_bits >> 48) << 0) | + (maj3(otp_secure_bits >> 52) << 1) | + (maj3(otp_secure_bits >> 56) << 2) | + (maj3(otp_secure_bits >> 60) << 3); #elif defined(CONFIG_ARMADA_32BIT) const struct a38x_boot_mode *boot_modes = a38x_boot_modes; const struct a38x_main_hdr_v1 *hdr = (struct a38x_main_hdr_v1 *)get_load_addr(); u32 id = hdr->blockid; + int is_secure = a38x_image_is_secure(hdr); + u64 otp_secure_bits = fuse_read_u64(EFUSE_LINE_SECURE_BOOT); + int otp_secure_boot = otp_secure_bits & 0x1; + unsigned int otp_boot_device = (otp_secure_bits >> 8) & 0x7; #endif for (mode = 0; boot_modes[mode].name; mode++) { @@ -787,15 +867,40 @@ static int bubt_check_boot_mode(const struct bubt_dev *dst) return -ENOEXEC; } - if (strcmp(boot_modes[mode].name, dst->name) == 0) - return 0; + if (strcmp(boot_modes[mode].name, dst->name) != 0) { + printf("Error: image meant to be booted from \"%s\", not \"%s\"!\n", + boot_modes[mode].name, dst->name); + return -ENOEXEC; + } - printf("Error: image meant to be booted from \"%s\", not \"%s\"!\n", - boot_modes[mode].name, dst->name); - return -ENOEXEC; -#else - return 0; + if (otp_secure_bits == (u64)-1) { + printf("Error: cannot read OTP secure bits\n"); + return -ENOEXEC; + } else { + if (otp_secure_boot && !is_secure) { + printf("Error: secure boot is enabled in OTP but image does not have secure boot header!\n"); + return -ENOEXEC; + } else if (!otp_secure_boot && is_secure) { +#if defined(CONFIG_ARMADA_3700) + /* + * Armada 3700 BootROM rejects trusted image when secure boot is not enabled. + * Armada 385 BootROM accepts image with secure boot header also when secure boot is not enabled. + */ + printf("Error: secure boot is disabled in OTP but image has secure boot header!\n"); + return -ENOEXEC; +#endif + } else if (otp_boot_device && otp_boot_device != id) { + for (secure_mode = 0; boot_modes[secure_mode].name; secure_mode++) { + if (boot_modes[secure_mode].id == otp_boot_device) + break; + } + printf("Error: boot source is set to \"%s\" in OTP but image is for \"%s\"!\n", + boot_modes[secure_mode].name ?: "unknown", dst->name); + return -ENOEXEC; + } + } #endif + return 0; } static int bubt_verify(const struct bubt_dev *dst) -- 2.20.1