Get rid of old code

This commit is contained in:
Alex Barney 2019-01-11 15:53:41 -06:00
parent 3e4dcd9466
commit 8861f25bc7
6 changed files with 41 additions and 358 deletions

View file

@ -1,53 +0,0 @@
using System.IO;
using System.Linq;
using DiscUtils.Fat;
namespace LibHac.Nand
{
public class NandPartition : IFileSystemOld
{
public FatFileSystem Fs { get; }
public NandPartition(FatFileSystem fileSystem)
{
Fs = fileSystem;
}
public bool FileExists(string path)
{
return Fs.FileExists(path);
}
public bool DirectoryExists(string path)
{
return Fs.DirectoryExists(path);
}
public Stream OpenFile(string path, FileMode mode)
{
return Fs.OpenFile(path, mode);
}
public Stream OpenFile(string path, FileMode mode, FileAccess access)
{
return Fs.OpenFile(path, mode, access);
}
public string[] GetFileSystemEntries(string path, string searchPattern)
{
return Fs.GetFileSystemEntries(path, searchPattern);
}
public string[] GetFileSystemEntries(string path, string searchPattern, SearchOption searchOption)
{
string[] files = Fs.GetFiles(path, searchPattern, searchOption);
string[] dirs = Fs.GetDirectories(path, searchPattern, searchOption);
return files.Concat(dirs).ToArray();
}
public string GetFullPath(string path)
{
return path;
}
}
}

View file

@ -1,73 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
namespace LibHac
{
public class FileSystem : IFileSystemOld
{
public string Root { get; }
public FileSystem(string rootDir)
{
Root = Path.GetFullPath(rootDir);
}
public bool FileExists(string path)
{
return File.Exists(Path.Combine(Root, path));
}
public bool DirectoryExists(string path)
{
return Directory.Exists(Path.Combine(Root, path));
}
public Stream OpenFile(string path, FileMode mode)
{
return new FileStream(Path.Combine(Root, path), mode);
}
public Stream OpenFile(string path, FileMode mode, FileAccess access)
{
return new FileStream(Path.Combine(Root, path), mode, access);
}
public string[] GetFileSystemEntries(string path, string searchPattern)
{
return Directory.GetFileSystemEntries(Path.Combine(Root, path), searchPattern);
}
public string[] GetFileSystemEntries(string path, string searchPattern, SearchOption searchOption)
{
//return Directory.GetFileSystemEntries(Path.Combine(Root, path), searchPattern, searchOption);
var result = new List<string>();
try
{
result.AddRange(GetFileSystemEntries(Path.Combine(Root, path), searchPattern));
}
catch (UnauthorizedAccessException) { /* Skip this directory */ }
if (searchOption == SearchOption.TopDirectoryOnly)
return result.ToArray();
string[] searchDirectories = Directory.GetDirectories(Path.Combine(Root, path));
foreach (string search in searchDirectories)
{
try
{
result.AddRange(GetFileSystemEntries(search, searchPattern, searchOption));
}
catch (UnauthorizedAccessException) { /* Skip this result */ }
}
return result.ToArray();
}
public string GetFullPath(string path)
{
return Path.Combine(Root, path);
}
}
}

View file

@ -1,15 +0,0 @@
using System.IO;
namespace LibHac
{
public interface IFileSystemOld
{
bool FileExists(string path);
bool DirectoryExists(string path);
Stream OpenFile(string path, FileMode mode);
Stream OpenFile(string path, FileMode mode, FileAccess access);
string[] GetFileSystemEntries(string path, string searchPattern);
string[] GetFileSystemEntries(string path, string searchPattern, SearchOption searchOption);
string GetFullPath(string path);
}
}

View file

