[PATCH v3 02/15] ecdsa: initial support of ecdsa using mbedtls
Raymond Mao
raymondmaoca at gmail.com
Tue Mar 31 18:10:45 CEST 2026
Hi Philippe,
On Tue, Mar 31, 2026 at 6:00 AM Philippe Reynes
<philippe.reynes at softathome.com> wrote:
>
> Adds an initial support of ecdsa verify using mbedtls.
>
> Signed-off-by: Philippe Reynes <philippe.reynes at 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
>
> include/crypto/internal/ecdsa.h | 14 ++++
> lib/mbedtls/Makefile | 3 +
> lib/mbedtls/ecdsa.c | 141 ++++++++++++++++++++++++++++++++
> 3 files changed, 158 insertions(+)
> create mode 100644 include/crypto/internal/ecdsa.h
> create mode 100644 lib/mbedtls/ecdsa.c
>
> diff --git a/include/crypto/internal/ecdsa.h b/include/crypto/internal/ecdsa.h
> new file mode 100644
> index 00000000000..d2edc006cc2
> --- /dev/null
> +++ b/include/crypto/internal/ecdsa.h
> @@ -0,0 +1,14 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Copyright (c) 2026, Philippe Reynes <philippe.reynes at softathome.com>
> + */
> +#ifndef __ECDSA_HELPER
> +#define __ECDSA_HELPER
Suggest to keep the same guard style as the existing one for RSA '_RSA_HELPER_'.
> +
> +struct ecdsa_public_key;
> +
> +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/Makefile b/lib/mbedtls/Makefile
> index 5433e17cc64..6db06092cee 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
> +obj-$(CONFIG_$(PHASE_)ECDSA_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..c2ba5c3d72b
> --- /dev/null
> +++ b/lib/mbedtls/ecdsa.c
> @@ -0,0 +1,141 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (C) 2026 Philippe Reynes <philippe.reynes at softathome.com>
> + */
> +
> +#include <crypto/ecdsa-uclass.h>
Should include the header you added:
#include <crypto/internal/ecdsa.h>
> +#include "mbedtls_options.h" /* required to access private fields */
I didn't find private member access in below code, please double confirm.
If there is no private access, suggest removing this line.
> +#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)
> + goto out;
> +
> + if (!strcmp(curve_name, "prime256v1"))
> + grp_id = MBEDTLS_ECP_DP_SECP256R1;
As the statement 'stop on first group found', the grp_id should be
returned here.
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++;
> + }
> +
> + out:
> + 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;
> + const unsigned char *buf = hash;
> + size_t blen = hash_len;
> + mbedtls_ecp_point Q;
> + mbedtls_mpi r, s;
> + int key_len;
> + int err = -1;
> +
> + if (!(pubkey->size_bits % 8))
> + key_len = pubkey->size_bits / 8;
> + else
> + key_len = pubkey->size_bits / 8 + 1;
Please use 'DIV_ROUND_UP(pubkey->size_bits, 8)'.
> +
> + /* check the signature len */
> + if (sig_len != 2 * key_len) {
> + debug("%s: sig len should be twice the key len (sig len = %ld, key len = %d)\n",
> + __func__, 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) {
> + debug("%s: curve name %s not found\n",
> + __func__, 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 out1;
> + }
> +
> + /* prepare the pubkey */
> + mbedtls_ecp_point_init(&Q);
> + err = mbedtls_mpi_read_binary(&Q.X, pubkey->x, key_len);
> + if (err) {
> + debug("%s: could not read value x of the public key (err = %d)\n",
> + __func__, err);
> + err = -EINVAL;
> + goto out2;
> + }
> + err = mbedtls_mpi_read_binary(&Q.Y, pubkey->y, key_len);
> + if (err) {
> + debug("%s: could not read value y of the public key (err = %d)\n",
> + __func__, err);
> + err = -EINVAL;
> + goto out2;
> + }
> + mbedtls_mpi_lset(&Q.Z, 1);
The return code from mbedtls_mpi_lset needs to be checked here.
> +
> + /* check if the pubkey is valid */
> + err = mbedtls_ecp_check_pubkey(&grp, &Q);
> + if (err < 0) {
if (err)
> + debug("%s: public key is invalid (err = %d)\n", __func__, err);
> + err = -EKEYREJECTED;
> + goto out2;
> + }
> +
> + /* compute r */
> + mbedtls_mpi_init(&r);
> + err = mbedtls_mpi_read_binary(&r, signature, key_len);
> + if (err) {
> + debug("%s: could not read value r of the signature (err = %d)\n",
> + __func__, err);
> + err = -EINVAL;
> + goto out3;
> + }
> +
> + /* compute s */
> + mbedtls_mpi_init(&s);
> + err = mbedtls_mpi_read_binary(&s, (unsigned char *)signature + key_len,
> + key_len);
The casting of 'signature' is not needed.
Regards,
Raymond
> + if (err) {
> + debug("%s: could not read value s of the signature (err = %d)\n",
> + __func__, err);
> + err = -EINVAL;
> + goto out4;
> + }
> +
> + /* check the signature */
> + err = mbedtls_ecdsa_verify(&grp, buf, blen, &Q, &r, &s);
> + if (err)
> + err = -EINVAL;
> +
> + out4:
> + mbedtls_mpi_free(&s);
> + out3:
> + mbedtls_mpi_free(&r);
> + out2:
> + mbedtls_ecp_point_free(&Q);
> + out1:
> + mbedtls_ecp_group_free(&grp);
> + out:
> +
> + return err;
> +}
> --
> 2.43.0
>
More information about the U-Boot
mailing list