Metadata format - galaxy4public/hkmcavn-tools GitHub Wiki
NOTE: this page is going to be rewritten soon since it contains quite a few guesses, which are not fully investigated.
Each encrypted file in the firmware distribution has the metadata structure appended at the end. The size of that structure is 16420 bytes and it contains the signature of the metadata structure along with the padding bytes used to implement incomplete block decryption and a set of sha256 check sums across different parts of the file. This page describes the structure in detail.
struct __attribute__((packed)) metadata
{
union {
struct {
char magic[4];
char hash[32];
};
char header[36];
};
char aes_padding[16];
int32_t signature_store[2044];
char key_store[8192];
}
Offset | Length | Type | Value | Description |
---|---|---|---|---|
0 | 2 | char[2] | TE |
The metadata structure magic signature |
2 | 1 | char | 2 |
Can be either R (for version 2) or 2 (for version 3). As of Dec 2022, only version 3 is supported. |
3 | 1 | char | (unused) | |
4 | 32 | char[32] | SHA256 checksum over the entire metadata structure starting from offset of 36 bytes initialised by first 16 bytes from SHA256(<basename><size> ), where <basename> is the base name of the file the metadata is attached to and <size> is the file size - size of the metadata. |
|
36 | 16 | char[16] | A vector of padding bytes used for the AES128-CBC decryption of the unaligned last block (basically, as it is implemented in firmware, the unencrypted data is padded with \0 to the 16 byte block boundary before the encryption and the value of the encrypted padded bytes is saved as a vector here to assist with the decryption in the future) |
|
52 | 8176 | int32[2044] char[8176] |
An area storing a spread out encrypted byte array which contains a slightly modified RSA PKCS#1 v1.5 signature over the 99% of the encrypted file when read in 512 blocks. The modification is that the SHA256 calculation is initialised similarly to the one above with first 16 bytes produced by SHA(<basename><size> ). The spread out algorithm is reading the first int32 and calculates step as int32[0] % 23 + 8 , then it assembles a byte array by reading bytes at a step interval from the area. The number of bytes read by the algorithm may vary from 272 (with step of 30 ) to 1022 (with step of 8 ). The original code allocates a buffer of 256 bytes for the array and always fills it using the logic described above. |
|
8228 | 8192 | char[8192] | A key store area. Observed are RSA encrypted AES128 keys (16 bytes long) spread over the area with a step of 12 with the first encrypted bytes starting at offset 16 (from the start of the area). Additionally, the corresponding public RSA key is stored alongside the AES128 key and The original code collects 518 bytes |
DecryptToPIPE
utility is only checking the first 52 bytes of the metadata structure (i.e. it verifies the check sum of the structure, then uses AES128-CBC padding bytes to perform the decryption of the last block, if it is an incomplete one).
The "version" field was present and recognised by DecryptToPIPE
in the reference firmware files from LGe, however, no real usage or logic depending on that field have been observed so far.
Hyundai Mobis are using the "version" field to select different logic for the file integrity checks on the encrypted files. It is assumed, but not live tested, that "version 2" originally did not depend on RSA and had everything needed for the integrity checking incorporated in the metadata structure (possibly, occupying the last 8K of the metadata structure). There was also an iteration of "version 2" (seems to be a transitional version to the current one) where the encrypted byte array was being assembled with step
calculated as int32[0] % 12 + 4
and the collection started from the fifth byte in the area. The applicability of this logic was not observed in the modern applications inside the firmware so far.
The 8176
bytes long area following the padding seems to be an invention of Hyundai Mobis after they engaged Teruten Co. The stored data in that area is encrypted using RSA with the public key used for decryption located in /app/share/AppUpgrade/teruten5_pub.key
.