In memory of Ben “bushing” Byer, who passed away on Monday, February 8th, 2016.

Difference between revisions of "Title metadata"

From WiiBrew
Jump to navigation Jump to 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[...];