SUIT B. Moran
Internet-Draft M. Meriac
Intended status: Informational H. Tschofenig
Expires: May 3, 2018 ARM Limited
October 30, 2017

Firmware Manifest Format
draft-moran-suit-manifest-00

Abstract

This specification describes the format of a manifest. A manifest is a bundle of metadata about the firmware for an IoT device, where to find the firmware, the devices to which it applies, and cryptographic information protecting the manifest.

Status of This Memo

This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79.

Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet-Drafts is at https://datatracker.ietf.org/drafts/current/.

Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress."

This Internet-Draft will expire on May 3, 2018.

Copyright Notice

Copyright (c) 2017 IETF Trust and the persons identified as the document authors. All rights reserved.

This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Simplified BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Simplified BSD License.

This document may contain material from IETF Documents or IETF Contributions published or made publicly available before November 10, 2008. The person(s) controlling the copyright in some of this material may not have granted the IETF Trust the right to allow modifications of such material outside the IETF Standards Process. Without obtaining an adequate license from the person(s) controlling the copyright in such materials, this document may not be modified outside the IETF Standards Process, and derivative works of it may not be created outside the IETF Standards Process, except to format it for publication as an RFC or to translate it into languages other than English.


Table of Contents

1. Introduction

A firmware update mechanism is an essential security feature for IoT devices to deal with vulnerabilities. While the transport of firmware images to the devices themselves is important there are already various techniques available, such as the Lightweight Machine-to-Machine (LwM2M) protocol offering device management of IoT devices. Equally important is the inclusion of meta-data about the conveyed firmware image (in the form of a manifest) and the use of end-to-end security protection to detect modifications and (optionally) to make reverse engineering more difficult. End-to-end security allows the author, who builds the firmware image, to be sure that no other party (including potential adversaries) to install firmware updates on IoT devices with adequate privileges. This authorization process is ensured by the use of dedicated symmetric or asymmetric keys installed on the IoT device: for use cases where only integrity protection is required it is sufficient to install a trust anchor on the IoT device. For confidentiality protected firmware images it is additionally required to install either one or multiple symmetric or asymmetric keys on the IoT device. Starting security protection at the author is a risk mitigation technique so firmware images and manifests can be stored on untrusted respositories.

It is assumed that the reader is familiar with the high-level firmware update architecture [Architecture]. This document is structured as follows: In Section 3 we describe the main building blocks of the manifest and [format] contains the description of the ASN.1 of the manifest.

2. Conventions and Terminology

The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “NOT RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119 [RFC2119].

To describe the components of the manifest we use the terms structures and attributes. The manifest has a hierarchical structure and top level components are called structures and the attributes are the components within them.

3. Components

The key components of a manifest are shown in Figure 1 and are explained in the sub-sections below.

 +-------------------+    +-----------+
 | Manifest          |    | Condition |
 +-------------------+    +-----------+
 |  manifestVersion  |    |  type     |
 |  text             |    |  value    |     +-----------+
 |  nonce            |    +-----+-----+     | Directive |
 |  timestamp        |          |           +-----------+
 |  conditions ------+----------+           |  type     |
 |  directives ------+----------------------+  value    |
 |  aliases ---------+-----------------+    +-----------+
 |  dependencies ----+--------------+  |
 |  payloadInfo-+    |              |  |
 +--------------|----+        +-----+--+-----------+
                |             | ResourceReference  |
                |             +--------------------+
                |             |  hash              |
                |             |  uri               |
                |             +--------------------+
                |                       
 +--------------+-----+
 | PayloadInfo        |
 +--------------------+
 |  format            |
 |  digests           |
 |  storageIdentifier |
 |  uris              |
 |  size              |
 |  COSE_Encrypt      |
 +--------------------+

Figure 1: Components of a Manifest.

3.1. Manifest

The Manifest structure is the top-level construct that ties all other structures together. In addition to the structures explained in subsections below it contains

The following CDDL fragment defines the manifest.

