RFC 9124

A Manifest Information Model for Firmware Updates in Internet of Things (IoT) Devices

πŸ“… published January 2022, from ietf

A Manifest Information Model for Firmware Updates in Internet of Things (IoT) Devices

Part 1 of 8 πŸŽ€

okay bestie, so this is RFC 9124 πŸ¦‹ It's an Informational doc, which means it's published for info and is NOT a Standards Track spec. It came out in January 2022 from the IETF, with ISSN 2070-1721. The authors are B. Moran and H. Tschofenig, both from Arm Limited, and H. Birkholz from Fraunhofer SIT. The title block doesn't list anything it obsoletes or updates, so it doesn't replace or patch any older RFC πŸ’…

Abstract ✨

Vulnerabilities in IoT devices have made it super clear that we need a reliable, secure firmware update mechanism that still works on constrained devices 😭 To keep devices working and secure for their whole service life, the update mechanism has to fix vulnerabilities, update configuration settings, and add new functionality 🌸

One piece of that firmware update is a concise, machine-processable metadata document, aka a manifest. It describes the firmware image(s) and gives them appropriate protection πŸ” This document describes the information the manifest has to contain 🧚

Status of This Memo

This document is not an Internet Standards Track specification. It's published for informational purposes 🌈

This document is a product of the Internet Engineering Task Force (IETF). It represents the consensus of the IETF community, received public review, and was approved for publication by the Internet Engineering Steering Group (IESG). Not every document the IESG approves is a candidate for any level of Internet Standard, so see Section 2 of RFC 7841 for that 🫢

Info about the current status of this document, any errata, and how to send feedback is at https://www.rfc-editor.org/info/rfc9124 ✨

Copyright (c) 2022 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. Please read these carefully, because they describe your rights and restrictions for this document. Code Components extracted from this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions, and they come without warranty as described in the Revised BSD License πŸŽ€

Table of Contents

   1.  Introduction
   2.  Requirements and Terminology
     2.1.  Requirements Notation
     2.2.  Terminology
   3.  Manifest Information Elements
     3.1.  Version ID of the Manifest Structure
     3.2.  Monotonic Sequence Number
     3.3.  Vendor ID
     3.4.  Class ID
       3.4.1.  Example 1: Different Classes
       3.4.2.  Example 2: Upgrading Class ID
       3.4.3.  Example 3: Shared Functionality
       3.4.4.  Example 4: Rebranding
     3.5.  Precursor Image Digest Condition
     3.6.  Required Image Version List
     3.7.  Expiration Time
     3.8.  Payload Format
     3.9.  Processing Steps
     3.10. Storage Location
       3.10.1.  Example 1: Two Storage Locations
       3.10.2.  Example 2: Filesystem
       3.10.3.  Example 3: Flash Memory
     3.11. Component Identifier
     3.12. Payload Indicator
     3.13. Payload Digests
     3.14. Size
     3.15. Manifest Envelope Element: Signature
     3.16. Additional Installation Instructions
     3.17. Manifest Text Information
     3.18. Aliases
     3.19. Dependencies
     3.20. Encryption Wrapper
     3.21. XIP Address
     3.22. Load-Time Metadata
     3.23. Runtime Metadata
     3.24. Payload
     3.25. Manifest Envelope Element: Delegation Chain
   4.  Security Considerations
     4.1.  Threat Model
     4.2.  Threat Descriptions
       4.2.1.  THREAT.IMG.EXPIRED: Old Firmware
       4.2.2.  THREAT.IMG.EXPIRED.OFFLINE: Offline Device + Old
               Firmware
       4.2.3.  THREAT.IMG.INCOMPATIBLE: Mismatched Firmware
       4.2.4.  THREAT.IMG.FORMAT: The Target Device Misinterprets the
               Type of Payload
       4.2.5.  THREAT.IMG.LOCATION: The Target Device Installs the
               Payload to the Wrong Location
       4.2.6.  THREAT.NET.REDIRECT: Redirection to Inauthentic Payload
               Hosting
       4.2.7.  THREAT.NET.ONPATH: Traffic Interception
       4.2.8.  THREAT.IMG.REPLACE: Payload Replacement
       4.2.9.  THREAT.IMG.NON_AUTH: Unauthenticated Images
       4.2.10. THREAT.UPD.WRONG_PRECURSOR: Unexpected Precursor Images
       4.2.11. THREAT.UPD.UNAPPROVED: Unapproved Firmware
       4.2.12. THREAT.IMG.DISCLOSURE: Reverse Engineering of Firmware
               Image for Vulnerability Analysis
       4.2.13. THREAT.MFST.OVERRIDE: Overriding Critical Manifest
               Elements
       4.2.14. THREAT.MFST.EXPOSURE: Confidential Manifest Element
               Exposure
       4.2.15. THREAT.IMG.EXTRA: Extra Data after Image
       4.2.16. THREAT.KEY.EXPOSURE: Exposure of Signing Keys
       4.2.17. THREAT.MFST.MODIFICATION: Modification of Manifest or
               Payload prior to Signing
       4.2.18. THREAT.MFST.TOCTOU: Modification of Manifest between
               Authentication and Use
     4.3.  Security Requirements
       4.3.1.  REQ.SEC.SEQUENCE: Monotonic Sequence Numbers
       4.3.2.  REQ.SEC.COMPATIBLE: Vendor, Device-Type Identifiers
       4.3.3.  REQ.SEC.EXP: Expiration Time
       4.3.4.  REQ.SEC.AUTHENTIC: Cryptographic Authenticity
       4.3.5.  REQ.SEC.AUTH.IMG_TYPE: Authenticated Payload Type
       4.3.6.  REQ.SEC.AUTH.IMG_LOC: Authenticated Storage Location
       4.3.7.  REQ.SEC.AUTH.REMOTE_LOC: Authenticated Remote Payload
       4.3.8.  REQ.SEC.AUTH.EXEC: Secure Execution
       4.3.9.  REQ.SEC.AUTH.PRECURSOR: Authenticated Precursor Images
       4.3.10. REQ.SEC.AUTH.COMPATIBILITY: Authenticated Vendor and
               Class IDs
       4.3.11. REQ.SEC.RIGHTS: Rights Require Authenticity
       4.3.12. REQ.SEC.IMG.CONFIDENTIALITY: Payload Encryption
       4.3.13. REQ.SEC.ACCESS_CONTROL: Access Control
       4.3.14. REQ.SEC.MFST.CONFIDENTIALITY: Encrypted Manifests
       4.3.15. REQ.SEC.IMG.COMPLETE_DIGEST: Whole Image Digest
       4.3.16. REQ.SEC.REPORTING: Secure Reporting
       4.3.17. REQ.SEC.KEY.PROTECTION: Protected Storage of Signing
               Keys
       4.3.18. REQ.SEC.KEY.ROTATION: Protected Storage of Signing Keys
       4.3.19. REQ.SEC.MFST.CHECK: Validate Manifests prior to
               Deployment
       4.3.20. REQ.SEC.MFST.TRUSTED: Construct Manifests in a Trusted
               Environment
       4.3.21. REQ.SEC.MFST.CONST: Manifest Kept Immutable between
               Check and Use
     4.4.  User Stories
       4.4.1.  USER_STORY.INSTALL.INSTRUCTIONS: Installation
               Instructions
       4.4.2.  USER_STORY.MFST.FAIL_EARLY: Fail Early
       4.4.3.  USER_STORY.OVERRIDE: Override Non-critical Manifest
               Elements
       4.4.4.  USER_STORY.COMPONENT: Component Update
       4.4.5.  USER_STORY.MULTI_AUTH: Multiple Authorizations
       4.4.6.  USER_STORY.IMG.FORMAT: Multiple Payload Formats
       4.4.7.  USER_STORY.IMG.CONFIDENTIALITY: Prevent Confidential
               Information Disclosures
       4.4.8.  USER_STORY.IMG.UNKNOWN_FORMAT: Prevent Devices from
               Unpacking Unknown Formats
       4.4.9.  USER_STORY.IMG.CURRENT_VERSION: Specify Version Numbers
               of Target Firmware
       4.4.10. USER_STORY.IMG.SELECT: Enable Devices to Choose between
               Images
       4.4.11. USER_STORY.EXEC.MFST: Secure Execution Using Manifests
       4.4.12. USER_STORY.EXEC.DECOMPRESS: Decompress on Load
       4.4.13. USER_STORY.MFST.IMG: Payload in Manifest
       4.4.14. USER_STORY.MFST.PARSE: Simple Parsing
       4.4.15. USER_STORY.MFST.DELEGATION: Delegated Authority in
               Manifest
       4.4.16. USER_STORY.MFST.PRE_CHECK: Update Evaluation
       4.4.17. USER_STORY.MFST.ADMINISTRATION: Administration of
               Manifests
     4.5.  Usability Requirements
       4.5.1.  REQ.USE.MFST.PRE_CHECK: Pre-installation Checks
       4.5.2.  REQ.USE.MFST.TEXT: Descriptive Manifest Information
       4.5.3.  REQ.USE.MFST.OVERRIDE_REMOTE: Override Remote Resource
               Location
       4.5.4.  REQ.USE.MFST.COMPONENT: Component Updates
       4.5.5.  REQ.USE.MFST.MULTI_AUTH: Multiple Authentications
       4.5.6.  REQ.USE.IMG.FORMAT: Format Usability
       4.5.7.  REQ.USE.IMG.NESTED: Nested Formats
       4.5.8.  REQ.USE.IMG.VERSIONS: Target Version Matching
       4.5.9.  REQ.USE.IMG.SELECT: Select Image by Destination
       4.5.10. REQ.USE.EXEC: Executable Manifest
       4.5.11. REQ.USE.LOAD: Load-Time Information
       4.5.12. REQ.USE.PAYLOAD: Payload in Manifest Envelope
       4.5.13. REQ.USE.PARSE: Simple Parsing
       4.5.14. REQ.USE.DELEGATION: Delegation of Authority in Manifest
   5.  IANA Considerations
   6.  References
     6.1.  Normative References
     6.2.  Informative References
   Acknowledgements
   Authors' Addresses

