183 lines
4.5 KiB
C
183 lines
4.5 KiB
C
/*
|
|
* dnas.c -- Reverse engineering of iofilemgr_dnas.prx
|
|
* written by tpu.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "kirk_engine.h"
|
|
#include "crypto.h"
|
|
#include "psp_headers.h"
|
|
#include "amctrl.h"
|
|
|
|
/*************************************************************/
|
|
|
|
typedef struct {
|
|
unsigned __int8 key[16]; // 00: used to decrypt data content.
|
|
unsigned __int32 version; // 10: always 00
|
|
unsigned __int32 data_size; // 14
|
|
unsigned __int32 block_size; // 18
|
|
unsigned __int32 data_offset; // 1C
|
|
unsigned __int8 unk_20[16];
|
|
}PGD_DESC;
|
|
|
|
|
|
typedef struct {
|
|
PGD_DESC pgdesc;
|
|
unsigned __int32 key_index; // 0x30
|
|
unsigned __int8 pgd_key[16]; // 0x34
|
|
unsigned __int32 flag; // 0x44
|
|
unsigned __int32 flag_open; // 0x48
|
|
unsigned __int32 pgd_offset; // 0x4C
|
|
int seek_offset; // 0x50
|
|
unsigned __int32 data_offset; // 0x54
|
|
unsigned __int32 table_offset;// 0x58
|
|
unsigned __int32 unk_5c;
|
|
unsigned __int32 unk_60;
|
|
}PspIoHookParam;
|
|
|
|
|
|
unsigned __int8 dnas_key1A90[] = {0xED,0xE2,0x5D,0x2D,0xBB,0xF8,0x12,0xE5,0x3C,0x5C,0x59,0x32,0xFA,0xE3,0xE2,0x43};
|
|
unsigned __int8 dnas_key1AA0[] = {0x27,0x74,0xFB,0xEB,0xA4,0xA0, 1,0xD7,2,0x56,0x9E,0x33,0x8C,0x19,0x57,0x83};
|
|
|
|
__declspec(dllexport) int process_pgd(unsigned __int8 *pgd_buf, int pgd_size, int pgd_flag)
|
|
{
|
|
MAC_KEY mkey;
|
|
CIPHER_KEY ckey;
|
|
unsigned __int8 *fkey, vkey[16];
|
|
int key_index, mac_type, cipher_type, drm_type;
|
|
int retv, file_size, block_size, data_offset, table_size, align_size;
|
|
|
|
|
|
key_index = *(unsigned __int32*)(pgd_buf+4);
|
|
drm_type = *(unsigned __int32*)(pgd_buf+8);
|
|
|
|
if(drm_type==1){
|
|
mac_type = 1;
|
|
pgd_flag |= 4;
|
|
if(key_index>1){
|
|
mac_type = 3;
|
|
pgd_flag |= 8;
|
|
}
|
|
cipher_type = 1;
|
|
}else{
|
|
mac_type = 2;
|
|
cipher_type = 2;
|
|
}
|
|
|
|
// select fixed key
|
|
fkey = NULL;
|
|
if(pgd_flag&2)
|
|
fkey = dnas_key1A90;
|
|
if(pgd_flag&1)
|
|
fkey = dnas_key1AA0;
|
|
if(fkey==NULL){
|
|
printf("invalid pgd_flag! %08x\n", pgd_flag);
|
|
return -1;
|
|
}
|
|
|
|
// MAC_0x80 check
|
|
sceDrmBBMacInit(&mkey, mac_type);
|
|
sceDrmBBMacUpdate(&mkey, pgd_buf+0x00, 0x80);
|
|
retv = sceDrmBBMacFinal2(&mkey, pgd_buf+0x80, fkey);
|
|
if(retv){
|
|
printf("MAC_80 check failed!: %08x(%d)\n", retv, retv);
|
|
return -2;
|
|
}
|
|
|
|
// MAC_0x70
|
|
sceDrmBBMacInit(&mkey, mac_type);
|
|
sceDrmBBMacUpdate(&mkey, pgd_buf+0x00, 0x70);
|
|
bbmac_getkey(&mkey, pgd_buf+0x70, vkey);
|
|
hex_dump("Get version_key from MAC_70:", vkey, 16);
|
|
|
|
// decrypt PGD_DESC
|
|
sceDrmBBCipherInit(&ckey, cipher_type, 2, pgd_buf+0x10, vkey, 0);
|
|
sceDrmBBCipherUpdate(&ckey, pgd_buf+0x30, 0x30);
|
|
sceDrmBBCipherFinal(&ckey);
|
|
hex_dump("PGD header", pgd_buf, 0x90);
|
|
|
|
file_size = *(unsigned __int32*)(pgd_buf+0x44);
|
|
block_size = *(unsigned __int32*)(pgd_buf+0x48);
|
|
data_offset = *(unsigned __int32*)(pgd_buf+0x4c);
|
|
|
|
file_size = (file_size+15)&~15;
|
|
align_size = (file_size+block_size-1)&~(block_size-1);
|
|
table_size = align_size/block_size;
|
|
table_size *= 16;
|
|
|
|
if(file_size+table_size>pgd_size){
|
|
printf("invalid pgd data!\n");
|
|
return -3;
|
|
}
|
|
|
|
// table MAC check
|
|
sceDrmBBMacInit(&mkey, mac_type);
|
|
sceDrmBBMacUpdate(&mkey, pgd_buf+data_offset+file_size, table_size);
|
|
retv = sceDrmBBMacFinal(&mkey, pgd_buf+0x60, vkey);
|
|
if(retv){
|
|
printf("MAC_table check failed!: %08x(%d)\n", retv, retv);
|
|
return -4;
|
|
}
|
|
|
|
// decrypt data
|
|
sceDrmBBCipherInit(&ckey, cipher_type, 2, pgd_buf+0x30, vkey, 0);
|
|
sceDrmBBCipherUpdate(&ckey, pgd_buf+0x90, file_size);
|
|
sceDrmBBCipherFinal(&ckey);
|
|
hex_dump("PGD data", pgd_buf+0x90, (file_size>0x100)? 0x100 : file_size);
|
|
|
|
file_size = *(unsigned __int32*)(pgd_buf+0x44);
|
|
return file_size;
|
|
}
|
|
|
|
int decrypt_pgd(unsigned __int8 *pgd_buf, int pgd_size, int pgd_flag, unsigned __int8 *pgd_vkey);
|
|
|
|
__declspec(dllexport) int process_pgd_file(char *pgd_file)
|
|
{
|
|
unsigned __int8 *data_buf, *pgd_buf;
|
|
char fname[256];
|
|
int retv, data_size, pgd_size, pgd_flag;
|
|
|
|
data_buf = load_file(pgd_file, &data_size);
|
|
if(data_buf==NULL){
|
|
printf("Open input file <%s> error!\n", pgd_file);
|
|
return -1;
|
|
}
|
|
if(data_size<0x90){
|
|
free(data_buf);
|
|
return -1;
|
|
}
|
|
|
|
if(*(unsigned __int32*)(data_buf+0)==0x44475000){
|
|
pgd_buf = data_buf;
|
|
pgd_size = data_size;
|
|
}else if(*(unsigned __int32*)(data_buf+0x90)==0x44475000){
|
|
pgd_buf = data_buf+0x90;
|
|
pgd_size = data_size-0x90;
|
|
}else{
|
|
free(data_buf);
|
|
return -1;
|
|
}
|
|
printf("\nProcess %s ...\n", pgd_file);
|
|
|
|
// 0x40xxxxxx : 2
|
|
// 0x44xxxxxx : 1
|
|
// default as 2
|
|
pgd_flag = 2;
|
|
|
|
retv = decrypt_pgd(pgd_buf, pgd_size, pgd_flag, NULL);
|
|
if(retv>0){
|
|
sprintf(fname, "%s.decrypt", pgd_file);
|
|
write_file(fname, pgd_buf+0x90, retv);
|
|
printf("Save %s ...\n", fname);
|
|
}
|
|
|
|
free(data_buf);
|
|
return 0;
|
|
}
|
|
|
|
|
|
|