├── 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 | --------------------------------------------------------------------------------