static int unpack_image(const char *infn, const char *outdn) { struct imagewty_header *header; FILE *ifp, *lfp, *ofp; void *image, *curr; long imagesize; int i; ifp = fopen(infn, "rb"); if (ifp == NULL) { fprintf(stderr, "Error: unable to open %s!\n", infn); return 2; } fseek(ifp, 0, SEEK_END); imagesize = ftell(ifp); fseek(ifp, 0, SEEK_SET); if (imagesize <= 0) { fprintf(stderr, "Error: Invalid file size %ld (%s)\n", imagesize, strerror(errno)); return 3; } image = malloc(imagesize); if (!image) { fprintf(stderr, "Error: Unable to allocate memory for image: %ld\n", imagesize); return 4; } fread(image, imagesize, 1, ifp); fclose(ifp); /* Decrypt header (padded to 1024 bytes) */ curr = rc6_decrypt_inplace(image, 1024, &header_ctx); /* Decrypt file headers */ header = (struct imagewty_header*)image; curr = rc6_decrypt_inplace(curr, header->num_files * 1024, &fileheaders_ctx); /* Decrypt file contents */ for (i=0; i < header->num_files; i++) { struct imagewty_file_header *filehdr; void *next; filehdr = (struct imagewty_file_header*)(image + 1024 + (i * 1024)); next = rc6_decrypt_inplace(curr, filehdr->stored_length, &filecontent_ctx); #if TF_DECRYPT_WORKING if (!(strlen(filehdr->filename) >= 4 && strncmp(filehdr->filename + strlen(filehdr->filename) -4, ".fex", 4) == 0)) { /* Not a 'FEX' file, so we need to decrypt it even more! */ tf_decrypt_inplace(curr, filehdr->stored_length); } #endif curr = next; } if (flag_compat_output == OUTPUT_UNIMG) { lfp = dir_fopen(outdn, "base.hdr", "wb"); if (lfp) { uint32_t *hdr = image + IMAGEWTY_MAGIC_LEN; fprintf(lfp, "%.8s\r\n", header->magic); for (i = 0; i < (sizeof(*header) - IMAGEWTY_MAGIC_LEN) / sizeof(uint32_t); i++) fprintf(lfp, "%08X\r\n", hdr[i]); fclose(lfp); } lfp = dir_fopen(outdn, "Filelist.txt", "wb"); } else if (flag_compat_output == OUTPUT_IMGREPACKER) { lfp = dir_fopen(outdn, "image.cfg", "wb"); if (lfp != NULL) { char timestr[256]; struct tm *tm; time_t t; time(&t); tm = localtime(&t); strcpy(timestr, asctime(tm)); /* strip newline */ timestr[strlen(timestr) -1] = '\0'; fputs(";/**************************************************************************/\r\n", lfp); fprintf(lfp, "; %s\r\n", timestr); fprintf(lfp, "; generated by %s\r\n", progname); fprintf(lfp, "; %s\r\n", infn); fputs(";/**************************************************************************/\r\n", lfp); fputs("[FILELIST]\r\n", lfp); } } for (i=0; i < header->num_files; i++) { struct imagewty_file_header *filehdr; char hdrfname[32], contfname[32]; filehdr = (struct imagewty_file_header*)(image + 1024 + (i * 1024)); if (flag_compat_output == OUTPUT_UNIMG) { printf("Extracting: %.8s %.16s (%u, %u)\n", filehdr->maintype, filehdr->subtype, filehdr->original_length, filehdr->stored_length); sprintf(hdrfname, "%.8s_%.16s.hdr", filehdr->maintype, filehdr->subtype); ofp = dir_fopen(outdn, hdrfname, "wb"); if (ofp) { fwrite(filehdr, filehdr->total_header_size, 1, ofp); fclose(ofp); } sprintf(contfname, "%.8s_%.16s", filehdr->maintype, filehdr->subtype); ofp = dir_fopen(outdn, contfname, "wb"); if (ofp) { fwrite(image + filehdr->offset, filehdr->original_length, 1, ofp); fclose(ofp); } fprintf(lfp, "%s\t%s\r\n", hdrfname, contfname); } else if (flag_compat_output == OUTPUT_IMGREPACKER) { printf("Extracting %s\n", filehdr->filename); ofp = dir_fopen(outdn, filehdr->filename, "wb"); if (ofp) { fwrite(image + filehdr->offset, filehdr->original_length, 1, ofp); fclose(ofp); } fprintf(lfp, "\t{filename = INPUT_DIR .. \"%s\", maintype = \"%.8s\", subtype = \"%.16s\",},\r\n", filehdr->filename[0] == '/' ? filehdr->filename+1 : filehdr->filename, filehdr->maintype, filehdr->subtype); } } if (lfp && flag_compat_output == OUTPUT_IMGREPACKER) { /* Now print the relevant stuff for the image.cfg */ fputs("\r\n[IMAGE_CFG]\r\n", lfp); fprintf(lfp, "version = 0x%06x\r\n", header->version); fprintf(lfp, "pid = 0x%08x\r\n", header->pid); fprintf(lfp, "vid = 0x%08x\r\n", header->vid); fprintf(lfp, "hardwareid = 0x%03x\r\n", header->hardware_id); fprintf(lfp, "firmwareid = 0x%03x\r\n", header->firmware_id); fprintf(lfp, "imagename = %s\r\n", infn); fputs("filelist = FILELIST\r\n", lfp); } if (lfp) fclose(lfp); return 0; }
static int decrypt_image(const char *infn, const char *outfn) { int num_files, pid, vid, hardware_id, firmware_id; struct imagewty_header *header; void *image, *curr; FILE *ifp, *ofp; long imagesize; int i; ifp = fopen(infn, "rb"); if (ifp == NULL) { fprintf(stderr, "Error: unable to open %s!\n", infn); return 2; } fseek(ifp, 0, SEEK_END); imagesize = ftell(ifp); fseek(ifp, 0, SEEK_SET); if (imagesize <= 0) { fprintf(stderr, "Error: Invalid file size %ld (%s)\n", imagesize, strerror(errno)); return 3; } image = malloc(imagesize); if (!image) { fprintf(stderr, "Error: Unable to allocate memory for image: %ld\n", imagesize); return 4; } fread(image, imagesize, 1, ifp); fclose(ifp); /* Check for encryption; see bug #2 (A31 unencrypted images) */ header = (struct imagewty_header*)image; if (memcmp(header->magic, IMAGEWTY_MAGIC, IMAGEWTY_MAGIC_LEN) == 0) flag_encryption_enabled = 0; /* Decrypt header (padded to 1024 bytes) */ curr = rc6_decrypt_inplace(image, 1024, &header_ctx); /* Check version of header and setup our local state */ if (header->header_version == 0x0300) { num_files = header->v3.num_files; hardware_id = header->v3.hardware_id; firmware_id = header->v3.firmware_id; pid = header->v3.pid; vid = header->v3.vid; } else /*if (header->header_version == 0x0100)*/ { num_files = header->v1.num_files; hardware_id = header->v1.hardware_id; firmware_id = header->v1.firmware_id; pid = header->v1.pid; vid = header->v1.vid; } /* Decrypt file headers */ curr = rc6_decrypt_inplace(curr, num_files * 1024, &fileheaders_ctx); /* Decrypt file contents */ for (i=0; i < num_files; i++) { struct imagewty_file_header *filehdr; uint64_t stored_length; const char *filename; void *next; filehdr = (struct imagewty_file_header*)(image + 1024 + (i * 1024)); if (header->header_version == 0x0300) { stored_length = filehdr->v3.stored_length; filename = filehdr->v3.filename; } else { stored_length = filehdr->v1.stored_length; filename = filehdr->v1.filename; } next = rc6_decrypt_inplace(curr, stored_length, &filecontent_ctx); if (TF_DECRYPT_WORKING && !(strlen(filename) >= 4 && strncmp(filename + strlen(filename) -4, ".fex", 4) == 0)) { /* Not a 'FEX' file, so we need to decrypt it even more! */ tf_decrypt_inplace(curr, stored_length); } curr = next; } ofp = fopen(outfn, "wb"); if (ofp == NULL) { fprintf(stderr, "Error: unable to open output file %s!\n", outfn); return 4; } fwrite(image, imagesize, 1, ofp); fclose(ofp); return 0; }