How to use ECDSA for signature verification?

Anshul Dalal anshuld at ti.com
Tue Nov 11 05:22:51 CET 2025


Hello Marko,

On Sat Nov 8, 2025 at 10:54 PM IST, Marko Mäkelä wrote:
> 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. 
>

Yes, those two seem to be the only one's implementing UCLASS_ECDSA.

> 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?
>

Should be possible, you can look at the current implementaitons of RSA
and lib/ecdsa/ecdsa-libcrypto.c for 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'
>

This is probably due to U-Boot failing to find a driver with
UCLASS_ECDSA, you can verify by adding a "#define DEBUG" to the top of
lib/ecdsa/ecdsa-verify.c and check if the following error shows up:

	ECDSA: Could not find ECDSA implementation: -19

Regards,
Anshul

> 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ä



More information about the U-Boot mailing list