release
dev builds
extras
themes manual
wiki
device status forums
mailing lists
IRC bugs
patches
dev guide



Wiki > Main > SbFileFormat (compare)

Difference: SbFileFormat (r14 vs. r13)

The sb format is used by most STMP chips to load the firmware. The format is different for different generations of chips. This page describes the sb format used by STMP 36xx and 37xx. It is used for example by Fuze+ (SansaFuzePlus). One can produce such a file using the elftosb2 program which can be found at Lyre project svn. The sbinfo Rockbox svn also contains an open source implementation of elftosb2 (see /utils/sbtools/). The sbtoelf utility which can be found in the Rockbox svn (next to elftosb) is able to decrypt and extract data from a .sb file, and can repack the code in several ELF files.

Format of the sb file. Everything is coded as little endian, even strings, except the "STMP" file magic.

Global file format

The .sb file consists of several blocks as show below

blockdescription
file header basic file header containing version info and sizes of the rest of the file
chunk headers this is a list of actual data blocks in the file
encryption data not much known about this
chunk bodies the actual data, aligned to blocks of 16 bytes
file signature encrypted SHA-1 sum of the whole encrypted file, padded with random data

File header

offsetlengthexamplemeaning
0x00 0x14 - SHA-1 sum of the rest of the file header (from 0x14-0x5F)
0x14 4 "STMP" file magic
0x18 2 01 01 Major and minor versions of the format
0x1A 2 00 01 a set of flags
0x1C 4 - total length of file in 16-byte units
0x20 4 0C 00 00 00 the elftosb2 program sets this to field (0x2A) + 2 x nr_keys = 6 + nr_chunks + 2 x nr_keys; probably the total size of headers (header+chunks+encryption data). Apparently this is the first boot tag block
0x24 4 00 00 00 00 First bootable section id (always 0 ?)
0x28 2 01 00 number of encryption keys
0x2A 2 0A 00 the elftosb2 program sets this to field (0x2C) + field (0x30) x field (0x2E) = 6+nr_chunks all the time; probably the offset to encryption data
0x2C 2 06 00 the elftosb2 program hardwires this field to 6
0x2E 2 04 00 number of following chunk headers
0x30 2 01 00 size of a chunk header in units of 16 bytes
0x32 6 - the elftosb2 program puts a random number here, however the fuze+ file has "sgtl" (= short for sigmatel?) at 0x34)
0x38 8 - creation time in microseconds since 2000/1/1 00:00:00
0x40 4 - product major version
0x44 4 - product minor version
0x48 4 - product sub version
0x4C 4 - component major version
0x50 4 - component minor version
0x54 4 - component sub version
0x58 2 00 00 drive tag
0x5A 6 - the elftosb2 program puts a random number here

The set of flags is as follows: bit 0 is display progress, bit 1 is verbose progress.

Chunk header

Chunk headers start at offset 0x60. Each chunk header is 16 bytes long and has the following structure. There are two types of chunks: boot sections and data sections.

offsetlengthexampledescription
0x0 4 "host" chunk name
0x4 4 - chunk offset in file in 16-byte units
0x8 4 - chunk size in 16-byte units
0xC 4 01 00 00 00 flags: bit 0 is bootable, bit 1 is cleartext (not encrypted)

See section about chunk data for more information about the content.

Encryption data

The elftosb2 program uses AES-128 in CBC mode. Internally, all important data is encrypted using a random key that will denote PK. This random key PK is written in an encrypted form in the sb file using the keys specified to the elftosb2 program. At this place of the file, the elftosb2 program outputs one 32 bytes value per key:

offsetlengthexampledescription
0x0 16 - this is the CBC-MAC of the header plus all the chunk headers (using the ith key if this is the ith key block, and using a 0 as IV)
0x10 16 - this is PK encrypted with the ith key using the first 16-bytes of the sb header as IV (ie part of SHA-1 signature)

Notice that if there are several keys, it is possible to cross-check PK with the several keys.

Final signature

The final signature is a 32-bytes block. When decrypted using PK, it consists of the SHA-1 of the whole file (ie the encrypted file) except the last 32-bytes (of course); since the SHA-1 is 20-bytes long, it is padded with random data.

offsetlengthexampledescription
0x0 20 - SHA-1 of the whole file except the last 32 bytes
0x14 12 - random data

