#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>

static int read_key(FILE *file, char **pkey)
{
  int key_len, pos, magic;
  char *key;
  fread(&key_len, 4, 1,file);
  key_len = ntohl(key_len);
  printf("len : %x (pos %x)\n", key_len, ftell(file));
  *pkey = key = calloc(key_len, 1);
  
  for (pos = 0; pos < key_len; pos++)
	  if(fread(key + pos, 1, 1, file) != 1) break;

  fseek(file, ftell(file)&3, SEEK_CUR);
  fread(&magic, 4, 1,file);
  magic = ntohl(magic);
  if (magic != 0x1885daab) {
	  printf("bad magic %x(%d)\n", ftell(file), pos);
	return 0;
  }
  return key_len;

}

void dump_key(char *key, int key_len)
{
  int pos;
  for(pos=0;pos<key_len;pos++)
	  printf("%02x ", key[pos]&0xff);
  printf("\n");

}
int main(int argc, char *argv[])
{
  FILE *fi, *fo;
  char c;
  char *firmware_key, *firmware_hash;
  int pos, file_size, key_len;
  
  if(argc != 3) {
    printf("Incorrect parameters\n");
    return 1;
  }
  fi = fopen(argv[1], "rb");
  if(fi == NULL) {
    printf("Unable to open input file\n");
    return 1;
  }
  fo = fopen(argv[2], "w+b");
  if(fo == NULL) {
    printf("Unable to open output file\n");
    fclose(fi);
    return 1;
  }

  fseek(fi, 0, SEEK_END);
  file_size = ftell(fi);
  fseek(fi, file_size & 0xfffff000, SEEK_SET);
    
  key_len = read_key(fi, &firmware_key);
  printf("Xor key : ");
  dump_key(firmware_key, key_len);
  
  
  fseek(fi, 0, SEEK_SET);
  pos = 0;
  while(!feof(fi)) {
    if(fread(&c, 1, 1, fi) != 1) break;
    c ^= firmware_key[pos];
    if(fwrite(&c, 1, 1, fo) != 1) break;
    pos++;
    if(pos == key_len) pos = 0;
  }

  fseek(fo, (file_size - 0x1000)& 0xfffff000, SEEK_SET);

  key_len = read_key(fo, &firmware_hash);
  printf("Unknow key : ");
  dump_key(firmware_hash, key_len);
  
  if(fclose(fo) != 0) {
    printf("Error closing output file\n");
    fclose(fi);
    return 1;
  }
  fclose(fi);
}
