Esempio n. 1
0
        private HierarchicalIntegrityVerificationStream InitIvfcStream(bool enableIntegrityChecks)
        {
            IvfcHeader ivfc = Header.Ivfc;

            const int ivfcLevels = 5;
            var       initInfo   = new IntegrityVerificationInfo[ivfcLevels];

            initInfo[0] = new IntegrityVerificationInfo
            {
                Data           = new MemoryStream(Header.MasterHashA),
                BlockSizePower = 0,
                Type           = IntegrityStreamType.Save
            };

            for (int i = 1; i < ivfcLevels; i++)
            {
                IvfcLevelHeader level = ivfc.LevelHeaders[i - 1];

                Stream data = i == ivfcLevels - 1
                    ? (Stream)JournalStream
                    : MetaRemapSource.CreateStream(level.LogicalOffset, level.HashDataSize);

                initInfo[i] = new IntegrityVerificationInfo
                {
                    Data           = data,
                    BlockSizePower = level.BlockSize,
                    Salt           = new HMACSHA256(Encoding.ASCII.GetBytes(SaltSources[i - 1])).ComputeHash(ivfc.SaltSource),
                    Type           = IntegrityStreamType.Save
                };
            }

            return(new HierarchicalIntegrityVerificationStream(initInfo, enableIntegrityChecks));
        }
Esempio n. 2
0
        public Header(IStorage storage, KeySet keySet)
        {
            MainStorage         = storage;
            MainHeader          = MainStorage.Slice(0x100, 0x200);
            DuplexHeader        = MainStorage.Slice(0x300, 0x44);
            DataIvfcHeader      = MainStorage.Slice(0x344, 0xC0);
            JournalHeader       = MainStorage.Slice(0x408, 0x200);
            SaveHeader          = MainStorage.Slice(0x608, 0x48);
            MainRemapHeader     = MainStorage.Slice(0x650, 0x40);
            MetaDataRemapHeader = MainStorage.Slice(0x690, 0x40);
            ExtraDataStorage    = MainStorage.Slice(0x6D8, 0x400);
            FatIvfcHeader       = MainStorage.Slice(0xAD8, 0xC0);

            Layout = new FsLayout(MainHeader);

            DuplexMasterBitmapA = MainStorage.Slice(Layout.DuplexMasterOffsetA, Layout.DuplexMasterSize);
            DuplexMasterBitmapB = MainStorage.Slice(Layout.DuplexMasterOffsetB, Layout.DuplexMasterSize);
            DataIvfcMaster      = MainStorage.Slice(Layout.IvfcMasterHashOffsetA, Layout.IvfcMasterHashSize);
            FatIvfcMaster       = MainStorage.Slice(Layout.FatIvfcMasterHashA, Layout.IvfcMasterHashSize);

            var reader = new BinaryReader(storage.AsStream());

            reader.BaseStream.Position = 0;
            Data = reader.ReadBytes(0x4000);
            reader.BaseStream.Position = 0;

            Cmac = reader.ReadBytes(0x10);

            reader.BaseStream.Position = 0x100;

            reader.BaseStream.Position = 0x300;
            Duplex = new DuplexHeader(reader);

            reader.BaseStream.Position = 0x6D8;
            ExtraData = new ExtraData(reader);

            Ivfc = new IvfcHeader(DataIvfcHeader)
            {
                NumLevels = 5
            };

            if (Layout.Version >= 0x50000)
            {
                FatIvfc = new IvfcHeader(FatIvfcHeader)
                {
                    NumLevels = 4
                };
            }

            MasterHash = storage.Slice(Layout.IvfcMasterHashOffsetA, Layout.IvfcMasterHashSize);

            Span <byte> actualHeaderHash = stackalloc byte[Sha256.DigestSize];

            Sha256.GenerateSha256Hash(Data.AsSpan(0x300, 0x3d00), actualHeaderHash);

            HeaderHashValidity = Utilities.SpansEqual(Layout.Hash, actualHeaderHash) ? Validity.Valid : Validity.Invalid;
            SignatureValidity  = ValidateSignature(keySet);
        }
