mirror of
https://github.com/Thealexbarney/LibHac.git
synced 2024-11-14 10:49:41 +01:00
Add AesXtsFileSystem resizing and renaming
This commit is contained in:
parent
5c1d8e0786
commit
1ee3841125
7 changed files with 96 additions and 8 deletions
|
@ -74,7 +74,9 @@ namespace LibHac.IO
|
||||||
{
|
{
|
||||||
Header.SetSize(size, VerificationKey);
|
Header.SetSize(size, VerificationKey);
|
||||||
|
|
||||||
throw new NotImplementedException();
|
BaseFile.Write(Header.ToBytes(false), 0);
|
||||||
|
|
||||||
|
BaseStorage.SetSize(size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,7 @@ namespace LibHac.IO
|
||||||
EncryptHeader(path, kekSeed, verificationKey);
|
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);
|
GenerateKek(kekSeed, path);
|
||||||
EncryptKeys();
|
EncryptKeys();
|
||||||
|
@ -84,7 +84,7 @@ namespace LibHac.IO
|
||||||
private void GenerateKek(byte[] kekSeed, string path)
|
private void GenerateKek(byte[] kekSeed, string path)
|
||||||
{
|
{
|
||||||
var hash = new HMACSHA256(kekSeed);
|
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);
|
byte[] checksum = hash.ComputeHash(pathBytes, 0, pathBytes.Length);
|
||||||
Array.Copy(checksum, 0, Kek1, 0, 0x10);
|
Array.Copy(checksum, 0, Kek1, 0, 0x10);
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
namespace LibHac.IO
|
namespace LibHac.IO
|
||||||
{
|
{
|
||||||
|
@ -95,7 +97,24 @@ namespace LibHac.IO
|
||||||
|
|
||||||
public void RenameFile(string srcPath, string dstPath)
|
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)
|
public bool DirectoryExists(string path)
|
||||||
|
@ -117,5 +136,34 @@ namespace LibHac.IO
|
||||||
{
|
{
|
||||||
BaseFileSystem.Commit();
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ namespace LibHac.IO
|
||||||
{
|
{
|
||||||
private IStorage BaseStorage { get; }
|
private IStorage BaseStorage { get; }
|
||||||
private int BlockSize { get; }
|
private int BlockSize { get; }
|
||||||
private readonly long _length;
|
private long _length;
|
||||||
|
|
||||||
private LinkedList<CacheBlock> Blocks { get; } = new LinkedList<CacheBlock>();
|
private LinkedList<CacheBlock> Blocks { get; } = new LinkedList<CacheBlock>();
|
||||||
private Dictionary<long, LinkedListNode<CacheBlock>> BlockDict { get; } = new Dictionary<long, LinkedListNode<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 long GetSize() => _length;
|
||||||
|
|
||||||
|
public override void SetSize(long size)
|
||||||
|
{
|
||||||
|
BaseStorage.SetSize(size);
|
||||||
|
|
||||||
|
_length = BaseStorage.GetSize();
|
||||||
|
}
|
||||||
|
|
||||||
private CacheBlock GetBlock(long blockIndex)
|
private CacheBlock GetBlock(long blockIndex)
|
||||||
{
|
{
|
||||||
if (BlockDict.TryGetValue(blockIndex, out LinkedListNode<CacheBlock> node))
|
if (BlockDict.TryGetValue(blockIndex, out LinkedListNode<CacheBlock> node))
|
||||||
|
|
|
@ -27,5 +27,10 @@ namespace LibHac.IO
|
||||||
}
|
}
|
||||||
|
|
||||||
public override long GetSize() => BaseFile.GetSize();
|
public override long GetSize() => BaseFile.GetSize();
|
||||||
|
|
||||||
|
public override void SetSize(long size)
|
||||||
|
{
|
||||||
|
BaseFile.SetSize(size);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ namespace LibHac.IO
|
||||||
protected IStorage BaseStorage { get; }
|
protected IStorage BaseStorage { get; }
|
||||||
|
|
||||||
public int SectorSize { get; }
|
public int SectorSize { get; }
|
||||||
public int SectorCount { get; }
|
public int SectorCount { get; private set; }
|
||||||
|
|
||||||
private long _length;
|
private long _length;
|
||||||
|
|
||||||
|
@ -15,8 +15,8 @@ namespace LibHac.IO
|
||||||
{
|
{
|
||||||
BaseStorage = baseStorage;
|
BaseStorage = baseStorage;
|
||||||
SectorSize = sectorSize;
|
SectorSize = sectorSize;
|
||||||
SectorCount = (int)Util.DivideByRoundUp(BaseStorage.GetSize(), sectorSize);
|
SectorCount = (int)Util.DivideByRoundUp(BaseStorage.GetSize(), SectorSize);
|
||||||
_length = baseStorage.GetSize();
|
_length = BaseStorage.GetSize();
|
||||||
|
|
||||||
if (!leaveOpen) ToDispose.Add(BaseStorage);
|
if (!leaveOpen) ToDispose.Add(BaseStorage);
|
||||||
}
|
}
|
||||||
|
@ -40,6 +40,14 @@ namespace LibHac.IO
|
||||||
|
|
||||||
public override long GetSize() => _length;
|
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>
|
/// <summary>
|
||||||
/// Validates that the size is a multiple of the sector size
|
/// Validates that the size is a multiple of the sector size
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -54,5 +54,23 @@ namespace LibHac.IO
|
||||||
}
|
}
|
||||||
|
|
||||||
public override long GetSize() => _length;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue