From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0371EC4338F for ; Thu, 29 Jul 2021 16:48:04 +0000 (UTC) Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 5855560EB2 for ; Thu, 29 Jul 2021 16:48:03 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 5855560EB2 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=lists.denx.de Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 81CD583113; Thu, 29 Jul 2021 18:47:49 +0200 (CEST) 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="C9GDI4eP"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 6712A82F3F; Thu, 29 Jul 2021 18:47:33 +0200 (CEST) Received: from mail-oo1-xc35.google.com (mail-oo1-xc35.google.com [IPv6:2607:f8b0:4864:20::c35]) (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 30F1582F24 for ; Thu, 29 Jul 2021 18:47:27 +0200 (CEST) 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-xc35.google.com with SMTP id h7-20020a4ab4470000b0290263c143bcb2so1729007ooo.7 for ; Thu, 29 Jul 2021 09:47:27 -0700 (PDT) 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=hGhCkg5iMjTXEs2cg0apE6gZJ42LV6oWNg3HSjMJvbw=; b=C9GDI4ePLqTnzepdURL5Ep4vPbyGUdhDNseBLshebi4iw8V/tEK2tHneRUFLIwbYP3 O/YveVoplUvx4lFnQHyimsksDb3VgaWC/FvcJecUeOT0MbO5lT8OWQttFckKposCvHOE F4qXdVY7G5FTj28WpIlDO5VcB7hdzQnLXJ11szNJ18WyvW6zpXhlAoy4Up8OWZCSpAYA VtqF0fujatjNFl7/CNRDPgSDXsi13MsXrgl2yB336bfEtNJyN8pCav9Cn76+noDym2bV oWyEPyhRo2NXgGHWFgkflPKzlcq9hZfmqHMhVY3LLkrUJ0cFelKk00YJzXbyGkbHzHbS rSvw== 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=hGhCkg5iMjTXEs2cg0apE6gZJ42LV6oWNg3HSjMJvbw=; b=M2zkw2Hdw8YEH3ZRFcvM1u8opoXsPVF4m2Px/9nkn7tEyFaJjs6VVQuKwTeSoYMQaN zCqdmOStlYUXQAYNVIvoM2dGEFLGvS4b7nAEZmN7TIHDLeGa1z+kaxW36xrkdvlzT3Jv bmwnwhBnnmNCs9FMamvZQLRI9nPAJSkzxWNnWoPWJNBo+aFKFtSxOZfmIJyoQHH8RKAb 9xRG9rt2BIBiboF7SBRZgvbsITJ1Y1bW9o+s3LgiUtOVdn+P+i7T8kpjMQ24vA/3aINw o3BiIU5Sr9jkfRWZd6mm046c8GUJzfs0cgXoqViEoAmafJ2iPVVuCupJv1CwOEKw5T6C ZtOw== X-Gm-Message-State: AOAM530FqQdaSw/ZuKc9fbFyfq3kZFGudl4F62M7Uuon3mSruxoW1+kV ehi+rY9SDP+EHmXKVctVuI2ixwpZWW4= X-Google-Smtp-Source: ABdhPJwM8LIOneooft9tdB4RJlXAtzDxTxaEogiOfcl8Xyjjr7NxwJgFOc3hnC1dvgPjzbDQXfec2g== X-Received: by 2002:a4a:5dc6:: with SMTP id w189mr3640745ooa.1.1627577245402; Thu, 29 Jul 2021 09:47:25 -0700 (PDT) Received: from nuclearis3.lan (c-98-195-139-126.hsd1.tx.comcast.net. [98.195.139.126]) by smtp.gmail.com with ESMTPSA id i12sm623273otr.56.2021.07.29.09.47.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 29 Jul 2021 09:47:24 -0700 (PDT) From: Alexandru Gagniuc To: u-boot@lists.denx.de, patrick.delaunay@foss.st.com Cc: Alexandru Gagniuc , sjg@chromium.org, etienne.carriere@linaro.org, patrice.chotard@foss.st.com Subject: [PATCH 2/5] lib: ecdsa: Implement UCLASS_ECDSA verification on target Date: Thu, 29 Jul 2021 11:47:16 -0500 Message-Id: <20210729164719.3490718-3-mr.nuke.me@gmail.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210729164719.3490718-1-mr.nuke.me@gmail.com> References: <20210729164719.3490718-1-mr.nuke.me@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 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.103.2 at phobos.denx.de X-Virus-Status: Clean Implement the crypto_algo .verify() function for ecdsa256. Because it backends on UCLASS_ECDSA, this change is focused on parsing the keys from devicetree and passing this information to the specific UCLASS driver. Signed-off-by: Alexandru Gagniuc Reviewed-by: Simon Glass --- lib/Kconfig | 1 + lib/Makefile | 1 + lib/ecdsa/Kconfig | 23 +++++++ lib/ecdsa/Makefile | 1 + lib/ecdsa/ecdsa-verify.c | 134 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 160 insertions(+) create mode 100644 lib/ecdsa/Kconfig create mode 100644 lib/ecdsa/Makefile create mode 100644 lib/ecdsa/ecdsa-verify.c diff --git a/lib/Kconfig b/lib/Kconfig index fdcf7ea405..014a2f7f77 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -303,6 +303,7 @@ config AES supported by the algorithm but only a 128-bit key is supported at present. +source lib/ecdsa/Kconfig source lib/rsa/Kconfig source lib/crypto/Kconfig source lib/crypt/Kconfig diff --git a/lib/Makefile b/lib/Makefile index 07c2ccd7cf..8ba745faa0 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_ECDSA) += ecdsa/ obj-$(CONFIG_$(SPL_)RSA) += rsa/ obj-$(CONFIG_HASH) += hash-checksum.o obj-$(CONFIG_SHA1) += sha1.o diff --git a/lib/ecdsa/Kconfig b/lib/ecdsa/Kconfig new file mode 100644 index 0000000000..a95c4ff581 --- /dev/null +++ b/lib/ecdsa/Kconfig @@ -0,0 +1,23 @@ +config ECDSA + bool "Enable ECDSA support" + depends on DM + help + This enables the ECDSA (elliptic curve signature) algorithm for FIT + image verification in U-Boot. The ECDSA algorithm is implemented + using the driver model, so CONFIG_DM is required by this library. + See doc/uImage.FIT/signature.txt for more details. + ECDSA is enabled for mkimage regardless of this option. + +if ECDSA + +config ECDSA_VERIFY + bool "Enable ECDSA verification support in U-Boot." + help + Allow ECDSA signatures to be recognized and verified in U-Boot. + +config SPL_ECDSA_VERIFY + bool "Enable ECDSA verification support in SPL" + help + Allow ECDSA signatures to be recognized and verified in SPL. + +endif diff --git a/lib/ecdsa/Makefile b/lib/ecdsa/Makefile new file mode 100644 index 0000000000..771d6d3135 --- /dev/null +++ b/lib/ecdsa/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_$(SPL_)ECDSA_VERIFY) += ecdsa-verify.o diff --git a/lib/ecdsa/ecdsa-verify.c b/lib/ecdsa/ecdsa-verify.c new file mode 100644 index 0000000000..0601700c4f --- /dev/null +++ b/lib/ecdsa/ecdsa-verify.c @@ -0,0 +1,134 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * ECDSA signature verification for u-boot + * + * This implements the firmware-side wrapper for ECDSA verification. It bridges + * the struct crypto_algo API to the ECDSA uclass implementations. + * + * Copyright (c) 2020, Alexandru Gagniuc + */ + +#include +#include +#include + +/* + * Derive size of an ECDSA key from the curve name + * + * While it's possible to extract the key size by using string manipulation, + * use a list of known curves for the time being. + */ +static int ecdsa_key_size(const char *curve_name) +{ + if (!strcmp(curve_name, "prime256v1")) + return 256; + else + return 0; +} + +static int fdt_get_key(struct ecdsa_public_key *key, const void *fdt, int node) +{ + int x_len, y_len; + + key->curve_name = fdt_getprop(fdt, node, "ecdsa,curve", NULL); + key->size_bits = ecdsa_key_size(key->curve_name); + if (key->size_bits == 0) { + debug("Unknown ECDSA curve '%s'", key->curve_name); + return -EINVAL; + } + + key->x = fdt_getprop(fdt, node, "ecdsa,x-point", &x_len); + key->y = fdt_getprop(fdt, node, "ecdsa,y-point", &y_len); + + if (!key->x || !key->y) + return -EINVAL; + + if (x_len != (key->size_bits / 8) || y_len != (key->size_bits / 8)) { + printf("%s: node=%d, curve@%p x@%p+%i y@%p+%i\n", __func__, + node, key->curve_name, key->x, x_len, key->y, y_len); + return -EINVAL; + } + + return 0; +} + +static int ecdsa_verify_hash(struct udevice *dev, + const struct image_sign_info *info, + const void *hash, const void *sig, uint sig_len) +{ + const struct ecdsa_ops *ops = device_get_ops(dev); + const struct checksum_algo *algo = info->checksum; + struct ecdsa_public_key key; + int sig_node, key_node, ret; + + if (!ops || !ops->verify) + return -ENODEV; + + if (info->required_keynode > 0) { + ret = fdt_get_key(&key, info->fdt_blob, info->required_keynode); + if (ret < 0) + return ret; + + return ops->verify(dev, &key, hash, algo->checksum_len, + sig, sig_len); + } + + sig_node = fdt_subnode_offset(info->fdt_blob, 0, FIT_SIG_NODENAME); + if (sig_node < 0) + return -ENOENT; + + /* Try all possible keys under the "/signature" node */ + fdt_for_each_subnode(key_node, info->fdt_blob, sig_node) { + ret = fdt_get_key(&key, info->fdt_blob, key_node); + if (ret < 0) + continue; + + ret = ops->verify(dev, &key, hash, algo->checksum_len, + sig, sig_len); + + /* On success, don't worry about remaining keys */ + if (!ret) + return 0; + } + + return -EPERM; +} + +int ecdsa_verify(struct image_sign_info *info, + const struct image_region region[], int region_count, + uint8_t *sig, uint sig_len) +{ + const struct checksum_algo *algo = info->checksum; + uint8_t hash[algo->checksum_len]; + struct udevice *dev; + int ret; + + ret = uclass_first_device_err(UCLASS_ECDSA, &dev); + if (ret) { + debug("ECDSA: Could not find ECDSA implementation: %d\n", ret); + return ret; + } + + ret = algo->calculate(algo->name, region, region_count, hash); + if (ret < 0) + return -EINVAL; + + return ecdsa_verify_hash(dev, info, hash, sig, sig_len); +} + +U_BOOT_CRYPTO_ALGO(ecdsa) = { + .name = "ecdsa256", + .key_len = ECDSA256_BYTES, + .verify = ecdsa_verify, +}; + +/* + * uclass definition for ECDSA API + * + * We don't implement any wrappers around ecdsa_ops->verify() because it's + * trivial to call ops->verify(). + */ +UCLASS_DRIVER(ecdsa) = { + .id = UCLASS_ECDSA, + .name = "ecdsa_verifier", +}; -- 2.31.1