Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
hrydgard
GitHub Repository: hrydgard/ppsspp
Path: blob/master/ext/libkirk/amctrl.c
3186 views
1
/*
2
* amctrl.c -- Reverse engineering of amctrl.prx
3
* written by tpu.
4
*/
5
6
7
#include <stdio.h>
8
#include <stdlib.h>
9
#include <string.h>
10
11
#include "kirk_engine.h"
12
#include "AES.h"
13
#include "SHA1.h"
14
#include "amctrl.h"
15
16
//Turn off optimization in VS2013
17
#ifdef _MSC_VER
18
#if (_MSC_VER == 1800)
19
#pragma optimize( "", off )
20
#endif
21
#pragma warning(disable:4996) // for strncpy
22
#endif
23
/*************************************************************/
24
25
static const u8 loc_1CD4[16] = {0xE3, 0x50, 0xED, 0x1D, 0x91, 0x0A, 0x1F, 0xD0, 0x29, 0xBB, 0x1C, 0x3E, 0xF3, 0x40, 0x77, 0xFB};
26
static const u8 loc_1CE4[16] = {0x13, 0x5F, 0xA4, 0x7C, 0xAB, 0x39, 0x5B, 0xA4, 0x76, 0xB8, 0xCC, 0xA9, 0x8F, 0x3A, 0x04, 0x45};
27
static const u8 loc_1CF4[16] = {0x67, 0x8D, 0x7F, 0xA3, 0x2A, 0x9C, 0xA0, 0xD1, 0x50, 0x8A, 0xD8, 0x38, 0x5E, 0x4B, 0x01, 0x7E};
28
29
/*************************************************************/
30
31
static int do_kirk4(KirkState *kirk, u8 *buf, int size, int type)
32
{
33
int retv;
34
u32 *header = (u32*)buf;
35
36
header[0] = 4;
37
header[1] = 0;
38
header[2] = 0;
39
header[3] = type;
40
header[4] = size;
41
42
retv = kirk_sceUtilsBufferCopyWithRange(kirk, buf, size+0x14, buf, size, 4);
43
44
if(retv)
45
return 0x80510311;
46
47
return 0;
48
}
49
50
static int do_kirk7(KirkState *kirk, u8 *buf, int size, int type)
51
{
52
int retv;
53
u32 *header = (u32*)buf;
54
55
header[0] = 5;
56
header[1] = 0;
57
header[2] = 0;
58
header[3] = type;
59
header[4] = size;
60
61
retv = kirk_sceUtilsBufferCopyWithRange(kirk, buf, size+0x14, buf, size, 7);
62
if(retv)
63
return 0x80510311;
64
65
return 0;
66
}
67
68
static int kirk5(KirkState *kirk, u8 *buf, int size)
69
{
70
int retv;
71
u32 *header = (u32*)buf;
72
73
header[0] = 4;
74
header[1] = 0;
75
header[2] = 0;
76
header[3] = 0x0100;
77
header[4] = size;
78
79
retv = kirk_sceUtilsBufferCopyWithRange(kirk, buf, size+0x14, buf, size, 5);
80
if(retv)
81
return 0x80510312;
82
83
return 0;
84
}
85
86
static int kirk8(KirkState *kirk, u8 *buf, int size)
87
{
88
int retv;
89
u32 *header = (u32*)buf;
90
91
header[0] = 5;
92
header[1] = 0;
93
header[2] = 0;
94
header[3] = 0x0100;
95
header[4] = size;
96
97
retv = kirk_sceUtilsBufferCopyWithRange(kirk, buf, size+0x14, buf, size, 8);
98
if(retv)
99
return 0x80510312;
100
101
return 0;
102
}
103
104
static int kirk14(KirkState *kirk, u8 *buf)
105
{
106
int retv;
107
108
retv = kirk_sceUtilsBufferCopyWithRange(kirk, buf, 0x14, 0, 0, 14);
109
if(retv)
110
return 0x80510315;
111
112
return 0;
113
}
114
115
/*************************************************************/
116
117
// Called by sceDrmBBMacUpdate
118
// encrypt_buf
119
static int sub_158(KirkState *kirk, u8 *buf, int size, u8 *key, int key_type)
120
{
121
int i, retv;
122
123
for(i=0; i<16; i++){
124
buf[0x14+i] ^= key[i];
125
}
126
127
retv = do_kirk4(kirk, buf, size, key_type);
128
if(retv)
129
return retv;
130
131
// copy last 16 bytes to keys
132
memcpy(key, buf+size+4, 16);
133
134
return 0;
135
}
136
137
138
// type:
139
// 2: use fuse id
140
// 3: use fixed id
141
int sceDrmBBMacInit(MAC_KEY *mkey, int type)
142
{
143
mkey->type = type;
144
mkey->pad_size = 0;
145
146
memset(mkey->key, 0, 16);
147
memset(mkey->pad, 0, 16);
148
149
return 0;
150
}
151
152
int sceDrmBBMacUpdate(KirkState *kirk, MAC_KEY *mkey, u8 *buf, int size)
153
{
154
int retv = 0, ksize, p, type;
155
u8 *kbuf;
156
157
if(mkey->pad_size>16){
158
retv = 0x80510302;
159
goto _exit;
160
}
161
162
if(mkey->pad_size+size<=16){
163
memcpy(mkey->pad+mkey->pad_size, buf, size);
164
mkey->pad_size += size;
165
retv = 0;
166
}else{
167
kbuf = kirk->kirk_buf+0x14;
168
// copy pad data first
169
memcpy(kbuf, mkey->pad, mkey->pad_size);
170
171
p = mkey->pad_size;
172
173
mkey->pad_size += size;
174
mkey->pad_size &= 0x0f;
175
if(mkey->pad_size==0)
176
mkey->pad_size = 16;
177
178
size -= mkey->pad_size;
179
// save last data to pad buf
180
memcpy(mkey->pad, buf+size, mkey->pad_size);
181
182
type = (mkey->type==2)? 0x3A : 0x38;
183
184
while(size){
185
ksize = (size+p>=0x0800)? 0x0800 : size+p;
186
memcpy(kbuf+p, buf, ksize-p);
187
retv = sub_158(kirk, kirk->kirk_buf, ksize, mkey->key, type);
188
if(retv)
189
goto _exit;
190
size -= (ksize-p);
191
buf += ksize-p;
192
p = 0;
193
}
194
}
195
196
_exit:
197
return retv;
198
199
}
200
201
int sceDrmBBMacFinal(KirkState *kirk, MAC_KEY *mkey, u8 *buf, u8 *vkey)
202
{
203
int i, retv, code;
204
u8 *kbuf, tmp[16], tmp1[16];
205
u32 t0, v0, v1;
206
207
if(mkey->pad_size>16)
208
return 0x80510302;
209
210
code = (mkey->type==2)? 0x3A : 0x38;
211
kbuf = kirk->kirk_buf+0x14;
212
213
memset(kbuf, 0, 16);
214
retv = do_kirk4(kirk, kirk->kirk_buf, 16, code);
215
if(retv)
216
goto _exit;
217
memcpy(tmp, kbuf, 16);
218
219
// left shift tmp 1 bit
220
t0 = (tmp[0]&0x80)? 0x87 : 0;
221
for(i=0; i<15; i++){
222
v1 = tmp[i+0];
223
v0 = tmp[i+1];
224
v1 <<= 1;
225
v0 >>= 7;
226
v0 |= v1;
227
tmp[i+0] = v0;
228
}
229
v0 = tmp[15];
230
v0 <<= 1;
231
v0 ^= t0;
232
tmp[15] = v0;
233
234
// padding remain data
235
if(mkey->pad_size<16){
236
// left shift tmp 1 bit
237
t0 = (tmp[0]&0x80)? 0x87 : 0;
238
for(i=0; i<15; i++){
239
v1 = tmp[i+0];
240
v0 = tmp[i+1];
241
v1 <<= 1;
242
v0 >>= 7;
243
v0 |= v1;
244
tmp[i+0] = v0;
245
}
246
v0 = tmp[15];
247
v0 <<= 1;
248
v0 ^= t0;
249
tmp[15] = v0;
250
251
mkey->pad[mkey->pad_size] = 0x80;
252
if(mkey->pad_size+1<16)
253
memset(mkey->pad+mkey->pad_size+1, 0, 16-mkey->pad_size-1);
254
}
255
256
for(i=0; i<16; i++){
257
mkey->pad[i] ^= tmp[i];
258
}
259
260
memcpy(kbuf, mkey->pad, 16);
261
memcpy(tmp1, mkey->key, 16);
262
263
retv = sub_158(kirk, kirk->kirk_buf, 0x10, tmp1, code);
264
if(retv)
265
return retv;
266
267
for(i=0; i<0x10; i++){
268
tmp1[i] ^= loc_1CD4[i];
269
}
270
271
if(mkey->type==2){
272
memcpy(kbuf, tmp1, 16);
273
274
retv = kirk5(kirk, kirk->kirk_buf, 0x10);
275
if(retv)
276
goto _exit;
277
278
retv = do_kirk4(kirk, kirk->kirk_buf, 0x10, code);
279
if(retv)
280
goto _exit;
281
282
memcpy(tmp1, kbuf, 16);
283
}
284
285
if(vkey){
286
for(i=0; i<0x10; i++){
287
tmp1[i] ^= vkey[i];
288
}
289
memcpy(kbuf, tmp1, 16);
290
291
retv = do_kirk4(kirk, kirk->kirk_buf, 0x10, code);
292
if(retv)
293
goto _exit;
294
295
memcpy(tmp1, kbuf, 16);
296
}
297
298
memcpy(buf, tmp1, 16);
299
300
memset(mkey->key, 0, 16);
301
memset(mkey->pad, 0, 16);
302
303
mkey->pad_size = 0;
304
mkey->type = 0;
305
retv = 0;
306
307
_exit:
308
return retv;
309
}
310
311
int sceDrmBBMacFinal2(KirkState *kirk, MAC_KEY *mkey, u8 *out, u8 *vkey)
312
{
313
int i, retv, type;
314
u8 *kbuf, tmp[16];
315
316
type = mkey->type;
317
retv = sceDrmBBMacFinal(kirk, mkey, tmp, vkey);
318
if(retv)
319
return retv;
320
321
kbuf = kirk->kirk_buf+0x14;
322
323
// decrypt bbmac
324
if(type==3){
325
memcpy(kbuf, out, 0x10);
326
do_kirk7(kirk, kirk->kirk_buf, 0x10, 0x63);
327
}else{
328
memcpy(kirk->kirk_buf, out, 0x10);
329
}
330
331
retv = 0;
332
for(i=0; i<0x10; i++){
333
if(kirk->kirk_buf[i]!=tmp[i]){
334
retv = 0x80510300;
335
break;
336
}
337
}
338
339
return retv;
340
}
341
342
// get key from bbmac
343
int bbmac_getkey(KirkState *kirk, MAC_KEY *mkey, u8 *bbmac, u8 *vkey)
344
{
345
int i, retv, type, code;
346
u8 *kbuf, tmp[16], tmp1[16];
347
348
type = mkey->type;
349
retv = sceDrmBBMacFinal(kirk, mkey, tmp, NULL);
350
if(retv)
351
return retv;
352
353
kbuf = kirk->kirk_buf+0x14;
354
355
// decrypt bbmac
356
if(type==3){
357
memcpy(kbuf, bbmac, 0x10);
358
do_kirk7(kirk, kirk->kirk_buf, 0x10, 0x63);
359
}else{
360
memcpy(kirk->kirk_buf, bbmac, 0x10);
361
}
362
363
memcpy(tmp1, kirk->kirk_buf, 16);
364
memcpy(kbuf, tmp1, 16);
365
366
code = (type==2)? 0x3A : 0x38;
367
do_kirk7(kirk, kirk->kirk_buf, 0x10, code);
368
369
for(i=0; i<0x10; i++){
370
vkey[i] = tmp[i] ^ kirk->kirk_buf[i];
371
}
372
373
return 0;
374
}
375
376
/*************************************************************/
377
378
static int sub_1F8(KirkState *kirk, u8 *buf, int size, u8 *key, int key_type)
379
{
380
int i, retv;
381
u8 tmp[16];
382
383
// copy last 16 bytes to tmp
384
memcpy(tmp, buf+size+0x14-16, 16);
385
386
retv = do_kirk7(kirk, buf, size, key_type);
387
if(retv)
388
return retv;
389
390
for(i=0; i<16; i++){
391
buf[i] ^= key[i];
392
}
393
394
// copy last 16 bytes to keys
395
memcpy(key, tmp, 16);
396
397
return 0;
398
}
399
400
401
static int sub_428(KirkState *kirk, u8 *kbuf, u8 *dbuf, int size, CIPHER_KEY *ckey)
402
{
403
int i, retv;
404
u8 tmp1[16], tmp2[16];
405
406
memcpy(kbuf+0x14, ckey->key, 16);
407
408
for(i=0; i<16; i++){
409
kbuf[0x14+i] ^= loc_1CF4[i];
410
}
411
412
if(ckey->type==2)
413
retv = kirk8(kirk, kbuf, 16);
414
else
415
retv = do_kirk7(kirk, kbuf, 16, 0x39);
416
if(retv)
417
return retv;
418
419
for(i=0; i<16; i++){
420
kbuf[i] ^= loc_1CE4[i];
421
}
422
423
memcpy(tmp2, kbuf, 0x10);
424
425
if(ckey->seed==1){
426
memset(tmp1, 0, 0x10);
427
}else{
428
memcpy(tmp1, tmp2, 0x10);
429
*(u32*)(tmp1+0x0c) = ckey->seed-1;
430
}
431
432
for(i=0; i<size; i+=16){
433
memcpy(kbuf+0x14+i, tmp2, 12);
434
*(u32*)(kbuf+0x14+i+12) = ckey->seed;
435
ckey->seed += 1;
436
}
437
438
retv = sub_1F8(kirk, kbuf, size, tmp1, 0x63);
439
if(retv)
440
return retv;
441
442
for(i=0; i<size; i++){
443
dbuf[i] ^= kbuf[i];
444
}
445
446
return 0;
447
}
448
449
// type: 1 use fixed key
450
// 2 use fuse id
451
// mode: 1 for encrypt
452
// 2 for decrypt
453
int sceDrmBBCipherInit(KirkState *kirk, CIPHER_KEY *ckey, int type, int mode, u8 *header_key, u8 *version_key, u32 seed)
454
{
455
int i, retv;
456
u8 *kbuf;
457
458
kbuf = kirk->kirk_buf+0x14;
459
ckey->type = type;
460
if(mode==2){
461
ckey->seed = seed+1;
462
for(i=0; i<16; i++){
463
ckey->key[i] = header_key[i];
464
}
465
if(version_key){
466
for(i=0; i<16; i++){
467
ckey->key[i] ^= version_key[i];
468
}
469
}
470
retv = 0;
471
}else if(mode==1){
472
ckey->seed = 1;
473
retv = kirk14(kirk, kirk->kirk_buf);
474
if(retv)
475
return retv;
476
477
memcpy(kbuf, kirk->kirk_buf, 0x10);
478
memset(kbuf+0x0c, 0, 4);
479
480
if(ckey->type==2){
481
for(i=0; i<16; i++){
482
kbuf[i] ^= loc_1CE4[i];
483
}
484
retv = kirk5(kirk, kirk->kirk_buf, 0x10);
485
for(i=0; i<16; i++){
486
kbuf[i] ^= loc_1CF4[i];
487
}
488
}else{
489
for(i=0; i<16; i++){
490
kbuf[i] ^= loc_1CE4[i];
491
}
492
retv = do_kirk4(kirk, kirk->kirk_buf, 0x10, 0x39);
493
for(i=0; i<16; i++){
494
kbuf[i] ^= loc_1CF4[i];
495
}
496
}
497
if(retv)
498
return retv;
499
500
memcpy(ckey->key, kbuf, 0x10);
501
memcpy(header_key, kbuf, 0x10);
502
503
if(version_key){
504
for(i=0; i<16; i++){
505
ckey->key[i] ^= version_key[i];
506
}
507
}
508
}else{
509
retv = 0;
510
}
511
512
return retv;
513
}
514
515
int sceDrmBBCipherUpdate(KirkState *kirk, CIPHER_KEY *ckey, u8 *data, int size)
516
{
517
int p, retv, dsize;
518
519
retv = 0;
520
p = 0;
521
522
while(size>0){
523
dsize = (size>=0x0800)? 0x0800 : size;
524
retv = sub_428(kirk, kirk->kirk_buf, data+p, dsize, ckey);
525
if(retv)
526
break;
527
size -= dsize;
528
p += dsize;
529
}
530
531
return retv;
532
}
533
534
int sceDrmBBCipherFinal(CIPHER_KEY *ckey)
535
{
536
memset(ckey->key, 0, 16);
537
ckey->type = 0;
538
ckey->seed = 0;
539
540
return 0;
541
}
542
543
/*************************************************************/
544
545
// AES128 encrypt key
546
static const u8 key_357C[0x30] = {
547
0x07,0x3D,0x9E,0x9D,0xA8,0xFD,0x3B,0x2F,0x63,0x18,0x93,0x2E,0xF8,0x57,0xA6,0x64,
548
0x37,0x49,0xB7,0x01,0xCA,0xE2,0xE0,0xC5,0x44,0x2E,0x06,0xB6,0x1E,0xFF,0x84,0xF2,
549
0x9D,0x31,0xB8,0x5A,0xC8,0xFA,0x16,0x80,0x73,0x60,0x18,0x82,0x18,0x77,0x91,0x9D,
550
};
551
552
static const u8 key_363C[16] = {
553
0x38,0x20,0xD0,0x11,0x07,0xA3,0xFF,0x3E,0x0A,0x4C,0x20,0x85,0x39,0x10,0xB5,0x54,
554
};
555
556
int sceNpDrmGetFixedKey(KirkState *kirk, u8 *key, char *npstr, int type)
557
{
558
AES_ctx akey;
559
MAC_KEY mkey;
560
char strbuf[0x30];
561
int retv;
562
563
if((type&0x01000000)==0)
564
return 0x80550901;
565
type &= 0x000000ff;
566
567
memset(strbuf, 0, 0x30);
568
strncpy(strbuf, npstr, 0x30);
569
570
retv = sceDrmBBMacInit(&mkey, 1);
571
if(retv)
572
return retv;
573
574
retv = sceDrmBBMacUpdate(kirk, &mkey, (u8*)strbuf, 0x30);
575
if(retv)
576
return retv;
577
578
retv = sceDrmBBMacFinal(kirk, &mkey, key, (u8*)key_363C);
579
if(retv)
580
return 0x80550902;
581
582
if(type==0)
583
return 0;
584
if(type>3)
585
return 0x80550901;
586
type = (type-1)*16;
587
588
AES_set_key(&akey, &key_357C[type], 128);
589
AES_encrypt(&akey, key, key);
590
591
return 0;
592
}
593
594
595
/*************************************************************/
596
597
598
static const u8 dnas_key1A90[] = {0xED,0xE2,0x5D,0x2D,0xBB,0xF8,0x12,0xE5,0x3C,0x5C,0x59,0x32,0xFA,0xE3,0xE2,0x43};
599
static const u8 dnas_key1AA0[] = {0x27,0x74,0xFB,0xEB,0xA4,0xA0, 1,0xD7, 2,0x56,0x9E,0x33,0x8C,0x19,0x57,0x83};
600
601
PGD_DESC *pgd_open(KirkState *kirk, u8 *pgd_buf, int pgd_flag, u8 *pgd_vkey)
602
{
603
PGD_DESC *pgd;
604
MAC_KEY mkey;
605
CIPHER_KEY ckey;
606
u8 *fkey;
607
int retv;
608
609
//DEBUG_LOG(Log::HLE, "Open PGD ...");
610
611
pgd = (PGD_DESC*)malloc(sizeof(PGD_DESC));
612
memset(pgd, 0, sizeof(PGD_DESC));
613
614
pgd->key_index = *(u32*)(pgd_buf+4);
615
pgd->drm_type = *(u32*)(pgd_buf+8);
616
617
if(pgd->drm_type==1){
618
pgd->mac_type = 1;
619
pgd_flag |= 4;
620
if(pgd->key_index>1){
621
pgd->mac_type = 3;
622
pgd_flag |= 8;
623
}
624
pgd->cipher_type = 1;
625
}else{
626
pgd->mac_type = 2;
627
pgd->cipher_type = 2;
628
}
629
pgd->open_flag = pgd_flag;
630
631
// select fixed key
632
fkey = NULL;
633
if(pgd_flag&2)
634
fkey = (u8*)dnas_key1A90;
635
if(pgd_flag&1)
636
fkey = (u8*)dnas_key1AA0;
637
if(fkey==NULL){
638
//ERROR_LOG(Log::HLE, "pgd_open: invalid pgd_flag! %08x\n", pgd_flag);
639
free(pgd);
640
return NULL;
641
}
642
643
// MAC_0x80 check
644
sceDrmBBMacInit(&mkey, pgd->mac_type);
645
sceDrmBBMacUpdate(kirk, &mkey, pgd_buf+0x00, 0x80);
646
retv = sceDrmBBMacFinal2(kirk, &mkey, pgd_buf+0x80, fkey);
647
if(retv){
648
//ERROR_LOG(Log::HLE, "pgd_open: MAC_80 check failed!: %08x(%d)\n", retv, retv);
649
free(pgd);
650
return NULL;
651
}
652
653
// MAC_0x70
654
sceDrmBBMacInit(&mkey, pgd->mac_type);
655
sceDrmBBMacUpdate(kirk, &mkey, pgd_buf+0x00, 0x70);
656
if(pgd_vkey){
657
// use given vkey
658
retv = sceDrmBBMacFinal2(kirk, &mkey, pgd_buf+0x70, pgd_vkey);
659
if(retv){
660
//ERROR_LOG(Log::HLE, "pgd_open: MAC_70 check failed!: %08x(%d)\n", retv, retv);
661
free(pgd);
662
return NULL;
663
}else{
664
memcpy(pgd->vkey, pgd_vkey, 16);
665
}
666
}else{
667
// get vkey from MAC_70
668
bbmac_getkey(kirk, &mkey, pgd_buf+0x70, pgd->vkey);
669
}
670
671
// decrypt PGD_DESC
672
sceDrmBBCipherInit(kirk, &ckey, pgd->cipher_type, 2, pgd_buf+0x10, pgd->vkey, 0);
673
sceDrmBBCipherUpdate(kirk, &ckey, pgd_buf+0x30, 0x30);
674
sceDrmBBCipherFinal(&ckey);
675
676
pgd->data_size = *(u32*)(pgd_buf+0x44);
677
pgd->block_size = *(u32*)(pgd_buf+0x48);
678
pgd->data_offset = *(u32*)(pgd_buf+0x4c);
679
memcpy(pgd->dkey, pgd_buf+0x30, 16);
680
681
pgd->align_size = (pgd->data_size+15)&~15;
682
pgd->table_offset = pgd->data_offset+pgd->align_size;
683
pgd->block_nr = (pgd->align_size+pgd->block_size-1)&~(pgd->block_size-1);
684
pgd->block_nr = pgd->block_nr/pgd->block_size;
685
686
pgd->file_offset = 0;
687
pgd->current_block = -1;
688
pgd->block_buf = (u8*)malloc(pgd->block_size*2);
689
690
return pgd;
691
}
692
693
int pgd_decrypt_block(KirkState *kirk, PGD_DESC *pgd, int block)
694
{
695
CIPHER_KEY ckey;
696
u32 block_offset;
697
698
block_offset = block*pgd->block_size;
699
700
// decrypt block data
701
sceDrmBBCipherInit(kirk, &ckey, pgd->cipher_type, 2, pgd->dkey, pgd->vkey, block_offset>>4);
702
sceDrmBBCipherUpdate(kirk, &ckey, pgd->block_buf, pgd->block_size);
703
sceDrmBBCipherFinal(&ckey);
704
705
return pgd->block_size;
706
}
707
708
int pgd_close(PGD_DESC *pgd)
709
{
710
if(pgd){
711
free(pgd->block_buf);
712
free(pgd);
713
}
714
return 0;
715
}
716
717
/*************************************************************/
718
719
720