Example #1
0
        public static byte VerifyHashType(NintendoContentFileSystemInfo fileSystemInfo, NintendoContentFileSystemInfo.EntryInfo entryInfo)
        {
            NintendoContentArchiveHashType contentArchiveHashType = (NintendoContentArchiveHashType)entryInfo.hashType;

            if (contentArchiveHashType == NintendoContentArchiveHashType.Auto)
            {
                string formatType = entryInfo.formatType;
                if (!(formatType == "PartitionFs"))
                {
                    if (!(formatType == "RomFs"))
                    {
                        throw new InvalidDataException("invalid format type.");
                    }
                    contentArchiveHashType = NintendoContentArchiveHashType.HierarchicalIntegrity;
                }
                else
                {
                    contentArchiveHashType = NintendoContentArchiveHashType.HierarchicalSha256;
                }
            }
            if (contentArchiveHashType != NintendoContentArchiveHashType.HierarchicalSha256 && contentArchiveHashType != NintendoContentArchiveHashType.HierarchicalIntegrity)
            {
                throw new InvalidDataException("invalid hash type.");
            }
            return((byte)contentArchiveHashType);
        }
        internal static NintendoContentFileSystemInfo GetReplacedNcaInfo(NintendoContentArchiveReader ncaReader, string descFilePath, EntryReplaceRule replaceRule)
        {
            NintendoContentFileSystemInfo commonNcaInfo = ArchiveReconstructionUtils.GetCommonNcaInfo(ncaReader);

            commonNcaInfo.keyAreaEncryptionKeyIndex = ncaReader.GetKeyIndex();
            commonNcaInfo.isProdEncryption          = false;
            if (descFilePath != null)
            {
                NintendoContentAdfReader.RetrieveInfoFromDesc(ref commonNcaInfo, descFilePath);
            }
            else if (replaceRule != null && commonNcaInfo.contentType == (byte)0)
            {
                throw new Exception("Replacing 'Program' content needs desc file.");
            }
            for (int fsIndex = 0; fsIndex < commonNcaInfo.numFsEntries; ++fsIndex)
            {
                string str = string.Format("fs{0}", (object)fsIndex);
                if (replaceRule != null && replaceRule.Path.StartsWith(str))
                {
                    EntryReplaceRule replaceRule1 = replaceRule;
                    replaceRule1.Path = replaceRule1.Path.Substring(str.Length + 1);
                    commonNcaInfo.fsEntries.Add(ArchiveReconstructionUtils.GetFsEntry(ncaReader, fsIndex, replaceRule1));
                }
                else
                {
                    commonNcaInfo.fsEntries.Add(ArchiveReconstructionUtils.GetFsEntry(ncaReader, fsIndex));
                }
            }
            return(commonNcaInfo);
        }
