Difference between revisions of "Title metadata"

From WiiBrew
Jump to: navigation, search
(fixed content record)
Line 5: Line 5:
 
A "title" is a standalone entity -- a game, a channel, etc.  Titles can be made up of multiple "contents".  (Don't ask me I just work here.)
 
A "title" is a standalone entity -- a game, a channel, etc.  Titles can be made up of multiple "contents".  (Don't ask me I just work here.)
 
   
 
   
// Common labels used in this file:
+
Many operations are done in terms of 64-byte blocks, which means you will often see padding out to the nearest 64-byte boundary at the end of a field.
// magicnum - control ints or shorts found in all tmds
 
// zeros    - bytes all filled with zeros
 
// undef    - non-zero data of unknown purpose
 
// sign    - zero-terminated string padded to 64 bytes
 
//            probably used in the signing process
 
// hash    - probably 20, 512 or 1024 byte hashes
 
//
 
// # in front of a comment signifies entires that are
 
// the same in each tmd-files the author checked
 
 
   
 
   
 
  typedef unsigned char  u8;
 
  typedef unsigned char  u8;
Line 29: Line 20:
 
  } content_record; // size: 0x30 bytes
 
  } content_record; // size: 0x30 bytes
  
  typedef struct{
+
enum sig_type {
  u32 magicnum0 [0x1]; // # 0x00010001
+
      RSA_2048 = 0x00010001,
  u8 hash0 [0x100]; // ?
+
      RSA_4096 = 0x00010000
  u8 zeros0 [0x3C]; // # 0
+
};
  u8 sign0 [0x40]; // # Root-CA-CP
+
 
  u8 undef0 [0x10]; // # ?
+
  typedef struct {
  u8 code [0x4]; // game code in ascii
+
        u32 sig_type;  
  u32 magicnum1 [0x1]; // # 0x00000001
+
        u8 sig[256];
  u8 publ [0x2]; // publisher id
+
        u8 fill1[60];
  u8  zeros1 [0x2]; // # 0
+
        u8 issuer[64]; // Root-CA%08x-CP%08x
  u8  undef1 [0x4]; // ?
+
        u8 version;
  u8  undef2 [0xE]; // ? 0x80
+
        u8 ca_crl_version;
  u8  zeros2 [0x2E]; // # 0
+
        u8 signer_crl_version;
  u8 undef3 [0x8]; // ?
+
        u8 fill2;
  VC_TMD_FILE files[7]; // 7 file entries
+
        u64 sys_version;
  u32 magicnum2 [0x1]; // # 0x00010001
+
        u64 title_id;
  u8  hash1 [0x100]; // # ?
+
        u32 title_type;
  u8  zeros3 [0x3C]; // # 0
+
        u16 group_id; // publisher
  u8  sign1 [0x40]; // # Root-CA
+
        u8 reserved[62];
  u32 magicnum3 [0x1]; // # 0x00000001
+
        u32 access_rights;
  u8  sign2 [0x40]; // # CP
+
        u16 title_version;
  u8  hash2 [0x104]; // # ?
+
        u16 num_contents;
  u32 magicnum4 [0x1]; // # 0x00010001
+
        u16 boot_index;
  u8  zeros4 [0x34]; // # 0
+
        u16 fill3;
  u32 magicnum5 [0x1]; // # 0x00100000
+
        content_record contents[num_contents];
  u8 hash3 [0x200]; // # ?
+
} tmd;
  u8 zeros5 [0x3C]; // # 0
+
 
  u8 sign3 [0x40]; // # Root
+
The tmd is then followed by a chain of certificates, where each certificate is of the general form
  u32 magicnum6 [0x1]; // # 0x00000001
+
 
  u8 sign4 [0x40]; // # CA
+
  u32 sig_type;  //
  u8 hash4 [0x104]; // # ?
+
  u8 sig[256];   // 256 for RSA_2048, 512 for RSA_4096
  u32 magicnum7 [0x1]; // # 0x00010001
+
  u8 issuer[32];
  u8 zeros6 [0x34]; // # 0
+
  u32 tag;  // identifies what is being signed
}VC_TMD; // size: 09E0 bytes
+
  u8 name[64]; // name of thing being signed
 +
  u8 key[...];

Revision as of 13:31, 16 January 2008


Nintendo Wii Title-Metadata (tmd) file structure

A "title" is a standalone entity -- a game, a channel, etc. Titles can be made up of multiple "contents". (Don't ask me I just work here.)

Many operations are done in terms of 64-byte blocks, which means you will often see padding out to the nearest 64-byte boundary at the end of a field.

typedef unsigned char  u8;
typedef unsigned short u16;
typedef unsigned int   u32; 
typedef unsigned long u64; 
typedef struct {
  u32 cid;		// content id
  u16 index;		// # number of the file
  u16  type;
  u64 size;
  u8  hash [20]; 		//  SHA1 hash content
} content_record; 			// size: 0x30 bytes

enum sig_type {

     RSA_2048 = 0x00010001,
     RSA_4096 = 0x00010000

};

typedef struct {
       u32 sig_type; 
       u8 sig[256];
       u8 fill1[60];
       u8 issuer[64]; // Root-CA%08x-CP%08x
       u8 version;
       u8 ca_crl_version;
       u8 signer_crl_version;
       u8 fill2;
       u64 sys_version;
       u64 title_id;
       u32 title_type;
       u16 group_id; // publisher
       u8 reserved[62];
       u32 access_rights;
       u16 title_version;
       u16 num_contents;
       u16 boot_index;
       u16 fill3;
       content_record contents[num_contents];

} tmd;

The tmd is then followed by a chain of certificates, where each certificate is of the general form

 u32 sig_type;  //
 u8 sig[256];   // 256 for RSA_2048, 512 for RSA_4096
 u8 issuer[32];
 u32 tag;  // identifies what is being signed
 u8 name[64]; // name of thing being signed
 u8 key[...];