From patchwork Fri Jan 8 19:17:32 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Alex G." X-Patchwork-Id: 1423944 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=TZhaTnDb; dkim-atps=neutral Received: from phobos.denx.de (unknown [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4DCCYl0LsJz9sWS for ; Sat, 9 Jan 2021 06:18:17 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id E4F3782987; Fri, 8 Jan 2021 20:17:51 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.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=gmail.com header.i=@gmail.com header.b="TZhaTnDb"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 8A2B282981; Fri, 8 Jan 2021 20:17:49 +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=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-ot1-x32c.google.com (mail-ot1-x32c.google.com [IPv6:2607:f8b0:4864:20::32c]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 536098295D for ; Fri, 8 Jan 2021 20:17:46 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=mr.nuke.me@gmail.com Received: by mail-ot1-x32c.google.com with SMTP id d8so10709333otq.6 for ; Fri, 08 Jan 2021 11:17:46 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=q7luY886YCkUHX5uKOq36J5cO4R4CTG3YCgmC8kP5K4=; b=TZhaTnDbREptsCnAzFUqDcFy9AgROtn6vP8AVFEW6x/mwoiVWGszG4cuk5oGSKNAH4 SV89S2dNd19Renzibx2PZYkmh3m1835rvEOExyPFgmmN0scHXEca5PuAwTpO6QqJyiby PouBHB96QDYU/z2ETszTOp5oRISz7bFA52YKFEyfCD/KNEii/L7UsnpUWjXtEVw6Gqqf PCz72KFpRQAhIHNsxorYWgC8EmlNgLZvkmeWFtjq+PzbSUYp1TXibQ5dm7k52M+2UnJq a3ularbx2xa7N6ylByxdlGX3bnRh7rb0TB3P9dAe4MtbRzSO5rAeJpFh69Y0dsTjPUOl pEzw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=q7luY886YCkUHX5uKOq36J5cO4R4CTG3YCgmC8kP5K4=; b=YvPtE4YEKGerGF66Hwgul/pjE23PS0O/yRWxxGPxlrWKoJjVr2KYteEOS06d3a+UeF l2tmBp73+csxU9glJJAgxMph9W5drQXMngr3lC9hAQ+l7ejuHgYDB345G26+ROGUJwO1 ruHqK5UY3SD+M59w/DqxVeQ0/PKxO+E2M9EJGAZKgI+8DNdIXVy1mM1qsCPJCV01vj3p k898uWaq5Wes+PK+O+0LAH7smBEHT+LE84VBWVAJJrkt5G71/XVfGBRf0CT9OXbH96OH cUasTmVaay5HE03PPQvd6ZhQiiFBZln1N83vJDKViXoq8Jiwuq2dtp4s4E4s4SUSbnx7 zGUQ== X-Gm-Message-State: AOAM531BTLaXlxLUHNqbSfjAVe1sS49f237ykR+WGDNRETdbGbp88fbo fViTNa/TO049o6EqVowdGfFal2L4Wgf/uEZp X-Google-Smtp-Source: ABdhPJwueNFtHysHfQraBpYSLIMievr/Mcbf5OC+2/hsTzJ4krMl4Q48sQngVQl82NSvcnkpt2PuJQ== X-Received: by 2002:a05:6830:1257:: with SMTP id s23mr3539593otp.69.1610133464796; Fri, 08 Jan 2021 11:17:44 -0800 (PST) Received: from nuclearis2-1.lan (c-98-195-139-126.hsd1.tx.comcast.net. [98.195.139.126]) by smtp.gmail.com with ESMTPSA id g200sm2131617oib.19.2021.01.08.11.17.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 08 Jan 2021 11:17:44 -0800 (PST) From: Alexandru Gagniuc To: u-boot@lists.denx.de, sjg@chromium.org Cc: Alexandru Gagniuc , trini@konsulko.com, marex@denx.de Subject: [PATCH v4 1/6] lib: Rename rsa-checksum.c to hash-checksum.c Date: Fri, 8 Jan 2021 13:17:32 -0600 Message-Id: <20210108191737.615022-2-mr.nuke.me@gmail.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20210108191737.615022-1-mr.nuke.me@gmail.com> References: <20210108191737.615022-1-mr.nuke.me@gmail.com> MIME-Version: 1.0 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 rsa-checksum.c sontains the hash_calculate() implementations. Despite the "rsa-" file prefix, this function is useful for other algorithms. To prevent confusion, move this file to lib/crypto, and rename it to hash-checksum.c, to give it a more "generic" feel. Signed-off-by: Alexandru Gagniuc --- common/image-fit-sig.c | 2 +- common/image-sig.c | 2 +- include/image.h | 2 +- include/u-boot/{rsa-checksum.h => hash-checksum.h} | 0 lib/Makefile | 1 + lib/crypto/pkcs7_verify.c | 2 +- lib/crypto/x509_public_key.c | 2 +- lib/{rsa/rsa-checksum.c => hash-checksum.c} | 3 ++- lib/rsa/Makefile | 2 +- tools/Makefile | 3 ++- 10 files changed, 11 insertions(+), 8 deletions(-) rename include/u-boot/{rsa-checksum.h => hash-checksum.h} (100%) rename lib/{rsa/rsa-checksum.c => hash-checksum.c} (96%) diff --git a/common/image-fit-sig.c b/common/image-fit-sig.c index 5401d9411b..7fcbb47235 100644 --- a/common/image-fit-sig.c +++ b/common/image-fit-sig.c @@ -15,7 +15,7 @@ DECLARE_GLOBAL_DATA_PTR; #include #include #include -#include +#include #define IMAGE_MAX_HASHED_NODES 100 diff --git a/common/image-sig.c b/common/image-sig.c index f3c209ae8b..21dafe6b91 100644 --- a/common/image-sig.c +++ b/common/image-sig.c @@ -16,7 +16,7 @@ DECLARE_GLOBAL_DATA_PTR; #endif /* !USE_HOSTCC*/ #include #include -#include +#include #define IMAGE_MAX_HASHED_NODES 100 diff --git a/include/image.h b/include/image.h index 41473dbb9c..a55b11b3ae 100644 --- a/include/image.h +++ b/include/image.h @@ -1258,7 +1258,7 @@ struct image_region { }; #if IMAGE_ENABLE_VERIFY -# include +# include #endif struct checksum_algo { const char *name; diff --git a/include/u-boot/rsa-checksum.h b/include/u-boot/hash-checksum.h similarity index 100% rename from include/u-boot/rsa-checksum.h rename to include/u-boot/hash-checksum.h diff --git a/lib/Makefile b/lib/Makefile index 851a80ef3b..cf64188ba5 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -60,6 +60,7 @@ endif obj-$(CONFIG_$(SPL_)ACPIGEN) += acpi/ obj-$(CONFIG_$(SPL_)MD5) += md5.o obj-$(CONFIG_$(SPL_)RSA) += rsa/ +obj-$(CONFIG_FIT_SIGNATURE) += hash-checksum.o obj-$(CONFIG_SHA1) += sha1.o obj-$(CONFIG_SHA256) += sha256.o obj-$(CONFIG_SHA512_ALGO) += sha512.o diff --git a/lib/crypto/pkcs7_verify.c b/lib/crypto/pkcs7_verify.c index 320ba49f79..3c411f651f 100644 --- a/lib/crypto/pkcs7_verify.c +++ b/lib/crypto/pkcs7_verify.c @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include #include #else diff --git a/lib/crypto/x509_public_key.c b/lib/crypto/x509_public_key.c index 91810a8640..d557ab27ae 100644 --- a/lib/crypto/x509_public_key.c +++ b/lib/crypto/x509_public_key.c @@ -19,7 +19,7 @@ #include #ifdef __UBOOT__ #include -#include +#include #else #include #include diff --git a/lib/rsa/rsa-checksum.c b/lib/hash-checksum.c similarity index 96% rename from lib/rsa/rsa-checksum.c rename to lib/hash-checksum.c index e60debb7df..d732ecc38f 100644 --- a/lib/rsa/rsa-checksum.c +++ b/lib/hash-checksum.c @@ -13,7 +13,8 @@ #else #include "fdt_host.h" #endif -#include +#include +#include int hash_calculate(const char *name, const struct image_region region[], diff --git a/lib/rsa/Makefile b/lib/rsa/Makefile index 8b75d41f04..c9ac72c1e2 100644 --- a/lib/rsa/Makefile +++ b/lib/rsa/Makefile @@ -5,6 +5,6 @@ # (C) Copyright 2000-2007 # Wolfgang Denk, DENX Software Engineering, wd@denx.de. -obj-$(CONFIG_$(SPL_TPL_)RSA_VERIFY) += rsa-verify.o rsa-checksum.o +obj-$(CONFIG_$(SPL_TPL_)RSA_VERIFY) += rsa-verify.o obj-$(CONFIG_$(SPL_TPL_)RSA_VERIFY_WITH_PKEY) += rsa-keyprop.o obj-$(CONFIG_RSA_SOFTWARE_EXP) += rsa-mod-exp.o diff --git a/tools/Makefile b/tools/Makefile index 253a6b9706..b1595ad814 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -67,7 +67,7 @@ LIBFDT_OBJS := $(addprefix libfdt/, fdt.o fdt_ro.o fdt_wip.o fdt_sw.o fdt_rw.o \ fdt_strerror.o fdt_empty_tree.o fdt_addresses.o fdt_overlay.o) RSA_OBJS-$(CONFIG_FIT_SIGNATURE) := $(addprefix lib/rsa/, \ - rsa-sign.o rsa-verify.o rsa-checksum.o \ + rsa-sign.o rsa-verify.o \ rsa-mod-exp.o) AES_OBJS-$(CONFIG_FIT_CIPHER) := $(addprefix lib/aes/, \ @@ -105,6 +105,7 @@ dumpimage-mkimage-objs := aisimage.o \ $(ROCKCHIP_OBS) \ socfpgaimage.o \ lib/crc16.o \ + lib/hash-checksum.o \ lib/sha1.o \ lib/sha256.o \ lib/sha512.o \ From patchwork Fri Jan 8 19:17:33 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Alex G." X-Patchwork-Id: 1423943 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=RDHbe1tH; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4DCCYk4F9gz9sWN for ; Sat, 9 Jan 2021 06:18:18 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 6A0918298E; Fri, 8 Jan 2021 20:17:53 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.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=gmail.com header.i=@gmail.com header.b="RDHbe1tH"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 7719982989; Fri, 8 Jan 2021 20:17:51 +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=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-ot1-x331.google.com (mail-ot1-x331.google.com [IPv6:2607:f8b0:4864:20::331]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 1698D8296E for ; Fri, 8 Jan 2021 20:17:47 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=mr.nuke.me@gmail.com Received: by mail-ot1-x331.google.com with SMTP id x13so10694105oto.8 for ; Fri, 08 Jan 2021 11:17:47 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=ZMFcPzJGlL+EiQ2gtFXoMKdtAzow+sUUCplHmDTH8JQ=; b=RDHbe1tH3Wc3NMFYiQbxG+lNYpVBSgX1Vu8s9SLOKwnAX+c0BZE8gSqP9ZyPT9cG/N ZOR36EMVistqiVZi3156mJpy79e0vg/tBxpTfPGMvhN3ie24+zF8ahfE9OqExDmEWUFM mjAbSrR3hsWzVesYRTQBiKhH3j2N8pQbcdc3ydl7R+rGoC+231XUpd+4GhH5e5uQwdCB iy2nAEtxF2qh993p1WL9sQzrDsoq1eVb51trapIu1aGeXVQg8+7+GLs00QqGpCyQxVCg sMo0Tk49wzLbLSTRdIdKAYwobDbwFa331z++oXeFziToHavXwK0+kMqNKZEfhK5DG3QF Onzw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=ZMFcPzJGlL+EiQ2gtFXoMKdtAzow+sUUCplHmDTH8JQ=; b=gFZQMMuiB8wJ9vVZvqIZsNc0I2KFaLSDr4op77MDZh8ibjppeo/NltVeya6Mapg0h6 OcAfarvuf5pDcIHX+aYzIrD4gPgn+6gtsZ2VkhAiB8H5/bZ/aCNaC48uQ/LMNjt43xDG +aDta9eH9Q1hl77TD9aQbW/vxs/1DeCU4e13xxELlAdcuKgYgTUHk3lgQ3uHUCA4VQoF 3GPhvgxXG2YD9pzcQ/RZ7hjmcjnBM+rXxLIvj2olg+gILAm+aJKLirsX1bOWwsBOi3ZK 4WZlLDM2nOfsWiXTYJ5NP8eWbFo3+CME26N5j48qGjeQTauyi5r1qhbm20/IuUsybH5O k0fg== X-Gm-Message-State: AOAM530N1Fhi149xwevfSYkd8ff6RUC9k/lbgZbBk9fzh/cqt1Qkm3da FP+Hk21LWDmmtgDlD4V/XcAL8o3RlzmGKYJE X-Google-Smtp-Source: ABdhPJwyHm8eNJ5vjwEQrSO57DNMKYvt4HCJPiWJLKlV3x+h1wvygprsVMxhxYP8i5VfRX88HbXRpQ== X-Received: by 2002:a9d:1720:: with SMTP id i32mr3684846ota.84.1610133465568; Fri, 08 Jan 2021 11:17:45 -0800 (PST) Received: from nuclearis2-1.lan (c-98-195-139-126.hsd1.tx.comcast.net. [98.195.139.126]) by smtp.gmail.com with ESMTPSA id g200sm2131617oib.19.2021.01.08.11.17.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 08 Jan 2021 11:17:45 -0800 (PST) From: Alexandru Gagniuc To: u-boot@lists.denx.de, sjg@chromium.org Cc: Alexandru Gagniuc , trini@konsulko.com, marex@denx.de Subject: [PATCH v4 2/6] lib/rsa: Make fdt_add_bignum() available outside of RSA code Date: Fri, 8 Jan 2021 13:17:33 -0600 Message-Id: <20210108191737.615022-3-mr.nuke.me@gmail.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20210108191737.615022-1-mr.nuke.me@gmail.com> References: <20210108191737.615022-1-mr.nuke.me@gmail.com> MIME-Version: 1.0 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 fdt_add_bignum() is useful for algorithms other than just RSA. To allow its use for ECDSA, move it to a common file under lib/. The new file is suffixed with '-libcrypto' because it has a direct dependency on openssl. This is due to the use of the "BIGNUM *" type. Signed-off-by: Alexandru Gagniuc --- include/u-boot/fdt-libcrypto.h | 27 +++++++++++++ lib/fdt-libcrypto.c | 72 ++++++++++++++++++++++++++++++++++ lib/rsa/rsa-sign.c | 65 +----------------------------- tools/Makefile | 1 + 4 files changed, 101 insertions(+), 64 deletions(-) create mode 100644 include/u-boot/fdt-libcrypto.h create mode 100644 lib/fdt-libcrypto.c diff --git a/include/u-boot/fdt-libcrypto.h b/include/u-boot/fdt-libcrypto.h new file mode 100644 index 0000000000..5142f37039 --- /dev/null +++ b/include/u-boot/fdt-libcrypto.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2020, Alexandru Gagniuc + * Copyright (c) 2013, Google Inc. + */ + +#ifndef _FDT_LIBCRYPTO_H +#define _FDT_LIBCRYPTO_H + +#include + +/** + * fdt_add_bignum() - Write a libcrypto BIGNUM as an FDT property + * + * Convert a libcrypto BIGNUM * into a big endian array of integers. + * + * @blob: FDT blob to modify + * @noffset: Offset of the FDT node + * @prop_name: What to call the property in the FDT + * @num: pointer to a libcrypto big number + * @num_bits: How big is 'num' in bits? + * @return 0 if all good all working, -ve on horror + */ +int fdt_add_bignum(void *blob, int noffset, const char *prop_name, + BIGNUM *num, int num_bits); + +#endif /* _FDT_LIBCRYPTO_H */ diff --git a/lib/fdt-libcrypto.c b/lib/fdt-libcrypto.c new file mode 100644 index 0000000000..ecb0344c8f --- /dev/null +++ b/lib/fdt-libcrypto.c @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2020, Alexandru Gagniuc + * Copyright (c) 2013, Google Inc. + */ + +#include +#include + +int fdt_add_bignum(void *blob, int noffset, const char *prop_name, + BIGNUM *num, int num_bits) +{ + int nwords = num_bits / 32; + int size; + uint32_t *buf, *ptr; + BIGNUM *tmp, *big2, *big32, *big2_32; + BN_CTX *ctx; + int ret; + + tmp = BN_new(); + big2 = BN_new(); + big32 = BN_new(); + big2_32 = BN_new(); + + /* + * Note: This code assumes that all of the above succeed, or all fail. + * In practice memory allocations generally do not fail (unless the + * process is killed), so it does not seem worth handling each of these + * as a separate case. Technicaly this could leak memory on failure, + * but a) it won't happen in practice, and b) it doesn't matter as we + * will immediately exit with a failure code. + */ + if (!tmp || !big2 || !big32 || !big2_32) { + fprintf(stderr, "Out of memory (bignum)\n"); + return -ENOMEM; + } + ctx = BN_CTX_new(); + if (!ctx) { + fprintf(stderr, "Out of memory (bignum context)\n"); + return -ENOMEM; + } + BN_set_word(big2, 2L); + BN_set_word(big32, 32L); + BN_exp(big2_32, big2, big32, ctx); /* B = 2^32 */ + + size = nwords * sizeof(uint32_t); + buf = malloc(size); + if (!buf) { + fprintf(stderr, "Out of memory (%d bytes)\n", size); + return -ENOMEM; + } + + /* Write out modulus as big endian array of integers */ + for (ptr = buf + nwords - 1; ptr >= buf; ptr--) { + BN_mod(tmp, num, big2_32, ctx); /* n = N mod B */ + *ptr = cpu_to_fdt32(BN_get_word(tmp)); + BN_rshift(num, num, 32); /* N = N/B */ + } + + /* + * We try signing with successively increasing size values, so this + * might fail several times + */ + ret = fdt_setprop(blob, noffset, prop_name, buf, size); + free(buf); + BN_free(tmp); + BN_free(big2); + BN_free(big32); + BN_free(big2_32); + + return ret ? -FDT_ERR_NOSPACE : 0; +} diff --git a/lib/rsa/rsa-sign.c b/lib/rsa/rsa-sign.c index 1f0d81bd7a..557c690a6d 100644 --- a/lib/rsa/rsa-sign.c +++ b/lib/rsa/rsa-sign.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -680,70 +681,6 @@ int rsa_get_params(RSA *key, uint64_t *exponent, uint32_t *n0_invp, return ret; } -static int fdt_add_bignum(void *blob, int noffset, const char *prop_name, - BIGNUM *num, int num_bits) -{ - int nwords = num_bits / 32; - int size; - uint32_t *buf, *ptr; - BIGNUM *tmp, *big2, *big32, *big2_32; - BN_CTX *ctx; - int ret; - - tmp = BN_new(); - big2 = BN_new(); - big32 = BN_new(); - big2_32 = BN_new(); - - /* - * Note: This code assumes that all of the above succeed, or all fail. - * In practice memory allocations generally do not fail (unless the - * process is killed), so it does not seem worth handling each of these - * as a separate case. Technicaly this could leak memory on failure, - * but a) it won't happen in practice, and b) it doesn't matter as we - * will immediately exit with a failure code. - */ - if (!tmp || !big2 || !big32 || !big2_32) { - fprintf(stderr, "Out of memory (bignum)\n"); - return -ENOMEM; - } - ctx = BN_CTX_new(); - if (!ctx) { - fprintf(stderr, "Out of memory (bignum context)\n"); - return -ENOMEM; - } - BN_set_word(big2, 2L); - BN_set_word(big32, 32L); - BN_exp(big2_32, big2, big32, ctx); /* B = 2^32 */ - - size = nwords * sizeof(uint32_t); - buf = malloc(size); - if (!buf) { - fprintf(stderr, "Out of memory (%d bytes)\n", size); - return -ENOMEM; - } - - /* Write out modulus as big endian array of integers */ - for (ptr = buf + nwords - 1; ptr >= buf; ptr--) { - BN_mod(tmp, num, big2_32, ctx); /* n = N mod B */ - *ptr = cpu_to_fdt32(BN_get_word(tmp)); - BN_rshift(num, num, 32); /* N = N/B */ - } - - /* - * We try signing with successively increasing size values, so this - * might fail several times - */ - ret = fdt_setprop(blob, noffset, prop_name, buf, size); - free(buf); - BN_free(tmp); - BN_free(big2); - BN_free(big32); - BN_free(big2_32); - - return ret ? -FDT_ERR_NOSPACE : 0; -} - int rsa_add_verify_data(struct image_sign_info *info, void *keydest) { BIGNUM *modulus, *r_squared; diff --git a/tools/Makefile b/tools/Makefile index b1595ad814..af7698fd01 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -106,6 +106,7 @@ dumpimage-mkimage-objs := aisimage.o \ socfpgaimage.o \ lib/crc16.o \ lib/hash-checksum.o \ + lib/fdt-libcrypto.o \ lib/sha1.o \ lib/sha256.o \ lib/sha512.o \ From patchwork Fri Jan 8 19:17:34 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Alex G." X-Patchwork-Id: 1423947 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=DHpOXOEz; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4DCCZK0l0qz9sWK for ; Sat, 9 Jan 2021 06:18:49 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 9650D82991; Fri, 8 Jan 2021 20:18:00 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.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=gmail.com header.i=@gmail.com header.b="DHpOXOEz"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 178E882991; Fri, 8 Jan 2021 20:17:54 +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=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-oi1-x230.google.com (mail-oi1-x230.google.com [IPv6:2607:f8b0:4864:20::230]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 4449A82978 for ; Fri, 8 Jan 2021 20:17:48 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=mr.nuke.me@gmail.com Received: by mail-oi1-x230.google.com with SMTP id 9so12529491oiq.3 for ; Fri, 08 Jan 2021 11:17:48 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=UhdPS0YVeMQliRFCgqtAECuo//BafFTSE4tB1XI6faQ=; b=DHpOXOEzG53+B/tT/zReJSuuywzPMHJyx7gpi4ccyohk9nSwnl0uieNhM+fEukoZkd 0w+qQHsHDA7BNP8DRUrx9HRRnvR3Qj0OAJJ04RRaTDlMZaQMOqnFDU4sLamdESJbwBWE +9dbAAC+SaTbOHcHbmaYKsv0yut3pgtYRSBtI5S01K71nvy2jasjOQKnyjA9vTps/XVZ GHDJwrioGP2rVEVb+W5/toHPx4aEHbWpKW7xcE8/BScDnKAN8VWKX4bw3qArNiQlJQrc twgSdrySbeTf3Fnd9PdYBuZZ/oLqMNr6Q0Cd6rV81t8cmHZ6uzt24DqnZg0RLmZ84wtd e8tA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=UhdPS0YVeMQliRFCgqtAECuo//BafFTSE4tB1XI6faQ=; b=maa8tLhQ8vOTih5kJzUfKYBmbXvl7rkI44oTiCd+fSNW+IcviX0C4OTr4u92PSqVEI U28Xis/gVZCh0By+xmb/X4nzMRQ8P/ghDPIlHUbVtJuq4pI77isyxD1adh5VrII5tHTi oo4hAX/ypftYj99qG9Wa9Y6/oB6Eg+4zb+4T8wbntvdqVGFTVbC7vXFsfgAq4QWxkCaT f86EI+pwJfj10L1vWhIEb9ASDA32j1ImdzKTjMT7SSVhaGWNGecKLjDOW7f0i7PWkqGs kKi0P+jQkWzw6K9Ol8Qsb5lOX0+sSEiQaC80UCxAU3w14iOR0JS2GrW/oS256hzWSd1E FJcg== X-Gm-Message-State: AOAM533uxhMBEYSQVsR7JWIRGL+m+XVJ9JnKgbd8DRpmIZsMUkBQN/Tr ZV+UV4r1SYpknbMbY1QhqXJpzjDjPpmgSXZW X-Google-Smtp-Source: ABdhPJzp5BS8IjrhraQt8U9zFhYXK82LlL3C41taP7NvYGX+woLpX+eYEqq5NTrFRw7FSQRR7xYivw== X-Received: by 2002:aca:1918:: with SMTP id l24mr3206202oii.2.1610133466361; Fri, 08 Jan 2021 11:17:46 -0800 (PST) Received: from nuclearis2-1.lan (c-98-195-139-126.hsd1.tx.comcast.net. [98.195.139.126]) by smtp.gmail.com with ESMTPSA id g200sm2131617oib.19.2021.01.08.11.17.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 08 Jan 2021 11:17:45 -0800 (PST) From: Alexandru Gagniuc To: u-boot@lists.denx.de, sjg@chromium.org Cc: Alexandru Gagniuc , trini@konsulko.com, marex@denx.de Subject: [PATCH v4 3/6] lib: Add support for ECDSA image signing Date: Fri, 8 Jan 2021 13:17:34 -0600 Message-Id: <20210108191737.615022-4-mr.nuke.me@gmail.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20210108191737.615022-1-mr.nuke.me@gmail.com> References: <20210108191737.615022-1-mr.nuke.me@gmail.com> MIME-Version: 1.0 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 mkimage supports rsa2048, and rsa4096 signatures. With newer silicon now supporting hardware-accelerated ECDSA, it makes sense to expand signing support to elliptic curves. Implement host-side ECDSA signing and verification with libcrypto. Device-side implementation of signature verification is beyond the scope of this patch. Signed-off-by: Alexandru Gagniuc --- common/image-sig.c | 11 +- include/image.h | 3 + include/u-boot/ecdsa.h | 94 +++++++++++ lib/ecdsa/ecdsa-libcrypto.c | 306 ++++++++++++++++++++++++++++++++++++ tools/Makefile | 3 + 5 files changed, 415 insertions(+), 2 deletions(-) create mode 100644 include/u-boot/ecdsa.h create mode 100644 lib/ecdsa/ecdsa-libcrypto.c diff --git a/common/image-sig.c b/common/image-sig.c index 21dafe6b91..4b7d01f6c2 100644 --- a/common/image-sig.c +++ b/common/image-sig.c @@ -15,6 +15,7 @@ DECLARE_GLOBAL_DATA_PTR; #endif /* !USE_HOSTCC*/ #include +#include #include #include @@ -82,8 +83,14 @@ struct crypto_algo crypto_algos[] = { .sign = rsa_sign, .add_verify_data = rsa_add_verify_data, .verify = rsa_verify, - } - + }, + { + .name = "ecdsa256", + .key_len = ECDSA256_BYTES, + .sign = ecdsa_sign, + .add_verify_data = ecdsa_add_verify_data, + .verify = ecdsa_verify, + }, }; struct padding_algo padding_algos[] = { diff --git a/include/image.h b/include/image.h index a55b11b3ae..6628173dca 100644 --- a/include/image.h +++ b/include/image.h @@ -1199,16 +1199,19 @@ int calculate_hash(const void *data, int data_len, const char *algo, # if defined(CONFIG_FIT_SIGNATURE) # define IMAGE_ENABLE_SIGN 1 # define IMAGE_ENABLE_VERIFY 1 +# define IMAGE_ENABLE_VERIFY_ECDSA 1 # define FIT_IMAGE_ENABLE_VERIFY 1 # include # else # define IMAGE_ENABLE_SIGN 0 # define IMAGE_ENABLE_VERIFY 0 +# define IMAGE_ENABLE_VERIFY_ECDSA 0 # define FIT_IMAGE_ENABLE_VERIFY 0 # endif #else # define IMAGE_ENABLE_SIGN 0 # define IMAGE_ENABLE_VERIFY CONFIG_IS_ENABLED(RSA_VERIFY) +# define IMAGE_ENABLE_VERIFY_ECDSA 0 # define FIT_IMAGE_ENABLE_VERIFY CONFIG_IS_ENABLED(FIT_SIGNATURE) #endif diff --git a/include/u-boot/ecdsa.h b/include/u-boot/ecdsa.h new file mode 100644 index 0000000000..979690d966 --- /dev/null +++ b/include/u-boot/ecdsa.h @@ -0,0 +1,94 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2020, Alexandru Gagniuc . + */ + +#ifndef _ECDSA_H +#define _ECDSA_H + +#include +#include +#include + +/** + * crypto_algo API impementation for ECDSA; + * @see "struct crypto_algo" + * @{ + */ +#if IMAGE_ENABLE_SIGN +/** + * sign() - calculate and return signature for given input data + * + * @info: Specifies key and FIT information + * @data: Pointer to the input data + * @data_len: Data length + * @sigp: Set to an allocated buffer holding the signature + * @sig_len: Set to length of the calculated hash + * + * This computes input data signature according to selected algorithm. + * Resulting signature value is placed in an allocated buffer, the + * pointer is returned as *sigp. The length of the calculated + * signature is returned via the sig_len pointer argument. The caller + * should free *sigp. + * + * @return: 0, on success, -ve on error + */ +int ecdsa_sign(struct image_sign_info *info, const struct image_region region[], + int region_count, uint8_t **sigp, uint *sig_len); + +/** + * add_verify_data() - Add verification information to FDT + * + * Add public key information to the FDT node, suitable for + * verification at run-time. The information added depends on the + * algorithm being used. I just copypasted this from rsa.h. + * + * @info: Specifies key and FIT information + * @keydest: Destination FDT blob for public key data + * @return: 0, on success, -ENOSPC if the keydest FDT blob ran out of space, + * other -ve value on error + */ +int ecdsa_add_verify_data(struct image_sign_info *info, void *keydest); +#else +static inline +int ecdsa_sign(struct image_sign_info *info, const struct image_region region[], + int region_count, uint8_t **sigp, uint *sig_len) +{ + return -ENXIO; +} + +static inline +int ecdsa_add_verify_data(struct image_sign_info *info, void *keydest) +{ + return -ENXIO; +} +#endif + +#if IMAGE_ENABLE_VERIFY_ECDSA +/** + * verify() - Verify a signature against some data + * + * @info: Specifies key and FIT information + * @data: Pointer to the input data + * @data_len: Data length + * @sig: Signature + * @sig_len: Number of bytes in signature + * @return 0 if verified, -ve on error + */ +int ecdsa_verify(struct image_sign_info *info, + const struct image_region region[], int region_count, + uint8_t *sig, uint sig_len); +#else +static inline +int ecdsa_verify(struct image_sign_info *info, + const struct image_region region[], int region_count, + uint8_t *sig, uint sig_len) +{ + return -ENXIO; +} +#endif +/** @} */ + +#define ECDSA256_BYTES (256 / 8) + +#endif diff --git a/lib/ecdsa/ecdsa-libcrypto.c b/lib/ecdsa/ecdsa-libcrypto.c new file mode 100644 index 0000000000..322880963f --- /dev/null +++ b/lib/ecdsa/ecdsa-libcrypto.c @@ -0,0 +1,306 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * ECDSA image signing implementation using libcrypto backend + * + * The signature is a binary representation of the (R, S) points, padded to the + * key size. The signature will be (2 * key_size_bits) / 8 bytes. + * + * Deviations from behavior of RSA equivalent: + * - Verification uses private key. This is not technically required, but a + * limitation on how clumsy the openssl API is to use. + * - Handling of keys and key paths: + * - The '-K' key directory option must contain path to the key file, + * instead of the key directory. + * - No assumptions are made about the file extension of the key + * - The 'key-name-hint' property is only used for naming devicetree nodes, + * but is not used for looking up keys on the filesystem. + * + * Copyright (c) 2020,2021, Alexandru Gagniuc + */ + +#include +#include +#include +#include +#include + +/* Image signing context for openssl-libcrypto */ +struct signer { + EVP_PKEY *evp_key; /* Pointer to EVP_PKEY object */ + EC_KEY *ecdsa_key; /* Pointer to EC_KEY object */ + void *hash; /* Pointer to hash used for verification */ + void *signature; /* Pointer to output signature. Do not free()!*/ +}; + +static int alloc_ctx(struct signer *ctx, const struct image_sign_info *info) +{ + memset(ctx, 0, sizeof(*ctx)); + + if (!OPENSSL_init_ssl(0, NULL)) { + fprintf(stderr, "Failure to init SSL library\n"); + return -1; + } + + ctx->hash = malloc(info->checksum->checksum_len); + ctx->signature = malloc(info->crypto->key_len * 2); + + if (!ctx->hash || !ctx->signature) + return -ENOMEM; + + return 0; +} + +static void free_ctx(struct signer *ctx) +{ + if (ctx->ecdsa_key) + EC_KEY_free(ctx->ecdsa_key); + + if (ctx->evp_key) + EVP_PKEY_free(ctx->evp_key); + + if (ctx->hash) + free(ctx->hash); +} + +/* + * Convert an ECDSA signature to raw format + * + * openssl DER-encodes 'binary' signatures. We want the signature in a raw + * (R, S) point pair. So we have to dance a bit. + */ +static void ecdsa_sig_encode_raw(void *buf, const ECDSA_SIG *sig, size_t order) +{ + int point_bytes = order; + const BIGNUM *r, *s; + uintptr_t s_buf; + + ECDSA_SIG_get0(sig, &r, &s); + s_buf = (uintptr_t)buf + point_bytes; + BN_bn2binpad(r, buf, point_bytes); + BN_bn2binpad(s, (void *)s_buf, point_bytes); +} + +/* Get a signature from a raw encoding */ +static ECDSA_SIG *ecdsa_sig_from_raw(void *buf, size_t order) +{ + int point_bytes = order; + uintptr_t s_buf; + ECDSA_SIG *sig; + BIGNUM *r, *s; + + sig = ECDSA_SIG_new(); + if (!sig) + return NULL; + + s_buf = (uintptr_t)buf + point_bytes; + r = BN_bin2bn(buf, point_bytes, NULL); + s = BN_bin2bn((void *)s_buf, point_bytes, NULL); + ECDSA_SIG_set0(sig, r, s); + + return sig; +} + +/* ECDSA key size in bytes */ +static size_t ecdsa_key_size_bytes(const EC_KEY *key) +{ + const EC_GROUP *group; + + group = EC_KEY_get0_group(key); + return EC_GROUP_order_bits(group) / 8; +} + +static int read_key(struct signer *ctx, const char *key_name) +{ + FILE *f = fopen(key_name, "r"); + + if (!f) { + fprintf(stderr, "Can not get key file '%s'\n", key_name); + return -ENOENT; + } + + ctx->evp_key = PEM_read_PrivateKey(f, NULL, NULL, NULL); + fclose(f); + if (!ctx->evp_key) { + fprintf(stderr, "Can not read key from '%s'\n", key_name); + return -EIO; + } + + if (EVP_PKEY_id(ctx->evp_key) != EVP_PKEY_EC) { + fprintf(stderr, "'%s' is not an ECDSA key\n", key_name); + return -EINVAL; + } + + ctx->ecdsa_key = EVP_PKEY_get1_EC_KEY(ctx->evp_key); + if (!ctx->ecdsa_key) + fprintf(stderr, "Can not extract ECDSA key\n"); + + return (ctx->ecdsa_key) ? 0 : -EINVAL; +} + +/* Prepare a 'signer' context that's ready to sign and verify. */ +static int prepare_ctx(struct signer *ctx, const struct image_sign_info *info) +{ + const char *kname = info->keydir; + int key_len_bytes, ret; + + ret = alloc_ctx(ctx, info); + if (ret) + return ret; + + ret = read_key(ctx, kname); + if (ret) + return ret; + + key_len_bytes = ecdsa_key_size_bytes(ctx->ecdsa_key); + if (key_len_bytes != info->crypto->key_len) { + fprintf(stderr, "Expected a %u-bit key, got %u-bit key\n", + info->crypto->key_len * 8, key_len_bytes * 8); + return -EINVAL; + } + + return 0; +} + +static int do_sign(struct signer *ctx, struct image_sign_info *info, + const struct image_region region[], int region_count) +{ + const struct checksum_algo *algo = info->checksum; + ECDSA_SIG *sig; + + algo->calculate(algo->name, region, region_count, ctx->hash); + sig = ECDSA_do_sign(ctx->hash, algo->checksum_len, ctx->ecdsa_key); + + ecdsa_sig_encode_raw(ctx->signature, sig, info->crypto->key_len); + + return 0; +} + +static int ecdsa_check_signature(struct signer *ctx, struct image_sign_info *info) +{ + ECDSA_SIG *sig; + int okay; + + sig = ecdsa_sig_from_raw(ctx->signature, info->crypto->key_len); + if (!sig) + return -ENOMEM; + + okay = ECDSA_do_verify(ctx->hash, info->checksum->checksum_len, + sig, ctx->ecdsa_key); + if (!okay) + fprintf(stderr, "WARNING: Signature is fake news!\n"); + + ECDSA_SIG_free(sig); + return !okay; +} + +static int do_verify(struct signer *ctx, struct image_sign_info *info, + const struct image_region region[], int region_count, + uint8_t *raw_sig, uint sig_len) +{ + const struct checksum_algo *algo = info->checksum; + + if (sig_len != info->crypto->key_len * 2) { + fprintf(stderr, "Signature has wrong length\n"); + return -EINVAL; + } + + memcpy(ctx->signature, raw_sig, sig_len); + algo->calculate(algo->name, region, region_count, ctx->hash); + + return ecdsa_check_signature(ctx, info); +} + +int ecdsa_sign(struct image_sign_info *info, const struct image_region region[], + int region_count, uint8_t **sigp, uint *sig_len) +{ + struct signer ctx; + int ret; + + ret = prepare_ctx(&ctx, info); + if (ret >= 0) { + do_sign(&ctx, info, region, region_count); + *sigp = ctx.signature; + *sig_len = info->crypto->key_len * 2; + + ret = ecdsa_check_signature(&ctx, info); + } + + free_ctx(&ctx); + return ret; +} + +int ecdsa_verify(struct image_sign_info *info, + const struct image_region region[], int region_count, + uint8_t *sig, uint sig_len) +{ + struct signer ctx; + int ret; + + ret = prepare_ctx(&ctx, info); + if (ret >= 0) + ret = do_verify(&ctx, info, region, region_count, sig, sig_len); + + free_ctx(&ctx); + return ret; +} + +static int do_add(struct signer *ctx, void *fdt, const char *key_node_name) +{ + int signature_node, key_node, ret, key_bits; + const char *curve_name; + const EC_GROUP *group; + const EC_POINT *point; + BIGNUM *x, *y; + + signature_node = fdt_subnode_offset(fdt, 0, FIT_SIG_NODENAME); + if (signature_node < 0) { + fprintf(stderr, "Could not find 'signature node: %s\n", + fdt_strerror(signature_node)); + return signature_node; + } + + key_node = fdt_add_subnode(fdt, signature_node, key_node_name); + if (key_node < 0) { + fprintf(stderr, "Could not create '%s' node: %s\n", + key_node_name, fdt_strerror(key_node)); + return key_node; + } + + group = EC_KEY_get0_group(ctx->ecdsa_key); + key_bits = EC_GROUP_order_bits(group); + curve_name = OBJ_nid2sn(EC_GROUP_get_curve_name(group)); + /* Let 'x' and 'y' memory leak by not BN_free()'ing them. */ + x = BN_new(); + y = BN_new(); + point = EC_KEY_get0_public_key(ctx->ecdsa_key); + EC_POINT_get_affine_coordinates(group, point, x, y, NULL); + + ret = fdt_setprop_string(fdt, key_node, "ecdsa,curve", curve_name); + if (ret < 0) + return ret; + + ret = fdt_add_bignum(fdt, key_node, "ecdsa,x-point", x, key_bits); + if (ret < 0) + return ret; + + ret = fdt_add_bignum(fdt, key_node, "ecdsa,y-point", y, key_bits); + if (ret < 0) + return ret; + + return 0; +} + +int ecdsa_add_verify_data(struct image_sign_info *info, void *fdt) +{ + const char *fdt_key_name; + struct signer ctx; + int ret; + + fdt_key_name = info->keyname ? info->keyname : "default-key"; + ret = prepare_ctx(&ctx, info); + if (ret >= 0) + do_add(&ctx, fdt, fdt_key_name); + + free_ctx(&ctx); + return ret; +} diff --git a/tools/Makefile b/tools/Makefile index af7698fd01..a4f7b7e80c 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -70,6 +70,8 @@ RSA_OBJS-$(CONFIG_FIT_SIGNATURE) := $(addprefix lib/rsa/, \ rsa-sign.o rsa-verify.o \ rsa-mod-exp.o) +ECDSA_OBJS-$(CONFIG_FIT_SIGNATURE) := $(addprefix lib/ecdsa/, ecdsa-libcrypto.o) + AES_OBJS-$(CONFIG_FIT_CIPHER) := $(addprefix lib/aes/, \ aes-encrypt.o aes-decrypt.o) @@ -119,6 +121,7 @@ dumpimage-mkimage-objs := aisimage.o \ gpimage.o \ gpimage-common.o \ mtk_image.o \ + $(ECDSA_OBJS-y) \ $(RSA_OBJS-y) \ $(AES_OBJS-y) From patchwork Fri Jan 8 19:17:35 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Alex G." X-Patchwork-Id: 1423946 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=r/yNYtz0; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4DCCZ72Tpbz9sWS for ; Sat, 9 Jan 2021 06:18:39 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 81E5E82999; Fri, 8 Jan 2021 20:17:58 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.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=gmail.com header.i=@gmail.com header.b="r/yNYtz0"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 0BB8682989; Fri, 8 Jan 2021 20:17:53 +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=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-oi1-x232.google.com (mail-oi1-x232.google.com [IPv6:2607:f8b0:4864:20::232]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 673A682977 for ; Fri, 8 Jan 2021 20:17:48 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=mr.nuke.me@gmail.com Received: by mail-oi1-x232.google.com with SMTP id l200so12496345oig.9 for ; Fri, 08 Jan 2021 11:17:48 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=0cIrclvqfMGJ60GhoWWA+GJSfTZG4dwuJGELTpj4fwY=; b=r/yNYtz0lUVxRI1oFDdIbtbGvvh/MJ6aKbsFHkCV1m8obtW2haryXi6SHa8+ympjAg mAELGjfAn2M79K5wmnFN/pXw8QQQrKyb++XN/mq2dXimZOQssN9fLDK1FhRlYYxckY3W RV9vgxP55OnveERHVHFnyWDp4R/fOq4fIy6rtn944s8rfP3wXsnSrlSUv5qkPnQ0wnvf zJ3mZoXByp38jDpkb6YoGnZBblDNijHq4Px8KQaJeP5056teSwNm47uKr3xWL+QHl3g6 0Dz0D5O36Ne3pLy1UJEw9w6xE3geiLuEox0n0rN5vGxG6DOEy1mjDwbRYbngAnnRZ2f8 fIxA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=0cIrclvqfMGJ60GhoWWA+GJSfTZG4dwuJGELTpj4fwY=; b=mtlelq3CZl+pPVZQdVaBhDf8t+VLVzfYnGeIxB6txzALiN47QafcdwJv2B5QBej421 Q8BPCUUdVjAPvBz+uF9QKe23ACG26Y6gZUy1VqHhaW/jQq33LL1Nqxyv0q+Ryf9ONaPk rALpEGrJD+/ZvTzglbNSUMBL3GCoknzuuDccJvD576x1Mn9kyTusi0LO1CxIOrKX7Q1o W+TDEqC7wg9B958z5K7JGgOD6WtXJiG/jjX2cEWQIzmaKWfCPtkOG+8ijshfW07JhgQi kPHjFWsTOtcdt91PzOwMHQGDAAgKWWJRoQj78JwuxB2VbO8M2zhwMVhujgn/yAL+8TPP NQYw== X-Gm-Message-State: AOAM5331R8gd6vb8rrRNLjNjbEiSxRsCaeRbfleQGYvqlXT7rk4xxrpJ IK04QQyVchfMx9nRk4DDXLSPZftDR4cevr61 X-Google-Smtp-Source: ABdhPJxZhR48JwzDVBPHEoL8IRRROaEjKHOPl02T4BJAZzWrRKFN9HW5AVFPqcKWD6+IN5/7iKUMhw== X-Received: by 2002:aca:bac3:: with SMTP id k186mr3161713oif.93.1610133467092; Fri, 08 Jan 2021 11:17:47 -0800 (PST) Received: from nuclearis2-1.lan (c-98-195-139-126.hsd1.tx.comcast.net. [98.195.139.126]) by smtp.gmail.com with ESMTPSA id g200sm2131617oib.19.2021.01.08.11.17.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 08 Jan 2021 11:17:46 -0800 (PST) From: Alexandru Gagniuc To: u-boot@lists.denx.de, sjg@chromium.org Cc: Alexandru Gagniuc , trini@konsulko.com, marex@denx.de Subject: [PATCH v4 4/6] doc: signature.txt: Document devicetree format for ECDSA keys Date: Fri, 8 Jan 2021 13:17:35 -0600 Message-Id: <20210108191737.615022-5-mr.nuke.me@gmail.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20210108191737.615022-1-mr.nuke.me@gmail.com> References: <20210108191737.615022-1-mr.nuke.me@gmail.com> MIME-Version: 1.0 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 Signed-off-by: Alexandru Gagniuc --- doc/uImage.FIT/signature.txt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/doc/uImage.FIT/signature.txt b/doc/uImage.FIT/signature.txt index a3455889ed..0139295d33 100644 --- a/doc/uImage.FIT/signature.txt +++ b/doc/uImage.FIT/signature.txt @@ -142,7 +142,7 @@ public key in U-Boot's control FDT (using CONFIG_OF_CONTROL). Public keys should be stored as sub-nodes in a /signature node. Required properties are: -- algo: Algorithm name (e.g. "sha1,rsa2048") +- algo: Algorithm name (e.g. "sha1,rsa2048" or "sha256,ecdsa256") Optional properties are: @@ -167,6 +167,11 @@ For RSA the following are mandatory: - rsa,r-squared: (2^num-bits)^2 as a big-endian multi-word integer - rsa,n0-inverse: -1 / modulus[0] mod 2^32 +For ECDSA the following are mandatory: +- ecdsa,curve: Name of ECDSA curve (e.g. "prime256v1") +- ecdsa,x-point: Public key X coordinate as a big-endian multi-word integer +- ecdsa,y-point: Public key Y coordinate as a big-endian multi-word integer + These parameters can be added to a binary device tree using parameter -K of the mkimage command:: From patchwork Fri Jan 8 19:17:36 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Alex G." X-Patchwork-Id: 1423945 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=o/QnXNvx; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4DCCYw53MGz9sWK for ; Sat, 9 Jan 2021 06:18:28 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 9733B82993; Fri, 8 Jan 2021 20:17:56 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.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=gmail.com header.i=@gmail.com header.b="o/QnXNvx"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id DD29D82990; Fri, 8 Jan 2021 20:17:52 +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=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-ot1-x32f.google.com (mail-ot1-x32f.google.com [IPv6:2607:f8b0:4864:20::32f]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id B34858297E for ; Fri, 8 Jan 2021 20:17:49 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=mr.nuke.me@gmail.com Received: by mail-ot1-x32f.google.com with SMTP id b24so10769836otj.0 for ; Fri, 08 Jan 2021 11:17:49 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=lB4W5X22Wt4/XqjqysB4P11Bnau9YMf6coAv92vuPec=; b=o/QnXNvxZAHAw1bKtIbSlD/fvVQnpfG/iaFidd8TwhelpaZj/QqBvfMHP8wLM34Sqf Z7ZXxtO/AihU5oi5szSnwHm5SuCapbPh/fQqvf1Pk3Pqp/oNkcvBL7bV6KtvgKwxEa+g h8A6JOB6BeJ9K3ijAcVP/FXGWcpQqsjf3cPb2D1NyKQvdPG7sPJHP1x0GEkd8+Jf2s7m 4LxfVymBmzK9oZ8qFcEUE7LMNh3CWoTKzk6jCX8s8XbmRq2NMMBoigwmigH3WHNSZznD /EMuYmmKUbv3Pa9UPQfUNoL7wDGjACUXbWVXK5KbKuik1hzjIZYG5cbXHUUgteJ/Zr54 Ajug== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=lB4W5X22Wt4/XqjqysB4P11Bnau9YMf6coAv92vuPec=; b=fqbtBkobuneMhpjoSVRkqULzBDXLQDp7WYTunTIOBjivkCH2Rb5xk8rBm07I/+/t1f Ndm88I2ebQgj1tI/jxzgYRRaDWYi/ba9zZ78Mz7RCqQWc+jaicK75WwVni1A+ueGtZcP 6Ok7Nt0jkQzyb16KPzKiw3DOZGWuebPswXhpdRi19Mb8jT7/NLUOuzXz18tPlNCm0VlK zsjz7rfdly0KdSjI7IbrXtfbkOrxgjJXn8e5jaZaX18MC49ir/CQmLaTQMBk9ug0giaD f3xcu7dRHiYhxFwWvmLq/Ltj6e1E6LHppAYWcX3JW/woz4QGBSJs3CFMNTY7VVPYCrO/ Ew+A== X-Gm-Message-State: AOAM530VWdyUBIdW0AYs8w4L3Z56TdJln/Bz/pO3cjbPe0lcTuLoV8Xe zlsgjB9wlFY8mOtnGYNUk5PEXOaTmfOq/UpW X-Google-Smtp-Source: ABdhPJwV/SnVtm59B6+d7AXLhtqczLCRRpWr9g2h+JCKkRULc/5+92C+u1PkwltI4sm6be8Jc1P36Q== X-Received: by 2002:a9d:46b:: with SMTP id 98mr3723868otc.200.1610133467984; Fri, 08 Jan 2021 11:17:47 -0800 (PST) Received: from nuclearis2-1.lan (c-98-195-139-126.hsd1.tx.comcast.net. [98.195.139.126]) by smtp.gmail.com with ESMTPSA id g200sm2131617oib.19.2021.01.08.11.17.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 08 Jan 2021 11:17:47 -0800 (PST) From: Alexandru Gagniuc To: u-boot@lists.denx.de, sjg@chromium.org Cc: Alexandru Gagniuc , trini@konsulko.com, marex@denx.de Subject: [PATCH v4 5/6] test/py: Add pycryptodomex to list of required pakages Date: Fri, 8 Jan 2021 13:17:36 -0600 Message-Id: <20210108191737.615022-6-mr.nuke.me@gmail.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20210108191737.615022-1-mr.nuke.me@gmail.com> References: <20210108191737.615022-1-mr.nuke.me@gmail.com> MIME-Version: 1.0 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 We wish to use pycryptodomex to verify code paths involving ECDSA signatures. Add it to requirements.txt so that they get picked up automatically .gitlab and .azure tasks Signed-off-by: Alexandru Gagniuc --- test/py/requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/test/py/requirements.txt b/test/py/requirements.txt index cf251186f4..5a25a9d5d5 100644 --- a/test/py/requirements.txt +++ b/test/py/requirements.txt @@ -10,6 +10,7 @@ packaging==19.2 pbr==5.4.3 pluggy==0.13.0 py==1.8.0 +pycryptodomex==3.9.8 pyparsing==2.4.2 pytest==5.2.1 python-mimeparse==1.6.0 From patchwork Fri Jan 8 19:17:37 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Alex G." X-Patchwork-Id: 1423948 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=H28uByyJ; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4DCCZV6PFCz9sWK for ; Sat, 9 Jan 2021 06:18:58 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 751DF8299F; Fri, 8 Jan 2021 20:18:04 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.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=gmail.com header.i=@gmail.com header.b="H28uByyJ"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 10CCA8298B; Fri, 8 Jan 2021 20:17:55 +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=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-oi1-x22b.google.com (mail-oi1-x22b.google.com [IPv6:2607:f8b0:4864:20::22b]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 6037982981 for ; Fri, 8 Jan 2021 20:17:50 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=mr.nuke.me@gmail.com Received: by mail-oi1-x22b.google.com with SMTP id d189so12470388oig.11 for ; Fri, 08 Jan 2021 11:17:50 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=rO7nSvBtdpPw3s9RfM2t/Jce98gXrHVS7NfquakStt8=; b=H28uByyJt6z/eCjLeCw5N3I5RAR7dygfZkUciib7zbwGCNDMtqmKXcgaGvXhorWF4T EN35Ah7NYOF6HFeqTQORnx1ZZeGdp7nV/5xdEgp0kI0NdS9ngLuGhqa29ChMq+eOf1y2 kcnk3QUNyDx8iIynvOdEFgvd3KDdZr10f4+KvKTk/GOs6W6ng9TXc90+78XWF9vwfvao NLO9UO0XA1BHmHAgwWWWN3DU0GRbKmfv+H8mcTNAr3XQErWkxwr4lVS6XnWHdiTIDNnl up4EgDbs11IQ371i5LtrDQC/FT5QKMEFoQis6/BjA16w0LNd1100Y1Ho3Cyiy7nggu+y DdOw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=rO7nSvBtdpPw3s9RfM2t/Jce98gXrHVS7NfquakStt8=; b=AA6Fj7/Lfu+KeBYQu27sANwdtGtQudxmOwEM6gfNtbuCTO5b434qkqFiWWghy9L2ip zZNcHypk+FKiw8m/3N3glWmeaXaEcATtjLbsjFJl+BmUwYpc4BnHvascPQZ7CBVftSNy 0wV8By7bLo04jB7cXwHH+zPinQYlFMbN0n84mX1ONcFbqaKngD8+WYen17psYDuP+Q28 UppPYyfp0GPKwE/YDZ139WgulsI6ejzDjEr3puj/XqS5vQnclY6M/li5WeEVSCw9SI1s LKRMFHhf/D5hTYaInZxBP0n8c58pDY+x45Px2txwbQK6vY0DGSv1nThxdkw6xn1vJbWG k09Q== X-Gm-Message-State: AOAM532caCQ6XlgaikINIluSSndKU0wrbdqSbfKobFqVL/PFiqgv2qUN baPc0sINqY2FFN6yh2S2+5GKjwsOpMyAkM08 X-Google-Smtp-Source: ABdhPJyXlSEotX0zpKD6FPISf8SoQZG2tVvgyWh0bzyYnNWUnHNJ2Ip/iBwLT2Vlko2KivS+V1s3Uw== X-Received: by 2002:aca:fd0b:: with SMTP id b11mr3340278oii.80.1610133468949; Fri, 08 Jan 2021 11:17:48 -0800 (PST) Received: from nuclearis2-1.lan (c-98-195-139-126.hsd1.tx.comcast.net. [98.195.139.126]) by smtp.gmail.com with ESMTPSA id g200sm2131617oib.19.2021.01.08.11.17.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 08 Jan 2021 11:17:48 -0800 (PST) From: Alexandru Gagniuc To: u-boot@lists.denx.de, sjg@chromium.org Cc: Alexandru Gagniuc , trini@konsulko.com, marex@denx.de Subject: [PATCH v4 6/6] test/py: ecdsa: Add test for mkimage ECDSA signing Date: Fri, 8 Jan 2021 13:17:37 -0600 Message-Id: <20210108191737.615022-7-mr.nuke.me@gmail.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20210108191737.615022-1-mr.nuke.me@gmail.com> References: <20210108191737.615022-1-mr.nuke.me@gmail.com> MIME-Version: 1.0 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 a test to make sure that the ECDSA signatures generated by mkimage can be verified successfully. pyCryptodomex was chosen as the crypto library because it integrates much better with python code. Using openssl would have been unnecessarily painful. Signed-off-by: Alexandru Gagniuc --- test/py/tests/test_fit_ecdsa.py | 111 ++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 test/py/tests/test_fit_ecdsa.py diff --git a/test/py/tests/test_fit_ecdsa.py b/test/py/tests/test_fit_ecdsa.py new file mode 100644 index 0000000000..6cadb0cbb5 --- /dev/null +++ b/test/py/tests/test_fit_ecdsa.py @@ -0,0 +1,111 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (c) 2020,2021 Alexandru Gagniuc + +""" +Test ECDSA signing of FIT images + +This test uses mkimage to sign an existing FIT image with an ECDSA key. The +signature is then extracted, and verified against pyCryptodome. +This test doesn't run the sandbox. It only checks the host tool 'mkimage' +""" + +import pytest +import u_boot_utils as util +from Cryptodome.Hash import SHA256 +from Cryptodome.PublicKey import ECC +from Cryptodome.Signature import DSS + +class SignableFitImage(object): + """ Helper to manipulate a FIT image on disk """ + def __init__(self, cons, file_name): + self.fit = file_name + self.cons = cons + self.signable_nodes = set() + + def __fdt_list(self, path): + return util.run_and_log(self.cons, f'fdtget -l {self.fit} {path}') + + def __fdt_set(self, node, **prop_value): + for prop, value in prop_value.items(): + util.run_and_log(self.cons, f'fdtput -ts {self.fit} {node} {prop} {value}') + + def __fdt_get_binary(self, node, prop): + numbers = util.run_and_log(self.cons, f'fdtget -tbi {self.fit} {node} {prop}') + + bignum = bytearray() + for little_num in numbers.split(): + bignum.append(int(little_num)) + + return bignum + + def find_signable_image_nodes(self): + for node in self.__fdt_list('/images').split(): + image = f'/images/{node}' + if 'signature' in self.__fdt_list(image): + self.signable_nodes.add(image) + + return self.signable_nodes + + def change_signature_algo_to_ecdsa(self): + for image in self.signable_nodes: + self.__fdt_set(f'{image}/signature', algo='sha256,ecdsa256') + + def sign(self, mkimage, key_file): + util.run_and_log(self.cons, [mkimage, '-F', self.fit, f'-k{key_file}']) + + def check_signatures(self, key): + for image in self.signable_nodes: + raw_sig = self.__fdt_get_binary(f'{image}/signature', 'value') + raw_bin = self.__fdt_get_binary(image, 'data') + + sha = SHA256.new(raw_bin) + verifier = DSS.new(key, 'fips-186-3') + verifier.verify(sha, bytes(raw_sig)) + + +@pytest.mark.buildconfigspec('fit_signature') +@pytest.mark.requiredtool('dtc') +@pytest.mark.requiredtool('fdtget') +@pytest.mark.requiredtool('fdtput') +def test_fit_ecdsa(u_boot_console): + """ Test that signatures generated by mkimage are legible. """ + def generate_ecdsa_key(): + return ECC.generate(curve='prime256v1') + + def assemble_fit_image(dest_fit, its, destdir): + dtc_args = f'-I dts -O dtb -i {destdir}' + util.run_and_log(cons, [mkimage, '-D', dtc_args, '-f', its, dest_fit]) + + def dtc(dts): + dtb = dts.replace('.dts', '.dtb') + util.run_and_log(cons, f'dtc {datadir}/{dts} -O dtb -o {tempdir}/{dtb}') + + cons = u_boot_console + mkimage = cons.config.build_dir + '/tools/mkimage' + datadir = cons.config.source_dir + '/test/py/tests/vboot/' + tempdir = cons.config.result_dir + key_file = f'{tempdir}/ecdsa-test-key.pem' + fit_file = f'{tempdir}/test.fit' + dtc('sandbox-kernel.dts') + + key = generate_ecdsa_key() + + # Create a fake kernel image -- zeroes will do just fine + with open(f'{tempdir}/test-kernel.bin', 'w') as fd: + fd.write(500 * chr(0)) + + # invokations of mkimage expect to read the key from disk + with open(key_file, 'w') as f: + f.write(key.export_key(format='PEM')) + + assemble_fit_image(fit_file, f'{datadir}/sign-images-sha256.its', tempdir) + + fit = SignableFitImage(cons, fit_file) + nodes = fit.find_signable_image_nodes() + if len(nodes) == 0: + raise ValueError('FIT image has no "/image" nodes with "signature"') + + fit.change_signature_algo_to_ecdsa() + fit.sign(mkimage, key_file) + fit.check_signatures(key)