From ee60eb78ff7b7682395d5a799bf19ede1ff36ad3 Mon Sep 17 00:00:00 2001 From: rafa_99 Date: Sun, 1 Sep 2019 14:22:25 +0000 Subject: Pushed stock tools and folder structure --- Compatibility.pdf | Bin 0 -> 335742 bytes input/.placeholder | 1 + output/.placeholder | 1 + tools/1/MSVBVM50.DLL | Bin 0 -> 1355776 bytes tools/1/PS3_Generate_LIC.DAT.exe | Bin 0 -> 74752 bytes tools/2/CFW2OFW_Helper.exe | Bin 0 -> 36864 bytes tools/2/EmList.json | 1 + tools/2/make_npdata.exe | Bin 0 -> 26112 bytes tools/3/do.bat | 84 + tools/3/makepkg1.exe | Bin 0 -> 608256 bytes tools/3/makepkg2.exe | Bin 0 -> 608256 bytes tools/4/input/act_dat/.gitignore | 2 + tools/4/input/idps_hex/.gitignore | 1 + tools/4/input/pkgs/.gitignore | 2 + tools/4/input/raps/.gitignore | 2 + tools/4/output/pkgs/.gitignore | 2 + tools/4/output/temp/.gitignore | 2 + tools/4/resign_linux.sh | 325 ++++ tools/4/resign_mac.sh | 315 ++++ tools/4/resign_windows.bat | 152 ++ tools/4/source/pre-compiled/linux/.gitignore | 1 + tools/4/source/pre-compiled/windows/cygwin1.dll | Bin 0 -> 3002325 bytes .../windows/ps3xploit_rifgen_edatresign.exe | Bin 0 -> 1422164 bytes tools/4/source/src/Makefile | 67 + tools/4/source/src/Makefile_macOS | 67 + tools/4/source/src/aes.c | 967 +++++++++++ tools/4/source/src/aes.h | 159 ++ tools/4/source/src/aes_omac.cpp | 55 + tools/4/source/src/aes_omac.h | 10 + tools/4/source/src/main.cpp | 1782 ++++++++++++++++++++ tools/4/source/src/pkg2zip_aes.c | 560 ++++++ tools/4/source/src/pkg2zip_aes.h | 29 + tools/4/source/src/pkg2zip_aes_x86.c | 206 +++ tools/4/source/src/pkg2zip_aes_x86.h | 21 + tools/4/source/src/pkg2zip_utils.h | 118 ++ tools/4/source/src/sha1.c | 399 +++++ tools/4/source/src/sha1.h | 133 ++ tools/4/source/src/types.h | 63 + tools/4/source/src/util.cpp | 522 ++++++ tools/4/source/src/util.h | 84 + tools/4/source/tools/ps3py/LICENSE | 19 + tools/4/source/tools/ps3py/crypt.c | 126 ++ tools/4/source/tools/ps3py/pkg.py | 845 ++++++++++ tools/4/source/tools/ps3py/setup.py | 8 + tools/4/source/tools/ps3py_exe/pkg_exdata.exe | Bin 0 -> 3459258 bytes 45 files changed, 7131 insertions(+) create mode 100644 Compatibility.pdf create mode 100644 input/.placeholder create mode 100644 output/.placeholder create mode 100644 tools/1/MSVBVM50.DLL create mode 100644 tools/1/PS3_Generate_LIC.DAT.exe create mode 100644 tools/2/CFW2OFW_Helper.exe create mode 100644 tools/2/EmList.json create mode 100644 tools/2/make_npdata.exe create mode 100644 tools/3/do.bat create mode 100644 tools/3/makepkg1.exe create mode 100644 tools/3/makepkg2.exe create mode 100644 tools/4/input/act_dat/.gitignore create mode 100644 tools/4/input/idps_hex/.gitignore create mode 100644 tools/4/input/pkgs/.gitignore create mode 100644 tools/4/input/raps/.gitignore create mode 100644 tools/4/output/pkgs/.gitignore create mode 100644 tools/4/output/temp/.gitignore create mode 100644 tools/4/resign_linux.sh create mode 100644 tools/4/resign_mac.sh create mode 100755 tools/4/resign_windows.bat create mode 100644 tools/4/source/pre-compiled/linux/.gitignore create mode 100644 tools/4/source/pre-compiled/windows/cygwin1.dll create mode 100644 tools/4/source/pre-compiled/windows/ps3xploit_rifgen_edatresign.exe create mode 100644 tools/4/source/src/Makefile create mode 100644 tools/4/source/src/Makefile_macOS create mode 100644 tools/4/source/src/aes.c create mode 100644 tools/4/source/src/aes.h create mode 100644 tools/4/source/src/aes_omac.cpp create mode 100644 tools/4/source/src/aes_omac.h create mode 100644 tools/4/source/src/main.cpp create mode 100644 tools/4/source/src/pkg2zip_aes.c create mode 100644 tools/4/source/src/pkg2zip_aes.h create mode 100644 tools/4/source/src/pkg2zip_aes_x86.c create mode 100644 tools/4/source/src/pkg2zip_aes_x86.h create mode 100644 tools/4/source/src/pkg2zip_utils.h create mode 100644 tools/4/source/src/sha1.c create mode 100644 tools/4/source/src/sha1.h create mode 100644 tools/4/source/src/types.h create mode 100644 tools/4/source/src/util.cpp create mode 100644 tools/4/source/src/util.h create mode 100644 tools/4/source/tools/ps3py/LICENSE create mode 100755 tools/4/source/tools/ps3py/crypt.c create mode 100755 tools/4/source/tools/ps3py/pkg.py create mode 100755 tools/4/source/tools/ps3py/setup.py create mode 100644 tools/4/source/tools/ps3py_exe/pkg_exdata.exe diff --git a/Compatibility.pdf b/Compatibility.pdf new file mode 100644 index 0000000..9b3b50a Binary files /dev/null and b/Compatibility.pdf differ diff --git a/input/.placeholder b/input/.placeholder new file mode 100644 index 0000000..26ef763 --- /dev/null +++ b/input/.placeholder @@ -0,0 +1 @@ +Ignore this file diff --git a/output/.placeholder b/output/.placeholder new file mode 100644 index 0000000..26ef763 --- /dev/null +++ b/output/.placeholder @@ -0,0 +1 @@ +Ignore this file diff --git a/tools/1/MSVBVM50.DLL b/tools/1/MSVBVM50.DLL new file mode 100644 index 0000000..772e492 Binary files /dev/null and b/tools/1/MSVBVM50.DLL differ diff --git a/tools/1/PS3_Generate_LIC.DAT.exe b/tools/1/PS3_Generate_LIC.DAT.exe new file mode 100644 index 0000000..1028d1f Binary files /dev/null and b/tools/1/PS3_Generate_LIC.DAT.exe differ diff --git a/tools/2/CFW2OFW_Helper.exe b/tools/2/CFW2OFW_Helper.exe new file mode 100644 index 0000000..61c9891 Binary files /dev/null and b/tools/2/CFW2OFW_Helper.exe differ diff --git a/tools/2/EmList.json b/tools/2/EmList.json new file mode 100644 index 0000000..7a69d58 --- /dev/null +++ b/tools/2/EmList.json @@ -0,0 +1 @@ +[{"titleIds":["BLES01697"],"works":0,"note":"Black screen after intro. [CFW2OFW Helper v8] [PS3GameConvert_V0.91] [Data Install] [SPRX]"},{"titleIds":["BLUS31478"],"works":1,"note":"Works without patch."},{"titleIds":["BLUS30187"],"works":0,"note":"Game has one patch but doesn't contain EBOOT.BIN. UPDATE: Tested with BLJM60066 EBOOT and multiple variations of file structures."},{"titleIds":["BLES01763"],"works":1,"note":"Install Game Data before DTU. Creates \"/game/BLES01767/\" directory."},{"titleIds":["BLES02143"],"works":1,"note":"You must pre-install game data before DTU."},{"titleIds":["BLUS31207"],"works":2,"note":"You must pre-install game data before DTU."},{"titleIds":["BCES01123","NPEA90127","BCUS98298"],"works":2,"note":"BCUS98298 - Requires Demo EBOOT, Edit PARAM.SFO Category from DG Disc Game (blueray) to HG Harddrive Game, Game Conversion not required."},{"titleIds":["BLUS30629"],"works":2,"note":"Copy & replace all 42 .SPRX files located in USRDIR/BINARIES/PS3/XJOB/SHIPPING."},{"titleIds":["BLUS30386"],"works":1,"note":"BD contains INSDAT (update) & PKGDIR (DLC). You will need to manually extract all of them to play the DLC quests."},{"titleIds":["BLUS31270"],"works":2,"note":"Create a BLUS31270 folder and copy USRDIR from the full game directory. Use the game converter on it, and then navigate to NPUB31270/USRDIR and delete everything except EBOOT.bin. Copy all of the contents of the converted BLUS31270 into the BLUS31270 folder you had created, and overwrite all. Copy both your BLUS31270 and NPUB31270 to your OFW PS3."},{"titleIds":["BLES00148"],"works":0,"note":"Infinite Loading / Black Screen / Stuck At Confirm Screen using several different methods."},{"titleIds":["BLES00683"],"works":2,"note":"Copy all Disc files, except EBOOT.BIN, default.self, and default_mp.self from \"/USRDIR/*\" to update folder \"BLES00683/USRDIR/*\". Delete all converted files from \"NPEB00683/USRDIR/*\" except EBOOT.BIN from update. Copy default.self and default_mp.self from Disc to \"NPEB00683/USRDIR/\". NOTE: the game does not need converted if you manually copy the needed files from PS3_GAME folder, excluding USRDIR."},{"titleIds":["BLES01432"],"works":2,"note":"Move all Disc files (original files before converting) from USRDIR except EBOOT.BIN, default.self, and default_mp.self to update folder BLXXYYYYY/USRDIR/* then convert your game (USRDIR only contain EBOOT.BIN, default.self, and default_mp.self files)"},{"titleIds":["BLES00404"],"works":2,"note":"The game with the patch and the modified PARAM.SFO must be thrown to another folder, for example BLES00404GAME, as well as the patch separately unchanged in the native folder (BLES00404)."},{"titleIds":["BLUS30428"],"works":2,"note":"Use EBOOT from BLJM60215 update. Use NPJB60215 as conversion directory. If using CFW2OFW tool, change TitleID in PARAM.SFO to BLJM60215 and create new LIC.DAT before conversion. Install Game Data before DTU. Creates \"/game/BLJM60215DATA/\" directory. Buttons will be in Japanese format (X/O swapped) and some text will also be in Japanese (mostly English) because of EBOOT."},{"titleIds":["BLES01765"],"works":2,"note":"Fix \"creating save data\" loop: Convert game using ps3gameconvert or CFW2OFW Helper"},{"titleIds":["BLES00723"],"works":0,"note":"Black screen after the Intro Logo's appear. [PS3GameConvert_V0.91]"},{"titleIds":["BLUS30790"],"works":1,"note":"Use PS3GameConvert_v0.91 if you encounter error 8001003E."},{"titleIds":["BLJM61258"],"works":1,"note":"Use PS3GameConvert_v0.91 if you encounter graphical errors. JP games contains english language."},{"titleIds":["BLES00948"],"works":1,"note":"Use PS3GameConvert_v0.91 if you get stuck at the red logo screen."},{"titleIds":["BLUS30763"],"works":2,"note":"Use PS3GameConvert_v0.91 to avoid getting the game stuck at the red logo screen. Pre-install game data before DTU."},{"titleIds":["BLUS31396"],"works":2,"note":"Use EBOOT from BLJM61157 Update. Change TitleID in PARAM.SFO to BLJM61157 and create new LIC.DAT before conversion."},{"titleIds":["BLES00932"],"works":2,"note":"Use EBOOT from BCAS20071 update. Use NPHA20071 as conversion directory. If using CFW2OFW tool, change TitleID in PARAM.SFO to BCAS20071 and create new LIC.DAT before conversion."},{"titleIds":["BLES01698","BLUS30723"],"works":0,"note":"Using default conversion causes freezing at initial auto-save. Replacing \"/USRDIR/BINARIES/NTJOBCODE/PS3/SUBMISSION/NTJOBCODE.PPU.SPRX\" from disc causes black screen. [Manual] [CFW2OFW Helper v8]"},{"titleIds":["BLES01287"],"works":1,"note":"Install Game Data Before DTU. Creates \"/game/BLES01287INSTALL/\" directory."},{"titleIds":["BLES00452"],"works":1,"note":"Don't add DLC or you will encounter an error during trophy install making the game unplayable."},{"titleIds":["BLUS30977"],"works":1,"note":"Run game to generate dev_hdd0/game/BLUS30977_HDDCACHE/ directory before DTU."},{"titleIds":["BLES02064"],"works":1,"note":"Run game to generate dev_hdd0/game/BLES02064_HDDCACHE/ directory before DTU."},{"titleIds":["BLUS30645"],"works":2,"note":"Install Game Data From Disc Before DTU. Creates \"/game/BLUS30645INSTALL/\" directory."},{"titleIds":["BLJM61090"],"works":2,"note":"Install Game Data from Disc Before DTU. Creates \"/game/NPJB00454/\" directory."},{"titleIds":["BLES01138"],"works":2,"note":"Install Game Data Before DTU. Also renamed converted directory to NPEA01138 to not conflict with Worms Ultimate Mayhem NPEB01138."},{"titleIds":["BLES02011","BLUS31420"],"works":2,"note":"Delete \"patch_sound_english.dat\" in patch folder."},{"titleIds":["NPUA80001"],"works":1,"note":"Free on PSN."},{"titleIds":["BLES02080"],"works":2,"note":"Install Game Data from Disc before DTU."},{"titleIds":["BLUS30307"],"works":1,"note":"Install Game Data Before DTU."},{"titleIds":["BLUS30209"],"works":2,"note":"Use EBOOT from BLES00391 update. Use NPEB00391 as conversion directory. If using CFW2OFW tool, change TitleID in PARAM.SFO to BLES00391 and create new LIC.DAT before conversion."},{"titleIds":["NPUA80019"],"works":1,"note":"Free on PSN."},{"titleIds":["BLUS31452"],"works":1,"note":"Install Game Data Before DTU. Creates \"/game/BLUS31452INSTALL/\" directory."},{"titleIds":["BLUS31588"],"works":2,"note":"Install Game Data from Disc before DTU."},{"titleIds":["BCUS98164"],"works":2,"note":"Install Game Data From Disc Before DTU. Creates \"/game/BCUS98164DATA/\" directory."},{"titleIds":["BCES00802","NPEA90076"],"works":2,"note":"Place the official patch into the /pkg folder of TABR and use \"Add a patch\" option when injecting. After restoring the backup, install the patch. Game can be played without Move controllers by disabling it in the game settings."},{"titleIds":["BLES00648"],"works":2,"note":"Use Demo EBOOT, PARAM.SFO and TITLE_ID from NPEB90167 and copy /USRDIR/* DISC files from BLES00648. Game loads and all stages are available. Note: Does not save data (?)"},{"titleIds":["BLUS31405","BLES01986"],"works":0,"note":"Black screen after the intro. Used EBOOT.BIN files from the demos but does not work."},{"titleIds":["BLES00254"],"works":2,"note":"Use Demo EBOOT, PARAM.SFO and TITLE_ID from NPUB90128 and copy /USRDIR/* DISC files from BLES00254"},{"titleIds":["NPUA80012","NPEA00004"],"works":2,"note":"Extract all files from NPUA80012 v2.01 DEMO. Delete all files from \"/USRDIR/*\" except EBOOT.BIN. Copy all files in \"/USRDIR/*\" from NPEA00004 v2.00, except EBOOT.BIN. Will display Trial Version on Title Screen and Nag after level completion, but all levels are available and functional."},{"titleIds":["BLES02102"],"works":2,"note":"Copy all .SPRX files located in USRDIR/master/prx and replace the ones in your converted game."},{"titleIds":["BLES01636"],"works":2,"note":"Install Game Data from Disc before DTU."},{"titleIds":["BLES02246"],"works":2,"note":"Copy & replace EBOOT.BIN of your converted game with the DEMO ver. then edit converted game PARAM.SFO Title ID to match the Demo ID and chancge Category to HG Harddrive Game."},{"titleIds":["NPEB90114","BLES00322","NPEB00052"],"works":2,"note":"Download the demo (NPEB90114) and take only the EBOOT.BIN and SPUJOBS.SPRX files from it, place them in the NPEB00052 folder and rename the folder to NPEB90114, and change the PARAM.SFO to NPEB90114."},{"titleIds":["BCUS01089"],"works":2,"note":"Install Game Data From Disc Before DTU. Creates \"/game/BCUS01089_R/\" directory."},{"titleIds":["BCES00129"],"works":2,"note":"The game with the patch and the changed PARAM.SFO should be thrown to another folder, for example BCES00129GAME, as well as the patch separately unchanged in the native folder (BCES00129)."},{"titleIds":["BLES01066"],"works":2,"note":"Install Game Data From Disc Before DTU. Creates \"/game/BLES01066_INSTALL/\" directory."},{"titleIds":["BLJS10221"],"works":1,"note":"Install Game Data Before DTU. Creates \"/game/BLJS10221_INSTALLDATA/\" directory."},{"titleIds":["BLJM61346"],"works":1,"note":"Install Game Data Before DTU. Creates \"NPJB00769DATA\" directory. Tested with NPJB61346 DLC. This is NOT the english conversion and I did not experience any errors."},{"titleIds":["BLUS31410"],"works":2,"note":"Install Game Data From Disc Before DTU."},{"titleIds":["BLUS30732"],"works":2,"note":"Replace all SPRX with DISC versions [/USRDIR/bin/*.sprx] and [/USRDIR/portal2/bin/*.sprx]."},{"titleIds":["BLES00389"],"works":0,"note":"Black Screen using several different methods."},{"titleIds":["BLES00839"],"works":0,"note":"Black Screen using several different methods."},{"titleIds":["BLUS30485"],"works":1,"note":"Install Game Data Before DTU. Creates \"/game/BLUS30485GAMEDATA/\" directory."},{"titleIds":["BLES01963"],"works":2,"note":"Install Game Data From Disc Before DTU. Install DLC, DLC Fix, and Update, After Disc Data."},{"titleIds":["NPEB90505","NPEB01356"],"works":2,"note":"The demo (NPEB90505) and the game (NPEB01356) are unpacked. Copy the ICON0.PNG and PIC1.PNG into it. In the folder USRDIR of the demo, delete everything except EBOOT.bin and copy everything from the full game's USRDIR into it except the EBOOT.bin. Delete cine_gameintro.pam and cine_gameintro_fr.pam. You can edit PARAM.SFO to have a better displayed name on the XMB."},{"titleIds":["BLES01179"],"works":1,"note":"Install Game Data Before DTU. Creates \"/game/BLES00680\" directory."},{"titleIds":["BLUS30855","BLES01465"],"works":2,"note":"Fix \"creating save data\" loop: Convert game using ps3gameconvert or CFW2OFW Helper"},{"titleIds":["BLUS31444"],"works":2,"note":"Fix \"creating save data\" loop: Convert game using ps3gameconvert_v0.7 or CFW2OFW Helper (recommended)"},{"titleIds":["BLES00373"],"works":1,"note":"Install Game Data Before DTU"},{"titleIds":["BLUS31205"],"works":1,"note":"Install Game Data Before DTU. Use PS3GameConvert_v0.91 if you experience any issues."},{"titleIds":["BLES00560"],"works":0,"note":"Black screen after Raven logo using CFW2OFW(v8). PS3GameConvert_v0.91 gives startup error. PS3GameConvert_v0.7 asks for disc to be inserted."},{"titleIds":["BCES01257"],"works":1,"note":"Install Game Data Before DTU"},{"titleIds":["BCES00894"],"works":1,"note":"Install Game Data Before DTU"},{"titleIds":["BCES00835"],"works":1,"note":"Install Game Data Before DTU"},{"titleIds":["BCES00494"],"works":1,"note":"Install Game Data Before DTU"},{"titleIds":["BCES00607"],"works":1,"note":"Install Game Data Before DTU"},{"titleIds":["BCES00265"],"works":1,"note":"Install Game Data Before DTU"},{"titleIds":["BLUS30464"],"works":2,"note":"Install Game Data From Disc Before DTU. Creates \"/game/BLUS30464_INSTALL/\" directory."},{"titleIds":["NPEB01046","NPUB90832","BLUS30927"],"works":2,"note":"Download the demo (NPUB90832) and the full game (NPEB01046). Replace the full game's EBOOT.bin with the one from the demo and and change the Title ID in the full game PARAM.SFO to NPUB90832, rename the full game folder to NPUB90832 and inject the full game. BLUS30927 - Use PS3GameConvert_v0.91 and pre-install game data before DTU."},{"titleIds":["BLES01250"],"works":0,"note":"Insert Disc Error 8001003E. [Manual] [CFW2OFW Helper v8]"},{"titleIds":["BCES00819"],"works":2,"note":"Use EBOOT and TitleID from NPEA90112 Demo. Copy all files from disc /USRDIR/* to demo /USRDIR/*. Encrypt all *.TXT files under \"/USRDIR/SORCGAME/\" [PS3TOC.TXT, PS3TOC_ALL.TXT, etc] to \"*.TXT.SDAT\" using npdtool. I tested this up until the \"Connect Playstation Eye Camera\" message."},{"titleIds":["BLES01766"],"works":2,"note":"Google: Splinter Cell: Blacklist PS3 OFW BD Mirror FIX Tutorial by Blade."},{"titleIds":["BCES01598"],"works":0,"note":"Infinite Loading Screen. [Manual] [CFW2OFW Helper v8]"},{"titleIds":["BLUS30445","BLUS30144"],"works":2,"note":"Edit the PARAM.SFO to BLUS30144 and copy the contents (except EBOOT.bin) of USRDIR into the patch file's USRDIR."},{"titleIds":["BLES00513"],"works":0,"note":"Game kicks you back to XMB. [PS3GameConvert_V0.91] [CFW2OFW Helper v8]"},{"titleIds":["BLES01371","NPUB90713"],"works":2,"note":"Rename PS3_GAME to NPUB90713, copy PARAM.SFO and eboot.bin from the demo (NPUB90713) into NPUB90713. In order to change the language to Russian, rename SFXDESC and WAVES_PS3 from CONTENT_ENG to CONTENT_RUS, and remove CONTENT_ENG and rename the following: CONTENT_RUS to CONTENT_ENG, CONTENT_RUS.000.XTC to CONTENT_ENG.000.XTC and STRINGTABLE_RUS.XCR in STRINGTABLE_ENG.XCR. You can edit PARAM.SFO to have a better displayed name on the XMB."},{"titleIds":["BLES00289"],"works":0,"note":"Return To XMB. Tested with converted and normal SPRX."},{"titleIds":["BLES01982"],"works":2,"note":"Install Game Data from Disc before DTU."},{"titleIds":["BLES00159","NPEB90036","NPEB90049"],"works":2,"note":"Unpack the demo (NPEB90036 or NPEB90049), copy PIC1.PNG from the disc version into the demo. Delete all of the contents (except EBOOT.bin) of the USRDIR folder in the demo and copy it into the disc version of the game."},{"titleIds":["BLUS30125"],"works":0,"note":"Freezes During Ubisoft Logo [Pre-intall Game Data] [SPRX] [PS3GameConvert_V0.91] [CFW2OFW Helper v8]"},{"titleIds":["BLES00409"],"works":0,"note":"Frozen Black Screen. [PS3GameConvert_V0.91] [CFW2OFW Helper v8] UPD - because in patch there is link to dev_bd"},{"titleIds":["BLUS30427"],"works":2,"note":"Install Game Data from Disc before DTU. Creates \"/game/BLUS30427DATA/\" directory."},{"titleIds":["NPEB90200","NPEB00100"],"works":2,"note":"Unpack NPEB90200, delete everything except EBOOT.BIN in the folder USRDIR. Unpack NPEB00100 together with the patch, combine. Unpack the file data3.fbz with 7-zip into any folder (for example, data3). After you can delete it, it will no longer be needed. Next, open data1.fbz 7-zip'om and move the contents of the folder into which we unpacked data3.fbz. Move the contents of the folder USRDIR (which is in NPEB00100) into NPEB90200. You can edit PARAM.SFO to have a better displayed name on the XMB."},{"titleIds":["BLES01355"],"works":1,"note":"Pre-Install game data before DTU to avoid data install errors."},{"titleIds":["NPEB00108"],"works":2,"note":"Add the line \"trialmode = false\" to the file local_config.txt (without quotes)"},{"titleIds":["BCES00225"],"works":2,"note":"Do not DTU the patch folder (BCES00225) or you will encounter a corrupt game data error. Game works without a patch or you can patch the game online after DTU. [CFW2OFW Helper v8]"},{"titleIds":["BCES00664"],"works":2,"note":"Rename patch to BCES00664DATA, delete the entire contents of its USRDIR folder, copy all dataXX.psarc to it from the disc. Edit the PARAM.SFO and remove the lines: PS3 System, Parental Lock Level, App Ver and Target Ver. Patch 2.10 (again) with the modified PARAM.SFO (HG and APP Ver 2.51) in the original folder (BCES00664) or in BCES00664GAME + DFEngine.sprx from patch 2.30. [CFW2OFW Helper v8]"}] \ No newline at end of file diff --git a/tools/2/make_npdata.exe b/tools/2/make_npdata.exe new file mode 100644 index 0000000..162b414 Binary files /dev/null and b/tools/2/make_npdata.exe differ diff --git a/tools/3/do.bat b/tools/3/do.bat new file mode 100644 index 0000000..4421468 --- /dev/null +++ b/tools/3/do.bat @@ -0,0 +1,84 @@ +@echo off + +set game= +set ptch= + +for /d %%v in (NP???????) do set game=%%v +for /d %%v in (BL???????) do set ptch=%%v +for /d %%v in (BC???????) do set ptch=%%v + +if "%game%" equ "" goto failure +if "%ptch%" equ "" goto failure + +echo Found folders +echo Game: %game% +echo Patch: %ptch% + +echo. + +echo Creating GAME pkg... + +echo contentid = 000000-%game:~0,9%_00-1GAME00000000000>package.conf +echo klicensee = 0x00000000000000000000000000000000>>package.conf +echo drmtype = Free>>package.conf +echo contenttype = GameExec>>package.conf +echo packagetype = HDDGamePatch>>package.conf +echo installdirectory = %game%>>package.conf +echo packageversion = 01.00>>package.conf + +makepkg1.exe -n package.conf %game%>nul + +if exist %game%\LICDIR xcopy "%game%\LICDIR\*.*" "%game%-LIC\LICDIR\*.*">nul +if exist %game%\INSDIR xcopy "%game%\INSDIR\*.*" "%game%-LIC\INSDIR\*.*">nul + +echo Creating PATCH pkg... + +echo contentid = 000000-%game:~0,9%_00-2PATCH0000000000>package.conf +echo klicensee = 0x00000000000000000000000000000000>>package.conf +echo drmtype = Free>>package.conf +echo contenttype = GameData>>package.conf +echo packagetype = DiscGamePatch>>package.conf +echo installdirectory = %ptch%>>package.conf +echo packageversion = 01.00>>package.conf + +makepkg1.exe -n package.conf %ptch%>nul + +if exist %game%-LIC ( + echo Creating LIC pkg... + + echo contentid = 000000-%game:~0,9%_00-3LIC000000000000>package.conf + echo klicensee = 0x00000000000000000000000000000000>>package.conf + echo drmtype = Free>>package.conf + echo contenttype = GameExec>>package.conf + echo packagetype = HDDGamePatch>>package.conf + echo installdirectory = %game%>>package.conf + echo packageversion = 01.00>>package.conf + + makepkg2.exe -n package.conf %game%-LIC>nul + + rd /S /Q "%game%-LIC">nul +) + +del package.conf>nul + +goto success + +:success + +echo. + +echo Successfully created pkgs. + +goto end + +:failure + +echo Some folders are missing. + +goto end + +:end + +echo Press any key to exit. + +pause>nul diff --git a/tools/3/makepkg1.exe b/tools/3/makepkg1.exe new file mode 100644 index 0000000..9627b00 Binary files /dev/null and b/tools/3/makepkg1.exe differ diff --git a/tools/3/makepkg2.exe b/tools/3/makepkg2.exe new file mode 100644 index 0000000..924c066 Binary files /dev/null and b/tools/3/makepkg2.exe differ diff --git a/tools/4/input/act_dat/.gitignore b/tools/4/input/act_dat/.gitignore new file mode 100644 index 0000000..3ff720a --- /dev/null +++ b/tools/4/input/act_dat/.gitignore @@ -0,0 +1,2 @@ +act.dat +signed_act.dat diff --git a/tools/4/input/idps_hex/.gitignore b/tools/4/input/idps_hex/.gitignore new file mode 100644 index 0000000..50a042e --- /dev/null +++ b/tools/4/input/idps_hex/.gitignore @@ -0,0 +1 @@ +idps.hex diff --git a/tools/4/input/pkgs/.gitignore b/tools/4/input/pkgs/.gitignore new file mode 100644 index 0000000..31e78b2 --- /dev/null +++ b/tools/4/input/pkgs/.gitignore @@ -0,0 +1,2 @@ +*.pkg +*.PKG diff --git a/tools/4/input/raps/.gitignore b/tools/4/input/raps/.gitignore new file mode 100644 index 0000000..79c5b39 --- /dev/null +++ b/tools/4/input/raps/.gitignore @@ -0,0 +1,2 @@ +*.rap +*.RAP diff --git a/tools/4/output/pkgs/.gitignore b/tools/4/output/pkgs/.gitignore new file mode 100644 index 0000000..31e78b2 --- /dev/null +++ b/tools/4/output/pkgs/.gitignore @@ -0,0 +1,2 @@ +*.pkg +*.PKG diff --git a/tools/4/output/temp/.gitignore b/tools/4/output/temp/.gitignore new file mode 100644 index 0000000..72931f4 --- /dev/null +++ b/tools/4/output/temp/.gitignore @@ -0,0 +1,2 @@ +*.rif +*.RIF diff --git a/tools/4/resign_linux.sh b/tools/4/resign_linux.sh new file mode 100644 index 0000000..aa86cd5 --- /dev/null +++ b/tools/4/resign_linux.sh @@ -0,0 +1,325 @@ +#!/bin/bash +# +# Copyright 2018 Caio Oliveira +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# PS3Xploit ReSign BASH Script for act.dat, PKG and RAP +# Thanks to @CaptainCPS-X for script to build a proper PKG using Python +function ps3xploit_resign() { + + # Usage: ps3xploit_resign (Resign for act.dat, PKG and RAP) + echo; + echo "ps3xploit_resign: PS3Xploit ReSign BASH Script for act.dat, PKG and RAP"; + echo; + + ### + ### Variables + ### + + # Main Exports + export PS3XPLOIT_RESIGNER_BINARY=; + export PS3XPLOIT_PKGPY_BINARY=; + export PS3XPLOIT_PYTHON_BINARY=; + + # Save Current Working Dir and Create a TEMPorary DIR + cwd=$(pwd); + + # Main tools + ps3py_tools_dir="${cwd}/source/tools/ps3py"; + ps3xploit_resign_source_dir="${cwd}/source/src"; + ps3xploit_precompiled_dir="${cwd}/source/pre-compiled/linux"; + + # Output dirs + output_pkgs_dir="${cwd}/output/pkgs"; + + # Input files + input_act_dat="${cwd}/input/act_dat/act.dat"; + input_idps_hex="${cwd}/input/idps_hex/idps.hex"; + + # Input dirs + input_raps_dir="${cwd}/input/raps" + input_pkgs_dir="${cwd}/input/pkgs" + + # RIF Package ContentID and Name + rif_pkg_contentid="RIF000-INSTALLER_00-0000000000000000"; + rif_pkg_name="${output_pkgs_dir}/PKG_RIF-INSTALLER.pkg"; + + ### + ### Check + ### + + # Search for *.rap files + input_raps_files=($(find "${input_raps_dir}/" -maxdepth 1 -type f \( -iname \*.rap -o -iname \*.RAP \))); + input_raps_size="${#input_raps_files[@]}"; + if [ "${input_raps_size}" -eq 0 ]; then + echo; + echo "ps3xploit_resign: No '*.rap' files found on '.${input_raps_dir##${cwd}}'"; + echo; + fi; + + # Check 'act.dat' and 'idps.hex' only when resign RAP files + if [ "${input_raps_size}" -gt 0 ]; then + for IFC in ${input_act_dat} ${input_idps_hex}; do + if [ ! -e "${IFC}" ]; then + echo; + echo "ps3xploit_resign: '.${IFC##${cwd}}' not found, exiting..."; + echo; + return; + fi; + done; + fi; + + # Search for *.pkg files + input_pkgs_files=($(find "${input_pkgs_dir}/" -maxdepth 1 -name "*.pkg")); + input_pkgs_size="${#input_pkgs_files[@]}"; + if [ "${input_pkgs_size}" -eq 0 ]; then + echo; + echo "ps3xploit_resign: No '*.pkg' files found on '.${input_pkgs_dir##${cwd}}'"; + echo; + fi; + + # Nothing to do, just exit + if [ "${input_raps_size}" -eq 0 -a "${input_pkgs_size}" -eq 0 ]; then + return; + fi; + + # Check source files of resign + if [ -f "${ps3xploit_resign_source_dir}" ]; then + echo; + echo "ps3xploit_resign: Resign Dir '.${ps3xploit_resign_source_dir##${cwd}}' not found, exiting..."; + echo; + return; + fi; + + ### + ### Prepare Common + ### + + # Cleanup + rm -rf "${ps3xploit_precompiled_dir}/ps3xploit_rifgen_edatresign"; + + # Message Output + echo; + echo "ps3xploit_resign: Building 'ps3xploit_rifgen_edatresign'"; + echo; + + # Go to src dir + cd "${ps3xploit_resign_source_dir}"; + + # Clean old builds + make clean; + + # Make 'ps3xploit_rifgen_edatresign' + make; + + # Return back to current dir + cd "${cwd}"; + + # Check if ps3xploit_rifgen_edatresing exists + PS3XPLOIT_RESIGNER_BINARY=$(readlink -e "${ps3xploit_resign_source_dir}/ps3xploit_rifgen_edatresign"); + if [ -z "${PS3XPLOIT_RESIGNER_BINARY}" ]; then + echo; + echo "ps3xploit_resign: 'ps3xploit_rifgen_edatresign' not found, exiting..."; + echo; + return; + fi; + + # Copy new binary to precompiled dir + cp "${PS3XPLOIT_RESIGNER_BINARY}" "${ps3xploit_precompiled_dir}/"; + + # Go to src dir + cd "${ps3xploit_resign_source_dir}"; + + # Clean build + make clean; + + # Return back to current dir + cd "${cwd}"; + + # Check Resigner binary file + PS3XPLOIT_RESIGNER_BINARY=$(readlink -e "${ps3xploit_precompiled_dir}/ps3xploit_rifgen_edatresign"); + + # Check 'Build ReSign for Linux' + if [ -z "${PS3XPLOIT_RESIGNER_BINARY}" ]; then + echo; + echo "ps3xploit_resign: 'ps3xploit_rifgen_edatresign' not found, exiting..."; + echo; + return; + fi; + + ### + ### Start - RIF + ### + + # Use only when resign RAP files + if [ "${input_raps_size}" -gt 0 ]; then + + # Check 'pkg.py' + PS3XPLOIT_PKGPY_BINARY=$(readlink -e "${ps3py_tools_dir}/pkg.py"); + if [ -z "${PS3XPLOIT_PKGPY_BINARY}" ]; then + echo "ps3xploit_resign: 'pkg.py' not found, exiting..."; + return; + fi; + + # Cleanup + rm -rf "${ps3py_tools_dir}/build" "${ps3py_tools_dir}/pkgcrypt.so"; + + # Check if the Python2.7 is installed + PS3XPLOIT_PYTHON_BINARY=$(which python2.7); + if [ -z "${PS3XPLOIT_PYTHON_BINARY}" ]; then + echo; + echo "ps3xploit_ps3py_all: 'python2.7' not is installed, exiting..."; + echo " To continue install 'python2.7'"; + echo; + return; + fi; + + # Check if python-dev is installed + python_headers=$(dpkg-query -l python-dev >/dev/null 2>&1; echo "${?}"); + if [ "${python_headers}" -ne 0 ]; then + echo; + echo "ps3xploit_ps3py_all: 'python-dev' not is installed, exiting..."; + echo " To continue install 'python-dev'"; + echo; + return; + fi; + + # Message output + echo; + echo "ps3xploit_ps3py_all: Preparing 'ps3py' tools"; + echo; + + # Go to src dir + cd "${ps3py_tools_dir}"; + + # Setup to 'pkg.py' + ${PS3XPLOIT_PYTHON_BINARY} 'setup.py' 'build'; + + # Return back to current dir + cd "${cwd}"; + + # Check if the 'pkgcrypt' is builded + ps3py_lib=$(readlink -e "${ps3py_tools_dir}/build/lib."*"/pkgcrypt.so"); + if [ -z "${ps3py_lib}" ]; then + echo; + echo "ps3xploit_ps3py_all: 'pkgcrypt.so' building failed, exiting..."; + echo; + return; + fi; + + # Copy new library + cp "${ps3py_lib}" "${ps3py_tools_dir}/"; + + # Cleanup + rm -rf "${rif_pkg_name:?}" "${rif_pkg_name:?}_signed.pkg"; + + # Create a TEMPorary DIR + temp_dir=$(mktemp -d); + + # Copy 'act.dat' and 'idps.hex' + for IFC in ${input_act_dat} ${input_idps_hex}; do + cp "${IFC}" "${temp_dir}/"; + done; + + # Sign RIF files + for ((srap=0; srap + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * The AES block cipher was designed by Vincent Rijmen and Joan Daemen. + * + * http://csrc.nist.gov/encryption/aes/rijndael/Rijndael.pdf + * http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf + */ + +#include "aes.h" + +/* + * 32-bit integer manipulation macros (little endian) + */ +#ifndef GET_ULONG_LE +#define GET_ULONG_LE(n,b,i) \ +{ \ + (n) = ( (unsigned long) (b)[(i) ] ) \ + | ( (unsigned long) (b)[(i) + 1] << 8 ) \ + | ( (unsigned long) (b)[(i) + 2] << 16 ) \ + | ( (unsigned long) (b)[(i) + 3] << 24 ); \ +} +#endif + +#ifndef PUT_ULONG_LE +#define PUT_ULONG_LE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \ +} +#endif + +/* + * Forward S-box + */ +static const unsigned char FSb[256] = +{ + 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, + 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, + 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, + 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, + 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, + 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, + 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, + 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, + 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, + 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, + 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, + 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, + 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, + 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, + 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, + 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, + 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, + 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, + 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, + 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, + 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, + 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, + 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, + 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, + 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, + 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, + 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, + 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, + 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, + 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, + 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, + 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16 +}; + +/* + * Forward tables + */ +#define FT \ +\ + V(A5,63,63,C6), V(84,7C,7C,F8), V(99,77,77,EE), V(8D,7B,7B,F6), \ + V(0D,F2,F2,FF), V(BD,6B,6B,D6), V(B1,6F,6F,DE), V(54,C5,C5,91), \ + V(50,30,30,60), V(03,01,01,02), V(A9,67,67,CE), V(7D,2B,2B,56), \ + V(19,FE,FE,E7), V(62,D7,D7,B5), V(E6,AB,AB,4D), V(9A,76,76,EC), \ + V(45,CA,CA,8F), V(9D,82,82,1F), V(40,C9,C9,89), V(87,7D,7D,FA), \ + V(15,FA,FA,EF), V(EB,59,59,B2), V(C9,47,47,8E), V(0B,F0,F0,FB), \ + V(EC,AD,AD,41), V(67,D4,D4,B3), V(FD,A2,A2,5F), V(EA,AF,AF,45), \ + V(BF,9C,9C,23), V(F7,A4,A4,53), V(96,72,72,E4), V(5B,C0,C0,9B), \ + V(C2,B7,B7,75), V(1C,FD,FD,E1), V(AE,93,93,3D), V(6A,26,26,4C), \ + V(5A,36,36,6C), V(41,3F,3F,7E), V(02,F7,F7,F5), V(4F,CC,CC,83), \ + V(5C,34,34,68), V(F4,A5,A5,51), V(34,E5,E5,D1), V(08,F1,F1,F9), \ + V(93,71,71,E2), V(73,D8,D8,AB), V(53,31,31,62), V(3F,15,15,2A), \ + V(0C,04,04,08), V(52,C7,C7,95), V(65,23,23,46), V(5E,C3,C3,9D), \ + V(28,18,18,30), V(A1,96,96,37), V(0F,05,05,0A), V(B5,9A,9A,2F), \ + V(09,07,07,0E), V(36,12,12,24), V(9B,80,80,1B), V(3D,E2,E2,DF), \ + V(26,EB,EB,CD), V(69,27,27,4E), V(CD,B2,B2,7F), V(9F,75,75,EA), \ + V(1B,09,09,12), V(9E,83,83,1D), V(74,2C,2C,58), V(2E,1A,1A,34), \ + V(2D,1B,1B,36), V(B2,6E,6E,DC), V(EE,5A,5A,B4), V(FB,A0,A0,5B), \ + V(F6,52,52,A4), V(4D,3B,3B,76), V(61,D6,D6,B7), V(CE,B3,B3,7D), \ + V(7B,29,29,52), V(3E,E3,E3,DD), V(71,2F,2F,5E), V(97,84,84,13), \ + V(F5,53,53,A6), V(68,D1,D1,B9), V(00,00,00,00), V(2C,ED,ED,C1), \ + V(60,20,20,40), V(1F,FC,FC,E3), V(C8,B1,B1,79), V(ED,5B,5B,B6), \ + V(BE,6A,6A,D4), V(46,CB,CB,8D), V(D9,BE,BE,67), V(4B,39,39,72), \ + V(DE,4A,4A,94), V(D4,4C,4C,98), V(E8,58,58,B0), V(4A,CF,CF,85), \ + V(6B,D0,D0,BB), V(2A,EF,EF,C5), V(E5,AA,AA,4F), V(16,FB,FB,ED), \ + V(C5,43,43,86), V(D7,4D,4D,9A), V(55,33,33,66), V(94,85,85,11), \ + V(CF,45,45,8A), V(10,F9,F9,E9), V(06,02,02,04), V(81,7F,7F,FE), \ + V(F0,50,50,A0), V(44,3C,3C,78), V(BA,9F,9F,25), V(E3,A8,A8,4B), \ + V(F3,51,51,A2), V(FE,A3,A3,5D), V(C0,40,40,80), V(8A,8F,8F,05), \ + V(AD,92,92,3F), V(BC,9D,9D,21), V(48,38,38,70), V(04,F5,F5,F1), \ + V(DF,BC,BC,63), V(C1,B6,B6,77), V(75,DA,DA,AF), V(63,21,21,42), \ + V(30,10,10,20), V(1A,FF,FF,E5), V(0E,F3,F3,FD), V(6D,D2,D2,BF), \ + V(4C,CD,CD,81), V(14,0C,0C,18), V(35,13,13,26), V(2F,EC,EC,C3), \ + V(E1,5F,5F,BE), V(A2,97,97,35), V(CC,44,44,88), V(39,17,17,2E), \ + V(57,C4,C4,93), V(F2,A7,A7,55), V(82,7E,7E,FC), V(47,3D,3D,7A), \ + V(AC,64,64,C8), V(E7,5D,5D,BA), V(2B,19,19,32), V(95,73,73,E6), \ + V(A0,60,60,C0), V(98,81,81,19), V(D1,4F,4F,9E), V(7F,DC,DC,A3), \ + V(66,22,22,44), V(7E,2A,2A,54), V(AB,90,90,3B), V(83,88,88,0B), \ + V(CA,46,46,8C), V(29,EE,EE,C7), V(D3,B8,B8,6B), V(3C,14,14,28), \ + V(79,DE,DE,A7), V(E2,5E,5E,BC), V(1D,0B,0B,16), V(76,DB,DB,AD), \ + V(3B,E0,E0,DB), V(56,32,32,64), V(4E,3A,3A,74), V(1E,0A,0A,14), \ + V(DB,49,49,92), V(0A,06,06,0C), V(6C,24,24,48), V(E4,5C,5C,B8), \ + V(5D,C2,C2,9F), V(6E,D3,D3,BD), V(EF,AC,AC,43), V(A6,62,62,C4), \ + V(A8,91,91,39), V(A4,95,95,31), V(37,E4,E4,D3), V(8B,79,79,F2), \ + V(32,E7,E7,D5), V(43,C8,C8,8B), V(59,37,37,6E), V(B7,6D,6D,DA), \ + V(8C,8D,8D,01), V(64,D5,D5,B1), V(D2,4E,4E,9C), V(E0,A9,A9,49), \ + V(B4,6C,6C,D8), V(FA,56,56,AC), V(07,F4,F4,F3), V(25,EA,EA,CF), \ + V(AF,65,65,CA), V(8E,7A,7A,F4), V(E9,AE,AE,47), V(18,08,08,10), \ + V(D5,BA,BA,6F), V(88,78,78,F0), V(6F,25,25,4A), V(72,2E,2E,5C), \ + V(24,1C,1C,38), V(F1,A6,A6,57), V(C7,B4,B4,73), V(51,C6,C6,97), \ + V(23,E8,E8,CB), V(7C,DD,DD,A1), V(9C,74,74,E8), V(21,1F,1F,3E), \ + V(DD,4B,4B,96), V(DC,BD,BD,61), V(86,8B,8B,0D), V(85,8A,8A,0F), \ + V(90,70,70,E0), V(42,3E,3E,7C), V(C4,B5,B5,71), V(AA,66,66,CC), \ + V(D8,48,48,90), V(05,03,03,06), V(01,F6,F6,F7), V(12,0E,0E,1C), \ + V(A3,61,61,C2), V(5F,35,35,6A), V(F9,57,57,AE), V(D0,B9,B9,69), \ + V(91,86,86,17), V(58,C1,C1,99), V(27,1D,1D,3A), V(B9,9E,9E,27), \ + V(38,E1,E1,D9), V(13,F8,F8,EB), V(B3,98,98,2B), V(33,11,11,22), \ + V(BB,69,69,D2), V(70,D9,D9,A9), V(89,8E,8E,07), V(A7,94,94,33), \ + V(B6,9B,9B,2D), V(22,1E,1E,3C), V(92,87,87,15), V(20,E9,E9,C9), \ + V(49,CE,CE,87), V(FF,55,55,AA), V(78,28,28,50), V(7A,DF,DF,A5), \ + V(8F,8C,8C,03), V(F8,A1,A1,59), V(80,89,89,09), V(17,0D,0D,1A), \ + V(DA,BF,BF,65), V(31,E6,E6,D7), V(C6,42,42,84), V(B8,68,68,D0), \ + V(C3,41,41,82), V(B0,99,99,29), V(77,2D,2D,5A), V(11,0F,0F,1E), \ + V(CB,B0,B0,7B), V(FC,54,54,A8), V(D6,BB,BB,6D), V(3A,16,16,2C) + +#define V(a,b,c,d) 0x##a##b##c##d +static const unsigned long FT0[256] = { FT }; +#undef V + +#define V(a,b,c,d) 0x##b##c##d##a +static const unsigned long FT1[256] = { FT }; +#undef V + +#define V(a,b,c,d) 0x##c##d##a##b +static const unsigned long FT2[256] = { FT }; +#undef V + +#define V(a,b,c,d) 0x##d##a##b##c +static const unsigned long FT3[256] = { FT }; +#undef V + +#undef FT + +/* + * Reverse S-box + */ +static const unsigned char RSb[256] = +{ + 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, + 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB, + 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, + 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, + 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, + 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E, + 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, + 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25, + 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, + 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, + 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, + 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84, + 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, + 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06, + 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, + 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, + 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, + 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73, + 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, + 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E, + 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, + 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, + 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, + 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, + 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, + 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F, + 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, + 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, + 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, + 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, + 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, + 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D +}; + +/* + * Reverse tables + */ +#define RT \ +\ + V(50,A7,F4,51), V(53,65,41,7E), V(C3,A4,17,1A), V(96,5E,27,3A), \ + V(CB,6B,AB,3B), V(F1,45,9D,1F), V(AB,58,FA,AC), V(93,03,E3,4B), \ + V(55,FA,30,20), V(F6,6D,76,AD), V(91,76,CC,88), V(25,4C,02,F5), \ + V(FC,D7,E5,4F), V(D7,CB,2A,C5), V(80,44,35,26), V(8F,A3,62,B5), \ + V(49,5A,B1,DE), V(67,1B,BA,25), V(98,0E,EA,45), V(E1,C0,FE,5D), \ + V(02,75,2F,C3), V(12,F0,4C,81), V(A3,97,46,8D), V(C6,F9,D3,6B), \ + V(E7,5F,8F,03), V(95,9C,92,15), V(EB,7A,6D,BF), V(DA,59,52,95), \ + V(2D,83,BE,D4), V(D3,21,74,58), V(29,69,E0,49), V(44,C8,C9,8E), \ + V(6A,89,C2,75), V(78,79,8E,F4), V(6B,3E,58,99), V(DD,71,B9,27), \ + V(B6,4F,E1,BE), V(17,AD,88,F0), V(66,AC,20,C9), V(B4,3A,CE,7D), \ + V(18,4A,DF,63), V(82,31,1A,E5), V(60,33,51,97), V(45,7F,53,62), \ + V(E0,77,64,B1), V(84,AE,6B,BB), V(1C,A0,81,FE), V(94,2B,08,F9), \ + V(58,68,48,70), V(19,FD,45,8F), V(87,6C,DE,94), V(B7,F8,7B,52), \ + V(23,D3,73,AB), V(E2,02,4B,72), V(57,8F,1F,E3), V(2A,AB,55,66), \ + V(07,28,EB,B2), V(03,C2,B5,2F), V(9A,7B,C5,86), V(A5,08,37,D3), \ + V(F2,87,28,30), V(B2,A5,BF,23), V(BA,6A,03,02), V(5C,82,16,ED), \ + V(2B,1C,CF,8A), V(92,B4,79,A7), V(F0,F2,07,F3), V(A1,E2,69,4E), \ + V(CD,F4,DA,65), V(D5,BE,05,06), V(1F,62,34,D1), V(8A,FE,A6,C4), \ + V(9D,53,2E,34), V(A0,55,F3,A2), V(32,E1,8A,05), V(75,EB,F6,A4), \ + V(39,EC,83,0B), V(AA,EF,60,40), V(06,9F,71,5E), V(51,10,6E,BD), \ + V(F9,8A,21,3E), V(3D,06,DD,96), V(AE,05,3E,DD), V(46,BD,E6,4D), \ + V(B5,8D,54,91), V(05,5D,C4,71), V(6F,D4,06,04), V(FF,15,50,60), \ + V(24,FB,98,19), V(97,E9,BD,D6), V(CC,43,40,89), V(77,9E,D9,67), \ + V(BD,42,E8,B0), V(88,8B,89,07), V(38,5B,19,E7), V(DB,EE,C8,79), \ + V(47,0A,7C,A1), V(E9,0F,42,7C), V(C9,1E,84,F8), V(00,00,00,00), \ + V(83,86,80,09), V(48,ED,2B,32), V(AC,70,11,1E), V(4E,72,5A,6C), \ + V(FB,FF,0E,FD), V(56,38,85,0F), V(1E,D5,AE,3D), V(27,39,2D,36), \ + V(64,D9,0F,0A), V(21,A6,5C,68), V(D1,54,5B,9B), V(3A,2E,36,24), \ + V(B1,67,0A,0C), V(0F,E7,57,93), V(D2,96,EE,B4), V(9E,91,9B,1B), \ + V(4F,C5,C0,80), V(A2,20,DC,61), V(69,4B,77,5A), V(16,1A,12,1C), \ + V(0A,BA,93,E2), V(E5,2A,A0,C0), V(43,E0,22,3C), V(1D,17,1B,12), \ + V(0B,0D,09,0E), V(AD,C7,8B,F2), V(B9,A8,B6,2D), V(C8,A9,1E,14), \ + V(85,19,F1,57), V(4C,07,75,AF), V(BB,DD,99,EE), V(FD,60,7F,A3), \ + V(9F,26,01,F7), V(BC,F5,72,5C), V(C5,3B,66,44), V(34,7E,FB,5B), \ + V(76,29,43,8B), V(DC,C6,23,CB), V(68,FC,ED,B6), V(63,F1,E4,B8), \ + V(CA,DC,31,D7), V(10,85,63,42), V(40,22,97,13), V(20,11,C6,84), \ + V(7D,24,4A,85), V(F8,3D,BB,D2), V(11,32,F9,AE), V(6D,A1,29,C7), \ + V(4B,2F,9E,1D), V(F3,30,B2,DC), V(EC,52,86,0D), V(D0,E3,C1,77), \ + V(6C,16,B3,2B), V(99,B9,70,A9), V(FA,48,94,11), V(22,64,E9,47), \ + V(C4,8C,FC,A8), V(1A,3F,F0,A0), V(D8,2C,7D,56), V(EF,90,33,22), \ + V(C7,4E,49,87), V(C1,D1,38,D9), V(FE,A2,CA,8C), V(36,0B,D4,98), \ + V(CF,81,F5,A6), V(28,DE,7A,A5), V(26,8E,B7,DA), V(A4,BF,AD,3F), \ + V(E4,9D,3A,2C), V(0D,92,78,50), V(9B,CC,5F,6A), V(62,46,7E,54), \ + V(C2,13,8D,F6), V(E8,B8,D8,90), V(5E,F7,39,2E), V(F5,AF,C3,82), \ + V(BE,80,5D,9F), V(7C,93,D0,69), V(A9,2D,D5,6F), V(B3,12,25,CF), \ + V(3B,99,AC,C8), V(A7,7D,18,10), V(6E,63,9C,E8), V(7B,BB,3B,DB), \ + V(09,78,26,CD), V(F4,18,59,6E), V(01,B7,9A,EC), V(A8,9A,4F,83), \ + V(65,6E,95,E6), V(7E,E6,FF,AA), V(08,CF,BC,21), V(E6,E8,15,EF), \ + V(D9,9B,E7,BA), V(CE,36,6F,4A), V(D4,09,9F,EA), V(D6,7C,B0,29), \ + V(AF,B2,A4,31), V(31,23,3F,2A), V(30,94,A5,C6), V(C0,66,A2,35), \ + V(37,BC,4E,74), V(A6,CA,82,FC), V(B0,D0,90,E0), V(15,D8,A7,33), \ + V(4A,98,04,F1), V(F7,DA,EC,41), V(0E,50,CD,7F), V(2F,F6,91,17), \ + V(8D,D6,4D,76), V(4D,B0,EF,43), V(54,4D,AA,CC), V(DF,04,96,E4), \ + V(E3,B5,D1,9E), V(1B,88,6A,4C), V(B8,1F,2C,C1), V(7F,51,65,46), \ + V(04,EA,5E,9D), V(5D,35,8C,01), V(73,74,87,FA), V(2E,41,0B,FB), \ + V(5A,1D,67,B3), V(52,D2,DB,92), V(33,56,10,E9), V(13,47,D6,6D), \ + V(8C,61,D7,9A), V(7A,0C,A1,37), V(8E,14,F8,59), V(89,3C,13,EB), \ + V(EE,27,A9,CE), V(35,C9,61,B7), V(ED,E5,1C,E1), V(3C,B1,47,7A), \ + V(59,DF,D2,9C), V(3F,73,F2,55), V(79,CE,14,18), V(BF,37,C7,73), \ + V(EA,CD,F7,53), V(5B,AA,FD,5F), V(14,6F,3D,DF), V(86,DB,44,78), \ + V(81,F3,AF,CA), V(3E,C4,68,B9), V(2C,34,24,38), V(5F,40,A3,C2), \ + V(72,C3,1D,16), V(0C,25,E2,BC), V(8B,49,3C,28), V(41,95,0D,FF), \ + V(71,01,A8,39), V(DE,B3,0C,08), V(9C,E4,B4,D8), V(90,C1,56,64), \ + V(61,84,CB,7B), V(70,B6,32,D5), V(74,5C,6C,48), V(42,57,B8,D0) + +#define V(a,b,c,d) 0x##a##b##c##d +static const unsigned long RT0[256] = { RT }; +#undef V + +#define V(a,b,c,d) 0x##b##c##d##a +static const unsigned long RT1[256] = { RT }; +#undef V + +#define V(a,b,c,d) 0x##c##d##a##b +static const unsigned long RT2[256] = { RT }; +#undef V + +#define V(a,b,c,d) 0x##d##a##b##c +static const unsigned long RT3[256] = { RT }; +#undef V + +#undef RT + +/* + * Round constants + */ +static const unsigned long RCON[10] = +{ + 0x00000001, 0x00000002, 0x00000004, 0x00000008, + 0x00000010, 0x00000020, 0x00000040, 0x00000080, + 0x0000001B, 0x00000036 +}; + +/* + * AES key schedule (encryption) + */ +int aes_setkey_enc( aes_context *ctx, const unsigned char *key, unsigned int keysize ) +{ + unsigned int i; + unsigned long *RK; + + switch( keysize ) + { + case 128: ctx->nr = 10; break; + case 192: ctx->nr = 12; break; + case 256: ctx->nr = 14; break; + default : return( POLARSSL_ERR_AES_INVALID_KEY_LENGTH ); + } + + ctx->rk = RK = ctx->buf; + + for( i = 0; i < (keysize >> 5); i++ ) + { + GET_ULONG_LE( RK[i], key, i << 2 ); + } + + switch( ctx->nr ) + { + case 10: + + for( i = 0; i < 10; i++, RK += 4 ) + { + RK[4] = RK[0] ^ RCON[i] ^ + ( (unsigned long) FSb[ ( RK[3] >> 8 ) & 0xFF ] ) ^ + ( (unsigned long) FSb[ ( RK[3] >> 16 ) & 0xFF ] << 8 ) ^ + ( (unsigned long) FSb[ ( RK[3] >> 24 ) & 0xFF ] << 16 ) ^ + ( (unsigned long) FSb[ ( RK[3] ) & 0xFF ] << 24 ); + + RK[5] = RK[1] ^ RK[4]; + RK[6] = RK[2] ^ RK[5]; + RK[7] = RK[3] ^ RK[6]; + } + break; + + case 12: + + for( i = 0; i < 8; i++, RK += 6 ) + { + RK[6] = RK[0] ^ RCON[i] ^ + ( (unsigned long) FSb[ ( RK[5] >> 8 ) & 0xFF ] ) ^ + ( (unsigned long) FSb[ ( RK[5] >> 16 ) & 0xFF ] << 8 ) ^ + ( (unsigned long) FSb[ ( RK[5] >> 24 ) & 0xFF ] << 16 ) ^ + ( (unsigned long) FSb[ ( RK[5] ) & 0xFF ] << 24 ); + + RK[7] = RK[1] ^ RK[6]; + RK[8] = RK[2] ^ RK[7]; + RK[9] = RK[3] ^ RK[8]; + RK[10] = RK[4] ^ RK[9]; + RK[11] = RK[5] ^ RK[10]; + } + break; + + case 14: + + for( i = 0; i < 7; i++, RK += 8 ) + { + RK[8] = RK[0] ^ RCON[i] ^ + ( (unsigned long) FSb[ ( RK[7] >> 8 ) & 0xFF ] ) ^ + ( (unsigned long) FSb[ ( RK[7] >> 16 ) & 0xFF ] << 8 ) ^ + ( (unsigned long) FSb[ ( RK[7] >> 24 ) & 0xFF ] << 16 ) ^ + ( (unsigned long) FSb[ ( RK[7] ) & 0xFF ] << 24 ); + + RK[9] = RK[1] ^ RK[8]; + RK[10] = RK[2] ^ RK[9]; + RK[11] = RK[3] ^ RK[10]; + + RK[12] = RK[4] ^ + ( (unsigned long) FSb[ ( RK[11] ) & 0xFF ] ) ^ + ( (unsigned long) FSb[ ( RK[11] >> 8 ) & 0xFF ] << 8 ) ^ + ( (unsigned long) FSb[ ( RK[11] >> 16 ) & 0xFF ] << 16 ) ^ + ( (unsigned long) FSb[ ( RK[11] >> 24 ) & 0xFF ] << 24 ); + + RK[13] = RK[5] ^ RK[12]; + RK[14] = RK[6] ^ RK[13]; + RK[15] = RK[7] ^ RK[14]; + } + break; + + default: + + break; + } + + return( 0 ); +} + +/* + * AES key schedule (decryption) + */ +int aes_setkey_dec( aes_context *ctx, const unsigned char *key, unsigned int keysize ) +{ + int i, j; + aes_context cty; + unsigned long *RK; + unsigned long *SK; + int ret; + + switch( keysize ) + { + case 128: ctx->nr = 10; break; + case 192: ctx->nr = 12; break; + case 256: ctx->nr = 14; break; + default : return( POLARSSL_ERR_AES_INVALID_KEY_LENGTH ); + } + + ctx->rk = RK = ctx->buf; + + ret = aes_setkey_enc( &cty, key, keysize ); + if( ret != 0 ) + return( ret ); + + SK = cty.rk + cty.nr * 4; + + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + + for( i = ctx->nr - 1, SK -= 8; i > 0; i--, SK -= 8 ) + { + for( j = 0; j < 4; j++, SK++ ) + { + *RK++ = RT0[ FSb[ ( *SK ) & 0xFF ] ] ^ + RT1[ FSb[ ( *SK >> 8 ) & 0xFF ] ] ^ + RT2[ FSb[ ( *SK >> 16 ) & 0xFF ] ] ^ + RT3[ FSb[ ( *SK >> 24 ) & 0xFF ] ]; + } + } + + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + + memset( &cty, 0, sizeof( aes_context ) ); + + return( 0 ); +} + +#define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ +{ \ + X0 = *RK++ ^ FT0[ ( Y0 ) & 0xFF ] ^ \ + FT1[ ( Y1 >> 8 ) & 0xFF ] ^ \ + FT2[ ( Y2 >> 16 ) & 0xFF ] ^ \ + FT3[ ( Y3 >> 24 ) & 0xFF ]; \ + \ + X1 = *RK++ ^ FT0[ ( Y1 ) & 0xFF ] ^ \ + FT1[ ( Y2 >> 8 ) & 0xFF ] ^ \ + FT2[ ( Y3 >> 16 ) & 0xFF ] ^ \ + FT3[ ( Y0 >> 24 ) & 0xFF ]; \ + \ + X2 = *RK++ ^ FT0[ ( Y2 ) & 0xFF ] ^ \ + FT1[ ( Y3 >> 8 ) & 0xFF ] ^ \ + FT2[ ( Y0 >> 16 ) & 0xFF ] ^ \ + FT3[ ( Y1 >> 24 ) & 0xFF ]; \ + \ + X3 = *RK++ ^ FT0[ ( Y3 ) & 0xFF ] ^ \ + FT1[ ( Y0 >> 8 ) & 0xFF ] ^ \ + FT2[ ( Y1 >> 16 ) & 0xFF ] ^ \ + FT3[ ( Y2 >> 24 ) & 0xFF ]; \ +} + +#define AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ +{ \ + X0 = *RK++ ^ RT0[ ( Y0 ) & 0xFF ] ^ \ + RT1[ ( Y3 >> 8 ) & 0xFF ] ^ \ + RT2[ ( Y2 >> 16 ) & 0xFF ] ^ \ + RT3[ ( Y1 >> 24 ) & 0xFF ]; \ + \ + X1 = *RK++ ^ RT0[ ( Y1 ) & 0xFF ] ^ \ + RT1[ ( Y0 >> 8 ) & 0xFF ] ^ \ + RT2[ ( Y3 >> 16 ) & 0xFF ] ^ \ + RT3[ ( Y2 >> 24 ) & 0xFF ]; \ + \ + X2 = *RK++ ^ RT0[ ( Y2 ) & 0xFF ] ^ \ + RT1[ ( Y1 >> 8 ) & 0xFF ] ^ \ + RT2[ ( Y0 >> 16 ) & 0xFF ] ^ \ + RT3[ ( Y3 >> 24 ) & 0xFF ]; \ + \ + X3 = *RK++ ^ RT0[ ( Y3 ) & 0xFF ] ^ \ + RT1[ ( Y2 >> 8 ) & 0xFF ] ^ \ + RT2[ ( Y1 >> 16 ) & 0xFF ] ^ \ + RT3[ ( Y0 >> 24 ) & 0xFF ]; \ +} + +/* + * AES-ECB block encryption/decryption + */ +int aes_crypt_ecb( aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ) +{ + int i; + unsigned long *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3; + + RK = ctx->rk; + + GET_ULONG_LE( X0, input, 0 ); X0 ^= *RK++; + GET_ULONG_LE( X1, input, 4 ); X1 ^= *RK++; + GET_ULONG_LE( X2, input, 8 ); X2 ^= *RK++; + GET_ULONG_LE( X3, input, 12 ); X3 ^= *RK++; + + if( mode == AES_DECRYPT ) + { + for( i = (ctx->nr >> 1) - 1; i > 0; i-- ) + { + AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); + AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); + } + + AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); + + X0 = *RK++ ^ \ + ( (unsigned long) RSb[ ( Y0 ) & 0xFF ] ) ^ + ( (unsigned long) RSb[ ( Y3 >> 8 ) & 0xFF ] << 8 ) ^ + ( (unsigned long) RSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^ + ( (unsigned long) RSb[ ( Y1 >> 24 ) & 0xFF ] << 24 ); + + X1 = *RK++ ^ \ + ( (unsigned long) RSb[ ( Y1 ) & 0xFF ] ) ^ + ( (unsigned long) RSb[ ( Y0 >> 8 ) & 0xFF ] << 8 ) ^ + ( (unsigned long) RSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^ + ( (unsigned long) RSb[ ( Y2 >> 24 ) & 0xFF ] << 24 ); + + X2 = *RK++ ^ \ + ( (unsigned long) RSb[ ( Y2 ) & 0xFF ] ) ^ + ( (unsigned long) RSb[ ( Y1 >> 8 ) & 0xFF ] << 8 ) ^ + ( (unsigned long) RSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^ + ( (unsigned long) RSb[ ( Y3 >> 24 ) & 0xFF ] << 24 ); + + X3 = *RK++ ^ \ + ( (unsigned long) RSb[ ( Y3 ) & 0xFF ] ) ^ + ( (unsigned long) RSb[ ( Y2 >> 8 ) & 0xFF ] << 8 ) ^ + ( (unsigned long) RSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^ + ( (unsigned long) RSb[ ( Y0 >> 24 ) & 0xFF ] << 24 ); + } + else /* AES_ENCRYPT */ + { + for( i = (ctx->nr >> 1) - 1; i > 0; i-- ) + { + AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); + AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); + } + + AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); + + X0 = *RK++ ^ \ + ( (unsigned long) FSb[ ( Y0 ) & 0xFF ] ) ^ + ( (unsigned long) FSb[ ( Y1 >> 8 ) & 0xFF ] << 8 ) ^ + ( (unsigned long) FSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^ + ( (unsigned long) FSb[ ( Y3 >> 24 ) & 0xFF ] << 24 ); + + X1 = *RK++ ^ \ + ( (unsigned long) FSb[ ( Y1 ) & 0xFF ] ) ^ + ( (unsigned long) FSb[ ( Y2 >> 8 ) & 0xFF ] << 8 ) ^ + ( (unsigned long) FSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^ + ( (unsigned long) FSb[ ( Y0 >> 24 ) & 0xFF ] << 24 ); + + X2 = *RK++ ^ \ + ( (unsigned long) FSb[ ( Y2 ) & 0xFF ] ) ^ + ( (unsigned long) FSb[ ( Y3 >> 8 ) & 0xFF ] << 8 ) ^ + ( (unsigned long) FSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^ + ( (unsigned long) FSb[ ( Y1 >> 24 ) & 0xFF ] << 24 ); + + X3 = *RK++ ^ \ + ( (unsigned long) FSb[ ( Y3 ) & 0xFF ] ) ^ + ( (unsigned long) FSb[ ( Y0 >> 8 ) & 0xFF ] << 8 ) ^ + ( (unsigned long) FSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^ + ( (unsigned long) FSb[ ( Y2 >> 24 ) & 0xFF ] << 24 ); + } + + PUT_ULONG_LE( X0, output, 0 ); + PUT_ULONG_LE( X1, output, 4 ); + PUT_ULONG_LE( X2, output, 8 ); + PUT_ULONG_LE( X3, output, 12 ); + + return( 0 ); +} + +/* + * AES-CBC buffer encryption/decryption + */ +int aes_crypt_cbc( aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + int i; + unsigned char temp[16]; + + if( length % 16 ) + return( POLARSSL_ERR_AES_INVALID_INPUT_LENGTH ); + + if( mode == AES_DECRYPT ) + { + while( length > 0 ) + { + memcpy( temp, input, 16 ); + aes_crypt_ecb( ctx, mode, input, output ); + + for( i = 0; i < 16; i++ ) + output[i] = (unsigned char)( output[i] ^ iv[i] ); + + memcpy( iv, temp, 16 ); + + input += 16; + output += 16; + length -= 16; + } + } + else + { + while( length > 0 ) + { + for( i = 0; i < 16; i++ ) + output[i] = (unsigned char)( input[i] ^ iv[i] ); + + aes_crypt_ecb( ctx, mode, output, output ); + memcpy( iv, output, 16 ); + + input += 16; + output += 16; + length -= 16; + } + } + + return( 0 ); +} + +/* + * AES-CTR buffer encryption/decryption + */ +int aes_crypt_ctr( aes_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[16], + unsigned char stream_block[16], + const unsigned char *input, + unsigned char *output ) +{ + int c, i, cb; + size_t n = *nc_off; + + while( length-- ) + { + if( n == 0 ) { + aes_crypt_ecb( ctx, AES_ENCRYPT, nonce_counter, stream_block ); + + i = 15; + do { + nonce_counter[i]++; + cb = nonce_counter[i] == 0; + } while( i-- && cb ); + + } + c = *input++; + *output++ = (unsigned char)( c ^ stream_block[n] ); + + n = (n + 1) & 0x0F; + } + + *nc_off = n; + + return( 0 ); +} + +/* AES-CMAC */ + +int aes_crypt_ctr_xor( aes_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[16], + unsigned char stream_block[16], + const unsigned char *input, + unsigned char *output , + size_t len_start_from) +{ + char bkp_riv[0x10]; + memcpy(bkp_riv, nonce_counter, 0x10); + int c, i, cb; + size_t n = *nc_off; + + while( length--) + { + if( n == 0 ) { + aes_crypt_ecb( ctx, AES_ENCRYPT, nonce_counter, stream_block ); + + i = 15; + do { + nonce_counter[i]++; + cb = nonce_counter[i] == 0; + } while( i-- && cb ); + + } + if(len_start_from==0) + { + c = *input++; + *output++ = (unsigned char)( c ^ stream_block[n] ); + } + else + { + length++; + len_start_from--; + } + + n = (n + 1) & 0x0F; + } + + *nc_off = n; + + memcpy(nonce_counter, bkp_riv, 0x10); + return( 0 ); +} + +#include + +unsigned char const_Rb[16] = { + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87 + +}; + +unsigned char const_Zero[16] = { + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + +}; + + + +void leftshift_onebit(unsigned char *input, unsigned char *output) + +{ + + int i; + + unsigned char overflow = 0; + + + + for (i = 15; i >= 0; i--) + + { + + output[i] = input[i] << 1; + + output[i] |= overflow; + + overflow = (input[i] & 0x80) ? 1 : 0; + + } + +} + + + +void xor_128(unsigned char *a, unsigned char *b, unsigned char *out) + +{ + + int i; + + for (i = 0; i < 16; i++) + + out[i] = a[i] ^ b[i]; + +} + + + +void generate_subkey(aes_context *ctx, unsigned char *K1, unsigned char *K2) + +{ + + unsigned char L[16]; + + unsigned char Z[16]; + + unsigned char tmp[16]; + + + + int i; + + for (i = 0; i < 16; i++) Z[i] = 0; + + + + aes_crypt_ecb(ctx, AES_ENCRYPT, Z, L); + + + + if ((L[0] & 0x80) == 0) + + { + + leftshift_onebit(L,K1); + + } else { + + leftshift_onebit(L,tmp); + + xor_128(tmp,const_Rb,K1); + + } + + + + if ((K1[0] & 0x80) == 0) + + { + + leftshift_onebit(K1,K2); + + } else { + + leftshift_onebit(K1,tmp); + + xor_128(tmp,const_Rb,K2); + + } + +} + + + +void padding (unsigned char *lastb, unsigned char *pad, uint64_t length) + +{ + + uint64_t i; + + for (i = 0; i < 16; i++) + + { + + if (i < length) + + pad[i] = lastb[i]; + + else if (i == length) + + pad[i] = 0x80; + + else + + pad[i] = 0x00; + + } + +} + + + +void aes_cmac(aes_context *ctx, uint64_t length, unsigned char *input, unsigned char *output) + +{ + + unsigned char X[16], Y[16], M_last[16], padded[16]; + + unsigned char K1[16], K2[16]; + + uint64_t n, i, flag; + + generate_subkey(ctx, K1, K2); + + + + n = (length + 15) / 16; + + if (n == 0) + + { + + n = 1; + + flag = 0; + + } else { + + if ((length % 16) == 0) + + flag = 1; + + else + + flag = 0; + + } + + + + if (flag) + + { + + xor_128(&input[16 * (n - 1)], K1, M_last); + + } else { + + padding(&input[16 * (n - 1)], padded, length % 16); + + xor_128(padded, K2, M_last); + + } + + + + for (i = 0; i < 16; i++) X[i] = 0; + + for (i = 0; i < n - 1; i++) + + { + + xor_128(X, &input[16*i], Y); + + aes_crypt_ecb(ctx, AES_ENCRYPT, Y, X); + + } + + + + xor_128(X,M_last,Y); + + aes_crypt_ecb(ctx, AES_ENCRYPT, Y, X); + + + + for (i = 0; i < 16; i++) + + output[i] = X[i]; + +} diff --git a/tools/4/source/src/aes.h b/tools/4/source/src/aes.h new file mode 100644 index 0000000..36e8324 --- /dev/null +++ b/tools/4/source/src/aes.h @@ -0,0 +1,159 @@ +/** + * \file aes.h + * + * \brief AES block cipher + * + * Copyright (C) 2006-2010, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_AES_H +#define POLARSSL_AES_H + +#include + +#define AES_ENCRYPT 1 +#define AES_DECRYPT 0 + +#define POLARSSL_ERR_AES_INVALID_KEY_LENGTH -0x0020 /**< Invalid key length. */ +#define POLARSSL_ERR_AES_INVALID_INPUT_LENGTH -0x0022 /**< Invalid data input length. */ + +/** + * \brief AES context structure + */ +typedef struct +{ + int nr; /*!< number of rounds */ + unsigned long *rk; /*!< AES round keys */ + unsigned long buf[68]; /*!< unaligned data */ +} +aes_context; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief AES key schedule (encryption) + * + * \param ctx AES context to be initialized + * \param key encryption key + * \param keysize must be 128, 192 or 256 + * + * \return 0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH + */ +int aes_setkey_enc( aes_context *ctx, const unsigned char *key, unsigned int keysize ); + +/** + * \brief AES key schedule (decryption) + * + * \param ctx AES context to be initialized + * \param key decryption key + * \param keysize must be 128, 192 or 256 + * + * \return 0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH + */ +int aes_setkey_dec( aes_context *ctx, const unsigned char *key, unsigned int keysize ); + +/** + * \brief AES-ECB block encryption/decryption + * + * \param ctx AES context + * \param mode AES_ENCRYPT or AES_DECRYPT + * \param input 16-byte input block + * \param output 16-byte output block + * + * \return 0 if successful + */ +int aes_crypt_ecb( aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ); + +/** + * \brief AES-CBC buffer encryption/decryption + * Length should be a multiple of the block + * size (16 bytes) + * + * \param ctx AES context + * \param mode AES_ENCRYPT or AES_DECRYPT + * \param length length of the input data + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \return 0 if successful, or POLARSSL_ERR_AES_INVALID_INPUT_LENGTH + */ +int aes_crypt_cbc( aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); + +/* + * \brief AES-CTR buffer encryption/decryption + * + * Warning: You have to keep the maximum use of your counter in mind! + * + * Note: Due to the nature of CTR you should use the same key schedule for + * both encryption and decryption. So a context initialized with + * aes_setkey_enc() for both AES_ENCRYPT and AES_DECRYPT. + * + * \param length The length of the data + * \param nc_off The offset in the current stream_block (for resuming + * within current cipher stream). The offset pointer to + * should be 0 at the start of a stream. + * \param nonce_counter The 128-bit nonce and counter. + * \param stream_block The saved stream-block for resuming. Is overwritten + * by the function. + * \param input The input data stream + * \param output The output data stream + * + * \return 0 if successful + */ +int aes_crypt_ctr( aes_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[16], + unsigned char stream_block[16], + const unsigned char *input, + unsigned char *output ); + + +int aes_crypt_ctr_xor( aes_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[16], + unsigned char stream_block[16], + const unsigned char *input, + unsigned char *output , + size_t len_start_from); + + + +#include +void aes_cmac(aes_context *ctx, uint64_t length, unsigned char *input, unsigned char *output); + +#ifdef __cplusplus +} +#endif + +#endif /* aes.h */ diff --git a/tools/4/source/src/aes_omac.cpp b/tools/4/source/src/aes_omac.cpp new file mode 100644 index 0000000..eb6982a --- /dev/null +++ b/tools/4/source/src/aes_omac.cpp @@ -0,0 +1,55 @@ +#include "types.h" +#include "aes.h" + +void _gf_mul(unsigned char *pad) +{ + unsigned int i; + unsigned cxor = (pad[0] & 0x80) ? 0x87 : 0; + + for(i = 0; i < 15; i++) + pad[i] = (pad[i] << 1) | (pad[i + 1] >> 7); + pad[15] = (pad[15] << 1) ^ cxor; +} + +void aes_omac1(u8 *digest, u8 *input, u32 length, u8 *key, u32 keybits) +{ + u32 i, j; + u32 overflow; + aes_context ctxt; + unsigned char buffer1[16], buffer2[16], dbuf[16]; + + memset(buffer1, 0, 16); + + aes_setkey_enc(&ctxt, key, keybits); + + aes_crypt_ecb(&ctxt, AES_ENCRYPT, buffer1, buffer2); + _gf_mul(buffer2); + + if(length > 16) + { + for(i = 0; i < length - 16; i += 16) + { + for(j = 0; j < 16; j++) + dbuf[j] = buffer1[j] ^ input[i + j]; + aes_crypt_ecb(&ctxt, AES_ENCRYPT, dbuf, buffer1); + } + } + + overflow = length & 0xf; + if(length % 16 == 0) + overflow = 16; + + memset(dbuf, 0, 16); + memcpy(dbuf, &(input[i]), overflow); + + if(overflow != 16) + { + dbuf[overflow] = 0x80; + _gf_mul(buffer2); + } + + for(i = 0; i < 16; i++) + dbuf[i] ^= buffer1[i] ^ buffer2[i]; + + aes_crypt_ecb(&ctxt, AES_ENCRYPT, dbuf, digest); +} diff --git a/tools/4/source/src/aes_omac.h b/tools/4/source/src/aes_omac.h new file mode 100644 index 0000000..686337c --- /dev/null +++ b/tools/4/source/src/aes_omac.h @@ -0,0 +1,10 @@ +#ifndef _AES_OMAC_H_ +#define _AES_OMAC_H_ + +#include "types.h" + +#define AES_OMAC1_DIGEST_SIZE 0x10 + +void aes_omac1(u8 *digest, u8 *input, u32 length, u8 *key, u32 keybits); + +#endif diff --git a/tools/4/source/src/main.cpp b/tools/4/source/src/main.cpp new file mode 100644 index 0000000..21b8f9c --- /dev/null +++ b/tools/4/source/src/main.cpp @@ -0,0 +1,1782 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define IDPS_KEYBITS 128 +#define ACT_DAT_KEYBITS 128 +#define RIF_KEYBITS 128 +#define RAP_KEYBITS 128 +#include "aes.h" +#include "util.h" +#include "sha1.h" +#include "pkg2zip_aes.h" + +#ifdef _WIN32 +#define fseek _fseeki64 +#define ftell _ftelli64 +#endif + +#define _LARGEFILE64_SOURCE +#define _FILE_OFFSET_BITS 64 + +uint8_t p_fixed[20]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x01,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; +uint8_t a_fixed[20]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x01,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC}; +uint8_t b_fixed[20]={0xA6,0x8B,0xED,0xC3,0x34,0x18,0x02,0x9C,0x1D,0x3C,0xE3,0x3B,0x9A,0x32,0x1F,0xCC,0xBB,0x9E,0x0F,0x0B}; +uint8_t n_fixed[21]={0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xB5,0xAE,0x3C,0x52,0x3E,0x63,0x94,0x4F,0x21,0x27}; +uint8_t gx_fixed[20]={0x12,0x8E,0xC4,0x25,0x64,0x87,0xFD,0x8F,0xDF,0x64,0xE2,0x43,0x7B,0xC0,0xA1,0xF6,0xD5,0xAF,0xDE,0x2C}; +uint8_t gy_fixed[20]={0x59,0x58,0x55,0x7E,0xB1,0xDB,0x00,0x12,0x60,0x42,0x55,0x24,0xDB,0xC3,0x79,0xD5,0xAC,0x5F,0x4A,0xDF}; + +uint8_t ec_p_nm[20]={0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x4A, 0x51, 0xC3, 0xAD, 0xC1, 0x9C, 0x6B, 0xB0, 0xDE, 0xD8}; +uint8_t ec_a_nm[20]={0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF ,0xFF ,0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +uint8_t ec_b_nm[20]={0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03}; +uint8_t ec_G_nm[40]={0xED, 0x71, 0x3B, 0xDA, 0x9B, 0x78, 0x02, 0x70, 0x20, 0x9B, 0x1D, 0xBC, 0x84, 0x3F, 0x5E, 0x09, 0x2A, 0x50, 0x21, 0xD3, 0xA6, 0xA7, 0xAA, 0x81, 0x4E, 0x24, 0xFF, 0xED, 0x9F, 0xBD, 0xAA, 0xDB, 0x24, 0x3C, 0x86, 0x2A, 0x53, 0xA0, 0xB5, 0x20}; +uint8_t ec_N_nm[20]={0x59, 0x74, 0x12, 0x3C, 0xCB, 0xE7, 0xFD, 0x63, 0xE2, 0xC3, 0x1C, 0xC4, 0x65, 0xCD, 0xE0, 0x33, 0x44, 0x61 ,0xF0, 0xF4}; + +//uint8_t ec_k[21]={0x00,0x42,0x75,0x72,0x6E,0x20,0x49,0x6E,0x20,0x48,0x65,0x6C,0x6C,0x20,0x53,0x6F,0x6E,0x79,0x20,0x21,0x21}; +//uint8_t ec_Q_nm[40]={0x7C,0xFD,0x88,0x8E,0xE9,0xDD,0x5F,0x60,0x30,0xA5,0xC1,0xC0,0xA2,0xF9,0x08,0x4A,0x74,0xB1,0x32,0x87,0x33,0x52,0x68,0x11,0xCF,0xBA,0x95,0x35,0x06,0xE4,0x41,0x11,0xF0,0xE2,0xD6,0xF2,0xD1,0x91,0x3E,0x69}; + +uint8_t ec_k[21]={0x00,0xbf,0x21,0x22,0x4b,0x04,0x1f,0x29,0x54,0x9d,0xb2,0x5e,0x9a,0xad,0xe1,0x9e,0x72,0x0a,0x1f,0xe0,0xf1}; +uint8_t ec_Q_nm[40]={0x94,0x8D,0xA1,0x3E,0x8C,0xAF,0xD5,0xBA,0x0E,0x90,0xCE,0x43,0x44,0x61,0xBB,0x32,0x7F,0xE7,0xE0,0x80,0x47,0x5E,0xAA,0x0A,0xD3,0xAD,0x4F,0x5B,0x62,0x47,0xA7,0xFD,0xA8,0x6D,0xF6,0x97,0x90,0x19,0x67,0x73}; + +struct point { + u8 x[20]; + u8 y[20]; +}; + + +static uint8_t ec_p[20]; +static uint8_t ec_a[20]; +static uint8_t ec_b[20]; +static point ec_G; +static point ec_Q; +static uint8_t ec_N[21]; + +#define MT_N 624 +#define MT_M 397 +#define MT_MATRIX_A 0x9908b0df +#define MT_UPPER_MASK 0x80000000 +#define MT_LOWER_MASK 0x7fffffff + +/*! Mersenne-Twister 19937 context. */ +typedef struct _mt19937_ctxt +{ + /*! State. */ + unsigned int state[MT_N]; + /*! Index. */ + unsigned int idx; +} mt19937_ctxt_t; + +void mt19937_init(mt19937_ctxt_t *ctxt, unsigned int seed) +{ + ctxt->state[0] = seed; + + for(ctxt->idx = 1; ctxt->idx < MT_N; ctxt->idx++) + ctxt->state[ctxt->idx] = (1812433253 * (ctxt->state[ctxt->idx - 1] ^ (ctxt->state[ctxt->idx - 1] >> 30)) + ctxt->idx); + + ctxt->idx = MT_M + 1; +} + +unsigned int mt19937_update(mt19937_ctxt_t *ctxt) +{ + unsigned int y, k; + static unsigned int mag01[2] = {0, MT_MATRIX_A}; + + if(ctxt->idx >= MT_N) + { + for(k = 0; k < MT_N - MT_M; k++) + { + y = (ctxt->state[k] & MT_UPPER_MASK) | + (ctxt->state[k + 1] & MT_LOWER_MASK); + ctxt->state[k] = ctxt->state[k + MT_M] ^ (y >> 1) ^ mag01[y & 1]; + } + + for(; k < MT_N - 1; k++) + { + y = (ctxt->state[k] & MT_UPPER_MASK) | + (ctxt->state[k + 1] & MT_LOWER_MASK); + ctxt->state[k] = ctxt->state[k + (MT_M - MT_N)] ^ (y >> 1) ^ mag01[y & 1]; + } + + y = (ctxt->state[MT_N - 1] & MT_UPPER_MASK) | + (ctxt->state[0] & MT_LOWER_MASK); + ctxt->state[MT_N - 1] = ctxt->state[MT_M - 1] ^ (y >> 1) ^ mag01[y & 1]; + + ctxt->idx = 0; + } + + y = ctxt->state[ctxt->idx++]; + + y ^= (y >> 11); + y ^= (y << 7) & 0x9d2c5680UL; + y ^= (y << 15) & 0xefc60000UL; + y ^= (y >> 18); + + return y; +} + +static mt19937_ctxt_t _mt19937_ctxt; +static BOOL _mt_init = FALSE; + +u8 _get_rand_byte() +{ + if(_mt_init == FALSE) + { + _mt_init = TRUE; + mt19937_init(&_mt19937_ctxt, clock()); + } + + return (u8)(mt19937_update(&_mt19937_ctxt) & 0xFF); +} + +void _fill_rand_bytes(u8 *dst, u32 len) +{ + u32 i; + + for(i = 0; i < len; i++) + dst[i] = _get_rand_byte(); +} + +static void memcpy_inv(u8 *dst, u8 *src, u32 len) +{ + u32 j; + + for (j = 0; j < len; j++) + dst[j] = ~src[j]; +} + +void bn_print(char *name, u8 *a, u32 n) +{ + u32 i; + + printf("%s = ", name); + + for (i = 0; i < n; i++) + printf("%02x", a[i]); + + printf("\n"); +} + +static void bn_zero(u8 *d, u32 n) +{ + memset(d, 0, n); +} + +void bn_copy(u8 *d, u8 *a, u32 n) +{ + memcpy(d, a, n); +} + +int bn_compare(u8 *a, u8 *b, u32 n) +{ + u32 i; + + for (i = 0; i < n; i++) { + if (a[i] < b[i]) + return -1; + if (a[i] > b[i]) + return 1; + } + + return 0; +} + +static u8 bn_add_1(u8 *d, u8 *a, u8 *b, u32 n) +{ + u32 i; + u32 dig; + u8 c; + + c = 0; + for (i = n - 1; i < n; i--) { + dig = a[i] + b[i] + c; + c = dig >> 8; + d[i] = dig; + } + + return c; +} + +static u8 bn_sub_1(u8 *d, u8 *a, u8 *b, u32 n) +{ + u32 i; + u32 dig; + u8 c; + + c = 1; + for (i = n - 1; i < n; i--) { + dig = a[i] + 255 - b[i] + c; + c = dig >> 8; + d[i] = dig; + } + + return 1 - c; +} + +void bn_reduce(u8 *d, u8 *N, u32 n) +{ + if (bn_compare(d, N, n) >= 0) + bn_sub_1(d, d, N, n); +} + +void bn_add(u8 *d, u8 *a, u8 *b, u8 *N, u32 n) +{ + if (bn_add_1(d, a, b, n)) + bn_sub_1(d, d, N, n); + + bn_reduce(d, N, n); +} + +void bn_sub(u8 *d, u8 *a, u8 *b, u8 *N, u32 n) +{ + if (bn_sub_1(d, a, b, n)) + bn_add_1(d, d, N, n); +} + +static const u8 inv256[0x80] = { + 0x01, 0xab, 0xcd, 0xb7, 0x39, 0xa3, 0xc5, 0xef, + 0xf1, 0x1b, 0x3d, 0xa7, 0x29, 0x13, 0x35, 0xdf, + 0xe1, 0x8b, 0xad, 0x97, 0x19, 0x83, 0xa5, 0xcf, + 0xd1, 0xfb, 0x1d, 0x87, 0x09, 0xf3, 0x15, 0xbf, + 0xc1, 0x6b, 0x8d, 0x77, 0xf9, 0x63, 0x85, 0xaf, + 0xb1, 0xdb, 0xfd, 0x67, 0xe9, 0xd3, 0xf5, 0x9f, + 0xa1, 0x4b, 0x6d, 0x57, 0xd9, 0x43, 0x65, 0x8f, + 0x91, 0xbb, 0xdd, 0x47, 0xc9, 0xb3, 0xd5, 0x7f, + 0x81, 0x2b, 0x4d, 0x37, 0xb9, 0x23, 0x45, 0x6f, + 0x71, 0x9b, 0xbd, 0x27, 0xa9, 0x93, 0xb5, 0x5f, + 0x61, 0x0b, 0x2d, 0x17, 0x99, 0x03, 0x25, 0x4f, + 0x51, 0x7b, 0x9d, 0x07, 0x89, 0x73, 0x95, 0x3f, + 0x41, 0xeb, 0x0d, 0xf7, 0x79, 0xe3, 0x05, 0x2f, + 0x31, 0x5b, 0x7d, 0xe7, 0x69, 0x53, 0x75, 0x1f, + 0x21, 0xcb, 0xed, 0xd7, 0x59, 0xc3, 0xe5, 0x0f, + 0x11, 0x3b, 0x5d, 0xc7, 0x49, 0x33, 0x55, 0xff, +}; + +static void bn_mon_muladd_dig(u8 *d, u8 *a, u8 b, u8 *N, u32 n) +{ + u32 dig; + u32 i; + + u8 z = -(d[n-1] + a[n-1]*b) * inv256[N[n-1]/2]; + + dig = d[n-1] + a[n-1]*b + N[n-1]*z; + dig >>= 8; + + for (i = n - 2; i < n; i--) { + dig += d[i] + a[i]*b + N[i]*z; + d[i+1] = dig; + dig >>= 8; + } + + d[0] = dig; + dig >>= 8; + + if (dig) + bn_sub_1(d, d, N, n); + + bn_reduce(d, N, n); +} + +void bn_mon_mul(u8 *d, u8 *a, u8 *b, u8 *N, u32 n) +{ + u8 t[512]; + u32 i; + + bn_zero(t, n); + + for (i = n - 1; i < n; i--) + bn_mon_muladd_dig(t, a, b[i], N, n); + + bn_copy(d, t, n); +} + +void bn_to_mon(u8 *d, u8 *N, u32 n) +{ + u32 i; + + for (i = 0; i < 8*n; i++) + bn_add(d, d, d, N, n); +} + +void bn_from_mon(u8 *d, u8 *N, u32 n) +{ + u8 t[512]; + + bn_zero(t, n); + t[n-1] = 1; + bn_mon_mul(d, d, t, N, n); +} + +static void bn_mon_exp(u8 *d, u8 *a, u8 *N, u32 n, u8 *e, u32 en) +{ + u8 t[512]; + u32 i; + u8 mask; + + bn_zero(d, n); + d[n-1] = 1; + bn_to_mon(d, N, n); + + for (i = 0; i < en; i++) + for (mask = 0x80; mask != 0; mask >>= 1) { + bn_mon_mul(t, d, d, N, n); + if ((e[i] & mask) != 0) + bn_mon_mul(d, t, a, N, n); + else + bn_copy(d, t, n); + } +} + +static void elt_copy(u8 *d, u8 *a) +{ + memcpy(d, a, 20); +} + +static void elt_zero(u8 *d) +{ + memset(d, 0, 20); +} + +static int elt_is_zero(u8 *d) +{ + u32 i; + + for (i = 0; i < 20; i++) + if (d[i] != 0) + return 0; + + return 1; +} + +static void elt_add(u8 *d, u8 *a, u8 *b) +{ + bn_add(d, a, b, ec_p, 20); +} + +static void elt_sub(u8 *d, u8 *a, u8 *b) +{ + bn_sub(d, a, b, ec_p, 20); +} + +static void elt_mul(u8 *d, u8 *a, u8 *b) +{ + bn_mon_mul(d, a, b, ec_p, 20); +} + +static void elt_square(u8 *d, u8 *a) +{ + elt_mul(d, a, a); +} + +void bn_mon_inv(u8 *d, u8 *a, u8 *N, u32 n) +{ + u8 t[512], s[512]; + + bn_zero(s, n); + s[n-1] = 2; + bn_sub_1(t, N, s, n); + bn_mon_exp(d, a, N, n, t, n); +} + +static void elt_inv(u8 *d, u8 *a) +{ + u8 s[20]; + elt_copy(s, a); + bn_mon_inv(d, s, ec_p, 20); +} + +static void point_to_mon(struct point *p) +{ + bn_to_mon(p->x, ec_p, 20); + bn_to_mon(p->y, ec_p, 20); +} + +static void point_from_mon(struct point *p) +{ + bn_from_mon(p->x, ec_p, 20); + bn_from_mon(p->y, ec_p, 20); +} + +static void point_zero(struct point *p) +{ + elt_zero(p->x); + elt_zero(p->y); +} + +static int point_is_zero(struct point *p) +{ + return elt_is_zero(p->x) && elt_is_zero(p->y); +} + +static void point_double(struct point *r, struct point *p) +{ + u8 s[20], t[20]; + struct point pp; + u8 *px, *py, *rx, *ry; + + pp = *p; + + px = pp.x; + py = pp.y; + rx = r->x; + ry = r->y; + + if (elt_is_zero(py)) { + point_zero(r); + return; + } + + elt_square(t, px); // t = px*px + elt_add(s, t, t); // s = 2*px*px + elt_add(s, s, t); // s = 3*px*px + elt_add(s, s, ec_a); // s = 3*px*px + a + elt_add(t, py, py); // t = 2*py + elt_inv(t, t); // t = 1/(2*py) + elt_mul(s, s, t); // s = (3*px*px+a)/(2*py) + + elt_square(rx, s); // rx = s*s + elt_add(t, px, px); // t = 2*px + elt_sub(rx, rx, t); // rx = s*s - 2*px + + elt_sub(t, px, rx); // t = -(rx-px) + elt_mul(ry, s, t); // ry = -s*(rx-px) + elt_sub(ry, ry, py); // ry = -s*(rx-px) - py +} + +static void point_add(struct point *r, struct point *p, struct point *q) +{ + u8 s[20], t[20], u[20]; + u8 *px, *py, *qx, *qy, *rx, *ry; + struct point pp, qq; + + pp = *p; + qq = *q; + + px = pp.x; + py = pp.y; + qx = qq.x; + qy = qq.y; + rx = r->x; + ry = r->y; + + if (point_is_zero(&pp)) { + elt_copy(rx, qx); + elt_copy(ry, qy); + return; + } + + if (point_is_zero(&qq)) { + elt_copy(rx, px); + elt_copy(ry, py); + return; + } + + elt_sub(u, qx, px); + + if (elt_is_zero(u)) { + elt_sub(u, qy, py); + if (elt_is_zero(u)) + point_double(r, &pp); + else + point_zero(r); + + return; + } + + elt_inv(t, u); // t = 1/(qx-px) + elt_sub(u, qy, py); // u = qy-py + elt_mul(s, t, u); // s = (qy-py)/(qx-px) + + elt_square(rx, s); // rx = s*s + elt_add(t, px, qx); // t = px+qx + elt_sub(rx, rx, t); // rx = s*s - (px+qx) + + elt_sub(t, px, rx); // t = -(rx-px) + elt_mul(ry, s, t); // ry = -s*(rx-px) + elt_sub(ry, ry, py); // ry = -s*(rx-px) - py +} + +static void point_mul(struct point *d, u8 *a, struct point *b) // a is bignum +{ + u32 i; + u8 mask; + + point_zero(d); + + for (i = 0; i < 21; i++) + for (mask = 0x80; mask != 0; mask >>= 1) { + point_double(d, d); + if ((a[i] & mask) != 0) + point_add(d, d, b); + } +} + +static void generate_ecdsa(u8 *R, u8 *S, u8 *k, u8 *hash) +{ + u8 e[21]; + u8 kk[21]; + u8 m[21]; + u8 minv[21]; + struct point mG; + + e[0] = 0; + memcpy(e + 1, hash, 20); + bn_reduce(e, ec_N, 21); + +try_again: + _fill_rand_bytes(m, 21); + m[0] = 0; + if (bn_compare(m, ec_N, 21) >= 0) + goto try_again; + + // R = (mG).x + point_mul(&mG, m, &ec_G); + point_from_mon(&mG); + R[0] = 0; + elt_copy(R+1, mG.x); + + // S = m**-1*(e + Rk) (mod N) + + bn_copy(kk, k, 21); + bn_reduce(kk, ec_N, 21); + bn_to_mon(m, ec_N, 21); + bn_to_mon(e, ec_N, 21); + bn_to_mon(R, ec_N, 21); + bn_to_mon(kk, ec_N, 21); + + bn_mon_mul(S, R, kk, ec_N, 21); + bn_add(kk, S, e, ec_N, 21); + bn_mon_inv(minv, m, ec_N, 21); + bn_mon_mul(S, minv, kk, ec_N, 21); + + bn_from_mon(R, ec_N, 21); + bn_from_mon(S, ec_N, 21); +} + +int set_vsh_curve(u8 *p, u8 *a, u8 *b, u8 *N, u8 *Gx, u8 *Gy) +{ + memcpy(p,p_fixed, 20); + memcpy(a, a_fixed, 20); + memcpy(b, b_fixed, 20); + memcpy(N, n_fixed, 21); + memcpy(Gx, gx_fixed, 20); + memcpy(Gy, gy_fixed, 20); + + return 0; +} + +int ecdsa_set_curve() +{ + set_vsh_curve(ec_p, ec_a, ec_b, ec_N, ec_G.x, ec_G.y); + bn_to_mon(ec_a, ec_p, 20); + bn_to_mon(ec_b, ec_p, 20); + + point_to_mon(&ec_G); + return 0; +} + +void ecdsa_set_pub() +{ + memcpy(ec_Q.x, ec_Q_nm,20); + memcpy(ec_Q.y, ec_Q_nm+20,20); + point_to_mon(&ec_Q); +} + +void ecdsa_set_priv() +{ + //ec_k already set +} + +static int check_ecdsa(struct point *Q, u8 *R, u8 *S, u8 *hash) +{ + u8 Sinv[21]; + u8 e[21]; + u8 w1[21], w2[21]; + struct point r1, r2; + u8 rr[21]; + + e[0] = 0; + memcpy(e + 1, hash, 20); + bn_reduce(e, ec_N, 21); + + bn_to_mon(R, ec_N, 21); + bn_to_mon(S, ec_N, 21); + bn_to_mon(e, ec_N, 21); + + bn_mon_inv(Sinv, S, ec_N, 21); + + bn_mon_mul(w1, e, Sinv, ec_N, 21); + bn_mon_mul(w2, R, Sinv, ec_N, 21); + + bn_from_mon(w1, ec_N, 21); + bn_from_mon(w2, ec_N, 21); + + point_mul(&r1, w1, &ec_G); + point_mul(&r2, w2, Q); + + point_add(&r1, &r1, &r2); + + point_from_mon(&r1); + + rr[0] = 0; + memcpy(rr + 1, r1.x, 20); + bn_reduce(rr, ec_N, 21); + + bn_from_mon(R, ec_N, 21); + bn_from_mon(S, ec_N, 21); + + return (bn_compare(rr, R, 21) == 0); +} + +void ecdsa_sign(u8 *hash, u8 *R, u8 *S) +{ + generate_ecdsa(R, S, ec_k, hash); +} + +//! Byte swap unsigned short +uint16_t swap_uint16( uint16_t val ) +{ + return (val << 8) | (val >> 8 ); +} + +//! Byte swap short +int16_t swap_int16( int16_t val ) +{ + return (val << 8) | ((val >> 8) & 0xFF); +} + +//! Byte swap unsigned int +uint32_t swap_uint32( uint32_t val ) +{ + val = ((val << 8) & 0xFF00FF00 ) | ((val >> 8) & 0xFF00FF ); + return (val << 16) | (val >> 16); +} + +//! Byte swap int +int32_t swap_int32( int32_t val ) +{ + val = ((val << 8) & 0xFF00FF00) | ((val >> 8) & 0xFF00FF ); + return (val << 16) | ((val >> 16) & 0xFFFF); +} + +int64_t swap_int64( int64_t val ) +{ + val = ((val << 8) & 0xFF00FF00FF00FF00ULL ) | ((val >> 8) & 0x00FF00FF00FF00FFULL ); + val = ((val << 16) & 0xFFFF0000FFFF0000ULL ) | ((val >> 16) & 0x0000FFFF0000FFFFULL ); + return (val << 32) | ((val >> 32) & 0xFFFFFFFFULL); +} + +uint64_t swap_uint64( uint64_t val ) +{ + val = ((val << 8) & 0xFF00FF00FF00FF00ULL ) | ((val >> 8) & 0x00FF00FF00FF00FFULL ); + val = ((val << 16) & 0xFFFF0000FFFF0000ULL ) | ((val >> 16) & 0x0000FFFF0000FFFFULL ); + return (val << 32) | (val >> 32); +} + +long long current_timestamp() { + struct timeval te; + gettimeofday(&te, NULL); // get current time + long long milliseconds = te.tv_sec*1000LL + te.tv_usec/1000; // calculate milliseconds + // printf("milliseconds: %lld\n", milliseconds); + return milliseconds; +} + +FILE *forge_act_dat() +{ + uint64_t timestamp=current_timestamp(); //today + uint32_t version=1; + version=swap_uint32(version); + uint32_t unk=2; + unk=swap_uint32(unk); + uint64_t psn_id=2; + psn_id=swap_uint64(psn_id); + timestamp=swap_uint64(timestamp); + FILE *fp=fopen("act.dat","wb"); + uint8_t *act_dat=new uint8_t[0x1038]; + memset(act_dat,0x11, 0x1038); + memcpy(act_dat, &version, 4); + memcpy(act_dat+4, &unk,4); + memcpy(act_dat+8, &psn_id, 8); + memcpy(act_dat+0x870, ×tamp, 8); + fwrite(act_dat, 0x1038,1,fp); + fclose(fp); + return fp=fopen("act.dat", "rb"); +} + +int read_act_dat_and_make_rif(char *path) +{ + char *content_id=(char *)malloc(256); + memset(content_id,0,256); + strcpy(content_id, path); + char *slash2 = strrchr (content_id, '\\'); + if (slash2 != NULL) + { + *slash2 = '\0'; + content_id=slash2+1; + } + + char *slash_rev = strrchr (content_id, '/'); + if (slash_rev != NULL) + { + *slash_rev = '\0'; + content_id=slash_rev+1; + } + + char *lastdot = strrchr (content_id, '.'); + if (lastdot != NULL) + *lastdot = '\0'; + + + uint8_t idps[0x10]; + aes_context aes_ctxt; + uint8_t idps_const[0x10]={0x5E,0x06,0xE0,0x4F,0xD9,0x4A,0x71,0xBF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}; + uint8_t rif_key_const[0x10]={0xDA,0x7D,0x4B,0x5E,0x49,0x9A,0x4F,0x53,0xB1,0xC1,0xA1,0x4A,0x74,0x84,0x44,0x3B}; + printf("reading:idps.hex\n"); + FILE *fp=fopen("idps.hex", "rb"); + if(!fp) + { + return -1; + } + fread(idps, 0x10, 1, fp); + fclose(fp); + uint8_t act_dat_key[0x10]; + uint8_t klicensee[0x10]; + uint8_t klicensee_enc_rif[0x10]; + uint8_t rap[0x10]; + uint64_t account_id; + //uint8_t rifkey[0x10]; + fp=fopen("act.dat","rb"); + if(!fp) + { + // fp=forge_act_dat(); + return -1; + } + printf("reading:act.dat\n"); + fseek(fp,0x8,SEEK_SET); + fread(&account_id, 8,1,fp);//skip aa account need + fseek(fp,0x10,SEEK_SET); + fread(act_dat_key, 0x10,1,fp); //copy first key in primary table of act.dat + fclose(fp); + + printf("reading:%s\n", path); + fp=fopen(path, "rb"); + if(!fp) + { + return -1; + } + fread(rap, 0x10,1,fp); + fclose(fp); + uint8_t *rif=(uint8_t *)malloc(0x200); + memset(rif,0,0x200); + + get_rif_key(rap, rif+0x50); //convert rap to rifkey(klicensee) + aes_setkey_enc(&aes_ctxt, idps, IDPS_KEYBITS); + aes_crypt_ecb(&aes_ctxt, AES_ENCRYPT, idps_const, idps_const); + + aes_setkey_dec(&aes_ctxt, idps_const, IDPS_KEYBITS); + aes_crypt_ecb(&aes_ctxt, AES_DECRYPT, act_dat_key, act_dat_key); + + + aes_setkey_enc(&aes_ctxt, act_dat_key, ACT_DAT_KEYBITS); + aes_crypt_ecb(&aes_ctxt, AES_ENCRYPT, rif+0x50, rif+0x50);//encrypt rif with act.dat first key primary key table + + uint8_t index_act_key[4]={0};//very first key in act.dat primary table + uint8_t index_act_key_enc[0x10]; + aes_setkey_enc(&aes_ctxt, rif_key_const, RIF_KEYBITS); + aes_crypt_ecb(&aes_ctxt, AES_ENCRYPT, rif+0x40, rif+0x40); + uint64_t timestamp=current_timestamp(); //today + timestamp=swap_uint64(timestamp); + uint32_t version_number=1; + version_number=swap_uint32(version_number); + uint32_t license_type=0x00010002; + license_type=swap_uint32(license_type); + uint64_t expiration_time=0; + expiration_time=swap_uint64(expiration_time); + memcpy(rif, &version_number,4); + memcpy(rif+4, &license_type,4); + memcpy(rif+8,&account_id,8); + memcpy(rif+0x10, content_id, 0x24); +// memcpy(rif+0x40, index_act_key_enc, 0x10); +// memcpy(rif+0x50, klicensee_enc_rif,0x10); + memcpy(rif+0x60, ×tamp, 8); + memcpy(rif+0x68, &expiration_time,8); + uint8_t sha1_digest[20]; + sha1(rif, 0x70,sha1_digest); + ecdsa_set_curve(); + ecdsa_set_pub(); + ecdsa_set_priv(); + uint8_t R[0x15]; + uint8_t S[0x15]; + ecdsa_sign(sha1_digest, R, S); + memcpy(rif+0x70, R+1, 0x14); + memcpy(rif+0x70+0x14, S+1, 0x14); + sha1(rif, 0xa0,sha1_digest); + memcpy(rif+0xa0, sha1_digest,0x10); + memcpy(rif+0xb0, sha1_digest,0x10); + memset(rif+0xc0, 0, 0x40); + _fill_rand_bytes(rif+0x100, 0x100); + + strcpy(path+strlen(path)-4, ".rif"); + printf("writing:%s\n", path); + fp=fopen(path, "wb"); + fwrite(rif, 0x98,1,fp); //only needed till here + fclose(fp); + return 0; +} + +int read_rif_key(char *content_id, uint8_t *rifkey) +{ + uint8_t idps[0x10]; + aes_context aes_ctxt; + uint8_t idps_const[0x10]={0x5E,0x06,0xE0,0x4F,0xD9,0x4A,0x71,0xBF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}; + uint8_t rif_key_const[0x10]={0xDA,0x7D,0x4B,0x5E,0x49,0x9A,0x4F,0x53,0xB1,0xC1,0xA1,0x4A,0x74,0x84,0x44,0x3B}; + printf("reading:idps.hex\n"); + FILE *fp=fopen("idps.hex", "rb"); + if(!fp) + { + return -1; + } + fread(idps, 0x10, 1, fp); + fclose(fp); + uint8_t act_dat_key[0x10]; + uint8_t klicensee[0x10]; + uint8_t klicensee_enc_rif[0x10]; + uint8_t rap[0x10]; + fp=fopen("act.dat","rb"); + if(!fp) + { + return -1; + } + printf("reading:act.dat\n"); + fseek(fp,0x8,SEEK_SET); + fseek(fp,0x10,SEEK_SET); + fread(act_dat_key, 0x10,1,fp); //copy first key in primary table of act.dat + fclose(fp); + char rap_path[0x80]; + strcpy(rap_path, content_id); + strcat(rap_path, ".rap"); + printf("reading:%s\n", rap_path); + fp=fopen(rap_path, "rb"); + if(!fp) + { + return -1; + } + fread(rap, 0x10,1,fp); + fclose(fp); + uint8_t *rif=(uint8_t *)malloc(0x200); + memset(rif,0,0x200); + + get_rif_key(rap, rifkey); //convert rap to rifkey(klicensee) + return 0; +} + +u8 ps2_iv[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + + +int sign_act_dat() +{ + uint8_t *act_dat_buf=(uint8_t *)malloc(0x2000); + printf("reading:act.dat\n"); + FILE *fp=fopen("act.dat","rb"); + fread(act_dat_buf, 0x1038,1,fp); + fclose(fp); + uint8_t digest[20]; + sha1(act_dat_buf, 0x1010, digest); + uint8_t R[0x15]; + uint8_t S[0x15]; + ecdsa_sign(digest, R,S); + memcpy(act_dat_buf+0x1010, R+1, 0x14); + memcpy(act_dat_buf+0x1010+0x14, S+1, 0x14); + printf("writing:signed_act.dat\n"); + fp=fopen("signed_act.dat","wb"); + fwrite(act_dat_buf, 0x1038,1,fp); + fclose(fp); + return 0; +} + +static void set_ps2_iv(u8 iv[]) +{ + memcpy(iv, ps2_iv, 0x10); +} + +static inline u32 be32(u8 *p) +{ + u32 a; + + a = p[0] << 24; + a |= p[1] << 16; + a |= p[2] << 8; + a |= p[3] << 0; + + return a; +} + +static inline u32 le32(u8 *p) +{ + u32 a; + + a = p[3] << 24; + a |= p[2] << 16; + a |= p[1] << 8; + a |= p[0] << 0; + + return a; +} + +static inline u64 be64(u8 *p) +{ + u32 a, b; + + a = be32(p); + b = be32(p + 4); + + return ((u64)a<<32) | b; +} + + +void dump_meta(char mode[], FILE *in, char meta_file[], uint8_t *klicensee) +{ +#define PS2_META_SEGMENT_START 1 +#define PS2_DATA_SEGMENT_START 2 +#define PS2_DEFAULT_SEGMENT_SIZE 0x4000 +#define PS2_META_ENTRY_SIZE 0x20 + u8 ps2_key_cex_meta[] = { 0x38, 0x9D, 0xCB, 0xA5, 0x20, 0x3C, 0x81, 0x59, 0xEC, 0xF9, 0x4C, 0x93, 0x93, 0x16, 0x4C, 0xC9 }; + u8 ps2_key_cex_data[] = { 0x10, 0x17, 0x82, 0x34, 0x63, 0xF4, 0x68, 0xC1, 0xAA, 0x41, 0xD7, 0x00, 0xB1, 0x40, 0xF2, 0x57 }; + u8 ps2_key_cex_vmc[] = { 0x64, 0xE3, 0x0D, 0x19, 0xA1, 0x69, 0x41, 0xD6, 0x77, 0xE3, 0x2E, 0xEB, 0xE0, 0x7F, 0x45, 0xD2 }; + FILE * meta_out; + + u8 ps2_key_dex_meta[] = { 0x2B, 0x05, 0xF7, 0xC7, 0xAF, 0xD1, 0xB1, 0x69, 0xD6, 0x25, 0x86, 0x50, 0x3A, 0xEA, 0x97, 0x98 }; +u8 ps2_key_dex_data[] = { 0x74, 0xFF, 0x7E, 0x5D, 0x1D, 0x7B, 0x96, 0x94, 0x3B, 0xEF, 0xDC, 0xFA, 0x81, 0xFC, 0x20, 0x07 }; +u8 ps2_key_dex_vmc[] = { 0x30, 0x47, 0x9D, 0x4B, 0x80, 0xE8, 0x9E, 0x2B, 0x59, 0xE5, 0xC9, 0x14, 0x5E, 0x10, 0x64, 0xA9 }; +u8 ps2_data_key[0x10]; + u8 ps2_meta_key[0x10]; + u8 iv[0x10]; + + int segment_size; + s64 data_size; + int i; + u8 header[256]; + u8 * data_buffer; + u8 * meta_buffer; + u32 read = 0; + int num_child_segments; + + //open files + meta_out = fopen(meta_file, "wb"); + + //get file info + read = fread(header, 256, 1, in); + segment_size = be32(header + 0x84); + data_size = be64(header + 0x88); + num_child_segments = segment_size / PS2_META_ENTRY_SIZE; + + printf("segment size: %x\ndata_size: %llx\n\n", segment_size, data_size); + + //alloc buffers + data_buffer = (u8 *)malloc(segment_size*num_child_segments); + meta_buffer = (u8 *)malloc(segment_size); + + //generate keys + if(strcmp(mode, "cex") == 0) + { + printf("cex\n"); + set_ps2_iv(iv); + aescbc128_encrypt(ps2_key_cex_data, iv, klicensee, ps2_data_key, 0x10); + aescbc128_encrypt(ps2_key_cex_meta, iv, klicensee, ps2_meta_key, 0x10); + }else{ + printf("dex\n"); + set_ps2_iv(iv); + aescbc128_encrypt(ps2_key_dex_data, iv, klicensee, ps2_data_key, 0x10); + aescbc128_encrypt(ps2_key_dex_meta, iv, klicensee, ps2_meta_key, 0x10); + } + + + //decrypt iso + fseek(in, segment_size, SEEK_SET); + + while(read = fread(meta_buffer, 1, segment_size, in)) + { + //decrypt meta + aescbc128_decrypt(ps2_meta_key, iv, meta_buffer, meta_buffer, read); + fwrite(meta_buffer, read, 1, meta_out); + read = fread(data_buffer, 1, segment_size*num_child_segments, in); + } + + //cleanup + free(data_buffer); + free(meta_buffer); + + fclose(meta_out); + fseek(in, 0, SEEK_SET); +} + +int sign_enc(FILE *fp) +{ + uint8_t *buf=(uint8_t *)malloc(0x200); + memset(buf,0,0x200); + fread(buf, 0x100,1,fp); + uint8_t R[0x15]; + uint8_t S[0x15]; + uint8_t digest[20]; + sha1(buf, 0xd8, digest); + ecdsa_sign(digest,R,S); + fseek(fp, 0xD8, SEEK_SET); + fwrite(R+1, 0x14,1,fp); + fwrite(S+1,0x14,1,fp); + return 0; +} + +static inline void wbe32(u8 *p, u32 v) +{ + p[0] = v >> 24; + p[1] = v >> 16; + p[2] = v >> 8; + p[3] = v; +} + +static inline void wbe64(u8 *p, u64 v) +{ + wbe32(p + 4, v); + v >>= 32; + wbe32(p, v); +} + +#include +#include "pkg2zip_aes_x86.h" + +static void decrypt_debug_pkg_normal(uint8_t *pkg, uint64_t size, uint64_t offset, int file, uint64_t len) +{ + u8 key[0x40]; + u8 bfr[0x1c]; + u64 i; + + memset(key, 0, sizeof key); + memcpy(key, pkg + 0x60, 8); + memcpy(key + 0x08, pkg + 0x60, 8); + memcpy(key + 0x10, pkg + 0x60 + 0x08, 8); + memcpy(key + 0x18, pkg + 0x60 + 0x08, 8); + + sha1(key, sizeof key, bfr); + + if(len>(10*1024*1024)) + { + munmap(pkg, 10*1024*1024); + } + else + { + munmap(pkg, len); + } + if(len>(100*1024*1024)) + { + pkg=(uint8_t *)mmap(0, 100*1024*1024, PROT_READ | PROT_WRITE, MAP_PRIVATE, file, 0); + } + else + { + pkg=(uint8_t *)mmap(0, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, file, 0); + } + + uint32_t last_round_size=len; + uint64_t count=offset; + lseek(file, 0, SEEK_SET); + for (i = offset; i < (size+offset); i++, count++) { + if (i != offset && (i % 16) == 0) { + wbe64(key + 0x38, be64(key + 0x38) + 1); + sha1(key, sizeof key, bfr); + } + if(i%(100*1024*1024)==0) + { + write(file, pkg, 100*1024*1024); + munmap(pkg, 100*1024*1024); + lseek(file, i, SEEK_SET); + if((size+offset-i)>(100*1024*1024)) + { + pkg=(uint8_t *)mmap(0, 100*1024*1024, PROT_READ | PROT_WRITE, MAP_PRIVATE, file, i); + } + else + { + pkg=(uint8_t *)mmap(0, (size+offset-i), PROT_READ | PROT_WRITE, MAP_PRIVATE, file, i); + lseek(file, i, SEEK_SET); + last_round_size=(size+offset-i); + } + count=0; + } + pkg[count] ^= bfr[i & 0xf]; + } + write(file, pkg, last_round_size); + munmap(pkg, last_round_size); +} + +static void decrypt_debug_pkg_sse(uint8_t *pkg, uint64_t size, uint64_t offset, int file, uint64_t len) +{ + u8 key[0x40]; + u8 bfr[0x1c]; + u64 i; + u64 ret=0; + uint32_t last_round_size=len; + + memset(key, 0, sizeof key); + memcpy(key, pkg + 0x60, 8); + memcpy(key + 0x08, pkg + 0x60, 8); + memcpy(key + 0x10, pkg + 0x60 + 0x08, 8); + memcpy(key + 0x18, pkg + 0x60 + 0x08, 8); + + SHA1(key, sizeof key, bfr); + + if(len>(10*1024*1024)) + { + munmap(pkg, 10*1024*1024); + } + else + { + munmap(pkg, len); + } + if(len>(100*1024*1024)) + { + pkg=(uint8_t *)mmap(0, 100*1024*1024, PROT_READ | PROT_WRITE, MAP_PRIVATE, file, 0); + } + else + { + pkg=(uint8_t *)mmap(0, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, file, 0); + } + + xor1_sse(pkg+offset,pkg+offset,bfr, 0x10); + lseek(file, 0, SEEK_SET); + uint64_t count=offset+0x10; + #pragma unroll + for (i = (0x10+offset); i < (size+offset); i+=0x10, count+=0x10) { + + wbe64(key + 0x38, be64(key + 0x38) + 1); + SHA1(key, sizeof key, bfr); + if(i%(100*1024*1024)==0) + { + write(file, pkg, 100*1024*1024); + munmap(pkg, 100*1024*1024); + lseek(file, i, SEEK_SET); + if((size+offset-i)>(100*1024*1024)) + { + pkg=(uint8_t *)mmap(0, 100*1024*1024, PROT_READ | PROT_WRITE, MAP_PRIVATE, file, i); + } + else + { + pkg=(uint8_t *)mmap(0, (size+offset-i), PROT_READ | PROT_WRITE, MAP_PRIVATE, file, i); + lseek(file, i, SEEK_SET); + last_round_size=(size+offset-i); + } + count=0; + } + xor1_sse(pkg+count,pkg+count,bfr, 0x10); + } + + write(file, pkg, last_round_size); + munmap(pkg, last_round_size); +} + +static void decrypt_debug_pkg(uint8_t *pkg, uint64_t size, uint64_t offset_data, int file, uint64_t len) +{ + if(aes128_supported_x86()) + { + decrypt_debug_pkg_sse(pkg,size,offset_data, file, len); + } + else + { + decrypt_debug_pkg_normal(pkg,size,offset_data, file, len); + } +} + +int decrypt_retail_pkg_data(uint8_t *buf, uint64_t size, uint8_t *data_riv, uint8_t *gpkg_key) +{ + aes128ctr(gpkg_key, data_riv, buf, size, buf); + return 0; +} + +static void check_ps2_pkg_patch(uint8_t *pkg, uint64_t offset, int fd) +{ + u64 i; + u64 n_files; + u32 fname_len; + u32 fname_off; + u64 file_offset; + u32 flags; + char fname[256]; + u8 *tmp; + u8 tmp_buf[0x100]; + + uint8_t digest[20]; + uint8_t R[0x15]; + uint8_t S[0x15]; + + u8 magic_ps2[4]={'P','S','2',0x00}; + u8 magic_edat[4]={'N','P','D',0x00}; + + n_files = be32(pkg + 0x14); + + for (i = 0; i < n_files; i++) { + tmp = pkg + offset + i*0x20; + + fname_off = be32(tmp) + offset; + fname_len = be32(tmp + 0x04); + file_offset = be64(tmp + 0x08) + offset; + uint64_t size = be64(tmp + 0x10); + flags = be32(tmp + 0x18); + if (fname_len >= sizeof fname) + printf("filename too long: %s\n", pkg + fname_off); + + memset(fname, 0, sizeof fname); + memset(tmp_buf, 0, sizeof tmp_buf); + strncpy(fname, (char *)(pkg + fname_off), fname_len); + flags &= 0xff; + printf("%s\n", fname); + + char *last_slash=strrchr(fname, '/'); + if(!last_slash) //we are in root of pkg + { + continue; + } + if((strstr(last_slash, ".edat")) || (strstr(last_slash, ".EDAT")) || (strstr(last_slash, "CONFIG")) || (strstr(last_slash, "ISO.BIN.ENC"))) + { + if(flags != 4) //it is not a directory + { + printf("found %s..Resigning\n", last_slash); + //sign_enc_buf(pkg+file_offset); + lseek(fd,file_offset+0x00, SEEK_SET); + read(fd, tmp_buf, 0x100); + if((memcmp(tmp_buf, magic_ps2, 4)==0) || (memcmp(tmp_buf, magic_edat,4)==0)) //it is indeed a ps2 file or edat + { + sha1(tmp_buf, 0xd8, digest); + ecdsa_sign(digest, R, S); + lseek(fd,file_offset+0xd8, SEEK_SET); + write(fd, R+1, 0x14); + lseek(fd,file_offset+0xd8+0x14, SEEK_SET); + write(fd, S+1, 0x14); + } + } + } + } +} + +typedef struct __TOC_HEADER { + uint32_t fname_offset; + uint32_t name_size; + uint64_t file_off; + uint64_t file_size; + uint8_t psp_key_type; + uint8_t shit_stuff[7]; +} TOC_HEADER; + +int parse_psp_pkg(uint8_t *pkg, uint32_t toc_len, uint8_t *iv_const, uint32_t data_size, int file_out, uint64_t offset_data) +{ + TOC_HEADER *header=(TOC_HEADER *)malloc(2*1024*1024); + uint8_t pkg_key[0x10]={0x2E,0x7B,0x71,0xD7,0xC9,0xC9,0xA1,0x4E,0xA3,0x22,0x1F,0x18,0x88,0x28,0xB8,0xF8}; + uint8_t pkg_key_psp[0x10]={0x07,0xF2,0xC6,0x82,0x90,0xB5,0x0D,0x2C,0x33,0x81,0x8D,0x70,0x9B,0x60,0xE6,0x2B}; + + aes128_key ps3_key; + aes128_init(&ps3_key, pkg_key); + + memcpy(header, pkg, toc_len); + int i=0; + int number_files=toc_len/0x20; + uint8_t main_key[0x10]; + + uint32_t len_dec_name=0; + uint8_t second_last; + uint8_t *tmp_buf=(uint8_t *)malloc(100*1024*1024); + uint8_t name[4096]={0}; + + for(i=0;i0x10) + { + len_dec_name=0x20; + } + else if(header[i].name_size>0x20) + { + len_dec_name=0x30; + } + else + { + len_dec_name=0x10; + } + printf("len_dec_name=%x\n", len_dec_name); + printf("header[i].fname_offset=%x\n", header[i].fname_offset); + printf("header[i].file_off=%x\n", header[i].file_off); + printf("header[i].file_size=%x\n", header[i].file_size); + printf("number_files=%x\n", number_files); + + int loop=0; + printf("key: "); + + for (loop = 0; loop < 0x10; loop++) + { + printf("%02X", main_key[loop]); + } + printf("\n"); + + loop=0; + printf("iv: "); + + for (loop = 0; loop < 0x10; loop++) + { + printf("%02X", iv_const[loop]); + } + printf("\n"); + + // aes128ctrxor(main_key, iv_const, pkg+header[i].fname_offset, len_dec_name, pkg+header[i].fname_offset,header[i].fname_offset-toc_len); + aes128_ctr_xor(&key, iv_const, ((header[i].fname_offset)-toc_len)/16, pkg+header[i].fname_offset, len_dec_name); + aes128_ctr_xor(&key, iv_const, ((header[i].file_off)-toc_len)/16, pkg+header[i].file_off, header[i].file_size); + + // aes128ctrxor(main_key, iv_const, pkg+header[i].file_off, header[i].file_size, pkg+header[i].file_off,header[i].file_off-toc_len); + } + return 0; +} + +int main(int argc, char *argv[]) +{ + printf("----------------PS3XPLOIT RESIGNER v3----------------\nHAN v3 tools brought you by W, escortd3w, bguerville, habib\nSpecial thanks to Joonie for testing this tool\n-----------------------------------------------------\n"); + + if(argc<2) + { + goto done; + } + +if((strstr(argv[1], ".rap")) || (strstr(argv[1], ".RAP"))) + { + if(read_act_dat_and_make_rif(argv[1])==0) + { + sign_act_dat(); + printf("\nits done!\npress enter\n"); + } + else + { + printf("\nverify your files!"); + } + getchar(); + getchar(); + return 0; + } + else if((strstr(argv[1], ".EDAT")) || (strstr(argv[1], ".edat"))) + { + char *slash2 = strrchr (argv[1], '\\'); + if (slash2 != NULL) + { + *slash2 = '\0'; + argv[1]=slash2+1; + } + FILE *fp=fopen(argv[1], "rb+"); + if(!fp) + { + printf("edat unreadable!\n"); + } + + uint32_t license; + char *content_id_edat=(char *)malloc(0x100); + memset(content_id_edat,0,0x100); + fread(content_id_edat, 0x34, 1,fp); + memcpy(&license, content_id_edat+8, 4); + license=swap_uint32(license); + content_id_edat+=0x10; + uint8_t rifkey[0x10]; + +/*OLD METHOD!!!!!*/ +/* if((license==2) || (license==3)) + { + read_rif_key(content_id_edat, rifkey); + } + uint8_t meta_sig_hash_output[20]; + uint8_t header_sig_hash_output[20]; + unsigned char devklic_edat[16] = {0x52,0xC0,0xB5,0xCA,0x76,0xD6,0x13,0x4B,0xB4,0x5F,0xC6,0x6C,0xA6,0x37,0xF2,0xC1}; + + FILE *devklic_explicit=fopen("devklic", "rb"); + if(devklic_explicit) + { + printf("using explicit devklic\n"); + fread(devklic_edat, 16, 1, devklic_explicit); + fclose(devklic_explicit); + } + + if(extract_data_and_sign(fp, devklic_edat, rifkey, 0)) + { + getchar(); + return -1; + } +*/ +/*END*/ +/* NEW METHOD!!!!!!!!*/ + ecdsa_set_curve(); + ecdsa_set_pub(); + ecdsa_set_priv(); + fseek(fp,0,SEEK_SET); + sign_enc(fp); +/*END*/ + fclose(fp); + printf("edat resigned!\n"); + fp=fopen("ISO.BIN.ENC", "rb+"); + if(fp) + { + // dump_meta((char *)"cex", fp, (char *)"ISO.BIN.ENC_meta_out", rifkey); + sign_enc(fp); + printf("enc resigned!\n"); + fclose(fp); + fp=fopen("CONFIG", "rb+"); + if(fp) + { + sign_enc(fp); + printf("config resigned!\n"); + fclose(fp); + } + } + getchar(); + getchar(); + return 0; + } + else if((strstr(argv[1], ".pkg")) || (strstr(argv[1], ".PKG"))) + { + ecdsa_set_curve(); + ecdsa_set_pub(); + ecdsa_set_priv(); + struct stat stat1; + if(stat(argv[1], &stat1)!=0) + { + printf("cant open file!\n"); + getchar(); + return -1; + } + uint64_t len=stat1.st_size; + printf("size:%016llx\n", len); + + int fd=open(argv[1], O_RDONLY); + uint8_t *buf2=NULL; + char out_path[4096]; + strcpy(out_path, argv[1]); + strcat(out_path, "_signed.pkg"); + int fd_out=open(out_path, O_RDWR|O_CREAT, 0600); + lseek(fd_out, 0, SEEK_SET); + printf("making backup\n"); + uint64_t bkp=0; + for(bkp;bkp(10*1024*1024)) + { + buf=(uint8_t *)mmap(0, 10*1024*1024, PROT_READ | PROT_WRITE, MAP_SHARED, fd_out, 0); + } + else + { + buf=(uint8_t *)mmap(0, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd_out, 0); + } + + if(!buf) + { + printf("not enough free memory!\n"); + return -1; + } + uint64_t data_size=*(uint64_t *)(buf+0x28); + uint8_t iv[0x10]; + uint64_t offset_data=*(uint64_t *)(buf+0x20); + offset_data=swap_uint64(offset_data); + uint32_t pkg_info_offset=*(uint32_t *)(buf+0x8); + pkg_info_offset=swap_uint32(pkg_info_offset); + uint32_t header_size=*(uint32_t *)(buf+0x10); + header_size=swap_uint32(header_size); + uint32_t toc_size=(swap_uint32(*(uint32_t *)(buf+0x14)))*0x20; + + uint32_t pkg_type=*(uint32_t *)(buf+pkg_info_offset+0x14); + pkg_type=swap_uint32(pkg_type); + + memcpy(iv, buf+0x70, 0x10); + uint8_t iv_bkp[0x10]; + memcpy(iv_bkp, iv, 0x10); + data_size=swap_uint64(data_size); + uint8_t pkg_key[0x10]={0x2E,0x7B,0x71,0xD7,0xC9,0xC9,0xA1,0x4E,0xA3,0x22,0x1F,0x18,0x88,0x28,0xB8,0xF8}; + uint8_t pkg_key_psp[0x10]={0x07,0xF2,0xC6,0x82,0x90,0xB5,0x0D,0x2C,0x33,0x81,0x8D,0x70,0x9B,0x60,0xE6,0x2B}; + if(*(uint8_t *)&buf[4]!=0x80) + { + *(uint8_t *)&buf[4]=0x80; + uint8_t retail_flag=0x80; + + + if((pkg_type==0xf) || (pkg_type==0x6) || (pkg_type==0x7)) //0xf==minis, 0x6==ps1, 0x7==psp, 0x14==remastered + { + printf("PKG type PSP/PSX detected\n"); + *(uint8_t *)&buf[7]=2; + } + printf("decrypting debug pkg\n"); + decrypt_debug_pkg(buf, data_size, offset_data, fd_out, len); + + if(len>(10*1024*1024)) + { + buf=(uint8_t *)mmap(0, 10*1024*1024, PROT_READ | PROT_WRITE, MAP_SHARED, fd_out, 0); + } + else + { + buf=(uint8_t *)mmap(0, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd_out, 0); + } + + printf("encrypting retail pkg\n"); + check_ps2_pkg_patch(buf, offset_data, fd_out); + if(*(uint8_t *)&buf[7]==2) + { + memcpy(iv, iv_bkp, 0x10); + parse_psp_pkg(buf+offset_data, toc_size, iv, data_size, fd_out, offset_data); + + memcpy(iv, iv_bkp, 0x10); + decrypt_retail_pkg_data(buf+offset_data, toc_size, iv, pkg_key_psp); + memcpy(iv, iv_bkp, 0x10); + } + else + { + memcpy(iv, iv_bkp, 0x10); + parse_psp_pkg(buf+offset_data, toc_size, iv, data_size, fd_out, offset_data); + + memcpy(iv, iv_bkp, 0x10); + decrypt_retail_pkg_data(buf+offset_data, toc_size, iv, pkg_key); + } + cmac_hash_forge(pkg_key, 0x10, buf, 0x80, buf+0x80); + } + else + { + printf("decrypting retail pkg\n"); + if(*(uint8_t *)&buf[7]==2) + { + printf("type psp detected\n"); + decrypt_retail_pkg_data(buf+offset_data, toc_size, iv, pkg_key_psp); + memcpy(iv, iv_bkp, 0x10); + parse_psp_pkg(buf+offset_data, toc_size, iv, data_size, fd_out, offset_data); + + } + else + { + memcpy(iv, iv_bkp, 0x10); + decrypt_retail_pkg_data(buf+offset_data, toc_size, iv, pkg_key); + memcpy(iv, iv_bkp, 0x10); + parse_psp_pkg(buf+offset_data, toc_size, iv, data_size, fd_out, offset_data); + + memcpy(iv, iv_bkp, 0x10); + } + printf("encrypting retail pkg\n"); + check_ps2_pkg_patch(buf, offset_data, fd_out); + + if(*(uint8_t *)&buf[7]==2) + { + parse_psp_pkg(buf+offset_data, toc_size, iv, data_size, fd_out, offset_data); + memcpy(iv, iv_bkp,0x10); + decrypt_retail_pkg_data(buf+offset_data, toc_size, iv, pkg_key_psp); + } + else + { + memcpy(iv, iv_bkp,0x10); + parse_psp_pkg(buf+offset_data, toc_size, iv, data_size, fd_out, offset_data); + + memcpy(iv, iv_bkp,0x10); + decrypt_retail_pkg_data(buf+offset_data, toc_size, iv, pkg_key); + } + cmac_hash_forge(pkg_key, 0x10, buf, 0x80, buf+0x80); + } + + uint8_t digest[20]; + uint8_t R[0x15]; + uint8_t S[0x15]; + + cmac_hash_forge(pkg_key, 0x10, buf+pkg_info_offset, header_size-0x40, buf+pkg_info_offset+header_size-0x40); + + if(len>(10*1024*1024)) + { + munmap(buf, 10*1024*1024); + } + else + { + munmap(buf, len); + } + + SHA_CTX ctx; + + SHA1_Init( &ctx ); + uint64_t sha1_loop=0; + for(sha1_loop;sha1_loop +#include + +#if defined(_MSC_VER) +#define PLATFORM_SUPPORTS_AESNI 1 + +#include +static void get_cpuid(uint32_t level, uint32_t* arr) +{ + __cpuidex((int*)arr, level, 0); +} + +#elif defined(__x86_64__) || defined(__i386__) +#define PLATFORM_SUPPORTS_AESNI 1 + +#include +static void get_cpuid(uint32_t level, uint32_t* arr) +{ + __cpuid_count(level, 0, arr[0], arr[1], arr[2], arr[3]); +} + +#else +#define PLATFORM_SUPPORTS_AESNI 0 +#endif + +#if PLATFORM_SUPPORTS_AESNI +int aes128_supported_x86() +{ + static int init = 0; + static int supported; + if (!init) + { + init = 1; + + uint32_t a[4]; + get_cpuid(0, a); + + if (a[0] >= 1) + { + get_cpuid(1, a); + supported = ((a[2] & (1 << 9)) && (a[2] & (1 << 25))); + } + } + return supported; +} + +void aes128_init_x86(aes128_key* context, const uint8_t* key); +void aes128_init_dec_x86(aes128_key* context, const uint8_t* key); +void aes128_ecb_encrypt_x86(const aes128_key* context, const uint8_t* input, uint8_t* output); +void aes128_ecb_decrypt_x86(const aes128_key* context, const uint8_t* input, uint8_t* output); +void aes128_ctr_xor_x86(const aes128_key* context, const uint8_t* iv, uint8_t* buffer, size_t size); +void aes128_cmac_process_x86(const aes128_key* ctx, uint8_t* block, const uint8_t *buffer, uint32_t size); +void aes128_psp_decrypt_x86(const aes128_key* ctx, const uint8_t* prev, const uint8_t* block, uint8_t* buffer, uint32_t size); +#endif + +static const uint8_t rcon[] = { + 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36, +}; + +static const uint8_t Te[] = { + 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, + 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, + 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, + 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, + 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, + 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, + 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, + 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, + 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, + 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, + 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, + 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, + 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, + 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, + 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, + 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16, +}; + +static uint8_t Td[] = { + 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, + 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, + 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, + 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, + 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, + 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, + 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, + 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, + 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, + 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, + 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, + 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, + 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, + 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, + 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, + 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d, +}; + +static const uint32_t TE[] = { + 0xc66363a5, 0xf87c7c84, 0xee777799, 0xf67b7b8d, 0xfff2f20d, 0xd66b6bbd, 0xde6f6fb1, 0x91c5c554, + 0x60303050, 0x02010103, 0xce6767a9, 0x562b2b7d, 0xe7fefe19, 0xb5d7d762, 0x4dababe6, 0xec76769a, + 0x8fcaca45, 0x1f82829d, 0x89c9c940, 0xfa7d7d87, 0xeffafa15, 0xb25959eb, 0x8e4747c9, 0xfbf0f00b, + 0x41adadec, 0xb3d4d467, 0x5fa2a2fd, 0x45afafea, 0x239c9cbf, 0x53a4a4f7, 0xe4727296, 0x9bc0c05b, + 0x75b7b7c2, 0xe1fdfd1c, 0x3d9393ae, 0x4c26266a, 0x6c36365a, 0x7e3f3f41, 0xf5f7f702, 0x83cccc4f, + 0x6834345c, 0x51a5a5f4, 0xd1e5e534, 0xf9f1f108, 0xe2717193, 0xabd8d873, 0x62313153, 0x2a15153f, + 0x0804040c, 0x95c7c752, 0x46232365, 0x9dc3c35e, 0x30181828, 0x379696a1, 0x0a05050f, 0x2f9a9ab5, + 0x0e070709, 0x24121236, 0x1b80809b, 0xdfe2e23d, 0xcdebeb26, 0x4e272769, 0x7fb2b2cd, 0xea75759f, + 0x1209091b, 0x1d83839e, 0x582c2c74, 0x341a1a2e, 0x361b1b2d, 0xdc6e6eb2, 0xb45a5aee, 0x5ba0a0fb, + 0xa45252f6, 0x763b3b4d, 0xb7d6d661, 0x7db3b3ce, 0x5229297b, 0xdde3e33e, 0x5e2f2f71, 0x13848497, + 0xa65353f5, 0xb9d1d168, 0x00000000, 0xc1eded2c, 0x40202060, 0xe3fcfc1f, 0x79b1b1c8, 0xb65b5bed, + 0xd46a6abe, 0x8dcbcb46, 0x67bebed9, 0x7239394b, 0x944a4ade, 0x984c4cd4, 0xb05858e8, 0x85cfcf4a, + 0xbbd0d06b, 0xc5efef2a, 0x4faaaae5, 0xedfbfb16, 0x864343c5, 0x9a4d4dd7, 0x66333355, 0x11858594, + 0x8a4545cf, 0xe9f9f910, 0x04020206, 0xfe7f7f81, 0xa05050f0, 0x783c3c44, 0x259f9fba, 0x4ba8a8e3, + 0xa25151f3, 0x5da3a3fe, 0x804040c0, 0x058f8f8a, 0x3f9292ad, 0x219d9dbc, 0x70383848, 0xf1f5f504, + 0x63bcbcdf, 0x77b6b6c1, 0xafdada75, 0x42212163, 0x20101030, 0xe5ffff1a, 0xfdf3f30e, 0xbfd2d26d, + 0x81cdcd4c, 0x180c0c14, 0x26131335, 0xc3ecec2f, 0xbe5f5fe1, 0x359797a2, 0x884444cc, 0x2e171739, + 0x93c4c457, 0x55a7a7f2, 0xfc7e7e82, 0x7a3d3d47, 0xc86464ac, 0xba5d5de7, 0x3219192b, 0xe6737395, + 0xc06060a0, 0x19818198, 0x9e4f4fd1, 0xa3dcdc7f, 0x44222266, 0x542a2a7e, 0x3b9090ab, 0x0b888883, + 0x8c4646ca, 0xc7eeee29, 0x6bb8b8d3, 0x2814143c, 0xa7dede79, 0xbc5e5ee2, 0x160b0b1d, 0xaddbdb76, + 0xdbe0e03b, 0x64323256, 0x743a3a4e, 0x140a0a1e, 0x924949db, 0x0c06060a, 0x4824246c, 0xb85c5ce4, + 0x9fc2c25d, 0xbdd3d36e, 0x43acacef, 0xc46262a6, 0x399191a8, 0x319595a4, 0xd3e4e437, 0xf279798b, + 0xd5e7e732, 0x8bc8c843, 0x6e373759, 0xda6d6db7, 0x018d8d8c, 0xb1d5d564, 0x9c4e4ed2, 0x49a9a9e0, + 0xd86c6cb4, 0xac5656fa, 0xf3f4f407, 0xcfeaea25, 0xca6565af, 0xf47a7a8e, 0x47aeaee9, 0x10080818, + 0x6fbabad5, 0xf0787888, 0x4a25256f, 0x5c2e2e72, 0x381c1c24, 0x57a6a6f1, 0x73b4b4c7, 0x97c6c651, + 0xcbe8e823, 0xa1dddd7c, 0xe874749c, 0x3e1f1f21, 0x964b4bdd, 0x61bdbddc, 0x0d8b8b86, 0x0f8a8a85, + 0xe0707090, 0x7c3e3e42, 0x71b5b5c4, 0xcc6666aa, 0x904848d8, 0x06030305, 0xf7f6f601, 0x1c0e0e12, + 0xc26161a3, 0x6a35355f, 0xae5757f9, 0x69b9b9d0, 0x17868691, 0x99c1c158, 0x3a1d1d27, 0x279e9eb9, + 0xd9e1e138, 0xebf8f813, 0x2b9898b3, 0x22111133, 0xd26969bb, 0xa9d9d970, 0x078e8e89, 0x339494a7, + 0x2d9b9bb6, 0x3c1e1e22, 0x15878792, 0xc9e9e920, 0x87cece49, 0xaa5555ff, 0x50282878, 0xa5dfdf7a, + 0x038c8c8f, 0x59a1a1f8, 0x09898980, 0x1a0d0d17, 0x65bfbfda, 0xd7e6e631, 0x844242c6, 0xd06868b8, + 0x824141c3, 0x299999b0, 0x5a2d2d77, 0x1e0f0f11, 0x7bb0b0cb, 0xa85454fc, 0x6dbbbbd6, 0x2c16163a, +}; + +static const uint32_t TD[] = { + 0x51f4a750, 0x7e416553, 0x1a17a4c3, 0x3a275e96, 0x3bab6bcb, 0x1f9d45f1, 0xacfa58ab, 0x4be30393, + 0x2030fa55, 0xad766df6, 0x88cc7691, 0xf5024c25, 0x4fe5d7fc, 0xc52acbd7, 0x26354480, 0xb562a38f, + 0xdeb15a49, 0x25ba1b67, 0x45ea0e98, 0x5dfec0e1, 0xc32f7502, 0x814cf012, 0x8d4697a3, 0x6bd3f9c6, + 0x038f5fe7, 0x15929c95, 0xbf6d7aeb, 0x955259da, 0xd4be832d, 0x587421d3, 0x49e06929, 0x8ec9c844, + 0x75c2896a, 0xf48e7978, 0x99583e6b, 0x27b971dd, 0xbee14fb6, 0xf088ad17, 0xc920ac66, 0x7dce3ab4, + 0x63df4a18, 0xe51a3182, 0x97513360, 0x62537f45, 0xb16477e0, 0xbb6bae84, 0xfe81a01c, 0xf9082b94, + 0x70486858, 0x8f45fd19, 0x94de6c87, 0x527bf8b7, 0xab73d323, 0x724b02e2, 0xe31f8f57, 0x6655ab2a, + 0xb2eb2807, 0x2fb5c203, 0x86c57b9a, 0xd33708a5, 0x302887f2, 0x23bfa5b2, 0x02036aba, 0xed16825c, + 0x8acf1c2b, 0xa779b492, 0xf307f2f0, 0x4e69e2a1, 0x65daf4cd, 0x0605bed5, 0xd134621f, 0xc4a6fe8a, + 0x342e539d, 0xa2f355a0, 0x058ae132, 0xa4f6eb75, 0x0b83ec39, 0x4060efaa, 0x5e719f06, 0xbd6e1051, + 0x3e218af9, 0x96dd063d, 0xdd3e05ae, 0x4de6bd46, 0x91548db5, 0x71c45d05, 0x0406d46f, 0x605015ff, + 0x1998fb24, 0xd6bde997, 0x894043cc, 0x67d99e77, 0xb0e842bd, 0x07898b88, 0xe7195b38, 0x79c8eedb, + 0xa17c0a47, 0x7c420fe9, 0xf8841ec9, 0x00000000, 0x09808683, 0x322bed48, 0x1e1170ac, 0x6c5a724e, + 0xfd0efffb, 0x0f853856, 0x3daed51e, 0x362d3927, 0x0a0fd964, 0x685ca621, 0x9b5b54d1, 0x24362e3a, + 0x0c0a67b1, 0x9357e70f, 0xb4ee96d2, 0x1b9b919e, 0x80c0c54f, 0x61dc20a2, 0x5a774b69, 0x1c121a16, + 0xe293ba0a, 0xc0a02ae5, 0x3c22e043, 0x121b171d, 0x0e090d0b, 0xf28bc7ad, 0x2db6a8b9, 0x141ea9c8, + 0x57f11985, 0xaf75074c, 0xee99ddbb, 0xa37f60fd, 0xf701269f, 0x5c72f5bc, 0x44663bc5, 0x5bfb7e34, + 0x8b432976, 0xcb23c6dc, 0xb6edfc68, 0xb8e4f163, 0xd731dcca, 0x42638510, 0x13972240, 0x84c61120, + 0x854a247d, 0xd2bb3df8, 0xaef93211, 0xc729a16d, 0x1d9e2f4b, 0xdcb230f3, 0x0d8652ec, 0x77c1e3d0, + 0x2bb3166c, 0xa970b999, 0x119448fa, 0x47e96422, 0xa8fc8cc4, 0xa0f03f1a, 0x567d2cd8, 0x223390ef, + 0x87494ec7, 0xd938d1c1, 0x8ccaa2fe, 0x98d40b36, 0xa6f581cf, 0xa57ade28, 0xdab78e26, 0x3fadbfa4, + 0x2c3a9de4, 0x5078920d, 0x6a5fcc9b, 0x547e4662, 0xf68d13c2, 0x90d8b8e8, 0x2e39f75e, 0x82c3aff5, + 0x9f5d80be, 0x69d0937c, 0x6fd52da9, 0xcf2512b3, 0xc8ac993b, 0x10187da7, 0xe89c636e, 0xdb3bbb7b, + 0xcd267809, 0x6e5918f4, 0xec9ab701, 0x834f9aa8, 0xe6956e65, 0xaaffe67e, 0x21bccf08, 0xef15e8e6, + 0xbae79bd9, 0x4a6f36ce, 0xea9f09d4, 0x29b07cd6, 0x31a4b2af, 0x2a3f2331, 0xc6a59430, 0x35a266c0, + 0x744ebc37, 0xfc82caa6, 0xe090d0b0, 0x33a7d815, 0xf104984a, 0x41ecdaf7, 0x7fcd500e, 0x1791f62f, + 0x764dd68d, 0x43efb04d, 0xccaa4d54, 0xe49604df, 0x9ed1b5e3, 0x4c6a881b, 0xc12c1fb8, 0x4665517f, + 0x9d5eea04, 0x018c355d, 0xfa877473, 0xfb0b412e, 0xb3671d5a, 0x92dbd252, 0xe9105633, 0x6dd64713, + 0x9ad7618c, 0x37a10c7a, 0x59f8148e, 0xeb133c89, 0xcea927ee, 0xb761c935, 0xe11ce5ed, 0x7a47b13c, + 0x9cd2df59, 0x55f2733f, 0x1814ce79, 0x73c737bf, 0x53f7cdea, 0x5ffdaa5b, 0xdf3d6f14, 0x7844db86, + 0xcaaff381, 0xb968c43e, 0x3824342c, 0xc2a3405f, 0x161dc372, 0xbce2250c, 0x283c498b, 0xff0d9541, + 0x39a80171, 0x080cb3de, 0xd8b4e49c, 0x6456c190, 0x7bcb8461, 0xd532b670, 0x486c5c74, 0xd0b85742, +}; + +static uint8_t byte32(uint32_t x, int n) +{ + return (uint8_t)(x >> (8 * n)); +} + +static uint32_t ror32(uint32_t x, int n) +{ + return (x >> n) | (x << (32 - n)); +} + +static uint32_t setup_mix(uint32_t x) +{ + return (Te[byte32(x, 2)] << 24) ^ (Te[byte32(x, 1)] << 16) ^ (Te[byte32(x, 0)] << 8) ^ Te[byte32(x, 3)]; +} + +static uint32_t setup_mix2(uint32_t x) +{ + return TD[Te[byte32(x, 3)]] ^ ror32(TD[Te[byte32(x, 2)]], 8) ^ ror32(TD[Te[byte32(x, 1)]], 16) ^ ror32(TD[Te[byte32(x, 0)]], 24); +} + +void aes128_init(aes128_key* ctx, const uint8_t* key) +{ +#if PLATFORM_SUPPORTS_AESNI + if (aes128_supported_x86()) + { + aes128_init_x86(ctx, key); + return; + } +#endif + + uint32_t* ekey = ctx->key; + + ekey[0] = get32be(key + 0); + ekey[1] = get32be(key + 4); + ekey[2] = get32be(key + 8); + ekey[3] = get32be(key + 12); + + for (size_t i=0; i<10; i++) + { + uint32_t temp = ekey[3]; + ekey[4] = ekey[0] ^ setup_mix(temp) ^ (rcon[i] << 24); + ekey[5] = ekey[1] ^ ekey[4]; + ekey[6] = ekey[2] ^ ekey[5]; + ekey[7] = ekey[3] ^ ekey[6]; + ekey += 4; + } +} + +void aes128_init_dec(aes128_key* ctx, const uint8_t* key) +{ +#if PLATFORM_SUPPORTS_AESNI + if (aes128_supported_x86()) + { + aes128_init_dec_x86(ctx, key); + return; + } +#endif + + aes128_key enc; + aes128_init(&enc, key); + + uint32_t* ekey = enc.key + 40; + uint32_t* dkey = ctx->key; + + *dkey++ = ekey[0]; + *dkey++ = ekey[1]; + *dkey++ = ekey[2]; + *dkey++ = ekey[3]; + ekey -= 4; + + for (size_t i = 0; i < 9; i++) + { + *dkey++ = setup_mix2(ekey[0]); + *dkey++ = setup_mix2(ekey[1]); + *dkey++ = setup_mix2(ekey[2]); + *dkey++ = setup_mix2(ekey[3]); + ekey -= 4; + } + + *dkey++ = ekey[0]; + *dkey++ = ekey[1]; + *dkey++ = ekey[2]; + *dkey++ = ekey[3]; +} + +static void aes128_encrypt(const aes128_key* ctx, const uint8_t* input, uint8_t* output) +{ + uint32_t t0, t1, t2, t3; + const uint32_t* key = ctx->key; + + uint32_t s0 = get32be(input + 0) ^ *key++; + uint32_t s1 = get32be(input + 4) ^ *key++; + uint32_t s2 = get32be(input + 8) ^ *key++; + uint32_t s3 = get32be(input + 12) ^ *key++; + + for (size_t i = 0; i<4; i++) + { + t0 = TE[byte32(s0, 3)] ^ ror32(TE[byte32(s1, 2)], 8) ^ ror32(TE[byte32(s2, 1)], 16) ^ ror32(TE[byte32(s3, 0)], 24) ^ *key++; + t1 = TE[byte32(s1, 3)] ^ ror32(TE[byte32(s2, 2)], 8) ^ ror32(TE[byte32(s3, 1)], 16) ^ ror32(TE[byte32(s0, 0)], 24) ^ *key++; + t2 = TE[byte32(s2, 3)] ^ ror32(TE[byte32(s3, 2)], 8) ^ ror32(TE[byte32(s0, 1)], 16) ^ ror32(TE[byte32(s1, 0)], 24) ^ *key++; + t3 = TE[byte32(s3, 3)] ^ ror32(TE[byte32(s0, 2)], 8) ^ ror32(TE[byte32(s1, 1)], 16) ^ ror32(TE[byte32(s2, 0)], 24) ^ *key++; + + s0 = TE[byte32(t0, 3)] ^ ror32(TE[byte32(t1, 2)], 8) ^ ror32(TE[byte32(t2, 1)], 16) ^ ror32(TE[byte32(t3, 0)], 24) ^ *key++; + s1 = TE[byte32(t1, 3)] ^ ror32(TE[byte32(t2, 2)], 8) ^ ror32(TE[byte32(t3, 1)], 16) ^ ror32(TE[byte32(t0, 0)], 24) ^ *key++; + s2 = TE[byte32(t2, 3)] ^ ror32(TE[byte32(t3, 2)], 8) ^ ror32(TE[byte32(t0, 1)], 16) ^ ror32(TE[byte32(t1, 0)], 24) ^ *key++; + s3 = TE[byte32(t3, 3)] ^ ror32(TE[byte32(t0, 2)], 8) ^ ror32(TE[byte32(t1, 1)], 16) ^ ror32(TE[byte32(t2, 0)], 24) ^ *key++; + } + + t0 = TE[byte32(s0, 3)] ^ ror32(TE[byte32(s1, 2)], 8) ^ ror32(TE[byte32(s2, 1)], 16) ^ ror32(TE[byte32(s3, 0)], 24) ^ *key++; + t1 = TE[byte32(s1, 3)] ^ ror32(TE[byte32(s2, 2)], 8) ^ ror32(TE[byte32(s3, 1)], 16) ^ ror32(TE[byte32(s0, 0)], 24) ^ *key++; + t2 = TE[byte32(s2, 3)] ^ ror32(TE[byte32(s3, 2)], 8) ^ ror32(TE[byte32(s0, 1)], 16) ^ ror32(TE[byte32(s1, 0)], 24) ^ *key++; + t3 = TE[byte32(s3, 3)] ^ ror32(TE[byte32(s0, 2)], 8) ^ ror32(TE[byte32(s1, 1)], 16) ^ ror32(TE[byte32(s2, 0)], 24) ^ *key++; + + s0 = (Te[byte32(t0, 3)] << 24) ^ (Te[byte32(t1, 2)] << 16) ^ (Te[byte32(t2, 1)] << 8) ^ Te[byte32(t3, 0)] ^ *key++; + s1 = (Te[byte32(t1, 3)] << 24) ^ (Te[byte32(t2, 2)] << 16) ^ (Te[byte32(t3, 1)] << 8) ^ Te[byte32(t0, 0)] ^ *key++; + s2 = (Te[byte32(t2, 3)] << 24) ^ (Te[byte32(t3, 2)] << 16) ^ (Te[byte32(t0, 1)] << 8) ^ Te[byte32(t1, 0)] ^ *key++; + s3 = (Te[byte32(t3, 3)] << 24) ^ (Te[byte32(t0, 2)] << 16) ^ (Te[byte32(t1, 1)] << 8) ^ Te[byte32(t2, 0)] ^ *key++; + + set32be(output + 0, s0); + set32be(output + 4, s1); + set32be(output + 8, s2); + set32be(output + 12, s3); +} + +static void aes128_decrypt(const aes128_key* ctx, const uint8_t* input, uint8_t* output) +{ + const uint32_t* key = ctx->key; + + uint32_t s0 = get32be(input + 0) ^ *key++; + uint32_t s1 = get32be(input + 4) ^ *key++; + uint32_t s2 = get32be(input + 8) ^ *key++; + uint32_t s3 = get32be(input + 12) ^ *key++; + + uint32_t t0 = TD[byte32(s0, 3)] ^ ror32(TD[byte32(s3, 2)], 8) ^ ror32(TD[byte32(s2, 1)], 16) ^ ror32(TD[byte32(s1, 0)], 24) ^ *key++; + uint32_t t1 = TD[byte32(s1, 3)] ^ ror32(TD[byte32(s0, 2)], 8) ^ ror32(TD[byte32(s3, 1)], 16) ^ ror32(TD[byte32(s2, 0)], 24) ^ *key++; + uint32_t t2 = TD[byte32(s2, 3)] ^ ror32(TD[byte32(s1, 2)], 8) ^ ror32(TD[byte32(s0, 1)], 16) ^ ror32(TD[byte32(s3, 0)], 24) ^ *key++; + uint32_t t3 = TD[byte32(s3, 3)] ^ ror32(TD[byte32(s2, 2)], 8) ^ ror32(TD[byte32(s1, 1)], 16) ^ ror32(TD[byte32(s0, 0)], 24) ^ *key++; + + for (size_t i = 0; i < 4; i++) + { + s0 = TD[byte32(t0, 3)] ^ ror32(TD[byte32(t3, 2)], 8) ^ ror32(TD[byte32(t2, 1)], 16) ^ ror32(TD[byte32(t1, 0)], 24) ^ *key++; + s1 = TD[byte32(t1, 3)] ^ ror32(TD[byte32(t0, 2)], 8) ^ ror32(TD[byte32(t3, 1)], 16) ^ ror32(TD[byte32(t2, 0)], 24) ^ *key++; + s2 = TD[byte32(t2, 3)] ^ ror32(TD[byte32(t1, 2)], 8) ^ ror32(TD[byte32(t0, 1)], 16) ^ ror32(TD[byte32(t3, 0)], 24) ^ *key++; + s3 = TD[byte32(t3, 3)] ^ ror32(TD[byte32(t2, 2)], 8) ^ ror32(TD[byte32(t1, 1)], 16) ^ ror32(TD[byte32(t0, 0)], 24) ^ *key++; + + t0 = TD[byte32(s0, 3)] ^ ror32(TD[byte32(s3, 2)], 8) ^ ror32(TD[byte32(s2, 1)], 16) ^ ror32(TD[byte32(s1, 0)], 24) ^ *key++; + t1 = TD[byte32(s1, 3)] ^ ror32(TD[byte32(s0, 2)], 8) ^ ror32(TD[byte32(s3, 1)], 16) ^ ror32(TD[byte32(s2, 0)], 24) ^ *key++; + t2 = TD[byte32(s2, 3)] ^ ror32(TD[byte32(s1, 2)], 8) ^ ror32(TD[byte32(s0, 1)], 16) ^ ror32(TD[byte32(s3, 0)], 24) ^ *key++; + t3 = TD[byte32(s3, 3)] ^ ror32(TD[byte32(s2, 2)], 8) ^ ror32(TD[byte32(s1, 1)], 16) ^ ror32(TD[byte32(s0, 0)], 24) ^ *key++; + } + + s0 = (Td[byte32(t0, 3)] << 24) ^ (Td[byte32(t3, 2)] << 16) ^ (Td[byte32(t2, 1)] << 8) ^ Td[byte32(t1, 0)] ^ *key++; + s1 = (Td[byte32(t1, 3)] << 24) ^ (Td[byte32(t0, 2)] << 16) ^ (Td[byte32(t3, 1)] << 8) ^ Td[byte32(t2, 0)] ^ *key++; + s2 = (Td[byte32(t2, 3)] << 24) ^ (Td[byte32(t1, 2)] << 16) ^ (Td[byte32(t0, 1)] << 8) ^ Td[byte32(t3, 0)] ^ *key++; + s3 = (Td[byte32(t3, 3)] << 24) ^ (Td[byte32(t2, 2)] << 16) ^ (Td[byte32(t1, 1)] << 8) ^ Td[byte32(t0, 0)] ^ *key++; + + set32be(output + 0, s0); + set32be(output + 4, s1); + set32be(output + 8, s2); + set32be(output + 12, s3); +} + +void aes128_ecb_encrypt(const aes128_key* ctx, const uint8_t* input, uint8_t* output) +{ +#if PLATFORM_SUPPORTS_AESNI + if (aes128_supported_x86()) + { + aes128_ecb_encrypt_x86(ctx, input, output); + return; + } +#endif + aes128_encrypt(ctx, input, output); +} + +void aes128_ecb_decrypt(const aes128_key* ctx, const uint8_t* input, uint8_t* output) +{ +#if PLATFORM_SUPPORTS_AESNI + if (aes128_supported_x86()) + { + aes128_ecb_decrypt_x86(ctx, input, output); + return; + } +#endif + aes128_decrypt(ctx, input, output); +} + +static void ctr_add(uint8_t* counter, uint64_t n) +{ + for (int i=15; i>=0; i--) + { + n = n + counter[i]; + counter[i] = (uint8_t)n; + n >>= 8; + } +} + +void aes128_ctr_xor(const aes128_key* context, const uint8_t* iv, uint64_t block, uint8_t* buffer, size_t size) +{ + uint8_t tmp[16]; + uint8_t counter[16]; + for (uint32_t i=0; i<16; i++) + { + counter[i] = iv[i]; + } + ctr_add(counter, block); + +#if PLATFORM_SUPPORTS_AESNI + if (aes128_supported_x86()) + { + aes128_ctr_xor_x86(context, counter, buffer, size); + return; + } +#endif + + while (size >= 16) + { + aes128_encrypt(context, counter, tmp); + for (uint32_t i=0; i<16; i++) + { + *buffer++ ^= tmp[i]; + } + ctr_add(counter, 1); + size -= 16; + } + + if (size != 0) + { + aes128_encrypt(context, counter, tmp); + for (size_t i=0; ikey, key); + memset(ctx->last, 0, 16); + ctx->size = 0; +} + +static void aes128_cmac_update(aes128_cmac_ctx* ctx, const uint8_t* buffer, uint32_t size) +{ + if (ctx->size + size <= 16) + { + memcpy(ctx->block + ctx->size, buffer, size); + ctx->size += size; + return; + } + + if (ctx->size != 0) + { + uint32_t avail = 16 - ctx->size; + memcpy(ctx->block + ctx->size, buffer, avail < size ? avail : size); + buffer += avail; + size -= avail; + + aes128_cmac_process(&ctx->key, ctx->last, ctx->block, 16); + } + + if (size >= 16) + { + uint32_t full = (size - 1) & ~15; + aes128_cmac_process(&ctx->key, ctx->last, buffer, full); + buffer += full; + size -= full; + } + + memcpy(ctx->block, buffer, size); + ctx->size = size; +} + +static void cmac_gfmul(uint8_t* block) +{ + uint8_t carry = 0; + for (int i = 15; i >= 0; i--) + { + uint8_t x = block[i]; + block[i] = (block[i] << 1) | (carry >> 7); + carry = x; + } + + block[15] ^= (carry & 0x80 ? 0x87 : 0); +} + +static void aes128_cmac_done(aes128_cmac_ctx* ctx, uint8_t* mac) +{ + uint8_t zero[16] = { 0 }; + aes128_ecb_encrypt(&ctx->key, zero, mac); + + cmac_gfmul(mac); + + if (ctx->size != 16) + { + cmac_gfmul(mac); + + ctx->block[ctx->size] = 0x80; + memset(ctx->block + ctx->size + 1, 0, 16 - (ctx->size + 1)); + } + + for (size_t i = 0; i < 16; i++) + { + mac[i] ^= ctx->block[i]; + } + + aes128_cmac_process(&ctx->key, mac, ctx->last, 16); +} + +void aes128_cmac(const uint8_t* key, const uint8_t* buffer, uint32_t size, uint8_t* mac) +{ + aes128_cmac_ctx ctx; + aes128_cmac_init(&ctx, key); + aes128_cmac_update(&ctx, buffer, size); + aes128_cmac_done(&ctx, mac); +} + +void aes128_psp_decrypt(const aes128_key* ctx, const uint8_t* iv, uint32_t index, uint8_t* buffer, uint32_t size) +{ + assert(size % 16 == 0); + + uint8_t PKG_ALIGN(16) prev[16]; + uint8_t PKG_ALIGN(16) block[16]; + + if (index == 0) + { + memset(prev, 0, 16); + } + else + { + memcpy(prev, iv, 12); + set32le(prev + 12, index); + } + + memcpy(block, iv, 16); + set32le(block + 12, index); + +#if PLATFORM_SUPPORTS_AESNI + if (aes128_supported_x86()) + { + aes128_psp_decrypt_x86(ctx, prev, block, buffer, size); + return; + } +#endif + + for (uint32_t i = 0; i < size; i += 16) + { + set32le(block + 12, get32le(block + 12) + 1); + + uint8_t out[16]; + aes128_ecb_decrypt(ctx, block, out); + + for (size_t k = 0; k < 16; k++) + { + *buffer++ ^= prev[k] ^ out[k]; + } + memcpy(prev, block, 16); + } +} diff --git a/tools/4/source/src/pkg2zip_aes.h b/tools/4/source/src/pkg2zip_aes.h new file mode 100644 index 0000000..cfd36f8 --- /dev/null +++ b/tools/4/source/src/pkg2zip_aes.h @@ -0,0 +1,29 @@ +#pragma once + +#include "pkg2zip_utils.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef struct aes128_key { + uint32_t PKG_ALIGN(16) key[44]; +} aes128_key; + +void aes128_init(aes128_key* ctx, const uint8_t* key); +void aes128_init_dec(aes128_key* ctx, const uint8_t* key); + +void aes128_ecb_encrypt(const aes128_key* ctx, const uint8_t* input, uint8_t* output); +void aes128_ecb_decrypt(const aes128_key* ctx, const uint8_t* input, uint8_t* output); + +void aes128_ctr_xor(const aes128_key* ctx, const uint8_t* iv, uint64_t block, uint8_t* buffer, size_t size); + +void aes128_cmac(const uint8_t* key, const uint8_t* buffer, uint32_t size, uint8_t* mac); + +void aes128_psp_decrypt(const aes128_key* ctx, const uint8_t* iv, uint32_t index, uint8_t* buffer, uint32_t size); +int aes128_supported_x86(); + +#ifdef __cplusplus +} +#endif diff --git a/tools/4/source/src/pkg2zip_aes_x86.c b/tools/4/source/src/pkg2zip_aes_x86.c new file mode 100644 index 0000000..de3a05a --- /dev/null +++ b/tools/4/source/src/pkg2zip_aes_x86.c @@ -0,0 +1,206 @@ +#include "pkg2zip_aes.h" + +#include +#include // AESNI +#include // SSSE3 +#include "pkg2zip_aes_x86.h" + +#define AES128_INIT(ctx, x, rcon) \ +{ \ + __m128i a, b; \ + _mm_store_si128(ctx, x); \ + a = _mm_aeskeygenassist_si128(x, rcon); \ + a = _mm_shuffle_epi32(a, 0xff); \ + b = _mm_slli_si128(x, 4); \ + x = _mm_xor_si128(x, b); \ + b = _mm_slli_si128(b, 4); \ + x = _mm_xor_si128(x, b); \ + b = _mm_slli_si128(b, 4); \ + x = _mm_xor_si128(x, b); \ + x = _mm_xor_si128(x, a); \ +} + +/*void region_xor_sse(unsigned char* dst, unsigned char* src, int block_size) +{ + __m128i* dst_ptr = (__m128i*)dst; + + __m128i xmm1 = _mm_load_si128((__m128i*)src); + __m128i xmm2 = _mm_load_si128(dst_ptr); + + xmm2 = _mm_xor_si128(xmm1, xmm2); + _mm_store_si128(dst_ptr, xmm2); +}*/ + +void region_xor_sse(unsigned char* dst, unsigned char* src, int len) +{ + unsigned char * restrict p1 = __builtin_assume_aligned(src, 16); + unsigned char * restrict p2 = __builtin_assume_aligned(dst, 16); + + unsigned int i; + for (i = 0; i < len; ++i) + p2[i] = p1[i] ^ p2[i]; +} + +void xor1_sse(unsigned char *dest, unsigned char *src1, unsigned char *src2, int size) +{ + int i; + for(i = 0; i < size; i++) + { + dest[i] = src1[i] ^ src2[i]; + } +} + +void aes128_init_x86(aes128_key* ctx, const uint8_t* key) +{ + __m128i* ekey = (__m128i*)ctx->key; + + __m128i x = _mm_loadu_si128((const __m128i*)key); + AES128_INIT(ekey + 0, x, 0x01); + AES128_INIT(ekey + 1, x, 0x02); + AES128_INIT(ekey + 2, x, 0x04); + AES128_INIT(ekey + 3, x, 0x08); + AES128_INIT(ekey + 4, x, 0x10); + AES128_INIT(ekey + 5, x, 0x20); + AES128_INIT(ekey + 6, x, 0x40); + AES128_INIT(ekey + 7, x, 0x80); + AES128_INIT(ekey + 8, x, 0x1b); + AES128_INIT(ekey + 9, x, 0x36); + _mm_store_si128(ekey + 10, x); +} + +void aes128_init_dec_x86(aes128_key* ctx, const uint8_t* key) +{ + aes128_key enc; + aes128_init_x86(&enc, key); + + const __m128i* ekey = (__m128i*)&enc.key; + __m128i* dkey = (__m128i*)&ctx->key; + + _mm_store_si128(dkey + 10, _mm_load_si128(ekey + 0)); + for (size_t i = 1; i < 10; i++) + { + _mm_store_si128(dkey + 10 - i, _mm_aesimc_si128(_mm_load_si128(ekey + i))); + } + _mm_store_si128(dkey + 0, _mm_load_si128(ekey + 10)); +} + +static __m128i aes128_encrypt_x86(__m128i input, const __m128i* key) +{ + __m128i tmp = _mm_xor_si128(input, _mm_load_si128(key + 0)); + tmp = _mm_aesenc_si128(tmp, _mm_load_si128(key + 1)); + tmp = _mm_aesenc_si128(tmp, _mm_load_si128(key + 2)); + tmp = _mm_aesenc_si128(tmp, _mm_load_si128(key + 3)); + tmp = _mm_aesenc_si128(tmp, _mm_load_si128(key + 4)); + tmp = _mm_aesenc_si128(tmp, _mm_load_si128(key + 5)); + tmp = _mm_aesenc_si128(tmp, _mm_load_si128(key + 6)); + tmp = _mm_aesenc_si128(tmp, _mm_load_si128(key + 7)); + tmp = _mm_aesenc_si128(tmp, _mm_load_si128(key + 8)); + tmp = _mm_aesenc_si128(tmp, _mm_load_si128(key + 9)); + return _mm_aesenclast_si128(tmp, _mm_load_si128(key + 10)); +} + +static __m128i aes128_decrypt_x86(__m128i input, const __m128i* key) +{ + __m128i tmp = _mm_xor_si128(input, _mm_load_si128(key + 0)); + tmp = _mm_aesdec_si128(tmp, _mm_load_si128(key + 1)); + tmp = _mm_aesdec_si128(tmp, _mm_load_si128(key + 2)); + tmp = _mm_aesdec_si128(tmp, _mm_load_si128(key + 3)); + tmp = _mm_aesdec_si128(tmp, _mm_load_si128(key + 4)); + tmp = _mm_aesdec_si128(tmp, _mm_load_si128(key + 5)); + tmp = _mm_aesdec_si128(tmp, _mm_load_si128(key + 6)); + tmp = _mm_aesdec_si128(tmp, _mm_load_si128(key + 7)); + tmp = _mm_aesdec_si128(tmp, _mm_load_si128(key + 8)); + tmp = _mm_aesdec_si128(tmp, _mm_load_si128(key + 9)); + return _mm_aesdeclast_si128(tmp, _mm_load_si128(key + 10)); +} + +void aes128_ecb_encrypt_x86(const aes128_key* ctx, const uint8_t* input, uint8_t* output) +{ + const __m128i* key = (__m128i*)ctx->key; + __m128i tmp = aes128_encrypt_x86(_mm_loadu_si128((const __m128i*)input), key); + _mm_storeu_si128((__m128i*)output, tmp); +} + +void aes128_ecb_decrypt_x86(const aes128_key* ctx, const uint8_t* input, uint8_t* output) +{ + const __m128i* key = (__m128i*)ctx->key; + __m128i tmp = aes128_decrypt_x86(_mm_loadu_si128((const __m128i*)input), key); + _mm_storeu_si128((__m128i*)output, tmp); +} + +static __m128i ctr_increment(__m128i counter) +{ + __m128i swap = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + __m128i tmp = _mm_shuffle_epi8(counter, swap); + tmp = _mm_add_epi64(tmp, _mm_set_epi32(0, 0, 0, 1)); + return _mm_shuffle_epi8(tmp, swap); +} + +void aes128_ctr_xor_x86(const aes128_key* ctx, const uint8_t* iv, uint8_t* buffer, size_t size) +{ + const __m128i* key = (__m128i*)ctx->key; + __m128i counter = _mm_loadu_si128((const __m128i*)iv); + + while (size >= 16) + { + __m128i block = aes128_encrypt_x86(counter, key); + __m128i tmp = _mm_xor_si128(_mm_loadu_si128((const __m128i*)buffer), block); + _mm_storeu_si128((__m128i*)buffer, tmp); + + counter = ctr_increment(counter); + + buffer += 16; + size -= 16; + } + + if (size != 0) + { + uint8_t full[16]; + memcpy(full, buffer, size); + memset(full + size, 0, 16 - size); + + __m128i block = aes128_encrypt_x86(counter, key); + __m128i tmp = _mm_xor_si128(_mm_loadu_si128((const __m128i*)full), block); + _mm_storeu_si128((__m128i*)full, tmp); + + memcpy(buffer, full, size); + } +} + +void aes128_cmac_process_x86(const aes128_key* ctx, uint8_t* block, const uint8_t* buffer, uint32_t size) +{ + const __m128i* key = (__m128i*)ctx->key; + __m128i* data = (__m128i*)buffer; + + __m128i tmp = _mm_loadu_si128((__m128i*)block); + for (uint32_t i = 0; i < size; i += 16) + { + __m128i input = _mm_loadu_si128(data++); + tmp = _mm_xor_si128(tmp, input); + tmp = aes128_encrypt_x86(tmp, key); + } + _mm_storeu_si128((__m128i*)block, tmp); +} + +void aes128_psp_decrypt_x86(const aes128_key* ctx, const uint8_t* prev, const uint8_t* block, uint8_t* buffer, uint32_t size) +{ + const __m128i* key = (__m128i*)ctx->key; + __m128i one = _mm_setr_epi32(0, 0, 0, 1); + + __m128i x = _mm_load_si128((__m128i*)prev); + __m128i y = _mm_load_si128((__m128i*)block); + + __m128i* data = (__m128i*)buffer; + + for (uint32_t i = 0; i < size; i += 16) + { + y = _mm_add_epi32(y, one); + + __m128i out = aes128_decrypt_x86(y, key); + + out = _mm_xor_si128(out, _mm_loadu_si128(data)); + out = _mm_xor_si128(out, x); + _mm_storeu_si128(data++, out); + x = y; + } +} diff --git a/tools/4/source/src/pkg2zip_aes_x86.h b/tools/4/source/src/pkg2zip_aes_x86.h new file mode 100644 index 0000000..d056bd2 --- /dev/null +++ b/tools/4/source/src/pkg2zip_aes_x86.h @@ -0,0 +1,21 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + + +void aes128_init_x86(aes128_key* context, const uint8_t* key); +void aes128_init_dec_x86(aes128_key* context, const uint8_t* key); +void aes128_ecb_encrypt_x86(const aes128_key* context, const uint8_t* input, uint8_t* output); +void aes128_ecb_decrypt_x86(const aes128_key* context, const uint8_t* input, uint8_t* output); +void aes128_ctr_xor_x86(const aes128_key* context, const uint8_t* iv, uint8_t* buffer, size_t size); +void aes128_cmac_process_x86(const aes128_key* ctx, uint8_t* block, const uint8_t *buffer, uint32_t size); +void aes128_psp_decrypt_x86(const aes128_key* ctx, const uint8_t* prev, const uint8_t* block, uint8_t* buffer, uint32_t size); + +void region_xor_sse( unsigned char* dst, unsigned char* src, int block_size); +void xor1_sse(unsigned char *dest, unsigned char *src1, unsigned char *src2, int size); + +#ifdef __cplusplus +} +#endif diff --git a/tools/4/source/src/pkg2zip_utils.h b/tools/4/source/src/pkg2zip_utils.h new file mode 100644 index 0000000..695dcda --- /dev/null +++ b/tools/4/source/src/pkg2zip_utils.h @@ -0,0 +1,118 @@ +#pragma once + +#include +#include + +#if defined(_MSC_VER) +# define NORETURN __declspec(noreturn) +# define PKG_ALIGN(x) __declspec(align(x)) +#else +# define NORETURN __attribute__((noreturn)) +# define PKG_ALIGN(x) __attribute__((aligned(x))) +#endif + +static inline uint32_t min32(uint32_t a, uint32_t b) +{ + return a < b ? a : b; +} + +static inline uint64_t min64(uint64_t a, uint64_t b) +{ + return a < b ? a : b; +} + +static inline uint16_t get16le(const uint8_t* bytes) +{ + return (bytes[0]) | (bytes[1] << 8); +} + +static inline uint32_t get32le(const uint8_t* bytes) +{ + return (bytes[0]) | (bytes[1] << 8) | (bytes[2] << 16) | (bytes[3] << 24); +} + +static inline uint64_t get64le(const uint8_t* bytes) +{ + return (uint64_t)bytes[0] + | ((uint64_t)bytes[1] << 8) + | ((uint64_t)bytes[2] << 16) + | ((uint64_t)bytes[3] << 24) + | ((uint64_t)bytes[4] << 32) + | ((uint64_t)bytes[5] << 40) + | ((uint64_t)bytes[6] << 48) + | ((uint64_t)bytes[7] << 56); +} + +static inline uint16_t get16be(const uint8_t* bytes) +{ + return (bytes[1]) | (bytes[0] << 8); +} + +static inline uint32_t get32be(const uint8_t* bytes) +{ + return (bytes[3]) | (bytes[2] << 8) | (bytes[1] << 16) | (bytes[0] << 24); +} + +static inline uint64_t get64be(const uint8_t* bytes) +{ + return (uint64_t)bytes[7] + | ((uint64_t)bytes[6] << 8) + | ((uint64_t)bytes[5] << 16) + | ((uint64_t)bytes[4] << 24) + | ((uint64_t)bytes[3] << 32) + | ((uint64_t)bytes[2] << 40) + | ((uint64_t)bytes[1] << 48) + | ((uint64_t)bytes[0] << 56); +} + +static inline void set16le(uint8_t* bytes, uint16_t x) +{ + bytes[0] = (uint8_t)x; + bytes[1] = (uint8_t)(x >> 8); +} + +static inline void set32le(uint8_t* bytes, uint32_t x) +{ + bytes[0] = (uint8_t)x; + bytes[1] = (uint8_t)(x >> 8); + bytes[2] = (uint8_t)(x >> 16); + bytes[3] = (uint8_t)(x >> 24); +} + +static inline void set64le(uint8_t* bytes, uint64_t x) +{ + bytes[0] = (uint8_t)x; + bytes[1] = (uint8_t)(x >> 8); + bytes[2] = (uint8_t)(x >> 16); + bytes[3] = (uint8_t)(x >> 24); + bytes[4] = (uint8_t)(x >> 32); + bytes[5] = (uint8_t)(x >> 40); + bytes[6] = (uint8_t)(x >> 48); + bytes[7] = (uint8_t)(x >> 56); +} + +static inline void set16be(uint8_t* bytes, uint16_t x) +{ + bytes[0] = (uint8_t)(x >> 8); + bytes[1] = (uint8_t)x; +} + +static inline void set32be(uint8_t* bytes, uint32_t x) +{ + bytes[0] = (uint8_t)(x >> 24); + bytes[1] = (uint8_t)(x >> 16); + bytes[2] = (uint8_t)(x >> 8); + bytes[3] = (uint8_t)x; +} + +static inline void set64be(uint8_t* bytes, uint64_t x) +{ + bytes[0] = (uint8_t)(x >> 56); + bytes[1] = (uint8_t)(x >> 48); + bytes[2] = (uint8_t)(x >> 40); + bytes[3] = (uint8_t)(x >> 32); + bytes[4] = (uint8_t)(x >> 24); + bytes[5] = (uint8_t)(x >> 16); + bytes[6] = (uint8_t)(x >> 8); + bytes[7] = (uint8_t)x; +} diff --git a/tools/4/source/src/sha1.c b/tools/4/source/src/sha1.c new file mode 100644 index 0000000..aa3b31b --- /dev/null +++ b/tools/4/source/src/sha1.c @@ -0,0 +1,399 @@ +/* + * FIPS-180-1 compliant SHA-1 implementation + * + * Copyright (C) 2006-2010, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * The SHA-1 standard was published by NIST in 1993. + * + * http://www.itl.nist.gov/fipspubs/fip180-1.htm + */ + +#include "sha1.h" + +/* + * 32-bit integer manipulation macros (big endian) + */ +#ifndef GET_ULONG_BE +#define GET_ULONG_BE(n,b,i) \ +{ \ + (n) = ( (unsigned long) (b)[(i) ] << 24 ) \ + | ( (unsigned long) (b)[(i) + 1] << 16 ) \ + | ( (unsigned long) (b)[(i) + 2] << 8 ) \ + | ( (unsigned long) (b)[(i) + 3] ); \ +} +#endif + +#ifndef PUT_ULONG_BE +#define PUT_ULONG_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} +#endif + +/* + * SHA-1 context setup + */ +void sha1_starts( sha1_context *ctx ) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; + ctx->state[4] = 0xC3D2E1F0; +} + +static void sha1_process( sha1_context *ctx, const unsigned char data[64] ) +{ + unsigned long temp, W[16], A, B, C, D, E; + + GET_ULONG_BE( W[ 0], data, 0 ); + GET_ULONG_BE( W[ 1], data, 4 ); + GET_ULONG_BE( W[ 2], data, 8 ); + GET_ULONG_BE( W[ 3], data, 12 ); + GET_ULONG_BE( W[ 4], data, 16 ); + GET_ULONG_BE( W[ 5], data, 20 ); + GET_ULONG_BE( W[ 6], data, 24 ); + GET_ULONG_BE( W[ 7], data, 28 ); + GET_ULONG_BE( W[ 8], data, 32 ); + GET_ULONG_BE( W[ 9], data, 36 ); + GET_ULONG_BE( W[10], data, 40 ); + GET_ULONG_BE( W[11], data, 44 ); + GET_ULONG_BE( W[12], data, 48 ); + GET_ULONG_BE( W[13], data, 52 ); + GET_ULONG_BE( W[14], data, 56 ); + GET_ULONG_BE( W[15], data, 60 ); + +#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) + +#define R(t) \ +( \ + temp = W[(t - 3) & 0x0F] ^ W[(t - 8) & 0x0F] ^ \ + W[(t - 14) & 0x0F] ^ W[ t & 0x0F], \ + ( W[t & 0x0F] = S(temp,1) ) \ +) + +#define P(a,b,c,d,e,x) \ +{ \ + e += S(a,5) + F(b,c,d) + K + x; b = S(b,30); \ +} + + A = ctx->state[0]; + B = ctx->state[1]; + C = ctx->state[2]; + D = ctx->state[3]; + E = ctx->state[4]; + +#define F(x,y,z) (z ^ (x & (y ^ z))) +#define K 0x5A827999 + + P( A, B, C, D, E, W[0] ); + P( E, A, B, C, D, W[1] ); + P( D, E, A, B, C, W[2] ); + P( C, D, E, A, B, W[3] ); + P( B, C, D, E, A, W[4] ); + P( A, B, C, D, E, W[5] ); + P( E, A, B, C, D, W[6] ); + P( D, E, A, B, C, W[7] ); + P( C, D, E, A, B, W[8] ); + P( B, C, D, E, A, W[9] ); + P( A, B, C, D, E, W[10] ); + P( E, A, B, C, D, W[11] ); + P( D, E, A, B, C, W[12] ); + P( C, D, E, A, B, W[13] ); + P( B, C, D, E, A, W[14] ); + P( A, B, C, D, E, W[15] ); + P( E, A, B, C, D, R(16) ); + P( D, E, A, B, C, R(17) ); + P( C, D, E, A, B, R(18) ); + P( B, C, D, E, A, R(19) ); + +#undef K +#undef F + +#define F(x,y,z) (x ^ y ^ z) +#define K 0x6ED9EBA1 + + P( A, B, C, D, E, R(20) ); + P( E, A, B, C, D, R(21) ); + P( D, E, A, B, C, R(22) ); + P( C, D, E, A, B, R(23) ); + P( B, C, D, E, A, R(24) ); + P( A, B, C, D, E, R(25) ); + P( E, A, B, C, D, R(26) ); + P( D, E, A, B, C, R(27) ); + P( C, D, E, A, B, R(28) ); + P( B, C, D, E, A, R(29) ); + P( A, B, C, D, E, R(30) ); + P( E, A, B, C, D, R(31) ); + P( D, E, A, B, C, R(32) ); + P( C, D, E, A, B, R(33) ); + P( B, C, D, E, A, R(34) ); + P( A, B, C, D, E, R(35) ); + P( E, A, B, C, D, R(36) ); + P( D, E, A, B, C, R(37) ); + P( C, D, E, A, B, R(38) ); + P( B, C, D, E, A, R(39) ); + +#undef K +#undef F + +#define F(x,y,z) ((x & y) | (z & (x | y))) +#define K 0x8F1BBCDC + + P( A, B, C, D, E, R(40) ); + P( E, A, B, C, D, R(41) ); + P( D, E, A, B, C, R(42) ); + P( C, D, E, A, B, R(43) ); + P( B, C, D, E, A, R(44) ); + P( A, B, C, D, E, R(45) ); + P( E, A, B, C, D, R(46) ); + P( D, E, A, B, C, R(47) ); + P( C, D, E, A, B, R(48) ); + P( B, C, D, E, A, R(49) ); + P( A, B, C, D, E, R(50) ); + P( E, A, B, C, D, R(51) ); + P( D, E, A, B, C, R(52) ); + P( C, D, E, A, B, R(53) ); + P( B, C, D, E, A, R(54) ); + P( A, B, C, D, E, R(55) ); + P( E, A, B, C, D, R(56) ); + P( D, E, A, B, C, R(57) ); + P( C, D, E, A, B, R(58) ); + P( B, C, D, E, A, R(59) ); + +#undef K +#undef F + +#define F(x,y,z) (x ^ y ^ z) +#define K 0xCA62C1D6 + + P( A, B, C, D, E, R(60) ); + P( E, A, B, C, D, R(61) ); + P( D, E, A, B, C, R(62) ); + P( C, D, E, A, B, R(63) ); + P( B, C, D, E, A, R(64) ); + P( A, B, C, D, E, R(65) ); + P( E, A, B, C, D, R(66) ); + P( D, E, A, B, C, R(67) ); + P( C, D, E, A, B, R(68) ); + P( B, C, D, E, A, R(69) ); + P( A, B, C, D, E, R(70) ); + P( E, A, B, C, D, R(71) ); + P( D, E, A, B, C, R(72) ); + P( C, D, E, A, B, R(73) ); + P( B, C, D, E, A, R(74) ); + P( A, B, C, D, E, R(75) ); + P( E, A, B, C, D, R(76) ); + P( D, E, A, B, C, R(77) ); + P( C, D, E, A, B, R(78) ); + P( B, C, D, E, A, R(79) ); + +#undef K +#undef F + + ctx->state[0] += A; + ctx->state[1] += B; + ctx->state[2] += C; + ctx->state[3] += D; + ctx->state[4] += E; +} + +/* + * SHA-1 process buffer + */ +void sha1_update( sha1_context *ctx, const unsigned char *input, size_t ilen ) +{ + size_t fill; + unsigned long left; + + if( ilen <= 0 ) + return; + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += (unsigned long) ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if( ctx->total[0] < (unsigned long) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + memcpy( (void *) (ctx->buffer + left), + (void *) input, fill ); + sha1_process( ctx, ctx->buffer ); + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + sha1_process( ctx, input ); + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + { + memcpy( (void *) (ctx->buffer + left), + (void *) input, ilen ); + } +} + +static const unsigned char sha1_padding[64] = +{ + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* + * SHA-1 final digest + */ +void sha1_finish( sha1_context *ctx, unsigned char output[20] ) +{ + unsigned long last, padn; + unsigned long high, low; + unsigned char msglen[8]; + + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_ULONG_BE( high, msglen, 0 ); + PUT_ULONG_BE( low, msglen, 4 ); + + last = ctx->total[0] & 0x3F; + padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); + + sha1_update( ctx, (unsigned char *) sha1_padding, padn ); + sha1_update( ctx, msglen, 8 ); + + PUT_ULONG_BE( ctx->state[0], output, 0 ); + PUT_ULONG_BE( ctx->state[1], output, 4 ); + PUT_ULONG_BE( ctx->state[2], output, 8 ); + PUT_ULONG_BE( ctx->state[3], output, 12 ); + PUT_ULONG_BE( ctx->state[4], output, 16 ); +} + +/* + * output = SHA-1( input buffer ) + */ +void sha1( const unsigned char *input, size_t ilen, unsigned char output[20] ) +{ + sha1_context ctx; + + sha1_starts( &ctx ); + sha1_update( &ctx, input, ilen ); + sha1_finish( &ctx, output ); + + memset( &ctx, 0, sizeof( sha1_context ) ); +} + +/* + * SHA-1 HMAC context setup + */ +void sha1_hmac_starts( sha1_context *ctx, const unsigned char *key, size_t keylen ) +{ + size_t i; + unsigned char sum[20]; + + if( keylen > 64 ) + { + sha1( key, keylen, sum ); + keylen = 20; + key = sum; + } + + memset( ctx->ipad, 0x36, 64 ); + memset( ctx->opad, 0x5C, 64 ); + + for( i = 0; i < keylen; i++ ) + { + ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] ); + ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] ); + } + + sha1_starts( ctx ); + sha1_update( ctx, ctx->ipad, 64 ); + + memset( sum, 0, sizeof( sum ) ); +} + +/* + * SHA-1 HMAC process buffer + */ +void sha1_hmac_update( sha1_context *ctx, const unsigned char *input, size_t ilen ) +{ + sha1_update( ctx, input, ilen ); +} + +/* + * SHA-1 HMAC final digest + */ +void sha1_hmac_finish( sha1_context *ctx, unsigned char output[20] ) +{ + unsigned char tmpbuf[20]; + + sha1_finish( ctx, tmpbuf ); + sha1_starts( ctx ); + sha1_update( ctx, ctx->opad, 64 ); + sha1_update( ctx, tmpbuf, 20 ); + sha1_finish( ctx, output ); + + memset( tmpbuf, 0, sizeof( tmpbuf ) ); +} + +/* + * SHA1 HMAC context reset + */ +void sha1_hmac_reset( sha1_context *ctx ) +{ + sha1_starts( ctx ); + sha1_update( ctx, ctx->ipad, 64 ); +} + +/* + * output = HMAC-SHA-1( hmac key, input buffer ) + */ +void sha1_hmac( const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char output[20] ) +{ + sha1_context ctx; + + sha1_hmac_starts( &ctx, key, keylen ); + sha1_hmac_update( &ctx, input, ilen ); + sha1_hmac_finish( &ctx, output ); + + memset( &ctx, 0, sizeof( sha1_context ) ); +} diff --git a/tools/4/source/src/sha1.h b/tools/4/source/src/sha1.h new file mode 100644 index 0000000..9ec45b2 --- /dev/null +++ b/tools/4/source/src/sha1.h @@ -0,0 +1,133 @@ +/** + * \file sha1.h + * + * \brief SHA-1 cryptographic hash function + * + * Copyright (C) 2006-2010, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_SHA1_H +#define POLARSSL_SHA1_H + +#include + +/** + * \brief SHA-1 context structure + */ +typedef struct +{ + unsigned long total[2]; /*!< number of bytes processed */ + unsigned long state[5]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ + + unsigned char ipad[64]; /*!< HMAC: inner padding */ + unsigned char opad[64]; /*!< HMAC: outer padding */ +} +sha1_context; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief SHA-1 context setup + * + * \param ctx context to be initialized + */ +void sha1_starts( sha1_context *ctx ); + +/** + * \brief SHA-1 process buffer + * + * \param ctx SHA-1 context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void sha1_update( sha1_context *ctx, const unsigned char *input, size_t ilen ); + +/** + * \brief SHA-1 final digest + * + * \param ctx SHA-1 context + * \param output SHA-1 checksum result + */ +void sha1_finish( sha1_context *ctx, unsigned char output[20] ); + +/** + * \brief Output = SHA-1( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output SHA-1 checksum result + */ +void sha1( const unsigned char *input, size_t ilen, unsigned char output[20] ); + +/** + * \brief SHA-1 HMAC context setup + * + * \param ctx HMAC context to be initialized + * \param key HMAC secret key + * \param keylen length of the HMAC key + */ +void sha1_hmac_starts( sha1_context *ctx, const unsigned char *key, size_t keylen ); + +/** + * \brief SHA-1 HMAC process buffer + * + * \param ctx HMAC context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void sha1_hmac_update( sha1_context *ctx, const unsigned char *input, size_t ilen ); + +/** + * \brief SHA-1 HMAC final digest + * + * \param ctx HMAC context + * \param output SHA-1 HMAC checksum result + */ +void sha1_hmac_finish( sha1_context *ctx, unsigned char output[20] ); + +/** + * \brief SHA-1 HMAC context reset + * + * \param ctx HMAC context to be reset + */ +void sha1_hmac_reset( sha1_context *ctx ); + +/** + * \brief Output = HMAC-SHA-1( hmac key, input buffer ) + * + * \param key HMAC secret key + * \param keylen length of the HMAC key + * \param input buffer holding the data + * \param ilen length of the input data + * \param output HMAC-SHA-1 result + */ +void sha1_hmac( const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char output[20] ); + +#ifdef __cplusplus +} +#endif + +#endif /* sha1.h */ diff --git a/tools/4/source/src/types.h b/tools/4/source/src/types.h new file mode 100644 index 0000000..4d323c0 --- /dev/null +++ b/tools/4/source/src/types.h @@ -0,0 +1,63 @@ +/* +* Copyright (c) 2011-2013 by naehrwert +* This file is released under the GPLv2. +*/ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +typedef char s8; +typedef unsigned char u8; +typedef short s16; +typedef unsigned short u16; +typedef int s32; +typedef unsigned int u32; +#if defined(_WIN32) && defined(_MSC_VER) +typedef __int64 s64; +typedef unsigned __int64 u64; +#else +typedef long long int s64; +typedef unsigned long long int u64; +#endif + +#define BOOL int +#define TRUE 1 +#define FALSE 0 + +//Align. +#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) + +//Bits <-> bytes conversion. +#define BITS2BYTES(x) ((x) / 8) +#define BYTES2BITS(x) ((x) * 8) + +//Endian swap for u16. +#define _ES16(val) \ + ((u16)(((((u16)val) & 0xff00) >> 8) | \ + ((((u16)val) & 0x00ff) << 8))) + +//Endian swap for u32. +#define _ES32(val) \ + ((u32)(((((u32)val) & 0xff000000) >> 24) | \ + ((((u32)val) & 0x00ff0000) >> 8 ) | \ + ((((u32)val) & 0x0000ff00) << 8 ) | \ + ((((u32)val) & 0x000000ff) << 24))) + +//Endian swap for u64. +#define _ES64(val) \ + ((u64)(((((u64)val) & 0xff00000000000000ull) >> 56) | \ + ((((u64)val) & 0x00ff000000000000ull) >> 40) | \ + ((((u64)val) & 0x0000ff0000000000ull) >> 24) | \ + ((((u64)val) & 0x000000ff00000000ull) >> 8 ) | \ + ((((u64)val) & 0x00000000ff000000ull) << 8 ) | \ + ((((u64)val) & 0x0000000000ff0000ull) << 24) | \ + ((((u64)val) & 0x000000000000ff00ull) << 40) | \ + ((((u64)val) & 0x00000000000000ffull) << 56))) + +#ifdef __cplusplus +} +#endif + diff --git a/tools/4/source/src/util.cpp b/tools/4/source/src/util.cpp new file mode 100644 index 0000000..adcd5a8 --- /dev/null +++ b/tools/4/source/src/util.cpp @@ -0,0 +1,522 @@ +/* +* Copyright (c) 2011-2013 by naehrwert +* This file is released under the GPLv2. +*/ + +#include +#include +#include +#include + +#include "types.h" +#include "util.h" + +u8 *_read_buffer(const s8 *file, u32 *length) +{ + FILE *fp; + u32 size; + + if((fp = fopen(file, "rb")) == NULL) + return NULL; + + fseek(fp, 0, SEEK_END); + size = ftell(fp); + fseek(fp, 0, SEEK_SET); + + u8 *buffer = (u8 *)malloc(sizeof(u8) * size); + fread(buffer, sizeof(u8), size, fp); + + if(length != NULL) + *length = size; + + fclose(fp); + + return buffer; +} + +int _write_buffer(const s8 *file, u8 *buffer, u32 length) +{ + FILE *fp; + + if((fp = fopen(file, "wb")) == NULL) + return 0; + + /**/ + while(length > 0) + { + u32 wrlen = 1024; + if(length < 1024) + wrlen = length; + fwrite(buffer, sizeof(u8), wrlen, fp); + length -= wrlen; + buffer += 1024; + } + /**/ + + //fwrite(buffer, sizeof(u8), length, fp); + + fclose(fp); + + return 1; +} + +#include "aes.h" +// Crypto functions (AES128-CBC, AES128-ECB, SHA1-HMAC and AES-CMAC). +void aescbc128_decrypt(unsigned char *key, unsigned char *iv, unsigned char *in, unsigned char *out, int len) +{ + aes_context ctx; + aes_setkey_dec(&ctx, key, 128); + aes_crypt_cbc(&ctx, AES_DECRYPT, len, iv, in, out); + + // Reset the IV. + memset(iv, 0, 0x10); +} + +void aescbc128_encrypt(unsigned char *key, unsigned char *iv, unsigned char *in, unsigned char *out, int len) +{ + aes_context ctx; + aes_setkey_enc(&ctx, key, 128); + aes_crypt_cbc(&ctx, AES_ENCRYPT, len, iv, in, out); + + // Reset the IV. + memset(iv, 0, 0x10); +} + +void aesecb128_encrypt(unsigned char *key, unsigned char *in, unsigned char *out) +{ + aes_context ctx; + aes_setkey_enc(&ctx, key, 128); + aes_crypt_ecb(&ctx, AES_ENCRYPT, in, out); +} + +int aes128ctr(u8 *key, u8 *iv, u8 *in, u64 len, u8 *out) +{ + aes_context aes_ctx = {0}; + size_t nc_off = 0; + unsigned char stream_block[0x10] = {0}; + int retval = -1; + + + // validate input params + if ( (key == NULL) || (iv == NULL) || (in == NULL) || (out == NULL) ) + goto exit; + + // set the AES key context + if (aes_setkey_enc(&aes_ctx, key, 128) != 0) + goto exit; + + // do the AES-CTR crypt + if (aes_crypt_ctr(&aes_ctx, (size_t)len, &nc_off, iv, stream_block, in, out) != 0) + goto exit; + // status success + retval = 0; + +exit: + // return status + return retval; +} + +int aes128ctrxor(u8 *key, u8 *iv, u8 *in, u64 len, u8 *out, size_t len_start_from) +{ + aes_context aes_ctx = {0}; + size_t nc_off = 0; + unsigned char stream_block[0x10] = {0}; + int retval = -1; + + + // validate input params + if ( (key == NULL) || (iv == NULL) || (in == NULL) || (out == NULL) ) + goto exit; + + // set the AES key context + if (aes_setkey_enc(&aes_ctx, key, 128) != 0) + goto exit; + + // do the AES-CTR crypt + if (aes_crypt_ctr_xor(&aes_ctx, (size_t)len, &nc_off, iv, stream_block, in, out, len_start_from) != 0) + goto exit; + // status success + retval = 0; + +exit: + // return status + return retval; +} + +unsigned char RAP_KEY[] = {0x86, 0x9F, 0x77, 0x45, 0xC1, 0x3F, 0xD8, 0x90, 0xCC, 0xF2, 0x91, 0x88, 0xE3, 0xCC, 0x3E, 0xDF}; +unsigned char RAP_PBOX[] = {0x0C, 0x03, 0x06, 0x04, 0x01, 0x0B, 0x0F, 0x08, 0x02, 0x07, 0x00, 0x05, 0x0A, 0x0E, 0x0D, 0x09}; +unsigned char RAP_E1[] = {0xA9, 0x3E, 0x1F, 0xD6, 0x7C, 0x55, 0xA3, 0x29, 0xB7, 0x5F, 0xDD, 0xA6, 0x2A, 0x95, 0xC7, 0xA5}; +unsigned char RAP_E2[] = {0x67, 0xD4, 0x5D, 0xA3, 0x29, 0x6D, 0x00, 0x6A, 0x4E, 0x7C, 0x53, 0x7B, 0xF5, 0x53, 0x8C, 0x74}; + +void get_rif_key(unsigned char* rap, unsigned char* rif) +{ + int i; + int round; + + unsigned char key[0x10]; + unsigned char iv[0x10]; + memset(key, 0, 0x10); + memset(iv, 0, 0x10); + + // Initial decrypt. + aescbc128_decrypt(RAP_KEY, iv, rap, key, 0x10); + + // rap2rifkey round. + for (round = 0; round < 5; ++round) + { + for (i = 0; i < 16; ++i) + { + int p = RAP_PBOX[i]; + key[p] ^= RAP_E1[p]; + } + for (i = 15; i >= 1; --i) + { + int p = RAP_PBOX[i]; + int pp = RAP_PBOX[i - 1]; + key[p] ^= key[pp]; + } + int o = 0; + for (i = 0; i < 16; ++i) + { + int p = RAP_PBOX[i]; + unsigned char kc = key[p] - o; + unsigned char ec2 = RAP_E2[p]; + if (o != 1 || kc != 0xFF) + { + o = kc < ec2 ? 1 : 0; + key[p] = kc - ec2; + } + else if (kc == 0xFF) + { + key[p] = kc - ec2; + } + else + { + key[p] = kc; + } + } + } + + memcpy(rif, key, 0x10); +} + +bool hmac_hash_compare(unsigned char *key, int key_len, unsigned char *in, int in_len, unsigned char *hash, int hash_len) + +{ + + unsigned char *out = new unsigned char[key_len]; + + + + sha1_hmac(key, key_len, in, in_len, out); + + + + for (int i = 0; i < hash_len; i++) + + { + + if (out[i] != hash[i]) + + { + + delete[] out; + + return false; + + } + + } + + + + delete[] out; + + + + return true; + +} + + +// Auxiliary functions (endian swap, xor and prng). + +short se16(short i) + +{ + + return (((i & 0xFF00) >> 8) | ((i & 0xFF) << 8)); + +} + + + +int se32(int i) + +{ + + return ((i & 0xFF000000) >> 24) | ((i & 0xFF0000) >> 8) | ((i & 0xFF00) << 8) | ((i & 0xFF) << 24); + +} + + + +u64 se64(u64 i) + +{ + + return ((i & 0x00000000000000ff) << 56) | ((i & 0x000000000000ff00) << 40) | + + ((i & 0x0000000000ff0000) << 24) | ((i & 0x00000000ff000000) << 8) | + + ((i & 0x000000ff00000000) >> 8) | ((i & 0x0000ff0000000000) >> 24) | + + ((i & 0x00ff000000000000) >> 40) | ((i & 0xff00000000000000) >> 56); + +} + + + +void xor1(unsigned char *dest, unsigned char *src1, unsigned char *src2, int size) + +{ + + int i; + + for(i = 0; i < size; i++) + + { + + dest[i] = src1[i] ^ src2[i]; + + } + +} + + + +void prng(unsigned char *dest, int size) + +{ + + unsigned char *buffer = new unsigned char[size]; + + srand((u32)time(0)); + + + + int i; + + for(i = 0; i < size; i++) + + buffer[i] = (unsigned char)(rand() & 0xFF); + + + + memcpy(dest, buffer, size); + + + + delete[] buffer; + +} + + + +// Hex string conversion auxiliary functions. + +u64 hex_to_u64(const char* hex_str) + +{ + + u32 length = strlen(hex_str); + + u64 tmp = 0; + + u64 result = 0; + + char c; + + + + while (length--) + + { + + c = *hex_str++; + + if((c >= '0') && (c <= '9')) + + tmp = c - '0'; + + else if((c >= 'a') && (c <= 'f')) + + tmp = c - 'a' + 10; + + else if((c >= 'A') && (c <= 'F')) + + tmp = c - 'A' + 10; + + else + + tmp = 0; + + result |= (tmp << (length * 4)); + + } + + + + return result; + +} + + + +void hex_to_bytes(unsigned char *data, const char *hex_str, unsigned int str_length) + +{ + + u32 data_length = str_length / 2; + + char tmp_buf[3] = {0, 0, 0}; + + + + // Don't convert if the string length is odd. + + if (!(str_length % 2)) + + { + + u8 *out = (u8 *) malloc (str_length * sizeof(u8)); + + u8 *pos = out; + + + + while (str_length--) + + { + + tmp_buf[0] = *hex_str++; + + tmp_buf[1] = *hex_str++; + + + + *pos++ = (u8)(hex_to_u64(tmp_buf) & 0xFF); + + } + + + + // Copy back to our array. + + memcpy(data, out, data_length); + + } + +} + + + +bool is_hex(const char* hex_str, unsigned int str_length) + +{ + + static const char hex_chars[] = "0123456789abcdefABCDEF"; + + + + if (hex_str == NULL) + + return false; + + + + unsigned int i; + + for (i = 0; i < str_length; i++) + + { + + if (strchr(hex_chars, hex_str[i]) == 0) + + return false; + + } + + + + return true; + +} + + + +void hmac_hash_forge(unsigned char *key, int key_len, unsigned char *in, int in_len, unsigned char *hash) + +{ + + sha1_hmac(key, key_len, in, in_len, hash); + +} + + + +bool cmac_hash_compare(unsigned char *key, int key_len, unsigned char *in, int in_len, unsigned char *hash, int hash_len) + +{ + + unsigned char *out = new unsigned char[key_len]; + + + + aes_context ctx; + + aes_setkey_enc(&ctx, key, 128); + + aes_cmac(&ctx, in_len, in, out); + + + + for (int i = 0; i < hash_len; i++) + + { + + if (out[i] != hash[i]) + + { + + delete[] out; + + return false; + + } + + } + + + + delete[] out; + + + + return true; + +} + + + +void cmac_hash_forge(unsigned char *key, int key_len, unsigned char *in, uint64_t in_len, unsigned char *hash) + +{ + + aes_context ctx; + + aes_setkey_enc(&ctx, key, 128); + + aes_cmac(&ctx, in_len, in, hash); + +} diff --git a/tools/4/source/src/util.h b/tools/4/source/src/util.h new file mode 100644 index 0000000..eadd39d --- /dev/null +++ b/tools/4/source/src/util.h @@ -0,0 +1,84 @@ +/* +* Copyright (c) 2011-2013 by naehrwert +* This file is released under the GPLv2. +*/ + +#ifndef _UTIL_H_ +#define _UTIL_H_ + +#include + +#include "types.h" +#include "sha1.h" +#include + +/*! Verbose. */ +extern BOOL _verbose; +#define _LOG_VERBOSE(...) _IF_VERBOSE(printf("[*] " __VA_ARGS__)) +#define _IF_VERBOSE(code) \ + do \ + { \ + if(_verbose == TRUE) \ + { \ + code; \ + } \ + } while(0) + +/*! Raw. */ +extern BOOL _raw; +#define _PRINT_RAW(fp, ...) _IF_RAW(fprintf(fp, __VA_ARGS__)) +#define _IF_RAW(code) \ + do \ + { \ + if(_raw == TRUE) \ + { \ + code; \ + } \ + } while(0) + +/*! ID to name entry. */ +typedef struct _id_to_name +{ + u64 id; + const s8 *name; +} id_to_name_t; + +/*! Utility functions. */ +u8 *_read_buffer(const s8 *file, u32 *length); +int _write_buffer(const s8 *file, u8 *buffer, u32 length); +// Crypto functions (AES128-CBC, AES128-ECB, SHA1-HMAC and AES-CMAC). +void aescbc128_decrypt(unsigned char *key, unsigned char *iv, unsigned char *in, unsigned char *out, int len); +void aescbc128_encrypt(unsigned char *key, unsigned char *iv, unsigned char *in, unsigned char *out, int len); +void aesecb128_encrypt(unsigned char *key, unsigned char *in, unsigned char *out); +void get_rif_key(unsigned char* rap, unsigned char* rif); +int aes128ctr(u8 *key, u8 *iv, u8 *in, u64 len, u8 *out); +int aes128ctrxor(u8 *key, u8 *iv, u8 *in, u64 len, u8 *out,size_t len_start_from); + +bool hmac_hash_compare(unsigned char *key, int key_len, unsigned char *in, int in_len, unsigned char *hash, int hash_len); + +void hmac_hash_forge(unsigned char *key, int key_len, unsigned char *in, int in_len, unsigned char *hash); + +bool cmac_hash_compare(unsigned char *key, int key_len, unsigned char *in, int in_len, unsigned char *hash, int hash_len); + +void cmac_hash_forge(unsigned char *key, int key_len, unsigned char *in, uint64_t in_len, unsigned char *hash); + +short se16(short i); + +int se32(int i); + +u64 se64(u64 i); + +void xor1(unsigned char *dest, unsigned char *src1, unsigned char *src2, int size); + +void prng(unsigned char *dest, int size); + + +// Hex string conversion auxiliary functions. + +u64 hex_to_u64(const char* hex_str); + +void hex_to_bytes(unsigned char *data, const char *hex_str, unsigned int str_length); + +bool is_hex(const char* hex_str, unsigned int str_length); + +#endif diff --git a/tools/4/source/tools/ps3py/LICENSE b/tools/4/source/tools/ps3py/LICENSE new file mode 100644 index 0000000..201154b --- /dev/null +++ b/tools/4/source/tools/ps3py/LICENSE @@ -0,0 +1,19 @@ + Copyright (c) 2011 PSL1GHT Development Team + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. diff --git a/tools/4/source/tools/ps3py/crypt.c b/tools/4/source/tools/ps3py/crypt.c new file mode 100755 index 0000000..01bb770 --- /dev/null +++ b/tools/4/source/tools/ps3py/crypt.c @@ -0,0 +1,126 @@ +/* Copyright (c) 2011 PSL1GHT Development Team + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include + +static PyObject *sha1_callback = NULL; + +static void manipulate(uint8_t *key) +{ + uint64_t temp = key[0x38] << 56| + key[0x39] << 48| + key[0x3a] << 40| + key[0x3b] << 32| + key[0x3c] << 24| + key[0x3d] << 16| + key[0x3e] << 8| + key[0x3f]; + temp++; + key[0x38] = (temp >> 56) & 0xff; + key[0x39] = (temp >> 48) & 0xff; + key[0x3a] = (temp >> 40) & 0xff; + key[0x3b] = (temp >> 32) & 0xff; + key[0x3c] = (temp >> 24) & 0xff; + key[0x3d] = (temp >> 16) & 0xff; + key[0x3e] = (temp >> 8) & 0xff; + key[0x3f] = (temp >> 0) & 0xff; +} + +static PyObject* pkg_crypt(PyObject *self, PyObject *args) +{ + uint8_t *key, *input, *ret; + int key_length, input_length, length; + int remaining, i, offset=0; + + PyObject *arglist; + PyObject *result; + + if (!PyArg_ParseTuple(args, "s#s#i", &key, &key_length, &input, &input_length, &length)) + return NULL; + ret = malloc(length); + remaining = length; + + while (remaining > 0) + { + int outHash_length; + uint8_t *outHash; + int bytes_to_dump = remaining; + if (bytes_to_dump > 0x10) + bytes_to_dump = 0x10; + + arglist = Py_BuildValue("(s#)", key, 0x40); + result = PyObject_CallObject(sha1_callback, arglist); + Py_DECREF(arglist); + if (!result) + return NULL; + if (!PyArg_Parse(result, "s#", &outHash, &outHash_length)) + return NULL; + + for(i = 0; i < bytes_to_dump; i++) + { + ret[offset] = outHash[i] ^ input[offset]; + offset++; + } + Py_DECREF(result); + manipulate(key); + remaining -= bytes_to_dump; + } + + /* Return the encrypted data */ + PyObject *py_ret = Py_BuildValue("s#", ret, length); + free(ret); + return py_ret; +} + +static PyObject *register_sha1_callback(PyObject *self, PyObject *args) +{ + PyObject *result = NULL; + PyObject *temp; + + if (PyArg_ParseTuple(args, "O:set_callback", &temp)) + { + if (!PyCallable_Check(temp)) + { + PyErr_SetString(PyExc_TypeError, "parameter must be callable"); + return NULL; + } + Py_XINCREF(temp); /* Add a reference to new callback */ + Py_XDECREF(sha1_callback); /* Dispose of previous callback */ + sha1_callback = temp; /* Remember new callback */ + /* Boilerplate to return "None" */ + Py_INCREF(Py_None); + result = Py_None; + } + return result; +} + +static PyMethodDef cryptMethods[] = { + {"pkgcrypt", pkg_crypt, METH_VARARGS, "C implementation of pkg.py's crypt function"}, + {"register_sha1_callback", register_sha1_callback, METH_VARARGS, "Register a callback to python's SHA1 function, so we don't have to bother with creating our own implementation."}, + {NULL, NULL, 0, NULL} +}; + +PyMODINIT_FUNC initpkgcrypt(void) +{ + (void) Py_InitModule("pkgcrypt", cryptMethods); +} + + diff --git a/tools/4/source/tools/ps3py/pkg.py b/tools/4/source/tools/ps3py/pkg.py new file mode 100755 index 0000000..01eb993 --- /dev/null +++ b/tools/4/source/tools/ps3py/pkg.py @@ -0,0 +1,845 @@ +#!/usr/bin/env python2 +from __future__ import with_statement +import struct, sys + +class StructType(tuple): + def __getitem__(self, value): + return [self] * value + def __call__(self, value, endian='<'): + if isinstance(value, str): + return struct.unpack(endian + tuple.__getitem__(self, 0), value[:tuple.__getitem__(self, 1)])[0] + else: + return struct.pack(endian + tuple.__getitem__(self, 0), value) + +class Struct(object): + __slots__ = ('__attrs__', '__baked__', '__defs__', '__endian__', '__next__', '__sizes__', '__values__') + int8 = StructType(('b', 1)) + uint8 = StructType(('B', 1)) + + int16 = StructType(('h', 2)) + uint16 = StructType(('H', 2)) + + int32 = StructType(('l', 4)) + uint32 = StructType(('L', 4)) + + int64 = StructType(('q', 8)) + uint64 = StructType(('Q', 8)) + + float = StructType(('f', 4)) + + def string(cls, len, offset=0, encoding=None, stripNulls=False, value=''): + return StructType(('string', (len, offset, encoding, stripNulls, value))) + string = classmethod(string) + + LE = '<' + BE = '>' + __endian__ = '<' + + def __init__(self, func=None, unpack=None, **kwargs): + self.__defs__ = [] + self.__sizes__ = [] + self.__attrs__ = [] + self.__values__ = {} + self.__next__ = True + self.__baked__ = False + + if func == None: + self.__format__() + else: + sys.settrace(self.__trace__) + func() + for name in func.func_code.co_varnames: + value = self.__frame__.f_locals[name] + self.__setattr__(name, value) + + self.__baked__ = True + + if unpack != None: + if isinstance(unpack, tuple): + self.unpack(*unpack) + else: + self.unpack(unpack) + + if len(kwargs): + for name in kwargs: + self.__values__[name] = kwargs[name] + + def __trace__(self, frame, event, arg): + self.__frame__ = frame + sys.settrace(None) + + def __setattr__(self, name, value): + if name in self.__slots__: + return object.__setattr__(self, name, value) + + if self.__baked__ == False: + if not isinstance(value, list): + value = [value] + attrname = name + else: + attrname = '*' + name + + self.__values__[name] = None + + for sub in value: + if isinstance(sub, Struct): + sub = sub.__class__ + try: + if issubclass(sub, Struct): + sub = ('struct', sub) + except TypeError: + pass + type_, size = tuple(sub) + if type_ == 'string': + self.__defs__.append(Struct.string) + self.__sizes__.append(size) + self.__attrs__.append(attrname) + self.__next__ = True + + if attrname[0] != '*': + self.__values__[name] = size[3] + elif self.__values__[name] == None: + self.__values__[name] = [size[3] for val in value] + elif type_ == 'struct': + self.__defs__.append(Struct) + self.__sizes__.append(size) + self.__attrs__.append(attrname) + self.__next__ = True + + if attrname[0] != '*': + self.__values__[name] = size() + elif self.__values__[name] == None: + self.__values__[name] = [size() for val in value] + else: + if self.__next__: + self.__defs__.append('') + self.__sizes__.append(0) + self.__attrs__.append([]) + self.__next__ = False + + self.__defs__[-1] += type_ + self.__sizes__[-1] += size + self.__attrs__[-1].append(attrname) + + if attrname[0] != '*': + self.__values__[name] = 0 + elif self.__values__[name] == None: + self.__values__[name] = [0 for val in value] + else: + try: + self.__values__[name] = value + except KeyError: + raise AttributeError(name) + + def __getattr__(self, name): + if self.__baked__ == False: + return name + else: + try: + return self.__values__[name] + except KeyError: + raise AttributeError(name) + + def __len__(self): + ret = 0 + arraypos, arrayname = None, None + + for i in range(len(self.__defs__)): + sdef, size, attrs = self.__defs__[i], self.__sizes__[i], self.__attrs__[i] + + if sdef == Struct.string: + size, offset, encoding, stripNulls, value = size + if isinstance(size, str): + size = self.__values__[size] + offset + elif sdef == Struct: + if attrs[0] == '*': + if arrayname != attrs: + arrayname = attrs + arraypos = 0 + size = len(self.__values__[attrs[1:]][arraypos]) + size = len(self.__values__[attrs]) + + ret += size + + return ret + + def unpack(self, data, pos=0): + for name in self.__values__: + if not isinstance(self.__values__[name], Struct): + self.__values__[name] = None + elif self.__values__[name].__class__ == list and len(self.__values__[name]) != 0: + if not isinstance(self.__values__[name][0], Struct): + self.__values__[name] = None + + arraypos, arrayname = None, None + + for i in range(len(self.__defs__)): + sdef, size, attrs = self.__defs__[i], self.__sizes__[i], self.__attrs__[i] + + if sdef == Struct.string: + size, offset, encoding, stripNulls, value = size + if isinstance(size, str): + size = self.__values__[size] + offset + + temp = data[pos:pos+size] + if len(temp) != size: + raise StructException('Expected %i byte string, got %i' % (size, len(temp))) + + if encoding != None: + temp = temp.decode(encoding) + + if stripNulls: + temp = temp.rstrip('\0') + + if attrs[0] == '*': + name = attrs[1:] + if self.__values__[name] == None: + self.__values__[name] = [] + self.__values__[name].append(temp) + else: + self.__values__[attrs] = temp + pos += size + elif sdef == Struct: + if attrs[0] == '*': + if arrayname != attrs: + arrayname = attrs + arraypos = 0 + name = attrs[1:] + self.__values__[attrs][arraypos].unpack(data, pos) + pos += len(self.__values__[attrs][arraypos]) + arraypos += 1 + else: + self.__values__[attrs].unpack(data, pos) + pos += len(self.__values__[attrs]) + else: + values = struct.unpack(self.__endian__+sdef, data[pos:pos+size]) + pos += size + j = 0 + for name in attrs: + if name[0] == '*': + name = name[1:] + if self.__values__[name] == None: + self.__values__[name] = [] + self.__values__[name].append(values[j]) + else: + self.__values__[name] = values[j] + j += 1 + + return self + + def pack(self): + arraypos, arrayname = None, None + + ret = '' + for i in range(len(self.__defs__)): + sdef, size, attrs = self.__defs__[i], self.__sizes__[i], self.__attrs__[i] + + if sdef == Struct.string: + size, offset, encoding, stripNulls, value = size + if isinstance(size, str): + size = self.__values__[size]+offset + + if attrs[0] == '*': + if arrayname != attrs: + arraypos = 0 + arrayname = attrs + temp = self.__values__[attrs[1:]][arraypos] + arraypos += 1 + else: + temp = self.__values__[attrs] + + if encoding != None: + temp = temp.encode(encoding) + + temp = temp[:size] + ret += temp + ('\0' * (size - len(temp))) + elif sdef == Struct: + if attrs[0] == '*': + if arrayname != attrs: + arraypos = 0 + arrayname = attrs + ret += self.__values__[attrs[1:]][arraypos].pack() + arraypos += 1 + else: + ret += self.__values__[attrs].pack() + else: + values = [] + for name in attrs: + if name[0] == '*': + if arrayname != name: + arraypos = 0 + arrayname = name + values.append(self.__values__[name[1:]][arraypos]) + arraypos += 1 + else: + values.append(self.__values__[name]) + + ret += struct.pack(self.__endian__+sdef, *values) + return ret + + def __getitem__(self, value): + return [('struct', self.__class__)] * value + +class SelfHeader(Struct): + __endian__ = Struct.BE + def __format__(self): + self.magic = Struct.uint32 + self.headerVer = Struct.uint32 + self.flags = Struct.uint16 + self.type = Struct.uint16 + self.meta = Struct.uint32 + self.headerSize = Struct.uint64 + self.encryptedSize = Struct.uint64 + self.unknown = Struct.uint64 + self.AppInfo = Struct.uint64 + self.elf = Struct.uint64 + self.phdr = Struct.uint64 + self.shdr = Struct.uint64 + self.phdrOffsets = Struct.uint64 + self.sceversion = Struct.uint64 + self.digest = Struct.uint64 + self.digestSize = Struct.uint64 + +class AppInfo(Struct): + __endian__ = Struct.BE + def __format__(self): + self.authid = Struct.uint64 + self.unknown = Struct.uint32 + self.appType = Struct.uint32 + self.appVersion = Struct.uint64 + +import struct +import sys +import hashlib +import os +import getopt +import ConfigParser +import io +import glob + +TYPE_NPDRMSELF = 0x1 +TYPE_RAW = 0x3 +TYPE_DIRECTORY = 0x4 + +TYPE_OVERWRITE_ALLOWED = 0x80000000 + +class EbootMeta(Struct): + __endian__ = Struct.BE + def __format__(self): + self.magic = Struct.uint32 + self.unk1 = Struct.uint32 + self.drmType = Struct.uint32 + self.unk2 = Struct.uint32 + self.contentID = Struct.uint8[0x30] + self.fileSHA1 = Struct.uint8[0x10] + self.notSHA1 = Struct.uint8[0x10] + self.notXORKLSHA1 = Struct.uint8[0x10] + self.nulls = Struct.uint8[0x10] +class MetaHeader(Struct): + __endian__ = Struct.BE + def __format__(self): + self.unk1 = Struct.uint32 + self.unk2 = Struct.uint32 + self.drmType = Struct.uint32 + self.unk4 = Struct.uint32 + + self.unk21 = Struct.uint32 + self.unk22 = Struct.uint32 + self.unk23 = Struct.uint32 + self.unk24 = Struct.uint32 + + self.unk31 = Struct.uint32 + self.unk32 = Struct.uint32 + self.unk33 = Struct.uint32 + self.secondaryVersion = Struct.uint16 + self.unk34 = Struct.uint16 + + self.dataSize = Struct.uint32 + self.unk42 = Struct.uint32 + self.unk43 = Struct.uint32 + self.packagedBy = Struct.uint16 + self.packageVersion = Struct.uint16 +class DigestBlock(Struct): + __endian__ = Struct.BE + def __format__(self): + self.type = Struct.uint32 + self.size = Struct.uint32 + self.isNext = Struct.uint64 +class FileHeader(Struct): + __endian__ = Struct.BE + def __format__(self): + self.fileNameOff = Struct.uint32 + self.fileNameLength = Struct.uint32 + self.fileOff = Struct.uint64 + + self.fileSize = Struct.uint64 + self.flags = Struct.uint32 + self.padding = Struct.uint32 + def __str__(self): + out = "" + out += "[X] File Name: %s [" % self.fileName + if self.flags & 0xFF == TYPE_NPDRMSELF: + out += "NPDRM Self]" + elif self.flags & 0xFF == TYPE_DIRECTORY: + out += "Directory]" + elif self.flags & 0xFF == TYPE_RAW: + out += "Raw Data]" + else: + out += "Unknown]" + if (self.flags & TYPE_OVERWRITE_ALLOWED ) != 0: + out += " Overwrite allowed.\n" + else: + out += " Overwrite NOT allowed.\n" + out += "\n" + + out += "[X] File Name offset: %08x\n" % self.fileNameOff + out += "[X] File Name Length: %08x\n" % self.fileNameLength + out += "[X] Offset To File Data: %016x\n" % self.fileOff + + out += "[X] File Size: %016x\n" % self.fileSize + out += "[X] Flags: %08x\n" % self.flags + out += "[X] Padding: %08x\n\n" % self.padding + assert self.padding == 0, "I guess I was wrong, this is not padding." + + + return out + def __repr__(self): + return self.fileName + (" Size: 0x%016x" % self.fileSize) + def __init__(self): + Struct.__init__(self) + self.fileName = "" + +class Header(Struct): + __endian__ = Struct.BE + def __format__(self): + self.magic = Struct.uint32 + self.type = Struct.uint32 + self.pkgInfoOff = Struct.uint32 + self.unk1 = Struct.uint32 + + self.headSize = Struct.uint32 + self.itemCount = Struct.uint32 + self.packageSize = Struct.uint64 + + self.dataOff = Struct.uint64 + self.dataSize = Struct.uint64 + + self.contentID = Struct.uint8[0x30] + self.QADigest = Struct.uint8[0x10] + self.KLicensee = Struct.uint8[0x10] + + + + def __str__(self): + context = keyToContext(self.QADigest) + setContextNum(context, 0xFFFFFFFFFFFFFFFF) + licensee = crypt(context, listToString(self.KLicensee), 0x10) + + out = "" + out += "[X] Magic: %08x\n" % self.magic + out += "[X] Type: %08x\n" % self.type + out += "[X] Offset to package info: %08x\n" % self.pkgInfoOff + out += "[ ] unk1: %08x\n" % self.unk1 + + out += "[X] Head Size: %08x\n" % self.headSize + out += "[X] Item Count: %08x\n" % self.itemCount + out += "[X] Package Size: %016x\n" % self.packageSize + + out += "[X] Data Offset: %016x\n" % self.dataOff + out += "[X] Data Size: %016x\n" % self.dataSize + + out += "[X] ContentID: '%s'\n" % (nullterm(self.contentID)) + + out += "[X] QA_Digest: %s\n" % (nullterm(self.QADigest, True)) + out += "[X] K Licensee: %s\n" % licensee.encode('hex') + + + return out +def listToString(inlist): + if isinstance(inlist, list): + return ''.join(["%c" % el for el in inlist]) + else: + return "" +def nullterm(str_plus, printhex=False): + if isinstance(str_plus, list): + if printhex: + str_plus = ''.join(["%X" % el for el in str_plus]) + else: + str_plus = listToString(str_plus) + z = str_plus.find('\0') + if z != -1: + return str_plus[:z] + else: + return str_plus + +def keyToContext(key): + if isinstance(key, list): + key = listToString(key) + key = key[0:16] + largekey = [] + for i in range(0, 8): + largekey.append(ord(key[i])) + for i in range(0, 8): + largekey.append(ord(key[i])) + for i in range(0, 8): + largekey.append(ord(key[i+8])) + for i in range(0, 8): + largekey.append(ord(key[i+8])) + for i in range(0, 0x20): + largekey.append(0) + return largekey + +#Thanks to anonymous for the help with the RE of this part, +# the x86 mess of ands and ors made my head go BOOM headshot. +def manipulate(key): + if not isinstance(key, list): + return + tmp = listToString(key[0x38:]) + + + tmpnum = struct.unpack('>Q', tmp)[0] + tmpnum += 1 + tmpnum = tmpnum & 0xFFFFFFFFFFFFFFFF + setContextNum(key, tmpnum) +def setContextNum(key, tmpnum): + tmpchrs = struct.pack('>Q', tmpnum) + + key[0x38] = ord(tmpchrs[0]) + key[0x39] = ord(tmpchrs[1]) + key[0x3a] = ord(tmpchrs[2]) + key[0x3b] = ord(tmpchrs[3]) + key[0x3c] = ord(tmpchrs[4]) + key[0x3d] = ord(tmpchrs[5]) + key[0x3e] = ord(tmpchrs[6]) + key[0x3f] = ord(tmpchrs[7]) + +try: + import pkgcrypt +except: + print "" + print "-----------------" + print "PKG BUILD ERROR" + print "-----------------" + print "Couldn't make PKG file. Go into the ps3py directory, and type the following:" + print "" + print "python2 setup.py build" + print "" + print "This should create a pkgcrypt.so file in the build/ directory. Move that file" + print "over to the root of the ps3py directory and try running this script again." + + +def crypt(key, inbuf, length): + if not isinstance(key, list): + return "" + # Call our ultra fast c implemetation + #return pkgcrypt.pkgcrypt(listToString(key), inbuf, length); #Fix For macOS 10.13.5 + + # Original python (slow) implementation + ret = "" + offset = 0 + while length > 0: + bytes_to_dump = length + if length > 0x10: + bytes_to_dump = 0x10 + outhash = SHA1(listToString(key)[0:0x40]) + for i in range(0, bytes_to_dump): + ret += chr(ord(outhash[i]) ^ ord(inbuf[offset])) + offset += 1 + manipulate(key) + length -= bytes_to_dump + return ret +def SHA1(data): + m = hashlib.sha1() + m.update(data) + return m.digest() + +pkgcrypt.register_sha1_callback(SHA1) + +def getFiles(files, folder, original): + oldfolder = folder + foundFiles = glob.glob( os.path.join(folder, '*') ) + sortedList = [] + for filepath in foundFiles: + if not os.path.isdir(filepath): + sortedList.append(filepath) + for filepath in foundFiles: + if os.path.isdir(filepath): + sortedList.append(filepath) + for filepath in sortedList: + newpath = filepath.replace("\\", "/") + newpath = newpath[len(original):] + if os.path.isdir(filepath): + folder = FileHeader() + folder.fileName = newpath + folder.fileNameOff = 0 + folder.fileNameLength = len(folder.fileName) + folder.fileOff = 0 + + folder.fileSize = 0 + folder.flags = TYPE_OVERWRITE_ALLOWED | TYPE_DIRECTORY + folder.padding = 0 + files.append(folder) + getFiles(files, filepath, original) + else: + file = FileHeader() + file.fileName = newpath + file.fileNameOff = 0 + file.fileNameLength = len(file.fileName) + file.fileOff = 0 + file.fileSize = os.path.getsize(filepath) + file.flags = TYPE_OVERWRITE_ALLOWED | TYPE_RAW + if newpath == "USRDIR/EBOOT.BIN": + file.fileSize = ((file.fileSize - 0x30 + 63) & ~63) + 0x30 + file.flags = TYPE_OVERWRITE_ALLOWED | TYPE_NPDRMSELF + + file.padding = 0 + files.append(file) + +def pack(folder, contentid, outname=None): + + qadigest = hashlib.sha1() + + header = Header() + header.magic = 0x7F504B47 + header.type = 0x01 + header.pkgInfoOff = 0xC0 + header.unk1 = 0x05 + + header.headSize = 0x80 + header.itemCount = 0 + header.packageSize = 0 + + header.dataOff = 0x140 + header.dataSize = 0 + + for i in range(0, 0x30): + header.contentID[i] = 0 + + for i in range(0,0x10): + header.QADigest[i] = 0 + header.KLicensee[i] = 0 + + #content type type name install path (on ps3) notes + #0x00000004 GameData (also Patches) /dev_hdd0/game/ + #0x00000005 Game_Exec /dev_hdd0/game/ + #0x00000006 PS1emu /dev_hdd0/game/ + #0x00000007 PSP & PCEngine /dev_hdd0/game/ + #0x00000008 + #0x00000009 Theme /dev_hdd0/theme + #0x0000000A Widget /dev_hdd0/widget + #0x0000000B License /dev_hdd0/home//exdata + #0x0000000C VSH Module /dev_hdd0/vsh/modules/ + #0x0000000D PSN Avatar /dev_hdd0/home//psn_avatar + #0x0000000E PSPgo /dev_hdd0/game/ Displayed as Unknown Album: Corrupted Data + #0x0000000F Minis /dev_hdd0/game/ + #0x00000010 NEOGEO /dev_hdd0/game/ + #0x00000011 VMC /dev_hdd0/tmp/vmc/ + #0x00000012 Seen on PS2 classic /dev_hdd0/game/ + #0x00000013 + #0x00000014 Seen on PSP remastered /dev_hdd0/game/ + #0x00000015 PSVita (PSP2GD) + #0x00000016 PSVita (PSP2AC) + #0x00000017 PSVita (PSP2LA) + #0x00000018 + #0x00000019 WT (Web TV?) /dev_hdd0/game/ + + metaBlock = MetaHeader() + metaBlock.unk1 = 1 #doesnt change output of --extract + metaBlock.unk2 = 4 #doesnt change output of --extract + metaBlock.drmType = 3 #1 = Network, 2 = Local, 3 = Free, anything else = unknown + metaBlock.unk4 = 2 + + metaBlock.unk21 = 4 + metaBlock.unk22 = 0xB #content type = 5 == gameexec, 4 == gamedata + metaBlock.unk23 = 3 + metaBlock.unk24 = 4 + + metaBlock.unk31 = 0xE #packageType 0x10 == patch, 0x8 == Demo&Key, 0x0 == Demo&Key (AND UserFiles = NotOverWrite), 0xE == normal, use 0xE for gamexec, and 8 for gamedata + metaBlock.unk32 = 4 #when this is 5 secondary version gets used?? + metaBlock.unk33 = 8 #doesnt change output of --extract + metaBlock.secondaryVersion = 0 + metaBlock.unk34 = 0 + + metaBlock.dataSize = 0 + metaBlock.unk42 = 5 + metaBlock.unk43 = 4 + metaBlock.packagedBy = 0x1061 + metaBlock.packageVersion = 0 + + + files = [] + getFiles(files, folder, folder) + header.itemCount = len(files) + dataToEncrypt = "" + fileDescLength = 0 + fileOff = 0x20 * len(files) + for file in files: + alignedSize = (file.fileNameLength + 0x0F) & ~0x0F + file.fileNameOff = fileOff + fileOff += alignedSize + for file in files: + file.fileOff = fileOff + fileOff += (file.fileSize + 0x0F) & ~0x0F + dataToEncrypt += file.pack() + for file in files: + alignedSize = (file.fileNameLength + 0x0F) & ~0x0F + dataToEncrypt += file.fileName + dataToEncrypt += "\0" * (alignedSize-file.fileNameLength) + fileDescLength = len(dataToEncrypt) + for file in files: + if not file.flags & 0xFF == TYPE_DIRECTORY: + path = os.path.join(folder, file.fileName) + fp = open(path, 'rb') + fileData = fp.read() + qadigest.update(fileData) + fileSHA1 = SHA1(fileData) + fp.close() + if fileData[0:9] == "SCE\0\0\0\0\x02\x80": + fselfheader = SelfHeader() + fselfheader.unpack(fileData[0:len(fselfheader)]) + appheader = AppInfo() + appheader.unpack(fileData[fselfheader.AppInfo:fselfheader.AppInfo+len(appheader)]) + found = False + digestOff = fselfheader.digest + while not found: + digest = DigestBlock() + digest.unpack(fileData[digestOff:digestOff+len(digest)]) + if digest.type == 3: + found = True + else: + digestOff += digest.size + if digest.isNext != 1: + break + digestOff += len(digest) + if appheader.appType == 8 and found: + dataToEncrypt += fileData[0:digestOff] + + meta = EbootMeta() + meta.magic = 0x4E504400 + meta.unk1 = 1 + meta.drmType = metaBlock.drmType + meta.unk2 = 1 + for i in range(0,min(len(contentid), 0x30)): + meta.contentID[i] = ord(contentid[i]) + for i in range(0,0x10): + meta.fileSHA1[i] = ord(fileSHA1[i]) + meta.notSHA1[i] = (~meta.fileSHA1[i]) & 0xFF + if i == 0xF: + meta.notXORKLSHA1[i] = (1 ^ meta.notSHA1[i] ^ 0xAA) & 0xFF + else: + meta.notXORKLSHA1[i] = (0 ^ meta.notSHA1[i] ^ 0xAA) & 0xFF + meta.nulls[i] = 0 + dataToEncrypt += meta.pack() + dataToEncrypt += fileData[digestOff + 0x80:] + else: + dataToEncrypt += fileData + else: + dataToEncrypt += fileData + + dataToEncrypt += '\0' * (((file.fileSize + 0x0F) & ~0x0F) - len(fileData)) + header.dataSize = len(dataToEncrypt) + metaBlock.dataSize = header.dataSize + header.packageSize = header.dataSize + 0x1A0 + head = header.pack() + qadigest.update(head) + qadigest.update(dataToEncrypt[0:fileDescLength]) + QA_Digest = qadigest.digest() + + for i in range(0, 0x10): + header.QADigest[i] = ord(QA_Digest[i]) + + for i in range(0, min(len(contentid), 0x30)): + header.contentID[i] = ord(contentid[i]) + + context = keyToContext(header.QADigest) + setContextNum(context, 0xFFFFFFFFFFFFFFFF) + licensee = crypt(context, listToString(header.KLicensee), 0x10) + + for i in range(0, min(len(contentid), 0x10)): + header.KLicensee[i] = ord(licensee[i]) + + if outname != None: + outFile = open(outname, 'wb') + else: + outFile = open(contentid + ".pkg", 'wb') + outFile.write(header.pack()) + headerSHA = SHA1(header.pack())[3:19] + outFile.write(headerSHA) + + + metaData = metaBlock.pack() + metaBlockSHA = SHA1(metaData)[3:19] + metaBlockSHAPad = '\0' * 0x30 + + context = keyToContext([ord(c) for c in metaBlockSHA]) + metaBlockSHAPadEnc = crypt(context, metaBlockSHAPad, 0x30) + + context = keyToContext([ord(c) for c in headerSHA]) + metaBlockSHAPadEnc2 = crypt(context, metaBlockSHAPadEnc, 0x30) + outFile.write(metaBlockSHAPadEnc2) + outFile.write(metaData) + outFile.write(metaBlockSHA) + outFile.write(metaBlockSHAPadEnc) + + context = keyToContext(header.QADigest) + encData = crypt(context, dataToEncrypt, header.dataSize) + outFile.write(encData) + outFile.write('\0' * 0x60) + outFile.close() + print header + +def usage(): + print """usage: [based on revision 1061] + + python pkg.py target-directory [out-file] + + python pkg.py [options] npdrm-package + -l | --list list packaged files. + -x | --extract extract package. + + python pkg.py [options] + --version print revision. + --help print this message.""" + +def version(): + print """pkg.py 0.5""" + +def main(): + extract = False + list = False + contentid = None + try: + opts, args = getopt.getopt(sys.argv[1:], "hx:dvl:c:", ["help", "extract=", "version", "list=", "contentid="]) + except getopt.GetoptError: + usage() + sys.exit(2) + for opt, arg in opts: + if opt in ("-h", "--help"): + usage() + sys.exit(2) + elif opt in ("-v", "--version"): + version() + sys.exit(2) + elif opt in ("-x", "--extract"): + fileToExtract = arg + extract = True + elif opt in ("-l", "--list"): + fileToList = arg + list = True + elif opt in ("-c", "--contentid"): + contentid = arg + else: + usage() + sys.exit(2) + if extract: + unpack(fileToExtract) + else: + if len(args) == 1 and contentid != None: + pack(args[0], contentid) + elif len(args) == 2 and contentid != None: + pack(args[0], contentid, args[1]) + else: + usage() + sys.exit(2) +if __name__ == "__main__": + main() diff --git a/tools/4/source/tools/ps3py/setup.py b/tools/4/source/tools/ps3py/setup.py new file mode 100755 index 0000000..c315b47 --- /dev/null +++ b/tools/4/source/tools/ps3py/setup.py @@ -0,0 +1,8 @@ +from distutils.core import setup, Extension + +module1 = Extension('pkgcrypt', sources = ['crypt.c']) + +setup (name = 'pkgcrypt', + version = '1.0', + description = 'C implementation of the crypt function from pkg.py', + ext_modules = [module1]) diff --git a/tools/4/source/tools/ps3py_exe/pkg_exdata.exe b/tools/4/source/tools/ps3py_exe/pkg_exdata.exe new file mode 100644 index 0000000..7140870 Binary files /dev/null and b/tools/4/source/tools/ps3py_exe/pkg_exdata.exe differ -- cgit v1.2.3