1. Introduction ✨

Vulnerabilities in IoT devices have made it super clear that we need a reliable, secure firmware update mechanism that still works on constrained devices 😭 To keep devices working and secure for their whole service life, the update mechanism has to fix vulnerabilities, update configuration settings, and add new functionality 🌸

One piece of that firmware update is a concise, machine-processable metadata document, aka a manifest. It describes the firmware image(s) and gives them appropriate protection πŸ” This document describes the information the manifest has to contain 🧚

This document lists all the information elements required in a manifest to secure firmware updates of IoT devices. Each information element is motivated by user stories and the threats it aims to mitigate πŸ’… These threats and user stories aren't meant to be an exhaustive list of threats against IoT devices or every possible user story for a firmware update. Instead, they describe the threats against firmware updates on their own and give enough motivation to specify information elements that cover a wide range of user stories πŸ¦‹

To separate information elements from how they're encoded and serialized over the wire, this document presents an information model. RFC 3444 [RFC3444] describes the differences between information models and data models πŸŽ€

Because this document covers a wide range of user stories and threats, not every information element applies to every scenario. So various information elements are optional to implement and optional to use, depending on which threats exist in a particular application domain and which user stories matter for a deployment 🌈

2. Requirements and Terminology

2.1. Requirements Notation

okay so the key words are "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" πŸ’– They're only interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, just like here 🫢

Unless otherwise stated, these words apply to the design of the manifest format, not to its implementation or application ✨ So whenever an information element is declared as "REQUIRED", that means the manifest format document has to include support for it πŸ‘‘

part 2 picks up with 2.2 Terminology πŸ‘€

2.2. Terminology

This document uses terms defined in [RFC9019]. The term "Operator" refers to either a device operator or a network operator.

"Secure time" and "secure clock" refer to a set of requirements on time sources. For local time sources, this primarily means that the clock must be monotonically increasing, including across power cycles, firmware updates, etc. For remote time sources, the provided time must be both authenticated and guaranteed to be correct to within some predetermined bounds, whenever the time source is accessible.

The term "Envelope" (or "Manifest Envelope") is used to describe an encoding that allows the bundling of a manifest with related information elements that are not directly contained within the manifest.

The term "payload" is used to describe the data that is delivered to a device during an update. This is distinct from a "firmware image", as described in [RFC9019], because the payload is often in an intermediate state, such as being encrypted, compressed, and/or encoded as a differential update. The payload, taken in isolation, is often not the final firmware image.

3. Manifest Information Elements ✨

Each manifest information element is anchored in a security requirement or a usability requirement. The manifest elements are described below, justified by their requirements.

3.1. Version ID of the Manifest Structure πŸŽ€

This is an identifier that describes which iteration of the manifest format is contained in the structure. This allows devices to identify the version of the manifest data model that is in use.

This element is REQUIRED.

3.2. Monotonic Sequence Number πŸ¦‹

This element provides a monotonically increasing (unsigned) sequence number to prevent malicious actors from reverting a firmware update against the policies of the relevant authority. This number must not wrap around.

For convenience, the monotonic sequence number may be a UTC timestamp. This allows global synchronization of sequence numbers without any additional management.

This element is REQUIRED.

Implements: REQ.SEC.SEQUENCE (Section 4.3.1)

3.3. Vendor ID πŸ’–

The Vendor ID element helps to distinguish between identically named products from different vendors. The Vendor ID is not intended to be a human-readable element. It is intended for binary match/mismatch comparison only.

Recommended practice is to use version 5 Universally Unique Identifiers (UUIDs) [RFC4122] with the vendor's domain name and the DNS name space ID. Other options include type 1 and type 4 UUIDs.

Fixed-size binary identifiers are preferred because they are simple to match, unambiguous in length, explicitly non-parsable, and require no issuing authority. Guaranteed unique integers are preferred because they are small and simple to match; however, they may not be fixed length, and they may require an issuing authority to ensure uniqueness. Free-form text is avoided because it is variable length, prone to error, and often requires parsing outside the scope of the manifest serialization.

If human-readable content is required, it SHOULD be contained in a separate manifest information element: Manifest Text Information (Section 3.17).

This element is RECOMMENDED.

Implements: REQ.SEC.COMPATIBLE (Section 4.3.2), REQ.SEC.AUTH.COMPATIBILITY (Section 4.3.10)

Here is an example for a domain-name-based UUID. Vendor A creates a UUID based on a domain name it controls, such as vendorId = UUID5(DNS, "vendor-a.example").

Because the DNS infrastructure prevents multiple registrations of the same domain name, this UUID is (with very high probability) guaranteed to be unique. Because the domain name is known, this UUID is reproducible. Type 1 and type 4 UUIDs produce similar guarantees of uniqueness, but not reproducibility.

This approach creates a contention when a vendor changes its name or relinquishes control of a domain name. In this scenario, it is possible that another vendor would start using that same domain name. However, this UUID is not proof of identity; a device's trust in a vendor must be anchored in a cryptographic key, not a UUID.

3.4. Class ID 🌸

A device "Class" is a set of different device types that can accept the same firmware update without modification. It thereby allows devices to determine the applicability of the firmware in an unambiguous way. Class IDs must be unique within the scope of a Vendor ID. This is to prevent similarly or identically named devices from colliding in their customer's infrastructure.

Recommended practice is to use version 5 UUIDs [RFC4122] with as much information as necessary to define firmware compatibility. Possible information used to derive the Class ID UUID includes:

  • Model name or number
  • Hardware revision
  • Runtime library version
  • Bootloader version
  • ROM revision
  • Silicon batch number

The Class ID UUID should use the Vendor ID as the name space identifier. Classes may be more fine-grained than is required to identify firmware compatibility. Classes must not be less granular than is required to identify firmware compatibility. Devices may have multiple Class IDs.

The Class ID is not intended to be a human-readable element. It is intended for binary match/mismatch comparison only. A manifest serialization SHOULD NOT permit free-form text content to be used for the Class ID. A fixed-size binary identifier SHOULD be used.

Some organizations desire to keep the same product naming across multiple, incompatible hardware revisions for ease of user experience. If this naming is propagated into the firmware, then matching a specific hardware version becomes a challenge. An opaque, non-readable binary identifier has no naming implications and so is more likely to be usable for distinguishing among incompatible device groupings, regardless of naming.

Fixed-size binary identifiers are preferred because they are simple to match, unambiguous in length, opaque and free from naming implications, and explicitly non-parsable. Free-form text is avoided because it is variable length, prone to error, often requires parsing outside the scope of the manifest serialization, and may be homogenized across incompatible device groupings.

If the Class ID is not implemented, then each logical device class must use a unique trust anchor for authorization.

This element is RECOMMENDED.

Implements: REQ.SEC.COMPATIBLE (Section 4.3.2), REQ.SEC.AUTH.COMPATIBILITY (Section 4.3.10)

3.4.1. Example 1: Different Classes 🧚

Vendor A creates Product Z and Product Y. The firmware images of Products Z and Y are not interchangeable. Vendor A creates UUIDs as follows:

  • vendorId = UUID5(DNS, "vendor-a.example")
  • ZclassId = UUID5(vendorId, "Product Z")
  • YclassId = UUID5(vendorId, "Product Y")

This ensures that Vendor A's Product Z cannot install firmware for Product Y and Product Y cannot install firmware for Product Z.

3.4.2. Example 2: Upgrading Class ID πŸ“

Vendor A creates Product X. Later, Vendor A adds a new feature to Product X, creating Product X v2. Product X requires a firmware update to work with firmware intended for Product X v2.

Vendor A creates UUIDs as follows:

  • vendorId = UUID5(DNS, "vendor-a.example")
  • XclassId = UUID5(vendorId, "Product X")
  • Xv2classId = UUID5(vendorId, "Product X v2")

When Product X receives the firmware update necessary to be compatible with Product X v2, part of the firmware update changes the Class ID to Xv2classId.

3.4.3. Example 3: Shared Functionality πŸ’œ

Vendor A produces two products: Product X and Product Y. These components share a common core (such as an operating system (OS)) but have different applications. The common core and the applications can be updated independently. To enable X and Y to receive the same common core update, they require the same Class ID. To ensure that only Product X receives Application X and only Product Y receives Application Y, Product X and Product Y must have different Class IDs. The vendor creates Class IDs as follows:

  • vendorId = UUID5(DNS, "vendor-a.example")
  • XclassId = UUID5(vendorId, "Product X")
  • YclassId = UUID5(vendorId, "Product Y")
  • CommonClassId = UUID5(vendorId, "common core")

Product X matches against both XclassId and CommonClassId. Product Y matches against both YclassId and CommonClassId.

3.4.4. Example 4: Rebranding πŸ‘‘

