From: Alexandru Gagniuc <mr.nuke.me@gmail.com>
To: u-boot@lists.denx.de, patrick.delaunay@foss.st.com
Cc: Alexandru Gagniuc <mr.nuke.me@gmail.com>,
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 [thread overview]
Message-ID: <20210729164719.3490718-3-mr.nuke.me@gmail.com> (raw)
In-Reply-To: <20210729164719.3490718-1-mr.nuke.me@gmail.com>
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 <mr.nuke.me@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
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 <mr.nuke.me@gmail.com>
+ */
+
+#include <crypto/ecdsa-uclass.h>
+#include <dm/uclass.h>
+#include <u-boot/ecdsa.h>
+
+/*
+ * 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
next prev parent reply other threads:[~2021-07-29 16:48 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-05-17 18:38 [PATCH v5 0/5] Enable ECDSA FIT verification for stm32mp Alexandru Gagniuc
2021-05-17 18:39 ` [PATCH v5 1/5] dm: crypto: Define UCLASS API for ECDSA signature verification Alexandru Gagniuc
2021-05-19 16:36 ` Simon Glass
2021-05-17 18:39 ` [PATCH v5 2/5] lib: ecdsa: Implement UCLASS_ECDSA verification on target Alexandru Gagniuc
2021-05-19 16:36 ` Simon Glass
2021-05-17 18:39 ` [PATCH v5 3/5] arm: stm32mp1: Implement ECDSA signature verification Alexandru Gagniuc
2021-05-17 18:39 ` [PATCH v5 4/5] Kconfig: FIT_SIGNATURE should not select RSA_VERIFY Alexandru Gagniuc
2021-05-17 19:10 ` Igor Opaniuk
2021-05-17 18:39 ` [PATCH v5 5/5] test: dm: Add test for ECDSA UCLASS support Alexandru Gagniuc
2021-07-27 8:09 ` Patrick DELAUNAY
2021-07-29 16:47 ` [PATCH 0/5] Enable ECDSA FIT verification for stm32mp Alexandru Gagniuc
2021-07-29 16:47 ` [PATCH 1/5] dm: crypto: Define UCLASS API for ECDSA signature verification Alexandru Gagniuc
2021-07-30 9:47 ` Patrick DELAUNAY
2021-08-16 11:31 ` Patrice CHOTARD
2021-07-29 16:47 ` Alexandru Gagniuc [this message]
2021-07-30 9:49 ` [PATCH 2/5] lib: ecdsa: Implement UCLASS_ECDSA verification on target Patrick DELAUNAY
2021-07-29 16:47 ` [PATCH 3/5] arm: stm32mp1: Implement ECDSA signature verification Alexandru Gagniuc
2021-07-30 9:51 ` Patrick DELAUNAY
2021-08-16 11:31 ` Patrice CHOTARD
2021-07-29 16:47 ` [PATCH 4/5] Kconfig: FIT_SIGNATURE should not select RSA_VERIFY Alexandru Gagniuc
2021-07-30 9:52 ` Patrick DELAUNAY
2021-08-16 11:32 ` Patrice CHOTARD
2021-07-29 16:47 ` [PATCH 5/5] test: dm: Add test for ECDSA UCLASS support Alexandru Gagniuc
2021-07-30 9:53 ` Patrick DELAUNAY
2021-08-16 11:32 ` Patrice CHOTARD
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210729164719.3490718-3-mr.nuke.me@gmail.com \
--to=mr.nuke.me@gmail.com \
--cc=etienne.carriere@linaro.org \
--cc=patrice.chotard@foss.st.com \
--cc=patrick.delaunay@foss.st.com \
--cc=sjg@chromium.org \
--cc=u-boot@lists.denx.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox