]>
A CBOR-based Firmware Manifest Serialisation FormatArm LimitedBrendan.Moran@arm.comArm Limitedhannes.tschofenig@gmx.netSecurity
SUITInternet-DraftThis 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.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) can install firmware updates on IoT devices without 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 also reduces the scope of a compromise of any repository or intermediate system to be no worse than a denial of service.It is assumed that the reader is familiar with the high-level firmware update architecture and with the information model specification , which motivates various elements in the manifest. In we describe the main building blocks of the manifest and contains the description of the CBOR of the manifest. Examples are found in .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 .SUIT: Sofware Update for the Internet of Things, the IETF working group for this specification.Payload: A piece of information, typically Firmware, to be delivered.Resource: A piece of information that is used to construct a payload.Processor: A component that transforms one or more Resources into another resource or into a payload.Manifest: A piece of information that describes one or more payloads, one or more resources, and the processors needed to transform resources into payloads.Update: One or more manifests that describe one or more payloads.Update Authority: The owner of a cryptographic key used to sign updates, trusted by recipient devices.RFC 8152 provides containers for signature, MAC, and encryption, but no basic digest container. The container needed for a digest is identical to a COSE_Mac0 structure, so no new container is defined.N.B. The value 19 is a placeholder and needs to be registered.In order to get a consistent encoding of the data to be digested, the Digest_structure is used to have a canonical form. The Digest_structure is a CBOR array. The fields of the Digest_structure in order are:A text string that identifies the structure that is being encoded. This string is “Digest”.The protected attributes from the COSE_Digest structure. If there are no protected attributes, a zero-length bstr is used.The protected attributes from the application encoded as a bstr type. If this field is not supplied, it defaults to a zero-length binary string. (See RFC 8152 , Section 4.3 for application UUIDance on constructing this field.)The payload to be digested encoded in a bstr type. The payload is placed here independent of how it is transported.The CDDL fragment that corresponds to the above text is:The steps to compute a Digest are:Create a Digest_structure and populate it with the appropriate fields.Create the value ToBeDigested by encoding the Digest_structure to a byte stream, using the encoding described in RFC 8152 , Section 14.Call the Digest creation algorithm passing in alg (the algorithm to Digest with), and ToBeDigested (the value to compute the digest on).Place the resulting Digest in the ‘tag’ field of the COSE_Digest structure.The steps to verify a Digest are:Create a Digest_structure object and populate it with the appropriate fields.Create the value ToBeDigested by encoding the Digest_structure to a byte stream, using the encoding described in RFC 8152 , Section 14.Call the digest creation algorithm passing in alg (the algorithm to digest with), and ToBeDigested (the value to compute the Digest on).Compare the digest value to the ‘tag’ field of the COSE_Digest structure.NameValueSHA-22440SHA-25641SHA-38442SHA-51243SHA3-22444SHA3-25645SHA3-38446SHA3-51247N.B. Values are provisional, pending review.Distributing firmware in a multi-party environment is a difficult operation. Each party requires a different subset of data. Some data may not be accessible to all parties. Multiple signatures may be required from parties with different authority. This topic is covered in more depth in The manifest is designed to work with a pull parser, where each section of the manifest is used in sequence. The expected workflow for a device installing a manifest is as follows:Verify the signature of the manifestVerify the applicability of the manifest (verify PreConditions)Verify that all installation processors are availableVerify that all dependencies are metRun PreInstalation DirectivesLoad the descriptor for the next payload to be installedLoad installation descriptor for the next payload to be installedInstall the payloadWhile there are more payloads to install, go to 5.Validate PostInstallation ConditionsRun PostInstallation DirectivesWhen multiple manifests are used for an update, the pull parser is not possible to orchestrate in the same manner.The SUIT manifest can be used for a variety of purposes throughout its lifecycle. The manifest allows:the Firmware Author to reason about releasing a firmware.the Network Operator to reason about compatibility of a firmware.the Device Operator to reason about the impact of a firmware.the Device Operator to manage distribution of firmware to devices.the Plant Manager to reason about timing and acceptance of firmware updates.the device to reason about the authority & authenticity of a firmware prior to installation.the device to reason about the applicability of a firmware.the device to reason about the installation of a firmware.the device to reason about the authenticity of a firmware at boot.Each of these uses happens at a different stage of the manifest lifecycle, so each has different requirements.To verify authenticity at boot time, only the smallest portion of the manifest is required. This core part of the manifest describes only the fully installed firmware and any of its dependencies.Because the manifest can be used by different actors at different times, some parts of the manifest can be removed without affecting later stages of the lifecycle. This is called “Severing.” Severing of information is achieved by separating that information from the signed container so that removing it does not affect the signature. This means that ensuring authenticity of severable parts of the manifest is a requirement for the signed portion of the manifest. Severing some parts makes it possible to discard parts of the manifest that are no longer necessary. This is important because it allows the storage used by the manifest to be greatly reduced. For example, no text size limits are needed if text is removed from the manifest prior to delivery to a constrained device.Elements are made severable by removing them from the manifest, encoding them in a bstr, and placing a COSE_Digest of the bstr in the manifest so that they can still be authenticated. The COSE_Digest typically consumes 10 bytes more than the size of the raw digest, therefore elements smaller than (Digest Bits)/8 + 10 SHOULD never be severable. Elements larger than (Digest Bits)/8 + 10 MAY be severable, while elements that are much larger than (Digest Bits)/8 + 10 SHOULD be severable.The map indices in this encoding are reset to 1 for each map within the structure. This is to keep the indices as small as possible. The goal is to keep the index objects to single bytes (CBOR positive integers 1-23).Wherever enumerations are used, they are started at 1. This allows detection of several common software errors that are caused by uninitialised variables. Positive numbers in enumerations are reserved for IANA registration. Negative numbers are used to identify application-specific implementations.CDDL names are lowerCamelCase and CDDL structures are UpperCamelCase so that these names can be directly transcribed into most common programming languages, whereas hyphens require translation and CDDL prefers hyphens to underscores.Payloads can take many forms, for example, binary, hex, s-record, elf, binary diff, PEM certificate, CBOR Web Token, serialised configuration. These payloads fall into two broad categories: those that require installation-time processing and those that do not. Binary, PEM certificate, and CBOR Web Token do not require installation-time processing. Hex, s-record, elf, and serialised configuration require installation-time processing. Binary diff is a special case that can be handled either in a pre-processing step or in an installation-time step, depending on the architectural requirements of the application.Some payloads cannot be directly converted to a writable binary stream. Hex, s-record, and elf may contain gaps and they have no guarantee of monotonic increase of address, which makes pre-processing them into a binary stream difficult on constrained platforms. Serialised configuration may be unpacked into a configuration database, which makes it impossible to preprocess into a binary stream, suitable for direct writing.This presents two problems for the manifest: first, it must indicate that a specialised installer is needed and, second, it cannot provide a hash of the payload that is checkable after installation. These two problems are resolved in the payloadInstaller and payloadInfo sections, respectively.Where a specialised installer is needed, a digest is not always calculable over an installed payload. For example, an elf, s-record or hex file may contain gaps that can contain any data, while not changing whether or not an installed payload is valid. Serialised configuration may update only some device data rather than all of it. This means that the digest cannot always be calculated over an installed payload when a specialised installer is used.The manifest is divided into several sections in a hierarchy as follows:The outer wrapper
The authentication wrapperThe manifest
Critical InformationPre-installation Information / ReferencePayloadsInstallation Information / ReferencePost-installation Information / ReferenceText / ReferenceCOSWID / ReferencePre-installation InformationInstallation InformationPost-installation InformationTextThis container is just a holder for the other pieces of the manifest. The CDDL that describes the wrapper is below:The authenticationWrapper contains a cryptographic authentication wrapper for the core part of the manifest. This is implemented as a COSE_Mac_Tagged or COSE_Sign_Tagged block. The Manifest is authenticated by this block in “detached payload” mode. The COSE_Mac_Tagged and COSE_Sign_Tagged blocks are described in RFC 8152 and are beyond the scope of this document. The AuthenticationWrapper MUST come first in the OuterWrapper, regardless of canonical encoding of CBOR. All validators MUST reject any OuterWrapper that begins with any element other than an AuthenticationWrapper.Every other element must be wrapped in a bstr to minimize the complexity of the code that evaluates the cryptographic integrity of the element and to ensure correct serialisation for integrity and authenticity checks.manifest contains a Manifest structure, which describes the payload(s) to be installed and any dependencies on other manifests.PreInstallationInfo provides all the information that a device needs in order to decide whether and when to install an updateInstallationInfo provides all the information that a device needs in order to process one or more resources into one or more payloads.PostInstallationInfo provides the information that a device needs to verify that a payload has been installed correctly, any instructions for what to do after the payload has been installed, for example migration tools.Text contains all the human-readable information that describes any and all parts of the manifest, its payload(s) and its resource(s).The manifest describes the critical metadata for the referenced payload(s). In addition, it contains:a version number for the manifest structure itselfa sequence numbera list of dependenciesa list of payloadsa reference for each of the severable blocks.The following CDDL fragment defines the manifest.Several fields in the Manifest can be either a CBOR structure or a COSE_Digest. In each of these cases, the COSE_Digest provides for a severable field. Severable fields are RECOMMENDED to implement. In particular, text SHOULD be severable, since most useful text elements occupy more space than a COSE_Digest, but are not needed by recipient devices. Because COSE_Digest is a CBOR Array and each severable element is a CBOR Map, it is straight-forward for a recipient to determine whether an element has been severed.The manifestVersion indicates the version of serialisation used to encode the manifest. Version 1 is the version described in this document. manifestVersion is MANDATORY.The sequence number is an anti-rollback counter. It also helps devices to determine which in a set of manifests is the “root” manifest in a given update. Each manifest MUST have a sequence number higher than each of its dependencies. It MAY be convenient to use a UTC timestamp in seconds as the sequence number. The SequenceNumber is MANDATORY.preInstall is a digest that uniquely identifies the content of the PreInstallationInfo that is packaged in the OuterWrapper. preInstall is OPTIONAL within a given Manifest. There MUST be one preInstall in at least one Manifest within an Update because PreInstallationInfo contains the conditions that define the applicability of the Update to specific hardware/firmware versions. preInstall MAY be severable.dependencies is a list of DependencyInfo blocks that specify manifests that must be present before the current manifest can be processed. dependencies is OPTIONAL.payloads is a list of PayloadInfo blocks that describe the payloads to be installed. payloads is OPTIONAL.install is a digest that uniquely identifies the content of the InstallationInfo that is packaged in the OuterWrapper. install is OPTIONAL. install MAYpostInstall is a digest that uniquely identifies the content of the PostInstallationInfo that is packaged in the OuterWrapper. postInstall is OPTIONAL.text is a digest that uniquely identifies the content of the Text that is packaged in the OuterWrapper. text is OPTIONAL.coswid is a digest that uniquely identifies the content of the concise-software-identifier that is packaged in the OuterWrapper. coswid is OPTIONAL.DependencyInfo specifies a manifest that describes one or more dependencies of the current manifest.The following CDDL describes the DependencyInfo structure.The depDigest specifies the dependency manifest uniquely by identifying a particular Manifest structure. The digest is calculated over the Manifest structure instead of the COSE Sig_structure or Mac_structure. This means that a digest may need to be calculated more than once, however this is necessary to ensure that removing a signature from a manifest does not break dependencies due to missing ‘body_protected’ and ‘body_signed’ elements. This is also necessary to support the trusted intermediary use case, where an intermediary re-signs the Manifest, removing the original signature, potentially with a different algorithm, or trading COSE_Sign for COSE_Mac.The depUris element describes one or more indications of where to find the dependency. This element is OPTIONAL when the fetch location for a dependency is known implicitly.The depScope element contains a ComponentIdentifier. This specifies the scope at which the dependency operates. This allows the dependency to be forwarded on to a component that is capable of parsing its own manifests. It also allows one manifest to be deployed to multiple dependent devices without those devices needing consistent component hierarchy. This element is MANDATORY.Payload Info describes a payload that is ready for installation. When representing a payload that requires a specialised installer, the Update Authority can provide information to regenerate a digest.The following CDDL describes the PayloadInfo structure.The payloadComponent element contains a ComponentIdentifier. This specifies the module/component/location in which the payload should be installed. The meaning of ComponentIdentifier is application-specific. In general, the last bstr in the ComponentIdentifier defines where to store a payload within a given storage subsystem in a Heterogeneous Storage Architecture device, the remainder of the elements in the ComponentIdentifier define which storage subsystem to use to store the payload. payloadComponent is MANDATORY. When used on a single-image device payloadComponent MAY contain 0 elements. On multi-image devices, payloadComponent MUST contain at least one element.payloadSize contains a positive integer that describes the size of the ready-to-install payload. Where the payload requires a specialised installer, this is the payload prior to installation. This element is MANDATORY.payloadDigest contains a digest of the payload, prior to installation. For payloads that do not require a specialised installer, this is the also the post-installation digest. This element is MANDATORY.regenInfo describes the mechanism for recreating a message digest of payload that requires a specialised installer. This element is OPTIONAL. This element is OPTIONAL TO IMPLEMENT.regenDigest is a Digest that contains the message digest that an application should regenerate to verify the installed payload. This element is MANDATORY when regenInfo is present.regenType is an int that identifies a particular mechanism for creating the regenDigest. This element is MANDATORY when regenInfo is present.regenParameters is a bstr that provides any additional arguments needed by the specialised installer. This element is OPTIONAL.When message digest regeneration is in place, regenType implies a regenParameters structure, as described in the following table:regenTypeRegenParametersDescription0-Reserved1[ * [ location: uint, length: uint] ]Lists a series of regions to include in the digest2[ * file: tstr ]Lists a series of files to digest3[ * key: tstr ]Lists a series of keys, whose values should be digestedPositive RegenType numbers are reserved for IANA registration. Negative numbers are reserved for proprietary, application-specific directives.The recipient processes the PreInstallationInfo in order to determine whether the manifest is applicable to it. This check is only needed once, so the PreInstallationInfo is severable.The following CDDL describes the PreInstallationInfo structure.preConditions contains a list of 0 or more PreCondition structures.preDirectives contains a list of 0 or more PreDirective structures.PreCondition structures describe conditions that must be true in order for a manifest to be installed. The target device MUST check these conditions before any installation is performed. The target device MAY check these conditions prior to fetching any dependency manifests.All updates MUST contain either a device IdCondition or both a vendor IdCondition and a class IdCondition. This is to ensure that firmware is only ever delivered to compatible devices.The following CDDL describes the PreCondition structure.All PreConditions are serialised as a list of one integer and one or more parameters. The type of the parameters is dictated by the value of the integer. An update that has contradictory preConditions MUST be rejected.IdCondition describes three conditions: the vendor ID condition, the class ID condition, and the device ID condition. Each of these conditions present a RFC 4122 UUID that MUST be matched by the installing device in order to consider the manifest valid.A device MUST have at least one vendor ID and one class ID. A device MAY have one or more device IDs, more than one vendor ID, and/or more than one class ID.TimeCondition describes one condition: the useBy condition, which can be used to specify the last time at which an update should be installed. The timestamp is encoded as a POSIX timestamp, that is seconds after 1970-01-01 00:00:00. Timestamp conditions MUST be evaluated in 64 bits, regardless of encoded CBOR size.ImageCondition describes two conditions: the currentContent and the notCurrentContent conditions. Both of these conditions specify a storage identifier and a digest that the contents of that storage identifier should match.BatteryLevelCondition provides a mechanism to test a device’s battery level before installing an update. This condition is for use in primary-cell applications, where the battery is only ever discharged. For batteries that are charged, BatteryLevelDirective is more appropriate, since it defines a “wait” until the battery level is sufficient to install the update. BatteryLevelCondition is specified in mWh.CustomCondition describes any proprietary, application specific condition. This is encoded as a negative integer, chosen by the firmware developer, and a bstr that encodes the parameters passed to system that evaluates the condition matching that integer.Positive Condition numbers are reserved for IANA registration. Negative numbers are reserved for proprietary, application-specific directives. When a negative number is used, the parameters MUST be wrapped in a bstr.Many conditions use identifiers to determine whether a manifest matches a given recipient or not. These identifiers are defined to be RFC 4122 UUIDs. These UUIDs are explicitly NOT human-readable. They are for machine-based matching only.A device may match any number of UUIDs for vendor or class identifier. This may be relevant to physical or software modules. For example, a device that has an OS and one or more applications might list one Vendor ID for the OS and one or more additional Vendor IDs for the applications. This device might also have a Class ID that must be matched for the OS and one or more Class IDs for the applications.A more complete example:
A device has the following physical components:
1. A host MCU
2. A WiFi moduleThis same device has three software modules:
1. An operating system
2. A WiFi module interface driver
3. An applicationSuppose that the WiFi module’s firmware has a proprietary update mechanism and does not support manifest processing. This device can report four class IDs:hardware model/revisionOSWiFi module model/revisionApplicationThis allows the OS, WiFi module, and application to be updated independently. To combat possible incompatibilities, the OS class ID can be changed each time the OS has a change to its API.This approach allows a vendor to target, for example, all devices with a particular WiFi module with an update, which is a very powerful mechanism, particularly when used for security updates.UUIDs MUST be created according to RFC 4122 . UUIDs SHOULD use versions 3, 4, or 5, as described in RFC 4122. Versions 1 and 2 do not provide a tangible benefit over version 4 for this application.The RECOMMENDED method to create a vendor ID is:
Vendor ID = UUID5(DNS_PREFIX, vendor domain name)The RECOMMENDED method to create a class ID is:
Class ID = UUID5(Vendor ID, Class-Specific-Information)Class-specific information is composed of a variety of data, for example:Model numberHardware revisionBootloader version (for immutable bootloaders)PreDirective structures describe operations that a device MUST execute prior to installing an update. For example, shut down monitored equipment, enter safe mode, sync cached files to disk, wait for another device to be updated, or wait until a specific time. Some PreDirectives may appear similar to PreConditions, however there is one difference: a PreCondition is evaluated at one time. A PreDirective can include a “wait” instruction, that means that the evaluation of the manifest does not immediately fail if the condition in the PreDirective is not met. Instead, the PreDirective remains active, waiting for its condition to be met.For example, suppose two devices, A and B. Device B has an “other device firmware version” condition, requiring Device A to be at Rev 2. If both devices are updated from Rev 1 to Rev 2 simultaneously, then Device B may fail the PreCondition check if Device A has not finished its installation. If a PreDirective is used instead, then it can be a “wait for other device firmware version” directive. Then, Device B will postpone its update until Device A has finished updating.The following CDDL describes the PreDirective structure.WaitUntilDirective instructs the target device to wait until a specific time to install the update. The timestamp is encoded as a POSIX timestamp, that is seconds after 1970-01-01 00:00:00. Timestamp conditions MUST be evaluated in 64 bits, regardless of encoded CBOR size.DayOfWeekDirective instructs the target device to wait until a specific day of the week to install the update. The day is encoded as days since Sunday, with Sunday being day 0 and Saturday being day 6.TimeOfDayDirective instructs the target device to wait until a specific time each day to install the update. When combined with DayOfWeekDirective, this can specify a particular time on a particular day of the week to install an update. Leap seconds are not allowed in the TimeOfDayDirective.BatteryLevelDirective defines a directive to wait until the battery is above the specified value. This is for use in rechargeable battery and energy harvesting devices because it instructs the device to wait for a minimum charge. BatteryLevelCondition should be used in discharge-only devices. BatteryLevelDirective is specified in mWh. Battery Levels MUST be evaluated in 16 bits or more. 32 bit evaluation MUST be used for high battery capacity devices (over 65535 mWh capacity)ExternalPowerDirective defines a directive to the device to wait until it is connected to an external power source before installing the update.NetworkDisconnectDirective defines a directive to the device to disconnect from the network before installing the update.Positive Directive numbers are reserved for IANA registration. Negative numbers are reserved for proprietary, application-specific directives.InstallationInfo contains the information that a device needs in order to install a payload. As described in [Payloads], some payloads require specialised installers. Where a specialised installer is needed, the InstallationInfo block must represent this requirement.InstallationInfo is described by the following CDDL.installationInfo contains a list of 0 or more PayloadInstallationInfo blocks. PayloadInstallationInfo is described by the following CDDLinstallComponent defines the component identifier of the component to update. This includes both the storage subsystem designator and the path within the storage subsystem as the final element of the component identifier. This element is MANDATORY.payloadProcessors defines where to obtain a resource and how to transform it into a payload. This element is MANDATORY. Processors MUST be instantiated in a parent-last order.The payloadInstaller contains a map of elements that are only needed when a specialised payload installer is used. This element is OPTIONAL TO IMPLEMENT.payloadInstallerID contains an integer that defines which payload installer will be used. Positive integers are reserved for IANA registration. Negative integers are reserved for application-specific payload installers. Default payload installers are listed below. This element is MANDATORY when payloadInstaller is defined.payloadInstallerIDDefinition[ 0 ]Binary[ 5, 2 ]Intel Hex[ 5, 3 ]Motorola S-Record[ 6, 1 ]Executable and Linkable Format (ELF)[ 7, 1 ]CBOR-encoded dataNote that specialised installer 0 (binary) is typically not necessary and SHOULD ONLY be used when one of the other members of the payloadInstaller structure is required for a particular application.These IDs are chosen to match those chosen for ProcessorIDs.payloadInstallerParameters contains a bstr that provides any additional arguments needed by the specialised installer. This element is OPTIONAL.Processors define one operation performed in order to modify a Resource in one step towards reconstructing the payload.All Processors are OPTIONAL to implement. int}
]]>The form of parameters and inputs depends on the processorId.ProcessorDependencies is an interger-indexed map of integers. Each processor defines its inputs as integers–these are the indicies of the map. The inputs to the processor are other processors, identified by index in the Processors list. Processors that use the ProcessorDependencies input form MUST have an index in the Processors list greater than any index listed in ProcessorDependencies. The last processor listed in Processors is the processor that generates the payload to be installed in the ComponentIdentifier in PayloadInstallationInfo.processorID contains a list of ints. This is conceptually similar to an OID, however, unlike an OID, this list is context-sensitive, encoded as a CBOR list, and supports negative numbers. The reasons for these distinctions are as follows. Contextual IDs are smaller because their use is correlated with their context. CBOR is already in use, so it reduces the number of CODECs required. Negative numbers allow for non-standard extension of IDs.Devices are expected to compare processorIDs, bytewise, as binary blobs.The first integer represents a broad classification of the processor, as defined in the following table.ID[0]TypeDescription0ReservedDo not use.1ResourceIndicates that the processor sources data by reading a resource.2CipherEncrypts or Decrypts data.3CompressCompresses or Decompresses data.4RelocateReserved for Relocation.5BinTextPacks or Unpacks Binary-to-text encoding formats.6ObjectReserved for object formats, such as elf.Each of these classifications has a subsetA resource can be either local or remote. Local resources fetch ComponentIdentifiers. Remote Resources fetch from URIs.IDTypeParametersInputsDescription[ 1, 1 ]RemoteDigestUriListFetch a resource from a remote location[ 1, 2 ]LocalDigestComponentIdentifierFetch a resource from a local locationCiphers are typically implemented using a cryptographic container, such as a COSE_Encrypt structure. In the context of SUIT Ciphers are typically used in decrypt mode, so this is the default behaviour. If encrypt mode is needed, then this can be achieved by extending the ID as shown in the table below.Only one input is used, specified using ProcessorDependencies[0], a positive integer index of the data to be processed in the tree.Only two Cipher modes are defined, the COSE_Encrypt and COSE_Encrypt0 Cipher mode2.IDTypeParametersInputsDescription[ 2, 1 ]COSE_EncryptCOSE_Encrypt{0 : dataIdx}Decrypt data enveloped by a COSE_Encrypt structure[ 2, 1, 2 ]COSE_EncryptCOSE_Encrypt{0 : dataIdx}Encrypt data enveloped by a COSE_Encrypt structure[ 2, 2 ]COSE_Encrypt0COSE_Encrypt0{0 : dataIdx}Decrypt data enveloped by a COSE_Encrypt0 structure[ 2, 2, 2 ]COSE_Encrypt0COSE_Encrypt0{0 : dataIdx}Encrypt data enveloped by a COSE_Encrypt0 structureMode 1 (decrypt) is implied when mode 2 (encrypt) is not specified.A compression/decompression algorithm. Typically, this means that the input should contain a valid compression container. Compression algorithms are typically used in decompress mode, so this is the default behaviour.Only one input is used, specified using ProcessorDependencies[0], a positive integer index of the data to be processed in the tree.IDTypeParametersInputsDescription[ 3, 1 ]gzipnil{0 : dataIdx}Decompress using gzip[ 3, 1, 2 ]gzipnil{0 : dataIdx}Compress using gzip[ 3, 2 ]bzip2nil{0 : dataIdx}Decompress using bzip2[ 3, 2, 2 ]bzip2nil{0 : dataIdx}Compress using bzip2[ 3, 4 ]lz4nil{0 : dataIdx}Decompress using lz4[ 3, 4, 2 ]lz4nil{0 : dataIdx}Compress using lz4[ 3, 7 ]lzmanil{0 : dataIdx}Decompress using lzma[ 3, 7, 2 ]lzmanil{0 : dataIdx}Compress using lzmaMode 1 (decompress) is implied when mode 2 (compress) is not specified.Relocation is reserved for future use.Packs or unpacks a binary-to-text format.WARNING: Some binary-to-text formats can cause significant difficulty for a resource-constrained device. They also dramatically increase bandwidth over equivalent binary formats, with the worst being hex encoding at a 2:1 inflation. The best is base64 at a 4:3 inflation.binary-to-text formats are typically used in decode mode, so this is the default behaviour.Only one input is used, specified using ProcessorDependencies[0], a positive integer index of the data to be processed in the tree.IDTypeParametersInputsDescription[ 5, 1 ]base64uint / tstr{ 0 : dataIdx }Decode base64 data in one of several encodings[ 5, 1, 2 ]base64uint / tstr{ 0 : dataIdx }Decode base64 data in one of several encodings[ 5, 2 ]hexnil{ 0 : dataIdx }Decode Intel Hex data[ 5, 2, 2 ]hexnil{ 0 : dataIdx }Encode Intel Hex data[ 5, 3 ]srecordnil{ 0 : dataIdx }Decode S-Record data[ 5, 3, 2 ]srecordnil{ 0 : dataIdx }Encode S-Record dataMode 1 (decode) is implied when mode 2 (encode) is not specified.When base64 is specified, several choices of parameter are available:TypeValueDescriptionuint1RFC 4648 standard base64uint2base64urltstrbase64 charactersetArbitrary base64, as specified by the character set.Object packing and unpacking is reserved for future use.PostInstallationInfo contains information that the recipient needs in order to determine whether an installation has completed successfully and whether anything needs to be done after completion. These checks and instructions are only needed once, so PostInstallationInfo is severable.The following CDDL describes the PostInstallationInfo structure.postConditions contains a list of 0 or more PostCondition structures. postConditions is OPTIONAL and OPTIONAL to implement.postDirectives contains a list of 0 or more PostDirective structures. postDirectives is OPTIONAL and OPTIONAL to implement.PostConditions are used to specify conditions that must be true after an update has completed. The ImageCondition specifies a digest of an image that must match after application of an update.PostDirectives can be used to specify an action taken by the recipient after application of an update is complete, such as:Reboot after applicationRestart designated component when installation is completeA small portion of RFC 8152 is reproduced in this CDDL so that COSE_Digest can be fully defined. values
}
empty_or_serialized_map = bstr .cbor header_map / bstr .size 0
Generic_Headers = (
? 1 => int / tstr, ; algorithm identifier
? 2 => [+label], ; criticality
? 3 => tstr / int, ; content type
? 4 => bstr, ; key identifier
? 5 => bstr, ; IV
? 6 => bstr, ; Partial IV
? 7 => COSE_Signature / [+COSE_Signature] ; Counter signature
)
COSE_Digest = COSE_Mac0
Manifest = {
manifestVersion : 1,
sequence : SequenceNumber,
? preInstall : PreInstallationInfo / COSE_Digest,
? dependencies : [* DependencyInfo],
? payloads : [* PayloadInfo],
? install : InstallationInfo / COSE_Digest,
? postInstall : PostInstallationInfo / COSE_Digest,
? text : TextInfo / COSE_Digest,
? coswid : concise-software-identity / COSE_Digest
}
manifestVersion = 1
sequence = 2
preInstall = 3
dependencies = 4
payloads = 5
install = 6
postInstall = 7
text = 8
coswid = 9
SequenceNumber = uint
DependencyInfo = {
depDigest : COSE_Digest, ; digest of the resource
depScope : ComponentIdentifier, ; where the dependency's
; payloads will be applied
? depUris : UriList ; where to find the resource
; applied
}
depDigest = 1
depScope = 2
depUris = 3
UriList = [ + [priority: int, uri: tstr] ]
ComponentIdentifier = [* bstr]
PayloadInfo = {
payloadComponent: ComponentIdentifier,
payloadSize: uint / nil,
payloadDigest: COSE_Digest,
? regenInfo : {
regenDigest: COSE_Digest
regenType: int
? regenParameters: bstr
},
}
payloadComponent = 1
payloadSize = 2
payloadDigest = 3
regenInfo = 4
regenDigest = 5
regenType = 6
regenParameters = 7
RegenType = LocationLengthRegenType /
FileListRegenType /
KeyListRegenType /
CustomRegenType
LocationLengthRegenType = 1
FileListRegenType = 2
KeyListRegenType = 3
CustomRegenType = nint
RegenParameters = LocationLengthRegenParameters /
FileListRegenParameters /
KeyListRegenParameters /
CustomRegenParameters
LocationLengthRegenParameters = [ * [ location: uint, length: uint ] ]
FileListRegenParameters = [ * file: tstr ]
KeyListRegenParameters = [ * key: tstr ]
CustomRegenParameters = bstr
PreInstallationInfo = {
? preConditions : [ * PreCondition ],
? preDirectives : [ * PreDirective ]
}
preConditions = 1
preDirectives = 2
PreCondition = IdCondition /
TimeCondition /
ImageCondition /
BatteryLevelCondition /
CustomCondition
IdCondition = [ vendor : 1, id: Uuid ] /
[ class : 2, id: Uuid ] /
[ device : 3, id: Uuid ]
Uuid = bstr .size 16
TimeCondition = [useBy: 4,
time: Timestamp]
ImageCondition = [ currentContent : 6 ,
digest: COSE_Digest / nil,
location: ComponentIdentifier ] /
[ notCurrentContent : 7 ,
digest: COSE_Digest / nil,
location: ComponentIdentifier ]
BatteryLevelCondition = [ batteryLevel: 8,
level: uint ]
CustomCondition = [nint,
parameters: bstr]
Timestamp = uint
PreDirective = WaitUntilDirective /
DayOfWeekDirective /
TimeOfDayDirective /
BatteryLevelDirective /
ExternalPowerDirective /
CustomDirective
WaitUntilDirective = [ 1,
timestamp: uint ]
DayOfWeekDirective = [ 2, day: 0..6 ]
TimeOfDayDirective = [ 3, hours: 0..23,
? minutes: 0..59,
? seconds: 0..59 ]
BatteryLevelDirective = [ 4, level: uint]
ExternalPowerDirective = [ 5 ]
NetworkDisconnectDirective = [ 6 ]
CustomDirective = [ nint,
? parameters: bstr ]
InstallationInfo = {
payloadInstallationInfo : [ * PayloadInstallationInfo ],
}
payloadInstallationInfo = 1
PayloadInstallationInfo = {
installComponent : ComponentIdentifier
payloadProcessors : [ * Processor ],
? allowOverride : bool,
? payloadInstaller: {
payloadInstallerID: [ * int ],
? payloadInstallerParameters: bstr,
}
}
installComponent = 1
payloadProcessors = 2
allowOverride = 3
payloadInstaller = 4
payloadInstallerID = 5
payloadInstallerParameters = 6
Processor = {
processorId: ProcessorID
parameters: COSE_Digest / COSE_Encrypt / COSE_Encrypt0 /
int / tstr / bstr / nil,
inputs: UriList / ComponentIdentifier / {int => int}
}
ProcessorID = [ * int ]
PostInstallationInfo = {
? postConditions : [ * PostCondition ],
? postDirectives : [ * PostDirective ]
}
postConditions = 1
postDirectives = 2
PostCondition = ImageCondition / CustomCondition
PostDirective = CustomDirective
Text = {
* int => tstr
}
]]>NOTE: COSE structures are specified as “any” to enable CDDL tooling to process this CDDL without including all of the COSE specification. The same consideration applies to concise-software-identifier.Note: Line-breaks have been introduced to meet the character line limit.Raw OuterWrapper: 62 bytesa102583aa3010102020581a301814130021825038444a1011829a0f658208c
af9283b13666ca4e50f7a1eee86ba40b5e6a1d2ca39f7498b6a6a7be8d8d67A manifest with payload description only, authenticated by an ECDSA signature. The signing key is identified by the Subject Key Identifier.Raw OuterWrapper: 188 bytesa201d8628444a103182aa0f6818343a10126a1045820537ac93ac909e79990
914caa00fe87eeea637ef89b5512e5cb6e558a136ff98d5847304502201d65
938ec454354a6e866b468e9808db4ef36e97de09f98fda92e9c0e3302fc802
2100aff871fe581d3f6b831d74e46f9acd7a015e5548770b2a437970be9272
a7fbaa02583aa3010102020581a301814130021825038444a1011829a0f658
208caf9283b13666ca4e50f7a1eee86ba40b5e6a1d2ca39f7498b6a6a7be8d8d67Raw OuterWrapper: 522 bytesa301d8628444a103182aa0f6818343a10126a1045820537ac93ac909e79990914ca
a00fe87eeea637ef89b5512e5cb6e558a136ff98d58473045022100830cf142cc4a
df563392dc7e0430000158bf3720b28b7cea388b0f1a5f8918a802201def2df34d6
abd3b17c3425573ff2b7cacae3dd085e11dfc23bf0c60be51b7da0658cca10178c8
4c6f72656d20697073756d20646f6c6f722073697420616d65742c20636f6e73656
374657475722061646970697363696e6720656c69742e204e756e63207365642074
696e636964756e7420616e74652c206120736f64616c6573206c6967756c612e205
0686173656c6c757320756c6c616d636f72706572206f64696f20636f6d6d6f646f
20697073756d20656765737461732c207669746165206c6163696e6961206c656f2
06f726e6172652e2053757370656e646973736520706f7375657265207365642e02
58b9a60101020203a10182820150fa6b4a53d5ad5fdfbe9de663e4d41ffe8202506
e04d3c2488759e4a597b5e7cd4976530581a301814130021825038444a1011829a0
f658208caf9283b13666ca4e50f7a1eee86ba40b5e6a1d2ca39f7498b6a6a7be8d8
d6706a10181a2018141300281a20182010103820076687474703a2f2f666f6f2e62
61722f62617a2e62696e088444a1011829a0f658204e2714598479d8b6634805df5
019ef3420edff0329894acc91de8c8de16fb0cfText severed (textInfoExt deleted from OuterWrapper): 315 bytesa201d8628444a103182aa0f6818343a10126a1045820537ac93ac909e79990914ca
a00fe87eeea637ef89b5512e5cb6e558a136ff98d58473045022100830cf142cc4a
df563392dc7e0430000158bf3720b28b7cea388b0f1a5f8918a802201def2df34d6
abd3b17c3425573ff2b7cacae3dd085e11dfc23bf0c60be51b7da0258b9a6010102
0203a10182820150fa6b4a53d5ad5fdfbe9de663e4d41ffe8202506e04d3c248875
9e4a597b5e7cd4976530581a301814130021825038444a1011829a0f658208caf92
83b13666ca4e50f7a1eee86ba40b5e6a1d2ca39f7498b6a6a7be8d8d6706a10181a
2018141300281a20182010103820076687474703a2f2f666f6f2e6261722f62617a
2e62696e088444a1011829a0f658204e2714598479d8b6634805df5019ef3420edf
f0329894acc91de8c8de16fb0cfSeveral registries will be required for:standard Conditionsstandard Directivesstandard Processorsstandard text valuesEditor’s Note: A few registries would be good to allow easier allocation of new features.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 .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/suitArchives of the list can be found at:
https://www.ietf.org/mail-archive/web/suit/current/index.htmlWe would like to thank the following persons for their support in designing this mechanism:Milosch MeriacGeraint LuffDan RosJohn-Paul StanfordCarsten BormannHenk BirkholzOyvind RonningstadFrank Audun KvamtroKrzysztof ChruscinskiAndrzej PuzdrowskiMichael RichardsonDavid BrownFinally, we would like to thank the IETF SUIT working group chairs, Dave Thaler, David Waltermire, and Russ Housley, for their support.Key words for use in RFCs to Indicate Requirement LevelsIn many standards track documents several words are used to signify the requirements in the specification. These words are often capitalized. This document defines these words as they should be interpreted in IETF documents. This document specifies an Internet Best Current Practices for the Internet Community, and requests discussion and suggestions for improvements.A Universally Unique IDentifier (UUID) URN NamespaceThis specification defines a Uniform Resource Name namespace for UUIDs (Universally Unique IDentifier), also known as GUIDs (Globally Unique IDentifier). A UUID is 128 bits long, and can guarantee uniqueness across space and time. UUIDs were originally used in the Apollo Network Computing System and later in the Open Software Foundation\'s (OSF) Distributed Computing Environment (DCE), and then in Microsoft Windows platforms.This specification is derived from the DCE specification with the kind permission of the OSF (now known as The Open Group). Information from earlier versions of the DCE specification have been incorporated into this document. [STANDARDS-TRACK]The Base16, Base32, and Base64 Data EncodingsThis document describes the commonly used base 64, base 32, and base 16 encoding schemes. It also discusses the use of line-feeds in encoded data, use of padding in encoded data, use of non-alphabet characters in encoded data, use of different encoding alphabets, and canonical encodings. [STANDARDS-TRACK]CBOR Object Signing and Encryption (COSE)Concise Binary Object Representation (CBOR) is a data format designed for small code size and small message size. There is a need for the ability to have basic security services defined for this data format. This document defines the CBOR Object Signing and Encryption (COSE) protocol. This specification describes how to create and process signatures, message authentication codes, and encryption using CBOR for serialization. This specification additionally describes how to represent cryptographic keys using CBOR.A Firmware Update Architecture for Internet of Things DevicesVulnerabilities with Internet of Things (IoT) devices have raised the need for a solid and secure firmware update mechanism that is also suitable for constrained devices. Incorporating such update mechanism to fix vulnerabilities, to update configuration settings as well as adding new functionality is recommended by security experts. This document lists requirements and describes an architecture for a firmware update mechanism suitable for IoT devices. The architecture is agnostic to the transport of the firmware images and associated meta-data. This version of the document assumes asymmetric cryptography and a public key infrastructure. Future versions may also describe a symmetric key approach for very constrained devices.Firmware Updates for Internet of Things Devices - An Information Model for ManifestsVulnerabilities with Internet of Things (IoT) devices have raised the need for a solid and secure firmware update mechanism that is also suitable for constrained devices. Incorporating such update mechanism to fix vulnerabilities, to update configuration settings as well as adding new functionality is recommended by security experts. One component of such a firmware update is the meta-data, or manifest, that describes the firmware image(s) and offers appropriate protection. This document describes all the information that must be present in the manifest.