Vendor A creates a Product A and its firmware. Vendor B sells the product under its own name as Product B with some customized configuration. The vendors create the Class IDs as follows:

  • vendorIdA = UUID5(DNS, "vendor-a.example")
  • classIdA = UUID5(vendorIdA, "Product A-Unlabeled")
  • vendorIdB = UUID5(DNS, "vendor-b.example")
  • classIdB = UUID5(vendorIdB, "Product B")

The product will match against each of these Class IDs. If Vendor A and Vendor B provide different components for the device, the implementor may choose to make ID matching scoped to each component. Then, the vendorIdA, classIdA match the component ID supplied by Vendor A, and the vendorIdB, classIdB match the component ID supplied by Vendor B.

3.5. Precursor Image Digest Condition 🫢

This element provides information about the payload that needs to be present on the device for an update to apply. This may, for example, be the case with differential updates.

This element is OPTIONAL.

Implements: REQ.SEC.AUTH.PRECURSOR (Section 4.3.9)

3.6. Required Image Version List 🌈

Payloads may only be applied to a specific firmware version or multiple firmware versions. For example, a payload containing a differential update may be applied only to a specific firmware version.

When a payload applies to multiple versions of firmware, the required image version list specifies which firmware versions must be present for the update to be applied. This allows the update author to target specific versions of firmware for an update, while excluding those to which it should not or cannot be applied.

This element is OPTIONAL.

Implements: REQ.USE.IMG.VERSIONS (Section 4.5.8)

3.7. Expiration Time ⭐

This element tells a device the time at which the manifest expires and should no longer be used. This element should be used where a secure source of time is provided and firmware is intended to expire predictably. This element may also be displayed (e.g., via an app) for user confirmation, since users typically have a reliable knowledge of the date.

Special consideration is required for end-of-life if firmware will not be updated again -- for example, if a business stops issuing updates to a device. In this case, the last valid firmware should not have an expiration time.

This element is OPTIONAL.

Implements: REQ.SEC.EXP (Section 4.3.3)

3.8. Payload Format πŸ”₯

This element describes the payload format within the signed metadata. It is used to enable devices to decode payloads correctly.

This element is REQUIRED.

Implements: REQ.SEC.AUTH.IMG_TYPE (Section 4.3.5), REQ.USE.IMG.FORMAT (Section 4.5.6)

3.9. Processing Steps

okay so this element is all about how a device decodes a payload πŸŽ€. If the payload is compressed, packed, or encrypted, this is where the device finds out what to do. The representation must describe which algorithms are used and must convey any additional parameters those algorithms need.

A processing step may indicate the expected digest of the payload once the processing is complete πŸ¦‹.

This element is RECOMMENDED πŸ’….

Implements: REQ.USE.IMG.NESTED (Section 4.5.7)

3.10. Storage Location

this one tells the device where to stash a payload inside a given component πŸ“¦. The device can use it to work out which permissions it needs and which physical storage spot to use.

This element is REQUIRED 🫢.

Implements: REQ.SEC.AUTH.IMG_LOC (Section 4.3.6)

3.10.1. Example 1: Two Storage Locations

picture a device with two components, an OS and an app 🌈. They can get updated independently, with dependencies keeping them compatible. The author picks two storage identifiers:

  • "OS"
  • "APP"

3.10.2. Example 2: Filesystem

a device with a full-featured filesystem πŸ“‚. The author decides the storage identifier is the path where the payload gets installed. If the payload is a tarball, the device unpacks it into that path.

3.10.3. Example 3: Flash Memory

a device with flash memory 🧚. The author makes the storage identifier the offset where the image gets written.

3.11. Component Identifier

if a device has more than one storage subsystem, a storage identifier alone isn't enough to say where and how to store a payload 😭. So a component identifier tells you which part of the storage subsystem the payload shall be placed in ✨.

A serialization may choose to combine the use of a component identifier and storage location (Section 3.10).

This element is OPTIONAL 🌸.

Implements: REQ.USE.MFST.COMPONENT (Section 4.5.4)

3.12. Payload Indicator

this is the info the device needs to go grab the payload πŸ›°οΈ. It only matters when the target device doesn't intrinsically know where to find the payload.

It can be encoded a few ways:

  • One URI
  • A list of URIs
  • A prioritized list of URIs
  • A list of signed URIs

This element is OPTIONAL πŸ¦‹.

Implements: REQ.SEC.AUTH.REMOTE_LOC (Section 4.3.7)

3.13. Payload Digests

this element holds one or more digests of one or more payloads πŸ”. Combined with the Signature (Section 3.15) element, the target device can make sure the payload(s) are authentic. A manifest format must provide a mechanism to select one payload from a list based on system parameters, such as an execute-in-place (XIP) installation address.

This element is REQUIRED. Support for more than one digest is OPTIONAL πŸ’–.

Implements: REQ.SEC.AUTHENTIC (Section 4.3.4), REQ.USE.IMG.SELECT (Section 4.5.9)

3.14. Size

this provides the payload's size in bytes, so the target device knows how big of a payload to expect πŸ“. Without it, devices are exposed to some classes of denial-of-service attacks πŸ™ˆ.

This element is REQUIRED.

Implements: REQ.SEC.AUTH.EXEC (Section 4.3.8)

3.15. Manifest Envelope Element: Signature

the signature element has everything needed to protect the manifest's contents against modification and to offer authentication of the signer πŸ”. Because it authenticates the manifest, it can't live inside the manifest itself. Instead, either the manifest sits inside the signature element, or the signature element is a member of the Manifest Envelope and gets bundled with the manifest.

The signature element is the foundation of all the manifest's security properties πŸ‘‘. Manifests that other manifests pull in as dependencies should include a signature, so the recipient can tell apart different actors with different permissions.

The signature element must support multiple signers and multiple signing algorithms. A manifest format may allow multiple manifests to be covered by a single signature element.

This element is REQUIRED in non-dependency manifests.

Implements: REQ.SEC.AUTHENTIC (Section 4.3.4), REQ.SEC.RIGHTS (Section 4.3.11), REQ.USE.MFST.MULTI_AUTH (Section 4.5.5)

3.16. Additional Installation Instructions

these are machine-readable commands the device should execute while processing the manifest πŸ€–. They're separate from the info needed to process a payload. Examples include update timing (install only on Sunday, at 0200), procedural stuff (shut down the equipment under control before executing the update), and pre- and post-installation steps (run a script). Other instructions could include requesting user confirmation before installing βœ….

This element is OPTIONAL.

Implements: REQ.USE.MFST.PRE_CHECK (Section 4.5.1)

3.17. Manifest Text Information

this is textual info about the update the manifest describes πŸ“. It's strictly for human consumption πŸ‘€. It MUST NOT be the basis of any decision made by the recipient.

This element is OPTIONAL.

Implements: REQ.USE.MFST.TEXT (Section 4.5.2)

3.18. Aliases

aliases give a manifest a way to augment or replace URIs or URI lists defined by one or more of its dependencies πŸ”.

This element is OPTIONAL.

Implements: REQ.USE.MFST.OVERRIDE_REMOTE (Section 4.5.3)

3.19. Dependencies

this is a list of other manifests the current manifest needs πŸ“‹. Manifests get identified in an unambiguous way, such as by a cryptographic digest.

This element is REQUIRED to support deployments that include both multiple authorities and multiple payloads πŸ’….

Implements: REQ.USE.MFST.COMPONENT (Section 4.5.4)

3.20. Encryption Wrapper

encrypting firmware images needs symmetric content encryption keys πŸ”‘. The encryption wrapper gives the device the info it needs to obtain or locate the key it uses to decrypt the firmware.

This element is REQUIRED for encrypted payloads.

Implements: REQ.SEC.IMG.CONFIDENTIALITY (Section 4.3.12)

3.21. XIP Address

to support XIP systems with multiple possible base addresses, you need to specify which address the payload is linked for 🎯.

For example, a microcontroller may have a simple bootloader that chooses one of two images to boot. That microcontroller then needs to choose one of two firmware images to install, based on which of its two images is older.

This element is OPTIONAL.

Implements: REQ.USE.IMG.SELECT (Section 4.5.9)

3.22. Load-Time Metadata

this gives the device what it needs to load one or more images πŸ“₯. It may include any of the following:

  • The source (e.g., non-volatile storage)
  • The destination (e.g., an address in RAM)
  • Cryptographic information
  • Decompression information
  • Unpacking information

Typically, loading means copying an image from its permanent storage location into its active use location. The metadata lets operations like decryption, decompression, and unpacking happen during that copy πŸͺ„.

This element is OPTIONAL.

Implements: REQ.USE.LOAD (Section 4.5.11)

3.23. Runtime Metadata

this is the extra info the device needs to boot πŸš€. It may include the entry point of an XIP image or the kernel command line to boot a Linux image.

This element is OPTIONAL.

Implements: REQ.USE.EXEC (Section 4.5.10)

3.24. Payload

the Payload element sits inside the manifest or Manifest Envelope and lets the manifest and payload be delivered at the same time 🎁. This is for small payloads, like cryptographic keys or configuration data.

This element is OPTIONAL.

Implements: REQ.USE.PAYLOAD (Section 4.5.12)

3.25. Manifest Envelope Element: Delegation Chain

the delegation chain gives you extra authorization power through authorization tokens, like Concise Binary Object Representation (CBOR) Web Tokens [RFC8392] with Proof-of-Possession Key Semantics [RFC8747] πŸ—οΈ. Each token is already protected and doesn't need another layer. Each authorization token typically includes a public key or a public key fingerprint, though this depends on the tokens used. Each token MAY include additional metadata, such as key usage information. Because the delegation chain is needed to verify the signature, it must be placed in the Manifest Envelope, rather than the manifest.

