espressif / esptool

Espressif SoC serial bootloader utility
https://docs.espressif.com/projects/esptool
GNU General Public License v2.0
5.6k stars 1.39k forks source link

Failed to create signature block with pre-calculated signatures (ESPTOOL-787) #942

Closed eme-bennytang closed 10 months ago

eme-bennytang commented 11 months ago

Operating System

Ubuntu 22.04.3 LTS

Esptool Version

v4.7.0 #bff9334

Python Version

Python 3.10.2

Full Esptool Command Line that Was Run

espsecure.py sign_data --version 2 --pub-key public_key.pem --signature signature.bin --output bootloader_signed.bin bootloader.bin

Esptool Output

espsecure.py v4.7.0
Pre-calculated signatures found
1 signing key(s) found.

A fatal error occurred: Signature verification failed: Invalid Signature
The pre-calculated signature has not been signed using the given public key

What is the Expected Behaviour?

It should give me bootloader with 4k signature block.

More Information

I have the need to separate the signing process and the building process. Moreover, I can't guarantee the signing process will be done in espsecure.py

Thus I am looking for ways to create the 4K bytes signature block with a signature provided from the signer.

The command below suppose to do the trick, but failed to do so. espsecure.py sign_data --version 2 --pub-key public_key.pem --signature signature.bin --output bootloader_signed.bin bootloader.bin

I created the signature.bin with openssl dgst -sha256 -sign private_key.pem -out signature.bin bootloader.bin which gives me perfect 384 bytes signature (same as the 384 bytes RSA-PSS signature result in the signature block format)

I verified the signature by below command openssl dgst -verify public_key.pem -keyform PEM -sha256 -signature signature.bin -binary bootloader.bin

So there is no way the signature is invalid. Is there an issue on this command? Or did I misuse it?

Other Steps to Reproduce

No response

eme-bennytang commented 10 months ago

Any thoughts on this? Any help would be a great help ;)

radimkarnis commented 10 months ago

Hi @eme-bennytang, sorry for not getting to this sooner! I will get you appropriate support as soon as possible.

Harshal5 commented 10 months ago

Hello @eme-bennytang,

It looks like the external signature generated using the above commands does not create a valid RSA-PSS signature, but an RSA signature. Though as you have mentioned above,

which gives me perfect 384 bytes signature (same as the 384 bytes RSA-PSS signature result in the signature block format)

I would like you to re-check the openssl commands used to generate the signature. (openssl dgst -sha256 -sign private_key.pem -out signature.bin bootloader.bin)

One way to make sure that the generated signatures using the above command do not satisfy RSA-PSS signature padding is by generating two signatures using the same command and comparing the signatures. The two signatures should differ as PSS uses random data, thus the two signatures with the same input are different and both can be used to validate the original data.

You can use the below openssl commands to generate a correct RSA-PSS signature:

  1. Generate signing key:

    espsecure.py generate_signing_key --version 2 privateKey.pem

    OR

    openssl genrsa -out privateKey.pem 3072
  2. Generate the hash of the bootloader binary:

    openssl dgst -sha256 -binary bootloader.bin  > hashed_bootloader.bin
  3. Generate signature:

    openssl pkeyutl -sign \
    -in  hashed_bootloader.bin  -inkey privateKey.pem \
    -out signature.bin \
    -pkeyopt digest:sha256 \
    -pkeyopt rsa_padding_mode:pss \
    -pkeyopt rsa_pss_saltlen:32
  4. Extract public key

    espsecure.py extract_public_key --version 2 --keyfile privateKey.pem publicKey.pem

    OR

    openssl rsa -in privateKey.pem -pubout > publicKey.pem
  5. Verify signature:

    openssl pkeyutl -verify \
    -in hashed_bootloader.bin -sigfile signature.bin \
    -pkeyopt rsa_padding_mode:pss \
    -pubin -inkey publicKey.pem \
    -pkeyopt rsa_pss_saltlen:32 \
    -pkeyopt digest:sha256
  6. Finally you can use the generated signature to create and append a signature block to the bootloader binary:

    espsecure.py sign_data --version 2 --pub-key publicKey.pem --signature signature.bin --output bootloader_signed.bin bootloader.bin
eme-bennytang commented 10 months ago

Hi @Harshal5

Thanks for the great help! We have successfully created the required signature (and thus the signature block) using your commands.

I will close this issue. :)