public ModifiableNintendoSubmissionPackageArchive(IReadableSink outSink, NintendoSubmissionPackageReader nspReader, ISource inSource, string targetEntryPath, string descFilePath, KeyConfiguration keyConfig) { this.m_KeyConfig = keyConfig; NintendoSubmissionPackageFileSystemInfo replacedNspInfo = ArchiveReconstructionUtils.GetReplacedNspInfo(nspReader, inSource, targetEntryPath, descFilePath, this.m_KeyConfig); this.ConnectionList = new List <Connection>((IEnumerable <Connection>) new NintendoSubmissionPackageArchive(outSink, replacedNspInfo, this.m_KeyConfig).ConnectionList); }
public ModifiableNintendoContentArchive(IReadableSink outSink, NintendoContentArchiveReader ncaReader, ISource inSource, string targetEntryPath, string descFilePath, KeyConfiguration keyConfig) { this.m_KeyConfig = keyConfig; NintendoContentArchiveSource contentArchiveSource = new NintendoContentArchiveSource(ArchiveReconstructionUtils.GetReplacedNcaInfo(ncaReader, descFilePath, new EntryReplaceRule() { Source = inSource, Path = targetEntryPath }), this.m_KeyConfig, false); outSink.SetSize(contentArchiveSource.Size); this.ConnectionList = new List <Connection>(); this.ConnectionList.Add(new Connection((ISource)contentArchiveSource, (ISink)outSink)); }
private static void CalculatePartitionSize(out long partitionHeaderSize, out long partitionSize, NintendoSubmissionPackageFileSystemInfo nspInfo, NintendoSubmissionPackageFileSystemInfo patchInfo, bool isNormal, KeyConfiguration keyConfig) { long num = 0; List <string> entryNameList = new List <string>(); for (int index1 = 0; index1 < nspInfo.Entries.Count; ++index1) { List <Tuple <ISource, NintendoContentInfo> > contentSourceList = new List <Tuple <ISource, NintendoContentInfo> >(); NintendoSubmissionPackageFileSystemInfo.EntryInfo entry = nspInfo.Entries[index1]; for (int index2 = 0; index2 < entry.Contents.Count; ++index2) { NintendoSubmissionPackageFileSystemInfo.ContentInfo content = entry.Contents[index2]; if ((!isNormal || !(content.ContentType != "Control")) && !(content.ContentType == "Meta")) { ISource source; if (content.FsInfo != null) { source = (ISource) new NintendoContentArchiveSource(content.FsInfo as NintendoContentFileSystemInfo, keyConfig, false); } else { if (content.Source == null) { throw new NotImplementedException(); } source = content.Source; } contentSourceList.Add(Tuple.Create <ISource, NintendoContentInfo>(source, new NintendoContentInfo(content.ContentType, source.Size))); entryNameList.Add("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.nca"); num += ProdEncryptedXciArchive.RoundupPageSize(source.Size); } } entryNameList.Add("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.cnmt.nca"); NintendoContentMetaArchiveSource metaArchiveSource = new NintendoContentMetaArchiveSource(entry.ContentMetaInfo == null ? new NintendoContentMetaBase(contentSourceList, entry.MetaType, entry.MetaFilePath) : new NintendoContentMetaBase(contentSourceList, entry.ContentMetaInfo.Data, entry.ContentMetaInfo.Model, true), entry.KeyIndex, keyConfig, nspInfo.IsProdEncryption, true); num += ProdEncryptedXciArchive.RoundupPageSize(metaArchiveSource.Size); } partitionHeaderSize = HashNameEntryPartitionFsHeaderSource <Sha256PartitionFileSystemMeta> .GetDummySize(entryNameList); ProdEncryptedXciArchive.CheckAlignmentPageSize(partitionHeaderSize); partitionSize = num; }
public ProdEncryptedXciArchive(IReadableSink outSink, NintendoSubmissionPackageReader nspReader, NintendoSubmissionPackageReader uppReader, NintendoSubmissionPackageReader patchReader, byte launchFlags, KeyConfiguration keyConfig) { this.ConnectionList = new List <Connection>(); this.m_rng = new RNGCryptoServiceProvider(); this.m_keyConfig = keyConfig; this.SetCryptor(this.m_keyConfig); uint num1 = 0; uint num2 = 0; ulong num3 = 0; byte[] numArray1 = (byte[])null; NintendoSubmissionPackageFileSystemInfo prodNspInfo = ArchiveReconstructionUtils.GetProdNspInfo(nspReader, this.m_keyConfig); XciUtils.CheckRomSizeAndClockRate(prodNspInfo.CardSize, prodNspInfo.CardClockRate); NintendoSubmissionPackageFileSystemInfo uppInfo = (NintendoSubmissionPackageFileSystemInfo)null; if (uppReader != null) { uppInfo = ArchiveReconstructionUtils.GetProdNspInfo(uppReader, this.m_keyConfig); } XciSizeInfo xciSize = ProdEncryptedXciArchive.CalculateXciSize(prodNspInfo, uppInfo, (NintendoSubmissionPackageFileSystemInfo)null, this.m_keyConfig); int romSize = XciUtils.GetRomSize(xciSize.TotalSize); if (romSize == XciInfo.InvalidRomSize) { throw new ArgumentException(string.Format("Xci size exceed the maximum size of the game card.", Array.Empty <object>())); } if (prodNspInfo.CardSize < romSize) { throw new ArgumentException(string.Format("Xci requires CardSpec/Size = {0}, though it is set as {1}.", (object)romSize, (object)prodNspInfo.CardSize)); } outSink.SetSize(xciSize.TotalSize); List <Sha256PartitionFsHashSource> hashSources1 = new List <Sha256PartitionFsHashSource>(); PartitionFileSystemInfo partFsInfo1 = new PartitionFileSystemInfo(); List <ContentHashSource> hashSources2 = new List <ContentHashSource>(); List <Sha256PartitionFsHashSource> hashSources3 = new List <Sha256PartitionFsHashSource>(); if (uppInfo != null && uppReader != null) { long partitionHeaderSize = xciSize.UpdatePartitionHeaderSize; foreach (NintendoSubmissionPackageFileSystemInfo.EntryInfo entry in uppInfo.Entries) { if (entry.MetaType == "SystemUpdate") { NintendoContentMetaReader contentMetaReader = new NintendoContentMetaReader(entry.ContentMetaInfo.Data); num2 = contentMetaReader.GetVersion(); num3 = contentMetaReader.GetId(); } } byte[] buffer = uppReader.ReadBase(0L, uppReader.GetBaseSize()); numArray1 = new SHA256CryptoServiceProvider().ComputeHash(buffer, 0, buffer.Length); foreach (Tuple <string, long> tuple in uppReader.ListFileInfo().FindAll((Predicate <Tuple <string, long> >)(x => x.Item1.EndsWith(".nca")))) { string str = tuple.Item1; long num4 = tuple.Item2; ulong offset = (ulong)(partitionHeaderSize - xciSize.UpdatePartitionHeaderSize); PartitionFileSystemInfo.EntryInfo entryInfo = PartitionFileSystemInfo.EntryInfo.Make(str, (ulong)num4, offset, 0UL, XciInfo.PageSize); partFsInfo1.entries.Add(entryInfo); FileSystemArchvieFileSource archvieFileSource = new FileSystemArchvieFileSource((IFileSystemArchiveReader)uppReader, str); IReadableSink readableSink = (IReadableSink) new ReadableSubSink(outSink, xciSize.UpdatePartitionOffset + partitionHeaderSize, archvieFileSource.Size); this.ConnectionList.Add(new Connection((ISource)archvieFileSource, (ISink)readableSink)); hashSources2.Add(new ContentHashSource((ISource)null, "no_change")); SinkLinkedSource sinkLinkedSource = new SinkLinkedSource((ISink)readableSink, (ISource) new Sha256StreamHashSource((ISource) new SubSource(readableSink.ToSource(), 0L, (long)XciInfo.PageSize))); hashSources3.Add(new Sha256PartitionFsHashSource((ISource)sinkLinkedSource, hashSources3.Count)); partitionHeaderSize += archvieFileSource.Size; } } HashAdaptedSha256PartitionFsHeaderSource partitionFsHeaderSource1 = new HashAdaptedSha256PartitionFsHeaderSource((ISource) new HashNameEntryPartitionFsHeaderSource <Sha256PartitionFileSystemMeta>(hashSources2, partFsInfo1, xciSize.UpdatePartitionHeaderSize), hashSources3); IReadableSink readableSink1 = (IReadableSink) new ReadableSubSink(outSink, xciSize.UpdatePartitionOffset, partitionFsHeaderSource1.Size); this.ConnectionList.Add(new Connection((ISource)partitionFsHeaderSource1, (ISink)readableSink1)); SinkLinkedSource sinkLinkedSource1 = new SinkLinkedSource((ISink)readableSink1, (ISource) new Sha256StreamHashSource((ISource) new SubSource(readableSink1.ToSource(), 0L, xciSize.UpdatePartitionHeaderSize))); hashSources1.Add(new Sha256PartitionFsHashSource((ISource)sinkLinkedSource1, hashSources1.Count)); PartitionFileSystemInfo partFsInfo2 = new PartitionFileSystemInfo(); PartitionFileSystemInfo partFsInfo3 = new PartitionFileSystemInfo(); List <ContentHashSource> hashSources4 = new List <ContentHashSource>(); List <ContentHashSource> hashSources5 = new List <ContentHashSource>(); List <Sha256PartitionFsHashSource> hashSources6 = new List <Sha256PartitionFsHashSource>(); List <Sha256PartitionFsHashSource> hashSources7 = new List <Sha256PartitionFsHashSource>(); long partitionHeaderSize1 = xciSize.SecurePartitionHeaderSize; long partitionHeaderSize2 = xciSize.NormalPartitionHeaderSize; for (int index1 = 0; index1 < prodNspInfo.Entries.Count; ++index1) { NintendoSubmissionPackageFileSystemInfo.EntryInfo entry = prodNspInfo.Entries[index1]; List <Tuple <ISource, NintendoContentInfo> > contentSourceList = new List <Tuple <ISource, NintendoContentInfo> >(); for (int index2 = 0; index2 < entry.Contents.Count; ++index2) { NintendoSubmissionPackageFileSystemInfo.ContentInfo content = entry.Contents[index2]; if (!(content.ContentType == "Meta")) { if (content.ContentType == "Program") { num1 = (content.FsInfo as NintendoContentFileSystemInfo).sdkAddonVersion; } (content.FsInfo as NintendoContentFileSystemInfo).distributionType = (byte)1; NintendoContentArchiveSource contentArchiveSource = new NintendoContentArchiveSource(content.FsInfo as NintendoContentFileSystemInfo, this.m_keyConfig, false); ulong offset1 = (ulong)(partitionHeaderSize1 - xciSize.SecurePartitionHeaderSize); PartitionFileSystemInfo.EntryInfo entryInfo1 = PartitionFileSystemInfo.EntryInfo.Make("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.nca", (ulong)contentArchiveSource.Size, offset1, 0UL, XciInfo.PageSize); partFsInfo2.entries.Add(entryInfo1); IReadableSink readableSink2 = (IReadableSink) new ReadableSubSink(outSink, xciSize.SecurePartitionOffset + partitionHeaderSize1, contentArchiveSource.Size); this.ConnectionList.Add(new Connection((ISource)contentArchiveSource, (ISink)readableSink2)); SinkLinkedSource sinkLinkedSource2 = new SinkLinkedSource((ISink)readableSink2, (ISource) new Sha256StreamHashSource(readableSink2.ToSource())); SinkLinkedSource sinkLinkedSource3 = new SinkLinkedSource((ISink)readableSink2, (ISource) new Sha256StreamHashSource((ISource) new SubSource(readableSink2.ToSource(), 0L, (long)XciInfo.PageSize))); hashSources4.Add(new ContentHashSource((ISource)sinkLinkedSource2, ".nca")); hashSources6.Add(new Sha256PartitionFsHashSource((ISource)sinkLinkedSource3, hashSources6.Count)); contentSourceList.Add(Tuple.Create <ISource, NintendoContentInfo>(hashSources4[hashSources4.Count - 1].Source, new NintendoContentInfo(content.ContentType, contentArchiveSource.Size))); partitionHeaderSize1 += ProdEncryptedXciArchive.RoundupPageSize(contentArchiveSource.Size); if (content.ContentType == "Control") { ulong offset2 = (ulong)(partitionHeaderSize2 - xciSize.NormalPartitionHeaderSize); PartitionFileSystemInfo.EntryInfo entryInfo2 = PartitionFileSystemInfo.EntryInfo.Make("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.nca", (ulong)contentArchiveSource.Size, offset2, 0UL, XciInfo.PageSize); partFsInfo3.entries.Add(entryInfo2); SinkLinkedSource sinkLinkedSource4 = new SinkLinkedSource((ISink)readableSink2, readableSink2.ToSource()); IReadableSink readableSink3 = (IReadableSink) new ReadableSubSink(outSink, xciSize.NormalPartitionOffset + partitionHeaderSize2, sinkLinkedSource4.Size); this.ConnectionList.Add(new Connection((ISource)sinkLinkedSource4, (ISink)readableSink3)); hashSources5.Add(new ContentHashSource((ISource)sinkLinkedSource2, ".nca")); hashSources7.Add(new Sha256PartitionFsHashSource((ISource)sinkLinkedSource3, hashSources7.Count)); partitionHeaderSize2 += ProdEncryptedXciArchive.RoundupPageSize(contentArchiveSource.Size); } } } NintendoContentMetaArchiveSource metaArchiveSource = new NintendoContentMetaArchiveSource(new NintendoContentMetaBase(contentSourceList, entry.ContentMetaInfo.Data, entry.ContentMetaInfo.Model, true), entry.KeyIndex, this.m_keyConfig, prodNspInfo.IsProdEncryption, true); ulong offset3 = (ulong)(partitionHeaderSize1 - xciSize.SecurePartitionHeaderSize); PartitionFileSystemInfo.EntryInfo entryInfo3 = PartitionFileSystemInfo.EntryInfo.Make("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.cnmt.nca", (ulong)metaArchiveSource.Size, offset3, 0UL, XciInfo.PageSize); partFsInfo2.entries.Add(entryInfo3); IReadableSink readableSink4 = (IReadableSink) new ReadableSubSink(outSink, xciSize.SecurePartitionOffset + partitionHeaderSize1, metaArchiveSource.Size); this.ConnectionList.Add(new Connection((ISource)metaArchiveSource, (ISink)readableSink4)); SinkLinkedSource sinkLinkedSource5 = new SinkLinkedSource((ISink)readableSink4, (ISource) new Sha256StreamHashSource(readableSink4.ToSource())); SinkLinkedSource sinkLinkedSource6 = new SinkLinkedSource((ISink)readableSink4, (ISource) new Sha256StreamHashSource((ISource) new SubSource(readableSink4.ToSource(), 0L, (long)XciInfo.PageSize))); hashSources4.Add(new ContentHashSource((ISource)sinkLinkedSource5, ".cnmt.nca")); hashSources6.Add(new Sha256PartitionFsHashSource((ISource)sinkLinkedSource6, hashSources6.Count)); partitionHeaderSize1 += ProdEncryptedXciArchive.RoundupPageSize(metaArchiveSource.Size); ulong offset4 = (ulong)(partitionHeaderSize2 - xciSize.NormalPartitionHeaderSize); PartitionFileSystemInfo.EntryInfo entryInfo4 = PartitionFileSystemInfo.EntryInfo.Make("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.cnmt.nca", (ulong)metaArchiveSource.Size, offset4, 0UL, XciInfo.PageSize); partFsInfo3.entries.Add(entryInfo4); SinkLinkedSource sinkLinkedSource7 = new SinkLinkedSource((ISink)readableSink4, readableSink4.ToSource()); IReadableSink readableSink5 = (IReadableSink) new ReadableSubSink(outSink, xciSize.NormalPartitionOffset + partitionHeaderSize2, sinkLinkedSource7.Size); this.ConnectionList.Add(new Connection((ISource)sinkLinkedSource7, (ISink)readableSink5)); hashSources5.Add(new ContentHashSource((ISource)sinkLinkedSource5, ".cnmt.nca")); hashSources7.Add(new Sha256PartitionFsHashSource((ISource)sinkLinkedSource6, hashSources7.Count)); partitionHeaderSize2 += ProdEncryptedXciArchive.RoundupPageSize(metaArchiveSource.Size); } HashAdaptedSha256PartitionFsHeaderSource partitionFsHeaderSource2 = new HashAdaptedSha256PartitionFsHeaderSource((ISource) new HashNameEntryPartitionFsHeaderSource <Sha256PartitionFileSystemMeta>(hashSources5, partFsInfo3, xciSize.NormalPartitionHeaderSize), hashSources7); IReadableSink readableSink6 = (IReadableSink) new ReadableSubSink(outSink, xciSize.NormalPartitionOffset, partitionFsHeaderSource2.Size); this.ConnectionList.Add(new Connection((ISource)partitionFsHeaderSource2, (ISink)readableSink6)); SinkLinkedSource sinkLinkedSource8 = new SinkLinkedSource((ISink)readableSink6, (ISource) new Sha256StreamHashSource((ISource) new SubSource(readableSink6.ToSource(), 0L, xciSize.NormalPartitionHeaderSize))); hashSources1.Add(new Sha256PartitionFsHashSource((ISource)sinkLinkedSource8, hashSources1.Count)); HashAdaptedSha256PartitionFsHeaderSource partitionFsHeaderSource3 = new HashAdaptedSha256PartitionFsHeaderSource((ISource) new HashNameEntryPartitionFsHeaderSource <Sha256PartitionFileSystemMeta>(hashSources4, partFsInfo2, xciSize.SecurePartitionHeaderSize), hashSources6); IReadableSink readableSink7 = (IReadableSink) new ReadableSubSink(outSink, xciSize.SecurePartitionOffset, partitionFsHeaderSource3.Size); this.ConnectionList.Add(new Connection((ISource)partitionFsHeaderSource3, (ISink)readableSink7)); SinkLinkedSource sinkLinkedSource9 = new SinkLinkedSource((ISink)readableSink7, (ISource) new Sha256StreamHashSource((ISource) new SubSource(readableSink7.ToSource(), 0L, xciSize.SecurePartitionHeaderSize))); hashSources1.Add(new Sha256PartitionFsHashSource((ISource)sinkLinkedSource9, hashSources1.Count)); PartitionFileSystemInfo partFsInfo4 = new PartitionFileSystemInfo(); List <ContentHashSource> hashSources8 = new List <ContentHashSource>(); ulong offset5 = (ulong)(xciSize.UpdatePartitionOffset - xciSize.UpdatePartitionOffset); PartitionFileSystemInfo.EntryInfo entryInfo5 = PartitionFileSystemInfo.EntryInfo.Make("update", (ulong)(xciSize.UpdatePartitionHeaderSize + xciSize.UpdatePartitionSize), offset5, 0UL, (uint)xciSize.UpdatePartitionHeaderSize); partFsInfo4.entries.Add(entryInfo5); hashSources8.Add(new ContentHashSource((ISource)null, "update")); ulong offset6 = (ulong)(xciSize.NormalPartitionOffset - xciSize.UpdatePartitionOffset); PartitionFileSystemInfo.EntryInfo entryInfo6 = PartitionFileSystemInfo.EntryInfo.Make("normal", (ulong)(xciSize.NormalPartitionHeaderSize + xciSize.NormalPartitionSize), offset6, 0UL, (uint)xciSize.NormalPartitionHeaderSize); partFsInfo4.entries.Add(entryInfo6); hashSources8.Add(new ContentHashSource((ISource)null, "normal")); ulong offset7 = (ulong)(xciSize.SecurePartitionOffset - xciSize.UpdatePartitionOffset); PartitionFileSystemInfo.EntryInfo entryInfo7 = PartitionFileSystemInfo.EntryInfo.Make("secure", (ulong)(xciSize.SecurePartitionHeaderSize + xciSize.SecurePartitionSize), offset7, 0UL, (uint)xciSize.SecurePartitionHeaderSize); partFsInfo4.entries.Add(entryInfo7); hashSources8.Add(new ContentHashSource((ISource)null, "secure")); HashAdaptedSha256PartitionFsHeaderSource partitionFsHeaderSource4 = new HashAdaptedSha256PartitionFsHeaderSource((ISource) new HashNameEntryPartitionFsHeaderSource <Sha256PartitionFileSystemMeta>(hashSources8, partFsInfo4, xciSize.RootPartitionHeaderSize), hashSources1); IReadableSink readableSink8 = (IReadableSink) new ReadableSubSink(outSink, xciSize.RootPartitionOffset, partitionFsHeaderSource4.Size); this.ConnectionList.Add(new Connection((ISource)partitionFsHeaderSource4, (ISink)readableSink8)); ISource rootPartitionFsHeaderHashSource = (ISource) new SinkLinkedSource((ISink)readableSink8, (ISource) new Sha256StreamHashSource((ISource) new SubSource(readableSink8.ToSource(), 0L, xciSize.RootPartitionHeaderSize))); byte[] data1 = new byte[8]; this.m_rng.GetBytes(data1); ulong uint64 = BitConverter.ToUInt64(data1, 0); byte[] numArray2 = new byte[XciMeta.TitleKey1Size]; byte[] numArray3 = new byte[XciMeta.TitleKey2Size]; this.m_rng.GetBytes(numArray2); this.m_rng.GetBytes(numArray3); byte[] initialData = this.CreateInitialData(uint64, new Pair <byte[], byte[]>(numArray2, numArray3)); byte[] keyArea = this.CreateKeyArea(initialData, new Pair <byte[], byte[]>(numArray2, numArray3)); MemorySource memorySource = new MemorySource(keyArea, 0, keyArea.Length); byte[] data2 = new byte[XciInfo.IvSize]; this.m_rng.GetBytes(data2); XciInfo xciInfo = new XciInfo(); xciInfo.romAreaStartPageAddress = (uint)((ulong)xciSize.SecurePartitionOffset / (ulong)XciInfo.PageSize) - XciInfo.CardKeyAreaPageCount; xciInfo.kekIndex = XciInfo.KekIndexVersion0; xciInfo.romSize = XciInfo.ConvertRomSizeToRomSizeByte(prodNspInfo.CardSize); xciInfo.flags = launchFlags; xciInfo.packageId = uint64; xciInfo.validDataEndAddress = (uint)((int)(uint)((ulong)ProdEncryptedXciArchive.RoundupPageSize(xciSize.TotalSize) / (ulong)XciInfo.PageSize) - (int)XciInfo.CardKeyAreaPageCount - 1); xciInfo.iv = data2; xciInfo.partitionFsHeaderAddress = (ulong)(XciInfo.NormalAreaStartPageAddress - XciInfo.CardKeyAreaPageCount) * (ulong)XciInfo.PageSize; xciInfo.partitionFsHeaderSize = (ulong)xciSize.RootPartitionHeaderSize; xciInfo.partitionFsHeaderHash = (byte[])null; xciInfo.selSec = XciInfo.SelSecForT1; xciInfo.fwVersion = XciInfo.FwVersion; xciInfo.accCtrl1 = XciInfo.ConvertClockRateToAccCtrl1(prodNspInfo.CardClockRate); xciInfo.fwMode = num1; xciInfo.cupVersion = num2; xciInfo.cupId = num3; xciInfo.uppHash = numArray1 != null ? ((IEnumerable <byte>)numArray1).Take <byte>(XciInfo.UppHashSize).ToArray <byte>() : new byte[XciInfo.UppHashSize]; XciMeta xciMeta = new XciMeta(initialData); XciHeaderSource xciHeaderSource = new XciHeaderSource(ref xciInfo, xciMeta, rootPartitionFsHeaderHashSource, this.m_headerEncryptor, this.m_headerSigner); ReadableSubSink readableSubSink1 = new ReadableSubSink(outSink, 0L, memorySource.Size); this.ConnectionList.Add(new Connection((ISource)memorySource, (ISink)readableSubSink1)); ReadableSubSink readableSubSink2 = new ReadableSubSink(outSink, memorySource.Size, xciHeaderSource.Size); this.ConnectionList.Add(new Connection((ISource)xciHeaderSource, (ISink)readableSubSink2)); }
internal static XciSizeInfo CalculateXciSize(NintendoSubmissionPackageFileSystemInfo nspInfo, NintendoSubmissionPackageFileSystemInfo uppInfo, NintendoSubmissionPackageFileSystemInfo patchInfo, KeyConfiguration keyConfig) { XciSizeInfo xciSizeInfo = new XciSizeInfo(); xciSizeInfo.RootPartitionOffset = (long)XciInfo.NormalAreaStartPageAddress * (long)XciInfo.PageSize; ProdEncryptedXciArchive.CalculateRootPartitionHeaderSize(out xciSizeInfo.RootPartitionHeaderSize); xciSizeInfo.UpdatePartitionOffset = xciSizeInfo.RootPartitionOffset + xciSizeInfo.RootPartitionHeaderSize; ProdEncryptedXciArchive.CalculateUpdatePartitionSize(out xciSizeInfo.UpdatePartitionHeaderSize, out xciSizeInfo.UpdatePartitionSize, uppInfo); xciSizeInfo.NormalPartitionOffset = xciSizeInfo.UpdatePartitionOffset + xciSizeInfo.UpdatePartitionHeaderSize + xciSizeInfo.UpdatePartitionSize; ProdEncryptedXciArchive.CalculatePartitionSize(out xciSizeInfo.NormalPartitionHeaderSize, out xciSizeInfo.NormalPartitionSize, nspInfo, patchInfo, true, keyConfig); xciSizeInfo.SecurePartitionOffset = ProdEncryptedXciArchive.RoundupRomAreaStartPageAddress(xciSizeInfo.NormalPartitionOffset + xciSizeInfo.NormalPartitionHeaderSize + xciSizeInfo.NormalPartitionSize) + (long)(XciInfo.CardKeyAreaPageCount * XciInfo.PageSize); ProdEncryptedXciArchive.CalculatePartitionSize(out xciSizeInfo.SecurePartitionHeaderSize, out xciSizeInfo.SecurePartitionSize, nspInfo, patchInfo, false, keyConfig); xciSizeInfo.TotalSize = xciSizeInfo.SecurePartitionOffset + xciSizeInfo.SecurePartitionHeaderSize + xciSizeInfo.SecurePartitionSize; return(xciSizeInfo); }
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 void SetCryptor(KeyConfiguration config) { if (this.m_fileSystemInfo.isProdEncryption) { this.m_bodyEncryptionKeyEncryptor = this.m_keyConfig.GetProdKeyAreaEncryptionKey() == null ? (IEncryptor) new HsmAes128CryptoDriver(Aes128KeyIndex.NcaContentKey) : (IEncryptor) new Aes128CryptoDriver(this.m_keyConfig.GetProdKeyAreaEncryptionKey().Key); byte[][] numArray1 = new byte[2][] { new byte[16], new byte[16] }; byte[][] numArray2 = new byte[2][] { new byte[16] { (byte)90, (byte)62, (byte)216, (byte)79, (byte)222, (byte)192, (byte)216, (byte)38, (byte)49, (byte)247, (byte)226, (byte)93, (byte)25, (byte)123, (byte)245, (byte)208 }, new byte[16] { (byte)28, (byte)155, (byte)123, (byte)250, (byte)246, (byte)40, (byte)24, (byte)61, (byte)113, (byte)246, (byte)77, (byte)115, (byte)241, (byte)80, (byte)185, (byte)210 } }; IEncryptor encryptor = this.m_keyConfig.GetProdNcaHeaderEncryptionKek() == null ? (IEncryptor) new HsmAes128CryptoDriver(Aes128KeyIndex.NcaHeader) : (IEncryptor) new Aes128CryptoDriver(this.m_keyConfig.GetProdNcaHeaderEncryptionKek().Key); encryptor.DecryptBlock(numArray2[0], 0, 16, numArray1[0], 0); encryptor.DecryptBlock(numArray2[1], 0, 16, numArray1[1], 0); this.m_headerEncryptor = (IXtsModeEncryptor) new Aes128XtsCryptoDriver(numArray1[0], numArray1[1]); if (this.m_keyConfig.GetNcaHeader1SignKey() != null) { RsaKey ncaHeader1SignKey = this.m_keyConfig.GetNcaHeader1SignKey(); this.m_header1Signer = (ISigner) new Rsa2048PssSha256SignCryptoDriver(ncaHeader1SignKey.KeyModulus, ncaHeader1SignKey.KeyPublicExponent, ncaHeader1SignKey.KeyPrivateExponent); } else { this.m_header1Signer = (ISigner) new HsmRsa2048PssSha256SignCryptoDriver(Rsa2048PssSha256KeyIndex.NcaHeader1); } if (this.m_fileSystemInfo.contentType != (byte)0) { this.m_header2Signer = (ISigner)null; } else { RsaKey randomRsaKey = this.m_keyConfig.GetRandomRsaKey(); this.m_header2Signer = (ISigner) new Rsa2048PssSha256SignCryptoDriver(randomRsaKey.KeyModulus, randomRsaKey.KeyPublicExponent, randomRsaKey.KeyPrivateExponent); } if (this.m_keyConfig.GetAcidSignKey() != null) { RsaKey acidSignKey = this.m_keyConfig.GetAcidSignKey(); this.m_acidSigner = (ISigner) new Rsa2048PssSha256SignCryptoDriver(acidSignKey.KeyModulus, acidSignKey.KeyPublicExponent, acidSignKey.KeyPrivateExponent); } else { this.m_acidSigner = (ISigner) new HsmRsa2048PssSha256SignCryptoDriver(Rsa2048PssSha256KeyIndex.Acid); } RsaKey randomRsaKey1 = this.m_keyConfig.GetRandomRsaKey(); this.m_nrrSigner = (ISigner) new Rsa2048PssSha256SignCryptoDriver(randomRsaKey1.KeyModulus, randomRsaKey1.KeyPublicExponent, randomRsaKey1.KeyPrivateExponent); if (this.m_keyConfig.GetNrrCertificateSignKey() != null) { RsaKey certificateSignKey = this.m_keyConfig.GetNrrCertificateSignKey(); this.m_nrrCertificateSigner = (ISigner) new Rsa2048PssSha256SignCryptoDriver(certificateSignKey.KeyModulus, certificateSignKey.KeyPublicExponent, certificateSignKey.KeyPrivateExponent); } else { this.m_nrrCertificateSigner = (ISigner) new HsmRsa2048PssSha256SignCryptoDriver(Rsa2048PssSha256KeyIndex.NrrCertificate); } } else { this.m_bodyEncryptionKeyEncryptor = (IEncryptor) new Aes128CryptoDriver(this.m_keyConfig.GetKeyAreaEncryptionKey((uint)this.m_fileSystemInfo.keyAreaEncryptionKeyIndex).Key); this.m_headerEncryptor = (IXtsModeEncryptor) new Aes128XtsCryptoDriver(Aes128XtsCryptoDriver.GetDefaultKey(2), Aes128XtsCryptoDriver.GetDefaultKey(3)); this.m_header1Signer = (ISigner) new Rsa2048PssSha256SignCryptoDriver(Rsa2048PssSha256KeyIndex.NcaHeader1); this.m_header2Signer = this.m_fileSystemInfo.contentType != (byte)0 || this.m_fileSystemInfo.header2SignKeyModulus == null || (this.m_fileSystemInfo.header2SignKeyPublicExponent == null || this.m_fileSystemInfo.header2SignKeyPrivateExponent == null) ? (ISigner)null : (ISigner) new Rsa2048PssSha256SignCryptoDriver(this.m_fileSystemInfo.header2SignKeyModulus, this.m_fileSystemInfo.header2SignKeyPublicExponent, this.m_fileSystemInfo.header2SignKeyPrivateExponent); this.m_acidSigner = (ISigner)null; this.m_nrrSigner = (ISigner) new Rsa2048PssSha256SignCryptoDriver(Rsa2048PssSha256KeyIndex.NrrCertificate); this.m_nrrCertificateSigner = (ISigner) new Rsa2048PssSha256SignCryptoDriver(Rsa2048PssSha256KeyIndex.NrrCertificate); } }