Ledger Nano X - The secure hardware wallet
SHARE
TWEET

magicus

a guest Feb 9th, 2008 63 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // parse-channel.c
  2. // Compile with:
  3. // gcc -g -DLARGE_FILES -D_FILE_OFFSET_BITS=64 -Wall -W -O2   -c -o parse-channel.o parse-channel.c
  4. // gcc -g -lcrypto  parse-channel.o tools.o bn.o ec.o   -o parse-channel
  5. // The other files are from segher's git repository, created by his Makefile.
  6.  
  7. // Copyright 2008 Magicus <magicus@gmail.com>
  8. // This file is based on tachtig.c, which is
  9. // Copyright 2007,2008  Segher Boessenkool  <segher@kernel.crashing.org>
  10. // Licensed under the terms of the GNU GPL, version 2
  11. // http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
  12.  
  13. #include <string.h>
  14. #include <stdlib.h>
  15. #include <stdio.h>
  16.  
  17. #include "tools.h"
  18.  
  19. #define ERROR(s) do { fprintf(stderr, s "\n"); exit(1); } while (0)
  20.  
  21. // FIXME: this should really move to tools.c
  22. u16 be16(u8 *p)
  23. {
  24.         return  (p[0] << 8) | p[1];
  25. }
  26.  
  27. static u8 sd_key[16];
  28. static u8 sd_iv[16];
  29. static u8 md5_blanker[16];
  30.  
  31. static FILE *fp;
  32.  
  33. static char gamename[5];
  34.  
  35. static size_t partB_size;
  36. static u16 num_contents;
  37. static size_t* content_sizes;
  38.  
  39. typedef struct {
  40.       u32 title_id_01_code;
  41.       u32 title_id_02_name;
  42.       u32 partB_size;
  43.       u8  md5[0x10];
  44.       u8  data[0x624];
  45. } partA_header_t;
  46.  
  47. typedef struct {
  48.        u32 sig_type;
  49.        u8 sig[256];
  50.        u8 fill1[60];
  51.        u8 issuer[64]; // Root-CA%08x-CP%08x
  52.        u8 version;
  53.        u8 ca_crl_version;
  54.        u8 signer_crl_version;
  55.        u8 fill2;
  56.        u64 sys_version;
  57.        u64 title_id;
  58.        u32 title_type;
  59.        u16 group_id; // publisher
  60.        u8 reserved[62];
  61.        u32 access_rights;
  62.        u16 title_version;
  63.        u16 num_contents;
  64.        u16 boot_index;
  65.        u16 fill3;
  66. } tmd_t;
  67.  
  68. typedef struct {
  69.   u32 cid;              // content id
  70.   u16 index;            // # number of the file
  71.   u16  type;
  72.   u64 size;
  73.   u8  hash [20];                //  SHA1 hash content
  74. } content_record_t;
  75.  
  76. static void write_part(void* data, size_t size, char* name)
  77. {
  78.         FILE *out;
  79.         char filename[128];
  80.  
  81.   snprintf(filename, sizeof(filename), "%s_%s.bin", gamename, name);
  82.   filename[128] = '\0';
  83.         out = fopen(filename, "wb");
  84.         fwrite(data, 1, size, out);
  85.         fclose(out);   
  86. }
  87.  
  88. static void do_partA_header(void)
  89. {
  90.   partA_header_t header;
  91.         u8 md5_file[16];
  92.         u8 md5_calc[16];
  93.  
  94.         fread(&header, 1, sizeof header, fp);
  95.  
  96.         aes_cbc_dec(sd_key, sd_iv, (u8*) &header, sizeof header, (u8*) &header);
  97.  
  98.         memcpy(md5_file, header.md5, 16);
  99.         memcpy(header.md5, md5_blanker, 16);
  100.         md5((u8*) &header, sizeof header, md5_calc);
  101.  
  102.         if (memcmp(md5_file, md5_calc, 0x10)) {
  103.                 ERROR("MD5 mismatch");
  104.   }
  105.  
  106.         // Get the four-letter code of the game, for file naming purposes.
  107.         strncpy(gamename, (char*) &header.title_id_02_name, 4);
  108.         gamename[5] = '\0';
  109.         printf("Game code is: %s\n", gamename);
  110.  
  111.   partB_size = be32((u8*) &header.partB_size);
  112.   printf("Size of part B: 0x%x\n", partB_size);
  113.  
  114.   write_part(&header, sizeof(header), "01_header");
  115. }
  116.  
  117. static void do_partB_gameinfo(void)
  118. {
  119.         u8 *data;
  120.         size_t rounded_size;
  121.  
  122.         rounded_size = (partB_size + 63) & ~63;
  123.  
  124.         data = malloc(rounded_size);
  125.         fread(data, 1, rounded_size, fp);
  126.  
  127.         aes_cbc_dec(sd_key, sd_iv, data, rounded_size, data);
  128.        
  129.   write_part(data, rounded_size, "02_gameinfo");
  130.  
  131.   free(data);
  132. }
  133.  
  134. static void do_partC_Bk_header(void)
  135. {
  136.         u8 header[0x80];
  137.  
  138.         fread(header, 1, sizeof header, fp);
  139.  
  140.         if (be32(header + 4) != 0x426b0001)
  141.                 ERROR("no Bk header");
  142.         if (be32(header) != 0x70)
  143.                 ERROR("wrong Bk header size");
  144.  
  145.         fprintf(stderr, "NG id: %08x\n", be32(header + 8));
  146.  
  147.   write_part(header, sizeof(header), "03_bk_header");
  148. }
  149.  
  150. static void do_partD_tmd(void)
  151. {
  152.         tmd_t tmd;
  153.         u8* data;
  154.         size_t tmd_size;
  155.         int i;
  156.         content_record_t* rec;
  157.  
  158.         fread(&tmd, 1, sizeof tmd, fp);
  159.  
  160.   num_contents = be16((u8*) &tmd.num_contents);
  161.   printf("Number of content files: %d\n", num_contents);
  162.  
  163.   // Now we can read the rest of the tmd.
  164.   tmd_size = sizeof(tmd) + num_contents*sizeof(content_record_t);
  165.   tmd_size = (tmd_size + 63) & ~63;
  166.  
  167.   data = malloc(tmd_size);
  168.   memcpy(data, &tmd, sizeof(tmd));
  169.   fread(&data[sizeof(tmd)], 1, tmd_size-sizeof(tmd), fp);
  170.  
  171.   write_part(data, tmd_size, "04_tmd");
  172.  
  173.   content_sizes = calloc(1, sizeof (size_t) *  num_contents);
  174.  
  175.   rec = (content_record_t*) &data[sizeof(tmd)];
  176.   for (i = 0; i < num_contents; i++, rec++) {
  177.     u16 type = be16((u8*) &rec->type);
  178.  
  179.     if (!(type & 0x8000)) {
  180.       content_sizes[i] = (size_t)be64((u8*) &rec->size);
  181.     }
  182.   }
  183. }
  184.  
  185. static void do_partE_contents(void)
  186. {
  187.   int i;
  188.        
  189.   for (i=0; i < num_contents; i++) {
  190.           if (content_sizes[i] != 0) {
  191.       char name[128];
  192.       u8 *data;
  193.       size_t rounded_size = (content_sizes[i] + 63) & ~63;
  194.      
  195.       data = malloc(rounded_size);
  196.       fread(data, 1, rounded_size, fp);
  197.        
  198.       snprintf(name, 128, "05_content_%02d", i);
  199.       printf("Writing included content index %d of size: %x\n", i, content_sizes[i]);
  200.      
  201.       write_part(data, rounded_size, name);
  202.  
  203.       free (data);
  204.     }
  205.   }
  206. }
  207.  
  208. static void do_partF_cert(void)
  209. {
  210.         u8 cert[0x340];
  211.  
  212.         fread(cert, 1, sizeof cert, fp);
  213.        
  214.   write_part(cert, sizeof(cert), "06_cert");
  215. }
  216.  
  217.  
  218. int main(int argc, char **argv)
  219. {
  220.   if (argc != 2) {
  221.     ERROR("Usage: parse-channel <file>");
  222.   }
  223.  
  224.         get_key("sd-key", sd_key, 16);
  225.         get_key("sd-iv", sd_iv, 16);
  226.         get_key("md5-blanker", md5_blanker, 16);
  227.  
  228.         fp = fopen(argv[1], "rb");
  229.  
  230.   do_partA_header();
  231.         do_partB_gameinfo();
  232.         do_partC_Bk_header();
  233.         do_partD_tmd();
  234.         do_partE_contents();
  235.         do_partF_cert();
  236.  
  237.         fclose(fp);
  238.  
  239.         return 0;
  240. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Top