From patchwork Wed Dec 30 21:00:23 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandru Gagniuc X-Patchwork-Id: 1421451 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=O9r19NDd; 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 4D5kGc0HJhz9sRR for ; Thu, 31 Dec 2020 08:01:11 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id DAD1482627; Wed, 30 Dec 2020 22:00: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="O9r19NDd"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 775DA82615; Wed, 30 Dec 2020 22:00:48 +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, T_SPF_HELO_TEMPERROR autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-oi1-x234.google.com (mail-oi1-x234.google.com [IPv6:2607:f8b0:4864:20::234]) (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 531E6825BF for ; Wed, 30 Dec 2020 22:00:38 +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-x234.google.com with SMTP id p5so19940913oif.7 for ; Wed, 30 Dec 2020 13:00:38 -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=z6sdSTakhTVhrMBvulGF9yfgWWQga8jXEjfwLY7mDb0=; b=O9r19NDd2SGLOoxmztg3+vQZJNKju032cZjQRfqMnUzRosUksOIkm1oufeOnI5JfxO GtRkzA3pePGR+yhm2/hpqwrb6h6nGeMbRa+PP4psRWdTfIUjlOnAamjH4J4RpSH6BqxN hWWGtlv8iRDxxwtlYbTkWQPP9bNl9eXCI+wfo+cVPzHbf5yVLaswM9krQ9gJgludk2IJ Id7lmjHsif3JsCLjWxPoZEQl7gJDNDgeSyUhAJHkQ4oJI6JX7b9HM2kFpieU3z2EOhxH xG9A9bZXK7uDApFgxsNtpsSzjr41rTAjY7YqQhlED4IoBmH9h/2nOF05i2hjPTchJYVq 7cmg== 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=z6sdSTakhTVhrMBvulGF9yfgWWQga8jXEjfwLY7mDb0=; b=JBBxJkApCv4ejTWzfBsBA6tJCYHeYbPo74EQFTYrIQg7dp8KtrmtQJANauJbHWT6Xf TfqVHs9E6Kewmr0K99xm5iMIQetrZivz9Cp486FTYF/rwwKOhaqVdP0Epmui3RhlsxOn dKwd69UMMbSf4isgy2UDcVFA7dcyLJS/4yllYP+7Rrfbx4RJmyscQmnb5aCnAAwjqko8 AtqUX8iW5lICaU0PiyoyoVKXLnaeo9+aLKIccXWuAQsEx5FRJBcKEgd/WYJyNK5YQUuO 1H9aFsP+ySDxH1XrOyy/BxGcDLpnxHUi9M0QfUnSZmurzjqVLkqQOPg7NRWjm1HYGznf mO/A== X-Gm-Message-State: AOAM531myXYCF4FAHVsTtXNTQVrHnFh3mj5qMouKvRM5wyjZgdltS030 2qhPzOvww5snByN5CL3F2Y2GMl/gr/cRX+yZ X-Google-Smtp-Source: ABdhPJzYtSYhUVqYdxrE1QwYbnF8g3Fl22cpe0TsuYI2qhna91TMdwJdPZOQlbN3jOmhrUd+JT/8rA== X-Received: by 2002:a54:4817:: with SMTP id j23mr6531682oij.158.1609362036918; Wed, 30 Dec 2020 13:00:36 -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 n16sm11414787oop.9.2020.12.30.13.00.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 30 Dec 2020 13:00:36 -0800 (PST) From: Alexandru Gagniuc To: u-boot@lists.denx.de, sjg@chromium.org Cc: Alexandru Gagniuc , trini@konsulko.com, marex@denx.de, Philippe Reynes , Thirupathaiah Annapureddy , AKASHI Takahiro , Masahiro Yamada , Reuben Dowle , Lokesh Vutla , Sam Protsenko , Naoki Hayama , Atish Patra , Bin Meng , Heinrich Schuchardt , Pragnesh Patel , Andrii Anisov , Christian Gmeiner , Sean Anderson , Anatolij Gustschin , Heiko Stuebner , Philipp Tomsich , Stefan Roese , Trevor Woerner Subject: [PATCH RFC v2 1/5] lib: Rename rsa-checksum.c to hash-checksum.c Date: Wed, 30 Dec 2020 15:00:23 -0600 Message-Id: <20201230210028.4065824-2-mr.nuke.me@gmail.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201230210028.4065824-1-mr.nuke.me@gmail.com> References: <20201230210028.4065824-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 Reviewed-by: Simon Glass --- 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 00bc03bebe..d1a0b3d9f6 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 Wed Dec 30 21:00:24 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandru Gagniuc X-Patchwork-Id: 1421450 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=ns9pjapM; 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 4D5kGP0y5xz9sT5 for ; Thu, 31 Dec 2020 08:01:00 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id E385B82603; Wed, 30 Dec 2020 22:00:55 +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="ns9pjapM"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 26BC28260A; Wed, 30 Dec 2020 22:00:47 +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 A6756825E3 for ; Wed, 30 Dec 2020 22:00:41 +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 x13so19975569oic.5 for ; Wed, 30 Dec 2020 13:00:41 -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=2nZoy3lK6hcMzwgknsojZ/YjyBNdqbjSNvb9P23dj0k=; b=ns9pjapMOuEuYk8MTDBgYEFcqN9de6Am2Bemt4cn04JGrUsC6yQ1ZdINxtxGn6Wvxj K0bW8qYgpz5vENSpeaB/EG2mTu7yiX+fBQ5jcnKWP6J/MO/AXlrztAiRml8jK9cuSbtI Yl1odrON41eDNg0V1V5F4ny0PeopWW/IGXrZGEV7MxwHs/nltR01HANE927bl2HEZI6w AQmR4G1duGWk1CfGbV/9YcYvmo2ujWuhpSXNww/HOq/EqdSNRpw57h9EMAMXt01WBflg aepGv4fbXBbI+xrEOm2ECoLB5TnnRUcke01ZLcxDXx9YNTKl1NgpsreG975ooY0bU/JV nvBw== 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=2nZoy3lK6hcMzwgknsojZ/YjyBNdqbjSNvb9P23dj0k=; b=Rgf63MNPhW/5KLCDm+eZnuh2rl6csPCz94ihY22Sk5FUgLMRElWUNY1xkWhu0q3zdF xrJyXJ7HdGuJvkx3drJVCNrNStXmstgb2ivJTWsrQsGoxqS5s3tduOB75MOsdXVAHrMl pAitsniDYZFm4j068RVwTae7I8s1diD0AWn8BcfNMKJz3AhGoBse+6pjEpoBn7eaOqPX 12VU3mwCwTk3zqwJeNE4vT+hLy/B/Vt8/ufPwwIO6OnYtryZKOmh09mMdXIqOcHO4Ay5 DfxSgSzo8p6ZfdCmhczFBuXm4piryBRjsQr+e0WeSb+7CXmklHhz3IYqUldnzOVOKGwP 3+fQ== X-Gm-Message-State: AOAM532ihQo1fJWTisLtltU1YKkbVaIRrTzIHlkhvjDGa2CRmb5gGu2+ OB7+kVxql+RYiIFjbkXHyxbdrUGPhNNfCTHU X-Google-Smtp-Source: ABdhPJwnIaM6RMf/FS3ECqWaLmDIfAjuGeWX7EPgaEFohaufDwLC5DzlmfrZ0cUCg0XGonTG2Pz2ww== X-Received: by 2002:a54:4583:: with SMTP id z3mr6352210oib.19.1609362040228; Wed, 30 Dec 2020 13:00:40 -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 n16sm11414787oop.9.2020.12.30.13.00.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 30 Dec 2020 13:00:39 -0800 (PST) From: Alexandru Gagniuc To: u-boot@lists.denx.de, sjg@chromium.org Cc: Alexandru Gagniuc , trini@konsulko.com, marex@denx.de, George McCollister , Philippe Reynes , Jonathan Gray , Jan Luebbe , Heinrich Schuchardt , Masahiro Yamada , AKASHI Takahiro , Chris Packham , Stefan Roese , Trevor Woerner Subject: [PATCH RFC v2 2/5] lib/rsa: Make fdt_add_bignum() available outside of RSA code Date: Wed, 30 Dec 2020 15:00:24 -0600 Message-Id: <20201230210028.4065824-3-mr.nuke.me@gmail.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201230210028.4065824-1-mr.nuke.me@gmail.com> References: <20201230210028.4065824-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 Reviewed-by: Simon Glass --- include/u-boot/fdt-libcrypto.h | 15 +++++++ lib/fdt-libcrypto.c | 72 ++++++++++++++++++++++++++++++++++ lib/rsa/rsa-sign.c | 65 +----------------------------- tools/Makefile | 1 + 4 files changed, 89 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..a6873487ed --- /dev/null +++ b/include/u-boot/fdt-libcrypto.h @@ -0,0 +1,15 @@ +/* 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 + +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 Wed Dec 30 21:00:25 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandru Gagniuc X-Patchwork-Id: 1421452 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=JUkkvO1f; 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 4D5kGp6hlVz9sSs for ; Thu, 31 Dec 2020 08:01:22 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id F0B1882603; Wed, 30 Dec 2020 22:01: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="JUkkvO1f"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 155A78261F; Wed, 30 Dec 2020 22:00: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-ot1-x332.google.com (mail-ot1-x332.google.com [IPv6:2607:f8b0:4864:20::332]) (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 650E982603 for ; Wed, 30 Dec 2020 22:00:45 +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-x332.google.com with SMTP id 11so16475007oty.9 for ; Wed, 30 Dec 2020 13:00:45 -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=aHSeBitByb5JOK5aBUQbqReMNyTs5glsf2j49hFq2Bg=; b=JUkkvO1f2/61JehkmGTLyGXyzgeZwbKryKFjDimyZTIdNM+B9mZiKg/tmmONk9npDZ CvwGDac4++BA3Cr0AsFjIluhaZTMHAwl/BjIa9UIfbPnOtZrYuWTahjH5IUwAMa+juRY UM14HnlncZnIqtK3ZnLENSntReNN6jVlS9EORhG9j8j1ZPsKJB9vQlBPOBx+6PxoNLI9 6sVbvSGzsleBddAgBa+YMStRDhEnftZqzlmfDmoso96wnlVXIpVRpRysKTMLBsKSRtYG 1u1GQ7/SfNxuIb4GCUuNO2BQ/oM0coRY6B6xQULt2FtbiGQDp4AJ42b9fJH0JRvZ58ku JUPw== 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=aHSeBitByb5JOK5aBUQbqReMNyTs5glsf2j49hFq2Bg=; b=ByigD8ZgInfDDti/kiu1KcPTYZ5tBL8HHLjTbGjyIs/6ctXOcBwohLyI0xhCo//CPX htRoLRBngB7xVsPf8BENUim4eFbwfHKFm51k6R/9bXUUDf+JPE4EiEVc2xHcwxw29Ug4 qhpkTWeIDxOYyOATjcAPtNbL8KXMZg5gkRogV9GrPZXpLSZb+TosXQGHeUUCO5Od2fKR EF89xOzIPWTnRTFMMXEJ3dFI8nIJN0ntuElviLsNK65tAVjb1oyZVEpvZ9OLUd5U331I MSLjBF6O5seX0k6wNE2lQBB4H7WLEpYnpKftHJPFIEA2uaF4w8qqywAoDnCp2PbX0ZXo 86QQ== X-Gm-Message-State: AOAM531zzcmmGtkBtBfk8uQtXsrIknFjZ96MMFWPsWQl6D6OtBxAdnCl 6HdWmfqekvLKStL9pyF4cRiMR+OAdWtjltyF X-Google-Smtp-Source: ABdhPJxbqyNxag+kv4Fi3FjyKcypkcA0+YpSCbczy7a38oSdOvsUI/ivZtUzQQgHz6CcHE3AM4jSkQ== X-Received: by 2002:a05:6830:1c2d:: with SMTP id f13mr40806382ote.365.1609362043666; Wed, 30 Dec 2020 13:00:43 -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 n16sm11414787oop.9.2020.12.30.13.00.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 30 Dec 2020 13:00:43 -0800 (PST) From: Alexandru Gagniuc To: u-boot@lists.denx.de, sjg@chromium.org Cc: Alexandru Gagniuc , trini@konsulko.com, marex@denx.de, Reuben Dowle , AKASHI Takahiro , Philippe Reynes , Masahiro Yamada , Stefan Roese , Trevor Woerner Subject: [PATCH RFC v2 3/5] lib: Add support for ECDSA image signing Date: Wed, 30 Dec 2020 15:00:25 -0600 Message-Id: <20201230210028.4065824-4-mr.nuke.me@gmail.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201230210028.4065824-1-mr.nuke.me@gmail.com> References: <20201230210028.4065824-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 | 14 +- include/u-boot/ecdsa.h | 27 ++++ lib/ecdsa/ecdsa-libcrypto.c | 300 ++++++++++++++++++++++++++++++++++++ tools/Makefile | 3 + 4 files changed, 342 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..2548b3eb0f 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,17 @@ struct crypto_algo crypto_algos[] = { .sign = rsa_sign, .add_verify_data = rsa_add_verify_data, .verify = rsa_verify, - } - + }, +#if defined(USE_HOSTCC) + /* Currently, only host support exists for ECDSA */ + { + .name = "ecdsa256", + .key_len = ECDSA256_BYTES, + .sign = ecdsa_sign, + .add_verify_data = ecdsa_add_verify_data, + .verify = ecdsa_verify, + }, +#endif }; struct padding_algo padding_algos[] = { diff --git a/include/u-boot/ecdsa.h b/include/u-boot/ecdsa.h new file mode 100644 index 0000000000..a13a7267e1 --- /dev/null +++ b/include/u-boot/ecdsa.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2020, Alexandru Gagniuc . + */ + +#ifndef _ECDSA_H +#define _ECDSA_H + +#include +#include + +/** + * crypto_algo API impementation for ECDSA; + * @see "struct crypto_algo" + * @{ + */ +int ecdsa_sign(struct image_sign_info *info, const struct image_region region[], + int region_count, uint8_t **sigp, uint *sig_len); +int ecdsa_verify(struct image_sign_info *info, + const struct image_region region[], int region_count, + uint8_t *sig, uint sig_len); +int ecdsa_add_verify_data(struct image_sign_info *info, void *keydest); +/** @} */ + +#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..ff491411d0 --- /dev/null +++ b/lib/ecdsa/ecdsa-libcrypto.c @@ -0,0 +1,300 @@ +// 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, Alexandru Gagniuc + */ + +#include +#include +#include +#include +#include + +struct signer { + EVP_PKEY *evp_key; + EC_KEY *ecdsa_key; + void *hash; + void *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 -1; + + 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); +} + +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; +} + +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 -1; + } + + 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 -1; + } + + if (EVP_PKEY_id(ctx->evp_key) != EVP_PKEY_EC) { + fprintf(stderr, "'%s' is not an ECDSA key\n", key_name); + return -1; + } + + 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 : -1; +} + +static int prepare_ctx(struct signer *ctx, const struct image_sign_info *info) +{ + const char *kname = info->keydir; + int key_len_bytes; + + if (alloc_ctx(ctx, info) < 0) + return -1; + + if (read_key(ctx, kname) < 0) + return -1; + + 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 -1; + } + + 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 -1; + + 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 -1; + } + + 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 Wed Dec 30 21:00:26 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandru Gagniuc X-Patchwork-Id: 1421453 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=Pvo2jZAn; 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 4D5kH32l7Qz9sRR for ; Thu, 31 Dec 2020 08:01:35 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 22AA582603; Wed, 30 Dec 2020 22:01:32 +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="Pvo2jZAn"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 3F4568260A; Wed, 30 Dec 2020 22:00: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-oo1-xc2d.google.com (mail-oo1-xc2d.google.com [IPv6:2607:f8b0:4864:20::c2d]) (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 8A69B82604 for ; Wed, 30 Dec 2020 22:00: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-oo1-xc2d.google.com with SMTP id y14so3946321oom.10 for ; Wed, 30 Dec 2020 13:00: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=0cIrclvqfMGJ60GhoWWA+GJSfTZG4dwuJGELTpj4fwY=; b=Pvo2jZAndnB6gInXVkdCcS9oGTweJKzA4JQrzCzLrc0GNNoAFb5Wi8+cg/SRKffgaT SJ+MHucVcjm+0736dYF1MOUe53pnFEn1pSaTc3a9dDZeKT1ekPVsBe1OuE789BFZajz7 tShKBAvDWZxeLw1AUkNbp7K4viD58lwSec0tiPE7X9dASe0BW1y2Y61BNQxiQ2io4yDh VAjh1dlUk7vwHYcA28bH+FffJNCdyFSUSMM8kG5lqgUV4JlfJ+uRKy21nPAJ/OD0lNRn jnJBOemk39jcpmSrzeXuxJBCDkX30SMRnuSJzPs/LANPifGNNJD9UpufTvEub1rxDK0n 7Mhg== 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=fPbNhHDxN8/qzgHdkyOE+MkLUDAzVkRqwOTz6CZvfD2cHiJp6GKxGKB3HGZRa5Losw mSYzYlMuEK1KzjnirbqVDXnDtT5jBl+X3cwzF+YUBRZjj8lp2GyW8YQbwWeMBsD/yh2j Bd5ejTvGxHlyEHaTlwrY6x4MoEFjtpwKYHfPMqG6rC+MxdxLvvSM9lXNu6k6xEhdfzjK qxqsQNPEY0vkizvqwU/EJ8SFye+bpWVsDusLurZ2zDPyM1Uz75u/qrxWD3pSmF52rbdH 96jGyQ2rQWbXLp/IyS0SisSR4mXkV4Lu0j9GOqhhTyKc+usdtrlS5fCBQ/EVlGLTzujo E7BA== X-Gm-Message-State: AOAM530BDpu78xwrX73ZzBrLuFg3q59t0AEMqNI2Yt8FWFGO27CJpphs eTYieUNavf9N1oMZQmWYFczE63vT20SY/UIU X-Google-Smtp-Source: ABdhPJx9OAcGWjxS63zETDA9YogjT1VJl5RWDbaMbFVU5nX7oCnhvyF/bRWCYZ5yNeZSFaNsDiOw0Q== X-Received: by 2002:a4a:e718:: with SMTP id y24mr32241039oou.91.1609362045006; Wed, 30 Dec 2020 13:00: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 n16sm11414787oop.9.2020.12.30.13.00.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 30 Dec 2020 13:00:44 -0800 (PST) From: Alexandru Gagniuc To: u-boot@lists.denx.de, sjg@chromium.org Cc: Alexandru Gagniuc , trini@konsulko.com, marex@denx.de, Jan Luebbe , Thirupathaiah Annapureddy , George McCollister Subject: [PATCH RFC v2 4/5] doc: signature.txt: Document devicetree format for ECDSA keys Date: Wed, 30 Dec 2020 15:00:26 -0600 Message-Id: <20201230210028.4065824-5-mr.nuke.me@gmail.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201230210028.4065824-1-mr.nuke.me@gmail.com> References: <20201230210028.4065824-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 Reviewed-by: Simon Glass --- 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 Wed Dec 30 21:00:27 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandru Gagniuc X-Patchwork-Id: 1421454 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=RmGSQAKa; 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 4D5kHG4FL6z9sRR for ; Thu, 31 Dec 2020 08:01:46 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 3332D8261B; Wed, 30 Dec 2020 22:01:36 +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="RmGSQAKa"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 7E37E82608; Wed, 30 Dec 2020 22:00: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-oo1-xc29.google.com (mail-oo1-xc29.google.com [IPv6:2607:f8b0:4864:20::c29]) (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 DF835824DE for ; Wed, 30 Dec 2020 22:00: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-oo1-xc29.google.com with SMTP id o5so3947874oop.12 for ; Wed, 30 Dec 2020 13:00: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=oR1rsoDfRxgSydEJEY6erEfXhN74tArRQwYyg1RF88Y=; b=RmGSQAKa+Y0FucrEkhHQIDqvPkwMcX03TLt9c+l3GL6GDLTncBcUh5kZ2o7XR1b0AT LuwKoxDCIGi/x8yWqXRl8ga0WY7Cm7GXw2eNX4fxQycD6vyYDMC5+A4TMkrVC132xf3h m9szuax+H1uRKQCnnjA9ZcX4Uj/PS2uqi7Q6Z54NPJjSPDvp9SPasdkyOhOw+VAwiKBH 8/QKjH9y7iI0frjgcuLAHCb9p9UKEJD4RRPhX9VBz7kWG+lp5BfJvR8IdQfEM4/LfgWF VN7VESNK5KSUn8X7Jp0fbaTmwnIqZJmI6J1smoO4SVOLrq+RF/5LbkQMHy8IP/tYf79x m7wQ== 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=oR1rsoDfRxgSydEJEY6erEfXhN74tArRQwYyg1RF88Y=; b=Hq+Fbi4P8YuPz7/2aq9Mddb6PWo6QZI5mi/oKmf6RiGibtqwCj1/TK4Vh7VBB7Th6C 2VYbg3VbKbcvdEGeC0xxwEHTOYmV0wnT92y3TOoQ3cHCjM2JyN4WN1ldT7Qr3F0oMENq pyJgfyzSICgVeqy4TVdD189pq5RTdceqOzFqN+Le7FOOkZFZ3tG96qijr21LP8N0ywl0 k6NxJHuWB7XljyEUG1PWd8KabdrV/wsfabp97nqbF15VUnj7mebjRYayu1b/T5ShFHRy bEGw+0bCOeGOiRsb7biFN3gOgU8CSQTTDrY8oQBEGTMViDmJ1TK/OmwEWt0rcnLsHzCB Ov0Q== X-Gm-Message-State: AOAM5339i8vXupIpEOOr00vdVhkYYiRM77UY/pdJu8oCnf9ivWEkNNZH 6nlEbmmL1ATbQ/YPNsE3uN8zkwJ+gz/uqK2G X-Google-Smtp-Source: ABdhPJxBz3iaFpvxH7Zng7mRjaAmPi9t/6V0+rHCcgskMB/17an6ZMG3+RqBr9pLhedBWDWCpnfKig== X-Received: by 2002:a4a:d126:: with SMTP id n6mr37201588oor.47.1609362047187; Wed, 30 Dec 2020 13:00: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 n16sm11414787oop.9.2020.12.30.13.00.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 30 Dec 2020 13:00: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 RFC v2 5/5] test/py: ecdsa: Add test for mkimage ECDSA signing Date: Wed, 30 Dec 2020 15:00:27 -0600 Message-Id: <20201230210028.4065824-6-mr.nuke.me@gmail.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201230210028.4065824-1-mr.nuke.me@gmail.com> References: <20201230210028.4065824-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..957964d329 --- /dev/null +++ b/test/py/tests/test_fit_ecdsa.py @@ -0,0 +1,111 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (c) 2020, 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): + """TODO: Document me + """ + 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 number kernel image with zeroes + with open(f'{tempdir}/test-kernel.bin', 'w') as fd: + fd.write(500 * chr(0)) + + 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)