Difference between revisions of "IMG1"
Plzdonthaxme (talk | contribs) m (add verification routine and misc changes) |
|||
Line 9: | Line 9: | ||
== Header Format == | == Header Format == | ||
− | struct | + | struct IMG1 { |
− | + | u8 magic[4]; // 0x0, SoC digits, eg. `8720`. | |
− | + | u8 version[3]; // 0x4, `1.0` or `2.0` | |
− | + | u8 format; // 0x7, Encryption/signature format. See below. | |
− | + | u32 entrypoint; // 0x8, Offset to jump to within body (after header). | |
− | + | u32 bodyLen; // 0xC, Size of the image body, ie. the data loaded into memory, before the | |
// signature/certificates start, after the header. | // signature/certificates start, after the header. | ||
− | + | u32 dataLen; // 0x10, Size of everything that's not the header (body + signature + certificates). | |
− | + | u32 footerCertOffset; // 0x14, Offset of certificate start (after header). | |
− | + | u32 footerCertLen; // 0x18, Size of certificate bundle. | |
− | + | u8 salt[32]; // 0x1C, Random data. | |
− | + | u16 unk1; // 0x3C | |
− | + | u16 unk2; // 0x3E, Security epoch? | |
− | + | u8 headerSign[16]; // 0x40, AES-encrypted SHA1 signature of everything up to headerSign. | |
− | + | u8 headerLeftover[4]; // 0x50, Last four bytes of unencrypted SHA1, usually leftover in images, but not | |
// checked by firmware. Curiosity. | // checked by firmware. Curiosity. | ||
} | } | ||
− | The | + | The body is padded to either 0x800 (S5L8900 (iOS)/S5L8702), 0x600 (S5L8720/S5L8930) or 0x400 (S5L8723/S5L8740) bytes. The different sections are a bit tricky to reason about, here's an attempted overview: |
0: Header (0x40 + 0x14 bytes, first 0x40 signed into last 0x14 bytes) | 0: Header (0x40 + 0x14 bytes, first 0x40 signed into last 0x14 bytes) | ||
Line 39: | Line 39: | ||
The body signature is always 0x80 bytes long, and its length is not counted into bodyLen or footerCertLen. | The body signature is always 0x80 bytes long, and its length is not counted into bodyLen or footerCertLen. | ||
− | A few assertions should hold: | + | A few assertions should hold for non-Touch iPods: |
# File size == $header_size + bodyLen + footerCertLen + 0x80 | # File size == $header_size + bodyLen + footerCertLen + 0x80 | ||
# dataLen = bodyLen + 0x80 + footerCertLen | # dataLen = bodyLen + 0x80 + footerCertLen | ||
+ | |||
+ | It is worth noting that for early iOS devices, dataLen is actually the offset to the body signature. It is unknown why Apple has changed this to the data length. | ||
=== Encryption/Signature Formats === | === Encryption/Signature Formats === | ||
Line 59: | Line 61: | ||
|} | |} | ||
− | DFU mode in N3G,N4G,N5G seems only accepts X509_SIGNED_ENCRYPTED. | + | DFU mode in N3G, N4G, N5G seems only accepts X509_SIGNED_ENCRYPTED. |
Other boot modes (notably in N3G) seem to accept other formats, but that's to be verified. N4G+/2.0 do not accept any non-X509 formats. | Other boot modes (notably in N3G) seem to accept other formats, but that's to be verified. N4G+/2.0 do not accept any non-X509 formats. | ||
Line 67: | Line 69: | ||
Nano4G+ use 2.0. Everything else uses 1.0. | Nano4G+ use 2.0. Everything else uses 1.0. | ||
− | 1.0 bootroms supports encryption formats 1,2, 3 and 4. 2.0 only supports encryption formats 3 and 4. | + | 1.0 bootroms supports encryption formats 1, 2, 3 and 4. 2.0 only supports encryption formats 3 and 4. |
When uploading IMG1 images via DFU, 1.0 images need to be suffixed with a CRC32 of their content. 2.0 images don't need the CRC32. | When uploading IMG1 images via DFU, 1.0 images need to be suffixed with a CRC32 of their content. 2.0 images don't need the CRC32. | ||
Line 85: | Line 87: | ||
// data is ready, ship it! | // data is ready, ship it! | ||
− | + | As after the 0x10 bytes of the AES-encrypted SHA1 signature, there are 4 bytes of unencrypted SHA1 (because a SHA1 digest is 0x14 bytes, while an AES128 block is 0x10 bytes). This means that you can check the header signature yourself (or, well, 32 bits of the signature) by performing the following: | |
− | + | sha1(data[0:0x40]).digest()[-4:] == data[0x50:0x54] | |
This has likely zero security implications, but is nonetheless a fascinating curiosity. | This has likely zero security implications, but is nonetheless a fascinating curiosity. | ||
+ | |||
+ | === Verification Routine === | ||
+ | |||
+ | There are 2 signatures that may be verified, those being the header signature and the body signature. | ||
+ | |||
+ | The header signature in full may be verified by taking the SHA1 digest of data[0:0x40], encrypting it with the Global/GID key, and comparing it with the header signature. | ||
+ | |||
+ | The body signature may be verified by first finding the leaf certificate, taking the public key from it, then verifying the body signature with the body data (defined as data[bodyPad:bodyPad + bodyLen]) and the public key. |
Revision as of 04:55, 18 April 2023
Contents
Introduction
IMG1 is a pseudonym for the image format used by early iOS devices and all S5L-based iPods.
It is sometimes called the '8900' image, which is how it was called on the original iPhone / S5L8900. It is also sometimes called the 'DFU image' format (because it's used in DFU mode to load WTF).
The iPhone Wiki has some basic information about the format. However, that only describes the '1.0' version of IMG1. The lineage of IMG1 has continued in iPods long after iOS-based devices stopped its use, with IMG2/IMG3 never making it to the newer non-Touch iPods. Here we describe the known usage of IMG1, including its 2.0 version, in clickwheel iPods and non-iBoot bootroms.
Header Format
struct IMG1 { u8 magic[4]; // 0x0, SoC digits, eg. `8720`. u8 version[3]; // 0x4, `1.0` or `2.0` u8 format; // 0x7, Encryption/signature format. See below. u32 entrypoint; // 0x8, Offset to jump to within body (after header). u32 bodyLen; // 0xC, Size of the image body, ie. the data loaded into memory, before the // signature/certificates start, after the header. u32 dataLen; // 0x10, Size of everything that's not the header (body + signature + certificates). u32 footerCertOffset; // 0x14, Offset of certificate start (after header). u32 footerCertLen; // 0x18, Size of certificate bundle. u8 salt[32]; // 0x1C, Random data. u16 unk1; // 0x3C u16 unk2; // 0x3E, Security epoch? u8 headerSign[16]; // 0x40, AES-encrypted SHA1 signature of everything up to headerSign. u8 headerLeftover[4]; // 0x50, Last four bytes of unencrypted SHA1, usually leftover in images, but not // checked by firmware. Curiosity. }
The body is padded to either 0x800 (S5L8900 (iOS)/S5L8702), 0x600 (S5L8720/S5L8930) or 0x400 (S5L8723/S5L8740) bytes. The different sections are a bit tricky to reason about, here's an attempted overview:
0: Header (0x40 + 0x14 bytes, first 0x40 signed into last 0x14 bytes) 0x54: Padding until $header_size (magic dependent, 0x600 in this example) 0x600: Body, bodyLen bytes. ... 0x600 + bodyLen: body signature (for X509 formats) 0x680 + bodyLen (also 0x600+footerCertLen): certificate bundle (for X509 formats) 0x680 + bodyLen + footerCertLen: end of file.
The body signature is always 0x80 bytes long, and its length is not counted into bodyLen or footerCertLen.
A few assertions should hold for non-Touch iPods:
- File size == $header_size + bodyLen + footerCertLen + 0x80
- dataLen = bodyLen + 0x80 + footerCertLen
It is worth noting that for early iOS devices, dataLen is actually the offset to the body signature. It is unknown why Apple has changed this to the data length.
Encryption/Signature Formats
Format (number) | Header signed (SHA1+AES) | Body encrypted | Body signed (X509/RSA) | AES Operation | Notes |
---|---|---|---|---|---|
SIGNED_ENCRYPTED (1) | ✅ | ✅ | ❌ | Encryption, Global/GID Key | Not accepted in 2.0. |
SIGNED (2) | ✅ | ❌ | ❌ | Encryption, Global/GID Key | Not accepted in 2.0. |
X509_SIGNED_ENCRYPTED (3) | ✅ | ✅ | ✅ | Decryption, Global/GID Key | Most (all?) released images have this type |
X509_SIGNED (4) | ✅ | ❌ | ✅ | Decryption, Global/GID Key |
DFU mode in N3G, N4G, N5G seems only accepts X509_SIGNED_ENCRYPTED.
Other boot modes (notably in N3G) seem to accept other formats, but that's to be verified. N4G+/2.0 do not accept any non-X509 formats.
Differences between v1.0 and 2.0
Nano4G+ use 2.0. Everything else uses 1.0.
1.0 bootroms supports encryption formats 1, 2, 3 and 4. 2.0 only supports encryption formats 3 and 4.
When uploading IMG1 images via DFU, 1.0 images need to be suffixed with a CRC32 of their content. 2.0 images don't need the CRC32.
Differences between iBoot/SecureROM and iPod images
The iPod images do not use 'Key 0x837', and in fact use the Global/GID key for all AES operations.
The iPod images are sometimes decrypted using the encrypt direction of the AES engine (formats 1 and 2) and sometimes with the decrypt direction of the AES engine (formats 3 and 4). iBoot/SecureROM images seem to all use the decrypt direction.
Leftover SHA in header
It seems like whatever generates IMG1 images does so in the following pseudocode:
sha1(src=data, srcLen=0x40, dst=data+0x40) aes(src=data+0x40, size=0x10) // data is ready, ship it!
As after the 0x10 bytes of the AES-encrypted SHA1 signature, there are 4 bytes of unencrypted SHA1 (because a SHA1 digest is 0x14 bytes, while an AES128 block is 0x10 bytes). This means that you can check the header signature yourself (or, well, 32 bits of the signature) by performing the following:
sha1(data[0:0x40]).digest()[-4:] == data[0x50:0x54]
This has likely zero security implications, but is nonetheless a fascinating curiosity.
Verification Routine
There are 2 signatures that may be verified, those being the header signature and the body signature.
The header signature in full may be verified by taking the SHA1 digest of data[0:0x40], encrypting it with the Global/GID key, and comparing it with the header signature.
The body signature may be verified by first finding the leaf certificate, taking the public key from it, then verifying the body signature with the body data (defined as data[bodyPad:bodyPad + bodyLen]) and the public key.