Hi Philippe,

On Thu, Feb 19, 2026 at 8:26 AM Philippe Reynes
<[email protected]> wrote:
>
> Adds an initial support of ecdsa verify using mbedtls.
>
> Signed-off-by: Philippe Reynes <[email protected]>
> ---
> v2:
> - rename sw_ecdsa.c to ecdsa.c
>
>  include/crypto/internal/sw_ecdsa.h | 14 +++++


Please rename the file to 'ecdsa.h'.


>  lib/mbedtls/Makefile               |  3 +
>  lib/mbedtls/ecdsa.c                | 94 ++++++++++++++++++++++++++++++
>  3 files changed, 111 insertions(+)
>  create mode 100644 include/crypto/internal/sw_ecdsa.h
>  create mode 100644 lib/mbedtls/ecdsa.c
>
> diff --git a/include/crypto/internal/sw_ecdsa.h 
> b/include/crypto/internal/sw_ecdsa.h
> new file mode 100644
> index 00000000000..b1ca31da0f8
> --- /dev/null
> +++ b/include/crypto/internal/sw_ecdsa.h
> @@ -0,0 +1,14 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Copyright (c) 2026, Philippe Reynes <[email protected]>
> + */
> +#ifndef _SW_ECDSA
> +#define _SW_ECDSA
> +
> +struct ecdsa_public_key;
> +
> +int sw_ecdsa_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..0ed95f4407f
> --- /dev/null
> +++ b/lib/mbedtls/ecdsa.c
> @@ -0,0 +1,94 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (C) 2026 Philippe Reynes <[email protected]>
> + */
> +
> +#include <crypto/ecdsa-uclass.h>
> +#include "mbedtls_options.h" /* required to access private fields */
> +#include <mbedtls/ecdsa.h>
> +#include <mbedtls/ecp.h>
> +
> +static mbedtls_ecp_group_id sw_ecdsa_search_group_id(const char *curve_name)


Please remove the prefix 'sw_', using MbedTLS does not necessarily
mean SW, as the library allows HW acceleration via hooks through
'_ALT' configs.


> +{
> +       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;
> +
> +       info = mbedtls_ecp_curve_list();
> +       while (info && info->name) {
> +               if (!strcmp(curve_name, info->name))
> +                       grp_id = info->grp_id;


If a match is found, the loop should break immediately.


> +               info++;
> +       }
> +
> + out:
> +       return grp_id;
> +}
> +
> +int sw_ecdsa_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;
> +


Missing signature length validation, for example:
if (sig_len != 2 * key_len)
    return -EINVAL;


> +       /* search the group */
> +       grp_id = sw_ecdsa_search_group_id(pubkey->curve_name);
> +       if (grp_id == MBEDTLS_ECP_DP_NONE) {
> +               printf("%s: curve name %s not found\n",
> +                      __func__, pubkey->curve_name);


Please use debug().


> +               goto out;
> +       }
> +
> +       /* init and load the group */
> +       mbedtls_ecp_group_init(&grp);
> +       err = mbedtls_ecp_group_load(&grp, grp_id);
> +       if (err < 0)


'if (err)'


> +               goto out;
> +
> +       /* prepare the pubkey */
> +       mbedtls_ecp_point_init(&Q);
> +       mbedtls_mpi_init(&Q.X);
> +       mbedtls_mpi_init(&Q.Y);
> +       mbedtls_mpi_init(&Q.Z);


Redundant mpi_init on Q.X/Y/Z, as mbedtls_ecp_point_init() already
initializes X, Y, Z.


> +       mbedtls_mpi_read_binary(&Q.X, pubkey->x, key_len);
> +       mbedtls_mpi_read_binary(&Q.Y, pubkey->y, key_len);


Missing return value checks for mbedtls_mpi_read_binary().


> +       mbedtls_mpi_lset(&Q.Z, 1);
> +
> +       /* check if the pubkey is valid */
> +       err = mbedtls_ecp_check_pubkey(&grp, &Q);
> +       if (err < 0) {


'if (err)'


> +               printf("%s: public key is invalid (err = %d)\n", __func__, 
> err);


Please use debug().


> +               goto out;
> +       }
> +
> +       /* compute r */
> +       mbedtls_mpi_init(&r);
> +       mbedtls_mpi_read_binary(&r, signature, key_len);


Missing return value checks for mbedtls_mpi_read_binary().


> +
> +       /* compute s */
> +       mbedtls_mpi_init(&s);
> +       mbedtls_mpi_read_binary(&s, signature + key_len, key_len);


Missing return value checks for mbedtls_mpi_read_binary().
Please cast signature to const u8 * (or unsigned char *)
before doing pointer arithmetic.


> +
> +       /* check the signature */
> +       err = mbedtls_ecdsa_verify(&grp, buf, blen, &Q, &r, &s);
> +
> + out:


Potential memory leak.
MbedTLS objects allocate internal memory after invoking
mbedtls_ecp_group_load() or mbedtls_mpi_read_binary(), which must be
freed before returning errors via:
mbedtls_mpi_free()
mbedtls_ecp_point_free()
mbedtls_ecp_group_free()


> +       return err;


Please map all MbedTLS internal errors to U-Boot definitions.

Regards,
Raymond

> +}
> --
> 2.43.0
>

Reply via email to