Example #3
0
        public NintendoContentArchiveSource(NintendoContentFileSystemInfo fileSystemInfo, KeyConfiguration config, bool needsLogoPartition = false)
        {
            this.m_fileSystemInfo = fileSystemInfo;
            this.m_keyConfig      = config;
            this.SetCryptor(this.m_keyConfig);
            this.AddDefaultLogoPartitionIfNeeded(needsLogoPartition);
            fileSystemInfo.fsEntries.Sort((Comparison <NintendoContentFileSystemInfo.EntryInfo>)((x, y) => x.partitionIndex.CompareTo(y.partitionIndex)));
            NintendoContentFileSystemMeta meta = new NintendoContentFileSystemMeta();
            NintendoContentFileSystemEntryInfoContainer fsEntries = new NintendoContentFileSystemEntryInfoContainer(fileSystemInfo.fsEntries);
            List <ConcatenatedSource.Element>           elements1 = new List <ConcatenatedSource.Element>();

            NintendoContentArchiveSource.BodySourceElement[] bodySources = new NintendoContentArchiveSource.BodySourceElement[fileSystemInfo.fsEntries.Count];
            long offset = (long)meta.GetFsHeaderSize() * 4L;

            foreach (NintendoContentFileSystemInfo.EntryInfo entryInfo in fsEntries)
            {
                if (entryInfo.type != null)
                {
                    ISource source = NintendoContentArchiveSource.GetDataSource(entryInfo);
                    if (fileSystemInfo.isProdEncryption && fileSystemInfo.contentType == (byte)0 && entryInfo.partitionIndex == 0)
                    {
                        source = this.AcidResignedSource(source);
                    }
                    if (fileSystemInfo.contentType == (byte)0 && entryInfo.partitionIndex == 1)
                    {
                        source = this.NrrSignedSource(source);
                    }
                    int currentIndex = fsEntries.CurrentIndex;
                    bodySources[currentIndex].DataOffset = offset;
                    NintendoContentArchiveSource.BuildDataInfo buildInfo = new NintendoContentArchiveSource.BuildDataInfo(meta, source, offset, currentIndex);
                    fileSystemInfo.fsEntries[currentIndex] = this.BuildData(entryInfo, buildInfo);
                    offset = buildInfo.CurrentOffset;
                    Sha256HierarchicalHashCalculatedSource calculatedSource = new Sha256HierarchicalHashCalculatedSource(buildInfo.HeaderSource, (int)buildInfo.HeaderSource.Size, 1);
                    ConcatenatedSource.Element             element1         = new ConcatenatedSource.Element(calculatedSource.GetMasterHashSource(), "fsHeaderHash" + (object)currentIndex, (long)(32 * currentIndex));
                    elements1.Add(element1);
                    ConcatenatedSource.Element element2 = new ConcatenatedSource.Element((ISource)calculatedSource, "fsHeader" + (object)currentIndex, (long)currentIndex * (long)meta.GetFsHeaderSize());
                    bodySources[currentIndex].HeaderElement      = element2;
                    bodySources[currentIndex].DataSourceElements = buildInfo.DataSourceElements;
                }
            }
            if (fsEntries.IsReverse)
            {
                elements1.Reverse();
            }
            NintendoContentArchiveSource.BodyEncryptionKey bodyEncryptionKey = new NintendoContentArchiveSource.BodyEncryptionKey(fileSystemInfo);
            this.MakeBody(meta, fsEntries, bodySources, bodyEncryptionKey);
            this.MakeNcaHeader(meta, (ISource) new ConcatenatedSource(elements1), bodyEncryptionKey);
            List <ConcatenatedSource.Element> elements2 = new List <ConcatenatedSource.Element>();

            ConcatenatedSource.Element element3 = new ConcatenatedSource.Element(this.m_headerSource, "header", 0L);
            ConcatenatedSource.Element element4 = new ConcatenatedSource.Element(this.m_bodySource, "body", element3.Source.Size);
            elements2.Add(element3);
            elements2.Add(element4);
            this.m_source = (ISource) new ConcatenatedSource(elements2);
            this.Size     = this.m_source.Size;
        }
Example #4
0
 public BodyEncryptionKey(NintendoContentFileSystemInfo fileSystemInfo)
 {
     this.m_internalKey    = new byte[4][];
     this.m_internalKey[2] = Encoding.ASCII.GetBytes("ContentKeyDEFGHI");
     if (fileSystemInfo.keyAreaEncryptionKeyIndex == (byte)0 && !fileSystemInfo.isProdEncryption)
     {
         return;
     }
     new RNGCryptoServiceProvider().GetBytes(this.m_internalKey[2]);
 }
        internal static NintendoContentFileSystemInfo GetProdNcaInfo(NintendoContentArchiveReader ncaReader)
        {
            NintendoContentFileSystemInfo commonNcaInfo = ArchiveReconstructionUtils.GetCommonNcaInfo(ncaReader);

            commonNcaInfo.keyAreaEncryptionKeyIndex = (byte)0;
            commonNcaInfo.isProdEncryption          = true;
            for (int fsIndex = 0; fsIndex < commonNcaInfo.numFsEntries; ++fsIndex)
            {
                commonNcaInfo.fsEntries.Add(ArchiveReconstructionUtils.GetFsEntry(ncaReader, fsIndex));
            }
            return(commonNcaInfo);
        }