Esempio n. 3
0
        public Header(Keyset keyset, BinaryReader reader)
        {
            reader.BaseStream.Position = 0;
            Data = reader.ReadBytes(0x4000);
            reader.BaseStream.Position = 0;

            Cmac = reader.ReadBytes(0x10);

            reader.BaseStream.Position = 0x100;
            Layout = new FsLayout(reader);

            reader.BaseStream.Position = 0x300;
            Duplex = new DuplexHeader(reader);

            reader.BaseStream.Position = 0x344;
            Ivfc = new IvfcHeader(reader);

            reader.BaseStream.Position = 0x408;
            Journal = new JournalHeader(reader);

            reader.BaseStream.Position = 0x608;
            Save = new SaveHeader(reader);

            reader.BaseStream.Position = 0x650;
            FileRemap = new RemapHeader(reader);
            reader.BaseStream.Position = 0x690;
            MetaRemap = new RemapHeader(reader);

            reader.BaseStream.Position = 0x6D8;
            ExtraData = new ExtraData(reader);

            reader.BaseStream.Position = Layout.IvfcMasterHashOffsetA;
            MasterHashA = reader.ReadBytes((int)Layout.IvfcMasterHashSize);
            reader.BaseStream.Position = Layout.IvfcMasterHashOffsetB;
            MasterHashB = reader.ReadBytes((int)Layout.IvfcMasterHashSize);

            reader.BaseStream.Position = Layout.DuplexMasterOffsetA;
            DuplexMasterA = reader.ReadBytes((int)Layout.DuplexMasterSize);
            reader.BaseStream.Position = Layout.DuplexMasterOffsetB;
            DuplexMasterB = reader.ReadBytes((int)Layout.DuplexMasterSize);

            reader.BaseStream.Position = Layout.FileMapEntryOffset;
            FileMapEntries             = new MapEntry[FileRemap.MapEntryCount];
            for (int i = 0; i < FileRemap.MapEntryCount; i++)
            {
                FileMapEntries[i] = new MapEntry(reader);
            }

            reader.BaseStream.Position = Layout.MetaMapEntryOffset;
            MetaMapEntries             = new MapEntry[MetaRemap.MapEntryCount];
            for (int i = 0; i < MetaRemap.MapEntryCount; i++)
            {
                MetaMapEntries[i] = new MapEntry(reader);
            }

            HeaderHashValidity = Crypto.CheckMemoryHashTable(Data, Layout.Hash, 0x300, 0x3d00);
            SignatureValidity  = ValidateSignature(keyset);
        }
Esempio n. 4
0
        public Header(IStorage storage, Keyset keyset)
        {
            MainStorage         = storage;
            MainHeader          = MainStorage.Slice(0x100, 0x200);
            DuplexHeader        = MainStorage.Slice(0x300, 0x44);
            DataIvfcHeader      = MainStorage.Slice(0x344, 0xC0);
            JournalHeader       = MainStorage.Slice(0x408, 0x200);
            SaveHeader          = MainStorage.Slice(0x608, 0x48);
            MainRemapHeader     = MainStorage.Slice(0x650, 0x40);
            MetaDataRemapHeader = MainStorage.Slice(0x690, 0x40);
            ExtraDataStorage    = MainStorage.Slice(0x6D8, 0x400);
            FatIvfcHeader       = MainStorage.Slice(0xAD8, 0xC0);

            Layout = new FsLayout(MainHeader);

            DuplexMasterBitmapA = MainStorage.Slice(Layout.DuplexMasterOffsetA, Layout.DuplexMasterSize);
            DuplexMasterBitmapB = MainStorage.Slice(Layout.DuplexMasterOffsetB, Layout.DuplexMasterSize);
            DataIvfcMaster      = MainStorage.Slice(Layout.IvfcMasterHashOffsetA, Layout.IvfcMasterHashSize);
            FatIvfcMaster       = MainStorage.Slice(Layout.FatIvfcMasterHashA, Layout.IvfcMasterHashSize);

            var reader = new BinaryReader(storage.AsStream());

            reader.BaseStream.Position = 0;
            Data = reader.ReadBytes(0x4000);
            reader.BaseStream.Position = 0;

            Cmac = reader.ReadBytes(0x10);

            reader.BaseStream.Position = 0x100;

            reader.BaseStream.Position = 0x300;
            Duplex = new DuplexHeader(reader);

            reader.BaseStream.Position = 0x6D8;
            ExtraData = new ExtraData(reader);

            Ivfc = new IvfcHeader(DataIvfcHeader)
            {
                NumLevels = 5
            };

            if (Layout.Version >= 0x50000)
            {
                FatIvfc = new IvfcHeader(FatIvfcHeader)
                {
                    NumLevels = 4
                };
            }

            MasterHash = storage.Slice(Layout.IvfcMasterHashOffsetA, Layout.IvfcMasterHashSize);

            HeaderHashValidity = Crypto.CheckMemoryHashTable(Data, Layout.Hash, 0x300, 0x3d00);
            SignatureValidity  = ValidateSignature(keyset);
        }