The first token in any delegation chain MUST be authenticated by the recipient's trust anchor. Each subsequent token MUST be authenticated using the previous token. This lets a recipient discard each antecedent token after it has authenticated the subsequent token πŸ—‘οΈ. The final token MUST enable authentication of the manifest. More than one delegation chain MAY be used if more than one signature is used. Note that no restriction is placed on the encoding order of these tokens; the order of elements is logical only 🧠.

This element is OPTIONAL.

Implements: REQ.USE.DELEGATION (Section 4.5.14), REQ.SEC.KEY.ROTATION (Section 4.3.18)


4. Security Considerations ✨

the following subsections cover the threat model, user stories, security requirements, and usability requirements πŸ›‘οΈ. This section also explains the motivations behind each of the manifest information elements.

Worth remembering: a firmware update is, by definition, remote code execution. So if a device is configured to trust an entity to provide firmware, it trusts that entity to behave correctly. Many classes of attacks can be mitigated by verifying that a firmware update came from a trusted party and that no rollback is taking place. However, if the trusted entity has been compromised and distributes attacker-provided firmware to devices, then the possibilities for defense are limited πŸ’€.

4.1. Threat Model

the following subsections tell you about the threats that were considered, the security requirements derived from those threats, and the fields that make it possible to implement those requirements πŸ•΅οΈβ€β™€οΈ. This model uses the Spoofing, Tampering, Repudiation, Information Disclosure, Denial of Service, and Elevation of Privilege (STRIDE) approach [STRIDE]. Each threat is classified according to the following:

  • Spoofing identity
  • Tampering with data
  • Repudiation
  • Information disclosure
  • Denial of service
  • Elevation of privilege

This threat model only covers elements related to the transport of firmware updates. It explicitly does not cover threats outside of the transport of firmware updates. For example, threats to an IoT device due to physical access are out of scope 🚫.

4.2. Threat Descriptions

a lot of the threats in this section come with a "threat escalation" description 🧩. That explains how a threat might fit together with other threats to produce a high-severity threat. This matters because some threats may look low severity on their own, but they can be combined with others to build a high-severity compromise.

4.2.1. THREAT.IMG.EXPIRED: Old Firmware

Classification: Elevation of Privilege

okay so picture this πŸ₯Ή: an attacker sends a device an old manifest, and it's still valid, along with an old firmware image that's also still valid. If that firmware has a known vulnerability, the attacker can exploit it and gain control of the device. πŸ’€ not the main character energy we want.

Threat Escalation: If the attacker is able to exploit the known vulnerability, then this threat can be escalated to all types ✨

Mitigated by: REQ.SEC.SEQUENCE (Section 4.3.1)

4.2.2. THREAT.IMG.EXPIRED.OFFLINE: Offline Device + Old Firmware

Classification: Elevation of Privilege

this one is lowkey sneaky πŸ™ˆ. The attacker targets a device that's been offline for a long time and is still running old firmware. They send an old, but valid, manifest along with an old, but valid, firmware image to that device. The attacker-provided firmware is newer than what's installed, but older than the most recently available firmware. If that firmware has a known vulnerability, the attacker may be able to gain control of the device. Because the device has been offline for ages, it has no idea any new updates exist, so it treats the old manifest as the most current one. 😭

The fix depends on where the threat is coming from, so the implementor has to think it through carefully 🧠. If the threat comes from a network actor (including an on-path attacker) or from someone who broke into a management system, a user confirmation can mitigate it. The device just displays an expiration date and asks for confirmation, and that's it ✨. If the user is the attacker, though, an online confirmation system (for example, a trusted timestamp server) can be used as the mitigation instead 🫢.

Threat Escalation: If the attacker is able to exploit the known vulnerability, then this threat can be escalated to all types ✨

Mitigated by: REQ.SEC.EXP (Section 4.3.3), REQ.USE.MFST.PRE_CHECK (Section 4.5.1)

4.2.3. THREAT.IMG.INCOMPATIBLE: Mismatched Firmware

Classification: Denial of Service

the attacker sends a valid firmware image meant for the wrong type of device, signed by someone who has firmware installation permission on both device types πŸ™ƒ. The device verifies it positively because it's signed by an actor with the right permission, so it goes "yep, looks good" πŸ’…. This could have wide-ranging consequences. For devices that are similar, it could cause minor breakage or expose security vulnerabilities. For devices that are very different, it's likely to render them inoperable πŸ’€.

Mitigated by: REQ.SEC.COMPATIBLE (Section 4.3.2)

For example, imagine two vendors, Vendor A and Vendor B, who adopt the same trade name in different geographic regions. They both make products with the same names, or product name matching isn't used at all. Now firmware from Vendor A matches devices from Vendor B πŸ‘€.

If the vendors are the firmware authorities, then devices from Vendor A will reject images signed by Vendor B, since they use different credentials πŸ”. However, if both devices trust the same author, then devices from Vendor A could install firmware that was meant for devices from Vendor B. 😬

4.2.4. THREAT.IMG.FORMAT: The Target Device Misinterprets the Type of Payload

Classification: Denial of Service

if a device misreads the format of the firmware image, it can end up installing that image incorrectly πŸ€¦β€β™€οΈ. An incorrectly installed firmware image would likely make the device stop functioning. Rip πŸ’€.

Threat Escalation: An attacker that can cause a device to misinterpret the received firmware image may gain elevation of privilege and potentially expand this to all types of threats.

Mitigated by: REQ.SEC.AUTH.IMG_TYPE (Section 4.3.5)

4.2.5. THREAT.IMG.LOCATION: The Target Device Installs the Payload to the Wrong Location

Classification: Denial of Service

if a device installs a firmware image in the wrong spot, it's probably going to break 🫠. For example, a firmware image installed as an application could cause a device and/or application to stop functioning.

Threat Escalation: An attacker that can cause a device to misinterpret the received code may gain elevation of privilege and potentially expand this to all types of threats.

Mitigated by: REQ.SEC.AUTH.IMG_LOC (Section 4.3.6)

4.2.6. THREAT.NET.REDIRECT: Redirection to Inauthentic Payload Hosting

Classification: Denial of Service

if a device gets tricked into fetching a payload from an attacker-controlled site, the attacker can send corrupted payloads to devices 🚩. Not cute.

Mitigated by: REQ.SEC.AUTH.REMOTE_LOC (Section 4.3.7)

4.2.7. THREAT.NET.ONPATH: Traffic Interception

Classification: Spoofing Identity, Tampering with Data

this is the classic "someone is sitting in the middle" situation πŸ‘οΈ. An attacker intercepts all traffic to and from a device, so they can monitor or modify any data going to or from it πŸ•΅οΈβ€β™€οΈ. That includes manifests, payloads, status reports, and capability reports, which can be modified or never delivered to the intended recipient. It can also mean analysing the data going to or from the device by its content, size, or frequency. Yikes, bestie 😭.

Mitigated by: REQ.SEC.AUTHENTIC (Section 4.3.4), REQ.SEC.IMG.CONFIDENTIALITY (Section 4.3.12), REQ.SEC.AUTH.REMOTE_LOC (Section 4.3.7), REQ.SEC.MFST.CONFIDENTIALITY (Section 4.3.14), REQ.SEC.REPORTING (Section 4.3.16)

4.2.8. THREAT.IMG.REPLACE: Payload Replacement

Classification: Elevation of Privilege

the attacker swaps out newly downloaded firmware after the device has finished verifying the manifest 😱. This could make the device execute the attacker's code. This attack likely needs physical access to the device, but it's possible it's done together with another threat that allows remote execution. This is a typical Time Of Check / Time Of Use (TOCTOU) attack ⏱️. Classic.

Threat Escalation: If the attacker is able to exploit a known vulnerability or if the attacker can supply their own firmware, then this threat can be escalated to all types.

Mitigated by: REQ.SEC.AUTH.EXEC (Section 4.3.8)

4.2.9. THREAT.IMG.NON_AUTH: Unauthenticated Images

Classification: Elevation of Privilege / all types

if an attacker can install their own firmware on a device (for example, by messing with either the payload or the metadata), then they have complete control of the device πŸ‘‘πŸ’€.

Mitigated by: REQ.SEC.AUTHENTIC (Section 4.3.4)

4.2.10. THREAT.UPD.WRONG_PRECURSOR: Unexpected Precursor Images

Classification: Denial of Service / all types

modifying payloads and metadata lets an attacker cause a bunch of denial-of-service attacks πŸ™ƒ. Here are a few examples.

An attacker sends a valid, current manifest to a device that has an unexpected precursor image. If a payload format requires a precursor image (like delta updates) and that precursor image isn't available on the target device, the update could break πŸ’”.

An attacker that can cause a device to install a payload against the wrong precursor image could gain elevation of privilege and potentially expand this to all types of threats. However, it's unlikely that a valid differential update applied to the wrong precursor would result in functional but vulnerable firmware πŸ€”.

Mitigated by: REQ.SEC.AUTH.PRECURSOR (Section 4.3.9)

4.2.11. THREAT.UPD.UNAPPROVED: Unapproved Firmware

Classification: Denial of Service, Elevation of Privilege

