public bool CommitHeader(Keyset keyset) { SharedStream headerStream = SavefileSource.CreateStream(); 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 Stream OpenIni1() { int offset = 0x200 + Header.SectionSizes[0]; SharedStream encStream = StreamSource.CreateStream(offset, Header.SectionSizes[1]); return(new RandomAccessSectorStream(new Aes128CtrStream(encStream, Key, Header.SectionCounters[1]))); }
private void SaveToFileInner() { ApiCallSource.AssertAccess(Permissions, Access.Write); long pos = SharedStream.Stream.Position; SharedStream.Seek(0); File.WriteAllBytes(SourcePath, SharedStream.ReadToEnd()); SharedStream.Seek(pos); }
internal void SaveToFileInner() { ApiCallSource.AssertAccess(Permissions, Access.Write); var pos = SharedStream.Stream.Position; SharedStream.Seek(0); File.WriteAllText(SourcePath, SharedStream.ReadToEnd()); SharedStream.Seek(pos); }
public Stream OpenHeaderPart2() { SharedStream encStream = StreamSource.CreateStream(0x110, 0xF0); // The counter starts counting at 0x100, but the block at 0x100 isn't encrypted. // Increase the counter by one and start decrypting at 0x110. var counter = new byte[0x10]; Array.Copy(Header.Counter, counter, 0x10); Util.IncrementByteArray(counter); return(new RandomAccessSectorStream(new Aes128CtrStream(encStream, Key, counter))); }
internal void SerializeInner <TObject>(TObject obj, WriteMode writeMode = WriteMode.Overwrite) { ApiCallSource.AssertAccess(Permissions, Access.Write); if (writeMode == WriteMode.Overwrite) { SharedStream.Seek(0); SharedStream.SetLength(0); } else { SharedStream.Seek(0, SeekOrigin.End); } SharedStream.WriteLine(JsonConvert.SerializeObject(obj, Formatting.Indented)); }
internal void SerializeInner <TObject>(TObject obj, WriteMode writeMode = WriteMode.Overwrite) { ApiCallSource.AssertAccess(Permissions, Access.Write); if (writeMode == WriteMode.Overwrite) { SharedStream.Seek(0); SharedStream.SetLength(0); } else { SharedStream.Seek(0, SeekOrigin.End); } using (var writer = new StringWriter()) { new XmlSerializer(typeof(TObject)).Serialize(writer, obj); SharedStream.WriteLine(writer.ToString()); } }
public Package2(Keyset keyset, Stream stream) { StreamSource = new SharedStreamSource(stream); SharedStream headerStream = StreamSource.CreateStream(0, 0x200); KeyRevision = FindKeyGeneration(keyset, headerStream); Key = keyset.Package2Keys[KeyRevision]; Header = new Package2Header(headerStream, Key); PackageSize = BitConverter.ToInt32(Header.Counter, 0) ^ BitConverter.ToInt32(Header.Counter, 8) ^ BitConverter.ToInt32(Header.Counter, 12); HeaderVersion = Header.Counter[4] ^ Header.Counter[6] ^ Header.Counter[7]; if (PackageSize != 0x200 + Header.SectionSizes[0] + Header.SectionSizes[1] + Header.SectionSizes[2]) { throw new InvalidDataException("Package2 Header is corrupt!"); } }
internal TObject DeserializeInner <TObject>(long offset = long.MaxValue, SeekOrigin loc = SeekOrigin.Begin, bool retainPosition = true) { ApiCallSource.AssertAccess(Permissions, Access.Read); long?returnPosition = null; if (offset != long.MaxValue) { if (retainPosition) { returnPosition = SharedStream.Stream.Position; } SharedStream.Seek(offset, loc); } TObject obj = (TObject) new XmlSerializer(typeof(TObject)).Deserialize(new StreamReader(SharedStream.Stream)); if (returnPosition != null) { SharedStream.Seek(returnPosition.Value); } return(obj); }
public bool SignHeader(Keyset keyset) { if (keyset.SaveMacKey.IsEmpty()) { return(false); } var data = new byte[0x200]; var cmac = new byte[0x10]; SharedStream headerStream = SavefileSource.CreateStream(); headerStream.Position = 0x100; headerStream.Read(data, 0, 0x200); Crypto.CalculateAesCmac(keyset.SaveMacKey, data, 0, cmac, 0, 0x200); headerStream.Position = 0; headerStream.Write(cmac, 0, 0x10); return(true); }
internal TObject DeserializeInner <TObject>(long offset = long.MaxValue, SeekOrigin loc = SeekOrigin.Begin, bool retainPosition = true) { ApiCallSource.AssertAccess(Permissions, Access.Read); long?returnPosition = null; if (offset != long.MaxValue) { if (retainPosition) { returnPosition = SharedStream.Stream.Position; } SharedStream.Seek(offset, loc); } var obj = JsonConvert.DeserializeObject <TObject>(SharedStream.ReadToEnd()); if (returnPosition != null) { SharedStream.Seek(returnPosition.Value); } return(obj); }
public Savefile(Keyset keyset, Stream file, bool enableIntegrityChecks) { SavefileSource = new SharedStreamSource(file); using (var reader = new BinaryReader(SavefileSource.CreateStream(), Encoding.Default, true)) { Header = new Header(keyset, reader); FsLayout layout = Header.Layout; FileRemap = new RemapStream( SavefileSource.CreateStream(layout.FileMapDataOffset, layout.FileMapDataSize), Header.FileMapEntries, Header.FileRemap.MapSegmentCount); FileRemapSource = new SharedStreamSource(FileRemap); var duplexLayers = new DuplexFsLayerInfo[3]; duplexLayers[0] = new DuplexFsLayerInfo { DataA = new MemoryStream(Header.DuplexMasterA), DataB = new MemoryStream(Header.DuplexMasterB), Info = Header.Duplex.Layers[0] }; duplexLayers[1] = new DuplexFsLayerInfo { DataA = FileRemapSource.CreateStream(layout.DuplexL1OffsetA, layout.DuplexL1Size), DataB = FileRemapSource.CreateStream(layout.DuplexL1OffsetB, layout.DuplexL1Size), Info = Header.Duplex.Layers[1] }; duplexLayers[2] = new DuplexFsLayerInfo { DataA = FileRemapSource.CreateStream(layout.DuplexDataOffsetA, layout.DuplexDataSize), DataB = FileRemapSource.CreateStream(layout.DuplexDataOffsetB, layout.DuplexDataSize), Info = Header.Duplex.Layers[2] }; DuplexL1A = FileRemapSource.CreateStream(layout.DuplexL1OffsetA, layout.DuplexL1Size); DuplexL1B = FileRemapSource.CreateStream(layout.DuplexL1OffsetB, layout.DuplexL1Size); DuplexDataA = FileRemapSource.CreateStream(layout.DuplexDataOffsetA, layout.DuplexDataSize); DuplexDataB = FileRemapSource.CreateStream(layout.DuplexDataOffsetB, layout.DuplexDataSize); JournalData = FileRemapSource.CreateStream(layout.JournalDataOffset, layout.JournalDataSizeB + layout.SizeReservedArea); DuplexData = new LayeredDuplexFs(duplexLayers, Header.Layout.DuplexIndex == 1); MetaRemap = new RemapStream(DuplexData, Header.MetaMapEntries, Header.MetaRemap.MapSegmentCount); MetaRemapSource = new SharedStreamSource(MetaRemap); JournalTable = MetaRemapSource.CreateStream(layout.JournalTableOffset, layout.JournalTableSize); JournalBitmapUpdatedPhysical = MetaRemapSource.CreateStream(layout.JournalBitmapUpdatedPhysicalOffset, layout.JournalBitmapUpdatedPhysicalSize); JournalBitmapUpdatedVirtual = MetaRemapSource.CreateStream(layout.JournalBitmapUpdatedVirtualOffset, layout.JournalBitmapUpdatedVirtualSize); JournalBitmapUnassigned = MetaRemapSource.CreateStream(layout.JournalBitmapUnassignedOffset, layout.JournalBitmapUnassignedSize); JournalLayer1Hash = MetaRemapSource.CreateStream(layout.IvfcL1Offset, layout.IvfcL1Size); JournalLayer2Hash = MetaRemapSource.CreateStream(layout.IvfcL2Offset, layout.IvfcL2Size); JournalLayer3Hash = MetaRemapSource.CreateStream(layout.IvfcL3Offset, layout.IvfcL3Size); JournalFat = MetaRemapSource.CreateStream(layout.FatOffset, layout.FatSize); AllocationTable = new AllocationTable(JournalFat); MappingEntry[] journalMap = JournalStream.ReadMappingEntries(JournalTable, Header.Journal.MainDataBlockCount); SharedStream journalData = FileRemapSource.CreateStream(layout.JournalDataOffset, layout.JournalDataSizeB + layout.SizeReservedArea); JournalStream = new JournalStream(journalData, journalMap, (int)Header.Journal.BlockSize); JournalStreamSource = new SharedStreamSource(JournalStream); IvfcStream = InitIvfcStream(enableIntegrityChecks); IvfcStreamSource = new SharedStreamSource(IvfcStream); ReadFileInfo(); var dictionary = new Dictionary <string, FileEntry>(); foreach (FileEntry entry in Files) { dictionary[entry.FullPath] = entry; } FileDict = dictionary; } }
internal byte[]? ReadToEndInner() { ApiCallSource.AssertAccess(Permissions, Access.Read); return(SharedStream?.ReadToEnd()); }