static int do_upg(void *buf, long size) { int ret = get_key_and_sig(true, buf); if(ret != 0) return ret; struct upg_file_t *file = upg_read_memory(buf, size, g_key, g_sig, NULL, generic_std_printf); if(file == NULL) return ret; for(int i = 0; i < file->nr_files; i++) { if(!g_out_prefix) continue; char *str = malloc(strlen(g_out_prefix) + 32); sprintf(str, "%s%d.bin", g_out_prefix, i); FILE *f = fopen(str, "wb"); if(!f) { cprintf(GREY, "Cannot open '%s' for writing\n", str); free(str); continue; } free(str); fwrite(file->files[i].data, 1, file->files[i].size, f); fclose(f); } upg_free(file); return 0; }
static int create_upg(int argc, char **argv) { if(argc == 0) { cprintf(GREY, "You must specify a firmware filename\n"); usage(); } int ret = get_key_and_sig(false, NULL); if(ret != 0) return ret; struct upg_file_t *upg = upg_new(); int nr_files = argc - 1; for(int i = 0; i < nr_files; i++) { FILE *f = fopen(argv[1 + i], "rb"); if(f == NULL) { upg_free(upg); printf(GREY, "Cannot open input file '%s': %m\n", argv[i + 1]); return 1; } size_t size = filesize(f); void *buf = malloc(size); if(fread(buf, 1, size, f) != size) { cprintf(GREY, "Cannot read input file '%s': %m\n", argv[i + 1]); fclose(f); upg_free(upg); return 1; } fclose(f); upg_append(upg, buf, size); } size_t size = 0; void *buf = upg_write_memory(upg, g_key, g_sig, &size, NULL, generic_std_printf); upg_free(upg); if(buf == NULL) { cprintf(GREY, "Error creating UPG file\n"); return 1; } FILE *fout = fopen(argv[0], "wb"); if(fout == NULL) { cprintf(GREY, "Cannot open output firmware file: %m\n"); free(buf); return 1; } if(fwrite(buf, 1, size, fout) != size) { cprintf(GREY, "Cannot write output file: %m\n"); fclose(fout); free(buf); return 1; } fclose(fout); free(buf); return 0; }
static int create_upg(int argc, char **argv) { if(argc == 0) { printf("You must specify a firmware filename\n"); usage(); } int ret = get_key_and_sig(false, NULL); if(ret != 0) return ret; FILE *fout = fopen(argv[0], "wb"); if(fout == NULL) { printf("Cannot open output firmware file: %m\n"); return 1; } int nr_files = argc - 1; FILE **files = malloc(nr_files * sizeof(FILE *)); for(int i = 0; i < nr_files; i++) { files[i] = fopen(argv[1 + i], "rb"); if(files[i] == NULL) { printf("Cannot open input file '%s': %m\n", argv[i + 1]); return 1; } } struct upg_md5_t md5; memset(&md5, 0, sizeof(md5)); MD5_CTX c; MD5_Init(&c); // output a dummy md5 sum fwrite(&md5, 1, sizeof(md5), fout); // output the encrypted signature struct upg_header_t hdr; memcpy(hdr.sig, g_sig, 8); hdr.nr_files = nr_files; hdr.pad = 0; ret = fwp_write(&hdr, sizeof(hdr), &hdr, (void *)g_key); if(ret) return ret; MD5_Update(&c, &hdr, sizeof(hdr)); fwrite(&hdr, 1, sizeof(hdr), fout); // output file headers long offset = sizeof(md5) + sizeof(hdr) + nr_files * sizeof(struct upg_entry_t); for(int i = 0; i < nr_files; i++) { struct upg_entry_t entry; entry.offset = offset; entry.size = filesize(files[i]); offset += ROUND_UP(entry.size, 8); // do it before encryption !! ret = fwp_write(&entry, sizeof(entry), &entry, (void *)g_key); if(ret) return ret; MD5_Update(&c, &entry, sizeof(entry)); fwrite(&entry, 1, sizeof(entry), fout); } cprintf(BLUE, "Files\n"); for(int i = 0; i < nr_files; i++) { long size = filesize(files[i]); long r_size = ROUND_UP(size, 8); cprintf(GREY, " File"); cprintf(RED, " %d\n", i); cprintf_field(" Offset: ", "0x%lx\n", ftell(fout)); cprintf_field(" Size: ", "0x%lx\n", size); void *buf = malloc(r_size); memset(buf, 0, r_size); fread(buf, 1, size, files[i]); fclose(files[i]); ret = fwp_write(buf, r_size, buf, (void *)g_key); if(ret) return ret; MD5_Update(&c, buf, r_size); fwrite(buf, 1, r_size, fout); free(buf); } fseek(fout, 0, SEEK_SET); MD5_Final(md5.md5, &c); fwrite(&md5, 1, sizeof(md5), fout); fclose(fout); return 0; }
static int do_upg(void *buf, long size) { struct upg_md5_t *md5 = buf; cprintf(BLUE, "Preliminary\n"); cprintf(GREEN, " MD5: "); for(int i = 0; i < 16; i++) cprintf(YELLOW, "%02x", md5->md5[i]); printf(" "); uint8_t actual_md5[MD5_DIGEST_LENGTH]; { MD5_CTX c; MD5_Init(&c); MD5_Update(&c, md5 + 1, size - sizeof(struct upg_header_t)); MD5_Final(actual_md5, &c); } check_field(memcmp(actual_md5, md5->md5, 16), 0, "Ok\n", "Mismatch\n"); int ret = get_key_and_sig(true, md5 + 1); if(ret != 0) return ret; struct upg_header_t *hdr = (void *)(md5 + 1); ret = fwp_read(hdr, sizeof(struct upg_header_t), hdr, (void *)g_key); if(ret) return ret; cprintf(BLUE, "Header\n"); cprintf_field(" Signature:", " "); for(int i = 0; i < 8; i++) cprintf(YELLOW, "%c", isprint(hdr->sig[i]) ? hdr->sig[i] : '.'); if(g_sig) { check_field(memcmp(hdr->sig, g_sig, 8), 0, " OK\n", " Mismatch\n"); } else cprintf(RED, " Can't check\n"); cprintf_field(" Files: ", "%d\n", hdr->nr_files); cprintf_field(" Pad: ", "0x%x\n", hdr->pad); cprintf(BLUE, "Files\n"); struct upg_entry_t *entry = (void *)(hdr + 1); for(unsigned i = 0; i < hdr->nr_files; i++, entry++) { int ret = fwp_read(entry, sizeof(struct upg_entry_t), entry, (void *)g_key); if(ret) return ret; cprintf(GREY, " File"); cprintf(RED, " %d\n", i); cprintf_field(" Offset: ", "0x%x\n", entry->offset); cprintf_field(" Size: ", "0x%x\n", entry->size); if(g_out_prefix) { char *str = malloc(strlen(g_out_prefix) + 32); sprintf(str, "%s%d.bin", g_out_prefix, i); FILE *f = fopen(str, "wb"); if(f) { // round up size, there is some padding done with random data int crypt_size = ROUND_UP(entry->size, 8); int ret = fwp_read(buf + entry->offset, crypt_size, buf + entry->offset, (void *)g_key); if(ret) return ret; // but write the *good* amount of data fwrite(buf + entry->offset, 1, entry->size, f); fclose(f); } else cprintf(GREY, "Cannot open '%s' for writing\n", str); } } return 0; }