Example #6
0
        public static byte VerifyEncryptionType(NintendoContentFileSystemInfo fileSystemInfo, NintendoContentFileSystemInfo.EntryInfo entryInfo)
        {
            NintendoContentArchiveEncryptionType archiveEncryptionType = (NintendoContentArchiveEncryptionType)entryInfo.encryptionType;

            if (archiveEncryptionType == NintendoContentArchiveEncryptionType.Auto)
            {
                if (fileSystemInfo.contentType == (byte)0)
                {
                    switch (entryInfo.partitionIndex)
                    {
                    case 0:
                    case 1:
                        archiveEncryptionType = NintendoContentArchiveEncryptionType.AesCtr;
                        break;

                    case 2:
                        archiveEncryptionType = NintendoContentArchiveEncryptionType.None;
                        break;

                    default:
                        throw new InvalidDataException("invalid partition index.");
                    }
                }
                else
                {
                    archiveEncryptionType = NintendoContentArchiveEncryptionType.AesCtr;
                }
            }
            if (fileSystemInfo.contentType == (byte)0 && entryInfo.partitionIndex == 2 && archiveEncryptionType != NintendoContentArchiveEncryptionType.None)
            {
                throw new InvalidDataException("logo must be no encryption type.");
            }
            if (archiveEncryptionType != NintendoContentArchiveEncryptionType.None && archiveEncryptionType != NintendoContentArchiveEncryptionType.AesCtr)
            {
                throw new InvalidDataException("invalid encryption type.");
            }
            return((byte)archiveEncryptionType);
        }
 public static byte[] RetrieveInfoFromDesc(ref NintendoContentFileSystemInfo fileSystemInfo, string descFilePath)
 {
     byte[] numArray = (byte[])null;
     if (descFilePath != null)
     {
         XmlDocument xmlDocument = new XmlDocument();
         xmlDocument.Load(descFilePath);
         numArray = Convert.FromBase64String(xmlDocument.DocumentElement.SelectSingleNode("/Desc/Acid").InnerText);
         try
         {
             fileSystemInfo.header2SignKeyModulus         = Convert.FromBase64String(xmlDocument.DocumentElement.SelectSingleNode("/Desc/RSAKeyValue/Modulus").InnerText);
             fileSystemInfo.header2SignKeyPrivateExponent = Convert.FromBase64String(xmlDocument.DocumentElement.SelectSingleNode("/Desc/RSAKeyValue/D").InnerText);
             fileSystemInfo.header2SignKeyPublicExponent  = Convert.FromBase64String(xmlDocument.DocumentElement.SelectSingleNode("/Desc/RSAKeyValue/Exponent").InnerText);
         }
         catch
         {
             fileSystemInfo.header2SignKeyModulus         = (byte[])null;
             fileSystemInfo.header2SignKeyPrivateExponent = (byte[])null;
             fileSystemInfo.header2SignKeyPublicExponent  = (byte[])null;
         }
     }
     return(numArray);
 }
Example #8
0
 private bool NeedsDefaultLogoPartition(NintendoContentFileSystemInfo fileSystemInfo, bool needsLogoPartition)
 {
     if (fileSystemInfo.contentType == (byte)0 & needsLogoPartition)
     {
         bool flag1 = false;
         bool flag2 = false;
         foreach (NintendoContentFileSystemInfo.EntryInfo fsEntry in fileSystemInfo.fsEntries)
         {
             if (fsEntry.partitionType == "logo")
             {
                 flag1 = true;
             }
             if (fsEntry.partitionType == "data")
             {
                 flag2 = true;
             }
         }
         if (!flag1 & flag2)
         {
             return(true);
         }
     }
     return(false);
 }
        public NintendoContentFileSystemInfo GetFileSystemInfo()
        {
            NintendoContentFileSystemInfo fileSystemInfo1 = new NintendoContentFileSystemInfo();

            using (StreamReader streamReader = new StreamReader(this.m_adfPath, Encoding.UTF8))
            {
                YamlStream yamlStream = new YamlStream();
                yamlStream.Load((TextReader)streamReader);
                YamlMappingNode  rootNode;
                YamlSequenceNode child1;
                try
                {
                    rootNode = (YamlMappingNode)yamlStream.Documents[0].RootNode;
                    if (((YamlScalarNode)rootNode.Children[(YamlNode) new YamlScalarNode("formatType")]).Value != "NintendoContent")
                    {
                        throw new ArgumentException();
                    }
                    YamlScalarNode child2 = (YamlScalarNode)rootNode.Children[(YamlNode) new YamlScalarNode("contentType")];
                    YamlScalarNode child3 = (YamlScalarNode)rootNode.Children[(YamlNode) new YamlScalarNode("keyGeneration")];
                    YamlScalarNode child4 = (YamlScalarNode)rootNode.Children[(YamlNode) new YamlScalarNode("programId")];
                    YamlScalarNode child5 = (YamlScalarNode)rootNode.Children[(YamlNode) new YamlScalarNode("contentIndex")];
                    child1 = (YamlSequenceNode)rootNode.Children[(YamlNode) new YamlScalarNode("entries")];
                    fileSystemInfo1.contentType   = this.ConvertToContentTypeByte(child2.Value);
                    fileSystemInfo1.keyGeneration = Convert.ToByte(child3.Value);
                    fileSystemInfo1.programId     = Convert.ToUInt64(child4.Value, 16);
                    fileSystemInfo1.contentIndex  = Convert.ToUInt32(child5.Value);
                }
                catch
                {
                    throw new ArgumentException("invalid format .adf file.");
                }
                try
                {
                    YamlScalarNode child2 = (YamlScalarNode)rootNode.Children[(YamlNode) new YamlScalarNode("keyAreaEncryptionKeyIndex")];
                    fileSystemInfo1.keyAreaEncryptionKeyIndex = Convert.ToByte(child2.Value);
                }
                catch
                {
                    fileSystemInfo1.keyAreaEncryptionKeyIndex = (byte)0;
                }
                string descFilePath;
                if (fileSystemInfo1.contentType == (byte)0)
                {
                    try
                    {
                        descFilePath = ((YamlScalarNode)rootNode.Children[(YamlNode) new YamlScalarNode("descFilePath")]).Value;
                    }
                    catch
                    {
                        throw new ArgumentException(".desc file is not specified for program content.");
                    }
                }
                else
                {
                    descFilePath = (string)null;
                }
                byte[] numArray = (byte[])null;
                if (descFilePath != null)
                {
                    numArray = NintendoContentAdfReader.RetrieveInfoFromDesc(ref fileSystemInfo1, descFilePath);
                }
                foreach (YamlMappingNode yamlMappingNode in child1)
                {
                    NintendoContentFileSystemInfo.EntryInfo entryInfo1 = new NintendoContentFileSystemInfo.EntryInfo();
                    string adfPath = (string)null;
                    foreach (KeyValuePair <YamlNode, YamlNode> keyValuePair in yamlMappingNode)
                    {
                        switch (((YamlScalarNode)keyValuePair.Key).Value)
                        {
                        case "encryptionType":
                            entryInfo1.encryptionType = Convert.ToByte(((YamlScalarNode)keyValuePair.Value).Value);
                            continue;

                        case "formatType":
                            entryInfo1.formatType = ((YamlScalarNode)keyValuePair.Value).Value;
                            continue;

                        case "hashType":
                            entryInfo1.hashType = Convert.ToByte(((YamlScalarNode)keyValuePair.Value).Value);
                            continue;

                        case "partitionType":
                            entryInfo1.partitionType  = ((YamlScalarNode)keyValuePair.Value).Value;
                            entryInfo1.partitionIndex = this.GetPartitionIndex(entryInfo1.partitionType);
                            continue;

                        case "path":
                            adfPath = ((YamlScalarNode)keyValuePair.Value).Value;
                            continue;

                        case "type":
                            entryInfo1.type = ((YamlScalarNode)keyValuePair.Value).Value;
                            continue;

                        case "version":
                            entryInfo1.version = Convert.ToUInt16(((YamlScalarNode)keyValuePair.Value).Value);
                            continue;

                        default:
                            throw new ArgumentException("invalid format .adf file. invalid key is specified\n" + yamlMappingNode.ToString());
                        }
                    }
                    if (entryInfo1.type == null || entryInfo1.formatType == null || adfPath == null)
                    {
                        throw new ArgumentException("invalid format .adf file. \"type\" or \"formatType\" is not specified\n" + yamlMappingNode.ToString());
                    }
                    entryInfo1.version        = (ushort)2;
                    entryInfo1.hashType       = NintendoContentArchiveSource.VerifyHashType(fileSystemInfo1, entryInfo1);
                    entryInfo1.encryptionType = NintendoContentArchiveSource.VerifyEncryptionType(fileSystemInfo1, entryInfo1);
                    string formatType = entryInfo1.formatType;
                    if (!(formatType == "PartitionFs"))
                    {
                        if (!(formatType == "RomFs"))
                        {
                            throw new NotImplementedException("invalid format .adf file. invalid formatType." + yamlMappingNode.ToString());
                        }
                        RomFsAdfReader romFsAdfReader = new RomFsAdfReader(adfPath);
                        entryInfo1.fileSystemInfo = (Nintendo.Authoring.FileSystemMetaLibrary.FileSystemInfo)romFsAdfReader.GetFileSystemInfo();
                    }
                    else
                    {
                        PartitionFileSystemInfo fileSystemInfo2 = new PartitionFsAdfReader(adfPath).GetFileSystemInfo();
                        if (numArray != null && entryInfo1.partitionType == "code")
                        {
                            IEnumerable <PartitionFileSystemInfo.EntryInfo> source = fileSystemInfo2.entries.Where <PartitionFileSystemInfo.EntryInfo>((Func <PartitionFileSystemInfo.EntryInfo, bool>)(p => p.name == "main.npdm"));
                            if (fileSystemInfo1.contentType == (byte)0 && source.Count <PartitionFileSystemInfo.EntryInfo>() != 1)
                            {
                                throw new ArgumentException("\"main.npdm\" must be included in the code region.");
                            }
                            foreach (PartitionFileSystemInfo.EntryInfo entryInfo2 in source)
                            {
                                if (!((IEnumerable <byte>) this.ReadAcid(entryInfo2.path)).SequenceEqual <byte>((IEnumerable <byte>)numArray))
                                {
                                    throw new ArgumentException(".desc file specified differ from the one used to build code.");
                                }
                            }
                        }
                        entryInfo1.fileSystemInfo = (Nintendo.Authoring.FileSystemMetaLibrary.FileSystemInfo)fileSystemInfo2;
                    }
                    fileSystemInfo1.fsEntries.Add(entryInfo1);
                }
            }
            fileSystemInfo1.numFsEntries     = fileSystemInfo1.fsEntries.Count;
            fileSystemInfo1.isProdEncryption = false;
            return(fileSystemInfo1);
        }