[HTC Wildfire S] no.human.being:
A signed IMG file is called an NBH. I've skimmed through the code of some utilities that handle NBH files and tried to work out how they are laid out. The layout is "layered" and seems to be quite complex, so don't count on it, but here's what I found out. I'm gonna describe the layers from "outside in" which is the order you'd encounter them when trying to decode an NBH into a raw IMG. When encoding an IMG into an NBH of course we have to do the steps in reverse order.

The NBH format

All NBH files start with a "magic value" of "R00FF\n" followed by a 16 byte (128 bit) "seed key". This key is later used for signature generation. It seems that its value may be arbitrarily chosen. Setting it to all-zeroes may make signature generation a bit easier.

The header is followed by a sequence of multiple blocks which are numbered with a sequence number starting with the value one (not zero!). Each block looks like this.

4 bytes: block size
4 bytes: signature size
1 byte: flag
<block size> bytes: data
<signature size> bytes: signature

The flag is set to 1 for all blocks containing data. The signature of each of these blocks is generated from the data the block contains. The size of the signature is 128 bytes (1024 bits). I believe (but haven't verified yet) that all of these values are stored in little-endian format.

To generate the signature, first a SHA-1 hash of "data[block size bytes] + flag[as 4 bytes big-endian integer!] + seed key[16 bytes] + sequencenumber[1 byte sequence number]" concatenated in memory is calculated. The signature is derived from the hash using RSA. RSA makes use of modular exponentiation. This operation takes three input values called "base", "exponent" and "modulus" and produces a single output value. The base is generated by taking the byte 0x01 followed by 90 bytes of 0xff followed by the following 16 byte sequence.

0x00 0x30 0x21 0x30 0x09 0x06 0x05 0x2b 0x0e 0x03 0x02 0x1a 0x05 0x00 0x04 0x14

This sequence is followed by the 20 byte (160 bit) SHA-1 hash that was generated from the block for a total of 127 bytes (127 seems strange, why not 128?). This together forms the base for the RSA exponentiation. The exponent is the private key and the modulus is part of the public key (public exponent and modulus form the public key).

This is done for all blocks. After the last block containing data there is another block with block size zero and flag set to 2 containing a signature created from an "empty data section" (so a buffer of size zero) but the rest of the signature generation seems just as it is done for all the other blocks.

The DBH format

The "payload" of all the signed blocks in the NBH combined form what is called a DBH. A DBH is quite a complex data structure of its own right. It begins with 8 bytes containing the word "HTCIMAGE" followed by 32 bytes of a zero-padded device name (this should be "Marvel" for the WFS).

Then there are 128 bytes of data describing the types of the sections contained within the DBH file. Each section type is described by an entry of 4 bytes so a DBH can contain up to 32 sections. Unused section have their type set to zero. An HBOOT image has its section type set to 0x200 so this is the type we should use and the other 31 sections should be marked as unused.

Then there are 128 bytes of data describing the offsets of the sections into the image file. The offsets are relative to the end of the DBH header. Since we only use one section we can set all offsets to zero. This will result in the first section starting directly after the DBH header. All other sections are declared as unused by their type field anyhow.

Then there are 128 bytes of data describing the length of the sections. We will set this to 1.048.576 bytes, which is two times the length of our HBOOT image. This is because there is redundancy in the data that is used for error correction and the redundant information is exactly as big as the "actual" information.

Then there are 32 bytes for the CID, which is stored as a zero-padded string followed by 16 bytes for the ROM version (like "x.y.zzz.a") and another 16 bytes for the language (e. g. "UK"), which are also zero-padded strings.

The header is followed by the payload of the DBH which is the actual memory content (e. g. HBOOT code) split into chunks of 512 bytes each which are always repeated two times for redundancy.

Implementing the modular exponentiation used for RSA could be difficult as it makes use of arbitrary-precision arithmetic. This would be horribly painful to implement in C. However, one could build the "signer" app in Java and make use of the "java.math.BigInteger" class to perform the modular exponentiation.

Some of the things seem extremely weird, e. g. that the data is split into chunks of 512 bytes which are always repeated two times. It seems that what follows the DBH header gets written to NAND by the HBOOT so this would mean that the data gets written to NAND including the redundancy. However, when you read the phone's NAND, you see "normal" code without such redundancy. Do we have an "original" NBH of an HBOOT which we could use to verify things like this?