1 // Copyright 2007,2008 Segher Boessenkool <segher@kernel.crashing.org>
2 // Licensed under the terms of the GNU GPL, version 2
3 // http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
7 #include <openssl/aes.h>
8 #include <openssl/sha.h>
19 return (p
[0] << 24) | (p
[1] << 16) | (p
[2] << 8) | p
[3];
24 return ((u64
)be32(p
) << 32) | be32(p
+ 4);
29 return 4 * (u64
)be32(p
);
36 void sha(u8
*data
, u32 len
, u8
*hash
)
38 SHA1(data
, len
, hash
);
41 void get_key(const char *name
, u8
*key
, u32 len
)
47 home
= getenv("HOME");
49 fatal("cannot find HOME");
50 snprintf(path
, sizeof path
, "%s/.wii/%s", home
, name
);
52 fp
= fopen(path
, "rb");
54 fatal("cannot open common-key");
55 if (fread(key
, len
, 1, fp
) != 1)
56 fatal("error reading common-key");
60 void aes_cbc_dec(u8
*key
, u8
*iv
, u8
*in
, u32 len
, u8
*out
)
64 AES_set_decrypt_key(key
, 128, &aes_key
);
65 AES_cbc_encrypt(in
, out
, len
, &aes_key
, iv
, AES_DECRYPT
);
68 void decrypt_title_key(u8
*title_key_crypted
, u8
*title_id
, u8
*title_key
)
73 get_key("common-key", common_key
, 16);
75 memset(iv
, 0, sizeof iv
);
76 memcpy(iv
, title_id
, 8);
77 aes_cbc_dec(common_key
, iv
, title_key_crypted
, 16, title_key
);
80 static u8 root_key
[0x204];
81 static u8
*get_root_key(void)
83 get_key("root-key", root_key
, sizeof root_key
);
87 static u32
get_sig_len(u8
*sig
)
92 switch (type
- 0x10000) {
103 fprintf(stderr
, "get_sig_len(): unhandled sig type %08x\n", type
);
107 static u32
get_sub_len(u8
*sub
)
111 type
= be32(sub
+ 0x40);
123 fprintf(stderr
, "get_sub_len(): unhandled sub type %08x\n", type
);
127 static int check_rsa(u8
*h
, u8
*sig
, u8
*key
, u32 n
)
131 static const u8 ber
[16] = "\x00\x30\x21\x30\x09\x06\x05\x2b"
132 "\x0e\x03\x02\x1a\x05\x00\x04\x14";
136 memset(correct
+ 2, 0xff, n
- 38);
137 memcpy(correct
+ n
- 36, ber
, 16);
138 memcpy(correct
+ n
- 20, h
, 20);
139 //fprintf(stderr, "correct is:\n");
140 //hexdump(correct, n);
142 bn_exp(x
, sig
, key
, n
, key
+ n
, 4);
143 //fprintf(stderr, "x is:\n");
146 if (memcmp(correct
, x
, n
) == 0)
152 static int check_hash(u8
*h
, u8
*sig
, u8
*key
)
156 type
= be32(sig
) - 0x10000;
157 if (type
!= be32(key
+ 0x40))
162 return check_rsa(h
, sig
+ 4, key
+ 0x88, 0x100);
168 static u8
*find_cert_in_chain(u8
*sub
, u8
*cert
, u32 cert_len
)
172 u32 sig_len
, sub_len
;
176 strncpy(parent
, sub
, sizeof parent
);
177 parent
[sizeof parent
- 1] = 0;
178 child
= strrchr(parent
, '-');
186 for (p
= cert
; p
< cert
+ cert_len
; p
+= sig_len
+ sub_len
) {
187 sig_len
= get_sig_len(p
);
190 issuer
= p
+ sig_len
;
191 sub_len
= get_sub_len(issuer
);
195 if (strcmp(parent
, issuer
) == 0
196 && strcmp(child
, issuer
+ 0x44) == 0)
203 int check_cert_chain(u8
*data
, u32 data_len
, u8
*cert
, u32 cert_len
)
215 sig_len
= get_sig_len(sig
);
218 sub
= data
+ sig_len
;
219 sub_len
= data_len
- sig_len
;
224 fprintf(stderr
, ">>>>>> checking sig by %s...\n", sub
);
225 if (strcmp(sub
, "Root") == 0) {
226 key
= get_root_key();
227 sha(sub
, sub_len
, h
);
228 if (be32(sig
) != 0x10000)
230 return check_rsa(h
, sig
+ 4, key
, 0x200);
233 key_cert
= find_cert_in_chain(sub
, cert
, cert_len
);
237 key
= key_cert
+ get_sig_len(key_cert
);
239 sha(sub
, sub_len
, h
);
240 ret
= check_hash(h
, sig
, key
);
245 sig_len
= get_sig_len(sig
);
249 sub_len
= get_sub_len(sub
);
259 void do_yaz0(u8
*in
, u32 in_size
, u8
*out
, u32 out_size
)
268 for (nout
= 0; nout
< out_size
; ) {
274 if ((bits
& 0x80) != 0) {
280 d
|= (n
<< 8) & 0xf00;
287 for (i
= 0; i
< n
; i
++) {
303 void fatal(const char *s
)
314 void print_bytes(u8
*x
, u32 n
)
318 for (i
= 0; i
< n
; i
++)
319 fprintf(stderr
, "%02x", x
[i
]);
322 void hexdump(u8
*x
, u32 n
)
326 for (i
= 0; i
< n
; i
+= 16) {
327 fprintf(stderr
, "%04x:", i
);
328 for (j
= 0; j
< 16 && i
+ j
< n
; j
++) {
330 fprintf(stderr
, " ");
331 fprintf(stderr
, "%02x", *x
++);
333 fprintf(stderr
, "\n");
336 fprintf(stderr
, "\n");