Manifest = [
    manifestVersion : uint,
    text : {* int => tstr } / nil,
    nonce : bstr,
    timestamp : uint,
    conditions: [ * condition ],
    directives: [ * directive ] / nil,
    aliases: [ * ResourceReference ] / nil,
    dependencies: [ * ResourceReference ] / nil,
    extensions: { * int => bstr } / nil,
    payloadInfo: ? PayloadInfo
]

In the text section, positive integers define standard text fields, described in this draft. Negative integers define application-specific text fields.

+----------+----------------------------------------------------------+
| Field ID | Description                                              |
+----------+----------------------------------------------------------+
|        1 | A text description of this manifest                      |
|        2 | A text description of the payload                        |
|        3 | A text representation of the target vendor name /        |
|          | manufacturer name                                        |
|        4 | A text representation of the target model number /       |
|          | model name                                               |
+----------+----------------------------------------------------------+

Text fields are never used by the target. They are for informational purposes only.

3.2. PayloadInfo

The PayloadInfo structure contains information about the firmware image.

NOTE: digests needs some form of key derivation to prevent the need for multiple keys. It is expected that the same key be used, with a KDF of some kind, to derive a key from the key used to sign the manifest in the case of COSE_Mac manifests. Where manifests use COSE_Sign at the top level, it is expected that digests will use standard message digest algorithms instead of MAC algorithms.

The following CDDL fragment defines the payload info:

PayloadInfo = [
    format = [
        type: int,
        ? parameters : bstr
    ],
    size: uint,
    storageIdentifier: bstr,
    uris: [*[
        rank: int,
        uri: tstr
    ]] / nil,
    digestAlgorithm = [
        type : int,
        ? parameters: bstr
    ] / nil,
    digests = {* int => bstr} / nil,
    payload = COSE_Encrypt / bstr / nil
]

Digests can contain several kinds of digest:

+--------+------------------------------------------------------------+
| Digest | Description                                                |
| ID     |                                                            |
+--------+------------------------------------------------------------+
|      1 | raw payload digest: the digest of the payload with no      |
|        | modification. This is the digest of the plaintext payload. |
|        | This data is redundant when an AEAD cipher is used.        |
|      2 | installed payload digest: the digest of the payload, post- |
|        | installation. This is most useful in differential updates. |
|      3 | ciphertext digest: The digest of the ciphertext of the     |
|        | payload. This is useful when compressed or differential    |
|        | updates are used, since it can be used to verify the       |
|        | downloaded package prior to decryption.                    |
|      4 | pre-image digest: The digest of the image that must already|
|        | be present in the device in order to install the payload.  |
|        | Useful in differential updates.                            |
+--------+------------------------------------------------------------+

There are several ways that this format can reference a payload:

  1. The payload can be contained by the COSE_Encrypt object. In this case, no URIs are expected, since the payload is contained in COSE_Encrypt.
  2. The COSE_Encrypt object is present, but its ‘ciphertext’ is nil. This means that the ciphertext payload is delivered separately. In this case, at least one URI is expected in uris.
  3. The payload is a bstr. This encapsulates a plaintext payload. A raw payload digest is redundant. No URIs are expected.
  4. The payload is a nil. This means that the plaintext payload is delivered separately. In this case, at least one URI is expected in uris. At least one digest is expected in digests.

Most importantly, however, the PayloadInfo structure contains a reference to the firmware image (in the ‘reference’ attribute) or the image is embedded inside the PayloadInfo structure (within the ‘integrated’ attribute). A referenced image first needs to be fetched by the device before the update can be applied. The ‘reference’ attribute contains a ‘hash’ and a ‘uri’ attribute: the value in the ‘hash’ attribute allows the device to determine whether it has already obtained this firmware image and, since it is included in the digitally signed manifest, it protects the firmware image against modifications. The ‘uri’ attribute references the image.

Encryption is handled by the COSE_Encrypt structure. Most encryption modes are already supported via the COSE_Encrypt structure, only per-device pre-shared keys (or per-device ECDH derivation of pre-shared keys) needs to be described. When using an encrypted image key, shared between many devices, the COSE_Encrypt recipients structure should be filled out as follows:

