Commit | Line | Data |
---|---|---|
1de93811 ML |
1 | /*+-----------------------------+*/ |
2 | /*|2013 USER |*/ | |
3 | /*|decrypt algos by flatz |*/ | |
4 | /*| |*/ | |
5 | /*|GPL v3, DO NOT USE IF YOU |*/ | |
6 | /*|DISAGREE TO RELEASE SRC :P |*/ | |
7 | /*+-----------------------------+*/ | |
8 | ||
9 | #include "tools.h" | |
10 | #include "types.h" | |
11 | #include "iso.h" | |
12 | ||
13 | #include <stdio.h> | |
14 | #include <string.h> | |
15 | #include <assert.h> | |
16 | #include <stdlib.h> | |
17 | ||
18 | ||
19 | // !!!---- IMPORTANT FOR FWRITE FILES > 2GB ON 32BIT SYSTEMS ----!!! | |
20 | // add -D"_LARGEFILE64_SOURCE" | |
21 | // and -D"_FILE_OFFSET_BITS=64" | |
22 | // to CFLAGS | |
23 | // !!!-----------------------------------------------------------!!! | |
24 | ||
25 | #define PS2_META_SEGMENT_START 1 | |
26 | #define PS2_DATA_SEGMENT_START 2 | |
27 | #define PS2_DEFAULT_SEGMENT_SIZE 0x4000 | |
28 | #define PS2_META_ENTRY_SIZE 0x20 | |
29 | ||
30 | #define PS2_VMC_ENCRYPT 1 | |
31 | #define PS2_VMC_DECRYPT 0 | |
32 | ||
33 | //prototypes | |
34 | void ps2_encrypt_image(char mode[], char image_name[], char data_file[], char real_out_name[], char CID[]); | |
35 | void ps2_decrypt_image(char mode[], char image_name[], char meta_file[], char data_file[]); | |
36 | void ps2_crypt_vmc(char mode[], char vmc_path[], char vmc_out[], u8 root_key[], int crypt_mode); | |
37 | static void build_ps2_header(u8 * buffer, int npd_type, char content_id[], char filename[], s64 iso_size); | |
38 | ||
39 | ||
40 | //keys | |
41 | u8 ps2_per_console_seed[] = { 0xD9, 0x2D, 0x65, 0xDB, 0x05, 0x7D, 0x49, 0xE1, 0xA6, 0x6F, 0x22, 0x74, 0xB8, 0xBA, 0xC5, 0x08 }; | |
42 | ||
43 | u8 ps2_key_cex_meta[] = { 0x38, 0x9D, 0xCB, 0xA5, 0x20, 0x3C, 0x81, 0x59, 0xEC, 0xF9, 0x4C, 0x93, 0x93, 0x16, 0x4C, 0xC9 }; | |
44 | u8 ps2_key_cex_data[] = { 0x10, 0x17, 0x82, 0x34, 0x63, 0xF4, 0x68, 0xC1, 0xAA, 0x41, 0xD7, 0x00, 0xB1, 0x40, 0xF2, 0x57 }; | |
45 | u8 ps2_key_cex_vmc[] = { 0x64, 0xE3, 0x0D, 0x19, 0xA1, 0x69, 0x41, 0xD6, 0x77, 0xE3, 0x2E, 0xEB, 0xE0, 0x7F, 0x45, 0xD2 }; | |
46 | ||
47 | u8 ps2_key_dex_meta[] = { 0x2B, 0x05, 0xF7, 0xC7, 0xAF, 0xD1, 0xB1, 0x69, 0xD6, 0x25, 0x86, 0x50, 0x3A, 0xEA, 0x97, 0x98 }; | |
48 | u8 ps2_key_dex_data[] = { 0x74, 0xFF, 0x7E, 0x5D, 0x1D, 0x7B, 0x96, 0x94, 0x3B, 0xEF, 0xDC, 0xFA, 0x81, 0xFC, 0x20, 0x07 }; | |
49 | u8 ps2_key_dex_vmc[] = { 0x30, 0x47, 0x9D, 0x4B, 0x80, 0xE8, 0x9E, 0x2B, 0x59, 0xE5, 0xC9, 0x14, 0x5E, 0x10, 0x64, 0xA9 }; | |
50 | ||
51 | u8 ps2_iv[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; | |
52 | ||
53 | u8 fallback_header_hash[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }; | |
54 | ||
55 | u8 npd_omac_key2[] = {0x6B,0xA5,0x29,0x76,0xEF,0xDA,0x16,0xEF,0x3C,0x33,0x9F,0xB2,0x97,0x1E,0x25,0x6B}; | |
56 | u8 npd_omac_key3[] = {0x9B,0x51,0x5F,0xEA,0xCF,0x75,0x06,0x49,0x81,0xAA,0x60,0x4D,0x91,0xA5,0x4E,0x97}; | |
57 | u8 npd_kek[] = {0x72,0xF9,0x90,0x78,0x8F,0x9C,0xFF,0x74,0x57,0x25,0xF0,0x8E,0x4C,0x12,0x83,0x87}; | |
58 | ||
59 | ||
60 | u8 eid_root_key[0x30]; | |
61 | u8 * klicensee; | |
62 | ||
63 | ||
64 | static void set_ps2_iv(u8 iv[]) | |
65 | { | |
66 | memcpy(iv, ps2_iv, 0x10); | |
67 | } | |
68 | ||
69 | ||
70 | static void build_ps2_header(u8 * buffer, int npd_type, char content_id[], char filename[], s64 iso_size) | |
71 | { | |
72 | ||
73 | int i; | |
74 | u32 type = 1; | |
75 | u8 test_hash[] = { 0xBF, 0x2E, 0x44, 0x15, 0x52, 0x8F, 0xD7, 0xDD, 0xDB, 0x0A, 0xC2, 0xBF, 0x8C, 0x15, 0x87, 0x51 }; | |
76 | ||
77 | wbe32(buffer, 0x50533200); // PS2\0 | |
78 | wbe16(buffer + 0x4, 0x1); // ver major | |
79 | wbe16(buffer + 0x6, 0x1); // ver minor | |
80 | wbe32(buffer + 0x8, npd_type); // NPD type XX | |
81 | wbe32(buffer + 0xc, type); // type | |
82 | ||
83 | wbe64(buffer + 0x88, iso_size); //iso size | |
84 | wbe32(buffer + 0x84, PS2_DEFAULT_SEGMENT_SIZE); //segment size | |
85 | ||
86 | strncpy(buffer + 0x10, content_id, 0x30); | |
87 | ||
88 | u8 npd_omac_key[0x10]; | |
89 | ||
90 | for(i=0;i<0x10;i++) npd_omac_key[i] = npd_kek[i] ^ npd_omac_key2[i]; | |
91 | ||
92 | get_rand(buffer + 0x40, 0x10); //npdhash1 | |
93 | //memcpy(buffer + 0x40, test_hash, 0x10); | |
94 | ||
95 | int buf_len = 0x30+strlen(filename); | |
96 | char *buf = (char*)malloc(buf_len+1); | |
97 | memcpy(buf, buffer + 0x10, 0x30); | |
98 | strcpy(buf+0x30, filename); | |
99 | aesOmacMode1(buffer + 0x50, buf, buf_len, npd_omac_key3, sizeof(npd_omac_key3)*8); //npdhash2 | |
100 | free(buf); | |
101 | aesOmacMode1(buffer + 0x60, (u8*)(buffer), 0x60, npd_omac_key, sizeof(npd_omac_key)*8); //npdhash3 | |
102 | ||
103 | } | |
104 | ||
105 | ||
106 | void ps2_decrypt_image(char mode[], char image_name[], char meta_file[], char data_file[]) | |
107 | { | |
108 | FILE * in; | |
109 | FILE * data_out; | |
110 | FILE * meta_out; | |
111 | ||
112 | u8 ps2_data_key[0x10]; | |
113 | u8 ps2_meta_key[0x10]; | |
114 | u8 iv[0x10]; | |
115 | ||
116 | int segment_size; | |
117 | s64 data_size; | |
118 | int i; | |
119 | u8 header[256]; | |
120 | u8 * data_buffer; | |
121 | u8 * meta_buffer; | |
122 | u32 read = 0; | |
123 | int num_child_segments; | |
124 | ||
125 | //open files | |
126 | in = fopen(image_name, "rb"); | |
127 | meta_out = fopen(meta_file, "wb"); | |
128 | data_out = fopen(data_file, "wb"); | |
129 | ||
130 | //get file info | |
131 | read = fread(header, 256, 1, in); | |
132 | segment_size = be32(header + 0x84); | |
133 | data_size = be64(header + 0x88); | |
134 | num_child_segments = segment_size / PS2_META_ENTRY_SIZE; | |
135 | ||
136 | printf("segment size: %x\ndata_size: %lx\n\n", segment_size, data_size); | |
137 | ||
138 | //alloc buffers | |
139 | data_buffer = malloc(segment_size*num_child_segments); | |
140 | meta_buffer = malloc(segment_size); | |
141 | ||
142 | //generate keys | |
143 | if(strcmp(mode, "cex") == 0) | |
144 | { | |
145 | printf("cex\n"); | |
146 | set_ps2_iv(iv); | |
147 | aes128cbc_enc(ps2_key_cex_data, iv, klicensee, 0x10, ps2_data_key); | |
148 | aes128cbc_enc(ps2_key_cex_meta, iv, klicensee, 0x10, ps2_meta_key); | |
149 | }else{ | |
150 | printf("dex\n"); | |
151 | set_ps2_iv(iv); | |
152 | aes128cbc_enc(ps2_key_dex_data, iv, klicensee, 0x10, ps2_data_key); | |
153 | aes128cbc_enc(ps2_key_dex_meta, iv, klicensee, 0x10, ps2_meta_key); | |
154 | } | |
155 | ||
156 | ||
157 | //decrypt iso | |
158 | fseek(in, segment_size, SEEK_SET); | |
159 | ||
160 | while(read = fread(meta_buffer, 1, segment_size, in)) | |
161 | { | |
162 | //decrypt meta | |
163 | aes128cbc(ps2_meta_key, iv, meta_buffer, read, meta_buffer); | |
164 | fwrite(meta_buffer, read, 1, meta_out); | |
165 | ||
166 | ||
167 | read = fread(data_buffer, 1, segment_size*num_child_segments, in); | |
168 | for(i=0;i<num_child_segments;i++) | |
169 | aes128cbc(ps2_data_key, iv, data_buffer+(i*segment_size), segment_size, data_buffer+(i*segment_size)); | |
170 | if(data_size >= read) | |
171 | fwrite(data_buffer, read, 1, data_out); | |
172 | else | |
173 | fwrite(data_buffer, data_size, 1, data_out); | |
174 | ||
175 | data_size -= read; | |
176 | } | |
177 | ||
178 | //cleanup | |
179 | free(data_buffer); | |
180 | free(meta_buffer); | |
181 | ||
182 | fclose(in); | |
183 | fclose(data_out); | |
184 | fclose(meta_out); | |
185 | } | |
186 | ||
187 | ||
188 | void ps2_encrypt_image(char mode[], char image_name[], char data_file[], char real_out_name[], char CID[]) | |
189 | { | |
190 | FILE * in; | |
191 | FILE * data_out; | |
192 | ||
193 | u8 ps2_data_key[0x10]; | |
194 | u8 ps2_meta_key[0x10]; | |
195 | u8 iv[0x10]; | |
196 | ||
197 | u32 segment_size; | |
198 | s64 data_size; | |
199 | u32 i; | |
200 | u8 header[256]; | |
201 | u8 * data_buffer; | |
202 | u8 * meta_buffer; | |
203 | u8 * ps2_header; | |
204 | ||
205 | ||
206 | u32 read = 0; | |
207 | u32 num_child_segments = 0x200; | |
208 | u32 segment_number = 0; | |
209 | ||
210 | //open files | |
211 | in = fopen(image_name, "rb"); | |
212 | data_out = fopen(data_file, "wb"); | |
213 | ||
214 | //get file info | |
215 | segment_size = PS2_DEFAULT_SEGMENT_SIZE; | |
216 | fseeko(in, 0, SEEK_END); | |
217 | data_size = ftello(in); | |
218 | fseeko(in, 0, SEEK_SET); | |
219 | ||
220 | printf("segment size: %x\ndata_size: %lx\nCID: %s\niso %s\nout file: %s\n", segment_size, data_size, CID, image_name, data_file); | |
221 | ||
222 | //prepare buffers | |
223 | data_buffer = malloc(segment_size * 0x200); | |
224 | meta_buffer = malloc(segment_size); | |
225 | ps2_header = malloc(segment_size); | |
226 | memset(ps2_header, 0, segment_size); | |
227 | ||
228 | //generate keys | |
229 | if(strcmp(mode, "cex") == 0) | |
230 | { | |
231 | printf("cex\n"); | |
232 | set_ps2_iv(iv); | |
233 | aes128cbc_enc(ps2_key_cex_data, iv, klicensee, 0x10, ps2_data_key); | |
234 | aes128cbc_enc(ps2_key_cex_meta, iv, klicensee, 0x10, ps2_meta_key); | |
235 | }else{ | |
236 | printf("dex\n"); | |
237 | set_ps2_iv(iv); | |
238 | aes128cbc_enc(ps2_key_dex_data, iv, klicensee, 0x10, ps2_data_key); | |
239 | aes128cbc_enc(ps2_key_dex_meta, iv, klicensee, 0x10, ps2_meta_key); | |
240 | } | |
241 | ||
242 | ||
243 | //write incomplete ps2 header | |
244 | build_ps2_header(ps2_header, 2, CID, real_out_name, data_size); | |
245 | fwrite(ps2_header, segment_size, 1, data_out); | |
246 | ||
247 | ||
248 | //write encrypted image | |
249 | while(read = fread(data_buffer, 1, segment_size*num_child_segments, in)) | |
250 | { | |
251 | //last segments? | |
252 | if(read != (segment_size*num_child_segments)) | |
253 | { | |
254 | num_child_segments = (read / segment_size); | |
255 | if((read % segment_size) > 0) | |
256 | num_child_segments += 1; | |
257 | } | |
258 | ||
259 | memset(meta_buffer, 0, segment_size); | |
260 | ||
261 | //encrypt data and create meta | |
262 | for(i=0;i<num_child_segments;i++) | |
263 | { | |
264 | aes128cbc_enc(ps2_data_key, iv, data_buffer+(i*segment_size), segment_size, data_buffer+(i*segment_size)); | |
265 | sha1(data_buffer+(i*segment_size), segment_size, meta_buffer+(i*PS2_META_ENTRY_SIZE)); | |
266 | wbe32(meta_buffer+(i*PS2_META_ENTRY_SIZE)+0x14, segment_number); | |
267 | segment_number++; | |
268 | } | |
269 | ||
270 | //encrypt meta | |
271 | aes128cbc_enc(ps2_meta_key, iv, meta_buffer, segment_size, meta_buffer); | |
272 | ||
273 | //write meta and data | |
274 | fwrite(meta_buffer, segment_size, 1, data_out); | |
275 | fwrite(data_buffer, segment_size*num_child_segments, 1, data_out); | |
276 | ||
277 | memset(data_buffer, 0, segment_size*num_child_segments); | |
278 | } | |
279 | ||
280 | //finalize ps2_header | |
281 | // - wtf is between signature and first segment? | |
282 | ||
283 | //cleanup | |
284 | free(data_buffer); | |
285 | free(meta_buffer); | |
286 | free(ps2_header); | |
287 | ||
288 | fclose(in); | |
289 | fclose(data_out); | |
290 | } | |
291 | ||
292 | void ps2_crypt_vmc(char mode[], char vmc_path[], char vmc_out[], u8 root_key[], int crypt_mode) | |
293 | { | |
294 | FILE * in; | |
295 | FILE * data_out; | |
296 | FILE * meta_out; | |
297 | ||
298 | u8 ps2_vmc_key[0x10]; | |
299 | u8 iv[0x10]; | |
300 | ||
301 | int segment_size, data_size; | |
302 | int i; | |
303 | u8 header[256]; | |
304 | u8 * data_buffer; | |
305 | u8 * meta_buffer; | |
306 | u32 read = 0; | |
307 | ||
308 | segment_size = PS2_DEFAULT_SEGMENT_SIZE; | |
309 | ||
310 | //open files | |
311 | in = fopen(vmc_path, "rb"); | |
312 | data_out = fopen(vmc_out, "wb"); | |
313 | ||
314 | //alloc buffers | |
315 | data_buffer = malloc(segment_size); | |
316 | ||
317 | //generate keys | |
318 | if(strcmp(mode, "cex") == 0) | |
319 | { | |
320 | aes256cbc_enc(root_key, root_key+0x20, ps2_per_console_seed, 0x10, iv); | |
321 | memcpy(ps2_vmc_key, ps2_key_cex_vmc, 0x10); | |
322 | }else{ | |
323 | aes256cbc_enc(root_key, root_key+0x20, ps2_per_console_seed, 0x10, iv); | |
324 | memcpy(ps2_vmc_key, ps2_key_dex_vmc, 0x10); | |
325 | } | |
326 | ||
327 | memset(iv+8, 0, 8); | |
328 | ||
329 | while(read = fread(data_buffer, 1, segment_size, in)) | |
330 | { | |
331 | //decrypt or encrypt vmc | |
332 | if(crypt_mode == PS2_VMC_DECRYPT) | |
333 | aes128cbc(ps2_vmc_key, ps2_iv, data_buffer, read, data_buffer); | |
334 | else | |
335 | aes128cbc_enc(ps2_vmc_key, ps2_iv, data_buffer, read, data_buffer); | |
336 | fwrite(data_buffer, read, 1, data_out); | |
337 | ||
338 | } | |
339 | ||
340 | //cleanup | |
341 | free(data_buffer); | |
342 | ||
343 | fclose(in); | |
344 | fclose(data_out); | |
345 | ||
346 | } | |
347 | ||
348 | ||
349 | ||
350 | ||
351 | int main(int argc, char *argv[]) | |
352 | { | |
353 | ||
354 | u8 * root_key = NULL; | |
355 | ||
356 | printf("\nps2classic\nhttp://gitorious.ps3dev.net/ps2classic\nLicense: GPLv3\n\n"); | |
357 | ||
358 | ||
359 | if(argc == 1) | |
360 | { | |
361 | printf("usage:\n\tiso:\n\t\t%s d [cex/dex] [klicensee] [encrypted image] [out data] [out meta]\n", argv[0]); | |
362 | printf("\t\t%s e [cex/dex] [klicensee] [iso] [out data] [real out name] [CID]\n", argv[0]); | |
363 | printf("\t\nvmc:\n\t\t%s vd [cex/dex] [vme file] [out vmc] [(eid root key)]\n", argv[0]); | |
364 | printf("\t\t%s ve [cex/dex] [vmc file] [out vme] [(eid root key)]\n", argv[0]); | |
365 | printf("\t\nimage tools:\n\t\t%s prepare [image file]\n", argv[0]); | |
366 | printf("\t\t%s info [image file]\n", argv[0]); | |
367 | exit(0); | |
368 | } | |
369 | ||
370 | if(argc > 6) | |
371 | klicensee = mmap_file(argv[3]); | |
372 | ||
373 | if(strcmp(argv[1], "d") == 0) | |
374 | if(argc == 7) | |
375 | ps2_decrypt_image(argv[2], argv[4], argv[6], argv[5]); | |
376 | else | |
377 | printf("Error: invalid number of arguments for decryption\n"); | |
378 | else if(strcmp(argv[1], "e") == 0) | |
379 | if(argc == 8) | |
380 | ps2_encrypt_image(argv[2], argv[4], argv[5], argv[6], argv[7]); | |
381 | else | |
382 | printf("Error: invalid number of arguments for encryption\n"); | |
383 | else if(strcmp(argv[1], "vd") == 0 || strcmp(argv[1], "ve") == 0) | |
384 | { | |
385 | if(argc == 6) | |
386 | root_key = mmap_file(argv[3]); | |
387 | else if(argc == 5){ | |
388 | root_key = malloc(0x30); | |
389 | memset(root_key, 0, 0x30); | |
390 | }else{ | |
391 | printf("Error: invalid number of arguments for vme processing\n"); | |
392 | exit(0); | |
393 | } | |
394 | ||
395 | if(strcmp(argv[1], "vd") == 0) | |
396 | ps2_crypt_vmc(argv[2], argv[3], argv[4], root_key, PS2_VMC_DECRYPT); | |
397 | else | |
398 | ps2_crypt_vmc(argv[2], argv[3], argv[4], root_key, PS2_VMC_ENCRYPT); | |
399 | ||
400 | free(root_key); | |
401 | } | |
402 | else if(strcmp(argv[1], "prepare") == 0 && argc == 3) | |
403 | { | |
404 | prepare_iso(argv[2]); | |
405 | } | |
406 | else if(strcmp(argv[1], "info") == 0 && argc == 3) | |
407 | { | |
408 | print_ps2image_info(argv[2]); | |
409 | } | |
410 | else | |
411 | printf("FAIL: unknown option or wrong number of arguments\n"); | |
412 | ||
413 | } |