@ -1,93 +0,0 @@
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using LibHac.IO;
namespace LibHac
{
public class Nax0 : IDisposable
{
private const int SectorSize = 0x4000;
public byte[] Hmac { get; private set; }
public byte[][] EncKeys { get; } = Util.CreateJaggedArray<byte[][]>(2, 0x10);
public byte[][] Keys { get; } = Util.CreateJaggedArray<byte[][]>(2, 0x10);
public byte[] Key { get; } = new byte[0x20];
public long Length { get; private set; }
public IStorage BaseStorage { get; }
private bool LeaveOpen { get; }
public Nax0(Keyset keyset, IStorage storage, string sdPath, bool leaveOpen)
{
LeaveOpen = leaveOpen;
ReadHeader(storage.AsStream());
DeriveKeys(keyset, sdPath, storage);
BaseStorage = new CachedStorage(new Aes128XtsStorage(storage.Slice(SectorSize), Key, SectorSize, leaveOpen), 4, leaveOpen);
}
private void ReadHeader(Stream stream)
{
var reader = new BinaryReader(stream);
Hmac = reader.ReadBytes(0x20);
string magic = reader.ReadAscii(4);
reader.BaseStream.Position += 4;
if (magic != "NAX0") throw new InvalidDataException("Not an NAX0 file");
EncKeys[0] = reader.ReadBytes(0x10);
EncKeys[1] = reader.ReadBytes(0x10);
Length = reader.ReadInt64();
}
private void DeriveKeys(Keyset keyset, string sdPath, IStorage storage)
{
var validationHashKey = new byte[0x60];
storage.Read(validationHashKey, 0x20);
// Try both the NCA and save key sources and pick the one that works
for (int k = 0; k < 2; k++)
{
var naxSpecificKeys = Util.CreateJaggedArray<byte[][]>(2, 0x10);
var hashKey = new byte[0x10];
Array.Copy(keyset.SdCardKeys[k], hashKey, 0x10);
// Use the sd path to generate the kek for this NAX0
var hash = new HMACSHA256(hashKey);
byte[] sdPathBytes = Encoding.ASCII.GetBytes(sdPath);
byte[] checksum = hash.ComputeHash(sdPathBytes, 0, sdPathBytes.Length);
Array.Copy(checksum, 0, naxSpecificKeys[0], 0, 0x10);
Array.Copy(checksum, 0x10, naxSpecificKeys[1], 0, 0x10);
// Decrypt this NAX0's keys
Crypto.DecryptEcb(naxSpecificKeys[0], EncKeys[0], Keys[0], 0x10);
Crypto.DecryptEcb(naxSpecificKeys[1], EncKeys[1], Keys[1], 0x10);
Array.Copy(Keys[0], 0, Key, 0, 0x10);
Array.Copy(Keys[1], 0, Key, 0x10, 0x10);
// Copy the decrypted keys into the NAX0 header and use that for the HMAC key
// for validating that the keys are correct
Array.Copy(Keys[0], 0, validationHashKey, 8, 0x10);
Array.Copy(Keys[1], 0, validationHashKey, 0x18, 0x10);
var validationHash = new HMACSHA256(validationHashKey);
byte[] validationMac = validationHash.ComputeHash(keyset.SdCardKeys[k], 0x10, 0x10);
if (Util.ArraysEqual(Hmac, validationMac))
{
return;
}
}
throw new ArgumentException("NAX0 key derivation failed.");
}
public void Dispose()
{
if (!LeaveOpen)
{
BaseStorage?.Dispose();
}
}
}
}

View file

