Talk:Certificate chain

From WiiBrew
Jump to navigation Jump to search

It would be handy to have some code to check the certificates... so that we can tell if a file has been trucha'd

surely it isn't that hard, you just have to know 'e', 'n', the sig and the file signed which are on every wii...

Problem is which bit of the certificates is e and which is n?

sample code per request

Here's a Snippet of how I walk the keys and check everything I possibly can. The presumption is you already have the binary blob of the cert section (u8 *c), and the reported length of the cert from the header (w_hdr.sz_crt):

#define round_up(x,n)(-(-(x)&-(n)))
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
struct wad_crt{
  u32 sig_type;
  u8 sig[0x200];
  u8 fill1[0x3C];
  u8 issuer[0x40];
  u32 key_type;
  u8 child[0x40];
  u8 pub_key[0x204];
  u8 fill2[0x38];
};

static u8 num_crt;

static void get_crt(u8 *c){
  u64 j=0;
  u16 i,s,k;
  struct wad_crt * tmp=NULL;
  for(num_crt=0;;num_crt++){
    if(sizeof w_crt!=(num_crt+1)*sizeof(struct wad_crt)){
      tmp=(struct wad_crt *)realloc(w_crt,(num_crt+1)*sizeof(struct wad_crt));
      if(tmp!=NULL) w_crt=tmp;
    }
    w_crt[num_crt].sig_type=be32(c+j);
    switch(w_crt[num_crt].sig_type){
      case 0x00010000: s=0x200; break; /*RSA_4096*/
      case 0x00010001: s=0x100; break; /*RSA_2048*/
      case 0x00010002: s=0x40;  break; /*ECC*/
      default:
        fprintf(stderr,"  get_crt[%u]: unknown sig_type (%08x)\n",num_crt,w_crt[num_crt].sig_type);
        exit(1);
    }
    strncpy(w_crt[num_crt].sig,    c+j+0x04,    s);
    strncpy(w_crt[num_crt].fill1,  c+j+s+0x04,  0x3C);
    strncpy(w_crt[num_crt].issuer, c+j+s+0x40,  0x40);
    w_crt[num_crt].key_type=be32(  c+j+s+0x80);
    switch(w_crt[num_crt].key_type){
      case 0x00000000: k=0x204; break; /*RSA_4096*/
      case 0x00000001: k=0x104; break; /*RSA_2048*/
      default:
        fprintf(stderr,"  get_crt[%u]: unknown key_type (%08x)\n",num_crt,w_crt[num_crt].key_type);
        exit(1);
    }
    strncpy(w_crt[num_crt].child  ,c+j+s+0x84,  0x40);
    strncpy(w_crt[num_crt].pub_key,c+j+s+0xC4,  k);
    strncpy(w_crt[num_crt].fill2,  c+j+s+k+0xC4,0x38);
    
    for(i=0;i<0x3c;i++){
      if(w_crt[num_crt].fill1[i]!=0x00){
        fprintf(stderr,"  get_crt[%u]: fill1 is non-zero padded\n",num_crt);
        exit(1);
      }
    }
    if(strncmp(w_crt[num_crt].issuer,"Root",4)!=0){
      fprintf(stderr,"  get_crt[%u]: unknown issuer (%s)\n",num_crt,w_crt[num_crt].issuer);
      exit(1);
    }
    for(i=0;i<0x38;i++){
      if(w_crt[num_crt].fill2[i]!=0x00){
        fprintf(stderr,"  get_crt[%u]: fill2 is non-zero padded\n",num_crt);
        exit(1);
      }
    }
    j+=round_up(s+k+0xFC,0x40);
    if(j >= round_up(w_hdr.sz_crt,0x40)) break;
  }
}

--Finitelife (talk) 05:13, 15 October 2014 (CEST)