public void Open() { DiskInfo disk = SelectedDisk; var storage = new CachedStorage(new DeviceStream(disk.PhysicalName, disk.Length).AsStorage(), disk.SectorSize * 100, 4, true); storage.SetReadOnly(); Stream stream = storage.AsStream(); Keyset keyset = OpenKeyset(); var nand = new Nand(stream, keyset); Stream prodinfo = nand.OpenProdInfo(); var calibration = new Calibration(prodinfo); keyset.EticketExtKeyRsa = Crypto.DecryptRsaKey(calibration.EticketExtKeyRsa, keyset.EticketRsaKek); Ticket[] tickets = GetTickets(keyset, nand); using (var outStream = new StreamWriter("titlekeys.txt")) { foreach (Ticket ticket in tickets) { byte[] key = ticket.GetTitleKey(keyset); outStream.WriteLine($"{ticket.RightsId.ToHexString()},{key.ToHexString()}"); } } }
public async Task <(RootedKeyPath KeyPath, Key PrivateKey)> CreatePrivateKey() { var settings = await this.GetSettings(); Keyset wallet; if (settings.DefaultKeyset is HDFingerprint fp) { wallet = await OpenKeyset(fp); } else { var extkey = new ExtKey(); wallet = new Keyset() { HDKey = extkey.GetWif(this.Network), NextKeyPath = new KeyPath(0) }; fp = extkey.Neuter().PubKey.GetHDFingerPrint(); settings.DefaultKeyset = fp; await this.SaveSettings(settings); } var key = wallet.GetNextKey(); await this.SaveKeyset(fp, wallet); return(new RootedKeyPath(fp, key.KeyPath), key.Key); }
private bool DecryptTOC() { if (VolumeHeader is null) { throw new InvalidOperationException("Header was not yet loaded"); } if (IsPatchVolume) { string path = PDIPFSPathResolver.GetPathFromSeed(VolumeHeader.TOCEntryIndex); string localPath = Path.Combine(this.PatchVolumeFolder, path); Program.Log($"[!] Volume Patch Path Table of contents located at: {localPath}", true); if (!File.Exists(localPath)) { Program.Log($"[X] Error: Unable to locate PDIPFS main TOC file on local filesystem. ({path})", true); return(false); } using var fs = new FileStream(localPath, FileMode.Open); byte[] data = new byte[VolumeHeader.CompressedTOCSize]; fs.Read(data); // Accessing a new file, we need to decrypt the header again Program.Log($"[-] TOC Entry is {VolumeHeader.TOCEntryIndex} which is at {path} - decrypting it", true); Keyset.CryptData(data, VolumeHeader.TOCEntryIndex); Program.Log($"[-] Decompressing TOC file..", true); if (!MiscUtils.TryInflateInMemory(data, VolumeHeader.TOCSize, out byte[] deflatedData))
private static void DecryptFile(CryptVerbs options, Keyset keys, string file) { byte[] input = File.ReadAllBytes(file); if (!string.IsNullOrEmpty(options.Salsa20KeyEncrypt)) { byte[] keyBytes = MiscUtils.StringToByteArray(options.Salsa20KeyEncrypt); using SymmetricAlgorithm salsa20 = new Salsa20SymmetricAlgorithm(); byte[] dataKey = new byte[8]; Console.WriteLine($"[:] Salsa Encrypting '{file}'.."); using var decrypt = salsa20.CreateDecryptor(keyBytes, dataKey); decrypt.TransformBlock(input, 0, input.Length, input, 0); } else if (!string.IsNullOrEmpty(options.Salsa20KeyDecrypt)) { byte[] keyBytes = MiscUtils.StringToByteArray(options.Salsa20KeyDecrypt); using SymmetricAlgorithm salsa20 = new Salsa20SymmetricAlgorithm(); byte[] dataKey = new byte[8]; Console.WriteLine($"[:] Salsa Decrypting '{file}'.."); using var encrypt = salsa20.CreateEncryptor(keyBytes, dataKey); encrypt.TransformBlock(input, 0, input.Length, input, 0); } else { Console.WriteLine($"[:] Crypting '{file}'.."); keys.CryptData(input, 0); } Console.WriteLine($"[:] Saving file as {file}.dec.."); File.WriteAllBytes(file, input); }
public static void generateJson(string firmware, string pathkey, string firmver, string fwint, string output) { Keyset keyset = ExternalKeyReader.ReadKeyFile(pathkey); StringBuilder sb = new StringBuilder(); StringWriter sw = new StringWriter(sb); int files = Directory.GetFiles(firmware).Length; using (JsonWriter writer = new JsonTextWriter(sw)) { writer.Formatting = Formatting.Indented; writer.WriteStartObject(); writer.WritePropertyName("fw_info"); writer.WriteStartObject(); writer.WritePropertyName("version"); writer.WriteValue(firmver); writer.WritePropertyName("IsExfat"); writer.WriteValue(true); writer.WritePropertyName("files"); writer.WriteValue(files); writer.WriteEnd(); writer.WritePropertyName("titleids"); writer.WriteStartArray(); // escribir todos los titleid ListTitleid(firmware, keyset, writer); writer.WriteEndArray(); writer.WritePropertyName("programid"); writer.WriteStartObject(); Listnca(firmware, fwint, keyset, writer); writer.WriteEndObject(); writer.WriteEnd(); } File.WriteAllText(Path.Combine(output, fwint), sb.ToString()); }
/// <summary> /// Decrypts a segmented file within a stream and saves it to the provided path. /// </summary> /// <param name="keyset"></param> /// <param name="fs"></param> /// <param name="seed"></param> /// <param name="outPath"></param> public unsafe static void DecryptToFile(Keyset keyset, FileStream fs, uint seed, uint outSize, string outPath, bool closeStream = true) { // Our new file using (var newFileStream = new FileStream(outPath, FileMode.Create)) { var decryptStream = new CryptoStream(fs, new VolumeCryptoTransform(keyset, seed), CryptoStreamMode.Read); int bytes = (int)outSize; int read; const int bufSize = 81_920; byte[] buffer = ArrayPool <byte> .Shared.Rent(bufSize); while (outSize > 0 && (read = decryptStream.Read(buffer, 0, Math.Min(buffer.Length, (int)bytes))) > 0) { newFileStream.Write(buffer, 0, read); bytes -= read; } ArrayPool <byte> .Shared.Return(buffer); } if (closeStream) { fs.Dispose(); } }
public Nca(Keyset keyset, IStorage storage, bool leaveOpen, bool isDecryptedNca = false) { LeaveOpen = leaveOpen; BaseStorage = storage; Keyset = keyset; IsDecryptedNca = isDecryptedNca; if (IsDecryptedNca) { var DecryptedHeader = new byte[0xC00]; storage.AsStream().Read(DecryptedHeader, 0, 0xC00); Header = new NcaHeader(new BinaryReader(new MemoryStream(DecryptedHeader)), keyset); } else { Header = DecryptHeader(); } CryptoType = Math.Max(Header.CryptoType, Header.CryptoType2); if (CryptoType > 0) { CryptoType--; } HasRightsId = !Header.RightsId.IsEmpty(); if (!HasRightsId) { DecryptKeyArea(keyset); } else if (keyset.TitleKeys.TryGetValue(Header.RightsId, out byte[] titleKey))
/// <summary> /// Load XCI file from disk /// </summary> /// <param name="path">Path to XCI file</param> /// <param name="verify">Verify hashes and signatures</param> /// <returns></returns> public static XCI Load(string path, Keyset keyset, bool verify = true) { using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read)) using (BinaryReader br = new BinaryReader(fs)) { XCI xci = new XCI(path); xci.Keyset = keyset; // Gamecard Header byte[] bytes = br.ReadBytes(0x200); // sizeof XCIHeader xci.GamecardHeader = bytes.ToStruct <XCIHeader>(); if (xci.GamecardHeader.MagicString != "HEAD") { throw new Exception("Invalid GamecardHeader magic! Maybe this isn't an XCI file?"); } // TODO: Gamecard Info // TODO: Gamecard Certificate // TODO: Initial Data // HFS0, see comments in HFS0Root and HFS0Partition fs.Position = 0xF000; // start of HFS0Header xci.FileSystem = HFS0Root.Load(path, fs); return(xci); } }
public static void Extract(Stream inFileStream, string outDir, bool verify, Keyset keyset, Output Out, bool isDecryptedNca = false) { using (var file = new StreamStorage(inFileStream, false)) { var nca = new Nca(keyset, file, false, isDecryptedNca); Out.Log(nca.Print()); if (verify) { Out.Log($"ValidateMasterHashes...\r\n"); nca.ValidateMasterHashes(); } for (var i = 0; i < 3; ++i) { if (nca.Sections[i] != null) { if (verify) { nca.VerifySection(i, Out); } nca.ExtractSection(i, Path.Combine(outDir, i.ToString()), IntegrityCheckLevel.None, Out); } } } }
public void UntrimAndEncrypt(Keyset keyset) { FolderTools.ExtractTitlekeys(decryptedDir, keyset, Out); var decryptedFs = new LocalFileSystem(decryptedDir); var encryptedFs = new LocalFileSystem(encryptedDir); EncryptNCA.Encrypt(decryptedFs, encryptedFs, VerifyHashes, keyset, Out); var dirDecrypted = new DirectoryInfo(decryptedDir); foreach (var file in decryptedFs.EnumerateEntries() .Where(item => item.Type == DirectoryEntryType.File && !item.Name.EndsWith(".tca"))) { if (!file.Name.EndsWith(".nca")) { using (var srcFile = decryptedFs.OpenFile(file.FullPath, OpenMode.Read)) using (var destFile = FolderTools.CreateAndOpen(file, encryptedFs, file.Name, file.Size)) { srcFile.CopyTo(destFile); } } decryptedFs.DeleteFile(file.FullPath); } UntrimDeltaNCA.Process(decryptedDir, encryptedFs, keyset, Out); EncryptNCA.Encrypt(decryptedFs, encryptedFs, VerifyHashes, keyset, Out); }
public static Keyset GetKeyset(KeysetName kn) { Keyset ks = new Keyset(); if (kn.Equals(KeysetName.Arrows)) { ks.LEFT = KeyCode.LeftArrow; ks.RIGHT = KeyCode.RightArrow; ks.UP = KeyCode.UpArrow; ks.DOWN = KeyCode.DownArrow; ks.JUMP = KeyCode.Space; ks.ATTACK = KeyCode.M; } else if (kn.Equals(KeysetName.WASD)) { ks.LEFT = KeyCode.A; ks.RIGHT = KeyCode.D; ks.UP = KeyCode.W; ks.DOWN = KeyCode.S; ks.JUMP = KeyCode.R; ks.ATTACK = KeyCode.E; } return(ks); }
public NcaWrapper(Keyset keyset, string ncaPath, string updateNcaPath = null) { // Open the FileStream fileStream = File.OpenRead(ncaPath); // Create the Nca instance baseNca = new Nca(keyset, fileStream.AsStorage(), true); // Open the update NCA if it exists if (updateNcaPath != null) { // Open the FileStream updateFileStream = File.OpenRead(updateNcaPath); // Create the update Nca instance updateNca = new Nca(keyset, updateFileStream.AsStorage(), true); // Set the baseNca updateNca.SetBaseNca(baseNca); } // Open the exefs Exefs = new PartitionFileSystem(nca.OpenSection(ProgramPartitionType.Code, false, IntegrityCheckLevel.ErrorOnInvalid, false)); // Open the romfs Romfs = new RomFsFileSystem(nca.OpenSection(ProgramPartitionType.Data, false, IntegrityCheckLevel.ErrorOnInvalid, false)); }
// Start is called before the first frame update void Start() { inMiddleOfAttack = false; inMiddleOfJump = false; rb = GetComponent <Rigidbody>(); ks = Controls.GetKeyset(controls); if (rotationAxis.Equals(axis.x)) { rotationVector = Vector3.right; } else if (rotationAxis.Equals(axis.y)) { rotationVector = Vector3.up; } else if (rotationAxis.Equals(axis.z)) { rotationVector = Vector3.forward; } rb.mass = mass; //deltaRotation = Quaternion.Euler(rotationVector * angularVelocity * Time.deltaTime); /* No amount of angular velocity could generate enough force to keep the blade stable while spinning. * So used this to keep the blade stable. */ rb.freezeRotation = true; Physics.gravity = Vector3.down * jumpGravity; initRotation = transform.rotation; dashAbility = new DashAbility(); dashAbility.dashState = DashState.Ready; tilt = new Tilt(initRotation.eulerAngles.x, maxTilt); //Rotating the blade every frame to keep it spinning. bladeSpin = Quaternion.Euler(Vector3.forward * angularVelocity * Time.deltaTime); }
private static SwitchFs OpenSdCard(string path, IProgressReport logger = null) { SwitchFs switchFs; Keyset keyset = OpenKeyset(); var baseFs = new LocalFileSystem(path); if (Directory.Exists(Path.Combine(path, "Nintendo", "Contents", "registered"))) { logger?.LogMessage("Treating path as SD card storage"); switchFs = SwitchFs.OpenSdCard(keyset, baseFs); } else if (Directory.Exists(Path.Combine(path, "Contents", "registered"))) { logger?.LogMessage("Treating path as NAND storage"); switchFs = SwitchFs.OpenNandPartition(keyset, baseFs); } else { logger?.LogMessage("Treating path as a directory of loose NCAs"); switchFs = SwitchFs.OpenNcaDirectory(keyset, baseFs); } return(switchFs); }
public static InstallerUnpacker Load(Keyset keyset, string file, bool saveHeaderToc = false) { if (keyset.Key.Data is null || keyset.Key.Data.Length < 4) { return(null); } Span <byte> header = stackalloc byte[0x10]; using (var fs = new FileStream(file, FileMode.Open)) fs.Read(header); keyset.CryptData(header, DefaultSeed); SpanReader sr = new SpanReader(header, Endian.Big); if (sr.ReadStringRaw(4) != Magic) { return(null); } Program.Log($"[:] Successfully decrypted installer header with keyset: {keyset.GameCode} - {keyset.Magic}"); uint tocSize = sr.ReadUInt32(); ulong fileCount = sr.ReadUInt64(); Program.Log($"[:] TOC Size: {tocSize}"); Program.Log($"[:] File Count: {fileCount}.."); InstallerUnpacker unpacker = new InstallerUnpacker(keyset, file); unpacker.LoadToC(tocSize, (uint)fileCount); return(unpacker); }
public Savefile(Keyset keyset, Stream file, IntegrityCheckLevel integrityCheckLevel) { SavefileSource = new SharedStreamSource(file); Header = new Header(keyset, SavefileSource); FsLayout layout = Header.Layout; DataRemapStorage = new RemapStorage(SavefileSource.CreateStream(layout.FileMapDataOffset, layout.FileMapDataSize), Header.FileRemap, Header.FileMapEntries); DuplexData = InitDuplexStream(DataRemapStorage, Header); MetaRemapStorage = new RemapStorage(DuplexData, Header.MetaRemap, Header.MetaMapEntries); Stream journalTable = MetaRemapStorage.OpenStream(layout.JournalTableOffset, layout.JournalTableSize); MappingEntry[] journalMap = JournalStream.ReadMappingEntries(journalTable, Header.Journal.MainDataBlockCount); Stream journalData = DataRemapStorage.OpenStream(layout.JournalDataOffset, layout.JournalDataSizeB + layout.SizeReservedArea); var journalStream = new JournalStream(journalData, journalMap, (int)Header.Journal.BlockSize); JournalStreamSource = new SharedStreamSource(journalStream); IvfcStream = InitIvfcStream(integrityCheckLevel); SaveFs = new SaveFs(IvfcStream, MetaRemapStorage.OpenStream(layout.FatOffset, layout.FatSize), Header.Save); IvfcStreamSource = new SharedStreamSource(IvfcStream); }
public void LoadXCI() { Keyset keyset = Keyset.Load("keys.txt"); XCI xci = XCI.Load(XCI_PATH, keyset); Assert.IsNotNull(xci); }
public static List <Ticket> DumpTickets(Keyset keyset, IStorage savefile, string consoleName) { var tickets = new List <Ticket>(); var save = new SaveDataFileSystem(keyset, savefile, IntegrityCheckLevel.ErrorOnInvalid, false); var ticketList = new BinaryReader(save.OpenFile("/ticket_list.bin", OpenMode.Read).AsStream()); var ticketFile = new BinaryReader(save.OpenFile("/ticket.bin", OpenMode.Read).AsStream()); DirectoryInfo ticketFolder = HACGUIKeyset.GetTicketsDirectory(consoleName); ticketFolder.Create(); var titleId = ticketList.ReadUInt64(); while (titleId != ulong.MaxValue) { ticketList.BaseStream.Position += 0x18; var start = ticketFile.BaseStream.Position; Ticket ticket = new Ticket(ticketFile); Stream ticketFileStream = ticketFolder.GetFile(BitConverter.ToString(ticket.RightsId).Replace("-", "").ToLower() + ".tik").Create(); byte[] data = ticket.GetBytes(); ticketFileStream.Write(data, 0, data.Length); ticketFileStream.Close(); tickets.Add(ticket); ticketFile.BaseStream.Position = start + 0x400; titleId = ticketList.ReadUInt64(); } return(tickets); }
/// <summary> /// Decrypts and decompress a file in a segmented stream and saves it to the provided path. /// </summary> /// <param name="keyset"></param> /// <param name="fs"></param> /// <param name="seed"></param> /// <param name="outPath"></param> public unsafe static void DecryptAndInflateToFile(Keyset keyset, FileStream fs, uint seed, uint uncompressedSize, string outPath, bool closeStream = true) { // Our new file using (var newFileStream = new FileStream(outPath, FileMode.Create)) { var decryptStream = new CryptoStream(fs, new VolumeCryptoTransform(keyset, seed), CryptoStreamMode.Read); decryptStream.Read(_tmpBuff, 0, 8); // Compress Ignore header var ds = new DeflateStream(decryptStream, CompressionMode.Decompress); int bytesLeft = (int)uncompressedSize; int read; const int bufSize = 81_920; byte[] buffer = ArrayPool <byte> .Shared.Rent(bufSize); int currentPos = 0; while (bytesLeft > 0 && (read = ds.Read(buffer, 0, Math.Min(buffer.Length, bytesLeft))) > 0) { newFileStream.Write(buffer, 0, read); bytesLeft -= read; } ArrayPool <byte> .Shared.Return(buffer); } if (closeStream) { fs.Dispose(); } }
public static void File2Tickets(string inFile, string outDirPath, Keyset keyset, Output Out) { var inFileExtension = Path.GetExtension(inFile).ToLower(); using (var inputFile = new FileStream(inFile, FileMode.Open, FileAccess.Read)) { switch (inFileExtension) { case ".nsp": var pfs = new PartitionFileSystem(inputFile.AsStorage()); ProcessNsp.ExtractTickets(pfs, outDirPath, keyset, Out); break; case ".xci": var xci = new Xci(keyset, inputFile.AsStorage()); ProcessXci.ExtractTickets(xci, outDirPath, keyset, Out); break; case ".nspz": case ".xciz": var pfsz = new PartitionFileSystem(inputFile.AsStorage()); DecompressFs.ExtractTickets(pfsz, outDirPath, keyset, Out); break; default: throw new NotImplementedException(); } } }
Script GetExecutedScript(string scriptTemplate, Script prevScript, Dictionary <string, Keyset> sets) { StringBuilder executedScript = new StringBuilder(); int lastToCopy = 0; foreach (Match match in Regex.Matches(scriptTemplate, "<([^\\.]*?)\\.([^.]*?)>")) { var name = match.Groups[1].Value; Keyset keyset; if (!sets.TryGetValue(name.ToLowerInvariant(), out keyset)) { keyset = new Keyset(name); sets.Add(name.ToLowerInvariant(), keyset); } var element = match.Groups[2].Value; var replacement = keyset.GetValue(element, prevScript); if (replacement == null) { throw new Exception("Element " + element + " unrecognized, possible values are pubkey, pubkeyhash ,key, signature"); } var before = scriptTemplate.Substring(lastToCopy, match.Index - lastToCopy); executedScript.Append(before); executedScript.Append(replacement); lastToCopy = match.Index + match.Length; } executedScript.Append(scriptTemplate.Substring(lastToCopy, scriptTemplate.Length - lastToCopy)); return(new Script(executedScript.ToString())); }
public Result Commit(Keyset keyset) { CoreDataIvfcStorage.Flush(); FatIvfcStorage?.Flush(); Stream headerStream = BaseStorage.AsStream(); var hashData = new byte[0x3d00]; headerStream.Position = 0x300; headerStream.Read(hashData, 0, hashData.Length); byte[] hash = Crypto.ComputeSha256(hashData, 0, hashData.Length); headerStream.Position = 0x108; headerStream.Write(hash, 0, hash.Length); if (keyset == null || keyset.SaveMacKey.IsEmpty()) { return(ResultFs.PreconditionViolation); } var cmacData = new byte[0x200]; var cmac = new byte[0x10]; headerStream.Position = 0x100; headerStream.Read(cmacData, 0, 0x200); Crypto.CalculateAesCmac(keyset.SaveMacKey, cmacData, 0, cmac, 0, 0x200); headerStream.Position = 0; headerStream.Write(cmac, 0, 0x10); headerStream.Flush(); return(Result.Success); }
public bool CommitHeader(Keyset keyset) { // todo Stream headerStream = BaseStorage.AsStream(); var hashData = new byte[0x3d00]; headerStream.Position = 0x300; headerStream.Read(hashData, 0, hashData.Length); byte[] hash = Crypto.ComputeSha256(hashData, 0, hashData.Length); headerStream.Position = 0x108; headerStream.Write(hash, 0, hash.Length); if (keyset.SaveMacKey.IsEmpty()) { return(false); } var cmacData = new byte[0x200]; var cmac = new byte[0x10]; headerStream.Position = 0x100; headerStream.Read(cmacData, 0, 0x200); Crypto.CalculateAesCmac(keyset.SaveMacKey, cmacData, 0, cmac, 0, 0x200); headerStream.Position = 0; headerStream.Write(cmac, 0, 0x10); headerStream.Flush(); return(true); }
public static void Listnca(string sdfs, string fwint, Keyset keyset, JsonWriter writer) { SwitchFs switchFs; LocalFileSystem baseFs = new LocalFileSystem(sdfs); switchFs = SwitchFs.OpenNcaDirectory(keyset, baseFs); string lasttitleid = ""; string lastncaid = ""; string type; foreach (SwitchFsNca nca in switchFs.Ncas.Values.OrderBy(x => x.Nca.Header.TitleId)) { if (nca.Nca.Header.TitleId.ToString("X16") != lasttitleid) { writer.WritePropertyName(nca.Nca.Header.TitleId.ToString("X16")); writer.WriteStartObject(); writer.WritePropertyName(nca.Nca.Header.ContentType.ToString()); writer.WriteValue(nca.NcaId); // solo contiene META if (int.Parse(fwint) >= 738197944) { if ("0100000000000825" == nca.Nca.Header.TitleId.ToString("X16") || "0100000000000029" == nca.Nca.Header.TitleId.ToString("X16") || "0100000000000816" == nca.Nca.Header.TitleId.ToString("X16")) { writer.WriteEnd(); } } else if ("010000000000001B" == nca.Nca.Header.TitleId.ToString("X16") || "0100000000000029" == nca.Nca.Header.TitleId.ToString("X16") || "0100000000000816" == nca.Nca.Header.TitleId.ToString("X16")) { writer.WriteEnd(); } lastncaid = nca.NcaId; lasttitleid = nca.Nca.Header.TitleId.ToString("X16"); } if (lastncaid != nca.NcaId && lasttitleid == nca.Nca.Header.TitleId.ToString()) { if (nca.Nca.Header.ContentType.ToString() == "Data" || nca.Nca.Header.ContentType.ToString() == "PublicData") { type = "Program"; } else { type = nca.Nca.Header.ContentType.ToString(); } writer.WritePropertyName(type); writer.WriteValue(nca.NcaId); writer.WriteEnd(); lastncaid = nca.NcaId; lasttitleid = nca.Nca.Header.TitleId.ToString("X16"); } else if (lastncaid != nca.NcaId && lasttitleid != nca.Nca.Header.TitleId.ToString()) { writer.WritePropertyName(nca.Nca.Header.ContentType.ToString()); writer.WriteValue(nca.NcaId); writer.WriteEnd(); lastncaid = nca.NcaId; lasttitleid = nca.Nca.Header.TitleId.ToString("X16"); } } }
public static void Initialize() { // Get the KeysetConfig KeysetConfig keysetConfig = Configuration.LoadedConfiguration.KeysetConfig; Keyset = ExternalKeys.ReadKeyFile(keysetConfig.ProductionKeys, keysetConfig.TitleKeys); }
private Validity ValidateSignature(Keyset keyset) { Span <byte> calculatedCmac = stackalloc byte[0x10]; Aes.CalculateCmac(calculatedCmac, Data.AsSpan(0x100, 0x200), keyset.SaveMacKey); return(CryptoUtil.IsSameBytes(calculatedCmac, Cmac, Aes.BlockSize) ? Validity.Valid : Validity.Invalid); }
private Validity ValidateSignature(Keyset keyset) { var calculatedCmac = new byte[0x10]; Crypto.CalculateAesCmac(keyset.SaveMacKey, Data, 0x100, calculatedCmac, 0, 0x200); return(Util.ArraysEqual(calculatedCmac, Cmac) ? Validity.Valid : Validity.Invalid); }
public NcaHeader(Keyset keyset, IStorage headerStorage) { (byte[] header, bool isEncrypted) = DecryptHeader(keyset, headerStorage); _header = header; IsEncrypted = isEncrypted; FormatVersion = DetectNcaVersion(_header.Span); }
public Header(Keyset keyset, BinaryReader reader) { reader.BaseStream.Position = 0; Data = reader.ReadBytes(0x4000); reader.BaseStream.Position = 0; Cmac = reader.ReadBytes(0x10); reader.BaseStream.Position = 0x100; Layout = new FsLayout(reader); reader.BaseStream.Position = 0x300; Duplex = new DuplexHeader(reader); reader.BaseStream.Position = 0x344; Ivfc = new IvfcHeader(reader); reader.BaseStream.Position = 0x408; Journal = new JournalHeader(reader); reader.BaseStream.Position = 0x608; Save = new SaveHeader(reader); reader.BaseStream.Position = 0x650; FileRemap = new RemapHeader(reader); reader.BaseStream.Position = 0x690; MetaRemap = new RemapHeader(reader); reader.BaseStream.Position = 0x6D8; ExtraData = new ExtraData(reader); reader.BaseStream.Position = Layout.IvfcMasterHashOffsetA; MasterHashA = reader.ReadBytes((int)Layout.IvfcMasterHashSize); reader.BaseStream.Position = Layout.IvfcMasterHashOffsetB; MasterHashB = reader.ReadBytes((int)Layout.IvfcMasterHashSize); reader.BaseStream.Position = Layout.DuplexMasterOffsetA; DuplexMasterA = reader.ReadBytes((int)Layout.DuplexMasterSize); reader.BaseStream.Position = Layout.DuplexMasterOffsetB; DuplexMasterB = reader.ReadBytes((int)Layout.DuplexMasterSize); reader.BaseStream.Position = Layout.FileMapEntryOffset; FileMapEntries = new MapEntry[FileRemap.MapEntryCount]; for (int i = 0; i < FileRemap.MapEntryCount; i++) { FileMapEntries[i] = new MapEntry(reader); } reader.BaseStream.Position = Layout.MetaMapEntryOffset; MetaMapEntries = new MapEntry[MetaRemap.MapEntryCount]; for (int i = 0; i < MetaRemap.MapEntryCount; i++) { MetaMapEntries[i] = new MapEntry(reader); } HeaderHashValidity = Crypto.CheckMemoryHashTable(Data, Layout.Hash, 0x300, 0x3d00); SignatureValidity = ValidateSignature(keyset); }
public Header(IStorage storage, Keyset keyset) { MainStorage = storage; MainHeader = MainStorage.Slice(0x100, 0x200); DuplexHeader = MainStorage.Slice(0x300, 0x44); DataIvfcHeader = MainStorage.Slice(0x344, 0xC0); JournalHeader = MainStorage.Slice(0x408, 0x200); SaveHeader = MainStorage.Slice(0x608, 0x48); MainRemapHeader = MainStorage.Slice(0x650, 0x40); MetaDataRemapHeader = MainStorage.Slice(0x690, 0x40); ExtraDataStorage = MainStorage.Slice(0x6D8, 0x400); FatIvfcHeader = MainStorage.Slice(0xAD8, 0xC0); Layout = new FsLayout(MainHeader); DuplexMasterBitmapA = MainStorage.Slice(Layout.DuplexMasterOffsetA, Layout.DuplexMasterSize); DuplexMasterBitmapB = MainStorage.Slice(Layout.DuplexMasterOffsetB, Layout.DuplexMasterSize); DataIvfcMaster = MainStorage.Slice(Layout.IvfcMasterHashOffsetA, Layout.IvfcMasterHashSize); FatIvfcMaster = MainStorage.Slice(Layout.FatIvfcMasterHashA, Layout.IvfcMasterHashSize); var reader = new BinaryReader(storage.AsStream()); reader.BaseStream.Position = 0; Data = reader.ReadBytes(0x4000); reader.BaseStream.Position = 0; Cmac = reader.ReadBytes(0x10); reader.BaseStream.Position = 0x100; reader.BaseStream.Position = 0x300; Duplex = new DuplexHeader(reader); reader.BaseStream.Position = 0x6D8; ExtraData = new ExtraData(reader); Ivfc = new IvfcHeader(DataIvfcHeader) { NumLevels = 5 }; if (Layout.Version >= 0x50000) { FatIvfc = new IvfcHeader(FatIvfcHeader) { NumLevels = 4 }; } MasterHash = storage.Slice(Layout.IvfcMasterHashOffsetA, Layout.IvfcMasterHashSize); Span <byte> actualHeaderHash = stackalloc byte[Sha256.DigestSize]; Sha256.GenerateSha256Hash(Data.AsSpan(0x300, 0x3d00), actualHeaderHash); HeaderHashValidity = Utilities.SpansEqual(Layout.Hash, actualHeaderHash) ? Validity.Valid : Validity.Invalid; SignatureValidity = ValidateSignature(keyset); }