Creating a manifest
The manifest is an ASN.1-encoded DER format that contains all the information a device needs to validate, download and install a firmware update.
The manifest tool is a cross-platform Python-based command-line interface (CLI) tool that lets you create and sign manifests to use in update campaigns.
The manifest provides the device with:
- The vendor and the class IDs of the target devices.
- The name of the component for which the update is intended.
- The version, digest, size and format of the candidate firmware.
- The URL using which the device downloads the candidate firmware.
- The priority of the update.
- A signature the device uses to validate and authenticate the manifest.
The device receives the manifest, validates the manifest's authenticity and parses the information provided in the manifest.
Based on the information provided in the manifest, the device verifies that:
- The update is a new firmware version.
- The firmware image is compatible with the device based on the vendor and class IDs (device make and model identifiers).
If the device verifies the manifest successfully, the device starts to process the update request. Otherwise, the device rejects the update.
This page explains how to create manifests for various images types using the manifest tool in production mode.
Note: The manifest-dev-tool tool lets you run a simplified end-to-end update campaign in developer mode.
For more information about the manifest tool CLI commands, see the manifest tool documentation.
Prerequisites
-
Python virtual environment (recommended).
-
To install the manifest tool, run:
pip install manifest-tool
Creating a firmware update manifest
To create a manifest for a firmware update of a device's main component:
-
Create a manifest configuration file, called
manifest.yaml
, and populate it:vendor: vendor-id: <Vendor ID> device: class-id: <Class ID> priority: 1 payload: url: <Payload URL> file-path: <Payload path> format: raw-binary component: MAIN
Where:
<Vendor ID>
is the device Vendor ID you provisioned during the factory process step.<Class ID>
is the device Class ID you provisioned during the factory process step.<Payload URL>
is the URL of the image that you copy from Device Management Portal after you upload the image to Device Management.<Payload path>
is the path to your local copy of the uploaded binary. For example,BUILD/<target>/<toolchain>/mbed-cloud-client-example_update.bin
.
-
Create a manifest file:
manifest-tool create --config manifest.yaml --key <PRIVATE_KEY> --fw-version <NEW_VERSION> --output <OUTPUT_MANIFEST_FILE>
Where:
<PRIVATE_KEY>
is the path to your update private key.<NEW_VERSION>
is the version number of the new firmware image in semantic versioning (SemVer) format.<OUTPUT_MANIFEST_FILE>
is the name you'd like to give to your manifest file; for example,manifest.bin
.
Creating a component update manifest
Device Management lets you update components different from the device's main firmware image, such as wireless connectivity modules, embedded sensors or different partitions or packages in Linux-based devices; for example, a BLE stack running on a coprocessor. For more information about updating components, see Component update.
To create a manifest for a firmware update of a device component:
-
Create a manifest configuration file, called
manifest.yaml
, and populate it:vendor: vendor-id: <Vendor ID> device: class-id: <Class ID> priority: 1 payload: url: <Payload URL> file-path: <Payload path> format: raw-binary component: <COMP_NAME>
Where:
<Vendor ID>
is the device Vendor ID you provisioned during the factory process step.<Class ID>
is the device Class ID you provisioned during the factory process step.<Payload URL>
is the URL of the image you upload to Device Management.<Payload path>
is the path to your local copy of the uploaded binary. For example,BUILD/<target>/<toolchain>/mbed-cloud-client-example_update.bin
.<COMP_NAME>
is the name of the component, as defined on the device.
-
Create the manifest file, passing the new component version in the command-line argument:
manifest-tool create --config manifest.yaml --key <PRIVATE_KEY> --fw-version <COMP_NEW_VERSION> --output <OUTPUT_MANIFEST_FILE>
Where:
<PRIVATE_KEY>
is the path to your update private key.<COMP_NEW_VERSION>
is the version number of the new firmware image in semantic versioning (SemVer) format.<OUTPUT_MANIFEST_FILE>
is the name you'd like to give to your manifest file; for example,manifest.bin
.
Creating a combined update manifest
A combined update lets you update multiple images on the device simultaneously.
To enable running a combined update on your devices, you must define a device component that consists of the relevant subcomponents that need to be updated together, as explained in Implementing combined update.
Use manifest-package-tool
to create a combined package, which groups together the images that need to be updated simultaneously and provides the device with data about the images, before creating the manifest for your campaign.
To create a combined package and a manifest for a combined update:
-
Create a combined package configuration file, called
combined_package_config.yaml
, and populate it:images: - file_name: <Image Path> sub_comp_name: <Image Identifier> vendor_data: <Image Vendor Data> - file_name: <Image Path> sub_comp_name: <Image Identifier> vendor_data: <Image Vendor Data>
Where:
-
<Image Path>
is the path to your local firmware image. For example,BUILD/<target>/<toolchain>/first_image.bin
. -
<Image Identifier>
This is the namemanifest-package-tool
gives to the firmware image file in the combined package. The client expects the name of each image in the package to correspond to a subcomponent (sub_comp_name
) defined on the device.For more information, see Implementing combined update.
-
<Image Vendor Data>
is the Vendor data of the firmware image.
-
-
Create the combined package:
manifest-package-tool create --config combined_package_config.yaml --output combined_package
-
Instead of uploading an individual firmware image, upload the compackage to Device Management Portal as described in Uploading the firmware image.
-
Create a manifest configuration file, called
manifest.yaml
, and populate it:vendor: vendor-id: <Vendor ID> device: class-id: <Class ID> priority: 1 payload: url: <Combined package URL> file-path: <Combined package path> format: <encrypted-combined or combined> component: <COMP_NAME>
Where:
<Vendor ID>
is the device Vendor ID you provisioned during the factory process step.<Class ID>
is the device Class ID you provisioned during the factory process step.<Combined package URL>
is the URL of the combined package you upload to Device Management.<Combined package path>
is the path to your local copy of the uploaded combined package.<COMP_NAME>
is the name of the component, as defined on the device. If the component is main component - setMAIN
value to this field.
-
Create the manifest file, passing the new component version in the command-line argument:
manifest-tool create --config manifest.yaml --key <PRIVATE_KEY> --fw-version <COMP_NEW_VERSION> --output <OUTPUT_MANIFEST_FILE>
Where:
<PRIVATE_KEY>
is the path to your update private key.<COMP_NEW_VERSION>
is the version number of the new firmware image in semantic versioning (SemVer) format.<OUTPUT_MANIFEST_FILE>
is the name you'd like to give to your manifest file; for example,manifest.bin
.
Creating a delta update manifest
To update a deployed device's firmware, you can use a delta update campaign instead of a full update campaign.
A delta patch contains the information necessary to reconstruct the new image from the old one. This means you only need to transmit the delta, not a full new image, to the device. Delta updates can save bandwidth and energy for NarrowBand-Internet of Things (NB-IoT) devices, or when installing large firmware images with only small code changes. Using a delta image can also reduce the amount of time needed for an update campaign.
To create a manifest for a delta patch update:
-
Generate a delta patch using the manifest-delta-tool:
manifest-delta-tool --current-fw <current image> --new-fw <new image> --output delta-patch.bin
Where:
<current image>
is the path to the currently installed firmware image.<new image>
is the path to the candidate image.
-
Instead of uploading a firmware image, upload the delta patch to Device Management Portal as described in Uploading the firmware image.
-
Create a manifest configuration file, called
manifest.yaml
, and populate it:vendor: vendor-id: <Vendor ID> device: class-id: <Class ID> priority: 1 payload: url: <Payload URL> file-path: <Payload path> format: arm-patch-stream component: <MAIN>
Where:
<Vendor ID>
is the device Vendor ID you provisioned during the factory process step.<Class ID>
is the device Class ID you provisioned during the factory process step.<Payload URL>
is the URL of the image that you copy from Device Management Portal after you upload the image to Device Management..<Payload path>
is the path to your local copy of the uploadeddelta-patch.bin
file.
-
Create a manifest file:
manifest-tool create --config manifest.yaml --key <PRIVATE_KEY> --fw-version <NEW_VERSION> --output <OUTPUT_MANIFEST_FILE>
Where:
<PRIVATE_KEY>
is the path to your update private key.<NEW_VERSION>
is the version number of the new firmware image in semantic versioning (SemVer) format.<OUTPUT_MANIFEST_FILE>
is the name you'd like to give to your manifest file; for example,manifest.bin
.
Creating an encrypted firmware image manifest
Device Management lets you encrypt firmware images you upload to use in firmware update campaigns. This security feature protects your campaign from attackers who might try to intercept and read the firmware.
Note: The cloud-encrypted image feature is supported in Device Management Client version 4.10 and higher and manifest tool version 2.3.0 and higher.
When you choose the cloud-encrypted image option, Device Management encrypts the image you upload and provides you with the encrypted image's URL, digest and image size, which you must include in the manifest.
To create a manifest for an encrypted firmware update:
-
Toggle the Image file encryption switch when you upload the firmware image.
-
Create a manifest configuration file, called
manifest.yaml
, and populate it:vendor: vendor-id: <Vendor ID> device: class-id: <Class ID> priority: 1 payload: url: <Payload URL> file-path: <Payload path> format: encrypted-raw encrypted: digest: <Encrypted image digest> size: <Encrypted image size> component: <MAIN>
Where:
<Vendor ID>
is the device Vendor ID you provisioned during the factory process step.<Class ID>
is the device Class ID you provisioned during the factory process step.<Payload URL>
is the URL of the image that you copy from Device Management Portal after you upload the image to Device Management.<Payload path>
is the path to your local copy of the uploaded binary. For example,BUILD/<target>/<toolchain>/mbed-cloud-client-example_update.bin
.<Encrypted image digest>
is the digest of the encrypted image that you copy from Device Management Portal after you upload the image to Device Management.<Encrypted image size>
is the size of the encrypted image that you copy from Device Management Portal after you upload the image to Device Management.
-
Create a manifest file:
manifest-tool create --config manifest.yaml --key <PRIVATE_KEY> --fw-version <NEW_VERSION> --output <OUTPUT_MANIFEST_FILE>
Where:
<PRIVATE_KEY>
is the path to your update private key.<NEW_VERSION>
is the version number of the new firmware image in semantic versioning (SemVer) format.<OUTPUT_MANIFEST_FILE>
is the name you'd like to give to your manifest file; for example,manifest.bin
.
Creating a manifest that uses external signing tool
You can use a hardware security module (HSM) to perform signing operations in production. To use an HSM for signing, the manifest tool can call an external signing tool:
<tool> <digest algorithm> <key identifier> <input file> <output file>
The manifest tool writes the data to sign to the <input file>
before the script is called.
The manifest tool reads the <output file>
to find the signature after the script finishes.
Both files should be in raw, binary form.
This guide gives two tool examples of the signing tool process:
- OpenSSL as an external signing tool.
- OpenSC's
pkcs11-tool
as a digest calculator andpkcs15-crypt
as a signing tool.
We present both of these examples as bash scripts.
Signing with OpenSSL
Note: We provide OpenSSL signing tool instructions only as an example. The security of the OpenSSL solution is identical to that of using the manifest tool's internal signing feature. This is an example of how to integrate the manifest tool with an external signing tool.
Please adapt these instructions for use with your external signing tool, for example, an HSM or a secure token.
-
Create the following script which is a wrapper for OpenSSL:
openssl-sign.sh:
#!/usr/bin/env bash $ openssl dgst -binary -"$1" -keyform PEM -sign "$2" -out "$4" "$3"
Parameters:
- $1: Digest algorithm.
- $2: Key identifier.
- $3: Input file.
- $4: Output file.
-
Generate an ECDSA keypair and a self-signed certificate:
openssl ecparam -genkey -name prime256v1 -out key.pem openssl req -new -sha256 -key key.pem -out csr.csr openssl req -x509 -sha256 -days 365 -key key.pem -in csr.csr -outform der -out certificate.der
-
Create a manifest configuration file, called
manifest.yaml
, based on the instructions provided in Creating a firmware update manifest section. -
Add to this configuration file the path to the external signing tool:
signing-tool: <A path to an external signing tool>
-
Create the manifest file:
manifest-tool create --config manifest.yaml --key <PRIVATE_KEY> --fw-version <NEW_VERSION> --output <OUTPUT_MANIFEST_FILE>
Where:
<PRIVATE_KEY>
is the path to your update private key.<NEW_VERSION>
is the version number of the new firmware image in semantic versioning (SemVer) format.<OUTPUT_MANIFEST_FILE>
is the name you'd like to give to your manifest file; for example,manifest.bin
.
Signing with a secure token
Please adapt these instructions for your external signing tool, such as an HSM or secure token.
-
Create the following script which is a wrapper for PKCS11/PKCS15:
#!/usr/bin/env bash if [ "$1" = "sha256" ]; then DGST15="sha-256" DGST11="SHA256" fi SHA=$(pkcs11-tool --hash -m "$DGST11" -i "$3" | xxd -ps -c 64) pkcs15-crypt -s -i <(echo "$SHA" | xxd -r -ps) --$DGST15 -k "$2" -f openssl -o "$4"
-
Prepare the secure token:
- Generate a new ECDSA secp256r1 keypair with signature permissions (optional if key already exists).
- Generate a certificate for the selected keypair (optional if certificate already exists).
- Export the certificate from the token.
- Convert the certificate to DER with OpenSSL:
openssl x509 -inform PEM -in <PEM certificate> -outform DER -out <DER certificate>
-
Create the manifest file:
manifest-tool create --config manifest.yaml --key <PRIVATE_KEY> --fw-version <NEW_VERSION> --output <OUTPUT_MANIFEST_FILE>
Where:
<PRIVATE_KEY>
is the key identifier of the signing key on the secure token.<NEW_VERSION>
is the version number of the new firmware image in semantic versioning (SemVer) format.<OUTPUT_MANIFEST_FILE>
is the name you'd like to give to your manifest file; for example,manifest.bin
.