Hi Philippe,
On Thu, Feb 19, 2026 at 8:26 AM Philippe Reynes
<[email protected]> wrote:
>
> Current implementation of ecdsa only supports key len aligned on
> 8 bits. But the curve secp521r1 use a key of 521 bits which is not
> aligned on 8 bits. In this commit, we update the key management
> for ecdsa to support key of any lenght.
>
> Signed-off-by: Philippe Reynes <[email protected]>
> ---
> v2:
> - intitial version
>
> lib/ecdsa/ecdsa-libcrypto.c | 21 +++++++++++++++++++--
> lib/ecdsa/ecdsa-verify.c | 24 ++++++++++++++++++++++--
> lib/fdt-libcrypto.c | 2 +-
> tools/image-sig-host.c | 2 +-
> 4 files changed, 43 insertions(+), 6 deletions(-)
>
> diff --git a/lib/ecdsa/ecdsa-libcrypto.c b/lib/ecdsa/ecdsa-libcrypto.c
> index c4bfb2cec61..6f25ccc783d 100644
> --- a/lib/ecdsa/ecdsa-libcrypto.c
> +++ b/lib/ecdsa/ecdsa-libcrypto.c
> @@ -45,6 +45,7 @@ static int fdt_get_key(struct ecdsa_public_key *key, const
> void *fdt, int node)
> {
> int x_len;
> int y_len;
> + int expected_len;
>
> key->curve_name = fdt_getprop(fdt, node, "ecdsa,curve", NULL);
> if (!key->curve_name)
> @@ -54,6 +55,8 @@ static int fdt_get_key(struct ecdsa_public_key *key, const
> void *fdt, int node)
> key->size_bits = 256;
> else if (!strcmp(key->curve_name, "secp384r1"))
> key->size_bits = 384;
> + else if (!strcmp(key->curve_name, "secp521r1"))
> + key->size_bits = 521;
> else
> return -EINVAL;
>
> @@ -63,7 +66,19 @@ static int fdt_get_key(struct ecdsa_public_key *key, const
> void *fdt, int node)
> if (!key->x || !key->y)
> return -EINVAL;
>
> - if (x_len != key->size_bits / 8 || y_len != key->size_bits / 8)
> + /*
> + * the public key is stored as an array of u32, so if the key size if
s/if/is/
> + * not a multiple of 32 (for example 521), we may have extra bytes.
> + * To avoid any issue later, we shift the x and y pointer to the first
> + * useful byte.
> + */
> + expected_len = (key->size_bits + 7) / 8;
> + if (x_len > expected_len)
> + key->x += x_len - expected_len;
> + if (y_len > expected_len)
> + key->y += y_len - expected_len;
> +
> + if (x_len < expected_len || y_len < expected_len)
> return -EINVAL;
>
> return 0;
> @@ -89,6 +104,8 @@ static int read_key_from_fdt(struct signer *ctx, const
> void *fdt, int node)
> nid = NID_X9_62_prime256v1;
> } else if (!strcmp(pubkey.curve_name, "secp384r1")) {
> nid = NID_secp384r1;
> + } else if (!strcmp(pubkey.curve_name, "secp521r1")) {
> + nid = NID_secp521r1;
> } else {
> fprintf(stderr, "Unsupported curve name: '%s'\n",
> pubkey.curve_name);
> return -EINVAL;
> @@ -111,7 +128,7 @@ static int read_key_from_fdt(struct signer *ctx, const
> void *fdt, int node)
> return -ENOMEM;
> }
>
> - len = pubkey.size_bits / 8;
> + len = (pubkey.size_bits + 7) / 8;
>
> uint8_t buf[1 + len * 2];
>
> diff --git a/lib/ecdsa/ecdsa-verify.c b/lib/ecdsa/ecdsa-verify.c
> index 629b662cf6c..d87d95a5002 100644
> --- a/lib/ecdsa/ecdsa-verify.c
> +++ b/lib/ecdsa/ecdsa-verify.c
> @@ -24,13 +24,15 @@ static int ecdsa_key_size(const char *curve_name)
> return 256;
> else if (!strcmp(curve_name, "secp384r1"))
> return 384;
> + else if (!strcmp(curve_name, "secp521r1"))
> + return 521;
>
> return 0;
> }
>
> static int fdt_get_key(struct ecdsa_public_key *key, const void *fdt, int
> node)
> {
> - int x_len, y_len;
> + int expected_len, x_len, y_len;
>
> key->curve_name = fdt_getprop(fdt, node, "ecdsa,curve", NULL);
> if (!key->curve_name) {
> @@ -50,7 +52,19 @@ static int fdt_get_key(struct ecdsa_public_key *key, const
> void *fdt, int node)
> if (!key->x || !key->y)
> return -EINVAL;
>
> - if (x_len != (key->size_bits / 8) || y_len != (key->size_bits / 8)) {
> + /*
> + * the public key is stored as an array of u32, so if the key size if
s/if/is/
Regards,
Raymond
> + * not a multiple of 32 (for example 521), we may have extra bytes.
> + * To avoid any issue later, we shift the x and y pointer to the first
> + * useful byte.
> + */
> + expected_len = (key->size_bits + 7) / 8;
> + if (x_len > expected_len)
> + key->x += x_len - expected_len;
> + if (y_len > expected_len)
> + key->y += y_len - expected_len;
> +
> + if (x_len < expected_len || y_len < expected_len) {
> 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;
> @@ -135,6 +149,12 @@ U_BOOT_CRYPTO_ALGO(ecdsa384) = {
> .verify = ecdsa_verify,
> };
>
> +U_BOOT_CRYPTO_ALGO(ecdsa521) = {
> + .name = "ecdsa521",
> + .key_len = ECDSA521_BYTES,
> + .verify = ecdsa_verify,
> +};
> +
> /*
> * uclass definition for ECDSA API
> *
> diff --git a/lib/fdt-libcrypto.c b/lib/fdt-libcrypto.c
> index ecb0344c8f6..090246b44e9 100644
> --- a/lib/fdt-libcrypto.c
> +++ b/lib/fdt-libcrypto.c
> @@ -10,7 +10,7 @@
> int fdt_add_bignum(void *blob, int noffset, const char *prop_name,
> BIGNUM *num, int num_bits)
> {
> - int nwords = num_bits / 32;
> + int nwords = (num_bits + 31) / 32;
> int size;
> uint32_t *buf, *ptr;
> BIGNUM *tmp, *big2, *big32, *big2_32;
> diff --git a/tools/image-sig-host.c b/tools/image-sig-host.c
> index 5285263c616..a2272b196e7 100644
> --- a/tools/image-sig-host.c
> +++ b/tools/image-sig-host.c
> @@ -84,7 +84,7 @@ struct crypto_algo crypto_algos[] = {
> .verify = ecdsa_verify,
> },
> {
> - .name = "secp521r1",
> + .name = "ecdsa521",
> .key_len = ECDSA521_BYTES,
> .sign = ecdsa_sign,
> .add_verify_data = ecdsa_add_verify_data,
> --
> 2.43.0
>