Beispiel #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);
            }
        }
Beispiel #2
0
        /// <summary>
        /// Read from a stream and get ticket, if possible
        /// </summary>
        /// <param name="reader">BinaryReader representing the input stream</param>
        /// <param name="ticketSize">Ticket size from the header</param>
        /// <returns>Ticket object, null on error</returns>
        public static Ticket Read(BinaryReader reader, int ticketSize)
        {
            Ticket tk = new Ticket();

            try
            {
                long startingPosition = reader.BaseStream.Position;

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

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

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

                default:
                    return(null);
                }

                tk.Signature = reader.ReadBytes(tk.SignatureSize);
                reader.ReadBytes(tk.PaddingSize); // Padding
                tk.Issuer             = reader.ReadBytes(0x40);
                tk.ECCPublicKey       = reader.ReadBytes(0x3C);
                tk.Version            = reader.ReadByte();
                tk.CaCrlVersion       = reader.ReadByte();
                tk.SignerCrlVersion   = reader.ReadByte();
                tk.TitleKey           = reader.ReadBytes(0x10);
                tk.Reserved1          = reader.ReadByte();
                tk.TicketID           = reader.ReadUInt64();
                tk.ConsoleID          = reader.ReadUInt32();
                tk.TitleID            = reader.ReadUInt64();
                tk.Reserved2          = reader.ReadUInt16();
                tk.TicketTitleVersion = reader.ReadUInt16();
                tk.Reserved3          = reader.ReadUInt64();
                tk.LicenseType        = reader.ReadByte();
                tk.CommonKeyYIndex    = reader.ReadByte();
                tk.Reserved4          = reader.ReadBytes(0x2A);
                tk.eShopAccountID     = reader.ReadUInt32();
                tk.Reserved5          = reader.ReadByte();
                tk.Audit     = reader.ReadByte();
                tk.Reserved6 = reader.ReadBytes(0x42);

                tk.Limits = new int[0x10];
                for (int i = 0; i < 0x10; i++)
                {
                    tk.Limits[i] = reader.ReadInt32();
                }

                reader.ReadBytes(4); // Seek to size in Content Index
                tk.ContentIndexSize = BitConverter.ToInt32(reader.ReadBytes(4).Reverse().ToArray(), 0);
                reader.BaseStream.Seek(-8, SeekOrigin.Current);
                tk.ContentIndex = reader.ReadBytes(tk.ContentIndexSize);
                if (reader.BaseStream.Position % 64 != 0)
                {
                    reader.BaseStream.Seek(64 - (reader.BaseStream.Position % 64), SeekOrigin.Current);
                }

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

                return(tk);
            }
            catch
            {
                return(null);
            }
        }
Beispiel #3
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);
            }
        }