From patchwork Thu Nov 26 18:40:58 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sughosh Ganu X-Patchwork-Id: 333039 Delivered-To: patch@linaro.org Received: by 2002:a92:5e16:0:0:0:0:0 with SMTP id s22csp1542456ilb; Thu, 26 Nov 2020 10:42:22 -0800 (PST) X-Google-Smtp-Source: ABdhPJyyaI4eYqvO0WEA7xlunUOBVezPcHzaUHh32czXeTFSf95kIv93zfvlW5nKUv/pZpx/NZmr X-Received: by 2002:a50:c40d:: with SMTP id v13mr3856953edf.1.1606416142651; Thu, 26 Nov 2020 10:42:22 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1606416142; cv=none; d=google.com; s=arc-20160816; b=dWMFPpd88P4BY09F2qp1guV8c1dABRdtfcpqvHHSGWxhSucRShutalpiT7N08LDVMq h19/XECsfzmBKlfW/UBcbSs7k0SCoat6UH8UdyhScb5pC5O9jmDCJUo1GOn8yM2LXadG /pXHk3CG5VXwGUPqRcHl46LrqDYfPV0YdRT0XJX4E1AS0cpzy5xZjDhpS0d6XKSR3JiF eNTR/HMsB2xMXSFLW3fPNTmAV5nRuk5XgKNYVjh3F4VZKkbSqVHK4IRCRalJTYRhrTW2 YgKBMSRcZn55tDxPHLiTKlePLk3cmQRONTa+i+WaBFm149MpXlz+cOAi6B6jTe58Z0LH WZZA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:references:in-reply-to :message-id:date:subject:cc:to:from; bh=TPnulCXKO1zooLm7HRL6Q6lJQeNu1y5YwKiu/57+pbc=; b=lFKRQ6yo09EtsPx8yk8kj+cGFK9XQVwVLolU1ekFMIA0ZxNBYqby/C1Gt/7JjbD/X8 V48F2dKyiHEsVyotSM7bnnxWp630opOhR4nUAfdS1Bj7uHe6FL7aAYIC2PMeNbwT0daC K9x6XeCAuXSFpStfJbKZjLMA7lXzUFuPlDjQSr0ytJBuHhRT8YdU2qjnpR3pcYb43Fpm YkUEjlV5MgiIpOEH7iU700r5SJEisggfIQlfxJr7NwIBvcoUbY3p6elSs1dpNOxd5kv6 wd8PumFWnth8s+D5KnlZhanymznVovaETvNDASiuFbkIhp3nNZ40KRfSmBYAv9J+ARYM CMpg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 85.214.62.61 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from phobos.denx.de (phobos.denx.de. [85.214.62.61]) by mx.google.com with ESMTPS id q16si3602589ejy.572.2020.11.26.10.42.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 26 Nov 2020 10:42:22 -0800 (PST) Received-SPF: pass (google.com: domain of u-boot-bounces@lists.denx.de designates 85.214.62.61 as permitted sender) client-ip=85.214.62.61; Authentication-Results: mx.google.com; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 85.214.62.61 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id CA185826D6; Thu, 26 Nov 2020 19:42:09 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Received: by phobos.denx.de (Postfix, from userid 109) id B58D7826E4; Thu, 26 Nov 2020 19:42:03 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,SPF_HELO_NONE, URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by phobos.denx.de (Postfix) with ESMTP id 4EC7F826CB for ; Thu, 26 Nov 2020 19:41:56 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=fail smtp.mailfrom=sughosh.ganu@linaro.org Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id E4EB21597; Thu, 26 Nov 2020 10:41:54 -0800 (PST) Received: from a076522.blr.arm.com (a076522.blr.arm.com [10.162.16.44]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 422613F23F; Thu, 26 Nov 2020 10:41:52 -0800 (PST) From: Sughosh Ganu To: u-boot@lists.denx.de Cc: Takahiro Akashi , Heinrich Schuchardt , Alexander Graf , Lukasz Majewski , Tuomas Tynkkynen , Tom Rini , Sughosh Ganu Subject: [PATCH 02/14] mkeficapsule: Add support for embedding public key in a dtb Date: Fri, 27 Nov 2020 00:10:58 +0530 Message-Id: <20201126184110.30521-3-sughosh.ganu@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20201126184110.30521-1-sughosh.ganu@linaro.org> References: <20201126184110.30521-1-sughosh.ganu@linaro.org> X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.34 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.102.3 at phobos.denx.de X-Virus-Status: Clean Add options for embedding the public key esl(efi signature list) file to the platform's dtb. The esl file is then retrieved and used for authenticating the capsule to be used for updating firmare components on the platform. The esl file can now be embedded in the dtb by invoking the following command mkeficapsule -K -D This will create a node named 'signature' in the dtb, and the esl file will be stored as 'capsule-key' Signed-off-by: Sughosh Ganu --- tools/Makefile | 1 + tools/mkeficapsule.c | 198 ++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 186 insertions(+), 13 deletions(-) -- 2.17.1 diff --git a/tools/Makefile b/tools/Makefile index 66d9376803..6d7b48fb57 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -218,6 +218,7 @@ hostprogs-$(CONFIG_MIPS) += mips-relocs hostprogs-$(CONFIG_ASN1_COMPILER) += asn1_compiler HOSTCFLAGS_asn1_compiler.o = -idirafter $(srctree)/include +mkeficapsule-objs := mkeficapsule.o $(LIBFDT_OBJS) hostprogs-$(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) += mkeficapsule # We build some files with extra pedantic flags to try to minimize things diff --git a/tools/mkeficapsule.c b/tools/mkeficapsule.c index 45e27d74a5..ce05da12d6 100644 --- a/tools/mkeficapsule.c +++ b/tools/mkeficapsule.c @@ -4,16 +4,22 @@ * Author: AKASHI Takahiro */ +#include #include #include #include #include #include #include +#include #include + +#include #include #include +#include "fdt_host.h" + typedef __u8 u8; typedef __u16 u16; typedef __u32 u32; @@ -23,6 +29,8 @@ typedef __s32 s32; #define aligned_u64 __aligned_u64 +#define SIGNATURE_NODENAME "signature" + #ifndef __packed #define __packed __attribute__((packed)) #endif @@ -43,6 +51,8 @@ static struct option options[] = { {"raw", required_argument, NULL, 'r'}, {"index", required_argument, NULL, 'i'}, {"instance", required_argument, NULL, 'I'}, + {"dtb", required_argument, NULL, 'D'}, + {"public key", required_argument, NULL, 'K'}, {"version", required_argument, NULL, 'v'}, {"help", no_argument, NULL, 'h'}, {NULL, 0, NULL, 0}, @@ -52,15 +62,154 @@ static void print_usage(void) { printf("Usage: %s [options] \n" "Options:\n" - "\t--fit new FIT image file\n" - "\t--raw new raw image file\n" - "\t--index update image index\n" - "\t--instance update hardware instance\n" - "\t--version firmware version\n" - "\t--help print a help message\n", + "\t--fit new FIT image file\n" + "\t--raw new raw image file\n" + "\t--index update image index\n" + "\t--instance update hardware instance\n" + "\t--version firmware version\n" + "\t--public-key public key esl file\n" + "\t--dtb dtb file\n" + "\t--help print a help message\n", tool_name); } +static int fdt_add_pub_key_data(void *sptr, void *dptr, size_t key_size) +{ + int parent; + int ret = 0; + + parent = fdt_subnode_offset(dptr, 0, SIGNATURE_NODENAME); + if (parent == -FDT_ERR_NOTFOUND) { + parent = fdt_add_subnode(dptr, 0, SIGNATURE_NODENAME); + if (parent < 0) { + ret = parent; + if (ret != -FDT_ERR_NOSPACE) { + fprintf(stderr, + "Couldn't create signature node: %s\n", + fdt_strerror(parent)); + } + } + } + if (ret) + goto done; + + /* Write the key to the FDT node */ + ret = fdt_setprop(dptr, parent, "capsule-key", + sptr, key_size); + +done: + if (ret) + ret = ret == -FDT_ERR_NOSPACE ? -ENOSPC : -EIO; + + return ret; +} + +static int add_public_key(const char *pkey_file, const char *dtb_file) +{ + int ret; + int srcfd = 0; + int destfd = 0; + void *sptr = NULL; + void *dptr = NULL; + off_t src_size; + struct stat pub_key; + struct stat dtb; + + /* Find out the size of the public key */ + srcfd = open(pkey_file, O_RDONLY); + if (srcfd == -1) { + fprintf(stderr, "%s: Can't open %s: %s\n", + __func__, pkey_file, strerror(errno)); + goto err; + } + + ret = fstat(srcfd, &pub_key); + if (ret == -1) { + fprintf(stderr, "%s: Can't stat %s: %s\n", + __func__, pkey_file, strerror(errno)); + goto err; + } + + src_size = pub_key.st_size; + + /* mmap the public key esl file */ + sptr = mmap(0, src_size, PROT_READ, MAP_SHARED, srcfd, 0); + if ((sptr == MAP_FAILED) || (errno != 0)) { + fprintf(stderr, "%s: Failed to mmap %s:%s\n", + __func__, pkey_file, strerror(errno)); + goto err; + } + + /* Open the dest FDT */ + destfd = open(dtb_file, O_RDWR); + if (destfd == -1) { + fprintf(stderr, "%s: Can't open %s: %s\n", + __func__, dtb_file, strerror(errno)); + goto err; + } + + ret = fstat(destfd, &dtb); + if (ret == -1) { + fprintf(stderr, "%s: Can't stat %s: %s\n", + __func__, dtb_file, strerror(errno)); + goto err; + } + + dtb.st_size += src_size; + if (ftruncate(destfd, dtb.st_size)) { + fprintf(stderr, "%s: Can't expand %s: %s\n", + __func__, dtb_file, strerror(errno)); + goto err;; + } + + errno = 0; + /* mmap the dtb file */ + dptr = mmap(0, dtb.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, + destfd, 0); + if ((dptr == MAP_FAILED) || (errno != 0)) { + fprintf(stderr, "%s: Failed to mmap %s:%s\n", + __func__, dtb_file, strerror(errno)); + goto err; + } + + if (fdt_check_header(dptr)) { + fprintf(stderr, "%s: Invalid FDT header\n", __func__); + goto err; + } + + ret = fdt_open_into(dptr, dptr, dtb.st_size); + if (ret) { + fprintf(stderr, "%s: Cannot expand FDT: %s\n", + __func__, fdt_strerror(ret)); + goto err; + } + + /* Copy the esl file to the expanded FDT */ + ret = fdt_add_pub_key_data(sptr, dptr, src_size); + if (ret < 0) { + fprintf(stderr, "%s: Unable to add public key to the FDT\n", + __func__); + goto err; + } + + return 0; + +err: + if (sptr) + munmap(sptr, src_size); + + if (dptr) + munmap(dptr, dtb.st_size); + + if (srcfd >= 0) + close(srcfd); + + if (destfd >= 0) + close(destfd); + + return -1; +} + static int create_fwbin(char *path, char *bin, efi_guid_t *guid, unsigned long version, unsigned long index, unsigned long instance) @@ -171,17 +320,22 @@ err_1: int main(int argc, char **argv) { char *file; + char *pkey_file; + char *dtb_file; efi_guid_t *guid; unsigned long index, instance, version; int c, idx; + int ret; file = NULL; + pkey_file = NULL; + dtb_file = NULL; guid = NULL; index = 0; instance = 0; version = 0; for (;;) { - c = getopt_long(argc, argv, "f:r:i:I:v:h", options, &idx); + c = getopt_long(argc, argv, "f:r:i:I:v:D:K:h", options, &idx); if (c == -1) break; @@ -211,22 +365,40 @@ int main(int argc, char **argv) case 'v': version = strtoul(optarg, NULL, 0); break; + case 'K': + if (pkey_file) { + printf("Public Key already specified\n"); + return -1; + } + pkey_file = optarg; + break; + case 'D': + if (dtb_file) { + printf("DTB file already specified\n"); + return -1; + } + dtb_file = optarg; + break; case 'h': print_usage(); return 0; } } - /* need a output file */ - if (argc != optind + 1) { + /* need a fit image file or raw image file */ + if (!file && !pkey_file && !dtb_file) { print_usage(); return -1; } - /* need a fit image file or raw image file */ - if (!file) { - print_usage(); - return -1; + if (pkey_file && dtb_file) { + ret = add_public_key(pkey_file, dtb_file); + if (ret == -1) { + printf("Adding public key to the dtb failed\n"); + return -1; + } else { + return 0; + } } if (create_fwbin(argv[optind], file, guid, version, index, instance)