Update images from verified source¶
It is becoming very important that a device must not only be safely updated, but also that it can verify if the delivered image is coming from a known source and it was not corrupted introducing some malware.
To achieve this goal, SWUpdate must verify the incoming images. There are several ways to do this. Should the compound image be signed ? Or some parts of it ?
Advantages and disadvantages are described in the following chapter.
Signing the compound image¶
It looks quite straightforward if the whole compound image is signed. However, this has some heavy drawbacks. It is not possible to know if the image is verified until the whole image is loaded. This means that verification can be done after installing the single images instead of doing it before touching the device. This leads to have some uninstall procedure if part of a not verified image is already installed, procedures that cannot be safe in case of power off letting some unwanted piece of software on the device.
Signing the sub-images¶
If each sub-image is signed, the verification is done before calling the corresponding hardware. Only signed images can be installed. Anyway, this remains unbound with the description of the release in sw-description. Even if sw-description is signed, an attacker can mix signed images together generating a new compound image that can be installed as well, because all sub-images are verified.
Combining signing sw-description with hash verification¶
To avoid the described drawbacks, SWUpdate combines signed sw-description with the verification of hashes for each single image. This means that only sw-description generated by a verified source can be accepted by the installer. sw-description contains hashes for each sub-image to verify that each delivered sub-image really belongs to the release.
Choice of algorithm¶
The algorithm chosen to sign and verify the sw-descrription file can be selected via menuconfig. Currently, the following mechanisms are implemented:
- RSA Public / private key. The private key belongs to thebuildsystem, while the public key must be installed on the target.
- CMS using certificates
Key or certificate is passed to SWUpdate with the -k parameter.
Tool to generate keys / certificates¶
The openssl tool is used to generate the keys. This is part of the OpenSSL project. A complete documentation can be found at the openSSL Website.
Usage with RSA PKCS#1.5¶
Generating private and public key¶
First, the private key must be created:
openssl genrsa -aes256 -out priv.pem
This asks for a passphrase. It is possible to retrieve the passhphrase from a file - of course, this must be protected against intrusion.
openssl genrsa -aes256 -passout file:passout -out priv.pem
The private key is used to export the public key with:
openssl rsa -in priv.pem -out public.pem -outform PEM -pubout
“public.pem” contains the key in a format suitable for swupdate. The file can be passed to swupdate at the command line with the -k parameter.
How to sign with RSA¶
Signing the image is very simple:
openssl dgst -sha256 -sign priv.pem sw-description > sw-description.sig
Usage with certificates and CMS¶
Generating self-signed certificates¶
openssl req -x509 -newkey rsa:4096 -nodes -keyout mycert.key.pem \
-out mycert.cert.pem -subj "/O=SWUpdate /CN=target"
Check the documentation for more information about parameters. The “mycert.key.pem” contains the private key and it is used for signing. It is not delivered on the target.
The target must have “mycert.cert.pem” installed - this is used by SWUpdate for verification.
Using PKI issued certificates¶
It is also possible to use PKI issued code signing certificates. However, SWUpdate uses OpenSSL library for handling CMS signatures and the library requires the following attributes to be set on the signing certificate:
keyUsage=digitalSignature
extendedKeyUsage=emailProtection
It is also possible to completelly disable signing certificate key usage checking if this requirement cannot be satisfied. This is controlled by CONFIG_CMS_IGNORE_CERTIFICATE_PURPOSE configuration option.
How to sign with CMS¶
Signing the image is simple as in the previous case:
openssl cms -sign -in sw-description -out sw-description.sig -signer mycert.cert.pem \
-inkey mycert.key.pem -outform DER -nosmimecap -binary
Building a signed SWU image¶
There are two files, sw-description and its signature sw-description.sig. The signature file must always directly follow the description file.
Each image inside sw-description must have the attribute “sha256”, with the SHA256 sum of the image. If an image does not have the sha256 attribute, the whole compound image results as not verified and SWUpdate stops with an error before starting to install.
A simple script to create a signed image can be:
#!/bin/bash
MODE="RSA"
PRODUCT_NAME="myproduct"
CONTAINER_VER="1.0"
IMAGES="rootfs kernel"
FILES="sw-description sw-description.sig $IMAGES"
#if you use RSA
if [ x"$MODE" == "xRSA" ]; then
openssl dgst -sha256 -sign priv.pem sw-description > sw-description.sig
else
openssl cms -sign -in sw-description -out sw-description.sig -signer mycert.cert.pem \
-inkey mycert.key.pem -outform DER -nosmimecap -binary
fi
for i in $FILES;do
echo $i;done | cpio -ov -H crc > ${PRODUCT_NAME}_${CONTAINER_VER}.swu
Example for sw-description with signed image¶
The example applies to a Beaglebone, installing Yocto images:
software =
{
version = "0.1.0";
hardware-compatibility: [ "revC"];
images: (
{
filename = "core-image-full-cmdline-beaglebone.ext3";
device = "/dev/mmcblk0p2";
type = "raw";
sha256 = "43cdedde429d1ee379a7d91e3e7c4b0b9ff952543a91a55bb2221e5c72cb342b";
}
);
scripts: (
{
filename = "test.lua";
type = "lua";
sha256 = "f53e0b271af4c2896f56a6adffa79a1ffa3e373c9ac96e00c4cfc577b9bea5f1";
}
);
}
Running SWUpdate with signed images¶
Verification is activated by setting CONFIG_SIGNED_IMAGES in SWUpdate’s configuration. If activated, SWUpdate will always check the compound image. For security reasons, it is not possible to disable the check at runtime. The -k parameter (public key file) is mandatory and the program stops if the public key is not passed.