public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
From: Alexandru Gagniuc <mr.nuke.me@gmail.com>
To: u-boot@lists.denx.de
Subject: [PATCH 3/5] lib: ecdsa: Implement signature verification for crypto_algo API
Date: Mon, 11 Jan 2021 09:41:35 -0600	[thread overview]
Message-ID: <20210111154137.621732-4-mr.nuke.me@gmail.com> (raw)
In-Reply-To: <20210111154137.621732-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>
---
 lib/ecdsa/ecdsa-verify.c | 117 ++++++++++++++++++++++++++++++++++++++-
 1 file changed, 116 insertions(+), 1 deletion(-)

diff --git a/lib/ecdsa/ecdsa-verify.c b/lib/ecdsa/ecdsa-verify.c
index d2e6a40f4a..d84f6eb093 100644
--- a/lib/ecdsa/ecdsa-verify.c
+++ b/lib/ecdsa/ecdsa-verify.c
@@ -1,13 +1,128 @@
 // 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 <dm/uclass.h>
 #include <u-boot/ecdsa.h>
+#include <crypto/ecdsa-uclass.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 == 0)
+			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)
 {
-	return -EOPNOTSUPP;
+	const struct checksum_algo *algo = info->checksum;
+	uint8_t hash[algo->checksum_len];
+	struct udevice *dev;
+	int ret;
+
+	ret = uclass_first_device(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);
 }
+
+/*
+ * 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.26.2

  parent reply	other threads:[~2021-01-11 15:41 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-01-11 15:41 [PATCH 0/5] Enable ECDSA FIT verification for stm32mp Alexandru Gagniuc
2021-01-11 15:41 ` [PATCH 1/5] dm: crypto: Define UCLASS API for ECDSA signature verification Alexandru Gagniuc
2021-01-13 16:10   ` Simon Glass
2021-01-14 16:09     ` Alex G.
2021-01-14 19:16       ` Simon Glass
2021-01-11 15:41 ` [PATCH 2/5] lib: ecdsa: Add skeleton to implement ecdsa verification in u-boot Alexandru Gagniuc
2021-02-09 15:11   ` Patrick DELAUNAY
2021-02-09 22:37     ` Alex G.
2021-01-11 15:41 ` Alexandru Gagniuc [this message]
2021-01-13 16:10   ` [PATCH 3/5] lib: ecdsa: Implement signature verification for crypto_algo API Simon Glass
2021-02-09 15:56   ` Patrick DELAUNAY
2021-02-09 22:58     ` Alex G.
2021-01-11 15:41 ` [PATCH 4/5] arm: stm32mp1: Implement ECDSA signature verification Alexandru Gagniuc
2021-01-11 15:41 ` [PATCH 5/5] Kconfig: FIT_SIGNATURE should not select RSA_VERIFY Alexandru Gagniuc
2021-01-13 16:10   ` Simon Glass
2021-02-09 15:08 ` [PATCH 0/5] Enable ECDSA FIT verification for stm32mp Patrick DELAUNAY
2021-02-09 21:28   ` Alex G.

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=20210111154137.621732-4-mr.nuke.me@gmail.com \
    --to=mr.nuke.me@gmail.com \
    --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