(assumes AES-CCM-64-128-128; alg, iv will be different for different modes.)

/ recipients / [
    [
        / protected / h'a1011820' / {
            \ alg \ 1:32 \ AES-CCM-64-128-128 \
        } / ,
        / unprotected / {
            / kid / 4:'<uri for key lookup>' /,
            / iv / 5:h'<7 bytes>'
        },
        / ciphertext / nil
    ]
]

This allows a manifest to direct a device to fetch keys from a particular location, identify them by name, or perform another fetch/lookup operation. The exact method for key distribution is out of scope, however an array of COSE_Encrypt objects, each containing a single key object, with a simple recipient object seems appropriate.

This mode is tailored to use cases where a single encrypted firmware image is transmitted to many IoT devices.

3.3. Condition and Directive

The Condition and the Directive structures together allow “If <…> Then <…>” rules to be expressed.

It offers the following functionality:

The following CDDL fragment defines the structure of a condition:

condition = [
    type : int,
    parameters : bstr
]
directive = condition

Some condition types are predefined:

+--------------+------------------------------------------------------+
| Condition ID | Description                                          |
+--------------+------------------------------------------------------+
|            1 | Vendor ID. parameters contains the 128-bit vendor ID |
|              | to match.                                            |
|            2 | Class ID. parameters contains the 128-bit device     |
|              | class ID to match.                                   |
|            3 | Device ID. parameters contains the 128-bit device    |
|              | ID to match.                                         |
|            4 | Best Before. Do not apply the update after time.     |
|              | Parameter is a uint timestamp encoded in the bstr.   |
+--------------+------------------------------------------------------+

Some directive types are predefined:

+--------------+------------------------------------------------------+
| Directive ID | Description                                          |
+--------------+------------------------------------------------------+
|            1 | Apply Immediately. Apply right away. Do not wait.    |
|              | Parameters MUST contain a True or False, serialized  |
|              | in the bstr. Setting this value to False will cause  |
|              | the target to wait until a new manifest arrives with |
|              | Apply Immediately set to true and a dependency on    |
|              | this manifest.                                       |
|            2 | Apply After. Wait until time to apply update.        |
|              | Parameter is serialized as a uint timestamp encoded  |
|              | in the bstr.                                         |
+--------------+------------------------------------------------------+

Application-specific conditions and directives MUST use negative identifiers.

3.4. Aliases and Dependencies

In some situations an IoT device may require more than a single firmware update image. To express the requirement that more than a single image has to be installed on a device the dependencies structure is used, which is of type ResourceReference.

The following CDDL fragment defines the ResourceReference:

ResourceReference = [
    uri : tstr,
    digest : bstr
]

Aliases are used to refer to alternative locations of firmware images. This is useful in environments where organizations cache firmware images (and their corresponding manifests) on premise to avoid the need to fetch imagines from repositories maintained by the developer’s organizations (such a device manufacturer or an OEM).

3.5. Device Identification

A device is identified by at least three identifiers:

3.5.1. Vendor ID

The vendor ID is a 128-bit number that conforms to RFC-4122, type 5. This number is used by the device to verify manifests.

The Vendor ID should be derived from the manufacturer’s domain name using the algorithm defined in Section 4.3 of RFC-4122.

A vendor ID is typically compiled into a firmware image since it is static for the lifetime of the firmware.

3.5.2. Device class ID

The device class is a 128-bit number that conforms to RFC-4122, type 5. This number is used by the client to verify manifests. The Device Class ID SHOULD use the Vendor ID as the namespace, but the ID within the namespace can be arbitrary.

A class ID is also typically compiled into a firmware image since it is static for the lifetime of the firmware.

3.5.3. Device ID

