Example #1
0
        public XciHeader(KeySet keySet, Stream stream)
        {
            using (var reader = new BinaryReader(stream, Encoding.Default, true))
            {
                Signature = reader.ReadBytes(SignatureSize);
                Magic     = reader.ReadAscii(4);
                if (Magic != HeaderMagic)
                {
                    throw new InvalidDataException("Invalid XCI file: Header magic invalid.");
                }

                reader.BaseStream.Position = SignatureSize;
                byte[] sigData = reader.ReadBytes(SignatureSize);
                reader.BaseStream.Position = SignatureSize + 4;

                SignatureValidity = CryptoOld.Rsa2048Pkcs1Verify(sigData, Signature, _xciHeaderPubk);

                RomAreaStartPage    = reader.ReadInt32();
                BackupAreaStartPage = reader.ReadInt32();
                byte keyIndex = reader.ReadByte();
                KekIndex          = (byte)(keyIndex >> 4);
                TitleKeyDecIndex  = (byte)(keyIndex & 7);
                GameCardSize      = (GameCardSizeInternal)reader.ReadByte();
                CardHeaderVersion = reader.ReadByte();
                Flags             = (GameCardAttribute)reader.ReadByte();
                PackageId         = reader.ReadUInt64();
                ValidDataEndPage  = reader.ReadInt64();
                AesCbcIv          = reader.ReadBytes(Aes.KeySize128);
                Array.Reverse(AesCbcIv);
                RootPartitionOffset     = reader.ReadInt64();
                RootPartitionHeaderSize = reader.ReadInt64();
                RootPartitionHeaderHash = reader.ReadBytes(Sha256.DigestSize);
                InitialDataHash         = reader.ReadBytes(Sha256.DigestSize);
                SelSec      = reader.ReadInt32();
                SelT1Key    = reader.ReadInt32();
                SelKey      = reader.ReadInt32();
                LimAreaPage = reader.ReadInt32();

                if (keySet != null && !keySet.XciHeaderKey.IsZeros())
                {
                    byte[] encHeader = reader.ReadBytes(EncryptedHeaderSize);
                    byte[] decHeader = new byte[EncryptedHeaderSize];
                    Aes.DecryptCbc128(encHeader, decHeader, keySet.XciHeaderKey, AesCbcIv);

                    using (var decReader = new BinaryReader(new MemoryStream(decHeader)))
                    {
                        FwVersion      = decReader.ReadUInt64();
                        AccCtrl1       = (CardClockRate)decReader.ReadInt32();
                        Wait1TimeRead  = decReader.ReadInt32();
                        Wait2TimeRead  = decReader.ReadInt32();
                        Wait1TimeWrite = decReader.ReadInt32();
                        Wait2TimeWrite = decReader.ReadInt32();
                        FwMode         = decReader.ReadInt32();
                        UppVersion     = decReader.ReadInt32();
                        decReader.BaseStream.Position += 4;
                        UppHash = decReader.ReadBytes(8);
                        UppId   = decReader.ReadUInt64();
                    }
                }

                ImageHash = new byte[Sha256.DigestSize];
                Sha256.GenerateSha256Hash(sigData, ImageHash);

                reader.BaseStream.Position = RootPartitionOffset;
                byte[] headerBytes = reader.ReadBytes((int)RootPartitionHeaderSize);

                Span <byte> actualHeaderHash = stackalloc byte[Sha256.DigestSize];
                Sha256.GenerateSha256Hash(headerBytes, actualHeaderHash);

                PartitionFsHeaderValidity = Utilities.SpansEqual(RootPartitionHeaderHash, actualHeaderHash) ? Validity.Valid : Validity.Invalid;
            }
        }