/* To compile : */
/* gcc -O9 -Wall -s -o livecrypt2 livecrypt2.c */

#include <stdio.h>
#include <stdlib.h>

#define FIRMWARE_KEY_SIZE    48

/* Before this offset, we assume we have a sufficient number of consecutive zeros */
/* to find out the XOR key */
#define CRAMFS_OFFSET        0x1000

/*
  Key of the UK firmware :
  94 00 03 02 00 14 E8 15 3F A6 D8 A2 D8 14 71 46 FF 80 09 38 76 08 E0 C0 5C 3C 00 14 63 4A CD F8 96 C6 C2 0D BD E7 E7 BB 12 CF 3C 21 F7 05 CF 77
  
  Key of the FR firmware :
  94 00 03 02 00 14 36 4B DC 1C CC 32 87 93 D2 FE 28 4E B4 4B EB 8F 6E 24 C1 04 00 14 F0 32 68 AB 15 81 A5 83 F4 63 DD 26 88 91 7E 41 CC 9D 1B F1
*/

static char firmware_key[FIRMWARE_KEY_SIZE];

int main(int argc, char *argv[])
{
  FILE *fi, *fo;
  char c;
  int i;
  
  printf("Livebox firmware decrypter [http://lekernel.lya-fr.com]\n");
  if(argc != 3) {
    fprintf(stderr, "Incorrect parameters ; usage: livecrypt <input file> <output file>\n");
    return 1;
  }
  fi = fopen(argv[1], "rb");
  if(fi == NULL) {
    perror("Unable to open input file");
    return 1;
  }
  fo = fopen(argv[2], "wb");
  if(fo == NULL) {
    perror("Unable to open output file");
    fclose(fi);
    return 1;
  }
  
  i = CRAMFS_OFFSET - FIRMWARE_KEY_SIZE;
  if((i % FIRMWARE_KEY_SIZE) != 0) i -= (i % FIRMWARE_KEY_SIZE);
  printf("Reading XOR key at offset %d, for %d bytes\n", i, FIRMWARE_KEY_SIZE);
  
  if(fseek(fi, i, SEEK_SET) != 0) {
    perror("fseek");
    fclose(fo);
    fclose(fi);
    return 1;
  }
  
  if(fread(&firmware_key[0], FIRMWARE_KEY_SIZE, 1, fi) != 1) {
    fprintf(stderr, "Unable to read XOR key\n");
    fclose(fo);
    fclose(fi);
    return 1;
  }
  
  rewind(fi);
  
  printf("Key:");
  for(i=0;i<FIRMWARE_KEY_SIZE;i++) printf(" %02hhX", firmware_key[i]);
  printf("\n");
  
  i = 0;
  while(!feof(fi)) {
    if(fread(&c, 1, 1, fi) != 1) break;
    c ^= firmware_key[i];
    if(fwrite(&c, 1, 1, fo) != 1) break;
    i++;
    if(i == FIRMWARE_KEY_SIZE) i = 0;
  }
  
  if(fclose(fo) != 0) {
    perror("Error closing output file");
    fclose(fi);
    return 1;
  }
  fclose(fi);
  
  printf("Successully decrypted '%s' to '%s'.\n", argv[1], argv[2]);
  
  return 0;
}
