private IStorage OpenAesCtrExStorage(IStorage baseStorage, int index) { NcaFsHeader fsHeader = Header.GetFsHeader(index); NcaFsPatchInfo info = fsHeader.GetPatchInfo(); long sectionOffset = Header.GetSectionStartOffset(index); long sectionSize = Header.GetSectionSize(index); long bktrOffset = info.RelocationTreeOffset; long bktrSize = sectionSize - bktrOffset; long dataSize = info.RelocationTreeOffset; byte[] key = GetContentKey(NcaKeyType.AesCtr); byte[] counter = Aes128CtrStorage.CreateCounter(fsHeader.Counter, bktrOffset + sectionOffset); byte[] counterEx = Aes128CtrStorage.CreateCounter(fsHeader.Counter, sectionOffset); IStorage bucketTreeData = new CachedStorage(new Aes128CtrStorage(baseStorage.Slice(bktrOffset, bktrSize), key, counter, true), 4, true); IStorage encryptionBucketTreeData = bucketTreeData.Slice(info.EncryptionTreeOffset - bktrOffset); IStorage decStorage = new Aes128CtrExStorage(baseStorage.Slice(0, dataSize), encryptionBucketTreeData, key, counterEx, true); decStorage = new CachedStorage(decStorage, 0x4000, 4, true); return(new ConcatenationStorage(new[] { decStorage, bucketTreeData }, true)); }
private IStorage OpenAesCtrExStorage(IStorage baseStorage, int index, bool decrypting) { NcaFsHeader fsHeader = GetFsHeader(index); NcaFsPatchInfo info = fsHeader.GetPatchInfo(); long sectionOffset = Header.GetSectionStartOffset(index); long sectionSize = Header.GetSectionSize(index); long bktrOffset = info.RelocationTreeOffset; long bktrSize = sectionSize - bktrOffset; long dataSize = info.RelocationTreeOffset; byte[] key = GetContentKey(NcaKeyType.AesCtr); byte[] counter = Aes128CtrStorage.CreateCounter(fsHeader.Counter, bktrOffset + sectionOffset); byte[] counterEx = Aes128CtrStorage.CreateCounter(fsHeader.Counter, sectionOffset); IStorage bucketTreeData; IStorage outputBucketTreeData; if (decrypting) { bucketTreeData = new CachedStorage(new Aes128CtrStorage(baseStorage.Slice(bktrOffset, bktrSize), key, counter, true), 4, true); outputBucketTreeData = bucketTreeData; } else { bucketTreeData = baseStorage.Slice(bktrOffset, bktrSize); outputBucketTreeData = new CachedStorage(new Aes128CtrStorage(baseStorage.Slice(bktrOffset, bktrSize), key, counter, true), 4, true); } var encryptionBucketTreeData = new SubStorage(bucketTreeData, info.EncryptionTreeOffset - bktrOffset, sectionSize - info.EncryptionTreeOffset); var cachedBucketTreeData = new CachedStorage(encryptionBucketTreeData, IndirectStorage.NodeSize, 6, true); var treeHeader = new BucketTree.Header(); info.EncryptionTreeHeader.CopyTo(SpanHelpers.AsByteSpan(ref treeHeader)); long nodeStorageSize = IndirectStorage.QueryNodeStorageSize(treeHeader.EntryCount); long entryStorageSize = IndirectStorage.QueryEntryStorageSize(treeHeader.EntryCount); var tableNodeStorage = new SubStorage(cachedBucketTreeData, 0, nodeStorageSize); var tableEntryStorage = new SubStorage(cachedBucketTreeData, nodeStorageSize, entryStorageSize); IStorage decStorage = new Aes128CtrExStorage(baseStorage.Slice(0, dataSize), tableNodeStorage, tableEntryStorage, treeHeader.EntryCount, key, counterEx, true); return(new ConcatenationStorage(new[] { decStorage, outputBucketTreeData }, true)); }