mirror of
https://github.com/Thealexbarney/LibHac.git
synced 2024-11-14 10:49:41 +01:00
Add romfs superblock validation
This commit is contained in:
parent
95ee755774
commit
3e6d2a7761
4 changed files with 88 additions and 9 deletions
|
@ -30,7 +30,7 @@ namespace hactoolnet
|
||||||
static void ReadNca()
|
static void ReadNca()
|
||||||
{
|
{
|
||||||
var keyset = ExternalKeys.ReadKeyFile("keys.txt", "titlekeys.txt");
|
var keyset = ExternalKeys.ReadKeyFile("keys.txt", "titlekeys.txt");
|
||||||
using (var file = new FileStream("bf8b106a2e68df3c3f1694636423585a.nca", FileMode.Open, FileAccess.Read))
|
using (var file = new FileStream("671d172e7993ee033d1be25ee76378e3.nca", FileMode.Open, FileAccess.Read))
|
||||||
{
|
{
|
||||||
var nca = new Nca(keyset, file, false);
|
var nca = new Nca(keyset, file, false);
|
||||||
var romfs = nca.OpenSection(0, false);
|
var romfs = nca.OpenSection(0, false);
|
||||||
|
@ -107,7 +107,7 @@ namespace hactoolnet
|
||||||
{
|
{
|
||||||
Console.WriteLine($" {nca.HasRightsId} {nca.NcaId} {nca.Header.ContentType}");
|
Console.WriteLine($" {nca.HasRightsId} {nca.NcaId} {nca.Header.ContentType}");
|
||||||
|
|
||||||
foreach (var sect in nca.Sections)
|
foreach (var sect in nca.Sections.Where(x => x != null))
|
||||||
{
|
{
|
||||||
Console.WriteLine($" {sect.SectionNum} {sect.Type} {sect.Header.CryptType} {sect.SuperblockHashValidity}");
|
Console.WriteLine($" {sect.SectionNum} {sect.Type} {sect.Header.CryptType} {sect.SuperblockHashValidity}");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using libhac.XTSSharp;
|
using libhac.XTSSharp;
|
||||||
|
@ -17,7 +16,7 @@ namespace libhac
|
||||||
public Stream Stream { get; private set; }
|
public Stream Stream { get; private set; }
|
||||||
private bool KeepOpen { get; }
|
private bool KeepOpen { get; }
|
||||||
|
|
||||||
public List<NcaSection> Sections = new List<NcaSection>();
|
public NcaSection[] Sections { get; } = new NcaSection[4];
|
||||||
|
|
||||||
public Nca(Keyset keyset, Stream stream, bool keepOpen)
|
public Nca(Keyset keyset, Stream stream, bool keepOpen)
|
||||||
{
|
{
|
||||||
|
@ -47,14 +46,14 @@ namespace libhac
|
||||||
{
|
{
|
||||||
var section = ParseSection(i);
|
var section = ParseSection(i);
|
||||||
if (section == null) continue;
|
if (section == null) continue;
|
||||||
Sections.Add(section);
|
Sections[i] = section;
|
||||||
ValidateSuperblockHash(i);
|
ValidateSuperblockHash(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Stream OpenSection(int index, bool raw)
|
public Stream OpenSection(int index, bool raw)
|
||||||
{
|
{
|
||||||
if (index >= Sections.Count) throw new ArgumentOutOfRangeException(nameof(index));
|
if (Sections[index] == null) throw new ArgumentOutOfRangeException(nameof(index));
|
||||||
var sect = Sections[index];
|
var sect = Sections[index];
|
||||||
|
|
||||||
long offset = sect.Offset;
|
long offset = sect.Offset;
|
||||||
|
@ -83,7 +82,7 @@ namespace libhac
|
||||||
switch (sect.Header.CryptType)
|
switch (sect.Header.CryptType)
|
||||||
{
|
{
|
||||||
case SectionCryptType.None:
|
case SectionCryptType.None:
|
||||||
break;
|
return new SubStream(Stream, offset, size);
|
||||||
case SectionCryptType.XTS:
|
case SectionCryptType.XTS:
|
||||||
break;
|
break;
|
||||||
case SectionCryptType.CTR:
|
case SectionCryptType.CTR:
|
||||||
|
@ -144,7 +143,7 @@ namespace libhac
|
||||||
|
|
||||||
private void ValidateSuperblockHash(int index)
|
private void ValidateSuperblockHash(int index)
|
||||||
{
|
{
|
||||||
if (index >= Sections.Count) throw new ArgumentOutOfRangeException(nameof(index));
|
if (Sections[index] == null) throw new ArgumentOutOfRangeException(nameof(index));
|
||||||
var sect = Sections[index];
|
var sect = Sections[index];
|
||||||
var stream = OpenSection(index, true);
|
var stream = OpenSection(index, true);
|
||||||
|
|
||||||
|
@ -164,6 +163,10 @@ namespace libhac
|
||||||
size = pfs0.HashTableSize;
|
size = pfs0.HashTableSize;
|
||||||
break;
|
break;
|
||||||
case SectionType.Romfs:
|
case SectionType.Romfs:
|
||||||
|
var ivfc = sect.Header.Romfs.IvfcHeader;
|
||||||
|
expected = ivfc.MasterHash;
|
||||||
|
offset = (long)ivfc.LevelHeaders[0].LogicalOffset;
|
||||||
|
size = 1 << (int)ivfc.LevelHeaders[0].BlockSize;
|
||||||
break;
|
break;
|
||||||
case SectionType.Bktr:
|
case SectionType.Bktr:
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -101,6 +101,7 @@ namespace libhac
|
||||||
|
|
||||||
public NcaFsHeader(BinaryReader reader)
|
public NcaFsHeader(BinaryReader reader)
|
||||||
{
|
{
|
||||||
|
var start = reader.BaseStream.Position;
|
||||||
Field0 = reader.ReadByte();
|
Field0 = reader.ReadByte();
|
||||||
Field1 = reader.ReadByte();
|
Field1 = reader.ReadByte();
|
||||||
PartitionType = (SectionPartitionType)reader.ReadByte();
|
PartitionType = (SectionPartitionType)reader.ReadByte();
|
||||||
|
@ -128,7 +129,7 @@ namespace libhac
|
||||||
}
|
}
|
||||||
|
|
||||||
Ctr = reader.ReadBytes(8).Reverse().ToArray();
|
Ctr = reader.ReadBytes(8).Reverse().ToArray();
|
||||||
reader.BaseStream.Position += 184;
|
reader.BaseStream.Position = start + 512;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
75
libhac/Substream.cs
Normal file
75
libhac/Substream.cs
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace libhac
|
||||||
|
{
|
||||||
|
public class SubStream : Stream
|
||||||
|
{
|
||||||
|
private Stream BaseStream { get; }
|
||||||
|
private long Offset { get; }
|
||||||
|
|
||||||
|
public SubStream(Stream baseStream, long offset, long length)
|
||||||
|
{
|
||||||
|
if (baseStream == null) throw new ArgumentNullException(nameof(baseStream));
|
||||||
|
if (offset < 0) throw new ArgumentOutOfRangeException(nameof(offset));
|
||||||
|
if (!baseStream.CanSeek || !baseStream.CanRead) throw new NotSupportedException();
|
||||||
|
|
||||||
|
BaseStream = baseStream;
|
||||||
|
Length = length;
|
||||||
|
Offset = offset;
|
||||||
|
|
||||||
|
baseStream.Seek(offset, SeekOrigin.Current);
|
||||||
|
}
|
||||||
|
public override int Read(byte[] buffer, int offset, int count)
|
||||||
|
{
|
||||||
|
long remaining = Length - Position;
|
||||||
|
if (remaining <= 0) return 0;
|
||||||
|
if (remaining < count) count = (int)remaining;
|
||||||
|
return BaseStream.Read(buffer, offset, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override long Length { get; }
|
||||||
|
public override bool CanRead => BaseStream.CanRead;
|
||||||
|
public override bool CanWrite => BaseStream.CanWrite;
|
||||||
|
public override bool CanSeek => BaseStream.CanSeek;
|
||||||
|
|
||||||
|
public override long Position
|
||||||
|
{
|
||||||
|
get => BaseStream.Position - Offset;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value < 0 || value >= Length)
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(value));
|
||||||
|
|
||||||
|
BaseStream.Position = Offset + value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override long Seek(long offset, SeekOrigin origin)
|
||||||
|
{
|
||||||
|
switch (origin)
|
||||||
|
{
|
||||||
|
case SeekOrigin.Begin:
|
||||||
|
Position = offset;
|
||||||
|
break;
|
||||||
|
case SeekOrigin.Current:
|
||||||
|
Position += offset;
|
||||||
|
break;
|
||||||
|
case SeekOrigin.End:
|
||||||
|
Position = Length - offset;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Position;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void SetLength(long value) => throw new NotSupportedException();
|
||||||
|
|
||||||
|
public override void Flush() => BaseStream.Flush();
|
||||||
|
|
||||||
|
public override void Write(byte[] buffer, int offset, int count)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue