public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
From: "Marko Mäkelä" <marko.makela@iki.fi>
To: u-boot@lists.denx.de
Subject: Re: How to use ECDSA for signature verification?
Date: Sat, 8 Nov 2025 19:24:00 +0200	[thread overview]
Message-ID: <aQ98sHenb3G1MQDi@kehys.lan> (raw)
In-Reply-To: <aO1GvGrXUw-co84_@kehys.lan>

Hi all,

I am new to u-boot, please bear with me. I got CONFIG_FIT_SIGNATURE=y to 
work with the RSA algorithm, but not with ECDSA.

My two main questions are:

Is CONFIG_ECDSA_VERIFY only implemented for the two targets:
rom_api_ops in arch/arm/mach-stm32mp/ecdsa_romapi.c
cptra_ecdsa_ops in drivers/crypto/aspeed/cptra_ecdsa.c. 

Is it feasible to support something more modern than RSA signatures on a 
reasonably high-end target, such as ARMv8? Are there any suggestions or 
git commits that you would suggest as a reference?

Mon, Oct 13, 2025 at 09:36:50PM +0300, Marko Mäkelä wrote:
>Hi all,
>
>Yesterday, I successfully built the u-boot master branch with 
>CONFIG_FIT_SIGNATURE=y and CONFIG_RSA=y and got the signature 
>verification working with sha256,rsa2048.
>
>Today, I wanted to try out CONFIG_ECDSA=y, but I am facing some 
>trouble.  I am generating the key and trying to add its public part to 
>the device tree blob as with fdt_add_pubkey as follows:

I got a bit further with this, using the algorithm sha256,ecdsa256.

With a patch and some work-arounds, I think I understood the host-side 
workflow. However, the signature check on my target (TI Sitara am62x) is 
failing.

Unlike with RSA, the mkimage command expects the ECDSA private key in a 
file like dev.pem, not dev.key. I successfully created a private key and 
constructed a signed FIT image with the following commands:

openssl ecparam -name prime256v1 -genkey -noout -out dev.pem
mkimage -k . -f fitImage.its fitImage

I verified the presence of a signature by running the following command, 
which produced the signature in a "value" subnode:

dtc -I dtb fitImage|grep -A10 signature

For the algorithm sha256,ecdsa256 that I chose, the fdt_add_pubkey tool 
requires a patch to avoid SIGSEGV, which I am copying below from my 
previous message:

diff --git a/tools/fdt_add_pubkey.c b/tools/fdt_add_pubkey.c
index 5582d7a8efe..4f7028cc15c 100644
--- a/tools/fdt_add_pubkey.c
+++ b/tools/fdt_add_pubkey.c
@@ -73,9 +73,10 @@ static void reset_info(struct image_sign_info *info)
  	info->keyname = keyname;
  	info->name = algo_name;
  	info->require_keys = require_keys;
+	info->checksum = image_get_checksum_algo(algo_name);
  	info->crypto = image_get_crypto_algo(algo_name);
  
-	if (!info->crypto) {
+	if (!info->checksum || !info->crypto) {
  		fprintf(stderr, "Unsupported signature algorithm '%s'\n",
  			algo_name);
  		exit(EXIT_FAILURE);

Unlike with RSA, fdt_add_pubkey does not accept a public key:

fdt_add_pubkey: Cannot add public key to FIT blob: Unknown error -5

I am able to work around this by invoking the tool on a _private_ key 
dev.pem that the fitImage had been signed with.

I don't know if there is a cleaner way, but here's how I am embedding 
the public key to the image. I first build U-boot from the scratch, 
modify the generated u-boot.dtb, and finally rebuild to have the 
modified DTB included:

make clean
make -j$(nproc) CROSS_COMPILE=aarch64-linux-gnu- ...
cp u-boot.dtb u-boot-pubkey.dtb
fdt_add_pubkey -a sha256,ecdsa256 -n dev -k . -r conf u-boot-pubkey.dtb
fit_check_sign -f fitImage -k u-boot-pubkey.dtb
make EXT_DTB=u-boot-pubkey.dtb \
-j$(nproc) CROSS_COMPILE=aarch64-linux-gnu- ...

Even though fit_check_sign passes on the host system, the signature 
check would fail on the target system (TI AM62x) as follows:

8304957 bytes read in 346 ms (22.9 MiB/s)
## Executing script at 90000000
sha256,ecdsa256:dev-  error!
Unknown signature algorithm for '<NULL>' hash node in 'conf-1' config node
Failed to verify required signature 'dev'
Boot failed (err=1)

It turns out that for ECDSA signature verification, at least three 
configuration options will be needed:

CONFIG_FIT_SIGNATURE=y
CONFIG_ECDSA=y
CONFIG_ECDSA_VERIFY=y

Rebuilding with CONFIG_ECDSA_VERIFY=y changed the error message to the 
following:

sha256,ecdsa256:dev-  error!
Verification failed for '<NULL>' hash node in 'conf-1' config node
Failed to verify required signature 'dev'

I did not attach a debugger to the target, but I am rather sure that the 
verification fails because of the following:

static int ecdsa_verify_hash(struct udevice *dev,
			     const struct image_sign_info *info,
			     const void *hash, const void *sig, uint sig_len)
{
	const struct ecdsa_ops *ops = device_get_ops(dev);
	const struct checksum_algo *algo = info->checksum;
	struct ecdsa_public_key key;
	int sig_node, key_node, ret;

	if (!ops || !ops->verify)
		return -ENODEV;

I found only two definitions of ecdsa_ops, and it does not look like 
either one should be available on my target system.

The cosmetic error <NULL> in the error message occurs because the local 
variable "noffset" in fit_image_verify_sig() will only be valid if the 
for loop is executing "goto error". This bug is tricky to fix, because 
as far as I understand, we want to allow multiple signatures to be 
verified.

One more thing that I noticed is that the function fit_check_sign() has 
an unused parameter:

diff --git a/tools/fit_check_sign.c b/tools/fit_check_sign.c
index ab3266aff20..3d1e66f2b58 100644
--- a/tools/fit_check_sign.c
+++ b/tools/fit_check_sign.c
@@ -80,7 +80,7 @@ int main(int argc, char **argv)
  			return EXIT_FAILURE;
  	}
  	image_set_host_blob(key_blob);
-	ret = fit_check_sign(fit_blob, key_blob, config_name);
+	ret = fit_check_sign(fit_blob, NULL, config_name);
  	if (!ret) {
  		ret = EXIT_SUCCESS;
  		fprintf(stderr, "Signature check OK\n");

The above patch shows the only caller of the function. It also shows 
that the caller is invoking image_set_host_blob() on that parameter, 
which is why the check is able to work. Maybe that call should be made 
part of fit_check_sign() itself? Anyway, this code does not execute on 
the target.

With best regards,

	Marko Mäkelä

  reply	other threads:[~2025-11-08 17:24 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-10-13 18:36 How to use ECDSA for signature verification? Marko Mäkelä
2025-11-08 17:24 ` Marko Mäkelä [this message]
2025-11-11  4:22   ` Anshul Dalal
2025-11-11 15:56     ` Marko Mäkelä
2026-02-03  5:32       ` Anshul Dalal

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=aQ98sHenb3G1MQDi@kehys.lan \
    --to=marko.makela@iki.fi \
    --cc=u-boot@lists.denx.de \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox