Subject: Re: [Fud] initial comments on draft-moran-fud-manifest-00

From: Brendan Moran <[email-masked]>
Date: Wed, 30 Aug 2017 11:33:32 +0000

Hi Emmanuel,

I have placed comments in-line.

Best Regards,
Brendan

On Wed, 19 July 2017 18:37 UTC, Emmanuel Baccelli wrote:
> =====
> General comments:
> =====
>
> Let's make sure that a minimalistic version of the manifest format is
> applicable
> easily to low-end IoT devices:
> - class 1 devices (RFC7228) with a single MCU,
> - very low bandwidth network connection,
> - may not have an "interoperable" notion of absolute time,
> - …

Agreed. The drafted manifest format should be compatible with this, however there may be compromises, e.g. in terms of the type of cryptography used for signing.

> As additional reference points, let's also look out the (work-in-progress)
> metadata format
> of RIOT images [1], and of MCUBoot images [2] which
> In particular, the whole metadata of a RIOT image fits in less than 200
> bytes.
> A nice goal could thus be that we aim to fit a minimal (but compliant)
> format
> of the manifest within 256bytes.

The default size of the manifest is < 512 bytes, however it is a bit different than the RIOT metadata header. In addition to the contents of the RIOT header, the manifest includes:
- vendor and model identifiers to prevent installation of firmware on the wrong device. These are also used to allow a device manager to identify the provenance of an update.
- a digest identifier to allow for flexibility in digest algorithm
- a URI to allow for flexibility in the distribution of the firmware itself (see comments above)
- a nonce to protect the signature algorithm
- a storage identifier to allow the target device to decide where to store the payload in a system that uses more than one area of firmware (for example if the network stack is updated independent of other components). This is roughly equivalent to start_addr
- a format specifier to allow for more advanced update schemes such as compressed images
- a timestamp for rollback protection

In addition, it uses CMS for proving the authenticity and integrity of the manifest. In the mode we have selected, this includes several additional OIDs and an additional hash.

Manifests are approximately 420 bytes with these features, except using a trivial storage identifier and no reference URI.

If these values are not included in the manifest, the system must imply them in some way, either by being assumed or by being hard-coded. Therefore, I believe that these features are necessary for the manifest to apply broadly to IoT devices.

> # In section 3.1
>
> timestamp:
> If we want to cover the cases when the device has no notion of "now",
> (i.e. is not time-synchronized with the author/server/storage)
> the device will only be able to interpret this field as some kind of
> sequence number. This does not bringing much more information compared to
> the version number field.
> In particular, I'm wondering why the timestamp actually protects from
> downgrade attacks:
> I suppose we trust that newer software will have newer version numbers.
> Is it to cover the case when the version number "wraps around"?

The timestamp is effectively a sequence number for the manifest, however, it is intended to work with a minimum of chances of error. If several firmware authors take turns issuing new firmware for devices, there is a chance for errors when selecting the correct sequence number due to the coordination between different actors. This is even more problematic when a new manifest must be issued for an old firmware (the permitted form of rollback). Timestamps, however, are monotonically increasing and globally synchronized.

While this could be implemented another way, with user-defined sequence numbers, timestamps make it easy to get the sequence number right and hard to get it wrong. They also provide extra features in systems that do have a concept of local time.

> # In section 3.2
>
> I would suggest we add the format type "script".
> We have use cases where modules might be scripts.

I'm happy to add new format types, however "script" is not specific enough without additional information. I suggest that we amend the format as follows:

FormatIdentifier ::= SEQUENCE {
   format          CHOICE {
       enum        ENUMERATED {
           rawBinary(1), hexLocationLengthData(2), elf(3), bsdiff(4)
       },
       objectId    OBJECT IDENTIFIER
   },
   parameters ANY DEFINED BY format OPTIONAL
}

PayloadInfo ::= SEQUENCE {
   formatId      FormatIdentifier,
   encryptionInfo EncryptionInfo OPTIONAL,
   storageIdentifier OCTET STRING,
   size INTEGER,
   payload CHOICE {
       reference    ResourceReference,
       integrated   OCTET STRING
   }
}

This would allow "script" to be descriptive by adding additional information in the parameters section.

> nonce:
> I'm not sure the case of "producing manifests too quickly" with the same
> time-stamp
> is realistic.
> Even if it was, since a nonce is random, the nonce would not help to decide
> which
> firmware is newer.
> However, we could assume that the version number would be lexicographically
> greater
> in the newest firmware.
> Hence, I am unsure what is the function of the nonce.

The purpose of the nonce is to ensure that the same data is never signed twice. This protects the signature algorithm from some classes of attack. On modern hardware, it's quite easy to generate many manifests in a second, so the timestamp is insufficient to guard against multiple signatures of the same data.

> storageIdentifier:
> as per my comments to the architecture draft, I suggest we focus first on
> the case
> where there is only one MCU.
> Should this field be optional?

The behaviour of storageIdentifier is application-specific. It can be used to designate: a firmware module in a multi-module system, for example a bootloader, vs. a main application. It can be used to designate a particular processor in a multi-processor application. The interpretation of the storage identifier is entirely up to the application. This means that it can even represent the start address if that is desired.

> # In section 3.3
>
> "Apply an update only to devices that match the vendorId, classId, deviceId
> attributes"
> is this condition not necessary in all cases?

This was a compound condition. There are situations where you may want to apply an update only with a matching deviceId, there are also situations where you might want to apply an update to a matching vendorId and classId, but to many devices. So, vendorId and classId might be considered to be always mandatory, however, deviceId is optional. However, I dislike giving vendorId and classId their own dedicated entries, because it makes the format more complex to parse and process. Having vendorId and classId in the conditions seems cleaner.

> Conditions on absolute time:
> see my above comments on absolute time, and time synchronization
> requirements that might
> not be met in low-end IoT devices.

Yes, this may be a problem. Presumably, such a device could report an "unimplemented feature" error, etc. Authors of updates need to be sure that they don't use features that aren't implemented on their targets. This will cause a failure, but this should be a graceful failure, since a device will continue to operate unhindered in the architecture described.

> # In section 3.4
>
> Here again I propose to focus on single MCU cases first.

Multiple firmware images does not necessarily imply multiple MCUs. There may be multiple firmware images on a single device. For example, a device with an integrated cryptographic accelerator may require a separate image to update that accelerator. Likewise, there are WiFi IoT devices that download a firmware image to the WiFi chip over SDIO on every boot. These could be distributed as separate images, despite being hosted on a single MCU.

> # In section 3.5.2
> make it optional?

This cannot be optional because it is used by devices to match incoming manifests to their hardware.

> # In section 4.
>
> Do you have an estimate as how many bytes this is over the air for the
> manifest?

The DER-encoded manifest is generally less than 512 bytes. This can vary, depending on content. If a certificate is included, that will increase the size. For secp256r1 curves, a certificate is approximately 650 bytes.
IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.