Skip to main content
Skip table of contents

Tutorial - SignServer Secure Boot V2 with Espressif ESP32

This tutorial demonstrates how a trusted remote signing process for the Espressif ESP32 microcontroller can be implemented by enabling SignServer code signing infrastructure with trusted certificates issued through EJBCA. 

ESP32 is popular in the IoT community as a foundation for connected devices and its built-in Secure Boot V2 feature prevents unauthorized code from running on the chip. The RSA-based Secure boot scheme (Secure Boot V2) allows the microcontroller to verify the digital signature, which is calculated through the application binary itself, each time it is booted.

The ESP32 development environment comes with a toolchain that enables you to generate and integrate signing functionality during your build process on your local machine. For more information about how the workflow is implemented, refer to the Espressif documentation on Secure Boot V2 and Remote Signing of Images

The following tutorial demonstrates how you configure and enable SignServer in combination with EJBCA to use the Espressif espsecure.py command line program to sign app images & partition tables data for Secure Boot  on a remote system.

The ESP32 Secure Boot V2 concept is part of the overall security features developed by Espressif Systems. For more information, refer to the Espressif documentation on Secure Boot V2.

In this tutorial, you will learn how to:

  • Issue signing certificate using EJBCA
  • Create a signing token in SignServer
  • Configure ESP-IDF and enable Secure Boot
  • Generate remote signing images using SignServer

Prerequisites

To take full advantage of this tutorial, you need to have a basic understanding of the Espressif platform and security concepts. It is assumed that you are familiar and experienced with the ESP32 microcontroller and the ESP-IDF development framework, its system architecture, and the software lifecycle process. You should also understand and be able to apply the basic security functions of the ESP32. 

Before you begin, you also need the following:

Part 1 - Create signer and issue signing certificate

The following steps outline how to create a SignServer signer and issue a signing certificate using the EJBCA Certificate Authority (CA).

To learn how to create a signer and issue a signing certificate, you can also follow steps 1-3 in the tutorial SignServer Container Signing with Cosign.

Step 1 - Issue signing certificate using EJBCA

Use your Certificate Authority (CA) to issue a signing certificate. This tutorial uses the EJBCA CA. To learn how to get started with EJBCA, you can follow the EJBCA Community Docker container, see Quick Start Guide - Start EJBCA Container with Client Certificate Authenticated Access.

The following sections describe how to create basic profiles in EJBCA and issue a digital signing certificate.

Create Certificate Profile

Certificate profiles define the constraints of the certificate, for example, what keys it can use, and what the extensions will be.

To create a certificate profile that the certificate will be issued under, follow these steps:

  1. In EJBCA, under CA Functions, click Certificate Profiles.
  2. Click the bottom row of the List of Certificate Profiles, specify the name PlainSigner, and then click Add.
    The newly created  template is displayed in the list of certificate profiles.
  3. Click Edit for the PlainSigner profile and specify the following:
    • For Available Key Algorithms, select ECDSA.
    • For Validity or end date of the certificate, specify 1y for one-year validity.
    • For Key Usage, clear Non-repudiation and Key encipherment to only use Digital Signature.
    • For Extended Key Usage, clear Use to not use any extended key usage.
  4. Leave the rest of the fields as default and click Save to store the profile.

Create End Entity Profile

To create an end entity profile with information about the holder of the certificate, follow these steps:

  1. In EJBCA, under RA Functions, click End Entity Profiles.
  2. In the Add End Entity Profile field, add a name for the new profile, in this example PlainSigner, and click Add profile.
    The newly created profile is displayed in the list of end entity profiles.
  3. Select the PlainSigner profile, and click Edit End Entity Profile.
  4. Update the following to map the end entity profile to the PlainSigner certificate profile:
    • For Available Certificate Profile, select PlainSigner.
    • For Default Certificate Profile, select PlainSigner.
  5. Click Save to store the updated end entity profile.

Now that you have created the profiles, you can continue and issue the certificate in the next step.

Issue Code Signing Certificate

There are optional ways for issuing the code signing certificate. You can either issue a new token with the certificate using EJBCA, or use an existing key pair for signing if you have one. 

If you are following the ESP-IDF Programming Guide or tutorial in the later step to Configure ESP-IDF and enable Secure Boot, you will generate a key pair locally and should therefore use the Alternative 2: Issue Code Signing Certificate from existing signing key pair to generate the signature token.

Alternative 1: Issue Code Signing Certificate

To issue a 'fresh' token with the certificate using the EJBCA RA UI:

  1. In EJBCA, click RA Web to access the EJBCA RA UI.
  2. Under Request new certificate, select Make New Request.
  3. For Select Request Template Certificate Type, select PlainSigner.
  4. For Key-pair generation, select By the CA.
  5. For Enrollment code, enter a password. This will be the same password that is used to protect the certificate once downloaded.
  6. Click Download PKCS#12 to download and save the generated certificate file as ESPSigner.p12.

Your token is downloaded as an ESPSigner.p12 file that you will upload to SignServer in the next step.

Alternative 2: Issue Code Signing Certificate from existing signing key pair

