public NcaFsHeader(BinaryReader reader) { long start = reader.BaseStream.Position; Version = reader.ReadInt16(); FormatType = (NcaFormatType)reader.ReadByte(); HashType = (NcaHashType)reader.ReadByte(); EncryptionType = (NcaEncryptionType)reader.ReadByte(); reader.BaseStream.Position += 3; switch (HashType) { case NcaHashType.Sha256: Sha256Info = new Sha256Info(reader); break; case NcaHashType.Ivfc: IvfcInfo = new IvfcHeader(reader); break; } if (EncryptionType == NcaEncryptionType.AesCtrEx) { BktrInfo = new BktrPatchInfo(); reader.BaseStream.Position = start + 0x100; BktrInfo.RelocationHeader = new BktrHeader(reader); BktrInfo.EncryptionHeader = new BktrHeader(reader); } if (FormatType == NcaFormatType.Pfs0) { Type = SectionType.Pfs0; } else if (FormatType == NcaFormatType.Romfs) { if (EncryptionType == NcaEncryptionType.AesCtrEx) { Type = SectionType.Bktr; } else { Type = SectionType.Romfs; } } reader.BaseStream.Position = start + 0x140; Ctr = reader.ReadBytes(8).Reverse().ToArray(); reader.BaseStream.Position = start + 512; }
public BktrCryptoStream(Stream baseStream, byte[] key, long offset, long length, long counterOffset, byte[] ctrHi, BktrPatchInfo bktr) : base(baseStream, key, offset, length, counterOffset, ctrHi) { BktrHeader header = bktr.EncryptionHeader; byte[] subsectionBytes; using (var streamDec = new RandomAccessSectorStream(new Aes128CtrStream(baseStream, key, offset, length, counterOffset, ctrHi))) { streamDec.Position = header.Offset; subsectionBytes = new byte[header.Size]; streamDec.Read(subsectionBytes, 0, subsectionBytes.Length); } using (var reader = new BinaryReader(new MemoryStream(subsectionBytes))) { AesSubsectionBlock = new AesSubsectionBlock(reader); } foreach (AesSubsectionBucket bucket in AesSubsectionBlock.Buckets) { SubsectionEntries.AddRange(bucket.Entries); } // Add a subsection for the BKTR headers to make things easier var headerSubsection = new AesSubsectionEntry { Offset = bktr.RelocationHeader.Offset, Counter = (uint)(ctrHi[4] << 24 | ctrHi[5] << 16 | ctrHi[6] << 8 | ctrHi[7]), OffsetEnd = long.MaxValue }; SubsectionEntries.Add(headerSubsection); for (int i = 0; i < SubsectionEntries.Count - 1; i++) { SubsectionEntries[i].Next = SubsectionEntries[i + 1]; SubsectionEntries[i].OffsetEnd = SubsectionEntries[i + 1].Offset; } SubsectionOffsets = SubsectionEntries.Select(x => x.Offset).ToList(); CurrentEntry = GetSubsectionEntry(0); UpdateCounterSubsection(CurrentEntry.Counter); baseStream.Position = offset; }