mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
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:
parent
997512ace2
commit
e5f22521da
@ -654,24 +654,97 @@ Secure Boot Best Practices
|
|||||||
Technical Details
|
Technical Details
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
The following sections contain low-level reference descriptions of various Secure Boot elements:
|
The following sections contain low-level reference descriptions of various Secure Boot elements.
|
||||||
|
|
||||||
|
|
||||||
Manual Commands
|
|
||||||
~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
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.
|
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:
|
||||||
|
|
||||||
idf.py secure-sign-data --keyfile ./my_signing_key.pem --output ./image_signed.bin image-unsigned.bin
|
.. 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.
|
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:
|
.. _secure-boot-v2-and-flash-encr:
|
||||||
|
|
||||||
|
@ -436,6 +436,22 @@ def action_extensions(base_actions: Dict, project_path: str) -> Dict:
|
|||||||
sign_data_args += [extra_args['datafile']]
|
sign_data_args += [extra_args['datafile']]
|
||||||
RunTool('espsecure', sign_data_args, args.build_dir)()
|
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:
|
def _parse_efuse_args(ctx: click.core.Context, args: PropertyDict, extra_args: Dict) -> List:
|
||||||
efuse_args = []
|
efuse_args = []
|
||||||
if args.port:
|
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': {
|
'efuse-burn': {
|
||||||
'callback': efuse_burn,
|
'callback': efuse_burn,
|
||||||
'help': 'Burn the eFuse with the specified name.',
|
'help': 'Burn the eFuse with the specified name.',
|
||||||
|
@ -521,6 +521,19 @@ class TestSecureCommands(TestWrapperCommands):
|
|||||||
output = self.call_command(sign_command)
|
output = self.call_command(sign_command)
|
||||||
self.assertIn('Signed', output)
|
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):
|
class TestMergeBinCommands(TestWrapperCommands):
|
||||||
"""
|
"""
|
||||||
|
Loading…
Reference in New Issue
Block a user