@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using LibHac.IO;
using LibHac.IO.Save;
@ -12,44 +11,23 @@ namespace LibHac
public class SwitchFs : IDisposable
{
public Keyset Keyset { get; }
public IFileSystemOld Fs { get; }
public string ContentsDir { get; }
public string SaveDir { get; }
public IAttributeFileSystem BaseFs { get; }
public AesXtsFileSystem Fs { get; }
public Dictionary<string, Nca> Ncas { get; } = new Dictionary<string, Nca>(StringComparer.OrdinalIgnoreCase);
public Dictionary<string, SaveDataFileSystem> Saves { get; } = new Dictionary<string, SaveDataFileSystem>(StringComparer.OrdinalIgnoreCase);
public Dictionary<ulong, Title> Titles { get; } = new Dictionary<ulong, Title>();
public Dictionary<ulong, Application> Applications { get; } = new Dictionary<ulong, Application>();
public SwitchFs(Keyset keyset, IFileSystemOld fs)
public SwitchFs(Keyset keyset, IAttributeFileSystem fs)
{
Fs = fs;
BaseFs = fs;
Keyset = keyset;
if (fs.DirectoryExists("Nintendo"))
{
ContentsDir = fs.GetFullPath(Path.Combine("Nintendo", "Contents"));
SaveDir = fs.GetFullPath(Path.Combine("Nintendo", "save"));
}
else
{
if (fs.DirectoryExists("Contents"))
{
ContentsDir = fs.GetFullPath("Contents");
}
var concatFs = new ConcatenationFileSystem(BaseFs);
Fs = new AesXtsFileSystem(concatFs, keyset.SdCardKeys[1], 0x4000);
if (fs.DirectoryExists("save"))
{
SaveDir = fs.GetFullPath("save");
}
}
if (ContentsDir == null)
{
throw new DirectoryNotFoundException("Could not find \"Contents\" directory");
}
OpenAllSaves();
// OpenAllSaves();
OpenAllNcas();
ReadTitles();
ReadControls();
@ -58,88 +36,70 @@ namespace LibHac
private void OpenAllNcas()
{
string[] files = Fs.GetFileSystemEntries(ContentsDir, "*.nca", SearchOption.AllDirectories);
IEnumerable<DirectoryEntry> files = Fs.OpenDirectory("/", OpenDirectoryMode.All).EnumerateEntries("*.nca", SearchOptions.RecurseSubdirectories);
foreach (string file in files)
foreach (DirectoryEntry fileEntry in files)
{
Nca nca = null;
try
{
bool isNax0;
IStorage storage = OpenSplitNcaStorage(Fs, file);
if (storage == null) continue;
var storage = new FileStorage(Fs.OpenFile(fileEntry.FullPath, OpenMode.Read));
using (var reader = new BinaryReader(storage.AsStream(), Encoding.Default, true))
{
reader.BaseStream.Position = 0x20;
isNax0 = reader.ReadUInt32() == 0x3058414E; // NAX0
reader.BaseStream.Position = 0;
}
nca = new Nca(Keyset, storage, false);
if (isNax0)
{
string sdPath = "/" + Util.GetRelativePath(file, ContentsDir).Replace('\\', '/');
var nax0 = new Nax0(Keyset, storage, sdPath, false);
nca = new Nca(Keyset, nax0.BaseStorage, false);
}
else
{
nca = new Nca(Keyset, storage, false);
}
nca.NcaId = Path.GetFileNameWithoutExtension(file);
nca.NcaId = Path.GetFileNameWithoutExtension(fileEntry.Name);
string extension = nca.Header.ContentType == ContentType.Meta ? ".cnmt.nca" : ".nca";
nca.Filename = nca.NcaId + extension;
}
catch (MissingKeyException ex)
{
if (ex.Name == null)
{ Console.WriteLine($"{ex.Message} File:\n{file}"); }
{ Console.WriteLine($"{ex.Message} File:\n{fileEntry}"); }
else
{
string name = ex.Type == KeyType.Title ? $"Title key for rights ID {ex.Name}" : ex.Name;
Console.WriteLine($"{ex.Message}\nKey: {name}\nFile: {file}");
Console.WriteLine($"{ex.Message}\nKey: {name}\nFile: {fileEntry}");
}
}
catch (Exception ex)
{
Console.WriteLine($"{ex.Message} File: {file}");
Console.WriteLine($"{ex.Message} File: {fileEntry}");
}
if (nca?.NcaId != null) Ncas.Add(nca.NcaId, nca);
}
}
private void OpenAllSaves()
{
if (SaveDir == null) return;
//private void OpenAllSaves()
//{
// if (SaveDir == null) return;
string[] files = Fs.GetFileSystemEntries(SaveDir, "*");
// string[] files = Fs.GetFileSystemEntries(SaveDir, "*");
foreach (string file in files)
{
SaveDataFileSystem save = null;
string saveName = Path.GetFileNameWithoutExtension(file);
// foreach (string file in files)
// {
// SaveDataFileSystem save = null;
// string saveName = Path.GetFileNameWithoutExtension(file);
try
{
IStorage storage = Fs.OpenFile(file, FileMode.Open).AsStorage();
// try
// {
// IStorage storage = Fs.OpenFile(file, FileMode.Open).AsStorage();
string sdPath = "/" + Util.GetRelativePath(file, SaveDir).Replace('\\', '/');
var nax0 = new Nax0(Keyset, storage, sdPath, false);
save = new SaveDataFileSystem(Keyset, nax0.BaseStorage, IntegrityCheckLevel.None, true);
}
catch (Exception ex)
{
Console.WriteLine($"{ex.Message} File: {file}");
}
// string sdPath = "/" + Util.GetRelativePath(file, SaveDir).Replace('\\', '/');
// var nax0 = new Nax0(Keyset, storage, sdPath, false);
// save = new SaveDataFileSystem(Keyset, nax0.BaseStorage, IntegrityCheckLevel.None, true);
// }
// catch (Exception ex)
// {
// Console.WriteLine($"{ex.Message} File: {file}");
// }
if (save != null && saveName != null)
{
Saves[saveName] = save;
}
}
}
// if (save != null && saveName != null)
// {
// Saves[saveName] = save;
// }
// }
//}
private void ReadTitles()
{
@ -232,49 +192,6 @@ namespace LibHac
}
}
internal static IStorage OpenSplitNcaStorage(IFileSystemOld fs, string path)
{
var files = new List<string>();
var storages = new List<IStorage>();
if (fs.DirectoryExists(path))
{
while (true)
{
string partName = Path.Combine(path, $"{files.Count:D2}");
if (!fs.FileExists(partName)) break;
files.Add(partName);
}
}
else if (fs.FileExists(path))
{
if (Path.GetFileName(path) != "00")
{
return fs.OpenFile(path, FileMode.Open, FileAccess.Read).AsStorage();
}
files.Add(path);
}
else
{
throw new FileNotFoundException("Could not find the input file or directory");
}
if (files.Count == 1)
{
return fs.OpenFile(files[0], FileMode.Open, FileAccess.Read).AsStorage();
}
foreach (string file in files)
{
storages.Add(fs.OpenFile(file, FileMode.Open, FileAccess.Read).AsStorage());
}
if (storages.Count == 0) return null; //todo
return new ConcatenationStorage(storages, true);
}
private void DisposeNcas()
{
foreach (Nca nca in Ncas.Values)

View file

@ -13,7 +13,7 @@ namespace hactoolnet
{
public static void Process(Context ctx)
{
var switchFs = new SwitchFs(ctx.Keyset, new FileSystem(ctx.Options.InFile));
var switchFs = new SwitchFs(ctx.Keyset, new LocalFileSystem($"{ctx.Options.InFile}/Nintendo/Contents"));
if (ctx.Options.ListNcas)
{