From 8f697e406a99ad28872cad866816d8c062582bf1 Mon Sep 17 00:00:00 2001 From: Tobias Schramm Date: Wed, 24 Jan 2018 01:38:14 +0100 Subject: [PATCH] mkfwimage: Add image type definition for WA images This patch adds a new type of ubiquiti image, the WA image. First seen on the NanoStation AC loco the generic name implies that we will see this type of image on more ubiquiti devices thus it makes sense to implement it in mkfwimage. The main difference is that WA images are signed. The "END" header has been replaced by a "ENDS" header followed by a 2048 bit RSA signature. This signature is not being generated by mkfwimage and filled with 0x00. Signed-off-by: Tobias Schramm --- tools/firmware-utils/src/fw.h | 8 ++ tools/firmware-utils/src/mkfwimage.c | 168 +++++++++++++++++++-------- 2 files changed, 129 insertions(+), 47 deletions(-) diff --git a/tools/firmware-utils/src/fw.h b/tools/firmware-utils/src/fw.h index e37859c52d..44f8d851d2 100644 --- a/tools/firmware-utils/src/fw.h +++ b/tools/firmware-utils/src/fw.h @@ -24,6 +24,7 @@ #define MAGIC_HEADER "OPEN" #define MAGIC_PART "PART" #define MAGIC_END "END." +#define MAGIC_ENDS "ENDS" #define MAGIC_LENGTH 4 @@ -57,6 +58,13 @@ typedef struct signature { u_int32_t pad; } __attribute__ ((packed)) signature_t; +typedef struct signature_rsa { + char magic[MAGIC_LENGTH]; +// u_int32_t crc; + unsigned char rsa_signature[256]; + u_int32_t pad; +} __attribute__ ((packed)) signature_rsa_t; + #define VERSION "1.2" #define INFO(...) fprintf(stdout, __VA_ARGS__) diff --git a/tools/firmware-utils/src/mkfwimage.c b/tools/firmware-utils/src/mkfwimage.c index d8d5239cc5..2b84d3db53 100644 --- a/tools/firmware-utils/src/mkfwimage.c +++ b/tools/firmware-utils/src/mkfwimage.c @@ -29,65 +29,106 @@ #include #include #include +#include #include "fw.h" typedef struct fw_layout_data { - char name[PATH_MAX]; u_int32_t kern_start; u_int32_t kern_entry; u_int32_t firmware_max_length; } fw_layout_t; -fw_layout_t fw_layout_data[] = { +struct fw_info { + char name[PATH_MAX]; + struct fw_layout_data fw_layout; + bool sign; +}; + +struct fw_info fw_info[] = { { - .name = "XS2", - .kern_start = 0xbfc30000, - .kern_entry = 0x80041000, - .firmware_max_length= 0x00390000, + .name = "XS2", + .fw_layout = { + .kern_start = 0xbfc30000, + .kern_entry = 0x80041000, + .firmware_max_length= 0x00390000, + }, + .sign = false, }, { - .name = "XS5", - .kern_start = 0xbe030000, - .kern_entry = 0x80041000, - .firmware_max_length= 0x00390000, + .name = "XS5", + .fw_layout = { + .kern_start = 0xbe030000, + .kern_entry = 0x80041000, + .firmware_max_length= 0x00390000, + }, + .sign = false, }, { - .name = "RS", - .kern_start = 0xbf030000, - .kern_entry = 0x80060000, - .firmware_max_length= 0x00B00000, + .name = "RS", + .fw_layout = { + .kern_start = 0xbf030000, + .kern_entry = 0x80060000, + .firmware_max_length= 0x00B00000, + }, + .sign = false, }, { - .name = "RSPRO", - .kern_start = 0xbf030000, - .kern_entry = 0x80060000, - .firmware_max_length= 0x00F00000, + .name = "RSPRO", + .fw_layout = { + .kern_start = 0xbf030000, + .kern_entry = 0x80060000, + .firmware_max_length= 0x00F00000, + }, + .sign = false, }, { - .name = "LS-SR71", - .kern_start = 0xbf030000, - .kern_entry = 0x80060000, - .firmware_max_length= 0x00640000, + .name = "LS-SR71", + .fw_layout = { + .kern_start = 0xbf030000, + .kern_entry = 0x80060000, + .firmware_max_length= 0x00640000, + }, + .sign = false, }, { - .name = "XS2-8", - .kern_start = 0xa8030000, - .kern_entry = 0x80041000, - .firmware_max_length= 0x006C0000, + .name = "XS2-8", + .fw_layout = { + .kern_start = 0xa8030000, + .kern_entry = 0x80041000, + .firmware_max_length= 0x006C0000, + }, + .sign = false, + }, { - .name = "XM", - .kern_start = 0x9f050000, - .kern_entry = 0x80002000, - .firmware_max_length= 0x00760000, + .name = "XM", + .fw_layout = { + .kern_start = 0x9f050000, + .kern_entry = 0x80002000, + .firmware_max_length= 0x00760000, + }, + .sign = false, }, { - .name = "UBDEV01", - .kern_start = 0x9f050000, - .kern_entry = 0x80002000, - .firmware_max_length= 0x006A0000, + .name = "UBDEV01", + .fw_layout = { + .kern_start = 0x9f050000, + .kern_entry = 0x80002000, + .firmware_max_length= 0x006A0000, + }, + .sign = false, }, - { .name = "", + { + .name = "WA", + .fw_layout = { + .kern_start = 0x9f050000, + .kern_entry = 0x80002000, + .firmware_max_length= 0x00F60000, + }, + .sign = true, + }, + { + .name = "", }, }; @@ -116,8 +157,20 @@ typedef struct image_info { char outputfile[PATH_MAX]; u_int32_t part_count; part_data_t parts[MAX_SECTIONS]; + struct fw_info* fwinfo; } image_info_t; +static struct fw_info* get_fwinfo(char* board_name) { + struct fw_info *fwinfo = fw_info; + while(strlen(fwinfo->name)) { + if(strcmp(fwinfo->name, board_name) == 0) { + return fwinfo; + } + fwinfo++; + } + return NULL; +} + static void write_header(void* mem, const char *magic, const char* version) { header_t* header = mem; @@ -142,6 +195,17 @@ static void write_signature(void* mem, u_int32_t sig_offset) sign->pad = 0L; } +static void write_signature_rsa(void* mem, u_int32_t sig_offset) +{ + /* write signature */ + signature_rsa_t* sign = (signature_rsa_t*)(mem + sig_offset); + memset(sign, 0, sizeof(signature_rsa_t)); + + memcpy(sign->magic, MAGIC_ENDS, MAGIC_LENGTH); +// sign->crc = htonl(crc32(0L,(unsigned char *)mem, sig_offset)); + sign->pad = 0L; +} + static int write_part(void* mem, part_data_t* d) { char* addr; @@ -237,17 +301,9 @@ static int create_image_layout(const char* kernelfile, const char* rootfsfile, c part_data_t* kernel = &im->parts[0]; part_data_t* rootfs = &im->parts[1]; - fw_layout_t* p; + fw_layout_t* p = &im->fwinfo->fw_layout; - p = &fw_layout_data[0]; - while (*p->name && (strcmp(p->name, board_name) != 0)) - p++; - if (!*p->name) { - printf("BUG! Unable to find default fw layout!\n"); - exit(-1); - } - - printf("board = %s\n", p->name); + printf("board = %s\n", im->fwinfo->name); strcpy(kernel->partition_name, "kernel"); kernel->partition_index = 1; kernel->partition_baseaddr = p->kern_start; @@ -330,7 +386,12 @@ static int build_image(image_info_t* im) int i; // build in-memory buffer - mem_size = sizeof(header_t) + sizeof(signature_t); + mem_size = sizeof(header_t); + if(im->fwinfo->sign) { + mem_size += sizeof(signature_rsa_t); + } else { + mem_size += sizeof(signature_t); + } for (i = 0; i < im->part_count; ++i) { part_data_t* d = &im->parts[i]; @@ -359,7 +420,11 @@ static int build_image(image_info_t* im) ptr += sizeof(part_t) + d->stats.st_size + sizeof(part_crc_t); } // write signature - write_signature(mem, mem_size - sizeof(signature_t)); + if(im->fwinfo->sign) { + write_signature_rsa(mem, mem_size - sizeof(signature_rsa_t)); + } else { + write_signature(mem, mem_size - sizeof(signature_t)); + } // write in-memory buffer into file if ((f = fopen(im->outputfile, "w")) == NULL) @@ -388,6 +453,7 @@ int main(int argc, char* argv[]) char board_name[PATH_MAX]; int o, rc; image_info_t im; + struct fw_info *fwinfo; memset(&im, 0, sizeof(im)); memset(kernelfile, 0, sizeof(kernelfile)); @@ -447,6 +513,14 @@ int main(int argc, char* argv[]) return -2; } + if ((fwinfo = get_fwinfo(board_name)) == NULL) { + ERROR("Invalid baord name '%s'\n", board_name); + usage(argv[0]); + return -2; + } + + im.fwinfo = fwinfo; + if ((rc = create_image_layout(kernelfile, rootfsfile, board_name, &im)) != 0) { ERROR("Failed creating firmware layout description - error code: %d\n", rc); -- 2.30.2