Chunk bodies

In the fuze+ firmware file, the following chunks were found:

  • a chunk consisting of just NULL characters
  • "host", encrypted
  • "play", encrypted
  • "rsrc", plain

It is suspected that only boot sections are encrypted. A section is encrypted in AES-128 CBC mode using the PK key (see encryption data section) and the first 16-bytes of the sb header as IV (ie part of SHA-1 signature). The boot sections have a special format (when decrypted) to explain where load the instructions, which part of memory to fill and how to call functions. The format of the data sections has not been investigated.

Boot section format

A boot section consist of a list of instruction. Each instruction starts with a 4-byte header with indicates what type of instruction it is. All values are in little-endian. All instruction are of size 16-bytes even, unused bytes are set to zero.

offsetlengthexampledescription
0x0 1 - checksum (see explaination below)
0x1 1 0x06 Opcode
0x2 2 - Always zero except for tag command

The checksum is computed this way. This is 90 plus the sum of all bytes of the instruction except the first one (to avoid circular reference), modulo 2^8=256. Here is an example:

offsetlengthexampledescription
0x0 1 0x4F checksum
0x1 1 0x02 Opcode (Load)
0x2 2 0x0000 Always zero
0x4 4 0x08048134 Loading address
0x8 4 0x00000013 Length of the data (in bytes)
0xC 4 0x099b99e2 CRC of the data

We check that 0x4F = 90+(0x2+0x00+0x00)+(0x08+0x04+0x81+0x34)+(0x00+0x00+0x00+0x13)+(0x09+0x9b+0x99+0xe2)

Nop instruction

The nop instruction terminates the boot section (it seems), it only consists of the header with opcode 0.

offsetlengthexampledescription
0x0 1 - checksum
0x1 1 0x00 Opcode
0x2 2 0x0000 Always zero

Tag instruction

The tag instruction has the opcode 1 and has unknown format and semantics.

offsetlengthexampledescription
0x0 1 - checksum
0x1 1 0x01 Opcode
0x2 2 - Unknown
? ? ? ?

Load instruction

The load instruction has the opcode 2 and is of variable size. It starts with a 16-byte header followed by some data. The header indicates the size of the data, the address at which to load it and include a CRC checksum.

offsetlengthexampledescription
0x0 1 - checksum
0x1 1 0x02 Opcode
0x2 2 0x0000 Always zero
0x4 4 - Loading address
0x8 4 - Length of the data (in bytes)
0xC 4 - CRC of the data (see explaination below)

The data is padded so next instruction will be aligned on a 16-byte boundary. The padding data is random and IS TAKEN INTO ACCOUNT in the CRC. The CRC is a classical CRC32 algorithm, the tables used can be found in the SVN.

Fill instruction

The fill instruction has the opcode 3 and is of fixed size (16-bytes). The instruction indicates the size of memory range to fill, the starting address and the pattern.

offsetlengthexampledescription
0x0 1 - checksum
0x1 1 0x03 Opcode
0x2 2 0x0000 Always zero
0x4 4 - Filling address
0x8 4 - Length of the area to fill (in bytes ?)
0xC 4 - Pattern

Jump instruction

The jump instruction is the same as the call instruction (except for the semantics of course) and has opcode 4.

Call instruction

The call instruction has opcode and has a calling address as well as a argument for the function.

offsetlengthexampledescription
0x0 1 - checksum
0x1 1 0x05 Opcode
0x2 2 0x0000 Always zero
0x4 4 - Calling address
0x8 4 0x0000 Always zero
0xC 4 - Argument

Mode instruction

The mode instruction has opcode 6 and has unknown format and semantics.

offsetlengthexampledescription
0x0 1 - checksum
0x1 1 0x06 Opcode
0x2 2 0x0000 Always zero
? ? ? ?

Encryption notes

See Block ciphers on wikipedia for more information on CBC mode. See CBC-MAC on wikipedia for more information on CBC-MAC. When nothing is said, it means the IV (Initialisation Vector) is taken to be 0.

-- AmauryPouly - 26 Nov 2010

r18 - 30 Jan 2012 - 14:34:34 - AmauryPouly

Revision r14 - 17 Apr 2011 - 23:31 - AmauryPouly
Revision r13 - 16 Apr 2011 - 14:16 - AmauryPouly
Copyright by the contributing authors.