Skip to content
Permalink
Browse files

Merge pull request #12559 from DaveeFTW/prxdecrypt

Expand PRX decryption capabilities
  • Loading branch information
hrydgard committed Jan 11, 2020
2 parents 6d8ddb7 + 4c9e7b7 commit 42bfcc7fa6686d17db382bb6854d308f18c39c79

Large diffs are not rendered by default.

@@ -20,8 +20,6 @@
#include "Common/Common.h"
#include "Common/CommonTypes.h"

#define MISSING_KEY -10

#ifdef _MSC_VER
#pragma pack(push, 1)
#endif
@@ -66,5 +64,4 @@ typedef struct
#pragma pack(pop)
#endif

int pspDecryptPRX(const u8 *inbuf, u8 *outbuf, u32 size);

int pspDecryptPRX(const u8 *inbuf, u8 *outbuf, u32 size, const u8 *seed = nullptr);
@@ -19,6 +19,8 @@
#include <algorithm>
#include <set>

#include "zlib.h"

#include "base/stringutil.h"
#include "Common/ChunkFile.h"
#include "Common/FileUtil.h"
@@ -1060,6 +1062,32 @@ static bool KernelImportModuleFuncs(Module *module, u32 *firstImportStubAddr, bo
return true;
}

static int gzipDecompress(u8 *OutBuffer, int OutBufferLength, u8 *InBuffer) {
int err;
uLong crc;
z_stream stream;
u8 *outBufferPtr;

outBufferPtr = OutBuffer;
stream.next_in = InBuffer;
stream.avail_in = (uInt)OutBufferLength;
stream.next_out = outBufferPtr;
stream.avail_out = (uInt)OutBufferLength;
stream.zalloc = (alloc_func)0;
stream.zfree = (free_func)0;
err = inflateInit2(&stream, 16+MAX_WBITS);
if (err != Z_OK) {
return -1;
}
err = inflate(&stream, Z_FINISH);
if (err != Z_STREAM_END) {
inflateEnd(&stream);
return -2;
}
inflateEnd(&stream);
return stream.total_out;
}