The device ID is also a 128-bit number that conforms to RFC-4122. The device ID can come from a variety of sources. For example, a device may obtain this identifier during the manufacturing phase (together with other configuration information and manufacturer-provided credentials). In this case, we recommend using RFC-4122, type 1, where the node ID is the factory tool ID, which provides traceability of a device back to the origin of manufacture. A device ID can also come from on-device resources, such as device unique-ID registers or device identifiers in CPUs. Our recommendation is to provide unique CPU resources to a generator function similar to the one used for the class_id. In this example, the device_info may be a combination of several components, such as:

Where multiple sources of unique identity are available, they should all be provided to the UUID function, since it combines them to create a single, unique identifier.

3.6. Authentication of manifests

At the top level, manifests are authenticated using either the COSE_Mac or COSE_Sign structures, depending on application. The considerations that apply to encryption keys in PayloadInfo apply equally to the use of Mac keys in COSE_Mac.

3.7. Minimum feature set

Not all devices will support the full feature set described in this RFC. If features become complex enough, it may be necessary to report the features used by a manifest in a bitstring, however this is redundant information, so it is excluded in this draft.

At minimum, targets MUST support the following manifest fields:

  1. manifestVersion, so that the target can tell which version of manifest is in use.
  2. text (this is ignored by the target)
  3. nonce (this is ignored by the target)
  4. timestamp
  5. conditions
  6. payloadInfo

A target attempting to parse a manifest that contains non-nil fields that it does not support SHALL report an error in validation.

At minimum, targets MUST support the ONE of the following payload modes:

  1. digestAlgorithm, digests, bstr
  2. digestAlgorithm, digests, uris, nil payload
  3. COSE_Encrypt, inline ciphertext
  4. COSE_Encrypt, nil ciphertext

4. Manifest CDDL full specification

condition = [
    type : int,
    parameters : bstr
]
directive = condition

ResourceReference = [
    uri : tstr,
    digest : bstr
]

PayloadInfo = [
    format = [
        type: int,
        ? parameters : bstr
    ],
    size: uint,
    storageIdentifier: bstr,
    uris: [*[
        rank: int,
        uri: tstr
    ]] / nil,
    digestAlgorithm = [
        type : int,
        ? parameters: bstr
    ] / nil,
    digests = {* int => bstr} / nil,
    payload = COSE_Encrypt / bstr / nil
]

Manifest = [
    manifestVersion : uint,
    text : {* int => tstr } / nil,
    nonce : bstr,
    timestamp : uint,
    conditions: [ * condition ],
    directives: [ * directive ] / nil,
    aliases: [ * ResourceReference ] / nil,
    dependencies: [ * ResourceReference ] / nil,
    extensions: { * int => bstr } / nil,
    payloadInfo: ? payloadInfo
]

The manifest itself is encapsulated in either a COSE_Mac or a COSE_Sign block.

5. IANA Considerations

Editor’s Note: A few registries would be good to allow easier allocation of new features.

6. Security Considerations

This document is about a manifest format describing and protecting firmware images and as such it is part of a larger solution for offering a standardized way of delivering firmware updates to IoT devices. A more detailed discussion about security can be found in the architecture document [Architecture].

7. Mailing List Information

The discussion list for this document is located at the e-mail address suit@ietf.org. Information on the group and information on how to subscribe to the list is at https://www1.ietf.org/mailman/listinfo/suit

Archives of the list can be found at: https://www.ietf.org/mail-archive/web/suit/current/index.html

8. Acknowledgements

We would like the following persons for their feedback:

We would also like to thank the BOF chairs, Russ Housley and David Waltermire, and the responsible security area director, Kathleen Moriarty, for their support.

9. References

9.1. Normative References

[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997.

9.2. Informative References

[Architecture] Moran, B., "A Firmware Update Architecture for Internet of Things Devices", October 2017.
[format] Moran, B., "Firmware Manifest Format (ASN.1 Format)", July 2017.

Authors' Addresses

Brendan Moran ARM Limited EMail: Brendan.Moran@arm.com
Milosch Meriac ARM Limited EMail: Milosch.Meriac@arm.com
Hannes Tschofenig ARM Limited EMail: hannes.tschofenig@gmx.net