From 25e2761c669035c991dff115f03e34f1505bd97a Mon Sep 17 00:00:00 2001 From: Mateusz Michalek Date: Mon, 9 Dec 2024 15:34:31 +0100 Subject: [PATCH] doc: compression format describes internals of signed image with compressed payload. Signed-off-by: Mateusz Michalek Signed-off-by: Anna Wojdylo --- docs/compression_format.md | 172 +++++++++++++++++++++++++++++++++++++ docs/images/decomp.png | Bin 0 -> 41701 bytes docs/imgtool.md | 126 +++++++++++++++++++-------- 3 files changed, 263 insertions(+), 35 deletions(-) create mode 100644 docs/compression_format.md create mode 100644 docs/images/decomp.png diff --git a/docs/compression_format.md b/docs/compression_format.md new file mode 100644 index 000000000..ddb99d534 --- /dev/null +++ b/docs/compression_format.md @@ -0,0 +1,172 @@ +# Compressed binary file internals + +This article describes the structure of the +`zephyr.signed.bin` file when image +compression is enabled. You do not need to know these details to use the +image compression subsystem, but they can be beneficial if you want to +use them for verification or custom integration purposes. + +For an example, see the following structure of the file: + +![LZMA header](./images/decomp.png) + +## [LZMA Header](#LZMA-Header) + +The Lempel-Ziv-Markov chain Algorithm (LZMA) header is crucial for files +compressed using the LZMA method. It contains metadata essential for +decompression. The `lzma2_header` encodes compression parameters using +two bytes. + +### [Calculating compression parameters](#Calculating-compression-parameters) + +Compression parameters can be calculated, retrieved, or changed +depending on your needs. For details, see the following sections. + +#### [Default values](#Default-values) + +Compression parameters have the following default values: + +- `dict_size`: 131072 +- `pb`: 2 +- `lc`: 3 +- `lp`: 1 + +#### [Adjusting dictionary size](#Adjusting-dictionary-size) + +You can calculate the `dict_size` using the following method: + +``` {.c} +unsigned int i = 0; + +for (i = 0; i < 40; i++) { + if (raw_dict_size <= (((uint32_t)2 | ((i) & 1)) << ((i) / 2 + 11))) { + break; + } +} +dict_size = (uint8_t)i; +``` + +With this method, `dict_size` can have one of the following values: + + |Hex Value | Size | + |-----------|------------| + |0x00 | 4096 | + |0x01 | 6144 | + |0x02 | 8192 | + |0x03 | 12288 | + |0x04 | 16384 | + |0x05 | 24576 | + |0x06 | 32768 | + |0x07 | 49152 | + |0x08 | 65536 | + |0x09 | 98304 | + |0x0a | 131072 | + |0x0b | 196608 | + |0x0c | 262144 | + |0x0d | 393216 | + |0x0e | 524288 | + |0x0f | 786432 | + |0x10 | 1048576 | + |0x11 | 1572864 | + |0x12 | 2097152 | + |0x13 | 3145728 | + |0x14 | 4194304 | + |0x15 | 6291456 | + |0x16 | 8388608 | + |0x17 | 12582912 | + |0x18 | 16777216 | + |0x19 | 25165824 | + |0x1a | 33554432 | + |0x1b | 50331648 | + |0x1c | 67108864 | + |0x1d | 100663296 | + |0x1e | 134217728 | + |0x1f | 201326592 | + |0x20 | 268435456 | + |0x21 | 402653184 | + |0x22 | 536870912 | + |0x23 | 805306368 | + |0x24 | 1073741824 | + |0x25 | 1610612736 | + |0x26 | 2147483648 | + |0x27 | 3221225472 | + +#### [Calculating literal context, literal pos, and pos bits](#Calculating-literal-context-literal-pos-and-pos-bits) + +The second byte of the `lzma2_header` carries the following parameters: + +- `lc`, which specifies a number of literal context bits + +- `lp`, which specifies a number of literal pos bits + +- `pb`, which specifies a number of pos bits + + These parameters are encoded with the following formula: + + ``` {.c} + pb_lp_lc = (uint8_t)((pb * 5 + lp) * 9 + lc); + ``` + + To decode these values from the combined `pb_lp_lc` byte, run the + following code: + + ``` {.c} + lc = pb_lp_lc % 9; + pb_lp_lc /= 9; + pb = pb_lp_lc / 5; + lp = pb_lp_lc % 5; + ``` + +## [Extracting LZMA stream from image](#Extracting-LZMA-stream-from-image) + +To extract and decompress the LZMA stream from the image, follow these +steps: + +1. Determine the offset of the compressed stream by adding the + `lzma2_header` size and the value stored under + `image_header.ih_hdr_size`. For the size of the compressed stream, + see `image_header.ih_img_size`. +2. If the compressed stream is isolated and stored in a file named + `raw.lzma`, you can perform + decompression using the following commands: + + - Without an ARM thumb filter: + + ``` {.bash} + unlzma --lzma2 --format=raw --suffix=.lzma raw.lzma + ``` + + - With an ARM thumb filter: + + ``` {.bash} + unlzma --armthumb --lzma2 --format=raw --suffix=.lzma raw.lzma + ``` + +Once the command is executed you will see a newly created file named +`raw`, which is identical to the +image before compression. + +## [TLVs](#TLVs) + +The following Type-Length-Values (TLVs) are used in the context of +decompressed images: + +- `DECOMP_SIZE (0x70)`: Specifies the size of the decompressed image. +- `DECOMP_SHA (0x71)`: Contains the hash of the decompressed image. +- `DECOMP_SIGNATURE (0x72)`: Holds the signature of either the hash or + the entire image. + +These TLVs are placed in the protected TLV section, ensuring they are +included in the hashing and signature calculations during the +verification process. The process for choosing the type of cryptographic +signature and hash algorithm used for securing the image is the same, +regardless of whether the image has undergone compression. + +## [Sample](#Sample) + +For practical implementation, you can find a simple stand-alone +verification program under the following path +`bootloader/mcuboot/samples/compression_test/independent_cmp.c` + +This program demonstrates how to independently verify the integrity and +authenticity of a decompressed image using the specified TLVs. diff --git a/docs/images/decomp.png b/docs/images/decomp.png new file mode 100644 index 0000000000000000000000000000000000000000..a24220fa5c60fd71e78e37ce49461b5ebf26d2bb GIT binary patch literal 41701 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%0A@kot7t_AY(Jd;cEV?r*7diEE3yJRuZn-gc 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,), ... " + --pad-sig Add 0-2 bytes of padding to ECDSA signature + (for mcuboot <1.5) + -H, --header-size INTEGER [required] + --pad-header Add --header-size zeroed bytes at the + beginning of the image + -S, --slot-size INTEGER Size of the slot. If the slots have + different sizes, use the size of the + secondary slot. [required] + --pad Pad image to --slot-size bytes, adding + trailer magic + --confirm When padding the image, mark it as confirmed + (implies --pad) + -M, --max-sectors INTEGER When padding allow for this amount of + sectors (defaults to 128) + --boot-record sw_type Create CBOR encoded boot record TLV. The + sw_type represents the role of the software + component (e.g. CoFM for coprocessor + firmware). [max. 12 characters] + --overwrite-only Use overwrite-only instead of swap upgrades + -e, --endian [little|big] Select little or big endian + -c, --clear Output a non-encrypted image with encryption + capabilities,so it can be installed in the + primary slot, and encrypted when swapped to + the secondary. + --skip-encryption Set encryption flags and TLV's without + applying encryption. + --compression [disabled|lzma2|lzma2armthumb] + Enable image compression using specified + type. Will fall back without image + compression automatically if the compression + increases the image size. + --encrypt-keylen [128|256] When encrypting the image using AES, select + a 128 bit or 256 bit key len. + -E, --encrypt filename Encrypt image using the provided public key. + (Not supported in direct-xip or ram-load + mode.) + --save-enctlv When upgrading, save encrypted key TLVs + instead of plain keys. Enable when + BOOT_SWAP_SAVE_ENCTLV config option was set. + -F, --rom-fixed INTEGER Set flash address the image is built for. + -L, --load-addr INTEGER Load address for image when it should run + from RAM. + -x, --hex-addr INTEGER Adjust address in hex output file. + -R, --erased-val [0|0xff] The value that is read back from erased + flash. + --custom-tlv [tag] [value] Custom TLV that will be placed into + protected area. Add "0x" prefix if the value + should be interpreted as an integer, + otherwise it will be interpreted as a + string. Specify the option multiple times to + add multiple TLVs. + --non-bootable Mark the image as non-bootable. + -h, --help Show this message and exit. The main arguments given are the key file generated above, a version field to place in the header (1.2.3 for example), the alignment of the @@ -111,6 +161,12 @@ the load address (in Intel Hex terms, the Extended Linear Address record) to adjust for the new bytes prepended to the file. The load address of all data existing in the file should not change. +The `--compression` option enables LZMA compression over payload. Details +about internals of image generated with this option can be found here +[here](./compression_format.md) +This isn't fully supported on the embedded side but can be utilised when +project is built on top of the mcuboot. + The `--slot-size` argument is required and used to check that the firmware does not overflow into the swap status area (metadata). If swap upgrades are not being used, `--overwrite-only` can be passed to avoid adding the swap