200 lines
8.0 KiB
Plaintext
200 lines
8.0 KiB
Plaintext
Image3 Tagged Object Format
|
|
===========================
|
|
|
|
Overview
|
|
--------
|
|
The Image3 format attempts to address some of the shortcomings of the Image2 and 'DFU' formats
|
|
based on lessons learned during their deployment.
|
|
|
|
Compared with Image2, Image3 features far fewer fields in the fixed portion of the header, and
|
|
discards many of the optional behaviours that have been found to be redundant and/or confusing.
|
|
|
|
Compared with the DFU format, Image3 provides a flexible mechanism for extending image metadata
|
|
and a simpler signing and encryption strategy.
|
|
|
|
|
|
Description
|
|
-----------
|
|
The Image3 object format features a compact fixed header, followed by a variable-length buffer
|
|
containing (tag,data) tuples. A balanced approach is taken towards the use of structured tag data;
|
|
tags should avoid collecting unrelated data items, but structured tags are acceptable.
|
|
|
|
The header contains a magic number ('Img3') identifying the format, size information for the tag
|
|
buffer and signed area, and a type value used to describe the contents of the image.
|
|
|
|
When placed into storage 'owned' by the device, a field in the fixed header can be used to indicate
|
|
the skip distance to the next image. This field should be considered a hint only, as it is not
|
|
signed.
|
|
|
|
Code handling tags should be careful not to assume any set of valid tags; new tags may be added
|
|
at any point.
|
|
|
|
|
|
Security
|
|
--------
|
|
Image3 objects are not mutable once hashed and signed. The signing of an image is indicated by
|
|
a non-zero value for the "signed length" header field, which further implies the presence of
|
|
two tags containing the signed hash and applicable certificate chain. These tags are always
|
|
placed last in the buffer, and are necessarily not covered by the signature. The two tags
|
|
contain a signed hash (placed first) and the certificate chain buffer (placed last).
|
|
|
|
The signed hash covers the signed length field and the buffer as described by that length. Code
|
|
handling Image3 images must range-check the buffer length against whatever local buffer is in use.
|
|
Once the signed hash is validated, the internal structure of the object can be trusted and further
|
|
bounds checking is not required for security purposes.
|
|
|
|
When an Image3 object is written into local storage (storage 'owned' by a given system) the signed
|
|
hash should be encrypted using a system-private key. When the object is subsequently read back the
|
|
hash should likewise be decrypted. This operation prevents objects being 'stolen' by code that does
|
|
not have access to the system-private key, limiting the potential impact of leaked objects.
|
|
|
|
|
|
Format Details
|
|
--------------
|
|
In the descriptions below, tags may be described as 'unique', in which case only one may be present,
|
|
or 'multiple' in which case more than one may legally be present. Additionally, tags may be
|
|
mandatory or optional.
|
|
|
|
|
|
Image header
|
|
''''''''''''
|
|
struct image3_header {
|
|
UInt32 ihMagic = 'Img3';
|
|
UInt32 ihSkipDistance;
|
|
UInt32 ihBufferLength;
|
|
UInt32 ihSignedLength;
|
|
UInt32 ihType;
|
|
UInt8 ihBuffer[];
|
|
};
|
|
|
|
|
|
ihSkipDistance is the byte offset from the address of the current header to the next header when the
|
|
object is placed in a byte-addressed storage container, e.g. ROM.
|
|
|
|
ihBufferLength is the valid length of the buffer in bytes.
|
|
|
|
ihSignedLength is the length of the portion of the buffer which is signed. This is thus the offset
|
|
from the start of the buffer to the tag containing the signed hash.
|
|
|
|
ihType is the four-byte type tag for the image. This is typically consulted before signature
|
|
verification when scanning a collection of images, but as it is contained within the signed area
|
|
providing verification is successful it can be considered trusted.
|
|
|
|
|
|
Tag header
|
|
''''''''''
|
|
struct image3_tag {
|
|
UInt32 itTag = 'xxxx';
|
|
UInt32 itLength;
|
|
UInt32 itSkipDistance;
|
|
UInt8 itBuffer[];
|
|
};
|
|
|
|
itLength is the valid length in bytes of the data within the tag's data buffer.
|
|
|
|
itSkipDistance is the distance in bytes from the address of the current tag header to the next tag
|
|
header. This value may be adjusted in order to obtain specific alignment of the payload of
|
|
subsequent tags.
|
|
|
|
|
|
Signed Hash - "SHSH" - unique, optional
|
|
'''''''''''''''''''''''''''''''''''''''
|
|
The SHSH tag contains the signed SHA-1 hash of the signed portion of the buffer. If present it is
|
|
always the second-last tag in the buffer.
|
|
|
|
|
|
Certificate Chain - 'CERT' - unique, optional
|
|
'''''''''''''''''''''''''''''''''''''''''''''
|
|
The CERT tag contains the opaque certificate chain that will be used to validate the signed hash.
|
|
If present it is always the last tag in the buffer.
|
|
|
|
Note that it is permitted for the leaf certificate in the certificate chain to carry an Image3
|
|
object (which is assumed to be signed/certified by the chain itself), and trust evaluation of
|
|
an object may add valid tags to the object by way of this embedded image.
|
|
|
|
|
|
Version - 'VERS' - unique, optional
|
|
'''''''''''''''''''''''''''''''''''
|
|
Free-form 7-bit ascii version information
|
|
|
|
|
|
Security Epoch - 'SEPO' - unique, optional
|
|
''''''''''''''''''''''''''''''''''''''''''
|
|
32-bit unsigned little-endian value.
|
|
|
|
This tag provides the security epoch for which the image is considered valid. If the tag is
|
|
not present, the image is valid for any epoch.
|
|
|
|
|
|
Security Domain - 'SDOM' - unique, optional
|
|
'''''''''''''''''''''''''''''''''''''''''''
|
|
Describes the organisational domain for which this image can be considered valid.
|
|
|
|
This tag is supplied by the leaf certificate rather than the image itself, in order to constrain the
|
|
uses to which a given certificate can be put.
|
|
|
|
#define kImage3SecurityDomainManufacturer 0
|
|
#define kImage3SecurityDomainDarwin 1
|
|
|
|
|
|
Production Status - 'PROD' - unique, optional
|
|
'''''''''''''''''''''''''''''''''''''''''''''
|
|
Indicates whether this is a 'production' status image.
|
|
|
|
This tag is supplied by the leaf certificate rather than the image itself, in order to constrain the
|
|
uses to which a given certificate can be put.
|
|
|
|
#define kImage3SecurityProductionStatus 1
|
|
|
|
|
|
Chip Type ID - 'CHIP' - multiple, optional
|
|
''''''''''''''''''''''''''''''''''''''''''
|
|
Indicates which specific chip type the image is valid for.
|
|
|
|
This tag is supplied by the leaf certificate rather than the image itself, in order to constrain the
|
|
uses to which a given certificate can be put.
|
|
|
|
|
|
Board Type ID - 'BORD' - multiple, optional
|
|
Unique Chip ID - 'ECID' - multiple, optional
|
|
''''''''''''''''''''''''''''''''''''''''''''
|
|
These tags allow for the restriction of objects to specific chip or board types, or specific chips.
|
|
|
|
For the payload to be considered valid, one of each present tag type must match the device. In the
|
|
absence of a tag type, all devices are assumed to match that type.
|
|
|
|
|
|
Data Payload - 'DATA' - unique, optional
|
|
''''''''''''''''''''''''''''''''''''''''
|
|
This tag is used in the common case where the object has a plain data payload.
|
|
|
|
|
|
Encryption Keybag - 'KBAG' - multiple, optional
|
|
'''''''''''''''''''''''''''''''''''''''''''''''
|
|
In the case where the data payload is encrypted, one or more keybag tags will be present. The data
|
|
payload is never encrypted with a key directly known to the consumer; the payload key is placed in a
|
|
keybag, encrypted by a key known to a specific consumer. The keybag includes a selector mechanism
|
|
that allows the consumer to determine which keybag is applicable.
|
|
|
|
The presence of a keybag indicates that the data payload is encrypted.
|
|
|
|
typedef struct {
|
|
u_int32_t kbSelector;
|
|
#define kImage3KeybagSelectorNoKey (0)
|
|
#define kImage3KeybagSelectorChipUnique (1)
|
|
u_int32_t kbKeySize;
|
|
u_int8_t kbIVBytes[16];
|
|
u_int8_t kbKeyBytes[32];
|
|
} Image3TagKBAG;
|
|
|
|
The kbKeySize value is expresed in bits.
|
|
|
|
The kbSelector indicates which key is to be used to decrypt the key in kbKeyBytes. The decryption
|
|
buffer should be padded with zeroes before decrypting the key.
|
|
|
|
kImage3KeybagSelectorNoKey The key is not encrypted; use it as-is (this is not useful
|
|
except for testing purposes).
|
|
|
|
kImage3KeybagSelectorChipUnique The key is encrypted with a key unique to the chip type;
|
|
this is generally referred to as GID 0.
|