From: Philippe Reynes <philippe.reynes@softathome.com>
To: marko.makela@iki.fi, jonny.green@keytechinc.com,
raymondmaoca@gmail.com, trini@konsulko.com,
simon.glass@canonical.com
Cc: u-boot@lists.u-boot-project.org,
Philippe Reynes <philippe.reynes@softathome.com>
Subject: [PATCH v9 03/15] ecdsa: initial support of ecdsa using mbedtls
Date: Thu, 3 Sep 2026 10:16:53 +0200 [thread overview]
Message-ID: <20260903081705.12894-4-philippe.reynes@softathome.com> (raw)
In-Reply-To: <20260903081705.12894-1-philippe.reynes@softathome.com>
Adds an initial support of ecdsa verify using mbedtls.
Reviewed-by: Raymond Mao <raymondmaoca@gmail.com>
Signed-off-by: Philippe Reynes <philippe.reynes@softathome.com>
---
v2:
- rename sw_ecdsa.c to ecdsa.c
v3:
- rename sw_ecdsa_verify to ecdsa_hash_verify
- stop on first group found
- check signature len
- use debug instead of printf
- check function returns
- fix memleaks in ecdsa_hash_verify
v4:
- move struct ecdsa_public_key from ecdsa-u-class.h to internal/ecdsa.h
- use DIV_ROUND_UP
- some code cleanup
v5:
- add kerneldoc header for ecdsa_hash_verify
- read error when setting Q.Z
v6:
- add ECDSA_VERIFY_MBEDTLS
- fix kerneldoc: doc not add a space before :
v7:
- no change
v8:
- add some useful comments
- avoid using label such as out1, out2, out3 ...
- code cleanup
v9:
- no change
configs/sandbox_defconfig | 1 +
include/crypto/ecdsa-uclass.h | 15 +---
include/crypto/internal/ecdsa.h | 39 ++++++++
lib/mbedtls/Kconfig | 7 ++
lib/mbedtls/Makefile | 3 +
lib/mbedtls/ecdsa.c | 152 ++++++++++++++++++++++++++++++++
6 files changed, 203 insertions(+), 14 deletions(-)
create mode 100644 include/crypto/internal/ecdsa.h
create mode 100644 lib/mbedtls/ecdsa.c
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index b9991d269d9..63682ef0e74 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -390,6 +390,7 @@ CONFIG_CMD_DHRYSTONE=y
CONFIG_MBEDTLS_LIB=y
CONFIG_HKDF_MBEDTLS=y
CONFIG_ECDSA_MBEDTLS=y
+CONFIG_ECDSA_VERIFY_MBEDTLS=y
CONFIG_ECDSA=y
CONFIG_ECDSA_VERIFY=y
CONFIG_RSASSA_PSS=y
diff --git a/include/crypto/ecdsa-uclass.h b/include/crypto/ecdsa-uclass.h
index 189843820a0..047a5eda2fc 100644
--- a/include/crypto/ecdsa-uclass.h
+++ b/include/crypto/ecdsa-uclass.h
@@ -4,20 +4,7 @@
*/
#include <dm/device.h>
-
-/**
- * struct ecdsa_public_key - ECDSA public key properties
- *
- * The struct has pointers to the (x, y) curve coordinates to an ECDSA public
- * key, as well as the name of the ECDSA curve. The size of the key is inferred
- * from the 'curve_name'
- */
-struct ecdsa_public_key {
- const char *curve_name; /* Name of curve, e.g. "prime256v1" */
- const void *x; /* x coordinate of public key */
- const void *y; /* y coordinate of public key */
- unsigned int size_bits; /* key size in bits, derived from curve name */
-};
+#include <crypto/internal/ecdsa.h>
struct ecdsa_ops {
/**
diff --git a/include/crypto/internal/ecdsa.h b/include/crypto/internal/ecdsa.h
new file mode 100644
index 00000000000..244a07d1f1f
--- /dev/null
+++ b/include/crypto/internal/ecdsa.h
@@ -0,0 +1,39 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2026, Philippe Reynes <philippe.reynes@softathome.com>
+ */
+#ifndef _ECDSA_HELPER_
+#define _ECDSA_HELPER_
+
+#include <linux/types.h>
+
+/**
+ * struct ecdsa_public_key - ECDSA public key properties
+ *
+ * The struct has pointers to the (x, y) curve coordinates to an ECDSA public
+ * key, as well as the name of the ECDSA curve. The size of the key is inferred
+ * from the 'curve_name'
+ */
+struct ecdsa_public_key {
+ const char *curve_name; /* Name of curve, e.g. "prime256v1" */
+ const void *x; /* x coordinate of public key */
+ const void *y; /* y coordinate of public key */
+ unsigned int size_bits; /* key size in bits, derived from curve name */
+};
+
+/**
+ * ecdsa_hash_verify() - Verify the ecdsa signature of a hash
+ *
+ * @pubkey: ecdsa public key
+ * @hash: Hash
+ * @hash_len: Size of the hash
+ * @signature: Signature
+ * @sig_len: Size of the signature
+ *
+ * Return: 0 if all verified ok, <0 on error
+ */
+int ecdsa_hash_verify(const struct ecdsa_public_key *pubkey,
+ const void *hash, size_t hash_len,
+ const void *signature, size_t sig_len);
+
+#endif
diff --git a/lib/mbedtls/Kconfig b/lib/mbedtls/Kconfig
index e019f17d6bd..66bc16db451 100644
--- a/lib/mbedtls/Kconfig
+++ b/lib/mbedtls/Kconfig
@@ -308,6 +308,13 @@ config ECDSA_MBEDTLS
This option enables support of ECDSA with the MbedTLS certificate
library.
+config ECDSA_VERIFY_MBEDTLS
+ bool "Enable ECDSA verify"
+ depends on ECDSA_MBEDTLS && ECDSA_VERIFY
+ help
+ This option enables support of ECDSA signature check with
+ MbedTLS certificate library.
+
endif # MBEDTLS_LIB_X509
config MBEDTLS_LIB_TLS
diff --git a/lib/mbedtls/Makefile b/lib/mbedtls/Makefile
index 0c86c90d15a..b96db812afc 100644
--- a/lib/mbedtls/Makefile
+++ b/lib/mbedtls/Makefile
@@ -11,6 +11,9 @@ obj-$(CONFIG_$(PHASE_)SHA1_MBEDTLS) += sha1.o
obj-$(CONFIG_$(PHASE_)SHA256_MBEDTLS) += sha256.o
obj-$(CONFIG_$(PHASE_)SHA512_MBEDTLS) += sha512.o
+# shim layer for ecdsa verify
+obj-$(CONFIG_$(PHASE_)ECDSA_VERIFY_MBEDTLS) += ecdsa.o
+
# x509 libraries
obj-$(CONFIG_$(PHASE_)ASYMMETRIC_PUBLIC_KEY_MBEDTLS) += \
public_key.o
diff --git a/lib/mbedtls/ecdsa.c b/lib/mbedtls/ecdsa.c
new file mode 100644
index 00000000000..ca4e572e638
--- /dev/null
+++ b/lib/mbedtls/ecdsa.c
@@ -0,0 +1,152 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2026 Philippe Reynes <philippe.reynes@softathome.com>
+ */
+
+#include <log.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/types.h>
+
+#include <crypto/internal/ecdsa.h>
+
+#include "mbedtls_options.h" /* required to access private fields */
+#include <mbedtls/ecdsa.h>
+#include <mbedtls/ecp.h>
+
+static mbedtls_ecp_group_id ecdsa_search_group_id(const char *curve_name)
+{
+ mbedtls_ecp_group_id grp_id = MBEDTLS_ECP_DP_NONE;
+ const mbedtls_ecp_curve_info *info;
+
+ if (!curve_name)
+ return MBEDTLS_ECP_DP_NONE;
+
+ /*
+ * This curve name is read in the FIT metadata.
+ * When this FIT metadata are filled by mkimage (or binman),
+ * the curve name is the alias/name provided by OpenSSL.
+ * And for secp256r1, OpenSSL uses the alias prime256v1.
+ * So here, we have to manage this OpenSSL alias.
+ */
+ if (!strcmp(curve_name, "prime256v1"))
+ return MBEDTLS_ECP_DP_SECP256R1;
+
+ info = mbedtls_ecp_curve_list();
+ while (info && info->name) {
+ if (!strcmp(curve_name, info->name)) {
+ grp_id = info->grp_id;
+ break;
+ }
+ info++;
+ }
+
+ return grp_id;
+}
+
+int ecdsa_hash_verify(const struct ecdsa_public_key *pubkey,
+ const void *hash, size_t hash_len,
+ const void *signature, size_t sig_len)
+{
+ mbedtls_ecp_group_id grp_id;
+ mbedtls_ecp_group grp;
+ mbedtls_ecp_point Q;
+ mbedtls_mpi r, s;
+ int key_len;
+ int err;
+
+ key_len = DIV_ROUND_UP(pubkey->size_bits, 8);
+
+ /* check the signature len */
+ if (sig_len != 2 * key_len) {
+ log_debug("sig len should be twice the key len (sig len = %zu, key len = %d)\n",
+ sig_len, key_len);
+ err = -EINVAL;
+ goto out;
+ }
+
+ /* search the group */
+ grp_id = ecdsa_search_group_id(pubkey->curve_name);
+ if (grp_id == MBEDTLS_ECP_DP_NONE) {
+ log_debug("curve name %s not found\n", pubkey->curve_name);
+ err = -EINVAL;
+ goto out;
+ }
+
+ /* init and load the group */
+ mbedtls_ecp_group_init(&grp);
+ err = mbedtls_ecp_group_load(&grp, grp_id);
+ if (err) {
+ err = -EINVAL;
+ goto free_grp;
+ }
+
+ /* prepare the pubkey */
+ mbedtls_ecp_point_init(&Q);
+ err = mbedtls_mpi_read_binary(&Q.X, pubkey->x, key_len);
+ if (err) {
+ log_debug("could not read value x of the public key (err = %d)\n",
+ err);
+ err = -EINVAL;
+ goto free_q;
+ }
+ err = mbedtls_mpi_read_binary(&Q.Y, pubkey->y, key_len);
+ if (err) {
+ log_debug("could not read value y of the public key (err = %d)\n",
+ err);
+ err = -EINVAL;
+ goto free_q;
+ }
+ err = mbedtls_mpi_lset(&Q.Z, 1);
+ if (err) {
+ log_debug("could not set value z of the public key (err = %d)\n",
+ err);
+ err = -EINVAL;
+ goto free_q;
+ }
+
+ /* check if the pubkey is valid */
+ err = mbedtls_ecp_check_pubkey(&grp, &Q);
+ if (err) {
+ log_debug("public key is invalid (err = %d)\n", err);
+ err = -EKEYREJECTED;
+ goto free_q;
+ }
+
+ /* compute r */
+ mbedtls_mpi_init(&r);
+ err = mbedtls_mpi_read_binary(&r, signature, key_len);
+ if (err) {
+ log_debug("could not read value r of the signature (err = %d)\n",
+ err);
+ err = -EINVAL;
+ goto free_r;
+ }
+
+ /* compute s */
+ mbedtls_mpi_init(&s);
+ err = mbedtls_mpi_read_binary(&s, signature + key_len, key_len);
+ if (err) {
+ log_debug("could not read value s of the signature (err = %d)\n",
+ err);
+ err = -EINVAL;
+ goto free_s;
+ }
+
+ /* check the signature */
+ err = mbedtls_ecdsa_verify(&grp, hash, hash_len, &Q, &r, &s);
+ if (err)
+ err = -EINVAL;
+
+ free_s:
+ mbedtls_mpi_free(&s);
+ free_r:
+ mbedtls_mpi_free(&r);
+ free_q:
+ mbedtls_ecp_point_free(&Q);
+ free_grp:
+ mbedtls_ecp_group_free(&grp);
+ out:
+
+ return err;
+}
--
2.43.0
next prev parent reply other threads:[~2026-09-03 8:17 UTC|newest]
Thread overview: 36+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-03 8:16 [PATCH v9 00/15] add software ecdsa support Philippe Reynes
2026-09-03 8:16 ` [PATCH v9 01/15] ecdsa: fix support of secp521r1 Philippe Reynes
2026-09-03 14:30 ` Raymond Mao
2026-09-03 8:16 ` [PATCH v9 02/15] mbedtls: enable support of ecc Philippe Reynes
2026-09-03 14:31 ` Raymond Mao
2026-09-03 8:16 ` Philippe Reynes [this message]
2026-09-03 14:31 ` [PATCH v9 03/15] ecdsa: initial support of ecdsa using mbedtls Raymond Mao
2026-09-03 8:16 ` [PATCH v9 04/15] test: lib: ecdsa: add initial test Philippe Reynes
2026-09-03 14:32 ` Raymond Mao
2026-09-03 8:16 ` [PATCH v9 05/15] drivers: crypto: add software ecdsa support Philippe Reynes
2026-09-03 14:32 ` Raymond Mao
2026-09-03 15:33 ` Raymond Mao
2026-09-03 18:33 ` Tom Rini
2026-09-03 8:16 ` [PATCH v9 06/15] test: dm: ecdsa.c: clean this test as software ecdsa is now implemented Philippe Reynes
2026-09-03 14:33 ` Raymond Mao
2026-09-03 8:16 ` [PATCH v9 07/15] test: py: vboot: prepare integration test for ecdsa Philippe Reynes
2026-09-03 15:42 ` Raymond Mao
2026-09-03 8:16 ` [PATCH v9 08/15] test: vboot: add " Philippe Reynes
2026-09-03 15:43 ` Raymond Mao
2026-09-03 8:16 ` [PATCH v9 09/15] tools: fit_image_setup_sig: set required_keynode to -1 Philippe Reynes
2026-09-03 14:34 ` Raymond Mao
2026-09-03 8:17 ` [PATCH v9 10/15] tools: mkimage: pre-load: add support of ecdsa Philippe Reynes
2026-09-03 14:36 ` Raymond Mao
2026-09-03 8:17 ` [PATCH v9 11/15] tools: binman: " Philippe Reynes
2026-09-03 14:37 ` Raymond Mao
2026-09-03 8:17 ` [PATCH v9 12/15] boot: " Philippe Reynes
2026-09-03 14:38 ` Raymond Mao
2026-09-03 8:17 ` [PATCH v9 13/15] tools: preload_check_sign: " Philippe Reynes
2026-09-03 14:39 ` Raymond Mao
2026-09-03 8:17 ` [PATCH v9 14/15] test: py: vboot: prepare test for global signature with ecdsa Philippe Reynes
2026-09-03 14:40 ` Raymond Mao
2026-09-03 8:17 ` [PATCH v9 15/15] test: py: vboot: add " Philippe Reynes
2026-09-03 14:41 ` Raymond Mao
2026-09-03 18:35 ` [PATCH v9 00/15] add software ecdsa support Tom Rini
2026-09-04 8:10 ` Philippe Reynes
2026-09-04 14:32 ` Tom Rini
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=20260903081705.12894-4-philippe.reynes@softathome.com \
--to=philippe.reynes@softathome.com \
--cc=jonny.green@keytechinc.com \
--cc=marko.makela@iki.fi \
--cc=raymondmaoca@gmail.com \
--cc=simon.glass@canonical.com \
--cc=trini@konsulko.com \
--cc=u-boot@lists.u-boot-project.org \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.