CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
Path: blob/master/ext/libkirk/amctrl.c
Views: 1401
/*1* amctrl.c -- Reverse engineering of amctrl.prx2* written by tpu.3*/456#include <stdio.h>7#include <stdlib.h>8#include <string.h>910#include "kirk_engine.h"11#include "AES.h"12#include "SHA1.h"13#include "amctrl.h"1415//Turn off optimization in VS201316#ifdef _MSC_VER17#if (_MSC_VER == 1800)18#pragma optimize( "", off )19#endif20#pragma warning(disable:4996) // for strncpy21#endif22/*************************************************************/2324static const u8 loc_1CD4[16] = {0xE3, 0x50, 0xED, 0x1D, 0x91, 0x0A, 0x1F, 0xD0, 0x29, 0xBB, 0x1C, 0x3E, 0xF3, 0x40, 0x77, 0xFB};25static const u8 loc_1CE4[16] = {0x13, 0x5F, 0xA4, 0x7C, 0xAB, 0x39, 0x5B, 0xA4, 0x76, 0xB8, 0xCC, 0xA9, 0x8F, 0x3A, 0x04, 0x45};26static const u8 loc_1CF4[16] = {0x67, 0x8D, 0x7F, 0xA3, 0x2A, 0x9C, 0xA0, 0xD1, 0x50, 0x8A, 0xD8, 0x38, 0x5E, 0x4B, 0x01, 0x7E};2728static u8 kirk_buf[0x0814]; // 1DC0 1DD42930/*************************************************************/3132static int do_kirk4(u8 *buf, int size, int type)33{34int retv;35u32 *header = (u32*)buf;3637header[0] = 4;38header[1] = 0;39header[2] = 0;40header[3] = type;41header[4] = size;4243retv = kirk_sceUtilsBufferCopyWithRange(buf, size+0x14, buf, size, 4);4445if(retv)46return 0x80510311;4748return 0;49}5051static int do_kirk7(u8 *buf, int size, int type)52{53int retv;54u32 *header = (u32*)buf;5556header[0] = 5;57header[1] = 0;58header[2] = 0;59header[3] = type;60header[4] = size;6162retv = kirk_sceUtilsBufferCopyWithRange(buf, size+0x14, buf, size, 7);63if(retv)64return 0x80510311;6566return 0;67}6869static int kirk5(u8 *buf, int size)70{71int retv;72u32 *header = (u32*)buf;7374header[0] = 4;75header[1] = 0;76header[2] = 0;77header[3] = 0x0100;78header[4] = size;7980retv = kirk_sceUtilsBufferCopyWithRange(buf, size+0x14, buf, size, 5);81if(retv)82return 0x80510312;8384return 0;85}8687static int kirk8(u8 *buf, int size)88{89int retv;90u32 *header = (u32*)buf;9192header[0] = 5;93header[1] = 0;94header[2] = 0;95header[3] = 0x0100;96header[4] = size;9798retv = kirk_sceUtilsBufferCopyWithRange(buf, size+0x14, buf, size, 8);99if(retv)100return 0x80510312;101102return 0;103}104105static int kirk14(u8 *buf)106{107int retv;108109retv = kirk_sceUtilsBufferCopyWithRange(buf, 0x14, 0, 0, 14);110if(retv)111return 0x80510315;112113return 0;114}115116/*************************************************************/117118// Called by sceDrmBBMacUpdate119// encrypt_buf120static int sub_158(u8 *buf, int size, u8 *key, int key_type)121{122int i, retv;123124for(i=0; i<16; i++){125buf[0x14+i] ^= key[i];126}127128retv = do_kirk4(buf, size, key_type);129if(retv)130return retv;131132// copy last 16 bytes to keys133memcpy(key, buf+size+4, 16);134135return 0;136}137138139// type:140// 2: use fuse id141// 3: use fixed id142int sceDrmBBMacInit(MAC_KEY *mkey, int type)143{144mkey->type = type;145mkey->pad_size = 0;146147memset(mkey->key, 0, 16);148memset(mkey->pad, 0, 16);149150return 0;151}152153int sceDrmBBMacUpdate(MAC_KEY *mkey, u8 *buf, int size)154{155int retv = 0, ksize, p, type;156u8 *kbuf;157158if(mkey->pad_size>16){159retv = 0x80510302;160goto _exit;161}162163if(mkey->pad_size+size<=16){164memcpy(mkey->pad+mkey->pad_size, buf, size);165mkey->pad_size += size;166retv = 0;167}else{168kbuf = kirk_buf+0x14;169// copy pad data first170memcpy(kbuf, mkey->pad, mkey->pad_size);171172p = mkey->pad_size;173174mkey->pad_size += size;175mkey->pad_size &= 0x0f;176if(mkey->pad_size==0)177mkey->pad_size = 16;178179size -= mkey->pad_size;180// save last data to pad buf181memcpy(mkey->pad, buf+size, mkey->pad_size);182183type = (mkey->type==2)? 0x3A : 0x38;184185while(size){186ksize = (size+p>=0x0800)? 0x0800 : size+p;187memcpy(kbuf+p, buf, ksize-p);188retv = sub_158(kirk_buf, ksize, mkey->key, type);189if(retv)190goto _exit;191size -= (ksize-p);192buf += ksize-p;193p = 0;194}195}196197_exit:198return retv;199200}201202int sceDrmBBMacFinal(MAC_KEY *mkey, u8 *buf, u8 *vkey)203{204int i, retv, code;205u8 *kbuf, tmp[16], tmp1[16];206u32 t0, v0, v1;207208if(mkey->pad_size>16)209return 0x80510302;210211code = (mkey->type==2)? 0x3A : 0x38;212kbuf = kirk_buf+0x14;213214memset(kbuf, 0, 16);215retv = do_kirk4(kirk_buf, 16, code);216if(retv)217goto _exit;218memcpy(tmp, kbuf, 16);219220// left shift tmp 1 bit221t0 = (tmp[0]&0x80)? 0x87 : 0;222for(i=0; i<15; i++){223v1 = tmp[i+0];224v0 = tmp[i+1];225v1 <<= 1;226v0 >>= 7;227v0 |= v1;228tmp[i+0] = v0;229}230v0 = tmp[15];231v0 <<= 1;232v0 ^= t0;233tmp[15] = v0;234235// padding remain data236if(mkey->pad_size<16){237// left shift tmp 1 bit238t0 = (tmp[0]&0x80)? 0x87 : 0;239for(i=0; i<15; i++){240v1 = tmp[i+0];241v0 = tmp[i+1];242v1 <<= 1;243v0 >>= 7;244v0 |= v1;245tmp[i+0] = v0;246}247v0 = tmp[15];248v0 <<= 1;249v0 ^= t0;250tmp[15] = v0;251252mkey->pad[mkey->pad_size] = 0x80;253if(mkey->pad_size+1<16)254memset(mkey->pad+mkey->pad_size+1, 0, 16-mkey->pad_size-1);255}256257for(i=0; i<16; i++){258mkey->pad[i] ^= tmp[i];259}260261memcpy(kbuf, mkey->pad, 16);262memcpy(tmp1, mkey->key, 16);263264retv = sub_158(kirk_buf, 0x10, tmp1, code);265if(retv)266return retv;267268for(i=0; i<0x10; i++){269tmp1[i] ^= loc_1CD4[i];270}271272if(mkey->type==2){273memcpy(kbuf, tmp1, 16);274275retv = kirk5(kirk_buf, 0x10);276if(retv)277goto _exit;278279retv = do_kirk4(kirk_buf, 0x10, code);280if(retv)281goto _exit;282283memcpy(tmp1, kbuf, 16);284}285286if(vkey){287for(i=0; i<0x10; i++){288tmp1[i] ^= vkey[i];289}290memcpy(kbuf, tmp1, 16);291292retv = do_kirk4(kirk_buf, 0x10, code);293if(retv)294goto _exit;295296memcpy(tmp1, kbuf, 16);297}298299memcpy(buf, tmp1, 16);300301memset(mkey->key, 0, 16);302memset(mkey->pad, 0, 16);303304mkey->pad_size = 0;305mkey->type = 0;306retv = 0;307308_exit:309return retv;310}311312int sceDrmBBMacFinal2(MAC_KEY *mkey, u8 *out, u8 *vkey)313{314int i, retv, type;315u8 *kbuf, tmp[16];316317type = mkey->type;318retv = sceDrmBBMacFinal(mkey, tmp, vkey);319if(retv)320return retv;321322kbuf = kirk_buf+0x14;323324// decrypt bbmac325if(type==3){326memcpy(kbuf, out, 0x10);327do_kirk7(kirk_buf, 0x10, 0x63);328}else{329memcpy(kirk_buf, out, 0x10);330}331332retv = 0;333for(i=0; i<0x10; i++){334if(kirk_buf[i]!=tmp[i]){335retv = 0x80510300;336break;337}338}339340return retv;341}342343// get key from bbmac344int bbmac_getkey(MAC_KEY *mkey, u8 *bbmac, u8 *vkey)345{346int i, retv, type, code;347u8 *kbuf, tmp[16], tmp1[16];348349type = mkey->type;350retv = sceDrmBBMacFinal(mkey, tmp, NULL);351if(retv)352return retv;353354kbuf = kirk_buf+0x14;355356// decrypt bbmac357if(type==3){358memcpy(kbuf, bbmac, 0x10);359do_kirk7(kirk_buf, 0x10, 0x63);360}else{361memcpy(kirk_buf, bbmac, 0x10);362}363364memcpy(tmp1, kirk_buf, 16);365memcpy(kbuf, tmp1, 16);366367code = (type==2)? 0x3A : 0x38;368do_kirk7(kirk_buf, 0x10, code);369370for(i=0; i<0x10; i++){371vkey[i] = tmp[i] ^ kirk_buf[i];372}373374return 0;375}376377/*************************************************************/378379static int sub_1F8(u8 *buf, int size, u8 *key, int key_type)380{381int i, retv;382u8 tmp[16];383384// copy last 16 bytes to tmp385memcpy(tmp, buf+size+0x14-16, 16);386387retv = do_kirk7(buf, size, key_type);388if(retv)389return retv;390391for(i=0; i<16; i++){392buf[i] ^= key[i];393}394395// copy last 16 bytes to keys396memcpy(key, tmp, 16);397398return 0;399}400401402static int sub_428(u8 *kbuf, u8 *dbuf, int size, CIPHER_KEY *ckey)403{404int i, retv;405u8 tmp1[16], tmp2[16];406407memcpy(kbuf+0x14, ckey->key, 16);408409for(i=0; i<16; i++){410kbuf[0x14+i] ^= loc_1CF4[i];411}412413if(ckey->type==2)414retv = kirk8(kbuf, 16);415else416retv = do_kirk7(kbuf, 16, 0x39);417if(retv)418return retv;419420for(i=0; i<16; i++){421kbuf[i] ^= loc_1CE4[i];422}423424memcpy(tmp2, kbuf, 0x10);425426if(ckey->seed==1){427memset(tmp1, 0, 0x10);428}else{429memcpy(tmp1, tmp2, 0x10);430*(u32*)(tmp1+0x0c) = ckey->seed-1;431}432433for(i=0; i<size; i+=16){434memcpy(kbuf+0x14+i, tmp2, 12);435*(u32*)(kbuf+0x14+i+12) = ckey->seed;436ckey->seed += 1;437}438439retv = sub_1F8(kbuf, size, tmp1, 0x63);440if(retv)441return retv;442443for(i=0; i<size; i++){444dbuf[i] ^= kbuf[i];445}446447return 0;448}449450// type: 1 use fixed key451// 2 use fuse id452// mode: 1 for encrypt453// 2 for decrypt454int sceDrmBBCipherInit(CIPHER_KEY *ckey, int type, int mode, u8 *header_key, u8 *version_key, u32 seed)455{456int i, retv;457u8 *kbuf;458459kbuf = kirk_buf+0x14;460ckey->type = type;461if(mode==2){462ckey->seed = seed+1;463for(i=0; i<16; i++){464ckey->key[i] = header_key[i];465}466if(version_key){467for(i=0; i<16; i++){468ckey->key[i] ^= version_key[i];469}470}471retv = 0;472}else if(mode==1){473ckey->seed = 1;474retv = kirk14(kirk_buf);475if(retv)476return retv;477478memcpy(kbuf, kirk_buf, 0x10);479memset(kbuf+0x0c, 0, 4);480481if(ckey->type==2){482for(i=0; i<16; i++){483kbuf[i] ^= loc_1CE4[i];484}485retv = kirk5(kirk_buf, 0x10);486for(i=0; i<16; i++){487kbuf[i] ^= loc_1CF4[i];488}489}else{490for(i=0; i<16; i++){491kbuf[i] ^= loc_1CE4[i];492}493retv = do_kirk4(kirk_buf, 0x10, 0x39);494for(i=0; i<16; i++){495kbuf[i] ^= loc_1CF4[i];496}497}498if(retv)499return retv;500501memcpy(ckey->key, kbuf, 0x10);502memcpy(header_key, kbuf, 0x10);503504if(version_key){505for(i=0; i<16; i++){506ckey->key[i] ^= version_key[i];507}508}509}else{510retv = 0;511}512513return retv;514}515516int sceDrmBBCipherUpdate(CIPHER_KEY *ckey, u8 *data, int size)517{518int p, retv, dsize;519520retv = 0;521p = 0;522523while(size>0){524dsize = (size>=0x0800)? 0x0800 : size;525retv = sub_428(kirk_buf, data+p, dsize, ckey);526if(retv)527break;528size -= dsize;529p += dsize;530}531532return retv;533}534535int sceDrmBBCipherFinal(CIPHER_KEY *ckey)536{537memset(ckey->key, 0, 16);538ckey->type = 0;539ckey->seed = 0;540541return 0;542}543544/*************************************************************/545546// AES128 encrypt key547static const u8 key_357C[0x30] = {5480x07,0x3D,0x9E,0x9D,0xA8,0xFD,0x3B,0x2F,0x63,0x18,0x93,0x2E,0xF8,0x57,0xA6,0x64,5490x37,0x49,0xB7,0x01,0xCA,0xE2,0xE0,0xC5,0x44,0x2E,0x06,0xB6,0x1E,0xFF,0x84,0xF2,5500x9D,0x31,0xB8,0x5A,0xC8,0xFA,0x16,0x80,0x73,0x60,0x18,0x82,0x18,0x77,0x91,0x9D,551};552553static const u8 key_363C[16] = {5540x38,0x20,0xD0,0x11,0x07,0xA3,0xFF,0x3E,0x0A,0x4C,0x20,0x85,0x39,0x10,0xB5,0x54,555};556557int sceNpDrmGetFixedKey(u8 *key, char *npstr, int type)558{559AES_ctx akey;560MAC_KEY mkey;561char strbuf[0x30];562int retv;563564if((type&0x01000000)==0)565return 0x80550901;566type &= 0x000000ff;567568memset(strbuf, 0, 0x30);569strncpy(strbuf, npstr, 0x30);570571retv = sceDrmBBMacInit(&mkey, 1);572if(retv)573return retv;574575retv = sceDrmBBMacUpdate(&mkey, (u8*)strbuf, 0x30);576if(retv)577return retv;578579retv = sceDrmBBMacFinal(&mkey, key, (u8*)key_363C);580if(retv)581return 0x80550902;582583if(type==0)584return 0;585if(type>3)586return 0x80550901;587type = (type-1)*16;588589AES_set_key(&akey, &key_357C[type], 128);590AES_encrypt(&akey, key, key);591592return 0;593}594595596/*************************************************************/597598599static const u8 dnas_key1A90[] = {0xED,0xE2,0x5D,0x2D,0xBB,0xF8,0x12,0xE5,0x3C,0x5C,0x59,0x32,0xFA,0xE3,0xE2,0x43};600static const u8 dnas_key1AA0[] = {0x27,0x74,0xFB,0xEB,0xA4,0xA0, 1,0xD7, 2,0x56,0x9E,0x33,0x8C,0x19,0x57,0x83};601602PGD_DESC *pgd_open(u8 *pgd_buf, int pgd_flag, u8 *pgd_vkey)603{604PGD_DESC *pgd;605MAC_KEY mkey;606CIPHER_KEY ckey;607u8 *fkey;608int retv;609610//DEBUG_LOG(Log::HLE, "Open PGD ...");611612pgd = (PGD_DESC*)malloc(sizeof(PGD_DESC));613memset(pgd, 0, sizeof(PGD_DESC));614615pgd->key_index = *(u32*)(pgd_buf+4);616pgd->drm_type = *(u32*)(pgd_buf+8);617618if(pgd->drm_type==1){619pgd->mac_type = 1;620pgd_flag |= 4;621if(pgd->key_index>1){622pgd->mac_type = 3;623pgd_flag |= 8;624}625pgd->cipher_type = 1;626}else{627pgd->mac_type = 2;628pgd->cipher_type = 2;629}630pgd->open_flag = pgd_flag;631632// select fixed key633fkey = NULL;634if(pgd_flag&2)635fkey = (u8*)dnas_key1A90;636if(pgd_flag&1)637fkey = (u8*)dnas_key1AA0;638if(fkey==NULL){639//ERROR_LOG(Log::HLE, "pgd_open: invalid pgd_flag! %08x\n", pgd_flag);640free(pgd);641return NULL;642}643644// MAC_0x80 check645sceDrmBBMacInit(&mkey, pgd->mac_type);646sceDrmBBMacUpdate(&mkey, pgd_buf+0x00, 0x80);647retv = sceDrmBBMacFinal2(&mkey, pgd_buf+0x80, fkey);648if(retv){649//ERROR_LOG(Log::HLE, "pgd_open: MAC_80 check failed!: %08x(%d)\n", retv, retv);650free(pgd);651return NULL;652}653654// MAC_0x70655sceDrmBBMacInit(&mkey, pgd->mac_type);656sceDrmBBMacUpdate(&mkey, pgd_buf+0x00, 0x70);657if(pgd_vkey){658// use given vkey659retv = sceDrmBBMacFinal2(&mkey, pgd_buf+0x70, pgd_vkey);660if(retv){661//ERROR_LOG(Log::HLE, "pgd_open: MAC_70 check failed!: %08x(%d)\n", retv, retv);662free(pgd);663return NULL;664}else{665memcpy(pgd->vkey, pgd_vkey, 16);666}667}else{668// get vkey from MAC_70669bbmac_getkey(&mkey, pgd_buf+0x70, pgd->vkey);670}671672// decrypt PGD_DESC673sceDrmBBCipherInit(&ckey, pgd->cipher_type, 2, pgd_buf+0x10, pgd->vkey, 0);674sceDrmBBCipherUpdate(&ckey, pgd_buf+0x30, 0x30);675sceDrmBBCipherFinal(&ckey);676677pgd->data_size = *(u32*)(pgd_buf+0x44);678pgd->block_size = *(u32*)(pgd_buf+0x48);679pgd->data_offset = *(u32*)(pgd_buf+0x4c);680memcpy(pgd->dkey, pgd_buf+0x30, 16);681682pgd->align_size = (pgd->data_size+15)&~15;683pgd->table_offset = pgd->data_offset+pgd->align_size;684pgd->block_nr = (pgd->align_size+pgd->block_size-1)&~(pgd->block_size-1);685pgd->block_nr = pgd->block_nr/pgd->block_size;686687pgd->file_offset = 0;688pgd->current_block = -1;689pgd->block_buf = (u8*)malloc(pgd->block_size*2);690691return pgd;692}693694int pgd_decrypt_block(PGD_DESC *pgd, int block)695{696CIPHER_KEY ckey;697u32 block_offset;698699block_offset = block*pgd->block_size;700701// decrypt block data702sceDrmBBCipherInit(&ckey, pgd->cipher_type, 2, pgd->dkey, pgd->vkey, block_offset>>4);703sceDrmBBCipherUpdate(&ckey, pgd->block_buf, pgd->block_size);704sceDrmBBCipherFinal(&ckey);705706return pgd->block_size;707}708709int pgd_close(PGD_DESC *pgd)710{711if(pgd){712free(pgd->block_buf);713free(pgd);714}715return 0;716}717718/*************************************************************/719720721722