public NintendoContentArchiveSource(NintendoContentFileSystemInfo fileSystemInfo, KeyConfiguration config, bool needsLogoPartition = false) { this.m_fileSystemInfo = fileSystemInfo; this.m_keyConfig = config; this.SetCryptor(this.m_keyConfig); this.AddDefaultLogoPartitionIfNeeded(needsLogoPartition); fileSystemInfo.fsEntries.Sort((Comparison <NintendoContentFileSystemInfo.EntryInfo>)((x, y) => x.partitionIndex.CompareTo(y.partitionIndex))); NintendoContentFileSystemMeta meta = new NintendoContentFileSystemMeta(); NintendoContentFileSystemEntryInfoContainer fsEntries = new NintendoContentFileSystemEntryInfoContainer(fileSystemInfo.fsEntries); List <ConcatenatedSource.Element> elements1 = new List <ConcatenatedSource.Element>(); NintendoContentArchiveSource.BodySourceElement[] bodySources = new NintendoContentArchiveSource.BodySourceElement[fileSystemInfo.fsEntries.Count]; long offset = (long)meta.GetFsHeaderSize() * 4L; foreach (NintendoContentFileSystemInfo.EntryInfo entryInfo in fsEntries) { if (entryInfo.type != null) { ISource source = NintendoContentArchiveSource.GetDataSource(entryInfo); if (fileSystemInfo.isProdEncryption && fileSystemInfo.contentType == (byte)0 && entryInfo.partitionIndex == 0) { source = this.AcidResignedSource(source); } if (fileSystemInfo.contentType == (byte)0 && entryInfo.partitionIndex == 1) { source = this.NrrSignedSource(source); } int currentIndex = fsEntries.CurrentIndex; bodySources[currentIndex].DataOffset = offset; NintendoContentArchiveSource.BuildDataInfo buildInfo = new NintendoContentArchiveSource.BuildDataInfo(meta, source, offset, currentIndex); fileSystemInfo.fsEntries[currentIndex] = this.BuildData(entryInfo, buildInfo); offset = buildInfo.CurrentOffset; Sha256HierarchicalHashCalculatedSource calculatedSource = new Sha256HierarchicalHashCalculatedSource(buildInfo.HeaderSource, (int)buildInfo.HeaderSource.Size, 1); ConcatenatedSource.Element element1 = new ConcatenatedSource.Element(calculatedSource.GetMasterHashSource(), "fsHeaderHash" + (object)currentIndex, (long)(32 * currentIndex)); elements1.Add(element1); ConcatenatedSource.Element element2 = new ConcatenatedSource.Element((ISource)calculatedSource, "fsHeader" + (object)currentIndex, (long)currentIndex * (long)meta.GetFsHeaderSize()); bodySources[currentIndex].HeaderElement = element2; bodySources[currentIndex].DataSourceElements = buildInfo.DataSourceElements; } } if (fsEntries.IsReverse) { elements1.Reverse(); } NintendoContentArchiveSource.BodyEncryptionKey bodyEncryptionKey = new NintendoContentArchiveSource.BodyEncryptionKey(fileSystemInfo); this.MakeBody(meta, fsEntries, bodySources, bodyEncryptionKey); this.MakeNcaHeader(meta, (ISource) new ConcatenatedSource(elements1), bodyEncryptionKey); List <ConcatenatedSource.Element> elements2 = new List <ConcatenatedSource.Element>(); ConcatenatedSource.Element element3 = new ConcatenatedSource.Element(this.m_headerSource, "header", 0L); ConcatenatedSource.Element element4 = new ConcatenatedSource.Element(this.m_bodySource, "body", element3.Source.Size); elements2.Add(element3); elements2.Add(element4); this.m_source = (ISource) new ConcatenatedSource(elements2); this.Size = this.m_source.Size; }
private NintendoContentFileSystemInfo.EntryInfo BuildData(NintendoContentFileSystemInfo.EntryInfo entryInfo, NintendoContentArchiveSource.BuildDataInfo buildInfo) { entryInfo.hashType = NintendoContentArchiveSource.VerifyHashType(this.m_fileSystemInfo, entryInfo); entryInfo.encryptionType = NintendoContentArchiveSource.VerifyEncryptionType(this.m_fileSystemInfo, entryInfo); entryInfo.startOffset = (ulong)buildInfo.CurrentOffset + buildInfo.Meta.GetHeaderSize(); entryInfo.hashTargetSize = (ulong)buildInfo.DataSource.Size; IHierarchicalHashCalculatedSource calculatedSource; switch (entryInfo.hashType) { case 2: calculatedSource = (IHierarchicalHashCalculatedSource) new Sha256HierarchicalHashCalculatedSource(buildInfo.DataSource, buildInfo.Meta.GetHashBlockSize((ValueType)entryInfo), 2); break; case 3: calculatedSource = (IHierarchicalHashCalculatedSource) new IntegrityHierarchicalHashCalculatedSource(buildInfo.DataSource); break; default: throw new NotImplementedException(); } long offset1 = 0; ISource layerHashSource = calculatedSource.GetLayerHashSource(); entryInfo.hashDataSize = (ulong)layerHashSource.Size; ConcatenatedSource.Element element1 = new ConcatenatedSource.Element(layerHashSource, "fsHash" + (object)buildInfo.Index, offset1); buildInfo.DataSourceElements.Add(element1); long offset2 = offset1 + element1.Source.Size; int num1 = (int)(offset2 % 512L); if (0 < num1) { ConcatenatedSource.Element element2 = new ConcatenatedSource.Element((ISource) new PaddingSource((long)(512 - num1)), "fsHashPadding" + (object)buildInfo.Index, offset2); buildInfo.DataSourceElements.Add(element2); offset2 += element2.Source.Size; } entryInfo.hashTargetOffset = (ulong)offset2; ConcatenatedSource.Element element3 = new ConcatenatedSource.Element((ISource)calculatedSource, "fsData" + (object)buildInfo.Index, offset2); buildInfo.DataSourceElements.Add(element3); long offset3 = offset2 + element3.Source.Size; int num2 = (int)(offset3 % 512L); if (0 < num2) { ConcatenatedSource.Element element2 = new ConcatenatedSource.Element((ISource) new PaddingSource((long)(512 - num2)), "fsDataPadding" + (object)buildInfo.Index, offset3); buildInfo.DataSourceElements.Add(element2); offset3 += element2.Source.Size; } buildInfo.CurrentOffset += offset3; entryInfo.endOffset = (ulong)buildInfo.CurrentOffset + buildInfo.Meta.GetHeaderSize(); buildInfo.HeaderSource = calculatedSource.GetFsHeaderSource(entryInfo); return(entryInfo); }
internal NintendoContentMetaArchiveSource(NintendoContentMetaBase contentMeta, int keyEncryptionKeyIndex, KeyConfiguration config, bool isProdEncryption, bool isGameCard) { NintendoContentMetaReader contentMetaReader = new NintendoContentMetaReader(contentMeta.GetBytes()); ISource source1 = contentMeta.GetSource(); PartitionFileSystemInfo partitionFileSystemInfo = new PartitionFileSystemInfo(); partitionFileSystemInfo.version = 0; partitionFileSystemInfo.entries.Add(new PartitionFileSystemInfo.EntryInfo() { type = "source", name = contentMeta.GetEntryName(), offset = 0UL, size = (ulong)source1.Size }); PartitionFileSystemMeta partitionFileSystemMeta = new PartitionFileSystemMeta(); List <ConcatenatedSource.Element> elements = new List <ConcatenatedSource.Element>(); PartitionFileSystemInfo fileSystemInfo = partitionFileSystemInfo; byte[] buffer = partitionFileSystemMeta.Create(fileSystemInfo); ConcatenatedSource.Element element1 = new ConcatenatedSource.Element((ISource) new MemorySource(buffer, 0, buffer.Length), "meta", 0L); ConcatenatedSource.Element element2 = new ConcatenatedSource.Element(source1, "body", element1.Source.Size); elements.Add(element1); elements.Add(element2); ISource source2 = (ISource) new ConcatenatedSource(elements); this.m_source = (ISource) new NintendoContentArchiveSource(new NintendoContentFileSystemInfo() { distributionType = isGameCard ? (byte)1 : (byte)0, contentType = (byte)1, keyGeneration = (byte)0, programId = contentMetaReader.GetId(), contentIndex = 0U, keyAreaEncryptionKeyIndex = (byte)keyEncryptionKeyIndex, isProdEncryption = isProdEncryption, fsEntries = { new NintendoContentFileSystemInfo.EntryInfo() { type = "source", formatType = "PartitionFs", sourceInterface = (SourceInterface) new CliCompatibleSource(source2), version = (ushort)2, hashType = (byte)0, encryptionType = (byte)0 } }, numFsEntries = 1 }, config, false); this.Size = this.m_source.Size; }
public ISource GetLayerHashSource() { if (this.m_hashLayerCount == 1) { return(this.GetMasterHashSource()); } List <ConcatenatedSource.Element> elements = new List <ConcatenatedSource.Element>(); long offset = 0; for (int index = 1; index < this.m_hashLayerCount; ++index) { ConcatenatedSource.Element element = new ConcatenatedSource.Element((ISource) new SinkLinkedSource((ISink)this.m_hierarchicalHashValueSinkList[index], this.m_hierarchicalHashValueSinkList[index].ToSource()), "Hash:L" + (object)index, offset); offset += this.m_hierarchicalHashValueSinkList[index].Size; elements.Add(element); } return((ISource) new ConcatenatedSource(elements)); }
private void MakeBody(NintendoContentFileSystemMeta meta, NintendoContentFileSystemEntryInfoContainer fsEntries, NintendoContentArchiveSource.BodySourceElement[] bodySources, NintendoContentArchiveSource.BodyEncryptionKey bodyEncryptionKey) { List <ConcatenatedSource.Element> elements = new List <ConcatenatedSource.Element>(); for (int index = 0; index < bodySources.Length; ++index) { if (bodySources[index].HeaderElement == null) { PaddingSource paddingSource = new PaddingSource((long)meta.GetFsHeaderSize()); elements.Add(new ConcatenatedSource.Element((ISource)paddingSource, "fsHeader" + (object)index, (long)index * (long)meta.GetFsHeaderSize())); } else { ConcatenatedSource.Element headerElement = bodySources[index].HeaderElement; ISource source = (ISource) new Aes128XtsEncryptedSource(headerElement.Source, this.m_headerEncryptor); elements.Add(new ConcatenatedSource.Element(source, headerElement.Signature, headerElement.Offset)); } } for (int length = bodySources.Length; length < 4; ++length) { PaddingSource paddingSource = new PaddingSource((long)meta.GetFsHeaderSize()); elements.Add(new ConcatenatedSource.Element((ISource)paddingSource, "fsHeader" + (object)length, (long)length * (long)meta.GetFsHeaderSize())); } foreach (NintendoContentFileSystemInfo.EntryInfo fsEntry in fsEntries) { int currentIndex = fsEntries.CurrentIndex; ISource source = (ISource) new ConcatenatedSource(bodySources[currentIndex].DataSourceElements); switch (fsEntry.encryptionType) { case 1: elements.Add(new ConcatenatedSource.Element(source, "fsData" + (object)currentIndex, bodySources[currentIndex].DataOffset)); continue; case 3: source = (ISource) new Aes128CtrEncryptedSource(source, (ICtrModeEncryptor) new Aes128CtrCryptoDriver(bodyEncryptionKey.GetInternalKey(NintendoContentArchiveEncryptionKeyIndex.AesCtr)), (int)this.m_fileSystemInfo.keyGeneration, (long)fsEntry.startOffset); goto case 1; default: throw new InvalidDataException(); } } this.m_bodySource = (ISource) new ConcatenatedSource(elements); this.m_fileSystemInfo.contentSize = meta.GetHeaderSize() + (ulong)this.m_bodySource.Size; }
public PartitionFsArchiveSource(PartitionFileSystemInfo fileSystemInfo) { PartitionFileSystemMeta partitionFileSystemMeta = new PartitionFileSystemMeta(); List <ConcatenatedSource.Element> elements = new List <ConcatenatedSource.Element>(); PartitionFileSystemInfo fileSystemInfo1 = fileSystemInfo; byte[] buffer = partitionFileSystemMeta.Create(fileSystemInfo1); ConcatenatedSource.Element element1 = new ConcatenatedSource.Element((ISource) new MemorySource(buffer, 0, buffer.Length), "meta", 0L); elements.Add(element1); long size = element1.Source.Size; foreach (PartitionFileSystemInfo.EntryInfo entry in fileSystemInfo.entries) { ConcatenatedSource.Element element2 = new ConcatenatedSource.Element(entry.sourceInterface != null ? (ISource)entry.sourceInterface : (ISource) new FileSource(entry.path, 0L, (long)entry.size), entry.name, (long)entry.offset + size); elements.Add(element2); } this.m_source = (ISource) new ConcatenatedSource(elements); this.Size = this.m_source.Size; }
public ByteData PullData(long offset, int size) { int count1 = 0; byte[] array1 = new byte[size]; long offset1 = offset; while (count1 != size) { ConcatenatedSource.Element element = this.GetElement(offset1); ByteData byteData = element.Source.PullData(offset1 - element.Offset, size - count1); ArraySegment <byte> buffer = byteData.Buffer; if (buffer.Count != 0) { buffer = byteData.Buffer; byte[] array2 = buffer.Array; buffer = byteData.Buffer; int offset2 = buffer.Offset; byte[] numArray = array1; int dstOffset = count1; buffer = byteData.Buffer; int count2 = buffer.Count; Buffer.BlockCopy((Array)array2, offset2, (Array)numArray, dstOffset, count2); int num1 = count1; buffer = byteData.Buffer; int count3 = buffer.Count; count1 = num1 + count3; long num2 = offset1; buffer = byteData.Buffer; long count4 = (long)buffer.Count; offset1 = num2 + count4; } else { break; } } return(new ByteData(new ArraySegment <byte>(array1, 0, count1))); }
public ConcatenatedSource(List <ConcatenatedSource.Element> elements) { this.Elements = new List <ConcatenatedSource.Element>(); foreach (ConcatenatedSource.Element element in elements) { this.Elements.Add(element); } this.Elements.Sort((IComparer <ConcatenatedSource.Element>) new ConcatenatedSource.ElementOffsetComparer()); for (int index = 0; index < this.Elements.Count - 1; ++index) { long size = this.Elements[index + 1].Offset - (this.Elements[index].Offset + this.Elements[index].Source.Size); if (size < 0L) { throw new ArgumentException("entries layout overlaps. please check .adf file."); } if (size > 0L) { ConcatenatedSource.Element element = new ConcatenatedSource.Element((ISource) new PaddingSource(size), string.Empty, this.Elements[index].Offset + this.Elements[index].Source.Size); this.Elements.Insert(index + 1, element); } } this.Size = this.Elements.Last <ConcatenatedSource.Element>().Offset + this.Elements.Last <ConcatenatedSource.Element>().Source.Size; }
public RomFsArchiveSource(RomFsFileSystemInfo fileSystemInfo) { RomFsFileSystemMeta fsFileSystemMeta = new RomFsFileSystemMeta(); List <ConcatenatedSource.Element> elements = new List <ConcatenatedSource.Element>(); RomFsFileSystemInfo fileSystemInfo1 = fileSystemInfo; RomFsFileSystemMetaInfo fileSystemMetaInfo = fsFileSystemMeta.Create(fileSystemInfo1); ConcatenatedSource.Element element1 = new ConcatenatedSource.Element((ISource) new MemorySource(fileSystemMetaInfo.header, 0, fileSystemMetaInfo.header.Length), "meta_header", 0L); elements.Add(element1); long size = element1.Source.Size; foreach (RomFsFileSystemInfo.EntryInfo entry in fileSystemInfo.entries) { if (entry.type == "file") { ConcatenatedSource.Element element2 = new ConcatenatedSource.Element((ISource) new FileSource(entry.path, 0L, (long)entry.size), entry.name, (long)entry.offset + size); elements.Add(element2); } else if (entry.type == "source") { ConcatenatedSource.Element element2 = new ConcatenatedSource.Element((ISource)entry.sourceInterface, entry.name, (long)entry.offset + size); elements.Add(element2); } } RomFsFileSystemInfo.EntryInfo entry1 = fileSystemInfo.entries[fileSystemInfo.entries.Count - 1]; long offset = size + (long)entry1.offset + (long)entry1.size; if (fileSystemMetaInfo.offsetData > offset) { elements.Add(new ConcatenatedSource.Element((ISource) new PaddingSource(fileSystemMetaInfo.offsetData - offset), "romFsMetaBodyPadding", offset)); } ConcatenatedSource.Element element3 = new ConcatenatedSource.Element((ISource) new MemorySource(fileSystemMetaInfo.data, 0, fileSystemMetaInfo.data.Length), "meta_data", fileSystemMetaInfo.offsetData); elements.Add(element3); this.m_source = (ISource) new ConcatenatedSource(elements); this.Size = this.m_source.Size; }