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); }
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; }
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); }
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); }
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); }