CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
hrydgard

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

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