static Module *__KernelLoadELFFromPtr(const u8 *ptr, size_t elfSize, u32 loadAddress, bool fromTop, std::string *error_string, u32 *magic, u32 &error) {
Module *module = new Module;
kernelObjects.Create(module);
@@ -1097,6 +1125,7 @@ static Module *__KernelLoadELFFromPtr(const u8 *ptr, size_t elfSize, u32 loadAdd
}

const u8 *in = ptr;
const auto isGzip = head->comp_attribute & 1;
// Kind of odd.
u32 size = head->psp_size;
if (size > elfSize) {
@@ -1105,11 +1134,12 @@ static Module *__KernelLoadELFFromPtr(const u8 *ptr, size_t elfSize, u32 loadAdd
kernelObjects.Destroy<Module>(module->GetUID());
return nullptr;
}
newptr = new u8[std::max(head->elf_size, head->psp_size)];
const auto maxElfSize = std::max(head->elf_size, head->psp_size);
newptr = new u8[maxElfSize];
ptr = newptr;
magicPtr = (u32_le *)ptr;
int ret = pspDecryptPRX(in, (u8*)ptr, head->psp_size);
if (ret == MISSING_KEY) {
if (reportedModule) {
// This should happen for all "kernel" modules.
*error_string = "Missing key";
delete [] newptr;
@@ -1150,6 +1180,15 @@ static Module *__KernelLoadELFFromPtr(const u8 *ptr, size_t elfSize, u32 loadAdd
// TODO: Is this right?
module->nm.bss_size = head->bss_size;

// decompress if required
if (isGzip)
{
auto temp = new u8[ret];
memcpy(temp, ptr, ret);
gzipDecompress((u8 *)ptr, maxElfSize, temp);
delete[] temp;
}

// If we've made it this far, it should be safe to dump.
if (g_Config.bDumpDecryptedEboot) {
INFO_LOG(SCEMODULE, "Dumping decrypted EBOOT.BIN to file.");
@@ -20,6 +20,7 @@

#include "Core/MemMap.h"
#include "Core/System.h"
#include "Core/ELF/PrxDecrypter.h"
#include "Core/FileSystems/MetaFileSystem.h"
#include "Core/HLE/scePauth.h"
#include "Core/HLE/HLE.h"
@@ -28,100 +29,36 @@

static int scePauth_F7AA47F6(u32 srcPtr, int srcLength, u32 destLengthPtr, u32 workArea)
{
u8 *src, *key;
u32 crc;
char name[256];
std::string hostPath;
FILE *fp;
int size;

INFO_LOG(HLE, "scePauth_F7AA47F6(%08x, %08x, %08x, %08x)", srcPtr, srcLength, destLengthPtr, workArea);

sprintf(name, "ms0:/PAUTH");
pspFileSystem.GetHostPath(std::string(name), hostPath);

src = (u8*)Memory::GetPointer(srcPtr);
key = (u8*)Memory::GetPointer(workArea);
crc = crc32(0, src, srcLength);

sprintf(name, "%s/pauth_%08x.bin.decrypt", hostPath.c_str(), crc);
fp = File::OpenCFile(name, "rb");
if (fp){
fseek(fp, 0, SEEK_END);
size = ftell(fp);
fseek(fp, 0, SEEK_SET);
fread(src, 1, size, fp);
fclose(fp);
Memory::Write_U32(size, destLengthPtr);
INFO_LOG(HLE, "Read from decrypted file %s", name);
return 0;
}

pspFileSystem.MkDir("ms0:/PAUTH");

sprintf(name, "%s/pauth_%08x.bin", hostPath.c_str(), crc);
ERROR_LOG(HLE, "No decrypted file found! save as %s", name);
auto src = Memory::GetPointer(srcPtr);
auto key = Memory::GetPointer(workArea);

fp = File::OpenCFile(name, "wb");
fwrite(src, 1, srcLength, fp);
fclose(fp);
const auto decryptResult = pspDecryptPRX(src, src, srcLength, key);

sprintf(name, "%s/pauth_%08x.key", hostPath.c_str(), crc);
fp = File::OpenCFile(name, "wb");
fwrite(key, 1, 16, fp);
fclose(fp);
if (decryptResult < 0)
{
ERROR_LOG(HLE, "Pauth decryption failed 0x%08X", decryptResult);
return decryptResult;
}

// We failed decrypting and dumped encrypted files, some games like Idolmaster
// use this to check for firmware version, so let's still return no problem.
Memory::Write_U32(decryptResult, destLengthPtr);
return 0;
}

static int scePauth_98B83B5D(u32 srcPtr, int srcLength, u32 destLengthPtr, u32 workArea)
{
u8 *src, *key;
u32 crc;
char name[256];
std::string hostPath;
FILE *fp;
int size;

INFO_LOG(HLE, "scePauth_98B83B5D(%08x, %08x, %08x, %08x)", srcPtr, srcLength, destLengthPtr, workArea);

sprintf(name, "ms0:/PAUTH");
pspFileSystem.GetHostPath(std::string(name), hostPath);

src = (u8*)Memory::GetPointer(srcPtr);
key = (u8*)Memory::GetPointer(workArea);
crc = crc32(0, src, srcLength);

sprintf(name, "%s/pauth_%08x.bin.decrypt", hostPath.c_str(), crc);
fp = File::OpenCFile(name, "rb");
if (fp){
fseek(fp, 0, SEEK_END);
size = ftell(fp);
fseek(fp, 0, SEEK_SET);
fread(src, 1, size, fp);
fclose(fp);
Memory::Write_U32(size, destLengthPtr);
INFO_LOG(HLE, "Read from decrypted file %s", name);
return 0;
}
auto src = Memory::GetPointer(srcPtr);
auto key = Memory::GetPointer(workArea);

pspFileSystem.MkDir("ms0:/PAUTH");
const auto decryptResult = pspDecryptPRX(src, src, srcLength, key);

sprintf(name, "%s/pauth_%08x.bin", hostPath.c_str(), crc);
ERROR_LOG(HLE, "No decrypted file found! save as %s", name);

fp = File::OpenCFile(name, "wb");
fwrite(src, 1, srcLength, fp);
fclose(fp);

sprintf(name, "%s/pauth_%08x.key", hostPath.c_str(), crc);
fp = File::OpenCFile(name, "wb");
fwrite(key, 1, 16, fp);
fclose(fp);
if (decryptResult < 0)
{
ERROR_LOG(HLE, "Pauth decryption failed 0x%08X", decryptResult);
return decryptResult;
}

return -1;
Memory::Write_U32(decryptResult, destLengthPtr);
return 0;
}

const HLEFunction scePauth[] = {
@@ -1304,7 +1304,7 @@ void xor_128(const unsigned char *a, const unsigned char *b, unsigned char *out)
}

//No IV support!
void AES_cbc_encrypt(AES_ctx *ctx, u8 *src, u8 *dst, int size)
void AES_cbc_encrypt(AES_ctx *ctx, const u8 *src, u8 *dst, int size)
{
u8 block_buff[16];

@@ -1325,7 +1325,7 @@ void AES_cbc_encrypt(AES_ctx *ctx, u8 *src, u8 *dst, int size)
}
}

void AES_cbc_decrypt(AES_ctx *ctx, u8 *src, u8 *dst, int size)
void AES_cbc_decrypt(AES_ctx *ctx, const u8 *src, u8 *dst, int size)
{
u8 block_buff[16];
u8 block_buff_previous[16];
@@ -40,8 +40,8 @@ void rijndael_encrypt(rijndael_ctx *, const u8 *, u8 *);
int AES_set_key(AES_ctx *ctx, const u8 *key, int bits);
void AES_encrypt(AES_ctx *ctx, const u8 *src, u8 *dst);
void AES_decrypt(AES_ctx *ctx, const u8 *src, u8 *dst);
void AES_cbc_encrypt(AES_ctx *ctx, u8 *src, u8 *dst, int size);
void AES_cbc_decrypt(AES_ctx *ctx, u8 *src, u8 *dst, int size);
void AES_cbc_encrypt(AES_ctx *ctx, const u8 *src, u8 *dst, int size);
void AES_cbc_decrypt(AES_ctx *ctx, const u8 *src, u8 *dst, int size);
void AES_CMAC(AES_ctx *ctx, unsigned char *input, int length, unsigned char *mac);

int rijndaelKeySetupEnc(unsigned int [], const unsigned char [], int);
@@ -30,7 +30,7 @@ static u8 kirk_buf[0x0814]; // 1DC0 1DD4

/*************************************************************/

static int kirk4(u8 *buf, int size, int type)
static int do_kirk4(u8 *buf, int size, int type)
{
int retv;
u32 *header = (u32*)buf;
@@ -49,7 +49,7 @@ static int kirk4(u8 *buf, int size, int type)
return 0;
}

static int kirk7(u8 *buf, int size, int type)
static int do_kirk7(u8 *buf, int size, int type)
{
int retv;
u32 *header = (u32*)buf;
@@ -126,7 +126,7 @@ static int sub_158(u8 *buf, int size, u8 *key, int key_type)
buf[0x14+i] ^= key[i];
}

retv = kirk4(buf, size, key_type);
retv = do_kirk4(buf, size, key_type);
if(retv)
return retv;

@@ -213,7 +213,7 @@ int sceDrmBBMacFinal(MAC_KEY *mkey, u8 *buf, u8 *vkey)
kbuf = kirk_buf+0x14;

memset(kbuf, 0, 16);
retv = kirk4(kirk_buf, 16, code);
retv = do_kirk4(kirk_buf, 16, code);
if(retv)
goto _exit;
memcpy(tmp, kbuf, 16);
@@ -277,7 +277,7 @@ int sceDrmBBMacFinal(MAC_KEY *mkey, u8 *buf, u8 *vkey)
if(retv)
goto _exit;

retv = kirk4(kirk_buf, 0x10, code);
retv = do_kirk4(kirk_buf, 0x10, code);
if(retv)
goto _exit;

@@ -290,7 +290,7 @@ int sceDrmBBMacFinal(MAC_KEY *mkey, u8 *buf, u8 *vkey)
}
memcpy(kbuf, tmp1, 16);

retv = kirk4(kirk_buf, 0x10, code);
retv = do_kirk4(kirk_buf, 0x10, code);
if(retv)
goto _exit;

@@ -325,7 +325,7 @@ int sceDrmBBMacFinal2(MAC_KEY *mkey, u8 *out, u8 *vkey)
// decrypt bbmac
if(type==3){
memcpy(kbuf, out, 0x10);
kirk7(kirk_buf, 0x10, 0x63);
do_kirk7(kirk_buf, 0x10, 0x63);
}else{
memcpy(kirk_buf, out, 0x10);
}
@@ -357,7 +357,7 @@ int bbmac_getkey(MAC_KEY *mkey, u8 *bbmac, u8 *vkey)
// decrypt bbmac
if(type==3){
memcpy(kbuf, bbmac, 0x10);
kirk7(kirk_buf, 0x10, 0x63);
do_kirk7(kirk_buf, 0x10, 0x63);
}else{
memcpy(kirk_buf, bbmac, 0x10);
}
@@ -366,7 +366,7 @@ int bbmac_getkey(MAC_KEY *mkey, u8 *bbmac, u8 *vkey)
memcpy(kbuf, tmp1, 16);

code = (type==2)? 0x3A : 0x38;
kirk7(kirk_buf, 0x10, code);
do_kirk7(kirk_buf, 0x10, code);

for(i=0; i<0x10; i++){
vkey[i] = tmp[i] ^ kirk_buf[i];
@@ -385,7 +385,7 @@ static int sub_1F8(u8 *buf, int size, u8 *key, int key_type)
// copy last 16 bytes to tmp
memcpy(tmp, buf+size+0x14-16, 16);

retv = kirk7(buf, size, key_type);
retv = do_kirk7(buf, size, key_type);
if(retv)
return retv;

@@ -414,7 +414,7 @@ static int sub_428(u8 *kbuf, u8 *dbuf, int size, CIPHER_KEY *ckey)
if(ckey->type==2)
retv = kirk8(kbuf, 16);
else
retv = kirk7(kbuf, 16, 0x39);
retv = do_kirk7(kbuf, 16, 0x39);
if(retv)
return retv;

@@ -491,7 +491,7 @@ int sceDrmBBCipherInit(CIPHER_KEY *ckey, int type, int mode, u8 *header_key, u8
for(i=0; i<16; i++){
kbuf[i] ^= loc_1CE4[i];
}
retv = kirk4(kirk_buf, 0x10, 0x39);
retv = do_kirk4(kirk_buf, 0x10, 0x39);
for(i=0; i<16; i++){
kbuf[i] ^= loc_1CF4[i];
}

0 comments on commit 42bfcc7

Please sign in to comment.
You can’t perform that action at this time.