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 D1B52C433EF for ; Mon, 28 Mar 2022 20:59:12 +0000 (UTC) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 745DF83FDC; Mon, 28 Mar 2022 22:58:07 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=none (p=none dis=none) header.from=softathome.com 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=softathome1.onmicrosoft.com header.i=@softathome1.onmicrosoft.com header.b="dai+wK6S"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 5ECEC83F97; Mon, 28 Mar 2022 22:57:29 +0200 (CEST) Received: from FRA01-MR2-obe.outbound.protection.outlook.com (mail-mr2fra01on0628.outbound.protection.outlook.com [IPv6:2a01:111:f400:7e19::628]) (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 0EB3383F8D for ; Mon, 28 Mar 2022 22:57:16 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=none (p=none dis=none) header.from=softathome.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=philippe.reynes@softathome.com ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=nwNTrbjp6fO5OM5I56nPg7U4BFkGXn2SMCVaPZKMf825dGckVPoH+sRvzqe9p1rFZjQmOQiKIMM9BJ/uTW9a8wUb4OIoZeVHz91Xqln5PWfIpxX8gbknJ8nvINBQEanMsR2zJ26eQVfe2VrJjgouxKiEvxPMBnDPz943VDn/QpJwUQGILHvJQGi4geb6r6xgJEO5zNm1GObL9wE8oEIlbnaazkfRrqX35FDPZ58zu+atYeWLUUXvv5pOGm00OWo9KuAZ4yD3x9mL2MQ+I1QWnMO8i2pXJIrj0unsYFL/fauCKPrMVE/PwrwYPGPI7a59639ui8g8ZmjFgBJv1toNtw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=pykVpkH+AvnN9Epq4prEfCGgOuGORSCj19UOS9kS/1c=; b=dv7y9D7qrk5ee10QMWg5o4jQ5FUwwNxpVCsNIWRecllVaQJKQ+SFTrZBbOULiEO6bM4CbXw4F5g4+zn0tSp/1B/mLUQuwQIW31GN0Jxz32lH7gDVgwC5B7+nIiFmPtgJNMC0bY1FD+iI87gA+peqSuiCbtjW3dSKgbIDcgdB2i7tzYyLj3sXp/G04VjXMqj4xpylF7V3bqHzSmPQQrXSg7fA6oIuKaBNe+gmBFvdi5nrgZYC17ukWYd5eoF4jpDjKvsQ/u9pq9MDOXxSU3lR2gpWI26n5/xNSlShx1d/9hFri7uG54Bm3Jdre2SxotmGbIkiFJXjUCya//f3WbwPdA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 149.6.166.170) smtp.rcpttodomain=chromium.org smtp.mailfrom=softathome.com; dmarc=bestguesspass action=none header.from=softathome.com; dkim=none (message not signed); arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=softathome1.onmicrosoft.com; s=selector1-softathome1-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=pykVpkH+AvnN9Epq4prEfCGgOuGORSCj19UOS9kS/1c=; b=dai+wK6Sw3/ukJS8qR8qO8y4U0ciVMGXGcGjybArirawO3tDAsiltS0yeU11KMtVmPIr1ZGTP9624qqJyQvOB7DjUu6MnqovcMM0QNu+MKIr5e0PQGDrCQ3j5yLnYFYpWb7a/SrwgaghKMDZ/iWft41F5jROpac9tRYBJwZmfv/eUZWGu5In5Hwg+ouuoiCn3P34ZkL33akdRRPX4+rZQ9zmGmTyWWwaSLXASdh54LN6qlkuy5uQkCrHw3cdnxBRU2mzmcILdLJ2SeaQ/r7e1c7RvrA6yk7mSZRGNEz6ychjCqicUJ+6X9h/Wz1tG8lQRJYZbgOqLha3rrGoOE1tDQ== Received: from MR1P264CA0122.FRAP264.PROD.OUTLOOK.COM (2603:10a6:501:50::32) by PR0P264MB2341.FRAP264.PROD.OUTLOOK.COM (2603:10a6:102:1e0::16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5102.17; Mon, 28 Mar 2022 20:57:14 +0000 Received: from MR2FRA01FT011.eop-fra01.prod.protection.outlook.com (2603:10a6:501:50:cafe::81) by MR1P264CA0122.outlook.office365.com (2603:10a6:501:50::32) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5102.17 via Frontend Transport; Mon, 28 Mar 2022 20:57:14 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 149.6.166.170) smtp.mailfrom=softathome.com; dkim=none (message not signed) header.d=none;dmarc=bestguesspass action=none header.from=softathome.com; Received-SPF: Pass (protection.outlook.com: domain of softathome.com designates 149.6.166.170 as permitted sender) receiver=protection.outlook.com; client-ip=149.6.166.170; helo=proxy.softathome.com; Received: from proxy.softathome.com (149.6.166.170) by MR2FRA01FT011.mail.protection.outlook.com (10.152.50.189) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5102.18 via Frontend Transport; Mon, 28 Mar 2022 20:57:13 +0000 Received: from localhost.localdomain (unknown [192.168.72.32]) by proxy.softathome.com (Postfix) with ESMTPSA id 3C8E420117; Mon, 28 Mar 2022 22:57:12 +0200 (CEST) From: Philippe Reynes To: sjg@chromium.org, rasmus.villemoes@prevas.dk Cc: u-boot@lists.denx.de, Philippe Reynes Subject: [PATCH v8 07/15] boot: image: add a stage pre-load Date: Mon, 28 Mar 2022 22:56:59 +0200 Message-Id: <20220328205707.348270-8-philippe.reynes@softathome.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220328205707.348270-1-philippe.reynes@softathome.com> References: <20220328205707.348270-1-philippe.reynes@softathome.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email Content-Type: text/plain X-MS-Office365-Filtering-Correlation-Id: 2902f319-cb5d-4cce-d1f9-08da10fd88f4 X-MS-TrafficTypeDiagnostic: PR0P264MB2341:EE_ X-Microsoft-Antispam-PRVS: X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: 4BToaY0ZjUJa/RzVY5SsTb0mDoIRMMzsLNwltyQh82ZRI1ROeu3LMQgVAqUDgQMJDrES69fIqfEViWxcsXtlZg7aiR3Wi8k0qe5AqrKY8XFljMGxsLBoTqp2Fm0NmpeR1ZivtwETmXqSbRoHbJUwjOG/aOzd3sTwNwqvRxdxdEh8ZCBbF1jbjqY/Qb+uRiv/4WPvzuhzimsq9wSjfUNDqmJScGx7yXzKUnezbsTYA3tuc26kOX41jOG847e+VO7JiTBIDzcmvyJCmY2fMUjAqWDdnBXW7ttIOLHxWyw43SkfkLApUB9IyiBFTVC0Kk0ObcGBs/aCiF2B5I0It1+AKNhsTq9MZ+6xHwVuk/aAfG+v820fyaIYRx4I4g3/YVtxeSEXf2BVGXcdbDrljRRZMUtpKenSzwpXvVZfgdGwzN6iu+ivPnRvJzhVxUjqnz7X/4COeEE0N8mumLqm+t5ctGwtUuS2be/dmi4v7MgNVxk+rfclc/jgXIqckmrdL98RglPTxuucQ6ndzsC2WnOzlAJOoYvQrVYFRxM8nbMAsNTcCRCM4yhoFbSb+nhAFnThYMScmx8sfSCRWVQc81bFS846DC0034NmcnXHjJJSZszXt91GAo+nG1QZlj8vh3xcyp8TalMYenIxXY9jNH242LS5xvoAjVRof+8F4QWRC7yEN23mPqML0KgICQf2Zh6sJlXDKc77bvFPhgoRfcusiQ== X-Forefront-Antispam-Report: CIP:149.6.166.170; CTRY:FR; LANG:en; SCL:1; SRV:; IPV:CAL; SFV:NSPM; H:proxy.softathome.com; PTR:InfoDomainNonexistent; CAT:NONE; SFS:(13230001)(4636009)(36840700001)(40470700004)(46966006)(70586007)(6966003)(47076005)(36860700001)(82960400001)(44832011)(70206006)(1076003)(8936002)(316002)(26005)(186003)(6266002)(2616005)(30864003)(4326008)(6666004)(86362001)(36756003)(107886003)(82310400004)(8676002)(40460700003)(81166007)(356005)(508600001)(336012)(426003)(83380400001)(2906002)(5660300002)(36900700001); DIR:OUT; SFP:1101; X-OriginatorOrg: softathome.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 28 Mar 2022 20:57:13.6237 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 2902f319-cb5d-4cce-d1f9-08da10fd88f4 X-MS-Exchange-CrossTenant-Id: aa10e044-e405-4c10-8353-36b4d0cce511 X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=aa10e044-e405-4c10-8353-36b4d0cce511; Ip=[149.6.166.170]; Helo=[proxy.softathome.com] X-MS-Exchange-CrossTenant-AuthSource: MR2FRA01FT011.eop-fra01.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: PR0P264MB2341 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.5 at phobos.denx.de X-Virus-Status: Clean Add a stage pre-load that could check or modify an image. For the moment, only a header with a signature is supported. This header has the following format: - magic : 4 bytes - version : 4 bytes - header size : 4 bytes - image size : 4 bytes - offset image signature : 4 bytes - flags : 4 bytes - reserved0 : 4 bytes - reserved1 : 4 bytes - sha256 of the image signature : 32 bytes - signature of the first 64 bytes : n bytes - image signature : n bytes - padding : up to header size The stage uses a node /image/pre-load/sig to get some informations: - algo-name (mandatory) : name of the algo used to sign - padding-name : name of padding used to sign - signature-size : size of the signature (in the header) - mandatory : set to yes if this sig is mandatory - public-key (madatory) : value of the public key Before running the image, the stage pre-load checks the signature provided in the header. This is an initial support, later we could add the support of: - ciphering - uncompressing - ... Signed-off-by: Philippe Reynes --- boot/Kconfig | 55 ++++++ boot/Makefile | 1 + boot/image-pre-load.c | 416 ++++++++++++++++++++++++++++++++++++++++++ include/image.h | 14 ++ 4 files changed, 486 insertions(+) create mode 100644 boot/image-pre-load.c diff --git a/boot/Kconfig b/boot/Kconfig index b83a4e8400..cb5f48dcf9 100644 --- a/boot/Kconfig +++ b/boot/Kconfig @@ -993,6 +993,61 @@ config AUTOBOOT_MENU_SHOW endmenu +menu "Image support" + +config IMAGE_PRE_LOAD + bool "Image pre-load support" + help + Enable an image pre-load stage in the SPL. + This pre-load stage allows to do some manipulation + or check (for example signature check) on an image + before launching it. + +config SPL_IMAGE_PRE_LOAD + bool "Image pre-load support within SPL" + depends on SPL && IMAGE_PRE_LOAD + help + Enable an image pre-load stage in the SPL. + This pre-load stage allows to do some manipulation + or check (for example signature check) on an image + before launching it. + +config IMAGE_PRE_LOAD_SIG + bool "Image pre-load signature support" + depends on IMAGE_PRE_LOAD + select FIT_SIGNATURE + select RSA + select RSA_VERIFY_WITH_PKEY + help + Enable signature check support in the pre-load stage. + For this feature a very simple header is added before + the image with few fields: + - a magic + - the image size + - the signature + All other information (header size, type of signature, + ...) are provided in the node /image/pre-load/sig of + u-boot. + +config SPL_IMAGE_PRE_LOAD_SIG + bool "Image pre-load signature support witin SPL" + depends on SPL_IMAGE_PRE_LOAD && IMAGE_PRE_LOAD_SIG + select SPL_FIT_SIGNATURE + select SPL_RSA + select SPL_RSA_VERIFY_WITH_PKEY + help + Enable signature check support in the pre-load stage in the SPL. + For this feature a very simple header is added before + the image with few fields: + - a magic + - the image size + - the signature + All other information (header size, type of signature, + ...) are provided in the node /image/pre-load/sig of + u-boot. + +endmenu + config USE_BOOTARGS bool "Enable boot arguments" help diff --git a/boot/Makefile b/boot/Makefile index 2938c3f145..59752c65ca 100644 --- a/boot/Makefile +++ b/boot/Makefile @@ -26,6 +26,7 @@ obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += image-fdt.o obj-$(CONFIG_$(SPL_TPL_)FIT_SIGNATURE) += fdt_region.o obj-$(CONFIG_$(SPL_TPL_)FIT) += image-fit.o obj-$(CONFIG_$(SPL_)MULTI_DTB_FIT) += boot_fit.o common_fit.o +obj-$(CONFIG_$(SPL_TPL_)IMAGE_PRE_LOAD) += image-pre-load.o obj-$(CONFIG_$(SPL_TPL_)IMAGE_SIGN_INFO) += image-sig.o obj-$(CONFIG_$(SPL_TPL_)FIT_SIGNATURE) += image-fit-sig.o obj-$(CONFIG_$(SPL_TPL_)FIT_CIPHER) += image-cipher.o diff --git a/boot/image-pre-load.c b/boot/image-pre-load.c new file mode 100644 index 0000000000..78d89069a9 --- /dev/null +++ b/boot/image-pre-load.c @@ -0,0 +1,416 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2021 Philippe Reynes + */ + +#include +#include +DECLARE_GLOBAL_DATA_PTR; +#include +#include + +#include + +#define IMAGE_PRE_LOAD_SIG_MAGIC 0x55425348 +#define IMAGE_PRE_LOAD_SIG_OFFSET_MAGIC 0 +#define IMAGE_PRE_LOAD_SIG_OFFSET_IMG_LEN 4 +#define IMAGE_PRE_LOAD_SIG_OFFSET_SIG 8 + +#define IMAGE_PRE_LOAD_PATH "/image/pre-load/sig" +#define IMAGE_PRE_LOAD_PROP_ALGO_NAME "algo-name" +#define IMAGE_PRE_LOAD_PROP_PADDING_NAME "padding-name" +#define IMAGE_PRE_LOAD_PROP_SIG_SIZE "signature-size" +#define IMAGE_PRE_LOAD_PROP_PUBLIC_KEY "public-key" +#define IMAGE_PRE_LOAD_PROP_MANDATORY "mandatory" + +#ifndef CONFIG_SYS_BOOTM_LEN +/* use 8MByte as default max gunzip size */ +#define CONFIG_SYS_BOOTM_LEN 0x800000 +#endif + +/* + * Information in the device-tree about the signature in the header + */ +struct image_sig_info { + char *algo_name; /* Name of the algo (eg: sha256,rsa2048) */ + char *padding_name; /* Name of the padding */ + u8 *key; /* Public signature key */ + int key_len; /* Length of the public key */ + u32 sig_size; /* size of the signature (in the header) */ + int mandatory; /* Set if the signature is mandatory */ + + struct image_sign_info sig_info; /* Signature info */ +}; + +/* + * Header of the signature header + */ +struct sig_header_s { + u32 magic; + u32 version; + u32 header_size; + u32 image_size; + u32 offset_img_sig; + u32 flags; + u32 reserved0; + u32 reserved1; + u8 sha256_img_sig[SHA256_SUM_LEN]; +}; + +#define SIG_HEADER_LEN (sizeof(struct sig_header_s)) + +/* + * Offset of the image + * + * This value is used to skip the header before really launching the image + */ +ulong image_load_offset; + +/* + * This function gathers information about the signature check + * that could be done before launching the image. + * + * return: + * < 0 => an error has occurred + * 0 => OK + * 1 => no setup + */ +static int image_pre_load_sig_setup(struct image_sig_info *info) +{ + const void *algo_name, *padding_name, *key, *mandatory; + const u32 *sig_size; + int key_len; + int node, ret = 0; + + if (!info) { + log_err("ERROR: info is NULL for image pre-load sig check\n"); + ret = -EINVAL; + goto out; + } + + memset(info, 0, sizeof(*info)); + + node = fdt_path_offset(gd_fdt_blob(), IMAGE_PRE_LOAD_PATH); + if (node < 0) { + log_info("INFO: no info for image pre-load sig check\n"); + ret = 1; + goto out; + } + + algo_name = fdt_getprop(gd_fdt_blob(), node, + IMAGE_PRE_LOAD_PROP_ALGO_NAME, NULL); + if (!algo_name) { + printf("ERROR: no algo_name for image pre-load sig check\n"); + ret = -EINVAL; + goto out; + } + + padding_name = fdt_getprop(gd_fdt_blob(), node, + IMAGE_PRE_LOAD_PROP_PADDING_NAME, NULL); + if (!padding_name) { + log_info("INFO: no padding_name provided, so using pkcs-1.5\n"); + padding_name = "pkcs-1.5"; + } + + sig_size = fdt_getprop(gd_fdt_blob(), node, + IMAGE_PRE_LOAD_PROP_SIG_SIZE, NULL); + if (!sig_size) { + log_err("ERROR: no signature-size for image pre-load sig check\n"); + ret = -EINVAL; + goto out; + } + + key = fdt_getprop(gd_fdt_blob(), node, + IMAGE_PRE_LOAD_PROP_PUBLIC_KEY, &key_len); + if (!key) { + log_err("ERROR: no key for image pre-load sig check\n"); + ret = -EINVAL; + goto out; + } + + info->algo_name = (char *)algo_name; + info->padding_name = (char *)padding_name; + info->key = (uint8_t *)key; + info->key_len = key_len; + info->sig_size = fdt32_to_cpu(*sig_size); + + mandatory = fdt_getprop(gd_fdt_blob(), node, + IMAGE_PRE_LOAD_PROP_MANDATORY, NULL); + if (mandatory && !strcmp((char *)mandatory, "yes")) + info->mandatory = 1; + + /* Compute signature information */ + info->sig_info.name = info->algo_name; + info->sig_info.padding = image_get_padding_algo(info->padding_name); + info->sig_info.checksum = image_get_checksum_algo(info->sig_info.name); + info->sig_info.crypto = image_get_crypto_algo(info->sig_info.name); + info->sig_info.key = info->key; + info->sig_info.keylen = info->key_len; + + out: + return ret; +} + +static int image_pre_load_sig_get_magic(ulong addr, u32 *magic) +{ + struct sig_header_s *sig_header; + int ret = 0; + + sig_header = (struct sig_header_s *)map_sysmem(addr, SIG_HEADER_LEN); + if (!sig_header) { + log_err("ERROR: can't map first header\n"); + ret = -EFAULT; + goto out; + } + + *magic = fdt32_to_cpu(sig_header->magic); + + unmap_sysmem(sig_header); + + out: + return ret; +} + +static int image_pre_load_sig_get_header_size(ulong addr, u32 *header_size) +{ + struct sig_header_s *sig_header; + int ret = 0; + + sig_header = (struct sig_header_s *)map_sysmem(addr, SIG_HEADER_LEN); + if (!sig_header) { + log_err("ERROR: can't map first header\n"); + ret = -EFAULT; + goto out; + } + + *header_size = fdt32_to_cpu(sig_header->header_size); + + unmap_sysmem(sig_header); + + out: + return ret; +} + +/* + * return: + * < 0 => no magic and magic mandatory (or error when reading magic) + * 0 => magic found + * 1 => magic NOT found + */ +static int image_pre_load_sig_check_magic(struct image_sig_info *info, ulong addr) +{ + u32 magic; + int ret = 1; + + ret = image_pre_load_sig_get_magic(addr, &magic); + if (ret < 0) + goto out; + + if (magic != IMAGE_PRE_LOAD_SIG_MAGIC) { + if (info->mandatory) { + log_err("ERROR: signature is mandatory\n"); + ret = -EINVAL; + goto out; + } + ret = 1; + goto out; + } + + ret = 0; /* magic found */ + + out: + return ret; +} + +static int image_pre_load_sig_check_header_sig(struct image_sig_info *info, ulong addr) +{ + void *header; + struct image_region reg; + u32 sig_len; + u8 *sig; + int ret = 0; + + /* Only map header of the header and its signature */ + header = (void *)map_sysmem(addr, SIG_HEADER_LEN + info->sig_size); + if (!header) { + log_err("ERROR: can't map header\n"); + ret = -EFAULT; + goto out; + } + + reg.data = header; + reg.size = SIG_HEADER_LEN; + + sig = (uint8_t *)header + SIG_HEADER_LEN; + sig_len = info->sig_size; + + ret = info->sig_info.crypto->verify(&info->sig_info, ®, 1, sig, sig_len); + if (ret) { + log_err("ERROR: header signature check has failed (err=%d)\n", ret); + ret = -EINVAL; + goto out_unmap; + } + + out_unmap: + unmap_sysmem(header); + + out: + return ret; +} + +static int image_pre_load_sig_check_img_sig_sha256(struct image_sig_info *info, ulong addr) +{ + struct sig_header_s *sig_header; + u32 header_size, offset_img_sig; + void *header; + u8 sha256_img_sig[SHA256_SUM_LEN]; + int ret = 0; + + sig_header = (struct sig_header_s *)map_sysmem(addr, SIG_HEADER_LEN); + if (!sig_header) { + log_err("ERROR: can't map first header\n"); + ret = -EFAULT; + goto out; + } + + header_size = fdt32_to_cpu(sig_header->header_size); + offset_img_sig = fdt32_to_cpu(sig_header->offset_img_sig); + + header = (void *)map_sysmem(addr, header_size); + if (!header) { + log_err("ERROR: can't map header\n"); + ret = -EFAULT; + goto out_sig_header; + } + + sha256_csum_wd(header + offset_img_sig, info->sig_size, + sha256_img_sig, CHUNKSZ_SHA256); + + ret = memcmp(sig_header->sha256_img_sig, sha256_img_sig, SHA256_SUM_LEN); + if (ret) { + log_err("ERROR: sha256 of image signature is invalid\n"); + ret = -EFAULT; + goto out_header; + } + + out_header: + unmap_sysmem(header); + out_sig_header: + unmap_sysmem(sig_header); + out: + return ret; +} + +static int image_pre_load_sig_check_img_sig(struct image_sig_info *info, ulong addr) +{ + struct sig_header_s *sig_header; + u32 header_size, image_size, offset_img_sig; + void *image; + struct image_region reg; + u32 sig_len; + u8 *sig; + int ret = 0; + + sig_header = (struct sig_header_s *)map_sysmem(addr, SIG_HEADER_LEN); + if (!sig_header) { + log_err("ERROR: can't map first header\n"); + ret = -EFAULT; + goto out; + } + + header_size = fdt32_to_cpu(sig_header->header_size); + image_size = fdt32_to_cpu(sig_header->image_size); + offset_img_sig = fdt32_to_cpu(sig_header->offset_img_sig); + + unmap_sysmem(sig_header); + + image = (void *)map_sysmem(addr, header_size + image_size); + if (!image) { + log_err("ERROR: can't map full image\n"); + ret = -EFAULT; + goto out; + } + + reg.data = image + header_size; + reg.size = image_size; + + sig = (uint8_t *)image + offset_img_sig; + sig_len = info->sig_size; + + ret = info->sig_info.crypto->verify(&info->sig_info, ®, 1, sig, sig_len); + if (ret) { + log_err("ERROR: signature check has failed (err=%d)\n", ret); + ret = -EINVAL; + goto out_unmap_image; + } + + log_info("INFO: signature check has succeed\n"); + + out_unmap_image: + unmap_sysmem(image); + + out: + return ret; +} + +int image_pre_load_sig(ulong addr) +{ + struct image_sig_info info; + int ret; + + ret = image_pre_load_sig_setup(&info); + if (ret < 0) + goto out; + if (ret > 0) { + ret = 0; + goto out; + } + + ret = image_pre_load_sig_check_magic(&info, addr); + if (ret < 0) + goto out; + if (ret > 0) { + ret = 0; + goto out; + } + + /* Check the signature of the signature header */ + ret = image_pre_load_sig_check_header_sig(&info, addr); + if (ret < 0) + goto out; + + /* Check sha256 of the image signature */ + ret = image_pre_load_sig_check_img_sig_sha256(&info, addr); + if (ret < 0) + goto out; + + /* Check the image signature */ + ret = image_pre_load_sig_check_img_sig(&info, addr); + if (!ret) { + u32 header_size; + + ret = image_pre_load_sig_get_header_size(addr, &header_size); + if (ret) { + log_err("%s: can't get header size\n", __func__); + ret = -EINVAL; + goto out; + } + + image_load_offset += header_size; + } + + out: + return ret; +} + +int image_pre_load(ulong addr) +{ + int ret = 0; + + image_load_offset = 0; + + if (CONFIG_IS_ENABLED(IMAGE_PRE_LOAD_SIG)) + ret = image_pre_load_sig(addr); + + return ret; +} diff --git a/include/image.h b/include/image.h index 97e5f2eb24..fbcf70f5e4 100644 --- a/include/image.h +++ b/include/image.h @@ -48,6 +48,7 @@ struct fdt_region; extern ulong image_load_addr; /* Default Load Address */ extern ulong image_save_addr; /* Default Save Address */ extern ulong image_save_size; /* Default Save Size */ +extern ulong image_load_offset; /* Default Load Address Offset */ /* An invalid size, meaning that the image size is not known */ #define IMAGE_SIZE_INVAL (-1UL) @@ -1323,6 +1324,19 @@ struct crypto_algo *image_get_crypto_algo(const char *full_name); */ struct padding_algo *image_get_padding_algo(const char *name); +/** + * image_pre_load() - Manage pre load header + * + * Manage the pre-load header before launching the image. + * It checks the signature of the image. It also set the + * variable image_load_offset to skip this header before + * launching the image. + * + * @param addr Address of the image + * @return: 0 on success, -ve on error + */ +int image_pre_load(ulong addr); + /** * fit_image_verify_required_sigs() - Verify signatures marked as 'required' * -- 2.25.1