Merge branch 'feat/add_espsecure_subcommands' into 'master'

feat: Add espsecure subcommands into idf.py

See merge request espressif/esp-idf!29424
This commit is contained in:
Roland Dobai 2024-05-31 18:29:55 +08:00
commit 7b7f73ba2a
6 changed files with 366 additions and 46 deletions

View File

@ -30,12 +30,6 @@ idf_build_get_property(project_dir PROJECT_DIR)
if(CONFIG_SECURE_SIGNED_APPS)
add_custom_target(gen_secure_boot_keys)
if(CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME)
set(secure_apps_signing_version "1")
elseif(CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME OR CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME)
set(secure_apps_signing_version "2")
endif()
if(CONFIG_SECURE_BOOT_V1_ENABLED)
# Check that the configuration is sane
if((CONFIG_SECURE_BOOTLOADER_REFLASHABLE AND CONFIG_SECURE_BOOTLOADER_ONE_TIME_FLASH) OR
@ -68,8 +62,7 @@ if(CONFIG_SECURE_SIGNED_APPS)
if(CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME)
fail_at_build_time(gen_secure_boot_signing_key
"Secure Boot Signing Key ${CONFIG_SECURE_BOOT_SIGNING_KEY} does not exist. Generate using:"
"\tespsecure.py generate_signing_key --version ${secure_apps_signing_version} \
${CONFIG_SECURE_BOOT_SIGNING_KEY}")
"\tidf.py secure-generate-signing-key ${CONFIG_SECURE_BOOT_SIGNING_KEY}")
else()
if(CONFIG_SECURE_BOOT_ECDSA_KEY_LEN_192_BITS)
set(scheme "ecdsa192")
@ -78,8 +71,7 @@ if(CONFIG_SECURE_SIGNED_APPS)
endif()
fail_at_build_time(gen_secure_boot_signing_key
"Secure Boot Signing Key ${CONFIG_SECURE_BOOT_SIGNING_KEY} does not exist. Generate using:"
"\tespsecure.py generate_signing_key --version ${secure_apps_signing_version} \
--scheme ${scheme} ${CONFIG_SECURE_BOOT_SIGNING_KEY}")
"\tidf.py secure-generate-signing-key --scheme ${scheme} ${CONFIG_SECURE_BOOT_SIGNING_KEY}")
endif()
else()
add_custom_target(gen_secure_boot_signing_key)
@ -124,7 +116,7 @@ idf_build_get_property(sdkconfig SDKCONFIG)
idf_build_get_property(python PYTHON)
idf_build_get_property(extra_cmake_args EXTRA_CMAKE_ARGS)
# We cannot pass lists are a parameter to the external project without modifying the ';' spearator
# We cannot pass lists are a parameter to the external project without modifying the ';' separator
string(REPLACE ";" "|" BOOTLOADER_IGNORE_EXTRA_COMPONENT "${BOOTLOADER_IGNORE_EXTRA_COMPONENT}")
externalproject_add(bootloader

View File

@ -5,12 +5,15 @@ Flash Encryption
{IDF_TARGET_ESP32_V3_ONLY:default="", esp32="(ESP32 V3 only)"}
{IDF_TARGET_ENCRYPT_COMMAND:default="espsecure.py encrypt_flash_data --aes_xts", esp32="espsecure.py encrypt_flash_data"}
{IDF_TARGET_ENCRYPT_COMMAND:default="idf.py secure-encrypt-flash-data --aes-xts", esp32="idf.py secure-encrypt-flash-data"}
:link_to_translation:`zh_CN:[中文]`
This is a quick start guide to {IDF_TARGET_NAME}'s flash encryption feature. Using application code as an example, it demonstrates how to test and verify flash encryption operations during development and production.
.. note::
In this guide, most used commands are in the form of ``idf.py secure-<command>``, which is a wrapper around corresponding ``espsecure.py <command>``. The idf.py-based commands provides more user-friendly experience, although may lack some of the advanced functionality of their espsecure.py-based counterparts.
Introduction
------------
@ -359,7 +362,7 @@ To use a host generated key, take the following steps:
.. code-block:: bash
espsecure.py generate_flash_encryption_key my_flash_encryption_key.bin
idf.py secure-generate-flash-encryption-key my_flash_encryption_key.bin
.. only:: SOC_FLASH_ENCRYPTION_XTS_AES_256
@ -367,20 +370,20 @@ To use a host generated key, take the following steps:
.. code-block:: bash
espsecure.py generate_flash_encryption_key my_flash_encryption_key.bin
idf.py secure-generate-flash-encryption-key my_flash_encryption_key.bin
else if :ref:`Size of generated XTS-AES key <CONFIG_SECURE_FLASH_ENCRYPTION_KEYSIZE>` is AES-256 (512-bit key):
.. code-block:: bash
espsecure.py generate_flash_encryption_key --keylen 512 my_flash_encryption_key.bin
idf.py secure-generate-flash-encryption-key --keylen 512 my_flash_encryption_key.bin
.. only:: SOC_FLASH_ENCRYPTION_XTS_AES_128 and not SOC_FLASH_ENCRYPTION_XTS_AES_256 and not SOC_EFUSE_CONSISTS_OF_ONE_KEY_BLOCK
.. code-block:: bash
espsecure.py generate_flash_encryption_key my_flash_encryption_key.bin
idf.py secure-generate-flash-encryption-key my_flash_encryption_key.bin
.. only:: SOC_FLASH_ENCRYPTION_XTS_AES_128 and SOC_EFUSE_CONSISTS_OF_ONE_KEY_BLOCK
@ -388,13 +391,13 @@ To use a host generated key, take the following steps:
.. code-block:: bash
espsecure.py generate_flash_encryption_key my_flash_encryption_key.bin
idf.py secure-generate-flash-encryption-key my_flash_encryption_key.bin
else if :ref:`Size of generated XTS-AES key <CONFIG_SECURE_FLASH_ENCRYPTION_KEYSIZE>` is AES-128 key derived from 128 bits (SHA256(128 bits)):
.. code-block:: bash
espsecure.py generate_flash_encryption_key --keylen 128 my_flash_encryption_key.bin
idf.py secure-generate-flash-encryption-key --keylen 128 my_flash_encryption_key.bin
3. **Before the first encrypted boot**, burn the key into your device's eFuse using the command below. This action can be done **only once**.
@ -996,19 +999,19 @@ Manually encrypting or decrypting files requires the flash encryption key to be
The key file should be a single raw binary file (example: ``key.bin``).
For example, these are the steps to encrypt the file ``build/my-app.bin`` to flash at offset 0x10000. Run espsecure.py as follows:
For example, these are the steps to encrypt the file ``my-app.bin`` to flash at offset 0x10000. Run idf.py as follows:
.. only:: esp32
.. code-block:: bash
espsecure.py encrypt_flash_data --keyfile /path/to/key.bin --address 0x10000 --output my-app-ciphertext.bin build/my-app.bin
idf.py secure-encrypt-flash-data --keyfile /path/to/key.bin --address 0x10000 --output my-app-ciphertext.bin my-app.bin
.. only:: not esp32
.. code-block:: bash
espsecure.py encrypt_flash_data --aes_xts --keyfile /path/to/key.bin --address 0x10000 --output my-app-ciphertext.bin build/my-app.bin
idf.py secure-encrypt-flash-data --aes-xts --keyfile /path/to/key.bin --address 0x10000 --output my-app-ciphertext.bin my-app.bin
The file ``my-app-ciphertext.bin`` can then be flashed to offset 0x10000 using ``esptool.py``. To see all of the command line options recommended for ``esptool.py``, see the output printed when ``idf.py build`` succeeds.
@ -1018,9 +1021,9 @@ The file ``my-app-ciphertext.bin`` can then be flashed to offset 0x10000 using `
.. only:: esp32
If your ESP32 uses non-default :ref:`FLASH_CRYPT_CONFIG value in eFuse <setting-flash-crypt-config>` then you will need to pass the ``--flash_crypt_conf`` argument to ``espsecure.py`` to set the matching value. This will not happen if the device configured flash encryption by itself, but may happen if burning eFuses manually to enable flash encryption.
If your ESP32 uses non-default :ref:`FLASH_CRYPT_CONFIG value in eFuse <setting-flash-crypt-config>` then you will need to pass the ``--flash-crypt-conf`` argument to ``idf.py`` command to set the matching value. This will not happen if the device configured flash encryption by itself, but may happen if burning eFuses manually to enable flash encryption.
The command ``espsecure.py decrypt_flash_data`` can be used with the same options (and different input/output files), to decrypt ciphertext flash contents or a previously encrypted file.
The command ``idf.py decrypt-flash-data`` can be used with the same options (and different input/output files), to decrypt ciphertext flash contents or a previously encrypted file.
.. only:: SOC_SPIRAM_SUPPORTED and not esp32

View File

@ -17,6 +17,9 @@ Secure boot is separate from the :doc:`flash-encryption` feature, and you can us
Enabling secure boot limits your options for further updates of your {IDF_TARGET_NAME}. Make sure to read this document thoroughly and understand the implications of enabling secure boot.
.. note::
In this guide, most used commands are in the form of ``idf.py secure-<command>``, which is a wrapper around corresponding ``espsecure.py <command>``. The idf.py-based commands provides more user-friendly experience, although may lack some of the advanced functionality of their espsecure.py-based counterparts.
Background
----------
@ -92,7 +95,7 @@ How to Enable Secure Boot
3. Set other menuconfig options as desired. Pay particular attention to the ``Bootloader Config`` options, as you can only flash the bootloader once. Then exit menuconfig and save your configuration.
4. When you run ``idf.py build`` for the first time, if the signing key is not found, then an error message will be printed with a command to generate a signing key via ``espsecure.py generate_signing_key``.
4. When you run ``idf.py build`` for the first time, if the signing key is not found, then an error message will be printed with a command to generate a signing key via ``idf.py secure-generate-signing-key``.
.. important::
@ -160,7 +163,7 @@ To enable a reflashable bootloader:
Generating Secure Boot Signing Key
----------------------------------
The build system will prompt you with a command to generate a new signing key via ``espsecure.py generate_signing_key``. This uses the python-ecdsa library, which in turn uses Python's ``os.urandom()`` as a random number source.
The build system will prompt you with a command to generate a new signing key via ``idf.py secure-generate-signing-key``. This uses the python-ecdsa library, which in turn uses Python's ``os.urandom()`` as a random number source.
The strength of the signing key is proportional to the random number source of the system, and the correctness of the algorithm used. For production devices, we recommend generating signing keys from a system with a quality entropy source and using the best available EC key generation utilities.
@ -190,17 +193,17 @@ To extract the public key from the private key:
The path to the public signature verification key needs to be specified in the menuconfig under ``Secure boot public signature verification key`` in order to build the secure bootloader.
After the app image and partition table are built, the build system will print signing steps using ``espsecure.py``:
After the app image and partition table are built, the build system will print signing steps using ``idf.py``:
.. code-block::
espsecure.py sign_data --keyfile PRIVATE_SIGNING_KEY BINARY_FILE
idf.py secure-sign-data --version 1 --keyfile PRIVATE_SIGNING_KEY BINARY_FILE
The above command appends the image signature to the existing binary. You can use the `--output` argument to write the signed binary to a separate file:
.. code-block::
espsecure.py sign_data --keyfile PRIVATE_SIGNING_KEY --output SIGNED_BINARY_FILE BINARY_FILE
idf.py secure-sign-data --version 1 --keyfile PRIVATE_SIGNING_KEY --output SIGNED_BINARY_FILE BINARY_FILE
Secure Boot Best Practices
@ -208,7 +211,7 @@ Secure Boot Best Practices
* Generate the signing key on a system with a quality source of entropy.
* Keep the signing key private at all times. A leak of this key will compromise the secure boot system.
* Do not allow any third party to observe any aspects of the key generation or signing process using ``espsecure.py``. Both processes are vulnerable to timing or other side-channel attacks.
* Do not allow any third party to observe any aspects of the key generation or signing process using ``espsecure.py`` or ``idf.py secure-`` subcommands. Both processes are vulnerable to timing or other side-channel attacks.
* Enable all secure boot options in Secure Boot Configuration. These include flash encryption, disabling of JTAG, disabling BASIC ROM interpreter, and disabling the UART bootloader encrypted flash access.
* Use secure boot in combination with :doc:`flash-encryption` to prevent local readout of the flash contents.
@ -284,13 +287,13 @@ Manual Commands
Secure boot is integrated into the ESP-IDF build system, so ``idf.py build`` will automatically sign an app image if secure boot is enabled. ``idf.py bootloader`` will produce a bootloader digest if menuconfig is configured for it.
However, it is possible to use the ``espsecure.py`` tool to make standalone signatures and digests.
However, it is possible to use the ``idf.py secure-`` subcommands to make standalone signatures and digests.
To sign a binary image:
.. code-block::
espsecure.py sign_data --keyfile ./my_signing_key.pem --output ./image_signed.bin image-unsigned.bin
idf.py secure-sign-data --version 1 --keyfile ./my_signing_key.pem --output ./image_signed.bin image-unsigned.bin
The keyfile is the PEM file containing an ECDSA private signing key.
@ -298,11 +301,11 @@ To generate a bootloader digest:
.. code-block::
espsecure.py digest_secure_bootloader --keyfile ./securebootkey.bin --output ./bootloader-digest.bin build/bootloader/bootloader.bin
idf.py secure-digest-secure-bootloader --keyfile ./securebootkey.bin --output ./bootloader-digest.bin bootloader/bootloader.bin
The keyfile is the 32-byte raw secure boot key for the device.
The output of the ``espsecure.py digest_secure_bootloader`` command is a single file that contains both the digest and the bootloader appended to it. To flash the combined digest plus bootloader to the device:
The output of the ``idf.py secure-digest-secure-bootloader`` command is a single file that contains both the digest and the bootloader appended to it. To flash the combined digest plus bootloader to the device:
.. code-block::

View File

@ -37,6 +37,10 @@ Secure Boot V2
``Secure Boot V2`` is available for ESP32-C3 from ECO3 onwards. To use these options in menuconfig, set :ref:`CONFIG_ESP32C3_REV_MIN` greater than or equal to `Rev 3`.
.. note::
In this guide, most used commands are in the form of ``idf.py secure-<command>``, which is a wrapper around corresponding ``espsecure.py <command>``. The idf.py-based commands provides more user-friendly experience, although may lack some of the advanced functionality of their espsecure.py-based counterparts.
Background
----------
@ -378,7 +382,7 @@ How To Enable Secure Boot V2
5. Set other menuconfig options (as desired). Then exit menuconfig and save your configuration.
6. The first time you run ``idf.py build``, if the signing key is not found then an error message will be printed with a command to generate a signing key via ``espsecure.py generate_signing_key``.
6. The first time you run ``idf.py build``, if the signing key is not found then an error message will be printed with a command to generate a signing key via ``idf.py secure-generate-signing-key``.
.. important::
A signing key generated this way will use the best random number source available to the OS and its Python installation (`/dev/urandom` on OSX/Linux and `CryptGenRandom()` on Windows). If this random number source is weak, then the private key will be weak.
@ -422,7 +426,7 @@ Restrictions After Secure Boot Is Enabled
Generating Secure Boot Signing Key
----------------------------------
The build system will prompt you with a command to generate a new signing key via ``espsecure.py generate_signing_key``.
The build system will prompt you with a command to generate a new signing key via ``idf.py secure-generate-signing-key``.
.. only:: esp32 or SOC_SECURE_BOOT_V2_RSA
@ -465,20 +469,20 @@ Remember that the strength of the Secure Boot system depends on keeping the sign
Remote Signing of Images
------------------------
Signing Using ``espsecure.py``
Signing Using ``idf.py``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
For production builds, it can be good practice to use a remote signing server rather than have the signing key on the build machine (which is the default esp-idf Secure Boot configuration). The espsecure.py command line program can be used to sign app images & partition table data for Secure Boot, on a remote system.
To use remote signing, disable the option :ref:`CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES` and build the firmware. The private signing key does not need to be present on the build system.
After the app image and partition table are built, the build system will print signing steps using espsecure.py::
After the app image and partition table are built, the build system will print signing steps using idf.py::
espsecure.py sign_data BINARY_FILE --version 2 --keyfile PRIVATE_SIGNING_KEY
idf.py secure-sign-data BINARY_FILE --keyfile PRIVATE_SIGNING_KEY
The above command appends the image signature to the existing binary. You can use the `--output` argument to write the signed binary to a separate file::
espsecure.py sign_data --version 2 --keyfile PRIVATE_SIGNING_KEY --output SIGNED_BINARY_FILE BINARY_FILE
idf.py secure-sign-data --keyfile PRIVATE_SIGNING_KEY --output SIGNED_BINARY_FILE BINARY_FILE
Signing Using Pre-calculated Signatures
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -487,7 +491,7 @@ If you have valid pre-calculated signatures generated for an image and their cor
In such cases, the firmware image should be built by disabling the option :ref:`CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES`. This image will be secure-padded and to generate a signed binary use the following command::
espsecure.py sign_data --version 2 --pub-key PUBLIC_SIGNING_KEY --signature SIGNATURE_FILE --output SIGNED_BINARY_FILE BINARY_FILE
idf.py secure-sign-data --pub-key PUBLIC_SIGNING_KEY --signature SIGNATURE_FILE --output SIGNED_BINARY_FILE BINARY_FILE
The above command verifies the signature, generates a signature block (refer to :ref:`signature-block-format`) and appends it to the binary file.
@ -514,7 +518,7 @@ Secure Boot Best Practices
* Generate the signing key on a system with a quality source of entropy.
* Keep the signing key private at all times. A leak of this key will compromise the Secure Boot system.
* Do not allow any third party to observe any aspects of the key generation or signing process using espsecure.py. Both processes are vulnerable to timing or other side-channel attacks.
* Do not allow any third party to observe any aspects of the key generation or signing process using ``idf.py secure-`` commands. Both processes are vulnerable to timing or other side-channel attacks.
* Enable all Secure Boot options in the Secure Boot Configuration. These include flash encryption, disabling of JTAG, disabling BASIC ROM interpreter, and disabling the UART bootloader encrypted flash access.
* Use Secure Boot in combination with :doc:`flash-encryption` to prevent local readout of the flash contents.
@ -536,8 +540,8 @@ Secure Boot Best Practices
* The bootloader should be signed with all the private key(s) that are needed for the life of the device, before it is flashed.
* The build system can sign with at most one private key, user has to run manual commands to append more signatures if necessary.
* You can use the append functionality of ``espsecure.py``, this command would also printed at the end of the Secure Boot V2 enabled bootloader compilation.
espsecure.py sign_data -k secure_boot_signing_key2.pem -v 2 --append_signatures -o signed_bootloader.bin build/bootloader/bootloader.bin
* You can use the append functionality of ``idf.py secure-sign-data``, this command would also printed at the end of the Secure Boot V2 enabled bootloader compilation.
idf.py secure-sign-data -k secure_boot_signing_key2.pem --append_signatures -o signed_bootloader.bin build/bootloader/bootloader.bin
* While signing with multiple private keys, it is recommended that the private keys be signed independently, if possible on different servers and stored separately.
* You can check the signatures attached to a binary using -
espsecure.py signature_info_v2 datafile.bin
@ -595,11 +599,11 @@ 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 secure signed binaries on build is enabled.
However, it is possible to use the ``espsecure.py`` tool to make standalone signatures and digests.
However, it is possible to use the ``idf.py`` tool to make standalone signatures and digests.
To sign a binary image::
espsecure.py sign_data --version 2 --keyfile ./my_signing_key.pem --output ./image_signed.bin image-unsigned.bin
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.

View File

@ -9,6 +9,10 @@ Security
This guide provides an overview of the overall security features available in various Espressif solutions. It is highly recommended to consider this guide while designing the products with the Espressif platform and the ESP-IDF software stack from the **security** perspective.
.. note::
In this guide, most used commands are in the form of ``idf.py secure-<command>``, which is a wrapper around corresponding ``espsecure.py <command>``. The idf.py-based commands provides more user-friendly experience, although may lack some of the advanced functionality of their espsecure.py-based counterparts.
Goals
-----
@ -45,7 +49,7 @@ Secure Boot Best Practices
* Generate the signing key on a system with a quality source of entropy.
* Always keep the signing key private. A leak of this key will compromise the Secure Boot system.
* Do not allow any third party to observe any aspects of the key generation or signing process using ``espsecure.py``. Both processes are vulnerable to timing or other side-channel attacks.
* Do not allow any third party to observe any aspects of the key generation or signing process using ``idf.py secure-`` or ``espsecure.py`` commands. Both processes are vulnerable to timing or other side-channel attacks.
* Ensure that all security eFuses have been correctly programmed, including disabling of the debug interfaces, non-required boot mediums (e.g., UART DL mode), etc.

View File

@ -259,6 +259,134 @@ def action_extensions(base_actions: Dict, project_path: str) -> Dict:
print(f'Merged binary {output} will be created in the build directory...')
RunTool('merge_bin', merge_bin_args, args.build_dir, build_dir=args.build_dir, hints=not args.no_hints)()
def secure_decrypt_flash_data(
action: str,
ctx: click.core.Context,
args: PropertyDict,
aes_xts: bool,
keyfile: str,
output: str,
address: str,
flash_crypt_conf: str,
**extra_args: str) -> None:
ensure_build_directory(args, ctx.info_name)
decrypt_flash_data_args = [PYTHON, '-m', 'espsecure', 'decrypt_flash_data']
if aes_xts:
decrypt_flash_data_args += ['--aes_xts']
if keyfile:
decrypt_flash_data_args += ['--keyfile', keyfile]
if output:
decrypt_flash_data_args += ['--output', output]
if address:
decrypt_flash_data_args += ['--address', address]
if flash_crypt_conf:
decrypt_flash_data_args += ['--flash_crypt_conf', flash_crypt_conf]
if extra_args['encrypted_file']:
decrypt_flash_data_args += [extra_args['encrypted_file']]
RunTool('espsecure', decrypt_flash_data_args, args.build_dir)()
def secure_digest_secure_bootloader(
action: str,
ctx: click.core.Context,
args: PropertyDict,
keyfile: str,
output: str,
iv: str,
**extra_args: str) -> None:
ensure_build_directory(args, ctx.info_name)
digest_secure_bootloader_args = [PYTHON, '-m', 'espsecure', 'digest_secure_bootloader']
if keyfile:
digest_secure_bootloader_args += ['--keyfile', keyfile]
if output:
digest_secure_bootloader_args += ['--output', output]
if iv:
digest_secure_bootloader_args += ['--iv', iv]
if extra_args['image']:
digest_secure_bootloader_args += [extra_args['image']]
RunTool('espsecure', digest_secure_bootloader_args, args.build_dir)()
def secure_encrypt_flash_data(
action: str,
ctx: click.core.Context,
args: PropertyDict,
aes_xts: bool,
keyfile: str,
output: str,
address: str,
flash_crypt_conf: str,
**extra_args: str) -> None:
ensure_build_directory(args, ctx.info_name)
encrypt_flash_data_args = [PYTHON, '-m', 'espsecure', 'encrypt_flash_data']
if aes_xts:
encrypt_flash_data_args += ['--aes_xts']
if keyfile:
encrypt_flash_data_args += ['--keyfile', keyfile]
if output:
encrypt_flash_data_args += ['--output', output]
if address:
encrypt_flash_data_args += ['--address', address]
if flash_crypt_conf:
encrypt_flash_data_args += ['--flash_crypt_conf', flash_crypt_conf]
if extra_args['plaintext_file']:
encrypt_flash_data_args += [extra_args['plaintext_file']]
RunTool('espsecure', encrypt_flash_data_args, args.build_dir)()
def secure_generate_flash_encryption_key(action: str, ctx: click.core.Context, args: PropertyDict, keylen: str, **extra_args: str) -> None:
ensure_build_directory(args, ctx.info_name)
generate_flash_encryption_key_args = [PYTHON, '-m', 'espsecure', 'generate_flash_encryption_key']
if keylen:
generate_flash_encryption_key_args += ['--keylen', keylen]
if extra_args['keyfile']:
generate_flash_encryption_key_args += [extra_args['keyfile']]
RunTool('espsecure', generate_flash_encryption_key_args, args.build_dir)()
def secure_generate_signing_key(action: str, ctx: click.core.Context, args: PropertyDict, version: str, scheme: str, **extra_args: str) -> None:
ensure_build_directory(args, ctx.info_name)
generate_signing_key_args = [PYTHON, '-m', 'espsecure', 'generate_signing_key']
project_desc = _get_project_desc(ctx, args)
ecdsa_scheme = get_sdkconfig_value(project_desc['config_file'], 'CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME')
ecdsa_v2_scheme = get_sdkconfig_value(project_desc['config_file'], 'CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME')
rsa_scheme = get_sdkconfig_value(project_desc['config_file'], 'CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME')
if ecdsa_scheme:
version = '1'
elif ecdsa_v2_scheme or rsa_scheme:
version = '2'
if version:
generate_signing_key_args += ['--version', version]
if scheme:
generate_signing_key_args += ['--scheme', '2']
if extra_args['keyfile']:
generate_signing_key_args += [extra_args['keyfile']]
RunTool('espsecure', generate_signing_key_args, args.build_dir)()
def secure_sign_data(action: str,
ctx: click.core.Context,
args: PropertyDict,
version: str,
keyfile: str,
append_signatures: bool,
pub_key: str,
signature: str,
output: str,
**extra_args: str) -> None:
ensure_build_directory(args, ctx.info_name)
sign_data_args = [PYTHON, '-m', 'espsecure', 'sign_data']
if version:
sign_data_args += ['--version', version]
if keyfile:
sign_data_args += ['--keyfile', keyfile]
if append_signatures:
sign_data_args += ['--append_signatures']
if pub_key:
sign_data_args += ['--pub-key', pub_key]
if signature:
sign_data_args += ['--signature', signature]
if output:
sign_data_args += ['--output', output]
if extra_args['datafile']:
sign_data_args += [extra_args['datafile']]
RunTool('espsecure', sign_data_args, args.build_dir)()
BAUD_AND_PORT = [BAUD_RATE, PORT]
flash_options = BAUD_AND_PORT + [
{
@ -330,6 +458,192 @@ def action_extensions(base_actions: Dict, project_path: str) -> Dict:
],
'dependencies': ['all'], # all = build
},
'secure-decrypt-flash-data': {
'callback': secure_decrypt_flash_data,
'options': [
{
'names': ['--aes-xts', '-x'],
'is_flag': True,
'help': ('Decrypt data using AES-XTS.'),
},
{
'names': ['--keyfile', '-k'],
'help': ('File with flash encryption key.'),
},
{
'names': ['--output', '-o'],
'help': ('Output file for plaintext data.'),
},
{
'names': ['--address', '-a'],
'help': ('Address offset in flash that file was read from.'),
},
{
'names': ['--flash-crypt-conf'],
'help': ('Override FLASH_CRYPT_CONF efuse value (default is 0XF).'),
},
],
'arguments': [
{
'names': ['encrypted_file'],
'nargs': 1,
},
],
},
'secure-digest-secure-bootloader': {
'callback': secure_digest_secure_bootloader,
'help': ('Take a bootloader binary image and a secure boot key, and output a combined'
'digest+binary suitable for flashing along with the precalculated secure boot key.'),
'options': [
{
'names': ['--keyfile', '-k'],
'help': ('256 bit key for secure boot digest.'),
},
{
'names': ['--output', '-o'],
'help': ('Output file for signed digest image.'),
},
{
'names': ['--iv'],
'help': (
'128 byte IV file. Supply a file for testing purposes only, if not supplied an IV will be randomly generated.'
),
},
],
'arguments': [
{
'names': ['image'],
'nargs': 1,
},
],
},
'secure-encrypt-flash-data': {
'callback': secure_encrypt_flash_data,
'help': 'Encrypt some data suitable for encrypted flash (using known key).',
'options': [
{
'names': ['--aes-xts', '-x'],
'is_flag': True,
'help': (
'Encrypt data using AES-XTS if chip supports it.'
),
},
{
'names': ['--keyfile', '-k'],
'help': ('File with flash encryption key.'),
},
{
'names': ['--output', '-o'],
'help': ('Output file for encrypted data.'),
},
{
'names': ['--address', '-a'],
'help': ('Address offset in flash where file will be flashed.'),
},
{
'names': ['--flash-crypt-conf'],
'help': (
'Override FLASH_CRYPT_CONF eFuse value (default is 0XF).'
),
},
],
'arguments': [
{
'names': ['plaintext_file'],
'nargs': 1,
},
],
},
'secure-generate-flash-encryption-key': {
'callback': secure_generate_flash_encryption_key,
'options': [
{
'names': ['--keylen', '-l'],
'help': (
'Length of private key digest file to generate (in bits). 3/4 Coding Scheme requires 192 bit key.'
),
},
],
'arguments': [
{
'names': ['keyfile'],
'nargs': 1,
},
],
},
'secure-generate-signing-key': {
'callback': secure_generate_signing_key,
'help': ('Generate a private key for signing secure boot images as per the secure boot version. Key file is generated in PEM'
'format, Secure Boot V1 - ECDSA NIST256p private key. Secure Boot V2 - RSA 3072, ECDSA NIST256p, ECDSA NIST192p'
'private key.'),
'options': [
{
'names': ['--version', '-v'],
'help': ('Version of the secure boot signing scheme to use.'),
'type': click.Choice(['1', '2']),
'default': '2',
},
{
'names': ['--scheme', '-s'],
'help': ('Scheme of secure boot signing.'),
'type': click.Choice(['rsa3072', 'ecdsa192', 'ecdsa256']),
},
],
'arguments': [
{
'names': ['keyfile'],
'nargs': 1,
},
],
},
'secure-sign-data': {
'callback': secure_sign_data,
'help': ('Sign a data file for use with secure boot. Signing algorithm is deterministic ECDSA w/ SHA-512 (V1) or either RSA-'
'PSS or ECDSA w/ SHA-256 (V2).'),
'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': ('Private key file for signing. Key is in PEM format.'),
},
{
'names': ['--append-signatures', '-a'],
'is_flag': True,
'help': (
'Append signature block(s) to already signed image. Valid only for ESP32-S2.'
),
},
{
'names': ['--pub-key'],
'help': (
'Public key files corresponding to the private key used to generate the pre-calculated signatures. Keys should be in PEM format.'
),
},
{
'names': ['--signature'],
'help': (
'Pre-calculated signatures. Signatures generated using external private keys e.g. keys stored in HSM.'
),
},
{
'names': ['--output', '-o'],
'help': (
'Output file for signed digest image. Default is to sign the input file.'
),
},
],
'arguments': [
{
'names': ['datafile'],
'nargs': 1,
},
],
},
'monitor': {
'callback':
monitor,