From 641b78ab6765c223cf3ea96c2f46572cf0687b64 Mon Sep 17 00:00:00 2001 From: tpu Date: Sat, 20 Apr 2013 13:51:40 +0800 Subject: [PATCH] add DLC support --- Core/HLE/sceIo.cpp | 65 ++++++++++++++++++++++++----------- Core/HLE/scePspNpDrm_user.cpp | 21 ++++++----- ext/libkirk/amctrl.c | 40 ++++++++++++++++++--- ext/libkirk/amctrl.h | 1 + 4 files changed, 94 insertions(+), 33 deletions(-) diff --git a/Core/HLE/sceIo.cpp b/Core/HLE/sceIo.cpp index b8d6952cc4..c1a4c0063c 100644 --- a/Core/HLE/sceIo.cpp +++ b/Core/HLE/sceIo.cpp @@ -186,6 +186,7 @@ public: u32 openMode; u32 npdrm; + u32 pgd_offset; PGD_DESC *pgdInfo; }; @@ -735,6 +736,7 @@ FileNode *__IoOpen(const char* filename, int flags, int mode) { f->openMode = access; f->npdrm = (flags & O_NPDRM)? true: false; + f->pgd_offset = 0; return f; } @@ -1365,33 +1367,54 @@ int __IoIoctl(u32 id, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 out switch (cmd) { // Define decryption key (amctrl.prx DRM) - case 0x04100001: + case 0x04100001: { + u8 keybuf[16]; + u8 *key_ptr; + u8 pgd_header[0x90]; + u8 pgd_magic[4] = {0x00, 0x50, 0x47, 0x44}; + if (Memory::IsValidAddress(indataPtr) && inlen == 16) { - u8 keybuf[16]; - u8 pgd_header[0x90]; - u8 pgd_magic[4] = {0x00, 0x50, 0x47, 0x44}; - INFO_LOG(HLE, "Decrypting PGD DRM files"); memcpy(keybuf, Memory::GetPointer(indataPtr), 16); - pspFileSystem.ReadFile(f->handle, pgd_header, 0x90); - f->pgdInfo = pgd_open(pgd_header, 2, keybuf); - if(f->pgdInfo==NULL){ - ERROR_LOG(HLE, "Not a valid PGD file. Open as normal file."); - f->npdrm = false; - pspFileSystem.SeekFile(f->handle, (s32)0, FILEMOVE_BEGIN); - if(memcmp(pgd_header, pgd_magic, 4)==0){ - // File is PGD file, but key mismatch - return ERROR_PGD_INVALID_HEADER; - }else{ - // File is decrypted. - return 0; - } + key_ptr = keybuf; + }else{ + key_ptr = NULL; + } + + INFO_LOG(HLE, "Decrypting PGD DRM files"); + pspFileSystem.SeekFile(f->handle, (s32)f->pgd_offset, FILEMOVE_BEGIN); + pspFileSystem.ReadFile(f->handle, pgd_header, 0x90); + f->pgdInfo = pgd_open(pgd_header, 2, key_ptr); + if(f->pgdInfo==NULL){ + ERROR_LOG(HLE, "Not a valid PGD file. Open as normal file."); + f->npdrm = false; + pspFileSystem.SeekFile(f->handle, (s32)0, FILEMOVE_BEGIN); + if(memcmp(pgd_header, pgd_magic, 4)==0){ + // File is PGD file, but key mismatch + return ERROR_PGD_INVALID_HEADER; }else{ - // Everthing OK. - f->npdrm = true; + // File is decrypted. return 0; } + }else{ + // Everthing OK. + f->npdrm = true; + f->pgdInfo->data_offset += f->pgd_offset; + return 0; } break; + } + // Set PGD offset. Called from sceNpDrmEdataSetupKey + case 0x04100002: + f->pgd_offset = indataPtr; + break; + + // Get PGD data size. Called from sceNpDrmEdataGetDataSize + case 0x04100010: + if(f->pgdInfo) + return f->pgdInfo->data_size; + else + return (int)f->info.size; + break; // Get UMD sector size case 0x01020003: @@ -1443,7 +1466,7 @@ u32 sceIoIoctl(u32 id, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 ou { int result = __IoIoctl(id, cmd, indataPtr, inlen, outdataPtr, outlen); // Just a low estimate on timing. - return hleDelayResult(0, "io ctrl command", 100); + return hleDelayResult(result, "io ctrl command", 100); } u32 sceIoIoctlAsync(u32 id, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 outlen) diff --git a/Core/HLE/scePspNpDrm_user.cpp b/Core/HLE/scePspNpDrm_user.cpp index 384cefc2e4..4941df2efe 100644 --- a/Core/HLE/scePspNpDrm_user.cpp +++ b/Core/HLE/scePspNpDrm_user.cpp @@ -2,34 +2,39 @@ #include "HLE.h" +u32 sceIoIoctl(u32 id, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 outlen); + int sceNpDrmSetLicenseeKey(u32 npDrmKeyAddr) { - ERROR_LOG(HLE, "UNIMPL sceNpDrmSetLicenseeKey(%08x)", npDrmKeyAddr); + INFO_LOG(HLE, "call sceNpDrmSetLicenseeKey(%08x)", npDrmKeyAddr); return 0; } int sceNpDrmClearLicenseeKey() { - ERROR_LOG(HLE, "UNIMPL sceNpDrmClearLicenseeKey()"); + INFO_LOG(HLE, "call sceNpDrmClearLicenseeKey()"); return 0; } int sceNpDrmRenameCheck(const char *filename) { - ERROR_LOG(HLE, "UNIMPL sceNpDrmRenameCheck(%s)", filename); + INFO_LOG(HLE, "call sceNpDrmRenameCheck(%s)", filename); return 0; } int sceNpDrmEdataSetupKey(u32 edataFd) { - ERROR_LOG(HLE, "UNIMPL sceNpDrmEdataSetupKey %x", edataFd); - return 0; + INFO_LOG(HLE, "call sceNpDrmEdataSetupKey %x", edataFd); + /* set PGD offset */ + sceIoIoctl(edataFd, 0x04100002, 0x90, 0, 0, 0); + /* call PGD open */ + return sceIoIoctl(edataFd, 0x04100001, 0, 0, 0, 0); } int sceNpDrmEdataGetDataSize(u32 edataFd) { - ERROR_LOG(HLE, "UNIMPL sceNpDrmEdataGetDataSize %x", edataFd); - return 0; + INFO_LOG(HLE, "call sceNpDrmEdataGetDataSize %x", edataFd); + return sceIoIoctl(edataFd, 0x04100010, 0, 0, 0, 0); } int sceNpDrmOpen() @@ -67,4 +72,4 @@ void Register_sceNpDrm() RegisterModule("sceNpDrm", ARRAY_SIZE(sceNpDrm), sceNpDrm); RegisterModule("scePspNpDrm_user", ARRAY_SIZE(sceNpDrm), sceNpDrm); } - \ No newline at end of file + diff --git a/ext/libkirk/amctrl.c b/ext/libkirk/amctrl.c index c499e7cff8..189a3f0d34 100644 --- a/ext/libkirk/amctrl.c +++ b/ext/libkirk/amctrl.c @@ -334,6 +334,40 @@ int sceDrmBBMacFinal2(MAC_KEY *mkey, u8 *out, u8 *vkey) return retv; } +// get key from bbmac +int bbmac_getkey(MAC_KEY *mkey, u8 *bbmac, u8 *vkey) +{ + int i, retv, type, code; + u8 *kbuf, tmp[16], tmp1[16]; + + type = mkey->type; + retv = sceDrmBBMacFinal(mkey, tmp, NULL); + if(retv) + return retv; + + kbuf = kirk_buf+0x14; + + // decrypt bbmac + if(type==3){ + memcpy(kbuf, bbmac, 0x10); + kirk7(kirk_buf, 0x10, 0x63); + }else{ + memcpy(kirk_buf, bbmac, 0x10); + } + + memcpy(tmp1, kirk_buf, 16); + memcpy(kbuf, tmp1, 16); + + code = (type==2)? 0x3A : 0x38; + kirk7(kirk_buf, 0x10, code); + + for(i=0; i<0x10; i++){ + vkey[i] = tmp[i] ^ kirk_buf[i]; + } + + return 0; +} + /*************************************************************/ static int sub_1F8(u8 *buf, int size, u8 *key, int key_type) @@ -625,12 +659,10 @@ PGD_DESC *pgd_open(u8 *pgd_buf, int pgd_flag, u8 *pgd_vkey) memcpy(pgd->vkey, pgd_vkey, 16); } }else{ - //ERROR_LOG(HLE, "pgd_open: need key!\n"); - free(pgd); - return NULL; + // get vkey from MAC_70 + bbmac_getkey(&mkey, pgd_buf+0x70, pgd->vkey); } - // decrypt PGD_DESC sceDrmBBCipherInit(&ckey, pgd->cipher_type, 2, pgd_buf+0x10, pgd->vkey, 0); sceDrmBBCipherUpdate(&ckey, pgd_buf+0x30, 0x30); diff --git a/ext/libkirk/amctrl.h b/ext/libkirk/amctrl.h index 9a22ac9567..e4c9d04aaf 100644 --- a/ext/libkirk/amctrl.h +++ b/ext/libkirk/amctrl.h @@ -45,6 +45,7 @@ int sceDrmBBMacInit(MAC_KEY *mkey, int type); int sceDrmBBMacUpdate(MAC_KEY *mkey, u8 *buf, int size); int sceDrmBBMacFinal(MAC_KEY *mkey, u8 *buf, u8 *vkey); int sceDrmBBMacFinal2(MAC_KEY *mkey, u8 *out, u8 *vkey); +int bbmac_getkey(MAC_KEY *mkey, u8 *bbmac, u8 *vkey); // type: 1 use fixed key // 2 use fuse id