This forum uses cookies
This forum makes use of cookies to store your login information if you are registered, and your last visit if you are not. Cookies are small text documents stored on your computer; the cookies set by this forum can only be used on this website and pose no security risk. Cookies on this forum also track the specific topics you have read and when you last read them. Please confirm whether you accept or reject these cookies being set.

A cookie will be stored in your browser regardless of choice to prevent you being asked this question again. You will be able to change your cookie settings at any time using the link in the footer.

Thread Rating:
  • 1 Vote(s) - 5 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Savedata Encryption/Decryption
#1
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
Reply
#2
Great job, congratulations! Wink
Reply
#3
You are genius guys ;-) Congrats for all your fantastic work!
Reply
#4
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
Reply
#5
(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!
Reply
#6
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
CPU: Intel C2D E8500 @4.2 GHZ GPU: MSI Radeon 6870 Twin Frozr II 1024MB (920/1050)
RAM: 2x2GB Corsair Dominator DDR2-1066 5-5-5-15
Reply
#7
(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.
Funny thing, I spend more time on the forum instead of on emulators Tongue

Reply
#8
(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.
Reply
#9
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.
CPU: Intel C2D E8500 @4.2 GHZ GPU: MSI Radeon 6870 Twin Frozr II 1024MB (920/1050)
RAM: 2x2GB Corsair Dominator DDR2-1066 5-5-5-15
Reply
#10
(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
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)