Add AesXtsFileSystem resizing and renaming

This commit is contained in:
Alex Barney 2019-03-25 16:44:49 -05:00
parent 5c1d8e0786
commit 1ee3841125
7 changed files with 96 additions and 8 deletions

View file

@ -74,7 +74,9 @@ namespace LibHac.IO
{
Header.SetSize(size, VerificationKey);
throw new NotImplementedException();
BaseFile.Write(Header.ToBytes(false), 0);
BaseStorage.SetSize(size);
}
}
}

View file

@ -47,7 +47,7 @@ namespace LibHac.IO
EncryptHeader(path, kekSeed, verificationKey);
}
private void EncryptHeader(string path, byte[] kekSeed, byte[] verificationKey)
public void EncryptHeader(string path, byte[] kekSeed, byte[] verificationKey)
{
GenerateKek(kekSeed, path);
EncryptKeys();
@ -84,7 +84,7 @@ namespace LibHac.IO
private void GenerateKek(byte[] kekSeed, string path)
{
var hash = new HMACSHA256(kekSeed);
byte[] pathBytes = Encoding.ASCII.GetBytes(path);
byte[] pathBytes = Encoding.UTF8.GetBytes(path);
byte[] checksum = hash.ComputeHash(pathBytes, 0, pathBytes.Length);
Array.Copy(checksum, 0, Kek1, 0, 0x10);

View file

@ -1,4 +1,6 @@
using System;
using System.Diagnostics;
using System.IO;
namespace LibHac.IO
{
@ -95,7 +97,24 @@ namespace LibHac.IO
public void RenameFile(string srcPath, string dstPath)
{
throw new NotImplementedException();
srcPath = PathTools.Normalize(srcPath);
dstPath = PathTools.Normalize(dstPath);
AesXtsFileHeader header = ReadXtsHeader(srcPath);
BaseFileSystem.RenameFile(srcPath, dstPath);
try
{
WriteXtsHeader(header, dstPath);
}
catch (Exception)
{
BaseFileSystem.RenameFile(dstPath, srcPath);
WriteXtsHeader(header, srcPath);
throw;
}
}
public bool DirectoryExists(string path)
@ -117,5 +136,34 @@ namespace LibHac.IO
{
BaseFileSystem.Commit();
}
private AesXtsFileHeader ReadXtsHeader(string path)
{
Debug.Assert(PathTools.IsNormalized(path.AsSpan()));
using (IFile file = BaseFileSystem.OpenFile(path, OpenMode.Read))
{
var header = new AesXtsFileHeader(file);
if (!header.TryDecryptHeader(path, KekSource, ValidationKey))
{
throw new InvalidDataException("Could not decrypt AES-XTS keys");
}
return header;
}
}
private void WriteXtsHeader(AesXtsFileHeader header, string path)
{
Debug.Assert(PathTools.IsNormalized(path.AsSpan()));
header.EncryptHeader(path, KekSource, ValidationKey);
using (IFile file = BaseFileSystem.OpenFile(path, OpenMode.ReadWrite))
{
file.Write(header.ToBytes(false), 0);
}
}
}
}

View file

@ -8,7 +8,7 @@ namespace LibHac.IO
{
private IStorage BaseStorage { get; }
private int BlockSize { get; }
private readonly long _length;
private long _length;
private LinkedList<CacheBlock> Blocks { get; } = new LinkedList<CacheBlock>();
private Dictionary<long, LinkedListNode<CacheBlock>> BlockDict { get; } = new Dictionary<long, LinkedListNode<CacheBlock>>();
@ -99,6 +99,13 @@ namespace LibHac.IO
public override long GetSize() => _length;
public override void SetSize(long size)
{
BaseStorage.SetSize(size);
_length = BaseStorage.GetSize();
}
private CacheBlock GetBlock(long blockIndex)
{
if (BlockDict.TryGetValue(blockIndex, out LinkedListNode<CacheBlock> node))

View file

@ -27,5 +27,10 @@ namespace LibHac.IO
}
public override long GetSize() => BaseFile.GetSize();
public override void SetSize(long size)
{
BaseFile.SetSize(size);
}
}
}

View file

@ -7,7 +7,7 @@ namespace LibHac.IO
protected IStorage BaseStorage { get; }
public int SectorSize { get; }
public int SectorCount { get; }
public int SectorCount { get; private set; }
private long _length;
@ -15,8 +15,8 @@ namespace LibHac.IO
{
BaseStorage = baseStorage;
SectorSize = sectorSize;
SectorCount = (int)Util.DivideByRoundUp(BaseStorage.GetSize(), sectorSize);
_length = baseStorage.GetSize();
SectorCount = (int)Util.DivideByRoundUp(BaseStorage.GetSize(), SectorSize);
_length = BaseStorage.GetSize();
if (!leaveOpen) ToDispose.Add(BaseStorage);
}
@ -40,6 +40,14 @@ namespace LibHac.IO
public override long GetSize() => _length;
public override void SetSize(long size)
{
BaseStorage.SetSize(size);
SectorCount = (int)Util.DivideByRoundUp(BaseStorage.GetSize(), SectorSize);
_length = BaseStorage.GetSize();
}
/// <summary>
/// Validates that the size is a multiple of the sector size
/// </summary>

View file

@ -54,5 +54,23 @@ namespace LibHac.IO
}
public override long GetSize() => _length;
public override void SetSize(long size)
{
//if (!IsResizable)
// return 0x313802;
//if (Offset < 0 || size < 0)
// return 0x2F5C02;
if (BaseStorage.GetSize() != Offset + _length)
{
throw new NotSupportedException("SubStorage cannot be resized unless it is located at the end of the base storage.");
}
BaseStorage.SetSize(Offset + size);
_length = size;
}
}
}