this threat can show up in a few different ways, but it's ultimately about making sure devices keep the behavior their owner or Operator needs πŸŽ€. The owner or Operator typically needs the device to keep certain features, functions, capabilities, behaviors, or interoperability constraints (basically, behavior in general). If those requirements get broken, the device won't fulfil its purpose 😩. So if any party other than the device's owner or the owner's contracted device operator can change device behavior without approval, that counts as an elevation of privilege.

A network operator can be in the same boat. They may need devices to behave a certain way to keep the network healthy 🌐. If device behavior on a network can be changed without the network operator's approval, that's an elevation of privilege with respect to the network.

For example, say the owner bought a device because of Features A, B, and C, and then the manufacturer releases a firmware update that removes Feature A. Now the device might not meet the owner's requirements anymore 😀. In some situations, this can cause much bigger threats. Imagine Feature A is running a safety-critical system, whether the manufacturer meant for that to happen or not. If unapproved firmware gets installed, that system could become unsafe 🚨.

In a second example, the owner or Operator of a system made of two or more interoperating devices needs to approve firmware for that system so everything keeps working together 🧩. If the firmware isn't qualified, the whole system might stop working. So if a device installs firmware without approval from its owner or Operator, that's a threat to the device or to the system as a whole.

Similarly, the Operator of a network may need to approve firmware for devices attached to the network to keep conditions favourable inside it πŸ“Ά. If the firmware isn't qualified, it could degrade network performance. So if a device installs firmware without the network operator's approval, that's a threat to the network itself.

Threat Escalation: If the network operator expects configuration that's present in devices deployed in Network A, but not in devices deployed in Network B, then the device may experience degraded security, leading to threats of all types.

Mitigated by: REQ.SEC.RIGHTS (Section 4.3.11), REQ.SEC.ACCESS_CONTROL (Section 4.3.13)

4.2.11.1. Example 1: Multiple Network Operators with a Single Device Operator

okay this example is a whole plot twist 🎬. Assume device operators expect the rights to create firmware, but network operators expect the rights to qualify firmware as "fit for purpose" on their networks. Also assume that device operators manage devices that can be deployed on any network, including Network A and Network B in our example.

An attacker may obtain a manifest for a device on Network A. Then the attacker sends that manifest to a device on Network B 😈. Network A and Network B are under the control of different Operators, and firmware for a device on Network A hasn't been qualified for Network B. So the target device on Network B is now violating Operator B's policy, and it may be disabled by this unqualified (but signed) firmware 🫣.

This is a denial of service because it can render devices inoperable. It's also an elevation of privilege because it lets the attacker make installation decisions that should belong to the Operator πŸ‘‘.

4.2.11.2. Example 2: Single Network Operator with Multiple Device Operators ✨

Okay so picture this: multiple devices that interoperate are hanging out on the same network, talking to each other 🌸. Some are made and managed by Device Operator A, and others by Device Operator B. Then Device Operator A drops new firmware that breaks compatibility with Device Operator B's devices πŸ’€. An attacker sneaks that new firmware onto the devices managed by Device Operator A, and the network operator never approved it πŸ™ˆ. The whole larger system breaks, causing denial of service and possibly other threats too.

⚠️ Bestie, if the network is a distributed Supervisory Control and Data Acquisition (SCADA) system, this could cause misbehavior of the process that is under control. Not cute at all.

4.2.12. THREAT.IMG.DISCLOSURE: Reverse Engineering of Firmware Image for Vulnerability Analysis πŸ”

Classification: all types

An attacker wants to mount an attack on an IoT device πŸ‘€. To prep for it, they reverse engineer the provided firmware image and analyze it for vulnerabilities.

Mitigated by: REQ.SEC.IMG.CONFIDENTIALITY (Section 4.3.12)

4.2.13. THREAT.MFST.OVERRIDE: Overriding Critical Manifest Elements πŸ‘‘

Classification: Elevation of Privilege

An authorized actor, but not the author, uses an override mechanism (USER_STORY.OVERRIDE (Section 4.4.3)) to change an information element in a manifest that the author signed. For example, if the authorized actor overrides the digest and URI of the payload, they can replace the entire payload with whatever they want 😀.

Threat Escalation: By overriding elements such as payload installation instructions or a firmware digest, this threat can be escalated to all types πŸ“ˆ.

Mitigated by: REQ.SEC.ACCESS_CONTROL (Section 4.3.13)

4.2.14. THREAT.MFST.EXPOSURE: Confidential Manifest Element Exposure 🫣

Classification: Information Disclosure

A third party may be able to extract sensitive information from the manifest πŸ‘€.

Mitigated by: REQ.SEC.MFST.CONFIDENTIALITY (Section 4.3.14)

4.2.15. THREAT.IMG.EXTRA: Extra Data after Image 🧩

Classification: all types

If a third party modifies the image so that it contains extra code after a valid, authentic image, that third party can use their own code to make better use of an existing vulnerability 😈.

Mitigated by: REQ.SEC.IMG.COMPLETE_DIGEST (Section 4.3.15)

4.2.16. THREAT.KEY.EXPOSURE: Exposure of Signing Keys πŸ”‘

Classification: all types

If a third party obtains a key, or even indirect access to a key (for example, in a hardware security module (HSM)), then they can do everything the legitimate owner of the key can do. If the key is trusted for firmware updates, the third party can perform firmware updates as though they were the legitimate owner of the key 😱.

For example, if manifest signing is performed on a server connected to the internet, an attacker may compromise the server and then be able to sign manifests, even if the keys for manifest signing are held in an HSM that the server accesses πŸ’€.

Mitigated by: REQ.SEC.KEY.PROTECTION (Section 4.3.17), REQ.SEC.KEY.ROTATION (Section 4.3.18)

4.2.17. THREAT.MFST.MODIFICATION: Modification of Manifest or Payload prior to Signing ✍️

Classification: all types

If an attacker can alter a manifest or payload before it is signed, they can do all the same things as the manifest author. This lets the attacker deploy firmware updates to any devices that trust the manifest author 🚨. If an attacker can modify the code of a payload before the corresponding manifest is created, they can insert their own code. If an attacker can modify the manifest before it is signed, they can redirect the manifest to their own payload πŸ™…β€β™€οΈ.

For example, the attacker deploys malware to the developer's computer or signing service that watches manifest creation activities and inserts code into any binary that a manifest references.

For example, the attacker deploys malware to the developer's computer or signing service that replaces the referenced binary (digest) and URI with the attacker's binary (digest) and URI.

Mitigated by: REQ.SEC.MFST.CHECK (Section 4.3.19), REQ.SEC.MFST.TRUSTED (Section 4.3.20)

4.2.18. THREAT.MFST.TOCTOU: Modification of Manifest between Authentication and Use ⏱️

Classification: all types

If an attacker can modify a manifest after it is authenticated (time of check) but before it is used (time of use), then the attacker can place any content whatsoever in the manifest πŸ’….

Mitigated by: REQ.SEC.MFST.CONST (Section 4.3.21)


4.3. Security Requirements πŸ›‘οΈ

The security requirements here are a set of policies that mitigate the threats described in Section 4.1. Think of them as the rules that keep the threats above from happening 🌈.

4.3.1. REQ.SEC.SEQUENCE: Monotonic Sequence Numbers πŸ”’

Only an actor with firmware installation authority is permitted to decide when device firmware can be installed. To enforce this rule, manifests MUST contain monotonically increasing sequence numbers. Manifests may use UTC epoch timestamps to coordinate monotonically increasing sequence numbers across many actors in many locations. If UTC epoch timestamps are used, they must not be treated as times; they must be treated only as sequence numbers. Devices must reject manifests with sequence numbers smaller than any onboard sequence number, i.e., there is no sequence number rollover βͺ.

      |  Note: This is not a firmware version field.  It is a manifest
      |  sequence number.  A firmware version may be rolled back by
      |  creating a new manifest for the old firmware version with a
      |  later sequence number.

Mitigates: THREAT.IMG.EXPIRED (Section 4.2.1)

Implemented by: Monotonic Sequence Number (Section 3.2)

4.3.2. REQ.SEC.COMPATIBLE: Vendor, Device-Type Identifiers 🏷️

Devices MUST only apply firmware that is intended for them. Devices must know that a given update applies to their vendor, model, hardware revision, and software revision. Human-readable identifiers are often prone to error in this regard, so unique identifiers should be used instead πŸ€“.

Mitigates: THREAT.IMG.INCOMPATIBLE (Section 4.2.3)

Implemented by: Vendor ID Condition (Section 3.3), Class ID Condition (Section 3.4)

4.3.3. REQ.SEC.EXP: Expiration Time ⏳

A firmware manifest MAY expire after a given time, and devices may have a secure clock (local or remote). If a secure clock is provided and the firmware manifest has an expiration timestamp, the device must reject the manifest if the current time is later than the expiration time.

Special consideration is required for end-of-life in cases where a device will not be updated again, for example, if a business stops issuing updates for a device. The last valid firmware should not have an expiration time πŸͺ¦.

If a device has a flawed time source (either local or remote), an old update can be deployed as new 😬.

Mitigates: THREAT.IMG.EXPIRED.OFFLINE (Section 4.2.2)

Implemented by: Expiration Time (Section 3.7)

4.3.4. REQ.SEC.AUTHENTIC: Cryptographic Authenticity πŸ”

The authenticity of an update MUST be demonstrable. Typically, this means that updates must be digitally signed. Because the manifest contains information about how to install the update, the manifest's authenticity must also be demonstrable. To reduce the overhead required for validation, the manifest contains the cryptographic digest of the firmware image, rather than a second digital signature. The authenticity of the manifest can be verified with a digital signature or Message Authentication Code. The authenticity of the firmware image is tied to the manifest by the use of a cryptographic digest of the firmware image 🫢.

