TP-Link Switch Image Format
This page is WiP and details the TP-Link image format header as found in various Realtek-based switches.
- The whole file is DES CBC encrypted - IV and Key are known
- There is a 512 Byte header, the structure is known
- The header MD5 sum matches if the last 128 bytes of the decrypted image are omitted or zeroed
- There are about 8000 bytes of data at the end of the image that are not part of any partition; that's a lot of zeros, the product ID, 200 bytes of base64 data (maybe an RSA signature?)
Decoding the image file
IV and Key can be extracted from the U-Boot source at common/DesDecode.c. There are the two variables:
unsigned char des_key[] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07 };
unsigned char des_iv[] = { 0xf5,0x10,0x10,0x73,0x6e,0xfb,0xab,0xb2 };
With this knowledge, we can use openssl to decode the image:
openssl enc -d -des-cbc -in encrypted.bin -out decrypted.bin -nosalt -nopad -p -iv f51010736efbabb2 -K 0001020304050607
Note: this may require legacy providers to be enabled for recent version of openssl
Image Format
The image itself contains a 512 byte header. The structure can also be found in the U-Boot source code at include/tplink/flashAppFsImage.h:
#define MD5_CHECKSUM_OFFSET 0 #define MD5_DIGEST_LEN 16 #define FLASH_PRODUCT_LENGTH 16 #define TP_IMAGE_NAME_SIZE 200 #define TP_IMAGE_HEADER_SIZE 512 #define FL_SIZE_LEN 16 /* "0x100000" */ #define FL_VER_LEN 16 /* "0x10000" */ typedef struct { char md5[MD5_DIGEST_LEN]; unsigned char productId[FLASH_PRODUCT_LENGTH]; char imagename[TP_IMAGE_NAME_SIZE]; UINT32 usrImageSize; UINT32 uImageSize; UINT32 bootromSize; UINT32 compressMethod; char flBootSize[FL_SIZE_LEN]; char flKernelOffset[FL_SIZE_LEN]; char flKernelSize[FL_SIZE_LEN]; char flUsrImg1Offset[FL_SIZE_LEN]; char flUsrImg1Size[FL_SIZE_LEN]; char flUsrImg2Offset[FL_SIZE_LEN]; char flUsrImg2Size[FL_SIZE_LEN]; char flUsrAppOffset[FL_SIZE_LEN]; char flUsrAppSize[FL_SIZE_LEN]; char flVer[FL_VER_LEN]; }_TP_IMAGE_HEADER;
MD5 Sum
In the T2500G-10TS GPL archive, the common/flashAppFsImage.c has a (commented out) section on MD5 and checksum calculation.
The header MD5 sum matches, given the following:
- The header MD5 sum needs to be zeroed (=salt)
- The last 128 bytes of the image, an RSA signature, need to be truncated.
The RSA signature contained in the last 128, signs the 16 MD5 checksum bytes. The public key of the certificate is contained in the aforementioned source file as a BASE64 string.
Embedded RSA Key
There is an embedded RSA public key towards the end of the image. Upon decoding, the string "RSA1" pops up, it is most likely an RSA Public Key Blob. Its purpose is yet unknown, but:
- All firmware version for the T1600G-52PS have the same key
- The latest firmware versions for the T1500G-10MPS and the T2500G-10TS have the same key (others not checked)