EmuNewz Network
Savedata Encryption/Decryption - Printable Version

+- EmuNewz Network (https://www.emunewz.net/forum)
+-- Forum: PSP Emulation (https://www.emunewz.net/forum/forumdisplay.php?fid=191)
+--- Forum: JPCSP Official Forum (https://www.emunewz.net/forum/forumdisplay.php?fid=51)
+---- Forum: svn trunk discussion (https://www.emunewz.net/forum/forumdisplay.php?fid=56)
+---- Thread: Savedata Encryption/Decryption (/showthread.php?tid=3673)

Pages: 1 2 3 4 5 6 7 8 9 10 11 12


Savedata Encryption/Decryption - Hykem - 02-16-2011

So, after a couple of weeks of absense on my side, I'm finally back to reveal my findings on the intrinsics of the module chnnlsv.prx, which is reponsible for handling savedata encryption/decryption in the PSP.
Thanks to all the rest of the dev's team, Darth1701 and BlackDaemon's help, I was finally able to fully reverse engineer this module and unterstand it's crypto algorithms, which were still unknown until today.

The purpose of this post is to offer and disclose a brief pseudo code shaped summary of my findings before commiting anything to JPCSP/PCSP.
Please remember that this post is solely for investigational purposes!

-----------------------------------------------------------------------------------
[CHNNLSV.PRX]:

- Structs:
SDCtx1 {
int mode;
int unk;
byte[16] buf;
}

SDCtx2 {
int mode;
byte[16] result;
byte[16] key;
int keylength
}

- Functions' prototypes:
sceSdSetIndex(SDCtx2 ctx, int encMode);
sceSdCreateList(SDCtx1 ctx, int encMode, int genMode, byte[] data, byte[] key);
sceSdRemoveValue(SDCtx2 ctx, byte[] data, int length);
sceSdGetLastIndex(SDCtx2 ctx, byte[] hash, byte[] key);
sceSdSetMember(SDCtx1 ctx, byte[] data, int length);
sceChnnlsv_21BE78B4(SDCtx1 ctx);

- Details:
-> sceSdSetIndex: This function is responsible for initializing ctx's params to 0 and set ctx.mode to encMode.
-> sceSdCreateList: This is the main key generating function. The param genMode can be 1 for encryption or 2 for decryption. In the first case, a random pseudo number is encrypted and appended to decrypted data and it will be used as encrypting key after being XORed with the param key (if specified). In decryption, the first 16-bytes of data represent this generated hash, and all that happens is the XORing with the param key (if specified) and subsequent saving of this key for further use.
-> sceSdRemoveValue: This function is used in hash generation. This only matters in encryption processes, and it's used to collect and generate a key from the main encrypted data.
-> sceSdGetLastIndex: This function is also used in hash generation. It's called to generate a hash based on the context collected by sceSdRemoveValue. The hashes processed by this function must be written to the SAVEDATA_PARAMS field of the existing PARAM.SFO file when encrypting data to validate it.
-> sceSdSetMember: This is the main encryption/decryption function. It works by generating a binary list using a part of the key obtained by sceSdCreateList and a few custom algorithmic steps. Depending on which encMode is specified, different calls to KIRK CMDs can be used and different private CHNNLSV SD keys are XORed with the obtained key before generating the list (check the keys section). The final step consists on decrypting with KIRK CMD7 this binary list, and the result will then be XORed with the encrypted/decrypted data giving a decrypted/encrypted output.
-> sceChnnlsv_21BE78B4: Just clears the ctx struct. Pretty much like a sceSdSetIndex but for SDCtx1 instead.

- SD Keys (located in the chnnlsv.prx's subsection sceChnnlsv_driver):
Code:
Key1 = {0x40, 0xE6, 0x53, 0x3F, 0x05, 0x11, 0x3A, 0x4E, 0xA1, 0x4B, 0xDA, 0xD6, 0x72, 0x7C, 0x53, 0x4C};
Key2 = {0xFA, 0xAA, 0x50, 0xEC, 0x2F, 0xDE, 0x54, 0x93, 0xAD, 0x14, 0xB2, 0xCE, 0xA5, 0x30, 0x05, 0xDF};
Key3 = {0x36, 0xA5, 0x3E, 0xAC, 0xC5, 0x26, 0x9E, 0xA3, 0x83, 0xD9, 0xEC, 0x25, 0x6C, 0x48, 0x48, 0x72};
Key4 = {0xD8, 0xC0, 0xB0, 0xF3, 0x3E, 0x6B, 0x76, 0x85, 0xFD, 0xFB, 0x4D, 0x7D, 0x45, 0x1E, 0x92, 0x03};
Key5 = {0xCB, 0x15, 0xF4, 0x07, 0xF9, 0x6A, 0x52, 0x3C, 0x04, 0xB9, 0xB2, 0xEE, 0x5C, 0x53, 0xFA, 0x86};
Key6 = {0x70, 0x44, 0xA3, 0xAE, 0xEF, 0x5D, 0xA5, 0xF2, 0x85, 0x7F, 0xF2, 0xD6, 0x94, 0xF5, 0x36, 0x3B};
Key7 = {0xEC, 0x6D, 0x29, 0x59, 0x26, 0x35, 0xA5, 0x7F, 0x97, 0x2A, 0x0D, 0xBC, 0xA3, 0x26, 0x33, 0x00};

Key3 and Key4 were the first encryption/decryption keys being used (up to firmware 2.5.2). Key6 and Key7 are the keys associated with the new mode being used since then.
Key2 and Key5 are used in hash generation and Key1 is still unknown.

-----------------------------------------------------------------------------------

Enjoy! Smile


RE: Savedata Encryption/Decryption - BlackDaemon - 02-16-2011

Great job, congratulations! Wink


RE: Savedata Encryption/Decryption - skyeyes83 - 02-17-2011

You are genius guys ;-) Congrats for all your fantastic work!


RE: Savedata Encryption/Decryption - Hykem - 02-17-2011

As of r1993, JPCSP now handles encrypted SAVEDATA. That means you can go grab those save files, for your games, with HP 999 and everything unlocked and what not. Tongue

Just check the new option under Options>Configuration>Crypto>"Handle SAVEDATA in crypto mode".
This forces JPCSP to exclusively handle encrypted data all the time. The reason behind this is because, unfortunately, there's no way to identify if we're dealing with plain data or encrypted data. The files have no header or flags, nor the savedata parameters specify anything about it. There are specific modes to load only encrypted data, but the applications are not forced to use them, since all modes can operate with encrypted data (chnnlsv.prx works separately from the utility module).

So, if you intend to play a game in JPCSP from the beginning to it's end, it's probably better to just keep this new option unchecked and work with plain data.
Then, if you find a save game you're interested in loading, turn the option on, add the save game to the ms0:/SAVEDATA folder and run the game.
Or, if you want to port your save state into your PSP, turn the option on, run the game, save, go to ms0:/SAVEDATA and the data stored there will now be encrypted and ready to be transfered. Wink


RE: Savedata Encryption/Decryption - oliox - 02-17-2011

(02-17-2011, 08:11 PM)Hykem Wrote: Or, if you want to port your save state into your PSP, turn the option on, run the game, save, go to ms0:/SAVEDATA and the data stored there will now be encrypted and ready to be transfered. Wink

wait if you turn the option on how will the emulator load your plain savedata?Huh

Nevertheless, congrats! keep up the good work!


RE: Savedata Encryption/Decryption - andutrache - 02-17-2011

am i the only one that cannot save in any game with the new option on?
I get a ugly :
java.lang.ArrayIndexOutOfBoundsException
at java.lang.System.arraycopy(Native Method)
at jpcsp.crypto.CryptoEngine.hleSdCreateList(CryptoEngine.java:1147)
at jpcsp.crypto.CryptoEngine.DecryptSavedata(CryptoEngine.java:1806)
at jpcsp.HLE.kernel.types.SceUtilitySavedataParam.loadEncryptedFile(SceU
tilitySavedataParam.java:495)
at jpcsp.HLE.kernel.types.SceUtilitySavedataParam.singleRead(SceUtilityS
avedataParam.java:373)
at jpcsp.HLE.modules150.sceUtility.hleUtilitySavedataDisplay(sceUtility.
java:1270)
at jpcsp.HLE.modules150.sceUtility.sceUtilitySavedataUpdate(sceUtility.j
ava:1415)
at jpcsp.HLE.modules150.sceUtility$17.execute(sceUtility.java:2017)
at jpcsp.HLE.modules.HLEModuleManager.handleSyscall(HLEModuleManager.jav
a:334)
at jpcsp.HLE.SyscallHandler.syscall(SyscallHandler.java:94)
at jpcsp.Allegrex.compiler.RuntimeContext.syscall(RuntimeContext.java:67
0)
at _S1_3_88F4488.s(_S1_3_88F4488.java:4)
at _S1_3_882C0F4.s(_S1_3_882C0F4.java:172)
at _S1_3_882C0F4.exec(_S1_3_882C0F4.java)
at jpcsp.Allegrex.compiler.RuntimeContext.jumpCall(RuntimeContext.java:1
16)
at jpcsp.Allegrex.compiler.RuntimeContext.call(RuntimeContext.java:195)
at _S1_3_887A870.s(_S1_3_887A870.java:44)
at _S1_3_887A5CC.s(_S1_3_887A5CC.java:24)
at _S1_3_8879AF4.s8879c84(_S1_3_8879AF4.java:532)
at _S1_3_8879AF4.s(_S1_3_8879AF4.java:400)
at _S1_3_8804F0C.s88050ec(_S1_3_8804F0C.java:484)
at _S1_3_8804F0C.s(_S1_3_8804F0C.java:480)
at _S1_3_887D000.s887d118(_S1_3_887D000.java:284)
at _S1_3_887D000.s(_S1_3_887D000.java:280)
at _S1_3_887D000.exec(_S1_3_887D000.java)
at jpcsp.Allegrex.compiler.RuntimeContext.runThread(RuntimeContext.java:
701)
at jpcsp.Allegrex.compiler.RuntimeThread.run(RuntimeThread.java:51)

whenever i try to save any game


RE: Savedata Encryption/Decryption - Kai3213 - 02-17-2011

(02-17-2011, 10:39 PM)oliox Wrote:
(02-17-2011, 08:11 PM)Hykem Wrote: Or, if you want to port your save state into your PSP, turn the option on, run the game, save, go to ms0:/SAVEDATA and the data stored there will now be encrypted and ready to be transfered. Wink

wait if you turn the option on how will the emulator load your plain savedata?Huh

Nevertheless, congrats! keep up the good work!

It doesn't, it's meant for your psp. Just turn off the option and save normally on jpcsp.


RE: Savedata Encryption/Decryption - Hykem - 02-18-2011

(02-17-2011, 10:52 PM)andutrache Wrote: am i the only one that cannot save in any game with the new option on?
I get a ugly :
java.lang.ArrayIndexOutOfBoundsException
at java.lang.System.arraycopy(Native Method)
at jpcsp.crypto.CryptoEngine.hleSdCreateList(CryptoEngine.java:1147)
at jpcsp.crypto.CryptoEngine.DecryptSavedata(CryptoEngine.java:1806)
at jpcsp.HLE.kernel.types.SceUtilitySavedataParam.loadEncryptedFile(SceU
tilitySavedataParam.java:495)
at jpcsp.HLE.kernel.types.SceUtilitySavedataParam.singleRead(SceUtilityS
avedataParam.java:373)
at jpcsp.HLE.modules150.sceUtility.hleUtilitySavedataDisplay(sceUtility.
java:1270)
at jpcsp.HLE.modules150.sceUtility.sceUtilitySavedataUpdate(sceUtility.j
ava:1415)
at jpcsp.HLE.modules150.sceUtility$17.execute(sceUtility.java:2017)
at jpcsp.HLE.modules.HLEModuleManager.handleSyscall(HLEModuleManager.jav
a:334)
at jpcsp.HLE.SyscallHandler.syscall(SyscallHandler.java:94)
at jpcsp.Allegrex.compiler.RuntimeContext.syscall(RuntimeContext.java:67
0)
at _S1_3_88F4488.s(_S1_3_88F4488.java:4)
at _S1_3_882C0F4.s(_S1_3_882C0F4.java:172)
at _S1_3_882C0F4.exec(_S1_3_882C0F4.java)
at jpcsp.Allegrex.compiler.RuntimeContext.jumpCall(RuntimeContext.java:1
16)
at jpcsp.Allegrex.compiler.RuntimeContext.call(RuntimeContext.java:195)
at _S1_3_887A870.s(_S1_3_887A870.java:44)
at _S1_3_887A5CC.s(_S1_3_887A5CC.java:24)
at _S1_3_8879AF4.s8879c84(_S1_3_8879AF4.java:532)
at _S1_3_8879AF4.s(_S1_3_8879AF4.java:400)
at _S1_3_8804F0C.s88050ec(_S1_3_8804F0C.java:484)
at _S1_3_8804F0C.s(_S1_3_8804F0C.java:480)
at _S1_3_887D000.s887d118(_S1_3_887D000.java:284)
at _S1_3_887D000.s(_S1_3_887D000.java:280)
at _S1_3_887D000.exec(_S1_3_887D000.java)
at jpcsp.Allegrex.compiler.RuntimeContext.runThread(RuntimeContext.java:
701)
at jpcsp.Allegrex.compiler.RuntimeThread.run(RuntimeThread.java:51)

whenever i try to save any game

Do you happen to have any previous plain data for those games in ms0:/SAVEDATA folder? In those circunstances you will be decrypting decrypted data, which will end up in an error.
The error you posted is related to a System.arraycopy ocurring during DecryptSavedata, so that's when trying to load savedata, not saving.


RE: Savedata Encryption/Decryption - andutrache - 02-18-2011

no i deleted all my saves, then enabled the option, if i download a P3P save from the internet i can load it fine but when i try to save i get the mentioned errors and a dialog box :
Game data has not been saved
Abort save? Yes / No

I also get a 0 KB savefile on the slot i try to save to.


RE: Savedata Encryption/Decryption - Hykem - 02-18-2011

(02-18-2011, 05:22 PM)andutrache Wrote: no i deleted all my saves, then enabled the option, if i download a P3P save from the internet i can load it fine but when i try to save i get the mentioned errors and a dialog box :
Game data has not been saved
Abort save? Yes / No

I also get a 0 KB savefile on the slot i try to save to.

Hmm...
That's really odd, since, as you can see, in this line:
Code:
at jpcsp.crypto.CryptoEngine.DecryptSavedata(CryptoEngine.java:1806)
DecryptSavedata is being called, so I'm guessing the game you're trying to save with, is attempting to load the data first, and only then is going to save.
This is common in recent games (6.00 firmware and up) that use multi call save modes.

Again, this can be seen in the following line:
Code:
at jpcsp.HLE.kernel.types.SceUtilitySavedataParam.singleRead(SceUtilitySavedataParam.java:373)
Looks like this game is using SceUtilitySavedataParam.singleRead which belongs to SAVEDATA MODE 15.

Could you please list some of the games you've tried testing this feature with? There's a good chance that it may be an additional protection mechanism or an additional checking layer.
Thanks! Smile