├── chovy-trans.ico
├── PspCrypto
├── __sce_discinfo
├── Libraries.cs
├── PspParameter.cs
├── Security
│ └── Cryptography
│ │ ├── HashAlgorithmNames.cs
│ │ ├── HashProviderDispenser.cs
│ │ ├── EbootPbpKCalculator.cs
│ │ ├── HashProvider.cs
│ │ ├── HMACManagedHashProvider.cs
│ │ ├── HMACCommon.cs
│ │ ├── SHA224.cs
│ │ ├── HMACSHA224.cs
│ │ ├── ECDsaManaged.cs
│ │ └── SHAManagedHashProvider.cs
├── SceRtc.cs
├── PspCrypto.csproj
├── SceDdrdb.cs
├── Utils.cs
├── Lz.cs
├── Resource.Designer.cs
├── AtracCrypto.cs
├── ECDsaHelper.cs
├── DNASHelper.cs
├── Resource.resx
├── Structs.cs
└── AesHelper.cs
├── CHOVY-TRANSFER
├── chovytrans.gif
├── chovy-trans.ico
├── App.config
├── Properties
│ ├── Settings.settings
│ ├── PublishProfiles
│ │ ├── FolderProfile.pubxml.user
│ │ └── FolderProfile.pubxml
│ ├── AssemblyInfo.cs
│ ├── Settings.Designer.cs
│ ├── Resources.Designer.cs
│ └── Resources.resx
├── CHOVY-TRANSFER.csproj.user
├── Program.cs
├── CHOVY-TRANSFER.csproj
├── Sfo.cs
└── CHOVYTRANSFER.Designer.cs
├── .gitignore
├── LiLib
├── LiLib.csproj
├── MathUtil.cs
├── Progress
│ ├── ProgressTracker.cs
│ └── ProgressInfo.cs
└── StreamUtil.cs
├── Vita
├── Vita.csproj
├── ContentManager
│ ├── Account.cs
│ ├── KeyGenerator.cs
│ └── SettingsReader.cs
└── PsvImgTools
│ ├── PSVIMGStructs.cs
│ ├── PSVMDBuilder.cs
│ ├── PSVIMGStream.cs
│ └── PSVIMGFileStream.cs
├── README.md
└── CHOVY-TRANSFER.sln
/chovy-trans.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LiEnby/chovy-trans/HEAD/chovy-trans.ico
--------------------------------------------------------------------------------
/PspCrypto/__sce_discinfo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LiEnby/chovy-trans/HEAD/PspCrypto/__sce_discinfo
--------------------------------------------------------------------------------
/CHOVY-TRANSFER/chovytrans.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LiEnby/chovy-trans/HEAD/CHOVY-TRANSFER/chovytrans.gif
--------------------------------------------------------------------------------
/CHOVY-TRANSFER/chovy-trans.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LiEnby/chovy-trans/HEAD/CHOVY-TRANSFER/chovy-trans.ico
--------------------------------------------------------------------------------
/PspCrypto/Libraries.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | internal static class Libraries
6 | {
7 | internal const string CryptoNative = "PspCryptoHelper";
8 | }
9 |
--------------------------------------------------------------------------------
/CHOVY-TRANSFER/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .vs/*
2 | */obj/*
3 | */bin/*
4 |
5 | Thumbs.Db
6 |
7 | CHOVY-GEN/Debug/*
8 | CHOVY-GEN/Release/*
9 |
10 | LiLib/bin/*
11 | LiLib/obj/*
12 |
13 | Vita/bin/*
14 | Vita/lib/*
15 |
16 | CHOVY-TRANSFER/obj/*
17 | CHOVY-TRANSFER/bin/*
--------------------------------------------------------------------------------
/LiLib/LiLib.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net6.0
5 | enable
6 | enable
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/PspCrypto/PspParameter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace ECDsaTest
6 | {
7 | internal class PspParameter
8 | {
9 | public byte[] Kinv { get; set; }
10 | public byte[] Rp { get; set; }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/CHOVY-TRANSFER/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/PspCrypto/Security/Cryptography/HashAlgorithmNames.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace PspCrypto.Security.Cryptography
8 | {
9 | internal static class HashAlgorithmNames
10 | {
11 | public const string SHA224 = "SHA224";
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/CHOVY-TRANSFER/CHOVY-TRANSFER.csproj.user:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | <_LastSelectedProfileId>C:\Users\Li\Documents\git\chovy-trans\CHOVY-TRANSFER\Properties\PublishProfiles\FolderProfile.pubxml
5 |
6 |
7 |
8 | Form
9 |
10 |
11 |
--------------------------------------------------------------------------------
/CHOVY-TRANSFER/Properties/PublishProfiles/FolderProfile.pubxml.user:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 | True|2023-07-10T03:53:35.4493264Z;True|2023-07-10T15:48:49.3356830+12:00;True|2023-07-10T15:44:35.4847823+12:00;True|2023-07-10T15:42:39.5955955+12:00;True|2023-07-10T15:30:22.5199359+12:00;True|2023-07-10T13:56:34.8005938+12:00;
8 |
9 |
10 |
--------------------------------------------------------------------------------
/Vita/Vita.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net6.0
5 | enable
6 | enable
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/CHOVY-TRANSFER/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 | [assembly: AssemblyTrademark("")]
5 | [assembly: AssemblyCulture("")]
6 |
7 | // Setting ComVisible to false makes the types in this assembly not visible
8 | // to COM components. If you need to access a type in this assembly from
9 | // COM, set the ComVisible attribute to true on that type.
10 | [assembly: ComVisible(false)]
11 |
12 | // The following GUID is for the ID of the typelib if this project is exposed to COM
13 | [assembly: Guid("b4cad2c0-ba54-46b6-a8d0-43a9c2390d3c")]
14 |
--------------------------------------------------------------------------------
/CHOVY-TRANSFER/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using System.Windows.Forms;
6 |
7 | namespace CHOVY_TRANSFER
8 | {
9 | static class Program
10 | {
11 | ///
12 | /// The main entry point for the application.
13 | ///
14 | [STAThread]
15 | static void Main()
16 | {
17 | Application.EnableVisualStyles();
18 | Application.SetCompatibleTextRenderingDefault(false);
19 | Application.Run(new CHOVYTRANSFER());
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/CHOVY-TRANSFER/Properties/PublishProfiles/FolderProfile.pubxml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 | Release
8 | Any CPU
9 | bin\Release\net6.0-windows\publish\win-x86\
10 | FileSystem
11 | <_TargetId>Folder
12 | net6.0-windows
13 | win-x86
14 | true
15 | true
16 | true
17 |
18 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | #Chovy-Trans
2 | Allows you to transfer DIGITAL PS1 or PSP games from your PlayStation Portable onto your PlayStation Vita. via content mannager assistant
3 |
4 | NOTE: This is NOT a HACK! - it is the same as if you installed the game on your PSVita then backed it up with Content Mannager
5 |
6 | And does NOT enable piracy, you can only bring DIGITAL games you legally own on your own PSP over to PSVita no Copy Protection is broken here.
7 |
8 | For that -- you would need : [Chovy-Sign2](https://github.com/KuromeSan/chovy-sign/)
9 |
10 | heres an example of Spyro The Dragon running on a USA account: https://www.youtube.com/watch?v=CO5vgqEAiD0
11 |
12 | Usage: https://www.youtube.com/watch?v=iDjOHnM3ZHk
13 |
14 | credit: SteelWolf89, Cloud Strife, dots-tb, motoharu
15 |
--------------------------------------------------------------------------------
/PspCrypto/SceRtc.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace PspCrypto
8 | {
9 | public class SceRtc
10 | {
11 | public static ulong ksceRtcGetCurrentTick()
12 | {
13 | return ksceRtcGetCurrentSecureTick();
14 | }
15 |
16 | public static ulong ksceRtcGetCurrentNetworkTick()
17 | {
18 | return ksceRtcGetCurrentSecureTick();
19 | }
20 | public static ulong ksceRtcGetCurrentSecureTick()
21 | {
22 | DateTime epoch = new DateTime(1, 1, 1, 0, 0, 0);
23 | DateTime now = DateTime.UtcNow;
24 | TimeSpan ts = now.Subtract(epoch);
25 | return Convert.ToUInt64(Math.Floor(ts.TotalMilliseconds)) * 1000;
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/PspCrypto/PspCrypto.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net6.0
5 | true
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | True
17 | True
18 | Resource.resx
19 |
20 |
21 |
22 |
23 |
24 | ResXFileCodeGenerator
25 | Resource.Designer.cs
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/LiLib/MathUtil.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace Li.Utilities
8 | {
9 | public static class MathUtil
10 | {
11 | public static int CalculateDifference(int val1, int val2)
12 | {
13 | int smaller = Convert.ToInt32(Math.Min(val1, val2));
14 | int larger = Convert.ToInt32(Math.Max(val1, val2));
15 |
16 | return larger - smaller;
17 | }
18 |
19 | public static byte[] StringToByteArray(string hex)
20 | {
21 | return Enumerable.Range(0, hex.Length).Where(x => x % 2 == 0).Select(x => Convert.ToByte(hex.Substring(x, 2), 16)).ToArray();
22 | }
23 |
24 | public static int CalculatePaddingAmount(int total, int alignTo)
25 | {
26 | int remainder = total % alignTo;
27 | int padAmt = alignTo - (remainder);
28 | if ((remainder) == 0) return 0;
29 | return padAmt;
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/PspCrypto/SceDdrdb.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Runtime.CompilerServices;
4 | using System.Runtime.InteropServices;
5 | using System.Security.Cryptography;
6 | using System.Text;
7 |
8 | namespace PspCrypto
9 | {
10 | public static class SceDdrdb
11 | {
12 | public static int sceDdrdbHash(ReadOnlySpan src, int size, Span digest)
13 | {
14 | SHA1.HashData(src[..size], digest);
15 | return 0;
16 | }
17 |
18 | public static int sceDdrdbSigvry(ReadOnlySpan pubKey, ReadOnlySpan hash, ReadOnlySpan sig)
19 | {
20 | Span buff = stackalloc byte[Marshal.SizeOf()];
21 | ref KIRKEngine.KIRK_CMD17_BUFFER buffer = ref MemoryMarshal.AsRef(buff);
22 | pubKey[..0x28].CopyTo(buffer.public_key.point);
23 | hash[..20].CopyTo(buffer.message_hash);
24 | sig[..0x28].CopyTo(buffer.signature.sig);
25 | return KIRKEngine.sceUtilsBufferCopyWithRange(null, 0, buff, 100, KIRKEngine.KIRK_CMD_ECDSA_VERIFY);
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/PspCrypto/Utils.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.InteropServices;
3 |
4 | namespace PspCrypto
5 | {
6 | public static class Utils
7 | {
8 | public static bool IsEmpty(Span buf, int buf_size)
9 | {
10 | if (buf != null && buf.Length >= buf_size)
11 | {
12 | int i;
13 | for (i = 0; i < buf_size; i++)
14 | {
15 | if (buf[i] != 0) return false;
16 | }
17 | }
18 | return true;
19 | }
20 |
21 | public static void BuildDrmBBMacFinal2(Span mac)
22 | {
23 | Span checksum = new byte[20 + 0x10];
24 | ref var aesHdr = ref MemoryMarshal.AsRef(checksum);
25 | aesHdr.mode = KIRKEngine.KIRK_MODE_ENCRYPT_CBC;
26 | aesHdr.keyseed = 0x63;
27 | aesHdr.data_size = 0x10;
28 | mac.CopyTo(checksum.Slice(20));
29 | KIRKEngine.sceUtilsBufferCopyWithRange(checksum, 0x10, checksum, 0x10,
30 | KIRKEngine.KIRK_CMD_ENCRYPT_IV_0);
31 | checksum.Slice(20, 0x10).CopyTo(mac);
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/CHOVY-TRANSFER/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace CHOVY_TRANSFER.Properties {
12 |
13 |
14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.4.0.0")]
16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
17 |
18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
19 |
20 | public static Settings Default {
21 | get {
22 | return defaultInstance;
23 | }
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Vita/ContentManager/Account.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace Vita.ContentManager
8 | {
9 | public class Account
10 | {
11 | public Account(UInt64 accountId)
12 | {
13 | this.accountId = accountId;
14 | }
15 | private UInt64 accountId;
16 | public bool Devkit;
17 |
18 | public byte[] AccountId
19 | {
20 | get
21 | {
22 | if (Devkit) return new byte[8];
23 | return BitConverter.GetBytes(accountId);
24 | }
25 | }
26 | public string AccountIdStr
27 | {
28 | get
29 | {
30 | return BitConverter.ToString(AccountId).Replace("-", "").ToLowerInvariant();
31 | }
32 | }
33 |
34 | public string CmaKeyStr
35 | {
36 | get
37 | {
38 | return KeyGenerator.GenerateKeyStr(AccountIdStr);
39 | }
40 | }
41 |
42 | public byte[] CmaKey
43 | {
44 | get
45 | {
46 | return KeyGenerator.GenerateKey(AccountId);
47 | }
48 | }
49 |
50 |
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/LiLib/Progress/ProgressTracker.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace Li.Progress
8 | {
9 | public class ProgressTracker
10 | {
11 | private List> progressCallbacks = new List>();
12 |
13 | public void RegisterCallback(Action cb)
14 | {
15 | progressCallbacks.Add(cb);
16 | }
17 |
18 | protected void copyToProgress(Stream src, Stream dst, string msg)
19 | {
20 | src.Seek(0, SeekOrigin.Begin);
21 | byte[] readBuffer = new byte[0x30000];
22 | while (src.Position < src.Length)
23 | {
24 | int readAmt = src.Read(readBuffer, 0x00, readBuffer.Length);
25 | dst.Write(readBuffer, 0x00, readAmt);
26 |
27 | updateProgress(Convert.ToInt32(src.Position), Convert.ToInt32(src.Length), msg);
28 | }
29 | }
30 |
31 | protected void updateProgress(int done, int remain, string what)
32 | {
33 | ProgressInfo inf = new ProgressInfo(done, remain, what);
34 | foreach (Action cb in progressCallbacks)
35 | cb(inf);
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/CHOVY-TRANSFER/CHOVY-TRANSFER.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net6.0-windows
4 | WinExe
5 | CHOVY_TRANSFER
6 | CHOVY-TRANS
7 | false
8 | true
9 | true
10 |
11 |
12 | chovy-trans.ico
13 | CHOVY-TRANSFER
14 | CHOVY-TRANSFER
15 | Copyright © 2019
16 | 1.0.0.0
17 | 1.0.0.0
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/LiLib/Progress/ProgressInfo.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace Li.Progress
8 | {
9 | public class ProgressInfo
10 | {
11 | private int totalDone;
12 | private int totalRemain;
13 | private string currentlyDoing;
14 |
15 | public int Done
16 | {
17 | get
18 | {
19 | return totalDone;
20 | }
21 | }
22 |
23 | public int Remain
24 | {
25 | get
26 | {
27 | return totalRemain;
28 | }
29 | }
30 |
31 | public string CurrentProcess
32 | {
33 | get
34 | {
35 | return currentlyDoing;
36 | }
37 | }
38 |
39 | public double Progress
40 | {
41 | get
42 | {
43 | return Convert.ToDouble(totalDone) / Convert.ToDouble(totalRemain) * 100.0;
44 | }
45 | }
46 |
47 | public int ProgressInt
48 | {
49 | get
50 | {
51 | return Convert.ToInt32(Math.Floor(Progress));
52 | }
53 | }
54 |
55 | internal ProgressInfo(int done, int remain, string currentProcess)
56 | {
57 | totalDone = done;
58 | totalRemain = remain;
59 | currentlyDoing = currentProcess;
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/PspCrypto/Lz.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Drawing;
4 | using System.IO;
5 | using System.Text;
6 |
7 | namespace PspCrypto
8 | {
9 | public class Lz
10 | {
11 | public static byte[] compress(byte[] in_buf, bool np9660=false)
12 | {
13 | //Decoder decoder = new Decoder();
14 | //using var inStream = new MemoryStream(@in);
15 | //using var outStream = new MemoryStream(@out);
16 | //byte[] properties = new byte[5];
17 | //inStream.Read(properties, 0, 5);
18 | //decoder.SetDecoderProperties(properties);
19 | //decoder.Code(inStream, outStream, insize, size, null);
20 | //return 0;
21 | var lzrc = new Lzrc(np9660);
22 |
23 | // compress data, and get the compressed data length
24 | return lzrc.lzrc_compress(in_buf, in_buf.Length);
25 | }
26 | public static int decompress(byte[] @out, byte[] @in, int size, int insize, bool np9660=false)
27 | {
28 | //Decoder decoder = new Decoder();
29 | //using var inStream = new MemoryStream(@in);
30 | //using var outStream = new MemoryStream(@out);
31 | //byte[] properties = new byte[5];
32 | //inStream.Read(properties, 0, 5);
33 | //decoder.SetDecoderProperties(properties);
34 | //decoder.Code(inStream, outStream, insize, size, null);
35 | //return 0;
36 | var lzrc = new Lzrc(np9660);
37 | lzrc.lzrc_decompress(@out, size, @in, insize);
38 | return 0;
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/PspCrypto/Security/Cryptography/HashProviderDispenser.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Security.Cryptography;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace PspCrypto.Security.Cryptography
9 | {
10 | internal class HashProviderDispenser
11 | {
12 | public static HashProvider CreateHashProvider(string hashAlgorithmId)
13 | {
14 | switch (hashAlgorithmId)
15 | {
16 | case HashAlgorithmNames.SHA224:
17 | return new SHAManagedHashProvider(hashAlgorithmId);
18 | }
19 | throw new CryptographicException(string.Format("'{0}' is not a known hash algorithm.", hashAlgorithmId));
20 | }
21 |
22 | public static class OneShotHashProvider
23 | {
24 | public static unsafe int MacData(
25 | string hashAlgorithmId,
26 | ReadOnlySpan key,
27 | ReadOnlySpan source,
28 | Span destination)
29 | {
30 | using HashProvider provider = CreateMacProvider(hashAlgorithmId, key);
31 | provider.AppendHashData(source);
32 | return provider.FinalizeHashAndReset(destination);
33 | }
34 |
35 | public static int HashData(string hashAlgorithmId, ReadOnlySpan source, Span destination)
36 | {
37 | HashProvider provider = CreateHashProvider(hashAlgorithmId);
38 | provider.AppendHashData(source);
39 | return provider.FinalizeHashAndReset(destination);
40 | }
41 | }
42 |
43 | public static unsafe HashProvider CreateMacProvider(string hashAlgorithmId, ReadOnlySpan key)
44 | {
45 | switch (hashAlgorithmId)
46 | {
47 | case HashAlgorithmNames.SHA224:
48 | return new HMACManagedHashProvider(hashAlgorithmId, key);
49 | }
50 | throw new CryptographicException(string.Format("'{0}' is not a known hash algorithm.", hashAlgorithmId));
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/Vita/ContentManager/KeyGenerator.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Security.Cryptography;
4 | using System.Text;
5 |
6 | namespace Vita.ContentManager
7 | {
8 | public class KeyGenerator
9 | {
10 | static Byte[] Passphrase = Encoding.ASCII.GetBytes("Sri Jayewardenepura Kotte");
11 | static Byte[] Key = { 0xA9, 0xFA, 0x5A, 0x62, 0x79, 0x9F, 0xCC, 0x4C, 0x72, 0x6B, 0x4E, 0x2C, 0xE3, 0x50, 0x6D, 0x38 };
12 |
13 | public static string GenerateKeyStr(string Aid)
14 | {
15 | try
16 | {
17 | Int64 longlong = Convert.ToInt64(Aid, 16);
18 |
19 | byte[] AidBytes = BitConverter.GetBytes(longlong);
20 | Array.Reverse(AidBytes);
21 |
22 | byte[] DerivedKey = GenerateKey(AidBytes);
23 |
24 |
25 | return BitConverter.ToString(DerivedKey).Replace("-", "");
26 | }
27 | catch (Exception)
28 | {
29 | return "INVALID_AID";
30 | }
31 | }
32 | public static byte[] GenerateKey(byte[] Aid)
33 | {
34 | var ms = new MemoryStream();
35 | ms.Write(Aid, 0, Aid.Length);
36 | ms.Write(Passphrase, 0, Passphrase.Length);
37 | Byte[] DerviedKey = ms.ToArray();
38 | ms.Dispose();
39 |
40 | SHA256 sha = SHA256.Create();
41 | DerviedKey = sha.ComputeHash(DerviedKey);
42 | sha.Dispose();
43 |
44 | DerviedKey = Decrypt(DerviedKey, Key);
45 |
46 | return DerviedKey;
47 | }
48 |
49 | private static byte[] Decrypt(byte[] cipherData, byte[] Key)
50 | {
51 | MemoryStream ms = new MemoryStream();
52 | Aes alg = Aes.Create();
53 | alg.Mode = CipherMode.ECB;
54 | alg.Padding = PaddingMode.None;
55 | alg.KeySize = 128;
56 | alg.Key = Key;
57 | CryptoStream cs = new CryptoStream(ms,
58 | alg.CreateDecryptor(), CryptoStreamMode.Write);
59 | cs.Write(cipherData, 0, cipherData.Length);
60 | cs.Close();
61 | byte[] decryptedData = ms.ToArray();
62 | return decryptedData;
63 | }
64 |
65 | }
66 | }
--------------------------------------------------------------------------------
/PspCrypto/Resource.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace PspCrypto {
12 | using System;
13 |
14 |
15 | ///
16 | /// A strongly-typed resource class, for looking up localized strings, etc.
17 | ///
18 | // This class was auto-generated by the StronglyTypedResourceBuilder
19 | // class via a tool like ResGen or Visual Studio.
20 | // To add or remove a member, edit your .ResX file then rerun ResGen
21 | // with the /str option, or rebuild your VS project.
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resource {
26 |
27 | private static global::System.Resources.ResourceManager resourceMan;
28 |
29 | private static global::System.Globalization.CultureInfo resourceCulture;
30 |
31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
32 | internal Resource() {
33 | }
34 |
35 | ///
36 | /// Returns the cached ResourceManager instance used by this class.
37 | ///
38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
39 | internal static global::System.Resources.ResourceManager ResourceManager {
40 | get {
41 | if (object.ReferenceEquals(resourceMan, null)) {
42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("PspCrypto.Resource", typeof(Resource).Assembly);
43 | resourceMan = temp;
44 | }
45 | return resourceMan;
46 | }
47 | }
48 |
49 | ///
50 | /// Overrides the current thread's CurrentUICulture property for all
51 | /// resource lookups using this strongly typed resource class.
52 | ///
53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
54 | internal static global::System.Globalization.CultureInfo Culture {
55 | get {
56 | return resourceCulture;
57 | }
58 | set {
59 | resourceCulture = value;
60 | }
61 | }
62 |
63 | ///
64 | /// Looks up a localized resource of type System.Byte[].
65 | ///
66 | internal static byte[] @__sce_discinfo {
67 | get {
68 | object obj = ResourceManager.GetObject("__sce_discinfo", resourceCulture);
69 | return ((byte[])(obj));
70 | }
71 | }
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/PspCrypto/Security/Cryptography/EbootPbpKCalculator.cs:
--------------------------------------------------------------------------------
1 | using Org.BouncyCastle.Crypto.Digests;
2 | using Org.BouncyCastle.Crypto.Macs;
3 | using Org.BouncyCastle.Crypto.Parameters;
4 | using Org.BouncyCastle.Crypto.Signers;
5 | using Org.BouncyCastle.Math;
6 | using Org.BouncyCastle.Security;
7 | using System;
8 |
9 | namespace PspCrypto.Security.Cryptography
10 | {
11 | internal class EbootPbpKCalculator : IDsaKCalculator
12 | {
13 | private int _type;
14 |
15 | private BigInteger _n;
16 |
17 | public EbootPbpKCalculator(int type)
18 | {
19 | _type = type;
20 | }
21 |
22 | public bool IsDeterministic => true;
23 |
24 | private readonly Memory _hash = new byte[0x40];
25 |
26 | public void Init(BigInteger n, SecureRandom random)
27 | {
28 | throw new NotImplementedException();
29 | }
30 | public void Init(BigInteger n, BigInteger d, byte[] message)
31 | {
32 | _n = n;
33 | Span hmacIn = stackalloc byte[0x38];
34 | message[..0x1C].CopyTo(hmacIn);
35 | KeyVault.Eboot_priv[_type].CopyTo(hmacIn[0x1C..]);
36 |
37 | var hmac = new HMac(new Sha256Digest());
38 | hmac.Init(new KeyParameter(KeyVault.Eboot_hmacKey));
39 | hmac.BlockUpdate(hmacIn);
40 | var hmac_hash_iv = new byte[hmac.GetMacSize()];
41 | hmac.DoFinal(hmac_hash_iv);
42 |
43 | int ret;
44 | do
45 | {
46 | ret = can_be_reversed_80C17A(message, 0x1c, hmac_hash_iv, _hash.Span);
47 | if (ret != 0 || (ret = can_be_reversed_80C17A(message, 0x1c, hmac_hash_iv, _hash.Span[0x20..])) != 0)
48 | {
49 | throw new Exception();
50 | }
51 |
52 | } while (ret != 0);
53 | }
54 |
55 | public BigInteger NextK()
56 | {
57 | var bn = new BigInteger(1, _hash.Span[..0x3c]);
58 | var ret = bn.Mod(_n);
59 | return ret;
60 | }
61 |
62 |
63 | private static int can_be_reversed_80C17A(Span src, int some_size, Span iv,
64 | Span src_xored_digest)
65 | {
66 | Span src_xored = stackalloc byte[0x20];
67 | iv.CopyTo(src_xored);
68 |
69 | if (some_size > 0x20)
70 | {
71 | return 0x12;
72 | }
73 |
74 | for (int i = 0; i < some_size; i++)
75 | {
76 | src_xored[i] ^= src[i];
77 | }
78 |
79 | using var sha256 = System.Security.Cryptography.SHA256.Create();
80 | var hash = sha256.ComputeHash(src_xored.ToArray());
81 | hash.CopyTo(src_xored_digest);
82 |
83 | for (int i = 0; i < 0x20; i++)
84 | {
85 | iv[i] ^= src_xored_digest[i];
86 | }
87 |
88 | for (int i = 0; i < 0x20; i++)
89 | {
90 | if (iv[i] != 0xFF)
91 | {
92 | iv[i] += 1;
93 | break;
94 | }
95 |
96 | iv[i] = 0;
97 | }
98 |
99 | return 0;
100 | }
101 |
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/PspCrypto/Security/Cryptography/HashProvider.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace PspCrypto.Security.Cryptography
9 | {
10 | //
11 | // This abstract class represents a reusable hash object and can wrap a CNG or WinRT hash object.
12 | //
13 | internal abstract class HashProvider : IDisposable
14 | {
15 | // Adds new data to be hashed. This can be called repeatedly in order to hash data from noncontiguous sources.
16 | public void AppendHashData(byte[] data, int offset, int count)
17 | {
18 | ArgumentNullException.ThrowIfNull(data);
19 |
20 | // AppendHashData can be called via exposed APIs (e.g. a type that derives from
21 | // HMACSHA1 and calls HashCore) and could be passed bad data from there. It could
22 | // also receive a bad count from HashAlgorithm reading from a Stream that returns
23 | // an invalid number of bytes read. Since our implementations of AppendHashDataCore
24 | // end up using unsafe code, we want to be sure the arguments are valid.
25 | if (offset < 0)
26 | throw new ArgumentOutOfRangeException(nameof(offset), "Non-negative number required.");
27 | if (count < 0)
28 | throw new ArgumentOutOfRangeException(nameof(count), "Non-negative number required.");
29 | if (data.Length - offset < count)
30 | throw new ArgumentException("Offset and length were out of bounds for the array or count is greater than the number of elements from index to the end of the source collection.");
31 |
32 | AppendHashData(new ReadOnlySpan(data, offset, count));
33 | }
34 |
35 | public abstract void AppendHashData(ReadOnlySpan data);
36 |
37 | // Compute the hash based on the appended data and resets the HashProvider for more hashing.
38 | public abstract int FinalizeHashAndReset(Span destination);
39 |
40 | public abstract int GetCurrentHash(Span destination);
41 |
42 | public byte[] FinalizeHashAndReset()
43 | {
44 | byte[] ret = new byte[HashSizeInBytes];
45 |
46 | int written = FinalizeHashAndReset(ret);
47 | Debug.Assert(written == HashSizeInBytes);
48 |
49 | return ret;
50 | }
51 |
52 | public bool TryFinalizeHashAndReset(Span destination, out int bytesWritten)
53 | {
54 | if (destination.Length < HashSizeInBytes)
55 | {
56 | bytesWritten = 0;
57 | return false;
58 | }
59 |
60 | bytesWritten = FinalizeHashAndReset(destination);
61 | return true;
62 | }
63 |
64 | // Returns the length of the byte array returned by FinalizeHashAndReset.
65 | public abstract int HashSizeInBytes { get; }
66 |
67 | // Releases any native resources and keys used by the HashProvider.
68 | public void Dispose()
69 | {
70 | Dispose(true);
71 | GC.SuppressFinalize(this);
72 | }
73 |
74 | // Releases any native resources and keys used by the HashProvider.
75 | public abstract void Dispose(bool disposing);
76 |
77 | public abstract void Reset();
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/CHOVY-TRANSFER/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace CHOVY_TRANSFER.Properties {
12 | using System;
13 |
14 |
15 | ///
16 | /// A strongly-typed resource class, for looking up localized strings, etc.
17 | ///
18 | // This class was auto-generated by the StronglyTypedResourceBuilder
19 | // class via a tool like ResGen or Visual Studio.
20 | // To add or remove a member, edit your .ResX file then rerun ResGen
21 | // with the /str option, or rebuild your VS project.
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources {
26 |
27 | private static global::System.Resources.ResourceManager resourceMan;
28 |
29 | private static global::System.Globalization.CultureInfo resourceCulture;
30 |
31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
32 | internal Resources() {
33 | }
34 |
35 | ///
36 | /// Returns the cached ResourceManager instance used by this class.
37 | ///
38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
39 | internal static global::System.Resources.ResourceManager ResourceManager {
40 | get {
41 | if (object.ReferenceEquals(resourceMan, null)) {
42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("CHOVY_TRANSFER.Properties.Resources", typeof(Resources).Assembly);
43 | resourceMan = temp;
44 | }
45 | return resourceMan;
46 | }
47 | }
48 |
49 | ///
50 | /// Overrides the current thread's CurrentUICulture property for all
51 | /// resource lookups using this strongly typed resource class.
52 | ///
53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
54 | internal static global::System.Globalization.CultureInfo Culture {
55 | get {
56 | return resourceCulture;
57 | }
58 | set {
59 | resourceCulture = value;
60 | }
61 | }
62 |
63 | ///
64 | /// Looks up a localized resource of type System.Drawing.Bitmap.
65 | ///
66 | internal static System.Drawing.Bitmap chovytrans {
67 | get {
68 | object obj = ResourceManager.GetObject("chovytrans", resourceCulture);
69 | return ((System.Drawing.Bitmap)(obj));
70 | }
71 | }
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/CHOVY-TRANSFER.sln:
--------------------------------------------------------------------------------
1 | Microsoft Visual Studio Solution File, Format Version 12.00
2 | # Visual Studio Version 17
3 | VisualStudioVersion = 17.4.33205.214
4 | MinimumVisualStudioVersion = 10.0.40219.1
5 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CHOVY-TRANSFER", "CHOVY-TRANSFER\CHOVY-TRANSFER.csproj", "{B4CAD2C0-BA54-46B6-A8D0-43A9C2390D3C}"
6 | EndProject
7 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PspCrypto", "PspCrypto\PspCrypto.csproj", "{C93D6CE7-989F-4C89-A29B-9684C9297184}"
8 | EndProject
9 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vita", "Vita\Vita.csproj", "{8463BD1A-EC79-4469-A383-26020298F512}"
10 | EndProject
11 | Global
12 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
13 | Debug|Any CPU = Debug|Any CPU
14 | Debug|x64 = Debug|x64
15 | Debug|x86 = Debug|x86
16 | Release|Any CPU = Release|Any CPU
17 | Release|x64 = Release|x64
18 | Release|x86 = Release|x86
19 | EndGlobalSection
20 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
21 | {B4CAD2C0-BA54-46B6-A8D0-43A9C2390D3C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
22 | {B4CAD2C0-BA54-46B6-A8D0-43A9C2390D3C}.Debug|Any CPU.Build.0 = Debug|Any CPU
23 | {B4CAD2C0-BA54-46B6-A8D0-43A9C2390D3C}.Debug|x64.ActiveCfg = Debug|Any CPU
24 | {B4CAD2C0-BA54-46B6-A8D0-43A9C2390D3C}.Debug|x64.Build.0 = Debug|Any CPU
25 | {B4CAD2C0-BA54-46B6-A8D0-43A9C2390D3C}.Debug|x86.ActiveCfg = Debug|Any CPU
26 | {B4CAD2C0-BA54-46B6-A8D0-43A9C2390D3C}.Debug|x86.Build.0 = Debug|Any CPU
27 | {B4CAD2C0-BA54-46B6-A8D0-43A9C2390D3C}.Release|Any CPU.ActiveCfg = Release|Any CPU
28 | {B4CAD2C0-BA54-46B6-A8D0-43A9C2390D3C}.Release|Any CPU.Build.0 = Release|Any CPU
29 | {B4CAD2C0-BA54-46B6-A8D0-43A9C2390D3C}.Release|x64.ActiveCfg = Release|Any CPU
30 | {B4CAD2C0-BA54-46B6-A8D0-43A9C2390D3C}.Release|x64.Build.0 = Release|Any CPU
31 | {B4CAD2C0-BA54-46B6-A8D0-43A9C2390D3C}.Release|x86.ActiveCfg = Release|Any CPU
32 | {B4CAD2C0-BA54-46B6-A8D0-43A9C2390D3C}.Release|x86.Build.0 = Release|Any CPU
33 | {C93D6CE7-989F-4C89-A29B-9684C9297184}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
34 | {C93D6CE7-989F-4C89-A29B-9684C9297184}.Debug|Any CPU.Build.0 = Debug|Any CPU
35 | {C93D6CE7-989F-4C89-A29B-9684C9297184}.Debug|x64.ActiveCfg = Debug|Any CPU
36 | {C93D6CE7-989F-4C89-A29B-9684C9297184}.Debug|x64.Build.0 = Debug|Any CPU
37 | {C93D6CE7-989F-4C89-A29B-9684C9297184}.Debug|x86.ActiveCfg = Debug|Any CPU
38 | {C93D6CE7-989F-4C89-A29B-9684C9297184}.Debug|x86.Build.0 = Debug|Any CPU
39 | {C93D6CE7-989F-4C89-A29B-9684C9297184}.Release|Any CPU.ActiveCfg = Release|Any CPU
40 | {C93D6CE7-989F-4C89-A29B-9684C9297184}.Release|Any CPU.Build.0 = Release|Any CPU
41 | {C93D6CE7-989F-4C89-A29B-9684C9297184}.Release|x64.ActiveCfg = Release|Any CPU
42 | {C93D6CE7-989F-4C89-A29B-9684C9297184}.Release|x64.Build.0 = Release|Any CPU
43 | {C93D6CE7-989F-4C89-A29B-9684C9297184}.Release|x86.ActiveCfg = Release|Any CPU
44 | {C93D6CE7-989F-4C89-A29B-9684C9297184}.Release|x86.Build.0 = Release|Any CPU
45 | {8463BD1A-EC79-4469-A383-26020298F512}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
46 | {8463BD1A-EC79-4469-A383-26020298F512}.Debug|Any CPU.Build.0 = Debug|Any CPU
47 | {8463BD1A-EC79-4469-A383-26020298F512}.Debug|x64.ActiveCfg = Debug|Any CPU
48 | {8463BD1A-EC79-4469-A383-26020298F512}.Debug|x64.Build.0 = Debug|Any CPU
49 | {8463BD1A-EC79-4469-A383-26020298F512}.Debug|x86.ActiveCfg = Debug|Any CPU
50 | {8463BD1A-EC79-4469-A383-26020298F512}.Debug|x86.Build.0 = Debug|Any CPU
51 | {8463BD1A-EC79-4469-A383-26020298F512}.Release|Any CPU.ActiveCfg = Release|Any CPU
52 | {8463BD1A-EC79-4469-A383-26020298F512}.Release|Any CPU.Build.0 = Release|Any CPU
53 | {8463BD1A-EC79-4469-A383-26020298F512}.Release|x64.ActiveCfg = Release|Any CPU
54 | {8463BD1A-EC79-4469-A383-26020298F512}.Release|x64.Build.0 = Release|Any CPU
55 | {8463BD1A-EC79-4469-A383-26020298F512}.Release|x86.ActiveCfg = Release|Any CPU
56 | {8463BD1A-EC79-4469-A383-26020298F512}.Release|x86.Build.0 = Release|Any CPU
57 | EndGlobalSection
58 | GlobalSection(SolutionProperties) = preSolution
59 | HideSolutionNode = FALSE
60 | EndGlobalSection
61 | GlobalSection(ExtensibilityGlobals) = postSolution
62 | SolutionGuid = {D2939D13-1FC7-4C9B-95D9-BA3B53E08138}
63 | EndGlobalSection
64 | EndGlobal
65 |
--------------------------------------------------------------------------------
/PspCrypto/Security/Cryptography/HMACManagedHashProvider.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.Linq;
5 | using System.Security.Cryptography;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 |
9 | namespace PspCrypto.Security.Cryptography
10 | {
11 | internal sealed class HMACManagedHashProvider : HashProvider
12 | {
13 | private bool _hashing;
14 | private readonly int _blockSizeValue;
15 | private readonly int _hashSizeValue;
16 |
17 | private readonly byte[] _key;
18 | private readonly HashProvider _hash1;
19 | private readonly HashProvider _hash2;
20 |
21 | public HMACManagedHashProvider(string hashAlgorithmId, ReadOnlySpan key)
22 | {
23 | _hash1 = HashProviderDispenser.CreateHashProvider(hashAlgorithmId);
24 | _hash2 = HashProviderDispenser.CreateHashProvider(hashAlgorithmId);
25 |
26 | _blockSizeValue = 64;
27 | _hashSizeValue = 224 / 8;
28 |
29 | _key = InitializeKey(key);
30 | }
31 |
32 | private byte[] InitializeKey(ReadOnlySpan key)
33 | {
34 | if (key.Length > _blockSizeValue)
35 | {
36 | byte[] result = new byte[_hashSizeValue];
37 | _hash1.AppendHashData(key);
38 | int written = _hash1.FinalizeHashAndReset(result);
39 | Debug.Assert(written == result.Length);
40 |
41 | return result;
42 | }
43 |
44 | return key.ToArray();
45 | }
46 |
47 | public override void AppendHashData(ReadOnlySpan data)
48 | {
49 | if (!_hashing)
50 | {
51 | AppendInnerBuffer();
52 | _hashing = true;
53 | }
54 |
55 | _hash1.AppendHashData(data);
56 | }
57 |
58 | public override int FinalizeHashAndReset(Span destination)
59 | {
60 | int written = GetCurrentHash(destination);
61 | Reset();
62 | return written;
63 | }
64 |
65 | public override int GetCurrentHash(Span destination)
66 | {
67 | if (!_hashing)
68 | {
69 | AppendInnerBuffer();
70 | _hashing = true;
71 | }
72 |
73 | // finalize the original hash
74 | Span hashValue1 = stackalloc byte[_hashSizeValue];
75 | int hash1Written = _hash1.GetCurrentHash(hashValue1);
76 | Debug.Assert(hash1Written == hashValue1.Length);
77 |
78 | // write the outer array
79 | AppendOuterBuffer();
80 | // write the inner hash and finalize the hash
81 | _hash2.AppendHashData(hashValue1);
82 | return _hash2.FinalizeHashAndReset(destination);
83 | }
84 |
85 | private void AppendInnerBuffer() => AppendPaddingBuffer(0x36, _hash1);
86 | private void AppendOuterBuffer() => AppendPaddingBuffer(0x5C, _hash2);
87 |
88 | private void AppendPaddingBuffer(byte paddingConstant, HashProvider hash)
89 | {
90 | Span paddingBuffer = stackalloc byte[_blockSizeValue];
91 | paddingBuffer.Fill(paddingConstant);
92 |
93 | for (int i = 0; i < _key.Length; i++)
94 | {
95 | paddingBuffer[i] ^= _key[i];
96 | }
97 |
98 | hash.AppendHashData(paddingBuffer);
99 | CryptographicOperations.ZeroMemory(paddingBuffer);
100 | }
101 |
102 | public override int HashSizeInBytes => _hashSizeValue;
103 |
104 | public override void Dispose(bool disposing)
105 | {
106 | if (disposing)
107 | {
108 | _hash1.Dispose();
109 | _hash2.Dispose();
110 |
111 | CryptographicOperations.ZeroMemory(_key);
112 | }
113 | }
114 |
115 | public override void Reset()
116 | {
117 | if (_hashing)
118 | {
119 | _hash1.Reset();
120 | _hash2.Reset();
121 | _hashing = false;
122 | }
123 | }
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/PspCrypto/AtracCrypto.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Runtime.InteropServices;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 |
9 | namespace PspCrypto
10 | {
11 | public class AtracCrypto
12 | {
13 |
14 | const int NBYTES = 0x180;
15 | private static uint ROTR32(uint v, int n)
16 | {
17 | n &= 32 - 1;
18 | return (v >> n) | (v << (32 - n));
19 | }
20 |
21 | public static int UnscrambleAtracData(byte[] data, uint key)
22 | {
23 | int blocks = (data.Length / NBYTES) / 0x10;
24 | int chunks_rest = (data.Length / NBYTES) % 0x10;
25 | Span ptr = MemoryMarshal.Cast(data);
26 | uint tmp2 = key;
27 | uint tmp;
28 | uint value;
29 | // for each block
30 | while (blocks > 0)
31 | {
32 | // for each chunk of block
33 | for (int i = 0; i < 0x10; i++)
34 | {
35 | tmp = tmp2;
36 |
37 | // for each value of chunk
38 | for (int k = 0; k < (NBYTES / 4); k++)
39 | {
40 | value = ptr[k];
41 | ptr[k] = tmp ^ value;
42 | tmp = tmp2 + (value * 123456789);
43 | }
44 |
45 | tmp2 = ROTR32(tmp2, 1);
46 | ptr = ptr[(NBYTES / 4)..]; // pointer on next chunk
47 | }
48 |
49 | blocks--;
50 | }
51 |
52 | // do rest chunks
53 | for (int i = 0; i < chunks_rest; i++)
54 | {
55 | tmp = tmp2;
56 |
57 | // for each value of chunk
58 | for (int k = 0; k < (NBYTES / 4); k++)
59 | {
60 | value = ptr[k];
61 | ptr[k] = tmp ^ value;
62 | tmp = tmp2 + (value * 123456789);
63 | }
64 |
65 | tmp2 = ROTR32(tmp2, 1);
66 | ptr = ptr[(NBYTES / 4)..]; // next chunk
67 | }
68 |
69 | return 0;
70 | }
71 |
72 | public static void ScrambleAtracData(Stream input, Stream output, uint key)
73 | {
74 | int blocks = (Convert.ToInt32(input.Length) / NBYTES) / 0x10;
75 | int chunks_rest = (Convert.ToInt32(input.Length) / NBYTES) % 0x10;
76 | Span block = stackalloc byte[NBYTES];
77 | uint tmp2 = key;
78 | uint tmp;
79 | // for each block
80 | while (blocks > 0)
81 | {
82 | // for each chunk of block
83 | for (int i = 0; i < 0x10; i++)
84 | {
85 | tmp = tmp2;
86 |
87 | input.Read(block);
88 | Span ptr = MemoryMarshal.Cast(block);
89 |
90 | // for each value of chunk
91 | for (int k = 0; k < (NBYTES / 4); k++)
92 | {
93 | ptr[k] ^= tmp;
94 | tmp = tmp2 + (ptr[k] * 123456789);
95 | }
96 | output.Write(block);
97 |
98 | tmp2 = ROTR32(tmp2, 1);
99 | ptr = ptr[(NBYTES / 4)..]; // pointer on next chunk
100 | }
101 |
102 | blocks--;
103 | }
104 |
105 | // do rest chunks
106 | for (int i = 0; i < chunks_rest; i++)
107 | {
108 | tmp = tmp2;
109 |
110 | input.Read(block);
111 | Span ptr = MemoryMarshal.Cast(block);
112 |
113 | // for each value of chunk
114 | for (int k = 0; k < (NBYTES / 4); k++)
115 | {
116 | ptr[k] ^= tmp;
117 | tmp = tmp2 + (ptr[k] * 123456789);
118 | }
119 | output.Write(block);
120 |
121 | tmp2 = ROTR32(tmp2, 1);
122 | ptr = ptr[(NBYTES / 4)..]; // next chunk
123 | }
124 | }
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/PspCrypto/ECDsaHelper.cs:
--------------------------------------------------------------------------------
1 | using PspCrypto.Security.Cryptography;
2 | using System;
3 | using System.Security.Cryptography;
4 |
5 | namespace PspCrypto
6 | {
7 | public static class ECDsaHelper
8 | {
9 | public static ECCurve SetCurve(byte[] p, byte[] a, byte[] b, byte[] n, byte[] gx, byte[] gy)
10 | {
11 | return new ECCurve
12 | {
13 | A = a,
14 | B = b,
15 | Prime = p,
16 | Order = n,
17 | CurveType = ECCurve.ECCurveType.PrimeShortWeierstrass,
18 | Cofactor = new byte[] { 0x01 },
19 | G = new ECPoint { X = gx, Y = gy }
20 | };
21 | }
22 |
23 | public static (byte[], ECPoint) GenerateKey(byte[] p, byte[] a, byte[] b, byte[] n, byte[] gx, byte[] gy)
24 | {
25 | var curve = new ECCurve
26 | {
27 | A = a,
28 | B = b,
29 | Prime = p,
30 | Order = n,
31 | CurveType = ECCurve.ECCurveType.PrimeShortWeierstrass,
32 | Cofactor = new byte[] { 0x01 },
33 | G = { X = gx, Y = gy }
34 | };
35 | var ecdsa = new ECDsaManaged();
36 | ecdsa.GenerateKey(curve);
37 | var parameter = ecdsa.ExportExplicitParameters(true);
38 | return (parameter.D, parameter.Q);
39 | }
40 |
41 | public static ECDsa Create(ECCurve curve, byte[] privateKey)
42 | {
43 | return Create(curve, privateKey, new byte[privateKey.Length], new byte[privateKey.Length]);
44 | }
45 |
46 |
47 | public static ECDsa Create(ECCurve curve, byte[] pubx, byte[] puby)
48 | {
49 | return Create(curve, null, pubx, puby);
50 | }
51 |
52 | public static ECDsa Create(ECCurve curve, Span pubx, Span puby)
53 | {
54 | return Create(curve, null, pubx.ToArray(), puby.ToArray());
55 | }
56 |
57 | public static ECDsa Create(ECCurve curve, byte[] privateKey, byte[] pubx, byte[] puby, bool ebootPbp = false, int type = 1)
58 | {
59 | var par = new ECParameters
60 | {
61 | Curve = curve,
62 | D = privateKey,
63 | Q = { X = pubx, Y = puby }
64 | };
65 | return new ECDsaManaged(par, ebootPbp, type);
66 | }
67 |
68 | public static void SignNpImageHeader(Span npHdr)
69 | {
70 | var curve = SetCurve(KeyVault.ec_p, KeyVault.ec_a, KeyVault.ec_b2, KeyVault.ec_N2, KeyVault.Gx2,
71 | KeyVault.Gy2);
72 | using var ecdsa = Create(curve, KeyVault.ec_Priv2, KeyVault.Px2, KeyVault.Py2);
73 | var hash = ecdsa.SignData(npHdr[..0xD8].ToArray(), HashAlgorithmName.SHA1);
74 | hash.CopyTo(npHdr[0xD8..]);
75 | }
76 |
77 | public static bool VerifyEdat(Span edat)
78 | {
79 | var curve = SetCurve(KeyVault.ec_p, KeyVault.ec_a, KeyVault.ec_b2, KeyVault.ec_N2, KeyVault.Gx2,
80 | KeyVault.Gy2);
81 | using var ecdsa = Create(curve, KeyVault.EdatPx, KeyVault.EdatPy);
82 | return ecdsa.VerifyData(edat[..0x58], edat.Slice(0x58, 0x28), HashAlgorithmName.SHA1);
83 | }
84 |
85 | public static void SignEdat(Span edat)
86 | {
87 | var curve = SetCurve(KeyVault.ec_p, KeyVault.ec_a, KeyVault.ec_b2, KeyVault.ec_N2, KeyVault.Gx2,
88 | KeyVault.Gy2);
89 | using var ecdsa = Create(curve, KeyVault.EdatPirv, KeyVault.EdatPx, KeyVault.EdatPy);
90 | var sig = ecdsa.SignData(edat[..0x58].ToArray(), HashAlgorithmName.SHA1);
91 | sig.CopyTo(edat[0x58..]);
92 | }
93 |
94 | public static void SignParamSfo(ReadOnlySpan param, Span sig)
95 | {
96 | var curve = SetCurve(KeyVault.ec_p, KeyVault.ec_a, KeyVault.ec_b2, KeyVault.ec_N2, KeyVault.Gx2,
97 | KeyVault.Gy2);
98 | using var ecdsa = Create(curve, KeyVault.ec_Priv2, KeyVault.Px2, KeyVault.Py2);
99 | var sigTmp = ecdsa.SignData(param.ToArray(), HashAlgorithmName.SHA1);
100 | sigTmp.CopyTo(sig);
101 | }
102 |
103 | public static bool VerifyEbootPbp(Span data, Span sig)
104 | {
105 | var sha224 = SHA224.Create();
106 | var hash = sha224.ComputeHash(data.ToArray());
107 | var curve = SetCurve(KeyVault.Eboot_p, KeyVault.Eboot_a, KeyVault.Eboot_b, KeyVault.Eboot_N, KeyVault.Eboot_Gx,
108 | KeyVault.Eboot_Gy);
109 | using var ecdsa = Create(curve, KeyVault.Eboot_priv2, KeyVault.Eboot_pub2x, KeyVault.Eboot_pub2y, true);
110 | return ecdsa.VerifyHash(hash, sig);
111 | }
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/PspCrypto/Security/Cryptography/HMACCommon.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics.CodeAnalysis;
4 | using System.Diagnostics;
5 | using System.Linq;
6 | using System.Security.Cryptography;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 |
10 | namespace PspCrypto.Security.Cryptography
11 | {
12 | //
13 | // This class provides the common functionality for HMACSHA1, HMACSHA256, HMACMD5, etc.
14 | // Ideally, this would be encapsulated in a common base class but the preexisting contract
15 | // locks these public classes into deriving directly from HMAC so we have to use encapsulation
16 | // and delegation to HMACCommon instead.
17 | //
18 | // This wrapper adds the ability to change the Key on the fly for compat with the desktop.
19 | //
20 | internal sealed class HMACCommon
21 | {
22 | public HMACCommon(string hashAlgorithmId, byte[] key, int blockSize) :
23 | this(hashAlgorithmId, (ReadOnlySpan)key, blockSize)
24 | {
25 | // If the key is smaller than the block size, the delegated ctor won't have initialized ActualKey,
26 | // so set it here as would ChangeKey.
27 | ActualKey ??= key;
28 | }
29 |
30 | internal HMACCommon(string hashAlgorithmId, ReadOnlySpan key, int blockSize)
31 | {
32 | Debug.Assert(!string.IsNullOrEmpty(hashAlgorithmId));
33 | Debug.Assert(blockSize > 0 || blockSize == -1);
34 |
35 | _hashAlgorithmId = hashAlgorithmId;
36 | _blockSize = blockSize;
37 |
38 | // note: will not set ActualKey if key size is smaller or equal than blockSize
39 | // this is to avoid extra allocation. ActualKey can still be used if key is generated.
40 | // Otherwise the ReadOnlySpan overload would actually be slower than byte array overload.
41 | ActualKey = ChangeKeyImpl(key);
42 | }
43 |
44 | public int HashSizeInBits => _hMacProvider.HashSizeInBytes * 8;
45 | public int HashSizeInBytes => _hMacProvider.HashSizeInBytes;
46 |
47 | public void ChangeKey(byte[] key)
48 | {
49 | ActualKey = ChangeKeyImpl(key) ?? key;
50 | }
51 |
52 | [MemberNotNull(nameof(_hMacProvider))]
53 | private byte[] ChangeKeyImpl(ReadOnlySpan key)
54 | {
55 | byte[] modifiedKey = null;
56 |
57 | // If _blockSize is -1 the key isn't going to be extractable by the object holder,
58 | // so there's no point in recalculating it in managed code.
59 | if (key.Length > _blockSize && _blockSize > 0)
60 | {
61 | // Perform RFC 2104, section 2 key adjustment.
62 | modifiedKey = _hashAlgorithmId switch
63 | {
64 | "SHA224" => SHA224.HashData(key),
65 | _ => throw new CryptographicException(string.Format("'{0}' is not a known hash algorithm.", _hashAlgorithmId)),
66 | };
67 | }
68 |
69 | HashProvider oldHashProvider = _hMacProvider;
70 | _hMacProvider = null!;
71 | oldHashProvider?.Dispose(true);
72 | _hMacProvider = HashProviderDispenser.CreateMacProvider(_hashAlgorithmId, key);
73 |
74 | return modifiedKey;
75 | }
76 |
77 | // The actual key used for hashing. This will not be the same as the original key passed to ChangeKey() if the original key exceeded the
78 | // hash algorithm's block size. (See RFC 2104, section 2)
79 | public byte[] ActualKey { get; private set; }
80 |
81 | // Adds new data to be hashed. This can be called repeatedly in order to hash data from noncontiguous sources.
82 | public void AppendHashData(byte[] data, int offset, int count) =>
83 | _hMacProvider.AppendHashData(data, offset, count);
84 |
85 | public void AppendHashData(ReadOnlySpan source) =>
86 | _hMacProvider.AppendHashData(source);
87 |
88 | // Compute the hash based on the appended data and resets the HashProvider for more hashing.
89 | public byte[] FinalizeHashAndReset() =>
90 | _hMacProvider.FinalizeHashAndReset();
91 |
92 | public int FinalizeHashAndReset(Span destination) =>
93 | _hMacProvider.FinalizeHashAndReset(destination);
94 |
95 | public bool TryFinalizeHashAndReset(Span destination, out int bytesWritten) =>
96 | _hMacProvider.TryFinalizeHashAndReset(destination, out bytesWritten);
97 |
98 | public int GetCurrentHash(Span destination) =>
99 | _hMacProvider.GetCurrentHash(destination);
100 |
101 | public void Reset() => _hMacProvider.Reset();
102 |
103 | public void Dispose(bool disposing)
104 | {
105 | if (disposing)
106 | {
107 | _hMacProvider?.Dispose(true);
108 | _hMacProvider = null!;
109 | }
110 | }
111 |
112 | private readonly string _hashAlgorithmId;
113 | private HashProvider _hMacProvider;
114 | private readonly int _blockSize;
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/PspCrypto/Security/Cryptography/SHA224.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using System.Security.Cryptography;
5 | using System.Diagnostics;
6 |
7 | namespace PspCrypto.Security.Cryptography
8 | {
9 | public abstract class SHA224 : HashAlgorithm
10 | {
11 | ///
12 | /// The hash size produced by the SHA224 algorithm, in bits.
13 | ///
14 | public const int HashSizeInBits = 224;
15 |
16 | ///
17 | /// The hash size produced by the SHA224 algorithm, in bytes.
18 | ///
19 | public const int HashSizeInBytes = HashSizeInBits / 8;
20 |
21 | public SHA224()
22 | {
23 | // SHA-224 hash length are 224 bits long
24 | HashSizeValue = HashSizeInBits;
25 | }
26 |
27 | public static new SHA224 Create() => new Implementation();
28 |
29 | public new static SHA224 Create(string hashName)
30 | {
31 | var o = (SHA224)CryptoConfig.CreateFromName(hashName);
32 | // in case machine.config isn't configured to use any SHA224 implementation
33 | if (o == null)
34 | {
35 | o = new Implementation();
36 | }
37 | return o;
38 | }
39 |
40 | ///
41 | /// Computes the hash of data using the SHA224 algorithm.
42 | ///
43 | /// The data to hash.
44 | /// The hash of the data.
45 | ///
46 | /// is .
47 | ///
48 | public static byte[] HashData(byte[] source)
49 | {
50 | ArgumentNullException.ThrowIfNull(source);
51 |
52 | return HashData(new ReadOnlySpan(source));
53 | }
54 |
55 | ///
56 | /// Computes the hash of data using the SHA224 algorithm.
57 | ///
58 | /// The data to hash.
59 | /// The hash of the data.
60 | public static byte[] HashData(ReadOnlySpan source)
61 | {
62 | byte[] buffer = GC.AllocateUninitializedArray(HashSizeInBytes);
63 |
64 | int written = HashData(source, buffer.AsSpan());
65 | Debug.Assert(written == buffer.Length);
66 |
67 | return buffer;
68 | }
69 |
70 | ///
71 | /// Computes the hash of data using the SHA224 algorithm.
72 | ///
73 | /// The data to hash.
74 | /// The buffer to receive the hash value.
75 | /// The total number of bytes written to .
76 | ///
77 | /// The buffer in is too small to hold the calculated hash
78 | /// size. The SHA224 algorithm always produces a 224-bit hash, or 28 bytes.
79 | ///
80 | public static int HashData(ReadOnlySpan source, Span destination)
81 | {
82 | if (!TryHashData(source, destination, out int bytesWritten))
83 | throw new ArgumentException("Destination is too short.", nameof(destination));
84 |
85 | return bytesWritten;
86 | }
87 |
88 |
89 | ///
90 | /// Attempts to compute the hash of data using the SHA224 algorithm.
91 | ///
92 | /// The data to hash.
93 | /// The buffer to receive the hash value.
94 | ///
95 | /// When this method returns, the total number of bytes written into .
96 | ///
97 | ///
98 | /// if is too small to hold the
99 | /// calculated hash, otherwise.
100 | ///
101 | public static bool TryHashData(ReadOnlySpan source, Span destination, out int bytesWritten)
102 | {
103 | if (destination.Length < HashSizeInBytes)
104 | {
105 | bytesWritten = 0;
106 | return false;
107 | }
108 |
109 | bytesWritten = HashProviderDispenser.OneShotHashProvider.HashData(HashAlgorithmNames.SHA224, source, destination);
110 | Debug.Assert(bytesWritten == HashSizeInBytes);
111 |
112 | return true;
113 | }
114 |
115 | private sealed class Implementation : SHA224
116 | {
117 | private readonly HashProvider _hashProvider;
118 |
119 | public Implementation()
120 | {
121 | _hashProvider = HashProviderDispenser.CreateHashProvider(HashAlgorithmNames.SHA224);
122 | HashSizeValue = _hashProvider.HashSizeInBytes * 8;
123 | }
124 |
125 | protected sealed override void HashCore(byte[] array, int ibStart, int cbSize) =>
126 | _hashProvider.AppendHashData(array, ibStart, cbSize);
127 |
128 | protected sealed override void HashCore(ReadOnlySpan source) =>
129 | _hashProvider.AppendHashData(source);
130 |
131 | protected sealed override byte[] HashFinal() =>
132 | _hashProvider.FinalizeHashAndReset();
133 |
134 | protected sealed override bool TryHashFinal(Span destination, out int bytesWritten) =>
135 | _hashProvider.TryFinalizeHashAndReset(destination, out bytesWritten);
136 |
137 | public sealed override void Initialize() => _hashProvider.Reset();
138 |
139 | protected sealed override void Dispose(bool disposing)
140 | {
141 | _hashProvider.Dispose(disposing);
142 | base.Dispose(disposing);
143 | }
144 | }
145 | }
146 | }
147 |
--------------------------------------------------------------------------------
/PspCrypto/DNASHelper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Runtime.InteropServices;
4 | using System.Security.Cryptography;
5 | using System.Text;
6 |
7 | namespace PspCrypto
8 | {
9 | using PgdHeader = DNASStream.PgdHeader;
10 | using PgdDesc = DNASStream.PgdDesc;
11 |
12 | public static class DNASHelper
13 | {
14 | public static int CalculateSize(int dataSize, int blockSize)
15 | {
16 | int alignSize = (dataSize + 15) & ~15;
17 | int tableSize = ((alignSize + blockSize - 1) & ~(blockSize - 1)) / (blockSize / 16);
18 | int pgdSize = 0x90 + alignSize + tableSize;
19 | return pgdSize;
20 | }
21 |
22 | public static int Encrypt(Span pgdData, ReadOnlySpan data, ReadOnlySpan key, int dataSize, int keyIndex, int drmType, int flag = 2, int blockSize = 0x400)
23 | {
24 | // Additional size variables.
25 | var dataOffset = 0x90;
26 | var alignSize = (dataSize + 15) & ~15;
27 | var tableOffset = dataOffset + alignSize;
28 | var tableSize = ((alignSize + blockSize - 1) & ~(blockSize - 1)) / (blockSize / 16);
29 | var pgdSize = 0x90 + alignSize + tableSize;
30 |
31 | if (pgdData.Length < pgdSize)
32 | {
33 | return -1;
34 | }
35 |
36 | data[..dataSize].CopyTo(pgdData[dataOffset..]);
37 |
38 | ref var pgdHdr = ref MemoryMarshal.AsRef(pgdData);
39 | pgdHdr.Magic = 0x44475000;
40 | pgdHdr.KeyIndex = keyIndex;
41 | pgdHdr.DrmType = drmType;
42 |
43 | // Select the hashing, crypto and open modes.
44 | int macType;
45 | int cipherType;
46 | var openFlag = flag;
47 | if (drmType == 1)
48 | {
49 | macType = 1;
50 | cipherType = 1;
51 | openFlag |= 4;
52 | if (keyIndex > 1)
53 | {
54 | macType = 3;
55 | openFlag |= 0xc;
56 | }
57 | }
58 | else
59 | {
60 | macType = 2;
61 | cipherType = 2;
62 | }
63 |
64 | // Select the fixed DNAS key.
65 |
66 |
67 | byte[] dnasKey = null;
68 |
69 | if ((openFlag & 2) != 0)
70 | {
71 | dnasKey = DNASStream.DnasKey1;
72 | }
73 | else if ((openFlag & 1) != 0)
74 | {
75 | dnasKey = DNASStream.DnasKey2;
76 | }
77 |
78 | if (dnasKey == null)
79 | {
80 | throw new Exception();
81 | }
82 |
83 | // Set the decryption parameters in the decrypted header.
84 | ref var pgdDesc = ref MemoryMarshal.AsRef(pgdHdr.PgdDesc);
85 | pgdDesc.DataSize = dataSize;
86 | pgdDesc.BlockSize = blockSize;
87 | pgdDesc.DataOffset = dataOffset;
88 |
89 | // Generate random header and data keys.
90 | RandomNumberGenerator.Fill(pgdData.Slice(0x10, 0x30));
91 |
92 | // Encrypt the data.
93 | DNASStream.DoBBCipher(pgdData[dataOffset..], alignSize, 0, key, pgdDesc.Key, cipherType);
94 |
95 | // Build data MAC hash.
96 | var tableNum = tableSize / 16;
97 | for (int i = 0; i < tableNum; i++)
98 | {
99 | int rsize = alignSize - i * blockSize;
100 | if (rsize > blockSize)
101 | rsize = blockSize;
102 | if (keyIndex < 3)
103 | {
104 | BuildBBMac(pgdData[(dataOffset + i * blockSize)..], rsize, key,
105 | pgdData[(tableOffset + i * 16)..],
106 | macType);
107 | }
108 | else
109 | {
110 | BuildBBMac(pgdData[(dataOffset + i * blockSize)..], rsize, key,
111 | pgdData[(tableOffset + i * 16)..],
112 | macType);
113 | }
114 | }
115 |
116 | // Build table MAC hash.
117 | BuildBBMac(pgdData.Slice(tableOffset), tableSize, key, pgdHdr.MacTableHash, macType);
118 |
119 | // Encrypt the PGD header block (0x30 bytes).
120 | DNASStream.DoBBCipher(pgdHdr.PgdDesc, 0x30, 0, key, pgdHdr.DescKey, cipherType);
121 |
122 | // Build MAC hash at 0x70 (key hash).
123 | BuildBBMac(pgdData, 0x70, key, pgdHdr.Hash70, macType);
124 |
125 | // Build MAC hash at 0x80 (DNAS hash).
126 | BuildBBMac(pgdData, 0x80, dnasKey, pgdHdr.Hash80, macType);
127 |
128 | return pgdSize;
129 | }
130 |
131 | static int BuildBBMac(ReadOnlySpan data, int size, ReadOnlySpan key, Span hash, int macType, int seed = 0)
132 | {
133 | Span mkey = stackalloc byte[Marshal.SizeOf()];
134 | Span tmpKey = stackalloc byte[0x10];
135 | int ret = unchecked((int)0x80510201);
136 | if (hash != null)
137 | {
138 | ret = AMCTRL.sceDrmBBMacInit(mkey, macType);
139 | if (ret != 0)
140 | {
141 | return ret;
142 | }
143 |
144 | ret = AMCTRL.sceDrmBBMacUpdate(mkey, data, size);
145 | if (ret != 0)
146 | {
147 | return ret;
148 | }
149 | key.CopyTo(tmpKey);
150 | if (seed != 0)
151 | {
152 | var tmpXor = MemoryMarshal.Cast(tmpKey);
153 | tmpXor[0] ^= seed;
154 | }
155 |
156 | ret = AMCTRL.sceDrmBBMacFinal(mkey, hash, tmpKey);
157 | if (ret != 0)
158 | {
159 | ret = unchecked((int)0x80510207);
160 | }
161 |
162 | if (macType == 3)
163 | {
164 | Utils.BuildDrmBBMacFinal2(hash);
165 | }
166 |
167 | }
168 |
169 | return ret;
170 | }
171 | }
172 | }
173 |
--------------------------------------------------------------------------------
/PspCrypto/Resource.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 |
122 | __sce_discinfo;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
123 |
124 |
--------------------------------------------------------------------------------
/LiLib/StreamUtil.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace Li.Utilities
8 | {
9 | public class StreamUtil
10 | {
11 | private Stream s;
12 | public StreamUtil(Stream s)
13 | {
14 | this.s = s;
15 | }
16 | public string ReadStrLen(int len)
17 | {
18 | return Encoding.UTF8.GetString(ReadBytes(len));
19 | }
20 | public string ReadCDStr(int len)
21 | {
22 | return ReadStrLen(len).Trim(' ');
23 | }
24 | public string ReadCStr()
25 | {
26 | using (MemoryStream ms = new MemoryStream())
27 | {
28 | while (true)
29 | {
30 | byte c = (byte)s.ReadByte();
31 | if (c == 0)
32 | break;
33 | ms.WriteByte(c);
34 | }
35 | return Encoding.UTF8.GetString(ms.ToArray());
36 | }
37 | }
38 | public UInt32 ReadUInt32At(int location)
39 | {
40 | long oldPos = s.Position;
41 | s.Seek(location, SeekOrigin.Begin);
42 | UInt32 outp = ReadUInt32();
43 | s.Seek(oldPos, SeekOrigin.Begin);
44 | return outp;
45 | }
46 |
47 | public Int32 ReadInt32At(int location)
48 | {
49 | long oldPos = s.Position;
50 | s.Seek(location, SeekOrigin.Begin);
51 | Int32 outp = ReadInt32();
52 | s.Seek(oldPos, SeekOrigin.Begin);
53 | return outp;
54 | }
55 |
56 | public byte[] ReadBytesAt(int location, int length)
57 | {
58 | long oldPos = s.Position;
59 | s.Seek(location, SeekOrigin.Begin);
60 | byte[] work_buf = ReadBytes(length);
61 | s.Seek(oldPos, SeekOrigin.Begin);
62 | return work_buf;
63 | }
64 |
65 | public string ReadStringAt(int location)
66 | {
67 | long oldPos = s.Position;
68 | s.Seek(location, SeekOrigin.Begin);
69 | string outp = ReadCStr();
70 | s.Seek(oldPos, SeekOrigin.Begin);
71 | return outp;
72 | }
73 | public byte ReadByte()
74 | {
75 | return (byte)s.ReadByte();
76 | }
77 | public byte[] ReadBytes(int len)
78 | {
79 | byte[] data = new byte[len];
80 | s.Read(data, 0x00, len);
81 | return data;
82 | }
83 | public UInt16 ReadUInt16()
84 | {
85 | byte[] vbytes = ReadBytes(0x2);
86 | return BitConverter.ToUInt16(vbytes);
87 | }
88 | public Int16 ReadInt16()
89 | {
90 | byte[] vbytes = ReadBytes(0x2);
91 | return BitConverter.ToInt16(vbytes);
92 | }
93 | public UInt32 ReadUInt32()
94 | {
95 | byte[] vbytes = ReadBytes(0x4);
96 | return BitConverter.ToUInt32(vbytes);
97 | }
98 | public Int32 ReadInt32()
99 | {
100 | byte[] vbytes = ReadBytes(0x4);
101 | return BitConverter.ToInt32(vbytes);
102 | }
103 | public void WriteBytesWithPadding(byte[] data, byte b, int len)
104 | {
105 | if (len < data.Length)
106 | {
107 | s.Write(data, 0, len);
108 | return;
109 | }
110 | else
111 | {
112 | WriteBytes(data);
113 | WritePadding(b, (len - data.Length));
114 | }
115 | }
116 | public void WriteStrWithPadding(string str, byte b, int len)
117 | {
118 | WriteBytesWithPadding(Encoding.UTF8.GetBytes(str), b, len);
119 | }
120 | public void WriteUInt64(UInt64 v)
121 | {
122 | WriteBytes(BitConverter.GetBytes(v));
123 | }
124 | public void WriteInt64(Int64 v)
125 | {
126 | WriteBytes(BitConverter.GetBytes(v));
127 | }
128 | public void WriteUInt16(UInt16 v)
129 | {
130 | WriteBytes(BitConverter.GetBytes(v));
131 | }
132 | public void WriteInt16(Int16 v)
133 | {
134 | WriteBytes(BitConverter.GetBytes(v));
135 | }
136 |
137 | public void WriteUInt32(UInt32 v)
138 | {
139 | WriteBytes(BitConverter.GetBytes(v));
140 | }
141 | public void WriteInt32BE(Int32 v)
142 | {
143 | WriteBytes(BitConverter.GetBytes(v).Reverse().ToArray());
144 | }
145 | public void WriteInt32At(Int32 v, long location)
146 | {
147 | long oldPos = s.Position;
148 | s.Seek(location, SeekOrigin.Begin);
149 | WriteInt32(v);
150 | s.Seek(oldPos, SeekOrigin.Begin);
151 | }
152 | public void WriteUInt32At(UInt32 v, long location)
153 | {
154 | long oldPos = s.Position;
155 | s.Seek(location, SeekOrigin.Begin);
156 | WriteUInt32(v);
157 | s.Seek(oldPos, SeekOrigin.Begin);
158 | }
159 |
160 | public void WriteInt32(Int32 v)
161 | {
162 | WriteBytes(BitConverter.GetBytes(v));
163 | }
164 | public void WriteCStr(string str)
165 | {
166 | WriteStr(str);
167 | WriteByte(0x00);
168 | }
169 | public void WriteStr(string str)
170 | {
171 | WriteBytes(Encoding.UTF8.GetBytes(str));
172 | }
173 |
174 | public void WritePadding(byte b, int len)
175 | {
176 | if (len < 0) return;
177 | for(int i = 0; i < len; i++)
178 | {
179 | WriteByte(b);
180 | }
181 | }
182 |
183 | public void AlignTo(byte padByte, int align)
184 | {
185 | int padAmt = MathUtil.CalculatePaddingAmount(Convert.ToInt32(s.Position), align);
186 |
187 | this.WritePadding(padByte, padAmt);
188 | }
189 | public void PadUntil(byte b, int len)
190 | {
191 | int remain = Convert.ToInt32(len - s.Length);
192 | WritePadding(b, remain);
193 | }
194 | public void WriteBytes(byte[] bytes)
195 | {
196 | s.Write(bytes, 0, bytes.Length);
197 | }
198 | public void WriteByte(byte b)
199 | {
200 | s.WriteByte(b);
201 | }
202 |
203 | }
204 | }
205 |
--------------------------------------------------------------------------------
/PspCrypto/Security/Cryptography/HMACSHA224.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.Linq;
5 | using System.Security.Cryptography;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 |
9 | namespace PspCrypto.Security.Cryptography
10 | {
11 | public class HMACSHA224 : HMAC
12 | {
13 | ///
14 | /// The hash size produced by the HMAC SHA224 algorithm, in bits.
15 | ///
16 | public const int HashSizeInBits = 224;
17 |
18 | ///
19 | /// The hash size produced by the HMAC SHA24 algorithm, in bytes.
20 | ///
21 | public const int HashSizeInBytes = HashSizeInBits / 8;
22 |
23 | public HMACSHA224()
24 | : this(RandomNumberGenerator.GetBytes(BlockSize))
25 | { }
26 |
27 | public HMACSHA224(byte[] key)
28 | {
29 | if (key is null)
30 | {
31 | throw new ArgumentNullException(nameof(key));
32 | }
33 |
34 | HashName = HashAlgorithmNames.SHA224;
35 | _hMacCommon = new HMACCommon(HashAlgorithmNames.SHA224, key, BlockSize);
36 | base.Key = _hMacCommon.ActualKey!;
37 | // this not really needed as it'll initialize BlockSizeValue with same value it has which is 64.
38 | // we just want to be explicit in all HMAC extended classes
39 | BlockSizeValue = BlockSize;
40 | HashSizeValue = _hMacCommon.HashSizeInBits;
41 | Debug.Assert(HashSizeValue == HashSizeInBits);
42 | }
43 |
44 | public override byte[] Key
45 | {
46 | get
47 | {
48 | return base.Key;
49 | }
50 | set
51 | {
52 | ArgumentNullException.ThrowIfNull(value);
53 | _hMacCommon.ChangeKey(value);
54 | base.Key = _hMacCommon.ActualKey!;
55 | }
56 | }
57 |
58 | protected override void HashCore(byte[] rgb, int ib, int cb) =>
59 | _hMacCommon.AppendHashData(rgb, ib, cb);
60 |
61 | protected override void HashCore(ReadOnlySpan source) =>
62 | _hMacCommon.AppendHashData(source);
63 |
64 | protected override byte[] HashFinal() =>
65 | _hMacCommon.FinalizeHashAndReset();
66 |
67 | protected override bool TryHashFinal(Span destination, out int bytesWritten) =>
68 | _hMacCommon.TryFinalizeHashAndReset(destination, out bytesWritten);
69 |
70 | public override void Initialize() => _hMacCommon.Reset();
71 |
72 | ///
73 | /// Computes the HMAC of data using the SHA224 algorithm.
74 | ///
75 | /// The HMAC key.
76 | /// The data to HMAC.
77 | /// The HMAC of the data.
78 | ///
79 | /// or is .
80 | ///
81 | public static byte[] HashData(byte[] key, byte[] source)
82 | {
83 | ArgumentNullException.ThrowIfNull(key);
84 | ArgumentNullException.ThrowIfNull(source);
85 |
86 | return HashData(new ReadOnlySpan(key), new ReadOnlySpan(source));
87 | }
88 |
89 | ///
90 | /// Computes the HMAC of data using the SHA224 algorithm.
91 | ///
92 | /// The HMAC key.
93 | /// The data to HMAC.
94 | /// The HMAC of the data.
95 | public static byte[] HashData(ReadOnlySpan key, ReadOnlySpan source)
96 | {
97 | byte[] buffer = new byte[HashSizeInBytes];
98 |
99 | int written = HashData(key, source, buffer.AsSpan());
100 | Debug.Assert(written == buffer.Length);
101 |
102 | return buffer;
103 | }
104 |
105 | ///
106 | /// Computes the HMAC of data using the SHA224 algorithm.
107 | ///
108 | /// The HMAC key.
109 | /// The data to HMAC.
110 | /// The buffer to receive the HMAC value.
111 | /// The total number of bytes written to .
112 | ///
113 | /// The buffer in is too small to hold the calculated hash
114 | /// size. The SHA224 algorithm always produces a 224-bit HMAC, or 28 bytes.
115 | ///
116 | public static int HashData(ReadOnlySpan key, ReadOnlySpan source, Span destination)
117 | {
118 | if (!TryHashData(key, source, destination, out int bytesWritten))
119 | {
120 | throw new ArgumentException("Destination is too short.", nameof(destination));
121 | }
122 |
123 | return bytesWritten;
124 | }
125 |
126 | ///
127 | /// Attempts to compute the HMAC of data using the SHA224 algorithm.
128 | ///
129 | /// The HMAC key.
130 | /// The data to HMAC.
131 | /// The buffer to receive the HMAC value.
132 | ///
133 | /// When this method returns, the total number of bytes written into .
134 | ///
135 | ///
136 | /// if is too small to hold the
137 | /// calculated hash, otherwise.
138 | ///
139 | public static bool TryHashData(ReadOnlySpan key, ReadOnlySpan source, Span destination, out int bytesWritten)
140 | {
141 | if (destination.Length < HashSizeInBytes)
142 | {
143 | bytesWritten = 0;
144 | return false;
145 | }
146 |
147 | bytesWritten = HashProviderDispenser.OneShotHashProvider.MacData(HashAlgorithmNames.SHA224, key, source, destination);
148 | Debug.Assert(bytesWritten == HashSizeInBytes);
149 |
150 | return true;
151 | }
152 |
153 | private HMACCommon _hMacCommon;
154 | private const int BlockSize = 64;
155 | }
156 | }
157 |
--------------------------------------------------------------------------------
/CHOVY-TRANSFER/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 |
122 | ..\chovytrans.gif;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
123 |
124 |
--------------------------------------------------------------------------------
/Vita/ContentManager/SettingsReader.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Win32;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace Vita.ContentManager
9 | {
10 | public class SettingsReader
11 | {
12 | private static string? overrideBackupsFolder = null;
13 | public static string AppFolder
14 | {
15 | get
16 | {
17 | return Path.Combine(BackupsFolder, "APP");
18 | }
19 | }
20 | public static string PspSavedataFolder
21 | {
22 | get
23 | {
24 | return Path.Combine(BackupsFolder, "PSAVEDATA");
25 | }
26 | }
27 |
28 | public static string PsmFolder
29 | {
30 | get
31 | {
32 | return Path.Combine(BackupsFolder, "PSM");
33 | }
34 | }
35 | public static string SystemFolder
36 | {
37 | get
38 | {
39 | return Path.Combine(BackupsFolder, "SYSTEM");
40 | }
41 | }
42 | public static string Ps1Folder
43 | {
44 | get
45 | {
46 | return Path.Combine(BackupsFolder, "PSGAME");
47 | }
48 | }
49 | public static string PspFolder
50 | {
51 | get
52 | {
53 | return Path.Combine(BackupsFolder, "PGAME");
54 | }
55 | }
56 | public static string BackupsFolder
57 | {
58 | get
59 | {
60 | if (overrideBackupsFolder is not null) return overrideBackupsFolder;
61 |
62 | string? cmaFolder = getQcmaPSVitaFolder();
63 | if (cmaFolder is not null) return cmaFolder;
64 | cmaFolder = getDevkitCmaPSVitaFolder();
65 | if (cmaFolder is not null) return cmaFolder;
66 | cmaFolder = getSonyCmaPSVitaFolder();
67 | if (cmaFolder is not null) return cmaFolder;
68 | return getDefaultCmaPSVitaFolder();
69 | }
70 | set
71 | {
72 | overrideBackupsFolder = value;
73 | }
74 | }
75 |
76 | private static string getDefaultCmaPSVitaFolder()
77 | {
78 | return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), "PS Vita");
79 | }
80 |
81 | private static string getQcmaConfFile()
82 | {
83 | if (OperatingSystem.IsLinux())
84 | return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".config", "codestation", "qcma.conf");
85 | else if (OperatingSystem.IsMacOS())
86 | return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "Library", "Preferences", "com.codestation.qcma.plist");
87 | else
88 | throw new PlatformNotSupportedException("cannot open qcma config as i dont know where it is.");
89 | }
90 | private static string? getQcmaConfigSetting(string file, string key)
91 | {
92 | if (!File.Exists(file)) return null;
93 |
94 | if (OperatingSystem.IsLinux())
95 | {
96 | using (TextReader confFile = File.OpenText(file))
97 | {
98 | for (string? ln = confFile.ReadLine();
99 | ln is not null;
100 | ln = confFile.ReadLine())
101 | {
102 | ln = ln.Trim();
103 | if (ln.StartsWith("[")) continue;
104 |
105 | string[] kvp = ln.Split('=');
106 | if (kvp.Length < 2) continue;
107 |
108 | string settingKey = kvp[0].Trim();
109 | string settingValue = kvp[1].Trim();
110 |
111 |
112 | if (settingKey == key)
113 | return settingValue;
114 | }
115 | }
116 | }
117 | else if (OperatingSystem.IsMacOS())
118 | {
119 | throw new PlatformNotSupportedException("TODO: Implement reading bplist file from mac os");
120 | }
121 | return null;
122 | }
123 |
124 | private static string? getRegistryKey(string registryPath, string keyName)
125 | {
126 | if (OperatingSystem.IsWindows())
127 | {
128 | using (RegistryKey? regKey = Registry.CurrentUser.OpenSubKey(registryPath))
129 | {
130 | if (regKey is null) return null;
131 | string? keyData = (regKey.GetValue(keyName) as string);
132 | if (keyData is null) return null;
133 | return keyData;
134 | }
135 | }
136 | else
137 | {
138 | throw new PlatformNotSupportedException("cannot use registry on os other than windows");
139 | }
140 | }
141 |
142 | private static string? getSonyCmaPSVitaFolder()
143 | {
144 | if (OperatingSystem.IsWindows())
145 | {
146 | return getRegistryKey(@"Software\Sony Corporation\Sony Corporation\Content Manager Assistant\Settings", "ApplicationHomePath");
147 | }
148 | return null;
149 | }
150 | private static string? getDevkitCmaPSVitaFolder()
151 | {
152 | if (OperatingSystem.IsWindows())
153 | {
154 | return getRegistryKey(@"Software\SCE\PSP2\Content Manager Assistant for PlayStation(R)Vita DevKit\Settings", "ApplicationHomePath");
155 | }
156 | return null;
157 | }
158 | private static string? getQcmaPSVitaFolder()
159 | {
160 | if (OperatingSystem.IsWindows())
161 | {
162 | return getRegistryKey(@"Software\codestation\qcma", "appsPath");
163 | }
164 | else if (OperatingSystem.IsLinux())
165 | {
166 | string qcmaConf = getQcmaConfFile();
167 | return getQcmaConfigSetting(qcmaConf, "appsPath");
168 | }
169 | else if (OperatingSystem.IsMacOS())
170 | {
171 | string qcmaConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "Library", "Preferences", "com.codestation.qcma.plist");
172 | // TODO: read file
173 | }
174 | return null;
175 | }
176 | }
177 | }
178 |
--------------------------------------------------------------------------------
/Vita/PsvImgTools/PSVIMGStructs.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Vita.PsvImgTools
4 | {
5 |
6 | public class PSVIMGConstants
7 | {
8 | public const int AES_BLOCK_SIZE = 0x10;
9 | public const int SHA256_BLOCK_SIZE = 0x20;
10 | public const int PSVIMG_BLOCK_SIZE = 0x8000;
11 | public const int PSVIMG_ENTRY_ALIGN = 0x400;
12 |
13 | public const string PSVIMG_HEADER_END = "EndOfHeader\n";
14 | public const string PSVIMG_TAILOR_END = "EndOfTailer\n";
15 | public const string PSVIMG_PADDING_END = "\n";
16 |
17 | public const int FULL_PSVIMG_SIZE = PSVIMG_BLOCK_SIZE + SHA256_BLOCK_SIZE;
18 | }
19 |
20 | internal class StringReader
21 | {
22 | internal static string ReadUntilTerminator(byte[] StringBytes)
23 | {
24 | string str = "";
25 | foreach (byte sByte in StringBytes)
26 | {
27 | if (sByte != 0x00)
28 | {
29 | str += (char)sByte;
30 | }
31 | else
32 | {
33 | return str;
34 | }
35 | }
36 | return str;
37 | }
38 | }
39 |
40 | internal class SceDateTime
41 | {
42 | public ushort Year;
43 | public ushort Month;
44 | public ushort Day;
45 | public ushort Hour;
46 | public ushort Minute;
47 | public ushort Second;
48 | public uint Microsecond;
49 |
50 | public SceDateTime()
51 | {
52 |
53 | }
54 | }
55 |
56 | internal class SceIoStat
57 | {
58 | public enum Modes
59 | {
60 | /** Format bits mask */
61 | FormatBits = 0xF000,
62 | /** Symbolic link */
63 | SymbLink = 0x4000,
64 | /** Directory */
65 | Directory = 0x1000,
66 | /** Regular file */
67 | File = 0x2000,
68 |
69 | /** Set UID */
70 | SetUid = 0x0800,
71 | /** Set GID */
72 | SetGid = 0x0400,
73 | /** Sticky */
74 | Sticky = 0x0200,
75 |
76 | /** Others access rights mask */
77 | OthersAcesssMask = 0x01C0,
78 | /** Others read permission */
79 | OthersRead = 0x0100,
80 | /** Others write permission */
81 | OthersWrite = 0x0080,
82 | /** Others execute permission */
83 | OthersExecute = 0x0040,
84 |
85 | /** Group access rights mask */
86 | GroupAcessMask = 0x0038,
87 | /** Group read permission */
88 | GroupRead = 0x0020,
89 | /** Group write permission */
90 | GroupWrite = 0x0010,
91 | /** Group execute permission */
92 | GroupExecute = 0x0008,
93 |
94 | /** User access rights mask */
95 | UserAcessMask = 0x0007,
96 | /** User read permission */
97 | UserRead = 0x0004,
98 | /** User write permission */
99 | UserWrite = 0x0002,
100 | /** User execute permission */
101 | UserExecute = 0x0001,
102 | };
103 | public enum AttributesEnum
104 | {
105 | /** Format mask */
106 | FormatMask = 0x0038, // Format mask
107 | /** Symlink */
108 | SymbLink = 0x0008, // Symbolic link
109 | /** Directory */
110 | Directory = 0x0010, // Directory
111 | /** Regular file */
112 | File = 0x0020, // Regular file
113 |
114 | /** Hidden read permission */
115 | Read = 0x0004, // read
116 | /** Hidden write permission */
117 | Write = 0x0002, // write
118 | /** Hidden execute permission */
119 | Execute = 0x0001, // execute
120 | };
121 |
122 | public Modes Mode;
123 | public AttributesEnum Attributes;
124 | /** Size of the file in bytes. */
125 | public ulong Size;
126 | /** Creation time. */
127 | public SceDateTime CreationTime;
128 | /** Access time. */
129 | public SceDateTime AccessTime;
130 | /** Modification time. */
131 | public SceDateTime ModificaionTime;
132 | /** Device-specific data. */
133 | public uint[] Private = new uint[6];
134 | public SceIoStat()
135 | {
136 | for (int i = 0; i < Private.Length; i++)
137 | {
138 | Private[i] = 0;
139 | }
140 | }
141 | };
142 |
143 | internal class PsvImgTailer
144 | {
145 | public ulong Flags;
146 | public byte[] Padding = new byte[1004];
147 | public byte[] bEnd = new byte[12];
148 |
149 | public string End
150 | {
151 | get
152 | {
153 | return StringReader.ReadUntilTerminator(bEnd);
154 | }
155 | }
156 | }
157 | internal class PSVIMGPadding
158 | {
159 | public static long GetPadding(long size)
160 | {
161 | long padding;
162 | if ((size & PSVIMGConstants.PSVIMG_ENTRY_ALIGN - 1) >= 1)
163 | {
164 | padding = PSVIMGConstants.PSVIMG_ENTRY_ALIGN - (size & PSVIMGConstants.PSVIMG_ENTRY_ALIGN - 1);
165 | }
166 | else
167 | {
168 | padding = 0;
169 | }
170 | return padding;
171 | }
172 | }
173 |
174 | internal class PsvImgHeader
175 | {
176 | public ulong SysTime;
177 | public ulong Flags;
178 | public SceIoStat Statistics;
179 | public byte[] bParentPath = new byte[256];
180 | public uint unk_16C; // set to 1
181 | public byte[] bPath = new byte[256];
182 | public byte[] Padding = new byte[904];
183 | public byte[] bEnd = new byte[12];
184 |
185 | public string Path
186 | {
187 | get
188 | {
189 | return StringReader.ReadUntilTerminator(bPath);
190 | }
191 | }
192 |
193 | public string End
194 | {
195 | get
196 | {
197 | return StringReader.ReadUntilTerminator(bEnd);
198 | }
199 | }
200 |
201 | public string ParentPath
202 | {
203 | get
204 | {
205 | return StringReader.ReadUntilTerminator(bParentPath);
206 | }
207 | }
208 | public PsvImgHeader()
209 | {
210 |
211 | }
212 | }
213 | }
214 |
--------------------------------------------------------------------------------
/PspCrypto/Structs.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Runtime.InteropServices;
4 | using System.Text;
5 |
6 | namespace PspCrypto
7 | {
8 | public enum SceExecFileDecryptMode : byte
9 | {
10 | /* Not an executable. */
11 | DECRYPT_MODE_NO_EXEC = 0,
12 | /* 1.50 Kernel module. */
13 | DECRYPT_MODE_BOGUS_MODULE = 1,
14 | DECRYPT_MODE_KERNEL_MODULE = 2,
15 | DECRYPT_MODE_VSH_MODULE = 3,
16 | DECRYPT_MODE_USER_MODULE = 4,
17 | DECRYPT_MODE_UMD_GAME_EXEC = 9,
18 | DECRYPT_MODE_GAMESHARING_EXEC = 10,
19 | /* USB/WLAN module. */
20 | DECRYPT_MODE_UNKNOWN_11 = 11,
21 | DECRYPT_MODE_MS_UPDATER = 12,
22 | DECRYPT_MODE_DEMO_EXEC = 13,
23 | DECRYPT_MODE_APP_MODULE = 14,
24 | DECRYPT_MODE_UNKNOWN_18 = 18,
25 | DECRYPT_MODE_UNKNOWN_19 = 19,
26 | DECRYPT_MODE_POPS_EXEC = 20,
27 | /* MS module. */
28 | DECRYPT_MODE_UNKNOWN_21 = 21,
29 | /* APP module. */
30 | DECRYPT_MODE_UNKNOWN_22 = 22,
31 | /* USER module. */
32 | DECRYPT_MODE_UNKNOWN_23 = 23,
33 | /* USER module. */
34 | DECRYPT_MODE_UNKNOWN_25 = 25,
35 | }
36 |
37 | [StructLayout(LayoutKind.Sequential, Pack = 1)]
38 | public unsafe struct PSPHeader2
39 | {
40 | public Span RawHdr
41 | {
42 | get
43 | {
44 | fixed (uint* ptr = &magic)
45 | {
46 | return new Span(ptr, 0x80);
47 | }
48 | }
49 | }
50 | public uint magic;
51 | public ushort modAttribute;
52 | public ushort compAttribute;
53 | public byte moduleVerLo;
54 | public byte moduleVerHi;
55 | private fixed byte _modName[27];
56 |
57 | public Span modName
58 | {
59 | get
60 | {
61 | fixed (byte* ptr = _modName)
62 | {
63 | return new Span(ptr, 27);
64 | }
65 | }
66 | }
67 | public byte terminal;
68 | public byte modVersion;
69 | public byte nSegments;
70 | public int elfSize;
71 | public int pspSize;
72 | public uint bootEntry;
73 | public int modInfoOffset;
74 | public uint bssSize;
75 | private fixed ushort _segAlign[4];
76 |
77 | public Span segAlign
78 | {
79 | get
80 | {
81 | fixed (ushort* ptr = _segAlign)
82 | {
83 | return new Span(ptr, 4);
84 | }
85 | }
86 | }
87 | private fixed uint _segAddress[4];
88 |
89 | public Span segAddress
90 | {
91 | get
92 | {
93 | fixed (uint* ptr = _segAddress)
94 | {
95 | return new Span(ptr, 4);
96 | }
97 | }
98 | }
99 | private fixed uint _segSize[4];
100 |
101 | public Span segSize
102 | {
103 | get
104 | {
105 | fixed (uint* ptr = _segSize)
106 | {
107 | return new Span(ptr, 4);
108 | }
109 | }
110 | }
111 | public fixed uint reserved[5];
112 | public uint devkitVersion;
113 | public SceExecFileDecryptMode decryptMode;
114 | public byte padding;
115 | public ushort overlapSize;
116 | private fixed byte _aesKey[16];
117 | public Span aesKey
118 | {
119 | get
120 | {
121 | fixed (byte* ptr = _aesKey)
122 | {
123 | return new Span(ptr, 16);
124 | }
125 | }
126 | }
127 |
128 | public Span keyData
129 | {
130 | get
131 | {
132 | fixed (byte* ptr = _aesKey)
133 | {
134 | return new Span(ptr, 0x30);
135 | }
136 | }
137 | }
138 |
139 | public Span keyData50
140 | {
141 | get
142 | {
143 | fixed (byte* ptr = _aesKey)
144 | {
145 | return new Span(ptr, 0x50);
146 | }
147 | }
148 | }
149 |
150 | private fixed byte _cmacKey[16];
151 | public Span cmacKey
152 | {
153 | get
154 | {
155 | fixed (byte* ptr = _cmacKey)
156 | {
157 | return new Span(ptr, 16);
158 | }
159 | }
160 | }
161 | private fixed byte _cmacHeaderHash[16];
162 | public Span cmacHeaderHash
163 | {
164 | get
165 | {
166 | fixed (byte* ptr = _cmacHeaderHash)
167 | {
168 | return new Span(ptr, 16);
169 | }
170 | }
171 | }
172 |
173 | public Span sizeInfo
174 | {
175 | get
176 | {
177 | fixed (int* ptr = &dataSize)
178 | {
179 | return new Span(ptr, 0x10);
180 | }
181 | }
182 | }
183 | public int dataSize;
184 | public int dataOffset;
185 | public uint unk184;
186 | public uint unk188;
187 | private fixed byte _cmacDataHash[16];
188 |
189 | public Span cmacDataHash
190 | {
191 | get
192 | {
193 | fixed (byte* ptr = _cmacDataHash)
194 | {
195 | return new Span(ptr, 16);
196 | }
197 | }
198 | }
199 |
200 | public Span CheckData
201 | {
202 | get
203 | {
204 | fixed (uint* ptr = &tag)
205 | {
206 | return new Span(ptr, 0x80);
207 | }
208 | }
209 | }
210 | public uint tag;
211 | private fixed byte _sCheck[0x58];
212 |
213 | public Span sCheck
214 | {
215 | get
216 | {
217 | fixed (byte* ptr = _sCheck)
218 | {
219 | return new Span(ptr, 0x58);
220 | }
221 | }
222 | }
223 | private fixed byte _sha1Hash[20];
224 |
225 | public Span sha1Hash
226 | {
227 | get
228 | {
229 | fixed (byte* ptr = _sha1Hash)
230 | {
231 | return new Span(ptr, 20);
232 | }
233 | }
234 | }
235 | private fixed byte _keyData4[16];
236 |
237 | public Span keyData4
238 | {
239 | get
240 | {
241 | fixed (byte* ptr = _keyData4)
242 | {
243 | return new Span(ptr, 16);
244 | }
245 | }
246 | }
247 | }
248 |
249 |
250 | [StructLayout(LayoutKind.Sequential, Pack = 1)]
251 | public struct PbpHeader
252 | {
253 | public int Sig;
254 | public int Version;
255 | public int ParamOff;
256 | public int Icon0Off;
257 | public int Icon1Off;
258 | public int Pic0Off;
259 | public int Pic1Off;
260 | public int Snd0Off;
261 | public int DataPspOff;
262 | public int DataPsarOff;
263 | }
264 | }
265 |
--------------------------------------------------------------------------------
/PspCrypto/Security/Cryptography/ECDsaManaged.cs:
--------------------------------------------------------------------------------
1 | using Org.BouncyCastle.Crypto;
2 | using Org.BouncyCastle.Crypto.Generators;
3 | using Org.BouncyCastle.Crypto.Parameters;
4 | using Org.BouncyCastle.Crypto.Signers;
5 | using Org.BouncyCastle.Math;
6 | using Org.BouncyCastle.Math.EC;
7 | using Org.BouncyCastle.Security;
8 | using System;
9 |
10 | namespace PspCrypto.Security.Cryptography
11 | {
12 | internal class ECDsaManaged : System.Security.Cryptography.ECDsa
13 | {
14 | private ECKeyParameters _ecKeyParameters;
15 | private readonly bool _ebootPbp;
16 | private readonly int _type;
17 |
18 | public ECDsaManaged()
19 | {
20 |
21 | }
22 |
23 | public ECDsaManaged(System.Security.Cryptography.ECParameters parameters, bool ebootPbp, int type)
24 | {
25 | _ebootPbp = ebootPbp;
26 | _type = type;
27 | var gx = new BigInteger(1, parameters.Curve.G.X);
28 | var gy = new BigInteger(1, parameters.Curve.G.Y);
29 | var curve = ConvertECCurve(parameters.Curve);
30 | var g = curve.CreatePoint(gx, gy);
31 | var domainParameters = new ECDomainParameters(curve, g, curve.Order);
32 | if (parameters.D != null)
33 | {
34 | var privateKey = new BigInteger(1, parameters.D);
35 | _ecKeyParameters = new ECPrivateKeyParameters(privateKey, domainParameters);
36 | }
37 | else if (parameters.Q.X != null && parameters.Q.Y != null)
38 | {
39 | var publicKey = curve.CreatePoint(new BigInteger(1, parameters.Q.X), new BigInteger(1, parameters.Q.Y));
40 | _ecKeyParameters = new ECPublicKeyParameters(publicKey, domainParameters);
41 | }
42 | else
43 | {
44 | throw new ArgumentException("invalid parameters", nameof(parameters));
45 | }
46 | }
47 |
48 | public override byte[] SignHash(byte[] hash)
49 | {
50 | if (_ecKeyParameters is not ECPrivateKeyParameters)
51 | {
52 | throw new ArgumentException("key is not private Key");
53 | }
54 | var signer = CreateSigner();
55 | signer.Init(true, _ecKeyParameters);
56 | signer.BlockUpdate(hash);
57 | return signer.GenerateSignature();
58 | }
59 |
60 | public override bool VerifyHash(byte[] hash, byte[] signature)
61 | {
62 | var signer = CreateSigner();
63 | if (_ecKeyParameters is ECPrivateKeyParameters ecPrivateKeyParameters)
64 | {
65 | var publicKey = new ECPublicKeyParameters(
66 | ecPrivateKeyParameters.Parameters.G.Multiply(ecPrivateKeyParameters.D),
67 | ecPrivateKeyParameters.Parameters);
68 | signer.Init(false, publicKey);
69 | }
70 | else
71 | {
72 | signer.Init(false, _ecKeyParameters);
73 | }
74 | signer.BlockUpdate(hash);
75 | return signer.VerifySignature(signature);
76 | }
77 |
78 | protected override byte[] HashData(byte[] data, int offset, int count, System.Security.Cryptography.HashAlgorithmName hashAlgorithm)
79 | {
80 | var dataSpan = new ReadOnlySpan(data, offset, count);
81 | if (hashAlgorithm == System.Security.Cryptography.HashAlgorithmName.SHA256)
82 | {
83 | return System.Security.Cryptography.SHA256.HashData(dataSpan);
84 | }
85 | else if (hashAlgorithm == System.Security.Cryptography.HashAlgorithmName.SHA1)
86 | {
87 | return System.Security.Cryptography.SHA1.HashData(dataSpan);
88 | }
89 | else
90 | {
91 | throw new NotSupportedException($"{hashAlgorithm} not supported");
92 | }
93 | }
94 |
95 | private ISigner CreateSigner()
96 | {
97 | IDigest digest = DigestUtilities.GetDigest("NONE");
98 | IDsa dsa = _ebootPbp ? new ECDsaSigner(new EbootPbpKCalculator(_type)) : new ECDsaSigner();
99 | var signer = new DsaDigestSigner(dsa, digest, PlainDsaEncoding.Instance);
100 | return signer;
101 | }
102 |
103 | private FpCurve _fpCurve;
104 |
105 | public override void GenerateKey(System.Security.Cryptography.ECCurve curve)
106 | {
107 | _fpCurve = ConvertECCurve(curve);
108 | var gx = new BigInteger(1, curve.G.X);
109 | var gy = new BigInteger(1, curve.G.Y);
110 | var g = _fpCurve.CreatePoint(gx, gy);
111 | var domainParameters = new ECDomainParameters(_fpCurve, g, _fpCurve.Order);
112 | var gen = new ECKeyPairGenerator();
113 | gen.Init(new ECKeyGenerationParameters(domainParameters, new SecureRandom()));
114 | var keyPair = gen.GenerateKeyPair();
115 | _ecKeyParameters = (ECKeyParameters)keyPair.Private;
116 | }
117 |
118 | public override System.Security.Cryptography.ECParameters ExportExplicitParameters(bool includePrivateParameters)
119 | {
120 | var normalG = _ecKeyParameters.Parameters.G;
121 | var curve = new System.Security.Cryptography.ECCurve
122 | {
123 | A = _fpCurve.A.ToBigInteger().ToByteArrayUnsigned(),
124 | B = _fpCurve.B.ToBigInteger().ToByteArrayUnsigned(),
125 | Prime = _fpCurve.Q.ToByteArrayUnsigned(),
126 | Order = _fpCurve.Order.ToByteArrayUnsigned(),
127 | Cofactor = _fpCurve.Cofactor.ToByteArrayUnsigned(),
128 | G = new System.Security.Cryptography.ECPoint
129 | {
130 | X = normalG.AffineXCoord.ToBigInteger().ToByteArrayUnsigned(),
131 | Y = normalG.AffineYCoord.ToBigInteger().ToByteArrayUnsigned()
132 | }
133 | };
134 | var parameters = new System.Security.Cryptography.ECParameters
135 | {
136 | Curve = curve
137 | };
138 | if (includePrivateParameters && _ecKeyParameters is ECPrivateKeyParameters privateKeyParameters)
139 | {
140 | parameters.D = privateKeyParameters.D.ToByteArrayUnsigned();
141 | var publicKey = _ecKeyParameters.Parameters.G.Multiply(privateKeyParameters.D).Normalize();
142 | parameters.Q = new System.Security.Cryptography.ECPoint
143 | {
144 | X = publicKey.AffineXCoord.ToBigInteger().ToByteArrayUnsigned(),
145 | Y = publicKey.AffineYCoord.ToBigInteger().ToByteArrayUnsigned()
146 | };
147 | }
148 | else if (_ecKeyParameters is ECPublicKeyParameters publicKeyParameters)
149 | {
150 | var publicKey = publicKeyParameters.Q.Normalize();
151 | parameters.Q = new System.Security.Cryptography.ECPoint
152 | {
153 | X = publicKey.AffineXCoord.ToBigInteger().ToByteArrayUnsigned(),
154 | Y = publicKey.AffineYCoord.ToBigInteger().ToByteArrayUnsigned()
155 | };
156 | }
157 | return parameters;
158 | }
159 |
160 | private static FpCurve ConvertECCurve(System.Security.Cryptography.ECCurve curve)
161 | {
162 | var p = new BigInteger(1, curve.Prime);
163 | var a = new BigInteger(1, curve.A);
164 | var b = new BigInteger(1, curve.B);
165 | var n = new BigInteger(1, curve.Order);
166 | var fpCurve = new FpCurve(p, a, b, n, BigInteger.One);
167 | return fpCurve;
168 | }
169 | }
170 | }
171 |
--------------------------------------------------------------------------------
/Vita/PsvImgTools/PSVMDBuilder.cs:
--------------------------------------------------------------------------------
1 | using Ionic.Zlib;
2 | using System;
3 | using System.IO;
4 | using System.Security.Cryptography;
5 | using System.Text;
6 | namespace Vita.PsvImgTools
7 | {
8 | public class PSVMDBuilder
9 | {
10 | private static void memset(byte[] buf, byte content, long length)
11 | {
12 | for (int i = 0; i < length; i++)
13 | {
14 | buf[i] = content;
15 | }
16 | }
17 |
18 | private static void writeUInt64(Stream dst, ulong value)
19 | {
20 | byte[] ValueBytes = BitConverter.GetBytes(value);
21 | dst.Write(ValueBytes, 0x00, 0x8);
22 | }
23 | private static void writeInt64(Stream dst, long value)
24 | {
25 | byte[] ValueBytes = BitConverter.GetBytes(value);
26 | dst.Write(ValueBytes, 0x00, 0x8);
27 | }
28 | private static void writeUInt16(Stream dst, ushort value)
29 | {
30 | byte[] ValueBytes = BitConverter.GetBytes(value);
31 | dst.Write(ValueBytes, 0x00, 0x2);
32 | }
33 | private static void writeInt16(Stream dst, short value)
34 | {
35 | byte[] ValueBytes = BitConverter.GetBytes(value);
36 | dst.Write(ValueBytes, 0x00, 0x2);
37 | }
38 |
39 | private static void writeInt32(Stream dst, int value)
40 | {
41 | byte[] ValueBytes = BitConverter.GetBytes(value);
42 | dst.Write(ValueBytes, 0x00, 0x4);
43 | }
44 | private static void writeUInt32(Stream dst, uint value)
45 | {
46 | byte[] ValueBytes = BitConverter.GetBytes(value);
47 | dst.Write(ValueBytes, 0x00, 0x4);
48 | }
49 |
50 |
51 | private static void writeString(Stream dst, string str, int len = -1)
52 | {
53 | if (len < 0)
54 | {
55 | len = str.Length;
56 | }
57 |
58 | byte[] StrBytes = Encoding.UTF8.GetBytes(str);
59 | dst.Write(StrBytes, 0x00, len);
60 | }
61 |
62 | private static void writePadding(Stream dst, byte paddingByte, long paddingLen)
63 | {
64 | byte[] paddingData = new byte[paddingLen];
65 | memset(paddingData, paddingByte, paddingLen);
66 | dst.Write(paddingData, 0x00, paddingData.Length);
67 | }
68 | private static void writeStringWithPadding(Stream dst, string str, int padSize, byte padByte = 0x78)
69 | {
70 | int StrLen = str.Length;
71 | if (StrLen > padSize)
72 | {
73 | StrLen = padSize;
74 | }
75 |
76 | int PaddingLen = padSize - StrLen - 1;
77 | writeString(dst, str, StrLen);
78 | dst.WriteByte(0x00);
79 | writePadding(dst, padByte, PaddingLen);
80 | }
81 |
82 | private static byte[] aes_ecb_decrypt(byte[] cipherText, byte[] KEY, int size = -1)
83 | {
84 | if (size < 0)
85 | {
86 | size = cipherText.Length;
87 | }
88 |
89 | MemoryStream ms = new MemoryStream();
90 |
91 | Aes alg = Aes.Create();
92 | alg.Mode = CipherMode.ECB;
93 | alg.Padding = PaddingMode.None;
94 | alg.KeySize = 256;
95 | alg.BlockSize = 128;
96 | alg.Key = KEY;
97 | CryptoStream cs = new CryptoStream(ms, alg.CreateDecryptor(), CryptoStreamMode.Write);
98 | cs.Write(cipherText, 0, size);
99 | cs.Close();
100 | byte[] plainText = ms.ToArray();
101 | return plainText;
102 | }
103 |
104 | private static byte[] aes_cbc_decrypt(byte[] cipherData, byte[] IV, byte[] Key)
105 | {
106 | MemoryStream ms = new MemoryStream();
107 | Aes alg = Aes.Create();
108 | alg.Mode = CipherMode.CBC;
109 | alg.Padding = PaddingMode.None;
110 | alg.KeySize = 256;
111 | alg.BlockSize = 128;
112 | alg.Key = Key;
113 | alg.IV = IV;
114 | CryptoStream cs = new CryptoStream(ms, alg.CreateDecryptor(), CryptoStreamMode.Write);
115 | cs.Write(cipherData, 0, cipherData.Length);
116 | cs.Close();
117 | byte[] decryptedData = ms.ToArray();
118 | return decryptedData;
119 | }
120 | private static byte[] aes_cbc_encrypt(byte[] plainText, byte[] IV, byte[] KEY, int size = -1)
121 | {
122 | if (size < 0)
123 | {
124 | size = plainText.Length;
125 | }
126 |
127 | MemoryStream ms = new MemoryStream();
128 |
129 | Aes alg = Aes.Create();
130 | alg.Mode = CipherMode.CBC;
131 | alg.Padding = PaddingMode.None;
132 | alg.KeySize = 256;
133 | alg.BlockSize = 128;
134 | alg.Key = KEY;
135 | alg.IV = IV;
136 | CryptoStream cs = new CryptoStream(ms, alg.CreateEncryptor(), CryptoStreamMode.Write);
137 | cs.Write(plainText, 0, size);
138 | cs.Close();
139 | byte[] cipherText = ms.ToArray();
140 | return cipherText;
141 | }
142 |
143 |
144 | public static void CreatePsvmd(Stream OutputStream, Stream EncryptedPsvimg, long ContentSize, string BackupType, byte[] Key)
145 | {
146 | byte[] IV = new byte[PSVIMGConstants.AES_BLOCK_SIZE];
147 | EncryptedPsvimg.Seek(0x00, SeekOrigin.Begin);
148 | EncryptedPsvimg.Read(IV, 0x00, IV.Length);
149 | IV = aes_ecb_decrypt(IV, Key);
150 | MemoryStream ms = new MemoryStream();
151 |
152 | writeUInt32(ms, 0xFEE1900D); // magic
153 | writeUInt32(ms, 0x2); // type
154 | writeUInt64(ms, 0x03000000); // fw ver
155 | ms.Write(new byte[0x10], 0x00, 0x10); // PSID
156 | writeStringWithPadding(ms, BackupType, 0x40, 0x00); //backup type
157 | writeInt64(ms, EncryptedPsvimg.Length); // total size
158 | writeUInt64(ms, 0x2); //version
159 | writeInt64(ms, ContentSize); // content size
160 | ms.Write(IV, 0x00, 0x10); // IV
161 | writeUInt64(ms, 0x00); //ux0 info
162 | writeUInt64(ms, 0x00); //ur0 info
163 | writeUInt64(ms, 0x00); //unused 98
164 | writeUInt64(ms, 0x00); //unused A0
165 | writeUInt32(ms, 0x1); //add data
166 |
167 | ms.Seek(0x00, SeekOrigin.Begin);
168 | byte[] psvMd = ms.ToArray();
169 | ms.Close();
170 |
171 | ms = new MemoryStream();
172 | byte[] psvMdCompressed = ZlibStream.CompressBuffer(psvMd);
173 | psvMdCompressed[0x1] = 0x9C;
174 | ms.Write(psvMdCompressed, 0x00, psvMdCompressed.Length);
175 |
176 | SHA256 sha = SHA256.Create();
177 | byte[] shadata = sha.ComputeHash(psvMdCompressed);
178 | ms.Write(shadata, 0x00, shadata.Length);
179 |
180 | int PaddingLen = Convert.ToInt32(PSVIMGConstants.AES_BLOCK_SIZE - (ms.Length & PSVIMGConstants.AES_BLOCK_SIZE - 1));
181 | writePadding(ms, 0x00, PaddingLen);
182 |
183 | writeInt32(ms, PaddingLen); //Padding Length
184 | writeUInt32(ms, 0x00);
185 | writeInt64(ms, ms.Length + 0x8 + IV.Length);
186 | ms.Seek(0x00, SeekOrigin.Begin);
187 | byte[] toEncrypt = ms.ToArray();
188 | ms.Close();
189 |
190 | byte[] EncryptedData = aes_cbc_encrypt(toEncrypt, IV, Key);
191 | OutputStream.Write(IV, 0x00, IV.Length);
192 | OutputStream.Write(EncryptedData, 0x00, EncryptedData.Length);
193 | return;
194 | }
195 |
196 |
197 | public static byte[] DecryptPsvmd(Stream PsvMdFile, byte[] Key)
198 | {
199 | byte[] IV = new byte[PSVIMGConstants.AES_BLOCK_SIZE];
200 | PsvMdFile.Read(IV, 0x00, IV.Length);
201 | byte[] remaining = new byte[PsvMdFile.Length - IV.Length];
202 | PsvMdFile.Read(remaining, 0x00, remaining.Length);
203 | byte[] zlibCompressed = aes_cbc_decrypt(remaining, IV, Key);
204 | return zlibCompressed;
205 | // return ZlibStream.UncompressBuffer(zlibCompressed);
206 | }
207 | }
208 | }
209 |
--------------------------------------------------------------------------------
/CHOVY-TRANSFER/Sfo.cs:
--------------------------------------------------------------------------------
1 | using Li.Utilities;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Diagnostics.Tracing;
5 | using System.IO;
6 | using System.Runtime.CompilerServices;
7 |
8 | // A Sfo Parser Written by Li
9 | // Because all the others are overly-complicated for no reason!
10 | // MIT Licensed.
11 |
12 | namespace Param
13 | {
14 |
15 | public class Sfo
16 | {
17 |
18 | private struct SfoEntry
19 | {
20 | internal string keyName;
21 | internal byte type;
22 | internal UInt32 valueSize;
23 | internal UInt32 totalSize;
24 | internal byte align;
25 | internal object value;
26 | }
27 |
28 | const int SFO_MAGIC = 0x46535000;
29 | const byte PSF_TYPE_BIN = 0;
30 | const byte PSF_TYPE_STR = 2;
31 | const byte PSF_TYPE_VAL = 4;
32 |
33 | private Dictionary sfoEntries;
34 | public Object this[string index]
35 | {
36 | get
37 | {
38 | if (sfoEntries.ContainsKey(index))
39 | return sfoEntries[index].value;
40 | else
41 | return null;
42 | }
43 | set
44 | {
45 | if (sfoEntries.ContainsKey(index))
46 | {
47 | SfoEntry sfoEnt = sfoEntries[index];
48 | sfoEnt.value = value;
49 |
50 | // update sz
51 | sfoEnt.valueSize = getObjectSz(sfoEnt.value);
52 |
53 | if (sfoEnt.valueSize > sfoEnt.totalSize)
54 | sfoEnt.totalSize = Convert.ToUInt32(MathUtil.CalculatePaddingAmount(Convert.ToInt32(sfoEnt.valueSize), sfoEnt.align));
55 |
56 | // update type
57 | sfoEnt.type = getPsfType(sfoEnt.value);
58 |
59 | sfoEntries[index] = sfoEnt;
60 | }
61 | else
62 | {
63 | UInt32 sz = getObjectSz(value);
64 | int alg = MathUtil.CalculatePaddingAmount(Convert.ToInt32(sz), 4);
65 |
66 | AddKey(index, value, Convert.ToUInt32(sz + alg), 4);
67 | }
68 | }
69 | }
70 |
71 | public void AddKey(string keyName, object value, UInt32 totalSize, byte align = 4)
72 | {
73 | SfoEntry ent = new SfoEntry();
74 | ent.keyName = keyName;
75 | ent.type = getPsfType(value);
76 | ent.valueSize = getObjectSz(value);
77 | ent.totalSize = Convert.ToUInt32(totalSize + MathUtil.CalculatePaddingAmount(Convert.ToInt32(totalSize), align));
78 | ent.align = align;
79 | ent.value = value;
80 | sfoEntries[ent.keyName] = ent;
81 | }
82 |
83 | public Sfo()
84 | {
85 | sfoEntries = new Dictionary();
86 | }
87 |
88 |
89 | private static UInt32 getObjectSz(Object obj)
90 | {
91 | if (obj is Int32) return 4;
92 | if (obj is UInt32) return 4;
93 | if (obj is String) return Convert.ToUInt32((obj as String).Length + 1);
94 | if (obj is Byte[]) return Convert.ToUInt32((obj as Byte[]).Length);
95 | throw new Exception("Object is of unsupported type: " + obj.GetType());
96 | }
97 |
98 | private static byte getPsfType(Object obj)
99 | {
100 | if (obj is Int32 || obj is UInt32) return PSF_TYPE_VAL;
101 | if (obj is String) return PSF_TYPE_STR;
102 | if (obj is Byte[]) return PSF_TYPE_BIN;
103 | throw new Exception("Object is of unsupported type: " + obj.GetType());
104 | }
105 |
106 | public byte[] WriteSfo(UInt32 version = 0x101, Byte align = 0x4)
107 | {
108 | using (MemoryStream sfoStream = new MemoryStream())
109 | {
110 | WriteSfo(sfoStream, version, align);
111 | byte[] sfoBytes = sfoStream.ToArray();
112 | return sfoBytes;
113 | }
114 | }
115 | public void WriteSfo(Stream SfoStream, UInt32 version = 0x101, Byte align = 0x4)
116 | {
117 | using (MemoryStream sfoStream = new MemoryStream())
118 | {
119 | StreamUtil sfoUtil = new StreamUtil(sfoStream);
120 |
121 | sfoUtil.WriteUInt32(SFO_MAGIC);
122 | sfoUtil.WriteUInt32(version);
123 |
124 | sfoUtil.WriteUInt32(0xFFFFFFFF); // key offset
125 | sfoUtil.WriteUInt32(0xFFFFFFFF); // value offset
126 | // (will fill these in after the file is created)
127 |
128 | sfoUtil.WriteInt32(sfoEntries.Count);
129 |
130 | using (MemoryStream keyTable = new MemoryStream())
131 | {
132 | StreamUtil keyUtils = new StreamUtil(keyTable);
133 | using (MemoryStream valueTable = new MemoryStream())
134 | {
135 | StreamUtil valueUtils = new StreamUtil(valueTable);
136 | foreach (SfoEntry entry in sfoEntries.Values)
137 | {
138 | // write name
139 | sfoUtil.WriteUInt16(Convert.ToUInt16(keyTable.Position));
140 | keyUtils.WriteCStr(entry.keyName);
141 |
142 |
143 |
144 | // write entry
145 |
146 | sfoUtil.WriteByte(align); // align
147 | sfoUtil.WriteByte(entry.type); // type
148 | sfoUtil.WriteUInt32(entry.valueSize); // valueSize
149 | sfoUtil.WriteUInt32(entry.totalSize); // totalSize
150 |
151 | // write data
152 | sfoUtil.WriteUInt32(Convert.ToUInt32(valueTable.Position)); // dataOffset
153 |
154 | switch (entry.type)
155 | {
156 | case PSF_TYPE_VAL:
157 | valueUtils.WriteUInt32(Convert.ToUInt32(entry.value));
158 | valueUtils.WritePadding(0x00, Convert.ToInt32(entry.totalSize - entry.valueSize));
159 | break;
160 | case PSF_TYPE_STR:
161 | valueUtils.WriteStrWithPadding(entry.value as String, 0x00, Convert.ToInt32(entry.totalSize));
162 | break;
163 | case PSF_TYPE_BIN:
164 | valueUtils.WriteBytesWithPadding(entry.value as Byte[], 0x00, Convert.ToInt32(entry.totalSize));
165 | break;
166 | }
167 | }
168 |
169 |
170 | keyUtils.AlignTo(0x00, align);
171 | UInt32 keyOffset = Convert.ToUInt32(sfoStream.Position);
172 | keyTable.Seek(0x00, SeekOrigin.Begin);
173 | keyTable.CopyTo(sfoStream);
174 |
175 | UInt32 valueOffset = Convert.ToUInt32(sfoStream.Position);
176 | valueTable.Seek(0x00, SeekOrigin.Begin);
177 | valueTable.CopyTo(sfoStream);
178 |
179 | sfoStream.Seek(0x8, SeekOrigin.Begin);
180 | sfoUtil.WriteUInt32(keyOffset); // key offset
181 | sfoUtil.WriteUInt32(valueOffset); // value offset
182 | }
183 | }
184 |
185 | sfoStream.Seek(0x0, SeekOrigin.Begin);
186 | sfoStream.CopyTo(SfoStream);
187 | }
188 |
189 | }
190 |
191 | public static Sfo ReadSfo(Stream SfoStream)
192 | {
193 | Sfo sfoFile = new Sfo();
194 | StreamUtil DataUtils = new StreamUtil(SfoStream);
195 |
196 | // Read Sfo Header
197 | UInt32 magic = DataUtils.ReadUInt32();
198 | UInt32 version = DataUtils.ReadUInt32();
199 | UInt32 keyOffset = DataUtils.ReadUInt32();
200 | UInt32 valueOffset = DataUtils.ReadUInt32();
201 | UInt32 count = DataUtils.ReadUInt32();
202 |
203 | if (magic == SFO_MAGIC) //\x00PSF
204 | {
205 | for (int i = 0; i < count; i++)
206 | {
207 | SfoEntry entry = new SfoEntry();
208 |
209 | UInt16 nameOffset = DataUtils.ReadUInt16();
210 | entry.align = DataUtils.ReadByte();
211 | entry.type = DataUtils.ReadByte();
212 | entry.valueSize = DataUtils.ReadUInt32();
213 | entry.totalSize = DataUtils.ReadUInt32();
214 | UInt32 dataOffset = DataUtils.ReadUInt32();
215 |
216 | int keyLocation = Convert.ToInt32(keyOffset + nameOffset);
217 | entry.keyName = DataUtils.ReadStringAt(keyLocation);
218 | int valueLocation = Convert.ToInt32(valueOffset + dataOffset);
219 |
220 |
221 | switch (entry.type)
222 | {
223 | case PSF_TYPE_STR:
224 | entry.value = DataUtils.ReadStringAt(valueLocation);
225 | break;
226 |
227 | case PSF_TYPE_VAL:
228 | entry.value = DataUtils.ReadUInt32At(valueLocation);
229 | break;
230 |
231 | case PSF_TYPE_BIN:
232 | entry.value = DataUtils.ReadBytesAt(valueLocation, Convert.ToInt32(entry.valueSize));
233 | break;
234 | }
235 |
236 |
237 | sfoFile.sfoEntries[entry.keyName] = entry;
238 | }
239 |
240 | }
241 | else
242 | {
243 | throw new InvalidDataException("Sfo Magic is Invalid.");
244 | }
245 |
246 | return sfoFile;
247 | }
248 |
249 | public static Sfo ReadSfo(byte[] Sfo)
250 | {
251 | using (MemoryStream SfoStream = new MemoryStream(Sfo))
252 | {
253 | return ReadSfo(SfoStream);
254 | }
255 | }
256 | }
257 | }
258 |
--------------------------------------------------------------------------------
/PspCrypto/AesHelper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using System.Security.Cryptography;
4 |
5 | namespace PspCrypto
6 | {
7 | public static class AesHelper
8 | {
9 | private static readonly byte[] padding = { 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11 };
10 |
11 | static readonly byte[] IV0 = new byte[16];
12 | static readonly byte[] Z = new byte[16];
13 |
14 | public static Aes CreateAes()
15 | {
16 | var aes = Aes.Create();
17 | aes.KeySize = 128;
18 | if (aes == null)
19 | {
20 | throw new Exception("Create Aes Failed");
21 | }
22 | aes.Mode = CipherMode.CBC;
23 | aes.Padding = PaddingMode.None;
24 | aes.IV = IV0;
25 | return aes;
26 | }
27 |
28 | public static Aes CreateKirkAes()
29 | {
30 | var aes = CreateAes();
31 | aes.Key = KeyVault.kirk1_key;
32 | return aes;
33 | }
34 |
35 | #if false
36 | public static byte[] Cmac(Aes aes, byte[] orgdata, int offset = 0, int len = -1)
37 | {
38 | if (len == -1)
39 | {
40 | len = orgdata.Length;
41 | }
42 |
43 | byte[] data;
44 | if (offset == 0 && len == orgdata.Length)
45 | {
46 | data = orgdata;
47 | }
48 | else
49 | {
50 | data = new byte[len];
51 | Buffer.BlockCopy(orgdata, offset, data, 0, len);
52 | }
53 | // SubKey generation
54 | // step 1, AES-128 with key K is applied to an all-zero input block.
55 | byte[] L = AesEncrypt(aes, Z);
56 |
57 | // step 2, K1 is derived through the following operation:
58 | byte[] FirstSubkey = Rol(L); //If the most significant bit of L is equal to 0, K1 is the left-shift of L by 1 bit.
59 | if ((L[0] & 0x80) == 0x80)
60 | FirstSubkey[15] ^= 0x87; // Otherwise, K1 is the exclusive-OR of c
61 |
62 | // step 3, K2 is derived through the following operation:
63 | byte[] SecondSubkey = Rol(FirstSubkey); // If the most significant bit of K1 is equal to 0, K2 is the left-shift of K1 by 1 bit.
64 | if ((FirstSubkey[0] & 0x80) == 0x80)
65 | SecondSubkey[15] ^= 0x87; // Otherwise, K2 is the exclusive-OR of const_Rb and the left-shift of K1 by 1 bit.
66 |
67 | // MAC computing
68 | if (((data.Length != 0) && (data.Length % 16 == 0)))
69 | {
70 | // If the size of the input message block is equal to a positive multiple of the block size (namely, 128 bits),
71 | // the last block shall be exclusive-OR'ed with K1 before processing
72 | for (int j = 0; j < FirstSubkey.Length; j++)
73 | data[data.Length - 16 + j] ^= FirstSubkey[j];
74 | }
75 | else
76 | {
77 | // Otherwise, the last block shall be padded with 10^i
78 | byte[] padding = new byte[16 - data.Length % 16];
79 | padding[0] = 0x80;
80 |
81 | data = data.Concat(padding).ToArray();
82 |
83 | // and exclusive-OR'ed with K2
84 | for (int j = 0; j < SecondSubkey.Length; j++)
85 | data[data.Length - 16 + j] ^= SecondSubkey[j];
86 | }
87 |
88 | // The result of the previous process will be the input of the last encryption.
89 | byte[] encResult = AesEncrypt(aes, data);
90 |
91 | byte[] HashValue = new byte[16];
92 | //Array.Copy(encResult, encResult.Length - HashValue.Length, HashValue, 0, HashValue.Length);
93 | Buffer.BlockCopy(encResult, encResult.Length - HashValue.Length, HashValue, 0, HashValue.Length);
94 |
95 | return HashValue;
96 | }
97 |
98 | #endif
99 | public static void Cmac(Aes aes, Span dst, ReadOnlySpan src)
100 | {
101 | byte[] data = src.ToArray();
102 | // SubKey generation
103 | // step 1, AES-128 with key K is applied to an all-zero input block.
104 | byte[] L = AesEncrypt(aes, Z);
105 |
106 | // step 2, K1 is derived through the following operation:
107 | byte[] FirstSubkey = Rol(L); //If the most significant bit of L is equal to 0, K1 is the left-shift of L by 1 bit.
108 | if ((L[0] & 0x80) == 0x80)
109 | FirstSubkey[15] ^= 0x87; // Otherwise, K1 is the exclusive-OR of c
110 |
111 | // step 3, K2 is derived through the following operation:
112 | byte[] SecondSubkey = Rol(FirstSubkey); // If the most significant bit of K1 is equal to 0, K2 is the left-shift of K1 by 1 bit.
113 | if ((FirstSubkey[0] & 0x80) == 0x80)
114 | SecondSubkey[15] ^= 0x87; // Otherwise, K2 is the exclusive-OR of const_Rb and the left-shift of K1 by 1 bit.
115 |
116 | // MAC computing
117 | if (((data.Length != 0) && (data.Length % 16 == 0)))
118 | {
119 | // If the size of the input message block is equal to a positive multiple of the block size (namely, 128 bits),
120 | // the last block shall be exclusive-OR'ed with K1 before processing
121 | for (int j = 0; j < FirstSubkey.Length; j++)
122 | data[data.Length - 16 + j] ^= FirstSubkey[j];
123 | }
124 | else
125 | {
126 | // Otherwise, the last block shall be padded with 10^i
127 | byte[] padding = new byte[16 - data.Length % 16];
128 | padding[0] = 0x80;
129 |
130 | data = data.Concat(padding).ToArray();
131 |
132 | // and exclusive-OR'ed with K2
133 | for (int j = 0; j < SecondSubkey.Length; j++)
134 | data[data.Length - 16 + j] ^= SecondSubkey[j];
135 | }
136 |
137 | // The result of the previous process will be the input of the last encryption.
138 | byte[] encResult = AesEncrypt(aes, data);
139 |
140 | encResult.AsSpan(encResult.Length - 16,16).CopyTo(dst);
141 |
142 | //byte[] HashValue = new byte[16];
143 | //Array.Copy(encResult, encResult.Length - HashValue.Length, HashValue, 0, HashValue.Length);
144 | //Buffer.BlockCopy(encResult, encResult.Length - HashValue.Length, HashValue, 0, HashValue.Length);
145 |
146 | //return HashValue;
147 | }
148 |
149 | private static byte[] Rol(byte[] b)
150 | {
151 | byte[] r = new byte[b.Length];
152 | byte carry = 0;
153 |
154 | for (int i = b.Length - 1; i >= 0; i--)
155 | {
156 | ushort u = (ushort)(b[i] << 1);
157 | r[i] = (byte)((u & 0xff) + carry);
158 | carry = (byte)((u & 0xff00) >> 8);
159 | }
160 |
161 | return r;
162 | }
163 |
164 | private static byte[] AesEncrypt(Aes aes, byte[] data)
165 | {
166 | using var encryptor = aes.CreateEncryptor();
167 | return encryptor.TransformFinalBlock(data, 0, data.Length);
168 | }
169 | #if false
170 |
171 | public static byte[] AesEncrypt(Aes aes, byte[] data, int offset, int length)
172 | {
173 | using var encryptor = aes.CreateEncryptor();
174 | return encryptor.TransformFinalBlock(data, offset, length);
175 | }
176 | #endif
177 |
178 | public static void AesEncrypt(Aes aes, Span oubput, ReadOnlySpan input, int size = 0)
179 | {
180 | byte[] buffer;
181 | if (size == 0)
182 | {
183 | size = input.Length;
184 | }
185 | if (size % 16 != 0)
186 | {
187 | buffer = new byte[(size + 15) / 16 * 16];
188 | var bufferSpan = new Span(buffer);
189 | input.CopyTo(bufferSpan);
190 | padding.AsSpan(0, buffer.Length - size).CopyTo(bufferSpan[size..]);
191 | }
192 | else
193 | {
194 | buffer = input[..size].ToArray();
195 | }
196 | using var encryptor = aes.CreateEncryptor();
197 | var encData = encryptor.TransformFinalBlock(buffer, 0, buffer.Length);
198 | encData.AsSpan().CopyTo(oubput);
199 | }
200 |
201 | #if false
202 | public static byte[] AesDecrypt(Aes aes, byte[] data, int offset, int length)
203 | {
204 | aes.Padding = PaddingMode.None;
205 | using var encryptor = aes.CreateDecryptor();
206 | int fixLength = length;
207 | if (length % 16 != 0)
208 | {
209 | fixLength = (length / 16 + 1) * 16;
210 | }
211 |
212 | byte[] ret = encryptor.TransformFinalBlock(data, offset, fixLength);
213 | return ret.Take(length).ToArray();
214 | }
215 |
216 | public static void AesDecrypt(Aes aes, byte[] src, byte[] dst, int size)
217 | {
218 | var tmp = AesDecrypt(aes, src, 0, size);
219 | Buffer.BlockCopy(tmp, 0, dst, 0, size);
220 | }
221 | #endif
222 |
223 | public static void AesDecrypt(Aes aes, Span dst, ReadOnlySpan src, int length)
224 | {
225 |
226 | int fixLength = length;
227 | if (length % 16 != 0)
228 | {
229 | fixLength = (length + 15) / 16 * 16;
230 | }
231 | var buffer = src[..fixLength].ToArray();
232 | using var encryptor = aes.CreateDecryptor();
233 | var decData = encryptor.TransformFinalBlock(buffer, 0, buffer.Length);
234 | decData.AsSpan(0, length).CopyTo(dst);
235 | }
236 |
237 | public static int AesDecrypt(ReadOnlySpan src, Span dst, ReadOnlySpan key)
238 | {
239 | Aes aes = Aes.Create();
240 | aes.Key = key[..16].ToArray();
241 | return aes.DecryptEcb(src[..16], dst, PaddingMode.None);
242 | }
243 |
244 | public static int AesEncrypt(ReadOnlySpan src, Span dst, ReadOnlySpan key)
245 | {
246 | Aes aes = Aes.Create();
247 | aes.Key = key[..16].ToArray();
248 | return aes.EncryptEcb(src[..16], dst, PaddingMode.None);
249 | }
250 | }
251 | }
252 |
--------------------------------------------------------------------------------
/Vita/PsvImgTools/PSVIMGStream.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Security.Cryptography;
4 |
5 |
6 | namespace Vita.PsvImgTools
7 | {
8 | public class PSVIMGStream : Stream
9 | {
10 | private Stream baseStream;
11 | private MemoryStream blockStream;
12 | private byte[] key;
13 | public Stream BaseStream
14 | {
15 | get
16 | {
17 | return baseStream;
18 | }
19 | }
20 |
21 | public byte[] Key
22 | {
23 | get
24 | {
25 | return key;
26 | }
27 | set
28 | {
29 | key = value;
30 | }
31 | }
32 |
33 | public long BlockNo
34 | {
35 | get
36 | {
37 | return getBlockIndex();
38 | }
39 | set
40 | {
41 | seekToBlock(value);
42 | update();
43 | }
44 | }
45 |
46 | public long BlockRemaining
47 | {
48 | get
49 | {
50 | return getRemainingBlock();
51 | }
52 | }
53 |
54 | public long BlockPosition
55 | {
56 | get
57 | {
58 | return blockStream.Position;
59 | }
60 | set
61 | {
62 | blockStream.Seek(value, SeekOrigin.Begin);
63 | }
64 | }
65 | public override bool CanWrite
66 | {
67 | get
68 | {
69 | return false;
70 | }
71 | }
72 |
73 | public override bool CanRead
74 | {
75 | get
76 | {
77 | return true;
78 | }
79 | }
80 | public override long Length
81 | {
82 | get
83 | {
84 | return baseStream.Length - PSVIMGConstants.AES_BLOCK_SIZE;
85 | }
86 | }
87 |
88 | public override bool CanSeek
89 | {
90 | get
91 | {
92 | return true;
93 | }
94 | }
95 |
96 | public override long Position
97 | {
98 | get
99 | {
100 | return baseStream.Position - PSVIMGConstants.AES_BLOCK_SIZE;
101 | }
102 | set
103 | {
104 | Seek(value, SeekOrigin.Begin);
105 | }
106 |
107 | }
108 |
109 | public PSVIMGStream(Stream file, byte[] KEY)
110 | {
111 | baseStream = file;
112 | key = KEY;
113 | if (!verifyFooter())
114 | {
115 | throw new Exception("Invalid KEY!");
116 | }
117 | blockStream = new MemoryStream();
118 | baseStream.Seek(PSVIMGConstants.AES_BLOCK_SIZE, SeekOrigin.Begin);
119 | update();
120 | }
121 |
122 | public override int Read(byte[] buffer, int offset, int count)
123 | {
124 | int remaining = (int)getRemainingBlock();
125 | int read = 0;
126 |
127 | if (count < remaining)
128 | {
129 | read += blockStream.Read(buffer, offset, count);
130 | baseStream.Seek(count, SeekOrigin.Current);
131 | }
132 | else
133 | {
134 | using (MemoryStream ms = new MemoryStream())
135 | {
136 | while (true)
137 | {
138 | update();
139 | remaining = (int)getRemainingBlock();
140 | int curPos = count - read;
141 |
142 | if (curPos > remaining)
143 | {
144 | read += remaining;
145 | blockStream.CopyTo(ms, remaining);
146 | baseStream.Seek(remaining, SeekOrigin.Current);
147 | }
148 | else
149 | {
150 | read += curPos;
151 | blockStream.CopyTo(ms, curPos);
152 | baseStream.Seek(curPos, SeekOrigin.Current);
153 | break;
154 | }
155 |
156 | }
157 | ms.Seek(0x00, SeekOrigin.Begin);
158 | ms.Read(buffer, offset, count);
159 | }
160 | }
161 | return read;
162 |
163 | }
164 |
165 | public override void Flush()
166 | {
167 | update();
168 | baseStream.Flush();
169 | blockStream.Flush();
170 | }
171 |
172 | public override long Seek(long offset, SeekOrigin origin)
173 | {
174 | long ret = 0;
175 | if (origin == SeekOrigin.Begin)
176 | {
177 | ret = baseStream.Seek(offset + PSVIMGConstants.AES_BLOCK_SIZE, SeekOrigin.Begin);
178 | }
179 | else if (origin == SeekOrigin.Current)
180 | {
181 | long pos = baseStream.Position;
182 | if (pos + offset >= PSVIMGConstants.AES_BLOCK_SIZE)
183 | {
184 | ret = baseStream.Seek(offset, SeekOrigin.Current);
185 | }
186 | else
187 | {
188 | ret = baseStream.Seek(offset + PSVIMGConstants.AES_BLOCK_SIZE, SeekOrigin.Current);
189 | }
190 | }
191 | else if (origin == SeekOrigin.End)
192 | {
193 | long pos = baseStream.Length;
194 | if (pos + offset >= PSVIMGConstants.AES_BLOCK_SIZE)
195 | {
196 | ret = baseStream.Seek(offset, SeekOrigin.End);
197 | }
198 | else
199 | {
200 | ret = baseStream.Seek(offset + PSVIMGConstants.AES_BLOCK_SIZE, SeekOrigin.End);
201 | }
202 | }
203 | update();
204 | return ret;
205 | }
206 |
207 | public override void SetLength(long value)
208 | {
209 | throw new NotImplementedException("PSVIMGStream is Read-Only");
210 | }
211 |
212 | public override void Write(byte[] buffer, int offset, int count)
213 | {
214 | throw new NotImplementedException("PSVIMGStream is Read-Only");
215 | }
216 |
217 |
218 | public override void Close()
219 | {
220 | blockStream.Dispose();
221 | baseStream.Dispose();
222 | base.Close();
223 | }
224 | private void update()
225 | {
226 | long offset = Position % PSVIMGConstants.FULL_PSVIMG_SIZE;
227 | long blockIndex = getBlockIndex();
228 | byte[] decryptedBlock = getBlock(blockIndex);
229 | blockStream.Seek(0x00, SeekOrigin.Begin);
230 | blockStream.SetLength(decryptedBlock.Length);
231 | blockStream.Write(decryptedBlock, 0x00, decryptedBlock.Length);
232 | seekToBlock(blockIndex);
233 | baseStream.Seek(offset, SeekOrigin.Current);
234 | blockStream.Seek(offset, SeekOrigin.Begin);
235 | }
236 |
237 | private long getBlockIndex()
238 | {
239 | long i = 0;
240 | long curPos = baseStream.Position;
241 | long fullBlock;
242 | long blockOffset;
243 |
244 | while (true)
245 | {
246 | blockOffset = i * PSVIMGConstants.FULL_PSVIMG_SIZE + PSVIMGConstants.AES_BLOCK_SIZE;
247 | long remaining = getRemainingBase();
248 | if (remaining < PSVIMGConstants.FULL_PSVIMG_SIZE)
249 | {
250 | fullBlock = blockOffset + remaining;
251 | }
252 | else
253 | {
254 | fullBlock = blockOffset + PSVIMGConstants.FULL_PSVIMG_SIZE;
255 | }
256 | if (curPos >= blockOffset && curPos < fullBlock)
257 | {
258 | break;
259 | }
260 | if (blockOffset > baseStream.Length)
261 | {
262 | break;
263 | }
264 | i++;
265 | }
266 | return i;
267 |
268 |
269 | }
270 | private long getRemainingBase()
271 | {
272 | return baseStream.Length - baseStream.Position;
273 | }
274 | private long getRemainingBlock()
275 | {
276 | return blockStream.Length - blockStream.Position;
277 | }
278 | private byte[] getIV(long blockindex)
279 | {
280 | byte[] iv = new byte[0x10];
281 | seekToBlock(blockindex);
282 | baseStream.Seek(baseStream.Position - PSVIMGConstants.AES_BLOCK_SIZE, SeekOrigin.Begin);
283 | baseStream.Read(iv, 0x00, iv.Length);
284 | return iv;
285 | }
286 | private byte[] aes_cbc_decrypt(byte[] cipherData, byte[] IV)
287 | {
288 | MemoryStream ms = new MemoryStream();
289 | Aes alg = Aes.Create();
290 | alg.Mode = CipherMode.CBC;
291 | alg.Padding = PaddingMode.None;
292 | alg.KeySize = 256;
293 | alg.BlockSize = 128;
294 | alg.Key = key;
295 | alg.IV = IV;
296 | CryptoStream cs = new CryptoStream(ms, alg.CreateDecryptor(), CryptoStreamMode.Write);
297 | cs.Write(cipherData, 0, cipherData.Length);
298 | cs.Close();
299 | byte[] decryptedData = ms.ToArray();
300 | return decryptedData;
301 | }
302 |
303 | private void seekToBlock(long blockIndex)
304 | {
305 | long blockOffset;
306 | blockOffset = blockIndex * PSVIMGConstants.FULL_PSVIMG_SIZE + PSVIMGConstants.AES_BLOCK_SIZE;
307 |
308 | if (blockOffset > baseStream.Length)
309 | {
310 | blockOffset = baseStream.Length;
311 | }
312 |
313 | baseStream.Seek(blockOffset, SeekOrigin.Begin);
314 | }
315 |
316 | private bool verifyFooter()
317 | {
318 | byte[] Footer = new byte[0x10];
319 | byte[] IV = new byte[PSVIMGConstants.AES_BLOCK_SIZE];
320 |
321 | baseStream.Seek(baseStream.Length - (Footer.Length + IV.Length), SeekOrigin.Begin);
322 | baseStream.Read(IV, 0x00, PSVIMGConstants.AES_BLOCK_SIZE);
323 | baseStream.Read(Footer, 0x00, 0x10);
324 |
325 | byte[] FooterDec = aes_cbc_decrypt(Footer, IV);
326 | ulong FooterLen;
327 | using (MemoryStream ms = new MemoryStream(FooterDec))
328 | {
329 | ms.Seek(0x4, SeekOrigin.Current);
330 | ms.Seek(0x4, SeekOrigin.Current);
331 | byte[] LenInt = new byte[0x8];
332 | ms.Read(LenInt, 0x00, 0x8);
333 | FooterLen = BitConverter.ToUInt64(LenInt, 0x00);
334 | }
335 | if (Convert.ToUInt64(baseStream.Length) == FooterLen)
336 | {
337 | return true;
338 | }
339 | else
340 | {
341 | return false;
342 | }
343 | }
344 |
345 | private byte[] getBlock(long blockIndex)
346 | {
347 | byte[] iv = getIV(blockIndex);
348 | long remaining = getRemainingBase();
349 | byte[] encryptedBlock;
350 | if (PSVIMGConstants.FULL_PSVIMG_SIZE < remaining)
351 | {
352 | encryptedBlock = new byte[PSVIMGConstants.FULL_PSVIMG_SIZE];
353 | }
354 | else
355 | {
356 | encryptedBlock = new byte[remaining];
357 | }
358 |
359 |
360 | baseStream.Read(encryptedBlock, 0x00, encryptedBlock.Length);
361 | byte[] decryptedBlock = aes_cbc_decrypt(encryptedBlock, iv);
362 | return decryptedBlock;
363 | }
364 | }
365 | }
--------------------------------------------------------------------------------
/Vita/PsvImgTools/PSVIMGFileStream.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using static Vita.PsvImgTools.SceIoStat;
4 |
5 | namespace Vita.PsvImgTools
6 | {
7 | public class PSVIMGFileStream : Stream
8 | {
9 |
10 | long length = 0;
11 | long startPos = 0;
12 | long endPos = 0;
13 | long position = 0;
14 |
15 | private PSVIMGStream psvStream;
16 | public PSVIMGFileStream(PSVIMGStream psv, string Path)
17 | {
18 | psvStream = psv;
19 | if (Path.First() == '/')
20 | findFile(Path);
21 | else
22 | findFileMatching(Path);
23 | }
24 |
25 | public void WriteToFile(string FilePath)
26 | {
27 | using (FileStream fs = File.OpenWrite(FilePath))
28 | {
29 | fs.SetLength(0);
30 | int written = 0;
31 | long left = length - written;
32 | byte[] work_buf;
33 | Seek(0x00, SeekOrigin.Begin);
34 | while (left > 0)
35 | {
36 | left = length - written;
37 | if (left < 0x10000)
38 | {
39 | work_buf = new byte[left];
40 | }
41 | else
42 | {
43 | work_buf = new byte[0x10000];
44 | }
45 | Read(work_buf, 0x00, work_buf.Length);
46 | fs.Write(work_buf, 0x00, work_buf.Length);
47 | written += work_buf.Length;
48 | }
49 |
50 |
51 | }
52 |
53 | }
54 | public override bool CanRead
55 | {
56 | get
57 | {
58 | return true;
59 | }
60 | }
61 |
62 | public override bool CanSeek
63 | {
64 | get
65 | {
66 | return true;
67 | }
68 | }
69 | public override bool CanWrite
70 | {
71 | get
72 | {
73 | return false;
74 | }
75 | }
76 | public override long Length
77 | {
78 | get
79 | {
80 | return length;
81 | }
82 | }
83 |
84 | public override long Position
85 | {
86 | get
87 | {
88 | return position;
89 | }
90 | set
91 | {
92 | Seek(value, SeekOrigin.Begin);
93 | }
94 | }
95 |
96 | public override void Flush()
97 | {
98 | psvStream.Flush();
99 | }
100 | private int _read(byte[] buffer, int offset, int count)
101 | {
102 |
103 | using (MemoryStream ms = new MemoryStream())
104 | {
105 | int read = 0;
106 | while (true)
107 | {
108 | int remainBlock = Convert.ToInt32(psvStream.BlockRemaining - PSVIMGConstants.SHA256_BLOCK_SIZE);
109 | int remainRead = count - read;
110 |
111 | if (remainRead < remainBlock)
112 | {
113 | byte[] tmp = new byte[remainRead];
114 | psvStream.Read(tmp, 0x00, remainRead);
115 | ms.Write(tmp, 0x00, tmp.Length);
116 | read += remainRead;
117 | break;
118 | }
119 | else
120 | {
121 | byte[] tmp = new byte[remainBlock];
122 | psvStream.Read(tmp, 0x00, remainBlock);
123 | ms.Write(tmp, 0x00, tmp.Length);
124 | psvStream.Seek(PSVIMGConstants.SHA256_BLOCK_SIZE, SeekOrigin.Current);
125 | read += Convert.ToInt32(remainBlock);
126 | }
127 | }
128 | ms.Seek(0x00, SeekOrigin.Begin);
129 | return ms.Read(buffer, offset, count);
130 | }
131 |
132 | }
133 |
134 | private long _seek(long amount, SeekOrigin orig)
135 | {
136 | long ToSeek = 0;
137 | long SeekAdd = 0;
138 | long remainBlock = psvStream.BlockRemaining - PSVIMGConstants.SHA256_BLOCK_SIZE;
139 | while (true)
140 | {
141 | long remainSeek = amount - ToSeek;
142 |
143 | if (remainSeek < remainBlock)
144 | {
145 | ToSeek += remainSeek;
146 | break;
147 | }
148 | else
149 | {
150 | ToSeek += remainBlock;
151 | SeekAdd += PSVIMGConstants.SHA256_BLOCK_SIZE;
152 | }
153 | remainBlock = PSVIMGConstants.PSVIMG_BLOCK_SIZE;
154 | }
155 | ToSeek += SeekAdd;
156 | return psvStream.Seek(ToSeek, orig);
157 | }
158 | public override int Read(byte[] buffer, int offset, int count)
159 | {
160 | if (startPos + count > endPos)
161 | {
162 | count = Convert.ToInt32(endPos);
163 | }
164 | return _read(buffer, offset, count);
165 | }
166 |
167 | public override long Seek(long offset, SeekOrigin origin)
168 | {
169 | if (origin == SeekOrigin.Begin)
170 | {
171 | if (offset <= endPos)
172 | {
173 | psvStream.Seek(startPos, SeekOrigin.Begin);
174 | _seek(offset, SeekOrigin.Current);
175 | position = offset;
176 | return position;
177 | }
178 | else
179 | {
180 | throw new IndexOutOfRangeException("Offset is out of range of file");
181 | }
182 |
183 | }
184 | else if (origin == SeekOrigin.Current)
185 | {
186 | if (offset <= endPos)
187 | {
188 | _seek(offset, SeekOrigin.Current);
189 | position += offset;
190 | return position;
191 | }
192 | else
193 | {
194 | throw new IndexOutOfRangeException("Offset is out of range of file");
195 | }
196 | }
197 | else
198 | {
199 | long realOffset = endPos + offset;
200 | if (realOffset <= endPos)
201 | {
202 | _seek(realOffset, SeekOrigin.Begin);
203 | return Position;
204 | }
205 | else
206 | {
207 | throw new IndexOutOfRangeException("Offset is out of range of file");
208 | }
209 | }
210 |
211 | }
212 |
213 | public override void SetLength(long value)
214 | {
215 | throw new NotImplementedException("PSVFileStream is Read-Only");
216 | }
217 |
218 | public override void Write(byte[] buffer, int offset, int count)
219 | {
220 | throw new NotImplementedException("PSVFileStream is Read-Only");
221 | }
222 |
223 | private ushort readUInt16()
224 | {
225 | byte[] intBuf = new byte[0x2];
226 | _read(intBuf, 0x00, 0x02);
227 | return BitConverter.ToUInt16(intBuf, 0);
228 | }
229 | private uint readUInt32()
230 | {
231 | byte[] intBuf = new byte[0x4];
232 | _read(intBuf, 0x00, 0x04);
233 | return BitConverter.ToUInt32(intBuf, 0);
234 | }
235 | private ulong readUInt64()
236 | {
237 | byte[] intBuf = new byte[0x8];
238 | _read(intBuf, 0x00, 0x08);
239 | return BitConverter.ToUInt64(intBuf, 0);
240 | }
241 | private SceDateTime readDatetime()
242 | {
243 | SceDateTime dateTime = new SceDateTime();
244 | dateTime.Year = readUInt16();
245 | dateTime.Month = readUInt16();
246 | dateTime.Day = readUInt16();
247 | dateTime.Hour = readUInt16();
248 | dateTime.Minute = readUInt16();
249 | dateTime.Second = readUInt16();
250 | dateTime.Microsecond = readUInt32();
251 | return dateTime;
252 | }
253 | private SceIoStat readStats()
254 | {
255 | SceIoStat stat = new SceIoStat();
256 | stat.Mode = (Modes)readUInt32();
257 | stat.Attributes = (AttributesEnum)readUInt32();
258 | stat.Size = readUInt64();
259 | stat.CreationTime = readDatetime();
260 | stat.AccessTime = readDatetime();
261 | stat.ModificaionTime = readDatetime();
262 | for (int i = 0; i < stat.Private.Length; i++)
263 | {
264 | stat.Private[i] = readUInt32();
265 | }
266 | return stat;
267 | }
268 | private PsvImgHeader readHeader()
269 | {
270 | PsvImgHeader header = new PsvImgHeader();
271 | header.SysTime = readUInt64();
272 | header.Flags = readUInt64();
273 | header.Statistics = readStats();
274 | _read(header.bParentPath, 0x00, 256);
275 | header.unk_16C = readUInt32();
276 | _read(header.bPath, 0x00, 256);
277 | _read(header.Padding, 0x00, 904);
278 | _read(header.bEnd, 0x00, 12);
279 | return header;
280 | }
281 |
282 | public override void Close()
283 | {
284 | psvStream.Dispose();
285 | base.Close();
286 | }
287 |
288 | private PsvImgTailer readTailer()
289 | {
290 | PsvImgTailer tailer = new PsvImgTailer();
291 | tailer.Flags = readUInt64();
292 | _read(tailer.Padding, 0x00, 1004);
293 | _read(tailer.bEnd, 0x00, 12);
294 | return tailer;
295 | }
296 |
297 | private void findFileMatching(string path)
298 | {
299 | _seek(0x00, SeekOrigin.Begin);
300 | while (psvStream.Position < psvStream.Length)
301 | {
302 | PsvImgHeader header = readHeader();
303 | long size = (long)header.Statistics.Size;
304 | long padding = PSVIMGPadding.GetPadding(size);
305 |
306 | if (header.Path.Contains(path, StringComparison.InvariantCultureIgnoreCase))
307 | {
308 | length = size;
309 | startPos = psvStream.Position;
310 | endPos = startPos + length;
311 | return;
312 | }
313 | else
314 | {
315 | _seek(size + padding, SeekOrigin.Current);
316 | PsvImgTailer tailer = readTailer();
317 | }
318 |
319 | }
320 | throw new FileNotFoundException("Cannot find file specified");
321 |
322 | }
323 | private void findFile(string path)
324 | {
325 | _seek(0x00, SeekOrigin.Begin);
326 | while (psvStream.Position < psvStream.Length)
327 | {
328 | PsvImgHeader header = readHeader();
329 | long size = (long)header.Statistics.Size;
330 | long padding = PSVIMGPadding.GetPadding(size);
331 |
332 | if (header.Path.Equals(path, StringComparison.InvariantCultureIgnoreCase))
333 | {
334 | length = size;
335 | startPos = psvStream.Position;
336 | endPos = startPos + length;
337 | return;
338 | }
339 | else
340 | {
341 | _seek(size + padding, SeekOrigin.Current);
342 | PsvImgTailer tailer = readTailer();
343 | }
344 |
345 | }
346 | throw new FileNotFoundException("Cannot find file specified");
347 |
348 | }
349 | }
350 | }
351 |
--------------------------------------------------------------------------------
/PspCrypto/Security/Cryptography/SHAManagedHashProvider.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.IO;
5 | using System.Linq;
6 | using System.Security.Cryptography;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 |
10 | using static System.Numerics.BitOperations;
11 |
12 | namespace PspCrypto.Security.Cryptography
13 | {
14 | internal sealed class SHAManagedHashProvider : HashProvider
15 | {
16 | private int hashSizeInBytes;
17 | private SHAManagedImplementationBase impl;
18 | private MemoryStream buffer;
19 |
20 | public SHAManagedHashProvider(string hashAlgorithmId)
21 | {
22 | switch (hashAlgorithmId)
23 | {
24 | case HashAlgorithmNames.SHA224:
25 | impl = new SHA224ManagedImplementation();
26 | hashSizeInBytes = 28;
27 | break;
28 | default:
29 | throw new CryptographicException(string.Format("'{0}' is not a known hash algorithm.", hashAlgorithmId));
30 | }
31 | }
32 |
33 | public override void AppendHashData(ReadOnlySpan data)
34 | {
35 | buffer ??= new MemoryStream(1000);
36 |
37 | buffer.Write(data);
38 | }
39 |
40 | public override int FinalizeHashAndReset(Span destination)
41 | {
42 | GetCurrentHash(destination);
43 | buffer = null;
44 |
45 | return hashSizeInBytes;
46 | }
47 |
48 | public override int GetCurrentHash(Span destination)
49 | {
50 | Debug.Assert(destination.Length >= hashSizeInBytes);
51 |
52 | impl.Initialize();
53 | if (buffer != null)
54 | {
55 | impl.HashCore(buffer.GetBuffer(), 0, (int)buffer.Length);
56 | }
57 | impl.HashFinal().CopyTo(destination);
58 |
59 | return hashSizeInBytes;
60 | }
61 |
62 | public override int HashSizeInBytes => hashSizeInBytes;
63 |
64 | public override void Reset()
65 | {
66 | buffer = null;
67 | impl.Initialize();
68 | }
69 |
70 | public override void Dispose(bool disposing)
71 | {
72 | }
73 |
74 | private abstract class SHAManagedImplementationBase
75 | {
76 | public abstract void Initialize();
77 | public abstract void HashCore(byte[] partIn, int ibStart, int cbSize);
78 | public abstract byte[] HashFinal();
79 | }
80 |
81 | private sealed class SHA224ManagedImplementation : SHAManagedImplementationBase
82 | {
83 | private byte[] _buffer;
84 | private long _count; // Number of bytes in the hashed message
85 | private uint[] _stateSHA224;
86 | private uint[] _W;
87 |
88 | public SHA224ManagedImplementation()
89 | {
90 | _stateSHA224 = new uint[8];
91 | _buffer = new byte[64];
92 | _W = new uint[64];
93 |
94 | InitializeState();
95 | }
96 |
97 | public override void Initialize()
98 | {
99 | InitializeState();
100 |
101 | // Zeroize potentially sensitive information.
102 | Array.Clear(_buffer, 0, _buffer.Length);
103 | Array.Clear(_W, 0, _W.Length);
104 | }
105 |
106 | private void InitializeState()
107 | {
108 | _count = 0;
109 |
110 | _stateSHA224[0] = 0xc1059ed8;
111 | _stateSHA224[1] = 0x367cd507;
112 | _stateSHA224[2] = 0x3070dd17;
113 | _stateSHA224[3] = 0xf70e5939;
114 | _stateSHA224[4] = 0xffc00b31;
115 | _stateSHA224[5] = 0x68581511;
116 | _stateSHA224[6] = 0x64f98fa7;
117 | _stateSHA224[7] = 0xbefa4fa4;
118 | }
119 |
120 | /* SHA256 block update operation. Continues an SHA message-digest
121 | operation, processing another message block, and updating the
122 | context.
123 | */
124 | public override unsafe void HashCore(byte[] partIn, int ibStart, int cbSize)
125 | {
126 | int bufferLen;
127 | int partInLen = cbSize;
128 | int partInBase = ibStart;
129 |
130 | /* Compute length of buffer */
131 | bufferLen = (int)(_count & 0x3f);
132 |
133 | /* Update number of bytes */
134 | _count += partInLen;
135 |
136 | fixed (uint* stateSHA256 = _stateSHA224)
137 | {
138 | fixed (byte* buffer = _buffer)
139 | {
140 | fixed (uint* expandedBuffer = _W)
141 | {
142 | if (bufferLen > 0 && bufferLen + partInLen >= 64)
143 | {
144 | Buffer.BlockCopy(partIn, partInBase, _buffer, bufferLen, 64 - bufferLen);
145 | partInBase += 64 - bufferLen;
146 | partInLen -= 64 - bufferLen;
147 | SHATransform(expandedBuffer, stateSHA256, buffer);
148 | bufferLen = 0;
149 | }
150 |
151 | /* Copy input to temporary buffer and hash */
152 | while (partInLen >= 64)
153 | {
154 | Buffer.BlockCopy(partIn, partInBase, _buffer, 0, 64);
155 | partInBase += 64;
156 | partInLen -= 64;
157 | SHATransform(expandedBuffer, stateSHA256, buffer);
158 | }
159 |
160 | if (partInLen > 0)
161 | {
162 | Buffer.BlockCopy(partIn, partInBase, _buffer, bufferLen, partInLen);
163 | }
164 | }
165 | }
166 | }
167 | }
168 |
169 | /* SHA256 finalization. Ends an SHA256 message-digest operation, writing
170 | the message digest.
171 | */
172 | public override byte[] HashFinal()
173 | {
174 | byte[] pad;
175 | int padLen;
176 | long bitCount;
177 | byte[] hash = new byte[28]; // HashSizeValue = 224
178 |
179 | /* Compute padding: 80 00 00 ... 00 00
180 | */
181 |
182 | padLen = 64 - (int)(_count & 0x3f);
183 | if (padLen <= 8)
184 | padLen += 64;
185 |
186 | pad = new byte[padLen];
187 | pad[0] = 0x80;
188 |
189 | // Convert count to bit count
190 | bitCount = _count * 8;
191 |
192 | pad[padLen - 8] = (byte)(bitCount >> 56 & 0xff);
193 | pad[padLen - 7] = (byte)(bitCount >> 48 & 0xff);
194 | pad[padLen - 6] = (byte)(bitCount >> 40 & 0xff);
195 | pad[padLen - 5] = (byte)(bitCount >> 32 & 0xff);
196 | pad[padLen - 4] = (byte)(bitCount >> 24 & 0xff);
197 | pad[padLen - 3] = (byte)(bitCount >> 16 & 0xff);
198 | pad[padLen - 2] = (byte)(bitCount >> 8 & 0xff);
199 | pad[padLen - 1] = (byte)(bitCount >> 0 & 0xff);
200 |
201 | /* Digest padding */
202 | HashCore(pad, 0, pad.Length);
203 |
204 | /* Store digest */
205 | SHAUtils.DWORDToBigEndian(hash, _stateSHA224, 7);
206 |
207 | return hash;
208 | }
209 |
210 | private static readonly uint[] _K = {
211 | 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
212 | 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
213 | 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
214 | 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
215 | 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
216 | 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
217 | 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
218 | 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
219 | 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
220 | 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
221 | 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
222 | 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
223 | 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
224 | 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
225 | 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
226 | 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
227 | };
228 |
229 | private static unsafe void SHATransform(uint* expandedBuffer, uint* state, byte* block)
230 | {
231 | uint a, b, c, d, e, f, h, g;
232 | uint aa, bb, cc, dd, ee, ff, hh, gg;
233 | uint T1;
234 |
235 | a = state[0];
236 | b = state[1];
237 | c = state[2];
238 | d = state[3];
239 | e = state[4];
240 | f = state[5];
241 | g = state[6];
242 | h = state[7];
243 |
244 | // fill in the first 16 bytes of W.
245 | SHAUtils.DWORDFromBigEndian(expandedBuffer, 16, block);
246 | SHA256Expand(expandedBuffer);
247 |
248 | /* Apply the SHA256 compression function */
249 | // We are trying to be smart here and avoid as many copies as we can
250 | // The perf gain with this method over the straightforward modify and shift
251 | // forward is >= 20%, so it's worth the pain
252 | for (int j = 0; j < 64;)
253 | {
254 | T1 = h + Sigma_1(e) + Ch(e, f, g) + _K[j] + expandedBuffer[j];
255 | ee = d + T1;
256 | aa = T1 + Sigma_0(a) + Maj(a, b, c);
257 | j++;
258 |
259 | T1 = g + Sigma_1(ee) + Ch(ee, e, f) + _K[j] + expandedBuffer[j];
260 | ff = c + T1;
261 | bb = T1 + Sigma_0(aa) + Maj(aa, a, b);
262 | j++;
263 |
264 | T1 = f + Sigma_1(ff) + Ch(ff, ee, e) + _K[j] + expandedBuffer[j];
265 | gg = b + T1;
266 | cc = T1 + Sigma_0(bb) + Maj(bb, aa, a);
267 | j++;
268 |
269 | T1 = e + Sigma_1(gg) + Ch(gg, ff, ee) + _K[j] + expandedBuffer[j];
270 | hh = a + T1;
271 | dd = T1 + Sigma_0(cc) + Maj(cc, bb, aa);
272 | j++;
273 |
274 | T1 = ee + Sigma_1(hh) + Ch(hh, gg, ff) + _K[j] + expandedBuffer[j];
275 | h = aa + T1;
276 | d = T1 + Sigma_0(dd) + Maj(dd, cc, bb);
277 | j++;
278 |
279 | T1 = ff + Sigma_1(h) + Ch(h, hh, gg) + _K[j] + expandedBuffer[j];
280 | g = bb + T1;
281 | c = T1 + Sigma_0(d) + Maj(d, dd, cc);
282 | j++;
283 |
284 | T1 = gg + Sigma_1(g) + Ch(g, h, hh) + _K[j] + expandedBuffer[j];
285 | f = cc + T1;
286 | b = T1 + Sigma_0(c) + Maj(c, d, dd);
287 | j++;
288 |
289 | T1 = hh + Sigma_1(f) + Ch(f, g, h) + _K[j] + expandedBuffer[j];
290 | e = dd + T1;
291 | a = T1 + Sigma_0(b) + Maj(b, c, d);
292 | j++;
293 | }
294 |
295 | state[0] += a;
296 | state[1] += b;
297 | state[2] += c;
298 | state[3] += d;
299 | state[4] += e;
300 | state[5] += f;
301 | state[6] += g;
302 | state[7] += h;
303 | }
304 |
305 | private static uint Ch(uint x, uint y, uint z)
306 | {
307 | return x & y ^ (x ^ 0xffffffff) & z;
308 | }
309 |
310 | private static uint Maj(uint x, uint y, uint z)
311 | {
312 | return x & y ^ x & z ^ y & z;
313 | }
314 |
315 | private static uint sigma_0(uint x)
316 | {
317 | return RotateRight(x, 7) ^ RotateRight(x, 18) ^ x >> 3;
318 | }
319 |
320 | private static uint sigma_1(uint x)
321 | {
322 | return RotateRight(x, 17) ^ RotateRight(x, 19) ^ x >> 10;
323 | }
324 |
325 | private static uint Sigma_0(uint x)
326 | {
327 | return RotateRight(x, 2) ^ RotateRight(x, 13) ^ RotateRight(x, 22);
328 | }
329 |
330 | private static uint Sigma_1(uint x)
331 | {
332 | return RotateRight(x, 6) ^ RotateRight(x, 11) ^ RotateRight(x, 25);
333 | }
334 |
335 | /* This function creates W_16,...,W_63 according to the formula
336 | W_j <- sigma_1(W_{j-2}) + W_{j-7} + sigma_0(W_{j-15}) + W_{j-16};
337 | */
338 | private static unsafe void SHA256Expand(uint* x)
339 | {
340 | for (int i = 16; i < 64; i++)
341 | {
342 | x[i] = sigma_1(x[i - 2]) + x[i - 7] + sigma_0(x[i - 15]) + x[i - 16];
343 | }
344 | }
345 | }
346 |
347 | private static class SHAUtils
348 | {
349 | // digits == number of DWORDs
350 | public static unsafe void DWORDFromBigEndian(uint* x, int digits, byte* block)
351 | {
352 | int i;
353 | int j;
354 |
355 | for (i = 0, j = 0; i < digits; i++, j += 4)
356 | x[i] = (uint)(block[j] << 24 | block[j + 1] << 16 | block[j + 2] << 8 | block[j + 3]);
357 | }
358 |
359 | // encodes x (DWORD) into block (unsigned char), most significant byte first.
360 | // digits == number of DWORDs
361 | public static void DWORDToBigEndian(byte[] block, uint[] x, int digits)
362 | {
363 | int i;
364 | int j;
365 |
366 | for (i = 0, j = 0; i < digits; i++, j += 4)
367 | {
368 | block[j] = (byte)(x[i] >> 24 & 0xff);
369 | block[j + 1] = (byte)(x[i] >> 16 & 0xff);
370 | block[j + 2] = (byte)(x[i] >> 8 & 0xff);
371 | block[j + 3] = (byte)(x[i] & 0xff);
372 | }
373 | }
374 | }
375 | }
376 | }
377 |
--------------------------------------------------------------------------------
/CHOVY-TRANSFER/CHOVYTRANSFER.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace CHOVY_TRANSFER
2 | {
3 | partial class CHOVYTRANSFER
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Windows Form Designer generated code
24 |
25 | ///
26 | /// Required method for Designer support - do not modify
27 | /// the contents of this method with the code editor.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(CHOVYTRANSFER));
32 | this.driveLetterSrc = new System.Windows.Forms.ComboBox();
33 | this.pspFolder = new System.Windows.Forms.TextBox();
34 | this.groupBox1 = new System.Windows.Forms.GroupBox();
35 | this.cmaDir = new System.Windows.Forms.TextBox();
36 | this.driveLetterDst = new System.Windows.Forms.ComboBox();
37 | this.label2 = new System.Windows.Forms.Label();
38 | this.label1 = new System.Windows.Forms.Label();
39 | this.pspGames = new System.Windows.Forms.ListBox();
40 | this.label3 = new System.Windows.Forms.Label();
41 | this.transVita = new System.Windows.Forms.Button();
42 | this.progressBar = new System.Windows.Forms.ProgressBar();
43 | this.progressStatus = new System.Windows.Forms.Label();
44 | this.pictureBox1 = new System.Windows.Forms.PictureBox();
45 | this.dexToggle = new System.Windows.Forms.PictureBox();
46 | this.currentFile = new System.Windows.Forms.Label();
47 | this.groupBox1.SuspendLayout();
48 | ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
49 | ((System.ComponentModel.ISupportInitialize)(this.dexToggle)).BeginInit();
50 | this.SuspendLayout();
51 | //
52 | // driveLetterSrc
53 | //
54 | this.driveLetterSrc.BackColor = System.Drawing.Color.DimGray;
55 | this.driveLetterSrc.DisplayMember = "1";
56 | this.driveLetterSrc.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
57 | this.driveLetterSrc.FlatStyle = System.Windows.Forms.FlatStyle.Popup;
58 | this.driveLetterSrc.ForeColor = System.Drawing.Color.Lime;
59 | this.driveLetterSrc.FormattingEnabled = true;
60 | this.driveLetterSrc.Items.AddRange(new object[] {
61 | "A:\\",
62 | "B:\\",
63 | "C:\\",
64 | "D:\\",
65 | "E:\\",
66 | "F:\\",
67 | "G:\\",
68 | "H:\\",
69 | "I:\\",
70 | "J:\\",
71 | "K:\\",
72 | "L:\\",
73 | "M:\\",
74 | "N:\\",
75 | "O:\\",
76 | "P:\\",
77 | "Q:\\",
78 | "R:\\",
79 | "S:\\",
80 | "T:\\",
81 | "U:\\",
82 | "V:\\",
83 | "W:\\",
84 | "X:\\",
85 | "Y:\\",
86 | "Z:\\"});
87 | this.driveLetterSrc.Location = new System.Drawing.Point(86, 14);
88 | this.driveLetterSrc.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
89 | this.driveLetterSrc.Name = "driveLetterSrc";
90 | this.driveLetterSrc.Size = new System.Drawing.Size(47, 23);
91 | this.driveLetterSrc.TabIndex = 1;
92 | this.driveLetterSrc.SelectedIndexChanged += new System.EventHandler(this.driveLetterSrc_SelectedIndexChanged);
93 | //
94 | // pspFolder
95 | //
96 | this.pspFolder.BackColor = System.Drawing.Color.DimGray;
97 | this.pspFolder.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
98 | this.pspFolder.ForeColor = System.Drawing.Color.Lime;
99 | this.pspFolder.Location = new System.Drawing.Point(141, 15);
100 | this.pspFolder.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
101 | this.pspFolder.Name = "pspFolder";
102 | this.pspFolder.Size = new System.Drawing.Size(226, 23);
103 | this.pspFolder.TabIndex = 2;
104 | this.pspFolder.Text = "PSP";
105 | this.pspFolder.TextChanged += new System.EventHandler(this.pspFolder_TextChanged);
106 | //
107 | // groupBox1
108 | //
109 | this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
110 | | System.Windows.Forms.AnchorStyles.Right)));
111 | this.groupBox1.BackColor = System.Drawing.Color.Black;
112 | this.groupBox1.Controls.Add(this.cmaDir);
113 | this.groupBox1.Controls.Add(this.driveLetterDst);
114 | this.groupBox1.Controls.Add(this.label2);
115 | this.groupBox1.Controls.Add(this.label1);
116 | this.groupBox1.Controls.Add(this.driveLetterSrc);
117 | this.groupBox1.Controls.Add(this.pspFolder);
118 | this.groupBox1.ForeColor = System.Drawing.Color.Lime;
119 | this.groupBox1.Location = new System.Drawing.Point(189, 14);
120 | this.groupBox1.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
121 | this.groupBox1.Name = "groupBox1";
122 | this.groupBox1.Padding = new System.Windows.Forms.Padding(4, 3, 4, 3);
123 | this.groupBox1.Size = new System.Drawing.Size(726, 47);
124 | this.groupBox1.TabIndex = 3;
125 | this.groupBox1.TabStop = false;
126 | this.groupBox1.Text = "Directories";
127 | //
128 | // cmaDir
129 | //
130 | this.cmaDir.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
131 | | System.Windows.Forms.AnchorStyles.Right)));
132 | this.cmaDir.BackColor = System.Drawing.Color.DimGray;
133 | this.cmaDir.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
134 | this.cmaDir.ForeColor = System.Drawing.Color.Lime;
135 | this.cmaDir.Location = new System.Drawing.Point(512, 14);
136 | this.cmaDir.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
137 | this.cmaDir.Name = "cmaDir";
138 | this.cmaDir.Size = new System.Drawing.Size(206, 23);
139 | this.cmaDir.TabIndex = 6;
140 | this.cmaDir.Text = "Users\\XXX\\Documents\\PS Vita";
141 | this.cmaDir.TextChanged += new System.EventHandler(this.cmaDir_TextChanged);
142 | //
143 | // driveLetterDst
144 | //
145 | this.driveLetterDst.BackColor = System.Drawing.Color.DimGray;
146 | this.driveLetterDst.DisplayMember = "1";
147 | this.driveLetterDst.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
148 | this.driveLetterDst.FlatStyle = System.Windows.Forms.FlatStyle.Popup;
149 | this.driveLetterDst.ForeColor = System.Drawing.Color.Lime;
150 | this.driveLetterDst.FormattingEnabled = true;
151 | this.driveLetterDst.Items.AddRange(new object[] {
152 | "A:\\",
153 | "B:\\",
154 | "C:\\",
155 | "D:\\",
156 | "E:\\",
157 | "F:\\",
158 | "G:\\",
159 | "H:\\",
160 | "I:\\",
161 | "J:\\",
162 | "K:\\",
163 | "L:\\",
164 | "M:\\",
165 | "N:\\",
166 | "O:\\",
167 | "P:\\",
168 | "Q:\\",
169 | "R:\\",
170 | "S:\\",
171 | "T:\\",
172 | "U:\\",
173 | "V:\\",
174 | "W:\\",
175 | "X:\\",
176 | "Y:\\",
177 | "Z:\\"});
178 | this.driveLetterDst.Location = new System.Drawing.Point(457, 13);
179 | this.driveLetterDst.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
180 | this.driveLetterDst.Name = "driveLetterDst";
181 | this.driveLetterDst.Size = new System.Drawing.Size(47, 23);
182 | this.driveLetterDst.TabIndex = 5;
183 | this.driveLetterDst.SelectedIndexChanged += new System.EventHandler(this.driveLetterDst_SelectedIndexChanged);
184 | //
185 | // label2
186 | //
187 | this.label2.AutoSize = true;
188 | this.label2.Location = new System.Drawing.Point(376, 17);
189 | this.label2.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
190 | this.label2.Name = "label2";
191 | this.label2.Size = new System.Drawing.Size(73, 15);
192 | this.label2.TabIndex = 4;
193 | this.label2.Text = "CMA Folder:";
194 | //
195 | // label1
196 | //
197 | this.label1.AutoSize = true;
198 | this.label1.Location = new System.Drawing.Point(13, 18);
199 | this.label1.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
200 | this.label1.Name = "label1";
201 | this.label1.Size = new System.Drawing.Size(66, 15);
202 | this.label1.TabIndex = 3;
203 | this.label1.Text = "PSP Folder:";
204 | //
205 | // pspGames
206 | //
207 | this.pspGames.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
208 | | System.Windows.Forms.AnchorStyles.Left)
209 | | System.Windows.Forms.AnchorStyles.Right)));
210 | this.pspGames.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))));
211 | this.pspGames.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
212 | this.pspGames.ForeColor = System.Drawing.Color.Lime;
213 | this.pspGames.FormattingEnabled = true;
214 | this.pspGames.ItemHeight = 15;
215 | this.pspGames.Location = new System.Drawing.Point(189, 84);
216 | this.pspGames.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
217 | this.pspGames.Name = "pspGames";
218 | this.pspGames.Size = new System.Drawing.Size(725, 257);
219 | this.pspGames.TabIndex = 4;
220 | //
221 | // label3
222 | //
223 | this.label3.AutoSize = true;
224 | this.label3.ForeColor = System.Drawing.Color.Lime;
225 | this.label3.Location = new System.Drawing.Point(186, 65);
226 | this.label3.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
227 | this.label3.Name = "label3";
228 | this.label3.Size = new System.Drawing.Size(86, 15);
229 | this.label3.TabIndex = 5;
230 | this.label3.Text = "Games on PSP:";
231 | //
232 | // transVita
233 | //
234 | this.transVita.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
235 | this.transVita.BackColor = System.Drawing.Color.Black;
236 | this.transVita.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
237 | this.transVita.ForeColor = System.Drawing.Color.Red;
238 | this.transVita.Location = new System.Drawing.Point(757, 348);
239 | this.transVita.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
240 | this.transVita.Name = "transVita";
241 | this.transVita.Size = new System.Drawing.Size(158, 27);
242 | this.transVita.TabIndex = 6;
243 | this.transVita.Text = "MOV 1, PSVITA";
244 | this.transVita.UseVisualStyleBackColor = false;
245 | this.transVita.EnabledChanged += new System.EventHandler(this.transVita_EnabledChanged);
246 | this.transVita.Click += new System.EventHandler(this.transVita_Click);
247 | //
248 | // progressBar
249 | //
250 | this.progressBar.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
251 | | System.Windows.Forms.AnchorStyles.Right)));
252 | this.progressBar.Location = new System.Drawing.Point(236, 348);
253 | this.progressBar.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
254 | this.progressBar.Name = "progressBar";
255 | this.progressBar.Size = new System.Drawing.Size(514, 27);
256 | this.progressBar.TabIndex = 7;
257 | //
258 | // progressStatus
259 | //
260 | this.progressStatus.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
261 | this.progressStatus.ForeColor = System.Drawing.Color.Lime;
262 | this.progressStatus.Location = new System.Drawing.Point(186, 354);
263 | this.progressStatus.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
264 | this.progressStatus.Name = "progressStatus";
265 | this.progressStatus.Size = new System.Drawing.Size(42, 17);
266 | this.progressStatus.TabIndex = 8;
267 | this.progressStatus.Text = "0%";
268 | this.progressStatus.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
269 | //
270 | // pictureBox1
271 | //
272 | this.pictureBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
273 | | System.Windows.Forms.AnchorStyles.Left)));
274 | this.pictureBox1.BackgroundImage = global::CHOVY_TRANSFER.Properties.Resources.chovytrans;
275 | this.pictureBox1.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch;
276 | this.pictureBox1.Location = new System.Drawing.Point(10, 9);
277 | this.pictureBox1.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
278 | this.pictureBox1.Name = "pictureBox1";
279 | this.pictureBox1.Size = new System.Drawing.Size(168, 381);
280 | this.pictureBox1.TabIndex = 9;
281 | this.pictureBox1.TabStop = false;
282 | //
283 | // dexToggle
284 | //
285 | this.dexToggle.Location = new System.Drawing.Point(911, 0);
286 | this.dexToggle.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
287 | this.dexToggle.Name = "dexToggle";
288 | this.dexToggle.Size = new System.Drawing.Size(19, 18);
289 | this.dexToggle.TabIndex = 10;
290 | this.dexToggle.TabStop = false;
291 | this.dexToggle.Click += new System.EventHandler(this.dexToggle_Click);
292 | //
293 | // currentFile
294 | //
295 | this.currentFile.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
296 | | System.Windows.Forms.AnchorStyles.Right)));
297 | this.currentFile.ForeColor = System.Drawing.Color.Lime;
298 | this.currentFile.Location = new System.Drawing.Point(186, 378);
299 | this.currentFile.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
300 | this.currentFile.Name = "currentFile";
301 | this.currentFile.Size = new System.Drawing.Size(728, 17);
302 | this.currentFile.TabIndex = 11;
303 | this.currentFile.Text = "Waiting ...";
304 | this.currentFile.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
305 | //
306 | // CHOVYTRANSFER
307 | //
308 | this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
309 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
310 | this.BackColor = System.Drawing.Color.Black;
311 | this.ClientSize = new System.Drawing.Size(929, 404);
312 | this.Controls.Add(this.currentFile);
313 | this.Controls.Add(this.dexToggle);
314 | this.Controls.Add(this.pictureBox1);
315 | this.Controls.Add(this.progressStatus);
316 | this.Controls.Add(this.progressBar);
317 | this.Controls.Add(this.transVita);
318 | this.Controls.Add(this.label3);
319 | this.Controls.Add(this.pspGames);
320 | this.Controls.Add(this.groupBox1);
321 | this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
322 | this.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
323 | this.Name = "CHOVYTRANSFER";
324 | this.Text = "Chovy-Transfer";
325 | this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.CHOVYTRANSFER_FormClosing);
326 | this.Load += new System.EventHandler(this.CHOVYTRANSFER_Load);
327 | this.groupBox1.ResumeLayout(false);
328 | this.groupBox1.PerformLayout();
329 | ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
330 | ((System.ComponentModel.ISupportInitialize)(this.dexToggle)).EndInit();
331 | this.ResumeLayout(false);
332 | this.PerformLayout();
333 |
334 | }
335 |
336 | #endregion
337 | private System.Windows.Forms.ComboBox driveLetterSrc;
338 | private System.Windows.Forms.TextBox pspFolder;
339 | private System.Windows.Forms.GroupBox groupBox1;
340 | private System.Windows.Forms.Label label1;
341 | private System.Windows.Forms.Label label2;
342 | private System.Windows.Forms.TextBox cmaDir;
343 | private System.Windows.Forms.ComboBox driveLetterDst;
344 | private System.Windows.Forms.ListBox pspGames;
345 | private System.Windows.Forms.Label label3;
346 | private System.Windows.Forms.Button transVita;
347 | private System.Windows.Forms.ProgressBar progressBar;
348 | private System.Windows.Forms.Label progressStatus;
349 | private System.Windows.Forms.PictureBox pictureBox1;
350 | private System.Windows.Forms.PictureBox dexToggle;
351 | private System.Windows.Forms.Label currentFile;
352 | }
353 | }
354 |
355 |
--------------------------------------------------------------------------------