docs(secure_boot_v2): Mention idf.py and openssl commands to generate and verify signatures

- Adds support for verify_signature command in idf.py

Closes https://github.com/espressif/esptool/issues/942
This commit is contained in:
harshal.patil 2024-08-16 12:13:44 +05:30
parent 997512ace2
commit e5f22521da
No known key found for this signature in database
GPG Key ID: 5B5EC97C35B9A2E5
3 changed files with 133 additions and 9 deletions

View File

@ -654,24 +654,97 @@ Secure Boot Best Practices
Technical Details
-----------------
The following sections contain low-level reference descriptions of various Secure Boot elements:
Manual Commands
~~~~~~~~~~~~~~~
The following sections contain low-level reference descriptions of various Secure Boot elements.
Secure Boot is integrated into the ESP-IDF build system, so ``idf.py build`` will sign an app image, and ``idf.py bootloader`` will produce a signed bootloader if :ref:`CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES` is enabled.
However, it is possible to use the ``idf.py`` tool to make standalone signatures and digests.
However, it is possible to use the ``idf.py`` or the ``openssl`` tool to generate standalone signatures and verify them. Using ``idf.py`` is recommended, but in case you need to generate or verify signatures in non-ESP-IDF environments,
you could also use the ``openssl`` commands as the Secure Boot V2 signature generation is compliant with the standard signing algorithms.
To sign a binary image:
Generating and Verifying signatures using ``idf.py``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. code-block::
1. To sign a binary image:
.. code-block::
idf.py secure-sign-data --keyfile ./my_signing_key.pem --output ./image_signed.bin image-unsigned.bin
Keyfile is the PEM file containing an {IDF_TARGET_SBV2_KEY} private signing key.
2. To verify a signed binary image:
.. code-block::
idf.py secure-verify-signature --keyfile ./my_signing_key.pem image_signed.bin
Keyfile is the PEM file containing an {IDF_TARGET_SBV2_KEY} public/\private signing key.
Generating and Verifying signatures using OpenSSL
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
It is preferred to use the ``idf.py`` tool to generate and verify signatures, but in case you need to perform these operations using OpenSSL, following are the reference commands to do so:
1. Generate digest of the image binary file whose signature needs to be calculated.
.. code-block:: bash
openssl dgst -sha256 -binary BINARY_FILE > DIGEST_BINARY_FILE
2. Generate signature of the image using the above calculated digest.
.. only:: SOC_SECURE_BOOT_V2_RSA
For generating an RSA-PSS signature:
.. code-block:: bash
openssl pkeyutl -sign \
-in DIGEST_BINARY_FILE \
-inkey PRIVATE_SIGNING_KEY \
-out SIGNATURE_FILE \
-pkeyopt digest:sha256 \
-pkeyopt rsa_padding_mode:pss \
-pkeyopt rsa_pss_saltlen:32
.. only:: SOC_SECURE_BOOT_V2_ECC
For generating an ECDSA signature:
.. code-block:: bash
openssl pkeyutl -sign \
-in DIGEST_BINARY_FILE \
-inkey PRIVATE_SIGNING_KEY \
-out SIGNATURE_FILE
3. Verify the generated signature.
.. only:: SOC_SECURE_BOOT_V2_RSA
For verifying an RSA-PSS signature:
.. code-block:: bash
openssl pkeyutl -verify \
-in DIGEST_BINARY_FILE \
-pubin -inkey PUBLIC_SIGNING_KEY \
-sigfile SIGNATURE_FILE \
-pkeyopt rsa_padding_mode:pss \
-pkeyopt rsa_pss_saltlen:32 \
-pkeyopt digest:sha256
.. only:: SOC_SECURE_BOOT_V2_ECC
For verifying an ECDSA signature:
.. code-block:: bash
openssl pkeyutl -verify \
-in DIGEST_BINARY_FILE \
-pubin -inkey PUBLIC_SIGNING_KEY \
-sigfile SIGNATURE_FILE
.. _secure-boot-v2-and-flash-encr:

View File

@ -436,6 +436,22 @@ def action_extensions(base_actions: Dict, project_path: str) -> Dict:
sign_data_args += [extra_args['datafile']]
RunTool('espsecure', sign_data_args, args.build_dir)()
def secure_verify_signature(action: str,
ctx: click.core.Context,
args: PropertyDict,
version: str,
keyfile: str,
**extra_args: str) -> None:
ensure_build_directory(args, ctx.info_name)
verify_signature_args = [PYTHON, '-m', 'espsecure', 'verify_signature']
if version:
verify_signature_args += ['--version', version]
if keyfile:
verify_signature_args += ['--keyfile', keyfile]
if extra_args['datafile']:
verify_signature_args += [extra_args['datafile']]
RunTool('espsecure', verify_signature_args, args.build_dir)()
def _parse_efuse_args(ctx: click.core.Context, args: PropertyDict, extra_args: Dict) -> List:
efuse_args = []
if args.port:
@ -792,6 +808,28 @@ def action_extensions(base_actions: Dict, project_path: str) -> Dict:
},
],
},
'secure-verify-signature': {
'callback': secure_verify_signature,
'help': ('Verify a previously signed binary image, using the ECDSA (V1) or either RSA or ECDSA (V2) public key.'),
'options': [
{
'names': ['--version', '-v'],
'help': ('Version of the secure boot signing scheme to use.'),
'type': click.Choice(['1', '2']),
'default': '2',
},
{
'names': ['--keyfile', '-k'],
'help': ('Public key file for verification. Can be private or public key in PEM format.'),
},
],
'arguments': [
{
'names': ['datafile'],
'nargs': 1,
},
],
},
'efuse-burn': {
'callback': efuse_burn,
'help': 'Burn the eFuse with the specified name.',

View File

@ -521,6 +521,19 @@ class TestSecureCommands(TestWrapperCommands):
output = self.call_command(sign_command)
self.assertIn('Signed', output)
def secure_verify_signature(self):
self.secure_sign_data()
sign_command = [sys.executable,
idf_py_path,
'secure-verify-signature',
'--version',
'2',
'--keyfile',
f'../{self.signing_key}',
'bootloader-signed.bin']
output = self.call_command(sign_command)
self.assertIn('verification successful', output)
class TestMergeBinCommands(TestWrapperCommands):
"""