In some use cases, an existing key pair may already exist for signing. A certificate signing request can then be created with the key pair and a corresponding certificate issued. 

To generate a PKCS#10 request with an existing key pair and then create a PKCS#12 token with the certificate, you can use a tool provided.

The token is stored as an ESPSigner.p12 file that you will upload to SignServer in the next step.

Step 2 - Create signing token in SignServer

Create Crypto Worker

To add a crypto worker in SignServer for storing the private keys, perform the following steps:

  1. In your terminal, copy the ESPSigner.p12 certificate to the SignServer Docker container:

    CODE
    docker cp ESPSigner.p12 <CONTAINER-ID>:opt/signserver/res/test/dss10

     

  2. Go to the SignServer Administration Web Workers page.
  3. Click Add to add a new crypto worker and choose the method From Template.
  4. In the Load From Template list menu, select the keystore-crypto.properties worker template and click Next.
  5. To update the path to the keystore file to reference the ESPSigner.p12 token, specify "WORKERGENID1.KEYSTOREPATH"=/opt/signserver/res/test/dss10/ESPSigner.p12
  6. Click Apply to add the crypto worker.
  7. Click Activate to activate the newly created "CryptoTokenP12".
  8. Enter the enrollment code, and then click Activate.

The crypto token is now created based on the ESPSigner.p12 file.

Create Signing Worker

To create the signing worker in SignServer, perform the following steps:

  1. First, to copy the alias of the crypto token, do the following:

    • On the SignServer Workers page, select the CryptoTokenP12 and then click Crypto Token.

    • On the Crypto Token page, click the alias in the list to display its details.

    • Right-click the alias value in the list and select Copy.

    • Click Workers in the menu bar to go back to the Workers page.
  2. Next, to create the signing worker, do the following:

    1. On the SignServer Workers page, click Add and choose the method From Template

    2. In the Load From Template list menu, select the plainsigner.properties worker template and click Next

    3. On the Add Worker / Load Configuration page, choose the method From Template.
    4. In the Load From Template list menu, select the plainsigner.properties worker template and click Next.
    5. To update to use the alias from the crypto token copied in the previous step, paste the alias as the value for "WORKERGENID1.DEFAULTKEY"
  3. Click Apply to load the configuration.

  4. The newly created signing worker is listed  and active.

Your SignServer environment is now set up to be able to receive signing requests.

Configure Signing Worker for Client Side Hashing with RSA-PSS

To configure the SignServer PlainSigner worker to use client side hashing with the RSA-PSS, perform the following steps:

  1. Select the PlainSigner worker you previously generated.
  2. Click Configuration.
  3. Edit 'SIGNATUREALGORITHM' and add 'Value': 'NONEwithRSAandMGF1'
  4. Click Add and specify a new Property Name: 'CLIENTSIDEHASHING', Value:"true"

Your SignServer worker is now ready for client side hashing with RSA PSS.

Part 2 - Enable ESP32 Secure Boot V2 and sign application 

Once you have completed all the steps in the first part of this tutorial, you can now use your signer to generate a signature and sign an ESP32 application.

Step 1 - Configure ESP-IDF and enable Secure Boot

To enable Secure Boot V2, refer to the instructions provided in the ESP-IDF Programming Guide section How to Enable Secure Boot or follow their tutorial Enabling Secure Boot (V2) on ESP32 Platforms in Development and Production.

Note

If you follow the documentation or the tutorial, you will have generated a key pair locally in the first step. Please use option 2 to generate the signature token as described above. 

Follow the Espressif tutorials to enable Secure Boot on the ESP32, burn the public key to the eFuse, and load the signed Bootloader. 

Once you have tested the entire workflow, you will now switch to the remote signing option. In order to proceed, you should first deselect Secure Boot in the ESP-IDF project configuration menu (idf.py menuconfig).

Step 2 - Generate remote signature 

For production builds, it is 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 following provides a modified espsecure.py command line script that allows to sign app images and partition table data for Secure Boot, on a remote SignServer

To use remote signing, disable the option CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES and build the firmware. The private signing key does not need to be present on the build system.

Once the app image and partition table are built, use the modified Python script espsecure.py to generate the remote Signature using SignServer, according to the following example.

BASH
espsecure.py sign_data --signserver --version 2 --pub-key <your public key in PEM format> --output <sign binary file>  <unsigned input bin file>

Step 3 - Upload image and verify signature with ESP32

To upload the image and display the application output and verify the signature, run the following terminal command:

CODE
idf.py -p <yourPortID>  monitor 

The boot process prints something like the following to display that the application image signature is verified and the application is loaded:

You have now implemented a trustworthy code signing process for ESP32 by integrating SignServer code signing into the boot process and thus secured the code-signing keys.

Next steps

In this tutorial, you learned how code signing can be integrated into the ESP32 enabling Secure Boot V2 software build process and code signing signatures can be generated with SignServer for ESP32 firmware, integrating with EJBCA to issue the required code-signing certificates.  

To find out more about how to use SignServer together with Cosign to create signed container images, see Tutorial - SignServer Container Signing with Cosign.

To learn how to get started with code signing in SignServer, see the Code Signing Technical How-to.

JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.