Mitigates: THREAT.IMG.NON_AUTH (Section 4.2.9), THREAT.NET.ONPATH (Section 4.2.7)

Implemented by: Signature (Section 3.15), Payload Digests (Section 3.13)

4.3.5. REQ.SEC.AUTH.IMG_TYPE: Authenticated Payload Type 🧾

The type of payload MUST be authenticated. For example, the target must know whether the payload is XIP firmware, a loadable module, or configuration data πŸ—‚οΈ.

Mitigates: THREAT.IMG.FORMAT (Section 4.2.4)

Implemented by: Payload Format (Section 3.8), Signature (Section 3.15)

4.3.6. REQ.SEC.AUTH.IMG_LOC: Authenticated Storage Location πŸ“

The location on the target where the payload is to be stored MUST be authenticated.

Mitigates: THREAT.IMG.LOCATION (Section 4.2.5)

Implemented by: Storage Location (Section 3.10)

4.3.7. REQ.SEC.AUTH.REMOTE_LOC: Authenticated Remote Payload 🌐

The location where a target should find a payload MUST be authenticated. Remote resources need to receive an equal amount of cryptographic protection as the manifest itself when dereferencing URIs. The security considerations of Uniform Resource Identifiers (URIs) are applicable [RFC3986] πŸ”—.

Mitigates: THREAT.NET.REDIRECT (Section 4.2.6), THREAT.NET.ONPATH (Section 4.2.7)

Implemented by: Payload Indicator (Section 3.12)

4.3.8. REQ.SEC.AUTH.EXEC: Secure Execution πŸš€

The target SHOULD verify firmware at the time of boot. This requires authenticated payload size and firmware digest πŸ₯Ύ.

Mitigates: THREAT.IMG.REPLACE (Section 4.2.8)

Implemented by: Payload Digests (Section 3.13), Size (Section 3.14)

4.3.9. REQ.SEC.AUTH.PRECURSOR: Authenticated Precursor Images 🧬

If an update uses a differential compression method, it MUST specify the digest of the precursor image, and that digest MUST be authenticated 🧠.

Mitigates: THREAT.UPD.WRONG_PRECURSOR (Section 4.2.10)

Implemented by: Precursor Image Digest (Section 3.5)

4.3.10. REQ.SEC.AUTH.COMPATIBILITY: Authenticated Vendor and Class IDs πŸͺͺ

The identifiers that specify firmware compatibility MUST be authenticated, so that only compatible firmware gets installed on a target device πŸ’–.

Mitigates: THREAT.IMG.INCOMPATIBLE (Section 4.2.3)

Implemented by: Vendor ID Condition (Section 3.3), Class ID Condition (Section 3.4)

4.3.11. REQ.SEC.RIGHTS: Rights Require Authenticity πŸ‘‘

If a device grants different rights to different actors, exercising those rights MUST be accompanied by proof of those rights, in the form of proof of authenticity. Authenticity mechanisms, such as those required in REQ.SEC.AUTHENTIC (Section 4.3.4), can be used to prove authenticity βœ….

For example, if a device has a policy that requires firmware to have both an Authorship right and a Qualification right, and if that device grants Authorship and Qualification rights to different parties (such as a device operator and a network operator, respectively), then the firmware cannot be installed without proof of rights from both the device operator and the network operator 🀝.

Mitigates: THREAT.UPD.UNAPPROVED (Section 4.2.11)

Implemented by: Signature (Section 3.15)

4.3.12. REQ.SEC.IMG.CONFIDENTIALITY: Payload Encryption πŸ™ˆ

The manifest information model MUST enable encrypted payloads. Encryption helps to prevent third parties, including attackers, from reading the content of the firmware image. This can protect against confidential information disclosures and discovery of vulnerabilities through reverse engineering. Therefore, the manifest must convey the information required to allow an intended recipient to decrypt an encrypted payload πŸ”’βœ¨.

Mitigates: THREAT.IMG.DISCLOSURE (Section 4.2.12), THREAT.NET.ONPATH (Section 4.2.7)

Implemented by: Encryption Wrapper (Section 3.20)

4.3.13. REQ.SEC.ACCESS_CONTROL: Access Control ✨

okay so if a device gives different rights to different actors, then every time someone uses a right, it MUST be checked against that actor's list of rights πŸ”. This usually looks like an Access Control List (ACL) πŸ’…. ACLs get used in two situations:

  1. An ACL decides which parts of the manifest can be overridden, and by who πŸŽ€.
  2. An ACL decides which component identifier / storage identifier pairs can be written, and by who πŸ¦‹.

Mitigates: THREAT.MFST.OVERRIDE (Section 4.2.13), THREAT.UPD.UNAPPROVED (Section 4.2.11)

Implemented by: Client-side code, not specified in manifest

4.3.14. REQ.SEC.MFST.CONFIDENTIALITY: Encrypted Manifests 🧚

bestie, a manifest format MUST let you encrypt selected parts of the manifest, or encrypt the whole thing, so the sensitive stuff about the firmware metadata doesn't leak πŸ™ˆ. Literally keep the secrets locked up πŸ”’.

Mitigates: THREAT.MFST.EXPOSURE (Section 4.2.14), THREAT.NET.ONPATH (Section 4.2.7)

Implemented by: Manifest Encryption Wrapper / Transport Security

4.3.15. REQ.SEC.IMG.COMPLETE_DIGEST: Whole Image Digest πŸ“

the digest SHOULD cover all the available space in a fixed-size storage location πŸ’–. Variable-size storage locations MUST be restricted to exactly the size of the deployed payload. Why? So no data can get distributed without being covered by the digest πŸ‘€. Like, XIP microcontrollers usually have fixed-size storage, right? So those devices should deploy a digest covering the deployed firmware image, concatenated with the default erased value of any remaining space ✨. It's giving completeness.

Mitigates: THREAT.IMG.EXTRA (Section 4.2.15)

Implemented by: Payload Digests (Section 3.13)

4.3.16. REQ.SEC.REPORTING: Secure Reporting πŸ“£

status reports from the device to any remote system MUST go over an authenticated, confidential channel πŸ”. That way nobody can modify or spoof the reports. No cap, this one is non-negotiable πŸ’….

Mitigates: THREAT.NET.ONPATH (Section 4.2.7)

Implemented by: Transport Security / Manifest format triggering generation of reports

4.3.17. REQ.SEC.KEY.PROTECTION: Protected Storage of Signing Keys πŸ—οΈ

cryptographic keys for signing or authenticating manifests SHOULD be stored somewhere networked devices can't reach, like an HSM or an air-gapped computer 🏰. This protects against an attacker getting their hands on the keys 😭.

