Adds an initial support of ecdsa verify using mbedtls. Signed-off-by: Philippe Reynes <[email protected]> --- include/crypto/internal/sw_ecdsa.h | 14 +++++ lib/mbedtls/Makefile | 3 + lib/mbedtls/sw_ecdsa.c | 94 ++++++++++++++++++++++++++++++ 3 files changed, 111 insertions(+) create mode 100644 include/crypto/internal/sw_ecdsa.h create mode 100644 lib/mbedtls/sw_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 54a893609cf..a5331313a60 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 crypto +obj-$(CONFIG_$(PHASE_)ECDSA_MBEDTLS) += sw_ecdsa.o + # x509 libraries obj-$(CONFIG_$(PHASE_)ASYMMETRIC_PUBLIC_KEY_MBEDTLS) += \ public_key.o diff --git a/lib/mbedtls/sw_ecdsa.c b/lib/mbedtls/sw_ecdsa.c new file mode 100644 index 00000000000..0ed95f4407f --- /dev/null +++ b/lib/mbedtls/sw_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) +{ + 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; + 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; + + /* 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); + goto out; + } + + /* init and load the group */ + mbedtls_ecp_group_init(&grp); + err = mbedtls_ecp_group_load(&grp, grp_id); + if (err < 0) + 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); + mbedtls_mpi_read_binary(&Q.X, pubkey->x, key_len); + mbedtls_mpi_read_binary(&Q.Y, pubkey->y, key_len); + mbedtls_mpi_lset(&Q.Z, 1); + + /* check if the pubkey is valid */ + err = mbedtls_ecp_check_pubkey(&grp, &Q); + if (err < 0) { + printf("%s: public key is invalid (err = %d)\n", __func__, err); + goto out; + } + + /* compute r */ + mbedtls_mpi_init(&r); + mbedtls_mpi_read_binary(&r, signature, key_len); + + /* compute s */ + mbedtls_mpi_init(&s); + mbedtls_mpi_read_binary(&s, signature + key_len, key_len); + + /* check the signature */ + err = mbedtls_ecdsa_verify(&grp, buf, blen, &Q, &r, &s); + + out: + return err; +} -- 2.43.0

