/// <summary> /// Writes the PFS image to the given stream /// </summary> public void WriteImage(Stream stream) { WriteData(stream); if (hdr.Mode.HasFlag(PfsMode.Signed)) { Log("Signing..."); var signKey = Crypto.PfsGenSignKey(properties.EKPFS, hdr.Seed); foreach (var sig in data_sigs.Concat(final_sigs)) { var sig_buffer = new byte[sig.Size]; stream.Position = sig.Block * properties.BlockSize; stream.Read(sig_buffer, 0, sig.Size); stream.Position = sig.SigOffset; stream.Write(Crypto.HmacSha256(signKey, sig_buffer), 0, 32); stream.WriteLE((int)sig.Block); } } if (hdr.Mode.HasFlag(PfsMode.Encrypted)) { Log("Encrypting..."); var(tweakKey, dataKey) = Crypto.PfsGenEncKey(properties.EKPFS, hdr.Seed); var transformer = new XtsBlockTransform(dataKey, tweakKey); byte[] sectorBuffer = new byte[xtsSectorSize]; foreach (var xtsSector in XtsSectorGen()) { stream.Position = xtsSector * xtsSectorSize; stream.Read(sectorBuffer, 0, xtsSectorSize); transformer.EncryptSector(sectorBuffer, (ulong)xtsSector); stream.Position = xtsSector * xtsSectorSize; stream.Write(sectorBuffer, 0, xtsSectorSize); } } }
public void TestRoundTrip() { byte[] dataKey = new byte[16]; byte[] tweakKey = new byte[16]; var transformer = new XtsBlockTransform(dataKey, tweakKey); byte[] data = new byte[] { 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, }; byte[] expected = data.ToArray(); transformer.EncryptSector(data, 0); CollectionAssert.AreNotEqual(expected, data); transformer.DecryptSector(data, 0); CollectionAssert.AreEqual(expected, data); transformer.EncryptSector(data, 1); CollectionAssert.AreNotEqual(expected, data); transformer.DecryptSector(data, 1); CollectionAssert.AreEqual(expected, data); }
public void WriteImage(Stream stream) { Log("Writing header..."); hdr.WriteToStream(stream); Log("Writing inodes..."); WriteInodes(stream); Log("Writing superroot dirents"); WriteSuperrootDirents(stream); var fpt_file = new FSFile(s => fpt.WriteToStream(s), "flat_path_table", fpt.Size); fpt_file.ino = fpt_ino; allNodes.Insert(0, fpt_file); Log("Writing data blocks..."); for (var x = 0; x < allNodes.Count; x++) { var f = allNodes[x]; stream.Position = f.ino.StartBlock * hdr.BlockSize; WriteFSNode(stream, f); } stream.SetLength(hdr.Ndblock * hdr.BlockSize); if (hdr.Mode.HasFlag(PfsMode.Signed)) { Log("Signing..."); var signKey = Crypto.PfsGenSignKey(properties.EKPFS, hdr.Seed); foreach (var sig in sig_order) { var sig_buffer = new byte[sig.Size]; stream.Position = sig.Block * properties.BlockSize; stream.Read(sig_buffer, 0, sig.Size); stream.Position = sig.SigOffset; stream.Write(Crypto.HmacSha256(signKey, sig_buffer), 0, 32); stream.WriteLE((int)sig.Block); } } if (hdr.Mode.HasFlag(PfsMode.Encrypted)) { Log("Encrypting..."); var encKey = Crypto.PfsGenEncKey(properties.EKPFS, hdr.Seed); var dataKey = new byte[16]; var tweakKey = new byte[16]; Buffer.BlockCopy(encKey, 0, tweakKey, 0, 16); Buffer.BlockCopy(encKey, 16, dataKey, 0, 16); stream.Position = hdr.BlockSize; var transformer = new XtsBlockTransform(dataKey, tweakKey); const int sectorSize = 0x1000; long xtsSector = 16; long totalSectors = (stream.Length + 0xFFF) / sectorSize; byte[] sectorBuffer = new byte[sectorSize]; while (xtsSector < totalSectors) { if (xtsSector / 0x10 == emptyBlock) { xtsSector += 16; } stream.Position = xtsSector * sectorSize; stream.Read(sectorBuffer, 0, sectorSize); transformer.EncryptSector(sectorBuffer, (ulong)xtsSector); stream.Position = xtsSector * sectorSize; stream.Write(sectorBuffer, 0, sectorSize); xtsSector += 1; } } }