diff --git a/PS3/data/internal_keys b/PS3/data/internal_keys new file mode 100644 index 0000000..846e8aa --- /dev/null +++ b/PS3/data/internal_keys @@ -0,0 +1,125 @@ +[pkg-sd] +category=PKG +revision=0000 +version=0000008400000000 +erk=FEDCBA98765432100123456789ABCDEFFEDCBA98765432100123456789ABCDEF +riv=0123456789ABCDEFFEDCBA9876543210 +pub=123DA14B3D21D82AFC759A9CF6F41610A24EC8704306BAC4E0941A5B70EEA037F1482EA7EC578872 +priv=000000000000000000000000000000000001000000 +ctype=27 + +[spp-sd] +category=SPP +revision=0000 +version=0000008400000000 +erk=FEDCBA98765432100123456789ABCDEFFEDCBA98765432100123456789ABCDEF +riv=0123456789ABCDEFFEDCBA9876543210 +pub=123DA14B3D21D82AFC759A9CF6F41610A24EC8704306BAC4E0941A5B70EEA037F1482EA7EC578872 +priv=000000000000000000000000000000000001000000 +ctype=27 + +[rvk-sd] +category=RVK +revision=0000 +version=0000008400000000 +erk=FEDCBA98765432100123456789ABCDEFFEDCBA98765432100123456789ABCDEF +riv=0123456789ABCDEFFEDCBA9876543210 +pub=123DA14B3D21D82AFC759A9CF6F41610A24EC8704306BAC4E0941A5B70EEA037F1482EA7EC578872 +priv=000000000000000000000000000000000001000000 +ctype=27 + +[lv0ldr-sd] +category=SELF +revision=0000 +version=0000008400000000 +program_type=LV0 +erk=FEDCBA98765432100123456789ABCDEFFEDCBA98765432100123456789ABCDEF +riv=0123456789ABCDEFFEDCBA9876543210 +pub=123DA14B3D21D82AFC759A9CF6F41610A24EC8704306BAC4E0941A5B70EEA037F1482EA7EC578872 +priv=000000000000000000000000000000000001000000 +ctype=27 + +[metldr-sd] +category=SELF +revision=0000 +version=0000008400000000 +program_type=LDR +erk=FEDCBA98765432100123456789ABCDEFFEDCBA98765432100123456789ABCDEF +riv=0123456789ABCDEFFEDCBA9876543210 +pub=123DA14B3D21D82AFC759A9CF6F41610A24EC8704306BAC4E0941A5B70EEA037F1482EA7EC578872 +priv=000000000000000000000000000000000001000000 +ctype=27 + +[isoldr-sd] +category=SELF +revision=0000 +version=0000008400000000 +program_type=ISO +erk=9E85BEE6D39E9632A77FE3CD6E647C8DFE4606C383E1697DD6D9CE63341EAFF9 +riv=2C1F4C82FF3A796D3A772CEEF010ECA4 +pub=625D1DF4C3264BBA9FC17A4437BA42591585A5ECCC6F3042DB3A80CBBC0426DAF33549C537AA7782 +priv=00D19A1B338041F7C31062B9C40E725E1DA5D7C11A +ctype=20 + +[lv1ldr-sd] +category=SELF +version=0000008300000000 +program_type=LV1 +erk=FEDCBA98765432100123456789ABCDEFFEDCBA98765432100123456789ABCDEF +riv=0123456789ABCDEFFEDCBA9876543210 +pub=123DA14B3D21D82AFC759A9CF6F41610A24EC8704306BAC4E0941A5B70EEA037F1482EA7EC578872 +priv=000000000000000000000000000000000001000000 +ctype=27 + +[lv1ldr-sd] +category=SELF +version=0000008400000000 +program_type=LV1 +erk=014485445EC9926C50F613AE77D9C37AA99838CCEB6F75FA78E29A8C622E8011 +riv=A17D6A522CB1B08F97DA8A82E97C12F7 +pub=72C1034FC8E4C1707B7147B9E930FA3F28EBFE070B5EBFBAE4A666B498050929815CF727C6264573 +priv=008732ACD0889FF7480C5C7D9A5D3BF43C46F220F8 +ctype=11 + +[lv2ldr-sd] +category=SELF +version=0000008300000000 +program_type=LV2 +erk=FEDCBA98765432100123456789ABCDEFFEDCBA98765432100123456789ABCDEF +riv=0123456789ABCDEFFEDCBA9876543210 +pub=123DA14B3D21D82AFC759A9CF6F41610A24EC8704306BAC4E0941A5B70EEA037F1482EA7EC578872 +priv=000000000000000000000000000000000001000000 +ctype=27 + +[lv2ldr-sd] +category=SELF +version=0000008400000000 +program_type=LV2 +erk=014485445EC9926C50F613AE77D9C37AA99838CCEB6F75FA78E29A8C622E8011 +riv=A17D6A522CB1B08F97DA8A82E97C12F7 +pub=72C1034FC8E4C1707B7147B9E930FA3F28EBFE070B5EBFBAE4A666B498050929815CF727C6264573 +priv=008732ACD0889FF7480C5C7D9A5D3BF43C46F220F8 +ctype=11 + +[appldr-sd] +category=SELF +revision=0000 +version=0000008400000000 +program_type=APP +erk=014485445EC9926C50F613AE77D9C37AA99838CCEB6F75FA78E29A8C622E8011 +riv=A17D6A522CB1B08F97DA8A82E97C12F7 +pub=72C1034FC8E4C1707B7147B9E930FA3F28EBFE070B5EBFBAE4A666B498050929815CF727C6264573 +priv=008732ACD0889FF7480C5C7D9A5D3BF43C46F220F8 +ctype=11 + +[appldr-sd] +category=SELF +revision=0000 +version=0000008400000000 +program_type=UNK_7 +erk=BBDF2959EB4AAEF5882BE11FF033B77FF9FD55B1F30819D42154F6B069C14FEF +riv=241C0CC5A8591B50EF460EE3E50116C3 +pub=0E140FBAD23F1B236C6AD0623A7C2C6366AEDA66380860A9D727A56FD681F644EF22A7E07979A1BE +priv= +ctype=33 + diff --git a/PS3/data/keys b/PS3/data/keys new file mode 100644 index 0000000..d0adcbd --- /dev/null +++ b/PS3/data/keys @@ -0,0 +1,1257 @@ +[NP_tid] +category=OTHER +key=9B515FEACF75064981AA604D91A54E97 + +[NP_ci] +category=OTHER +key=6BA52976EFDA16EF3C339FB2971E256B + +[NP_klic_free] +category=OTHER +key=72F990788F9CFF745725F08E4C128387 + +[NP_klic_key] +category=OTHER +key=F2FBCA7A75B04EDC1390638CCDFDD1EE + +[NP_idps_const] +category=OTHER +key=5E06E04FD94A71BF0000000000000001 + +[NP_rif_key] +category=OTHER +key=DA7D4B5E499A4F53B1C1A14A7484443B + +[NP_sig] +category=OTHER +pub=E6792E446CEBA27BCADF374B99504FD8E80ADFEB3E66DE73FFE58D3291221C65018C038D3822C3C9 +priv= +ctype=2 + +[NP_rap_initial] +category=OTHER +key=869F7745C13FD890CCF29188E3CC3EDF + +[NP_rap_pbox] +category=OTHER +key=0C030604010B0F08020700050A0E0D09 + +[NP_rap_e1] +category=OTHER +key=A93E1FD67C55A329B75FDDA62A95C7A5 + +[NP_rap_e2] +category=OTHER +key=67D45DA3296D006A4E7C537BF5538C74 + +[pkg] +category=PKG +revision=0000 +version=0003005500000000 +erk=A97818BD193A67A16FE83A855E1BE9FB5640938D4DBCB2CB52C5A2F8B02B1031 +riv=4ACEF01224FBEEDF8245F8FF10211E6E +pub=41DA1A8F74FF8D3F1CE20EF3E9D8865C96014FE373CA143C9BADEDF2D9D3C7573307115CCFE04F13 +priv=00542D46E7B3DAAC8AEB81E533873AABD6D74BB710 +ctype=23 + +[spkg] +category=PKG +version=0004008200000000 +revision=0000 +erk=F8F99006F1C007D5D0B1909E9566E0E70B569399FC3394A811809FDB5CAE92CD +riv=59D28DB4ADDFB40B7D768BC9667C67B1 +pub=5432BDDD1F97418147AFF016EAA6100834F2CAA8C498B88965689EE44DF349B066CD43CBF4F2C5D0 +priv= +ctype=17 + +[spp] +category=SPP +revision=0000 +version=0003005500000000 +erk=56C655747A4B6957A2D8BB9AC605C297E6AC9871932BFECDDE066CEE5B29470A +riv=007E6B268EF1E986D10A9889CF93A8CB +pub=265C04E7F20C3B8ACAC90E7C9D12757ED7ACBC01AA6624A2A927E719A4AA1222F87D917005F6072A +priv=0001608EF3BACAFFB8C3A5958A24F758325B62B08C +ctype=22 + +[spp] +category=SPP +revision=0000 +version=0003005600000000 +erk=7FD222B3FEF467DF7E3F63AC8B77501A3B38752411E96AFEDA6587B5CD5E91B0 +riv=B889290922B002F57086B818A8FDE3CC +pub=71E12CB3D81AFA79670AF4FAC4BBE41AA7F7DDF368F5615E933CB1C21A783B73C085CA49986CCF63 +priv= +ctype=22 + +[spp] +category=SPP +revision=0000 +version=0003006100000000 +erk=ED17248214B9AB34D57ED5CA6CCAEC9879137B4B46CE5064E6491D34001BACF2 +riv=3E05572881C5BC845D310EAC28497B08 +pub=504F905A8AAAA0E9BF55F6D5285697E2CABDB1A5240C4745BE8923308169EAB43E1BFD265F5E579E +priv= +ctype=13 + +[spp] +category=SPP +revision=0000 +version=0003006600000000 +erk=E750FE8ED144D99782AC605944350B9F41AE489C3274C42C1BFD5AB06115C7C4 +riv=0F23BBED0473B4899AD793AC76D8F722 +pub=934861FF0D4BAF7141B658D1D84441D413060D7E534E99E357B5090EECFB34D947694ADB9F6E7D3F +priv= +ctype=22 + +[spp] +category=SPP +revision=0000 +version=0003007400000000 +erk=4B1A459AF1D484DABD727BD316351A9A1B3404E9B1DE925B95527166DB3BB2D0 +riv=3B6203C2730D283F978A12D5390DD747 +pub=0AEEB187EA76913765A15A435F2F1B15545F60794FB5244DC54801B6BABD497565ED6BF57C1A80C8 +priv= +ctype=23 + +[spp] +category=SPP +revision=0000 +version=0004001100000000 +erk=11FA6344E869787209E6806E66A7799F7128BD98AEAE95B386D4C88EDDDB3FEF +riv=67B49380C74FFB15AD929E8C819586AD +pub=5E028AC83D1BF838CEC43CA11969C72533A057BB0C3CB4A571F8E08DD5DF793CD1E1270CA6E89FB3 +priv= +ctype=04 + +[spp] +category=SPP +revision=0000 +version=0004008200000000 +erk=D2961BBFFEDAEE269B061454D6ACF262CD71BC6F5320180F0A04A07583CCF7C5 +riv=6D308B59BC9054B12C833359D31BAE77 +pub=0CDD0D1541A6B0DFD12E951578536CA60C93853B88FCE17592DC8D134B08A94AF8BB08667E2D70A5 +priv= +ctype=07 + +[rvk] +category=RVK +revision=0000 +version=0003005500000000 +erk=03AF06FD1CE6DA366361682CDF59F9708B5D7876F40A9E1E9AC2B22F51B60BDF +riv=8B5D7876F40A9E1E9AC2B22F51B60BDF +pub=9ADE7830EB74245EC357CE4F6401633E5A8048FD865F9D8F1A9189535A37623E2921427463A754F7 +priv=00245E673B039D656DA206BDAE4EAEFCBF2A8D5EAF +ctype=29 + +[rvk] +category=RVK +revision=0000 +version=0003005600000000 +erk=22628A9EC4C414D5B32F2B4BA4926089DE9A461B190FB3E4392D057C525535DE +riv=DE9A461B190FB3E4392D057C525535DE +pub=51751B9F1DA58638D2D99F67E20A1D4A454C5B042CD1D0A449A2989808002BA68FB5B7F4B5B4E63B +priv= +ctype=32 + +[rvk] +category=RVK +revision=0000 +version=0003006100000000 +erk=BCFEDBE01D445CDEF335C543703D8E9C1199FAC33DC4595D7382EAF54EF9C4C3 +riv=B20A23079516205525683D8058379CBF +pub=9859B677A5B8FCCA31A6FBA2E3220EE5E207343A58EEEE6B6CB260EB5E971352C45428E8C8398BE6 +priv= +ctype=33 + +[rvk] +category=RVK +revision=0000 +version=0003006600000000 +erk=1EBD693BD813ADDA2203DAEE0441F4146C174F68F532B3E43A48F029230EF70C +riv=501819323BFCF9FB99396B46B70A97E7 +pub=6563EA3D5694A913F24059A57B2A3645C7C8A587CF20075EFD978A048CAD7A68A8EB7E6BC4BC5448 +priv= +ctype=30 + +[rvk] +category=RVK +revision=0000 +version=0003007400000000 +erk=4AF39F7A4E214ECB270416EDD17113A23DC5AD2EDAA5FC91817EE171CDB8B9F4 +riv=0E5CB28FA2666E3ED45289DABC67DDC2 +pub=758BBF611ED6BB8C32D2A49A7AD456D585D11C74926F977737EE309F213D971404A8F9022B409371 +priv= +ctype=31 + +[rvk] +category=RVK +revision=0000 +version=0004001100000000 +erk=99E8959A4363BE9EBDBC2B9C73BCBBE627BF112883E650E3F95879C0BFFB103E +riv=182CC801794A2F7027BB76D29D598550 +pub=6319A4B7D99FD3A3332CB13F3DE44A898B6A4CF04B9C15E6166AFC7C5272AF7A4DE04E802FD2C71C +priv= +ctype=02 + +[rvk] +category=RVK +version=0004008200000000 +revision=0000 +erk=695984B7EE2EC2F77FCC3120150DCE7E4480D84480DDD8C5940AEB6F79E63D17 +riv=A8BA3E4E63B2BB06FC0CE57E3BB8FC46 +pub=7F1950C6E497E922400586EE338B41E01C906C5A6DFD75FEB5249CFA4BEC534F5CA679670A452B2A +priv= +ctype=12 + +[lv0ldr] +category=SELF +version=0000000000000000 +revision=0000 +program_type=LV0 +erk=B9F3F9E6107CFF2680A91E118C2403CF4A6F18F3C7EFD7D13D1AC4DB760BD222 +riv=B43661B9A79BAD9D8E2B046469CDA1E7 +pub=4C870BE86DDD996A92A3F7F404F33604244A1D02AB5B78BC9DAF030B78BE8867CF586171B7D45D20 +priv=002CC736C7AD06D264E9AB663EB1F35F5DC159248C +ctype=33 + +[lv0ldr] +category=SELF +revision=0000 +version=0004008200000000 +program_type=LV0 +erk=CA7A24EC38BDB45B98CCD7D363EA2AF0C326E65081E0630CB9AB2D215865878A +riv=F9205F46F6021697E670F13DFA726212 +pub=A8FD6DB24532D094EFA08CB41C9A72287D905C6B27B42BE4AB925AAF4AFFF34D41EEB54DD128700D +priv=001AD976FCDE86F5B8FF3E63EF3A7F94E861975BA3 +ctype=33 + +[metldr] +category=SELF +revision=0000 +program_type=LDR +erk=C0CEFE84C227F75BD07A7EB846509F93B238E770DACB9FF4A388F812482BE21B +riv=47EE7454E4774CC9B8960C7B59F4C14D +pub=C2D4AAF319355019AF99D44E2B58CA29252C89123D11D6218F40B138CAB29B7101F3AEB72A975019 +priv=00C5B2BFA1A413DD16F26D31C0F2ED4720DCFB0670 +ctype=20 + +[isoldr] +category=SELF +version=0000008400000000 +revision=0000 +program_type=ISO +erk=8860D0CFF4D0DC688D3223321B96B59A777E6914961488E07048DAECB020ECA4 +riv=C82D015D46CF152F1DD0C16F18B5B1E5 +pub=733918D7C888130509346E6B4A8B6CAA357AB557E814E8122BF102C14A314BF9475B9D70EAF9EC29 +priv=009BE892E122A5C943C1BB7403A67318AA9E1B286F +ctype=36 + +[isoldr] +category=SELF +version=0003003000000000 +revision=0001 +program_type=ISO +erk=8860D0CFF4D0DC688D3223321B96B59A777E6914961488E07048DAECB020ECA4 +riv=C82D015D46CF152F1DD0C16F18B5B1E5 +pub=733918D7C888130509346E6B4A8B6CAA357AB557E814E8122BF102C14A314BF9475B9D70EAF9EC29 +priv=009BE892E122A5C943C1BB7403A67318AA9E1B286F +ctype=36 + +[isoldr] +category=SELF +version=0003004200000000 +revision=0001 +program_type=ISO +erk=101E27F3FA2FB53ACA924F783AD553162D56B975D05B81351A1111799F20254D +riv=8D2E9C6297B8AD252998458296AC773C +pub=138446EE0BDDA5638F97328C8956E6489CBBFE57C5961D40DD5C43BB4138F1C400A8B27204A5D625 +priv=00849DBC57D3B92F01864E6E82EB4EF0EF6311E122 +ctype=32 + +[isoldr] +category=SELF +version=0003005000000000 +revision=0001 +program_type=ISO +erk=3F2604FA27AEADFBE1AC69EB00BB16EF196C2193CBD62900FFD8C25041680843 +riv=A414AC1DB7987E43777651B330B899E1 +pub=1F4633AFDE18614D6CEF38A2FD6C4CCAC7B6EB8109D72CD066ECEBA0193EA3F43C37AE83179A4E5F +priv=0085B4B05DEBA7E6AD831653C974D95149803BB272 +ctype=33 + +[isoldr] +category=SELF +revision=0001 +version=0003005500000000 +program_type=ISO +erk=BDB74AA6E3BA2DC10B1BD7F17198399A158DBE1FA0BEA68C90FCACBE4D04BE37 +riv=0207A479B1574F8E7F697528F05D5435 +pub=917E1F1DC48A54EB5F10B38E7569BB5383628A7C906F0DCA62FDA33805C15FAB270016940A09DB58 +priv=00294411363290975BA551336D3965D88AF029A17B +ctype=03 + +[isoldr] +category=SELF +version=0003005600000000 +revision=0001 +program_type=ISO +erk=311C015F169F2A1E0757F7064B14C7C9F3A3FFEE015BD4E3A22401A2667857CE +riv=7BB8B3F5AC8E0890E3148AE5688C7350 +pub=3F040EFA2335FED5670BA4D5C3AB2D9D0B4BA69D154A0062EA995A7D21DBAF0DC5A0DAD333D1C1DD +priv= +ctype=08 + +[isoldr] +category=SELF +revision=0001 +version=0003006100000000 +program_type=ISO +erk=8474ADCA3B3244931EECEB9357841442442A1C4A4BCF4E498E6738950F4E4093 +riv=FFF9CACCC4129125CAFB240F419E5F39 +pub=098E1A53E59A95316B00D5A29C05FFEBAE41D1A8A386F9DA96F98858FD25E07BB7A3BC96A5D5B556 +priv= +ctype=03 + +[isoldr] +category=SELF +revision=0001 +version=0003006600000000 +program_type=ISO +erk=E6A21C599B75696C169EC02582BDA74A776134A6E05108EA701EC0CA2AC03592 +riv=D292A7BD57C0BB2EABBCA1252FA9EDEF +pub=2ED078A13DC4617EB550AD06E228C83C142A2D588EB5E729402D18038A14842FD65B277DCAD225A5 +priv= +ctype=08 + +[isoldr] +category=SELF +revision=0001 +version=0003007400000000 +program_type=ISO +erk=072D3A5C3BDB0D674DE209381432B20414BC9BDA0F583ECB94BD9A134176DD51 +riv=8516A81F02CF938740498A406C880871 +pub=5A778DEB5C4F12E8D48E06A2BBBBE3C90FA8C6C47DF9BDB5697FD4A8EB7941CE3F59A557E81C787D +priv= +ctype=21 + +[isoldr] +category=SELF +version=0003007400000000 +revision=0100 +program_type=ISO +erk=786FAB8A0B89474A2CB80B3EA104CCCB9E13F66B45EC499BB31865D07C661EA8 +riv=94662F13D99A9F5D211C979FFDF65FE3 +pub=912C94C252B7799CEB45DFBB73EF7CAD9BCC0793A3331BBB79E3C47C0F5C782F698065A8D4DB0D8B +priv= +ctype=0E + +[isoldr] +category=SELF +revision=0001 +version=0004001100000000 +program_type=ISO +erk=4262657A3185D9480F82C8BD2F81766FCC2C8FD7DD5EBE8657B00B939E0C75BD +riv=4F1E3EF07D893A4714B1B3D5A4E50479 +pub=4DBFCFA68B52F1D66E09AFA6C18EC65479EDBD027B6B8C6A5D85FE5C84D43EA40CEF1672078A0702 +priv= +ctype=11 + +[isoldr] +category=SELF +version=0004001100000000 +revision=0100 +program_type=ISO +erk=16AA7D7C35399E2B1BFAF68CD19D7512A7855029C08BECC4CC3F035DF7F9C70B +riv=0E50DB6D937D262CB0499136852FCB80 +pub=AEE2795BF295662A50DFAFE70D1B0B6F0A2EBB211E1323A275FC6E2D13BE4F2F10CA34784F4CF1EC +priv= +ctype=0F + +[isoldr] +category=SELF +revision=0001 +version=0004008200000000 +program_type=ISO +erk=63565DBE98C3B1A52AADC907C47130FE57A10734E84F22592670F86ED2B0A086 +riv=953F6A99891B4739358F5363A00C08B9 +pub=26BE7B02E7D65C6C21BF4063CDB8C0092FE1679D62FA1A8CCC284A1D21885473A959992537A06612 +priv= +ctype=15 + +[isoldr] +category=SELF +version=0004008200000000 +revision=0100 +program_type=ISO +erk=B96EA32CB96EA32DB96EA32CB96EA32CB96EA32CB96EA32DB96EA32CB96EA32C +riv=B96EA32CB96EA32DB96EA32DB96EA32C +pub=2D7066E68C6AC3373B1346FD76FE7D18A207C811500E65D85DB57BC4A27AD78F59FD53F38F50E151 +priv=00B96EA32CB96EA32DB96EA32CB96EA32CB96EA32E +ctype=02 + +[lv1ldr] +category=SELF +version=0003003000000000 +program_type=LV1 +erk=B9F3F9E6107CFF2680A91E118C2403CF4A6F18F3C7EFD7D13D1AC4DB760BD222 +riv=B43661B9A79BAD9D8E2B046469CDA1E7 +pub=4C870BE86DDD996A92A3F7F404F33604244A1D02AB5B78BC9DAF030B78BE8867CF586171B7D45D20 +priv=002CC736C7AD06D264E9AB663EB1F35F5DC159248C +ctype=33 + +[lv1ldr] +category=SELF +version=0003004200000000 +program_type=LV1 +erk=B880593856C8C6D2037585626A12977F50DCFCF3F132D2C89AA6E670EAFC1646 +riv=A79B05D4E37B8117A95E6E7C14FB640E +pub=7454C7CCBFC2F66C142D78A730A3A6F973CC0FB75A46FCBB390790138910A0CAC78E5E21F4DA3375 +priv=00033A699FDD2DA6CDD6CCC03B2C6145F998706F74 +ctype=34 + +[lv1ldr] +category=SELF +version=0003005000000000 +program_type=LV1 +erk=1E8EEEA9E80A729F3FA52CF523B25941EA44B4155D94E5DADC5C5A77847620C7 +riv=E034D31A80316960024D1B3D3164FDC3 +pub=7E3A196f4A5879F3A7B091A2263F7C24E1716129B580566D308D9C2254B36AEE53DEF30EC85F8398 +priv=005815D17125D04C33790321DE29EB6241365100B5 +ctype=35 + +[lv1ldr] +category=SELF +version=0003005500000000 +program_type=LV1 +erk=53ABDF84BE08B0351B734F2B97D2BE1621BC6C889E4362E5C70F39D6C3ED9F23 +riv=44E652661AC7584DBE08ECB810FB5FC0 +pub=733198A7759BC07326755BC9773A8A17C8A7043C7BDAB83D88E230512E2EA3852D7DA4263A7E97F9 +priv=004312C65347ACBE95CC306442FEFD0AF4C2935EB3 +ctype=05 + +[lv1ldr] +category=SELF +version=0003005600000000 +program_type=LV1 +erk=48793EBDDA1AF65D737DA2FDA2DD104447A698F8A82CAAEE992831711BA94E83 +riv=15DCF3C67147A45D09DE7521EECA07A1 +pub=85A8868C320127F10B6598964C69221C086702021D31803520E21FDE4DBE827766BE41825CB7328C +priv= +ctype=07 + +[lv1ldr] +category=SELF +revision=0000 +version=0003006100000000 +program_type=LV1 +erk=5FF17D836E2C4AD69476E2614F64BDD05B9115389A9A6D055B5B544B1C34E3D5 +riv=DF0F50EC3C4743C5B17839D7B49F24A4 +pub=1CDABE30833823F461CA534104115FFF60010B710631E435A7D915E82AE88EDE667264656CB7062E +priv= +ctype=05 + +[lv1ldr] +category=SELF +version=0003006600000000 +program_type=LV1 +erk=BD0621FA19383C3C72ECBC3B008F1CD55FFD7C3BB7510BF11AD0CF0FC2B70951 +riv=569AF3745E1E02E3E288273CDE244CD8 +pub=21E26F11C2D69478609DD1BD278CDFC940D90386455BA52FCD1FA7E27AC2AFA826C79A10193B625C +priv= +ctype=07 + +[lv1ldr] +category=SELF +version=0003007400000000 +program_type=LV1 +erk=41A6E0039041E9D8AAF4EF2F2A2971248EDBD96A3985611ED7B4CE73EE4804FE +riv=C8C98D5A5CE23AF5607A352AECACB0DC +pub=4389664390265F96C1A882374C0F856364E33DB09BE124A4666F9A12F0DD9C811EDD55BA21ED0667 +priv= +ctype=12 + +[lv1ldr] +category=SELF +version=0004001100000000 +program_type=LV1 +erk=557EDF6C063F3272B0D44EEC12F418DA774815B5415597CC5F75C21E048BAD74 +riv=7144D7574937818517826227EF4AC0B4 +pub=085D38DBF9B757329EB862107929909D32FA1DAE60641BF4AC25319D7650597EE977F8E810FEEA96 +priv= +ctype=13 + +[lv1ldr] +category=SELF +version=0004008200000000 +program_type=LV1 +erk=10CEA04973FCCC12EC19924510822D8D4C41F657FD3D7E73F415A8D687421BCD +riv=ED8699562C6AC65204FA166257E7FCF4 +pub=9AF86FC869C159FBB62F7D9674EE257ABF12E5A96D5875B4AA73C13C2BC13E2A4079F98B9B935EE2 +priv= +ctype=14 + +[lv2ldr] +category=SELF +version=0003003000000000 +program_type=LV2 +erk=94303F69513572AB5AE17C8C2A1839D2C24C28F65389D3BBB11894CE23E0798F +riv=9769BFD187B90990AE5FEA4E110B9CF5 +pub=AFAF5E96AF396CBB69071082C46A8F34A030E8EDB799E0A7BE00AA264DFF3AEBF7923920D559404D +priv=0070ABF9361B02291829D479F56AB248203CD3EB46 +ctype=20 + +[lv2ldr] +category=SELF +version=0003004200000000 +program_type=LV2 +erk=575B0A6C4B4F2760A03FE4189EBAF4D947279FD982B14070349098B08FF92C10 +riv=411CB18F460CE50CAF2C426D8F0D93C8 +pub=3FEE313954CB3039C321A7E33B97FFDEC8988A8B55759161B04DBF4731284E4A8191E3F17D32B0EA +priv=0073076441A08CD179E5FACE349B86DA58B5B7BA78 +ctype=21 + +[lv2ldr] +category=SELF +version=0003005000000000 +program_type=LV2 +erk=6DBD48D787C58803A8D724DA5ACF04FF8FCE91D7545D2322F2B7ABF57014AF68 +riv=603A36213708520ED5D745DEC1325BA5 +pub=5888CB83AC3CCA9610BC173C53141C0CA58B93719E744660CA8823D5EAEE8F9BF736997054E4B7E3 +priv=0009EBC3DE442FA5FBF6C4F3D4F9EAB07778A142BD +ctype=22 + +[lv2ldr] +category=SELF +version=0003005500000000 +program_type=LV2 +erk=84015E90FA23139628A3C75CC09714E6427B527A82D18ABC3E91CD8D7DDAFF17 +riv=5B240444D645F2038118F97FD5A145D5 +pub=B266318245266B2D33641CD8A864066D077FAC60B7E27399099A70A683454B70F9888E7CC0C2BF72 +priv=009D4CBA2BFB1A8330D3E20E59D281D476D231C73A +ctype=0x32 + +[lv2ldr] +category=SELF +version=0003005600000000 +program_type=LV2 +erk=EAE15444048EFDE7A831BFA9F5D96F047C9FCFF50723E292CF50F5417D81E359 +riv=9CA9282DC7FA9F315EF3156D970B7CD4 +pub=0D58938CB47598A6A672874F1768068F8B80D8D17014D2ABEBAC85E5B0993D9FB6F307DDC3DDA699 +priv= +ctype=33 + +[lv2ldr] +category=SELF +version=0003006100000000 +revision=0000 +program_type=LV2 +erk=88AD367EDEC2FEED3E2F99B1C685075C41BDEC90C84F526CAF588F89BBD1CBCC +riv=8D18E8E525230E63DE10291C9DD615BF +pub=86EED1D65E58890ABDA9ACA486A2BDDB9C0A529C2053FAE301F0F698EAF443DA0F60595A597A7027 +priv= +ctype=32 + +[lv2ldr] +category=SELF +version=0003006600000000 +revision=0000 +program_type=LV2 +erk=688D5FCAC6F4EA35AC6AC79B10506007286131EE038116DB8AA2C0B0340D9FB0 +riv=75E0239D18B0B669EAE650972F99726B +pub=008E1C820AC567D1BFB8FE3CC6AD2E1845A1D1B19ED2E18B18CA34A8D28A83EC60C63859CDB3DACA +priv= +ctype=33 + +[lv2ldr] +category=SELF +version=0003007400000000 +revision=0000 +program_type=LV2 +erk=E81C5B04C29FB079A4A2687A39D4EA97BFB49D80EF546CEB292979A5F77A6254 +riv=15058FA7F2CAD7C528B5F605F6444EB0 +pub=438D0E5C1E7AFB18234DB6867472FF5F52B750F30C379C7DD1EE0FD23E417B3EA819CC01BAC480ED +priv= +ctype=11 + +[lv2ldr] +category=SELF +version=0004001100000000 +revision=0000 +program_type=LV2 +erk=A1E4B86ED02BF7F1372A2C73FE02BC738907EB37CE3BA605FE783C999FAFDB97 +riv=BBE7799B9A37CB272E386618FDFD4AEC +pub=5B31A8E2A663EBD673196E2E1022E0D64988C4E1BBFE5E474415883A3BA0D9C562A2BE9C30E9B4A8 +priv= +ctype=07 + +[lv2ldr] +category=SELF +version=0004008200000000 +program_type=LV2 +erk=0CAF212B6FA53C0DA7E2C575ADF61DBE68F34A33433B1B891ABF5C4251406A03 +riv=9B79374722AD888EB6A35A2DF25A8B3E +pub=1034A6F98AF6625CC3E3604B59B971CA617DF337538D2179EBB22F3BDC9D0C6DA56BA7DDFD205A50 +priv= +ctype=14 + +[appldr] +category=SELF +revision=0000 +version=0000008300000000 +program_type=APP +erk=95F50019E7A68E341FA72EFDF4D60ED376E25CF46BB48DFDD1F080259DC93F04 +riv=4A0955D946DB70D691A640BB7FAECC4C +pub=6F8DF8EBD0A1D1DB08B30DD3A951E3F1F27E34030B42C729C55555232D61B834B8BDFFB07E54B343 +priv=006C3E4CCB2C69A5AD7C6F60448E50C7F9184EEAF4 +ctype=21 + +[appldr] +category=SELF +revision=0001 +version=0003003000000000 +program_type=APP +erk=79481839C406A632BDB4AC093D73D99AE1587F24CE7E69192C1CD0010274A8AB +riv=6F0F25E1C8C4B7AE70DF968B04521DDA +pub=94D1B7378BAFF5DFED269240A7A364ED68446741622E50BC6079B6E606A2F8E0A4C56E5CFF836526 +priv=003DE80167D2F0E9D30F2145144A558D1174F5410C +ctype=11 + +[appldr] +category=SELF +revision=0002 +version=0003003000000000 +program_type=APP +erk=4F89BE98DDD43CAD343F5BA6B1A133B0A971566F770484AAC20B5DD1DC9FA06A +riv=90C127A9B43BA9D8E89FE6529E25206F +pub=8CA6905F46148D7D8D84D2AFCEAE61B41E6750FC22EA435DFA61FCE6F4F860EE4F54D9196CA5290E +priv=00530446451C568968EBF7068B1F45C252D70EC942 +ctype=13 + +[appldr] +category=SELF +revision=0003 +version=0003003000000000 +program_type=APP +erk=C1E6A351FCED6A0636BFCB6801A0942DB7C28BDFC5E0A053A3F52F52FCE9754E +riv=E0908163F457576440466ACAA443AE7C +pub=50022D5D37C97905F898E78E7AA14A0B5CAAD5CE8190AE5629A10D6F0CF4173597B37A95A7545C92 +priv= +ctype=0B + +[appldr] +category=SELF +revision=0004 +version=0003004200000000 +program_type=APP +erk=838F5860CF97CDAD75B399CA44F4C214CDF951AC795298D71DF3C3B7E93AAEDA +riv=7FDBB2E924D182BB0D69844ADC4ECA5B +pub=1F140E8EF887DAB52F079A06E6915A6460B75CD256834A43FA7AF90C23067AF412EDAFE2C1778D69 +priv=0074E922FDEE5DC4CDF22FC8D7986477F813400860 +ctype=14 + +[appldr] +category=SELF +revision=0005 +version=0003004200000000 +program_type=APP +erk=C109AB56593DE5BE8BA190578E7D8109346E86A11088B42C727E2B793FD64BDC +riv=15D3F191295C94B09B71EBDE088A187A +pub=B6BB0A84C649A90D97EBA55B555366F52381BB38A84C8BB71DA5A5A0949043C6DB249029A43156F7 +priv= +ctype=15 + +[appldr] +category=SELF +revision=0006 +version=0003004200000000 +program_type=APP +erk=6DFD7AFB470D2B2C955AB22264B1FF3C67F180983B26C01615DE9F2ECCBE7F41 +riv=24BD1C19D2A8286B8ACE39E4A37801C2 +pub=71F46AC33FF89DF589A100A7FB64CEAC244C9A0CBBC1FDCE80FB4BF8A0D2E66293309CB8EE8CFA95 +priv= +ctype=2C + +[appldr] +category=SELF +revision=0007 +version=0003005000000000 +program_type=APP +erk=945B99C0E69CAF0558C588B95FF41B232660ECB017741F3218C12F9DFDEEDE55 +riv=1D5EFBE7C5D34AD60F9FBC46A5977FCE +pub=AB284CA549B2DE9AA5C903B75652F78D192F8F4A8F3CD99209415C0A84C5C9FD6BF3095C1C18FFCD +priv=002CF896D35DB871D0E6A252E799876A70D043C23E +ctype=15 + +[appldr] +category=SELF +revision=0008 +version=0003005000000000 +program_type=APP +erk=2C9E8969EC44DFB6A8771DC7F7FDFBCCAF329EC3EC070900CABB23742A9A6E13 +riv=5A4CEFD5A9C3C093D0B9352376D19405 +pub=6E82F6B54A0E9DEBE4A8B3043EE3B24CD9BBB62B4416B0482582E419A2552E29AB4BEA0A4D7FA2D5 +priv= +ctype=16 + +[appldr] +category=SELF +revision=0009 +version=0003005000000000 +program_type=APP +erk=F69E4A2934F114D89F386CE766388366CDD210F1D8913E3B973257F1201D632B +riv=F4D535069301EE888CC2A852DB654461 +pub=1D7B974D10E61C2ED087A0981535904677EC07E96260F89565FF7EBDA4EE035C2AA9BCBDD5893F99 +priv= +ctype=2D + +[appldr] +category=SELF +revision=000A +version=0003005500000000 +program_type=APP +erk=29805302E7C92F204009161CA93F776A072141A8C46A108E571C46D473A176A3 +riv=5D1FAB844107676ABCDFC25EAEBCB633 +pub=09301B6436C85B53CB1585300A3F1AF9FB14DB7C30088C4642AD66D5C148B8995BB1A698A8C71827 +priv=0010818ED8A666051C6198662C3D6DDE2CA4901DDC +ctype=25 + +[appldr] +category=SELF +revision=000B +version=0003005500000000 +program_type=APP +erk=A4C97402CC8A71BC7748661FE9CE7DF44DCE95D0D58938A59F47B9E9DBA7BFC3 +riv=E4792F2B9DB30CB8D1596077A13FB3B5 +pub=2733C889D289550FE00EAA5A47A34CEF0C1AF187610EB07BA35D2C09BB73C80B244EB4147700D1BF +priv= +ctype=26 + +[appldr] +category=SELF +revision=000C +version=0003005500000000 +program_type=APP +erk=9814EFFF67B7074D1B263BF85BDC8576CE9DEC914123971B169472A1BC2387FA +riv=D43B1FA8BE15714B3078C23908BB2BCA +pub=7D1986C6BEE6CE1E0C5893BD2DF203881F40D5056761CC3F1F2E9D9A378617A2DE40BA5F09844CEB +priv= +ctype=3D + +[appldr] +category=SELF +revision=000D +version=0003005600000000 +program_type=APP +erk=03B4C421E0C0DE708C0F0B71C24E3EE04306AE7383D8C5621394CCB99FF7A194 +riv=5ADB9EAFE897B54CB1060D6885BE22CF +pub=71502ADB5783583AB88B2D5F23F419AF01C8B1E72FCA1E694AD49FE3266F1F9C61EFC6F29B351142 +priv= +ctype=12 + +[appldr] +category=SELF +revision=000E +version=0003005600000000 +program_type=APP +erk=39A870173C226EB8A3EEE9CA6FB675E82039B2D0CCB22653BFCE4DB013BAEA03 +riv=90266C98CBAA06C1BF145FF760EA1B45 +pub=84DE5692809848E5ACBE25BE548F6981E3DB14735A5DDE1A0FD1F475866532B862B1AB6A004B7255 +priv= +ctype=27 + +[appldr] +category=SELF +revision=000F +version=0003005600000000 +program_type=APP +erk=FD52DFA7C6EEF5679628D12E267AA863B9365E6DB95470949CFD235B3FCA0F3B +riv=64F50296CF8CF49CD7C643572887DA0B +pub=0696D6CCBD7CF585EF5E00D547503C185D7421581BAD196E081723CD0A97FA40B2C0CD2492B0B5A1 +priv= +ctype=3A + +[appldr] +category=SELF +revision=0010 +version=0003006100000000 +program_type=APP +erk=A5E51AD8F32FFBDE808972ACEE46397F2D3FE6BC823C8218EF875EE3A9B0584F +riv=7A203D5112F799979DF0E1B8B5B52AA4 +pub=50597B7F680DD89F6594D9BDC0CBEE03666AB53647D0487F7F452FE2DD02694631EA755548C9E934 +priv= +ctype=25 + +[appldr] +category=SELF +revision=0011 +version=0003006100000000 +program_type=APP +erk=0F8EAB8884A51D092D7250597388E3B8B75444AC138B9D36E5C7C5B8C3DF18FD +riv=97AF39C383E7EF1C98FA447C597EA8FE +pub=2FDA7A56AAEA65921C0284FF1942C6DE137370093D106034B59191951A5201B422D462F8726F852D +priv= +ctype=26 + +[appldr] +category=SELF +revision=0012 +version=0003006100000000 +program_type=APP +erk=D127E0F7F31F2546D374E46F26A45F14016308EDB409185187AB7F0B2DEE6715 +riv=25589F01B97B9BE1E07447A3CE7F06B9 +pub=3C266FF46D1F526405CCCDD67EE9C7D5693B4A072C06988CAD22ADDB64439A32E2337722F51FC15B +priv= +ctype=3D + +[appldr] +category=SELF +revision=0013 +version=0003006600000000 +program_type=APP +erk=DBF62D76FC81C8AC92372A9D631DDC9219F152C59C4B20BFF8F96B64AB065E94 +riv=CB5DD4BE8CF115FFB25801BC6086E729 +pub=B26FE6D3E3A1E766FAE79A8E6A7F48998E7FC1E4B0AD8745FF54C018C2A6CC7A0DD7525FAFEA4917 +priv= +ctype=12 + +[appldr] +category=SELF +revision=0014 +version=0003006600000000 +program_type=APP +erk=491B0D72BB21ED115950379F4564CE784A4BFAABB00E8CB71294B192B7B9F88E +riv=F98843588FED8B0E62D7DDCB6F0CECF4 +pub=04275E8838EF95BD013B223C3DF674540932F21B534C7ED2944B9104D938FEB03B824DDB866AB26E +priv= +ctype=27 + +[appldr] +category=SELF +revision=0015 +version=0003006600000000 +program_type=APP +erk=324D2BFEDA4044604EDCA550EB7F56065C4CA91DFB2636EC78030353DC1CEFF4 +riv=A37B2139FBCF62F6B41F796A594440C8 +pub=A6283C12B04C37DDC6EBBF4B31E5F1B1B2602DC83EBA6362C9C1189BF25A3EF1BB3766625A4E9694 +priv= +ctype=3A + +[appldr] +category=SELF +revision=0016 +version=0003007400000000 +program_type=APP +erk=A106692224F1E91E1C4EBAD4A25FBFF66B4B13E88D878E8CD072F23CD1C5BF7C +riv=62773C70BD749269C0AFD1F12E73909E +pub=566635D3E1DCEC47243AAD1628AE6B2CEB33463FC155E4635846CE33899C5E353DDFA47FEF5694AF +priv= +ctype=30 + +[appldr] +category=SELF +revision=0017 +version=0003007400000000 +program_type=APP +erk=4E104DCE09BA878C75DA98D0B1636F0E5F058328D81419E2A3D22AB0256FDF46 +riv=954A86C4629E116532304A740862EF85 +pub=3B7B04C71CAE2B1199D57453C038BB1B541A05AD1B94167B0AB47A9B24CAECB9000CB21407009666 +priv= +ctype=08 + +[appldr] +category=SELF +revision=0018 +version=0003007400000000 +program_type=APP +erk=1F876AB252DDBCB70E74DC4A20CD8ED51E330E62490E652F862877E8D8D0F997 +riv=BF8D6B1887FA88E6D85C2EDB2FBEC147 +pub=64A04126D77BF6B4D686F6E8F87DD150A5B014BA922D2B694FFF4453E11239A6E0B58F1703C51494 +priv= +ctype=11 + +[appldr] +category=SELF +revision=0019 +version=0004001100000000 +program_type=APP +erk=3236B9937174DF1DC12EC2DD8A318A0EA4D3ECDEA5DFB4AC1B8278447000C297 +riv=6153DEE781B8ADDC6A439498B816DC46 +pub=148DCA961E2738BAF84B2D1B6E2DA2ABD6A95F2C9571E54C6922F9ED9674F062B7F1BE5BD6FA5268 +priv= +ctype=31 + +[appldr] +category=SELF +revision=001A +version=0004001100000000 +program_type=APP +erk=5EFD1E9961462794E3B9EF2A4D0C1F46F642AAE053B5025504130590E66F19C9 +riv=1AC8FA3B3C90F8FDE639515F91B58327 +pub=BE4B1B513536960618BFEF12A713F6673881B02F9DC616191E823FC8337CCF99ADAA6172019C0C23 +priv= +ctype=17 + +[appldr] +category=SELF +revision=001B +version=0004001100000000 +program_type=APP +erk=66637570D1DEC098467DB207BAEA786861964D0964D4DBAF89E76F46955D181B +riv=9F7B5713A5ED59F6B35CD8F8A165D4B8 +pub=4AB6FB1F6F0C3D9219923C1AC683137AB05DF667833CC6A5E8F590E4E28FE2EB180C7D5861117CFB +priv= +ctype=12 + +[appldr] +category=SELF +revision=001C +version=0004008200000000 +program_type=APP +erk=CFF025375BA0079226BE01F4A31F346D79F62CFB643CA910E16CF60BD9092752 +riv=FD40664E2EBBA01BF359B0DCDF543DA4 +pub=36C1ACE6DD5CCC0006FDF3424750FAC515FC5CFA2C93EC53C6EC2BC421708D154E91F2E7EA54A893 +priv= +ctype=09 + +[appldr] +category=SELF +revision=001D +version=0004008200000000 +program_type=APP +erk=D202174EB65A62048F3674B59EF6FE72E1872962F3E1CD658DE8D7AF71DA1F3E +riv=ACB9945914EBB7B9A31ECE320AE09F2D +pub=430322887503CF52928FAAA410FD623C7321281C8825D95F5B47EF078EFCFC44454C3AB4F00BB879 +priv= +ctype=1A + +[appldr] +category=SELF +revision=0000 +version=0000008400000000 +program_type=NPDRM +erk=8E737230C80E66AD0162EDDD32F1F774EE5E4E187449F19079437A508FCF9C86 +riv=7AAECC60AD12AED90C348D8C11D2BED5 +pub=05BF09CB6FD78050C78DE69CC316FF27C9F1ED66A45BFCE0A1E5A6749B19BD546BBB4602CF373440 +priv= +ctype=0A + +[appldr] +category=SELF +revision=0001 +version=0003003000000000 +program_type=NPDRM +erk=F9EDD0301F770FABBA8863D9897F0FEA6551B09431F61312654E28F43533EA6B +riv=A551CCB4A42C37A734A2B4F9657D5540 +pub=B05F9DA5F9121EE4031467E74C505C29A8E29D1022379EDFF0500B9AE480B5DAB4578A4C61C5D6BF +priv=00040AB47509BED04BD96521AD1B365B86BF620A98 +ctype=11 + +[appldr] +category=SELF +revision=0003 +version=0003003000000000 +program_type=NPDRM +erk=1B715B0C3E8DC4C1A5772EBA9C5D34F7CCFE5B82025D453F3167566497239664 +riv=E31E206FBB8AEA27FAB0D9A2FFB6B62F +pub=3F51E59FC74D6618D34431FA67987FA11ABBFACC7111811473CD9988FE91C43FC74605E7B8CB732D +priv= +ctype=08 + +[appldr] +category=SELF +revision=0004 +version=0003004200000000 +program_type=NPDRM +erk=BB4DBF66B744A33934172D9F8379A7A5EA74CB0F559BB95D0E7AECE91702B706 +riv=ADF7B207A15AC601110E61DDFC210AF6 +pub=9C327471BAFF1F877AE4FE29F4501AF5AD6A2C459F8622697F583EFCA2CA30ABB5CD45D1131CAB30 +priv=00B61A91DF4AB6A9F142C326BA9592B5265DA88856 +ctype=16 + +[appldr] +category=SELF +revision=0006 +version=0003004200000000 +program_type=NPDRM +erk=8B4C52849765D2B5FA3D5628AFB17644D52B9FFEE235B4C0DB72A62867EAA020 +riv=05719DF1B1D0306C03910ADDCE4AF887 +pub=2A5D6C6908CA98FC4740D834C6400E6D6AD74CF0A712CF1E7DAE806E98605CC308F6A03658F2970E +priv= +ctype=29 + +[appldr] +category=SELF +revision=0007 +version=0003005000000000 +program_type=NPDRM +erk=3946DFAA141718C7BE339A0D6C26301C76B568AEBC5CD52652F2E2E0297437C3 +riv=E4897BE553AE025CDCBF2B15D1C9234E +pub=A13AFE8B63F897DA2D3DC3987B39389DC10BAD99DFB703838C4A0BC4E8BB44659C726CFD0CE60D0E +priv=009EF86907782A318D4CC3617EBACE2480E73A46F6 +ctype=17 + +[appldr] +category=SELF +revision=0009 +version=0003005000000000 +program_type=NPDRM +erk=0786F4B0CA5937F515BDCE188F569B2EF3109A4DA0780A7AA07BD89C3350810A +riv=04AD3C2F122A3B35E804850CAD142C6D +pub=A1FE61035DBBEA5A94D120D03C000D3B2F084B9F4AFA99A2D4A588DF92B8F36327CE9E47889A45D0 +priv= +ctype=2A + +[appldr] +category=SELF +revision=000A +version=0003005500000000 +program_type=NPDRM +erk=03C21AD78FBB6A3D425E9AAB1298F9FD70E29FD4E6E3A3C151205DA50C413DE4 +riv=0A99D4D4F8301A88052D714AD2FB565E +pub=3995C390C9F7FBBAB124A1C14E70F9741A5E6BDF17A605D88239652C8EA7D5FC9F24B30546C1E44B +priv=009AC6B22A056BA9E0B6D1520F28A57A3135483F9F +ctype=27 + +[appldr] +category=SELF +revision=000C +version=0003005500000000 +program_type=NPDRM +erk=357EBBEA265FAEC271182D571C6CD2F62CFA04D325588F213DB6B2E0ED166D92 +riv=D26E6DD2B74CD78E866E742E5571B84F +pub=00DCF5391618604AB42C8CFF3DC304DF45341EBA4551293E9E2B68FFE2DF527FFA3BE8329E015E57 +priv= +ctype=3A + +[appldr] +category=SELF +revision=000D +version=0003005600000000 +program_type=NPDRM +erk=337A51416105B56E40D7CAF1B954CDAF4E7645F28379904F35F27E81CA7B6957 +riv=8405C88E042280DBD794EC7E22B74002 +pub=9BFF1CC7118D2393DE50D5CF44909860683411A532767BFDAC78622DB9E5456753FE422CBAFA1DA1 +priv= +ctype=18 + +[appldr] +category=SELF +revision=000F +version=0003005600000000 +program_type=NPDRM +erk=135C098CBE6A3E037EBE9F2BB9B30218DDE8D68217346F9AD33203352FBB3291 +riv=4070C898C2EAAD1634A288AA547A35A8 +pub=BBD7CCCB556C2EF0F908DC7810FAFC37F2E56B3DAA5F7FAF53A4944AA9B841F76AB091E16B231433 +priv= +ctype=3B + +[appldr] +category=SELF +revision=0010 +version=0003006100000000 +program_type=NPDRM +erk=4B3CD10F6A6AA7D99F9B3A660C35ADE08EF01C2C336B9E46D1BB5678B4261A61 +riv=C0F2AB86E6E0457552DB50D7219371C5 +pub=64A5C60BC2AD18B8A237E4AA690647E12BF7A081523FAD4F29BE89ACAC72F7AB43C74EC9AFFDA213 +priv= +ctype=27 + +[appldr] +category=SELF +revision=0012 +version=0003006100000000 +program_type=NPDRM +erk=D2F32F6E1D7A96131FAECE657008B57AAC14A9475CEF983A55E6C82CF1FCC374 +riv=211B52440AB7066A53121106FEB29FD5 +pub=EA2F8826D1ECA47B029B41C833615006FAF535AAD30594319EA4F767925EBAE3A3EEE32E6D29580C +priv= +ctype=3A + +[appldr] +category=SELF +revision=0013 +version=0003006600000000 +program_type=NPDRM +erk=265C93CF48562EC5D18773BEB7689B8AD10C5EB6D21421455DEBC4FB128CBF46 +riv=8DEA5FF959682A9B98B688CEA1EF4A1D +pub=9D8DB5A880608DC69717991AFC3AD5C0215A5EE413328C2ABC8F35589E04432373DB2E2339EEF7C8 +priv= +ctype=18 + +[appldr] +category=SELF +revision=0015 +version=0003006600000000 +program_type=NPDRM +erk=3DED5C82E18CD9F695855B1757CA91447EA34D906A66BEAAB46113F9BCE1D92F +riv=ABF2DA36D993554FB060322DC51097F7 +pub=497296C62F2C489F9F0E7628887AD54715EFD1227B053C6AA4501D43FF6FB536B78315C08D786569 +priv= +ctype=3B + +[appldr] +category=SELF +revision=0016 +version=0003007400000000 +program_type=NPDRM +erk=7910340483E419E55F0D33E4EA5410EEEC3AF47814667ECA2AA9D75602B14D4B +riv=4AD981431B98DFD39B6388EDAD742A8E +pub=62DFE488E410B1B6B2F559E4CB932BCB78845AB623CC59FDF65168400FD76FA82ED1DC60E091D1D1 +priv= +ctype=25 + +[appldr] +category=SELF +revision=0018 +version=0003007400000000 +program_type=NPDRM +erk=1A4B32C927257811F777997EA9549CEFD2AE829A528F771A3EE7FEB2110E0133 +riv=402666C76D795D228089810DDC128D14 +pub=ABD149AB27BEE0DEC0E34BB8A8CA225E3FCF504E2DDE6A55BBD39A06CFB068CFC3CF5DF8B117EB5A +priv= +ctype=15 + +[appldr] +category=SELF +revision=0019 +version=0004001100000000 +program_type=NPDRM +erk=FBDA75963FE690CFF35B7AA7B408CF631744EDEF5F7931A04D58FD6A921FFDB3 +riv=F72C1D80FFDA2E3BF085F4133E6D2805 +pub=637EAD34E7B85C723C627E68ABDD0419914EBED4008311731DD87FDDA2DAF71F856A70E14DA17B42 +priv= +ctype=24 + +[appldr] +category=SELF +revision=001B +version=0004001100000000 +program_type=NPDRM +erk=BCF9BD763A7B787CF1428EF45546AF5EBB3D816ABA1C6FF2FFD3D854B71F355B +riv=D03979E47D236BD278EC7331B7DA0BD4 +pub=4F30DF9F3A9D6B3AF92510F81F7961DD404F5E09BFF4D989969727509E39B94A750D12A063189848 +priv= +ctype=17 + +[appldr] +category=SELF +revision=001C +version=0004008200000000 +program_type=NPDRM +erk=8103EA9DB790578219C4CEDF0592B43064A7D98B601B6C7BC45108C4047AA80F +riv=246F4B8328BE6A2D394EDE20479247C5 +pub=503172C9551308A87621ECEE90362D14889BFED2CF32B0B3E32A4F9FE527A41464B735E1ADBC6762 +priv= +ctype=30 + +[appldr] +category=SELF +revision=0000 +version=0003003000000000 +program_type=UNK_7 +erk=D91166973979EA8694476B011AC62C7E9F37DA26DE1E5C2EE3D66E42B8517085 +riv=DC01280A6E46BC674B81A7E8801EBE6E +pub=A0FC44108236141BF3517A662B027AFC1AC513A05690496C754DEB7D43BDC41B80FD75C212624EE4 +priv= +ctype=11 + +[appldr] +category=SELF +revision=0000 +version=0003004200000000 +program_type=UNK_7 +erk=B73111B0B00117E48DE5E2EE5E534C0F0EFFA4890BBB8CAD01EE0F848F91583E +riv=86F56F9E5DE513894874B8BA253334B1 +pub=B0BA1A1AB9723BB4E87CED9637BE056066BC56E16572D43D0210A06411DBF8FEB8885CD912384AE5 +priv= +ctype=12 + +[appldr] +category=SELF +revision=0000 +version=0003005000000000 +program_type=UNK_7 +erk=8E944267C02E69A4FE474B7F5FCD7974A4F936FF4355AEC4F80EFA123858D8F6 +riv=908A75754E521EAC2F5A4889C6D7B72D +pub=91201DA7D79E8EE2563142ECBD646DA026C963AC09E760E5390FFE24DAE6864310ABE147F8204D0B +priv= +ctype=13 + +[appldr] +category=SELF +revision=0000 +version=0003005500000000 +program_type=UNK_7 +erk=BB31DF9A6F62C0DF853075FAA65134D9CE2240306C1731D1F7DA9B5329BD699F +riv=263057225873F83940A65C8C926AC3E4 +pub=BC3A82A4F44C43A197070CD236FDC94FCC542D69A3E803E0AFF78D1F3DA19A79D2F61FAB5B94B437 +priv= +ctype=23 + +[appldr] +category=SELF +revision=0000 +version=0003005600000000 +program_type=UNK_7 +erk=71AA75C70A255580E4AE9BDAA0B08828C53EAA713CD0713797F143B284C1589B +riv=9DED878CB6BA07121C0F50E7B172A8BF +pub=387FCDAEAFF1B59CFAF79CE6215A065ACEAFFAF4048A4F217E1FF5CE67C66EC3F089DB235E52F9D3 +priv= +ctype=29 + +[appldr] +category=SELF +revision=0000 +version=0003006100000000 +program_type=UNK_7 +erk=F5D1DBC182F5083CD4EA37C431C7DAC73882C07F232D2699B1DD9FDDF1BF4195 +riv=D3A7C3C91CBA014FCBCA6D5570DE13FF +pub=97CA8A9781F45E557E98F176EF794FCDA6B151EB3DFD1ABA12151E00AE59957C3B15628FC8875D28 +priv= +ctype=23 + +[appldr] +category=SELF +revision=0000 +version=0003006600000000 +program_type=UNK_7 +erk=BF10F09590C0152F7EF749FF4B990122A4E8E5491DA49A2D931E72EEB990F860 +riv=22C19C5522F7A782AFC547C2640F5BDE +pub=3233BA2B284189FB1687DF653002257A0925D8EB0C64EBBE8CC7DE87F548D107DE1FD3D1D285DB4F +priv= +ctype=29 + +[appldr] +category=SELF +revision=0000 +version=0003007400000000 +program_type=UNK_7 +erk=F11DBD2C97B32AD37E55F8E743BC821D3E67630A6784D9A058DDD26313482F0F +riv=FC5FA12CA3D2D336C4B8B425D679DA55 +pub=19E27EE90E33EDAB16B22E688B5F704E5C6EC1062070EBF43554CD03DFDAE16D684BB8B5574DBECA +priv= +ctype=15 + +[appldr] +category=SELF +revision=0000 +version=0004001100000000 +program_type=UNK_7 +erk=751EE949CD3ADF50A469197494A1EC358409CCBE6E85217EBDE7A87D3FF1ABD8 +riv=23AE4ADA4D3F798DC5ED98000337FF77 +pub=1BABA87CD1AD705C462D4E7427B6DAF59A50383A348A15088F0EDFCF1ADF2B5C2B2D507B2A357D36 +priv= +ctype=1A + +[appldr] +category=SELF +revision=0000 +version=0004008200000000 +program_type=UNK_7 +erk=46BD0891224E0CE13E2162921D4BB76193AEEE4416A729FCDD111C5536BF87C9 +riv=BF036387CDB613C0AC88A6D9D2CC5316 +pub=A14F6D5F9AD7EBB3B7A39A7C32F13E5DC3B0BA16BDC33D39FDDF88F4AEEA6CFEEB0C0796C917A952 +priv= +ctype=0F + diff --git a/PS3/data/ldr_curves b/PS3/data/ldr_curves new file mode 100644 index 0000000..602292a Binary files /dev/null and b/PS3/data/ldr_curves differ diff --git a/PS3/data/vsh_curves b/PS3/data/vsh_curves new file mode 100644 index 0000000..8eea736 Binary files /dev/null and b/PS3/data/vsh_curves differ diff --git a/PS3/klics/CONTEN-TIDCONTEN_TI-DCONTENTIDCONTEN.klic b/PS3/klics/CONTEN-TIDCONTEN_TI-DCONTENTIDCONTEN.klic new file mode 100644 index 0000000..2f1ccb6 --- /dev/null +++ b/PS3/klics/CONTEN-TIDCONTEN_TI-DCONTENTIDCONTEN.klic @@ -0,0 +1 @@ +ExampleExampleEx \ No newline at end of file diff --git a/PS3/raps/Put .rap files here b/PS3/raps/Put .rap files here new file mode 100644 index 0000000..e69de29 diff --git a/PS3/rifs/Put .rif files here b/PS3/rifs/Put .rif files here new file mode 100644 index 0000000..e69de29 diff --git a/Release/scetool.exe b/Release/scetool.exe new file mode 100644 index 0000000..158e95e Binary files /dev/null and b/Release/scetool.exe differ diff --git a/keys.cpp b/keys.cpp deleted file mode 100644 index 43cb6f9..0000000 --- a/keys.cpp +++ /dev/null @@ -1,725 +0,0 @@ -/* -* Copyright (c) 2011-2013 by naehrwert -* Copyright (c) 2012 by flatz -* This file is released under the GPLv2. -*/ - -#include -#include - -#include -#include - -#ifdef _WIN32 -#include -#else -#include -#endif - -#include "config.h" -#include "types.h" -#include "list.h" -#include "sce.h" -#include "keys.h" -#include "util.h" -#include "tables.h" -#include "aes.h" - -/* -[keyname] -type={SELF, RVK, PKG, SPP, OTHER} -revision={00, ..., 18, 8000} -version={..., 0001000000000000, ...} -self_type={LV0, LV1, LV2, APP, ISO, LDR, UNK_7, NPDRM} -key=... -erk=... -riv=... -pub=... -priv=... -ctype=... -*/ - -/*! Loaded keysets. */ -list_t *_keysets; -/*! Loaded curves. */ -curve_t *_curves; -/*! Loaded VSH curves. */ -vsh_curve_t *_vsh_curves; - -static u8 rap_init_key[0x10] = -{ - 0x86, 0x9F, 0x77, 0x45, 0xC1, 0x3F, 0xD8, 0x90, 0xCC, 0xF2, 0x91, 0x88, 0xE3, 0xCC, 0x3E, 0xDF -}; - -static u8 rap_pbox[0x10] = -{ - 0x0C, 0x03, 0x06, 0x04, 0x01, 0x0B, 0x0F, 0x08, 0x02, 0x07, 0x00, 0x05, 0x0A, 0x0E, 0x0D, 0x09 -}; - -static u8 rap_e1[0x10] = -{ - 0xA9, 0x3E, 0x1F, 0xD6, 0x7C, 0x55, 0xA3, 0x29, 0xB7, 0x5F, 0xDD, 0xA6, 0x2A, 0x95, 0xC7, 0xA5 -}; - -static u8 rap_e2[0x10] = -{ - 0x67, 0xD4, 0x5D, 0xA3, 0x29, 0x6D, 0x00, 0x6A, 0x4E, 0x7C, 0x53, 0x7B, 0xF5, 0x53, 0x8C, 0x74 -}; - -static void _fill_property(keyset_t *ks, s8 *prop, s8 *value) -{ - if(strcmp(prop, "type") == 0) - { - if(strcmp(value, "SELF") == 0) - ks->type = KEYTYPE_SELF; - else if(strcmp(value, "RVK") == 0) - ks->type = KEYTYPE_RVK; - else if(strcmp(value, "PKG") == 0) - ks->type = KEYTYPE_PKG; - else if(strcmp(value, "SPP") == 0) - ks->type = KEYTYPE_SPP; - else if(strcmp(value, "OTHER") == 0) - ks->type = KEYTYPE_OTHER; - else - printf("[*] Error: Unknown type '%s'.\n", value); - } - else if(strcmp(prop, "revision") == 0) - ks->key_revision = (u16)_x_to_u64(value); - else if(strcmp(prop, "version") == 0) - ks->version = _x_to_u64(value); - else if(strcmp(prop, "self_type") == 0) - { - if(strcmp(value, "LV0") == 0) - ks->self_type = SELF_TYPE_LV0; - else if(strcmp(value, "LV1") == 0) - ks->self_type = SELF_TYPE_LV1; - else if(strcmp(value, "LV2") == 0) - ks->self_type = SELF_TYPE_LV2; - else if(strcmp(value, "APP") == 0) - ks->self_type = SELF_TYPE_APP; - else if(strcmp(value, "ISO") == 0) - ks->self_type = SELF_TYPE_ISO; - else if(strcmp(value, "LDR") == 0) - ks->self_type = SELF_TYPE_LDR; - else if(strcmp(value, "UNK_7") == 0) - ks->self_type = SELF_TYPE_UNK_7; - else if(strcmp(value, "NPDRM") == 0) - ks->self_type = SELF_TYPE_NPDRM; - else - printf("[*] Error: unknown SELF type '%s'.\n", value); - } - else if(strcmp(prop, "erk") == 0 || strcmp(prop, "key") == 0) - { - ks->erk = _x_to_u8_buffer(value); - ks->erklen = strlen(value) / 2; - } - else if(strcmp(prop, "riv") == 0) - { - ks->riv = _x_to_u8_buffer(value); - ks->rivlen = strlen(value) / 2; - } - else if(strcmp(prop, "pub") == 0) - ks->pub = _x_to_u8_buffer(value); - else if(strcmp(prop, "priv") == 0) - ks->priv = _x_to_u8_buffer(value); - else if(strcmp(prop, "ctype") == 0) - ks->ctype = (u8)_x_to_u64(value); - else - printf("[*] Error: Unknown keyfile property '%s'.\n", prop); -} - -static s64 _compare_keysets(keyset_t *ks1, keyset_t *ks2) -{ - s64 res; - - if((res = (s64)ks1->version - (s64)ks2->version) == 0) - res = (s64)ks1->key_revision - (s64)ks2->key_revision; - - return res; -} - -static void _sort_keysets() -{ - u32 i, to = _keysets->count; - lnode_t *max; - - list_t *tmp = list_create(); - - for(i = 0; i < to; i++) - { - max = _keysets->head; - LIST_FOREACH(iter, _keysets) - { - if(_compare_keysets((keyset_t *)max->value, (keyset_t *)iter->value) < 0) - max = iter; - } - list_push(tmp, max->value); - list_remove_node(_keysets, max); - } - - list_destroy(_keysets); - _keysets = tmp; -} - -void _print_key_list(FILE *fp) -{ - const s8 *name; - s32 len = 0, tmp; - - LIST_FOREACH(iter, _keysets) - if((tmp = strlen(((keyset_t *)iter->value)->name)) > len) - len = tmp; - - fprintf(fp, " Name"); - _print_align(fp, " ", len, 4); - fprintf(fp, " Type Revision Version SELF-Type\n"); - - LIST_FOREACH(iter, _keysets) - { - keyset_t *ks = (keyset_t *)iter->value; - fprintf(fp, " %s", ks->name); - _print_align(fp, " ", len, strlen(ks->name)); - fprintf(fp, " %-5s 0x%04X %s ", _get_name(_key_types, ks->type), ks->key_revision, sce_version_to_str(ks->version)); - if(ks->type == KEYTYPE_SELF) - { - name = _get_name(_self_types, ks->self_type); - if(name != NULL) - fprintf(fp, "[%s]\n", name); - else - fprintf(fp, "0x%08X\n", ks->self_type); - } - else - fprintf(fp, "\n"); - } -} - -#define LINEBUFSIZE 512 -BOOL keys_load(const s8 *kfile) -{ - u32 i = 0, lblen; - FILE *fp; - s8 lbuf[LINEBUFSIZE]; - keyset_t *cks = NULL; - - if((_keysets = list_create()) == NULL) - return FALSE; - - if((fp = fopen(kfile, "r")) == NULL) - { - list_destroy(_keysets); - return FALSE; - } - - do - { - //Get next line. - lbuf[0] = 0; - fgets(lbuf, LINEBUFSIZE, fp); - lblen = strlen(lbuf); - - //Don't parse empty lines (ignore '\n') and comment lines (starting with '#'). - if(lblen > 1 && lbuf[0] != '#') - { - //Remove '\n'. - lbuf[lblen-1] = 0; - - //Check for keyset entry. - if(lblen > 2 && lbuf[0] == '[') - { - if(cks != NULL) - { - //Add to keyset list. - list_push(_keysets, cks); - cks = NULL; - } - - //Find name end. - for(i = 0; lbuf[i] != ']' && lbuf[i] != '\n' && i < lblen; i++); - lbuf[i] = 0; - - //Allocate keyset and fill name. - cks = (keyset_t *)malloc(sizeof(keyset_t)); - memset(cks, 0, sizeof(keyset_t)); - cks->name = strdup(&lbuf[1]); - } - else if(cks != NULL) - { - //Find property name end. - for(i = 0; lbuf[i] != '=' && lbuf[i] != '\n' && i < lblen; i++); - lbuf[i] = 0; - - //Fill property. - _fill_property(cks, &lbuf[0], &lbuf[i+1]); - } - } - } while(!feof(fp)); - - //Add last keyset to keyset list. - if(cks != NULL) - list_push(_keysets, cks); - - //Sort keysets. - _sort_keysets(); - - return TRUE; -} -#undef LINEBUFSIZE - -static keyset_t *_keyset_find_for_self(u32 self_type, u16 key_revision, u64 version) -{ - LIST_FOREACH(iter, _keysets) - { - keyset_t *ks = (keyset_t *)iter->value; - - if(ks->self_type == self_type) - { - switch(self_type) - { - case SELF_TYPE_LV0: - return ks; - break; - case SELF_TYPE_LV1: - if(version <= ks->version) - return ks; - break; - case SELF_TYPE_LV2: - if(version <= ks->version) - return ks; - break; - case SELF_TYPE_APP: - if(key_revision == ks->key_revision) - return ks; - break; - case SELF_TYPE_ISO: - if(version <= ks->version && key_revision == ks->key_revision) - return ks; - break; - case SELF_TYPE_LDR: - return ks; - break; - case SELF_TYPE_NPDRM: - if(key_revision == ks->key_revision) - return ks; - break; - } - } - } - - return NULL; -} - -static keyset_t *_keyset_find_for_rvk(u32 key_revision) -{ - LIST_FOREACH(iter, _keysets) - { - keyset_t *ks = (keyset_t *)iter->value; - - if(ks->type == KEYTYPE_RVK && key_revision <= ks->key_revision) - return ks; - } - - return NULL; -} - -static keyset_t *_keyset_find_for_pkg(u16 key_revision) -{ - LIST_FOREACH(iter, _keysets) - { - keyset_t *ks = (keyset_t *)iter->value; - - if(ks->type == KEYTYPE_PKG && key_revision <= ks->key_revision) - return ks; - } - - return NULL; -} - -static keyset_t *_keyset_find_for_spp(u16 key_revision) -{ - LIST_FOREACH(iter, _keysets) - { - keyset_t *ks = (keyset_t *)iter->value; - - if(ks->type == KEYTYPE_SPP && key_revision <= ks->key_revision) - return ks; - } - - return NULL; -} - -keyset_t *keyset_find(sce_buffer_ctxt_t *ctxt) -{ - keyset_t *res = NULL; - - switch(ctxt->sceh->header_type) - { - case SCE_HEADER_TYPE_SELF: - res = _keyset_find_for_self(ctxt->self.ai->self_type, ctxt->sceh->key_revision, ctxt->self.ai->version); - break; - case SCE_HEADER_TYPE_RVK: - res = _keyset_find_for_rvk(ctxt->sceh->key_revision); - break; - case SCE_HEADER_TYPE_PKG: - res = _keyset_find_for_pkg(ctxt->sceh->key_revision); - break; - case SCE_HEADER_TYPE_SPP: - res = _keyset_find_for_spp(ctxt->sceh->key_revision); - break; - } - - if(res == NULL) - printf("[*] Error: Could not find keyset for %s.\n", _get_name(_sce_header_types, ctxt->sceh->header_type)); - - return res; -} - -keyset_t *keyset_find_by_name(const s8 *name) -{ - LIST_FOREACH(iter, _keysets) - { - keyset_t *ks = (keyset_t *)iter->value; - if(strcmp(ks->name, name) == 0) - return ks; - } - - printf("[*] Error: Could not find keyset '%s'.\n", name); - - return NULL; -} - -BOOL curves_load(const s8 *cfile) -{ - u32 len = 0; - - _curves = (curve_t *)_read_buffer(cfile, &len); - - if(_curves == NULL) - return FALSE; - - if(len != CURVES_LENGTH) - { - free(_curves); - return FALSE; - } - - return TRUE; -} - -curve_t *curve_find(u8 ctype) -{ - if(ctype > CTYPE_MAX) - return NULL; - return &_curves[ctype]; -} - -BOOL vsh_curves_load(const s8 *cfile) -{ - u32 len = 0; - - _vsh_curves = (vsh_curve_t *)_read_buffer(cfile, &len); - - if(_vsh_curves == NULL) - return FALSE; - - if(len != VSH_CURVES_LENGTH) - { - free(_vsh_curves); - return FALSE; - } - - return TRUE; -} - -static curve_t _tmp_curve; -curve_t *vsh_curve_find(u8 ctype) -{ - if(ctype > VSH_CTYPE_MAX) - return NULL; - - _memcpy_inv(_tmp_curve.p, _vsh_curves[ctype].p, 20); - _memcpy_inv(_tmp_curve.a, _vsh_curves[ctype].a, 20); - _memcpy_inv(_tmp_curve.b, _vsh_curves[ctype].b, 20); - _tmp_curve.N[0] = ~0x00; - _memcpy_inv(_tmp_curve.N+1, _vsh_curves[ctype].N, 20); - _memcpy_inv(_tmp_curve.Gx, _vsh_curves[ctype].Gx, 20); - _memcpy_inv(_tmp_curve.Gy, _vsh_curves[ctype].Gx, 20); - - return &_tmp_curve; -} - -static u8 *idps_load() -{ - s8 *ps3 = NULL, path[256]; - u8 *idps; - u32 len = 0; - - if((ps3 = getenv(CONFIG_ENV_PS3)) != NULL) - if(access(ps3, 0) != 0) - ps3 = NULL; - - if(ps3 != NULL) - { - sprintf(path, "%s/%s", ps3, CONFIG_IDPS_FILE); - if(access(path, 0) != 0) - sprintf(path, "%s/%s", CONFIG_IDPS_PATH, CONFIG_IDPS_FILE); - } - else - sprintf(path, "%s/%s", CONFIG_IDPS_PATH, CONFIG_IDPS_FILE); - - idps = (u8 *)_read_buffer(path, &len); - - if(idps == NULL) - return NULL; - - if(len != IDPS_LENGTH) - { - free(idps); - return NULL; - } - - return idps; -} - -static act_dat_t *act_dat_load() -{ - s8 *ps3 = NULL, path[256]; - act_dat_t *act_dat; - u32 len = 0; - - if((ps3 = getenv(CONFIG_ENV_PS3)) != NULL) - if(access(ps3, 0) != 0) - ps3 = NULL; - - if(ps3 != NULL) - { - sprintf(path, "%s/%s", ps3, CONFIG_ACT_DAT_FILE); - if(access(path, 0) != 0) - sprintf(path, "%s/%s", CONFIG_ACT_DAT_PATH, CONFIG_ACT_DAT_FILE); - } - else - sprintf(path, "%s/%s", CONFIG_ACT_DAT_PATH, CONFIG_ACT_DAT_FILE); - - act_dat = (act_dat_t *)_read_buffer(path, &len); - - if(act_dat == NULL) - return NULL; - - if(len != ACT_DAT_LENGTH) - { - free(act_dat); - return NULL; - } - - return act_dat; -} - -static rif_t *rif_load(const s8 *content_id) -{ - s8 *ps3 = NULL, path[256]; - rif_t *rif; - u32 len = 0; - - if((ps3 = getenv(CONFIG_ENV_PS3)) != NULL) - if(access(ps3, 0) != 0) - ps3 = NULL; - - if(ps3 != NULL) - { - sprintf(path, "%s/%s%s", ps3, content_id, CONFIG_RIF_FILE_EXT); - if(access(path, 0) != 0) - sprintf(path, "%s/%s%s", CONFIG_RIF_PATH, content_id, CONFIG_RIF_FILE_EXT); - } - else - sprintf(path, "%s/%s%s", CONFIG_RIF_PATH, content_id, CONFIG_RIF_FILE_EXT); - - rif = (rif_t *)_read_buffer(path, &len); - if(rif == NULL) - return NULL; - - if(len < RIF_LENGTH) - { - free(rif); - return NULL; - } - - return rif; -} - -static u8 *rap_load(const s8 *content_id) -{ - s8 *ps3 = NULL, path[256]; - u8 *rap; - u32 len = 0; - - if((ps3 = getenv(CONFIG_ENV_PS3)) != NULL) - if(access(ps3, 0) != 0) - ps3 = NULL; - - if(ps3 != NULL) - { - sprintf(path, "%s/%s%s", ps3, content_id, CONFIG_RAP_FILE_EXT); - if(access(path, 0) != 0) - sprintf(path, "%s/%s%s", CONFIG_RAP_PATH, content_id, CONFIG_RAP_FILE_EXT); - } - else - sprintf(path, "%s/%s%s", CONFIG_RAP_PATH, content_id, CONFIG_RAP_FILE_EXT); - - rap = (u8 *)_read_buffer(path, &len); - - if(rap == NULL) - return NULL; - - if(len != RAP_LENGTH) - { - free(rap); - return NULL; - } - - return rap; -} - -static BOOL rap_to_klicensee(const s8 *content_id, u8 *klicensee) -{ - u8 *rap; - aes_context aes_ctxt; - int round_num; - int i; - - rap = rap_load(content_id); - if(rap == NULL) - return FALSE; - - aes_setkey_dec(&aes_ctxt, rap_init_key, RAP_KEYBITS); - aes_crypt_ecb(&aes_ctxt, AES_DECRYPT, rap, rap); - - for (round_num = 0; round_num < 5; ++round_num) - { - for (i = 0; i < 16; ++i) - { - int p = rap_pbox[i]; - rap[p] ^= rap_e1[p]; - } - for (i = 15; i >= 1; --i) - { - int p = rap_pbox[i]; - int pp = rap_pbox[i - 1]; - rap[p] ^= rap[pp]; - } - int o = 0; - for (i = 0; i < 16; ++i) - { - int p = rap_pbox[i]; - u8 kc = rap[p] - o; - u8 ec2 = rap_e2[p]; - if (o != 1 || kc != 0xFF) - { - o = kc < ec2 ? 1 : 0; - rap[p] = kc - ec2; - } - else if (kc == 0xFF) - rap[p] = kc - ec2; - else - rap[p] = kc; - } - } - - memcpy(klicensee, rap, RAP_LENGTH); - free(rap); - - return TRUE; -} - -BOOL klicensee_by_content_id(const s8 *content_id, u8 *klicensee) -{ - aes_context aes_ctxt; - - if(rap_to_klicensee(content_id, klicensee) == FALSE) - { - keyset_t *ks_np_idps_const, *ks_np_rif_key; - rif_t *rif; - u8 idps_const[0x10]; - u8 act_dat_key[0x10]; - u32 act_dat_key_index; - u8 *idps; - act_dat_t *act_dat; - - if((idps = idps_load()) == NULL) - { - printf("[*] Error: Could not load IDPS.\n"); - return FALSE; - } - else - _LOG_VERBOSE("IDPS loaded.\n"); - - if((act_dat = act_dat_load()) == NULL) - { - printf("[*] Error: Could not load act.dat.\n"); - return FALSE; - } - else - _LOG_VERBOSE("act.dat loaded.\n"); - - ks_np_idps_const = keyset_find_by_name(CONFIG_NP_IDPS_CONST_KNAME); - if(ks_np_idps_const == NULL) - return FALSE; - memcpy(idps_const, ks_np_idps_const->erk, 0x10); - - ks_np_rif_key = keyset_find_by_name(CONFIG_NP_RIF_KEY_KNAME); - if(ks_np_rif_key == NULL) - return FALSE; - - rif = rif_load(content_id); - if(rif == NULL) - { - printf("[*] Error: Could not obtain klicensee for '%s'.\n", content_id); - return FALSE; - } - - aes_setkey_dec(&aes_ctxt, ks_np_rif_key->erk, RIF_KEYBITS); - aes_crypt_ecb(&aes_ctxt, AES_DECRYPT, rif->act_key_index, rif->act_key_index); - - act_dat_key_index = _ES32(*(u32 *)(rif->act_key_index + 12)); - if(act_dat_key_index > 127) - { - printf("[*] Error: act.dat key index out of bounds.\n"); - return FALSE; - } - - memcpy(act_dat_key, act_dat->primary_key_table + act_dat_key_index * BITS2BYTES(ACT_DAT_KEYBITS), BITS2BYTES(ACT_DAT_KEYBITS)); - - 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_dec(&aes_ctxt, act_dat_key, ACT_DAT_KEYBITS); - aes_crypt_ecb(&aes_ctxt, AES_DECRYPT, rif->klicensee, klicensee); - - free(rif); - - _LOG_VERBOSE("klicensee decrypted.\n"); - } - else - _LOG_VERBOSE("klicensee converted from %s.rap.\n", content_id); - - return TRUE; -} - -keyset_t *keyset_from_buffer(u8 *keyset) -{ - keyset_t *ks; - - if((ks = (keyset_t *)malloc(sizeof(keyset_t))) == NULL) - return NULL; - - ks->erk = (u8 *)_memdup(keyset, 0x20); - ks->erklen = 0x20; - ks->riv = (u8 *)_memdup(keyset + 0x20, 0x10); - ks->rivlen = 0x10; - ks->pub = (u8 *)_memdup(keyset + 0x20 + 0x10, 0x28); - ks->priv = (u8 *)_memdup(keyset + 0x20 + 0x10 + 0x28, 0x15); - ks->ctype = (u8)*(keyset + 0x20 + 0x10 + 0x28 + 0x15); - - return ks; -} diff --git a/sce.cpp b/sce.cpp deleted file mode 100644 index dd647cf..0000000 --- a/sce.cpp +++ /dev/null @@ -1,1001 +0,0 @@ -/* -* Copyright (c) 2011-2013 by naehrwert -* Copyright (c) 2011-2012 by Youness Alaoui -* This file is released under the GPLv2. -*/ - -#include -#include -#include -#include - -#include "types.h" -#include "util.h" -#include "elf.h" -#include "sce.h" -#include "sce_inlines.h" -#include "keys.h" -#include "aes.h" -#include "sha1.h" -#include "ecdsa.h" -#include "tables.h" -#include "config.h" -#include "zlib.h" -#include "np.h" - -void _print_sce_header(FILE *fp, sce_header_t *h) -{ - const s8 *name; - const s8 *key_revision; - - fprintf(fp, "[*] SCE Header:\n"); - fprintf(fp, " Magic 0x%08X [%s]\n", h->magic, (h->magic == SCE_HEADER_MAGIC ? "OK" : "ERROR")); - fprintf(fp, " Version 0x%08X\n", h->version); - - if(h->key_revision == KEY_REVISION_DEBUG) - fprintf(fp, " Key Revision [DEBUG]\n"); - else - fprintf(fp, " Key Revision 0x%04X\n", h->key_revision); - - name = _get_name(_sce_header_types, h->header_type); - if(name != NULL) - fprintf(fp, " Header Type [%s]\n", name); - else - fprintf(fp, " Header Type 0x%04X\n", h->header_type); - - fprintf(fp, " Metadata Offset 0x%08X\n", h->metadata_offset); - fprintf(fp, " Header Length 0x%016llX\n", h->header_len); - fprintf(fp, " Data Length 0x%016llX\n", h->data_len); -} - -void _print_metadata_info(FILE *fp, metadata_info_t *mi) -{ - fprintf(fp, "[*] Metadata Info:\n"); - _hexdump(fp, " Key", 0, mi->key, METADATA_INFO_KEY_LEN, FALSE); - _hexdump(fp, " IV ", 0, mi->iv, METADATA_INFO_IV_LEN, FALSE); -} - -void _print_metadata_header(FILE *fp, metadata_header_t *mh) -{ - fprintf(fp, "[*] Metadata Header:\n"); - fprintf(fp, " Signature Input Length 0x%016llX\n", mh->sig_input_length); - fprintf(fp, " unknown_0 0x%08X\n", mh->unknown_0); - fprintf(fp, " Section Count 0x%08X\n", mh->section_count); - fprintf(fp, " Key Count 0x%08X\n", mh->key_count); - fprintf(fp, " Optional Header Size 0x%08X\n", mh->opt_header_size); - fprintf(fp, " unknown_1 0x%08X\n", mh->unknown_1); - fprintf(fp, " unknown_2 0x%08X\n", mh->unknown_2); -} - -static void _print_metadata_section_header_header(FILE *fp) -{ - fprintf(fp, "[*] Metadata Section Headers:\n"); - fprintf(fp, " Idx Offset Size Type Index Hashed SHA1 Encrypted Key IV Compressed\n"); -} - -void _print_metadata_section_header(FILE *fp, metadata_section_header_t *msh, u32 idx) -{ - fprintf(fp, " %03d %08llX %08llX %02X %02X ", - idx, msh->data_offset, msh->data_size, msh->type, msh->index); - - if(msh->hashed == METADATA_SECTION_HASHED) - fprintf(fp, "[YES] %02X ", msh->sha1_index); - else - fprintf(fp, "[NO ] -- "); - - if(msh->encrypted == METADATA_SECTION_ENCRYPTED) - fprintf(fp, "[YES] %02X %02X ", msh->key_index, msh->iv_index); - else - fprintf(fp, "[NO ] -- -- "); - - if(msh->compressed == METADATA_SECTION_COMPRESSED) - fprintf(fp, "[YES]\n"); - else - fprintf(fp, "[NO ]\n"); -} - -void _print_sce_file_keys(FILE *fp, sce_buffer_ctxt_t *ctxt) -{ - u32 i; - - //Get start of keys. - u8 *keys = (u8 *)ctxt->metash + sizeof(metadata_section_header_t) * ctxt->metah->section_count; - - fprintf(fp, "[*] SCE File Keys:\n"); - for(i = 0; i < ctxt->metah->key_count; i++) - { - fprintf(fp, " %02X:", i); - _hexdump(fp, "", i, keys+i*0x10, 0x10, FALSE); - } -} - -static sce_buffer_ctxt_t *_sce_create_ctxt() -{ - sce_buffer_ctxt_t *res; - - if((res = (sce_buffer_ctxt_t *)malloc(sizeof(sce_buffer_ctxt_t))) == NULL) - return NULL; - - memset(res, 0, sizeof(sce_buffer_ctxt_t)); - - res->scebuffer = NULL; - res->mdec = TRUE; - - //Allocate SCE header. - res->sceh = (sce_header_t *)malloc(sizeof(sce_header_t)); - memset(res->sceh, 0, sizeof(sce_header_t)); - - //Allocate metadata info (with random key/iv). - res->metai = (metadata_info_t *)malloc(sizeof(metadata_info_t)); - _fill_rand_bytes(res->metai->key, 0x10); - memset(res->metai->key_pad, 0, 0x10); - _fill_rand_bytes(res->metai->iv, 0x10); - memset(res->metai->iv_pad, 0, 0x10); - //Allocate metadata header. - res->metah = (metadata_header_t *)malloc(sizeof(metadata_header_t)); - //memset(res->metah, 0, sizeof(metadata_header_t)); - //Allocate signature. - res->sig = (signature_t *)malloc(sizeof(signature_t)); - - res->makeself = NULL; - - return res; -} - -sce_buffer_ctxt_t *sce_create_ctxt_from_buffer(u8 *scebuffer) -{ - sce_buffer_ctxt_t *res; - - if((res = (sce_buffer_ctxt_t *)malloc(sizeof(sce_buffer_ctxt_t))) == NULL) - return NULL; - - memset(res, 0, sizeof(sce_buffer_ctxt_t)); - - res->scebuffer = scebuffer; - res->mdec = FALSE; - - //Set pointer to SCE header. - res->sceh = (sce_header_t *)scebuffer; - _es_sce_header(res->sceh); - - //Set pointers to file type specific headers. - switch(res->sceh->header_type) - { - case SCE_HEADER_TYPE_SELF: - { - //SELF header. - res->self.selfh = (self_header_t *)(res->scebuffer + sizeof(sce_header_t)); - _es_self_header(res->self.selfh); - - //Application info. - res->self.ai = (app_info_t *)(res->scebuffer + res->self.selfh->app_info_offset); - _es_app_info(res->self.ai); - - //Section infos. - res->self.si = (section_info_t *)(res->scebuffer + res->self.selfh->section_info_offset); - - //SCE version. - if(res->self.selfh->sce_version_offset != NULL) - { - res->self.sv = (sce_version_t *)(res->scebuffer + res->self.selfh->sce_version_offset); - _es_sce_version(res->self.sv); - } - else - res->self.sv = 0; - - //Get pointers to all control infos. - u32 len = (u32)res->self.selfh->control_info_size; - if(len > 0) - { - u8 *ptr = res->scebuffer + res->self.selfh->control_info_offset; - res->self.cis = list_create(); - - while(len > 0) - { - control_info_t *tci = (control_info_t *)ptr; - _es_control_info(tci); - ptr += tci->size; - len -= tci->size; - list_add_back(res->self.cis, tci); - } - } - else - res->self.cis = NULL; - } - break; - case SCE_HEADER_TYPE_RVK: - //TODO - break; - case SCE_HEADER_TYPE_PKG: - //TODO - break; - case SCE_HEADER_TYPE_SPP: - //TODO - break; - default: - free(res); - return NULL; - break; - } - - //Set pointers to metadata headers. - res->metai = (metadata_info_t *)(scebuffer + sizeof(sce_header_t) + res->sceh->metadata_offset); - res->metah = (metadata_header_t *)((u8 *)res->metai + sizeof(metadata_info_t)); - res->metash = (metadata_section_header_t *)((u8 *)res->metah + sizeof(metadata_header_t)); - - return res; -} - -sce_buffer_ctxt_t *sce_create_ctxt_build_self(u8 *elf, u32 elf_len) -{ - sce_buffer_ctxt_t *res; - - if((res = _sce_create_ctxt()) == NULL) - return NULL; - - res->sceh->magic = SCE_HEADER_MAGIC; - res->sceh->version = SCE_HEADER_VERSION_2; - res->sceh->header_type = SCE_HEADER_TYPE_SELF; - - //Allocate SELF header. - res->self.selfh = (self_header_t *)malloc(sizeof(self_header_t)); - memset(res->self.selfh, 0, sizeof(self_header_t)); - res->self.selfh->header_type = SUB_HEADER_TYPE_SELF; - //Allocate application info. - res->self.ai = (app_info_t *)malloc(sizeof(app_info_t)); - memset(res->self.ai, 0, sizeof(app_info_t)); - //SCE version. - res->self.sv = (sce_version_t *)malloc(sizeof(sce_version_t)); - //Create control info list. - res->self.cis = list_create(); - //Create optional headers list. - res->self.ohs = list_create(); - - //Makeself context. - res->makeself = (makeself_ctxt_t *)malloc(sizeof(makeself_ctxt_t)); - memset(res->makeself, 0, sizeof(makeself_ctxt_t)); - //ELF buffer. - res->makeself->elf = elf; - res->makeself->elf_len = elf_len; - - //Section list. - res->secs = list_create(); - - return res; -} - -void sce_add_data_section(sce_buffer_ctxt_t *ctxt, void *buffer, u32 size, BOOL may_compr) -{ - sce_section_ctxt_t *sctxt = (sce_section_ctxt_t *)malloc(sizeof(sce_section_ctxt_t)); - sctxt->buffer = buffer; - sctxt->size = size; - sctxt->may_compr = may_compr; - list_add_back(ctxt->secs, sctxt); -} - -void sce_set_metash(sce_buffer_ctxt_t *ctxt, u32 type, BOOL encrypted, u32 idx) -{ - ctxt->metash[idx].type = type; - ctxt->metash[idx].index = (type == METADATA_SECTION_TYPE_PHDR ? idx : type == METADATA_SECTION_TYPE_SHDR ? idx + 1 : idx); - ctxt->metash[idx].hashed = METADATA_SECTION_HASHED; - ctxt->metash[idx].encrypted = (encrypted == TRUE ? METADATA_SECTION_ENCRYPTED : METADATA_SECTION_NOT_ENCRYPTED); - ctxt->metash[idx].compressed = METADATA_SECTION_NOT_COMPRESSED; -} - -void sce_compress_data(sce_buffer_ctxt_t *ctxt) -{ - u32 i = 0; - uLongf size_comp, size_bound; - - LIST_FOREACH(iter, ctxt->secs) - { - sce_section_ctxt_t *sec = (sce_section_ctxt_t *)iter->value; - - //Check if the section may be compressed. - if(sec->may_compr == TRUE) - { - if(sec->size > 0) - { - size_comp = size_bound = compressBound(sec->size); - u8 *buf = (u8 *)malloc(sizeof(u8) * size_bound); - compress(buf, &size_comp, (const u8 *)sec->buffer, sec->size); - - if(size_comp < sec->size) - { - //Set compressed buffer and size. - sec->buffer = buf; - sec->size = size_comp; - - //Set compression in section info. - if(ctxt->sceh->header_type == SCE_HEADER_TYPE_SELF && i < ctxt->makeself->si_sec_cnt) - { - ctxt->self.si[i].compressed = SECTION_INFO_COMPRESSED; - //Update size too. - ctxt->self.si[i].size = size_comp; - } - - //Set compression in maetadata section header. - ctxt->metash[i].compressed = METADATA_SECTION_COMPRESSED; - } - else - { - free(buf); - _LOG_VERBOSE("Skipped compression of section %03d (0x%08X >= 0x%08X)\n", i, size_comp, sec->size); - } - } - else - _LOG_VERBOSE("Skipped compression of section %03d (size is zero)\n", i); - } - - i++; - } -} - -static u32 _sce_get_ci_len(sce_buffer_ctxt_t *ctxt) -{ - u32 res = 0; - - LIST_FOREACH(iter, ctxt->self.cis) - res += ((control_info_t *)iter->value)->size; - - return res; -} - -static u32 _sce_get_oh_len(sce_buffer_ctxt_t *ctxt) -{ - u32 res = 0; - - LIST_FOREACH(iter, ctxt->self.ohs) - res += ((opt_header_t *)iter->value)->size; - - return res; -} - -void _sce_fixup_ctxt(sce_buffer_ctxt_t *ctxt) -{ - u32 i = 0, base_off, last_off; - - //Set section info data. - base_off = ctxt->sceh->header_len; - LIST_FOREACH(iter, ctxt->secs) - { - //Save last offset. - last_off = base_off; - - //Section offsets. - sce_section_ctxt_t *sec = (sce_section_ctxt_t *)iter->value; - sec->offset = base_off; - - //Section infos for SELF (that are present as data sections). - if(ctxt->sceh->header_type == SCE_HEADER_TYPE_SELF && i < ctxt->makeself->si_sec_cnt) - //{ - ctxt->self.si[i].offset = base_off; - // ctxt->self.si[i].size = sec->size; - //} - - //Metadata section headers. - ctxt->metash[i].data_offset = base_off; - ctxt->metash[i].data_size = sec->size; - - //Update offset and data length. - base_off += sec->size; - ctxt->sceh->data_len = base_off - ctxt->sceh->header_len; - base_off = ALIGN(base_off, SCE_ALIGN); - - i++; - } - - //Set metadata offset (counted from after SCE header). - ctxt->sceh->metadata_offset = ctxt->off_metai - sizeof(sce_header_t); - - //Set metadata header values. - ctxt->metah->sig_input_length = ctxt->off_sig; - ctxt->metah->unknown_0 = 1; - ctxt->metah->opt_header_size = _sce_get_oh_len(ctxt); - ctxt->metah->unknown_1 = 0; - ctxt->metah->unknown_2 = 0; - - switch(ctxt->sceh->header_type) - { - case SCE_HEADER_TYPE_SELF: - { - //Set header offsets. - ctxt->self.selfh->app_info_offset = ctxt->off_self.off_ai; - ctxt->self.selfh->elf_offset = ctxt->off_self.off_ehdr; - ctxt->self.selfh->phdr_offset = ctxt->off_self.off_phdr; - ctxt->self.selfh->section_info_offset = ctxt->off_self.off_si; - ctxt->self.selfh->sce_version_offset = ctxt->off_self.off_sv; - ctxt->self.selfh->control_info_offset = ctxt->off_self.off_cis; - ctxt->self.selfh->control_info_size = _sce_get_ci_len(ctxt); - - //Set section headers offset in SELF header (last data section) if available. - if(ctxt->makeself->shdrs != NULL) - ctxt->self.selfh->shdr_offset = last_off; - else - ctxt->self.selfh->shdr_offset = 0; - } - break; - case SCE_HEADER_TYPE_RVK: - //TODO - break; - case SCE_HEADER_TYPE_PKG: - //TODO - break; - case SCE_HEADER_TYPE_SPP: - //TODO - break; - default: - //TODO - break; - } -} - -void _sce_fixup_keys(sce_buffer_ctxt_t *ctxt) -{ - u32 i; - - //Build keys array. - ctxt->keys_len = 0; - ctxt->metah->key_count = 0; - for(i = 0; i < ctxt->metah->section_count; i++) - { - if(ctxt->metash[i].encrypted == METADATA_SECTION_ENCRYPTED) - { - ctxt->keys_len += 0x80; //0x60 HMAC, 0x20 key/iv - ctxt->metah->key_count += 8; - ctxt->metash[i].sha1_index = ctxt->metah->key_count - 8; - ctxt->metash[i].key_index = ctxt->metah->key_count - 2; - ctxt->metash[i].iv_index = ctxt->metah->key_count - 1; - } - else - { - ctxt->keys_len += 0x60; //0x60 HMAC - ctxt->metah->key_count += 6; - ctxt->metash[i].sha1_index = ctxt->metah->key_count - 6; - ctxt->metash[i].key_index = 0xFFFFFFFF; - ctxt->metash[i].iv_index = 0xFFFFFFFF; - } - } - - //Allocate and fill keys array. - ctxt->keys = (u8 *)malloc(sizeof(u8) * ctxt->keys_len); - _fill_rand_bytes(ctxt->keys, ctxt->keys_len); - -#ifndef CONFIG_PRIVATE_BUILD - time_t rawtime; - struct tm *ti; - s8 buf[16+1]; - - time(&rawtime); - ti = localtime(&rawtime); - sprintf(buf, "%02d%02d%02d::%02d%02d%04d", - ti->tm_hour, ti->tm_min, ti->tm_sec, - ti->tm_mday, ti->tm_mon, ti->tm_year+1900); - - memcpy(ctxt->keys + 0x20, "SURPRIZE :D "/**/, 12); - memcpy(ctxt->keys + 0x30, "IM IN UR KEYZ !!", 16); - u8 foo[16] = {0x09, 0xB8, 0xBE, 0xAE, 0x83, 0xC0, 0x17, 0xA6, 0x3B, 0x11, 0xB0, 0x50, 0xC4, 0xCE, 0xED, 0xF9}; - memcpy(ctxt->keys + 0x40, foo, 16); - memcpy(ctxt->keys + 0x50, buf, 16); -#endif -} - -/*! Increase offset and align it. */ -#define _INC_OFF_TYPE(off, type) off; \ - off += sizeof(type); \ - off = ALIGN(off, SCE_ALIGN) -#define _INC_OFF_SIZE(off, size) off; \ - off += (size); \ - off = ALIGN(off, SCE_ALIGN) - -void sce_layout_ctxt(sce_buffer_ctxt_t *ctxt) -{ - u32 coff = 0; - - //SCE header. - ctxt->off_sceh = _INC_OFF_TYPE(coff, sce_header_t); - - switch(ctxt->sceh->header_type) - { - case SCE_HEADER_TYPE_SELF: - { - //SELF header. - ctxt->off_self.off_selfh = _INC_OFF_TYPE(coff, self_header_t); - //Application info. - ctxt->off_self.off_ai = _INC_OFF_TYPE(coff, app_info_t); - //ELF header. - ctxt->off_self.off_ehdr = _INC_OFF_SIZE(coff, ctxt->makeself->ehsize); - //ELF Program headers. - ctxt->off_self.off_phdr = _INC_OFF_SIZE(coff, ctxt->makeself->phsize); - //Section info. - ctxt->off_self.off_si = _INC_OFF_SIZE(coff, sizeof(section_info_t) * ctxt->makeself->si_cnt); - //SCE version. - ctxt->off_self.off_sv = _INC_OFF_TYPE(coff, sce_version_t); - //Control infos. - ctxt->off_self.off_cis = _INC_OFF_SIZE(coff, _sce_get_ci_len(ctxt)); - } - break; - case SCE_HEADER_TYPE_RVK: - //TODO - break; - case SCE_HEADER_TYPE_PKG: - //TODO - break; - case SCE_HEADER_TYPE_SPP: - //TODO - break; - default: - //TODO - break; - } - - //Metadata info. - ctxt->off_metai = _INC_OFF_TYPE(coff, metadata_info_t); - //Metadata header. - ctxt->off_metah = _INC_OFF_TYPE(coff, metadata_header_t); - //Metadata section headers. - ctxt->off_metash = _INC_OFF_SIZE(coff, ctxt->metah->section_count * sizeof(metadata_section_header_t)); - //Keys. - _sce_fixup_keys(ctxt); - ctxt->off_keys = _INC_OFF_SIZE(coff, ctxt->keys_len); - - //SELF only headers. - if(ctxt->sceh->header_type == SCE_HEADER_TYPE_SELF) - { - //Optional headers. - ctxt->off_self.off_ohs = _INC_OFF_SIZE(coff, _sce_get_oh_len(ctxt)); - } - - //Signature. - ctxt->off_sig = _INC_OFF_TYPE(coff, signature_t); - - //Header padding. - ctxt->off_hdrpad = coff; - coff = ALIGN(coff, HEADER_ALIGN); - - //Set header length. - ctxt->sceh->header_len = coff; - - //Set missing values, etc. - _sce_fixup_ctxt(ctxt); -} - -static void _sce_build_header(sce_buffer_ctxt_t *ctxt) -{ - u32 i; - - //Allocate header buffer. - ctxt->scebuffer = (u8*)malloc(sizeof(u8) * ctxt->sceh->header_len); - memset(ctxt->scebuffer, 0, sizeof(u8) * ctxt->sceh->header_len); - - //SCE header. - _copy_es_sce_header((sce_header_t *)(ctxt->scebuffer + ctxt->off_sceh), ctxt->sceh); - - //File type dependent headers. - switch(ctxt->sceh->header_type) - { - case SCE_HEADER_TYPE_SELF: - { - //SELF header. - _copy_es_self_header((self_header_t *)(ctxt->scebuffer + ctxt->off_self.off_selfh), ctxt->self.selfh); - //Application info. - _copy_es_app_info((app_info_t *)(ctxt->scebuffer + ctxt->off_self.off_ai), ctxt->self.ai); - //ELF header. - memcpy(ctxt->scebuffer + ctxt->off_self.off_ehdr, ctxt->makeself->ehdr, ctxt->makeself->ehsize); - //ELF program headers. - memcpy(ctxt->scebuffer + ctxt->off_self.off_phdr, ctxt->makeself->phdrs, ctxt->makeself->phsize); - - //Section info. - u32 i; - for(i = 0; i < ctxt->makeself->si_cnt; i++) - _copy_es_section_info((section_info_t *)(ctxt->scebuffer + ctxt->off_self.off_si + sizeof(section_info_t) * i), &ctxt->self.si[i]); - - //SCE version. - _copy_es_sce_version((sce_version_t *)(ctxt->scebuffer + ctxt->off_self.off_sv), ctxt->self.sv); - - //Control infos. - u32 ci_base = ctxt->off_self.off_cis; - LIST_FOREACH(iter, ctxt->self.cis) - { - control_info_t *ci = (control_info_t *)iter->value; - - //Copy control info header. - _copy_es_control_info((control_info_t *)(ctxt->scebuffer + ci_base), ci); - //Copy data. - memcpy(ctxt->scebuffer + ci_base + sizeof(control_info_t), ((u8 *)ci) + sizeof(control_info_t), ci->size - sizeof(control_info_t)); - - ci_base += ci->size; - } - } - break; - case SCE_HEADER_TYPE_RVK: - //TODO - break; - case SCE_HEADER_TYPE_PKG: - //TODO - break; - case SCE_HEADER_TYPE_SPP: - //TODO - break; - default: - //TODO - break; - } - - //Metadata info. - memcpy(ctxt->scebuffer + ctxt->off_metai, ctxt->metai, sizeof(metadata_info_t)); - //Metadata header. - _copy_es_metadata_header((metadata_header_t *)(ctxt->scebuffer + ctxt->off_metah), ctxt->metah); - //Metadata section headers. - for(i = 0; i < ctxt->metah->section_count; i++) - _copy_es_metadata_section_header((metadata_section_header_t *)(ctxt->scebuffer + ctxt->off_metash + sizeof(metadata_section_header_t) * i), &ctxt->metash[i]); - - //Keys. - //memcpy(ctxt->scebuffer + ctxt->off_keys, ctxt->keys, ctxt->keys_len); - - //SELF only headers. - if(ctxt->sceh->header_type == SCE_HEADER_TYPE_SELF) - { - //Optional headers. - u32 oh_base = ctxt->off_self.off_ohs; - LIST_FOREACH(iter, ctxt->self.ohs) - { - opt_header_t *oh = (opt_header_t *)iter->value; - - //Copy optional header. - _copy_es_opt_header((opt_header_t *)(ctxt->scebuffer + oh_base), oh); - //Copy data. - memcpy(ctxt->scebuffer + oh_base + sizeof(opt_header_t), ((u8 *)oh) + sizeof(opt_header_t), oh->size - sizeof(opt_header_t)); - - oh_base += oh->size; - } - } -} - -static BOOL _sce_sign_header(sce_buffer_ctxt_t *ctxt, keyset_t *ks) -{ - u8 hash[0x14]; - - //Well... - if(ks->priv == NULL || ks->pub == NULL) - return FALSE; - - //Generate header hash. - sha1(ctxt->scebuffer, ctxt->metah->sig_input_length, hash); - - //Generate signature. - ecdsa_set_curve(ks->ctype); - ecdsa_set_pub(ks->pub); - ecdsa_set_priv(ks->priv); - ecdsa_sign(hash, ctxt->sig->r, ctxt->sig->s); - - //Copy Signature. - memcpy(ctxt->scebuffer + ctxt->off_sig, ctxt->sig, sizeof(signature_t)); - - return TRUE; -} - -static void _sce_calculate_hashes(sce_buffer_ctxt_t *ctxt) -{ - u32 i = 0, sha1_idx; - - LIST_FOREACH(iter, ctxt->secs) - { - sce_section_ctxt_t *sec = (sce_section_ctxt_t *)iter->value; - - sha1_idx = ctxt->metash[i].sha1_index; - memset(ctxt->keys + sha1_idx * 0x10, 0, 0x20); - sha1_hmac(ctxt->keys + (sha1_idx + 2) * 0x10, 0x40, (u8 *)sec->buffer, sec->size, ctxt->keys + sha1_idx * 0x10); - - i++; - } -} - -static BOOL _sce_encrypt_header(sce_buffer_ctxt_t *ctxt, u8 *keyset) -{ - u8 *ptr; - size_t nc_off; - u8 sblk[0x10], iv[0x10]; - keyset_t *ks; - aes_context aes_ctxt; - - //Check if a keyset is provided. - if(keyset == NULL) - { - //Try to find keyset. - if((ks = keyset_find(ctxt)) == NULL) - return FALSE; - } - else - { - //Use the provided keyset. - ks = keyset_from_buffer(keyset); - } - - //Calculate hashes. - _sce_calculate_hashes(ctxt); - - //Copy keys. - memcpy(ctxt->scebuffer + ctxt->off_keys, ctxt->keys, ctxt->keys_len); - - //Sign header. - _sce_sign_header(ctxt, ks); - - //Encrypt metadata header, metadata section headers and keys. - nc_off = 0; - ptr = ctxt->scebuffer + ctxt->off_metah; - aes_setkey_enc(&aes_ctxt, ctxt->metai->key, METADATA_INFO_KEYBITS); - memcpy(iv, ctxt->metai->iv, 0x10); - aes_crypt_ctr(&aes_ctxt, - ctxt->sceh->header_len - (sizeof(sce_header_t) + ctxt->sceh->metadata_offset + sizeof(metadata_info_t)), - &nc_off, iv, sblk, ptr, ptr); - - //Encrypt metadata info. - aes_setkey_enc(&aes_ctxt, ks->erk, KEYBITS(ks->erklen)); - ptr = ctxt->scebuffer + ctxt->off_metai; - aes_crypt_cbc(&aes_ctxt, AES_ENCRYPT, sizeof(metadata_info_t), ks->riv, ptr, ptr); - - //Add NPDRM layer. - if(ctxt->sceh->header_type == SCE_HEADER_TYPE_SELF && ctxt->self.ai->self_type == SELF_TYPE_NPDRM) - if(np_encrypt_npdrm(ctxt) == FALSE) - return FALSE; - - return TRUE; -} - -static void _sce_encrypt_data(sce_buffer_ctxt_t *ctxt) -{ - u32 i = 0; - aes_context aes_ctxt; - - LIST_FOREACH(iter, ctxt->secs) - { - sce_section_ctxt_t *sec = (sce_section_ctxt_t *)iter->value; - - size_t nc_off = 0; - u8 buf[16]; - u8 iv[16]; - - if(ctxt->metash[i].encrypted == METADATA_SECTION_ENCRYPTED) - { - memcpy(iv, ctxt->keys + ctxt->metash[i].iv_index * 0x10, 0x10); - aes_setkey_enc(&aes_ctxt, ctxt->keys + ctxt->metash[i].key_index * 0x10, 128); - aes_crypt_ctr(&aes_ctxt, sec->size, &nc_off, iv, buf, (u8 *)sec->buffer, (u8 *)sec->buffer); - } - - i++; - } -} - -BOOL sce_encrypt_ctxt(sce_buffer_ctxt_t *ctxt, u8 *keyset) -{ - //Build SCE file header. - _sce_build_header(ctxt); - - //Encrypt header. - if(_sce_encrypt_header(ctxt, keyset) == FALSE) - return FALSE; - - //Encrypt data. - _sce_encrypt_data(ctxt); - - return TRUE; -} - -BOOL sce_write_ctxt(sce_buffer_ctxt_t *ctxt, s8 *fname) -{ - FILE *fp; - - if((fp = fopen(fname, "wb")) == NULL) - return FALSE; - - //Write SCE file header. - fwrite(ctxt->scebuffer, sizeof(u8), ctxt->sceh->header_len, fp); - - //Write SCE file sections. - LIST_FOREACH(iter, ctxt->secs) - { - sce_section_ctxt_t *sec = (sce_section_ctxt_t *)iter->value; - fseek(fp, sec->offset, SEEK_SET); - fwrite(sec->buffer, sizeof(u8), sec->size, fp); - } - - fclose(fp); - - return TRUE; -} - -BOOL sce_decrypt_header(sce_buffer_ctxt_t *ctxt, u8 *metadata_info, u8 *keyset) -{ - u32 i; - size_t nc_off; - u8 sblk[0x10], iv[0x10]; - keyset_t *ks; - aes_context aes_ctxt; - - //Check if provided metadata info should be used. - if(metadata_info == NULL) - { - //Check if a keyset is provided. - if(keyset == NULL) - { - //Try to find keyset. - if((ks = keyset_find(ctxt)) == NULL) - return FALSE; - - _LOG_VERBOSE("Using keyset [%s 0x%04X %s]\n", ks->name, ks->key_revision, sce_version_to_str(ks->version)); - } - else - { - //Use the provided keyset. - ks = keyset_from_buffer(keyset); - } - - //Remove NPDRM layer. - if(ctxt->sceh->header_type == SCE_HEADER_TYPE_SELF && ctxt->self.ai->self_type == SELF_TYPE_NPDRM) - if(np_decrypt_npdrm(ctxt) == FALSE) - return FALSE; - - //Decrypt metadata info. - aes_setkey_dec(&aes_ctxt, ks->erk, KEYBITS(ks->erklen)); - memcpy(iv, ks->riv, 0x10); //!!! - aes_crypt_cbc(&aes_ctxt, AES_DECRYPT, sizeof(metadata_info_t), iv, (u8 *)ctxt->metai, (u8 *)ctxt->metai); - } - else - { - //Copy provided metadata info over SELF metadata. - memcpy((u8 *)ctxt->metai, metadata_info, sizeof(metadata_info)); - } - - if(ctxt->metai->key_pad[0] != 0x00 || ctxt->metai->iv_pad[0] != 0x00) - return FALSE; - - //Decrypt metadata header, metadata section headers and keys. - nc_off = 0; - aes_setkey_enc(&aes_ctxt, ctxt->metai->key, METADATA_INFO_KEYBITS); - aes_crypt_ctr(&aes_ctxt, - ctxt->sceh->header_len - (sizeof(sce_header_t) + ctxt->sceh->metadata_offset + sizeof(metadata_info_t)), - &nc_off, ctxt->metai->iv, sblk, (u8 *)ctxt->metah, (u8 *)ctxt->metah); - - //Fixup headers. - _es_metadata_header(ctxt->metah); - for(i = 0; i < ctxt->metah->section_count; i++) - _es_metadata_section_header(&ctxt->metash[i]); - - //Metadata decrypted. - ctxt->mdec = TRUE; - - //Set start of SCE file keys. - ctxt->keys = (u8 *)ctxt->metash + sizeof(metadata_section_header_t) * ctxt->metah->section_count; - ctxt->keys_len = ctxt->metah->key_count * 0x10; - - //Set SELF only headers. - if(ctxt->sceh->header_type == SCE_HEADER_TYPE_SELF) - { - //Get pointers to all optional headers. - ctxt->self.ohs = list_create(); - opt_header_t *oh = (opt_header_t *)(ctxt->keys + ctxt->metah->key_count * 0x10); - _es_opt_header(oh); - list_add_back(ctxt->self.ohs, oh); - while(oh->next != 0) - { - oh = (opt_header_t *)((u8 *)oh + oh->size); - _es_opt_header(oh); - list_add_back(ctxt->self.ohs, oh); - } - - //Signature. - ctxt->sig = (signature_t *)((u8 *)oh + oh->size); - } - else - ctxt->sig = (signature_t *)(ctxt->keys + ctxt->metah->key_count * 0x10); - - return TRUE; -} - -BOOL sce_decrypt_data(sce_buffer_ctxt_t *ctxt) -{ - u32 i; - aes_context aes_ctxt; - - //Decrypt sections. - for(i = 0; i < ctxt->metah->section_count; i++) - { - size_t nc_off = 0; - u8 buf[16]; - u8 iv[16]; - - //Only decrypt encrypted sections. - if(ctxt->metash[i].encrypted == METADATA_SECTION_ENCRYPTED) - { - if(ctxt->metash[i].key_index > ctxt->metah->key_count - 1 || ctxt->metash[i].iv_index > ctxt->metah->key_count) - printf("[*] Warning: Skipped decryption of section %03d (marked encrypted but key/iv index out of range)\n", i); - else - { - memcpy(iv, ctxt->keys + ctxt->metash[i].iv_index * 0x10, 0x10); - aes_setkey_enc(&aes_ctxt, ctxt->keys + ctxt->metash[i].key_index * 0x10, 128); - u8 *ptr = ctxt->scebuffer + ctxt->metash[i].data_offset; - aes_crypt_ctr(&aes_ctxt, ctxt->metash[i].data_size, &nc_off, iv, buf, ptr, ptr); - } - } - } - - return TRUE; -} - -void sce_print_info(FILE *fp, sce_buffer_ctxt_t *ctxt) -{ - u32 i; - - //Print SCE header. - _print_sce_header(fp, ctxt->sceh); - - //Check if the metadata was decrypted. - if(ctxt->mdec == FALSE) - return; - - //Print metadata infos. - _print_metadata_info(fp, ctxt->metai); - _print_metadata_header(fp, ctxt->metah); - - //Print section infos. - _print_metadata_section_header_header(fp); - for(i = 0; i < ctxt->metah->section_count; i++) - _print_metadata_section_header(fp, &ctxt->metash[i], i); - - //Print keys. - _print_sce_file_keys(fp, ctxt); -} - -static s8 _sce_tmp_vstr[16]; -s8 *sce_version_to_str(u64 version) -{ - u32 v = version >> 32; - sprintf(_sce_tmp_vstr, "%02X.%02X", (v & 0xFFFF0000) >> 16, v & 0x0000FFFF); - return _sce_tmp_vstr; -} - -u64 sce_str_to_version(s8 *version) -{ - u16 h, l; - sscanf(version, "%02X.%02X", &h, &l); - return ((u64)(h << 16 | l)) << 32; -} - -u64 sce_hexver_to_decver(u64 version) -{ - //TODO: hackity hack. - s8 tmp[16]; - u32 v = version >> 32; - u64 res; - - sprintf(tmp, "%02X%02X", (v & 0xFFFF0000) >> 16, v & 0x0000FFFF); - sscanf(tmp, "%d", &v); - res = v*100; - - return res; -} - -control_info_t *sce_get_ctrl_info(sce_buffer_ctxt_t *ctxt, u32 type) -{ - LIST_FOREACH(iter, ctxt->self.cis) - { - control_info_t *ci = (control_info_t *)iter->value; - if(ci->type == type) - return ci; - } - - return NULL; -} - -opt_header_t *sce_get_opt_header(sce_buffer_ctxt_t *ctxt, u32 type) -{ - LIST_FOREACH(iter, ctxt->self.ohs) - { - opt_header_t *oh = (opt_header_t *)iter->value; - if(oh->type == type) - return oh; - } - - return NULL; -} diff --git a/sce_inlines.h b/sce_inlines.h deleted file mode 100644 index 26a6763..0000000 --- a/sce_inlines.h +++ /dev/null @@ -1,201 +0,0 @@ -/* -* Copyright (c) 2011-2013 by naehrwert -* This file is released under the GPLv2. -*/ - -#ifndef _SCE_INLINES_H_ -#define _SCE_INLINES_H_ - -#include - -#include "types.h" -#include "sce.h" - -static inline void _es_sce_header(sce_header_t *h) -{ - h->magic = _ES32(h->magic); - h->version = _ES32(h->version); - h->key_revision = _ES16(h->key_revision); - h->header_type = _ES16(h->header_type); - h->metadata_offset = _ES32(h->metadata_offset); - h->header_len = _ES64(h->header_len); - h->data_len = _ES64(h->data_len); -} - -static inline void _copy_es_sce_header(sce_header_t *dst, sce_header_t *src) -{ - memcpy(dst, src, sizeof(sce_header_t)); - _es_sce_header(dst); -} - -static inline void _es_metadata_header(metadata_header_t *h) -{ - h->sig_input_length = _ES64(h->sig_input_length); - h->unknown_0 = _ES32(h->unknown_0); - h->section_count = _ES32(h->section_count); - h->key_count = _ES32(h->key_count); - h->opt_header_size = _ES32(h->opt_header_size); - h->unknown_1 = _ES32(h->unknown_1); - h->unknown_2 = _ES32(h->unknown_2); -} - -static inline void _copy_es_metadata_header(metadata_header_t *dst, metadata_header_t *src) -{ - memcpy(dst, src, sizeof(metadata_header_t)); - _es_metadata_header(dst); -} - -static inline void _es_metadata_section_header(metadata_section_header_t *h) -{ - h->data_offset = _ES64(h->data_offset); - h->data_size = _ES64(h->data_size); - h->type = _ES32(h->type); - h->index = _ES32(h->index); - h->hashed = _ES32(h->hashed); - h->sha1_index = _ES32(h->sha1_index); - h->encrypted = _ES32(h->encrypted); - h->key_index = _ES32(h->key_index); - h->iv_index = _ES32(h->iv_index); - h->compressed = _ES32(h->compressed); -} - -static inline void _copy_es_metadata_section_header(metadata_section_header_t *dst, metadata_section_header_t *src) -{ - memcpy(dst, src, sizeof(metadata_section_header_t)); - _es_metadata_section_header(dst); -} - -static inline void _es_self_header(self_header_t *h) -{ - h->header_type = _ES64(h->header_type); - h->app_info_offset = _ES64(h->app_info_offset); - h->elf_offset = _ES64(h->elf_offset); - h->phdr_offset = _ES64(h->phdr_offset); - h->shdr_offset = _ES64(h->shdr_offset); - h->section_info_offset = _ES64(h->section_info_offset); - h->sce_version_offset = _ES64(h->sce_version_offset); - h->control_info_offset = _ES64(h->control_info_offset); - h->control_info_size = _ES64(h->control_info_size); - h->padding = _ES64(h->padding); -} - -static inline void _copy_es_self_header(self_header_t *dst, self_header_t *src) -{ - memcpy(dst, src, sizeof(self_header_t)); - _es_self_header(dst); -} - -static inline void _es_section_info(section_info_t *si) -{ - si->offset = _ES64(si->offset); - si->size = _ES64(si->size); - si->compressed = _ES32(si->compressed); - si->unknown_0 = _ES32(si->unknown_0); - si->unknown_1 = _ES32(si->unknown_1); - si->encrypted = _ES32(si->encrypted); -} - -static inline void _copy_es_section_info(section_info_t *dst, section_info_t *src) -{ - memcpy(dst, src, sizeof(section_info_t)); - _es_section_info(dst); -} - -static inline void _es_sce_version(sce_version_t *sv) -{ - sv->header_type = _ES32(sv->header_type); - sv->present = _ES32(sv->present); - sv->size = _ES32(sv->size); - sv->unknown_3 = _ES32(sv->unknown_3); -} - -static inline void _copy_es_sce_version(sce_version_t *dst, sce_version_t *src) -{ - memcpy(dst, src, sizeof(sce_version_t)); - _es_sce_version(dst); -} - -static inline void _es_app_info(app_info_t *ai) -{ - ai->auth_id = _ES64(ai->auth_id); - ai->vendor_id = _ES32(ai->vendor_id); - ai->self_type = _ES32(ai->self_type); - ai->version = _ES64(ai->version); - ai->padding = _ES64(ai->padding); -} - -static inline void _copy_es_app_info(app_info_t *dst, app_info_t *src) -{ - memcpy(dst, src, sizeof(app_info_t)); - _es_app_info(dst); -} - -static inline void _es_control_info(control_info_t *ci) -{ - ci->type = _ES32(ci->type); - ci->size = _ES32(ci->size); - ci->next = _ES64(ci->next); -} - -static inline void _copy_es_control_info(control_info_t *dst, control_info_t *src) -{ - memcpy(dst, src, sizeof(control_info_t)); - _es_control_info(dst); -} - -static inline void _es_ci_data_digest_40(ci_data_digest_40_t *dig) -{ - dig->fw_version = _ES64(dig->fw_version); -} - -static inline void _copy_es_ci_data_digest_40(ci_data_digest_40_t *dst, ci_data_digest_40_t *src) -{ - memcpy(dst, src, sizeof(ci_data_digest_40_t)); - _es_ci_data_digest_40(dst); -} - -static inline void _es_ci_data_npdrm(ci_data_npdrm_t *np) -{ - np->magic = _ES32(np->magic); - np->unknown_0 = _ES32(np->unknown_0); - np->license_type = _ES32(np->license_type); - np->app_type = _ES32(np->app_type); - np->unknown_1 = _ES64(np->unknown_1); - np->unknown_2 = _ES64(np->unknown_2); -} - -static inline void _copy_es_ci_data_npdrm(ci_data_npdrm_t *dst, ci_data_npdrm_t *src) -{ - memcpy(dst, src, sizeof(ci_data_npdrm_t)); - _es_ci_data_npdrm(dst); -} - -static inline void _es_opt_header(opt_header_t *oh) -{ - oh->type = _ES32(oh->type); - oh->size = _ES32(oh->size); - oh->next = _ES64(oh->next); -} - -static inline void _copy_es_opt_header(opt_header_t *dst, opt_header_t *src) -{ - memcpy(dst, src, sizeof(opt_header_t)); - _es_opt_header(dst); -} - -static inline void _es_oh_data_cap_flags(oh_data_cap_flags_t *cf) -{ - cf->unk3 = _ES64(cf->unk3); - cf->unk4 = _ES64(cf->unk4); - cf->flags = _ES64(cf->flags); - cf->unk6 = _ES32(cf->unk6); - cf->unk7 = _ES32(cf->unk7); -} - -static inline void _copy_es_cap_flags(oh_data_cap_flags_t *dst, oh_data_cap_flags_t *src) -{ - memcpy(dst, src, sizeof(oh_data_cap_flags_t)); - _es_oh_data_cap_flags(dst); -} - -#endif diff --git a/scetool.sln b/scetool.sln new file mode 100644 index 0000000..cb566c5 --- /dev/null +++ b/scetool.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.30723.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "scetool", "scetool.vcxproj", "{39DC2066-1E3C-488C-8A76-1BB64ABF6C99}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {39DC2066-1E3C-488C-8A76-1BB64ABF6C99}.Debug|Win32.ActiveCfg = Debug|Win32 + {39DC2066-1E3C-488C-8A76-1BB64ABF6C99}.Debug|Win32.Build.0 = Debug|Win32 + {39DC2066-1E3C-488C-8A76-1BB64ABF6C99}.Release|Win32.ActiveCfg = Release|Win32 + {39DC2066-1E3C-488C-8A76-1BB64ABF6C99}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/scetool.vcxproj b/scetool.vcxproj new file mode 100644 index 0000000..9097c8d --- /dev/null +++ b/scetool.vcxproj @@ -0,0 +1,128 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {39DC2066-1E3C-488C-8A76-1BB64ABF6C99} + Win32Proj + + + + Application + true + v120_xp + + + Application + false + v120_xp + + + + + + + + + + + + + false + + + false + + + + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreadedDebug + Level3 + ProgramDatabase + Disabled + + + MachineX86 + true + Console + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;zlibd.lib;%(AdditionalDependencies) + /SUBSYSTEM:CONSOLE,5.01 %(AdditionalOptions) + + + + + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreaded + Level3 + ProgramDatabase + + + MachineX86 + true + Console + true + true + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;zlib.lib;%(AdditionalDependencies) + /SUBSYSTEM:CONSOLE,5.01 %(AdditionalOptions) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/scetool.vcxproj.filters b/scetool.vcxproj.filters new file mode 100644 index 0000000..0b74b5d --- /dev/null +++ b/scetool.vcxproj.filters @@ -0,0 +1,153 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + \ No newline at end of file diff --git a/scetool.vcxproj.user b/scetool.vcxproj.user new file mode 100644 index 0000000..ff5921c --- /dev/null +++ b/scetool.vcxproj.user @@ -0,0 +1,8 @@ + + + + + + WindowsLocalDebugger + + \ No newline at end of file diff --git a/self.cpp b/self.cpp deleted file mode 100644 index 8caea0b..0000000 --- a/self.cpp +++ /dev/null @@ -1,1082 +0,0 @@ -/* -* Copyright (c) 2011-2013 by naehrwert -* This file is released under the GPLv2. -*/ - -#include -#include - -#include "types.h" -#include "config.h" -#include "util.h" -#include "sce.h" -#include "sce_inlines.h" -#include "self.h" -#include "elf.h" -#include "elf_inlines.h" -#include "tables.h" -#include "sha1.h" -#include "np.h" - -static void _get_shdr_flags(s8 *str, u64 flags) -{ - memset(str, '-', 3); - str[3] = 0; - - if(flags & SHF_WRITE) - str[0] = 'W'; - if(flags & SHF_ALLOC) - str[1] = 'A'; - if(flags & SHF_EXECINSTR) - str[2] = 'E'; -} - -static void _get_phdr_flags(s8 *str, u64 flags) -{ - memset(str, '-', 3); - str[3] = 0; - - if(flags & PF_X) - str[0] = 'X'; - if(flags & PF_W) - str[1] = 'W'; - if(flags & PF_R) - str[2] = 'R'; -} - -void _print_self_header(FILE *fp, self_header_t *h) -{ - fprintf(fp, "[*] SELF Header:\n"); - fprintf(fp, " Header Type 0x%016llX\n", h->header_type); - fprintf(fp, " App Info Offset 0x%016llX\n", h->app_info_offset); - fprintf(fp, " ELF Offset 0x%016llX\n", h->elf_offset); - fprintf(fp, " PH Offset 0x%016llX\n", h->phdr_offset); - fprintf(fp, " SH Offset 0x%016llX\n", h->shdr_offset); - fprintf(fp, " Section Info Offset 0x%016llX\n", h->section_info_offset); - fprintf(fp, " SCE Version Offset 0x%016llX\n", h->sce_version_offset); - fprintf(fp, " Control Info Offset 0x%016llX\n", h->control_info_offset); - fprintf(fp, " Control Info Size 0x%016llX\n", h->control_info_size); - //fprintf(fp, " padding 0x%016llX\n", h->padding); -} - -void _print_app_info(FILE *fp, app_info_t *ai) -{ - const s8 *name; - - fprintf(fp, "[*] Application Info:\n"); - - name = _get_name(_auth_ids, ai->auth_id); - if(name != NULL) - { - fprintf(fp, " Auth-ID "); - _PRINT_RAW(fp, "0x%016llX ", ai->auth_id); - fprintf(fp, "[%s]\n", name); - } - else - fprintf(fp, " Auth-ID 0x%016llX\n", ai->auth_id); - - name = _get_name(_vendor_ids, ai->vendor_id); - if(name != NULL) - { - fprintf(fp, " Vendor-ID "); - _PRINT_RAW(fp, "0x%08X ", ai->vendor_id); - fprintf(fp, "[%s]\n", name); - } - else - fprintf(fp, " Vendor-ID 0x%08X\n", ai->vendor_id); - - name = _get_name(_self_types, ai->self_type); - if(name != NULL) - fprintf(fp, " SELF-Type [%s]\n", name); - else - fprintf(fp, " SELF-Type 0x%08X\n", ai->self_type); - - fprintf(fp, " Version %s\n", sce_version_to_str(ai->version)); - //fprintf(fp, " padding 0x%016llX\n", ai->padding); -} - -void _print_section_info_header(FILE *fp) -{ - fprintf(fp, "[*] Section Infos:\n"); - fprintf(fp, " Idx Offset Size Compressed unk0 unk1 Encrypted\n"); -} - -void _print_section_info(FILE *fp, section_info_t *si, u32 idx) -{ - fprintf(fp, " %03d %08X %08X %s %08X %08X %s\n", - idx, (u32)si->offset, (u32)si->size, si->compressed == 2 ? "[YES]" : "[NO ]", - si->unknown_0, si->unknown_1, si->encrypted == 1 ? "[YES]" : "[NO ]"); -} - -void _print_sce_version(FILE *fp, sce_version_t *sv) -{ - fprintf(fp, "[*] SCE Version:\n"); - fprintf(fp, " Header Type 0x%08X\n", sv->header_type); - fprintf(fp, " Present [%s]\n", sv->present == SCE_VERSION_PRESENT ? "TRUE" : "FALSE"); - fprintf(fp, " Size 0x%08X\n", sv->size); - fprintf(fp, " unknown_3 0x%08X\n", sv->unknown_3); -} - -void _print_control_info(FILE *fp, control_info_t *ci) -{ - const s8 *name; - - fprintf(fp, "[*] Control Info\n"); - - name = _get_name(_control_info_types, ci->type); - if(name != NULL) - fprintf(fp, " Type %s\n", name); - else - fprintf(fp, " Type 0x%08X\n", ci->type); - - fprintf(fp, " Size 0x%08X\n", ci->size); - fprintf(fp, " Next [%s]\n", ci->next == 1 ? "TRUE" : "FALSE"); - - switch(ci->type) - { - case CONTROL_INFO_TYPE_FLAGS: - _hexdump(fp, " Flags", 0, (u8 *)ci + sizeof(control_info_t), ci->size - sizeof(control_info_t), FALSE); - break; - case CONTROL_INFO_TYPE_DIGEST: - if(ci->size == 0x30) - { - ci_data_digest_30_t *dig = (ci_data_digest_30_t *)((u8 *)ci + sizeof(control_info_t)); - _hexdump(fp, " Digest", 0, dig->digest, 20, FALSE); - } - else if(ci->size == 0x40) - { - ci_data_digest_40_t *dig = (ci_data_digest_40_t *)((u8 *)ci + sizeof(control_info_t)); - _es_ci_data_digest_40(dig); - _hexdump(fp, " Digest 1 ", 0, dig->digest1, 20, FALSE); - _hexdump(fp, " Digest 2 ", 0, dig->digest2, 20, FALSE); - if(dig->fw_version != 0) - fprintf(fp, " FW Version %d [%02d.%02d]\n", (u32)dig->fw_version, ((u32)dig->fw_version)/10000, (((u32)dig->fw_version)%10000)/100); - } - break; - case CONTROL_INFO_TYPE_NPDRM: - { - ci_data_npdrm_t *np = (ci_data_npdrm_t *)((u8 *)ci + sizeof(control_info_t)); - //Was already fixed in decrypt_header. - //_es_ci_data_npdrm(np); - fprintf(fp, " Magic 0x%08X [%s]\n", np->magic, (np->magic == NP_CI_MAGIC ? "OK" : "ERROR")); - fprintf(fp, " unknown_0 0x%08X\n", np->unknown_0); - fprintf(fp, " Licence Type 0x%08X\n", np->license_type); - fprintf(fp, " App Type 0x%08X\n", np->app_type); - fprintf(fp, " ContentID %s\n", np->content_id); - _hexdump(fp, " Random Pad ", 0, np->rndpad, 0x10, FALSE); - _hexdump(fp, " CID_FN Hash ", 0, np->hash_cid_fname, 0x10, FALSE); - _hexdump(fp, " CI Hash ", 0, np->hash_ci, 0x10, FALSE); - fprintf(fp, " unknown_1 0x%016llX\n", np->unknown_1); - fprintf(fp, " unknown_2 0x%016llX\n", np->unknown_2); - } - break; - } -} - -static void _print_cap_flags_flags(FILE *fp, oh_data_cap_flags_t *cf) -{ - if(cf->flags & 0x01) - fprintf(fp, "0x01 "); - if(cf->flags & 0x02) - fprintf(fp, "0x02 "); - if(cf->flags & 0x04) - fprintf(fp, "0x04 "); - if(cf->flags & CAP_FLAG_REFTOOL) - fprintf(fp, "REFTOOL "); - if(cf->flags & CAP_FLAG_DEBUG) - fprintf(fp, "DEBUG "); - if(cf->flags & CAP_FLAG_RETAIL) - fprintf(fp, "RETAIL "); - if(cf->flags & CAP_FLAG_SYSDBG) - fprintf(fp, "SYSDBG "); -} - -void _print_opt_header(FILE *fp, opt_header_t *oh) -{ - const s8 *name; - - fprintf(fp, "[*] Optional Header\n"); - - name = _get_name(_optional_header_types, oh->type); - if(name != NULL) - fprintf(fp, " Type %s\n", name); - else - fprintf(fp, " Type 0x%08X\n", oh->type); - - fprintf(fp, " Size 0x%08X\n", oh->size); - fprintf(fp, " Next [%s]\n", oh->next == 1 ? "TRUE" : "FALSE"); - - switch(oh->type) - { - case OPT_HEADER_TYPE_CAP_FLAGS: - { - oh_data_cap_flags_t *cf = (oh_data_cap_flags_t *)((u8 *)oh + sizeof(opt_header_t)); - - _IF_RAW(_hexdump(fp, " Flags", 0, (u8 *)cf, sizeof(oh_data_cap_flags_t), FALSE)); - - _es_oh_data_cap_flags(cf); - - fprintf(fp, " unknown_3 0x%016llX\n", cf->unk3); - fprintf(fp, " unknown_4 0x%016llX\n", cf->unk4); - - fprintf(fp, " Flags 0x%016llX [ ", cf->flags); - _print_cap_flags_flags(fp, cf); - fprintf(fp, "]\n"); - - fprintf(fp, " unknown_6 0x%08X\n", cf->unk6); - fprintf(fp, " unknown_7 0x%08X\n", cf->unk7); - } - break; -#ifdef CONFIG_DUMP_INDIV_SEED - case OPT_HEADER_TYPE_INDIV_SEED: - { - u8 *is = (u8 *)oh + sizeof(opt_header_t); - _hexdump(fp, " Seed", 0, is, oh->size - sizeof(opt_header_t), TRUE); - } - break; -#endif - } -} - -void _print_elf32_ehdr(FILE *fp, Elf32_Ehdr *h) -{ - const s8 *name; - - fprintf(fp, "[*] ELF32 Header:\n"); - - name = _get_name(_e_types, h->e_type); - if(name != NULL) - fprintf(fp, " Type [%s]\n", name); - else - fprintf(fp, " Type 0x%04X\n", h->e_type); - - name = _get_name(_e_machines, h->e_machine); - if(name != NULL) - fprintf(fp, " Machine [%s]\n", name); - else - fprintf(fp, " Machine 0x%04X\n", h->e_machine); - - fprintf(fp, " Version 0x%08X\n", h->e_version); - fprintf(fp, " Entry 0x%08X\n", h->e_entry); - fprintf(fp, " Program Headers Offset 0x%08X\n", h->e_phoff); - fprintf(fp, " Section Headers Offset 0x%08X\n", h->e_shoff); - fprintf(fp, " Flags 0x%08X\n", h->e_flags); - fprintf(fp, " Program Headers Count %04d\n", h->e_phnum); - fprintf(fp, " Section Headers Count %04d\n", h->e_shnum); - fprintf(fp, " SH String Index %04d\n", h->e_shstrndx); -} - -void _print_elf64_ehdr(FILE *fp, Elf64_Ehdr *h) -{ - const s8 *name; - - fprintf(fp, "[*] ELF64 Header:\n"); - - name = _get_name(_e_types, h->e_type); - if(name != NULL) - fprintf(fp, " Type [%s]\n", name); - else - fprintf(fp, " Type 0x%04X\n", h->e_type); - - name = _get_name(_e_machines, h->e_machine); - if(name != NULL) - fprintf(fp, " Machine [%s]\n", name); - else - fprintf(fp, " Machine 0x%04X\n", h->e_machine); - - fprintf(fp, " Version 0x%08X\n", h->e_version); - fprintf(fp, " Entry 0x%016llX\n", h->e_entry); - fprintf(fp, " Program Headers Offset 0x%016llX\n", h->e_phoff); - fprintf(fp, " Section Headers Offset 0x%016llX\n", h->e_shoff); - fprintf(fp, " Flags 0x%08X\n", h->e_flags); - fprintf(fp, " Program Headers Count %04d\n", h->e_phnum); - fprintf(fp, " Section Headers Count %04d\n", h->e_shnum); - fprintf(fp, " SH String Index %04d\n", h->e_shstrndx); -} - -void _print_elf32_shdr_header(FILE *fp) -{ - fprintf(fp, "[*] ELF32 Section Headers:\n"); - fprintf(fp, " Idx Name Type Flags Address Offset Size ES Align LK\n"); -} - -void _print_elf32_shdr(FILE *fp, Elf32_Shdr *h, u32 idx) -{ - const s8 *name; - s8 flags[4]; - - _get_shdr_flags(flags, h->sh_flags); - - fprintf(fp, " %03d %04X ", idx, h->sh_name); - - name = _get_name(_sh_types, h->sh_type); - if(name != NULL) - fprintf(fp, "%-13s ", name); - else - fprintf(fp, "%08X ", h->sh_type); - - fprintf(fp, "%s %05X %05X %05X %02X %05X %03d\n", - flags, h->sh_addr, h->sh_offset, h->sh_size, h->sh_entsize, h->sh_addralign, h->sh_link); -} - -void _print_elf64_shdr_header(FILE *fp) -{ - fprintf(fp, "[*] ELF64 Section Headers:\n"); - fprintf(fp, " Idx Name Type Flags Address Offset Size ES Align LK\n"); -} - -void _print_elf64_shdr(FILE *fp, Elf64_Shdr *h, u32 idx) -{ - const s8 *name; - s8 flags[4]; - - _get_shdr_flags(flags, h->sh_flags); - - fprintf(fp, " %03d %04X ", idx, h->sh_name); - - name = _get_name(_sh_types, h->sh_type); - if(name != NULL) - fprintf(fp, "%-13s ", name); - else - fprintf(fp, "%08X ", h->sh_type); - - fprintf(fp, "%s %08X %08X %08X %04X %08X %03d\n", - flags, (u32)h->sh_addr, (u32)h->sh_offset, (u32)h->sh_size, (u32)h->sh_entsize, (u32)h->sh_addralign, h->sh_link); -} - -void _print_elf32_phdr_header(FILE *fp) -{ - fprintf(fp, "[*] ELF32 Program Headers:\n"); - fprintf(fp, " Idx Type Offset VAddr PAddr FileSize MemSize Flags Align\n"); -} - -void _print_elf32_phdr(FILE *fp, Elf32_Phdr *h, u32 idx) -{ - const s8 *name; - - s8 flags[4]; - - _get_phdr_flags(flags, h->p_flags); - - fprintf(fp, " %03d ", idx); - - name = _get_name(_ph_types, h->p_type); - if(name != NULL) - fprintf(fp, "%-7s ", name); - else - fprintf(fp, "0x%08X ", h->p_type); - - fprintf(fp, "%05X %05X %05X %05X %05X %s %05X\n", - h->p_offset, h->p_vaddr, h->p_paddr, h->p_filesz, h->p_memsz, flags, h->p_align); -} - -void _print_elf64_phdr_header(FILE *fp) -{ - fprintf(fp, "[*] ELF64 Program Headers:\n"); - fprintf(fp, " Idx Type Offset VAddr PAddr FileSize MemSize PPU SPU RSX Align\n"); -} - -void _print_elf64_phdr(FILE *fp, Elf64_Phdr *h, u32 idx) -{ - const s8 *name; - - s8 ppu[4], spu[4], rsx[4]; - - _get_phdr_flags(ppu, h->p_flags); - _get_phdr_flags(spu, h->p_flags >> 20); - _get_phdr_flags(rsx, h->p_flags >> 24); - - fprintf(fp, " %03d ", idx); - - name = _get_name(_ph_types, h->p_type); - if(name != NULL) - fprintf(fp, "%-8s ", name); - else - fprintf(fp, "%08X ", h->p_type); - - fprintf(fp, "%08X %08X %08X %08X %08X %s %s %s %08X\n", - (u32)h->p_offset, (u32)h->p_vaddr, (u32)h->p_paddr, (u32)h->p_filesz, (u32)h->p_memsz, ppu, spu, rsx, (u32)h->p_align); -} - -BOOL self_print_info(FILE *fp, sce_buffer_ctxt_t *ctxt) -{ - u32 i, self_type; - const u8 *eident; - - //Check for SELF. - if(ctxt->sceh->header_type != SCE_HEADER_TYPE_SELF) - return FALSE; - - //Print SELF infos. - _print_self_header(fp, ctxt->self.selfh); - _print_app_info(fp, ctxt->self.ai); - if(ctxt->self.sv != NULL) - _print_sce_version(fp, ctxt->self.sv); - - //Print control infos. - if(ctxt->self.cis != NULL) - LIST_FOREACH(iter, ctxt->self.cis) - _print_control_info(fp, (control_info_t *)iter->value); - - //Print optional headers. - if(ctxt->mdec == TRUE) - { - LIST_FOREACH(iter, ctxt->self.ohs) - { -#ifndef CONFIG_DUMP_INDIV_SEED - if(((opt_header_t *)iter->value)->type != OPT_HEADER_TYPE_INDIV_SEED) - _print_opt_header(fp, (opt_header_t *)iter->value); -#else - _print_opt_header(fp, (opt_header_t *)iter->value); -#endif - } - } - - self_type = ctxt->self.ai->self_type; - eident = ctxt->scebuffer + ctxt->self.selfh->elf_offset; - - //SPU is 32 bit. - if(self_type == SELF_TYPE_LDR || self_type == SELF_TYPE_ISO || eident[EI_CLASS] == ELFCLASS32) - { - //32 bit ELF. - Elf32_Ehdr *eh = (Elf32_Ehdr *)(ctxt->scebuffer + ctxt->self.selfh->elf_offset); - _es_elf32_ehdr(eh); - - //Print section infos. - _print_section_info_header(fp); - for(i = 0; i < eh->e_phnum; i++) - { - _es_section_info(&ctxt->self.si[i]); - _print_section_info(fp, &ctxt->self.si[i], i); - } - - //Print ELF header. - _print_elf32_ehdr(fp, eh); - - Elf32_Phdr *ph = (Elf32_Phdr *)(ctxt->scebuffer + ctxt->self.selfh->phdr_offset); - - //Print program headers. - _print_elf32_phdr_header(fp); - for(i = 0; i < eh->e_phnum; i++) - { - _es_elf32_phdr(&ph[i]); - _print_elf32_phdr(fp, &ph[i], i); - } - - if(eh->e_shnum > 0) - { - Elf32_Shdr *sh = (Elf32_Shdr *)(ctxt->scebuffer + ctxt->self.selfh->shdr_offset); - - //Print section headers. - _print_elf32_shdr_header(fp); - for(i = 0; i < eh->e_shnum; i++) - { - _es_elf32_shdr(&sh[i]); - _print_elf32_shdr(fp, &sh[i], i); - } - } - } - else - { - //64 bit ELF. - Elf64_Ehdr *eh = (Elf64_Ehdr *)(ctxt->scebuffer + ctxt->self.selfh->elf_offset); - _es_elf64_ehdr(eh); - - //Print section infos. - _print_section_info_header(fp); - for(i = 0; i < eh->e_phnum; i++) - { - _es_section_info(&ctxt->self.si[i]); - _print_section_info(fp, &ctxt->self.si[i], i); - } - - //Print ELF header. - _print_elf64_ehdr(stdout, eh); - - Elf64_Phdr *ph = (Elf64_Phdr *)(ctxt->scebuffer + ctxt->self.selfh->phdr_offset); - - //Print program headers. - _print_elf64_phdr_header(fp); - for(i = 0; i < eh->e_phnum; i++) - { - _es_elf64_phdr(&ph[i]); - _print_elf64_phdr(fp, &ph[i], i); - } - - if(eh->e_shnum > 0) - { - Elf64_Shdr *sh = (Elf64_Shdr *)(ctxt->scebuffer + ctxt->self.selfh->shdr_offset); - - //Print section headers. - _print_elf64_shdr_header(fp); - for(i = 0; i < eh->e_shnum; i++) - { - _es_elf64_shdr(&sh[i]); - _print_elf64_shdr(fp, &sh[i], i); - } - } - } - - return TRUE; -} - -//TODO: maybe implement better. -BOOL self_write_to_elf(sce_buffer_ctxt_t *ctxt, const s8 *elf_out) -{ - FILE *fp; - u32 i, self_type; - - const u8 *eident; - - //Check for SELF. - if(ctxt->sceh->header_type != SCE_HEADER_TYPE_SELF) - return FALSE; - - if((fp = fopen(elf_out, "wb")) == NULL) - return FALSE; - - self_type = ctxt->self.ai->self_type; - eident = ctxt->scebuffer + ctxt->self.selfh->elf_offset; - - //SPU is 32 bit. - if(self_type == SELF_TYPE_LDR || self_type == SELF_TYPE_ISO || eident[EI_CLASS] == ELFCLASS32) - { -#ifdef CONFIG_DUMP_INDIV_SEED - /* - //Print individuals seed. - if(self_type == SELF_TYPE_ISO) - { - u8 *indiv_seed = (u8 *)ctxt->self.ish + sizeof(iseed_header_t); - s8 ifile[256]; - sprintf(ifile, "%s.indiv_seed.bin", elf_out); - FILE *ifp = fopen(ifile, "wb"); - fwrite(indiv_seed, sizeof(u8), ctxt->self.ish->size - sizeof(iseed_header_t), ifp); - fclose(ifp); - } - */ -#endif - - //32 bit ELF. - Elf32_Ehdr ceh, *eh = (Elf32_Ehdr *)(ctxt->scebuffer + ctxt->self.selfh->elf_offset); - _copy_es_elf32_ehdr(&ceh, eh); - - //Write ELF header. - fwrite(eh, sizeof(Elf32_Ehdr), 1, fp); - - //Write program headers. - Elf32_Phdr *ph = (Elf32_Phdr *)(ctxt->scebuffer + ctxt->self.selfh->phdr_offset); - fwrite(ph, sizeof(Elf32_Phdr), ceh.e_phnum, fp); - - //Write program data. - metadata_section_header_t *msh = ctxt->metash; - for(i = 0; i < ctxt->metah->section_count; i++) - { - if(msh[i].type == METADATA_SECTION_TYPE_PHDR) - { - _es_elf32_phdr(&ph[msh[i].index]); - fseek(fp, ph[msh[i].index].p_offset, SEEK_SET); - fwrite(ctxt->scebuffer + msh[i].data_offset, sizeof(u8), msh[i].data_size, fp); - } - } - - //Write section headers. - if(ctxt->self.selfh->shdr_offset != 0) - { - Elf32_Shdr *sh = (Elf32_Shdr *)(ctxt->scebuffer + ctxt->self.selfh->shdr_offset); - fseek(fp, ceh.e_shoff, SEEK_SET); - fwrite(sh, sizeof(Elf32_Shdr), ceh.e_shnum, fp); - } - } - else - { - //64 bit ELF. - Elf64_Ehdr ceh, *eh = (Elf64_Ehdr *)(ctxt->scebuffer + ctxt->self.selfh->elf_offset); - _copy_es_elf64_ehdr(&ceh, eh); - - //Write ELF header. - fwrite(eh, sizeof(Elf64_Ehdr), 1, fp); - - //Write program headers. - Elf64_Phdr *ph = (Elf64_Phdr *)(ctxt->scebuffer + ctxt->self.selfh->phdr_offset); - fwrite(ph, sizeof(Elf64_Phdr), ceh.e_phnum, fp); - - //Write program data. - metadata_section_header_t *msh = ctxt->metash; - for(i = 0; i < ctxt->metah->section_count; i++) - { - if(msh[i].type == METADATA_SECTION_TYPE_PHDR) - { - if(msh[i].compressed == METADATA_SECTION_COMPRESSED) - { - _es_elf64_phdr(&ph[msh[i].index]); - u8 *data = (u8 *)malloc(ph[msh[i].index].p_filesz); - - _zlib_inflate(ctxt->scebuffer + msh[i].data_offset, msh[i].data_size, data, ph[msh[i].index].p_filesz); - fseek(fp, ph[msh[i].index].p_offset, SEEK_SET); - fwrite(data, sizeof(u8), ph[msh[i].index].p_filesz, fp); - - free(data); - } - else - { - _es_elf64_phdr(&ph[msh[i].index]); - fseek(fp, ph[msh[i].index].p_offset, SEEK_SET); - fwrite(ctxt->scebuffer + msh[i].data_offset, sizeof(u8), msh[i].data_size, fp); - } - } - } - - //Write section headers. - if(ctxt->self.selfh->shdr_offset != 0) - { - Elf64_Shdr *sh = (Elf64_Shdr *)(ctxt->scebuffer + ctxt->self.selfh->shdr_offset); - fseek(fp, ceh.e_shoff, SEEK_SET); - fwrite(sh, sizeof(Elf64_Shdr), ceh.e_shnum, fp); - } - } - - fclose(fp); - - return TRUE; -} - -/*! Static zero control flags. */ -static u8 _static_control_flags[0x20] = -{ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -/*! Static control digest1. */ -static u8 _static_control_digest[0x14] = -{ - 0x62, 0x7C, 0xB1, 0x80, 0x8A, 0xB9, 0x38, 0xE3, 0x2C, 0x8C, 0x09, 0x17, 0x08, 0x72, 0x6A, 0x57, 0x9E, 0x25, 0x86, 0xE4 -}; - -static BOOL _create_control_infos(sce_buffer_ctxt_t *ctxt, self_config_t *sconf) -{ - control_info_t *ci; - u32 self_type = ctxt->self.ai->self_type; - - //Step 1. - switch(self_type) - { - case SELF_TYPE_LV0: - case SELF_TYPE_LV1: - case SELF_TYPE_LV2: - case SELF_TYPE_APP: - case SELF_TYPE_ISO: - case SELF_TYPE_LDR: - case SELF_TYPE_NPDRM: //TODO: <-- figure more out. - { - //Add control flags. - ci = (control_info_t *)malloc(sizeof(control_info_t) + sizeof(ci_data_flags_t)); - ci->type = CONTROL_INFO_TYPE_FLAGS; - ci->size = sizeof(control_info_t) + sizeof(ci_data_flags_t); - ci->next = 1; - - ci_data_flags_t *cif = (ci_data_flags_t *)((u8 *)ci + sizeof(control_info_t)); - - //Add default flags. - if(sconf->ctrl_flags == NULL) - memcpy(cif->data, _static_control_flags, 0x20); - else - memcpy(cif->data, sconf->ctrl_flags, 0x20); - - list_add_back(ctxt->self.cis, ci); - } - break; - } - - //Step 2. - switch(self_type) - { - case SELF_TYPE_LV0: - case SELF_TYPE_LV1: - case SELF_TYPE_LV2: - case SELF_TYPE_APP: - case SELF_TYPE_ISO: - case SELF_TYPE_LDR: - case SELF_TYPE_NPDRM: - { - //Add digest 0x40. - ci = (control_info_t *)malloc(sizeof(control_info_t) + sizeof(ci_data_digest_40_t)); - ci->type = CONTROL_INFO_TYPE_DIGEST; - ci->size = sizeof(control_info_t) + sizeof(ci_data_digest_40_t); - if(self_type == SELF_TYPE_NPDRM) - ci->next = 1; - else - ci->next = 0; - - ci_data_digest_40_t *cid = (ci_data_digest_40_t *)((u8 *)ci + sizeof(control_info_t)); - memcpy(cid->digest1, _static_control_digest, 0x14); - memset(cid->digest2, 0, 0x14); - sha1(ctxt->makeself->elf, ctxt->makeself->elf_len, cid->digest2); - - //TODO: check that. - if(self_type == SELF_TYPE_NPDRM) - cid->fw_version = sce_hexver_to_decver(sconf->fw_version); - else - cid->fw_version = 0; - - //Fixup. - _es_ci_data_digest_40(cid); - - list_add_back(ctxt->self.cis, ci); - } - break; - } - - //Step 3. - switch(self_type) - { - case SELF_TYPE_NPDRM: - { - //Add NPDRM control info. - if(sconf->npdrm_config == NULL) - return FALSE; - - ci = (control_info_t *)malloc(sizeof(control_info_t) + sizeof(ci_data_npdrm_t)); - ci->type = CONTROL_INFO_TYPE_NPDRM; - ci->size = sizeof(control_info_t) + sizeof(ci_data_npdrm_t); - ci->next = 0; - - ci_data_npdrm_t *cinp = (ci_data_npdrm_t *)((u8 *)ci + sizeof(control_info_t)); - - //Create NPDRM control info. - if(np_create_ci(sconf->npdrm_config, cinp) == FALSE) - { - free(ci); - return FALSE; - } - - list_add_back(ctxt->self.cis, ci); - } - break; - } - - return TRUE; -} - -static void _set_cap_flags(u32 self_type, oh_data_cap_flags_t *capf) -{ - switch(self_type) - { - case SELF_TYPE_LV0: - capf->flags = CAP_FLAG_SYSDBG | CAP_FLAG_RETAIL | CAP_FLAG_DEBUG | CAP_FLAG_REFTOOL | 0x3; //0x7B; - capf->unk6 = 1; - break; - case SELF_TYPE_LV1: - capf->flags = CAP_FLAG_SYSDBG | CAP_FLAG_RETAIL | CAP_FLAG_DEBUG | CAP_FLAG_REFTOOL | 0x3; //0x7B; - capf->unk6 = 1; - break; - case SELF_TYPE_LV2: - capf->flags = CAP_FLAG_SYSDBG | CAP_FLAG_RETAIL | CAP_FLAG_DEBUG | CAP_FLAG_REFTOOL | 0x3; //0x7B; - capf->unk6 = 1; - break; - case SELF_TYPE_APP: - capf->flags = CAP_FLAG_SYSDBG | CAP_FLAG_RETAIL | CAP_FLAG_DEBUG | CAP_FLAG_REFTOOL | 0x3; //0x7B; - capf->unk6 = 1; - capf->unk7 = 0x20000; - break; - case SELF_TYPE_ISO: - capf->flags = CAP_FLAG_SYSDBG | CAP_FLAG_RETAIL | CAP_FLAG_DEBUG | CAP_FLAG_REFTOOL; //0x78; - break; - case SELF_TYPE_LDR: - capf->flags = CAP_FLAG_SYSDBG | CAP_FLAG_RETAIL | CAP_FLAG_DEBUG | CAP_FLAG_REFTOOL; //0x78; - break; - case SELF_TYPE_NPDRM: - capf->flags = CAP_FLAG_RETAIL | CAP_FLAG_DEBUG | CAP_FLAG_REFTOOL | 0x3; //0x3B; - capf->unk6 = 1; - capf->unk7 = 0x2000; - break; - } - - _es_oh_data_cap_flags(capf); -} - -static BOOL _create_optional_headers(sce_buffer_ctxt_t *ctxt, self_config_t *sconf) -{ - opt_header_t *oh; - u32 self_type = ctxt->self.ai->self_type; - - //Step 1. - switch(self_type) - { - case SELF_TYPE_LV0: - case SELF_TYPE_LV1: - case SELF_TYPE_LV2: - case SELF_TYPE_APP: - case SELF_TYPE_ISO: - case SELF_TYPE_LDR: - case SELF_TYPE_NPDRM: - { - //Add capability flags. - oh = (opt_header_t *)malloc(sizeof(opt_header_t) + sizeof(oh_data_cap_flags_t)); - oh->type = OPT_HEADER_TYPE_CAP_FLAGS; - oh->size = sizeof(opt_header_t) + sizeof(oh_data_cap_flags_t); - if(self_type == SELF_TYPE_ISO) - oh->next = 1; - else - oh->next = 0; - - oh_data_cap_flags_t *capf = (oh_data_cap_flags_t *)((u8 *)oh + sizeof(opt_header_t)); - - //Add default flags. - if(sconf->cap_flags == NULL) - _set_cap_flags(self_type, capf); - else - memcpy(capf, sconf->cap_flags, 0x20); - - list_add_back(ctxt->self.ohs, oh); - } - break; - } - - //Step 2. - switch(self_type) - { - case SELF_TYPE_ISO: - { - //Add individuals seed. - oh = (opt_header_t *)malloc(sizeof(opt_header_t) + 0x100); - oh->type = OPT_HEADER_TYPE_INDIV_SEED; - oh->size = sizeof(opt_header_t) + 0x100; - oh->next = 0; - - u8 *is = (u8 *)oh + sizeof(opt_header_t); - memset(is, 0, 0x100); -#ifdef CONFIG_CUSTOM_INDIV_SEED - if(sconf->indiv_seed != NULL) - memcpy(is, sconf->indiv_seed, sconf->indiv_seed_size); -#endif - - list_add_back(ctxt->self.ohs, oh); - } - break; - } - - return TRUE; -} - -static void _fill_sce_version(sce_buffer_ctxt_t *ctxt) -{ - ctxt->self.sv->header_type = SUB_HEADER_TYPE_SCEVERSION; - ctxt->self.sv->present = SCE_VERSION_NOT_PRESENT; - ctxt->self.sv->size = sizeof(sce_version_t); - ctxt->self.sv->unknown_3 = 0x00000000; -} - -static void _add_phdr_section(sce_buffer_ctxt_t *ctxt, u32 p_type, u32 size, u32 idx) -{ - //Offset gets set later. - ctxt->self.si[idx].offset = 0; - ctxt->self.si[idx].size = size; - - if(p_type == PT_LOAD || p_type == PT_PS3_PRX_RELOC || p_type == 0x700000A8) - ctxt->self.si[idx].encrypted = 1; //Encrypted LOAD (?). - else - ctxt->self.si[idx].encrypted = 0; //No LOAD (?). - - ctxt->self.si[idx].compressed = SECTION_INFO_NOT_COMPRESSED; - ctxt->self.si[idx].unknown_0 = 0; //Unknown. - ctxt->self.si[idx].unknown_1 = 0; //Unknown. -} - -static BOOL _add_shdrs_section(sce_buffer_ctxt_t *ctxt, u32 idx) -{ - //Add a section for the section headers. - if(ctxt->makeself->shdrs != NULL) - { - u32 shsize = ctxt->makeself->shsize; - void *sec = _memdup(ctxt->makeself->shdrs, shsize); - sce_add_data_section(ctxt, sec, shsize, FALSE); - - //Fill metadata section header. - sce_set_metash(ctxt, METADATA_SECTION_TYPE_SHDR, FALSE, idx); - - return TRUE; - } - - return FALSE; -} - -static BOOL _build_self_32(sce_buffer_ctxt_t *ctxt, self_config_t *sconf) -{ - u32 i; - - Elf32_Ehdr *ehdr; - Elf32_Phdr *phdrs; - //Elf32_Shdr *shdrs; - - //Copy ELF header. - ctxt->makeself->ehdr = (Elf32_Ehdr *)_memdup(ctxt->makeself->elf, sizeof(Elf32_Ehdr)); - ctxt->makeself->ehsize = sizeof(Elf32_Ehdr); - ehdr = (Elf32_Ehdr *)_memdup(ctxt->makeself->elf, sizeof(Elf32_Ehdr)); - _es_elf32_ehdr(ehdr); - - //Copy program headers. - ctxt->makeself->phdrs = (Elf32_Phdr *)_memdup(ctxt->makeself->elf + ehdr->e_phoff, sizeof(Elf32_Phdr) * ehdr->e_phnum); - ctxt->makeself->phsize = sizeof(Elf32_Phdr) * ehdr->e_phnum; - phdrs = (Elf32_Phdr *)_memdup(ctxt->makeself->elf + ehdr->e_phoff, sizeof(Elf32_Phdr) * ehdr->e_phnum); - - //Copy section headers. - if(ehdr->e_shnum != 0) - { - ctxt->makeself->shdrs = (Elf32_Shdr *)_memdup(ctxt->makeself->elf + ehdr->e_shoff, sizeof(Elf32_Shdr) * ehdr->e_shnum); - ctxt->makeself->shsize = sizeof(Elf32_Shdr) * ehdr->e_shnum; - //shdrs = (Elf32_Shdr *)_memdup(ctxt->makeself->elf + ehdr->e_shoff, sizeof(Elf32_Shdr) * ehdr->e_shnum); - } - - //Allocate metadata section headers (one for each program header and one for the section headers). - ctxt->metash = (metadata_section_header_t *)malloc(sizeof(metadata_section_header_t) * (ehdr->e_phnum + 1)); - - //Copy sections, fill section infos and metadata section headers. - ctxt->self.si = (section_info_t *)malloc(sizeof(section_info_t) * ehdr->e_phnum); - for(i = 0; i < ehdr->e_phnum; i++) - { - _es_elf32_phdr(&phdrs[i]); - void *sec = _memdup(ctxt->makeself->elf + phdrs[i].p_offset, phdrs[i].p_filesz); - //Never compress sections on SPU SELFs. - sce_add_data_section(ctxt, sec, phdrs[i].p_filesz, FALSE); - - //Add section info. - _add_phdr_section(ctxt, phdrs[i].p_type, phdrs[i].p_filesz, i); - //Fill metadata section header. - sce_set_metash(ctxt, METADATA_SECTION_TYPE_PHDR, phdrs[i].p_type == PT_LOAD ? TRUE : FALSE, i); - } - - //Section info count. - ctxt->makeself->si_cnt = ehdr->e_phnum; - //Number of section infos that are present as data sections. - ctxt->makeself->si_sec_cnt = ehdr->e_phnum; - - //Add a section for the section headers. - if(sconf->add_shdrs == TRUE) - if(_add_shdrs_section(ctxt, i) == TRUE) - i++; - - //Metadata. - ctxt->metah->section_count = i; - - return TRUE; -} - -static BOOL _build_self_64(sce_buffer_ctxt_t *ctxt, self_config_t *sconf) -{ - u32 i; - - Elf64_Ehdr *ehdr; - Elf64_Phdr *phdrs; - //Elf64_Shdr *shdrs; - - //Copy ELF header. - ctxt->makeself->ehdr = (Elf64_Ehdr *)_memdup(ctxt->makeself->elf, sizeof(Elf64_Ehdr)); - ctxt->makeself->ehsize = sizeof(Elf64_Ehdr); - ehdr = (Elf64_Ehdr *)_memdup(ctxt->makeself->elf, sizeof(Elf64_Ehdr)); - _es_elf64_ehdr(ehdr); - - //Copy program headers. - ctxt->makeself->phdrs = (Elf64_Phdr *)_memdup(ctxt->makeself->elf + ehdr->e_phoff, sizeof(Elf64_Phdr) * ehdr->e_phnum); - ctxt->makeself->phsize = sizeof(Elf64_Phdr) * ehdr->e_phnum; - phdrs = (Elf64_Phdr *)_memdup(ctxt->makeself->elf + ehdr->e_phoff, sizeof(Elf64_Phdr) * ehdr->e_phnum); - - //Copy section headers. - if(ehdr->e_shnum != 0) - { - ctxt->makeself->shdrs = (Elf64_Shdr *)_memdup(ctxt->makeself->elf + ehdr->e_shoff, sizeof(Elf64_Shdr) * ehdr->e_shnum); - ctxt->makeself->shsize = sizeof(Elf64_Shdr) * ehdr->e_shnum; - //shdrs = (Elf64_Shdr *)_memdup(ctxt->makeself->elf + ehdr->e_shoff, sizeof(Elf64_Shdr) * ehdr->e_shnum); - } - - //Allocate metadata section headers (one for each program header and one for the section headers). - ctxt->metash = (metadata_section_header_t *)malloc(sizeof(metadata_section_header_t) * (ehdr->e_phnum + 1)); - - //Copy sections, fill section infos and metadata section headers. - ctxt->self.si = (section_info_t *)malloc(sizeof(section_info_t) * ehdr->e_phnum); - u32 loff = 0xFFFFFFFF, skip = 0; - for(i = 0; i < ehdr->e_phnum; i++) - { - _es_elf64_phdr(&phdrs[i]); - - //Add section info. - _add_phdr_section(ctxt, phdrs[i].p_type, phdrs[i].p_filesz, i); - - //TODO: what if the size differs, why skip other program headers? - //Fill metadata section header but skip identical program header offsets. - if(sconf->skip_sections == TRUE && (phdrs[i].p_offset == loff || !(phdrs[i].p_type == PT_LOAD || phdrs[i].p_type == PT_PS3_PRX_RELOC || phdrs[i].p_type == 0x700000A8))) - { - const s8 *name = _get_name(_ph_types, phdrs[i].p_type); - if(name != NULL) - _LOG_VERBOSE("Skipped program header %-8s @ 0x%08X (0x%08X)\n", name, phdrs[i].p_offset, phdrs[i].p_filesz); - else - _LOG_VERBOSE("Skipped program header 0x%08X @ 0x%08X (0x%08X)\n", phdrs[i].p_type, phdrs[i].p_offset, phdrs[i].p_filesz); - skip++; - } - else - { - void *sec = _memdup(ctxt->makeself->elf + phdrs[i].p_offset, phdrs[i].p_filesz); - //PPU sections may be compressed. - sce_add_data_section(ctxt, sec, phdrs[i].p_filesz, TRUE); - sce_set_metash(ctxt, METADATA_SECTION_TYPE_PHDR, TRUE /*(phdrs[i].p_type == PT_LOAD || phdrs[i].p_type == PT_PS3_PRX_RELOC || phdrs[i].p_type == 0x700000A8) ? TRUE : FALSE*/, i - skip); - } - - loff = phdrs[i].p_offset; - } - - //Section info count. - ctxt->makeself->si_cnt = ehdr->e_phnum; - //Number of section infos that are present as data sections. - ctxt->makeself->si_sec_cnt = i - skip; - - //Add a section for the section headers. - if(sconf->add_shdrs == TRUE) - if(_add_shdrs_section(ctxt, i - skip) == TRUE) - i++; - - //Metadata. - i -= skip; - ctxt->metah->section_count = i; - - return TRUE; -} - -BOOL self_build_self(sce_buffer_ctxt_t *ctxt, self_config_t *sconf) -{ - //const u8 *eident; - - //Fill config values. - ctxt->sceh->key_revision = sconf->key_revision; - ctxt->self.ai->auth_id = sconf->auth_id; - ctxt->self.ai->vendor_id = sconf->vendor_id; - ctxt->self.ai->self_type = sconf->self_type; - ctxt->self.ai->version = sconf->app_version; - - //Create control infos. - if(_create_control_infos(ctxt, sconf) == FALSE) - { - printf("[*] Error: Could not create SELF control infos.\n"); - return FALSE; - } - -#ifdef CONFIG_CUSTOM_INDIV_SEED - if(sconf->indiv_seed != NULL && sconf->self_type != SELF_TYPE_ISO) - printf("[*] Warning: Skipping individuals seed for non-ISO SELF.\n"); -#endif - - //Create optional headers. - if(_create_optional_headers(ctxt, sconf) == FALSE) - { - printf("[*] Error: Could not create SELF optional headers.\n"); - return FALSE; - } - - //Set SCE version. - _fill_sce_version(ctxt); - - //Check for 32 bit or 64 bit ELF. - //eident = (const u8*)ctxt->makeself->elf; - if(sconf->self_type == SELF_TYPE_LDR || sconf->self_type == SELF_TYPE_ISO /*|| eident[EI_CLASS] == ELFCLASS32*/) - return _build_self_32(ctxt, sconf); - return _build_self_64(ctxt, sconf); -} diff --git a/Makefile b/src/Makefile similarity index 99% rename from Makefile rename to src/Makefile index d9734a1..b2a1b0e 100644 --- a/Makefile +++ b/src/Makefile @@ -1,4 +1,4 @@ -CC=gcc +CC=g++ CFLAGS=-g -O0 -Wall OS_TARGET=scetool LDFLAGS=-lz diff --git a/README b/src/README similarity index 72% rename from README rename to src/README index e082320..abfaded 100644 --- a/README +++ b/src/README @@ -9,13 +9,14 @@ NP local license handling (C) 2012 by flatz - /data/act.dat : act.dat - /rifs/* : *.rif files - /raps/* : *.rap files + - /klics/* : *.klic files ==> Keyfile Format <== [keyname] - type={SELF, RVK, PKG, SPP, OTHER} + category={SELF, RVK, PKG, SPP, OTHER} revision={00, ..., 18, 8000} version={..., 0001000000000000, ...} - self_type={LV0, LV1, LV2, APP, ISO, LDR, UNK_7, NPDRM} + program_type={LV0, LV1, LV2, APP, ISO, LDR, UNK_7, NPDRM} key=... erk=... riv=... @@ -25,9 +26,9 @@ NP local license handling (C) 2012 by flatz ==> Keyset Example <== [metldr] - type=SELF + category=SELF revision=00 - self_type=LDR + program_type=LDR erk=0000000000000000000000000000000000000000000000000000000000000000 riv=00000000000000000000000000000000 pub=00000000000000000000000000000000000000000000000000000000000000000000000000000000 @@ -43,6 +44,12 @@ NP local license handling (C) 2012 by flatz - [NP_rif_key]: rif key. - [NP_sig]: Footer signature ECDSA keyset. +==> NPDRM ReActPsn Key(set) Names <== + - [NP_rap_initial]: RAP initial aes decryption key. + - [NP_rap_pbox]: RAP permutation box constant. + - [NP_rap_e1] RAP e1 constant. + - [NP_rap_e2] RAP e2 constant. + ==> Override Keyset <== It should be a single hex-string consisting of: 32 bytes (Key) 16 bytes (IV) 40 bytes (Pub) 21 bytes (Priv) 1 byte (CType). @@ -59,7 +66,7 @@ OPTIONS Possible Values Explanation -v, --verbose Enable verbose output. -r, --raw Enable raw value output. -t, --template File-in Template file (SELF only) - -0, --sce-type SELF/RVK/PKG/SPP SCE File Type + -0, --category SELF/RVK/PKG/SPP SCE File Type -1, --compress-data TRUE/FALSE(default) Whether to compress data or not. -s, --skip-sections TRUE(default)/FALSE Whether to skip sections or not. -2, --key-revision e.g. 00,01,...,0A,... Key Revision @@ -67,10 +74,10 @@ OPTIONS Possible Values Explanation -K, --keyset 32(Key)16(IV) 40(Pub)21(Priv)1(CT) Override keyset. - -3, --self-auth-id e.g. 1010000001000003 Authentication ID - -4, --self-vendor-id e.g. 01000002 Vendor ID - -5, --self-type LV0/LV1/LV2/APP/ISO/ - LDR/NPDRM SELF Type + -3, --program-auth-id e.g. 1010000001000003 Authentication ID + -4, --program-vendor-id e.g. 01000002 Vendor ID + -5, --program-type LV0/LV1/LV2/APP/ISO/ + LDR/NPDRM Program Type -A, --self-app-version e.g. 0001000000000000 Application Version -6, --self-fw-version e.g. 0003004100000000 Firmware Version -7, --self-add-shdrs TRUE(default)/FALSE Whether to add ELF shdrs or not. @@ -84,6 +91,34 @@ OPTIONS Possible Values Explanation -j, --np-add-sig TRUE/FALSE(default) Whether to add a NP sig. or not. ==> History <== + +Version 0.3.1 +- Updated Program Authority IDs. +- Fixed Vsh Curve loader. +Version 0.3.0 +- Added Internal keys support. +- Added Signed Elf ver.2 decryption support. +- Decrypting header will now use key-bruteforce method. +- Options changed. +- Removed Pub/Priv configs, enabled all features by default. +Version 0.2.14 +- Added PS3 Linux support. +- Fixed ECDSA checking. +Version 0.2.13 +- Unlocked decryption for self files with network license type. +- Fixed one minor bug with capability flags. +Version 0.2.12 + - Enabled options to compress and skip sections for SPU selfs. + - Extended information about the NPDRM selfs. +Version 0.2.11 + - Added .klic files support for easy decryption of the free-license-type NPDRM selfs. + - "PS3" path environment variable will now be searched for "data", "raps" and "klics" directories. + - Enabled encryption for APP and NPDRM SPU selfs. +Version 0.2.10 + - Added ECDSA Signature parsing and validation. + - Added klicensee parsing. + - Fixed metadata info IV parsing. + - Enabled Individuals seed functions for configuration. Version 0.2.9 - Plaintext sections will now take less space in metadata header keys array. - Added option to specifiy a template SELF to take configuration values from. diff --git a/aes.c b/src/aes.cpp similarity index 100% rename from aes.c rename to src/aes.cpp diff --git a/aes.h b/src/aes.h similarity index 100% rename from aes.h rename to src/aes.h diff --git a/aes_omac.cpp b/src/aes_omac.cpp similarity index 100% rename from aes_omac.cpp rename to src/aes_omac.cpp diff --git a/aes_omac.h b/src/aes_omac.h similarity index 100% rename from aes_omac.h rename to src/aes_omac.h diff --git a/bn.cpp b/src/bn.cpp similarity index 100% rename from bn.cpp rename to src/bn.cpp diff --git a/config.h b/src/config.h similarity index 64% rename from config.h rename to src/config.h index d2469af..c80760b 100644 --- a/config.h +++ b/src/config.h @@ -6,30 +6,8 @@ #ifndef _CONFIG_H_ #define _CONFIG_H_ -/*! scetool base version. */ -#define SCETOOL_VERSION_BASE "0.2.9" - -/*! Private build. */ -//#define CONFIG_PRIVATE_BUILD -#define BUILD_FOR "naehrwert" -//#define BUILD_FOR "unicorns" - /*! scetool version. */ -#ifdef CONFIG_PRIVATE_BUILD - #ifdef BUILD_FOR - #define SCETOOL_VERSION SCETOOL_VERSION_BASE " " - #else - #error Specify a name in BUILD_FOR. - #endif -#else - #define SCETOOL_VERSION SCETOOL_VERSION_BASE " " -#endif - -/*! Private build options. */ -#ifdef CONFIG_PRIVATE_BUILD - #define CONFIG_CUSTOM_INDIV_SEED - #define CONFIG_DUMP_INDIV_SEED -#endif +#define SCETOOL_VERSION "0.3.1" #if 0 /*! scetool API. */ @@ -41,15 +19,12 @@ #endif #endif -/*! NPDRM watermark text (16 bytes exactly). */ -//"I like kittens !" -#define CONFIG_NPDRM_WATERMARK "watermarktrololo" - /*! Environment variables. */ #define CONFIG_ENV_PS3 "PS3" /*! Path configurations. */ #define CONFIG_KEYS_FILE "keys" +#define CONFIG_INTERNAL_KEYS_FILE "internal_keys" #define CONFIG_KEYS_PATH "./data" #define CONFIG_CURVES_FILE "ldr_curves" #define CONFIG_CURVES_PATH "./data" @@ -63,6 +38,8 @@ #define CONFIG_RIF_PATH "./rifs" #define CONFIG_RAP_FILE_EXT ".rap" #define CONFIG_RAP_PATH "./raps" +#define CONFIG_KLIC_FILE_EXT ".klic" +#define CONFIG_KLIC_PATH "./klics" /*! Key names. */ #define CONFIG_NP_TID_KNAME "NP_tid" @@ -72,5 +49,9 @@ #define CONFIG_NP_IDPS_CONST_KNAME "NP_idps_const" #define CONFIG_NP_RIF_KEY_KNAME "NP_rif_key" #define CONFIG_NP_SIG_KNAME "NP_sig" +#define CONFIG_NP_RAP_INITIAL_KNAME "NP_rap_initial" +#define CONFIG_NP_RAP_PBOX_KNAME "NP_rap_pbox" +#define CONFIG_NP_RAP_E1_KNAME "NP_rap_e1" +#define CONFIG_NP_RAP_E2_KNAME "NP_rap_e2" #endif diff --git a/ec.cpp b/src/ec.cpp similarity index 87% rename from ec.cpp rename to src/ec.cpp index 85edf68..70d5def 100644 --- a/ec.cpp +++ b/src/ec.cpp @@ -73,7 +73,7 @@ static void elt_square(u8 *d, u8 *a) elt_mul(d, a, a); } -static void elt_inv(u8 *d, u8 *a) +void elt_inv(u8 *d, u8 *a) { u8 s[20]; elt_copy(s, a); @@ -314,12 +314,16 @@ static int check_ecdsa(struct point *Q, u8 *R, u8 *S, u8 *hash) return (bn_compare(rr, R, 21) == 0); } -#if 0 -static void ec_priv_to_pub(u8 *k, u8 *Q) + +void ec_priv_to_pub(u8 *k, u8 *Q) { - point_mul(Q, k, ec_G); + struct point mQ; + point_mul(&mQ, k, &ec_G); + point_from_mon(&mQ); + elt_copy(Q, mQ.x); + elt_copy(Q+20, mQ.y); } -#endif + int ecdsa_set_curve(u32 type) { @@ -355,3 +359,30 @@ void ecdsa_sign(u8 *hash, u8 *R, u8 *S) { generate_ecdsa(R, S, ec_k, hash); } + +void get_m (u8 *r, u8 *s, u8 *e, u8 *k, u8 *m) +{ +u8 tmp_r[21], tmp_s[21], tmp_e[21], tmp_k[21]; +u8 tmp_mul[21], tmp_sum[21], tmp_inv[21]; + +tmp_r[0] = tmp_s[0] = tmp_e[0] = 0; +bn_copy(tmp_r, r, 21); +bn_copy(tmp_s, s, 21); +bn_copy(tmp_e + 1, e, 20); +bn_reduce(tmp_e, ec_N, 21); +bn_to_mon(tmp_r, ec_N, 21); +bn_to_mon(tmp_s, ec_N, 21); +bn_to_mon(tmp_e, ec_N, 21); + +tmp_k[0] = 0; +bn_copy(tmp_k, k, 21); +bn_reduce(tmp_k, ec_N, 21); +bn_to_mon(tmp_k, ec_N, 21); + +bn_mon_mul(tmp_mul, tmp_r, tmp_k, ec_N, 21); +bn_add(tmp_sum, tmp_mul, tmp_e, ec_N, 21); +bn_mon_inv(tmp_inv, tmp_s, ec_N, 21); +bn_mon_mul(tmp_mul, tmp_inv, tmp_sum, ec_N, 21); +bn_from_mon(tmp_mul, ec_N, 21); +memcpy (m, tmp_mul + 1, 20); +} diff --git a/ecdsa.cpp b/src/ecdsa.cpp similarity index 100% rename from ecdsa.cpp rename to src/ecdsa.cpp diff --git a/ecdsa.h b/src/ecdsa.h similarity index 53% rename from ecdsa.h rename to src/ecdsa.h index 2653c3f..f6d7275 100644 --- a/ecdsa.h +++ b/src/ecdsa.h @@ -6,5 +6,8 @@ void ecdsa_set_pub(u8 *Q); void ecdsa_set_priv(u8 *k); int ecdsa_verify(u8 *hash, u8 *R, u8 *S); void ecdsa_sign(u8 *hash, u8 *R, u8 *S); - +void ec_priv_to_pub(u8 *k, u8 *Q); +void elt_inv(u8 *d, u8 *a); +void get_m (u8 *r, u8 *s, u8 *e, u8 *k, u8 *m); +int ecdsa_get_params(u32 type, u8 *p, u8 *a, u8 *b, u8 *N, u8 *Gx, u8 *Gy); #endif diff --git a/elf.h b/src/elf.h similarity index 99% rename from elf.h rename to src/elf.h index ddc5860..db934cd 100644 --- a/elf.h +++ b/src/elf.h @@ -248,11 +248,11 @@ typedef struct Elf32_Word sh_type; /* Section type */ Elf32_Word sh_flags; /* Section flags */ Elf32_Addr sh_addr; /* Section virtual addr at execution */ - Elf32_Off sh_offset; /* Section file offset */ + Elf32_Off sh_offset; /* Section file offset */ Elf32_Word sh_size; /* Section size in bytes */ Elf32_Word sh_link; /* Link to another section */ Elf32_Word sh_info; /* Additional section information */ - Elf32_Word sh_addralign; /* Section alignment */ + Elf32_Word sh_addralign; /* Section alignment */ Elf32_Word sh_entsize; /* Entry size if section holds table */ } Elf32_Shdr; @@ -262,11 +262,11 @@ typedef struct Elf64_Word sh_type; /* Section type */ Elf64_Xword sh_flags; /* Section flags */ Elf64_Addr sh_addr; /* Section virtual addr at execution */ - Elf64_Off sh_offset; /* Section file offset */ + Elf64_Off sh_offset; /* Section file offset */ Elf64_Xword sh_size; /* Section size in bytes */ Elf64_Word sh_link; /* Link to another section */ Elf64_Word sh_info; /* Additional section information */ - Elf64_Xword sh_addralign; /* Section alignment */ + Elf64_Xword sh_addralign; /* Section alignment */ Elf64_Xword sh_entsize; /* Entry size if section holds table */ } Elf64_Shdr; @@ -502,7 +502,7 @@ typedef struct typedef struct { Elf32_Word p_type; /* Segment type */ - Elf32_Off p_offset; /* Segment file offset */ + Elf32_Off p_offset; /* Segment file offset */ Elf32_Addr p_vaddr; /* Segment virtual address */ Elf32_Addr p_paddr; /* Segment physical address */ Elf32_Word p_filesz; /* Segment size in file */ @@ -515,7 +515,7 @@ typedef struct { Elf64_Word p_type; /* Segment type */ Elf64_Word p_flags; /* Segment flags */ - Elf64_Off p_offset; /* Segment file offset */ + Elf64_Off p_offset; /* Segment file offset */ Elf64_Addr p_vaddr; /* Segment virtual address */ Elf64_Addr p_paddr; /* Segment physical address */ Elf64_Xword p_filesz; /* Segment size in file */ @@ -925,7 +925,7 @@ typedef struct interpretation of the AUXV. Must be > 16. */ #define AT_IGNOREPPC 22 /* Entry should be ignored. */ -#define AT_SECURE 23 /* Boolean, was exec setuid-like? */ +#define AT_SECURE 23 /* boolean, was exec setuid-like? */ /* Pointer to the global system page used for system calls and other nice things. */ @@ -1463,7 +1463,7 @@ typedef struct #define PT_MIPS_RTPROC 0x70000001 /* Runtime procedure table. */ #define PT_MIPS_OPTIONS 0x70000002 -/* Special program header types. */ +/* Special elf program header types. */ #define PF_MIPS_LOCAL 0x10000000 diff --git a/elf_inlines.h b/src/elf_inlines.h similarity index 100% rename from elf_inlines.h rename to src/elf_inlines.h diff --git a/frontend.cpp b/src/frontend.cpp similarity index 80% rename from frontend.cpp rename to src/frontend.cpp index b06949e..b721d6a 100644 --- a/frontend.cpp +++ b/src/frontend.cpp @@ -2,6 +2,7 @@ * Copyright (c) 2011-2013 by naehrwert * This file is released under the GPLv2. */ +#define _CRT_SECURE_NO_WARNINGS #include #include @@ -30,29 +31,27 @@ extern s8 *_meta_info; extern s8 *_keyset; extern s8 *_auth_id; extern s8 *_vendor_id; -extern s8 *_self_type; +extern s8 *_program_type; extern s8 *_app_version; extern s8 *_fw_version; extern s8 *_add_shdrs; extern s8 *_ctrl_flags; extern s8 *_cap_flags; -#ifdef CONFIG_CUSTOM_INDIV_SEED extern s8 *_indiv_seed; -#endif extern s8 *_license_type; extern s8 *_app_type; extern s8 *_content_id; extern s8 *_real_fname; extern s8 *_add_sig; -static BOOL _is_hexdigit(s8 c) +static bool _is_hexdigit(s8 c) { if((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) return TRUE; return FALSE; } -static BOOL _is_hexnumber(const s8 *str) +static bool _is_hexnumber(const s8 *str) { u32 i, len = strlen(str); for(i = 0; i < len; i++) @@ -61,7 +60,7 @@ static BOOL _is_hexnumber(const s8 *str) return TRUE; } -static BOOL _fill_self_config_template(s8 *file, self_config_t *sconf) +static bool _fill_self_config_template(s8 *file, self_config_t *sconf) { u8 *buf = _read_buffer(file, NULL); if(buf != NULL) @@ -74,16 +73,16 @@ static BOOL _fill_self_config_template(s8 *file, self_config_t *sconf) _LOG_VERBOSE("Template header decrypted.\n"); _LOG_VERBOSE("Using:\n"); - sconf->key_revision = ctxt->sceh->key_revision; + sconf->key_revision = _ES16(ctxt->cfh->key_revision); _IF_VERBOSE(printf(" Key Revision 0x%04X\n", sconf->key_revision)); - sconf->auth_id = ctxt->self.ai->auth_id; + sconf->auth_id = _ES64(ctxt->self.ai->auth_id); _IF_VERBOSE(printf(" Auth-ID 0x%016llX\n", sconf->auth_id)); - sconf->vendor_id = ctxt->self.ai->vendor_id; + sconf->vendor_id = _ES32(ctxt->self.ai->vendor_id); _IF_VERBOSE(printf(" Vendor-ID 0x%08X\n", sconf->vendor_id)); - sconf->self_type = ctxt->self.ai->self_type; - _IF_VERBOSE(printf(" SELF-Type 0x%08X\n", sconf->self_type)); - sconf->app_version = ctxt->self.ai->version; - _IF_VERBOSE(printf(" APP Version 0x%016llX\n", sconf->app_version)); + sconf->program_type = _ES32(ctxt->self.ai->program_type); + _IF_VERBOSE(printf(" Program-Type 0x%08X\n", sconf->program_type)); + sconf->app_version = _ES64(ctxt->self.ai->version); + _IF_VERBOSE(printf(" APP-Version 0x%016llX\n", sconf->app_version)); control_info_t *ci = sce_get_ctrl_info(ctxt, CONTROL_INFO_TYPE_DIGEST); ci_data_digest_40_t *cid = (ci_data_digest_40_t *)((u8 *)ci + sizeof(control_info_t)); @@ -100,16 +99,14 @@ static BOOL _fill_self_config_template(s8 *file, self_config_t *sconf) sconf->cap_flags = (u8 *)_memdup(((u8 *)oh) + sizeof(opt_header_t), 0x20); _IF_VERBOSE(_hexdump(stdout, " Capability Flags", 0, sconf->cap_flags, 0x20, 0)); -#ifdef CONFIG_CUSTOM_INDIV_SEED sconf->indiv_seed = NULL; - if(ctxt->self.ai->self_type == SELF_TYPE_ISO) + if(_ES32(ctxt->self.ai->program_type) == PROGRAM_TYPE_ISO) { oh = sce_get_opt_header(ctxt, OPT_HEADER_TYPE_INDIV_SEED); - sconf->indiv_seed = (u8 *)_memdup(((u8 *)oh) + sizeof(opt_header_t), oh->size - sizeof(opt_header_t)); - sconf->indiv_seed_size = oh->size - sizeof(opt_header_t); + sconf->indiv_seed = (u8 *)_memdup(((u8 *)oh) + sizeof(opt_header_t), _ES32(oh->size) - sizeof(opt_header_t)); + sconf->indiv_seed_size = _ES32(oh->size) - sizeof(opt_header_t); _IF_VERBOSE(_hexdump(stdout, " Individuals Seed", 0, sconf->indiv_seed, sconf->indiv_seed_size, 0)); } -#endif sconf->add_shdrs = TRUE; if(_add_shdrs != NULL) @@ -139,7 +136,7 @@ static BOOL _fill_self_config_template(s8 *file, self_config_t *sconf) return FALSE; } -static BOOL _fill_self_config(self_config_t *sconf) +static bool _fill_self_config(self_config_t *sconf) { if(_key_rev == NULL) { @@ -151,7 +148,7 @@ static BOOL _fill_self_config(self_config_t *sconf) printf("[*] Error (Key Revision): Please provide a valid hexadecimal number.\n"); return FALSE; } - sconf->key_revision = _x_to_u64(_key_rev); + sconf->key_revision = (u16)_x_to_u64(_key_rev); if(_auth_id == NULL) { @@ -165,20 +162,20 @@ static BOOL _fill_self_config(self_config_t *sconf) printf("[*] Error: Please specify a vendor ID.\n"); return FALSE; } - sconf->vendor_id = _x_to_u64(_vendor_id); + sconf->vendor_id = (u32)_x_to_u64(_vendor_id); - if(_self_type == NULL) + if(_program_type == NULL) { - printf("[*] Error: Please specify a SELF type.\n"); + printf("[*] Error: Please specify a program type.\n"); return FALSE; } - u64 type = _get_id(_self_types_params, _self_type); + u64 type = _get_id(_program_types_params, _program_type); if(type == (u64)(-1)) { - printf("[*] Error: Invalid SELF type.\n"); + printf("[*] Error: Invalid program type.\n"); return FALSE; } - sconf->self_type = type; + sconf->program_type = (u32)type; if(_app_version == NULL) { @@ -223,7 +220,6 @@ static BOOL _fill_self_config(self_config_t *sconf) sconf->cap_flags = _x_to_u8_buffer(_cap_flags); } -#ifdef CONFIG_CUSTOM_INDIV_SEED sconf->indiv_seed = NULL; if(_indiv_seed != NULL) { @@ -236,14 +232,13 @@ static BOOL _fill_self_config(self_config_t *sconf) sconf->indiv_seed = _x_to_u8_buffer(_indiv_seed); sconf->indiv_seed_size = len / 2; } -#endif sconf->npdrm_config = NULL; return TRUE; } -static BOOL _fill_npdrm_config(self_config_t *sconf) +static bool _fill_npdrm_config(self_config_t *sconf) { if((sconf->npdrm_config = (npdrm_config_t *)malloc(sizeof(npdrm_config_t))) == NULL) return FALSE; @@ -275,7 +270,7 @@ static BOOL _fill_npdrm_config(self_config_t *sconf) printf("[*] Error: Invalid application type.\n"); return FALSE; } - sconf->npdrm_config->app_type = type; + sconf->npdrm_config->app_type = (u32)type; if(_content_id == NULL) { @@ -334,13 +329,22 @@ void frontend_print_infos(s8 *file) } else printf("[*] Warning: Could not decrypt header.\n"); - sce_print_info(stdout, ctxt); - if(ctxt->sceh->header_type == SCE_HEADER_TYPE_SELF) + + cf_print_info(stdout, ctxt); + //sce_print_info(stdout, ctxt, keyset); + if(_ES16(ctxt->cfh->category) == CF_CATEGORY_SELF) self_print_info(stdout, ctxt); - else if(ctxt->sceh->header_type == SCE_HEADER_TYPE_RVK && ctxt->mdec == TRUE) + else if(_ES16(ctxt->cfh->category) == CF_CATEGORY_RVK && ctxt->mdec == TRUE) rvk_print(stdout, ctxt); - else if(ctxt->sceh->header_type == SCE_HEADER_TYPE_SPP && ctxt->mdec == TRUE) + else if(_ES16(ctxt->cfh->category) == CF_CATEGORY_SPP && ctxt->mdec == TRUE) spp_print(stdout, ctxt); + + sce_print_info(stdout, ctxt, keyset); + if(_ES16(ctxt->cfh->category) == CF_CATEGORY_SELF) + self_print_encrypted_info(stdout, ctxt); + if(ctxt->mdec == TRUE) + print_sce_signature_info(stdout, ctxt, keyset); + free(ctxt); } else @@ -387,34 +391,34 @@ void frontend_decrypt(s8 *file_in, s8 *file_out) if(sce_decrypt_data(ctxt)) { _LOG_VERBOSE("Data decrypted.\n"); - if(ctxt->sceh->header_type == SCE_HEADER_TYPE_SELF) + if(_ES16(ctxt->cfh->category) == CF_CATEGORY_SELF) { if(self_write_to_elf(ctxt, file_out) == TRUE) printf("[*] ELF written to %s.\n", file_out); else printf("[*] Error: Could not write ELF.\n"); } - else if(ctxt->sceh->header_type == SCE_HEADER_TYPE_RVK) + else if(_ES16(ctxt->cfh->category) == CF_CATEGORY_RVK) { - if(_write_buffer(file_out, ctxt->scebuffer + ctxt->metash[0].data_offset, - ctxt->metash[0].data_size + ctxt->metash[1].data_size)) + if(_write_buffer(file_out, ctxt->scebuffer + _ES64(ctxt->metash[0].data_offset), + _ES64(ctxt->metash[0].data_size) + _ES64(ctxt->metash[1].data_size))) printf("[*] RVK written to %s.\n", file_out); else printf("[*] Error: Could not write RVK.\n"); } - else if(ctxt->sceh->header_type == SCE_HEADER_TYPE_PKG) + else if(_ES16(ctxt->cfh->category) == CF_CATEGORY_PKG) { - /*if(_write_buffer(file_out, ctxt->scebuffer + ctxt->metash[0].data_offset, - ctxt->metash[0].data_size + ctxt->metash[1].data_size + ctxt->metash[2].data_size)) + /*if(_write_buffer(file_out, ctxt->scebuffer + _ES64(ctxt->metash[0].data_offset), + _ES64(ctxt->metash[0].data_size) + _ES64(ctxt->metash[1].data_size) + _ES64(ctxt->metash[2].data_size))) printf("[*] PKG written to %s.\n", file_out); else printf("[*] Error: Could not write PKG.\n");*/ printf("soon...\n"); } - else if(ctxt->sceh->header_type == SCE_HEADER_TYPE_SPP) + else if(_ES16(ctxt->cfh->category) == CF_CATEGORY_SPP) { - if(_write_buffer(file_out, ctxt->scebuffer + ctxt->metash[0].data_offset, - ctxt->metash[0].data_size + ctxt->metash[1].data_size)) + if(_write_buffer(file_out, ctxt->scebuffer + _ES64(ctxt->metash[0].data_offset), + _ES64(ctxt->metash[0].data_size) + _ES64(ctxt->metash[1].data_size))) printf("[*] SPP written to %s.\n", file_out); else printf("[*] Error: Could not write SPP.\n"); @@ -437,7 +441,7 @@ void frontend_decrypt(s8 *file_in, s8 *file_out) void frontend_encrypt(s8 *file_in, s8 *file_out) { - BOOL can_compress = FALSE; + bool can_compress = FALSE; self_config_t sconf; sce_buffer_ctxt_t *ctxt; u32 file_len = 0; @@ -468,7 +472,7 @@ void frontend_encrypt(s8 *file_in, s8 *file_out) if(strcmp(_file_type, "SELF") == 0) { - if(_self_type == NULL && _template == NULL) + if(_program_type == NULL && _template == NULL) { printf("[*] Error: Please specify a SELF type.\n"); return; @@ -487,7 +491,7 @@ void frontend_encrypt(s8 *file_in, s8 *file_out) return; } - if(sconf.self_type == SELF_TYPE_NPDRM) + if(sconf.program_type == PROGRAM_TYPE_NPDRM) if(_fill_npdrm_config(&sconf) == FALSE) return; @@ -501,7 +505,7 @@ void frontend_encrypt(s8 *file_in, s8 *file_out) } //SPU SELFs may not be compressed. - if(!(sconf.self_type == SELF_TYPE_LDR || sconf.self_type == SELF_TYPE_ISO)) + if(!(sconf.program_type == PROGRAM_TYPE_LDR || sconf.program_type == PROGRAM_TYPE_ISO)) can_compress = TRUE; } else if(strcmp(_file_type, "RVK") == 0) @@ -547,7 +551,7 @@ void frontend_encrypt(s8 *file_in, s8 *file_out) { printf("[*] %s written.\n", file_out); //Add NPDRM footer signature. - if(sconf.self_type == SELF_TYPE_NPDRM && _add_sig != NULL && strcmp(_add_sig, "TRUE") == 0) + if(sconf.program_type == PROGRAM_TYPE_NPDRM && _add_sig != NULL && strcmp(_add_sig, "TRUE") == 0) { if(np_sign_file(file_out) == TRUE) printf("[*] Added NPDRM footer signature.\n"); diff --git a/frontend.h b/src/frontend.h similarity index 100% rename from frontend.h rename to src/frontend.h diff --git a/getopt.c b/src/getopt.cpp similarity index 100% rename from getopt.c rename to src/getopt.cpp diff --git a/getopt.h b/src/getopt.h similarity index 97% rename from getopt.h rename to src/getopt.h index 19ca909..bfa7586 100644 --- a/getopt.h +++ b/src/getopt.h @@ -45,7 +45,6 @@ EXPRESSLY ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. #if defined(EXPORTS_GETOPT) && defined(STATIC_GETOPT) #error "The preprocessor definitions of EXPORTS_GETOPT and STATIC_GETOPT can only be used individually" #elif defined(STATIC_GETOPT) -#pragma message("Warning static builds of getopt violate the Lesser GNU Public License") #define _GETOPT_API #elif defined(EXPORTS_GETOPT) #pragma message("Exporting getopt library") diff --git a/src/keys.cpp b/src/keys.cpp new file mode 100644 index 0000000..a40b18b --- /dev/null +++ b/src/keys.cpp @@ -0,0 +1,1090 @@ +/* +* Copyright (c) 2011-2013 by naehrwert +* Copyright (c) 2012 by flatz +* This file is released under the GPLv2. +*/ +#define _CRT_SECURE_NO_WARNINGS + +#include +#include + +#include +#include + +#ifdef _WIN32 +#include +#else +#include +#endif + +#include "config.h" +#include "types.h" +#include "list.h" +#include "sce.h" +#include "keys.h" +#include "util.h" +#include "tables.h" +#include "aes.h" + +/* +[keyname] +category={SELF, RVK, PKG, SPP, OTHER} +revision={00, ..., 18, 8000} +version={..., 0001000000000000, ...} +program_type={LV0, LV1, LV2, APP, ISO, LDR, UNK_7, NPDRM} +key=... +erk=... +riv=... +pub=... +priv=... +ctype=... +*/ + +/*! Loaded keysets. */ +list_t *_keysets; +/*! Loaded internal keysets. */ +list_t *_internal_keysets; +/*! Loaded loader curves. */ +curve_t *_curves; +/*! Loaded VSH curves. */ +vsh_curve_t *_vsh_curves; +/*! Backup keyset. */ +keyset_t *_used_keyset; + +static void _fill_property(keyset_t *ks, s8 *prop, s8 *value) +{ + if(strcmp(prop, "category") == 0) + { + if(strcmp(value, "SELF") == 0) + ks->category = KEYCATEGORY_SELF; + else if(strcmp(value, "RVK") == 0) + ks->category = KEYCATEGORY_RVK; + else if(strcmp(value, "PKG") == 0) + ks->category = KEYCATEGORY_PKG; + else if(strcmp(value, "SPP") == 0) + ks->category = KEYCATEGORY_SPP; + else if(strcmp(value, "OTHER") == 0) + ks->category = KEYCATEGORY_OTHER; + else + printf("[*] Error: Unknown category '%s'.\n", value); + } + else if(strcmp(prop, "revision") == 0) + ks->key_revision = (u16)_x_to_u64(value); + else if(strcmp(prop, "version") == 0) + ks->version = _x_to_u64(value); + else if(strcmp(prop, "program_type") == 0) + { + if(strcmp(value, "LV0") == 0) + ks->program_type = PROGRAM_TYPE_LV0; + else if(strcmp(value, "LV1") == 0) + ks->program_type = PROGRAM_TYPE_LV1; + else if(strcmp(value, "LV2") == 0) + ks->program_type = PROGRAM_TYPE_LV2; + else if(strcmp(value, "APP") == 0) + ks->program_type = PROGRAM_TYPE_APP; + else if(strcmp(value, "ISO") == 0) + ks->program_type = PROGRAM_TYPE_ISO; + else if(strcmp(value, "LDR") == 0) + ks->program_type = PROGRAM_TYPE_LDR; + else if(strcmp(value, "UNK_7") == 0) + ks->program_type = PROGRAM_TYPE_UNK_7; + else if(strcmp(value, "NPDRM") == 0) + ks->program_type = PROGRAM_TYPE_NPDRM; + else + printf("[*] Error: unknown SELF type '%s'.\n", value); + } + else if(strcmp(prop, "erk") == 0 || strcmp(prop, "key") == 0) + { + ks->erk = _x_to_u8_buffer(value); + ks->erklen = strlen(value) / 2; + } + else if(strcmp(prop, "riv") == 0) + { + ks->riv = _x_to_u8_buffer(value); + ks->rivlen = strlen(value) / 2; + } + else if(strcmp(prop, "pub") == 0) + ks->pub = _x_to_u8_buffer(value); + else if(strcmp(prop, "priv") == 0) + ks->priv = _x_to_u8_buffer(value); + else if(strcmp(prop, "ctype") == 0) + ks->ctype = (u8)_x_to_u64(value); + else + printf("[*] Error: Unknown keyfile property '%s'.\n", prop); +} + +static s64 _compare_keysets(keyset_t *ks1, keyset_t *ks2) +{ + s64 res; + + if((res = (s64)ks1->version - (s64)ks2->version) == 0) + res = (s64)ks1->key_revision - (s64)ks2->key_revision; + + return res; +} + +static void _sort_keysets() +{ + u32 i, to = _keysets->count; + lnode_t *max; + + list_t *tmp = list_create(); + + for(i = 0; i < to; i++) + { + max = _keysets->head; + LIST_FOREACH(iter, _keysets) + { + if(_compare_keysets((keyset_t *)max->value, (keyset_t *)iter->value) < 0) + max = iter; + } + list_push(tmp, max->value); + list_remove_node(_keysets, max); + } + + list_destroy(_keysets); + _keysets = tmp; +} + +static void _sort_internal_keysets() +{ + u32 i, to = _internal_keysets->count; + lnode_t *max; + + list_t *tmp = list_create(); + + for(i = 0; i < to; i++) + { + max = _internal_keysets->head; + LIST_FOREACH(iter, _internal_keysets) + { + if(_compare_keysets((keyset_t *)max->value, (keyset_t *)iter->value) < 0) + max = iter; + } + list_push(tmp, max->value); + list_remove_node(_internal_keysets, max); + } + + list_destroy(_internal_keysets); + _internal_keysets = tmp; +} + +void _print_key_list(FILE *fp) +{ + const s8 *name; + s32 len = 0, tmp; + + LIST_FOREACH(iter, _keysets) + if((tmp = strlen(((keyset_t *)iter->value)->name)) > len) + len = tmp; + + fprintf(fp, " Name"); + _print_align(fp, " ", len, 4); + fprintf(fp, " Category Revision Version Program-Type\n"); + + LIST_FOREACH(iter, _keysets) + { + keyset_t *ks = (keyset_t *)iter->value; + fprintf(fp, " %s", ks->name); + _print_align(fp, " ", len, strlen(ks->name)); + fprintf(fp, " %-5s 0x%04X %s ", _get_name(_key_categories, ks->category), ks->key_revision, sce_version_to_str(ks->version)); + if(ks->category == KEYCATEGORY_SELF) + { + name = _get_name(_program_types, ks->program_type); + if(name != NULL) + fprintf(fp, "[%s]\n", name); + else + fprintf(fp, "0x%08X\n", ks->program_type); + } + else + fprintf(fp, "\n"); + } +} + +void _print_internal_key_list(FILE *fp) +{ + const s8 *name; + s32 len = 0, tmp; + + LIST_FOREACH(iter, _internal_keysets) + if((tmp = strlen(((keyset_t *)iter->value)->name)) > len) + len = tmp; + + fprintf(fp, " Name"); + _print_align(fp, " ", len, 4); + fprintf(fp, " Category Revision Version Program-Type\n"); + + LIST_FOREACH(iter, _internal_keysets) + { + keyset_t *ks = (keyset_t *)iter->value; + fprintf(fp, " %s", ks->name); + _print_align(fp, " ", len, strlen(ks->name)); + fprintf(fp, " %-5s 0x%04X %s ", _get_name(_key_categories, ks->category), ks->key_revision, sce_version_to_str(ks->version)); + if(ks->category == KEYCATEGORY_SELF) + { + name = _get_name(_program_types, ks->program_type); + if(name != NULL) + fprintf(fp, "[%s]\n", name); + else + fprintf(fp, "0x%08X\n", ks->program_type); + } + else + fprintf(fp, "\n"); + } +} + +#define LINEBUFSIZE 512 +bool keys_load(const s8 *kfile) +{ + u32 i = 0, lblen; + FILE *fp; + s8 lbuf[LINEBUFSIZE]; + keyset_t *cks = NULL; + + if((_keysets = list_create()) == NULL) + return FALSE; + + if((fp = fopen(kfile, "r")) == NULL) + { + list_destroy(_keysets); + return FALSE; + } + + do + { + //Get next line. + lbuf[0] = 0; + fgets(lbuf, LINEBUFSIZE, fp); + lblen = strlen(lbuf); + + //Don't parse empty lines (ignore '\n') and comment lines (starting with '#'). + if(lblen > 1 && lbuf[0] != '#') + { + //Remove '\n'. + lbuf[lblen-1] = 0; + + //Check for keyset entry. + if(lblen > 2 && lbuf[0] == '[') + { + if(cks != NULL) + { + //Add to keyset list. + list_push(_keysets, cks); + cks = NULL; + } + + //Find name end. + for(i = 0; lbuf[i] != ']' && lbuf[i] != '\n' && i < lblen; i++); + lbuf[i] = 0; + + //Allocate keyset and fill name. + cks = (keyset_t *)malloc(sizeof(keyset_t)); + memset(cks, 0, sizeof(keyset_t)); + cks->name = strdup(&lbuf[1]); + } + else if(cks != NULL) + { + //Find property name end. + for(i = 0; lbuf[i] != '=' && lbuf[i] != '\n' && i < lblen; i++); + lbuf[i] = 0; + + //Fill property. + _fill_property(cks, &lbuf[0], &lbuf[i+1]); + } + } + } while(!feof(fp)); + + //Add last keyset to keyset list. + if(cks != NULL) + list_push(_keysets, cks); + + //Sort keysets. + _sort_keysets(); + + return TRUE; +} + +bool internal_keys_load(const s8 *kfile) +{ + u32 i = 0, lblen; + FILE *fp; + s8 lbuf[LINEBUFSIZE]; + keyset_t *cks = NULL; + + if((_internal_keysets = list_create()) == NULL) + return FALSE; + + if((fp = fopen(kfile, "r")) == NULL) + { + list_destroy(_internal_keysets); + return FALSE; + } + + do + { + //Get next line. + lbuf[0] = 0; + fgets(lbuf, LINEBUFSIZE, fp); + lblen = strlen(lbuf); + + //Don't parse empty lines (ignore '\n') and comment lines (starting with '#'). + if(lblen > 1 && lbuf[0] != '#') + { + //Remove '\n'. + lbuf[lblen-1] = 0; + + //Check for keyset entry. + if(lblen > 2 && lbuf[0] == '[') + { + if(cks != NULL) + { + //Add to keyset list. + list_push(_internal_keysets, cks); + cks = NULL; + } + + //Find name end. + for(i = 0; lbuf[i] != ']' && lbuf[i] != '\n' && i < lblen; i++); + lbuf[i] = 0; + + //Allocate keyset and fill name. + cks = (keyset_t *)malloc(sizeof(keyset_t)); + memset(cks, 0, sizeof(keyset_t)); + cks->name = strdup(&lbuf[1]); + } + else if(cks != NULL) + { + //Find property name end. + for(i = 0; lbuf[i] != '=' && lbuf[i] != '\n' && i < lblen; i++); + lbuf[i] = 0; + + //Fill property. + _fill_property(cks, &lbuf[0], &lbuf[i+1]); + } + } + } while(!feof(fp)); + + //Add last keyset to keyset list. + if(cks != NULL) + list_push(_internal_keysets, cks); + + //Sort keysets. + _sort_internal_keysets(); + + return TRUE; +} +#undef LINEBUFSIZE + +static bool validate_keyset(sce_buffer_ctxt_t *ctxt, keyset_t *ks) +{ + u8 *test_buf = (u8 *)malloc(sizeof(u8) * 0x50); + u8 *test_buf2 = (u8 *)malloc(sizeof(u8) * 0x50); + u8 *iv = (u8 *)malloc(sizeof(u8) * 0x10); + u8 *sblk = (u8 *)malloc(sizeof(u8) * 0x10); + u8 *ctr_iv = (u8 *)malloc(sizeof(u8) * 0x10); + aes_context aes_ctxt; + size_t nc_off; + u64 sig_input_length; + u32 sig_algo, section_count; + + memcpy(test_buf, ctxt->metai, 0x50); + + memcpy(test_buf2, test_buf, 0x50); + nc_off = 0; + + memcpy(iv, ks->riv, 0x10); + aes_setkey_dec(&aes_ctxt, ks->erk, KEYBITS(ks->erklen)); + aes_crypt_cbc(&aes_ctxt, AES_DECRYPT, 0x40, iv, test_buf2, test_buf2); + + nc_off = 0; + memcpy (ctr_iv, (test_buf2 + 0x20) ,0x10); + aes_setkey_enc(&aes_ctxt, test_buf2, METADATA_INFO_KEYBITS); + aes_crypt_ctr(&aes_ctxt, 0x10, &nc_off, ctr_iv, sblk, (test_buf2 + 0x40), (test_buf2 + 0x40)); + + sig_input_length = _ES64(*(u64*)&test_buf2[0x40]); + sig_algo = _ES32(*(u32*)&test_buf2[0x48]); + section_count = _ES32(*(u32*)&test_buf2[0x4C]); + + if((sig_input_length < _ES64(ctxt->cfh->file_offset)) && sig_algo == 1 && section_count < 0xFF) + return true; + + memcpy(test_buf2, test_buf, 0x50); + memcpy(iv, ks->riv, 0x10); + aes_setkey_enc(&aes_ctxt, ks->erk, KEYBITS(ks->erklen)); + aes_crypt_ctr(&aes_ctxt, 0x40, &nc_off, iv, sblk, test_buf2, test_buf2); + + nc_off = 0; + memcpy (ctr_iv, (test_buf2 + 0x20) ,0x10); + aes_setkey_enc(&aes_ctxt, test_buf2, METADATA_INFO_KEYBITS); + aes_crypt_ctr(&aes_ctxt, 0x10, &nc_off, ctr_iv, sblk, (test_buf2 + 0x40), (test_buf2 + 0x40)); + + sig_input_length = _ES64(*(u64*)&test_buf2[0x40]); + sig_algo = _ES32(*(u32*)&test_buf2[0x48]); + section_count = _ES32(*(u32*)&test_buf2[0x4C]); + + if((sig_input_length < _ES64(ctxt->cfh->file_offset)) && sig_algo == 1 && section_count < 0xFF) + return true; + + return false; +} + +static keyset_t *_keyset_bruteforce_for_self(sce_buffer_ctxt_t *ctxt, u32 program_type, list_t *__keysets) +{ + LIST_FOREACH(iter, __keysets) + { + keyset_t *ks = (keyset_t *)iter->value; + + if(ks->program_type == program_type) + { + switch(program_type) + { + case PROGRAM_TYPE_LV0: + if (validate_keyset(ctxt, ks)) + return ks; + break; + case PROGRAM_TYPE_LV1: + if (validate_keyset(ctxt, ks)) + return ks; + break; + case PROGRAM_TYPE_LV2: + if (validate_keyset(ctxt, ks)) + return ks; + break; + case PROGRAM_TYPE_APP: + if (validate_keyset(ctxt, ks)) + return ks; + break; + case PROGRAM_TYPE_ISO: + if (validate_keyset(ctxt, ks)) + return ks; + break; + case PROGRAM_TYPE_LDR: + if (validate_keyset(ctxt, ks)) + return ks; + break; + case PROGRAM_TYPE_NPDRM: + if (validate_keyset(ctxt, ks)) + return ks; + break; + } + } + } + + return NULL; +} + +static keyset_t *_keyset_bruteforce_for_rvk(sce_buffer_ctxt_t *ctxt, list_t *__keysets) +{ + LIST_FOREACH(iter, __keysets) + { + keyset_t *ks = (keyset_t *)iter->value; + + if(ks->category == KEYCATEGORY_RVK) + if (validate_keyset(ctxt, ks)) + return ks; + } + + return NULL; +} + +static keyset_t *_keyset_bruteforce_for_pkg(sce_buffer_ctxt_t *ctxt, list_t *__keysets) +{ + LIST_FOREACH(iter, __keysets) + { + keyset_t *ks = (keyset_t *)iter->value; + + if(ks->category == KEYCATEGORY_PKG) + if (validate_keyset(ctxt, ks)) + return ks; + } + + return NULL; +} + +static keyset_t *_keyset_bruteforce_for_spp(sce_buffer_ctxt_t *ctxt, list_t *__keysets) +{ + LIST_FOREACH(iter, __keysets) + { + keyset_t *ks = (keyset_t *)iter->value; + + if(ks->category == KEYCATEGORY_SPP) + if (validate_keyset(ctxt, ks)) + return ks; + } + + return NULL; +} + +keyset_t *keyset_bruteforce(sce_buffer_ctxt_t *ctxt) +{ + keyset_t *res = NULL; + + switch(_ES16(ctxt->cfh->category)) + { + case CF_CATEGORY_SELF: + res = _keyset_bruteforce_for_self(ctxt, _ES32(ctxt->self.ai->program_type), _keysets); + break; + case CF_CATEGORY_RVK: + res = _keyset_bruteforce_for_rvk(ctxt, _keysets); + break; + case CF_CATEGORY_PKG: + res = _keyset_bruteforce_for_pkg(ctxt, _keysets); + break; + case CF_CATEGORY_SPP: + res = _keyset_bruteforce_for_spp(ctxt, _keysets); + break; + } + + if(res == NULL) + { + switch(_ES16(ctxt->cfh->category)) + { + case CF_CATEGORY_SELF: + res = _keyset_bruteforce_for_self(ctxt, _ES32(ctxt->self.ai->program_type), _internal_keysets); + break; + case CF_CATEGORY_RVK: + res = _keyset_bruteforce_for_rvk(ctxt, _internal_keysets); + break; + case CF_CATEGORY_PKG: + res = _keyset_bruteforce_for_pkg(ctxt, _internal_keysets); + break; + case CF_CATEGORY_SPP: + res = _keyset_bruteforce_for_spp(ctxt, _internal_keysets); + break; + } + } + //Backup keyset. + if(res != NULL) + _used_keyset = res; + + if(res == NULL) + printf("[*] Error: Could not find keyset for %s.\n", _get_name(_cert_file_categories, _ES16(ctxt->cfh->category))); + + return res; +} + +keyset_t *get_used_keyset() +{ + return _used_keyset; +} + +static keyset_t *_keyset_find_for_self(u32 program_type, u16 key_revision, u64 version) +{ + LIST_FOREACH(iter, _keysets) + { + keyset_t *ks = (keyset_t *)iter->value; + + if(ks->program_type == program_type) + { + switch(program_type) + { + case PROGRAM_TYPE_LV0: + return ks; + break; + case PROGRAM_TYPE_LV1: + if(version <= ks->version) + return ks; + break; + case PROGRAM_TYPE_LV2: + if(version <= ks->version) + return ks; + break; + case PROGRAM_TYPE_APP: + if(key_revision == ks->key_revision) + return ks; + break; + case PROGRAM_TYPE_ISO: + if(version <= ks->version && key_revision == ks->key_revision) + return ks; + break; + case PROGRAM_TYPE_LDR: + return ks; + break; + case PROGRAM_TYPE_NPDRM: + if(key_revision == ks->key_revision) + return ks; + break; + } + } + } + + return NULL; +} + +static keyset_t *_keyset_find_for_rvk(u32 key_revision) +{ + LIST_FOREACH(iter, _keysets) + { + keyset_t *ks = (keyset_t *)iter->value; + + if(ks->category == KEYCATEGORY_RVK && key_revision <= ks->key_revision) + return ks; + } + + return NULL; +} + +static keyset_t *_keyset_find_for_pkg(u16 key_revision) +{ + LIST_FOREACH(iter, _keysets) + { + keyset_t *ks = (keyset_t *)iter->value; + + if(ks->category == KEYCATEGORY_PKG && key_revision <= ks->key_revision) + return ks; + } + + return NULL; +} + +static keyset_t *_keyset_find_for_spp(u16 key_revision) +{ + LIST_FOREACH(iter, _keysets) + { + keyset_t *ks = (keyset_t *)iter->value; + + if(ks->category == KEYCATEGORY_SPP && key_revision <= ks->key_revision) + return ks; + } + + return NULL; +} + +keyset_t *keyset_find(sce_buffer_ctxt_t *ctxt) +{ + keyset_t *res = NULL; + + switch(_ES16(ctxt->cfh->category)) + { + case CF_CATEGORY_SELF: + res = _keyset_find_for_self(_ES32(ctxt->self.ai->program_type), _ES16(ctxt->cfh->key_revision), _ES64(ctxt->self.ai->version)); + break; + case CF_CATEGORY_RVK: + res = _keyset_find_for_rvk(_ES16(ctxt->cfh->key_revision)); + break; + case CF_CATEGORY_PKG: + res = _keyset_find_for_pkg(_ES16(ctxt->cfh->key_revision)); + break; + case CF_CATEGORY_SPP: + res = _keyset_find_for_spp(_ES16(ctxt->cfh->key_revision)); + break; + } + + if(res == NULL) + printf("[*] Error: Could not find keyset for %s.\n", _get_name(_cert_file_categories, _ES16(ctxt->cfh->category))); + + return res; +} + +keyset_t *keyset_find_by_name(const s8 *name) +{ + LIST_FOREACH(iter, _keysets) + { + keyset_t *ks = (keyset_t *)iter->value; + if(strcmp(ks->name, name) == 0) + return ks; + } + + printf("[*] Error: Could not find keyset '%s'.\n", name); + + return NULL; +} + +bool curves_load(const s8 *cfile) +{ + u32 len = 0; + + _curves = (curve_t *)_read_buffer(cfile, &len); + + if(_curves == NULL) + return FALSE; + + if(len != CURVES_LENGTH) + { + free(_curves); + return FALSE; + } + + return TRUE; +} + +curve_t *curve_find(u8 ctype) +{ + if(ctype > CTYPE_MAX) + return NULL; + return &_curves[ctype]; +} + +bool vsh_curves_load(const s8 *cfile) +{ + u32 len = 0; + + _vsh_curves = (vsh_curve_t *)_read_buffer(cfile, &len); + + if(_vsh_curves == NULL) + return FALSE; + + if(len != VSH_CURVES_LENGTH) + { + free(_vsh_curves); + return FALSE; + } + + return TRUE; +} + +static curve_t _tmp_curve; +curve_t *vsh_curve_find(u8 ctype) +{ + if(ctype > VSH_CTYPE_MAX) + return NULL; + + memcpy(_tmp_curve.p, _vsh_curves[ctype].p, 20); + memcpy(_tmp_curve.a, _vsh_curves[ctype].a, 20); + memcpy(_tmp_curve.b, _vsh_curves[ctype].b, 20); + _tmp_curve.N[0] = ~0x00; + memcpy(_tmp_curve.N+1, _vsh_curves[ctype].N, 20); + memcpy(_tmp_curve.Gx, _vsh_curves[ctype].Gx, 20); + memcpy(_tmp_curve.Gy, _vsh_curves[ctype].Gy, 20); + + return &_tmp_curve; +} + +static u8 *idps_load() +{ + s8 *ps3 = NULL, path[256]; + u8 *idps; + u32 len = 0; + + if((ps3 = getenv(CONFIG_ENV_PS3)) != NULL) + if(access(ps3, 0) != 0) + ps3 = NULL; + + if(ps3 != NULL) + { + sprintf(path, "%s/%s", ps3, CONFIG_IDPS_FILE); + if(access(path, 0) != 0) + sprintf(path, "%s/%s", CONFIG_IDPS_PATH, CONFIG_IDPS_FILE); + if(access(path, 0) != 0) + sprintf(path, "%s/%s/%s", ps3, CONFIG_IDPS_PATH, CONFIG_IDPS_FILE); + } + else + sprintf(path, "%s/%s", CONFIG_IDPS_PATH, CONFIG_IDPS_FILE); + + idps = (u8 *)_read_buffer(path, &len); + + if(idps == NULL) + return NULL; + + if(len != IDPS_LENGTH) + { + free(idps); + return NULL; + } + + return idps; +} + +static act_dat_t *act_dat_load() +{ + s8 *ps3 = NULL, path[256]; + act_dat_t *act_dat; + u32 len = 0; + + if((ps3 = getenv(CONFIG_ENV_PS3)) != NULL) + if(access(ps3, 0) != 0) + ps3 = NULL; + + if(ps3 != NULL) + { + sprintf(path, "%s/%s", ps3, CONFIG_ACT_DAT_FILE); + if(access(path, 0) != 0) + sprintf(path, "%s/%s", CONFIG_ACT_DAT_PATH, CONFIG_ACT_DAT_FILE); + if(access(path, 0) != 0) + sprintf(path, "%s/%s/%s", ps3, CONFIG_ACT_DAT_PATH, CONFIG_ACT_DAT_FILE); + } + else + sprintf(path, "%s/%s", CONFIG_ACT_DAT_PATH, CONFIG_ACT_DAT_FILE); + + act_dat = (act_dat_t *)_read_buffer(path, &len); + + if(act_dat == NULL) + return NULL; + + if(len != ACT_DAT_LENGTH) + { + free(act_dat); + return NULL; + } + + return act_dat; +} + +static rif_t *rif_load(const s8 *content_id) +{ + s8 *ps3 = NULL, path[256]; + rif_t *rif; + u32 len = 0; + + if((ps3 = getenv(CONFIG_ENV_PS3)) != NULL) + if(access(ps3, 0) != 0) + ps3 = NULL; + + if(ps3 != NULL) + { + sprintf(path, "%s/%s%s", ps3, content_id, CONFIG_RIF_FILE_EXT); + if(access(path, 0) != 0) + sprintf(path, "%s/%s%s", CONFIG_RIF_PATH, content_id, CONFIG_RIF_FILE_EXT); + if(access(path, 0) != 0) + sprintf(path, "%s/%s/%s%s", ps3, CONFIG_RIF_PATH, content_id, CONFIG_RIF_FILE_EXT); + } + else + sprintf(path, "%s/%s%s", CONFIG_RIF_PATH, content_id, CONFIG_RIF_FILE_EXT); + + rif = (rif_t *)_read_buffer(path, &len); + if(rif == NULL) + return NULL; + + if(len < RIF_LENGTH) + { + free(rif); + return NULL; + } + + return rif; +} + +static u8 *rap_load(const s8 *content_id) +{ + s8 *ps3 = NULL, path[256]; + u8 *rap; + u32 len = 0; + + if((ps3 = getenv(CONFIG_ENV_PS3)) != NULL) + if(access(ps3, 0) != 0) + ps3 = NULL; + + if(ps3 != NULL) + { + sprintf(path, "%s/%s%s", ps3, content_id, CONFIG_RAP_FILE_EXT); + if(access(path, 0) != 0) + sprintf(path, "%s/%s%s", CONFIG_RAP_PATH, content_id, CONFIG_RAP_FILE_EXT); + if(access(path, 0) != 0) + sprintf(path, "%s/%s/%s%s", ps3, CONFIG_RAP_PATH, content_id, CONFIG_RAP_FILE_EXT); + } + else + sprintf(path, "%s/%s%s", CONFIG_RAP_PATH, content_id, CONFIG_RAP_FILE_EXT); + + rap = (u8 *)_read_buffer(path, &len); + + if(rap == NULL) + return NULL; + + if(len != RAP_LENGTH) + { + free(rap); + return NULL; + } + + return rap; +} + +static bool rap_to_klicensee(const s8 *content_id, u8 *klicensee) +{ + u8 *rap; + aes_context aes_ctxt; + int round_num; + int i; + keyset_t *rap_init_key, *rap_pbox, *rap_e1, *rap_e2; + + rap_init_key = keyset_find_by_name(CONFIG_NP_RAP_INITIAL_KNAME); + if(rap_init_key == NULL) + return FALSE; + + rap_pbox = keyset_find_by_name(CONFIG_NP_RAP_PBOX_KNAME); + if(rap_pbox == NULL) + return FALSE; + + rap_e1 = keyset_find_by_name(CONFIG_NP_RAP_E1_KNAME); + if(rap_e1 == NULL) + return FALSE; + + rap_e2 = keyset_find_by_name(CONFIG_NP_RAP_E2_KNAME); + if(rap_e2 == NULL) + return FALSE; + + rap = rap_load(content_id); + if(rap == NULL) + return FALSE; + + aes_setkey_dec(&aes_ctxt, rap_init_key->erk, RAP_KEYBITS); + aes_crypt_ecb(&aes_ctxt, AES_DECRYPT, rap, rap); + + for (round_num = 0; round_num < 5; ++round_num) + { + for (i = 0; i < 16; ++i) + { + int p = rap_pbox->erk[i]; + rap[p] ^= rap_e1->erk[p]; + } + for (i = 15; i >= 1; --i) + { + int p = rap_pbox->erk[i]; + int pp = rap_pbox->erk[i - 1]; + rap[p] ^= rap[pp]; + } + int o = 0; + for (i = 0; i < 16; ++i) + { + int p = rap_pbox->erk[i]; + u8 kc = rap[p] - o; + u8 ec2 = rap_e2->erk[p]; + if (o != 1 || kc != 0xFF) + { + o = kc < ec2 ? 1 : 0; + rap[p] = kc - ec2; + } + else + rap[p] = kc - ec2; + } + } + + memcpy(klicensee, rap, RAP_LENGTH); + free(rap); + + return TRUE; +} + +bool klicensee_by_content_id(const s8 *content_id, u8 *klicensee) +{ + aes_context aes_ctxt; + + if(rap_to_klicensee(content_id, klicensee) == FALSE) + { + keyset_t *ks_np_idps_const, *ks_np_rif_key; + rif_t *rif; + u8 idps_const[0x10]; + u8 act_dat_key[0x10]; + u32 act_dat_key_index; + u8 *idps; + act_dat_t *act_dat; + + if((idps = idps_load()) == NULL) + { + printf("[*] Error: Could not load IDPS.\n"); + return FALSE; + } + else + _LOG_VERBOSE("IDPS loaded.\n"); + + if((act_dat = act_dat_load()) == NULL) + { + printf("[*] Error: Could not load act.dat.\n"); + return FALSE; + } + else + _LOG_VERBOSE("act.dat loaded.\n"); + + ks_np_idps_const = keyset_find_by_name(CONFIG_NP_IDPS_CONST_KNAME); + if(ks_np_idps_const == NULL) + return FALSE; + memcpy(idps_const, ks_np_idps_const->erk, 0x10); + + ks_np_rif_key = keyset_find_by_name(CONFIG_NP_RIF_KEY_KNAME); + if(ks_np_rif_key == NULL) + return FALSE; + + rif = rif_load(content_id); + if(rif == NULL) + { + printf("[*] Error: Could not obtain klicensee for '%s'.\n", content_id); + return FALSE; + } + + aes_setkey_dec(&aes_ctxt, ks_np_rif_key->erk, RIF_KEYBITS); + aes_crypt_ecb(&aes_ctxt, AES_DECRYPT, rif->act_key_index, rif->act_key_index); + + act_dat_key_index = _ES32(*(u32 *)(rif->act_key_index + 12)); + if(act_dat_key_index > 127) + { + printf("[*] Error: act.dat key index out of bounds.\n"); + return FALSE; + } + + memcpy(act_dat_key, act_dat->primary_key_table + act_dat_key_index * BITS2BYTES(ACT_DAT_KEYBITS), BITS2BYTES(ACT_DAT_KEYBITS)); + + 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_dec(&aes_ctxt, act_dat_key, ACT_DAT_KEYBITS); + aes_crypt_ecb(&aes_ctxt, AES_DECRYPT, rif->klicensee, klicensee); + + free(rif); + + _LOG_VERBOSE("Klicensee decrypted.\n"); + } + else + _LOG_VERBOSE("Klicensee converted from %s.rap.\n", content_id); + + return TRUE; +} + +bool dev_klicensee_by_content_id(const s8 *content_id, u8 *klicensee) +{ + + s8 *ps3 = NULL, path[256]; + u8 *klic; + u32 len = 0; + + if((ps3 = getenv(CONFIG_ENV_PS3)) != NULL) + if(access(ps3, 0) != 0) + ps3 = NULL; + + if(ps3 != NULL) + { + sprintf(path, "%s/%s%s", ps3, content_id, CONFIG_KLIC_FILE_EXT); + if(access(path, 0) != 0) + sprintf(path, "%s/%s%s", CONFIG_KLIC_PATH, content_id, CONFIG_KLIC_FILE_EXT); + if(access(path, 0) != 0) + sprintf(path, "%s/%s/%s%s", ps3, CONFIG_KLIC_PATH, content_id, CONFIG_KLIC_FILE_EXT); + } + else + sprintf(path, "%s/%s%s", CONFIG_KLIC_PATH, content_id, CONFIG_KLIC_FILE_EXT); + + klic = (u8 *)_read_buffer(path, &len); + + if(klic == NULL) + return FALSE; + + if(len != KLIC_LENGTH) + { + free(klic); + return FALSE; + } + memcpy(klicensee, klic, KLIC_LENGTH); + free(klic); + _LOG_VERBOSE("Klicensee loaded from %s.klic.\n", content_id); + + return TRUE; +} + +keyset_t *keyset_from_buffer(u8 *keyset) +{ + keyset_t *ks; + + if((ks = (keyset_t *)malloc(sizeof(keyset_t))) == NULL) + return NULL; + + ks->erk = (u8 *)_memdup(keyset, 0x20); + ks->erklen = 0x20; + ks->riv = (u8 *)_memdup(keyset + 0x20, 0x10); + ks->rivlen = 0x10; + ks->pub = (u8 *)_memdup(keyset + 0x20 + 0x10, 0x28); + ks->priv = (u8 *)_memdup(keyset + 0x20 + 0x10 + 0x28, 0x15); + ks->ctype = (u8)*(keyset + 0x20 + 0x10 + 0x28 + 0x15); + + return ks; +} diff --git a/keys.h b/src/keys.h similarity index 75% rename from keys.h rename to src/keys.h index 1a12fae..a984e47 100644 --- a/keys.h +++ b/src/keys.h @@ -11,11 +11,11 @@ #define KEYBITS(klen) BYTES2BITS(klen) -#define KEYTYPE_SELF 1 -#define KEYTYPE_RVK 2 -#define KEYTYPE_PKG 3 -#define KEYTYPE_SPP 4 -#define KEYTYPE_OTHER 5 +#define KEYCATEGORY_SELF 1 +#define KEYCATEGORY_RVK 2 +#define KEYCATEGORY_PKG 3 +#define KEYCATEGORY_SPP 4 +#define KEYCATEGORY_OTHER 5 /*! Flag to use VSH curve. */ #define USE_VSH_CURVE 0x40 @@ -35,6 +35,7 @@ #define ACT_DAT_LENGTH 0x1038 #define RIF_LENGTH 0x98 #define RAP_LENGTH 0x10 +#define KLIC_LENGTH 0x10 /*! IDPS, RIF, act.dat key lengths. */ #define IDPS_KEYBITS 128 @@ -47,14 +48,14 @@ typedef struct _keyset { /*! Name. */ s8 *name; - /*! Type. */ - u32 type; + /*! Category. */ + u32 category; /*! Key revision. */ u16 key_revision; /*! Version. */ u64 version; - /*! SELF type. */ - u32 self_type; + /*! Program type. */ + u32 program_type; /*! Key length. */ u32 erklen; /*! Key. */ @@ -85,10 +86,10 @@ typedef struct _curve /*! VSH Curve entry. */ typedef struct _vsh_curve { + u8 p[20]; u8 a[20]; u8 b[20]; u8 N[20]; - u8 p[20]; u8 Gx[20]; u8 Gy[20]; } vsh_curve_t; @@ -115,19 +116,24 @@ typedef struct _rif } rif_t; void _print_key_list(FILE *fp); +void _print_internal_key_list(FILE *fp); -BOOL keys_load(const s8 *kfile); +bool keys_load(const s8 *kfile); +bool internal_keys_load(const s8 *kfile); keyset_t *keyset_find(sce_buffer_ctxt_t *ctxt); +keyset_t *keyset_bruteforce(sce_buffer_ctxt_t *ctxt); keyset_t *keyset_find_by_name(const s8 *name); -BOOL curves_load(const s8 *cfile); +bool curves_load(const s8 *cfile); curve_t *curve_find(u8 ctype); -BOOL vsh_curves_load(const s8 *cfile); +bool vsh_curves_load(const s8 *cfile); curve_t *vsh_curve_find(u8 ctype); -BOOL klicensee_by_content_id(const s8 *content_id, u8 *klicensee); +bool klicensee_by_content_id(const s8 *content_id, u8 *klicensee); +bool dev_klicensee_by_content_id(const s8 *content_id, u8 *klicensee); keyset_t *keyset_from_buffer(u8 *keyset); +keyset_t *get_used_keyset(); #endif diff --git a/list.cpp b/src/list.cpp similarity index 93% rename from list.cpp rename to src/list.cpp index aac05ea..ded4c47 100644 --- a/list.cpp +++ b/src/list.cpp @@ -38,7 +38,7 @@ void list_destroy(list_t *l) free(l); } -BOOL list_isempty(list_t *l) +bool list_isempty(list_t *l) { if(l == NULL) return FALSE; @@ -56,7 +56,7 @@ u32 list_count(list_t *l) return l->count; } -BOOL list_push(list_t *l, void *value) +bool list_push(list_t *l, void *value) { if(l == NULL) return FALSE; @@ -96,7 +96,7 @@ void *list_pop(list_t *l) return res; } -BOOL list_add_back(list_t *l, void *value) +bool list_add_back(list_t *l, void *value) { if(l == NULL) return FALSE; @@ -155,7 +155,7 @@ lnode_t *list_get_node(list_t *l, u32 idx) return iter; } -BOOL list_remove_node(list_t *l, lnode_t *node) +bool list_remove_node(list_t *l, lnode_t *node) { if(l == NULL) return FALSE; @@ -188,7 +188,7 @@ BOOL list_remove_node(list_t *l, lnode_t *node) return FALSE; } -BOOL list_remove_value(list_t *l, void *value) +bool list_remove_value(list_t *l, void *value) { if(l == NULL) return FALSE; diff --git a/list.h b/src/list.h similarity index 72% rename from list.h rename to src/list.h index a42b081..172261e 100644 --- a/list.h +++ b/src/list.h @@ -24,14 +24,14 @@ typedef struct _list list_t *list_create(); void list_destroy(list_t *l); -BOOL list_isempty(list_t *l); +bool list_isempty(list_t *l); u32 list_count(list_t *l); -BOOL list_push(list_t *l, void *value); +bool list_push(list_t *l, void *value); void *list_pop(list_t *l); -BOOL list_add_back(list_t *l, void *value); +bool list_add_back(list_t *l, void *value); void *list_get(list_t *l, u32 idx); lnode_t *list_get_node(list_t *l, u32 idx); -BOOL list_remove_node(list_t *l, lnode_t *node); -BOOL list_remove_value(list_t *l, void *value); +bool list_remove_node(list_t *l, lnode_t *node); +bool list_remove_value(list_t *l, void *value); #endif diff --git a/main.cpp b/src/main.cpp similarity index 65% rename from main.cpp rename to src/main.cpp index 44266c3..6d139b1 100644 --- a/main.cpp +++ b/src/main.cpp @@ -2,6 +2,7 @@ * Copyright (c) 2011-2013 by naehrwert * This file is released under the GPLv2. */ +#define _CRT_SECURE_NO_WARNINGS #include #include @@ -36,20 +37,20 @@ #define ARG_OPT optional_argument /*! Verbose mode. */ -BOOL _verbose = FALSE; +bool _verbose = FALSE; /*! Raw mode. */ -BOOL _raw = FALSE; +bool _raw = FALSE; /*! We got work. */ -static BOOL _got_work = FALSE; +static bool _got_work = FALSE; /*! List keys. */ -static BOOL _list_keys = FALSE; +static bool _list_keys = FALSE; /*! Print infos on file. */ -static BOOL _print_info = FALSE; +static bool _print_info = FALSE; /*! Decrypt file. */ -static BOOL _decrypt_file = FALSE; +static bool _decrypt_file = FALSE; /*! Encrypt file. */ -static BOOL _encrypt_file = FALSE; +static bool _encrypt_file = FALSE; /*! Parameters. */ s8 *_template = NULL; @@ -61,15 +62,13 @@ s8 *_meta_info = NULL; s8 *_keyset = NULL; s8 *_auth_id = NULL; s8 *_vendor_id = NULL; -s8 *_self_type = NULL; +s8 *_program_type = NULL; s8 *_app_version = NULL; s8 *_fw_version = NULL; s8 *_add_shdrs = NULL; s8 *_ctrl_flags = NULL; s8 *_cap_flags = NULL; -#ifdef CONFIG_CUSTOM_INDIV_SEED s8 *_indiv_seed = NULL; -#endif s8 *_license_type = NULL; s8 *_app_type = NULL; s8 *_content_id = NULL; @@ -84,7 +83,7 @@ static s8 *_file_out = NULL; /*! Long option values. */ #define VAL_TEMPLATE 't' -#define VAL_FILE_TYPE '0' +#define VAL_FILE_CATEGORY '0' #define VAL_COMPRESS_DATA '1' #define VAL_SKIP_SECTIONS 's' #define VAL_KEY_REV '2' @@ -92,15 +91,13 @@ static s8 *_file_out = NULL; #define VAL_KEYSET 'K' #define VAL_AUTH_ID '3' #define VAL_VENDOR_ID '4' -#define VAL_SELF_TYPE '5' +#define VAL_PROGRAM_TYPE '5' #define VAL_APP_VERSION 'A' #define VAL_FW_VERSION '6' #define VAL_ADD_SHDRS '7' #define VAL_CTRL_FLAGS '8' #define VAL_CAP_FLAGS '9' -#ifdef CONFIG_CUSTOM_INDIV_SEED #define VAL_INDIV_SEED 'a' -#endif #define VAL_LICENSE_TYPE 'b' #define VAL_APP_TYPE 'c' #define VAL_CONTENT_ID 'f' @@ -118,23 +115,21 @@ static struct option options[] = {"verbose", ARG_NONE, NULL, 'v'}, {"raw", ARG_NONE, NULL, 'r'}, {"template", ARG_REQ, NULL, VAL_TEMPLATE}, - {"sce-type", ARG_REQ, NULL, VAL_FILE_TYPE}, + {"category", ARG_REQ, NULL, VAL_FILE_CATEGORY}, {"compress-data", ARG_REQ, NULL, VAL_COMPRESS_DATA}, {"skip-sections", ARG_REQ, NULL, VAL_SKIP_SECTIONS}, {"key-revision", ARG_REQ, NULL, VAL_KEY_REV}, {"meta-info", ARG_REQ, NULL, VAL_META_INFO}, {"keyset", ARG_REQ, NULL, VAL_KEYSET}, - {"self-auth-id", ARG_REQ, NULL, VAL_AUTH_ID}, - {"self-vendor-id", ARG_REQ, NULL, VAL_VENDOR_ID}, - {"self-type", ARG_REQ, NULL, VAL_SELF_TYPE}, + {"program-auth-id", ARG_REQ, NULL, VAL_AUTH_ID}, + {"program-vendor-id", ARG_REQ, NULL, VAL_VENDOR_ID}, + {"program-type", ARG_REQ, NULL, VAL_PROGRAM_TYPE}, {"self-app-version", ARG_REQ, NULL, VAL_APP_VERSION}, {"self-fw-version", ARG_REQ, NULL, VAL_FW_VERSION}, {"self-add-shdrs", ARG_REQ, NULL, VAL_ADD_SHDRS}, {"self-ctrl-flags", ARG_REQ, NULL, VAL_CTRL_FLAGS}, {"self-cap-flags", ARG_REQ, NULL, VAL_CAP_FLAGS}, -#ifdef CONFIG_CUSTOM_INDIV_SEED {"self-indiv-seed", ARG_REQ, NULL, VAL_INDIV_SEED}, -#endif {"np-license-type", ARG_REQ, NULL, VAL_LICENSE_TYPE}, {"np-app-type", ARG_REQ, NULL, VAL_APP_TYPE}, {"np-content-id", ARG_REQ, NULL, VAL_CONTENT_ID}, @@ -158,41 +153,39 @@ static void print_usage() print_version(); printf("USAGE: scetool [options] command\n"); - printf("COMMANDS Parameters Explanation\n"); - printf(" -h, --help Print this help.\n"); - printf(" -k, --print-keys List keys.\n"); - printf(" -i, --print-infos File-in Print SCE file info.\n"); - printf(" -d, --decrypt File-in File-out Decrypt/dump SCE file.\n"); - printf(" -e, --encrypt File-in File-out Encrypt/create SCE file.\n"); - printf("OPTIONS Possible Values Explanation\n"); - printf(" -v, --verbose Enable verbose output.\n"); - printf(" -r, --raw Enable raw value output.\n"); - printf(" -t, --template File-in Template file (SELF only)\n"); - printf(" -0, --sce-type SELF/RVK/PKG/SPP SCE File Type\n"); - printf(" -1, --compress-data TRUE/FALSE(default) Whether to compress data or not.\n"); - printf(" -s, --skip-sections TRUE(default)/FALSE Whether to skip sections or not.\n"); - printf(" -2, --key-revision e.g. 00,01,...,0A,... Key Revision\n"); - printf(" -m, --meta-info 64 bytes Use provided meta info to decrypt.\n"); - printf(" -K, --keyset 32(Key)16(IV)\n"); - printf(" 40(Pub)21(Priv)1(CT) Override keyset.\n"); - printf(" -3, --self-auth-id e.g. 1010000001000003 Authentication ID\n"); - printf(" -4, --self-vendor-id e.g. 01000002 Vendor ID\n"); - printf(" -5, --self-type LV0/LV1/LV2/APP/ISO/\n"); - printf(" LDR/NPDRM SELF Type\n"); - printf(" -A, --self-app-version e.g. 0001000000000000 Application Version\n"); - printf(" -6, --self-fw-version e.g. 0003004100000000 Firmware Version\n"); - printf(" -7, --self-add-shdrs TRUE(default)/FALSE Whether to add ELF shdrs or not.\n"); - printf(" -8, --self-ctrl-flags 32 bytes Override control flags.\n"); - printf(" -9, --self-cap-flags 32 bytes Override capability flags.\n"); -#ifdef CONFIG_CUSTOM_INDIV_SEED - printf(" -a, --self-indiv-seed 256 bytes Individuals Seed (ISO only)\n"); -#endif - printf(" -b, --np-license-type LOCAL/FREE License Type\n"); - printf(" -c, --np-app-type SPRX/EXEC/USPRX/UEXEC App Type (U* for updates)\n"); - printf(" -f, --np-content-id Content ID\n"); - printf(" -l, --np-klicensee 16 bytes Override klicensee.\n"); - printf(" -g, --np-real-fname e.g. EBOOT.BIN Real Filename\n"); - printf(" -j, --np-add-sig TRUE/FALSE(default) Whether to add a NP sig. or not.\n"); + printf("COMMANDS Parameters Explanation\n"); + printf(" -h, --help Print this help.\n"); + printf(" -k, --print-keys List keys.\n"); + printf(" -i, --print-infos File-in Print SCE file info.\n"); + printf(" -d, --decrypt File-in File-out Decrypt/dump SCE file.\n"); + printf(" -e, --encrypt File-in File-out Encrypt/create SCE file.\n"); + printf("OPTIONS Possible Values Explanation\n"); + printf(" -v, --verbose Enable verbose output.\n"); + printf(" -r, --raw Enable raw value output.\n"); + printf(" -t, --template File-in Template file (SELF only)\n"); + printf(" -0, --category SELF/RVK/PKG/SPP SCE File Type\n"); + printf(" -1, --compress-data TRUE/FALSE(default) Whether to compress data or not.\n"); + printf(" -s, --skip-sections TRUE(default)/FALSE Whether to skip sections or not.\n"); + printf(" -2, --key-revision e.g. 00,01,...,0A,... Key Revision\n"); + printf(" -m, --meta-info 64 bytes Use provided meta info to decrypt.\n"); + printf(" -K, --keyset 32(Key)16(IV)\n"); + printf(" 40(Pub)21(Priv)1(CT) Override keyset.\n"); + printf(" -3, --program-auth-id e.g. 1010000001000003 Authentication ID\n"); + printf(" -4, --program-vendor-id e.g. 01000002 Vendor ID\n"); + printf(" -5, --program-type LV0/LV1/LV2/APP/ISO/\n"); + printf(" LDR/NPDRM Program Type\n"); + printf(" -A, --self-app-version e.g. 0001000000000000 Application Version\n"); + printf(" -6, --self-fw-version e.g. 0003004100000000 Firmware Version\n"); + printf(" -7, --self-add-shdrs TRUE(default)/FALSE Whether to add ELF shdrs or not.\n"); + printf(" -8, --self-ctrl-flags 32 bytes Override control flags.\n"); + printf(" -9, --self-cap-flags 32 bytes Override capability flags.\n"); + printf(" -a, --self-indiv-seed 256 bytes Individuals Seed (ISO only)\n"); + printf(" -b, --np-license-type LOCAL/FREE License Type\n"); + printf(" -c, --np-app-type SPRX/EXEC/USPRX/UEXEC App Type (U* for updates)\n"); + printf(" -f, --np-content-id Content ID\n"); + printf(" -l, --np-klicensee 16 bytes Override klicensee.\n"); + printf(" -g, --np-real-fname e.g. EBOOT.BIN Real Filename\n"); + printf(" -j, --np-add-sig TRUE/FALSE(default) Whether to add a NP sig. or not.\n"); //getchar(); @@ -203,11 +196,7 @@ static void parse_args(int argc, char **argv) { char c; -#ifdef CONFIG_CUSTOM_INDIV_SEED while((c = getopt_long(argc, argv, "hki:d:e:vrt:0:1:s:2:m:K:3:4:5:A:6:7:8:9:a:b:c:f:l:g:j:", options, NULL)) != -1) -#else - while((c = getopt_long(argc, argv, "hki:d:e:vrt:0:1:s:2:m:K:3:4:5:A:6:7:8:9:b:c:f:l:g:j:", options, NULL)) != -1) -#endif { switch(c) { @@ -250,7 +239,7 @@ static void parse_args(int argc, char **argv) case VAL_TEMPLATE: _template = optarg; break; - case VAL_FILE_TYPE: + case VAL_FILE_CATEGORY: _file_type = optarg; break; case VAL_COMPRESS_DATA: @@ -274,8 +263,8 @@ static void parse_args(int argc, char **argv) case VAL_VENDOR_ID: _vendor_id = optarg; break; - case VAL_SELF_TYPE: - _self_type = optarg; + case VAL_PROGRAM_TYPE: + _program_type = optarg; break; case VAL_APP_VERSION: _app_version = optarg; @@ -292,11 +281,9 @@ static void parse_args(int argc, char **argv) case VAL_CAP_FLAGS: _cap_flags = optarg; break; -#ifdef CONFIG_CUSTOM_INDIV_SEED case VAL_INDIV_SEED: _indiv_seed = optarg; break; -#endif case VAL_LICENSE_TYPE: _license_type = optarg; break; @@ -348,7 +335,6 @@ static void parse_args(int argc, char **argv) } } -#ifndef _DEBUG int main(int argc, char **argv) { s8 *ps3 = NULL, path[256]; @@ -378,6 +364,8 @@ int main(int argc, char **argv) sprintf(path, "%s/%s", ps3, CONFIG_KEYS_FILE); if(access(path, 0) != 0) sprintf(path, "%s/%s", CONFIG_KEYS_PATH, CONFIG_KEYS_FILE); + if(access(path, 0) != 0) + sprintf(path, "%s/%s/%s", ps3, CONFIG_KEYS_PATH, CONFIG_KEYS_FILE); } else sprintf(path, "%s/%s", CONFIG_KEYS_PATH, CONFIG_KEYS_FILE); @@ -393,13 +381,40 @@ int main(int argc, char **argv) else printf("[*] Warning: Could not load keys.\n"); } + + //Load internal keysets. + if(ps3 != NULL) + { + sprintf(path, "%s/%s", ps3, CONFIG_INTERNAL_KEYS_FILE); + if(access(path, 0) != 0) + sprintf(path, "%s/%s", CONFIG_KEYS_PATH, CONFIG_INTERNAL_KEYS_FILE); + if(access(path, 0) != 0) + sprintf(path, "%s/%s/%s", ps3, CONFIG_KEYS_PATH, CONFIG_INTERNAL_KEYS_FILE); + } + else + sprintf(path, "%s/%s", CONFIG_KEYS_PATH, CONFIG_INTERNAL_KEYS_FILE); + if(internal_keys_load(path) == TRUE) + _LOG_VERBOSE("Loaded internal keysets.\n"); + else + { + if(_list_keys == TRUE) + { + printf("[*] Error: Could not load internal keys.\n"); + return 0; + } + else + printf("[*] Warning: Could not load internal keys.\n"); + } + - //Load curves. + //Load loader curves. if(ps3 != NULL) { sprintf(path, "%s/%s", ps3, CONFIG_CURVES_FILE); if(access(path, 0) != 0) sprintf(path, "%s/%s", CONFIG_CURVES_PATH, CONFIG_CURVES_FILE); + if(access(path, 0) != 0) + sprintf(path, "%s/%s/%s", ps3, CONFIG_CURVES_PATH, CONFIG_CURVES_FILE); } else sprintf(path, "%s/%s", CONFIG_CURVES_PATH, CONFIG_CURVES_FILE); @@ -408,12 +423,14 @@ int main(int argc, char **argv) else printf("[*] Warning: Could not load loader curves.\n"); - //Load curves. + //Load vsh curves. if(ps3 != NULL) { sprintf(path, "%s/%s", ps3, CONFIG_VSH_CURVES_FILE); if(access(path, 0) != 0) sprintf(path, "%s/%s", CONFIG_VSH_CURVES_PATH, CONFIG_VSH_CURVES_FILE); + if(access(path, 0) != 0) + sprintf(path, "%s/%s/%s", ps3, CONFIG_VSH_CURVES_PATH, CONFIG_VSH_CURVES_FILE); } else sprintf(path, "%s/%s", CONFIG_VSH_CURVES_PATH, CONFIG_VSH_CURVES_FILE); @@ -437,6 +454,8 @@ int main(int argc, char **argv) { printf("[*] Loaded keysets:\n"); _print_key_list(stdout); + printf("[*] Loaded internal keysets:\n"); + _print_internal_key_list(stdout); } else if(_print_info) frontend_print_infos(_file_in); @@ -447,4 +466,4 @@ int main(int argc, char **argv) return 0; } -#endif + diff --git a/mt19937.cpp b/src/mt19937.cpp similarity index 100% rename from mt19937.cpp rename to src/mt19937.cpp diff --git a/mt19937.h b/src/mt19937.h similarity index 100% rename from mt19937.h rename to src/mt19937.h diff --git a/np.cpp b/src/np.cpp similarity index 77% rename from np.cpp rename to src/np.cpp index e5387f2..3b733f9 100644 --- a/np.cpp +++ b/src/np.cpp @@ -3,6 +3,7 @@ * Copyright (c) 2012 by flatz * This file is released under the GPLv2. */ +#define _CRT_SECURE_NO_WARNINGS #include @@ -30,11 +31,9 @@ static ci_data_npdrm_t *_sce_find_ci_npdrm(sce_buffer_ctxt_t *ctxt) { control_info_t *ci = (control_info_t *)iter->value; - if(ci->type == CONTROL_INFO_TYPE_NPDRM) + if(_ES32(ci->type) == CONTROL_INFO_TYPE_NPDRM) { ci_data_npdrm_t *np = (ci_data_npdrm_t *)((u8 *)ci + sizeof(control_info_t)); - //Fixup. - _es_ci_data_npdrm(np); return np; } } @@ -48,13 +47,15 @@ void np_set_klicensee(u8 *klicensee) _klicensee_key = klicensee; } -BOOL np_decrypt_npdrm(sce_buffer_ctxt_t *ctxt) +bool np_decrypt_npdrm(sce_buffer_ctxt_t *ctxt) { aes_context aes_ctxt; - keyset_t *ks_np_klic_free, *ks_klic_key; + ci_data_npdrm_t *np; + keyset_t *ks_np_klic_free, *ks_klic_key, *ks_np_ci; + u8 hash_check[0x10], ci_key[0x10]; u8 npdrm_key[0x10]; u8 npdrm_iv[0x10]; - ci_data_npdrm_t *np; + int i; if((np = _sce_find_ci_npdrm(ctxt)) == NULL) return FALSE; @@ -65,14 +66,28 @@ BOOL np_decrypt_npdrm(sce_buffer_ctxt_t *ctxt) return FALSE; if(_klicensee_key != NULL) memcpy(npdrm_key, _klicensee_key, 0x10); - else if(np->license_type == NP_LICENSE_FREE) + else if(_ES32(np->license_type) == NP_LICENSE_FREE) { ks_np_klic_free = keyset_find_by_name(CONFIG_NP_KLIC_FREE_KNAME); - if(ks_np_klic_free == NULL) + ks_np_ci = keyset_find_by_name(CONFIG_NP_CI_KNAME); + if(ks_np_ci == NULL) return FALSE; - memcpy(npdrm_key, ks_np_klic_free->erk, 0x10); + + //Generate control info hash key. + for(i = 0; i < 0x10; i++) + ci_key[i] = ks_np_ci->erk[i] ^ ks_np_klic_free->erk[i]; + + //Check header for control info hash and try to load appropriate klicensee key. + aes_omac1(hash_check, (u8 *)_sce_find_ci_npdrm(ctxt), 0x60, ci_key, KEYBITS(0x10)); + if (memcmp(hash_check, np->hash_ci, 0x10) != 0) + { + if((dev_klicensee_by_content_id((s8 *)np->content_id, npdrm_key)) == FALSE) + return FALSE; + } + else + memcpy(npdrm_key, ks_np_klic_free->erk, 0x10); } - else if(np->license_type == NP_LICENSE_LOCAL) + else if(_ES32(np->license_type) == NP_LICENSE_LOCAL || _ES32(np->license_type) == NP_LICENSE_NETWORK ) { if ((klicensee_by_content_id((s8 *)np->content_id, npdrm_key)) == FALSE) return FALSE; @@ -80,6 +95,11 @@ BOOL np_decrypt_npdrm(sce_buffer_ctxt_t *ctxt) else return FALSE; + if(_raw == TRUE) + { + _hexdump(stdout, "[*] Klicensee:", 0, npdrm_key, sizeof(npdrm_key), FALSE); + } + aes_setkey_dec(&aes_ctxt, ks_klic_key->erk, METADATA_INFO_KEYBITS); aes_crypt_ecb(&aes_ctxt, AES_DECRYPT, npdrm_key, npdrm_key); @@ -90,7 +110,7 @@ BOOL np_decrypt_npdrm(sce_buffer_ctxt_t *ctxt) return TRUE; } -BOOL np_encrypt_npdrm(sce_buffer_ctxt_t *ctxt) +bool np_encrypt_npdrm(sce_buffer_ctxt_t *ctxt) { aes_context aes_ctxt; keyset_t *ks_np_klic_free, *ks_klic_key; @@ -107,14 +127,14 @@ BOOL np_encrypt_npdrm(sce_buffer_ctxt_t *ctxt) return FALSE; if(_klicensee_key != NULL) memcpy(npdrm_key, _klicensee_key, 0x10); - else if(np->license_type == NP_LICENSE_FREE) + else if(_ES32(np->license_type) == NP_LICENSE_FREE) { ks_np_klic_free = keyset_find_by_name(CONFIG_NP_KLIC_FREE_KNAME); if(ks_np_klic_free == NULL) return FALSE; memcpy(npdrm_key, ks_np_klic_free->erk, 0x10); } - else if(np->license_type == NP_LICENSE_LOCAL) + else if(_ES32(np->license_type) == NP_LICENSE_LOCAL) { if ((klicensee_by_content_id((s8 *)np->content_id, npdrm_key)) == FALSE) return FALSE; @@ -132,7 +152,7 @@ BOOL np_encrypt_npdrm(sce_buffer_ctxt_t *ctxt) return TRUE; } -BOOL np_create_ci(npdrm_config_t *npconf, ci_data_npdrm_t *cinp) +bool np_create_ci(npdrm_config_t *npconf, ci_data_npdrm_t *cinp) { u32 i, len; u8 *cid_fname, ci_key[0x10]; @@ -145,7 +165,7 @@ BOOL np_create_ci(npdrm_config_t *npconf, ci_data_npdrm_t *cinp) if(ks_np_tid == NULL || ks_np_ci == NULL) return FALSE; - //Can only create NPDRM SELF with local and free license. + //Can only create NPDRM SELF with "local" and free license. if(_klicensee_key != NULL) memcpy(npdrm_key, _klicensee_key, 0x10); else if(npconf->license_type == NP_LICENSE_FREE) @@ -163,22 +183,14 @@ BOOL np_create_ci(npdrm_config_t *npconf, ci_data_npdrm_t *cinp) else return FALSE; - cinp->magic = NP_CI_MAGIC; - cinp->unknown_0 = 1; - cinp->license_type = npconf->license_type; - cinp->app_type = npconf->app_type; + cinp->magic = _ES32(NP_CI_MAGIC); + cinp->version = _ES32(1); + cinp->license_type = _ES32(npconf->license_type); + cinp->app_type = _ES32(npconf->app_type); memcpy(cinp->content_id, npconf->content_id, 0x30); - #ifdef CONFIG_PRIVATE_BUILD - _fill_rand_bytes(cinp->rndpad, 0x10); - #else - //Better than boring random bytes! - memcpy(cinp->rndpad, CONFIG_NPDRM_WATERMARK, 0x10); - #endif - cinp->unknown_1 = 0; - cinp->unknown_2 = 0; - - //Fixup before hashing. - _es_ci_data_npdrm(cinp); + _fill_rand_bytes(cinp->rndpad, 0x10); + cinp->limited_time_start = _ES64(0); + cinp->limited_time_end = _ES64(0); //Generate control info hash key. for(i = 0; i < 0x10; i++) @@ -199,7 +211,7 @@ BOOL np_create_ci(npdrm_config_t *npconf, ci_data_npdrm_t *cinp) //TODO: The fwrite/fread error checking was broken. //Maybe the MS runtime is returning the number of bytes written instead of the element count? -BOOL np_sign_file(s8 *fname) +bool np_sign_file(s8 *fname) { u8 padding_data[0x10] = { diff --git a/np.h b/src/np.h similarity index 76% rename from np.h rename to src/np.h index eff5309..1b47851 100644 --- a/np.h +++ b/src/np.h @@ -28,15 +28,15 @@ typedef struct _npdrm_config void np_set_klicensee(u8 *klicensee); /*! Remove NPDRM layer. */ -BOOL np_decrypt_npdrm(sce_buffer_ctxt_t *ctxt); +bool np_decrypt_npdrm(sce_buffer_ctxt_t *ctxt); /*! Add NPDRM layer. */ -BOOL np_encrypt_npdrm(sce_buffer_ctxt_t *ctxt); +bool np_encrypt_npdrm(sce_buffer_ctxt_t *ctxt); /*! Create NPDRM control info. */ -BOOL np_create_ci(npdrm_config_t *npconf, ci_data_npdrm_t *cinp); +bool np_create_ci(npdrm_config_t *npconf, ci_data_npdrm_t *cinp); /*! Add NP signature to file. */ -BOOL np_sign_file(s8 *fname); +bool np_sign_file(s8 *fname); #endif diff --git a/pkg.cpp b/src/pkg.cpp similarity index 100% rename from pkg.cpp rename to src/pkg.cpp diff --git a/pkg.h b/src/pkg.h similarity index 100% rename from pkg.h rename to src/pkg.h diff --git a/rvk.cpp b/src/rvk.cpp similarity index 85% rename from rvk.cpp rename to src/rvk.cpp index 8d1e75a..8119df0 100644 --- a/rvk.cpp +++ b/src/rvk.cpp @@ -28,7 +28,7 @@ static void _print_rvk_header(FILE *fp, rvk_header_t *h) /* typedef struct _prg_rvk_entry { - u32 self_type; //3, 4 + u32 program_type; //3, 4 u32 unk_1; //1, 3 union { @@ -65,11 +65,11 @@ static void _print_prg_rvk_entry(FILE *fp, prg_rvk_entry_t *e) { const s8 *name; - name = _get_name(_self_types, e->self_type); + name = _get_name(_program_types, e->program_type); if(name != NULL) fprintf(fp, " %-19s ", name); else - fprintf(fp, " 0x%08X ", e->self_type); + fprintf(fp, " 0x%08X ", e->program_type); name = _get_name(_check_type_values, e->check_type); if(name != NULL) @@ -94,7 +94,7 @@ void rvk_print(FILE *fp, sce_buffer_ctxt_t *ctxt) { u32 i; - rvk_header_t *rvkh = (rvk_header_t *)(ctxt->scebuffer + ctxt->metash[0].data_offset); + rvk_header_t *rvkh = (rvk_header_t *)(ctxt->scebuffer + _ES64(ctxt->metash[0].data_offset)); _es_rvk_header(rvkh); _print_rvk_header(fp, rvkh); @@ -102,7 +102,7 @@ void rvk_print(FILE *fp, sce_buffer_ctxt_t *ctxt) //Program revoke. if(rvkh->type_0 == 4) { - prg_rvk_entry_t *ent = (prg_rvk_entry_t *)(ctxt->scebuffer + ctxt->metash[1].data_offset); + prg_rvk_entry_t *ent = (prg_rvk_entry_t *)(ctxt->scebuffer + _ES64(ctxt->metash[1].data_offset)); _print_prg_rvk_entry_header(fp); for(i = 0; i < rvkh->entcnt; i++) { @@ -113,7 +113,7 @@ void rvk_print(FILE *fp, sce_buffer_ctxt_t *ctxt) else if(rvkh->type_0 == 3) { fprintf(fp, "[*] Package Revoke List Entries:\n"); - u8 *ent = (u8 *)(ctxt->scebuffer + ctxt->metash[1].data_offset); + u8 *ent = (u8 *)(ctxt->scebuffer + _ES64(ctxt->metash[1].data_offset)); for(i = 0; i < rvkh->entcnt; i++) { _hexdump(fp, " ent", i*0x20, ent, 0x20, TRUE); diff --git a/rvk.h b/src/rvk.h similarity index 96% rename from rvk.h rename to src/rvk.h index 52ce830..be035ba 100644 --- a/rvk.h +++ b/src/rvk.h @@ -58,7 +58,7 @@ static inline void _es_rvk_header(rvk_header_t *h) /*! Program revoke list entry. */ typedef struct _prg_rvk_entry { - u32 self_type; //3, 4 + u32 program_type; //3, 4 u32 check_type; u64 version; union @@ -71,7 +71,7 @@ typedef struct _prg_rvk_entry static inline void _es_prg_rvk_entry(prg_rvk_entry_t *e) { - e->self_type = _ES32(e->self_type); + e->program_type = _ES32(e->program_type); e->check_type = _ES32(e->check_type); e->version = _ES64(e->version); e->auth_id = _ES64(e->auth_id); diff --git a/src/sce.cpp b/src/sce.cpp new file mode 100644 index 0000000..9167999 --- /dev/null +++ b/src/sce.cpp @@ -0,0 +1,1125 @@ +/* +* Copyright (c) 2011-2013 by naehrwert +* Copyright (c) 2011-2012 by Youness Alaoui +* This file is released under the GPLv2. +*/ +#define _CRT_SECURE_NO_WARNINGS + +#include +#include +#include +#include + +#include "types.h" +#include "util.h" +#include "elf.h" +#include "sce.h" +#include "sce_inlines.h" +#include "keys.h" +#include "aes.h" +#include "sha1.h" +#include "ecdsa.h" +#include "tables.h" +#include "config.h" +#include "zlib.h" +#include "np.h" + +void _print_cert_file_header(FILE *fp, cert_file_header_t *h) +{ + const s8 *name; + const s8 *key_revision; + + fprintf(fp, "[*] Certified File Header:\n"); + fprintf(fp, " Magic 0x%08X [%s]\n", _ES32(h->magic), (_ES32(h->magic) == CF_MAGIC ? "OK" : "ERROR")); + fprintf(fp, " Version 0x%08X\n", _ES32(h->version)); + + if(_ES16(h->key_revision) == KEY_REVISION_DEBUG) + fprintf(fp, " Key Revision [DEBUG]\n"); + else + fprintf(fp, " Key Revision 0x%04X\n", _ES16(h->key_revision)); + + name = _get_name(_cert_file_categories, _ES16(h->category)); + if(name != NULL) + { + fprintf(fp, " Category "); + _PRINT_RAW(fp, "0x%04X ", _ES16(h->category)); + fprintf(fp, "[%s]\n", name); + } + else + fprintf(fp, " Category 0x%04X\n", _ES16(h->category)); + + fprintf(fp, " Ext Header Size 0x%08X\n", _ES32(h->ext_header_size)); + fprintf(fp, " File Offset 0x%016llX\n", _ES64(h->file_offset)); + fprintf(fp, " File Size 0x%016llX\n", _ES64(h->file_size)); +} + +void _print_metadata_info(FILE *fp, metadata_info_t *mi) +{ + fprintf(fp, "[*] Encryption Root Header:\n"); + _hexdump(fp, " Key", 0, mi->key, METADATA_INFO_KEY_LEN, FALSE); + _hexdump(fp, " ", 0, mi->key_pad, METADATA_INFO_KEY_LEN, FALSE); + _hexdump(fp, " IV ", 0, mi->iv, METADATA_INFO_IV_LEN, FALSE); + _hexdump(fp, " ", 0, mi->iv_pad, METADATA_INFO_IV_LEN, FALSE); +} + +void _print_metadata_header(FILE *fp, metadata_header_t *mh) +{ + const s8 *sig_algo; + sig_algo = _get_name(_sig_algorithms, _ES32(mh->sig_algorithm)); + + + fprintf(fp, "[*] Metadata Header:\n"); + fprintf(fp, " Signature Input Length 0x%016llX\n", _ES64(mh->sig_input_length)); + if(sig_algo != NULL) + { + fprintf(fp, " Signature Algorithm "); + _PRINT_RAW(fp, "0x%08X ", _ES32(mh->sig_algorithm)); + fprintf(fp, "[%s]\n", sig_algo); + } + else + fprintf(fp, " Signature Algorithm 0x%08X\n", _ES32(mh->sig_algorithm)); + fprintf(fp, " Section Count 0x%08X\n", _ES32(mh->section_count)); + fprintf(fp, " Key Count 0x%08X\n", _ES32(mh->key_count)); + fprintf(fp, " Optional Header Size 0x%08X\n", _ES32(mh->opt_header_size)); + fprintf(fp, " unknown_1 0x%08X\n", _ES32(mh->unknown_1)); + fprintf(fp, " unknown_2 0x%08X\n", _ES32(mh->unknown_2)); +} + +static void _print_metadata_section_header_header(FILE *fp) +{ + fprintf(fp, "[*] Metadata Section Headers:\n"); + fprintf(fp, " Idx Offset Size Type Index Hashed SHA1 Encrypted Key IV Compressed\n"); +} + +void _print_metadata_section_header(FILE *fp, metadata_section_header_t *msh, u32 idx) +{ + const s8 *name; + name = _get_name(_msh_types, _ES32(msh->type)); + + fprintf(fp, " %03d %08llX %08llX %s %02X ", + idx, _ES64(msh->data_offset), _ES64(msh->data_size), name, _ES32(msh->index)); + + if(_ES32(msh->hashed) == METADATA_SECTION_HASHED) + fprintf(fp, "[YES] %02X ", _ES32(msh->sha1_index)); + else + fprintf(fp, "[NO ] -- "); + + if(_ES32(msh->encrypted) == METADATA_SECTION_ENCRYPTED) + fprintf(fp, "[YES] %02X %02X ", _ES32(msh->key_index), _ES32(msh->iv_index)); + else + fprintf(fp, "[NO ] -- -- "); + + if(_ES32(msh->compressed) == METADATA_SECTION_COMPRESSED) + fprintf(fp, "[YES]\n"); + else + fprintf(fp, "[NO ]\n"); +} + +void _print_sce_file_keys(FILE *fp, sce_buffer_ctxt_t *ctxt) +{ + u32 i; + + //Get start of keys. + u8 *keys = (u8 *)ctxt->metash + sizeof(metadata_section_header_t) * _ES32(ctxt->metah->section_count); + + fprintf(fp, "[*] SCE File Keys:\n"); + for(i = 0; i < _ES32(ctxt->metah->key_count); i++) + { + fprintf(fp, " %02X:", i); + _hexdump(fp, "", i, keys+i*0x10, 0x10, FALSE); + } +} + +void _print_sce_signature(FILE *fp, signature_t *sig) +{ + fprintf(fp, "[*] Signature Info:\n"); + _hexdump(fp, " R", 0, sig->r, SIGNATURE_R_SIZE, FALSE); + _hexdump(fp, " S", 0, sig->s, SIGNATURE_S_SIZE, FALSE); +} + +void _print_sce_signature_status(FILE *fp, sce_buffer_ctxt_t *ctxt, u8 *keyset) +{ + u8 hash[0x14]; + u8 Q[0x28]; + u8 K[0x14]; + u8 zero_buf[0x14]; + keyset_t *ks; + + //Check if a keyset is provided. + if(keyset == NULL) + { + //Get previously used keyset + ks = get_used_keyset(); + } + else + { + //Use the provided keyset. + ks = keyset_from_buffer(keyset); + } + + //Generate header hash. + sha1(ctxt->scebuffer, _ES64(ctxt->metah->sig_input_length), hash); + _hexdump(fp, " H", 0, hash, 0x14, FALSE); + + //get curve params + u8 *ec_p = (u8 *)malloc(sizeof(u8) * 20); + u8 *ec_a = (u8 *)malloc(sizeof(u8) * 20); + u8 *ec_b = (u8 *)malloc(sizeof(u8) * 20); + u8 *ec_N = (u8 *)malloc(sizeof(u8) * 21); + u8 *ec_Gx = (u8 *)malloc(sizeof(u8) * 20); + u8 *ec_Gy = (u8 *)malloc(sizeof(u8) * 20); + memset(ec_p, 0, 20); + memset(ec_a, 0, 20); + memset(ec_b, 0, 20); + memset(ec_N, 0, 21); + memset(ec_Gx, 0, 20); + memset(ec_Gy, 0, 20); + //Print curve order N + if (ecdsa_get_params(ks->ctype, ec_p, ec_a, ec_b, ec_N, ec_Gx, ec_Gy) == 0) + _hexdump (fp, " N", 0, ec_N + 1, 20, FALSE); + + //Set ecdsa params + ecdsa_set_curve(ks->ctype); + ecdsa_set_pub(ks->pub); + + //Validate private key and calculate K + ec_priv_to_pub(ks->priv, Q); + get_m(ctxt->sig->r, ctxt->sig->s, hash, ks->priv, K); + if (memcmp(ks->pub, Q, sizeof(Q)) == 0) + _hexdump (fp, " K", 0, K, 0x14, FALSE); + + //Validate the signature. + memset(zero_buf, 0, sizeof(zero_buf)); + if ((memcmp(ctxt->sig->r, zero_buf, sizeof(zero_buf)) == 0) || (memcmp(ctxt->sig->s, zero_buf, sizeof(zero_buf)) == 0)) + fprintf(fp, "[*] Signature status: FAIL\n"); + else + fprintf(fp, "[*] Signature status: %s\n", (ecdsa_verify(hash, ctxt->sig->r, ctxt->sig->s) == TRUE ? "OK" : "FAIL")); +} + +static sce_buffer_ctxt_t *_sce_create_ctxt() +{ + sce_buffer_ctxt_t *res; + + if((res = (sce_buffer_ctxt_t *)malloc(sizeof(sce_buffer_ctxt_t))) == NULL) + return NULL; + + memset(res, 0, sizeof(sce_buffer_ctxt_t)); + + res->scebuffer = NULL; + res->mdec = TRUE; + + //Allocate Cert file header. + res->cfh = (cert_file_header_t *)malloc(sizeof(cert_file_header_t)); + memset(res->cfh, 0, sizeof(cert_file_header_t)); + + //Allocate metadata info (with random key/iv). + res->metai = (metadata_info_t *)malloc(sizeof(metadata_info_t)); + _fill_rand_bytes(res->metai->key, 0x10); + memset(res->metai->key_pad, 0, 0x10); + _fill_rand_bytes(res->metai->iv, 0x10); + memset(res->metai->iv_pad, 0, 0x10); + //Allocate metadata header. + res->metah = (metadata_header_t *)malloc(sizeof(metadata_header_t)); + //memset(res->metah, 0, sizeof(metadata_header_t)); + //Allocate signature. + res->sig = (signature_t *)malloc(sizeof(signature_t)); + + res->makeself = NULL; + + return res; +} + +sce_buffer_ctxt_t *sce_create_ctxt_from_buffer(u8 *scebuffer) +{ + sce_buffer_ctxt_t *res; + + if((res = (sce_buffer_ctxt_t *)malloc(sizeof(sce_buffer_ctxt_t))) == NULL) + return NULL; + + memset(res, 0, sizeof(sce_buffer_ctxt_t)); + + res->scebuffer = scebuffer; + res->mdec = FALSE; + + //Set pointer to Cert file header. + res->cfh = (cert_file_header_t *)scebuffer; + + //Set pointers to file type specific headers. + switch(_ES16(res->cfh->category)) + { + case CF_CATEGORY_SELF: + { + //SELF header. + res->self.selfh = (self_header_t *)(res->scebuffer + sizeof(cert_file_header_t)); + + //Program info. + res->self.ai = (app_info_t *)(res->scebuffer + _ES64(res->self.selfh->app_info_offset)); + + //Section infos. + if (_ES64(res->self.selfh->segment_info_offset) != NULL) + { + res->self.si = (segment_info_t *)(res->scebuffer + _ES64(res->self.selfh->segment_info_offset)); + } + else + res->self.si = 0; + + //SCE version. + if(_ES64(res->self.selfh->sce_version_offset) != NULL) + { + res->self.sv = (sce_version_t *)(res->scebuffer + _ES64(res->self.selfh->sce_version_offset)); + } + else + res->self.sv = 0; + + //Get pointers to all control infos. + if ((_ES64(res->self.selfh->control_info_offset)) != 0) + { + u32 len = (u32)(_ES64(res->self.selfh->control_info_size)); + if(len > 0) + { + u8 *ptr = res->scebuffer + _ES64(res->self.selfh->control_info_offset); + res->self.cis = list_create(); + + while(len > 0) + { + control_info_t *tci = (control_info_t *)ptr; + ptr += _ES32(tci->size); + len -= _ES32(tci->size); + list_add_back(res->self.cis, tci); + } + } + } + else + res->self.cis = NULL; + } + break; + case CF_CATEGORY_RVK: + //TODO + break; + case CF_CATEGORY_PKG: + //TODO + break; + case CF_CATEGORY_SPP: + //TODO + break; + default: + free(res); + return NULL; + break; + } + + //Set pointers to metadata headers. + res->metai = (metadata_info_t *)(scebuffer + sizeof(cert_file_header_t) + _ES32(res->cfh->ext_header_size)); + res->metah = (metadata_header_t *)((u8 *)res->metai + sizeof(metadata_info_t)); + res->metash = (metadata_section_header_t *)((u8 *)res->metah + sizeof(metadata_header_t)); + + return res; +} + +sce_buffer_ctxt_t *sce_create_ctxt_build_self(u8 *elf, u32 elf_len) +{ + sce_buffer_ctxt_t *res; + + if((res = _sce_create_ctxt()) == NULL) + return NULL; + + res->cfh->magic = _ES32(CF_MAGIC); + res->cfh->version = _ES32(CF_VERSION_2); + res->cfh->category = _ES16(CF_CATEGORY_SELF); + + //Allocate SELF header. + res->self.selfh = (self_header_t *)malloc(sizeof(self_header_t)); + memset(res->self.selfh, 0, sizeof(self_header_t)); + res->self.selfh->header_type = _ES64(SUB_HEADER_TYPE_SELF); + //Allocate program info. + res->self.ai = (app_info_t *)malloc(sizeof(app_info_t)); + memset(res->self.ai, 0, sizeof(app_info_t)); + //SCE version. + res->self.sv = (sce_version_t *)malloc(sizeof(sce_version_t)); + //Create control info list. + res->self.cis = list_create(); + //Create optional headers list. + res->self.ohs = list_create(); + + //Makeself context. + res->makeself = (makeself_ctxt_t *)malloc(sizeof(makeself_ctxt_t)); + memset(res->makeself, 0, sizeof(makeself_ctxt_t)); + //ELF buffer. + res->makeself->elf = elf; + res->makeself->elf_len = elf_len; + + //Section list. + res->secs = list_create(); + + return res; +} + +void sce_add_data_section(sce_buffer_ctxt_t *ctxt, void *buffer, u32 size, bool may_compr) +{ + sce_section_ctxt_t *sctxt = (sce_section_ctxt_t *)malloc(sizeof(sce_section_ctxt_t)); + sctxt->buffer = buffer; + sctxt->size = size; + sctxt->may_compr = may_compr; + list_add_back(ctxt->secs, sctxt); +} + +void sce_set_metash(sce_buffer_ctxt_t *ctxt, u32 type, bool encrypted, u32 idx) +{ + ctxt->metash[idx].type = _ES32(type); + ctxt->metash[idx].index = _ES32(_ES32(type) == METADATA_SECTION_TYPE_PHDR ? idx : _ES32(type) == METADATA_SECTION_TYPE_SHDR ? idx + 1 : idx); + ctxt->metash[idx].hashed = _ES32(METADATA_SECTION_HASHED); + ctxt->metash[idx].encrypted = _ES32(encrypted == TRUE ? METADATA_SECTION_ENCRYPTED : METADATA_SECTION_NOT_ENCRYPTED); + ctxt->metash[idx].compressed = _ES32(METADATA_SECTION_NOT_COMPRESSED); +} + +void sce_compress_data(sce_buffer_ctxt_t *ctxt) +{ + u32 i = 0; + uLongf size_comp, size_bound; + + LIST_FOREACH(iter, ctxt->secs) + { + sce_section_ctxt_t *sec = (sce_section_ctxt_t *)iter->value; + + //Check if the section may be compressed. + if(sec->may_compr == TRUE) + { + if(sec->size > 0) + { + size_comp = size_bound = compressBound(sec->size); + u8 *buf = (u8 *)malloc(sizeof(u8) * size_bound); + compress(buf, &size_comp, (const u8 *)sec->buffer, sec->size); + + if(size_comp < sec->size) + { + //Set compressed buffer and size. + sec->buffer = buf; + sec->size = size_comp; + + //Set compression in section info. + if(_ES16(ctxt->cfh->category) == CF_CATEGORY_SELF && i < ctxt->makeself->si_sec_cnt) + { + ctxt->self.si[i].compressed = SEGMENT_INFO_COMPRESSED; + //Update size too. + ctxt->self.si[i].size = size_comp; + } + + //Set compression in metadata section header. + ctxt->metash[i].compressed = _ES32(METADATA_SECTION_COMPRESSED); + } + else + { + free(buf); + _LOG_VERBOSE("Skipped compression of section %03d (0x%08X >= 0x%08X)\n", i, size_comp, sec->size); + } + } + else + _LOG_VERBOSE("Skipped compression of section %03d (size is zero)\n", i); + } + + i++; + } +} + +static u32 _sce_get_ci_len(sce_buffer_ctxt_t *ctxt) +{ + u32 res = 0; + + LIST_FOREACH(iter, ctxt->self.cis) + res += _ES32(((control_info_t *)iter->value)->size); + + return res; +} + +static u32 _sce_get_oh_len(sce_buffer_ctxt_t *ctxt) +{ + u32 res = 0; + + LIST_FOREACH(iter, ctxt->self.ohs) + res += _ES32(((opt_header_t *)iter->value)->size); + + return res; +} + +void _sce_fixup_ctxt(sce_buffer_ctxt_t *ctxt) +{ + u32 i = 0, base_off, last_off; + + //Set section info data. + base_off = _ES64(ctxt->cfh->file_offset); + LIST_FOREACH(iter, ctxt->secs) + { + //Save last offset. + last_off = base_off; + + //Section offsets. + sce_section_ctxt_t *sec = (sce_section_ctxt_t *)iter->value; + sec->offset = base_off; + + //Section infos for SELF (that are present as data sections). + if(_ES16(ctxt->cfh->category) == CF_CATEGORY_SELF && i < ctxt->makeself->si_sec_cnt) + //{ + ctxt->self.si[i].offset = base_off; + // ctxt->self.si[i].size = sec->size; + //} + + //Metadata section headers. + ctxt->metash[i].data_offset = _ES64(base_off); + ctxt->metash[i].data_size = _ES64(sec->size); + + //Update offset and data length. + base_off += sec->size; + ctxt->cfh->file_size = _ES64(base_off - _ES64(ctxt->cfh->file_offset)); + base_off = ALIGN(base_off, SCE_ALIGN); + + i++; + } + + //Set metadata offset (counted from after Cert file header). + ctxt->cfh->ext_header_size = _ES32(ctxt->off_metai - sizeof(cert_file_header_t)); + + //Set metadata header values. + ctxt->metah->sig_input_length = _ES64(ctxt->off_sig); + ctxt->metah->sig_algorithm = _ES32(SIGNATURE_ALGORITHM_ECDSA); + ctxt->metah->opt_header_size = _ES32(_sce_get_oh_len(ctxt)); + ctxt->metah->unknown_1 = _ES32(0); + ctxt->metah->unknown_2 = _ES32(0); + + switch(_ES16(ctxt->cfh->category)) + { + case CF_CATEGORY_SELF: + { + //Set header offsets. + ctxt->self.selfh->app_info_offset = _ES64(ctxt->off_self.off_ai); + ctxt->self.selfh->elf_offset = _ES64(ctxt->off_self.off_ehdr); + ctxt->self.selfh->phdr_offset = _ES64(ctxt->off_self.off_phdr); + ctxt->self.selfh->segment_info_offset = _ES64(ctxt->off_self.off_si); + ctxt->self.selfh->sce_version_offset = _ES64(ctxt->off_self.off_sv); + ctxt->self.selfh->control_info_offset = _ES64(ctxt->off_self.off_cis); + ctxt->self.selfh->control_info_size = _ES64(_sce_get_ci_len(ctxt)); + + //Set section headers offset in SELF header (last data section) if available. + if(ctxt->makeself->shdrs != NULL) + ctxt->self.selfh->shdr_offset = _ES64(last_off); + else + ctxt->self.selfh->shdr_offset = _ES64(0); + } + break; + case CF_CATEGORY_RVK: + //TODO + break; + case CF_CATEGORY_PKG: + //TODO + break; + case CF_CATEGORY_SPP: + //TODO + break; + default: + //TODO + break; + } +} + +void _sce_fixup_keys(sce_buffer_ctxt_t *ctxt) +{ + u32 i; + + //Build keys array. + ctxt->keys_len = 0; + ctxt->metah->key_count = _ES32(0); + for(i = 0; i < _ES32(ctxt->metah->section_count); i++) + { + if(_ES32(ctxt->metash[i].encrypted) == METADATA_SECTION_ENCRYPTED) + { + ctxt->keys_len += 0x80; //0x60 HMAC, 0x20 key/iv + ctxt->metah->key_count += _ES32(8); + ctxt->metash[i].sha1_index = _ES32(_ES32(ctxt->metah->key_count) - 8); + ctxt->metash[i].key_index = _ES32(_ES32(ctxt->metah->key_count) - 2); + ctxt->metash[i].iv_index = _ES32(_ES32(ctxt->metah->key_count) - 1); + } + else + { + ctxt->keys_len += 0x60; //0x60 HMAC + ctxt->metah->key_count += _ES32(6); + ctxt->metash[i].sha1_index = _ES32(_ES32(ctxt->metah->key_count) - 6); + ctxt->metash[i].key_index = _ES32(0xFFFFFFFF); + ctxt->metash[i].iv_index = _ES32(0xFFFFFFFF); + } + } + + //Allocate and fill keys array. + ctxt->keys = (u8 *)malloc(sizeof(u8) * ctxt->keys_len); + _fill_rand_bytes(ctxt->keys, ctxt->keys_len); +} + +/*! Increase offset and align it. */ +#define _INC_OFF_TYPE(off, type) off; \ + off += sizeof(type); \ + off = ALIGN(off, SCE_ALIGN) +#define _INC_OFF_SIZE(off, size) off; \ + off += (size); \ + off = ALIGN(off, SCE_ALIGN) + +void sce_layout_ctxt(sce_buffer_ctxt_t *ctxt) +{ + u32 coff = 0; + + //Cert file header. + ctxt->off_cfh = _INC_OFF_TYPE(coff, cert_file_header_t); + + switch(_ES16(ctxt->cfh->category)) + { + case CF_CATEGORY_SELF: + { + //SELF header. + ctxt->off_self.off_selfh = _INC_OFF_TYPE(coff, self_header_t); + //Program info. + ctxt->off_self.off_ai = _INC_OFF_TYPE(coff, app_info_t); + //ELF header. + ctxt->off_self.off_ehdr = _INC_OFF_SIZE(coff, ctxt->makeself->ehsize); + //ELF Program headers. + ctxt->off_self.off_phdr = _INC_OFF_SIZE(coff, ctxt->makeself->phsize); + //Section info. + ctxt->off_self.off_si = _INC_OFF_SIZE(coff, sizeof(segment_info_t) * ctxt->makeself->si_cnt); + //SCE version. + ctxt->off_self.off_sv = _INC_OFF_TYPE(coff, sce_version_t); + //Control infos. + ctxt->off_self.off_cis = _INC_OFF_SIZE(coff, _sce_get_ci_len(ctxt)); + } + break; + case CF_CATEGORY_RVK: + //TODO + break; + case CF_CATEGORY_PKG: + //TODO + break; + case CF_CATEGORY_SPP: + //TODO + break; + default: + //TODO + break; + } + + //Metadata info. + ctxt->off_metai = _INC_OFF_TYPE(coff, metadata_info_t); + //Metadata header. + ctxt->off_metah = _INC_OFF_TYPE(coff, metadata_header_t); + //Metadata section headers. + ctxt->off_metash = _INC_OFF_SIZE(coff, _ES32(ctxt->metah->section_count) * sizeof(metadata_section_header_t)); + //Keys. + _sce_fixup_keys(ctxt); + ctxt->off_keys = _INC_OFF_SIZE(coff, ctxt->keys_len); + + //SELF only headers. + if(_ES16(ctxt->cfh->category) == CF_CATEGORY_SELF) + { + //Optional headers. + ctxt->off_self.off_ohs = _INC_OFF_SIZE(coff, _sce_get_oh_len(ctxt)); + } + + //Signature. + ctxt->off_sig = _INC_OFF_TYPE(coff, signature_t); + + //Header padding. + ctxt->off_hdrpad = coff; + coff = ALIGN(coff, HEADER_ALIGN); + + //Set header length. + ctxt->cfh->file_offset = _ES64(coff); + + //Set missing values, etc. + _sce_fixup_ctxt(ctxt); +} + +static void _sce_build_header(sce_buffer_ctxt_t *ctxt) +{ + u32 i; + + //Allocate header buffer. + ctxt->scebuffer = (u8*)malloc(sizeof(u8) * _ES64(ctxt->cfh->file_offset)); + memset(ctxt->scebuffer, 0, sizeof(u8) * _ES64(ctxt->cfh->file_offset)); + + //Cert file header. + memcpy((cert_file_header_t *)(ctxt->scebuffer + ctxt->off_cfh), ctxt->cfh, sizeof(cert_file_header_t)); + + //File category dependent headers. + switch(_ES16(ctxt->cfh->category)) + { + case CF_CATEGORY_SELF: + { + //SELF header. + memcpy((self_header_t *)(ctxt->scebuffer + ctxt->off_self.off_selfh), ctxt->self.selfh, sizeof(self_header_t)); + //Program info. + memcpy((app_info_t *)(ctxt->scebuffer + ctxt->off_self.off_ai), ctxt->self.ai, sizeof(app_info_t)); + //ELF header. + memcpy(ctxt->scebuffer + ctxt->off_self.off_ehdr, ctxt->makeself->ehdr, ctxt->makeself->ehsize); + //ELF program headers. + memcpy(ctxt->scebuffer + ctxt->off_self.off_phdr, ctxt->makeself->phdrs, ctxt->makeself->phsize); + + //Section info. + u32 i; + for(i = 0; i < ctxt->makeself->si_cnt; i++) + _copy_es_segment_info((segment_info_t *)(ctxt->scebuffer + ctxt->off_self.off_si + sizeof(segment_info_t) * i), &ctxt->self.si[i]); + + //SCE version. + memcpy((sce_version_t *)(ctxt->scebuffer + ctxt->off_self.off_sv), ctxt->self.sv, sizeof(sce_version_t)); + + //Control infos. + u32 ci_base = ctxt->off_self.off_cis; + LIST_FOREACH(iter, ctxt->self.cis) + { + control_info_t *ci = (control_info_t *)iter->value; + + //Copy control info header. + memcpy((control_info_t *)(ctxt->scebuffer + ci_base), ci, sizeof(control_info_t)); + //Copy data. + memcpy(ctxt->scebuffer + ci_base + sizeof(control_info_t), ((u8 *)ci) + sizeof(control_info_t), _ES32(ci->size) - sizeof(control_info_t)); + + ci_base += _ES32(ci->size); + } + } + break; + case CF_CATEGORY_RVK: + //TODO + break; + case CF_CATEGORY_PKG: + //TODO + break; + case CF_CATEGORY_SPP: + //TODO + break; + default: + //TODO + break; + } + + //Metadata info. + memcpy(ctxt->scebuffer + ctxt->off_metai, ctxt->metai, sizeof(metadata_info_t)); + //Metadata header. + memcpy((metadata_header_t *)(ctxt->scebuffer + ctxt->off_metah), ctxt->metah, sizeof(metadata_header_t)); + //Metadata section headers. + for(i = 0; i < _ES32(ctxt->metah->section_count); i++) + memcpy((metadata_section_header_t *)(ctxt->scebuffer + ctxt->off_metash + sizeof(metadata_section_header_t) * i), &ctxt->metash[i], sizeof(metadata_section_header_t)); + + //Keys. + //memcpy(ctxt->scebuffer + ctxt->off_keys, ctxt->keys, ctxt->keys_len); + + //SELF only headers. + if(_ES16(ctxt->cfh->category) == CF_CATEGORY_SELF) + { + //Optional headers. + u32 oh_base = ctxt->off_self.off_ohs; + LIST_FOREACH(iter, ctxt->self.ohs) + { + opt_header_t *oh = (opt_header_t *)iter->value; + + //Copy optional header. + memcpy((opt_header_t *)(ctxt->scebuffer + oh_base), oh, sizeof(opt_header_t)); + //Copy data. + memcpy(ctxt->scebuffer + oh_base + sizeof(opt_header_t), ((u8 *)oh) + sizeof(opt_header_t), _ES32(oh->size) - sizeof(opt_header_t)); + + oh_base += _ES32(oh->size); + } + } +} + +static bool _sce_sign_header(sce_buffer_ctxt_t *ctxt, keyset_t *ks) +{ + u8 hash[0x14]; + + //Well... + if(ks->priv == NULL || ks->pub == NULL) + return FALSE; + + //Generate header hash. + sha1(ctxt->scebuffer, _ES64(ctxt->metah->sig_input_length), hash); + + //Generate signature. + ecdsa_set_curve(ks->ctype); + ecdsa_set_pub(ks->pub); + ecdsa_set_priv(ks->priv); + ecdsa_sign(hash, ctxt->sig->r, ctxt->sig->s); + + //Copy Signature. + memcpy(ctxt->scebuffer + ctxt->off_sig, ctxt->sig, sizeof(signature_t)); + + return TRUE; +} + +static void _sce_calculate_hashes(sce_buffer_ctxt_t *ctxt) +{ + u32 i = 0, sha1_idx; + + LIST_FOREACH(iter, ctxt->secs) + { + sce_section_ctxt_t *sec = (sce_section_ctxt_t *)iter->value; + + sha1_idx = _ES32(ctxt->metash[i].sha1_index); + memset(ctxt->keys + sha1_idx * 0x10, 0, 0x20); + sha1_hmac(ctxt->keys + (sha1_idx + 2) * 0x10, 0x40, (u8 *)sec->buffer, sec->size, ctxt->keys + sha1_idx * 0x10); + + i++; + } +} + +static bool _sce_encrypt_header(sce_buffer_ctxt_t *ctxt, u8 *keyset) +{ + u8 *ptr; + size_t nc_off; + u8 sblk[0x10], iv[0x10]; + keyset_t *ks; + aes_context aes_ctxt; + + //Check if a keyset is provided. + if(keyset == NULL) + { + //Try to find keyset. + if((ks = keyset_find(ctxt)) == NULL) + return FALSE; + } + else + { + //Use the provided keyset. + ks = keyset_from_buffer(keyset); + } + + //Calculate hashes. + _sce_calculate_hashes(ctxt); + + //Copy keys. + memcpy(ctxt->scebuffer + ctxt->off_keys, ctxt->keys, ctxt->keys_len); + + //Sign header. + _sce_sign_header(ctxt, ks); + + //Encrypt metadata header, metadata section headers and keys. + nc_off = 0; + ptr = ctxt->scebuffer + ctxt->off_metah; + aes_setkey_enc(&aes_ctxt, ctxt->metai->key, METADATA_INFO_KEYBITS); + memcpy(iv, ctxt->metai->iv, 0x10); + aes_crypt_ctr(&aes_ctxt, + _ES64(ctxt->cfh->file_offset) - (sizeof(cert_file_header_t) + _ES32(ctxt->cfh->ext_header_size) + sizeof(metadata_info_t)), + &nc_off, iv, sblk, ptr, ptr); + + //Encrypt metadata info. + aes_setkey_enc(&aes_ctxt, ks->erk, KEYBITS(ks->erklen)); + ptr = ctxt->scebuffer + ctxt->off_metai; + aes_crypt_cbc(&aes_ctxt, AES_ENCRYPT, sizeof(metadata_info_t), ks->riv, ptr, ptr); + + //Add NPDRM layer. + if(_ES16(ctxt->cfh->category) == CF_CATEGORY_SELF && _ES32(ctxt->self.ai->program_type) == PROGRAM_TYPE_NPDRM) + if(np_encrypt_npdrm(ctxt) == FALSE) + return FALSE; + + return TRUE; +} + +static void _sce_encrypt_data(sce_buffer_ctxt_t *ctxt) +{ + u32 i = 0; + aes_context aes_ctxt; + + LIST_FOREACH(iter, ctxt->secs) + { + sce_section_ctxt_t *sec = (sce_section_ctxt_t *)iter->value; + + size_t nc_off = 0; + u8 buf[16]; + u8 iv[16]; + + if(_ES32(ctxt->metash[i].encrypted) == METADATA_SECTION_ENCRYPTED) + { + memcpy(iv, ctxt->keys + _ES32(ctxt->metash[i].iv_index) * 0x10, 0x10); + aes_setkey_enc(&aes_ctxt, ctxt->keys + _ES32(ctxt->metash[i].key_index) * 0x10, 128); + aes_crypt_ctr(&aes_ctxt, sec->size, &nc_off, iv, buf, (u8 *)sec->buffer, (u8 *)sec->buffer); + } + + i++; + } +} + +bool sce_encrypt_ctxt(sce_buffer_ctxt_t *ctxt, u8 *keyset) +{ + //Build SCE file header. + _sce_build_header(ctxt); + + //Encrypt header. + if(_sce_encrypt_header(ctxt, keyset) == FALSE) + return FALSE; + + //Encrypt data. + _sce_encrypt_data(ctxt); + + return TRUE; +} + +bool sce_write_ctxt(sce_buffer_ctxt_t *ctxt, s8 *fname) +{ + FILE *fp; + + if((fp = fopen(fname, "wb")) == NULL) + return FALSE; + + //Write SCE file header. + fwrite(ctxt->scebuffer, sizeof(u8), _ES64(ctxt->cfh->file_offset), fp); + + //Write SCE file sections. + LIST_FOREACH(iter, ctxt->secs) + { + sce_section_ctxt_t *sec = (sce_section_ctxt_t *)iter->value; + fseek(fp, sec->offset, SEEK_SET); + fwrite(sec->buffer, sizeof(u8), sec->size, fp); + } + + fclose(fp); + + return TRUE; +} +//refactoring needed +static bool check_for_old_algorithm(sce_buffer_ctxt_t *ctxt, keyset_t *ks) +{ + u8 *test_buf = (u8 *)malloc(sizeof(u8) * 0x50); + u8 *test_buf2 = (u8 *)malloc(sizeof(u8) * 0x50); + u8 *iv = (u8 *)malloc(sizeof(u8) * 0x10); + u8 *sblk = (u8 *)malloc(sizeof(u8) * 0x10); + u8 *ctr_iv = (u8 *)malloc(sizeof(u8) * 0x10); + aes_context aes_ctxt; + size_t nc_off; + u64 sig_input_length; + u32 sig_algo, section_count; + + memcpy(test_buf, ctxt->metai, 0x50); + + memcpy(test_buf2, test_buf, 0x50); + nc_off = 0; + + memcpy(test_buf2, test_buf, 0x50); + memcpy(iv, ks->riv, 0x10); + aes_setkey_enc(&aes_ctxt, ks->erk, KEYBITS(ks->erklen)); + aes_crypt_ctr(&aes_ctxt, 0x40, &nc_off, iv, sblk, test_buf2, test_buf2); + + nc_off = 0; + memcpy (ctr_iv, (test_buf2 + 0x20) ,0x10); + aes_setkey_enc(&aes_ctxt, test_buf2, METADATA_INFO_KEYBITS); + aes_crypt_ctr(&aes_ctxt, 0x10, &nc_off, ctr_iv, sblk, (test_buf2 + 0x40), (test_buf2 + 0x40)); + + sig_input_length = _ES64(*(u64*)&test_buf2[0x40]); + sig_algo = _ES32(*(u32*)&test_buf2[0x48]); + section_count = _ES32(*(u32*)&test_buf2[0x4C]); + + if((sig_input_length < _ES64(ctxt->cfh->file_offset)) && sig_algo == 1 && section_count < 0xFF) + return true; + + return false; +} +//refactoring needed +bool sce_decrypt_header(sce_buffer_ctxt_t *ctxt, u8 *metadata_info, u8 *keyset) +{ + u32 i; + size_t nc_off; + u8 sblk[0x10], iv[0x10], ctr_iv[0x10]; + keyset_t *ks; + aes_context aes_ctxt; + + //Check if provided metadata info should be used. + if(metadata_info == NULL) + { + //Remove NPDRM layer. + if(_ES16(ctxt->cfh->category) == CF_CATEGORY_SELF && _ES32(ctxt->self.ai->program_type) == PROGRAM_TYPE_NPDRM) + if(np_decrypt_npdrm(ctxt) == FALSE) + return FALSE; + + //Check if a keyset is provided. + if(keyset == NULL) + { + //Try to find keyset. + if((ks = keyset_bruteforce(ctxt)) == NULL) + return FALSE; + + _LOG_VERBOSE("Using keyset [%s 0x%04X %s]\n", ks->name, ks->key_revision, sce_version_to_str(ks->version)); + } + else + { + //Use the provided keyset. + ks = keyset_from_buffer(keyset); + } + + //Decrypt metadata info. + + nc_off = 0; + + memcpy(iv, ks->riv, 0x10); //!!! + if (check_for_old_algorithm(ctxt, ks) == false) + { + aes_setkey_dec(&aes_ctxt, ks->erk, KEYBITS(ks->erklen)); + aes_crypt_cbc(&aes_ctxt, AES_DECRYPT, sizeof(metadata_info_t), iv, (u8 *)ctxt->metai, (u8 *)ctxt->metai); + } + else + { + aes_setkey_enc(&aes_ctxt, ks->erk, KEYBITS(ks->erklen)); + aes_crypt_ctr(&aes_ctxt, sizeof(metadata_info_t), &nc_off, iv, sblk, (u8 *)ctxt->metai, (u8 *)ctxt->metai); + } + } + else + { + //Copy provided metadata info over SELF metadata. + memcpy((u8 *)ctxt->metai, metadata_info, sizeof(metadata_info)); + } + + //Decrypt metadata header, metadata section headers and keys. + nc_off = 0; + memcpy (ctr_iv, ctxt->metai->iv ,0x10); + aes_setkey_enc(&aes_ctxt, ctxt->metai->key, METADATA_INFO_KEYBITS); + aes_crypt_ctr(&aes_ctxt, + _ES64(ctxt->cfh->file_offset) - (sizeof(cert_file_header_t) + _ES32(ctxt->cfh->ext_header_size) + sizeof(metadata_info_t)), + &nc_off, ctr_iv, sblk, (u8 *)ctxt->metah, (u8 *)ctxt->metah); + + //Check if the metadata was decrypted properly. + if (_ES64(ctxt->metah->sig_input_length) > _ES64(ctxt->cfh->file_offset)) + return FALSE; + + //Metadata decrypted. + ctxt->mdec = TRUE; + + //Set start of SCE file keys. + ctxt->keys = (u8 *)ctxt->metash + sizeof(metadata_section_header_t) * _ES32(ctxt->metah->section_count); + ctxt->keys_len = _ES32(ctxt->metah->key_count) * 0x10; + + //Set SELF only headers. + if((_ES16(ctxt->cfh->category) == CF_CATEGORY_SELF) && (_ES64(ctxt->metah->opt_header_size) > 0)) + { + //Get pointers to all optional headers. + ctxt->self.ohs = list_create(); + opt_header_t *oh = (opt_header_t *)(ctxt->keys + _ES32(ctxt->metah->key_count) * 0x10); + list_add_back(ctxt->self.ohs, oh); + while(_ES64(oh->next) != 0) + { + oh = (opt_header_t *)((u8 *)oh + _ES32(oh->size)); + list_add_back(ctxt->self.ohs, oh); + } + + //Signature. + ctxt->sig = (signature_t *)((u8 *)oh + _ES32(oh->size)); + } + else + ctxt->sig = (signature_t *)(ctxt->keys + _ES32(ctxt->metah->key_count) * 0x10); + + return TRUE; +} + +bool sce_decrypt_data(sce_buffer_ctxt_t *ctxt) +{ + u32 i; + aes_context aes_ctxt; + + //Decrypt sections. + for(i = 0; i < _ES32(ctxt->metah->section_count); i++) + { + size_t nc_off = 0; + u8 buf[16]; + u8 iv[16]; + + //Only decrypt encrypted sections. + if(_ES32(ctxt->metash[i].encrypted) == METADATA_SECTION_ENCRYPTED) + { + if(_ES32(ctxt->metash[i].key_index) > _ES32(ctxt->metah->key_count) - 1 || _ES32(ctxt->metash[i].iv_index) > _ES32(ctxt->metah->key_count)) + printf("[*] Warning: Skipped decryption of section %03d (marked encrypted but key/iv index out of range)\n", i); + else + { + memcpy(iv, ctxt->keys + _ES32(ctxt->metash[i].iv_index) * 0x10, 0x10); + aes_setkey_enc(&aes_ctxt, ctxt->keys + _ES32(ctxt->metash[i].key_index) * 0x10, 128); + u8 *ptr = ctxt->scebuffer + _ES64(ctxt->metash[i].data_offset); + aes_crypt_ctr(&aes_ctxt, _ES64(ctxt->metash[i].data_size), &nc_off, iv, buf, ptr, ptr); + } + } + } + + return TRUE; +} + +void cf_print_info(FILE *fp, sce_buffer_ctxt_t *ctxt) +{ + //Print Cert file header. + _print_cert_file_header(fp, ctxt->cfh); +} + +void sce_print_info(FILE *fp, sce_buffer_ctxt_t *ctxt, u8 *keyset) +{ + u32 i; + + //Check if the metadata was decrypted. + if(ctxt->mdec == FALSE) + return; + + //Print metadata infos. + _print_metadata_info(fp, ctxt->metai); + _print_metadata_header(fp, ctxt->metah); + + //Print section infos. + _print_metadata_section_header_header(fp); + for(i = 0; i < _ES32(ctxt->metah->section_count); i++) + _print_metadata_section_header(fp, &ctxt->metash[i], i); + + //Print keys. + _print_sce_file_keys(fp, ctxt); +} + +void print_sce_signature_info(FILE *fp, sce_buffer_ctxt_t *ctxt, u8 *keyset) +{ + _print_sce_signature(fp, ctxt->sig); + _print_sce_signature_status(fp, ctxt, keyset); +} + +static s8 _sce_tmp_vstr[16]; +s8 *sce_version_to_str(u64 version) +{ + u32 v = version >> 32; + sprintf(_sce_tmp_vstr, "%02X.%02X", (v & 0xFFFF0000) >> 16, v & 0x0000FFFF); + return _sce_tmp_vstr; +} + +u64 sce_str_to_version(s8 *version) +{ + u16 h, l; + sscanf(version, "%02X.%02X", &h, &l); + return ((u64)(h << 16 | l)) << 32; +} + +u64 sce_hexver_to_decver(u64 version) +{ + //TODO: hackity hack. + s8 tmp[16]; + u32 v = version >> 32; + u64 res; + + sprintf(tmp, "%02X%02X", (v & 0xFFFF0000) >> 16, v & 0x0000FFFF); + sscanf(tmp, "%d", &v); + res = v*100; + + return res; +} + +control_info_t *sce_get_ctrl_info(sce_buffer_ctxt_t *ctxt, u32 type) +{ + LIST_FOREACH(iter, ctxt->self.cis) + { + control_info_t *ci = (control_info_t *)iter->value; + if(_ES32(ci->type) == type) + return ci; + } + + return NULL; +} + +opt_header_t *sce_get_opt_header(sce_buffer_ctxt_t *ctxt, u32 type) +{ + LIST_FOREACH(iter, ctxt->self.ohs) + { + opt_header_t *oh = (opt_header_t *)iter->value; + if(_ES32(oh->type) == type) + return oh; + } + + return NULL; +} \ No newline at end of file diff --git a/sce.h b/src/sce.h similarity index 81% rename from sce.h rename to src/sce.h index 5d5a889..79d0f37 100644 --- a/sce.h +++ b/src/sce.h @@ -17,12 +17,12 @@ /*! Header align. */ #define HEADER_ALIGN 0x80 -/*! SCE header magic value ("SCE\0"). */ -#define SCE_HEADER_MAGIC 0x53434500 +/*! Cert file magic value ("SCE\0"). */ +#define CF_MAGIC 0x53434500 -/*! SCE header versions. */ -/*! Header version 2. */ -#define SCE_HEADER_VERSION_2 2 +/*! Cert file versions. */ +/*! Cert file version 2. */ +#define CF_VERSION_2 2 /*! Key revisions. */ #define KEY_REVISION_0 0x00 @@ -52,15 +52,15 @@ //#define KEY_REVISION_ 0x18 #define KEY_REVISION_DEBUG 0x8000 -/*! SCE header types. */ -/*! SELF header. */ -#define SCE_HEADER_TYPE_SELF 1 -/*! RVK header. */ -#define SCE_HEADER_TYPE_RVK 2 -/*! PKG header. */ -#define SCE_HEADER_TYPE_PKG 3 -/*! SPP header. */ -#define SCE_HEADER_TYPE_SPP 4 +/*! Cert file categories. */ +/*! SELF file. */ +#define CF_CATEGORY_SELF 1 +/*! RVK file. */ +#define CF_CATEGORY_RVK 2 +/*! PKG file. */ +#define CF_CATEGORY_PKG 3 +/*! SPP file. */ +#define CF_CATEGORY_SPP 4 /*! Sub header types. */ /*! SCE version header. */ @@ -81,6 +81,8 @@ #define OPT_HEADER_TYPE_CAP_FLAGS 1 /*! Individuals seed header. */ #define OPT_HEADER_TYPE_INDIV_SEED 2 +/*! Control flags header 4. */ +#define OPT_HEADER_TYPE_CONTROL_FLAGS 4 /*! Metadata key/iv lengths. */ #define METADATA_INFO_KEYBITS 128 @@ -94,8 +96,8 @@ #define METADATA_SECTION_TYPE_SHDR 1 /*! Program header. */ #define METADATA_SECTION_TYPE_PHDR 2 -/*! Unknown header type 3. */ -#define METADATA_SECTION_TYPE_UNK_3 3 +/*! Sceversion section. */ +#define METADATA_SECTION_TYPE_SCEV 3 /*! Section is hashed. */ #define METADATA_SECTION_HASHED 2 @@ -108,6 +110,9 @@ /*! Section is compressed. */ #define METADATA_SECTION_COMPRESSED 2 +/*! Signature types. */ +#define SIGNATURE_ALGORITHM_ECDSA 1 + /*! Signature sizes. */ /*! Signature S part size. */ #define SIGNATURE_S_SIZE 21 @@ -115,32 +120,32 @@ #define SIGNATURE_R_SIZE 21 /*! Compressed. */ -#define SECTION_INFO_COMPRESSED 2 +#define SEGMENT_INFO_COMPRESSED 2 /*! Not compressed. */ -#define SECTION_INFO_NOT_COMPRESSED 1 +#define SEGMENT_INFO_NOT_COMPRESSED 1 /*! SCE version not present. */ #define SCE_VERSION_NOT_PRESENT 0 /*! SCE version present. */ #define SCE_VERSION_PRESENT 1 -/*! SELF types. */ +/*! Program types. */ /*! lv0. */ -#define SELF_TYPE_LV0 1 +#define PROGRAM_TYPE_LV0 1 /*! lv1. */ -#define SELF_TYPE_LV1 2 +#define PROGRAM_TYPE_LV1 2 /*! lv2. */ -#define SELF_TYPE_LV2 3 +#define PROGRAM_TYPE_LV2 3 /*! Application. */ -#define SELF_TYPE_APP 4 +#define PROGRAM_TYPE_APP 4 /*! Isolated SPU module. */ -#define SELF_TYPE_ISO 5 +#define PROGRAM_TYPE_ISO 5 /*! Secure loader. */ -#define SELF_TYPE_LDR 6 +#define PROGRAM_TYPE_LDR 6 /*! Unknown type 7. */ -#define SELF_TYPE_UNK_7 7 +#define PROGRAM_TYPE_UNK_7 7 /*! NPDRM application. */ -#define SELF_TYPE_NPDRM 8 +#define PROGRAM_TYPE_NPDRM 8 /*! NPDRM control info magic value ("NPD\0"). */ #define NP_CI_MAGIC 0x4E504400 @@ -157,8 +162,8 @@ #define NP_TYPE_USPRX (NP_TYPE_UPDATE | NP_TYPE_SPRX) #define NP_TYPE_UEXEC (NP_TYPE_UPDATE | NP_TYPE_EXEC) -/*! SCE header. */ -typedef struct _sce_header +/*! Cert file header. */ +typedef struct _cert_file_header { /*! Magic value. */ u32 magic; @@ -166,22 +171,22 @@ typedef struct _sce_header u32 version; /*! Key revision. */ u16 key_revision; - /*! Header type. */ - u16 header_type; - /*! Metadata offset. */ - u32 metadata_offset; - /*! Header length. */ - u64 header_len; - /*! Length of encapsulated data. */ - u64 data_len; -} sce_header_t; + /*! File category. */ + u16 category; + /*! Extended header size. */ + u32 ext_header_size; + /*! Offset of encapsulated file. */ + u64 file_offset; + /*! Size of encapsulated file. */ + u64 file_size; +} cert_file_header_t; /*! SELF header. */ typedef struct _self_header { /*! Header type. */ u64 header_type; - /*! Application info offset. */ + /*! Program info offset. */ u64 app_info_offset; /*! ELF offset. */ u64 elf_offset; @@ -189,8 +194,8 @@ typedef struct _self_header u64 phdr_offset; /*! Section headers offset. */ u64 shdr_offset; - /*! Section info offset. */ - u64 section_info_offset; + /*! Segment info offset. */ + u64 segment_info_offset; /*! SCE version offset. */ u64 sce_version_offset; /*! Control info offset. */ @@ -218,7 +223,8 @@ typedef struct _metadata_header { /*! Signature input length. */ u64 sig_input_length; - u32 unknown_0; + /*! Signature algorithm. */ + u32 sig_algorithm; /*! Section count. */ u32 section_count; /*! Key count. */ @@ -262,8 +268,8 @@ typedef struct _signature u8 padding[6]; } signature_t; -/*! Section info. */ -typedef struct _section_info +/*! Segment info. */ +typedef struct _segment_info { u64 offset; u64 size; @@ -271,7 +277,7 @@ typedef struct _section_info u32 unknown_0; u32 unknown_1; u32 encrypted; -} section_info_t; +} segment_info_t; /*! SCE version. */ typedef struct _sce_version @@ -305,7 +311,7 @@ typedef struct _sce_version_data_30 #define VENDOR_TERRITORY_MASK 0xFF000000 #define VENDOR_ID_MASK 0x00FFFFFF -/*! Application info. */ +/*! Program info. */ typedef struct _app_info { /*! Auth ID. */ @@ -313,13 +319,23 @@ typedef struct _app_info /*! Vendor ID. */ u32 vendor_id; /*! SELF type. */ - u32 self_type; + u32 program_type; /*! Version. */ u64 version; /*! Padding. */ u64 padding; } app_info_t; +/*! Vender ID. */ +typedef struct _vendor_id +{ + u8 territory; + u8 unknown_1; + u8 unknown_2; + u8 gos_id; +} vendor_id_t; + + /*! Control info. */ typedef struct _control_info { @@ -381,7 +397,8 @@ typedef struct _ci_data_npdrm { /*! Magic. */ u32 magic; - u32 unknown_0; + /*! Version. */ + u32 version; /*! License type. */ u32 license_type; /*! Application type. */ @@ -394,8 +411,10 @@ typedef struct _ci_data_npdrm u8 hash_cid_fname[0x10]; /*! Control info hash. */ u8 hash_ci[0x10]; - u64 unknown_1; - u64 unknown_2; + /*! Start of the Validity period. */ + u64 limited_time_start; + /*! End of the Validity period. */ + u64 limited_time_end; } ci_data_npdrm_t; /*! Optional header. */ @@ -413,10 +432,10 @@ typedef struct _opt_header #define CAP_FLAG_1 0x01 //only seen in PPU selfs #define CAP_FLAG_2 0x02 //only seen in PPU selfs #define CAP_FLAG_4 0x04 //only seen in bdj PPU self -#define CAP_FLAG_REFTOOL 0x08 -#define CAP_FLAG_DEBUG 0x10 -#define CAP_FLAG_RETAIL 0x20 -#define CAP_FLAG_SYSDBG 0x40 +#define CAP_FLAG_DEH 0x08 //00001000b +#define CAP_FLAG_DEX 0x10 //00010000b +#define CAP_FLAG_CEX 0x20 //00100000b +#define CAP_FLAG_ARCADE 0x40 //01000000b #define UNK7_2000 0x2000 //hddbind? #define UNK7_20000 0x20000 //flashbind? @@ -446,7 +465,7 @@ typedef struct _sce_section_ctxt /*! Offset. */ u32 offset; /*! May be compressed. */ - BOOL may_compr; + bool may_compr; } sce_section_ctxt_t; typedef struct _makeself_ctxt @@ -479,8 +498,8 @@ typedef struct _sce_buffer_ctxt /*! SCE file buffer. */ u8 *scebuffer; - /*! SCE header. */ - sce_header_t *sceh; + /*! Cert file header. */ + cert_file_header_t *cfh; /*! File type dependent header. */ union { @@ -488,10 +507,10 @@ typedef struct _sce_buffer_ctxt { /*! SELF header. */ self_header_t *selfh; - /*! Application info. */ + /*! Program info. */ app_info_t *ai; /*! Section info. */ - section_info_t *si; + segment_info_t *si; /*! SCE version. */ sce_version_t *sv; /*! Control infos. */ @@ -514,24 +533,24 @@ typedef struct _sce_buffer_ctxt signature_t *sig; /*! Metadata decrypted? */ - BOOL mdec; + bool mdec; /*! Data layout. */ - /*! SCE header offset. */ - u32 off_sceh; + /*! Cert file header offset. */ + u32 off_cfh; union { struct { /*! SELF header offset. */ u32 off_selfh; - /*! Application info offset. */ + /*! Program info offset. */ u32 off_ai; /*! ELF header offset. */ u32 off_ehdr; /*! Program header offset. */ u32 off_phdr; - /*! Section info offset. */ + /*! Segment info offset. */ u32 off_si; /*! SCE version offset. */ u32 off_sv; @@ -572,10 +591,10 @@ sce_buffer_ctxt_t *sce_create_ctxt_from_buffer(u8 *scebuffer); sce_buffer_ctxt_t *sce_create_ctxt_build_self(u8 *elf, u32 elf_len); /*! Add data section to SCE context. */ -void sce_add_data_section(sce_buffer_ctxt_t *ctxt, void *buffer, u32 size, BOOL may_compr); +void sce_add_data_section(sce_buffer_ctxt_t *ctxt, void *buffer, u32 size, bool may_compr); /*! Set metadata section header. */ -void sce_set_metash(sce_buffer_ctxt_t *ctxt, u32 type, BOOL encrypted, u32 idx); +void sce_set_metash(sce_buffer_ctxt_t *ctxt, u32 type, bool encrypted, u32 idx); /*! Compress data. */ void sce_compress_data(sce_buffer_ctxt_t *ctxt); @@ -584,19 +603,25 @@ void sce_compress_data(sce_buffer_ctxt_t *ctxt); void sce_layout_ctxt(sce_buffer_ctxt_t *ctxt); /*! Encrypt context. */ -BOOL sce_encrypt_ctxt(sce_buffer_ctxt_t *ctxt, u8 *keyset); +bool sce_encrypt_ctxt(sce_buffer_ctxt_t *ctxt, u8 *keyset); /*! Write context to file. */ -BOOL sce_write_ctxt(sce_buffer_ctxt_t *ctxt, s8 *fname); +bool sce_write_ctxt(sce_buffer_ctxt_t *ctxt, s8 *fname); /*! Decrypt header (use passed metadata_into if not NULL). */ -BOOL sce_decrypt_header(sce_buffer_ctxt_t *ctxt, u8 *metadata_info, u8 *keyset); +bool sce_decrypt_header(sce_buffer_ctxt_t *ctxt, u8 *metadata_info, u8 *keyset); /*! Decrypt data. */ -BOOL sce_decrypt_data(sce_buffer_ctxt_t *ctxt); +bool sce_decrypt_data(sce_buffer_ctxt_t *ctxt); + +/*! Print SCE header info. */ +void cf_print_info(FILE *fp, sce_buffer_ctxt_t *ctxt); /*! Print SCE file info. */ -void sce_print_info(FILE *fp, sce_buffer_ctxt_t *ctxt); +void sce_print_info(FILE *fp, sce_buffer_ctxt_t *ctxt, u8 *keyset); + +/*! Print SCE signature status. */ +void print_sce_signature_info(FILE *fp, sce_buffer_ctxt_t *ctxt, u8 *keyset); /*! Get version string from version. */ s8 *sce_version_to_str(u64 version); diff --git a/src/sce_inlines.h b/src/sce_inlines.h new file mode 100644 index 0000000..e888e62 --- /dev/null +++ b/src/sce_inlines.h @@ -0,0 +1,57 @@ +/* +* Copyright (c) 2011-2013 by naehrwert +* This file is released under the GPLv2. +*/ + +#ifndef _SCE_INLINES_H_ +#define _SCE_INLINES_H_ + +#include + +#include "types.h" +#include "sce.h" + + +static inline void _es_segment_info(segment_info_t *si) +{ + si->offset = _ES64(si->offset); + si->size = _ES64(si->size); + si->compressed = _ES32(si->compressed); + si->unknown_0 = _ES32(si->unknown_0); + si->unknown_1 = _ES32(si->unknown_1); + si->encrypted = _ES32(si->encrypted); +} + +static inline void _copy_es_segment_info(segment_info_t *dst, segment_info_t *src) +{ + memcpy(dst, src, sizeof(segment_info_t)); + _es_segment_info(dst); +} + +static inline void _es_ci_data_digest_40(ci_data_digest_40_t *dig) +{ + dig->fw_version = _ES64(dig->fw_version); +} + +static inline void _copy_es_ci_data_digest_40(ci_data_digest_40_t *dst, ci_data_digest_40_t *src) +{ + memcpy(dst, src, sizeof(ci_data_digest_40_t)); + _es_ci_data_digest_40(dst); +} + +static inline void _es_oh_data_cap_flags(oh_data_cap_flags_t *cf) +{ + cf->unk3 = _ES64(cf->unk3); + cf->unk4 = _ES64(cf->unk4); + cf->flags = _ES64(cf->flags); + cf->unk6 = _ES32(cf->unk6); + cf->unk7 = _ES32(cf->unk7); +} + +static inline void _copy_es_cap_flags(oh_data_cap_flags_t *dst, oh_data_cap_flags_t *src) +{ + memcpy(dst, src, sizeof(oh_data_cap_flags_t)); + _es_oh_data_cap_flags(dst); +} + +#endif diff --git a/src/self.cpp b/src/self.cpp new file mode 100644 index 0000000..3610ac7 --- /dev/null +++ b/src/self.cpp @@ -0,0 +1,1220 @@ +/* +* Copyright (c) 2011-2013 by naehrwert +* This file is released under the GPLv2. +*/ +#define _CRT_SECURE_NO_WARNINGS + +#include +#include +#include + +#include "types.h" +#include "config.h" +#include "util.h" +#include "sce.h" +#include "sce_inlines.h" +#include "self.h" +#include "elf.h" +#include "elf_inlines.h" +#include "tables.h" +#include "sha1.h" +#include "np.h" + +static void _get_shdr_flags(s8 *str, u64 flags) +{ + memset(str, '-', 3); + str[3] = 0; + + if(flags & SHF_WRITE) + str[0] = 'W'; + if(flags & SHF_ALLOC) + str[1] = 'A'; + if(flags & SHF_EXECINSTR) + str[2] = 'E'; +} + +static void _get_phdr_flags(s8 *str, u64 flags) +{ + memset(str, '-', 3); + str[3] = 0; + + if(flags & PF_X) + str[0] = 'X'; + if(flags & PF_W) + str[1] = 'W'; + if(flags & PF_R) + str[2] = 'R'; +} + +void _print_self_header(FILE *fp, self_header_t *h) +{ + fprintf(fp, "[*] Extended Header:\n"); + fprintf(fp, "[*] Signed Elf Header:\n"); + fprintf(fp, " Version 0x%016llX\n", _ES64(h->header_type)); + fprintf(fp, " Prog Ident Header Offset 0x%016llX\n", _ES64(h->app_info_offset)); + fprintf(fp, " ELF Header Offset 0x%016llX\n", _ES64(h->elf_offset)); + fprintf(fp, " ELF Program Headers Offset 0x%016llX\n", _ES64(h->phdr_offset)); + + if ((_ES64(h->shdr_offset)) != 0) + fprintf(fp, " ELF Section Headers Offset 0x%016llX\n", _ES64(h->shdr_offset)); + else + fprintf(fp, " ELF Section Headers Offset N\\A\n"); + + fprintf(fp, " Segment Info Offset 0x%016llX\n", _ES64(h->segment_info_offset)); + + if ((_ES64(h->sce_version_offset)) != 0) + fprintf(fp, " SCE Version Offset 0x%016llX\n", _ES64(h->sce_version_offset)); + else + fprintf(fp, " SCE Version Offset N\\A\n"); + + if ((_ES64(h->control_info_offset)) != 0) + { + fprintf(fp, " Supplemental Header Offset 0x%016llX\n", _ES64(h->control_info_offset)); + fprintf(fp, " Supplemental Header Size 0x%016llX\n", _ES64(h->control_info_size)); + } + else + { + fprintf(fp, " Supplemental Header Offset N\\A\n"); + fprintf(fp, " Supplemental Header Size N\\A\n"); + } + //fprintf(fp, " padding 0x%016llX\n", _ES64(h->padding)); +} + +void _print_app_info(FILE *fp, app_info_t *ai) +{ + const s8 *name; + + fprintf(fp, "[*] Program Identification Header:\n"); + + name = _get_name(_auth_ids, _ES64(ai->auth_id)); + if(name != NULL) + { + fprintf(fp, " Auth-ID "); + _PRINT_RAW(fp, "0x%016llX ", _ES64(ai->auth_id)); + fprintf(fp, "[%s]\n", name); + } + else + fprintf(fp, " Auth-ID 0x%016llX\n", _ES64(ai->auth_id)); + + name = _get_name(_vendor_ids, _ES32(ai->vendor_id)); + if(name != NULL) + { + fprintf(fp, " Vendor-ID "); + _PRINT_RAW(fp, "0x%08X ", _ES32(ai->vendor_id)); + fprintf(fp, "[%s]\n", name); + } + else + fprintf(fp, " Vendor-ID 0x%08X\n", _ES32(ai->vendor_id)); + + vendor_id_t *vendor = (vendor_id_t*)(&ai->vendor_id); + _PRINT_RAW(fp, " Territory 0x%02X\n", (vendor->territory)); + //_PRINT_RAW(fp, " unknown_1 0x%02X\n", (vendor->unknown_1)); + //_PRINT_RAW(fp, " unknown_2 0x%02X\n", (vendor->unknown_2)); + _PRINT_RAW(fp, " Gos-id 0x%02X\n", (vendor->gos_id)); + + name = _get_name(_program_types, _ES32(ai->program_type)); + if(name != NULL) + { + fprintf(fp, " Type ", name); + _PRINT_RAW(fp, "0x%08X ", _ES32(ai->program_type)); + fprintf(fp, "[%s]\n", name); + } + + else + fprintf(fp, " Type 0x%08X\n", _ES32(ai->program_type)); + + fprintf(fp, " Version %s\n", sce_version_to_str(_ES64(ai->version))); + //fprintf(fp, " padding 0x%016llX\n", _ES64(ai->padding)); +} + +void _print_segment_info_header_2(FILE *fp) +{ + fprintf(fp, "[*] Segment Infos:\n"); + fprintf(fp, " Idx Offset Size\n"); +} + +void _print_segment_info_header_3(FILE *fp) +{ + fprintf(fp, "[*] Segment Infos:\n"); + fprintf(fp, " Idx Offset Size Compressed unk0 unk1 Encrypted\n"); +} + +void _print_segment_info_2(FILE *fp, segment_info_t *si, u32 idx) +{ + fprintf(fp, " %03d %08X %08X\n", + idx, (u32)_ES64(si->offset), (u32)_ES64(si->size)); +} + +void _print_segment_info_3(FILE *fp, segment_info_t *si, u32 idx) +{ + fprintf(fp, " %03d %08X %08X %s %08X %08X %s\n", + idx, (u32)_ES64(si->offset), (u32)_ES64(si->size), _ES32(si->compressed) == 2 ? "[YES]" : "[NO ]", + _ES32(si->unknown_0), _ES32(si->unknown_1), _ES32(si->encrypted) == 1 ? "[YES]" : "[NO ]"); +} + +void _print_sce_version(FILE *fp, sce_version_t *sv) +{ + fprintf(fp, "[*] SCE Version:\n"); + fprintf(fp, " Header Type 0x%08X\n", _ES32(sv->header_type)); + fprintf(fp, " Present [%s]\n", _ES32(sv->present) == SCE_VERSION_PRESENT ? "TRUE" : "FALSE"); + fprintf(fp, " Size 0x%08X\n", _ES32(sv->size)); + fprintf(fp, " unknown_3 0x%08X\n", _ES32(sv->unknown_3)); +} + +void _print_control_info(FILE *fp, control_info_t *ci) +{ + const s8 *name; + time_t t; + tm* aTm; + + fprintf(fp, "[*] Supplemental Header\n"); + + name = _get_name(_control_info_types, _ES32(ci->type)); + if(name != NULL) + fprintf(fp, " Type %s\n", name); + else + fprintf(fp, " Type 0x%08X\n", _ES32(ci->type)); + + fprintf(fp, " Size 0x%08X\n", _ES32(ci->size)); + fprintf(fp, " Next [%s]\n", _ES64(ci->next) == 1 ? "TRUE" : "FALSE"); + + switch(_ES32(ci->type)) + { + case CONTROL_INFO_TYPE_FLAGS: + _hexdump(fp, " Flags", 0, (u8 *)ci + sizeof(control_info_t), _ES32(ci->size) - sizeof(control_info_t), FALSE); + break; + case CONTROL_INFO_TYPE_DIGEST: + if(_ES32(ci->size) == 0x30) + { + ci_data_digest_30_t *dig = (ci_data_digest_30_t *)((u8 *)ci + sizeof(control_info_t)); + _hexdump(fp, " Digest", 0, dig->digest, 20, FALSE); + } + else if(_ES32(ci->size) == 0x40) + { + ci_data_digest_40_t *dig = (ci_data_digest_40_t *)((u8 *)ci + sizeof(control_info_t)); + _hexdump(fp, " Digest 1 ", 0, dig->digest1, 20, FALSE); + _hexdump(fp, " Digest 2 ", 0, dig->digest2, 20, FALSE); + if(_ES64(dig->fw_version) != 0) + fprintf(fp, " FW Version %d [%02d.%02d]\n", (u32)_ES64(dig->fw_version), ((u32)_ES64(dig->fw_version))/10000, (((u32)_ES64(dig->fw_version))%10000)/100); + } + break; + case CONTROL_INFO_TYPE_NPDRM: + { + ci_data_npdrm_t *np = (ci_data_npdrm_t *)((u8 *)ci + sizeof(control_info_t)); + //Was already fixed in decrypt_header. + //_es_ci_data_npdrm(np); + fprintf(fp, " Magic 0x%08X [%s]\n", _ES32(np->magic), (_ES32(np->magic) == NP_CI_MAGIC ? "OK" : "ERROR")); + fprintf(fp, " Version 0x%08X\n", _ES32(np->version)); + + name = _get_name(_np_license_types, _ES32(np->license_type)); + if(name != NULL) + { + fprintf(fp, " Licence Type "); + _PRINT_RAW(fp, "0x%08X ", _ES32(np->license_type)); + fprintf(fp, "[%s]\n", name); + } + else + fprintf(fp, " Licence Type 0x%08X\n", _ES32(np->license_type)); + + name = _get_name(_np_app_types, _ES32(np->app_type)); + if(name != NULL) + { + fprintf(fp, " App Type "); + _PRINT_RAW(fp, "0x%08X ", _ES32(np->app_type)); + fprintf(fp, "[%s]\n", name); + } + else + fprintf(fp, " App Type 0x%08X\n", _ES32(np->app_type)); + + fprintf(fp, " ContentID %s\n", np->content_id); + _hexdump(fp, " Random Pad ", 0, np->rndpad, 0x10, FALSE); + _hexdump(fp, " CID_FN Hash ", 0, np->hash_cid_fname, 0x10, FALSE); + _hexdump(fp, " CI Hash ", 0, np->hash_ci, 0x10, FALSE); + + t = (time_t)(_ES64(np->limited_time_start) / 1000); + aTm = localtime(&t); + if(_ES64(np->limited_time_start) != 0) + { + fprintf(fp, " Validity Start "); + _PRINT_RAW(fp, "0x%016llX ", _ES64(np->limited_time_start)); + fprintf(fp, "[%04d/%02d/%02d %02d:%02d:%02d]\n",aTm->tm_year+1900, aTm->tm_mon+1, aTm->tm_mday, aTm->tm_hour, aTm->tm_min, aTm->tm_sec); + } + else + { + fprintf(fp, " Validity Start "); + _PRINT_RAW(fp, "0x%016llX ", _ES64(np->limited_time_start)); + fprintf(fp, "[Unlimited]\n"); + } + + t = (time_t)(_ES64(np->limited_time_end) / 1000); + aTm = localtime(&t); + if(_ES64(np->limited_time_end) != 0) + { + fprintf(fp, " Validity End "); + _PRINT_RAW(fp, "0x%016llX ", _ES64(np->limited_time_end)); + fprintf(fp, "[%04d/%02d/%02d %02d:%02d:%02d]\n",aTm->tm_year+1900, aTm->tm_mon+1, aTm->tm_mday, aTm->tm_hour, aTm->tm_min, aTm->tm_sec); + } + else + { + fprintf(fp, " Validity End "); + _PRINT_RAW(fp, "0x%016llX ", _ES64(np->limited_time_end)); + fprintf(fp, "[Unlimited]\n"); + } + } + break; + } +} + +static void _print_cap_flags_flags(FILE *fp, oh_data_cap_flags_t *cf) +{ + if(_ES64(cf->flags) & 0x01) + fprintf(fp, "0x01 "); + if(_ES64(cf->flags) & 0x02) + fprintf(fp, "0x02 "); + if(_ES64(cf->flags) & 0x04) + fprintf(fp, "0x04 "); + if(_ES64(cf->flags) & CAP_FLAG_DEH) + fprintf(fp, "DEH "); + if(_ES64(cf->flags) & CAP_FLAG_DEX) + fprintf(fp, "DEX "); + if(_ES64(cf->flags) & CAP_FLAG_CEX) + fprintf(fp, "CEX "); + if(_ES64(cf->flags) & CAP_FLAG_ARCADE) + fprintf(fp, "ARCADE "); +} + +void _print_opt_header(FILE *fp, opt_header_t *oh) +{ + const s8 *name; + + fprintf(fp, "[*] Optional Header\n"); + + name = _get_name(_optional_header_types, _ES32(oh->type)); + if(name != NULL) + fprintf(fp, " Type %s\n", name); + else + fprintf(fp, " Type 0x%08X\n", _ES32(oh->type)); + + fprintf(fp, " Size 0x%08X\n", _ES32(oh->size)); + fprintf(fp, " Next [%s]\n", _ES64(oh->next) == 1 ? "TRUE" : "FALSE"); + + switch(_ES32(oh->type)) + { + case OPT_HEADER_TYPE_CAP_FLAGS: + { + if (_ES32(oh->size) == 0x30) + { + oh_data_cap_flags_t *cf = (oh_data_cap_flags_t *)((u8 *)oh + sizeof(opt_header_t)); + + _IF_RAW(_hexdump(fp, " Flags", 0, (u8 *)cf, sizeof(oh_data_cap_flags_t), FALSE)); + + // _es_oh_data_cap_flags(cf); + + fprintf(fp, " unknown_3 0x%016llX\n", _ES64(cf->unk3)); + fprintf(fp, " unknown_4 0x%016llX\n", _ES64(cf->unk4)); + + fprintf(fp, " Flags 0x%016llX [ ", _ES64(cf->flags)); + _print_cap_flags_flags(fp, cf); + fprintf(fp, "]\n"); + + fprintf(fp, " unknown_6 0x%08X\n", _ES32(cf->unk6)); + fprintf(fp, " unknown_7 0x%08X\n", _ES32(cf->unk7)); + } + else + { + u8 *h1 = (u8 *)oh + sizeof(opt_header_t); + _hexdump(fp, " Flags", 0, h1, _ES32(oh->size) - sizeof(opt_header_t), FALSE); + } + } + break; + case OPT_HEADER_TYPE_INDIV_SEED: + { + u8 *is = (u8 *)oh + sizeof(opt_header_t); + _hexdump(fp, " Seed", 0, is, _ES32(oh->size) - sizeof(opt_header_t), FALSE); + } + break; + case OPT_HEADER_TYPE_CONTROL_FLAGS: + { + u8 *ctrlf = (u8 *)oh + sizeof(opt_header_t); + _hexdump(fp, " Flags", 0, ctrlf, _ES32(oh->size) - sizeof(opt_header_t), FALSE); + } + break; + } +} + +void _print_elf32_ehdr(FILE *fp, Elf32_Ehdr *h) +{ + const s8 *name; + + fprintf(fp, "[*] ELF32 Header:\n"); + + name = _get_name(_e_types, _ES16(h->e_type)); + if(name != NULL) + fprintf(fp, " Type [%s]\n", name); + else + fprintf(fp, " Type 0x%04X\n", _ES16(h->e_type)); + + name = _get_name(_e_machines, _ES16(h->e_machine)); + if(name != NULL) + fprintf(fp, " Machine [%s]\n", name); + else + fprintf(fp, " Machine 0x%04X\n", _ES16(h->e_machine)); + + fprintf(fp, " Version 0x%08X\n", _ES32(h->e_version)); + fprintf(fp, " Entry 0x%08X\n", _ES32(h->e_entry)); + fprintf(fp, " Program Headers Offset 0x%08X\n", _ES32(h->e_phoff)); + fprintf(fp, " Section Headers Offset 0x%08X\n", _ES32(h->e_shoff)); + fprintf(fp, " Flags 0x%08X\n", _ES32(h->e_flags)); + fprintf(fp, " Program Headers Count %04d\n", _ES16(h->e_phnum)); + fprintf(fp, " Section Headers Count %04d\n", _ES16(h->e_shnum)); + fprintf(fp, " SH String Index %04d\n", _ES16(h->e_shstrndx)); +} + +void _print_elf64_ehdr(FILE *fp, Elf64_Ehdr *h) +{ + const s8 *name; + + fprintf(fp, "[*] ELF64 Header:\n"); + + name = _get_name(_e_types, _ES16(h->e_type)); + if(name != NULL) + fprintf(fp, " Type [%s]\n", name); + else + fprintf(fp, " Type 0x%04X\n", _ES16(h->e_type)); + + name = _get_name(_e_machines, _ES16(h->e_machine)); + if(name != NULL) + fprintf(fp, " Machine [%s]\n", name); + else + fprintf(fp, " Machine 0x%04X\n", _ES16(h->e_machine)); + + fprintf(fp, " Version 0x%08X\n", _ES32(h->e_version)); + fprintf(fp, " Entry 0x%016llX\n", _ES64(h->e_entry)); + fprintf(fp, " Program Headers Offset 0x%016llX\n", _ES64(h->e_phoff)); + fprintf(fp, " Section Headers Offset 0x%016llX\n", _ES64(h->e_shoff)); + fprintf(fp, " Flags 0x%08X\n", _ES32(h->e_flags)); + fprintf(fp, " Program Headers Count %04d\n", _ES16(h->e_phnum)); + fprintf(fp, " Section Headers Count %04d\n", _ES16(h->e_shnum)); + fprintf(fp, " SH String Index %04d\n", _ES16(h->e_shstrndx)); +} + +void _print_elf32_shdr_header(FILE *fp) +{ + fprintf(fp, "[*] ELF32 Section Headers:\n"); + fprintf(fp, " Idx Name Type Flags Address Offset Size ES Align LK\n"); +} + +void _print_elf32_shdr(FILE *fp, Elf32_Shdr *h, u32 idx) +{ + const s8 *name; + s8 flags[4]; + + _get_shdr_flags(flags, _ES32(h->sh_flags)); + + fprintf(fp, " %03d %04X ", idx, _ES32(h->sh_name)); + + name = _get_name(_sh_types, _ES32(h->sh_type)); + if(name != NULL) + fprintf(fp, "%-13s ", name); + else + fprintf(fp, "%08X ", _ES32(h->sh_type)); + + fprintf(fp, "%s %05X %05X %05X %02X %05X %03d\n", + flags, _ES32(h->sh_addr), _ES32(h->sh_offset), _ES32(h->sh_size), _ES32(h->sh_entsize), _ES32(h->sh_addralign), _ES32(h->sh_link)); +} + +void _print_elf64_shdr_header(FILE *fp) +{ + fprintf(fp, "[*] ELF64 Section Headers:\n"); + fprintf(fp, " Idx Name Type Flags Address Offset Size ES Align LK\n"); +} + +void _print_elf64_shdr(FILE *fp, Elf64_Shdr *h, u32 idx) +{ + const s8 *name; + s8 flags[4]; + + _get_shdr_flags(flags, _ES64(h->sh_flags)); + + fprintf(fp, " %03d %04X ", idx, _ES32(h->sh_name)); + + name = _get_name(_sh_types, _ES32(h->sh_type)); + if(name != NULL) + fprintf(fp, "%-13s ", name); + else + fprintf(fp, "%08X ", _ES32(h->sh_type)); + + fprintf(fp, "%s %016llX %08X %08X %04X %08X %03d\n", + flags, (u64)_ES64(h->sh_addr), (u32)_ES64(h->sh_offset), (u32)_ES64(h->sh_size), (u32)_ES64(h->sh_entsize), (u32)_ES64(h->sh_addralign), _ES32(h->sh_link)); +} + +void _print_elf32_phdr_header(FILE *fp) +{ + fprintf(fp, "[*] ELF32 Program Headers:\n"); + fprintf(fp, " Idx Type Offset VAddr PAddr FileSize MemSize Flags Align\n"); +} + +void _print_elf32_phdr(FILE *fp, Elf32_Phdr *h, u32 idx) +{ + const s8 *name; + + s8 flags[4]; + + _get_phdr_flags(flags, _ES32(h->p_flags)); + + fprintf(fp, " %03d ", idx); + + name = _get_name(_ph_types, _ES32(h->p_type)); + if(name != NULL) + fprintf(fp, "%-7s ", name); + else + fprintf(fp, "0x%08X ", _ES32(h->p_type)); + + fprintf(fp, "%05X %05X %05X %05X %05X %s %05X\n", + _ES32(h->p_offset), _ES32(h->p_vaddr), _ES32(h->p_paddr), _ES32(h->p_filesz), _ES32(h->p_memsz), flags, _ES32(h->p_align)); +} + +void _print_elf64_phdr_header(FILE *fp) +{ + fprintf(fp, "[*] ELF64 Program Headers:\n"); + fprintf(fp, " Idx Type Offset VAddr PAddr FileSize MemSize PPU SPU RSX Align\n"); +} + +void _print_elf64_phdr(FILE *fp, Elf64_Phdr *h, u32 idx) +{ + const s8 *name; + + s8 ppu[4], spu[4], rsx[4]; + + _get_phdr_flags(ppu, _ES32(h->p_flags)); + _get_phdr_flags(spu, _ES32(h->p_flags) >> 20); + _get_phdr_flags(rsx, _ES32(h->p_flags) >> 24); + + fprintf(fp, " %03d ", idx); + + name = _get_name(_ph_types, _ES32(h->p_type)); + if(name != NULL) + fprintf(fp, "%-8s ", name); + else + fprintf(fp, "%08X ", _ES32(h->p_type)); + + fprintf(fp, "%08X %016llX %016llX %08X %08X %s %s %s %08X\n", + (u32)_ES64(h->p_offset), (u64)_ES64(h->p_vaddr), (u64)_ES64(h->p_paddr), (u32)_ES64(h->p_filesz), (u32)_ES64(h->p_memsz), ppu, spu, rsx, (u32)_ES64(h->p_align)); +} + +bool self_print_info(FILE *fp, sce_buffer_ctxt_t *ctxt) +{ + u32 i, program_type; + const u8 *eident; + + //Check for SELF. + if(_ES16(ctxt->cfh->category) != CF_CATEGORY_SELF) + return FALSE; + + //Print SELF infos. + _print_self_header(fp, ctxt->self.selfh); + _print_app_info(fp, ctxt->self.ai); + if(ctxt->self.sv != NULL) + _print_sce_version(fp, ctxt->self.sv); + + //Print control infos. + if(ctxt->self.cis != NULL) + LIST_FOREACH(iter, ctxt->self.cis) + _print_control_info(fp, (control_info_t *)iter->value); + + program_type = _ES32(ctxt->self.ai->program_type); + eident = ctxt->scebuffer + _ES64(ctxt->self.selfh->elf_offset); + + //SPU is 32 bit. + if(program_type == PROGRAM_TYPE_LDR || program_type == PROGRAM_TYPE_ISO || eident[EI_CLASS] == ELFCLASS32) + { + //32 bit ELF. + Elf32_Ehdr *eh = (Elf32_Ehdr *)(ctxt->scebuffer + _ES64(ctxt->self.selfh->elf_offset)); + + //Print segment infos. + + + if (_ES64(ctxt->self.selfh->header_type) == 3) + _print_segment_info_header_3(fp); + else + _print_segment_info_header_2(fp); + + for(i = 0; i < _ES16(eh->e_phnum); i++) + { + if (_ES64(ctxt->self.selfh->header_type) == 3) + _print_segment_info_3(fp, &ctxt->self.si[i], i); + else + _print_segment_info_2(fp, &ctxt->self.si[i], i); + } + + + //Print ELF header. + _print_elf32_ehdr(fp, eh); + + Elf32_Phdr *ph = (Elf32_Phdr *)(ctxt->scebuffer + _ES64(ctxt->self.selfh->phdr_offset)); + + //Print program headers. + _print_elf32_phdr_header(fp); + for(i = 0; i < _ES16(eh->e_phnum); i++) + _print_elf32_phdr(fp, &ph[i], i); + + if(_ES16(eh->e_shnum) > 0) + { + Elf32_Shdr *sh = (Elf32_Shdr *)(ctxt->scebuffer + _ES64(ctxt->self.selfh->shdr_offset)); + + //Print section headers. + _print_elf32_shdr_header(fp); + for(i = 0; i < _ES16(eh->e_shnum); i++) + _print_elf32_shdr(fp, &sh[i], i); + } + } + else + { + //64 bit ELF. + Elf64_Ehdr *eh = (Elf64_Ehdr *)(ctxt->scebuffer + _ES64(ctxt->self.selfh->elf_offset)); + + //Print segment infos. + if(ctxt->self.si != NULL) + { + if (_ES64(ctxt->self.selfh->header_type) == 3) + _print_segment_info_header_3(fp); + else + _print_segment_info_header_2(fp); + + for(i = 0; i < _ES16(eh->e_phnum); i++) + { + if (_ES64(ctxt->self.selfh->header_type) == 3) + _print_segment_info_3(fp, &ctxt->self.si[i], i); + else + _print_segment_info_2(fp, &ctxt->self.si[i], i); + } + } + + //Print ELF header. + _print_elf64_ehdr(stdout, eh); + + Elf64_Phdr *ph = (Elf64_Phdr *)(ctxt->scebuffer + _ES64(ctxt->self.selfh->phdr_offset)); + + //Print program headers. + _print_elf64_phdr_header(fp); + + for(i = 0; i < _ES16(eh->e_phnum); i++) + _print_elf64_phdr(fp, &ph[i], i); + + if(_ES16(eh->e_shnum) > 0) + { + + Elf64_Shdr *sh = (Elf64_Shdr *)(ctxt->scebuffer + _ES64(ctxt->self.selfh->shdr_offset)); + + //Print section headers. + _print_elf64_shdr_header(fp); + for(i = 0; i < _ES16(eh->e_shnum); i++) + _print_elf64_shdr(fp, &sh[i], i); + } + } + + return TRUE; +} + +bool self_print_encrypted_info(FILE *fp, sce_buffer_ctxt_t *ctxt) +{ + //Print optional headers. + if(ctxt->mdec == TRUE) + if (_ES64(ctxt->metah->opt_header_size) > 0) + { + LIST_FOREACH(iter, ctxt->self.ohs) + _print_opt_header(fp, (opt_header_t *)iter->value); + } + return TRUE; +} + +//TODO: maybe implement better. +bool self_write_to_elf(sce_buffer_ctxt_t *ctxt, const s8 *elf_out) +{ + FILE *fp; + u32 i, program_type; + + const u8 *eident; + + //Check for SELF. + if(_ES16(ctxt->cfh->category) != CF_CATEGORY_SELF) + return FALSE; + + if((fp = fopen(elf_out, "wb")) == NULL) + return FALSE; + + program_type = _ES32(ctxt->self.ai->program_type); + eident = ctxt->scebuffer + _ES64(ctxt->self.selfh->elf_offset); + + //SPU is 32 bit. + if(program_type == PROGRAM_TYPE_LDR || program_type == PROGRAM_TYPE_ISO || eident[EI_CLASS] == ELFCLASS32) + { + //Print individuals seed. + if(program_type == PROGRAM_TYPE_ISO) + { + LIST_FOREACH(iter, ctxt->self.ohs) + { + opt_header_t *oh = (opt_header_t *)iter->value; + if (_ES32(oh->type) == OPT_HEADER_TYPE_INDIV_SEED) + { + s8 ifile[256]; + sprintf(ifile, "%s.indiv_seed.bin", elf_out); + FILE *ifp = fopen(ifile, "wb"); + fwrite(((u8 *)oh) + sizeof(opt_header_t), sizeof(u8), _ES32(oh->size) - sizeof(opt_header_t), ifp); + printf("[*] SEED dumped to %s.\n", ifile); + } + } + } + + //32 bit ELF. + Elf32_Ehdr ceh, *eh = (Elf32_Ehdr *)(ctxt->scebuffer + _ES64(ctxt->self.selfh->elf_offset)); + _copy_es_elf32_ehdr(&ceh, eh); + + //Write ELF header. + fwrite(eh, sizeof(Elf32_Ehdr), 1, fp); + + //Write program headers. + Elf32_Phdr *ph = (Elf32_Phdr *)(ctxt->scebuffer + _ES64(ctxt->self.selfh->phdr_offset)); + fwrite(ph, sizeof(Elf32_Phdr), ceh.e_phnum, fp); + + //Write program data. + metadata_section_header_t *msh = ctxt->metash; + for(i = 0; i < _ES32(ctxt->metah->section_count); i++) + { + if(_ES32(msh[i].type) == METADATA_SECTION_TYPE_PHDR) + { + if(_ES32(msh[i].compressed) == METADATA_SECTION_COMPRESSED) + { + _es_elf32_phdr(&ph[_ES32(msh[i].index)]); + u8 *data = (u8 *)malloc(ph[_ES32(msh[i].index)].p_filesz); + + _zlib_inflate(ctxt->scebuffer + _ES64(msh[i].data_offset), _ES64(msh[i].data_size), data, ph[_ES32(msh[i].index)].p_filesz); + fseek(fp, ph[_ES32(msh[i].index)].p_offset, SEEK_SET); + fwrite(data, sizeof(u8), ph[_ES32(msh[i].index)].p_filesz, fp); + + free(data); + } + else + { + _es_elf32_phdr(&ph[_ES32(msh[i].index)]); + fseek(fp, ph[_ES32(msh[i].index)].p_offset, SEEK_SET); + fwrite(ctxt->scebuffer + _ES64(msh[i].data_offset), sizeof(u8), _ES64(msh[i].data_size), fp); + } + } + } + + //Write section headers. + if(_ES64(ctxt->self.selfh->shdr_offset) != 0) + { + Elf32_Shdr *sh = (Elf32_Shdr *)(ctxt->scebuffer + _ES64(ctxt->self.selfh->shdr_offset)); + fseek(fp, ceh.e_shoff, SEEK_SET); + fwrite(sh, sizeof(Elf32_Shdr), ceh.e_shnum, fp); + } + } + else + { + //64 bit ELF. + Elf64_Ehdr ceh, *eh = (Elf64_Ehdr *)(ctxt->scebuffer + _ES64(ctxt->self.selfh->elf_offset)); + _copy_es_elf64_ehdr(&ceh, eh); + + //Write ELF header. + fwrite(eh, sizeof(Elf64_Ehdr), 1, fp); + + //Write program headers. + Elf64_Phdr *ph = (Elf64_Phdr *)(ctxt->scebuffer + _ES64(ctxt->self.selfh->phdr_offset)); + fwrite(ph, sizeof(Elf64_Phdr), ceh.e_phnum, fp); + + //Write program data. + metadata_section_header_t *msh = ctxt->metash; + for(i = 0; i < _ES32(ctxt->metah->section_count); i++) + { + if(_ES32(msh[i].type) == METADATA_SECTION_TYPE_PHDR) + { + if(_ES32(msh[i].compressed) == METADATA_SECTION_COMPRESSED) + { + _es_elf64_phdr(&ph[_ES32(msh[i].index)]); + u8 *data = (u8 *)malloc(ph[_ES32(msh[i].index)].p_filesz); + + _zlib_inflate(ctxt->scebuffer + _ES64(msh[i].data_offset), _ES64(msh[i].data_size), data, ph[_ES32(msh[i].index)].p_filesz); + fseek(fp, ph[_ES32(msh[i].index)].p_offset, SEEK_SET); + fwrite(data, sizeof(u8), ph[_ES32(msh[i].index)].p_filesz, fp); + + free(data); + } + else + { + _es_elf64_phdr(&ph[_ES32(msh[i].index)]); + fseek(fp, ph[_ES32(msh[i].index)].p_offset, SEEK_SET); + fwrite(ctxt->scebuffer + _ES64(msh[i].data_offset), sizeof(u8), _ES64(msh[i].data_size), fp); + } + } + } + + //Write section headers. + if(_ES64(ctxt->self.selfh->shdr_offset) != 0) + { + Elf64_Shdr *sh = (Elf64_Shdr *)(ctxt->scebuffer + _ES64(ctxt->self.selfh->shdr_offset)); + fseek(fp, ceh.e_shoff, SEEK_SET); + fwrite(sh, sizeof(Elf64_Shdr), ceh.e_shnum, fp); + } + } + + fclose(fp); + + return TRUE; +} + +/*! Static zero control flags. */ +static u8 _static_control_flags[0x20] = +{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +/*! Static control digest1. */ +static u8 _static_control_digest[0x14] = +{ + 0x62, 0x7C, 0xB1, 0x80, 0x8A, 0xB9, 0x38, 0xE3, 0x2C, 0x8C, 0x09, 0x17, 0x08, 0x72, 0x6A, 0x57, 0x9E, 0x25, 0x86, 0xE4 +}; + +static bool _create_control_infos(sce_buffer_ctxt_t *ctxt, self_config_t *sconf) +{ + control_info_t *ci; + u32 program_type = _ES32(ctxt->self.ai->program_type); + + //Step 1. + switch(program_type) + { + case PROGRAM_TYPE_LV0: + case PROGRAM_TYPE_LV1: + case PROGRAM_TYPE_LV2: + case PROGRAM_TYPE_APP: + case PROGRAM_TYPE_ISO: + case PROGRAM_TYPE_LDR: + case PROGRAM_TYPE_NPDRM: //TODO: <-- figure more out. + { + //Add control flags. + ci = (control_info_t *)malloc(sizeof(control_info_t) + sizeof(ci_data_flags_t)); + ci->type = _ES32(CONTROL_INFO_TYPE_FLAGS); + ci->size = _ES32(sizeof(control_info_t) + sizeof(ci_data_flags_t)); + ci->next = _ES64(1); + + ci_data_flags_t *cif = (ci_data_flags_t *)((u8 *)ci + sizeof(control_info_t)); + + //Add default flags. + if(sconf->ctrl_flags == NULL) + memcpy(cif->data, _static_control_flags, 0x20); + else + memcpy(cif->data, sconf->ctrl_flags, 0x20); + + list_add_back(ctxt->self.cis, ci); + } + break; + } + + //Step 2. + switch(program_type) + { + case PROGRAM_TYPE_LV0: + case PROGRAM_TYPE_LV1: + case PROGRAM_TYPE_LV2: + case PROGRAM_TYPE_APP: + case PROGRAM_TYPE_ISO: + case PROGRAM_TYPE_LDR: + case PROGRAM_TYPE_NPDRM: + { + //Add digest 0x40. + ci = (control_info_t *)malloc(sizeof(control_info_t) + sizeof(ci_data_digest_40_t)); + ci->type = _ES32(CONTROL_INFO_TYPE_DIGEST); + ci->size = _ES32(sizeof(control_info_t) + sizeof(ci_data_digest_40_t)); + if(program_type == PROGRAM_TYPE_NPDRM) + ci->next = _ES64(1); + else + ci->next = _ES64(0); + + ci_data_digest_40_t *cid = (ci_data_digest_40_t *)((u8 *)ci + sizeof(control_info_t)); + memcpy(cid->digest1, _static_control_digest, 0x14); + memset(cid->digest2, 0, 0x14); + sha1(ctxt->makeself->elf, ctxt->makeself->elf_len, cid->digest2); + + //TODO: check that. + if(program_type == PROGRAM_TYPE_NPDRM) + cid->fw_version = sce_hexver_to_decver(sconf->fw_version); + else + cid->fw_version = 0; + + //Fixup. + _es_ci_data_digest_40(cid); + + list_add_back(ctxt->self.cis, ci); + } + break; + } + + //Step 3. + switch(program_type) + { + case PROGRAM_TYPE_NPDRM: + { + //Add NPDRM control info. + if(sconf->npdrm_config == NULL) + return FALSE; + + ci = (control_info_t *)malloc(sizeof(control_info_t) + sizeof(ci_data_npdrm_t)); + ci->type = _ES32(CONTROL_INFO_TYPE_NPDRM); + ci->size = _ES32(sizeof(control_info_t) + sizeof(ci_data_npdrm_t)); + ci->next = _ES64(0); + + ci_data_npdrm_t *cinp = (ci_data_npdrm_t *)((u8 *)ci + sizeof(control_info_t)); + + //Create NPDRM control info. + if(np_create_ci(sconf->npdrm_config, cinp) == FALSE) + { + free(ci); + return FALSE; + } + + list_add_back(ctxt->self.cis, ci); + } + break; + } + + return TRUE; +} + +static void _set_cap_flags(u32 program_type, oh_data_cap_flags_t *capf) +{ + switch(program_type) + { + case PROGRAM_TYPE_LV0: + capf->flags = CAP_FLAG_ARCADE | CAP_FLAG_CEX | CAP_FLAG_DEX | CAP_FLAG_DEH | 0x3; //0x7B; + capf->unk6 = 1; + break; + case PROGRAM_TYPE_LV1: + capf->flags = CAP_FLAG_ARCADE | CAP_FLAG_CEX | CAP_FLAG_DEX | CAP_FLAG_DEH | 0x3; //0x7B; + capf->unk6 = 1; + break; + case PROGRAM_TYPE_LV2: + capf->flags = CAP_FLAG_ARCADE | CAP_FLAG_CEX | CAP_FLAG_DEX | CAP_FLAG_DEH | 0x3; //0x7B; + capf->unk6 = 1; + break; + case PROGRAM_TYPE_APP: + capf->flags = CAP_FLAG_ARCADE | CAP_FLAG_CEX | CAP_FLAG_DEX | CAP_FLAG_DEH | 0x3; //0x7B; + capf->unk6 = 1; + capf->unk7 = 0x20000; + break; + case PROGRAM_TYPE_ISO: + capf->flags = CAP_FLAG_ARCADE | CAP_FLAG_CEX | CAP_FLAG_DEX | CAP_FLAG_DEH; //0x78; + break; + case PROGRAM_TYPE_LDR: + capf->flags = CAP_FLAG_ARCADE | CAP_FLAG_CEX | CAP_FLAG_DEX | CAP_FLAG_DEH; //0x78; + break; + case PROGRAM_TYPE_NPDRM: + capf->flags = CAP_FLAG_CEX | CAP_FLAG_DEX | CAP_FLAG_DEH | 0x3; //0x3B; + capf->unk6 = 1; + capf->unk7 = 0x2000; + break; + } + + _es_oh_data_cap_flags(capf); +} + +static bool _create_optional_headers(sce_buffer_ctxt_t *ctxt, self_config_t *sconf) +{ + opt_header_t *oh; + u32 program_type = _ES32(ctxt->self.ai->program_type); + + //Step 1. + switch(program_type) + { + case PROGRAM_TYPE_LV0: + case PROGRAM_TYPE_LV1: + case PROGRAM_TYPE_LV2: + case PROGRAM_TYPE_APP: + case PROGRAM_TYPE_ISO: + case PROGRAM_TYPE_LDR: + case PROGRAM_TYPE_NPDRM: + { + //Add capability flags. + oh = (opt_header_t *)malloc(sizeof(opt_header_t) + sizeof(oh_data_cap_flags_t)); + oh->type = _ES32(OPT_HEADER_TYPE_CAP_FLAGS); + oh->size = _ES32(sizeof(opt_header_t) + sizeof(oh_data_cap_flags_t)); + if(program_type == PROGRAM_TYPE_ISO) + oh->next = _ES64(1); + else + oh->next = _ES64(0); + + oh_data_cap_flags_t *capf = (oh_data_cap_flags_t *)((u8 *)oh + sizeof(opt_header_t)); + memset(capf, 0, 0x20); + + //Add default flags. + if(sconf->cap_flags == NULL) + _set_cap_flags(program_type, capf); + else + memcpy(capf, sconf->cap_flags, 0x20); + + list_add_back(ctxt->self.ohs, oh); + } + break; + } + + //Step 2. + switch(program_type) + { + case PROGRAM_TYPE_ISO: + { + //Add individuals seed. + oh = (opt_header_t *)malloc(sizeof(opt_header_t) + 0x100); + oh->type = _ES32(OPT_HEADER_TYPE_INDIV_SEED); + oh->size = _ES32(sizeof(opt_header_t) + 0x100); + oh->next = _ES64(0); + + u8 *is = (u8 *)oh + sizeof(opt_header_t); + memset(is, 0, 0x100); + if(sconf->indiv_seed != NULL) + memcpy(is, sconf->indiv_seed, sconf->indiv_seed_size); + + list_add_back(ctxt->self.ohs, oh); + } + break; + } + + return TRUE; +} + +static void _fill_sce_version(sce_buffer_ctxt_t *ctxt) +{ + ctxt->self.sv->header_type = _ES32(SUB_HEADER_TYPE_SCEVERSION); + ctxt->self.sv->present = _ES32(SCE_VERSION_NOT_PRESENT); + ctxt->self.sv->size = _ES32(sizeof(sce_version_t)); + ctxt->self.sv->unknown_3 = _ES32(0x00000000); +} + +static void _add_phdr_section(sce_buffer_ctxt_t *ctxt, u32 p_type, u32 size, u32 idx) +{ + //Offset gets set later. + ctxt->self.si[idx].offset = 0; + ctxt->self.si[idx].size = size; + + if(p_type == PT_LOAD || p_type == PT_PS3_PRX_RELOC || p_type == 0x700000A8) + ctxt->self.si[idx].encrypted = 1; //Encrypted LOAD (?). + else + ctxt->self.si[idx].encrypted = 0; //No LOAD (?). + + ctxt->self.si[idx].compressed = SEGMENT_INFO_NOT_COMPRESSED; + ctxt->self.si[idx].unknown_0 = 0; //Unknown. + ctxt->self.si[idx].unknown_1 = 0; //Unknown. +} + +static bool _add_shdrs_section(sce_buffer_ctxt_t *ctxt, u32 idx) +{ + //Add a section for the section headers. + if(ctxt->makeself->shdrs != NULL) + { + u32 shsize = ctxt->makeself->shsize; + void *sec = _memdup(ctxt->makeself->shdrs, shsize); + sce_add_data_section(ctxt, sec, shsize, FALSE); + + //Fill metadata section header. + sce_set_metash(ctxt, METADATA_SECTION_TYPE_SHDR, FALSE, idx); + + return TRUE; + } + + return FALSE; +} + +static bool _build_self_32(sce_buffer_ctxt_t *ctxt, self_config_t *sconf) +{ + u32 i; + + Elf32_Ehdr *ehdr; + Elf32_Phdr *phdrs; + //Elf32_Shdr *shdrs; + + //Copy ELF header. + ctxt->makeself->ehdr = (Elf32_Ehdr *)_memdup(ctxt->makeself->elf, sizeof(Elf32_Ehdr)); + ctxt->makeself->ehsize = sizeof(Elf32_Ehdr); + ehdr = (Elf32_Ehdr *)_memdup(ctxt->makeself->elf, sizeof(Elf32_Ehdr)); + _es_elf32_ehdr(ehdr); + + //Copy program headers. + ctxt->makeself->phdrs = (Elf32_Phdr *)_memdup(ctxt->makeself->elf + ehdr->e_phoff, sizeof(Elf32_Phdr) * ehdr->e_phnum); + ctxt->makeself->phsize = sizeof(Elf32_Phdr) * ehdr->e_phnum; + phdrs = (Elf32_Phdr *)_memdup(ctxt->makeself->elf + ehdr->e_phoff, sizeof(Elf32_Phdr) * ehdr->e_phnum); + + //Copy section headers. + if(ehdr->e_shnum != 0) + { + ctxt->makeself->shdrs = (Elf32_Shdr *)_memdup(ctxt->makeself->elf + ehdr->e_shoff, sizeof(Elf32_Shdr) * ehdr->e_shnum); + ctxt->makeself->shsize = sizeof(Elf32_Shdr) * ehdr->e_shnum; + //shdrs = (Elf32_Shdr *)_memdup(ctxt->makeself->elf + ehdr->e_shoff, sizeof(Elf32_Shdr) * ehdr->e_shnum); + } + + //Allocate metadata section headers (one for each program header and one for the section headers). + ctxt->metash = (metadata_section_header_t *)malloc(sizeof(metadata_section_header_t) * (ehdr->e_phnum + 1)); + + //Copy segments, fill segment infos and metadata section headers. + ctxt->self.si = (segment_info_t *)malloc(sizeof(segment_info_t) * ehdr->e_phnum); + u32 loff = 0xFFFFFFFF, skip = 0; + for(i = 0; i < ehdr->e_phnum; i++) + { + _es_elf32_phdr(&phdrs[i]); + + //Add section info. + _add_phdr_section(ctxt, phdrs[i].p_type, phdrs[i].p_filesz, i); + + //Fill metadata section header but skip identical program header offsets. + if(sconf->skip_sections == TRUE && (phdrs[i].p_offset == loff || !(phdrs[i].p_type == PT_LOAD || phdrs[i].p_type == PT_PS3_PRX_RELOC || phdrs[i].p_type == 0x700000A8))) + { + const s8 *name = _get_name(_ph_types, phdrs[i].p_type); + if(name != NULL) + _LOG_VERBOSE("Skipped program header %-8s @ 0x%08X (0x%08X)\n", name, phdrs[i].p_offset, phdrs[i].p_filesz); + else + _LOG_VERBOSE("Skipped program header 0x%08X @ 0x%08X (0x%08X)\n", phdrs[i].p_type, phdrs[i].p_offset, phdrs[i].p_filesz); + skip++; + } + else + { + void *sec = _memdup(ctxt->makeself->elf + phdrs[i].p_offset, phdrs[i].p_filesz); + //SPU sections may be compressed. + sce_add_data_section(ctxt, sec, phdrs[i].p_filesz, TRUE); + sce_set_metash(ctxt, METADATA_SECTION_TYPE_PHDR, TRUE /*(phdrs[i].p_type == PT_LOAD || phdrs[i].p_type == PT_PS3_PRX_RELOC || phdrs[i].p_type == 0x700000A8) ? TRUE : FALSE*/, i - skip); + } + + loff = phdrs[i].p_offset; + } + + //Segment info count. + ctxt->makeself->si_cnt = ehdr->e_phnum; + //Number of segment infos that are present as data sections. + ctxt->makeself->si_sec_cnt = ehdr->e_phnum; + + //Add a section for the section headers. + if(sconf->add_shdrs == TRUE) + if(_add_shdrs_section(ctxt, i - skip) == TRUE) + i++; + + //Metadata. + i -= skip; + ctxt->metah->section_count = _ES32(i); + + return TRUE; +} + +static bool _build_self_64(sce_buffer_ctxt_t *ctxt, self_config_t *sconf) +{ + u32 i; + + Elf64_Ehdr *ehdr; + Elf64_Phdr *phdrs; + //Elf64_Shdr *shdrs; + + //Copy ELF header. + ctxt->makeself->ehdr = (Elf64_Ehdr *)_memdup(ctxt->makeself->elf, sizeof(Elf64_Ehdr)); + ctxt->makeself->ehsize = sizeof(Elf64_Ehdr); + ehdr = (Elf64_Ehdr *)_memdup(ctxt->makeself->elf, sizeof(Elf64_Ehdr)); + _es_elf64_ehdr(ehdr); + + //Copy program headers. + ctxt->makeself->phdrs = (Elf64_Phdr *)_memdup(ctxt->makeself->elf + ehdr->e_phoff, sizeof(Elf64_Phdr) * ehdr->e_phnum); + ctxt->makeself->phsize = sizeof(Elf64_Phdr) * ehdr->e_phnum; + phdrs = (Elf64_Phdr *)_memdup(ctxt->makeself->elf + ehdr->e_phoff, sizeof(Elf64_Phdr) * ehdr->e_phnum); + + //Copy section headers. + if(ehdr->e_shnum != 0) + { + ctxt->makeself->shdrs = (Elf64_Shdr *)_memdup(ctxt->makeself->elf + ehdr->e_shoff, sizeof(Elf64_Shdr) * ehdr->e_shnum); + ctxt->makeself->shsize = sizeof(Elf64_Shdr) * ehdr->e_shnum; + //shdrs = (Elf64_Shdr *)_memdup(ctxt->makeself->elf + ehdr->e_shoff, sizeof(Elf64_Shdr) * ehdr->e_shnum); + } + + //Allocate metadata section headers (one for each program header and one for the section headers). + ctxt->metash = (metadata_section_header_t *)malloc(sizeof(metadata_section_header_t) * (ehdr->e_phnum + 1)); + + //Copy segments, fill segment infos and metadata section headers. + ctxt->self.si = (segment_info_t *)malloc(sizeof(segment_info_t) * ehdr->e_phnum); + u32 loff = 0xFFFFFFFF, skip = 0; + for(i = 0; i < ehdr->e_phnum; i++) + { + _es_elf64_phdr(&phdrs[i]); + + //Add section info. + _add_phdr_section(ctxt, phdrs[i].p_type, phdrs[i].p_filesz, i); + + //TODO: what if the size differs, why skip other program headers? + //Fill metadata section header but skip identical program header offsets. + if(sconf->skip_sections == TRUE && (phdrs[i].p_offset == loff || !(phdrs[i].p_type == PT_LOAD || phdrs[i].p_type == PT_PS3_PRX_RELOC || phdrs[i].p_type == 0x700000A8))) + { + const s8 *name = _get_name(_ph_types, phdrs[i].p_type); + if(name != NULL) + _LOG_VERBOSE("Skipped program header %-8s @ 0x%08X (0x%08X)\n", name, phdrs[i].p_offset, phdrs[i].p_filesz); + else + _LOG_VERBOSE("Skipped program header 0x%08X @ 0x%08X (0x%08X)\n", phdrs[i].p_type, phdrs[i].p_offset, phdrs[i].p_filesz); + skip++; + } + else + { + void *sec = _memdup(ctxt->makeself->elf + phdrs[i].p_offset, phdrs[i].p_filesz); + //PPU sections may be compressed. + sce_add_data_section(ctxt, sec, phdrs[i].p_filesz, TRUE); + sce_set_metash(ctxt, METADATA_SECTION_TYPE_PHDR, TRUE /*(phdrs[i].p_type == PT_LOAD || phdrs[i].p_type == PT_PS3_PRX_RELOC || phdrs[i].p_type == 0x700000A8) ? TRUE : FALSE*/, i - skip); + } + + loff = phdrs[i].p_offset; + } + + //Segment info count. + ctxt->makeself->si_cnt = ehdr->e_phnum; + //Number of segment infos that are present as data sections. + ctxt->makeself->si_sec_cnt = i - skip; + + //Add a section for the section headers. + if(sconf->add_shdrs == TRUE) + if(_add_shdrs_section(ctxt, i - skip) == TRUE) + i++; + + //Metadata. + i -= skip; + ctxt->metah->section_count = _ES32(i); + + return TRUE; +} + +bool self_build_self(sce_buffer_ctxt_t *ctxt, self_config_t *sconf) +{ + const u8 *eident; + + //Fill config values. + ctxt->cfh->key_revision = _ES16(sconf->key_revision); + ctxt->self.ai->auth_id = _ES64(sconf->auth_id); + ctxt->self.ai->vendor_id = _ES32(sconf->vendor_id); + ctxt->self.ai->program_type = _ES32(sconf->program_type); + ctxt->self.ai->version = _ES64(sconf->app_version); + + //Create control infos. + if(_create_control_infos(ctxt, sconf) == FALSE) + { + printf("[*] Error: Could not create SELF control infos.\n"); + return FALSE; + } + + if(sconf->indiv_seed != NULL && sconf->program_type != PROGRAM_TYPE_ISO) + printf("[*] Warning: Skipping individuals seed for non-ISO SELF.\n"); + + //Create optional headers. + if(_create_optional_headers(ctxt, sconf) == FALSE) + { + printf("[*] Error: Could not create SELF optional headers.\n"); + return FALSE; + } + + //Set SCE version. + _fill_sce_version(ctxt); + + //Check for 32 bit or 64 bit ELF. + eident = (const u8*)ctxt->makeself->elf; + if(sconf->program_type == PROGRAM_TYPE_LDR || sconf->program_type == PROGRAM_TYPE_ISO || eident[EI_CLASS] == ELFCLASS32) + return _build_self_32(ctxt, sconf); + return _build_self_64(ctxt, sconf); +} diff --git a/self.h b/src/self.h similarity index 75% rename from self.h rename to src/self.h index c4377c8..82841f4 100644 --- a/self.h +++ b/src/self.h @@ -26,11 +26,11 @@ typedef struct _self_config { /*! Add section headers. */ - BOOL add_shdrs; + bool add_shdrs; /*! Compress data. */ - BOOL compress_data; + bool compress_data; /*! Skip sections. */ - BOOL skip_sections; + bool skip_sections; /*! Key revision. */ u16 key_revision; @@ -38,35 +38,35 @@ typedef struct _self_config u64 auth_id; /*! Vendor ID. */ u32 vendor_id; - /*! SELF type. */ - u32 self_type; + /*! Program type. */ + u32 program_type; /*! Application version. */ u64 app_version; /*! Firmware version. */ u64 fw_version; - /*! Control flags. */ u8 *ctrl_flags; /*! Capability flags. */ u8 *cap_flags; -#ifdef CONFIG_CUSTOM_INDIV_SEED /*! Individuals seed. */ u8 *indiv_seed; /*! Individuals seed size. */ u32 indiv_seed_size; -#endif /*! NPDRM config (used if not NULL). */ npdrm_config_t *npdrm_config; } self_config_t; /*! Print SELF info. */ -BOOL self_print_info(FILE *fp, sce_buffer_ctxt_t *ctxt); +bool self_print_info(FILE *fp, sce_buffer_ctxt_t *ctxt); + +/*! Print SELF encrypted info. */ +bool self_print_encrypted_info(FILE *fp, sce_buffer_ctxt_t *ctxt); /*! Create ELF from SELF. */ -BOOL self_write_to_elf(sce_buffer_ctxt_t *ctxt, const s8 *elf_out); +bool self_write_to_elf(sce_buffer_ctxt_t *ctxt, const s8 *elf_out); /*! Create SELF from ELF. */ -BOOL self_build_self(sce_buffer_ctxt_t *ctxt, self_config_t *sconf); +bool self_build_self(sce_buffer_ctxt_t *ctxt, self_config_t *sconf); #endif diff --git a/sha1.c b/src/sha1.cpp similarity index 100% rename from sha1.c rename to src/sha1.cpp diff --git a/sha1.h b/src/sha1.h similarity index 100% rename from sha1.h rename to src/sha1.h diff --git a/spp.cpp b/src/spp.cpp similarity index 92% rename from spp.cpp rename to src/spp.cpp index 9564f33..9255e26 100644 --- a/spp.cpp +++ b/src/spp.cpp @@ -38,11 +38,11 @@ void spp_print(FILE *fp, sce_buffer_ctxt_t *ctxt) u32 i; //First section contains the SPP header. - spp_header_t *header = (spp_header_t *)(ctxt->scebuffer + ctxt->metash[0].data_offset); + spp_header_t *header = (spp_header_t *)(ctxt->scebuffer + _ES64(ctxt->metash[0].data_offset)); _es_spp_header(header); //Second section contains the entries. - u8 *ent = ctxt->scebuffer + ctxt->metash[1].data_offset; + u8 *ent = ctxt->scebuffer + _ES64(ctxt->metash[1].data_offset); _print_spp_header(fp, header); diff --git a/spp.h b/src/spp.h similarity index 100% rename from spp.h rename to src/spp.h diff --git a/tables.cpp b/src/tables.cpp similarity index 69% rename from tables.cpp rename to src/tables.cpp index f736b9c..2f8e4dd 100644 --- a/tables.cpp +++ b/src/tables.cpp @@ -12,30 +12,30 @@ #include "keys.h" /*! SELF types. */ -id_to_name_t _self_types[] = +id_to_name_t _program_types[] = { - {SELF_TYPE_LV0, "lv0"}, - {SELF_TYPE_LV1, "lv1"}, - {SELF_TYPE_LV2, "lv2"}, - {SELF_TYPE_APP, "Application"}, - {SELF_TYPE_ISO, "Isolated SPU Module"}, - {SELF_TYPE_LDR, "Secure Loader"}, - {SELF_TYPE_UNK_7, "Unknown 7"}, - {SELF_TYPE_NPDRM, "NPDRM Application"}, + {PROGRAM_TYPE_LV0, "lv0"}, + {PROGRAM_TYPE_LV1, "lv1"}, + {PROGRAM_TYPE_LV2, "lv2"}, + {PROGRAM_TYPE_APP, "Application"}, + {PROGRAM_TYPE_ISO, "Isolated SPU Module"}, + {PROGRAM_TYPE_LDR, "Secure Loader"}, + {PROGRAM_TYPE_UNK_7, "Unknown 7"}, + {PROGRAM_TYPE_NPDRM, "NPDRM Application"}, {0, NULL} }; /*! SELF types as parameter. */ -id_to_name_t _self_types_params[] = +id_to_name_t _program_types_params[] = { - {SELF_TYPE_LV0, "LV0"}, - {SELF_TYPE_LV1, "LV1"}, - {SELF_TYPE_LV2, "LV2"}, - {SELF_TYPE_APP, "APP"}, - {SELF_TYPE_ISO, "ISO"}, - {SELF_TYPE_LDR, "LDR"}, - //{SELF_TYPE_UNK_7, "UNK7"}, - {SELF_TYPE_NPDRM, "NPDRM"}, + {PROGRAM_TYPE_LV0, "LV0"}, + {PROGRAM_TYPE_LV1, "LV1"}, + {PROGRAM_TYPE_LV2, "LV2"}, + {PROGRAM_TYPE_APP, "APP"}, + {PROGRAM_TYPE_ISO, "ISO"}, + {PROGRAM_TYPE_LDR, "LDR"}, + //{PROGRAM_TYPE_UNK_7, "UNK7"}, + {PROGRAM_TYPE_NPDRM, "NPDRM"}, {0, NULL} }; @@ -52,9 +52,17 @@ id_to_name_t _control_info_types[] = id_to_name_t _optional_header_types[] = { {OPT_HEADER_TYPE_CAP_FLAGS, "Capability Flags"}, -#ifdef CONFIG_DUMP_INDIV_SEED {OPT_HEADER_TYPE_INDIV_SEED, "Individuals Seed"}, -#endif + {OPT_HEADER_TYPE_CONTROL_FLAGS, "Control Flags"}, + {0, NULL} +}; + +/*! NPDRM license types. */ +id_to_name_t _np_license_types[] = +{ + {NP_LICENSE_NETWORK, "NETWORK"}, + {NP_LICENSE_LOCAL, "LOCAL"}, + {NP_LICENSE_FREE, "FREE"}, {0, NULL} }; @@ -65,7 +73,7 @@ id_to_name_t _np_app_types[] = {NP_TYPE_EXEC, "EXEC"}, {NP_TYPE_USPRX, "USPRX"}, {NP_TYPE_UEXEC, "UEXEC"}, - {0, NULL}, + {0, NULL} }; /*! Auth IDs. */ @@ -78,7 +86,18 @@ id_to_name_t _auth_ids[] = {0x1070000002000002, "mcore"}, {0x1070000003000002, "mgvideo"}, {0x1070000004000002, "swagner, swreset"}, + {0x107000000E000001, "vtrm_server (lv1)"}, + {0x107000000F000001, "update_manager_server (lv1)"}, + {0x1070000010000001, "sc_manager_server (lv1)"}, + {0x1070000011000001, "secure_rtc_server (lv1)"}, + {0x1070000012000001, "spm_server (lv1)"}, + {0x1070000013000001, "sb_manager_server (lv1)"}, + {0x1070000014000001, "framework (lv1)"}, + {0x1070000015000001, "lv2_loader (lv1)"}, + {0x1070000016000001, "profile_loader (lv1)"}, {0x1070000017000001, "ss_init (lv1)"}, + {0x1070000018000001, "individual_info_mgr_server (lv1)"}, + {0x1070000019000001, "app_info_manager_server (lv1)"}, {0x107000001A000001, "ss_sc_init_pu (lv1)"}, {0x107000001C000001, "updater_frontend (lv1)"}, {0x107000001D000001, "sysmgr_ss (lv1)"}, @@ -90,6 +109,7 @@ id_to_name_t _auth_ids[] = {0x1070000024000001, "sv_iso_spu_module"}, {0x1070000025000001, "aim_spu_module"}, {0x1070000026000001, "ss_sc_init"}, + {0x1070000027000001, "dispatcher (lv1)"}, {0x1070000028000001, "factory_data_mngr_server (lv1)"}, {0x1070000029000001, "fdm_spu_module"}, {0x1070000032000001, "ss_server1 (lv1)"}, @@ -102,6 +122,8 @@ id_to_name_t _auth_ids[] = {0x1070000041000001, "ps1emu"}, {0x1070000043000001, "me_iso_spu_module"}, {0x1070000046000001, "spu_mode_auth"}, + {0x1070000047000001, "otheros"}, + {0x1070000048000001, "ftpd"}, {0x107000004C000001, "spu_utoken_processor"}, {0x1070000052000001, "sys/internal + vsh/module modules"}, {0x1070000055000001, "manu_info_spu_module"}, @@ -125,6 +147,7 @@ id_to_name_t _auth_ids[] = {0x1FF0000008000001, "lv1ldr"}, {0x1FF0000009000001, "lv2ldr"}, {0x1FF000000A000001, "isoldr"}, + {0x1FF000000B000001, "rvkldr"}, {0x1FF000000C000001, "appldr"}, {0, NULL} }; @@ -198,14 +221,23 @@ id_to_name_t _ph_types[] = {0, NULL} }; -/*! Key types. */ -id_to_name_t _key_types[] = +/*! Metadata section header types. */ +id_to_name_t _msh_types[] = { - {KEYTYPE_SELF, "SELF"}, - {KEYTYPE_RVK, "RVK"}, - {KEYTYPE_PKG, "PKG"}, - {KEYTYPE_SPP, "SPP"}, - {KEYTYPE_OTHER, "OTHER"}, + {METADATA_SECTION_TYPE_SHDR, "SHDR"}, + {METADATA_SECTION_TYPE_PHDR, "PHDR"}, + {METADATA_SECTION_TYPE_SCEV, "SCEV"}, + {0, NULL} +}; + +/*! Key types. */ +id_to_name_t _key_categories[] = +{ + {KEYCATEGORY_SELF, "SELF"}, + {KEYCATEGORY_RVK, "RVK"}, + {KEYCATEGORY_PKG, "PKG"}, + {KEYCATEGORY_SPP, "SPP"}, + {KEYCATEGORY_OTHER, "OTHER"}, {0, NULL} }; @@ -248,12 +280,18 @@ const s8 *_key_revisions[] = }; */ -/*! SCE header types. */ -id_to_name_t _sce_header_types[] = +/*! Cert file types. */ +id_to_name_t _cert_file_categories[] = { - {SCE_HEADER_TYPE_SELF, "SELF"}, - {SCE_HEADER_TYPE_RVK, "RVK"}, - {SCE_HEADER_TYPE_PKG, "PKG"}, - {SCE_HEADER_TYPE_SPP, "SPP"}, + {CF_CATEGORY_SELF, "SELF"}, + {CF_CATEGORY_RVK, "RVK"}, + {CF_CATEGORY_PKG, "PKG"}, + {CF_CATEGORY_SPP, "SPP"}, + {0, NULL} +}; + +id_to_name_t _sig_algorithms[] = +{ + {SIGNATURE_ALGORITHM_ECDSA, "ECDSA"}, {0, NULL} }; diff --git a/tables.h b/src/tables.h similarity index 68% rename from tables.h rename to src/tables.h index 032cefc..1cfcfd8 100644 --- a/tables.h +++ b/src/tables.h @@ -10,10 +10,10 @@ #include "util.h" /*! SELF types. */ -extern id_to_name_t _self_types[]; +extern id_to_name_t _program_types[]; /*! SELF types as parameter. */ -extern id_to_name_t _self_types_params[]; +extern id_to_name_t _program_types_params[]; /* Control info types. */ extern id_to_name_t _control_info_types[]; @@ -21,6 +21,9 @@ extern id_to_name_t _control_info_types[]; /*! Optional header types. */ extern id_to_name_t _optional_header_types[]; +/*! NPDRM license types. */ +extern id_to_name_t _np_license_types[]; + /*! NPDRM application types. */ extern id_to_name_t _np_app_types[]; @@ -42,13 +45,19 @@ extern id_to_name_t _sh_types[]; /*! Program header types. */ extern id_to_name_t _ph_types[]; +/*! Metadata section header types. */ +extern id_to_name_t _msh_types[]; + /*! Key types. */ -extern id_to_name_t _key_types[]; +extern id_to_name_t _key_categories[]; /*! Key revisions. */ //extern const s8 *_key_revisions[]; -/*! SCE header types. */ -extern id_to_name_t _sce_header_types[]; +/*! Cert file types. */ +extern id_to_name_t _cert_file_categories[]; + +/*! Signature algorithms. */ +extern id_to_name_t _sig_algorithms[]; #endif diff --git a/types.h b/src/types.h similarity index 88% rename from types.h rename to src/types.h index 4d323c0..129b9f8 100644 --- a/types.h +++ b/src/types.h @@ -23,7 +23,7 @@ typedef long long int s64; typedef unsigned long long int u64; #endif -#define BOOL int +#define bool int #define TRUE 1 #define FALSE 0 @@ -38,6 +38,10 @@ typedef unsigned long long int u64; #define _ES16(val) \ ((u16)(((((u16)val) & 0xff00) >> 8) | \ ((((u16)val) & 0x00ff) << 8))) + +#ifdef __BIG_ENDIAN__ + #define _ES16(val) val +#endif //Endian swap for u32. #define _ES32(val) \ @@ -45,6 +49,10 @@ typedef unsigned long long int u64; ((((u32)val) & 0x00ff0000) >> 8 ) | \ ((((u32)val) & 0x0000ff00) << 8 ) | \ ((((u32)val) & 0x000000ff) << 24))) + +#ifdef __BIG_ENDIAN__ + #define _ES32(val) val +#endif //Endian swap for u64. #define _ES64(val) \ @@ -57,6 +65,10 @@ typedef unsigned long long int u64; ((((u64)val) & 0x000000000000ff00ull) << 40) | \ ((((u64)val) & 0x00000000000000ffull) << 56))) +#ifdef __BIG_ENDIAN__ + #define _ES64(val) val +#endif + #ifdef __cplusplus } #endif diff --git a/util.cpp b/src/util.cpp similarity index 94% rename from util.cpp rename to src/util.cpp index 5a5733d..2f81f29 100644 --- a/util.cpp +++ b/src/util.cpp @@ -2,6 +2,7 @@ * Copyright (c) 2011-2013 by naehrwert * This file is released under the GPLv2. */ +#define _CRT_SECURE_NO_WARNINGS #include #include @@ -13,7 +14,7 @@ #include "zlib.h" #include "mt19937.h" -void _hexdump(FILE *fp, const char *name, u32 offset, u8 *buf, int len, BOOL print_addr) +void _hexdump(FILE *fp, const char *name, u32 offset, u8 *buf, int len, bool print_addr) { int i, j, align = strlen(name) + 1; @@ -133,9 +134,9 @@ void _zlib_inflate(u8 *in, u64 len_in, u8 *out, u64 len_out) inflateInit(&s); - s.avail_in = len_in; + s.avail_in = (u32)len_in; s.next_in = in; - s.avail_out = len_out; + s.avail_out = (u32)len_out; s.next_out = out; inflate(&s, Z_FINISH); @@ -154,9 +155,9 @@ void _zlib_deflate(u8 *in, u64 len_in, u8 *out, u64 len_out) deflateInit(&s, Z_BEST_COMPRESSION); - s.avail_in = len_in; + s.avail_in = (u32)len_in; s.next_in = in; - s.avail_out = len_out; + s.avail_out = (u32)len_out; s.next_out = out; deflate(&s, Z_FINISH); @@ -165,7 +166,7 @@ void _zlib_deflate(u8 *in, u64 len_in, u8 *out, u64 len_out) } static mt19937_ctxt_t _mt19937_ctxt; -static BOOL _mt_init = FALSE; +static bool _mt_init = FALSE; u8 _get_rand_byte() { diff --git a/util.h b/src/util.h similarity index 95% rename from util.h rename to src/util.h index 42bdc56..834061f 100644 --- a/util.h +++ b/src/util.h @@ -11,7 +11,7 @@ #include "types.h" /*! Verbose. */ -extern BOOL _verbose; +extern bool _verbose; #define _LOG_VERBOSE(...) _IF_VERBOSE(printf("[*] " __VA_ARGS__)) #define _IF_VERBOSE(code) \ do \ @@ -23,7 +23,7 @@ extern BOOL _verbose; } while(0) /*! Raw. */ -extern BOOL _raw; +extern bool _raw; #define _PRINT_RAW(fp, ...) _IF_RAW(fprintf(fp, __VA_ARGS__)) #define _IF_RAW(code) \ do \ @@ -42,7 +42,7 @@ typedef struct _id_to_name } id_to_name_t; /*! Utility functions. */ -void _hexdump(FILE *fp, const char *name, u32 offset, u8 *buf, int len, BOOL print_addr); +void _hexdump(FILE *fp, const char *name, u32 offset, u8 *buf, int len, bool print_addr); void _print_align(FILE *fp, const s8 *str, s32 align, s32 len); u8 *_read_buffer(const s8 *file, u32 *length); int _write_buffer(const s8 *file, u8 *buffer, u32 length); diff --git a/zconf.h b/src/zconf.h similarity index 72% rename from zconf.h rename to src/zconf.h index 02ce56c..9987a77 100644 --- a/zconf.h +++ b/src/zconf.h @@ -1,5 +1,5 @@ /* zconf.h -- configuration of the zlib compression library - * Copyright (C) 1995-2010 Jean-loup Gailly. + * Copyright (C) 1995-2013 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -15,11 +15,13 @@ * this permanently in zconf.h using "./configure --zprefix". */ #ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ +# define Z_PREFIX_SET /* all linked symbols */ # define _dist_code z__dist_code # define _length_code z__length_code # define _tr_align z__tr_align +# define _tr_flush_bits z__tr_flush_bits # define _tr_flush_block z__tr_flush_block # define _tr_init z__tr_init # define _tr_stored_block z__tr_stored_block @@ -27,9 +29,11 @@ # define adler32 z_adler32 # define adler32_combine z_adler32_combine # define adler32_combine64 z_adler32_combine64 -# define compress z_compress -# define compress2 z_compress2 -# define compressBound z_compressBound +# ifndef Z_SOLO +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# endif # define crc32 z_crc32 # define crc32_combine z_crc32_combine # define crc32_combine64 z_crc32_combine64 @@ -40,44 +44,53 @@ # define deflateInit2_ z_deflateInit2_ # define deflateInit_ z_deflateInit_ # define deflateParams z_deflateParams +# define deflatePending z_deflatePending # define deflatePrime z_deflatePrime # define deflateReset z_deflateReset +# define deflateResetKeep z_deflateResetKeep # define deflateSetDictionary z_deflateSetDictionary # define deflateSetHeader z_deflateSetHeader # define deflateTune z_deflateTune # define deflate_copyright z_deflate_copyright # define get_crc_table z_get_crc_table -# define gz_error z_gz_error -# define gz_intmax z_gz_intmax -# define gz_strwinerror z_gz_strwinerror -# define gzbuffer z_gzbuffer -# define gzclearerr z_gzclearerr -# define gzclose z_gzclose -# define gzclose_r z_gzclose_r -# define gzclose_w z_gzclose_w -# define gzdirect z_gzdirect -# define gzdopen z_gzdopen -# define gzeof z_gzeof -# define gzerror z_gzerror -# define gzflush z_gzflush -# define gzgetc z_gzgetc -# define gzgets z_gzgets -# define gzoffset z_gzoffset -# define gzoffset64 z_gzoffset64 -# define gzopen z_gzopen -# define gzopen64 z_gzopen64 -# define gzprintf z_gzprintf -# define gzputc z_gzputc -# define gzputs z_gzputs -# define gzread z_gzread -# define gzrewind z_gzrewind -# define gzseek z_gzseek -# define gzseek64 z_gzseek64 -# define gzsetparams z_gzsetparams -# define gztell z_gztell -# define gztell64 z_gztell64 -# define gzungetc z_gzungetc -# define gzwrite z_gzwrite +# ifndef Z_SOLO +# define gz_error z_gz_error +# define gz_intmax z_gz_intmax +# define gz_strwinerror z_gz_strwinerror +# define gzbuffer z_gzbuffer +# define gzclearerr z_gzclearerr +# define gzclose z_gzclose +# define gzclose_r z_gzclose_r +# define gzclose_w z_gzclose_w +# define gzdirect z_gzdirect +# define gzdopen z_gzdopen +# define gzeof z_gzeof +# define gzerror z_gzerror +# define gzflush z_gzflush +# define gzgetc z_gzgetc +# define gzgetc_ z_gzgetc_ +# define gzgets z_gzgets +# define gzoffset z_gzoffset +# define gzoffset64 z_gzoffset64 +# define gzopen z_gzopen +# define gzopen64 z_gzopen64 +# ifdef _WIN32 +# define gzopen_w z_gzopen_w +# endif +# define gzprintf z_gzprintf +# define gzvprintf z_gzvprintf +# define gzputc z_gzputc +# define gzputs z_gzputs +# define gzread z_gzread +# define gzrewind z_gzrewind +# define gzseek z_gzseek +# define gzseek64 z_gzseek64 +# define gzsetparams z_gzsetparams +# define gztell z_gztell +# define gztell64 z_gztell64 +# define gzungetc z_gzungetc +# define gzwrite z_gzwrite +# endif # define inflate z_inflate # define inflateBack z_inflateBack # define inflateBackEnd z_inflateBackEnd @@ -92,16 +105,22 @@ # define inflateReset z_inflateReset # define inflateReset2 z_inflateReset2 # define inflateSetDictionary z_inflateSetDictionary +# define inflateGetDictionary z_inflateGetDictionary # define inflateSync z_inflateSync # define inflateSyncPoint z_inflateSyncPoint # define inflateUndermine z_inflateUndermine +# define inflateResetKeep z_inflateResetKeep # define inflate_copyright z_inflate_copyright # define inflate_fast z_inflate_fast # define inflate_table z_inflate_table -# define uncompress z_uncompress +# ifndef Z_SOLO +# define uncompress z_uncompress +# endif # define zError z_zError -# define zcalloc z_zcalloc -# define zcfree z_zcfree +# ifndef Z_SOLO +# define zcalloc z_zcalloc +# define zcfree z_zcfree +# endif # define zlibCompileFlags z_zlibCompileFlags # define zlibVersion z_zlibVersion @@ -111,7 +130,9 @@ # define alloc_func z_alloc_func # define charf z_charf # define free_func z_free_func -# define gzFile z_gzFile +# ifndef Z_SOLO +# define gzFile z_gzFile +# endif # define gz_header z_gz_header # define gz_headerp z_gz_headerp # define in_func z_in_func @@ -197,6 +218,12 @@ # endif #endif +#if defined(ZLIB_CONST) && !defined(z_const) +# define z_const const +#else +# define z_const +#endif + /* Some Mac compilers merge all .h files incorrectly: */ #if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) # define NO_DUMMY_DECL @@ -243,6 +270,14 @@ # endif #endif +#ifndef Z_ARG /* function prototypes for stdarg */ +# if defined(STDC) || defined(Z_HAVE_STDARG_H) +# define Z_ARG(args) args +# else +# define Z_ARG(args) () +# endif +#endif + /* The following definitions for FAR are needed only for MSDOS mixed * model programming (small or medium model with some far allocations). * This was tested only with MSC; for other MSDOS compilers you may have @@ -356,12 +391,47 @@ typedef uLong FAR uLongf; typedef Byte *voidp; #endif +#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC) +# include +# if (UINT_MAX == 0xffffffffUL) +# define Z_U4 unsigned +# elif (ULONG_MAX == 0xffffffffUL) +# define Z_U4 unsigned long +# elif (USHRT_MAX == 0xffffffffUL) +# define Z_U4 unsigned short +# endif +#endif + +#ifdef Z_U4 + typedef Z_U4 z_crc_t; +#else + typedef unsigned long z_crc_t; +#endif + #ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ # define Z_HAVE_UNISTD_H #endif +#ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */ +# define Z_HAVE_STDARG_H +#endif + #ifdef STDC -# include /* for off_t */ +# ifndef Z_SOLO +# include /* for off_t */ +# endif +#endif + +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifndef Z_SOLO +# include /* for va_list */ +# endif +#endif + +#ifdef _WIN32 +# ifndef Z_SOLO +# include /* for wchar_t */ +# endif #endif /* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and @@ -370,21 +440,38 @@ typedef uLong FAR uLongf; * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as * equivalently requesting no 64-bit operations */ -#if -_LARGEFILE64_SOURCE - -1 == 1 +#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1 # undef _LARGEFILE64_SOURCE #endif -#if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) -# include /* for SEEK_* and off_t */ -# ifdef VMS -# include /* for off_t */ -# endif -# ifndef z_off_t -# define z_off_t off_t +#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H) +# define Z_HAVE_UNISTD_H +#endif +#ifndef Z_SOLO +# if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) +# include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ +# ifdef VMS +# include /* for off_t */ +# endif +# ifndef z_off_t +# define z_off_t off_t +# endif # endif #endif -#ifndef SEEK_SET +#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0 +# define Z_LFS64 +#endif + +#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64) +# define Z_LARGE64 +#endif + +#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64) +# define Z_WANT64 +#endif + +#if !defined(SEEK_SET) && !defined(Z_SOLO) # define SEEK_SET 0 /* Seek from beginning of file. */ # define SEEK_CUR 1 /* Seek from current position. */ # define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ @@ -394,18 +481,14 @@ typedef uLong FAR uLongf; # define z_off_t long #endif -#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 +#if !defined(_WIN32) && defined(Z_LARGE64) # define z_off64_t off64_t #else -# define z_off64_t z_off_t -#endif - -#if defined(__OS400__) -# define NO_vsnprintf -#endif - -#if defined(__MVS__) -# define NO_vsnprintf +# if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO) +# define z_off64_t __int64 +# else +# define z_off64_t z_off_t +# endif #endif /* MVS linker does not support external names larger than 8 bytes */ diff --git a/zlib.h b/src/zlib.h similarity index 84% rename from zlib.h rename to src/zlib.h index bfbba83..3e0c767 100644 --- a/zlib.h +++ b/src/zlib.h @@ -1,7 +1,7 @@ /* zlib.h -- interface of the 'zlib' general purpose compression library - version 1.2.5, April 19th, 2010 + version 1.2.8, April 28th, 2013 - Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler + Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -24,8 +24,8 @@ The data format used by the zlib library is described by RFCs (Request for - Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt - (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). + Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950 + (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format). */ #ifndef ZLIB_H @@ -37,11 +37,11 @@ extern "C" { #endif -#define ZLIB_VERSION "1.2.5" -#define ZLIB_VERNUM 0x1250 +#define ZLIB_VERSION "1.2.8" +#define ZLIB_VERNUM 0x1280 #define ZLIB_VER_MAJOR 1 #define ZLIB_VER_MINOR 2 -#define ZLIB_VER_REVISION 5 +#define ZLIB_VER_REVISION 8 #define ZLIB_VER_SUBREVISION 0 /* @@ -83,15 +83,15 @@ typedef void (*free_func) OF((voidpf opaque, voidpf address)); struct internal_state; typedef struct z_stream_s { - Bytef *next_in; /* next input byte */ + z_const Bytef *next_in; /* next input byte */ uInt avail_in; /* number of bytes available at next_in */ - uLong total_in; /* total nb of input bytes read so far */ + uLong total_in; /* total number of input bytes read so far */ Bytef *next_out; /* next output byte should be put there */ uInt avail_out; /* remaining free space at next_out */ - uLong total_out; /* total nb of bytes output so far */ + uLong total_out; /* total number of bytes output so far */ - char *msg; /* last error message, NULL if no error */ + z_const char *msg; /* last error message, NULL if no error */ struct internal_state FAR *state; /* not visible by applications */ alloc_func zalloc; /* used to allocate the internal state */ @@ -327,8 +327,9 @@ ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); Z_FINISH can be used immediately after deflateInit if all the compression is to be done in a single step. In this case, avail_out must be at least the - value returned by deflateBound (see below). If deflate does not return - Z_STREAM_END, then it must be called again as described above. + value returned by deflateBound (see below). Then deflate is guaranteed to + return Z_STREAM_END. If not enough output space is provided, deflate will + not return Z_STREAM_END, and it must be called again as described above. deflate() sets strm->adler to the adler32 checksum of all input read so far (that is, total_in bytes). @@ -451,23 +452,29 @@ ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); error. However if all decompression is to be performed in a single step (a single call of inflate), the parameter flush should be set to Z_FINISH. In this case all pending input is processed and all pending output is flushed; - avail_out must be large enough to hold all the uncompressed data. (The size - of the uncompressed data may have been saved by the compressor for this - purpose.) The next operation on this stream must be inflateEnd to deallocate - the decompression state. The use of Z_FINISH is never required, but can be - used to inform inflate that a faster approach may be used for the single - inflate() call. + avail_out must be large enough to hold all of the uncompressed data for the + operation to complete. (The size of the uncompressed data may have been + saved by the compressor for this purpose.) The use of Z_FINISH is not + required to perform an inflation in one step. However it may be used to + inform inflate that a faster approach can be used for the single inflate() + call. Z_FINISH also informs inflate to not maintain a sliding window if the + stream completes, which reduces inflate's memory footprint. If the stream + does not complete, either because not all of the stream is provided or not + enough output space is provided, then a sliding window will be allocated and + inflate() can be called again to continue the operation as if Z_NO_FLUSH had + been used. In this implementation, inflate() always flushes as much output as possible to the output buffer, and always uses the faster approach on the - first call. So the only effect of the flush parameter in this implementation - is on the return value of inflate(), as noted below, or when it returns early - because Z_BLOCK or Z_TREES is used. + first call. So the effects of the flush parameter in this implementation are + on the return value of inflate() as noted below, when inflate() returns early + when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of + memory for a sliding window when Z_FINISH is used. If a preset dictionary is needed after this call (see inflateSetDictionary - below), inflate sets strm->adler to the adler32 checksum of the dictionary + below), inflate sets strm->adler to the Adler-32 checksum of the dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise it sets - strm->adler to the adler32 checksum of all output produced so far (that is, + strm->adler to the Adler-32 checksum of all output produced so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described below. At the end of the stream, inflate() checks that its computed adler32 checksum is equal to that saved by the compressor and returns Z_STREAM_END @@ -478,7 +485,9 @@ ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); initializing with inflateInit2(). Any information contained in the gzip header is not retained, so applications that need that information should instead use raw inflate, see inflateInit2() below, or inflateBack() and - perform their own processing of the gzip header and trailer. + perform their own processing of the gzip header and trailer. When processing + gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output + producted so far. The CRC-32 is checked against the gzip trailer. inflate() returns Z_OK if some progress has been made (more input processed or more output produced), Z_STREAM_END if the end of the compressed data has @@ -580,10 +589,15 @@ ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, uInt dictLength)); /* Initializes the compression dictionary from the given byte sequence - without producing any compressed output. This function must be called - immediately after deflateInit, deflateInit2 or deflateReset, before any call - of deflate. The compressor and decompressor must use exactly the same - dictionary (see inflateSetDictionary). + without producing any compressed output. When using the zlib format, this + function must be called immediately after deflateInit, deflateInit2 or + deflateReset, and before any call of deflate. When doing raw deflate, this + function must be called either before any call of deflate, or immediately + after the completion of a deflate block, i.e. after all input has been + consumed and all output has been delivered when using any of the flush + options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH. The + compressor and decompressor must use exactly the same dictionary (see + inflateSetDictionary). The dictionary should consist of strings (byte sequences) that are likely to be encountered later in the data to be compressed, with the most commonly @@ -610,8 +624,8 @@ ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is inconsistent (for example if deflate has already been called for this stream - or if the compression method is bsort). deflateSetDictionary does not - perform any compression: this will be done by deflate(). + or if not at a block boundary for raw deflate). deflateSetDictionary does + not perform any compression: this will be done by deflate(). */ ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, @@ -688,9 +702,29 @@ ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, deflation of sourceLen bytes. It must be called after deflateInit() or deflateInit2(), and after deflateSetHeader(), if used. This would be used to allocate an output buffer for deflation in a single pass, and so would be - called before deflate(). + called before deflate(). If that first deflate() call is provided the + sourceLen input bytes, an output buffer allocated to the size returned by + deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed + to return Z_STREAM_END. Note that it is possible for the compressed size to + be larger than the value returned by deflateBound() if flush options other + than Z_FINISH or Z_NO_FLUSH are used. */ +ZEXTERN int ZEXPORT deflatePending OF((z_streamp strm, + unsigned *pending, + int *bits)); +/* + deflatePending() returns the number of bytes and bits of output that have + been generated, but not yet provided in the available output. The bytes not + provided would be due to the available output space having being consumed. + The number of bits of output not provided are between 0 and 7, where they + await more bits to join them in order to fill out a full byte. If pending + or bits are Z_NULL, then those values are not set. + + deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. + */ + ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, int bits, int value)); @@ -703,8 +737,9 @@ ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, than or equal to 16, and that many of the least significant bits of value will be inserted in the output. - deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. + deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough + room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the + source stream state was inconsistent. */ ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, @@ -790,10 +825,11 @@ ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, if that call returned Z_NEED_DICT. The dictionary chosen by the compressor can be determined from the adler32 value returned by that call of inflate. The compressor and decompressor must use exactly the same dictionary (see - deflateSetDictionary). For raw inflate, this function can be called - immediately after inflateInit2() or inflateReset() and before any call of - inflate() to set the dictionary. The application must insure that the - dictionary that was used for compression is provided. + deflateSetDictionary). For raw inflate, this function can be called at any + time to set the dictionary. If the provided dictionary is smaller than the + window and there is already data in the window, then the provided dictionary + will amend what's there. The application must insure that the dictionary + that was used for compression is provided. inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is @@ -803,19 +839,38 @@ ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, inflate(). */ +ZEXTERN int ZEXPORT inflateGetDictionary OF((z_streamp strm, + Bytef *dictionary, + uInt *dictLength)); +/* + Returns the sliding dictionary being maintained by inflate. dictLength is + set to the number of bytes in the dictionary, and that many bytes are copied + to dictionary. dictionary must have enough space, where 32768 bytes is + always enough. If inflateGetDictionary() is called with dictionary equal to + Z_NULL, then only the dictionary length is returned, and nothing is copied. + Similary, if dictLength is Z_NULL, then it is not set. + + inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the + stream state is inconsistent. +*/ + ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); /* - Skips invalid compressed data until a full flush point (see above the - description of deflate with Z_FULL_FLUSH) can be found, or until all + Skips invalid compressed data until a possible full flush point (see above + for the description of deflate with Z_FULL_FLUSH) can be found, or until all available input is skipped. No output is provided. - inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR - if no more input was provided, Z_DATA_ERROR if no flush point has been - found, or Z_STREAM_ERROR if the stream structure was inconsistent. In the - success case, the application may save the current current value of total_in - which indicates where valid compressed data was found. In the error case, - the application may repeatedly call inflateSync, providing more input each - time, until success or end of the input data. + inflateSync searches for a 00 00 FF FF pattern in the compressed data. + All full flush points have this pattern, but not all occurrences of this + pattern are full flush points. + + inflateSync returns Z_OK if a possible full flush point has been found, + Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point + has been found, or Z_STREAM_ERROR if the stream structure was inconsistent. + In the success case, the application may save the current current value of + total_in which indicates where valid compressed data was found. In the + error case, the application may repeatedly call inflateSync, providing more + input each time, until success or end of the input data. */ ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, @@ -962,12 +1017,13 @@ ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, See inflateBack() for the usage of these routines. inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of - the paramaters are invalid, Z_MEM_ERROR if the internal state could not be + the parameters are invalid, Z_MEM_ERROR if the internal state could not be allocated, or Z_VERSION_ERROR if the version of the library does not match the version of the header file. */ -typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *)); +typedef unsigned (*in_func) OF((void FAR *, + z_const unsigned char FAR * FAR *)); typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, @@ -975,11 +1031,12 @@ ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, out_func out, void FAR *out_desc)); /* inflateBack() does a raw inflate with a single call using a call-back - interface for input and output. This is more efficient than inflate() for - file i/o applications in that it avoids copying between the output and the - sliding window by simply making the window itself the output buffer. This - function trusts the application to not change the output buffer passed by - the output function, at least until inflateBack() returns. + interface for input and output. This is potentially more efficient than + inflate() for file i/o applications, in that it avoids copying between the + output and the sliding window by simply making the window itself the output + buffer. inflate() can be faster on modern CPUs when used with large + buffers. inflateBack() trusts the application to not change the output + buffer passed by the output function, at least until inflateBack() returns. inflateBackInit() must be called first to allocate the internal state and to initialize the state with the user-provided window buffer. @@ -1088,6 +1145,7 @@ ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); 27-31: 0 (reserved) */ +#ifndef Z_SOLO /* utility functions */ @@ -1149,10 +1207,11 @@ ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, uncompress returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output - buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. In + the case where there is not enough room, uncompress() will fill the output + buffer with the uncompressed data up to that point. */ - /* gzip file access functions */ /* @@ -1162,7 +1221,7 @@ ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, wrapper, documented in RFC 1952, wrapped around a deflate stream. */ -typedef voidp gzFile; /* opaque gzip file descriptor */ +typedef struct gzFile_s *gzFile; /* semi-opaque gzip file descriptor */ /* ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); @@ -1172,13 +1231,28 @@ ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F' for fixed code compression as in "wb9F". (See the description of - deflateInit2 for more information about the strategy parameter.) Also "a" - can be used instead of "w" to request that the gzip stream that will be - written be appended to the file. "+" will result in an error, since reading - and writing to the same gzip file is not supported. + deflateInit2 for more information about the strategy parameter.) 'T' will + request transparent writing or appending with no compression and not using + the gzip format. + + "a" can be used instead of "w" to request that the gzip stream that will + be written be appended to the file. "+" will result in an error, since + reading and writing to the same gzip file is not supported. The addition of + "x" when writing will create the file exclusively, which fails if the file + already exists. On systems that support it, the addition of "e" when + reading or writing will set the flag to close the file on an execve() call. + + These functions, as well as gzip, will read and decode a sequence of gzip + streams in a file. The append function of gzopen() can be used to create + such a file. (Also see gzflush() for another way to do this.) When + appending, gzopen does not test whether the file begins with a gzip stream, + nor does it look for the end of the gzip streams to begin appending. gzopen + will simply append a gzip stream to the existing file. gzopen can be used to read a file which is not in gzip format; in this - case gzread will directly read from the file without decompression. + case gzread will directly read from the file without decompression. When + reading, this will be detected automatically by looking for the magic two- + byte gzip header. gzopen returns NULL if the file could not be opened, if there was insufficient memory to allocate the gzFile state, or if an invalid mode was @@ -1197,7 +1271,11 @@ ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd, mode);. The duplicated descriptor should be saved to avoid a leak, since - gzdopen does not close fd if it fails. + gzdopen does not close fd if it fails. If you are using fileno() to get the + file descriptor from a FILE *, then you will have to use dup() to avoid + double-close()ing the file descriptor. Both gzclose() and fclose() will + close the associated file descriptor, so they need to have different file + descriptors. gzdopen returns NULL if there was insufficient memory to allocate the gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not @@ -1235,14 +1313,26 @@ ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); /* Reads the given number of uncompressed bytes from the compressed file. If - the input file was not in gzip format, gzread copies the given number of - bytes into the buffer. + the input file is not in gzip format, gzread copies the given number of + bytes into the buffer directly from the file. After reaching the end of a gzip stream in the input, gzread will continue - to read, looking for another gzip stream, or failing that, reading the rest - of the input file directly without decompression. The entire input file - will be read if gzread is called until it returns less than the requested - len. + to read, looking for another gzip stream. Any number of gzip streams may be + concatenated in the input file, and will all be decompressed by gzread(). + If something other than a gzip stream is encountered after a gzip stream, + that remaining trailing garbage is ignored (and no error is returned). + + gzread can be used to read a gzip file that is being concurrently written. + Upon reaching the end of the input, gzread will return with the available + data. If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then + gzclearerr can be used to clear the end of file indicator in order to permit + gzread to be tried again. Z_OK indicates that a gzip stream was completed + on the last gzread. Z_BUF_ERROR indicates that the input file ended in the + middle of a gzip stream. Note that gzread does not return -1 in the event + of an incomplete gzip stream. This error is deferred until gzclose(), which + will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip + stream. Alternatively, gzerror can be used before gzclose to detect this + case. gzread returns the number of uncompressed bytes actually read, less than len for end of file, or -1 for error. @@ -1256,7 +1346,7 @@ ZEXTERN int ZEXPORT gzwrite OF((gzFile file, error. */ -ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); +ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...)); /* Converts, formats, and writes the arguments to the compressed file under control of the format string, as in fprintf. gzprintf returns the number of @@ -1301,7 +1391,10 @@ ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); /* Reads one byte from the compressed file. gzgetc returns this byte or -1 - in case of end of file or error. + in case of end of file or error. This is implemented as a macro for speed. + As such, it does not do all of the checking the other functions do. I.e. + it does not check to see if file is NULL, nor whether the structure file + points to has been clobbered or not. */ ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); @@ -1397,9 +1490,7 @@ ZEXTERN int ZEXPORT gzeof OF((gzFile file)); ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); /* Returns true (1) if file is being copied directly while reading, or false - (0) if file is a gzip stream being decompressed. This state can change from - false to true while reading the input file if the end of a gzip stream is - reached, but is followed by data that is not another gzip stream. + (0) if file is a gzip stream being decompressed. If the input file is empty, gzdirect() will return true, since the input does not contain a gzip stream. @@ -1408,6 +1499,13 @@ ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); cause buffers to be allocated to allow reading the file to determine if it is a gzip file. Therefore if gzbuffer() is used, it should be called before gzdirect(). + + When writing, gzdirect() returns true (1) if transparent writing was + requested ("wT" for the gzopen() mode), or false (0) otherwise. (Note: + gzdirect() is not needed when writing. Transparent writing must be + explicitly requested, so the application already knows the answer. When + linking statically, using gzdirect() will include all of the zlib code for + gzip file reading and decompression, which may not be desired.) */ ZEXTERN int ZEXPORT gzclose OF((gzFile file)); @@ -1419,7 +1517,8 @@ ZEXTERN int ZEXPORT gzclose OF((gzFile file)); must not be called more than once on the same allocation. gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a - file operation error, or Z_OK on success. + file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the + last read ended in the middle of a gzip stream, or Z_OK on success. */ ZEXTERN int ZEXPORT gzclose_r OF((gzFile file)); @@ -1457,6 +1556,7 @@ ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); file that is being written concurrently. */ +#endif /* !Z_SOLO */ /* checksum functions */ @@ -1492,16 +1592,17 @@ ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of - seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. + seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. Note + that the z_off_t type (like off_t) is a signed integer. If len2 is + negative, the result has no meaning or utility. */ ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); /* Update a running CRC-32 with the bytes buf[0..len-1] and return the updated CRC-32. If buf is Z_NULL, this function returns the required - initial value for the for the crc. Pre- and post-conditioning (one's - complement) is performed within this function so it shouldn't be done by the - application. + initial value for the crc. Pre- and post-conditioning (one's complement) is + performed within this function so it shouldn't be done by the application. Usage example: @@ -1544,17 +1645,42 @@ ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, const char *version, int stream_size)); #define deflateInit(strm, level) \ - deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) + deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) #define inflateInit(strm) \ - inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) + inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) #define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ - (strategy), ZLIB_VERSION, sizeof(z_stream)) + (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) #define inflateInit2(strm, windowBits) \ - inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) + inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ + (int)sizeof(z_stream)) #define inflateBackInit(strm, windowBits, window) \ inflateBackInit_((strm), (windowBits), (window), \ - ZLIB_VERSION, sizeof(z_stream)) + ZLIB_VERSION, (int)sizeof(z_stream)) + +#ifndef Z_SOLO + +/* gzgetc() macro and its supporting function and exposed data structure. Note + * that the real internal state is much larger than the exposed structure. + * This abbreviated structure exposes just enough for the gzgetc() macro. The + * user should not mess with these exposed elements, since their names or + * behavior could change in the future, perhaps even capriciously. They can + * only be used by the gzgetc() macro. You have been warned. + */ +struct gzFile_s { + unsigned have; + unsigned char *next; + z_off64_t pos; +}; +ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */ +#ifdef Z_PREFIX_SET +# undef z_gzgetc +# define z_gzgetc(g) \ + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : gzgetc(g)) +#else +# define gzgetc(g) \ + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : gzgetc(g)) +#endif /* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if @@ -1562,7 +1688,7 @@ ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, * functions are changed to 64 bits) -- in case these are set on systems * without large file support, _LFS64_LARGEFILE must also be true */ -#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 +#ifdef Z_LARGE64 ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); @@ -1571,14 +1697,23 @@ ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t)); #endif -#if !defined(ZLIB_INTERNAL) && _FILE_OFFSET_BITS-0 == 64 && _LFS64_LARGEFILE-0 -# define gzopen gzopen64 -# define gzseek gzseek64 -# define gztell gztell64 -# define gzoffset gzoffset64 -# define adler32_combine adler32_combine64 -# define crc32_combine crc32_combine64 -# ifdef _LARGEFILE64_SOURCE +#if !defined(ZLIB_INTERNAL) && defined(Z_WANT64) +# ifdef Z_PREFIX_SET +# define z_gzopen z_gzopen64 +# define z_gzseek z_gzseek64 +# define z_gztell z_gztell64 +# define z_gzoffset z_gzoffset64 +# define z_adler32_combine z_adler32_combine64 +# define z_crc32_combine z_crc32_combine64 +# else +# define gzopen gzopen64 +# define gzseek gzseek64 +# define gztell gztell64 +# define gzoffset gzoffset64 +# define adler32_combine adler32_combine64 +# define crc32_combine crc32_combine64 +# endif +# ifndef Z_LARGE64 ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int)); ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile)); @@ -1595,6 +1730,13 @@ ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); #endif +#else /* Z_SOLO */ + + ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); + +#endif /* !Z_SOLO */ + /* hack for buggy compilers */ #if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) struct internal_state {int dummy;}; @@ -1603,8 +1745,21 @@ ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, /* undocumented functions */ ZEXTERN const char * ZEXPORT zError OF((int)); ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp)); -ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); +ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table OF((void)); ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int)); +ZEXTERN int ZEXPORT inflateResetKeep OF((z_streamp)); +ZEXTERN int ZEXPORT deflateResetKeep OF((z_streamp)); +#if defined(_WIN32) && !defined(Z_SOLO) +ZEXTERN gzFile ZEXPORT gzopen_w OF((const wchar_t *path, + const char *mode)); +#endif +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifndef Z_SOLO +ZEXTERN int ZEXPORTVA gzvprintf Z_ARG((gzFile file, + const char *format, + va_list va)); +# endif +#endif #ifdef __cplusplus } diff --git a/zlib/Readme b/zlib/Readme new file mode 100644 index 0000000..e8ba480 --- /dev/null +++ b/zlib/Readme @@ -0,0 +1,2 @@ +Take both .lib files and put it to Visual_Studio installation folder\VC\lib\ +or compile it yourself from the official source code (http://zlib.net/zlib-1.2.8.tar.gz) \ No newline at end of file diff --git a/zlib/zlib.lib b/zlib/zlib.lib new file mode 100644 index 0000000..edaf56f Binary files /dev/null and b/zlib/zlib.lib differ diff --git a/zlib/zlibd.lib b/zlib/zlibd.lib new file mode 100644 index 0000000..bf30b8b Binary files /dev/null and b/zlib/zlibd.lib differ