Keys SHOULD also be stored in a way that limits the risk of a legitimate but compromised entity (like a server or a developer's computer) issuing signing requests. Lowkey scary, but we plan for it 🫢.

Mitigates: THREAT.KEY.EXPOSURE (Section 4.2.16)

Implemented by: Hardware-assisted isolation technologies, which are outside the scope of the manifest format

4.3.18. REQ.SEC.KEY.ROTATION: Protected Storage of Signing Keys πŸ”„

cryptographic keys for signing or authenticating manifests SHOULD be replaced from time to time 🌈. Replacing a trust anchor is hard and risky, so keys used for signing updates SHOULD be delegates of that trust anchor. Smart, right? πŸ‘‘

If key expiration is based on time, then a secure clock is needed ⏰. If the time source a recipient uses to check expiration is flawed, an old signing key can be treated as current πŸ’€. That compounds THREAT.KEY.EXPOSURE (Section 4.2.16), so it's a double whammy.

Mitigates: THREAT.KEY.EXPOSURE (Section 4.2.16)

Implemented by: Secure storage technology, which is a system design/ implementation aspect outside the scope of the manifest format

4.3.19. REQ.SEC.MFST.CHECK: Validate Manifests prior to Deployment βœ…

manifests SHOULD be verified before deployment 🧐. This cuts down on devices installing firmware images that accidentally damage them. Iconic prevention behavior πŸ’….

Mitigates: THREAT.MFST.MODIFICATION (Section 4.2.17)

Implemented by: Testing infrastructure. While outside the scope of the manifest format, proper testing of low-level software is essential for avoiding unnecessary downtime or worse situations.

4.3.20. REQ.SEC.MFST.TRUSTED: Construct Manifests in a Trusted Environment 🏯

for high-risk deployments, like large numbers of devices or devices that provide critical functions, manifests SHOULD be constructed in a protected environment, such as an air-gapped computer πŸ›‘οΈ. Note that a networked computer connected to an HSM does NOT fulfill this requirement. Sorry, not sorry (see THREAT.MFST.MODIFICATION (Section 4.2.17)) πŸ™ˆ.

Mitigates: THREAT.MFST.MODIFICATION (Section 4.2.17)

Implemented by: Physical and network security for protecting the environment where firmware updates are prepared to avoid unauthorized access to this infrastructure

4.3.21. REQ.SEC.MFST.CONST: Manifest Kept Immutable between Check and Use 🧊

the manifest and any data pulled out of it MUST be held immutable between its authenticity check (time of check) and its use (time of use) 🧊. To make that guarantee, the manifest MUST fit within internal memory or secure memory, such as encrypted memory. The recipient SHOULD defend the manifest from tampering by code or hardware living on the recipient, like other processes or debuggers πŸ•΅οΈβ€β™€οΈ.

If an application requires the manifest to be verified before it's stored, then the manifest MUST fit in RAM. Main character energy for memory planning 🧠.

Mitigates: THREAT.MFST.TOCTOU (Section 4.2.18)

Implemented by: Proper system design with sufficient resources and implementation avoiding TOCTOU attacks

4.4. User Stories πŸŽ€

user stories give us expected use cases πŸ’œ. They feed into usability requirements, so they matter a lot 🌸.

4.4.1. USER_STORY.INSTALL.INSTRUCTIONS: Installation Instructions πŸ“

as a device operator, I want to give my devices extra installation instructions so I can keep the process details out of my payload data πŸ“.

Some installation instructions might look like this:

  • Use a table of hashes to make sure each block of the payload is validated before writing.
  • Do not report progress.
  • Pre-cache the update, but do not install.
  • Install the pre-cached update matching this manifest.
  • Install this update immediately, overriding any long-running tasks.

Satisfied by: REQ.USE.MFST.PRE_CHECK (Section 4.5.1)

4.4.2. USER_STORY.MFST.FAIL_EARLY: Fail Early πŸͺ«

as a designer of a resource-constrained IoT device, I want bad updates to fail as early as possible, so I can save battery life and limit the bandwidth I use πŸ”‹.

Satisfied by: REQ.USE.MFST.PRE_CHECK (Section 4.5.1)

4.4.3. USER_STORY.OVERRIDE: Override Non-critical Manifest Elements πŸŽ›οΈ

as a device operator, I'd love to override the non-critical info in the manifest so I can control my devices more precisely πŸ’…. The authority to do this comes from installing a limited trust anchor issued by another authority πŸ”‘.

Some examples of info that could be overridden:

URIs (Section 3.12): This lets the device operator point devices at their own infrastructure to reduce network load 🌐.

Conditions: This lets the device operator add extra constraints on installing the manifest 🚧.

Directives (Section 3.16): This lets the device operator add more instructions, like when to install ⏳.

Processing Steps (Section 3.9): If an intermediary does something on behalf of a device, it may need to override the processing steps πŸ§‘β€πŸ€β€πŸ§‘. It's still possible for a device to verify the final content and the result of any processing step that specifies a digest πŸ”. Some processing steps should be non-overridable, and that's a hard line 🚫.

Satisfied by: REQ.USE.MFST.COMPONENT (Section 4.5.4)

4.4.4. USER_STORY.COMPONENT: Component Update 🧩

as a device operator, I want to split my firmware into components so I can shrink the size of updates, give different parties responsibility for different components, and separate the frequently updated parts from the rarely updated ones 🍰.

Satisfied by: REQ.USE.MFST.COMPONENT (Section 4.5.4)

4.4.5. USER_STORY.MULTI_AUTH: Multiple Authorizations πŸ”

as a device operator, I want to make sure a firmware update is good quality before installing it, so all the devices in my product family stay interoperable ✨. I also want changes to my devices to need my express approval πŸ‘‘.

Satisfied by: REQ.USE.MFST.MULTI_AUTH (Section 4.5.5), REQ.SEC.ACCESS_CONTROL (Section 4.3.13)

4.4.6. USER_STORY.IMG.FORMAT: Multiple Payload Formats πŸ“¦

as a device operator, I want to send multiple payload formats that suit my update, so I can optimize the bandwidth my devices use πŸ¦‹.

Satisfied by: REQ.USE.IMG.FORMAT (Section 4.5.6)

4.4.7. USER_STORY.IMG.CONFIDENTIALITY: Prevent Confidential Information Disclosures 🀫

as a firmware author, I want confidential info in the manifest to stay hidden when manifests and firmware images get distributed πŸ™Š. That confidential info can include details about the device the update is being applied to, plus whatever is inside the firmware image itself πŸ’œ.

Satisfied by: REQ.SEC.IMG.CONFIDENTIALITY (Section 4.3.12)

4.4.8. USER_STORY.IMG.UNKNOWN_FORMAT: Prevent Devices from Unpacking Unknown Formats πŸ“­

as a device operator, I want devices to figure out whether they can process a payload before downloading it πŸ™Œ.

Sometimes it's useful for a third party to do some processing on behalf of a target. For that to work, the third party MUST indicate what processing happened and how to verify it against the Trust Provisioning Authority's intent 🧾.

This amounts to overriding Processing Steps (Section 3.9) and Payload Indicator (Section 3.12) πŸŽ€.

Satisfied by: REQ.USE.IMG.FORMAT (Section 4.5.6), REQ.USE.IMG.NESTED (Section 4.5.7), REQ.USE.MFST.OVERRIDE_REMOTE (Section 4.5.3)

4.4.9. USER_STORY.IMG.CURRENT_VERSION: Specify Version Numbers of Target Firmware πŸ”’

as a device operator, I want to target devices for updates based on their current firmware version, so I can control which versions get replaced with a single manifest 🎯.

Satisfied by: REQ.USE.IMG.VERSIONS (Section 4.5.8)

4.4.10. USER_STORY.IMG.SELECT: Enable Devices to Choose between Images πŸͺ„

as a developer, I want to sign two or more versions of my firmware in a single manifest, so I can use a super simple bootloader that picks between images executed in place 🫧.

Satisfied by: REQ.USE.IMG.SELECT (Section 4.5.9)

4.4.11. USER_STORY.EXEC.MFST: Secure Execution Using Manifests πŸ”

as a signer for both secure execution/boot and firmware deployment, I'd like to use the same signed document for both tasks. That keeps my data size smaller, lets me share common code, and cuts down on signature verifications πŸ’–.

Satisfied by: REQ.USE.EXEC (Section 4.5.10)

4.4.12. USER_STORY.EXEC.DECOMPRESS: Decompress on Load πŸ—œοΈ

as a developer of firmware for a run-from-RAM device, I want to use compressed images and tell the bootloader I'm doing so in the manifest. That way it works with secure execution/boot πŸš€.

Satisfied by: REQ.USE.LOAD (Section 4.5.11)

4.4.13. USER_STORY.MFST.IMG: Payload in Manifest ✨

okay so picture this πŸŽ€ you're an Operator running devices on a constrained network, and you want the manifest to be able to bring a small payload along in the same packet πŸ¦‹ so you can cut down on network traffic. literally the vibe is "why send two things when one will do" πŸ’…

Small payloads may include, for example, wrapped content encryption keys, configuration information, public keys, authorization tokens, or X.509 certificates πŸ”‘

Satisfied by: REQ.USE.PAYLOAD (Section 4.5.12)

4.4.14. USER_STORY.MFST.PARSE: Simple Parsing πŸ’–

bestie, as a developer for constrained devices, you want a low-complexity library for processing updates 🧚 so you can fit more of your application code onto the device. main character energy, more code and less parsing drama πŸ‘‘

Satisfied by: REQ.USE.PARSE (Section 4.5.13)

4.4.15. USER_STORY.MFST.DELEGATION: Delegated Authority in Manifest πŸ”

so this one is for the device operator who rotates delegated authority more often than they deliver firmware updates 😭 they'd like to delegate a new authority whenever they deliver a firmware update, so both jobs happen in one transmission. two birds, one packet 🐦

Satisfied by: REQ.USE.DELEGATION (Section 4.5.14)

4.4.16. USER_STORY.MFST.PRE_CHECK: Update Evaluation πŸ™ˆ

as an Operator of a constrained network, you want devices on your network to be able to check whether an update is suitable before starting any large download. that way nobody wastes bandwidth on something they were never going to use πŸ’€

Satisfied by: REQ.USE.MFST.PRE_CHECK (Section 4.5.1)

4.4.17. USER_STORY.MFST.ADMINISTRATION: Administration of Manifests πŸ“‹

as a device operator, you want to understand what an update will do and which devices it applies to ✨ so you can make informed choices about which updates to apply, when to apply them, and which devices should be updated. clipboard queen behavior πŸ’…

Satisfied by: REQ.USE.MFST.TEXT (Section 4.5.2)


4.5. Usability Requirements 🌈

the following usability requirements satisfy the user stories listed above 🫢

4.5.1. REQ.USE.MFST.PRE_CHECK: Pre-installation Checks

A manifest format MUST be able to carry all information required to process an update πŸ“¦

for example, information about which precursor image is required for a differential update must be placed in the manifest 🧠

Satisfies: USER_STORY.MFST.PRE_CHECK (Section 4.4.16), USER_STORY.INSTALL.INSTRUCTIONS (Section 4.4.1)

Implemented by: Additional Installation Instructions (Section 3.16)

4.5.2. REQ.USE.MFST.TEXT: Descriptive Manifest Information πŸ“

It MUST be possible for a device operator to determine what a manifest will do and which devices will accept it prior to distribution πŸ‘€

Satisfies: USER_STORY.MFST.ADMINISTRATION (Section 4.4.17)

Implemented by: Manifest Text Information (Section 3.17)

4.5.3. REQ.USE.MFST.OVERRIDE_REMOTE: Override Remote Resource Location πŸ”€

A manifest format MUST be able to redirect payload fetches πŸͺ„ this applies where two manifests are used in conjunction. for example, a device operator creates a manifest specifying a payload and signs it, and provides a URI for that payload. then a network operator creates a second manifest, with a dependency on the first. they use this second manifest to override the URIs provided by the device operator, directing them into their own infrastructure instead πŸ—οΈ

some devices may provide this capability, while others may only look at canonical sources of firmware. for this to be possible, the device must fetch the payload, whereas a device that accepts payload pushes will ignore this feature πŸ™…β€β™€οΈ

Satisfies: USER_STORY.OVERRIDE (Section 4.4.3)

Implemented by: Aliases (Section 3.18)

4.5.4. REQ.USE.MFST.COMPONENT: Component Updates 🧩

A manifest format MUST be able to express the requirement to install one or more payloads from one or more authorities so that a multi-payload update can be described. this allows multiple parties with different permissions to collaborate in creating a single update for the IoT device, across multiple components 🀝

this requirement implies that it must be possible to construct a tree of manifests on a multi-image target 🌳

in order to enable devices with a heterogeneous storage architecture, the manifest must enable specification of both a storage system and the storage location within that storage system πŸ—„οΈ

Satisfies: USER_STORY.OVERRIDE (Section 4.4.3), USER_STORY.COMPONENT (Section 4.4.4)

Implemented by: Dependencies, StorageIdentifier, ComponentIdentifier

4.5.4.1. Example 1: Multiple Microcontrollers πŸ”Œ

An IoT device with multiple microcontrollers in the same physical device will likely require multiple payloads with different component identifiers πŸ’œ

4.5.4.2. Example 2: Code and Configuration βš™οΈ

A firmware image can be divided into two payloads: code and configuration. these payloads may require authorizations from different actors in order to install (see REQ.SEC.RIGHTS (Section 4.3.11) and REQ.SEC.ACCESS_CONTROL (Section 4.3.13)). this structure means that multiple manifests may be required, with a dependency structure between them πŸͺ†

4.5.4.3. Example 3: Multiple Software Modules 🧱

A firmware image can be divided into multiple functional blocks for separate testing and distribution. this means that code would need to be distributed in multiple payloads. for example, this might be desirable in order to ensure that common code between devices is identical in order to reduce distribution bandwidth πŸ“‰

4.5.5. REQ.USE.MFST.MULTI_AUTH: Multiple Authentications ✍️

A manifest format MUST be able to carry multiple signatures so that authorizations from multiple parties with different permissions can be required in order to authorize installation of a manifest. it's giving group project with everyone signing off πŸ–ŠοΈ

Satisfies: USER_STORY.MULTI_AUTH (Section 4.4.5)

Implemented by: Signature (Section 3.15)

4.5.6. REQ.USE.IMG.FORMAT: Format Usability 🎨

The manifest format MUST accommodate any payload format that an Operator wishes to use. this enables the recipient to detect which format the Operator has chosen. some examples of payload format are as follows:

  • Binary
  • Executable and Linkable Format (ELF)
  • Differential
  • Compressed
  • Packed configuration
  • Intel HEX
  • Motorola S-Record

Satisfies: USER_STORY.IMG.FORMAT (Section 4.4.6) USER_STORY.IMG.UNKNOWN_FORMAT (Section 4.4.8)

Implemented by: Payload Format (Section 3.8)

4.5.7. REQ.USE.IMG.NESTED: Nested Formats πŸͺΊ

The manifest format MUST accommodate nested formats, announcing to the target device all the nesting steps and any parameters used by those steps πŸ”

Satisfies: USER_STORY.IMG.CONFIDENTIALITY (Section 4.4.7)

Implemented by: Processing Steps (Section 3.9)

4.5.8. REQ.USE.IMG.VERSIONS: Target Version Matching πŸ”’

The manifest format MUST provide a method to specify multiple version numbers of firmware to which the manifest applies, either with a list or with range matching 🎯

Satisfies: USER_STORY.IMG.CURRENT_VERSION (Section 4.4.9)

Implemented by: Required Image Version List (Section 3.6)

4.5.9. REQ.USE.IMG.SELECT: Select Image by Destination πŸ“

The manifest format MUST provide a mechanism to list multiple equivalent payloads by execute-in-place (XIP) installation address, including the payload digest and, optionally, payload URIs πŸ—ΊοΈ

Satisfies: USER_STORY.IMG.SELECT (Section 4.4.10)

Implemented by: XIP Address (Section 3.21)

4.5.10. REQ.USE.EXEC: Executable Manifest πŸš€

The manifest format MUST allow the description of an executable system with a manifest on both XIP microcontrollers and complex operating systems. in addition, the manifest format MUST be able to express metadata, such as a kernel command line, used by any loader or bootloader 🐧

Satisfies: USER_STORY.EXEC.MFST (Section 4.4.11)

Implemented by: Runtime Metadata (Section 3.23)

4.5.11. REQ.USE.LOAD: Load-Time Information ⏱️

The manifest format MUST enable carrying additional metadata for load-time processing of a payload, such as cryptographic information, load address, and compression algorithm. note that load comes before execution/boot πŸ₯Ύ

Satisfies: USER_STORY.EXEC.DECOMPRESS (Section 4.4.12)

Implemented by: Load-Time Metadata (Section 3.22)

4.5.12. REQ.USE.PAYLOAD: Payload in Manifest Envelope 🎁

The manifest format MUST allow placing a payload in the same structure as the manifest. this may place the payload in the same packet as the manifest πŸ“¬

Integrated payloads may include, for example, binaries as well as configuration information, and keying material πŸ”‘

When an integrated payload is provided, this increases the size of the manifest. manifest size can cause several processing and storage concerns that require careful consideration 😬 the payload can prevent the whole manifest from being contained in a single network packet, which can cause fragmentation and the loss of portions of the manifest in lossy networks. this causes the need for reassembly and retransmission logic. The manifest MUST be held immutable between verification and processing (see REQ.SEC.MFST.CONST (Section 4.3.21)), so a larger manifest will consume more memory with immutability guarantees -- for example, internal RAM or NVRAM, or external secure memory. if the manifest exceeds the available immutable memory, then it MUST be processed modularly, evaluating each of the following: delegation chains; the security container; and the actual manifest, which includes verifying the integrated payload. if the security model calls for downloading the manifest and validating it before storing to NVRAM in order to prevent wear to NVRAM and energy expenditure in NVRAM, then either increasing memory allocated to manifest storage or modular processing of the received manifest may be required. while the manifest has been organized to enable this type of processing, it creates additional complexity in the parser. if the manifest is stored in NVRAM prior to processing, the integrated payload may cause the manifest to exceed the available storage. because the manifest is received prior to validation of applicability, authority, or correctness, integrated payloads cause the recipient to expend network bandwidth and energy that may not be required if the manifest is discarded, and these costs vary with the size of the integrated payload πŸ”‹

See also: REQ.SEC.MFST.CONST (Section 4.3.21)

Satisfies: USER_STORY.MFST.IMG (Section 4.4.13)

Implemented by: Payload (Section 3.24)

4.5.13. REQ.USE.PARSE: Simple Parsing 🧹

The structure of the manifest MUST be simple to parse to reduce the attack vectors against manifest parsers. this one is serious, bestie πŸ›‘οΈ

Satisfies: USER_STORY.MFST.PARSE (Section 4.4.14)

Implemented by: N/A

4.5.14. REQ.USE.DELEGATION: Delegation of Authority in Manifest 🀌

A manifest format MUST enable the delivery of delegation information. this information delivers a new key with which the recipient can verify the manifest πŸ”‘βœ¨

Satisfies: USER_STORY.MFST.DELEGATION (Section 4.4.15)

Implemented by: Delegation Chain (Section 3.25)


5. IANA Considerations

This document has no IANA actions 🌸

6. References

5. IANA Considerations ✨

πŸ’… The text for this section wasn't in the chunk I was given, so I'm not rewriting it here. Please send it along and I'll slay it in the next pass.

6. References πŸ“š

6.1. Normative References πŸ”₯

6.2. Informative References 🌸

Acknowledgements 🫢

Bestie, the working group chairs deserve a huge shoutout: Dave Thaler, Russ Housley, and David Waltermire. They gave review comments and support, and they were absolutely iconic about it. πŸ‘‘

Huge thanks also to everyone at the 2018 Berlin Software Updates for Internet of Things (SUIT) Hackathon and the June 2018 virtual design team meetings. Their discussion input made this so much better. πŸ’œ

Special thanks to Koen Zandberg, Emmanuel Baccelli, Carsten Bormann, David Brown, Markus Gueller, Frank Audun Kvamtrø, Øyvind Rønningstad, Michael Richardson, Jan-Frederik Rieckers, Francisco Acosta, Anton Gerasimov, Matthias WÀhlisch, Max Grâning, Daniel Petry, Gaëtan Harter, Ralph Hamm, Steve Patrick, Fabio Utzig, Paul Lambert, Saïd Gharout, and Milen Stoychev. You are all legends. 🧚

We also want to thank everyone who helped develop this information model, especially Milosch Meriac, Jean-Luc Giraud, Dan Ros, Amyas Phillips, and Gary Thomson. πŸ¦‹

Finally, a big thank you to these IESG members for their review feedback: Erik Kline, Murray Kucherawy, Barry Leiba, Alissa Cooper, Stephen Farrell, and Benjamin Kaduk. They were not here to play. πŸ’…


Authors' Addresses πŸ’Œ

Brendan Moran Arm Limited

Email: Brendan.Moran@arm.com

Hannes Tschofenig Arm Limited

Email: hannes.tschofenig@gmx.net

Henk Birkholz Fraunhofer SIT

Email: henk.birkholz@sit.fraunhofer.de

πŸ“¦ where this page comes from