Ejemplo n.º 1
0
        /// <summary>
        /// Read from a stream and get a CIA header, if possible
        /// </summary>
        /// <param name="reader">BinaryReader representing the input stream</param>
        /// <returns>CIA header object, null on error</returns>
        public static CIAHeader Read(BinaryReader reader)
        {
            CIAHeader header = new CIAHeader();

            try
            {
                header.HeaderSize           = reader.ReadInt32();
                header.Type                 = reader.ReadUInt16();
                header.Version              = reader.ReadUInt16();
                header.CertificateChainSize = reader.ReadInt32();
                header.TicketSize           = reader.ReadInt32();
                header.TMDFileSize          = reader.ReadInt32();
                header.MetaSize             = reader.ReadInt32();
                header.ContentSize          = reader.ReadInt64();
                header.ContentIndex         = reader.ReadBytes(0x2000);
                if (reader.BaseStream.Position % 64 != 0)
                {
                    reader.BaseStream.Seek(64 - (reader.BaseStream.Position % 64), SeekOrigin.Current);
                }

                header.CertificateChain    = new Certificate[3];
                header.CertificateChain[0] = Certificate.Read(reader); // CA
                header.CertificateChain[1] = Certificate.Read(reader); // Ticket
                header.CertificateChain[2] = Certificate.Read(reader); // TMD
                if (reader.BaseStream.Position % 64 != 0)
                {
                    reader.BaseStream.Seek(64 - (reader.BaseStream.Position % 64), SeekOrigin.Current);
                }

                header.Ticket = Ticket.Read(reader, header.TicketSize);
                if (reader.BaseStream.Position % 64 != 0)
                {
                    reader.BaseStream.Seek(64 - (reader.BaseStream.Position % 64), SeekOrigin.Current);
                }

                header.TMDFileData = TitleMetadata.Read(reader, header.TMDFileSize);
                if (reader.BaseStream.Position % 64 != 0)
                {
                    reader.BaseStream.Seek(64 - (reader.BaseStream.Position % 64), SeekOrigin.Current);
                }

                long startingPosition     = reader.BaseStream.Position;
                List <NCCHHeader> headers = new List <NCCHHeader>();
                while (reader.BaseStream.Position < startingPosition + header.ContentSize)
                {
                    long       initPosition = reader.BaseStream.Position;
                    NCCHHeader ncchHeader   = NCCHHeader.Read(reader, readSignature: true);
                    if (ncchHeader == null)
                    {
                        break;
                    }

                    headers.Add(ncchHeader);
                    reader.BaseStream.Seek(initPosition + ncchHeader.ContentSizeInMediaUnits * 0x200, SeekOrigin.Begin);
                }

                header.Partitions = headers.ToArray();
                if (header.MetaSize > 0)
                {
                    header.MetaFileData = MetaFile.Read(reader);
                }

                return(header);
            }
            catch
            {
                return(null);
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Read from a stream and get ticket metadata, if possible
        /// </summary>
        /// <param name="reader">BinaryReader representing the input stream</param>
        /// <param name="metadataSize">Metadata size from the header</param>
        /// <returns>Title metadata object, null on error</returns>
        public static TitleMetadata Read(BinaryReader reader, int metadataSize)
        {
            TitleMetadata tm = new TitleMetadata();

            try
            {
                long startingPosition = reader.BaseStream.Position;

                tm.SignatureType = (SignatureType)reader.ReadUInt32();
                switch (tm.SignatureType)
                {
                case SignatureType.RSA_4096_SHA1:
                case SignatureType.RSA_4096_SHA256:
                    tm.SignatureSize = 0x200;
                    tm.PaddingSize   = 0x3C;
                    break;

                case SignatureType.RSA_2048_SHA1:
                case SignatureType.RSA_2048_SHA256:
                    tm.SignatureSize = 0x100;
                    tm.PaddingSize   = 0x3C;
                    break;

                case SignatureType.ECDSA_SHA1:
                case SignatureType.ECDSA_SHA256:
                    tm.SignatureSize = 0x03C;
                    tm.PaddingSize   = 0x40;
                    break;
                }

                tm.Signature = reader.ReadBytes(tm.SignatureSize);
                reader.ReadBytes(tm.PaddingSize); // Padding
                tm.SignatureIssuer              = reader.ReadBytes(0x40);
                tm.Version                      = reader.ReadByte();
                tm.CaCrlVersion                 = reader.ReadByte();
                tm.SignerCrlVersion             = reader.ReadByte();
                tm.Reserved1                    = reader.ReadByte();
                tm.SystemVersion                = reader.ReadUInt64();
                tm.TitleID                      = reader.ReadUInt64();
                tm.TitleType                    = reader.ReadUInt32();
                tm.GroupID                      = reader.ReadUInt16();
                tm.SaveDataSize                 = reader.ReadUInt32();
                tm.SRLPrivateSaveDataSize       = reader.ReadUInt32();
                tm.Reserved2                    = reader.ReadUInt32();
                tm.SRLFlag                      = reader.ReadByte();
                tm.Reserved3                    = reader.ReadBytes(0x31);
                tm.AccessRights                 = reader.ReadUInt32();
                tm.TitleVersion                 = reader.ReadUInt16();
                tm.ContentCount                 = BitConverter.ToUInt16(reader.ReadBytes(2).Reverse().ToArray(), 0);
                tm.BootContent                  = reader.ReadUInt16();
                tm.Padding                      = reader.ReadUInt16();
                tm.SHA256HashContentInfoRecords = reader.ReadBytes(0x20);

                tm.ContentInfoRecords = new ContentInfoRecord[64];
                for (int i = 0; i < 64; i++)
                {
                    tm.ContentInfoRecords[i] = ContentInfoRecord.Read(reader);
                }

                tm.ContentChunkRecords = new ContentChunkRecord[tm.ContentCount];
                for (int i = 0; i < tm.ContentCount; i++)
                {
                    tm.ContentChunkRecords[i] = ContentChunkRecord.Read(reader);
                }

                if (metadataSize > (reader.BaseStream.Position - startingPosition) + (2 * 0x200))
                {
                    tm.CertificateChain    = new Certificate[2];
                    tm.CertificateChain[0] = Certificate.Read(reader); // TMD
                    tm.CertificateChain[1] = Certificate.Read(reader); // CA
                }

                return(tm);
            }
            catch
            {
                return(null);
            }
        }