Пример #1
0
        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));
        }
Пример #2
0
        public IStorage OpenRawStorageWithPatch(Nca patchNca, int index)
        {
            IStorage patchStorage = patchNca.OpenRawStorage(index);
            IStorage baseStorage  = SectionExists(index) ? OpenRawStorage(index) : new NullStorage();

            patchStorage.GetSize(out long patchSize).ThrowIfFailure();
            baseStorage.GetSize(out long baseSize).ThrowIfFailure();

            NcaFsHeader    header    = patchNca.Header.GetFsHeader(index);
            NcaFsPatchInfo patchInfo = header.GetPatchInfo();

            if (patchInfo.RelocationTreeSize == 0)
            {
                return(patchStorage);
            }

            var treeHeader = new BucketTree.Header();

            patchInfo.RelocationTreeHeader.CopyTo(SpanHelpers.AsByteSpan(ref treeHeader));
            long nodeStorageSize  = IndirectStorage.QueryNodeStorageSize(treeHeader.EntryCount);
            long entryStorageSize = IndirectStorage.QueryEntryStorageSize(treeHeader.EntryCount);

            var relocationTableStorage = new SubStorage(patchStorage, patchInfo.RelocationTreeOffset, patchInfo.RelocationTreeSize);
            var cachedTableStorage     = new CachedStorage(relocationTableStorage, IndirectStorage.NodeSize, 4, true);

            var tableNodeStorage  = new SubStorage(cachedTableStorage, 0, nodeStorageSize);
            var tableEntryStorage = new SubStorage(cachedTableStorage, nodeStorageSize, entryStorageSize);

            var storage = new IndirectStorage();

            storage.Initialize(tableNodeStorage, tableEntryStorage, treeHeader.EntryCount).ThrowIfFailure();

            storage.SetStorage(0, baseStorage, 0, baseSize);
            storage.SetStorage(1, patchStorage, 0, patchSize);

            return(storage);
        }