diff --git a/LibHac/Bktr.cs b/LibHac/Bktr.cs index edc5aec1..f3a289f4 100644 --- a/LibHac/Bktr.cs +++ b/LibHac/Bktr.cs @@ -19,7 +19,7 @@ namespace LibHac public Bktr(Stream patchRomfs, Stream baseRomfs, NcaSection section) { - if (section.Type != SectionType.Bktr) throw new ArgumentException("Section is not of type BKTR"); + if (section.Header.EncryptionType != NcaEncryptionType.AesCtrEx) throw new ArgumentException("Section is not of type BKTR"); Patch = patchRomfs ?? throw new NullReferenceException($"{nameof(patchRomfs)} cannot be null"); Base = baseRomfs ?? throw new NullReferenceException($"{nameof(baseRomfs)} cannot be null"); diff --git a/LibHac/Nca.cs b/LibHac/Nca.cs index db5c8505..8ec75bad 100644 --- a/LibHac/Nca.cs +++ b/LibHac/Nca.cs @@ -371,21 +371,19 @@ namespace LibHac long offset = 0; long size = 0; - switch (sect.Type) + switch (sect.Header.HashType) { - case SectionType.Invalid: - break; - case SectionType.Pfs0: + case NcaHashType.Sha256: offset = sect.Header.Sha256Info.HashTableOffset; size = sect.Header.Sha256Info.HashTableSize; break; - case SectionType.Romfs: + case NcaHashType.Ivfc when sect.Header.EncryptionType == NcaEncryptionType.AesCtrEx: + CheckBktrKey(sect); + break; + case NcaHashType.Ivfc: offset = sect.Header.IvfcInfo.LevelHeaders[0].LogicalOffset; size = 1 << sect.Header.IvfcInfo.LevelHeaders[0].BlockSizePower; break; - case SectionType.Bktr: - CheckBktrKey(sect); - return; } Stream stream = OpenSection(index, true, IntegrityCheckLevel.None); @@ -395,7 +393,7 @@ namespace LibHac stream.Read(hashTable, 0, hashTable.Length); sect.MasterHashValidity = Crypto.CheckMemoryHashTable(hashTable, expected, 0, hashTable.Length); - if (sect.Type == SectionType.Romfs) sect.Header.IvfcInfo.LevelHeaders[0].HashValidity = sect.MasterHashValidity; + if (sect.Header.HashType == NcaHashType.Ivfc) sect.Header.IvfcInfo.LevelHeaders[0].HashValidity = sect.MasterHashValidity; } public void Dispose() diff --git a/LibHac/NcaStructs.cs b/LibHac/NcaStructs.cs index 369f43cc..c75f1c68 100644 --- a/LibHac/NcaStructs.cs +++ b/LibHac/NcaStructs.cs @@ -148,32 +148,6 @@ namespace LibHac } } - public class RomfsSuperblock - { - public IvfcHeader IvfcHeader; - - public RomfsSuperblock(BinaryReader reader) - { - IvfcHeader = new IvfcHeader(reader); - reader.BaseStream.Position += 0x58; - } - } - - public class BktrSuperblock - { - public IvfcHeader IvfcHeader; - public BktrHeader RelocationHeader; - public BktrHeader SubsectionHeader; - - public BktrSuperblock(BinaryReader reader) - { - IvfcHeader = new IvfcHeader(reader); - reader.BaseStream.Position += 0x18; - RelocationHeader = new BktrHeader(reader); - SubsectionHeader = new BktrHeader(reader); - } - } - public class BktrPatchInfo { public BktrHeader RelocationHeader; @@ -304,18 +278,6 @@ namespace LibHac } } - public class Pfs0Section - { - public PfsSuperblock Superblock { get; set; } - public Validity Validity { get; set; } - } - - public class RomfsSection - { - public RomfsSuperblock Superblock { get; set; } - public IvfcLevel[] IvfcLevels { get; set; } = new IvfcLevel[Romfs.IvfcMaxLevel]; - } - public enum ProgramPartitionType { Code, diff --git a/LibHac/Pfs.cs b/LibHac/Pfs.cs index a3d8ab1b..c809dca2 100644 --- a/LibHac/Pfs.cs +++ b/LibHac/Pfs.cs @@ -68,29 +68,6 @@ namespace LibHac Hfs0 } - public class PfsSuperblock - { - public byte[] MasterHash; /* SHA-256 hash of the hash table. */ - public int BlockSize; /* In bytes. */ - public uint Always2; - public long HashTableOffset; /* Normally zero. */ - public long HashTableSize; - public long Pfs0Offset; - public long Pfs0Size; - - public PfsSuperblock(BinaryReader reader) - { - MasterHash = reader.ReadBytes(0x20); - BlockSize = reader.ReadInt32(); - Always2 = reader.ReadUInt32(); - HashTableOffset = reader.ReadInt64(); - HashTableSize = reader.ReadInt64(); - Pfs0Offset = reader.ReadInt64(); - Pfs0Size = reader.ReadInt64(); - reader.BaseStream.Position += 0xF0; - } - } - public class PfsHeader { public string Magic; diff --git a/LibHac/Romfs.cs b/LibHac/Romfs.cs index be15a7a7..2b8bd7b2 100644 --- a/LibHac/Romfs.cs +++ b/LibHac/Romfs.cs @@ -143,19 +143,6 @@ namespace LibHac } } - - - public class IvfcLevel - { - public long DataOffset { get; set; } - public long DataSize { get; set; } - public long HashOffset { get; set; } - public long HashSize { get; set; } - public long HashBlockSize { get; set; } - public long HashBlockCount { get; set; } - public Validity HashValidity { get; set; } - } - public static class RomfsExtensions { public static void Extract(this Romfs romfs, string outDir, IProgressReport logger = null) diff --git a/README.md b/README.md index 8c54efae..ffcefd72 100644 --- a/README.md +++ b/README.md @@ -15,9 +15,10 @@ hactoolnet is an example program that uses LibHac. It is used in a similar manne Usage: hactoolnet.exe [options...] Options: -r, --raw Keep raw data, don't unpack. - -y, --verify Verify hashes. + -y, --verify Verify all hashes in the input file. + -h, --enablehash Enable hash checks when reading the input file. -k, --keyset Load keys from an external file. - -t, --intype=type Specify input file type [nca, xci, romfs, pk11, pk21, switchfs, save, keygen] + -t, --intype=type Specify input file type [nca, xci, romfs, pk11, pk21, ini1, kip1, switchfs, save, keygen] --titlekeys Load title keys from an external file. NCA options: --section0 Specify Section 0 file path. @@ -53,6 +54,8 @@ Package1 options: --outdir Specify Package1 directory path. Package2 options: --outdir Specify Package2 directory path. +INI1 options: + --outdir Specify INI1 directory path. Switch FS options: --sdseed Set console unique seed for SD card NAX0 encryption. --listapps List application info. @@ -64,10 +67,13 @@ Switch FS options: --romfs Specify RomFS directory path. (--title must be specified) --romfsdir Specify RomFS directory path. (--title must be specified) --savedir Specify save file directory path. + -y, --verify Verify all titles, or verify a single title if --title is set. Savefile options: --outdir Specify directory path to save contents to. --debugoutdir Specify directory path to save intermediate data to for debugging. --sign Sign the save file. (Requires device_key in key file) +Keygen options: + --outdir Specify directory path to save key files to. ``` ## Examples diff --git a/hactoolnet/CliParser.cs b/hactoolnet/CliParser.cs index 476912f3..d2a434d4 100644 --- a/hactoolnet/CliParser.cs +++ b/hactoolnet/CliParser.cs @@ -198,6 +198,7 @@ namespace hactoolnet sb.AppendLine(" --romfs Specify RomFS directory path. (--title must be specified)"); sb.AppendLine(" --romfsdir Specify RomFS directory path. (--title must be specified)"); sb.AppendLine(" --savedir Specify save file directory path."); + sb.AppendLine(" -y, --verify Verify all titles, or verify a single title if --title is set."); sb.AppendLine("Savefile options:"); sb.AppendLine(" --outdir Specify directory path to save contents to."); sb.AppendLine(" --debugoutdir Specify directory path to save intermediate data to for debugging."); diff --git a/hactoolnet/ProcessNca.cs b/hactoolnet/ProcessNca.cs index c000021b..53517d80 100644 --- a/hactoolnet/ProcessNca.cs +++ b/hactoolnet/ProcessNca.cs @@ -160,16 +160,13 @@ namespace hactoolnet PrintItem(sb, colLen, " Partition Type:", sect.IsExefs ? "ExeFS" : sect.Type.ToString()); PrintItem(sb, colLen, " Section CTR:", sect.Header.Ctr); - switch (sect.Type) + switch (sect.Header.HashType) { - case SectionType.Pfs0: - PrintPfs0(sect); + case NcaHashType.Sha256: + PrintSha256Hash(sect); break; - case SectionType.Romfs: - PrintRomfs(sect); - break; - case SectionType.Bktr: - PrintRomfs(sect); + case NcaHashType.Ivfc: + PrintIvfcHash(sect); break; default: sb.AppendLine(" Unknown/invalid superblock!"); @@ -178,7 +175,7 @@ namespace hactoolnet } } - void PrintPfs0(NcaSection sect) + void PrintSha256Hash(NcaSection sect) { Sha256Info hashInfo = sect.Header.Sha256Info; @@ -192,7 +189,7 @@ namespace hactoolnet PrintItem(sb, colLen, " PFS0 Size:", $"0x{hashInfo.DataSize:x12}"); } - void PrintRomfs(NcaSection sect) + void PrintIvfcHash(NcaSection sect) { IvfcHeader ivfcInfo = sect.Header.IvfcInfo;