Esempio n. 5
0
        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;
        }
Esempio n. 6
0
        private HierarchicalIntegrityVerificationStorage InitJournalIvfcStorage(IntegrityCheckLevel integrityCheckLevel)
        {
            const int  ivfcLevels = 5;
            IvfcHeader ivfc       = Header.Ivfc;
            var        levels     = new List <IStorage> {
                Header.DataIvfcMaster
            };

            for (int i = 0; i < ivfcLevels - 2; i++)
            {
                IvfcLevelHeader level = ivfc.LevelHeaders[i];
                levels.Add(MetaRemapStorage.Slice(level.Offset, level.Size));
            }

            IvfcLevelHeader dataLevel = ivfc.LevelHeaders[ivfcLevels - 2];

            levels.Add(JournalStorage.Slice(dataLevel.Offset, dataLevel.Size));

            return(new HierarchicalIntegrityVerificationStorage(ivfc, levels, IntegrityStorageType.Save, integrityCheckLevel, LeaveOpen));
        }
Esempio n. 7
0
        internal static void SetLevelValidities(this HierarchicalIntegrityVerificationStream stream, IvfcHeader header)
        {
            for (int i = 0; i < stream.Levels.Length - 1; i++)
            {
                Validity[] level         = stream.LevelValidities[i];
                var        levelValidity = Validity.Valid;

                foreach (Validity block in level)
                {
                    if (block == Validity.Invalid)
                    {
                        levelValidity = Validity.Invalid;
                        break;
                    }

                    if (block == Validity.Unchecked && levelValidity != Validity.Invalid)
                    {
                        levelValidity = Validity.Unchecked;
                    }
                }

                header.LevelHeaders[i].HashValidity = levelValidity;
            }
        }
Esempio n. 8
0
        public static void PrintIvfcHash(StringBuilder sb, int colLen, int indentSize, IvfcHeader ivfcInfo,
                                         IntegrityStorageType type)
        {
            var prefix  = new string(' ', indentSize);
            var prefix2 = new string(' ', indentSize + 4);

            if (type == IntegrityStorageType.RomFs)
            {
                PrintItem(sb, colLen,
                          $"{prefix}Master Hash{ivfcInfo.LevelHeaders[0].HashValidity.GetValidityString()}:",
                          ivfcInfo.MasterHash);
            }

            PrintItem(sb, colLen, $"{prefix}Magic:", ivfcInfo.Magic);
            PrintItem(sb, colLen, $"{prefix}Version:", ivfcInfo.Version);

            if (type == IntegrityStorageType.Save)
            {
                PrintItem(sb, colLen, $"{prefix}Salt Seed:", ivfcInfo.SaltSource);
            }

            var levelCount = Math.Max(ivfcInfo.NumLevels - 1, 0);

            if (type == IntegrityStorageType.Save)
            {
                levelCount = 4;
            }

            var offsetLen = type == IntegrityStorageType.Save ? 16 : 12;

            for (var i = 0; i < levelCount; i++)
            {
                var  level      = ivfcInfo.LevelHeaders[i];
                long hashOffset = 0;

                if (i != 0)
                {
                    hashOffset = ivfcInfo.LevelHeaders[i - 1].Offset;
                }

                sb.AppendLine($"{prefix}Level {i}{level.HashValidity.GetValidityString()}:");
                PrintItem(sb, colLen, $"{prefix2}Data Offset:", $"0x{level.Offset.ToString($"x{offsetLen}")}");
                PrintItem(sb, colLen, $"{prefix2}Data Size:", $"0x{level.Size.ToString($"x{offsetLen}")}");
                PrintItem(sb, colLen, $"{prefix2}Hash Offset:", $"0x{hashOffset.ToString($"x{offsetLen}")}");
                PrintItem(sb, colLen, $"{prefix2}Hash BlockSize:", $"0x{1 << level.BlockSizePower:x8}");
            }
        }