LibHac/LibHac.Nand/Nand.cs
Alex Barney 3d50085e22
Use Storage throughout the library instead of Stream (#18)
*Create an IStorage interface and Storage abstract class to use instead of Stream

* Improve AES-XTS performance by ~16x

* Double AES-CTR performance: 800 MB/s -> 1600 MB/s on a 6700K

* Add AES-XTS tests

* Add AES benchmark and AES-CTR writing

* Add support for a hashed FAT in save files

* Add option to export decrypted NCA

* Allow opening decrypted package1 and package2

* Make sure romfs disposal can cascade all the way down

* Validate NCA, NPDM and package2 signatures
2018-11-18 23:20:34 -05:00

76 lines
3.1 KiB
C#

using System.IO;
using System.Linq;
using DiscUtils;
using DiscUtils.Fat;
using DiscUtils.Partitions;
using DiscUtils.Streams;
using LibHac.IO;
namespace LibHac.Nand
{
public class Nand
{
private GuidPartitionInfo ProdInfo { get; }
private GuidPartitionInfo ProdInfoF { get; }
private GuidPartitionInfo Safe { get; }
private GuidPartitionInfo System { get; }
private GuidPartitionInfo User { get; }
public Keyset Keyset { get; }
public Nand(Stream stream, Keyset keyset)
{
var disc = new GuidPartitionTable(stream, Geometry.Null);
GuidPartitionInfo[] partitions = disc.Partitions.Select(x => (GuidPartitionInfo)x).ToArray();
ProdInfo = partitions.FirstOrDefault(x => x.Name == "PRODINFO");
ProdInfoF = partitions.FirstOrDefault(x => x.Name == "PRODINFOF");
Safe = partitions.FirstOrDefault(x => x.Name == "SAFE");
System = partitions.FirstOrDefault(x => x.Name == "SYSTEM");
User = partitions.FirstOrDefault(x => x.Name == "USER");
Keyset = keyset;
}
public Stream OpenProdInfo()
{
IStorage encStorage = ProdInfo.Open().AsStorage();
var decStorage = new CachedStorage(new Aes128XtsStorage(encStorage, Keyset.BisKeys[0], 0x4000, true), 0x4000, 4, true);
decStorage.SetReadOnly();
return decStorage.AsStream();
}
public NandPartition OpenProdInfoF()
{
IStorage encStorage = ProdInfoF.Open().AsStorage();
var decStorage = new CachedStorage(new Aes128XtsStorage(encStorage, Keyset.BisKeys[0], 0x4000, true), 0x4000, 4, true);
decStorage.SetReadOnly();
var fat = new FatFileSystem(decStorage.AsStream(), Ownership.None);
return new NandPartition(fat);
}
public NandPartition OpenSafePartition()
{
IStorage encStorage = Safe.Open().AsStorage();
var decStorage = new CachedStorage(new Aes128XtsStorage(encStorage, Keyset.BisKeys[1], 0x4000, true), 0x4000, 4, true);
decStorage.SetReadOnly();
var fat = new FatFileSystem(decStorage.AsStream(), Ownership.None);
return new NandPartition(fat);
}
public NandPartition OpenSystemPartition()
{
IStorage encStorage = System.Open().AsStorage();
var decStorage = new CachedStorage(new Aes128XtsStorage(encStorage, Keyset.BisKeys[2], 0x4000, true), 0x4000, 4, true);
decStorage.SetReadOnly();
var fat = new FatFileSystem(decStorage.AsStream(), Ownership.None);
return new NandPartition(fat);
}
public NandPartition OpenUserPartition()
{
IStorage encStorage = User.Open().AsStorage();
var decStorage = new CachedStorage(new Aes128XtsStorage(encStorage, Keyset.BisKeys[3], 0x4000, true), 0x4000, 4, true);
decStorage.SetReadOnly();
var fat = new FatFileSystem(decStorage.AsStream(), Ownership.None);
return new NandPartition(fat);
}
}
}